mirror of https://github.com/acidanthera/audk.git
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:
parent
d19862fe4f
commit
50fa1b3a86
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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()
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
Loading…
Reference in New Issue