]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/MptScsiDxe/MptScsi.c
OvmfPkg/MptScsiDxe: Report targets and one LUN
[mirror_edk2.git] / OvmfPkg / MptScsiDxe / MptScsi.c
1 /** @file
2
3 This driver produces Extended SCSI Pass Thru Protocol instances for
4 LSI Fusion MPT SCSI devices.
5
6 Copyright (C) 2020, Oracle and/or its affiliates.
7
8 SPDX-License-Identifier: BSD-2-Clause-Patent
9
10 **/
11
12 #include <IndustryStandard/FusionMptScsi.h>
13 #include <IndustryStandard/Pci.h>
14 #include <Library/BaseMemoryLib.h>
15 #include <Library/DebugLib.h>
16 #include <Library/MemoryAllocationLib.h>
17 #include <Library/PcdLib.h>
18 #include <Library/UefiBootServicesTableLib.h>
19 #include <Library/UefiLib.h>
20 #include <Protocol/PciIo.h>
21 #include <Protocol/ScsiPassThruExt.h>
22 #include <Uefi/UefiSpec.h>
23
24 //
25 // Higher versions will be used before lower, 0x10-0xffffffef is the version
26 // range for IVH (Indie Hardware Vendors)
27 //
28 #define MPT_SCSI_BINDING_VERSION 0x10
29
30 //
31 // Runtime Structures
32 //
33
34 #define MPT_SCSI_DEV_SIGNATURE SIGNATURE_32 ('M','P','T','S')
35 typedef struct {
36 UINT32 Signature;
37 EFI_EXT_SCSI_PASS_THRU_PROTOCOL PassThru;
38 EFI_EXT_SCSI_PASS_THRU_MODE PassThruMode;
39 UINT8 MaxTarget;
40 } MPT_SCSI_DEV;
41
42 #define MPT_SCSI_FROM_PASS_THRU(PassThruPtr) \
43 CR (PassThruPtr, MPT_SCSI_DEV, PassThru, MPT_SCSI_DEV_SIGNATURE)
44
45 //
46 // Ext SCSI Pass Thru
47 //
48
49 STATIC
50 EFI_STATUS
51 EFIAPI
52 MptScsiPassThru (
53 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
54 IN UINT8 *Target,
55 IN UINT64 Lun,
56 IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet,
57 IN EFI_EVENT Event OPTIONAL
58 )
59 {
60 return EFI_UNSUPPORTED;
61 }
62
63 STATIC
64 BOOLEAN
65 IsTargetInitialized (
66 IN UINT8 *Target
67 )
68 {
69 UINTN Idx;
70
71 for (Idx = 0; Idx < TARGET_MAX_BYTES; ++Idx) {
72 if (Target[Idx] != 0xFF) {
73 return TRUE;
74 }
75 }
76 return FALSE;
77 }
78
79 STATIC
80 EFI_STATUS
81 EFIAPI
82 MptScsiGetNextTargetLun (
83 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
84 IN OUT UINT8 **Target,
85 IN OUT UINT64 *Lun
86 )
87 {
88 MPT_SCSI_DEV *Dev;
89
90 Dev = MPT_SCSI_FROM_PASS_THRU (This);
91 //
92 // Currently support only LUN 0, so hardcode it
93 //
94 if (!IsTargetInitialized (*Target)) {
95 ZeroMem (*Target, TARGET_MAX_BYTES);
96 *Lun = 0;
97 } else if (**Target > Dev->MaxTarget || *Lun > 0) {
98 return EFI_INVALID_PARAMETER;
99 } else if (**Target < Dev->MaxTarget) {
100 //
101 // This device interface support 256 targets only, so it's enough to
102 // increment the LSB of Target, as it will never overflow.
103 //
104 **Target += 1;
105 } else {
106 return EFI_NOT_FOUND;
107 }
108
109 return EFI_SUCCESS;
110 }
111
112 STATIC
113 EFI_STATUS
114 EFIAPI
115 MptScsiGetNextTarget (
116 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
117 IN OUT UINT8 **Target
118 )
119 {
120 MPT_SCSI_DEV *Dev;
121
122 Dev = MPT_SCSI_FROM_PASS_THRU (This);
123 if (!IsTargetInitialized (*Target)) {
124 ZeroMem (*Target, TARGET_MAX_BYTES);
125 } else if (**Target > Dev->MaxTarget) {
126 return EFI_INVALID_PARAMETER;
127 } else if (**Target < Dev->MaxTarget) {
128 //
129 // This device interface support 256 targets only, so it's enough to
130 // increment the LSB of Target, as it will never overflow.
131 //
132 **Target += 1;
133 } else {
134 return EFI_NOT_FOUND;
135 }
136
137 return EFI_SUCCESS;
138 }
139
140 STATIC
141 EFI_STATUS
142 EFIAPI
143 MptScsiBuildDevicePath (
144 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
145 IN UINT8 *Target,
146 IN UINT64 Lun,
147 IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
148 )
149 {
150 return EFI_UNSUPPORTED;
151 }
152
153 STATIC
154 EFI_STATUS
155 EFIAPI
156 MptScsiGetTargetLun (
157 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
158 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
159 OUT UINT8 **Target,
160 OUT UINT64 *Lun
161 )
162 {
163 return EFI_UNSUPPORTED;
164 }
165
166 STATIC
167 EFI_STATUS
168 EFIAPI
169 MptScsiResetChannel (
170 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This
171 )
172 {
173 return EFI_UNSUPPORTED;
174 }
175
176 STATIC
177 EFI_STATUS
178 EFIAPI
179 MptScsiResetTargetLun (
180 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
181 IN UINT8 *Target,
182 IN UINT64 Lun
183 )
184 {
185 return EFI_UNSUPPORTED;
186 }
187
188 //
189 // Driver Binding
190 //
191
192 STATIC
193 EFI_STATUS
194 EFIAPI
195 MptScsiControllerSupported (
196 IN EFI_DRIVER_BINDING_PROTOCOL *This,
197 IN EFI_HANDLE ControllerHandle,
198 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
199 )
200 {
201 EFI_STATUS Status;
202 EFI_PCI_IO_PROTOCOL *PciIo;
203 PCI_TYPE00 Pci;
204
205 Status = gBS->OpenProtocol (
206 ControllerHandle,
207 &gEfiPciIoProtocolGuid,
208 (VOID **)&PciIo,
209 This->DriverBindingHandle,
210 ControllerHandle,
211 EFI_OPEN_PROTOCOL_BY_DRIVER
212 );
213 if (EFI_ERROR (Status)) {
214 return Status;
215 }
216
217 Status = PciIo->Pci.Read (
218 PciIo,
219 EfiPciIoWidthUint32,
220 0,
221 sizeof (Pci) / sizeof (UINT32),
222 &Pci
223 );
224 if (EFI_ERROR (Status)) {
225 goto Done;
226 }
227
228 if (Pci.Hdr.VendorId == LSI_LOGIC_PCI_VENDOR_ID &&
229 (Pci.Hdr.DeviceId == LSI_53C1030_PCI_DEVICE_ID ||
230 Pci.Hdr.DeviceId == LSI_SAS1068_PCI_DEVICE_ID ||
231 Pci.Hdr.DeviceId == LSI_SAS1068E_PCI_DEVICE_ID)) {
232 Status = EFI_SUCCESS;
233 } else {
234 Status = EFI_UNSUPPORTED;
235 }
236
237 Done:
238 gBS->CloseProtocol (
239 ControllerHandle,
240 &gEfiPciIoProtocolGuid,
241 This->DriverBindingHandle,
242 ControllerHandle
243 );
244 return Status;
245 }
246
247 STATIC
248 EFI_STATUS
249 EFIAPI
250 MptScsiControllerStart (
251 IN EFI_DRIVER_BINDING_PROTOCOL *This,
252 IN EFI_HANDLE ControllerHandle,
253 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
254 )
255 {
256 EFI_STATUS Status;
257 MPT_SCSI_DEV *Dev;
258
259 Dev = AllocateZeroPool (sizeof (*Dev));
260 if (Dev == NULL) {
261 return EFI_OUT_OF_RESOURCES;
262 }
263
264 Dev->Signature = MPT_SCSI_DEV_SIGNATURE;
265
266 Dev->MaxTarget = PcdGet8 (PcdMptScsiMaxTargetLimit);
267
268 //
269 // Host adapter channel, doesn't exist
270 //
271 Dev->PassThruMode.AdapterId = MAX_UINT32;
272 Dev->PassThruMode.Attributes =
273 EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL |
274 EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL;
275
276 Dev->PassThru.Mode = &Dev->PassThruMode;
277 Dev->PassThru.PassThru = &MptScsiPassThru;
278 Dev->PassThru.GetNextTargetLun = &MptScsiGetNextTargetLun;
279 Dev->PassThru.BuildDevicePath = &MptScsiBuildDevicePath;
280 Dev->PassThru.GetTargetLun = &MptScsiGetTargetLun;
281 Dev->PassThru.ResetChannel = &MptScsiResetChannel;
282 Dev->PassThru.ResetTargetLun = &MptScsiResetTargetLun;
283 Dev->PassThru.GetNextTarget = &MptScsiGetNextTarget;
284
285 Status = gBS->InstallProtocolInterface (
286 &ControllerHandle,
287 &gEfiExtScsiPassThruProtocolGuid,
288 EFI_NATIVE_INTERFACE,
289 &Dev->PassThru
290 );
291 if (EFI_ERROR (Status)) {
292 goto FreePool;
293 }
294
295 return EFI_SUCCESS;
296
297 FreePool:
298 FreePool (Dev);
299
300 return Status;
301 }
302
303 STATIC
304 EFI_STATUS
305 EFIAPI
306 MptScsiControllerStop (
307 IN EFI_DRIVER_BINDING_PROTOCOL *This,
308 IN EFI_HANDLE ControllerHandle,
309 IN UINTN NumberOfChildren,
310 IN EFI_HANDLE *ChildHandleBuffer
311 )
312 {
313 EFI_STATUS Status;
314 EFI_EXT_SCSI_PASS_THRU_PROTOCOL *PassThru;
315 MPT_SCSI_DEV *Dev;
316
317 Status = gBS->OpenProtocol (
318 ControllerHandle,
319 &gEfiExtScsiPassThruProtocolGuid,
320 (VOID **)&PassThru,
321 This->DriverBindingHandle,
322 ControllerHandle,
323 EFI_OPEN_PROTOCOL_GET_PROTOCOL // Lookup only
324 );
325 if (EFI_ERROR (Status)) {
326 return Status;
327 }
328
329 Dev = MPT_SCSI_FROM_PASS_THRU (PassThru);
330
331 Status = gBS->UninstallProtocolInterface (
332 ControllerHandle,
333 &gEfiExtScsiPassThruProtocolGuid,
334 &Dev->PassThru
335 );
336 if (EFI_ERROR (Status)) {
337 return Status;
338 }
339
340 FreePool (Dev);
341
342 return Status;
343 }
344
345 STATIC
346 EFI_DRIVER_BINDING_PROTOCOL mMptScsiDriverBinding = {
347 &MptScsiControllerSupported,
348 &MptScsiControllerStart,
349 &MptScsiControllerStop,
350 MPT_SCSI_BINDING_VERSION,
351 NULL, // ImageHandle, filled by EfiLibInstallDriverBindingComponentName2
352 NULL, // DriverBindingHandle, filled as well
353 };
354
355 //
356 // Component Name
357 //
358
359 STATIC
360 EFI_UNICODE_STRING_TABLE mDriverNameTable[] = {
361 { "eng;en", L"LSI Fusion MPT SCSI Driver" },
362 { NULL, NULL }
363 };
364
365 STATIC
366 EFI_COMPONENT_NAME_PROTOCOL mComponentName;
367
368 EFI_STATUS
369 EFIAPI
370 MptScsiGetDriverName (
371 IN EFI_COMPONENT_NAME_PROTOCOL *This,
372 IN CHAR8 *Language,
373 OUT CHAR16 **DriverName
374 )
375 {
376 return LookupUnicodeString2 (
377 Language,
378 This->SupportedLanguages,
379 mDriverNameTable,
380 DriverName,
381 (BOOLEAN)(This == &mComponentName) // Iso639Language
382 );
383 }
384
385 EFI_STATUS
386 EFIAPI
387 MptScsiGetDeviceName (
388 IN EFI_COMPONENT_NAME_PROTOCOL *This,
389 IN EFI_HANDLE DeviceHandle,
390 IN EFI_HANDLE ChildHandle,
391 IN CHAR8 *Language,
392 OUT CHAR16 **ControllerName
393 )
394 {
395 return EFI_UNSUPPORTED;
396 }
397
398 STATIC
399 EFI_COMPONENT_NAME_PROTOCOL mComponentName = {
400 &MptScsiGetDriverName,
401 &MptScsiGetDeviceName,
402 "eng" // SupportedLanguages, ISO 639-2 language codes
403 };
404
405 STATIC
406 EFI_COMPONENT_NAME2_PROTOCOL mComponentName2 = {
407 (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) &MptScsiGetDriverName,
408 (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) &MptScsiGetDeviceName,
409 "en" // SupportedLanguages, RFC 4646 language codes
410 };
411
412 //
413 // Entry Point
414 //
415
416 EFI_STATUS
417 EFIAPI
418 MptScsiEntryPoint (
419 IN EFI_HANDLE ImageHandle,
420 IN EFI_SYSTEM_TABLE *SystemTable
421 )
422 {
423 return EfiLibInstallDriverBindingComponentName2 (
424 ImageHandle,
425 SystemTable,
426 &mMptScsiDriverBinding,
427 ImageHandle, // The handle to install onto
428 &mComponentName,
429 &mComponentName2
430 );
431 }