Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * PCI autoconfiguration library | |
3 | * | |
4 | * Author: Matt Porter <mporter@mvista.com> | |
5 | * | |
6 | * Copyright 2000, 2001 MontaVista Software Inc. | |
7 | * Copyright 2001 Bradley D. LaRonde <brad@ltc.com> | |
8 | * Copyright 2003 Paul Mundt <lethal@linux-sh.org> | |
9 | * | |
10 | * This program is free software; you can redistribute it and/or modify it | |
11 | * under the terms of the GNU General Public License as published by the | |
12 | * Free Software Foundation; either version 2 of the License, or (at your | |
13 | * option) any later version. | |
14 | */ | |
15 | ||
16 | /* | |
17 | * Modified for MIPS by Jun Sun, jsun@mvista.com | |
18 | * | |
19 | * . Simplify the interface between pci_auto and the rest: a single function. | |
20 | * . Assign resources from low address to upper address. | |
21 | * . change most int to u32. | |
22 | * | |
23 | * Further modified to include it as mips generic code, ppopov@mvista.com. | |
24 | * | |
25 | * 2001-10-26 Bradley D. LaRonde <brad@ltc.com> | |
26 | * - Add a top_bus argument to the "early config" functions so that | |
27 | * they can set a fake parent bus pointer to convince the underlying | |
28 | * pci ops to use type 1 configuration for sub busses. | |
29 | * - Set bridge base and limit registers correctly. | |
30 | * - Align io and memory base properly before and after bridge setup. | |
31 | * - Don't fall through to pci_setup_bars for bridge. | |
32 | * - Reformat the debug output to look more like lspci's output. | |
33 | * | |
34 | * Cloned for SuperH by M. R. Brown, mrbrown@0xd6.org | |
35 | * | |
36 | * 2003-08-05 Paul Mundt <lethal@linux-sh.org> | |
37 | * - Don't update the BAR values on systems that already have valid addresses | |
38 | * and don't want these updated for whatever reason, by way of a new config | |
39 | * option check. However, we still read in the old BAR values so that they | |
40 | * can still be reported through the debug output. | |
41 | */ | |
42 | ||
43 | #include <linux/kernel.h> | |
44 | #include <linux/init.h> | |
45 | #include <linux/types.h> | |
46 | #include <linux/pci.h> | |
47 | ||
5283ecb5 PM |
48 | #define DEBUG |
49 | #ifdef DEBUG | |
1da177e4 LT |
50 | #define DBG(x...) printk(x) |
51 | #else | |
5283ecb5 | 52 | #define DBG(x...) |
1da177e4 LT |
53 | #endif |
54 | ||
55 | /* | |
56 | * These functions are used early on before PCI scanning is done | |
57 | * and all of the pci_dev and pci_bus structures have been created. | |
58 | */ | |
59 | static struct pci_dev *fake_pci_dev(struct pci_channel *hose, | |
60 | int top_bus, int busnr, int devfn) | |
61 | { | |
62 | static struct pci_dev dev; | |
63 | static struct pci_bus bus; | |
64 | ||
65 | dev.bus = &bus; | |
66 | dev.sysdata = hose; | |
67 | dev.devfn = devfn; | |
68 | bus.number = busnr; | |
69 | bus.ops = hose->pci_ops; | |
70 | ||
71 | if(busnr != top_bus) | |
72 | /* Fake a parent bus structure. */ | |
73 | bus.parent = &bus; | |
74 | else | |
75 | bus.parent = NULL; | |
76 | ||
77 | return &dev; | |
78 | } | |
79 | ||
80 | #define EARLY_PCI_OP(rw, size, type) \ | |
175fb09f | 81 | static int early_##rw##_config_##size(struct pci_channel *hose, \ |
1da177e4 LT |
82 | int top_bus, int bus, int devfn, int offset, type value) \ |
83 | { \ | |
84 | return pci_##rw##_config_##size( \ | |
85 | fake_pci_dev(hose, top_bus, bus, devfn), \ | |
86 | offset, value); \ | |
87 | } | |
88 | ||
89 | EARLY_PCI_OP(read, byte, u8 *) | |
90 | EARLY_PCI_OP(read, word, u16 *) | |
91 | EARLY_PCI_OP(read, dword, u32 *) | |
92 | EARLY_PCI_OP(write, byte, u8) | |
93 | EARLY_PCI_OP(write, word, u16) | |
94 | EARLY_PCI_OP(write, dword, u32) | |
95 | ||
96 | static struct resource *io_resource_inuse; | |
97 | static struct resource *mem_resource_inuse; | |
98 | ||
99 | static u32 pciauto_lower_iospc; | |
100 | static u32 pciauto_upper_iospc; | |
101 | ||
102 | static u32 pciauto_lower_memspc; | |
103 | static u32 pciauto_upper_memspc; | |
104 | ||
5283ecb5 | 105 | static void __init |
1da177e4 LT |
106 | pciauto_setup_bars(struct pci_channel *hose, |
107 | int top_bus, | |
108 | int current_bus, | |
109 | int pci_devfn, | |
110 | int bar_limit) | |
111 | { | |
112 | u32 bar_response, bar_size, bar_value; | |
113 | u32 bar, addr_mask, bar_nr = 0; | |
114 | u32 * upper_limit; | |
115 | u32 * lower_limit; | |
116 | int found_mem64 = 0; | |
117 | ||
118 | for (bar = PCI_BASE_ADDRESS_0; bar <= bar_limit; bar+=4) { | |
1da177e4 LT |
119 | u32 bar_addr; |
120 | ||
121 | /* Read the old BAR value */ | |
122 | early_read_config_dword(hose, top_bus, | |
123 | current_bus, | |
124 | pci_devfn, | |
125 | bar, | |
126 | &bar_addr); | |
1da177e4 LT |
127 | |
128 | /* Tickle the BAR and get the response */ | |
129 | early_write_config_dword(hose, top_bus, | |
130 | current_bus, | |
131 | pci_devfn, | |
132 | bar, | |
133 | 0xffffffff); | |
134 | ||
135 | early_read_config_dword(hose, top_bus, | |
136 | current_bus, | |
137 | pci_devfn, | |
138 | bar, | |
139 | &bar_response); | |
140 | ||
5283ecb5 | 141 | /* |
1da177e4 LT |
142 | * Write the old BAR value back out, only update the BAR |
143 | * if we implicitly want resources to be updated, which | |
144 | * is done by the generic code further down. -- PFM. | |
145 | */ | |
146 | early_write_config_dword(hose, top_bus, | |
147 | current_bus, | |
148 | pci_devfn, | |
149 | bar, | |
150 | bar_addr); | |
1da177e4 LT |
151 | |
152 | /* If BAR is not implemented go to the next BAR */ | |
153 | if (!bar_response) | |
154 | continue; | |
155 | ||
156 | /* | |
157 | * Workaround for a BAR that doesn't use its upper word, | |
158 | * like the ALi 1535D+ PCI DC-97 Controller Modem (M5457). | |
159 | * bdl <brad@ltc.com> | |
160 | */ | |
161 | if (!(bar_response & 0xffff0000)) | |
162 | bar_response |= 0xffff0000; | |
163 | ||
164 | retry: | |
165 | /* Check the BAR type and set our address mask */ | |
166 | if (bar_response & PCI_BASE_ADDRESS_SPACE) { | |
167 | addr_mask = PCI_BASE_ADDRESS_IO_MASK; | |
168 | upper_limit = &pciauto_upper_iospc; | |
169 | lower_limit = &pciauto_lower_iospc; | |
170 | DBG(" I/O"); | |
171 | } else { | |
172 | if ((bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == | |
173 | PCI_BASE_ADDRESS_MEM_TYPE_64) | |
174 | found_mem64 = 1; | |
175 | ||
5283ecb5 | 176 | addr_mask = PCI_BASE_ADDRESS_MEM_MASK; |
1da177e4 LT |
177 | upper_limit = &pciauto_upper_memspc; |
178 | lower_limit = &pciauto_lower_memspc; | |
179 | DBG(" Mem"); | |
180 | } | |
181 | ||
182 | ||
183 | /* Calculate requested size */ | |
184 | bar_size = ~(bar_response & addr_mask) + 1; | |
185 | ||
186 | /* Allocate a base address */ | |
187 | bar_value = ((*lower_limit - 1) & ~(bar_size - 1)) + bar_size; | |
188 | ||
189 | if ((bar_value + bar_size) > *upper_limit) { | |
190 | if (bar_response & PCI_BASE_ADDRESS_SPACE) { | |
191 | if (io_resource_inuse->child) { | |
5283ecb5 | 192 | io_resource_inuse = |
1da177e4 | 193 | io_resource_inuse->child; |
5283ecb5 | 194 | pciauto_lower_iospc = |
1da177e4 | 195 | io_resource_inuse->start; |
5283ecb5 | 196 | pciauto_upper_iospc = |
1da177e4 LT |
197 | io_resource_inuse->end + 1; |
198 | goto retry; | |
199 | } | |
200 | ||
201 | } else { | |
202 | if (mem_resource_inuse->child) { | |
5283ecb5 | 203 | mem_resource_inuse = |
1da177e4 | 204 | mem_resource_inuse->child; |
5283ecb5 | 205 | pciauto_lower_memspc = |
1da177e4 | 206 | mem_resource_inuse->start; |
5283ecb5 | 207 | pciauto_upper_memspc = |
1da177e4 LT |
208 | mem_resource_inuse->end + 1; |
209 | goto retry; | |
210 | } | |
211 | } | |
212 | DBG(" unavailable -- skipping, value %x size %x\n", | |
213 | bar_value, bar_size); | |
214 | continue; | |
215 | } | |
216 | ||
bb686609 HS |
217 | if (bar_value < *lower_limit || (bar_value + bar_size) >= *upper_limit) { |
218 | DBG(" unavailable -- skipping, value %x size %x\n", | |
219 | bar_value, bar_size); | |
220 | continue; | |
221 | } | |
222 | ||
1da177e4 LT |
223 | #ifdef CONFIG_PCI_AUTO_UPDATE_RESOURCES |
224 | /* Write it out and update our limit */ | |
225 | early_write_config_dword(hose, top_bus, current_bus, pci_devfn, | |
226 | bar, bar_value); | |
227 | #endif | |
228 | ||
229 | *lower_limit = bar_value + bar_size; | |
230 | ||
231 | /* | |
232 | * If we are a 64-bit decoder then increment to the | |
233 | * upper 32 bits of the bar and force it to locate | |
234 | * in the lower 4GB of memory. | |
5283ecb5 | 235 | */ |
1da177e4 LT |
236 | if (found_mem64) { |
237 | bar += 4; | |
238 | early_write_config_dword(hose, top_bus, | |
239 | current_bus, | |
240 | pci_devfn, | |
241 | bar, | |
242 | 0x00000000); | |
243 | } | |
244 | ||
245 | DBG(" at 0x%.8x [size=0x%x]\n", bar_value, bar_size); | |
246 | ||
247 | bar_nr++; | |
248 | } | |
249 | ||
250 | } | |
251 | ||
252 | static void __init | |
253 | pciauto_prescan_setup_bridge(struct pci_channel *hose, | |
254 | int top_bus, | |
255 | int current_bus, | |
256 | int pci_devfn, | |
257 | int sub_bus) | |
258 | { | |
259 | /* Configure bus number registers */ | |
260 | early_write_config_byte(hose, top_bus, current_bus, pci_devfn, | |
261 | PCI_PRIMARY_BUS, current_bus); | |
262 | early_write_config_byte(hose, top_bus, current_bus, pci_devfn, | |
263 | PCI_SECONDARY_BUS, sub_bus + 1); | |
264 | early_write_config_byte(hose, top_bus, current_bus, pci_devfn, | |
265 | PCI_SUBORDINATE_BUS, 0xff); | |
266 | ||
267 | /* Align memory and I/O to 1MB and 4KB boundaries. */ | |
268 | pciauto_lower_memspc = (pciauto_lower_memspc + (0x100000 - 1)) | |
269 | & ~(0x100000 - 1); | |
270 | pciauto_lower_iospc = (pciauto_lower_iospc + (0x1000 - 1)) | |
271 | & ~(0x1000 - 1); | |
272 | ||
273 | /* Set base (lower limit) of address range behind bridge. */ | |
274 | early_write_config_word(hose, top_bus, current_bus, pci_devfn, | |
275 | PCI_MEMORY_BASE, pciauto_lower_memspc >> 16); | |
276 | early_write_config_byte(hose, top_bus, current_bus, pci_devfn, | |
277 | PCI_IO_BASE, (pciauto_lower_iospc & 0x0000f000) >> 8); | |
278 | early_write_config_word(hose, top_bus, current_bus, pci_devfn, | |
279 | PCI_IO_BASE_UPPER16, pciauto_lower_iospc >> 16); | |
280 | ||
281 | /* We don't support prefetchable memory for now, so disable */ | |
282 | early_write_config_word(hose, top_bus, current_bus, pci_devfn, | |
283 | PCI_PREF_MEMORY_BASE, 0); | |
284 | early_write_config_word(hose, top_bus, current_bus, pci_devfn, | |
285 | PCI_PREF_MEMORY_LIMIT, 0); | |
286 | } | |
287 | ||
288 | static void __init | |
289 | pciauto_postscan_setup_bridge(struct pci_channel *hose, | |
290 | int top_bus, | |
291 | int current_bus, | |
292 | int pci_devfn, | |
293 | int sub_bus) | |
294 | { | |
295 | u32 temp; | |
296 | ||
297 | /* | |
298 | * [jsun] we always bump up baselines a little, so that if there | |
299 | * nothing behind P2P bridge, we don't wind up overlapping IO/MEM | |
300 | * spaces. | |
301 | */ | |
302 | pciauto_lower_memspc += 1; | |
303 | pciauto_lower_iospc += 1; | |
304 | ||
305 | /* Configure bus number registers */ | |
306 | early_write_config_byte(hose, top_bus, current_bus, pci_devfn, | |
307 | PCI_SUBORDINATE_BUS, sub_bus); | |
308 | ||
309 | /* Set upper limit of address range behind bridge. */ | |
310 | early_write_config_word(hose, top_bus, current_bus, pci_devfn, | |
311 | PCI_MEMORY_LIMIT, pciauto_lower_memspc >> 16); | |
312 | early_write_config_byte(hose, top_bus, current_bus, pci_devfn, | |
313 | PCI_IO_LIMIT, (pciauto_lower_iospc & 0x0000f000) >> 8); | |
314 | early_write_config_word(hose, top_bus, current_bus, pci_devfn, | |
315 | PCI_IO_LIMIT_UPPER16, pciauto_lower_iospc >> 16); | |
316 | ||
317 | /* Align memory and I/O to 1MB and 4KB boundaries. */ | |
318 | pciauto_lower_memspc = (pciauto_lower_memspc + (0x100000 - 1)) | |
319 | & ~(0x100000 - 1); | |
320 | pciauto_lower_iospc = (pciauto_lower_iospc + (0x1000 - 1)) | |
321 | & ~(0x1000 - 1); | |
322 | ||
323 | /* Enable memory and I/O accesses, enable bus master */ | |
324 | early_read_config_dword(hose, top_bus, current_bus, pci_devfn, | |
325 | PCI_COMMAND, &temp); | |
326 | early_write_config_dword(hose, top_bus, current_bus, pci_devfn, | |
327 | PCI_COMMAND, temp | PCI_COMMAND_IO | PCI_COMMAND_MEMORY | |
328 | | PCI_COMMAND_MASTER); | |
329 | } | |
330 | ||
331 | static void __init | |
332 | pciauto_prescan_setup_cardbus_bridge(struct pci_channel *hose, | |
333 | int top_bus, | |
334 | int current_bus, | |
335 | int pci_devfn, | |
336 | int sub_bus) | |
337 | { | |
338 | /* Configure bus number registers */ | |
339 | early_write_config_byte(hose, top_bus, current_bus, pci_devfn, | |
340 | PCI_PRIMARY_BUS, current_bus); | |
341 | early_write_config_byte(hose, top_bus, current_bus, pci_devfn, | |
342 | PCI_SECONDARY_BUS, sub_bus + 1); | |
343 | early_write_config_byte(hose, top_bus, current_bus, pci_devfn, | |
344 | PCI_SUBORDINATE_BUS, 0xff); | |
345 | ||
346 | /* Align memory and I/O to 4KB and 4 byte boundaries. */ | |
347 | pciauto_lower_memspc = (pciauto_lower_memspc + (0x1000 - 1)) | |
348 | & ~(0x1000 - 1); | |
349 | pciauto_lower_iospc = (pciauto_lower_iospc + (0x4 - 1)) | |
350 | & ~(0x4 - 1); | |
351 | ||
352 | early_write_config_dword(hose, top_bus, current_bus, pci_devfn, | |
353 | PCI_CB_MEMORY_BASE_0, pciauto_lower_memspc); | |
354 | early_write_config_dword(hose, top_bus, current_bus, pci_devfn, | |
355 | PCI_CB_IO_BASE_0, pciauto_lower_iospc); | |
356 | } | |
357 | ||
358 | static void __init | |
359 | pciauto_postscan_setup_cardbus_bridge(struct pci_channel *hose, | |
360 | int top_bus, | |
361 | int current_bus, | |
362 | int pci_devfn, | |
363 | int sub_bus) | |
364 | { | |
365 | u32 temp; | |
366 | ||
1da177e4 LT |
367 | /* |
368 | * [jsun] we always bump up baselines a little, so that if there | |
369 | * nothing behind P2P bridge, we don't wind up overlapping IO/MEM | |
370 | * spaces. | |
371 | */ | |
372 | pciauto_lower_memspc += 1; | |
373 | pciauto_lower_iospc += 1; | |
1da177e4 LT |
374 | |
375 | /* | |
376 | * Configure subordinate bus number. The PCI subsystem | |
377 | * bus scan will renumber buses (reserving three additional | |
378 | * for this PCI<->CardBus bridge for the case where a CardBus | |
379 | * adapter contains a P2P or CB2CB bridge. | |
380 | */ | |
381 | ||
382 | early_write_config_byte(hose, top_bus, current_bus, pci_devfn, | |
383 | PCI_SUBORDINATE_BUS, sub_bus); | |
384 | ||
385 | /* | |
386 | * Reserve an additional 4MB for mem space and 16KB for | |
387 | * I/O space. This should cover any additional space | |
388 | * requirement of unusual CardBus devices with | |
389 | * additional bridges that can consume more address space. | |
390 | * | |
391 | * Although pcmcia-cs currently will reprogram bridge | |
392 | * windows, the goal is to add an option to leave them | |
393 | * alone and use the bridge window ranges as the regions | |
394 | * that are searched for free resources upon hot-insertion | |
395 | * of a device. This will allow a PCI<->CardBus bridge | |
396 | * configured by this routine to happily live behind a | |
397 | * P2P bridge in a system. | |
398 | */ | |
1da177e4 LT |
399 | /* Align memory and I/O to 4KB and 4 byte boundaries. */ |
400 | pciauto_lower_memspc = (pciauto_lower_memspc + (0x1000 - 1)) | |
401 | & ~(0x1000 - 1); | |
402 | pciauto_lower_iospc = (pciauto_lower_iospc + (0x4 - 1)) | |
403 | & ~(0x4 - 1); | |
404 | /* Set up memory and I/O filter limits, assume 32-bit I/O space */ | |
405 | early_write_config_dword(hose, top_bus, current_bus, pci_devfn, | |
406 | PCI_CB_MEMORY_LIMIT_0, pciauto_lower_memspc - 1); | |
407 | early_write_config_dword(hose, top_bus, current_bus, pci_devfn, | |
408 | PCI_CB_IO_LIMIT_0, pciauto_lower_iospc - 1); | |
409 | ||
410 | /* Enable memory and I/O accesses, enable bus master */ | |
411 | early_read_config_dword(hose, top_bus, current_bus, pci_devfn, | |
412 | PCI_COMMAND, &temp); | |
413 | early_write_config_dword(hose, top_bus, current_bus, pci_devfn, | |
414 | PCI_COMMAND, temp | PCI_COMMAND_IO | PCI_COMMAND_MEMORY | | |
415 | PCI_COMMAND_MASTER); | |
416 | } | |
417 | ||
418 | #define PCIAUTO_IDE_MODE_MASK 0x05 | |
419 | ||
420 | static int __init | |
421 | pciauto_bus_scan(struct pci_channel *hose, int top_bus, int current_bus) | |
422 | { | |
423 | int sub_bus; | |
424 | u32 pci_devfn, pci_class, cmdstat, found_multi=0; | |
425 | unsigned short vid, did; | |
426 | unsigned char header_type; | |
427 | int devfn_start = 0; | |
428 | int devfn_stop = 0xff; | |
429 | ||
430 | sub_bus = current_bus; | |
5283ecb5 | 431 | |
1da177e4 LT |
432 | if (hose->first_devfn) |
433 | devfn_start = hose->first_devfn; | |
434 | if (hose->last_devfn) | |
435 | devfn_stop = hose->last_devfn; | |
5283ecb5 | 436 | |
1da177e4 LT |
437 | for (pci_devfn=devfn_start; pci_devfn<devfn_stop; pci_devfn++) { |
438 | ||
439 | if (PCI_FUNC(pci_devfn) && !found_multi) | |
440 | continue; | |
441 | ||
442 | early_read_config_word(hose, top_bus, current_bus, pci_devfn, | |
443 | PCI_VENDOR_ID, &vid); | |
444 | ||
445 | if (vid == 0xffff) continue; | |
446 | ||
447 | early_read_config_byte(hose, top_bus, current_bus, pci_devfn, | |
448 | PCI_HEADER_TYPE, &header_type); | |
449 | ||
450 | if (!PCI_FUNC(pci_devfn)) | |
451 | found_multi = header_type & 0x80; | |
452 | ||
453 | early_read_config_word(hose, top_bus, current_bus, pci_devfn, | |
454 | PCI_DEVICE_ID, &did); | |
455 | ||
456 | early_read_config_dword(hose, top_bus, current_bus, pci_devfn, | |
457 | PCI_CLASS_REVISION, &pci_class); | |
458 | ||
459 | DBG("%.2x:%.2x.%x Class %.4x: %.4x:%.4x", | |
460 | current_bus, PCI_SLOT(pci_devfn), PCI_FUNC(pci_devfn), | |
461 | pci_class >> 16, vid, did); | |
462 | if (pci_class & 0xff) | |
463 | DBG(" (rev %.2x)", pci_class & 0xff); | |
464 | DBG("\n"); | |
465 | ||
466 | if ((pci_class >> 16) == PCI_CLASS_BRIDGE_PCI) { | |
467 | DBG(" Bridge: primary=%.2x, secondary=%.2x\n", | |
468 | current_bus, sub_bus + 1); | |
1da177e4 LT |
469 | pciauto_prescan_setup_bridge(hose, top_bus, current_bus, |
470 | pci_devfn, sub_bus); | |
471 | DBG("Scanning sub bus %.2x, I/O 0x%.8x, Mem 0x%.8x\n", | |
472 | sub_bus + 1, | |
473 | pciauto_lower_iospc, pciauto_lower_memspc); | |
474 | sub_bus = pciauto_bus_scan(hose, top_bus, sub_bus+1); | |
475 | DBG("Back to bus %.2x\n", current_bus); | |
476 | pciauto_postscan_setup_bridge(hose, top_bus, current_bus, | |
477 | pci_devfn, sub_bus); | |
478 | continue; | |
479 | } else if ((pci_class >> 16) == PCI_CLASS_BRIDGE_CARDBUS) { | |
480 | DBG(" CARDBUS Bridge: primary=%.2x, secondary=%.2x\n", | |
481 | current_bus, sub_bus + 1); | |
482 | DBG("PCI Autoconfig: Found CardBus bridge, device %d function %d\n", PCI_SLOT(pci_devfn), PCI_FUNC(pci_devfn)); | |
483 | /* Place CardBus Socket/ExCA registers */ | |
484 | pciauto_setup_bars(hose, top_bus, current_bus, pci_devfn, PCI_BASE_ADDRESS_0); | |
5283ecb5 | 485 | |
1da177e4 LT |
486 | pciauto_prescan_setup_cardbus_bridge(hose, top_bus, |
487 | current_bus, pci_devfn, sub_bus); | |
5283ecb5 | 488 | |
1da177e4 LT |
489 | DBG("Scanning sub bus %.2x, I/O 0x%.8x, Mem 0x%.8x\n", |
490 | sub_bus + 1, | |
491 | pciauto_lower_iospc, pciauto_lower_memspc); | |
492 | sub_bus = pciauto_bus_scan(hose, top_bus, sub_bus+1); | |
493 | DBG("Back to bus %.2x, sub_bus is %x\n", current_bus, sub_bus); | |
494 | pciauto_postscan_setup_cardbus_bridge(hose, top_bus, | |
495 | current_bus, pci_devfn, sub_bus); | |
496 | continue; | |
497 | } else if ((pci_class >> 16) == PCI_CLASS_STORAGE_IDE) { | |
498 | ||
499 | unsigned char prg_iface; | |
500 | ||
501 | early_read_config_byte(hose, top_bus, current_bus, | |
502 | pci_devfn, PCI_CLASS_PROG, &prg_iface); | |
503 | if (!(prg_iface & PCIAUTO_IDE_MODE_MASK)) { | |
504 | DBG("Skipping legacy mode IDE controller\n"); | |
505 | continue; | |
506 | } | |
507 | } | |
508 | ||
509 | /* | |
510 | * Found a peripheral, enable some standard | |
511 | * settings | |
512 | */ | |
513 | early_read_config_dword(hose, top_bus, current_bus, pci_devfn, | |
514 | PCI_COMMAND, &cmdstat); | |
515 | early_write_config_dword(hose, top_bus, current_bus, pci_devfn, | |
516 | PCI_COMMAND, cmdstat | PCI_COMMAND_IO | | |
517 | PCI_COMMAND_MEMORY | | |
518 | PCI_COMMAND_MASTER); | |
1da177e4 LT |
519 | early_write_config_byte(hose, top_bus, current_bus, pci_devfn, |
520 | PCI_LATENCY_TIMER, 0x80); | |
1da177e4 LT |
521 | |
522 | /* Allocate PCI I/O and/or memory space */ | |
523 | pciauto_setup_bars(hose, top_bus, current_bus, pci_devfn, PCI_BASE_ADDRESS_5); | |
524 | } | |
525 | return sub_bus; | |
526 | } | |
527 | ||
528 | int __init | |
529 | pciauto_assign_resources(int busno, struct pci_channel *hose) | |
530 | { | |
531 | /* setup resource limits */ | |
532 | io_resource_inuse = hose->io_resource; | |
533 | mem_resource_inuse = hose->mem_resource; | |
534 | ||
535 | pciauto_lower_iospc = io_resource_inuse->start; | |
536 | pciauto_upper_iospc = io_resource_inuse->end + 1; | |
537 | pciauto_lower_memspc = mem_resource_inuse->start; | |
538 | pciauto_upper_memspc = mem_resource_inuse->end + 1; | |
539 | DBG("Autoconfig PCI channel 0x%p\n", hose); | |
540 | DBG("Scanning bus %.2x, I/O 0x%.8x:0x%.8x, Mem 0x%.8x:0x%.8x\n", | |
541 | busno, pciauto_lower_iospc, pciauto_upper_iospc, | |
542 | pciauto_lower_memspc, pciauto_upper_memspc); | |
543 | ||
544 | return pciauto_bus_scan(hose, busno, busno); | |
545 | } |