Changeset 12838559 in rtems
- Timestamp:
- 06/13/03 17:40:41 (20 years ago)
- Children:
- 641fb28
- Parents:
- 7a848b40
- Location:
- c/src/lib/libbsp/powerpc/shared
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
c/src/lib/libbsp/powerpc/shared/ChangeLog
r7a848b40 r12838559 1 2003-06-13 Greg Menke <gregory.menke@gsfc.nasa.gov> 2 3 PR 405/bsps 4 * bootloader/pci.c: Added support for configuring devices for pci 5 busses > 0 6 * pci/pci.c, pci/pci.h: Added FixupPCI() to store vectors in the 7 INTERRUPT_LINE register of pci devices any # of hops away 8 from the host processor. 9 * motorola/motorola.c, motorola/motorola.h: Added interrupt 10 routing tables in support of FixupPCI. This is board-specific, 11 each board will have to supply information for FixupPCI() to do 12 anything for it. 13 * startup/bspstart.c: Extended bat2 to cover entire PCI address space. 14 * irq/irq.c, irq/irq.h: Added support for shared interrupts. 15 Existing single hander vectors are undisturbed, a new function 16 added to allow adding/removing handlers from a vector. 17 1 18 2003-06-13 Till Straumann <strauman@slac.stanford.edu> 2 19 -
c/src/lib/libbsp/powerpc/shared/bootloader/README
r7a848b40 r12838559 40 40 41 41 42 ************************************************** 43 2003/5/7, Greg Menke, gregory.menke@gsfc.nasa.gov 44 45 Reworked the pci bus 0 initialization a little and added support for 46 configuring an arbitrary number of other busses & their respective 47 bridges. Also added support for configuring IO ranges below 0x10000, 48 which I think is reasonable given this is a PowerPC bsp. 49 -
c/src/lib/libbsp/powerpc/shared/bootloader/pci.c
r7a848b40 r12838559 23 23 #include "pci.h" 24 24 #include <libcpu/io.h> 25 #include <libcpu/page.h> 25 26 #include <bsp/consoleIo.h> 27 28 26 29 27 30 typedef unsigned int u32; … … 35 38 36 39 typedef struct _pci_resource { 37 38 39 40 41 42 43 40 struct _pci_resource *next; 41 struct pci_dev *dev; 42 u_long base; /* will be 64 bits on 64 bits machines */ 43 u_long size; 44 u_char type; /* 1 is I/O else low order 4 bits of the memory type */ 45 u_char reg; /* Register # in conf space header */ 46 u_short cmd; /* Original cmd byte */ 44 47 } pci_resource; 45 48 46 49 typedef struct _pci_area { 47 48 49 50 51 50 struct _pci_area *next; 51 u_long start; 52 u_long end; 53 struct pci_bus *bus; 54 u_int flags; 52 55 } pci_area; 53 56 54 57 typedef struct _pci_area_head { 55 56 57 58 pci_area *head; 59 u_long mask; 60 int high; /* To allocate from top */ 58 61 } pci_area_head; 59 62 … … 63 66 64 67 struct _pci_private { 65 66 67 68 69 70 68 volatile u_int * config_addr; 69 volatile u_char * config_data; 70 struct pci_dev **last_dev_p; 71 struct pci_bus pci_root; 72 pci_resource *resources; 73 pci_area_head io, mem; 71 74 72 75 } pci_private = { 73 74 75 76 77 78 76 config_addr: NULL, 77 config_data: (volatile u_char *) 0x80800000, 78 last_dev_p: NULL, 79 resources: NULL, 80 io: {NULL, 0xfff, 0}, 81 mem: {NULL, 0xfffff, 0} 79 82 }; 80 83 … … 93 96 static void 94 97 print_pci_resources(const char *s) { 95 pci_resource *p; 96 printk("%s", s); 97 for (p=pci->resources; p; p=p->next) { 98 printk(" %p:%p %06x %08lx %08lx %d\n", 99 p, p->next, 100 (p->dev->devfn<<8)+(p->dev->bus->number<<16) 101 +0x10+p->reg*4, 102 p->base, 103 p->size, 104 p->type); 105 } 98 pci_resource *p; 99 printk("%s", s); 100 for (p=pci->resources; p; p=p->next) { 101 /* 102 printk(" %p:%p %06x %08lx %08lx %d\n", 103 p, p->next, 104 (p->dev->devfn<<8)+(p->dev->bus->number<<16) 105 +0x10+p->reg*4, 106 p->base, 107 p->size, 108 p->type); 109 */ 110 111 printk(" %p:%p %d:%02x (%04x:%04x) %08lx %08lx %d\n", 112 p, p->next, 113 p->dev->bus->number, PCI_SLOT(p->dev->devfn), 114 p->dev->vendor, p->dev->device, 115 p->base, 116 p->size, 117 p->type); 118 119 } 106 120 } 107 121 108 122 static void 109 123 print_pci_area(pci_area *p) { 110 111 112 113 124 for (; p; p=p->next) { 125 printk(" %p:%p %p %08lx %08lx\n", 126 p, p->next, p->bus, p->start, p->end); 127 } 114 128 } 115 129 116 130 static void 117 131 print_pci_areas(const char *s) { 118 119 120 121 132 printk("%s PCI I/O areas:\n",s); 133 print_pci_area(pci->io.head); 134 printk(" PCI memory areas:\n"); 135 print_pci_area(pci->mem.head); 122 136 } 123 137 #else … … 133 147 134 148 struct blacklist_entry { 135 136 137 149 u_short vendor, device; 150 u_char reg; 151 u_long actual_size; 138 152 }; 139 153 … … 142 156 143 157 static struct blacklist_entry blacklist[] = { 144 145 158 BLACKLIST(S3, TRIO, 0, 0x04000000), 159 {0xffff, 0, 0, 0} 146 160 }; 147 161 … … 157 171 PCI_AREA_MEMORY)) 158 172 173 174 159 175 static int insert_before(pci_resource *e, pci_resource *t) { 160 if (e->dev->bus->number != t->dev->bus->number) 161 return e->dev->bus->number > t->dev->bus->number; 162 if (AREA(e) != AREA(t)) return AREA(e)<AREA(t); 163 return (e->size > t->size); 164 } 176 if (e->dev->bus->number != t->dev->bus->number) 177 return e->dev->bus->number > t->dev->bus->number; 178 if (AREA(e) != AREA(t)) return AREA(e)<AREA(t); 179 return (e->size > t->size); 180 } 181 182 183 184 165 185 166 186 static void insert_resource(pci_resource *r) { 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 187 struct blacklist_entry *b; 188 pci_resource *p; 189 if (!r) return; 190 191 /* First fixup in case we have a blacklist entry. Note that this 192 * may temporarily leave a resource in an inconsistent state: with 193 * (base & (size-1)) !=0. This is harmless. 194 */ 195 for (b=blacklist; b->vendor!=0xffff; b++) { 196 if ((r->dev->vendor==b->vendor) && 197 (r->dev->device==b->device) && 198 (r->reg==b->reg)) { 199 r->size=b->actual_size; 200 break; 201 } 202 } 183 203 184 /* Motorola NT firmware does not configure pci devices which are not 185 * required for booting, others do. For now: 186 * - allocated devices in the ISA range (64kB I/O, 16Mb memory) 187 * but non zero base registers are left as is. 188 * - all other registers, whether already allocated or not, are 189 * reallocated unless they require an inordinate amount of 190 * resources (>256 Mb for memory >64kB for I/O). These 191 * devices with too large mapping requirements are simply ignored 192 * and their bases are set to 0. This should disable the 193 * corresponding decoders according to the PCI specification. 194 * Many devices are buggy in this respect, however, but the 195 * limits have hopefully been set high enough to avoid problems. 196 */ 197 198 if ((r->type==PCI_BASE_ADDRESS_SPACE_IO) 199 ? (r->base && r->base <0x10000) 200 : (r->base && r->base <0x1000000)) { 201 sfree(r); 202 return; 203 } 204 205 if ((r->type==PCI_BASE_ADDRESS_SPACE_IO) 206 ? (r->size >= 0x10000) 207 : (r->size >= 0x10000000)) { 208 r->size = 0; 209 r->base = 0; 210 } 211 212 /* Now insert into the list sorting by 213 * 1) decreasing bus number 214 * 2) space: prefetchable memory, non-prefetchable and finally I/O 215 * 3) decreasing size 216 */ 217 if (!pci->resources || insert_before(r, pci->resources)) { 218 r->next = pci->resources; 219 pci->resources=r; 220 } else { 221 for (p=pci->resources; p->next; p=p->next) { 222 if (insert_before(r, p->next)) break; 223 } 224 r->next=p->next; 225 p->next=r; 226 } 227 } 204 /* Motorola NT firmware does not configure pci devices which are not 205 * required for booting, others do. For now: 206 * - allocated devices in the ISA range (64kB I/O, 16Mb memory) 207 * but non zero base registers are left as is. 208 * - all other registers, whether already allocated or not, are 209 * reallocated unless they require an inordinate amount of 210 * resources (>256 Mb for memory >64kB for I/O). These 211 * devices with too large mapping requirements are simply ignored 212 * and their bases are set to 0. This should disable the 213 * corresponding decoders according to the PCI specification. 214 * Many devices are buggy in this respect, however, but the 215 * limits have hopefully been set high enough to avoid problems. 216 */ 217 218 #if 0 219 if ((r->type==PCI_BASE_ADDRESS_SPACE_IO) 220 ? (r->base && r->base <0x10000) 221 : (r->base && r->base <0x1000000)) { 222 sfree(r); 223 return; 224 } 225 #endif 226 227 if ((r->type==PCI_BASE_ADDRESS_SPACE_IO) 228 ? (r->size >= 0x10000) 229 : (r->size >= 0x10000000)) { 230 r->size = 0; 231 r->base = 0; 232 } 233 234 /* Now insert into the list sorting by 235 * 1) decreasing bus number 236 * 2) space: prefetchable memory, non-prefetchable and finally I/O 237 * 3) decreasing size 238 */ 239 if (!pci->resources || insert_before(r, pci->resources)) { 240 r->next = pci->resources; 241 pci->resources=r; 242 } else { 243 for (p=pci->resources; p->next; p=p->next) { 244 if (insert_before(r, p->next)) break; 245 } 246 r->next=p->next; 247 p->next=r; 248 } 249 } 250 251 252 253 228 254 229 255 /* This version only works for bus 0. I don't have any P2P bridges to test … … 235 261 236 262 static u_long find_range(u_char bus, u_char type, 237 pci_resource **first, 238 pci_resource **past, u_int *flags) { 239 pci_resource *p; 240 u_long total=0; 241 u_int fl=0; 242 243 for (p=pci->resources; p; p=p->next) { 244 if ((p->dev->bus->number == bus) && 245 AREA(p)==type) break; 246 } 247 *first = p; 248 for (; p; p=p->next) { 249 if ((p->dev->bus->number != bus) || 250 AREA(p)!=type || p->size == 0) break; 251 total = total+p->size; 252 fl |= 1<<p->type; 253 } 254 *past = p; 255 /* This will be used later to tell whether there are any 32 bit 256 * devices in an area which could be mapped higher than 4Gb 257 * on 64 bits architectures 258 */ 259 *flags = fl; 260 return total; 261 } 263 pci_resource **first, 264 pci_resource **past, u_int *flags) { 265 pci_resource *p; 266 u_long total=0; 267 u_int fl=0; 268 269 for (p=pci->resources; p; p=p->next) 270 { 271 if ((p->dev->bus->number == bus) && 272 AREA(p)==type) break; 273 } 274 275 *first = p; 276 277 for (; p; p=p->next) 278 { 279 if ((p->dev->bus->number != bus) || 280 AREA(p)!=type || p->size == 0) break; 281 total = total+p->size; 282 fl |= 1<<p->type; 283 } 284 285 *past = p; 286 /* This will be used later to tell whether there are any 32 bit 287 * devices in an area which could be mapped higher than 4Gb 288 * on 64 bits architectures 289 */ 290 *flags = fl; 291 return total; 292 } 293 294 295 296 297 262 298 263 299 static inline void init_free_area(pci_area_head *h, u_long start, 264 u_long end, u_int mask, int high) { 265 pci_area *p; 266 p = salloc(sizeof(pci_area)); 267 if (!p) return; 268 h->head = p; 269 p->next = NULL; 270 p->start = (start+mask)&~mask; 271 p->end = (end-mask)|mask; 272 p->bus = NULL; 273 h->mask = mask; 274 h->high = high; 275 } 300 u_long end, u_int mask, int high) { 301 pci_area *p; 302 p = salloc(sizeof(pci_area)); 303 if (!p) return; 304 h->head = p; 305 p->next = NULL; 306 p->start = (start+mask)&~mask; 307 p->end = (end-mask)|mask; 308 p->bus = NULL; 309 h->mask = mask; 310 h->high = high; 311 } 312 313 314 315 316 276 317 277 318 static void insert_area(pci_area_head *h, pci_area *p) { 278 pci_area *q = h->head; 279 if (!p) return; 280 if (q && (q->start< p->start)) { 281 for(;q->next && q->next->start<p->start; q = q->next); 282 if ((q->end >= p->start) || 283 (q->next && p->end>=q->next->start)) { 284 sfree(p); 285 printk("Overlapping pci areas!\n"); 286 return; 287 } 288 p->next = q->next; 289 q->next = p; 290 } else { /* Insert at head */ 291 if (q && (p->end >= q->start)) { 292 sfree(p); 293 printk("Overlapping pci areas!\n"); 294 return; 295 } 296 p->next = q; 297 h->head = p; 298 } 299 } 319 pci_area *q = h->head; 320 if (!p) return; 321 if (q && (q->start< p->start)) { 322 for(;q->next && q->next->start<p->start; q = q->next); 323 if ((q->end >= p->start) || 324 (q->next && p->end>=q->next->start)) { 325 sfree(p); 326 printk("Overlapping pci areas!\n"); 327 return; 328 } 329 p->next = q->next; 330 q->next = p; 331 } else { /* Insert at head */ 332 if (q && (p->end >= q->start)) { 333 sfree(p); 334 printk("Overlapping pci areas!\n"); 335 return; 336 } 337 p->next = q; 338 h->head = p; 339 } 340 } 341 342 343 344 300 345 301 346 static 302 void remove_area(pci_area_head *h, pci_area *p) { 303 pci_area *q = h->head; 304 305 if (!p || !q) return; 306 if (q==p) { 307 h->head = q->next; 308 return; 309 } 310 for(;q && q->next!=p; q=q->next); 311 if (q) q->next=p->next; 312 } 347 void remove_area(pci_area_head *h, pci_area *p) 348 { 349 pci_area *q = h->head; 350 351 if (!p || !q) return; 352 if (q==p) 353 { 354 h->head = q->next; 355 return; 356 } 357 for(;q && q->next!=p; q=q->next); 358 if (q) q->next=p->next; 359 } 360 361 362 363 364 313 365 314 366 static pci_area * alloc_area(pci_area_head *h, struct pci_bus *bus, 315 u_long required, u_long mask, u_int flags) { 316 pci_area *p; 317 pci_area *from, *split, *new; 318 319 required = (required+h->mask) & ~h->mask; 320 for (p=h->head, from=NULL; p; p=p->next) { 321 u_long l1 = ((p->start+required+mask)&~mask)-1; 322 u_long l2 = ((p->start+mask)&~mask)+required-1; 323 /* Allocated areas point to the bus to which they pertain */ 324 if (p->bus) continue; 325 if ((p->end)>=l1 || (p->end)>=l2) from=p; 326 if (from && !h->high) break; 327 } 328 if (!from) return NULL; 329 330 split = salloc(sizeof(pci_area)); 331 new = salloc(sizeof(pci_area)); 332 /* If allocation of new succeeds then allocation of split has 333 * also been successful (given the current mm algorithms) ! 334 */ 335 if (!new) { 336 sfree(split); 337 return NULL; 338 } 339 new->bus = bus; 340 new->flags = flags; 341 /* Now allocate pci_space taking alignment into account ! */ 342 if (h->high) { 343 u_long l1 = ((from->end+1)&~mask)-required; 344 u_long l2 = (from->end+1-required)&~mask; 345 new->start = (l1>l2) ? l1 : l2; 346 split->end = from->end; 347 from->end = new->start-1; 348 split->start = new->start+required; 349 new->end = new->start+required-1; 350 } else { 351 u_long l1 = ((from->start+mask)&~mask)+required-1; 352 u_long l2 = ((from->start+required+mask)&~mask)-1; 353 new->end = (l1<l2) ? l1 : l2; 354 split->start = from->start; 355 from->start = new->end+1; 356 new->start = new->end+1-required; 357 split->end = new->start-1; 358 } 367 u_long required, u_long mask, u_int flags) { 368 pci_area *p; 369 pci_area *from, *split, *new; 370 371 required = (required+h->mask) & ~h->mask; 372 for (p=h->head, from=NULL; p; p=p->next) 373 { 374 u_long l1 = ((p->start+required+mask)&~mask)-1; 375 u_long l2 = ((p->start+mask)&~mask)+required-1; 376 /* Allocated areas point to the bus to which they pertain */ 377 if (p->bus) continue; 378 if ((p->end)>=l1 || (p->end)>=l2) from=p; 379 if (from && !h->high) break; 380 } 381 if (!from) return NULL; 382 383 split = salloc(sizeof(pci_area)); 384 new = salloc(sizeof(pci_area)); 385 /* If allocation of new succeeds then allocation of split has 386 * also been successful (given the current mm algorithms) ! 387 */ 388 if (!new) { 389 sfree(split); 390 return NULL; 391 } 392 new->bus = bus; 393 new->flags = flags; 394 /* Now allocate pci_space taking alignment into account ! */ 395 if (h->high) 396 { 397 u_long l1 = ((from->end+1)&~mask)-required; 398 u_long l2 = (from->end+1-required)&~mask; 399 new->start = (l1>l2) ? l1 : l2; 400 split->end = from->end; 401 from->end = new->start-1; 402 split->start = new->start+required; 403 new->end = new->start+required-1; 404 } 405 else 406 { 407 u_long l1 = ((from->start+mask)&~mask)+required-1; 408 u_long l2 = ((from->start+required+mask)&~mask)-1; 409 new->end = (l1<l2) ? l1 : l2; 410 split->start = from->start; 411 from->start = new->end+1; 412 new->start = new->end+1-required; 413 split->end = new->start-1; 414 } 359 415 360 if (from->end+1 == from->start) remove_area(h, from); 361 if (split->end+1 != split->start) { 362 split->bus = NULL; 363 insert_area(h, split); 364 } else { 365 sfree(split); 366 } 367 insert_area(h, new); 368 print_pci_areas("alloc_area called:\n"); 369 return new; 370 } 416 if (from->end+1 == from->start) remove_area(h, from); 417 if (split->end+1 != split->start) 418 { 419 split->bus = NULL; 420 insert_area(h, split); 421 } 422 else 423 { 424 sfree(split); 425 } 426 insert_area(h, new); 427 print_pci_areas("alloc_area called:\n"); 428 return new; 429 } 430 431 432 433 371 434 372 435 static inline 373 void alloc_space(pci_area *p, pci_resource *r) { 374 if (p->start & (r->size-1)) { 375 r->base = p->end+1-r->size; 376 p->end -= r->size; 377 } else { 378 r->base = p->start; 379 p->start += r->size; 380 } 381 } 382 383 static void reconfigure_bus_space(u_char bus, u_char type, pci_area_head *h) { 384 pci_resource *first, *past, *r; 385 pci_area *area, tmp; 386 u_int flags; 387 u_int required = find_range(bus, type, &first, &past, &flags); 388 389 if (required==0) return; 390 area = alloc_area(h, first->dev->bus, required, first->size-1, flags); 391 if (!area) return; 392 tmp = *area; 393 for (r=first; r!=past; r=r->next) { 394 alloc_space(&tmp, r); 395 } 396 } 436 void alloc_space(pci_area *p, pci_resource *r) 437 { 438 if (p->start & (r->size-1)) { 439 r->base = p->end+1-r->size; 440 p->end -= r->size; 441 } else { 442 r->base = p->start; 443 p->start += r->size; 444 } 445 } 446 447 448 449 450 451 static void reconfigure_bus_space(u_char bus, u_char type, pci_area_head *h) 452 { 453 pci_resource *first, *past, *r; 454 pci_area *area, tmp; 455 u_int flags; 456 u_int required = find_range(bus, type, &first, &past, &flags); 457 458 if (required==0) return; 459 460 area = alloc_area(h, first->dev->bus, required, first->size-1, flags); 461 462 if (!area) return; 463 464 tmp = *area; 465 for (r=first; r!=past; r=r->next) 466 { 467 alloc_space(&tmp, r); 468 } 469 } 470 471 472 473 474 475 476 477 #define BUS0_IO_START 0x10000 478 #define BUS0_IO_END 0x1ffff 479 #define BUS0_MEM_START 0x1000000 480 #define BUS0_MEM_END 0xaffffff 481 482 #define BUSREST_IO_START 0x20000 483 #define BUSREST_IO_END 0x7ffff 484 #define BUSREST_MEM_START 0xb000000 485 #define BUSREST_MEM_END 0x30000000 486 487 488 489 397 490 398 491 static void reconfigure_pci(void) { 399 pci_resource *r; 400 struct pci_dev *dev; 401 /* FIXME: for now memory is relocated from low, it's better 402 * to start from higher addresses. 403 */ 404 init_free_area(&pci->io, 0x10000, 0x7fffff, 0xfff, 0); 405 init_free_area(&pci->mem, 0x1000000, 0x3cffffff, 0xfffff, 0); 406 407 /* First reconfigure the I/O space, this will be more 408 * complex when there is more than 1 bus. And 64 bits 409 * devices are another kind of problems. 410 */ 411 reconfigure_bus_space(0, PCI_AREA_IO, &pci->io); 412 reconfigure_bus_space(0, PCI_AREA_MEMORY, &pci->mem); 413 reconfigure_bus_space(0, PCI_AREA_PREFETCHABLE, &pci->mem); 414 415 /* Now we have to touch the configuration space of all 416 * the devices to remap them better than they are right now. 417 * This is done in 3 steps: 418 * 1) first disable I/O and memory response of all devices 419 * 2) modify the base registers 420 * 3) restore the original PCI_COMMAND register. 421 */ 422 for (r=pci->resources; r; r= r->next) { 423 if (!r->dev->sysdata) { 424 r->dev->sysdata=r; 425 pci_read_config_word(r->dev, PCI_COMMAND, &r->cmd); 426 pci_write_config_word(r->dev, PCI_COMMAND, 427 r->cmd & ~(PCI_COMMAND_IO| 428 PCI_COMMAND_MEMORY)); 429 } 430 } 431 432 for (r=pci->resources; r; r= r->next) { 433 pci_write_config_dword(r->dev, 434 PCI_BASE_ADDRESS_0+(r->reg<<2), 435 r->base); 436 if ((r->type& 437 (PCI_BASE_ADDRESS_SPACE| 438 PCI_BASE_ADDRESS_MEM_TYPE_MASK)) == 439 (PCI_BASE_ADDRESS_SPACE_MEMORY| 440 PCI_BASE_ADDRESS_MEM_TYPE_64)) { 441 pci_write_config_dword(r->dev, 442 PCI_BASE_ADDRESS_1+ 443 (r->reg<<2), 444 0); 445 } 446 } 447 for (dev=bd->pci_devices; dev; dev= dev->next) { 448 if (dev->sysdata) { 449 pci_write_config_word(dev, PCI_COMMAND, 450 ((pci_resource *)dev->sysdata) 451 ->cmd); 452 dev->sysdata=NULL; 453 } 454 } 455 } 492 pci_resource *r; 493 struct pci_dev *dev; 494 495 /* FIXME: for now memory is relocated from low, it's better 496 * to start from higher addresses. 497 */ 498 /* 499 init_free_area(&pci->io, 0x10000, 0x7fffff, 0xfff, 0); 500 init_free_area(&pci->mem, 0x1000000, 0x3cffffff, 0xfffff, 0); 501 */ 502 503 init_free_area(&pci->io, BUS0_IO_START, BUS0_IO_END, 0xfff, 0); 504 init_free_area(&pci->mem, BUS0_MEM_START, BUS0_MEM_END, 0xfffff, 0); 505 506 507 /* First reconfigure the I/O space, this will be more 508 * complex when there is more than 1 bus. And 64 bits 509 * devices are another kind of problems. 510 */ 511 reconfigure_bus_space(0, PCI_AREA_IO, &pci->io); 512 reconfigure_bus_space(0, PCI_AREA_MEMORY, &pci->mem); 513 reconfigure_bus_space(0, PCI_AREA_PREFETCHABLE, &pci->mem); 514 515 /* Now we have to touch the configuration space of all 516 * the devices to remap them better than they are right now. 517 * This is done in 3 steps: 518 * 1) first disable I/O and memory response of all devices 519 * 2) modify the base registers 520 * 3) restore the original PCI_COMMAND register. 521 */ 522 for (r=pci->resources; r; r= r->next) { 523 if (!r->dev->sysdata) { 524 r->dev->sysdata=r; 525 pci_read_config_word(r->dev, PCI_COMMAND, &r->cmd); 526 pci_write_config_word(r->dev, PCI_COMMAND, 527 r->cmd & ~(PCI_COMMAND_IO| 528 PCI_COMMAND_MEMORY)); 529 } 530 } 531 532 for (r=pci->resources; r; r= r->next) { 533 pci_write_config_dword(r->dev, 534 PCI_BASE_ADDRESS_0+(r->reg<<2), 535 r->base); 536 if ((r->type& 537 (PCI_BASE_ADDRESS_SPACE| 538 PCI_BASE_ADDRESS_MEM_TYPE_MASK)) == 539 (PCI_BASE_ADDRESS_SPACE_MEMORY| 540 PCI_BASE_ADDRESS_MEM_TYPE_64)) { 541 pci_write_config_dword(r->dev, 542 PCI_BASE_ADDRESS_1+ 543 (r->reg<<2), 544 0); 545 } 546 } 547 for (dev=bd->pci_devices; dev; dev= dev->next) { 548 if (dev->sysdata) { 549 pci_write_config_word(dev, PCI_COMMAND, 550 ((pci_resource *)dev->sysdata) 551 ->cmd); 552 dev->sysdata=NULL; 553 } 554 } 555 } 556 557 558 559 560 456 561 457 562 static int 458 563 indirect_pci_read_config_byte(unsigned char bus, unsigned char dev_fn, 459 564 unsigned char offset, unsigned char *val) { 460 461 462 463 565 out_be32(pci->config_addr, 566 0x80|(bus<<8)|(dev_fn<<16)|((offset&~3)<<24)); 567 *val=in_8(pci->config_data + (offset&3)); 568 return PCIBIOS_SUCCESSFUL; 464 569 } 465 570 … … 467 572 indirect_pci_read_config_word(unsigned char bus, unsigned char dev_fn, 468 573 unsigned char offset, unsigned short *val) { 469 470 471 472 473 474 574 *val = 0xffff; 575 if (offset&1) return PCIBIOS_BAD_REGISTER_NUMBER; 576 out_be32(pci->config_addr, 577 0x80|(bus<<8)|(dev_fn<<16)|((offset&~3)<<24)); 578 *val=in_le16((volatile u_short *)(pci->config_data + (offset&3))); 579 return PCIBIOS_SUCCESSFUL; 475 580 } 476 581 477 582 static int 478 583 indirect_pci_read_config_dword(unsigned char bus, unsigned char dev_fn, 479 480 481 482 483 484 485 584 unsigned char offset, unsigned int *val) { 585 *val = 0xffffffff; 586 if (offset&3) return PCIBIOS_BAD_REGISTER_NUMBER; 587 out_be32(pci->config_addr, 588 0x80|(bus<<8)|(dev_fn<<16)|(offset<<24)); 589 *val=in_le32((volatile u_int *)pci->config_data); 590 return PCIBIOS_SUCCESSFUL; 486 591 } 487 592 … … 489 594 indirect_pci_write_config_byte(unsigned char bus, unsigned char dev_fn, 490 595 unsigned char offset, unsigned char val) { 491 492 493 494 596 out_be32(pci->config_addr, 597 0x80|(bus<<8)|(dev_fn<<16)|((offset&~3)<<24)); 598 out_8(pci->config_data + (offset&3), val); 599 return PCIBIOS_SUCCESSFUL; 495 600 } 496 601 … … 498 603 indirect_pci_write_config_word(unsigned char bus, unsigned char dev_fn, 499 604 unsigned char offset, unsigned short val) { 500 501 502 503 504 605 if (offset&1) return PCIBIOS_BAD_REGISTER_NUMBER; 606 out_be32(pci->config_addr, 607 0x80|(bus<<8)|(dev_fn<<16)|((offset&~3)<<24)); 608 out_le16((volatile u_short *)(pci->config_data + (offset&3)), val); 609 return PCIBIOS_SUCCESSFUL; 505 610 } 506 611 … … 508 613 indirect_pci_write_config_dword(unsigned char bus, unsigned char dev_fn, 509 614 unsigned char offset, unsigned int val) { 510 511 512 513 514 615 if (offset&3) return PCIBIOS_BAD_REGISTER_NUMBER; 616 out_be32(pci->config_addr, 617 0x80|(bus<<8)|(dev_fn<<16)|(offset<<24)); 618 out_le32((volatile u_int *)pci->config_data, val); 619 return PCIBIOS_SUCCESSFUL; 515 620 } 516 621 517 622 static const struct pci_config_access_functions indirect_functions = { 518 519 520 521 522 523 623 indirect_pci_read_config_byte, 624 indirect_pci_read_config_word, 625 indirect_pci_read_config_dword, 626 indirect_pci_write_config_byte, 627 indirect_pci_write_config_word, 628 indirect_pci_write_config_dword 524 629 }; 525 630 … … 527 632 static int 528 633 direct_pci_read_config_byte(unsigned char bus, unsigned char dev_fn, 529 530 531 532 533 534 535 536 634 unsigned char offset, unsigned char *val) { 635 if (bus != 0 || (1<<PCI_SLOT(dev_fn) & 0xff8007fe)) { 636 *val=0xff; 637 return PCIBIOS_DEVICE_NOT_FOUND; 638 } 639 *val=in_8(pci->config_data + ((1<<PCI_SLOT(dev_fn))&~1) 640 + (PCI_FUNC(dev_fn)<<8) + offset); 641 return PCIBIOS_SUCCESSFUL; 537 642 } 538 643 539 644 static int 540 645 direct_pci_read_config_word(unsigned char bus, unsigned char dev_fn, 541 542 543 544 545 546 547 548 549 550 646 unsigned char offset, unsigned short *val) { 647 *val = 0xffff; 648 if (offset&1) return PCIBIOS_BAD_REGISTER_NUMBER; 649 if (bus != 0 || (1<<PCI_SLOT(dev_fn) & 0xff8007fe)) { 650 return PCIBIOS_DEVICE_NOT_FOUND; 651 } 652 *val=in_le16((volatile u_short *) 653 (pci->config_data + ((1<<PCI_SLOT(dev_fn))&~1) 654 + (PCI_FUNC(dev_fn)<<8) + offset)); 655 return PCIBIOS_SUCCESSFUL; 551 656 } 552 657 553 658 static int 554 659 direct_pci_read_config_dword(unsigned char bus, unsigned char dev_fn, 555 556 557 558 559 560 561 562 563 564 660 unsigned char offset, unsigned int *val) { 661 *val = 0xffffffff; 662 if (offset&3) return PCIBIOS_BAD_REGISTER_NUMBER; 663 if (bus != 0 || (1<<PCI_SLOT(dev_fn) & 0xff8007fe)) { 664 return PCIBIOS_DEVICE_NOT_FOUND; 665 } 666 *val=in_le32((volatile u_int *) 667 (pci->config_data + ((1<<PCI_SLOT(dev_fn))&~1) 668 + (PCI_FUNC(dev_fn)<<8) + offset)); 669 return PCIBIOS_SUCCESSFUL; 565 670 } 566 671 567 672 static int 568 673 direct_pci_write_config_byte(unsigned char bus, unsigned char dev_fn, 569 570 571 572 573 574 575 576 674 unsigned char offset, unsigned char val) { 675 if (bus != 0 || (1<<PCI_SLOT(dev_fn) & 0xff8007fe)) { 676 return PCIBIOS_DEVICE_NOT_FOUND; 677 } 678 out_8(pci->config_data + ((1<<PCI_SLOT(dev_fn))&~1) 679 + (PCI_FUNC(dev_fn)<<8) + offset, 680 val); 681 return PCIBIOS_SUCCESSFUL; 577 682 } 578 683 579 684 static int 580 685 direct_pci_write_config_word(unsigned char bus, unsigned char dev_fn, 581 582 583 584 585 586 587 588 589 590 686 unsigned char offset, unsigned short val) { 687 if (offset&1) return PCIBIOS_BAD_REGISTER_NUMBER; 688 if (bus != 0 || (1<<PCI_SLOT(dev_fn) & 0xff8007fe)) { 689 return PCIBIOS_DEVICE_NOT_FOUND; 690 } 691 out_le16((volatile u_short *) 692 (pci->config_data + ((1<<PCI_SLOT(dev_fn))&~1) 693 + (PCI_FUNC(dev_fn)<<8) + offset), 694 val); 695 return PCIBIOS_SUCCESSFUL; 591 696 } 592 697 593 698 static int 594 699 direct_pci_write_config_dword(unsigned char bus, unsigned char dev_fn, 595 596 597 598 599 600 601 602 603 604 700 unsigned char offset, unsigned int val) { 701 if (offset&3) return PCIBIOS_BAD_REGISTER_NUMBER; 702 if (bus != 0 || (1<<PCI_SLOT(dev_fn) & 0xff8007fe)) { 703 return PCIBIOS_DEVICE_NOT_FOUND; 704 } 705 out_le32((volatile u_int *) 706 (pci->config_data + ((1<<PCI_SLOT(dev_fn))&~1) 707 + (PCI_FUNC(dev_fn)<<8) + offset), 708 val); 709 return PCIBIOS_SUCCESSFUL; 605 710 } 606 711 607 712 static const struct pci_config_access_functions direct_functions = { 608 609 610 611 612 613 713 direct_pci_read_config_byte, 714 direct_pci_read_config_word, 715 direct_pci_read_config_dword, 716 direct_pci_write_config_byte, 717 direct_pci_write_config_word, 718 direct_pci_write_config_dword 614 719 }; 720 721 722 723 615 724 616 725 617 726 void pci_read_bases(struct pci_dev *dev, unsigned int howmany) 618 727 { 619 unsigned int reg, nextreg; 728 unsigned int reg, nextreg; 729 620 730 #define REG (PCI_BASE_ADDRESS_0 + (reg<<2)) 621 u_short cmd; 622 u32 l, ml; 623 pci_read_config_word(dev, PCI_COMMAND, &cmd); 624 625 for(reg=0; reg<howmany; reg=nextreg) { 626 pci_resource *r; 627 nextreg=reg+1; 628 pci_read_config_dword(dev, REG, &l); 731 732 u_short cmd; 733 u32 l, ml; 734 pci_read_config_word(dev, PCI_COMMAND, &cmd); 735 736 for(reg=0; reg<howmany; reg=nextreg) 737 { 738 pci_resource *r; 739 740 nextreg=reg+1; 741 pci_read_config_dword(dev, REG, &l); 629 742 #if 0 630 if (l == 0xffffffff /*AJF || !l*/) continue; 631 #endif 632 /* Note that disabling the memory response of a host bridge 633 * would lose data if a DMA transfer were in progress. In a 634 * bootloader we don't care however. Also we can't print any 635 * message for a while since we might just disable the console. 636 */ 637 pci_write_config_word(dev, PCI_COMMAND, cmd & 638 ~(PCI_COMMAND_IO|PCI_COMMAND_MEMORY)); 639 pci_write_config_dword(dev, REG, ~0); 640 pci_read_config_dword(dev, REG, &ml); 641 pci_write_config_dword(dev, REG, l); 642 643 /* Reenable the device now that we've played with 644 * base registers. 645 */ 646 pci_write_config_word(dev, PCI_COMMAND, cmd); 647 648 /* seems to be an unused entry skip it */ 649 if ( ml == 0 || ml == 0xffffffff ) continue; 650 651 if ((l & 652 (PCI_BASE_ADDRESS_SPACE|PCI_BASE_ADDRESS_MEM_TYPE_MASK)) 653 == (PCI_BASE_ADDRESS_MEM_TYPE_64 654 |PCI_BASE_ADDRESS_SPACE_MEMORY)) { 655 nextreg=reg+2; 656 } 657 dev->base_address[reg] = l; 658 r = salloc(sizeof(pci_resource)); 659 if (!r) { 660 printk("Error allocating pci_resource struct.\n"); 661 continue; 662 } 663 r->dev = dev; 664 r->reg = reg; 665 if ((l&PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) { 666 r->type = l&~PCI_BASE_ADDRESS_IO_MASK; 667 r->base = l&PCI_BASE_ADDRESS_IO_MASK; 668 r->size = ~(ml&PCI_BASE_ADDRESS_IO_MASK)+1; 669 } else { 670 r->type = l&~PCI_BASE_ADDRESS_MEM_MASK; 671 r->base = l&PCI_BASE_ADDRESS_MEM_MASK; 672 r->size = ~(ml&PCI_BASE_ADDRESS_MEM_MASK)+1; 673 } 674 /* Check for the blacklisted entries */ 675 insert_resource(r); 676 } 677 } 743 if (l == 0xffffffff /*AJF || !l*/) continue; 744 #endif 745 /* Note that disabling the memory response of a host bridge 746 * would lose data if a DMA transfer were in progress. In a 747 * bootloader we don't care however. Also we can't print any 748 * message for a while since we might just disable the console. 749 */ 750 pci_write_config_word(dev, PCI_COMMAND, cmd & 751 ~(PCI_COMMAND_IO|PCI_COMMAND_MEMORY)); 752 pci_write_config_dword(dev, REG, ~0); 753 pci_read_config_dword(dev, REG, &ml); 754 pci_write_config_dword(dev, REG, l); 755 756 /* Reenable the device now that we've played with 757 * base registers. 758 */ 759 pci_write_config_word(dev, PCI_COMMAND, cmd); 760 761 /* seems to be an unused entry skip it */ 762 if ( ml == 0 || ml == 0xffffffff ) continue; 763 764 if ((l & 765 (PCI_BASE_ADDRESS_SPACE|PCI_BASE_ADDRESS_MEM_TYPE_MASK)) 766 == (PCI_BASE_ADDRESS_MEM_TYPE_64 767 |PCI_BASE_ADDRESS_SPACE_MEMORY)) { 768 nextreg=reg+2; 769 } 770 dev->base_address[reg] = l; 771 r = salloc(sizeof(pci_resource)); 772 if (!r) { 773 printk("Error allocating pci_resource struct.\n"); 774 continue; 775 } 776 r->dev = dev; 777 r->reg = reg; 778 if ((l&PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) { 779 r->type = l&~PCI_BASE_ADDRESS_IO_MASK; 780 r->base = l&PCI_BASE_ADDRESS_IO_MASK; 781 r->size = ~(ml&PCI_BASE_ADDRESS_IO_MASK)+1; 782 } else { 783 r->type = l&~PCI_BASE_ADDRESS_MEM_MASK; 784 r->base = l&PCI_BASE_ADDRESS_MEM_MASK; 785 r->size = ~(ml&PCI_BASE_ADDRESS_MEM_MASK)+1; 786 } 787 /* Check for the blacklisted entries */ 788 insert_resource(r); 789 } 790 } 791 792 793 794 678 795 679 796 … … 682 799 u_int pci_scan_bus(struct pci_bus *bus) 683 800 { 684 unsigned int devfn, l, max, class; 685 unsigned char irq, hdr_type, is_multi = 0; 686 struct pci_dev *dev, **bus_last; 687 struct pci_bus *child; 688 689 bus_last = &bus->devices; 690 max = bus->secondary; 691 for (devfn = 0; devfn < 0xff; ++devfn) { 692 if (PCI_FUNC(devfn) && !is_multi) { 693 /* not a multi-function device */ 694 continue; 695 } 696 if (pcibios_read_config_byte(bus->number, devfn, PCI_HEADER_TYPE, &hdr_type)) 697 continue; 698 if (!PCI_FUNC(devfn)) 699 is_multi = hdr_type & 0x80; 700 701 if (pcibios_read_config_dword(bus->number, devfn, PCI_VENDOR_ID, &l) || 702 /* some broken boards return 0 if a slot is empty: */ 703 l == 0xffffffff || l == 0x00000000 || l == 0x0000ffff || l == 0xffff0000) { 704 is_multi = 0; 705 continue; 706 } 707 708 dev = salloc(sizeof(*dev)); 709 dev->bus = bus; 710 dev->devfn = devfn; 711 dev->vendor = l & 0xffff; 712 dev->device = (l >> 16) & 0xffff; 713 714 pcibios_read_config_dword(bus->number, devfn, 715 PCI_CLASS_REVISION, &class); 716 class >>= 8; /* upper 3 bytes */ 717 dev->class = class; 718 class >>= 8; 719 dev->hdr_type = hdr_type; 720 721 switch (hdr_type & 0x7f) { /* header type */ 722 case PCI_HEADER_TYPE_NORMAL: /* standard header */ 723 if (class == PCI_CLASS_BRIDGE_PCI) 724 goto bad; 725 /* 726 * If the card generates interrupts, read IRQ number 727 * (some architectures change it during pcibios_fixup()) 728 */ 729 pcibios_read_config_byte(bus->number, dev->devfn, PCI_INTERRUPT_PIN, &irq); 730 if (irq) 731 pcibios_read_config_byte(bus->number, dev->devfn, PCI_INTERRUPT_LINE, &irq); 732 dev->irq = irq; 733 /* 734 * read base address registers, again pcibios_fixup() can 735 * tweak these 736 */ 737 pci_read_bases(dev, 6); 738 pcibios_read_config_dword(bus->number, devfn, PCI_ROM_ADDRESS, &l); 739 dev->rom_address = (l == 0xffffffff) ? 0 : l; 740 break; 741 case PCI_HEADER_TYPE_BRIDGE: /* bridge header */ 742 if (class != PCI_CLASS_BRIDGE_PCI) 743 goto bad; 744 pci_read_bases(dev, 2); 745 pcibios_read_config_dword(bus->number, devfn, PCI_ROM_ADDRESS1, &l); 746 dev->rom_address = (l == 0xffffffff) ? 0 : l; 747 break; 748 case PCI_HEADER_TYPE_CARDBUS: /* CardBus bridge header */ 749 if (class != PCI_CLASS_BRIDGE_CARDBUS) 750 goto bad; 751 pci_read_bases(dev, 1); 752 break; 753 default: /* unknown header */ 754 bad: 755 printk("PCI device with unknown " 756 "header type %d ignored.\n", 757 hdr_type&0x7f); 758 continue; 759 } 760 761 /* 762 * Put it into the global PCI device chain. It's used to 763 * find devices once everything is set up. 764 */ 765 *pci->last_dev_p = dev; 766 pci->last_dev_p = &dev->next; 767 768 /* 769 * Now insert it into the list of devices held 770 * by the parent bus. 771 */ 772 *bus_last = dev; 773 bus_last = &dev->sibling; 774 775 } 776 777 /* 778 * After performing arch-dependent fixup of the bus, look behind 779 * all PCI-to-PCI bridges on this bus. 780 */ 781 for(dev=bus->devices; dev; dev=dev->sibling) 782 /* 783 * If it's a bridge, scan the bus behind it. 784 */ 785 if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { 786 unsigned int buses; 787 unsigned int devfn = dev->devfn; 788 unsigned short cr; 789 790 /* 791 * Insert it into the tree of buses. 792 */ 793 child = salloc(sizeof(*child)); 794 child->next = bus->children; 795 bus->children = child; 796 child->self = dev; 797 child->parent = bus; 798 799 /* 800 * Set up the primary, secondary and subordinate 801 * bus numbers. 802 */ 803 child->number = child->secondary = ++max; 804 child->primary = bus->secondary; 805 child->subordinate = 0xff; 806 /* 807 * Clear all status bits and turn off memory, 808 * I/O and master enables. 809 */ 810 pcibios_read_config_word(bus->number, devfn, PCI_COMMAND, &cr); 811 pcibios_write_config_word(bus->number, devfn, PCI_COMMAND, 0x0000); 812 pcibios_write_config_word(bus->number, devfn, PCI_STATUS, 0xffff); 813 /* 814 * Read the existing primary/secondary/subordinate bus 815 * number configuration to determine if the PCI bridge 816 * has already been configured by the system. If so, 817 * do not modify the configuration, merely note it. 818 */ 819 pcibios_read_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, &buses); 820 if ((buses & 0xFFFFFF) != 0) 821 { 822 unsigned int cmax; 823 824 child->primary = buses & 0xFF; 825 child->secondary = (buses >> 8) & 0xFF; 826 child->subordinate = (buses >> 16) & 0xFF; 827 child->number = child->secondary; 828 cmax = pci_scan_bus(child); 829 if (cmax > max) max = cmax; 830 } 831 else 832 { 833 /* 834 * Configure the bus numbers for this bridge: 835 */ 836 buses &= 0xff000000; 837 buses |= 838 (((unsigned int)(child->primary) << 0) | 839 ((unsigned int)(child->secondary) << 8) | 840 ((unsigned int)(child->subordinate) << 16)); 841 pcibios_write_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, buses); 842 /* 843 * Now we can scan all subordinate buses: 844 */ 845 max = pci_scan_bus(child); 846 /* 847 * Set the subordinate bus number to its real 848 * value: 849 */ 850 child->subordinate = max; 851 buses = (buses & 0xff00ffff) 852 | ((unsigned int)(child->subordinate) << 16); 853 pcibios_write_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, buses); 854 } 855 pcibios_write_config_word(bus->number, devfn, PCI_COMMAND, cr); 856 } 857 858 /* 859 * We've scanned the bus and so we know all about what's on 860 * the other side of any bridges that may be on this bus plus 861 * any devices. 862 * 863 * Return how far we've got finding sub-buses. 864 */ 865 return max; 866 } 801 unsigned int devfn, l, max, class; 802 unsigned char irq, hdr_type, is_multi = 0; 803 struct pci_dev *dev, **bus_last; 804 struct pci_bus *child; 805 806 #if 0 807 printk("scanning pci bus %d\n", bus->number ); 808 #endif 809 810 bus_last = &bus->devices; 811 max = bus->secondary; 812 for (devfn = 0; devfn < 0xff; ++devfn) { 813 if (PCI_FUNC(devfn) && !is_multi) { 814 /* not a multi-function device */ 815 continue; 816 } 817 if (pcibios_read_config_byte(bus->number, devfn, PCI_HEADER_TYPE, &hdr_type)) 818 continue; 819 if (!PCI_FUNC(devfn)) 820 is_multi = hdr_type & 0x80; 821 822 if (pcibios_read_config_dword(bus->number, devfn, PCI_VENDOR_ID, &l) || 823 /* some broken boards return 0 if a slot is empty: */ 824 l == 0xffffffff || l == 0x00000000 || l == 0x0000ffff || l == 0xffff0000) { 825 is_multi = 0; 826 continue; 827 } 828 829 dev = salloc(sizeof(*dev)); 830 dev->bus = bus; 831 dev->devfn = devfn; 832 dev->vendor = l & 0xffff; 833 dev->device = (l >> 16) & 0xffff; 834 835 pcibios_read_config_dword(bus->number, devfn, 836 PCI_CLASS_REVISION, &class); 837 class >>= 8; /* upper 3 bytes */ 838 dev->class = class; 839 class >>= 8; 840 dev->hdr_type = hdr_type; 841 842 switch (hdr_type & 0x7f) { /* header type */ 843 case PCI_HEADER_TYPE_NORMAL: /* standard header */ 844 if (class == PCI_CLASS_BRIDGE_PCI) 845 goto bad; 846 /* 847 * If the card generates interrupts, read IRQ number 848 * (some architectures change it during pcibios_fixup()) 849 */ 850 pcibios_read_config_byte(bus->number, dev->devfn, PCI_INTERRUPT_PIN, &irq); 851 if (irq) 852 pcibios_read_config_byte(bus->number, dev->devfn, PCI_INTERRUPT_LINE, &irq); 853 dev->irq = irq; 854 /* 855 * read base address registers, again pcibios_fixup() can 856 * tweak these 857 */ 858 pci_read_bases(dev, 6); 859 pcibios_read_config_dword(bus->number, devfn, PCI_ROM_ADDRESS, &l); 860 dev->rom_address = (l == 0xffffffff) ? 0 : l; 861 break; 862 case PCI_HEADER_TYPE_BRIDGE: /* bridge header */ 863 if (class != PCI_CLASS_BRIDGE_PCI) 864 goto bad; 865 pci_read_bases(dev, 2); 866 pcibios_read_config_dword(bus->number, devfn, PCI_ROM_ADDRESS1, &l); 867 dev->rom_address = (l == 0xffffffff) ? 0 : l; 868 break; 869 case PCI_HEADER_TYPE_CARDBUS: /* CardBus bridge header */ 870 if (class != PCI_CLASS_BRIDGE_CARDBUS) 871 goto bad; 872 pci_read_bases(dev, 1); 873 break; 874 875 default: /* unknown header */ 876 bad: 877 printk("PCI device with unknown header type %d ignored.\n", 878 hdr_type&0x7f); 879 continue; 880 } 881 882 /* 883 * Put it into the global PCI device chain. It's used to 884 * find devices once everything is set up. 885 */ 886 *pci->last_dev_p = dev; 887 pci->last_dev_p = &dev->next; 888 889 /* 890 * Now insert it into the list of devices held 891 * by the parent bus. 892 */ 893 *bus_last = dev; 894 bus_last = &dev->sibling; 895 896 } 897 898 /* 899 * After performing arch-dependent fixup of the bus, look behind 900 * all PCI-to-PCI bridges on this bus. 901 */ 902 for(dev=bus->devices; dev; dev=dev->sibling) 903 /* 904 * If it's a bridge, scan the bus behind it. 905 */ 906 if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { 907 unsigned int buses; 908 unsigned int devfn = dev->devfn; 909 unsigned short cr; 910 911 /* 912 * Insert it into the tree of buses. 913 */ 914 child = salloc(sizeof(*child)); 915 child->next = bus->children; 916 bus->children = child; 917 child->self = dev; 918 child->parent = bus; 919 920 /* 921 * Set up the primary, secondary and subordinate 922 * bus numbers. 923 */ 924 child->number = child->secondary = ++max; 925 child->primary = bus->secondary; 926 child->subordinate = 0xff; 927 /* 928 * Clear all status bits and turn off memory, 929 * I/O and master enables. 930 */ 931 pcibios_read_config_word(bus->number, devfn, PCI_COMMAND, &cr); 932 pcibios_write_config_word(bus->number, devfn, PCI_COMMAND, 0x0000); 933 pcibios_write_config_word(bus->number, devfn, PCI_STATUS, 0xffff); 934 /* 935 * Read the existing primary/secondary/subordinate bus 936 * number configuration to determine if the PCI bridge 937 * has already been configured by the system. If so, 938 * do not modify the configuration, merely note it. 939 */ 940 pcibios_read_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, &buses); 941 if ((buses & 0xFFFFFF) != 0) 942 { 943 unsigned int cmax; 944 945 child->primary = buses & 0xFF; 946 child->secondary = (buses >> 8) & 0xFF; 947 child->subordinate = (buses >> 16) & 0xFF; 948 child->number = child->secondary; 949 cmax = pci_scan_bus(child); 950 if (cmax > max) max = cmax; 951 } 952 else 953 { 954 /* 955 * Configure the bus numbers for this bridge: 956 */ 957 buses &= 0xff000000; 958 buses |= 959 (((unsigned int)(child->primary) << 0) | 960 ((unsigned int)(child->secondary) << 8) | 961 ((unsigned int)(child->subordinate) << 16)); 962 pcibios_write_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, buses); 963 /* 964 * Now we can scan all subordinate buses: 965 */ 966 max = pci_scan_bus(child); 967 /* 968 * Set the subordinate bus number to its real 969 * value: 970 */ 971 child->subordinate = max; 972 buses = (buses & 0xff00ffff) 973 | ((unsigned int)(child->subordinate) << 16); 974 pcibios_write_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, buses); 975 } 976 pcibios_write_config_word(bus->number, devfn, PCI_COMMAND, cr ); 977 } 978 979 /* 980 * We've scanned the bus and so we know all about what's on 981 * the other side of any bridges that may be on this bus plus 982 * any devices. 983 * 984 * Return how far we've got finding sub-buses. 985 */ 986 return max; 987 } 988 989 990 991 992 993 994 995 996 997 998 #if 0 867 999 868 1000 void 869 pci_fixup(void) { 870 struct pci_dev *p; 871 struct pci_bus *bus; 872 for (bus = &pci_root; bus; bus=bus->next) { 873 874 for (p=bus->devices; p; p=p->sibling) { 875 } 876 } 877 } 878 879 void pci_init(void) { 880 PPC_DEVICE *hostbridge; 881 882 if (pci->last_dev_p) { 883 printk("Two or more calls to pci_init!\n"); 884 return; 885 } 886 pci->last_dev_p = &(bd->pci_devices); 887 hostbridge=residual_find_device(PROCESSORDEVICE, NULL, 888 BridgeController, 889 PCIBridge, -1, 0); 890 if (hostbridge) { 891 if (hostbridge->DeviceId.Interface==PCIBridgeIndirect) { 892 bd->pci_functions=&indirect_functions; 893 /* Should be extracted from residual data, 894 * indeed MPC106 in CHRP mode is different, 895 * but we should not use residual data in 896 * this case anyway. 897 */ 898 pci->config_addr = ((volatile u_int *) 899 (ptr_mem_map->io_base+0xcf8)); 900 pci->config_data = ptr_mem_map->io_base+0xcfc; 901 } else if(hostbridge->DeviceId.Interface==PCIBridgeDirect) { 902 bd->pci_functions=&direct_functions; 903 pci->config_data=(u_char *) 0x80800000; 904 } else { 905 } 906 } else { 907 /* Let us try by experimentation at our own risk! */ 908 u_int id0; 909 bd->pci_functions = &direct_functions; 910 /* On all direct bridges I know the host bridge itself 911 * appears as device 0 function 0. 912 */ 913 pcibios_read_config_dword(0, 0, PCI_VENDOR_ID, &id0); 914 if (id0==~0U) { 915 bd->pci_functions = &indirect_functions; 916 pci->config_addr = ((volatile u_int *) 917 (ptr_mem_map->io_base+0xcf8)); 918 pci->config_data = ptr_mem_map->io_base+0xcfc; 919 } 920 /* Here we should check that the host bridge is actually 921 * present, but if it not, we are in such a desperate 922 * situation, that we probably can't even tell it. 923 */ 924 } 925 /* Now build a small database of all found PCI devices */ 926 printk("\nPCI: Probing PCI hardware\n"); 927 pci_root.subordinate=pci_scan_bus(&pci_root); 928 print_pci_resources("Configurable PCI resources:\n"); 929 reconfigure_pci(); 930 print_pci_resources("Allocated PCI resources:\n"); 931 } 932 1001 pci_fixup(void) 1002 { 1003 struct pci_dev *p; 1004 struct pci_bus *bus; 1005 1006 for (bus = &pci_root; bus; bus=bus->next) 1007 { 1008 for (p=bus->devices; p; p=p->sibling) 1009 { 1010 } 1011 } 1012 } 1013 1014 1015 1016 1017 1018 1019 static void print_pci_info() 1020 { 1021 pci_resource *r; 1022 struct pci_bus *pb = &pci_root; 1023 1024 printk("\n"); 1025 printk("PCI busses:\n"); 1026 1027 for(pb= &pci_root; pb; pb=pb->children ) 1028 { 1029 printk(" number %d, primary %d, secondary %d, subordinate %d\n", 1030 pb->number, 1031 pb->primary, 1032 pb->secondary, 1033 pb->subordinate ); 1034 printk(" bridge; vendor %04x, device %04x\n", 1035 pb->self->vendor, 1036 pb->self->device ); 1037 1038 { 1039 struct pci_dev *pd; 1040 1041 for(pd= pb->devices; pd; pd=pd->sibling ) 1042 { 1043 printk(" vendor %04x, device %04x, irq %d\n", 1044 pd->vendor, 1045 pd->device, 1046 pd->irq ); 1047 1048 } 1049 printk("\n"); 1050 } 1051 1052 } 1053 printk("\n"); 1054 1055 printk("PCI resources:\n"); 1056 for (r=pci->resources; r; r= r->next) 1057 { 1058 printk(" bus %d, vendor %04x, device %04x, base %08x, size %08x, type %d\n", 1059 r->dev->bus->number, 1060 r->dev->vendor, 1061 r->dev->device, 1062 r->base, 1063 r->size, 1064 r->type ); 1065 } 1066 printk("\n"); 1067 1068 return; 1069 } 1070 1071 #endif 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 static struct _addr_start 1085 { 1086 unsigned32 start_pcimem; 1087 unsigned32 start_pciio; 1088 unsigned32 start_prefetch; 1089 } astart; 1090 1091 1092 1093 1094 1095 static pci_resource *enum_device_resources( struct pci_dev *pdev, int i ) 1096 { 1097 pci_resource *r; 1098 1099 for(r= pci->resources; r; r= r->next ) 1100 { 1101 if( r->dev == pdev ) 1102 { 1103 if( i-- == 0 ) break; 1104 } 1105 } 1106 return r; 1107 } 1108 1109 1110 1111 1112 1113 1114 #define MEMORY_IO_GRANULARITY 256 1115 1116 1117 1118 static void recursive_bus_reconfigure( struct pci_bus *pbus ) 1119 { 1120 struct pci_dev *pdev; 1121 struct pci_bus *childbus; 1122 int isroot = 0; 1123 1124 1125 if( !pbus ) 1126 { 1127 /* start with the root bus */ 1128 astart.start_pcimem = BUSREST_MEM_START; 1129 astart.start_pciio = BUSREST_IO_START; 1130 astart.start_prefetch = ((BUSREST_MEM_END >> 16) << 16); 1131 1132 pbus = &pci_root; 1133 isroot = -1; 1134 } 1135 1136 1137 #define WRITE_BRIDGE_IO 1138 #define WRITE_BRIDGE_MEM 1139 #define WRITE_BRIDGE_PF 1140 #define WRITE_BRIDGE_ENABLE 1141 1142 1143 /* 1144 ** Run thru the p2p bridges on this bus and recurse into subordinate busses 1145 */ 1146 for( childbus= pbus->children; childbus; childbus= childbus->next ) 1147 { 1148 pdev= childbus->self; 1149 1150 { 1151 struct _addr_start addrhold; 1152 unsigned8 base8, limit8; 1153 unsigned16 base16, limit16, ubase16, ulimit16; 1154 1155 /* save the base address values */ 1156 memcpy( &addrhold, &astart, sizeof(struct _addr_start)); 1157 1158 recursive_bus_reconfigure( childbus ); 1159 1160 #ifdef PCI_DEBUG 1161 printk("pci: configuring bus %d bridge (%04x:%04x), bus %d : (%d-%d)\n", 1162 pdev->bus->number, 1163 pdev->vendor, 1164 pdev->device, 1165 childbus->primary, 1166 childbus->secondary, 1167 childbus->subordinate ); 1168 #endif 1169 1170 1171 1172 /* 1173 **use the current values & the saved ones to figure out 1174 ** the address spaces for the bridge 1175 */ 1176 1177 if( addrhold.start_pciio == astart.start_pciio ) 1178 { 1179 base8 = limit8 = 0xff; 1180 ubase16 = ulimit16 = 0xffff; 1181 } 1182 else 1183 { 1184 base8 = (unsigned8) ((addrhold.start_pciio >> 8) & 0xf0); 1185 ubase16 = (unsigned16)(addrhold.start_pciio >> 16); 1186 limit8 = (unsigned8) ((astart.start_pciio >> 8 ) & 0xf0); 1187 ulimit16 = (unsigned16)(astart.start_pciio >> 16); 1188 astart.start_pciio += 0x1000; 1189 } 1190 1191 #ifdef PCI_DEBUG 1192 printk("pci: io base %08x limit %08x\n", (base8<<8)+(ubase16<<16), (limit8<<8)+(ulimit16<<16)); 1193 #endif 1194 #ifdef WRITE_BRIDGE_IO 1195 pcibios_write_config_word(pdev->bus->number, pdev->devfn, PCI_IO_BASE_UPPER16, ubase16 ); 1196 pcibios_write_config_byte(pdev->bus->number, pdev->devfn, PCI_IO_BASE, base8 ); 1197 1198 pcibios_write_config_word(pdev->bus->number, pdev->devfn, PCI_IO_LIMIT_UPPER16, ulimit16 ); 1199 pcibios_write_config_byte(pdev->bus->number, pdev->devfn, PCI_IO_LIMIT, limit8 ); 1200 #endif 1201 1202 1203 1204 1205 if( addrhold.start_pcimem == astart.start_pcimem ) 1206 { 1207 limit16 = 0; 1208 base16 = 0xffff; 1209 } 1210 else 1211 { 1212 limit16= (unsigned16)((astart.start_pcimem >> 16) & 0xfff0); 1213 base16 = (unsigned16)((addrhold.start_pcimem >> 16) & 0xfff0); 1214 astart.start_pcimem += 0x100000; 1215 } 1216 #ifdef PCI_DEBUG 1217 printk("pci: memory %04x, limit %04x\n", base16, limit16); 1218 #endif 1219 #ifdef WRITE_BRIDGE_MEM 1220 pcibios_write_config_word(pdev->bus->number, pdev->devfn, PCI_MEMORY_BASE, base16 ); 1221 pcibios_write_config_word(pdev->bus->number, pdev->devfn, PCI_MEMORY_LIMIT, limit16 ); 1222 #endif 1223 1224 1225 1226 if( astart.start_prefetch == addrhold.start_prefetch ) 1227 { 1228 limit16 = 0; 1229 base16 = 0xffff; 1230 } 1231 else 1232 { 1233 limit16= (unsigned16)((addrhold.start_prefetch >> 16) & 0xfff0); 1234 base16 = (unsigned16)((astart.start_prefetch >> 16) & 0xfff0); 1235 astart.start_prefetch -= 0x100000; 1236 } 1237 #ifdef PCI_DEBUG 1238 printk("pci: pf memory %04x, limit %04x\n", base16, limit16); 1239 #endif 1240 #ifdef WRITE_BRIDGE_PF 1241 pcibios_write_config_dword(pdev->bus->number, pdev->devfn, PCI_PREF_BASE_UPPER32, 0); 1242 pcibios_write_config_word(pdev->bus->number, pdev->devfn, PCI_PREF_MEMORY_BASE, base16 ); 1243 pcibios_write_config_dword(pdev->bus->number, pdev->devfn, PCI_PREF_LIMIT_UPPER32, 0); 1244 pcibios_write_config_word(pdev->bus->number, pdev->devfn, PCI_PREF_MEMORY_LIMIT, limit16 ); 1245 1246 #endif 1247 1248 #ifdef WRITE_BRIDGE_ENABLE 1249 pcibios_write_config_word(pdev->bus->number, pdev->devfn, PCI_BRIDGE_CONTROL, (unsigned16)( PCI_BRIDGE_CTL_PARITY | 1250 PCI_BRIDGE_CTL_SERR | 1251 PCI_BRIDGE_CTL_FAST_BACK)); 1252 1253 pcibios_write_config_word(pdev->bus->number, pdev->devfn, PCI_COMMAND, (unsigned16)( PCI_COMMAND_IO | 1254 PCI_COMMAND_MEMORY | 1255 PCI_COMMAND_MASTER | 1256 PCI_COMMAND_PARITY | 1257 PCI_COMMAND_WAIT | 1258 PCI_COMMAND_SERR | 1259 PCI_COMMAND_FAST_BACK )); 1260 #endif 1261 } 1262 } 1263 1264 1265 1266 1267 1268 1269 if( !isroot ) 1270 { 1271 #ifdef PCI_DEBUG 1272 printk("pci: Configuring devices on bus %d\n", pbus->number); 1273 #endif 1274 /* 1275 ** Run thru this bus and set up addresses for all the non-bridge devices 1276 */ 1277 for( pdev = pbus->devices; pdev; pdev= pdev->sibling ) 1278 { 1279 if( (pdev->class >> 8) != PCI_CLASS_BRIDGE_PCI ) 1280 { 1281 pci_resource *r; 1282 int i = 0; 1283 unsigned alloc; 1284 1285 /* enumerate all the resources defined by this device & reserve space 1286 ** for each of their defined regions. 1287 */ 1288 1289 #ifdef PCI_DEBUG 1290 printk("pci: configuring; vendor %04x, device %04x\n", pdev->vendor, pdev->device ); 1291 #endif 1292 1293 while( (r= enum_device_resources( pdev, i++ )) ) 1294 { 1295 if( r->type & PCI_BASE_ADDRESS_MEM_PREFETCH ) 1296 { 1297 /* prefetchable space */ 1298 1299 /* shift base pointer down to an integer multiple of the size of the desired region */ 1300 astart.start_prefetch -= (alloc= ((r->size / PAGE_SIZE) + 1) * PAGE_SIZE); 1301 /* shift base pointer down to an integer multiple of the size of the desired region */ 1302 astart.start_prefetch = (astart.start_prefetch / r->size) * r->size; 1303 1304 r->base = astart.start_prefetch; 1305 #ifdef PCI_DEBUG 1306 printk("pci: pf %08X, size %08X, alloc %08X\n", r->base, r->size, alloc ); 1307 #endif 1308 } 1309 else if( r->type & PCI_BASE_ADDRESS_SPACE_IO ) 1310 { 1311 /* io space */ 1312 1313 /* shift base pointer up to an integer multiple of the size of the desired region */ 1314 if( astart.start_pciio % r->size ) 1315 astart.start_pciio = (((astart.start_pciio / r->size) + 1) * r->size); 1316 1317 r->base = astart.start_pciio; 1318 astart.start_pciio += (alloc= ((r->size / MEMORY_IO_GRANULARITY) + 1) * MEMORY_IO_GRANULARITY); 1319 #ifdef PCI_DEBUG 1320 printk("pci: io %08X, size %08X, alloc %08X\n", r->base, r->size, alloc ); 1321 #endif 1322 } 1323 else 1324 { 1325 /* memory space */ 1326 1327 /* shift base pointer up to an integer multiple of the size of the desired region */ 1328 if( astart.start_pcimem % r->size ) 1329 astart.start_pcimem = (((astart.start_pcimem / r->size) + 1) * r->size); 1330 1331 r->base = astart.start_pcimem; 1332 astart.start_pcimem += (alloc= ((r->size / MEMORY_IO_GRANULARITY) + 1) * MEMORY_IO_GRANULARITY); 1333 #ifdef PCI_DEBUG 1334 printk("pci: mem %08X, size %08X, alloc %08X\n", r->base, r->size, alloc ); 1335 #endif 1336 } 1337 } 1338 1339 } 1340 } 1341 } 1342 1343 } 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 void pci_init(void) 1355 { 1356 PPC_DEVICE *hostbridge; 1357 1358 if (pci->last_dev_p) { 1359 printk("Two or more calls to pci_init!\n"); 1360 return; 1361 } 1362 pci->last_dev_p = &(bd->pci_devices); 1363 hostbridge=residual_find_device(PROCESSORDEVICE, NULL, 1364 BridgeController, 1365 PCIBridge, -1, 0); 1366 if (hostbridge) { 1367 if (hostbridge->DeviceId.Interface==PCIBridgeIndirect) { 1368 bd->pci_functions=&indirect_functions; 1369 /* Should be extracted from residual data, 1370 * indeed MPC106 in CHRP mode is different, 1371 * but we should not use residual data in 1372 * this case anyway. 1373 */ 1374 pci->config_addr = ((volatile u_int *) 1375 (ptr_mem_map->io_base+0xcf8)); 1376 pci->config_data = ptr_mem_map->io_base+0xcfc; 1377 } else if(hostbridge->DeviceId.Interface==PCIBridgeDirect) { 1378 bd->pci_functions=&direct_functions; 1379 pci->config_data=(u_char *) 0x80800000; 1380 } else { 1381 } 1382 } else { 1383 /* Let us try by experimentation at our own risk! */ 1384 u_int id0; 1385 bd->pci_functions = &direct_functions; 1386 /* On all direct bridges I know the host bridge itself 1387 * appears as device 0 function 0. 1388 */ 1389 pcibios_read_config_dword(0, 0, PCI_VENDOR_ID, &id0); 1390 if (id0==~0U) { 1391 bd->pci_functions = &indirect_functions; 1392 pci->config_addr = ((volatile u_int *) 1393 (ptr_mem_map->io_base+0xcf8)); 1394 pci->config_data = ptr_mem_map->io_base+0xcfc; 1395 } 1396 /* Here we should check that the host bridge is actually 1397 * present, but if it not, we are in such a desperate 1398 * situation, that we probably can't even tell it. 1399 */ 1400 } 1401 /* Now build a small database of all found PCI devices */ 1402 printk("\nPCI: Probing PCI hardware\n"); 1403 pci_root.subordinate=pci_scan_bus(&pci_root); 1404 1405 print_pci_resources("Installed PCI resources:\n"); 1406 1407 recursive_bus_reconfigure(NULL); 1408 reconfigure_pci(); 1409 1410 print_pci_resources("Allocated PCI resources:\n"); 1411 } 1412 1413 1414 /* eof */ -
c/src/lib/libbsp/powerpc/shared/irq/irq.c
r7a848b40 r12838559 119 119 } 120 120 121 122 /* 123 * ------------------------ RTEMS Shared Irq Handler Mngt Routines ---------------- 124 */ 125 int BSP_install_rtems_shared_irq_handler (const rtems_irq_connect_data* irq) 126 { 127 unsigned int level; 128 rtems_irq_connect_data* vchain; 129 130 if (!isValidInterrupt(irq->name)) { 131 printk("Invalid interrupt vector %i\n",irq->name); 132 return 0; 133 } 134 if ( (int)rtems_hdl_tbl[irq->name].next_handler == -1 ) { 135 printk("IRQ vector %i already connected to an unshared handler\n",irq->name); 136 return 0; 137 } 138 _CPU_ISR_Disable(level); 139 140 141 vchain = (rtems_irq_connect_data*)malloc(sizeof(rtems_irq_connect_data)); 142 143 /* save off topmost handler */ 144 vchain[0]= rtems_hdl_tbl[irq->name]; 145 146 /* 147 * store the data provided by user 148 */ 149 rtems_hdl_tbl[irq->name] = *irq; 150 151 /* link chain to new topmost handler */ 152 rtems_hdl_tbl[irq->name].next_handler = (void *)vchain; 153 154 155 if (is_isa_irq(irq->name)) { 156 /* 157 * Enable interrupt at PIC level 158 */ 159 BSP_irq_enable_at_i8259s (irq->name); 160 } 161 162 if (is_pci_irq(irq->name)) { 163 /* 164 * Enable interrupt at OPENPIC level 165 */ 166 openpic_enable_irq ((int) irq->name - BSP_PCI_IRQ_LOWEST_OFFSET); 167 } 168 169 if (is_processor_irq(irq->name)) { 170 /* 171 * Enable exception at processor level 172 */ 173 } 174 /* 175 * Enable interrupt on device 176 */ 177 irq->on(irq); 178 179 _CPU_ISR_Enable(level); 180 181 return 1; 182 } 183 184 121 185 /* 122 186 * ------------------------ RTEMS Single Irq Handler Mngt Routines ---------------- … … 148 212 */ 149 213 rtems_hdl_tbl[irq->name] = *irq; 214 rtems_hdl_tbl[irq->name].next_handler = (void *)-1; 150 215 151 216 if (is_isa_irq(irq->name)) { … … 190 255 int BSP_remove_rtems_irq_handler (const rtems_irq_connect_data* irq) 191 256 { 257 rtems_irq_connect_data *pchain= NULL, *vchain = NULL; 192 258 unsigned int level; 193 259 … … 207 273 _CPU_ISR_Disable(level); 208 274 275 if( (int)rtems_hdl_tbl[irq->name].next_handler != -1 ) 276 { 277 int found = 0; 278 279 for( (pchain= NULL, vchain = &rtems_hdl_tbl[irq->name]); 280 (vchain->hdl != default_rtems_entry.hdl); 281 (pchain= vchain, vchain = (rtems_irq_connect_data*)vchain->next_handler) ) 282 { 283 if( vchain->hdl == irq->hdl ) 284 { 285 found= -1; break; 286 } 287 } 288 289 if( !found ) 290 { 291 _CPU_ISR_Enable(level); 292 return 0; 293 } 294 } 295 else 296 { 297 if (rtems_hdl_tbl[irq->name].hdl != irq->hdl) 298 { 299 _CPU_ISR_Enable(level); 300 return 0; 301 } 302 } 303 209 304 if (is_isa_irq(irq->name)) { 210 305 /* … … 233 328 * restore the default irq value 234 329 */ 235 rtems_hdl_tbl[irq->name] = default_rtems_entry; 330 if( !vchain ) 331 { 332 /* single handler vector... */ 333 rtems_hdl_tbl[irq->name] = default_rtems_entry; 334 } 335 else 336 { 337 if( pchain ) 338 { 339 /* non-first handler being removed */ 340 pchain->next_handler = vchain->next_handler; 341 } 342 else 343 { 344 /* first handler isn't malloc'ed, so just overwrite it. Since 345 the contents of vchain are being struct copied, vchain itself 346 goes away */ 347 rtems_hdl_tbl[irq->name]= *vchain; 348 } 349 free(vchain); 350 } 236 351 237 352 _CPU_ISR_Enable(level); … … 266 381 for (i=BSP_ISA_IRQ_LOWEST_OFFSET; i < BSP_ISA_IRQ_LOWEST_OFFSET + BSP_ISA_IRQ_NUMBER; i++) { 267 382 if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) { 268 BSP_irq_enable_at_i8259s (i); 269 rtems_hdl_tbl[i].on(&rtems_hdl_tbl[i]); 383 BSP_irq_enable_at_i8259s (i); 384 385 /* rtems_hdl_tbl[i].on(&rtems_hdl_tbl[i]); */ 386 { 387 rtems_irq_connect_data* vchain; 388 for( vchain = &rtems_hdl_tbl[i]; 389 ((int)vchain != -1 && vchain->hdl != default_rtems_entry.hdl); 390 vchain = (rtems_irq_connect_data*)vchain->next_handler ) 391 { 392 vchain->on(vchain); 393 } 394 } 270 395 } 271 396 else { 272 rtems_hdl_tbl[i].off(&rtems_hdl_tbl[i]); 273 BSP_irq_disable_at_i8259s (i); 397 /* rtems_hdl_tbl[i].off(&rtems_hdl_tbl[i]); */ 398 { 399 rtems_irq_connect_data* vchain; 400 for( vchain = &rtems_hdl_tbl[i]; 401 ((int)vchain != -1 && vchain->hdl != default_rtems_entry.hdl); 402 vchain = (rtems_irq_connect_data*)vchain->next_handler ) 403 { 404 vchain->off(vchain); 405 } 406 } 407 BSP_irq_disable_at_i8259s (i); 274 408 } 275 409 } … … 288 422 internal_config->irqPrioTbl[i]); 289 423 if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) { 290 openpic_enable_irq ((int) i - BSP_PCI_IRQ_LOWEST_OFFSET); 291 rtems_hdl_tbl[i].on(&rtems_hdl_tbl[i]); 424 openpic_enable_irq ((int) i - BSP_PCI_IRQ_LOWEST_OFFSET); 425 /* rtems_hdl_tbl[i].on(&rtems_hdl_tbl[i]); */ 426 { 427 rtems_irq_connect_data* vchain; 428 for( vchain = &rtems_hdl_tbl[i]; 429 ((int)vchain != -1 && vchain->hdl != default_rtems_entry.hdl); 430 vchain = (rtems_irq_connect_data*)vchain->next_handler ) 431 { 432 vchain->on(vchain); 433 } 434 } 435 292 436 } 293 437 else { 294 rtems_hdl_tbl[i].off(&rtems_hdl_tbl[i]); 295 openpic_disable_irq ((int) i - BSP_PCI_IRQ_LOWEST_OFFSET); 438 /* rtems_hdl_tbl[i].off(&rtems_hdl_tbl[i]); */ 439 { 440 rtems_irq_connect_data* vchain; 441 for( vchain = &rtems_hdl_tbl[i]; 442 ((int)vchain != -1 && vchain->hdl != default_rtems_entry.hdl); 443 vchain = (rtems_irq_connect_data*)vchain->next_handler ) 444 { 445 vchain->off(vchain); 446 } 447 } 448 449 openpic_disable_irq ((int) i - BSP_PCI_IRQ_LOWEST_OFFSET); 296 450 } 297 451 } … … 305 459 for (i=BSP_PROCESSOR_IRQ_LOWEST_OFFSET; i < BSP_PROCESSOR_IRQ_LOWEST_OFFSET + BSP_PROCESSOR_IRQ_NUMBER; i++) { 306 460 if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) { 307 rtems_hdl_tbl[i].on(&rtems_hdl_tbl[i]); 461 /* rtems_hdl_tbl[i].on(&rtems_hdl_tbl[i]); */ 462 { 463 rtems_irq_connect_data* vchain; 464 for( vchain = &rtems_hdl_tbl[i]; 465 ((int)vchain != -1 && vchain->hdl != default_rtems_entry.hdl); 466 vchain = (rtems_irq_connect_data*)vchain->next_handler ) 467 { 468 vchain->on(vchain); 469 } 470 } 471 308 472 } 309 473 else { 310 rtems_hdl_tbl[i].off(&rtems_hdl_tbl[i]); 474 /* rtems_hdl_tbl[i].off(&rtems_hdl_tbl[i]); */ 475 { 476 rtems_irq_connect_data* vchain; 477 for( vchain = &rtems_hdl_tbl[i]; 478 ((int)vchain != -1 && vchain->hdl != default_rtems_entry.hdl); 479 vchain = (rtems_irq_connect_data*)vchain->next_handler ) 480 { 481 vchain->off(vchain); 482 } 483 } 484 311 485 } 312 486 } … … 374 548 _CPU_MSR_SET(new_msr); 375 549 376 rtems_hdl_tbl[irq].hdl(); 550 /* rtems_hdl_tbl[irq].hdl(); */ 551 { 552 rtems_irq_connect_data* vchain; 553 for( vchain = &rtems_hdl_tbl[irq]; 554 ((int)vchain != -1 && vchain->hdl != default_rtems_entry.hdl); 555 vchain = (rtems_irq_connect_data*)vchain->next_handler ) 556 { 557 vchain->hdl(); 558 } 559 } 560 377 561 378 562 _CPU_MSR_SET(msr); -
c/src/lib/libbsp/powerpc/shared/irq/irq.h
r7a848b40 r12838559 144 144 145 145 typedef struct __rtems_irq_connect_data__ { 146 /* 147 * IRQ line 148 */ 149 rtems_irq_symbolic_name name; 150 /* 151 * handler. See comment on handler properties below in function prototype. 152 */ 153 rtems_irq_hdl hdl; 154 /* 155 * function for enabling interrupts at device level (ONLY!). 156 * The BSP code will automatically enable it at i8259s level and openpic level. 157 * RATIONALE : anyway such code has to exist in current driver code. 158 * It is usually called immediately AFTER connecting the interrupt handler. 159 * RTEMS may well need such a function when restoring normal interrupt 160 * processing after a debug session. 161 * 162 */ 163 rtems_irq_enable on; 164 /* 165 * function for disabling interrupts at device level (ONLY!). 166 * The code will disable it at i8259s level. RATIONALE : anyway 167 * such code has to exist for clean shutdown. It is usually called 168 * BEFORE disconnecting the interrupt. RTEMS may well need such 169 * a function when disabling normal interrupt processing for 170 * a debug session. May well be a NOP function. 171 */ 172 rtems_irq_disable off; 173 /* 174 * function enabling to know what interrupt may currently occur 175 * if someone manipulates the i8259s interrupt mask without care... 176 */ 177 rtems_irq_is_enabled isOn; 146 /* 147 * IRQ line 148 */ 149 rtems_irq_symbolic_name name; 150 /* 151 * handler. See comment on handler properties below in function prototype. 152 */ 153 rtems_irq_hdl hdl; 154 /* 155 * function for enabling interrupts at device level (ONLY!). 156 * The BSP code will automatically enable it at i8259s level and openpic level. 157 * RATIONALE : anyway such code has to exist in current driver code. 158 * It is usually called immediately AFTER connecting the interrupt handler. 159 * RTEMS may well need such a function when restoring normal interrupt 160 * processing after a debug session. 161 * 162 */ 163 rtems_irq_enable on; 164 /* 165 * function for disabling interrupts at device level (ONLY!). 166 * The code will disable it at i8259s level. RATIONALE : anyway 167 * such code has to exist for clean shutdown. It is usually called 168 * BEFORE disconnecting the interrupt. RTEMS may well need such 169 * a function when disabling normal interrupt processing for 170 * a debug session. May well be a NOP function. 171 */ 172 rtems_irq_disable off; 173 /* 174 * function enabling to know what interrupt may currently occur 175 * if someone manipulates the i8259s interrupt mask without care... 176 */ 177 rtems_irq_is_enabled isOn; 178 /* 179 * Set to -1 for vectors forced to have only 1 handler 180 */ 181 void *next_handler; 182 178 183 }rtems_irq_connect_data; 179 184 … … 277 282 */ 278 283 int BSP_install_rtems_irq_handler (const rtems_irq_connect_data*); 284 int BSP_install_rtems_shared_irq_handler (const rtems_irq_connect_data*); 285 286 #define BSP_SHARED_HANDLER_SUPPORT 1 287 279 288 /* 280 289 * function to get the current RTEMS irq handler for ptr->name. It enables to -
c/src/lib/libbsp/powerpc/shared/motorola/motorola.c
r7a848b40 r12838559 18 18 #include <libcpu/io.h> 19 19 #include <string.h> 20 21 22 /* 23 ** Board-specific table that maps interrupt names to onboard pci 24 ** peripherals as well as local pci busses. This table is used at 25 ** bspstart() to configure the interrupt name & pin for all devices that 26 ** do not have it already specified. If the device is already 27 ** configured, we leave it alone but sanity check & print a warning if 28 ** we don't know about the pin/line the card gives us. 29 ** 30 ** bus = the bus number of the slot/device in question 31 ** 32 ** slot : 33 ** 34 ** If slot != -1, it indicates a device on the given bus in that slot 35 ** is to use one of the listed interrupt names given an interrupt pin. 36 ** 37 ** If slot == -1, it means devices on this bus can occupy any slot- 38 ** and for pci, this means the particular interrupt pin that the 39 ** device signals is therefore dependent on the particular slot. To 40 ** work from the slot to the interrupt pin, the swizzle table is used. 41 ** Once the bus and interrupt pin is known, the correct interrupt name 42 ** can be pulled from the table. The swizzle table relates the 43 ** interrupt pin from the device to the particular interrupt 44 ** controller interrupt pin- so it is quite reasonable for a device on 45 ** bus 1 signalling interrupt pin 1 to show up at the interrupt 46 ** controller as pin 4- this is why the int pin field varies for 47 ** bridged pci busses. 48 ** 49 ** 50 ** opts = bitmap of options that control the configuration of this 51 ** slot/bus. 52 ** 53 ** pin_routes[] = array of pin & vectors that may serve this slot; 54 ** 55 ** pin = the pin # which delivers an interrupt on this route, A=1, 56 ** B=2, C=3, D=4 57 ** 58 ** int_name[4] = an array of up to 4 bsp-specific interrupt name 59 ** that can be used by this route. Unused entries should be -1. 60 ** The array is of primary use for slots that can be vectored thru 61 ** multiple interrupt lines over the interrupt pin supplied by the 62 ** record. If more than one entry is present, the most preferable 63 ** should supplied first. 64 ** 65 */ 66 67 #define NULL_PINMAP {-1,{-1,-1,-1,-1}} 68 #define NULL_INTMAP {-1,-1,-1,{}} 69 70 71 72 static struct _int_map mcp750_intmap[] = { 73 74 { 0, 16, 0, {{1, {5, 19,-1,-1}}, /* pmc slot */ 75 NULL_PINMAP}}, 76 77 { 0, 14, 0, {{1, {10,18,-1,-1}}, /* onboard ethernet */ 78 NULL_PINMAP}}, 79 80 { 1, -1, 0, {{1, {24,-1,-1,-1}}, 81 {2, {25,-1,-1,-1}}, 82 {3, {26,-1,-1,-1}}, 83 {4, {27,-1,-1,-1}}, 84 NULL_PINMAP}}, 85 86 NULL_INTMAP }; 87 88 89 90 91 static struct _int_map mtx603_intmap[] = { 92 93 {0, 14, 0, {{1, {10,16,-1,-1}}, /* onboard ethernet */ 94 NULL_PINMAP}}, 95 96 {0, 12, 0, {{1, {14,18,-1,-1}}, /* onboard scsi */ 97 NULL_PINMAP}}, 98 99 {0, 16, 0, {{1, {25,-1,-1,-1}}, /* pci/pmc slot 1 */ 100 {2, {26,-1,-1,-1}}, 101 {3, {27,-1,-1,-1}}, 102 {4, {28,-1,-1,-1}}, 103 NULL_PINMAP}}, 104 105 {0, 17, 0, {{1, {26,-1,-1,-1}}, /* pci/pmc slot 2 */ 106 {2, {27,-1,-1,-1}}, 107 {3, {28,-1,-1,-1}}, 108 {4, {25,-1,-1,-1}}, 109 NULL_PINMAP}}, 110 111 {0, 18, 0, {{1, {27,-1,-1,-1}}, /* pci slot 3 */ 112 {2, {28,-1,-1,-1}}, 113 {3, {25,-1,-1,-1}}, 114 {4, {26,-1,-1,-1}}, 115 NULL_PINMAP}}, 116 117 NULL_INTMAP }; 118 119 120 121 122 123 124 125 126 /* 127 * This table represents the standard PCI swizzle defined in the 128 * PCI bus specification. Table taken from Linux 2.4.18, prep_pci.c, 129 * the values in this table are interrupt_pin values (1 based). 130 */ 131 static unsigned char prep_pci_intpins[4][4] = 132 { 133 { 1, 2, 3, 4 }, /* Buses 0, 4, 8, ... */ 134 { 2, 3, 4, 1 }, /* Buses 1, 5, 9, ... */ 135 { 3, 4, 1, 2 }, /* Buses 2, 6, 10 ... */ 136 { 4, 1, 2, 3 }, /* Buses 3, 7, 11 ... */ 137 }; 138 139 static int prep_pci_swizzle(int slot, int pin) 140 { 141 return prep_pci_intpins[ slot % 4 ][ pin-1 ]; 142 } 143 144 145 146 147 148 149 150 20 151 21 152 typedef struct { … … 25 156 * 0x200 if this board has a Hawk chip. 26 157 */ 27 int cpu_type; 28 int base_type; 29 const char *name; 158 int cpu_type; 159 int base_type; 160 const char *name; 161 162 struct _int_map *intmap; 163 int (*swizzler)(int, int); 30 164 } mot_info_t; 31 165 32 166 33 167 static const mot_info_t mot_boards[] = { 34 {0x300, 0x00, "MVME 2400" },35 {0x010, 0x00, "Genesis" },36 {0x020, 0x00, "Powerstack (Series E)" },37 {0x040, 0x00, "Blackhawk (Powerstack)" },38 {0x050, 0x00, "Omaha (PowerStack II Pro3000)" },39 {0x060, 0x00, "Utah (Powerstack II Pro4000)" },40 {0x0A0, 0x00, "Powerstack (Series EX)" },41 {0x1E0, 0xE0, "Mesquite cPCI (MCP750)" },42 {0x1E0, 0xE1, "Sitka cPCI (MCPN750)" },43 {0x1E0, 0xE2, "Mesquite cPCI (MCP750) w/ HAC" },44 {0x1E0, 0xF6, "MTX Plus" },45 {0x1E0, 0xF7, "MTX w/o Parallel Port" },46 {0x1E0, 0xF8, "MTX w/ Parallel Port" },47 {0x1E0, 0xF9, "MVME 2300" },48 {0x1E0, 0xFA, "MVME 2300SC/2600" },49 {0x1E0, 0xFB, "MVME 2600 with MVME712M" },50 {0x1E0, 0xFC, "MVME 2600/2700 with MVME761" },51 {0x1E0, 0xFD, "MVME 3600 with MVME712M" },52 {0x1E0, 0xFE, "MVME 3600 with MVME761" },53 {0x1E0, 0xFF, "MVME 1600-001 or 1600-011" },168 {0x300, 0x00, "MVME 2400", NULL, NULL}, 169 {0x010, 0x00, "Genesis", NULL, NULL}, 170 {0x020, 0x00, "Powerstack (Series E)", NULL, NULL}, 171 {0x040, 0x00, "Blackhawk (Powerstack)", NULL, NULL}, 172 {0x050, 0x00, "Omaha (PowerStack II Pro3000)", NULL, NULL}, 173 {0x060, 0x00, "Utah (Powerstack II Pro4000)", NULL, NULL}, 174 {0x0A0, 0x00, "Powerstack (Series EX)", NULL, NULL}, 175 {0x1E0, 0xE0, "Mesquite cPCI (MCP750)", mcp750_intmap, prep_pci_swizzle}, 176 {0x1E0, 0xE1, "Sitka cPCI (MCPN750)", mcp750_intmap, prep_pci_swizzle}, 177 {0x1E0, 0xE2, "Mesquite cPCI (MCP750) w/ HAC", mcp750_intmap, prep_pci_swizzle}, 178 {0x1E0, 0xF6, "MTX Plus", NULL, NULL}, 179 {0x1E0, 0xF7, "MTX w/o Parallel Port", mtx603_intmap, prep_pci_swizzle}, 180 {0x1E0, 0xF8, "MTX w/ Parallel Port", mtx603_intmap, prep_pci_swizzle}, 181 {0x1E0, 0xF9, "MVME 2300", NULL, NULL}, 182 {0x1E0, 0xFA, "MVME 2300SC/2600", NULL, NULL}, 183 {0x1E0, 0xFB, "MVME 2600 with MVME712M", NULL, NULL}, 184 {0x1E0, 0xFC, "MVME 2600/2700 with MVME761", NULL, NULL}, 185 {0x1E0, 0xFD, "MVME 3600 with MVME712M", NULL, NULL}, 186 {0x1E0, 0xFE, "MVME 3600 with MVME761", NULL, NULL}, 187 {0x1E0, 0xFF, "MVME 1600-001 or 1600-011", NULL, NULL}, 54 188 {0x000, 0x00, ""} 55 189 }; 190 191 56 192 57 193 prep_t currentPrepType; … … 115 251 } 116 252 253 117 254 const char* motorolaBoardToString(motorolaBoard board) 118 255 { … … 121 258 } 122 259 260 261 const struct _int_map *motorolaIntMap(motorolaBoard board) 262 { 263 if (board == MOTOROLA_UNKNOWN) return NULL; 264 return mot_boards[board].intmap; 265 } 266 267 268 const void *motorolaIntSwizzle(motorolaBoard board) 269 { 270 if (board == MOTOROLA_UNKNOWN) return NULL; 271 return (void *)mot_boards[board].swizzler; 272 } 273 -
c/src/lib/libbsp/powerpc/shared/motorola/motorola.h
r7a848b40 r12838559 17 17 18 18 #include <bsp/residual.h> 19 #include <bsp/pci.h> 20 21 22 23 24 25 26 19 27 20 28 typedef enum { … … 62 70 extern motorolaBoard currentBoard; 63 71 extern const char* motorolaBoardToString(motorolaBoard); 72 extern const struct _int_map *motorolaIntMap(motorolaBoard board); 73 extern const void *motorolaIntSwizzle(motorolaBoard board); 64 74 65 75 -
c/src/lib/libbsp/powerpc/shared/pci/pci.c
r7a848b40 r12838559 217 217 218 218 219 220 221 222 223 224 225 226 227 228 229 230 #define PRINT_MSG() \ 231 printk("pci : Device %d:%02x routed to interrupt_line %d\n", pbus, pslot, int_name ) 232 233 234 /* 235 ** Validate a test interrupt name and print a warning if its not one of 236 ** the names defined in the routing record. 237 */ 238 static int test_intname( struct _int_map *row, int pbus, int pslot, int int_pin, int int_name ) 239 { 240 int j,k; 241 int _nopin= -1, _noname= -1; 242 243 for(j=0; row->pin_route[j].pin > -1; j++) 244 { 245 if( row->pin_route[j].pin == int_pin ) 246 { 247 _nopin = 0; 248 249 for(k=0; k<4 && row->pin_route[j].int_name[k] > -1; k++ ) 250 { 251 if( row->pin_route[j].int_name[k] == int_name ){ _noname=0; break; } 252 } 253 break; 254 } 255 } 256 257 if( _nopin ) 258 { 259 printk("pci : Device %d:%02x supplied a bogus interrupt_pin %d\n", pbus, pslot, int_pin ); 260 return -1; 261 } 262 else 263 { 264 if( _noname ) 265 printk("pci : Device %d:%02x supplied a suspicious interrupt_line %d, using it anyway\n", pbus, pslot, int_name ); 266 } 267 return 0; 268 } 269 270 271 272 273 274 struct pcibridge 275 { 276 int bus,slot; 277 }; 278 279 280 static int FindPCIbridge( int mybus, struct pcibridge *pb ) 281 { 282 int pbus, pslot; 283 unsigned8 bussec, buspri; 284 unsigned16 devid, vendorid, dclass; 285 286 for(pbus=0; pbus< BusCountPCI(); pbus++) 287 { 288 for(pslot=0; pslot< PCI_MAX_DEVICES; pslot++) 289 { 290 pci_read_config_word(pbus, pslot, 0, PCI_DEVICE_ID, &devid); 291 if( devid == 0xffff ) continue; 292 293 pci_read_config_word(pbus, pslot, 0, PCI_DEVICE_ID, &vendorid); 294 if( vendorid == 0xffff ) continue; 295 296 pci_read_config_word(pbus, pslot, 0, PCI_CLASS_DEVICE, &dclass); 297 298 if( dclass == PCI_CLASS_BRIDGE_PCI ) 299 { 300 pci_read_config_byte(pbus, pslot, 0, PCI_PRIMARY_BUS, &buspri); 301 pci_read_config_byte(pbus, pslot, 0, PCI_SECONDARY_BUS, &bussec); 302 303 #if 0 304 printk("pci : Found bridge at %d:%d, mybus %d, pribus %d, secbus %d ", pbus, pslot, mybus, buspri, bussec ); 305 #endif 306 if( bussec == mybus ) 307 { 308 #if 0 309 printk("match\n"); 310 #endif 311 /* found our nearest bridge going towards the root */ 312 pb->bus = pbus; 313 pb->slot = pslot; 314 315 return 0; 316 } 317 #if 0 318 printk("no match\n"); 319 #endif 320 } 321 322 323 } 324 } 325 return -1; 326 } 327 328 329 330 331 332 333 334 335 void FixupPCI( struct _int_map *bspmap, int (*swizzler)(int,int) ) 336 { 337 unsigned char cvalue; 338 unsigned16 devid; 339 int ismatch, i, j, pbus, pslot, int_pin, int_name; 340 341 /* 342 ** If the device has a non-zero INTERRUPT_PIN, assign a bsp-specific 343 ** INTERRUPT_NAME if one isn't already in place. Then, drivers can 344 ** trivially use INTERRUPT_NAME to hook up with devices. 345 */ 346 347 for(pbus=0; pbus< BusCountPCI(); pbus++) 348 { 349 for(pslot=0; pslot< PCI_MAX_DEVICES; pslot++) 350 { 351 pci_read_config_word(pbus, pslot, 0, PCI_DEVICE_ID, &devid); 352 if( devid == 0xffff ) continue; 353 354 /* got a device */ 355 356 pci_read_config_byte( pbus, pslot, 0, PCI_INTERRUPT_PIN, &cvalue); 357 int_pin = cvalue; 358 359 pci_read_config_byte( pbus, pslot, 0, PCI_INTERRUPT_LINE, &cvalue); 360 int_name = cvalue; 361 362 /* printk("pci : device %d:%02x devid %04x, intpin %d, intline %d\n", pbus, pslot, devid, int_pin, int_name ); */ 363 364 if( int_pin > 0 ) 365 { 366 ismatch = 0; 367 368 /* 369 ** first run thru the bspmap table and see if we have an explicit configuration 370 */ 371 for(i=0; bspmap[i].bus > -1; i++) 372 { 373 if( bspmap[i].bus == pbus && bspmap[i].slot == pslot ) 374 { 375 ismatch = -1; 376 /* we have a record in the table that gives specific 377 * pins and interrupts for devices in this slot */ 378 if( int_name == 255 ) 379 { 380 /* find the vector associated with whatever pin the device gives us */ 381 for( int_name=-1, j=0; bspmap[i].pin_route[j].pin > -1; j++ ) 382 { 383 if( bspmap[i].pin_route[j].pin == int_pin ) 384 { 385 int_name = bspmap[i].pin_route[j].int_name[0]; 386 break; 387 } 388 } 389 if( int_name == -1 ) 390 { 391 printk("pci : Unable to resolve device %d:%d w/ swizzled int pin %i to an interrupt_line.\n", pbus, pslot, int_pin ); 392 } 393 else 394 { 395 PRINT_MSG(); 396 pci_write_config_byte(pbus,pslot,0,PCI_INTERRUPT_LINE,(cvalue= int_name, cvalue)); 397 } 398 } 399 else 400 { 401 test_intname( &bspmap[i],pbus,pslot,int_pin,int_name); 402 } 403 break; 404 } 405 } 406 407 408 if( !ismatch ) 409 { 410 /* 411 ** no match, which means we're on a bus someplace. Work 412 ** backwards from it to one of our defined busses, 413 ** swizzling thru each bridge on the way. 414 */ 415 416 /* keep pbus, pslot pointed to the device being 417 configured while we track down the bridges using 418 tbus,tslot. We keep searching the routing table because 419 we may end up finding our bridge in it */ 420 421 int tbus= pbus, tslot= pslot; 422 423 for(;;) 424 { 425 426 for(i=0; bspmap[i].bus > -1; i++) 427 { 428 if( bspmap[i].bus == tbus && (bspmap[i].slot == tslot || bspmap[i].slot == -1) ) 429 { 430 ismatch = -1; 431 /* found a record for this bus, so swizzle the 432 * int_pin which we then use to find the 433 * interrupt_name. 434 */ 435 436 if( int_name == 255 ) 437 { 438 /* 439 ** FIXME. I can't believe this little hack 440 ** is right. It does not yield an error in 441 ** convienently simple situations. 442 */ 443 if( tbus ) int_pin = (*swizzler)(tslot,int_pin); 444 445 446 /* 447 ** int_pin points to the interrupt channel 448 ** this card ends up delivering interrupts 449 ** on. Find the int_name servicing it. 450 */ 451 for( int_name=-1, j=0; bspmap[i].pin_route[j].pin > -1; j++ ) 452 { 453 if( bspmap[i].pin_route[j].pin == int_pin ) 454 { 455 int_name = bspmap[i].pin_route[j].int_name[0]; 456 break; 457 } 458 } 459 if( int_name == -1 ) 460 { 461 printk("pci : Unable to resolve device %d:%d w/ swizzled int pin %i to an interrupt_line.\n", pbus, pslot, int_pin ); 462 } 463 else 464 { 465 PRINT_MSG(); 466 pci_write_config_byte(pbus,pslot,0,PCI_INTERRUPT_LINE,(cvalue= int_name, cvalue)); 467 } 468 } 469 else 470 { 471 test_intname(&bspmap[i],pbus,pslot,int_pin,int_name); 472 } 473 goto donesearch; 474 } 475 } 476 477 478 if( !ismatch ) 479 { 480 struct pcibridge pb; 481 482 /* 483 ** Haven't found our bus in the int map, so work 484 ** upwards thru the bridges till we find it. 485 */ 486 487 if( FindPCIbridge( tbus, &pb )== 0 ) 488 { 489 int_pin = (*swizzler)(tslot,int_pin); 490 491 /* our next bridge up is on pb.bus, pb.slot- now 492 ** instead of pointing to the device we're 493 ** trying to configure, we move from bridge to 494 ** bridge. 495 */ 496 497 tbus = pb.bus; 498 tslot = pb.slot; 499 } 500 else 501 { 502 printk("pci : No bridge from bus %i towards root found\n", tbus ); 503 goto donesearch; 504 } 505 506 } 507 508 } 509 } 510 donesearch: 511 512 513 if( !ismatch && int_pin != 0 && int_name == 255 ) 514 { 515 printk("pci : Unable to match device %d:%d with an int routing table entry\n", pbus, pslot ); 516 } 517 518 519 } 520 } 521 } 522 } 523 524 525 526 527 528 529 530 531 532 219 533 /* 220 534 * This routine determines the maximum bus number in the system … … 229 543 230 544 detect_host_bridge(); 545 231 546 /* 232 547 * Scan PCI bus 0 looking for PCI-PCI bridges -
c/src/lib/libbsp/powerpc/shared/pci/pci.h
r7a848b40 r12838559 1154 1154 extern void InitializePCI(); 1155 1155 1156 1157 struct _pin_routes 1158 { 1159 int pin, int_name[4]; 1160 }; 1161 struct _int_map 1162 { 1163 int bus, slot, opts; 1164 struct _pin_routes pin_route[5]; 1165 }; 1166 1167 void FixupPCI( struct _int_map *, int (*swizzler)(int,int) ); 1168 1169 1156 1170 /* scan for a specific device */ 1157 1171 /* find a particular PCI device -
c/src/lib/libbsp/powerpc/shared/pci/pcifinddevice.c
r7a848b40 r12838559 38 38 continue; 39 39 #ifdef PCI_DEBUG 40 printk("BSP_pciFindDevice: found 0x%08x at % i/%i/%i\n",d,bus,dev,fun);40 printk("BSP_pciFindDevice: found 0x%08x at %d/%d/%d\n",d,bus,dev,fun); 41 41 #endif 42 42 (void) pci_read_config_word(bus,dev,fun,PCI_VENDOR_ID,&s); -
c/src/lib/libbsp/powerpc/shared/startup/bspstart.c
r7a848b40 r12838559 254 254 */ 255 255 /* T. Straumann: give more PCI address space */ 256 setdbat(2, PCI_MEM_BASE, PCI_MEM_BASE, 0x 10000000, IO_PAGE);256 setdbat(2, PCI_MEM_BASE, PCI_MEM_BASE, 0x30000000, IO_PAGE); 257 257 /* 258 258 * Must have acces to open pic PCI ACK registers … … 301 301 #endif 302 302 InitializePCI(); 303 304 { 305 struct _int_map *bspmap = motorolaIntMap(currentBoard); 306 if( bspmap ) 307 { 308 printk("pci : Configuring interrupt routing for '%s'\n", motorolaBoardToString(currentBoard)); 309 FixupPCI(bspmap, motorolaIntSwizzle(currentBoard) ); 310 } 311 else 312 printk("pci : Interrupt routing not available for this bsp\n"); 313 314 } 315 316 317 303 318 #ifdef SHOW_MORE_INIT_SETTINGS 304 319 printk("Number of PCI buses found is : %d\n", BusCountPCI());
Note: See TracChangeset
for help on using the changeset viewer.