Big SCSI bus update of the day, NCR 5380 too (January 20th, 2025)
1. Separate the SCSI bus functions from NCR 5380 into true general purpose SCSI bus functions, allowing use of future legacy scsi controllers. 2. Corrected NCR 5380 chip period for the SCSI controllers based on that chip so that CD-ROM speed is correct enough per speed tests and no more breakage (I hope, report if they are still there, please!) on desyncs. 3. A NCR 5380 software reset involves asserting an IRQ.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user