source: rtems/cpukit/libpci/pci/access.h @ a31845f7

4.11
Last change on this file since a31845f7 was a31845f7, checked in by Daniel Hellstrom <daniel@…>, on Nov 28, 2011 at 9:11:10 AM

LIBPCI: added PCI layer to cpukit/libpci

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