Sync USB modules with main trunk.

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3423 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
vanjeff 2007-07-24 09:54:50 +00:00
parent d19862fe4f
commit 50fa1b3a86
6 changed files with 332 additions and 141 deletions

View File

@ -150,10 +150,14 @@ EhcDumpBuf (
#define EHC_DEBUG(arg) EhcDebug arg #define EHC_DEBUG(arg) EhcDebug arg
#define EHC_ERROR(arg) EhcError arg #define EHC_ERROR(arg) EhcError arg
#define EHC_DUMP_QH(arg) EhcDumpQh arg #define EHC_DUMP_QH(arg) EhcDumpQh arg
#define EHC_DUMP_QTD(arg) EhcDumpQtd arg
#define EHC_DUMP_BUF(arg) EhcDumpBuf arg
#else #else
#define EHC_DEBUG(arg) #define EHC_DEBUG(arg)
#define EHC_ERROR(arg) #define EHC_ERROR(arg)
#define EHC_DUMP_QH(arg) #define EHC_DUMP_QH(arg)
#define EHC_DUMP_QTD(arg)
#define EHC_DUMP_BUF(arg)
#endif #endif
#endif #endif

View File

@ -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; BOOLEAN Finished;
UINT8 *ProcBuf; UINT8 *ProcBuf;
URB *Urb; URB *Urb;
EFI_STATUS Status;
OldTpl = gBS->RaiseTPL (EHC_TPL); OldTpl = gBS->RaiseTPL (EHC_TPL);
Ehc = (USB2_HC_DEV *) Context; Ehc = (USB2_HC_DEV *) Context;
@ -890,6 +952,15 @@ EhcMoniteAsyncRequests (
continue; continue;
} }
//
// 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. // Allocate a buffer then copy the transferred data for user.
// If failed to allocate the buffer, update the URB for next // If failed to allocate the buffer, update the URB for next

View File

@ -881,40 +881,71 @@ UsbEnumeratePort (
// connect/disconnect. Other three events are: ENABLE, SUSPEND, RESET. // connect/disconnect. Other three events are: ENABLE, SUSPEND, RESET.
// ENABLE/RESET is used to reset port. SUSPEND isn't supported. // 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 (USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_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);
}
} else if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_CONNECTION)) {
//
// Device connected or disconnected. Either way, if there is
// already a device present in the bus, need to remove it.
//
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 // 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: new device connected at port %d\n", Port)); USB_DEBUG (("UsbEnumeratePort: Critical Over Current\n", Port));
Status = UsbEnumerateNewDev (HubIf, Port); return EFI_DEVICE_ERROR;
} else { } else {
USB_DEBUG (("UsbEnumeratePort: device disconnected event on port %d\n", Port)); //
// 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;
} }
} }
if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_ENABLE)) {
//
// 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.
//
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;
}
ON_ENUMERATE:
//
// 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); HubApi->ClearPortChange (HubIf, Port);
return Status; return Status;
} }

View File

@ -645,11 +645,16 @@ UsbIoGetEndpointDescriptor (
UsbIf = USB_INTERFACE_FROM_USBIO (This); UsbIf = USB_INTERFACE_FROM_USBIO (This);
if ((Descriptor == NULL) || (Index >= UsbIf->IfSetting->Desc.NumEndpoints)) { if ((Descriptor == NULL) || (Index > 15)) {
gBS->RestoreTPL (OldTpl); gBS->RestoreTPL (OldTpl);
return EFI_INVALID_PARAMETER; return EFI_INVALID_PARAMETER;
} }
if (Index >= UsbIf->IfSetting->Desc.NumEndpoints) {
gBS->RestoreTPL (OldTpl);
return EFI_NOT_FOUND;
}
CopyMem ( CopyMem (
Descriptor, Descriptor,
&(UsbIf->IfSetting->Endpoints[Index]->Desc), &(UsbIf->IfSetting->Endpoints[Index]->Desc),
@ -813,6 +818,11 @@ UsbIoPortReset (
UsbIf = USB_INTERFACE_FROM_USBIO (This); UsbIf = USB_INTERFACE_FROM_USBIO (This);
Dev = UsbIf->Device; Dev = UsbIf->Device;
if (UsbIf->IsHub == TRUE) {
Status = EFI_INVALID_PARAMETER;
goto ON_EXIT;
}
HubIf = Dev->ParentIf; HubIf = Dev->ParentIf;
Status = HubIf->HubApi->ResetPort (HubIf, Dev->ParentPort); Status = HubIf->HubApi->ResetPort (HubIf, Dev->ParentPort);
@ -875,7 +885,6 @@ EFI_USB_IO_PROTOCOL mUsbIoProtocol = {
UsbIoPortReset UsbIoPortReset
}; };
//@MT: EFI_DRIVER_ENTRY_POINT (UsbBusDriverEntryPoint)
EFI_STATUS EFI_STATUS
EFIAPI EFIAPI

View File

@ -26,6 +26,34 @@ Revision History
#include "UsbMassImpl.h" #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 Read an UINT32 from the buffer to avoid byte alignment problems, then
convert that to the little endia. The USB mass storage bootability spec 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) { if (EFI_ERROR (Status) || CmdResult != USB_MASS_CMD_SUCCESS) {
DEBUG ((mUsbMscError, "UsbBootRequestSense: (%r) CmdResult=0x%x\n", Status, CmdResult)); 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)) { switch (USB_BOOT_SENSE_KEY (SenseData.SenseKey)) {
case USB_BOOT_SENSE_NO_SENSE: case USB_BOOT_SENSE_NO_SENSE:
Status = EFI_NO_RESPONSE;
break;
case USB_BOOT_SENSE_RECOVERED: case USB_BOOT_SENSE_RECOVERED:
// //
// Suppose hardware can handle this case, and recover later by itself // Suppose hardware can handle this case, and recover later by itself
@ -159,26 +190,12 @@ UsbBootRequestSense (
break; break;
case USB_BOOT_SENSE_NOT_READY: case USB_BOOT_SENSE_NOT_READY:
switch (SenseData.ASC) { Status = EFI_DEVICE_ERROR;
case USB_BOOT_ASC_NO_MEDIA: if (SenseData.ASC == USB_BOOT_ASC_NO_MEDIA) {
Status = EFI_NO_MEDIA; Media->MediaPresent = FALSE;
Media->MediaPresent = FALSE; Status = EFI_NO_MEDIA;
break; } else if (SenseData.ASC == USB_BOOT_ASC_NOT_READY) {
Status = EFI_NOT_READY;
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;
}
} }
break; break;
@ -189,14 +206,18 @@ UsbBootRequestSense (
case USB_BOOT_SENSE_UNIT_ATTENTION: case USB_BOOT_SENSE_UNIT_ATTENTION:
Status = EFI_DEVICE_ERROR; Status = EFI_DEVICE_ERROR;
if (SenseData.ASC == USB_BOOT_ASC_MEDIA_CHANGE) { 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; break;
case USB_BOOT_SNESE_DATA_PROTECT: case USB_BOOT_SNESE_DATA_PROTECT:
Status = EFI_WRITE_PROTECTED; Status = EFI_WRITE_PROTECTED;
UsbMass->BlockIoMedia.ReadOnly = TRUE; Media->ReadOnly = TRUE;
break; break;
default: default:
@ -270,6 +291,9 @@ UsbBootExecCmd (
return EFI_SUCCESS; return EFI_SUCCESS;
} }
DEBUG ((mUsbMscInfo, "UsbBootExecCmd: Fail to Exec 0x%x Cmd /w %r\n",
*(UINT8 *)Cmd ,Status));
return UsbBootRequestSense (UsbMass); return UsbBootRequestSense (UsbMass);
} }
@ -417,7 +441,7 @@ UsbBootInquiry (
EfiUsbDataIn, EfiUsbDataIn,
&InquiryData, &InquiryData,
sizeof (USB_BOOT_INQUIRY_DATA), sizeof (USB_BOOT_INQUIRY_DATA),
USB_BOOT_INQUIRY_CMD_TIMEOUT USB_BOOT_GENERAL_CMD_TIMEOUT
); );
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
return Status; return Status;
@ -485,8 +509,12 @@ UsbBootReadCapacity (
Media->LastBlock = UsbBootGetUint32 (CapacityData.LastLba); Media->LastBlock = UsbBootGetUint32 (CapacityData.LastLba);
Media->BlockSize = UsbBootGetUint32 (CapacityData.BlockLen); Media->BlockSize = UsbBootGetUint32 (CapacityData.BlockLen);
DEBUG ((mUsbMscInfo, "UsbBootReadCapacity Success LBA=%d BlockSize=%d\n", if (Media->BlockSize == 0) {
Media->LastBlock, Media->BlockSize)); return EFI_NOT_READY;
}
DEBUG ((mUsbMscInfo, "UsbBootReadCapacity Success LBA=%ld BlockSize=%d\n",
Media->LastBlock, Media->BlockSize));
return EFI_SUCCESS; return EFI_SUCCESS;
} }
@ -503,47 +531,49 @@ UsbBootReadCapacity (
**/ **/
EFI_STATUS EFI_STATUS
UsbBootModeSense ( UsbScsiModeSense (
IN USB_MASS_DEVICE *UsbMass IN USB_MASS_DEVICE *UsbMass
) )
{ {
EFI_STATUS Status; EFI_STATUS Status;
USB_BOOT_MODE_SENSE_CMD ModeSenseCmd; USB_SCSI_MODE_SENSE6_CMD ModeSenseCmd;
USB_BOOT_MODE_PARA_HEADER ModeParaHeader; USB_SCSI_MODE_SENSE6_PARA_HEADER ModeParaHeader;
UINT8 CommandSet; EFI_BLOCK_IO_MEDIA *Media;
ZeroMem (&ModeSenseCmd, sizeof (USB_BOOT_MODE_SENSE_CMD)); CopyMem (
ZeroMem (&ModeParaHeader, sizeof (USB_BOOT_MODE_PARA_HEADER)); &Media,
&(UsbMass->BlockIoMedia),
sizeof (EFI_BLOCK_IO_MEDIA)
);
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; ModeSenseCmd.OpCode = USB_SCSI_MODE_SENSE6_OPCODE;
ModeSenseCmd.Lun = USB_BOOT_LUN (UsbMass->Lun);
if (CommandSet == USB_MASS_STORE_SCSI) { ModeSenseCmd.PageCode = 0x3F;
// ModeSenseCmd.AllocateLen = (UINT8) sizeof (USB_SCSI_MODE_SENSE6_PARA_HEADER);
// 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);
Status = UsbBootExecCmdWithRetry ( Status = UsbBootExecCmdWithRetry (
UsbMass, UsbMass,
&ModeSenseCmd, &ModeSenseCmd,
sizeof (USB_BOOT_MODE_SENSE_CMD), sizeof (USB_SCSI_MODE_SENSE6_CMD),
EfiUsbDataIn, EfiUsbDataIn,
&ModeParaHeader, &ModeParaHeader,
sizeof (USB_BOOT_MODE_PARA_HEADER), sizeof (USB_SCSI_MODE_SENSE6_PARA_HEADER),
USB_BOOT_GENERAL_CMD_TIMEOUT USB_BOOT_GENERAL_CMD_TIMEOUT
); );
// //
// Did nothing with the Header here // ModeSense(6) is used to get the information of WriteProtected. While only some of
// But probably should // devices support this command, so have a try here.
// //
if (!EFI_ERROR (Status)) {
Media->ReadOnly = (ModeParaHeader.DevicePara & 0x80) ? TRUE : FALSE;
}
return Status; return Status;
} }
@ -570,6 +600,15 @@ UsbBootGetParams (
{ {
EFI_BLOCK_IO_MEDIA *Media; EFI_BLOCK_IO_MEDIA *Media;
EFI_STATUS Status; 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); Status = UsbBootInquiry (UsbMass);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
@ -577,29 +616,30 @@ UsbBootGetParams (
return Status; return Status;
} }
Media = &(UsbMass->BlockIoMedia);
// //
// Don't use the Removable bit in inquirydata to test whether the media // Don't use the Removable bit in inquirydata to test whether the media
// is removable because many flash disks wrongly set this bit. // is removable because many flash disks wrongly set this bit.
// //
if ((UsbMass->Pdt == USB_PDT_CDROM) || (UsbMass->Pdt == USB_PDT_OPTICAL)) { 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; UsbMass->OpticalStorage = TRUE;
// //
// Default value 2048 Bytes, in case no media present at first time // Default value 2048 Bytes, in case no media present at first time
// //
Media->BlockSize = 0x0800; 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); UsbScsiModeSense (UsbMass);
if (EFI_ERROR (Status)) {
DEBUG ((mUsbMscError, "UsbBootGetParams: UsbBootModeSense (%r)\n", Status));
return Status;
}
} }
return UsbBootReadCapacity (UsbMass); return UsbBootReadCapacity (UsbMass);
@ -623,6 +663,8 @@ UsbBootDetectMedia (
{ {
EFI_BLOCK_IO_MEDIA OldMedia; EFI_BLOCK_IO_MEDIA OldMedia;
EFI_BLOCK_IO_MEDIA *Media; EFI_BLOCK_IO_MEDIA *Media;
UINT8 CmdSet;
EFI_TPL OldTpl;
EFI_STATUS Status; EFI_STATUS Status;
Media = &UsbMass->BlockIoMedia; Media = &UsbMass->BlockIoMedia;
@ -633,54 +675,80 @@ UsbBootDetectMedia (
sizeof (EFI_BLOCK_IO_MEDIA) sizeof (EFI_BLOCK_IO_MEDIA)
); );
// CmdSet = ((EFI_USB_INTERFACE_DESCRIPTOR *) (UsbMass->Context))->InterfaceSubClass;
// First test whether the device is ready and get status
// If media changed or ready, need read the device's capacity
//
Status = UsbBootIsUnitReady (UsbMass); 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)) { if (EFI_ERROR (Status)) {
return 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)) {
DEBUG ((mUsbMscError, "UsbBootDetectMedia: UsbBootReadCapacity (%r)\n", Status));
goto ON_ERROR;
}
return EFI_SUCCESS;
ON_ERROR:
// //
// Detect whether it is necessary to reinstall the BlockIO // 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) || if ((Media->MediaId != OldMedia.MediaId) ||
(Media->MediaPresent != OldMedia.MediaPresent) || (Media->MediaPresent != OldMedia.MediaPresent) ||
(Media->ReadOnly != OldMedia.ReadOnly) || (Media->ReadOnly != OldMedia.ReadOnly) ||
(Media->BlockSize != OldMedia.BlockSize) || (Media->BlockSize != OldMedia.BlockSize) ||
(Media->LastBlock != OldMedia.LastBlock)) { (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 ( gBS->ReinstallProtocolInterface (
UsbMass->Controller, UsbMass->Controller,
&gEfiBlockIoProtocolGuid, &gEfiBlockIoProtocolGuid,
&UsbMass->BlockIo, &UsbMass->BlockIo,
&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) { if (Media->MediaPresent != OldMedia.MediaPresent) {
Status = EFI_NO_MEDIA; if (Media->MediaPresent == TRUE) {
Media->MediaId = 1;
} else {
Media->MediaId = 0;
}
} }
if (Media->MediaId != OldMedia.MediaId) {
Status = EFI_MEDIA_CHANGED; if ((Media->ReadOnly != OldMedia.ReadOnly) ||
} (Media->BlockSize != OldMedia.BlockSize) ||
if (Media->ReadOnly != OldMedia.ReadOnly) { (Media->LastBlock != OldMedia.LastBlock)) {
Status = EFI_WRITE_PROTECTED; Media->MediaId++;
} }
} }
@ -728,13 +796,9 @@ UsbBootReadBlocks (
ByteSize = (UINT32)Count * BlockSize; 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) USB_BOOT_GENERAL_CMD_TIMEOUT;
Timeout = (UINT32)Count * USB_BOOT_OPTICAL_BLOCK_TIMEOUT;
} else {
Timeout = (UINT32)Count * USB_BOOT_GENERAL_BLOCK_TIMEOUT;
}
// //
// Fill in the command then execute // Fill in the command then execute
@ -808,13 +872,9 @@ UsbBootWriteBlocks (
ByteSize = (UINT32)Count * BlockSize; 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) USB_BOOT_GENERAL_CMD_TIMEOUT;
Timeout = (UINT32)Count * USB_BOOT_OPTICAL_BLOCK_TIMEOUT;
} else {
Timeout = (UINT32)Count * USB_BOOT_GENERAL_BLOCK_TIMEOUT;
}
// //
// Fill in the write10 command block // Fill in the write10 command block

View File

@ -39,12 +39,14 @@ enum {
USB_BOOT_INQUIRY_OPCODE = 0x12, USB_BOOT_INQUIRY_OPCODE = 0x12,
USB_BOOT_REQUEST_SENSE_OPCODE = 0x03, 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_READ_CAPACITY_OPCODE = 0x25,
USB_BOOT_TEST_UNIT_READY_OPCODE = 0x00, USB_BOOT_TEST_UNIT_READY_OPCODE = 0x00,
USB_BOOT_READ10_OPCODE = 0x28, 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: // The Sense Key part of the sense data. Sense data has three levels:
// Sense key, Additional Sense Code and Additional Sense Code Qualifier // 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_SENSE_MISCOMPARE = 0x0E, // Source data mis-match while verfying.
USB_BOOT_ASC_NOT_READY = 0x04, USB_BOOT_ASC_NOT_READY = 0x04,
USB_BOOT_ASC_MEDIA_UPSIDE_DOWN = 0x06,
USB_BOOT_ASC_NO_MEDIA = 0x3A, USB_BOOT_ASC_NO_MEDIA = 0x3A,
USB_BOOT_ASC_MEDIA_CHANGE = 0x28, USB_BOOT_ASC_MEDIA_CHANGE = 0x28,
USB_BOOT_ASCQ_IN_PROGRESS = 0x01,
USB_BOOT_ASCQ_DEVICE_BUSY = 0xFF,
// //
// Other parameters // Other parameters
// //
@ -90,11 +88,13 @@ enum {
// //
// Boot Transfer timeout // Boot Transfer timeout
// //
USB_BOOT_GENERAL_BLOCK_TIMEOUT = 200 * USB_MASS_STALL_1_MS, // USB2.0 Spec define the up-limit timeout 5s for all command. USB floppy,
USB_BOOT_OPTICAL_BLOCK_TIMEOUT = 1 * USB_MASS_STALL_1_S, // USB CD-Rom and iPod devices are much slower than USB key when reponse
USB_BOOT_GENERAL_CMD_TIMEOUT = 1 * USB_MASS_STALL_1_S, // most of commands, So we set 5s as timeout here.
USB_BOOT_INQUIRY_CMD_TIMEOUT = 3 * USB_MASS_STALL_1_S, //
//
USB_BOOT_GENERAL_CMD_TIMEOUT = 5 * USB_MASS_STALL_1_S,
// //
// Supported PDT codes, or Peripheral Device Type // Supported PDT codes, or Peripheral Device Type
// //
@ -159,7 +159,7 @@ typedef struct {
UINT8 ParaListLenLsb; UINT8 ParaListLenLsb;
UINT8 Reserved1; UINT8 Reserved1;
UINT8 Pad[2]; UINT8 Pad[2];
} USB_BOOT_MODE_SENSE_CMD; } USB_BOOT_MODE_SENSE10_CMD;
typedef struct { typedef struct {
UINT8 ModeDataLenMsb; UINT8 ModeDataLenMsb;
@ -167,7 +167,7 @@ typedef struct {
UINT8 Reserved0[4]; UINT8 Reserved0[4];
UINT8 BlkDesLenMsb; UINT8 BlkDesLenMsb;
UINT8 BlkDesLenLsb; UINT8 BlkDesLenLsb;
} USB_BOOT_MODE_PARA_HEADER; } USB_BOOT_MODE_SENSE10_PARA_HEADER;
typedef struct { typedef struct {
UINT8 OpCode; UINT8 OpCode;
@ -209,6 +209,22 @@ typedef struct {
UINT8 ASCQ; // Additional Sense Code Qualifier UINT8 ASCQ; // Additional Sense Code Qualifier
UINT8 Reserverd2[4]; UINT8 Reserverd2[4];
} USB_BOOT_REQUEST_SENSE_DATA; } 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() #pragma pack()
// //