3 This driver produces Extended SCSI Pass Thru Protocol instances for
4 LSI Fusion MPT SCSI devices.
6 Copyright (C) 2020, Oracle and/or its affiliates.
8 SPDX-License-Identifier: BSD-2-Clause-Patent
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>
25 // Higher versions will be used before lower, 0x10-0xffffffef is the version
26 // range for IVH (Indie Hardware Vendors)
28 #define MPT_SCSI_BINDING_VERSION 0x10
34 #define MPT_SCSI_DEV_SIGNATURE SIGNATURE_32 ('M','P','T','S')
37 EFI_EXT_SCSI_PASS_THRU_PROTOCOL PassThru
;
38 EFI_EXT_SCSI_PASS_THRU_MODE PassThruMode
;
42 #define MPT_SCSI_FROM_PASS_THRU(PassThruPtr) \
43 CR (PassThruPtr, MPT_SCSI_DEV, PassThru, MPT_SCSI_DEV_SIGNATURE)
53 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL
*This
,
56 IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET
*Packet
,
57 IN EFI_EVENT Event OPTIONAL
60 return EFI_UNSUPPORTED
;
71 for (Idx
= 0; Idx
< TARGET_MAX_BYTES
; ++Idx
) {
72 if (Target
[Idx
] != 0xFF) {
82 MptScsiGetNextTargetLun (
83 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL
*This
,
84 IN OUT UINT8
**Target
,
90 Dev
= MPT_SCSI_FROM_PASS_THRU (This
);
92 // Currently support only LUN 0, so hardcode it
94 if (!IsTargetInitialized (*Target
)) {
95 ZeroMem (*Target
, TARGET_MAX_BYTES
);
97 } else if (**Target
> Dev
->MaxTarget
|| *Lun
> 0) {
98 return EFI_INVALID_PARAMETER
;
99 } else if (**Target
< Dev
->MaxTarget
) {
101 // This device interface support 256 targets only, so it's enough to
102 // increment the LSB of Target, as it will never overflow.
106 return EFI_NOT_FOUND
;
115 MptScsiGetNextTarget (
116 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL
*This
,
117 IN OUT UINT8
**Target
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
) {
129 // This device interface support 256 targets only, so it's enough to
130 // increment the LSB of Target, as it will never overflow.
134 return EFI_NOT_FOUND
;
143 MptScsiBuildDevicePath (
144 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL
*This
,
147 IN OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePath
151 SCSI_DEVICE_PATH
*ScsiDevicePath
;
153 if (DevicePath
== NULL
) {
154 return EFI_INVALID_PARAMETER
;
158 // This device support 256 targets only, so it's enough to dereference
159 // the LSB of Target.
161 Dev
= MPT_SCSI_FROM_PASS_THRU (This
);
162 if (*Target
> Dev
->MaxTarget
|| Lun
> 0) {
163 return EFI_NOT_FOUND
;
166 ScsiDevicePath
= AllocateZeroPool (sizeof (*ScsiDevicePath
));
167 if (ScsiDevicePath
== NULL
) {
168 return EFI_OUT_OF_RESOURCES
;
171 ScsiDevicePath
->Header
.Type
= MESSAGING_DEVICE_PATH
;
172 ScsiDevicePath
->Header
.SubType
= MSG_SCSI_DP
;
173 ScsiDevicePath
->Header
.Length
[0] = (UINT8
)sizeof (*ScsiDevicePath
);
174 ScsiDevicePath
->Header
.Length
[1] = (UINT8
)(sizeof (*ScsiDevicePath
) >> 8);
175 ScsiDevicePath
->Pun
= *Target
;
176 ScsiDevicePath
->Lun
= (UINT16
)Lun
;
178 *DevicePath
= &ScsiDevicePath
->Header
;
185 MptScsiGetTargetLun (
186 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL
*This
,
187 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
193 SCSI_DEVICE_PATH
*ScsiDevicePath
;
195 if (DevicePath
== NULL
||
196 Target
== NULL
|| *Target
== NULL
|| Lun
== NULL
) {
197 return EFI_INVALID_PARAMETER
;
200 if (DevicePath
->Type
!= MESSAGING_DEVICE_PATH
||
201 DevicePath
->SubType
!= MSG_SCSI_DP
) {
202 return EFI_UNSUPPORTED
;
205 Dev
= MPT_SCSI_FROM_PASS_THRU (This
);
206 ScsiDevicePath
= (SCSI_DEVICE_PATH
*)DevicePath
;
207 if (ScsiDevicePath
->Pun
> Dev
->MaxTarget
||
208 ScsiDevicePath
->Lun
> 0) {
209 return EFI_NOT_FOUND
;
212 ZeroMem (*Target
, TARGET_MAX_BYTES
);
214 // This device support 256 targets only, so it's enough to set the LSB
217 **Target
= (UINT8
)ScsiDevicePath
->Pun
;
218 *Lun
= ScsiDevicePath
->Lun
;
226 MptScsiResetChannel (
227 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL
*This
230 return EFI_UNSUPPORTED
;
236 MptScsiResetTargetLun (
237 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL
*This
,
242 return EFI_UNSUPPORTED
;
252 MptScsiControllerSupported (
253 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
254 IN EFI_HANDLE ControllerHandle
,
255 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
259 EFI_PCI_IO_PROTOCOL
*PciIo
;
262 Status
= gBS
->OpenProtocol (
264 &gEfiPciIoProtocolGuid
,
266 This
->DriverBindingHandle
,
268 EFI_OPEN_PROTOCOL_BY_DRIVER
270 if (EFI_ERROR (Status
)) {
274 Status
= PciIo
->Pci
.Read (
278 sizeof (Pci
) / sizeof (UINT32
),
281 if (EFI_ERROR (Status
)) {
285 if (Pci
.Hdr
.VendorId
== LSI_LOGIC_PCI_VENDOR_ID
&&
286 (Pci
.Hdr
.DeviceId
== LSI_53C1030_PCI_DEVICE_ID
||
287 Pci
.Hdr
.DeviceId
== LSI_SAS1068_PCI_DEVICE_ID
||
288 Pci
.Hdr
.DeviceId
== LSI_SAS1068E_PCI_DEVICE_ID
)) {
289 Status
= EFI_SUCCESS
;
291 Status
= EFI_UNSUPPORTED
;
297 &gEfiPciIoProtocolGuid
,
298 This
->DriverBindingHandle
,
307 MptScsiControllerStart (
308 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
309 IN EFI_HANDLE ControllerHandle
,
310 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
316 Dev
= AllocateZeroPool (sizeof (*Dev
));
318 return EFI_OUT_OF_RESOURCES
;
321 Dev
->Signature
= MPT_SCSI_DEV_SIGNATURE
;
323 Dev
->MaxTarget
= PcdGet8 (PcdMptScsiMaxTargetLimit
);
326 // Host adapter channel, doesn't exist
328 Dev
->PassThruMode
.AdapterId
= MAX_UINT32
;
329 Dev
->PassThruMode
.Attributes
=
330 EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL
|
331 EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL
;
333 Dev
->PassThru
.Mode
= &Dev
->PassThruMode
;
334 Dev
->PassThru
.PassThru
= &MptScsiPassThru
;
335 Dev
->PassThru
.GetNextTargetLun
= &MptScsiGetNextTargetLun
;
336 Dev
->PassThru
.BuildDevicePath
= &MptScsiBuildDevicePath
;
337 Dev
->PassThru
.GetTargetLun
= &MptScsiGetTargetLun
;
338 Dev
->PassThru
.ResetChannel
= &MptScsiResetChannel
;
339 Dev
->PassThru
.ResetTargetLun
= &MptScsiResetTargetLun
;
340 Dev
->PassThru
.GetNextTarget
= &MptScsiGetNextTarget
;
342 Status
= gBS
->InstallProtocolInterface (
344 &gEfiExtScsiPassThruProtocolGuid
,
345 EFI_NATIVE_INTERFACE
,
348 if (EFI_ERROR (Status
)) {
363 MptScsiControllerStop (
364 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
365 IN EFI_HANDLE ControllerHandle
,
366 IN UINTN NumberOfChildren
,
367 IN EFI_HANDLE
*ChildHandleBuffer
371 EFI_EXT_SCSI_PASS_THRU_PROTOCOL
*PassThru
;
374 Status
= gBS
->OpenProtocol (
376 &gEfiExtScsiPassThruProtocolGuid
,
378 This
->DriverBindingHandle
,
380 EFI_OPEN_PROTOCOL_GET_PROTOCOL
// Lookup only
382 if (EFI_ERROR (Status
)) {
386 Dev
= MPT_SCSI_FROM_PASS_THRU (PassThru
);
388 Status
= gBS
->UninstallProtocolInterface (
390 &gEfiExtScsiPassThruProtocolGuid
,
393 if (EFI_ERROR (Status
)) {
403 EFI_DRIVER_BINDING_PROTOCOL mMptScsiDriverBinding
= {
404 &MptScsiControllerSupported
,
405 &MptScsiControllerStart
,
406 &MptScsiControllerStop
,
407 MPT_SCSI_BINDING_VERSION
,
408 NULL
, // ImageHandle, filled by EfiLibInstallDriverBindingComponentName2
409 NULL
, // DriverBindingHandle, filled as well
417 EFI_UNICODE_STRING_TABLE mDriverNameTable
[] = {
418 { "eng;en", L
"LSI Fusion MPT SCSI Driver" },
423 EFI_COMPONENT_NAME_PROTOCOL mComponentName
;
427 MptScsiGetDriverName (
428 IN EFI_COMPONENT_NAME_PROTOCOL
*This
,
430 OUT CHAR16
**DriverName
433 return LookupUnicodeString2 (
435 This
->SupportedLanguages
,
438 (BOOLEAN
)(This
== &mComponentName
) // Iso639Language
444 MptScsiGetDeviceName (
445 IN EFI_COMPONENT_NAME_PROTOCOL
*This
,
446 IN EFI_HANDLE DeviceHandle
,
447 IN EFI_HANDLE ChildHandle
,
449 OUT CHAR16
**ControllerName
452 return EFI_UNSUPPORTED
;
456 EFI_COMPONENT_NAME_PROTOCOL mComponentName
= {
457 &MptScsiGetDriverName
,
458 &MptScsiGetDeviceName
,
459 "eng" // SupportedLanguages, ISO 639-2 language codes
463 EFI_COMPONENT_NAME2_PROTOCOL mComponentName2
= {
464 (EFI_COMPONENT_NAME2_GET_DRIVER_NAME
) &MptScsiGetDriverName
,
465 (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME
) &MptScsiGetDeviceName
,
466 "en" // SupportedLanguages, RFC 4646 language codes
476 IN EFI_HANDLE ImageHandle
,
477 IN EFI_SYSTEM_TABLE
*SystemTable
480 return EfiLibInstallDriverBindingComponentName2 (
483 &mMptScsiDriverBinding
,
484 ImageHandle
, // The handle to install onto