1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63#include <hw/hw.h>
64#include <hw/pci/msi.h>
65#include <hw/i386/pc.h>
66#include <hw/pci/pci.h>
67#include <hw/isa/isa.h>
68#include "block/block.h"
69#include "sysemu/dma.h"
70
71#include <hw/ide/pci.h>
72#include <hw/ide/ahci.h>
73
74#define ICH9_SATA_CAP_OFFSET 0xA8
75
76#define ICH9_IDP_BAR 4
77#define ICH9_MEM_BAR 5
78
79#define ICH9_IDP_INDEX 0x10
80#define ICH9_IDP_INDEX_LOG2 0x04
81
82static const VMStateDescription vmstate_ich9_ahci = {
83 .name = "ich9_ahci",
84 .unmigratable = 1,
85 .version_id = 1,
86 .fields = (VMStateField []) {
87 VMSTATE_PCI_DEVICE(card, AHCIPCIState),
88 VMSTATE_AHCI(ahci, AHCIPCIState),
89 VMSTATE_END_OF_LIST()
90 },
91};
92
93static void pci_ich9_reset(DeviceState *dev)
94{
95 struct AHCIPCIState *d = DO_UPCAST(struct AHCIPCIState, card.qdev, dev);
96
97 ahci_reset(&d->ahci);
98}
99
100static int pci_ich9_ahci_init(PCIDevice *dev)
101{
102 struct AHCIPCIState *d;
103 int sata_cap_offset;
104 uint8_t *sata_cap;
105 d = DO_UPCAST(struct AHCIPCIState, card, dev);
106
107 ahci_init(&d->ahci, &dev->qdev, pci_dma_context(dev), 6);
108
109 pci_config_set_prog_interface(d->card.config, AHCI_PROGMODE_MAJOR_REV_1);
110
111 d->card.config[PCI_CACHE_LINE_SIZE] = 0x08;
112 d->card.config[PCI_LATENCY_TIMER] = 0x00;
113 pci_config_set_interrupt_pin(d->card.config, 1);
114
115
116 d->card.config[0x90] = 1 << 6;
117
118 msi_init(dev, 0x50, 1, true, false);
119 d->ahci.irq = d->card.irq[0];
120
121 pci_register_bar(&d->card, ICH9_IDP_BAR, PCI_BASE_ADDRESS_SPACE_IO,
122 &d->ahci.idp);
123 pci_register_bar(&d->card, ICH9_MEM_BAR, PCI_BASE_ADDRESS_SPACE_MEMORY,
124 &d->ahci.mem);
125
126 sata_cap_offset = pci_add_capability(&d->card, PCI_CAP_ID_SATA,
127 ICH9_SATA_CAP_OFFSET, SATA_CAP_SIZE);
128 if (sata_cap_offset < 0) {
129 return sata_cap_offset;
130 }
131
132 sata_cap = d->card.config + sata_cap_offset;
133 pci_set_word(sata_cap + SATA_CAP_REV, 0x10);
134 pci_set_long(sata_cap + SATA_CAP_BAR,
135 (ICH9_IDP_BAR + 0x4) | (ICH9_IDP_INDEX_LOG2 << 4));
136 d->ahci.idp_offset = ICH9_IDP_INDEX;
137
138 return 0;
139}
140
141static void pci_ich9_uninit(PCIDevice *dev)
142{
143 struct AHCIPCIState *d;
144 d = DO_UPCAST(struct AHCIPCIState, card, dev);
145
146 msi_uninit(dev);
147 ahci_uninit(&d->ahci);
148}
149
150static void ich_ahci_class_init(ObjectClass *klass, void *data)
151{
152 DeviceClass *dc = DEVICE_CLASS(klass);
153 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
154
155 k->init = pci_ich9_ahci_init;
156 k->exit = pci_ich9_uninit;
157 k->vendor_id = PCI_VENDOR_ID_INTEL;
158 k->device_id = PCI_DEVICE_ID_INTEL_82801IR;
159 k->revision = 0x02;
160 k->class_id = PCI_CLASS_STORAGE_SATA;
161 dc->vmsd = &vmstate_ich9_ahci;
162 dc->reset = pci_ich9_reset;
163}
164
165static const TypeInfo ich_ahci_info = {
166 .name = "ich9-ahci",
167 .parent = TYPE_PCI_DEVICE,
168 .instance_size = sizeof(AHCIPCIState),
169 .class_init = ich_ahci_class_init,
170};
171
172static void ich_ahci_register_types(void)
173{
174 type_register_static(&ich_ahci_info);
175}
176
177type_init(ich_ahci_register_types)
178