3 Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php.
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14 #include "DmaProtection.h"
17 Return the index of PCI descriptor.
19 @param[in] VtdIndex The index used to identify a VTd engine.
20 @param[in] Segment The Segment used to identify a VTd engine.
21 @param[in] SourceId The SourceId used to identify a VTd engine and table entry.
23 @return The index of the PCI descriptor.
24 @retval (UINTN)-1 The PCI descriptor is not found.
30 IN VTD_SOURCE_ID SourceId
35 if (Segment
!= mVtdUnitInformation
[VtdIndex
].Segment
) {
39 for (Index
= 0; Index
< mVtdUnitInformation
[VtdIndex
].PciDeviceInfo
.PciDescriptorNumber
; Index
++) {
40 if ((mVtdUnitInformation
[VtdIndex
].PciDeviceInfo
.PciDescriptors
[Index
].Bits
.Bus
== SourceId
.Bits
.Bus
) &&
41 (mVtdUnitInformation
[VtdIndex
].PciDeviceInfo
.PciDescriptors
[Index
].Bits
.Device
== SourceId
.Bits
.Device
) &&
42 (mVtdUnitInformation
[VtdIndex
].PciDeviceInfo
.PciDescriptors
[Index
].Bits
.Function
== SourceId
.Bits
.Function
) ) {
51 Register PCI device to VTd engine as PCI descriptor.
53 @param[in] VtdIndex The index of VTd engine.
54 @param[in] Segment The segment of the source.
55 @param[in] SourceId The SourceId of the source.
56 @param[in] IsRealPciDevice TRUE: It is a real PCI device.
57 FALSE: It is not a real PCI device.
58 @param[in] CheckExist TRUE: ERROR will be returned if the PCI device is already registered.
59 FALSE: SUCCESS will be returned if the PCI device is registered.
61 @retval EFI_SUCCESS The PCI device is registered.
62 @retval EFI_OUT_OF_RESOURCES No enough resource to register a new PCI device.
63 @retval EFI_ALREADY_STARTED The device is already registered.
69 IN VTD_SOURCE_ID SourceId
,
70 IN BOOLEAN IsRealPciDevice
,
74 PCI_DEVICE_INFORMATION
*PciDeviceInfo
;
75 VTD_SOURCE_ID
*PciDescriptor
;
76 UINTN PciDescriptorIndex
;
78 BOOLEAN
*NewIsRealPciDevice
;
79 VTD_SOURCE_ID
*NewPciDescriptors
;
81 PciDeviceInfo
= &mVtdUnitInformation
[VtdIndex
].PciDeviceInfo
;
83 if (PciDeviceInfo
->IncludeAllFlag
) {
85 // Do not register device in other VTD Unit
87 for (Index
= 0; Index
< VtdIndex
; Index
++) {
88 PciDescriptorIndex
= GetPciDescriptor (Index
, Segment
, SourceId
);
89 if (PciDescriptorIndex
!= (UINTN
)-1) {
90 DEBUG ((DEBUG_INFO
, " RegisterPciDevice: PCI S%04x B%02x D%02x F%02x already registered by Other Vtd(%d)\n", Segment
, SourceId
.Bits
.Bus
, SourceId
.Bits
.Device
, SourceId
.Bits
.Function
, Index
));
96 PciDescriptorIndex
= GetPciDescriptor (VtdIndex
, Segment
, SourceId
);
97 if (PciDescriptorIndex
== (UINTN
)-1) {
102 if (PciDeviceInfo
->PciDescriptorNumber
>= PciDeviceInfo
->PciDescriptorMaxNumber
) {
106 NewIsRealPciDevice
= AllocateZeroPool (sizeof(*NewIsRealPciDevice
) * (PciDeviceInfo
->PciDescriptorMaxNumber
+ MAX_PCI_DESCRIPTORS
));
107 if (NewIsRealPciDevice
== NULL
) {
108 return EFI_OUT_OF_RESOURCES
;
110 NewPciDescriptors
= AllocateZeroPool (sizeof(*NewPciDescriptors
) * (PciDeviceInfo
->PciDescriptorMaxNumber
+ MAX_PCI_DESCRIPTORS
));
111 if (NewPciDescriptors
== NULL
) {
112 FreePool (NewIsRealPciDevice
);
113 return EFI_OUT_OF_RESOURCES
;
115 PciDeviceInfo
->PciDescriptorMaxNumber
+= MAX_PCI_DESCRIPTORS
;
116 if (PciDeviceInfo
->IsRealPciDevice
!= NULL
) {
117 CopyMem (NewIsRealPciDevice
, PciDeviceInfo
->IsRealPciDevice
, sizeof(*NewIsRealPciDevice
) * PciDeviceInfo
->PciDescriptorNumber
);
118 FreePool (PciDeviceInfo
->IsRealPciDevice
);
120 PciDeviceInfo
->IsRealPciDevice
= NewIsRealPciDevice
;
121 if (PciDeviceInfo
->PciDescriptors
!= NULL
) {
122 CopyMem (NewPciDescriptors
, PciDeviceInfo
->PciDescriptors
, sizeof(*NewPciDescriptors
) * PciDeviceInfo
->PciDescriptorNumber
);
123 FreePool (PciDeviceInfo
->PciDescriptors
);
125 PciDeviceInfo
->PciDescriptors
= NewPciDescriptors
;
128 ASSERT (PciDeviceInfo
->PciDescriptorNumber
< PciDeviceInfo
->PciDescriptorMaxNumber
);
130 PciDescriptor
= &PciDeviceInfo
->PciDescriptors
[PciDeviceInfo
->PciDescriptorNumber
];
131 PciDescriptor
->Bits
.Bus
= SourceId
.Bits
.Bus
;
132 PciDescriptor
->Bits
.Device
= SourceId
.Bits
.Device
;
133 PciDescriptor
->Bits
.Function
= SourceId
.Bits
.Function
;
134 PciDeviceInfo
->IsRealPciDevice
[PciDeviceInfo
->PciDescriptorNumber
] = IsRealPciDevice
;
136 PciDeviceInfo
->PciDescriptorNumber
++;
138 DEBUG ((DEBUG_INFO
, " RegisterPciDevice: PCI S%04x B%02x D%02x F%02x", Segment
, SourceId
.Bits
.Bus
, SourceId
.Bits
.Device
, SourceId
.Bits
.Function
));
139 if (!IsRealPciDevice
) {
140 DEBUG ((DEBUG_INFO
, " (*)"));
142 DEBUG ((DEBUG_INFO
, "\n"));
145 DEBUG ((DEBUG_INFO
, " RegisterPciDevice: PCI S%04x B%02x D%02x F%02x already registered\n", Segment
, SourceId
.Bits
.Bus
, SourceId
.Bits
.Device
, SourceId
.Bits
.Function
));
146 return EFI_ALREADY_STARTED
;
154 Scan PCI bus and register PCI devices under the bus.
156 @param[in] VtdIndex The index of VTd engine.
157 @param[in] Segment The segment of the source.
158 @param[in] Bus The bus of the source.
160 @retval EFI_SUCCESS The PCI devices under the bus are registered.
161 @retval EFI_OUT_OF_RESOURCES No enough resource to register a new PCI device.
172 UINT8 SecondaryBusNumber
;
180 VTD_SOURCE_ID SourceId
;
182 // Scan the PCI bus for devices
183 for (Device
= 0; Device
< PCI_MAX_DEVICE
+ 1; Device
++) {
184 HeaderType
= PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(Segment
, Bus
, Device
, 0, PCI_HEADER_TYPE_OFFSET
));
185 MaxFunction
= PCI_MAX_FUNC
+ 1;
186 if ((HeaderType
& HEADER_TYPE_MULTI_FUNCTION
) == 0x00) {
189 for (Function
= 0; Function
< MaxFunction
; Function
++) {
190 VendorID
= PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRESS(Segment
, Bus
, Device
, Function
, PCI_VENDOR_ID_OFFSET
));
191 DeviceID
= PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRESS(Segment
, Bus
, Device
, Function
, PCI_DEVICE_ID_OFFSET
));
192 if (VendorID
== 0xFFFF && DeviceID
== 0xFFFF) {
196 SourceId
.Bits
.Bus
= Bus
;
197 SourceId
.Bits
.Device
= Device
;
198 SourceId
.Bits
.Function
= Function
;
199 Status
= RegisterPciDevice (VtdIndex
, Segment
, SourceId
, TRUE
, FALSE
);
200 if (EFI_ERROR (Status
)) {
204 BaseClass
= PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(Segment
, Bus
, Device
, Function
, PCI_CLASSCODE_OFFSET
+ 2));
205 if (BaseClass
== PCI_CLASS_BRIDGE
) {
206 SubClass
= PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(Segment
, Bus
, Device
, Function
, PCI_CLASSCODE_OFFSET
+ 1));
207 if (SubClass
== PCI_CLASS_BRIDGE_P2P
) {
208 SecondaryBusNumber
= PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(Segment
, Bus
, Device
, Function
, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET
));
209 DEBUG ((DEBUG_INFO
," ScanPciBus: PCI bridge S%04x B%02x D%02x F%02x (SecondBus:%02x)\n", Segment
, Bus
, Device
, Function
, SecondaryBusNumber
));
210 if (SecondaryBusNumber
!= 0) {
211 Status
= ScanPciBus (VtdIndex
, Segment
, SecondaryBusNumber
);
212 if (EFI_ERROR (Status
)) {
225 Dump the PCI device information managed by this VTd engine.
227 @param[in] VtdIndex The index of VTd engine.
236 DEBUG ((DEBUG_INFO
,"PCI Device Information (Number 0x%x, IncludeAll - %d):\n",
237 mVtdUnitInformation
[VtdIndex
].PciDeviceInfo
.PciDescriptorNumber
,
238 mVtdUnitInformation
[VtdIndex
].PciDeviceInfo
.IncludeAllFlag
240 for (Index
= 0; Index
< mVtdUnitInformation
[VtdIndex
].PciDeviceInfo
.PciDescriptorNumber
; Index
++) {
241 DEBUG ((DEBUG_INFO
," S%04x B%02x D%02x F%02x\n",
242 mVtdUnitInformation
[VtdIndex
].Segment
,
243 mVtdUnitInformation
[VtdIndex
].PciDeviceInfo
.PciDescriptors
[Index
].Bits
.Bus
,
244 mVtdUnitInformation
[VtdIndex
].PciDeviceInfo
.PciDescriptors
[Index
].Bits
.Device
,
245 mVtdUnitInformation
[VtdIndex
].PciDeviceInfo
.PciDescriptors
[Index
].Bits
.Function
251 Find the VTd index by the Segment and SourceId.
253 @param[in] Segment The segment of the source.
254 @param[in] SourceId The SourceId of the source.
255 @param[out] ExtContextEntry The ExtContextEntry of the source.
256 @param[out] ContextEntry The ContextEntry of the source.
258 @return The index of the PCI descriptor.
259 @retval (UINTN)-1 The PCI descriptor is not found.
262 FindVtdIndexByPciDevice (
264 IN VTD_SOURCE_ID SourceId
,
265 OUT VTD_EXT_CONTEXT_ENTRY
**ExtContextEntry
,
266 OUT VTD_CONTEXT_ENTRY
**ContextEntry
270 VTD_ROOT_ENTRY
*RootEntry
;
271 VTD_CONTEXT_ENTRY
*ContextEntryTable
;
272 VTD_CONTEXT_ENTRY
*ThisContextEntry
;
273 VTD_EXT_ROOT_ENTRY
*ExtRootEntry
;
274 VTD_EXT_CONTEXT_ENTRY
*ExtContextEntryTable
;
275 VTD_EXT_CONTEXT_ENTRY
*ThisExtContextEntry
;
276 UINTN PciDescriptorIndex
;
278 for (VtdIndex
= 0; VtdIndex
< mVtdUnitNumber
; VtdIndex
++) {
279 if (Segment
!= mVtdUnitInformation
[VtdIndex
].Segment
) {
283 PciDescriptorIndex
= GetPciDescriptor (VtdIndex
, Segment
, SourceId
);
284 if (PciDescriptorIndex
== (UINTN
)-1) {
288 // DEBUG ((DEBUG_INFO,"FindVtdIndex(0x%x) for S%04x B%02x D%02x F%02x\n", VtdIndex, Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function));
290 if (mVtdUnitInformation
[VtdIndex
].ExtRootEntryTable
!= 0) {
291 ExtRootEntry
= &mVtdUnitInformation
[VtdIndex
].ExtRootEntryTable
[SourceId
.Index
.RootIndex
];
292 ExtContextEntryTable
= (VTD_EXT_CONTEXT_ENTRY
*)(UINTN
)VTD_64BITS_ADDRESS(ExtRootEntry
->Bits
.LowerContextTablePointerLo
, ExtRootEntry
->Bits
.LowerContextTablePointerHi
) ;
293 ThisExtContextEntry
= &ExtContextEntryTable
[SourceId
.Index
.ContextIndex
];
294 if (ThisExtContextEntry
->Bits
.AddressWidth
== 0) {
297 *ExtContextEntry
= ThisExtContextEntry
;
298 *ContextEntry
= NULL
;
300 RootEntry
= &mVtdUnitInformation
[VtdIndex
].RootEntryTable
[SourceId
.Index
.RootIndex
];
301 ContextEntryTable
= (VTD_CONTEXT_ENTRY
*)(UINTN
)VTD_64BITS_ADDRESS(RootEntry
->Bits
.ContextTablePointerLo
, RootEntry
->Bits
.ContextTablePointerHi
) ;
302 ThisContextEntry
= &ContextEntryTable
[SourceId
.Index
.ContextIndex
];
303 if (ThisContextEntry
->Bits
.AddressWidth
== 0) {
306 *ExtContextEntry
= NULL
;
307 *ContextEntry
= ThisContextEntry
;