From: yshang1 Date: Tue, 3 Jul 2007 01:47:19 +0000 (+0000) Subject: Move Pci/AtapiPassThru/Dxe to Pci/AtapiPassThruDxe. X-Git-Tag: edk2-stable201903~22985 X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=commitdiff_plain;h=581c608bab1bd19105697b2f98b61651051815de Move Pci/AtapiPassThru/Dxe to Pci/AtapiPassThruDxe. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2970 6f19259b-4bc3-4df7-8a09-765794883524 --- diff --git a/MdeModulePkg/Bus/Pci/AtapiPassThru/Dxe/AtapiPassThru.c b/MdeModulePkg/Bus/Pci/AtapiPassThru/Dxe/AtapiPassThru.c deleted file mode 100644 index f14d9e3482..0000000000 --- a/MdeModulePkg/Bus/Pci/AtapiPassThru/Dxe/AtapiPassThru.c +++ /dev/null @@ -1,2177 +0,0 @@ -/** @file - Copyright (c) 2006, Intel Corporation - All rights reserved. This program and the accompanying materials - are licensed and made available under the terms and conditions of the BSD License - which accompanies this distribution. The full text of the license may be found at - http://opensource.org/licenses/bsd-license.php - - THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, - WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -#include "AtapiPassThru.h" - -/// -/// IDE registers' fixed address -/// -static IDE_BASE_REGISTERS gAtapiIoPortRegisters[2] = { - { 0x1f0, { 0x1f1 }, 0x1f2, 0x1f3, 0x1f4, 0x1f5, 0x1f6, { 0x1f7 }, { 0x3f6 }, 0x3f7, 0 }, - { 0x170, { 0x171 }, 0x172, 0x173, 0x174, 0x175, 0x176, { 0x177 }, { 0x376 }, 0x377, 0 } -}; - -static SCSI_COMMAND_SET gEndTable = { 0xff, (DATA_DIRECTION) 0xff }; - -/// -/// This table contains all the supported ATAPI commands. -/// -static SCSI_COMMAND_SET gSupportedATAPICommands[] = { - { OP_INQUIRY, DataIn }, - { OP_LOAD_UNLOAD_CD, NoData }, - { OP_MECHANISM_STATUS, DataIn }, - { OP_MODE_SELECT_10, DataOut }, - { OP_MODE_SENSE_10, DataIn }, - { OP_PAUSE_RESUME, NoData }, - { OP_PLAY_AUDIO_10, DataIn }, - { OP_PLAY_AUDIO_MSF, DataIn }, - { OP_PLAY_CD, DataIn }, - { OP_PLAY_CD_MSF, DataIn }, - { OP_PREVENT_ALLOW_MEDIUM_REMOVAL,NoData }, - { OP_READ_10, DataIn }, - { OP_READ_12, DataIn }, - { OP_READ_CAPACITY, DataIn }, - { OP_READ_CD, DataIn }, - { OP_READ_CD_MSF, DataIn }, - { OP_READ_HEADER, DataIn }, - { OP_READ_SUB_CHANNEL, DataIn }, - { OP_READ_TOC, DataIn }, - { OP_REQUEST_SENSE, DataIn }, - { OP_SCAN, NoData }, - { OP_SEEK_10, NoData }, - { OP_SET_CD_SPEED, DataOut }, - { OP_STOPPLAY_SCAN, NoData }, - { OP_START_STOP_UNIT, NoData }, - { OP_TEST_UNIT_READY, NoData }, - { OP_FORMAT_UNIT, DataOut }, - { OP_READ_FORMAT_CAPACITIES, DataIn }, - { OP_VERIFY, DataOut }, - { OP_WRITE_10, DataOut }, - { OP_WRITE_12, DataOut }, - { OP_WRITE_AND_VERIFY, DataOut }, - { 0xff, (DATA_DIRECTION) 0xff } -}; - -static CHAR16 *gControllerNameString = (CHAR16 *) L"ATAPI Controller"; -static CHAR16 *gAtapiChannelString = (CHAR16 *) L"ATAPI Channel"; - -EFI_DRIVER_BINDING_PROTOCOL gAtapiScsiPassThruDriverBinding = { - AtapiScsiPassThruDriverBindingSupported, - AtapiScsiPassThruDriverBindingStart, - AtapiScsiPassThruDriverBindingStop, - 0xa, - NULL, - NULL -}; - -/** - Supported. - - (Standard DriverBinding Protocol Supported() function) - - @return EFI_STATUS - - @todo This - add argument and description to function comment - @todo Controller - add argument and description to function comment - @todo RemainingDevicePath - add argument and description to function comment - @todo EFI_UNSUPPORTED - add return value to function comment -**/ -EFI_STATUS -EFIAPI -AtapiScsiPassThruDriverBindingSupported ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ) -{ - EFI_STATUS Status; - EFI_PCI_IO_PROTOCOL *PciIo; - PCI_TYPE00 Pci; - - // - // Open the IO Abstraction(s) needed to perform the supported test - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - (VOID **) &PciIo, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Use the PCI I/O Protocol to see if Controller is a IDE Controller that - // can be managed by this driver. Read the PCI Configuration Header - // for this device. - // - Status = PciIo->Pci.Read ( - PciIo, - EfiPciIoWidthUint32, - 0, - sizeof (Pci) / sizeof (UINT32), - &Pci - ); - if (EFI_ERROR (Status)) { - gBS->CloseProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); - return EFI_UNSUPPORTED; - } - - if (Pci.Hdr.ClassCode[2] != PCI_CLASS_MASS_STORAGE || Pci.Hdr.ClassCode[1] != PCI_CLASS_IDE) { - - Status = EFI_UNSUPPORTED; - } - - gBS->CloseProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - return Status; -} - -/** - Create handles for IDE channels specified by RemainingDevicePath. - Install SCSI Pass Thru Protocol onto each created handle. - - (Standard DriverBinding Protocol Start() function) - - @return EFI_STATUS - - @todo This - add argument and description to function comment - @todo Controller - add argument and description to function comment - @todo RemainingDevicePath - add argument and description to function comment -**/ -EFI_STATUS -EFIAPI -AtapiScsiPassThruDriverBindingStart ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ) -{ - EFI_STATUS Status; - EFI_PCI_IO_PROTOCOL *PciIo; - - PciIo = NULL; - Status = gBS->OpenProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - (VOID **) &PciIo, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = PciIo->Attributes ( - PciIo, - EfiPciIoAttributeOperationEnable, - EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO | EFI_PCI_DEVICE_ENABLE, - NULL - ); - if (EFI_ERROR (Status)) { - goto Done; - } - - // - // Create SCSI Pass Thru instance for the IDE channel. - // - Status = RegisterAtapiScsiPassThru (This, Controller, PciIo); - -Done: - if (EFI_ERROR (Status)) { - if (PciIo) { - PciIo->Attributes ( - PciIo, - EfiPciIoAttributeOperationDisable, - EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO | EFI_PCI_DEVICE_ENABLE, - NULL - ); - } - - gBS->CloseProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); - } - - return Status; -} - -/** - Stop. - - (Standard DriverBinding Protocol Stop() function) - - @return EFI_STATUS - - @todo This - add argument and description to function comment - @todo Controller - add argument and description to function comment - @todo NumberOfChildren - add argument and description to function comment - @todo ChildHandleBuffer - add argument and description to function comment - @todo EFI_SUCCESS - add return value to function comment -**/ -EFI_STATUS -EFIAPI -AtapiScsiPassThruDriverBindingStop ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN UINTN NumberOfChildren, - IN EFI_HANDLE *ChildHandleBuffer - ) -{ - EFI_STATUS Status; - EFI_SCSI_PASS_THRU_PROTOCOL *ScsiPassThru; - ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate; - - Status = gBS->OpenProtocol ( - Controller, - &gEfiScsiPassThruProtocolGuid, - (VOID **) &ScsiPassThru, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR (Status)) { - return Status; - } - - AtapiScsiPrivate = ATAPI_SCSI_PASS_THRU_DEV_FROM_THIS (ScsiPassThru); - - Status = gBS->UninstallProtocolInterface ( - Controller, - &gEfiScsiPassThruProtocolGuid, - &AtapiScsiPrivate->ScsiPassThru - ); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Release Pci Io protocol on the controller handle. - // - AtapiScsiPrivate->PciIo->Attributes ( - AtapiScsiPrivate->PciIo, - EfiPciIoAttributeOperationDisable, - EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO | EFI_PCI_DEVICE_ENABLE, - NULL - ); - - gBS->CloseProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - gBS->FreePool (AtapiScsiPrivate); - - return EFI_SUCCESS; -} - -/** - Attaches SCSI Pass Thru Protocol for specified IDE channel. - - @param Controller: Parent device handle to the IDE channel. - @param PciIo: PCI I/O protocol attached on the "Controller". - - @return EFI_SUCCESS Always returned unless installing SCSI Pass Thru Protocol failed. - - @todo This - add argument and description to function comment - @todo Controller - add argument and description to function comment - @todo PciIo - add argument and description to function comment - @todo EFI_OUT_OF_RESOURCES - add return value to function comment -**/ -EFI_STATUS -RegisterAtapiScsiPassThru ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_PCI_IO_PROTOCOL *PciIo - ) -{ - EFI_STATUS Status; - ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate; - UINT64 Attributes; - - AtapiScsiPrivate = AllocateZeroPool (sizeof (ATAPI_SCSI_PASS_THRU_DEV)); - if (AtapiScsiPrivate == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - Attributes = EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO | EFI_PCI_DEVICE_ENABLE; - CopyMem (AtapiScsiPrivate->ChannelName, gAtapiChannelString, sizeof (gAtapiChannelString)); - - // - // Enable channel - // - PciIo->Attributes (PciIo, EfiPciIoAttributeOperationSet, Attributes, NULL); - - AtapiScsiPrivate->Signature = ATAPI_SCSI_PASS_THRU_DEV_SIGNATURE; - AtapiScsiPrivate->Handle = Controller; - - // - // will reset the IoPort inside each API function. - // - AtapiScsiPrivate->IoPort = gAtapiIoPortRegisters; - AtapiScsiPrivate->PciIo = PciIo; - - // - // initialize SCSI Pass Thru Protocol interface - // - AtapiScsiPrivate->ScsiPassThru.Mode = &AtapiScsiPrivate->ScsiPassThruMode; - AtapiScsiPrivate->ScsiPassThru.PassThru = AtapiScsiPassThruFunction; - AtapiScsiPrivate->ScsiPassThru.GetNextDevice = AtapiScsiPassThruGetNextDevice; - AtapiScsiPrivate->ScsiPassThru.BuildDevicePath = AtapiScsiPassThruBuildDevicePath; - AtapiScsiPrivate->ScsiPassThru.GetTargetLun = AtapiScsiPassThruGetTargetLun; - AtapiScsiPrivate->ScsiPassThru.ResetChannel = AtapiScsiPassThruResetChannel; - AtapiScsiPrivate->ScsiPassThru.ResetTarget = AtapiScsiPassThruResetTarget; - - // - // Set Mode - // - CopyMem (AtapiScsiPrivate->ControllerName, gControllerNameString, sizeof (gControllerNameString)); - - AtapiScsiPrivate->ScsiPassThruMode.ControllerName = AtapiScsiPrivate->ControllerName; - AtapiScsiPrivate->ScsiPassThruMode.ChannelName = AtapiScsiPrivate->ChannelName; - AtapiScsiPrivate->ScsiPassThruMode.AdapterId = 4; - // - // non-RAID SCSI controllers should set both physical and logical attributes - // - AtapiScsiPrivate->ScsiPassThruMode.Attributes = EFI_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL | - EFI_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL; - AtapiScsiPrivate->ScsiPassThruMode.IoAlign = 0; - - // - // Initialize the LatestTargetId to 0xFFFFFFFF (for the GetNextDevice() call). - // - AtapiScsiPrivate->LatestTargetId = 0xFFFFFFFF; - AtapiScsiPrivate->LatestLun = 0; - - Status = gBS->InstallProtocolInterface ( - &Controller, - &gEfiScsiPassThruProtocolGuid, - EFI_NATIVE_INTERFACE, - &AtapiScsiPrivate->ScsiPassThru - ); - return Status; -} - -/** - Implements EFI_SCSI_PASS_THRU_PROTOCOL.PassThru() function. - - @param This The EFI_SCSI_PASS_THRU_PROTOCOL instance. - @param Target The Target ID of the ATAPI device to send the SCSI - Request Packet. To ATAPI devices attached on an IDE - Channel, Target ID 0 indicates Master device;Target - ID 1 indicates Slave device. - @param Lun The LUN of the ATAPI device to send the SCSI Request - Packet. To the ATAPI device, Lun is always 0. - @param Packet The SCSI Request Packet to send to the ATAPI device - specified by Target and Lun. - @param Event If non-blocking I/O is not supported then Event is ignored, - and blocking I/O is performed.
- If Event is NULL, then blocking I/O is performed.
- If Event is not NULL and non blocking I/O is supported, - then non-blocking I/O is performed, and Event will be signaled - when the SCSI Request Packet completes. - - @todo This - add argument and description to function comment - @todo EFI_INVALID_PARAMETER - add return value to function comment - @todo EFI_SUCCESS - add return value to function comment -**/ -EFI_STATUS -EFIAPI -AtapiScsiPassThruFunction ( - IN EFI_SCSI_PASS_THRU_PROTOCOL *This, - IN UINT32 Target, - IN UINT64 Lun, - IN OUT EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet, - IN EFI_EVENT Event OPTIONAL - ) -{ - ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate; - EFI_STATUS Status; - - AtapiScsiPrivate = ATAPI_SCSI_PASS_THRU_DEV_FROM_THIS (This); - - // - // Target is not allowed beyond MAX_TARGET_ID - // - if (Target > MAX_TARGET_ID) { - return EFI_INVALID_PARAMETER; - } - - // - // check the data fields in Packet parameter. - // - Status = CheckSCSIRequestPacket (Packet); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // If Request Packet targets at the IDE channel itself, - // do nothing. - // - if (Target == This->Mode->AdapterId) { - Packet->TransferLength = 0; - return EFI_SUCCESS; - } - - // - // According to Target ID, reset the Atapi I/O Register mapping - // (Target Id in [0,1] area, using gAtapiIoPortRegisters[0], - // Target Id in [2,3] area, using gAtapiIoPortRegisters[1] - // - if ((Target / 2) == 0) { - AtapiScsiPrivate->IoPort = &gAtapiIoPortRegisters[0]; - } else { - AtapiScsiPrivate->IoPort = &gAtapiIoPortRegisters[1]; - } - - // - // the ATAPI SCSI interface does not support non-blocking I/O - // ignore the Event parameter - // - // Performs blocking I/O. - // - Status = SubmitBlockingIoCommand (AtapiScsiPrivate, Target, Packet); - return Status; -} - -/** - Used to retrieve the list of legal Target IDs for SCSI devices - on a SCSI channel. - - @param This Protocol instance pointer. - @param Target On input, a pointer to the Target ID of a SCSI - device present on the SCSI channel. On output, - a pointer to the Target ID of the next SCSI device - present on a SCSI channel. An input value of - 0xFFFFFFFF retrieves the Target ID of the first - SCSI device present on a SCSI channel. - @param Lun On input, a pointer to the LUN of a SCSI device - present on the SCSI channel. On output, a pointer - to the LUN of the next SCSI device present on - a SCSI channel. - - @retval EFI_SUCCESS The Target ID and Lun of the next SCSI device - on the SCSI channel was returned in Target and Lun. - @retval EFI_NOT_FOUND There are no more SCSI devices on this SCSI channel. - @retval EFI_INVALID_PARAMETER Target is not 0xFFFFFFFF,and Target and Lun were not - returned on a previous call to GetNextDevice(). - -**/ -EFI_STATUS -EFIAPI -AtapiScsiPassThruGetNextDevice ( - IN EFI_SCSI_PASS_THRU_PROTOCOL *This, - IN OUT UINT32 *Target, - IN OUT UINT64 *Lun - ) -{ - ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate; - - // - // Retrieve Device Private Data Structure. - // - AtapiScsiPrivate = ATAPI_SCSI_PASS_THRU_DEV_FROM_THIS (This); - - // - // Check whether Target is valid. - // - if (Target == NULL || Lun == NULL) { - return EFI_INVALID_PARAMETER; - } - - if ((*Target != 0xFFFFFFFF) && - ((*Target != AtapiScsiPrivate->LatestTargetId) || - (*Lun != AtapiScsiPrivate->LatestLun))) { - return EFI_INVALID_PARAMETER; - } - - if (*Target == MAX_TARGET_ID) { - return EFI_NOT_FOUND; - } - - if (*Target == 0xFFFFFFFF) { - *Target = 0; - } else { - *Target = AtapiScsiPrivate->LatestTargetId + 1; - } - - *Lun = 0; - - // - // Update the LatestTargetId. - // - AtapiScsiPrivate->LatestTargetId = *Target; - AtapiScsiPrivate->LatestLun = *Lun; - - return EFI_SUCCESS; - -} - -/** - Used to allocate and build a device path node for a SCSI device - on a SCSI channel. Would not build device path for a SCSI Host Controller. - - @param This Protocol instance pointer. - @param Target The Target ID of the SCSI device for which - a device path node is to be allocated and built. - @param Lun The LUN of the SCSI device for which a device - path node is to be allocated and built. - @param DevicePath A pointer to a single device path node that - describes the SCSI device specified by - Target and Lun. This function is responsible - for allocating the buffer DevicePath with the boot - service AllocatePool(). It is the caller's - responsibility to free DevicePath when the caller - is finished with DevicePath. - - @retval EFI_SUCCESS The device path node that describes the SCSI device - specified by Target and Lun was allocated and - returned in DevicePath. - @retval EFI_NOT_FOUND The SCSI devices specified by Target and Lun does - not exist on the SCSI channel. - @retval EFI_INVALID_PARAMETER DevicePath is NULL. - @retval EFI_OUT_OF_RESOURCES There are not enough resources to allocate - DevicePath. - -**/ -EFI_STATUS -EFIAPI -AtapiScsiPassThruBuildDevicePath ( - IN EFI_SCSI_PASS_THRU_PROTOCOL *This, - IN UINT32 Target, - IN UINT64 Lun, - IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath - ) -{ - EFI_DEV_PATH *Node; - - // - // Validate parameters passed in. - // - - if (DevicePath == NULL) { - return EFI_INVALID_PARAMETER; - } - - // - // can not build device path for the SCSI Host Controller. - // - if ((Target > (MAX_TARGET_ID - 1)) || (Lun != 0)) { - return EFI_NOT_FOUND; - } - - Node = AllocateZeroPool (sizeof (EFI_DEV_PATH)); - if (Node == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - Node->DevPath.Type = MESSAGING_DEVICE_PATH; - Node->DevPath.SubType = MSG_ATAPI_DP; - SetDevicePathNodeLength (&Node->DevPath, sizeof (ATAPI_DEVICE_PATH)); - - Node->Atapi.PrimarySecondary = (UINT8) (Target / 2); - Node->Atapi.SlaveMaster = (UINT8) (Target % 2); - Node->Atapi.Lun = (UINT16) Lun; - - *DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Node; - - return EFI_SUCCESS; -} - -/** - Used to translate a device path node to a Target ID and LUN. - - @param This Protocol instance pointer. - @param DevicePath A pointer to the device path node that - describes a SCSI device on the SCSI channel. - @param Target A pointer to the Target ID of a SCSI device - on the SCSI channel. - @param Lun A pointer to the LUN of a SCSI device on - the SCSI channel. - - @retval EFI_SUCCESS DevicePath was successfully translated to a - Target ID and LUN, and they were returned - in Target and Lun. - @retval EFI_INVALID_PARAMETER DevicePath is NULL. - @retval EFI_INVALID_PARAMETER Target is NULL. - @retval EFI_INVALID_PARAMETER Lun is NULL. - @retval EFI_UNSUPPORTED This driver does not support the device path - node type in DevicePath. - @retval EFI_NOT_FOUND A valid translation from DevicePath to a - Target ID and LUN does not exist. - -**/ -EFI_STATUS -EFIAPI -AtapiScsiPassThruGetTargetLun ( - IN EFI_SCSI_PASS_THRU_PROTOCOL *This, - IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, - OUT UINT32 *Target, - OUT UINT64 *Lun - ) -{ - EFI_DEV_PATH *Node; - - // - // Validate parameters passed in. - // - if (DevicePath == NULL || Target == NULL || Lun == NULL) { - return EFI_INVALID_PARAMETER; - } - - // - // Check whether the DevicePath belongs to SCSI_DEVICE_PATH - // - if ((DevicePath->Type != MESSAGING_DEVICE_PATH) || - (DevicePath->SubType != MSG_ATAPI_DP) || - (DevicePathNodeLength(DevicePath) != sizeof(ATAPI_DEVICE_PATH))) { - return EFI_UNSUPPORTED; - } - - Node = (EFI_DEV_PATH *) DevicePath; - - *Target = Node->Atapi.PrimarySecondary * 2 + Node->Atapi.SlaveMaster; - *Lun = Node->Atapi.Lun; - - if (*Target > (MAX_TARGET_ID - 1) || *Lun != 0) { - return EFI_NOT_FOUND; - } - - return EFI_SUCCESS; -} - -/** - Resets a SCSI channel.This operation resets all the - SCSI devices connected to the SCSI channel. - - @param This Protocol instance pointer. - - @retval EFI_SUCCESS The SCSI channel was reset. - @retval EFI_UNSUPPORTED The SCSI channel does not support - a channel reset operation. - @retval EFI_DEVICE_ERROR A device error occurred while - attempting to reset the SCSI channel. - @retval EFI_TIMEOUT A timeout occurred while attempting - to reset the SCSI channel. - -**/ -EFI_STATUS -EFIAPI -AtapiScsiPassThruResetChannel ( - IN EFI_SCSI_PASS_THRU_PROTOCOL *This - ) -{ - UINT8 DeviceControlValue; - ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate; - UINT8 Index; - - AtapiScsiPrivate = ATAPI_SCSI_PASS_THRU_DEV_FROM_THIS (This); - - // - // Reset both Primary channel and Secondary channel. - // so, the IoPort pointer must point to the right I/O Register group - // - for (Index = 0; Index < 2; Index++) { - // - // Reset - // - AtapiScsiPrivate->IoPort = &gAtapiIoPortRegisters[Index]; - - DeviceControlValue = 0; - // - // set SRST bit to initiate soft reset - // - DeviceControlValue |= SRST; - // - // disable Interrupt - // - DeviceControlValue |= bit (1); - WritePortB ( - AtapiScsiPrivate->PciIo, - AtapiScsiPrivate->IoPort->Alt.DeviceControl, - DeviceControlValue - ); - - // - // Wait 10us - // - gBS->Stall (10); - - // - // Clear SRST bit - // 0xfb:1111,1011 - // - DeviceControlValue &= 0xfb; - - WritePortB (AtapiScsiPrivate->PciIo, AtapiScsiPrivate->IoPort->Alt.DeviceControl, DeviceControlValue); - - // - // slave device needs at most 31s to clear BSY - // - if (StatusWaitForBSYClear (AtapiScsiPrivate, 31000) == EFI_TIMEOUT) { - return EFI_DEVICE_ERROR; - } - } - - return EFI_SUCCESS; -} - -/** - Resets a SCSI device that is connected to a SCSI channel. - - @param This Protocol instance pointer. - @param Target The Target ID of the SCSI device to reset. - @param Lun The LUN of the SCSI device to reset. - - @retval EFI_SUCCESS The SCSI device specified by Target and - Lun was reset. - @retval EFI_UNSUPPORTED The SCSI channel does not support a target - reset operation. - @retval EFI_INVALID_PARAMETER Target or Lun are invalid. - @retval EFI_DEVICE_ERROR A device error occurred while attempting - to reset the SCSI device specified by Target - and Lun. - @retval EFI_TIMEOUT A timeout occurred while attempting to reset - the SCSI device specified by Target and Lun. - -**/ -EFI_STATUS -EFIAPI -AtapiScsiPassThruResetTarget ( - IN EFI_SCSI_PASS_THRU_PROTOCOL *This, - IN UINT32 Target, - IN UINT64 Lun - ) -{ - ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate; - UINT8 Command; - UINT8 DeviceSelect; - - AtapiScsiPrivate = ATAPI_SCSI_PASS_THRU_DEV_FROM_THIS (This); - - if (Target > MAX_TARGET_ID) { - return EFI_INVALID_PARAMETER; - } - // - // Directly return EFI_SUCCESS if want to reset the host controller - // - if (Target == This->Mode->AdapterId) { - return EFI_SUCCESS; - } - - // - // According to Target ID, reset the Atapi I/O Register mapping - // (Target Id in [0,1] area, using gAtapiIoPortRegisters[0], - // Target Id in [2,3] area, using gAtapiIoPortRegisters[1] - // - if ((Target / 2) == 0) { - AtapiScsiPrivate->IoPort = &gAtapiIoPortRegisters[0]; - } else { - AtapiScsiPrivate->IoPort = &gAtapiIoPortRegisters[1]; - } - - // - // for ATAPI device, no need to wait DRDY ready after device selecting. - // - // bit7 and bit5 are both set to 1 for backward compatibility - // - DeviceSelect = (UINT8) (((bit (7) | bit (5)) | (Target << 4))); - WritePortB (AtapiScsiPrivate->PciIo, AtapiScsiPrivate->IoPort->Head, DeviceSelect); - - Command = ATAPI_SOFT_RESET_CMD; - WritePortB (AtapiScsiPrivate->PciIo, AtapiScsiPrivate->IoPort->Reg.Command, Command); - - // - // BSY clear is the only status return to the host by the device - // when reset is complete. - // slave device needs at most 31s to clear BSY - // - if (EFI_ERROR (StatusWaitForBSYClear (AtapiScsiPrivate, 31000))) { - return EFI_DEVICE_ERROR; - } - - // - // stall 5 seconds to make the device status stable - // - gBS->Stall (5000000); - - return EFI_SUCCESS; -} - - -/** - Checks the parameters in the SCSI Request Packet to make sure - they are valid for a SCSI Pass Thru request. - - @todo function comment is missing 'Routine Description:' - @todo function comment is missing 'Arguments:' - @todo function comment is missing 'Returns:' - @todo Packet - add argument and description to function comment - @todo EFI_INVALID_PARAMETER - add return value to function comment - @todo EFI_INVALID_PARAMETER - add return value to function comment - @todo EFI_INVALID_PARAMETER - add return value to function comment - @todo EFI_UNSUPPORTED - add return value to function comment - @todo EFI_SUCCESS - add return value to function comment -**/ -EFI_STATUS -CheckSCSIRequestPacket ( - EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet - ) -{ - if (Packet == NULL) { - return EFI_INVALID_PARAMETER; - } - - if (!ValidCdbLength (Packet->CdbLength)) { - return EFI_INVALID_PARAMETER; - } - - if (Packet->Cdb == NULL) { - return EFI_INVALID_PARAMETER; - } - - // - // Checks whether the request command is supported. - // - if (!IsCommandValid (Packet)) { - return EFI_UNSUPPORTED; - } - - return EFI_SUCCESS; -} - -/** - Checks the requested SCSI command: - Is it supported by this driver? - Is the Data transfer direction reasonable? - - @todo function comment is missing 'Routine Description:' - @todo function comment is missing 'Arguments:' - @todo function comment is missing 'Returns:' - @todo Packet - add argument and description to function comment -**/ -BOOLEAN -IsCommandValid ( - EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet - ) -{ - UINT8 Index; - UINT8 *OpCode; - - OpCode = (UINT8 *) (Packet->Cdb); - - for (Index = 0; CompareMem (&gSupportedATAPICommands[Index], &gEndTable, sizeof (SCSI_COMMAND_SET)); Index++) { - - if (*OpCode == gSupportedATAPICommands[Index].OpCode) { - // - // Check whether the requested Command is supported by this driver - // - if (Packet->DataDirection == DataIn) { - // - // Check whether the requested data direction conforms to - // what it should be. - // - if (gSupportedATAPICommands[Index].Direction == DataOut) { - return FALSE; - } - } - - if (Packet->DataDirection == DataOut) { - // - // Check whether the requested data direction conforms to - // what it should be. - // - if (gSupportedATAPICommands[Index].Direction == DataIn) { - return FALSE; - } - } - - return TRUE; - } - } - - return FALSE; -} - -/** - Performs blocking I/O request. - - @param AtapiScsiPrivate Private data structure for the specified channel. - @param Target The Target ID of the ATAPI device to send the SCSI - Request Packet. To ATAPI devices attached on an IDE - Channel, Target ID 0 indicates Master device;Target - ID 1 indicates Slave device. - @param Packet The SCSI Request Packet to send to the ATAPI device - specified by Target. - - @todo AtapiScsiPrivate - add argument and description to function comment -**/ -EFI_STATUS -SubmitBlockingIoCommand ( - ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, - UINT32 Target, - EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet - ) -{ - UINT8 PacketCommand[12]; - UINT64 TimeoutInMicroSeconds; - EFI_STATUS PacketCommandStatus; - - // - // Fill ATAPI Command Packet according to CDB - // - ZeroMem (&PacketCommand, 12); - CopyMem (&PacketCommand, Packet->Cdb, Packet->CdbLength); - - // - // Timeout is 100ns unit, convert it to 1000ns (1us) unit. - // - TimeoutInMicroSeconds = DivU64x32 (Packet->Timeout, (UINT32) 10); - - // - // Submit ATAPI Command Packet - // - PacketCommandStatus = AtapiPacketCommand ( - AtapiScsiPrivate, - Target, - PacketCommand, - Packet->DataBuffer, - &(Packet->TransferLength), - (DATA_DIRECTION) Packet->DataDirection, - TimeoutInMicroSeconds - ); - if (!EFI_ERROR (PacketCommandStatus) || (Packet->SenseData == NULL)) { - Packet->SenseDataLength = 0; - return PacketCommandStatus; - } - // - // Return SenseData if PacketCommandStatus matches - // the following return codes. - // - if ((PacketCommandStatus == EFI_WARN_BUFFER_TOO_SMALL) || - (PacketCommandStatus == EFI_DEVICE_ERROR) || - (PacketCommandStatus == EFI_TIMEOUT)) { - - // - // avoid submit request sense command continuously. - // - if (PacketCommand[0] == OP_REQUEST_SENSE) { - Packet->SenseDataLength = 0; - return PacketCommandStatus; - } - - RequestSenseCommand ( - AtapiScsiPrivate, - Target, - Packet->Timeout, - Packet->SenseData, - &Packet->SenseDataLength - ); - } - - return PacketCommandStatus; -} - -/** - RequestSenseCommand - - @param AtapiScsiPrivate - @param Target - @param Timeout - @param SenseData - @param SenseDataLength - - @todo Add function description - @todo AtapiScsiPrivate TODO: add argument description - @todo Target TODO: add argument description - @todo Timeout TODO: add argument description - @todo SenseData TODO: add argument description - @todo SenseDataLength TODO: add argument description - @todo add return values -**/ -EFI_STATUS -RequestSenseCommand ( - ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, - UINT32 Target, - UINT64 Timeout, - VOID *SenseData, - UINT8 *SenseDataLength - ) -{ - EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET Packet; - UINT8 Cdb[12]; - EFI_STATUS Status; - - ZeroMem (&Packet, sizeof (EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET)); - ZeroMem (Cdb, 12); - - Cdb[0] = OP_REQUEST_SENSE; - Cdb[4] = (UINT8) (*SenseDataLength); - - Packet.Timeout = Timeout; - Packet.DataBuffer = SenseData; - Packet.SenseData = NULL; - Packet.Cdb = Cdb; - Packet.TransferLength = *SenseDataLength; - Packet.CdbLength = 12; - Packet.DataDirection = DataIn; - - Status = SubmitBlockingIoCommand (AtapiScsiPrivate, Target, &Packet); - *SenseDataLength = (UINT8) (Packet.TransferLength); - return Status; -} - -/** - Submits ATAPI command packet to the specified ATAPI device. - - @param AtapiScsiPrivate: Private data structure for the specified channel. - @param Target: The Target ID of the ATAPI device to send the SCSI - Request Packet. To ATAPI devices attached on an IDE - Channel, Target ID 0 indicates Master device;Target - ID 1 indicates Slave device. - @param PacketCommand: Points to the ATAPI command packet. - @param Buffer: Points to the transferred data. - @param ByteCount: When input,indicates the buffer size; when output, - indicates the actually transferred data size. - @param Direction: Indicates the data transfer direction. - @param TimeoutInMicroSeconds: The timeout, in micro second units, - to use for the execution of this ATAPI command. - A TimeoutInMicroSeconds value of 0 means that - this function will wait indefinitely for the ATAPI - command to execute. -

- If TimeoutInMicroSeconds is greater than zero, then - this function will return EFI_TIMEOUT if the time - required to execute the ATAPI command is greater - than TimeoutInMicroSeconds. -

- - @todo AtapiScsiPrivate - add argument and description to function comment - @todo PacketCommand - add argument and description to function comment - @todo Buffer - add argument and description to function comment - @todo ByteCount - add argument and description to function comment - @todo Direction - add argument and description to function comment -**/ -EFI_STATUS -AtapiPacketCommand ( - ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, - UINT32 Target, - UINT8 *PacketCommand, - VOID *Buffer, - UINT32 *ByteCount, - DATA_DIRECTION Direction, - UINT64 TimeoutInMicroSeconds - ) -{ - - UINT16 *CommandIndex; - UINT8 Count; - EFI_STATUS Status; - - // - // Set all the command parameters by fill related registers. - // Before write to all the following registers, BSY and DRQ must be 0. - // - Status = StatusDRQClear (AtapiScsiPrivate, TimeoutInMicroSeconds); - if (EFI_ERROR (Status)) { - if (Status == EFI_ABORTED) { - Status = EFI_DEVICE_ERROR; - } - - *ByteCount = 0; - return Status; - } - // - // Select device via Device/Head Register. - // "Target = 0" indicates device 0; "Target = 1" indicates device 1 - // - WritePortB ( - AtapiScsiPrivate->PciIo, - AtapiScsiPrivate->IoPort->Head, - (UINT8) ((Target << 4) | DEFAULT_CMD) // DEFAULT_CMD: 0xa0 (1010,0000) - ); - - // - // No OVL; No DMA (by setting feature register) - // - WritePortB ( - AtapiScsiPrivate->PciIo, - AtapiScsiPrivate->IoPort->Reg1.Feature, - 0x00 - ); - - // - // set the transfersize to MAX_ATAPI_BYTE_COUNT to let the device - // determine how much data should be transfered. - // - WritePortB ( - AtapiScsiPrivate->PciIo, - AtapiScsiPrivate->IoPort->CylinderLsb, - (UINT8) (MAX_ATAPI_BYTE_COUNT & 0x00ff) - ); - WritePortB ( - AtapiScsiPrivate->PciIo, - AtapiScsiPrivate->IoPort->CylinderMsb, - (UINT8) (MAX_ATAPI_BYTE_COUNT >> 8) - ); - - // - // DEFAULT_CTL:0x0a (0000,1010) - // Disable interrupt - // - WritePortB ( - AtapiScsiPrivate->PciIo, - AtapiScsiPrivate->IoPort->Alt.DeviceControl, - DEFAULT_CTL - ); - - // - // Send Packet command to inform device - // that the following data bytes are command packet. - // - WritePortB ( - AtapiScsiPrivate->PciIo, - AtapiScsiPrivate->IoPort->Reg.Command, - PACKET_CMD - ); - - // - // Before data transfer, BSY should be 0 and DRQ should be 1. - // if they are not in specified time frame, - // retrieve Sense Key from Error Register before return. - // - Status = StatusDRQReady (AtapiScsiPrivate, TimeoutInMicroSeconds); - if (EFI_ERROR (Status)) { - if (Status == EFI_ABORTED) { - Status = EFI_DEVICE_ERROR; - } - - *ByteCount = 0; - return Status; - } - - // - // Send out command packet - // - CommandIndex = (UINT16 *) PacketCommand; - for (Count = 0; Count < 6; Count++, CommandIndex++) { - WritePortW (AtapiScsiPrivate->PciIo, AtapiScsiPrivate->IoPort->Data, *CommandIndex); - } - - // - // call AtapiPassThruPioReadWriteData() function to get - // requested transfer data form device. - // - return AtapiPassThruPioReadWriteData ( - AtapiScsiPrivate, - Buffer, - ByteCount, - Direction, - TimeoutInMicroSeconds - ); -} - -/** - Performs data transfer between ATAPI device and host after the - ATAPI command packet is sent. - - @param AtapiScsiPrivate: Private data structure for the specified channel. - @param Buffer: Points to the transferred data. - @param ByteCount: When input,indicates the buffer size; when output, - indicates the actually transferred data size. - @param Direction: Indicates the data transfer direction. - @param TimeoutInMicroSeconds: The timeout, in micro second units, - to use for the execution of this ATAPI command. - A TimeoutInMicroSeconds value of 0 means that - this function will wait indefinitely for the ATAPI - command to execute. -

- If TimeoutInMicroSeconds is greater than zero, then - this function will return EFI_TIMEOUT if the time - required to execute the ATAPI command is greater - than TimeoutInMicroSeconds. -

- - @todo AtapiScsiPrivate - add argument and description to function comment - @todo Buffer - add argument and description to function comment - @todo ByteCount - add argument and description to function comment - @todo Direction - add argument and description to function comment - @todo EFI_DEVICE_ERROR - add return value to function comment - @todo EFI_DEVICE_ERROR - add return value to function comment - @todo EFI_WARN_BUFFER_TOO_SMALL - add return value to function comment -**/ -EFI_STATUS -AtapiPassThruPioReadWriteData ( - ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, - UINT16 *Buffer, - UINT32 *ByteCount, - DATA_DIRECTION Direction, - UINT64 TimeoutInMicroSeconds - ) -{ - UINT32 Index; - UINT32 RequiredWordCount; - UINT32 ActualWordCount; - - UINT32 WordCount; - EFI_STATUS Status; - UINT16 *ptrBuffer; - - Status = EFI_SUCCESS; - - // - // Non Data transfer request is also supported. - // - if (*ByteCount == 0 || Buffer == NULL) { - *ByteCount = 0; - if (EFI_ERROR (StatusWaitForBSYClear (AtapiScsiPrivate, TimeoutInMicroSeconds))) { - return EFI_DEVICE_ERROR; - } - } - - ptrBuffer = Buffer; - RequiredWordCount = *ByteCount / 2; - - // - // ActuralWordCount means the word count of data really transfered. - // - ActualWordCount = 0; - - while (ActualWordCount < RequiredWordCount) { - // - // before each data transfer stream, the host should poll DRQ bit ready, - // which indicates device's ready for data transfer . - // - Status = StatusDRQReady (AtapiScsiPrivate, TimeoutInMicroSeconds); - if (EFI_ERROR (Status)) { - *ByteCount = ActualWordCount * 2; - - AtapiPassThruCheckErrorStatus (AtapiScsiPrivate); - - if (ActualWordCount == 0) { - return EFI_DEVICE_ERROR; - } - // - // ActualWordCount > 0 - // - if (ActualWordCount < RequiredWordCount) { - return EFI_WARN_BUFFER_TOO_SMALL; - } - } - // - // get current data transfer size from Cylinder Registers. - // - WordCount = ReadPortB (AtapiScsiPrivate->PciIo, AtapiScsiPrivate->IoPort->CylinderMsb) << 8; - WordCount = WordCount | ReadPortB (AtapiScsiPrivate->PciIo, AtapiScsiPrivate->IoPort->CylinderLsb); - WordCount = WordCount & 0xffff; - WordCount /= 2; - - // - // perform a series data In/Out. - // - for (Index = 0; (Index < WordCount) && (ActualWordCount < RequiredWordCount); Index++, ActualWordCount++) { - - if (Direction == DataIn) { - - *ptrBuffer = ReadPortW (AtapiScsiPrivate->PciIo, AtapiScsiPrivate->IoPort->Data); - } else { - - WritePortW (AtapiScsiPrivate->PciIo, AtapiScsiPrivate->IoPort->Data, *ptrBuffer); - } - - ptrBuffer++; - - } - } - // - // After data transfer is completed, normally, DRQ bit should clear. - // - StatusDRQClear (AtapiScsiPrivate, TimeoutInMicroSeconds); - - // - // read status register to check whether error happens. - // - Status = AtapiPassThruCheckErrorStatus (AtapiScsiPrivate); - - *ByteCount = ActualWordCount * 2; - - return Status; -} - - -/** - Read one byte from a specified I/O port. - - @todo function comment is missing 'Routine Description:' - @todo function comment is missing 'Arguments:' - @todo function comment is missing 'Returns:' - @todo PciIo - add argument and description to function comment - @todo Port - add argument and description to function comment -**/ -UINT8 -ReadPortB ( - IN EFI_PCI_IO_PROTOCOL *PciIo, - IN UINT16 Port - ) -{ - UINT8 Data; - - Data = 0; - PciIo->Io.Read ( - PciIo, - EfiPciIoWidthUint8, - EFI_PCI_IO_PASS_THROUGH_BAR, - (UINT64) Port, - 1, - &Data - ); - return Data; -} - - -/** - Read one word from a specified I/O port. - - @todo function comment is missing 'Routine Description:' - @todo function comment is missing 'Arguments:' - @todo function comment is missing 'Returns:' - @todo PciIo - add argument and description to function comment - @todo Port - add argument and description to function comment -**/ -UINT16 -ReadPortW ( - IN EFI_PCI_IO_PROTOCOL *PciIo, - IN UINT16 Port - ) -{ - UINT16 Data; - - Data = 0; - PciIo->Io.Read ( - PciIo, - EfiPciIoWidthUint16, - EFI_PCI_IO_PASS_THROUGH_BAR, - (UINT64) Port, - 1, - &Data - ); - return Data; -} - - -/** - Write one byte to a specified I/O port. - - @todo function comment is missing 'Routine Description:' - @todo function comment is missing 'Arguments:' - @todo function comment is missing 'Returns:' - @todo PciIo - add argument and description to function comment - @todo Port - add argument and description to function comment - @todo Data - add argument and description to function comment -**/ -VOID -WritePortB ( - IN EFI_PCI_IO_PROTOCOL *PciIo, - IN UINT16 Port, - IN UINT8 Data - ) -{ - - PciIo->Io.Write ( - PciIo, - EfiPciIoWidthUint8, - EFI_PCI_IO_PASS_THROUGH_BAR, - (UINT64) Port, - 1, - &Data - ); - -} - - -/** - Write one word to a specified I/O port. - - @todo function comment is missing 'Routine Description:' - @todo function comment is missing 'Arguments:' - @todo function comment is missing 'Returns:' - @todo PciIo - add argument and description to function comment - @todo Port - add argument and description to function comment - @todo Data - add argument and description to function comment -**/ -VOID -WritePortW ( - IN EFI_PCI_IO_PROTOCOL *PciIo, - IN UINT16 Port, - IN UINT16 Data - ) -{ - - PciIo->Io.Write ( - PciIo, - EfiPciIoWidthUint16, - EFI_PCI_IO_PASS_THROUGH_BAR, - (UINT64) Port, - 1, - &Data - ); -} - -/** - Check whether DRQ is clear in the Status Register. (BSY must also be cleared) - If TimeoutInMicroSeconds is zero, this routine should wait infinitely for - DRQ clear. Otherwise, it will return EFI_TIMEOUT when specified time is - elapsed. - - @todo function comment is missing 'Routine Description:' - @todo function comment is missing 'Arguments:' - @todo function comment is missing 'Returns:' - @todo AtapiScsiPrivate - add argument and description to function comment - @todo TimeoutInMicroSeconds - add argument and description to function comment - @todo EFI_ABORTED - add return value to function comment - @todo EFI_TIMEOUT - add return value to function comment - @todo EFI_SUCCESS - add return value to function comment -**/ -EFI_STATUS -StatusDRQClear ( - ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, - UINT64 TimeoutInMicroSeconds - ) -{ - UINT64 Delay; - UINT8 StatusRegister; - UINT8 ErrRegister; - - if (TimeoutInMicroSeconds == 0) { - Delay = 2; - } else { - Delay = DivU64x32 (TimeoutInMicroSeconds, (UINT32) 30) + 1; - } - - do { - - StatusRegister = ReadPortB ( - AtapiScsiPrivate->PciIo, - AtapiScsiPrivate->IoPort->Reg.Status - ); - - // - // wait for BSY == 0 and DRQ == 0 - // - if ((StatusRegister & (DRQ | BSY)) == 0) { - break; - } - // - // check whether the command is aborted by the device - // - if ((StatusRegister & (BSY | ERR)) == ERR) { - - ErrRegister = ReadPortB ( - AtapiScsiPrivate->PciIo, - AtapiScsiPrivate->IoPort->Reg1.Error - ); - if ((ErrRegister & ABRT_ERR) == ABRT_ERR) { - - return EFI_ABORTED; - } - } - // - // Stall for 30 us - // - gBS->Stall (30); - - // - // Loop infinitely if not meeting expected condition - // - if (TimeoutInMicroSeconds == 0) { - Delay = 2; - } - - Delay--; - } while (Delay); - - if (Delay == 0) { - return EFI_TIMEOUT; - } - - return EFI_SUCCESS; -} - -/** - Check whether DRQ is clear in the Alternate Status Register. - (BSY must also be cleared). - If TimeoutInMicroSeconds is zero, this routine should wait infinitely for - DRQ clear. Otherwise, it will return EFI_TIMEOUT when specified time is - elapsed. - - @todo function comment is missing 'Routine Description:' - @todo function comment is missing 'Arguments:' - @todo function comment is missing 'Returns:' - @todo AtapiScsiPrivate - add argument and description to function comment - @todo TimeoutInMicroSeconds - add argument and description to function comment - @todo EFI_ABORTED - add return value to function comment - @todo EFI_TIMEOUT - add return value to function comment - @todo EFI_SUCCESS - add return value to function comment -**/ -EFI_STATUS -AltStatusDRQClear ( - ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, - UINT64 TimeoutInMicroSeconds - ) -{ - UINT64 Delay; - UINT8 AltStatusRegister; - UINT8 ErrRegister; - - if (TimeoutInMicroSeconds == 0) { - Delay = 2; - } else { - Delay = DivU64x32 (TimeoutInMicroSeconds, (UINT32) 30) + 1; - } - - do { - - AltStatusRegister = ReadPortB ( - AtapiScsiPrivate->PciIo, - AtapiScsiPrivate->IoPort->Alt.AltStatus - ); - - // - // wait for BSY == 0 and DRQ == 0 - // - if ((AltStatusRegister & (DRQ | BSY)) == 0) { - break; - } - - if ((AltStatusRegister & (BSY | ERR)) == ERR) { - - ErrRegister = ReadPortB ( - AtapiScsiPrivate->PciIo, - AtapiScsiPrivate->IoPort->Reg1.Error - ); - if ((ErrRegister & ABRT_ERR) == ABRT_ERR) { - - return EFI_ABORTED; - } - } - // - // Stall for 30 us - // - gBS->Stall (30); - - // - // Loop infinitely if not meeting expected condition - // - if (TimeoutInMicroSeconds == 0) { - Delay = 2; - } - - Delay--; - } while (Delay); - - if (Delay == 0) { - return EFI_TIMEOUT; - } - - return EFI_SUCCESS; -} - -/** - Check whether DRQ is ready in the Status Register. (BSY must also be cleared) - If TimeoutInMicroSeconds is zero, this routine should wait infinitely for - DRQ ready. Otherwise, it will return EFI_TIMEOUT when specified time is - elapsed. - - @todo function comment is missing 'Routine Description:' - @todo function comment is missing 'Arguments:' - @todo function comment is missing 'Returns:' - @todo AtapiScsiPrivate - add argument and description to function comment - @todo TimeoutInMicroSeconds - add argument and description to function comment - @todo EFI_ABORTED - add return value to function comment - @todo EFI_TIMEOUT - add return value to function comment - @todo EFI_SUCCESS - add return value to function comment -**/ -EFI_STATUS -StatusDRQReady ( - ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, - UINT64 TimeoutInMicroSeconds - ) -{ - UINT64 Delay; - UINT8 StatusRegister; - UINT8 ErrRegister; - - if (TimeoutInMicroSeconds == 0) { - Delay = 2; - } else { - Delay = DivU64x32 (TimeoutInMicroSeconds, (UINT32) 30) + 1; - } - - do { - // - // read Status Register will clear interrupt - // - StatusRegister = ReadPortB ( - AtapiScsiPrivate->PciIo, - AtapiScsiPrivate->IoPort->Reg.Status - ); - - // - // BSY==0,DRQ==1 - // - if ((StatusRegister & (BSY | DRQ)) == DRQ) { - break; - } - - if ((StatusRegister & (BSY | ERR)) == ERR) { - - ErrRegister = ReadPortB ( - AtapiScsiPrivate->PciIo, - AtapiScsiPrivate->IoPort->Reg1.Error - ); - if ((ErrRegister & ABRT_ERR) == ABRT_ERR) { - return EFI_ABORTED; - } - } - - // - // Stall for 30 us - // - gBS->Stall (30); - - // - // Loop infinitely if not meeting expected condition - // - if (TimeoutInMicroSeconds == 0) { - Delay = 2; - } - - Delay--; - } while (Delay); - - if (Delay == 0) { - return EFI_TIMEOUT; - } - - return EFI_SUCCESS; -} - -/** - Check whether DRQ is ready in the Alternate Status Register. - (BSY must also be cleared) - If TimeoutInMicroSeconds is zero, this routine should wait infinitely for - DRQ ready. Otherwise, it will return EFI_TIMEOUT when specified time is - elapsed. - - @todo function comment is missing 'Routine Description:' - @todo function comment is missing 'Arguments:' - @todo function comment is missing 'Returns:' - @todo AtapiScsiPrivate - add argument and description to function comment - @todo TimeoutInMicroSeconds - add argument and description to function comment - @todo EFI_ABORTED - add return value to function comment - @todo EFI_TIMEOUT - add return value to function comment - @todo EFI_SUCCESS - add return value to function comment -**/ -EFI_STATUS -AltStatusDRQReady ( - ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, - UINT64 TimeoutInMicroSeconds - ) -{ - UINT64 Delay; - UINT8 AltStatusRegister; - UINT8 ErrRegister; - - if (TimeoutInMicroSeconds == 0) { - Delay = 2; - } else { - Delay = DivU64x32 (TimeoutInMicroSeconds, (UINT32) 30) + 1; - } - - do { - // - // read Status Register will clear interrupt - // - AltStatusRegister = ReadPortB ( - AtapiScsiPrivate->PciIo, - AtapiScsiPrivate->IoPort->Alt.AltStatus - ); - // - // BSY==0,DRQ==1 - // - if ((AltStatusRegister & (BSY | DRQ)) == DRQ) { - break; - } - - if ((AltStatusRegister & (BSY | ERR)) == ERR) { - - ErrRegister = ReadPortB ( - AtapiScsiPrivate->PciIo, - AtapiScsiPrivate->IoPort->Reg1.Error - ); - if ((ErrRegister & ABRT_ERR) == ABRT_ERR) { - return EFI_ABORTED; - } - } - - // - // Stall for 30 us - // - gBS->Stall (30); - - // - // Loop infinitely if not meeting expected condition - // - if (TimeoutInMicroSeconds == 0) { - Delay = 2; - } - - Delay--; - } while (Delay); - - if (Delay == 0) { - return EFI_TIMEOUT; - } - - return EFI_SUCCESS; -} - -/** - Check whether BSY is clear in the Status Register. - If TimeoutInMicroSeconds is zero, this routine should wait infinitely for - BSY clear. Otherwise, it will return EFI_TIMEOUT when specified time is - elapsed. - - @todo function comment is missing 'Routine Description:' - @todo function comment is missing 'Arguments:' - @todo function comment is missing 'Returns:' - @todo AtapiScsiPrivate - add argument and description to function comment - @todo TimeoutInMicroSeconds - add argument and description to function comment - @todo EFI_TIMEOUT - add return value to function comment - @todo EFI_SUCCESS - add return value to function comment -**/ -EFI_STATUS -StatusWaitForBSYClear ( - ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, - UINT64 TimeoutInMicroSeconds - ) -{ - UINT64 Delay; - UINT8 StatusRegister; - - if (TimeoutInMicroSeconds == 0) { - Delay = 2; - } else { - Delay = DivU64x32 (TimeoutInMicroSeconds, (UINT32) 30) + 1; - } - - do { - - StatusRegister = ReadPortB ( - AtapiScsiPrivate->PciIo, - AtapiScsiPrivate->IoPort->Reg.Status - ); - if ((StatusRegister & BSY) == 0x00) { - break; - } - - // - // Stall for 30 us - // - gBS->Stall (30); - - // - // Loop infinitely if not meeting expected condition - // - if (TimeoutInMicroSeconds == 0) { - Delay = 2; - } - - Delay--; - } while (Delay); - - if (Delay == 0) { - return EFI_TIMEOUT; - } - - return EFI_SUCCESS; -} - -/** - Check whether BSY is clear in the Alternate Status Register. - If TimeoutInMicroSeconds is zero, this routine should wait infinitely for - BSY clear. Otherwise, it will return EFI_TIMEOUT when specified time is - elapsed. - - @todo function comment is missing 'Routine Description:' - @todo function comment is missing 'Arguments:' - @todo function comment is missing 'Returns:' - @todo AtapiScsiPrivate - add argument and description to function comment - @todo TimeoutInMicroSeconds - add argument and description to function comment - @todo EFI_TIMEOUT - add return value to function comment - @todo EFI_SUCCESS - add return value to function comment -**/ -EFI_STATUS -AltStatusWaitForBSYClear ( - ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, - UINT64 TimeoutInMicroSeconds - ) -{ - UINT64 Delay; - UINT8 AltStatusRegister; - - if (TimeoutInMicroSeconds == 0) { - Delay = 2; - } else { - Delay = DivU64x32 (TimeoutInMicroSeconds, (UINT32) 30) + 1; - } - - do { - - AltStatusRegister = ReadPortB ( - AtapiScsiPrivate->PciIo, - AtapiScsiPrivate->IoPort->Alt.AltStatus - ); - if ((AltStatusRegister & BSY) == 0x00) { - break; - } - - // - // Stall for 30 us - // - gBS->Stall (30); - // - // Loop infinitely if not meeting expected condition - // - if (TimeoutInMicroSeconds == 0) { - Delay = 2; - } - - Delay--; - } while (Delay); - - if (Delay == 0) { - return EFI_TIMEOUT; - } - - return EFI_SUCCESS; -} - -/** - Check whether DRDY is ready in the Status Register. - (BSY must also be cleared) - If TimeoutInMicroSeconds is zero, this routine should wait infinitely for - DRDY ready. Otherwise, it will return EFI_TIMEOUT when specified time is - elapsed. - - @todo function comment is missing 'Routine Description:' - @todo function comment is missing 'Arguments:' - @todo function comment is missing 'Returns:' - @todo AtapiScsiPrivate - add argument and description to function comment - @todo TimeoutInMicroSeconds - add argument and description to function comment - @todo EFI_ABORTED - add return value to function comment - @todo EFI_TIMEOUT - add return value to function comment - @todo EFI_SUCCESS - add return value to function comment -**/ -EFI_STATUS -StatusDRDYReady ( - ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, - UINT64 TimeoutInMicroSeconds - ) -{ - UINT64 Delay; - UINT8 StatusRegister; - UINT8 ErrRegister; - - if (TimeoutInMicroSeconds == 0) { - Delay = 2; - } else { - Delay = DivU64x32 (TimeoutInMicroSeconds, (UINT32) 30) + 1; - } - - do { - StatusRegister = ReadPortB ( - AtapiScsiPrivate->PciIo, - AtapiScsiPrivate->IoPort->Reg.Status - ); - // - // BSY == 0 , DRDY == 1 - // - if ((StatusRegister & (DRDY | BSY)) == DRDY) { - break; - } - - if ((StatusRegister & (BSY | ERR)) == ERR) { - - ErrRegister = ReadPortB ( - AtapiScsiPrivate->PciIo, - AtapiScsiPrivate->IoPort->Reg1.Error - ); - if ((ErrRegister & ABRT_ERR) == ABRT_ERR) { - return EFI_ABORTED; - } - } - - // - // Stall for 30 us - // - gBS->Stall (30); - // - // Loop infinitely if not meeting expected condition - // - if (TimeoutInMicroSeconds == 0) { - Delay = 2; - } - - Delay--; - } while (Delay); - - if (Delay == 0) { - return EFI_TIMEOUT; - } - - return EFI_SUCCESS; -} - -/** - Check whether DRDY is ready in the Alternate Status Register. - (BSY must also be cleared) - If TimeoutInMicroSeconds is zero, this routine should wait infinitely for - DRDY ready. Otherwise, it will return EFI_TIMEOUT when specified time is - elapsed. - - @todo function comment is missing 'Routine Description:' - @todo function comment is missing 'Arguments:' - @todo function comment is missing 'Returns:' - @todo AtapiScsiPrivate - add argument and description to function comment - @todo TimeoutInMicroSeconds - add argument and description to function comment - @todo EFI_ABORTED - add return value to function comment - @todo EFI_TIMEOUT - add return value to function comment - @todo EFI_SUCCESS - add return value to function comment -**/ -EFI_STATUS -AltStatusDRDYReady ( - ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, - UINT64 TimeoutInMicroSeconds - ) -{ - UINT64 Delay; - UINT8 AltStatusRegister; - UINT8 ErrRegister; - - if (TimeoutInMicroSeconds == 0) { - Delay = 2; - } else { - Delay = DivU64x32 (TimeoutInMicroSeconds, (UINT32) 30) + 1; - } - - do { - AltStatusRegister = ReadPortB ( - AtapiScsiPrivate->PciIo, - AtapiScsiPrivate->IoPort->Alt.AltStatus - ); - // - // BSY == 0 , DRDY == 1 - // - if ((AltStatusRegister & (DRDY | BSY)) == DRDY) { - break; - } - - if ((AltStatusRegister & (BSY | ERR)) == ERR) { - - ErrRegister = ReadPortB ( - AtapiScsiPrivate->PciIo, - AtapiScsiPrivate->IoPort->Reg1.Error - ); - if ((ErrRegister & ABRT_ERR) == ABRT_ERR) { - return EFI_ABORTED; - } - } - - // - // Stall for 30 us - // - gBS->Stall (30); - // - // Loop infinitely if not meeting expected condition - // - if (TimeoutInMicroSeconds == 0) { - Delay = 2; - } - - Delay--; - } while (Delay); - - if (Delay == 0) { - return EFI_TIMEOUT; - } - - return EFI_SUCCESS; -} - -/** - Check Error Register for Error Information. - - @todo function comment is missing 'Routine Description:' - @todo function comment is missing 'Arguments:' - @todo function comment is missing 'Returns:' - @todo AtapiScsiPrivate - add argument and description to function comment - @todo EFI_SUCCESS - add return value to function comment - @todo EFI_DEVICE_ERROR - add return value to function comment -**/ -EFI_STATUS -AtapiPassThruCheckErrorStatus ( - ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate - ) -{ - UINT8 StatusRegister; - UINT8 ErrorRegister; - - StatusRegister = ReadPortB ( - AtapiScsiPrivate->PciIo, - AtapiScsiPrivate->IoPort->Reg.Status - ); - - DEBUG_CODE_BEGIN (); - - if (StatusRegister & DWF) { - DEBUG ( - (EFI_D_BLKIO, - "AtapiPassThruCheckErrorStatus()-- %02x : Error : Write Fault\n", - StatusRegister) - ); - } - - if (StatusRegister & CORR) { - DEBUG ( - (EFI_D_BLKIO, - "AtapiPassThruCheckErrorStatus()-- %02x : Error : Corrected Data\n", - StatusRegister) - ); - } - - if (StatusRegister & ERR) { - ErrorRegister = ReadPortB (AtapiScsiPrivate->PciIo, AtapiScsiPrivate->IoPort->Reg1.Error); - - - if (ErrorRegister & BBK_ERR) { - DEBUG ( - (EFI_D_BLKIO, - "AtapiPassThruCheckErrorStatus()-- %02x : Error : Bad Block Detected\n", - ErrorRegister) - ); - } - - if (ErrorRegister & UNC_ERR) { - DEBUG ( - (EFI_D_BLKIO, - "AtapiPassThruCheckErrorStatus()-- %02x : Error : Uncorrectable Data\n", - ErrorRegister) - ); - } - - if (ErrorRegister & MC_ERR) { - DEBUG ( - (EFI_D_BLKIO, - "AtapiPassThruCheckErrorStatus()-- %02x : Error : Media Change\n", - ErrorRegister) - ); - } - - if (ErrorRegister & ABRT_ERR) { - DEBUG ( - (EFI_D_BLKIO, - "AtapiPassThruCheckErrorStatus()-- %02x : Error : Abort\n", - ErrorRegister) - ); - } - - if (ErrorRegister & TK0NF_ERR) { - DEBUG ( - (EFI_D_BLKIO, - "AtapiPassThruCheckErrorStatus()-- %02x : Error : Track 0 Not Found\n", - ErrorRegister) - ); - } - - if (ErrorRegister & AMNF_ERR) { - DEBUG ( - (EFI_D_BLKIO, - "AtapiPassThruCheckErrorStatus()-- %02x : Error : Address Mark Not Found\n", - ErrorRegister) - ); - } - } - - DEBUG_CODE_END (); - - if ((StatusRegister & (ERR | DWF | CORR)) == 0) { - return EFI_SUCCESS; - } - - - return EFI_DEVICE_ERROR; -} - -/** - The user Entry Point for module AtapiPassThru. The user code starts with this function. - - @param[in] ImageHandle The firmware allocated handle for the EFI image. - @param[in] SystemTable A pointer to the EFI System Table. - - @retval EFI_SUCCESS The entry point is executed successfully. - @retval other Some error occurs when executing this entry point. - -**/ -EFI_STATUS -EFIAPI -InitializeAtapiPassThru( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - // - // Install driver model protocol(s). - // - Status = EfiLibInstallAllDriverProtocols ( - ImageHandle, - SystemTable, - &gAtapiScsiPassThruDriverBinding, - ImageHandle, - &gAtapiScsiPassThruComponentName, - NULL, - NULL - ); - ASSERT_EFI_ERROR (Status); - - return Status; -} diff --git a/MdeModulePkg/Bus/Pci/AtapiPassThru/Dxe/AtapiPassThru.h b/MdeModulePkg/Bus/Pci/AtapiPassThru/Dxe/AtapiPassThru.h deleted file mode 100644 index 49b97a821f..0000000000 --- a/MdeModulePkg/Bus/Pci/AtapiPassThru/Dxe/AtapiPassThru.h +++ /dev/null @@ -1,833 +0,0 @@ -/** @file - Copyright (c) 2006, Intel Corporation - All rights reserved. This program and the accompanying materials - are licensed and made available under the terms and conditions of the BSD License - which accompanies this distribution. The full text of the license may be found at - http://opensource.org/licenses/bsd-license.php - - THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, - WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - - Module Name: AtapiPassThru.h - -**/ - -#ifndef _APT_H -#define _APT_H - - -// -// The package level header files this module uses -// -#include -// -// The protocols, PPI and GUID defintions for this module -// -#include -#include -// -// The Library classes this module consumes -// -#include -#include -#include -#include -#include -#include -#include -#include - -/// -/// bit definition -/// -#define bit(a) (1 << (a)) - -#define MAX_TARGET_ID 4 - -// -// IDE Registers -// -typedef union { - UINT16 Command; /* when write */ - UINT16 Status; /* when read */ -} IDE_CMD_OR_STATUS; - -typedef union { - UINT16 Error; /* when read */ - UINT16 Feature; /* when write */ -} IDE_ERROR_OR_FEATURE; - -typedef union { - UINT16 AltStatus; /* when read */ - UINT16 DeviceControl; /* when write */ -} IDE_AltStatus_OR_DeviceControl; - -/// -/// IDE registers set -/// -typedef struct { - UINT16 Data; - IDE_ERROR_OR_FEATURE Reg1; - UINT16 SectorCount; - UINT16 SectorNumber; - UINT16 CylinderLsb; - UINT16 CylinderMsb; - UINT16 Head; - IDE_CMD_OR_STATUS Reg; - - IDE_AltStatus_OR_DeviceControl Alt; - UINT16 DriveAddress; - - UINT16 MasterSlave; -} IDE_BASE_REGISTERS; - -#define ATAPI_SCSI_PASS_THRU_DEV_SIGNATURE EFI_SIGNATURE_32 ('a', 's', 'p', 't') - -typedef struct { - UINTN Signature; - - EFI_HANDLE Handle; - EFI_SCSI_PASS_THRU_PROTOCOL ScsiPassThru; - EFI_SCSI_PASS_THRU_MODE ScsiPassThruMode; - EFI_PCI_IO_PROTOCOL *PciIo; - - // - // Local Data goes here - // - IDE_BASE_REGISTERS *IoPort; - - CHAR16 ControllerName[100]; - CHAR16 ChannelName[100]; - - UINT32 LatestTargetId; - UINT64 LatestLun; - -} ATAPI_SCSI_PASS_THRU_DEV; - -#define ATAPI_SCSI_PASS_THRU_DEV_FROM_THIS(a) \ - CR (a, \ - ATAPI_SCSI_PASS_THRU_DEV, \ - ScsiPassThru, \ - ATAPI_SCSI_PASS_THRU_DEV_SIGNATURE \ - ) - -// -// Global Variables -// -extern EFI_DRIVER_BINDING_PROTOCOL gAtapiScsiPassThruDriverBinding; -extern EFI_COMPONENT_NAME_PROTOCOL gAtapiScsiPassThruComponentName; - -// -// ATAPI Command op code -// -#define OP_INQUIRY 0x12 -#define OP_LOAD_UNLOAD_CD 0xa6 -#define OP_MECHANISM_STATUS 0xbd -#define OP_MODE_SELECT_10 0x55 -#define OP_MODE_SENSE_10 0x5a -#define OP_PAUSE_RESUME 0x4b -#define OP_PLAY_AUDIO_10 0x45 -#define OP_PLAY_AUDIO_MSF 0x47 -#define OP_PLAY_CD 0xbc -#define OP_PLAY_CD_MSF 0xb4 -#define OP_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e -#define OP_READ_10 0x28 -#define OP_READ_12 0xa8 -#define OP_READ_CAPACITY 0x25 -#define OP_READ_CD 0xbe -#define OP_READ_CD_MSF 0xb9 -#define OP_READ_HEADER 0x44 -#define OP_READ_SUB_CHANNEL 0x42 -#define OP_READ_TOC 0x43 -#define OP_REQUEST_SENSE 0x03 -#define OP_SCAN 0xba -#define OP_SEEK_10 0x2b -#define OP_SET_CD_SPEED 0xbb -#define OP_STOPPLAY_SCAN 0x4e -#define OP_START_STOP_UNIT 0x1b -#define OP_TEST_UNIT_READY 0x00 - -#define OP_FORMAT_UNIT 0x04 -#define OP_READ_FORMAT_CAPACITIES 0x23 -#define OP_VERIFY 0x2f -#define OP_WRITE_10 0x2a -#define OP_WRITE_12 0xaa -#define OP_WRITE_AND_VERIFY 0x2e - -// -// ATA Command -// -#define ATAPI_SOFT_RESET_CMD 0x08 - -typedef enum { - DataIn = 0, - DataOut = 1, - NoData = 2, - End = 0xff -} DATA_DIRECTION; - -typedef struct { - UINT8 OpCode; - DATA_DIRECTION Direction; -} SCSI_COMMAND_SET; - -#define MAX_CHANNEL 2 - -#define ValidCdbLength(Len) ((Len) == 6 || (Len) == 10 || (Len) == 12) ? 1 : 0 - -// -// IDE registers bit definitions -// -// ATA Err Reg bitmap -// -#define BBK_ERR bit (7) ///< Bad block detected -#define UNC_ERR bit (6) ///< Uncorrectable Data -#define MC_ERR bit (5) ///< Media Change -#define IDNF_ERR bit (4) ///< ID Not Found -#define MCR_ERR bit (3) ///< Media Change Requested -#define ABRT_ERR bit (2) ///< Aborted Command -#define TK0NF_ERR bit (1) ///< Track 0 Not Found -#define AMNF_ERR bit (0) ///< Address Mark Not Found - -// -// ATAPI Err Reg bitmap -// -#define SENSE_KEY_ERR (bit (7) | bit (6) | bit (5) | bit (4)) -#define EOM_ERR bit (1) ///< End of Media Detected -#define ILI_ERR bit (0) ///< Illegal Length Indication - -// -// Device/Head Reg -// -#define LBA_MODE bit (6) -#define DEV bit (4) -#define HS3 bit (3) -#define HS2 bit (2) -#define HS1 bit (1) -#define HS0 bit (0) -#define CHS_MODE (0) -#define DRV0 (0) -#define DRV1 (1) -#define MST_DRV DRV0 -#define SLV_DRV DRV1 - -// -// Status Reg -// -#define BSY bit (7) ///< Controller Busy -#define DRDY bit (6) ///< Drive Ready -#define DWF bit (5) ///< Drive Write Fault -#define DSC bit (4) ///< Disk Seek Complete -#define DRQ bit (3) ///< Data Request -#define CORR bit (2) ///< Corrected Data -#define IDX bit (1) ///< Index -#define ERR bit (0) ///< Error -#define CHECK bit (0) ///< Check bit for ATAPI Status Reg - -// -// Device Control Reg -// -#define SRST bit (2) ///< Software Reset -#define IEN_L bit (1) ///< Interrupt Enable - -// -// ATAPI Feature Register -// -#define OVERLAP bit (1) -#define DMA bit (0) - -// -// ATAPI Interrupt Reason Reson Reg (ATA Sector Count Register) -// -#define RELEASE bit (2) -#define IO bit (1) -#define CoD bit (0) - -#define PACKET_CMD 0xA0 - -#define DEFAULT_CMD (0xa0) -// -// default content of device control register, disable INT -// -#define DEFAULT_CTL (0x0a) -#define MAX_ATAPI_BYTE_COUNT (0xfffe) - -// -// function prototype -// - -EFI_STATUS -EFIAPI -AtapiScsiPassThruDriverBindingSupported ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ); - -EFI_STATUS -EFIAPI -AtapiScsiPassThruDriverBindingStart ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ); - -EFI_STATUS -EFIAPI -AtapiScsiPassThruDriverBindingStop ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN UINTN NumberOfChildren, - IN EFI_HANDLE *ChildHandleBuffer - ); - -// -// EFI Component Name Functions -// -EFI_STATUS -EFIAPI -AtapiScsiPassThruComponentNameGetDriverName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN CHAR8 *Language, - OUT CHAR16 **DriverName - ); - -EFI_STATUS -EFIAPI -AtapiScsiPassThruComponentNameGetControllerName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle OPTIONAL, - IN CHAR8 *Language, - OUT CHAR16 **ControllerName - ); - -/** - AtapiScsiPassThruDriverEntryPoint - - @param ImageHandle - @param SystemTable - - @todo Add function description - @todo ImageHandle - add argument description - @todo SystemTable - add argument description - @todo add return values ---*/ -EFI_STATUS -EFIAPI -AtapiScsiPassThruDriverEntryPoint ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -; - -/** - RegisterAtapiScsiPassThru - - @param This - @param Controller - @param PciIo - - @todo Add function description - @todo This add argument description - @todo Controller add argument description - @todo PciIo add argument description - @todo add return values -**/ -EFI_STATUS -RegisterAtapiScsiPassThru ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_PCI_IO_PROTOCOL *PciIo - ) -; - -/** - AtapiScsiPassThruFunction - - @param This - @param Target - @param Lun - @param Packet - @param Event - - @todo Add function description - @todo This - add argument description - @todo Target - add argument description - @todo Lun - add argument description - @todo Packet - add argument description - @todo Event - add argument description - @todo add return values -**/ -EFI_STATUS -EFIAPI -AtapiScsiPassThruFunction ( - IN EFI_SCSI_PASS_THRU_PROTOCOL *This, - IN UINT32 Target, - IN UINT64 Lun, - IN OUT EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet, - IN EFI_EVENT Event OPTIONAL - ) -; - -/** - AtapiScsiPassThruGetNextDevice - - TODO: Add function description - - @param This TODO: add argument description - @param Target TODO: add argument description - @param Lun TODO: add argument description - - TODO: add return values - -**/ -EFI_STATUS -EFIAPI -AtapiScsiPassThruGetNextDevice ( - IN EFI_SCSI_PASS_THRU_PROTOCOL *This, - IN OUT UINT32 *Target, - IN OUT UINT64 *Lun - ) -; - -/** - AtapiScsiPassThruBuildDevicePath - - TODO: Add function description - - @param This TODO: add argument description - @param Target TODO: add argument description - @param Lun TODO: add argument description - @param DevicePath TODO: add argument description - - TODO: add return values - -**/ -EFI_STATUS -EFIAPI -AtapiScsiPassThruBuildDevicePath ( - IN EFI_SCSI_PASS_THRU_PROTOCOL *This, - IN UINT32 Target, - IN UINT64 Lun, - IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath - ) -; - -/** - AtapiScsiPassThruGetTargetLun - - TODO: Add function description - - @param This TODO: add argument description - @param DevicePath TODO: add argument description - @param Target TODO: add argument description - @param Lun TODO: add argument description - - TODO: add return values - -**/ -EFI_STATUS -EFIAPI -AtapiScsiPassThruGetTargetLun ( - IN EFI_SCSI_PASS_THRU_PROTOCOL *This, - IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, - OUT UINT32 *Target, - OUT UINT64 *Lun - ) -; - -/** - AtapiScsiPassThruResetChannel - - TODO: Add function description - - @param This TODO: add argument description - - TODO: add return values - -**/ -EFI_STATUS -EFIAPI -AtapiScsiPassThruResetChannel ( - IN EFI_SCSI_PASS_THRU_PROTOCOL *This - ) -; - -/** - AtapiScsiPassThruResetTarget - - TODO: Add function description - - @param This TODO: add argument description - @param Target TODO: add argument description - @param Lun TODO: add argument description - - TODO: add return values - -**/ -EFI_STATUS -EFIAPI -AtapiScsiPassThruResetTarget ( - IN EFI_SCSI_PASS_THRU_PROTOCOL *This, - IN UINT32 Target, - IN UINT64 Lun - ) -; - -/** - CheckSCSIRequestPacket - - TODO: Add function description - - @param Packet TODO: add argument description - - TODO: add return values - -**/ -EFI_STATUS -CheckSCSIRequestPacket ( - EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet - ) -; - -/** - SubmitBlockingIoCommand - - TODO: Add function description - - @param AtapiScsiPrivate TODO: add argument description - @param Target TODO: add argument description - @param Packet TODO: add argument description - - TODO: add return values - -**/ -EFI_STATUS -SubmitBlockingIoCommand ( - ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, - UINT32 Target, - EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet - ) -; - -/** - IsCommandValid - - TODO: Add function description - - @param Packet - TODO: add argument description - - @return TODO: add return values - ---*/ -BOOLEAN -IsCommandValid ( - EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet - ) -; - -/** - RequestSenseCommand - - TODO: Add function description - - @param AtapiScsiPrivate TODO: add argument description - @param Target TODO: add argument description - @param Timeout TODO: add argument description - @param SenseData TODO: add argument description - @param SenseDataLength TODO: add argument description - - TODO: add return values - -**/ -EFI_STATUS -RequestSenseCommand ( - ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, - UINT32 Target, - UINT64 Timeout, - VOID *SenseData, - UINT8 *SenseDataLength - ) -; - -/** - AtapiPacketCommand - - TODO: Add function description - - @param AtapiScsiPrivate TODO: add argument description - @param Target TODO: add argument description - @param PacketCommand TODO: add argument description - @param Buffer TODO: add argument description - @param ByteCount TODO: add argument description - @param Direction TODO: add argument description - @param TimeOutInMicroSeconds TODO: add argument description - - TODO: add return values - -**/ -EFI_STATUS -AtapiPacketCommand ( - ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, - UINT32 Target, - UINT8 *PacketCommand, - VOID *Buffer, - UINT32 *ByteCount, - DATA_DIRECTION Direction, - UINT64 TimeOutInMicroSeconds - ) -; - - -/** - ReadPortB - - TODO: Add function description - - @param PciIo TODO: add argument description - @param Port TODO: add argument description - - TODO: add return values - -**/ -UINT8 -ReadPortB ( - IN EFI_PCI_IO_PROTOCOL *PciIo, - IN UINT16 Port - ) -; - - -/** - ReadPortW - - TODO: Add function description - - @param PciIo TODO: add argument description - @param Port TODO: add argument description - - TODO: add return values - -**/ -UINT16 -ReadPortW ( - IN EFI_PCI_IO_PROTOCOL *PciIo, - IN UINT16 Port - ) -; - - -/** - WritePortB - - TODO: Add function description - - @param PciIo TODO: add argument description - @param Port TODO: add argument description - @param Data TODO: add argument description - - TODO: add return values - -**/ -VOID -WritePortB ( - IN EFI_PCI_IO_PROTOCOL *PciIo, - IN UINT16 Port, - IN UINT8 Data - ) -; - - -/** - WritePortW - - TODO: Add function description - - @param PciIo TODO: add argument description - @param Port TODO: add argument description - @param Data TODO: add argument description - - TODO: add return values - -**/ -VOID -WritePortW ( - IN EFI_PCI_IO_PROTOCOL *PciIo, - IN UINT16 Port, - IN UINT16 Data - ) -; - -/** - StatusDRQClear - - TODO: Add function description - - @param AtapiScsiPrivate TODO: add argument description - @param TimeOutInMicroSeconds TODO: add argument description - - TODO: add return values - -**/ -EFI_STATUS -StatusDRQClear ( - ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, - UINT64 TimeOutInMicroSeconds - ) -; - -/** - AltStatusDRQClear - - TODO: Add function description - - @param AtapiScsiPrivate TODO: add argument description - @param TimeOutInMicroSeconds TODO: add argument description - - TODO: add return values - -**/ -EFI_STATUS -AltStatusDRQClear ( - ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, - UINT64 TimeOutInMicroSeconds - ) -; - -/** - StatusDRQReady - - TODO: Add function description - - @param AtapiScsiPrivate TODO: add argument description - @param TimeOutInMicroSeconds TODO: add argument description - - TODO: add return values - -**/ -EFI_STATUS -StatusDRQReady ( - ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, - UINT64 TimeOutInMicroSeconds - ) -; - -/** - AltStatusDRQReady - - TODO: Add function description - - @param AtapiScsiPrivate TODO: add argument description - @param TimeOutInMicroSeconds TODO: add argument description - - TODO: add return values - -**/ -EFI_STATUS -AltStatusDRQReady ( - ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, - UINT64 TimeOutInMicroSeconds - ) -; - -/** - TODO: Add function description - - @param AtapiScsiPrivate TODO: add argument description - @param TimeoutInMicroSeconds TODO: add argument description - - TODO: add return values - -**/ -EFI_STATUS -StatusWaitForBSYClear ( - ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, - UINT64 TimeoutInMicroSeconds - ) -; - -/** - TODO: Add function description - - @param AtapiScsiPrivate TODO: add argument description - @param TimeoutInMicroSeconds TODO: add argument description - - TODO: add return values - -**/ -EFI_STATUS -AltStatusWaitForBSYClear ( - ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, - UINT64 TimeoutInMicroSeconds - ) -; - -/** - TODO: Add function description - - @param AtapiScsiPrivate TODO: add argument description - @param TimeoutInMicroSeconds TODO: add argument description - - TODO: add return values - -**/ -EFI_STATUS -StatusDRDYReady ( - ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, - UINT64 TimeoutInMicroSeconds - ) -; - -/** - TODO: Add function description - - @param AtapiScsiPrivate TODO: add argument description - @param TimeoutInMicroSeconds TODO: add argument description - - TODO: add return values - -**/ -EFI_STATUS -AltStatusDRDYReady ( - ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, - UINT64 TimeoutInMicroSeconds - ) -; - -/** - TODO: Add function description - - @param AtapiScsiPrivate TODO: add argument description - @param Buffer TODO: add argument description - @param ByteCount TODO: add argument description - @param Direction TODO: add argument description - @param TimeOutInMicroSeconds TODO: add argument description - - TODO: add return values - -**/ -EFI_STATUS -AtapiPassThruPioReadWriteData ( - ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, - UINT16 *Buffer, - UINT32 *ByteCount, - DATA_DIRECTION Direction, - UINT64 TimeOutInMicroSeconds - ) -; - -/** - TODO: Add function description - - @param AtapiScsiPrivate TODO: add argument description - - TODO: add return values - -**/ -EFI_STATUS -AtapiPassThruCheckErrorStatus ( - ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate - ) -; -#endif diff --git a/MdeModulePkg/Bus/Pci/AtapiPassThru/Dxe/AtapiPassThru.inf b/MdeModulePkg/Bus/Pci/AtapiPassThru/Dxe/AtapiPassThru.inf deleted file mode 100644 index d449723358..0000000000 --- a/MdeModulePkg/Bus/Pci/AtapiPassThru/Dxe/AtapiPassThru.inf +++ /dev/null @@ -1,93 +0,0 @@ -#/** @file -# Description file for the Atapi Passthru component. -# -# This driver simulates SCSI devices with Atapi devices to test the SCSI io -# protocol. -# Copyright (c) 2006 - 2007, Intel Corporation -# -# All rights reserved. This program and the accompanying materials -# are licensed and made available under the terms and conditions of the BSD License -# which accompanies this distribution. The full text of the license may be found at -# http://opensource.org/licenses/bsd-license.php -# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. -# -# -#**/ - -################################################################################ -# -# Defines Section - statements that will be processed to create a Makefile. -# -################################################################################ -[Defines] - INF_VERSION = 0x00010005 - BASE_NAME = AtapiPassThru - FILE_GUID = E49061CE-99A7-41d3-AB3A-36E5CFBAD63E - MODULE_TYPE = UEFI_DRIVER - VERSION_STRING = 1.0 - EDK_RELEASE_VERSION = 0x00020000 - EFI_SPECIFICATION_VERSION = 0x00020000 - - ENTRY_POINT = InitializeAtapiPassThru - -# -# The following information is for reference only and not required by the build tools. -# -# VALID_ARCHITECTURES = IA32 X64 IPF EBC -# -# DRIVER_BINDING = gAtapiScsiPassThruDriverBinding -# COMPONENT_NAME = gAtapiScsiPassThruComponentName -# - -################################################################################ -# -# Sources Section - list of files that are required for the build to succeed. -# -################################################################################ - -[Sources.common] - ComponentName.c - AtapiPassThru.c - AtapiPassThru.h - - -################################################################################ -# -# Package Dependency Section - list of Package files that are required for -# this module. -# -################################################################################ - -[Packages] - MdePkg/MdePkg.dec - - -################################################################################ -# -# Library Class Section - list of Library Classes that are required for -# this module. -# -################################################################################ - -[LibraryClasses] - UefiBootServicesTableLib - MemoryAllocationLib - BaseMemoryLib - UefiLib - BaseLib - UefiDriverEntryPoint - DebugLib - - -################################################################################ -# -# Protocol C Name Section - list of Protocol and Protocol Notify C Names -# that this module uses or produces. -# -################################################################################ - -[Protocols] - gEfiScsiPassThruProtocolGuid # PROTOCOL BY_START - gEfiPciIoProtocolGuid # PROTOCOL TO_START - diff --git a/MdeModulePkg/Bus/Pci/AtapiPassThru/Dxe/AtapiPassThru.msa b/MdeModulePkg/Bus/Pci/AtapiPassThru/Dxe/AtapiPassThru.msa deleted file mode 100644 index b33cb93326..0000000000 --- a/MdeModulePkg/Bus/Pci/AtapiPassThru/Dxe/AtapiPassThru.msa +++ /dev/null @@ -1,72 +0,0 @@ - - - - AtapiPassThru - UEFI_DRIVER - E49061CE-99A7-41d3-AB3A-36E5CFBAD63E - 1.0 - Description file for the Atapi Passthru component. - This driver simulates SCSI devices with Atapi devices to test the SCSI io - protocol. - Copyright (c) 2006 - 2007, Intel Corporation - All rights reserved. This program and the accompanying materials - are licensed and made available under the terms and conditions of the BSD License - which accompanies this distribution. The full text of the license may be found at - http://opensource.org/licenses/bsd-license.php - THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, - WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052 - - - IA32 X64 IPF EBC - false - AtapiPassThru - - - - DebugLib - - - UefiDriverEntryPoint - - - BaseLib - - - UefiLib - - - BaseMemoryLib - - - MemoryAllocationLib - - - UefiBootServicesTableLib - - - - AtapiPassThru.h - AtapiPassThru.c - ComponentName.c - - - - - - - gEfiPciIoProtocolGuid - - - gEfiScsiPassThruProtocolGuid - - - - EFI_SPECIFICATION_VERSION 0x00020000 - EDK_RELEASE_VERSION 0x00020000 - - gAtapiScsiPassThruDriverBinding - gAtapiScsiPassThruComponentName - - - diff --git a/MdeModulePkg/Bus/Pci/AtapiPassThru/Dxe/ComponentName.c b/MdeModulePkg/Bus/Pci/AtapiPassThru/Dxe/ComponentName.c deleted file mode 100644 index 1731571069..0000000000 --- a/MdeModulePkg/Bus/Pci/AtapiPassThru/Dxe/ComponentName.c +++ /dev/null @@ -1,120 +0,0 @@ -/** @file - Copyright (c) 2006, Intel Corporation - All rights reserved. This program and the accompanying materials - are licensed and made available under the terms and conditions of the BSD License - which accompanies this distribution. The full text of the license may be found at - http://opensource.org/licenses/bsd-license.php - - THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, - WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - - Module Name: ComponentName.c - -**/ -#include "AtapiPassThru.h" - -/// -/// EFI Component Name Protocol -/// -EFI_COMPONENT_NAME_PROTOCOL gAtapiScsiPassThruComponentName = { - AtapiScsiPassThruComponentNameGetDriverName, - AtapiScsiPassThruComponentNameGetControllerName, - "eng" -}; - -static EFI_UNICODE_STRING_TABLE mAtapiScsiPassThruDriverNameTable[] = { - { "eng", (CHAR16 *) L"ATAPI SCSI Pass Thru Driver" }, - { NULL , NULL } -}; - -/** - Retrieves a Unicode string that is the user readable name of the EFI Driver. - - @param This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. - @param Language A pointer to a three character ISO 639-2 language identifier. - This is the language of the driver name that that the caller - is requesting, and it must match one of the languages specified - in SupportedLanguages. The number of languages supported by a - driver is up to the driver writer. - @param DriverName A pointer to the Unicode string to return. This Unicode string - is the name of the driver specified by This in the language - specified by Language. - - @retval EFI_SUCCESS The Unicode string for the Driver specified by This - and the language specified by Language was returned - in DriverName. - @retval EFI_INVALID_PARAMETER Language is NULL. - @retval EFI_INVALID_PARAMETER DriverName is NULL. - @retval EFI_UNSUPPORTED The driver specified by This does not support the - language specified by Language. - -**/ -EFI_STATUS -EFIAPI -AtapiScsiPassThruComponentNameGetDriverName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN CHAR8 *Language, - OUT CHAR16 **DriverName - ) -{ - return LookupUnicodeString ( - Language, - gAtapiScsiPassThruComponentName.SupportedLanguages, - mAtapiScsiPassThruDriverNameTable, - DriverName - ); -} - -/** - Retrieves a Unicode string that is the user readable name of the controller - that is being managed by an EFI Driver. - - @param This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. - @param ControllerHandle The handle of a controller that the driver specified by - This is managing. This handle specifies the controller - whose name is to be returned. - @param ChildHandle The handle of the child controller to retrieve the name - of. This is an optional parameter that may be NULL. It - will be NULL for device drivers. It will also be NULL - for a bus drivers that wish to retrieve the name of the - bus controller. It will not be NULL for a bus driver - that wishes to retrieve the name of a child controller. - @param Language A pointer to a three character ISO 639-2 language - identifier. This is the language of the controller name - that that the caller is requesting, and it must match one - of the languages specified in SupportedLanguages. The - number of languages supported by a driver is up to the - driver writer. - @param ControllerName A pointer to the Unicode string to return. This Unicode - string is the name of the controller specified by - ControllerHandle and ChildHandle in the language - specified by Language from the point of view of the - driver specified by This. - - @retval EFI_SUCCESS The Unicode string for the user readable name in the - language specified by Language for the driver - specified by This was returned in DriverName. - @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. - @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid - EFI_HANDLE. - @retval EFI_INVALID_PARAMETER Language is NULL. - @retval EFI_INVALID_PARAMETER ControllerName is NULL. - @retval EFI_UNSUPPORTED The driver specified by This is not currently - managing the controller specified by - ControllerHandle and ChildHandle. - @retval EFI_UNSUPPORTED The driver specified by This does not support the - language specified by Language. - -**/ -EFI_STATUS -EFIAPI -AtapiScsiPassThruComponentNameGetControllerName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle OPTIONAL, - IN CHAR8 *Language, - OUT CHAR16 **ControllerName - ) -{ - return EFI_UNSUPPORTED; -} diff --git a/MdeModulePkg/Bus/Pci/AtapiPassThruDxe/AtapiPassThru.c b/MdeModulePkg/Bus/Pci/AtapiPassThruDxe/AtapiPassThru.c new file mode 100644 index 0000000000..f14d9e3482 --- /dev/null +++ b/MdeModulePkg/Bus/Pci/AtapiPassThruDxe/AtapiPassThru.c @@ -0,0 +1,2177 @@ +/** @file + Copyright (c) 2006, Intel Corporation + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "AtapiPassThru.h" + +/// +/// IDE registers' fixed address +/// +static IDE_BASE_REGISTERS gAtapiIoPortRegisters[2] = { + { 0x1f0, { 0x1f1 }, 0x1f2, 0x1f3, 0x1f4, 0x1f5, 0x1f6, { 0x1f7 }, { 0x3f6 }, 0x3f7, 0 }, + { 0x170, { 0x171 }, 0x172, 0x173, 0x174, 0x175, 0x176, { 0x177 }, { 0x376 }, 0x377, 0 } +}; + +static SCSI_COMMAND_SET gEndTable = { 0xff, (DATA_DIRECTION) 0xff }; + +/// +/// This table contains all the supported ATAPI commands. +/// +static SCSI_COMMAND_SET gSupportedATAPICommands[] = { + { OP_INQUIRY, DataIn }, + { OP_LOAD_UNLOAD_CD, NoData }, + { OP_MECHANISM_STATUS, DataIn }, + { OP_MODE_SELECT_10, DataOut }, + { OP_MODE_SENSE_10, DataIn }, + { OP_PAUSE_RESUME, NoData }, + { OP_PLAY_AUDIO_10, DataIn }, + { OP_PLAY_AUDIO_MSF, DataIn }, + { OP_PLAY_CD, DataIn }, + { OP_PLAY_CD_MSF, DataIn }, + { OP_PREVENT_ALLOW_MEDIUM_REMOVAL,NoData }, + { OP_READ_10, DataIn }, + { OP_READ_12, DataIn }, + { OP_READ_CAPACITY, DataIn }, + { OP_READ_CD, DataIn }, + { OP_READ_CD_MSF, DataIn }, + { OP_READ_HEADER, DataIn }, + { OP_READ_SUB_CHANNEL, DataIn }, + { OP_READ_TOC, DataIn }, + { OP_REQUEST_SENSE, DataIn }, + { OP_SCAN, NoData }, + { OP_SEEK_10, NoData }, + { OP_SET_CD_SPEED, DataOut }, + { OP_STOPPLAY_SCAN, NoData }, + { OP_START_STOP_UNIT, NoData }, + { OP_TEST_UNIT_READY, NoData }, + { OP_FORMAT_UNIT, DataOut }, + { OP_READ_FORMAT_CAPACITIES, DataIn }, + { OP_VERIFY, DataOut }, + { OP_WRITE_10, DataOut }, + { OP_WRITE_12, DataOut }, + { OP_WRITE_AND_VERIFY, DataOut }, + { 0xff, (DATA_DIRECTION) 0xff } +}; + +static CHAR16 *gControllerNameString = (CHAR16 *) L"ATAPI Controller"; +static CHAR16 *gAtapiChannelString = (CHAR16 *) L"ATAPI Channel"; + +EFI_DRIVER_BINDING_PROTOCOL gAtapiScsiPassThruDriverBinding = { + AtapiScsiPassThruDriverBindingSupported, + AtapiScsiPassThruDriverBindingStart, + AtapiScsiPassThruDriverBindingStop, + 0xa, + NULL, + NULL +}; + +/** + Supported. + + (Standard DriverBinding Protocol Supported() function) + + @return EFI_STATUS + + @todo This - add argument and description to function comment + @todo Controller - add argument and description to function comment + @todo RemainingDevicePath - add argument and description to function comment + @todo EFI_UNSUPPORTED - add return value to function comment +**/ +EFI_STATUS +EFIAPI +AtapiScsiPassThruDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + PCI_TYPE00 Pci; + + // + // Open the IO Abstraction(s) needed to perform the supported test + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Use the PCI I/O Protocol to see if Controller is a IDE Controller that + // can be managed by this driver. Read the PCI Configuration Header + // for this device. + // + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, + sizeof (Pci) / sizeof (UINT32), + &Pci + ); + if (EFI_ERROR (Status)) { + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + return EFI_UNSUPPORTED; + } + + if (Pci.Hdr.ClassCode[2] != PCI_CLASS_MASS_STORAGE || Pci.Hdr.ClassCode[1] != PCI_CLASS_IDE) { + + Status = EFI_UNSUPPORTED; + } + + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return Status; +} + +/** + Create handles for IDE channels specified by RemainingDevicePath. + Install SCSI Pass Thru Protocol onto each created handle. + + (Standard DriverBinding Protocol Start() function) + + @return EFI_STATUS + + @todo This - add argument and description to function comment + @todo Controller - add argument and description to function comment + @todo RemainingDevicePath - add argument and description to function comment +**/ +EFI_STATUS +EFIAPI +AtapiScsiPassThruDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + + PciIo = NULL; + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationEnable, + EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO | EFI_PCI_DEVICE_ENABLE, + NULL + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + // + // Create SCSI Pass Thru instance for the IDE channel. + // + Status = RegisterAtapiScsiPassThru (This, Controller, PciIo); + +Done: + if (EFI_ERROR (Status)) { + if (PciIo) { + PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationDisable, + EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO | EFI_PCI_DEVICE_ENABLE, + NULL + ); + } + + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + } + + return Status; +} + +/** + Stop. + + (Standard DriverBinding Protocol Stop() function) + + @return EFI_STATUS + + @todo This - add argument and description to function comment + @todo Controller - add argument and description to function comment + @todo NumberOfChildren - add argument and description to function comment + @todo ChildHandleBuffer - add argument and description to function comment + @todo EFI_SUCCESS - add return value to function comment +**/ +EFI_STATUS +EFIAPI +AtapiScsiPassThruDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +{ + EFI_STATUS Status; + EFI_SCSI_PASS_THRU_PROTOCOL *ScsiPassThru; + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate; + + Status = gBS->OpenProtocol ( + Controller, + &gEfiScsiPassThruProtocolGuid, + (VOID **) &ScsiPassThru, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + AtapiScsiPrivate = ATAPI_SCSI_PASS_THRU_DEV_FROM_THIS (ScsiPassThru); + + Status = gBS->UninstallProtocolInterface ( + Controller, + &gEfiScsiPassThruProtocolGuid, + &AtapiScsiPrivate->ScsiPassThru + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Release Pci Io protocol on the controller handle. + // + AtapiScsiPrivate->PciIo->Attributes ( + AtapiScsiPrivate->PciIo, + EfiPciIoAttributeOperationDisable, + EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO | EFI_PCI_DEVICE_ENABLE, + NULL + ); + + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + gBS->FreePool (AtapiScsiPrivate); + + return EFI_SUCCESS; +} + +/** + Attaches SCSI Pass Thru Protocol for specified IDE channel. + + @param Controller: Parent device handle to the IDE channel. + @param PciIo: PCI I/O protocol attached on the "Controller". + + @return EFI_SUCCESS Always returned unless installing SCSI Pass Thru Protocol failed. + + @todo This - add argument and description to function comment + @todo Controller - add argument and description to function comment + @todo PciIo - add argument and description to function comment + @todo EFI_OUT_OF_RESOURCES - add return value to function comment +**/ +EFI_STATUS +RegisterAtapiScsiPassThru ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_PCI_IO_PROTOCOL *PciIo + ) +{ + EFI_STATUS Status; + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate; + UINT64 Attributes; + + AtapiScsiPrivate = AllocateZeroPool (sizeof (ATAPI_SCSI_PASS_THRU_DEV)); + if (AtapiScsiPrivate == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Attributes = EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO | EFI_PCI_DEVICE_ENABLE; + CopyMem (AtapiScsiPrivate->ChannelName, gAtapiChannelString, sizeof (gAtapiChannelString)); + + // + // Enable channel + // + PciIo->Attributes (PciIo, EfiPciIoAttributeOperationSet, Attributes, NULL); + + AtapiScsiPrivate->Signature = ATAPI_SCSI_PASS_THRU_DEV_SIGNATURE; + AtapiScsiPrivate->Handle = Controller; + + // + // will reset the IoPort inside each API function. + // + AtapiScsiPrivate->IoPort = gAtapiIoPortRegisters; + AtapiScsiPrivate->PciIo = PciIo; + + // + // initialize SCSI Pass Thru Protocol interface + // + AtapiScsiPrivate->ScsiPassThru.Mode = &AtapiScsiPrivate->ScsiPassThruMode; + AtapiScsiPrivate->ScsiPassThru.PassThru = AtapiScsiPassThruFunction; + AtapiScsiPrivate->ScsiPassThru.GetNextDevice = AtapiScsiPassThruGetNextDevice; + AtapiScsiPrivate->ScsiPassThru.BuildDevicePath = AtapiScsiPassThruBuildDevicePath; + AtapiScsiPrivate->ScsiPassThru.GetTargetLun = AtapiScsiPassThruGetTargetLun; + AtapiScsiPrivate->ScsiPassThru.ResetChannel = AtapiScsiPassThruResetChannel; + AtapiScsiPrivate->ScsiPassThru.ResetTarget = AtapiScsiPassThruResetTarget; + + // + // Set Mode + // + CopyMem (AtapiScsiPrivate->ControllerName, gControllerNameString, sizeof (gControllerNameString)); + + AtapiScsiPrivate->ScsiPassThruMode.ControllerName = AtapiScsiPrivate->ControllerName; + AtapiScsiPrivate->ScsiPassThruMode.ChannelName = AtapiScsiPrivate->ChannelName; + AtapiScsiPrivate->ScsiPassThruMode.AdapterId = 4; + // + // non-RAID SCSI controllers should set both physical and logical attributes + // + AtapiScsiPrivate->ScsiPassThruMode.Attributes = EFI_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL | + EFI_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL; + AtapiScsiPrivate->ScsiPassThruMode.IoAlign = 0; + + // + // Initialize the LatestTargetId to 0xFFFFFFFF (for the GetNextDevice() call). + // + AtapiScsiPrivate->LatestTargetId = 0xFFFFFFFF; + AtapiScsiPrivate->LatestLun = 0; + + Status = gBS->InstallProtocolInterface ( + &Controller, + &gEfiScsiPassThruProtocolGuid, + EFI_NATIVE_INTERFACE, + &AtapiScsiPrivate->ScsiPassThru + ); + return Status; +} + +/** + Implements EFI_SCSI_PASS_THRU_PROTOCOL.PassThru() function. + + @param This The EFI_SCSI_PASS_THRU_PROTOCOL instance. + @param Target The Target ID of the ATAPI device to send the SCSI + Request Packet. To ATAPI devices attached on an IDE + Channel, Target ID 0 indicates Master device;Target + ID 1 indicates Slave device. + @param Lun The LUN of the ATAPI device to send the SCSI Request + Packet. To the ATAPI device, Lun is always 0. + @param Packet The SCSI Request Packet to send to the ATAPI device + specified by Target and Lun. + @param Event If non-blocking I/O is not supported then Event is ignored, + and blocking I/O is performed.
+ If Event is NULL, then blocking I/O is performed.
+ If Event is not NULL and non blocking I/O is supported, + then non-blocking I/O is performed, and Event will be signaled + when the SCSI Request Packet completes. + + @todo This - add argument and description to function comment + @todo EFI_INVALID_PARAMETER - add return value to function comment + @todo EFI_SUCCESS - add return value to function comment +**/ +EFI_STATUS +EFIAPI +AtapiScsiPassThruFunction ( + IN EFI_SCSI_PASS_THRU_PROTOCOL *This, + IN UINT32 Target, + IN UINT64 Lun, + IN OUT EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet, + IN EFI_EVENT Event OPTIONAL + ) +{ + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate; + EFI_STATUS Status; + + AtapiScsiPrivate = ATAPI_SCSI_PASS_THRU_DEV_FROM_THIS (This); + + // + // Target is not allowed beyond MAX_TARGET_ID + // + if (Target > MAX_TARGET_ID) { + return EFI_INVALID_PARAMETER; + } + + // + // check the data fields in Packet parameter. + // + Status = CheckSCSIRequestPacket (Packet); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // If Request Packet targets at the IDE channel itself, + // do nothing. + // + if (Target == This->Mode->AdapterId) { + Packet->TransferLength = 0; + return EFI_SUCCESS; + } + + // + // According to Target ID, reset the Atapi I/O Register mapping + // (Target Id in [0,1] area, using gAtapiIoPortRegisters[0], + // Target Id in [2,3] area, using gAtapiIoPortRegisters[1] + // + if ((Target / 2) == 0) { + AtapiScsiPrivate->IoPort = &gAtapiIoPortRegisters[0]; + } else { + AtapiScsiPrivate->IoPort = &gAtapiIoPortRegisters[1]; + } + + // + // the ATAPI SCSI interface does not support non-blocking I/O + // ignore the Event parameter + // + // Performs blocking I/O. + // + Status = SubmitBlockingIoCommand (AtapiScsiPrivate, Target, Packet); + return Status; +} + +/** + Used to retrieve the list of legal Target IDs for SCSI devices + on a SCSI channel. + + @param This Protocol instance pointer. + @param Target On input, a pointer to the Target ID of a SCSI + device present on the SCSI channel. On output, + a pointer to the Target ID of the next SCSI device + present on a SCSI channel. An input value of + 0xFFFFFFFF retrieves the Target ID of the first + SCSI device present on a SCSI channel. + @param Lun On input, a pointer to the LUN of a SCSI device + present on the SCSI channel. On output, a pointer + to the LUN of the next SCSI device present on + a SCSI channel. + + @retval EFI_SUCCESS The Target ID and Lun of the next SCSI device + on the SCSI channel was returned in Target and Lun. + @retval EFI_NOT_FOUND There are no more SCSI devices on this SCSI channel. + @retval EFI_INVALID_PARAMETER Target is not 0xFFFFFFFF,and Target and Lun were not + returned on a previous call to GetNextDevice(). + +**/ +EFI_STATUS +EFIAPI +AtapiScsiPassThruGetNextDevice ( + IN EFI_SCSI_PASS_THRU_PROTOCOL *This, + IN OUT UINT32 *Target, + IN OUT UINT64 *Lun + ) +{ + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate; + + // + // Retrieve Device Private Data Structure. + // + AtapiScsiPrivate = ATAPI_SCSI_PASS_THRU_DEV_FROM_THIS (This); + + // + // Check whether Target is valid. + // + if (Target == NULL || Lun == NULL) { + return EFI_INVALID_PARAMETER; + } + + if ((*Target != 0xFFFFFFFF) && + ((*Target != AtapiScsiPrivate->LatestTargetId) || + (*Lun != AtapiScsiPrivate->LatestLun))) { + return EFI_INVALID_PARAMETER; + } + + if (*Target == MAX_TARGET_ID) { + return EFI_NOT_FOUND; + } + + if (*Target == 0xFFFFFFFF) { + *Target = 0; + } else { + *Target = AtapiScsiPrivate->LatestTargetId + 1; + } + + *Lun = 0; + + // + // Update the LatestTargetId. + // + AtapiScsiPrivate->LatestTargetId = *Target; + AtapiScsiPrivate->LatestLun = *Lun; + + return EFI_SUCCESS; + +} + +/** + Used to allocate and build a device path node for a SCSI device + on a SCSI channel. Would not build device path for a SCSI Host Controller. + + @param This Protocol instance pointer. + @param Target The Target ID of the SCSI device for which + a device path node is to be allocated and built. + @param Lun The LUN of the SCSI device for which a device + path node is to be allocated and built. + @param DevicePath A pointer to a single device path node that + describes the SCSI device specified by + Target and Lun. This function is responsible + for allocating the buffer DevicePath with the boot + service AllocatePool(). It is the caller's + responsibility to free DevicePath when the caller + is finished with DevicePath. + + @retval EFI_SUCCESS The device path node that describes the SCSI device + specified by Target and Lun was allocated and + returned in DevicePath. + @retval EFI_NOT_FOUND The SCSI devices specified by Target and Lun does + not exist on the SCSI channel. + @retval EFI_INVALID_PARAMETER DevicePath is NULL. + @retval EFI_OUT_OF_RESOURCES There are not enough resources to allocate + DevicePath. + +**/ +EFI_STATUS +EFIAPI +AtapiScsiPassThruBuildDevicePath ( + IN EFI_SCSI_PASS_THRU_PROTOCOL *This, + IN UINT32 Target, + IN UINT64 Lun, + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath + ) +{ + EFI_DEV_PATH *Node; + + // + // Validate parameters passed in. + // + + if (DevicePath == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // can not build device path for the SCSI Host Controller. + // + if ((Target > (MAX_TARGET_ID - 1)) || (Lun != 0)) { + return EFI_NOT_FOUND; + } + + Node = AllocateZeroPool (sizeof (EFI_DEV_PATH)); + if (Node == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Node->DevPath.Type = MESSAGING_DEVICE_PATH; + Node->DevPath.SubType = MSG_ATAPI_DP; + SetDevicePathNodeLength (&Node->DevPath, sizeof (ATAPI_DEVICE_PATH)); + + Node->Atapi.PrimarySecondary = (UINT8) (Target / 2); + Node->Atapi.SlaveMaster = (UINT8) (Target % 2); + Node->Atapi.Lun = (UINT16) Lun; + + *DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Node; + + return EFI_SUCCESS; +} + +/** + Used to translate a device path node to a Target ID and LUN. + + @param This Protocol instance pointer. + @param DevicePath A pointer to the device path node that + describes a SCSI device on the SCSI channel. + @param Target A pointer to the Target ID of a SCSI device + on the SCSI channel. + @param Lun A pointer to the LUN of a SCSI device on + the SCSI channel. + + @retval EFI_SUCCESS DevicePath was successfully translated to a + Target ID and LUN, and they were returned + in Target and Lun. + @retval EFI_INVALID_PARAMETER DevicePath is NULL. + @retval EFI_INVALID_PARAMETER Target is NULL. + @retval EFI_INVALID_PARAMETER Lun is NULL. + @retval EFI_UNSUPPORTED This driver does not support the device path + node type in DevicePath. + @retval EFI_NOT_FOUND A valid translation from DevicePath to a + Target ID and LUN does not exist. + +**/ +EFI_STATUS +EFIAPI +AtapiScsiPassThruGetTargetLun ( + IN EFI_SCSI_PASS_THRU_PROTOCOL *This, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + OUT UINT32 *Target, + OUT UINT64 *Lun + ) +{ + EFI_DEV_PATH *Node; + + // + // Validate parameters passed in. + // + if (DevicePath == NULL || Target == NULL || Lun == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Check whether the DevicePath belongs to SCSI_DEVICE_PATH + // + if ((DevicePath->Type != MESSAGING_DEVICE_PATH) || + (DevicePath->SubType != MSG_ATAPI_DP) || + (DevicePathNodeLength(DevicePath) != sizeof(ATAPI_DEVICE_PATH))) { + return EFI_UNSUPPORTED; + } + + Node = (EFI_DEV_PATH *) DevicePath; + + *Target = Node->Atapi.PrimarySecondary * 2 + Node->Atapi.SlaveMaster; + *Lun = Node->Atapi.Lun; + + if (*Target > (MAX_TARGET_ID - 1) || *Lun != 0) { + return EFI_NOT_FOUND; + } + + return EFI_SUCCESS; +} + +/** + Resets a SCSI channel.This operation resets all the + SCSI devices connected to the SCSI channel. + + @param This Protocol instance pointer. + + @retval EFI_SUCCESS The SCSI channel was reset. + @retval EFI_UNSUPPORTED The SCSI channel does not support + a channel reset operation. + @retval EFI_DEVICE_ERROR A device error occurred while + attempting to reset the SCSI channel. + @retval EFI_TIMEOUT A timeout occurred while attempting + to reset the SCSI channel. + +**/ +EFI_STATUS +EFIAPI +AtapiScsiPassThruResetChannel ( + IN EFI_SCSI_PASS_THRU_PROTOCOL *This + ) +{ + UINT8 DeviceControlValue; + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate; + UINT8 Index; + + AtapiScsiPrivate = ATAPI_SCSI_PASS_THRU_DEV_FROM_THIS (This); + + // + // Reset both Primary channel and Secondary channel. + // so, the IoPort pointer must point to the right I/O Register group + // + for (Index = 0; Index < 2; Index++) { + // + // Reset + // + AtapiScsiPrivate->IoPort = &gAtapiIoPortRegisters[Index]; + + DeviceControlValue = 0; + // + // set SRST bit to initiate soft reset + // + DeviceControlValue |= SRST; + // + // disable Interrupt + // + DeviceControlValue |= bit (1); + WritePortB ( + AtapiScsiPrivate->PciIo, + AtapiScsiPrivate->IoPort->Alt.DeviceControl, + DeviceControlValue + ); + + // + // Wait 10us + // + gBS->Stall (10); + + // + // Clear SRST bit + // 0xfb:1111,1011 + // + DeviceControlValue &= 0xfb; + + WritePortB (AtapiScsiPrivate->PciIo, AtapiScsiPrivate->IoPort->Alt.DeviceControl, DeviceControlValue); + + // + // slave device needs at most 31s to clear BSY + // + if (StatusWaitForBSYClear (AtapiScsiPrivate, 31000) == EFI_TIMEOUT) { + return EFI_DEVICE_ERROR; + } + } + + return EFI_SUCCESS; +} + +/** + Resets a SCSI device that is connected to a SCSI channel. + + @param This Protocol instance pointer. + @param Target The Target ID of the SCSI device to reset. + @param Lun The LUN of the SCSI device to reset. + + @retval EFI_SUCCESS The SCSI device specified by Target and + Lun was reset. + @retval EFI_UNSUPPORTED The SCSI channel does not support a target + reset operation. + @retval EFI_INVALID_PARAMETER Target or Lun are invalid. + @retval EFI_DEVICE_ERROR A device error occurred while attempting + to reset the SCSI device specified by Target + and Lun. + @retval EFI_TIMEOUT A timeout occurred while attempting to reset + the SCSI device specified by Target and Lun. + +**/ +EFI_STATUS +EFIAPI +AtapiScsiPassThruResetTarget ( + IN EFI_SCSI_PASS_THRU_PROTOCOL *This, + IN UINT32 Target, + IN UINT64 Lun + ) +{ + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate; + UINT8 Command; + UINT8 DeviceSelect; + + AtapiScsiPrivate = ATAPI_SCSI_PASS_THRU_DEV_FROM_THIS (This); + + if (Target > MAX_TARGET_ID) { + return EFI_INVALID_PARAMETER; + } + // + // Directly return EFI_SUCCESS if want to reset the host controller + // + if (Target == This->Mode->AdapterId) { + return EFI_SUCCESS; + } + + // + // According to Target ID, reset the Atapi I/O Register mapping + // (Target Id in [0,1] area, using gAtapiIoPortRegisters[0], + // Target Id in [2,3] area, using gAtapiIoPortRegisters[1] + // + if ((Target / 2) == 0) { + AtapiScsiPrivate->IoPort = &gAtapiIoPortRegisters[0]; + } else { + AtapiScsiPrivate->IoPort = &gAtapiIoPortRegisters[1]; + } + + // + // for ATAPI device, no need to wait DRDY ready after device selecting. + // + // bit7 and bit5 are both set to 1 for backward compatibility + // + DeviceSelect = (UINT8) (((bit (7) | bit (5)) | (Target << 4))); + WritePortB (AtapiScsiPrivate->PciIo, AtapiScsiPrivate->IoPort->Head, DeviceSelect); + + Command = ATAPI_SOFT_RESET_CMD; + WritePortB (AtapiScsiPrivate->PciIo, AtapiScsiPrivate->IoPort->Reg.Command, Command); + + // + // BSY clear is the only status return to the host by the device + // when reset is complete. + // slave device needs at most 31s to clear BSY + // + if (EFI_ERROR (StatusWaitForBSYClear (AtapiScsiPrivate, 31000))) { + return EFI_DEVICE_ERROR; + } + + // + // stall 5 seconds to make the device status stable + // + gBS->Stall (5000000); + + return EFI_SUCCESS; +} + + +/** + Checks the parameters in the SCSI Request Packet to make sure + they are valid for a SCSI Pass Thru request. + + @todo function comment is missing 'Routine Description:' + @todo function comment is missing 'Arguments:' + @todo function comment is missing 'Returns:' + @todo Packet - add argument and description to function comment + @todo EFI_INVALID_PARAMETER - add return value to function comment + @todo EFI_INVALID_PARAMETER - add return value to function comment + @todo EFI_INVALID_PARAMETER - add return value to function comment + @todo EFI_UNSUPPORTED - add return value to function comment + @todo EFI_SUCCESS - add return value to function comment +**/ +EFI_STATUS +CheckSCSIRequestPacket ( + EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet + ) +{ + if (Packet == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (!ValidCdbLength (Packet->CdbLength)) { + return EFI_INVALID_PARAMETER; + } + + if (Packet->Cdb == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Checks whether the request command is supported. + // + if (!IsCommandValid (Packet)) { + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + +/** + Checks the requested SCSI command: + Is it supported by this driver? + Is the Data transfer direction reasonable? + + @todo function comment is missing 'Routine Description:' + @todo function comment is missing 'Arguments:' + @todo function comment is missing 'Returns:' + @todo Packet - add argument and description to function comment +**/ +BOOLEAN +IsCommandValid ( + EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet + ) +{ + UINT8 Index; + UINT8 *OpCode; + + OpCode = (UINT8 *) (Packet->Cdb); + + for (Index = 0; CompareMem (&gSupportedATAPICommands[Index], &gEndTable, sizeof (SCSI_COMMAND_SET)); Index++) { + + if (*OpCode == gSupportedATAPICommands[Index].OpCode) { + // + // Check whether the requested Command is supported by this driver + // + if (Packet->DataDirection == DataIn) { + // + // Check whether the requested data direction conforms to + // what it should be. + // + if (gSupportedATAPICommands[Index].Direction == DataOut) { + return FALSE; + } + } + + if (Packet->DataDirection == DataOut) { + // + // Check whether the requested data direction conforms to + // what it should be. + // + if (gSupportedATAPICommands[Index].Direction == DataIn) { + return FALSE; + } + } + + return TRUE; + } + } + + return FALSE; +} + +/** + Performs blocking I/O request. + + @param AtapiScsiPrivate Private data structure for the specified channel. + @param Target The Target ID of the ATAPI device to send the SCSI + Request Packet. To ATAPI devices attached on an IDE + Channel, Target ID 0 indicates Master device;Target + ID 1 indicates Slave device. + @param Packet The SCSI Request Packet to send to the ATAPI device + specified by Target. + + @todo AtapiScsiPrivate - add argument and description to function comment +**/ +EFI_STATUS +SubmitBlockingIoCommand ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, + UINT32 Target, + EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet + ) +{ + UINT8 PacketCommand[12]; + UINT64 TimeoutInMicroSeconds; + EFI_STATUS PacketCommandStatus; + + // + // Fill ATAPI Command Packet according to CDB + // + ZeroMem (&PacketCommand, 12); + CopyMem (&PacketCommand, Packet->Cdb, Packet->CdbLength); + + // + // Timeout is 100ns unit, convert it to 1000ns (1us) unit. + // + TimeoutInMicroSeconds = DivU64x32 (Packet->Timeout, (UINT32) 10); + + // + // Submit ATAPI Command Packet + // + PacketCommandStatus = AtapiPacketCommand ( + AtapiScsiPrivate, + Target, + PacketCommand, + Packet->DataBuffer, + &(Packet->TransferLength), + (DATA_DIRECTION) Packet->DataDirection, + TimeoutInMicroSeconds + ); + if (!EFI_ERROR (PacketCommandStatus) || (Packet->SenseData == NULL)) { + Packet->SenseDataLength = 0; + return PacketCommandStatus; + } + // + // Return SenseData if PacketCommandStatus matches + // the following return codes. + // + if ((PacketCommandStatus == EFI_WARN_BUFFER_TOO_SMALL) || + (PacketCommandStatus == EFI_DEVICE_ERROR) || + (PacketCommandStatus == EFI_TIMEOUT)) { + + // + // avoid submit request sense command continuously. + // + if (PacketCommand[0] == OP_REQUEST_SENSE) { + Packet->SenseDataLength = 0; + return PacketCommandStatus; + } + + RequestSenseCommand ( + AtapiScsiPrivate, + Target, + Packet->Timeout, + Packet->SenseData, + &Packet->SenseDataLength + ); + } + + return PacketCommandStatus; +} + +/** + RequestSenseCommand + + @param AtapiScsiPrivate + @param Target + @param Timeout + @param SenseData + @param SenseDataLength + + @todo Add function description + @todo AtapiScsiPrivate TODO: add argument description + @todo Target TODO: add argument description + @todo Timeout TODO: add argument description + @todo SenseData TODO: add argument description + @todo SenseDataLength TODO: add argument description + @todo add return values +**/ +EFI_STATUS +RequestSenseCommand ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, + UINT32 Target, + UINT64 Timeout, + VOID *SenseData, + UINT8 *SenseDataLength + ) +{ + EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET Packet; + UINT8 Cdb[12]; + EFI_STATUS Status; + + ZeroMem (&Packet, sizeof (EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET)); + ZeroMem (Cdb, 12); + + Cdb[0] = OP_REQUEST_SENSE; + Cdb[4] = (UINT8) (*SenseDataLength); + + Packet.Timeout = Timeout; + Packet.DataBuffer = SenseData; + Packet.SenseData = NULL; + Packet.Cdb = Cdb; + Packet.TransferLength = *SenseDataLength; + Packet.CdbLength = 12; + Packet.DataDirection = DataIn; + + Status = SubmitBlockingIoCommand (AtapiScsiPrivate, Target, &Packet); + *SenseDataLength = (UINT8) (Packet.TransferLength); + return Status; +} + +/** + Submits ATAPI command packet to the specified ATAPI device. + + @param AtapiScsiPrivate: Private data structure for the specified channel. + @param Target: The Target ID of the ATAPI device to send the SCSI + Request Packet. To ATAPI devices attached on an IDE + Channel, Target ID 0 indicates Master device;Target + ID 1 indicates Slave device. + @param PacketCommand: Points to the ATAPI command packet. + @param Buffer: Points to the transferred data. + @param ByteCount: When input,indicates the buffer size; when output, + indicates the actually transferred data size. + @param Direction: Indicates the data transfer direction. + @param TimeoutInMicroSeconds: The timeout, in micro second units, + to use for the execution of this ATAPI command. + A TimeoutInMicroSeconds value of 0 means that + this function will wait indefinitely for the ATAPI + command to execute. +

+ If TimeoutInMicroSeconds is greater than zero, then + this function will return EFI_TIMEOUT if the time + required to execute the ATAPI command is greater + than TimeoutInMicroSeconds. +

+ + @todo AtapiScsiPrivate - add argument and description to function comment + @todo PacketCommand - add argument and description to function comment + @todo Buffer - add argument and description to function comment + @todo ByteCount - add argument and description to function comment + @todo Direction - add argument and description to function comment +**/ +EFI_STATUS +AtapiPacketCommand ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, + UINT32 Target, + UINT8 *PacketCommand, + VOID *Buffer, + UINT32 *ByteCount, + DATA_DIRECTION Direction, + UINT64 TimeoutInMicroSeconds + ) +{ + + UINT16 *CommandIndex; + UINT8 Count; + EFI_STATUS Status; + + // + // Set all the command parameters by fill related registers. + // Before write to all the following registers, BSY and DRQ must be 0. + // + Status = StatusDRQClear (AtapiScsiPrivate, TimeoutInMicroSeconds); + if (EFI_ERROR (Status)) { + if (Status == EFI_ABORTED) { + Status = EFI_DEVICE_ERROR; + } + + *ByteCount = 0; + return Status; + } + // + // Select device via Device/Head Register. + // "Target = 0" indicates device 0; "Target = 1" indicates device 1 + // + WritePortB ( + AtapiScsiPrivate->PciIo, + AtapiScsiPrivate->IoPort->Head, + (UINT8) ((Target << 4) | DEFAULT_CMD) // DEFAULT_CMD: 0xa0 (1010,0000) + ); + + // + // No OVL; No DMA (by setting feature register) + // + WritePortB ( + AtapiScsiPrivate->PciIo, + AtapiScsiPrivate->IoPort->Reg1.Feature, + 0x00 + ); + + // + // set the transfersize to MAX_ATAPI_BYTE_COUNT to let the device + // determine how much data should be transfered. + // + WritePortB ( + AtapiScsiPrivate->PciIo, + AtapiScsiPrivate->IoPort->CylinderLsb, + (UINT8) (MAX_ATAPI_BYTE_COUNT & 0x00ff) + ); + WritePortB ( + AtapiScsiPrivate->PciIo, + AtapiScsiPrivate->IoPort->CylinderMsb, + (UINT8) (MAX_ATAPI_BYTE_COUNT >> 8) + ); + + // + // DEFAULT_CTL:0x0a (0000,1010) + // Disable interrupt + // + WritePortB ( + AtapiScsiPrivate->PciIo, + AtapiScsiPrivate->IoPort->Alt.DeviceControl, + DEFAULT_CTL + ); + + // + // Send Packet command to inform device + // that the following data bytes are command packet. + // + WritePortB ( + AtapiScsiPrivate->PciIo, + AtapiScsiPrivate->IoPort->Reg.Command, + PACKET_CMD + ); + + // + // Before data transfer, BSY should be 0 and DRQ should be 1. + // if they are not in specified time frame, + // retrieve Sense Key from Error Register before return. + // + Status = StatusDRQReady (AtapiScsiPrivate, TimeoutInMicroSeconds); + if (EFI_ERROR (Status)) { + if (Status == EFI_ABORTED) { + Status = EFI_DEVICE_ERROR; + } + + *ByteCount = 0; + return Status; + } + + // + // Send out command packet + // + CommandIndex = (UINT16 *) PacketCommand; + for (Count = 0; Count < 6; Count++, CommandIndex++) { + WritePortW (AtapiScsiPrivate->PciIo, AtapiScsiPrivate->IoPort->Data, *CommandIndex); + } + + // + // call AtapiPassThruPioReadWriteData() function to get + // requested transfer data form device. + // + return AtapiPassThruPioReadWriteData ( + AtapiScsiPrivate, + Buffer, + ByteCount, + Direction, + TimeoutInMicroSeconds + ); +} + +/** + Performs data transfer between ATAPI device and host after the + ATAPI command packet is sent. + + @param AtapiScsiPrivate: Private data structure for the specified channel. + @param Buffer: Points to the transferred data. + @param ByteCount: When input,indicates the buffer size; when output, + indicates the actually transferred data size. + @param Direction: Indicates the data transfer direction. + @param TimeoutInMicroSeconds: The timeout, in micro second units, + to use for the execution of this ATAPI command. + A TimeoutInMicroSeconds value of 0 means that + this function will wait indefinitely for the ATAPI + command to execute. +

+ If TimeoutInMicroSeconds is greater than zero, then + this function will return EFI_TIMEOUT if the time + required to execute the ATAPI command is greater + than TimeoutInMicroSeconds. +

+ + @todo AtapiScsiPrivate - add argument and description to function comment + @todo Buffer - add argument and description to function comment + @todo ByteCount - add argument and description to function comment + @todo Direction - add argument and description to function comment + @todo EFI_DEVICE_ERROR - add return value to function comment + @todo EFI_DEVICE_ERROR - add return value to function comment + @todo EFI_WARN_BUFFER_TOO_SMALL - add return value to function comment +**/ +EFI_STATUS +AtapiPassThruPioReadWriteData ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, + UINT16 *Buffer, + UINT32 *ByteCount, + DATA_DIRECTION Direction, + UINT64 TimeoutInMicroSeconds + ) +{ + UINT32 Index; + UINT32 RequiredWordCount; + UINT32 ActualWordCount; + + UINT32 WordCount; + EFI_STATUS Status; + UINT16 *ptrBuffer; + + Status = EFI_SUCCESS; + + // + // Non Data transfer request is also supported. + // + if (*ByteCount == 0 || Buffer == NULL) { + *ByteCount = 0; + if (EFI_ERROR (StatusWaitForBSYClear (AtapiScsiPrivate, TimeoutInMicroSeconds))) { + return EFI_DEVICE_ERROR; + } + } + + ptrBuffer = Buffer; + RequiredWordCount = *ByteCount / 2; + + // + // ActuralWordCount means the word count of data really transfered. + // + ActualWordCount = 0; + + while (ActualWordCount < RequiredWordCount) { + // + // before each data transfer stream, the host should poll DRQ bit ready, + // which indicates device's ready for data transfer . + // + Status = StatusDRQReady (AtapiScsiPrivate, TimeoutInMicroSeconds); + if (EFI_ERROR (Status)) { + *ByteCount = ActualWordCount * 2; + + AtapiPassThruCheckErrorStatus (AtapiScsiPrivate); + + if (ActualWordCount == 0) { + return EFI_DEVICE_ERROR; + } + // + // ActualWordCount > 0 + // + if (ActualWordCount < RequiredWordCount) { + return EFI_WARN_BUFFER_TOO_SMALL; + } + } + // + // get current data transfer size from Cylinder Registers. + // + WordCount = ReadPortB (AtapiScsiPrivate->PciIo, AtapiScsiPrivate->IoPort->CylinderMsb) << 8; + WordCount = WordCount | ReadPortB (AtapiScsiPrivate->PciIo, AtapiScsiPrivate->IoPort->CylinderLsb); + WordCount = WordCount & 0xffff; + WordCount /= 2; + + // + // perform a series data In/Out. + // + for (Index = 0; (Index < WordCount) && (ActualWordCount < RequiredWordCount); Index++, ActualWordCount++) { + + if (Direction == DataIn) { + + *ptrBuffer = ReadPortW (AtapiScsiPrivate->PciIo, AtapiScsiPrivate->IoPort->Data); + } else { + + WritePortW (AtapiScsiPrivate->PciIo, AtapiScsiPrivate->IoPort->Data, *ptrBuffer); + } + + ptrBuffer++; + + } + } + // + // After data transfer is completed, normally, DRQ bit should clear. + // + StatusDRQClear (AtapiScsiPrivate, TimeoutInMicroSeconds); + + // + // read status register to check whether error happens. + // + Status = AtapiPassThruCheckErrorStatus (AtapiScsiPrivate); + + *ByteCount = ActualWordCount * 2; + + return Status; +} + + +/** + Read one byte from a specified I/O port. + + @todo function comment is missing 'Routine Description:' + @todo function comment is missing 'Arguments:' + @todo function comment is missing 'Returns:' + @todo PciIo - add argument and description to function comment + @todo Port - add argument and description to function comment +**/ +UINT8 +ReadPortB ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT16 Port + ) +{ + UINT8 Data; + + Data = 0; + PciIo->Io.Read ( + PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) Port, + 1, + &Data + ); + return Data; +} + + +/** + Read one word from a specified I/O port. + + @todo function comment is missing 'Routine Description:' + @todo function comment is missing 'Arguments:' + @todo function comment is missing 'Returns:' + @todo PciIo - add argument and description to function comment + @todo Port - add argument and description to function comment +**/ +UINT16 +ReadPortW ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT16 Port + ) +{ + UINT16 Data; + + Data = 0; + PciIo->Io.Read ( + PciIo, + EfiPciIoWidthUint16, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) Port, + 1, + &Data + ); + return Data; +} + + +/** + Write one byte to a specified I/O port. + + @todo function comment is missing 'Routine Description:' + @todo function comment is missing 'Arguments:' + @todo function comment is missing 'Returns:' + @todo PciIo - add argument and description to function comment + @todo Port - add argument and description to function comment + @todo Data - add argument and description to function comment +**/ +VOID +WritePortB ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT16 Port, + IN UINT8 Data + ) +{ + + PciIo->Io.Write ( + PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) Port, + 1, + &Data + ); + +} + + +/** + Write one word to a specified I/O port. + + @todo function comment is missing 'Routine Description:' + @todo function comment is missing 'Arguments:' + @todo function comment is missing 'Returns:' + @todo PciIo - add argument and description to function comment + @todo Port - add argument and description to function comment + @todo Data - add argument and description to function comment +**/ +VOID +WritePortW ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT16 Port, + IN UINT16 Data + ) +{ + + PciIo->Io.Write ( + PciIo, + EfiPciIoWidthUint16, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) Port, + 1, + &Data + ); +} + +/** + Check whether DRQ is clear in the Status Register. (BSY must also be cleared) + If TimeoutInMicroSeconds is zero, this routine should wait infinitely for + DRQ clear. Otherwise, it will return EFI_TIMEOUT when specified time is + elapsed. + + @todo function comment is missing 'Routine Description:' + @todo function comment is missing 'Arguments:' + @todo function comment is missing 'Returns:' + @todo AtapiScsiPrivate - add argument and description to function comment + @todo TimeoutInMicroSeconds - add argument and description to function comment + @todo EFI_ABORTED - add return value to function comment + @todo EFI_TIMEOUT - add return value to function comment + @todo EFI_SUCCESS - add return value to function comment +**/ +EFI_STATUS +StatusDRQClear ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, + UINT64 TimeoutInMicroSeconds + ) +{ + UINT64 Delay; + UINT8 StatusRegister; + UINT8 ErrRegister; + + if (TimeoutInMicroSeconds == 0) { + Delay = 2; + } else { + Delay = DivU64x32 (TimeoutInMicroSeconds, (UINT32) 30) + 1; + } + + do { + + StatusRegister = ReadPortB ( + AtapiScsiPrivate->PciIo, + AtapiScsiPrivate->IoPort->Reg.Status + ); + + // + // wait for BSY == 0 and DRQ == 0 + // + if ((StatusRegister & (DRQ | BSY)) == 0) { + break; + } + // + // check whether the command is aborted by the device + // + if ((StatusRegister & (BSY | ERR)) == ERR) { + + ErrRegister = ReadPortB ( + AtapiScsiPrivate->PciIo, + AtapiScsiPrivate->IoPort->Reg1.Error + ); + if ((ErrRegister & ABRT_ERR) == ABRT_ERR) { + + return EFI_ABORTED; + } + } + // + // Stall for 30 us + // + gBS->Stall (30); + + // + // Loop infinitely if not meeting expected condition + // + if (TimeoutInMicroSeconds == 0) { + Delay = 2; + } + + Delay--; + } while (Delay); + + if (Delay == 0) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +/** + Check whether DRQ is clear in the Alternate Status Register. + (BSY must also be cleared). + If TimeoutInMicroSeconds is zero, this routine should wait infinitely for + DRQ clear. Otherwise, it will return EFI_TIMEOUT when specified time is + elapsed. + + @todo function comment is missing 'Routine Description:' + @todo function comment is missing 'Arguments:' + @todo function comment is missing 'Returns:' + @todo AtapiScsiPrivate - add argument and description to function comment + @todo TimeoutInMicroSeconds - add argument and description to function comment + @todo EFI_ABORTED - add return value to function comment + @todo EFI_TIMEOUT - add return value to function comment + @todo EFI_SUCCESS - add return value to function comment +**/ +EFI_STATUS +AltStatusDRQClear ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, + UINT64 TimeoutInMicroSeconds + ) +{ + UINT64 Delay; + UINT8 AltStatusRegister; + UINT8 ErrRegister; + + if (TimeoutInMicroSeconds == 0) { + Delay = 2; + } else { + Delay = DivU64x32 (TimeoutInMicroSeconds, (UINT32) 30) + 1; + } + + do { + + AltStatusRegister = ReadPortB ( + AtapiScsiPrivate->PciIo, + AtapiScsiPrivate->IoPort->Alt.AltStatus + ); + + // + // wait for BSY == 0 and DRQ == 0 + // + if ((AltStatusRegister & (DRQ | BSY)) == 0) { + break; + } + + if ((AltStatusRegister & (BSY | ERR)) == ERR) { + + ErrRegister = ReadPortB ( + AtapiScsiPrivate->PciIo, + AtapiScsiPrivate->IoPort->Reg1.Error + ); + if ((ErrRegister & ABRT_ERR) == ABRT_ERR) { + + return EFI_ABORTED; + } + } + // + // Stall for 30 us + // + gBS->Stall (30); + + // + // Loop infinitely if not meeting expected condition + // + if (TimeoutInMicroSeconds == 0) { + Delay = 2; + } + + Delay--; + } while (Delay); + + if (Delay == 0) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +/** + Check whether DRQ is ready in the Status Register. (BSY must also be cleared) + If TimeoutInMicroSeconds is zero, this routine should wait infinitely for + DRQ ready. Otherwise, it will return EFI_TIMEOUT when specified time is + elapsed. + + @todo function comment is missing 'Routine Description:' + @todo function comment is missing 'Arguments:' + @todo function comment is missing 'Returns:' + @todo AtapiScsiPrivate - add argument and description to function comment + @todo TimeoutInMicroSeconds - add argument and description to function comment + @todo EFI_ABORTED - add return value to function comment + @todo EFI_TIMEOUT - add return value to function comment + @todo EFI_SUCCESS - add return value to function comment +**/ +EFI_STATUS +StatusDRQReady ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, + UINT64 TimeoutInMicroSeconds + ) +{ + UINT64 Delay; + UINT8 StatusRegister; + UINT8 ErrRegister; + + if (TimeoutInMicroSeconds == 0) { + Delay = 2; + } else { + Delay = DivU64x32 (TimeoutInMicroSeconds, (UINT32) 30) + 1; + } + + do { + // + // read Status Register will clear interrupt + // + StatusRegister = ReadPortB ( + AtapiScsiPrivate->PciIo, + AtapiScsiPrivate->IoPort->Reg.Status + ); + + // + // BSY==0,DRQ==1 + // + if ((StatusRegister & (BSY | DRQ)) == DRQ) { + break; + } + + if ((StatusRegister & (BSY | ERR)) == ERR) { + + ErrRegister = ReadPortB ( + AtapiScsiPrivate->PciIo, + AtapiScsiPrivate->IoPort->Reg1.Error + ); + if ((ErrRegister & ABRT_ERR) == ABRT_ERR) { + return EFI_ABORTED; + } + } + + // + // Stall for 30 us + // + gBS->Stall (30); + + // + // Loop infinitely if not meeting expected condition + // + if (TimeoutInMicroSeconds == 0) { + Delay = 2; + } + + Delay--; + } while (Delay); + + if (Delay == 0) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +/** + Check whether DRQ is ready in the Alternate Status Register. + (BSY must also be cleared) + If TimeoutInMicroSeconds is zero, this routine should wait infinitely for + DRQ ready. Otherwise, it will return EFI_TIMEOUT when specified time is + elapsed. + + @todo function comment is missing 'Routine Description:' + @todo function comment is missing 'Arguments:' + @todo function comment is missing 'Returns:' + @todo AtapiScsiPrivate - add argument and description to function comment + @todo TimeoutInMicroSeconds - add argument and description to function comment + @todo EFI_ABORTED - add return value to function comment + @todo EFI_TIMEOUT - add return value to function comment + @todo EFI_SUCCESS - add return value to function comment +**/ +EFI_STATUS +AltStatusDRQReady ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, + UINT64 TimeoutInMicroSeconds + ) +{ + UINT64 Delay; + UINT8 AltStatusRegister; + UINT8 ErrRegister; + + if (TimeoutInMicroSeconds == 0) { + Delay = 2; + } else { + Delay = DivU64x32 (TimeoutInMicroSeconds, (UINT32) 30) + 1; + } + + do { + // + // read Status Register will clear interrupt + // + AltStatusRegister = ReadPortB ( + AtapiScsiPrivate->PciIo, + AtapiScsiPrivate->IoPort->Alt.AltStatus + ); + // + // BSY==0,DRQ==1 + // + if ((AltStatusRegister & (BSY | DRQ)) == DRQ) { + break; + } + + if ((AltStatusRegister & (BSY | ERR)) == ERR) { + + ErrRegister = ReadPortB ( + AtapiScsiPrivate->PciIo, + AtapiScsiPrivate->IoPort->Reg1.Error + ); + if ((ErrRegister & ABRT_ERR) == ABRT_ERR) { + return EFI_ABORTED; + } + } + + // + // Stall for 30 us + // + gBS->Stall (30); + + // + // Loop infinitely if not meeting expected condition + // + if (TimeoutInMicroSeconds == 0) { + Delay = 2; + } + + Delay--; + } while (Delay); + + if (Delay == 0) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +/** + Check whether BSY is clear in the Status Register. + If TimeoutInMicroSeconds is zero, this routine should wait infinitely for + BSY clear. Otherwise, it will return EFI_TIMEOUT when specified time is + elapsed. + + @todo function comment is missing 'Routine Description:' + @todo function comment is missing 'Arguments:' + @todo function comment is missing 'Returns:' + @todo AtapiScsiPrivate - add argument and description to function comment + @todo TimeoutInMicroSeconds - add argument and description to function comment + @todo EFI_TIMEOUT - add return value to function comment + @todo EFI_SUCCESS - add return value to function comment +**/ +EFI_STATUS +StatusWaitForBSYClear ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, + UINT64 TimeoutInMicroSeconds + ) +{ + UINT64 Delay; + UINT8 StatusRegister; + + if (TimeoutInMicroSeconds == 0) { + Delay = 2; + } else { + Delay = DivU64x32 (TimeoutInMicroSeconds, (UINT32) 30) + 1; + } + + do { + + StatusRegister = ReadPortB ( + AtapiScsiPrivate->PciIo, + AtapiScsiPrivate->IoPort->Reg.Status + ); + if ((StatusRegister & BSY) == 0x00) { + break; + } + + // + // Stall for 30 us + // + gBS->Stall (30); + + // + // Loop infinitely if not meeting expected condition + // + if (TimeoutInMicroSeconds == 0) { + Delay = 2; + } + + Delay--; + } while (Delay); + + if (Delay == 0) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +/** + Check whether BSY is clear in the Alternate Status Register. + If TimeoutInMicroSeconds is zero, this routine should wait infinitely for + BSY clear. Otherwise, it will return EFI_TIMEOUT when specified time is + elapsed. + + @todo function comment is missing 'Routine Description:' + @todo function comment is missing 'Arguments:' + @todo function comment is missing 'Returns:' + @todo AtapiScsiPrivate - add argument and description to function comment + @todo TimeoutInMicroSeconds - add argument and description to function comment + @todo EFI_TIMEOUT - add return value to function comment + @todo EFI_SUCCESS - add return value to function comment +**/ +EFI_STATUS +AltStatusWaitForBSYClear ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, + UINT64 TimeoutInMicroSeconds + ) +{ + UINT64 Delay; + UINT8 AltStatusRegister; + + if (TimeoutInMicroSeconds == 0) { + Delay = 2; + } else { + Delay = DivU64x32 (TimeoutInMicroSeconds, (UINT32) 30) + 1; + } + + do { + + AltStatusRegister = ReadPortB ( + AtapiScsiPrivate->PciIo, + AtapiScsiPrivate->IoPort->Alt.AltStatus + ); + if ((AltStatusRegister & BSY) == 0x00) { + break; + } + + // + // Stall for 30 us + // + gBS->Stall (30); + // + // Loop infinitely if not meeting expected condition + // + if (TimeoutInMicroSeconds == 0) { + Delay = 2; + } + + Delay--; + } while (Delay); + + if (Delay == 0) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +/** + Check whether DRDY is ready in the Status Register. + (BSY must also be cleared) + If TimeoutInMicroSeconds is zero, this routine should wait infinitely for + DRDY ready. Otherwise, it will return EFI_TIMEOUT when specified time is + elapsed. + + @todo function comment is missing 'Routine Description:' + @todo function comment is missing 'Arguments:' + @todo function comment is missing 'Returns:' + @todo AtapiScsiPrivate - add argument and description to function comment + @todo TimeoutInMicroSeconds - add argument and description to function comment + @todo EFI_ABORTED - add return value to function comment + @todo EFI_TIMEOUT - add return value to function comment + @todo EFI_SUCCESS - add return value to function comment +**/ +EFI_STATUS +StatusDRDYReady ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, + UINT64 TimeoutInMicroSeconds + ) +{ + UINT64 Delay; + UINT8 StatusRegister; + UINT8 ErrRegister; + + if (TimeoutInMicroSeconds == 0) { + Delay = 2; + } else { + Delay = DivU64x32 (TimeoutInMicroSeconds, (UINT32) 30) + 1; + } + + do { + StatusRegister = ReadPortB ( + AtapiScsiPrivate->PciIo, + AtapiScsiPrivate->IoPort->Reg.Status + ); + // + // BSY == 0 , DRDY == 1 + // + if ((StatusRegister & (DRDY | BSY)) == DRDY) { + break; + } + + if ((StatusRegister & (BSY | ERR)) == ERR) { + + ErrRegister = ReadPortB ( + AtapiScsiPrivate->PciIo, + AtapiScsiPrivate->IoPort->Reg1.Error + ); + if ((ErrRegister & ABRT_ERR) == ABRT_ERR) { + return EFI_ABORTED; + } + } + + // + // Stall for 30 us + // + gBS->Stall (30); + // + // Loop infinitely if not meeting expected condition + // + if (TimeoutInMicroSeconds == 0) { + Delay = 2; + } + + Delay--; + } while (Delay); + + if (Delay == 0) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +/** + Check whether DRDY is ready in the Alternate Status Register. + (BSY must also be cleared) + If TimeoutInMicroSeconds is zero, this routine should wait infinitely for + DRDY ready. Otherwise, it will return EFI_TIMEOUT when specified time is + elapsed. + + @todo function comment is missing 'Routine Description:' + @todo function comment is missing 'Arguments:' + @todo function comment is missing 'Returns:' + @todo AtapiScsiPrivate - add argument and description to function comment + @todo TimeoutInMicroSeconds - add argument and description to function comment + @todo EFI_ABORTED - add return value to function comment + @todo EFI_TIMEOUT - add return value to function comment + @todo EFI_SUCCESS - add return value to function comment +**/ +EFI_STATUS +AltStatusDRDYReady ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, + UINT64 TimeoutInMicroSeconds + ) +{ + UINT64 Delay; + UINT8 AltStatusRegister; + UINT8 ErrRegister; + + if (TimeoutInMicroSeconds == 0) { + Delay = 2; + } else { + Delay = DivU64x32 (TimeoutInMicroSeconds, (UINT32) 30) + 1; + } + + do { + AltStatusRegister = ReadPortB ( + AtapiScsiPrivate->PciIo, + AtapiScsiPrivate->IoPort->Alt.AltStatus + ); + // + // BSY == 0 , DRDY == 1 + // + if ((AltStatusRegister & (DRDY | BSY)) == DRDY) { + break; + } + + if ((AltStatusRegister & (BSY | ERR)) == ERR) { + + ErrRegister = ReadPortB ( + AtapiScsiPrivate->PciIo, + AtapiScsiPrivate->IoPort->Reg1.Error + ); + if ((ErrRegister & ABRT_ERR) == ABRT_ERR) { + return EFI_ABORTED; + } + } + + // + // Stall for 30 us + // + gBS->Stall (30); + // + // Loop infinitely if not meeting expected condition + // + if (TimeoutInMicroSeconds == 0) { + Delay = 2; + } + + Delay--; + } while (Delay); + + if (Delay == 0) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +/** + Check Error Register for Error Information. + + @todo function comment is missing 'Routine Description:' + @todo function comment is missing 'Arguments:' + @todo function comment is missing 'Returns:' + @todo AtapiScsiPrivate - add argument and description to function comment + @todo EFI_SUCCESS - add return value to function comment + @todo EFI_DEVICE_ERROR - add return value to function comment +**/ +EFI_STATUS +AtapiPassThruCheckErrorStatus ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate + ) +{ + UINT8 StatusRegister; + UINT8 ErrorRegister; + + StatusRegister = ReadPortB ( + AtapiScsiPrivate->PciIo, + AtapiScsiPrivate->IoPort->Reg.Status + ); + + DEBUG_CODE_BEGIN (); + + if (StatusRegister & DWF) { + DEBUG ( + (EFI_D_BLKIO, + "AtapiPassThruCheckErrorStatus()-- %02x : Error : Write Fault\n", + StatusRegister) + ); + } + + if (StatusRegister & CORR) { + DEBUG ( + (EFI_D_BLKIO, + "AtapiPassThruCheckErrorStatus()-- %02x : Error : Corrected Data\n", + StatusRegister) + ); + } + + if (StatusRegister & ERR) { + ErrorRegister = ReadPortB (AtapiScsiPrivate->PciIo, AtapiScsiPrivate->IoPort->Reg1.Error); + + + if (ErrorRegister & BBK_ERR) { + DEBUG ( + (EFI_D_BLKIO, + "AtapiPassThruCheckErrorStatus()-- %02x : Error : Bad Block Detected\n", + ErrorRegister) + ); + } + + if (ErrorRegister & UNC_ERR) { + DEBUG ( + (EFI_D_BLKIO, + "AtapiPassThruCheckErrorStatus()-- %02x : Error : Uncorrectable Data\n", + ErrorRegister) + ); + } + + if (ErrorRegister & MC_ERR) { + DEBUG ( + (EFI_D_BLKIO, + "AtapiPassThruCheckErrorStatus()-- %02x : Error : Media Change\n", + ErrorRegister) + ); + } + + if (ErrorRegister & ABRT_ERR) { + DEBUG ( + (EFI_D_BLKIO, + "AtapiPassThruCheckErrorStatus()-- %02x : Error : Abort\n", + ErrorRegister) + ); + } + + if (ErrorRegister & TK0NF_ERR) { + DEBUG ( + (EFI_D_BLKIO, + "AtapiPassThruCheckErrorStatus()-- %02x : Error : Track 0 Not Found\n", + ErrorRegister) + ); + } + + if (ErrorRegister & AMNF_ERR) { + DEBUG ( + (EFI_D_BLKIO, + "AtapiPassThruCheckErrorStatus()-- %02x : Error : Address Mark Not Found\n", + ErrorRegister) + ); + } + } + + DEBUG_CODE_END (); + + if ((StatusRegister & (ERR | DWF | CORR)) == 0) { + return EFI_SUCCESS; + } + + + return EFI_DEVICE_ERROR; +} + +/** + The user Entry Point for module AtapiPassThru. The user code starts with this function. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval other Some error occurs when executing this entry point. + +**/ +EFI_STATUS +EFIAPI +InitializeAtapiPassThru( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Install driver model protocol(s). + // + Status = EfiLibInstallAllDriverProtocols ( + ImageHandle, + SystemTable, + &gAtapiScsiPassThruDriverBinding, + ImageHandle, + &gAtapiScsiPassThruComponentName, + NULL, + NULL + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} diff --git a/MdeModulePkg/Bus/Pci/AtapiPassThruDxe/AtapiPassThru.h b/MdeModulePkg/Bus/Pci/AtapiPassThruDxe/AtapiPassThru.h new file mode 100644 index 0000000000..49b97a821f --- /dev/null +++ b/MdeModulePkg/Bus/Pci/AtapiPassThruDxe/AtapiPassThru.h @@ -0,0 +1,833 @@ +/** @file + Copyright (c) 2006, Intel Corporation + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + Module Name: AtapiPassThru.h + +**/ + +#ifndef _APT_H +#define _APT_H + + +// +// The package level header files this module uses +// +#include +// +// The protocols, PPI and GUID defintions for this module +// +#include +#include +// +// The Library classes this module consumes +// +#include +#include +#include +#include +#include +#include +#include +#include + +/// +/// bit definition +/// +#define bit(a) (1 << (a)) + +#define MAX_TARGET_ID 4 + +// +// IDE Registers +// +typedef union { + UINT16 Command; /* when write */ + UINT16 Status; /* when read */ +} IDE_CMD_OR_STATUS; + +typedef union { + UINT16 Error; /* when read */ + UINT16 Feature; /* when write */ +} IDE_ERROR_OR_FEATURE; + +typedef union { + UINT16 AltStatus; /* when read */ + UINT16 DeviceControl; /* when write */ +} IDE_AltStatus_OR_DeviceControl; + +/// +/// IDE registers set +/// +typedef struct { + UINT16 Data; + IDE_ERROR_OR_FEATURE Reg1; + UINT16 SectorCount; + UINT16 SectorNumber; + UINT16 CylinderLsb; + UINT16 CylinderMsb; + UINT16 Head; + IDE_CMD_OR_STATUS Reg; + + IDE_AltStatus_OR_DeviceControl Alt; + UINT16 DriveAddress; + + UINT16 MasterSlave; +} IDE_BASE_REGISTERS; + +#define ATAPI_SCSI_PASS_THRU_DEV_SIGNATURE EFI_SIGNATURE_32 ('a', 's', 'p', 't') + +typedef struct { + UINTN Signature; + + EFI_HANDLE Handle; + EFI_SCSI_PASS_THRU_PROTOCOL ScsiPassThru; + EFI_SCSI_PASS_THRU_MODE ScsiPassThruMode; + EFI_PCI_IO_PROTOCOL *PciIo; + + // + // Local Data goes here + // + IDE_BASE_REGISTERS *IoPort; + + CHAR16 ControllerName[100]; + CHAR16 ChannelName[100]; + + UINT32 LatestTargetId; + UINT64 LatestLun; + +} ATAPI_SCSI_PASS_THRU_DEV; + +#define ATAPI_SCSI_PASS_THRU_DEV_FROM_THIS(a) \ + CR (a, \ + ATAPI_SCSI_PASS_THRU_DEV, \ + ScsiPassThru, \ + ATAPI_SCSI_PASS_THRU_DEV_SIGNATURE \ + ) + +// +// Global Variables +// +extern EFI_DRIVER_BINDING_PROTOCOL gAtapiScsiPassThruDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gAtapiScsiPassThruComponentName; + +// +// ATAPI Command op code +// +#define OP_INQUIRY 0x12 +#define OP_LOAD_UNLOAD_CD 0xa6 +#define OP_MECHANISM_STATUS 0xbd +#define OP_MODE_SELECT_10 0x55 +#define OP_MODE_SENSE_10 0x5a +#define OP_PAUSE_RESUME 0x4b +#define OP_PLAY_AUDIO_10 0x45 +#define OP_PLAY_AUDIO_MSF 0x47 +#define OP_PLAY_CD 0xbc +#define OP_PLAY_CD_MSF 0xb4 +#define OP_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e +#define OP_READ_10 0x28 +#define OP_READ_12 0xa8 +#define OP_READ_CAPACITY 0x25 +#define OP_READ_CD 0xbe +#define OP_READ_CD_MSF 0xb9 +#define OP_READ_HEADER 0x44 +#define OP_READ_SUB_CHANNEL 0x42 +#define OP_READ_TOC 0x43 +#define OP_REQUEST_SENSE 0x03 +#define OP_SCAN 0xba +#define OP_SEEK_10 0x2b +#define OP_SET_CD_SPEED 0xbb +#define OP_STOPPLAY_SCAN 0x4e +#define OP_START_STOP_UNIT 0x1b +#define OP_TEST_UNIT_READY 0x00 + +#define OP_FORMAT_UNIT 0x04 +#define OP_READ_FORMAT_CAPACITIES 0x23 +#define OP_VERIFY 0x2f +#define OP_WRITE_10 0x2a +#define OP_WRITE_12 0xaa +#define OP_WRITE_AND_VERIFY 0x2e + +// +// ATA Command +// +#define ATAPI_SOFT_RESET_CMD 0x08 + +typedef enum { + DataIn = 0, + DataOut = 1, + NoData = 2, + End = 0xff +} DATA_DIRECTION; + +typedef struct { + UINT8 OpCode; + DATA_DIRECTION Direction; +} SCSI_COMMAND_SET; + +#define MAX_CHANNEL 2 + +#define ValidCdbLength(Len) ((Len) == 6 || (Len) == 10 || (Len) == 12) ? 1 : 0 + +// +// IDE registers bit definitions +// +// ATA Err Reg bitmap +// +#define BBK_ERR bit (7) ///< Bad block detected +#define UNC_ERR bit (6) ///< Uncorrectable Data +#define MC_ERR bit (5) ///< Media Change +#define IDNF_ERR bit (4) ///< ID Not Found +#define MCR_ERR bit (3) ///< Media Change Requested +#define ABRT_ERR bit (2) ///< Aborted Command +#define TK0NF_ERR bit (1) ///< Track 0 Not Found +#define AMNF_ERR bit (0) ///< Address Mark Not Found + +// +// ATAPI Err Reg bitmap +// +#define SENSE_KEY_ERR (bit (7) | bit (6) | bit (5) | bit (4)) +#define EOM_ERR bit (1) ///< End of Media Detected +#define ILI_ERR bit (0) ///< Illegal Length Indication + +// +// Device/Head Reg +// +#define LBA_MODE bit (6) +#define DEV bit (4) +#define HS3 bit (3) +#define HS2 bit (2) +#define HS1 bit (1) +#define HS0 bit (0) +#define CHS_MODE (0) +#define DRV0 (0) +#define DRV1 (1) +#define MST_DRV DRV0 +#define SLV_DRV DRV1 + +// +// Status Reg +// +#define BSY bit (7) ///< Controller Busy +#define DRDY bit (6) ///< Drive Ready +#define DWF bit (5) ///< Drive Write Fault +#define DSC bit (4) ///< Disk Seek Complete +#define DRQ bit (3) ///< Data Request +#define CORR bit (2) ///< Corrected Data +#define IDX bit (1) ///< Index +#define ERR bit (0) ///< Error +#define CHECK bit (0) ///< Check bit for ATAPI Status Reg + +// +// Device Control Reg +// +#define SRST bit (2) ///< Software Reset +#define IEN_L bit (1) ///< Interrupt Enable + +// +// ATAPI Feature Register +// +#define OVERLAP bit (1) +#define DMA bit (0) + +// +// ATAPI Interrupt Reason Reson Reg (ATA Sector Count Register) +// +#define RELEASE bit (2) +#define IO bit (1) +#define CoD bit (0) + +#define PACKET_CMD 0xA0 + +#define DEFAULT_CMD (0xa0) +// +// default content of device control register, disable INT +// +#define DEFAULT_CTL (0x0a) +#define MAX_ATAPI_BYTE_COUNT (0xfffe) + +// +// function prototype +// + +EFI_STATUS +EFIAPI +AtapiScsiPassThruDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +AtapiScsiPassThruDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +AtapiScsiPassThruDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +// +// EFI Component Name Functions +// +EFI_STATUS +EFIAPI +AtapiScsiPassThruComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + +EFI_STATUS +EFIAPI +AtapiScsiPassThruComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +/** + AtapiScsiPassThruDriverEntryPoint + + @param ImageHandle + @param SystemTable + + @todo Add function description + @todo ImageHandle - add argument description + @todo SystemTable - add argument description + @todo add return values +--*/ +EFI_STATUS +EFIAPI +AtapiScsiPassThruDriverEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +; + +/** + RegisterAtapiScsiPassThru + + @param This + @param Controller + @param PciIo + + @todo Add function description + @todo This add argument description + @todo Controller add argument description + @todo PciIo add argument description + @todo add return values +**/ +EFI_STATUS +RegisterAtapiScsiPassThru ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_PCI_IO_PROTOCOL *PciIo + ) +; + +/** + AtapiScsiPassThruFunction + + @param This + @param Target + @param Lun + @param Packet + @param Event + + @todo Add function description + @todo This - add argument description + @todo Target - add argument description + @todo Lun - add argument description + @todo Packet - add argument description + @todo Event - add argument description + @todo add return values +**/ +EFI_STATUS +EFIAPI +AtapiScsiPassThruFunction ( + IN EFI_SCSI_PASS_THRU_PROTOCOL *This, + IN UINT32 Target, + IN UINT64 Lun, + IN OUT EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet, + IN EFI_EVENT Event OPTIONAL + ) +; + +/** + AtapiScsiPassThruGetNextDevice + + TODO: Add function description + + @param This TODO: add argument description + @param Target TODO: add argument description + @param Lun TODO: add argument description + + TODO: add return values + +**/ +EFI_STATUS +EFIAPI +AtapiScsiPassThruGetNextDevice ( + IN EFI_SCSI_PASS_THRU_PROTOCOL *This, + IN OUT UINT32 *Target, + IN OUT UINT64 *Lun + ) +; + +/** + AtapiScsiPassThruBuildDevicePath + + TODO: Add function description + + @param This TODO: add argument description + @param Target TODO: add argument description + @param Lun TODO: add argument description + @param DevicePath TODO: add argument description + + TODO: add return values + +**/ +EFI_STATUS +EFIAPI +AtapiScsiPassThruBuildDevicePath ( + IN EFI_SCSI_PASS_THRU_PROTOCOL *This, + IN UINT32 Target, + IN UINT64 Lun, + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath + ) +; + +/** + AtapiScsiPassThruGetTargetLun + + TODO: Add function description + + @param This TODO: add argument description + @param DevicePath TODO: add argument description + @param Target TODO: add argument description + @param Lun TODO: add argument description + + TODO: add return values + +**/ +EFI_STATUS +EFIAPI +AtapiScsiPassThruGetTargetLun ( + IN EFI_SCSI_PASS_THRU_PROTOCOL *This, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + OUT UINT32 *Target, + OUT UINT64 *Lun + ) +; + +/** + AtapiScsiPassThruResetChannel + + TODO: Add function description + + @param This TODO: add argument description + + TODO: add return values + +**/ +EFI_STATUS +EFIAPI +AtapiScsiPassThruResetChannel ( + IN EFI_SCSI_PASS_THRU_PROTOCOL *This + ) +; + +/** + AtapiScsiPassThruResetTarget + + TODO: Add function description + + @param This TODO: add argument description + @param Target TODO: add argument description + @param Lun TODO: add argument description + + TODO: add return values + +**/ +EFI_STATUS +EFIAPI +AtapiScsiPassThruResetTarget ( + IN EFI_SCSI_PASS_THRU_PROTOCOL *This, + IN UINT32 Target, + IN UINT64 Lun + ) +; + +/** + CheckSCSIRequestPacket + + TODO: Add function description + + @param Packet TODO: add argument description + + TODO: add return values + +**/ +EFI_STATUS +CheckSCSIRequestPacket ( + EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet + ) +; + +/** + SubmitBlockingIoCommand + + TODO: Add function description + + @param AtapiScsiPrivate TODO: add argument description + @param Target TODO: add argument description + @param Packet TODO: add argument description + + TODO: add return values + +**/ +EFI_STATUS +SubmitBlockingIoCommand ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, + UINT32 Target, + EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet + ) +; + +/** + IsCommandValid + + TODO: Add function description + + @param Packet - TODO: add argument description + + @return TODO: add return values + +--*/ +BOOLEAN +IsCommandValid ( + EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet + ) +; + +/** + RequestSenseCommand + + TODO: Add function description + + @param AtapiScsiPrivate TODO: add argument description + @param Target TODO: add argument description + @param Timeout TODO: add argument description + @param SenseData TODO: add argument description + @param SenseDataLength TODO: add argument description + + TODO: add return values + +**/ +EFI_STATUS +RequestSenseCommand ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, + UINT32 Target, + UINT64 Timeout, + VOID *SenseData, + UINT8 *SenseDataLength + ) +; + +/** + AtapiPacketCommand + + TODO: Add function description + + @param AtapiScsiPrivate TODO: add argument description + @param Target TODO: add argument description + @param PacketCommand TODO: add argument description + @param Buffer TODO: add argument description + @param ByteCount TODO: add argument description + @param Direction TODO: add argument description + @param TimeOutInMicroSeconds TODO: add argument description + + TODO: add return values + +**/ +EFI_STATUS +AtapiPacketCommand ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, + UINT32 Target, + UINT8 *PacketCommand, + VOID *Buffer, + UINT32 *ByteCount, + DATA_DIRECTION Direction, + UINT64 TimeOutInMicroSeconds + ) +; + + +/** + ReadPortB + + TODO: Add function description + + @param PciIo TODO: add argument description + @param Port TODO: add argument description + + TODO: add return values + +**/ +UINT8 +ReadPortB ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT16 Port + ) +; + + +/** + ReadPortW + + TODO: Add function description + + @param PciIo TODO: add argument description + @param Port TODO: add argument description + + TODO: add return values + +**/ +UINT16 +ReadPortW ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT16 Port + ) +; + + +/** + WritePortB + + TODO: Add function description + + @param PciIo TODO: add argument description + @param Port TODO: add argument description + @param Data TODO: add argument description + + TODO: add return values + +**/ +VOID +WritePortB ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT16 Port, + IN UINT8 Data + ) +; + + +/** + WritePortW + + TODO: Add function description + + @param PciIo TODO: add argument description + @param Port TODO: add argument description + @param Data TODO: add argument description + + TODO: add return values + +**/ +VOID +WritePortW ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT16 Port, + IN UINT16 Data + ) +; + +/** + StatusDRQClear + + TODO: Add function description + + @param AtapiScsiPrivate TODO: add argument description + @param TimeOutInMicroSeconds TODO: add argument description + + TODO: add return values + +**/ +EFI_STATUS +StatusDRQClear ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, + UINT64 TimeOutInMicroSeconds + ) +; + +/** + AltStatusDRQClear + + TODO: Add function description + + @param AtapiScsiPrivate TODO: add argument description + @param TimeOutInMicroSeconds TODO: add argument description + + TODO: add return values + +**/ +EFI_STATUS +AltStatusDRQClear ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, + UINT64 TimeOutInMicroSeconds + ) +; + +/** + StatusDRQReady + + TODO: Add function description + + @param AtapiScsiPrivate TODO: add argument description + @param TimeOutInMicroSeconds TODO: add argument description + + TODO: add return values + +**/ +EFI_STATUS +StatusDRQReady ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, + UINT64 TimeOutInMicroSeconds + ) +; + +/** + AltStatusDRQReady + + TODO: Add function description + + @param AtapiScsiPrivate TODO: add argument description + @param TimeOutInMicroSeconds TODO: add argument description + + TODO: add return values + +**/ +EFI_STATUS +AltStatusDRQReady ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, + UINT64 TimeOutInMicroSeconds + ) +; + +/** + TODO: Add function description + + @param AtapiScsiPrivate TODO: add argument description + @param TimeoutInMicroSeconds TODO: add argument description + + TODO: add return values + +**/ +EFI_STATUS +StatusWaitForBSYClear ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, + UINT64 TimeoutInMicroSeconds + ) +; + +/** + TODO: Add function description + + @param AtapiScsiPrivate TODO: add argument description + @param TimeoutInMicroSeconds TODO: add argument description + + TODO: add return values + +**/ +EFI_STATUS +AltStatusWaitForBSYClear ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, + UINT64 TimeoutInMicroSeconds + ) +; + +/** + TODO: Add function description + + @param AtapiScsiPrivate TODO: add argument description + @param TimeoutInMicroSeconds TODO: add argument description + + TODO: add return values + +**/ +EFI_STATUS +StatusDRDYReady ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, + UINT64 TimeoutInMicroSeconds + ) +; + +/** + TODO: Add function description + + @param AtapiScsiPrivate TODO: add argument description + @param TimeoutInMicroSeconds TODO: add argument description + + TODO: add return values + +**/ +EFI_STATUS +AltStatusDRDYReady ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, + UINT64 TimeoutInMicroSeconds + ) +; + +/** + TODO: Add function description + + @param AtapiScsiPrivate TODO: add argument description + @param Buffer TODO: add argument description + @param ByteCount TODO: add argument description + @param Direction TODO: add argument description + @param TimeOutInMicroSeconds TODO: add argument description + + TODO: add return values + +**/ +EFI_STATUS +AtapiPassThruPioReadWriteData ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, + UINT16 *Buffer, + UINT32 *ByteCount, + DATA_DIRECTION Direction, + UINT64 TimeOutInMicroSeconds + ) +; + +/** + TODO: Add function description + + @param AtapiScsiPrivate TODO: add argument description + + TODO: add return values + +**/ +EFI_STATUS +AtapiPassThruCheckErrorStatus ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate + ) +; +#endif diff --git a/MdeModulePkg/Bus/Pci/AtapiPassThruDxe/AtapiPassThru.inf b/MdeModulePkg/Bus/Pci/AtapiPassThruDxe/AtapiPassThru.inf new file mode 100644 index 0000000000..d449723358 --- /dev/null +++ b/MdeModulePkg/Bus/Pci/AtapiPassThruDxe/AtapiPassThru.inf @@ -0,0 +1,93 @@ +#/** @file +# Description file for the Atapi Passthru component. +# +# This driver simulates SCSI devices with Atapi devices to test the SCSI io +# protocol. +# Copyright (c) 2006 - 2007, Intel Corporation +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +################################################################################ +# +# Defines Section - statements that will be processed to create a Makefile. +# +################################################################################ +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = AtapiPassThru + FILE_GUID = E49061CE-99A7-41d3-AB3A-36E5CFBAD63E + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + EDK_RELEASE_VERSION = 0x00020000 + EFI_SPECIFICATION_VERSION = 0x00020000 + + ENTRY_POINT = InitializeAtapiPassThru + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# +# DRIVER_BINDING = gAtapiScsiPassThruDriverBinding +# COMPONENT_NAME = gAtapiScsiPassThruComponentName +# + +################################################################################ +# +# Sources Section - list of files that are required for the build to succeed. +# +################################################################################ + +[Sources.common] + ComponentName.c + AtapiPassThru.c + AtapiPassThru.h + + +################################################################################ +# +# Package Dependency Section - list of Package files that are required for +# this module. +# +################################################################################ + +[Packages] + MdePkg/MdePkg.dec + + +################################################################################ +# +# Library Class Section - list of Library Classes that are required for +# this module. +# +################################################################################ + +[LibraryClasses] + UefiBootServicesTableLib + MemoryAllocationLib + BaseMemoryLib + UefiLib + BaseLib + UefiDriverEntryPoint + DebugLib + + +################################################################################ +# +# Protocol C Name Section - list of Protocol and Protocol Notify C Names +# that this module uses or produces. +# +################################################################################ + +[Protocols] + gEfiScsiPassThruProtocolGuid # PROTOCOL BY_START + gEfiPciIoProtocolGuid # PROTOCOL TO_START + diff --git a/MdeModulePkg/Bus/Pci/AtapiPassThruDxe/AtapiPassThru.msa b/MdeModulePkg/Bus/Pci/AtapiPassThruDxe/AtapiPassThru.msa new file mode 100644 index 0000000000..b33cb93326 --- /dev/null +++ b/MdeModulePkg/Bus/Pci/AtapiPassThruDxe/AtapiPassThru.msa @@ -0,0 +1,72 @@ + + + + AtapiPassThru + UEFI_DRIVER + E49061CE-99A7-41d3-AB3A-36E5CFBAD63E + 1.0 + Description file for the Atapi Passthru component. + This driver simulates SCSI devices with Atapi devices to test the SCSI io + protocol. + Copyright (c) 2006 - 2007, Intel Corporation + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052 + + + IA32 X64 IPF EBC + false + AtapiPassThru + + + + DebugLib + + + UefiDriverEntryPoint + + + BaseLib + + + UefiLib + + + BaseMemoryLib + + + MemoryAllocationLib + + + UefiBootServicesTableLib + + + + AtapiPassThru.h + AtapiPassThru.c + ComponentName.c + + + + + + + gEfiPciIoProtocolGuid + + + gEfiScsiPassThruProtocolGuid + + + + EFI_SPECIFICATION_VERSION 0x00020000 + EDK_RELEASE_VERSION 0x00020000 + + gAtapiScsiPassThruDriverBinding + gAtapiScsiPassThruComponentName + + + diff --git a/MdeModulePkg/Bus/Pci/AtapiPassThruDxe/ComponentName.c b/MdeModulePkg/Bus/Pci/AtapiPassThruDxe/ComponentName.c new file mode 100644 index 0000000000..1731571069 --- /dev/null +++ b/MdeModulePkg/Bus/Pci/AtapiPassThruDxe/ComponentName.c @@ -0,0 +1,120 @@ +/** @file + Copyright (c) 2006, Intel Corporation + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + Module Name: ComponentName.c + +**/ +#include "AtapiPassThru.h" + +/// +/// EFI Component Name Protocol +/// +EFI_COMPONENT_NAME_PROTOCOL gAtapiScsiPassThruComponentName = { + AtapiScsiPassThruComponentNameGetDriverName, + AtapiScsiPassThruComponentNameGetControllerName, + "eng" +}; + +static EFI_UNICODE_STRING_TABLE mAtapiScsiPassThruDriverNameTable[] = { + { "eng", (CHAR16 *) L"ATAPI SCSI Pass Thru Driver" }, + { NULL , NULL } +}; + +/** + Retrieves a Unicode string that is the user readable name of the EFI Driver. + + @param This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + @param Language A pointer to a three character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + @param DriverName A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + @retval EFI_INVALID_PARAMETER Language is NULL. + @retval EFI_INVALID_PARAMETER DriverName is NULL. + @retval EFI_UNSUPPORTED The driver specified by This does not support the + language specified by Language. + +**/ +EFI_STATUS +EFIAPI +AtapiScsiPassThruComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + return LookupUnicodeString ( + Language, + gAtapiScsiPassThruComponentName.SupportedLanguages, + mAtapiScsiPassThruDriverNameTable, + DriverName + ); +} + +/** + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + @param This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + @param ControllerHandle The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + @param ChildHandle The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + @param Language A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + @param ControllerName A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language + specified by Language from the point of view of the + driver specified by This. + + @retval EFI_SUCCESS The Unicode string for the user readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid + EFI_HANDLE. + @retval EFI_INVALID_PARAMETER Language is NULL. + @retval EFI_INVALID_PARAMETER ControllerName is NULL. + @retval EFI_UNSUPPORTED The driver specified by This is not currently + managing the controller specified by + ControllerHandle and ChildHandle. + @retval EFI_UNSUPPORTED The driver specified by This does not support the + language specified by Language. + +**/ +EFI_STATUS +EFIAPI +AtapiScsiPassThruComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + return EFI_UNSUPPORTED; +}