]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/PcatSingleSegmentPciCfg2Pei/PciCfg2.c
fdd67f7abb86b66483fca1a04631ea4c1e8b20e9
[mirror_edk2.git] / MdeModulePkg / Universal / PcatSingleSegmentPciCfg2Pei / PciCfg2.c
1 /** @file
2 Installs Single Segment Pci Configuration PPI.
3
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
9
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.
12
13 **/
14
15 #include <PiPei.h>
16
17 #include <Ppi/PciCfg2.h>
18
19 #include <Library/BaseLib.h>
20 #include <Library/DebugLib.h>
21 #include <Library/PciLib.h>
22 #include <Library/PeimEntryPoint.h>
23
24 #include <IndustryStandard/Pci.h>
25
26 /**
27 Reads from a given location in the PCI configuration space.
28
29 @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.
30
31 @param This Pointer to local data for the interface.
32
33 @param Width The width of the access. Enumerated in bytes.
34 See EFI_PEI_PCI_CFG_PPI_WIDTH above.
35
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.
38
39 @param Buffer A pointer to the buffer of data..
40
41
42 @retval EFI_SUCCESS The function completed successfully.
43
44 @retval EFI_DEVICE_ERROR There was a problem with the transaction.
45
46 @retval EFI_DEVICE_NOT_READY The device is not capable of supporting the operation at this
47 time.
48
49 **/
50 EFI_STATUS
51 EFIAPI
52 PciCfg2Read (
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,
56 IN UINT64 Address,
57 IN OUT VOID *Buffer
58 );
59
60 /**
61 Write to a given location in the PCI configuration space.
62
63 @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.
64
65 @param This Pointer to local data for the interface.
66
67 @param Width The width of the access. Enumerated in bytes.
68 See EFI_PEI_PCI_CFG_PPI_WIDTH above.
69
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.
72
73 @param Buffer A pointer to the buffer of data..
74
75
76 @retval EFI_SUCCESS The function completed successfully.
77
78 @retval EFI_DEVICE_ERROR There was a problem with the transaction.
79
80 @retval EFI_DEVICE_NOT_READY The device is not capable of supporting the operation at this
81 time.
82
83 **/
84 EFI_STATUS
85 EFIAPI
86 PciCfg2Write (
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,
90 IN UINT64 Address,
91 IN OUT VOID *Buffer
92 );
93
94
95 /**
96 PCI read-modify-write operation.
97
98 @param PeiServices An indirect pointer to the PEI Services Table
99 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. Type
104 EFI_PEI_PCI_CFG_PPI_WIDTH is defined in Read().
105
106 @param Address The physical address of the access.
107
108 @param SetBits Points to value to bitwise-OR with the read configuration value.
109
110 The size of the value is determined by Width.
111
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.
114
115
116 @retval EFI_SUCCESS The function completed successfully.
117
118 @retval EFI_DEVICE_ERROR There was a problem with the transaction.
119
120 @retval EFI_DEVICE_NOT_READY The device is not capable of supporting
121 the operation at this time.
122
123 **/
124 EFI_STATUS
125 EFIAPI
126 PciCfg2Modify (
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,
130 IN UINT64 Address,
131 IN VOID *SetBits,
132 IN VOID *ClearBits
133 );
134
135
136
137 /**
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
141 controller.
142
143 @param Read PCI read services. See the Read() function description.
144
145 @param Write PCI write services. See the Write() function description.
146
147 @param Modify PCI read-modify-write services. See the Modify() function description.
148
149 @param Segment The PCI bus segment which the specified functions will access.
150
151 **/
152 GLOBAL_REMOVE_IF_UNREFERENCED
153 EFI_PEI_PCI_CFG2_PPI gPciCfg2Ppi = {
154 PciCfg2Read,
155 PciCfg2Write,
156 PciCfg2Modify
157 };
158
159 GLOBAL_REMOVE_IF_UNREFERENCED
160 EFI_PEI_PPI_DESCRIPTOR gPciCfg2PpiList = {
161 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
162 &gEfiPciCfg2PpiGuid,
163 &gPciCfg2Ppi
164 };
165
166
167 /**
168 Convert EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS to PCI_LIB_ADDRESS.
169
170 @param Address PCI address with
171 EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS format.
172
173 @return The PCI address with PCI_LIB_ADDRESS format.
174
175 **/
176 UINTN
177 PciCfgAddressConvert (
178 EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS *Address
179 )
180 {
181 if (Address->ExtendedRegister == 0) {
182 return PCI_LIB_ADDRESS (Address->Bus, Address->Device, Address->Function, Address->Register);
183 }
184
185 return PCI_LIB_ADDRESS (Address->Bus, Address->Device, Address->Function, Address->ExtendedRegister);
186 }
187
188
189 /**
190 Reads from a given location in the PCI configuration space.
191
192 @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.
193
194 @param This Pointer to local data for the interface.
195
196 @param Width The width of the access. Enumerated in bytes.
197 See EFI_PEI_PCI_CFG_PPI_WIDTH above.
198
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.
201
202 @param Buffer A pointer to the buffer of data..
203
204
205 @retval EFI_SUCCESS The function completed successfully.
206
207 @retval EFI_DEVICE_ERROR There was a problem with the transaction.
208
209 @retval EFI_DEVICE_NOT_READY The device is not capable of supporting the operation at this
210 time.
211
212 **/
213 EFI_STATUS
214 EFIAPI
215 PciCfg2Read (
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,
219 IN UINT64 Address,
220 IN OUT VOID *Buffer
221 )
222 {
223 UINTN PciLibAddress;
224
225 PciLibAddress = PciCfgAddressConvert ((EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS *) &Address);
226
227 if (Width == EfiPeiPciCfgWidthUint8) {
228 *((UINT8 *) Buffer) = PciRead8 (PciLibAddress);
229 } else if (Width == EfiPeiPciCfgWidthUint16) {
230 if ((PciLibAddress & 0x01) == 0) {
231 //
232 // Aligned Pci address access
233 //
234 WriteUnaligned16 (((UINT16 *) Buffer), PciRead16 (PciLibAddress));
235 } else {
236 //
237 // Unaligned Pci address access, break up the request into byte by byte.
238 //
239 *((UINT8 *) Buffer) = PciRead8 (PciLibAddress);
240 *((UINT8 *) Buffer + 1) = PciRead8 (PciLibAddress + 1);
241 }
242 } else if (Width == EfiPeiPciCfgWidthUint32) {
243 if ((PciLibAddress & 0x03) == 0) {
244 //
245 // Aligned Pci address access
246 //
247 WriteUnaligned32 (((UINT32 *) Buffer), PciRead32 (PciLibAddress));
248 } else if ((PciLibAddress & 0x01) == 0) {
249 //
250 // Unaligned Pci address access, break up the request into word by word.
251 //
252 WriteUnaligned16 (((UINT16 *) Buffer), PciRead16 (PciLibAddress));
253 WriteUnaligned16 (((UINT16 *) Buffer + 1), PciRead16 (PciLibAddress + 2));
254 } else {
255 //
256 // Unaligned Pci address access, break up the request into byte by byte.
257 //
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);
262 }
263 } else {
264 return EFI_INVALID_PARAMETER;
265 }
266
267 return EFI_SUCCESS;
268 }
269
270 /**
271 Write to a given location in the PCI configuration space.
272
273 @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.
274
275 @param This Pointer to local data for the interface.
276
277 @param Width The width of the access. Enumerated in bytes.
278 See EFI_PEI_PCI_CFG_PPI_WIDTH above.
279
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.
282
283 @param Buffer A pointer to the buffer of data..
284
285
286 @retval EFI_SUCCESS The function completed successfully.
287
288 @retval EFI_DEVICE_ERROR There was a problem with the transaction.
289
290 @retval EFI_DEVICE_NOT_READY The device is not capable of supporting the operation at this
291 time.
292
293 **/
294 EFI_STATUS
295 EFIAPI
296 PciCfg2Write (
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,
300 IN UINT64 Address,
301 IN OUT VOID *Buffer
302 )
303 {
304 UINTN PciLibAddress;
305
306 PciLibAddress = PciCfgAddressConvert ((EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS *) &Address);
307
308 if (Width == EfiPeiPciCfgWidthUint8) {
309 PciWrite8 (PciLibAddress, *((UINT8 *) Buffer));
310 } else if (Width == EfiPeiPciCfgWidthUint16) {
311 if ((PciLibAddress & 0x01) == 0) {
312 //
313 // Aligned Pci address access
314 //
315 PciWrite16 (PciLibAddress, ReadUnaligned16 ((UINT16 *) Buffer));
316 } else {
317 //
318 // Unaligned Pci address access, break up the request into byte by byte.
319 //
320 PciWrite8 (PciLibAddress, *((UINT8 *) Buffer));
321 PciWrite8 (PciLibAddress + 1, *((UINT8 *) Buffer + 1));
322 }
323 } else if (Width == EfiPeiPciCfgWidthUint32) {
324 if ((PciLibAddress & 0x03) == 0) {
325 //
326 // Aligned Pci address access
327 //
328 PciWrite32 (PciLibAddress, ReadUnaligned32 ((UINT32 *) Buffer));
329 } else if ((PciLibAddress & 0x01) == 0) {
330 //
331 // Unaligned Pci address access, break up the request into word by word.
332 //
333 PciWrite16 (PciLibAddress, ReadUnaligned16 ((UINT16 *) Buffer));
334 PciWrite16 (PciLibAddress + 2, ReadUnaligned16 ((UINT16 *) Buffer + 1));
335 } else {
336 //
337 // Unaligned Pci address access, break up the request into byte by byte.
338 //
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));
343 }
344 } else {
345 return EFI_INVALID_PARAMETER;
346 }
347
348 return EFI_SUCCESS;
349 }
350
351
352 /**
353 PCI read-modify-write operation.
354
355 @param PeiServices An indirect pointer to the PEI Services Table
356 published by the PEI Foundation.
357
358 @param This Pointer to local data for the interface.
359
360 @param Width The width of the access. Enumerated in bytes. Type
361 EFI_PEI_PCI_CFG_PPI_WIDTH is defined in Read().
362
363 @param Address The physical address of the access.
364
365 @param SetBits Points to value to bitwise-OR with the read configuration value.
366
367 The size of the value is determined by Width.
368
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.
371
372
373 @retval EFI_SUCCESS The function completed successfully.
374
375 @retval EFI_DEVICE_ERROR There was a problem with the transaction.
376
377 @retval EFI_DEVICE_NOT_READY The device is not capable of supporting
378 the operation at this time.
379
380 **/
381 EFI_STATUS
382 EFIAPI
383 PciCfg2Modify (
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,
387 IN UINT64 Address,
388 IN VOID *SetBits,
389 IN VOID *ClearBits
390 )
391 {
392 UINTN PciLibAddress;
393 UINT16 ClearValue16;
394 UINT16 SetValue16;
395 UINT32 ClearValue32;
396 UINT32 SetValue32;
397
398 PciLibAddress = PciCfgAddressConvert ((EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS *) &Address);
399
400 if (Width == EfiPeiPciCfgWidthUint8) {
401 PciAndThenOr8 (PciLibAddress, (UINT8) (~(*(UINT8 *) ClearBits)), *((UINT8 *) SetBits));
402 } else if (Width == EfiPeiPciCfgWidthUint16) {
403 if ((PciLibAddress & 0x01) == 0) {
404 //
405 // Aligned Pci address access
406 //
407 ClearValue16 = (UINT16) (~ReadUnaligned16 ((UINT16 *) ClearBits));
408 SetValue16 = ReadUnaligned16 ((UINT16 *) SetBits);
409 PciAndThenOr16 (PciLibAddress, ClearValue16, SetValue16);
410 } else {
411 //
412 // Unaligned Pci address access, break up the request into byte by byte.
413 //
414 PciAndThenOr8 (PciLibAddress, (UINT8) (~(*(UINT8 *) ClearBits)), *((UINT8 *) SetBits));
415 PciAndThenOr8 (PciLibAddress + 1, (UINT8) (~(*((UINT8 *) ClearBits + 1))), *((UINT8 *) SetBits + 1));
416 }
417 } else if (Width == EfiPeiPciCfgWidthUint32) {
418 if ((PciLibAddress & 0x03) == 0) {
419 //
420 // Aligned Pci address access
421 //
422 ClearValue32 = (UINT32) (~ReadUnaligned32 ((UINT32 *) ClearBits));
423 SetValue32 = ReadUnaligned32 ((UINT32 *) SetBits);
424 PciAndThenOr32 (PciLibAddress, ClearValue32, SetValue32);
425 } else if ((PciLibAddress & 0x01) == 0) {
426 //
427 // Unaligned Pci address access, break up the request into word by word.
428 //
429 ClearValue16 = (UINT16) (~ReadUnaligned16 ((UINT16 *) ClearBits));
430 SetValue16 = ReadUnaligned16 ((UINT16 *) SetBits);
431 PciAndThenOr16 (PciLibAddress, ClearValue16, SetValue16);
432
433 ClearValue16 = (UINT16) (~ReadUnaligned16 ((UINT16 *) ClearBits + 1));
434 SetValue16 = ReadUnaligned16 ((UINT16 *) SetBits + 1);
435 PciAndThenOr16 (PciLibAddress + 2, ClearValue16, SetValue16);
436 } else {
437 //
438 // Unaligned Pci address access, break up the request into byte by byte.
439 //
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));
444 }
445 } else {
446 return EFI_INVALID_PARAMETER;
447 }
448 return EFI_SUCCESS;
449 }
450
451 /**
452 Module's entry function.
453 This routine will install EFI_PEI_PCI_CFG2_PPI.
454
455 @param FileHandle Handle of the file being invoked.
456 @param PeiServices Describes the list of possible PEI Services.
457
458 @return Whether success to install service.
459 **/
460 EFI_STATUS
461 EFIAPI
462 PeimInitializePciCfg (
463 IN EFI_PEI_FILE_HANDLE FileHandle,
464 IN CONST EFI_PEI_SERVICES **PeiServices
465 )
466 {
467 EFI_STATUS Status;
468
469 ASSERT ((**PeiServices).Hdr.Revision >= PEI_SERVICES_REVISION);
470
471 (**(EFI_PEI_SERVICES **)PeiServices).PciCfg = &gPciCfg2Ppi;
472 Status = (**PeiServices).InstallPpi ((CONST EFI_PEI_SERVICES **)PeiServices, &gPciCfg2PpiList);
473
474 return Status;
475 }