summaryrefslogtreecommitdiff
path: root/EdkModulePkg/Bus/Usb/UsbMassStorage
diff options
context:
space:
mode:
authorbbahnsen <bbahnsen@6f19259b-4bc3-4df7-8a09-765794883524>2006-04-21 22:54:32 +0000
committerbbahnsen <bbahnsen@6f19259b-4bc3-4df7-8a09-765794883524>2006-04-21 22:54:32 +0000
commit878ddf1fc3540a715f63594ed22b6929e881afb4 (patch)
treec56c44dac138137b510e1fba7c3efe5e4d84bea2 /EdkModulePkg/Bus/Usb/UsbMassStorage
downloadedk2-platforms-878ddf1fc3540a715f63594ed22b6929e881afb4.tar.xz
Initial import.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'EdkModulePkg/Bus/Usb/UsbMassStorage')
-rw-r--r--EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/ComponentName.c154
-rw-r--r--EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorage.c727
-rw-r--r--EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorage.h59
-rw-r--r--EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorage.mbd43
-rw-r--r--EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorage.msa70
-rw-r--r--EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorageData.h394
-rw-r--r--EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorageHelper.c1653
-rw-r--r--EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorageHelper.h111
-rw-r--r--EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/build.xml47
9 files changed, 3258 insertions, 0 deletions
diff --git a/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/ComponentName.c b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/ComponentName.c
new file mode 100644
index 0000000000..a021d95389
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/ComponentName.c
@@ -0,0 +1,154 @@
+/*++
+
+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 "UsbMassStorage.h"
+
+//
+// EFI Component Name Functions
+//
+EFI_STATUS
+EFIAPI
+UsbMassStorageComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+EFI_STATUS
+EFIAPI
+UsbMassStorageComponentNameGetControllerName (
+ 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 gUsbMassStorageComponentName = {
+ UsbMassStorageComponentNameGetDriverName,
+ UsbMassStorageComponentNameGetControllerName,
+ "eng"
+};
+
+STATIC EFI_UNICODE_STRING_TABLE mUsbMassStorageDriverNameTable[] = {
+ { "eng", (CHAR16 *) L"Generic USB Mass Storage Driver" },
+ { NULL , NULL }
+};
+
+EFI_STATUS
+EFIAPI
+UsbMassStorageComponentNameGetDriverName (
+ 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,
+ gUsbMassStorageComponentName.SupportedLanguages,
+ mUsbMassStorageDriverNameTable,
+ DriverName
+ );
+}
+
+EFI_STATUS
+EFIAPI
+UsbMassStorageComponentNameGetControllerName (
+ 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.
+
+--*/
+{
+ return EFI_UNSUPPORTED;
+}
diff --git a/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorage.c b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorage.c
new file mode 100644
index 0000000000..932b8c5ed9
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorage.c
@@ -0,0 +1,727 @@
+/*++
+
+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:
+
+ UsbMassStorage.c
+
+Abstract:
+
+ USB Mass Storage Driver
+
+Revision History
+
+--*/
+
+#include "UsbMassStorage.h"
+#include "UsbMassStorageHelper.h"
+
+extern EFI_COMPONENT_NAME_PROTOCOL gUsbMassStorageComponentName;
+
+//
+// Prototypes
+// Driver model protocol interface
+//
+EFI_STATUS
+EFIAPI
+USBMassStorageDriverBindingEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+EFI_STATUS
+EFIAPI
+USBFloppyDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+EFI_STATUS
+EFIAPI
+USBFloppyDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+EFI_STATUS
+EFIAPI
+USBFloppyDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ );
+
+//
+// Block I/O Protocol Interface
+//
+STATIC
+EFI_STATUS
+EFIAPI
+USBFloppyReset (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ );
+
+STATIC
+EFI_STATUS
+EFIAPI
+USBFloppyReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ );
+
+STATIC
+EFI_STATUS
+EFIAPI
+USBFloppyWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ );
+
+STATIC
+EFI_STATUS
+EFIAPI
+USBFloppyFlushBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This
+ );
+
+//
+// USB Floppy Driver Global Variables
+//
+EFI_DRIVER_BINDING_PROTOCOL gUSBFloppyDriverBinding = {
+ USBFloppyDriverBindingSupported,
+ USBFloppyDriverBindingStart,
+ USBFloppyDriverBindingStop,
+ 0x10,
+ NULL,
+ NULL
+};
+
+EFI_STATUS
+EFIAPI
+USBFloppyDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+ Routine Description:
+ Test to see if this driver supports ControllerHandle. Any ControllerHandle
+ that has UsbHcProtocol installed will be supported.
+
+ Arguments:
+ This - Protocol instance pointer.
+ Controller - Handle of device to test
+ RemainingDevicePath - Not used
+
+ Returns:
+ EFI_SUCCESS - This driver supports this device.
+ EFI_UNSUPPORTED - This driver does not support this device.
+
+--*/
+{
+ EFI_STATUS OpenStatus;
+ EFI_USB_ATAPI_PROTOCOL *AtapiProtocol;
+
+ //
+ // check whether EFI_USB_ATAPI_PROTOCOL exists, if it does,
+ // then the controller must be a USB Mass Storage Controller
+ //
+ OpenStatus = gBS->OpenProtocol (
+ Controller,
+ &gEfiUsbAtapiProtocolGuid,
+ (VOID **) &AtapiProtocol,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (OpenStatus)) {
+ return OpenStatus;
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbAtapiProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+USBFloppyDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+ Routine Description:
+ Starting the Usb Bus Driver
+
+ Arguments:
+ This - Protocol instance pointer.
+ Controller - Handle of device to test
+ RemainingDevicePath - Not used
+
+ Returns:
+ EFI_SUCCESS - This driver supports this device.
+ EFI_UNSUPPORTED - This driver does not support this device.
+ EFI_DEVICE_ERROR - This driver cannot be started due to device
+ Error
+ EFI_OUT_OF_RESOURCES- Can't allocate memory resources
+ EFI_ALREADY_STARTED - Thios driver has been started
+--*/
+{
+ EFI_STATUS Status;
+ EFI_USB_ATAPI_PROTOCOL *AtapiProtocol;
+ USB_FLOPPY_DEV *UsbFloppyDevice;
+
+ UsbFloppyDevice = NULL;
+ //
+ // Check whether Usb Atapi Protocol attached on the controller handle.
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiUsbAtapiProtocolGuid,
+ (VOID **) &AtapiProtocol,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ sizeof (USB_FLOPPY_DEV),
+ (VOID **) &UsbFloppyDevice
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbAtapiProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ return Status;
+ }
+
+ ZeroMem (UsbFloppyDevice, sizeof (USB_FLOPPY_DEV));
+
+ UsbFloppyDevice->Handle = Controller;
+ UsbFloppyDevice->BlkIo.Media = &UsbFloppyDevice->BlkMedia;
+ UsbFloppyDevice->Signature = USB_FLOPPY_DEV_SIGNATURE;
+ UsbFloppyDevice->BlkIo.Reset = USBFloppyReset;
+ UsbFloppyDevice->BlkIo.ReadBlocks = USBFloppyReadBlocks;
+ UsbFloppyDevice->BlkIo.WriteBlocks = USBFloppyWriteBlocks;
+ UsbFloppyDevice->BlkIo.FlushBlocks = USBFloppyFlushBlocks;
+ UsbFloppyDevice->AtapiProtocol = AtapiProtocol;
+
+ //
+ // Identify drive type and retrieve media information.
+ //
+ Status = USBFloppyIdentify (UsbFloppyDevice);
+ if (EFI_ERROR (Status)) {
+ if (UsbFloppyDevice->SenseData != NULL) {
+ gBS->FreePool (UsbFloppyDevice->SenseData);
+ }
+
+ gBS->FreePool (UsbFloppyDevice);
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbAtapiProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ return Status;
+ }
+ //
+ // Install Block I/O protocol for the usb floppy device.
+ //
+ Status = gBS->InstallProtocolInterface (
+ &Controller,
+ &gEfiBlockIoProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &UsbFloppyDevice->BlkIo
+ );
+ if (EFI_ERROR (Status)) {
+ if (UsbFloppyDevice->SenseData != NULL) {
+ gBS->FreePool (UsbFloppyDevice->SenseData);
+ }
+
+ gBS->FreePool (UsbFloppyDevice);
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbAtapiProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+
+EFI_STATUS
+EFIAPI
+USBFloppyDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ 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.
+ Controller - 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
+ EFI_DEVICE_ERROR
+ others
+
+--*/
+{
+ EFI_STATUS Status;
+ USB_FLOPPY_DEV *UsbFloppyDevice;
+ EFI_BLOCK_IO_PROTOCOL *BlkIo;
+
+ //
+ // First find USB_FLOPPY_DEV
+ //
+ gBS->OpenProtocol (
+ Controller,
+ &gEfiBlockIoProtocolGuid,
+ (VOID **) &BlkIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ UsbFloppyDevice = USB_FLOPPY_DEV_FROM_THIS (BlkIo);
+
+ //
+ // Uninstall Block I/O protocol from the device handle
+ //
+ Status = gBS->UninstallProtocolInterface (
+ Controller,
+ &gEfiBlockIoProtocolGuid,
+ &UsbFloppyDevice->BlkIo
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Stop using EFI_USB_ATAPI_PROTOCOL
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbAtapiProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ if (UsbFloppyDevice->SenseData != NULL) {
+ gBS->FreePool (UsbFloppyDevice->SenseData);
+ }
+
+ gBS->FreePool (UsbFloppyDevice);
+
+ return EFI_SUCCESS;
+}
+
+
+STATIC
+EFI_STATUS
+EFIAPI
+USBFloppyReset (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+/*++
+
+ Routine Description:
+ Implements EFI_BLOCK_IO_PROTOCOL.Reset() function.
+
+ Arguments:
+ This The EFI_BLOCK_IO_PROTOCOL instance.
+ ExtendedVerification
+ Indicates that the driver may perform a more exhaustive
+ verification operation of the device during reset.
+ (This parameter is ingored in this driver.)
+
+ Returns:
+ EFI_SUCCESS - Success
+--*/
+{
+ USB_FLOPPY_DEV *UsbFloppyDevice;
+ EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
+ EFI_STATUS Status;
+
+ UsbFloppyDevice = USB_FLOPPY_DEV_FROM_THIS (This);
+
+ UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
+
+ //
+ // directly calling EFI_USB_ATAPI_PROTOCOL.Reset() to implement reset.
+ //
+ Status = UsbAtapiInterface->UsbAtapiReset (UsbAtapiInterface, TRUE);
+
+ return Status;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+USBFloppyReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+/*++
+
+ Routine Description:
+ Implements EFI_BLOCK_IO_PROTOCOL.ReadBlocks() function.
+
+ Arguments:
+ This The EFI_BLOCK_IO_PROTOCOL instance.
+ MediaId The media id that the read request is for.
+ LBA The starting logical block address to read from on the device.
+ BufferSize
+ The size of the Buffer in bytes. This must be a multiple of
+ the intrinsic block size of the device.
+ Buffer A pointer to the destination buffer for the data. The caller
+ is responsible for either having implicit or explicit ownership
+ of the buffer.
+
+ Returns:
+ EFI_INVALID_PARAMETER - Parameter is error
+ EFI_SUCCESS - Success
+ EFI_DEVICE_ERROR - Hardware Error
+ EFI_NO_MEDIA - No media
+ EFI_MEDIA_CHANGED - Media Change
+ EFI_BAD_BUFFER_SIZE - Buffer size is bad
+ --*/
+{
+ USB_FLOPPY_DEV *UsbFloppyDevice;
+ EFI_STATUS Status;
+ EFI_BLOCK_IO_MEDIA *Media;
+ UINTN BlockSize;
+ UINTN NumberOfBlocks;
+ BOOLEAN MediaChange;
+ EFI_TPL OldTpl;
+ UINT32 Retry;
+
+ OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY);
+ Status = EFI_SUCCESS;
+ MediaChange = FALSE;
+ Retry = 0;
+
+ UsbFloppyDevice = USB_FLOPPY_DEV_FROM_THIS (This);
+
+ //
+ // Check parameters
+ //
+ if (!Buffer) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ if (BufferSize == 0) {
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+
+ UsbFloppyTestUnitReady (UsbFloppyDevice);
+
+ Status = UsbFloppyDetectMedia (UsbFloppyDevice, &MediaChange);
+ if (EFI_ERROR (Status)) {
+
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+ if (MediaChange) {
+ gBS->RestoreTPL (OldTpl);
+ gBS->ReinstallProtocolInterface (
+ UsbFloppyDevice->Handle,
+ &gEfiBlockIoProtocolGuid,
+ &UsbFloppyDevice->BlkIo,
+ &UsbFloppyDevice->BlkIo
+ );
+ gBS->RaiseTPL (EFI_TPL_NOTIFY);
+ }
+
+ Media = UsbFloppyDevice->BlkIo.Media;
+ BlockSize = Media->BlockSize;
+ NumberOfBlocks = BufferSize / BlockSize;
+
+ if (!(Media->MediaPresent)) {
+ Status = EFI_NO_MEDIA;
+ goto Done;
+ }
+
+ if (MediaId != Media->MediaId) {
+ Status = EFI_MEDIA_CHANGED;
+ goto Done;
+ }
+
+ if (BufferSize % BlockSize != 0) {
+ Status = EFI_BAD_BUFFER_SIZE;
+ goto Done;
+ }
+
+ if (LBA > Media->LastBlock) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ if ((LBA + NumberOfBlocks - 1) > Media->LastBlock) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ if (!EFI_ERROR (Status)) {
+
+ Status = USBFloppyRead10 (UsbFloppyDevice, Buffer, LBA, 1);
+ if (EFI_ERROR (Status)) {
+ This->Reset (This, TRUE);
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+ LBA += 1;
+ NumberOfBlocks -= 1;
+ Buffer = (UINT8 *) Buffer + This->Media->BlockSize;
+
+ if (NumberOfBlocks == 0) {
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+
+ Status = USBFloppyRead10 (UsbFloppyDevice, Buffer, LBA, NumberOfBlocks);
+ if (EFI_ERROR (Status)) {
+ This->Reset (This, TRUE);
+ Status = EFI_DEVICE_ERROR;
+ }
+ }
+
+Done:
+ gBS->RestoreTPL (OldTpl);
+ return Status;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+USBFloppyWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ )
+/*++
+
+ Routine Description:
+ Implements EFI_BLOCK_IO_PROTOCOL.WriteBlocks() function.
+
+ Arguments:
+ This The EFI_BLOCK_IO_PROTOCOL instance.
+ MediaId The media id that the write request is for.
+ LBA The starting logical block address to be written.
+ The caller is responsible for writing to only
+ legitimate locations.
+ BufferSize
+ The size of the Buffer in bytes. This must be a multiple of
+ the intrinsic block size of the device.
+ Buffer A pointer to the source buffer for the data. The caller
+ is responsible for either having implicit or explicit ownership
+ of the buffer.
+
+ Returns:
+ EFI_INVALID_PARAMETER - Parameter is error
+ EFI_SUCCESS - Success
+ EFI_DEVICE_ERROR - Hardware Error
+ EFI_NO_MEDIA - No media
+ EFI_MEDIA_CHANGED - Media Change
+ EFI_BAD_BUFFER_SIZE - Buffer size is bad
+
+--*/
+{
+ USB_FLOPPY_DEV *UsbFloppyDevice;
+ EFI_STATUS Status;
+ EFI_BLOCK_IO_MEDIA *Media;
+ UINTN BlockSize;
+ UINTN NumberOfBlocks;
+ BOOLEAN MediaChange;
+ EFI_TPL OldTpl;
+ UINT32 Retry;
+
+ OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY);
+ Status = EFI_SUCCESS;
+ MediaChange = FALSE;
+ Retry = 0;
+
+ UsbFloppyDevice = USB_FLOPPY_DEV_FROM_THIS (This);
+
+ //
+ // Check parameters
+ //
+ if (!Buffer) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ if (BufferSize == 0) {
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+
+ UsbFloppyTestUnitReady (UsbFloppyDevice);
+
+ Status = UsbFloppyDetectMedia (UsbFloppyDevice, &MediaChange);
+ if (EFI_ERROR (Status)) {
+
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+ if (MediaChange) {
+ gBS->RestoreTPL (OldTpl);
+ gBS->ReinstallProtocolInterface (
+ UsbFloppyDevice->Handle,
+ &gEfiBlockIoProtocolGuid,
+ &UsbFloppyDevice->BlkIo,
+ &UsbFloppyDevice->BlkIo
+ );
+ gBS->RaiseTPL (EFI_TPL_NOTIFY);
+ }
+
+ Media = UsbFloppyDevice->BlkIo.Media;
+ BlockSize = Media->BlockSize;
+ NumberOfBlocks = BufferSize / BlockSize;
+
+ if (!(Media->MediaPresent)) {
+ Status = EFI_NO_MEDIA;
+ goto Done;
+ }
+
+ if (MediaId != Media->MediaId) {
+ Status = EFI_MEDIA_CHANGED;
+ goto Done;
+ }
+
+ if (BufferSize % BlockSize != 0) {
+ Status = EFI_BAD_BUFFER_SIZE;
+ goto Done;
+ }
+
+ if (LBA > Media->LastBlock) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ if ((LBA + NumberOfBlocks - 1) > Media->LastBlock) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ if (UsbFloppyDevice->BlkMedia.ReadOnly) {
+ Status = EFI_WRITE_PROTECTED;
+ goto Done;
+ }
+
+ if (!EFI_ERROR (Status)) {
+ Status = USBFloppyWrite10 (UsbFloppyDevice, Buffer, LBA, 1);
+ if (EFI_ERROR (Status)) {
+ This->Reset (This, TRUE);
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+ LBA += 1;
+ NumberOfBlocks -= 1;
+ Buffer = (UINT8 *) Buffer + This->Media->BlockSize;
+
+ if (NumberOfBlocks == 0) {
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+
+ Status = USBFloppyWrite10 (UsbFloppyDevice, Buffer, LBA, NumberOfBlocks);
+ if (EFI_ERROR (Status)) {
+ This->Reset (This, TRUE);
+ Status = EFI_DEVICE_ERROR;
+ }
+ }
+
+Done:
+ gBS->RestoreTPL (OldTpl);
+ return Status;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+USBFloppyFlushBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This
+ )
+/*++
+
+ Routine Description:
+ Implements EFI_BLOCK_IO_PROTOCOL.FlushBlocks() function.
+ (In this driver, this function just returns EFI_SUCCESS.)
+
+ Arguments:
+ This The EFI_BLOCK_IO_PROTOCOL instance.
+
+ Returns:
+ EFI_SUCCESS - Success
+--*/
+{
+ return EFI_SUCCESS;
+}
diff --git a/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorage.h b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorage.h
new file mode 100644
index 0000000000..4874bb08cc
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorage.h
@@ -0,0 +1,59 @@
+/*++
+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:
+
+ UsbMassStorage.h
+
+Abstract:
+
+ Header file for USB Mass Storage Driver's Data Structures
+
+Revision History
+--*/
+
+#ifndef _USB_FLP_H
+#define _USB_FLP_H
+
+
+#include <IndustryStandard/usb.h>
+#include "UsbMassStorageData.h"
+
+#define CLASS_MASSTORAGE 8
+#define SUBCLASS_UFI 4
+#define SUBCLASS_8070 5
+#define PROTOCOL_BOT 0x50
+#define PROTOCOL_CBI0 0
+#define PROTOCOL_CBI1 1
+
+#define USBFLOPPY 1
+#define USBFLOPPY2 2 // for those that use ReadCapacity(0x25) command to retrieve media capacity
+#define USBCDROM 3
+
+#define USB_FLOPPY_DEV_SIGNATURE EFI_SIGNATURE_32 ('u', 'f', 'l', 'p')
+
+typedef struct {
+ UINTN Signature;
+
+ EFI_HANDLE Handle;
+ EFI_BLOCK_IO_PROTOCOL BlkIo;
+ EFI_BLOCK_IO_MEDIA BlkMedia;
+ EFI_USB_ATAPI_PROTOCOL *AtapiProtocol;
+
+ REQUEST_SENSE_DATA *SenseData;
+ UINT8 SenseDataNumber;
+ UINT8 DeviceType;
+
+} USB_FLOPPY_DEV;
+
+#define USB_FLOPPY_DEV_FROM_THIS(a) \
+ CR(a, USB_FLOPPY_DEV, BlkIo, USB_FLOPPY_DEV_SIGNATURE)
+
+#endif
diff --git a/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorage.mbd b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorage.mbd
new file mode 100644
index 0000000000..c9c9b5c73b
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorage.mbd
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<ModuleBuildDescription xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MbdHeader>
+ <BaseName>UsbMassStorage</BaseName>
+ <Guid>A5C6D68B-E78A-4426-9278-A8F0D9EB4D8F</Guid>
+ <Version>0</Version>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, Intel Corporation</Copyright>
+ <License>
+ 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.
+ </License>
+ <Created>2006-03-12 17:09</Created>
+ <Modified>2006-03-19 15:18</Modified>
+ </MbdHeader>
+ <Libraries>
+ <Library>UefiBootServicesTableLib</Library>
+ <Library>UefiMemoryLib</Library>
+ <Library>UefiLib</Library>
+ <Library>UefiDriverEntryPoint</Library>
+ <Library>UefiDriverModelLib</Library>
+ <Library>DxeReportStatusCodeLib</Library>
+ <Library>BaseDebugLibReportStatusCode</Library>
+ <Library>EdkDxePrintLib</Library>
+ <Library>BaseLib</Library>
+ <Library>EdkUsbLib</Library>
+ <Library>DxeMemoryAllocationLib</Library>
+ </Libraries>
+</ModuleBuildDescription>
diff --git a/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorage.msa b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorage.msa
new file mode 100644
index 0000000000..d071c9f656
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorage.msa
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MsaHeader>
+ <BaseName>UsbMassStorage</BaseName>
+ <ModuleType>DXE_DRIVER</ModuleType>
+ <ComponentType>BS_DRIVER</ComponentType>
+ <Guid>A5C6D68B-E78A-4426-9278-A8F0D9EB4D8F</Guid>
+ <Version>0</Version>
+ <Abstract>Component description file for UsbMassStorage module</Abstract>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, Intel Corporation</Copyright>
+ <License>
+ 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.
+ </License>
+ <Specification>0</Specification>
+ <Created>2006-03-12 17:09</Created>
+ <Updated>2006-03-19 15:18</Updated>
+ </MsaHeader>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_CONSUMED">DebugLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiDriverModelLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiDriverEntryPoint</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseMemoryLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">EdkUsbLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">MemoryAllocationLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiBootServicesTableLib</LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>UsbMassStorage.h</Filename>
+ <Filename>UsbMassStorageData.h</Filename>
+ <Filename>UsbMassStorageHelper.h</Filename>
+ <Filename>UsbMassStorage.c</Filename>
+ <Filename>UsbMassStorageHelper.c</Filename>
+ <Filename>ComponentName.c</Filename>
+ </SourceFiles>
+ <Includes>
+ <PackageName>MdePkg</PackageName>
+ <PackageName>EdkModulePkg</PackageName>
+ </Includes>
+ <Protocols>
+ <Protocol Usage="TO_START">UsbAtapi</Protocol>
+ <Protocol Usage="BY_START">BlockIo</Protocol>
+ </Protocols>
+ <Externs>
+ <Extern>
+ <ModuleEntryPoint></ModuleEntryPoint>
+ </Extern>
+ <Extern>
+ <DriverBinding>gUSBFloppyDriverBinding</DriverBinding>
+ <ComponentName>gUsbMassStorageComponentName</ComponentName>
+ </Extern>
+ </Externs>
+</ModuleSurfaceArea>
diff --git a/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorageData.h b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorageData.h
new file mode 100644
index 0000000000..598c82e220
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorageData.h
@@ -0,0 +1,394 @@
+/*++
+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:
+
+ UsbMassStorageData.h
+
+Abstract:
+
+ Header file for USB Mass Storage Device related Data Structures
+
+Revision History
+--*/
+
+#ifndef _USB_FLP_DATA_H
+#define _USB_FLP_DATA_H
+
+//
+// bit definition
+//
+#define bit(a) 1 << (a)
+
+//
+// timeout unit is in millisecond.
+//
+#define USBFLPTIMEOUT 2000
+#define STALL_1_MILLI_SECOND 1000
+
+//
+// ATAPI Packet Command
+//
+#pragma pack(1)
+
+typedef struct {
+ UINT8 opcode;
+ UINT8 reserved_1;
+ UINT8 reserved_2;
+ UINT8 reserved_3;
+ UINT8 reserved_4;
+ UINT8 reserved_5;
+ UINT8 reserved_6;
+ UINT8 reserved_7;
+ UINT8 reserved_8;
+ UINT8 reserved_9;
+ UINT8 reserved_10;
+ UINT8 reserved_11;
+} TEST_UNIT_READY_CMD;
+
+typedef struct {
+ UINT8 opcode;
+ UINT8 reserved_1 : 4;
+ UINT8 lun : 4;
+ UINT8 page_code;
+ UINT8 reserved_3;
+ UINT8 allocation_length;
+ UINT8 reserved_5;
+ UINT8 reserved_6;
+ UINT8 reserved_7;
+ UINT8 reserved_8;
+ UINT8 reserved_9;
+ UINT8 reserved_10;
+ UINT8 reserved_11;
+} INQUIRY_CMD;
+
+typedef struct {
+ UINT8 opcode;
+ UINT8 reserved_1 : 4;
+ UINT8 lun : 4;
+ UINT8 reserved_2;
+ UINT8 reserved_3;
+ UINT8 allocation_length;
+ UINT8 reserved_5;
+ UINT8 reserved_6;
+ UINT8 reserved_7;
+ UINT8 reserved_8;
+ UINT8 reserved_9;
+ UINT8 reserved_10;
+ UINT8 reserved_11;
+} REQUEST_SENSE_CMD;
+
+typedef struct {
+ UINT8 opcode;
+ UINT8 reserved_1 : 4;
+ UINT8 lun : 4;
+ UINT8 page_code : 6;
+ UINT8 page_control : 2;
+ UINT8 reserved_3;
+ UINT8 reserved_4;
+ UINT8 reserved_5;
+ UINT8 reserved_6;
+ UINT8 parameter_list_length_hi;
+ UINT8 parameter_list_length_lo;
+ UINT8 reserved_9;
+ UINT8 reserved_10;
+ UINT8 reserved_11;
+} MODE_SENSE_CMD_UFI;
+
+typedef struct {
+ UINT8 opcode;
+ UINT8 reserved_1 : 3;
+ UINT8 dbd : 1;
+ UINT8 reserved_2 : 1;
+ UINT8 lun : 3;
+ UINT8 page_code : 6;
+ UINT8 page_control : 2;
+ UINT8 reserved_3;
+ UINT8 allocation_length;
+ UINT8 control;
+} MODE_SENSE_CMD_SCSI;
+
+typedef struct {
+ UINT8 opcode;
+ UINT8 reserved_1 : 5;
+ UINT8 lun : 3;
+ UINT8 Lba0;
+ UINT8 Lba1;
+ UINT8 Lba2;
+ UINT8 Lba3;
+ UINT8 reserved_6;
+ UINT8 TranLen0;
+ UINT8 TranLen1;
+ UINT8 reserved_9;
+ UINT8 reserved_10;
+ UINT8 reserved_11;
+} READ10_CMD;
+
+typedef struct {
+ UINT8 opcode;
+ UINT8 reserved_1;
+ UINT8 reserved_2;
+ UINT8 reserved_3;
+ UINT8 reserved_4;
+ UINT8 reserved_5;
+ UINT8 reserved_6;
+ UINT8 allocation_length_hi;
+ UINT8 allocation_length_lo;
+ UINT8 reserved_9;
+ UINT8 reserved_10;
+ UINT8 reserved_11;
+} READ_FORMAT_CAP_CMD;
+
+typedef union {
+ UINT16 Data16[6];
+ TEST_UNIT_READY_CMD TestUnitReady;
+ READ10_CMD Read10;
+ REQUEST_SENSE_CMD RequestSense;
+ INQUIRY_CMD Inquiry;
+ MODE_SENSE_CMD_UFI ModeSenseUFI;
+ READ_FORMAT_CAP_CMD ReadFormatCapacity;
+ MODE_SENSE_CMD_SCSI ModeSenseSCSI;
+} ATAPI_PACKET_COMMAND;
+
+#pragma pack()
+//
+// Packet Command Code
+//
+#define TEST_UNIT_READY 0x00
+#define REZERO 0x01
+#define REQUEST_SENSE 0x03
+#define FORMAT_UNIT 0x04
+#define REASSIGN_BLOCKS 0x07
+#define INQUIRY 0x12
+#define START_STOP_UNIT 0x1B
+#define PREVENT_ALLOW_MEDIA_REMOVAL 0x1E
+#define READ_FORMAT_CAPACITY 0x23
+#define OLD_FORMAT_UNIT 0x24
+#define READ_CAPACITY 0x25
+#define READ_10 0x28
+#define WRITE_10 0x2A
+#define SEEK 0x2B
+#define SEND_DIAGNOSTICS 0x3D
+#define WRITE_VERIFY 0x2E
+#define VERIFY 0x2F
+#define READ_DEFECT_DATA 0x37
+#define WRITE_BUFFER 0x38
+#define READ_BUFFER 0x3C
+#define READ_LONG 0x3E
+#define WRITE_LONG 0x3F
+#define MODE_SELECT 0x55
+#define UFI_MODE_SENSE5A 0x5A
+#define SCSI_MODE_SENSE1A 0x1A
+#define READ_12 0xA8
+#define WRITE_12 0xAA
+#define MAX_ATAPI_BYTE_COUNT (0xfffe)
+
+//
+// Sense Key
+//
+#define REQUEST_SENSE_ERROR (0x70)
+#define SK_NO_SENSE (0x0)
+#define SK_RECOVERY_ERROR (0x1)
+#define SK_NOT_READY (0x2)
+#define SK_MEDIUM_ERROR (0x3)
+#define SK_HARDWARE_ERROR (0x4)
+#define SK_ILLEGAL_REQUEST (0x5)
+#define SK_UNIT_ATTENTION (0x6)
+#define SK_DATA_PROTECT (0x7)
+#define SK_BLANK_CHECK (0x8)
+#define SK_VENDOR_SPECIFIC (0x9)
+#define SK_RESERVED_A (0xA)
+#define SK_ABORT (0xB)
+#define SK_RESERVED_C (0xC)
+#define SK_OVERFLOW (0xD)
+#define SK_MISCOMPARE (0xE)
+#define SK_RESERVED_F (0xF)
+
+//
+// Additional Sense Codes
+//
+#define ASC_NOT_READY (0x04)
+#define ASC_MEDIA_ERR1 (0x10)
+#define ASC_MEDIA_ERR2 (0x11)
+#define ASC_MEDIA_ERR3 (0x14)
+#define ASC_MEDIA_ERR4 (0x30)
+#define ASC_MEDIA_UPSIDE_DOWN (0x06)
+#define ASC_INVALID_CMD (0x20)
+#define ASC_LBA_OUT_OF_RANGE (0x21)
+#define ASC_INVALID_FIELD (0x24)
+#define ASC_WRITE_PROTECTED (0x27)
+#define ASC_MEDIA_CHANGE (0x28)
+#define ASC_RESET (0x29) /* Power On Reset or Bus Reset occurred */
+#define ASC_ILLEGAL_FIELD (0x26)
+#define ASC_NO_MEDIA (0x3A)
+#define ASC_ILLEGAL_MODE_FOR_THIS_TRACK (0x64)
+#define ASC_LOGICAL_UNIT_STATUS (0x08)
+
+//
+// Additional Sense Code Qualifier
+//
+#define ASCQ_IN_PROGRESS (0x01)
+#define ASCQ_DEVICE_BUSY (0xff)
+#define ASCQ_LOGICAL_UNIT_FAILURE (0x00)
+#define ASCQ_LOGICAL_UNIT_TIMEOUT (0x01)
+#define ASCQ_LOGICAL_UNIT_OVERRUN (0x80)
+
+#define SETFEATURE TRUE
+#define CLEARFEATURE FALSE
+
+//
+// ATAPI Data structure
+//
+#pragma pack(1)
+
+typedef struct {
+ UINT8 peripheral_type;
+ UINT8 RMB;
+ UINT8 version;
+ UINT8 response_data_format;
+ UINT8 addnl_length;
+ UINT8 reserved_5;
+ UINT8 reserved_6;
+ UINT8 reserved_7;
+ UINT8 vendor_info[8];
+ UINT8 product_id[12];
+ UINT8 eeprom_product_code[4];
+ UINT8 firmware_rev_level[4];
+} USB_INQUIRY_DATA;
+
+typedef struct {
+ UINT8 error_code : 7;
+ UINT8 valid : 1;
+ UINT8 reserved_1;
+ UINT8 sense_key : 4;
+ UINT8 reserved_21 : 1;
+ UINT8 ILI : 1;
+ UINT8 reserved_22 : 2;
+ UINT8 vendor_specific_3;
+ UINT8 vendor_specific_4;
+ UINT8 vendor_specific_5;
+ UINT8 vendor_specific_6;
+ UINT8 addnl_sense_length; // n - 7
+ UINT8 vendor_specific_8;
+ UINT8 vendor_specific_9;
+ UINT8 vendor_specific_10;
+ UINT8 vendor_specific_11;
+ UINT8 addnl_sense_code; // mandatory
+ UINT8 addnl_sense_code_qualifier; // mandatory
+ UINT8 field_replaceable_unit_code; // optional
+ UINT8 reserved_15;
+ UINT8 reserved_16;
+ UINT8 reserved_17;
+ //
+ // Followed by additional sense bytes : FIXME
+ //
+} REQUEST_SENSE_DATA;
+
+typedef struct {
+ UINT8 LastLba3;
+ UINT8 LastLba2;
+ UINT8 LastLba1;
+ UINT8 LastLba0;
+ UINT8 BlockSize3;
+ UINT8 BlockSize2;
+ UINT8 BlockSize1;
+ UINT8 BlockSize0;
+} READ_CAPACITY_DATA;
+
+typedef struct {
+ UINT8 reserved_0;
+ UINT8 reserved_1;
+ UINT8 reserved_2;
+ UINT8 Capacity_Length;
+ UINT8 LastLba3;
+ UINT8 LastLba2;
+ UINT8 LastLba1;
+ UINT8 LastLba0;
+ UINT8 DesCode : 2;
+ UINT8 reserved_9 : 6;
+ UINT8 BlockSize2;
+ UINT8 BlockSize1;
+ UINT8 BlockSize0;
+} READ_FORMAT_CAPACITY_DATA;
+
+typedef struct {
+ UINT8 mode_data_len_hi;
+ UINT8 mode_data_len_lo;
+ UINT8 media_type_code;
+ UINT8 reserved_3_0 : 4;
+ UINT8 dpofua : 1;
+ UINT8 reserved_3_1 : 2;
+ UINT8 write_protected : 1;
+ UINT8 reserved_4;
+ UINT8 reserved_5;
+ UINT8 reserved_6;
+ UINT8 reserved_7;
+} UFI_MODE_PARAMETER_HEADER;
+
+typedef struct {
+ UINT8 mode_data_len;
+ UINT8 media_type_code;
+ UINT8 speed : 4;
+ UINT8 buffered_mode : 3;
+ UINT8 write_protected : 1;
+ UINT8 block_descritptor_length;
+} SCSI_MODE_PARAMETER_HEADER6;
+
+typedef struct {
+ UINT8 page_code : 6;
+ UINT8 reserved_0 : 1;
+ UINT8 parameter_savable : 1;
+ UINT8 page_length;
+ UINT8 transfer_rate_msb;
+ UINT8 transfer_rate_lsb;
+ UINT8 number_of_heads;
+ UINT8 sectors_per_track;
+ UINT8 databytes_per_sector_msb;
+ UINT8 databytes_per_sector_lsb;
+ UINT8 number_of_cylinders_msb;
+ UINT8 number_of_cylinders_lsb;
+ UINT8 reserved_10_18[9];
+ UINT8 motor_on_delay;
+ UINT8 motor_off_delay;
+ UINT8 reserved_21_27[7];
+ UINT8 medium_rotation_rate_msb;
+ UINT8 medium_rotation_rate_lsb;
+ UINT8 reserved_30_31[2];
+} FLEXIBLE_DISK_PAGE;
+
+typedef struct {
+ UFI_MODE_PARAMETER_HEADER mode_param_header;
+ FLEXIBLE_DISK_PAGE flex_disk_page;
+} UFI_MODE_PARAMETER_PAGE_5;
+
+typedef struct {
+ UINT8 page_code : 6;
+ UINT8 reserved_0 : 1;
+ UINT8 parameter_savable : 1;
+ UINT8 page_length;
+ UINT8 reserved_2;
+ UINT8 inactive_time_multplier : 4;
+ UINT8 reserved_3 : 4;
+ UINT8 software_write_protect : 1;
+ UINT8 disable_media_access : 1;
+ UINT8 reserved_4 : 6;
+ UINT8 reserved_5;
+ UINT8 reserved_6;
+ UINT8 reserved_7;
+} TIMER_AND_PROTECT_PAGE;
+
+typedef struct {
+ UFI_MODE_PARAMETER_HEADER mode_param_header;
+ TIMER_AND_PROTECT_PAGE time_and_protect_page;
+} UFI_MODE_PARAMETER_PAGE_1C;
+
+#pragma pack()
+
+#endif
diff --git a/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorageHelper.c b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorageHelper.c
new file mode 100644
index 0000000000..b8ed813ea2
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorageHelper.c
@@ -0,0 +1,1653 @@
+/*++
+
+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:
+
+ UsbMassStorageHelper.c
+
+Abstract:
+
+ Helper functions for USB Mass Storage Driver
+
+Revision History
+
+--*/
+
+#include "UsbMassStorageHelper.h"
+
+STATIC
+BOOLEAN
+IsNoMedia (
+ IN REQUEST_SENSE_DATA *SenseData,
+ IN UINTN SenseCounts
+ );
+
+STATIC
+BOOLEAN
+IsMediaError (
+ IN REQUEST_SENSE_DATA *SenseData,
+ IN UINTN SenseCounts
+ );
+
+STATIC
+BOOLEAN
+IsMediaChange (
+ IN REQUEST_SENSE_DATA *SenseData,
+ IN UINTN SenseCounts
+ );
+
+STATIC
+BOOLEAN
+IsDriveReady (
+ IN REQUEST_SENSE_DATA *SenseData,
+ IN UINTN SenseCounts,
+ OUT BOOLEAN *NeedRetry
+ );
+
+STATIC
+BOOLEAN
+IsMediaWriteProtected (
+ IN REQUEST_SENSE_DATA *SenseData,
+ IN UINTN SenseCounts
+ );
+
+STATIC
+BOOLEAN
+IsLogicalUnitCommunicationOverRun (
+ IN REQUEST_SENSE_DATA *SenseData,
+ IN UINTN SenseCounts
+ );
+
+EFI_STATUS
+USBFloppyPacketCommand (
+ USB_FLOPPY_DEV *UsbFloppyDevice,
+ VOID *Command,
+ UINT8 CommandSize,
+ VOID *DataBuffer,
+ UINT32 BufferLength,
+ EFI_USB_DATA_DIRECTION Direction,
+ UINT16 TimeOutInMilliSeconds
+ )
+/*++
+
+ Routine Description:
+ Sends Packet Command to USB Floppy Drive.
+
+ Arguments:
+ UsbFloppyDevice - The USB_FLOPPY_DEV instance.
+ Command - A pointer to the command packet.
+ CommandSize - Indicates the size of the command packet.
+ DataBuffer - A pointer to the buffer for the data transfer
+ after the command packet.
+ BufferLength - Indicates the size of the Data Buffer.
+ Direction - Transfer Direction
+ TimeOutInMilliSeconds - Timeout Value
+ Returns:
+ EFI_SUCCESS - Success
+--*/
+{
+ EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
+ EFI_STATUS Status;
+
+ UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
+ //
+ // Directly calling EFI_USB_ATAPI_PROTOCOL.UsbAtapiPacketCmd()
+ // to perform the command request.
+ //
+ Status = UsbAtapiInterface->UsbAtapiPacketCmd (
+ UsbAtapiInterface,
+ Command,
+ CommandSize,
+ DataBuffer,
+ BufferLength,
+ Direction,
+ TimeOutInMilliSeconds
+ );
+
+ return Status;
+}
+
+EFI_STATUS
+USBFloppyIdentify (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice
+ )
+/*++
+
+ Routine Description:
+ Retrieves device information to tell the device type.
+
+ Arguments:
+ UsbFloppyDevice The USB_FLOPPY_DEV instance.
+
+ Returns:
+ EFI_DEVICE_ERROR - Hardware error
+ EFI_SUCCESS - Success
+--*/
+{
+
+ EFI_STATUS Status;
+ USB_INQUIRY_DATA *Idata;
+ BOOLEAN MediaChange;
+
+ //
+ // Send Inquiry Packet Command to get INQUIRY data.
+ //
+ Status = USBFloppyInquiry (UsbFloppyDevice, &Idata);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Get media removable info from INQUIRY data.
+ //
+ UsbFloppyDevice->BlkIo.Media->RemovableMedia = (UINT8) ((Idata->RMB & 0x80) == 0x80);
+
+ //
+ // Identify device type via INQUIRY data.
+ //
+ switch ((Idata->peripheral_type) & 0x1f) {
+ //
+ // Floppy
+ //
+ case 0x00:
+ UsbFloppyDevice->DeviceType = USBFLOPPY;
+ UsbFloppyDevice->BlkIo.Media->MediaId = 0;
+ UsbFloppyDevice->BlkIo.Media->MediaPresent = FALSE;
+ UsbFloppyDevice->BlkIo.Media->LastBlock = 0;
+ UsbFloppyDevice->BlkIo.Media->BlockSize = 0x200;
+ break;
+
+ //
+ // CD-ROM
+ //
+ case 0x05:
+ UsbFloppyDevice->DeviceType = USBCDROM;
+ UsbFloppyDevice->BlkIo.Media->MediaId = 0;
+ UsbFloppyDevice->BlkIo.Media->MediaPresent = FALSE;
+ UsbFloppyDevice->BlkIo.Media->LastBlock = 0;
+ UsbFloppyDevice->BlkIo.Media->BlockSize = 0x800;
+ UsbFloppyDevice->BlkIo.Media->ReadOnly = TRUE;
+ break;
+
+ default:
+ gBS->FreePool (Idata);
+ return EFI_DEVICE_ERROR;
+ };
+
+ //
+ // Initialize some device specific data.
+ //
+ //
+ // original sense data numbers
+ //
+ UsbFloppyDevice->SenseDataNumber = 6;
+
+ if (UsbFloppyDevice->SenseData != NULL) {
+ gBS->FreePool (UsbFloppyDevice->SenseData);
+ UsbFloppyDevice->SenseData = NULL;
+ }
+
+ UsbFloppyDevice->SenseData = AllocatePool (UsbFloppyDevice->SenseDataNumber * sizeof (REQUEST_SENSE_DATA));
+
+ if (UsbFloppyDevice->SenseData == NULL) {
+ gBS->FreePool (Idata);
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Get media information.
+ //
+ UsbFloppyDetectMedia (UsbFloppyDevice, &MediaChange);
+
+ gBS->FreePool (Idata);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+USBFloppyInquiry (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice,
+ OUT USB_INQUIRY_DATA **Idata
+ )
+/*++
+
+ Routine Description:
+ Send Inquiry Packet Command to device and retrieve Inquiry Data.
+
+ Arguments:
+ UsbFloppyDevice The USB_FLOPPY_DEV instance.
+ Idata A pointer pointing to the address of
+ Inquiry Data.
+
+ Returns:
+ EFI_DEVICE_ERROR - Hardware error
+ EFI_SUCCESS - Success
+--*/
+{
+ ATAPI_PACKET_COMMAND Packet;
+ EFI_STATUS Status;
+ EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
+
+ UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
+
+ //
+ // prepare command packet for the Inquiry Packet Command.
+ //
+ ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
+ Packet.Inquiry.opcode = INQUIRY;
+ Packet.Inquiry.page_code = 0;
+ Packet.Inquiry.allocation_length = sizeof (USB_INQUIRY_DATA);
+
+ *Idata = AllocateZeroPool (sizeof (USB_INQUIRY_DATA));
+ if (*Idata == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Send command packet and retrieve requested Inquiry Data.
+ //
+ Status = USBFloppyPacketCommand (
+ UsbFloppyDevice,
+ &Packet,
+ sizeof (ATAPI_PACKET_COMMAND),
+ (VOID *) (*Idata),
+ sizeof (USB_INQUIRY_DATA),
+ EfiUsbDataIn,
+ USBFLPTIMEOUT * 3
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (*Idata);
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+USBFloppyRead10 (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice,
+ IN VOID *Buffer,
+ IN EFI_LBA Lba,
+ IN UINTN NumberOfBlocks
+ )
+/*++
+
+ Routine Description:
+ Sends Read10 Packet Command to device to perform data transfer
+ from device to host.
+
+ Arguments:
+ UsbFloppyDevice - The USB_FLOPPY_DEV instance.
+ Buffer - A pointer to the destination buffer for the data.
+ The caller is responsible for either having implicit
+ or explicit ownership of the buffer.
+ Lba - The starting logical block address to read from
+ on the device.
+ NumberOfBlocks - Indicates the number of blocks that the read
+ operation requests.
+
+ Returns:
+ EFI_DEVICE_ERROR - Hardware error
+ EFI_SUCCESS - Success
+--*/
+{
+ ATAPI_PACKET_COMMAND Packet;
+ READ10_CMD *Read10Packet;
+ UINT16 MaxBlock;
+ UINT16 BlocksRemaining;
+ UINT16 SectorCount;
+ UINT32 Lba32;
+ UINT32 BlockSize;
+ UINT32 ByteCount;
+ VOID *ptrBuffer;
+ EFI_STATUS Status;
+ UINT16 TimeOut;
+ EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
+ UINTN SenseCounts;
+
+ UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
+
+ //
+ // prepare command packet for the Inquiry Packet Command.
+ //
+ ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
+ Read10Packet = &Packet.Read10;
+ Lba32 = (UINT32) Lba;
+ ptrBuffer = Buffer;
+ BlockSize = UsbFloppyDevice->BlkIo.Media->BlockSize;
+
+ MaxBlock = (UINT16) (65536 / BlockSize);
+ BlocksRemaining = (UINT16) NumberOfBlocks;
+
+ Status = EFI_SUCCESS;
+ while (BlocksRemaining > 0) {
+ if (BlocksRemaining <= MaxBlock) {
+ SectorCount = BlocksRemaining;
+ } else {
+ SectorCount = MaxBlock;
+ }
+ //
+ // fill the Packet data structure
+ //
+ Read10Packet->opcode = READ_10;
+
+ //
+ // Lba0 ~ Lba3 specify the start logical block address of the data transfer.
+ // Lba0 is MSB, Lba3 is LSB
+ //
+ Read10Packet->Lba3 = (UINT8) (Lba32 & 0xff);
+ Read10Packet->Lba2 = (UINT8) (Lba32 >> 8);
+ Read10Packet->Lba1 = (UINT8) (Lba32 >> 16);
+ Read10Packet->Lba0 = (UINT8) (Lba32 >> 24);
+
+ //
+ // TranLen0 ~ TranLen1 specify the transfer length in block unit.
+ // TranLen0 is MSB, TranLen is LSB
+ //
+ Read10Packet->TranLen1 = (UINT8) (SectorCount & 0xff);
+ Read10Packet->TranLen0 = (UINT8) (SectorCount >> 8);
+
+ ByteCount = SectorCount * BlockSize;
+
+ TimeOut = (UINT16) (SectorCount * USBFLPTIMEOUT);
+
+ Status = USBFloppyPacketCommand (
+ UsbFloppyDevice,
+ &Packet,
+ sizeof (ATAPI_PACKET_COMMAND),
+ (VOID *) ptrBuffer,
+ ByteCount,
+ EfiUsbDataIn,
+ TimeOut
+ );
+ if (EFI_ERROR (Status)) {
+
+ Status = UsbFloppyRequestSense (UsbFloppyDevice, &SenseCounts);
+ if (!EFI_ERROR (Status)) {
+ if (IsLogicalUnitCommunicationOverRun (
+ UsbFloppyDevice->SenseData,
+ SenseCounts
+ )) {
+ Lba32 = (UINT32) Lba;
+ ptrBuffer = Buffer;
+ BlocksRemaining = (UINT16) NumberOfBlocks;
+ MaxBlock = (UINT16) (MaxBlock / 4);
+ if (MaxBlock < 1) {
+ MaxBlock = 1;
+ }
+
+ continue;
+ }
+ } else {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // retry read10 command
+ //
+ Status = USBFloppyPacketCommand (
+ UsbFloppyDevice,
+ &Packet,
+ sizeof (ATAPI_PACKET_COMMAND),
+ (VOID *) ptrBuffer,
+ ByteCount,
+ EfiUsbDataIn,
+ TimeOut
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+ Lba32 += SectorCount;
+ ptrBuffer = (UINT8 *) ptrBuffer + SectorCount * BlockSize;
+ BlocksRemaining = (UINT16) (BlocksRemaining - SectorCount);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+USBFloppyReadCapacity (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice
+ )
+/*++
+
+ Routine Description:
+ Retrieves media capacity information via
+ sending Read Capacity Packet Command.
+
+ Arguments:
+ UsbFloppyDevice - The USB_FLOPPY_DEV instance.
+
+ Returns:
+ EFI_DEVICE_ERROR - Hardware error
+ EFI_SUCCESS - Success
+--*/
+{
+ //
+ // status returned by Read Capacity Packet Command
+ //
+ EFI_STATUS Status;
+ ATAPI_PACKET_COMMAND Packet;
+ EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
+
+ //
+ // used for capacity data returned from Usb Floppy
+ //
+ READ_CAPACITY_DATA Data;
+
+ ZeroMem (&Data, sizeof (Data));
+
+ UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
+
+ ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
+ Packet.Inquiry.opcode = READ_CAPACITY;
+ Status = USBFloppyPacketCommand (
+ UsbFloppyDevice,
+ &Packet,
+ sizeof (ATAPI_PACKET_COMMAND),
+ (VOID *) &Data,
+ sizeof (READ_CAPACITY_DATA),
+ EfiUsbDataIn,
+ USBFLPTIMEOUT
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ UsbFloppyDevice->BlkIo.Media->LastBlock = (Data.LastLba3 << 24) |
+ (Data.LastLba2 << 16) |
+ (Data.LastLba1 << 8) |
+ Data.LastLba0;
+
+ UsbFloppyDevice->BlkIo.Media->MediaPresent = TRUE;
+
+ UsbFloppyDevice->BlkIo.Media->BlockSize = 0x800;
+
+ return EFI_SUCCESS;
+
+}
+
+EFI_STATUS
+USBFloppyReadFormatCapacity (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice
+ )
+/*++
+
+ Routine Description:
+ Retrieves media capacity information via sending Read Format
+ Capacity Packet Command.
+
+ Arguments:
+ UsbFloppyDevice - The USB_FLOPPY_DEV instance.
+
+ Returns:
+ EFI_DEVICE_ERROR - Hardware error
+ EFI_SUCCESS - Success
+--*/
+{
+ //
+ // status returned by Read Capacity Packet Command
+ //
+ EFI_STATUS Status;
+ ATAPI_PACKET_COMMAND Packet;
+ EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
+
+ //
+ // used for capacity data returned from Usb Floppy
+ //
+ READ_FORMAT_CAPACITY_DATA FormatData;
+
+ ZeroMem (&FormatData, sizeof (FormatData));
+
+ UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
+
+ ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
+ Packet.ReadFormatCapacity.opcode = READ_FORMAT_CAPACITY;
+ Packet.ReadFormatCapacity.allocation_length_lo = 12;
+ Status = USBFloppyPacketCommand (
+ UsbFloppyDevice,
+ &Packet,
+ sizeof (ATAPI_PACKET_COMMAND),
+ (VOID *) &FormatData,
+ sizeof (READ_FORMAT_CAPACITY_DATA),
+ EfiUsbDataIn,
+ USBFLPTIMEOUT
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (FormatData.DesCode == 3) {
+ //
+ // Media is not present
+ //
+ UsbFloppyDevice->BlkIo.Media->MediaId = 0;
+ UsbFloppyDevice->BlkIo.Media->MediaPresent = FALSE;
+ UsbFloppyDevice->BlkIo.Media->LastBlock = 0;
+ } else {
+
+ UsbFloppyDevice->BlkIo.Media->LastBlock = (FormatData.LastLba3 << 24) |
+ (FormatData.LastLba2 << 16) |
+ (FormatData.LastLba1 << 8) |
+ FormatData.LastLba0;
+
+ UsbFloppyDevice->BlkIo.Media->LastBlock--;
+
+ UsbFloppyDevice->BlkIo.Media->BlockSize = (FormatData.BlockSize2 << 16) |
+ (FormatData.BlockSize1 << 8) |
+ FormatData.BlockSize0;
+
+ UsbFloppyDevice->BlkIo.Media->MediaPresent = TRUE;
+
+ UsbFloppyDevice->BlkIo.Media->BlockSize = 0x200;
+
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+EFI_STATUS
+UsbFloppyRequestSense (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice,
+ OUT UINTN *SenseCounts
+ )
+/*++
+
+ Routine Description:
+ Retrieves Sense Data from device via
+ sending Request Sense Packet Command.
+
+ Arguments:
+ UsbFloppyDevice - The USB_FLOPPY_DEV instance.
+ SenseCounts - A pointer to the number of Sense Data returned.
+
+ Returns:
+ EFI_DEVICE_ERROR - Hardware error
+ EFI_SUCCESS - Success
+--*/
+{
+ EFI_STATUS Status;
+ REQUEST_SENSE_DATA *Sense;
+ UINT8 *Ptr;
+ BOOLEAN SenseReq;
+ ATAPI_PACKET_COMMAND Packet;
+ EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
+
+ UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
+
+ *SenseCounts = 0;
+
+ ZeroMem (
+ UsbFloppyDevice->SenseData,
+ sizeof (REQUEST_SENSE_DATA) * (UsbFloppyDevice->SenseDataNumber)
+ );
+ //
+ // fill command packet for Request Sense Packet Command
+ //
+ ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
+ Packet.RequestSense.opcode = REQUEST_SENSE;
+ Packet.RequestSense.allocation_length = sizeof (REQUEST_SENSE_DATA);
+
+ //
+ // initialize pointer
+ //
+ Ptr = (UINT8 *) (UsbFloppyDevice->SenseData);
+
+ //
+ // request sense data from device continuously
+ // until no sense data exists in the device.
+ //
+ for (SenseReq = TRUE; SenseReq;) {
+
+ Sense = (REQUEST_SENSE_DATA *) Ptr;
+
+ //
+ // send out Request Sense Packet Command and get one Sense
+ // data from device.
+ //
+ Status = USBFloppyPacketCommand (
+ UsbFloppyDevice,
+ &Packet,
+ sizeof (ATAPI_PACKET_COMMAND),
+ (VOID *) Ptr,
+ sizeof (REQUEST_SENSE_DATA),
+ EfiUsbDataIn,
+ USBFLPTIMEOUT
+ );
+ //
+ // failed to get Sense data
+ //
+ if (EFI_ERROR (Status)) {
+ //
+ // Recovery the device back to normal state.
+ //
+ UsbFloppyDevice->AtapiProtocol->UsbAtapiReset (
+ UsbFloppyDevice->AtapiProtocol,
+ TRUE
+ );
+
+ if (*SenseCounts == 0) {
+ //
+ // never retrieved any sense data from device,
+ // just return error.
+ //
+ return EFI_DEVICE_ERROR;
+ } else {
+ //
+ // has retrieved some sense data from device,
+ // so return success.
+ //
+ return EFI_SUCCESS;
+ }
+ }
+
+ if (Sense->sense_key != SK_NO_SENSE) {
+ //
+ // Ptr is byte based pointer
+ //
+ Ptr += sizeof (REQUEST_SENSE_DATA);
+
+ (*SenseCounts)++;
+
+ } else {
+ //
+ // when no sense key, skip out the loop
+ //
+ SenseReq = FALSE;
+ }
+
+ //
+ // If the sense key numbers exceed Sense Data Buffer size,
+ // just skip the loop and do not fetch the sense key in this function.
+ //
+ if (*SenseCounts == UsbFloppyDevice->SenseDataNumber) {
+ SenseReq = FALSE;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+UsbFloppyTestUnitReady (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice
+ )
+/*++
+
+ Routine Description:
+ Sends Test Unit ReadyPacket Command to the device.
+
+ Arguments:
+ UsbFloppyDevice - The USB_FLOPPY_DEV instance.
+
+ Returns:
+ EFI_DEVICE_ERROR - Hardware error
+ EFI_SUCCESS - Success
+--*/
+{
+ ATAPI_PACKET_COMMAND Packet;
+ EFI_STATUS Status;
+ EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
+ UINT32 RetryIndex;
+ UINT32 MaximumRetryTimes;
+
+ UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
+ MaximumRetryTimes = 2;
+ //
+ // fill command packet
+ //
+ ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
+ Packet.TestUnitReady.opcode = TEST_UNIT_READY;
+
+ //
+ // send command packet
+ //
+ Status = EFI_DEVICE_ERROR;
+
+ for (RetryIndex = 0; RetryIndex < MaximumRetryTimes && EFI_ERROR (Status); RetryIndex++) {
+
+ Status = USBFloppyPacketCommand (
+ UsbFloppyDevice,
+ &Packet,
+ sizeof (ATAPI_PACKET_COMMAND),
+ NULL,
+ 0,
+ EfiUsbNoData,
+ USBFLPTIMEOUT
+ );
+
+ if (EFI_ERROR (Status)) {
+ gBS->Stall (100 * STALL_1_MILLI_SECOND);
+ }
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+USBFloppyWrite10 (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice,
+ IN VOID *Buffer,
+ IN EFI_LBA Lba,
+ IN UINTN NumberOfBlocks
+ )
+/*++
+
+ Routine Description:
+ Sends Write10 Packet Command to device to perform data transfer
+ from host to device.
+
+ Arguments:
+ UsbFloppyDevice - The USB_FLOPPY_DEV instance.
+ Buffer - A pointer to the source buffer for the data.
+ The caller is responsible for either having implicit
+ or explicit ownership of the buffer.
+ Lba - The starting logical block address to written to
+ the device.
+ NumberOfBlocks - Indicates the number of blocks that the write
+ operation requests.
+
+ Returns:
+ EFI_DEVICE_ERROR - Hardware error
+ EFI_SUCCESS - Success
+--*/
+{
+ ATAPI_PACKET_COMMAND Packet;
+ READ10_CMD *Write10Packet;
+ UINT16 MaxBlock;
+ UINT16 BlocksRemaining;
+ UINT16 SectorCount;
+ UINT32 Lba32;
+ UINT32 BlockSize;
+ UINT32 ByteCount;
+ VOID *ptrBuffer;
+ EFI_STATUS Status;
+ UINT16 TimeOut;
+ EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
+ UINTN SenseCounts;
+
+ UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
+
+ //
+ // prepare command packet for the Write10 Packet Command.
+ //
+ ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
+ Write10Packet = &Packet.Read10;
+ Lba32 = (UINT32) Lba;
+ ptrBuffer = Buffer;
+ BlockSize = UsbFloppyDevice->BlkIo.Media->BlockSize;
+
+ MaxBlock = (UINT16) (65536 / BlockSize);
+ BlocksRemaining = (UINT16) NumberOfBlocks;
+
+ Status = EFI_SUCCESS;
+ while (BlocksRemaining > 0) {
+
+ if (BlocksRemaining <= MaxBlock) {
+
+ SectorCount = BlocksRemaining;
+ } else {
+
+ SectorCount = MaxBlock;
+ }
+ //
+ // fill the Packet data structure
+ //
+ Write10Packet->opcode = WRITE_10;
+
+ //
+ // Lba0 ~ Lba3 specify the start logical block address
+ // of the data transfer.
+ // Lba0 is MSB, Lba3 is LSB
+ //
+ Write10Packet->Lba3 = (UINT8) (Lba32 & 0xff);
+ Write10Packet->Lba2 = (UINT8) (Lba32 >> 8);
+ Write10Packet->Lba1 = (UINT8) (Lba32 >> 16);
+ Write10Packet->Lba0 = (UINT8) (Lba32 >> 24);
+
+ //
+ // TranLen0 ~ TranLen1 specify the transfer length in block unit.
+ // TranLen0 is MSB, TranLen is LSB
+ //
+ Write10Packet->TranLen1 = (UINT8) (SectorCount & 0xff);
+ Write10Packet->TranLen0 = (UINT8) (SectorCount >> 8);
+
+ ByteCount = SectorCount * BlockSize;
+
+ TimeOut = (UINT16) (SectorCount * USBFLPTIMEOUT);
+
+ Status = USBFloppyPacketCommand (
+ UsbFloppyDevice,
+ &Packet,
+ sizeof (ATAPI_PACKET_COMMAND),
+ (VOID *) ptrBuffer,
+ ByteCount,
+ EfiUsbDataOut,
+ TimeOut
+ );
+ if (EFI_ERROR (Status)) {
+ Status = UsbFloppyRequestSense (UsbFloppyDevice, &SenseCounts);
+ if (!EFI_ERROR (Status)) {
+ if (IsLogicalUnitCommunicationOverRun (
+ UsbFloppyDevice->SenseData,
+ SenseCounts
+ )) {
+ Lba32 = (UINT32) Lba;
+ ptrBuffer = Buffer;
+ BlocksRemaining = (UINT16) NumberOfBlocks;
+ MaxBlock = (UINT16) (MaxBlock / 4);
+ if (MaxBlock < 1) {
+ MaxBlock = 1;
+ }
+
+ continue;
+ }
+ }
+ //
+ // retry write10 command
+ //
+ Status = USBFloppyPacketCommand (
+ UsbFloppyDevice,
+ &Packet,
+ sizeof (ATAPI_PACKET_COMMAND),
+ (VOID *) ptrBuffer,
+ ByteCount,
+ EfiUsbDataOut,
+ TimeOut
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+ Lba32 += SectorCount;
+ ptrBuffer = (UINT8 *) ptrBuffer + SectorCount * BlockSize;
+ BlocksRemaining = (UINT16) (BlocksRemaining - SectorCount);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+UsbFloppyDetectMedia (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice,
+ OUT BOOLEAN *MediaChange
+ )
+/*++
+
+ Routine Description:
+ Retrieves media information.
+
+ Arguments:
+ UsbFloppyDevice - The USB_FLOPPY_DEV instance.
+ MediaChange - Indicates whether media was changed.
+
+ Returns:
+ EFI_DEVICE_ERROR - Hardware error
+ EFI_SUCCESS - Success
+ EFI_INVALID_PARAMETER - Parameter is error
+--*/
+{
+ EFI_STATUS Status;
+ EFI_STATUS FloppyStatus;
+ //
+ // the following variables are used to record previous media information
+ //
+ EFI_BLOCK_IO_MEDIA OldMediaInfo;
+ UINTN SenseCounts;
+ UINTN RetryIndex;
+ UINTN RetryTimes;
+ UINTN MaximumRetryTimes;
+ BOOLEAN NeedRetry;
+
+ //
+ // a flag used to determine whether need to perform Read Capacity command.
+ //
+ BOOLEAN NeedReadCapacity;
+
+ REQUEST_SENSE_DATA *SensePtr;
+
+ //
+ // init
+ //
+ Status = EFI_SUCCESS;
+ FloppyStatus = EFI_SUCCESS;
+ CopyMem (&OldMediaInfo, UsbFloppyDevice->BlkIo.Media, sizeof (OldMediaInfo));
+ //OldMediaInfo = *UsbFloppyDevice->BlkIo.Media;
+ *MediaChange = FALSE;
+ NeedReadCapacity = TRUE;
+
+ //
+ // if there is no media present,or media not changed,
+ // the request sense command will detect faster than read capacity command.
+ // read capacity command can be bypassed, thus improve performance.
+ //
+ SenseCounts = 0;
+ Status = UsbFloppyRequestSense (UsbFloppyDevice, &SenseCounts);
+
+ if (!EFI_ERROR (Status)) {
+
+ SensePtr = UsbFloppyDevice->SenseData;
+
+ //
+ // No Media
+ //
+ if (IsNoMedia (UsbFloppyDevice->SenseData, SenseCounts)) {
+
+ NeedReadCapacity = FALSE;
+ UsbFloppyDevice->BlkIo.Media->MediaId = 0;
+ UsbFloppyDevice->BlkIo.Media->MediaPresent = FALSE;
+ UsbFloppyDevice->BlkIo.Media->LastBlock = 0;
+ } else {
+ //
+ // Media Changed
+ //
+ if (IsMediaChange (UsbFloppyDevice->SenseData, SenseCounts)) {
+ UsbFloppyDevice->BlkIo.Media->MediaId++;
+ }
+
+ //
+ // Media Write-protected
+ //
+ if (IsMediaWriteProtected (UsbFloppyDevice->SenseData, SenseCounts)) {
+ UsbFloppyDevice->BlkIo.Media->ReadOnly = TRUE;
+ }
+
+ //
+ // Media Error
+ //
+ if (IsMediaError (UsbFloppyDevice->SenseData, SenseCounts)) {
+ //
+ // if media error encountered, make it look like no media present.
+ //
+ UsbFloppyDevice->BlkIo.Media->MediaId = 0;
+ UsbFloppyDevice->BlkIo.Media->MediaPresent = FALSE;
+ UsbFloppyDevice->BlkIo.Media->LastBlock = 0;
+ }
+
+ }
+
+ }
+
+ if (NeedReadCapacity) {
+ //
+ // at most retry 5 times
+ //
+ MaximumRetryTimes = 5;
+ //
+ // initial retry twice
+ //
+ RetryTimes = 2;
+
+ for (RetryIndex = 0; (RetryIndex < RetryTimes) && (RetryIndex < MaximumRetryTimes); RetryIndex++) {
+ //
+ // Using different command to retrieve media capacity.
+ //
+ switch (UsbFloppyDevice->DeviceType) {
+
+ case USBCDROM:
+ Status = USBFloppyReadCapacity (UsbFloppyDevice);
+ break;
+
+ case USBFLOPPY:
+ UsbMassStorageModeSense (UsbFloppyDevice);
+ Status = USBFloppyReadFormatCapacity (UsbFloppyDevice);
+ if (EFI_ERROR (Status) || !UsbFloppyDevice->BlkMedia.MediaPresent) {
+ //
+ // retry the ReadCapacity command
+ //
+ UsbFloppyDevice->DeviceType = USBFLOPPY2;
+ Status = EFI_DEVICE_ERROR;
+ }
+ break;
+
+ case USBFLOPPY2:
+ UsbMassStorageModeSense (UsbFloppyDevice);
+ Status = USBFloppyReadCapacity (UsbFloppyDevice);
+ if (EFI_ERROR (Status)) {
+ //
+ // retry the ReadFormatCapacity command
+ //
+ UsbFloppyDevice->DeviceType = USBFLOPPY;
+ }
+ //
+ // force the BlockSize to be 0x200.
+ //
+ UsbFloppyDevice->BlkIo.Media->BlockSize = 0x200;
+ break;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // skip the loop when read capacity succeeds.
+ //
+ break;
+ }
+
+ SenseCounts = 0;
+
+ FloppyStatus = UsbFloppyRequestSense (UsbFloppyDevice, &SenseCounts);
+
+ //
+ // If Request Sense data failed,retry.
+ //
+ if (EFI_ERROR (FloppyStatus)) {
+ //
+ // retry once more
+ //
+ RetryTimes++;
+ continue;
+ }
+ //
+ // No Media
+ //
+ if (IsNoMedia (UsbFloppyDevice->SenseData, SenseCounts)) {
+
+ UsbFloppyDevice->BlkIo.Media->MediaId = 0;
+ UsbFloppyDevice->BlkIo.Media->MediaPresent = FALSE;
+ UsbFloppyDevice->BlkIo.Media->LastBlock = 0;
+ break;
+ }
+
+ if (IsMediaError (UsbFloppyDevice->SenseData, SenseCounts)) {
+ //
+ // if media error encountered, make it look like no media present.
+ //
+ UsbFloppyDevice->BlkIo.Media->MediaId = 0;
+ UsbFloppyDevice->BlkIo.Media->MediaPresent = FALSE;
+ UsbFloppyDevice->BlkIo.Media->LastBlock = 0;
+ break;
+ }
+
+ if (IsMediaWriteProtected (UsbFloppyDevice->SenseData, SenseCounts)) {
+ UsbFloppyDevice->BlkIo.Media->ReadOnly = TRUE;
+ continue;
+ }
+
+ if (!IsDriveReady (UsbFloppyDevice->SenseData, SenseCounts, &NeedRetry)) {
+
+ //
+ // Drive not ready: if NeedRetry, then retry once more;
+ // else return error
+ //
+ if (NeedRetry) {
+ //
+ // Stall 0.1 second to wait for drive becoming ready
+ //
+ gBS->Stall (100 * STALL_1_MILLI_SECOND);
+ //
+ // reset retry variable to zero,
+ // to make it retry for "drive in progress of becoming ready".
+ //
+ RetryIndex = 0;
+ continue;
+ } else {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+ //
+ // if read capacity fail not for above reasons, retry once more
+ //
+ RetryTimes++;
+
+ }
+ //
+ // ENDFOR
+ //
+
+ //
+ // tell whether the readcapacity process is successful or not
+ // ("Status" variable record the latest status returned
+ // by ReadCapacity AND "FloppyStatus" record the latest status
+ // returned by RequestSense)
+ //
+ if (EFI_ERROR (Status) && EFI_ERROR (FloppyStatus)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ }
+
+ if (UsbFloppyDevice->BlkIo.Media->MediaPresent != OldMediaInfo.MediaPresent) {
+
+ if (UsbFloppyDevice->BlkIo.Media->MediaPresent) {
+ UsbFloppyDevice->BlkIo.Media->MediaId = 1;
+ }
+
+ *MediaChange = TRUE;
+ }
+
+ if (UsbFloppyDevice->BlkIo.Media->ReadOnly != OldMediaInfo.ReadOnly) {
+ *MediaChange = TRUE;
+ UsbFloppyDevice->BlkIo.Media->MediaId += 1;
+ }
+
+ if (UsbFloppyDevice->BlkIo.Media->BlockSize != OldMediaInfo.BlockSize) {
+ *MediaChange = TRUE;
+ UsbFloppyDevice->BlkIo.Media->MediaId += 1;
+ }
+
+ if (UsbFloppyDevice->BlkIo.Media->LastBlock != OldMediaInfo.LastBlock) {
+ *MediaChange = TRUE;
+ UsbFloppyDevice->BlkIo.Media->MediaId += 1;
+ }
+
+ if (UsbFloppyDevice->BlkIo.Media->MediaId != OldMediaInfo.MediaId) {
+ *MediaChange = TRUE;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+
+EFI_STATUS
+UsbFloppyModeSense5APage5 (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice
+ )
+/*++
+
+ Routine Description:
+ Retrieves media capacity information via sending Read Format
+ Capacity Packet Command.
+
+ Arguments:
+ UsbFloppyDevice - The USB_FLOPPY_DEV instance.
+
+ Returns:
+ EFI_DEVICE_ERROR - Hardware error
+ EFI_SUCCESS - Success
+
+--*/
+{
+ //
+ // status returned by Read Capacity Packet Command
+ //
+ EFI_STATUS Status;
+ ATAPI_PACKET_COMMAND Packet;
+ EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
+ UFI_MODE_PARAMETER_PAGE_5 ModePage5;
+ EFI_LBA LastBlock;
+ UINT32 SectorsPerTrack;
+ UINT32 NumberOfCylinders;
+ UINT32 NumberOfHeads;
+ UINT32 DataBytesPerSector;
+
+ UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
+
+ ZeroMem (&ModePage5, sizeof (UFI_MODE_PARAMETER_PAGE_5));
+
+ ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
+ Packet.ModeSenseUFI.opcode = UFI_MODE_SENSE5A;
+ //
+ // Flexible Disk Page
+ //
+ Packet.ModeSenseUFI.page_code = 5;
+ //
+ // current values
+ //
+ Packet.ModeSenseUFI.page_control = 0;
+ Packet.ModeSenseUFI.parameter_list_length_hi = 0;
+ Packet.ModeSenseUFI.parameter_list_length_lo = sizeof (UFI_MODE_PARAMETER_PAGE_5);
+ Status = USBFloppyPacketCommand (
+ UsbFloppyDevice,
+ &Packet,
+ sizeof (ATAPI_PACKET_COMMAND),
+ (VOID *) &ModePage5,
+ sizeof (UFI_MODE_PARAMETER_PAGE_5),
+ EfiUsbDataIn,
+ USBFLPTIMEOUT
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ NumberOfHeads = ModePage5.flex_disk_page.number_of_heads;
+ SectorsPerTrack = ModePage5.flex_disk_page.sectors_per_track;
+ NumberOfCylinders = ModePage5.flex_disk_page.number_of_cylinders_msb << 8 |
+ ModePage5.flex_disk_page.number_of_cylinders_lsb;
+
+ LastBlock = SectorsPerTrack * NumberOfHeads * NumberOfCylinders;
+ DataBytesPerSector = ModePage5.flex_disk_page.databytes_per_sector_msb << 8 |
+ ModePage5.flex_disk_page.databytes_per_sector_lsb;
+
+ UsbFloppyDevice->BlkIo.Media->LastBlock = LastBlock;
+
+ UsbFloppyDevice->BlkIo.Media->LastBlock--;
+
+ UsbFloppyDevice->BlkIo.Media->BlockSize = DataBytesPerSector;
+
+ UsbFloppyDevice->BlkIo.Media->MediaPresent = TRUE;
+
+ UsbFloppyDevice->BlkIo.Media->ReadOnly =
+ ModePage5.mode_param_header.write_protected;
+
+ return EFI_SUCCESS;
+
+}
+
+EFI_STATUS
+UsbFloppyModeSense5APage1C (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice
+ )
+/*++
+
+ Routine Description:
+ Retrieves media capacity information via sending Read Format
+ Capacity Packet Command.
+
+ Arguments:
+ UsbFloppyDevice - The USB_FLOPPY_DEV instance.
+
+ Returns:
+ EFI_DEVICE_ERROR - Hardware error
+ EFI_SUCCESS - Success
+
+--*/
+{
+ //
+ // status returned by Read Capacity Packet Command
+ //
+ EFI_STATUS Status;
+ ATAPI_PACKET_COMMAND Packet;
+ EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
+ UFI_MODE_PARAMETER_PAGE_1C ModePage1C;
+
+ UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
+
+ ZeroMem (&ModePage1C, sizeof (UFI_MODE_PARAMETER_PAGE_1C));
+
+ ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
+ Packet.ModeSenseUFI.opcode = UFI_MODE_SENSE5A;
+ //
+ // Flexible Disk Page
+ //
+ Packet.ModeSenseUFI.page_code = 0x1C;
+ //
+ // current values
+ //
+ Packet.ModeSenseUFI.page_control = 0;
+ Packet.ModeSenseUFI.parameter_list_length_hi = 0;
+ Packet.ModeSenseUFI.parameter_list_length_lo = sizeof (UFI_MODE_PARAMETER_PAGE_1C);
+ Status = USBFloppyPacketCommand (
+ UsbFloppyDevice,
+ &Packet,
+ sizeof (ATAPI_PACKET_COMMAND),
+ (VOID *) &ModePage1C,
+ sizeof (UFI_MODE_PARAMETER_PAGE_1C),
+ EfiUsbDataIn,
+ USBFLPTIMEOUT
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ UsbFloppyDevice->BlkIo.Media->ReadOnly = ModePage1C.mode_param_header.write_protected;
+
+ return EFI_SUCCESS;
+
+}
+
+EFI_STATUS
+UsbMassStorageModeSense (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice
+ )
+{
+ if (UsbFloppyDevice->AtapiProtocol->CommandProtocol == EFI_USB_SUBCLASS_SCSI) {
+ return UsbSCSIModeSense1APage3F (UsbFloppyDevice);
+ } else {
+ return UsbFloppyModeSense5APage3F (UsbFloppyDevice);
+ }
+}
+
+EFI_STATUS
+UsbFloppyModeSense5APage3F (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice
+ )
+/*++
+
+ Routine Description:
+ Retrieves mode sense information via sending Mode Sense
+ Packet Command.
+
+ Arguments:
+ UsbFloppyDevice - The USB_FLOPPY_DEV instance.
+
+ Returns:
+ EFI_DEVICE_ERROR - Hardware error
+ EFI_SUCCESS - Success
+
+--*/
+{
+ //
+ // status returned by Read Capacity Packet Command
+ //
+ EFI_STATUS Status;
+ ATAPI_PACKET_COMMAND Packet;
+ EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
+ UFI_MODE_PARAMETER_HEADER Header;
+ UINT32 Size;
+
+ UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
+
+ Size = sizeof (UFI_MODE_PARAMETER_HEADER);
+
+ ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
+ Packet.ModeSenseUFI.opcode = UFI_MODE_SENSE5A;
+ Packet.ModeSenseUFI.page_code = 0x3F;
+ Packet.ModeSenseUFI.page_control = 0;
+ Packet.ModeSenseUFI.parameter_list_length_hi = 0;
+ Packet.ModeSenseUFI.parameter_list_length_lo = (UINT8) Size;
+ Status = USBFloppyPacketCommand (
+ UsbFloppyDevice,
+ &Packet,
+ sizeof (ATAPI_PACKET_COMMAND),
+ &Header,
+ Size,
+ EfiUsbDataIn,
+ USBFLPTIMEOUT
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ UsbFloppyDevice->BlkIo.Media->ReadOnly = Header.write_protected;
+
+ return EFI_SUCCESS;
+
+}
+
+EFI_STATUS
+UsbSCSIModeSense1APage3F (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice
+ )
+/*++
+
+ Routine Description:
+ Retrieves mode sense information via sending Mode Sense
+ Packet Command.
+
+ Arguments:
+ UsbFloppyDevice - The USB_FLOPPY_DEV instance.
+
+ Returns:
+ EFI_DEVICE_ERROR - Hardware error
+ EFI_SUCCESS - Success
+
+--*/
+{
+ //
+ // status returned by Read Capacity Packet Command
+ //
+ EFI_STATUS Status;
+ ATAPI_PACKET_COMMAND Packet;
+ EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
+ SCSI_MODE_PARAMETER_HEADER6 Header;
+ UINT32 Size;
+
+ UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
+
+ Size = sizeof (SCSI_MODE_PARAMETER_HEADER6);
+
+ ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
+ Packet.ModeSenseSCSI.opcode = SCSI_MODE_SENSE1A;
+ Packet.ModeSenseSCSI.page_code = 0x3F;
+ Packet.ModeSenseSCSI.page_control = 0;
+ Packet.ModeSenseSCSI.allocation_length = (UINT8) Size;
+ Status = USBFloppyPacketCommand (
+ UsbFloppyDevice,
+ &Packet,
+ sizeof (MODE_SENSE_CMD_SCSI),
+ &Header,
+ Size,
+ EfiUsbDataIn,
+ USBFLPTIMEOUT
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ UsbFloppyDevice->BlkIo.Media->ReadOnly = Header.write_protected;
+ return EFI_SUCCESS;
+
+}
+
+/*++
+
+ The following functions are a set of helper functions,
+ which are used to parse sense key returned by the device.
+
+--*/
+BOOLEAN
+IsNoMedia (
+ IN REQUEST_SENSE_DATA *SenseData,
+ IN UINTN SenseCounts
+ )
+{
+ REQUEST_SENSE_DATA *SensePtr;
+ UINTN Index;
+ BOOLEAN NoMedia;
+
+ NoMedia = FALSE;
+
+ SensePtr = SenseData;
+
+ for (Index = 0; Index < SenseCounts; Index++) {
+
+ if ((SensePtr->sense_key == SK_NOT_READY) &&
+ (SensePtr->addnl_sense_code == ASC_NO_MEDIA)) {
+
+ NoMedia = TRUE;
+ }
+
+ SensePtr++;
+ }
+
+ return NoMedia;
+}
+
+
+BOOLEAN
+IsMediaError (
+ IN REQUEST_SENSE_DATA *SenseData,
+ IN UINTN SenseCounts
+ )
+{
+ REQUEST_SENSE_DATA *SensePtr;
+ UINTN Index;
+ BOOLEAN IsError;
+
+ IsError = FALSE;
+ SensePtr = SenseData;
+
+ for (Index = 0; Index < SenseCounts; Index++) {
+
+ switch (SensePtr->sense_key) {
+
+ //
+ // Medium error case
+ //
+ case SK_MEDIUM_ERROR:
+ switch (SensePtr->addnl_sense_code) {
+
+ case ASC_MEDIA_ERR1:
+ case ASC_MEDIA_ERR2:
+ case ASC_MEDIA_ERR3:
+ case ASC_MEDIA_ERR4:
+ IsError = TRUE;
+ break;
+
+ default:
+ break;
+ }
+
+ break;
+
+ //
+ // Medium upside-down case
+ //
+ case SK_NOT_READY:
+ switch (SensePtr->addnl_sense_code) {
+ case ASC_MEDIA_UPSIDE_DOWN:
+ IsError = TRUE;
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ SensePtr++;
+ }
+
+ return IsError;
+}
+
+BOOLEAN
+IsMediaChange (
+ IN REQUEST_SENSE_DATA *SenseData,
+ IN UINTN SenseCounts
+ )
+{
+ REQUEST_SENSE_DATA *SensePtr;
+ UINTN Index;
+ BOOLEAN MediaChanged;
+
+ MediaChanged = FALSE;
+ SensePtr = SenseData;
+
+ for (Index = 0; Index < SenseCounts; Index++) {
+
+ if ((SensePtr->sense_key == SK_UNIT_ATTENTION) &&
+ (SensePtr->addnl_sense_code == ASC_MEDIA_CHANGE)) {
+
+ MediaChanged = TRUE;
+ }
+
+ SensePtr++;
+ }
+
+ return MediaChanged;
+}
+
+BOOLEAN
+IsDriveReady (
+ IN REQUEST_SENSE_DATA *SenseData,
+ IN UINTN SenseCounts,
+ OUT BOOLEAN *NeedRetry
+ )
+{
+ REQUEST_SENSE_DATA *SensePtr;
+ UINTN Index;
+ BOOLEAN IsReady;
+
+ IsReady = TRUE;
+ *NeedRetry = FALSE;
+ SensePtr = SenseData;
+
+ for (Index = 0; Index < SenseCounts; Index++) {
+
+ if ((SensePtr->sense_key == SK_NOT_READY) &&
+ (SensePtr->addnl_sense_code == ASC_NOT_READY)) {
+
+ switch (SensePtr->addnl_sense_code_qualifier) {
+
+ case ASCQ_IN_PROGRESS:
+ case ASCQ_DEVICE_BUSY:
+ IsReady = FALSE;
+ *NeedRetry = TRUE;
+ break;
+
+ default:
+ //
+ // Drive is in error condition,
+ // no need to retry.
+ //
+ IsReady = FALSE;
+ *NeedRetry = FALSE;
+ break;
+ }
+ }
+
+ SensePtr++;
+ }
+
+ return IsReady;
+}
+
+BOOLEAN
+IsMediaWriteProtected (
+ IN REQUEST_SENSE_DATA *SenseData,
+ IN UINTN SenseCounts
+ )
+{
+ REQUEST_SENSE_DATA *SensePtr;
+ UINTN Index;
+ BOOLEAN IsWriteProtected;
+
+ IsWriteProtected = FALSE;
+ SensePtr = SenseData;
+
+ for (Index = 0; Index < SenseCounts; Index++) {
+ //
+ // catch media write-protected condition.
+ //
+ if ((SensePtr->sense_key == SK_DATA_PROTECT) &&
+ (SensePtr->addnl_sense_code == ASC_WRITE_PROTECTED)) {
+
+ IsWriteProtected = TRUE;
+ }
+
+ SensePtr++;
+ }
+
+ return IsWriteProtected;
+}
+
+BOOLEAN
+IsLogicalUnitCommunicationOverRun (
+ IN REQUEST_SENSE_DATA *SenseData,
+ IN UINTN SenseCounts
+ )
+{
+ REQUEST_SENSE_DATA *SensePtr;
+ UINTN Index;
+ BOOLEAN IsOverRun;
+
+ IsOverRun = FALSE;
+ SensePtr = SenseData;
+
+ for (Index = 0; Index < SenseCounts; Index++) {
+
+ if ((SensePtr->sense_key == SK_NOT_READY) &&
+ (SensePtr->addnl_sense_code == ASC_LOGICAL_UNIT_STATUS) &&
+ (SensePtr->addnl_sense_code_qualifier == ASCQ_LOGICAL_UNIT_OVERRUN)) {
+ IsOverRun = TRUE;
+ }
+
+ SensePtr++;
+ }
+
+ return IsOverRun;
+}
diff --git a/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorageHelper.h b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorageHelper.h
new file mode 100644
index 0000000000..f41241adc4
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorageHelper.h
@@ -0,0 +1,111 @@
+/*++
+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:
+
+ UsbMassStorageHelper.h
+
+Abstract:
+
+ Function prototype for USB Mass Storage Driver
+
+Revision History
+--*/
+#ifndef _USB_FLPHLP_H
+#define _USB_FLPHLP_H
+
+#include "UsbMassStorage.h"
+
+EFI_STATUS
+USBFloppyIdentify (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice
+ );
+
+EFI_STATUS
+USBFloppyPacketCommand (
+ USB_FLOPPY_DEV *UsbFloppyDevice,
+ VOID *Command,
+ UINT8 CommandSize,
+ VOID *DataBuffer,
+ UINT32 BufferLength,
+ EFI_USB_DATA_DIRECTION Direction,
+ UINT16 TimeOutInMilliSeconds
+ );
+
+EFI_STATUS
+USBFloppyInquiry (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice,
+ OUT USB_INQUIRY_DATA **Idata
+ );
+
+EFI_STATUS
+USBFloppyRead10 (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice,
+ IN VOID *Buffer,
+ IN EFI_LBA Lba,
+ IN UINTN NumberOfBlocks
+ );
+
+EFI_STATUS
+USBFloppyReadFormatCapacity (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice
+ );
+
+EFI_STATUS
+UsbFloppyRequestSense (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice,
+ OUT UINTN *SenseCounts
+ );
+
+EFI_STATUS
+UsbFloppyTestUnitReady (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice
+ );
+
+EFI_STATUS
+USBFloppyWrite10 (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice,
+ IN VOID *Buffer,
+ IN EFI_LBA Lba,
+ IN UINTN NumberOfBlocks
+ );
+
+EFI_STATUS
+UsbFloppyDetectMedia (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice,
+ OUT BOOLEAN *MediaChange
+ );
+
+EFI_STATUS
+UsbFloppyModeSense5APage5 (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice
+ );
+
+EFI_STATUS
+UsbFloppyModeSense5APage1C (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice
+ );
+
+EFI_STATUS
+UsbFloppyModeSense5APage3F (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice
+ );
+
+EFI_STATUS
+UsbSCSIModeSense1APage3F (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice
+ );
+
+EFI_STATUS
+UsbMassStorageModeSense (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice
+ );
+
+#endif
diff --git a/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/build.xml b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/build.xml
new file mode 100644
index 0000000000..d2e48d3027
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/build.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?><!-- 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.-->
+<project basedir="." default="UsbMassStorage"><!--Apply external ANT tasks-->
+ <taskdef resource="GenBuild.tasks"/>
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+ <property environment="env"/>
+ <property name="WORKSPACE_DIR" value="${env.WORKSPACE}"/>
+ <import file="${WORKSPACE_DIR}\Tools\Conf\BuildMacro.xml"/><!--MODULE_RELATIVE PATH is relative to PACKAGE_DIR-->
+ <property name="MODULE_RELATIVE_PATH" value="Bus\Usb\UsbMassStorage\Dxe"/>
+ <property name="MODULE_DIR" value="${PACKAGE_DIR}\${MODULE_RELATIVE_PATH}"/>
+ <property name="COMMON_FILE" value="${WORKSPACE_DIR}\Tools\Conf\Common.xml"/>
+ <target name="UsbMassStorage">
+ <GenBuild baseName="UsbMassStorage" mbdFilename="${MODULE_DIR}\UsbMassStorage.mbd" msaFilename="${MODULE_DIR}\UsbMassStorage.msa"/>
+ </target>
+ <target depends="UsbMassStorage_clean" name="clean"/>
+ <target depends="UsbMassStorage_cleanall" name="cleanall"/>
+ <target name="UsbMassStorage_clean">
+ <OutputDirSetup baseName="UsbMassStorage" mbdFilename="${MODULE_DIR}\UsbMassStorage.mbd" msaFilename="${MODULE_DIR}\UsbMassStorage.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\UsbMassStorage_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\UsbMassStorage_build.xml" target="clean"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}" excludes="*.xml"/>
+ </target>
+ <target name="UsbMassStorage_cleanall">
+ <OutputDirSetup baseName="UsbMassStorage" mbdFilename="${MODULE_DIR}\UsbMassStorage.mbd" msaFilename="${MODULE_DIR}\UsbMassStorage.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\UsbMassStorage_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\UsbMassStorage_build.xml" target="cleanall"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}"/>
+ <delete dir="${DEST_DIR_DEBUG}"/>
+ <delete>
+ <fileset dir="${BIN_DIR}" includes="**UsbMassStorage*"/>
+ </delete>
+ </target>
+</project> \ No newline at end of file