]> git.proxmox.com Git - mirror_qemu.git/blame - hw/ide/piix.c
block: Eliminate DriveInfo member bdrv, use blk_by_legacy_dinfo()
[mirror_qemu.git] / hw / ide / piix.c
CommitLineData
4c3df0ec
JQ
1/*
2 * QEMU IDE Emulation: PCI PIIX3/4 support.
3 *
4 * Copyright (c) 2003 Fabrice Bellard
5 * Copyright (c) 2006 Openedhand Ltd.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
dfc65f1f 25
4c3df0ec 26#include <hw/hw.h>
0d09e41a 27#include <hw/i386/pc.h>
a2cb15b0 28#include <hw/pci/pci.h>
0d09e41a 29#include <hw/isa/isa.h>
b9fe8a7a 30#include "sysemu/block-backend.h"
9c17d615
PB
31#include "sysemu/blockdev.h"
32#include "sysemu/sysemu.h"
33#include "sysemu/dma.h"
4c3df0ec
JQ
34
35#include <hw/ide/pci.h>
36
a8170e5e 37static uint64_t bmdma_read(void *opaque, hwaddr addr, unsigned size)
4c3df0ec
JQ
38{
39 BMDMAState *bm = opaque;
40 uint32_t val;
41
a9deb8c6
AK
42 if (size != 1) {
43 return ((uint64_t)1 << (size * 8)) - 1;
44 }
45
4c3df0ec
JQ
46 switch(addr & 3) {
47 case 0:
48 val = bm->cmd;
49 break;
50 case 2:
51 val = bm->status;
52 break;
53 default:
54 val = 0xff;
55 break;
56 }
57#ifdef DEBUG_IDE
cb67be85 58 printf("bmdma: readb 0x%02x : 0x%02x\n", (uint8_t)addr, val);
4c3df0ec
JQ
59#endif
60 return val;
61}
62
a8170e5e 63static void bmdma_write(void *opaque, hwaddr addr,
a9deb8c6 64 uint64_t val, unsigned size)
4c3df0ec
JQ
65{
66 BMDMAState *bm = opaque;
a9deb8c6
AK
67
68 if (size != 1) {
69 return;
70 }
71
4c3df0ec 72#ifdef DEBUG_IDE
cb67be85 73 printf("bmdma: writeb 0x%02x : 0x%02x\n", (uint8_t)addr, (uint8_t)val);
4c3df0ec
JQ
74#endif
75 switch(addr & 3) {
a9deb8c6 76 case 0:
0ed8b6f6
BS
77 bmdma_cmd_writeb(bm, val);
78 break;
4c3df0ec
JQ
79 case 2:
80 bm->status = (val & 0x60) | (bm->status & 1) | (bm->status & ~val & 0x06);
81 break;
82 }
83}
84
a348f108 85static const MemoryRegionOps piix_bmdma_ops = {
a9deb8c6
AK
86 .read = bmdma_read,
87 .write = bmdma_write,
88};
89
90static void bmdma_setup_bar(PCIIDEState *d)
4c3df0ec 91{
4c3df0ec
JQ
92 int i;
93
1437c94b 94 memory_region_init(&d->bmdma_bar, OBJECT(d), "piix-bmdma-container", 16);
4c3df0ec
JQ
95 for(i = 0;i < 2; i++) {
96 BMDMAState *bm = &d->bmdma[i];
4c3df0ec 97
1437c94b 98 memory_region_init_io(&bm->extra_io, OBJECT(d), &piix_bmdma_ops, bm,
a9deb8c6
AK
99 "piix-bmdma", 4);
100 memory_region_add_subregion(&d->bmdma_bar, i * 8, &bm->extra_io);
1437c94b
PB
101 memory_region_init_io(&bm->addr_ioport, OBJECT(d),
102 &bmdma_addr_ioport_ops, bm, "bmdma", 4);
a9deb8c6 103 memory_region_add_subregion(&d->bmdma_bar, i * 8 + 4, &bm->addr_ioport);
4c3df0ec
JQ
104 }
105}
106
107static void piix3_reset(void *opaque)
108{
109 PCIIDEState *d = opaque;
f6c11d56
AF
110 PCIDevice *pd = PCI_DEVICE(d);
111 uint8_t *pci_conf = pd->config;
4c3df0ec
JQ
112 int i;
113
4a643563
BS
114 for (i = 0; i < 2; i++) {
115 ide_bus_reset(&d->bus[i]);
4a643563 116 }
4c3df0ec 117
1e68f8c4
MT
118 /* TODO: this is the default. do not override. */
119 pci_conf[PCI_COMMAND] = 0x00;
120 /* TODO: this is the default. do not override. */
121 pci_conf[PCI_COMMAND + 1] = 0x00;
122 /* TODO: use pci_set_word */
123 pci_conf[PCI_STATUS] = PCI_STATUS_FAST_BACK;
124 pci_conf[PCI_STATUS + 1] = PCI_STATUS_DEVSEL_MEDIUM >> 8;
4c3df0ec
JQ
125 pci_conf[0x20] = 0x01; /* BMIBA: 20-23h */
126}
127
61d9d6b0 128static void pci_piix_init_ports(PCIIDEState *d) {
4a91d3b3 129 static const struct {
61d9d6b0
SH
130 int iobase;
131 int iobase2;
132 int isairq;
133 } port_info[] = {
134 {0x1f0, 0x3f6, 14},
135 {0x170, 0x376, 15},
136 };
4a91d3b3 137 int i;
61d9d6b0
SH
138
139 for (i = 0; i < 2; i++) {
c6baf942 140 ide_bus_new(&d->bus[i], sizeof(d->bus[i]), DEVICE(d), i, 2);
4a91d3b3
RH
141 ide_init_ioport(&d->bus[i], NULL, port_info[i].iobase,
142 port_info[i].iobase2);
48a18b3c 143 ide_init2(&d->bus[i], isa_get_irq(NULL, port_info[i].isairq));
61d9d6b0 144
a9deb8c6 145 bmdma_init(&d->bus[i], &d->bmdma[i], d);
61d9d6b0
SH
146 d->bmdma[i].bus = &d->bus[i];
147 qemu_add_vm_change_state_handler(d->bus[i].dma->ops->restart_cb,
148 &d->bmdma[i].dma);
149 }
150}
151
25f8e2f5 152static int pci_piix_ide_initfn(PCIDevice *dev)
4c3df0ec 153{
f6c11d56
AF
154 PCIIDEState *d = PCI_IDE(dev);
155 uint8_t *pci_conf = dev->config;
4c3df0ec 156
1e68f8c4 157 pci_conf[PCI_CLASS_PROG] = 0x80; // legacy ATA mode
4c3df0ec
JQ
158
159 qemu_register_reset(piix3_reset, d);
4c3df0ec 160
a9deb8c6 161 bmdma_setup_bar(d);
f6c11d56 162 pci_register_bar(dev, 4, PCI_BASE_ADDRESS_SPACE_IO, &d->bmdma_bar);
4c3df0ec 163
02a9594b 164 vmstate_register(DEVICE(dev), 0, &vmstate_ide_pci, d);
4c3df0ec 165
61d9d6b0 166 pci_piix_init_ports(d);
4c3df0ec 167
4c3df0ec
JQ
168 return 0;
169}
170
15e8159e 171int pci_piix3_xen_ide_unplug(DeviceState *dev)
679f4f8b 172{
679f4f8b
SS
173 PCIIDEState *pci_ide;
174 DriveInfo *di;
175 int i = 0;
176
f6c11d56 177 pci_ide = PCI_IDE(dev);
679f4f8b
SS
178
179 for (; i < 3; i++) {
180 di = drive_get_by_index(IF_IDE, i);
f9e8fda4 181 if (di != NULL && !di->media_cd) {
b9fe8a7a 182 BlockBackend *blk = blk_by_legacy_dinfo(di);
fa1d36df
MA
183 BlockDriverState *bs = blk_bs(blk);
184 DeviceState *ds = bdrv_get_attached_dev(bs);
679f4f8b 185 if (ds) {
fa1d36df 186 bdrv_detach_dev(bs, ds);
679f4f8b 187 }
679f4f8b 188 pci_ide->bus[di->bus].ifs[di->unit].bs = NULL;
b9fe8a7a 189 blk_unref(blk);
679f4f8b
SS
190 }
191 }
02a9594b 192 qdev_reset_all(DEVICE(dev));
679f4f8b
SS
193 return 0;
194}
195
196PCIDevice *pci_piix3_xen_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn)
197{
198 PCIDevice *dev;
199
200 dev = pci_create_simple(bus, devfn, "piix3-ide-xen");
679f4f8b
SS
201 pci_ide_create_devs(dev, hd_table);
202 return dev;
203}
204
f90c2bcd 205static void pci_piix_ide_exitfn(PCIDevice *dev)
a9deb8c6 206{
f6c11d56 207 PCIIDEState *d = PCI_IDE(dev);
a9deb8c6
AK
208 unsigned i;
209
210 for (i = 0; i < 2; ++i) {
211 memory_region_del_subregion(&d->bmdma_bar, &d->bmdma[i].extra_io);
a9deb8c6 212 memory_region_del_subregion(&d->bmdma_bar, &d->bmdma[i].addr_ioport);
a9deb8c6 213 }
a9deb8c6
AK
214}
215
4c3df0ec
JQ
216/* hd_table must contain 4 block drivers */
217/* NOTE: for the PIIX3, the IRQs and IOports are hardcoded */
57c88866 218PCIDevice *pci_piix3_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn)
4c3df0ec
JQ
219{
220 PCIDevice *dev;
221
556cd098 222 dev = pci_create_simple(bus, devfn, "piix3-ide");
4c3df0ec 223 pci_ide_create_devs(dev, hd_table);
57c88866 224 return dev;
4c3df0ec
JQ
225}
226
227/* hd_table must contain 4 block drivers */
228/* NOTE: for the PIIX4, the IRQs and IOports are hardcoded */
57c88866 229PCIDevice *pci_piix4_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn)
4c3df0ec
JQ
230{
231 PCIDevice *dev;
232
556cd098 233 dev = pci_create_simple(bus, devfn, "piix4-ide");
4c3df0ec 234 pci_ide_create_devs(dev, hd_table);
57c88866 235 return dev;
4c3df0ec
JQ
236}
237
40021f08
AL
238static void piix3_ide_class_init(ObjectClass *klass, void *data)
239{
39bffca2 240 DeviceClass *dc = DEVICE_CLASS(klass);
40021f08
AL
241 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
242
40021f08
AL
243 k->init = pci_piix_ide_initfn;
244 k->exit = pci_piix_ide_exitfn;
245 k->vendor_id = PCI_VENDOR_ID_INTEL;
246 k->device_id = PCI_DEVICE_ID_INTEL_82371SB_1;
247 k->class_id = PCI_CLASS_STORAGE_IDE;
125ee0ed 248 set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
2897ae02 249 dc->hotpluggable = false;
40021f08
AL
250}
251
8c43a6f0 252static const TypeInfo piix3_ide_info = {
39bffca2 253 .name = "piix3-ide",
f6c11d56 254 .parent = TYPE_PCI_IDE,
39bffca2 255 .class_init = piix3_ide_class_init,
e855761c
AL
256};
257
40021f08
AL
258static void piix3_ide_xen_class_init(ObjectClass *klass, void *data)
259{
39bffca2 260 DeviceClass *dc = DEVICE_CLASS(klass);
40021f08
AL
261 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
262
263 k->init = pci_piix_ide_initfn;
264 k->vendor_id = PCI_VENDOR_ID_INTEL;
265 k->device_id = PCI_DEVICE_ID_INTEL_82371SB_1;
266 k->class_id = PCI_CLASS_STORAGE_IDE;
125ee0ed 267 set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
40021f08
AL
268}
269
8c43a6f0 270static const TypeInfo piix3_ide_xen_info = {
39bffca2 271 .name = "piix3-ide-xen",
f6c11d56 272 .parent = TYPE_PCI_IDE,
39bffca2 273 .class_init = piix3_ide_xen_class_init,
e855761c
AL
274};
275
40021f08
AL
276static void piix4_ide_class_init(ObjectClass *klass, void *data)
277{
39bffca2 278 DeviceClass *dc = DEVICE_CLASS(klass);
40021f08
AL
279 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
280
40021f08
AL
281 k->init = pci_piix_ide_initfn;
282 k->exit = pci_piix_ide_exitfn;
283 k->vendor_id = PCI_VENDOR_ID_INTEL;
284 k->device_id = PCI_DEVICE_ID_INTEL_82371AB;
285 k->class_id = PCI_CLASS_STORAGE_IDE;
125ee0ed 286 set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
2897ae02 287 dc->hotpluggable = false;
40021f08
AL
288}
289
8c43a6f0 290static const TypeInfo piix4_ide_info = {
39bffca2 291 .name = "piix4-ide",
f6c11d56 292 .parent = TYPE_PCI_IDE,
39bffca2 293 .class_init = piix4_ide_class_init,
4c3df0ec
JQ
294};
295
83f7d43a 296static void piix_ide_register_types(void)
4c3df0ec 297{
39bffca2
AL
298 type_register_static(&piix3_ide_info);
299 type_register_static(&piix3_ide_xen_info);
300 type_register_static(&piix4_ide_info);
4c3df0ec 301}
83f7d43a
AF
302
303type_init(piix_ide_register_types)