Merge branch '86Box:master' into master

This commit is contained in:
starfrost
2025-01-22 14:46:01 +00:00
committed by GitHub
17 changed files with 830 additions and 642 deletions

View File

@@ -333,6 +333,20 @@
#define BUS_IDLE (1 << 31)
#define STATE_IDLE 0
#define STATE_COMMAND 1
#define STATE_DATAIN 2
#define STATE_DATAOUT 3
#define STATE_STATUS 4
#define STATE_MESSAGEIN 5
#define STATE_SELECT 6
#define STATE_MESSAGEOUT 7
#define STATE_MESSAGE_ID 8
#define PIO_TX_BUS 0
#define DMA_IN_TX_BUS 1
#define DMA_OUT_TX_BUS 2
#define PHASE_IDLE 0x00
#define PHASE_COMMAND 0x01
#define PHASE_DATA_IN 0x02
@@ -420,6 +434,36 @@ typedef struct scsi_device_t {
void (*command_stop)(scsi_common_t *sc);
} scsi_device_t;
typedef struct scsi_bus_t {
int tx_mode;
int clear_req;
int wait_data;
int wait_complete;
int bus_out;
int bus_in;
int command_pos;
int command_issued;
int data_pos;
int msgout_pos;
int is_msgout;
int state;
int dma_on_pio_enabled;
uint8_t data;
uint8_t msglun;
uint8_t data_wait;
uint8_t command[16];
uint8_t msgout[4];
uint8_t target_id;
uint8_t bus_device;
uint32_t bus_phase;
double period;
double speed;
double divider;
double multi;
void *priv;
void (*timer)(void *priv, double period);
} scsi_bus_t;
/* These are based on the INQUIRY values. */
#define SCSI_NONE 0x0060
#define SCSI_FIXED_DISK 0x0000
@@ -454,6 +498,8 @@ extern void scsi_device_init(void);
extern void scsi_reset(void);
extern uint8_t scsi_get_bus(void);
extern int scsi_bus_read(scsi_bus_t *scsi_bus);
extern void scsi_bus_update(scsi_bus_t *scsi_bus, int bus);
extern void scsi_bus_set_speed(uint8_t bus, double speed);
extern double scsi_bus_get_speed(uint8_t bus);

View File

@@ -44,6 +44,9 @@
#define ICR_ACK 0x10
#define ICR_ARB_LOST 0x20
#define ICR_ARB_IN_PROGRESS 0x40
#define ICR_RST 0x80
#define ICR_PHASE 0x9e
#define ICR_WRITE 0x9f
#define MODE_ARBITRATE 0x01
#define MODE_DMA 0x02
@@ -63,70 +66,33 @@
#define TCR_REQ 0x08
#define TCR_LAST_BYTE_SENT 0x80
#define STATE_IDLE 0
#define STATE_COMMAND 1
#define STATE_DATAIN 2
#define STATE_DATAOUT 3
#define STATE_STATUS 4
#define STATE_MESSAGEIN 5
#define STATE_SELECT 6
#define STATE_MESSAGEOUT 7
#define STATE_MESSAGE_ID 8
#define DMA_IDLE 0
#define DMA_SEND 1
#define DMA_INITIATOR_RECEIVE 2
typedef struct ncr_t {
uint8_t icr;
uint8_t mode;
uint8_t tcr;
uint8_t data_wait;
uint8_t isr;
uint8_t output_data;
uint8_t target_id;
uint8_t tx_data;
uint8_t msglun;
uint8_t irq_state;
uint8_t command[20];
uint8_t msgout[4];
uint8_t bus;
int msgout_pos;
int is_msgout;
int dma_mode;
int cur_bus;
int bus_in;
int new_phase;
int state;
int clear_req;
int wait_data;
int wait_data_back;
int wait_complete;
int command_pos;
int data_pos;
int irq;
double period;
void *priv;
void (*dma_mode_ext)(void *priv, void *ext_priv);
void (*dma_mode_ext)(void *priv, void *ext_priv, uint8_t val);
int (*dma_send_ext)(void *priv, void *ext_priv);
int (*dma_initiator_receive_ext)(void *priv, void *ext_priv);
void (*timer)(void *ext_priv, double period);
scsi_bus_t scsibus;
} ncr_t;
extern int ncr5380_cmd_len[8];
extern void ncr5380_irq(ncr_t *ncr, int set_irq);
extern void ncr5380_set_irq(ncr_t *ncr, int irq);
extern void ncr5380_set_irq(ncr_t *ncr, int irq);
extern uint32_t ncr5380_get_bus_host(ncr_t *ncr);
extern void ncr5380_bus_read(ncr_t *ncr);
extern void ncr5380_bus_update(ncr_t *ncr, int bus);
extern void ncr5380_write(uint16_t port, uint8_t val, ncr_t *ncr);
extern uint8_t ncr5380_read(uint16_t port, ncr_t *ncr);

View File

@@ -202,6 +202,14 @@ typedef struct svga_t {
void (*vblank_start)(struct svga_t *svga);
void (*write)(uint32_t addr, uint8_t val, void *priv);
void (*writew)(uint32_t addr, uint16_t val, void *priv);
void (*writel)(uint32_t addr, uint32_t val, void *priv);
uint8_t (*read)(uint32_t addr, void *priv);
uint16_t (*readw)(uint32_t addr, void *priv);
uint32_t (*readl)(uint32_t addr, void *priv);
void (*ven_write)(struct svga_t *svga, uint8_t val, uint32_t addr);
float (*getclock)(int clock, void *priv);
float (*getclock8514)(int clock, void *priv);

View File

@@ -919,18 +919,63 @@ machine_xt_pc500_init(const machine_t *model)
return ret;
}
static const device_config_t vendex_config[] = {
// clang-format off
{
.name = "bios",
.description = "BIOS Version",
.type = CONFIG_BIOS,
.default_string = "vendex",
.default_int = 0,
.file_filter = "",
.spinner = { 0 },
.bios = {
{ .name = "Bios 2.03C", .internal_name = "vendex", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 16384, .files = { "roms/machines/vendex/Vendex Turbo 888 XT - ROM BIOS - VER 2.03C.bin", "" } },
// GlaBIOS for Juko ST
{ .name = "GlaBIOS 0.2.5 (8088)", .internal_name = "glabios_025_8088", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 16384, .files = { "roms/machines/glabios/GLABIOS_0.2.5_8TV.ROM", "" } },
{ .name = "GlaBIOS 0.2.5 (V20)", .internal_name = "glabios_025_v20", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 16384, .files = { "roms/machines/glabios/GLABIOS_0.2.5_VTV.ROM", "" } },
{ .files_no = 0 }
},
},
{ .name = "", .description = "", .type = CONFIG_END }
// clang-format on
};
const device_t vendex_device = {
.name = "Vendex 888T Devices",
.internal_name = "vendex_device",
.flags = 0,
.local = 0,
.init = NULL,
.close = NULL,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = vendex_config
};
int
machine_xt_vendex_init(const machine_t *model)
{
int ret;
int ret = 0;
const char *fn;
ret = bios_load_linear("roms/machines/vendex/Vendex Turbo 888 XT - ROM BIOS - VER 2.03C.bin",
0x000fc000, 16384, 0);
/* No ROMs available. */
if (!device_available(model->device))
return ret;
device_context(model->device);
fn = device_get_bios_file(model->device, device_get_config_bios("bios"), 0);
ret = bios_load_linear(fn, 0x000fc000, 16384, 0);
device_context_restore();
if (bios_only || !ret)
return ret;
/* On-board FDC cannot be disabled */
machine_xt_clone_init(model, 1);
device_add(&vendex_xt_rtc_onboard_device);

View File

@@ -65,6 +65,7 @@ extern const device_t ibmat_device;
extern const device_t ibmxt286_device;
extern const device_t pb450_device;
extern const device_t jukopc_device;
extern const device_t vendex_device;
const machine_filter_t machine_types[] = {
{ "None", MACHINE_TYPE_NONE },
@@ -1696,7 +1697,7 @@ const machine_t machines[] = {
.kbc_p1 = 0xff,
.gpio = 0xffffffff,
.gpio_acpi = 0xffffffff,
.device = NULL,
.device = &vendex_device,
.fdc_device = NULL,
.sio_device = NULL,
.vid_device = NULL,

View File

@@ -16,10 +16,14 @@
* Copyright 2016-2018 Miran Grca.
* Copyright 2017-2018 Fred N. van Kempen.
*/
#include <inttypes.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/device.h>
#include <86box/hdd.h>
@@ -29,9 +33,29 @@
#include <86box/plat_unused.h>
scsi_device_t scsi_devices[SCSI_BUS_MAX][SCSI_ID_MAX];
int scsi_command_length[8] = { 6, 10, 10, 6, 16, 12, 10, 6 };
uint8_t scsi_null_device_sense[18] = { 0x70, 0, SENSE_ILLEGAL_REQUEST, 0, 0, 0, 0, 0, 0, 0, 0, 0, ASC_INV_LUN, 0, 0, 0, 0, 0 };
#define SET_BUS_STATE(scsi_bus, state) scsi_bus->bus_out = (scsi_bus->bus_out & ~(SCSI_PHASE_MESSAGE_IN)) | (state & (SCSI_PHASE_MESSAGE_IN))
#ifdef ENABLE_SCSI_DEVICE_LOG
int scsi_device_do_log = ENABLE_SCSI_DEVICE_LOG;
static void
scsi_device_log(const char *fmt, ...)
{
va_list ap;
if (scsi_device_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
# define scsi_device_log(fmt, ...)
#endif
static uint8_t
scsi_device_target_command(scsi_device_t *dev, uint8_t *cdb)
{
@@ -189,3 +213,311 @@ scsi_device_init(void)
}
}
}
int
scsi_device_get_id(uint8_t data)
{
for (uint8_t c = 0; c < SCSI_ID_MAX; c++) {
if (data & (1 << c))
return c;
}
return -1;
}
static int
scsi_device_get_msg(uint8_t *msgp, int len)
{
uint8_t msg = msgp[0];
if ((msg == 0) || ((msg >= 0x02) && (msg <= 0x1f)) || (msg >= 0x80))
return 1;
if ((msg >= 0x20) && (msg <= 0x2f))
return 2;
if (len < 2)
return 3;
return msgp[1];
}
int
scsi_bus_read(scsi_bus_t *scsi_bus)
{
scsi_device_t *dev;
int phase;
/*Wait processes to handle bus requests*/
if (scsi_bus->clear_req) {
scsi_bus->clear_req--;
if (!scsi_bus->clear_req) {
scsi_device_log("Prelude to command data\n");
SET_BUS_STATE(scsi_bus, scsi_bus->bus_phase);
scsi_bus->bus_out |= BUS_REQ;
}
}
if (scsi_bus->wait_data) {
scsi_bus->wait_data--;
if (!scsi_bus->wait_data) {
dev = &scsi_devices[scsi_bus->bus_device][scsi_bus->target_id];
SET_BUS_STATE(scsi_bus, scsi_bus->bus_phase);
phase = scsi_bus->bus_out & SCSI_PHASE_MESSAGE_IN;
switch (phase) {
case SCSI_PHASE_DATA_IN:
scsi_device_log("DataIn.\n");
scsi_bus->state = STATE_DATAIN;
if ((dev->sc != NULL) && (dev->sc->temp_buffer != NULL))
scsi_bus->data = dev->sc->temp_buffer[scsi_bus->data_pos++];
scsi_bus->bus_out = (scsi_bus->bus_out & ~BUS_DATAMASK) | BUS_SETDATA(scsi_bus->data) | BUS_DBP;
break;
case SCSI_PHASE_DATA_OUT:
if (scsi_bus->bus_phase & BUS_IDLE) {
scsi_device_log("Bus Idle.\n");
scsi_bus->state = STATE_IDLE;
scsi_bus->bus_out &= ~BUS_BSY;
scsi_bus->timer(scsi_bus->priv, 0.0);
} else {
scsi_device_log("DataOut.\n");
scsi_bus->state = STATE_DATAOUT;
}
break;
case SCSI_PHASE_STATUS:
scsi_device_log("Status.\n");
scsi_bus->bus_out |= BUS_REQ;
scsi_bus->state = STATE_STATUS;
scsi_bus->bus_out = (scsi_bus->bus_out & ~BUS_DATAMASK) | BUS_SETDATA(dev->status) | BUS_DBP;
break;
case SCSI_PHASE_MESSAGE_IN:
scsi_device_log("Message In.\n");
scsi_bus->state = STATE_MESSAGEIN;
scsi_bus->bus_out = (scsi_bus->bus_out & ~BUS_DATAMASK) | BUS_SETDATA(0) | BUS_DBP;
break;
case SCSI_PHASE_MESSAGE_OUT:
scsi_device_log("Message Out.\n");
scsi_bus->bus_out |= BUS_REQ;
scsi_bus->state = STATE_MESSAGEOUT;
scsi_bus->bus_out = (scsi_bus->bus_out & ~BUS_DATAMASK) | BUS_SETDATA(scsi_bus->target_id >> 5) | BUS_DBP;
break;
default:
break;
}
}
}
if (scsi_bus->wait_complete) {
scsi_bus->wait_complete--;
if (!scsi_bus->wait_complete)
scsi_bus->bus_out |= BUS_REQ;
}
return scsi_bus->bus_out;
}
void
scsi_bus_update(scsi_bus_t *scsi_bus, int bus)
{
scsi_device_t *dev = &scsi_devices[scsi_bus->bus_device][scsi_bus->target_id];
double p;
uint8_t sel_data;
int msglen;
/*Start the SCSI command layer, which will also make the timings*/
if (bus & BUS_ARB)
scsi_bus->state = STATE_IDLE;
scsi_device_log("State = %i\n", scsi_bus->state);
switch (scsi_bus->state) {
case STATE_IDLE:
scsi_bus->clear_req = scsi_bus->wait_data = scsi_bus->wait_complete = 0;
if ((bus & BUS_SEL) && !(bus & BUS_BSY)) {
sel_data = BUS_GETDATA(bus);
scsi_bus->target_id = scsi_device_get_id(sel_data);
/*Once the device has been found and selected, mark it as busy*/
if ((scsi_bus->target_id != (uint8_t) -1) && scsi_device_present(&scsi_devices[scsi_bus->bus_device][scsi_bus->target_id])) {
scsi_bus->bus_out |= BUS_BSY;
scsi_bus->state = STATE_SELECT;
scsi_device_log("Select - target ID = %i, moving to state = %d.\n", scsi_bus->target_id, scsi_bus->state);
} else {
scsi_device_log("Device not found at ID %i, Current Bus BSY=%02x\n", scsi_bus->target_id, scsi_bus->bus_out);
scsi_bus->bus_out = 0;
}
}
break;
case STATE_SELECT:
if (!(bus & BUS_SEL)) {
if (!(bus & BUS_ATN)) {
if ((scsi_bus->target_id != (uint8_t) -1) && scsi_device_present(&scsi_devices[scsi_bus->bus_device][scsi_bus->target_id])) {
scsi_device_log("Device found at ID %i, Current Bus BSY=%02x\n", scsi_bus->target_id, scsi_bus->bus_out);
scsi_bus->state = STATE_COMMAND;
scsi_bus->bus_out = BUS_BSY | BUS_REQ;
scsi_bus->command_pos = 0;
SET_BUS_STATE(scsi_bus, SCSI_PHASE_COMMAND);
} else {
scsi_device_log("Device not found at ID %i again.\n", scsi_bus->target_id);
scsi_bus->state = STATE_IDLE;
scsi_bus->bus_out = 0;
}
} else {
scsi_device_log("Set to SCSI Message Out\n");
scsi_bus->bus_phase = SCSI_PHASE_MESSAGE_OUT;
scsi_bus->wait_data = 4;
scsi_bus->msgout_pos = 0;
scsi_bus->is_msgout = 1;
}
}
break;
case STATE_COMMAND:
if ((bus & BUS_ACK) && !(scsi_bus->bus_in & BUS_ACK)) {
/*Write command byte to the output data register*/
scsi_bus->command[scsi_bus->command_pos++] = BUS_GETDATA(bus);
scsi_bus->clear_req = 3;
scsi_bus->bus_phase = scsi_bus->bus_out & SCSI_PHASE_MESSAGE_IN;
scsi_bus->bus_out &= ~BUS_REQ;
scsi_device_log("Command pos=%i, output data=%02x\n", scsi_bus->command_pos, BUS_GETDATA(bus));
if (scsi_bus->command_pos == scsi_command_length[(scsi_bus->command[0] >> 5) & 7]) {
if (scsi_bus->is_msgout) {
scsi_bus->is_msgout = 0;
#if 0
scsi_bus->command[1] = (scsi_bus->command[1] & 0x1f) | (scsi_bus->msglun << 5);
#endif
}
/*Reset data position to default*/
scsi_bus->data_pos = 0;
dev = &scsi_devices[scsi_bus->bus_device][scsi_bus->target_id];
scsi_device_log("SCSI Command 0x%02X for ID %d, status code=%02x\n", scsi_bus->command[0], scsi_bus->target_id, dev->status);
dev->buffer_length = -1;
scsi_device_command_phase0(dev, scsi_bus->command);
scsi_device_log("SCSI ID %i: Command %02X: Buffer Length %i, SCSI Phase %02X\n", scsi_bus->target_id, scsi_bus->command[0], dev->buffer_length, dev->phase);
scsi_bus->period = 1.0;
scsi_bus->wait_data = 4;
scsi_bus->data_wait = 0;
scsi_bus->command_issued = 1;
if (dev->status == SCSI_STATUS_OK) {
/*If the SCSI phase is Data In or Data Out, allocate the SCSI buffer based on the transfer length of the command*/
if (dev->buffer_length && ((dev->phase == SCSI_PHASE_DATA_IN) || (dev->phase == SCSI_PHASE_DATA_OUT))) {
p = scsi_device_get_callback(dev);
scsi_bus->period = (p > 0.0) ? ((p / scsi_bus->divider) * scsi_bus->multi) : (((double) dev->buffer_length) * scsi_bus->speed);
scsi_device_log("SCSI ID %i: command 0x%02x for p = %lf, update = %lf, len = %i, dmamode = %x\n", scsi_bus->target_id, scsi_bus->command[0], scsi_device_get_callback(dev), scsi_bus->period, dev->buffer_length, scsi_bus->tx_mode);
}
}
scsi_bus->bus_phase = dev->phase;
}
}
break;
case STATE_DATAIN:
dev = &scsi_devices[scsi_bus->bus_device][scsi_bus->target_id];
if ((bus & BUS_ACK) && !(scsi_bus->bus_in & BUS_ACK)) {
if (scsi_bus->data_pos >= dev->buffer_length) {
scsi_bus->bus_out &= ~BUS_REQ;
scsi_device_command_phase1(dev);
scsi_bus->bus_phase = SCSI_PHASE_STATUS;
scsi_bus->wait_data = 4;
scsi_bus->wait_complete = 8;
} else {
if ((dev->sc != NULL) && (dev->sc->temp_buffer != NULL))
scsi_bus->data = dev->sc->temp_buffer[scsi_bus->data_pos++];
scsi_device_log("TXMode DataIn=%x, cmd=%02x.\n", scsi_bus->tx_mode, scsi_bus->command[0]);
scsi_bus->bus_out = (scsi_bus->bus_out & ~BUS_DATAMASK) | BUS_SETDATA(scsi_bus->data) | BUS_DBP | BUS_REQ;
if (scsi_bus->tx_mode == PIO_TX_BUS) { /*If a data in command that is not read 6/10 has been issued*/
scsi_device_log("DMA mode idle IN=%d.\n", scsi_bus->data_pos);
scsi_bus->data_wait |= 1;
scsi_bus->timer(scsi_bus->priv, scsi_bus->period);
} else {
scsi_device_log("DMA mode IN=%d.\n", scsi_bus->data_pos);
scsi_bus->clear_req = 3;
}
scsi_bus->bus_out &= ~BUS_REQ;
scsi_bus->bus_phase = SCSI_PHASE_DATA_IN;
}
}
break;
case STATE_DATAOUT:
dev = &scsi_devices[scsi_bus->bus_device][scsi_bus->target_id];
if ((bus & BUS_ACK) && !(scsi_bus->bus_in & BUS_ACK)) {
if ((dev->sc != NULL) && (dev->sc->temp_buffer != NULL))
dev->sc->temp_buffer[scsi_bus->data_pos++] = BUS_GETDATA(bus);
if (scsi_bus->data_pos >= dev->buffer_length) {
scsi_bus->bus_out &= ~BUS_REQ;
scsi_device_command_phase1(dev);
scsi_bus->bus_phase = SCSI_PHASE_STATUS;
scsi_bus->wait_data = 4;
scsi_bus->wait_complete = 8;
} else {
/*More data is to be transferred, place a request*/
if (scsi_bus->tx_mode == PIO_TX_BUS) { /*If a data in command that is not write 6/10 has been issued*/
scsi_device_log("DMA mode idle OUT=%d.\n", scsi_bus->data_pos);
scsi_bus->data_wait |= 1;
scsi_bus->timer(scsi_bus->priv, scsi_bus->period);
scsi_bus->bus_out &= ~BUS_REQ;
} else {
scsi_device_log("DMA mode OUT=%d.\n", scsi_bus->data_pos);
scsi_bus->bus_out |= BUS_REQ;
}
}
}
break;
case STATE_STATUS:
if ((bus & BUS_ACK) && !(scsi_bus->bus_in & BUS_ACK)) {
/*All transfers done, wait until next transfer*/
scsi_device_identify(&scsi_devices[scsi_bus->bus_device][scsi_bus->target_id], SCSI_LUN_USE_CDB);
scsi_bus->bus_out &= ~BUS_REQ;
scsi_bus->bus_phase = SCSI_PHASE_MESSAGE_IN;
scsi_bus->wait_data = 4;
scsi_bus->wait_complete = 8;
scsi_bus->command_issued = 0;
}
break;
case STATE_MESSAGEIN:
if ((bus & BUS_ACK) && !(scsi_bus->bus_in & BUS_ACK)) {
scsi_bus->bus_out &= ~BUS_REQ;
scsi_bus->bus_phase = BUS_IDLE;
scsi_bus->wait_data = 4;
}
break;
case STATE_MESSAGEOUT:
if ((bus & BUS_ACK) && !(scsi_bus->bus_in & BUS_ACK)) {
scsi_bus->msgout[scsi_bus->msgout_pos++] = BUS_GETDATA(bus);
msglen = scsi_device_get_msg(scsi_bus->msgout, scsi_bus->msgout_pos);
if (scsi_bus->msgout_pos >= msglen) {
if ((scsi_bus->msgout[0] & (0x80 | 0x20)) == 0x80)
scsi_bus->msglun = scsi_bus->msgout[0] & 7;
scsi_bus->bus_out &= ~BUS_REQ;
scsi_bus->state = STATE_MESSAGE_ID;
}
}
break;
case STATE_MESSAGE_ID:
if ((scsi_bus->target_id != (uint8_t) -1) && scsi_device_present(&scsi_devices[scsi_bus->bus_device][scsi_bus->target_id])) {
scsi_device_log("Device found at ID %i on MSGOUT, Current Bus BSY=%02x\n", scsi_bus->target_id, scsi_bus->bus_out);
scsi_device_identify(&scsi_devices[scsi_bus->bus_device][scsi_bus->target_id], scsi_bus->msglun);
scsi_bus->state = STATE_COMMAND;
scsi_bus->bus_out = BUS_BSY | BUS_REQ;
scsi_bus->command_pos = 0;
SET_BUS_STATE(scsi_bus, SCSI_PHASE_COMMAND);
}
break;
default:
break;
}
scsi_bus->bus_in = bus;
}

View File

@@ -42,8 +42,6 @@
#include <86box/scsi_device.h>
#include <86box/scsi_ncr5380.h>
int ncr5380_cmd_len[8] = { 6, 10, 10, 6, 16, 12, 10, 6 };
#ifdef ENABLE_NCR5380_LOG
int ncr5380_do_log = ENABLE_NCR5380_LOG;
@@ -62,8 +60,6 @@ ncr5380_log(const char *fmt, ...)
# define ncr5380_log(fmt, ...)
#endif
#define SET_BUS_STATE(ncr, state) ncr->cur_bus = (ncr->cur_bus & ~(SCSI_PHASE_MESSAGE_IN)) | (state & (SCSI_PHASE_MESSAGE_IN))
void
ncr5380_irq(ncr_t *ncr, int set_irq)
{
@@ -86,45 +82,15 @@ ncr5380_set_irq(ncr_t *ncr, int irq)
ncr->irq = irq;
}
static int
ncr5380_get_dev_id(uint8_t data)
{
for (uint8_t c = 0; c < SCSI_ID_MAX; c++) {
if (data & (1 << c))
return c;
}
return -1;
}
static int
ncr5380_getmsglen(uint8_t *msgp, int len)
{
uint8_t msg = msgp[0];
if (msg == 0 || (msg >= 0x02 && msg <= 0x1f) || msg >= 0x80)
return 1;
if (msg >= 0x20 && msg <= 0x2f)
return 2;
if (len < 2)
return 3;
return msgp[1];
}
static void
ncr5380_reset(ncr_t *ncr)
{
ncr->command_pos = 0;
ncr->data_pos = 0;
ncr->state = STATE_IDLE;
ncr->clear_req = 0;
ncr->cur_bus = 0;
ncr->tx_data = 0;
scsi_bus_t *scsi_bus = &ncr->scsibus;
ncr->output_data = 0;
ncr->data_wait = 0;
ncr->mode = 0;
ncr->tcr = 0;
ncr->icr = 0;
ncr->dma_mode = DMA_IDLE;
ncr5380_log("NCR Reset\n");
ncr->timer(ncr->priv, 0.0);
@@ -132,6 +98,17 @@ ncr5380_reset(ncr_t *ncr)
for (int i = 0; i < 8; i++)
scsi_device_reset(&scsi_devices[ncr->bus][i]);
scsi_bus->state = STATE_IDLE;
scsi_bus->clear_req = 0;
scsi_bus->wait_complete = 0;
scsi_bus->wait_data = 0;
scsi_bus->bus_in = 0;
scsi_bus->bus_out = 0;
scsi_bus->command_pos = 0;
scsi_bus->data_wait = 0;
scsi_bus->data = 0;
scsi_bus->command_issued = 0;
ncr5380_irq(ncr, 0);
}
@@ -173,280 +150,10 @@ ncr5380_get_bus_host(ncr_t *ncr)
return (bus_host | BUS_SETDATA(ncr->output_data));
}
void
ncr5380_bus_read(ncr_t *ncr)
{
const scsi_device_t *dev;
int phase;
/*Wait processes to handle bus requests*/
if (ncr->clear_req) {
ncr->clear_req--;
if (!ncr->clear_req) {
ncr5380_log("Prelude to command data\n");
SET_BUS_STATE(ncr, ncr->new_phase);
ncr->cur_bus |= BUS_REQ;
}
}
if (ncr->wait_data) {
ncr->wait_data--;
if (!ncr->wait_data) {
dev = &scsi_devices[ncr->bus][ncr->target_id];
SET_BUS_STATE(ncr, ncr->new_phase);
phase = (ncr->cur_bus & SCSI_PHASE_MESSAGE_IN);
if (phase == SCSI_PHASE_DATA_IN) {
if ((ncr->dma_mode == DMA_IDLE) || ncr->dma_initiator_receive_ext || (ncr->wait_data_back == 1)) {
ncr5380_log("Phase Data In.\n");
if ((dev->sc != NULL) && (dev->sc->temp_buffer != NULL))
ncr->tx_data = dev->sc->temp_buffer[ncr->data_pos++];
ncr->state = STATE_DATAIN;
ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP;
}
} else if (phase == SCSI_PHASE_DATA_OUT) {
if (ncr->new_phase & BUS_IDLE) {
ncr->state = STATE_IDLE;
ncr->cur_bus &= ~BUS_BSY;
} else {
if ((ncr->dma_mode == DMA_IDLE) || ncr->dma_send_ext || (ncr->wait_data_back == 1))
ncr->state = STATE_DATAOUT;
}
} else if (phase == SCSI_PHASE_STATUS) {
ncr5380_log("Phase Status.\n");
ncr->wait_data_back = 0;
ncr->cur_bus |= BUS_REQ;
ncr->state = STATE_STATUS;
ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(dev->status) | BUS_DBP;
} else if (phase == SCSI_PHASE_MESSAGE_IN) {
ncr5380_log("Phase Message In.\n");
ncr->state = STATE_MESSAGEIN;
ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(0) | BUS_DBP;
} else if (phase == SCSI_PHASE_MESSAGE_OUT) {
ncr->cur_bus |= BUS_REQ;
ncr->state = STATE_MESSAGEOUT;
ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->target_id >> 5) | BUS_DBP;
}
}
}
if (ncr->wait_complete) {
ncr->wait_complete--;
if (!ncr->wait_complete)
ncr->cur_bus |= BUS_REQ;
}
}
void
ncr5380_bus_update(ncr_t *ncr, int bus)
{
scsi_device_t *dev = &scsi_devices[ncr->bus][ncr->target_id];
double p;
uint8_t sel_data;
int msglen;
/*Start the SCSI command layer, which will also make the timings*/
if (bus & BUS_ARB)
ncr->state = STATE_IDLE;
ncr5380_log("State = %i\n", ncr->state);
switch (ncr->state) {
case STATE_IDLE:
ncr->clear_req = ncr->wait_data = ncr->wait_complete = 0;
if ((bus & BUS_SEL) && !(bus & BUS_BSY)) {
ncr5380_log("Selection phase\n");
sel_data = BUS_GETDATA(bus);
ncr->target_id = ncr5380_get_dev_id(sel_data);
ncr5380_log("Select - target ID = %i\n", ncr->target_id);
/*Once the device has been found and selected, mark it as busy*/
if ((ncr->target_id != (uint8_t) -1) && scsi_device_present(&scsi_devices[ncr->bus][ncr->target_id])) {
ncr->cur_bus |= BUS_BSY;
ncr->state = STATE_SELECT;
} else {
ncr5380_log("Device not found at ID %i, Current Bus BSY=%02x\n", ncr->target_id, ncr->cur_bus);
ncr->cur_bus = 0;
}
}
break;
case STATE_SELECT:
if (!(bus & BUS_SEL)) {
if (!(bus & BUS_ATN)) {
if ((ncr->target_id != (uint8_t) -1) && scsi_device_present(&scsi_devices[ncr->bus][ncr->target_id])) {
ncr5380_log("Device found at ID %i, Current Bus BSY=%02x\n", ncr->target_id, ncr->cur_bus);
ncr->state = STATE_COMMAND;
ncr->cur_bus = BUS_BSY | BUS_REQ;
ncr5380_log("CurBus BSY|REQ=%02x\n", ncr->cur_bus);
ncr->command_pos = 0;
SET_BUS_STATE(ncr, SCSI_PHASE_COMMAND);
} else {
ncr->state = STATE_IDLE;
ncr->cur_bus = 0;
}
} else {
ncr5380_log("Set to SCSI Message Out\n");
ncr->new_phase = SCSI_PHASE_MESSAGE_OUT;
ncr->wait_data = 4;
ncr->msgout_pos = 0;
ncr->is_msgout = 1;
}
}
break;
case STATE_COMMAND:
if ((bus & BUS_ACK) && !(ncr->bus_in & BUS_ACK)) {
/*Write command byte to the output data register*/
ncr->command[ncr->command_pos++] = BUS_GETDATA(bus);
ncr->clear_req = 3;
ncr->new_phase = ncr->cur_bus & SCSI_PHASE_MESSAGE_IN;
ncr->cur_bus &= ~BUS_REQ;
ncr5380_log("Command pos=%i, output data=%02x\n", ncr->command_pos, BUS_GETDATA(bus));
if (ncr->command_pos == ncr5380_cmd_len[(ncr->command[0] >> 5) & 7]) {
if (ncr->is_msgout) {
ncr->is_msgout = 0;
#if 0
ncr->command[1] = (ncr->command[1] & 0x1f) | (ncr->msglun << 5);
#endif
}
/*Reset data position to default*/
ncr->data_pos = 0;
dev = &scsi_devices[ncr->bus][ncr->target_id];
ncr5380_log("SCSI Command 0x%02X for ID %d, status code=%02x\n", ncr->command[0], ncr->target_id, dev->status);
dev->buffer_length = -1;
scsi_device_command_phase0(dev, ncr->command);
ncr5380_log("SCSI ID %i: Command %02X: Buffer Length %i, SCSI Phase %02X\n", ncr->target_id, ncr->command[0], dev->buffer_length, dev->phase);
ncr->period = 1.0;
ncr->wait_data = 4;
ncr->data_wait = 0;
if (dev->status == SCSI_STATUS_OK) {
/*If the SCSI phase is Data In or Data Out, allocate the SCSI buffer based on the transfer length of the command*/
if (dev->buffer_length && ((dev->phase == SCSI_PHASE_DATA_IN) || (dev->phase == SCSI_PHASE_DATA_OUT))) {
p = scsi_device_get_callback(dev);
ncr->period = (p > 0.0) ? p : (((double) dev->buffer_length) * 0.2);
ncr5380_log("SCSI ID %i: command 0x%02x for p = %lf, update = %lf, len = %i, dmamode = %x\n", ncr->target_id, ncr->command[0], scsi_device_get_callback(dev), ncr->period, dev->buffer_length, ncr->dma_mode);
}
}
ncr->new_phase = dev->phase;
}
}
break;
case STATE_DATAIN:
dev = &scsi_devices[ncr->bus][ncr->target_id];
if ((bus & BUS_ACK) && !(ncr->bus_in & BUS_ACK)) {
if (ncr->data_pos >= dev->buffer_length) {
ncr->cur_bus &= ~BUS_REQ;
ncr5380_log("CMD Phase1 DataIn.\n");
scsi_device_command_phase1(dev);
ncr->new_phase = SCSI_PHASE_STATUS;
ncr->wait_data = 4;
ncr->wait_complete = 8;
} else {
if ((dev->sc != NULL) && (dev->sc->temp_buffer != NULL))
ncr->tx_data = dev->sc->temp_buffer[ncr->data_pos++];
ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP | BUS_REQ;
if (ncr->dma_mode == DMA_IDLE) { /*If a data in command that is not read 6/10 has been issued*/
ncr->data_wait |= 1;
ncr5380_log("DMA mode idle IN=%d.\n", ncr->data_pos);
ncr->timer(ncr->priv, ncr->period);
} else {
ncr5380_log("DMA mode IN=%d.\n", ncr->data_pos);
ncr->clear_req = 3;
}
ncr->cur_bus &= ~BUS_REQ;
ncr->new_phase = SCSI_PHASE_DATA_IN;
}
}
break;
case STATE_DATAOUT:
dev = &scsi_devices[ncr->bus][ncr->target_id];
if ((bus & BUS_ACK) && !(ncr->bus_in & BUS_ACK)) {
if ((dev->sc != NULL) && (dev->sc->temp_buffer != NULL))
dev->sc->temp_buffer[ncr->data_pos++] = BUS_GETDATA(bus);
if (ncr->data_pos >= dev->buffer_length) {
ncr->cur_bus &= ~BUS_REQ;
scsi_device_command_phase1(dev);
ncr->new_phase = SCSI_PHASE_STATUS;
ncr->wait_data = 4;
ncr->wait_complete = 8;
} else {
/*More data is to be transferred, place a request*/
if (ncr->dma_mode == DMA_IDLE) { /*If a data out command that is not write 6/10 has been issued*/
ncr->data_wait |= 1;
ncr5380_log("DMA mode idle out\n");
ncr->timer(ncr->priv, ncr->period);
} else
ncr->clear_req = 3;
ncr->cur_bus &= ~BUS_REQ;
ncr5380_log("CurBus ~REQ_DataOut=%02x\n", ncr->cur_bus);
}
}
break;
case STATE_STATUS:
if ((bus & BUS_ACK) && !(ncr->bus_in & BUS_ACK)) {
/*All transfers done, wait until next transfer*/
scsi_device_identify(&scsi_devices[ncr->bus][ncr->target_id], SCSI_LUN_USE_CDB);
ncr->cur_bus &= ~BUS_REQ;
ncr->new_phase = SCSI_PHASE_MESSAGE_IN;
ncr->wait_data = 4;
ncr->wait_complete = 8;
}
break;
case STATE_MESSAGEIN:
if ((bus & BUS_ACK) && !(ncr->bus_in & BUS_ACK)) {
ncr->cur_bus &= ~BUS_REQ;
ncr->new_phase = BUS_IDLE;
ncr->wait_data = 4;
}
break;
case STATE_MESSAGEOUT:
ncr5380_log("Ack on MSGOUT = %02x\n", (bus & BUS_ACK));
if ((bus & BUS_ACK) && !(ncr->bus_in & BUS_ACK)) {
ncr->msgout[ncr->msgout_pos++] = BUS_GETDATA(bus);
msglen = ncr5380_getmsglen(ncr->msgout, ncr->msgout_pos);
if (ncr->msgout_pos >= msglen) {
if ((ncr->msgout[0] & (0x80 | 0x20)) == 0x80)
ncr->msglun = ncr->msgout[0] & 7;
ncr->cur_bus &= ~BUS_REQ;
ncr->state = STATE_MESSAGE_ID;
}
}
break;
case STATE_MESSAGE_ID:
if ((ncr->target_id != (uint8_t) -1) && scsi_device_present(&scsi_devices[ncr->bus][ncr->target_id])) {
ncr5380_log("Device found at ID %i on MSGOUT, Current Bus BSY=%02x\n", ncr->target_id, ncr->cur_bus);
scsi_device_identify(&scsi_devices[ncr->bus][ncr->target_id], ncr->msglun);
ncr->state = STATE_COMMAND;
ncr->cur_bus = BUS_BSY | BUS_REQ;
ncr5380_log("CurBus BSY|REQ=%02x\n", ncr->cur_bus);
ncr->command_pos = 0;
SET_BUS_STATE(ncr, SCSI_PHASE_COMMAND);
}
break;
default:
break;
}
ncr->bus_in = bus;
}
void
ncr5380_write(uint16_t port, uint8_t val, ncr_t *ncr)
{
scsi_bus_t *scsi_bus = &ncr->scsibus;
int bus_host = 0;
ncr5380_log("NCR5380 write(%04x,%02x)\n", port & 7, val);
@@ -462,8 +169,10 @@ ncr5380_write(uint16_t port, uint8_t val, ncr_t *ncr)
if ((val & 0x80) && !(ncr->icr & 0x80)) {
ncr5380_log("Resetting the 5380\n");
ncr5380_reset(ncr);
ncr5380_irq(ncr, 1);
}
ncr->icr = val;
ncr5380_log("ICR WaitData=%d, ClearReq=%d.\n", scsi_bus->wait_data, scsi_bus->clear_req);
break;
case 2: /* Mode register */
@@ -472,10 +181,8 @@ ncr5380_write(uint16_t port, uint8_t val, ncr_t *ncr)
ncr->icr &= ~ICR_ARB_LOST;
ncr->icr |= ICR_ARB_IN_PROGRESS;
}
ncr->mode = val;
ncr->dma_mode_ext(ncr, ncr->priv);
ncr->dma_mode_ext(ncr, ncr->priv, val);
break;
case 3: /* Target Command Register */
@@ -488,17 +195,17 @@ ncr5380_write(uint16_t port, uint8_t val, ncr_t *ncr)
break;
case 5: /* start DMA Send */
ncr5380_log("Write: start DMA send register\n");
pclog("Write: start DMA send register\n");
/*a Write 6/10 has occurred, start the timer when the block count is loaded*/
ncr->dma_mode = DMA_SEND;
scsi_bus->tx_mode = DMA_OUT_TX_BUS;
if (ncr->dma_send_ext)
ncr->dma_send_ext(ncr, ncr->priv);
break;
case 7: /* start DMA Initiator Receive */
ncr5380_log("[%04X:%08X]: Write: start DMA initiator receive register, dma? = %02x\n", CS, cpu_state.pc, ncr->mode & MODE_DMA);
ncr5380_log("[%04X:%08X]: Write: start DMA initiator receive register, waitdata=%d, clearreq=%d.\n", CS, cpu_state.pc, scsi_bus->wait_data, scsi_bus->clear_req);
/*a Read 6/10 has occurred, start the timer when the block count is loaded*/
ncr->dma_mode = DMA_INITIATOR_RECEIVE;
scsi_bus->tx_mode = DMA_IN_TX_BUS;
if (ncr->dma_initiator_receive_ext)
ncr->dma_initiator_receive_ext(ncr, ncr->priv);
break;
@@ -509,12 +216,13 @@ ncr5380_write(uint16_t port, uint8_t val, ncr_t *ncr)
}
bus_host = ncr5380_get_bus_host(ncr);
ncr5380_bus_update(ncr, bus_host);
scsi_bus_update(scsi_bus, bus_host);
}
uint8_t
ncr5380_read(uint16_t port, ncr_t *ncr)
{
scsi_bus_t *scsi_bus = &ncr->scsibus;
uint8_t ret = 0xff;
int bus;
int bus_state;
@@ -524,12 +232,17 @@ ncr5380_read(uint16_t port, ncr_t *ncr)
ncr5380_log("Read: Current SCSI data register\n");
if (ncr->icr & ICR_DBP) {
/*Return the data from the output register if on data bus phase from ICR*/
ret = ncr->output_data;
ncr5380_log("[%04X:%08X]: Data Bus Phase, ret=%02x, clearreq=%d, waitdata=%x.\n", CS, cpu_state.pc, ret, ncr->clear_req, ncr->wait_data);
if (scsi_bus->command_issued) {
bus = scsi_bus_read(scsi_bus);
ret = BUS_GETDATA(bus);
} else
ret = ncr->output_data;
ncr5380_log("[%04X:%08X]: Data Bus Phase, ret=%02x, clearreq=%d, waitdata=%x, txmode=%x.\n", CS, cpu_state.pc, ret, scsi_bus->clear_req, scsi_bus->wait_data, scsi_bus->tx_mode);
} else {
/*Return the data from the SCSI bus*/
ncr5380_bus_read(ncr);
ret = BUS_GETDATA(ncr->cur_bus);
bus = scsi_bus_read(scsi_bus);
ret = BUS_GETDATA(bus);
ncr5380_log("[%04X:%08X]: NCR Get SCSI bus data=%02x.\n", CS, cpu_state.pc, ret);
}
break;
@@ -552,15 +265,16 @@ ncr5380_read(uint16_t port, ncr_t *ncr)
case 4: /* Current SCSI Bus status */
ncr5380_log("Read: SCSI bus status register\n");
ret = 0;
ncr5380_bus_read(ncr);
ncr5380_log("NCR cur bus stat=%02x\n", ncr->cur_bus & 0xff);
ret |= (ncr->cur_bus & 0xff);
bus = scsi_bus_read(scsi_bus);
ret |= (bus & 0xff);
if (ncr->icr & ICR_SEL)
ret |= BUS_SEL;
if (ncr->icr & ICR_BSY)
ret |= BUS_BSY;
// if ((ret & SCSI_PHASE_MESSAGE_IN) == SCSI_PHASE_MESSAGE_IN)
// ret &= ~BUS_REQ;
/*Note by TC1995: Horrible hack, I know.*/
(void) scsi_bus_read(scsi_bus);
(void) scsi_bus_read(scsi_bus);
break;
case 5: /* Bus and Status register */
@@ -571,13 +285,12 @@ ncr5380_read(uint16_t port, ncr_t *ncr)
ncr5380_log("Get host from Interrupt\n");
/*Check if the phase in process matches with TCR's*/
if ((bus & SCSI_PHASE_MESSAGE_IN) == (ncr->cur_bus & SCSI_PHASE_MESSAGE_IN)) {
if ((bus & SCSI_PHASE_MESSAGE_IN) == (scsi_bus->bus_out & SCSI_PHASE_MESSAGE_IN)) {
ncr5380_log("Phase match\n");
ret |= STATUS_PHASE_MATCH;
}
ncr5380_bus_read(ncr);
bus = ncr->cur_bus;
bus = scsi_bus_read(scsi_bus);
if ((bus & BUS_ACK) || (ncr->icr & ICR_ACK))
ret |= STATUS_ACK;
@@ -610,8 +323,8 @@ ncr5380_read(uint16_t port, ncr_t *ncr)
case 6:
ncr5380_log("Read: Input Data.\n");
ncr5380_bus_read(ncr);
ret = BUS_GETDATA(ncr->cur_bus);
bus = scsi_bus_read(scsi_bus);
ret = BUS_GETDATA(bus);
break;
case 7: /* reset Parity/Interrupt */

View File

@@ -121,7 +121,8 @@ ncr53c400_write(uint32_t addr, uint8_t val, void *priv)
{
ncr53c400_t *ncr400 = (ncr53c400_t *) priv;
ncr_t *ncr = &ncr400->ncr;
scsi_device_t *dev = &scsi_devices[ncr->bus][ncr->target_id];
scsi_bus_t *scsi_bus = &ncr->scsibus;
scsi_device_t *dev = &scsi_devices[ncr->bus][scsi_bus->target_id];
addr &= 0x3fff;
@@ -146,16 +147,9 @@ ncr53c400_write(uint32_t addr, uint8_t val, void *priv)
if (ncr400->buffer_host_pos == MIN(128, dev->buffer_length)) {
ncr400->status_ctrl |= STATUS_BUFFER_NOT_READY;
ncr400->busy = 1;
if (!(ncr->mode & MODE_MONITOR_BUSY) && ((scsi_device_get_callback(dev) > 0.0)))
timer_on_auto(&ncr400->timer, ncr->period / 250.0);
else if ((ncr->mode & MODE_MONITOR_BUSY) && !ncr->wait_data) {
if (scsi_device_get_callback(dev) > 0.0)
timer_on_auto(&ncr400->timer, 100.0);
else
timer_on_auto(&ncr400->timer, 40.0);
}
}
}
} else
ncr53c400_log("No Write.\n");
break;
case 0x3980:
@@ -173,7 +167,7 @@ ncr53c400_write(uint32_t addr, uint8_t val, void *priv)
break;
case 0x3981: /* block counter register */
ncr53c400_log("Write block counter register: val=%d, dma mode=%x, period=%lf.\n", val, ncr->dma_mode, ncr->period);
ncr53c400_log("Write block counter register: val=%d, dma mode=%x, period=%lf.\n", val, scsi_bus->tx_mode, scsi_bus->period);
ncr400->block_count = val;
ncr400->block_count_loaded = 1;
@@ -186,17 +180,11 @@ ncr53c400_write(uint32_t addr, uint8_t val, void *priv)
}
if ((ncr->mode & MODE_DMA) && (dev->buffer_length > 0)) {
memset(ncr400->buffer, 0, MIN(128, dev->buffer_length));
if (ncr->mode & MODE_MONITOR_BUSY)
timer_on_auto(&ncr400->timer, (ncr->period / 4.0) * 3.0);
else if (scsi_device_get_callback(dev) > 0.0)
timer_on_auto(&ncr400->timer, 40.0);
else
timer_on_auto(&ncr400->timer, ncr->period);
ncr->wait_data_back = ncr->wait_data;
ncr53c400_log("DMA timer on=%02x, callback=%lf, scsi buflen=%d, waitdata=%d, waitcomplete=%d, clearreq=%d, datawait=%d, enabled=%d.\n",
ncr->mode & MODE_MONITOR_BUSY, scsi_device_get_callback(dev), dev->buffer_length, ncr->wait_data, ncr->wait_complete, ncr->clear_req, ncr->data_wait, timer_is_enabled(&ncr400->timer));
}
timer_on_auto(&ncr400->timer, scsi_bus->period);
ncr53c400_log("DMA timer on=%02x, callback=%lf, scsi buflen=%d, waitdata=%d, waitcomplete=%d, clearreq=%d, p=%lf enabled=%d.\n",
ncr->mode & MODE_MONITOR_BUSY, scsi_device_get_callback(dev), dev->buffer_length, scsi_bus->wait_data, scsi_bus->wait_complete, scsi_bus->clear_req, scsi_bus->period, timer_is_enabled(&ncr400->timer));
} else
ncr53c400_log("No Timer.\n");
break;
default:
@@ -216,7 +204,8 @@ ncr53c400_read(uint32_t addr, void *priv)
{
ncr53c400_t *ncr400 = (ncr53c400_t *) priv;
ncr_t *ncr = &ncr400->ncr;
scsi_device_t *dev = &scsi_devices[ncr->bus][ncr->target_id];
scsi_bus_t *scsi_bus = &ncr->scsibus;
scsi_device_t *dev = &scsi_devices[ncr->bus][scsi_bus->target_id];
uint8_t ret = 0xff;
addr &= 0x3fff;
@@ -240,7 +229,7 @@ ncr53c400_read(uint32_t addr, void *priv)
break;
case 0x3900:
if (ncr400->buffer_host_pos >= MIN(128, dev->buffer_length) || (!(ncr400->status_ctrl & CTRL_DATA_DIR))) {
if ((ncr400->buffer_host_pos >= MIN(128, dev->buffer_length)) || (!(ncr400->status_ctrl & CTRL_DATA_DIR))) {
ret = 0xff;
ncr53c400_log("No Read.\n");
} else {
@@ -249,15 +238,6 @@ ncr53c400_read(uint32_t addr, void *priv)
if (ncr400->buffer_host_pos == MIN(128, dev->buffer_length)) {
ncr400->status_ctrl |= STATUS_BUFFER_NOT_READY;
ncr53c400_log("Transfer busy read, status = %02x.\n", ncr400->status_ctrl);
if (!(ncr->mode & MODE_MONITOR_BUSY) && (scsi_device_get_callback(dev) > 0.0))
timer_on_auto(&ncr400->timer, ncr->period / 250.0);
else if ((ncr->mode & MODE_MONITOR_BUSY) && !ncr->wait_data) {
if (scsi_device_get_callback(dev) > 0.0)
timer_on_auto(&ncr400->timer, 100.0);
else
timer_on_auto(&ncr400->timer, 40.0);
}
}
}
break;
@@ -272,7 +252,7 @@ ncr53c400_read(uint32_t addr, void *priv)
if (ncr->mode & 0x30) { /*Parity bits*/
if (!(ncr->mode & MODE_DMA)) { /*This is to avoid RTBios 8.10R BIOS problems with the hard disk and detection.*/
ret |= 0x01; /*If the parity bits are set, bit 0 of the 53c400 status port should be set as well.*/
ncr->mode = 0; /*Required by RTASPI10.SYS otherwise it won't initialize.*/
ncr->mode = 0x00; /*Required by RTASPI10.SYS otherwise it won't initialize.*/
}
}
ncr53c400_log("NCR 53c400 status=%02x.\n", ret);
@@ -411,46 +391,47 @@ t130b_in(uint16_t port, void *priv)
}
static void
ncr53c400_dma_mode_ext(void *priv, void *ext_priv)
ncr53c400_dma_mode_ext(void *priv, UNUSED(void *ext_priv), uint8_t val)
{
ncr53c400_t *ncr400 = (ncr53c400_t *) ext_priv;
ncr_t *ncr = (ncr_t *) priv;
scsi_bus_t *scsi_bus = &ncr->scsibus;
/*When a pseudo-DMA transfer has completed (Send or Initiator Receive), mark it as complete and idle the status*/
ncr53c400_log("BlockCountLoaded=%d.\n", ncr400->block_count_loaded);
if (!ncr400->block_count_loaded) {
if (!(ncr->mode & MODE_DMA)) {
ncr53c400_log("No DMA mode\n");
ncr->tcr &= ~TCR_LAST_BYTE_SENT;
ncr->isr &= ~STATUS_END_OF_DMA;
ncr->dma_mode = DMA_IDLE;
}
ncr53c400_log("NCR 53c400: BlockCountLoaded=%d, DMA mode enabled=%02x, valDMA=%02x.\n", ncr400->block_count_loaded, ncr->mode & MODE_DMA, val & MODE_DMA);
if (!(val & MODE_DMA) && (ncr->mode & MODE_DMA)) {
ncr->tcr &= ~TCR_LAST_BYTE_SENT;
ncr->isr &= ~STATUS_END_OF_DMA;
scsi_bus->tx_mode = PIO_TX_BUS;
}
}
static void
ncr53c400_callback(void *priv)
{
ncr53c400_t *ncr400 = (void *) priv;
ncr53c400_t *ncr400 = (ncr53c400_t *) priv;
ncr_t *ncr = &ncr400->ncr;
scsi_device_t *dev = &scsi_devices[ncr->bus][ncr->target_id];
scsi_bus_t *scsi_bus = &ncr->scsibus;
scsi_device_t *dev = &scsi_devices[ncr->bus][scsi_bus->target_id];
int bus;
uint8_t c;
uint8_t temp;
uint8_t status;
if (ncr->dma_mode != DMA_IDLE)
if (scsi_bus->tx_mode != PIO_TX_BUS)
timer_on_auto(&ncr400->timer, 1.0);
if (ncr->data_wait & 1) {
ncr->clear_req = 3;
ncr->data_wait &= ~1;
if (scsi_bus->data_wait & 1) {
scsi_bus->clear_req = 3;
scsi_bus->data_wait &= ~1;
}
if (ncr->dma_mode == DMA_IDLE)
if (scsi_bus->tx_mode == PIO_TX_BUS) {
ncr53c400_log("Timer CMD=%02x.\n", scsi_bus->command[0]);
return;
}
switch (ncr->dma_mode) {
case DMA_SEND:
switch (scsi_bus->tx_mode) {
case DMA_OUT_TX_BUS:
if (ncr400->status_ctrl & CTRL_DATA_DIR) {
ncr53c400_log("DMA_SEND with DMA direction set wrong\n");
break;
@@ -468,8 +449,8 @@ ncr53c400_callback(void *priv)
while (1) {
for (c = 0; c < 10; c++) {
ncr5380_bus_read(ncr);
if (ncr->cur_bus & BUS_REQ)
status = scsi_bus_read(scsi_bus);
if (status & BUS_REQ)
break;
}
/* Data ready. */
@@ -478,8 +459,8 @@ ncr53c400_callback(void *priv)
bus = ncr5380_get_bus_host(ncr) & ~BUS_DATAMASK;
bus |= BUS_SETDATA(temp);
ncr5380_bus_update(ncr, bus | BUS_ACK);
ncr5380_bus_update(ncr, bus & ~BUS_ACK);
scsi_bus_update(scsi_bus, bus | BUS_ACK);
scsi_bus_update(scsi_bus, bus & ~BUS_ACK);
ncr400->buffer_pos++;
ncr53c400_log("NCR 53c400 Buffer pos for writing = %d\n", ncr400->buffer_pos);
@@ -492,7 +473,7 @@ ncr53c400_callback(void *priv)
ncr400->block_count = (ncr400->block_count - 1) & 0xff;
ncr53c400_log("NCR 53c400 Remaining blocks to be written=%d\n", ncr400->block_count);
if (!ncr400->block_count) {
ncr->dma_mode = DMA_IDLE;
scsi_bus->tx_mode = PIO_TX_BUS;
ncr400->block_count_loaded = 0;
ncr53c400_log("IO End of write transfer\n");
ncr->tcr |= TCR_LAST_BYTE_SENT;
@@ -507,7 +488,7 @@ ncr53c400_callback(void *priv)
}
break;
case DMA_INITIATOR_RECEIVE:
case DMA_IN_TX_BUS:
if (!(ncr400->status_ctrl & CTRL_DATA_DIR)) {
ncr53c400_log("DMA_INITIATOR_RECEIVE with DMA direction set wrong\n");
break;
@@ -523,18 +504,18 @@ ncr53c400_callback(void *priv)
while (1) {
for (c = 0; c < 10; c++) {
ncr5380_bus_read(ncr);
if (ncr->cur_bus & BUS_REQ)
status = scsi_bus_read(scsi_bus);
if (status & BUS_REQ)
break;
}
/* Data ready. */
ncr5380_bus_read(ncr);
temp = BUS_GETDATA(ncr->cur_bus);
bus = scsi_bus_read(scsi_bus);
temp = BUS_GETDATA(bus);
bus = ncr5380_get_bus_host(ncr);
ncr5380_bus_update(ncr, bus | BUS_ACK);
ncr5380_bus_update(ncr, bus & ~BUS_ACK);
scsi_bus_update(scsi_bus, bus | BUS_ACK);
scsi_bus_update(scsi_bus, bus & ~BUS_ACK);
ncr400->buffer[ncr400->buffer_pos++] = temp;
ncr53c400_log("NCR 53c400 Buffer pos for reading = %d\n", ncr400->buffer_pos);
@@ -546,7 +527,7 @@ ncr53c400_callback(void *priv)
ncr400->block_count = (ncr400->block_count - 1) & 0xff;
ncr53c400_log("NCR 53c400 Remaining blocks to be read=%d\n", ncr400->block_count);
if (!ncr400->block_count) {
ncr->dma_mode = DMA_IDLE;
scsi_bus->tx_mode = PIO_TX_BUS;
ncr400->block_count_loaded = 0;
ncr53c400_log("IO End of read transfer\n");
ncr->isr |= STATUS_END_OF_DMA;
@@ -564,13 +545,12 @@ ncr53c400_callback(void *priv)
break;
}
ncr53c400_log("Bus Read.\n");
ncr5380_bus_read(ncr);
status = scsi_bus_read(scsi_bus);
if (!(ncr->cur_bus & BUS_BSY) && (ncr->mode & MODE_MONITOR_BUSY)) {
if (!(status & BUS_BSY) && (ncr->mode & MODE_MONITOR_BUSY)) {
ncr53c400_log("Updating DMA\n");
ncr->mode &= ~MODE_DMA;
ncr->dma_mode = DMA_IDLE;
scsi_bus->tx_mode = PIO_TX_BUS;
ncr400->block_count_loaded = 0;
}
}
@@ -643,6 +623,7 @@ ncr53c400_init(const device_t *info)
const char *fn;
ncr53c400_t *ncr400;
ncr_t *ncr;
scsi_bus_t *scsi_bus;
ncr400 = malloc(sizeof(ncr53c400_t));
memset(ncr400, 0x00, sizeof(ncr53c400_t));
@@ -651,6 +632,7 @@ ncr53c400_init(const device_t *info)
ncr400->type = info->local;
ncr->bus = scsi_get_bus();
scsi_bus = &ncr->scsibus;
switch (ncr400->type) {
case ROM_LCS6821N: /* Longshine LCS6821N */
@@ -734,11 +716,17 @@ ncr53c400_init(const device_t *info)
ncr->dma_send_ext = NULL;
ncr->dma_initiator_receive_ext = NULL;
ncr->timer = ncr53c400_timer_on_auto;
scsi_bus->bus_device = ncr->bus;
scsi_bus->timer = ncr->timer;
scsi_bus->priv = ncr->priv;
ncr400->status_ctrl = STATUS_BUFFER_NOT_READY;
ncr400->buffer_host_pos = 128;
timer_add(&ncr400->timer, ncr53c400_callback, ncr400, 0);
scsi_bus_set_speed(ncr->bus, 5000000.0);
scsi_bus->speed = 0.2;
scsi_bus->divider = 2.0;
scsi_bus->multi = 1.750;
return ncr400;
}

View File

@@ -69,7 +69,8 @@ t128_write(uint32_t addr, uint8_t val, void *priv)
{
t128_t *t128 = (t128_t *) priv;
ncr_t *ncr = &t128->ncr;
const scsi_device_t *dev = &scsi_devices[ncr->bus][ncr->target_id];
scsi_bus_t *scsi_bus = &ncr->scsibus;
const scsi_device_t *dev = &scsi_devices[ncr->bus][scsi_bus->target_id];
addr &= 0x3fff;
if ((addr >= 0x1800) && (addr < 0x1880))
@@ -84,7 +85,7 @@ t128_write(uint32_t addr, uint8_t val, void *priv)
ncr5380_write((addr - 0x1d00) >> 5, val, ncr);
else if ((addr >= 0x1e00) && (addr < 0x2000)) {
if ((t128->host_pos < MIN(512, dev->buffer_length)) &&
(ncr->dma_mode == DMA_SEND)) {
(scsi_bus->tx_mode == DMA_OUT_TX_BUS)) {
t128->buffer[t128->host_pos] = val;
t128->host_pos++;
@@ -106,7 +107,8 @@ t128_read(uint32_t addr, void *priv)
{
t128_t *t128 = (t128_t *) priv;
ncr_t *ncr = &t128->ncr;
scsi_device_t *dev = &scsi_devices[ncr->bus][ncr->target_id];
scsi_bus_t *scsi_bus = &ncr->scsibus;
scsi_device_t *dev = &scsi_devices[ncr->bus][scsi_bus->target_id];
uint8_t ret = 0xff;
addr &= 0x3fff;
@@ -124,7 +126,7 @@ t128_read(uint32_t addr, void *priv)
ret = ncr5380_read((addr - 0x1d00) >> 5, ncr);
else if (addr >= 0x1e00 && addr < 0x2000) {
if ((t128->host_pos >= MIN(512, dev->buffer_length)) ||
(ncr->dma_mode != DMA_INITIATOR_RECEIVE))
(scsi_bus->tx_mode != DMA_IN_TX_BUS))
ret = 0xff;
else {
ret = t128->buffer[t128->host_pos++];
@@ -135,8 +137,8 @@ t128_read(uint32_t addr, void *priv)
if (t128->host_pos == MIN(512, dev->buffer_length)) {
t128->status &= ~0x04;
t128_log("T128 Transfer busy read, status = %02x, period = %lf\n",
t128->status, ncr->period);
if ((ncr->period == 0.2) || (ncr->period == 0.02))
t128->status, scsi_bus->period);
if ((scsi_bus->period == 0.2) || (scsi_bus->period == 0.02))
timer_on_auto(&t128->timer, 40.2);
} else if ((t128->host_pos < MIN(512, dev->buffer_length)) &&
(scsi_device_get_callback(dev) > 100.0))
@@ -148,15 +150,16 @@ t128_read(uint32_t addr, void *priv)
}
static void
t128_dma_mode_ext(void *priv, void *ext_priv)
t128_dma_mode_ext(void *priv, void *ext_priv, UNUSED(uint8_t val))
{
t128_t *t128 = (t128_t *) ext_priv;
ncr_t *ncr = (ncr_t *) priv;
scsi_bus_t *scsi_bus = &ncr->scsibus;
/*Don't stop the timer until it finishes the transfer*/
if (t128->block_loaded && (ncr->mode & MODE_DMA)) {
t128_log("Continuing DMA mode\n");
timer_on_auto(&t128->timer, ncr->period + 1.0);
timer_on_auto(&t128->timer, scsi_bus->period + 1.0);
}
/*When a pseudo-DMA transfer has completed (Send or Initiator Receive), mark it as complete and idle the status*/
@@ -164,7 +167,7 @@ t128_dma_mode_ext(void *priv, void *ext_priv)
t128_log("No DMA mode\n");
ncr->tcr &= ~TCR_LAST_BYTE_SENT;
ncr->isr &= ~STATUS_END_OF_DMA;
ncr->dma_mode = DMA_IDLE;
scsi_bus->tx_mode = PIO_TX_BUS;
}
}
@@ -173,7 +176,8 @@ t128_dma_send_ext(void *priv, void *ext_priv)
{
t128_t *t128 = (t128_t *) ext_priv;
ncr_t *ncr = (ncr_t *) priv;
scsi_device_t *dev = &scsi_devices[ncr->bus][ncr->target_id];
scsi_bus_t *scsi_bus = &ncr->scsibus;
scsi_device_t *dev = &scsi_devices[ncr->bus][scsi_bus->target_id];
if ((ncr->mode & MODE_DMA) && !timer_is_on(&t128->timer) && (dev->buffer_length > 0)) {
memset(t128->buffer, 0, MIN(512, dev->buffer_length));
@@ -194,7 +198,8 @@ t128_dma_initiator_receive_ext(void *priv, void *ext_priv)
{
t128_t *t128 = (t128_t *) ext_priv;
ncr_t *ncr = (ncr_t *) priv;
scsi_device_t *dev = &scsi_devices[ncr->bus][ncr->target_id];
scsi_bus_t *scsi_bus = &ncr->scsibus;
scsi_device_t *dev = &scsi_devices[ncr->bus][scsi_bus->target_id];
if ((ncr->mode & MODE_DMA) && !timer_is_on(&t128->timer) && (dev->buffer_length > 0)) {
memset(t128->buffer, 0, MIN(512, dev->buffer_length));
@@ -227,27 +232,29 @@ t128_callback(void *priv)
{
t128_t *t128 = (void *) priv;
ncr_t *ncr = &t128->ncr;
scsi_device_t *dev = &scsi_devices[ncr->bus][ncr->target_id];
int bus;
uint8_t c;
uint8_t temp;
scsi_bus_t *scsi_bus = &ncr->scsibus;
scsi_device_t *dev = &scsi_devices[ncr->bus][scsi_bus->target_id];
int bus;
uint8_t c;
uint8_t temp;
uint8_t status;
if ((ncr->dma_mode != DMA_IDLE) && (ncr->mode & MODE_DMA) && t128->block_loaded) {
if ((scsi_bus->tx_mode != PIO_TX_BUS) && (ncr->mode & MODE_DMA) && t128->block_loaded) {
if ((t128->host_pos == MIN(512, dev->buffer_length)) && t128->block_count)
t128->status |= 0x04;
timer_on_auto(&t128->timer, ncr->period / 55.0);
timer_on_auto(&t128->timer, scsi_bus->period / 55.0);
}
if (ncr->data_wait & 1) {
ncr->clear_req = 3;
ncr->data_wait &= ~1;
if (ncr->dma_mode == DMA_IDLE)
if (scsi_bus->data_wait & 1) {
scsi_bus->clear_req = 3;
scsi_bus->data_wait &= ~1;
if (scsi_bus->tx_mode == PIO_TX_BUS)
return;
}
switch (ncr->dma_mode) {
case DMA_SEND:
switch (scsi_bus->tx_mode) {
case DMA_OUT_TX_BUS:
if (!(t128->status & 0x04)) {
t128_log("Write status busy, block count = %i, host pos = %i\n", t128->block_count, t128->host_pos);
break;
@@ -263,8 +270,8 @@ t128_callback(void *priv)
write_again:
for (c = 0; c < 10; c++) {
ncr5380_bus_read(ncr);
if (ncr->cur_bus & BUS_REQ)
status = scsi_bus_read(scsi_bus);
if (status & BUS_REQ)
break;
}
@@ -274,8 +281,8 @@ write_again:
bus = ncr5380_get_bus_host(ncr) & ~BUS_DATAMASK;
bus |= BUS_SETDATA(temp);
ncr5380_bus_update(ncr, bus | BUS_ACK);
ncr5380_bus_update(ncr, bus & ~BUS_ACK);
scsi_bus_update(scsi_bus, bus | BUS_ACK);
scsi_bus_update(scsi_bus, bus & ~BUS_ACK);
t128->pos++;
t128_log("T128 Buffer pos for writing = %d\n", t128->pos);
@@ -302,7 +309,7 @@ write_again:
goto write_again;
break;
case DMA_INITIATOR_RECEIVE:
case DMA_IN_TX_BUS:
if (!(t128->status & 0x04)) {
t128_log("Read status busy, block count = %i, host pos = %i\n", t128->block_count, t128->host_pos);
break;
@@ -318,19 +325,19 @@ write_again:
read_again:
for (c = 0; c < 10; c++) {
ncr5380_bus_read(ncr);
if (ncr->cur_bus & BUS_REQ)
status = scsi_bus_read(scsi_bus);
if (status & BUS_REQ)
break;
}
/* Data ready. */
ncr5380_bus_read(ncr);
temp = BUS_GETDATA(ncr->cur_bus);
bus = scsi_bus_read(scsi_bus);
temp = BUS_GETDATA(bus);
bus = ncr5380_get_bus_host(ncr);
ncr5380_bus_update(ncr, bus | BUS_ACK);
ncr5380_bus_update(ncr, bus & ~BUS_ACK);
scsi_bus_update(scsi_bus, bus | BUS_ACK);
scsi_bus_update(scsi_bus, bus & ~BUS_ACK);
t128->buffer[t128->pos++] = temp;
t128_log("T128 Buffer pos for reading=%d, temp=%02x, len=%d.\n", t128->pos, temp, dev->buffer_length);
@@ -360,12 +367,12 @@ read_again:
break;
}
ncr5380_bus_read(ncr);
status = scsi_bus_read(scsi_bus);
if (!(ncr->cur_bus & BUS_BSY) && (ncr->mode & MODE_MONITOR_BUSY)) {
if (!(status & BUS_BSY) && (ncr->mode & MODE_MONITOR_BUSY)) {
t128_log("Updating DMA\n");
ncr->mode &= ~MODE_DMA;
ncr->dma_mode = DMA_IDLE;
scsi_bus->tx_mode = PIO_TX_BUS;
timer_on_auto(&t128->timer, 10.0);
}
}
@@ -467,12 +474,14 @@ t128_init(const device_t *info)
{
t128_t *t128;
ncr_t *ncr;
scsi_bus_t *scsi_bus;
t128 = malloc(sizeof(t128_t));
memset(t128, 0x00, sizeof(t128_t));
ncr = &t128->ncr;
ncr->bus = scsi_get_bus();
scsi_bus = &ncr->scsibus;
if (info->flags & DEVICE_MCA) {
rom_init(&t128->bios_rom, T128_ROM,
@@ -504,6 +513,9 @@ t128_init(const device_t *info)
ncr->dma_send_ext = t128_dma_send_ext;
ncr->dma_initiator_receive_ext = t128_dma_initiator_receive_ext;
ncr->timer = t128_timer_on_auto;
scsi_bus->bus_device = ncr->bus;
scsi_bus->timer = ncr->timer;
scsi_bus->priv = ncr->priv;
t128->status = 0x00 /*0x04*/;
t128->host_pos = 512;
if (!t128->bios_enabled && !(info->flags & DEVICE_MCA))
@@ -516,6 +528,9 @@ t128_init(const device_t *info)
timer_add(&t128->timer, t128_callback, t128, 0);
scsi_bus_set_speed(ncr->bus, 5000000.0);
scsi_bus->speed = 0.2;
scsi_bus->divider = 1.0;
scsi_bus->multi = 1.0;
return t128;
}

View File

@@ -273,20 +273,21 @@ ad1848_write(uint16_t addr, uint8_t val, void *priv)
return;
case 12:
if (ad1848->type != AD1848_TYPE_DEFAULT)
ad1848->regs[12] = ((ad1848->regs[12] & 0x0f) + (val & 0xf0)) | 0x80;
if (ad1848->type >= AD1848_TYPE_CS4248) {
ad1848->regs[12] = 0x80 | (val & 0x70) | (ad1848->regs[12] & 0x0f);
if ((ad1848->type >= AD1848_TYPE_CS4231) && (ad1848->type < AD1848_TYPE_CS4235)) {
if (val & 0x40)
ad1848->fmt_mask |= 0x80;
else
ad1848->fmt_mask &= ~0x80;
}
}
return;
case 14:
ad1848->count = ad1848->regs[15] | (val << 8);
break;
case 17:
/* Enable additional data formats on modes 2 and 3 where supported. */
if ((ad1848->type == AD1848_TYPE_CS4231) || (ad1848->type == AD1848_TYPE_CS4236B))
ad1848->fmt_mask = (val & 0x40) ? 0xf0 : 0x70;
break;
case 18:
case 19:
if (ad1848->type >= AD1848_TYPE_CS4236B) {

View File

@@ -12,7 +12,7 @@
*
* Authors: RichardG, <richardg867@gmail.com>
*
* Copyright 2021-2022 RichardG.
* Copyright 2021-2025 RichardG.
*/
#include <math.h>
#include <stdarg.h>
@@ -386,7 +386,7 @@ cs423x_write(uint16_t addr, uint8_t val, void *priv)
dev->ram_dl = CRYSTAL_RAM_CMD;
/* Update PnP state and resource data. */
dev->pnp_size = 384; /* we don't know the length */
dev->pnp_size = (dev->type >= CRYSTAL_CS4236) ? 384 : 256; /* we don't know the length */
cs423x_pnp_enable(dev, 1, 0);
}
break;
@@ -853,12 +853,13 @@ cs423x_init(const device_t *info)
dev->type = info->local & 0xff;
cs423x_log("CS423x: init(%02X)\n", dev->type);
switch (dev->type) {
case CRYSTAL_CS4235:
case CRYSTAL_CS4236B:
case CRYSTAL_CS4237B:
case CRYSTAL_CS4238B:
case CRYSTAL_CS4235:
case CRYSTAL_CS4239:
/* Same WSS codec and EEPROM structure. */
dev->ad1848_type = (dev->type == CRYSTAL_CS4235) ? AD1848_TYPE_CS4235 : AD1848_TYPE_CS4236;
dev->ad1848_type = (dev->type >= CRYSTAL_CS4235) ? AD1848_TYPE_CS4235 : AD1848_TYPE_CS4236B;
dev->pnp_offset = 0x4013;
/* Different Chip Version and ID registers, which shouldn't be reset by ad1848_init. */

View File

@@ -86,7 +86,7 @@
* Copyright 2008-2024 Sarah Walker.
* Copyright 2024 Miran Grca.
*/
#define _USE_MATH_DEFINES
#define _USE_MATH_DEFINES
#include <math.h>
#include <stdarg.h>
#include <stdint.h>
@@ -706,6 +706,7 @@ static uint8_t
pas16_in(uint16_t port, void *priv)
{
pas16_t *pas16 = (pas16_t *) priv;
scsi_bus_t *scsi_bus = NULL;
uint8_t ret = 0xff;
port -= pas16->base;
@@ -784,9 +785,11 @@ pas16_in(uint16_t port, void *priv)
ret = t128_read(0x1e00, pas16->scsi);
break;
case 0x5c01:
if (pas16->has_scsi)
if (pas16->has_scsi) {
scsi_bus = &pas16->scsi->ncr.scsibus;
/* Bits 0-6 must absolutely be set for SCSI hard disk drivers to work. */
ret = (((pas16->scsi->ncr.dma_mode != DMA_IDLE) && (pas16->scsi->status & 0x04)) << 7) | 0x7f;
ret = (((scsi_bus->tx_mode != PIO_TX_BUS) && (pas16->scsi->status & 0x04)) << 7) | 0x7f;
}
break;
case 0x5c03:
if (pas16->has_scsi)
@@ -1183,10 +1186,11 @@ pas16_scsi_callback(void *priv)
{
pas16_t * pas16 = (pas16_t *) priv;
t128_t * dev = pas16->scsi;
scsi_bus_t * scsi_bus = &dev->ncr.scsibus;
t128_callback(pas16->scsi);
if ((dev->ncr.dma_mode != DMA_IDLE) && (dev->status & 0x04)) {
if ((scsi_bus->tx_mode != PIO_TX_BUS) && (dev->status & 0x04)) {
timer_stop(&pas16->scsi_timer);
pas16->timeout_status &= 0x7f;
}

View File

@@ -4403,7 +4403,13 @@ gd54xx_init(const device_t *info)
if ((vram == 1) || (vram >= 256 && vram <= 1024))
svga->decode_mask = gd54xx->vram_mask;
svga->read = gd54xx_read;
svga->readw = gd54xx_readw;
svga->write = gd54xx_write;
svga->writew = gd54xx_writew;
if (gd54xx->bit32) {
svga->readl = gd54xx_readl;
svga->writel = gd54xx_writel;
mem_mapping_set_handler(&svga->mapping, gd54xx_read, gd54xx_readw, gd54xx_readl,
gd54xx_write, gd54xx_writew, gd54xx_writel);
mem_mapping_add(&gd54xx->mmio_mapping, 0, 0,
@@ -4423,6 +4429,8 @@ gd54xx_init(const device_t *info)
gd5480_vgablt_write, gd5480_vgablt_writew, gd5480_vgablt_writel,
NULL, MEM_MAPPING_EXTERNAL, gd54xx);
} else {
svga->readl = NULL;
svga->writel = NULL;
mem_mapping_set_handler(&svga->mapping, gd54xx_read, gd54xx_readw, NULL,
gd54xx_write, gd54xx_writew, NULL);
mem_mapping_add(&gd54xx->mmio_mapping, 0, 0,

View File

@@ -33,9 +33,12 @@
#include <86box/rom.h>
#include <86box/device.h>
#include <86box/video.h>
#include <86box/vid_8514a.h>
#include <86box/vid_xga.h>
#include <86box/vid_svga.h>
#include <86box/vid_svga_render.h>
#include <86box/vid_ati_eeprom.h>
#include <86box/vid_ati_mach8.h>
#include <86box/plat_fallthrough.h>
#include <86box/plat_unused.h>
@@ -425,9 +428,8 @@ ht216_out(uint16_t addr, uint8_t val, void *priv)
svga->banked_mask = 0xffff;
}
if (svga->gdcaddr <= 8) {
if (svga->gdcaddr <= 8)
svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) && svga->chain4 && svga->packed_chain4;
}
break;
case 0x3D4:
@@ -625,7 +627,9 @@ ht216_remap(ht216_t *ht216)
void
ht216_recalctimings(svga_t *svga)
{
ht216_t *ht216 = (ht216_t *) svga->priv;
ht216_t *ht216 = (ht216_t *) svga->priv;
ibm8514_t *dev = (ibm8514_t *) svga->dev8514;
mach_t *mach = (mach_t *) svga->ext8514;
int high_res_256 = 0;
@@ -672,10 +676,16 @@ ht216_recalctimings(svga_t *svga)
if (!svga->scrblank && svga->attr_palette_enable) {
if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/
if (svga->seqregs[1] & 8) /*40 column*/ {
if (svga->seqregs[1] & 8) /*40 column*/
svga->render = svga_render_text_40;
} else {
else
svga->render = svga_render_text_80;
if (ibm8514_active && (svga->dev8514 != NULL)) {
if (svga->ext8514 != NULL) {
if (!(dev->accel.advfunc_cntl & 0x01) && !(mach->accel.clock_sel & 0x01)) /*FIXME: Possibly a BIOS bug within the V7 chips when it's used with a 8514/A card?*/
dev->on &= ~0x01;
}
}
} else {
if (svga->crtc[0x17] == 0xeb) {
@@ -1576,10 +1586,17 @@ ht216_init(const device_t *info, uint32_t mem_size, int has_rom)
if (has_rom == 4)
svga->ramdac = device_add(&sc11484_nors2_ramdac_device);
svga->read = ht216_read;
svga->readw = NULL;
svga->readl = NULL;
svga->write = ht216_write;
svga->writew = ht216_writew;
if ((info->flags & DEVICE_VLB) || (info->flags & DEVICE_MCA)) {
svga->writel = ht216_writel;
mem_mapping_set_handler(&svga->mapping, ht216_read, NULL, NULL, ht216_write, ht216_writew, ht216_writel);
mem_mapping_add(&ht216->linear_mapping, 0, 0, ht216_read_linear, NULL, NULL, ht216_write_linear, ht216_writew_linear, ht216_writel_linear, NULL, MEM_MAPPING_EXTERNAL, svga);
} else {
svga->writel = NULL;
mem_mapping_set_handler(&svga->mapping, ht216_read, NULL, NULL, ht216_write, ht216_writew, NULL);
mem_mapping_add(&ht216->linear_mapping, 0, 0, ht216_read_linear, NULL, NULL, ht216_write_linear, ht216_writew_linear, NULL, NULL, MEM_MAPPING_EXTERNAL, svga);
}

View File

@@ -362,11 +362,6 @@ paradise_write(uint32_t addr, uint8_t val, void *priv)
uint32_t prev_addr;
uint32_t prev_addr2;
if (!(svga->attrregs[0x10] & 0x40)) {
svga_write(addr, val, svga);
return;
}
addr = (addr & 0x7fff) + paradise->write_bank[(addr >> 15) & 3];
/*Could be done in a better way but it works.*/
@@ -400,11 +395,6 @@ paradise_writew(uint32_t addr, uint16_t val, void *priv)
uint32_t prev_addr;
uint32_t prev_addr2;
if (!(svga->attrregs[0x10] & 0x40)) {
svga_writew(addr, val, svga);
return;
}
addr = (addr & 0x7fff) + paradise->write_bank[(addr >> 15) & 3];
/*Could be done in a better way but it works.*/
@@ -438,9 +428,6 @@ paradise_read(uint32_t addr, void *priv)
uint32_t prev_addr;
uint32_t prev_addr2;
if (!(svga->attrregs[0x10] & 0x40))
return svga_read(addr, svga);
addr = (addr & 0x7fff) + paradise->read_bank[(addr >> 15) & 3];
/*Could be done in a better way but it works.*/
@@ -474,9 +461,6 @@ paradise_readw(uint32_t addr, void *priv)
uint32_t prev_addr;
uint32_t prev_addr2;
if (!(svga->attrregs[0x10] & 0x40))
return svga_readw(addr, svga);
addr = (addr & 0x7fff) + paradise->read_bank[(addr >> 15) & 3];
/*Could be done in a better way but it works.*/
@@ -550,6 +534,12 @@ paradise_init(const device_t *info, uint32_t memory)
break;
}
svga->read = paradise_read;
svga->readw = paradise_readw;
svga->readl = NULL;
svga->write = paradise_write;
svga->writew = paradise_writew;
svga->writel = NULL;
mem_mapping_set_handler(&svga->mapping, paradise_read, paradise_readw, NULL, paradise_write, paradise_writew, NULL);
mem_mapping_set_p(&svga->mapping, paradise);

View File

@@ -984,7 +984,7 @@ svga_recalctimings(svga_t *svga)
svga_log("IBM 8514/A poll.\n");
timer_set_callback(&svga->timer, ibm8514_poll);
} else {
svga_log("SVGA Poll.\n");
svga_log("SVGA poll enabled.\n");
timer_set_callback(&svga->timer, svga_poll);
}
}
@@ -1081,6 +1081,7 @@ svga_poll(void *priv)
}
}
svga_log("SVGA Poll.\n");
if (!svga->linepos) {
if (svga->displine == ((svga->hwcursor_latch.y < 0) ? 0 : svga->hwcursor_latch.y) && svga->hwcursor_latch.ena) {
svga->hwcursor_on = svga->hwcursor_latch.cur_ysize - svga->hwcursor_latch.yoff;
@@ -1406,16 +1407,34 @@ svga_init(const device_t *info, svga_t *svga, void *priv, int memsize,
svga->ksc5601_english_font_type = 0;
if ((info->flags & DEVICE_PCI) || (info->flags & DEVICE_VLB) || (info->flags & DEVICE_MCA)) {
svga->read = svga_read;
svga->readw = svga_readw;
svga->readl = svga_readl;
svga->write = svga_write;
svga->writew = svga_writew;
svga->writel = svga_writel;
mem_mapping_add(&svga->mapping, 0xa0000, 0x20000,
svga_read, svga_readw, svga_readl,
svga_write, svga_writew, svga_writel,
NULL, MEM_MAPPING_EXTERNAL, svga);
} else if ((info->flags & DEVICE_ISA) && (info->flags & DEVICE_AT)) {
svga->read = svga_read;
svga->readw = svga_readw;
svga->readl = NULL;
svga->write = svga_write;
svga->writew = svga_writew;
svga->writel = NULL;
mem_mapping_add(&svga->mapping, 0xa0000, 0x20000,
svga_read, svga_readw, NULL,
svga_write, svga_writew, NULL,
NULL, MEM_MAPPING_EXTERNAL, svga);
} else {
svga->read = svga_read;
svga->readw = NULL;
svga->readl = NULL;
svga->write = svga_write;
svga->writew = NULL;
svga->writel = NULL;
mem_mapping_add(&svga->mapping, 0xa0000, 0x20000,
svga_read, NULL, NULL,
svga_write, NULL, NULL,

View File

@@ -188,7 +188,7 @@ xga_updatemapping(svga_t *svga)
mem_mapping_disable(&xga->linear_mapping);
break;
default:
xga_log("XGA: Extended Graphics mode.\n");
xga_log("XGA: Extended Graphics mode, ap=%d.\n", xga->aperture_cntl);
switch (xga->aperture_cntl) {
case 0:
xga_log("XGA: No 64KB aperture: 1MB=%x, 4MB=%x, SVGA Mapping Base=%x.\n", xga->base_addr_1mb, xga->linear_base, svga->mapping.base);
@@ -201,7 +201,7 @@ xga_updatemapping(svga_t *svga)
} else
mem_mapping_disable(&xga->linear_mapping);
mem_mapping_set_handler(&svga->mapping, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel);
mem_mapping_set_handler(&svga->mapping, svga->read, svga->readw, svga->readl, svga->write, svga->writew, svga->writel);
switch (svga->gdcreg[6] & 0xc) {
case 0x0: /*128k at A0000*/
mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000);
@@ -439,9 +439,9 @@ xga_ext_out_reg(xga_t *xga, svga_t *svga, uint8_t idx, uint8_t val)
break;
case 0x51:
xga_log("Reg51 write = %02x.\n", val);
xga_log("Reg51 write=%02x.\n", val & 0x07);
xga->disp_cntl_2 = val;
xga->on = ((val & 7) >= 2);
xga->on = ((val & 0x07) >= 0x02);
svga_recalctimings(svga);
break;
@@ -535,9 +535,11 @@ xga_ext_outb(uint16_t addr, uint8_t val, void *priv)
xga_log("[%04X:%08X]: EXT OUTB = %02x, val = %02x\n", CS, cpu_state.pc, addr, val);
switch (addr & 0x0f) {
case 0:
xga_log("[%04X:%08X]: EXT OUTB = %02x, val = %02x\n", CS, cpu_state.pc, addr, val);
xga->op_mode = val;
break;
case 1:
xga_log("[%04X:%08X]: EXT OUTB = %02x, val = %02x\n", CS, cpu_state.pc, addr, val);
xga->aperture_cntl = val & 3;
xga_updatemapping(svga);
break;
@@ -579,6 +581,7 @@ xga_ext_outb(uint16_t addr, uint8_t val, void *priv)
break;
default:
xga_log("[%04X:%08X]: EXT OUTB = %02x, val = %02x\n", CS, cpu_state.pc, addr, val);
break;
}
}
@@ -807,6 +810,7 @@ xga_ext_inb(uint16_t addr, void *priv)
break;
default:
xga_log("[%04X:%08X]: EXT INB = %02x, ret = %02x.\n\n", CS, cpu_state.pc, addr, ret);
break;
}
@@ -933,6 +937,32 @@ xga_accel_read_pattern_map_pixel(svga_t *svga, int x, int y, uint32_t base, int
return px;
}
static uint32_t
xga_accel_read_area_map_pixel(svga_t *svga, int x, int y, uint32_t base, int width)
{
const xga_t *xga = (xga_t *) svga->xga;
uint32_t addr = base;
int bits;
uint8_t byte;
uint8_t px;
int skip = 0;
if ((addr < xga->linear_base) || (addr > (xga->linear_base + 0xfffff)))
skip = 1;
addr += (y * (width >> 3));
addr += (x >> 3);
if (!skip) {
READ(addr, byte);
} else
byte = mem_readb_phys(addr);
bits = 7 - (x & 7);
px = (byte >> bits) & 1;
return px;
}
static uint32_t
xga_accel_read_map_pixel(svga_t *svga, int x, int y, int map, uint32_t base, int width)
{
@@ -971,6 +1001,7 @@ xga_accel_read_map_pixel(svga_t *svga, int x, int y, int map, uint32_t base, int
} else
byte = mem_readb_phys(addr);
xga_log("4bpp read: OPMODEBIG=%02x, SRC Map=%02x, DST Map=%02x, AccessMode=%02x, SRCPIX=%02x, DSTPIX=%02x, wordpix=%04x, x=%d, y=%d, skip=%d.\n", xga->op_mode & 0x08, (xga->accel.px_map_format[xga->accel.src_map] & 0x0f), (xga->accel.px_map_format[xga->accel.dst_map] & 0x0f), xga->access_mode & 0x0f, xga->accel.src_map, xga->accel.dst_map, byte, x, y, skip);
return byte;
case 3: /*8-bit*/
addr += (y * width);
@@ -984,19 +1015,15 @@ xga_accel_read_map_pixel(svga_t *svga, int x, int y, int map, uint32_t base, int
case 4: /*16-bit*/
addr += (y * (width << 1));
addr += (x << 1);
if (xga->access_mode & 0x08) {
if (!skip) {
READW(addr, byte);
} else
byte = mem_readw_phys(addr);
} else {
if (!skip) {
READW(addr, byte);
} else {
byte = mem_readw_phys(addr);
if ((xga->access_mode & 0x07) == 0x04)
byte = ((byte & 0xff00) >> 8) | ((byte & 0x00ff) << 8);
}
if (!skip) {
READW(addr, byte);
} else {
byte = mem_readw_phys(addr);
if ((xga->access_mode & 0x07) == 0x04)
byte = ((byte & 0xff00) >> 8) | ((byte & 0x00ff) << 8);
else if (xga->access_mode & 0x08)
byte = ((byte & 0xff00) >> 8) | ((byte & 0x00ff) << 8);
}
return byte;
@@ -1081,17 +1108,14 @@ xga_accel_write_map_pixel(svga_t *svga, int x, int y, int map, uint32_t base, ui
case 4: /*16-bit*/
addr += (y * width << 1);
addr += (x << 1);
if (xga->access_mode & 0x08) {
if (!skip) {
WRITEW(addr, pixel);
}
if (!skip) {
WRITEW(addr, pixel);
} else {
if (!skip) {
WRITEW(addr, pixel);
} else {
if ((xga->access_mode & 0x07) == 0x04)
pixel = ((pixel & 0xff00) >> 8) | ((pixel & 0x00ff) << 8);
}
if ((xga->access_mode & 0x07) == 0x04)
pixel = ((pixel & 0xff00) >> 8) | ((pixel & 0x00ff) << 8);
else if (xga->access_mode & 0x08)
pixel = ((pixel & 0xff00) >> 8) | ((pixel & 0x00ff) << 8);
}
mem_writew_phys(addr, pixel);
break;
@@ -1237,12 +1261,11 @@ xga_line_draw_write(svga_t *svga)
uint32_t srcbase = xga->accel.px_map_base[xga->accel.src_map];
int y = xga->accel.blt_width;
int x = 0;
int draw_pixel = 0;
int16_t dx;
int16_t dy;
int16_t cx;
int16_t cy;
int err = xga->accel.bres_err_term;
int draw_pixel = 0;
cx = xga->accel.src_map_x & 0xfff;
cy = xga->accel.src_map_y & 0xfff;
@@ -1256,38 +1279,57 @@ xga_line_draw_write(svga_t *svga)
dy |= ~0x17ff;
if ((xga->accel.command & 0x30) == 0x30)
xga_log("Line Draw Write: BLTWIDTH=%d, BLTHEIGHT=%d, FRGDCOLOR=%04x, XDIR=%i, YDIR=%i, steep=%s, ERR=%04x.\n", xga->accel.blt_width, xga->accel.blt_height, xga->accel.frgd_color & 0xffff, xdir, ydir, (xga->accel.octant & 0x01) ? "0" : "1", err);
xga_log("Line Draw Write Fill: DX=%d, DY=%d, BLTWIDTH=%d, BLTHEIGHT=%d, FRGDCOLOR=%04x, negative XDIR=%i, negative YDIR=%i, YMAJOR=%d, ERR=%d, BRESK2=%d, BRESK1=%d, mask=%02x.\n", dx, dy, xga->accel.blt_width, xga->accel.blt_height, xga->accel.frgd_color & 0xffff, (xga->accel.octant & 0x04), (xga->accel.octant & 0x02), (xga->accel.octant & 0x01), xga->accel.bres_err_term, xga->accel.bres_k2, xga->accel.bres_k1, xga->accel.command & 0xc0);
if (xga->accel.pat_src == 8) {
if ((xga->accel.command & 0x30) == 0x30) {
while (y >= 0) {
draw_pixel = 0;
if (xga->accel.octant & 0x01) {
if (xga->accel.octant & 0x02) { /*Bottom-to-Top*/
if (xga->accel.octant & 0x01) { /*Y Major*/
if (xga->accel.octant & 0x02) { /*Bottom to Top*/
if (x)
draw_pixel = 1;
} else { /*Top-to-Bottom*/
} else { /*Top to Bottom*/
if (y)
draw_pixel = 1;
}
} else if (!(xga->accel.octant & 0x04) && (err < (xga->accel.bres_k2 + xga->accel.bres_k1))) /*X+*/
draw_pixel = 1;
else if ((xga->accel.octant & 0x04) && (err >= 0)) /*X-*/
draw_pixel = 1;
if (xga->accel.command & 0xc0) {
if ((dx >= xga->accel.mask_map_origin_x_off) && (dx <= ((xga->accel.px_map_width[0] & 0xfff) + xga->accel.mask_map_origin_x_off)) && (dy >= xga->accel.mask_map_origin_y_off) && (dy <= ((xga->accel.px_map_height[0] & 0xfff) + xga->accel.mask_map_origin_y_off))) {
if (draw_pixel) {
src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, cx, cy, xga->accel.src_map, srcbase, xga->accel.px_map_width[xga->accel.src_map] + 1) : xga->accel.frgd_color;
dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, xga->accel.px_map_width[xga->accel.dst_map] + 1);
if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) {
ROP(1, dest_dat, src_dat);
xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1);
} else { /*X Major*/
if (xga->accel.octant & 0x04) { /*Right to Left*/
if (xga->accel.bres_err_term >= 0) {
if (xga->accel.octant & 0x02) { /*Bottom to Top*/
if (x)
draw_pixel = 1;
} else { /*Top to Bottom*/
if (y)
draw_pixel = 1;
}
}
} else { /*Left to Right*/
if (xga->accel.bres_err_term < (xga->accel.bres_k1 + xga->accel.bres_k2)) {
if (xga->accel.octant & 0x02) { /*Bottom to Top*/
if (x)
draw_pixel = 1;
} else { /*Top to Bottom*/
if (y)
draw_pixel = 1;
}
}
}
}
xga_log("Draw Boundary: DX=%d, DY=%d, wrt_pix=%d, ymajor=%d, bottomtotop=%x, len=%d, err=%d, frgdmix=%02x.\n", dx, dy, draw_pixel, xga->accel.octant & 0x01, xga->accel.octant & 0x02, y, xga->accel.bres_err_term, xga->accel.frgd_mix & 0x1f);
if (xga->accel.command & 0xc0) {
if ((dx >= xga->accel.mask_map_origin_x_off) && (dx <= ((xga->accel.px_map_width[0] & 0xfff) + xga->accel.mask_map_origin_x_off)) && (dy >= xga->accel.mask_map_origin_y_off) && (dy <= ((xga->accel.px_map_height[0] & 0xfff) + xga->accel.mask_map_origin_y_off)) && draw_pixel) {
src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, cx, cy, xga->accel.src_map, srcbase, xga->accel.px_map_width[xga->accel.src_map] + 1) : xga->accel.frgd_color;
dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, xga->accel.px_map_width[xga->accel.dst_map] + 1);
if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) {
old_dest_dat = dest_dat;
ROP(1, dest_dat, src_dat);
dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask);
xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1);
}
}
} else {
if (draw_pixel) {
@@ -1295,7 +1337,9 @@ xga_line_draw_write(svga_t *svga)
dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, xga->accel.px_map_width[xga->accel.dst_map] + 1);
if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) {
old_dest_dat = dest_dat;
ROP(1, dest_dat, src_dat);
dest_dat = (dest_dat & plane_mask) | (old_dest_dat & ~plane_mask);
xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, xga->accel.px_map_width[xga->accel.dst_map] + 1);
}
}
@@ -1310,28 +1354,28 @@ xga_line_draw_write(svga_t *svga)
else
dy++;
if (err >= 0) {
err += xga->accel.bres_k2;
if (xga->accel.bres_err_term >= 0) {
xga->accel.bres_err_term += xga->accel.bres_k2;
if (xga->accel.octant & 0x04)
dx--;
else
dx++;
} else
err += xga->accel.bres_k1;
xga->accel.bres_err_term += xga->accel.bres_k1;
} else {
if (xga->accel.octant & 0x04)
dx--;
else
dx++;
if (err >= 0) {
err += xga->accel.bres_k2;
if (xga->accel.bres_err_term >= 0) {
xga->accel.bres_err_term += xga->accel.bres_k2;
if (xga->accel.octant & 0x02)
dy--;
else
dy++;
} else
err += xga->accel.bres_k1;
xga->accel.bres_err_term += xga->accel.bres_k1;
}
x++;
y--;
@@ -1384,28 +1428,28 @@ xga_line_draw_write(svga_t *svga)
else
dy++;
if (err >= 0) {
err += xga->accel.bres_k2;
if (xga->accel.bres_err_term >= 0) {
xga->accel.bres_err_term += xga->accel.bres_k2;
if (xga->accel.octant & 0x04)
dx--;
else
dx++;
} else
err += xga->accel.bres_k1;
xga->accel.bres_err_term += xga->accel.bres_k1;
} else {
if (xga->accel.octant & 0x04)
dx--;
else
dx++;
if (err >= 0) {
err += xga->accel.bres_k2;
if (xga->accel.bres_err_term >= 0) {
xga->accel.bres_err_term += xga->accel.bres_k2;
if (xga->accel.octant & 0x02)
dy--;
else
dy++;
} else
err += xga->accel.bres_k1;
xga->accel.bres_err_term += xga->accel.bres_k1;
}
y--;
x++;
@@ -1454,20 +1498,21 @@ xga_bitblt(svga_t *svga)
if (xga->accel.dst_map_y >= 0x1800)
dy |= ~0x17ff;
xga_log("D(%d,%d), SWH(%d,%d), BLT(%d,%d), dstwidth=%d.\n", dx, dy, xga->accel.x, xga->accel.y, srcwidth, srcheight, dstwidth);
xga_log("D(%d,%d), SWH(%d,%d), BLT(%d,%d), dstwidth=%d, frgdcol=%04x, bkgdcol=%04x.\n", dx, dy, xga->accel.x, xga->accel.y, srcwidth, srcheight, dstwidth, frgdcol, bkgdcol);
xga->accel.pattern = 0;
xga->accel.filling = 0;
xga_log("XGA bitblt linear endian reverse=%d, access_mode=%x, octanty=%d, src command = %08x, "
xga_log("XGA bitblt access_mode=%x, octanty=%d, src command=%08x, "
"pxsrcmap=%x, pxpatmap=%x, pxdstmap=%x, srcmap=%d, patmap=%d, dstmap=%d, "
"usesrcvramfr=%d, usevrambk=%d.\n",
xga->linear_endian_reverse, xga->access_mode & 0x0f, ydir, xga->accel.command,
"usesrcvramfr=%d, usevrambk=%d, frgdcol=%04x, bkgdcol=%04x, bgmix=%02x, fgmix=%02x.\n",
xga->access_mode & 0x0f, ydir, xga->accel.command,
xga->accel.px_map_format[xga->accel.src_map] & 0x0f,
xga->accel.px_map_format[xga->accel.pat_src] & 0x0f,
xga->accel.px_map_format[xga->accel.dst_map] & 0x0f,
xga->accel.src_map, xga->accel.pat_src,
xga->accel.dst_map, ((xga->accel.command >> 28) & 3), ((xga->accel.command >> 30) & 3));
xga->accel.dst_map, ((xga->accel.command >> 28) & 3), ((xga->accel.command >> 30) & 3),
frgdcol, bkgdcol, xga->accel.bkgd_mix & 0x1f, xga->accel.frgd_mix & 0x1f);
if (xga->accel.pat_src == 8) {
if (srcheight == 7)
@@ -1593,17 +1638,19 @@ xga_bitblt(svga_t *svga)
xga->accel.px_map_width[2], xga->accel.px_map_width[3], bkgdcol);
xga_log("Pattern Enabled?=%d, patwidth=%d, patheight=%d, P(%d,%d).\n", xga->accel.pattern, patwidth, patheight, xga->accel.px, xga->accel.py);
if ((((xga->accel.command >> 24) & 0x0f) == 0x0a) && ((xga->accel.bkgd_mix & 0x1f) == 5)) {
while (xga->accel.y >= 0) {
mix = xga_accel_read_pattern_map_pixel(svga, xga->accel.px, xga->accel.py, patbase, patwidth + 1);
if (mix)
xga->accel.filling = !xga->accel.filling;
if (((xga->accel.command >> 24) & 0x0f) == 0x0a) {
if ((xga->accel.bkgd_mix & 0x1f) == 0x05) {
while (xga->accel.y >= 0) {
mix = xga_accel_read_area_map_pixel(svga, xga->accel.px, xga->accel.py, patbase, patwidth + 1);
if (mix)
xga->accel.filling ^= 1;
if (xga->accel.command & 0xc0) {
if ((dx >= xga->accel.mask_map_origin_x_off) && (dx <= ((xga->accel.px_map_width[0] & 0xfff) + xga->accel.mask_map_origin_x_off)) && (dy >= xga->accel.mask_map_origin_y_off) && (dy <= ((xga->accel.px_map_height[0] & 0xfff) + xga->accel.mask_map_origin_y_off))) {
src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1) : frgdcol;
if (xga->accel.filling) {
dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, 1024);
xga_log("Area Fill Command: dx=%d, dy=%d, mix=%x, filling=%x.\n", dx, dy, mix, xga->accel.filling);
if (xga->accel.command & 0xc0) {
if ((dx >= xga->accel.mask_map_origin_x_off) && (dx <= ((xga->accel.px_map_width[0] & 0xfff) + xga->accel.mask_map_origin_x_off)) && (dy >= xga->accel.mask_map_origin_y_off) && (dy <= ((xga->accel.px_map_height[0] & 0xfff) + xga->accel.mask_map_origin_y_off)) && xga->accel.filling) {
src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1) : frgdcol;
dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dstwidth + 1);
if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) {
old_dest_dat = dest_dat;
ROP(1, dest_dat, src_dat);
@@ -1612,11 +1659,9 @@ xga_bitblt(svga_t *svga)
xga_accel_write_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dest_dat, dstwidth + 1);
}
}
}
} else {
if ((dx >= 0) && (dx <= dstwidth) && (dy >= 0) && (dy <= dstheight)) {
src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1) : frgdcol;
if (xga->accel.filling) {
} else {
if ((dx >= 0) && (dx <= dstwidth) && (dy >= 0) && (dy <= dstheight) && xga->accel.filling) {
src_dat = (((xga->accel.command >> 28) & 3) == 2) ? xga_accel_read_map_pixel(svga, xga->accel.sx, xga->accel.sy, xga->accel.src_map, srcbase, srcwidth + 1) : frgdcol;
dest_dat = xga_accel_read_map_pixel(svga, dx, dy, xga->accel.dst_map, dstbase, dstwidth + 1);
if ((xga->accel.cc_cond == 4) || ((xga->accel.cc_cond == 1) && (dest_dat > color_cmp)) || ((xga->accel.cc_cond == 2) && (dest_dat == color_cmp)) || ((xga->accel.cc_cond == 3) && (dest_dat < color_cmp)) || ((xga->accel.cc_cond == 5) && (dest_dat >= color_cmp)) || ((xga->accel.cc_cond == 6) && (dest_dat != color_cmp)) || ((xga->accel.cc_cond == 7) && (dest_dat <= color_cmp))) {
old_dest_dat = dest_dat;
@@ -1627,32 +1672,35 @@ xga_bitblt(svga_t *svga)
}
}
}
}
xga->accel.sx = ((xga->accel.sx + xdir) & srcwidth) | (xga->accel.sx & ~srcwidth);
xga->accel.px++;
xga->accel.sx = ((xga->accel.sx + xdir) & srcwidth) | (xga->accel.sx & ~srcwidth);
xga->accel.px++;
dx++;
xga->accel.x--;
if (xga->accel.x < 0) {
xga->accel.y--;
xga->accel.x = xga->accel.blt_width & 0xfff;
dx++;
xga->accel.x--;
if (xga->accel.x < 0) {
xga->accel.y--;
xga->accel.x = xga->accel.blt_width & 0xfff;
dx = xga->accel.dst_map_x;
if (xga->accel.dst_map_x >= 0x1800)
dx |= ~0x17ff;
dx = xga->accel.dst_map_x;
if (xga->accel.dst_map_x >= 0x1800)
dx |= ~0x17ff;
xga->accel.sx = xga->accel.src_map_x & 0xfff;
xga->accel.px = xga->accel.pat_map_x & 0xfff;
xga->accel.sx = xga->accel.src_map_x & 0xfff;
xga->accel.px = xga->accel.pat_map_x & 0xfff;
xga->accel.sy = ((xga->accel.sy + ydir) & srcheight) | (xga->accel.sy & ~srcheight);
xga->accel.py++;
xga->accel.sy = ((xga->accel.sy + ydir) & srcheight) | (xga->accel.sy & ~srcheight);
xga->accel.py++;
dy++;
xga->accel.filling = 0;
dy++;
xga->accel.filling = 0;
if (xga->accel.y < 0)
return;
if (xga->accel.y < 0) {
xga->accel.dst_map_x = dx;
xga->accel.dst_map_y = dy;
return;
}
}
}
}
} else {
@@ -2171,7 +2219,6 @@ exec_command:
xga->accel.src_map = ((xga->accel.command >> 20) & 0x0f);
xga_log("PATMAP=%x, DSTMAP=%x, SRCMAP=%x.\n", xga->accel.px_map_format[xga->accel.pat_src], xga->accel.px_map_format[xga->accel.dst_map], xga->accel.px_map_format[xga->accel.src_map]);
#ifdef ENABLE_XGA_LOG
if (xga->accel.pat_src)
xga_log("[%04X:%08X]: Accel Command = %02x, full = %08x, patwidth = %d, "
"dstwidth = %d, srcwidth = %d, patheight = %d, dstheight = %d, "
@@ -2196,7 +2243,7 @@ exec_command:
xga->accel.px_map_format[xga->accel.dst_map] & 0x0f,
xga->accel.px_map_format[xga->accel.src_map] & 0x0f,
xga->accel.plane_mask);
#endif
switch ((xga->accel.command >> 24) & 0x0f) {
case 2: /*Short Stroke Vectors Read */
xga_log("Short Stroke Vectors Read.\n");
@@ -2670,7 +2717,7 @@ xga_write_test(uint32_t addr, uint8_t val, void *priv)
xga->vram[addr & xga->vram_mask] = val;
xga_log("XGA Linear endian reverse write, val = %02x, addr = %05x, banked mask = %04x, a5test=%d.\n", val, addr, svga->banked_mask, xga->a5_test);
}
} else if (xga->aperture_cntl)
} else if (xga->aperture_cntl || (!xga->aperture_cntl && (svga->mapping.base == 0xa0000)))
xga->on = 0;
}
}
@@ -2777,9 +2824,8 @@ xga_read_test(uint32_t addr, void *priv)
addr += xga->read_bank;
return xga->vram[addr & xga->vram_mask];
}
} else if (xga->aperture_cntl) {
} else if (xga->aperture_cntl || (!xga->aperture_cntl && (svga->mapping.base == 0xa0000)))
xga->on = 0;
}
}
return ret;
}
@@ -2874,7 +2920,7 @@ xga_write_linear(uint32_t addr, uint8_t val, void *priv)
svga_t *svga = (svga_t *) priv;
xga_t *xga = (xga_t *) svga->xga;
xga_log("WrtieLL XGA=%d.\n", xga->on);
xga_log("WriteLL XGA=%d.\n", xga->on);
if (!xga->on) {
svga_write_linear(addr, val, svga);
return;
@@ -2889,13 +2935,6 @@ xga_write_linear(uint32_t addr, uint8_t val, void *priv)
cycles -= svga->monitor->mon_video_timing_write_b;
if (!(xga->access_mode & 0x08)) {
if ((xga->access_mode & 0x07) == 0x04) {
if ((xga->accel.px_map_format[xga->accel.dst_map] & 0x07) == 0x04)
addr ^= 1;
}
}
xga->changedvram[(addr & xga->vram_mask) >> 12] = svga->monitor->mon_changeframecount;
xga->vram[addr & xga->vram_mask] = val;
}
@@ -2951,14 +2990,9 @@ xga_read_linear(uint32_t addr, void *priv)
cycles -= svga->monitor->mon_video_timing_read_b;
if (!(xga->access_mode & 0x08)) {
if ((xga->access_mode & 0x07) == 0x04) {
if ((xga->accel.px_map_format[xga->accel.dst_map] & 0x07) == 0x04)
addr ^= 1;
}
}
ret = xga->vram[addr & xga->vram_mask];
return xga->vram[addr & xga->vram_mask];
return ret;
}
static uint16_t
@@ -3234,7 +3268,7 @@ xga_mca_reset(void *priv)
svga_t *svga = (svga_t *) priv;
xga_log("MCA Reset.\n");
mem_mapping_set_handler(&svga->mapping, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel);
mem_mapping_set_handler(&svga->mapping, svga->read, svga->readw, svga->readl, svga->write, svga->writew, svga->writel);
xga_mca_write(0x102, 0, svga);
}
@@ -3250,7 +3284,7 @@ xga_reset(void *priv)
xga->on = 0;
xga->a5_test = 0;
mem_mapping_set_handler(&svga->mapping, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel);
mem_mapping_set_handler(&svga->mapping, svga->read, svga->readw, svga->readl, svga->write, svga->writew, svga->writel);
}
static uint8_t