macio.c (a504b9b91a1a884ce7e5296f4692b9cac85beab5) macio.c (343bd85a40811f0522063e58d565c6965bd81e00)
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

--- 29 unchanged lines hidden (view full) ---

38{
39 /*< private >*/
40 PCIDevice parent;
41 /*< public >*/
42
43 MemoryRegion bar;
44 CUDAState cuda;
45 DBDMAState dbdma;
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

--- 29 unchanged lines hidden (view full) ---

38{
39 /*< private >*/
40 PCIDevice parent;
41 /*< public >*/
42
43 MemoryRegion bar;
44 CUDAState cuda;
45 DBDMAState dbdma;
46 ESCCState escc;
46 MemoryRegion *pic_mem;
47 MemoryRegion *pic_mem;
47 MemoryRegion *escc_mem;
48 uint64_t frequency;
49} MacIOState;
50
51#define OLDWORLD_MACIO(obj) \
52 OBJECT_CHECK(OldWorldMacIOState, (obj), TYPE_OLDWORLD_MACIO)
53
54typedef struct OldWorldMacIOState {
55 /*< private >*/
56 MacIOState parent_obj;
57 /*< public >*/
58
48 uint64_t frequency;
49} MacIOState;
50
51#define OLDWORLD_MACIO(obj) \
52 OBJECT_CHECK(OldWorldMacIOState, (obj), TYPE_OLDWORLD_MACIO)
53
54typedef struct OldWorldMacIOState {
55 /*< private >*/
56 MacIOState parent_obj;
57 /*< public >*/
58
59 qemu_irq irqs[5];
59 qemu_irq irqs[7];
60
61 MacIONVRAMState nvram;
62 MACIOIDEState ide[2];
63} OldWorldMacIOState;
64
65#define NEWWORLD_MACIO(obj) \
66 OBJECT_CHECK(NewWorldMacIOState, (obj), TYPE_NEWWORLD_MACIO)
67
68typedef struct NewWorldMacIOState {
69 /*< private >*/
70 MacIOState parent_obj;
71 /*< public >*/
60
61 MacIONVRAMState nvram;
62 MACIOIDEState ide[2];
63} OldWorldMacIOState;
64
65#define NEWWORLD_MACIO(obj) \
66 OBJECT_CHECK(NewWorldMacIOState, (obj), TYPE_NEWWORLD_MACIO)
67
68typedef struct NewWorldMacIOState {
69 /*< private >*/
70 MacIOState parent_obj;
71 /*< public >*/
72 qemu_irq irqs[5];
72 qemu_irq irqs[7];
73 MACIOIDEState ide[2];
74} NewWorldMacIOState;
75
76/*
77 * The mac-io has two interfaces to the ESCC. One is called "escc-legacy",
78 * while the other one is the normal, current ESCC interface.
79 *
80 * The magic below creates memory aliases to spawn the escc-legacy device
81 * purely by rerouting the respective registers to our escc region. This
82 * works because the only difference between the two memory regions is the
83 * register layout, not their semantics.
84 *
85 * Reference: ftp://ftp.software.ibm.com/rs6000/technology/spec/chrp/inwork/CHRP_IORef_1.0.pdf
86 */
73 MACIOIDEState ide[2];
74} NewWorldMacIOState;
75
76/*
77 * The mac-io has two interfaces to the ESCC. One is called "escc-legacy",
78 * while the other one is the normal, current ESCC interface.
79 *
80 * The magic below creates memory aliases to spawn the escc-legacy device
81 * purely by rerouting the respective registers to our escc region. This
82 * works because the only difference between the two memory regions is the
83 * register layout, not their semantics.
84 *
85 * Reference: ftp://ftp.software.ibm.com/rs6000/technology/spec/chrp/inwork/CHRP_IORef_1.0.pdf
86 */
87static void macio_escc_legacy_setup(MacIOState *macio_state)
87static void macio_escc_legacy_setup(MacIOState *s)
88{
88{
89 ESCCState *escc = ESCC(&s->escc);
90 SysBusDevice *sbd = SYS_BUS_DEVICE(escc);
89 MemoryRegion *escc_legacy = g_new(MemoryRegion, 1);
91 MemoryRegion *escc_legacy = g_new(MemoryRegion, 1);
90 MemoryRegion *bar = &macio_state->bar;
92 MemoryRegion *bar = &s->bar;
91 int i;
92 static const int maps[] = {
93 0x00, 0x00, /* Command B */
94 0x02, 0x20, /* Command A */
95 0x04, 0x10, /* Data B */
96 0x06, 0x30, /* Data A */
97 0x08, 0x40, /* Enhancement B */
98 0x0A, 0x50, /* Enhancement A */
99 0x80, 0x80, /* Recovery count */
100 0x90, 0x90, /* Start A */
101 0xa0, 0xa0, /* Start B */
102 0xb0, 0xb0, /* Detect AB */
103 };
104
93 int i;
94 static const int maps[] = {
95 0x00, 0x00, /* Command B */
96 0x02, 0x20, /* Command A */
97 0x04, 0x10, /* Data B */
98 0x06, 0x30, /* Data A */
99 0x08, 0x40, /* Enhancement B */
100 0x0A, 0x50, /* Enhancement A */
101 0x80, 0x80, /* Recovery count */
102 0x90, 0x90, /* Start A */
103 0xa0, 0xa0, /* Start B */
104 0xb0, 0xb0, /* Detect AB */
105 };
106
105 memory_region_init(escc_legacy, OBJECT(macio_state), "escc-legacy", 256);
107 memory_region_init(escc_legacy, OBJECT(s), "escc-legacy", 256);
106 for (i = 0; i < ARRAY_SIZE(maps); i += 2) {
107 MemoryRegion *port = g_new(MemoryRegion, 1);
108 for (i = 0; i < ARRAY_SIZE(maps); i += 2) {
109 MemoryRegion *port = g_new(MemoryRegion, 1);
108 memory_region_init_alias(port, OBJECT(macio_state), "escc-legacy-port",
109 macio_state->escc_mem, maps[i+1], 0x2);
110 memory_region_init_alias(port, OBJECT(s), "escc-legacy-port",
111 sysbus_mmio_get_region(sbd, 0),
112 maps[i + 1], 0x2);
110 memory_region_add_subregion(escc_legacy, maps[i], port);
111 }
112
113 memory_region_add_subregion(bar, 0x12000, escc_legacy);
114}
115
113 memory_region_add_subregion(escc_legacy, maps[i], port);
114 }
115
116 memory_region_add_subregion(bar, 0x12000, escc_legacy);
117}
118
116static void macio_bar_setup(MacIOState *macio_state)
119static void macio_bar_setup(MacIOState *s)
117{
120{
118 MemoryRegion *bar = &macio_state->bar;
121 ESCCState *escc = ESCC(&s->escc);
122 SysBusDevice *sbd = SYS_BUS_DEVICE(escc);
123 MemoryRegion *bar = &s->bar;
119
124
120 if (macio_state->escc_mem) {
121 memory_region_add_subregion(bar, 0x13000, macio_state->escc_mem);
122 macio_escc_legacy_setup(macio_state);
123 }
125 memory_region_add_subregion(bar, 0x13000, sysbus_mmio_get_region(sbd, 0));
126 macio_escc_legacy_setup(s);
124}
125
126static void macio_common_realize(PCIDevice *d, Error **errp)
127{
128 MacIOState *s = MACIO(d);
129 SysBusDevice *sysbus_dev;
130 Error *err = NULL;
131

--- 10 unchanged lines hidden (view full) ---

142 if (err) {
143 error_propagate(errp, err);
144 return;
145 }
146 sysbus_dev = SYS_BUS_DEVICE(&s->cuda);
147 memory_region_add_subregion(&s->bar, 0x16000,
148 sysbus_mmio_get_region(sysbus_dev, 0));
149
127}
128
129static void macio_common_realize(PCIDevice *d, Error **errp)
130{
131 MacIOState *s = MACIO(d);
132 SysBusDevice *sysbus_dev;
133 Error *err = NULL;
134

--- 10 unchanged lines hidden (view full) ---

145 if (err) {
146 error_propagate(errp, err);
147 return;
148 }
149 sysbus_dev = SYS_BUS_DEVICE(&s->cuda);
150 memory_region_add_subregion(&s->bar, 0x16000,
151 sysbus_mmio_get_region(sysbus_dev, 0));
152
153 object_property_set_bool(OBJECT(&s->escc), true, "realized", &err);
154 if (err) {
155 error_propagate(errp, err);
156 return;
157 }
158
150 macio_bar_setup(s);
151 pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar);
152}
153
154static void macio_realize_ide(MacIOState *s, MACIOIDEState *ide,
155 qemu_irq irq0, qemu_irq irq1, int dmaid,
156 Error **errp)
157{

--- 22 unchanged lines hidden (view full) ---

180 if (err) {
181 error_propagate(errp, err);
182 return;
183 }
184
185 sysbus_dev = SYS_BUS_DEVICE(&s->cuda);
186 sysbus_connect_irq(sysbus_dev, 0, os->irqs[cur_irq++]);
187
159 macio_bar_setup(s);
160 pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar);
161}
162
163static void macio_realize_ide(MacIOState *s, MACIOIDEState *ide,
164 qemu_irq irq0, qemu_irq irq1, int dmaid,
165 Error **errp)
166{

--- 22 unchanged lines hidden (view full) ---

189 if (err) {
190 error_propagate(errp, err);
191 return;
192 }
193
194 sysbus_dev = SYS_BUS_DEVICE(&s->cuda);
195 sysbus_connect_irq(sysbus_dev, 0, os->irqs[cur_irq++]);
196
197 sysbus_dev = SYS_BUS_DEVICE(&s->escc);
198 sysbus_connect_irq(sysbus_dev, 0, os->irqs[cur_irq++]);
199 sysbus_connect_irq(sysbus_dev, 1, os->irqs[cur_irq++]);
200
188 object_property_set_bool(OBJECT(&os->nvram), true, "realized", &err);
189 if (err) {
190 error_propagate(errp, err);
191 return;
192 }
193 sysbus_dev = SYS_BUS_DEVICE(&os->nvram);
194 memory_region_add_subregion(&s->bar, 0x60000,
195 sysbus_mmio_get_region(sysbus_dev, 0));

--- 96 unchanged lines hidden (view full) ---

292 if (err) {
293 error_propagate(errp, err);
294 return;
295 }
296
297 sysbus_dev = SYS_BUS_DEVICE(&s->cuda);
298 sysbus_connect_irq(sysbus_dev, 0, ns->irqs[cur_irq++]);
299
201 object_property_set_bool(OBJECT(&os->nvram), true, "realized", &err);
202 if (err) {
203 error_propagate(errp, err);
204 return;
205 }
206 sysbus_dev = SYS_BUS_DEVICE(&os->nvram);
207 memory_region_add_subregion(&s->bar, 0x60000,
208 sysbus_mmio_get_region(sysbus_dev, 0));

--- 96 unchanged lines hidden (view full) ---

305 if (err) {
306 error_propagate(errp, err);
307 return;
308 }
309
310 sysbus_dev = SYS_BUS_DEVICE(&s->cuda);
311 sysbus_connect_irq(sysbus_dev, 0, ns->irqs[cur_irq++]);
312
313 sysbus_dev = SYS_BUS_DEVICE(&s->escc);
314 sysbus_connect_irq(sysbus_dev, 0, ns->irqs[cur_irq++]);
315 sysbus_connect_irq(sysbus_dev, 1, ns->irqs[cur_irq++]);
316
300 if (s->pic_mem) {
301 /* OpenPIC */
302 memory_region_add_subregion(&s->bar, 0x40000, s->pic_mem);
303 }
304
305 /* IDE buses */
306 for (i = 0; i < ARRAY_SIZE(ns->ide); i++) {
307 qemu_irq irq0 = ns->irqs[cur_irq++];

--- 34 unchanged lines hidden (view full) ---

342
343 object_initialize(&s->cuda, sizeof(s->cuda), TYPE_CUDA);
344 qdev_set_parent_bus(DEVICE(&s->cuda), sysbus_get_default());
345 object_property_add_child(obj, "cuda", OBJECT(&s->cuda), NULL);
346
347 object_initialize(&s->dbdma, sizeof(s->dbdma), TYPE_MAC_DBDMA);
348 qdev_set_parent_bus(DEVICE(&s->dbdma), sysbus_get_default());
349 object_property_add_child(obj, "dbdma", OBJECT(&s->dbdma), NULL);
317 if (s->pic_mem) {
318 /* OpenPIC */
319 memory_region_add_subregion(&s->bar, 0x40000, s->pic_mem);
320 }
321
322 /* IDE buses */
323 for (i = 0; i < ARRAY_SIZE(ns->ide); i++) {
324 qemu_irq irq0 = ns->irqs[cur_irq++];

--- 34 unchanged lines hidden (view full) ---

359
360 object_initialize(&s->cuda, sizeof(s->cuda), TYPE_CUDA);
361 qdev_set_parent_bus(DEVICE(&s->cuda), sysbus_get_default());
362 object_property_add_child(obj, "cuda", OBJECT(&s->cuda), NULL);
363
364 object_initialize(&s->dbdma, sizeof(s->dbdma), TYPE_MAC_DBDMA);
365 qdev_set_parent_bus(DEVICE(&s->dbdma), sysbus_get_default());
366 object_property_add_child(obj, "dbdma", OBJECT(&s->dbdma), NULL);
367
368 object_initialize(&s->escc, sizeof(s->escc), TYPE_ESCC);
369 qdev_prop_set_uint32(DEVICE(&s->escc), "disabled", 0);
370 qdev_prop_set_uint32(DEVICE(&s->escc), "frequency", ESCC_CLOCK);
371 qdev_prop_set_uint32(DEVICE(&s->escc), "it_shift", 4);
372 qdev_prop_set_chr(DEVICE(&s->escc), "chrA", serial_hds[0]);
373 qdev_prop_set_chr(DEVICE(&s->escc), "chrB", serial_hds[1]);
374 qdev_prop_set_uint32(DEVICE(&s->escc), "chnBtype", escc_serial);
375 qdev_prop_set_uint32(DEVICE(&s->escc), "chnAtype", escc_serial);
376 qdev_set_parent_bus(DEVICE(&s->escc), sysbus_get_default());
377 object_property_add_child(obj, "escc", OBJECT(&s->escc), NULL);
350}
351
352static const VMStateDescription vmstate_macio_oldworld = {
353 .name = "macio-oldworld",
354 .version_id = 0,
355 .minimum_version_id = 0,
356 .fields = (VMStateField[]) {
357 VMSTATE_PCI_DEVICE(parent_obj.parent, OldWorldMacIOState),

--- 81 unchanged lines hidden (view full) ---

439 type_register_static(&macio_type_info);
440 type_register_static(&macio_oldworld_type_info);
441 type_register_static(&macio_newworld_type_info);
442}
443
444type_init(macio_register_types)
445
446void macio_init(PCIDevice *d,
378}
379
380static const VMStateDescription vmstate_macio_oldworld = {
381 .name = "macio-oldworld",
382 .version_id = 0,
383 .minimum_version_id = 0,
384 .fields = (VMStateField[]) {
385 VMSTATE_PCI_DEVICE(parent_obj.parent, OldWorldMacIOState),

--- 81 unchanged lines hidden (view full) ---

467 type_register_static(&macio_type_info);
468 type_register_static(&macio_oldworld_type_info);
469 type_register_static(&macio_newworld_type_info);
470}
471
472type_init(macio_register_types)
473
474void macio_init(PCIDevice *d,
447 MemoryRegion *pic_mem,
448 MemoryRegion *escc_mem)
475 MemoryRegion *pic_mem)
449{
450 MacIOState *macio_state = MACIO(d);
451
452 macio_state->pic_mem = pic_mem;
476{
477 MacIOState *macio_state = MACIO(d);
478
479 macio_state->pic_mem = pic_mem;
453 macio_state->escc_mem = escc_mem;
454 /* Note: this code is strongly inspirated from the corresponding code
455 in PearPC */
456 qdev_prop_set_uint64(DEVICE(&macio_state->cuda), "timebase-frequency",
457 macio_state->frequency);
458
459 qdev_init_nofail(DEVICE(d));
460}
480 /* Note: this code is strongly inspirated from the corresponding code
481 in PearPC */
482 qdev_prop_set_uint64(DEVICE(&macio_state->cuda), "timebase-frequency",
483 macio_state->frequency);
484
485 qdev_init_nofail(DEVICE(d));
486}