xref: /qemu/hw/ide/sii3112.c (revision a9dd6604a663d1a88e5cf6b1446d6a1202c3334d)
1*a9dd6604SBALATON Zoltan /*
2*a9dd6604SBALATON Zoltan  * QEMU SiI3112A PCI to Serial ATA Controller Emulation
3*a9dd6604SBALATON Zoltan  *
4*a9dd6604SBALATON Zoltan  * Copyright (C) 2017 BALATON Zoltan <balaton@eik.bme.hu>
5*a9dd6604SBALATON Zoltan  *
6*a9dd6604SBALATON Zoltan  * This work is licensed under the terms of the GNU GPL, version 2 or later.
7*a9dd6604SBALATON Zoltan  * See the COPYING file in the top-level directory.
8*a9dd6604SBALATON Zoltan  *
9*a9dd6604SBALATON Zoltan  */
10*a9dd6604SBALATON Zoltan 
11*a9dd6604SBALATON Zoltan /* For documentation on this and similar cards see:
12*a9dd6604SBALATON Zoltan  * http://wiki.osdev.org/User:Quok/Silicon_Image_Datasheets
13*a9dd6604SBALATON Zoltan  */
14*a9dd6604SBALATON Zoltan 
15*a9dd6604SBALATON Zoltan #include <qemu/osdep.h>
16*a9dd6604SBALATON Zoltan #include <hw/ide/pci.h>
17*a9dd6604SBALATON Zoltan #include "trace.h"
18*a9dd6604SBALATON Zoltan 
19*a9dd6604SBALATON Zoltan #define TYPE_SII3112_PCI "sii3112"
20*a9dd6604SBALATON Zoltan #define SII3112_PCI(obj) OBJECT_CHECK(SiI3112PCIState, (obj), \
21*a9dd6604SBALATON Zoltan                          TYPE_SII3112_PCI)
22*a9dd6604SBALATON Zoltan 
23*a9dd6604SBALATON Zoltan typedef struct SiI3112Regs {
24*a9dd6604SBALATON Zoltan     uint32_t confstat;
25*a9dd6604SBALATON Zoltan     uint32_t scontrol;
26*a9dd6604SBALATON Zoltan     uint16_t sien;
27*a9dd6604SBALATON Zoltan     uint8_t swdata;
28*a9dd6604SBALATON Zoltan } SiI3112Regs;
29*a9dd6604SBALATON Zoltan 
30*a9dd6604SBALATON Zoltan typedef struct SiI3112PCIState {
31*a9dd6604SBALATON Zoltan     PCIIDEState i;
32*a9dd6604SBALATON Zoltan     MemoryRegion mmio;
33*a9dd6604SBALATON Zoltan     SiI3112Regs regs[2];
34*a9dd6604SBALATON Zoltan } SiI3112PCIState;
35*a9dd6604SBALATON Zoltan 
36*a9dd6604SBALATON Zoltan /* The sii3112_reg_read and sii3112_reg_write functions implement the
37*a9dd6604SBALATON Zoltan  * Internal Register Space - BAR5 (section 6.7 of the data sheet).
38*a9dd6604SBALATON Zoltan  */
39*a9dd6604SBALATON Zoltan 
40*a9dd6604SBALATON Zoltan static uint64_t sii3112_reg_read(void *opaque, hwaddr addr,
41*a9dd6604SBALATON Zoltan                                 unsigned int size)
42*a9dd6604SBALATON Zoltan {
43*a9dd6604SBALATON Zoltan     SiI3112PCIState *d = opaque;
44*a9dd6604SBALATON Zoltan     uint64_t val = 0;
45*a9dd6604SBALATON Zoltan 
46*a9dd6604SBALATON Zoltan     switch (addr) {
47*a9dd6604SBALATON Zoltan     case 0x00:
48*a9dd6604SBALATON Zoltan         val = d->i.bmdma[0].cmd;
49*a9dd6604SBALATON Zoltan         break;
50*a9dd6604SBALATON Zoltan     case 0x01:
51*a9dd6604SBALATON Zoltan         val = d->regs[0].swdata;
52*a9dd6604SBALATON Zoltan         break;
53*a9dd6604SBALATON Zoltan     case 0x02:
54*a9dd6604SBALATON Zoltan         val = d->i.bmdma[0].status;
55*a9dd6604SBALATON Zoltan         break;
56*a9dd6604SBALATON Zoltan     case 0x03:
57*a9dd6604SBALATON Zoltan         val = 0;
58*a9dd6604SBALATON Zoltan         break;
59*a9dd6604SBALATON Zoltan     case 0x04 ... 0x07:
60*a9dd6604SBALATON Zoltan         val = bmdma_addr_ioport_ops.read(&d->i.bmdma[0], addr - 4, size);
61*a9dd6604SBALATON Zoltan         break;
62*a9dd6604SBALATON Zoltan     case 0x08:
63*a9dd6604SBALATON Zoltan         val = d->i.bmdma[1].cmd;
64*a9dd6604SBALATON Zoltan         break;
65*a9dd6604SBALATON Zoltan     case 0x09:
66*a9dd6604SBALATON Zoltan         val = d->regs[1].swdata;
67*a9dd6604SBALATON Zoltan         break;
68*a9dd6604SBALATON Zoltan     case 0x0a:
69*a9dd6604SBALATON Zoltan         val = d->i.bmdma[1].status;
70*a9dd6604SBALATON Zoltan         break;
71*a9dd6604SBALATON Zoltan     case 0x0b:
72*a9dd6604SBALATON Zoltan         val = 0;
73*a9dd6604SBALATON Zoltan         break;
74*a9dd6604SBALATON Zoltan     case 0x0c ... 0x0f:
75*a9dd6604SBALATON Zoltan         val = bmdma_addr_ioport_ops.read(&d->i.bmdma[1], addr - 12, size);
76*a9dd6604SBALATON Zoltan         break;
77*a9dd6604SBALATON Zoltan     case 0x10:
78*a9dd6604SBALATON Zoltan         val = d->i.bmdma[0].cmd;
79*a9dd6604SBALATON Zoltan         val |= (d->regs[0].confstat & (1UL << 11) ? (1 << 4) : 0); /*SATAINT0*/
80*a9dd6604SBALATON Zoltan         val |= (d->regs[1].confstat & (1UL << 11) ? (1 << 6) : 0); /*SATAINT1*/
81*a9dd6604SBALATON Zoltan         val |= (d->i.bmdma[1].status & BM_STATUS_INT ? (1 << 14) : 0);
82*a9dd6604SBALATON Zoltan         val |= d->i.bmdma[0].status << 16;
83*a9dd6604SBALATON Zoltan         val |= d->i.bmdma[1].status << 24;
84*a9dd6604SBALATON Zoltan         break;
85*a9dd6604SBALATON Zoltan     case 0x18:
86*a9dd6604SBALATON Zoltan         val = d->i.bmdma[1].cmd;
87*a9dd6604SBALATON Zoltan         val |= (d->regs[1].confstat & (1UL << 11) ? (1 << 4) : 0);
88*a9dd6604SBALATON Zoltan         val |= d->i.bmdma[1].status << 16;
89*a9dd6604SBALATON Zoltan         break;
90*a9dd6604SBALATON Zoltan     case 0x80 ... 0x87:
91*a9dd6604SBALATON Zoltan         if (size == 1) {
92*a9dd6604SBALATON Zoltan             val = ide_ioport_read(&d->i.bus[0], addr - 0x80);
93*a9dd6604SBALATON Zoltan         } else if (addr == 0x80) {
94*a9dd6604SBALATON Zoltan             val = (size == 2) ? ide_data_readw(&d->i.bus[0], 0) :
95*a9dd6604SBALATON Zoltan                                 ide_data_readl(&d->i.bus[0], 0);
96*a9dd6604SBALATON Zoltan         } else {
97*a9dd6604SBALATON Zoltan             val = (1ULL << (size * 8)) - 1;
98*a9dd6604SBALATON Zoltan         }
99*a9dd6604SBALATON Zoltan         break;
100*a9dd6604SBALATON Zoltan     case 0x8a:
101*a9dd6604SBALATON Zoltan         val = (size == 1) ? ide_status_read(&d->i.bus[0], 4) :
102*a9dd6604SBALATON Zoltan                             (1ULL << (size * 8)) - 1;
103*a9dd6604SBALATON Zoltan         break;
104*a9dd6604SBALATON Zoltan     case 0xa0:
105*a9dd6604SBALATON Zoltan         val = d->regs[0].confstat;
106*a9dd6604SBALATON Zoltan         break;
107*a9dd6604SBALATON Zoltan     case 0xc0 ... 0xc7:
108*a9dd6604SBALATON Zoltan         if (size == 1) {
109*a9dd6604SBALATON Zoltan             val = ide_ioport_read(&d->i.bus[1], addr - 0xc0);
110*a9dd6604SBALATON Zoltan         } else if (addr == 0xc0) {
111*a9dd6604SBALATON Zoltan             val = (size == 2) ? ide_data_readw(&d->i.bus[1], 0) :
112*a9dd6604SBALATON Zoltan                                 ide_data_readl(&d->i.bus[1], 0);
113*a9dd6604SBALATON Zoltan         } else {
114*a9dd6604SBALATON Zoltan             val = (1ULL << (size * 8)) - 1;
115*a9dd6604SBALATON Zoltan         }
116*a9dd6604SBALATON Zoltan         break;
117*a9dd6604SBALATON Zoltan     case 0xca:
118*a9dd6604SBALATON Zoltan         val = (size == 1) ? ide_status_read(&d->i.bus[0], 4) :
119*a9dd6604SBALATON Zoltan                             (1ULL << (size * 8)) - 1;
120*a9dd6604SBALATON Zoltan         break;
121*a9dd6604SBALATON Zoltan     case 0xe0:
122*a9dd6604SBALATON Zoltan         val = d->regs[1].confstat;
123*a9dd6604SBALATON Zoltan         break;
124*a9dd6604SBALATON Zoltan     case 0x100:
125*a9dd6604SBALATON Zoltan         val = d->regs[0].scontrol;
126*a9dd6604SBALATON Zoltan         break;
127*a9dd6604SBALATON Zoltan     case 0x104:
128*a9dd6604SBALATON Zoltan         val = (d->i.bus[0].ifs[0].blk) ? 0x113 : 0;
129*a9dd6604SBALATON Zoltan         break;
130*a9dd6604SBALATON Zoltan     case 0x148:
131*a9dd6604SBALATON Zoltan         val = d->regs[0].sien << 16;
132*a9dd6604SBALATON Zoltan         break;
133*a9dd6604SBALATON Zoltan     case 0x180:
134*a9dd6604SBALATON Zoltan         val = d->regs[1].scontrol;
135*a9dd6604SBALATON Zoltan         break;
136*a9dd6604SBALATON Zoltan     case 0x184:
137*a9dd6604SBALATON Zoltan         val = (d->i.bus[1].ifs[0].blk) ? 0x113 : 0;
138*a9dd6604SBALATON Zoltan         break;
139*a9dd6604SBALATON Zoltan     case 0x1c8:
140*a9dd6604SBALATON Zoltan         val = d->regs[1].sien << 16;
141*a9dd6604SBALATON Zoltan         break;
142*a9dd6604SBALATON Zoltan     default:
143*a9dd6604SBALATON Zoltan         val = 0;
144*a9dd6604SBALATON Zoltan     }
145*a9dd6604SBALATON Zoltan     trace_sii3112_read(size, addr, val);
146*a9dd6604SBALATON Zoltan     return val;
147*a9dd6604SBALATON Zoltan }
148*a9dd6604SBALATON Zoltan 
149*a9dd6604SBALATON Zoltan static void sii3112_reg_write(void *opaque, hwaddr addr,
150*a9dd6604SBALATON Zoltan                               uint64_t val, unsigned int size)
151*a9dd6604SBALATON Zoltan {
152*a9dd6604SBALATON Zoltan     SiI3112PCIState *d = opaque;
153*a9dd6604SBALATON Zoltan 
154*a9dd6604SBALATON Zoltan     trace_sii3112_write(size, addr, val);
155*a9dd6604SBALATON Zoltan     switch (addr) {
156*a9dd6604SBALATON Zoltan     case 0x00:
157*a9dd6604SBALATON Zoltan     case 0x10:
158*a9dd6604SBALATON Zoltan         bmdma_cmd_writeb(&d->i.bmdma[0], val);
159*a9dd6604SBALATON Zoltan         break;
160*a9dd6604SBALATON Zoltan     case 0x01:
161*a9dd6604SBALATON Zoltan     case 0x11:
162*a9dd6604SBALATON Zoltan         d->regs[0].swdata = val & 0x3f;
163*a9dd6604SBALATON Zoltan         break;
164*a9dd6604SBALATON Zoltan     case 0x02:
165*a9dd6604SBALATON Zoltan     case 0x12:
166*a9dd6604SBALATON Zoltan         d->i.bmdma[0].status = (val & 0x60) | (d->i.bmdma[0].status & 1) |
167*a9dd6604SBALATON Zoltan                                (d->i.bmdma[0].status & ~val & 6);
168*a9dd6604SBALATON Zoltan         break;
169*a9dd6604SBALATON Zoltan     case 0x04 ... 0x07:
170*a9dd6604SBALATON Zoltan         bmdma_addr_ioport_ops.write(&d->i.bmdma[0], addr - 4, val, size);
171*a9dd6604SBALATON Zoltan         break;
172*a9dd6604SBALATON Zoltan     case 0x08:
173*a9dd6604SBALATON Zoltan     case 0x18:
174*a9dd6604SBALATON Zoltan         bmdma_cmd_writeb(&d->i.bmdma[1], val);
175*a9dd6604SBALATON Zoltan         break;
176*a9dd6604SBALATON Zoltan     case 0x09:
177*a9dd6604SBALATON Zoltan     case 0x19:
178*a9dd6604SBALATON Zoltan         d->regs[1].swdata = val & 0x3f;
179*a9dd6604SBALATON Zoltan         break;
180*a9dd6604SBALATON Zoltan     case 0x0a:
181*a9dd6604SBALATON Zoltan     case 0x1a:
182*a9dd6604SBALATON Zoltan         d->i.bmdma[1].status = (val & 0x60) | (d->i.bmdma[1].status & 1) |
183*a9dd6604SBALATON Zoltan                                (d->i.bmdma[1].status & ~val & 6);
184*a9dd6604SBALATON Zoltan         break;
185*a9dd6604SBALATON Zoltan     case 0x0c ... 0x0f:
186*a9dd6604SBALATON Zoltan         bmdma_addr_ioport_ops.write(&d->i.bmdma[1], addr - 12, val, size);
187*a9dd6604SBALATON Zoltan         break;
188*a9dd6604SBALATON Zoltan     case 0x80 ... 0x87:
189*a9dd6604SBALATON Zoltan         if (size == 1) {
190*a9dd6604SBALATON Zoltan             ide_ioport_write(&d->i.bus[0], addr - 0x80, val);
191*a9dd6604SBALATON Zoltan         } else if (addr == 0x80) {
192*a9dd6604SBALATON Zoltan             if (size == 2) {
193*a9dd6604SBALATON Zoltan                 ide_data_writew(&d->i.bus[0], 0, val);
194*a9dd6604SBALATON Zoltan             } else {
195*a9dd6604SBALATON Zoltan                 ide_data_writel(&d->i.bus[0], 0, val);
196*a9dd6604SBALATON Zoltan             }
197*a9dd6604SBALATON Zoltan         }
198*a9dd6604SBALATON Zoltan         break;
199*a9dd6604SBALATON Zoltan     case 0x8a:
200*a9dd6604SBALATON Zoltan         if (size == 1) {
201*a9dd6604SBALATON Zoltan             ide_cmd_write(&d->i.bus[0], 4, val);
202*a9dd6604SBALATON Zoltan         }
203*a9dd6604SBALATON Zoltan         break;
204*a9dd6604SBALATON Zoltan     case 0xc0 ... 0xc7:
205*a9dd6604SBALATON Zoltan         if (size == 1) {
206*a9dd6604SBALATON Zoltan             ide_ioport_write(&d->i.bus[1], addr - 0xc0, val);
207*a9dd6604SBALATON Zoltan         } else if (addr == 0xc0) {
208*a9dd6604SBALATON Zoltan             if (size == 2) {
209*a9dd6604SBALATON Zoltan                 ide_data_writew(&d->i.bus[1], 0, val);
210*a9dd6604SBALATON Zoltan             } else {
211*a9dd6604SBALATON Zoltan                 ide_data_writel(&d->i.bus[1], 0, val);
212*a9dd6604SBALATON Zoltan             }
213*a9dd6604SBALATON Zoltan         }
214*a9dd6604SBALATON Zoltan         break;
215*a9dd6604SBALATON Zoltan     case 0xca:
216*a9dd6604SBALATON Zoltan         if (size == 1) {
217*a9dd6604SBALATON Zoltan             ide_cmd_write(&d->i.bus[1], 4, val);
218*a9dd6604SBALATON Zoltan         }
219*a9dd6604SBALATON Zoltan         break;
220*a9dd6604SBALATON Zoltan     case 0x100:
221*a9dd6604SBALATON Zoltan         d->regs[0].scontrol = val & 0xfff;
222*a9dd6604SBALATON Zoltan         if (val & 1) {
223*a9dd6604SBALATON Zoltan             ide_bus_reset(&d->i.bus[0]);
224*a9dd6604SBALATON Zoltan         }
225*a9dd6604SBALATON Zoltan         break;
226*a9dd6604SBALATON Zoltan     case 0x148:
227*a9dd6604SBALATON Zoltan         d->regs[0].sien = (val >> 16) & 0x3eed;
228*a9dd6604SBALATON Zoltan         break;
229*a9dd6604SBALATON Zoltan     case 0x180:
230*a9dd6604SBALATON Zoltan         d->regs[1].scontrol = val & 0xfff;
231*a9dd6604SBALATON Zoltan         if (val & 1) {
232*a9dd6604SBALATON Zoltan             ide_bus_reset(&d->i.bus[1]);
233*a9dd6604SBALATON Zoltan         }
234*a9dd6604SBALATON Zoltan         break;
235*a9dd6604SBALATON Zoltan     case 0x1c8:
236*a9dd6604SBALATON Zoltan         d->regs[1].sien = (val >> 16) & 0x3eed;
237*a9dd6604SBALATON Zoltan         break;
238*a9dd6604SBALATON Zoltan     default:
239*a9dd6604SBALATON Zoltan         val = 0;
240*a9dd6604SBALATON Zoltan     }
241*a9dd6604SBALATON Zoltan }
242*a9dd6604SBALATON Zoltan 
243*a9dd6604SBALATON Zoltan static const MemoryRegionOps sii3112_reg_ops = {
244*a9dd6604SBALATON Zoltan     .read = sii3112_reg_read,
245*a9dd6604SBALATON Zoltan     .write = sii3112_reg_write,
246*a9dd6604SBALATON Zoltan     .endianness = DEVICE_LITTLE_ENDIAN,
247*a9dd6604SBALATON Zoltan };
248*a9dd6604SBALATON Zoltan 
249*a9dd6604SBALATON Zoltan /* the PCI irq level is the logical OR of the two channels */
250*a9dd6604SBALATON Zoltan static void sii3112_update_irq(SiI3112PCIState *s)
251*a9dd6604SBALATON Zoltan {
252*a9dd6604SBALATON Zoltan     int i, set = 0;
253*a9dd6604SBALATON Zoltan 
254*a9dd6604SBALATON Zoltan     for (i = 0; i < 2; i++) {
255*a9dd6604SBALATON Zoltan         set |= s->regs[i].confstat & (1UL << 11);
256*a9dd6604SBALATON Zoltan     }
257*a9dd6604SBALATON Zoltan     pci_set_irq(PCI_DEVICE(s), (set ? 1 : 0));
258*a9dd6604SBALATON Zoltan }
259*a9dd6604SBALATON Zoltan 
260*a9dd6604SBALATON Zoltan static void sii3112_set_irq(void *opaque, int channel, int level)
261*a9dd6604SBALATON Zoltan {
262*a9dd6604SBALATON Zoltan     SiI3112PCIState *s = opaque;
263*a9dd6604SBALATON Zoltan 
264*a9dd6604SBALATON Zoltan     trace_sii3112_set_irq(channel, level);
265*a9dd6604SBALATON Zoltan     if (level) {
266*a9dd6604SBALATON Zoltan         s->regs[channel].confstat |= (1UL << 11);
267*a9dd6604SBALATON Zoltan     } else {
268*a9dd6604SBALATON Zoltan         s->regs[channel].confstat &= ~(1UL << 11);
269*a9dd6604SBALATON Zoltan     }
270*a9dd6604SBALATON Zoltan 
271*a9dd6604SBALATON Zoltan     sii3112_update_irq(s);
272*a9dd6604SBALATON Zoltan }
273*a9dd6604SBALATON Zoltan 
274*a9dd6604SBALATON Zoltan static void sii3112_reset(void *opaque)
275*a9dd6604SBALATON Zoltan {
276*a9dd6604SBALATON Zoltan     SiI3112PCIState *s = opaque;
277*a9dd6604SBALATON Zoltan     int i;
278*a9dd6604SBALATON Zoltan 
279*a9dd6604SBALATON Zoltan     for (i = 0; i < 2; i++) {
280*a9dd6604SBALATON Zoltan         s->regs[i].confstat = 0x6515 << 16;
281*a9dd6604SBALATON Zoltan         ide_bus_reset(&s->i.bus[i]);
282*a9dd6604SBALATON Zoltan     }
283*a9dd6604SBALATON Zoltan }
284*a9dd6604SBALATON Zoltan 
285*a9dd6604SBALATON Zoltan static void sii3112_pci_realize(PCIDevice *dev, Error **errp)
286*a9dd6604SBALATON Zoltan {
287*a9dd6604SBALATON Zoltan     SiI3112PCIState *d = SII3112_PCI(dev);
288*a9dd6604SBALATON Zoltan     PCIIDEState *s = PCI_IDE(dev);
289*a9dd6604SBALATON Zoltan     MemoryRegion *mr;
290*a9dd6604SBALATON Zoltan     qemu_irq *irq;
291*a9dd6604SBALATON Zoltan     int i;
292*a9dd6604SBALATON Zoltan 
293*a9dd6604SBALATON Zoltan     pci_config_set_interrupt_pin(dev->config, 1);
294*a9dd6604SBALATON Zoltan     pci_set_byte(dev->config + PCI_CACHE_LINE_SIZE, 8);
295*a9dd6604SBALATON Zoltan 
296*a9dd6604SBALATON Zoltan     /* BAR5 is in PCI memory space */
297*a9dd6604SBALATON Zoltan     memory_region_init_io(&d->mmio, OBJECT(d), &sii3112_reg_ops, d,
298*a9dd6604SBALATON Zoltan                          "sii3112.bar5", 0x200);
299*a9dd6604SBALATON Zoltan     pci_register_bar(dev, 5, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio);
300*a9dd6604SBALATON Zoltan 
301*a9dd6604SBALATON Zoltan     /* BAR0-BAR4 are PCI I/O space aliases into BAR5 */
302*a9dd6604SBALATON Zoltan     mr = g_new(MemoryRegion, 1);
303*a9dd6604SBALATON Zoltan     memory_region_init_alias(mr, OBJECT(d), "sii3112.bar0", &d->mmio, 0x80, 8);
304*a9dd6604SBALATON Zoltan     pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, mr);
305*a9dd6604SBALATON Zoltan     mr = g_new(MemoryRegion, 1);
306*a9dd6604SBALATON Zoltan     memory_region_init_alias(mr, OBJECT(d), "sii3112.bar1", &d->mmio, 0x88, 4);
307*a9dd6604SBALATON Zoltan     pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_IO, mr);
308*a9dd6604SBALATON Zoltan     mr = g_new(MemoryRegion, 1);
309*a9dd6604SBALATON Zoltan     memory_region_init_alias(mr, OBJECT(d), "sii3112.bar2", &d->mmio, 0xc0, 8);
310*a9dd6604SBALATON Zoltan     pci_register_bar(dev, 2, PCI_BASE_ADDRESS_SPACE_IO, mr);
311*a9dd6604SBALATON Zoltan     mr = g_new(MemoryRegion, 1);
312*a9dd6604SBALATON Zoltan     memory_region_init_alias(mr, OBJECT(d), "sii3112.bar3", &d->mmio, 0xc8, 4);
313*a9dd6604SBALATON Zoltan     pci_register_bar(dev, 3, PCI_BASE_ADDRESS_SPACE_IO, mr);
314*a9dd6604SBALATON Zoltan     mr = g_new(MemoryRegion, 1);
315*a9dd6604SBALATON Zoltan     memory_region_init_alias(mr, OBJECT(d), "sii3112.bar4", &d->mmio, 0, 16);
316*a9dd6604SBALATON Zoltan     pci_register_bar(dev, 4, PCI_BASE_ADDRESS_SPACE_IO, mr);
317*a9dd6604SBALATON Zoltan 
318*a9dd6604SBALATON Zoltan     irq = qemu_allocate_irqs(sii3112_set_irq, d, 2);
319*a9dd6604SBALATON Zoltan     for (i = 0; i < 2; i++) {
320*a9dd6604SBALATON Zoltan         ide_bus_new(&s->bus[i], sizeof(s->bus[i]), DEVICE(dev), i, 1);
321*a9dd6604SBALATON Zoltan         ide_init2(&s->bus[i], irq[i]);
322*a9dd6604SBALATON Zoltan 
323*a9dd6604SBALATON Zoltan         bmdma_init(&s->bus[i], &s->bmdma[i], s);
324*a9dd6604SBALATON Zoltan         s->bmdma[i].bus = &s->bus[i];
325*a9dd6604SBALATON Zoltan         ide_register_restart_cb(&s->bus[i]);
326*a9dd6604SBALATON Zoltan     }
327*a9dd6604SBALATON Zoltan     qemu_register_reset(sii3112_reset, s);
328*a9dd6604SBALATON Zoltan }
329*a9dd6604SBALATON Zoltan 
330*a9dd6604SBALATON Zoltan static void sii3112_pci_exitfn(PCIDevice *dev)
331*a9dd6604SBALATON Zoltan {
332*a9dd6604SBALATON Zoltan     PCIIDEState *d = PCI_IDE(dev);
333*a9dd6604SBALATON Zoltan     int i;
334*a9dd6604SBALATON Zoltan 
335*a9dd6604SBALATON Zoltan     for (i = 0; i < 2; ++i) {
336*a9dd6604SBALATON Zoltan         memory_region_del_subregion(&d->bmdma_bar, &d->bmdma[i].extra_io);
337*a9dd6604SBALATON Zoltan         memory_region_del_subregion(&d->bmdma_bar, &d->bmdma[i].addr_ioport);
338*a9dd6604SBALATON Zoltan     }
339*a9dd6604SBALATON Zoltan }
340*a9dd6604SBALATON Zoltan 
341*a9dd6604SBALATON Zoltan static void sii3112_pci_class_init(ObjectClass *klass, void *data)
342*a9dd6604SBALATON Zoltan {
343*a9dd6604SBALATON Zoltan     DeviceClass *dc = DEVICE_CLASS(klass);
344*a9dd6604SBALATON Zoltan     PCIDeviceClass *pd = PCI_DEVICE_CLASS(klass);
345*a9dd6604SBALATON Zoltan 
346*a9dd6604SBALATON Zoltan     pd->vendor_id = 0x1095;
347*a9dd6604SBALATON Zoltan     pd->device_id = 0x3112;
348*a9dd6604SBALATON Zoltan     pd->class_id = PCI_CLASS_STORAGE_RAID;
349*a9dd6604SBALATON Zoltan     pd->revision = 1;
350*a9dd6604SBALATON Zoltan     pd->realize = sii3112_pci_realize;
351*a9dd6604SBALATON Zoltan     pd->exit = sii3112_pci_exitfn;
352*a9dd6604SBALATON Zoltan     dc->desc = "SiI3112A SATA controller";
353*a9dd6604SBALATON Zoltan     set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
354*a9dd6604SBALATON Zoltan }
355*a9dd6604SBALATON Zoltan 
356*a9dd6604SBALATON Zoltan static const TypeInfo sii3112_pci_info = {
357*a9dd6604SBALATON Zoltan     .name = TYPE_SII3112_PCI,
358*a9dd6604SBALATON Zoltan     .parent = TYPE_PCI_IDE,
359*a9dd6604SBALATON Zoltan     .instance_size = sizeof(SiI3112PCIState),
360*a9dd6604SBALATON Zoltan     .class_init = sii3112_pci_class_init,
361*a9dd6604SBALATON Zoltan };
362*a9dd6604SBALATON Zoltan 
363*a9dd6604SBALATON Zoltan static void sii3112_register_types(void)
364*a9dd6604SBALATON Zoltan {
365*a9dd6604SBALATON Zoltan     type_register_static(&sii3112_pci_info);
366*a9dd6604SBALATON Zoltan }
367*a9dd6604SBALATON Zoltan 
368*a9dd6604SBALATON Zoltan type_init(sii3112_register_types)
369