2 Installs Single Segment Pci Configuration PPI.
4 Copyright (c) 2006 - 2007, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include <Ppi/PciCfg2.h>
19 #include <Library/BaseLib.h>
20 #include <Library/DebugLib.h>
21 #include <Library/PciLib.h>
22 #include <Library/PeimEntryPoint.h>
24 #include <IndustryStandard/Pci.h>
27 Reads from a given location in the PCI configuration space.
29 @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.
31 @param This Pointer to local data for the interface.
33 @param Width The width of the access. Enumerated in bytes.
34 See EFI_PEI_PCI_CFG_PPI_WIDTH above.
36 @param Address The physical address of the access. The format of
37 the address is described by EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS.
39 @param Buffer A pointer to the buffer of data..
42 @retval EFI_SUCCESS The function completed successfully.
44 @retval EFI_DEVICE_ERROR There was a problem with the transaction.
46 @retval EFI_DEVICE_NOT_READY The device is not capable of supporting the operation at this
53 IN CONST EFI_PEI_SERVICES
**PeiServices
,
54 IN CONST EFI_PEI_PCI_CFG2_PPI
*This
,
55 IN EFI_PEI_PCI_CFG_PPI_WIDTH Width
,
61 Write to a given location in the PCI configuration space.
63 @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.
65 @param This Pointer to local data for the interface.
67 @param Width The width of the access. Enumerated in bytes.
68 See EFI_PEI_PCI_CFG_PPI_WIDTH above.
70 @param Address The physical address of the access. The format of
71 the address is described by EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS.
73 @param Buffer A pointer to the buffer of data..
76 @retval EFI_SUCCESS The function completed successfully.
78 @retval EFI_DEVICE_ERROR There was a problem with the transaction.
80 @retval EFI_DEVICE_NOT_READY The device is not capable of supporting the operation at this
87 IN CONST EFI_PEI_SERVICES
**PeiServices
,
88 IN CONST EFI_PEI_PCI_CFG2_PPI
*This
,
89 IN EFI_PEI_PCI_CFG_PPI_WIDTH Width
,
96 PCI read-modify-write operation.
98 @param PeiServices An indirect pointer to the PEI Services Table
99 published by the PEI Foundation.
101 @param This Pointer to local data for the interface.
103 @param Width The width of the access. Enumerated in bytes. Type
104 EFI_PEI_PCI_CFG_PPI_WIDTH is defined in Read().
106 @param Address The physical address of the access.
108 @param SetBits Points to value to bitwise-OR with the read configuration value.
110 The size of the value is determined by Width.
112 @param ClearBits Points to the value to negate and bitwise-AND with the read configuration value.
113 The size of the value is determined by Width.
116 @retval EFI_SUCCESS The function completed successfully.
118 @retval EFI_DEVICE_ERROR There was a problem with the transaction.
120 @retval EFI_DEVICE_NOT_READY The device is not capable of supporting
121 the operation at this time.
127 IN CONST EFI_PEI_SERVICES
**PeiServices
,
128 IN CONST EFI_PEI_PCI_CFG2_PPI
*This
,
129 IN EFI_PEI_PCI_CFG_PPI_WIDTH Width
,
138 @par Ppi Description:
139 The EFI_PEI_PCI_CFG2_PPI interfaces are used to abstract
140 accesses to PCI controllers behind a PCI root bridge
143 @param Read PCI read services. See the Read() function description.
145 @param Write PCI write services. See the Write() function description.
147 @param Modify PCI read-modify-write services. See the Modify() function description.
149 @param Segment The PCI bus segment which the specified functions will access.
152 GLOBAL_REMOVE_IF_UNREFERENCED
153 EFI_PEI_PCI_CFG2_PPI gPciCfg2Ppi
= {
159 GLOBAL_REMOVE_IF_UNREFERENCED
160 EFI_PEI_PPI_DESCRIPTOR gPciCfg2PpiList
= {
161 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
168 Convert EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS to PCI_LIB_ADDRESS.
170 @param Address PCI address with
171 EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS format.
173 @return The PCI address with PCI_LIB_ADDRESS format.
177 PciCfgAddressConvert (
178 EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS
*Address
181 if (Address
->ExtendedRegister
== 0) {
182 return PCI_LIB_ADDRESS (Address
->Bus
, Address
->Device
, Address
->Function
, Address
->Register
);
185 return PCI_LIB_ADDRESS (Address
->Bus
, Address
->Device
, Address
->Function
, Address
->ExtendedRegister
);
190 Reads from a given location in the PCI configuration space.
192 @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.
194 @param This Pointer to local data for the interface.
196 @param Width The width of the access. Enumerated in bytes.
197 See EFI_PEI_PCI_CFG_PPI_WIDTH above.
199 @param Address The physical address of the access. The format of
200 the address is described by EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS.
202 @param Buffer A pointer to the buffer of data..
205 @retval EFI_SUCCESS The function completed successfully.
207 @retval EFI_DEVICE_ERROR There was a problem with the transaction.
209 @retval EFI_DEVICE_NOT_READY The device is not capable of supporting the operation at this
216 IN CONST EFI_PEI_SERVICES
**PeiServices
,
217 IN CONST EFI_PEI_PCI_CFG2_PPI
*This
,
218 IN EFI_PEI_PCI_CFG_PPI_WIDTH Width
,
225 PciLibAddress
= PciCfgAddressConvert ((EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS
*) &Address
);
227 if (Width
== EfiPeiPciCfgWidthUint8
) {
228 *((UINT8
*) Buffer
) = PciRead8 (PciLibAddress
);
229 } else if (Width
== EfiPeiPciCfgWidthUint16
) {
230 if ((PciLibAddress
& 0x01) == 0) {
232 // Aligned Pci address access
234 WriteUnaligned16 (((UINT16
*) Buffer
), PciRead16 (PciLibAddress
));
237 // Unaligned Pci address access, break up the request into byte by byte.
239 *((UINT8
*) Buffer
) = PciRead8 (PciLibAddress
);
240 *((UINT8
*) Buffer
+ 1) = PciRead8 (PciLibAddress
+ 1);
242 } else if (Width
== EfiPeiPciCfgWidthUint32
) {
243 if ((PciLibAddress
& 0x03) == 0) {
245 // Aligned Pci address access
247 WriteUnaligned32 (((UINT32
*) Buffer
), PciRead32 (PciLibAddress
));
248 } else if ((PciLibAddress
& 0x01) == 0) {
250 // Unaligned Pci address access, break up the request into word by word.
252 WriteUnaligned16 (((UINT16
*) Buffer
), PciRead16 (PciLibAddress
));
253 WriteUnaligned16 (((UINT16
*) Buffer
+ 1), PciRead16 (PciLibAddress
+ 2));
256 // Unaligned Pci address access, break up the request into byte by byte.
258 *((UINT8
*) Buffer
) = PciRead8 (PciLibAddress
);
259 *((UINT8
*) Buffer
+ 1) = PciRead8 (PciLibAddress
+ 1);
260 *((UINT8
*) Buffer
+ 2) = PciRead8 (PciLibAddress
+ 2);
261 *((UINT8
*) Buffer
+ 3) = PciRead8 (PciLibAddress
+ 3);
264 return EFI_INVALID_PARAMETER
;
271 Write to a given location in the PCI configuration space.
273 @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.
275 @param This Pointer to local data for the interface.
277 @param Width The width of the access. Enumerated in bytes.
278 See EFI_PEI_PCI_CFG_PPI_WIDTH above.
280 @param Address The physical address of the access. The format of
281 the address is described by EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS.
283 @param Buffer A pointer to the buffer of data..
286 @retval EFI_SUCCESS The function completed successfully.
288 @retval EFI_DEVICE_ERROR There was a problem with the transaction.
290 @retval EFI_DEVICE_NOT_READY The device is not capable of supporting the operation at this
297 IN CONST EFI_PEI_SERVICES
**PeiServices
,
298 IN CONST EFI_PEI_PCI_CFG2_PPI
*This
,
299 IN EFI_PEI_PCI_CFG_PPI_WIDTH Width
,
306 PciLibAddress
= PciCfgAddressConvert ((EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS
*) &Address
);
308 if (Width
== EfiPeiPciCfgWidthUint8
) {
309 PciWrite8 (PciLibAddress
, *((UINT8
*) Buffer
));
310 } else if (Width
== EfiPeiPciCfgWidthUint16
) {
311 if ((PciLibAddress
& 0x01) == 0) {
313 // Aligned Pci address access
315 PciWrite16 (PciLibAddress
, ReadUnaligned16 ((UINT16
*) Buffer
));
318 // Unaligned Pci address access, break up the request into byte by byte.
320 PciWrite8 (PciLibAddress
, *((UINT8
*) Buffer
));
321 PciWrite8 (PciLibAddress
+ 1, *((UINT8
*) Buffer
+ 1));
323 } else if (Width
== EfiPeiPciCfgWidthUint32
) {
324 if ((PciLibAddress
& 0x03) == 0) {
326 // Aligned Pci address access
328 PciWrite32 (PciLibAddress
, ReadUnaligned32 ((UINT32
*) Buffer
));
329 } else if ((PciLibAddress
& 0x01) == 0) {
331 // Unaligned Pci address access, break up the request into word by word.
333 PciWrite16 (PciLibAddress
, ReadUnaligned16 ((UINT16
*) Buffer
));
334 PciWrite16 (PciLibAddress
+ 2, ReadUnaligned16 ((UINT16
*) Buffer
+ 1));
337 // Unaligned Pci address access, break up the request into byte by byte.
339 PciWrite8 (PciLibAddress
, *((UINT8
*) Buffer
));
340 PciWrite8 (PciLibAddress
+ 1, *((UINT8
*) Buffer
+ 1));
341 PciWrite8 (PciLibAddress
+ 2, *((UINT8
*) Buffer
+ 2));
342 PciWrite8 (PciLibAddress
+ 3, *((UINT8
*) Buffer
+ 3));
345 return EFI_INVALID_PARAMETER
;
353 PCI read-modify-write operation.
355 @param PeiServices An indirect pointer to the PEI Services Table
356 published by the PEI Foundation.
358 @param This Pointer to local data for the interface.
360 @param Width The width of the access. Enumerated in bytes. Type
361 EFI_PEI_PCI_CFG_PPI_WIDTH is defined in Read().
363 @param Address The physical address of the access.
365 @param SetBits Points to value to bitwise-OR with the read configuration value.
367 The size of the value is determined by Width.
369 @param ClearBits Points to the value to negate and bitwise-AND with the read configuration value.
370 The size of the value is determined by Width.
373 @retval EFI_SUCCESS The function completed successfully.
375 @retval EFI_DEVICE_ERROR There was a problem with the transaction.
377 @retval EFI_DEVICE_NOT_READY The device is not capable of supporting
378 the operation at this time.
384 IN CONST EFI_PEI_SERVICES
**PeiServices
,
385 IN CONST EFI_PEI_PCI_CFG2_PPI
*This
,
386 IN EFI_PEI_PCI_CFG_PPI_WIDTH Width
,
398 PciLibAddress
= PciCfgAddressConvert ((EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS
*) &Address
);
400 if (Width
== EfiPeiPciCfgWidthUint8
) {
401 PciAndThenOr8 (PciLibAddress
, (UINT8
) (~(*(UINT8
*) ClearBits
)), *((UINT8
*) SetBits
));
402 } else if (Width
== EfiPeiPciCfgWidthUint16
) {
403 if ((PciLibAddress
& 0x01) == 0) {
405 // Aligned Pci address access
407 ClearValue16
= (UINT16
) (~ReadUnaligned16 ((UINT16
*) ClearBits
));
408 SetValue16
= ReadUnaligned16 ((UINT16
*) SetBits
);
409 PciAndThenOr16 (PciLibAddress
, ClearValue16
, SetValue16
);
412 // Unaligned Pci address access, break up the request into byte by byte.
414 PciAndThenOr8 (PciLibAddress
, (UINT8
) (~(*(UINT8
*) ClearBits
)), *((UINT8
*) SetBits
));
415 PciAndThenOr8 (PciLibAddress
+ 1, (UINT8
) (~(*((UINT8
*) ClearBits
+ 1))), *((UINT8
*) SetBits
+ 1));
417 } else if (Width
== EfiPeiPciCfgWidthUint32
) {
418 if ((PciLibAddress
& 0x03) == 0) {
420 // Aligned Pci address access
422 ClearValue32
= (UINT32
) (~ReadUnaligned32 ((UINT32
*) ClearBits
));
423 SetValue32
= ReadUnaligned32 ((UINT32
*) SetBits
);
424 PciAndThenOr32 (PciLibAddress
, ClearValue32
, SetValue32
);
425 } else if ((PciLibAddress
& 0x01) == 0) {
427 // Unaligned Pci address access, break up the request into word by word.
429 ClearValue16
= (UINT16
) (~ReadUnaligned16 ((UINT16
*) ClearBits
));
430 SetValue16
= ReadUnaligned16 ((UINT16
*) SetBits
);
431 PciAndThenOr16 (PciLibAddress
, ClearValue16
, SetValue16
);
433 ClearValue16
= (UINT16
) (~ReadUnaligned16 ((UINT16
*) ClearBits
+ 1));
434 SetValue16
= ReadUnaligned16 ((UINT16
*) SetBits
+ 1);
435 PciAndThenOr16 (PciLibAddress
+ 2, ClearValue16
, SetValue16
);
438 // Unaligned Pci address access, break up the request into byte by byte.
440 PciAndThenOr8 (PciLibAddress
, (UINT8
) (~(*(UINT8
*) ClearBits
)), *((UINT8
*) SetBits
));
441 PciAndThenOr8 (PciLibAddress
+ 1, (UINT8
) (~(*((UINT8
*) ClearBits
+ 1))), *((UINT8
*) SetBits
+ 1));
442 PciAndThenOr8 (PciLibAddress
+ 2, (UINT8
) (~(*((UINT8
*) ClearBits
+ 2))), *((UINT8
*) SetBits
+ 2));
443 PciAndThenOr8 (PciLibAddress
+ 3, (UINT8
) (~(*((UINT8
*) ClearBits
+ 3))), *((UINT8
*) SetBits
+ 3));
446 return EFI_INVALID_PARAMETER
;
452 Module's entry function.
453 This routine will install EFI_PEI_PCI_CFG2_PPI.
455 @param FileHandle Handle of the file being invoked.
456 @param PeiServices Describes the list of possible PEI Services.
458 @return Whether success to install service.
462 PeimInitializePciCfg (
463 IN EFI_PEI_FILE_HANDLE FileHandle
,
464 IN CONST EFI_PEI_SERVICES
**PeiServices
469 ASSERT ((**PeiServices
).Hdr
.Revision
>= PEI_SERVICES_REVISION
);
471 (**(EFI_PEI_SERVICES
**)PeiServices
).PciCfg
= &gPciCfg2Ppi
;
472 Status
= (**PeiServices
).InstallPpi ((CONST EFI_PEI_SERVICES
**)PeiServices
, &gPciCfg2PpiList
);