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