diff options
Diffstat (limited to 'hw/scsi/lsi53c895a.c')
-rw-r--r-- | hw/scsi/lsi53c895a.c | 51 |
1 files changed, 33 insertions, 18 deletions
diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c index 0e51b94748..cb30414849 100644 --- a/hw/scsi/lsi53c895a.c +++ b/hw/scsi/lsi53c895a.c @@ -7,8 +7,11 @@ * This code is licensed under the LGPL. */ -/* ??? Need to check if the {read,write}[wl] routines work properly on - big-endian targets. */ +/* Note: + * LSI53C810 emulation is incorrect, in the sense that it supports + * features added in later evolutions. This should not be a problem, + * as well-behaved operating systems will not try to use them. + */ #include <assert.h> @@ -278,6 +281,7 @@ typedef struct { uint32_t script_ram[2048]; } LSIState; +#define TYPE_LSI53C810 "lsi53c810" #define TYPE_LSI53C895A "lsi53c895a" #define LSI53C895A(obj) \ @@ -998,12 +1002,6 @@ bad: s->msg_action = 0; } -/* Sign extend a 24-bit value. */ -static inline int32_t sxt24(int32_t n) -{ - return (n << 8) >> 8; -} - #define LSI_BUF_SIZE 4096 static void lsi_memcpy(LSIState *s, uint32_t dest, uint32_t src, int count) { @@ -1083,7 +1081,7 @@ again: /* Table indirect addressing. */ /* 32-bit Table indirect */ - offset = sxt24(addr); + offset = sextract32(addr, 0, 24); pci_dma_read(pci_dev, s->dsa + offset, buf, 8); /* byte count is stored in bits 0:23 only */ s->dbc = cpu_to_le32(buf[0]) & 0xffffff; @@ -1183,13 +1181,13 @@ again: uint32_t id; if (insn & (1 << 25)) { - id = read_dword(s, s->dsa + sxt24(insn)); + id = read_dword(s, s->dsa + sextract32(insn, 0, 24)); } else { id = insn; } id = (id >> 16) & 0xf; if (insn & (1 << 26)) { - addr = s->dsp + sxt24(addr); + addr = s->dsp + sextract32(addr, 0, 24); } s->dnad = addr; switch (opcode) { @@ -1385,7 +1383,7 @@ again: if (cond == jmp) { if (insn & (1 << 23)) { /* Relative address. */ - addr = s->dsp + sxt24(addr); + addr = s->dsp + sextract32(addr, 0, 24); } switch ((insn >> 27) & 7) { case 0: /* Jump */ @@ -1438,7 +1436,7 @@ again: int i; if (insn & (1 << 28)) { - addr = s->dsa + sxt24(addr); + addr = s->dsa + sextract32(addr, 0, 24); } n = (insn & 7); reg = (insn >> 16) & 0xff; @@ -1521,7 +1519,7 @@ static uint8_t lsi_reg_readb(LSIState *s, int offset) used for diagnostics, so should be ok. */ return 0; case 0xc: /* DSTAT */ - tmp = s->dstat | 0x80; + tmp = s->dstat | LSI_DSTAT_DFE; if ((s->istat0 & LSI_ISTAT0_INTF) == 0) s->dstat = 0; lsi_update_irq(s); @@ -1705,8 +1703,9 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val) s->sxfer = val; break; case 0x06: /* SDID */ - if ((val & 0xf) != (s->ssid & 0xf)) + if ((s->ssid & 0x80) && (val & 0xf) != (s->ssid & 0xf)) { BADF("Destination ID does not match SSID\n"); + } s->sdid = val & 0xf; break; case 0x07: /* GPREG0 */ @@ -1748,6 +1747,9 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val) case 0x17: /* MBOX1 */ s->mbox1 = val; break; + case 0x18: /* CTEST0 */ + /* nothing to do */ + break; case 0x1a: /* CTEST2 */ s->ctest2 = val & LSI_CTEST2_PCICIE; break; @@ -1876,8 +1878,7 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val) int shift; n = (offset - 0x58) >> 2; shift = (offset & 3) * 8; - s->scratch[n] &= ~(0xff << shift); - s->scratch[n] |= (val & 0xff) << shift; + s->scratch[n] = deposit32(s->scratch[n], shift, 8, val); } else { BADF("Unhandled writeb 0x%x = 0x%x\n", offset, val); } @@ -2113,7 +2114,7 @@ static int lsi_scsi_init(PCIDevice *dev) "lsi-io", 256); pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io_io); - pci_register_bar(dev, 1, 0, &s->mmio_io); + pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mmio_io); pci_register_bar(dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->ram_io); QTAILQ_INIT(&s->queue); @@ -2151,9 +2152,23 @@ static const TypeInfo lsi_info = { .class_init = lsi_class_init, }; +static void lsi53c810_class_init(ObjectClass *klass, void *data) +{ + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + + k->device_id = PCI_DEVICE_ID_LSI_53C810; +} + +static TypeInfo lsi53c810_info = { + .name = TYPE_LSI53C810, + .parent = TYPE_LSI53C895A, + .class_init = lsi53c810_class_init, +}; + static void lsi53c895a_register_types(void) { type_register_static(&lsi_info); + type_register_static(&lsi53c810_info); } type_init(lsi53c895a_register_types) |