1 | /* |
---|
2 | * pci.c -- Crude pci handling for early boot. |
---|
3 | * |
---|
4 | * Copyright (C) 1998, 1999 Gabriel Paubert, paubert@iram.es |
---|
5 | * |
---|
6 | * Modified to compile in RTEMS development environment |
---|
7 | * by Eric Valette |
---|
8 | * |
---|
9 | * Copyright (C) 1999 Eric Valette. valette@crf.canon.fr |
---|
10 | * |
---|
11 | * The license and distribution terms for this file may be |
---|
12 | * found in found in the file LICENSE in this distribution or at |
---|
13 | * http://www.rtems.com/license/LICENSE. |
---|
14 | * |
---|
15 | * $Id$ |
---|
16 | */ |
---|
17 | |
---|
18 | #include <sys/types.h> |
---|
19 | #include <rtems/bspIo.h> |
---|
20 | #include <libcpu/spr.h> |
---|
21 | #include "bootldr.h" |
---|
22 | #include "pci.h" |
---|
23 | #include <libcpu/io.h> |
---|
24 | #include <libcpu/page.h> |
---|
25 | #include <bsp/consoleIo.h> |
---|
26 | #include <string.h> |
---|
27 | |
---|
28 | #include <string.h> |
---|
29 | |
---|
30 | |
---|
31 | /* |
---|
32 | #define DEBUG |
---|
33 | #define PCI_DEBUG |
---|
34 | */ |
---|
35 | |
---|
36 | /* Used to reorganize PCI space on stupid machines which spread resources |
---|
37 | * across a wide address space. This is bad when P2P bridges are present |
---|
38 | * or when it limits the mappings that a resource hog like a PCI<->VME |
---|
39 | * bridge can use. |
---|
40 | */ |
---|
41 | |
---|
42 | typedef struct _pci_resource { |
---|
43 | struct _pci_resource *next; |
---|
44 | struct pci_dev *dev; |
---|
45 | u_long base; /* will be 64 bits on 64 bits machines */ |
---|
46 | u_long size; |
---|
47 | u_char type; /* 1 is I/O else low order 4 bits of the memory type */ |
---|
48 | u_char reg; /* Register # in conf space header */ |
---|
49 | u_short cmd; /* Original cmd byte */ |
---|
50 | } pci_resource; |
---|
51 | |
---|
52 | typedef struct _pci_area { |
---|
53 | struct _pci_area *next; |
---|
54 | u_long start; |
---|
55 | u_long end; |
---|
56 | struct pci_bus *bus; |
---|
57 | u_int flags; |
---|
58 | } pci_area; |
---|
59 | |
---|
60 | typedef struct _pci_area_head { |
---|
61 | pci_area *head; |
---|
62 | u_long mask; |
---|
63 | int high; /* To allocate from top */ |
---|
64 | } pci_area_head; |
---|
65 | |
---|
66 | #define PCI_AREA_PREFETCHABLE 0 |
---|
67 | #define PCI_AREA_MEMORY 1 |
---|
68 | #define PCI_AREA_IO 2 |
---|
69 | |
---|
70 | struct _pci_private { |
---|
71 | volatile u_int * config_addr; |
---|
72 | volatile u_char * config_data; |
---|
73 | struct pci_dev **last_dev_p; |
---|
74 | struct pci_bus pci_root; |
---|
75 | pci_resource *resources; |
---|
76 | pci_area_head io, mem; |
---|
77 | |
---|
78 | } pci_private = { |
---|
79 | config_addr: NULL, |
---|
80 | config_data: (volatile u_char *) 0x80800000, |
---|
81 | last_dev_p: NULL, |
---|
82 | resources: NULL, |
---|
83 | io: {NULL, 0xfff, 0}, |
---|
84 | mem: {NULL, 0xfffff, 0} |
---|
85 | }; |
---|
86 | |
---|
87 | #define pci ((struct _pci_private *)(bd->pci_private)) |
---|
88 | #define pci_root pci->pci_root |
---|
89 | |
---|
90 | #if !defined(DEBUG) |
---|
91 | #undef PCI_DEBUG |
---|
92 | /* |
---|
93 | #else |
---|
94 | #define PCI_DEBUG |
---|
95 | */ |
---|
96 | #endif |
---|
97 | |
---|
98 | #if defined(PCI_DEBUG) |
---|
99 | static void |
---|
100 | print_pci_resources(const char *s) { |
---|
101 | pci_resource *p; |
---|
102 | printk("%s", s); |
---|
103 | for (p=pci->resources; p; p=p->next) { |
---|
104 | /* |
---|
105 | printk(" %p:%p %06x %08lx %08lx %d\n", |
---|
106 | p, p->next, |
---|
107 | (p->dev->devfn<<8)+(p->dev->bus->number<<16) |
---|
108 | +0x10+p->reg*4, |
---|
109 | p->base, |
---|
110 | p->size, |
---|
111 | p->type); |
---|
112 | */ |
---|
113 | |
---|
114 | printk(" %p:%p %d:%02x (%04x:%04x) %08lx %08lx %d\n", |
---|
115 | p, p->next, |
---|
116 | p->dev->bus->number, PCI_SLOT(p->dev->devfn), |
---|
117 | p->dev->vendor, p->dev->device, |
---|
118 | p->base, |
---|
119 | p->size, |
---|
120 | p->type); |
---|
121 | |
---|
122 | } |
---|
123 | } |
---|
124 | |
---|
125 | static void |
---|
126 | print_pci_area(pci_area *p) { |
---|
127 | for (; p; p=p->next) { |
---|
128 | printk(" %p:%p %p %08lx %08lx\n", |
---|
129 | p, p->next, p->bus, p->start, p->end); |
---|
130 | } |
---|
131 | } |
---|
132 | |
---|
133 | static void |
---|
134 | print_pci_areas(const char *s) { |
---|
135 | printk("%s PCI I/O areas:\n",s); |
---|
136 | print_pci_area(pci->io.head); |
---|
137 | printk(" PCI memory areas:\n"); |
---|
138 | print_pci_area(pci->mem.head); |
---|
139 | } |
---|
140 | #else |
---|
141 | #define print_pci_areas(x) |
---|
142 | #define print_pci_resources(x) |
---|
143 | #endif |
---|
144 | |
---|
145 | /* Maybe there are some devices who use a size different |
---|
146 | * from the alignment. For now we assume both are the same. |
---|
147 | * The blacklist might be used for other weird things in the future too, |
---|
148 | * since weird non PCI complying devices seem to proliferate these days. |
---|
149 | */ |
---|
150 | |
---|
151 | struct blacklist_entry { |
---|
152 | u_short vendor, device; |
---|
153 | u_char reg; |
---|
154 | u_long actual_size; |
---|
155 | }; |
---|
156 | |
---|
157 | #define BLACKLIST(vid, did, breg, actual_size) \ |
---|
158 | {PCI_VENDOR_ID_##vid, PCI_DEVICE_ID_##vid##_##did, breg, actual_size} |
---|
159 | |
---|
160 | static struct blacklist_entry blacklist[] = { |
---|
161 | BLACKLIST(S3, TRIO, 0, 0x04000000), |
---|
162 | {0xffff, 0, 0, 0} |
---|
163 | }; |
---|
164 | |
---|
165 | /* This function filters resources and then inserts them into a list of |
---|
166 | * configurable pci resources. |
---|
167 | */ |
---|
168 | |
---|
169 | #define AREA(r) \ |
---|
170 | (((r->type&PCI_BASE_ADDRESS_SPACE)==PCI_BASE_ADDRESS_SPACE_IO) ? PCI_AREA_IO :\ |
---|
171 | ((r->type&PCI_BASE_ADDRESS_MEM_PREFETCH) ? PCI_AREA_PREFETCHABLE :\ |
---|
172 | PCI_AREA_MEMORY)) |
---|
173 | |
---|
174 | static int insert_before(pci_resource *e, pci_resource *t) { |
---|
175 | if (e->dev->bus->number != t->dev->bus->number) |
---|
176 | return e->dev->bus->number > t->dev->bus->number; |
---|
177 | if (AREA(e) != AREA(t)) return AREA(e)<AREA(t); |
---|
178 | return (e->size > t->size); |
---|
179 | } |
---|
180 | |
---|
181 | static void insert_resource(pci_resource *r) { |
---|
182 | struct blacklist_entry *b; |
---|
183 | pci_resource *p; |
---|
184 | if (!r) return; |
---|
185 | |
---|
186 | /* First fixup in case we have a blacklist entry. Note that this |
---|
187 | * may temporarily leave a resource in an inconsistent state: with |
---|
188 | * (base & (size-1)) !=0. This is harmless. |
---|
189 | */ |
---|
190 | for (b=blacklist; b->vendor!=0xffff; b++) { |
---|
191 | if ((r->dev->vendor==b->vendor) && |
---|
192 | (r->dev->device==b->device) && |
---|
193 | (r->reg==b->reg)) { |
---|
194 | r->size=b->actual_size; |
---|
195 | break; |
---|
196 | } |
---|
197 | } |
---|
198 | |
---|
199 | /* Motorola NT firmware does not configure pci devices which are not |
---|
200 | * required for booting, others do. For now: |
---|
201 | * - allocated devices in the ISA range (64kB I/O, 16Mb memory) |
---|
202 | * but non zero base registers are left as is. |
---|
203 | * - all other registers, whether already allocated or not, are |
---|
204 | * reallocated unless they require an inordinate amount of |
---|
205 | * resources (>256 Mb for memory >64kB for I/O). These |
---|
206 | * devices with too large mapping requirements are simply ignored |
---|
207 | * and their bases are set to 0. This should disable the |
---|
208 | * corresponding decoders according to the PCI specification. |
---|
209 | * Many devices are buggy in this respect, however, but the |
---|
210 | * limits have hopefully been set high enough to avoid problems. |
---|
211 | */ |
---|
212 | |
---|
213 | /* |
---|
214 | ** This is little ugly below. It seems that at least on the MCP750, |
---|
215 | ** the PBC has some default IO space mappings that the bsp #defines |
---|
216 | ** that read/write to PCI I/O space assume, particuarly the i8259 |
---|
217 | ** manipulation code. So, if we allow the small IO spaces on PCI bus |
---|
218 | ** 0 and 1 to be remapped, the registers can shift out from under the |
---|
219 | ** #defines. This is particuarly awful, but short of redefining the |
---|
220 | ** PCI I/O primitives to be functions with base addresses read from |
---|
221 | ** the hardware, we are stuck with the kludge below. Note that |
---|
222 | ** everything is remapped on the CPCI backplane and any downstream |
---|
223 | ** hardware, its just the builtin stuff we're tiptoeing around. |
---|
224 | ** |
---|
225 | ** Gregm, 7/16/2003 |
---|
226 | ** |
---|
227 | ** Gregm, changed 11/2003 so IO devices only on bus 0 zero are not |
---|
228 | ** remapped. This covers the builtin pc-like io devices- but |
---|
229 | ** properly maps IO devices on higher busses. |
---|
230 | */ |
---|
231 | if( r->dev->bus->number == 0 ) |
---|
232 | { |
---|
233 | if ((r->type==PCI_BASE_ADDRESS_SPACE_IO) |
---|
234 | ? (r->base && r->base <0x10000) |
---|
235 | : (r->base && r->base <0x1000000)) { |
---|
236 | |
---|
237 | #ifdef PCI_DEBUG |
---|
238 | printk("freeing region; %p:%p %d:%02x (%04x:%04x) %08lx %08lx %d\n", |
---|
239 | r, r->next, |
---|
240 | r->dev->bus->number, PCI_SLOT(r->dev->devfn), |
---|
241 | r->dev->vendor, r->dev->device, |
---|
242 | r->base, |
---|
243 | r->size, |
---|
244 | r->type); |
---|
245 | #endif |
---|
246 | sfree(r); |
---|
247 | return; |
---|
248 | } |
---|
249 | } |
---|
250 | |
---|
251 | |
---|
252 | /* 2004/11/30, PR 729 fix is removing the r->size=0 and r->base=0 |
---|
253 | * assignement which makes too-large regions conflict with onboard |
---|
254 | * hardware, replacing it with sfree which deletes the memory region |
---|
255 | * from the setup code, leaving it disabled. */ |
---|
256 | if ((r->type==PCI_BASE_ADDRESS_SPACE_IO) |
---|
257 | ? (r->size > 0x10000) |
---|
258 | : (r->size > 0x18000000)) { |
---|
259 | sfree(r); |
---|
260 | return; |
---|
261 | } |
---|
262 | |
---|
263 | /* Now insert into the list sorting by |
---|
264 | * 1) decreasing bus number |
---|
265 | * 2) space: prefetchable memory, non-prefetchable and finally I/O |
---|
266 | * 3) decreasing size |
---|
267 | */ |
---|
268 | if (!pci->resources || insert_before(r, pci->resources)) { |
---|
269 | r->next = pci->resources; |
---|
270 | pci->resources=r; |
---|
271 | } else { |
---|
272 | for (p=pci->resources; p->next; p=p->next) { |
---|
273 | if (insert_before(r, p->next)) break; |
---|
274 | } |
---|
275 | r->next=p->next; |
---|
276 | p->next=r; |
---|
277 | } |
---|
278 | } |
---|
279 | |
---|
280 | /* This version only works for bus 0. I don't have any P2P bridges to test |
---|
281 | * a more sophisticated version which has therefore not been implemented. |
---|
282 | * Prefetchable memory is not yet handled correctly either. |
---|
283 | * And several levels of PCI bridges much less even since there must be |
---|
284 | * allocated together to be able to setup correctly the top bridge. |
---|
285 | */ |
---|
286 | |
---|
287 | static u_long find_range(u_char bus, u_char type, |
---|
288 | pci_resource **first, |
---|
289 | pci_resource **past, u_int *flags) { |
---|
290 | pci_resource *p; |
---|
291 | u_long total=0; |
---|
292 | u_int fl=0; |
---|
293 | |
---|
294 | for (p=pci->resources; p; p=p->next) |
---|
295 | { |
---|
296 | if ((p->dev->bus->number == bus) && |
---|
297 | AREA(p)==type) break; |
---|
298 | } |
---|
299 | |
---|
300 | *first = p; |
---|
301 | |
---|
302 | for (; p; p=p->next) |
---|
303 | { |
---|
304 | if ((p->dev->bus->number != bus) || |
---|
305 | AREA(p)!=type || p->size == 0) break; |
---|
306 | total = total+p->size; |
---|
307 | fl |= 1<<p->type; |
---|
308 | } |
---|
309 | |
---|
310 | *past = p; |
---|
311 | /* This will be used later to tell whether there are any 32 bit |
---|
312 | * devices in an area which could be mapped higher than 4Gb |
---|
313 | * on 64 bits architectures |
---|
314 | */ |
---|
315 | *flags = fl; |
---|
316 | return total; |
---|
317 | } |
---|
318 | |
---|
319 | static inline void init_free_area(pci_area_head *h, u_long start, |
---|
320 | u_long end, u_int mask, int high) { |
---|
321 | pci_area *p; |
---|
322 | p = salloc(sizeof(pci_area)); |
---|
323 | if (!p) return; |
---|
324 | h->head = p; |
---|
325 | p->next = NULL; |
---|
326 | p->start = (start+mask)&~mask; |
---|
327 | p->end = (end-mask)|mask; |
---|
328 | p->bus = NULL; |
---|
329 | h->mask = mask; |
---|
330 | h->high = high; |
---|
331 | } |
---|
332 | |
---|
333 | static void insert_area(pci_area_head *h, pci_area *p) { |
---|
334 | pci_area *q = h->head; |
---|
335 | if (!p) return; |
---|
336 | if (q && (q->start< p->start)) { |
---|
337 | for(;q->next && q->next->start<p->start; q = q->next); |
---|
338 | if ((q->end >= p->start) || |
---|
339 | (q->next && p->end>=q->next->start)) { |
---|
340 | sfree(p); |
---|
341 | printk("Overlapping pci areas!\n"); |
---|
342 | return; |
---|
343 | } |
---|
344 | p->next = q->next; |
---|
345 | q->next = p; |
---|
346 | } else { /* Insert at head */ |
---|
347 | if (q && (p->end >= q->start)) { |
---|
348 | sfree(p); |
---|
349 | printk("Overlapping pci areas!\n"); |
---|
350 | return; |
---|
351 | } |
---|
352 | p->next = q; |
---|
353 | h->head = p; |
---|
354 | } |
---|
355 | } |
---|
356 | |
---|
357 | static |
---|
358 | void remove_area(pci_area_head *h, pci_area *p) |
---|
359 | { |
---|
360 | pci_area *q = h->head; |
---|
361 | |
---|
362 | if (!p || !q) return; |
---|
363 | if (q==p) |
---|
364 | { |
---|
365 | h->head = q->next; |
---|
366 | return; |
---|
367 | } |
---|
368 | for(;q && q->next!=p; q=q->next); |
---|
369 | if (q) q->next=p->next; |
---|
370 | } |
---|
371 | |
---|
372 | static pci_area * alloc_area(pci_area_head *h, struct pci_bus *bus, |
---|
373 | u_long required, u_long mask, u_int flags) { |
---|
374 | pci_area *p; |
---|
375 | pci_area *from, *split, *new; |
---|
376 | |
---|
377 | required = (required+h->mask) & ~h->mask; |
---|
378 | for (p=h->head, from=NULL; p; p=p->next) |
---|
379 | { |
---|
380 | u_long l1 = ((p->start+required+mask)&~mask)-1; |
---|
381 | u_long l2 = ((p->start+mask)&~mask)+required-1; |
---|
382 | /* Allocated areas point to the bus to which they pertain */ |
---|
383 | if (p->bus) continue; |
---|
384 | if ((p->end)>=l1 || (p->end)>=l2) from=p; |
---|
385 | if (from && !h->high) break; |
---|
386 | } |
---|
387 | if (!from) return NULL; |
---|
388 | |
---|
389 | split = salloc(sizeof(pci_area)); |
---|
390 | new = salloc(sizeof(pci_area)); |
---|
391 | /* If allocation of new succeeds then allocation of split has |
---|
392 | * also been successful (given the current mm algorithms) ! |
---|
393 | */ |
---|
394 | if (!new) { |
---|
395 | sfree(split); |
---|
396 | return NULL; |
---|
397 | } |
---|
398 | new->bus = bus; |
---|
399 | new->flags = flags; |
---|
400 | /* Now allocate pci_space taking alignment into account ! */ |
---|
401 | if (h->high) |
---|
402 | { |
---|
403 | u_long l1 = ((from->end+1)&~mask)-required; |
---|
404 | u_long l2 = (from->end+1-required)&~mask; |
---|
405 | new->start = (l1>l2) ? l1 : l2; |
---|
406 | split->end = from->end; |
---|
407 | from->end = new->start-1; |
---|
408 | split->start = new->start+required; |
---|
409 | new->end = new->start+required-1; |
---|
410 | } |
---|
411 | else |
---|
412 | { |
---|
413 | u_long l1 = ((from->start+mask)&~mask)+required-1; |
---|
414 | u_long l2 = ((from->start+required+mask)&~mask)-1; |
---|
415 | new->end = (l1<l2) ? l1 : l2; |
---|
416 | split->start = from->start; |
---|
417 | from->start = new->end+1; |
---|
418 | new->start = new->end+1-required; |
---|
419 | split->end = new->start-1; |
---|
420 | } |
---|
421 | |
---|
422 | if (from->end+1 == from->start) remove_area(h, from); |
---|
423 | if (split->end+1 != split->start) |
---|
424 | { |
---|
425 | split->bus = NULL; |
---|
426 | insert_area(h, split); |
---|
427 | } |
---|
428 | else |
---|
429 | { |
---|
430 | sfree(split); |
---|
431 | } |
---|
432 | insert_area(h, new); |
---|
433 | print_pci_areas("alloc_area called:\n"); |
---|
434 | return new; |
---|
435 | } |
---|
436 | |
---|
437 | static inline |
---|
438 | void alloc_space(pci_area *p, pci_resource *r) |
---|
439 | { |
---|
440 | if (p->start & (r->size-1)) { |
---|
441 | r->base = p->end+1-r->size; |
---|
442 | p->end -= r->size; |
---|
443 | } else { |
---|
444 | r->base = p->start; |
---|
445 | p->start += r->size; |
---|
446 | } |
---|
447 | } |
---|
448 | |
---|
449 | static void reconfigure_bus_space(u_char bus, u_char type, pci_area_head *h) |
---|
450 | { |
---|
451 | pci_resource *first, *past, *r; |
---|
452 | pci_area *area, tmp; |
---|
453 | u_int flags; |
---|
454 | u_int required = find_range(bus, type, &first, &past, &flags); |
---|
455 | |
---|
456 | if (required==0) return; |
---|
457 | |
---|
458 | area = alloc_area(h, first->dev->bus, required, first->size-1, flags); |
---|
459 | |
---|
460 | if (!area) return; |
---|
461 | |
---|
462 | tmp = *area; |
---|
463 | for (r=first; r!=past; r=r->next) |
---|
464 | { |
---|
465 | alloc_space(&tmp, r); |
---|
466 | } |
---|
467 | } |
---|
468 | |
---|
469 | #define BUS0_IO_START 0x10000 |
---|
470 | #define BUS0_IO_END 0x1ffff |
---|
471 | #define BUS0_MEM_START 0x1000000 |
---|
472 | #define BUS0_MEM_END 0x3f00000 |
---|
473 | |
---|
474 | #define BUSREST_IO_START 0x20000 |
---|
475 | #define BUSREST_IO_END 0x7ffff |
---|
476 | #define BUSREST_MEM_START 0x4000000 |
---|
477 | #define BUSREST_MEM_END 0x10000000 |
---|
478 | |
---|
479 | static void reconfigure_pci(void) { |
---|
480 | pci_resource *r; |
---|
481 | struct pci_dev *dev; |
---|
482 | |
---|
483 | /* FIXME: for now memory is relocated from low, it's better |
---|
484 | * to start from higher addresses. |
---|
485 | */ |
---|
486 | /* |
---|
487 | init_free_area(&pci->io, 0x10000, 0x7fffff, 0xfff, 0); |
---|
488 | init_free_area(&pci->mem, 0x1000000, 0x3cffffff, 0xfffff, 0); |
---|
489 | */ |
---|
490 | |
---|
491 | init_free_area(&pci->io, BUS0_IO_START, BUS0_IO_END, 0xfff, 0); |
---|
492 | init_free_area(&pci->mem, BUS0_MEM_START, BUS0_MEM_END, 0xfffff, 0); |
---|
493 | |
---|
494 | /* First reconfigure the I/O space, this will be more |
---|
495 | * complex when there is more than 1 bus. And 64 bits |
---|
496 | * devices are another kind of problems. |
---|
497 | */ |
---|
498 | reconfigure_bus_space(0, PCI_AREA_IO, &pci->io); |
---|
499 | reconfigure_bus_space(0, PCI_AREA_MEMORY, &pci->mem); |
---|
500 | reconfigure_bus_space(0, PCI_AREA_PREFETCHABLE, &pci->mem); |
---|
501 | |
---|
502 | /* Now we have to touch the configuration space of all |
---|
503 | * the devices to remap them better than they are right now. |
---|
504 | * This is done in 3 steps: |
---|
505 | * 1) first disable I/O and memory response of all devices |
---|
506 | * 2) modify the base registers |
---|
507 | * 3) restore the original PCI_COMMAND register. |
---|
508 | */ |
---|
509 | for (r=pci->resources; r; r= r->next) { |
---|
510 | if (!r->dev->sysdata) { |
---|
511 | r->dev->sysdata=r; |
---|
512 | pci_read_config_word(r->dev, PCI_COMMAND, &r->cmd); |
---|
513 | pci_write_config_word(r->dev, PCI_COMMAND, |
---|
514 | r->cmd & ~(PCI_COMMAND_IO| |
---|
515 | PCI_COMMAND_MEMORY)); |
---|
516 | } |
---|
517 | } |
---|
518 | |
---|
519 | for (r=pci->resources; r; r= r->next) { |
---|
520 | pci_write_config_dword(r->dev, |
---|
521 | PCI_BASE_ADDRESS_0+(r->reg<<2), |
---|
522 | r->base); |
---|
523 | if ((r->type& |
---|
524 | (PCI_BASE_ADDRESS_SPACE| |
---|
525 | PCI_BASE_ADDRESS_MEM_TYPE_MASK)) == |
---|
526 | (PCI_BASE_ADDRESS_SPACE_MEMORY| |
---|
527 | PCI_BASE_ADDRESS_MEM_TYPE_64)) { |
---|
528 | pci_write_config_dword(r->dev, |
---|
529 | PCI_BASE_ADDRESS_1+(r->reg<<2), |
---|
530 | 0); |
---|
531 | } |
---|
532 | } |
---|
533 | for (dev=bd->pci_devices; dev; dev= dev->next) { |
---|
534 | if (dev->sysdata) { |
---|
535 | pci_write_config_word(dev, PCI_COMMAND, |
---|
536 | ((pci_resource *)dev->sysdata) |
---|
537 | ->cmd); |
---|
538 | dev->sysdata=NULL; |
---|
539 | } |
---|
540 | } |
---|
541 | } |
---|
542 | |
---|
543 | static int |
---|
544 | indirect_pci_read_config_byte(unsigned char bus, unsigned char dev_fn, |
---|
545 | unsigned char offset, unsigned char *val) { |
---|
546 | out_be32(pci->config_addr, |
---|
547 | 0x80|(bus<<8)|(dev_fn<<16)|((offset&~3)<<24)); |
---|
548 | *val=in_8(pci->config_data + (offset&3)); |
---|
549 | return PCIBIOS_SUCCESSFUL; |
---|
550 | } |
---|
551 | |
---|
552 | static int |
---|
553 | indirect_pci_read_config_word(unsigned char bus, unsigned char dev_fn, |
---|
554 | unsigned char offset, unsigned short *val) { |
---|
555 | *val = 0xffff; |
---|
556 | if (offset&1) return PCIBIOS_BAD_REGISTER_NUMBER; |
---|
557 | out_be32(pci->config_addr, |
---|
558 | 0x80|(bus<<8)|(dev_fn<<16)|((offset&~3)<<24)); |
---|
559 | *val=in_le16((volatile u_short *)(pci->config_data + (offset&3))); |
---|
560 | return PCIBIOS_SUCCESSFUL; |
---|
561 | } |
---|
562 | |
---|
563 | static int |
---|
564 | indirect_pci_read_config_dword(unsigned char bus, unsigned char dev_fn, |
---|
565 | unsigned char offset, unsigned int *val) { |
---|
566 | *val = 0xffffffff; |
---|
567 | if (offset&3) return PCIBIOS_BAD_REGISTER_NUMBER; |
---|
568 | out_be32(pci->config_addr, |
---|
569 | 0x80|(bus<<8)|(dev_fn<<16)|(offset<<24)); |
---|
570 | *val=in_le32((volatile u_int *)pci->config_data); |
---|
571 | return PCIBIOS_SUCCESSFUL; |
---|
572 | } |
---|
573 | |
---|
574 | static int |
---|
575 | indirect_pci_write_config_byte(unsigned char bus, unsigned char dev_fn, |
---|
576 | unsigned char offset, unsigned char val) { |
---|
577 | out_be32(pci->config_addr, |
---|
578 | 0x80|(bus<<8)|(dev_fn<<16)|((offset&~3)<<24)); |
---|
579 | out_8(pci->config_data + (offset&3), val); |
---|
580 | return PCIBIOS_SUCCESSFUL; |
---|
581 | } |
---|
582 | |
---|
583 | static int |
---|
584 | indirect_pci_write_config_word(unsigned char bus, unsigned char dev_fn, |
---|
585 | unsigned char offset, unsigned short val) { |
---|
586 | if (offset&1) return PCIBIOS_BAD_REGISTER_NUMBER; |
---|
587 | out_be32(pci->config_addr, |
---|
588 | 0x80|(bus<<8)|(dev_fn<<16)|((offset&~3)<<24)); |
---|
589 | out_le16((volatile u_short *)(pci->config_data + (offset&3)), val); |
---|
590 | return PCIBIOS_SUCCESSFUL; |
---|
591 | } |
---|
592 | |
---|
593 | static int |
---|
594 | indirect_pci_write_config_dword(unsigned char bus, unsigned char dev_fn, |
---|
595 | unsigned char offset, unsigned int val) { |
---|
596 | if (offset&3) return PCIBIOS_BAD_REGISTER_NUMBER; |
---|
597 | out_be32(pci->config_addr, |
---|
598 | 0x80|(bus<<8)|(dev_fn<<16)|(offset<<24)); |
---|
599 | out_le32((volatile u_int *)pci->config_data, val); |
---|
600 | return PCIBIOS_SUCCESSFUL; |
---|
601 | } |
---|
602 | |
---|
603 | static const struct pci_config_access_functions indirect_functions = { |
---|
604 | indirect_pci_read_config_byte, |
---|
605 | indirect_pci_read_config_word, |
---|
606 | indirect_pci_read_config_dword, |
---|
607 | indirect_pci_write_config_byte, |
---|
608 | indirect_pci_write_config_word, |
---|
609 | indirect_pci_write_config_dword |
---|
610 | }; |
---|
611 | |
---|
612 | static int |
---|
613 | direct_pci_read_config_byte(unsigned char bus, unsigned char dev_fn, |
---|
614 | unsigned char offset, unsigned char *val) { |
---|
615 | if (bus != 0 || (1<<PCI_SLOT(dev_fn) & 0xff8007fe)) { |
---|
616 | *val=0xff; |
---|
617 | return PCIBIOS_DEVICE_NOT_FOUND; |
---|
618 | } |
---|
619 | *val=in_8(pci->config_data + ((1<<PCI_SLOT(dev_fn))&~1) |
---|
620 | + (PCI_FUNC(dev_fn)<<8) + offset); |
---|
621 | return PCIBIOS_SUCCESSFUL; |
---|
622 | } |
---|
623 | |
---|
624 | static int |
---|
625 | direct_pci_read_config_word(unsigned char bus, unsigned char dev_fn, |
---|
626 | unsigned char offset, unsigned short *val) { |
---|
627 | *val = 0xffff; |
---|
628 | if (offset&1) return PCIBIOS_BAD_REGISTER_NUMBER; |
---|
629 | if (bus != 0 || (1<<PCI_SLOT(dev_fn) & 0xff8007fe)) { |
---|
630 | return PCIBIOS_DEVICE_NOT_FOUND; |
---|
631 | } |
---|
632 | *val=in_le16((volatile u_short *) |
---|
633 | (pci->config_data + ((1<<PCI_SLOT(dev_fn))&~1) |
---|
634 | + (PCI_FUNC(dev_fn)<<8) + offset)); |
---|
635 | return PCIBIOS_SUCCESSFUL; |
---|
636 | } |
---|
637 | |
---|
638 | static int |
---|
639 | direct_pci_read_config_dword(unsigned char bus, unsigned char dev_fn, |
---|
640 | unsigned char offset, unsigned int *val) { |
---|
641 | *val = 0xffffffff; |
---|
642 | if (offset&3) return PCIBIOS_BAD_REGISTER_NUMBER; |
---|
643 | if (bus != 0 || (1<<PCI_SLOT(dev_fn) & 0xff8007fe)) { |
---|
644 | return PCIBIOS_DEVICE_NOT_FOUND; |
---|
645 | } |
---|
646 | *val=in_le32((volatile u_int *) |
---|
647 | (pci->config_data + ((1<<PCI_SLOT(dev_fn))&~1) |
---|
648 | + (PCI_FUNC(dev_fn)<<8) + offset)); |
---|
649 | return PCIBIOS_SUCCESSFUL; |
---|
650 | } |
---|
651 | |
---|
652 | static int |
---|
653 | direct_pci_write_config_byte(unsigned char bus, unsigned char dev_fn, |
---|
654 | unsigned char offset, unsigned char val) { |
---|
655 | if (bus != 0 || (1<<PCI_SLOT(dev_fn) & 0xff8007fe)) { |
---|
656 | return PCIBIOS_DEVICE_NOT_FOUND; |
---|
657 | } |
---|
658 | out_8(pci->config_data + ((1<<PCI_SLOT(dev_fn))&~1) |
---|
659 | + (PCI_FUNC(dev_fn)<<8) + offset, |
---|
660 | val); |
---|
661 | return PCIBIOS_SUCCESSFUL; |
---|
662 | } |
---|
663 | |
---|
664 | static int |
---|
665 | direct_pci_write_config_word(unsigned char bus, unsigned char dev_fn, |
---|
666 | unsigned char offset, unsigned short val) { |
---|
667 | if (offset&1) return PCIBIOS_BAD_REGISTER_NUMBER; |
---|
668 | if (bus != 0 || (1<<PCI_SLOT(dev_fn) & 0xff8007fe)) { |
---|
669 | return PCIBIOS_DEVICE_NOT_FOUND; |
---|
670 | } |
---|
671 | out_le16((volatile u_short *) |
---|
672 | (pci->config_data + ((1<<PCI_SLOT(dev_fn))&~1) |
---|
673 | + (PCI_FUNC(dev_fn)<<8) + offset), |
---|
674 | val); |
---|
675 | return PCIBIOS_SUCCESSFUL; |
---|
676 | } |
---|
677 | |
---|
678 | static int |
---|
679 | direct_pci_write_config_dword(unsigned char bus, unsigned char dev_fn, |
---|
680 | unsigned char offset, unsigned int val) { |
---|
681 | if (offset&3) return PCIBIOS_BAD_REGISTER_NUMBER; |
---|
682 | if (bus != 0 || (1<<PCI_SLOT(dev_fn) & 0xff8007fe)) { |
---|
683 | return PCIBIOS_DEVICE_NOT_FOUND; |
---|
684 | } |
---|
685 | out_le32((volatile u_int *) |
---|
686 | (pci->config_data + ((1<<PCI_SLOT(dev_fn))&~1) |
---|
687 | + (PCI_FUNC(dev_fn)<<8) + offset), |
---|
688 | val); |
---|
689 | return PCIBIOS_SUCCESSFUL; |
---|
690 | } |
---|
691 | |
---|
692 | static const struct pci_config_access_functions direct_functions = { |
---|
693 | direct_pci_read_config_byte, |
---|
694 | direct_pci_read_config_word, |
---|
695 | direct_pci_read_config_dword, |
---|
696 | direct_pci_write_config_byte, |
---|
697 | direct_pci_write_config_word, |
---|
698 | direct_pci_write_config_dword |
---|
699 | }; |
---|
700 | |
---|
701 | void pci_read_bases(struct pci_dev *dev, unsigned int howmany) |
---|
702 | { |
---|
703 | unsigned int reg, nextreg; |
---|
704 | |
---|
705 | #define REG (PCI_BASE_ADDRESS_0 + (reg<<2)) |
---|
706 | |
---|
707 | u_short cmd; |
---|
708 | uint32_t l, ml; |
---|
709 | pci_read_config_word(dev, PCI_COMMAND, &cmd); |
---|
710 | |
---|
711 | for(reg=0; reg<howmany; reg=nextreg) |
---|
712 | { |
---|
713 | pci_resource *r; |
---|
714 | |
---|
715 | nextreg=reg+1; |
---|
716 | pci_read_config_dword(dev, REG, &l); |
---|
717 | #if 0 |
---|
718 | if (l == 0xffffffff /*AJF || !l*/) continue; |
---|
719 | #endif |
---|
720 | /* Note that disabling the memory response of a host bridge |
---|
721 | * would lose data if a DMA transfer were in progress. In a |
---|
722 | * bootloader we don't care however. Also we can't print any |
---|
723 | * message for a while since we might just disable the console. |
---|
724 | */ |
---|
725 | pci_write_config_word(dev, PCI_COMMAND, cmd & |
---|
726 | ~(PCI_COMMAND_IO|PCI_COMMAND_MEMORY)); |
---|
727 | pci_write_config_dword(dev, REG, ~0); |
---|
728 | pci_read_config_dword(dev, REG, &ml); |
---|
729 | pci_write_config_dword(dev, REG, l); |
---|
730 | |
---|
731 | /* Reenable the device now that we've played with |
---|
732 | * base registers. |
---|
733 | */ |
---|
734 | pci_write_config_word(dev, PCI_COMMAND, cmd); |
---|
735 | |
---|
736 | /* seems to be an unused entry skip it */ |
---|
737 | if ( ml == 0 || ml == 0xffffffff ) continue; |
---|
738 | |
---|
739 | if ((l & |
---|
740 | (PCI_BASE_ADDRESS_SPACE|PCI_BASE_ADDRESS_MEM_TYPE_MASK)) |
---|
741 | == (PCI_BASE_ADDRESS_MEM_TYPE_64 |
---|
742 | |PCI_BASE_ADDRESS_SPACE_MEMORY)) { |
---|
743 | nextreg=reg+2; |
---|
744 | } |
---|
745 | dev->base_address[reg] = l; |
---|
746 | r = salloc(sizeof(pci_resource)); |
---|
747 | if (!r) { |
---|
748 | printk("Error allocating pci_resource struct.\n"); |
---|
749 | continue; |
---|
750 | } |
---|
751 | r->dev = dev; |
---|
752 | r->reg = reg; |
---|
753 | if ((l&PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) { |
---|
754 | r->type = l&~PCI_BASE_ADDRESS_IO_MASK; |
---|
755 | r->base = l&PCI_BASE_ADDRESS_IO_MASK; |
---|
756 | /* r->size = ~(ml&PCI_BASE_ADDRESS_IO_MASK)+1; */ |
---|
757 | } else { |
---|
758 | r->type = l&~PCI_BASE_ADDRESS_MEM_MASK; |
---|
759 | r->base = l&PCI_BASE_ADDRESS_MEM_MASK; |
---|
760 | /* r->size = ~(ml&PCI_BASE_ADDRESS_MEM_MASK)+1; */ |
---|
761 | } |
---|
762 | |
---|
763 | /* find the first bit set to one after the base |
---|
764 | address type bits to find length of region */ |
---|
765 | { |
---|
766 | unsigned int c= 16 , val= 0; |
---|
767 | while( !(val= ml & c) ) c <<= 1; |
---|
768 | r->size = val; |
---|
769 | } |
---|
770 | |
---|
771 | #ifdef PCI_DEBUG |
---|
772 | printk(" readbase bus %d, (%04x:%04x), base %08x, size %08x, type %d\n", |
---|
773 | r->dev->bus->number, |
---|
774 | r->dev->vendor, |
---|
775 | r->dev->device, |
---|
776 | r->base, |
---|
777 | r->size, |
---|
778 | r->type ); |
---|
779 | #endif |
---|
780 | |
---|
781 | /* Check for the blacklisted entries */ |
---|
782 | insert_resource(r); |
---|
783 | } |
---|
784 | } |
---|
785 | |
---|
786 | u_int pci_scan_bus(struct pci_bus *bus) |
---|
787 | { |
---|
788 | unsigned int devfn, l, max, class; |
---|
789 | unsigned char irq, hdr_type, is_multi = 0; |
---|
790 | struct pci_dev *dev, **bus_last; |
---|
791 | struct pci_bus *child; |
---|
792 | |
---|
793 | #if 0 |
---|
794 | printk("scanning pci bus %d\n", bus->number ); |
---|
795 | #endif |
---|
796 | |
---|
797 | bus_last = &bus->devices; |
---|
798 | max = bus->secondary; |
---|
799 | for (devfn = 0; devfn < 0xff; ++devfn) { |
---|
800 | if (PCI_FUNC(devfn) && !is_multi) { |
---|
801 | /* not a multi-function device */ |
---|
802 | continue; |
---|
803 | } |
---|
804 | if (pcibios_read_config_byte(bus->number, devfn, PCI_HEADER_TYPE, &hdr_type)) |
---|
805 | continue; |
---|
806 | if (!PCI_FUNC(devfn)) |
---|
807 | is_multi = hdr_type & 0x80; |
---|
808 | |
---|
809 | if (pcibios_read_config_dword(bus->number, devfn, PCI_VENDOR_ID, &l) || |
---|
810 | /* some broken boards return 0 if a slot is empty: */ |
---|
811 | l == 0xffffffff || l == 0x00000000 || l == 0x0000ffff || l == 0xffff0000) { |
---|
812 | is_multi = 0; |
---|
813 | continue; |
---|
814 | } |
---|
815 | |
---|
816 | dev = salloc(sizeof(*dev)); |
---|
817 | dev->bus = bus; |
---|
818 | dev->devfn = devfn; |
---|
819 | dev->vendor = l & 0xffff; |
---|
820 | dev->device = (l >> 16) & 0xffff; |
---|
821 | |
---|
822 | pcibios_read_config_dword(bus->number, devfn, |
---|
823 | PCI_CLASS_REVISION, &class); |
---|
824 | class >>= 8; /* upper 3 bytes */ |
---|
825 | dev->class = class; |
---|
826 | class >>= 8; |
---|
827 | dev->hdr_type = hdr_type; |
---|
828 | |
---|
829 | switch (hdr_type & 0x7f) { /* header type */ |
---|
830 | case PCI_HEADER_TYPE_NORMAL: /* standard header */ |
---|
831 | if (class == PCI_CLASS_BRIDGE_PCI) |
---|
832 | goto bad; |
---|
833 | /* |
---|
834 | * If the card generates interrupts, read IRQ number |
---|
835 | * (some architectures change it during pcibios_fixup()) |
---|
836 | */ |
---|
837 | pcibios_read_config_byte(bus->number, dev->devfn, PCI_INTERRUPT_PIN, &irq); |
---|
838 | if (irq) |
---|
839 | pcibios_read_config_byte(bus->number, dev->devfn, PCI_INTERRUPT_LINE, &irq); |
---|
840 | dev->irq = irq; |
---|
841 | /* |
---|
842 | * read base address registers, again pcibios_fixup() can |
---|
843 | * tweak these |
---|
844 | */ |
---|
845 | pci_read_bases(dev, 6); |
---|
846 | pcibios_read_config_dword(bus->number, devfn, PCI_ROM_ADDRESS, &l); |
---|
847 | dev->rom_address = (l == 0xffffffff) ? 0 : l; |
---|
848 | break; |
---|
849 | case PCI_HEADER_TYPE_BRIDGE: /* bridge header */ |
---|
850 | if (class != PCI_CLASS_BRIDGE_PCI) |
---|
851 | goto bad; |
---|
852 | pci_read_bases(dev, 2); |
---|
853 | pcibios_read_config_dword(bus->number, devfn, PCI_ROM_ADDRESS1, &l); |
---|
854 | dev->rom_address = (l == 0xffffffff) ? 0 : l; |
---|
855 | break; |
---|
856 | case PCI_HEADER_TYPE_CARDBUS: /* CardBus bridge header */ |
---|
857 | if (class != PCI_CLASS_BRIDGE_CARDBUS) |
---|
858 | goto bad; |
---|
859 | pci_read_bases(dev, 1); |
---|
860 | break; |
---|
861 | |
---|
862 | default: /* unknown header */ |
---|
863 | bad: |
---|
864 | printk("PCI device with unknown header type %d ignored.\n", |
---|
865 | hdr_type&0x7f); |
---|
866 | continue; |
---|
867 | } |
---|
868 | |
---|
869 | /* |
---|
870 | * Put it into the global PCI device chain. It's used to |
---|
871 | * find devices once everything is set up. |
---|
872 | */ |
---|
873 | *pci->last_dev_p = dev; |
---|
874 | pci->last_dev_p = &dev->next; |
---|
875 | |
---|
876 | /* |
---|
877 | * Now insert it into the list of devices held |
---|
878 | * by the parent bus. |
---|
879 | */ |
---|
880 | *bus_last = dev; |
---|
881 | bus_last = &dev->sibling; |
---|
882 | |
---|
883 | } |
---|
884 | |
---|
885 | /* |
---|
886 | * After performing arch-dependent fixup of the bus, look behind |
---|
887 | * all PCI-to-PCI bridges on this bus. |
---|
888 | */ |
---|
889 | for(dev=bus->devices; dev; dev=dev->sibling) |
---|
890 | /* |
---|
891 | * If it's a bridge, scan the bus behind it. |
---|
892 | */ |
---|
893 | if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { |
---|
894 | unsigned int buses; |
---|
895 | unsigned int devfn = dev->devfn; |
---|
896 | unsigned short cr; |
---|
897 | |
---|
898 | /* |
---|
899 | * Insert it into the tree of buses. |
---|
900 | */ |
---|
901 | child = salloc(sizeof(*child)); |
---|
902 | child->next = bus->children; |
---|
903 | bus->children = child; |
---|
904 | child->self = dev; |
---|
905 | child->parent = bus; |
---|
906 | |
---|
907 | /* |
---|
908 | * Set up the primary, secondary and subordinate |
---|
909 | * bus numbers. |
---|
910 | */ |
---|
911 | child->number = child->secondary = ++max; |
---|
912 | child->primary = bus->secondary; |
---|
913 | child->subordinate = 0xff; |
---|
914 | /* |
---|
915 | * Clear all status bits and turn off memory, |
---|
916 | * I/O and master enables. |
---|
917 | */ |
---|
918 | pcibios_read_config_word(bus->number, devfn, PCI_COMMAND, &cr); |
---|
919 | pcibios_write_config_word(bus->number, devfn, PCI_COMMAND, 0x0000); |
---|
920 | pcibios_write_config_word(bus->number, devfn, PCI_STATUS, 0xffff); |
---|
921 | /* |
---|
922 | * Read the existing primary/secondary/subordinate bus |
---|
923 | * number configuration to determine if the PCI bridge |
---|
924 | * has already been configured by the system. If so, |
---|
925 | * do not modify the configuration, merely note it. |
---|
926 | */ |
---|
927 | pcibios_read_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, &buses); |
---|
928 | if ((buses & 0xFFFFFF) != 0) |
---|
929 | { |
---|
930 | unsigned int cmax; |
---|
931 | |
---|
932 | child->primary = buses & 0xFF; |
---|
933 | child->secondary = (buses >> 8) & 0xFF; |
---|
934 | child->subordinate = (buses >> 16) & 0xFF; |
---|
935 | child->number = child->secondary; |
---|
936 | cmax = pci_scan_bus(child); |
---|
937 | if (cmax > max) max = cmax; |
---|
938 | } |
---|
939 | else |
---|
940 | { |
---|
941 | /* |
---|
942 | * Configure the bus numbers for this bridge: |
---|
943 | */ |
---|
944 | buses &= 0xff000000; |
---|
945 | buses |= |
---|
946 | (((unsigned int)(child->primary) << 0) | |
---|
947 | ((unsigned int)(child->secondary) << 8) | |
---|
948 | ((unsigned int)(child->subordinate) << 16)); |
---|
949 | pcibios_write_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, buses); |
---|
950 | /* |
---|
951 | * Now we can scan all subordinate buses: |
---|
952 | */ |
---|
953 | max = pci_scan_bus(child); |
---|
954 | /* |
---|
955 | * Set the subordinate bus number to its real |
---|
956 | * value: |
---|
957 | */ |
---|
958 | child->subordinate = max; |
---|
959 | buses = (buses & 0xff00ffff) |
---|
960 | | ((unsigned int)(child->subordinate) << 16); |
---|
961 | pcibios_write_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, buses); |
---|
962 | } |
---|
963 | pcibios_write_config_word(bus->number, devfn, PCI_COMMAND, cr ); |
---|
964 | } |
---|
965 | |
---|
966 | /* |
---|
967 | * We've scanned the bus and so we know all about what's on |
---|
968 | * the other side of any bridges that may be on this bus plus |
---|
969 | * any devices. |
---|
970 | * |
---|
971 | * Return how far we've got finding sub-buses. |
---|
972 | */ |
---|
973 | return max; |
---|
974 | } |
---|
975 | |
---|
976 | #if 0 |
---|
977 | |
---|
978 | void |
---|
979 | pci_fixup(void) |
---|
980 | { |
---|
981 | struct pci_dev *p; |
---|
982 | struct pci_bus *bus; |
---|
983 | |
---|
984 | for (bus = &pci_root; bus; bus=bus->next) |
---|
985 | { |
---|
986 | for (p=bus->devices; p; p=p->sibling) |
---|
987 | { |
---|
988 | } |
---|
989 | } |
---|
990 | } |
---|
991 | |
---|
992 | static void print_pci_info() |
---|
993 | { |
---|
994 | pci_resource *r; |
---|
995 | struct pci_bus *pb = &pci_root; |
---|
996 | |
---|
997 | printk("\n"); |
---|
998 | printk("PCI busses:\n"); |
---|
999 | |
---|
1000 | for(pb= &pci_root; pb; pb=pb->children ) |
---|
1001 | { |
---|
1002 | printk(" number %d, primary %d, secondary %d, subordinate %d\n", |
---|
1003 | pb->number, |
---|
1004 | pb->primary, |
---|
1005 | pb->secondary, |
---|
1006 | pb->subordinate ); |
---|
1007 | printk(" bridge; vendor %04x, device %04x\n", |
---|
1008 | pb->self->vendor, |
---|
1009 | pb->self->device ); |
---|
1010 | |
---|
1011 | { |
---|
1012 | struct pci_dev *pd; |
---|
1013 | |
---|
1014 | for(pd= pb->devices; pd; pd=pd->sibling ) |
---|
1015 | { |
---|
1016 | printk(" vendor %04x, device %04x, irq %d\n", |
---|
1017 | pd->vendor, |
---|
1018 | pd->device, |
---|
1019 | pd->irq ); |
---|
1020 | |
---|
1021 | } |
---|
1022 | printk("\n"); |
---|
1023 | } |
---|
1024 | |
---|
1025 | } |
---|
1026 | printk("\n"); |
---|
1027 | |
---|
1028 | printk("PCI resources:\n"); |
---|
1029 | for (r=pci->resources; r; r= r->next) |
---|
1030 | { |
---|
1031 | printk(" bus %d, vendor %04x, device %04x, base %08x, size %08x, type %d\n", |
---|
1032 | r->dev->bus->number, |
---|
1033 | r->dev->vendor, |
---|
1034 | r->dev->device, |
---|
1035 | r->base, |
---|
1036 | r->size, |
---|
1037 | r->type ); |
---|
1038 | } |
---|
1039 | printk("\n"); |
---|
1040 | |
---|
1041 | return; |
---|
1042 | } |
---|
1043 | |
---|
1044 | #endif |
---|
1045 | |
---|
1046 | static struct _addr_start |
---|
1047 | { |
---|
1048 | uint32_t start_pcimem; |
---|
1049 | uint32_t start_pciio; |
---|
1050 | uint32_t start_prefetch; |
---|
1051 | } astart; |
---|
1052 | |
---|
1053 | static pci_resource *enum_device_resources( struct pci_dev *pdev, int i ) |
---|
1054 | { |
---|
1055 | pci_resource *r; |
---|
1056 | |
---|
1057 | for(r= pci->resources; r; r= r->next ) |
---|
1058 | { |
---|
1059 | if( r->dev == pdev ) |
---|
1060 | { |
---|
1061 | if( i-- == 0 ) break; |
---|
1062 | } |
---|
1063 | } |
---|
1064 | return r; |
---|
1065 | } |
---|
1066 | |
---|
1067 | static void recursive_bus_reconfigure( struct pci_bus *pbus ) |
---|
1068 | { |
---|
1069 | struct pci_dev *pdev; |
---|
1070 | struct pci_bus *childbus; |
---|
1071 | int isroot = 0; |
---|
1072 | |
---|
1073 | if( !pbus ) |
---|
1074 | { |
---|
1075 | /* start with the root bus */ |
---|
1076 | astart.start_pcimem = BUSREST_MEM_START; |
---|
1077 | astart.start_pciio = BUSREST_IO_START; |
---|
1078 | astart.start_prefetch = ((BUSREST_MEM_END >> 16) << 16); |
---|
1079 | |
---|
1080 | pbus = &pci_root; |
---|
1081 | isroot = -1; |
---|
1082 | } |
---|
1083 | |
---|
1084 | #define WRITE_BRIDGE_IO |
---|
1085 | #define WRITE_BRIDGE_MEM |
---|
1086 | #define WRITE_BRIDGE_PF |
---|
1087 | #define WRITE_BRIDGE_ENABLE |
---|
1088 | |
---|
1089 | /* |
---|
1090 | ** Run thru the p2p bridges on this bus and recurse into subordinate busses |
---|
1091 | */ |
---|
1092 | for( childbus= pbus->children; childbus; childbus= childbus->next ) |
---|
1093 | { |
---|
1094 | pdev= childbus->self; |
---|
1095 | |
---|
1096 | pcibios_write_config_byte(pdev->bus->number, pdev->devfn, PCI_LATENCY_TIMER, 0x80 ); |
---|
1097 | pcibios_write_config_byte(pdev->bus->number, pdev->devfn, PCI_SEC_LATENCY_TIMER, 0x80 ); |
---|
1098 | |
---|
1099 | { |
---|
1100 | struct _addr_start addrhold; |
---|
1101 | uint8_t base8, limit8; |
---|
1102 | uint16_t base16, limit16, ubase16, ulimit16; |
---|
1103 | |
---|
1104 | /* save the base address values */ |
---|
1105 | memcpy( &addrhold, &astart, sizeof(struct _addr_start)); |
---|
1106 | |
---|
1107 | recursive_bus_reconfigure( childbus ); |
---|
1108 | |
---|
1109 | #ifdef PCI_DEBUG |
---|
1110 | printk("pci: configuring bus %d bridge (%04x:%04x), bus %d : (%d-%d)\n", |
---|
1111 | pdev->bus->number, |
---|
1112 | pdev->vendor, |
---|
1113 | pdev->device, |
---|
1114 | childbus->primary, |
---|
1115 | childbus->secondary, |
---|
1116 | childbus->subordinate ); |
---|
1117 | #endif |
---|
1118 | |
---|
1119 | /* |
---|
1120 | * use the current values & the saved ones to figure out |
---|
1121 | * the address spaces for the bridge |
---|
1122 | */ |
---|
1123 | |
---|
1124 | if( addrhold.start_pciio == astart.start_pciio ) |
---|
1125 | { |
---|
1126 | base8 = limit8 = 0xff; |
---|
1127 | ubase16 = ulimit16 = 0xffff; |
---|
1128 | } |
---|
1129 | else |
---|
1130 | { |
---|
1131 | base8 = (uint8_t) ((addrhold.start_pciio >> 8) & 0xf0); |
---|
1132 | ubase16 = (uint16_t)(addrhold.start_pciio >> 16); |
---|
1133 | limit8 = (uint8_t) ((astart.start_pciio >> 8 ) & 0xf0); |
---|
1134 | ulimit16 = (uint16_t)(astart.start_pciio >> 16); |
---|
1135 | astart.start_pciio += 0x1000; |
---|
1136 | } |
---|
1137 | |
---|
1138 | #ifdef PCI_DEBUG |
---|
1139 | printk("pci: io base %08x limit %08x\n", (base8<<8)+(ubase16<<16), (limit8<<8)+(ulimit16<<16)); |
---|
1140 | #endif |
---|
1141 | #ifdef WRITE_BRIDGE_IO |
---|
1142 | pcibios_write_config_word(pdev->bus->number, pdev->devfn, PCI_IO_BASE_UPPER16, ubase16 ); |
---|
1143 | pcibios_write_config_byte(pdev->bus->number, pdev->devfn, PCI_IO_BASE, base8 ); |
---|
1144 | |
---|
1145 | pcibios_write_config_word(pdev->bus->number, pdev->devfn, PCI_IO_LIMIT_UPPER16, ulimit16 ); |
---|
1146 | pcibios_write_config_byte(pdev->bus->number, pdev->devfn, PCI_IO_LIMIT, limit8 ); |
---|
1147 | #endif |
---|
1148 | |
---|
1149 | if( addrhold.start_pcimem == astart.start_pcimem ) |
---|
1150 | { |
---|
1151 | limit16 = 0; |
---|
1152 | base16 = 0xffff; |
---|
1153 | } |
---|
1154 | else |
---|
1155 | { |
---|
1156 | limit16= (uint16_t)((astart.start_pcimem >> 16) & 0xfff0); |
---|
1157 | base16 = (uint16_t)((addrhold.start_pcimem >> 16) & 0xfff0); |
---|
1158 | astart.start_pcimem += 0x100000; |
---|
1159 | } |
---|
1160 | #ifdef PCI_DEBUG |
---|
1161 | printk("pci: memory %04x, limit %04x\n", base16, limit16); |
---|
1162 | #endif |
---|
1163 | #ifdef WRITE_BRIDGE_MEM |
---|
1164 | pcibios_write_config_word(pdev->bus->number, pdev->devfn, PCI_MEMORY_BASE, base16 ); |
---|
1165 | pcibios_write_config_word(pdev->bus->number, pdev->devfn, PCI_MEMORY_LIMIT, limit16 ); |
---|
1166 | #endif |
---|
1167 | |
---|
1168 | |
---|
1169 | if( astart.start_prefetch == addrhold.start_prefetch ) |
---|
1170 | { |
---|
1171 | limit16 = 0; |
---|
1172 | base16 = 0xffff; |
---|
1173 | } |
---|
1174 | else |
---|
1175 | { |
---|
1176 | limit16= (uint16_t)((addrhold.start_prefetch >> 16) & 0xfff0); |
---|
1177 | base16 = (uint16_t)((astart.start_prefetch >> 16) & 0xfff0); |
---|
1178 | astart.start_prefetch -= 0x100000; |
---|
1179 | } |
---|
1180 | #ifdef PCI_DEBUG |
---|
1181 | printk("pci: pf memory %04x, limit %04x\n", base16, limit16); |
---|
1182 | #endif |
---|
1183 | #ifdef WRITE_BRIDGE_PF |
---|
1184 | pcibios_write_config_dword(pdev->bus->number, pdev->devfn, PCI_PREF_BASE_UPPER32, 0); |
---|
1185 | pcibios_write_config_word(pdev->bus->number, pdev->devfn, PCI_PREF_MEMORY_BASE, base16 ); |
---|
1186 | pcibios_write_config_dword(pdev->bus->number, pdev->devfn, PCI_PREF_LIMIT_UPPER32, 0); |
---|
1187 | pcibios_write_config_word(pdev->bus->number, pdev->devfn, PCI_PREF_MEMORY_LIMIT, limit16 ); |
---|
1188 | #endif |
---|
1189 | |
---|
1190 | #ifdef WRITE_BRIDGE_ENABLE |
---|
1191 | pcibios_write_config_word(pdev->bus->number, |
---|
1192 | pdev->devfn, |
---|
1193 | PCI_BRIDGE_CONTROL, |
---|
1194 | (uint16_t)( 0 )); |
---|
1195 | |
---|
1196 | pcibios_write_config_word(pdev->bus->number, |
---|
1197 | pdev->devfn, |
---|
1198 | PCI_COMMAND, |
---|
1199 | (uint16_t)( PCI_COMMAND_IO | |
---|
1200 | PCI_COMMAND_MEMORY | |
---|
1201 | PCI_COMMAND_MASTER )); |
---|
1202 | #endif |
---|
1203 | } |
---|
1204 | } |
---|
1205 | |
---|
1206 | if( !isroot ) |
---|
1207 | { |
---|
1208 | #ifdef PCI_DEBUG |
---|
1209 | printk("pci: Configuring devices on bus %d\n", pbus->number); |
---|
1210 | #endif |
---|
1211 | /* |
---|
1212 | ** Run thru this bus and set up addresses for all the non-bridge devices |
---|
1213 | */ |
---|
1214 | for( pdev = pbus->devices; pdev; pdev= pdev->sibling ) |
---|
1215 | { |
---|
1216 | if( (pdev->class >> 8) != PCI_CLASS_BRIDGE_PCI ) |
---|
1217 | { |
---|
1218 | pci_resource *r; |
---|
1219 | int i = 0; |
---|
1220 | unsigned alloc; |
---|
1221 | |
---|
1222 | /* enumerate all the resources defined by this device & reserve space |
---|
1223 | ** for each of their defined regions. |
---|
1224 | */ |
---|
1225 | |
---|
1226 | #ifdef PCI_DEBUG |
---|
1227 | printk("pci: configuring; vendor %04x, device %04x\n", pdev->vendor, pdev->device ); |
---|
1228 | #endif |
---|
1229 | |
---|
1230 | while( (r= enum_device_resources( pdev, i++ )) ) |
---|
1231 | { |
---|
1232 | /* |
---|
1233 | ** Force all memory spaces to be non-prefetchable because |
---|
1234 | ** on the pci bus, byte-wise reads against prefetchable |
---|
1235 | ** memory are applied as 32 bit reads, which is a pain |
---|
1236 | ** when you're trying to talk to hardware. This is a |
---|
1237 | ** little sub-optimal because the algorithm doesn't sort |
---|
1238 | ** the address regions to pack them in, OTOH, perhaps its |
---|
1239 | ** not so bad because the inefficient packing will help |
---|
1240 | ** avoid buffer overflow/underflow problems. |
---|
1241 | */ |
---|
1242 | #if 0 |
---|
1243 | if( (r->type & PCI_BASE_ADDRESS_MEM_PREFETCH) ) |
---|
1244 | { |
---|
1245 | /* prefetchable space */ |
---|
1246 | |
---|
1247 | /* shift base pointer down to an integer multiple of the size of the desired region */ |
---|
1248 | astart.start_prefetch -= (alloc= ((r->size / PAGE_SIZE) + 1) * PAGE_SIZE); |
---|
1249 | /* shift base pointer down to an integer multiple of the size of the desired region */ |
---|
1250 | astart.start_prefetch = (astart.start_prefetch / r->size) * r->size; |
---|
1251 | |
---|
1252 | r->base = astart.start_prefetch; |
---|
1253 | #ifdef PCI_DEBUG |
---|
1254 | printk("pci: pf %08X, size %08X, alloc %08X\n", r->base, r->size, alloc ); |
---|
1255 | #endif |
---|
1256 | } |
---|
1257 | #endif |
---|
1258 | if( r->type & PCI_BASE_ADDRESS_SPACE_IO ) |
---|
1259 | { |
---|
1260 | /* io space */ |
---|
1261 | |
---|
1262 | /* shift base pointer up to an integer multiple of the size of the desired region */ |
---|
1263 | if( astart.start_pciio % r->size ) |
---|
1264 | astart.start_pciio = (((astart.start_pciio / r->size) + 1) * r->size); |
---|
1265 | |
---|
1266 | r->base = astart.start_pciio; |
---|
1267 | astart.start_pciio += (alloc= ((r->size / PAGE_SIZE) + 1) * PAGE_SIZE); |
---|
1268 | #ifdef PCI_DEBUG |
---|
1269 | printk("pci: io %08X, size %08X, alloc %08X\n", r->base, r->size, alloc ); |
---|
1270 | #endif |
---|
1271 | } |
---|
1272 | else |
---|
1273 | { |
---|
1274 | /* memory space */ |
---|
1275 | |
---|
1276 | /* shift base pointer up to an integer multiple of the size of the desired region */ |
---|
1277 | if( astart.start_pcimem % r->size ) |
---|
1278 | astart.start_pcimem = (((astart.start_pcimem / r->size) + 1) * r->size); |
---|
1279 | |
---|
1280 | r->base = astart.start_pcimem; |
---|
1281 | astart.start_pcimem += (alloc= ((r->size / PAGE_SIZE) + 1) * PAGE_SIZE); |
---|
1282 | #ifdef PCI_DEBUG |
---|
1283 | printk("pci: mem %08X, size %08X, alloc %08X\n", r->base, r->size, alloc ); |
---|
1284 | #endif |
---|
1285 | } |
---|
1286 | } |
---|
1287 | |
---|
1288 | } |
---|
1289 | } |
---|
1290 | } |
---|
1291 | |
---|
1292 | } |
---|
1293 | |
---|
1294 | void pci_init(void) |
---|
1295 | { |
---|
1296 | PPC_DEVICE *hostbridge; |
---|
1297 | |
---|
1298 | if (pci->last_dev_p) { |
---|
1299 | printk("Two or more calls to pci_init!\n"); |
---|
1300 | return; |
---|
1301 | } |
---|
1302 | pci->last_dev_p = &(bd->pci_devices); |
---|
1303 | hostbridge=residual_find_device(PROCESSORDEVICE, NULL, |
---|
1304 | BridgeController, |
---|
1305 | PCIBridge, -1, 0); |
---|
1306 | if (hostbridge) { |
---|
1307 | if (hostbridge->DeviceId.Interface==PCIBridgeIndirect) { |
---|
1308 | bd->pci_functions=&indirect_functions; |
---|
1309 | /* Should be extracted from residual data, |
---|
1310 | * indeed MPC106 in CHRP mode is different, |
---|
1311 | * but we should not use residual data in |
---|
1312 | * this case anyway. |
---|
1313 | */ |
---|
1314 | pci->config_addr = ((volatile u_int *) |
---|
1315 | (ptr_mem_map->io_base+0xcf8)); |
---|
1316 | pci->config_data = ptr_mem_map->io_base+0xcfc; |
---|
1317 | } else if(hostbridge->DeviceId.Interface==PCIBridgeDirect) { |
---|
1318 | bd->pci_functions=&direct_functions; |
---|
1319 | pci->config_data=(u_char *) 0x80800000; |
---|
1320 | } else { |
---|
1321 | } |
---|
1322 | } else { |
---|
1323 | /* Let us try by experimentation at our own risk! */ |
---|
1324 | u_int id0; |
---|
1325 | bd->pci_functions = &direct_functions; |
---|
1326 | /* On all direct bridges I know the host bridge itself |
---|
1327 | * appears as device 0 function 0. |
---|
1328 | */ |
---|
1329 | pcibios_read_config_dword(0, 0, PCI_VENDOR_ID, &id0); |
---|
1330 | if (id0==~0U) { |
---|
1331 | bd->pci_functions = &indirect_functions; |
---|
1332 | pci->config_addr = ((volatile u_int *) |
---|
1333 | (ptr_mem_map->io_base+0xcf8)); |
---|
1334 | pci->config_data = ptr_mem_map->io_base+0xcfc; |
---|
1335 | } |
---|
1336 | /* Here we should check that the host bridge is actually |
---|
1337 | * present, but if it not, we are in such a desperate |
---|
1338 | * situation, that we probably can't even tell it. |
---|
1339 | */ |
---|
1340 | } |
---|
1341 | /* Now build a small database of all found PCI devices */ |
---|
1342 | printk("\nPCI: Probing PCI hardware\n"); |
---|
1343 | pci_root.subordinate=pci_scan_bus(&pci_root); |
---|
1344 | |
---|
1345 | print_pci_resources("Installed PCI resources:\n"); |
---|
1346 | |
---|
1347 | recursive_bus_reconfigure(NULL); |
---|
1348 | |
---|
1349 | reconfigure_pci(); |
---|
1350 | |
---|
1351 | print_pci_resources("Allocated PCI resources:\n"); |
---|
1352 | |
---|
1353 | #if 0 |
---|
1354 | print_pci_info(); |
---|
1355 | #endif |
---|
1356 | } |
---|
1357 | |
---|
1358 | /* eof */ |
---|