]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Universal/PcatSingleSegmentPciCfgPei/PciCfg2.c
1. EDK_RELEASE_VERSION removed;
[mirror_edk2.git] / IntelFrameworkModulePkg / Universal / PcatSingleSegmentPciCfgPei / PciCfg2.c
1 /**
2
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
8
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.
11
12 **/
13
14 #include "PciCfgInternal.h"
15
16 /**
17 @par Ppi Description:
18 The EFI_PEI_PCI_CFG2_PPI interfaces are used to abstract
19 accesses to PCI controllers behind a PCI root bridge
20 controller.
21
22 @param Read PCI read services. See the Read() function description.
23
24 @param Write PCI write services. See the Write() function description.
25
26 @param Modify PCI read-modify-write services. See the Modify() function description.
27
28 @param Segment The PCI bus segment which the specified functions will access.
29
30 **/
31 GLOBAL_REMOVE_IF_UNREFERENCED
32 EFI_PEI_PCI_CFG2_PPI gPciCfg2Ppi = {
33 PciCfg2Read,
34 PciCfg2Write,
35 PciCfg2Modify
36 };
37
38 GLOBAL_REMOVE_IF_UNREFERENCED
39 EFI_PEI_PPI_DESCRIPTOR gPciCfg2PpiList = {
40 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
41 &gEfiPciCfg2PpiGuid,
42 &gPciCfg2Ppi
43 };
44
45
46 /**
47 @par Ppi Description:
48 The EFI_PEI_PCI_CFG_PPI interfaces are used to abstract accesses to PCI
49 controllers behind a PCI root bridge controller.
50
51 @param Read PCI read services. See the Read() function description.
52
53 @param Write PCI write services. See the Write() function description.
54
55 @param Modify PCI read-modify-write services. See the Modify() function description.
56
57 @param Segment The PCI bus segment which the specified functions will access.
58
59 **/
60 GLOBAL_REMOVE_IF_UNREFERENCED
61 EFI_PEI_PCI_CFG_PPI gPciCfgPpi = {
62 PciCfgRead,
63 PciCfgWrite,
64 PciCfgModify
65 };
66
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,
71 &gPciCfgPpi
72 };
73
74
75 /**
76 Convert EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS to PCI_LIB_ADDRESS.
77
78 @param Address PCI address with
79 EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS format.
80
81 @return The PCI address with PCI_LIB_ADDRESS format.
82
83 **/
84 UINTN
85 PciCfgAddressConvert (
86 EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS *Address
87 )
88 {
89 if (Address->ExtendedRegister == 0) {
90 return PCI_LIB_ADDRESS (Address->Bus, Address->Device, Address->Function, Address->Register);
91 }
92
93 return PCI_LIB_ADDRESS (Address->Bus, Address->Device, Address->Function, Address->ExtendedRegister);
94 }
95
96 /**
97 Reads from a given location in the PCI configuration space.
98
99 @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.
100
101 @param This Pointer to local data for the interface.
102
103 @param Width The width of the access. Enumerated in bytes.
104 See EFI_PEI_PCI_CFG_PPI_WIDTH above.
105
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.
108
109 @param Buffer A pointer to the buffer of data..
110
111
112 @retval EFI_SUCCESS The function completed successfully.
113
114 @retval EFI_DEVICE_ERROR There was a problem with the transaction.
115
116 @retval EFI_DEVICE_NOT_READY The device is not capable of supporting the operation at this
117 time.
118
119 **/
120 EFI_STATUS
121 EFIAPI
122 PciCfg2Read (
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,
126 IN UINT64 Address,
127 IN OUT VOID *Buffer
128 )
129 {
130 UINTN PciLibAddress;
131
132 PciLibAddress = PciCfgAddressConvert ((EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS *) &Address);
133
134 if (Width == EfiPeiPciCfgWidthUint8) {
135 *((UINT8 *) Buffer) = PciRead8 (PciLibAddress);
136 } else if (Width == EfiPeiPciCfgWidthUint16) {
137 if ((PciLibAddress & 0x01) == 0) {
138 //
139 // Aligned Pci address access
140 //
141 WriteUnaligned16 (((UINT16 *) Buffer), PciRead16 (PciLibAddress));
142 } else {
143 //
144 // Unaligned Pci address access, break up the request into byte by byte.
145 //
146 *((UINT8 *) Buffer) = PciRead8 (PciLibAddress);
147 *((UINT8 *) Buffer + 1) = PciRead8 (PciLibAddress + 1);
148 }
149 } else if (Width == EfiPeiPciCfgWidthUint32) {
150 if ((PciLibAddress & 0x03) == 0) {
151 //
152 // Aligned Pci address access
153 //
154 WriteUnaligned32 (((UINT32 *) Buffer), PciRead32 (PciLibAddress));
155 } else if ((PciLibAddress & 0x01) == 0) {
156 //
157 // Unaligned Pci address access, break up the request into word by word.
158 //
159 WriteUnaligned16 (((UINT16 *) Buffer), PciRead16 (PciLibAddress));
160 WriteUnaligned16 (((UINT16 *) Buffer + 1), PciRead16 (PciLibAddress + 2));
161 } else {
162 //
163 // Unaligned Pci address access, break up the request into byte by byte.
164 //
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);
169 }
170 } else {
171 return EFI_INVALID_PARAMETER;
172 }
173
174 return EFI_SUCCESS;
175 }
176
177 /**
178 Write to a given location in the PCI configuration space.
179
180 @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.
181
182 @param This Pointer to local data for the interface.
183
184 @param Width The width of the access. Enumerated in bytes.
185 See EFI_PEI_PCI_CFG_PPI_WIDTH above.
186
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.
189
190 @param Buffer A pointer to the buffer of data..
191
192
193 @retval EFI_SUCCESS The function completed successfully.
194
195 @retval EFI_DEVICE_ERROR There was a problem with the transaction.
196
197 @retval EFI_DEVICE_NOT_READY The device is not capable of supporting the operation at this
198 time.
199
200 **/
201 EFI_STATUS
202 EFIAPI
203 PciCfg2Write (
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,
207 IN UINT64 Address,
208 IN OUT VOID *Buffer
209 )
210 {
211 UINTN PciLibAddress;
212
213 PciLibAddress = PciCfgAddressConvert ((EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS *) &Address);
214
215 if (Width == EfiPeiPciCfgWidthUint8) {
216 PciWrite8 (PciLibAddress, *((UINT8 *) Buffer));
217 } else if (Width == EfiPeiPciCfgWidthUint16) {
218 if ((PciLibAddress & 0x01) == 0) {
219 //
220 // Aligned Pci address access
221 //
222 PciWrite16 (PciLibAddress, ReadUnaligned16 ((UINT16 *) Buffer));
223 } else {
224 //
225 // Unaligned Pci address access, break up the request into byte by byte.
226 //
227 PciWrite8 (PciLibAddress, *((UINT8 *) Buffer));
228 PciWrite8 (PciLibAddress + 1, *((UINT8 *) Buffer + 1));
229 }
230 } else if (Width == EfiPeiPciCfgWidthUint32) {
231 if ((PciLibAddress & 0x03) == 0) {
232 //
233 // Aligned Pci address access
234 //
235 PciWrite32 (PciLibAddress, ReadUnaligned32 ((UINT32 *) Buffer));
236 } else if ((PciLibAddress & 0x01) == 0) {
237 //
238 // Unaligned Pci address access, break up the request into word by word.
239 //
240 PciWrite16 (PciLibAddress, ReadUnaligned16 ((UINT16 *) Buffer));
241 PciWrite16 (PciLibAddress + 2, ReadUnaligned16 ((UINT16 *) Buffer + 1));
242 } else {
243 //
244 // Unaligned Pci address access, break up the request into byte by byte.
245 //
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));
250 }
251 } else {
252 return EFI_INVALID_PARAMETER;
253 }
254
255 return EFI_SUCCESS;
256 }
257
258
259 /**
260 PCI read-modify-write operation.
261
262 @param PeiServices An indirect pointer to the PEI Services Table
263 published by the PEI Foundation.
264
265 @param This Pointer to local data for the interface.
266
267 @param Width The width of the access. Enumerated in bytes. Type
268 EFI_PEI_PCI_CFG_PPI_WIDTH is defined in Read().
269
270 @param Address The physical address of the access.
271
272 @param SetBits Points to value to bitwise-OR with the read configuration value.
273
274 The size of the value is determined by Width.
275
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.
278
279
280 @retval EFI_SUCCESS The function completed successfully.
281
282 @retval EFI_DEVICE_ERROR There was a problem with the transaction.
283
284 @retval EFI_DEVICE_NOT_READY The device is not capable of supporting
285 the operation at this time.
286
287 **/
288 EFI_STATUS
289 EFIAPI
290 PciCfg2Modify (
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,
294 IN UINT64 Address,
295 IN VOID *SetBits,
296 IN VOID *ClearBits
297 )
298 {
299 UINTN PciLibAddress;
300 UINT16 ClearValue16;
301 UINT16 SetValue16;
302 UINT32 ClearValue32;
303 UINT32 SetValue32;
304
305 PciLibAddress = PciCfgAddressConvert ((EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS *) &Address);
306
307 if (Width == EfiPeiPciCfgWidthUint8) {
308 PciAndThenOr8 (PciLibAddress, (UINT8) (~(*(UINT8 *) ClearBits)), *((UINT8 *) SetBits));
309 } else if (Width == EfiPeiPciCfgWidthUint16) {
310 if ((PciLibAddress & 0x01) == 0) {
311 //
312 // Aligned Pci address access
313 //
314 ClearValue16 = (UINT16) (~ReadUnaligned16 ((UINT16 *) ClearBits));
315 SetValue16 = ReadUnaligned16 ((UINT16 *) SetBits);
316 PciAndThenOr16 (PciLibAddress, ClearValue16, SetValue16);
317 } else {
318 //
319 // Unaligned Pci address access, break up the request into byte by byte.
320 //
321 PciAndThenOr8 (PciLibAddress, (UINT8) (~(*(UINT8 *) ClearBits)), *((UINT8 *) SetBits));
322 PciAndThenOr8 (PciLibAddress + 1, (UINT8) (~(*((UINT8 *) ClearBits + 1))), *((UINT8 *) SetBits + 1));
323 }
324 } else if (Width == EfiPeiPciCfgWidthUint32) {
325 if ((PciLibAddress & 0x03) == 0) {
326 //
327 // Aligned Pci address access
328 //
329 ClearValue32 = (UINT32) (~ReadUnaligned32 ((UINT32 *) ClearBits));
330 SetValue32 = ReadUnaligned32 ((UINT32 *) SetBits);
331 PciAndThenOr32 (PciLibAddress, ClearValue32, SetValue32);
332 } else if ((PciLibAddress & 0x01) == 0) {
333 //
334 // Unaligned Pci address access, break up the request into word by word.
335 //
336 ClearValue16 = (UINT16) (~ReadUnaligned16 ((UINT16 *) ClearBits));
337 SetValue16 = ReadUnaligned16 ((UINT16 *) SetBits);
338 PciAndThenOr16 (PciLibAddress, ClearValue16, SetValue16);
339
340 ClearValue16 = (UINT16) (~ReadUnaligned16 ((UINT16 *) ClearBits + 1));
341 SetValue16 = ReadUnaligned16 ((UINT16 *) SetBits + 1);
342 PciAndThenOr16 (PciLibAddress + 2, ClearValue16, SetValue16);
343 } else {
344 //
345 // Unaligned Pci address access, break up the request into byte by byte.
346 //
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));
351 }
352 } else {
353 return EFI_INVALID_PARAMETER;
354 }
355 return EFI_SUCCESS;
356 }
357
358 /**
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.
362
363 @param FileHandle Handle of the file being invoked.
364 @param PeiServices Describes the list of possible PEI Services.
365
366 @return Whether success to install service
367 **/
368 EFI_STATUS
369 EFIAPI
370 PeimInitializePciCfg (
371 IN EFI_PEI_FILE_HANDLE FileHandle,
372 IN CONST EFI_PEI_SERVICES **PeiServices
373 )
374 {
375 EFI_STATUS Status;
376
377 Status = EFI_SUCCESS;
378
379 if ((**PeiServices).Hdr.Revision < PEI_SERVICES_REVISION) {
380 //
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
386 // be updated as:
387 //
388 // FrameworkPeiServices = (FRAMEWORK_PEI_SERVICES **) PeiServices;
389 // (**FrameworkPeiServices).PciCfg = &mPciCfgPpi;
390 //
391 (**(EFI_PEI_SERVICES**)PeiServices).PciCfg = (EFI_PEI_PCI_CFG2_PPI *) &gPciCfgPpi;
392 } else {
393 (**(EFI_PEI_SERVICES**)PeiServices).PciCfg = &gPciCfg2Ppi;
394 }
395
396 if (!FeaturePcdGet (PcdPciCfgDisable)) {
397 Status = (**PeiServices).InstallPpi (PeiServices, &gPciCfgPpiList);
398 }
399 if (!FeaturePcdGet (PcdPciCfg2Disable)) {
400 Status = (**PeiServices).InstallPpi (PeiServices, &gPciCfg2PpiList);
401 }
402
403 return Status;
404 }
405