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_word );
|
||||||
PROVIDE_PCIAPI_INLINE ( direct, pci_write_config_dword );
|
PROVIDE_PCIAPI_INLINE ( direct, pci_write_config_dword );
|
||||||
PROVIDE_PCIAPI_INLINE ( direct, pci_ioremap );
|
PROVIDE_PCIAPI_INLINE ( direct, pci_ioremap );
|
||||||
|
PROVIDE_PCIAPI_RUNTIME ( direct, PCIAPI_PRIORITY_DIRECT );
|
||||||
struct pci_api pcidirect_api = PCIAPI_RUNTIME ( direct );
|
|
||||||
|
|||||||
@@ -11,6 +11,5 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
|||||||
|
|
||||||
#include <ipxe/pcibios.h>
|
#include <ipxe/pcibios.h>
|
||||||
#include <ipxe/pcidirect.h>
|
#include <ipxe/pcidirect.h>
|
||||||
#include <ipxe/pcicloud.h>
|
|
||||||
|
|
||||||
#endif /* _BITS_PCI_IO_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 );
|
return ioremap ( bus_addr, len );
|
||||||
}
|
}
|
||||||
|
|
||||||
extern struct pci_api pcibios_api;
|
|
||||||
|
|
||||||
#endif /* _IPXE_PCIBIOS_H */
|
#endif /* _IPXE_PCIBIOS_H */
|
||||||
|
|||||||
@@ -165,6 +165,4 @@ PCIAPI_INLINE ( direct, pci_ioremap ) ( struct pci_device *pci __unused,
|
|||||||
return ioremap ( bus_addr, len );
|
return ioremap ( bus_addr, len );
|
||||||
}
|
}
|
||||||
|
|
||||||
extern struct pci_api pcidirect_api;
|
|
||||||
|
|
||||||
#endif /* _PCIDIRECT_H */
|
#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_word );
|
||||||
PROVIDE_PCIAPI_INLINE ( pcbios, pci_write_config_dword );
|
PROVIDE_PCIAPI_INLINE ( pcbios, pci_write_config_dword );
|
||||||
PROVIDE_PCIAPI_INLINE ( pcbios, pci_ioremap );
|
PROVIDE_PCIAPI_INLINE ( pcbios, pci_ioremap );
|
||||||
|
PROVIDE_PCIAPI_RUNTIME ( pcbios, PCIAPI_PRIORITY_PCBIOS );
|
||||||
struct pci_api pcibios_api = PCIAPI_RUNTIME ( pcbios );
|
|
||||||
|
|||||||
@@ -4,4 +4,7 @@
|
|||||||
#ifdef PLATFORM_pcbios
|
#ifdef PLATFORM_pcbios
|
||||||
#undef PCIAPI_PCBIOS
|
#undef PCIAPI_PCBIOS
|
||||||
#define PCIAPI_CLOUD
|
#define PCIAPI_CLOUD
|
||||||
|
#define PCIAPI_RUNTIME_ECAM
|
||||||
|
#define PCIAPI_RUNTIME_PCBIOS
|
||||||
|
#define PCIAPI_RUNTIME_DIRECT
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||||
|
|
||||||
#include <config/settings.h>
|
#include <config/settings.h>
|
||||||
|
#include <config/ioapi.h>
|
||||||
|
|
||||||
/** @file
|
/** @file
|
||||||
*
|
*
|
||||||
@@ -34,3 +35,13 @@ PROVIDE_REQUIRING_SYMBOL();
|
|||||||
#ifdef PCI_SETTINGS
|
#ifdef PCI_SETTINGS
|
||||||
REQUIRE_OBJECT ( pci_settings );
|
REQUIRE_OBJECT ( pci_settings );
|
||||||
#endif
|
#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_word );
|
||||||
PROVIDE_PCIAPI_INLINE ( ecam, pci_write_config_dword );
|
PROVIDE_PCIAPI_INLINE ( ecam, pci_write_config_dword );
|
||||||
PROVIDE_PCIAPI_INLINE ( ecam, pci_ioremap );
|
PROVIDE_PCIAPI_INLINE ( ecam, pci_ioremap );
|
||||||
|
PROVIDE_PCIAPI_RUNTIME ( ecam, PCIAPI_PRIORITY_ECAM );
|
||||||
struct pci_api ecam_api = PCIAPI_RUNTIME ( ecam );
|
|
||||||
|
|||||||
@@ -26,9 +26,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ipxe/pci.h>
|
#include <ipxe/pci.h>
|
||||||
#include <ipxe/ecam.h>
|
|
||||||
#include <ipxe/pcibios.h>
|
|
||||||
#include <ipxe/pcidirect.h>
|
|
||||||
#include <ipxe/pcicloud.h>
|
#include <ipxe/pcicloud.h>
|
||||||
|
|
||||||
/** @file
|
/** @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 */
|
/** Cached PCI configuration space access API */
|
||||||
static struct {
|
static struct {
|
||||||
/** PCI bus:dev.fn address range */
|
/** PCI bus:dev.fn address range */
|
||||||
@@ -65,17 +57,14 @@ static struct pci_api * pcicloud_find ( uint32_t busdevfn,
|
|||||||
uint32_t index;
|
uint32_t index;
|
||||||
uint32_t first;
|
uint32_t first;
|
||||||
uint32_t last;
|
uint32_t last;
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
/* Return empty range on error */
|
/* Return empty range on error */
|
||||||
range->count = 0;
|
range->count = 0;
|
||||||
|
|
||||||
/* Try discovery via all known APIs */
|
/* Try discovery via all known APIs */
|
||||||
for ( i = 0 ; i < ( sizeof ( pcicloud_apis ) /
|
for_each_table_entry ( api, PCI_APIS ) {
|
||||||
sizeof ( pcicloud_apis[0] ) ) ; i++ ) {
|
|
||||||
|
|
||||||
/* Discover via this API */
|
/* Discover via this API */
|
||||||
api = pcicloud_apis[i];
|
|
||||||
api->pci_discover ( busdevfn, &candidate );
|
api->pci_discover ( busdevfn, &candidate );
|
||||||
|
|
||||||
/* Check for a matching or new closest allocation */
|
/* 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 */
|
/* Fall back to lowest priority API for any unclaimed gaps in ranges */
|
||||||
if ( ! api ) {
|
if ( ! api ) {
|
||||||
api = pcicloud_apis[ ( sizeof ( pcicloud_apis ) /
|
api = ( table_end ( PCI_APIS ) - 1 );
|
||||||
sizeof ( pcicloud_apis[0] ) ) - 1 ];
|
|
||||||
range->count = ( range->start - pci->busdevfn );
|
range->count = ( range->start - pci->busdevfn );
|
||||||
range->start = pci->busdevfn;
|
range->start = pci->busdevfn;
|
||||||
first = range->start;
|
first = range->start;
|
||||||
@@ -54,6 +54,4 @@ struct ecam_mapping {
|
|||||||
int rc;
|
int rc;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct pci_api ecam_api;
|
|
||||||
|
|
||||||
#endif /* _IPXE_ECAM_H */
|
#endif /* _IPXE_ECAM_H */
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <ipxe/api.h>
|
#include <ipxe/api.h>
|
||||||
|
#include <ipxe/tables.h>
|
||||||
#include <ipxe/iomap.h>
|
#include <ipxe/iomap.h>
|
||||||
#include <config/ioapi.h>
|
#include <config/ioapi.h>
|
||||||
|
|
||||||
@@ -61,6 +62,7 @@ struct pci_range {
|
|||||||
/* Include all architecture-independent I/O API headers */
|
/* Include all architecture-independent I/O API headers */
|
||||||
#include <ipxe/null_pci.h>
|
#include <ipxe/null_pci.h>
|
||||||
#include <ipxe/ecam_io.h>
|
#include <ipxe/ecam_io.h>
|
||||||
|
#include <ipxe/pcicloud.h>
|
||||||
#include <ipxe/efi/efi_pci_api.h>
|
#include <ipxe/efi/efi_pci_api.h>
|
||||||
#include <ipxe/linux/linux_pci.h>
|
#include <ipxe/linux/linux_pci.h>
|
||||||
|
|
||||||
@@ -171,23 +173,45 @@ struct pci_api {
|
|||||||
typeof ( pci_ioremap ) ( * pci_ioremap );
|
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 */
|
/** Provide a runtime selectable PCI I/O API */
|
||||||
#define PCIAPI_RUNTIME( _subsys ) { \
|
#define PROVIDE_PCIAPI_RUNTIME( subsys, priority ) \
|
||||||
.name = #_subsys, \
|
struct pci_api pciapi_ ## subsys __pci_api ( priority ) = { \
|
||||||
.pci_discover = PCIAPI_INLINE ( _subsys, pci_discover ), \
|
.name = #subsys, \
|
||||||
.pci_read_config_byte = \
|
.pci_discover = PCIAPI_INLINE ( subsys, pci_discover ), \
|
||||||
PCIAPI_INLINE ( _subsys, pci_read_config_byte ), \
|
.pci_read_config_byte = \
|
||||||
.pci_read_config_word = \
|
PCIAPI_INLINE ( subsys, pci_read_config_byte ), \
|
||||||
PCIAPI_INLINE ( _subsys, pci_read_config_word ), \
|
.pci_read_config_word = \
|
||||||
.pci_read_config_dword = \
|
PCIAPI_INLINE ( subsys, pci_read_config_word ), \
|
||||||
PCIAPI_INLINE ( _subsys, pci_read_config_dword ), \
|
.pci_read_config_dword = \
|
||||||
.pci_write_config_byte = \
|
PCIAPI_INLINE ( subsys, pci_read_config_dword ), \
|
||||||
PCIAPI_INLINE ( _subsys, pci_write_config_byte ), \
|
.pci_write_config_byte = \
|
||||||
.pci_write_config_word = \
|
PCIAPI_INLINE ( subsys, pci_write_config_byte ), \
|
||||||
PCIAPI_INLINE ( _subsys, pci_write_config_word ), \
|
.pci_write_config_word = \
|
||||||
.pci_write_config_dword = \
|
PCIAPI_INLINE ( subsys, pci_write_config_word ), \
|
||||||
PCIAPI_INLINE ( _subsys, pci_write_config_dword ), \
|
.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 */
|
#endif /* _IPXE_PCI_IO_H */
|
||||||
|
|||||||
Reference in New Issue
Block a user