--- lsi53c895a.c 2008-01-07 04:38:42.000000000 +0900 +++ /home/craig/tmp/qemu-0.9.1/hw/lsi53c895a.c 2008-10-30 00:10:40.000000000 +0900 @@ -14,8 +14,8 @@ #include "pci.h" #include "scsi-disk.h" -//#define DEBUG_LSI -//#define DEBUG_LSI_REG +#define DEBUG_LSI +#define DEBUG_LSI_REG #ifdef DEBUG_LSI #define DPRINTF(fmt, args...) \ @@ -209,6 +209,7 @@ uint8_t mbox0; uint8_t mbox1; uint8_t dfifo; + uint8_t ctest2; /* Only bit 3 used for PCICIE flag */ uint8_t ctest3; uint8_t ctest4; uint8_t ctest5; @@ -280,6 +281,7 @@ s->mbox0 = 0; s->mbox1 = 0; s->dfifo = 0; + s->ctest2 = 0; /* See comment on declaration */ s->ctest3 = 0; s->ctest4 = 0; s->ctest5 = 0; @@ -1207,7 +1209,7 @@ DPRINTF("SCRIPTS execution stopped\n"); } -static uint8_t lsi_reg_readb(LSIState *s, int offset) +static uint8_t lsi_reg_readb_wrap(LSIState *s, int offset) { uint8_t tmp; #define CASE_GET_REG32(name, addr) \ @@ -1268,7 +1270,7 @@ case 0x19: /* CTEST1 */ return 0; case 0x1a: /* CTEST2 */ - tmp = LSI_CTEST2_DACK | LSI_CTEST2_CM; + tmp = s->ctest2 | LSI_CTEST2_DACK | LSI_CTEST2_CM; if (s->istat0 & LSI_ISTAT0_SIGP) { s->istat0 &= ~LSI_ISTAT0_SIGP; tmp |= LSI_CTEST2_SIGP; @@ -1316,8 +1318,12 @@ s->sist1 = 0; lsi_update_irq(s); return tmp; - case 0x47: /* GPCNTL0 */ - return 0x0f; + case 0x46: /* MACNTL */ + return 0xf0; + case 0x47: /* GPIO */ + /* GPIO doesn't make a great deal of sense on a virtual device. + * Drivers that access this seem happy with 0x0f. */ + return 0x0f; case 0x48: /* STIME0 */ return s->stime0; case 0x4a: /* RESPID0 */ @@ -1374,6 +1380,16 @@ #undef CASE_GET_REG32 } +static uint8_t lsi_reg_readb(LSIState *s, int offset) +{ + /* Register map: page 128 */ + /* Registers 5c-5f: scratch */ + uint8_t tmp; + tmp = lsi_reg_readb_wrap(s,offset); + DPRINTF(" Value: %02hhx\n", tmp); + return tmp; +} + static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val) { #define CASE_SET_REG32(name, addr) \ @@ -1385,6 +1401,7 @@ #ifdef DEBUG_LSI_REG DPRINTF("Write reg %x = %02x\n", offset, val); #endif + switch (offset) { case 0x00: /* SCNTL0 */ s->scntl0 = val; @@ -1429,6 +1446,20 @@ SCRIPTS register move instructions are. */ s->sfbr = val; break; + case 0x09: /* SOCL */ + /* OpenServer's slha driver sets this register, but it's not really meant + * to and we just ignore the effect. */ + DPRINTF("SOCL set to %02hhx, ignoring\n", val); + break; + case 0x0a: /* SSID */ + /* This register is read only, but OpenServer's slha driver writes 0 to it + * anyway so clearly the real hardware permits that. */ + if (val != 0x00) + BADF("Write to read-only register SSID (0x0a)"); + break; + case 0x0b: /* SBCL */ + /* OpenServer's slha driver likes to write to this register, though it's read only. */ + break; case 0x0c: case 0x0d: case 0x0e: case 0x0f: /* Linux writes to these readonly registers on startup. */ return; @@ -1458,6 +1489,13 @@ case 0x17: /* MBOX1 */ s->mbox1 = val; break; + case 0x1a: /* CTEST2 */ + /* Read only, except bit 3 (PCICIE) which may be written */ + /* The docs say writing to this all other bits must be 0, + * but the OpenServer driver doesn't follow that rule so we'll + * just mask the other bits' values. */ + s->ctest2 = val & LSI_CTEST2_PCICIE; + break; case 0x1b: /* CTEST3 */ s->ctest3 = val & 0x0f; break; @@ -1572,6 +1610,11 @@ CASE_SET_REG32(ia, 0xd4) CASE_SET_REG32(sbc, 0xd8) CASE_SET_REG32(csbc, 0xdc) + case 0xff: + /* SCO Openserver's slha driver writes to this for no apparent reason. + * The register is reserved. We ignore the write. */ + DPRINTF("WARNING: Write to reserved register 0xff\n"); + break; default: if (offset >= 0x5c && offset < 0xa0) { int n; @@ -1580,6 +1623,10 @@ shift = (offset & 3) * 8; s->scratch[n] &= ~(0xff << shift); s->scratch[n] |= (val & 0xff) << shift; + } else if (offset >= 0x100) { + /* This is outside the register mapping, but OpenServer's slha driver + * still writes to it... */ + DPRINTF("WARNING: Write %hx = %02hhx outside existing register space; ignoring.\n", offset, val); } else { BADF("Unhandled writeb 0x%x = 0x%x\n", offset, val); } @@ -1858,12 +1905,21 @@ return NULL; } + /* PCI Vendor ID (word) */ s->pci_dev.config[0x00] = 0x00; s->pci_dev.config[0x01] = 0x10; + /* PCI device ID (word) */ s->pci_dev.config[0x02] = 0x12; s->pci_dev.config[0x03] = 0x00; + /* PCI base class code */ s->pci_dev.config[0x0b] = 0x01; - s->pci_dev.config[0x3d] = 0x01; /* interrupt pin 1 */ + /* PCI subsystem ID */ + s->pci_dev.config[0x2e] = 0x00; + s->pci_dev.config[0x2f] = 0x10; + /* PCI latency timer = 255 */ + s->pci_dev.config[0x0d] = 0xff; + /* Interrupt pin 1 */ + s->pci_dev.config[0x3d] = 0x01; s->mmio_io_addr = cpu_register_io_memory(0, lsi_mmio_readfn, lsi_mmio_writefn, s);