summaryrefslogtreecommitdiffstats
path: root/cpukit/include/pci/access.h
diff options
context:
space:
mode:
authorChris Johns <chrisj@rtems.org>2017-12-23 18:18:56 +1100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2018-01-25 08:45:26 +0100
commit2afb22b7e1ebcbe40373ff7e0efae7d207c655a9 (patch)
tree44759efe9374f13200a97e96d91bd9a2b7e5ce2a /cpukit/include/pci/access.h
parentMAINTAINERS: Add myself to Write After Approval. (diff)
downloadrtems-2afb22b7e1ebcbe40373ff7e0efae7d207c655a9.tar.bz2
Remove make preinstall
A speciality of the RTEMS build system was the make preinstall step. It copied header files from arbitrary locations into the build tree. The header files were included via the -Bsome/build/tree/path GCC command line option. This has at least seven problems: * The make preinstall step itself needs time and disk space. * Errors in header files show up in the build tree copy. This makes it hard for editors to open the right file to fix the error. * There is no clear relationship between source and build tree header files. This makes an audit of the build process difficult. * The visibility of all header files in the build tree makes it difficult to enforce API barriers. For example it is discouraged to use BSP-specifics in the cpukit. * An introduction of a new build system is difficult. * Include paths specified by the -B option are system headers. This may suppress warnings. * The parallel build had sporadic failures on some hosts. This patch removes the make preinstall step. All installed header files are moved to dedicated include directories in the source tree. Let @RTEMS_CPU@ be the target architecture, e.g. arm, powerpc, sparc, etc. Let @RTEMS_BSP_FAMILIY@ be a BSP family base directory, e.g. erc32, imx, qoriq, etc. The new cpukit include directories are: * cpukit/include * cpukit/score/cpu/@RTEMS_CPU@/include * cpukit/libnetworking The new BSP include directories are: * bsps/include * bsps/@RTEMS_CPU@/include * bsps/@RTEMS_CPU@/@RTEMS_BSP_FAMILIY@/include There are build tree include directories for generated files. The include directory order favours the most general header file, e.g. it is not possible to override general header files via the include path order. The "bootstrap -p" option was removed. The new "bootstrap -H" option should be used to regenerate the "headers.am" files. Update #3254.
Diffstat (limited to 'cpukit/include/pci/access.h')
-rw-r--r--cpukit/include/pci/access.h258
1 files changed, 258 insertions, 0 deletions
diff --git a/cpukit/include/pci/access.h b/cpukit/include/pci/access.h
new file mode 100644
index 0000000000..4337db30c3
--- /dev/null
+++ b/cpukit/include/pci/access.h
@@ -0,0 +1,258 @@
+/* Routines to access PCI memory/configuration space and other PCI related
+ * functions the PCI Library provides.
+ *
+ * COPYRIGHT (c) 2010 Cobham Gaisler AB.
+ *
+ * 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.
+ */
+
+
+#ifndef __PCI_ACCESS_H__
+#define __PCI_ACCESS_H__
+
+#include <stdint.h>
+#include <libcpu/byteorder.h>
+#include <rtems/score/basedefs.h>
+#include <pci.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Identification of a PCI configuration space device (16-bit) */
+typedef uint16_t pci_dev_t;
+/* Create a PCI Configuration Space ID */
+#define PCI_DEV(bus, slot, func) (((bus)<<8) | ((slot)<<3) | (func))
+/* Get Bus of a PCI Configuration Space ID */
+#define PCI_DEV_BUS(dev) (((dev) >> 8) & 0xff)
+/* Get Slot/Device of a PCI Configuration Space ID */
+#define PCI_DEV_SLOT(dev) (((dev) >> 3) & 0x1f)
+/* Get Function of a PCI Configuration Space ID */
+#define PCI_DEV_FUNC(dev) ((dev) & 0x7)
+/* Get Device and Function of a PCI Configuration Space ID */
+#define PCI_DEV_DEVFUNC(dev) ((dev) & 0xff)
+/* Expand Device into argument lists */
+#define PCI_DEV_EXPAND(dev) PCI_DEV_BUS((dev)), PCI_DEV_SLOT((dev)), PCI_DEV_FUNC((dev))
+
+/* Configuration Space Read/Write Operations */
+struct pci_cfg_ops {
+ /* Configuration Space Access and Setup Routines */
+ int (*read8)(pci_dev_t dev, int ofs, uint8_t *data);
+ int (*read16)(pci_dev_t dev, int ofs, uint16_t *data);
+ int (*read32)(pci_dev_t dev, int ofs, uint32_t *data);
+ int (*write8)(pci_dev_t dev, int ofs, uint8_t data);
+ int (*write16)(pci_dev_t dev, int ofs, uint16_t data);
+ int (*write32)(pci_dev_t dev, int ofs, uint32_t data);
+};
+
+/* Read a register over PCI I/O Space, and swap it if necessary (due to
+ * PCI endianness)
+ */
+struct pci_io_ops {
+ uint8_t (*read8)(uint8_t *adr);
+ uint16_t(*read16)(uint16_t *adr);
+ uint32_t (*read32)(uint32_t *adr);
+ void (*write8)(uint8_t *adr, uint8_t data);
+ void (*write16)(uint16_t *adr, uint16_t data);
+ void (*write32)(uint32_t *adr, uint32_t data);
+};
+
+/* Read a register over PCI Memory Space (non-prefetchable memory), and
+ * swap it if necessary (due to PCI endianness)
+ */
+struct pci_memreg_ops {
+ uint8_t (*ld8)(uint8_t *adr);
+ void (*st8)(uint8_t *adr, uint8_t data);
+
+ uint16_t(*ld_le16)(uint16_t *adr);
+ void (*st_le16)(uint16_t *adr, uint16_t data);
+ uint16_t(*ld_be16)(uint16_t *adr);
+ void (*st_be16)(uint16_t *adr, uint16_t data);
+
+ uint32_t (*ld_le32)(uint32_t *adr);
+ void (*st_le32)(uint32_t *adr, uint32_t data);
+ uint32_t (*ld_be32)(uint32_t *adr);
+ void (*st_be32)(uint32_t *adr, uint32_t data);
+};
+
+typedef uint8_t (*pci_ld8_t)(uint8_t *adr);
+typedef void (*pci_st8_t)(uint8_t *adr, uint8_t data);
+typedef uint16_t(pci_ld16_t)(uint16_t *adr);
+typedef void (*pci_st16_t)(uint16_t *adr, uint16_t data);
+typedef uint32_t (*pci_ld32_t)(uint32_t *adr);
+typedef void (*pci_st32_t)(uint32_t *adr, uint32_t data);
+
+struct pci_access_drv {
+ /* Configuration */
+ struct pci_cfg_ops cfg;
+
+ /* I/O Access operations */
+ struct pci_io_ops io;
+
+ /* Registers over Memory Access operations. Note that these funcs
+ * are only for code that need to be compatible with both Big-Endian
+ * and Little-Endian PCI bus or for some other reason need function
+ * pointers to access functions. Normally drivers use the inline
+ * functions for Registers-over-Memory access to avoid extra function
+ * call.
+ */
+ struct pci_memreg_ops *memreg;
+
+ /* Translate from PCI address to CPU address (dir=0). Translate
+ * CPU address to PCI address (dir!=0). The address will can be
+ * used to perform I/O access or memory access by CPU or PCI DMA
+ * peripheral.
+ *
+ * address In/Out. CPU address or PCI address.
+ * type Access type. 1=I/O, 2=MEMIO, 3=MEM
+ * dir Translate direction. 0=PCI-to-CPU, 0!=CPU-to-PCI,
+ *
+ * Return Value
+ * 0 = Success
+ * -1 = Requested Address not mapped into other address space
+ * i.e. not accessible
+ */
+ int (*translate)(uint32_t *address, int type, int dir);
+};
+
+/* Access Routines valid after a PCI-Access-Driver has registered */
+extern struct pci_access_drv pci_access_ops;
+
+/* Register PCI Access Driver */
+extern int pci_access_drv_register(struct pci_access_drv *drv);
+
+/* Set/unset bits in command and status register of a PCI device */
+extern void pci_modify_cmdsts(pci_dev_t dev, uint32_t mask, uint32_t val);
+
+/* Enable Memory in command register */
+RTEMS_INLINE_ROUTINE void pci_mem_enable(pci_dev_t dev)
+{
+ pci_modify_cmdsts(dev, PCIM_CMD_MEMEN, PCIM_CMD_MEMEN);
+}
+
+RTEMS_INLINE_ROUTINE void pci_mem_disable(pci_dev_t dev)
+{
+ pci_modify_cmdsts(dev, PCIM_CMD_MEMEN, 0);
+}
+
+RTEMS_INLINE_ROUTINE void pci_io_enable(pci_dev_t dev)
+{
+ pci_modify_cmdsts(dev, PCIM_CMD_PORTEN, PCIM_CMD_PORTEN);
+}
+
+RTEMS_INLINE_ROUTINE void pci_io_disable(pci_dev_t dev)
+{
+ pci_modify_cmdsts(dev, PCIM_CMD_PORTEN, 0);
+}
+
+RTEMS_INLINE_ROUTINE void pci_master_enable(pci_dev_t dev)
+{
+ pci_modify_cmdsts(dev, PCIM_CMD_BUSMASTEREN, PCIM_CMD_BUSMASTEREN);
+}
+
+RTEMS_INLINE_ROUTINE void pci_master_disable(pci_dev_t dev)
+{
+ pci_modify_cmdsts(dev, PCIM_CMD_BUSMASTEREN, 0);
+}
+
+/* Configuration Space Access Read Routines */
+extern int pci_cfg_r8(pci_dev_t dev, int ofs, uint8_t *data);
+extern int pci_cfg_r16(pci_dev_t dev, int ofs, uint16_t *data);
+extern int pci_cfg_r32(pci_dev_t dev, int ofs, uint32_t *data);
+
+/* Configuration Space Access Write Routines */
+extern int pci_cfg_w8(pci_dev_t dev, int ofs, uint8_t data);
+extern int pci_cfg_w16(pci_dev_t dev, int ofs, uint16_t data);
+extern int pci_cfg_w32(pci_dev_t dev, int ofs, uint32_t data);
+
+/* Read a register over PCI I/O Space */
+extern uint8_t pci_io_r8(uint32_t adr);
+extern uint16_t pci_io_r16(uint32_t adr);
+extern uint32_t pci_io_r32(uint32_t adr);
+
+/* Write a register over PCI I/O Space */
+extern void pci_io_w8(uint32_t adr, uint8_t data);
+extern void pci_io_w16(uint32_t adr, uint16_t data);
+extern void pci_io_w32(uint32_t adr, uint32_t data);
+
+/* Translate PCI address into CPU accessible address */
+RTEMS_INLINE_ROUTINE int pci_pci2cpu(uint32_t *address, int type)
+{
+ return pci_access_ops.translate(address, type, 0);
+}
+
+/* Translate CPU accessible address into PCI address (for DMA) */
+RTEMS_INLINE_ROUTINE int pci_cpu2pci(uint32_t *address, int type)
+{
+ return pci_access_ops.translate(address, type, 1);
+}
+
+/*** Read/Write a register over PCI Memory Space ***/
+
+RTEMS_INLINE_ROUTINE uint8_t pci_ld8(volatile uint8_t *addr)
+{
+ return *addr;
+}
+
+RTEMS_INLINE_ROUTINE void pci_st8(volatile uint8_t *addr, uint8_t val)
+{
+ *addr = val;
+}
+
+/* Registers-over-Memory Space access routines. The routines are not inlined
+ * so it is possible during run-time to select which function implemention
+ * to use. The use of these functions are not recommended since it will have a
+ * performance penalty.
+ *
+ * 8-bit accesses are the same for Little and Big endian PCI buses.
+ */
+uint8_t pci_mem_ld8(uint8_t *adr);
+void pci_mem_st8(uint8_t *adr, uint8_t data);
+/* Registers-over-Memory Space - Generic Big endian PCI bus definitions */
+uint16_t pci_mem_be_ld_le16(uint16_t *adr);
+uint16_t pci_mem_be_ld_be16(uint16_t *adr);
+uint32_t pci_mem_be_ld_le32(uint32_t *adr);
+uint32_t pci_mem_be_ld_be32(uint32_t *adr);
+void pci_mem_be_st_le16(uint16_t *adr, uint16_t data);
+void pci_mem_be_st_be16(uint16_t *adr, uint16_t data);
+void pci_mem_be_st_le32(uint32_t *adr, uint32_t data);
+void pci_mem_be_st_be32(uint32_t *adr, uint32_t data);
+/* Registers-over-Memory Space - Generic Little endian PCI bus definitions */
+uint16_t pci_mem_le_ld_le16(uint16_t *adr);
+uint16_t pci_mem_le_ld_be16(uint16_t *adr);
+uint32_t pci_mem_le_ld_le32(uint32_t *adr);
+uint32_t pci_mem_le_ld_be32(uint32_t *adr);
+void pci_mem_le_st_le16(uint16_t *adr, uint16_t data);
+void pci_mem_le_st_be16(uint16_t *adr, uint16_t data);
+void pci_mem_le_st_le32(uint32_t *adr, uint32_t data);
+void pci_mem_le_st_be32(uint32_t *adr, uint32_t data);
+
+/* Get Read/Write function for accessing a register over PCI Memory Space
+ * (non-inline functions).
+ *
+ * Arguments
+ * wr 0(Read), 1(Write)
+ * size 1(Byte), 2(Word), 4(Double Word)
+ * func Where function pointer will be stored
+ * endian PCI_LITTLE_ENDIAN or PCI_BIG_ENDIAN
+ * type 1(I/O), 3(REG over MEM), 4(CFG)
+ *
+ * Return
+ * 0 Found function
+ * others No such function defined by host driver or BSP
+ */
+extern int pci_access_func(int wr, int size, void **func, int endian, int type);
+
+/* Predefined functions for Host drivers or BSPs that define the
+ * register-over-memory space functions operations.
+ */
+extern struct pci_memreg_ops pci_mem_le_ops; /* For Little-Endian PCI bus */
+extern struct pci_memreg_ops pci_mem_be_ops; /* For Big-Endian PCI bus */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !__PCI_ACCESS_H__ */