summaryrefslogtreecommitdiffstats
path: root/bsps/i386/shared/pci/pci_io.c
diff options
context:
space:
mode:
Diffstat (limited to 'bsps/i386/shared/pci/pci_io.c')
-rw-r--r--bsps/i386/shared/pci/pci_io.c213
1 files changed, 213 insertions, 0 deletions
diff --git a/bsps/i386/shared/pci/pci_io.c b/bsps/i386/shared/pci/pci_io.c
new file mode 100644
index 0000000000..b6cd1005f0
--- /dev/null
+++ b/bsps/i386/shared/pci/pci_io.c
@@ -0,0 +1,213 @@
+/**
+ * @file
+ *
+ * PCI Support when Configuration Space is in I/O
+ */
+
+/*
+ * COPYRIGHT (c) 2016.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <rtems.h>
+#include <bsp.h>
+#include <bsp/bspimpl.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
+};