|
|
|
@@ -47,6 +47,7 @@
|
|
|
|
|
#define RT1000B_810R_ROM "roms/scsi/ncr5380/Rancho_RT1000_RTBios_version_8.10R.bin"
|
|
|
|
|
#define RT1000B_820R_ROM "roms/scsi/ncr5380/RTBIOS82.rom"
|
|
|
|
|
#define T130B_ROM "roms/scsi/ncr5380/trantor_t130b_bios_v2.14.bin"
|
|
|
|
|
#define T128_ROM "roms/scsi/ncr5380/trantor_t128_bios_v1.12.bin"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define NCR_CURDATA 0 /* current SCSI data (read only) */
|
|
|
|
@@ -108,8 +109,20 @@ typedef struct {
|
|
|
|
|
int command_pos, data_pos;
|
|
|
|
|
} ncr_t;
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
uint8_t ctrl;
|
|
|
|
|
uint8_t status;
|
|
|
|
|
uint8_t buffer[512];
|
|
|
|
|
uint8_t ext_ram[0x600];
|
|
|
|
|
uint8_t block_count;
|
|
|
|
|
|
|
|
|
|
int block_loaded, xfer_complete;
|
|
|
|
|
int pos, host_pos;
|
|
|
|
|
} t128_t;
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
ncr_t ncr;
|
|
|
|
|
t128_t t128;
|
|
|
|
|
|
|
|
|
|
const char *name;
|
|
|
|
|
|
|
|
|
@@ -122,7 +135,7 @@ typedef struct {
|
|
|
|
|
int8_t irq;
|
|
|
|
|
int8_t type;
|
|
|
|
|
int8_t bios_ver;
|
|
|
|
|
uint8_t block_count, block_count_num;
|
|
|
|
|
uint8_t block_count;
|
|
|
|
|
uint8_t status_ctrl;
|
|
|
|
|
uint8_t bus, pad;
|
|
|
|
|
|
|
|
|
@@ -247,15 +260,20 @@ ncr_timer_on(ncr5380_t *ncr_dev, ncr_t *ncr, int callback)
|
|
|
|
|
double p = ncr_dev->period;
|
|
|
|
|
|
|
|
|
|
if (ncr->data_wait & 2)
|
|
|
|
|
ncr->data_wait &= ~2;
|
|
|
|
|
ncr->data_wait &= ~2;
|
|
|
|
|
|
|
|
|
|
if (callback) {
|
|
|
|
|
if (ncr_dev->type == 3)
|
|
|
|
|
p *= 512.0;
|
|
|
|
|
else
|
|
|
|
|
p *= 128.0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (callback)
|
|
|
|
|
p *= 128.0;
|
|
|
|
|
|
|
|
|
|
p += 1.0;
|
|
|
|
|
|
|
|
|
|
ncr_log("P = %lf\n", p);
|
|
|
|
|
timer_on_auto(&ncr_dev->timer, p);
|
|
|
|
|
p += 1.0;
|
|
|
|
|
|
|
|
|
|
if (ncr_dev->type == 3 && ncr->dma_mode == DMA_SEND)
|
|
|
|
|
ncr_log("P = %lf, command = %02x, callback = %i, period = %lf, t128 pos = %i\n", p, ncr->command[0], callback, ncr_dev->period, ncr_dev->t128.host_pos);
|
|
|
|
|
timer_on_auto(&ncr_dev->timer, p);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -451,8 +469,9 @@ ncr_bus_update(void *priv, int bus)
|
|
|
|
|
p = scsi_device_get_callback(dev);
|
|
|
|
|
if (p <= 0.0) {
|
|
|
|
|
ncr_dev->period = 0.2;
|
|
|
|
|
} else
|
|
|
|
|
} else {
|
|
|
|
|
ncr_dev->period = p / ((double) dev->buffer_length);
|
|
|
|
|
}
|
|
|
|
|
ncr->data_wait |= 2;
|
|
|
|
|
ncr_log("SCSI ID %i: command 0x%02x for p = %lf, update = %lf, len = %i\n", ncr->target_id, ncr->command[0], p, ncr_dev->period, dev->buffer_length);
|
|
|
|
|
}
|
|
|
|
@@ -563,13 +582,14 @@ ncr_write(uint16_t port, uint8_t val, void *priv)
|
|
|
|
|
{
|
|
|
|
|
ncr5380_t *ncr_dev = (ncr5380_t *)priv;
|
|
|
|
|
ncr_t *ncr = &ncr_dev->ncr;
|
|
|
|
|
scsi_device_t *dev = &scsi_devices[ncr_dev->bus][ncr->target_id];
|
|
|
|
|
int bus_host = 0;
|
|
|
|
|
|
|
|
|
|
ncr_log("NCR5380 write(%04x,%02x)\n",port & 7,val);
|
|
|
|
|
ncr_log("NCR5380 write(%04x,%02x)\n",port & 7,val);
|
|
|
|
|
|
|
|
|
|
switch (port & 7) {
|
|
|
|
|
case 0: /* Output data register */
|
|
|
|
|
ncr_log("Write: Output data register\n");
|
|
|
|
|
ncr_log("Write: Output data register, val = %02x\n", val);
|
|
|
|
|
ncr->output_data = val;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
@@ -591,18 +611,34 @@ ncr_write(uint16_t port, uint8_t val, void *priv)
|
|
|
|
|
|
|
|
|
|
ncr->mode = val;
|
|
|
|
|
|
|
|
|
|
/*Don't stop the timer until it finishes the transfer*/
|
|
|
|
|
if (ncr_dev->block_count_loaded && (ncr->mode & MODE_DMA) && !timer_is_enabled(&ncr_dev->timer)) {
|
|
|
|
|
ncr_log("Continuing DMA mode\n");
|
|
|
|
|
ncr_timer_on(ncr_dev, ncr, 0);
|
|
|
|
|
}
|
|
|
|
|
if (ncr_dev->type == 3) {
|
|
|
|
|
/*Don't stop the timer until it finishes the transfer*/
|
|
|
|
|
if (ncr_dev->t128.block_loaded && (ncr->mode & MODE_DMA)) {
|
|
|
|
|
ncr_log("Continuing DMA mode\n");
|
|
|
|
|
ncr_timer_on(ncr_dev, ncr, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*When a pseudo-DMA transfer has completed (Send or Initiator Receive), mark it as complete and idle the status*/
|
|
|
|
|
if (!ncr_dev->t128.block_loaded && !(ncr->mode & MODE_DMA)) {
|
|
|
|
|
ncr_log("No DMA mode\n");
|
|
|
|
|
ncr->tcr &= ~TCR_LAST_BYTE_SENT;
|
|
|
|
|
ncr->isr &= ~STATUS_END_OF_DMA;
|
|
|
|
|
ncr->dma_mode = DMA_IDLE;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
/*Don't stop the timer until it finishes the transfer*/
|
|
|
|
|
if (ncr_dev->block_count_loaded && (ncr->mode & MODE_DMA) && !timer_is_enabled(&ncr_dev->timer)) {
|
|
|
|
|
ncr_log("Continuing DMA mode\n");
|
|
|
|
|
ncr_timer_on(ncr_dev, ncr, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*When a pseudo-DMA transfer has completed (Send or Initiator Receive), mark it as complete and idle the status*/
|
|
|
|
|
if (!ncr_dev->block_count_loaded && !(ncr->mode & MODE_DMA)) {
|
|
|
|
|
ncr_log("No DMA mode\n");
|
|
|
|
|
ncr->tcr &= ~TCR_LAST_BYTE_SENT;
|
|
|
|
|
ncr->isr &= ~STATUS_END_OF_DMA;
|
|
|
|
|
ncr->dma_mode = DMA_IDLE;
|
|
|
|
|
/*When a pseudo-DMA transfer has completed (Send or Initiator Receive), mark it as complete and idle the status*/
|
|
|
|
|
if (!ncr_dev->block_count_loaded && !(ncr->mode & MODE_DMA)) {
|
|
|
|
|
ncr_log("No DMA mode\n");
|
|
|
|
|
ncr->tcr &= ~TCR_LAST_BYTE_SENT;
|
|
|
|
|
ncr->isr &= ~STATUS_END_OF_DMA;
|
|
|
|
|
ncr->dma_mode = DMA_IDLE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
@@ -619,8 +655,18 @@ ncr_write(uint16_t port, uint8_t val, void *priv)
|
|
|
|
|
ncr_log("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;
|
|
|
|
|
if ((ncr->mode & MODE_DMA) && !timer_is_enabled(&ncr_dev->timer)) {
|
|
|
|
|
ncr_timer_on(ncr_dev, ncr, 0);
|
|
|
|
|
if (ncr_dev->type == 3) {
|
|
|
|
|
ncr_log("DMA send timer start, enabled? = %i\n", timer_is_enabled(&ncr_dev->timer));
|
|
|
|
|
ncr_dev->t128.block_count = dev->buffer_length >> 9;
|
|
|
|
|
ncr_dev->t128.block_loaded = 1;
|
|
|
|
|
|
|
|
|
|
ncr_dev->t128.host_pos = 0;
|
|
|
|
|
ncr_dev->t128.status |= 0x04;
|
|
|
|
|
} else {
|
|
|
|
|
if ((ncr->mode & MODE_DMA) && !timer_is_enabled(&ncr_dev->timer)) {
|
|
|
|
|
ncr_log("DMA send timer on\n");
|
|
|
|
|
ncr_timer_on(ncr_dev, ncr, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
@@ -628,8 +674,19 @@ ncr_write(uint16_t port, uint8_t val, void *priv)
|
|
|
|
|
ncr_log("Write: start DMA initiator receive register, dma? = %02x\n", ncr->mode & MODE_DMA);
|
|
|
|
|
/*a Read 6/10 has occurred, start the timer when the block count is loaded*/
|
|
|
|
|
ncr->dma_mode = DMA_INITIATOR_RECEIVE;
|
|
|
|
|
if ((ncr->mode & MODE_DMA) && !timer_is_enabled(&ncr_dev->timer)) {
|
|
|
|
|
ncr_timer_on(ncr_dev, ncr, 0);
|
|
|
|
|
if (ncr_dev->type == 3) {
|
|
|
|
|
ncr_log("DMA receive timer start, enabled? = %i\n", timer_is_enabled(&ncr_dev->timer));
|
|
|
|
|
ncr_dev->t128.block_count = dev->buffer_length >> 9;
|
|
|
|
|
ncr_dev->t128.block_loaded = 1;
|
|
|
|
|
|
|
|
|
|
ncr_dev->t128.host_pos = 512;
|
|
|
|
|
ncr_dev->t128.status |= 0x04;
|
|
|
|
|
timer_on_auto(&ncr_dev->timer, 0.2);
|
|
|
|
|
} else {
|
|
|
|
|
if ((ncr->mode & MODE_DMA) && !timer_is_enabled(&ncr_dev->timer)) {
|
|
|
|
|
ncr_log("DMA receive timer start\n");
|
|
|
|
|
ncr_timer_on(ncr_dev, ncr, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
@@ -638,7 +695,7 @@ ncr_write(uint16_t port, uint8_t val, void *priv)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ncr->dma_mode == DMA_IDLE || ncr_dev->type == 0) {
|
|
|
|
|
if (ncr->dma_mode == DMA_IDLE || ncr_dev->type == 0 || (ncr_dev->type == 3 && ncr->dma_mode == DMA_SEND)) {
|
|
|
|
|
bus_host = get_bus_host(ncr);
|
|
|
|
|
ncr_bus_update(priv, bus_host);
|
|
|
|
|
}
|
|
|
|
@@ -658,7 +715,7 @@ ncr_read(uint16_t port, void *priv)
|
|
|
|
|
ncr_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*/
|
|
|
|
|
ncr_log("Data Bus Phase\n");
|
|
|
|
|
ncr_log("Data Bus Phase, ret = %02x\n", ncr->output_data);
|
|
|
|
|
ret = ncr->output_data;
|
|
|
|
|
} else {
|
|
|
|
|
/*Return the data from the SCSI bus*/
|
|
|
|
@@ -792,11 +849,10 @@ memio_read(uint32_t addr, void *priv)
|
|
|
|
|
ret = 0xff;
|
|
|
|
|
} else {
|
|
|
|
|
ret = ncr_dev->buffer[ncr_dev->buffer_host_pos++];
|
|
|
|
|
ncr_log("Read Host pos = %i\n", ncr_dev->buffer_host_pos);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (ncr_dev->buffer_host_pos == 128) {
|
|
|
|
|
ncr_log("Not ready\n");
|
|
|
|
|
ncr_dev->status_ctrl |= STATUS_BUFFER_NOT_READY;
|
|
|
|
|
ncr_log("Transfer busy read, status = %02x\n", ncr_dev->status_ctrl);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
@@ -860,7 +916,7 @@ memio_write(uint32_t addr, uint8_t val, void *priv)
|
|
|
|
|
if (!(ncr_dev->status_ctrl & CTRL_DATA_DIR) && ncr_dev->buffer_host_pos < 128) {
|
|
|
|
|
ncr_dev->buffer[ncr_dev->buffer_host_pos++] = val;
|
|
|
|
|
|
|
|
|
|
ncr_log("Write host pos = %i\n", ncr_dev->buffer_host_pos);
|
|
|
|
|
ncr_log("Write host pos = %i, val = %02x\n", ncr_dev->buffer_host_pos, val);
|
|
|
|
|
|
|
|
|
|
if (ncr_dev->buffer_host_pos == 128) {
|
|
|
|
|
ncr_dev->status_ctrl |= STATUS_BUFFER_NOT_READY;
|
|
|
|
@@ -1003,37 +1059,66 @@ ncr_dma_send(ncr5380_t *ncr_dev, ncr_t *ncr, scsi_device_t *dev)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Data ready. */
|
|
|
|
|
data = ncr_dev->buffer[ncr_dev->buffer_pos];
|
|
|
|
|
if (ncr_dev->type == 3) {
|
|
|
|
|
data = ncr_dev->t128.buffer[ncr_dev->t128.pos];
|
|
|
|
|
} else
|
|
|
|
|
data = ncr_dev->buffer[ncr_dev->buffer_pos];
|
|
|
|
|
bus = get_bus_host(ncr) & ~BUS_DATAMASK;
|
|
|
|
|
bus |= BUS_SETDATA(data);
|
|
|
|
|
|
|
|
|
|
ncr_bus_update(ncr_dev, bus | BUS_ACK);
|
|
|
|
|
ncr_bus_update(ncr_dev, bus & ~BUS_ACK);
|
|
|
|
|
|
|
|
|
|
ncr_dev->buffer_pos++;
|
|
|
|
|
ncr_log("Buffer pos for writing = %d\n", ncr_dev->buffer_pos);
|
|
|
|
|
if (ncr_dev->type == 3) {
|
|
|
|
|
ncr_dev->t128.pos++;
|
|
|
|
|
ncr_log("Buffer pos for writing = %d, data = %02x\n", ncr_dev->t128.pos, data);
|
|
|
|
|
|
|
|
|
|
if (ncr_dev->buffer_pos == 128) {
|
|
|
|
|
ncr_dev->buffer_pos = 0;
|
|
|
|
|
ncr_dev->buffer_host_pos = 0;
|
|
|
|
|
ncr_dev->status_ctrl &= ~STATUS_BUFFER_NOT_READY;
|
|
|
|
|
ncr_dev->ncr_busy = 0;
|
|
|
|
|
ncr_dev->block_count = (ncr_dev->block_count - 1) & 0xff;
|
|
|
|
|
ncr_log("Remaining blocks to be written=%d\n", ncr_dev->block_count);
|
|
|
|
|
if (!ncr_dev->block_count) {
|
|
|
|
|
ncr_dev->block_count_loaded = 0;
|
|
|
|
|
ncr_log("IO End of write transfer\n");
|
|
|
|
|
ncr->tcr |= TCR_LAST_BYTE_SENT;
|
|
|
|
|
ncr->isr |= STATUS_END_OF_DMA;
|
|
|
|
|
timer_stop(&ncr_dev->timer);
|
|
|
|
|
if (ncr->mode & MODE_ENA_EOP_INT) {
|
|
|
|
|
ncr_log("NCR write irq\n");
|
|
|
|
|
ncr_irq(ncr_dev, ncr, 1);
|
|
|
|
|
}
|
|
|
|
|
if (ncr_dev->t128.pos == 512) {
|
|
|
|
|
ncr_dev->t128.pos = 0;
|
|
|
|
|
ncr_dev->t128.host_pos = 0;
|
|
|
|
|
ncr_dev->t128.status &= ~0x02;
|
|
|
|
|
ncr_dev->t128.block_count = (ncr_dev->t128.block_count - 1) & 0xff;
|
|
|
|
|
ncr_log("Remaining blocks to be written=%d\n", ncr_dev->t128.block_count);
|
|
|
|
|
if (!ncr_dev->t128.block_count) {
|
|
|
|
|
ncr_dev->t128.block_loaded = 0;
|
|
|
|
|
ncr_dev->t128.xfer_complete = 0;
|
|
|
|
|
ncr_log("IO End of write transfer\n");
|
|
|
|
|
ncr->tcr |= TCR_LAST_BYTE_SENT;
|
|
|
|
|
ncr->isr |= STATUS_END_OF_DMA;
|
|
|
|
|
timer_stop(&ncr_dev->timer);
|
|
|
|
|
if (ncr->mode & MODE_ENA_EOP_INT) {
|
|
|
|
|
ncr_log("NCR write irq\n");
|
|
|
|
|
ncr_irq(ncr_dev, ncr, 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
ncr_dev->buffer_pos++;
|
|
|
|
|
ncr_log("Buffer pos for writing = %d\n", ncr_dev->buffer_pos);
|
|
|
|
|
|
|
|
|
|
if (ncr_dev->buffer_pos == 128) {
|
|
|
|
|
ncr_dev->buffer_pos = 0;
|
|
|
|
|
ncr_dev->buffer_host_pos = 0;
|
|
|
|
|
ncr_dev->status_ctrl &= ~STATUS_BUFFER_NOT_READY;
|
|
|
|
|
ncr_dev->ncr_busy = 0;
|
|
|
|
|
ncr_dev->block_count = (ncr_dev->block_count - 1) & 0xff;
|
|
|
|
|
ncr_log("Remaining blocks to be written=%d\n", ncr_dev->block_count);
|
|
|
|
|
if (!ncr_dev->block_count) {
|
|
|
|
|
ncr_dev->block_count_loaded = 0;
|
|
|
|
|
ncr_log("IO End of write transfer\n");
|
|
|
|
|
ncr->tcr |= TCR_LAST_BYTE_SENT;
|
|
|
|
|
ncr->isr |= STATUS_END_OF_DMA;
|
|
|
|
|
timer_stop(&ncr_dev->timer);
|
|
|
|
|
if (ncr->mode & MODE_ENA_EOP_INT) {
|
|
|
|
|
ncr_log("NCR write irq\n");
|
|
|
|
|
ncr_irq(ncr_dev, ncr, 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
ncr_dma_send(ncr_dev, ncr, dev);
|
|
|
|
|
ncr_dma_send(ncr_dev, ncr, dev);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
@@ -1041,12 +1126,12 @@ ncr_dma_initiator_receive(ncr5380_t *ncr_dev, ncr_t *ncr, scsi_device_t *dev)
|
|
|
|
|
{
|
|
|
|
|
int bus, c = 0;
|
|
|
|
|
uint8_t temp;
|
|
|
|
|
|
|
|
|
|
if (scsi_device_get_callback(dev) > 0.0)
|
|
|
|
|
ncr_timer_on(ncr_dev, ncr, 1);
|
|
|
|
|
else
|
|
|
|
|
ncr_timer_on(ncr_dev, ncr, 0);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (scsi_device_get_callback(dev) > 0.0) {
|
|
|
|
|
ncr_timer_on(ncr_dev, ncr, 1);
|
|
|
|
|
} else
|
|
|
|
|
ncr_timer_on(ncr_dev, ncr, 0);
|
|
|
|
|
|
|
|
|
|
for (c = 0; c < 10; c++) {
|
|
|
|
|
ncr_bus_read(ncr_dev);
|
|
|
|
|
if (ncr->cur_bus & BUS_REQ)
|
|
|
|
@@ -1061,28 +1146,52 @@ ncr_dma_initiator_receive(ncr5380_t *ncr_dev, ncr_t *ncr, scsi_device_t *dev)
|
|
|
|
|
|
|
|
|
|
ncr_bus_update(ncr_dev, bus | BUS_ACK);
|
|
|
|
|
ncr_bus_update(ncr_dev, bus & ~BUS_ACK);
|
|
|
|
|
|
|
|
|
|
ncr_dev->buffer[ncr_dev->buffer_pos++] = temp;
|
|
|
|
|
ncr_log("Buffer pos for reading = %d\n", ncr_dev->buffer_pos);
|
|
|
|
|
|
|
|
|
|
if (ncr_dev->buffer_pos == 128) {
|
|
|
|
|
ncr_dev->buffer_pos = 0;
|
|
|
|
|
ncr_dev->buffer_host_pos = 0;
|
|
|
|
|
ncr_dev->status_ctrl &= ~STATUS_BUFFER_NOT_READY;
|
|
|
|
|
ncr_dev->block_count = (ncr_dev->block_count - 1) & 0xff;
|
|
|
|
|
ncr_log("Remaining blocks to be read=%d\n", ncr_dev->block_count);
|
|
|
|
|
if (!ncr_dev->block_count) {
|
|
|
|
|
ncr_dev->block_count_loaded = 0;
|
|
|
|
|
ncr_log("IO End of read transfer\n");
|
|
|
|
|
ncr->isr |= STATUS_END_OF_DMA;
|
|
|
|
|
timer_stop(&ncr_dev->timer);
|
|
|
|
|
if (ncr->mode & MODE_ENA_EOP_INT) {
|
|
|
|
|
ncr_log("NCR read irq\n");
|
|
|
|
|
ncr_irq(ncr_dev, ncr, 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (ncr_dev->type == 3) {
|
|
|
|
|
ncr_dev->t128.buffer[ncr_dev->t128.pos++] = temp;
|
|
|
|
|
ncr_log("Buffer pos for reading = %d, temp = %02x\n", ncr_dev->t128.pos, temp);
|
|
|
|
|
|
|
|
|
|
if (ncr_dev->t128.pos == 512) {
|
|
|
|
|
ncr_dev->t128.pos = 0;
|
|
|
|
|
ncr_dev->t128.host_pos = 0;
|
|
|
|
|
ncr_dev->t128.status &= ~0x02;
|
|
|
|
|
ncr_dev->t128.block_count = (ncr_dev->t128.block_count - 1) & 0xff;
|
|
|
|
|
ncr_log("Remaining blocks to be read=%d, status=%02x, len=%i\n", ncr_dev->t128.block_count, ncr_dev->t128.status, dev->buffer_length);
|
|
|
|
|
if (!ncr_dev->t128.block_count) {
|
|
|
|
|
ncr_dev->t128.block_loaded = 0;
|
|
|
|
|
ncr_log("IO End of read transfer\n");
|
|
|
|
|
ncr->isr |= STATUS_END_OF_DMA;
|
|
|
|
|
timer_stop(&ncr_dev->timer);
|
|
|
|
|
if (ncr->mode & MODE_ENA_EOP_INT) {
|
|
|
|
|
ncr_log("NCR read irq\n");
|
|
|
|
|
ncr_irq(ncr_dev, ncr, 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
ncr_dev->buffer[ncr_dev->buffer_pos++] = temp;
|
|
|
|
|
ncr_log("Buffer pos for reading = %d\n", ncr_dev->buffer_pos);
|
|
|
|
|
|
|
|
|
|
if (ncr_dev->buffer_pos == 128) {
|
|
|
|
|
ncr_dev->buffer_pos = 0;
|
|
|
|
|
ncr_dev->buffer_host_pos = 0;
|
|
|
|
|
ncr_dev->status_ctrl &= ~STATUS_BUFFER_NOT_READY;
|
|
|
|
|
ncr_dev->block_count = (ncr_dev->block_count - 1) & 0xff;
|
|
|
|
|
ncr_log("Remaining blocks to be read=%d\n", ncr_dev->block_count);
|
|
|
|
|
if (!ncr_dev->block_count) {
|
|
|
|
|
ncr_dev->block_count_loaded = 0;
|
|
|
|
|
ncr_log("IO End of read transfer\n");
|
|
|
|
|
ncr->isr |= STATUS_END_OF_DMA;
|
|
|
|
|
timer_stop(&ncr_dev->timer);
|
|
|
|
|
if (ncr->mode & MODE_ENA_EOP_INT) {
|
|
|
|
|
ncr_log("NCR read irq\n");
|
|
|
|
|
ncr_irq(ncr_dev, ncr, 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ncr_dma_initiator_receive(ncr_dev, ncr, dev);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -1093,11 +1202,36 @@ ncr_callback(void *priv)
|
|
|
|
|
ncr_t *ncr = &ncr_dev->ncr;
|
|
|
|
|
scsi_device_t *dev = &scsi_devices[ncr_dev->bus][ncr->target_id];
|
|
|
|
|
|
|
|
|
|
ncr_log("DMA mode=%d, status ctrl = %02x\n", ncr->dma_mode, ncr_dev->status_ctrl);
|
|
|
|
|
|
|
|
|
|
if (ncr->dma_mode != DMA_IDLE && (ncr->mode & MODE_DMA) && ncr_dev->block_count_loaded) {
|
|
|
|
|
ncr_timer_on(ncr_dev, ncr, 0);
|
|
|
|
|
}
|
|
|
|
|
if (ncr_dev->type == 3) {
|
|
|
|
|
ncr_log("DMA Callback, load = %i\n", ncr_dev->t128.block_loaded);
|
|
|
|
|
if (ncr->dma_mode != DMA_IDLE && (ncr->mode & MODE_DMA) && ncr_dev->t128.block_loaded) {
|
|
|
|
|
ncr_log("Timer on! Host POS = %i, status = %02x, DMA mode = %i, Period = %lf\n", ncr_dev->t128.host_pos, ncr_dev->t128.status, ncr->dma_mode, scsi_device_get_callback(dev));
|
|
|
|
|
if (ncr->dma_mode == DMA_INITIATOR_RECEIVE) {
|
|
|
|
|
if (ncr_dev->t128.host_pos < 512 && ncr_dev->t128.block_count)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (ncr_dev->t128.host_pos == 512 && ncr_dev->t128.block_count) {
|
|
|
|
|
ncr_dev->t128.status |= 0x04;
|
|
|
|
|
ncr_log("Keep reading\n");
|
|
|
|
|
ncr_timer_on(ncr_dev, ncr, 0);
|
|
|
|
|
}
|
|
|
|
|
} else if (ncr->dma_mode == DMA_SEND) {
|
|
|
|
|
if (ncr_dev->t128.host_pos < 512 && ncr_dev->t128.block_count)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (ncr_dev->t128.host_pos == 512 && ncr_dev->t128.block_count) {
|
|
|
|
|
ncr_dev->t128.status |= 0x04;
|
|
|
|
|
ncr_log("Keep writing\n");
|
|
|
|
|
ncr_timer_on(ncr_dev, ncr, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
ncr_log("DMA mode=%d, status ctrl = %02x\n", ncr->dma_mode, ncr_dev->status_ctrl);
|
|
|
|
|
if (ncr->dma_mode != DMA_IDLE && (ncr->mode & MODE_DMA) && ncr_dev->block_count_loaded) {
|
|
|
|
|
ncr_timer_on(ncr_dev, ncr, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ncr->data_wait & 1) {
|
|
|
|
|
ncr->clear_req = 3;
|
|
|
|
@@ -1109,36 +1243,58 @@ ncr_callback(void *priv)
|
|
|
|
|
|
|
|
|
|
switch(ncr->dma_mode) {
|
|
|
|
|
case DMA_SEND:
|
|
|
|
|
if (ncr_dev->status_ctrl & CTRL_DATA_DIR) {
|
|
|
|
|
ncr_log("DMA_SEND with DMA direction set wrong\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!(ncr_dev->status_ctrl & STATUS_BUFFER_NOT_READY)) {
|
|
|
|
|
ncr_log("Write buffer status ready\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!ncr_dev->block_count_loaded)
|
|
|
|
|
break;
|
|
|
|
|
if (ncr_dev->type != 3) {
|
|
|
|
|
if (ncr_dev->status_ctrl & CTRL_DATA_DIR) {
|
|
|
|
|
ncr_log("DMA_SEND with DMA direction set wrong\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!(ncr_dev->status_ctrl & STATUS_BUFFER_NOT_READY)) {
|
|
|
|
|
ncr_log("Write buffer status ready\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!ncr_dev->block_count_loaded)
|
|
|
|
|
break;
|
|
|
|
|
} else {
|
|
|
|
|
if (!(ncr_dev->t128.status & 0x04)) {
|
|
|
|
|
ncr_log("Write status busy\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!ncr_dev->t128.block_loaded) {
|
|
|
|
|
ncr_log("Write block not loaded\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ncr_dma_send(ncr_dev, ncr, dev);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case DMA_INITIATOR_RECEIVE:
|
|
|
|
|
if (!(ncr_dev->status_ctrl & CTRL_DATA_DIR)) {
|
|
|
|
|
ncr_log("DMA_INITIATOR_RECEIVE with DMA direction set wrong\n");
|
|
|
|
|
break;
|
|
|
|
|
if (ncr_dev->type != 3) {
|
|
|
|
|
if (!(ncr_dev->status_ctrl & CTRL_DATA_DIR)) {
|
|
|
|
|
ncr_log("DMA_INITIATOR_RECEIVE with DMA direction set wrong\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!(ncr_dev->status_ctrl & STATUS_BUFFER_NOT_READY)) {
|
|
|
|
|
ncr_log("Read buffer status ready\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!ncr_dev->block_count_loaded)
|
|
|
|
|
break;
|
|
|
|
|
} else {
|
|
|
|
|
if (!(ncr_dev->t128.status & 0x04)) {
|
|
|
|
|
ncr_log("Read status busy, block count = %i, host pos = %i\n", ncr_dev->t128.block_count, ncr_dev->t128.host_pos);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!ncr_dev->t128.block_loaded) {
|
|
|
|
|
ncr_log("Read block not loaded\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!(ncr_dev->status_ctrl & STATUS_BUFFER_NOT_READY)) {
|
|
|
|
|
ncr_log("Read buffer status ready\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!ncr_dev->block_count_loaded)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
ncr_dma_initiator_receive(ncr_dev, ncr, dev);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
@@ -1153,6 +1309,107 @@ ncr_callback(void *priv)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static uint8_t
|
|
|
|
|
t128_read(uint32_t addr, void *priv)
|
|
|
|
|
{
|
|
|
|
|
ncr5380_t *ncr_dev = (ncr5380_t *)priv;
|
|
|
|
|
ncr_t *ncr = &ncr_dev->ncr;
|
|
|
|
|
uint8_t ret = 0xff;
|
|
|
|
|
|
|
|
|
|
addr &= 0x3fff;
|
|
|
|
|
if (addr >= 0 && addr < 0x1800)
|
|
|
|
|
ret = ncr_dev->bios_rom.rom[addr & 0x1fff];
|
|
|
|
|
else if (addr >= 0x1800 && addr < 0x1880)
|
|
|
|
|
ret = ncr_dev->t128.ext_ram[addr - 0x1800];
|
|
|
|
|
else if (addr >= 0x1c00 && addr < 0x1c20) {
|
|
|
|
|
ret = ncr_dev->t128.ctrl;
|
|
|
|
|
} else if (addr >= 0x1c20 && addr < 0x1c40) {
|
|
|
|
|
ret = ncr_dev->t128.status;
|
|
|
|
|
ncr_log("T128 status read = %02x\n", ret);
|
|
|
|
|
} else if (addr >= 0x1d00 && addr < 0x1e00) {
|
|
|
|
|
if (addr >= 0x1d00 && addr < 0x1d20)
|
|
|
|
|
ret = ncr_read(0, ncr_dev);
|
|
|
|
|
else if (addr >= 0x1d20 && addr < 0x1d40)
|
|
|
|
|
ret = ncr_read(1, ncr_dev);
|
|
|
|
|
else if (addr >= 0x1d40 && addr < 0x1d60)
|
|
|
|
|
ret = ncr_read(2, ncr_dev);
|
|
|
|
|
else if (addr >= 0x1d60 && addr < 0x1d80)
|
|
|
|
|
ret = ncr_read(3, ncr_dev);
|
|
|
|
|
else if (addr >= 0x1d80 && addr < 0x1da0)
|
|
|
|
|
ret = ncr_read(4, ncr_dev);
|
|
|
|
|
else if (addr >= 0x1da0 && addr < 0x1dc0)
|
|
|
|
|
ret = ncr_read(5, ncr_dev);
|
|
|
|
|
else if (addr >= 0x1dc0 && addr < 0x1de0)
|
|
|
|
|
ret = ncr_read(6, ncr_dev);
|
|
|
|
|
else if (addr >= 0x1de0 && addr < 0x1e00)
|
|
|
|
|
ret = ncr_read(7, ncr_dev);
|
|
|
|
|
} else if (addr >= 0x1e00 && addr < 0x2000) {
|
|
|
|
|
if (ncr_dev->t128.host_pos >= 512 || ncr->dma_mode != DMA_INITIATOR_RECEIVE) {
|
|
|
|
|
ret = 0xff;
|
|
|
|
|
} else {
|
|
|
|
|
ret = ncr_dev->t128.buffer[ncr_dev->t128.host_pos++];
|
|
|
|
|
|
|
|
|
|
ncr_log("Read transfer, addr = %i, pos = %i\n", addr & 0x1ff, ncr_dev->t128.host_pos);
|
|
|
|
|
|
|
|
|
|
if (ncr_dev->t128.host_pos == 512) {
|
|
|
|
|
ncr_dev->t128.status &= ~0x04;
|
|
|
|
|
ncr_log("Transfer busy read, status = %02x\n", ncr_dev->t128.status);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return(ret);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
t128_write(uint32_t addr, uint8_t val, void *priv)
|
|
|
|
|
{
|
|
|
|
|
ncr5380_t *ncr_dev = (ncr5380_t *)priv;
|
|
|
|
|
ncr_t *ncr = &ncr_dev->ncr;
|
|
|
|
|
|
|
|
|
|
addr &= 0x3fff;
|
|
|
|
|
if (addr >= 0x1800 && addr < 0x1880)
|
|
|
|
|
ncr_dev->t128.ext_ram[addr - 0x1800] = val;
|
|
|
|
|
else if (addr >= 0x1c00 && addr < 0x1c20) {
|
|
|
|
|
if ((val & 0x02) && !(ncr_dev->t128.ctrl & 0x02)) {
|
|
|
|
|
ncr_dev->t128.status |= 0x02;
|
|
|
|
|
ncr_log("Timer fired\n");
|
|
|
|
|
}
|
|
|
|
|
ncr_dev->t128.ctrl = val;
|
|
|
|
|
ncr_log("T128 ctrl write = %02x\n", val);
|
|
|
|
|
} else if (addr >= 0x1d00 && addr < 0x1e00) {
|
|
|
|
|
if (addr >= 0x1d00 && addr < 0x1d20)
|
|
|
|
|
ncr_write(0, val, ncr_dev);
|
|
|
|
|
else if (addr >= 0x1d20 && addr < 0x1d40)
|
|
|
|
|
ncr_write(1, val, ncr_dev);
|
|
|
|
|
else if (addr >= 0x1d40 && addr < 0x1d60)
|
|
|
|
|
ncr_write(2, val, ncr_dev);
|
|
|
|
|
else if (addr >= 0x1d60 && addr < 0x1d80)
|
|
|
|
|
ncr_write(3, val, ncr_dev);
|
|
|
|
|
else if (addr >= 0x1d80 && addr < 0x1da0)
|
|
|
|
|
ncr_write(4, val, ncr_dev);
|
|
|
|
|
else if (addr >= 0x1da0 && addr < 0x1dc0)
|
|
|
|
|
ncr_write(5, val, ncr_dev);
|
|
|
|
|
else if (addr >= 0x1dc0 && addr < 0x1de0)
|
|
|
|
|
ncr_write(6, val, ncr_dev);
|
|
|
|
|
else if (addr >= 0x1de0 && addr < 0x1e00)
|
|
|
|
|
ncr_write(7, val, ncr_dev);
|
|
|
|
|
} else if (addr >= 0x1e00 && addr < 0x2000) {
|
|
|
|
|
if (ncr_dev->t128.host_pos < 512 && ncr->dma_mode == DMA_SEND) {
|
|
|
|
|
ncr_dev->t128.buffer[ncr_dev->t128.host_pos] = val;
|
|
|
|
|
ncr_dev->t128.host_pos++;
|
|
|
|
|
|
|
|
|
|
ncr_log("Write transfer, addr = %i, pos = %i, val = %02x\n", addr & 0x1ff, ncr_dev->t128.host_pos, val);
|
|
|
|
|
|
|
|
|
|
if (ncr_dev->t128.host_pos == 512) {
|
|
|
|
|
ncr_dev->t128.status &= ~0x04;
|
|
|
|
|
ncr_log("Transfer busy write, status = %02x\n", ncr_dev->t128.status);
|
|
|
|
|
timer_on_auto(&ncr_dev->timer, 0.2);
|
|
|
|
|
}
|
|
|
|
|
} else
|
|
|
|
|
ncr_log("Write PDMA addr = %i, val = %02x\n", addr & 0x1ff, val);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void *
|
|
|
|
|
ncr_init(const device_t *info)
|
|
|
|
@@ -1218,6 +1475,18 @@ ncr_init(const device_t *info)
|
|
|
|
|
io_sethandler(ncr_dev->base, 16,
|
|
|
|
|
t130b_in,NULL,NULL, t130b_out,NULL,NULL, ncr_dev);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 3: /* Trantor T128 */
|
|
|
|
|
ncr_dev->rom_addr = device_get_config_hex20("bios_addr");
|
|
|
|
|
ncr_dev->irq = device_get_config_int("irq");
|
|
|
|
|
rom_init(&ncr_dev->bios_rom, T128_ROM,
|
|
|
|
|
ncr_dev->rom_addr, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
|
|
|
|
|
|
|
|
|
|
mem_mapping_add(&ncr_dev->mapping, ncr_dev->rom_addr, 0x4000,
|
|
|
|
|
t128_read, NULL, NULL,
|
|
|
|
|
t128_write, NULL, NULL,
|
|
|
|
|
ncr_dev->bios_rom.rom, MEM_MAPPING_EXTERNAL, ncr_dev);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sprintf(temp, "%s: BIOS=%05X", ncr_dev->name, ncr_dev->rom_addr);
|
|
|
|
@@ -1228,10 +1497,14 @@ ncr_init(const device_t *info)
|
|
|
|
|
ncr_log("%s\n", temp);
|
|
|
|
|
|
|
|
|
|
ncr_reset(ncr_dev, &ncr_dev->ncr);
|
|
|
|
|
ncr_dev->status_ctrl = STATUS_BUFFER_NOT_READY;
|
|
|
|
|
ncr_dev->buffer_host_pos = 128;
|
|
|
|
|
|
|
|
|
|
timer_add(&ncr_dev->timer, ncr_callback, ncr_dev, 0);
|
|
|
|
|
if (ncr_dev->type != 3) {
|
|
|
|
|
ncr_dev->status_ctrl = STATUS_BUFFER_NOT_READY;
|
|
|
|
|
ncr_dev->buffer_host_pos = 128;
|
|
|
|
|
} else {
|
|
|
|
|
ncr_dev->t128.status = 0x04;
|
|
|
|
|
ncr_dev->t128.host_pos = 512;
|
|
|
|
|
}
|
|
|
|
|
timer_add(&ncr_dev->timer, ncr_callback, ncr_dev, 0);
|
|
|
|
|
|
|
|
|
|
return(ncr_dev);
|
|
|
|
|
}
|
|
|
|
@@ -1271,6 +1544,11 @@ t130b_available(void)
|
|
|
|
|
return(rom_present(T130B_ROM));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
t128_available(void)
|
|
|
|
|
{
|
|
|
|
|
return(rom_present(T128_ROM));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const device_config_t ncr5380_mmio_config[] = {
|
|
|
|
|
{
|
|
|
|
@@ -1473,3 +1751,14 @@ const device_t scsi_t130b_device =
|
|
|
|
|
NULL, NULL,
|
|
|
|
|
t130b_config
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const device_t scsi_t128_device =
|
|
|
|
|
{
|
|
|
|
|
"Trantor T128",
|
|
|
|
|
DEVICE_ISA,
|
|
|
|
|
3,
|
|
|
|
|
ncr_init, ncr_close, NULL,
|
|
|
|
|
{ t128_available },
|
|
|
|
|
NULL, NULL,
|
|
|
|
|
ncr5380_mmio_config
|
|
|
|
|
};
|
|
|
|
|