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