/** @file\r
- Copyright (c) 2006, Intel Corporation \r
- All rights reserved. This program and the accompanying materials \r
- are licensed and made available under the terms and conditions of the BSD License \r
- which accompanies this distribution. The full text of the license may be found at \r
- http://opensource.org/licenses/bsd-license.php \r
+ Copyright (c) 2006, Intel Corporation\r
+ All rights reserved. This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
\r
**/\r
\r
#include "AtapiPassThru.h"\r
\r
-///\r
-/// IDE registers' fixed address\r
-///\r
-static IDE_BASE_REGISTERS gAtapiIoPortRegisters[2] = {\r
- { 0x1f0, { 0x1f1 }, 0x1f2, 0x1f3, 0x1f4, 0x1f5, 0x1f6, { 0x1f7 }, { 0x3f6 }, 0x3f7, 0 },\r
- { 0x170, { 0x171 }, 0x172, 0x173, 0x174, 0x175, 0x176, { 0x177 }, { 0x376 }, 0x377, 0 } \r
-};\r
\r
static SCSI_COMMAND_SET gEndTable = { 0xff, (DATA_DIRECTION) 0xff };\r
\r
{ OP_WRITE_10, DataOut },\r
{ OP_WRITE_12, DataOut },\r
{ OP_WRITE_AND_VERIFY, DataOut },\r
- { 0xff, (DATA_DIRECTION) 0xff } \r
+ { 0xff, (DATA_DIRECTION) 0xff }\r
};\r
\r
static CHAR16 *gControllerNameString = (CHAR16 *) L"ATAPI Controller";\r
EFI_PCI_IO_PROTOCOL *PciIo;\r
PCI_TYPE00 Pci;\r
\r
+\r
//\r
// Open the IO Abstraction(s) needed to perform the supported test\r
//\r
);\r
if (EFI_ERROR (Status)) {\r
gBS->CloseProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
+ Controller,\r
+ &gEfiPciIoProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
return EFI_UNSUPPORTED;\r
}\r
\r
}\r
\r
gBS->CloseProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
+ Controller,\r
+ &gEfiPciIoProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
\r
return Status;\r
}\r
{\r
EFI_STATUS Status;\r
EFI_PCI_IO_PROTOCOL *PciIo;\r
+ UINT64 Supports;\r
+ UINT64 OriginalPciAttributes;\r
\r
PciIo = NULL;\r
Status = gBS->OpenProtocol (\r
return Status;\r
}\r
\r
+ //\r
+ // Save original PCI attributes\r
+ //\r
Status = PciIo->Attributes (\r
PciIo,\r
- EfiPciIoAttributeOperationEnable,\r
- EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO | EFI_PCI_DEVICE_ENABLE,\r
- NULL\r
+ EfiPciIoAttributeOperationGet,\r
+ 0,\r
+ &OriginalPciAttributes\r
);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = PciIo->Attributes (\r
+ PciIo,\r
+ EfiPciIoAttributeOperationSupported,\r
+ 0,\r
+ &Supports\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ Supports &= (EFI_PCI_DEVICE_ENABLE |\r
+ EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO |\r
+ EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO);\r
+ Status = PciIo->Attributes (\r
+ PciIo,\r
+ EfiPciIoAttributeOperationEnable,\r
+ Supports,\r
+ NULL\r
+ );\r
+ }\r
if (EFI_ERROR (Status)) {\r
goto Done;\r
}\r
//\r
// Create SCSI Pass Thru instance for the IDE channel.\r
//\r
- Status = RegisterAtapiScsiPassThru (This, Controller, PciIo);\r
+ Status = RegisterAtapiScsiPassThru (This, Controller, PciIo, OriginalPciAttributes);\r
\r
Done:\r
if (EFI_ERROR (Status)) {\r
- if (PciIo) {\r
- PciIo->Attributes (\r
- PciIo,\r
- EfiPciIoAttributeOperationDisable,\r
- EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO | EFI_PCI_DEVICE_ENABLE,\r
- NULL\r
- );\r
- }\r
+ //\r
+ // Restore original PCI attributes\r
+ //\r
+ PciIo->Attributes (\r
+ PciIo,\r
+ EfiPciIoAttributeOperationSet,\r
+ OriginalPciAttributes,\r
+ NULL\r
+ );\r
\r
gBS->CloseProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
+ Controller,\r
+ &gEfiPciIoProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
}\r
\r
return Status;\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
+\r
//\r
- // Release Pci Io protocol on the controller handle.\r
+ // Restore original PCI attributes\r
//\r
AtapiScsiPrivate->PciIo->Attributes (\r
- AtapiScsiPrivate->PciIo,\r
- EfiPciIoAttributeOperationDisable,\r
- EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO | EFI_PCI_DEVICE_ENABLE,\r
- NULL\r
- );\r
+ AtapiScsiPrivate->PciIo,\r
+ EfiPciIoAttributeOperationSet,\r
+ AtapiScsiPrivate->OriginalPciAttributes,\r
+ NULL\r
+ );\r
\r
gBS->CloseProtocol (\r
- Controller,\r
- &gEfiPciIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
+ Controller,\r
+ &gEfiPciIoProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
\r
gBS->FreePool (AtapiScsiPrivate);\r
\r
/**\r
Attaches SCSI Pass Thru Protocol for specified IDE channel.\r
\r
- @param Controller: Parent device handle to the IDE channel.\r
- @param PciIo: PCI I/O protocol attached on the "Controller".\r
+ @param Controller: Parent device handle to the IDE channel.\r
+ @param PciIo: PCI I/O protocol attached on the "Controller".\r
+ @param OriginalPciAttributes Original PCI attributes\r
+\r
\r
@return EFI_SUCCESS Always returned unless installing SCSI Pass Thru Protocol failed.\r
\r
RegisterAtapiScsiPassThru (\r
IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
IN EFI_HANDLE Controller,\r
- IN EFI_PCI_IO_PROTOCOL *PciIo\r
+ IN EFI_PCI_IO_PROTOCOL *PciIo,\r
+ IN UINT64 OriginalPciAttributes\r
)\r
{\r
EFI_STATUS Status;\r
ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate;\r
- UINT64 Attributes;\r
+ IDE_REGISTERS_BASE_ADDR IdeRegsBaseAddr[ATAPI_MAX_CHANNEL];\r
\r
AtapiScsiPrivate = AllocateZeroPool (sizeof (ATAPI_SCSI_PASS_THRU_DEV));\r
if (AtapiScsiPrivate == NULL) {\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
- Attributes = EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO | EFI_PCI_DEVICE_ENABLE;\r
CopyMem (AtapiScsiPrivate->ChannelName, gAtapiChannelString, sizeof (gAtapiChannelString));\r
\r
- //\r
- // Enable channel\r
- //\r
- PciIo->Attributes (PciIo, EfiPciIoAttributeOperationSet, Attributes, NULL);\r
-\r
AtapiScsiPrivate->Signature = ATAPI_SCSI_PASS_THRU_DEV_SIGNATURE;\r
AtapiScsiPrivate->Handle = Controller;\r
\r
//\r
// will reset the IoPort inside each API function.\r
//\r
- AtapiScsiPrivate->IoPort = gAtapiIoPortRegisters;\r
- AtapiScsiPrivate->PciIo = PciIo;\r
+ AtapiScsiPrivate->IoPort = NULL;\r
+ AtapiScsiPrivate->PciIo = PciIo;\r
+ AtapiScsiPrivate->OriginalPciAttributes = OriginalPciAttributes;\r
\r
//\r
+ // Obtain IDE IO port registers' base addresses\r
+ //\r
+ Status = GetIdeRegistersBaseAddr (PciIo, IdeRegsBaseAddr);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ InitAtapiIoPortRegisters(AtapiScsiPrivate, IdeRegsBaseAddr);\r
+\r
// initialize SCSI Pass Thru Protocol interface\r
//\r
AtapiScsiPrivate->ScsiPassThru.Mode = &AtapiScsiPrivate->ScsiPassThruMode;\r
//\r
// non-RAID SCSI controllers should set both physical and logical attributes\r
//\r
- AtapiScsiPrivate->ScsiPassThruMode.Attributes = EFI_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL | \r
+ AtapiScsiPrivate->ScsiPassThruMode.Attributes = EFI_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL |\r
EFI_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL;\r
AtapiScsiPrivate->ScsiPassThruMode.IoAlign = 0;\r
\r
//\r
- // Initialize the LatestTargetId to 0xFFFFFFFF (for the GetNextDevice() call).\r
+ // Initialize the LatestTargetId.\r
//\r
- AtapiScsiPrivate->LatestTargetId = 0xFFFFFFFF;\r
+ AtapiScsiPrivate->LatestTargetId = 4;\r
AtapiScsiPrivate->LatestLun = 0;\r
\r
Status = gBS->InstallProtocolInterface (\r
IN EFI_EVENT Event OPTIONAL\r
)\r
{\r
- ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate;\r
- EFI_STATUS Status;\r
+ ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate;\r
+ EFI_STATUS Status;\r
\r
AtapiScsiPrivate = ATAPI_SCSI_PASS_THRU_DEV_FROM_THIS (This);\r
\r
//\r
// Target is not allowed beyond MAX_TARGET_ID\r
//\r
- if (Target > MAX_TARGET_ID) {\r
+ if ((Target > MAX_TARGET_ID) || (Lun != 0)) {\r
return EFI_INVALID_PARAMETER;\r
}\r
- \r
+\r
//\r
// check the data fields in Packet parameter.\r
//\r
Packet->TransferLength = 0;\r
return EFI_SUCCESS;\r
}\r
- \r
+\r
//\r
// According to Target ID, reset the Atapi I/O Register mapping\r
- // (Target Id in [0,1] area, using gAtapiIoPortRegisters[0],\r
- // Target Id in [2,3] area, using gAtapiIoPortRegisters[1]\r
+ // (Target Id in [0,1] area, using AtapiIoPortRegisters[0],\r
+ // Target Id in [2,3] area, using AtapiIoPortRegisters[1]\r
//\r
if ((Target / 2) == 0) {\r
- AtapiScsiPrivate->IoPort = &gAtapiIoPortRegisters[0];\r
+ Target = Target % 2;\r
+ AtapiScsiPrivate->IoPort = &AtapiScsiPrivate->AtapiIoPortRegisters[0];\r
} else {\r
- AtapiScsiPrivate->IoPort = &gAtapiIoPortRegisters[1];\r
+ Target = Target % 2;\r
+ AtapiScsiPrivate->IoPort = &AtapiScsiPrivate->AtapiIoPortRegisters[1];\r
}\r
- \r
+\r
//\r
// the ATAPI SCSI interface does not support non-blocking I/O\r
// ignore the Event parameter\r
}\r
\r
/**\r
- Used to retrieve the list of legal Target IDs for SCSI devices \r
+ Used to retrieve the list of legal Target IDs for SCSI devices\r
on a SCSI channel.\r
\r
@param This Protocol instance pointer.\r
}\r
\r
/**\r
- Used to allocate and build a device path node for a SCSI device \r
+ Used to allocate and build a device path node for a SCSI device\r
on a SCSI channel. Would not build device path for a SCSI Host Controller.\r
\r
@param This Protocol instance pointer.\r
{\r
EFI_DEV_PATH *Node;\r
\r
+\r
//\r
// Validate parameters passed in.\r
//\r
- \r
+\r
if (DevicePath == NULL) {\r
return EFI_INVALID_PARAMETER;\r
}\r
- \r
+\r
//\r
// can not build device path for the SCSI Host Controller.\r
//\r
if (DevicePath == NULL || Target == NULL || Lun == NULL) {\r
return EFI_INVALID_PARAMETER;\r
}\r
- \r
+\r
//\r
// Check whether the DevicePath belongs to SCSI_DEVICE_PATH\r
//\r
}\r
\r
/**\r
- Resets a SCSI channel.This operation resets all the \r
+ Resets a SCSI channel.This operation resets all the\r
SCSI devices connected to the SCSI channel.\r
\r
@param This Protocol instance pointer.\r
UINT8 DeviceControlValue;\r
ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate;\r
UINT8 Index;\r
+ BOOLEAN ResetFlag;\r
\r
AtapiScsiPrivate = ATAPI_SCSI_PASS_THRU_DEV_FROM_THIS (This);\r
+ ResetFlag = FALSE;\r
\r
//\r
// Reset both Primary channel and Secondary channel.\r
//\r
// Reset\r
//\r
- AtapiScsiPrivate->IoPort = &gAtapiIoPortRegisters[Index];\r
+ AtapiScsiPrivate->IoPort = &AtapiScsiPrivate->AtapiIoPortRegisters[Index];\r
\r
DeviceControlValue = 0;\r
//\r
// 0xfb:1111,1011\r
//\r
DeviceControlValue &= 0xfb;\r
- \r
+\r
WritePortB (AtapiScsiPrivate->PciIo, AtapiScsiPrivate->IoPort->Alt.DeviceControl, DeviceControlValue);\r
\r
//\r
// slave device needs at most 31s to clear BSY\r
//\r
- if (StatusWaitForBSYClear (AtapiScsiPrivate, 31000) == EFI_TIMEOUT) {\r
- return EFI_DEVICE_ERROR;\r
+ if (StatusWaitForBSYClear (AtapiScsiPrivate, 31000000) != EFI_TIMEOUT) {\r
+ ResetFlag = TRUE;\r
}\r
}\r
\r
- return EFI_SUCCESS;\r
+ if (ResetFlag) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ return EFI_TIMEOUT;\r
}\r
\r
/**\r
\r
AtapiScsiPrivate = ATAPI_SCSI_PASS_THRU_DEV_FROM_THIS (This);\r
\r
- if (Target > MAX_TARGET_ID) {\r
+ if ((Target > MAX_TARGET_ID) || (Lun != 0)) {\r
return EFI_INVALID_PARAMETER;\r
}\r
//\r
if (Target == This->Mode->AdapterId) {\r
return EFI_SUCCESS;\r
}\r
- \r
+\r
//\r
// According to Target ID, reset the Atapi I/O Register mapping\r
- // (Target Id in [0,1] area, using gAtapiIoPortRegisters[0],\r
- // Target Id in [2,3] area, using gAtapiIoPortRegisters[1]\r
+ // (Target Id in [0,1] area, using AtapiIoPortRegisters[0],\r
+ // Target Id in [2,3] area, using AtapiIoPortRegisters[1]\r
//\r
if ((Target / 2) == 0) {\r
- AtapiScsiPrivate->IoPort = &gAtapiIoPortRegisters[0];\r
+ AtapiScsiPrivate->IoPort = &AtapiScsiPrivate->AtapiIoPortRegisters[0];\r
} else {\r
- AtapiScsiPrivate->IoPort = &gAtapiIoPortRegisters[1];\r
+ AtapiScsiPrivate->IoPort = &AtapiScsiPrivate->AtapiIoPortRegisters[1];\r
}\r
- \r
+\r
//\r
// for ATAPI device, no need to wait DRDY ready after device selecting.\r
//\r
// when reset is complete.\r
// slave device needs at most 31s to clear BSY\r
//\r
- if (EFI_ERROR (StatusWaitForBSYClear (AtapiScsiPrivate, 31000))) {\r
- return EFI_DEVICE_ERROR;\r
+ if (EFI_ERROR (StatusWaitForBSYClear (AtapiScsiPrivate, 31000000))) {\r
+ return EFI_TIMEOUT;\r
}\r
- \r
+\r
//\r
// stall 5 seconds to make the device status stable\r
//\r
return EFI_SUCCESS;\r
}\r
\r
- \r
-/**\r
- Checks the parameters in the SCSI Request Packet to make sure\r
- they are valid for a SCSI Pass Thru request.\r
+EFI_STATUS\r
+GetIdeRegistersBaseAddr (\r
+ IN EFI_PCI_IO_PROTOCOL *PciIo,\r
+ OUT IDE_REGISTERS_BASE_ADDR *IdeRegsBaseAddr\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Get IDE IO port registers' base addresses by mode. In 'Compatibility' mode,\r
+ use fixed addresses. In Native-PCI mode, get base addresses from BARs in\r
+ the PCI IDE controller's Configuration Space.\r
+\r
+Arguments:\r
+ PciIo - Pointer to the EFI_PCI_IO_PROTOCOL instance\r
+ IdeRegsBaseAddr - Pointer to IDE_REGISTERS_BASE_ADDR to\r
+ receive IDE IO port registers' base addresses\r
+\r
+Returns:\r
+\r
+ EFI_STATUS\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ PCI_TYPE00 PciData;\r
+\r
+ Status = PciIo->Pci.Read (\r
+ PciIo,\r
+ EfiPciIoWidthUint8,\r
+ 0,\r
+ sizeof (PciData),\r
+ &PciData\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if ((PciData.Hdr.ClassCode[0] & IDE_PRIMARY_OPERATING_MODE) == 0) {\r
+ IdeRegsBaseAddr[IdePrimary].CommandBlockBaseAddr = 0x1f0;\r
+ IdeRegsBaseAddr[IdePrimary].ControlBlockBaseAddr = 0x3f6;\r
+ } else {\r
+ //\r
+ // The BARs should be of IO type\r
+ //\r
+ if ((PciData.Device.Bar[0] & BIT0) == 0 ||\r
+ (PciData.Device.Bar[1] & BIT0) == 0) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ IdeRegsBaseAddr[IdePrimary].CommandBlockBaseAddr =\r
+ (UINT16) (PciData.Device.Bar[0] & 0x0000fff8);\r
+ IdeRegsBaseAddr[IdePrimary].ControlBlockBaseAddr =\r
+ (UINT16) ((PciData.Device.Bar[1] & 0x0000fffc) + 2);\r
+ }\r
+\r
+ if ((PciData.Hdr.ClassCode[0] & IDE_SECONDARY_OPERATING_MODE) == 0) {\r
+ IdeRegsBaseAddr[IdeSecondary].CommandBlockBaseAddr = 0x170;\r
+ IdeRegsBaseAddr[IdeSecondary].ControlBlockBaseAddr = 0x376;\r
+ } else {\r
+ //\r
+ // The BARs should be of IO type\r
+ //\r
+ if ((PciData.Device.Bar[2] & BIT0) == 0 ||\r
+ (PciData.Device.Bar[3] & BIT0) == 0) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ IdeRegsBaseAddr[IdeSecondary].CommandBlockBaseAddr =\r
+ (UINT16) (PciData.Device.Bar[2] & 0x0000fff8);\r
+ IdeRegsBaseAddr[IdeSecondary].ControlBlockBaseAddr =\r
+ (UINT16) ((PciData.Device.Bar[3] & 0x0000fffc) + 2);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+InitAtapiIoPortRegisters (\r
+ IN ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate,\r
+ IN IDE_REGISTERS_BASE_ADDR *IdeRegsBaseAddr\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Initialize each Channel's Base Address of CommandBlock and ControlBlock.\r
+\r
+Arguments:\r
+\r
+ AtapiScsiPrivate - The pointer of ATAPI_SCSI_PASS_THRU_DEV\r
+ IdeRegsBaseAddr - The pointer of IDE_REGISTERS_BASE_ADDR\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+\r
+ UINT8 IdeChannel;\r
+ UINT16 CommandBlockBaseAddr;\r
+ UINT16 ControlBlockBaseAddr;\r
+ IDE_BASE_REGISTERS *RegisterPointer;\r
+\r
+\r
+ for (IdeChannel = 0; IdeChannel < ATAPI_MAX_CHANNEL; IdeChannel++) {\r
+\r
+ RegisterPointer = &AtapiScsiPrivate->AtapiIoPortRegisters[IdeChannel];\r
+\r
+ //\r
+ // Initialize IDE IO port addresses, including Command Block registers\r
+ // and Control Block registers\r
+ //\r
+ CommandBlockBaseAddr = IdeRegsBaseAddr[IdeChannel].CommandBlockBaseAddr;\r
+ ControlBlockBaseAddr = IdeRegsBaseAddr[IdeChannel].ControlBlockBaseAddr;\r
+\r
+ RegisterPointer->Data = CommandBlockBaseAddr;\r
+ (*(UINT16 *) &RegisterPointer->Reg1) = (UINT16) (CommandBlockBaseAddr + 0x01);\r
+ RegisterPointer->SectorCount = (UINT16) (CommandBlockBaseAddr + 0x02);\r
+ RegisterPointer->SectorNumber = (UINT16) (CommandBlockBaseAddr + 0x03);\r
+ RegisterPointer->CylinderLsb = (UINT16) (CommandBlockBaseAddr + 0x04);\r
+ RegisterPointer->CylinderMsb = (UINT16) (CommandBlockBaseAddr + 0x05);\r
+ RegisterPointer->Head = (UINT16) (CommandBlockBaseAddr + 0x06);\r
+ (*(UINT16 *) &RegisterPointer->Reg) = (UINT16) (CommandBlockBaseAddr + 0x07);\r
+\r
+ (*(UINT16 *) &RegisterPointer->Alt) = ControlBlockBaseAddr;\r
+ RegisterPointer->DriveAddress = (UINT16) (ControlBlockBaseAddr + 0x01);\r
+ }\r
+\r
+}\r
+\r
\r
- @todo function comment is missing 'Routine Description:'\r
- @todo function comment is missing 'Arguments:'\r
- @todo function comment is missing 'Returns:'\r
- @todo Packet - add argument and description to function comment\r
- @todo EFI_INVALID_PARAMETER - add return value to function comment\r
- @todo EFI_INVALID_PARAMETER - add return value to function comment\r
- @todo EFI_INVALID_PARAMETER - add return value to function comment\r
- @todo EFI_UNSUPPORTED - add return value to function comment\r
- @todo EFI_SUCCESS - add return value to function comment\r
-**/\r
EFI_STATUS\r
CheckSCSIRequestPacket (\r
EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet\r
)\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Checks the parameters in the SCSI Request Packet to make sure\r
+ they are valid for a SCSI Pass Thru request.\r
+\r
+Arguments:\r
+\r
+ Packet - The pointer of EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET\r
+\r
+Returns:\r
+\r
+ EFI_STATUS\r
+\r
+--*/\r
{\r
if (Packet == NULL) {\r
return EFI_INVALID_PARAMETER;\r
if (Packet->Cdb == NULL) {\r
return EFI_INVALID_PARAMETER;\r
}\r
- \r
+\r
//\r
// Checks whether the request command is supported.\r
//\r
}\r
\r
/**\r
- Checks the requested SCSI command: \r
+ Checks the requested SCSI command:\r
Is it supported by this driver?\r
Is the Data transfer direction reasonable?\r
\r
Packet->SenseDataLength = 0;\r
return PacketCommandStatus;\r
}\r
+\r
+ //\r
+ // Check if SenseData meets the alignment requirement.\r
+ //\r
+ if ((AtapiScsiPrivate->ScsiPassThru.Mode->IoAlign != 0) \\r
+ && (AtapiScsiPrivate->ScsiPassThru.Mode->IoAlign != 1)) {\r
+ if (((UINTN)Packet->SenseData % AtapiScsiPrivate->ScsiPassThru.Mode->IoAlign) != 0) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ }\r
+\r
+\r
//\r
// Return SenseData if PacketCommandStatus matches\r
// the following return codes.\r
//\r
- if ((PacketCommandStatus == EFI_WARN_BUFFER_TOO_SMALL) ||\r
+ if ((PacketCommandStatus == EFI_BAD_BUFFER_SIZE) ||\r
(PacketCommandStatus == EFI_DEVICE_ERROR) ||\r
(PacketCommandStatus == EFI_TIMEOUT)) {\r
- \r
+\r
//\r
// avoid submit request sense command continuously.\r
//\r
EFI_STATUS Status;\r
\r
//\r
- // Set all the command parameters by fill related registers.\r
- // Before write to all the following registers, BSY and DRQ must be 0.\r
+ // Check if the buffer meets the alignment requirement.\r
//\r
- Status = StatusDRQClear (AtapiScsiPrivate, TimeoutInMicroSeconds);\r
- if (EFI_ERROR (Status)) {\r
- if (Status == EFI_ABORTED) {\r
- Status = EFI_DEVICE_ERROR;\r
+ if ((AtapiScsiPrivate->ScsiPassThru.Mode->IoAlign != 0) \\r
+ && (AtapiScsiPrivate->ScsiPassThru.Mode->IoAlign != 1)) {\r
+ if (((UINTN)Buffer % AtapiScsiPrivate->ScsiPassThru.Mode->IoAlign) != 0) {\r
+ return EFI_INVALID_PARAMETER;\r
}\r
+ }\r
\r
- *ByteCount = 0;\r
- return Status;\r
+ //\r
+ // Set all the command parameters by fill related registers.\r
+ // Before write to all the following registers, BSY must be 0.\r
+ //\r
+ Status = StatusWaitForBSYClear (AtapiScsiPrivate, TimeoutInMicroSeconds);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_DEVICE_ERROR;\r
}\r
+\r
+\r
//\r
// Select device via Device/Head Register.\r
// "Target = 0" indicates device 0; "Target = 1" indicates device 1\r
(UINT8) ((Target << 4) | DEFAULT_CMD) // DEFAULT_CMD: 0xa0 (1010,0000)\r
);\r
\r
+ //\r
+ // Set all the command parameters by fill related registers.\r
+ // Before write to all the following registers, BSY DRQ must be 0.\r
+ //\r
+ Status = StatusDRQClear(AtapiScsiPrivate, TimeoutInMicroSeconds);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ if (Status == EFI_ABORTED) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ }\r
+ *ByteCount = 0;\r
+ return Status;\r
+ }\r
+\r
//\r
// No OVL; No DMA (by setting feature register)\r
//\r
// ActualWordCount > 0\r
//\r
if (ActualWordCount < RequiredWordCount) {\r
- return EFI_WARN_BUFFER_TOO_SMALL;\r
+ return EFI_BAD_BUFFER_SIZE;\r
}\r
}\r
//\r
/**\r
Check whether DRQ is clear in the Status Register. (BSY must also be cleared)\r
If TimeoutInMicroSeconds is zero, this routine should wait infinitely for\r
- DRQ clear. Otherwise, it will return EFI_TIMEOUT when specified time is \r
+ DRQ clear. Otherwise, it will return EFI_TIMEOUT when specified time is\r
elapsed.\r
\r
@todo function comment is missing 'Routine Description:'\r
}\r
\r
/**\r
- Check whether DRQ is clear in the Alternate Status Register. \r
+ Check whether DRQ is clear in the Alternate Status Register.\r
(BSY must also be cleared).\r
If TimeoutInMicroSeconds is zero, this routine should wait infinitely for\r
- DRQ clear. Otherwise, it will return EFI_TIMEOUT when specified time is \r
+ DRQ clear. Otherwise, it will return EFI_TIMEOUT when specified time is\r
elapsed.\r
\r
@todo function comment is missing 'Routine Description:'\r
/**\r
Check whether DRQ is ready in the Status Register. (BSY must also be cleared)\r
If TimeoutInMicroSeconds is zero, this routine should wait infinitely for\r
- DRQ ready. Otherwise, it will return EFI_TIMEOUT when specified time is \r
+ DRQ ready. Otherwise, it will return EFI_TIMEOUT when specified time is\r
elapsed.\r
\r
@todo function comment is missing 'Routine Description:'\r
}\r
\r
/**\r
- Check whether DRQ is ready in the Alternate Status Register. \r
+ Check whether DRQ is ready in the Alternate Status Register.\r
(BSY must also be cleared)\r
If TimeoutInMicroSeconds is zero, this routine should wait infinitely for\r
- DRQ ready. Otherwise, it will return EFI_TIMEOUT when specified time is \r
+ DRQ ready. Otherwise, it will return EFI_TIMEOUT when specified time is\r
elapsed.\r
\r
@todo function comment is missing 'Routine Description:'\r
/**\r
Check whether BSY is clear in the Status Register.\r
If TimeoutInMicroSeconds is zero, this routine should wait infinitely for\r
- BSY clear. Otherwise, it will return EFI_TIMEOUT when specified time is \r
+ BSY clear. Otherwise, it will return EFI_TIMEOUT when specified time is\r
elapsed.\r
\r
@todo function comment is missing 'Routine Description:'\r
/**\r
Check whether BSY is clear in the Alternate Status Register.\r
If TimeoutInMicroSeconds is zero, this routine should wait infinitely for\r
- BSY clear. Otherwise, it will return EFI_TIMEOUT when specified time is \r
+ BSY clear. Otherwise, it will return EFI_TIMEOUT when specified time is\r
elapsed.\r
\r
@todo function comment is missing 'Routine Description:'\r
}\r
\r
/**\r
- Check whether DRDY is ready in the Status Register. \r
+ Check whether DRDY is ready in the Status Register.\r
(BSY must also be cleared)\r
If TimeoutInMicroSeconds is zero, this routine should wait infinitely for\r
- DRDY ready. Otherwise, it will return EFI_TIMEOUT when specified time is \r
+ DRDY ready. Otherwise, it will return EFI_TIMEOUT when specified time is\r
elapsed.\r
\r
@todo function comment is missing 'Routine Description:'\r
return EFI_ABORTED;\r
}\r
}\r
- \r
+\r
//\r
// Stall for 30 us\r
//\r
}\r
\r
/**\r
- Check whether DRDY is ready in the Alternate Status Register. \r
+ Check whether DRDY is ready in the Alternate Status Register.\r
(BSY must also be cleared)\r
If TimeoutInMicroSeconds is zero, this routine should wait infinitely for\r
- DRDY ready. Otherwise, it will return EFI_TIMEOUT when specified time is \r
+ DRDY ready. Otherwise, it will return EFI_TIMEOUT when specified time is\r
elapsed.\r
\r
@todo function comment is missing 'Routine Description:'\r
}\r
\r
/**\r
- Check Error Register for Error Information. \r
+ Check Error Register for Error Information.\r
\r
@todo function comment is missing 'Routine Description:'\r
@todo function comment is missing 'Arguments:'\r
AtapiScsiPrivate->PciIo,\r
AtapiScsiPrivate->IoPort->Reg.Status\r
);\r
- \r
+\r
DEBUG_CODE_BEGIN ();\r
\r
if (StatusRegister & DWF) {\r
\r
if (StatusRegister & ERR) {\r
ErrorRegister = ReadPortB (AtapiScsiPrivate->PciIo, AtapiScsiPrivate->IoPort->Reg1.Error);\r
- \r
+\r
\r
if (ErrorRegister & BBK_ERR) {\r
DEBUG (\r
return EFI_SUCCESS;\r
}\r
\r
- \r
+\r
return EFI_DEVICE_ERROR;\r
}\r
\r
/**\r
The user Entry Point for module AtapiPassThru. The user code starts with this function.\r
\r
- @param[in] ImageHandle The firmware allocated handle for the EFI image. \r
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
@param[in] SystemTable A pointer to the EFI System Table.\r
- \r
+\r
@retval EFI_SUCCESS The entry point is executed successfully.\r
@retval other Some error occurs when executing this entry point.\r
\r
//\r
// Install driver model protocol(s).\r
//\r
- Status = EfiLibInstallAllDriverProtocols (\r
+ Status = EfiLibInstallDriverBindingComponentName2 (\r
ImageHandle,\r
SystemTable,\r
&gAtapiScsiPassThruDriverBinding,\r
ImageHandle,\r
&gAtapiScsiPassThruComponentName,\r
- NULL,\r
- NULL\r
+ &gAtapiScsiPassThruComponentName2\r
);\r
ASSERT_EFI_ERROR (Status);\r
\r