614df948a21235c10fdd69b954c2cd591f5ed6ab
[people/mcb30/edk2.git] / edk2 / MdeModulePkg / Universal / PcatSingleSegmentPciCfg2Pei / PciCfg2.c
1 /** @file\r
2   Installs Single Segment Pci Configuration PPI.\r
3 \r
4   Copyright (c) 2006 - 2007, Intel Corporation\r
5   All rights reserved. This program and the accompanying materials\r
6   are licensed and made available under the terms and conditions of the BSD License\r
7   which accompanies this distribution.  The full text of the license may be found at\r
8   http://opensource.org/licenses/bsd-license.php\r
9 \r
10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12 \r
13 **/\r
14 \r
15 #include <PiPei.h>\r
16 \r
17 #include <Ppi/PciCfg2.h>\r
18 \r
19 #include <Library/BaseLib.h>\r
20 #include <Library/DebugLib.h>\r
21 #include <Library/PciLib.h>\r
22 #include <Library/PeimEntryPoint.h>\r
23 \r
24 #include <IndustryStandard/Pci.h>\r
25 \r
26 /**\r
27    Convert EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS to PCI_LIB_ADDRESS.\r
28 \r
29    @param Address   PCI address with\r
30                     EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS format.\r
31 \r
32    @return The PCI address with PCI_LIB_ADDRESS format.\r
33 \r
34 **/\r
35 STATIC\r
36 UINTN\r
37 PciCfgAddressConvert (\r
38   EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS *Address\r
39   )\r
40 {\r
41   if (Address->ExtendedRegister == 0) {\r
42     return PCI_LIB_ADDRESS (Address->Bus, Address->Device, Address->Function, Address->Register);\r
43   }\r
44 \r
45   return PCI_LIB_ADDRESS (Address->Bus, Address->Device, Address->Function, Address->ExtendedRegister);\r
46 }\r
47 \r
48 /**\r
49   Reads from a given location in the PCI configuration space.\r
50 \r
51   @param  PeiServices     An indirect pointer to the PEI Services Table published by the PEI Foundation.\r
52 \r
53   @param  This            Pointer to local data for the interface.\r
54 \r
55   @param  Width           The width of the access. Enumerated in bytes.\r
56                           See EFI_PEI_PCI_CFG_PPI_WIDTH above.\r
57 \r
58   @param  Address         The physical address of the access. The format of\r
59                           the address is described by EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS.\r
60 \r
61   @param  Buffer          A pointer to the buffer of data..\r
62 \r
63 \r
64   @retval EFI_SUCCESS           The function completed successfully.\r
65 \r
66   @retval EFI_DEVICE_ERROR      There was a problem with the transaction.\r
67 \r
68   @retval EFI_DEVICE_NOT_READY  The device is not capable of supporting the operation at this\r
69                                 time.\r
70 \r
71 **/\r
72 EFI_STATUS\r
73 EFIAPI\r
74 PciCfg2Read (\r
75   IN CONST  EFI_PEI_SERVICES          **PeiServices,\r
76   IN CONST  EFI_PEI_PCI_CFG2_PPI      *This,\r
77   IN        EFI_PEI_PCI_CFG_PPI_WIDTH Width,\r
78   IN        UINT64                    Address,\r
79   IN OUT    VOID                      *Buffer\r
80 );\r
81 \r
82 /**\r
83   Write to a given location in the PCI configuration space.\r
84 \r
85   @param  PeiServices     An indirect pointer to the PEI Services Table published by the PEI Foundation.\r
86 \r
87   @param  This            Pointer to local data for the interface.\r
88 \r
89   @param  Width           The width of the access. Enumerated in bytes.\r
90                           See EFI_PEI_PCI_CFG_PPI_WIDTH above.\r
91 \r
92   @param  Address         The physical address of the access. The format of\r
93                           the address is described by EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS.\r
94 \r
95   @param  Buffer          A pointer to the buffer of data..\r
96 \r
97 \r
98   @retval EFI_SUCCESS           The function completed successfully.\r
99 \r
100   @retval EFI_DEVICE_ERROR      There was a problem with the transaction.\r
101 \r
102   @retval EFI_DEVICE_NOT_READY  The device is not capable of supporting the operation at this\r
103                                 time.\r
104 \r
105 **/\r
106 EFI_STATUS\r
107 EFIAPI\r
108 PciCfg2Write (\r
109   IN CONST  EFI_PEI_SERVICES          **PeiServices,\r
110   IN CONST  EFI_PEI_PCI_CFG2_PPI      *This,\r
111   IN        EFI_PEI_PCI_CFG_PPI_WIDTH Width,\r
112   IN        UINT64                    Address,\r
113   IN OUT    VOID                      *Buffer\r
114 );\r
115 \r
116 \r
117 /**\r
118   PCI read-modify-write operation.\r
119 \r
120   @param  PeiServices     An indirect pointer to the PEI Services Table\r
121                           published by the PEI Foundation.\r
122 \r
123   @param  This            Pointer to local data for the interface.\r
124 \r
125   @param  Width           The width of the access. Enumerated in bytes. Type\r
126                           EFI_PEI_PCI_CFG_PPI_WIDTH is defined in Read().\r
127 \r
128   @param  Address         The physical address of the access.\r
129 \r
130   @param  SetBits         Points to value to bitwise-OR with the read configuration value.\r
131 \r
132                           The size of the value is determined by Width.\r
133 \r
134   @param  ClearBits       Points to the value to negate and bitwise-AND with the read configuration value.\r
135                           The size of the value is determined by Width.\r
136 \r
137 \r
138   @retval EFI_SUCCESS           The function completed successfully.\r
139 \r
140   @retval EFI_DEVICE_ERROR      There was a problem with the transaction.\r
141 \r
142   @retval EFI_DEVICE_NOT_READY  The device is not capable of supporting\r
143                                 the operation at this time.\r
144 \r
145 **/\r
146 EFI_STATUS\r
147 EFIAPI\r
148 PciCfg2Modify (\r
149   IN CONST  EFI_PEI_SERVICES          **PeiServices,\r
150   IN CONST  EFI_PEI_PCI_CFG2_PPI      *This,\r
151   IN        EFI_PEI_PCI_CFG_PPI_WIDTH Width,\r
152   IN        UINT64                    Address,\r
153   IN CONST  VOID                      *SetBits,\r
154   IN CONST  VOID                      *ClearBits\r
155 );\r
156 \r
157 \r
158 \r
159 /**\r
160   @par Ppi Description:\r
161   The EFI_PEI_PCI_CFG2_PPI interfaces are used to abstract\r
162   accesses to PCI controllers behind a PCI root bridge\r
163   controller.\r
164 \r
165   @param Read     PCI read services.  See the Read() function description.\r
166 \r
167   @param Write    PCI write services.  See the Write() function description.\r
168 \r
169   @param Modify   PCI read-modify-write services.  See the Modify() function description.\r
170 \r
171   @param Segment  The PCI bus segment which the specified functions will access.\r
172 \r
173 **/\r
174 GLOBAL_REMOVE_IF_UNREFERENCED\r
175 EFI_PEI_PCI_CFG2_PPI gPciCfg2Ppi = {\r
176   PciCfg2Read,\r
177   PciCfg2Write,\r
178   PciCfg2Modify\r
179 };\r
180 \r
181 GLOBAL_REMOVE_IF_UNREFERENCED\r
182 EFI_PEI_PPI_DESCRIPTOR gPciCfg2PpiList = {\r
183   (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
184   &gEfiPciCfg2PpiGuid,\r
185   &gPciCfg2Ppi\r
186 };\r
187 \r
188 /**\r
189   Reads from a given location in the PCI configuration space.\r
190 \r
191   @param  PeiServices     An indirect pointer to the PEI Services Table published by the PEI Foundation.\r
192 \r
193   @param  This            Pointer to local data for the interface.\r
194 \r
195   @param  Width           The width of the access. Enumerated in bytes.\r
196                           See EFI_PEI_PCI_CFG_PPI_WIDTH above.\r
197 \r
198   @param  Address         The physical address of the access. The format of\r
199                           the address is described by EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS.\r
200 \r
201   @param  Buffer          A pointer to the buffer of data..\r
202 \r
203 \r
204   @retval EFI_SUCCESS           The function completed successfully.\r
205 \r
206   @retval EFI_DEVICE_ERROR      There was a problem with the transaction.\r
207 \r
208   @retval EFI_DEVICE_NOT_READY  The device is not capable of supporting the operation at this\r
209                                 time.\r
210 \r
211 **/\r
212 EFI_STATUS\r
213 EFIAPI\r
214 PciCfg2Read (\r
215   IN CONST  EFI_PEI_SERVICES          **PeiServices,\r
216   IN CONST  EFI_PEI_PCI_CFG2_PPI      *This,\r
217   IN        EFI_PEI_PCI_CFG_PPI_WIDTH Width,\r
218   IN        UINT64                    Address,\r
219   IN OUT    VOID                      *Buffer\r
220 )\r
221 {\r
222   UINTN  PciLibAddress;\r
223 \r
224   PciLibAddress = PciCfgAddressConvert ((EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS *) &Address);\r
225 \r
226   if (Width == EfiPeiPciCfgWidthUint8) {\r
227     *((UINT8 *) Buffer) = PciRead8 (PciLibAddress);\r
228   } else if (Width == EfiPeiPciCfgWidthUint16) {\r
229     *((UINT16 *) Buffer) = PciRead16 (PciLibAddress);\r
230   } else if (Width == EfiPeiPciCfgWidthUint32) {\r
231     *((UINT32 *) Buffer) = PciRead32 (PciLibAddress);\r
232   } else {\r
233     return EFI_INVALID_PARAMETER;\r
234   }\r
235 \r
236   return EFI_SUCCESS;\r
237 }\r
238 \r
239 /**\r
240   Write to a given location in the PCI configuration space.\r
241 \r
242   @param  PeiServices     An indirect pointer to the PEI Services Table published by the PEI Foundation.\r
243 \r
244   @param  This            Pointer to local data for the interface.\r
245 \r
246   @param  Width           The width of the access. Enumerated in bytes.\r
247                           See EFI_PEI_PCI_CFG_PPI_WIDTH above.\r
248 \r
249   @param  Address         The physical address of the access. The format of\r
250                           the address is described by EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS.\r
251 \r
252   @param  Buffer          A pointer to the buffer of data..\r
253 \r
254 \r
255   @retval EFI_SUCCESS           The function completed successfully.\r
256 \r
257   @retval EFI_DEVICE_ERROR      There was a problem with the transaction.\r
258 \r
259   @retval EFI_DEVICE_NOT_READY  The device is not capable of supporting the operation at this\r
260                                 time.\r
261 \r
262 **/\r
263 EFI_STATUS\r
264 EFIAPI\r
265 PciCfg2Write (\r
266   IN CONST  EFI_PEI_SERVICES          **PeiServices,\r
267   IN CONST  EFI_PEI_PCI_CFG2_PPI      *This,\r
268   IN        EFI_PEI_PCI_CFG_PPI_WIDTH Width,\r
269   IN        UINT64                    Address,\r
270   IN OUT    VOID                      *Buffer\r
271 )\r
272 {\r
273   UINTN  PciLibAddress;\r
274 \r
275   PciLibAddress = PciCfgAddressConvert ((EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS *) &Address);\r
276 \r
277   if (Width == EfiPeiPciCfgWidthUint8) {\r
278     PciWrite8 (PciLibAddress, *((UINT8 *) Buffer));\r
279   } else if (Width == EfiPeiPciCfgWidthUint16) {\r
280     PciWrite16 (PciLibAddress, *((UINT16 *) Buffer));\r
281   } else if (Width == EfiPeiPciCfgWidthUint32) {\r
282     PciWrite32 (PciLibAddress, *((UINT32 *) Buffer));\r
283   } else {\r
284     return EFI_INVALID_PARAMETER;\r
285   }\r
286 \r
287   return EFI_SUCCESS;\r
288 }\r
289 \r
290 \r
291 /**\r
292   PCI read-modify-write operation.\r
293 \r
294   @param  PeiServices     An indirect pointer to the PEI Services Table\r
295                           published by the PEI Foundation.\r
296 \r
297   @param  This            Pointer to local data for the interface.\r
298 \r
299   @param  Width           The width of the access. Enumerated in bytes. Type\r
300                           EFI_PEI_PCI_CFG_PPI_WIDTH is defined in Read().\r
301 \r
302   @param  Address         The physical address of the access.\r
303 \r
304   @param  SetBits         Points to value to bitwise-OR with the read configuration value.\r
305 \r
306                           The size of the value is determined by Width.\r
307 \r
308   @param  ClearBits       Points to the value to negate and bitwise-AND with the read configuration value.\r
309                           The size of the value is determined by Width.\r
310 \r
311 \r
312   @retval EFI_SUCCESS           The function completed successfully.\r
313 \r
314   @retval EFI_DEVICE_ERROR      There was a problem with the transaction.\r
315 \r
316   @retval EFI_DEVICE_NOT_READY  The device is not capable of supporting\r
317                                 the operation at this time.\r
318 \r
319 **/\r
320 EFI_STATUS\r
321 EFIAPI\r
322 PciCfg2Modify (\r
323   IN CONST  EFI_PEI_SERVICES          **PeiServices,\r
324   IN CONST  EFI_PEI_PCI_CFG2_PPI      *This,\r
325   IN        EFI_PEI_PCI_CFG_PPI_WIDTH Width,\r
326   IN        UINT64                    Address,\r
327   IN        VOID                      *SetBits,\r
328   IN        VOID                      *ClearBits\r
329 )\r
330 {\r
331   UINTN   PciLibAddress;\r
332   UINT16  ClearValue16;\r
333   UINT16  SetValue16;\r
334   UINT32  ClearValue32;\r
335   UINT32  SetValue32;\r
336 \r
337   PciLibAddress = PciCfgAddressConvert ((EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS *) &Address);\r
338 \r
339   if (Width == EfiPeiPciCfgWidthUint8) {\r
340     PciAndThenOr8 (PciLibAddress, (UINT8) (~(*(UINT8 *) ClearBits)), *((UINT8 *) SetBits));\r
341   } else if (Width == EfiPeiPciCfgWidthUint16) {\r
342     ClearValue16  = (UINT16) (~ReadUnaligned16 ((UINT16 *) ClearBits));\r
343     SetValue16    = ReadUnaligned16 ((UINT16 *) SetBits);\r
344     PciAndThenOr16 (PciLibAddress, ClearValue16, SetValue16);\r
345   } else if (Width == EfiPeiPciCfgWidthUint32) {\r
346     ClearValue32  = (UINT32) (~ReadUnaligned32 ((UINT32 *) ClearBits));\r
347     SetValue32    = ReadUnaligned32 ((UINT32 *) SetBits);\r
348     PciAndThenOr32 (PciLibAddress, ClearValue32, SetValue32);\r
349   } else {\r
350     return EFI_INVALID_PARAMETER;\r
351   }\r
352   return EFI_SUCCESS;\r
353 }\r
354 \r
355 \r
356 EFI_STATUS\r
357 EFIAPI\r
358 PeimInitializePciCfg (\r
359   IN EFI_FFS_FILE_HEADER       *FfsHeader,\r
360   IN EFI_PEI_SERVICES          **PeiServices\r
361   )\r
362 {\r
363   EFI_STATUS            Status;\r
364 \r
365   ASSERT ((**PeiServices).Hdr.Revision >= PEI_SERVICES_REVISION);\r
366 \r
367   (**PeiServices).PciCfg = &gPciCfg2Ppi;\r
368   Status = (**PeiServices).InstallPpi ((CONST EFI_PEI_SERVICES **)PeiServices, &gPciCfg2PpiList);\r
369 \r
370   return Status;\r
371 }\r