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