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