diff --git a/src/include/86box/scsi_ncr5380.h b/src/include/86box/scsi_ncr5380.h index aa1f4ad89..b939162fd 100644 --- a/src/include/86box/scsi_ncr5380.h +++ b/src/include/86box/scsi_ncr5380.h @@ -26,6 +26,7 @@ extern const device_t scsi_lcs6821n_device; extern const device_t scsi_rt1000b_device; +extern const device_t scsi_t128_device; extern const device_t scsi_t130b_device; #if defined(DEV_BRANCH) && defined(USE_SUMO) extern const device_t scsi_scsiat_device; diff --git a/src/scsi/scsi.c b/src/scsi/scsi.c index fd619d172..0839d63e9 100644 --- a/src/scsi/scsi.c +++ b/src/scsi/scsi.c @@ -69,6 +69,7 @@ static SCSI_CARD scsi_cards[] = { { "bt545s", &buslogic_545s_device, }, { "lcs6821n", &scsi_lcs6821n_device, }, { "rt1000b", &scsi_rt1000b_device, }, + { "t128", &scsi_t128_device, }, { "t130b", &scsi_t130b_device, }, #ifdef WALTJE { "scsiat", &scsi_scsiat_device, }, diff --git a/src/scsi/scsi_ncr5380.c b/src/scsi/scsi_ncr5380.c index 11d1f570d..86f6faa7f 100644 --- a/src/scsi/scsi_ncr5380.c +++ b/src/scsi/scsi_ncr5380.c @@ -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, bufval[512]; + + 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; @@ -170,7 +183,7 @@ ncr_log(const char *fmt, ...) if (ncr5380_do_log) { va_start(ap, fmt); - pclog_ex(fmt, ap); + ncr_log_ex(fmt, ap); va_end(ap); } } @@ -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 +};