Merge pull request #5136 from 86Box/tc1995

NCR 5380-based changes of the day (January 12, 2025)
This commit is contained in:
Miran Grča
2025-01-12 21:01:47 +01:00
committed by GitHub
3 changed files with 62 additions and 25 deletions

View File

@@ -197,20 +197,29 @@ ncr5380_bus_read(ncr_t *ncr)
phase = (ncr->cur_bus & SCSI_PHASE_MESSAGE_IN);
if (phase == SCSI_PHASE_DATA_IN) {
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;
if (ncr->dma_mode == DMA_IDLE) {
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
ncr->state = STATE_DATAOUT;
} else {
if (ncr->dma_mode == DMA_IDLE)
ncr->state = STATE_DATAOUT;
}
} else if (phase == SCSI_PHASE_STATUS) {
ncr5380_log("Phase Status.\n");
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) {
@@ -335,19 +344,22 @@ ncr5380_bus_update(ncr_t *ncr, int bus)
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 {
ncr->tx_data = dev->sc->temp_buffer[ncr->data_pos++];
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\n");
ncr5380_log("DMA mode idle IN=%d.\n", ncr->data_pos);
ncr->timer(ncr->priv, ncr->period);
} else {
ncr5380_log("DMA mode IN.\n");
ncr5380_log("DMA mode IN=%d.\n", ncr->data_pos);
ncr->clear_req = 3;
}
@@ -359,7 +371,8 @@ ncr5380_bus_update(ncr_t *ncr, int bus)
case STATE_DATAOUT:
dev = &scsi_devices[ncr->bus][ncr->target_id];
if ((bus & BUS_ACK) && !(ncr->bus_in & BUS_ACK)) {
dev->sc->temp_buffer[ncr->data_pos++] = BUS_GETDATA(bus);
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;
@@ -439,12 +452,12 @@ ncr5380_write(uint16_t port, uint8_t val, ncr_t *ncr)
switch (port & 7) {
case 0: /* Output data register */
ncr5380_log("Write: Output data register, val = %02x\n", val);
ncr5380_log("[%04X:%08X]: Write: Output data register, val=%02x\n", CS, cpu_state.pc, val);
ncr->output_data = val;
break;
case 1: /* Initiator Command Register */
ncr5380_log("Write: Initiator command register\n");
ncr5380_log("[%04X:%08X]: Write: Initiator command register, val=%02x.\n", CS, cpu_state.pc, val);
if ((val & 0x80) && !(ncr->icr & 0x80)) {
ncr5380_log("Resetting the 5380\n");
ncr5380_reset(ncr);
@@ -465,7 +478,7 @@ ncr5380_write(uint16_t port, uint8_t val, ncr_t *ncr)
break;
case 3: /* Target Command Register */
ncr5380_log("Write: Target Command register\n");
ncr5380_log("Write: Target Command register, val=%02x.\n", val);
ncr->tcr = val;
break;
@@ -482,7 +495,7 @@ ncr5380_write(uint16_t port, uint8_t val, ncr_t *ncr)
break;
case 7: /* start DMA Initiator Receive */
ncr5380_log("Write: start DMA initiator receive register, dma? = %02x\n", ncr->mode & MODE_DMA);
ncr5380_log("[%04X:%08X]: Write: start DMA initiator receive register, dma? = %02x\n", CS, cpu_state.pc, 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->dma_initiator_receive_ext)
@@ -510,13 +523,13 @@ 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*/
ncr5380_log("Data Bus Phase, ret = %02x\n", ncr->output_data);
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);
} else {
/*Return the data from the SCSI bus*/
ncr5380_bus_read(ncr);
ncr5380_log("NCR GetData=%02x\n", BUS_GETDATA(ncr->cur_bus));
ret = BUS_GETDATA(ncr->cur_bus);
ncr5380_log("[%04X:%08X]: NCR Get SCSI bus data=%02x.\n", CS, cpu_state.pc, ret);
}
break;
@@ -595,7 +608,9 @@ ncr5380_read(uint16_t port, ncr_t *ncr)
break;
case 6:
ret = ncr->tx_data;
ncr5380_log("Read: Input Data.\n");
ncr5380_bus_read(ncr);
ret = BUS_GETDATA(ncr->cur_bus);
break;
case 7: /* reset Parity/Interrupt */

View File

@@ -148,6 +148,12 @@ ncr53c400_write(uint32_t addr, uint8_t val, void *priv)
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);
}
}
}
break;
@@ -181,13 +187,14 @@ 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);
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);
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_complete, ncr->wait_data, ncr->wait_complete, ncr->clear_req, ncr->data_wait, timer_is_enabled(&ncr400->timer));
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));
}
break;
@@ -244,6 +251,12 @@ ncr53c400_read(uint32_t addr, void *priv)
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;
@@ -397,16 +410,20 @@ t130b_in(uint16_t port, void *priv)
}
static void
ncr53c400_dma_mode_ext(void *priv, UNUSED(void *ext_priv))
ncr53c400_dma_mode_ext(void *priv, void *ext_priv)
{
ncr_t *ncr = (ncr_t *) priv;
ncr53c400_t *ncr400 = (ncr53c400_t *) ext_priv;
ncr_t *ncr = (ncr_t *) priv;
/*When a pseudo-DMA transfer has completed (Send or Initiator Receive), mark it as complete and idle the status*/
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("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;
}
}
}
@@ -474,6 +491,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;
ncr400->block_count_loaded = 0;
ncr53c400_log("IO End of write transfer\n");
ncr->tcr |= TCR_LAST_BYTE_SENT;
@@ -527,6 +545,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;
ncr400->block_count_loaded = 0;
ncr53c400_log("IO End of read transfer\n");
ncr->isr |= STATUS_END_OF_DMA;
@@ -544,6 +563,7 @@ ncr53c400_callback(void *priv)
break;
}
ncr53c400_log("Bus Read.\n");
ncr5380_bus_read(ncr);
if (!(ncr->cur_bus & BUS_BSY) && (ncr->mode & MODE_MONITOR_BUSY)) {

View File

@@ -287,6 +287,7 @@ write_again:
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) {
ncr->dma_mode = DMA_IDLE;
t128->block_loaded = 0;
t128_log("IO End of write transfer\n");
ncr->tcr |= TCR_LAST_BYTE_SENT;
@@ -343,6 +344,7 @@ read_again:
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;
ncr->dma_mode = DMA_IDLE;
t128_log("IO End of read transfer\n");
ncr->isr |= STATUS_END_OF_DMA;
timer_stop(&t128->timer);