summaryrefslogtreecommitdiff
path: root/MdeModulePkg
diff options
context:
space:
mode:
authorvanjeff <vanjeff@6f19259b-4bc3-4df7-8a09-765794883524>2007-07-24 09:54:50 +0000
committervanjeff <vanjeff@6f19259b-4bc3-4df7-8a09-765794883524>2007-07-24 09:54:50 +0000
commit50fa1b3a86faee57ca597e778c9db4ed4233f83e (patch)
tree9f7576b32fc70dc3f7bac646fc84c84861648e13 /MdeModulePkg
parentd19862fe4f9d0e5c5886c94a1e115f231d8fd302 (diff)
downloadedk2-platforms-50fa1b3a86faee57ca597e778c9db4ed4233f83e.tar.xz
Sync USB modules with main trunk.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3423 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'MdeModulePkg')
-rw-r--r--MdeModulePkg/Bus/Pci/EhciDxe/EhciDebug.h4
-rw-r--r--MdeModulePkg/Bus/Pci/EhciDxe/EhciSched.c71
-rw-r--r--MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c83
-rw-r--r--MdeModulePkg/Bus/Usb/UsbBusDxe/usbbus.c13
-rw-r--r--MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBoot.c256
-rw-r--r--MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBoot.h42
6 files changed, 330 insertions, 139 deletions
diff --git a/MdeModulePkg/Bus/Pci/EhciDxe/EhciDebug.h b/MdeModulePkg/Bus/Pci/EhciDxe/EhciDebug.h
index 247021b40d..4df8e9ee7e 100644
--- a/MdeModulePkg/Bus/Pci/EhciDxe/EhciDebug.h
+++ b/MdeModulePkg/Bus/Pci/EhciDxe/EhciDebug.h
@@ -150,10 +150,14 @@ EhcDumpBuf (
#define EHC_DEBUG(arg) EhcDebug arg
#define EHC_ERROR(arg) EhcError arg
#define EHC_DUMP_QH(arg) EhcDumpQh arg
+ #define EHC_DUMP_QTD(arg) EhcDumpQtd arg
+ #define EHC_DUMP_BUF(arg) EhcDumpBuf arg
#else
#define EHC_DEBUG(arg)
#define EHC_ERROR(arg)
#define EHC_DUMP_QH(arg)
+ #define EHC_DUMP_QTD(arg)
+ #define EHC_DUMP_BUF(arg)
#endif
#endif
diff --git a/MdeModulePkg/Bus/Pci/EhciDxe/EhciSched.c b/MdeModulePkg/Bus/Pci/EhciDxe/EhciSched.c
index b13e4078b0..4c2dc86f06 100644
--- a/MdeModulePkg/Bus/Pci/EhciDxe/EhciSched.c
+++ b/MdeModulePkg/Bus/Pci/EhciDxe/EhciSched.c
@@ -771,6 +771,67 @@ EhciDelAllAsyncIntTransfers (
}
}
+STATIC
+EFI_STATUS
+EhcFlushAsyncIntMap (
+ IN USB2_HC_DEV *Ehc,
+ IN URB *Urb
+ )
+/*++
+
+Routine Description:
+
+ Flush data from PCI controller specific address to mapped system
+ memory address.
+
+Arguments:
+
+ Ehc - The EHCI device
+ Urb - The URB to unmap
+
+Returns:
+
+ EFI_SUCCESS - Success to flush data to mapped system memory
+ EFI_DEVICE_ERROR - Fail to flush data to mapped system memory
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS PhyAddr;
+ EFI_PCI_IO_PROTOCOL_OPERATION MapOp;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINTN Len;
+ VOID *Map;
+
+ PciIo = Ehc->PciIo;
+ Len = Urb->DataLen;
+
+ if (Urb->Ep.Direction == EfiUsbDataIn) {
+ MapOp = EfiPciIoOperationBusMasterWrite;
+ } else {
+ MapOp = EfiPciIoOperationBusMasterRead;
+ }
+
+ Status = PciIo->Unmap (PciIo, Urb->DataMap);
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+ Urb->DataMap = NULL;
+
+ Status = PciIo->Map (PciIo, MapOp, Urb->Data, &Len, &PhyAddr, &Map);
+ if (EFI_ERROR (Status) || (Len != Urb->DataLen)) {
+ goto ON_ERROR;
+ }
+
+ Urb->DataPhy = (VOID *) ((UINTN) PhyAddr);
+ Urb->DataMap = Map;
+ return EFI_SUCCESS;
+
+ON_ERROR:
+ return EFI_DEVICE_ERROR;
+}
+
/**
@@ -873,6 +934,7 @@ EhcMoniteAsyncRequests (
BOOLEAN Finished;
UINT8 *ProcBuf;
URB *Urb;
+ EFI_STATUS Status;
OldTpl = gBS->RaiseTPL (EHC_TPL);
Ehc = (USB2_HC_DEV *) Context;
@@ -891,6 +953,15 @@ EhcMoniteAsyncRequests (
}
//
+ // Flush any PCI posted write transactions from a PCI host
+ // bridge to system memory.
+ //
+ Status = EhcFlushAsyncIntMap (Ehc, Urb);
+ if (EFI_ERROR (Status)) {
+ EHC_ERROR (("EhcMoniteAsyncRequests: Fail to Flush AsyncInt Mapped Memeory\n"));
+ }
+
+ //
// Allocate a buffer then copy the transferred data for user.
// If failed to allocate the buffer, update the URB for next
// round of transfer. Ignore the data of this round.
diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c
index 9fbaf6b417..0b5532ec56 100644
--- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c
+++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c
@@ -881,40 +881,71 @@ UsbEnumeratePort (
// connect/disconnect. Other three events are: ENABLE, SUSPEND, RESET.
// ENABLE/RESET is used to reset port. SUSPEND isn't supported.
//
- Status = EFI_SUCCESS;
+
+ if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_OVERCURRENT)) {
- if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_OVERCURRENT)) {
- //
- // If overcurrent condition is cleared, enable the port again
- //
- if (!USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_OVERCURRENT)) {
- HubApi->SetPortFeature (HubIf, Port, (EFI_USB_PORT_FEATURE) USB_HUB_PORT_POWER);
+ if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_OVERCURRENT)) {
+ //
+ // Both OverCurrent and OverCurrentChange set, means over current occurs,
+ // which probably is caused by short circuit. It has to wait system hardware
+ // to perform recovery.
+ //
+ USB_DEBUG (("UsbEnumeratePort: Critical Over Current\n", Port));
+ return EFI_DEVICE_ERROR;
+
+ } else {
+ //
+ // Only OverCurrentChange set, means system has been recoveried from
+ // over current. As a result, all ports are nearly power-off, so
+ // it's necessary to detach and enumerate all ports again.
+ //
+ USB_DEBUG (("UsbEnumeratePort: 2.0 device Recovery Over Current\n", Port));
+ goto ON_ENUMERATE;
+
}
+ }
- } else if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_CONNECTION)) {
+ if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_ENABLE)) {
//
- // Device connected or disconnected. Either way, if there is
- // already a device present in the bus, need to remove it.
+ // 1.1 roothub port reg doesn't reflect over-current state, while its counterpart
+ // on 2.0 roothub does. When over-current has influence on 1.1 device, the port
+ // would be disabled, so it's also necessary to detach and enumerate again.
//
- Child = UsbFindChild (HubIf, Port);
-
- if (Child != NULL) {
- USB_DEBUG (("UsbEnumeratePort: device at port %d removed from system\n", Port));
- UsbRemoveDevice (Child);
- }
+ USB_DEBUG (("UsbEnumeratePort: 1.1 device Recovery Over Current\n", Port));
+ goto ON_ENUMERATE;
+ }
+
+ if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_CONNECTION)) {
+ //
+ // Device connected or disconnected normally.
+ //
+ goto ON_ENUMERATE;
+ }
- if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_CONNECTION)) {
- //
- // Now, new device connected, enumerate and configure the device
- //
- USB_DEBUG (("UsbEnumeratePort: new device connected at port %d\n", Port));
- Status = UsbEnumerateNewDev (HubIf, Port);
+ON_ENUMERATE:
- } else {
- USB_DEBUG (("UsbEnumeratePort: device disconnected event on port %d\n", Port));
- }
+ //
+ // In case there is already a device on this port logically, it's safety to remove
+ // and enumerate again.
+ //
+ Child = UsbFindChild (HubIf, Port);
+
+ if (Child != NULL) {
+ USB_DEBUG (("UsbEnumeratePort: device at port %d removed from system\n", Port));
+ UsbRemoveDevice (Child);
}
-
+
+ if (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_CONNECTION)) {
+ //
+ // Now, new device connected, enumerate and configure the device
+ //
+ USB_DEBUG (("UsbEnumeratePort: new device connected at port %d\n", Port));
+ Status = UsbEnumerateNewDev (HubIf, Port);
+
+ } else {
+ USB_DEBUG (("UsbEnumeratePort: device disconnected event on port %d\n", Port));
+ }
+
HubApi->ClearPortChange (HubIf, Port);
return Status;
}
diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/usbbus.c b/MdeModulePkg/Bus/Usb/UsbBusDxe/usbbus.c
index c5a0604fca..096b10a831 100644
--- a/MdeModulePkg/Bus/Usb/UsbBusDxe/usbbus.c
+++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/usbbus.c
@@ -645,11 +645,16 @@ UsbIoGetEndpointDescriptor (
UsbIf = USB_INTERFACE_FROM_USBIO (This);
- if ((Descriptor == NULL) || (Index >= UsbIf->IfSetting->Desc.NumEndpoints)) {
+ if ((Descriptor == NULL) || (Index > 15)) {
gBS->RestoreTPL (OldTpl);
return EFI_INVALID_PARAMETER;
}
+ if (Index >= UsbIf->IfSetting->Desc.NumEndpoints) {
+ gBS->RestoreTPL (OldTpl);
+ return EFI_NOT_FOUND;
+ }
+
CopyMem (
Descriptor,
&(UsbIf->IfSetting->Endpoints[Index]->Desc),
@@ -813,6 +818,11 @@ UsbIoPortReset (
UsbIf = USB_INTERFACE_FROM_USBIO (This);
Dev = UsbIf->Device;
+ if (UsbIf->IsHub == TRUE) {
+ Status = EFI_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+
HubIf = Dev->ParentIf;
Status = HubIf->HubApi->ResetPort (HubIf, Dev->ParentPort);
@@ -875,7 +885,6 @@ EFI_USB_IO_PROTOCOL mUsbIoProtocol = {
UsbIoPortReset
};
-//@MT: EFI_DRIVER_ENTRY_POINT (UsbBusDriverEntryPoint)
EFI_STATUS
EFIAPI
diff --git a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBoot.c b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBoot.c
index e9b0a2a72a..e52d11532f 100644
--- a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBoot.c
+++ b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBoot.c
@@ -26,6 +26,34 @@ Revision History
#include "UsbMassImpl.h"
+EFI_TPL
+UsbGetCurrentTpl (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ return the current TPL, copied from the EDKII glue lib.
+
+Arguments:
+
+ VOID
+
+Returns:
+
+ Current TPL
+
+--*/
+{
+ EFI_TPL Tpl;
+
+ Tpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
+ gBS->RestoreTPL (Tpl);
+
+ return Tpl;
+}
+
/**
Read an UINT32 from the buffer to avoid byte alignment problems, then
convert that to the little endia. The USB mass storage bootability spec
@@ -140,7 +168,7 @@ UsbBootRequestSense (
);
if (EFI_ERROR (Status) || CmdResult != USB_MASS_CMD_SUCCESS) {
DEBUG ((mUsbMscError, "UsbBootRequestSense: (%r) CmdResult=0x%x\n", Status, CmdResult));
- return EFI_DEVICE_ERROR;
+ return Status;
}
//
@@ -151,6 +179,9 @@ UsbBootRequestSense (
switch (USB_BOOT_SENSE_KEY (SenseData.SenseKey)) {
case USB_BOOT_SENSE_NO_SENSE:
+ Status = EFI_NO_RESPONSE;
+ break;
+
case USB_BOOT_SENSE_RECOVERED:
//
// Suppose hardware can handle this case, and recover later by itself
@@ -159,26 +190,12 @@ UsbBootRequestSense (
break;
case USB_BOOT_SENSE_NOT_READY:
- switch (SenseData.ASC) {
- case USB_BOOT_ASC_NO_MEDIA:
- Status = EFI_NO_MEDIA;
- Media->MediaPresent = FALSE;
- break;
-
- case USB_BOOT_ASC_MEDIA_UPSIDE_DOWN:
- Status = EFI_DEVICE_ERROR;
- Media->MediaPresent = FALSE;
- break;
-
- case USB_BOOT_ASC_NOT_READY:
- if (SenseData.ASCQ == USB_BOOT_ASCQ_IN_PROGRESS ||
- SenseData.ASCQ == USB_BOOT_ASCQ_DEVICE_BUSY) {
- //
- // Regular timeout, and need retry once more
- //
- DEBUG ((mUsbMscInfo, "UsbBootRequestSense: Not ready and need retry once more\n"));
- Status = EFI_NOT_READY;
- }
+ Status = EFI_DEVICE_ERROR;
+ if (SenseData.ASC == USB_BOOT_ASC_NO_MEDIA) {
+ Media->MediaPresent = FALSE;
+ Status = EFI_NO_MEDIA;
+ } else if (SenseData.ASC == USB_BOOT_ASC_NOT_READY) {
+ Status = EFI_NOT_READY;
}
break;
@@ -189,14 +206,18 @@ UsbBootRequestSense (
case USB_BOOT_SENSE_UNIT_ATTENTION:
Status = EFI_DEVICE_ERROR;
if (SenseData.ASC == USB_BOOT_ASC_MEDIA_CHANGE) {
- Status = EFI_MEDIA_CHANGED;
- UsbMass->BlockIoMedia.MediaId++;
+ //
+ // If MediaChange, reset ReadOnly and new MediId
+ //
+ Status = EFI_MEDIA_CHANGED;
+ Media->ReadOnly = FALSE;
+ Media->MediaId++;
}
break;
case USB_BOOT_SNESE_DATA_PROTECT:
- Status = EFI_WRITE_PROTECTED;
- UsbMass->BlockIoMedia.ReadOnly = TRUE;
+ Status = EFI_WRITE_PROTECTED;
+ Media->ReadOnly = TRUE;
break;
default:
@@ -270,6 +291,9 @@ UsbBootExecCmd (
return EFI_SUCCESS;
}
+ DEBUG ((mUsbMscInfo, "UsbBootExecCmd: Fail to Exec 0x%x Cmd /w %r\n",
+ *(UINT8 *)Cmd ,Status));
+
return UsbBootRequestSense (UsbMass);
}
@@ -417,7 +441,7 @@ UsbBootInquiry (
EfiUsbDataIn,
&InquiryData,
sizeof (USB_BOOT_INQUIRY_DATA),
- USB_BOOT_INQUIRY_CMD_TIMEOUT
+ USB_BOOT_GENERAL_CMD_TIMEOUT
);
if (EFI_ERROR (Status)) {
return Status;
@@ -485,8 +509,12 @@ UsbBootReadCapacity (
Media->LastBlock = UsbBootGetUint32 (CapacityData.LastLba);
Media->BlockSize = UsbBootGetUint32 (CapacityData.BlockLen);
- DEBUG ((mUsbMscInfo, "UsbBootReadCapacity Success LBA=%d BlockSize=%d\n",
- Media->LastBlock, Media->BlockSize));
+ if (Media->BlockSize == 0) {
+ return EFI_NOT_READY;
+ }
+
+ DEBUG ((mUsbMscInfo, "UsbBootReadCapacity Success LBA=%ld BlockSize=%d\n",
+ Media->LastBlock, Media->BlockSize));
return EFI_SUCCESS;
}
@@ -503,47 +531,49 @@ UsbBootReadCapacity (
**/
EFI_STATUS
-UsbBootModeSense (
+UsbScsiModeSense (
IN USB_MASS_DEVICE *UsbMass
)
{
EFI_STATUS Status;
- USB_BOOT_MODE_SENSE_CMD ModeSenseCmd;
- USB_BOOT_MODE_PARA_HEADER ModeParaHeader;
- UINT8 CommandSet;
+ USB_SCSI_MODE_SENSE6_CMD ModeSenseCmd;
+ USB_SCSI_MODE_SENSE6_PARA_HEADER ModeParaHeader;
+ EFI_BLOCK_IO_MEDIA *Media;
+
+ CopyMem (
+ &Media,
+ &(UsbMass->BlockIoMedia),
+ sizeof (EFI_BLOCK_IO_MEDIA)
+ );
- ZeroMem (&ModeSenseCmd, sizeof (USB_BOOT_MODE_SENSE_CMD));
- ZeroMem (&ModeParaHeader, sizeof (USB_BOOT_MODE_PARA_HEADER));
+ ZeroMem (&ModeSenseCmd, sizeof (USB_SCSI_MODE_SENSE6_CMD));
+ ZeroMem (&ModeParaHeader, sizeof (USB_SCSI_MODE_SENSE6_PARA_HEADER));
//
- // overuse Context Pointer, the first field of Bot or Cbi is EFI_USB_INTERFACE_DESCRIPTOR
+ // ModeSense6 command is defined in [SCSI2Spec-Page151]
//
- CommandSet = ((EFI_USB_INTERFACE_DESCRIPTOR *) (UsbMass->Context))->InterfaceSubClass;
-
- if (CommandSet == USB_MASS_STORE_SCSI) {
- //
- // Not UFI Command Set, no ModeSense Command
- //
- return EFI_SUCCESS;
- }
-
- ModeSenseCmd.OpCode = USB_BOOT_MODE_SENSE10_OPCODE;
- ModeSenseCmd.PageCode = 0x3f;
- ModeSenseCmd.ParaListLenLsb = (UINT8) sizeof (USB_BOOT_MODE_PARA_HEADER);
+ ModeSenseCmd.OpCode = USB_SCSI_MODE_SENSE6_OPCODE;
+ ModeSenseCmd.Lun = USB_BOOT_LUN (UsbMass->Lun);
+ ModeSenseCmd.PageCode = 0x3F;
+ ModeSenseCmd.AllocateLen = (UINT8) sizeof (USB_SCSI_MODE_SENSE6_PARA_HEADER);
Status = UsbBootExecCmdWithRetry (
UsbMass,
&ModeSenseCmd,
- sizeof (USB_BOOT_MODE_SENSE_CMD),
+ sizeof (USB_SCSI_MODE_SENSE6_CMD),
EfiUsbDataIn,
&ModeParaHeader,
- sizeof (USB_BOOT_MODE_PARA_HEADER),
+ sizeof (USB_SCSI_MODE_SENSE6_PARA_HEADER),
USB_BOOT_GENERAL_CMD_TIMEOUT
);
+
//
- // Did nothing with the Header here
- // But probably should
+ // ModeSense(6) is used to get the information of WriteProtected. While only some of
+ // devices support this command, so have a try here.
//
+ if (!EFI_ERROR (Status)) {
+ Media->ReadOnly = (ModeParaHeader.DevicePara & 0x80) ? TRUE : FALSE;
+ }
return Status;
}
@@ -570,6 +600,15 @@ UsbBootGetParams (
{
EFI_BLOCK_IO_MEDIA *Media;
EFI_STATUS Status;
+ UINT8 CmdSet;
+
+ CopyMem (
+ &Media,
+ &(UsbMass->BlockIoMedia),
+ sizeof (EFI_BLOCK_IO_MEDIA)
+ );
+
+ CmdSet = ((EFI_USB_INTERFACE_DESCRIPTOR *) (UsbMass->Context))->InterfaceSubClass;
Status = UsbBootInquiry (UsbMass);
if (EFI_ERROR (Status)) {
@@ -577,29 +616,30 @@ UsbBootGetParams (
return Status;
}
- Media = &(UsbMass->BlockIoMedia);
//
// Don't use the Removable bit in inquirydata to test whether the media
// is removable because many flash disks wrongly set this bit.
//
if ((UsbMass->Pdt == USB_PDT_CDROM) || (UsbMass->Pdt == USB_PDT_OPTICAL)) {
//
- // CD-Rom or Optical device
+ // CD-Rom device and Non-CD optical device
//
UsbMass->OpticalStorage = TRUE;
//
// Default value 2048 Bytes, in case no media present at first time
//
Media->BlockSize = 0x0800;
- } else {
+ }
+
+ if ((UsbMass->Pdt != USB_PDT_CDROM) && (CmdSet == USB_MASS_STORE_SCSI)) {
//
- // Non CD-Rom device need ModeSenseCmd between InquiryCmd and ReadCapacityCmd
+ // ModeSense is required for the device with PDT of 0x00/0x07/0x0E,
+ // which is from [MassStorageBootabilitySpec-Page7].
+ // ModeSense(10) is useless here, while ModeSense(6) defined in SCSI
+ // could get the information of WriteProtected.
+ // Since not all device support this command, so skip if fail.
//
- Status = UsbBootModeSense (UsbMass);
- if (EFI_ERROR (Status)) {
- DEBUG ((mUsbMscError, "UsbBootGetParams: UsbBootModeSense (%r)\n", Status));
- return Status;
- }
+ UsbScsiModeSense (UsbMass);
}
return UsbBootReadCapacity (UsbMass);
@@ -623,6 +663,8 @@ UsbBootDetectMedia (
{
EFI_BLOCK_IO_MEDIA OldMedia;
EFI_BLOCK_IO_MEDIA *Media;
+ UINT8 CmdSet;
+ EFI_TPL OldTpl;
EFI_STATUS Status;
Media = &UsbMass->BlockIoMedia;
@@ -633,54 +675,80 @@ UsbBootDetectMedia (
sizeof (EFI_BLOCK_IO_MEDIA)
);
- //
- // First test whether the device is ready and get status
- // If media changed or ready, need read the device's capacity
- //
+ CmdSet = ((EFI_USB_INTERFACE_DESCRIPTOR *) (UsbMass->Context))->InterfaceSubClass;
+
Status = UsbBootIsUnitReady (UsbMass);
- if ((Status == EFI_SUCCESS && Media->MediaPresent) ||
- (Status == EFI_MEDIA_CHANGED)) {
- if ((UsbMass->Pdt != USB_PDT_CDROM) &&
- (UsbMass->Pdt != USB_PDT_OPTICAL)) {
- //
- // Non CD-Rom device need ModeSenseCmd between InquiryCmd and ReadCapacityCmd
- //
- UsbBootModeSense (UsbMass);
- }
- DEBUG ((mUsbMscInfo, "UsbBootDetectMedia: Need Read Capacity\n"));
- Status = UsbBootReadCapacity (UsbMass);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((mUsbMscError, "UsbBootDetectMedia: UsbBootIsUnitReady (%r)\n", Status));
+ goto ON_ERROR;
}
+
+ if ((UsbMass->Pdt != USB_PDT_CDROM) && (CmdSet == USB_MASS_STORE_SCSI)) {
+ //
+ // ModeSense is required for the device with PDT of 0x00/0x07/0x0E,
+ // which is from [MassStorageBootabilitySpec-Page7].
+ // ModeSense(10) is useless here, while ModeSense(6) defined in SCSI
+ // could get the information of WriteProtected.
+ // Since not all device support this command, so skip if fail.
+ //
+ UsbScsiModeSense (UsbMass);
+ }
+
+ Status = UsbBootReadCapacity (UsbMass);
if (EFI_ERROR (Status)) {
- return Status;
+ DEBUG ((mUsbMscError, "UsbBootDetectMedia: UsbBootReadCapacity (%r)\n", Status));
+ goto ON_ERROR;
}
+ return EFI_SUCCESS;
+
+ON_ERROR:
//
// Detect whether it is necessary to reinstall the BlockIO
//
+ // MediaId may change in RequestSense for MediaChanged
+ // MediaPresent may change in RequestSense for NoMedia
+ // MediaReadOnly may change in RequestSense for WriteProtected or MediaChanged
+ // MediaPresent/BlockSize/LastBlock may change in ReadCapacity
+ //
if ((Media->MediaId != OldMedia.MediaId) ||
(Media->MediaPresent != OldMedia.MediaPresent) ||
(Media->ReadOnly != OldMedia.ReadOnly) ||
(Media->BlockSize != OldMedia.BlockSize) ||
(Media->LastBlock != OldMedia.LastBlock)) {
- DEBUG ((mUsbMscInfo, "UsbBootDetectMedia: Need reinstall BlockIoProtocol\n"));
- Media->MediaId++;
+
+ OldTpl = UsbGetCurrentTpl ();
+ DEBUG ((mUsbMscError, "UsbBootDetectMedia: TPL before reinstall BlockIoProtocol is %d\n", OldTpl));
+
+ gBS->RestoreTPL (TPL_CALLBACK);
+
gBS->ReinstallProtocolInterface (
UsbMass->Controller,
&gEfiBlockIoProtocolGuid,
&UsbMass->BlockIo,
&UsbMass->BlockIo
);
+
+ DEBUG ((mUsbMscError, "UsbBootDetectMedia: TPL after reinstall is %d\n", UsbGetCurrentTpl()));
+ ASSERT (UsbGetCurrentTpl () == TPL_CALLBACK);
+
+ gBS->RaiseTPL (OldTpl);
+
//
- // Check whether media present or media changed or write protected
+ // Update MediaId after reinstall BLOCK_IO_PROTOCOL
//
- if (Media->MediaPresent == FALSE) {
- Status = EFI_NO_MEDIA;
- }
- if (Media->MediaId != OldMedia.MediaId) {
- Status = EFI_MEDIA_CHANGED;
+ if (Media->MediaPresent != OldMedia.MediaPresent) {
+ if (Media->MediaPresent == TRUE) {
+ Media->MediaId = 1;
+ } else {
+ Media->MediaId = 0;
+ }
}
- if (Media->ReadOnly != OldMedia.ReadOnly) {
- Status = EFI_WRITE_PROTECTED;
+
+ if ((Media->ReadOnly != OldMedia.ReadOnly) ||
+ (Media->BlockSize != OldMedia.BlockSize) ||
+ (Media->LastBlock != OldMedia.LastBlock)) {
+ Media->MediaId++;
}
}
@@ -728,13 +796,9 @@ UsbBootReadBlocks (
ByteSize = (UINT32)Count * BlockSize;
//
- // Optical device need longer timeout than other device
+ // USB command's upper limit timeout is 5s. [USB2.0-9.2.6.1]
//
- if (UsbMass->OpticalStorage == TRUE) {
- Timeout = (UINT32)Count * USB_BOOT_OPTICAL_BLOCK_TIMEOUT;
- } else {
- Timeout = (UINT32)Count * USB_BOOT_GENERAL_BLOCK_TIMEOUT;
- }
+ Timeout = (UINT32) USB_BOOT_GENERAL_CMD_TIMEOUT;
//
// Fill in the command then execute
@@ -808,13 +872,9 @@ UsbBootWriteBlocks (
ByteSize = (UINT32)Count * BlockSize;
//
- // Optical device need longer timeout than other device
+ // USB command's upper limit timeout is 5s. [USB2.0-9.2.6.1]
//
- if (UsbMass->OpticalStorage == TRUE) {
- Timeout = (UINT32)Count * USB_BOOT_OPTICAL_BLOCK_TIMEOUT;
- } else {
- Timeout = (UINT32)Count * USB_BOOT_GENERAL_BLOCK_TIMEOUT;
- }
+ Timeout = (UINT32) USB_BOOT_GENERAL_CMD_TIMEOUT;
//
// Fill in the write10 command block
diff --git a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBoot.h b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBoot.h
index dc4b43faae..bfef2609ad 100644
--- a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBoot.h
+++ b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBoot.h
@@ -39,12 +39,14 @@ enum {
USB_BOOT_INQUIRY_OPCODE = 0x12,
USB_BOOT_REQUEST_SENSE_OPCODE = 0x03,
- USB_BOOT_MODE_SENSE10_OPCODE = 0x5a,
+ USB_BOOT_MODE_SENSE10_OPCODE = 0x5A,
USB_BOOT_READ_CAPACITY_OPCODE = 0x25,
USB_BOOT_TEST_UNIT_READY_OPCODE = 0x00,
USB_BOOT_READ10_OPCODE = 0x28,
- USB_BOOT_WRITE10_OPCODE = 0x2a,
+ USB_BOOT_WRITE10_OPCODE = 0x2A,
+ USB_SCSI_MODE_SENSE6_OPCODE = 0x1A,
+
//
// The Sense Key part of the sense data. Sense data has three levels:
// Sense key, Additional Sense Code and Additional Sense Code Qualifier
@@ -64,13 +66,9 @@ enum {
USB_BOOT_SENSE_MISCOMPARE = 0x0E, // Source data mis-match while verfying.
USB_BOOT_ASC_NOT_READY = 0x04,
- USB_BOOT_ASC_MEDIA_UPSIDE_DOWN = 0x06,
USB_BOOT_ASC_NO_MEDIA = 0x3A,
USB_BOOT_ASC_MEDIA_CHANGE = 0x28,
- USB_BOOT_ASCQ_IN_PROGRESS = 0x01,
- USB_BOOT_ASCQ_DEVICE_BUSY = 0xFF,
-
//
// Other parameters
//
@@ -90,11 +88,13 @@ enum {
//
// Boot Transfer timeout
//
- USB_BOOT_GENERAL_BLOCK_TIMEOUT = 200 * USB_MASS_STALL_1_MS,
- USB_BOOT_OPTICAL_BLOCK_TIMEOUT = 1 * USB_MASS_STALL_1_S,
- USB_BOOT_GENERAL_CMD_TIMEOUT = 1 * USB_MASS_STALL_1_S,
- USB_BOOT_INQUIRY_CMD_TIMEOUT = 3 * USB_MASS_STALL_1_S,
-
+ // USB2.0 Spec define the up-limit timeout 5s for all command. USB floppy,
+ // USB CD-Rom and iPod devices are much slower than USB key when reponse
+ // most of commands, So we set 5s as timeout here.
+ //
+ //
+ USB_BOOT_GENERAL_CMD_TIMEOUT = 5 * USB_MASS_STALL_1_S,
+
//
// Supported PDT codes, or Peripheral Device Type
//
@@ -159,7 +159,7 @@ typedef struct {
UINT8 ParaListLenLsb;
UINT8 Reserved1;
UINT8 Pad[2];
-} USB_BOOT_MODE_SENSE_CMD;
+} USB_BOOT_MODE_SENSE10_CMD;
typedef struct {
UINT8 ModeDataLenMsb;
@@ -167,7 +167,7 @@ typedef struct {
UINT8 Reserved0[4];
UINT8 BlkDesLenMsb;
UINT8 BlkDesLenLsb;
-} USB_BOOT_MODE_PARA_HEADER;
+} USB_BOOT_MODE_SENSE10_PARA_HEADER;
typedef struct {
UINT8 OpCode;
@@ -209,6 +209,22 @@ typedef struct {
UINT8 ASCQ; // Additional Sense Code Qualifier
UINT8 Reserverd2[4];
} USB_BOOT_REQUEST_SENSE_DATA;
+
+typedef struct {
+ UINT8 OpCode;
+ UINT8 Lun;
+ UINT8 PageCode;
+ UINT8 Reserved0;
+ UINT8 AllocateLen;
+ UINT8 Control;
+} USB_SCSI_MODE_SENSE6_CMD;
+
+typedef struct {
+ UINT8 ModeDataLen;
+ UINT8 MediumType;
+ UINT8 DevicePara;
+ UINT8 BlkDesLen;
+} USB_SCSI_MODE_SENSE6_PARA_HEADER;
#pragma pack()
//