* 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>
uint32_t script_ram[2048];
} LSIState;
+#define TYPE_LSI53C810 "lsi53c810"
#define TYPE_LSI53C895A "lsi53c895a"
#define LSI53C895A(obj) \
level, s->dstat, s->sist1, s->sist0);
last_level = level;
}
- qemu_set_irq(d->irq[0], level);
+ pci_set_irq(d, level);
if (!level && lsi_irq_on_rsl(s) && !(s->scntl1 & LSI_SCNTL1_CON)) {
DPRINTF("Handled IRQs & disconnected, looking for pending "
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)
{
/* 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;
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) {
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 */
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;
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);
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 */
case 0x17: /* MBOX1 */
s->mbox1 = val;
break;
+ case 0x18: /* CTEST0 */
+ /* nothing to do */
+ break;
case 0x1a: /* CTEST2 */
s->ctest2 = val & LSI_CTEST2_PCICIE;
break;
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);
}
"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);
.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)