Commit 9167a69a816b8956d62da628b5b4dc87674647d6

Authored by balrog
1 parent c3b972c3

Implement LSI53C895A quirks exposed by OpenServer (Justin Chevrier).

After going through the debug log and scratching my head for quite some
time. I found the following:

The problem was with this block move:

lsi_scsi: SCRIPTS dsp=0fae8e50 opcode 01000028 arg 00f63c40
lsi_scsi: DMA addr=0x00f63c40 len=36

The number of bytes to be transferred (len) should be 40 which corresponds
to the block transfer of length 0x28 (from opcode 01000028). Instead we
have a length of 36 (0x24). The code responsible for this is (in
'lsi_do_dma'):

if (count > s->current_dma_len)
   count = s->current_dma_len;

Basically we're overwriting the length 40 with the value 36 which I
think we just left over in that variable from an earlier transfer. In my
patch below I initialize s->current_dma_len to s->dbc before we begin
the DMA transfer during Data In phase.

The attached patch gets Openserver 5.0.5 past the hardware detection
(and it lists the hard drive to boot, woohoo). It appears to stop a
little while later (doesn't seem SCSI related), but it's been so long since
I've booted Openserver I'm not sure what's supposted to happen after the HW
detection using the boot/root disks.

Props go to Craig Ringer for the initial post and the code that he posted
some of which is in this patch.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5706 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 22 additions and 2 deletions
hw/lsi53c895a.c
... ... @@ -209,6 +209,7 @@ typedef struct {
209 209 uint8_t mbox0;
210 210 uint8_t mbox1;
211 211 uint8_t dfifo;
  212 + uint8_t ctest2;
212 213 uint8_t ctest3;
213 214 uint8_t ctest4;
214 215 uint8_t ctest5;
... ... @@ -280,6 +281,7 @@ static void lsi_soft_reset(LSIState *s)
280 281 s->mbox0 = 0;
281 282 s->mbox1 = 0;
282 283 s->dfifo = 0;
  284 + s->ctest2 = 0;
283 285 s->ctest3 = 0;
284 286 s->ctest4 = 0;
285 287 s->ctest5 = 0;
... ... @@ -890,6 +892,7 @@ again:
890 892 break;
891 893 case PHASE_DI:
892 894 s->waiting = 2;
  895 + s->current_dma_len = s->dbc;
893 896 lsi_do_dma(s, 0);
894 897 if (s->waiting)
895 898 s->waiting = 3;
... ... @@ -1279,7 +1282,7 @@ static uint8_t lsi_reg_readb(LSIState *s, int offset)
1279 1282 case 0x19: /* CTEST1 */
1280 1283 return 0;
1281 1284 case 0x1a: /* CTEST2 */
1282   - tmp = LSI_CTEST2_DACK | LSI_CTEST2_CM;
  1285 + tmp = s->ctest2 | LSI_CTEST2_DACK | LSI_CTEST2_CM;
1283 1286 if (s->istat0 & LSI_ISTAT0_SIGP) {
1284 1287 s->istat0 &= ~LSI_ISTAT0_SIGP;
1285 1288 tmp |= LSI_CTEST2_SIGP;
... ... @@ -1327,6 +1330,8 @@ static uint8_t lsi_reg_readb(LSIState *s, int offset)
1327 1330 s->sist1 = 0;
1328 1331 lsi_update_irq(s);
1329 1332 return tmp;
  1333 + case 0x46: /* MACNTL */
  1334 + return 0x0f;
1330 1335 case 0x47: /* GPCNTL0 */
1331 1336 return 0x0f;
1332 1337 case 0x48: /* STIME0 */
... ... @@ -1440,6 +1445,9 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
1440 1445 SCRIPTS register move instructions are. */
1441 1446 s->sfbr = val;
1442 1447 break;
  1448 + case 0x0a: case 0x0b:
  1449 + /* Openserver writes to these readonly registers on startup */
  1450 + return;
1443 1451 case 0x0c: case 0x0d: case 0x0e: case 0x0f:
1444 1452 /* Linux writes to these readonly registers on startup. */
1445 1453 return;
... ... @@ -1469,6 +1477,9 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
1469 1477 case 0x17: /* MBOX1 */
1470 1478 s->mbox1 = val;
1471 1479 break;
  1480 + case 0x1a: /* CTEST2 */
  1481 + s->ctest2 = val & LSI_CTEST2_PCICIE;
  1482 + break;
1472 1483 case 0x1b: /* CTEST3 */
1473 1484 s->ctest3 = val & 0x0f;
1474 1485 break;
... ... @@ -1869,12 +1880,21 @@ void *lsi_scsi_init(PCIBus *bus, int devfn)
1869 1880 return NULL;
1870 1881 }
1871 1882  
  1883 + /* PCI Vendor ID (word) */
1872 1884 s->pci_dev.config[0x00] = 0x00;
1873 1885 s->pci_dev.config[0x01] = 0x10;
  1886 + /* PCI device ID (word) */
1874 1887 s->pci_dev.config[0x02] = 0x12;
1875 1888 s->pci_dev.config[0x03] = 0x00;
  1889 + /* PCI base class code */
1876 1890 s->pci_dev.config[0x0b] = 0x01;
1877   - s->pci_dev.config[0x3d] = 0x01; /* interrupt pin 1 */
  1891 + /* PCI subsystem ID */
  1892 + s->pci_dev.config[0x2e] = 0x00;
  1893 + s->pci_dev.config[0x2f] = 0x10;
  1894 + /* PCI latency timer = 255 */
  1895 + s->pci_dev.config[0x0d] = 0xff;
  1896 + /* Interrupt pin 1 */
  1897 + s->pci_dev.config[0x3d] = 0x01;
1878 1898  
1879 1899 s->mmio_io_addr = cpu_register_io_memory(0, lsi_mmio_readfn,
1880 1900 lsi_mmio_writefn, s);
... ...