#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
*
*/
-/** 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 */
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 */
/* 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;
#include <stdint.h>
#include <ipxe/api.h>
+#include <ipxe/tables.h>
#include <ipxe/iomap.h>
#include <config/ioapi.h>
/* 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>
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 ), \
- .pci_read_config_byte = \
- PCIAPI_INLINE ( _subsys, pci_read_config_byte ), \
- .pci_read_config_word = \
- PCIAPI_INLINE ( _subsys, pci_read_config_word ), \
- .pci_read_config_dword = \
- PCIAPI_INLINE ( _subsys, pci_read_config_dword ), \
- .pci_write_config_byte = \
- PCIAPI_INLINE ( _subsys, pci_write_config_byte ), \
- .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 ), \
+#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 ), \
+ .pci_read_config_word = \
+ PCIAPI_INLINE ( subsys, pci_read_config_word ), \
+ .pci_read_config_dword = \
+ PCIAPI_INLINE ( subsys, pci_read_config_dword ), \
+ .pci_write_config_byte = \
+ PCIAPI_INLINE ( subsys, pci_write_config_byte ), \
+ .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 ), \
}
#endif /* _IPXE_PCI_IO_H */