mirror of
https://github.com/ipxe/ipxe
synced 2026-01-21 09:57:23 +03:00
[pci] Use linker tables for runtime selectable PCI APIs
Use the linker table mechanism to enumerate the underlying PCI I/O APIs, to allow PCIAPI_CLOUD to become architecture-independent code. Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
@@ -54,5 +54,4 @@ PROVIDE_PCIAPI_INLINE ( direct, pci_write_config_byte );
|
||||
PROVIDE_PCIAPI_INLINE ( direct, pci_write_config_word );
|
||||
PROVIDE_PCIAPI_INLINE ( direct, pci_write_config_dword );
|
||||
PROVIDE_PCIAPI_INLINE ( direct, pci_ioremap );
|
||||
|
||||
struct pci_api pcidirect_api = PCIAPI_RUNTIME ( direct );
|
||||
PROVIDE_PCIAPI_RUNTIME ( direct, PCIAPI_PRIORITY_DIRECT );
|
||||
|
||||
@@ -11,6 +11,5 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#include <ipxe/pcibios.h>
|
||||
#include <ipxe/pcidirect.h>
|
||||
#include <ipxe/pcicloud.h>
|
||||
|
||||
#endif /* _BITS_PCI_IO_H */
|
||||
|
||||
@@ -155,6 +155,4 @@ PCIAPI_INLINE ( pcbios, pci_ioremap ) ( struct pci_device *pci __unused,
|
||||
return ioremap ( bus_addr, len );
|
||||
}
|
||||
|
||||
extern struct pci_api pcibios_api;
|
||||
|
||||
#endif /* _IPXE_PCIBIOS_H */
|
||||
|
||||
@@ -165,6 +165,4 @@ PCIAPI_INLINE ( direct, pci_ioremap ) ( struct pci_device *pci __unused,
|
||||
return ioremap ( bus_addr, len );
|
||||
}
|
||||
|
||||
extern struct pci_api pcidirect_api;
|
||||
|
||||
#endif /* _PCIDIRECT_H */
|
||||
|
||||
@@ -129,5 +129,4 @@ PROVIDE_PCIAPI_INLINE ( pcbios, pci_write_config_byte );
|
||||
PROVIDE_PCIAPI_INLINE ( pcbios, pci_write_config_word );
|
||||
PROVIDE_PCIAPI_INLINE ( pcbios, pci_write_config_dword );
|
||||
PROVIDE_PCIAPI_INLINE ( pcbios, pci_ioremap );
|
||||
|
||||
struct pci_api pcibios_api = PCIAPI_RUNTIME ( pcbios );
|
||||
PROVIDE_PCIAPI_RUNTIME ( pcbios, PCIAPI_PRIORITY_PCBIOS );
|
||||
|
||||
@@ -4,4 +4,7 @@
|
||||
#ifdef PLATFORM_pcbios
|
||||
#undef PCIAPI_PCBIOS
|
||||
#define PCIAPI_CLOUD
|
||||
#define PCIAPI_RUNTIME_ECAM
|
||||
#define PCIAPI_RUNTIME_PCBIOS
|
||||
#define PCIAPI_RUNTIME_DIRECT
|
||||
#endif
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#include <config/settings.h>
|
||||
#include <config/ioapi.h>
|
||||
|
||||
/** @file
|
||||
*
|
||||
@@ -34,3 +35,13 @@ PROVIDE_REQUIRING_SYMBOL();
|
||||
#ifdef PCI_SETTINGS
|
||||
REQUIRE_OBJECT ( pci_settings );
|
||||
#endif
|
||||
|
||||
#ifdef PCIAPI_RUNTIME_ECAM
|
||||
REQUIRE_OBJECT ( ecam );
|
||||
#endif
|
||||
#ifdef PCIAPI_RUNTIME_PCBIOS
|
||||
REQUIRE_OBJECT ( pcibios );
|
||||
#endif
|
||||
#ifdef PCIAPI_RUNTIME_DIRECT
|
||||
REQUIRE_OBJECT ( pcidirect );
|
||||
#endif
|
||||
|
||||
@@ -279,5 +279,4 @@ PROVIDE_PCIAPI_INLINE ( ecam, pci_write_config_byte );
|
||||
PROVIDE_PCIAPI_INLINE ( ecam, pci_write_config_word );
|
||||
PROVIDE_PCIAPI_INLINE ( ecam, pci_write_config_dword );
|
||||
PROVIDE_PCIAPI_INLINE ( ecam, pci_ioremap );
|
||||
|
||||
struct pci_api ecam_api = PCIAPI_RUNTIME ( ecam );
|
||||
PROVIDE_PCIAPI_RUNTIME ( ecam, PCIAPI_PRIORITY_ECAM );
|
||||
|
||||
@@ -26,9 +26,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <ipxe/pci.h>
|
||||
#include <ipxe/ecam.h>
|
||||
#include <ipxe/pcibios.h>
|
||||
#include <ipxe/pcidirect.h>
|
||||
#include <ipxe/pcicloud.h>
|
||||
|
||||
/** @file
|
||||
@@ -37,11 +34,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
*
|
||||
*/
|
||||
|
||||
/** Underlying PCI configuration space access APIs */
|
||||
static struct pci_api *pcicloud_apis[] = {
|
||||
&ecam_api, &pcibios_api, &pcidirect_api
|
||||
};
|
||||
|
||||
/** Cached PCI configuration space access API */
|
||||
static struct {
|
||||
/** PCI bus:dev.fn address range */
|
||||
@@ -65,17 +57,14 @@ static struct pci_api * pcicloud_find ( uint32_t busdevfn,
|
||||
uint32_t index;
|
||||
uint32_t first;
|
||||
uint32_t last;
|
||||
unsigned int i;
|
||||
|
||||
/* Return empty range on error */
|
||||
range->count = 0;
|
||||
|
||||
/* Try discovery via all known APIs */
|
||||
for ( i = 0 ; i < ( sizeof ( pcicloud_apis ) /
|
||||
sizeof ( pcicloud_apis[0] ) ) ; i++ ) {
|
||||
for_each_table_entry ( api, PCI_APIS ) {
|
||||
|
||||
/* Discover via this API */
|
||||
api = pcicloud_apis[i];
|
||||
api->pci_discover ( busdevfn, &candidate );
|
||||
|
||||
/* Check for a matching or new closest allocation */
|
||||
@@ -135,8 +124,7 @@ static struct pci_api * pcicloud_api ( struct pci_device *pci ) {
|
||||
|
||||
/* Fall back to lowest priority API for any unclaimed gaps in ranges */
|
||||
if ( ! api ) {
|
||||
api = pcicloud_apis[ ( sizeof ( pcicloud_apis ) /
|
||||
sizeof ( pcicloud_apis[0] ) ) - 1 ];
|
||||
api = ( table_end ( PCI_APIS ) - 1 );
|
||||
range->count = ( range->start - pci->busdevfn );
|
||||
range->start = pci->busdevfn;
|
||||
first = range->start;
|
||||
@@ -54,6 +54,4 @@ struct ecam_mapping {
|
||||
int rc;
|
||||
};
|
||||
|
||||
extern struct pci_api ecam_api;
|
||||
|
||||
#endif /* _IPXE_ECAM_H */
|
||||
|
||||
@@ -11,6 +11,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#include <stdint.h>
|
||||
#include <ipxe/api.h>
|
||||
#include <ipxe/tables.h>
|
||||
#include <ipxe/iomap.h>
|
||||
#include <config/ioapi.h>
|
||||
|
||||
@@ -61,6 +62,7 @@ struct pci_range {
|
||||
/* Include all architecture-independent I/O API headers */
|
||||
#include <ipxe/null_pci.h>
|
||||
#include <ipxe/ecam_io.h>
|
||||
#include <ipxe/pcicloud.h>
|
||||
#include <ipxe/efi/efi_pci_api.h>
|
||||
#include <ipxe/linux/linux_pci.h>
|
||||
|
||||
@@ -171,23 +173,45 @@ struct pci_api {
|
||||
typeof ( pci_ioremap ) ( * pci_ioremap );
|
||||
};
|
||||
|
||||
/** Runtime selectable PCI API table */
|
||||
#define PCI_APIS __table ( struct pci_api, "pci_apis" )
|
||||
|
||||
/**
|
||||
* Declare a runtime selectable PCI API
|
||||
*
|
||||
* In the common case of a non-runtime-selectable PCI I/O API, allow
|
||||
* the runtime API code to be garbage-collected at link time to save
|
||||
* space.
|
||||
*/
|
||||
#ifdef PCIAPI_CLOUD
|
||||
#define __pci_api( priority ) __table_entry ( PCI_APIS, priority )
|
||||
#else
|
||||
#define __pci_api( priority )
|
||||
#endif
|
||||
|
||||
/* PCI runtime selectable API priorities */
|
||||
#define PCIAPI_PRIORITY_ECAM 01 /**< ACPI ECAM */
|
||||
#define PCIAPI_PRIORITY_PCBIOS 02 /**< PCI BIOS calls */
|
||||
#define PCIAPI_PRIORITY_DIRECT 03 /**< Direct Type 1 accesses */
|
||||
|
||||
/** Provide a runtime selectable PCI I/O API */
|
||||
#define PCIAPI_RUNTIME( _subsys ) { \
|
||||
.name = #_subsys, \
|
||||
.pci_discover = PCIAPI_INLINE ( _subsys, pci_discover ), \
|
||||
#define PROVIDE_PCIAPI_RUNTIME( subsys, priority ) \
|
||||
struct pci_api pciapi_ ## subsys __pci_api ( priority ) = { \
|
||||
.name = #subsys, \
|
||||
.pci_discover = PCIAPI_INLINE ( subsys, pci_discover ), \
|
||||
.pci_read_config_byte = \
|
||||
PCIAPI_INLINE ( _subsys, pci_read_config_byte ), \
|
||||
PCIAPI_INLINE ( subsys, pci_read_config_byte ), \
|
||||
.pci_read_config_word = \
|
||||
PCIAPI_INLINE ( _subsys, pci_read_config_word ), \
|
||||
PCIAPI_INLINE ( subsys, pci_read_config_word ), \
|
||||
.pci_read_config_dword = \
|
||||
PCIAPI_INLINE ( _subsys, pci_read_config_dword ), \
|
||||
PCIAPI_INLINE ( subsys, pci_read_config_dword ), \
|
||||
.pci_write_config_byte = \
|
||||
PCIAPI_INLINE ( _subsys, pci_write_config_byte ), \
|
||||
PCIAPI_INLINE ( subsys, pci_write_config_byte ), \
|
||||
.pci_write_config_word = \
|
||||
PCIAPI_INLINE ( _subsys, pci_write_config_word ), \
|
||||
PCIAPI_INLINE ( subsys, pci_write_config_word ), \
|
||||
.pci_write_config_dword = \
|
||||
PCIAPI_INLINE ( _subsys, pci_write_config_dword ), \
|
||||
.pci_ioremap = PCIAPI_INLINE ( _subsys, pci_ioremap ), \
|
||||
PCIAPI_INLINE ( subsys, pci_write_config_dword ), \
|
||||
.pci_ioremap = PCIAPI_INLINE ( subsys, pci_ioremap ), \
|
||||
}
|
||||
|
||||
#endif /* _IPXE_PCI_IO_H */
|
||||
|
||||
Reference in New Issue
Block a user