108 lines
2.9 KiB
C++
108 lines
2.9 KiB
C++
|
#include "pci.h"
|
||
|
|
||
|
uint16_t ConfigReadWord (uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset){
|
||
|
uint32_t address;
|
||
|
uint32_t lbus = (uint32_t) bus;
|
||
|
uint32_t lslot = (uint32_t) slot;
|
||
|
uint32_t lfunc = (uint32_t) func;
|
||
|
uint16_t tmp = 0;
|
||
|
|
||
|
/* Create configuration address as per Figure 1 */
|
||
|
address = (uint32_t) ((lbus << 16) | (lslot << 11) | (lfunc << 8) | (offset & 0xFC) |((uint32_t) 0x80000000) );
|
||
|
/*write out the address */
|
||
|
outl(CONFIG_ADDRESS, address);
|
||
|
/* read in the data */
|
||
|
/* (offset & 2 ) * 8 ) = o will choosse the first word of the 32 bits register*/
|
||
|
tmp = (uint16_t)((inl(CONFIG_DATA)) >> ((offset & 2) * 8) & 0xFFFF);
|
||
|
return (tmp);
|
||
|
}
|
||
|
|
||
|
uint16_t CheckVendor (uint8_t bus, uint8_t slot) {
|
||
|
uint16_t vendor, device;
|
||
|
/*
|
||
|
Try and read the first configuration register. Since there ar no
|
||
|
vendors that == 0xFFFF, it must be a non-existent device.
|
||
|
*/
|
||
|
if((vendor = ConfigReadWord(bus, slot, 0,0)) != 0xFFFF) {
|
||
|
device = ConfigReadWord(bus, slot, 0,2);
|
||
|
// Possible read more config values ...
|
||
|
} return (vendor);
|
||
|
}
|
||
|
|
||
|
void checkDevice (uint8_t bus, uint8_t device ) {
|
||
|
uint8_t function = 0;
|
||
|
|
||
|
uint16_t vendorID = CheckVendor(bus, device);
|
||
|
if (vendorID == 0xFFFF) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
checkFunction (bus, device, function );
|
||
|
headerType = getHeaderType(bus, device, function );
|
||
|
if( (headerType & 0x80) != 0) {
|
||
|
/* It is a multi-function device, so check remaining functions */
|
||
|
for (function = 1; function < 8; function++){
|
||
|
if (CheckVendor(bus, device)!= 0xFFFF){
|
||
|
checkFunction(bus, device, function );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
void checkFunction (uint8_t bus, uint8_t device, uint8_t function ){
|
||
|
uint8_t baseClass;
|
||
|
uint8_t subClass;
|
||
|
uint8_t secondaryBus;
|
||
|
|
||
|
baseClass = getBaseClass(bus, device, function);
|
||
|
subClass = getSubClass (bus, device, function );
|
||
|
if ( (baseClass == 0x06) && (subClass == 0x04)){
|
||
|
secondaryBus = getSecondaryBus(bus,device, function);
|
||
|
checkBus(secondaryBus);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
// Brute-force scan
|
||
|
void checkAllBuses (){
|
||
|
uint16_t bus;
|
||
|
uint8_t device;
|
||
|
|
||
|
for(bus = 0; bus < 256; bus++){
|
||
|
for(device = 0; device < 32; device++){
|
||
|
checkDevice(bus,device);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Recursive scan
|
||
|
void checkBus (uint8_t bus){
|
||
|
uint8_t device;
|
||
|
|
||
|
for(device = 0; device < 32; device ++){
|
||
|
checkDevice(bus,device);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void checkAllBuses(){
|
||
|
uint8_t function;
|
||
|
uint8_t bus;
|
||
|
|
||
|
headerType = getHeaderType(0,0,0);
|
||
|
if ( (headerType & 0x80) == 0 ){
|
||
|
/* Single PCI host controller */
|
||
|
checkBus(0);
|
||
|
} else{
|
||
|
/* Multiple PCI host controllers */
|
||
|
for (function = 0; function < 8; function++){
|
||
|
if( CheckVendor(0,0) != 0xFFFF) {
|
||
|
break;
|
||
|
}
|
||
|
bus = function;
|
||
|
checkBus(bus);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|