/** @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
{ 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
)\r
{\r
EFI_STATUS Status;\r
- EFI_STATUS DisableStatus;\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
+ 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
//\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
- DisableStatus = PciIo->Attributes (\r
- PciIo,\r
- EfiPciIoAttributeOperationSupported,\r
- 0,\r
- &Supports\r
- );\r
- if (!EFI_ERROR (DisableStatus)) {\r
- Supports &= (EFI_PCI_DEVICE_ENABLE |\r
- EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO |\r
- EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO);\r
- DisableStatus = PciIo->Attributes (\r
- PciIo,\r
- EfiPciIoAttributeOperationDisable,\r
- Supports,\r
- NULL\r
- );\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
EFI_STATUS Status;\r
EFI_SCSI_PASS_THRU_PROTOCOL *ScsiPassThru;\r
ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate;\r
- UINT64 Supports;\r
\r
Status = gBS->OpenProtocol (\r
Controller,\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
- Status = AtapiScsiPrivate->PciIo->Attributes (\r
- AtapiScsiPrivate->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 = AtapiScsiPrivate->PciIo->Attributes (\r
- AtapiScsiPrivate->PciIo,\r
- EfiPciIoAttributeOperationDisable,\r
- Supports,\r
- NULL\r
- );\r
- }\r
+ AtapiScsiPrivate->PciIo->Attributes (\r
+ AtapiScsiPrivate->PciIo,\r
+ EfiPciIoAttributeOperationSet,\r
+ AtapiScsiPrivate->OriginalPciAttributes,\r
+ NULL\r
+ );\r
\r
gBS->CloseProtocol (\r
Controller,\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 Supports;\r
IDE_REGISTERS_BASE_ADDR IdeRegsBaseAddr[ATAPI_MAX_CHANNEL];\r
\r
AtapiScsiPrivate = AllocateZeroPool (sizeof (ATAPI_SCSI_PASS_THRU_DEV));\r
\r
CopyMem (AtapiScsiPrivate->ChannelName, gAtapiChannelString, sizeof (gAtapiChannelString));\r
\r
- //\r
- // Enable channel\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
-\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 = NULL;\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
// 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
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 AtapiIoPortRegisters[0],\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
// 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
// 0xfb:1111,1011\r
//\r
DeviceControlValue &= 0xfb;\r
- \r
+\r
WritePortB (AtapiScsiPrivate->PciIo, AtapiScsiPrivate->IoPort->Alt.DeviceControl, DeviceControlValue);\r
\r
//\r
if (ResetFlag) {\r
return EFI_SUCCESS;\r
}\r
- \r
+\r
return EFI_TIMEOUT;\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 AtapiIoPortRegisters[0],\r
} else {\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
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
\r
Arguments:\r
PciIo - Pointer to the EFI_PCI_IO_PROTOCOL instance\r
- IdeRegsBaseAddr - Pointer to IDE_REGISTERS_BASE_ADDR to \r
+ IdeRegsBaseAddr - Pointer to IDE_REGISTERS_BASE_ADDR to\r
receive IDE IO port registers' base addresses\r
- \r
+\r
Returns:\r
\r
EFI_STATUS\r
- \r
+\r
--*/\r
{\r
EFI_STATUS Status;\r
//\r
// The BARs should be of IO type\r
//\r
- if ((PciData.Device.Bar[0] & BIT0) == 0 || \r
+ if ((PciData.Device.Bar[0] & BIT0) == 0 ||\r
(PciData.Device.Bar[1] & BIT0) == 0) {\r
return EFI_UNSUPPORTED;\r
}\r
Initialize each Channel's Base Address of CommandBlock and ControlBlock.\r
\r
Arguments:\r
- \r
+\r
AtapiScsiPrivate - The pointer of ATAPI_SCSI_PASS_THRU_DEV\r
IdeRegsBaseAddr - The pointer of IDE_REGISTERS_BASE_ADDR\r
- \r
+\r
Returns:\r
- \r
+\r
None\r
\r
---*/ \r
+--*/\r
{\r
- \r
+\r
UINT8 IdeChannel;\r
UINT16 CommandBlockBaseAddr;\r
UINT16 ControlBlockBaseAddr;\r
IDE_BASE_REGISTERS *RegisterPointer;\r
\r
- \r
+\r
for (IdeChannel = 0; IdeChannel < ATAPI_MAX_CHANNEL; IdeChannel++) {\r
\r
RegisterPointer = &AtapiScsiPrivate->AtapiIoPortRegisters[IdeChannel];\r
//\r
CommandBlockBaseAddr = IdeRegsBaseAddr[IdeChannel].CommandBlockBaseAddr;\r
ControlBlockBaseAddr = IdeRegsBaseAddr[IdeChannel].ControlBlockBaseAddr;\r
- \r
+\r
RegisterPointer->Data = CommandBlockBaseAddr;\r
(*(UINT16 *) &RegisterPointer->Reg1) = (UINT16) (CommandBlockBaseAddr + 0x01);\r
RegisterPointer->SectorCount = (UINT16) (CommandBlockBaseAddr + 0x02);\r
RegisterPointer->CylinderMsb = (UINT16) (CommandBlockBaseAddr + 0x05);\r
RegisterPointer->Head = (UINT16) (CommandBlockBaseAddr + 0x06);\r
(*(UINT16 *) &RegisterPointer->Reg) = (UINT16) (CommandBlockBaseAddr + 0x07);\r
- \r
+\r
(*(UINT16 *) &RegisterPointer->Alt) = ControlBlockBaseAddr;\r
RegisterPointer->DriveAddress = (UINT16) (ControlBlockBaseAddr + 0x01);\r
}\r
\r
}\r
\r
- \r
+\r
EFI_STATUS\r
CheckSCSIRequestPacket (\r
EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet\r
\r
Arguments:\r
\r
- Packet - The pointer of EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET \r
+ Packet - The pointer of EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET\r
\r
Returns:\r
\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
//\r
// Check if SenseData meets the alignment requirement.\r
//\r
}\r
}\r
\r
- \r
+\r
//\r
// Return SenseData if PacketCommandStatus matches\r
// the following return codes.\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
/**\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