2
0
mirror of https://github.com/xcat2/xNBA.git synced 2024-11-22 09:31:51 +00:00

[pci] Add pci_find_next() to iterate over existent PCI devices

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown 2013-08-01 16:52:28 +01:00
parent 2b869786c5
commit 6d910559b3
2 changed files with 46 additions and 21 deletions

View File

@ -171,8 +171,20 @@ void adjust_pci_device ( struct pci_device *pci ) {
* @ret rc Return status code
*/
int pci_read_config ( struct pci_device *pci ) {
uint16_t busdevfn;
uint8_t hdrtype;
uint32_t tmp;
/* Ignore all but the first function on non-multifunction devices */
if ( PCI_FUNC ( pci->busdevfn ) != 0 ) {
busdevfn = pci->busdevfn;
pci->busdevfn = PCI_FIRST_FUNC ( pci->busdevfn );
pci_read_config_byte ( pci, PCI_HEADER_TYPE, &hdrtype );
pci->busdevfn = busdevfn;
if ( ! ( hdrtype & 0x80 ) )
return -ENODEV;
}
/* Check for physical device presence */
pci_read_config_dword ( pci, PCI_VENDOR_ID, &tmp );
if ( ( tmp == 0xffffffff ) || ( tmp == 0 ) )
@ -203,6 +215,32 @@ int pci_read_config ( struct pci_device *pci ) {
return 0;
}
/**
* Find next device on PCI bus
*
* @v pci PCI device to fill in
* @v busdevfn Starting bus:dev.fn address
* @ret busdevfn Bus:dev.fn address of next PCI device, or negative error
*/
int pci_find_next ( struct pci_device *pci, unsigned int busdevfn ) {
static unsigned int end;
int rc;
/* Determine number of PCI buses */
if ( ! end )
end = PCI_BUSDEVFN ( pci_num_bus(), 0, 0 );
/* Find next PCI device, if any */
for ( ; busdevfn < end ; busdevfn++ ) {
memset ( pci, 0, sizeof ( *pci ) );
pci_init ( pci, busdevfn );
if ( ( rc = pci_read_config ( pci ) ) == 0 )
return busdevfn;
}
return -ENODEV;
}
/**
* Find driver for PCI device
*
@ -276,14 +314,10 @@ void pci_remove ( struct pci_device *pci ) {
*/
static int pcibus_probe ( struct root_device *rootdev ) {
struct pci_device *pci = NULL;
unsigned int num_bus;
unsigned int busdevfn;
uint8_t hdrtype = 0;
int busdevfn = 0;
int rc;
num_bus = pci_num_bus();
for ( busdevfn = 0 ; busdevfn < PCI_BUSDEVFN ( num_bus, 0, 0 ) ;
busdevfn++ ) {
for ( busdevfn = 0 ; 1 ; busdevfn++ ) {
/* Allocate struct pci_device */
if ( ! pci )
@ -292,22 +326,11 @@ static int pcibus_probe ( struct root_device *rootdev ) {
rc = -ENOMEM;
goto err;
}
memset ( pci, 0, sizeof ( *pci ) );
pci_init ( pci, busdevfn );
/* Skip all but the first function on
* non-multifunction cards
*/
if ( PCI_FUNC ( busdevfn ) == 0 ) {
pci_read_config_byte ( pci, PCI_HEADER_TYPE,
&hdrtype );
} else if ( ! ( hdrtype & 0x80 ) ) {
continue;
}
/* Read device configuration */
if ( ( rc = pci_read_config ( pci ) ) != 0 )
continue;
/* Find next PCI device, if any */
busdevfn = pci_find_next ( pci, busdevfn );
if ( busdevfn < 0 )
break;
/* Look for a driver */
if ( ( rc = pci_find_driver ( pci ) ) != 0 ) {

View File

@ -351,6 +351,7 @@ struct pci_driver {
#define PCI_FUNC( busdevfn ) ( ( (busdevfn) >> 0 ) & 0x07 )
#define PCI_BUSDEVFN( bus, slot, func ) \
( ( (bus) << 8 ) | ( (slot) << 3 ) | ( (func) << 0 ) )
#define PCI_FIRST_FUNC( busdevfn ) ( (busdevfn) & ~0x07 )
#define PCI_BASE_CLASS( class ) ( (class) >> 16 )
#define PCI_SUB_CLASS( class ) ( ( (class) >> 8 ) & 0xff )
@ -385,6 +386,7 @@ extern void adjust_pci_device ( struct pci_device *pci );
extern unsigned long pci_bar_start ( struct pci_device *pci,
unsigned int reg );
extern int pci_read_config ( struct pci_device *pci );
extern int pci_find_next ( struct pci_device *pci, unsigned int busdevfn );
extern int pci_find_driver ( struct pci_device *pci );
extern int pci_probe ( struct pci_device *pci );
extern void pci_remove ( struct pci_device *pci );