TianoCore EDK2 master
Loading...
Searching...
No Matches
PciIo.c
Go to the documentation of this file.
1
9#include "PciBus.h"
10
11extern EDKII_IOMMU_PROTOCOL *mIoMmuProtocol;
12
13//
14// Pci Io Protocol Interface
15//
16EFI_PCI_IO_PROTOCOL mPciIoInterface = {
19 {
22 },
23 {
26 },
27 {
30 },
41 0,
42 NULL
43};
44
51VOID
53 IN PCI_IO_DEVICE *PciIoDevice
54 )
55{
56 CopyMem (&PciIoDevice->PciIo, &mPciIoInterface, sizeof (EFI_PCI_IO_PROTOCOL));
57}
58
76 IN PCI_IO_DEVICE *PciIoDevice,
77 IN UINT8 BarIndex,
78 IN PCI_BAR_TYPE Type,
80 IN IN UINTN Count,
81 IN UINT64 *Offset
82 )
83{
84 if ((UINT32)Width >= EfiPciIoWidthMaximum) {
85 return EFI_INVALID_PARAMETER;
86 }
87
88 if (BarIndex == EFI_PCI_IO_PASS_THROUGH_BAR) {
89 return EFI_SUCCESS;
90 }
91
92 //
93 // BarIndex 0-5 is legal
94 //
95 if (BarIndex >= PCI_MAX_BAR) {
96 return EFI_INVALID_PARAMETER;
97 }
98
99 if (!CheckBarType (PciIoDevice, BarIndex, Type)) {
100 return EFI_INVALID_PARAMETER;
101 }
102
103 //
104 // If Width is EfiPciIoWidthFifoUintX then convert to EfiPciIoWidthUintX
105 // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUintX
106 //
107 if ((Width >= EfiPciIoWidthFifoUint8) && (Width <= EfiPciIoWidthFifoUint64)) {
108 Count = 1;
109 }
110
111 Width = (EFI_PCI_IO_PROTOCOL_WIDTH)(Width & 0x03);
112
113 if ((*Offset + Count * (UINTN)(1 << Width)) - 1 >= PciIoDevice->PciBar[BarIndex].Length) {
114 return EFI_INVALID_PARAMETER;
115 }
116
117 *Offset = *Offset + PciIoDevice->PciBar[BarIndex].BaseAddress;
118
119 return EFI_SUCCESS;
120}
121
137 IN PCI_IO_DEVICE *PciIoDevice,
139 IN UINTN Count,
140 IN UINT64 *Offset
141 )
142{
143 UINT64 ExtendOffset;
144
145 if ((UINT32)Width >= EfiPciIoWidthMaximum) {
146 return EFI_INVALID_PARAMETER;
147 }
148
149 //
150 // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUintX
151 //
152 Width = (EFI_PCI_IO_PROTOCOL_WIDTH)(Width & 0x03);
153
154 if (PciIoDevice->IsPciExp) {
155 if ((*Offset + Count * (UINTN)(1 << Width)) - 1 >= PCI_EXP_MAX_CONFIG_OFFSET) {
156 return EFI_UNSUPPORTED;
157 }
158
159 ExtendOffset = LShiftU64 (*Offset, 32);
160 *Offset = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, 0);
161 *Offset = (*Offset) | ExtendOffset;
162 } else {
163 if ((*Offset + Count * (UINTN)(1 << Width)) - 1 >= PCI_MAX_CONFIG_OFFSET) {
164 return EFI_UNSUPPORTED;
165 }
166
167 *Offset = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, *Offset);
168 }
169
170 return EFI_SUCCESS;
171}
172
196EFIAPI
200 IN UINT8 BarIndex,
201 IN UINT64 Offset,
202 IN UINT64 Mask,
203 IN UINT64 Value,
204 IN UINT64 Delay,
205 OUT UINT64 *Result
206 )
207{
208 EFI_STATUS Status;
209 PCI_IO_DEVICE *PciIoDevice;
210
211 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
212
213 if ((UINT32)Width >= EfiPciIoWidthMaximum) {
214 return EFI_INVALID_PARAMETER;
215 }
216
217 Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, 1, &Offset);
218 if (EFI_ERROR (Status)) {
219 return EFI_UNSUPPORTED;
220 }
221
222 if (Width > EfiPciIoWidthUint64) {
223 return EFI_INVALID_PARAMETER;
224 }
225
226 //
227 // If request is not aligned, then convert request to EfiPciIoWithXXXUint8
228 //
229 if (FeaturePcdGet (PcdUnalignedPciIoEnable)) {
230 if ((Offset & ((1 << (Width & 0x03)) - 1)) != 0) {
231 Status = PciIoMemRead (This, Width, BarIndex, Offset, 1, Result);
232 if (EFI_ERROR (Status)) {
233 return Status;
234 }
235
236 if (((*Result & Mask) == Value) || (Delay == 0)) {
237 return EFI_SUCCESS;
238 }
239
240 do {
241 //
242 // Stall 10 us = 100 * 100ns
243 //
244 gBS->Stall (10);
245
246 Status = PciIoMemRead (This, Width, BarIndex, Offset, 1, Result);
247 if (EFI_ERROR (Status)) {
248 return Status;
249 }
250
251 if ((*Result & Mask) == Value) {
252 return EFI_SUCCESS;
253 }
254
255 if (Delay <= 100) {
256 return EFI_TIMEOUT;
257 }
258
259 Delay -= 100;
260 } while (TRUE);
261 }
262 }
263
264 Status = PciIoDevice->PciRootBridgeIo->PollMem (
265 PciIoDevice->PciRootBridgeIo,
267 Offset,
268 Mask,
269 Value,
270 Delay,
271 Result
272 );
273
274 if (EFI_ERROR (Status)) {
276 EFI_ERROR_CODE | EFI_ERROR_MINOR,
277 EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR,
278 PciIoDevice->DevicePath
279 );
280 }
281
282 return Status;
283}
284
308EFIAPI
312 IN UINT8 BarIndex,
313 IN UINT64 Offset,
314 IN UINT64 Mask,
315 IN UINT64 Value,
316 IN UINT64 Delay,
317 OUT UINT64 *Result
318 )
319{
320 EFI_STATUS Status;
321 PCI_IO_DEVICE *PciIoDevice;
322
323 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
324
325 if ((UINT32)Width > EfiPciIoWidthUint64) {
326 return EFI_INVALID_PARAMETER;
327 }
328
329 Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, 1, &Offset);
330 if (EFI_ERROR (Status)) {
331 return EFI_UNSUPPORTED;
332 }
333
334 //
335 // If request is not aligned, then convert request to EfiPciIoWithXXXUint8
336 //
337 if (FeaturePcdGet (PcdUnalignedPciIoEnable)) {
338 if ((Offset & ((1 << (Width & 0x03)) - 1)) != 0) {
339 Status = PciIoIoRead (This, Width, BarIndex, Offset, 1, Result);
340 if (EFI_ERROR (Status)) {
341 return Status;
342 }
343
344 if (((*Result & Mask) == Value) || (Delay == 0)) {
345 return EFI_SUCCESS;
346 }
347
348 do {
349 //
350 // Stall 10 us = 100 * 100ns
351 //
352 gBS->Stall (10);
353
354 Status = PciIoIoRead (This, Width, BarIndex, Offset, 1, Result);
355 if (EFI_ERROR (Status)) {
356 return Status;
357 }
358
359 if ((*Result & Mask) == Value) {
360 return EFI_SUCCESS;
361 }
362
363 if (Delay <= 100) {
364 return EFI_TIMEOUT;
365 }
366
367 Delay -= 100;
368 } while (TRUE);
369 }
370 }
371
372 Status = PciIoDevice->PciRootBridgeIo->PollIo (
373 PciIoDevice->PciRootBridgeIo,
375 Offset,
376 Mask,
377 Value,
378 Delay,
379 Result
380 );
381
382 if (EFI_ERROR (Status)) {
384 EFI_ERROR_CODE | EFI_ERROR_MINOR,
385 EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR,
386 PciIoDevice->DevicePath
387 );
388 }
389
390 return Status;
391}
392
414EFIAPI
418 IN UINT8 BarIndex,
419 IN UINT64 Offset,
420 IN UINTN Count,
421 IN OUT VOID *Buffer
422 )
423{
424 EFI_STATUS Status;
425 PCI_IO_DEVICE *PciIoDevice;
426
427 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
428
429 if ((UINT32)Width >= EfiPciIoWidthMaximum) {
430 return EFI_INVALID_PARAMETER;
431 }
432
433 if (Buffer == NULL) {
434 return EFI_INVALID_PARAMETER;
435 }
436
437 Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, Count, &Offset);
438 if (EFI_ERROR (Status)) {
439 return EFI_UNSUPPORTED;
440 }
441
442 //
443 // If request is not aligned, then convert request to EfiPciIoWithXXXUint8
444 //
445 if (FeaturePcdGet (PcdUnalignedPciIoEnable)) {
446 if ((Offset & ((1 << (Width & 0x03)) - 1)) != 0) {
447 Count *= (UINTN)(1 << (Width & 0x03));
448 Width = (EFI_PCI_IO_PROTOCOL_WIDTH)(Width & (~0x03));
449 }
450 }
451
452 Status = PciIoDevice->PciRootBridgeIo->Mem.Read (
453 PciIoDevice->PciRootBridgeIo,
455 Offset,
456 Count,
457 Buffer
458 );
459
460 if (EFI_ERROR (Status)) {
462 EFI_ERROR_CODE | EFI_ERROR_MINOR,
463 EFI_IO_BUS_PCI | EFI_IOB_EC_READ_ERROR,
464 PciIoDevice->DevicePath
465 );
466 }
467
468 return Status;
469}
470
492EFIAPI
496 IN UINT8 BarIndex,
497 IN UINT64 Offset,
498 IN UINTN Count,
499 IN OUT VOID *Buffer
500 )
501{
502 EFI_STATUS Status;
503 PCI_IO_DEVICE *PciIoDevice;
504
505 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
506
507 if ((UINT32)Width >= EfiPciIoWidthMaximum) {
508 return EFI_INVALID_PARAMETER;
509 }
510
511 if (Buffer == NULL) {
512 return EFI_INVALID_PARAMETER;
513 }
514
515 Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, Count, &Offset);
516 if (EFI_ERROR (Status)) {
517 return EFI_UNSUPPORTED;
518 }
519
520 //
521 // If request is not aligned, then convert request to EfiPciIoWithXXXUint8
522 //
523 if (FeaturePcdGet (PcdUnalignedPciIoEnable)) {
524 if ((Offset & ((1 << (Width & 0x03)) - 1)) != 0) {
525 Count *= (UINTN)(1 << (Width & 0x03));
526 Width = (EFI_PCI_IO_PROTOCOL_WIDTH)(Width & (~0x03));
527 }
528 }
529
530 Status = PciIoDevice->PciRootBridgeIo->Mem.Write (
531 PciIoDevice->PciRootBridgeIo,
533 Offset,
534 Count,
535 Buffer
536 );
537
538 if (EFI_ERROR (Status)) {
540 EFI_ERROR_CODE | EFI_ERROR_MINOR,
541 EFI_IO_BUS_PCI | EFI_IOB_EC_WRITE_ERROR,
542 PciIoDevice->DevicePath
543 );
544 }
545
546 return Status;
547}
548
570EFIAPI
574 IN UINT8 BarIndex,
575 IN UINT64 Offset,
576 IN UINTN Count,
577 IN OUT VOID *Buffer
578 )
579{
580 EFI_STATUS Status;
581 PCI_IO_DEVICE *PciIoDevice;
582
583 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
584
585 if ((UINT32)Width >= EfiPciIoWidthMaximum) {
586 return EFI_INVALID_PARAMETER;
587 }
588
589 if (Buffer == NULL) {
590 return EFI_INVALID_PARAMETER;
591 }
592
593 Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, Count, &Offset);
594 if (EFI_ERROR (Status)) {
595 return EFI_UNSUPPORTED;
596 }
597
598 //
599 // If request is not aligned, then convert request to EfiPciIoWithXXXUint8
600 //
601 if (FeaturePcdGet (PcdUnalignedPciIoEnable)) {
602 if ((Offset & ((1 << (Width & 0x03)) - 1)) != 0) {
603 Count *= (UINTN)(1 << (Width & 0x03));
604 Width = (EFI_PCI_IO_PROTOCOL_WIDTH)(Width & (~0x03));
605 }
606 }
607
608 Status = PciIoDevice->PciRootBridgeIo->Io.Read (
609 PciIoDevice->PciRootBridgeIo,
611 Offset,
612 Count,
613 Buffer
614 );
615
616 if (EFI_ERROR (Status)) {
618 EFI_ERROR_CODE | EFI_ERROR_MINOR,
619 EFI_IO_BUS_PCI | EFI_IOB_EC_READ_ERROR,
620 PciIoDevice->DevicePath
621 );
622 }
623
624 return Status;
625}
626
648EFIAPI
652 IN UINT8 BarIndex,
653 IN UINT64 Offset,
654 IN UINTN Count,
655 IN OUT VOID *Buffer
656 )
657{
658 EFI_STATUS Status;
659 PCI_IO_DEVICE *PciIoDevice;
660
661 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
662
663 if ((UINT32)Width >= EfiPciIoWidthMaximum) {
664 return EFI_INVALID_PARAMETER;
665 }
666
667 if (Buffer == NULL) {
668 return EFI_INVALID_PARAMETER;
669 }
670
671 Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, Count, &Offset);
672 if (EFI_ERROR (Status)) {
673 return EFI_UNSUPPORTED;
674 }
675
676 //
677 // If request is not aligned, then convert request to EfiPciIoWithXXXUint8
678 //
679 if (FeaturePcdGet (PcdUnalignedPciIoEnable)) {
680 if ((Offset & ((1 << (Width & 0x03)) - 1)) != 0) {
681 Count *= (UINTN)(1 << (Width & 0x03));
682 Width = (EFI_PCI_IO_PROTOCOL_WIDTH)(Width & (~0x03));
683 }
684 }
685
686 Status = PciIoDevice->PciRootBridgeIo->Io.Write (
687 PciIoDevice->PciRootBridgeIo,
689 Offset,
690 Count,
691 Buffer
692 );
693
694 if (EFI_ERROR (Status)) {
696 EFI_ERROR_CODE | EFI_ERROR_MINOR,
697 EFI_IO_BUS_PCI | EFI_IOB_EC_WRITE_ERROR,
698 PciIoDevice->DevicePath
699 );
700 }
701
702 return Status;
703}
704
724EFIAPI
728 IN UINT32 Offset,
729 IN UINTN Count,
730 IN OUT VOID *Buffer
731 )
732{
733 EFI_STATUS Status;
734 PCI_IO_DEVICE *PciIoDevice;
735 UINT64 Address;
736
737 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
738
739 Address = Offset;
740 Status = PciIoVerifyConfigAccess (PciIoDevice, Width, Count, &Address);
741 if (EFI_ERROR (Status)) {
742 return Status;
743 }
744
745 //
746 // If request is not aligned, then convert request to EfiPciIoWithXXXUint8
747 //
748 if (FeaturePcdGet (PcdUnalignedPciIoEnable)) {
749 if ((Offset & ((1 << (Width & 0x03)) - 1)) != 0) {
750 Count *= (UINTN)(1 << (Width & 0x03));
751 Width = (EFI_PCI_IO_PROTOCOL_WIDTH)(Width & (~0x03));
752 }
753 }
754
755 Status = PciIoDevice->PciRootBridgeIo->Pci.Read (
756 PciIoDevice->PciRootBridgeIo,
758 Address,
759 Count,
760 Buffer
761 );
762
763 if (EFI_ERROR (Status)) {
765 EFI_ERROR_CODE | EFI_ERROR_MINOR,
766 EFI_IO_BUS_PCI | EFI_IOB_EC_READ_ERROR,
767 PciIoDevice->DevicePath
768 );
769 }
770
771 return Status;
772}
773
793EFIAPI
797 IN UINT32 Offset,
798 IN UINTN Count,
799 IN OUT VOID *Buffer
800 )
801{
802 EFI_STATUS Status;
803 PCI_IO_DEVICE *PciIoDevice;
804 UINT64 Address;
805
806 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
807
808 Address = Offset;
809 Status = PciIoVerifyConfigAccess (PciIoDevice, Width, Count, &Address);
810 if (EFI_ERROR (Status)) {
811 return Status;
812 }
813
814 //
815 // If request is not aligned, then convert request to EfiPciIoWithXXXUint8
816 //
817 if (FeaturePcdGet (PcdUnalignedPciIoEnable)) {
818 if ((Offset & ((1 << (Width & 0x03)) - 1)) != 0) {
819 Count *= (UINTN)(1 << (Width & 0x03));
820 Width = (EFI_PCI_IO_PROTOCOL_WIDTH)(Width & (~0x03));
821 }
822 }
823
824 Status = PciIoDevice->PciRootBridgeIo->Pci.Write (
825 PciIoDevice->PciRootBridgeIo,
827 Address,
828 Count,
829 Buffer
830 );
831
832 if (EFI_ERROR (Status)) {
834 EFI_ERROR_CODE | EFI_ERROR_MINOR,
835 EFI_IO_BUS_PCI | EFI_IOB_EC_WRITE_ERROR,
836 PciIoDevice->DevicePath
837 );
838 }
839
840 return Status;
841}
842
872EFIAPI
876 IN UINT8 DestBarIndex,
877 IN UINT64 DestOffset,
878 IN UINT8 SrcBarIndex,
879 IN UINT64 SrcOffset,
880 IN UINTN Count
881 )
882{
883 EFI_STATUS Status;
884 PCI_IO_DEVICE *PciIoDevice;
885
886 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
887
888 if ((UINT32)Width >= EfiPciIoWidthMaximum) {
889 return EFI_INVALID_PARAMETER;
890 }
891
892 if ((Width == EfiPciIoWidthFifoUint8) ||
893 (Width == EfiPciIoWidthFifoUint16) ||
894 (Width == EfiPciIoWidthFifoUint32) ||
895 (Width == EfiPciIoWidthFifoUint64) ||
896 (Width == EfiPciIoWidthFillUint8) ||
897 (Width == EfiPciIoWidthFillUint16) ||
898 (Width == EfiPciIoWidthFillUint32) ||
899 (Width == EfiPciIoWidthFillUint64))
900 {
901 return EFI_INVALID_PARAMETER;
902 }
903
904 Status = PciIoVerifyBarAccess (PciIoDevice, DestBarIndex, PciBarTypeMem, Width, Count, &DestOffset);
905 if (EFI_ERROR (Status)) {
906 return EFI_UNSUPPORTED;
907 }
908
909 Status = PciIoVerifyBarAccess (PciIoDevice, SrcBarIndex, PciBarTypeMem, Width, Count, &SrcOffset);
910 if (EFI_ERROR (Status)) {
911 return EFI_UNSUPPORTED;
912 }
913
914 //
915 // If request is not aligned, then convert request to EfiPciIoWithXXXUint8
916 //
917 if (FeaturePcdGet (PcdUnalignedPciIoEnable)) {
918 if (((SrcOffset & ((1 << (Width & 0x03)) - 1)) != 0) || ((DestOffset & ((1 << (Width & 0x03)) - 1)) != 0)) {
919 Count *= (UINTN)(1 << (Width & 0x03));
920 Width = (EFI_PCI_IO_PROTOCOL_WIDTH)(Width & (~0x03));
921 }
922 }
923
924 Status = PciIoDevice->PciRootBridgeIo->CopyMem (
925 PciIoDevice->PciRootBridgeIo,
927 DestOffset,
928 SrcOffset,
929 Count
930 );
931
932 if (EFI_ERROR (Status)) {
934 EFI_ERROR_CODE | EFI_ERROR_MINOR,
935 EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR,
936 PciIoDevice->DevicePath
937 );
938 }
939
940 return Status;
941}
942
963EFIAPI
967 IN VOID *HostAddress,
968 IN OUT UINTN *NumberOfBytes,
969 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
970 OUT VOID **Mapping
971 )
972{
973 EFI_STATUS Status;
974 PCI_IO_DEVICE *PciIoDevice;
975 UINT64 IoMmuAttribute;
976 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION RootBridgeIoOperation;
977
978 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
979
980 if ((UINT32)Operation >= EfiPciIoOperationMaximum) {
981 return EFI_INVALID_PARAMETER;
982 }
983
984 if ((HostAddress == NULL) || (NumberOfBytes == NULL) || (DeviceAddress == NULL) || (Mapping == NULL)) {
985 return EFI_INVALID_PARAMETER;
986 }
987
988 RootBridgeIoOperation = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION)Operation;
989 if ((PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) != 0) {
991 }
992
993 Status = PciIoDevice->PciRootBridgeIo->Map (
994 PciIoDevice->PciRootBridgeIo,
995 RootBridgeIoOperation,
996 HostAddress,
997 NumberOfBytes,
998 DeviceAddress,
999 Mapping
1000 );
1001
1002 if (EFI_ERROR (Status)) {
1004 EFI_ERROR_CODE | EFI_ERROR_MINOR,
1005 EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR,
1006 PciIoDevice->DevicePath
1007 );
1008 }
1009
1010 if (mIoMmuProtocol != NULL) {
1011 if (!EFI_ERROR (Status)) {
1012 switch (Operation) {
1014 IoMmuAttribute = EDKII_IOMMU_ACCESS_READ;
1015 break;
1017 IoMmuAttribute = EDKII_IOMMU_ACCESS_WRITE;
1018 break;
1020 IoMmuAttribute = EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE;
1021 break;
1022 default:
1023 ASSERT (FALSE);
1024 return EFI_INVALID_PARAMETER;
1025 }
1026
1027 Status = mIoMmuProtocol->SetAttribute (
1028 mIoMmuProtocol,
1029 PciIoDevice->Handle,
1030 *Mapping,
1031 IoMmuAttribute
1032 );
1033 }
1034 }
1035
1036 return Status;
1037}
1038
1050EFIAPI
1052 IN EFI_PCI_IO_PROTOCOL *This,
1053 IN VOID *Mapping
1054 )
1055{
1056 EFI_STATUS Status;
1057 PCI_IO_DEVICE *PciIoDevice;
1058
1059 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
1060
1061 if (mIoMmuProtocol != NULL) {
1062 mIoMmuProtocol->SetAttribute (
1063 mIoMmuProtocol,
1064 PciIoDevice->Handle,
1065 Mapping,
1066 0
1067 );
1068 }
1069
1070 Status = PciIoDevice->PciRootBridgeIo->Unmap (
1071 PciIoDevice->PciRootBridgeIo,
1072 Mapping
1073 );
1074
1075 if (EFI_ERROR (Status)) {
1077 EFI_ERROR_CODE | EFI_ERROR_MINOR,
1078 EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR,
1079 PciIoDevice->DevicePath
1080 );
1081 }
1082
1083 return Status;
1084}
1085
1107EFIAPI
1109 IN EFI_PCI_IO_PROTOCOL *This,
1110 IN EFI_ALLOCATE_TYPE Type,
1111 IN EFI_MEMORY_TYPE MemoryType,
1112 IN UINTN Pages,
1113 OUT VOID **HostAddress,
1114 IN UINT64 Attributes
1115 )
1116{
1117 EFI_STATUS Status;
1118 PCI_IO_DEVICE *PciIoDevice;
1119
1120 if ((Attributes &
1121 (~(EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE | EFI_PCI_ATTRIBUTE_MEMORY_CACHED))) != 0)
1122 {
1123 return EFI_UNSUPPORTED;
1124 }
1125
1126 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
1127
1128 if ((PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) != 0) {
1129 Attributes |= EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE;
1130 }
1131
1132 Status = PciIoDevice->PciRootBridgeIo->AllocateBuffer (
1133 PciIoDevice->PciRootBridgeIo,
1134 Type,
1135 MemoryType,
1136 Pages,
1137 HostAddress,
1138 Attributes
1139 );
1140
1141 if (EFI_ERROR (Status)) {
1143 EFI_ERROR_CODE | EFI_ERROR_MINOR,
1144 EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR,
1145 PciIoDevice->DevicePath
1146 );
1147 }
1148
1149 return Status;
1150}
1151
1165EFIAPI
1167 IN EFI_PCI_IO_PROTOCOL *This,
1168 IN UINTN Pages,
1169 IN VOID *HostAddress
1170 )
1171{
1172 EFI_STATUS Status;
1173 PCI_IO_DEVICE *PciIoDevice;
1174
1175 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
1176
1177 Status = PciIoDevice->PciRootBridgeIo->FreeBuffer (
1178 PciIoDevice->PciRootBridgeIo,
1179 Pages,
1180 HostAddress
1181 );
1182
1183 if (EFI_ERROR (Status)) {
1185 EFI_ERROR_CODE | EFI_ERROR_MINOR,
1186 EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR,
1187 PciIoDevice->DevicePath
1188 );
1189 }
1190
1191 return Status;
1192}
1193
1206EFIAPI
1209 )
1210{
1211 EFI_STATUS Status;
1212 PCI_IO_DEVICE *PciIoDevice;
1213
1214 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
1215
1216 Status = PciIoDevice->PciRootBridgeIo->Flush (
1217 PciIoDevice->PciRootBridgeIo
1218 );
1219 if (EFI_ERROR (Status)) {
1221 EFI_ERROR_CODE | EFI_ERROR_MINOR,
1222 EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR,
1223 PciIoDevice->DevicePath
1224 );
1225 }
1226
1227 return Status;
1228}
1229
1244EFIAPI
1246 IN EFI_PCI_IO_PROTOCOL *This,
1247 OUT UINTN *Segment,
1248 OUT UINTN *Bus,
1249 OUT UINTN *Device,
1250 OUT UINTN *Function
1251 )
1252{
1253 PCI_IO_DEVICE *PciIoDevice;
1254
1255 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
1256
1257 if ((Segment == NULL) || (Bus == NULL) || (Device == NULL) || (Function == NULL)) {
1258 return EFI_INVALID_PARAMETER;
1259 }
1260
1261 *Segment = PciIoDevice->PciRootBridgeIo->SegmentNumber;
1262 *Bus = PciIoDevice->BusNumber;
1263 *Device = PciIoDevice->DeviceNumber;
1264 *Function = PciIoDevice->FunctionNumber;
1265
1266 return EFI_SUCCESS;
1267}
1268
1281BOOLEAN
1283 IN PCI_IO_DEVICE *PciIoDevice,
1284 IN UINT8 BarIndex,
1285 IN PCI_BAR_TYPE BarType
1286 )
1287{
1288 switch (BarType) {
1289 case PciBarTypeMem:
1290
1291 if ((PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeMem32) &&
1292 (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypePMem32) &&
1293 (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypePMem64) &&
1294 (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeMem64))
1295 {
1296 return FALSE;
1297 }
1298
1299 return TRUE;
1300
1301 case PciBarTypeIo:
1302 if ((PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeIo32) &&
1303 (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeIo16))
1304 {
1305 return FALSE;
1306 }
1307
1308 return TRUE;
1309
1310 default:
1311 break;
1312 }
1313
1314 return FALSE;
1315}
1316
1330 IN PCI_IO_DEVICE *PciIoDevice,
1331 IN UINT64 Attributes,
1333 )
1334{
1335 UINT64 PciRootBridgeSupports;
1336 UINT64 PciRootBridgeAttributes;
1337 UINT64 NewPciRootBridgeAttributes;
1338 EFI_STATUS Status;
1339
1340 //
1341 // Get the current attributes of this PCI device's PCI Root Bridge
1342 //
1343 Status = PciIoDevice->PciRootBridgeIo->GetAttributes (
1344 PciIoDevice->PciRootBridgeIo,
1345 &PciRootBridgeSupports,
1346 &PciRootBridgeAttributes
1347 );
1348 if (EFI_ERROR (Status)) {
1349 return EFI_UNSUPPORTED;
1350 }
1351
1352 //
1353 // Mask off attributes not supported by PCI root bridge.
1354 //
1355 Attributes &= ~(UINT64)(EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE |
1358
1359 //
1360 // Record the new attribute of the Root Bridge
1361 //
1362 if (Operation == EfiPciIoAttributeOperationEnable) {
1363 NewPciRootBridgeAttributes = PciRootBridgeAttributes | Attributes;
1364 } else {
1365 NewPciRootBridgeAttributes = PciRootBridgeAttributes & (~Attributes);
1366 }
1367
1368 //
1369 // Call the PCI Root Bridge to attempt to modify the attributes
1370 //
1371 if ((NewPciRootBridgeAttributes ^ PciRootBridgeAttributes) != 0) {
1372 Status = PciIoDevice->PciRootBridgeIo->SetAttributes (
1373 PciIoDevice->PciRootBridgeIo,
1374 NewPciRootBridgeAttributes,
1375 NULL,
1376 NULL
1377 );
1378 if (EFI_ERROR (Status)) {
1379 //
1380 // The PCI Root Bridge could not modify the attributes, so return the error.
1381 //
1382 return EFI_UNSUPPORTED;
1383 }
1384 }
1385
1386 //
1387 // Also update the attributes for this Root Bridge structure
1388 //
1389 PciIoDevice->Attributes = NewPciRootBridgeAttributes;
1390
1391 return EFI_SUCCESS;
1392}
1393
1406 IN PCI_IO_DEVICE *PciIoDevice,
1408 )
1409{
1410 EFI_STATUS Status;
1411 PCI_IO_DEVICE *Temp;
1412 UINT16 VGACommand;
1413
1414 //
1415 // Snoop attribute can be only modified by GFX
1416 //
1417 if (!IS_PCI_GFX (&PciIoDevice->Pci)) {
1418 return EFI_UNSUPPORTED;
1419 }
1420
1421 //
1422 // Get the boot VGA on the same Host Bridge
1423 //
1424 Temp = LocateVgaDeviceOnHostBridge (PciIoDevice->PciRootBridgeIo->ParentHandle);
1425
1426 if (Temp == NULL) {
1427 //
1428 // If there is no VGA device on the segment, set
1429 // this graphics card to decode the palette range
1430 //
1431 return EFI_SUCCESS;
1432 }
1433
1434 //
1435 // Check these two agents are on the same path
1436 //
1437 if (!PciDevicesOnTheSamePath (Temp, PciIoDevice)) {
1438 //
1439 // they are not on the same path, so snoop can be enabled or disabled
1440 //
1441 return EFI_SUCCESS;
1442 }
1443
1444 //
1445 // Check if they are on the same bus
1446 //
1447 if (Temp->Parent == PciIoDevice->Parent) {
1448 Status = PCI_READ_COMMAND_REGISTER (Temp, &VGACommand);
1449
1450 //
1451 // If they are on the same bus, either one can
1452 // be set to snoop, the other set to decode
1453 //
1454 if (!EFI_ERROR (Status) && ((VGACommand & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) != 0)) {
1455 //
1456 // VGA has set to snoop, so GFX can be only set to disable snoop
1457 //
1458 if (Operation == EfiPciIoAttributeOperationEnable) {
1459 return EFI_UNSUPPORTED;
1460 }
1461 } else {
1462 //
1463 // VGA has disabled to snoop, so GFX can be only enabled
1464 //
1465 if (Operation == EfiPciIoAttributeOperationDisable) {
1466 return EFI_UNSUPPORTED;
1467 }
1468 }
1469
1470 return EFI_SUCCESS;
1471 }
1472
1473 //
1474 // If they are on the same path but on the different bus
1475 // The first agent is set to snoop, the second one set to
1476 // decode
1477 //
1478
1479 if (Temp->BusNumber < PciIoDevice->BusNumber) {
1480 //
1481 // GFX should be set to decode
1482 //
1483 if (Operation == EfiPciIoAttributeOperationDisable) {
1485 Temp->Attributes |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
1486 } else {
1487 return EFI_UNSUPPORTED;
1488 }
1489 } else {
1490 //
1491 // GFX should be set to snoop
1492 //
1493 if (Operation == EfiPciIoAttributeOperationEnable) {
1495 Temp->Attributes &= (~(UINT64)EFI_PCI_COMMAND_VGA_PALETTE_SNOOP);
1496 } else {
1497 return EFI_UNSUPPORTED;
1498 }
1499 }
1500
1501 return EFI_SUCCESS;
1502}
1503
1524EFIAPI
1526 IN EFI_PCI_IO_PROTOCOL *This,
1528 IN UINT64 Attributes,
1529 OUT UINT64 *Result OPTIONAL
1530 )
1531{
1532 EFI_STATUS Status;
1533
1534 PCI_IO_DEVICE *PciIoDevice;
1535 PCI_IO_DEVICE *UpStreamBridge;
1536 PCI_IO_DEVICE *Temp;
1537
1538 UINT64 Supports;
1539 UINT64 UpStreamAttributes;
1540 UINT16 BridgeControl;
1541 UINT16 Command;
1542
1543 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
1544
1545 switch (Operation) {
1547 if (Result == NULL) {
1548 return EFI_INVALID_PARAMETER;
1549 }
1550
1551 *Result = PciIoDevice->Attributes;
1552 return EFI_SUCCESS;
1553
1555 if (Result == NULL) {
1556 return EFI_INVALID_PARAMETER;
1557 }
1558
1559 *Result = PciIoDevice->Supports;
1560 return EFI_SUCCESS;
1561
1563 Status = PciIoDevice->PciIo.Attributes (
1564 &(PciIoDevice->PciIo),
1566 Attributes,
1567 NULL
1568 );
1569 if (EFI_ERROR (Status)) {
1570 return EFI_UNSUPPORTED;
1571 }
1572
1573 Status = PciIoDevice->PciIo.Attributes (
1574 &(PciIoDevice->PciIo),
1576 (~Attributes) & (PciIoDevice->Supports),
1577 NULL
1578 );
1579 if (EFI_ERROR (Status)) {
1580 return EFI_UNSUPPORTED;
1581 }
1582
1583 return EFI_SUCCESS;
1584
1587 break;
1588
1589 default:
1590 return EFI_INVALID_PARAMETER;
1591 }
1592
1593 //
1594 // Just a trick for ENABLE attribute
1595 // EFI_PCI_DEVICE_ENABLE is not defined in UEFI spec, which is the internal usage.
1596 // So, this logic doesn't conform to UEFI spec, which should be removed.
1597 // But this trick logic is still kept for some binary drivers that depend on it.
1598 //
1599 if ((Attributes & EFI_PCI_DEVICE_ENABLE) == EFI_PCI_DEVICE_ENABLE) {
1600 Attributes &= (PciIoDevice->Supports);
1601
1602 //
1603 // Raise the EFI_P_PC_ENABLE Status code
1604 //
1607 EFI_IO_BUS_PCI | EFI_P_PC_ENABLE,
1608 PciIoDevice->DevicePath
1609 );
1610 }
1611
1612 //
1613 // Check VGA and VGA16, they can not be set at the same time
1614 //
1617 return EFI_UNSUPPORTED;
1618 }
1619 }
1620
1621 //
1622 // If no attributes can be supported, then return.
1623 // Otherwise, set the attributes that it can support.
1624 //
1625 Supports = (PciIoDevice->Supports) & Attributes;
1626 if (Supports != Attributes) {
1627 return EFI_UNSUPPORTED;
1628 }
1629
1630 //
1631 // For Root Bridge, just call RootBridgeIo to set attributes;
1632 //
1633 if (PciIoDevice->Parent == NULL) {
1634 Status = ModifyRootBridgeAttributes (PciIoDevice, Attributes, Operation);
1635 return Status;
1636 }
1637
1638 Command = 0;
1639 BridgeControl = 0;
1640
1641 //
1642 // For PPB & P2C, set relevant attribute bits
1643 //
1644 if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
1645 if ((Attributes & (EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16)) != 0) {
1646 BridgeControl |= EFI_PCI_BRIDGE_CONTROL_VGA;
1647 }
1648
1649 if ((Attributes & EFI_PCI_IO_ATTRIBUTE_ISA_IO) != 0) {
1650 BridgeControl |= EFI_PCI_BRIDGE_CONTROL_ISA;
1651 }
1652
1655 }
1656
1658 BridgeControl |= EFI_PCI_BRIDGE_CONTROL_VGA_16;
1659 }
1660 } else {
1661 //
1662 // Do with the attributes on VGA
1663 // Only for VGA's legacy resource, we just can enable once.
1664 //
1665 if ((Attributes &
1669 {
1670 //
1671 // Check if a VGA has been enabled before enabling a new one
1672 //
1673 if (Operation == EfiPciIoAttributeOperationEnable) {
1674 //
1675 // Check if there have been an active VGA device on the same Host Bridge
1676 //
1677 Temp = LocateVgaDeviceOnHostBridge (PciIoDevice->PciRootBridgeIo->ParentHandle);
1678 if ((Temp != NULL) && (Temp != PciIoDevice)) {
1679 //
1680 // An active VGA has been detected, so can not enable another
1681 //
1682 return EFI_UNSUPPORTED;
1683 }
1684 }
1685 }
1686
1687 //
1688 // Do with the attributes on GFX
1689 //
1691 if (Operation == EfiPciIoAttributeOperationEnable) {
1692 //
1693 // Check if snoop can be enabled in current configuration
1694 //
1695 Status = SupportPaletteSnoopAttributes (PciIoDevice, Operation);
1696
1697 if (EFI_ERROR (Status)) {
1698 //
1699 // Enable operation is forbidden, so mask the bit in attributes
1700 // so as to keep consistent with the actual Status
1701 //
1702 // Attributes &= (~EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO);
1703 //
1704 //
1705 //
1706 return EFI_UNSUPPORTED;
1707 }
1708 }
1709
1710 //
1711 // It can be supported, so get ready to set the bit
1712 //
1714 }
1715 }
1716
1717 if ((Attributes & EFI_PCI_IO_ATTRIBUTE_IO) != 0) {
1718 Command |= EFI_PCI_COMMAND_IO_SPACE;
1719 }
1720
1721 if ((Attributes & EFI_PCI_IO_ATTRIBUTE_MEMORY) != 0) {
1723 }
1724
1725 if ((Attributes & EFI_PCI_IO_ATTRIBUTE_BUS_MASTER) != 0) {
1726 Command |= EFI_PCI_COMMAND_BUS_MASTER;
1727 }
1728
1729 //
1730 // The upstream bridge should be also set to relevant attribute
1731 // expect for IO, Mem and BusMaster
1732 //
1733 UpStreamAttributes = Attributes &
1737 )
1738 );
1739 UpStreamBridge = PciIoDevice->Parent;
1740
1741 if (Operation == EfiPciIoAttributeOperationEnable) {
1742 //
1743 // Enable relevant attributes to command register and bridge control register
1744 //
1745 Status = PCI_ENABLE_COMMAND_REGISTER (PciIoDevice, Command);
1746 if (BridgeControl != 0) {
1747 Status = PCI_ENABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, BridgeControl);
1748 }
1749
1750 PciIoDevice->Attributes |= Attributes;
1751
1752 //
1753 // Enable attributes of the upstream bridge
1754 //
1755 Status = UpStreamBridge->PciIo.Attributes (
1756 &(UpStreamBridge->PciIo),
1758 UpStreamAttributes,
1759 NULL
1760 );
1761 } else {
1762 //
1763 // Disable relevant attributes to command register and bridge control register
1764 //
1765 Status = PCI_DISABLE_COMMAND_REGISTER (PciIoDevice, Command);
1766 if (BridgeControl != 0) {
1767 Status = PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice, BridgeControl);
1768 }
1769
1770 PciIoDevice->Attributes &= (~Attributes);
1771 Status = EFI_SUCCESS;
1772 }
1773
1774 if (EFI_ERROR (Status)) {
1776 EFI_ERROR_CODE | EFI_ERROR_MINOR,
1777 EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR,
1778 PciIoDevice->DevicePath
1779 );
1780 }
1781
1782 return Status;
1783}
1784
1797UINT64
1799 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *RootBridgeIo,
1800 UINT64 AddrRangeMin,
1801 UINT64 AddrLen
1802 )
1803{
1804 EFI_STATUS Status;
1805 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;
1806
1807 Status = RootBridgeIo->Configuration (
1808 RootBridgeIo,
1809 (VOID **)&Configuration
1810 );
1811 if (EFI_ERROR (Status)) {
1812 return (UINT64)-1;
1813 }
1814
1815 // According to UEFI 2.7, EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL::Configuration()
1816 // returns host address instead of device address, while AddrTranslationOffset
1817 // is not zero, and device address = host address + AddrTranslationOffset, so
1818 // we convert host address to device address for range compare.
1819 while (Configuration->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
1820 if ((Configuration->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) &&
1821 (Configuration->AddrRangeMin + Configuration->AddrTranslationOffset <= AddrRangeMin) &&
1822 (Configuration->AddrRangeMin + Configuration->AddrLen + Configuration->AddrTranslationOffset >= AddrRangeMin + AddrLen)
1823 )
1824 {
1825 return Configuration->AddrTranslationOffset;
1826 }
1827
1828 Configuration++;
1829 }
1830
1831 //
1832 // The resource occupied by BAR should be in the range reported by RootBridge.
1833 //
1834 ASSERT (FALSE);
1835 return (UINT64)-1;
1836}
1837
1861EFIAPI
1863 IN EFI_PCI_IO_PROTOCOL *This,
1864 IN UINT8 BarIndex,
1865 OUT UINT64 *Supports OPTIONAL,
1866 OUT VOID **Resources OPTIONAL
1867 )
1868{
1869 PCI_IO_DEVICE *PciIoDevice;
1872
1873 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
1874
1875 if ((Supports == NULL) && (Resources == NULL)) {
1876 return EFI_INVALID_PARAMETER;
1877 }
1878
1879 if ((BarIndex >= PCI_MAX_BAR) || (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypeUnknown)) {
1880 return EFI_UNSUPPORTED;
1881 }
1882
1883 //
1884 // This driver does not support modifications to the WRITE_COMBINE or
1885 // CACHED attributes for BAR ranges.
1886 //
1887 if (Supports != NULL) {
1889 }
1890
1891 if (Resources != NULL) {
1893 if (Descriptor == NULL) {
1894 return EFI_OUT_OF_RESOURCES;
1895 }
1896
1897 *Resources = Descriptor;
1898
1899 Descriptor->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1900 Descriptor->Len = (UINT16)(sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3);
1901 Descriptor->AddrRangeMin = PciIoDevice->PciBar[BarIndex].BaseAddress;
1902 Descriptor->AddrLen = PciIoDevice->PciBar[BarIndex].Length;
1903 Descriptor->AddrRangeMax = PciIoDevice->PciBar[BarIndex].Alignment;
1904
1905 switch (PciIoDevice->PciBar[BarIndex].BarType) {
1906 case PciBarTypeIo16:
1907 case PciBarTypeIo32:
1908 //
1909 // Io
1910 //
1911 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;
1912 break;
1913
1914 case PciBarTypePMem32:
1915 //
1916 // prefetchable
1917 //
1918 Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;
1919 //
1920 // Fall through
1921 //
1922 case PciBarTypeMem32:
1923 //
1924 // Mem
1925 //
1926 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
1927 //
1928 // 32 bit
1929 //
1930 Descriptor->AddrSpaceGranularity = 32;
1931 break;
1932
1933 case PciBarTypePMem64:
1934 //
1935 // prefetchable
1936 //
1937 Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;
1938 //
1939 // Fall through
1940 //
1941 case PciBarTypeMem64:
1942 //
1943 // Mem
1944 //
1945 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
1946 //
1947 // 64 bit
1948 //
1949 Descriptor->AddrSpaceGranularity = 64;
1950 break;
1951
1952 default:
1953 break;
1954 }
1955
1956 //
1957 // put the checksum
1958 //
1959 End = (EFI_ACPI_END_TAG_DESCRIPTOR *)(Descriptor + 1);
1960 End->Desc = ACPI_END_TAG_DESCRIPTOR;
1961 End->Checksum = 0;
1962
1963 //
1964 // Get the Address Translation Offset
1965 //
1966 if (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {
1967 Descriptor->AddrTranslationOffset = GetMmioAddressTranslationOffset (
1968 PciIoDevice->PciRootBridgeIo,
1969 Descriptor->AddrRangeMin,
1970 Descriptor->AddrLen
1971 );
1972 if (Descriptor->AddrTranslationOffset == (UINT64)-1) {
1973 FreePool (Descriptor);
1974 return EFI_UNSUPPORTED;
1975 }
1976 }
1977
1978 // According to UEFI spec 2.7, we need return host address for
1979 // PciIo->GetBarAttributes, and host address = device address - translation.
1980 Descriptor->AddrRangeMin -= Descriptor->AddrTranslationOffset;
1981 }
1982
1983 return EFI_SUCCESS;
1984}
1985
2011EFIAPI
2013 IN EFI_PCI_IO_PROTOCOL *This,
2014 IN UINT64 Attributes,
2015 IN UINT8 BarIndex,
2016 IN OUT UINT64 *Offset,
2017 IN OUT UINT64 *Length
2018 )
2019{
2020 EFI_STATUS Status;
2021 PCI_IO_DEVICE *PciIoDevice;
2022 UINT64 NonRelativeOffset;
2023 UINT64 Supports;
2024
2025 PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
2026
2027 //
2028 // Make sure Offset and Length are not NULL
2029 //
2030 if ((Offset == NULL) || (Length == NULL)) {
2031 return EFI_INVALID_PARAMETER;
2032 }
2033
2034 if (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypeUnknown) {
2035 return EFI_UNSUPPORTED;
2036 }
2037
2038 //
2039 // This driver does not support setting the WRITE_COMBINE or the CACHED attributes.
2040 // If Attributes is not 0, then return EFI_UNSUPPORTED.
2041 //
2043
2044 if (Attributes != (Attributes & Supports)) {
2045 return EFI_UNSUPPORTED;
2046 }
2047
2048 //
2049 // Attributes must be supported. Make sure the BAR range described by BarIndex, Offset, and
2050 // Length are valid for this PCI device.
2051 //
2052 NonRelativeOffset = *Offset;
2053 Status = PciIoVerifyBarAccess (
2054 PciIoDevice,
2055 BarIndex,
2056 PciBarTypeMem,
2057 EfiPciIoWidthUint8,
2058 (UINT32)*Length,
2059 &NonRelativeOffset
2060 );
2061 if (EFI_ERROR (Status)) {
2062 return EFI_UNSUPPORTED;
2063 }
2064
2065 return EFI_SUCCESS;
2066}
2067
2078BOOLEAN
2080 IN PCI_IO_DEVICE *PciDevice1,
2081 IN PCI_IO_DEVICE *PciDevice2
2082 )
2083{
2084 BOOLEAN Existed1;
2085 BOOLEAN Existed2;
2086
2087 if (PciDevice1->Parent == PciDevice2->Parent) {
2088 return TRUE;
2089 }
2090
2091 Existed1 = PciDeviceExisted (PciDevice1->Parent, PciDevice2);
2092 Existed2 = PciDeviceExisted (PciDevice2->Parent, PciDevice1);
2093
2094 return (BOOLEAN)(Existed1 || Existed2);
2095}
UINT64 UINTN
PACKED struct @89 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
UINT64 EFIAPI LShiftU64(IN UINT64 Operand, IN UINTN Count)
Definition: LShiftU64.c:28
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
#define NULL
Definition: Base.h:319
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define REPORT_STATUS_CODE_WITH_DEVICE_PATH(Type, Value, DevicePathParameter)
EFI_PCI_IO_PROTOCOL_WIDTH
Definition: PciIo.h:28
#define EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE
Map a memory range so writes are combined.
Definition: PciIo.h:56
#define EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY
MEM cycles 0xA0000-0xBFFFF (24 bit decode)
Definition: PciIo.h:52
#define EFI_PCI_IO_PASS_THROUGH_BAR
Special BAR that passes a memory or I/O cycle through unchanged.
Definition: PciIo.h:47
#define EFI_PCI_IO_ATTRIBUTE_VGA_IO_16
I/O cycles 0x3B0-0x3BB and 0x3C0-0x3DF (16 bit decode)
Definition: PciIo.h:67
#define EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE
Clear for an add-in PCI Device.
Definition: PciIo.h:62
#define EFI_PCI_IO_ATTRIBUTE_ISA_IO
I/O cycles 0x0100-0x03FF or greater (10 bit decode)
Definition: PciIo.h:50
#define EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
Clear for PCI controllers that can not genrate a DAC.
Definition: PciIo.h:64
#define EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16
I/O cycles 0x3C6, 0x3C8, 0x3C9 (16 bit decode)
Definition: PciIo.h:66
#define EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM
Clear for a physical PCI Option ROM accessed through ROM BAR.
Definition: PciIo.h:63
EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION
Definition: PciIo.h:99
@ EfiPciIoAttributeOperationDisable
Definition: PciIo.h:115
@ EfiPciIoAttributeOperationGet
Definition: PciIo.h:103
@ EfiPciIoAttributeOperationEnable
Definition: PciIo.h:111
@ EfiPciIoAttributeOperationSet
Definition: PciIo.h:107
@ EfiPciIoAttributeOperationSupported
Definition: PciIo.h:119
#define EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED
Map a memory range so all r/w accesses are cached.
Definition: PciIo.h:60
#define EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
Enable the DMA bit in the PCI Config Header.
Definition: PciIo.h:59
#define EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO
I/O cycles 0x3C6, 0x3C8, 0x3C9 (10 bit decode)
Definition: PciIo.h:51
EFI_PCI_IO_PROTOCOL_OPERATION
Definition: PciIo.h:77
@ EfiPciIoOperationBusMasterWrite
Definition: PciIo.h:85
@ EfiPciIoOperationBusMasterRead
Definition: PciIo.h:81
@ EfiPciIoOperationBusMasterCommonBuffer
Definition: PciIo.h:90
#define EFI_PCI_IO_ATTRIBUTE_MEMORY
Enable the Memory decode bit in the PCI Config Header.
Definition: PciIo.h:58
#define EFI_PCI_IO_ATTRIBUTE_IO
Enable the I/O decode bit in the PCI Config Header.
Definition: PciIo.h:57
#define EFI_PCI_IO_ATTRIBUTE_VGA_IO
I/O cycles 0x3B0-0x3BB and 0x3C0-0x3DF (10 bit decode)
Definition: PciIo.h:53
#define FeaturePcdGet(TokenName)
Definition: PcdLib.h:50
#define EFI_PCI_BRIDGE_CONTROL_VGA_16
0x0010
Definition: Pci22.h:609
#define IS_PCI_BRIDGE(_p)
Definition: Pci22.h:504
#define EFI_PCI_BRIDGE_CONTROL_VGA
0x0008
Definition: Pci22.h:608
#define EFI_PCI_COMMAND_MEMORY_SPACE
0x0002
Definition: Pci22.h:592
#define EFI_PCI_COMMAND_IO_SPACE
0x0001
Definition: Pci22.h:591
#define EFI_PCI_COMMAND_BUS_MASTER
0x0004
Definition: Pci22.h:593
#define IS_CARDBUS_BRIDGE(_p)
Definition: Pci22.h:515
#define EFI_PCI_BRIDGE_CONTROL_ISA
0x0004
Definition: Pci22.h:607
#define EFI_PCI_COMMAND_VGA_PALETTE_SNOOP
0x0020
Definition: Pci22.h:596
#define PCI_EXP_MAX_CONFIG_OFFSET
Definition: Pci23.h:83
#define IS_PCI_GFX(_p)
Definition: PciBus.h:325
#define PCI_READ_COMMAND_REGISTER(a, b)
Definition: PciCommand.h:143
#define PCI_ENABLE_BRIDGE_CONTROL_REGISTER(a, b)
Definition: PciCommand.h:215
#define PCI_DISABLE_COMMAND_REGISTER(a, b)
Definition: PciCommand.h:179
#define PCI_DISABLE_BRIDGE_CONTROL_REGISTER(a, b)
Definition: PciCommand.h:227
#define PCI_ENABLE_COMMAND_REGISTER(a, b)
Definition: PciCommand.h:167
BOOLEAN PciDeviceExisted(IN PCI_IO_DEVICE *Bridge, IN PCI_IO_DEVICE *PciIoDevice)
PCI_IO_DEVICE * LocateVgaDeviceOnHostBridge(IN EFI_HANDLE HostBridgeHandle)
EFI_STATUS EFIAPI PciIoGetLocation(IN EFI_PCI_IO_PROTOCOL *This, OUT UINTN *Segment, OUT UINTN *Bus, OUT UINTN *Device, OUT UINTN *Function)
Definition: PciIo.c:1245
BOOLEAN CheckBarType(IN PCI_IO_DEVICE *PciIoDevice, IN UINT8 BarIndex, IN PCI_BAR_TYPE BarType)
Definition: PciIo.c:1282
EFI_STATUS EFIAPI PciIoMemRead(IN EFI_PCI_IO_PROTOCOL *This, IN EFI_PCI_IO_PROTOCOL_WIDTH Width, IN UINT8 BarIndex, IN UINT64 Offset, IN UINTN Count, IN OUT VOID *Buffer)
Definition: PciIo.c:415
EFI_STATUS EFIAPI PciIoAttributes(IN EFI_PCI_IO_PROTOCOL *This, IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation, IN UINT64 Attributes, OUT UINT64 *Result OPTIONAL)
Definition: PciIo.c:1525
EFI_STATUS EFIAPI PciIoSetBarAttributes(IN EFI_PCI_IO_PROTOCOL *This, IN UINT64 Attributes, IN UINT8 BarIndex, IN OUT UINT64 *Offset, IN OUT UINT64 *Length)
Definition: PciIo.c:2012
EFI_STATUS EFIAPI PciIoConfigRead(IN EFI_PCI_IO_PROTOCOL *This, IN EFI_PCI_IO_PROTOCOL_WIDTH Width, IN UINT32 Offset, IN UINTN Count, IN OUT VOID *Buffer)
Definition: PciIo.c:725
EFI_STATUS EFIAPI PciIoMemWrite(IN EFI_PCI_IO_PROTOCOL *This, IN EFI_PCI_IO_PROTOCOL_WIDTH Width, IN UINT8 BarIndex, IN UINT64 Offset, IN UINTN Count, IN OUT VOID *Buffer)
Definition: PciIo.c:493
EFI_STATUS ModifyRootBridgeAttributes(IN PCI_IO_DEVICE *PciIoDevice, IN UINT64 Attributes, IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation)
Definition: PciIo.c:1329
BOOLEAN PciDevicesOnTheSamePath(IN PCI_IO_DEVICE *PciDevice1, IN PCI_IO_DEVICE *PciDevice2)
Definition: PciIo.c:2079
EFI_STATUS EFIAPI PciIoPollMem(IN EFI_PCI_IO_PROTOCOL *This, IN EFI_PCI_IO_PROTOCOL_WIDTH Width, IN UINT8 BarIndex, IN UINT64 Offset, IN UINT64 Mask, IN UINT64 Value, IN UINT64 Delay, OUT UINT64 *Result)
Definition: PciIo.c:197
EFI_STATUS EFIAPI PciIoMap(IN EFI_PCI_IO_PROTOCOL *This, IN EFI_PCI_IO_PROTOCOL_OPERATION Operation, IN VOID *HostAddress, IN OUT UINTN *NumberOfBytes, OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, OUT VOID **Mapping)
Definition: PciIo.c:964
EFI_STATUS EFIAPI PciIoIoWrite(IN EFI_PCI_IO_PROTOCOL *This, IN EFI_PCI_IO_PROTOCOL_WIDTH Width, IN UINT8 BarIndex, IN UINT64 Offset, IN UINTN Count, IN OUT VOID *Buffer)
Definition: PciIo.c:649
VOID InitializePciIoInstance(IN PCI_IO_DEVICE *PciIoDevice)
Definition: PciIo.c:52
UINT64 GetMmioAddressTranslationOffset(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *RootBridgeIo, UINT64 AddrRangeMin, UINT64 AddrLen)
Definition: PciIo.c:1798
EFI_STATUS SupportPaletteSnoopAttributes(IN PCI_IO_DEVICE *PciIoDevice, IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation)
Definition: PciIo.c:1405
EFI_STATUS EFIAPI PciIoConfigWrite(IN EFI_PCI_IO_PROTOCOL *This, IN EFI_PCI_IO_PROTOCOL_WIDTH Width, IN UINT32 Offset, IN UINTN Count, IN OUT VOID *Buffer)
Definition: PciIo.c:794
EFI_STATUS EFIAPI PciIoFlush(IN EFI_PCI_IO_PROTOCOL *This)
Definition: PciIo.c:1207
EFI_STATUS EFIAPI PciIoGetBarAttributes(IN EFI_PCI_IO_PROTOCOL *This, IN UINT8 BarIndex, OUT UINT64 *Supports OPTIONAL, OUT VOID **Resources OPTIONAL)
Definition: PciIo.c:1862
EFI_STATUS PciIoVerifyConfigAccess(IN PCI_IO_DEVICE *PciIoDevice, IN EFI_PCI_IO_PROTOCOL_WIDTH Width, IN UINTN Count, IN UINT64 *Offset)
Definition: PciIo.c:136
EFI_STATUS EFIAPI PciIoCopyMem(IN EFI_PCI_IO_PROTOCOL *This, IN EFI_PCI_IO_PROTOCOL_WIDTH Width, IN UINT8 DestBarIndex, IN UINT64 DestOffset, IN UINT8 SrcBarIndex, IN UINT64 SrcOffset, IN UINTN Count)
Definition: PciIo.c:873
EFI_STATUS EFIAPI PciIoPollIo(IN EFI_PCI_IO_PROTOCOL *This, IN EFI_PCI_IO_PROTOCOL_WIDTH Width, IN UINT8 BarIndex, IN UINT64 Offset, IN UINT64 Mask, IN UINT64 Value, IN UINT64 Delay, OUT UINT64 *Result)
Definition: PciIo.c:309
EFI_STATUS PciIoVerifyBarAccess(IN PCI_IO_DEVICE *PciIoDevice, IN UINT8 BarIndex, IN PCI_BAR_TYPE Type, IN IN EFI_PCI_IO_PROTOCOL_WIDTH Width, IN IN UINTN Count, IN UINT64 *Offset)
Definition: PciIo.c:75
EFI_STATUS EFIAPI PciIoUnmap(IN EFI_PCI_IO_PROTOCOL *This, IN VOID *Mapping)
Definition: PciIo.c:1051
EFI_STATUS EFIAPI PciIoAllocateBuffer(IN EFI_PCI_IO_PROTOCOL *This, IN EFI_ALLOCATE_TYPE Type, IN EFI_MEMORY_TYPE MemoryType, IN UINTN Pages, OUT VOID **HostAddress, IN UINT64 Attributes)
Definition: PciIo.c:1108
EFI_STATUS EFIAPI PciIoIoRead(IN EFI_PCI_IO_PROTOCOL *This, IN EFI_PCI_IO_PROTOCOL_WIDTH Width, IN UINT8 BarIndex, IN UINT64 Offset, IN UINTN Count, IN OUT VOID *Buffer)
Definition: PciIo.c:571
EFI_STATUS EFIAPI PciIoFreeBuffer(IN EFI_PCI_IO_PROTOCOL *This, IN UINTN Pages, IN VOID *HostAddress)
Definition: PciIo.c:1166
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION
@ EfiPciOperationBusMasterRead64
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
#define EFI_ERROR_MINOR
Definition: PiStatusCode.h:58
#define EFI_PROGRESS_CODE
Definition: PiStatusCode.h:43
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
EFI_MEMORY_TYPE
EFI_ALLOCATE_TYPE
Definition: UefiSpec.h:29
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_IO_MEM Write
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_IO_MEM Read