]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/PcatSingleSegmentPciCfg2Pei/PciCfg2.c
Code scrub for the following drivers and librarys.
[mirror_edk2.git] / MdeModulePkg / Universal / PcatSingleSegmentPciCfg2Pei / PciCfg2.c
CommitLineData
fb0b259e 1/** @file\r
109e9a61
LG
2 This driver installs Single Segment Pci Configuration 2 PPI \r
3 to provide read, write and modify access to Pci configuration space in PEI phase. \r
4 To follow PI specification, these services also support access to the unaligned Pci address.\r
12232778 5\r
109e9a61 6 Copyright (c) 2006 - 2008, Intel Corporation\r
12232778 7 All rights reserved. This program and the accompanying materials\r
8 are licensed and made available under the terms and conditions of the BSD License\r
9 which accompanies this distribution. The full text of the license may be found at\r
10 http://opensource.org/licenses/bsd-license.php\r
11\r
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14\r
15**/\r
16\r
17#include <PiPei.h>\r
12232778 18#include <Ppi/PciCfg2.h>\r
12232778 19#include <Library/BaseLib.h>\r
20#include <Library/DebugLib.h>\r
21#include <Library/PciLib.h>\r
22#include <Library/PeimEntryPoint.h>\r
2d85ada2 23#include <IndustryStandard/Pci.h>\r
12232778 24\r
aa79b0b3 25/**\r
26 Convert EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS to PCI_LIB_ADDRESS.\r
27\r
109e9a61 28 @param Address PCI address with EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS format.\r
aa79b0b3 29\r
109e9a61 30 @return PCI address with PCI_LIB_ADDRESS format.\r
aa79b0b3 31\r
32**/\r
33UINTN\r
34PciCfgAddressConvert (\r
35 EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS *Address\r
36 )\r
37{\r
38 if (Address->ExtendedRegister == 0) {\r
39 return PCI_LIB_ADDRESS (Address->Bus, Address->Device, Address->Function, Address->Register);\r
40 }\r
41\r
42 return PCI_LIB_ADDRESS (Address->Bus, Address->Device, Address->Function, Address->ExtendedRegister);\r
43}\r
44\r
12232778 45/**\r
46 Reads from a given location in the PCI configuration space.\r
47\r
48 @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.\r
12232778 49 @param This Pointer to local data for the interface.\r
12232778 50 @param Width The width of the access. Enumerated in bytes.\r
51 See EFI_PEI_PCI_CFG_PPI_WIDTH above.\r
12232778 52 @param Address The physical address of the access. The format of\r
53 the address is described by EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS.\r
109e9a61 54 @param Buffer A pointer to the buffer of data.\r
12232778 55\r
56 @retval EFI_SUCCESS The function completed successfully.\r
109e9a61
LG
57 @retval EFI_INVALID_PARAMETER The invalid access width.\r
58 \r
12232778 59**/\r
60EFI_STATUS\r
fb0b259e 61EFIAPI\r
12232778 62PciCfg2Read (\r
63 IN CONST EFI_PEI_SERVICES **PeiServices,\r
64 IN CONST EFI_PEI_PCI_CFG2_PPI *This,\r
65 IN EFI_PEI_PCI_CFG_PPI_WIDTH Width,\r
66 IN UINT64 Address,\r
67 IN OUT VOID *Buffer\r
cebc8d48 68 )\r
12232778 69{\r
70 UINTN PciLibAddress;\r
71\r
d8b61daa 72 PciLibAddress = PciCfgAddressConvert ((EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS *) &Address);\r
12232778 73\r
74 if (Width == EfiPeiPciCfgWidthUint8) {\r
75 *((UINT8 *) Buffer) = PciRead8 (PciLibAddress);\r
76 } else if (Width == EfiPeiPciCfgWidthUint16) {\r
8501ba4c
LG
77 if ((PciLibAddress & 0x01) == 0) {\r
78 //\r
79 // Aligned Pci address access\r
80 //\r
81 WriteUnaligned16 (((UINT16 *) Buffer), PciRead16 (PciLibAddress));\r
82 } else {\r
83 //\r
84 // Unaligned Pci address access, break up the request into byte by byte.\r
85 //\r
86 *((UINT8 *) Buffer) = PciRead8 (PciLibAddress);\r
87 *((UINT8 *) Buffer + 1) = PciRead8 (PciLibAddress + 1);\r
88 }\r
12232778 89 } else if (Width == EfiPeiPciCfgWidthUint32) {\r
8501ba4c
LG
90 if ((PciLibAddress & 0x03) == 0) {\r
91 //\r
92 // Aligned Pci address access\r
93 //\r
94 WriteUnaligned32 (((UINT32 *) Buffer), PciRead32 (PciLibAddress));\r
95 } else if ((PciLibAddress & 0x01) == 0) {\r
96 //\r
97 // Unaligned Pci address access, break up the request into word by word.\r
98 //\r
99 WriteUnaligned16 (((UINT16 *) Buffer), PciRead16 (PciLibAddress));\r
100 WriteUnaligned16 (((UINT16 *) Buffer + 1), PciRead16 (PciLibAddress + 2));\r
101 } else {\r
102 //\r
103 // Unaligned Pci address access, break up the request into byte by byte.\r
104 //\r
105 *((UINT8 *) Buffer) = PciRead8 (PciLibAddress);\r
106 *((UINT8 *) Buffer + 1) = PciRead8 (PciLibAddress + 1);\r
107 *((UINT8 *) Buffer + 2) = PciRead8 (PciLibAddress + 2);\r
108 *((UINT8 *) Buffer + 3) = PciRead8 (PciLibAddress + 3);\r
109 }\r
12232778 110 } else {\r
111 return EFI_INVALID_PARAMETER;\r
112 }\r
113\r
114 return EFI_SUCCESS;\r
115}\r
116\r
117/**\r
118 Write to a given location in the PCI configuration space.\r
119\r
120 @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.\r
12232778 121 @param This Pointer to local data for the interface.\r
12232778 122 @param Width The width of the access. Enumerated in bytes.\r
123 See EFI_PEI_PCI_CFG_PPI_WIDTH above.\r
12232778 124 @param Address The physical address of the access. The format of\r
125 the address is described by EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS.\r
109e9a61 126 @param Buffer A pointer to the buffer of data.\r
12232778 127\r
128 @retval EFI_SUCCESS The function completed successfully.\r
109e9a61 129 @retval EFI_INVALID_PARAMETER The invalid access width.\r
12232778 130\r
131**/\r
132EFI_STATUS\r
fb0b259e 133EFIAPI\r
12232778 134PciCfg2Write (\r
135 IN CONST EFI_PEI_SERVICES **PeiServices,\r
136 IN CONST EFI_PEI_PCI_CFG2_PPI *This,\r
137 IN EFI_PEI_PCI_CFG_PPI_WIDTH Width,\r
138 IN UINT64 Address,\r
139 IN OUT VOID *Buffer\r
cebc8d48 140 )\r
12232778 141{\r
142 UINTN PciLibAddress;\r
143\r
d8b61daa 144 PciLibAddress = PciCfgAddressConvert ((EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS *) &Address);\r
12232778 145\r
146 if (Width == EfiPeiPciCfgWidthUint8) {\r
147 PciWrite8 (PciLibAddress, *((UINT8 *) Buffer));\r
148 } else if (Width == EfiPeiPciCfgWidthUint16) {\r
8501ba4c
LG
149 if ((PciLibAddress & 0x01) == 0) {\r
150 //\r
151 // Aligned Pci address access\r
152 //\r
153 PciWrite16 (PciLibAddress, ReadUnaligned16 ((UINT16 *) Buffer));\r
154 } else {\r
155 //\r
156 // Unaligned Pci address access, break up the request into byte by byte.\r
157 //\r
158 PciWrite8 (PciLibAddress, *((UINT8 *) Buffer));\r
159 PciWrite8 (PciLibAddress + 1, *((UINT8 *) Buffer + 1)); \r
160 }\r
12232778 161 } else if (Width == EfiPeiPciCfgWidthUint32) {\r
8501ba4c
LG
162 if ((PciLibAddress & 0x03) == 0) {\r
163 //\r
164 // Aligned Pci address access\r
165 //\r
166 PciWrite32 (PciLibAddress, ReadUnaligned32 ((UINT32 *) Buffer));\r
167 } else if ((PciLibAddress & 0x01) == 0) {\r
168 //\r
169 // Unaligned Pci address access, break up the request into word by word.\r
170 //\r
171 PciWrite16 (PciLibAddress, ReadUnaligned16 ((UINT16 *) Buffer));\r
172 PciWrite16 (PciLibAddress + 2, ReadUnaligned16 ((UINT16 *) Buffer + 1));\r
173 } else {\r
174 //\r
175 // Unaligned Pci address access, break up the request into byte by byte.\r
176 //\r
177 PciWrite8 (PciLibAddress, *((UINT8 *) Buffer));\r
178 PciWrite8 (PciLibAddress + 1, *((UINT8 *) Buffer + 1)); \r
179 PciWrite8 (PciLibAddress + 2, *((UINT8 *) Buffer + 2)); \r
180 PciWrite8 (PciLibAddress + 3, *((UINT8 *) Buffer + 3)); \r
181 }\r
12232778 182 } else {\r
183 return EFI_INVALID_PARAMETER;\r
184 }\r
185\r
186 return EFI_SUCCESS;\r
187}\r
188\r
189\r
190/**\r
109e9a61
LG
191 This function performs a read-modify-write operation on the contents from a given\r
192 location in the PCI configuration space.\r
12232778 193\r
194 @param PeiServices An indirect pointer to the PEI Services Table\r
195 published by the PEI Foundation.\r
12232778 196 @param This Pointer to local data for the interface.\r
12232778 197 @param Width The width of the access. Enumerated in bytes. Type\r
198 EFI_PEI_PCI_CFG_PPI_WIDTH is defined in Read().\r
12232778 199 @param Address The physical address of the access.\r
12232778 200 @param SetBits Points to value to bitwise-OR with the read configuration value.\r
12232778 201 The size of the value is determined by Width.\r
12232778 202 @param ClearBits Points to the value to negate and bitwise-AND with the read configuration value.\r
203 The size of the value is determined by Width.\r
204\r
12232778 205 @retval EFI_SUCCESS The function completed successfully.\r
109e9a61 206 @retval EFI_INVALID_PARAMETER The invalid access width.\r
12232778 207\r
208**/\r
209EFI_STATUS\r
fb0b259e 210EFIAPI\r
12232778 211PciCfg2Modify (\r
212 IN CONST EFI_PEI_SERVICES **PeiServices,\r
213 IN CONST EFI_PEI_PCI_CFG2_PPI *This,\r
214 IN EFI_PEI_PCI_CFG_PPI_WIDTH Width,\r
215 IN UINT64 Address,\r
01edaf2a 216 IN VOID *SetBits,\r
217 IN VOID *ClearBits\r
cebc8d48 218 )\r
12232778 219{\r
702887db 220 UINTN PciLibAddress;\r
221 UINT16 ClearValue16;\r
222 UINT16 SetValue16;\r
223 UINT32 ClearValue32;\r
224 UINT32 SetValue32;\r
12232778 225\r
d8b61daa 226 PciLibAddress = PciCfgAddressConvert ((EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS *) &Address);\r
12232778 227\r
228 if (Width == EfiPeiPciCfgWidthUint8) {\r
702887db 229 PciAndThenOr8 (PciLibAddress, (UINT8) (~(*(UINT8 *) ClearBits)), *((UINT8 *) SetBits));\r
12232778 230 } else if (Width == EfiPeiPciCfgWidthUint16) {\r
8501ba4c
LG
231 if ((PciLibAddress & 0x01) == 0) {\r
232 //\r
233 // Aligned Pci address access\r
234 //\r
235 ClearValue16 = (UINT16) (~ReadUnaligned16 ((UINT16 *) ClearBits));\r
236 SetValue16 = ReadUnaligned16 ((UINT16 *) SetBits);\r
237 PciAndThenOr16 (PciLibAddress, ClearValue16, SetValue16);\r
238 } else {\r
239 //\r
240 // Unaligned Pci address access, break up the request into byte by byte.\r
241 //\r
242 PciAndThenOr8 (PciLibAddress, (UINT8) (~(*(UINT8 *) ClearBits)), *((UINT8 *) SetBits));\r
243 PciAndThenOr8 (PciLibAddress + 1, (UINT8) (~(*((UINT8 *) ClearBits + 1))), *((UINT8 *) SetBits + 1));\r
244 }\r
12232778 245 } else if (Width == EfiPeiPciCfgWidthUint32) {\r
8501ba4c
LG
246 if ((PciLibAddress & 0x03) == 0) {\r
247 //\r
248 // Aligned Pci address access\r
249 //\r
250 ClearValue32 = (UINT32) (~ReadUnaligned32 ((UINT32 *) ClearBits));\r
251 SetValue32 = ReadUnaligned32 ((UINT32 *) SetBits);\r
252 PciAndThenOr32 (PciLibAddress, ClearValue32, SetValue32);\r
253 } else if ((PciLibAddress & 0x01) == 0) {\r
254 //\r
255 // Unaligned Pci address access, break up the request into word by word.\r
256 //\r
257 ClearValue16 = (UINT16) (~ReadUnaligned16 ((UINT16 *) ClearBits));\r
258 SetValue16 = ReadUnaligned16 ((UINT16 *) SetBits);\r
259 PciAndThenOr16 (PciLibAddress, ClearValue16, SetValue16);\r
260\r
261 ClearValue16 = (UINT16) (~ReadUnaligned16 ((UINT16 *) ClearBits + 1));\r
262 SetValue16 = ReadUnaligned16 ((UINT16 *) SetBits + 1);\r
263 PciAndThenOr16 (PciLibAddress + 2, ClearValue16, SetValue16);\r
264 } else {\r
265 //\r
266 // Unaligned Pci address access, break up the request into byte by byte.\r
267 //\r
268 PciAndThenOr8 (PciLibAddress, (UINT8) (~(*(UINT8 *) ClearBits)), *((UINT8 *) SetBits));\r
269 PciAndThenOr8 (PciLibAddress + 1, (UINT8) (~(*((UINT8 *) ClearBits + 1))), *((UINT8 *) SetBits + 1));\r
270 PciAndThenOr8 (PciLibAddress + 2, (UINT8) (~(*((UINT8 *) ClearBits + 2))), *((UINT8 *) SetBits + 2));\r
271 PciAndThenOr8 (PciLibAddress + 3, (UINT8) (~(*((UINT8 *) ClearBits + 3))), *((UINT8 *) SetBits + 3));\r
272 }\r
12232778 273 } else {\r
274 return EFI_INVALID_PARAMETER;\r
275 }\r
109e9a61 276\r
12232778 277 return EFI_SUCCESS;\r
278}\r
279\r
109e9a61
LG
280EFI_PEI_PCI_CFG2_PPI gPciCfg2Ppi = {\r
281 PciCfg2Read,\r
282 PciCfg2Write,\r
283 PciCfg2Modify,\r
284 0\r
285};\r
286\r
287EFI_PEI_PPI_DESCRIPTOR gPciCfg2PpiList = {\r
288 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
289 &gEfiPciCfg2PpiGuid,\r
290 &gPciCfg2Ppi\r
291};\r
292\r
cebc8d48
LG
293/**\r
294 Module's entry function. \r
295 This routine will install EFI_PEI_PCI_CFG2_PPI.\r
296 \r
297 @param FileHandle Handle of the file being invoked.\r
298 @param PeiServices Describes the list of possible PEI Services.\r
12232778 299\r
cebc8d48
LG
300 @return Whether success to install service.\r
301**/\r
12232778 302EFI_STATUS\r
303EFIAPI\r
304PeimInitializePciCfg (\r
8bd22b8a
LG
305 IN EFI_PEI_FILE_HANDLE FileHandle,\r
306 IN CONST EFI_PEI_SERVICES **PeiServices\r
12232778 307 )\r
308{\r
309 EFI_STATUS Status;\r
310\r
109e9a61 311 ASSERT ((**PeiServices).Hdr.Revision >= PI_SPECIFICATION_VERSION);\r
12232778 312\r
8bd22b8a 313 (**(EFI_PEI_SERVICES **)PeiServices).PciCfg = &gPciCfg2Ppi;\r
109e9a61 314 Status = (**PeiServices).InstallPpi (PeiServices, &gPciCfg2PpiList);\r
12232778 315\r
316 return Status;\r
317}\r