]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/PcatSingleSegmentPciCfg2Pei/PciCfg2.c
code scrub ArpDxe
[mirror_edk2.git] / MdeModulePkg / Universal / PcatSingleSegmentPciCfg2Pei / PciCfg2.c
CommitLineData
fb0b259e 1/** @file\r
2 Installs Single Segment Pci Configuration PPI.\r
12232778 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
2d85ada2 24#include <IndustryStandard/Pci.h>\r
12232778 25\r
12232778 26/**\r
27 Reads from a given location in the PCI configuration space.\r
28\r
29 @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.\r
30\r
31 @param This Pointer to local data for the interface.\r
32\r
33 @param Width The width of the access. Enumerated in bytes.\r
34 See EFI_PEI_PCI_CFG_PPI_WIDTH above.\r
35\r
36 @param Address The physical address of the access. The format of\r
37 the address is described by EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS.\r
38\r
39 @param Buffer A pointer to the buffer of data..\r
40\r
41\r
42 @retval EFI_SUCCESS The function completed successfully.\r
43\r
44 @retval EFI_DEVICE_ERROR There was a problem with the transaction.\r
45\r
46 @retval EFI_DEVICE_NOT_READY The device is not capable of supporting the operation at this\r
47 time.\r
48\r
49**/\r
50EFI_STATUS\r
fb0b259e 51EFIAPI\r
12232778 52PciCfg2Read (\r
53 IN CONST EFI_PEI_SERVICES **PeiServices,\r
54 IN CONST EFI_PEI_PCI_CFG2_PPI *This,\r
55 IN EFI_PEI_PCI_CFG_PPI_WIDTH Width,\r
56 IN UINT64 Address,\r
57 IN OUT VOID *Buffer\r
cebc8d48 58 );\r
12232778 59\r
60/**\r
61 Write to a given location in the PCI configuration space.\r
62\r
63 @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.\r
64\r
65 @param This Pointer to local data for the interface.\r
66\r
67 @param Width The width of the access. Enumerated in bytes.\r
68 See EFI_PEI_PCI_CFG_PPI_WIDTH above.\r
69\r
70 @param Address The physical address of the access. The format of\r
71 the address is described by EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS.\r
72\r
73 @param Buffer A pointer to the buffer of data..\r
74\r
75\r
76 @retval EFI_SUCCESS The function completed successfully.\r
77\r
78 @retval EFI_DEVICE_ERROR There was a problem with the transaction.\r
79\r
80 @retval EFI_DEVICE_NOT_READY The device is not capable of supporting the operation at this\r
81 time.\r
82\r
83**/\r
84EFI_STATUS\r
fb0b259e 85EFIAPI\r
12232778 86PciCfg2Write (\r
87 IN CONST EFI_PEI_SERVICES **PeiServices,\r
88 IN CONST EFI_PEI_PCI_CFG2_PPI *This,\r
89 IN EFI_PEI_PCI_CFG_PPI_WIDTH Width,\r
90 IN UINT64 Address,\r
91 IN OUT VOID *Buffer\r
cebc8d48 92 );\r
12232778 93\r
94\r
95/**\r
96 PCI read-modify-write operation.\r
97\r
98 @param PeiServices An indirect pointer to the PEI Services Table\r
99 published by the PEI Foundation.\r
100\r
101 @param This Pointer to local data for the interface.\r
102\r
103 @param Width The width of the access. Enumerated in bytes. Type\r
104 EFI_PEI_PCI_CFG_PPI_WIDTH is defined in Read().\r
105\r
106 @param Address The physical address of the access.\r
107\r
108 @param SetBits Points to value to bitwise-OR with the read configuration value.\r
109\r
110 The size of the value is determined by Width.\r
111\r
112 @param ClearBits Points to the value to negate and bitwise-AND with the read configuration value.\r
113 The size of the value is determined by Width.\r
114\r
115\r
116 @retval EFI_SUCCESS The function completed successfully.\r
117\r
118 @retval EFI_DEVICE_ERROR There was a problem with the transaction.\r
119\r
120 @retval EFI_DEVICE_NOT_READY The device is not capable of supporting\r
121 the operation at this time.\r
122\r
123**/\r
124EFI_STATUS\r
fb0b259e 125EFIAPI\r
12232778 126PciCfg2Modify (\r
127 IN CONST EFI_PEI_SERVICES **PeiServices,\r
128 IN CONST EFI_PEI_PCI_CFG2_PPI *This,\r
129 IN EFI_PEI_PCI_CFG_PPI_WIDTH Width,\r
130 IN UINT64 Address,\r
6fc2b00b 131 IN VOID *SetBits,\r
132 IN VOID *ClearBits\r
cebc8d48 133 );\r
12232778 134\r
135\r
136\r
137/**\r
138 @par Ppi Description:\r
139 The EFI_PEI_PCI_CFG2_PPI interfaces are used to abstract\r
140 accesses to PCI controllers behind a PCI root bridge\r
141 controller.\r
142\r
143 @param Read PCI read services. See the Read() function description.\r
144\r
145 @param Write PCI write services. See the Write() function description.\r
146\r
147 @param Modify PCI read-modify-write services. See the Modify() function description.\r
148\r
149 @param Segment The PCI bus segment which the specified functions will access.\r
150\r
151**/\r
152GLOBAL_REMOVE_IF_UNREFERENCED\r
153EFI_PEI_PCI_CFG2_PPI gPciCfg2Ppi = {\r
154 PciCfg2Read,\r
155 PciCfg2Write,\r
156 PciCfg2Modify\r
157};\r
158\r
159GLOBAL_REMOVE_IF_UNREFERENCED\r
160EFI_PEI_PPI_DESCRIPTOR gPciCfg2PpiList = {\r
161 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
162 &gEfiPciCfg2PpiGuid,\r
163 &gPciCfg2Ppi\r
164};\r
165\r
aa79b0b3 166\r
167/**\r
168 Convert EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS to PCI_LIB_ADDRESS.\r
169\r
170 @param Address PCI address with\r
171 EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS format.\r
172\r
173 @return The PCI address with PCI_LIB_ADDRESS format.\r
174\r
175**/\r
176UINTN\r
177PciCfgAddressConvert (\r
178 EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS *Address\r
179 )\r
180{\r
181 if (Address->ExtendedRegister == 0) {\r
182 return PCI_LIB_ADDRESS (Address->Bus, Address->Device, Address->Function, Address->Register);\r
183 }\r
184\r
185 return PCI_LIB_ADDRESS (Address->Bus, Address->Device, Address->Function, Address->ExtendedRegister);\r
186}\r
187\r
188\r
12232778 189/**\r
190 Reads from a given location in the PCI configuration space.\r
191\r
192 @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.\r
193\r
194 @param This Pointer to local data for the interface.\r
195\r
196 @param Width The width of the access. Enumerated in bytes.\r
197 See EFI_PEI_PCI_CFG_PPI_WIDTH above.\r
198\r
199 @param Address The physical address of the access. The format of\r
200 the address is described by EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS.\r
201\r
202 @param Buffer A pointer to the buffer of data..\r
203\r
204\r
205 @retval EFI_SUCCESS The function completed successfully.\r
206\r
207 @retval EFI_DEVICE_ERROR There was a problem with the transaction.\r
208\r
209 @retval EFI_DEVICE_NOT_READY The device is not capable of supporting the operation at this\r
210 time.\r
211\r
212**/\r
213EFI_STATUS\r
fb0b259e 214EFIAPI\r
12232778 215PciCfg2Read (\r
216 IN CONST EFI_PEI_SERVICES **PeiServices,\r
217 IN CONST EFI_PEI_PCI_CFG2_PPI *This,\r
218 IN EFI_PEI_PCI_CFG_PPI_WIDTH Width,\r
219 IN UINT64 Address,\r
220 IN OUT VOID *Buffer\r
cebc8d48 221 )\r
12232778 222{\r
223 UINTN PciLibAddress;\r
224\r
d8b61daa 225 PciLibAddress = PciCfgAddressConvert ((EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS *) &Address);\r
12232778 226\r
227 if (Width == EfiPeiPciCfgWidthUint8) {\r
228 *((UINT8 *) Buffer) = PciRead8 (PciLibAddress);\r
229 } else if (Width == EfiPeiPciCfgWidthUint16) {\r
8501ba4c
LG
230 if ((PciLibAddress & 0x01) == 0) {\r
231 //\r
232 // Aligned Pci address access\r
233 //\r
234 WriteUnaligned16 (((UINT16 *) Buffer), PciRead16 (PciLibAddress));\r
235 } else {\r
236 //\r
237 // Unaligned Pci address access, break up the request into byte by byte.\r
238 //\r
239 *((UINT8 *) Buffer) = PciRead8 (PciLibAddress);\r
240 *((UINT8 *) Buffer + 1) = PciRead8 (PciLibAddress + 1);\r
241 }\r
12232778 242 } else if (Width == EfiPeiPciCfgWidthUint32) {\r
8501ba4c
LG
243 if ((PciLibAddress & 0x03) == 0) {\r
244 //\r
245 // Aligned Pci address access\r
246 //\r
247 WriteUnaligned32 (((UINT32 *) Buffer), PciRead32 (PciLibAddress));\r
248 } else if ((PciLibAddress & 0x01) == 0) {\r
249 //\r
250 // Unaligned Pci address access, break up the request into word by word.\r
251 //\r
252 WriteUnaligned16 (((UINT16 *) Buffer), PciRead16 (PciLibAddress));\r
253 WriteUnaligned16 (((UINT16 *) Buffer + 1), PciRead16 (PciLibAddress + 2));\r
254 } else {\r
255 //\r
256 // Unaligned Pci address access, break up the request into byte by byte.\r
257 //\r
258 *((UINT8 *) Buffer) = PciRead8 (PciLibAddress);\r
259 *((UINT8 *) Buffer + 1) = PciRead8 (PciLibAddress + 1);\r
260 *((UINT8 *) Buffer + 2) = PciRead8 (PciLibAddress + 2);\r
261 *((UINT8 *) Buffer + 3) = PciRead8 (PciLibAddress + 3);\r
262 }\r
12232778 263 } else {\r
264 return EFI_INVALID_PARAMETER;\r
265 }\r
266\r
267 return EFI_SUCCESS;\r
268}\r
269\r
270/**\r
271 Write to a given location in the PCI configuration space.\r
272\r
273 @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.\r
274\r
275 @param This Pointer to local data for the interface.\r
276\r
277 @param Width The width of the access. Enumerated in bytes.\r
278 See EFI_PEI_PCI_CFG_PPI_WIDTH above.\r
279\r
280 @param Address The physical address of the access. The format of\r
281 the address is described by EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS.\r
282\r
283 @param Buffer A pointer to the buffer of data..\r
284\r
285\r
286 @retval EFI_SUCCESS The function completed successfully.\r
287\r
288 @retval EFI_DEVICE_ERROR There was a problem with the transaction.\r
289\r
290 @retval EFI_DEVICE_NOT_READY The device is not capable of supporting the operation at this\r
291 time.\r
292\r
293**/\r
294EFI_STATUS\r
fb0b259e 295EFIAPI\r
12232778 296PciCfg2Write (\r
297 IN CONST EFI_PEI_SERVICES **PeiServices,\r
298 IN CONST EFI_PEI_PCI_CFG2_PPI *This,\r
299 IN EFI_PEI_PCI_CFG_PPI_WIDTH Width,\r
300 IN UINT64 Address,\r
301 IN OUT VOID *Buffer\r
cebc8d48 302 )\r
12232778 303{\r
304 UINTN PciLibAddress;\r
305\r
d8b61daa 306 PciLibAddress = PciCfgAddressConvert ((EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS *) &Address);\r
12232778 307\r
308 if (Width == EfiPeiPciCfgWidthUint8) {\r
309 PciWrite8 (PciLibAddress, *((UINT8 *) Buffer));\r
310 } else if (Width == EfiPeiPciCfgWidthUint16) {\r
8501ba4c
LG
311 if ((PciLibAddress & 0x01) == 0) {\r
312 //\r
313 // Aligned Pci address access\r
314 //\r
315 PciWrite16 (PciLibAddress, ReadUnaligned16 ((UINT16 *) Buffer));\r
316 } else {\r
317 //\r
318 // Unaligned Pci address access, break up the request into byte by byte.\r
319 //\r
320 PciWrite8 (PciLibAddress, *((UINT8 *) Buffer));\r
321 PciWrite8 (PciLibAddress + 1, *((UINT8 *) Buffer + 1)); \r
322 }\r
12232778 323 } else if (Width == EfiPeiPciCfgWidthUint32) {\r
8501ba4c
LG
324 if ((PciLibAddress & 0x03) == 0) {\r
325 //\r
326 // Aligned Pci address access\r
327 //\r
328 PciWrite32 (PciLibAddress, ReadUnaligned32 ((UINT32 *) Buffer));\r
329 } else if ((PciLibAddress & 0x01) == 0) {\r
330 //\r
331 // Unaligned Pci address access, break up the request into word by word.\r
332 //\r
333 PciWrite16 (PciLibAddress, ReadUnaligned16 ((UINT16 *) Buffer));\r
334 PciWrite16 (PciLibAddress + 2, ReadUnaligned16 ((UINT16 *) Buffer + 1));\r
335 } else {\r
336 //\r
337 // Unaligned Pci address access, break up the request into byte by byte.\r
338 //\r
339 PciWrite8 (PciLibAddress, *((UINT8 *) Buffer));\r
340 PciWrite8 (PciLibAddress + 1, *((UINT8 *) Buffer + 1)); \r
341 PciWrite8 (PciLibAddress + 2, *((UINT8 *) Buffer + 2)); \r
342 PciWrite8 (PciLibAddress + 3, *((UINT8 *) Buffer + 3)); \r
343 }\r
12232778 344 } else {\r
345 return EFI_INVALID_PARAMETER;\r
346 }\r
347\r
348 return EFI_SUCCESS;\r
349}\r
350\r
351\r
352/**\r
353 PCI read-modify-write operation.\r
354\r
355 @param PeiServices An indirect pointer to the PEI Services Table\r
356 published by the PEI Foundation.\r
357\r
358 @param This Pointer to local data for the interface.\r
359\r
360 @param Width The width of the access. Enumerated in bytes. Type\r
361 EFI_PEI_PCI_CFG_PPI_WIDTH is defined in Read().\r
362\r
363 @param Address The physical address of the access.\r
364\r
365 @param SetBits Points to value to bitwise-OR with the read configuration value.\r
366\r
367 The size of the value is determined by Width.\r
368\r
369 @param ClearBits Points to the value to negate and bitwise-AND with the read configuration value.\r
370 The size of the value is determined by Width.\r
371\r
372\r
373 @retval EFI_SUCCESS The function completed successfully.\r
374\r
375 @retval EFI_DEVICE_ERROR There was a problem with the transaction.\r
376\r
377 @retval EFI_DEVICE_NOT_READY The device is not capable of supporting\r
378 the operation at this time.\r
379\r
380**/\r
381EFI_STATUS\r
fb0b259e 382EFIAPI\r
12232778 383PciCfg2Modify (\r
384 IN CONST EFI_PEI_SERVICES **PeiServices,\r
385 IN CONST EFI_PEI_PCI_CFG2_PPI *This,\r
386 IN EFI_PEI_PCI_CFG_PPI_WIDTH Width,\r
387 IN UINT64 Address,\r
01edaf2a 388 IN VOID *SetBits,\r
389 IN VOID *ClearBits\r
cebc8d48 390 )\r
12232778 391{\r
702887db 392 UINTN PciLibAddress;\r
393 UINT16 ClearValue16;\r
394 UINT16 SetValue16;\r
395 UINT32 ClearValue32;\r
396 UINT32 SetValue32;\r
12232778 397\r
d8b61daa 398 PciLibAddress = PciCfgAddressConvert ((EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS *) &Address);\r
12232778 399\r
400 if (Width == EfiPeiPciCfgWidthUint8) {\r
702887db 401 PciAndThenOr8 (PciLibAddress, (UINT8) (~(*(UINT8 *) ClearBits)), *((UINT8 *) SetBits));\r
12232778 402 } else if (Width == EfiPeiPciCfgWidthUint16) {\r
8501ba4c
LG
403 if ((PciLibAddress & 0x01) == 0) {\r
404 //\r
405 // Aligned Pci address access\r
406 //\r
407 ClearValue16 = (UINT16) (~ReadUnaligned16 ((UINT16 *) ClearBits));\r
408 SetValue16 = ReadUnaligned16 ((UINT16 *) SetBits);\r
409 PciAndThenOr16 (PciLibAddress, ClearValue16, SetValue16);\r
410 } else {\r
411 //\r
412 // Unaligned Pci address access, break up the request into byte by byte.\r
413 //\r
414 PciAndThenOr8 (PciLibAddress, (UINT8) (~(*(UINT8 *) ClearBits)), *((UINT8 *) SetBits));\r
415 PciAndThenOr8 (PciLibAddress + 1, (UINT8) (~(*((UINT8 *) ClearBits + 1))), *((UINT8 *) SetBits + 1));\r
416 }\r
12232778 417 } else if (Width == EfiPeiPciCfgWidthUint32) {\r
8501ba4c
LG
418 if ((PciLibAddress & 0x03) == 0) {\r
419 //\r
420 // Aligned Pci address access\r
421 //\r
422 ClearValue32 = (UINT32) (~ReadUnaligned32 ((UINT32 *) ClearBits));\r
423 SetValue32 = ReadUnaligned32 ((UINT32 *) SetBits);\r
424 PciAndThenOr32 (PciLibAddress, ClearValue32, SetValue32);\r
425 } else if ((PciLibAddress & 0x01) == 0) {\r
426 //\r
427 // Unaligned Pci address access, break up the request into word by word.\r
428 //\r
429 ClearValue16 = (UINT16) (~ReadUnaligned16 ((UINT16 *) ClearBits));\r
430 SetValue16 = ReadUnaligned16 ((UINT16 *) SetBits);\r
431 PciAndThenOr16 (PciLibAddress, ClearValue16, SetValue16);\r
432\r
433 ClearValue16 = (UINT16) (~ReadUnaligned16 ((UINT16 *) ClearBits + 1));\r
434 SetValue16 = ReadUnaligned16 ((UINT16 *) SetBits + 1);\r
435 PciAndThenOr16 (PciLibAddress + 2, ClearValue16, SetValue16);\r
436 } else {\r
437 //\r
438 // Unaligned Pci address access, break up the request into byte by byte.\r
439 //\r
440 PciAndThenOr8 (PciLibAddress, (UINT8) (~(*(UINT8 *) ClearBits)), *((UINT8 *) SetBits));\r
441 PciAndThenOr8 (PciLibAddress + 1, (UINT8) (~(*((UINT8 *) ClearBits + 1))), *((UINT8 *) SetBits + 1));\r
442 PciAndThenOr8 (PciLibAddress + 2, (UINT8) (~(*((UINT8 *) ClearBits + 2))), *((UINT8 *) SetBits + 2));\r
443 PciAndThenOr8 (PciLibAddress + 3, (UINT8) (~(*((UINT8 *) ClearBits + 3))), *((UINT8 *) SetBits + 3));\r
444 }\r
12232778 445 } else {\r
446 return EFI_INVALID_PARAMETER;\r
447 }\r
448 return EFI_SUCCESS;\r
449}\r
450\r
cebc8d48
LG
451/**\r
452 Module's entry function. \r
453 This routine will install EFI_PEI_PCI_CFG2_PPI.\r
454 \r
455 @param FileHandle Handle of the file being invoked.\r
456 @param PeiServices Describes the list of possible PEI Services.\r
12232778 457\r
cebc8d48
LG
458 @return Whether success to install service.\r
459**/\r
12232778 460EFI_STATUS\r
461EFIAPI\r
462PeimInitializePciCfg (\r
8bd22b8a
LG
463 IN EFI_PEI_FILE_HANDLE FileHandle,\r
464 IN CONST EFI_PEI_SERVICES **PeiServices\r
12232778 465 )\r
466{\r
467 EFI_STATUS Status;\r
468\r
469 ASSERT ((**PeiServices).Hdr.Revision >= PEI_SERVICES_REVISION);\r
470\r
8bd22b8a 471 (**(EFI_PEI_SERVICES **)PeiServices).PciCfg = &gPciCfg2Ppi;\r
0c2b5da8 472 Status = (**PeiServices).InstallPpi ((CONST EFI_PEI_SERVICES **)PeiServices, &gPciCfg2PpiList);\r
12232778 473\r
474 return Status;\r
475}\r