Changeset 12838559 in rtems for c/src/lib/libbsp/powerpc/shared/pci/pci.c
- Timestamp:
- 06/13/03 17:40:41 (20 years ago)
- Children:
- 641fb28
- Parents:
- 7a848b40
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
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
Note: See TracChangeset
for help on using the changeset viewer.