diff options
-rw-r--r-- | hw/ide/ahci.c | 29 | ||||
-rw-r--r-- | hw/ide/ahci.h | 10 | ||||
-rw-r--r-- | hw/ide/ich.c | 3 |
3 files changed, 26 insertions, 16 deletions
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index 105dd53916..98bdf7059a 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -145,7 +145,7 @@ static void ahci_check_irq(AHCIState *s) DPRINTF(-1, "check irq %#x\n", s->control_regs.irqstatus); - for (i = 0; i < SATA_PORTS; i++) { + for (i = 0; i < s->ports; i++) { AHCIPortRegs *pr = &s->dev[i].port_regs; if (pr->irq_stat & pr->irq_mask) { s->control_regs.irqstatus |= (1 << i); @@ -303,7 +303,8 @@ static uint32_t ahci_mem_readl(void *ptr, target_phys_addr_t addr) DPRINTF(-1, "(addr 0x%08X), val 0x%08X\n", (unsigned) addr, val); } else if ((addr >= AHCI_PORT_REGS_START_ADDR) && - (addr < AHCI_PORT_REGS_END_ADDR)) { + (addr < (AHCI_PORT_REGS_START_ADDR + + (s->ports * AHCI_PORT_ADDR_OFFSET_LEN)))) { val = ahci_port_read(s, (addr - AHCI_PORT_REGS_START_ADDR) >> 7, addr & AHCI_PORT_ADDR_OFFSET_MASK); } @@ -355,7 +356,8 @@ static void ahci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val) DPRINTF(-1, "write to unknown register 0x%x\n", (unsigned)addr); } } else if ((addr >= AHCI_PORT_REGS_START_ADDR) && - (addr < AHCI_PORT_REGS_END_ADDR)) { + (addr < (AHCI_PORT_REGS_START_ADDR + + (s->ports * AHCI_PORT_ADDR_OFFSET_LEN)))) { ahci_port_write(s, (addr - AHCI_PORT_REGS_START_ADDR) >> 7, addr & AHCI_PORT_ADDR_OFFSET_MASK, val); } @@ -378,16 +380,16 @@ static void ahci_reg_init(AHCIState *s) { int i; - s->control_regs.cap = (SATA_PORTS - 1) | + s->control_regs.cap = (s->ports - 1) | (AHCI_NUM_COMMAND_SLOTS << 8) | (AHCI_SUPPORTED_SPEED_GEN1 << AHCI_SUPPORTED_SPEED) | HOST_CAP_NCQ | HOST_CAP_AHCI; - s->control_regs.impl = (1 << SATA_PORTS) - 1; + s->control_regs.impl = (1 << s->ports) - 1; s->control_regs.version = AHCI_VERSION_1_0; - for (i = 0; i < SATA_PORTS; i++) { + for (i = 0; i < s->ports; i++) { s->dev[i].port_state = STATE_RUN; } } @@ -1096,17 +1098,19 @@ static const IDEDMAOps ahci_dma_ops = { .reset = ahci_dma_reset, }; -void ahci_init(AHCIState *s, DeviceState *qdev) +void ahci_init(AHCIState *s, DeviceState *qdev, int ports) { qemu_irq *irqs; int i; + s->ports = ports; + s->dev = qemu_mallocz(sizeof(AHCIDevice) * ports); ahci_reg_init(s); s->mem = cpu_register_io_memory(ahci_readfn, ahci_writefn, s, DEVICE_LITTLE_ENDIAN); - irqs = qemu_allocate_irqs(ahci_irq_set, s, SATA_PORTS); + irqs = qemu_allocate_irqs(ahci_irq_set, s, s->ports); - for (i = 0; i < SATA_PORTS; i++) { + for (i = 0; i < s->ports; i++) { AHCIDevice *ad = &s->dev[i]; ide_bus_new(&ad->port, qdev, i); @@ -1120,6 +1124,11 @@ void ahci_init(AHCIState *s, DeviceState *qdev) } } +void ahci_uninit(AHCIState *s) +{ + qemu_free(s->dev); +} + void ahci_pci_map(PCIDevice *pci_dev, int region_num, pcibus_t addr, pcibus_t size, int type) { @@ -1137,7 +1146,7 @@ void ahci_reset(void *opaque) d->ahci.control_regs.irqstatus = 0; d->ahci.control_regs.ghc = 0; - for (i = 0; i < SATA_PORTS; i++) { + for (i = 0; i < d->ahci.ports; i++) { ahci_reset_port(&d->ahci, i); } } diff --git a/hw/ide/ahci.h b/hw/ide/ahci.h index b2786d1c07..a4560c41b6 100644 --- a/hw/ide/ahci.h +++ b/hw/ide/ahci.h @@ -188,11 +188,9 @@ #define AHCI_GENERIC_HOST_CONTROL_REGS_MAX_ADDR 0x20 /* Shouldn't this be 0x2c? */ -#define SATA_PORTS 4 - #define AHCI_PORT_REGS_START_ADDR 0x100 -#define AHCI_PORT_REGS_END_ADDR (AHCI_PORT_REGS_START_ADDR + SATA_PORTS * 0x80) #define AHCI_PORT_ADDR_OFFSET_MASK 0x7f +#define AHCI_PORT_ADDR_OFFSET_LEN 0x80 #define AHCI_NUM_COMMAND_SLOTS 31 #define AHCI_SUPPORTED_SPEED 20 @@ -289,9 +287,10 @@ struct AHCIDevice { }; typedef struct AHCIState { - AHCIDevice dev[SATA_PORTS]; + AHCIDevice *dev; AHCIControlRegs control_regs; int mem; + int ports; qemu_irq irq; } AHCIState; @@ -323,7 +322,8 @@ typedef struct NCQFrame { uint8_t reserved10; } __attribute__ ((packed)) NCQFrame; -void ahci_init(AHCIState *s, DeviceState *qdev); +void ahci_init(AHCIState *s, DeviceState *qdev, int ports); +void ahci_uninit(AHCIState *s); void ahci_pci_map(PCIDevice *pci_dev, int region_num, pcibus_t addr, pcibus_t size, int type); diff --git a/hw/ide/ich.c b/hw/ide/ich.c index 70cb766990..f242d7a81f 100644 --- a/hw/ide/ich.c +++ b/hw/ide/ich.c @@ -100,7 +100,7 @@ static int pci_ich9_ahci_init(PCIDevice *dev) msi_init(dev, 0x50, 1, true, false); - ahci_init(&d->ahci, &dev->qdev); + ahci_init(&d->ahci, &dev->qdev, 6); d->ahci.irq = d->card.irq[0]; return 0; @@ -116,6 +116,7 @@ static int pci_ich9_uninit(PCIDevice *dev) } qemu_unregister_reset(ahci_reset, d); + ahci_uninit(&d->ahci); return 0; } |