]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c
1. Impl PI 1.2 PCI part. Major changes include:
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / PciBusDxe / PciIo.c
CommitLineData
9060e3ec 1/** @file\r
2 EFI PCI IO protocol functions implementation for PCI Bus module.\r
3\r
4Copyright (c) 2006 - 2009, Intel Corporation\r
5All rights reserved. This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "PciBus.h"\r
16\r
17//\r
18// Pci Io Protocol Interface\r
19//\r
20EFI_PCI_IO_PROTOCOL mPciIoInterface = {\r
21 PciIoPollMem,\r
22 PciIoPollIo,\r
23 {\r
24 PciIoMemRead,\r
25 PciIoMemWrite\r
26 },\r
27 {\r
28 PciIoIoRead,\r
29 PciIoIoWrite\r
30 },\r
31 {\r
32 PciIoConfigRead,\r
33 PciIoConfigWrite\r
34 },\r
35 PciIoCopyMem,\r
36 PciIoMap,\r
37 PciIoUnmap,\r
38 PciIoAllocateBuffer,\r
39 PciIoFreeBuffer,\r
40 PciIoFlush,\r
41 PciIoGetLocation,\r
42 PciIoAttributes,\r
43 PciIoGetBarAttributes,\r
44 PciIoSetBarAttributes,\r
45 0,\r
46 NULL\r
47};\r
48\r
49/**\r
50 Report a error Status code of PCI bus driver controller.\r
51\r
52 @param PciIoDevice Pci device instance.\r
53 @param Code Status code value.\r
54\r
55**/\r
56EFI_STATUS\r
57ReportErrorStatusCode (\r
58 IN PCI_IO_DEVICE *PciIoDevice,\r
59 IN EFI_STATUS_CODE_VALUE Code\r
60 )\r
61{\r
62 return REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
63 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
64 Code,\r
65 PciIoDevice->DevicePath\r
66 );\r
67}\r
68\r
69/**\r
70 Initializes a PCI I/O Instance.\r
71\r
72 @param PciIoDevice Pci device instance.\r
73\r
74**/\r
75VOID\r
76InitializePciIoInstance (\r
77 IN PCI_IO_DEVICE *PciIoDevice\r
78 )\r
79{\r
80 CopyMem (&PciIoDevice->PciIo, &mPciIoInterface, sizeof (EFI_PCI_IO_PROTOCOL));\r
81}\r
82\r
83/**\r
84 Verifies access to a PCI Base Address Register (BAR).\r
85\r
86 @param PciIoDevice Pci device instance.\r
87 @param BarIndex The BAR index of the standard PCI Configuration header to use as the\r
88 base address for the memory or I/O operation to perform.\r
89 @param Type Operation type could be memory or I/O.\r
90 @param Width Signifies the width of the memory or I/O operations.\r
91 @param Count The number of memory or I/O operations to perform.\r
92 @param Offset The offset within the PCI configuration space for the PCI controller.\r
93\r
94 @retval EFI_INVALID_PARAMETER Invalid Width/BarIndex or Bar type.\r
95 @retval EFI_SUCCESS Successfully verified.\r
96\r
97**/\r
98EFI_STATUS\r
99PciIoVerifyBarAccess (\r
100 IN PCI_IO_DEVICE *PciIoDevice,\r
101 IN UINT8 BarIndex,\r
102 IN PCI_BAR_TYPE Type,\r
103 IN IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
104 IN IN UINTN Count,\r
105 IN UINT64 *Offset\r
106 )\r
107{\r
108 if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
109 return EFI_INVALID_PARAMETER;\r
110 }\r
111\r
112 if (BarIndex == EFI_PCI_IO_PASS_THROUGH_BAR) {\r
113 return EFI_SUCCESS;\r
114 }\r
115\r
116 //\r
117 // BarIndex 0-5 is legal\r
118 //\r
119 if (BarIndex >= PCI_MAX_BAR) {\r
120 return EFI_INVALID_PARAMETER;\r
121 }\r
122\r
123 if (!CheckBarType (PciIoDevice, BarIndex, Type)) {\r
124 return EFI_INVALID_PARAMETER;\r
125 }\r
126\r
127 //\r
128 // If Width is EfiPciIoWidthFifoUintX then convert to EfiPciIoWidthUintX\r
129 // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUintX\r
130 //\r
131 if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {\r
132 Count = 1;\r
133 }\r
134\r
135 Width = (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & 0x03);\r
136\r
137 if ((*Offset + Count * (UINTN)(1 << Width)) - 1 >= PciIoDevice->PciBar[BarIndex].Length) {\r
138 return EFI_INVALID_PARAMETER;\r
139 }\r
140\r
141 *Offset = *Offset + PciIoDevice->PciBar[BarIndex].BaseAddress;\r
142\r
143 return EFI_SUCCESS;\r
144}\r
145\r
146/**\r
147 Verifies access to a PCI Configuration Header.\r
148\r
149 @param PciIoDevice Pci device instance.\r
150 @param Width Signifies the width of the memory or I/O operations.\r
151 @param Count The number of memory or I/O operations to perform.\r
152 @param Offset The offset within the PCI configuration space for the PCI controller.\r
153\r
154 @retval EFI_INVALID_PARAMETER Invalid Width\r
155 @retval EFI_UNSUPPORTED Offset overflowed.\r
156 @retval EFI_SUCCESS Successfully verified.\r
157\r
158**/\r
159EFI_STATUS\r
160PciIoVerifyConfigAccess (\r
161 IN PCI_IO_DEVICE *PciIoDevice,\r
162 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
163 IN UINTN Count,\r
164 IN UINT64 *Offset\r
165 )\r
166{\r
167 UINT64 ExtendOffset;\r
168\r
169 if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
170 return EFI_INVALID_PARAMETER;\r
171 }\r
172\r
173 //\r
174 // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUintX\r
175 //\r
176 Width = (EFI_PCI_IO_PROTOCOL_WIDTH) (Width & 0x03);\r
177\r
178 if (PciIoDevice->IsPciExp) {\r
179 if ((*Offset + Count * (UINTN)(1 << Width)) - 1 >= PCI_EXP_MAX_CONFIG_OFFSET) {\r
180 return EFI_UNSUPPORTED;\r
181 }\r
182\r
183 ExtendOffset = LShiftU64 (*Offset, 32);\r
184 *Offset = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, 0);\r
185 *Offset = (*Offset) | ExtendOffset;\r
186\r
187 } else {\r
188 if ((*Offset + Count * (UINTN)(1 << Width)) - 1 >= PCI_MAX_CONFIG_OFFSET) {\r
189 return EFI_UNSUPPORTED;\r
190 }\r
191\r
192 *Offset = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, *Offset);\r
193 }\r
194\r
195 return EFI_SUCCESS;\r
196}\r
197\r
198/**\r
199 Reads from the memory space of a PCI controller. Returns either when the polling exit criteria is\r
200 satisfied or after a defined duration.\r
201\r
202 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
203 @param Width Signifies the width of the memory or I/O operations.\r
204 @param BarIndex The BAR index of the standard PCI Configuration header to use as the\r
205 base address for the memory operation to perform.\r
206 @param Offset The offset within the selected BAR to start the memory operation.\r
207 @param Mask Mask used for the polling criteria.\r
208 @param Value The comparison value used for the polling exit criteria.\r
209 @param Delay The number of 100 ns units to poll.\r
210 @param Result Pointer to the last value read from the memory location.\r
211\r
212 @retval EFI_SUCCESS The last data returned from the access matched the poll exit criteria.\r
213 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.\r
214 @retval EFI_UNSUPPORTED Offset is not valid for the BarIndex of this PCI controller.\r
215 @retval EFI_TIMEOUT Delay expired before a match occurred.\r
216 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
217 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
218\r
219**/\r
220EFI_STATUS\r
221EFIAPI\r
222PciIoPollMem (\r
223 IN EFI_PCI_IO_PROTOCOL *This,\r
224 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
225 IN UINT8 BarIndex,\r
226 IN UINT64 Offset,\r
227 IN UINT64 Mask,\r
228 IN UINT64 Value,\r
229 IN UINT64 Delay,\r
230 OUT UINT64 *Result\r
231 )\r
232{\r
233 EFI_STATUS Status;\r
234 PCI_IO_DEVICE *PciIoDevice;\r
235\r
236 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
237\r
238 if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
239 return EFI_INVALID_PARAMETER;\r
240 }\r
241\r
242 Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, 1, &Offset);\r
243 if (EFI_ERROR (Status)) {\r
244 return EFI_UNSUPPORTED;\r
245 }\r
246\r
247 if (Width > EfiPciIoWidthUint64) {\r
248 return EFI_INVALID_PARAMETER;\r
249 }\r
250\r
251 Status = PciIoDevice->PciRootBridgeIo->PollMem (\r
252 PciIoDevice->PciRootBridgeIo,\r
253 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
254 Offset,\r
255 Mask,\r
256 Value,\r
257 Delay,\r
258 Result\r
259 );\r
260\r
261 if (EFI_ERROR (Status)) {\r
262 ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);\r
263 }\r
264\r
265 return Status;\r
266}\r
267\r
268/**\r
269 Reads from the memory space of a PCI controller. Returns either when the polling exit criteria is\r
270 satisfied or after a defined duration.\r
271\r
272 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
273 @param Width Signifies the width of the memory or I/O operations.\r
274 @param BarIndex The BAR index of the standard PCI Configuration header to use as the\r
275 base address for the memory operation to perform.\r
276 @param Offset The offset within the selected BAR to start the memory operation.\r
277 @param Mask Mask used for the polling criteria.\r
278 @param Value The comparison value used for the polling exit criteria.\r
279 @param Delay The number of 100 ns units to poll.\r
280 @param Result Pointer to the last value read from the memory location.\r
281\r
282 @retval EFI_SUCCESS The last data returned from the access matched the poll exit criteria.\r
283 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.\r
284 @retval EFI_UNSUPPORTED Offset is not valid for the BarIndex of this PCI controller.\r
285 @retval EFI_TIMEOUT Delay expired before a match occurred.\r
286 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
287 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
288\r
289**/\r
290EFI_STATUS\r
291EFIAPI\r
292PciIoPollIo (\r
293 IN EFI_PCI_IO_PROTOCOL *This,\r
294 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
295 IN UINT8 BarIndex,\r
296 IN UINT64 Offset,\r
297 IN UINT64 Mask,\r
298 IN UINT64 Value,\r
299 IN UINT64 Delay,\r
300 OUT UINT64 *Result\r
301 )\r
302{\r
303 EFI_STATUS Status;\r
304 PCI_IO_DEVICE *PciIoDevice;\r
305\r
306 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
307\r
308 if (Width < 0 || Width > EfiPciIoWidthUint64) {\r
309 return EFI_INVALID_PARAMETER;\r
310 }\r
311\r
312 Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, 1, &Offset);\r
313 if (EFI_ERROR (Status)) {\r
314 return EFI_UNSUPPORTED;\r
315 }\r
316\r
317 Status = PciIoDevice->PciRootBridgeIo->PollIo (\r
318 PciIoDevice->PciRootBridgeIo,\r
319 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
320 Offset,\r
321 Mask,\r
322 Value,\r
323 Delay,\r
324 Result\r
325 );\r
326\r
327 if (EFI_ERROR (Status)) {\r
328 ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);\r
329 }\r
330\r
331 return Status;\r
332}\r
333\r
334/**\r
335 Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.\r
336\r
337 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
338 @param Width Signifies the width of the memory or I/O operations.\r
339 @param BarIndex The BAR index of the standard PCI Configuration header to use as the\r
340 base address for the memory or I/O operation to perform.\r
341 @param Offset The offset within the selected BAR to start the memory or I/O operation.\r
342 @param Count The number of memory or I/O operations to perform.\r
343 @param Buffer For read operations, the destination buffer to store the results. For write\r
344 operations, the source buffer to write data from.\r
345\r
346 @retval EFI_SUCCESS The data was read from or written to the PCI controller.\r
347 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.\r
348 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not\r
349 valid for the PCI BAR specified by BarIndex.\r
350 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
351 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
352\r
353**/\r
354EFI_STATUS\r
355EFIAPI\r
356PciIoMemRead (\r
357 IN EFI_PCI_IO_PROTOCOL *This,\r
358 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
359 IN UINT8 BarIndex,\r
360 IN UINT64 Offset,\r
361 IN UINTN Count,\r
362 IN OUT VOID *Buffer\r
363 )\r
364{\r
365 EFI_STATUS Status;\r
366 PCI_IO_DEVICE *PciIoDevice;\r
367\r
368 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
369\r
370 if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
371 return EFI_INVALID_PARAMETER;\r
372 }\r
373\r
374 if (Buffer == NULL) {\r
375 return EFI_INVALID_PARAMETER;\r
376 }\r
377\r
378 Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, Count, &Offset);\r
379 if (EFI_ERROR (Status)) {\r
380 return EFI_UNSUPPORTED;\r
381 }\r
382\r
383 Status = PciIoDevice->PciRootBridgeIo->Mem.Read (\r
384 PciIoDevice->PciRootBridgeIo,\r
385 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
386 Offset,\r
387 Count,\r
388 Buffer\r
389 );\r
390\r
391 if (EFI_ERROR (Status)) {\r
392 ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_READ_ERROR);\r
393 }\r
394\r
395 return Status;\r
396}\r
397\r
398/**\r
399 Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.\r
400\r
401 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
402 @param Width Signifies the width of the memory or I/O operations.\r
403 @param BarIndex The BAR index of the standard PCI Configuration header to use as the\r
404 base address for the memory or I/O operation to perform.\r
405 @param Offset The offset within the selected BAR to start the memory or I/O operation.\r
406 @param Count The number of memory or I/O operations to perform.\r
407 @param Buffer For read operations, the destination buffer to store the results. For write\r
408 operations, the source buffer to write data from.\r
409\r
410 @retval EFI_SUCCESS The data was read from or written to the PCI controller.\r
411 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.\r
412 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not\r
413 valid for the PCI BAR specified by BarIndex.\r
414 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
415 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
416\r
417**/\r
418EFI_STATUS\r
419EFIAPI\r
420PciIoMemWrite (\r
421 IN EFI_PCI_IO_PROTOCOL *This,\r
422 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
423 IN UINT8 BarIndex,\r
424 IN UINT64 Offset,\r
425 IN UINTN Count,\r
426 IN OUT VOID *Buffer\r
427 )\r
428{\r
429 EFI_STATUS Status;\r
430 PCI_IO_DEVICE *PciIoDevice;\r
431\r
432 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
433\r
434 if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
435 return EFI_INVALID_PARAMETER;\r
436 }\r
437\r
438 if (Buffer == NULL) {\r
439 return EFI_INVALID_PARAMETER;\r
440 }\r
441\r
442 Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, Count, &Offset);\r
443 if (EFI_ERROR (Status)) {\r
444 return EFI_UNSUPPORTED;\r
445 }\r
446\r
447 Status = PciIoDevice->PciRootBridgeIo->Mem.Write (\r
448 PciIoDevice->PciRootBridgeIo,\r
449 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
450 Offset,\r
451 Count,\r
452 Buffer\r
453 );\r
454\r
455 if (EFI_ERROR (Status)) {\r
456 ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_WRITE_ERROR);\r
457 }\r
458\r
459 return Status;\r
460}\r
461\r
462/**\r
463 Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.\r
464\r
465 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
466 @param Width Signifies the width of the memory or I/O operations.\r
467 @param BarIndex The BAR index of the standard PCI Configuration header to use as the\r
468 base address for the memory or I/O operation to perform.\r
469 @param Offset The offset within the selected BAR to start the memory or I/O operation.\r
470 @param Count The number of memory or I/O operations to perform.\r
471 @param Buffer For read operations, the destination buffer to store the results. For write\r
472 operations, the source buffer to write data from.\r
473\r
474 @retval EFI_SUCCESS The data was read from or written to the PCI controller.\r
475 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.\r
476 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not\r
477 valid for the PCI BAR specified by BarIndex.\r
478 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
479 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
480\r
481**/\r
482EFI_STATUS\r
483EFIAPI\r
484PciIoIoRead (\r
485 IN EFI_PCI_IO_PROTOCOL *This,\r
486 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
487 IN UINT8 BarIndex,\r
488 IN UINT64 Offset,\r
489 IN UINTN Count,\r
490 IN OUT VOID *Buffer\r
491 )\r
492{\r
493 EFI_STATUS Status;\r
494 PCI_IO_DEVICE *PciIoDevice;\r
495\r
496 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
497\r
498 if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
499 return EFI_INVALID_PARAMETER;\r
500 }\r
501\r
502 if (Buffer == NULL) {\r
503 return EFI_INVALID_PARAMETER;\r
504 }\r
505\r
506 Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, Count, &Offset);\r
507 if (EFI_ERROR (Status)) {\r
508 return EFI_UNSUPPORTED;\r
509 }\r
510\r
511 Status = PciIoDevice->PciRootBridgeIo->Io.Read (\r
512 PciIoDevice->PciRootBridgeIo,\r
513 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
514 Offset,\r
515 Count,\r
516 Buffer\r
517 );\r
518\r
519 if (EFI_ERROR (Status)) {\r
520 ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_READ_ERROR);\r
521 }\r
522\r
523 return Status;\r
524}\r
525\r
526/**\r
527 Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.\r
528\r
529 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
530 @param Width Signifies the width of the memory or I/O operations.\r
531 @param BarIndex The BAR index of the standard PCI Configuration header to use as the\r
532 base address for the memory or I/O operation to perform.\r
533 @param Offset The offset within the selected BAR to start the memory or I/O operation.\r
534 @param Count The number of memory or I/O operations to perform.\r
535 @param Buffer For read operations, the destination buffer to store the results. For write\r
536 operations, the source buffer to write data from.\r
537\r
538 @retval EFI_SUCCESS The data was read from or written to the PCI controller.\r
539 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.\r
540 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not\r
541 valid for the PCI BAR specified by BarIndex.\r
542 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
543 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
544\r
545**/\r
546EFI_STATUS\r
547EFIAPI\r
548PciIoIoWrite (\r
549 IN EFI_PCI_IO_PROTOCOL *This,\r
550 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
551 IN UINT8 BarIndex,\r
552 IN UINT64 Offset,\r
553 IN UINTN Count,\r
554 IN OUT VOID *Buffer\r
555 )\r
556{\r
557 EFI_STATUS Status;\r
558 PCI_IO_DEVICE *PciIoDevice;\r
559\r
560 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
561\r
562 if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
563 return EFI_INVALID_PARAMETER;\r
564 }\r
565\r
566 if (Buffer == NULL) {\r
567 return EFI_INVALID_PARAMETER;\r
568 }\r
569\r
570 Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, Count, &Offset);\r
571 if (EFI_ERROR (Status)) {\r
572 return EFI_UNSUPPORTED;\r
573 }\r
574\r
575 Status = PciIoDevice->PciRootBridgeIo->Io.Write (\r
576 PciIoDevice->PciRootBridgeIo,\r
577 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
578 Offset,\r
579 Count,\r
580 Buffer\r
581 );\r
582\r
583 if (EFI_ERROR (Status)) {\r
584 ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_WRITE_ERROR);\r
585 }\r
586\r
587 return Status;\r
588}\r
589\r
590/**\r
591 Enable a PCI driver to access PCI controller registers in PCI configuration space.\r
592\r
593 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
594 @param Width Signifies the width of the memory operations.\r
595 @param Offset The offset within the PCI configuration space for the PCI controller.\r
596 @param Count The number of PCI configuration operations to perform.\r
597 @param Buffer For read operations, the destination buffer to store the results. For write\r
598 operations, the source buffer to write data from.\r
599\r
600\r
601 @retval EFI_SUCCESS The data was read from or written to the PCI controller.\r
602 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not\r
603 valid for the PCI configuration header of the PCI controller.\r
604 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
605 @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid.\r
606\r
607**/\r
608EFI_STATUS\r
609EFIAPI\r
610PciIoConfigRead (\r
611 IN EFI_PCI_IO_PROTOCOL *This,\r
612 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
613 IN UINT32 Offset,\r
614 IN UINTN Count,\r
615 IN OUT VOID *Buffer\r
616 )\r
617{\r
618 EFI_STATUS Status;\r
619 PCI_IO_DEVICE *PciIoDevice;\r
620 UINT64 Address;\r
621\r
622 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
623\r
624 Address = Offset;\r
625 Status = PciIoVerifyConfigAccess (PciIoDevice, Width, Count, &Address);\r
626 if (EFI_ERROR (Status)) {\r
627 return Status;\r
628 }\r
629\r
630 Status = PciIoDevice->PciRootBridgeIo->Pci.Read (\r
631 PciIoDevice->PciRootBridgeIo,\r
632 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
633 Address,\r
634 Count,\r
635 Buffer\r
636 );\r
637\r
638 if (EFI_ERROR (Status)) {\r
639 ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_READ_ERROR);\r
640 }\r
641\r
642 return Status;\r
643}\r
644\r
645/**\r
646 Enable a PCI driver to access PCI controller registers in PCI configuration space.\r
647\r
648 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
649 @param Width Signifies the width of the memory operations.\r
650 @param Offset The offset within the PCI configuration space for the PCI controller.\r
651 @param Count The number of PCI configuration operations to perform.\r
652 @param Buffer For read operations, the destination buffer to store the results. For write\r
653 operations, the source buffer to write data from.\r
654\r
655\r
656 @retval EFI_SUCCESS The data was read from or written to the PCI controller.\r
657 @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not\r
658 valid for the PCI configuration header of the PCI controller.\r
659 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
660 @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid.\r
661\r
662**/\r
663EFI_STATUS\r
664EFIAPI\r
665PciIoConfigWrite (\r
666 IN EFI_PCI_IO_PROTOCOL *This,\r
667 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
668 IN UINT32 Offset,\r
669 IN UINTN Count,\r
670 IN OUT VOID *Buffer\r
671 )\r
672{\r
673 EFI_STATUS Status;\r
674 PCI_IO_DEVICE *PciIoDevice;\r
675 UINT64 Address;\r
676\r
677 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
678\r
679 Address = Offset;\r
680 Status = PciIoVerifyConfigAccess (PciIoDevice, Width, Count, &Address);\r
681 if (EFI_ERROR (Status)) {\r
682 return Status;\r
683 }\r
684\r
685 Status = PciIoDevice->PciRootBridgeIo->Pci.Write (\r
686 PciIoDevice->PciRootBridgeIo,\r
687 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
688 Address,\r
689 Count,\r
690 Buffer\r
691 );\r
692\r
693 if (EFI_ERROR (Status)) {\r
694 ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_WRITE_ERROR);\r
695 }\r
696\r
697 return Status;\r
698}\r
699\r
700/**\r
701 Enables a PCI driver to copy one region of PCI memory space to another region of PCI\r
702 memory space.\r
703\r
704 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
705 @param Width Signifies the width of the memory operations.\r
706 @param DestBarIndex The BAR index in the standard PCI Configuration header to use as the\r
707 base address for the memory operation to perform.\r
708 @param DestOffset The destination offset within the BAR specified by DestBarIndex to\r
709 start the memory writes for the copy operation.\r
710 @param SrcBarIndex The BAR index in the standard PCI Configuration header to use as the\r
711 base address for the memory operation to perform.\r
712 @param SrcOffset The source offset within the BAR specified by SrcBarIndex to start\r
713 the memory reads for the copy operation.\r
714 @param Count The number of memory operations to perform. Bytes moved is Width\r
715 size * Count, starting at DestOffset and SrcOffset.\r
716\r
717 @retval EFI_SUCCESS The data was copied from one memory region to another memory region.\r
718 @retval EFI_UNSUPPORTED DestBarIndex not valid for this PCI controller.\r
719 @retval EFI_UNSUPPORTED SrcBarIndex not valid for this PCI controller.\r
720 @retval EFI_UNSUPPORTED The address range specified by DestOffset, Width, and Count\r
721 is not valid for the PCI BAR specified by DestBarIndex.\r
722 @retval EFI_UNSUPPORTED The address range specified by SrcOffset, Width, and Count is\r
723 not valid for the PCI BAR specified by SrcBarIndex.\r
724 @retval EFI_INVALID_PARAMETER Width is invalid.\r
725 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
726\r
727**/\r
728EFI_STATUS\r
729EFIAPI\r
730PciIoCopyMem (\r
731 IN EFI_PCI_IO_PROTOCOL *This,\r
732 IN EFI_PCI_IO_PROTOCOL_WIDTH Width,\r
733 IN UINT8 DestBarIndex,\r
734 IN UINT64 DestOffset,\r
735 IN UINT8 SrcBarIndex,\r
736 IN UINT64 SrcOffset,\r
737 IN UINTN Count\r
738 )\r
739{\r
740 EFI_STATUS Status;\r
741 PCI_IO_DEVICE *PciIoDevice;\r
742\r
743 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
744\r
745 if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
746 return EFI_INVALID_PARAMETER;\r
747 }\r
748\r
749 if (Width == EfiPciIoWidthFifoUint8 ||\r
750 Width == EfiPciIoWidthFifoUint16 ||\r
751 Width == EfiPciIoWidthFifoUint32 ||\r
752 Width == EfiPciIoWidthFifoUint64 ||\r
753 Width == EfiPciIoWidthFillUint8 ||\r
754 Width == EfiPciIoWidthFillUint16 ||\r
755 Width == EfiPciIoWidthFillUint32 ||\r
756 Width == EfiPciIoWidthFillUint64) {\r
757 return EFI_INVALID_PARAMETER;\r
758 }\r
759\r
760 Status = PciIoVerifyBarAccess (PciIoDevice, DestBarIndex, PciBarTypeMem, Width, Count, &DestOffset);\r
761 if (EFI_ERROR (Status)) {\r
762 return EFI_UNSUPPORTED;\r
763 }\r
764\r
765 Status = PciIoVerifyBarAccess (PciIoDevice, SrcBarIndex, PciBarTypeMem, Width, Count, &SrcOffset);\r
766 if (EFI_ERROR (Status)) {\r
767 return EFI_UNSUPPORTED;\r
768 }\r
769\r
770 Status = PciIoDevice->PciRootBridgeIo->CopyMem (\r
771 PciIoDevice->PciRootBridgeIo,\r
772 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
773 DestOffset,\r
774 SrcOffset,\r
775 Count\r
776 );\r
777\r
778 if (EFI_ERROR (Status)) {\r
779 ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);\r
780 }\r
781\r
782 return Status;\r
783}\r
784\r
785/**\r
786 Provides the PCI controller-specific addresses needed to access system memory.\r
787\r
788 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
789 @param Operation Indicates if the bus master is going to read or write to system memory.\r
790 @param HostAddress The system memory address to map to the PCI controller.\r
791 @param NumberOfBytes On input the number of bytes to map. On output the number of bytes\r
792 that were mapped.\r
793 @param DeviceAddress The resulting map address for the bus master PCI controller to use to\r
794 access the hosts HostAddress.\r
795 @param Mapping A resulting value to pass to Unmap().\r
796\r
797 @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.\r
798 @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer.\r
799 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
800 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
801 @retval EFI_DEVICE_ERROR The system hardware could not map the requested address.\r
802\r
803**/\r
804EFI_STATUS\r
805EFIAPI\r
806PciIoMap (\r
807 IN EFI_PCI_IO_PROTOCOL *This,\r
808 IN EFI_PCI_IO_PROTOCOL_OPERATION Operation,\r
809 IN VOID *HostAddress,\r
810 IN OUT UINTN *NumberOfBytes,\r
811 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,\r
812 OUT VOID **Mapping\r
813 )\r
814{\r
815 EFI_STATUS Status;\r
816 PCI_IO_DEVICE *PciIoDevice;\r
817\r
818 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
819\r
820 if (Operation < 0 || Operation >= EfiPciIoOperationMaximum) {\r
821 return EFI_INVALID_PARAMETER;\r
822 }\r
823\r
824 if (HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL || Mapping == NULL) {\r
825 return EFI_INVALID_PARAMETER;\r
826 }\r
827\r
828 if ((PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) != 0) {\r
829 Operation = (EFI_PCI_IO_PROTOCOL_OPERATION) (Operation + EfiPciOperationBusMasterRead64);\r
830 }\r
831\r
832 Status = PciIoDevice->PciRootBridgeIo->Map (\r
833 PciIoDevice->PciRootBridgeIo,\r
834 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) Operation,\r
835 HostAddress,\r
836 NumberOfBytes,\r
837 DeviceAddress,\r
838 Mapping\r
839 );\r
840\r
841 if (EFI_ERROR (Status)) {\r
842 ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);\r
843 }\r
844\r
845 return Status;\r
846}\r
847\r
848/**\r
849 Completes the Map() operation and releases any corresponding resources.\r
850\r
851 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
852 @param Mapping The mapping value returned from Map().\r
853\r
854 @retval EFI_SUCCESS The range was unmapped.\r
855 @retval EFI_DEVICE_ERROR The data was not committed to the target system memory.\r
856\r
857**/\r
858EFI_STATUS\r
859EFIAPI\r
860PciIoUnmap (\r
861 IN EFI_PCI_IO_PROTOCOL *This,\r
862 IN VOID *Mapping\r
863 )\r
864{\r
865 EFI_STATUS Status;\r
866 PCI_IO_DEVICE *PciIoDevice;\r
867\r
868 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
869\r
870 Status = PciIoDevice->PciRootBridgeIo->Unmap (\r
871 PciIoDevice->PciRootBridgeIo,\r
872 Mapping\r
873 );\r
874\r
875 if (EFI_ERROR (Status)) {\r
876 ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);\r
877 }\r
878\r
879 return Status;\r
880}\r
881\r
882/**\r
883 Allocates pages that are suitable for an EfiPciIoOperationBusMasterCommonBuffer\r
884 mapping.\r
885\r
886 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
887 @param Type This parameter is not used and must be ignored.\r
888 @param MemoryType The type of memory to allocate, EfiBootServicesData or\r
889 EfiRuntimeServicesData.\r
890 @param Pages The number of pages to allocate.\r
891 @param HostAddress A pointer to store the base system memory address of the\r
892 allocated range.\r
893 @param Attributes The requested bit mask of attributes for the allocated range.\r
894\r
895 @retval EFI_SUCCESS The requested memory pages were allocated.\r
896 @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are\r
897 MEMORY_WRITE_COMBINE and MEMORY_CACHED.\r
898 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
899 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.\r
900\r
901**/\r
902EFI_STATUS\r
903EFIAPI\r
904PciIoAllocateBuffer (\r
905 IN EFI_PCI_IO_PROTOCOL *This,\r
906 IN EFI_ALLOCATE_TYPE Type,\r
907 IN EFI_MEMORY_TYPE MemoryType,\r
908 IN UINTN Pages,\r
909 OUT VOID **HostAddress,\r
910 IN UINT64 Attributes\r
911 )\r
912{\r
913 EFI_STATUS Status;\r
914 PCI_IO_DEVICE *PciIoDevice;\r
915\r
916 if ((Attributes &\r
917 (~(EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE | EFI_PCI_ATTRIBUTE_MEMORY_CACHED))) != 0){\r
918 return EFI_UNSUPPORTED;\r
919 }\r
920\r
921 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
922\r
923 if ((PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) != 0) {\r
924 Attributes |= EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE;\r
925 }\r
926\r
927 Status = PciIoDevice->PciRootBridgeIo->AllocateBuffer (\r
928 PciIoDevice->PciRootBridgeIo,\r
929 Type,\r
930 MemoryType,\r
931 Pages,\r
932 HostAddress,\r
933 Attributes\r
934 );\r
935\r
936 if (EFI_ERROR (Status)) {\r
937 ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);\r
938 }\r
939\r
940 return Status;\r
941}\r
942\r
943/**\r
944 Frees memory that was allocated with AllocateBuffer().\r
945\r
946 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
947 @param Pages The number of pages to free.\r
948 @param HostAddress The base system memory address of the allocated range.\r
949\r
950 @retval EFI_SUCCESS The requested memory pages were freed.\r
951 @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages\r
952 was not allocated with AllocateBuffer().\r
953\r
954**/\r
955EFI_STATUS\r
956EFIAPI\r
957PciIoFreeBuffer (\r
958 IN EFI_PCI_IO_PROTOCOL *This,\r
959 IN UINTN Pages,\r
960 IN VOID *HostAddress\r
961 )\r
962{\r
963 EFI_STATUS Status;\r
964 PCI_IO_DEVICE *PciIoDevice;\r
965\r
966 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
967\r
968 Status = PciIoDevice->PciRootBridgeIo->FreeBuffer (\r
969 PciIoDevice->PciRootBridgeIo,\r
970 Pages,\r
971 HostAddress\r
972 );\r
973\r
974 if (EFI_ERROR (Status)) {\r
975 ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);\r
976 }\r
977\r
978 return Status;\r
979}\r
980\r
981/**\r
982 Flushes all PCI posted write transactions from a PCI host bridge to system memory.\r
983\r
984 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
985\r
986 @retval EFI_SUCCESS The PCI posted write transactions were flushed from the PCI host\r
987 bridge to system memory.\r
988 @retval EFI_DEVICE_ERROR The PCI posted write transactions were not flushed from the PCI\r
989 host bridge due to a hardware error.\r
990\r
991**/\r
992EFI_STATUS\r
993EFIAPI\r
994PciIoFlush (\r
995 IN EFI_PCI_IO_PROTOCOL *This\r
996 )\r
997{\r
998 EFI_STATUS Status;\r
999 PCI_IO_DEVICE *PciIoDevice;\r
1000\r
1001 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
1002\r
1003 Status = PciIoDevice->PciRootBridgeIo->Flush (\r
1004 PciIoDevice->PciRootBridgeIo\r
1005 );\r
1006 if (EFI_ERROR (Status)) {\r
1007 ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);\r
1008 }\r
1009\r
1010 return Status;\r
1011}\r
1012\r
1013/**\r
1014 Retrieves this PCI controller's current PCI bus number, device number, and function number.\r
1015\r
1016 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
1017 @param SegmentNumber The PCI controller's current PCI segment number.\r
1018 @param BusNumber The PCI controller's current PCI bus number.\r
1019 @param DeviceNumber The PCI controller's current PCI device number.\r
1020 @param FunctionNumber The PCI controller's current PCI function number.\r
1021\r
1022 @retval EFI_SUCCESS The PCI controller location was returned.\r
1023 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
1024\r
1025**/\r
1026EFI_STATUS\r
1027EFIAPI\r
1028PciIoGetLocation (\r
1029 IN EFI_PCI_IO_PROTOCOL *This,\r
1030 OUT UINTN *Segment,\r
1031 OUT UINTN *Bus,\r
1032 OUT UINTN *Device,\r
1033 OUT UINTN *Function\r
1034 )\r
1035{\r
1036 PCI_IO_DEVICE *PciIoDevice;\r
1037\r
1038 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
1039\r
1040 if (Segment == NULL || Bus == NULL || Device == NULL || Function == NULL) {\r
1041 return EFI_INVALID_PARAMETER;\r
1042 }\r
1043\r
1044 *Segment = PciIoDevice->PciRootBridgeIo->SegmentNumber;\r
1045 *Bus = PciIoDevice->BusNumber;\r
1046 *Device = PciIoDevice->DeviceNumber;\r
1047 *Function = PciIoDevice->FunctionNumber;\r
1048\r
1049 return EFI_SUCCESS;\r
1050}\r
1051\r
1052/**\r
1053 Check BAR type for PCI resource.\r
1054\r
1055 @param PciIoDevice PCI device instance.\r
1056 @param BarIndex The BAR index of the standard PCI Configuration header to use as the\r
1057 base address for the memory or I/O operation to perform.\r
1058 @param BarType Memory or I/O.\r
1059\r
1060 @retval TRUE Pci device's bar type is same with input BarType.\r
1061 @retval TRUE Pci device's bar type is not same with input BarType.\r
1062\r
1063**/\r
1064BOOLEAN\r
1065CheckBarType (\r
1066 IN PCI_IO_DEVICE *PciIoDevice,\r
1067 IN UINT8 BarIndex,\r
1068 IN PCI_BAR_TYPE BarType\r
1069 )\r
1070{\r
1071 switch (BarType) {\r
1072\r
1073 case PciBarTypeMem:\r
1074\r
1075 if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeMem32 &&\r
1076 PciIoDevice->PciBar[BarIndex].BarType != PciBarTypePMem32 &&\r
1077 PciIoDevice->PciBar[BarIndex].BarType != PciBarTypePMem64 &&\r
1078 PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeMem64 ) {\r
1079 return FALSE;\r
1080 }\r
1081\r
1082 return TRUE;\r
1083\r
1084 case PciBarTypeIo:\r
1085 if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeIo32 &&\r
1086 PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeIo16){\r
1087 return FALSE;\r
1088 }\r
1089\r
1090 return TRUE;\r
1091\r
1092 default:\r
1093 break;\r
1094 }\r
1095\r
1096 return FALSE;\r
1097}\r
1098\r
1099/**\r
1100 Set/Disable new attributes to a Root Bridge.\r
1101\r
1102 @param PciIoDevice Pci device instance.\r
1103 @param Attributes New attribute want to be set.\r
1104 @param Operation Set or Disable.\r
1105\r
1106 @retval EFI_UNSUPPORTED If root bridge does not support change attribute.\r
1107 @retval EFI_SUCCESS Successfully set new attributs.\r
1108\r
1109**/\r
1110EFI_STATUS\r
1111ModifyRootBridgeAttributes (\r
1112 IN PCI_IO_DEVICE *PciIoDevice,\r
1113 IN UINT64 Attributes,\r
1114 IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation\r
1115 )\r
1116{\r
1117 UINT64 PciRootBridgeSupports;\r
1118 UINT64 PciRootBridgeAttributes;\r
1119 UINT64 NewPciRootBridgeAttributes;\r
1120 EFI_STATUS Status;\r
1121\r
1122 //\r
1123 // Get the current attributes of this PCI device's PCI Root Bridge\r
1124 //\r
1125 Status = PciIoDevice->PciRootBridgeIo->GetAttributes (\r
1126 PciIoDevice->PciRootBridgeIo,\r
1127 &PciRootBridgeSupports,\r
1128 &PciRootBridgeAttributes\r
1129 );\r
1130 if (EFI_ERROR (Status)) {\r
1131 return EFI_UNSUPPORTED;\r
1132 }\r
1133\r
1134 //\r
1135 // Record the new attribute of the Root Bridge\r
1136 //\r
1137 if (Operation == EfiPciIoAttributeOperationEnable) {\r
1138 NewPciRootBridgeAttributes = PciRootBridgeAttributes | Attributes;\r
1139 } else {\r
1140 NewPciRootBridgeAttributes = PciRootBridgeAttributes & (~Attributes);\r
1141 }\r
1142\r
1143 //\r
1144 // Call the PCI Root Bridge to attempt to modify the attributes\r
1145 //\r
1146 if ((NewPciRootBridgeAttributes ^ PciRootBridgeAttributes) != 0) {\r
1147\r
1148 Status = PciIoDevice->PciRootBridgeIo->SetAttributes (\r
1149 PciIoDevice->PciRootBridgeIo,\r
1150 NewPciRootBridgeAttributes,\r
1151 NULL,\r
1152 NULL\r
1153 );\r
1154 if (EFI_ERROR (Status)) {\r
1155 //\r
1156 // The PCI Root Bridge could not modify the attributes, so return the error.\r
1157 //\r
1158 return EFI_UNSUPPORTED;\r
1159 }\r
1160 }\r
1161\r
1162 //\r
1163 // Also update the attributes for this Root Bridge structure\r
1164 //\r
1165 PciIoDevice->Attributes = NewPciRootBridgeAttributes;\r
1166\r
1167 return EFI_SUCCESS;\r
1168}\r
1169\r
1170/**\r
1171 Check whether this device can be enable/disable to snoop.\r
1172\r
1173 @param PciIoDevice Pci device instance.\r
1174 @param Operation Enable/Disable.\r
1175\r
1176 @retval EFI_UNSUPPORTED Pci device is not GFX device or not support snoop.\r
1177 @retval EFI_SUCCESS Snoop can be supported.\r
1178\r
1179**/\r
1180EFI_STATUS\r
1181SupportPaletteSnoopAttributes (\r
1182 IN PCI_IO_DEVICE *PciIoDevice,\r
1183 IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation\r
1184 )\r
1185{\r
1186 PCI_IO_DEVICE *Temp;\r
1187 UINT16 VGACommand;\r
1188\r
1189 //\r
1190 // Snoop attribute can be only modified by GFX\r
1191 //\r
1192 if (!IS_PCI_GFX (&PciIoDevice->Pci)) {\r
1193 return EFI_UNSUPPORTED;\r
1194 }\r
1195\r
1196 //\r
1197 // Get the boot VGA on the same segement\r
1198 //\r
1199 Temp = ActiveVGADeviceOnTheSameSegment (PciIoDevice);\r
1200\r
1201 if (Temp == NULL) {\r
1202 //\r
1203 // If there is no VGA device on the segement, set\r
1204 // this graphics card to decode the palette range\r
1205 //\r
1206 return EFI_SUCCESS;\r
1207 }\r
1208\r
1209 //\r
1210 // Check these two agents are on the same path\r
1211 //\r
1212 if (!PciDevicesOnTheSamePath (Temp, PciIoDevice)) {\r
1213 //\r
1214 // they are not on the same path, so snoop can be enabled or disabled\r
1215 //\r
1216 return EFI_SUCCESS;\r
1217 }\r
1218 //\r
1219 // Check if they are on the same bus\r
1220 //\r
1221 if (Temp->Parent == PciIoDevice->Parent) {\r
1222\r
1223 PCI_READ_COMMAND_REGISTER (Temp, &VGACommand);\r
1224\r
1225 //\r
1226 // If they are on the same bus, either one can\r
1227 // be set to snoop, the other set to decode\r
1228 //\r
1229 if ((VGACommand & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) != 0) {\r
1230 //\r
1231 // VGA has set to snoop, so GFX can be only set to disable snoop\r
1232 //\r
1233 if (Operation == EfiPciIoAttributeOperationEnable) {\r
1234 return EFI_UNSUPPORTED;\r
1235 }\r
1236 } else {\r
1237 //\r
1238 // VGA has disabled to snoop, so GFX can be only enabled\r
1239 //\r
1240 if (Operation == EfiPciIoAttributeOperationDisable) {\r
1241 return EFI_UNSUPPORTED;\r
1242 }\r
1243 }\r
1244\r
1245 return EFI_SUCCESS;\r
1246 }\r
1247\r
1248 //\r
1249 // If they are on the same path but on the different bus\r
1250 // The first agent is set to snoop, the second one set to\r
1251 // decode\r
1252 //\r
1253\r
1254 if (Temp->BusNumber < PciIoDevice->BusNumber) {\r
1255 //\r
1256 // GFX should be set to decode\r
1257 //\r
1258 if (Operation == EfiPciIoAttributeOperationDisable) {\r
1259 PCI_ENABLE_COMMAND_REGISTER (Temp, EFI_PCI_COMMAND_VGA_PALETTE_SNOOP);\r
1260 Temp->Attributes |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;\r
1261 } else {\r
1262 return EFI_UNSUPPORTED;\r
1263 }\r
1264\r
1265 } else {\r
1266 //\r
1267 // GFX should be set to snoop\r
1268 //\r
1269 if (Operation == EfiPciIoAttributeOperationEnable) {\r
1270 PCI_DISABLE_COMMAND_REGISTER (Temp, EFI_PCI_COMMAND_VGA_PALETTE_SNOOP);\r
1271 Temp->Attributes &= (~EFI_PCI_COMMAND_VGA_PALETTE_SNOOP);\r
1272 } else {\r
1273 return EFI_UNSUPPORTED;\r
1274 }\r
1275\r
1276 }\r
1277\r
1278 return EFI_SUCCESS;\r
1279}\r
1280\r
1281/**\r
1282 Performs an operation on the attributes that this PCI controller supports. The operations include\r
1283 getting the set of supported attributes, retrieving the current attributes, setting the current\r
1284 attributes, enabling attributes, and disabling attributes.\r
1285\r
1286 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
1287 @param Operation The operation to perform on the attributes for this PCI controller.\r
1288 @param Attributes The mask of attributes that are used for Set, Enable, and Disable\r
1289 operations.\r
1290 @param Result A pointer to the result mask of attributes that are returned for the Get\r
1291 and Supported operations.\r
1292\r
1293 @retval EFI_SUCCESS The operation on the PCI controller's attributes was completed.\r
1294 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
1295 @retval EFI_UNSUPPORTED one or more of the bits set in\r
1296 Attributes are not supported by this PCI controller or one of\r
1297 its parent bridges when Operation is Set, Enable or Disable.\r
1298\r
1299**/\r
1300EFI_STATUS\r
1301EFIAPI\r
1302PciIoAttributes (\r
1303 IN EFI_PCI_IO_PROTOCOL * This,\r
1304 IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,\r
1305 IN UINT64 Attributes,\r
1306 OUT UINT64 *Result OPTIONAL\r
1307 )\r
1308{\r
1309 EFI_STATUS Status;\r
1310\r
1311 PCI_IO_DEVICE *PciIoDevice;\r
1312 PCI_IO_DEVICE *UpStreamBridge;\r
1313 PCI_IO_DEVICE *Temp;\r
1314\r
1315 UINT64 Supports;\r
1316 UINT64 UpStreamAttributes;\r
1317 UINT16 BridgeControl;\r
1318 UINT16 Command;\r
1319\r
1320 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
1321\r
1322 switch (Operation) {\r
1323 case EfiPciIoAttributeOperationGet:\r
1324 if (Result == NULL) {\r
1325 return EFI_INVALID_PARAMETER;\r
1326 }\r
1327\r
1328 *Result = PciIoDevice->Attributes;\r
1329 return EFI_SUCCESS;\r
1330\r
1331 case EfiPciIoAttributeOperationSupported:\r
1332 if (Result == NULL) {\r
1333 return EFI_INVALID_PARAMETER;\r
1334 }\r
1335\r
1336 *Result = PciIoDevice->Supports;\r
1337 return EFI_SUCCESS;\r
1338\r
1339 case EfiPciIoAttributeOperationSet:\r
1340 Status = PciIoDevice->PciIo.Attributes (\r
1341 &(PciIoDevice->PciIo),\r
1342 EfiPciIoAttributeOperationEnable,\r
1343 Attributes,\r
1344 NULL\r
1345 );\r
1346 if (EFI_ERROR (Status)) {\r
1347 return EFI_UNSUPPORTED;\r
1348 }\r
1349\r
1350 Status = PciIoDevice->PciIo.Attributes (\r
1351 &(PciIoDevice->PciIo),\r
1352 EfiPciIoAttributeOperationDisable,\r
1353 (~Attributes) & (PciIoDevice->Supports),\r
1354 NULL\r
1355 );\r
1356 if (EFI_ERROR (Status)) {\r
1357 return EFI_UNSUPPORTED;\r
1358 }\r
1359\r
1360 return EFI_SUCCESS;\r
1361\r
1362 case EfiPciIoAttributeOperationEnable:\r
1363 case EfiPciIoAttributeOperationDisable:\r
1364 break;\r
1365\r
1366 default:\r
1367 return EFI_INVALID_PARAMETER;\r
1368 }\r
1369 //\r
1370 // Just a trick for ENABLE attribute\r
1371 // EFI_PCI_DEVICE_ENABLE is not defined in UEFI spec, which is the internal usage.\r
1372 // So, this logic doesn't confrom to UEFI spec, which should be removed.\r
1373 // But this trick logic is still kept for some binary drivers that depend on it.\r
1374 //\r
1375 if ((Attributes & EFI_PCI_DEVICE_ENABLE) == EFI_PCI_DEVICE_ENABLE) {\r
1376 Attributes &= (PciIoDevice->Supports);\r
1377\r
1378 //\r
1379 // Raise the EFI_P_PC_ENABLE Status code\r
1380 //\r
1381 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
1382 EFI_PROGRESS_CODE,\r
1383 EFI_IO_BUS_PCI | EFI_P_PC_ENABLE,\r
1384 PciIoDevice->DevicePath\r
1385 );\r
1386 }\r
1387\r
1388 //\r
1389 // If no attributes can be supported, then return.\r
1390 // Otherwise, set the attributes that it can support.\r
1391 //\r
1392 Supports = (PciIoDevice->Supports) & Attributes;\r
1393 if (Supports != Attributes) {\r
1394 return EFI_UNSUPPORTED;\r
1395 }\r
1396\r
1397 //\r
1398 // For Root Bridge, just call RootBridgeIo to set attributes;\r
1399 //\r
1400 if (PciIoDevice->Parent == NULL) {\r
1401 Status = ModifyRootBridgeAttributes (PciIoDevice, Attributes, Operation);\r
1402 return Status;\r
1403 }\r
1404\r
1405 Command = 0;\r
1406 BridgeControl = 0;\r
1407\r
1408 //\r
1409 // Check VGA and VGA16, they can not be set at the same time\r
1410 //\r
1411 if (((Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) != 0 &&\r
1412 (Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO_16) != 0) ||\r
1413 ((Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) != 0 &&\r
1414 (Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16) != 0) ||\r
1415 ((Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO) != 0 &&\r
1416 (Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO_16) != 0) ||\r
1417 ((Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO) != 0 &&\r
1418 (Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16) != 0) ) {\r
1419 return EFI_UNSUPPORTED;\r
1420 }\r
1421\r
1422 //\r
1423 // For PPB & P2C, set relevant attribute bits\r
1424 //\r
1425 if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {\r
1426\r
1427 if ((Attributes & (EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16)) != 0) {\r
1428 BridgeControl |= EFI_PCI_BRIDGE_CONTROL_VGA;\r
1429 }\r
1430\r
1431 if ((Attributes & EFI_PCI_IO_ATTRIBUTE_ISA_IO) != 0) {\r
1432 BridgeControl |= EFI_PCI_BRIDGE_CONTROL_ISA;\r
1433 }\r
1434\r
1435 if ((Attributes & (EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO | EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16)) != 0) {\r
1436 Command |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;\r
1437 }\r
1438\r
1439 if ((Attributes & (EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16 | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16)) != 0) {\r
1440 BridgeControl |= EFI_PCI_BRIDGE_CONTROL_VGA_16;\r
1441 }\r
1442\r
1443 } else {\r
1444 //\r
1445 // Do with the attributes on VGA\r
1446 // Only for VGA's legacy resource, we just can enable once.\r
1447 //\r
1448 if ((Attributes &\r
1449 (EFI_PCI_IO_ATTRIBUTE_VGA_IO |\r
1450 EFI_PCI_IO_ATTRIBUTE_VGA_IO_16 |\r
1451 EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY)) != 0) {\r
1452 //\r
1453 // Check if a VGA has been enabled before enabling a new one\r
1454 //\r
1455 if (Operation == EfiPciIoAttributeOperationEnable) {\r
1456 //\r
1457 // Check if there have been an active VGA device on the same segment\r
1458 //\r
1459 Temp = ActiveVGADeviceOnTheSameSegment (PciIoDevice);\r
1460 if (Temp != NULL && Temp != PciIoDevice) {\r
1461 //\r
1462 // An active VGA has been detected, so can not enable another\r
1463 //\r
1464 return EFI_UNSUPPORTED;\r
1465 }\r
1466 }\r
1467 }\r
1468\r
1469 //\r
1470 // Do with the attributes on GFX\r
1471 //\r
1472 if ((Attributes & (EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO | EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16)) != 0) {\r
1473\r
1474 if (Operation == EfiPciIoAttributeOperationEnable) {\r
1475 //\r
1476 // Check if snoop can be enabled in current configuration\r
1477 //\r
1478 Status = SupportPaletteSnoopAttributes (PciIoDevice, Operation);\r
1479\r
1480 if (EFI_ERROR (Status)) {\r
1481\r
1482 //\r
1483 // Enable operation is forbidden, so mask the bit in attributes\r
1484 // so as to keep consistent with the actual Status\r
1485 //\r
1486 // Attributes &= (~EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO);\r
1487 //\r
1488 //\r
1489 //\r
1490 return EFI_UNSUPPORTED;\r
1491\r
1492 }\r
1493 }\r
1494\r
1495 //\r
1496 // It can be supported, so get ready to set the bit\r
1497 //\r
1498 Command |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;\r
1499 }\r
1500 }\r
1501\r
1502 if ((Attributes & EFI_PCI_IO_ATTRIBUTE_IO) != 0) {\r
1503 Command |= EFI_PCI_COMMAND_IO_SPACE;\r
1504 }\r
1505\r
1506 if ((Attributes & EFI_PCI_IO_ATTRIBUTE_MEMORY) != 0) {\r
1507 Command |= EFI_PCI_COMMAND_MEMORY_SPACE;\r
1508 }\r
1509\r
1510 if ((Attributes & EFI_PCI_IO_ATTRIBUTE_BUS_MASTER) != 0) {\r
1511 Command |= EFI_PCI_COMMAND_BUS_MASTER;\r
1512 }\r
1513 //\r
1514 // The upstream bridge should be also set to revelant attribute\r
1515 // expect for IO, Mem and BusMaster\r
1516 //\r
1517 UpStreamAttributes = Attributes &\r
1518 (~(EFI_PCI_IO_ATTRIBUTE_IO |\r
1519 EFI_PCI_IO_ATTRIBUTE_MEMORY |\r
1520 EFI_PCI_IO_ATTRIBUTE_BUS_MASTER\r
1521 )\r
1522 );\r
1523 UpStreamBridge = PciIoDevice->Parent;\r
1524\r
1525 if (Operation == EfiPciIoAttributeOperationEnable) {\r
1526 //\r
1527 // Enable relevant attributes to command register and bridge control register\r
1528 //\r
1529 Status = PCI_ENABLE_COMMAND_REGISTER (PciIoDevice, Command);\r
1530 if (BridgeControl != 0) {\r
1531 Status = PCI_ENABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, BridgeControl);\r
1532 }\r
1533\r
1534 PciIoDevice->Attributes |= Attributes;\r
1535\r
1536 //\r
1537 // Enable attributes of the upstream bridge\r
1538 //\r
1539 Status = UpStreamBridge->PciIo.Attributes (\r
1540 &(UpStreamBridge->PciIo),\r
1541 EfiPciIoAttributeOperationEnable,\r
1542 UpStreamAttributes,\r
1543 NULL\r
1544 );\r
1545 } else {\r
1546\r
1547 //\r
1548 // Disable relevant attributes to command register and bridge control register\r
1549 //\r
1550 Status = PCI_DISABLE_COMMAND_REGISTER (PciIoDevice, Command);\r
1551 if (BridgeControl != 0) {\r
1552 Status = PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, BridgeControl);\r
1553 }\r
1554\r
1555 PciIoDevice->Attributes &= (~Attributes);\r
1556 Status = EFI_SUCCESS;\r
1557\r
1558 }\r
1559\r
1560 if (EFI_ERROR (Status)) {\r
1561 ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);\r
1562 }\r
1563\r
1564 return Status;\r
1565}\r
1566\r
1567/**\r
1568 Gets the attributes that this PCI controller supports setting on a BAR using\r
1569 SetBarAttributes(), and retrieves the list of resource descriptors for a BAR.\r
1570\r
1571 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
1572 @param BarIndex The BAR index of the standard PCI Configuration header to use as the\r
1573 base address for resource range. The legal range for this field is 0..5.\r
1574 @param Supports A pointer to the mask of attributes that this PCI controller supports\r
1575 setting for this BAR with SetBarAttributes().\r
1576 @param Resources A pointer to the ACPI 2.0 resource descriptors that describe the current\r
1577 configuration of this BAR of the PCI controller.\r
1578\r
1579 @retval EFI_SUCCESS If Supports is not NULL, then the attributes that the PCI\r
1580 controller supports are returned in Supports. If Resources\r
1581 is not NULL, then the ACPI 2.0 resource descriptors that the PCI\r
1582 controller is currently using are returned in Resources.\r
1583 @retval EFI_INVALID_PARAMETER Both Supports and Attributes are NULL.\r
1584 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.\r
1585 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to allocate\r
1586 Resources.\r
1587\r
1588**/\r
1589EFI_STATUS\r
1590EFIAPI\r
1591PciIoGetBarAttributes (\r
1592 IN EFI_PCI_IO_PROTOCOL * This,\r
1593 IN UINT8 BarIndex,\r
1594 OUT UINT64 *Supports, OPTIONAL\r
1595 OUT VOID **Resources OPTIONAL\r
1596 )\r
1597{\r
1598\r
1599 UINT8 *Configuration;\r
1600 UINT8 NumConfig;\r
1601 PCI_IO_DEVICE *PciIoDevice;\r
1602 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;\r
1603 EFI_ACPI_END_TAG_DESCRIPTOR *PtrEnd;\r
1604\r
1605 NumConfig = 0;\r
1606\r
1607 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
1608\r
1609 if (Supports == NULL && Resources == NULL) {\r
1610 return EFI_INVALID_PARAMETER;\r
1611 }\r
1612\r
1613 if (BarIndex >= PCI_MAX_BAR) {\r
1614 return EFI_UNSUPPORTED;\r
1615 }\r
1616\r
1617 //\r
1618 // This driver does not support modifications to the WRITE_COMBINE or\r
1619 // CACHED attributes for BAR ranges.\r
1620 //\r
1621 if (Supports != NULL) {\r
1622 *Supports = PciIoDevice->Supports & EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED & EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE;\r
1623 }\r
1624\r
1625 if (Resources != NULL) {\r
1626\r
1627 if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeUnknown) {\r
1628 NumConfig = 1;\r
1629 }\r
1630\r
1631 Configuration = AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));\r
1632 if (Configuration == NULL) {\r
1633 return EFI_OUT_OF_RESOURCES;\r
1634 }\r
1635\r
1636 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;\r
1637\r
1638 if (NumConfig == 1) {\r
1639 Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
1640 Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
1641\r
1642 Ptr->AddrRangeMin = PciIoDevice->PciBar[BarIndex].BaseAddress;\r
1643 Ptr->AddrLen = PciIoDevice->PciBar[BarIndex].Length;\r
1644 Ptr->AddrRangeMax = PciIoDevice->PciBar[BarIndex].Alignment;\r
1645\r
1646 switch (PciIoDevice->PciBar[BarIndex].BarType) {\r
1647 case PciBarTypeIo16:\r
1648 case PciBarTypeIo32:\r
1649 //\r
1650 // Io\r
1651 //\r
1652 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;\r
1653 break;\r
1654\r
1655 case PciBarTypeMem32:\r
1656 //\r
1657 // Mem\r
1658 //\r
1659 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
1660 //\r
1661 // 32 bit\r
1662 //\r
1663 Ptr->AddrSpaceGranularity = 32;\r
1664 break;\r
1665\r
1666 case PciBarTypePMem32:\r
1667 //\r
1668 // Mem\r
1669 //\r
1670 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
1671 //\r
1672 // prefechable\r
1673 //\r
1674 Ptr->SpecificFlag = 0x6;\r
1675 //\r
1676 // 32 bit\r
1677 //\r
1678 Ptr->AddrSpaceGranularity = 32;\r
1679 break;\r
1680\r
1681 case PciBarTypeMem64:\r
1682 //\r
1683 // Mem\r
1684 //\r
1685 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
1686 //\r
1687 // 64 bit\r
1688 //\r
1689 Ptr->AddrSpaceGranularity = 64;\r
1690 break;\r
1691\r
1692 case PciBarTypePMem64:\r
1693 //\r
1694 // Mem\r
1695 //\r
1696 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
1697 //\r
1698 // prefechable\r
1699 //\r
1700 Ptr->SpecificFlag = 0x6;\r
1701 //\r
1702 // 64 bit\r
1703 //\r
1704 Ptr->AddrSpaceGranularity = 64;\r
1705 break;\r
1706\r
1707 default:\r
1708 break;\r
1709 }\r
1710\r
1711 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));\r
1712 }\r
1713\r
1714 //\r
1715 // put the checksum\r
1716 //\r
1717 PtrEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *) ((UINT8 *) Ptr);\r
1718 PtrEnd->Desc = ACPI_END_TAG_DESCRIPTOR;\r
1719 PtrEnd->Checksum = 0;\r
1720\r
1721 *Resources = Configuration;\r
1722 }\r
1723\r
1724 return EFI_SUCCESS;\r
1725}\r
1726\r
1727/**\r
1728 Sets the attributes for a range of a BAR on a PCI controller.\r
1729\r
1730 @param This A pointer to the EFI_PCI_IO_PROTOCOL instance.\r
1731 @param Attributes The mask of attributes to set for the resource range specified by\r
1732 BarIndex, Offset, and Length.\r
1733 @param BarIndex The BAR index of the standard PCI Configuration header to use as the\r
1734 base address for resource range. The legal range for this field is 0..5.\r
1735 @param Offset A pointer to the BAR relative base address of the resource range to be\r
1736 modified by the attributes specified by Attributes.\r
1737 @param Length A pointer to the length of the resource range to be modified by the\r
1738 attributes specified by Attributes.\r
1739\r
1740 @retval EFI_SUCCESS The set of attributes specified by Attributes for the resource\r
1741 range specified by BarIndex, Offset, and Length were\r
1742 set on the PCI controller, and the actual resource range is returned\r
1743 in Offset and Length.\r
1744 @retval EFI_INVALID_PARAMETER Offset or Length is NULL.\r
1745 @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller.\r
1746 @retval EFI_OUT_OF_RESOURCES There are not enough resources to set the attributes on the\r
1747 resource range specified by BarIndex, Offset, and\r
1748 Length.\r
1749\r
1750**/\r
1751EFI_STATUS\r
1752EFIAPI\r
1753PciIoSetBarAttributes (\r
1754 IN EFI_PCI_IO_PROTOCOL *This,\r
1755 IN UINT64 Attributes,\r
1756 IN UINT8 BarIndex,\r
1757 IN OUT UINT64 *Offset,\r
1758 IN OUT UINT64 *Length\r
1759 )\r
1760{\r
1761 EFI_STATUS Status;\r
1762 PCI_IO_DEVICE *PciIoDevice;\r
1763 UINT64 NonRelativeOffset;\r
1764 UINT64 Supports;\r
1765\r
1766 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
1767\r
1768 //\r
1769 // Make sure Offset and Length are not NULL\r
1770 //\r
1771 if (Offset == NULL || Length == NULL) {\r
1772 return EFI_INVALID_PARAMETER;\r
1773 }\r
1774\r
1775 if (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypeUnknown) {\r
1776 return EFI_UNSUPPORTED;\r
1777 }\r
1778 //\r
1779 // This driver does not support setting the WRITE_COMBINE or the CACHED attributes.\r
1780 // If Attributes is not 0, then return EFI_UNSUPPORTED.\r
1781 //\r
1782 Supports = PciIoDevice->Supports & EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED & EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE;\r
1783\r
1784 if (Attributes != (Attributes & Supports)) {\r
1785 return EFI_UNSUPPORTED;\r
1786 }\r
1787 //\r
1788 // Attributes must be supported. Make sure the BAR range describd by BarIndex, Offset, and\r
1789 // Length are valid for this PCI device.\r
1790 //\r
1791 NonRelativeOffset = *Offset;\r
1792 Status = PciIoVerifyBarAccess (\r
1793 PciIoDevice,\r
1794 BarIndex,\r
1795 PciBarTypeMem,\r
1796 EfiPciIoWidthUint8,\r
1797 (UINT32) *Length,\r
1798 &NonRelativeOffset\r
1799 );\r
1800 if (EFI_ERROR (Status)) {\r
1801 return EFI_UNSUPPORTED;\r
1802 }\r
1803\r
1804 return EFI_SUCCESS;\r
1805}\r
1806\r
1807/**\r
1808 Program parent bridge's attribute recurrently.\r
1809\r
1810 @param PciIoDevice Child Pci device instance\r
1811 @param Operation The operation to perform on the attributes for this PCI controller.\r
1812 @param Attributes The mask of attributes that are used for Set, Enable, and Disable\r
1813 operations.\r
1814\r
1815 @retval EFI_SUCCESS The operation on the PCI controller's attributes was completed.\r
1816 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
1817 @retval EFI_UNSUPPORTED one or more of the bits set in\r
1818 Attributes are not supported by this PCI controller or one of\r
1819 its parent bridges when Operation is Set, Enable or Disable.\r
1820\r
1821**/\r
1822EFI_STATUS\r
1823UpStreamBridgesAttributes (\r
1824 IN PCI_IO_DEVICE *PciIoDevice,\r
1825 IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,\r
1826 IN UINT64 Attributes\r
1827 )\r
1828{\r
1829 PCI_IO_DEVICE *Parent;\r
1830 EFI_PCI_IO_PROTOCOL *PciIo;\r
1831\r
1832 Parent = PciIoDevice->Parent;\r
1833\r
1834 while (Parent != NULL && IS_PCI_BRIDGE (&Parent->Pci)) {\r
1835\r
1836 //\r
1837 // Get the PciIo Protocol\r
1838 //\r
1839 PciIo = &Parent->PciIo;\r
1840\r
1841 PciIo->Attributes (PciIo, Operation, Attributes, NULL);\r
1842\r
1843 Parent = Parent->Parent;\r
1844 }\r
1845\r
1846 return EFI_SUCCESS;\r
1847}\r
1848\r
1849/**\r
1850 Test whether two Pci devices has same parent bridge.\r
1851\r
1852 @param PciDevice1 The first pci device for testing.\r
1853 @param PciDevice2 The second pci device for testing.\r
1854\r
1855 @retval TRUE Two Pci device has the same parent bridge.\r
1856 @retval FALSE Two Pci device has not the same parent bridge.\r
1857\r
1858**/\r
1859BOOLEAN\r
1860PciDevicesOnTheSamePath (\r
1861 IN PCI_IO_DEVICE *PciDevice1,\r
1862 IN PCI_IO_DEVICE *PciDevice2\r
1863 )\r
1864{\r
1865 BOOLEAN Existed1;\r
1866 BOOLEAN Existed2;\r
1867\r
1868 if (PciDevice1->Parent == PciDevice2->Parent) {\r
1869 return TRUE;\r
1870 }\r
1871\r
1872 Existed1 = PciDeviceExisted (PciDevice1->Parent, PciDevice2);\r
1873 Existed2 = PciDeviceExisted (PciDevice2->Parent, PciDevice1);\r
1874\r
1875 return (BOOLEAN) (Existed1 || Existed2);\r
1876}\r
1877\r