summaryrefslogtreecommitdiff
path: root/hw/ide/ich.c
diff options
context:
space:
mode:
authorDaniel Verkamp <daniel@drv.nu>2011-08-27 02:12:28 -0700
committerKevin Wolf <kwolf@redhat.com>2011-09-21 14:32:20 +0200
commit465f1ab16169f5d71e52f11d4c650a50fd681030 (patch)
tree02fee21253c82795551111e8d63f46fd7b2ba8f1 /hw/ide/ich.c
parent8e72506e20d9e606783de1cdb8d60dd9b9241e30 (diff)
downloadqemu-465f1ab16169f5d71e52f11d4c650a50fd681030.tar.gz
ahci: add port I/O index-data pair
Implement an I/O space index-data register pair as defined by the AHCI spec, including the corresponding SATA PCI capability and BAR. This allows real-mode code to access the AHCI registers; real-mode code cannot address the memory-mapped register space because it is beyond the first megabyte. Signed-off-by: Daniel Verkamp <daniel@drv.nu> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Diffstat (limited to 'hw/ide/ich.c')
-rw-r--r--hw/ide/ich.c27
1 files changed, 26 insertions, 1 deletions
diff --git a/hw/ide/ich.c b/hw/ide/ich.c
index 0327d0ee72..3f7510f52e 100644
--- a/hw/ide/ich.c
+++ b/hw/ide/ich.c
@@ -71,6 +71,14 @@
#include <hw/ide/pci.h>
#include <hw/ide/ahci.h>
+#define ICH9_SATA_CAP_OFFSET 0xA8
+
+#define ICH9_IDP_BAR 4
+#define ICH9_MEM_BAR 5
+
+#define ICH9_IDP_INDEX 0x10
+#define ICH9_IDP_INDEX_LOG2 0x04
+
static const VMStateDescription vmstate_ahci = {
.name = "ahci",
.unmigratable = 1,
@@ -79,6 +87,8 @@ static const VMStateDescription vmstate_ahci = {
static int pci_ich9_ahci_init(PCIDevice *dev)
{
struct AHCIPCIState *d;
+ int sata_cap_offset;
+ uint8_t *sata_cap;
d = DO_UPCAST(struct AHCIPCIState, card, dev);
ahci_init(&d->ahci, &dev->qdev, 6);
@@ -97,7 +107,22 @@ static int pci_ich9_ahci_init(PCIDevice *dev)
msi_init(dev, 0x50, 1, true, false);
d->ahci.irq = d->card.irq[0];
- pci_register_bar(&d->card, 5, 0, &d->ahci.mem);
+ pci_register_bar(&d->card, ICH9_IDP_BAR, PCI_BASE_ADDRESS_SPACE_IO,
+ &d->ahci.idp);
+ pci_register_bar(&d->card, ICH9_MEM_BAR, PCI_BASE_ADDRESS_SPACE_MEMORY,
+ &d->ahci.mem);
+
+ sata_cap_offset = pci_add_capability(&d->card, PCI_CAP_ID_SATA,
+ ICH9_SATA_CAP_OFFSET, SATA_CAP_SIZE);
+ if (sata_cap_offset < 0) {
+ return sata_cap_offset;
+ }
+
+ sata_cap = d->card.config + sata_cap_offset;
+ pci_set_word(sata_cap + SATA_CAP_REV, 0x10);
+ pci_set_long(sata_cap + SATA_CAP_BAR,
+ (ICH9_IDP_BAR + 0x4) | (ICH9_IDP_INDEX_LOG2 << 4));
+ d->ahci.idp_offset = ICH9_IDP_INDEX;
return 0;
}