RTEMS  5.1
access.h
1 /* Routines to access PCI memory/configuration space and other PCI related
2  * functions the PCI Library provides.
3  *
4  * COPYRIGHT (c) 2010 Cobham Gaisler AB.
5  *
6  * The license and distribution terms for this file may be
7  * found in the file LICENSE in this distribution or at
8  * http://www.rtems.org/license/LICENSE.
9  */
10 
11 
12 #ifndef __PCI_ACCESS_H__
13 #define __PCI_ACCESS_H__
14 
15 #include <stdint.h>
16 #include <libcpu/byteorder.h>
17 #include <rtems/score/basedefs.h>
18 #include <pci.h>
19 
20 #ifdef __cplusplus
21 extern "C" {
22 #endif
23 
24 /* Identification of a PCI configuration space device (16-bit) */
25 typedef uint16_t pci_dev_t;
26 /* Create a PCI Configuration Space ID */
27 #define PCI_DEV(bus, slot, func) (((bus)<<8) | ((slot)<<3) | (func))
28 /* Get Bus of a PCI Configuration Space ID */
29 #define PCI_DEV_BUS(dev) (((dev) >> 8) & 0xff)
30 /* Get Slot/Device of a PCI Configuration Space ID */
31 #define PCI_DEV_SLOT(dev) (((dev) >> 3) & 0x1f)
32 /* Get Function of a PCI Configuration Space ID */
33 #define PCI_DEV_FUNC(dev) ((dev) & 0x7)
34 /* Get Device and Function of a PCI Configuration Space ID */
35 #define PCI_DEV_DEVFUNC(dev) ((dev) & 0xff)
36 /* Expand Device into argument lists */
37 #define PCI_DEV_EXPAND(dev) PCI_DEV_BUS((dev)), PCI_DEV_SLOT((dev)), PCI_DEV_FUNC((dev))
38 
39 /* Configuration Space Read/Write Operations */
40 struct pci_cfg_ops {
41  /* Configuration Space Access and Setup Routines */
42  int (*read8)(pci_dev_t dev, int ofs, uint8_t *data);
43  int (*read16)(pci_dev_t dev, int ofs, uint16_t *data);
44  int (*read32)(pci_dev_t dev, int ofs, uint32_t *data);
45  int (*write8)(pci_dev_t dev, int ofs, uint8_t data);
46  int (*write16)(pci_dev_t dev, int ofs, uint16_t data);
47  int (*write32)(pci_dev_t dev, int ofs, uint32_t data);
48 };
49 
50 /* Read a register over PCI I/O Space, and swap it if necessary (due to
51  * PCI endianness)
52  */
53 struct pci_io_ops {
54  uint8_t (*read8)(uint8_t *adr);
55  uint16_t(*read16)(uint16_t *adr);
56  uint32_t (*read32)(uint32_t *adr);
57  void (*write8)(uint8_t *adr, uint8_t data);
58  void (*write16)(uint16_t *adr, uint16_t data);
59  void (*write32)(uint32_t *adr, uint32_t data);
60 };
61 
62 /* Read a register over PCI Memory Space (non-prefetchable memory), and
63  * swap it if necessary (due to PCI endianness)
64  */
66  uint8_t (*ld8)(uint8_t *adr);
67  void (*st8)(uint8_t *adr, uint8_t data);
68 
69  uint16_t(*ld_le16)(uint16_t *adr);
70  void (*st_le16)(uint16_t *adr, uint16_t data);
71  uint16_t(*ld_be16)(uint16_t *adr);
72  void (*st_be16)(uint16_t *adr, uint16_t data);
73 
74  uint32_t (*ld_le32)(uint32_t *adr);
75  void (*st_le32)(uint32_t *adr, uint32_t data);
76  uint32_t (*ld_be32)(uint32_t *adr);
77  void (*st_be32)(uint32_t *adr, uint32_t data);
78 };
79 
80 typedef uint8_t (*pci_ld8_t)(uint8_t *adr);
81 typedef void (*pci_st8_t)(uint8_t *adr, uint8_t data);
82 typedef uint16_t(pci_ld16_t)(uint16_t *adr);
83 typedef void (*pci_st16_t)(uint16_t *adr, uint16_t data);
84 typedef uint32_t (*pci_ld32_t)(uint32_t *adr);
85 typedef void (*pci_st32_t)(uint32_t *adr, uint32_t data);
86 
88  /* Configuration */
89  struct pci_cfg_ops cfg;
90 
91  /* I/O Access operations */
92  struct pci_io_ops io;
93 
94  /* Registers over Memory Access operations. Note that these funcs
95  * are only for code that need to be compatible with both Big-Endian
96  * and Little-Endian PCI bus or for some other reason need function
97  * pointers to access functions. Normally drivers use the inline
98  * functions for Registers-over-Memory access to avoid extra function
99  * call.
100  */
101  struct pci_memreg_ops *memreg;
102 
103  /* Translate from PCI address to CPU address (dir=0). Translate
104  * CPU address to PCI address (dir!=0). The address will can be
105  * used to perform I/O access or memory access by CPU or PCI DMA
106  * peripheral.
107  *
108  * address In/Out. CPU address or PCI address.
109  * type Access type. 1=I/O, 2=MEMIO, 3=MEM
110  * dir Translate direction. 0=PCI-to-CPU, 0!=CPU-to-PCI,
111  *
112  * Return Value
113  * 0 = Success
114  * -1 = Requested Address not mapped into other address space
115  * i.e. not accessible
116  */
117  int (*translate)(uint32_t *address, int type, int dir);
118 };
119 
120 /* Access Routines valid after a PCI-Access-Driver has registered */
121 extern struct pci_access_drv pci_access_ops;
122 
123 /* Register PCI Access Driver */
124 extern int pci_access_drv_register(struct pci_access_drv *drv);
125 
126 /* Set/unset bits in command and status register of a PCI device */
127 extern void pci_modify_cmdsts(pci_dev_t dev, uint32_t mask, uint32_t val);
128 
129 /* Enable Memory in command register */
130 RTEMS_INLINE_ROUTINE void pci_mem_enable(pci_dev_t dev)
131 {
132  pci_modify_cmdsts(dev, PCIM_CMD_MEMEN, PCIM_CMD_MEMEN);
133 }
134 
135 RTEMS_INLINE_ROUTINE void pci_mem_disable(pci_dev_t dev)
136 {
137  pci_modify_cmdsts(dev, PCIM_CMD_MEMEN, 0);
138 }
139 
140 RTEMS_INLINE_ROUTINE void pci_io_enable(pci_dev_t dev)
141 {
142  pci_modify_cmdsts(dev, PCIM_CMD_PORTEN, PCIM_CMD_PORTEN);
143 }
144 
145 RTEMS_INLINE_ROUTINE void pci_io_disable(pci_dev_t dev)
146 {
147  pci_modify_cmdsts(dev, PCIM_CMD_PORTEN, 0);
148 }
149 
150 RTEMS_INLINE_ROUTINE void pci_master_enable(pci_dev_t dev)
151 {
152  pci_modify_cmdsts(dev, PCIM_CMD_BUSMASTEREN, PCIM_CMD_BUSMASTEREN);
153 }
154 
155 RTEMS_INLINE_ROUTINE void pci_master_disable(pci_dev_t dev)
156 {
157  pci_modify_cmdsts(dev, PCIM_CMD_BUSMASTEREN, 0);
158 }
159 
160 /* Configuration Space Access Read Routines */
161 extern int pci_cfg_r8(pci_dev_t dev, int ofs, uint8_t *data);
162 extern int pci_cfg_r16(pci_dev_t dev, int ofs, uint16_t *data);
163 extern int pci_cfg_r32(pci_dev_t dev, int ofs, uint32_t *data);
164 
165 /* Configuration Space Access Write Routines */
166 extern int pci_cfg_w8(pci_dev_t dev, int ofs, uint8_t data);
167 extern int pci_cfg_w16(pci_dev_t dev, int ofs, uint16_t data);
168 extern int pci_cfg_w32(pci_dev_t dev, int ofs, uint32_t data);
169 
170 /* Read a register over PCI I/O Space */
171 extern uint8_t pci_io_r8(uint32_t adr);
172 extern uint16_t pci_io_r16(uint32_t adr);
173 extern uint32_t pci_io_r32(uint32_t adr);
174 
175 /* Write a register over PCI I/O Space */
176 extern void pci_io_w8(uint32_t adr, uint8_t data);
177 extern void pci_io_w16(uint32_t adr, uint16_t data);
178 extern void pci_io_w32(uint32_t adr, uint32_t data);
179 
180 /* Translate PCI address into CPU accessible address */
181 RTEMS_INLINE_ROUTINE int pci_pci2cpu(uint32_t *address, int type)
182 {
183  return pci_access_ops.translate(address, type, 0);
184 }
185 
186 /* Translate CPU accessible address into PCI address (for DMA) */
187 RTEMS_INLINE_ROUTINE int pci_cpu2pci(uint32_t *address, int type)
188 {
189  return pci_access_ops.translate(address, type, 1);
190 }
191 
192 /*** Read/Write a register over PCI Memory Space ***/
193 
194 RTEMS_INLINE_ROUTINE uint8_t pci_ld8(volatile uint8_t *addr)
195 {
196  return *addr;
197 }
198 
199 RTEMS_INLINE_ROUTINE void pci_st8(volatile uint8_t *addr, uint8_t val)
200 {
201  *addr = val;
202 }
203 
204 /* Registers-over-Memory Space access routines. The routines are not inlined
205  * so it is possible during run-time to select which function implemention
206  * to use. The use of these functions are not recommended since it will have a
207  * performance penalty.
208  *
209  * 8-bit accesses are the same for Little and Big endian PCI buses.
210  */
211 uint8_t pci_mem_ld8(uint8_t *adr);
212 void pci_mem_st8(uint8_t *adr, uint8_t data);
213 /* Registers-over-Memory Space - Generic Big endian PCI bus definitions */
214 uint16_t pci_mem_be_ld_le16(uint16_t *adr);
215 uint16_t pci_mem_be_ld_be16(uint16_t *adr);
216 uint32_t pci_mem_be_ld_le32(uint32_t *adr);
217 uint32_t pci_mem_be_ld_be32(uint32_t *adr);
218 void pci_mem_be_st_le16(uint16_t *adr, uint16_t data);
219 void pci_mem_be_st_be16(uint16_t *adr, uint16_t data);
220 void pci_mem_be_st_le32(uint32_t *adr, uint32_t data);
221 void pci_mem_be_st_be32(uint32_t *adr, uint32_t data);
222 /* Registers-over-Memory Space - Generic Little endian PCI bus definitions */
223 uint16_t pci_mem_le_ld_le16(uint16_t *adr);
224 uint16_t pci_mem_le_ld_be16(uint16_t *adr);
225 uint32_t pci_mem_le_ld_le32(uint32_t *adr);
226 uint32_t pci_mem_le_ld_be32(uint32_t *adr);
227 void pci_mem_le_st_le16(uint16_t *adr, uint16_t data);
228 void pci_mem_le_st_be16(uint16_t *adr, uint16_t data);
229 void pci_mem_le_st_le32(uint32_t *adr, uint32_t data);
230 void pci_mem_le_st_be32(uint32_t *adr, uint32_t data);
231 
232 /* Get Read/Write function for accessing a register over PCI Memory Space
233  * (non-inline functions).
234  *
235  * Arguments
236  * wr 0(Read), 1(Write)
237  * size 1(Byte), 2(Word), 4(Double Word)
238  * func Where function pointer will be stored
239  * endian PCI_LITTLE_ENDIAN or PCI_BIG_ENDIAN
240  * type 1(I/O), 3(REG over MEM), 4(CFG)
241  *
242  * Return
243  * 0 Found function
244  * others No such function defined by host driver or BSP
245  */
246 extern int pci_access_func(int wr, int size, void **func, int endian, int type);
247 
248 /* Predefined functions for Host drivers or BSPs that define the
249  * register-over-memory space functions operations.
250  */
251 extern struct pci_memreg_ops pci_mem_le_ops; /* For Little-Endian PCI bus */
252 extern struct pci_memreg_ops pci_mem_be_ops; /* For Big-Endian PCI bus */
253 
254 #ifdef __cplusplus
255 }
256 #endif
257 
258 #endif /* !__PCI_ACCESS_H__ */
Definition: access.h:87
Definition: access.h:65
Definition: access.h:40
Definition: access.h:53
Basic Definitions.
unsigned size
Definition: tte.h:74
#define RTEMS_INLINE_ROUTINE
Definition: basedefs.h:66