1 |
30 |
unneback |
/*
|
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.OARcorp.com/rtems/license.html.
|
14 |
|
|
*
|
15 |
|
|
* $Id: pci.c,v 1.2 2001-09-27 12:01:06 chris Exp $
|
16 |
|
|
*/
|
17 |
|
|
|
18 |
|
|
|
19 |
|
|
#include <sys/types.h>
|
20 |
|
|
#include <libcpu/spr.h>
|
21 |
|
|
#include "bootldr.h"
|
22 |
|
|
#include "pci.h"
|
23 |
|
|
#include <libcpu/io.h>
|
24 |
|
|
#include <bsp/consoleIo.h>
|
25 |
|
|
|
26 |
|
|
typedef unsigned int u32;
|
27 |
|
|
|
28 |
|
|
/*#define DEBUG*/
|
29 |
|
|
/* Used to reorganize PCI space on stupid machines which spread resources
|
30 |
|
|
* across a wide address space. This is bad when P2P bridges are present
|
31 |
|
|
* or when it limits the mappings that a resource hog like a PCI<->VME
|
32 |
|
|
* bridge can use.
|
33 |
|
|
*/
|
34 |
|
|
|
35 |
|
|
typedef struct _pci_resource {
|
36 |
|
|
struct _pci_resource *next;
|
37 |
|
|
struct pci_dev *dev;
|
38 |
|
|
u_long base; /* will be 64 bits on 64 bits machines */
|
39 |
|
|
u_long size;
|
40 |
|
|
u_char type; /* 1 is I/O else low order 4 bits of the memory type */
|
41 |
|
|
u_char reg; /* Register # in conf space header */
|
42 |
|
|
u_short cmd; /* Original cmd byte */
|
43 |
|
|
} pci_resource;
|
44 |
|
|
|
45 |
|
|
typedef struct _pci_area {
|
46 |
|
|
struct _pci_area *next;
|
47 |
|
|
u_long start;
|
48 |
|
|
u_long end;
|
49 |
|
|
struct pci_bus *bus;
|
50 |
|
|
u_int flags;
|
51 |
|
|
} pci_area;
|
52 |
|
|
|
53 |
|
|
typedef struct _pci_area_head {
|
54 |
|
|
pci_area *head;
|
55 |
|
|
u_long mask;
|
56 |
|
|
int high; /* To allocate from top */
|
57 |
|
|
} pci_area_head;
|
58 |
|
|
|
59 |
|
|
#define PCI_AREA_PREFETCHABLE 0
|
60 |
|
|
#define PCI_AREA_MEMORY 1
|
61 |
|
|
#define PCI_AREA_IO 2
|
62 |
|
|
|
63 |
|
|
struct _pci_private {
|
64 |
|
|
volatile u_int * config_addr;
|
65 |
|
|
volatile u_char * config_data;
|
66 |
|
|
struct pci_dev **last_dev_p;
|
67 |
|
|
struct pci_bus pci_root;
|
68 |
|
|
pci_resource *resources;
|
69 |
|
|
pci_area_head io, mem;
|
70 |
|
|
|
71 |
|
|
} pci_private = {
|
72 |
|
|
config_addr: NULL,
|
73 |
|
|
config_data: (volatile u_char *) 0x80800000,
|
74 |
|
|
last_dev_p: NULL,
|
75 |
|
|
resources: NULL,
|
76 |
|
|
io: {NULL, 0xfff, 0},
|
77 |
|
|
mem: {NULL, 0xfffff, 0}
|
78 |
|
|
};
|
79 |
|
|
|
80 |
|
|
#define pci ((struct _pci_private *)(bd->pci_private))
|
81 |
|
|
#define pci_root pci->pci_root
|
82 |
|
|
|
83 |
|
|
#if !defined(DEBUG)
|
84 |
|
|
#undef PCI_DEBUG
|
85 |
|
|
/*
|
86 |
|
|
#else
|
87 |
|
|
#define PCI_DEBUG
|
88 |
|
|
*/
|
89 |
|
|
#endif
|
90 |
|
|
|
91 |
|
|
#if defined(PCI_DEBUG)
|
92 |
|
|
static void
|
93 |
|
|
print_pci_resources(const char *s) {
|
94 |
|
|
pci_resource *p;
|
95 |
|
|
printk("%s", s);
|
96 |
|
|
for (p=pci->resources; p; p=p->next) {
|
97 |
|
|
printk(" %p:%p %06x %08lx %08lx %d\n",
|
98 |
|
|
p, p->next,
|
99 |
|
|
(p->dev->devfn<<8)+(p->dev->bus->number<<16)
|
100 |
|
|
+0x10+p->reg*4,
|
101 |
|
|
p->base,
|
102 |
|
|
p->size,
|
103 |
|
|
p->type);
|
104 |
|
|
}
|
105 |
|
|
}
|
106 |
|
|
|
107 |
|
|
static void
|
108 |
|
|
print_pci_area(pci_area *p) {
|
109 |
|
|
for (; p; p=p->next) {
|
110 |
|
|
printk(" %p:%p %p %08lx %08lx\n",
|
111 |
|
|
p, p->next, p->bus, p->start, p->end);
|
112 |
|
|
}
|
113 |
|
|
}
|
114 |
|
|
|
115 |
|
|
static void
|
116 |
|
|
print_pci_areas(const char *s) {
|
117 |
|
|
printk("%s PCI I/O areas:\n",s);
|
118 |
|
|
print_pci_area(pci->io.head);
|
119 |
|
|
printk(" PCI memory areas:\n");
|
120 |
|
|
print_pci_area(pci->mem.head);
|
121 |
|
|
}
|
122 |
|
|
#else
|
123 |
|
|
#define print_pci_areas(x)
|
124 |
|
|
#define print_pci_resources(x)
|
125 |
|
|
#endif
|
126 |
|
|
|
127 |
|
|
/* Maybe there are some devices who use a size different
|
128 |
|
|
* from the alignment. For now we assume both are the same.
|
129 |
|
|
* The blacklist might be used for other weird things in the future too,
|
130 |
|
|
* since weird non PCI complying devices seem to proliferate these days.
|
131 |
|
|
*/
|
132 |
|
|
|
133 |
|
|
struct blacklist_entry {
|
134 |
|
|
u_short vendor, device;
|
135 |
|
|
u_char reg;
|
136 |
|
|
u_long actual_size;
|
137 |
|
|
};
|
138 |
|
|
|
139 |
|
|
#define BLACKLIST(vid, did, breg, actual_size) \
|
140 |
|
|
{PCI_VENDOR_ID_##vid, PCI_DEVICE_ID_##vid##_##did, breg, actual_size}
|
141 |
|
|
|
142 |
|
|
static struct blacklist_entry blacklist[] = {
|
143 |
|
|
BLACKLIST(S3, TRIO, 0, 0x04000000),
|
144 |
|
|
{0xffff, 0, 0, 0}
|
145 |
|
|
};
|
146 |
|
|
|
147 |
|
|
|
148 |
|
|
/* This function filters resources and then inserts them into a list of
|
149 |
|
|
* configurable pci resources.
|
150 |
|
|
*/
|
151 |
|
|
|
152 |
|
|
|
153 |
|
|
#define AREA(r) \
|
154 |
|
|
(((r->type&PCI_BASE_ADDRESS_SPACE)==PCI_BASE_ADDRESS_SPACE_IO) ? PCI_AREA_IO :\
|
155 |
|
|
((r->type&PCI_BASE_ADDRESS_MEM_PREFETCH) ? PCI_AREA_PREFETCHABLE :\
|
156 |
|
|
PCI_AREA_MEMORY))
|
157 |
|
|
|
158 |
|
|
static int insert_before(pci_resource *e, pci_resource *t) {
|
159 |
|
|
if (e->dev->bus->number != t->dev->bus->number)
|
160 |
|
|
return e->dev->bus->number > t->dev->bus->number;
|
161 |
|
|
if (AREA(e) != AREA(t)) return AREA(e)<AREA(t);
|
162 |
|
|
return (e->size > t->size);
|
163 |
|
|
}
|
164 |
|
|
|
165 |
|
|
static void insert_resource(pci_resource *r) {
|
166 |
|
|
struct blacklist_entry *b;
|
167 |
|
|
pci_resource *p;
|
168 |
|
|
if (!r) return;
|
169 |
|
|
|
170 |
|
|
/* First fixup in case we have a blacklist entry. Note that this
|
171 |
|
|
* may temporarily leave a resource in an inconsistent state: with
|
172 |
|
|
* (base & (size-1)) !=0. This is harmless.
|
173 |
|
|
*/
|
174 |
|
|
for (b=blacklist; b->vendor!=0xffff; b++) {
|
175 |
|
|
if ((r->dev->vendor==b->vendor) &&
|
176 |
|
|
(r->dev->device==b->device) &&
|
177 |
|
|
(r->reg==b->reg)) {
|
178 |
|
|
r->size=b->actual_size;
|
179 |
|
|
break;
|
180 |
|
|
}
|
181 |
|
|
}
|
182 |
|
|
|
183 |
|
|
/* Motorola NT firmware does not configure pci devices which are not
|
184 |
|
|
* required for booting, others do. For now:
|
185 |
|
|
* - allocated devices in the ISA range (64kB I/O, 16Mb memory)
|
186 |
|
|
* but non zero base registers are left as is.
|
187 |
|
|
* - all other registers, whether already allocated or not, are
|
188 |
|
|
* reallocated unless they require an inordinate amount of
|
189 |
|
|
* resources (>256 Mb for memory >64kB for I/O). These
|
190 |
|
|
* devices with too large mapping requirements are simply ignored
|
191 |
|
|
* and their bases are set to 0. This should disable the
|
192 |
|
|
* corresponding decoders according to the PCI specification.
|
193 |
|
|
* Many devices are buggy in this respect, however, but the
|
194 |
|
|
* limits have hopefully been set high enough to avoid problems.
|
195 |
|
|
*/
|
196 |
|
|
|
197 |
|
|
if ((r->type==PCI_BASE_ADDRESS_SPACE_IO)
|
198 |
|
|
? (r->base && r->base <0x10000)
|
199 |
|
|
: (r->base && r->base <0x1000000)) {
|
200 |
|
|
sfree(r);
|
201 |
|
|
return;
|
202 |
|
|
}
|
203 |
|
|
|
204 |
|
|
if ((r->type==PCI_BASE_ADDRESS_SPACE_IO)
|
205 |
|
|
? (r->size >= 0x10000)
|
206 |
|
|
: (r->size >= 0x10000000)) {
|
207 |
|
|
r->size = 0;
|
208 |
|
|
r->base = 0;
|
209 |
|
|
}
|
210 |
|
|
|
211 |
|
|
/* Now insert into the list sorting by
|
212 |
|
|
* 1) decreasing bus number
|
213 |
|
|
* 2) space: prefetchable memory, non-prefetchable and finally I/O
|
214 |
|
|
* 3) decreasing size
|
215 |
|
|
*/
|
216 |
|
|
if (!pci->resources || insert_before(r, pci->resources)) {
|
217 |
|
|
r->next = pci->resources;
|
218 |
|
|
pci->resources=r;
|
219 |
|
|
} else {
|
220 |
|
|
for (p=pci->resources; p->next; p=p->next) {
|
221 |
|
|
if (insert_before(r, p->next)) break;
|
222 |
|
|
}
|
223 |
|
|
r->next=p->next;
|
224 |
|
|
p->next=r;
|
225 |
|
|
}
|
226 |
|
|
}
|
227 |
|
|
|
228 |
|
|
/* This version only works for bus 0. I don't have any P2P bridges to test
|
229 |
|
|
* a more sophisticated version which has therefore not been implemented.
|
230 |
|
|
* Prefetchable memory is not yet handled correctly either.
|
231 |
|
|
* And several levels of PCI bridges much less even since there must be
|
232 |
|
|
* allocated together to be able to setup correctly the top bridge.
|
233 |
|
|
*/
|
234 |
|
|
|
235 |
|
|
static u_long find_range(u_char bus, u_char type,
|
236 |
|
|
pci_resource **first,
|
237 |
|
|
pci_resource **past, u_int *flags) {
|
238 |
|
|
pci_resource *p;
|
239 |
|
|
u_long total=0;
|
240 |
|
|
u_int fl=0;
|
241 |
|
|
|
242 |
|
|
for (p=pci->resources; p; p=p->next) {
|
243 |
|
|
if ((p->dev->bus->number == bus) &&
|
244 |
|
|
AREA(p)==type) break;
|
245 |
|
|
}
|
246 |
|
|
*first = p;
|
247 |
|
|
for (; p; p=p->next) {
|
248 |
|
|
if ((p->dev->bus->number != bus) ||
|
249 |
|
|
AREA(p)!=type || p->size == 0) break;
|
250 |
|
|
total = total+p->size;
|
251 |
|
|
fl |= 1<<p->type;
|
252 |
|
|
}
|
253 |
|
|
*past = p;
|
254 |
|
|
/* This will be used later to tell whether there are any 32 bit
|
255 |
|
|
* devices in an area which could be mapped higher than 4Gb
|
256 |
|
|
* on 64 bits architectures
|
257 |
|
|
*/
|
258 |
|
|
*flags = fl;
|
259 |
|
|
return total;
|
260 |
|
|
}
|
261 |
|
|
|
262 |
|
|
static inline void init_free_area(pci_area_head *h, u_long start,
|
263 |
|
|
u_long end, u_int mask, int high) {
|
264 |
|
|
pci_area *p;
|
265 |
|
|
p = salloc(sizeof(pci_area));
|
266 |
|
|
if (!p) return;
|
267 |
|
|
h->head = p;
|
268 |
|
|
p->next = NULL;
|
269 |
|
|
p->start = (start+mask)&~mask;
|
270 |
|
|
p->end = (end-mask)|mask;
|
271 |
|
|
p->bus = NULL;
|
272 |
|
|
h->mask = mask;
|
273 |
|
|
h->high = high;
|
274 |
|
|
}
|
275 |
|
|
|
276 |
|
|
static void insert_area(pci_area_head *h, pci_area *p) {
|
277 |
|
|
pci_area *q = h->head;
|
278 |
|
|
if (!p) return;
|
279 |
|
|
if (q && (q->start< p->start)) {
|
280 |
|
|
for(;q->next && q->next->start<p->start; q = q->next);
|
281 |
|
|
if ((q->end >= p->start) ||
|
282 |
|
|
(q->next && p->end>=q->next->start)) {
|
283 |
|
|
sfree(p);
|
284 |
|
|
printk("Overlapping pci areas!\n");
|
285 |
|
|
return;
|
286 |
|
|
}
|
287 |
|
|
p->next = q->next;
|
288 |
|
|
q->next = p;
|
289 |
|
|
} else { /* Insert at head */
|
290 |
|
|
if (q && (p->end >= q->start)) {
|
291 |
|
|
sfree(p);
|
292 |
|
|
printk("Overlapping pci areas!\n");
|
293 |
|
|
return;
|
294 |
|
|
}
|
295 |
|
|
p->next = q;
|
296 |
|
|
h->head = p;
|
297 |
|
|
}
|
298 |
|
|
}
|
299 |
|
|
|
300 |
|
|
static
|
301 |
|
|
void remove_area(pci_area_head *h, pci_area *p) {
|
302 |
|
|
pci_area *q = h->head;
|
303 |
|
|
|
304 |
|
|
if (!p || !q) return;
|
305 |
|
|
if (q==p) {
|
306 |
|
|
h->head = q->next;
|
307 |
|
|
return;
|
308 |
|
|
}
|
309 |
|
|
for(;q && q->next!=p; q=q->next);
|
310 |
|
|
if (q) q->next=p->next;
|
311 |
|
|
}
|
312 |
|
|
|
313 |
|
|
static pci_area * alloc_area(pci_area_head *h, struct pci_bus *bus,
|
314 |
|
|
u_long required, u_long mask, u_int flags) {
|
315 |
|
|
pci_area *p;
|
316 |
|
|
pci_area *from, *split, *new;
|
317 |
|
|
|
318 |
|
|
required = (required+h->mask) & ~h->mask;
|
319 |
|
|
for (p=h->head, from=NULL; p; p=p->next) {
|
320 |
|
|
u_long l1 = ((p->start+required+mask)&~mask)-1;
|
321 |
|
|
u_long l2 = ((p->start+mask)&~mask)+required-1;
|
322 |
|
|
/* Allocated areas point to the bus to which they pertain */
|
323 |
|
|
if (p->bus) continue;
|
324 |
|
|
if ((p->end)>=l1 || (p->end)>=l2) from=p;
|
325 |
|
|
if (from && !h->high) break;
|
326 |
|
|
}
|
327 |
|
|
if (!from) return NULL;
|
328 |
|
|
|
329 |
|
|
split = salloc(sizeof(pci_area));
|
330 |
|
|
new = salloc(sizeof(pci_area));
|
331 |
|
|
/* If allocation of new succeeds then allocation of split has
|
332 |
|
|
* also been successful (given the current mm algorithms) !
|
333 |
|
|
*/
|
334 |
|
|
if (!new) {
|
335 |
|
|
sfree(split);
|
336 |
|
|
return NULL;
|
337 |
|
|
}
|
338 |
|
|
new->bus = bus;
|
339 |
|
|
new->flags = flags;
|
340 |
|
|
/* Now allocate pci_space taking alignment into account ! */
|
341 |
|
|
if (h->high) {
|
342 |
|
|
u_long l1 = ((from->end+1)&~mask)-required;
|
343 |
|
|
u_long l2 = (from->end+1-required)&~mask;
|
344 |
|
|
new->start = (l1>l2) ? l1 : l2;
|
345 |
|
|
split->end = from->end;
|
346 |
|
|
from->end = new->start-1;
|
347 |
|
|
split->start = new->start+required;
|
348 |
|
|
new->end = new->start+required-1;
|
349 |
|
|
} else {
|
350 |
|
|
u_long l1 = ((from->start+mask)&~mask)+required-1;
|
351 |
|
|
u_long l2 = ((from->start+required+mask)&~mask)-1;
|
352 |
|
|
new->end = (l1<l2) ? l1 : l2;
|
353 |
|
|
split->start = from->start;
|
354 |
|
|
from->start = new->end+1;
|
355 |
|
|
new->start = new->end+1-required;
|
356 |
|
|
split->end = new->start-1;
|
357 |
|
|
}
|
358 |
|
|
|
359 |
|
|
if (from->end+1 == from->start) remove_area(h, from);
|
360 |
|
|
if (split->end+1 != split->start) {
|
361 |
|
|
split->bus = NULL;
|
362 |
|
|
insert_area(h, split);
|
363 |
|
|
} else {
|
364 |
|
|
sfree(split);
|
365 |
|
|
}
|
366 |
|
|
insert_area(h, new);
|
367 |
|
|
print_pci_areas("alloc_area called:\n");
|
368 |
|
|
return new;
|
369 |
|
|
}
|
370 |
|
|
|
371 |
|
|
static inline
|
372 |
|
|
void alloc_space(pci_area *p, pci_resource *r) {
|
373 |
|
|
if (p->start & (r->size-1)) {
|
374 |
|
|
r->base = p->end+1-r->size;
|
375 |
|
|
p->end -= r->size;
|
376 |
|
|
} else {
|
377 |
|
|
r->base = p->start;
|
378 |
|
|
p->start += r->size;
|
379 |
|
|
}
|
380 |
|
|
}
|
381 |
|
|
|
382 |
|
|
static void reconfigure_bus_space(u_char bus, u_char type, pci_area_head *h) {
|
383 |
|
|
pci_resource *first, *past, *r;
|
384 |
|
|
pci_area *area, tmp;
|
385 |
|
|
u_int flags;
|
386 |
|
|
u_int required = find_range(bus, type, &first, &past, &flags);
|
387 |
|
|
|
388 |
|
|
if (required==0) return;
|
389 |
|
|
area = alloc_area(h, first->dev->bus, required, first->size-1, flags);
|
390 |
|
|
if (!area) return;
|
391 |
|
|
tmp = *area;
|
392 |
|
|
for (r=first; r!=past; r=r->next) {
|
393 |
|
|
alloc_space(&tmp, r);
|
394 |
|
|
}
|
395 |
|
|
}
|
396 |
|
|
|
397 |
|
|
static void reconfigure_pci(void) {
|
398 |
|
|
pci_resource *r;
|
399 |
|
|
struct pci_dev *dev;
|
400 |
|
|
/* FIXME: for now memory is relocated from low, it's better
|
401 |
|
|
* to start from higher addresses.
|
402 |
|
|
*/
|
403 |
|
|
init_free_area(&pci->io, 0x10000, 0x7fffff, 0xfff, 0);
|
404 |
|
|
init_free_area(&pci->mem, 0x1000000, 0x3cffffff, 0xfffff, 0);
|
405 |
|
|
|
406 |
|
|
/* First reconfigure the I/O space, this will be more
|
407 |
|
|
* complex when there is more than 1 bus. And 64 bits
|
408 |
|
|
* devices are another kind of problems.
|
409 |
|
|
*/
|
410 |
|
|
reconfigure_bus_space(0, PCI_AREA_IO, &pci->io);
|
411 |
|
|
reconfigure_bus_space(0, PCI_AREA_MEMORY, &pci->mem);
|
412 |
|
|
reconfigure_bus_space(0, PCI_AREA_PREFETCHABLE, &pci->mem);
|
413 |
|
|
|
414 |
|
|
/* Now we have to touch the configuration space of all
|
415 |
|
|
* the devices to remap them better than they are right now.
|
416 |
|
|
* This is done in 3 steps:
|
417 |
|
|
* 1) first disable I/O and memory response of all devices
|
418 |
|
|
* 2) modify the base registers
|
419 |
|
|
* 3) restore the original PCI_COMMAND register.
|
420 |
|
|
*/
|
421 |
|
|
for (r=pci->resources; r; r= r->next) {
|
422 |
|
|
if (!r->dev->sysdata) {
|
423 |
|
|
r->dev->sysdata=r;
|
424 |
|
|
pci_read_config_word(r->dev, PCI_COMMAND, &r->cmd);
|
425 |
|
|
pci_write_config_word(r->dev, PCI_COMMAND,
|
426 |
|
|
r->cmd & ~(PCI_COMMAND_IO|
|
427 |
|
|
PCI_COMMAND_MEMORY));
|
428 |
|
|
}
|
429 |
|
|
}
|
430 |
|
|
|
431 |
|
|
for (r=pci->resources; r; r= r->next) {
|
432 |
|
|
pci_write_config_dword(r->dev,
|
433 |
|
|
PCI_BASE_ADDRESS_0+(r->reg<<2),
|
434 |
|
|
r->base);
|
435 |
|
|
if ((r->type&
|
436 |
|
|
(PCI_BASE_ADDRESS_SPACE|
|
437 |
|
|
PCI_BASE_ADDRESS_MEM_TYPE_MASK)) ==
|
438 |
|
|
(PCI_BASE_ADDRESS_SPACE_MEMORY|
|
439 |
|
|
PCI_BASE_ADDRESS_MEM_TYPE_64)) {
|
440 |
|
|
pci_write_config_dword(r->dev,
|
441 |
|
|
PCI_BASE_ADDRESS_1+
|
442 |
|
|
(r->reg<<2),
|
443 |
|
|
0);
|
444 |
|
|
}
|
445 |
|
|
}
|
446 |
|
|
for (dev=bd->pci_devices; dev; dev= dev->next) {
|
447 |
|
|
if (dev->sysdata) {
|
448 |
|
|
pci_write_config_word(dev, PCI_COMMAND,
|
449 |
|
|
((pci_resource *)dev->sysdata)
|
450 |
|
|
->cmd);
|
451 |
|
|
dev->sysdata=NULL;
|
452 |
|
|
}
|
453 |
|
|
}
|
454 |
|
|
}
|
455 |
|
|
|
456 |
|
|
static int
|
457 |
|
|
indirect_pci_read_config_byte(unsigned char bus, unsigned char dev_fn,
|
458 |
|
|
unsigned char offset, unsigned char *val) {
|
459 |
|
|
out_be32(pci->config_addr,
|
460 |
|
|
0x80|(bus<<8)|(dev_fn<<16)|((offset&~3)<<24));
|
461 |
|
|
*val=in_8(pci->config_data + (offset&3));
|
462 |
|
|
return PCIBIOS_SUCCESSFUL;
|
463 |
|
|
}
|
464 |
|
|
|
465 |
|
|
static int
|
466 |
|
|
indirect_pci_read_config_word(unsigned char bus, unsigned char dev_fn,
|
467 |
|
|
unsigned char offset, unsigned short *val) {
|
468 |
|
|
*val = 0xffff;
|
469 |
|
|
if (offset&1) return PCIBIOS_BAD_REGISTER_NUMBER;
|
470 |
|
|
out_be32(pci->config_addr,
|
471 |
|
|
0x80|(bus<<8)|(dev_fn<<16)|((offset&~3)<<24));
|
472 |
|
|
*val=in_le16((volatile u_short *)(pci->config_data + (offset&3)));
|
473 |
|
|
return PCIBIOS_SUCCESSFUL;
|
474 |
|
|
}
|
475 |
|
|
|
476 |
|
|
static int
|
477 |
|
|
indirect_pci_read_config_dword(unsigned char bus, unsigned char dev_fn,
|
478 |
|
|
unsigned char offset, unsigned int *val) {
|
479 |
|
|
*val = 0xffffffff;
|
480 |
|
|
if (offset&3) return PCIBIOS_BAD_REGISTER_NUMBER;
|
481 |
|
|
out_be32(pci->config_addr,
|
482 |
|
|
0x80|(bus<<8)|(dev_fn<<16)|(offset<<24));
|
483 |
|
|
*val=in_le32((volatile u_int *)pci->config_data);
|
484 |
|
|
return PCIBIOS_SUCCESSFUL;
|
485 |
|
|
}
|
486 |
|
|
|
487 |
|
|
static int
|
488 |
|
|
indirect_pci_write_config_byte(unsigned char bus, unsigned char dev_fn,
|
489 |
|
|
unsigned char offset, unsigned char val) {
|
490 |
|
|
out_be32(pci->config_addr,
|
491 |
|
|
0x80|(bus<<8)|(dev_fn<<16)|((offset&~3)<<24));
|
492 |
|
|
out_8(pci->config_data + (offset&3), val);
|
493 |
|
|
return PCIBIOS_SUCCESSFUL;
|
494 |
|
|
}
|
495 |
|
|
|
496 |
|
|
static int
|
497 |
|
|
indirect_pci_write_config_word(unsigned char bus, unsigned char dev_fn,
|
498 |
|
|
unsigned char offset, unsigned short val) {
|
499 |
|
|
if (offset&1) return PCIBIOS_BAD_REGISTER_NUMBER;
|
500 |
|
|
out_be32(pci->config_addr,
|
501 |
|
|
0x80|(bus<<8)|(dev_fn<<16)|((offset&~3)<<24));
|
502 |
|
|
out_le16((volatile u_short *)(pci->config_data + (offset&3)), val);
|
503 |
|
|
return PCIBIOS_SUCCESSFUL;
|
504 |
|
|
}
|
505 |
|
|
|
506 |
|
|
static int
|
507 |
|
|
indirect_pci_write_config_dword(unsigned char bus, unsigned char dev_fn,
|
508 |
|
|
unsigned char offset, unsigned int val) {
|
509 |
|
|
if (offset&3) return PCIBIOS_BAD_REGISTER_NUMBER;
|
510 |
|
|
out_be32(pci->config_addr,
|
511 |
|
|
0x80|(bus<<8)|(dev_fn<<16)|(offset<<24));
|
512 |
|
|
out_le32((volatile u_int *)pci->config_data, val);
|
513 |
|
|
return PCIBIOS_SUCCESSFUL;
|
514 |
|
|
}
|
515 |
|
|
|
516 |
|
|
static const struct pci_config_access_functions indirect_functions = {
|
517 |
|
|
indirect_pci_read_config_byte,
|
518 |
|
|
indirect_pci_read_config_word,
|
519 |
|
|
indirect_pci_read_config_dword,
|
520 |
|
|
indirect_pci_write_config_byte,
|
521 |
|
|
indirect_pci_write_config_word,
|
522 |
|
|
indirect_pci_write_config_dword
|
523 |
|
|
};
|
524 |
|
|
|
525 |
|
|
|
526 |
|
|
static int
|
527 |
|
|
direct_pci_read_config_byte(unsigned char bus, unsigned char dev_fn,
|
528 |
|
|
unsigned char offset, unsigned char *val) {
|
529 |
|
|
if (bus != 0 || (1<<PCI_SLOT(dev_fn) & 0xff8007fe)) {
|
530 |
|
|
*val=0xff;
|
531 |
|
|
return PCIBIOS_DEVICE_NOT_FOUND;
|
532 |
|
|
}
|
533 |
|
|
*val=in_8(pci->config_data + ((1<<PCI_SLOT(dev_fn))&~1)
|
534 |
|
|
+ (PCI_FUNC(dev_fn)<<8) + offset);
|
535 |
|
|
return PCIBIOS_SUCCESSFUL;
|
536 |
|
|
}
|
537 |
|
|
|
538 |
|
|
static int
|
539 |
|
|
direct_pci_read_config_word(unsigned char bus, unsigned char dev_fn,
|
540 |
|
|
unsigned char offset, unsigned short *val) {
|
541 |
|
|
*val = 0xffff;
|
542 |
|
|
if (offset&1) return PCIBIOS_BAD_REGISTER_NUMBER;
|
543 |
|
|
if (bus != 0 || (1<<PCI_SLOT(dev_fn) & 0xff8007fe)) {
|
544 |
|
|
return PCIBIOS_DEVICE_NOT_FOUND;
|
545 |
|
|
}
|
546 |
|
|
*val=in_le16((volatile u_short *)
|
547 |
|
|
(pci->config_data + ((1<<PCI_SLOT(dev_fn))&~1)
|
548 |
|
|
+ (PCI_FUNC(dev_fn)<<8) + offset));
|
549 |
|
|
return PCIBIOS_SUCCESSFUL;
|
550 |
|
|
}
|
551 |
|
|
|
552 |
|
|
static int
|
553 |
|
|
direct_pci_read_config_dword(unsigned char bus, unsigned char dev_fn,
|
554 |
|
|
unsigned char offset, unsigned int *val) {
|
555 |
|
|
*val = 0xffffffff;
|
556 |
|
|
if (offset&3) return PCIBIOS_BAD_REGISTER_NUMBER;
|
557 |
|
|
if (bus != 0 || (1<<PCI_SLOT(dev_fn) & 0xff8007fe)) {
|
558 |
|
|
return PCIBIOS_DEVICE_NOT_FOUND;
|
559 |
|
|
}
|
560 |
|
|
*val=in_le32((volatile u_int *)
|
561 |
|
|
(pci->config_data + ((1<<PCI_SLOT(dev_fn))&~1)
|
562 |
|
|
+ (PCI_FUNC(dev_fn)<<8) + offset));
|
563 |
|
|
return PCIBIOS_SUCCESSFUL;
|
564 |
|
|
}
|
565 |
|
|
|
566 |
|
|
static int
|
567 |
|
|
direct_pci_write_config_byte(unsigned char bus, unsigned char dev_fn,
|
568 |
|
|
unsigned char offset, unsigned char val) {
|
569 |
|
|
if (bus != 0 || (1<<PCI_SLOT(dev_fn) & 0xff8007fe)) {
|
570 |
|
|
return PCIBIOS_DEVICE_NOT_FOUND;
|
571 |
|
|
}
|
572 |
|
|
out_8(pci->config_data + ((1<<PCI_SLOT(dev_fn))&~1)
|
573 |
|
|
+ (PCI_FUNC(dev_fn)<<8) + offset,
|
574 |
|
|
val);
|
575 |
|
|
return PCIBIOS_SUCCESSFUL;
|
576 |
|
|
}
|
577 |
|
|
|
578 |
|
|
static int
|
579 |
|
|
direct_pci_write_config_word(unsigned char bus, unsigned char dev_fn,
|
580 |
|
|
unsigned char offset, unsigned short val) {
|
581 |
|
|
if (offset&1) return PCIBIOS_BAD_REGISTER_NUMBER;
|
582 |
|
|
if (bus != 0 || (1<<PCI_SLOT(dev_fn) & 0xff8007fe)) {
|
583 |
|
|
return PCIBIOS_DEVICE_NOT_FOUND;
|
584 |
|
|
}
|
585 |
|
|
out_le16((volatile u_short *)
|
586 |
|
|
(pci->config_data + ((1<<PCI_SLOT(dev_fn))&~1)
|
587 |
|
|
+ (PCI_FUNC(dev_fn)<<8) + offset),
|
588 |
|
|
val);
|
589 |
|
|
return PCIBIOS_SUCCESSFUL;
|
590 |
|
|
}
|
591 |
|
|
|
592 |
|
|
static int
|
593 |
|
|
direct_pci_write_config_dword(unsigned char bus, unsigned char dev_fn,
|
594 |
|
|
unsigned char offset, unsigned int val) {
|
595 |
|
|
if (offset&3) return PCIBIOS_BAD_REGISTER_NUMBER;
|
596 |
|
|
if (bus != 0 || (1<<PCI_SLOT(dev_fn) & 0xff8007fe)) {
|
597 |
|
|
return PCIBIOS_DEVICE_NOT_FOUND;
|
598 |
|
|
}
|
599 |
|
|
out_le32((volatile u_int *)
|
600 |
|
|
(pci->config_data + ((1<<PCI_SLOT(dev_fn))&~1)
|
601 |
|
|
+ (PCI_FUNC(dev_fn)<<8) + offset),
|
602 |
|
|
val);
|
603 |
|
|
return PCIBIOS_SUCCESSFUL;
|
604 |
|
|
}
|
605 |
|
|
|
606 |
|
|
static const struct pci_config_access_functions direct_functions = {
|
607 |
|
|
direct_pci_read_config_byte,
|
608 |
|
|
direct_pci_read_config_word,
|
609 |
|
|
direct_pci_read_config_dword,
|
610 |
|
|
direct_pci_write_config_byte,
|
611 |
|
|
direct_pci_write_config_word,
|
612 |
|
|
direct_pci_write_config_dword
|
613 |
|
|
};
|
614 |
|
|
|
615 |
|
|
|
616 |
|
|
void pci_read_bases(struct pci_dev *dev, unsigned int howmany)
|
617 |
|
|
{
|
618 |
|
|
unsigned int reg, nextreg;
|
619 |
|
|
#define REG (PCI_BASE_ADDRESS_0 + (reg<<2))
|
620 |
|
|
u_short cmd;
|
621 |
|
|
u32 l, ml;
|
622 |
|
|
pci_read_config_word(dev, PCI_COMMAND, &cmd);
|
623 |
|
|
|
624 |
|
|
for(reg=0; reg<howmany; reg=nextreg) {
|
625 |
|
|
pci_resource *r;
|
626 |
|
|
nextreg=reg+1;
|
627 |
|
|
pci_read_config_dword(dev, REG, &l);
|
628 |
|
|
#if 0
|
629 |
|
|
if (l == 0xffffffff /*AJF || !l*/) continue;
|
630 |
|
|
#endif
|
631 |
|
|
/* Note that disabling the memory response of a host bridge
|
632 |
|
|
* would lose data if a DMA transfer were in progress. In a
|
633 |
|
|
* bootloader we don't care however. Also we can't print any
|
634 |
|
|
* message for a while since we might just disable the console.
|
635 |
|
|
*/
|
636 |
|
|
pci_write_config_word(dev, PCI_COMMAND, cmd &
|
637 |
|
|
~(PCI_COMMAND_IO|PCI_COMMAND_MEMORY));
|
638 |
|
|
pci_write_config_dword(dev, REG, ~0);
|
639 |
|
|
pci_read_config_dword(dev, REG, &ml);
|
640 |
|
|
pci_write_config_dword(dev, REG, l);
|
641 |
|
|
|
642 |
|
|
/* Reenable the device now that we've played with
|
643 |
|
|
* base registers.
|
644 |
|
|
*/
|
645 |
|
|
pci_write_config_word(dev, PCI_COMMAND, cmd);
|
646 |
|
|
|
647 |
|
|
/* seems to be an unused entry skip it */
|
648 |
|
|
if ( ml == 0 || ml == 0xffffffff ) continue;
|
649 |
|
|
|
650 |
|
|
if ((l &
|
651 |
|
|
(PCI_BASE_ADDRESS_SPACE|PCI_BASE_ADDRESS_MEM_TYPE_MASK))
|
652 |
|
|
== (PCI_BASE_ADDRESS_MEM_TYPE_64
|
653 |
|
|
|PCI_BASE_ADDRESS_SPACE_MEMORY)) {
|
654 |
|
|
nextreg=reg+2;
|
655 |
|
|
}
|
656 |
|
|
dev->base_address[reg] = l;
|
657 |
|
|
r = salloc(sizeof(pci_resource));
|
658 |
|
|
if (!r) {
|
659 |
|
|
printk("Error allocating pci_resource struct.\n");
|
660 |
|
|
continue;
|
661 |
|
|
}
|
662 |
|
|
r->dev = dev;
|
663 |
|
|
r->reg = reg;
|
664 |
|
|
if ((l&PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) {
|
665 |
|
|
r->type = l&~PCI_BASE_ADDRESS_IO_MASK;
|
666 |
|
|
r->base = l&PCI_BASE_ADDRESS_IO_MASK;
|
667 |
|
|
r->size = ~(ml&PCI_BASE_ADDRESS_IO_MASK)+1;
|
668 |
|
|
} else {
|
669 |
|
|
r->type = l&~PCI_BASE_ADDRESS_MEM_MASK;
|
670 |
|
|
r->base = l&PCI_BASE_ADDRESS_MEM_MASK;
|
671 |
|
|
r->size = ~(ml&PCI_BASE_ADDRESS_MEM_MASK)+1;
|
672 |
|
|
}
|
673 |
|
|
/* Check for the blacklisted entries */
|
674 |
|
|
insert_resource(r);
|
675 |
|
|
}
|
676 |
|
|
}
|
677 |
|
|
|
678 |
|
|
|
679 |
|
|
|
680 |
|
|
|
681 |
|
|
u_int pci_scan_bus(struct pci_bus *bus)
|
682 |
|
|
{
|
683 |
|
|
unsigned int devfn, l, max, class;
|
684 |
|
|
unsigned char irq, hdr_type, is_multi = 0;
|
685 |
|
|
struct pci_dev *dev, **bus_last;
|
686 |
|
|
struct pci_bus *child;
|
687 |
|
|
|
688 |
|
|
bus_last = &bus->devices;
|
689 |
|
|
max = bus->secondary;
|
690 |
|
|
for (devfn = 0; devfn < 0xff; ++devfn) {
|
691 |
|
|
if (PCI_FUNC(devfn) && !is_multi) {
|
692 |
|
|
/* not a multi-function device */
|
693 |
|
|
continue;
|
694 |
|
|
}
|
695 |
|
|
if (pcibios_read_config_byte(bus->number, devfn, PCI_HEADER_TYPE, &hdr_type))
|
696 |
|
|
continue;
|
697 |
|
|
if (!PCI_FUNC(devfn))
|
698 |
|
|
is_multi = hdr_type & 0x80;
|
699 |
|
|
|
700 |
|
|
if (pcibios_read_config_dword(bus->number, devfn, PCI_VENDOR_ID, &l) ||
|
701 |
|
|
/* some broken boards return 0 if a slot is empty: */
|
702 |
|
|
l == 0xffffffff || l == 0x00000000 || l == 0x0000ffff || l == 0xffff0000) {
|
703 |
|
|
is_multi = 0;
|
704 |
|
|
continue;
|
705 |
|
|
}
|
706 |
|
|
|
707 |
|
|
dev = salloc(sizeof(*dev));
|
708 |
|
|
dev->bus = bus;
|
709 |
|
|
dev->devfn = devfn;
|
710 |
|
|
dev->vendor = l & 0xffff;
|
711 |
|
|
dev->device = (l >> 16) & 0xffff;
|
712 |
|
|
|
713 |
|
|
pcibios_read_config_dword(bus->number, devfn,
|
714 |
|
|
PCI_CLASS_REVISION, &class);
|
715 |
|
|
class >>= 8; /* upper 3 bytes */
|
716 |
|
|
dev->class = class;
|
717 |
|
|
class >>= 8;
|
718 |
|
|
dev->hdr_type = hdr_type;
|
719 |
|
|
|
720 |
|
|
switch (hdr_type & 0x7f) { /* header type */
|
721 |
|
|
case PCI_HEADER_TYPE_NORMAL: /* standard header */
|
722 |
|
|
if (class == PCI_CLASS_BRIDGE_PCI)
|
723 |
|
|
goto bad;
|
724 |
|
|
/*
|
725 |
|
|
* If the card generates interrupts, read IRQ number
|
726 |
|
|
* (some architectures change it during pcibios_fixup())
|
727 |
|
|
*/
|
728 |
|
|
pcibios_read_config_byte(bus->number, dev->devfn, PCI_INTERRUPT_PIN, &irq);
|
729 |
|
|
if (irq)
|
730 |
|
|
pcibios_read_config_byte(bus->number, dev->devfn, PCI_INTERRUPT_LINE, &irq);
|
731 |
|
|
dev->irq = irq;
|
732 |
|
|
/*
|
733 |
|
|
* read base address registers, again pcibios_fixup() can
|
734 |
|
|
* tweak these
|
735 |
|
|
*/
|
736 |
|
|
pci_read_bases(dev, 6);
|
737 |
|
|
pcibios_read_config_dword(bus->number, devfn, PCI_ROM_ADDRESS, &l);
|
738 |
|
|
dev->rom_address = (l == 0xffffffff) ? 0 : l;
|
739 |
|
|
break;
|
740 |
|
|
case PCI_HEADER_TYPE_BRIDGE: /* bridge header */
|
741 |
|
|
if (class != PCI_CLASS_BRIDGE_PCI)
|
742 |
|
|
goto bad;
|
743 |
|
|
pci_read_bases(dev, 2);
|
744 |
|
|
pcibios_read_config_dword(bus->number, devfn, PCI_ROM_ADDRESS1, &l);
|
745 |
|
|
dev->rom_address = (l == 0xffffffff) ? 0 : l;
|
746 |
|
|
break;
|
747 |
|
|
case PCI_HEADER_TYPE_CARDBUS: /* CardBus bridge header */
|
748 |
|
|
if (class != PCI_CLASS_BRIDGE_CARDBUS)
|
749 |
|
|
goto bad;
|
750 |
|
|
pci_read_bases(dev, 1);
|
751 |
|
|
break;
|
752 |
|
|
default: /* unknown header */
|
753 |
|
|
bad:
|
754 |
|
|
printk("PCI device with unknown "
|
755 |
|
|
"header type %d ignored.\n",
|
756 |
|
|
hdr_type&0x7f);
|
757 |
|
|
continue;
|
758 |
|
|
}
|
759 |
|
|
|
760 |
|
|
/*
|
761 |
|
|
* Put it into the global PCI device chain. It's used to
|
762 |
|
|
* find devices once everything is set up.
|
763 |
|
|
*/
|
764 |
|
|
*pci->last_dev_p = dev;
|
765 |
|
|
pci->last_dev_p = &dev->next;
|
766 |
|
|
|
767 |
|
|
/*
|
768 |
|
|
* Now insert it into the list of devices held
|
769 |
|
|
* by the parent bus.
|
770 |
|
|
*/
|
771 |
|
|
*bus_last = dev;
|
772 |
|
|
bus_last = &dev->sibling;
|
773 |
|
|
|
774 |
|
|
}
|
775 |
|
|
|
776 |
|
|
/*
|
777 |
|
|
* After performing arch-dependent fixup of the bus, look behind
|
778 |
|
|
* all PCI-to-PCI bridges on this bus.
|
779 |
|
|
*/
|
780 |
|
|
for(dev=bus->devices; dev; dev=dev->sibling)
|
781 |
|
|
/*
|
782 |
|
|
* If it's a bridge, scan the bus behind it.
|
783 |
|
|
*/
|
784 |
|
|
if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
|
785 |
|
|
unsigned int buses;
|
786 |
|
|
unsigned int devfn = dev->devfn;
|
787 |
|
|
unsigned short cr;
|
788 |
|
|
|
789 |
|
|
/*
|
790 |
|
|
* Insert it into the tree of buses.
|
791 |
|
|
*/
|
792 |
|
|
child = salloc(sizeof(*child));
|
793 |
|
|
child->next = bus->children;
|
794 |
|
|
bus->children = child;
|
795 |
|
|
child->self = dev;
|
796 |
|
|
child->parent = bus;
|
797 |
|
|
|
798 |
|
|
/*
|
799 |
|
|
* Set up the primary, secondary and subordinate
|
800 |
|
|
* bus numbers.
|
801 |
|
|
*/
|
802 |
|
|
child->number = child->secondary = ++max;
|
803 |
|
|
child->primary = bus->secondary;
|
804 |
|
|
child->subordinate = 0xff;
|
805 |
|
|
/*
|
806 |
|
|
* Clear all status bits and turn off memory,
|
807 |
|
|
* I/O and master enables.
|
808 |
|
|
*/
|
809 |
|
|
pcibios_read_config_word(bus->number, devfn, PCI_COMMAND, &cr);
|
810 |
|
|
pcibios_write_config_word(bus->number, devfn, PCI_COMMAND, 0x0000);
|
811 |
|
|
pcibios_write_config_word(bus->number, devfn, PCI_STATUS, 0xffff);
|
812 |
|
|
/*
|
813 |
|
|
* Read the existing primary/secondary/subordinate bus
|
814 |
|
|
* number configuration to determine if the PCI bridge
|
815 |
|
|
* has already been configured by the system. If so,
|
816 |
|
|
* do not modify the configuration, merely note it.
|
817 |
|
|
*/
|
818 |
|
|
pcibios_read_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, &buses);
|
819 |
|
|
if ((buses & 0xFFFFFF) != 0)
|
820 |
|
|
{
|
821 |
|
|
unsigned int cmax;
|
822 |
|
|
|
823 |
|
|
child->primary = buses & 0xFF;
|
824 |
|
|
child->secondary = (buses >> 8) & 0xFF;
|
825 |
|
|
child->subordinate = (buses >> 16) & 0xFF;
|
826 |
|
|
child->number = child->secondary;
|
827 |
|
|
cmax = pci_scan_bus(child);
|
828 |
|
|
if (cmax > max) max = cmax;
|
829 |
|
|
}
|
830 |
|
|
else
|
831 |
|
|
{
|
832 |
|
|
/*
|
833 |
|
|
* Configure the bus numbers for this bridge:
|
834 |
|
|
*/
|
835 |
|
|
buses &= 0xff000000;
|
836 |
|
|
buses |=
|
837 |
|
|
(((unsigned int)(child->primary) << 0) |
|
838 |
|
|
((unsigned int)(child->secondary) << 8) |
|
839 |
|
|
((unsigned int)(child->subordinate) << 16));
|
840 |
|
|
pcibios_write_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, buses);
|
841 |
|
|
/*
|
842 |
|
|
* Now we can scan all subordinate buses:
|
843 |
|
|
*/
|
844 |
|
|
max = pci_scan_bus(child);
|
845 |
|
|
/*
|
846 |
|
|
* Set the subordinate bus number to its real
|
847 |
|
|
* value:
|
848 |
|
|
*/
|
849 |
|
|
child->subordinate = max;
|
850 |
|
|
buses = (buses & 0xff00ffff)
|
851 |
|
|
| ((unsigned int)(child->subordinate) << 16);
|
852 |
|
|
pcibios_write_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, buses);
|
853 |
|
|
}
|
854 |
|
|
pcibios_write_config_word(bus->number, devfn, PCI_COMMAND, cr);
|
855 |
|
|
}
|
856 |
|
|
|
857 |
|
|
/*
|
858 |
|
|
* We've scanned the bus and so we know all about what's on
|
859 |
|
|
* the other side of any bridges that may be on this bus plus
|
860 |
|
|
* any devices.
|
861 |
|
|
*
|
862 |
|
|
* Return how far we've got finding sub-buses.
|
863 |
|
|
*/
|
864 |
|
|
return max;
|
865 |
|
|
}
|
866 |
|
|
|
867 |
|
|
void
|
868 |
|
|
pci_fixup(void) {
|
869 |
|
|
struct pci_dev *p;
|
870 |
|
|
struct pci_bus *bus;
|
871 |
|
|
for (bus = &pci_root; bus; bus=bus->next) {
|
872 |
|
|
|
873 |
|
|
for (p=bus->devices; p; p=p->sibling) {
|
874 |
|
|
}
|
875 |
|
|
}
|
876 |
|
|
}
|
877 |
|
|
|
878 |
|
|
void pci_init(void) {
|
879 |
|
|
PPC_DEVICE *hostbridge;
|
880 |
|
|
|
881 |
|
|
if (pci->last_dev_p) {
|
882 |
|
|
printk("Two or more calls to pci_init!\n");
|
883 |
|
|
return;
|
884 |
|
|
}
|
885 |
|
|
pci->last_dev_p = &(bd->pci_devices);
|
886 |
|
|
hostbridge=residual_find_device(PROCESSORDEVICE, NULL,
|
887 |
|
|
BridgeController,
|
888 |
|
|
PCIBridge, -1, 0);
|
889 |
|
|
if (hostbridge) {
|
890 |
|
|
if (hostbridge->DeviceId.Interface==PCIBridgeIndirect) {
|
891 |
|
|
bd->pci_functions=&indirect_functions;
|
892 |
|
|
/* Should be extracted from residual data,
|
893 |
|
|
* indeed MPC106 in CHRP mode is different,
|
894 |
|
|
* but we should not use residual data in
|
895 |
|
|
* this case anyway.
|
896 |
|
|
*/
|
897 |
|
|
pci->config_addr = ((volatile u_int *)
|
898 |
|
|
(ptr_mem_map->io_base+0xcf8));
|
899 |
|
|
pci->config_data = ptr_mem_map->io_base+0xcfc;
|
900 |
|
|
} else if(hostbridge->DeviceId.Interface==PCIBridgeDirect) {
|
901 |
|
|
bd->pci_functions=&direct_functions;
|
902 |
|
|
pci->config_data=(u_char *) 0x80800000;
|
903 |
|
|
} else {
|
904 |
|
|
}
|
905 |
|
|
} else {
|
906 |
|
|
/* Let us try by experimentation at our own risk! */
|
907 |
|
|
u_int id0;
|
908 |
|
|
bd->pci_functions = &direct_functions;
|
909 |
|
|
/* On all direct bridges I know the host bridge itself
|
910 |
|
|
* appears as device 0 function 0.
|
911 |
|
|
*/
|
912 |
|
|
pcibios_read_config_dword(0, 0, PCI_VENDOR_ID, &id0);
|
913 |
|
|
if (id0==~0U) {
|
914 |
|
|
bd->pci_functions = &indirect_functions;
|
915 |
|
|
pci->config_addr = ((volatile u_int *)
|
916 |
|
|
(ptr_mem_map->io_base+0xcf8));
|
917 |
|
|
pci->config_data = ptr_mem_map->io_base+0xcfc;
|
918 |
|
|
}
|
919 |
|
|
/* Here we should check that the host bridge is actually
|
920 |
|
|
* present, but if it not, we are in such a desperate
|
921 |
|
|
* situation, that we probably can't even tell it.
|
922 |
|
|
*/
|
923 |
|
|
}
|
924 |
|
|
/* Now build a small database of all found PCI devices */
|
925 |
|
|
printk("\nPCI: Probing PCI hardware\n");
|
926 |
|
|
pci_root.subordinate=pci_scan_bus(&pci_root);
|
927 |
|
|
print_pci_resources("Configurable PCI resources:\n");
|
928 |
|
|
reconfigure_pci();
|
929 |
|
|
print_pci_resources("Allocated PCI resources:\n");
|
930 |
|
|
}
|
931 |
|
|
|