summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/i386/shared
diff options
context:
space:
mode:
authorJoel Sherrill <joel@rtems.org>2016-03-03 10:36:24 -0600
committerJoel Sherrill <joel@rtems.org>2016-03-10 10:30:25 -0600
commitf770fcb3688f4db8aabb13964dfcbe28ef6fbd02 (patch)
tree298c432cb62516bb77f9a022e28837ba953e440a /c/src/lib/libbsp/i386/shared
parentpc386/configure.ac: Delete incorrect and unused AM_CONDITIONAL (diff)
downloadrtems-f770fcb3688f4db8aabb13964dfcbe28ef6fbd02.tar.bz2
Add shared PCI support and enhance pc386 to support non-legacy PCI configuration space
This patch fundamentally results from enhancements to the pc386 BSP to support systems which do **NOT** have the legacy PCI BIOS. The patch adds support for detecting when legacy PCI BIOS is not present and then using IO space to access to PCI Configuration Space. This resulted in dynamically selected between two implementations of PCI and refactoring out the shared methods. This patch adds shared implementations of pci_bus_count() and pci_find_device(). Subsequent patches will remove implementations of these methods in other BSPs where possible.
Diffstat (limited to 'c/src/lib/libbsp/i386/shared')
-rw-r--r--c/src/lib/libbsp/i386/shared/pci/pci_io.c198
-rw-r--r--c/src/lib/libbsp/i386/shared/pci/pcibios.c149
2 files changed, 217 insertions, 130 deletions
diff --git a/c/src/lib/libbsp/i386/shared/pci/pci_io.c b/c/src/lib/libbsp/i386/shared/pci/pci_io.c
new file mode 100644
index 0000000000..5947c04388
--- /dev/null
+++ b/c/src/lib/libbsp/i386/shared/pci/pci_io.c
@@ -0,0 +1,198 @@
+#include <rtems.h>
+#include <rtems/pci.h>
+#include <bsp.h>
+
+static int pci_io_initialized = 0;
+
+/*
+ * Forward reference. Initialized at bottom.
+ */
+static const pci_config_access_functions pci_io_indirect_functions;
+
+/*
+ * Detects presense of PCI Configuration is in I/O space. If so, return
+ * pointer to accessor methods.
+ *
+ * NOTE: TBD to determine if (a) PCI Bus exists and (b) this is the
+ * access method.
+ */
+const pci_config_access_functions *pci_io_initialize(void)
+{
+ pci_io_initialized = 1;
+
+ printk( "PCI I/O Support Initialized\n" );
+
+ return &pci_io_indirect_functions;
+}
+
+/*
+ * Build PCI Address
+ */
+static inline uint32_t pci_io_build_address(
+ uint16_t bus,
+ uint16_t slot,
+ uint16_t function,
+ uint16_t offset
+)
+{
+ uint32_t bus_u32 = (uint32_t)bus;
+ uint32_t slot_u32 = (uint32_t)slot;
+ uint32_t function_u32 = (uint32_t)function;
+ uint32_t address;
+
+ /*
+ * create configuration address as per figure at
+ * http://wiki.osdev.org/PCI#Configuration_Space_Access_Mechanism_.231
+ */
+ address = (uint32_t) 0x80000000; /* Bit 31 - Enable Bit */
+ /* Bits 30-24 - Reserved */
+ address |= bus_u32 << 16; /* Bits 23-16 - Bus Number */
+ address |= slot_u32 << 11; /* Bits 15-11 - Device/Slot Number */
+ address |= function_u32 << 8; /* Bits 10-8 - Function Number */
+ address |= offset & 0xfc; /* Bits 7-2 - Offset/Register Number */
+ /* Bits 1-0 - Reserved 0 */
+ return address;
+}
+
+static int BSP_pci_read_config_byte(
+ unsigned char bus,
+ unsigned char slot,
+ unsigned char function,
+ unsigned char offset,
+ unsigned char *value
+)
+{
+ uint32_t address;
+ uint32_t tmp;
+
+ address = pci_io_build_address( bus, slot, function, offset );
+
+ /* write out the address */
+ outport_long(0xCF8, address);
+
+ /* read in the data */
+ inport_long(0xCFC, tmp);
+
+ /* (offset & 3) * 8) = 0 will choose the first byte of the 32 bits register */
+ *value = (uint16_t)(tmp >> ((offset & 3) * 8)) & 0xff;
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int BSP_pci_read_config_word(
+ unsigned char bus,
+ unsigned char slot,
+ unsigned char function,
+ unsigned char offset,
+ unsigned short *value
+)
+{
+ uint32_t address;
+ uint32_t tmp;
+
+ address = pci_io_build_address( bus, slot, function, offset );
+
+ /* write out the address */
+ outport_long(0xCF8, address);
+
+ /* read in the data */
+ inport_long(0xCFC, tmp);
+
+ /* (offset & 2) * 8) = 0 will choose the first word of the 32 bits register */
+ *value = (uint16_t)(tmp >> ((offset & 2) * 8)) & 0xffff;
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int BSP_pci_read_config_dword(
+ unsigned char bus,
+ unsigned char slot,
+ unsigned char function,
+ unsigned char offset,
+ uint32_t *value
+)
+{
+ uint32_t address;
+ uint32_t tmp;
+
+ address = pci_io_build_address( bus, slot, function, offset );
+
+ /* write out the address */
+ outport_long(0xCF8, address);
+
+ /* read in the data */
+ inport_long(0xCFC, tmp);
+
+ *value = tmp;
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int BSP_pci_write_config_byte(
+ unsigned char bus,
+ unsigned char slot,
+ unsigned char function,
+ unsigned char offset,
+ unsigned char value
+)
+{
+ uint32_t address;
+
+ address = pci_io_build_address( bus, slot, function, offset );
+
+ /* write out the address */
+ outport_long(0xCF8, address);
+
+ /* read in the data */
+ outport_byte(0xCFC, value);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int BSP_pci_write_config_word(
+ unsigned char bus,
+ unsigned char slot,
+ unsigned char function,
+ unsigned char offset,
+ unsigned short value
+)
+{
+ uint32_t address;
+
+ address = pci_io_build_address( bus, slot, function, offset );
+
+ /* write out the address */
+ outport_long(0xCF8, address);
+
+ /* read in the data */
+ outport_word(0xCFC, value);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int BSP_pci_write_config_dword(
+ unsigned char bus,
+ unsigned char slot,
+ unsigned char function,
+ unsigned char offset,
+ uint32_t value
+)
+{
+ uint32_t address;
+
+ address = pci_io_build_address( bus, slot, function, offset );
+
+ /* write out the address */
+ outport_long(0xCF8, address);
+
+ /* read in the data */
+ outport_long(0xCFC, value);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static const pci_config_access_functions pci_io_indirect_functions = {
+ BSP_pci_read_config_byte,
+ BSP_pci_read_config_word,
+ BSP_pci_read_config_dword,
+ BSP_pci_write_config_byte,
+ BSP_pci_write_config_word,
+ BSP_pci_write_config_dword
+};
diff --git a/c/src/lib/libbsp/i386/shared/pci/pcibios.c b/c/src/lib/libbsp/i386/shared/pci/pcibios.c
index 7dc53a125e..e74649413b 100644
--- a/c/src/lib/libbsp/i386/shared/pci/pcibios.c
+++ b/c/src/lib/libbsp/i386/shared/pci/pcibios.c
@@ -40,16 +40,23 @@ static int pcib_convert_err(int err);
#define PCIB_DEVSIG_BUS(x) (((x)>>8) &0xff)
#define PCIB_DEVSIG_DEV(x) (((x)>>3) & 0x1f)
#define PCIB_DEVSIG_FUNC(x) ((x) & 0x7)
+
/*
- * Detects presense of PCI BIOS, returns
- * error code
+ * Forward reference. Initialized at bottom.
*/
-int
-pci_initialize(void)
+static const pci_config_access_functions pci_bios_indirect_functions;
+
+/* prototype before defining */
+const pci_config_access_functions *pci_bios_initialize(void);
+
+/*
+ * Detects presense of PCI BIOS, returns pointer to accessor methods.
+ */
+const pci_config_access_functions *pci_bios_initialize(void)
{
unsigned char *ucp;
- unsigned char sum;
- int i;
+ unsigned char sum;
+ int i;
pcibInitialized = 0;
@@ -80,7 +87,7 @@ pci_initialize(void)
if (ucp >= (unsigned char *)0xFFFFF) {
/* BIOS-32 not found */
- return PCIB_ERR_NOTPRESENT;
+ return NULL;
}
/* BIOS-32 found, let us find PCI BIOS */
@@ -102,7 +109,7 @@ pci_initialize(void)
if ((pcibExchg[0] & 0xff) != 0) {
/* Not found */
- return PCIB_ERR_NOTPRESENT;
+ return NULL;
}
/* Found PCI entry point */
@@ -125,130 +132,18 @@ pci_initialize(void)
if ((pcibExchg[0] & 0xff00) != 0) {
/* Not found */
- return PCIB_ERR_NOTPRESENT;
+ return NULL;
}
if (pcibExchg[3] != 0x20494350) {
/* Signature does not match */
- return PCIB_ERR_NOTPRESENT;
+ return NULL;
}
/* Success */
-
pcibInitialized = 1;
- return PCIB_ERR_SUCCESS;
-}
-
-/*
- * Find specified device and return its signature: combination
- * of bus number, device number and function number
- */
-static int
-pcib_find_by_devid(int vendorId, int devId, int idx, int *sig)
-{
- if (!pcibInitialized) {
- return PCIB_ERR_UNINITIALIZED;
- }
-
- pcibExchg[0] = pcibEntry;
- pcibExchg[1] = vendorId;
- pcibExchg[2] = devId;
- pcibExchg[3] = idx;
-
- __asm__ (" pusha");
- __asm__ (" movl pcibExchg, %edi");
- __asm__ (" movb $0xb1, %ah");
- __asm__ (" movb $0x02, %al");
- __asm__ (" movl pcibExchg+4, %edx");
- __asm__ (" movl pcibExchg+8, %ecx");
- __asm__ (" movl pcibExchg+12, %esi");
- __asm__ (" pushl %cs");
- __asm__ (" call *%edi");
- __asm__ (" movl %eax, pcibExchg");
- __asm__ (" movl %ebx, pcibExchg+4");
- __asm__ (" popa");
-
- *sig = pcibExchg[1] & 0xffff;
- return pcib_convert_err((pcibExchg[0] >> 8) & 0xff);
-}
-
-int
-pci_find_device(
- unsigned short vendorid,
- unsigned short deviceid,
- int instance,
- int *pbus,
- int *pdev,
- int *pfun
-)
-{
- int status;
- int sig = 0;
-
- status = pcib_find_by_devid( vendorid, deviceid, instance, &sig );
-
- *pbus = PCIB_DEVSIG_BUS(sig);
- *pdev = PCIB_DEVSIG_DEV(sig);
- *pfun = PCIB_DEVSIG_FUNC(sig);
- return status ? -1 : 0;
-}
-
-static uint8_t ucBusCount = 0xff;
-
-unsigned char
-pci_bus_count(void)
-{
- if ( ucBusCount == 0xff ) {
- unsigned char bus;
- unsigned char dev;
- unsigned char fun;
- unsigned char nfn;
- unsigned char hd = 0;
- uint32_t d = 0;
-
- ucBusCount = 0;
-
- for (bus=0; bus< 0xff; bus++) {
- for (dev=0; dev<PCI_MAX_DEVICES; dev++) {
- pci_read_config_dword(bus, dev, fun, PCI_VENDOR_ID, &d);
-
- if ( -1 == d ) {
- continue;
- }
-
- pci_read_config_byte(bus, dev, fun, PCI_HEADER_TYPE, &hd);
- nfn = (hd & 0x80) ? PCI_MAX_FUNCTIONS : 1;
-
- for ( fun=0; fun<nfn; fun++ ) {
-
- pci_read_config_dword(bus, dev, fun, PCI_VENDOR_ID, &d);
- if ( -1 == d )
- continue;
-
- pci_read_config_dword(bus, dev, fun, PCI_CLASS_REVISION, &d);
-
- if ( (d >> 16) == PCI_CLASS_BRIDGE_PCI ) {
- pci_read_config_byte(bus, dev, fun, PCI_SUBORDINATE_BUS, &hd);
-
- if ( hd > ucBusCount )
- ucBusCount = hd;
- }
-
- }
- }
- }
-
- if ( ucBusCount == 0 ) {
- printk("pci_bus_count() found 0 busses, assuming 1\n");
- ucBusCount = 1;
- } else if ( ucBusCount == 0xff ) {
- printk("pci_bus_count() found 0xff busses, assuming 1\n");
- ucBusCount = 1;
- }
- }
-
- return ucBusCount;
+ return &pci_bios_indirect_functions;
}
/*
@@ -568,7 +463,7 @@ BSP_pci_write_config_dword(
return PCIBIOS_SUCCESSFUL;
}
-const pci_config_access_functions pci_indirect_functions = {
+static const pci_config_access_functions pci_bios_indirect_functions = {
BSP_pci_read_config_byte,
BSP_pci_read_config_word,
BSP_pci_read_config_dword,
@@ -576,9 +471,3 @@ const pci_config_access_functions pci_indirect_functions = {
BSP_pci_write_config_word,
BSP_pci_write_config_dword
};
-
-rtems_pci_config_t BSP_pci_configuration = {
- (volatile unsigned char*)0,
- (volatile unsigned char*)0,
- &pci_indirect_functions
-};