From 878ddf1fc3540a715f63594ed22b6929e881afb4 Mon Sep 17 00:00:00 2001 From: bbahnsen Date: Fri, 21 Apr 2006 22:54:32 +0000 Subject: Initial import. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3 6f19259b-4bc3-4df7-8a09-765794883524 --- EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/Cbi0.c | 1042 ++++++++++++++++++++ .../Bus/Usb/UsbCbi/Dxe/Cbi0/ComponentName.c | 192 ++++ EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/UsbCbi0.mbd | 43 + EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/UsbCbi0.msa | 68 ++ EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/build.xml | 47 + EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi1/UsbCbi1.mbd | 43 + EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi1/UsbCbi1.msa | 66 ++ EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi1/build.xml | 47 + EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi1/cbi1.c | 854 ++++++++++++++++ EdkModulePkg/Bus/Usb/UsbCbi/Dxe/cbi.h | 70 ++ 10 files changed, 2472 insertions(+) create mode 100644 EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/Cbi0.c create mode 100644 EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/ComponentName.c create mode 100644 EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/UsbCbi0.mbd create mode 100644 EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/UsbCbi0.msa create mode 100644 EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/build.xml create mode 100644 EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi1/UsbCbi1.mbd create mode 100644 EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi1/UsbCbi1.msa create mode 100644 EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi1/build.xml create mode 100644 EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi1/cbi1.c create mode 100644 EdkModulePkg/Bus/Usb/UsbCbi/Dxe/cbi.h (limited to 'EdkModulePkg/Bus/Usb/UsbCbi') diff --git a/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/Cbi0.c b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/Cbi0.c new file mode 100644 index 0000000000..5bd8728fcf --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/Cbi0.c @@ -0,0 +1,1042 @@ +/*++ + +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: + + Cbi0.c + +Abstract: + +--*/ + +#include "../cbi.h" + +extern EFI_COMPONENT_NAME_PROTOCOL gUsbCbi0ComponentName; +// +// Function prototypes +// +EFI_STATUS +EFIAPI +UsbCbi0DriverEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +// +// Bot Driver Binding Protocol +// +STATIC +EFI_STATUS +EFIAPI +Cbi0DriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +STATIC +EFI_STATUS +EFIAPI +Cbi0DriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +STATIC +EFI_STATUS +EFIAPI +Cbi0DriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +VOID +Cbi0ReportStatusCode ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value + ); + + +EFI_DRIVER_BINDING_PROTOCOL gUsbCbi0DriverBinding = { + Cbi0DriverBindingSupported, + Cbi0DriverBindingStart, + Cbi0DriverBindingStop, + 0x10, + NULL, + NULL +}; + +STATIC +EFI_STATUS +Cbi0RecoveryReset ( + IN USB_CBI_DEVICE *UsbCbiDev + ); + +STATIC +EFI_STATUS +Cbi0CommandPhase ( + IN USB_CBI_DEVICE *UsbCbiDev, + IN VOID *Command, + IN UINT8 CommandSize, + IN UINT16 Timeout + ); + +STATIC +EFI_STATUS +Cbi0DataPhase ( + IN USB_CBI_DEVICE *UsbCbiDev, + IN UINT32 *DataSize, + IN OUT VOID *DataBuffer, + IN EFI_USB_DATA_DIRECTION Direction, + IN UINT16 Timeout + ); + +STATIC +EFI_STATUS +Cbi0StatusPhase ( + IN USB_CBI_DEVICE *UsbCbiDev, + OUT INTERRUPT_DATA_BLOCK *InterruptDataBlock, + IN UINT16 Timeout + ); + +// +// USB Atapi protocol prototype +// +STATIC +EFI_STATUS +EFIAPI +Cbi0AtapiCommand ( + IN EFI_USB_ATAPI_PROTOCOL *This, + IN VOID *Command, + IN UINT8 CommandSize, + IN VOID *DataBuffer, + IN UINT32 BufferLength, + IN EFI_USB_DATA_DIRECTION Direction, + IN UINT16 TimeOutInMilliSeconds + ); + +STATIC +EFI_STATUS +EFIAPI +Cbi0MassStorageReset ( + IN EFI_USB_ATAPI_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +STATIC EFI_USB_ATAPI_PROTOCOL Cbi0AtapiProtocol = { + Cbi0AtapiCommand, + Cbi0MassStorageReset, + 0 +}; + +STATIC +EFI_STATUS +EFIAPI +Cbi0DriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + + Routine Description: + Test to see if this driver supports ControllerHandle. Any ControllerHandle + than contains a BlockIo and DiskIo protocol can be supported. + + Arguments: + This - Protocol instance pointer. + ControllerHandle - Handle of device to test + RemainingDevicePath - Not used + + Returns: + EFI_SUCCESS - This driver supports this device + EFI_ALREADY_STARTED - This driver is already running on this device + other - This driver does not support this device + +--*/ +{ + EFI_STATUS Status; + EFI_USB_IO_PROTOCOL *UsbIo; + EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor; + + // + // Check if the Controller supports USB IO protocol + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + (VOID **) &UsbIo, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Get the Default interface descriptor, now we only + // suppose interface 1 + // + Status = UsbIo->UsbGetInterfaceDescriptor ( + UsbIo, + &InterfaceDescriptor + ); + if (EFI_ERROR (Status)) { + gBS->CloseProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + return Status; + } + // + // Check if it is a Cbi0 Type Mass Storage Device + // + if((InterfaceDescriptor.InterfaceClass != MASS_STORAGE_CLASS) || + (InterfaceDescriptor.InterfaceProtocol != CBI0_INTERFACE_PROTOCOL)) { + Status = EFI_UNSUPPORTED; + } else { + Status = EFI_SUCCESS; + } + + gBS->CloseProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + + return Status; +} + +STATIC +EFI_STATUS +EFIAPI +Cbi0DriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + + Routine Description: + Start this driver on ControllerHandle by opening a Block IO and Disk IO + protocol, reading Device Path, and creating a child handle with a + Disk IO and device path protocol. + + Arguments: + This - Protocol instance pointer. + ControllerHandle - Handle of device to bind driver to + RemainingDevicePath - Not used + + Returns: + EFI_SUCCESS - This driver is added to DeviceHandle + EFI_ALREADY_STARTED - This driver is already running on DeviceHandle + other - This driver does not support this device + EFI_OUT_OF_RESOURCES- Can't allocate memory + EFI_UNSUPPORTED - Endpoint is not as expected +--*/ +{ + USB_CBI_DEVICE *UsbCbiDev; + UINT8 Index; + EFI_USB_ENDPOINT_DESCRIPTOR EndpointDescriptor; + EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor; + EFI_STATUS Status; + EFI_USB_IO_PROTOCOL *UsbIo; + UINT8 EndpointExistMask; + + // + // Check if the Controller supports USB IO protocol + // + UsbCbiDev = NULL; + + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + (VOID **) &UsbIo, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Get the controller interface descriptor + // + Status = UsbIo->UsbGetInterfaceDescriptor ( + UsbIo, + &InterfaceDescriptor + ); + if (EFI_ERROR (Status)) { + gBS->CloseProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + return Status; + } + + Cbi0AtapiProtocol.CommandProtocol = InterfaceDescriptor.InterfaceSubClass; + + UsbCbiDev = AllocateZeroPool (sizeof (USB_CBI_DEVICE)); + if (UsbCbiDev == NULL) { + gBS->CloseProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + return EFI_OUT_OF_RESOURCES; + } + + UsbCbiDev->Signature = USB_CBI_DEVICE_SIGNATURE; + UsbCbiDev->UsbIo = UsbIo; + CopyMem (&UsbCbiDev->InterfaceDescriptor, &InterfaceDescriptor, sizeof (InterfaceDescriptor)); + CopyMem (&UsbCbiDev->UsbAtapiProtocol, &Cbi0AtapiProtocol, sizeof (Cbi0AtapiProtocol)); + + // + // Get the Device Path Protocol on Controller's handle + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiDevicePathProtocolGuid, + (VOID **) &UsbCbiDev->DevicePath, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + gBS->CloseProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + if (UsbCbiDev != NULL) { + gBS->FreePool (UsbCbiDev); + } + + return Status; + } + // + // Mask used to see whether all three kinds of endpoints exist, + // Mask value: + // bit0: bulk in endpoint; + // bit1: bulk out endpoint; + // bit2: interrupt in endpoint; + // + EndpointExistMask = 0; + for (Index = 0; Index < InterfaceDescriptor.NumEndpoints; Index++) { + UsbIo->UsbGetEndpointDescriptor ( + UsbIo, + Index, + &EndpointDescriptor + ); + + // + // We parse bulk endpoint + // + if (EndpointDescriptor.Attributes == 0x02) { + if (EndpointDescriptor.EndpointAddress & 0x80) { + CopyMem (&UsbCbiDev->BulkInEndpointDescriptor, &EndpointDescriptor, sizeof(EndpointDescriptor)); + // UsbCbiDev->BulkInEndpointDescriptor = EndpointDescriptor; + EndpointExistMask |= bit (0); + } else { + CopyMem (&UsbCbiDev->BulkOutEndpointDescriptor, &EndpointDescriptor, sizeof(EndpointDescriptor)); + // UsbCbiDev->BulkOutEndpointDescriptor = EndpointDescriptor; + EndpointExistMask |= bit (1); + } + } + // + // We parse interrupt endpoint + // + if (EndpointDescriptor.Attributes == 0x03) { + CopyMem (&UsbCbiDev->InterruptEndpointDescriptor, &EndpointDescriptor, sizeof(EndpointDescriptor)); + // UsbCbiDev->InterruptEndpointDescriptor = EndpointDescriptor; + EndpointExistMask |= bit (2); + } + + } + // + // Double check we have all endpoints needed + // + if (EndpointExistMask != (bit (0) | bit (1) | bit (2))) { + gBS->CloseProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + if (UsbCbiDev != NULL) { + gBS->FreePool (UsbCbiDev); + } + + return EFI_UNSUPPORTED; + } + // + // After installing Usb-Atapi protocol onto this handle + // it will be called by upper layer drivers such as Fat + // + Cbi0ReportStatusCode ( + UsbCbiDev->DevicePath, + EFI_PROGRESS_CODE, + (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_ENABLE) + ); + + Status = gBS->InstallProtocolInterface ( + &ControllerHandle, + &gEfiUsbAtapiProtocolGuid, + EFI_NATIVE_INTERFACE, + &UsbCbiDev->UsbAtapiProtocol + ); + if (EFI_ERROR (Status)) { + gBS->CloseProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + if (UsbCbiDev != NULL) { + gBS->FreePool (UsbCbiDev); + } + + return Status; + } + + UsbCbiDev->ControllerNameTable = NULL; + AddUnicodeString ( + "eng", + gUsbCbi0ComponentName.SupportedLanguages, + &UsbCbiDev->ControllerNameTable, + (CHAR16 *) L"Usb Cbi0 Mass Storage" + ); + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +Cbi0DriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + + Routine Description: + Stop this driver on ControllerHandle. Support stoping any child handles + created by this driver. + + Arguments: + This - Protocol instance pointer. + ControllerHandle - Handle of device to stop driver on + NumberOfChildren - Number of Children in the ChildHandleBuffer + ChildHandleBuffer - List of handles for the children we need to stop. + + Returns: + EFI_SUCCESS - This driver is removed DeviceHandle + EFI_UNSUPPORTED - This driver was not removed from this device + +--*/ +{ + EFI_STATUS Status; + EFI_USB_ATAPI_PROTOCOL *Cbi0AtapiProtocol; + USB_CBI_DEVICE *UsbCbiDev; + EFI_USB_IO_PROTOCOL *UsbIo; + + // + // Get our context back. + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiUsbAtapiProtocolGuid, + (VOID **) &Cbi0AtapiProtocol, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + UsbCbiDev = USB_CBI_DEVICE_FROM_THIS (Cbi0AtapiProtocol); + + UsbIo = UsbCbiDev->UsbIo; + + Cbi0ReportStatusCode ( + UsbCbiDev->DevicePath, + EFI_PROGRESS_CODE, + (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_DISABLE) + ); + + // + // Uninstall protocol + // + Status = gBS->UninstallProtocolInterface ( + ControllerHandle, + &gEfiUsbAtapiProtocolGuid, + &UsbCbiDev->UsbAtapiProtocol + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->CloseProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + // + // Free all allocated resources + // + if (UsbCbiDev->ControllerNameTable) { + FreeUnicodeStringTable (UsbCbiDev->ControllerNameTable); + } + + gBS->FreePool (UsbCbiDev); + + return Status; +} + + +STATIC +EFI_STATUS +Cbi0RecoveryReset ( + IN USB_CBI_DEVICE *UsbCbiDev + ) +/*++ + +Routine Description: + + Cbi0 Recovery Reset routine + +Arguments: + + UsbCbiDev - Cbi0RecoveryReset + +Returns: + + EFI_SUCCESS - Success + +--*/ +{ + UINT8 ResetCommand[12]; + EFI_STATUS Status; + EFI_USB_IO_PROTOCOL *UsbIo; + UINT8 EndpointAddress; + UINT32 Result; + UINT16 Timeout; + + UsbIo = UsbCbiDev->UsbIo; + + Cbi0ReportStatusCode ( + UsbCbiDev->DevicePath, + EFI_PROGRESS_CODE, + (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_RESET) + ); + // + // CBI reset command protocol + // + SetMem (ResetCommand, sizeof (ResetCommand), 0xff); + ResetCommand[0] = 0x1d; + ResetCommand[1] = 0x04; + + // + // (in millisecond unit) + // + Timeout = STALL_1_SECOND; + + Status = Cbi0AtapiCommand ( + &UsbCbiDev->UsbAtapiProtocol, + ResetCommand, + 12, + NULL, + 0, + EfiUsbNoData, + Timeout + ); + if (EFI_ERROR (Status)) { + return Status; + } + + gBS->Stall (100 * 1000); + // + // clear bulk in endpoint stall feature + // + EndpointAddress = UsbCbiDev->BulkInEndpointDescriptor.EndpointAddress; + Status = UsbClearEndpointHalt ( + UsbIo, + EndpointAddress, + &Result + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // clear bulk out endpoint stall feature + // + EndpointAddress = UsbCbiDev->BulkOutEndpointDescriptor.EndpointAddress; + Status = UsbClearEndpointHalt ( + UsbIo, + EndpointAddress, + &Result + ); + // + // according to CBI spec, no need to clear interrupt endpoint feature. + // + return Status; +} + +STATIC +EFI_STATUS +Cbi0CommandPhase ( + IN USB_CBI_DEVICE *UsbCbiDev, + IN VOID *Command, + IN UINT8 CommandSize, + IN UINT16 Timeout + ) +/*++ + + Routine Description: + Send ATAPI command through CBI0 interface. + + Arguments: + UsbCbiDev - USB_CBI_DEVICE + Command - Command to send + CommandSize - Command size + Timeout - Time out value in milliseconds + Returns: + EFI_SUCCESS - Success + EFI_DEVICE_ERROR - Fail + Others + +--*/ +{ + EFI_STATUS Status; + UINT32 Result; + EFI_USB_IO_PROTOCOL *UsbIo; + EFI_USB_DEVICE_REQUEST Request; + + UsbIo = UsbCbiDev->UsbIo; + + ZeroMem (&Request, sizeof (EFI_USB_DEVICE_REQUEST)); + + // + // Device request see CBI specification + // + Request.RequestType = 0x21; + Request.Request = 0x00; + Request.Value = 0; + Request.Index = 0; + Request.Length = CommandSize; + + Status = UsbIo->UsbControlTransfer ( + UsbIo, + &Request, + EfiUsbDataOut, + Timeout, + Command, + CommandSize, + &Result + ); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +Cbi0DataPhase ( + IN USB_CBI_DEVICE *UsbCbiDev, + IN UINT32 *DataSize, + IN OUT VOID *DataBuffer, + IN EFI_USB_DATA_DIRECTION Direction, + IN UINT16 Timeout + ) +/*++ + + Routine Description: + Get/Send Data through CBI0 interface + + Arguments: + UsbCbiDev - USB_CBI_DEVICE + DataSize - Data size + DataBuffer - Data buffer + Direction - IN/OUT/NODATA + Timeout - Time out value in milliseconds + Returns: + EFI_SUCCESS + Others + +--*/ +{ + EFI_STATUS Status; + EFI_USB_IO_PROTOCOL *UsbIo; + UINT8 EndpointAddress; + UINTN Remain; + UINTN Increment; + UINT32 MaxPacketLength; + UINT8 *BufferPtr; + UINT32 Result; + UINTN TransferredSize; + + UsbIo = UsbCbiDev->UsbIo; + + Remain = *DataSize; + BufferPtr = (UINT8 *) DataBuffer; + TransferredSize = 0; + // + // retrieve the the max packet length of the given endpoint + // + if (Direction == EfiUsbDataIn) { + MaxPacketLength = UsbCbiDev->BulkInEndpointDescriptor.MaxPacketSize; + EndpointAddress = UsbCbiDev->BulkInEndpointDescriptor.EndpointAddress; + } else { + MaxPacketLength = UsbCbiDev->BulkOutEndpointDescriptor.MaxPacketSize; + EndpointAddress = UsbCbiDev->BulkOutEndpointDescriptor.EndpointAddress; + } + + while (Remain > 0) { + + if (Remain > 16 * MaxPacketLength) { + Increment = 16 * MaxPacketLength; + } else { + Increment = Remain; + } + + Status = UsbIo->UsbBulkTransfer ( + UsbIo, + EndpointAddress, + BufferPtr, + &Increment, + Timeout, + &Result + ); + TransferredSize += Increment; + + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + + BufferPtr += Increment; + Remain -= Increment; + } + + return EFI_SUCCESS; + +ErrorExit: + + if (Direction == EfiUsbDataIn) { + Cbi0ReportStatusCode ( + UsbCbiDev->DevicePath, + EFI_ERROR_CODE | EFI_ERROR_MINOR, + (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_EC_INPUT_ERROR) + ); + } else { + Cbi0ReportStatusCode ( + UsbCbiDev->DevicePath, + EFI_ERROR_CODE | EFI_ERROR_MINOR, + (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_EC_OUTPUT_ERROR) + ); + } + + if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) { + Status = Cbi0RecoveryReset (UsbCbiDev); + } + + *DataSize = (UINT32) TransferredSize; + return Status; +} + +STATIC +EFI_STATUS +Cbi0StatusPhase ( + IN USB_CBI_DEVICE *UsbCbiDev, + OUT INTERRUPT_DATA_BLOCK *InterruptDataBlock, + IN UINT16 Timeout + ) +/*++ + + Routine Description: + Get transfer status through BOT interface + + Arguments: + UsbCbiDev - USB_CBI_DEVICE + InterruptDataBlock - Interrupt Data Block for interrupt transfer + Timeout - Time out value in milliseconds + Returns: + EFI_SUCCESS + Others + +--*/ +{ + UINT8 EndpointAddress; + UINTN InterruptDataBlockLength; + UINT32 Result; + EFI_STATUS Status; + + ZeroMem (InterruptDataBlock, sizeof (INTERRUPT_DATA_BLOCK)); + + EndpointAddress = UsbCbiDev->InterruptEndpointDescriptor.EndpointAddress; + InterruptDataBlockLength = sizeof (INTERRUPT_DATA_BLOCK); + + Status = UsbCbiDev->UsbIo->UsbSyncInterruptTransfer ( + UsbCbiDev->UsbIo, + EndpointAddress, + InterruptDataBlock, + &InterruptDataBlockLength, + Timeout, + &Result + ); + if (EFI_ERROR (Status)) { + if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) { + // + // just endpoint stall happens + // + UsbClearEndpointHalt ( + UsbCbiDev->UsbIo, + EndpointAddress, + &Result + ); + gBS->Stall (100 * 1000); + } + + return Status; + } + + return EFI_SUCCESS; +} +// +// Cbi0 Atapi Protocol Implementation +// +STATIC +EFI_STATUS +EFIAPI +Cbi0MassStorageReset ( + IN EFI_USB_ATAPI_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +/*++ + + Routine Description: + Reset CBI Devices + + Arguments: + This - Protocol instance pointer. + ExtendedVerification - TRUE if we need to do strictly reset. + + Returns: + EFI_SUCCESS - Command succeeded. + EFI_DEVICE_ERROR - Command failed. + +--*/ +{ + EFI_STATUS Status; + EFI_USB_IO_PROTOCOL *UsbIo; + USB_CBI_DEVICE *UsbCbiDev; + + UsbCbiDev = USB_CBI_DEVICE_FROM_THIS (This); + UsbIo = UsbCbiDev->UsbIo; + + if (ExtendedVerification) { + // + // UsbIo->UsbPortReset (UsbIo); + // + } + + Status = Cbi0RecoveryReset (UsbCbiDev); + return Status; +} + +STATIC +EFI_STATUS +EFIAPI +Cbi0AtapiCommand ( + IN EFI_USB_ATAPI_PROTOCOL *This, + IN VOID *Command, + IN UINT8 CommandSize, + IN VOID *DataBuffer, + IN UINT32 BufferLength, + IN EFI_USB_DATA_DIRECTION Direction, + IN UINT16 TimeOutInMilliSeconds + ) +/*++ + + Routine Description: + Send ATAPI command using BOT protocol. + + Arguments: + This - Protocol instance pointer. + Command - Command buffer + CommandSize - Size of Command Buffer + DataBuffer - Data buffer + BufferLength - Length of Data buffer + Direction - Data direction of this command + TimeOutInMilliSeconds - Timeout value in ms + + Returns: + EFI_SUCCESS - Command succeeded. + EFI_DEVICE_ERROR - Command failed. + EFI_INVALID_PARAMETER - Invalidate parameter +--*/ +{ + EFI_STATUS Status; + USB_CBI_DEVICE *UsbCbiDev; + UINT32 BufferSize; + INTERRUPT_DATA_BLOCK InterruptDataBlock; + EFI_STATUS DataPhaseStatus; + + if (Direction != EfiUsbNoData) { + if (DataBuffer == NULL || BufferLength == 0) { + return EFI_INVALID_PARAMETER; + } + } + + DataPhaseStatus = EFI_SUCCESS; + // + // Get the context + // + UsbCbiDev = USB_CBI_DEVICE_FROM_THIS (This); + + // + // First send ATAPI command through Cbi + // + Status = Cbi0CommandPhase ( + UsbCbiDev, + Command, + CommandSize, + TimeOutInMilliSeconds + ); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + // + // Send/Get Data if there is a Data Stage + // + switch (Direction) { + + case EfiUsbDataIn: + case EfiUsbDataOut: + BufferSize = BufferLength; + + DataPhaseStatus = Cbi0DataPhase ( + UsbCbiDev, + &BufferSize, + DataBuffer, + Direction, + TimeOutInMilliSeconds + ); + break; + + case EfiUsbNoData: + break; + } + + if (EFI_ERROR (DataPhaseStatus)) { + return EFI_DEVICE_ERROR; + } + + // + // Status Phase + // + Status = Cbi0StatusPhase ( + UsbCbiDev, + &InterruptDataBlock, + TimeOutInMilliSeconds + ); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + if (This->CommandProtocol != EFI_USB_SUBCLASS_UFI) { + + if (InterruptDataBlock.bType == 0) { + // + // indicates command completion + // + switch (InterruptDataBlock.bValue & 0x03) { + + case 0: + Status = EFI_SUCCESS; + break; + + case 1: + Status = EFI_DEVICE_ERROR; + break; + + case 2: + Status = Cbi0RecoveryReset (UsbCbiDev); + if (EFI_ERROR (Status)) { + UsbCbiDev->UsbIo->UsbPortReset (UsbCbiDev->UsbIo); + } + + Status = EFI_DEVICE_ERROR; + break; + + case 3: + Status = EFI_DEVICE_ERROR; + } + } else { + Status = DataPhaseStatus; + } + + } else { + // + // UFI device, InterruptDataBlock.bType: ASC (Additional Sense Code) + // InterruptDataBlock.bValue: ASCQ (Additional Snese Code Qualifier) + // + Status = DataPhaseStatus; + } + + return Status; +} + +VOID +Cbi0ReportStatusCode ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value + ) +/*++ + + Routine Description: + Report Status Code in Usb Cbi0 Driver + + Arguments: + DevicePath - Use this to get Device Path + CodeType - Status Code Type + CodeValue - Status Code Value + + Returns: + None + +--*/ +{ + + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + CodeType, + Value, + DevicePath + ); +} diff --git a/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/ComponentName.c b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/ComponentName.c new file mode 100644 index 0000000000..0692c7fee5 --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/ComponentName.c @@ -0,0 +1,192 @@ +/*++ + +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 + +Abstract: + +--*/ + +#include "../cbi.h" + +extern EFI_DRIVER_BINDING_PROTOCOL gUsbCbi0DriverBinding; + +// +// EFI Component Name Functions +// +EFI_STATUS +EFIAPI +UsbCbi0ComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + +EFI_STATUS +EFIAPI +UsbCbi0ComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +// +// EFI Component Name Protocol +// +EFI_COMPONENT_NAME_PROTOCOL gUsbCbi0ComponentName = { + UsbCbi0ComponentNameGetDriverName, + UsbCbi0ComponentNameGetControllerName, + "eng" +}; + +STATIC EFI_UNICODE_STRING_TABLE mUsbCbi0DriverNameTable[] = { + { "eng", (CHAR16 *) L"Usb Cbi0 Mass Storage Driver" }, + { NULL , NULL } +}; + + +EFI_STATUS +EFIAPI +UsbCbi0ComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + 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. + 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. + + Returns: + EFI_SUCCESS - The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - DriverName is NULL. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return LookupUnicodeString ( + Language, + gUsbCbi0ComponentName.SupportedLanguages, + mUsbCbi0DriverNameTable, + DriverName + ); +} + +EFI_STATUS +EFIAPI +UsbCbi0ComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + 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. + 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. + 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. + 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. + + Returns: + 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. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - ControllerName is NULL. + EFI_UNSUPPORTED - The driver specified by This is not currently managing + the controller specified by ControllerHandle and + ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + EFI_STATUS Status; + USB_CBI_DEVICE *UsbCbiDev; + EFI_USB_ATAPI_PROTOCOL *UsbAtapi; + + // + // This is a device driver, so ChildHandle must be NULL. + // + if (ChildHandle != NULL) { + return EFI_UNSUPPORTED; + } + + // + // Get the device context + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiUsbAtapiProtocolGuid, + (VOID **) &UsbAtapi, + gUsbCbi0DriverBinding.DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + UsbCbiDev = USB_CBI_DEVICE_FROM_THIS (UsbAtapi); + + return LookupUnicodeString ( + Language, + gUsbCbi0ComponentName.SupportedLanguages, + UsbCbiDev->ControllerNameTable, + ControllerName + ); + +} diff --git a/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/UsbCbi0.mbd b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/UsbCbi0.mbd new file mode 100644 index 0000000000..17a63f9b21 --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/UsbCbi0.mbd @@ -0,0 +1,43 @@ + + + + + UsbCbi0 + A3527D16-E6CC-42f5-BADB-BF3DE177742B + 0 + FIX ME! + Copyright (c) 2004-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. + + 2006-03-12 17:09 + 2006-03-19 15:18 + + + UefiBootServicesTableLib + UefiMemoryLib + UefiLib + UefiDriverEntryPoint + UefiDriverModelLib + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + EdkDxePrintLib + BaseLib + EdkUsbLib + DxeMemoryAllocationLib + + diff --git a/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/UsbCbi0.msa b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/UsbCbi0.msa new file mode 100644 index 0000000000..a128159e12 --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/UsbCbi0.msa @@ -0,0 +1,68 @@ + + + + + UsbCbi0 + DXE_DRIVER + BS_DRIVER + A3527D16-E6CC-42f5-BADB-BF3DE177742B + 0 + Component description file for UsbCbi1 module + FIX ME! + Copyright (c) 2004-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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:18 + + + DebugLib + UefiDriverModelLib + UefiDriverEntryPoint + BaseLib + UefiLib + BaseMemoryLib + EdkUsbLib + ReportStatusCodeLib + MemoryAllocationLib + UefiBootServicesTableLib + + + cbi0.c + componentname.c + + + MdePkg + EdkModulePkg + + + DevicePath + UsbIo + UsbAtapi + + + + + + + gUsbCbi0DriverBinding + gUsbCbi0ComponentName + + + diff --git a/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/build.xml b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/build.xml new file mode 100644 index 0000000000..e406abee8b --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi1/UsbCbi1.mbd b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi1/UsbCbi1.mbd new file mode 100644 index 0000000000..e48251eb07 --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi1/UsbCbi1.mbd @@ -0,0 +1,43 @@ + + + + + UsbCbi1 + B40612B2-A063-11d4-9A3A-0090273FC14D + 0 + FIX ME! + Copyright (c) 2004-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. + + 2006-03-12 17:09 + 2006-03-19 15:18 + + + UefiBootServicesTableLib + UefiMemoryLib + UefiLib + UefiDriverEntryPoint + UefiDriverModelLib + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + EdkDxePrintLib + BaseLib + EdkUsbLib + DxeMemoryAllocationLib + + diff --git a/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi1/UsbCbi1.msa b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi1/UsbCbi1.msa new file mode 100644 index 0000000000..057585689e --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi1/UsbCbi1.msa @@ -0,0 +1,66 @@ + + + + + UsbCbi1 + DXE_DRIVER + BS_DRIVER + B40612B2-A063-11d4-9A3A-0090273FC14D + 0 + Component description file for UsbCbi1 module + FIX ME! + Copyright (c) 2004-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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:18 + + + DebugLib + UefiDriverModelLib + UefiDriverEntryPoint + BaseLib + UefiLib + BaseMemoryLib + EdkUsbLib + ReportStatusCodeLib + MemoryAllocationLib + UefiBootServicesTableLib + + + cbi1.c + + + MdePkg + EdkModulePkg + + + DevicePath + UsbIo + UsbAtapi + + + + + + + gCBI1DriverBinding + + + diff --git a/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi1/build.xml b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi1/build.xml new file mode 100644 index 0000000000..132e52237c --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi1/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi1/cbi1.c b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi1/cbi1.c new file mode 100644 index 0000000000..71644acef8 --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi1/cbi1.c @@ -0,0 +1,854 @@ +/*++ + +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: + + cbi1.c + +Abstract: + cbi1 transportation protocol implementation files + +--*/ + +#include "../cbi.h" + +EFI_STATUS +EFIAPI +UsbCBI1DriverEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +// +// CBI Function prototypes +// +STATIC +EFI_STATUS +CBI1CommandPhase ( + IN USB_CBI_DEVICE *UsbCbiDev, + IN VOID *Command, + IN UINT8 CommandSize, + OUT UINT32 *Result + ); + +STATIC +EFI_STATUS +CBI1DataPhase ( + IN USB_CBI_DEVICE *UsbCbiDev, + IN UINT32 DataSize, + IN OUT VOID *DataBuffer, + IN EFI_USB_DATA_DIRECTION Direction, + IN UINT16 Timeout, + OUT UINT32 *Result + ); + +// +// USB Atapi implementation +// +STATIC +EFI_STATUS +EFIAPI +CBI1AtapiCommand ( + IN EFI_USB_ATAPI_PROTOCOL *This, + IN VOID *Command, + IN UINT8 CommandSize, + IN VOID *DataBuffer, + IN UINT32 BufferLength, + IN EFI_USB_DATA_DIRECTION Direction, + IN UINT16 TimeOutInMilliSeconds + ); + +STATIC +EFI_STATUS +EFIAPI +CBI1MassStorageReset ( + IN EFI_USB_ATAPI_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +// +// CBI1 Driver Binding Protocol +// +STATIC +EFI_STATUS +EFIAPI +CBI1DriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +STATIC +EFI_STATUS +EFIAPI +CBI1DriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +STATIC +EFI_STATUS +EFIAPI +CBI1DriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +VOID +Cbi1ReportStatusCode ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value + ); + + +EFI_DRIVER_BINDING_PROTOCOL gCBI1DriverBinding = { + CBI1DriverBindingSupported, + CBI1DriverBindingStart, + CBI1DriverBindingStop, + 0x10, + NULL, + NULL +}; + +STATIC EFI_USB_ATAPI_PROTOCOL CBI1AtapiProtocol = { + CBI1AtapiCommand, + CBI1MassStorageReset, + 0 +}; + +// +// CBI1 Driver Binding implementation +// +STATIC +EFI_STATUS +EFIAPI +CBI1DriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + + Routine Description: + Test to see if this driver supports ControllerHandle. Any ControllerHandle + than contains a BlockIo and DiskIo protocol can be supported. + + Arguments: + This - Protocol instance pointer. + ControllerHandle - Handle of device to test + RemainingDevicePath - Not used + + Returns: + EFI_SUCCESS - This driver supports this device + EFI_ALREADY_STARTED - This driver is already running on this device + other - This driver does not support this device + +--*/ +{ + EFI_STATUS Status; + EFI_USB_IO_PROTOCOL *UsbIo; + EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor; + + // + // Check if the Controller supports USB IO protocol + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + (VOID **) &UsbIo, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Get the Controller interface descriptor + // + Status = UsbIo->UsbGetInterfaceDescriptor ( + UsbIo, + &InterfaceDescriptor + ); + if (EFI_ERROR (Status)) { + goto Exit; + } + // + // Bug here: just let Vendor specific CBI protocol get supported + // + if (!((InterfaceDescriptor.InterfaceClass == 0xFF) && + (InterfaceDescriptor.InterfaceProtocol == 0))) { + Status = EFI_UNSUPPORTED; + goto Exit; + } + +Exit: + gBS->CloseProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + return Status; + +} + +STATIC +EFI_STATUS +EFIAPI +CBI1DriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + + Routine Description: + Start this driver on ControllerHandle by opening a Block IO and Disk IO + protocol, reading Device Path, and creating a child handle with a + Disk IO and device path protocol. + + Arguments: + This - Protocol instance pointer. + ControllerHandle - Handle of device to bind driver to + RemainingDevicePath - Not used + + Returns: + EFI_SUCCESS - This driver is added to DeviceHandle + EFI_ALREADY_STARTED - This driver is already running on DeviceHandle + other - This driver does not support this device + +--*/ +{ + USB_CBI_DEVICE *UsbCbiDev; + UINT8 Index; + EFI_USB_ENDPOINT_DESCRIPTOR EndpointDescriptor; + EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor; + EFI_STATUS Status; + EFI_USB_IO_PROTOCOL *UsbIo; + BOOLEAN Found; + + Found = FALSE; + // + // Check if the Controller supports USB IO protocol + // + UsbCbiDev = NULL; + + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + (VOID **) &UsbIo, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Get the controller interface descriptor + // + Status = UsbIo->UsbGetInterfaceDescriptor ( + UsbIo, + &InterfaceDescriptor + ); + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + + CBI1AtapiProtocol.CommandProtocol = InterfaceDescriptor.InterfaceSubClass; + + UsbCbiDev = AllocateZeroPool (sizeof (USB_CBI_DEVICE)); + if (UsbCbiDev == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ErrorExit; + } + + UsbCbiDev->Signature = USB_CBI_DEVICE_SIGNATURE; + UsbCbiDev->UsbIo = UsbIo; + CopyMem (&UsbCbiDev->InterfaceDescriptor, &InterfaceDescriptor, sizeof (InterfaceDescriptor)); + CopyMem (&UsbCbiDev->UsbAtapiProtocol , &CBI1AtapiProtocol, sizeof (CBI1AtapiProtocol)); + + // + // Get the Device Path Protocol on Controller's handle + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiDevicePathProtocolGuid, + (VOID **) &UsbCbiDev->DevicePath, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + + for (Index = 0; Index < InterfaceDescriptor.NumEndpoints; Index++) { + UsbIo->UsbGetEndpointDescriptor ( + UsbIo, + Index, + &EndpointDescriptor + ); + + // + // We parse bulk endpoint + // + if (EndpointDescriptor.Attributes == 0x02) { + if (EndpointDescriptor.EndpointAddress & 0x80) { + CopyMem (&UsbCbiDev->BulkInEndpointDescriptor, &EndpointDescriptor, sizeof(EndpointDescriptor)); + //UsbCbiDev->BulkInEndpointDescriptor = EndpointDescriptor; + } else { + CopyMem (&UsbCbiDev->BulkOutEndpointDescriptor, &EndpointDescriptor, sizeof(EndpointDescriptor)); + //UsbCbiDev->BulkOutEndpointDescriptor = EndpointDescriptor; + } + + Found = TRUE; + } + // + // We parse interrupt endpoint + // + if (EndpointDescriptor.Attributes == 0x03) { + CopyMem (&UsbCbiDev->InterruptEndpointDescriptor, &EndpointDescriptor, sizeof(EndpointDescriptor)); + //UsbCbiDev->InterruptEndpointDescriptor = EndpointDescriptor; + Found = TRUE; + } + + } + // + // Double check we have these + // + if (!Found) { + goto ErrorExit; + } + // + // After installing Usb-Atapi protocol onto this handle + // it will be called by upper layer drivers such as Fat + // + Cbi1ReportStatusCode ( + UsbCbiDev->DevicePath, + EFI_PROGRESS_CODE, + (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_ENABLE) + ); + + Status = gBS->InstallProtocolInterface ( + &ControllerHandle, + &gEfiUsbAtapiProtocolGuid, + EFI_NATIVE_INTERFACE, + &UsbCbiDev->UsbAtapiProtocol + ); + + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + + return EFI_SUCCESS; + +ErrorExit: + gBS->CloseProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + if (UsbCbiDev != NULL) { + gBS->FreePool (UsbCbiDev); + } + + return Status; + +} + +STATIC +EFI_STATUS +EFIAPI +CBI1DriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + + Routine Description: + Stop this driver on ControllerHandle. Support stoping any child handles + created by this driver. + + Arguments: + This - Protocol instance pointer. + ControllerHandle - Handle of device to stop driver on + NumberOfChildren - Number of Children in the ChildHandleBuffer + ChildHandleBuffer - List of handles for the children we need to stop. + + Returns: + EFI_SUCCESS - This driver is removed DeviceHandle + EFI_UNSUPPORTED - Can't open the gEfiUsbAtapiProtocolGuid protocol + other - This driver was not removed from this device + +--*/ +{ + EFI_STATUS Status; + EFI_USB_ATAPI_PROTOCOL *CBI1AtapiProtocol; + USB_CBI_DEVICE *UsbCbiDev; + EFI_USB_IO_PROTOCOL *UsbIo; + + // + // Get our context back. + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiUsbAtapiProtocolGuid, + (VOID **) &CBI1AtapiProtocol, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + UsbCbiDev = USB_CBI_DEVICE_FROM_THIS (CBI1AtapiProtocol); + + UsbIo = UsbCbiDev->UsbIo; + + Cbi1ReportStatusCode ( + UsbCbiDev->DevicePath, + EFI_PROGRESS_CODE, + (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_DISABLE) + ); + + Status = gBS->UninstallProtocolInterface ( + ControllerHandle, + &gEfiUsbAtapiProtocolGuid, + &UsbCbiDev->UsbAtapiProtocol + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->CloseProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + gBS->FreePool (UsbCbiDev); + + return Status; + +} +// +// CBI1 command +// +STATIC +EFI_STATUS +CBI1CommandPhase ( + IN USB_CBI_DEVICE *UsbCbiDev, + IN VOID *Command, + IN UINT8 CommandSize, + OUT UINT32 *Result + ) +/*++ + + Routine Description: + In order to make consistence, CBI transportation protocol does only use + the first 3 parameters. Other parameters are not used here. + + Arguments: + UsbCbiDev - USB_CBI_DEVICE + Command - Command to send + CommandSize - Command Size + Result - Result to return + + Returns: + EFI_SUCCESS - This driver is removed DeviceHandle + other - This driver was not removed from this device +--*/ +{ + EFI_STATUS Status; + EFI_USB_IO_PROTOCOL *UsbIo; + EFI_USB_DEVICE_REQUEST Request; + UINT32 TimeOutInMilliSeconds; + + UsbIo = UsbCbiDev->UsbIo; + + ZeroMem (&Request, sizeof (EFI_USB_DEVICE_REQUEST)); + + // + // Device request see CBI specification + // + Request.RequestType = 0x21; + Request.Length = CommandSize; + + TimeOutInMilliSeconds = 1000; + + Status = UsbIo->UsbControlTransfer ( + UsbIo, + &Request, + EfiUsbDataOut, + TimeOutInMilliSeconds, + Command, + CommandSize, + Result + ); + + return Status; +} + +STATIC +EFI_STATUS +CBI1DataPhase ( + IN USB_CBI_DEVICE *UsbCbiDev, + IN UINT32 DataSize, + IN OUT VOID *DataBuffer, + IN EFI_USB_DATA_DIRECTION Direction, + IN UINT16 Timeout, + OUT UINT32 *Result + ) +/*++ + +Routine Description: + + CBI1 Data Phase + +Arguments: + + UsbCbiDev - USB_CBI_DEVICE + DataSize - Data Size + DataBuffer - Data Buffer + Direction - IN/OUT/NODATA + Timeout - Time out value in milliseconds + Result - Transfer result + +Returns: + + EFI_SUCCESS - Success + +--*/ +{ + EFI_STATUS Status; + EFI_USB_IO_PROTOCOL *UsbIo; + UINT8 EndpointAddr; + UINTN Remain; + UINTN Increment; + UINT32 MaxPacketLen; + UINT8 *BufferPtr; + + UsbIo = UsbCbiDev->UsbIo; + + Remain = DataSize; + BufferPtr = (UINT8 *) DataBuffer; + + // + // retrieve the the max packet length of the given endpoint + // + if (Direction == EfiUsbDataIn) { + MaxPacketLen = (UsbCbiDev->BulkInEndpointDescriptor).MaxPacketSize; + EndpointAddr = (UsbCbiDev->BulkInEndpointDescriptor).EndpointAddress; + } else { + MaxPacketLen = (UsbCbiDev->BulkOutEndpointDescriptor).MaxPacketSize; + EndpointAddr = (UsbCbiDev->BulkOutEndpointDescriptor).EndpointAddress; + } + + while (Remain > 0) { + // + // Using 15 packets to aVOID Bitstuff error + // + if (Remain > 15 * MaxPacketLen) { + Increment = 15 * MaxPacketLen; + } else { + Increment = Remain; + } + + Status = UsbIo->UsbBulkTransfer ( + UsbIo, + EndpointAddr, + BufferPtr, + &Increment, + Timeout, + Result + ); + + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + + BufferPtr += Increment; + Remain -= Increment; + } + + return EFI_SUCCESS; + +ErrorExit: + + if (Direction == EfiUsbDataIn) { + Cbi1ReportStatusCode ( + UsbCbiDev->DevicePath, + EFI_ERROR_CODE | EFI_ERROR_MINOR, + (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_EC_INPUT_ERROR) + ); + } else { + Cbi1ReportStatusCode ( + UsbCbiDev->DevicePath, + EFI_ERROR_CODE | EFI_ERROR_MINOR, + (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_EC_OUTPUT_ERROR) + ); + } + + if (((*Result) & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) { + // + // just endpoint stall happens + // + UsbClearEndpointHalt ( + UsbIo, + EndpointAddr, + Result + ); + } + + return Status; +} +// +// CBI1 USB ATAPI Protocol +// +STATIC +EFI_STATUS +EFIAPI +CBI1MassStorageReset ( + IN EFI_USB_ATAPI_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +/*++ + + Routine Description: + Reset CBI Devices + + Arguments: + This - Protocol instance pointer. + ExtendedVerification - TRUE if we need to do strictly reset. + + Returns: + EFI_SUCCESS - Command succeeded. + EFI_DEVICE_ERROR - Command failed. + +--*/ +{ + UINT8 ResetCommand[12]; + EFI_STATUS Status; + EFI_USB_IO_PROTOCOL *UsbIo; + USB_CBI_DEVICE *UsbCbiDev; + UINT8 EndpointAddr; + UINT32 Result; + + UsbCbiDev = USB_CBI_DEVICE_FROM_THIS (This); + UsbIo = UsbCbiDev->UsbIo; + + Cbi1ReportStatusCode ( + UsbCbiDev->DevicePath, + EFI_PROGRESS_CODE, + (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_RESET) + ); + + if (ExtendedVerification) { + UsbIo->UsbPortReset (UsbIo); + } + // + // CBI reset command protocol + // + SetMem (ResetCommand, sizeof (ResetCommand), 0xff); + ResetCommand[0] = 0x1d; + ResetCommand[1] = 0x04; + + Status = CBI1CommandPhase ( + UsbCbiDev, + ResetCommand, + 12, + &Result + ); + + // + // clear bulk in endpoint stall feature + // + EndpointAddr = UsbCbiDev->BulkInEndpointDescriptor.EndpointAddress; + UsbClearEndpointHalt ( + UsbIo, + EndpointAddr, + &Result + ); + + // + // clear bulk out endpoint stall feature + // + EndpointAddr = UsbCbiDev->BulkOutEndpointDescriptor.EndpointAddress; + UsbClearEndpointHalt ( + UsbIo, + EndpointAddr, + &Result + ); + + return EFI_SUCCESS; + +} + +STATIC +EFI_STATUS +EFIAPI +CBI1AtapiCommand ( + IN EFI_USB_ATAPI_PROTOCOL *This, + IN VOID *Command, + IN UINT8 CommandSize, + IN VOID *DataBuffer, + IN UINT32 BufferLength, + IN EFI_USB_DATA_DIRECTION Direction, + IN UINT16 TimeOutInMilliSeconds + ) +/*++ + + Routine Description: + Send ATAPI command using CBI1 protocol. + + Arguments: + This - Protocol instance pointer. + Command - Command buffer + CommandSize - Size of Command Buffer + DataBuffer - Data buffer + BufferLength - Length of Data buffer + Direction - Data direction of this command + TimeOutInMilliSeconds - Timeout value in ms + + Returns: + EFI_SUCCESS - Command succeeded. + EFI_DEVICE_ERROR - Command failed. + +--*/ +{ + EFI_STATUS Status; + USB_CBI_DEVICE *UsbCbiDev; + UINT32 Result; + UINT8 Index; + UINT8 MaxRetryNum; + + UsbCbiDev = USB_CBI_DEVICE_FROM_THIS (This); + + MaxRetryNum = 3; + + for (Index = 0; Index < MaxRetryNum; Index++) { + + // + // First send ATAPI command through CBI1 + // + Status = CBI1CommandPhase ( + UsbCbiDev, + Command, + CommandSize, + &Result + ); + if (EFI_ERROR (Status)) { + + switch (Result) { + + case EFI_USB_NOERROR: + case EFI_USB_ERR_STALL: + case EFI_USB_ERR_SYSTEM: + return EFI_DEVICE_ERROR; + + default: + continue; + break; + } + } else { + break; + } + } + + if (Index == MaxRetryNum) { + return EFI_DEVICE_ERROR; + } + + for (Index = 0; Index < MaxRetryNum; Index++) { + // + // Send/Get Data if there is a Data Stage + // + switch (Direction) { + + case EfiUsbDataIn: + case EfiUsbDataOut: + Status = CBI1DataPhase ( + UsbCbiDev, + BufferLength, + DataBuffer, + Direction, + TimeOutInMilliSeconds, + &Result + ); + + if (EFI_ERROR (Status)) { + switch (Result) { + + case EFI_USB_NOERROR: + case EFI_USB_ERR_STALL: + case EFI_USB_ERR_SYSTEM: + return EFI_DEVICE_ERROR; + + default: + continue; + break; + } + + } else { + + return EFI_SUCCESS; + } + break; + + case EfiUsbNoData: + return EFI_SUCCESS; + } + } + // + // If goes here, means met error. + // + return EFI_DEVICE_ERROR; +} + +VOID +Cbi1ReportStatusCode ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value + ) +/*++ + + Routine Description: + Report Status Code in Usb Cbi1 Driver + + Arguments: + DevicePath - Use this to get Device Path + CodeType - Status Code Type + CodeValue - Status Code Value + + Returns: + None + +--*/ +{ + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + CodeType, + Value, + DevicePath + ); + +} diff --git a/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/cbi.h b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/cbi.h new file mode 100644 index 0000000000..dfbe4d9886 --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/cbi.h @@ -0,0 +1,70 @@ +/*++ + +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: + + cbi.h + +Abstract: + + USB CBI transportation protocol definitions. +--*/ + +#ifndef _CBI_H +#define _CBI_H + + +#include + +#define bit(a) (1 << (a)) + +#define MASS_STORAGE_CLASS 0x08 +#define CBI0_INTERFACE_PROTOCOL 0x00 +#define CBI1_INTERFACE_PROTOCOL 0x01 + +// +// in millisecond unit +// +#define STALL_1_SECOND 1000 + +#pragma pack(1) +// +// Data block definition for transportation through interrupt endpoint +// +typedef struct { + UINT8 bType; + UINT8 bValue; +} INTERRUPT_DATA_BLOCK; + +#pragma pack() + +#define USB_CBI_DEVICE_SIGNATURE EFI_SIGNATURE_32 ('u', 'c', 'b', 'i') + +// +// Device structure for CBI, interrupt endpoint may be not used in +// CBI1 Protocol +// +typedef struct { + UINT32 Signature; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_USB_ATAPI_PROTOCOL UsbAtapiProtocol; + EFI_USB_IO_PROTOCOL *UsbIo; + EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor; + EFI_USB_ENDPOINT_DESCRIPTOR BulkInEndpointDescriptor; + EFI_USB_ENDPOINT_DESCRIPTOR BulkOutEndpointDescriptor; + EFI_USB_ENDPOINT_DESCRIPTOR InterruptEndpointDescriptor; + EFI_UNICODE_STRING_TABLE *ControllerNameTable; +} USB_CBI_DEVICE; + +#define USB_CBI_DEVICE_FROM_THIS(a) \ + CR(a, USB_CBI_DEVICE, UsbAtapiProtocol, USB_CBI_DEVICE_SIGNATURE) + +#endif -- cgit v1.2.3