]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c
MdeModulePkg/NonDiscoverablePciDeviceDxe: add support for non-coherent DMA
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / NonDiscoverablePciDeviceDxe / NonDiscoverablePciDeviceDxe.c
1 /** @file
2
3 Copyright (C) 2016, Linaro Ltd. All rights reserved.<BR>
4
5 This program and the accompanying materials are licensed and made available
6 under the terms and conditions of the BSD License which accompanies this
7 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, WITHOUT
11 WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "NonDiscoverablePciDeviceIo.h"
16
17 #include <Protocol/DriverBinding.h>
18
19 EFI_CPU_ARCH_PROTOCOL *mCpu;
20
21 //
22 // We only support the following device types
23 //
24 STATIC
25 CONST EFI_GUID * CONST
26 SupportedNonDiscoverableDevices [] = {
27 &gEdkiiNonDiscoverableAhciDeviceGuid,
28 &gEdkiiNonDiscoverableEhciDeviceGuid,
29 &gEdkiiNonDiscoverableNvmeDeviceGuid,
30 &gEdkiiNonDiscoverableOhciDeviceGuid,
31 &gEdkiiNonDiscoverableSdhciDeviceGuid,
32 &gEdkiiNonDiscoverableUfsDeviceGuid,
33 &gEdkiiNonDiscoverableUhciDeviceGuid,
34 &gEdkiiNonDiscoverableXhciDeviceGuid,
35 };
36
37 //
38 // Probe, start and stop functions of this driver, called by the DXE core for
39 // specific devices.
40 //
41 // The following specifications document these interfaces:
42 // - Driver Writer's Guide for UEFI 2.3.1 v1.01, 9 Driver Binding Protocol
43 // - UEFI Spec 2.3.1 + Errata C, 10.1 EFI Driver Binding Protocol
44 //
45 // The implementation follows:
46 // - Driver Writer's Guide for UEFI 2.3.1 v1.01
47 // - 5.1.3.4 OpenProtocol() and CloseProtocol()
48 // - UEFI Spec 2.3.1 + Errata C
49 // - 6.3 Protocol Handler Services
50 //
51
52 STATIC
53 EFI_STATUS
54 EFIAPI
55 NonDiscoverablePciDeviceSupported (
56 IN EFI_DRIVER_BINDING_PROTOCOL *This,
57 IN EFI_HANDLE DeviceHandle,
58 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
59 )
60 {
61 NON_DISCOVERABLE_DEVICE *Device;
62 EFI_STATUS Status;
63 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;
64 INTN Idx;
65
66 Status = gBS->OpenProtocol (DeviceHandle,
67 &gEdkiiNonDiscoverableDeviceProtocolGuid, (VOID **)&Device,
68 This->DriverBindingHandle, DeviceHandle,
69 EFI_OPEN_PROTOCOL_BY_DRIVER);
70 if (EFI_ERROR (Status)) {
71 return Status;
72 }
73
74 Status = EFI_UNSUPPORTED;
75 for (Idx = 0; Idx < ARRAY_SIZE (SupportedNonDiscoverableDevices); Idx++) {
76 if (CompareGuid (Device->Type, SupportedNonDiscoverableDevices [Idx])) {
77 Status = EFI_SUCCESS;
78 break;
79 }
80 }
81
82 if (EFI_ERROR (Status)) {
83 goto CloseProtocol;
84 }
85
86 //
87 // We only support MMIO devices, so iterate over the resources to ensure
88 // that they only describe things that we can handle
89 //
90 for (Desc = Device->Resources; Desc->Desc != ACPI_END_TAG_DESCRIPTOR;
91 Desc = (VOID *)((UINT8 *)Desc + Desc->Len + 3)) {
92 if (Desc->Desc != ACPI_ADDRESS_SPACE_DESCRIPTOR ||
93 Desc->ResType != ACPI_ADDRESS_SPACE_TYPE_MEM) {
94 Status = EFI_UNSUPPORTED;
95 break;
96 }
97 }
98
99 CloseProtocol:
100 gBS->CloseProtocol (DeviceHandle, &gEdkiiNonDiscoverableDeviceProtocolGuid,
101 This->DriverBindingHandle, DeviceHandle);
102
103 return Status;
104 }
105
106 STATIC
107 EFI_STATUS
108 EFIAPI
109 NonDiscoverablePciDeviceStart (
110 IN EFI_DRIVER_BINDING_PROTOCOL *This,
111 IN EFI_HANDLE DeviceHandle,
112 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
113 )
114 {
115 NON_DISCOVERABLE_PCI_DEVICE *Dev;
116 EFI_STATUS Status;
117
118 Dev = AllocateZeroPool (sizeof *Dev);
119 if (Dev == NULL) {
120 return EFI_OUT_OF_RESOURCES;
121 }
122
123 Status = gBS->OpenProtocol (DeviceHandle,
124 &gEdkiiNonDiscoverableDeviceProtocolGuid,
125 (VOID **)&Dev->Device, This->DriverBindingHandle,
126 DeviceHandle, EFI_OPEN_PROTOCOL_BY_DRIVER);
127 if (EFI_ERROR (Status)) {
128 goto FreeDev;
129 }
130
131 InitializePciIoProtocol (Dev);
132
133 //
134 // Setup complete, attempt to export the driver instance's
135 // EFI_PCI_IO_PROTOCOL interface.
136 //
137 Dev->Signature = NON_DISCOVERABLE_PCI_DEVICE_SIG;
138 Status = gBS->InstallProtocolInterface (&DeviceHandle, &gEfiPciIoProtocolGuid,
139 EFI_NATIVE_INTERFACE, &Dev->PciIo);
140 if (EFI_ERROR (Status)) {
141 goto CloseProtocol;
142 }
143
144 return EFI_SUCCESS;
145
146 CloseProtocol:
147 gBS->CloseProtocol (DeviceHandle, &gEdkiiNonDiscoverableDeviceProtocolGuid,
148 This->DriverBindingHandle, DeviceHandle);
149
150 FreeDev:
151 FreePool (Dev);
152
153 return Status;
154 }
155
156
157 STATIC
158 EFI_STATUS
159 EFIAPI
160 NonDiscoverablePciDeviceStop (
161 IN EFI_DRIVER_BINDING_PROTOCOL *This,
162 IN EFI_HANDLE DeviceHandle,
163 IN UINTN NumberOfChildren,
164 IN EFI_HANDLE *ChildHandleBuffer
165 )
166 {
167 EFI_STATUS Status;
168 EFI_PCI_IO_PROTOCOL *PciIo;
169 NON_DISCOVERABLE_PCI_DEVICE *Dev;
170
171 Status = gBS->OpenProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,
172 (VOID **)&PciIo, This->DriverBindingHandle, DeviceHandle,
173 EFI_OPEN_PROTOCOL_GET_PROTOCOL);
174 if (EFI_ERROR (Status)) {
175 return Status;
176 }
177
178 Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO (PciIo);
179
180 //
181 // Handle Stop() requests for in-use driver instances gracefully.
182 //
183 Status = gBS->UninstallProtocolInterface (DeviceHandle,
184 &gEfiPciIoProtocolGuid, &Dev->PciIo);
185 if (EFI_ERROR (Status)) {
186 return Status;
187 }
188
189 gBS->CloseProtocol (DeviceHandle, &gEdkiiNonDiscoverableDeviceProtocolGuid,
190 This->DriverBindingHandle, DeviceHandle);
191
192 FreePool (Dev);
193
194 return EFI_SUCCESS;
195 }
196
197
198 //
199 // The static object that groups the Supported() (ie. probe), Start() and
200 // Stop() functions of the driver together. Refer to UEFI Spec 2.3.1 + Errata
201 // C, 10.1 EFI Driver Binding Protocol.
202 //
203 STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = {
204 &NonDiscoverablePciDeviceSupported,
205 &NonDiscoverablePciDeviceStart,
206 &NonDiscoverablePciDeviceStop,
207 0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed drivers
208 NULL,
209 NULL
210 };
211
212 //
213 // Entry point of this driver.
214 //
215 EFI_STATUS
216 EFIAPI
217 NonDiscoverablePciDeviceDxeEntryPoint (
218 IN EFI_HANDLE ImageHandle,
219 IN EFI_SYSTEM_TABLE *SystemTable
220 )
221 {
222 EFI_STATUS Status;
223
224 Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&mCpu);
225 ASSERT_EFI_ERROR(Status);
226
227 return EfiLibInstallDriverBindingComponentName2 (
228 ImageHandle,
229 SystemTable,
230 &gDriverBinding,
231 ImageHandle,
232 &gComponentName,
233 &gComponentName2
234 );
235 }