30#define MPT_SCSI_BINDING_VERSION 0x10
44 UINT8 Sense[MAX_UINT8];
53#define MPT_SCSI_DEV_SIGNATURE SIGNATURE_32 ('M','P','T','S')
59 UINT32 StallPerPollUsec;
61 UINT64 OriginalPciAttributes;
66 BOOLEAN IoReplyEnqueued;
69#define MPT_SCSI_FROM_PASS_THRU(PassThruPtr) \
70 CR (PassThruPtr, MPT_SCSI_DEV, PassThru, MPT_SCSI_DEV_SIGNATURE)
72#define MPT_SCSI_DMA_ADDR(Dev, MemberName) \
73 (Dev->DmaPhysical + OFFSET_OF (MPT_SCSI_DMA_BUFFER, MemberName))
75#define MPT_SCSI_DMA_ADDR_HIGH(Dev, MemberName) \
76 ((UINT32)RShiftU64 (MPT_SCSI_DMA_ADDR (Dev, MemberName), 32))
78#define MPT_SCSI_DMA_ADDR_LOW(Dev, MemberName) \
79 ((UINT32)MPT_SCSI_DMA_ADDR (Dev, MemberName))
93 return Dev->PciIo->Io.Write (
111 return Dev->PciIo->Io.Read (
125 IN UINT8 DoorbellFunc,
132 (((UINT32)DoorbellFunc) << 24) | (DoorbellArg << 16)
147 Status = MptDoorbell (Dev, MPT_DOORBELL_RESET, 0);
148 if (EFI_ERROR (Status)) {
155 Status = Out32 (Dev, MPT_REG_IMASK, MPT_IMASK_DOORBELL | MPT_IMASK_REPLY);
156 if (EFI_ERROR (Status)) {
163 Status = Out32 (Dev, MPT_REG_ISTATUS, 0);
164 if (EFI_ERROR (Status)) {
188 Req = &AlignedReq.Data;
190 Status = MptScsiReset (Dev);
191 if (EFI_ERROR (Status)) {
196 ZeroMem (&Reply,
sizeof (Reply));
197 Req->WhoInit = MPT_IOC_WHOINIT_ROM_BIOS;
198 Req->Function = MPT_MESSAGE_HDR_FUNCTION_IOC_INIT;
201 "Req supports 255 targets only (max target is 254)"
203 Req->MaxDevices = Dev->MaxTarget + 1;
205 Req->ReplyFrameSize =
sizeof Dev->Dma->IoReply.Data;
206 Req->HostMfaHighAddr = MPT_SCSI_DMA_ADDR_HIGH (Dev, IoRequest);
207 Req->SenseBufferHighAddr = MPT_SCSI_DMA_ADDR_HIGH (Dev, Sense);
213 sizeof (*Req) %
sizeof (UINT32) == 0,
214 "Req must be multiple of UINT32"
217 sizeof (*Req) /
sizeof (UINT32) <= MAX_UINT8,
218 "Req must fit in MAX_UINT8 Dwords"
220 Status = MptDoorbell (
222 MPT_DOORBELL_HANDSHAKE,
223 (UINT8)(
sizeof (*Req) /
sizeof (UINT32))
225 if (EFI_ERROR (Status)) {
229 Status = Dev->PciIo->Io.Write (
231 EfiPciIoWidthFifoUint32,
234 sizeof (*Req) /
sizeof (UINT32),
237 if (EFI_ERROR (Status)) {
250 sizeof (Reply) %
sizeof (UINT16) == 0,
251 "Reply must be multiple of UINT16"
253 ReplyBytes = (UINT8 *)&Reply;
254 while (ReplyBytes != (UINT8 *)(&Reply + 1)) {
255 Status = In32 (Dev, MPT_REG_DOORBELL, &ReplyWord);
256 if (EFI_ERROR (Status)) {
260 CopyMem (ReplyBytes, &ReplyWord,
sizeof (UINT16));
261 ReplyBytes +=
sizeof (UINT16);
267 Status = Out32 (Dev, MPT_REG_ISTATUS, 0);
268 if (EFI_ERROR (Status)) {
277ReportHostAdapterError (
281 DEBUG ((DEBUG_ERROR,
"%a: fatal error in scsi request\n", __func__));
282 Packet->InTransferLength = 0;
283 Packet->OutTransferLength = 0;
284 Packet->SenseDataLength = 0;
285 Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OTHER;
286 Packet->TargetStatus = EFI_EXT_SCSI_STATUS_TARGET_TASK_ABORTED;
287 return EFI_DEVICE_ERROR;
292ReportHostAdapterOverrunError (
296 Packet->SenseDataLength = 0;
297 Packet->HostAdapterStatus =
298 EFI_EXT_SCSI_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN;
299 Packet->TargetStatus = EFI_EXT_SCSI_STATUS_TARGET_GOOD;
300 return EFI_BAD_BUFFER_SIZE;
305MptScsiPopulateRequest (
314 Request = &Dev->Dma->IoRequest.Data;
316 if ((Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_BIDIRECTIONAL) ||
317 ((Packet->InTransferLength > 0) && (Packet->OutTransferLength > 0)) ||
318 (Packet->CdbLength > sizeof (Request->Header.Cdb)))
320 return EFI_UNSUPPORTED;
323 if ((Target > Dev->MaxTarget) || (Lun > 0) ||
324 (Packet->DataDirection > EFI_EXT_SCSI_DATA_DIRECTION_BIDIRECTIONAL) ||
329 ((Packet->InTransferLength > 0) &&
330 ((Packet->InDataBuffer ==
NULL) ||
331 (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_WRITE)
339 ((Packet->OutTransferLength > 0) &&
340 ((Packet->OutDataBuffer ==
NULL) ||
341 (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ)
346 return EFI_INVALID_PARAMETER;
349 if (Packet->InTransferLength > sizeof (Dev->Dma->Data)) {
350 Packet->InTransferLength =
sizeof (Dev->Dma->Data);
351 return ReportHostAdapterOverrunError (Packet);
354 if (Packet->OutTransferLength > sizeof (Dev->Dma->Data)) {
355 Packet->OutTransferLength =
sizeof (Dev->Dma->Data);
356 return ReportHostAdapterOverrunError (Packet);
359 ZeroMem (Request,
sizeof (*Request));
360 Request->Header.TargetId = Target;
364 Request->Header.Lun[1] = (UINT8)Lun;
365 Request->Header.Function = MPT_MESSAGE_HDR_FUNCTION_SCSI_IO_REQUEST;
366 Request->Header.MessageContext = 1;
368 Request->Header.CdbLength = Packet->CdbLength;
369 CopyMem (Request->Header.Cdb, Packet->Cdb, Packet->CdbLength);
374 ZeroMem (Dev->Dma->Sense, Packet->SenseDataLength);
375 Request->Header.SenseBufferLength = Packet->SenseDataLength;
376 Request->Header.SenseBufferLowAddress = MPT_SCSI_DMA_ADDR_LOW (Dev, Sense);
378 Request->Sg.EndOfList = 1;
379 Request->Sg.EndOfBuffer = 1;
380 Request->Sg.LastElement = 1;
381 Request->Sg.ElementType = MPT_SG_ENTRY_TYPE_SIMPLE;
382 Request->Sg.Is64BitAddress = 1;
383 Request->Sg.DataBufferAddress = MPT_SCSI_DMA_ADDR (Dev, Data);
389 sizeof (Dev->Dma->Data) < SIZE_16MB,
390 "MPT_SCSI_DMA_BUFFER.Data must be smaller than 16MB"
393 if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
394 Request->Header.DataLength = Packet->InTransferLength;
395 Request->Sg.Length = Packet->InTransferLength;
396 Request->Header.Control = MPT_SCSIIO_REQUEST_CONTROL_TXDIR_READ;
398 Request->Header.DataLength = Packet->OutTransferLength;
399 Request->Sg.Length = Packet->OutTransferLength;
400 Request->Header.Control = MPT_SCSIIO_REQUEST_CONTROL_TXDIR_WRITE;
402 CopyMem (Dev->Dma->Data, Packet->OutDataBuffer, Packet->OutTransferLength);
403 Request->Sg.BufferContainsData = 1;
406 if (Request->Header.DataLength == 0) {
407 Request->Header.Control = MPT_SCSIIO_REQUEST_CONTROL_TXDIR_NONE;
422 if (!Dev->IoReplyEnqueued) {
427 Status = Out32 (Dev, MPT_REG_REP_Q, MPT_SCSI_DMA_ADDR_LOW (Dev, IoReply));
428 if (EFI_ERROR (Status)) {
429 return EFI_DEVICE_ERROR;
432 Dev->IoReplyEnqueued =
TRUE;
435 Status = Out32 (Dev, MPT_REG_REQ_Q, MPT_SCSI_DMA_ADDR_LOW (Dev, IoRequest));
436 if (EFI_ERROR (Status)) {
437 return EFI_DEVICE_ERROR;
459 Status = In32 (Dev, MPT_REG_ISTATUS, &Istatus);
460 if (EFI_ERROR (Status)) {
467 if (Istatus & MPT_IMASK_REPLY) {
471 gBS->Stall (Dev->StallPerPollUsec);
474 Status = In32 (Dev, MPT_REG_REP_Q, Reply);
475 if (EFI_ERROR (Status)) {
484 Status = In32 (Dev, MPT_REG_REP_Q, &EmptyReply);
485 if (EFI_ERROR (Status) || (EmptyReply != MAX_UINT32)) {
486 return EFI_DEVICE_ERROR;
500 if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
501 CopyMem (Packet->InDataBuffer, Dev->Dma->Data, Packet->InTransferLength);
504 if (Reply == Dev->Dma->IoRequest.Data.Header.MessageContext) {
508 Packet->SenseDataLength = 0;
509 Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OK;
510 Packet->TargetStatus = EFI_EXT_SCSI_STATUS_TARGET_GOOD;
511 }
else if ((Reply & BIT31) != 0) {
512 DEBUG ((DEBUG_INFO,
"%a: Full reply returned\n", __func__));
517 Dev->IoReplyEnqueued =
FALSE;
519 Packet->TargetStatus = Dev->Dma->IoReply.Data.ScsiStatus;
523 ASSERT (Dev->Dma->IoReply.Data.SenseCount <= Packet->SenseDataLength);
524 Packet->SenseDataLength =
525 (UINT8)
MIN (Dev->Dma->IoReply.Data.SenseCount, Packet->SenseDataLength);
526 CopyMem (Packet->SenseData, Dev->Dma->Sense, Packet->SenseDataLength);
528 if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
529 Packet->InTransferLength = Dev->Dma->IoReply.Data.TransferCount;
531 Packet->OutTransferLength = Dev->Dma->IoReply.Data.TransferCount;
534 switch (Dev->Dma->IoReply.Data.IocStatus) {
535 case MPT_SCSI_IOCSTATUS_SUCCESS:
536 Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OK;
538 case MPT_SCSI_IOCSTATUS_DEVICE_NOT_THERE:
539 Packet->HostAdapterStatus =
540 EFI_EXT_SCSI_STATUS_HOST_ADAPTER_SELECTION_TIMEOUT;
542 case MPT_SCSI_IOCSTATUS_DATA_UNDERRUN:
543 case MPT_SCSI_IOCSTATUS_DATA_OVERRUN:
544 Packet->HostAdapterStatus =
545 EFI_EXT_SCSI_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN;
548 Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OTHER;
549 return EFI_DEVICE_ERROR;
552 DEBUG ((DEBUG_ERROR,
"%a: unexpected reply (%x)\n", __func__, Reply));
553 return ReportHostAdapterError (Packet);
578 Dev = MPT_SCSI_FROM_PASS_THRU (This);
582 Status = MptScsiPopulateRequest (Dev, *Target, Lun, Packet);
583 if (EFI_ERROR (Status)) {
590 Status = MptScsiSendRequest (Dev, Packet);
591 if (EFI_ERROR (Status)) {
592 return ReportHostAdapterError (Packet);
595 Status = MptScsiGetReply (Dev, &Reply);
596 if (EFI_ERROR (Status)) {
597 return ReportHostAdapterError (Packet);
600 return MptScsiHandleReply (Dev, Reply, Packet);
611 for (Idx = 0; Idx < TARGET_MAX_BYTES; ++Idx) {
612 if (Target[Idx] != 0xFF) {
623MptScsiGetNextTargetLun (
625 IN OUT UINT8 **Target,
631 Dev = MPT_SCSI_FROM_PASS_THRU (This);
635 if (!IsTargetInitialized (*Target)) {
636 ZeroMem (*Target, TARGET_MAX_BYTES);
638 }
else if ((**Target > Dev->MaxTarget) || (*Lun > 0)) {
639 return EFI_INVALID_PARAMETER;
640 }
else if (**Target < Dev->MaxTarget) {
647 return EFI_NOT_FOUND;
656MptScsiGetNextTarget (
658 IN OUT UINT8 **Target
663 Dev = MPT_SCSI_FROM_PASS_THRU (This);
664 if (!IsTargetInitialized (*Target)) {
665 ZeroMem (*Target, TARGET_MAX_BYTES);
666 }
else if (**Target > Dev->MaxTarget) {
667 return EFI_INVALID_PARAMETER;
668 }
else if (**Target < Dev->MaxTarget) {
675 return EFI_NOT_FOUND;
684MptScsiBuildDevicePath (
694 if (DevicePath ==
NULL) {
695 return EFI_INVALID_PARAMETER;
702 Dev = MPT_SCSI_FROM_PASS_THRU (This);
703 if ((*Target > Dev->MaxTarget) || (Lun > 0)) {
704 return EFI_NOT_FOUND;
708 if (ScsiDevicePath ==
NULL) {
709 return EFI_OUT_OF_RESOURCES;
714 ScsiDevicePath->Header.
Length[0] = (UINT8)
sizeof (*ScsiDevicePath);
715 ScsiDevicePath->Header.
Length[1] = (UINT8)(
sizeof (*ScsiDevicePath) >> 8);
716 ScsiDevicePath->
Pun = *Target;
717 ScsiDevicePath->
Lun = (UINT16)Lun;
719 *DevicePath = &ScsiDevicePath->Header;
736 if ((DevicePath ==
NULL) ||
739 return EFI_INVALID_PARAMETER;
745 return EFI_UNSUPPORTED;
748 Dev = MPT_SCSI_FROM_PASS_THRU (This);
750 if ((ScsiDevicePath->
Pun > Dev->MaxTarget) ||
751 (ScsiDevicePath->
Lun > 0))
753 return EFI_NOT_FOUND;
756 ZeroMem (*Target, TARGET_MAX_BYTES);
761 **Target = (UINT8)ScsiDevicePath->
Pun;
762 *Lun = ScsiDevicePath->
Lun;
774 return EFI_UNSUPPORTED;
788 DEBUG ((DEBUG_VERBOSE,
"%a: Context=0x%p\n", __func__, Context));
795MptScsiResetTargetLun (
801 return EFI_UNSUPPORTED;
811MptScsiControllerSupported (
821 Status =
gBS->OpenProtocol (
823 &gEfiPciIoProtocolGuid,
825 This->DriverBindingHandle,
827 EFI_OPEN_PROTOCOL_BY_DRIVER
829 if (EFI_ERROR (Status)) {
833 Status = PciIo->Pci.Read (
837 sizeof (Pci) /
sizeof (UINT32),
840 if (EFI_ERROR (Status)) {
844 if ((Pci.Hdr.VendorId == LSI_LOGIC_PCI_VENDOR_ID) &&
845 ((Pci.Hdr.DeviceId == LSI_53C1030_PCI_DEVICE_ID) ||
846 (Pci.Hdr.DeviceId == LSI_SAS1068_PCI_DEVICE_ID) ||
847 (Pci.Hdr.DeviceId == LSI_SAS1068E_PCI_DEVICE_ID)))
851 Status = EFI_UNSUPPORTED;
857 &gEfiPciIoProtocolGuid,
858 This->DriverBindingHandle,
867MptScsiControllerStart (
880 return EFI_OUT_OF_RESOURCES;
883 Dev->Signature = MPT_SCSI_DEV_SIGNATURE;
885 Dev->MaxTarget =
PcdGet8 (PcdMptScsiMaxTargetLimit);
886 Dev->StallPerPollUsec =
PcdGet32 (PcdMptScsiStallPerPollUsec);
888 Status =
gBS->OpenProtocol (
890 &gEfiPciIoProtocolGuid,
891 (VOID **)&Dev->PciIo,
892 This->DriverBindingHandle,
894 EFI_OPEN_PROTOCOL_BY_DRIVER
896 if (EFI_ERROR (Status)) {
900 Status = Dev->PciIo->Attributes (
904 &Dev->OriginalPciAttributes
906 if (EFI_ERROR (Status)) {
913 Status = Dev->PciIo->Attributes (
920 if (EFI_ERROR (Status)) {
927 Status = Dev->PciIo->Attributes (
933 if (EFI_ERROR (Status)) {
942 "%a: failed to enable 64-bit DMA addresses\n",
951 Status = Dev->PciIo->AllocateBuffer (
957 EFI_PCI_ATTRIBUTE_MEMORY_CACHED
959 if (EFI_ERROR (Status)) {
960 goto RestoreAttributes;
964 Status = Dev->PciIo->Map (
972 if (EFI_ERROR (Status)) {
977 Status = EFI_OUT_OF_RESOURCES;
981 Status = MptScsiInit (Dev);
982 if (EFI_ERROR (Status)) {
986 Status =
gBS->CreateEvent (
987 EVT_SIGNAL_EXIT_BOOT_SERVICES,
993 if (EFI_ERROR (Status)) {
1000 Dev->PassThruMode.
AdapterId = MAX_UINT32;
1002 EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL |
1003 EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL;
1005 Dev->PassThru.
Mode = &Dev->PassThruMode;
1006 Dev->PassThru.PassThru = &MptScsiPassThru;
1007 Dev->PassThru.GetNextTargetLun = &MptScsiGetNextTargetLun;
1008 Dev->PassThru.BuildDevicePath = &MptScsiBuildDevicePath;
1009 Dev->PassThru.GetTargetLun = &MptScsiGetTargetLun;
1010 Dev->PassThru.ResetChannel = &MptScsiResetChannel;
1011 Dev->PassThru.ResetTargetLun = &MptScsiResetTargetLun;
1012 Dev->PassThru.GetNextTarget = &MptScsiGetNextTarget;
1014 Status =
gBS->InstallProtocolInterface (
1016 &gEfiExtScsiPassThruProtocolGuid,
1020 if (EFI_ERROR (Status)) {
1027 gBS->CloseEvent (Dev->ExitBoot);
1039 Dev->PciIo->FreeBuffer (
1046 Dev->PciIo->Attributes (
1049 Dev->OriginalPciAttributes,
1054 gBS->CloseProtocol (
1056 &gEfiPciIoProtocolGuid,
1057 This->DriverBindingHandle,
1070MptScsiControllerStop (
1081 Status =
gBS->OpenProtocol (
1083 &gEfiExtScsiPassThruProtocolGuid,
1085 This->DriverBindingHandle,
1087 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1089 if (EFI_ERROR (Status)) {
1093 Dev = MPT_SCSI_FROM_PASS_THRU (PassThru);
1095 Status =
gBS->UninstallProtocolInterface (
1097 &gEfiExtScsiPassThruProtocolGuid,
1100 if (EFI_ERROR (Status)) {
1104 gBS->CloseEvent (Dev->ExitBoot);
1113 Dev->PciIo->FreeBuffer (
1119 Dev->PciIo->Attributes (
1122 Dev->OriginalPciAttributes,
1126 gBS->CloseProtocol (
1128 &gEfiPciIoProtocolGuid,
1129 This->DriverBindingHandle,
1140 &MptScsiControllerSupported,
1141 &MptScsiControllerStart,
1142 &MptScsiControllerStop,
1143 MPT_SCSI_BINDING_VERSION,
1154 {
"eng;en", L
"LSI Fusion MPT SCSI Driver" },
1163MptScsiGetDriverName (
1166 OUT CHAR16 **DriverName
1171 This->SupportedLanguages,
1174 (BOOLEAN)(This == &mComponentName)
1180MptScsiGetDeviceName (
1185 OUT CHAR16 **ControllerName
1188 return EFI_UNSUPPORTED;
1193 &MptScsiGetDriverName,
1194 &MptScsiGetDeviceName,
1219 &mMptScsiDriverBinding,
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
EFI_STATUS(EFIAPI * EFI_COMPONENT_NAME2_GET_DRIVER_NAME)(IN EFI_COMPONENT_NAME2_PROTOCOL *This, IN CHAR8 *Language, OUT CHAR16 **DriverName)
EFI_STATUS(EFIAPI * EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)(IN EFI_COMPONENT_NAME2_PROTOCOL *This, IN EFI_HANDLE ControllerHandle, IN EFI_HANDLE ChildHandle OPTIONAL, IN CHAR8 *Language, OUT CHAR16 **ControllerName)
#define MESSAGING_DEVICE_PATH
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
#define DEBUG(Expression)
#define EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
Clear for PCI controllers that can not genrate a DAC.
@ EfiPciIoAttributeOperationGet
@ EfiPciIoAttributeOperationEnable
@ EfiPciIoAttributeOperationSet
#define EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
Enable the DMA bit in the PCI Config Header.
@ EfiPciIoOperationBusMasterCommonBuffer
#define EFI_PCI_IO_ATTRIBUTE_IO
Enable the I/O decode bit in the PCI Config Header.
#define PcdGet8(TokenName)
#define PcdGet32(TokenName)
#define FixedPcdGet8(TokenName)
UINT64 EFI_PHYSICAL_ADDRESS
#define EFI_PAGES_TO_SIZE(Pages)
#define EFI_SIZE_TO_PAGES(Size)
EFI_STATUS EFIAPI LookupUnicodeString2(IN CONST CHAR8 *Language, IN CONST CHAR8 *SupportedLanguages, IN CONST EFI_UNICODE_STRING_TABLE *UnicodeStringTable, OUT CHAR16 **UnicodeString, IN BOOLEAN Iso639Language)
EFI_STATUS EFIAPI EfiLibInstallDriverBindingComponentName2(IN CONST EFI_HANDLE ImageHandle, IN CONST EFI_SYSTEM_TABLE *SystemTable, IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding, IN EFI_HANDLE DriverBindingHandle, IN CONST EFI_COMPONENT_NAME_PROTOCOL *ComponentName OPTIONAL, IN CONST EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2 OPTIONAL)
EFI_EXT_SCSI_PASS_THRU_MODE * Mode