From: Bernie Innocenti Date: Thu, 9 Jul 2026 09:37:39 +0000 (+0200) Subject: a4091: emulate 53C710 SCSI loopback pins X-Git-Url: https://gitweb.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=99ae54efe1e380150f9f36f402604363d1f98ca1;p=francis%2Fwinuae.git a4091: emulate 53C710 SCSI loopback pins The ncr7xx SCSI pin test drives the output latches and reads them back through the bus input registers in loopback mode. Model the A4091 loopback path for SBDL, SBCL, and SSTAT1, and add the missing SOCL write latch. SCNTL1.ADB now latches instead of aborting the setup write, allowing the loopback reads to observe the driven SODL and SOCL state. --- diff --git a/qemuvga/lsi53c710.cpp b/qemuvga/lsi53c710.cpp index b61eaf83..069f5fed 100644 --- a/qemuvga/lsi53c710.cpp +++ b/qemuvga/lsi53c710.cpp @@ -43,7 +43,7 @@ do { write_log("lsi_scsi: error: " fmt , ## __VA_ARGS__); assert(false);} while #define LSI_SCNTL0_TRG 0x01 #define LSI_SCNTL0_AAP 0x02 -#define LSI_SCNTL0_EPG 0x08 +#define LSI_SCNTL0_EPG 0x04 #define LSI_SCNTL0_EPC 0x08 #define LSI_SCNTL0_WATN 0x10, #define LSI_SCNTL0_START 0x20 @@ -142,6 +142,7 @@ do { write_log("lsi_scsi: error: " fmt , ## __VA_ARGS__); assert(false);} while #define LSI_CTEST2_DDIR 0x80 #define LSI_CTEST4_SFWR 0x08 +#define LSI_CTEST4_SLBE 0x10 #define LSI_CTEST5_BL2 0x04 #define LSI_CTEST5_DDIR 0x08 @@ -295,6 +296,11 @@ static uint8_t lsi_scsi_parity(uint8_t val, uint8_t scntl1) return parity; } +static bool lsi_scsi_loopback(LSIState710 *s) +{ + return (s->ctest4 & LSI_CTEST4_SLBE) && (s->scntl1 & LSI_SCNTL1_ADB); +} + static inline int lsi_irq_on_rsl(LSIState710 *s) { return 0; //return (s->sien0 & LSI_SIST0_RSL) && (s->scid & LSI_SCID_RRE); @@ -1683,7 +1689,15 @@ static uint8_t lsi_reg_readb2(LSIState710 *s, int offset) /* This is needed by the linux drivers. We currently only update it during the MSG IN phase. */ return s->sidl; + case 0x0a: /* SBDL */ + return lsi_scsi_loopback(s) ? s->sodl : 0; case 0xb: /* SBCL */ + if (lsi_scsi_loopback(s)) { + tmp = s->socl; + if (!(s->scntl0 & LSI_SCNTL0_TRG)) + tmp &= ~0x48; + return tmp; + } tmp = 0; if (s->scntl1 & LSI_SCNTL1_CON) { /* NetBSD 1.x checks for REQ */ @@ -1707,7 +1721,13 @@ static uint8_t lsi_reg_readb2(LSIState710 *s, int offset) lsi_update_irq(s); return tmp; case 0x0e: /* SSTAT1 */ - return s->sstat1; + tmp = s->sstat1 & ~0x03; + if (s->scntl1 & LSI_SCNTL1_RST) + tmp |= 0x02; + if (lsi_scsi_loopback(s) && (s->scntl0 & LSI_SCNTL0_EPG) && + lsi_scsi_parity(s->sodl, s->scntl1)) + tmp |= 0x01; + return tmp; case 0x0f: /* SSTAT2 */ return (s->sstat2 & 0x0f) | (s->scsi_fifo_count << 4); CASE_GET_REG32(dsa, 0x10) @@ -1817,9 +1837,8 @@ static void lsi_reg_writeb(LSIState710 *s, int offset, uint8_t val) break; case 0x01: /* SCNTL1 */ s->scntl1 = val; - if (val & LSI_SCNTL1_ADB) { - BADF("Immediate Arbritration not implemented\n"); - } + /* SCNTL1.ADB drives SODL/SOCL onto the bus; in loopback mode the + read handlers feed those latches back through SBDL/SBCL. */ if (val & LSI_SCNTL1_RST) { if (!(s->sstat0 & LSI_SSTAT0_RST)) { // qbus_reset_all(&s->bus.qbus); @@ -1847,6 +1866,9 @@ static void lsi_reg_writeb(LSIState710 *s, int offset, uint8_t val) s->scsi_fifo[s->scsi_fifo_count++] = (parity << 8) | val; } break; + case 0x07: /* SOCL */ + s->socl = val; + break; case 0x0b: /* SBCL */ lsi_set_phase (s, val & PHASE_MASK); break;