summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Brown2005-04-16 13:16:31 +0200
committerMichael Brown2005-04-16 13:16:31 +0200
commit6e5a3858bff856e41955523e8ffc0251ce601d80 (patch)
tree0ef75b19425618f7e848d4ca5d76673383615645
parentImproved debugging output (diff)
downloadipxe-6e5a3858bff856e41955523e8ffc0251ce601d80.tar.gz
ipxe-6e5a3858bff856e41955523e8ffc0251ce601d80.tar.xz
ipxe-6e5a3858bff856e41955523e8ffc0251ce601d80.zip
Read number of PCI buses returned by BIOS so that we can scan more
quickly.
-rw-r--r--src/arch/i386/core/pci_io.c31
-rw-r--r--src/drivers/bus/pci.c11
-rw-r--r--src/include/pci.h7
3 files changed, 37 insertions, 12 deletions
diff --git a/src/arch/i386/core/pci_io.c b/src/arch/i386/core/pci_io.c
index ffbf53c55..28d9cbdd2 100644
--- a/src/arch/i386/core/pci_io.c
+++ b/src/arch/i386/core/pci_io.c
@@ -56,8 +56,10 @@ static int have_pcibios;
/* Macro for calling a 32-bit entry point with flat physical
* addresses. Use in a statement such as
* __asm__ ( FLAT_FAR_CALL_ESI,
- * : <output registers>
+ * : "=S" ( discard, or real output ), <other output registers>
* : "S" ( entry_point ), <other input registers> );
+ * "=S" *must* be specified as an output, otherwise the compiler will
+ * assume that it remains unaltered.
*/
#define FLAT_FAR_CALL_ESI "call _virt_to_phys\n\t" \
"pushl %%cs\n\t" \
@@ -135,18 +137,20 @@ static void find_pcibios16 ( void ) {
uint32_t signature;
uint16_t flags;
uint16_t revision;
+ uint8_t max_bus;
/* PCI BIOS installation check */
REAL_EXEC ( rm_pcibios_check,
"int $0x1a\n\t"
"pushfw\n\t"
- "popw %%cx\n\t",
- 4,
+ "popw %%si\n\t",
+ 5,
OUT_CONSTRAINTS ( "=a" ( present ), "=b" ( revision ),
- "=c" ( flags ), "=d" ( signature ) ),
+ "=c" ( max_bus ), "=d" ( signature ),
+ "=S" ( flags ) ),
IN_CONSTRAINTS ( "a" ( ( PCIBIOS_PCI_FUNCTION_ID << 8 ) +
PCIBIOS_PCI_BIOS_PRESENT ) ),
- CLOBBER ( "esi", "edi", "ebp" ) );
+ CLOBBER ( "edi", "ebp" ) );
if ( ( flags & CF ) ||
( ( present >> 8 ) != 0 ) ||
@@ -156,8 +160,9 @@ static void find_pcibios16 ( void ) {
}
/* We have a PCI BIOS */
- DBG ( "Found 16-bit PCI BIOS interface\n" );
+ DBG ( "Found 16-bit PCI BIOS interface with %d buses\n", max_bus + 1 );
have_pcibios = 1;
+ pci_max_bus = max_bus;
return;
}
@@ -280,7 +285,7 @@ static void find_pcibios32 ( void ) {
uint16_t present;
uint32_t flags;
uint16_t revision;
- uint32_t discard;
+ uint8_t max_bus;
/* Locate BIOS32 service directory */
bios32 = find_bios32 ();
@@ -299,9 +304,9 @@ static void find_pcibios32 ( void ) {
/* PCI BIOS installation check */
__asm__ ( FLAT_FAR_CALL_ESI
"pushfl\n\t"
- "popl %%ecx\n\t"
- : "=a" ( present ), "=b" ( revision ), "=c" ( flags ),
- "=d" ( signature ), "=S" ( discard )
+ "popl %%esi\n\t"
+ : "=a" ( present ), "=b" ( revision ), "=c" ( max_bus ),
+ "=d" ( signature ), "=S" ( flags )
: "a" ( ( PCIBIOS_PCI_FUNCTION_ID << 8 )
+ PCIBIOS_PCI_BIOS_PRESENT ),
"S" ( pcibios32_entry )
@@ -315,8 +320,10 @@ static void find_pcibios32 ( void ) {
}
/* We have a PCI BIOS */
- DBG ( "Found 32-bit PCI BIOS interface at %#x\n", pcibios32_entry );
+ DBG ( "Found 32-bit PCI BIOS interface at %#x with %d bus(es)\n",
+ pcibios32_entry, max_bus + 1 );
have_pcibios = 1;
+ pci_max_bus = max_bus;
return;
}
@@ -435,7 +442,7 @@ int pci_write_config_dword ( struct pci_device *pci, unsigned int where,
pcibios_write_config_dword ( pci, where, value ) :
pcidirect_write_config_dword ( pci, where, value );
}
-
+
unsigned long pci_bus_base ( struct pci_device *pci __unused ) {
/* architecturally this must be 0 */
return 0;
diff --git a/src/drivers/bus/pci.c b/src/drivers/bus/pci.c
index 4b34454c1..44b3a1b49 100644
--- a/src/drivers/bus/pci.c
+++ b/src/drivers/bus/pci.c
@@ -10,6 +10,13 @@ DEV_BUS( struct pci_device, pci_dev );
static char pci_magic[0]; /* guaranteed unique symbol */
/*
+ * pci_io.c may know how many buses we have, in which case it can
+ * overwrite this value.
+ *
+ */
+unsigned int pci_max_bus = 0xff;
+
+/*
* Fill in parameters (vendor & device ids, class, membase etc.) for a
* PCI device based on bus & devfn.
*
@@ -18,6 +25,10 @@ static char pci_magic[0]; /* guaranteed unique symbol */
static int fill_pci_device ( struct pci_device *pci ) {
uint32_t l;
int reg;
+
+ /* Check bus is within range */
+ if ( PCI_BUS ( pci->busdevfn ) > pci_max_bus )
+ return 0;
/* Check to see if there's anything physically present.
*/
diff --git a/src/include/pci.h b/src/include/pci.h
index ee1631de8..9b7fcadae 100644
--- a/src/include/pci.h
+++ b/src/include/pci.h
@@ -319,6 +319,13 @@ extern int pci_write_config_dword ( struct pci_device *dev, unsigned int where,
extern unsigned long pci_bus_base ( struct pci_device *dev );
/*
+ * pci_io.c is allowed to overwrite pci_max_bus if it knows what the
+ * highest bus in the system will be.
+ *
+ */
+extern unsigned int pci_max_bus;
+
+/*
* Functions in pci.c
*
*/