]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[pci] Use linker tables for runtime selectable PCI APIs
authorMichael Brown <mcb30@ipxe.org>
Mon, 24 Nov 2025 20:18:52 +0000 (20:18 +0000)
committerMichael Brown <mcb30@ipxe.org>
Mon, 24 Nov 2025 20:54:01 +0000 (20:54 +0000)
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>
12 files changed:
src/arch/x86/core/pcidirect.c
src/arch/x86/include/bits/pci_io.h
src/arch/x86/include/ipxe/pcibios.h
src/arch/x86/include/ipxe/pcidirect.h
src/arch/x86/interface/pcbios/pcibios.c
src/config/cloud/ioapi.h
src/config/config_pci.c
src/drivers/bus/ecam.c
src/drivers/bus/pcicloud.c [moved from src/arch/x86/interface/pcbios/pcicloud.c with 94% similarity]
src/include/ipxe/ecam.h
src/include/ipxe/pci_io.h
src/include/ipxe/pcicloud.h [moved from src/arch/x86/include/ipxe/pcicloud.h with 100% similarity]

index 90d4623b3d72dd700817bf9dec2191bd19cef514..887b78a0bcc61827b0635f50467e46cfcb172bbe 100644 (file)
@@ -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 );
index a074d337070d7c6b41b349d5159152fef6f6dc9b..b41e562ee34bc96a70c670b05223ca2434aa2936 100644 (file)
@@ -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 */
index ef958565479754ae6e3b1415334469c3fe2137fb..87b4035559ece43f94cf5ffb9d31a29c68137932 100644 (file)
@@ -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 */
index 999b52763ec042a8321f77adb3c3f886a16b30d3..50157658269ceef19b0253d0347897e28fb413c3 100644 (file)
@@ -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 */
index ebe40ba7df2b70bc9732f00810de3d60eed8042e..6b88ee907462bd6f95743efa2161890184bf72b6 100644 (file)
@@ -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 );
index ba0896a9a6aecfd2f44acb252fbe772e60e6a2f9..bcd2459814bab13883641b541953bd2d98c9c761 100644 (file)
@@ -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
index cb8df712ad25c39e1e464ffb5594e60fe0ccba22..8ed9f6603cf5210918f90dc2a0ce3b986bd4df0b 100644 (file)
@@ -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
index 976254c18d2239eeb1819b6c326f43d0f9712695..602f7bd8af3c26caff05dccd3f9b45991976b585 100644 (file)
@@ -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 );
similarity index 94%
rename from src/arch/x86/interface/pcbios/pcicloud.c
rename to src/drivers/bus/pcicloud.c
index 284cd078c9b4a101cb541d61516e32d3b6978d0d..9e1fd32b2b09e4ce0e8c29fed12478924b813a50 100644 (file)
@@ -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;
index ff08aee5a5c9357204832b7093f5655522af6ad2..856a673c5193bf9a1594937d90156f5e28c2bdb5 100644 (file)
@@ -54,6 +54,4 @@ struct ecam_mapping {
        int rc;
 };
 
-extern struct pci_api ecam_api;
-
 #endif /* _IPXE_ECAM_H */
index 9b4cbcab4ccf7969550f569278e4e4ce3ca50040..456e29e6ee41d4dc869c53b0aba24212b5d49930 100644 (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 */