|
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.h" |
|
28 |
|
29 typedef struct macio_state_t macio_state_t; |
|
30 struct macio_state_t { |
|
31 int is_oldworld; |
|
32 int pic_mem_index; |
|
33 int dbdma_mem_index; |
|
34 int cuda_mem_index; |
|
35 void *nvram; |
|
36 int nb_ide; |
|
37 int ide_mem_index[4]; |
|
38 }; |
|
39 |
|
40 static void macio_map (PCIDevice *pci_dev, int region_num, |
|
41 uint32_t addr, uint32_t size, int type) |
|
42 { |
|
43 macio_state_t *macio_state; |
|
44 int i; |
|
45 |
|
46 macio_state = (macio_state_t *)(pci_dev + 1); |
|
47 if (macio_state->pic_mem_index >= 0) { |
|
48 if (macio_state->is_oldworld) { |
|
49 /* Heathrow PIC */ |
|
50 cpu_register_physical_memory(addr + 0x00000, 0x1000, |
|
51 macio_state->pic_mem_index); |
|
52 } else { |
|
53 /* OpenPIC */ |
|
54 cpu_register_physical_memory(addr + 0x40000, 0x40000, |
|
55 macio_state->pic_mem_index); |
|
56 } |
|
57 } |
|
58 if (macio_state->dbdma_mem_index >= 0) { |
|
59 cpu_register_physical_memory(addr + 0x08000, 0x1000, |
|
60 macio_state->dbdma_mem_index); |
|
61 } |
|
62 if (macio_state->cuda_mem_index >= 0) { |
|
63 cpu_register_physical_memory(addr + 0x16000, 0x2000, |
|
64 macio_state->cuda_mem_index); |
|
65 } |
|
66 for (i = 0; i < macio_state->nb_ide; i++) { |
|
67 if (macio_state->ide_mem_index[i] >= 0) { |
|
68 cpu_register_physical_memory(addr + 0x1f000 + (i * 0x1000), 0x1000, |
|
69 macio_state->ide_mem_index[i]); |
|
70 } |
|
71 } |
|
72 if (macio_state->nvram != NULL) |
|
73 macio_nvram_map(macio_state->nvram, addr + 0x60000); |
|
74 } |
|
75 |
|
76 void macio_init (PCIBus *bus, int device_id, int is_oldworld, int pic_mem_index, |
|
77 int dbdma_mem_index, int cuda_mem_index, void *nvram, |
|
78 int nb_ide, int *ide_mem_index) |
|
79 { |
|
80 PCIDevice *d; |
|
81 macio_state_t *macio_state; |
|
82 int i; |
|
83 |
|
84 d = pci_register_device(bus, "macio", |
|
85 sizeof(PCIDevice) + sizeof(macio_state_t), |
|
86 -1, NULL, NULL); |
|
87 macio_state = (macio_state_t *)(d + 1); |
|
88 macio_state->is_oldworld = is_oldworld; |
|
89 macio_state->pic_mem_index = pic_mem_index; |
|
90 macio_state->dbdma_mem_index = dbdma_mem_index; |
|
91 macio_state->cuda_mem_index = cuda_mem_index; |
|
92 macio_state->nvram = nvram; |
|
93 if (nb_ide > 4) |
|
94 nb_ide = 4; |
|
95 macio_state->nb_ide = nb_ide; |
|
96 for (i = 0; i < nb_ide; i++) |
|
97 macio_state->ide_mem_index[i] = ide_mem_index[i]; |
|
98 for (; i < 4; i++) |
|
99 macio_state->ide_mem_index[i] = -1; |
|
100 /* Note: this code is strongly inspirated from the corresponding code |
|
101 in PearPC */ |
|
102 d->config[0x00] = 0x6b; // vendor_id |
|
103 d->config[0x01] = 0x10; |
|
104 d->config[0x02] = device_id; |
|
105 d->config[0x03] = device_id >> 8; |
|
106 |
|
107 d->config[0x0a] = 0x00; // class_sub = pci2pci |
|
108 d->config[0x0b] = 0xff; // class_base = bridge |
|
109 d->config[0x0e] = 0x00; // header_type |
|
110 |
|
111 d->config[0x3d] = 0x01; // interrupt on pin 1 |
|
112 |
|
113 pci_register_io_region(d, 0, 0x80000, |
|
114 PCI_ADDRESS_SPACE_MEM, macio_map); |
|
115 } |