3 This driver produces Extended SCSI Pass Thru Protocol instances for
4 LSI 53C895A SCSI devices.
6 Copyright (C) 2020, SUSE LLC.
8 SPDX-License-Identifier: BSD-2-Clause-Patent
12 #include <IndustryStandard/LsiScsi.h>
13 #include <IndustryStandard/Pci.h>
14 #include <Library/BaseLib.h>
15 #include <Library/BaseMemoryLib.h>
16 #include <Library/DebugLib.h>
17 #include <Library/MemoryAllocationLib.h>
18 #include <Library/UefiBootServicesTableLib.h>
19 #include <Library/UefiLib.h>
20 #include <Protocol/PciIo.h>
21 #include <Protocol/PciRootBridgeIo.h>
22 #include <Protocol/ScsiPassThruExt.h>
23 #include <Uefi/UefiSpec.h>
28 // The next seven functions implement EFI_EXT_SCSI_PASS_THRU_PROTOCOL
29 // for the LSI 53C895A SCSI Controller. Refer to UEFI Spec 2.3.1 + Errata C,
31 // - 14.1 SCSI Driver Model Overview,
32 // - 14.7 Extended SCSI Pass Thru Protocol.
38 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL
*This
,
41 IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET
*Packet
,
42 IN EFI_EVENT Event OPTIONAL
45 return EFI_UNSUPPORTED
;
50 LsiScsiGetNextTargetLun (
51 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL
*This
,
52 IN OUT UINT8
**TargetPointer
,
61 LsiScsiBuildDevicePath (
62 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL
*This
,
65 IN OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePath
74 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL
*This
,
75 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
76 OUT UINT8
**TargetPointer
,
80 return EFI_UNSUPPORTED
;
86 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL
*This
89 return EFI_UNSUPPORTED
;
94 LsiScsiResetTargetLun (
95 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL
*This
,
100 return EFI_UNSUPPORTED
;
105 LsiScsiGetNextTarget (
106 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL
*This
,
107 IN OUT UINT8
**TargetPointer
110 return EFI_NOT_FOUND
;
114 // Probe, start and stop functions of this driver, called by the DXE core for
117 // The following specifications document these interfaces:
118 // - Driver Writer's Guide for UEFI 2.3.1 v1.01, 9 Driver Binding Protocol
119 // - UEFI Spec 2.3.1 + Errata C, 10.1 EFI Driver Binding Protocol
124 LsiScsiControllerSupported (
125 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
126 IN EFI_HANDLE ControllerHandle
,
127 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
131 EFI_PCI_IO_PROTOCOL
*PciIo
;
134 Status
= gBS
->OpenProtocol (
136 &gEfiPciIoProtocolGuid
,
138 This
->DriverBindingHandle
,
140 EFI_OPEN_PROTOCOL_BY_DRIVER
142 if (EFI_ERROR (Status
)) {
146 Status
= PciIo
->Pci
.Read (
150 sizeof (Pci
) / sizeof (UINT32
),
153 if (EFI_ERROR (Status
)) {
157 if (Pci
.Hdr
.VendorId
== LSI_LOGIC_PCI_VENDOR_ID
&&
158 Pci
.Hdr
.DeviceId
== LSI_53C895A_PCI_DEVICE_ID
) {
159 Status
= EFI_SUCCESS
;
161 Status
= EFI_UNSUPPORTED
;
167 &gEfiPciIoProtocolGuid
,
168 This
->DriverBindingHandle
,
176 LsiScsiControllerStart (
177 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
178 IN EFI_HANDLE ControllerHandle
,
179 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
185 Dev
= AllocateZeroPool (sizeof (*Dev
));
187 return EFI_OUT_OF_RESOURCES
;
190 Dev
->Signature
= LSI_SCSI_DEV_SIGNATURE
;
193 // Host adapter channel, doesn't exist
195 Dev
->PassThruMode
.AdapterId
= MAX_UINT32
;
196 Dev
->PassThruMode
.Attributes
=
197 EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL
|
198 EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL
;
200 Dev
->PassThru
.Mode
= &Dev
->PassThruMode
;
201 Dev
->PassThru
.PassThru
= &LsiScsiPassThru
;
202 Dev
->PassThru
.GetNextTargetLun
= &LsiScsiGetNextTargetLun
;
203 Dev
->PassThru
.BuildDevicePath
= &LsiScsiBuildDevicePath
;
204 Dev
->PassThru
.GetTargetLun
= &LsiScsiGetTargetLun
;
205 Dev
->PassThru
.ResetChannel
= &LsiScsiResetChannel
;
206 Dev
->PassThru
.ResetTargetLun
= &LsiScsiResetTargetLun
;
207 Dev
->PassThru
.GetNextTarget
= &LsiScsiGetNextTarget
;
209 Status
= gBS
->InstallProtocolInterface (
211 &gEfiExtScsiPassThruProtocolGuid
,
212 EFI_NATIVE_INTERFACE
,
215 if (EFI_ERROR (Status
)) {
229 LsiScsiControllerStop (
230 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
231 IN EFI_HANDLE ControllerHandle
,
232 IN UINTN NumberOfChildren
,
233 IN EFI_HANDLE
*ChildHandleBuffer
237 EFI_EXT_SCSI_PASS_THRU_PROTOCOL
*PassThru
;
240 Status
= gBS
->OpenProtocol (
242 &gEfiExtScsiPassThruProtocolGuid
,
244 This
->DriverBindingHandle
,
246 EFI_OPEN_PROTOCOL_GET_PROTOCOL
// Lookup only
248 if (EFI_ERROR (Status
)) {
252 Dev
= LSI_SCSI_FROM_PASS_THRU (PassThru
);
254 Status
= gBS
->UninstallProtocolInterface (
256 &gEfiExtScsiPassThruProtocolGuid
,
259 if (EFI_ERROR (Status
)) {
269 // The static object that groups the Supported() (ie. probe), Start() and
270 // Stop() functions of the driver together. Refer to UEFI Spec 2.3.1 + Errata
271 // C, 10.1 EFI Driver Binding Protocol.
274 EFI_DRIVER_BINDING_PROTOCOL gDriverBinding
= {
275 &LsiScsiControllerSupported
,
276 &LsiScsiControllerStart
,
277 &LsiScsiControllerStop
,
278 0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed drivers
279 NULL
, // ImageHandle, to be overwritten by
280 // EfiLibInstallDriverBindingComponentName2() in LsiScsiEntryPoint()
281 NULL
// DriverBindingHandle, ditto
286 // The purpose of the following scaffolding (EFI_COMPONENT_NAME_PROTOCOL and
287 // EFI_COMPONENT_NAME2_PROTOCOL implementation) is to format the driver's name
288 // in English, for display on standard console devices. This is recommended for
289 // UEFI drivers that follow the UEFI Driver Model. Refer to the Driver Writer's
290 // Guide for UEFI 2.3.1 v1.01, 11 UEFI Driver and Controller Names.
292 // Device type names ("LSI 53C895A SCSI Controller") are not formatted because
293 // the driver supports only that device type. Therefore the driver name
294 // suffices for unambiguous identification.
298 EFI_UNICODE_STRING_TABLE mDriverNameTable
[] = {
299 { "eng;en", L
"LSI 53C895A SCSI Controller Driver" },
304 EFI_COMPONENT_NAME_PROTOCOL gComponentName
;
308 LsiScsiGetDriverName (
309 IN EFI_COMPONENT_NAME_PROTOCOL
*This
,
311 OUT CHAR16
**DriverName
314 return LookupUnicodeString2 (
316 This
->SupportedLanguages
,
319 (BOOLEAN
)(This
== &gComponentName
) // Iso639Language
325 LsiScsiGetDeviceName (
326 IN EFI_COMPONENT_NAME_PROTOCOL
*This
,
327 IN EFI_HANDLE DeviceHandle
,
328 IN EFI_HANDLE ChildHandle
,
330 OUT CHAR16
**ControllerName
333 return EFI_UNSUPPORTED
;
337 EFI_COMPONENT_NAME_PROTOCOL gComponentName
= {
338 &LsiScsiGetDriverName
,
339 &LsiScsiGetDeviceName
,
340 "eng" // SupportedLanguages, ISO 639-2 language codes
344 EFI_COMPONENT_NAME2_PROTOCOL gComponentName2
= {
345 (EFI_COMPONENT_NAME2_GET_DRIVER_NAME
) &LsiScsiGetDriverName
,
346 (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME
) &LsiScsiGetDeviceName
,
347 "en" // SupportedLanguages, RFC 4646 language codes
351 // Entry point of this driver
356 IN EFI_HANDLE ImageHandle
,
357 IN EFI_SYSTEM_TABLE
*SystemTable
360 return EfiLibInstallDriverBindingComponentName2 (
364 ImageHandle
, // The handle to install onto