3 Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
4 Copyright (c) 2016, Linaro, Ltd. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "NonDiscoverablePciDeviceIo.h"
18 #include <IndustryStandard/Acpi.h>
20 #include <Protocol/PciRootBridgeIo.h>
23 EFI_PHYSICAL_ADDRESS AllocAddress
;
25 EFI_PCI_IO_PROTOCOL_OPERATION Operation
;
27 } NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO
;
30 // Get the resource associated with BAR number 'BarIndex'.
35 IN NON_DISCOVERABLE_PCI_DEVICE
*Dev
,
37 OUT EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
**Descriptor
40 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Desc
;
42 if (BarIndex
< Dev
->BarOffset
) {
46 BarIndex
-= Dev
->BarOffset
;
48 for (Desc
= Dev
->Device
->Resources
;
49 Desc
->Desc
!= ACPI_END_TAG_DESCRIPTOR
;
50 Desc
= (VOID
*)((UINT8
*)Desc
+ Desc
->Len
+ 3)) {
65 IN EFI_PCI_IO_PROTOCOL
*This
,
66 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
76 return EFI_UNSUPPORTED
;
82 IN EFI_PCI_IO_PROTOCOL
*This
,
83 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
93 return EFI_UNSUPPORTED
;
99 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
107 volatile UINT8
*Dst8
;
108 volatile UINT16
*Dst16
;
109 volatile UINT32
*Dst32
;
110 volatile CONST UINT8
*Src8
;
111 volatile CONST UINT16
*Src16
;
112 volatile CONST UINT32
*Src32
;
115 // Loop for each iteration and move the data
117 switch (Width
& 0x3) {
118 case EfiPciWidthUint8
:
121 for (;Count
> 0; Count
--, Dst8
+= DstStride
, Src8
+= SrcStride
) {
125 case EfiPciWidthUint16
:
126 Dst16
= (UINT16
*)Dst
;
127 Src16
= (UINT16
*)Src
;
128 for (;Count
> 0; Count
--, Dst16
+= DstStride
, Src16
+= SrcStride
) {
132 case EfiPciWidthUint32
:
133 Dst32
= (UINT32
*)Dst
;
134 Src32
= (UINT32
*)Src
;
135 for (;Count
> 0; Count
--, Dst32
+= DstStride
, Src32
+= SrcStride
) {
140 return EFI_INVALID_PARAMETER
;
149 IN EFI_PCI_IO_PROTOCOL
*This
,
150 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
157 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
160 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Desc
;
163 if (Buffer
== NULL
) {
164 return EFI_INVALID_PARAMETER
;
167 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
170 // Only allow accesses to the BARs we emulate
172 Status
= GetBarResource (Dev
, BarIndex
, &Desc
);
173 if (EFI_ERROR (Status
)) {
177 if (Offset
+ (Count
<< (Width
& 0x3)) > Desc
->AddrLen
) {
178 return EFI_UNSUPPORTED
;
181 Address
= (VOID
*)(UINTN
)(Desc
->AddrRangeMin
+ Offset
);
182 AlignMask
= (1 << (Width
& 0x03)) - 1;
183 if ((UINTN
)Address
& AlignMask
) {
184 return EFI_INVALID_PARAMETER
;
188 case EfiPciWidthUint8
:
189 case EfiPciWidthUint16
:
190 case EfiPciWidthUint32
:
191 case EfiPciWidthUint64
:
192 return PciIoMemRW (Width
, Count
, 1, Buffer
, 1, Address
);
194 case EfiPciWidthFifoUint8
:
195 case EfiPciWidthFifoUint16
:
196 case EfiPciWidthFifoUint32
:
197 case EfiPciWidthFifoUint64
:
198 return PciIoMemRW (Width
, Count
, 1, Buffer
, 0, Address
);
200 case EfiPciWidthFillUint8
:
201 case EfiPciWidthFillUint16
:
202 case EfiPciWidthFillUint32
:
203 case EfiPciWidthFillUint64
:
204 return PciIoMemRW (Width
, Count
, 0, Buffer
, 1, Address
);
209 return EFI_INVALID_PARAMETER
;
215 IN EFI_PCI_IO_PROTOCOL
*This
,
216 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
223 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
226 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Desc
;
229 if (Buffer
== NULL
) {
230 return EFI_INVALID_PARAMETER
;
233 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
236 // Only allow accesses to the BARs we emulate
238 Status
= GetBarResource (Dev
, BarIndex
, &Desc
);
239 if (EFI_ERROR (Status
)) {
243 if (Offset
+ (Count
<< (Width
& 0x3)) > Desc
->AddrLen
) {
244 return EFI_UNSUPPORTED
;
247 Address
= (VOID
*)(UINTN
)(Desc
->AddrRangeMin
+ Offset
);
248 AlignMask
= (1 << (Width
& 0x03)) - 1;
249 if ((UINTN
)Address
& AlignMask
) {
250 return EFI_INVALID_PARAMETER
;
254 case EfiPciWidthUint8
:
255 case EfiPciWidthUint16
:
256 case EfiPciWidthUint32
:
257 case EfiPciWidthUint64
:
258 return PciIoMemRW (Width
, Count
, 1, Address
, 1, Buffer
);
260 case EfiPciWidthFifoUint8
:
261 case EfiPciWidthFifoUint16
:
262 case EfiPciWidthFifoUint32
:
263 case EfiPciWidthFifoUint64
:
264 return PciIoMemRW (Width
, Count
, 0, Address
, 1, Buffer
);
266 case EfiPciWidthFillUint8
:
267 case EfiPciWidthFillUint16
:
268 case EfiPciWidthFillUint32
:
269 case EfiPciWidthFillUint64
:
270 return PciIoMemRW (Width
, Count
, 1, Address
, 0, Buffer
);
275 return EFI_INVALID_PARAMETER
;
281 IN EFI_PCI_IO_PROTOCOL
*This
,
282 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
290 return EFI_UNSUPPORTED
;
296 IN EFI_PCI_IO_PROTOCOL
*This
,
297 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
305 return EFI_UNSUPPORTED
;
311 IN EFI_PCI_IO_PROTOCOL
*This
,
312 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
318 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
322 if (Width
< 0 || Width
>= EfiPciIoWidthMaximum
|| Buffer
== NULL
) {
323 return EFI_INVALID_PARAMETER
;
326 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
327 Address
= (UINT8
*)&Dev
->ConfigSpace
+ Offset
;
328 Length
= Count
<< ((UINTN
)Width
& 0x3);
330 if (Offset
+ Length
> sizeof (Dev
->ConfigSpace
)) {
332 // Read all zeroes for config space accesses beyond the first
335 Length
-= sizeof (Dev
->ConfigSpace
) - Offset
;
336 ZeroMem ((UINT8
*)Buffer
+ sizeof (Dev
->ConfigSpace
) - Offset
, Length
);
338 Count
-= Length
>> ((UINTN
)Width
& 0x3);
340 return PciIoMemRW (Width
, Count
, 1, Buffer
, 1, Address
);
346 IN EFI_PCI_IO_PROTOCOL
*This
,
347 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
353 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
356 if (Width
< 0 || Width
>= EfiPciIoWidthMaximum
|| Buffer
== NULL
) {
357 return EFI_INVALID_PARAMETER
;
360 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
361 Address
= (UINT8
*)&Dev
->ConfigSpace
+ Offset
;
363 if (Offset
+ (Count
<< ((UINTN
)Width
& 0x3)) > sizeof (Dev
->ConfigSpace
)) {
364 return EFI_UNSUPPORTED
;
367 return PciIoMemRW (Width
, Count
, 1, Address
, 1, Buffer
);
373 IN EFI_PCI_IO_PROTOCOL
*This
,
374 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
375 IN UINT8 DestBarIndex
,
376 IN UINT64 DestOffset
,
377 IN UINT8 SrcBarIndex
,
383 return EFI_UNSUPPORTED
;
389 IN EFI_PCI_IO_PROTOCOL
*This
,
390 IN EFI_PCI_IO_PROTOCOL_OPERATION Operation
,
391 IN VOID
*HostAddress
,
392 IN OUT UINTN
*NumberOfBytes
,
393 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
397 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
399 NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO
*MapInfo
;
402 // If HostAddress exceeds 4 GB, and this device does not support 64-bit DMA
403 // addressing, we need to allocate a bounce buffer and copy over the data.
405 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
406 if ((Dev
->Attributes
& EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
) == 0 &&
407 (UINTN
)HostAddress
+ *NumberOfBytes
> SIZE_4GB
) {
410 // Bounce buffering is not possible for consistent mappings
412 if (Operation
== EfiPciIoOperationBusMasterCommonBuffer
) {
413 return EFI_UNSUPPORTED
;
416 MapInfo
= AllocatePool (sizeof *MapInfo
);
417 if (MapInfo
== NULL
) {
418 return EFI_OUT_OF_RESOURCES
;
421 MapInfo
->AllocAddress
= MAX_UINT32
;
422 MapInfo
->HostAddress
= HostAddress
;
423 MapInfo
->Operation
= Operation
;
424 MapInfo
->NumberOfBytes
= *NumberOfBytes
;
426 Status
= gBS
->AllocatePages (AllocateMaxAddress
, EfiBootServicesData
,
427 EFI_SIZE_TO_PAGES (MapInfo
->NumberOfBytes
),
428 &MapInfo
->AllocAddress
);
429 if (EFI_ERROR (Status
)) {
431 // If we fail here, it is likely because the system has no memory below
432 // 4 GB to begin with. There is not much we can do about that other than
433 // fail the map request.
436 return EFI_DEVICE_ERROR
;
438 if (Operation
== EfiPciIoOperationBusMasterRead
) {
439 gBS
->CopyMem ((VOID
*)(UINTN
)MapInfo
->AllocAddress
, HostAddress
,
442 *DeviceAddress
= MapInfo
->AllocAddress
;
445 *DeviceAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)HostAddress
;
454 IN EFI_PCI_IO_PROTOCOL
*This
,
458 NON_DISCOVERABLE_PCI_DEVICE_MAP_INFO
*MapInfo
;
461 if (MapInfo
!= NULL
) {
462 if (MapInfo
->Operation
== EfiPciIoOperationBusMasterWrite
) {
463 gBS
->CopyMem (MapInfo
->HostAddress
, (VOID
*)(UINTN
)MapInfo
->AllocAddress
,
464 MapInfo
->NumberOfBytes
);
466 gBS
->FreePages (MapInfo
->AllocAddress
,
467 EFI_SIZE_TO_PAGES (MapInfo
->NumberOfBytes
));
475 CoherentPciIoAllocateBuffer (
476 IN EFI_PCI_IO_PROTOCOL
*This
,
477 IN EFI_ALLOCATE_TYPE Type
,
478 IN EFI_MEMORY_TYPE MemoryType
,
480 OUT VOID
**HostAddress
,
484 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
485 EFI_PHYSICAL_ADDRESS AllocAddress
;
486 EFI_ALLOCATE_TYPE AllocType
;
489 if ((Attributes
& ~(EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE
|
490 EFI_PCI_ATTRIBUTE_MEMORY_CACHED
)) != 0) {
491 return EFI_UNSUPPORTED
;
495 // Allocate below 4 GB if the dual address cycle attribute has not
496 // been set. If the system has no memory available below 4 GB, there
497 // is little we can do except propagate the error.
499 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
500 if ((Dev
->Attributes
& EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
) == 0) {
501 AllocAddress
= MAX_UINT32
;
502 AllocType
= AllocateMaxAddress
;
504 AllocType
= AllocateAnyPages
;
507 Status
= gBS
->AllocatePages (AllocType
, MemoryType
, Pages
, &AllocAddress
);
508 if (!EFI_ERROR (Status
)) {
509 *HostAddress
= (VOID
*)(UINTN
)AllocAddress
;
516 CoherentPciIoFreeBuffer (
517 IN EFI_PCI_IO_PROTOCOL
*This
,
522 FreePages (HostAddress
, Pages
);
530 IN EFI_PCI_IO_PROTOCOL
*This
539 IN EFI_PCI_IO_PROTOCOL
*This
,
540 OUT UINTN
*SegmentNumber
,
541 OUT UINTN
*BusNumber
,
542 OUT UINTN
*DeviceNumber
,
543 OUT UINTN
*FunctionNumber
546 if (SegmentNumber
== NULL
||
548 DeviceNumber
== NULL
||
549 FunctionNumber
== NULL
) {
550 return EFI_INVALID_PARAMETER
;
564 IN EFI_PCI_IO_PROTOCOL
*This
,
565 IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation
,
566 IN UINT64 Attributes
,
567 OUT UINT64
*Result OPTIONAL
570 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
573 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
577 case EfiPciIoAttributeOperationGet
:
578 if (Result
== NULL
) {
579 return EFI_INVALID_PARAMETER
;
581 *Result
= Dev
->Attributes
;
584 case EfiPciIoAttributeOperationSupported
:
585 if (Result
== NULL
) {
586 return EFI_INVALID_PARAMETER
;
588 *Result
= EFI_PCI_DEVICE_ENABLE
| EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
;
591 case EfiPciIoAttributeOperationEnable
:
592 Attributes
|= Dev
->Attributes
;
593 case EfiPciIoAttributeOperationSet
:
594 Enable
= ((~Dev
->Attributes
& Attributes
) & EFI_PCI_DEVICE_ENABLE
) != 0;
595 Dev
->Attributes
= Attributes
;
598 case EfiPciIoAttributeOperationDisable
:
599 Dev
->Attributes
&= ~Attributes
;
603 return EFI_INVALID_PARAMETER
;
607 // If we're setting any of the EFI_PCI_DEVICE_ENABLE bits, perform
608 // the device specific initialization now.
610 if (Enable
&& !Dev
->Enabled
&& Dev
->Device
->Initialize
!= NULL
) {
611 Dev
->Device
->Initialize (Dev
->Device
);
619 PciIoGetBarAttributes (
620 IN EFI_PCI_IO_PROTOCOL
*This
,
622 OUT UINT64
*Supports OPTIONAL
,
623 OUT VOID
**Resources OPTIONAL
626 NON_DISCOVERABLE_PCI_DEVICE
*Dev
;
627 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptor
, *BarDesc
;
628 EFI_ACPI_END_TAG_DESCRIPTOR
*End
;
631 if (Supports
== NULL
&& Resources
== NULL
) {
632 return EFI_INVALID_PARAMETER
;
635 Dev
= NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO(This
);
637 Status
= GetBarResource (Dev
, BarIndex
, &BarDesc
);
638 if (EFI_ERROR (Status
)) {
643 // Don't expose any configurable attributes for our emulated BAR
645 if (Supports
!= NULL
) {
649 if (Resources
!= NULL
) {
650 Descriptor
= AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) +
651 sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
652 if (Descriptor
== NULL
) {
653 return EFI_OUT_OF_RESOURCES
;
656 CopyMem (Descriptor
, BarDesc
, sizeof *Descriptor
);
658 End
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) (Descriptor
+ 1);
659 End
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
662 *Resources
= Descriptor
;
669 PciIoSetBarAttributes (
670 IN EFI_PCI_IO_PROTOCOL
*This
,
671 IN UINT64 Attributes
,
673 IN OUT UINT64
*Offset
,
674 IN OUT UINT64
*Length
678 return EFI_UNSUPPORTED
;
681 STATIC CONST EFI_PCI_IO_PROTOCOL PciIoTemplate
=
685 { PciIoMemRead
, PciIoMemWrite
},
686 { PciIoIoRead
, PciIoIoWrite
},
687 { PciIoPciRead
, PciIoPciWrite
},
691 CoherentPciIoAllocateBuffer
,
692 CoherentPciIoFreeBuffer
,
696 PciIoGetBarAttributes
,
697 PciIoSetBarAttributes
,
703 InitializePciIoProtocol (
704 NON_DISCOVERABLE_PCI_DEVICE
*Dev
707 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Desc
;
710 Dev
->ConfigSpace
.Hdr
.VendorId
= PCI_ID_VENDOR_UNKNOWN
;
711 Dev
->ConfigSpace
.Hdr
.DeviceId
= PCI_ID_DEVICE_DONTCARE
;
713 // Copy protocol structure
714 CopyMem(&Dev
->PciIo
, &PciIoTemplate
, sizeof PciIoTemplate
);
716 if (CompareGuid (Dev
->Device
->Type
, &gEdkiiNonDiscoverableAhciDeviceGuid
)) {
717 Dev
->ConfigSpace
.Hdr
.ClassCode
[0] = PCI_IF_MASS_STORAGE_AHCI
;
718 Dev
->ConfigSpace
.Hdr
.ClassCode
[1] = PCI_CLASS_MASS_STORAGE_SATADPA
;
719 Dev
->ConfigSpace
.Hdr
.ClassCode
[2] = PCI_CLASS_MASS_STORAGE
;
721 } else if (CompareGuid (Dev
->Device
->Type
,
722 &gEdkiiNonDiscoverableEhciDeviceGuid
)) {
723 Dev
->ConfigSpace
.Hdr
.ClassCode
[0] = PCI_IF_EHCI
;
724 Dev
->ConfigSpace
.Hdr
.ClassCode
[1] = PCI_CLASS_SERIAL_USB
;
725 Dev
->ConfigSpace
.Hdr
.ClassCode
[2] = PCI_CLASS_SERIAL
;
727 } else if (CompareGuid (Dev
->Device
->Type
,
728 &gEdkiiNonDiscoverableNvmeDeviceGuid
)) {
729 Dev
->ConfigSpace
.Hdr
.ClassCode
[0] = 0x2; // PCI_IF_NVMHCI
730 Dev
->ConfigSpace
.Hdr
.ClassCode
[1] = 0x8; // PCI_CLASS_MASS_STORAGE_NVM
731 Dev
->ConfigSpace
.Hdr
.ClassCode
[2] = PCI_CLASS_MASS_STORAGE
;
733 } else if (CompareGuid (Dev
->Device
->Type
,
734 &gEdkiiNonDiscoverableOhciDeviceGuid
)) {
735 Dev
->ConfigSpace
.Hdr
.ClassCode
[0] = PCI_IF_OHCI
;
736 Dev
->ConfigSpace
.Hdr
.ClassCode
[1] = PCI_CLASS_SERIAL_USB
;
737 Dev
->ConfigSpace
.Hdr
.ClassCode
[2] = PCI_CLASS_SERIAL
;
739 } else if (CompareGuid (Dev
->Device
->Type
,
740 &gEdkiiNonDiscoverableSdhciDeviceGuid
)) {
741 Dev
->ConfigSpace
.Hdr
.ClassCode
[0] = 0x0; // don't care
742 Dev
->ConfigSpace
.Hdr
.ClassCode
[1] = PCI_SUBCLASS_SD_HOST_CONTROLLER
;
743 Dev
->ConfigSpace
.Hdr
.ClassCode
[2] = PCI_CLASS_SYSTEM_PERIPHERAL
;
745 } else if (CompareGuid (Dev
->Device
->Type
,
746 &gEdkiiNonDiscoverableXhciDeviceGuid
)) {
747 Dev
->ConfigSpace
.Hdr
.ClassCode
[0] = PCI_IF_XHCI
;
748 Dev
->ConfigSpace
.Hdr
.ClassCode
[1] = PCI_CLASS_SERIAL_USB
;
749 Dev
->ConfigSpace
.Hdr
.ClassCode
[2] = PCI_CLASS_SERIAL
;
751 } else if (CompareGuid (Dev
->Device
->Type
,
752 &gEdkiiNonDiscoverableUhciDeviceGuid
)) {
753 Dev
->ConfigSpace
.Hdr
.ClassCode
[0] = PCI_IF_UHCI
;
754 Dev
->ConfigSpace
.Hdr
.ClassCode
[1] = PCI_CLASS_SERIAL_USB
;
755 Dev
->ConfigSpace
.Hdr
.ClassCode
[2] = PCI_CLASS_SERIAL
;
757 } else if (CompareGuid (Dev
->Device
->Type
,
758 &gEdkiiNonDiscoverableUfsDeviceGuid
)) {
759 Dev
->ConfigSpace
.Hdr
.ClassCode
[0] = 0x0; // don't care
760 Dev
->ConfigSpace
.Hdr
.ClassCode
[1] = 0x9; // UFS controller subclass;
761 Dev
->ConfigSpace
.Hdr
.ClassCode
[2] = PCI_CLASS_MASS_STORAGE
;
764 ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER
);
768 // Iterate over the resources to populate the virtual BARs
770 Idx
= Dev
->BarOffset
;
771 for (Desc
= Dev
->Device
->Resources
, Dev
->BarCount
= 0;
772 Desc
->Desc
!= ACPI_END_TAG_DESCRIPTOR
;
773 Desc
= (VOID
*)((UINT8
*)Desc
+ Desc
->Len
+ 3)) {
775 ASSERT (Desc
->Desc
== ACPI_ADDRESS_SPACE_DESCRIPTOR
);
776 ASSERT (Desc
->ResType
== ACPI_ADDRESS_SPACE_TYPE_MEM
);
778 if (Idx
>= PCI_MAX_BARS
||
779 (Idx
== PCI_MAX_BARS
- 1 && Desc
->AddrSpaceGranularity
== 64)) {
781 "%a: resource count exceeds number of emulated BARs\n",
787 Dev
->ConfigSpace
.Device
.Bar
[Idx
] = (UINT32
)Desc
->AddrRangeMin
;
790 if (Desc
->AddrSpaceGranularity
== 64) {
791 Dev
->ConfigSpace
.Device
.Bar
[Idx
] |= 0x4;
792 Dev
->ConfigSpace
.Device
.Bar
[++Idx
] = (UINT32
)RShiftU64 (
793 Desc
->AddrRangeMin
, 32);