3 Copyright (c) 2006 - 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14 #include "PciCfgInternal.h"
18 The EFI_PEI_PCI_CFG2_PPI interfaces are used to abstract
19 accesses to PCI controllers behind a PCI root bridge
22 @param Read PCI read services. See the Read() function description.
24 @param Write PCI write services. See the Write() function description.
26 @param Modify PCI read-modify-write services. See the Modify() function description.
28 @param Segment The PCI bus segment which the specified functions will access.
31 GLOBAL_REMOVE_IF_UNREFERENCED
32 EFI_PEI_PCI_CFG2_PPI gPciCfg2Ppi
= {
38 GLOBAL_REMOVE_IF_UNREFERENCED
39 EFI_PEI_PPI_DESCRIPTOR gPciCfg2PpiList
= {
40 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
48 The EFI_PEI_PCI_CFG_PPI interfaces are used to abstract accesses to PCI
49 controllers behind a PCI root bridge controller.
51 @param Read PCI read services. See the Read() function description.
53 @param Write PCI write services. See the Write() function description.
55 @param Modify PCI read-modify-write services. See the Modify() function description.
57 @param Segment The PCI bus segment which the specified functions will access.
60 GLOBAL_REMOVE_IF_UNREFERENCED
61 EFI_PEI_PCI_CFG_PPI gPciCfgPpi
= {
67 GLOBAL_REMOVE_IF_UNREFERENCED
68 EFI_PEI_PPI_DESCRIPTOR gPciCfgPpiList
= {
69 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
70 &gEfiPciCfgPpiInServiceTableGuid
,
76 Convert EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS to PCI_LIB_ADDRESS.
78 @param Address PCI address with
79 EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS format.
81 @return The PCI address with PCI_LIB_ADDRESS format.
85 PciCfgAddressConvert (
86 EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS
*Address
89 if (Address
->ExtendedRegister
== 0) {
90 return PCI_LIB_ADDRESS (Address
->Bus
, Address
->Device
, Address
->Function
, Address
->Register
);
93 return PCI_LIB_ADDRESS (Address
->Bus
, Address
->Device
, Address
->Function
, Address
->ExtendedRegister
);
97 Reads from a given location in the PCI configuration space.
99 @param PeiServices An indirect pointer to the PEI Services Table 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.
104 See EFI_PEI_PCI_CFG_PPI_WIDTH above.
106 @param Address The physical address of the access. The format of
107 the address is described by EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS.
109 @param Buffer A pointer to the buffer of data..
112 @retval EFI_SUCCESS The function completed successfully.
114 @retval EFI_DEVICE_ERROR There was a problem with the transaction.
116 @retval EFI_DEVICE_NOT_READY The device is not capable of supporting the operation at this
123 IN CONST EFI_PEI_SERVICES
**PeiServices
,
124 IN CONST EFI_PEI_PCI_CFG2_PPI
*This
,
125 IN EFI_PEI_PCI_CFG_PPI_WIDTH Width
,
132 PciLibAddress
= PciCfgAddressConvert ((EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS
*) &Address
);
134 if (Width
== EfiPeiPciCfgWidthUint8
) {
135 *((UINT8
*) Buffer
) = PciRead8 (PciLibAddress
);
136 } else if (Width
== EfiPeiPciCfgWidthUint16
) {
137 if ((PciLibAddress
& 0x01) == 0) {
139 // Aligned Pci address access
141 WriteUnaligned16 (((UINT16
*) Buffer
), PciRead16 (PciLibAddress
));
144 // Unaligned Pci address access, break up the request into byte by byte.
146 *((UINT8
*) Buffer
) = PciRead8 (PciLibAddress
);
147 *((UINT8
*) Buffer
+ 1) = PciRead8 (PciLibAddress
+ 1);
149 } else if (Width
== EfiPeiPciCfgWidthUint32
) {
150 if ((PciLibAddress
& 0x03) == 0) {
152 // Aligned Pci address access
154 WriteUnaligned32 (((UINT32
*) Buffer
), PciRead32 (PciLibAddress
));
155 } else if ((PciLibAddress
& 0x01) == 0) {
157 // Unaligned Pci address access, break up the request into word by word.
159 WriteUnaligned16 (((UINT16
*) Buffer
), PciRead16 (PciLibAddress
));
160 WriteUnaligned16 (((UINT16
*) Buffer
+ 1), PciRead16 (PciLibAddress
+ 2));
163 // Unaligned Pci address access, break up the request into byte by byte.
165 *((UINT8
*) Buffer
) = PciRead8 (PciLibAddress
);
166 *((UINT8
*) Buffer
+ 1) = PciRead8 (PciLibAddress
+ 1);
167 *((UINT8
*) Buffer
+ 2) = PciRead8 (PciLibAddress
+ 2);
168 *((UINT8
*) Buffer
+ 3) = PciRead8 (PciLibAddress
+ 3);
171 return EFI_INVALID_PARAMETER
;
178 Write to a given location in the PCI configuration space.
180 @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.
182 @param This Pointer to local data for the interface.
184 @param Width The width of the access. Enumerated in bytes.
185 See EFI_PEI_PCI_CFG_PPI_WIDTH above.
187 @param Address The physical address of the access. The format of
188 the address is described by EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS.
190 @param Buffer A pointer to the buffer of data..
193 @retval EFI_SUCCESS The function completed successfully.
195 @retval EFI_DEVICE_ERROR There was a problem with the transaction.
197 @retval EFI_DEVICE_NOT_READY The device is not capable of supporting the operation at this
204 IN CONST EFI_PEI_SERVICES
**PeiServices
,
205 IN CONST EFI_PEI_PCI_CFG2_PPI
*This
,
206 IN EFI_PEI_PCI_CFG_PPI_WIDTH Width
,
213 PciLibAddress
= PciCfgAddressConvert ((EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS
*) &Address
);
215 if (Width
== EfiPeiPciCfgWidthUint8
) {
216 PciWrite8 (PciLibAddress
, *((UINT8
*) Buffer
));
217 } else if (Width
== EfiPeiPciCfgWidthUint16
) {
218 if ((PciLibAddress
& 0x01) == 0) {
220 // Aligned Pci address access
222 PciWrite16 (PciLibAddress
, ReadUnaligned16 ((UINT16
*) Buffer
));
225 // Unaligned Pci address access, break up the request into byte by byte.
227 PciWrite8 (PciLibAddress
, *((UINT8
*) Buffer
));
228 PciWrite8 (PciLibAddress
+ 1, *((UINT8
*) Buffer
+ 1));
230 } else if (Width
== EfiPeiPciCfgWidthUint32
) {
231 if ((PciLibAddress
& 0x03) == 0) {
233 // Aligned Pci address access
235 PciWrite32 (PciLibAddress
, ReadUnaligned32 ((UINT32
*) Buffer
));
236 } else if ((PciLibAddress
& 0x01) == 0) {
238 // Unaligned Pci address access, break up the request into word by word.
240 PciWrite16 (PciLibAddress
, ReadUnaligned16 ((UINT16
*) Buffer
));
241 PciWrite16 (PciLibAddress
+ 2, ReadUnaligned16 ((UINT16
*) Buffer
+ 1));
244 // Unaligned Pci address access, break up the request into byte by byte.
246 PciWrite8 (PciLibAddress
, *((UINT8
*) Buffer
));
247 PciWrite8 (PciLibAddress
+ 1, *((UINT8
*) Buffer
+ 1));
248 PciWrite8 (PciLibAddress
+ 2, *((UINT8
*) Buffer
+ 2));
249 PciWrite8 (PciLibAddress
+ 3, *((UINT8
*) Buffer
+ 3));
252 return EFI_INVALID_PARAMETER
;
260 PCI read-modify-write operation.
262 @param PeiServices An indirect pointer to the PEI Services Table
263 published by the PEI Foundation.
265 @param This Pointer to local data for the interface.
267 @param Width The width of the access. Enumerated in bytes. Type
268 EFI_PEI_PCI_CFG_PPI_WIDTH is defined in Read().
270 @param Address The physical address of the access.
272 @param SetBits Points to value to bitwise-OR with the read configuration value.
274 The size of the value is determined by Width.
276 @param ClearBits Points to the value to negate and bitwise-AND with the read configuration value.
277 The size of the value is determined by Width.
280 @retval EFI_SUCCESS The function completed successfully.
282 @retval EFI_DEVICE_ERROR There was a problem with the transaction.
284 @retval EFI_DEVICE_NOT_READY The device is not capable of supporting
285 the operation at this time.
291 IN CONST EFI_PEI_SERVICES
**PeiServices
,
292 IN CONST EFI_PEI_PCI_CFG2_PPI
*This
,
293 IN EFI_PEI_PCI_CFG_PPI_WIDTH Width
,
305 PciLibAddress
= PciCfgAddressConvert ((EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS
*) &Address
);
307 if (Width
== EfiPeiPciCfgWidthUint8
) {
308 PciAndThenOr8 (PciLibAddress
, (UINT8
) (~(*(UINT8
*) ClearBits
)), *((UINT8
*) SetBits
));
309 } else if (Width
== EfiPeiPciCfgWidthUint16
) {
310 if ((PciLibAddress
& 0x01) == 0) {
312 // Aligned Pci address access
314 ClearValue16
= (UINT16
) (~ReadUnaligned16 ((UINT16
*) ClearBits
));
315 SetValue16
= ReadUnaligned16 ((UINT16
*) SetBits
);
316 PciAndThenOr16 (PciLibAddress
, ClearValue16
, SetValue16
);
319 // Unaligned Pci address access, break up the request into byte by byte.
321 PciAndThenOr8 (PciLibAddress
, (UINT8
) (~(*(UINT8
*) ClearBits
)), *((UINT8
*) SetBits
));
322 PciAndThenOr8 (PciLibAddress
+ 1, (UINT8
) (~(*((UINT8
*) ClearBits
+ 1))), *((UINT8
*) SetBits
+ 1));
324 } else if (Width
== EfiPeiPciCfgWidthUint32
) {
325 if ((PciLibAddress
& 0x03) == 0) {
327 // Aligned Pci address access
329 ClearValue32
= (UINT32
) (~ReadUnaligned32 ((UINT32
*) ClearBits
));
330 SetValue32
= ReadUnaligned32 ((UINT32
*) SetBits
);
331 PciAndThenOr32 (PciLibAddress
, ClearValue32
, SetValue32
);
332 } else if ((PciLibAddress
& 0x01) == 0) {
334 // Unaligned Pci address access, break up the request into word by word.
336 ClearValue16
= (UINT16
) (~ReadUnaligned16 ((UINT16
*) ClearBits
));
337 SetValue16
= ReadUnaligned16 ((UINT16
*) SetBits
);
338 PciAndThenOr16 (PciLibAddress
, ClearValue16
, SetValue16
);
340 ClearValue16
= (UINT16
) (~ReadUnaligned16 ((UINT16
*) ClearBits
+ 1));
341 SetValue16
= ReadUnaligned16 ((UINT16
*) SetBits
+ 1);
342 PciAndThenOr16 (PciLibAddress
+ 2, ClearValue16
, SetValue16
);
345 // Unaligned Pci address access, break up the request into byte by byte.
347 PciAndThenOr8 (PciLibAddress
, (UINT8
) (~(*(UINT8
*) ClearBits
)), *((UINT8
*) SetBits
));
348 PciAndThenOr8 (PciLibAddress
+ 1, (UINT8
) (~(*((UINT8
*) ClearBits
+ 1))), *((UINT8
*) SetBits
+ 1));
349 PciAndThenOr8 (PciLibAddress
+ 2, (UINT8
) (~(*((UINT8
*) ClearBits
+ 2))), *((UINT8
*) SetBits
+ 2));
350 PciAndThenOr8 (PciLibAddress
+ 3, (UINT8
) (~(*((UINT8
*) ClearBits
+ 3))), *((UINT8
*) SetBits
+ 3));
353 return EFI_INVALID_PARAMETER
;
359 Module's entry function.
360 This routine will install EFI_PEI_PCI_CFG2_PPI or EFI_PEI_PCI_CFG_PPI
361 according to PeiServices's version.
363 @param FileHandle Handle of the file being invoked.
364 @param PeiServices Describes the list of possible PEI Services.
366 @return Whether success to install service
370 PeimInitializePciCfg (
371 IN EFI_PEI_FILE_HANDLE FileHandle
,
372 IN CONST EFI_PEI_SERVICES
**PeiServices
377 Status
= EFI_SUCCESS
;
379 if ((**PeiServices
).Hdr
.Revision
< PEI_SERVICES_REVISION
) {
381 // BugBug: Curently, the FrameworkPkg does not define
382 // FRAMEWORK_PEI_SERVICES. So, In order to install
383 // the PeiServices.PciCfg(), we casttype
384 // EFI_PEI_PCI_CFG_PPI to EFI_PEI_PCI_CFG2_PPI.
385 // After defining the FRAMEWORK_PEI_SERVICES. this should
388 // FrameworkPeiServices = (FRAMEWORK_PEI_SERVICES **) PeiServices;
389 // (**FrameworkPeiServices).PciCfg = &mPciCfgPpi;
391 (**(EFI_PEI_SERVICES
**)PeiServices
).PciCfg
= (EFI_PEI_PCI_CFG2_PPI
*) &gPciCfgPpi
;
393 (**(EFI_PEI_SERVICES
**)PeiServices
).PciCfg
= &gPciCfg2Ppi
;
396 if (!FeaturePcdGet (PcdPciCfgDisable
)) {
397 Status
= (**PeiServices
).InstallPpi (PeiServices
, &gPciCfgPpiList
);
399 if (!FeaturePcdGet (PcdPciCfg2Disable
)) {
400 Status
= (**PeiServices
).InstallPpi (PeiServices
, &gPciCfg2PpiList
);