📄 pci.c
字号:
pb->bus = pbus; pb->slot = pslot; return 0; }#if 0 printk("no match\n");#endif } } } return -1;}void FixupPCI( const struct _int_map *bspmap, int (*swizzler)(int,int) ){ unsigned char cvalue; unsigned16 devid; int ismatch, i, j, pbus, pslot, int_pin, int_name; /* ** If the device has a non-zero INTERRUPT_PIN, assign a bsp-specific ** INTERRUPT_NAME if one isn't already in place. Then, drivers can ** trivially use INTERRUPT_NAME to hook up with devices. */ for(pbus=0; pbus< BusCountPCI(); pbus++) { for(pslot=0; pslot< PCI_MAX_DEVICES; pslot++) { pci_read_config_word(pbus, pslot, 0, PCI_DEVICE_ID, &devid); if( devid == 0xffff ) continue; /* got a device */ pci_read_config_byte( pbus, pslot, 0, PCI_INTERRUPT_PIN, &cvalue); int_pin = cvalue; pci_read_config_byte( pbus, pslot, 0, PCI_INTERRUPT_LINE, &cvalue); int_name = cvalue;/* printk("pci : device %d:%02x devid %04x, intpin %d, intline %d\n", pbus, pslot, devid, int_pin, int_name ); */ if( int_pin > 0 ) { ismatch = 0; /* ** first run thru the bspmap table and see if we have an explicit configuration */ for(i=0; bspmap[i].bus > -1; i++) { if( bspmap[i].bus == pbus && bspmap[i].slot == pslot ) { ismatch = -1; /* we have a record in the table that gives specific * pins and interrupts for devices in this slot */ if( int_name == 255 ) { /* find the vector associated with whatever pin the device gives us */ for( int_name=-1, j=0; bspmap[i].pin_route[j].pin > -1; j++ ) { if( bspmap[i].pin_route[j].pin == int_pin ) { int_name = bspmap[i].pin_route[j].int_name[0]; break; } } if( int_name == -1 ) { printk("pci : Unable to resolve device %d:%d w/ swizzled int pin %d to an interrupt_line.\n", pbus, pslot, int_pin ); } else { PRINT_MSG(); pci_write_config_byte(pbus,pslot,0,PCI_INTERRUPT_LINE,(cvalue= int_name, cvalue)); } } else { test_intname( &bspmap[i],pbus,pslot,int_pin,int_name); } break; } } if( !ismatch ) { /* ** no match, which means we're on a bus someplace. Work ** backwards from it to one of our defined busses, ** swizzling thru each bridge on the way. */ /* keep pbus, pslot pointed to the device being configured while we track down the bridges using tbus,tslot. We keep searching the routing table because we may end up finding our bridge in it */ int tbus= pbus, tslot= pslot; for(;;) { for(i=0; bspmap[i].bus > -1; i++) { if( bspmap[i].bus == tbus && (bspmap[i].slot == tslot || bspmap[i].slot == -1) ) { ismatch = -1; /* found a record for this bus, so swizzle the * int_pin which we then use to find the * interrupt_name. */ if( int_name == 255 ) { /* ** FIXME. I can't believe this little hack ** is right. It does not yield an error in ** convienently simple situations. */ if( tbus ) int_pin = (*swizzler)(tslot,int_pin); /* ** int_pin points to the interrupt channel ** this card ends up delivering interrupts ** on. Find the int_name servicing it. */ for( int_name=-1, j=0; bspmap[i].pin_route[j].pin > -1; j++ ) { if( bspmap[i].pin_route[j].pin == int_pin ) { int_name = bspmap[i].pin_route[j].int_name[0]; break; } } if( int_name == -1 ) { printk("pci : Unable to resolve device %d:%d w/ swizzled int pin %d to an interrupt_line.\n", pbus, pslot, int_pin ); } else { PRINT_MSG(); pci_write_config_byte(pbus,pslot,0,PCI_INTERRUPT_LINE,(cvalue= int_name, cvalue)); } } else { test_intname(&bspmap[i],pbus,pslot,int_pin,int_name); } goto donesearch; } } if( !ismatch ) { struct pcibridge pb; /* ** Haven't found our bus in the int map, so work ** upwards thru the bridges till we find it. */ if( FindPCIbridge( tbus, &pb )== 0 ) { int_pin = (*swizzler)(tslot,int_pin); /* our next bridge up is on pb.bus, pb.slot- now ** instead of pointing to the device we're ** trying to configure, we move from bridge to ** bridge. */ tbus = pb.bus; tslot = pb.slot; } else { printk("pci : No bridge from bus %d towards root found\n", tbus ); goto donesearch; } } } } donesearch: if( !ismatch && int_pin != 0 && int_name == 255 ) { printk("pci : Unable to match device %d:%d with an int routing table entry\n", pbus, pslot ); } } } }}/* * This routine determines the maximum bus number in the system */void InitializePCI(){ extern void detect_host_bridge(); unsigned char ucSlotNumber, ucFnNumber, ucNumFuncs; unsigned char ucHeader; unsigned char ucMaxSubordinate; unsigned int ulClass, ulDeviceID; detect_host_bridge(); /* * Scan PCI bus 0 looking for PCI-PCI bridges */ for(ucSlotNumber=0;ucSlotNumber<PCI_MAX_DEVICES;ucSlotNumber++) { (void)pci_read_config_dword(0, ucSlotNumber, 0, PCI_VENDOR_ID, &ulDeviceID); if(ulDeviceID==PCI_INVALID_VENDORDEVICEID) { /* * This slot is empty */ continue; } (void)pci_read_config_byte(0, ucSlotNumber, 0, PCI_HEADER_TYPE, &ucHeader); if(ucHeader&PCI_MULTI_FUNCTION) { ucNumFuncs=PCI_MAX_FUNCTIONS; } else { ucNumFuncs=1; } for(ucFnNumber=0;ucFnNumber<ucNumFuncs;ucFnNumber++) { (void)pci_read_config_dword(0, ucSlotNumber, ucFnNumber, PCI_VENDOR_ID, &ulDeviceID); if(ulDeviceID==PCI_INVALID_VENDORDEVICEID) { /* * This slot/function is empty */ continue; } /* * This slot/function has a device fitted. */ (void)pci_read_config_dword(0, ucSlotNumber, ucFnNumber, PCI_CLASS_REVISION, &ulClass); ulClass >>= 16; if (ulClass == PCI_CLASS_BRIDGE_PCI) { /* * We have found a PCI-PCI bridge */ (void)pci_read_config_byte(0, ucSlotNumber, ucFnNumber, PCI_SUBORDINATE_BUS, &ucMaxSubordinate); if(ucMaxSubordinate>ucMaxPCIBus) { ucMaxPCIBus=ucMaxSubordinate; } } } }}/* * Return the number of PCI busses in the system */unsigned char BusCountPCI(){ return(ucMaxPCIBus+1);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -