From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1KvD7y-0001sP-Ux for qemu-devel@nongnu.org; Wed, 29 Oct 2008 11:38:35 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1KvD7x-0001rE-3D for qemu-devel@nongnu.org; Wed, 29 Oct 2008 11:38:34 -0400 Received: from [199.232.76.173] (port=48015 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1KvD7w-0001qx-RB for qemu-devel@nongnu.org; Wed, 29 Oct 2008 11:38:32 -0400 Received: from www.postnewspapers.com.au ([202.61.230.242]:60968) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1KvD7u-0001Yq-VP for qemu-devel@nongnu.org; Wed, 29 Oct 2008 11:38:32 -0400 Received: from mail.postnewspapers.com.au (202-89-185-120.static.dsl.amnet.net.au [202.89.185.120]) by www.postnewspapers.com.au (Postfix) with ESMTP id 7C3065C17E for ; Thu, 30 Oct 2008 00:38:14 +0900 (WST) Received: from [10.0.0.53] (wallace.localnet [10.0.0.53]) by mail.postnewspapers.com.au (Postfix) with ESMTP id 641321E0434 for ; Thu, 30 Oct 2008 00:38:14 +0900 (WST) Message-ID: <49088366.8080900@postnewspapers.com.au> Date: Thu, 30 Oct 2008 00:38:14 +0900 From: Craig Ringer MIME-Version: 1.0 Subject: Re: [Qemu-devel] LSI53C895A, IDE HDD detection under SCO OpenServer 5.0.5 References: <49082BF8.2030508@postnewspapers.com.au> In-Reply-To: <49082BF8.2030508@postnewspapers.com.au> Content-Type: multipart/mixed; boundary="------------030106000903020809010509" Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org This is a multi-part message in MIME format. --------------030106000903020809010509 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Hi all Sorry to reply to myself, but thanks to an incredibly useful tip on the IRC channel that the controller has public documentation, I've got it detecting under OpenServer 5.0.5. The OpenServer kernel panics shortly afterwards, so there's clearly still something not right, but it's at least finding the controller and talking to it to a reasonable degree. I've attached a diff showing the changes I ended up making. It's not intended as a patch to be applied to qemu, at least not at this point, but I thought it might be informative and useful. I haven't removed the uncommenting of the LSI_DEBUG and LSI_DEBUG_REG flags, nor the wrapping of lsi_reg_readb with a function that prints the return values, so it's really raw. The initial problem, by the way, was that the driver didn't like the controller reporting a PCI latency setting of 0. It seemed happy enough with 255, which is what most BIOSes seem to set according to various lspci results from real hardware that I found on the 'net. After that was changed the driver started accessing the device registers via the memory mapping. It pokes all sorts of registers that the virtual hardware doesn't currently implement, so there was a long and repetitive compile/build/test cycle to identfy and implement each one that was missing. I'm far from sure I'm doing the right thing with all of them, especially as the driver does things it probably shouldn't, such as: - Writing to several read-only registers - Writing to a register where only bit 3 may be set with the value 0x51 - Writing to the reserved register 0xff; and - Running a script that writes to registers 0x100 - 0x105, though they don't appear to exist. This last one looks like it might well be a bug in the virtual hardware. At this point it seems to be doing quite a bit of communication with the controller before infinitely looping on a SCRIPTS invocation. lsi_scsi: SCRIPTS dsp=f0010003 opcode ffffffff arg ffffffff lsi_scsi: Load reg 0xff size 7 addr 0xffffffff = 00ff5397 lsi_scsi: SCRIPTS dsp=f001000b opcode ffffffff arg ffffffff lsi_scsi: Load reg 0xff size 7 addr 0xffffffff = 00ff5397 lsi_scsi: SCRIPTS dsp=f0010013 opcode ffffffff arg ffffffff lsi_scsi: Load reg 0xff size 7 addr 0xffffffff = 00ff5397 lsi_scsi: SCRIPTS dsp=f001001b opcode ffffffff arg ffffffff lsi_scsi: Load reg 0xff size 7 addr 0xffffffff = 00ff5397 lsi_scsi: SCRIPTS dsp=f0010023 opcode ffffffff arg ffffffff lsi_scsi: Load reg 0xff size 7 addr 0xffffffff = 00ff5397 lsi_scsi: SCRIPTS dsp=f001002b opcode ffffffff arg ffffffff lsi_scsi: Load reg 0xff size 7 addr 0xffffffff = 00ff5397 ... and so on ... so it's presumably scanning for something or otherwise expecting one of these calls to produce a different result than it does. Any tips would be appreciated. I just thought I'd put this out in public view in case I don't manage to get it all sorted out and someone else is in this delightful position later. No idea about the IDE detection yet, I haven't had a chance to look at what it's doing there. -- Craig Ringer --------------030106000903020809010509 Content-Type: text/x-diff; name="lsi_openserver_diff1.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="lsi_openserver_diff1.diff" --- 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); --------------030106000903020809010509--