mirror of
https://github.com/ipxe/ipxe
synced 2025-12-23 21:41:43 +03:00
Restructured PCI subsystem to fit the new device model.
Generic PCI code now handles 64-bit BARs correctly when setting "membase"; drivers should need to call pci_bar_start() only if they want to use BARs other than the first memory or I/O BAR. Split rarely-used PCI functions out into pciextra.c. Core PCI code is now 662 bytes (down from 1308 bytes in Etherboot 5.4). 284 bytes of this saving comes from the pci/pciextra split. Cosmetic changes to lots of drivers (e.g. vendor_id->vendor in order to match the names used in Linux).
This commit is contained in:
79
src/drivers/bus/pciextra.c
Normal file
79
src/drivers/bus/pciextra.c
Normal file
@@ -0,0 +1,79 @@
|
||||
#include <stdint.h>
|
||||
#include <gpxe/pci.h>
|
||||
|
||||
/**
|
||||
* Look for a PCI capability
|
||||
*
|
||||
* @v pci PCI device to query
|
||||
* @v cap Capability code
|
||||
* @ret address Address of capability, or 0 if not found
|
||||
*
|
||||
* Determine whether or not a device supports a given PCI capability.
|
||||
* Returns the address of the requested capability structure within
|
||||
* the device's PCI configuration space, or 0 if the device does not
|
||||
* support it.
|
||||
*/
|
||||
int pci_find_capability ( struct pci_device *pci, int cap ) {
|
||||
uint16_t status;
|
||||
uint8_t pos, id;
|
||||
uint8_t hdr_type;
|
||||
int ttl = 48;
|
||||
|
||||
pci_read_config_word ( pci, PCI_STATUS, &status );
|
||||
if ( ! ( status & PCI_STATUS_CAP_LIST ) )
|
||||
return 0;
|
||||
|
||||
pci_read_config_byte ( pci, PCI_HEADER_TYPE, &hdr_type );
|
||||
switch ( hdr_type & 0x7F ) {
|
||||
case PCI_HEADER_TYPE_NORMAL:
|
||||
case PCI_HEADER_TYPE_BRIDGE:
|
||||
default:
|
||||
pci_read_config_byte ( pci, PCI_CAPABILITY_LIST, &pos );
|
||||
break;
|
||||
case PCI_HEADER_TYPE_CARDBUS:
|
||||
pci_read_config_byte ( pci, PCI_CB_CAPABILITY_LIST, &pos );
|
||||
break;
|
||||
}
|
||||
while ( ttl-- && pos >= 0x40 ) {
|
||||
pos &= ~3;
|
||||
pci_read_config_byte ( pci, pos + PCI_CAP_LIST_ID, &id );
|
||||
DBG ( "PCI Capability: %d\n", id );
|
||||
if ( id == 0xff )
|
||||
break;
|
||||
if ( id == cap )
|
||||
return pos;
|
||||
pci_read_config_byte ( pci, pos + PCI_CAP_LIST_NEXT, &pos );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the size of a PCI BAR
|
||||
*
|
||||
* @v pci PCI device
|
||||
* @v reg PCI register number
|
||||
* @ret size BAR size
|
||||
*
|
||||
* It should not be necessary for any Etherboot code to call this
|
||||
* function.
|
||||
*/
|
||||
unsigned long pci_bar_size ( struct pci_device *pci, unsigned int reg ) {
|
||||
uint32_t start, size;
|
||||
|
||||
/* Save the original bar */
|
||||
pci_read_config_dword ( pci, reg, &start );
|
||||
/* Compute which bits can be set */
|
||||
pci_write_config_dword ( pci, reg, ~0 );
|
||||
pci_read_config_dword ( pci, reg, &size );
|
||||
/* Restore the original size */
|
||||
pci_write_config_dword ( pci, reg, start );
|
||||
/* Find the significant bits */
|
||||
if ( start & PCI_BASE_ADDRESS_SPACE_IO ) {
|
||||
size &= PCI_BASE_ADDRESS_IO_MASK;
|
||||
} else {
|
||||
size &= PCI_BASE_ADDRESS_MEM_MASK;
|
||||
}
|
||||
/* Find the lowest bit set */
|
||||
size = size & ~( size - 1 );
|
||||
return size;
|
||||
}
|
||||
Reference in New Issue
Block a user