]> Git Repo - qemu.git/blob - hw/macio.c
ide/macio: QOM'ify MacIO IDE
[qemu.git] / hw / macio.c
1 /*
2  * PowerMac MacIO device emulation
3  *
4  * Copyright (c) 2005-2007 Fabrice Bellard
5  * Copyright (c) 2007 Jocelyn Mayer
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  */
25 #include "hw.h"
26 #include "ppc/mac.h"
27 #include "pci/pci.h"
28 #include "mac_dbdma.h"
29 #include "escc.h"
30
31 #define TYPE_MACIO "macio"
32 #define MACIO(obj) OBJECT_CHECK(MacIOState, (obj), TYPE_MACIO)
33
34 typedef struct MacIOState
35 {
36     /*< private >*/
37     PCIDevice parent;
38     /*< public >*/
39
40     MemoryRegion bar;
41     void *dbdma;
42     MemoryRegion *pic_mem;
43     MemoryRegion *cuda_mem;
44     MemoryRegion *escc_mem;
45 } MacIOState;
46
47 #define OLDWORLD_MACIO(obj) \
48     OBJECT_CHECK(OldWorldMacIOState, (obj), TYPE_OLDWORLD_MACIO)
49
50 typedef struct OldWorldMacIOState {
51     /*< private >*/
52     MacIOState parent_obj;
53     /*< public >*/
54
55     qemu_irq irqs[2];
56
57     MacIONVRAMState nvram;
58     MACIOIDEState ide;
59 } OldWorldMacIOState;
60
61 #define NEWWORLD_MACIO(obj) \
62     OBJECT_CHECK(NewWorldMacIOState, (obj), TYPE_NEWWORLD_MACIO)
63
64 typedef struct NewWorldMacIOState {
65     /*< private >*/
66     MacIOState parent_obj;
67     /*< public >*/
68     qemu_irq irqs[4];
69     MACIOIDEState ide[2];
70 } NewWorldMacIOState;
71
72 static void macio_bar_setup(MacIOState *macio_state)
73 {
74     MemoryRegion *bar = &macio_state->bar;
75
76     if (macio_state->escc_mem) {
77         memory_region_add_subregion(bar, 0x13000, macio_state->escc_mem);
78     }
79     if (macio_state->cuda_mem) {
80         memory_region_add_subregion(bar, 0x16000, macio_state->cuda_mem);
81     }
82 }
83
84 static int macio_common_initfn(PCIDevice *d)
85 {
86     MacIOState *s = MACIO(d);
87
88     d->config[0x3d] = 0x01; // interrupt on pin 1
89
90     macio_bar_setup(s);
91     pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar);
92
93     return 0;
94 }
95
96 static int macio_oldworld_initfn(PCIDevice *d)
97 {
98     MacIOState *s = MACIO(d);
99     OldWorldMacIOState *os = OLDWORLD_MACIO(d);
100     SysBusDevice *sysbus_dev;
101     int ret = macio_common_initfn(d);
102     if (ret < 0) {
103         return ret;
104     }
105
106     ret = qdev_init(DEVICE(&os->nvram));
107     if (ret < 0) {
108         return ret;
109     }
110     sysbus_dev = SYS_BUS_DEVICE(&os->nvram);
111     memory_region_add_subregion(&s->bar, 0x60000,
112                                 sysbus_mmio_get_region(sysbus_dev, 0));
113     pmac_format_nvram_partition(&os->nvram, os->nvram.size);
114
115     if (s->pic_mem) {
116         /* Heathrow PIC */
117         memory_region_add_subregion(&s->bar, 0x00000, s->pic_mem);
118     }
119
120     sysbus_dev = SYS_BUS_DEVICE(&os->ide);
121     sysbus_connect_irq(sysbus_dev, 0, os->irqs[0]);
122     sysbus_connect_irq(sysbus_dev, 1, os->irqs[1]);
123     macio_ide_register_dma(&os->ide, s->dbdma, 0x16);
124     ret = qdev_init(DEVICE(&os->ide));
125     if (ret < 0) {
126         return ret;
127     }
128
129     return 0;
130 }
131
132 static void macio_oldworld_init(Object *obj)
133 {
134     MacIOState *s = MACIO(obj);
135     OldWorldMacIOState *os = OLDWORLD_MACIO(obj);
136     DeviceState *dev;
137
138     qdev_init_gpio_out(DEVICE(obj), os->irqs, ARRAY_SIZE(os->irqs));
139
140     object_initialize(&os->nvram, TYPE_MACIO_NVRAM);
141     dev = DEVICE(&os->nvram);
142     qdev_prop_set_uint32(dev, "size", 0x2000);
143     qdev_prop_set_uint32(dev, "it_shift", 4);
144
145     object_initialize(&os->ide, TYPE_MACIO_IDE);
146     qdev_set_parent_bus(DEVICE(&os->ide), sysbus_get_default());
147     memory_region_add_subregion(&s->bar, 0x1f000 + (1 * 0x1000), &os->ide.mem);
148     object_property_add_child(obj, "ide", OBJECT(&os->ide), NULL);
149 }
150
151 static int macio_newworld_initfn(PCIDevice *d)
152 {
153     MacIOState *s = MACIO(d);
154     NewWorldMacIOState *ns = NEWWORLD_MACIO(d);
155     SysBusDevice *sysbus_dev;
156     int ret = macio_common_initfn(d);
157     if (ret < 0) {
158         return ret;
159     }
160
161     if (s->pic_mem) {
162         /* OpenPIC */
163         memory_region_add_subregion(&s->bar, 0x40000, s->pic_mem);
164     }
165
166     sysbus_dev = SYS_BUS_DEVICE(&ns->ide[0]);
167     sysbus_connect_irq(sysbus_dev, 0, ns->irqs[0]);
168     sysbus_connect_irq(sysbus_dev, 1, ns->irqs[1]);
169     macio_ide_register_dma(&ns->ide[0], s->dbdma, 0x16);
170     ret = qdev_init(DEVICE(&ns->ide[0]));
171     if (ret < 0) {
172         return ret;
173     }
174
175     sysbus_dev = SYS_BUS_DEVICE(&ns->ide[1]);
176     sysbus_connect_irq(sysbus_dev, 0, ns->irqs[2]);
177     sysbus_connect_irq(sysbus_dev, 1, ns->irqs[3]);
178     macio_ide_register_dma(&ns->ide[0], s->dbdma, 0x1a);
179     ret = qdev_init(DEVICE(&ns->ide[1]));
180     if (ret < 0) {
181         return ret;
182     }
183
184     return 0;
185 }
186
187 static void macio_newworld_init(Object *obj)
188 {
189     MacIOState *s = MACIO(obj);
190     NewWorldMacIOState *ns = NEWWORLD_MACIO(obj);
191     int i;
192     gchar *name;
193
194     qdev_init_gpio_out(DEVICE(obj), ns->irqs, ARRAY_SIZE(ns->irqs));
195
196     for (i = 0; i < 2; i++) {
197         object_initialize(&ns->ide[i], TYPE_MACIO_IDE);
198         qdev_set_parent_bus(DEVICE(&ns->ide[i]), sysbus_get_default());
199         memory_region_add_subregion(&s->bar, 0x1f000 + ((i + 1) * 0x1000),
200                                     &ns->ide[i].mem);
201         name = g_strdup_printf("ide[%i]", i);
202         object_property_add_child(obj, name, OBJECT(&ns->ide[i]), NULL);
203         g_free(name);
204     }
205 }
206
207 static void macio_instance_init(Object *obj)
208 {
209     MacIOState *s = MACIO(obj);
210     MemoryRegion *dbdma_mem;
211
212     memory_region_init(&s->bar, "macio", 0x80000);
213
214     s->dbdma = DBDMA_init(&dbdma_mem);
215     memory_region_add_subregion(&s->bar, 0x08000, dbdma_mem);
216 }
217
218 static void macio_oldworld_class_init(ObjectClass *oc, void *data)
219 {
220     PCIDeviceClass *pdc = PCI_DEVICE_CLASS(oc);
221
222     pdc->init = macio_oldworld_initfn;
223     pdc->device_id = PCI_DEVICE_ID_APPLE_343S1201;
224 }
225
226 static void macio_newworld_class_init(ObjectClass *oc, void *data)
227 {
228     PCIDeviceClass *pdc = PCI_DEVICE_CLASS(oc);
229
230     pdc->init = macio_newworld_initfn;
231     pdc->device_id = PCI_DEVICE_ID_APPLE_UNI_N_KEYL;
232 }
233
234 static void macio_class_init(ObjectClass *klass, void *data)
235 {
236     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
237
238     k->vendor_id = PCI_VENDOR_ID_APPLE;
239     k->class_id = PCI_CLASS_OTHERS << 8;
240 }
241
242 static const TypeInfo macio_oldworld_type_info = {
243     .name          = TYPE_OLDWORLD_MACIO,
244     .parent        = TYPE_MACIO,
245     .instance_size = sizeof(OldWorldMacIOState),
246     .instance_init = macio_oldworld_init,
247     .class_init    = macio_oldworld_class_init,
248 };
249
250 static const TypeInfo macio_newworld_type_info = {
251     .name          = TYPE_NEWWORLD_MACIO,
252     .parent        = TYPE_MACIO,
253     .instance_size = sizeof(NewWorldMacIOState),
254     .instance_init = macio_newworld_init,
255     .class_init    = macio_newworld_class_init,
256 };
257
258 static const TypeInfo macio_type_info = {
259     .name          = TYPE_MACIO,
260     .parent        = TYPE_PCI_DEVICE,
261     .instance_size = sizeof(MacIOState),
262     .instance_init = macio_instance_init,
263     .abstract      = true,
264     .class_init    = macio_class_init,
265 };
266
267 static void macio_register_types(void)
268 {
269     type_register_static(&macio_type_info);
270     type_register_static(&macio_oldworld_type_info);
271     type_register_static(&macio_newworld_type_info);
272 }
273
274 type_init(macio_register_types)
275
276 void macio_init(PCIDevice *d,
277                 MemoryRegion *pic_mem,
278                 MemoryRegion *cuda_mem,
279                 MemoryRegion *escc_mem)
280 {
281     MacIOState *macio_state = MACIO(d);
282
283     macio_state->pic_mem = pic_mem;
284     macio_state->cuda_mem = cuda_mem;
285     macio_state->escc_mem = escc_mem;
286     /* Note: this code is strongly inspirated from the corresponding code
287        in PearPC */
288
289     qdev_init_nofail(DEVICE(d));
290 }
This page took 0.040129 seconds and 4 git commands to generate.