#include <hw/hw.h>
#include <hw/pci/msi.h>
-#include <hw/pc.h>
+#include <hw/i386/pc.h>
#include <hw/pci/pci.h>
#include <hw/sysbus.h>
#include "monitor/monitor.h"
#include "sysemu/dma.h"
-#include "exec/cpu-common.h"
#include "internal.h"
#include <hw/ide/pci.h>
#include <hw/ide/ahci.h>
static void ahci_irq_raise(AHCIState *s, AHCIDevice *dev)
{
- struct AHCIPCIState *d = container_of(s, AHCIPCIState, ahci);
+ AHCIPCIState *d = container_of(s, AHCIPCIState, ahci);
+ PCIDevice *pci_dev = PCI_DEVICE(d);
DPRINTF(0, "raise irq\n");
- if (msi_enabled(&d->card)) {
- msi_notify(&d->card, 0);
+ if (msi_enabled(pci_dev)) {
+ msi_notify(pci_dev, 0);
} else {
qemu_irq_raise(s->irq);
}
static void ahci_irq_lower(AHCIState *s, AHCIDevice *dev)
{
- struct AHCIPCIState *d = container_of(s, AHCIPCIState, ahci);
+ AHCIPCIState *d = container_of(s, AHCIPCIState, ahci);
DPRINTF(0, "lower irq\n");
- if (!msi_enabled(&d->card)) {
+ if (!msi_enabled(PCI_DEVICE(d))) {
qemu_irq_lower(s->irq);
}
}
if (!cmd_fis) {
/* map cmd_fis */
uint64_t tbl_addr = le64_to_cpu(ad->cur_cmd->tbl_addr);
- cmd_fis = dma_memory_map(ad->hba->dma, tbl_addr, &cmd_len,
+ cmd_fis = dma_memory_map(ad->hba->as, tbl_addr, &cmd_len,
DMA_DIRECTION_TO_DEVICE);
cmd_mapped = 1;
}
ahci_trigger_irq(ad->hba, ad, PORT_IRQ_D2H_REG_FIS);
if (cmd_mapped) {
- dma_memory_unmap(ad->hba->dma, cmd_fis, cmd_len,
+ dma_memory_unmap(ad->hba->as, cmd_fis, cmd_len,
DMA_DIRECTION_TO_DEVICE, cmd_len);
}
}
int off_idx = -1;
int off_pos = -1;
int tbl_entry_size;
+ IDEBus *bus = &ad->port;
+ BusState *qbus = BUS(bus);
if (!sglist_alloc_hint) {
DPRINTF(ad->port_no, "no sg list given by guest: 0x%08x\n", opts);
}
/* map PRDT */
- if (!(prdt = dma_memory_map(ad->hba->dma, prdt_addr, &prdt_len,
+ if (!(prdt = dma_memory_map(ad->hba->as, prdt_addr, &prdt_len,
DMA_DIRECTION_TO_DEVICE))){
DPRINTF(ad->port_no, "map failed\n");
return -1;
goto out;
}
- qemu_sglist_init(sglist, (sglist_alloc_hint - off_idx), ad->hba->dma);
+ qemu_sglist_init(sglist, qbus->parent, (sglist_alloc_hint - off_idx),
+ ad->hba->as);
qemu_sglist_add(sglist, le64_to_cpu(tbl[off_idx].addr + off_pos),
le32_to_cpu(tbl[off_idx].flags_size) + 1 - off_pos);
}
out:
- dma_memory_unmap(ad->hba->dma, prdt, prdt_len,
+ dma_memory_unmap(ad->hba->as, prdt, prdt_len,
DMA_DIRECTION_TO_DEVICE, prdt_len);
return r;
}
tbl_addr = le64_to_cpu(cmd->tbl_addr);
cmd_len = 0x80;
- cmd_fis = dma_memory_map(s->dma, tbl_addr, &cmd_len,
+ cmd_fis = dma_memory_map(s->as, tbl_addr, &cmd_len,
DMA_DIRECTION_FROM_DEVICE);
if (!cmd_fis) {
/* We're ready to process the command in FIS byte 2. */
ide_exec_cmd(&s->dev[port].port, cmd_fis[2]);
- if (s->dev[port].port.ifs[0].status & READY_STAT) {
+ if ((s->dev[port].port.ifs[0].status & (READY_STAT|DRQ_STAT|BUSY_STAT)) ==
+ READY_STAT) {
ahci_write_fis_d2h(&s->dev[port], cmd_fis);
}
}
out:
- dma_memory_unmap(s->dma, cmd_fis, cmd_len, DMA_DIRECTION_FROM_DEVICE,
+ dma_memory_unmap(s->as, cmd_fis, cmd_len, DMA_DIRECTION_FROM_DEVICE,
cmd_len);
if (s->dev[port].port.ifs[0].status & (BUSY_STAT|DRQ_STAT)) {
}
static int ahci_dma_set_inactive(IDEDMA *dma)
+{
+ return 0;
+}
+
+static int ahci_async_cmd_done(IDEDMA *dma)
{
AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma);
- DPRINTF(ad->port_no, "dma done\n");
+ DPRINTF(ad->port_no, "async cmd done\n");
/* update d2h status */
ahci_write_fis_d2h(ad, NULL);
.set_unit = ahci_dma_set_unit,
.add_status = ahci_dma_add_status,
.set_inactive = ahci_dma_set_inactive,
+ .async_cmd_done = ahci_async_cmd_done,
.restart_cb = ahci_dma_restart_cb,
.reset = ahci_dma_reset,
};
-void ahci_init(AHCIState *s, DeviceState *qdev, DMAContext *dma, int ports)
+void ahci_init(AHCIState *s, DeviceState *qdev, AddressSpace *as, int ports)
{
qemu_irq *irqs;
int i;
- s->dma = dma;
+ s->as = as;
s->ports = ports;
s->dev = g_malloc0(sizeof(AHCIDevice) * ports);
ahci_reg_init(s);
/* XXX BAR size should be 1k, but that breaks, so bump it to 4k for now */
- memory_region_init_io(&s->mem, &ahci_mem_ops, s, "ahci", AHCI_MEM_BAR_SIZE);
- memory_region_init_io(&s->idp, &ahci_idp_ops, s, "ahci-idp", 32);
+ memory_region_init_io(&s->mem, OBJECT(qdev), &ahci_mem_ops, s,
+ "ahci", AHCI_MEM_BAR_SIZE);
+ memory_region_init_io(&s->idp, OBJECT(qdev), &ahci_idp_ops, s,
+ "ahci-idp", 32);
irqs = qemu_allocate_irqs(ahci_irq_set, s, s->ports);
for (i = 0; i < s->ports; i++) {
AHCIDevice *ad = &s->dev[i];
- ide_bus_new(&ad->port, qdev, i);
+ ide_bus_new(&ad->port, sizeof(ad->port), qdev, i, 1);
ide_init2(&ad->port, irqs[i]);
ad->hba = s;
int i;
s->control_regs.irqstatus = 0;
- s->control_regs.ghc = 0;
+ /* AHCI Enable (AE)
+ * The implementation of this bit is dependent upon the value of the
+ * CAP.SAM bit. If CAP.SAM is '0', then GHC.AE shall be read-write and
+ * shall have a reset value of '0'. If CAP.SAM is '1', then AE shall be
+ * read-only and shall have a reset value of '1'.
+ *
+ * We set HOST_CAP_AHCI so we must enable AHCI at reset.
+ */
+ s->control_regs.ghc = HOST_CTL_AHCI_EN;
for (i = 0; i < s->ports; i++) {
pr = &s->dev[i].port_regs;
},
};
+#define TYPE_SYSBUS_AHCI "sysbus-ahci"
+#define SYSBUS_AHCI(obj) OBJECT_CHECK(SysbusAHCIState, (obj), TYPE_SYSBUS_AHCI)
+
typedef struct SysbusAHCIState {
- SysBusDevice busdev;
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
AHCIState ahci;
uint32_t num_ports;
} SysbusAHCIState;
static void sysbus_ahci_reset(DeviceState *dev)
{
- SysbusAHCIState *s = DO_UPCAST(SysbusAHCIState, busdev.qdev, dev);
+ SysbusAHCIState *s = SYSBUS_AHCI(dev);
ahci_reset(&s->ahci);
}
-static int sysbus_ahci_init(SysBusDevice *dev)
+static void sysbus_ahci_realize(DeviceState *dev, Error **errp)
{
- SysbusAHCIState *s = FROM_SYSBUS(SysbusAHCIState, dev);
- ahci_init(&s->ahci, &dev->qdev, NULL, s->num_ports);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+ SysbusAHCIState *s = SYSBUS_AHCI(dev);
- sysbus_init_mmio(dev, &s->ahci.mem);
- sysbus_init_irq(dev, &s->ahci.irq);
- return 0;
+ ahci_init(&s->ahci, dev, NULL, s->num_ports);
+
+ sysbus_init_mmio(sbd, &s->ahci.mem);
+ sysbus_init_irq(sbd, &s->ahci.irq);
}
static Property sysbus_ahci_properties[] = {
static void sysbus_ahci_class_init(ObjectClass *klass, void *data)
{
- SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
DeviceClass *dc = DEVICE_CLASS(klass);
- sbc->init = sysbus_ahci_init;
+ dc->realize = sysbus_ahci_realize;
dc->vmsd = &vmstate_sysbus_ahci;
dc->props = sysbus_ahci_properties;
dc->reset = sysbus_ahci_reset;
+ set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
}
static const TypeInfo sysbus_ahci_info = {
- .name = "sysbus-ahci",
+ .name = TYPE_SYSBUS_AHCI,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(SysbusAHCIState),
.class_init = sysbus_ahci_class_init,