diff options
Diffstat (limited to 'arch/mips/pci/pci-ip27.c')
-rw-r--r-- | arch/mips/pci/pci-ip27.c | 292 |
1 files changed, 1 insertions, 291 deletions
diff --git a/arch/mips/pci/pci-ip27.c b/arch/mips/pci/pci-ip27.c index 662196d9fb58..80eb9af9ecdf 100644 --- a/arch/mips/pci/pci-ip27.c +++ b/arch/mips/pci/pci-ip27.c | |||
@@ -40,297 +40,7 @@ static struct bridge_controller bridges[MAX_PCI_BUSSES]; | |||
40 | struct bridge_controller *irq_to_bridge[MAX_PCI_BUSSES * MAX_DEVICES_PER_PCIBUS]; | 40 | struct bridge_controller *irq_to_bridge[MAX_PCI_BUSSES * MAX_DEVICES_PER_PCIBUS]; |
41 | int irq_to_slot[MAX_PCI_BUSSES * MAX_DEVICES_PER_PCIBUS]; | 41 | int irq_to_slot[MAX_PCI_BUSSES * MAX_DEVICES_PER_PCIBUS]; |
42 | 42 | ||
43 | /* | 43 | extern struct pci_ops bridge_pci_ops; |
44 | * The Bridge ASIC supports both type 0 and type 1 access. Type 1 is | ||
45 | * not really documented, so right now I can't write code which uses it. | ||
46 | * Therefore we use type 0 accesses for now even though they won't work | ||
47 | * correcly for PCI-to-PCI bridges. | ||
48 | * | ||
49 | * The function is complicated by the ultimate brokeness of the IOC3 chip | ||
50 | * which is used in SGI systems. The IOC3 can only handle 32-bit PCI | ||
51 | * accesses and does only decode parts of it's address space. | ||
52 | */ | ||
53 | |||
54 | static int pci_conf0_read_config(struct pci_bus *bus, unsigned int devfn, | ||
55 | int where, int size, u32 * value) | ||
56 | { | ||
57 | struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); | ||
58 | bridge_t *bridge = bc->base; | ||
59 | int slot = PCI_SLOT(devfn); | ||
60 | int fn = PCI_FUNC(devfn); | ||
61 | volatile void *addr; | ||
62 | u32 cf, shift, mask; | ||
63 | int res; | ||
64 | |||
65 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[PCI_VENDOR_ID]; | ||
66 | if (get_dbe(cf, (u32 *) addr)) | ||
67 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
68 | |||
69 | /* | ||
70 | * IOC3 is fucked fucked beyond believe ... Don't even give the | ||
71 | * generic PCI code a chance to look at it for real ... | ||
72 | */ | ||
73 | if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) | ||
74 | goto oh_my_gawd; | ||
75 | |||
76 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[where ^ (4 - size)]; | ||
77 | |||
78 | if (size == 1) | ||
79 | res = get_dbe(*value, (u8 *) addr); | ||
80 | else if (size == 2) | ||
81 | res = get_dbe(*value, (u16 *) addr); | ||
82 | else | ||
83 | res = get_dbe(*value, (u32 *) addr); | ||
84 | |||
85 | return res ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; | ||
86 | |||
87 | oh_my_gawd: | ||
88 | |||
89 | /* | ||
90 | * IOC3 is fucked fucked beyond believe ... Don't even give the | ||
91 | * generic PCI code a chance to look at the wrong register. | ||
92 | */ | ||
93 | if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) { | ||
94 | *value = 0; | ||
95 | return PCIBIOS_SUCCESSFUL; | ||
96 | } | ||
97 | |||
98 | /* | ||
99 | * IOC3 is fucked fucked beyond believe ... Don't try to access | ||
100 | * anything but 32-bit words ... | ||
101 | */ | ||
102 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; | ||
103 | |||
104 | if (get_dbe(cf, (u32 *) addr)) | ||
105 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
106 | |||
107 | shift = ((where & 3) << 3); | ||
108 | mask = (0xffffffffU >> ((4 - size) << 3)); | ||
109 | *value = (cf >> shift) & mask; | ||
110 | |||
111 | return PCIBIOS_SUCCESSFUL; | ||
112 | } | ||
113 | |||
114 | static int pci_conf1_read_config(struct pci_bus *bus, unsigned int devfn, | ||
115 | int where, int size, u32 * value) | ||
116 | { | ||
117 | struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); | ||
118 | bridge_t *bridge = bc->base; | ||
119 | int busno = bus->number; | ||
120 | int slot = PCI_SLOT(devfn); | ||
121 | int fn = PCI_FUNC(devfn); | ||
122 | volatile void *addr; | ||
123 | u32 cf, shift, mask; | ||
124 | int res; | ||
125 | |||
126 | bridge->b_pci_cfg = (busno << 16) | (slot << 11); | ||
127 | addr = &bridge->b_type1_cfg.c[(fn << 8) | PCI_VENDOR_ID]; | ||
128 | if (get_dbe(cf, (u32 *) addr)) | ||
129 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
130 | |||
131 | /* | ||
132 | * IOC3 is fucked fucked beyond believe ... Don't even give the | ||
133 | * generic PCI code a chance to look at it for real ... | ||
134 | */ | ||
135 | if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) | ||
136 | goto oh_my_gawd; | ||
137 | |||
138 | bridge->b_pci_cfg = (busno << 16) | (slot << 11); | ||
139 | addr = &bridge->b_type1_cfg.c[(fn << 8) | (where ^ (4 - size))]; | ||
140 | |||
141 | if (size == 1) | ||
142 | res = get_dbe(*value, (u8 *) addr); | ||
143 | else if (size == 2) | ||
144 | res = get_dbe(*value, (u16 *) addr); | ||
145 | else | ||
146 | res = get_dbe(*value, (u32 *) addr); | ||
147 | |||
148 | return res ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; | ||
149 | |||
150 | oh_my_gawd: | ||
151 | |||
152 | /* | ||
153 | * IOC3 is fucked fucked beyond believe ... Don't even give the | ||
154 | * generic PCI code a chance to look at the wrong register. | ||
155 | */ | ||
156 | if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) { | ||
157 | *value = 0; | ||
158 | return PCIBIOS_SUCCESSFUL; | ||
159 | } | ||
160 | |||
161 | /* | ||
162 | * IOC3 is fucked fucked beyond believe ... Don't try to access | ||
163 | * anything but 32-bit words ... | ||
164 | */ | ||
165 | bridge->b_pci_cfg = (busno << 16) | (slot << 11); | ||
166 | addr = &bridge->b_type1_cfg.c[(fn << 8) | where]; | ||
167 | |||
168 | if (get_dbe(cf, (u32 *) addr)) | ||
169 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
170 | |||
171 | shift = ((where & 3) << 3); | ||
172 | mask = (0xffffffffU >> ((4 - size) << 3)); | ||
173 | *value = (cf >> shift) & mask; | ||
174 | |||
175 | return PCIBIOS_SUCCESSFUL; | ||
176 | } | ||
177 | |||
178 | static int pci_read_config(struct pci_bus *bus, unsigned int devfn, | ||
179 | int where, int size, u32 * value) | ||
180 | { | ||
181 | if (bus->number > 0) | ||
182 | return pci_conf1_read_config(bus, devfn, where, size, value); | ||
183 | |||
184 | return pci_conf0_read_config(bus, devfn, where, size, value); | ||
185 | } | ||
186 | |||
187 | static int pci_conf0_write_config(struct pci_bus *bus, unsigned int devfn, | ||
188 | int where, int size, u32 value) | ||
189 | { | ||
190 | struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); | ||
191 | bridge_t *bridge = bc->base; | ||
192 | int slot = PCI_SLOT(devfn); | ||
193 | int fn = PCI_FUNC(devfn); | ||
194 | volatile void *addr; | ||
195 | u32 cf, shift, mask, smask; | ||
196 | int res; | ||
197 | |||
198 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[PCI_VENDOR_ID]; | ||
199 | if (get_dbe(cf, (u32 *) addr)) | ||
200 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
201 | |||
202 | /* | ||
203 | * IOC3 is fucked fucked beyond believe ... Don't even give the | ||
204 | * generic PCI code a chance to look at it for real ... | ||
205 | */ | ||
206 | if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) | ||
207 | goto oh_my_gawd; | ||
208 | |||
209 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[where ^ (4 - size)]; | ||
210 | |||
211 | if (size == 1) { | ||
212 | res = put_dbe(value, (u8 *) addr); | ||
213 | } else if (size == 2) { | ||
214 | res = put_dbe(value, (u16 *) addr); | ||
215 | } else { | ||
216 | res = put_dbe(value, (u32 *) addr); | ||
217 | } | ||
218 | |||
219 | if (res) | ||
220 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
221 | |||
222 | return PCIBIOS_SUCCESSFUL; | ||
223 | |||
224 | oh_my_gawd: | ||
225 | |||
226 | /* | ||
227 | * IOC3 is fucked fucked beyond believe ... Don't even give the | ||
228 | * generic PCI code a chance to touch the wrong register. | ||
229 | */ | ||
230 | if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) | ||
231 | return PCIBIOS_SUCCESSFUL; | ||
232 | |||
233 | /* | ||
234 | * IOC3 is fucked fucked beyond believe ... Don't try to access | ||
235 | * anything but 32-bit words ... | ||
236 | */ | ||
237 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; | ||
238 | |||
239 | if (get_dbe(cf, (u32 *) addr)) | ||
240 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
241 | |||
242 | shift = ((where & 3) << 3); | ||
243 | mask = (0xffffffffU >> ((4 - size) << 3)); | ||
244 | smask = mask << shift; | ||
245 | |||
246 | cf = (cf & ~smask) | ((value & mask) << shift); | ||
247 | if (put_dbe(cf, (u32 *) addr)) | ||
248 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
249 | |||
250 | return PCIBIOS_SUCCESSFUL; | ||
251 | } | ||
252 | |||
253 | static int pci_conf1_write_config(struct pci_bus *bus, unsigned int devfn, | ||
254 | int where, int size, u32 value) | ||
255 | { | ||
256 | struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); | ||
257 | bridge_t *bridge = bc->base; | ||
258 | int slot = PCI_SLOT(devfn); | ||
259 | int fn = PCI_FUNC(devfn); | ||
260 | int busno = bus->number; | ||
261 | volatile void *addr; | ||
262 | u32 cf, shift, mask, smask; | ||
263 | int res; | ||
264 | |||
265 | bridge->b_pci_cfg = (busno << 16) | (slot << 11); | ||
266 | addr = &bridge->b_type1_cfg.c[(fn << 8) | PCI_VENDOR_ID]; | ||
267 | if (get_dbe(cf, (u32 *) addr)) | ||
268 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
269 | |||
270 | /* | ||
271 | * IOC3 is fucked fucked beyond believe ... Don't even give the | ||
272 | * generic PCI code a chance to look at it for real ... | ||
273 | */ | ||
274 | if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) | ||
275 | goto oh_my_gawd; | ||
276 | |||
277 | addr = &bridge->b_type1_cfg.c[(fn << 8) | (where ^ (4 - size))]; | ||
278 | |||
279 | if (size == 1) { | ||
280 | res = put_dbe(value, (u8 *) addr); | ||
281 | } else if (size == 2) { | ||
282 | res = put_dbe(value, (u16 *) addr); | ||
283 | } else { | ||
284 | res = put_dbe(value, (u32 *) addr); | ||
285 | } | ||
286 | |||
287 | if (res) | ||
288 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
289 | |||
290 | return PCIBIOS_SUCCESSFUL; | ||
291 | |||
292 | oh_my_gawd: | ||
293 | |||
294 | /* | ||
295 | * IOC3 is fucked fucked beyond believe ... Don't even give the | ||
296 | * generic PCI code a chance to touch the wrong register. | ||
297 | */ | ||
298 | if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) | ||
299 | return PCIBIOS_SUCCESSFUL; | ||
300 | |||
301 | /* | ||
302 | * IOC3 is fucked fucked beyond believe ... Don't try to access | ||
303 | * anything but 32-bit words ... | ||
304 | */ | ||
305 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; | ||
306 | |||
307 | if (get_dbe(cf, (u32 *) addr)) | ||
308 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
309 | |||
310 | shift = ((where & 3) << 3); | ||
311 | mask = (0xffffffffU >> ((4 - size) << 3)); | ||
312 | smask = mask << shift; | ||
313 | |||
314 | cf = (cf & ~smask) | ((value & mask) << shift); | ||
315 | if (put_dbe(cf, (u32 *) addr)) | ||
316 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
317 | |||
318 | return PCIBIOS_SUCCESSFUL; | ||
319 | } | ||
320 | |||
321 | static int pci_write_config(struct pci_bus *bus, unsigned int devfn, | ||
322 | int where, int size, u32 value) | ||
323 | { | ||
324 | if (bus->number > 0) | ||
325 | return pci_conf1_write_config(bus, devfn, where, size, value); | ||
326 | |||
327 | return pci_conf0_write_config(bus, devfn, where, size, value); | ||
328 | } | ||
329 | |||
330 | static struct pci_ops bridge_pci_ops = { | ||
331 | .read = pci_read_config, | ||
332 | .write = pci_write_config, | ||
333 | }; | ||
334 | 44 | ||
335 | int __init bridge_probe(nasid_t nasid, int widget_id, int masterwid) | 45 | int __init bridge_probe(nasid_t nasid, int widget_id, int masterwid) |
336 | { | 46 | { |