From a2534c1f4f655c6675f1b324344aa7233900ec0b Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sat, 8 Mar 2025 14:41:59 +0100 Subject: [PATCH] Trantor T128/MediaVision SCSI changes of the day (March 8th, 2025) 1. Made as best as possible implementation of the status bits 1-2 of the Trantor 128 so to make a more accurate speed for SCSI devices (CD-ROM and HDD) without stalls. 2. Slightly reorganized the timer of the T128. --- src/scsi/scsi_t128.c | 292 +++++++++++++++++++++---------------------- 1 file changed, 142 insertions(+), 150 deletions(-) diff --git a/src/scsi/scsi_t128.c b/src/scsi/scsi_t128.c index 5ac3b5d67..6b73ae131 100644 --- a/src/scsi/scsi_t128.c +++ b/src/scsi/scsi_t128.c @@ -77,11 +77,8 @@ t128_write(uint32_t addr, uint8_t val, void *priv) if ((addr >= 0x1800) && (addr < 0x1880)) t128->ext_ram[addr & 0x7f] = val; else if ((addr >= 0x1c00) && (addr < 0x1c20)) { - if ((val & 0x02) && !(t128->ctrl & 0x02)) - t128->status |= 0x02; - + t128_log("T128 ctrl write=%02x, mode=%02x.\n", val, ncr->mode & MODE_DMA); t128->ctrl = val; - t128_log("T128 ctrl write=%02x\n", val); } else if ((addr >= 0x1d00) && (addr < 0x1e00)) ncr5380_write((addr - 0x1d00) >> 5, val, ncr); else if ((addr >= 0x1e00) && (addr < 0x2000)) { @@ -90,13 +87,15 @@ t128_write(uint32_t addr, uint8_t val, void *priv) t128->buffer[t128->host_pos] = val; t128->host_pos++; - t128_log("T128 Write transfer, addr = %i, pos = %i, val = %02x\n", - addr & 0x1ff, t128->host_pos, val); + t128_log("T128 Write transfer: pos=%i, addr=%x.\n", + t128->host_pos, addr & 0x1ff); if (t128->host_pos == MIN(512, dev->buffer_length)) { + t128_log("T128 Transfer busy write, status=%02x, period=%lf, enabled=%d, loaded=%d.\n", + t128->status, scsi_bus->period, timer_is_enabled(&t128->timer), t128->block_loaded); + t128->status &= ~0x04; - t128_log("Transfer busy write, status = %02x\n", t128->status); - timer_on_auto(&t128->timer, 0.02); + timer_on_auto(&t128->timer, 1.0); } } } @@ -119,31 +118,45 @@ t128_read(uint32_t addr, void *priv) ret = t128->ext_ram[addr & 0x7f]; else if ((addr >= 0x1c00) && (addr < 0x1c20)) { ret = t128->ctrl; - t128_log("T128 ctrl read=%02x, dma=%02x\n", ret, ncr->mode & MODE_DMA); + t128_log("T128 ctrl read=%02x, dma=%02x, load=%d, cnt=%d.\n", ret, ncr->mode & MODE_DMA, t128->block_loaded, t128->block_count); } else if ((addr >= 0x1c20) && (addr < 0x1c40)) { ret = t128->status; - t128_log("T128 status read=%02x, dma=%02x\n", ret, ncr->mode & MODE_DMA); + t128_log("T128 status read=%02x, dma=%02x, blockload=%d, timer=%d.\n", ret, ncr->mode & MODE_DMA, t128->block_loaded, timer_is_enabled(&t128->timer)); } else if ((addr >= 0x1d00) && (addr < 0x1e00)) ret = ncr5380_read((addr - 0x1d00) >> 5, ncr); else if (addr >= 0x1e00 && addr < 0x2000) { - if ((t128->host_pos >= MIN(512, dev->buffer_length)) || - (scsi_bus->tx_mode != DMA_IN_TX_BUS)) - ret = 0xff; - else { + if ((scsi_bus->tx_mode == DMA_IN_TX_BUS) && + (t128->host_pos < MIN(512, dev->buffer_length))) { ret = t128->buffer[t128->host_pos++]; - t128_log("T128 Read transfer, addr = %i, pos = %i\n", addr & 0x1ff, - t128->host_pos); + t128_log("T128 Read transfer: pos=%i, addr=%x.\n", + t128->host_pos, addr & 0x1ff); 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, 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)) - cycles += 100; /*Needed to avoid timer de-syncing with transfers.*/ + t128_log("T128 Transfer busy read, status=%02x, period=%lf, enabled=%d.\n", + t128->status, scsi_bus->period, timer_is_enabled(&t128->timer)); + + if (!t128->block_loaded) { + ncr->isr |= STATUS_END_OF_DMA; + if (ncr->mode & MODE_ENA_EOP_INT) { + t128_log("T128 read irq\n"); + ncr5380_irq(ncr, 1); + } + t128->status &= ~0x04; + scsi_bus->bus_out |= BUS_CD; + scsi_bus->tx_mode = PIO_TX_BUS; + timer_stop(&t128->timer); + } else if (!timer_is_enabled(&t128->timer)) + timer_on_auto(&t128->timer, 1.0); + else + t128->status &= ~0x04; + } + } else { + /*According to the WinNT DDK sources, just get the status timeout bit from here.*/ + if (!(t128->status & 0x02)) + t128->status |= 0x02; + + t128_log("Read not allowed.\n"); } } @@ -151,24 +164,20 @@ t128_read(uint32_t addr, void *priv) } static void -t128_dma_mode_ext(void *priv, void *ext_priv, UNUSED(uint8_t val)) +t128_dma_mode_ext(void *priv, void *ext_priv, 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, scsi_bus->period + 1.0); - } - /*When a pseudo-DMA transfer has completed (Send or Initiator Receive), mark it as complete and idle the status*/ - if (!t128->block_loaded && !(ncr->mode & MODE_DMA)) { - t128_log("No DMA mode\n"); - ncr->tcr &= ~TCR_LAST_BYTE_SENT; - ncr->isr &= ~STATUS_END_OF_DMA; - scsi_bus->tx_mode = PIO_TX_BUS; + if (!t128->block_loaded) { + if (!(val & MODE_DMA)) { + ncr->tcr &= ~TCR_LAST_BYTE_SENT; + ncr->isr &= ~STATUS_END_OF_DMA; + scsi_bus->tx_mode = PIO_TX_BUS; + t128_log("End of DMA.\n"); + } } } @@ -180,9 +189,9 @@ t128_dma_send_ext(void *priv, void *ext_priv) 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)) { + if ((ncr->mode & MODE_DMA) && (dev->buffer_length > 0)) { + t128_log("T128 DMA OUT, len=%d.\n", dev->buffer_length); memset(t128->buffer, 0, MIN(512, dev->buffer_length)); - t128->status |= 0x04; t128->host_pos = 0; t128->block_count = dev->buffer_length >> 9; @@ -190,6 +199,7 @@ t128_dma_send_ext(void *priv, void *ext_priv) t128->block_count = 1; t128->block_loaded = 1; + t128->status |= 0x04; } return 1; } @@ -202,9 +212,9 @@ t128_dma_initiator_receive_ext(void *priv, void *ext_priv) 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)) { + if ((ncr->mode & MODE_DMA) && (dev->buffer_length > 0)) { + t128_log("T128 DMA IN, len=%d.\n", dev->buffer_length); memset(t128->buffer, 0, MIN(512, dev->buffer_length)); - t128->status |= 0x04; t128->host_pos = MIN(512, dev->buffer_length); t128->block_count = dev->buffer_length >> 9; @@ -212,7 +222,8 @@ t128_dma_initiator_receive_ext(void *priv, void *ext_priv) t128->block_count = 1; t128->block_loaded = 1; - timer_on_auto(&t128->timer, 0.02); + t128->status &= ~0x04; + timer_on_auto(&t128->timer, 1.0); } return 1; } @@ -222,16 +233,16 @@ t128_timer_on_auto(void *ext_priv, double period) { t128_t *t128 = (t128_t *) ext_priv; - if (period == 0.0) + if (period <= 0.0) timer_stop(&t128->timer); - else + else if ((period > 0.0) && !timer_is_enabled(&t128->timer)) timer_on_auto(&t128->timer, period); } void t128_callback(void *priv) { - t128_t *t128 = (void *) priv; + t128_t *t128 = (t128_t *) priv; ncr_t *ncr = &t128->ncr; scsi_bus_t *scsi_bus = &ncr->scsibus; scsi_device_t *dev = &scsi_devices[ncr->bus][scsi_bus->target_id]; @@ -240,128 +251,110 @@ t128_callback(void *priv) uint8_t temp; uint8_t status; - 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, scsi_bus->period / 55.0); - } + if (scsi_bus->tx_mode != PIO_TX_BUS) + timer_on_auto(&t128->timer, scsi_bus->period / 65.0); 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; + } + + if (scsi_bus->tx_mode == PIO_TX_BUS) { + t128_log("Timer CMD=%02x.\n", scsi_bus->command[0]); + return; } 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; - } - - if (!t128->block_loaded) { - t128_log("Write block not loaded\n"); - break; - } - if (t128->host_pos < MIN(512, dev->buffer_length)) break; -write_again: - for (c = 0; c < 10; c++) { - status = scsi_bus_read(scsi_bus); - if (status & BUS_REQ) - break; - } - - /* Data ready. */ - temp = t128->buffer[t128->pos]; - - bus = ncr5380_get_bus_host(ncr) & ~BUS_DATAMASK; - bus |= BUS_SETDATA(temp); - - 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); - - if (t128->pos == MIN(512, dev->buffer_length)) { - t128->pos = 0; - t128->host_pos = 0; - t128->status &= ~0x02; - t128->block_count = (t128->block_count - 1) & 0xff; - t128_log("T128 Remaining blocks to be written=%d\n", t128->block_count); - if (!t128->block_count) { - t128->block_loaded = 0; - t128_log("IO End of write transfer\n"); - ncr->tcr |= TCR_LAST_BYTE_SENT; - ncr->isr |= STATUS_END_OF_DMA; - timer_stop(&t128->timer); - if (ncr->mode & MODE_ENA_EOP_INT) { - t128_log("T128 write irq\n"); - ncr5380_irq(ncr, 1); - } - } + if (!t128->block_loaded) break; - } else - goto write_again; + + while (1) { + for (c = 0; c < 10; c++) { + status = scsi_bus_read(scsi_bus); + if (status & BUS_REQ) + break; + } + + /* Data ready. */ + temp = t128->buffer[t128->pos]; + + bus = ncr5380_get_bus_host(ncr) & ~BUS_DATAMASK; + bus |= BUS_SETDATA(temp); + + 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); + + if (t128->pos == MIN(512, dev->buffer_length)) { + t128->status |= 0x04; + t128->status &= ~0x02; + t128->pos = 0; + t128->host_pos = 0; + t128->block_count = (t128->block_count - 1) & 0xff; + t128_log("T128 Remaining blocks to be written=%d\n", t128->block_count); + if (!t128->block_count) { + t128->block_loaded = 0; + ncr->tcr |= TCR_LAST_BYTE_SENT; + ncr->isr |= STATUS_END_OF_DMA; + if (ncr->mode & MODE_ENA_EOP_INT) { + t128_log("T128 write irq\n"); + ncr5380_irq(ncr, 1); + } + scsi_bus->tx_mode = PIO_TX_BUS; + timer_stop(&t128->timer); + t128_log("IO End of write transfer\n"); + } + break; + } + } break; 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; - } - - if (!t128->block_loaded) { - t128_log("Read block not loaded\n"); - break; - } - if (t128->host_pos < MIN(512, dev->buffer_length)) break; -read_again: - for (c = 0; c < 10; c++) { - status = scsi_bus_read(scsi_bus); - if (status & BUS_REQ) - break; - } - - /* Data ready. */ - bus = scsi_bus_read(scsi_bus); - temp = BUS_GETDATA(bus); - - bus = ncr5380_get_bus_host(ncr); - - 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); - - if (t128->pos == MIN(512, dev->buffer_length)) { - t128->pos = 0; - t128->host_pos = 0; - t128->status &= ~0x02; - t128->block_count = (t128->block_count - 1) & 0xff; - t128_log("T128 Remaining blocks to be read=%d, status=%02x, len=%i, cdb[0] = %02x\n", t128->block_count, t128->status, dev->buffer_length, ncr->command[0]); - if (!t128->block_count) { - t128->block_loaded = 0; - t128_log("IO End of read transfer\n"); - ncr->isr |= STATUS_END_OF_DMA; - timer_stop(&t128->timer); - if (ncr->mode & MODE_ENA_EOP_INT) { - t128_log("NCR read irq\n"); - ncr5380_irq(ncr, 1); - } - } + if (!t128->block_loaded) break; - } else - goto read_again; + + while (1) { + for (c = 0; c < 10; c++) { + status = scsi_bus_read(scsi_bus); + if (status & BUS_REQ) + break; + } + /* Data ready. */ + bus = scsi_bus_read(scsi_bus); + temp = BUS_GETDATA(bus); + + bus = ncr5380_get_bus_host(ncr); + + 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\n", t128->pos); + + if (t128->pos == MIN(512, dev->buffer_length)) { + t128->status |= 0x04; + t128->status &= ~0x02; + t128->pos = 0; + t128->host_pos = 0; + t128->block_count = (t128->block_count - 1) & 0xff; + t128_log("T128 Remaining blocks to be read=%d\n", t128->block_count); + if (!t128->block_count) { + t128->block_loaded = 0; + scsi_bus->bus_out |= BUS_REQ; + t128_log("IO End of read transfer\n"); + } + break; + } + } break; default: @@ -374,7 +367,7 @@ read_again: t128_log("Updating DMA\n"); ncr->mode &= ~MODE_DMA; scsi_bus->tx_mode = PIO_TX_BUS; - timer_on_auto(&t128->timer, 10.0); + t128->block_loaded = 0; } } @@ -513,7 +506,7 @@ t128_init(const device_t *info) scsi_bus->bus_device = ncr->bus; scsi_bus->timer = ncr->timer; scsi_bus->priv = ncr->priv; - t128->status = 0x00 /*0x04*/; + t128->status = 0x00; t128->host_pos = 512; if (!t128->bios_enabled && !(info->flags & DEVICE_MCA)) t128->status |= 0x80; @@ -528,7 +521,6 @@ t128_init(const device_t *info) scsi_bus->speed = 0.2; scsi_bus->divider = 1.0; scsi_bus->multi = 1.0; - return t128; }