source: rtems/c/src/lib/libbsp/i386/shared/pci/pci_io.c @ 78c9fe8

5
Last change on this file since 78c9fe8 was f770fcb, checked in by Joel Sherrill <joel@…>, on 03/03/16 at 16:36:24

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.

  • Property mode set to 100644
File size: 4.4 KB
Line 
1#include <rtems.h>
2#include <rtems/pci.h>
3#include <bsp.h>
4
5static int pci_io_initialized = 0;
6
7/*
8 * Forward reference. Initialized at bottom.
9 */
10static const pci_config_access_functions pci_io_indirect_functions;
11
12/*
13 * Detects presense of PCI Configuration is in I/O space. If so, return
14 * pointer to accessor methods.
15 *
16 * NOTE: TBD to determine if (a) PCI Bus exists and (b) this is the
17 *       access method.
18 */
19const pci_config_access_functions *pci_io_initialize(void)
20{
21  pci_io_initialized = 1;
22
23  printk( "PCI I/O Support Initialized\n" );
24
25  return &pci_io_indirect_functions;
26}
27
28/*
29 * Build PCI Address
30 */
31static inline uint32_t pci_io_build_address(
32  uint16_t  bus,
33  uint16_t  slot,
34  uint16_t  function,
35  uint16_t  offset
36)
37{
38  uint32_t bus_u32      = (uint32_t)bus;
39  uint32_t slot_u32     = (uint32_t)slot;
40  uint32_t function_u32 = (uint32_t)function;
41  uint32_t address;
42
43  /*
44   * create configuration address as per figure at
45   *   http://wiki.osdev.org/PCI#Configuration_Space_Access_Mechanism_.231
46   */
47  address  = (uint32_t) 0x80000000;  /* Bit  31    - Enable Bit */
48                                     /* Bits 30-24 - Reserved */
49  address |= bus_u32 << 16;          /* Bits 23-16 - Bus Number */
50  address |= slot_u32 << 11;         /* Bits 15-11 - Device/Slot Number */
51  address |= function_u32 << 8;      /* Bits 10-8  - Function Number */
52  address |= offset & 0xfc;          /* Bits 7-2   - Offset/Register Number */
53                                     /* Bits 1-0   - Reserved 0 */
54  return address;
55}
56
57static int BSP_pci_read_config_byte(
58  unsigned char bus,
59  unsigned char slot,
60  unsigned char function,
61  unsigned char offset,
62  unsigned char *value
63)
64{
65  uint32_t address;
66  uint32_t tmp;
67
68  address = pci_io_build_address( bus, slot, function, offset );
69
70  /* write out the address */
71  outport_long(0xCF8, address);
72
73  /* read in the data */
74  inport_long(0xCFC, tmp);
75
76  /* (offset & 3) * 8) = 0 will choose the first byte of the 32 bits register */
77  *value = (uint16_t)(tmp >> ((offset & 3) * 8)) & 0xff;
78  return PCIBIOS_SUCCESSFUL;
79}
80
81static int BSP_pci_read_config_word(
82  unsigned char bus,
83  unsigned char slot,
84  unsigned char function,
85  unsigned char offset,
86  unsigned short *value
87)
88{
89  uint32_t address;
90  uint32_t tmp;
91
92  address = pci_io_build_address( bus, slot, function, offset );
93
94  /* write out the address */
95  outport_long(0xCF8, address);
96
97  /* read in the data */
98  inport_long(0xCFC, tmp);
99
100  /* (offset & 2) * 8) = 0 will choose the first word of the 32 bits register */
101  *value = (uint16_t)(tmp >> ((offset & 2) * 8)) & 0xffff;
102  return PCIBIOS_SUCCESSFUL;
103}
104
105static int BSP_pci_read_config_dword(
106  unsigned char bus,
107  unsigned char slot,
108  unsigned char function,
109  unsigned char offset,
110  uint32_t     *value
111)
112{
113  uint32_t address;
114  uint32_t tmp;
115
116  address = pci_io_build_address( bus, slot, function, offset );
117
118  /* write out the address */
119  outport_long(0xCF8, address);
120
121  /* read in the data */
122  inport_long(0xCFC, tmp);
123
124  *value = tmp;
125  return PCIBIOS_SUCCESSFUL;
126}
127
128static int BSP_pci_write_config_byte(
129  unsigned char bus,
130  unsigned char slot,
131  unsigned char function,
132  unsigned char offset,
133  unsigned char value
134)
135{
136  uint32_t address;
137
138  address = pci_io_build_address( bus, slot, function, offset );
139
140  /* write out the address */
141  outport_long(0xCF8, address);
142
143  /* read in the data */
144  outport_byte(0xCFC, value);
145
146  return PCIBIOS_SUCCESSFUL;
147}
148
149static int BSP_pci_write_config_word(
150  unsigned char bus,
151  unsigned char slot,
152  unsigned char function,
153  unsigned char offset,
154  unsigned short value
155)
156{
157  uint32_t address;
158
159  address = pci_io_build_address( bus, slot, function, offset );
160
161  /* write out the address */
162  outport_long(0xCF8, address);
163
164  /* read in the data */
165  outport_word(0xCFC, value);
166
167  return PCIBIOS_SUCCESSFUL;
168}
169
170static int BSP_pci_write_config_dword(
171  unsigned char bus,
172  unsigned char slot,
173  unsigned char function,
174  unsigned char offset,
175  uint32_t      value
176)
177{
178  uint32_t address;
179
180  address = pci_io_build_address( bus, slot, function, offset );
181
182  /* write out the address */
183  outport_long(0xCF8, address);
184
185  /* read in the data */
186  outport_long(0xCFC, value);
187
188  return PCIBIOS_SUCCESSFUL;
189}
190
191static const pci_config_access_functions pci_io_indirect_functions = {
192  BSP_pci_read_config_byte,
193  BSP_pci_read_config_word,
194  BSP_pci_read_config_dword,
195  BSP_pci_write_config_byte,
196  BSP_pci_write_config_word,
197  BSP_pci_write_config_dword
198};
Note: See TracBrowser for help on using the repository browser.