Tweaked NCR 53C810 timings a bit and made it no longer return on bad selection or non-data commands, fixes NT 3.1.

This commit is contained in:
OBattler
2018-03-11 00:16:20 +01:00
parent c0bb63bd82
commit e5442e367b

View File

@@ -10,7 +10,7 @@
* NCR and later Symbios and LSI. This controller was designed * NCR and later Symbios and LSI. This controller was designed
* for the PCI bus. * for the PCI bus.
* *
* Version: @(#)scsi_ncr53c810.c 1.0.8 2018/03/09 * Version: @(#)scsi_ncr53c810.c 1.0.9 2018/03/10
* *
* Authors: Paul Brook (QEMU) * Authors: Paul Brook (QEMU)
* Artyom Tarasenko (QEMU) * Artyom Tarasenko (QEMU)
@@ -653,12 +653,14 @@ ncr53c810_add_msg_byte(ncr53c810_t *dev, uint8_t data)
} }
static void static int
ncr53c810_do_command(ncr53c810_t *dev, uint8_t id) ncr53c810_do_command(ncr53c810_t *dev, uint8_t id)
{ {
scsi_device_t *sd; scsi_device_t *sd;
uint8_t buf[12]; uint8_t buf[12];
int64_t p;
double period; double period;
memset(buf, 0, 12); memset(buf, 0, 12);
@@ -674,7 +676,7 @@ ncr53c810_do_command(ncr53c810_t *dev, uint8_t id)
if (((id == -1) || !scsi_device_present(id, dev->current_lun))) { if (((id == -1) || !scsi_device_present(id, dev->current_lun))) {
ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: Bad Selection\n", id, dev->current_lun, buf[0]); ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: Bad Selection\n", id, dev->current_lun, buf[0]);
ncr53c810_bad_selection(dev, id); ncr53c810_bad_selection(dev, id);
return; return 0;
} }
dev->current = (ncr53c810_request*)malloc(sizeof(ncr53c810_request)); dev->current = (ncr53c810_request*)malloc(sizeof(ncr53c810_request));
@@ -701,21 +703,27 @@ ncr53c810_do_command(ncr53c810_t *dev, uint8_t id)
if ((sd->Phase == SCSI_PHASE_DATA_IN) && (sd->BufferLength > 0)) { if ((sd->Phase == SCSI_PHASE_DATA_IN) && (sd->BufferLength > 0)) {
ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: PHASE_DI\n", id, dev->current_lun, buf[0]); ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: PHASE_DI\n", id, dev->current_lun, buf[0]);
ncr53c810_set_phase(dev, PHASE_DI); ncr53c810_set_phase(dev, PHASE_DI);
dev->timer_period = scsi_device_get_callback(dev->current->tag, dev->current_lun); p = scsi_device_get_callback(dev->current->tag, dev->current_lun);
if (dev->timer_period <= 0LL) { if (p <= 0LL) {
period = ((double) sd->BufferLength) * 0.2 * ((double) TIMER_USEC); /* Fast SCSI: 10000000 bytes per second */ period = ((double) sd->BufferLength) * 0.1 * ((double) TIMER_USEC); /* Fast SCSI: 10000000 bytes per second */
dev->timer_period = (int64_t) period; dev->timer_period += (int64_t) period;
} } else
dev->timer_period += p;
return 1;
} else if ((sd->Phase == SCSI_PHASE_DATA_OUT) && (sd->BufferLength > 0)) { } else if ((sd->Phase == SCSI_PHASE_DATA_OUT) && (sd->BufferLength > 0)) {
ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: PHASE_DO\n", id, dev->current_lun, buf[0]); ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: PHASE_DO\n", id, dev->current_lun, buf[0]);
ncr53c810_set_phase(dev, PHASE_DO); ncr53c810_set_phase(dev, PHASE_DO);
dev->timer_period = scsi_device_get_callback(dev->current->tag, dev->current_lun); p = scsi_device_get_callback(dev->current->tag, dev->current_lun);
if (dev->timer_period <= 0LL) { if (p <= 0LL) {
period = ((double) sd->BufferLength) * 0.2 * ((double) TIMER_USEC); /* Fast SCSI: 10000000 bytes per second */ period = ((double) sd->BufferLength) * 0.1 * ((double) TIMER_USEC); /* Fast SCSI: 10000000 bytes per second */
dev->timer_period = (int64_t) period; dev->timer_period += (int64_t) period;
}
} else } else
dev->timer_period += p;
return 1;
} else {
ncr53c810_command_complete(dev, sd->Status); ncr53c810_command_complete(dev, sd->Status);
return 0;
}
} }
@@ -931,7 +939,7 @@ static void
ncr53c810_process_script(ncr53c810_t *dev) ncr53c810_process_script(ncr53c810_t *dev)
{ {
uint32_t insn, addr, id, buf[2], dest; uint32_t insn, addr, id, buf[2], dest;
int opcode, insn_processed = 0, reg, operator, cond, jmp, n, i; int opcode, insn_processed = 0, reg, operator, cond, jmp, n, i, c;
int32_t offset; int32_t offset;
uint8_t op0, op1, data8, mask, data[7], *pp; uint8_t op0, op1, data8, mask, data[7], *pp;
@@ -943,7 +951,11 @@ again:
/* If we receive an empty opcode increment the DSP by 4 bytes /* If we receive an empty opcode increment the DSP by 4 bytes
instead of 8 and execute the next opcode at that location */ instead of 8 and execute the next opcode at that location */
dev->dsp += 4; dev->dsp += 4;
dev->timer_period += (10LL * TIMER_USEC);
if (insn_processed < 100)
goto again; goto again;
else
return;
} }
addr = read_dword(dev, dev->dsp + 4); addr = read_dword(dev, dev->dsp + 4);
ncr53c810_log("SCRIPTS dsp=%08x opcode %08x arg %08x\n", dev->dsp, insn, addr); ncr53c810_log("SCRIPTS dsp=%08x opcode %08x arg %08x\n", dev->dsp, insn, addr);
@@ -957,7 +969,6 @@ again:
if (dev->sist1 & NCR_SIST1_STO) { if (dev->sist1 & NCR_SIST1_STO) {
ncr53c810_log("Delayed select timeout\n"); ncr53c810_log("Delayed select timeout\n");
dev->sstop = 1; dev->sstop = 1;
dev->timer_period = dev->timer_enabled = 0;
break; break;
} }
ncr53c810_log("Block Move DBC=%d\n", dev->dbc); ncr53c810_log("Block Move DBC=%d\n", dev->dbc);
@@ -1002,9 +1013,18 @@ again:
break; break;
case PHASE_CMD: case PHASE_CMD:
ncr53c810_log("Command Phase\n"); ncr53c810_log("Command Phase\n");
ncr53c810_do_command(dev, dev->sdid); c = ncr53c810_do_command(dev, dev->sdid);
if (!c || dev->sstop || dev->waiting || ((dev->sstat1 & 0x7) == PHASE_ST))
break;
dev->dfifo = dev->dbc & 0xff; dev->dfifo = dev->dbc & 0xff;
dev->ctest5 = (dev->ctest5 & 0xfc) | ((dev->dbc >> 8) & 3); dev->ctest5 = (dev->ctest5 & 0xfc) | ((dev->dbc >> 8) & 3);
dev->timer_period += (40LL * TIMER_USEC);
if (dev->dcntl & NCR_DCNTL_SSM)
ncr53c810_script_dma_interrupt(dev, NCR_DSTAT_SSI);
return; return;
case PHASE_ST: case PHASE_ST:
ncr53c810_log("Status Phase\n"); ncr53c810_log("Status Phase\n");
@@ -1177,7 +1197,6 @@ again:
if (dev->sist1 & NCR_SIST1_STO) { if (dev->sist1 & NCR_SIST1_STO) {
ncr53c810_log("Delayed select timeout\n"); ncr53c810_log("Delayed select timeout\n");
dev->sstop = 1; dev->sstop = 1;
dev->timer_period = dev->timer_enabled = 0;
break; break;
} }
cond = jmp = (insn & (1 << 19)) != 0; cond = jmp = (insn & (1 << 19)) != 0;
@@ -1269,6 +1288,8 @@ again:
ncr53c810_log("%02X: Unknown command\n", (uint8_t) (insn >> 30)); ncr53c810_log("%02X: Unknown command\n", (uint8_t) (insn >> 30));
} }
dev->timer_period += (40LL * TIMER_USEC);
ncr53c810_log("instructions processed %i\n", insn_processed); ncr53c810_log("instructions processed %i\n", insn_processed);
if (insn_processed > 10000 && !dev->waiting) { if (insn_processed > 10000 && !dev->waiting) {
/* Some windows drivers make the device spin waiting for a memory /* Some windows drivers make the device spin waiting for a memory
@@ -1304,7 +1325,8 @@ again:
static void static void
ncr53c810_execute_script(ncr53c810_t *dev) ncr53c810_execute_script(ncr53c810_t *dev)
{ {
dev->timer_period = 10LL * TIMER_USEC; dev->sstop = 0;
dev->timer_period = 40LL * TIMER_USEC;
dev->timer_enabled = 1; dev->timer_enabled = 1;
} }
@@ -1315,18 +1337,18 @@ ncr53c810_callback(void *p)
ncr53c810_t *dev = (ncr53c810_t *) p; ncr53c810_t *dev = (ncr53c810_t *) p;
dev->timer_period = 0; dev->timer_period = 0;
if (!dev->waiting) if (!dev->sstop) {
if (dev->waiting)
dev->timer_period = 40LL * TIMER_USEC;
else
ncr53c810_process_script(dev); ncr53c810_process_script(dev);
}
if (dev->sstop) { if (dev->sstop) {
dev->timer_period = 0;
dev->timer_enabled = 0; dev->timer_enabled = 0;
return; dev->timer_period = 0;
} else } else
dev->timer_enabled = 1; dev->timer_enabled = 1;
if (dev->timer_period == 0)
dev->timer_period = 50LL * TIMER_USEC;
} }