[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:
Michael Brown
2025-11-24 20:18:52 +00:00
parent 0cf2f8028c
commit ff1a17dc7e
12 changed files with 59 additions and 43 deletions

View File

@@ -54,6 +54,4 @@ struct ecam_mapping {
int rc;
};
extern struct pci_api ecam_api;
#endif /* _IPXE_ECAM_H */

View File

@@ -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 ), \
.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 */

View File

@@ -0,0 +1,28 @@
#ifndef _IPXE_PCICLOUD_H
#define _IPXE_PCICLOUD_H
/** @file
*
* Cloud VM PCI configuration space access
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#ifdef PCIAPI_CLOUD
#define PCIAPI_PREFIX_cloud
#else
#define PCIAPI_PREFIX_cloud __cloud_
#endif
/**
* Check if PCI bus probing is allowed
*
* @ret ok Bus probing is allowed
*/
static inline __always_inline int
PCIAPI_INLINE ( cloud, pci_can_probe ) ( void ) {
return 1;
}
#endif /* _IPXE_PCICLOUD_H */