From 50fa1b3a86faee57ca597e778c9db4ed4233f83e Mon Sep 17 00:00:00 2001 From: vanjeff Date: Tue, 24 Jul 2007 09:54:50 +0000 Subject: [PATCH] Sync USB modules with main trunk. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3423 6f19259b-4bc3-4df7-8a09-765794883524 --- MdeModulePkg/Bus/Pci/EhciDxe/EhciDebug.h | 4 + MdeModulePkg/Bus/Pci/EhciDxe/EhciSched.c | 71 +++++ MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c | 83 ++++-- MdeModulePkg/Bus/Usb/UsbBusDxe/usbbus.c | 13 +- .../Bus/Usb/UsbMassStorageDxe/UsbMassBoot.c | 256 +++++++++++------- .../Bus/Usb/UsbMassStorageDxe/UsbMassBoot.h | 42 ++- 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; @@ -890,6 +952,15 @@ EhcMoniteAsyncRequests ( 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. // If failed to allocate the buffer, update the URB for next 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() // -- 2.39.2