]> git.proxmox.com Git - mirror_qemu.git/blobdiff - hw/lsi53c895a.c
qdev: add return value to init() callbacks.
[mirror_qemu.git] / hw / lsi53c895a.c
index 36ee28e7140912058fecb7e27a350262fa86a691..b4865582ece80402cd888c8ae7910842e03189f7 100644 (file)
@@ -10,6 +10,8 @@
 /* ??? Need to check if the {read,write}[wl] routines work properly on
    big-endian targets.  */
 
+#include <assert.h>                             \
+
 #include "hw.h"
 #include "pci.h"
 #include "scsi-disk.h"
 //#define DEBUG_LSI_REG
 
 #ifdef DEBUG_LSI
-#define DPRINTF(fmt, args...) \
-do { printf("lsi_scsi: " fmt , ##args); } while (0)
-#define BADF(fmt, args...) \
-do { fprintf(stderr, "lsi_scsi: error: " fmt , ##args); exit(1);} while (0)
+#define DPRINTF(fmt, ...) \
+do { printf("lsi_scsi: " fmt , ## __VA_ARGS__); } while (0)
+#define BADF(fmt, ...) \
+do { fprintf(stderr, "lsi_scsi: error: " fmt , ## __VA_ARGS__); exit(1);} while (0)
 #else
-#define DPRINTF(fmt, args...) do {} while(0)
-#define BADF(fmt, args...) \
-do { fprintf(stderr, "lsi_scsi: error: " fmt , ##args);} while (0)
+#define DPRINTF(fmt, ...) do {} while(0)
+#define BADF(fmt, ...) \
+do { fprintf(stderr, "lsi_scsi: error: " fmt , ## __VA_ARGS__);} while (0)
 #endif
 
 #define LSI_SCNTL0_TRG    0x01
@@ -262,6 +264,7 @@ typedef struct {
     uint32_t sbc;
     uint32_t csbc;
     uint32_t scratch[18]; /* SCRATCHA-SCRATCHR */
+    uint8_t sbr;
 
     /* Script ram is stored as 32-bit words in host byteorder.  */
     uint32_t script_ram[2048];
@@ -330,6 +333,7 @@ static void lsi_soft_reset(LSIState *s)
     s->ia = 0;
     s->sbc = 0;
     s->csbc = 0;
+    s->sbr = 0;
 }
 
 static int lsi_dma_40bit(LSIState *s)
@@ -841,14 +845,15 @@ 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)
 {
     int n;
-    uint8_t buf[TARGET_PAGE_SIZE];
+    uint8_t buf[LSI_BUF_SIZE];
 
     DPRINTF("memcpy dest 0x%08x src 0x%08x count %d\n", dest, src, count);
     while (count) {
-        n = (count > TARGET_PAGE_SIZE) ? TARGET_PAGE_SIZE : count;
+        n = (count > LSI_BUF_SIZE) ? LSI_BUF_SIZE : count;
         cpu_physical_memory_read(src, buf, n);
         cpu_physical_memory_write(dest, buf, n);
         src += n;
@@ -1369,6 +1374,8 @@ static uint8_t lsi_reg_readb(LSIState *s, int offset)
     CASE_GET_REG32(dsa, 0x10)
     case 0x14: /* ISTAT0 */
         return s->istat0;
+    case 0x15: /* ISTAT1 */
+        return s->istat1;
     case 0x16: /* MBOX0 */
         return s->mbox0;
     case 0x17: /* MBOX1 */
@@ -1398,6 +1405,7 @@ static uint8_t lsi_reg_readb(LSIState *s, int offset)
     CASE_GET_REG24(dbc, 0x24)
     case 0x27: /* DCMD */
         return s->dcmd;
+    CASE_GET_REG32(dnad, 0x28)
     CASE_GET_REG32(dsp, 0x2c)
     CASE_GET_REG32(dsps, 0x30)
     CASE_GET_REG32(scratch[0], 0x34)
@@ -1405,6 +1413,8 @@ static uint8_t lsi_reg_readb(LSIState *s, int offset)
         return s->dmode;
     case 0x39: /* DIEN */
         return s->dien;
+    case 0x3a: /* SBR */
+        return s->sbr;
     case 0x3b: /* DCNTL */
         return s->dcntl;
     case 0x40: /* SIEN0 */
@@ -1484,6 +1494,11 @@ static uint8_t lsi_reg_readb(LSIState *s, int offset)
 
 static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
 {
+#define CASE_SET_REG24(name, addr) \
+    case addr    : s->name &= 0xffffff00; s->name |= val;       break; \
+    case addr + 1: s->name &= 0xffff00ff; s->name |= val << 8;  break; \
+    case addr + 2: s->name &= 0xff00ffff; s->name |= val << 16; break;
+
 #define CASE_SET_REG32(name, addr) \
     case addr    : s->name &= 0xffffff00; s->name |= val;       break; \
     case addr + 1: s->name &= 0xffff00ff; s->name |= val << 8;  break; \
@@ -1588,6 +1603,8 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
         }
         s->ctest5 = val;
         break;
+    CASE_SET_REG24(dbc, 0x24)
+    CASE_SET_REG32(dnad, 0x28)
     case 0x2c: /* DSP[0:7] */
         s->dsp &= 0xffffff00;
         s->dsp |= val;
@@ -1619,6 +1636,9 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
         s->dien = val;
         lsi_update_irq(s);
         break;
+    case 0x3a: /* SBR */
+        s->sbr = val;
+        break;
     case 0x3b: /* DCNTL */
         s->dcntl = val & ~(LSI_DCNTL_PFF | LSI_DCNTL_STD);
         if ((val & LSI_DCNTL_STD) && (s->istat1 & LSI_ISTAT1_SRUN) == 0)
@@ -1698,6 +1718,7 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val)
             BADF("Unhandled writeb 0x%x = 0x%x\n", offset, val);
         }
     }
+#undef CASE_SET_REG24
 #undef CASE_SET_REG32
 }
 
@@ -1758,13 +1779,13 @@ static uint32_t lsi_mmio_readl(void *opaque, target_phys_addr_t addr)
     return val;
 }
 
-static CPUReadMemoryFunc *lsi_mmio_readfn[3] = {
+static CPUReadMemoryFunc * const lsi_mmio_readfn[3] = {
     lsi_mmio_readb,
     lsi_mmio_readw,
     lsi_mmio_readl,
 };
 
-static CPUWriteMemoryFunc *lsi_mmio_writefn[3] = {
+static CPUWriteMemoryFunc * const lsi_mmio_writefn[3] = {
     lsi_mmio_writeb,
     lsi_mmio_writew,
     lsi_mmio_writel,
@@ -1839,13 +1860,13 @@ static uint32_t lsi_ram_readl(void *opaque, target_phys_addr_t addr)
     return le32_to_cpu(s->script_ram[addr >> 2]);
 }
 
-static CPUReadMemoryFunc *lsi_ram_readfn[3] = {
+static CPUReadMemoryFunc * const lsi_ram_readfn[3] = {
     lsi_ram_readb,
     lsi_ram_readw,
     lsi_ram_readl,
 };
 
-static CPUWriteMemoryFunc *lsi_ram_writefn[3] = {
+static CPUWriteMemoryFunc * const lsi_ram_writefn[3] = {
     lsi_ram_writeb,
     lsi_ram_writew,
     lsi_ram_writel,
@@ -1937,9 +1958,9 @@ static void lsi_mmio_mapfunc(PCIDevice *pci_dev, int region_num,
     cpu_register_physical_memory(addr + 0, 0x400, s->mmio_io_addr);
 }
 
-void lsi_scsi_attach(void *opaque, BlockDriverState *bd, int id)
+void lsi_scsi_attach(DeviceState *host, BlockDriverState *bd, int id)
 {
-    LSIState *s = (LSIState *)opaque;
+    LSIState *s = (LSIState *)host;
 
     if (id < 0) {
         for (id = 0; id < LSI_MAX_DEVS; id++) {
@@ -1962,6 +1983,174 @@ void lsi_scsi_attach(void *opaque, BlockDriverState *bd, int id)
     bd->private = &s->pci_dev;
 }
 
+static void lsi_scsi_save(QEMUFile *f, void *opaque)
+{
+    LSIState *s = opaque;
+
+    assert(s->dma_buf == NULL);
+    assert(s->current_dma_len == 0);
+    assert(s->active_commands == 0);
+
+    pci_device_save(&s->pci_dev, f);
+
+    qemu_put_sbe32s(f, &s->carry);
+    qemu_put_sbe32s(f, &s->sense);
+    qemu_put_sbe32s(f, &s->msg_action);
+    qemu_put_sbe32s(f, &s->msg_len);
+    qemu_put_buffer(f, s->msg, sizeof (s->msg));
+    qemu_put_sbe32s(f, &s->waiting);
+
+    qemu_put_be32s(f, &s->dsa);
+    qemu_put_be32s(f, &s->temp);
+    qemu_put_be32s(f, &s->dnad);
+    qemu_put_be32s(f, &s->dbc);
+    qemu_put_8s(f, &s->istat0);
+    qemu_put_8s(f, &s->istat1);
+    qemu_put_8s(f, &s->dcmd);
+    qemu_put_8s(f, &s->dstat);
+    qemu_put_8s(f, &s->dien);
+    qemu_put_8s(f, &s->sist0);
+    qemu_put_8s(f, &s->sist1);
+    qemu_put_8s(f, &s->sien0);
+    qemu_put_8s(f, &s->sien1);
+    qemu_put_8s(f, &s->mbox0);
+    qemu_put_8s(f, &s->mbox1);
+    qemu_put_8s(f, &s->dfifo);
+    qemu_put_8s(f, &s->ctest2);
+    qemu_put_8s(f, &s->ctest3);
+    qemu_put_8s(f, &s->ctest4);
+    qemu_put_8s(f, &s->ctest5);
+    qemu_put_8s(f, &s->ccntl0);
+    qemu_put_8s(f, &s->ccntl1);
+    qemu_put_be32s(f, &s->dsp);
+    qemu_put_be32s(f, &s->dsps);
+    qemu_put_8s(f, &s->dmode);
+    qemu_put_8s(f, &s->dcntl);
+    qemu_put_8s(f, &s->scntl0);
+    qemu_put_8s(f, &s->scntl1);
+    qemu_put_8s(f, &s->scntl2);
+    qemu_put_8s(f, &s->scntl3);
+    qemu_put_8s(f, &s->sstat0);
+    qemu_put_8s(f, &s->sstat1);
+    qemu_put_8s(f, &s->scid);
+    qemu_put_8s(f, &s->sxfer);
+    qemu_put_8s(f, &s->socl);
+    qemu_put_8s(f, &s->sdid);
+    qemu_put_8s(f, &s->ssid);
+    qemu_put_8s(f, &s->sfbr);
+    qemu_put_8s(f, &s->stest1);
+    qemu_put_8s(f, &s->stest2);
+    qemu_put_8s(f, &s->stest3);
+    qemu_put_8s(f, &s->sidl);
+    qemu_put_8s(f, &s->stime0);
+    qemu_put_8s(f, &s->respid0);
+    qemu_put_8s(f, &s->respid1);
+    qemu_put_be32s(f, &s->mmrs);
+    qemu_put_be32s(f, &s->mmws);
+    qemu_put_be32s(f, &s->sfs);
+    qemu_put_be32s(f, &s->drs);
+    qemu_put_be32s(f, &s->sbms);
+    qemu_put_be32s(f, &s->dbms);
+    qemu_put_be32s(f, &s->dnad64);
+    qemu_put_be32s(f, &s->pmjad1);
+    qemu_put_be32s(f, &s->pmjad2);
+    qemu_put_be32s(f, &s->rbc);
+    qemu_put_be32s(f, &s->ua);
+    qemu_put_be32s(f, &s->ia);
+    qemu_put_be32s(f, &s->sbc);
+    qemu_put_be32s(f, &s->csbc);
+    qemu_put_buffer(f, (uint8_t *)s->scratch, sizeof (s->scratch));
+    qemu_put_8s(f, &s->sbr);
+
+    qemu_put_buffer(f, (uint8_t *)s->script_ram, sizeof (s->script_ram));
+}
+
+static int lsi_scsi_load(QEMUFile *f, void *opaque, int version_id)
+{
+    LSIState *s = opaque;
+    int ret;
+
+    if (version_id > 0) {
+        return -EINVAL;
+    }
+
+    if ((ret = pci_device_load(&s->pci_dev, f)) < 0)
+        return ret;
+
+    qemu_get_sbe32s(f, &s->carry);
+    qemu_get_sbe32s(f, &s->sense);
+    qemu_get_sbe32s(f, &s->msg_action);
+    qemu_get_sbe32s(f, &s->msg_len);
+    qemu_get_buffer(f, s->msg, sizeof (s->msg));
+    qemu_get_sbe32s(f, &s->waiting);
+
+    qemu_get_be32s(f, &s->dsa);
+    qemu_get_be32s(f, &s->temp);
+    qemu_get_be32s(f, &s->dnad);
+    qemu_get_be32s(f, &s->dbc);
+    qemu_get_8s(f, &s->istat0);
+    qemu_get_8s(f, &s->istat1);
+    qemu_get_8s(f, &s->dcmd);
+    qemu_get_8s(f, &s->dstat);
+    qemu_get_8s(f, &s->dien);
+    qemu_get_8s(f, &s->sist0);
+    qemu_get_8s(f, &s->sist1);
+    qemu_get_8s(f, &s->sien0);
+    qemu_get_8s(f, &s->sien1);
+    qemu_get_8s(f, &s->mbox0);
+    qemu_get_8s(f, &s->mbox1);
+    qemu_get_8s(f, &s->dfifo);
+    qemu_get_8s(f, &s->ctest2);
+    qemu_get_8s(f, &s->ctest3);
+    qemu_get_8s(f, &s->ctest4);
+    qemu_get_8s(f, &s->ctest5);
+    qemu_get_8s(f, &s->ccntl0);
+    qemu_get_8s(f, &s->ccntl1);
+    qemu_get_be32s(f, &s->dsp);
+    qemu_get_be32s(f, &s->dsps);
+    qemu_get_8s(f, &s->dmode);
+    qemu_get_8s(f, &s->dcntl);
+    qemu_get_8s(f, &s->scntl0);
+    qemu_get_8s(f, &s->scntl1);
+    qemu_get_8s(f, &s->scntl2);
+    qemu_get_8s(f, &s->scntl3);
+    qemu_get_8s(f, &s->sstat0);
+    qemu_get_8s(f, &s->sstat1);
+    qemu_get_8s(f, &s->scid);
+    qemu_get_8s(f, &s->sxfer);
+    qemu_get_8s(f, &s->socl);
+    qemu_get_8s(f, &s->sdid);
+    qemu_get_8s(f, &s->ssid);
+    qemu_get_8s(f, &s->sfbr);
+    qemu_get_8s(f, &s->stest1);
+    qemu_get_8s(f, &s->stest2);
+    qemu_get_8s(f, &s->stest3);
+    qemu_get_8s(f, &s->sidl);
+    qemu_get_8s(f, &s->stime0);
+    qemu_get_8s(f, &s->respid0);
+    qemu_get_8s(f, &s->respid1);
+    qemu_get_be32s(f, &s->mmrs);
+    qemu_get_be32s(f, &s->mmws);
+    qemu_get_be32s(f, &s->sfs);
+    qemu_get_be32s(f, &s->drs);
+    qemu_get_be32s(f, &s->sbms);
+    qemu_get_be32s(f, &s->dbms);
+    qemu_get_be32s(f, &s->dnad64);
+    qemu_get_be32s(f, &s->pmjad1);
+    qemu_get_be32s(f, &s->pmjad2);
+    qemu_get_be32s(f, &s->rbc);
+    qemu_get_be32s(f, &s->ua);
+    qemu_get_be32s(f, &s->ia);
+    qemu_get_be32s(f, &s->sbc);
+    qemu_get_be32s(f, &s->csbc);
+    qemu_get_buffer(f, (uint8_t *)s->scratch, sizeof (s->scratch));
+    qemu_get_8s(f, &s->sbr);
+
+    qemu_get_buffer(f, (uint8_t *)s->script_ram, sizeof (s->script_ram));
+
+    return 0;
+}
+
 static int lsi_scsi_uninit(PCIDevice *d)
 {
     LSIState *s = (LSIState *) d;
@@ -1974,18 +2163,11 @@ static int lsi_scsi_uninit(PCIDevice *d)
     return 0;
 }
 
-void *lsi_scsi_init(PCIBus *bus, int devfn)
+static int lsi_scsi_init(PCIDevice *dev)
 {
-    LSIState *s;
+    LSIState *s = (LSIState *)dev;
     uint8_t *pci_conf;
 
-    s = (LSIState *)pci_register_device(bus, "LSI53C895A SCSI HBA",
-                                        sizeof(*s), devfn, NULL, NULL);
-    if (s == NULL) {
-        fprintf(stderr, "lsi-scsi: Failed to register PCI device\n");
-        return NULL;
-    }
-
     pci_conf = s->pci_dev.config;
 
     /* PCI Vendor ID (word) */
@@ -2002,16 +2184,16 @@ void *lsi_scsi_init(PCIBus *bus, int devfn)
     /* Interrupt pin 1 */
     pci_conf[0x3d] = 0x01;
 
-    s->mmio_io_addr = cpu_register_io_memory(0, lsi_mmio_readfn,
+    s->mmio_io_addr = cpu_register_io_memory(lsi_mmio_readfn,
                                              lsi_mmio_writefn, s);
-    s->ram_io_addr = cpu_register_io_memory(0, lsi_ram_readfn,
+    s->ram_io_addr = cpu_register_io_memory(lsi_ram_readfn,
                                             lsi_ram_writefn, s);
 
-    pci_register_io_region((struct PCIDevice *)s, 0, 256,
+    pci_register_bar((struct PCIDevice *)s, 0, 256,
                            PCI_ADDRESS_SPACE_IO, lsi_io_mapfunc);
-    pci_register_io_region((struct PCIDevice *)s, 1, 0x400,
+    pci_register_bar((struct PCIDevice *)s, 1, 0x400,
                            PCI_ADDRESS_SPACE_MEM, lsi_mmio_mapfunc);
-    pci_register_io_region((struct PCIDevice *)s, 2, 0x2000,
+    pci_register_bar((struct PCIDevice *)s, 2, 0x2000,
                            PCI_ADDRESS_SPACE_MEM, lsi_ram_mapfunc);
     s->queue = qemu_malloc(sizeof(lsi_queue));
     s->queue_len = 1;
@@ -2020,5 +2202,21 @@ void *lsi_scsi_init(PCIBus *bus, int devfn)
 
     lsi_soft_reset(s);
 
-    return s;
+    scsi_bus_new(&dev->qdev, lsi_scsi_attach);
+
+    register_savevm("lsiscsi", -1, 0, lsi_scsi_save, lsi_scsi_load, s);
+    return 0;
 }
+
+static PCIDeviceInfo lsi_info = {
+    .qdev.name = "lsi53c895a",
+    .qdev.size = sizeof(LSIState),
+    .init      = lsi_scsi_init,
+};
+
+static void lsi53c895a_register_devices(void)
+{
+    pci_qdev_register(&lsi_info);
+}
+
+device_init(lsi53c895a_register_devices);