X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=MdeModulePkg%2FBus%2FPci%2FXhciDxe%2FXhciSched.c;h=4b7462704a812ee2868123a8100ed63df7a64c22;hb=8147fe090fb566f9a1ed8fde24098bbe425026be;hp=58a2f984a9450a127e065f95fa8ec35580ef15c7;hpb=3719c2aa879bcbcf3f0ab1f710e81fe2dbc19d9a;p=mirror_edk2.git diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c b/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c index 58a2f984a9..4b7462704a 100644 --- a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c +++ b/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c @@ -2,14 +2,10 @@ XHCI transfer scheduling routines. -Copyright (c) 2011 - 2017, Intel Corporation. All rights reserved.
-This program and the accompanying materials -are licensed and made available under the terms and conditions of the BSD License -which accompanies this distribution. The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +Copyright (c) 2011 - 2020, Intel Corporation. All rights reserved.
+Copyright (c) Microsoft Corporation.
+Copyright (C) 2022 Advanced Micro Devices, Inc. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -24,25 +20,25 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. @return Created URB or NULL. **/ -URB* +URB * XhcCreateCmdTrb ( IN USB_XHCI_INSTANCE *Xhc, IN TRB_TEMPLATE *CmdTrb ) { - URB *Urb; + URB *Urb; Urb = AllocateZeroPool (sizeof (URB)); if (Urb == NULL) { return NULL; } - Urb->Signature = XHC_URB_SIG; + Urb->Signature = XHC_URB_SIG; - Urb->Ring = &Xhc->CmdRing; + Urb->Ring = &Xhc->CmdRing; XhcSyncTrsRing (Xhc, Urb->Ring); - Urb->TrbNum = 1; - Urb->TrbStart = Urb->Ring->RingEnqueue; + Urb->TrbNum = 1; + Urb->TrbStart = Urb->Ring->RingEnqueue; CopyMem (Urb->TrbStart, CmdTrb, sizeof (TRB_TEMPLATE)); Urb->TrbStart->CycleBit = Urb->Ring->RingPCS & BIT0; Urb->TrbEnd = Urb->TrbStart; @@ -68,14 +64,14 @@ XhcCreateCmdTrb ( EFI_STATUS EFIAPI XhcCmdTransfer ( - IN USB_XHCI_INSTANCE *Xhc, - IN TRB_TEMPLATE *CmdTrb, - IN UINTN Timeout, - OUT TRB_TEMPLATE **EvtTrb + IN USB_XHCI_INSTANCE *Xhc, + IN TRB_TEMPLATE *CmdTrb, + IN UINTN Timeout, + OUT TRB_TEMPLATE **EvtTrb ) { - EFI_STATUS Status; - URB *Urb; + EFI_STATUS Status; + URB *Urb; // // Validate the parameters @@ -87,7 +83,7 @@ XhcCmdTransfer ( Status = EFI_DEVICE_ERROR; if (XhcIsHalt (Xhc) || XhcIsSysError (Xhc)) { - DEBUG ((EFI_D_ERROR, "XhcCmdTransfer: HC is halted\n")); + DEBUG ((DEBUG_ERROR, "XhcCmdTransfer: HC is halted\n")); goto ON_EXIT; } @@ -97,7 +93,7 @@ XhcCmdTransfer ( Urb = XhcCreateCmdTrb (Xhc, CmdTrb); if (Urb == NULL) { - DEBUG ((EFI_D_ERROR, "XhcCmdTransfer: failed to create URB\n")); + DEBUG ((DEBUG_ERROR, "XhcCmdTransfer: failed to create URB\n")); Status = EFI_OUT_OF_RESOURCES; goto ON_EXIT; } @@ -133,24 +129,24 @@ ON_EXIT: @return Created URB or NULL **/ -URB* +URB * XhcCreateUrb ( - IN USB_XHCI_INSTANCE *Xhc, - IN UINT8 BusAddr, - IN UINT8 EpAddr, - IN UINT8 DevSpeed, - IN UINTN MaxPacket, - IN UINTN Type, - IN EFI_USB_DEVICE_REQUEST *Request, - IN VOID *Data, - IN UINTN DataLen, - IN EFI_ASYNC_USB_TRANSFER_CALLBACK Callback, - IN VOID *Context + IN USB_XHCI_INSTANCE *Xhc, + IN UINT8 BusAddr, + IN UINT8 EpAddr, + IN UINT8 DevSpeed, + IN UINTN MaxPacket, + IN UINTN Type, + IN EFI_USB_DEVICE_REQUEST *Request, + IN VOID *Data, + IN UINTN DataLen, + IN EFI_ASYNC_USB_TRANSFER_CALLBACK Callback, + IN VOID *Context ) { - USB_ENDPOINT *Ep; - EFI_STATUS Status; - URB *Urb; + USB_ENDPOINT *Ep; + EFI_STATUS Status; + URB *Urb; Urb = AllocateZeroPool (sizeof (URB)); if (Urb == NULL) { @@ -177,7 +173,7 @@ XhcCreateUrb ( Status = XhcCreateTransferTrb (Xhc, Urb); ASSERT_EFI_ERROR (Status); if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "XhcCreateUrb: XhcCreateTransferTrb Failed, Status = %r\n", Status)); + DEBUG ((DEBUG_ERROR, "XhcCreateUrb: XhcCreateTransferTrb Failed, Status = %r\n", Status)); FreePool (Urb); Urb = NULL; } @@ -194,14 +190,14 @@ XhcCreateUrb ( **/ VOID XhcFreeUrb ( - IN USB_XHCI_INSTANCE *Xhc, - IN URB *Urb + IN USB_XHCI_INSTANCE *Xhc, + IN URB *Urb ) { if ((Xhc == NULL) || (Urb == NULL)) { return; } - + if (Urb->DataMap != NULL) { Xhc->PciIo->Unmap (Xhc->PciIo, Urb->DataMap); } @@ -220,23 +216,23 @@ XhcFreeUrb ( **/ EFI_STATUS XhcCreateTransferTrb ( - IN USB_XHCI_INSTANCE *Xhc, - IN URB *Urb + IN USB_XHCI_INSTANCE *Xhc, + IN URB *Urb ) { - VOID *OutputContext; - TRANSFER_RING *EPRing; - UINT8 EPType; - UINT8 SlotId; - UINT8 Dci; - TRB *TrbStart; - UINTN TotalLen; - UINTN Len; - UINTN TrbNum; - EFI_PCI_IO_PROTOCOL_OPERATION MapOp; - EFI_PHYSICAL_ADDRESS PhyAddr; - VOID *Map; - EFI_STATUS Status; + VOID *OutputContext; + TRANSFER_RING *EPRing; + UINT8 EPType; + UINT8 SlotId; + UINT8 Dci; + TRB *TrbStart; + UINTN TotalLen; + UINTN Len; + UINTN TrbNum; + EFI_PCI_IO_PROTOCOL_OPERATION MapOp; + EFI_PHYSICAL_ADDRESS PhyAddr; + VOID *Map; + EFI_STATUS Status; SlotId = XhcBusDevAddrToSlotId (Xhc, Urb->Ep.BusAddr); if (SlotId == 0) { @@ -249,34 +245,37 @@ XhcCreateTransferTrb ( Urb->Completed = 0; Urb->Result = EFI_USB_NOERROR; - Dci = XhcEndpointToDci (Urb->Ep.EpAddr, (UINT8)(Urb->Ep.Direction)); + Dci = XhcEndpointToDci (Urb->Ep.EpAddr, (UINT8)(Urb->Ep.Direction)); ASSERT (Dci < 32); - EPRing = (TRANSFER_RING *)(UINTN) Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1]; - Urb->Ring = EPRing; + EPRing = (TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1]; + Urb->Ring = EPRing; OutputContext = Xhc->UsbDevContext[SlotId].OutputContext; if (Xhc->HcCParams.Data.Csz == 0) { - EPType = (UINT8) ((DEVICE_CONTEXT *)OutputContext)->EP[Dci-1].EPType; + EPType = (UINT8)((DEVICE_CONTEXT *)OutputContext)->EP[Dci-1].EPType; } else { - EPType = (UINT8) ((DEVICE_CONTEXT_64 *)OutputContext)->EP[Dci-1].EPType; + EPType = (UINT8)((DEVICE_CONTEXT_64 *)OutputContext)->EP[Dci-1].EPType; } - - if (Urb->Data != NULL) { - if (((UINT8) (Urb->Ep.Direction)) == EfiUsbDataIn) { + + // + // No need to remap. + // + if ((Urb->Data != NULL) && (Urb->DataMap == NULL)) { + if (((UINT8)(Urb->Ep.Direction)) == EfiUsbDataIn) { MapOp = EfiPciIoOperationBusMasterWrite; } else { MapOp = EfiPciIoOperationBusMasterRead; } - - Len = Urb->DataLen; - Status = Xhc->PciIo->Map (Xhc->PciIo, MapOp, Urb->Data, &Len, &PhyAddr, &Map); - + + Len = Urb->DataLen; + Status = Xhc->PciIo->Map (Xhc->PciIo, MapOp, Urb->Data, &Len, &PhyAddr, &Map); + if (EFI_ERROR (Status) || (Len != Urb->DataLen)) { - DEBUG ((EFI_D_ERROR, "XhcCreateTransferTrb: Fail to map Urb->Data.\n")); + DEBUG ((DEBUG_ERROR, "XhcCreateTransferTrb: Fail to map Urb->Data.\n")); return EFI_OUT_OF_RESOURCES; } - - Urb->DataPhy = (VOID *) ((UINTN) PhyAddr); - Urb->DataMap = Map; + + Urb->DataPhy = (VOID *)((UINTN)PhyAddr); + Urb->DataMap = Map; } // @@ -289,7 +288,7 @@ XhcCreateTransferTrb ( // // For control transfer, create SETUP_STAGE_TRB first. // - TrbStart = (TRB *)(UINTN)EPRing->RingEnqueue; + TrbStart = (TRB *)(UINTN)EPRing->RingEnqueue; TrbStart->TrbCtrSetup.bmRequestType = Urb->Request->RequestType; TrbStart->TrbCtrSetup.bRequest = Urb->Request->Request; TrbStart->TrbCtrSetup.wValue = Urb->Request->Value; @@ -300,13 +299,19 @@ XhcCreateTransferTrb ( TrbStart->TrbCtrSetup.IOC = 1; TrbStart->TrbCtrSetup.IDT = 1; TrbStart->TrbCtrSetup.Type = TRB_TYPE_SETUP_STAGE; - if (Urb->Ep.Direction == EfiUsbDataIn) { - TrbStart->TrbCtrSetup.TRT = 3; - } else if (Urb->Ep.Direction == EfiUsbDataOut) { - TrbStart->TrbCtrSetup.TRT = 2; + if (Urb->DataLen > 0) { + if (Urb->Ep.Direction == EfiUsbDataIn) { + TrbStart->TrbCtrSetup.TRT = 3; + } else if (Urb->Ep.Direction == EfiUsbDataOut) { + TrbStart->TrbCtrSetup.TRT = 2; + } else { + DEBUG ((DEBUG_ERROR, "XhcCreateTransferTrb: Direction sholud be IN or OUT when Data exists!\n")); + ASSERT (FALSE); + } } else { TrbStart->TrbCtrSetup.TRT = 0; } + // // Update the cycle bit // @@ -318,10 +323,10 @@ XhcCreateTransferTrb ( // if (Urb->DataLen > 0) { XhcSyncTrsRing (Xhc, EPRing); - TrbStart = (TRB *)(UINTN)EPRing->RingEnqueue; - TrbStart->TrbCtrData.TRBPtrLo = XHC_LOW_32BIT(Urb->DataPhy); - TrbStart->TrbCtrData.TRBPtrHi = XHC_HIGH_32BIT(Urb->DataPhy); - TrbStart->TrbCtrData.Length = (UINT32) Urb->DataLen; + TrbStart = (TRB *)(UINTN)EPRing->RingEnqueue; + TrbStart->TrbCtrData.TRBPtrLo = XHC_LOW_32BIT (Urb->DataPhy); + TrbStart->TrbCtrData.TRBPtrHi = XHC_HIGH_32BIT (Urb->DataPhy); + TrbStart->TrbCtrData.Length = (UINT32)Urb->DataLen; TrbStart->TrbCtrData.TDSize = 0; TrbStart->TrbCtrData.IntTarget = 0; TrbStart->TrbCtrData.ISP = 1; @@ -336,18 +341,20 @@ XhcCreateTransferTrb ( } else { TrbStart->TrbCtrData.DIR = 0; } + // // Update the cycle bit // TrbStart->TrbCtrData.CycleBit = EPRing->RingPCS & BIT0; Urb->TrbNum++; } + // // For control transfer, create STATUS_STAGE_TRB. // Get the pointer to next TRB for status stage use // XhcSyncTrsRing (Xhc, EPRing); - TrbStart = (TRB *)(UINTN)EPRing->RingEnqueue; + TrbStart = (TRB *)(UINTN)EPRing->RingEnqueue; TrbStart->TrbCtrStatus.IntTarget = 0; TrbStart->TrbCtrStatus.IOC = 1; TrbStart->TrbCtrStatus.CH = 0; @@ -359,6 +366,7 @@ XhcCreateTransferTrb ( } else { TrbStart->TrbCtrStatus.DIR = 0; } + // // Update the cycle bit // @@ -384,10 +392,11 @@ XhcCreateTransferTrb ( } else { Len = 0x10000; } - TrbStart = (TRB *)(UINTN)EPRing->RingEnqueue; - TrbStart->TrbNormal.TRBPtrLo = XHC_LOW_32BIT((UINT8 *) Urb->DataPhy + TotalLen); - TrbStart->TrbNormal.TRBPtrHi = XHC_HIGH_32BIT((UINT8 *) Urb->DataPhy + TotalLen); - TrbStart->TrbNormal.Length = (UINT32) Len; + + TrbStart = (TRB *)(UINTN)EPRing->RingEnqueue; + TrbStart->TrbNormal.TRBPtrLo = XHC_LOW_32BIT ((UINT8 *)Urb->DataPhy + TotalLen); + TrbStart->TrbNormal.TRBPtrHi = XHC_HIGH_32BIT ((UINT8 *)Urb->DataPhy + TotalLen); + TrbStart->TrbNormal.Length = (UINT32)Len; TrbStart->TrbNormal.TDSize = 0; TrbStart->TrbNormal.IntTarget = 0; TrbStart->TrbNormal.ISP = 1; @@ -419,10 +428,11 @@ XhcCreateTransferTrb ( } else { Len = 0x10000; } - TrbStart = (TRB *)(UINTN)EPRing->RingEnqueue; - TrbStart->TrbNormal.TRBPtrLo = XHC_LOW_32BIT((UINT8 *) Urb->DataPhy + TotalLen); - TrbStart->TrbNormal.TRBPtrHi = XHC_HIGH_32BIT((UINT8 *) Urb->DataPhy + TotalLen); - TrbStart->TrbNormal.Length = (UINT32) Len; + + TrbStart = (TRB *)(UINTN)EPRing->RingEnqueue; + TrbStart->TrbNormal.TRBPtrLo = XHC_LOW_32BIT ((UINT8 *)Urb->DataPhy + TotalLen); + TrbStart->TrbNormal.TRBPtrHi = XHC_HIGH_32BIT ((UINT8 *)Urb->DataPhy + TotalLen); + TrbStart->TrbNormal.Length = (UINT32)Len; TrbStart->TrbNormal.TDSize = 0; TrbStart->TrbNormal.IntTarget = 0; TrbStart->TrbNormal.ISP = 1; @@ -443,7 +453,7 @@ XhcCreateTransferTrb ( break; default: - DEBUG ((EFI_D_INFO, "Not supported EPType 0x%x!\n",EPType)); + DEBUG ((DEBUG_INFO, "Not supported EPType 0x%x!\n", EPType)); ASSERT (FALSE); break; } @@ -451,7 +461,6 @@ XhcCreateTransferTrb ( return EFI_SUCCESS; } - /** Initialize the XHCI host controller for schedule. @@ -460,13 +469,13 @@ XhcCreateTransferTrb ( **/ VOID XhcInitSched ( - IN USB_XHCI_INSTANCE *Xhc + IN USB_XHCI_INSTANCE *Xhc ) { VOID *Dcbaa; EFI_PHYSICAL_ADDRESS DcbaaPhy; UINT64 CmdRing; - EFI_PHYSICAL_ADDRESS CmdRingPhy; + EFI_PHYSICAL_ADDRESS CmdRingPhy; UINTN Entries; UINT32 MaxScratchpadBufs; UINT64 *ScratchBuf; @@ -497,8 +506,8 @@ XhcInitSched ( // The Device Context Base Address Array shall contain MaxSlotsEn + 1 entries. // Software shall set Device Context Base Address Array entries for unallocated Device Slots to '0'. // - Entries = (Xhc->MaxSlotsEn + 1) * sizeof(UINT64); - Dcbaa = UsbHcAllocateMem (Xhc->MemPool, Entries); + Entries = (Xhc->MaxSlotsEn + 1) * sizeof (UINT64); + Dcbaa = UsbHcAllocateMem (Xhc->MemPool, Entries, FALSE); ASSERT (Dcbaa != NULL); ZeroMem (Dcbaa, Entries); @@ -517,7 +526,7 @@ XhcInitSched ( ScratchEntryMap = AllocateZeroPool (sizeof (UINTN) * MaxScratchpadBufs); ASSERT (ScratchEntryMap != NULL); Xhc->ScratchEntryMap = ScratchEntryMap; - + // // Allocate the buffer to record the host address for each entry // @@ -526,14 +535,14 @@ XhcInitSched ( Xhc->ScratchEntry = ScratchEntry; ScratchPhy = 0; - Status = UsbHcAllocateAlignedPages ( - Xhc->PciIo, - EFI_SIZE_TO_PAGES (MaxScratchpadBufs * sizeof (UINT64)), - Xhc->PageSize, - (VOID **) &ScratchBuf, - &ScratchPhy, - &Xhc->ScratchMap - ); + Status = UsbHcAllocateAlignedPages ( + Xhc->PciIo, + EFI_SIZE_TO_PAGES (MaxScratchpadBufs * sizeof (UINT64)), + Xhc->PageSize, + (VOID **)&ScratchBuf, + &ScratchPhy, + &Xhc->ScratchMap + ); ASSERT_EFI_ERROR (Status); ZeroMem (ScratchBuf, MaxScratchpadBufs * sizeof (UINT64)); @@ -544,14 +553,14 @@ XhcInitSched ( // for (Index = 0; Index < MaxScratchpadBufs; Index++) { ScratchEntryPhy = 0; - Status = UsbHcAllocateAlignedPages ( - Xhc->PciIo, - EFI_SIZE_TO_PAGES (Xhc->PageSize), - Xhc->PageSize, - (VOID **) &ScratchEntry[Index], - &ScratchEntryPhy, - (VOID **) &ScratchEntryMap[Index] - ); + Status = UsbHcAllocateAlignedPages ( + Xhc->PciIo, + EFI_SIZE_TO_PAGES (Xhc->PageSize), + Xhc->PageSize, + (VOID **)&ScratchEntry[Index], + &ScratchEntryPhy, + (VOID **)&ScratchEntryMap[Index] + ); ASSERT_EFI_ERROR (Status); ZeroMem ((VOID *)(UINTN)ScratchEntry[Index], Xhc->PageSize); // @@ -559,11 +568,12 @@ XhcInitSched ( // *ScratchBuf++ = ScratchEntryPhy; } + // // The Scratchpad Buffer Array contains pointers to the Scratchpad Buffers. Entry 0 of the // Device Context Base Address Array points to the Scratchpad Buffer Array. // - *(UINT64 *)Dcbaa = (UINT64)(UINTN) ScratchPhy; + *(UINT64 *)Dcbaa = (UINT64)(UINTN)ScratchPhy; } // @@ -576,10 +586,10 @@ XhcInitSched ( // So divide it to two 32-bytes width register access. // DcbaaPhy = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Dcbaa, Entries); - XhcWriteOpReg (Xhc, XHC_DCBAAP_OFFSET, XHC_LOW_32BIT(DcbaaPhy)); + XhcWriteOpReg (Xhc, XHC_DCBAAP_OFFSET, XHC_LOW_32BIT (DcbaaPhy)); XhcWriteOpReg (Xhc, XHC_DCBAAP_OFFSET + 4, XHC_HIGH_32BIT (DcbaaPhy)); - DEBUG ((EFI_D_INFO, "XhcInitSched:DCBAA=0x%x\n", (UINT64)(UINTN)Xhc->DCBAA)); + DEBUG ((DEBUG_INFO, "XhcInitSched:DCBAA=0x%x\n", (UINT64)(UINTN)Xhc->DCBAA)); // // Define the Command Ring Dequeue Pointer by programming the Command Ring Control Register @@ -593,19 +603,17 @@ XhcInitSched ( // Transfer Ring it checks for a Cycle bit transition. If a transition detected, the ring is empty. // So we set RCS as inverted PCS init value to let Command Ring empty // - CmdRing = (UINT64)(UINTN)Xhc->CmdRing.RingSeg0; - CmdRingPhy = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, (VOID *)(UINTN) CmdRing, sizeof (TRB_TEMPLATE) * CMD_RING_TRB_NUMBER); + CmdRing = (UINT64)(UINTN)Xhc->CmdRing.RingSeg0; + CmdRingPhy = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, (VOID *)(UINTN)CmdRing, sizeof (TRB_TEMPLATE) * CMD_RING_TRB_NUMBER); ASSERT ((CmdRingPhy & 0x3F) == 0); CmdRingPhy |= XHC_CRCR_RCS; // // Some 3rd party XHCI external cards don't support single 64-bytes width register access, // So divide it to two 32-bytes width register access. // - XhcWriteOpReg (Xhc, XHC_CRCR_OFFSET, XHC_LOW_32BIT(CmdRingPhy)); + XhcWriteOpReg (Xhc, XHC_CRCR_OFFSET, XHC_LOW_32BIT (CmdRingPhy)); XhcWriteOpReg (Xhc, XHC_CRCR_OFFSET + 4, XHC_HIGH_32BIT (CmdRingPhy)); - DEBUG ((EFI_D_INFO, "XhcInitSched:XHC_CRCR=0x%x\n", Xhc->CmdRing.RingSeg0)); - // // Disable the 'interrupter enable' bit in USB_CMD // and clear IE & IP bit in all Interrupter X Management Registers. @@ -620,7 +628,14 @@ XhcInitSched ( // Allocate EventRing for Cmd, Ctrl, Bulk, Interrupt, AsynInterrupt transfer // CreateEventRing (Xhc, &Xhc->EventRing); - DEBUG ((EFI_D_INFO, "XhcInitSched:XHC_EVENTRING=0x%x\n", Xhc->EventRing.EventRingSeg0)); + DEBUG (( + DEBUG_INFO, + "XhcInitSched: Created CMD ring [%p~%p) EVENT ring [%p~%p)\n", + Xhc->CmdRing.RingSeg0, + (UINTN)Xhc->CmdRing.RingSeg0 + sizeof (TRB_TEMPLATE) * CMD_RING_TRB_NUMBER, + Xhc->EventRing.EventRingSeg0, + (UINTN)Xhc->EventRing.EventRingSeg0 + sizeof (TRB_TEMPLATE) * EVENT_RING_TRB_NUMBER + )); } /** @@ -640,39 +655,40 @@ XhcInitSched ( EFI_STATUS EFIAPI XhcRecoverHaltedEndpoint ( - IN USB_XHCI_INSTANCE *Xhc, - IN URB *Urb + IN USB_XHCI_INSTANCE *Xhc, + IN URB *Urb ) { - EFI_STATUS Status; - UINT8 Dci; - UINT8 SlotId; + EFI_STATUS Status; + UINT8 Dci; + UINT8 SlotId; Status = EFI_SUCCESS; SlotId = XhcBusDevAddrToSlotId (Xhc, Urb->Ep.BusAddr); if (SlotId == 0) { return EFI_DEVICE_ERROR; } + Dci = XhcEndpointToDci (Urb->Ep.EpAddr, (UINT8)(Urb->Ep.Direction)); ASSERT (Dci < 32); - - DEBUG ((EFI_D_INFO, "Recovery Halted Slot = %x,Dci = %x\n", SlotId, Dci)); + + DEBUG ((DEBUG_INFO, "Recovery Halted Slot = %x,Dci = %x\n", SlotId, Dci)); // // 1) Send Reset endpoint command to transit from halt to stop state // - Status = XhcResetEndpoint(Xhc, SlotId, Dci); - if (EFI_ERROR(Status)) { - DEBUG ((EFI_D_ERROR, "XhcRecoverHaltedEndpoint: Reset Endpoint Failed, Status = %r\n", Status)); + Status = XhcResetEndpoint (Xhc, SlotId, Dci); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "XhcRecoverHaltedEndpoint: Reset Endpoint Failed, Status = %r\n", Status)); goto Done; } // // 2)Set dequeue pointer // - Status = XhcSetTrDequeuePointer(Xhc, SlotId, Dci, Urb); - if (EFI_ERROR(Status)) { - DEBUG ((EFI_D_ERROR, "XhcRecoverHaltedEndpoint: Set Transfer Ring Dequeue Pointer Failed, Status = %r\n", Status)); + Status = XhcSetTrDequeuePointer (Xhc, SlotId, Dci, Urb); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "XhcRecoverHaltedEndpoint: Set Transfer Ring Dequeue Pointer Failed, Status = %r\n", Status)); goto Done; } @@ -695,46 +711,58 @@ Done: @param Urb The urb which doesn't get completed in a specified timeout range. @retval EFI_SUCCESS The dequeuing of the TDs is successful. + @retval EFI_ALREADY_STARTED The Urb is finished so no deque is needed. @retval Others Failed to stop the endpoint and dequeue the TDs. **/ EFI_STATUS EFIAPI XhcDequeueTrbFromEndpoint ( - IN USB_XHCI_INSTANCE *Xhc, - IN URB *Urb + IN USB_XHCI_INSTANCE *Xhc, + IN URB *Urb ) { - EFI_STATUS Status; - UINT8 Dci; - UINT8 SlotId; + EFI_STATUS Status; + UINT8 Dci; + UINT8 SlotId; Status = EFI_SUCCESS; SlotId = XhcBusDevAddrToSlotId (Xhc, Urb->Ep.BusAddr); if (SlotId == 0) { return EFI_DEVICE_ERROR; } + Dci = XhcEndpointToDci (Urb->Ep.EpAddr, (UINT8)(Urb->Ep.Direction)); ASSERT (Dci < 32); - - DEBUG ((EFI_D_INFO, "Stop Slot = %x,Dci = %x\n", SlotId, Dci)); + + DEBUG ((DEBUG_VERBOSE, "Stop Slot = %x,Dci = %x\n", SlotId, Dci)); // // 1) Send Stop endpoint command to stop xHC from executing of the TDs on the endpoint // - Status = XhcStopEndpoint(Xhc, SlotId, Dci); - if (EFI_ERROR(Status)) { - DEBUG ((EFI_D_ERROR, "XhcDequeueTrbFromEndpoint: Stop Endpoint Failed, Status = %r\n", Status)); + Status = XhcStopEndpoint (Xhc, SlotId, Dci, Urb); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "XhcDequeueTrbFromEndpoint: Stop Endpoint Failed, Status = %r\n", Status)); goto Done; } // // 2)Set dequeue pointer // - Status = XhcSetTrDequeuePointer(Xhc, SlotId, Dci, Urb); - if (EFI_ERROR(Status)) { - DEBUG ((EFI_D_ERROR, "XhcDequeueTrbFromEndpoint: Set Transfer Ring Dequeue Pointer Failed, Status = %r\n", Status)); - goto Done; + if (Urb->Finished && (Urb->Result == EFI_USB_NOERROR)) { + // + // Return Already Started to indicate the pending URB is finished. + // This fixes BULK data loss when transfer is detected as timeout + // but finished just before stopping endpoint. + // + Status = EFI_ALREADY_STARTED; + DEBUG ((DEBUG_INFO, "XhcDequeueTrbFromEndpoint: Pending URB is finished: Length Actual/Expect = %d/%d!\n", Urb->Completed, Urb->DataLen)); + } else { + Status = XhcSetTrDequeuePointer (Xhc, SlotId, Dci, Urb); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "XhcDequeueTrbFromEndpoint: Set Transfer Ring Dequeue Pointer Failed, Status = %r\n", Status)); + goto Done; + } } // @@ -755,8 +783,8 @@ Done: **/ VOID CreateEventRing ( - IN USB_XHCI_INSTANCE *Xhc, - OUT EVENT_RING *EventRing + IN USB_XHCI_INSTANCE *Xhc, + OUT EVENT_RING *EventRing ) { VOID *Buf; @@ -768,18 +796,18 @@ CreateEventRing ( ASSERT (EventRing != NULL); Size = sizeof (TRB_TEMPLATE) * EVENT_RING_TRB_NUMBER; - Buf = UsbHcAllocateMem (Xhc->MemPool, Size); + Buf = UsbHcAllocateMem (Xhc->MemPool, Size, TRUE); ASSERT (Buf != NULL); - ASSERT (((UINTN) Buf & 0x3F) == 0); + ASSERT (((UINTN)Buf & 0x3F) == 0); ZeroMem (Buf, Size); EventRing->EventRingSeg0 = Buf; EventRing->TrbNumber = EVENT_RING_TRB_NUMBER; - EventRing->EventRingDequeue = (TRB_TEMPLATE *) EventRing->EventRingSeg0; - EventRing->EventRingEnqueue = (TRB_TEMPLATE *) EventRing->EventRingSeg0; - + EventRing->EventRingDequeue = (TRB_TEMPLATE *)EventRing->EventRingSeg0; + EventRing->EventRingEnqueue = (TRB_TEMPLATE *)EventRing->EventRingSeg0; + DequeuePhy = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Buf, Size); - + // // Software maintains an Event Ring Consumer Cycle State (CCS) bit, initializing it to '1' // and toggling it every time the Event Ring Dequeue Pointer wraps back to the beginning of the Event Ring. @@ -787,12 +815,12 @@ CreateEventRing ( EventRing->EventRingCCS = 1; Size = sizeof (EVENT_RING_SEG_TABLE_ENTRY) * ERST_NUMBER; - Buf = UsbHcAllocateMem (Xhc->MemPool, Size); + Buf = UsbHcAllocateMem (Xhc->MemPool, Size, FALSE); ASSERT (Buf != NULL); - ASSERT (((UINTN) Buf & 0x3F) == 0); + ASSERT (((UINTN)Buf & 0x3F) == 0); ZeroMem (Buf, Size); - ERSTBase = (EVENT_RING_SEG_TABLE_ENTRY *) Buf; + ERSTBase = (EVENT_RING_SEG_TABLE_ENTRY *)Buf; EventRing->ERSTBase = ERSTBase; ERSTBase->PtrLo = XHC_LOW_32BIT (DequeuePhy); ERSTBase->PtrHi = XHC_HIGH_32BIT (DequeuePhy); @@ -817,12 +845,12 @@ CreateEventRing ( XhcWriteRuntimeReg ( Xhc, XHC_ERDP_OFFSET, - XHC_LOW_32BIT((UINT64)(UINTN)DequeuePhy) + XHC_LOW_32BIT ((UINT64)(UINTN)DequeuePhy) ); XhcWriteRuntimeReg ( Xhc, XHC_ERDP_OFFSET + 4, - XHC_HIGH_32BIT((UINT64)(UINTN)DequeuePhy) + XHC_HIGH_32BIT ((UINT64)(UINTN)DequeuePhy) ); // // Program the Interrupter Event Ring Segment Table Base Address (ERSTBA) register(5.5.2.3.2) @@ -833,12 +861,12 @@ CreateEventRing ( XhcWriteRuntimeReg ( Xhc, XHC_ERSTBA_OFFSET, - XHC_LOW_32BIT((UINT64)(UINTN)ERSTPhy) + XHC_LOW_32BIT ((UINT64)(UINTN)ERSTPhy) ); XhcWriteRuntimeReg ( Xhc, XHC_ERSTBA_OFFSET + 4, - XHC_HIGH_32BIT((UINT64)(UINTN)ERSTPhy) + XHC_HIGH_32BIT ((UINT64)(UINTN)ERSTPhy) ); // // Need set IMAN IE bit to enble the ring interrupt @@ -856,39 +884,39 @@ CreateEventRing ( **/ VOID CreateTransferRing ( - IN USB_XHCI_INSTANCE *Xhc, - IN UINTN TrbNum, - OUT TRANSFER_RING *TransferRing + IN USB_XHCI_INSTANCE *Xhc, + IN UINTN TrbNum, + OUT TRANSFER_RING *TransferRing ) { VOID *Buf; LINK_TRB *EndTrb; EFI_PHYSICAL_ADDRESS PhyAddr; - Buf = UsbHcAllocateMem (Xhc->MemPool, sizeof (TRB_TEMPLATE) * TrbNum); + Buf = UsbHcAllocateMem (Xhc->MemPool, sizeof (TRB_TEMPLATE) * TrbNum, TRUE); ASSERT (Buf != NULL); - ASSERT (((UINTN) Buf & 0x3F) == 0); + ASSERT (((UINTN)Buf & 0x3F) == 0); ZeroMem (Buf, sizeof (TRB_TEMPLATE) * TrbNum); - TransferRing->RingSeg0 = Buf; - TransferRing->TrbNumber = TrbNum; - TransferRing->RingEnqueue = (TRB_TEMPLATE *) TransferRing->RingSeg0; - TransferRing->RingDequeue = (TRB_TEMPLATE *) TransferRing->RingSeg0; - TransferRing->RingPCS = 1; + TransferRing->RingSeg0 = Buf; + TransferRing->TrbNumber = TrbNum; + TransferRing->RingEnqueue = (TRB_TEMPLATE *)TransferRing->RingSeg0; + TransferRing->RingDequeue = (TRB_TEMPLATE *)TransferRing->RingSeg0; + TransferRing->RingPCS = 1; // // 4.9.2 Transfer Ring Management // To form a ring (or circular queue) a Link TRB may be inserted at the end of a ring to // point to the first TRB in the ring. // - EndTrb = (LINK_TRB *) ((UINTN)Buf + sizeof (TRB_TEMPLATE) * (TrbNum - 1)); + EndTrb = (LINK_TRB *)((UINTN)Buf + sizeof (TRB_TEMPLATE) * (TrbNum - 1)); EndTrb->Type = TRB_TYPE_LINK; - PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Buf, sizeof (TRB_TEMPLATE) * TrbNum); + PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Buf, sizeof (TRB_TEMPLATE) * TrbNum); EndTrb->PtrLo = XHC_LOW_32BIT (PhyAddr); EndTrb->PtrHi = XHC_HIGH_32BIT (PhyAddr); // // Toggle Cycle (TC). When set to '1', the xHC shall toggle its interpretation of the Cycle bit. // - EndTrb->TC = 1; + EndTrb->TC = 1; // // Set Cycle bit as other TRB PCS init value // @@ -905,11 +933,11 @@ CreateTransferRing ( EFI_STATUS EFIAPI XhcFreeEventRing ( - IN USB_XHCI_INSTANCE *Xhc, - IN EVENT_RING *EventRing -) + IN USB_XHCI_INSTANCE *Xhc, + IN EVENT_RING *EventRing + ) { - if(EventRing->EventRingSeg0 == NULL) { + if (EventRing->EventRingSeg0 == NULL) { return EFI_SUCCESS; } @@ -933,20 +961,21 @@ XhcFreeEventRing ( **/ VOID XhcFreeSched ( - IN USB_XHCI_INSTANCE *Xhc + IN USB_XHCI_INSTANCE *Xhc ) { - UINT32 Index; - UINT64 *ScratchEntry; - + UINT32 Index; + UINT64 *ScratchEntry; + if (Xhc->ScratchBuf != NULL) { ScratchEntry = Xhc->ScratchEntry; for (Index = 0; Index < Xhc->MaxScratchpadBufs; Index++) { // // Free Scratchpad Buffers // - UsbHcFreeAlignedPages (Xhc->PciIo, (VOID*)(UINTN)ScratchEntry[Index], EFI_SIZE_TO_PAGES (Xhc->PageSize), (VOID *) Xhc->ScratchEntryMap[Index]); + UsbHcFreeAlignedPages (Xhc->PciIo, (VOID *)(UINTN)ScratchEntry[Index], EFI_SIZE_TO_PAGES (Xhc->PageSize), (VOID *)Xhc->ScratchEntryMap[Index]); } + // // Free Scratchpad Buffer Array // @@ -959,14 +988,14 @@ XhcFreeSched ( UsbHcFreeMem (Xhc->MemPool, Xhc->CmdRing.RingSeg0, sizeof (TRB_TEMPLATE) * CMD_RING_TRB_NUMBER); Xhc->CmdRing.RingSeg0 = NULL; } - - XhcFreeEventRing (Xhc,&Xhc->EventRing); + + XhcFreeEventRing (Xhc, &Xhc->EventRing); if (Xhc->DCBAA != NULL) { - UsbHcFreeMem (Xhc->MemPool, Xhc->DCBAA, (Xhc->MaxSlotsEn + 1) * sizeof(UINT64)); + UsbHcFreeMem (Xhc->MemPool, Xhc->DCBAA, (Xhc->MaxSlotsEn + 1) * sizeof (UINT64)); Xhc->DCBAA = NULL; } - + // // Free memory pool at last // @@ -977,45 +1006,44 @@ XhcFreeSched ( } /** - Check if the Trb is a transaction of the URBs in XHCI's asynchronous transfer list. + Check if the Trb is a transaction of the URB. @param Xhc The XHCI Instance. - @param Trb The TRB to be checked. - @param Urb The pointer to the matched Urb. + @param Trb The TRB to be checked + @param Urb The URB to be checked. - @retval TRUE The Trb is matched with a transaction of the URBs in the async list. - @retval FALSE The Trb is not matched with any URBs in the async list. + @retval TRUE It is a transaction of the URB. + @retval FALSE It is not any transaction of the URB. **/ BOOLEAN -IsAsyncIntTrb ( - IN USB_XHCI_INSTANCE *Xhc, - IN TRB_TEMPLATE *Trb, - OUT URB **Urb +IsTransferRingTrb ( + IN USB_XHCI_INSTANCE *Xhc, + IN TRB_TEMPLATE *Trb, + IN URB *Urb ) { - LIST_ENTRY *Entry; - LIST_ENTRY *Next; - TRB_TEMPLATE *CheckedTrb; - URB *CheckedUrb; - UINTN Index; + LINK_TRB *LinkTrb; + TRB_TEMPLATE *CheckedTrb; + UINTN Index; + EFI_PHYSICAL_ADDRESS PhyAddr; - EFI_LIST_FOR_EACH_SAFE (Entry, Next, &Xhc->AsyncIntTransfers) { - CheckedUrb = EFI_LIST_CONTAINER (Entry, URB, UrbList); - CheckedTrb = CheckedUrb->TrbStart; - for (Index = 0; Index < CheckedUrb->TrbNum; Index++) { - if (Trb == CheckedTrb) { - *Urb = CheckedUrb; - return TRUE; - } - CheckedTrb++; - // - // If the checked TRB is the link TRB at the end of the transfer ring, - // recircle it to the head of the ring. - // - if (CheckedTrb->Type == TRB_TYPE_LINK) { - CheckedTrb = (TRB_TEMPLATE*) CheckedUrb->Ring->RingSeg0; - } + CheckedTrb = Urb->TrbStart; + for (Index = 0; Index < Urb->TrbNum; Index++) { + if (Trb == CheckedTrb) { + return TRUE; + } + + CheckedTrb++; + // + // If the checked TRB is the link TRB at the end of the transfer ring, + // recircle it to the head of the ring. + // + if (CheckedTrb->Type == TRB_TYPE_LINK) { + LinkTrb = (LINK_TRB *)CheckedTrb; + PhyAddr = (EFI_PHYSICAL_ADDRESS)(LinkTrb->PtrLo | LShiftU64 ((UINT64)LinkTrb->PtrHi, 32)); + CheckedTrb = (TRB_TEMPLATE *)(UINTN)UsbHcGetHostAddrForPciAddr (Xhc->MemPool, (VOID *)(UINTN)PhyAddr, sizeof (TRB_TEMPLATE)); + ASSERT (CheckedTrb == Urb->Ring->RingSeg0); } } @@ -1023,33 +1051,33 @@ IsAsyncIntTrb ( } /** - Check if the Trb is a transaction of the URB. + Check if the Trb is a transaction of the URBs in XHCI's asynchronous transfer list. - @param Trb The TRB to be checked - @param Urb The transfer ring to be checked. + @param Xhc The XHCI Instance. + @param Trb The TRB to be checked. + @param Urb The pointer to the matched Urb. - @retval TRUE It is a transaction of the URB. - @retval FALSE It is not any transaction of the URB. + @retval TRUE The Trb is matched with a transaction of the URBs in the async list. + @retval FALSE The Trb is not matched with any URBs in the async list. **/ BOOLEAN -IsTransferRingTrb ( - IN TRB_TEMPLATE *Trb, - IN URB *Urb +IsAsyncIntTrb ( + IN USB_XHCI_INSTANCE *Xhc, + IN TRB_TEMPLATE *Trb, + OUT URB **Urb ) { - TRB_TEMPLATE *CheckedTrb; - UINTN Index; + LIST_ENTRY *Entry; + LIST_ENTRY *Next; + URB *CheckedUrb; - CheckedTrb = Urb->Ring->RingSeg0; - - ASSERT (Urb->Ring->TrbNumber == CMD_RING_TRB_NUMBER || Urb->Ring->TrbNumber == TR_RING_TRB_NUMBER); - - for (Index = 0; Index < Urb->Ring->TrbNumber; Index++) { - if (Trb == CheckedTrb) { + BASE_LIST_FOR_EACH_SAFE (Entry, Next, &Xhc->AsyncIntTransfers) { + CheckedUrb = EFI_LIST_CONTAINER (Entry, URB, UrbList); + if (IsTransferRingTrb (Xhc, Trb, CheckedUrb)) { + *Urb = CheckedUrb; return TRUE; } - CheckedTrb++; } return FALSE; @@ -1067,21 +1095,21 @@ IsTransferRingTrb ( **/ BOOLEAN XhcCheckUrbResult ( - IN USB_XHCI_INSTANCE *Xhc, - IN URB *Urb + IN USB_XHCI_INSTANCE *Xhc, + IN URB *Urb ) { - EVT_TRB_TRANSFER *EvtTrb; - TRB_TEMPLATE *TRBPtr; - UINTN Index; - UINT8 TRBType; - EFI_STATUS Status; - URB *AsyncUrb; - URB *CheckedUrb; - UINT64 XhcDequeue; - UINT32 High; - UINT32 Low; - EFI_PHYSICAL_ADDRESS PhyAddr; + EVT_TRB_TRANSFER *EvtTrb; + TRB_TEMPLATE *TRBPtr; + UINTN Index; + UINT8 TRBType; + EFI_STATUS Status; + URB *AsyncUrb; + URB *CheckedUrb; + UINT64 XhcDequeue; + UINT32 High; + UINT32 Low; + EFI_PHYSICAL_ADDRESS PhyAddr; ASSERT ((Xhc != NULL) && (Urb != NULL)); @@ -1118,69 +1146,82 @@ XhcCheckUrbResult ( if ((EvtTrb->Type != TRB_TYPE_COMMAND_COMPLT_EVENT) && (EvtTrb->Type != TRB_TYPE_TRANS_EVENT)) { continue; } - + // // Need convert pci device address to host address // - PhyAddr = (EFI_PHYSICAL_ADDRESS)(EvtTrb->TRBPtrLo | LShiftU64 ((UINT64) EvtTrb->TRBPtrHi, 32)); - TRBPtr = (TRB_TEMPLATE *)(UINTN) UsbHcGetHostAddrForPciAddr (Xhc->MemPool, (VOID *)(UINTN) PhyAddr, sizeof (TRB_TEMPLATE)); + PhyAddr = (EFI_PHYSICAL_ADDRESS)(EvtTrb->TRBPtrLo | LShiftU64 ((UINT64)EvtTrb->TRBPtrHi, 32)); + TRBPtr = (TRB_TEMPLATE *)(UINTN)UsbHcGetHostAddrForPciAddr (Xhc->MemPool, (VOID *)(UINTN)PhyAddr, sizeof (TRB_TEMPLATE)); // - // Update the status of Urb according to the finished event regardless of whether - // the urb is current checked one or in the XHCI's async transfer list. + // Update the status of URB including the pending URB, the URB that is currently checked, + // and URBs in the XHCI's async interrupt transfer list. // This way is used to avoid that those completed async transfer events don't get // handled in time and are flushed by newer coming events. // - if (IsTransferRingTrb (TRBPtr, Urb)) { + if ((Xhc->PendingUrb != NULL) && IsTransferRingTrb (Xhc, TRBPtr, Xhc->PendingUrb)) { + CheckedUrb = Xhc->PendingUrb; + } else if (IsTransferRingTrb (Xhc, TRBPtr, Urb)) { CheckedUrb = Urb; - } else if (IsAsyncIntTrb (Xhc, TRBPtr, &AsyncUrb)) { + } else if (IsAsyncIntTrb (Xhc, TRBPtr, &AsyncUrb)) { CheckedUrb = AsyncUrb; } else { continue; } - + switch (EvtTrb->Completecode) { case TRB_COMPLETION_STALL_ERROR: CheckedUrb->Result |= EFI_USB_ERR_STALL; CheckedUrb->Finished = TRUE; - DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: STALL_ERROR! Completecode = %x\n",EvtTrb->Completecode)); + DEBUG ((DEBUG_ERROR, "XhcCheckUrbResult: STALL_ERROR! Completecode = %x\n", EvtTrb->Completecode)); goto EXIT; case TRB_COMPLETION_BABBLE_ERROR: CheckedUrb->Result |= EFI_USB_ERR_BABBLE; CheckedUrb->Finished = TRUE; - DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: BABBLE_ERROR! Completecode = %x\n",EvtTrb->Completecode)); + DEBUG ((DEBUG_ERROR, "XhcCheckUrbResult: BABBLE_ERROR! Completecode = %x\n", EvtTrb->Completecode)); goto EXIT; case TRB_COMPLETION_DATA_BUFFER_ERROR: CheckedUrb->Result |= EFI_USB_ERR_BUFFER; CheckedUrb->Finished = TRUE; - DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: ERR_BUFFER! Completecode = %x\n",EvtTrb->Completecode)); + DEBUG ((DEBUG_ERROR, "XhcCheckUrbResult: ERR_BUFFER! Completecode = %x\n", EvtTrb->Completecode)); goto EXIT; case TRB_COMPLETION_USB_TRANSACTION_ERROR: CheckedUrb->Result |= EFI_USB_ERR_TIMEOUT; CheckedUrb->Finished = TRUE; - DEBUG ((EFI_D_ERROR, "XhcCheckUrbResult: TRANSACTION_ERROR! Completecode = %x\n",EvtTrb->Completecode)); + DEBUG ((DEBUG_ERROR, "XhcCheckUrbResult: TRANSACTION_ERROR! Completecode = %x\n", EvtTrb->Completecode)); goto EXIT; + case TRB_COMPLETION_STOPPED: + case TRB_COMPLETION_STOPPED_LENGTH_INVALID: + CheckedUrb->Result |= EFI_USB_ERR_TIMEOUT; + CheckedUrb->Finished = TRUE; + // + // The pending URB is timeout and force stopped when stopping endpoint. + // Continue the loop to receive the Command Complete Event for stopping endpoint. + // + continue; + case TRB_COMPLETION_SHORT_PACKET: case TRB_COMPLETION_SUCCESS: if (EvtTrb->Completecode == TRB_COMPLETION_SHORT_PACKET) { - DEBUG ((EFI_D_VERBOSE, "XhcCheckUrbResult: short packet happens!\n")); + DEBUG ((DEBUG_VERBOSE, "XhcCheckUrbResult: short packet happens!\n")); } - TRBType = (UINT8) (TRBPtr->Type); + TRBType = (UINT8)(TRBPtr->Type); if ((TRBType == TRB_TYPE_DATA_STAGE) || (TRBType == TRB_TYPE_NORMAL) || - (TRBType == TRB_TYPE_ISOCH)) { - CheckedUrb->Completed += (((TRANSFER_TRB_NORMAL*)TRBPtr)->Length - EvtTrb->Length); + (TRBType == TRB_TYPE_ISOCH)) + { + CheckedUrb->Completed += (((TRANSFER_TRB_NORMAL *)TRBPtr)->Length - EvtTrb->Length); } break; default: - DEBUG ((EFI_D_ERROR, "Transfer Default Error Occur! Completecode = 0x%x!\n",EvtTrb->Completecode)); + DEBUG ((DEBUG_ERROR, "Transfer Default Error Occur! Completecode = 0x%x!\n", EvtTrb->Completecode)); CheckedUrb->Result |= EFI_USB_ERR_TIMEOUT; CheckedUrb->Finished = TRUE; goto EXIT; @@ -1211,9 +1252,9 @@ EXIT: // Some 3rd party XHCI external cards don't support single 64-bytes width register access, // So divide it to two 32-bytes width register access. // - Low = XhcReadRuntimeReg (Xhc, XHC_ERDP_OFFSET); - High = XhcReadRuntimeReg (Xhc, XHC_ERDP_OFFSET + 4); - XhcDequeue = (UINT64)(LShiftU64((UINT64)High, 32) | Low); + Low = XhcReadRuntimeReg (Xhc, XHC_ERDP_OFFSET); + High = XhcReadRuntimeReg (Xhc, XHC_ERDP_OFFSET + 4); + XhcDequeue = (UINT64)(LShiftU64 ((UINT64)High, 32) | Low); PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Xhc->EventRing.EventRingDequeue, sizeof (TRB_TEMPLATE)); @@ -1229,34 +1270,39 @@ EXIT: return Urb->Finished; } - /** Execute the transfer by polling the URB. This is a synchronous operation. - @param Xhc The XHCI Instance. - @param CmdTransfer The executed URB is for cmd transfer or not. - @param Urb The URB to execute. - @param Timeout The time to wait before abort, in millisecond. + @param Xhc The XHCI Instance. + @param CmdTransfer The executed URB is for cmd transfer or not. + @param Urb The URB to execute. + @param Timeout The time to wait before abort, in millisecond. - @return EFI_DEVICE_ERROR The transfer failed due to transfer error. - @return EFI_TIMEOUT The transfer failed due to time out. - @return EFI_SUCCESS The transfer finished OK. + @return EFI_DEVICE_ERROR The transfer failed due to transfer error. + @return EFI_TIMEOUT The transfer failed due to time out. + @return EFI_SUCCESS The transfer finished OK. + @retval EFI_OUT_OF_RESOURCES Memory for the timer event could not be allocated. **/ EFI_STATUS XhcExecTransfer ( - IN USB_XHCI_INSTANCE *Xhc, - IN BOOLEAN CmdTransfer, - IN URB *Urb, - IN UINTN Timeout + IN USB_XHCI_INSTANCE *Xhc, + IN BOOLEAN CmdTransfer, + IN URB *Urb, + IN UINTN Timeout ) { - EFI_STATUS Status; - UINTN Index; - UINT64 Loop; - UINT8 SlotId; - UINT8 Dci; - BOOLEAN Finished; + EFI_STATUS Status; + UINT8 SlotId; + UINT8 Dci; + BOOLEAN Finished; + EFI_EVENT TimeoutEvent; + BOOLEAN IndefiniteTimeout; + + Status = EFI_SUCCESS; + Finished = FALSE; + TimeoutEvent = NULL; + IndefiniteTimeout = FALSE; if (CmdTransfer) { SlotId = 0; @@ -1266,31 +1312,62 @@ XhcExecTransfer ( if (SlotId == 0) { return EFI_DEVICE_ERROR; } - Dci = XhcEndpointToDci (Urb->Ep.EpAddr, (UINT8)(Urb->Ep.Direction)); + + Dci = XhcEndpointToDci (Urb->Ep.EpAddr, (UINT8)(Urb->Ep.Direction)); ASSERT (Dci < 32); } - Status = EFI_SUCCESS; - Loop = Timeout * XHC_1_MILLISECOND; if (Timeout == 0) { - Loop = 0xFFFFFFFF; + IndefiniteTimeout = TRUE; + goto RINGDOORBELL; } + Status = gBS->CreateEvent ( + EVT_TIMER, + TPL_CALLBACK, + NULL, + NULL, + &TimeoutEvent + ); + + if (EFI_ERROR (Status)) { + goto DONE; + } + + Status = gBS->SetTimer ( + TimeoutEvent, + TimerRelative, + EFI_TIMER_PERIOD_MILLISECONDS (Timeout) + ); + + if (EFI_ERROR (Status)) { + goto DONE; + } + +RINGDOORBELL: XhcRingDoorBell (Xhc, SlotId, Dci); - for (Index = 0; Index < Loop; Index++) { + do { Finished = XhcCheckUrbResult (Xhc, Urb); if (Finished) { break; } + gBS->Stall (XHC_1_MICROSECOND); - } + } while (IndefiniteTimeout || EFI_ERROR (gBS->CheckEvent (TimeoutEvent))); - if (Index == Loop) { +DONE: + if (EFI_ERROR (Status)) { + Urb->Result = EFI_USB_ERR_NOTEXECUTE; + } else if (!Finished) { Urb->Result = EFI_USB_ERR_TIMEOUT; Status = EFI_TIMEOUT; } else if (Urb->Result != EFI_USB_NOERROR) { - Status = EFI_DEVICE_ERROR; + Status = EFI_DEVICE_ERROR; + } + + if (TimeoutEvent != NULL) { + gBS->CloseEvent (TimeoutEvent); } return Status; @@ -1310,26 +1387,37 @@ XhcExecTransfer ( **/ EFI_STATUS XhciDelAsyncIntTransfer ( - IN USB_XHCI_INSTANCE *Xhc, - IN UINT8 BusAddr, - IN UINT8 EpNum + IN USB_XHCI_INSTANCE *Xhc, + IN UINT8 BusAddr, + IN UINT8 EpNum ) { LIST_ENTRY *Entry; LIST_ENTRY *Next; URB *Urb; EFI_USB_DATA_DIRECTION Direction; + EFI_STATUS Status; Direction = ((EpNum & 0x80) != 0) ? EfiUsbDataIn : EfiUsbDataOut; EpNum &= 0x0F; Urb = NULL; - EFI_LIST_FOR_EACH_SAFE (Entry, Next, &Xhc->AsyncIntTransfers) { + BASE_LIST_FOR_EACH_SAFE (Entry, Next, &Xhc->AsyncIntTransfers) { Urb = EFI_LIST_CONTAINER (Entry, URB, UrbList); if ((Urb->Ep.BusAddr == BusAddr) && (Urb->Ep.EpAddr == EpNum) && - (Urb->Ep.Direction == Direction)) { + (Urb->Ep.Direction == Direction)) + { + // + // Device doesn't finish the IntTransfer until real data comes + // So the TRB should be removed as well. + // + Status = XhcDequeueTrbFromEndpoint (Xhc, Urb); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "XhciDelAsyncIntTransfer: XhcDequeueTrbFromEndpoint failed\n")); + } + RemoveEntryList (&Urb->UrbList); FreePool (Urb->Data); XhcFreeUrb (Xhc, Urb); @@ -1348,21 +1436,97 @@ XhciDelAsyncIntTransfer ( **/ VOID XhciDelAllAsyncIntTransfers ( - IN USB_XHCI_INSTANCE *Xhc + IN USB_XHCI_INSTANCE *Xhc ) { - LIST_ENTRY *Entry; - LIST_ENTRY *Next; - URB *Urb; + LIST_ENTRY *Entry; + LIST_ENTRY *Next; + URB *Urb; + EFI_STATUS Status; - EFI_LIST_FOR_EACH_SAFE (Entry, Next, &Xhc->AsyncIntTransfers) { + BASE_LIST_FOR_EACH_SAFE (Entry, Next, &Xhc->AsyncIntTransfers) { Urb = EFI_LIST_CONTAINER (Entry, URB, UrbList); + + // + // Device doesn't finish the IntTransfer until real data comes + // So the TRB should be removed as well. + // + Status = XhcDequeueTrbFromEndpoint (Xhc, Urb); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "XhciDelAllAsyncIntTransfers: XhcDequeueTrbFromEndpoint failed\n")); + } + RemoveEntryList (&Urb->UrbList); FreePool (Urb->Data); XhcFreeUrb (Xhc, Urb); } } +/** + Insert a single asynchronous interrupt transfer for + the device and endpoint. + + @param Xhc The XHCI Instance + @param BusAddr The logical device address assigned by UsbBus driver + @param EpAddr Endpoint addrress + @param DevSpeed The device speed + @param MaxPacket The max packet length of the endpoint + @param DataLen The length of data buffer + @param Callback The function to call when data is transferred + @param Context The context to the callback + + @return Created URB or NULL + +**/ +URB * +XhciInsertAsyncIntTransfer ( + IN USB_XHCI_INSTANCE *Xhc, + IN UINT8 BusAddr, + IN UINT8 EpAddr, + IN UINT8 DevSpeed, + IN UINTN MaxPacket, + IN UINTN DataLen, + IN EFI_ASYNC_USB_TRANSFER_CALLBACK Callback, + IN VOID *Context + ) +{ + VOID *Data; + URB *Urb; + + Data = AllocateZeroPool (DataLen); + if (Data == NULL) { + DEBUG ((DEBUG_ERROR, "%a: failed to allocate buffer\n", __FUNCTION__)); + return NULL; + } + + Urb = XhcCreateUrb ( + Xhc, + BusAddr, + EpAddr, + DevSpeed, + MaxPacket, + XHC_INT_TRANSFER_ASYNC, + NULL, + Data, + DataLen, + Callback, + Context + ); + if (Urb == NULL) { + DEBUG ((DEBUG_ERROR, "%a: failed to create URB\n", __FUNCTION__)); + FreePool (Data); + return NULL; + } + + // + // New asynchronous transfer must inserted to the head. + // Check the comments in XhcMoniteAsyncRequests + // + InsertHeadList (&Xhc->AsyncIntTransfers, &Urb->UrbList); + + return Urb; +} + /** Update the queue head for next round of asynchronous transfer @@ -1372,17 +1536,18 @@ XhciDelAllAsyncIntTransfers ( **/ VOID XhcUpdateAsyncRequest ( - IN USB_XHCI_INSTANCE *Xhc, - IN URB *Urb + IN USB_XHCI_INSTANCE *Xhc, + IN URB *Urb ) { - EFI_STATUS Status; + EFI_STATUS Status; if (Urb->Result == EFI_USB_NOERROR) { Status = XhcCreateTransferTrb (Xhc, Urb); if (EFI_ERROR (Status)) { return; } + Status = RingIntTransferDoorBell (Xhc, Urb); if (EFI_ERROR (Status)) { return; @@ -1403,16 +1568,16 @@ XhcUpdateAsyncRequest ( **/ EFI_STATUS XhcFlushAsyncIntMap ( - IN USB_XHCI_INSTANCE *Xhc, - IN URB *Urb + IN USB_XHCI_INSTANCE *Xhc, + IN URB *Urb ) { - EFI_STATUS Status; - EFI_PHYSICAL_ADDRESS PhyAddr; - EFI_PCI_IO_PROTOCOL_OPERATION MapOp; - EFI_PCI_IO_PROTOCOL *PciIo; - UINTN Len; - VOID *Map; + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS PhyAddr; + EFI_PCI_IO_PROTOCOL_OPERATION MapOp; + EFI_PCI_IO_PROTOCOL *PciIo; + UINTN Len; + VOID *Map; PciIo = Xhc->PciIo; Len = Urb->DataLen; @@ -1437,8 +1602,8 @@ XhcFlushAsyncIntMap ( goto ON_ERROR; } - Urb->DataPhy = (VOID *) ((UINTN) PhyAddr); - Urb->DataMap = Map; + Urb->DataPhy = (VOID *)((UINTN)PhyAddr); + Urb->DataMap = Map; return EFI_SUCCESS; ON_ERROR: @@ -1455,24 +1620,24 @@ ON_ERROR: VOID EFIAPI XhcMonitorAsyncRequests ( - IN EFI_EVENT Event, - IN VOID *Context + IN EFI_EVENT Event, + IN VOID *Context ) { - USB_XHCI_INSTANCE *Xhc; - LIST_ENTRY *Entry; - LIST_ENTRY *Next; - UINT8 *ProcBuf; - URB *Urb; - UINT8 SlotId; - EFI_STATUS Status; - EFI_TPL OldTpl; + USB_XHCI_INSTANCE *Xhc; + LIST_ENTRY *Entry; + LIST_ENTRY *Next; + UINT8 *ProcBuf; + URB *Urb; + UINT8 SlotId; + EFI_STATUS Status; + EFI_TPL OldTpl; OldTpl = gBS->RaiseTPL (XHC_TPL); - Xhc = (USB_XHCI_INSTANCE*) Context; + Xhc = (USB_XHCI_INSTANCE *)Context; - EFI_LIST_FOR_EACH_SAFE (Entry, Next, &Xhc->AsyncIntTransfers) { + BASE_LIST_FOR_EACH_SAFE (Entry, Next, &Xhc->AsyncIntTransfers) { Urb = EFI_LIST_CONTAINER (Entry, URB, UrbList); // @@ -1499,7 +1664,7 @@ XhcMonitorAsyncRequests ( // Status = XhcFlushAsyncIntMap (Xhc, Urb); if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "XhcMonitorAsyncRequests: Fail to Flush AsyncInt Mapped Memeory\n")); + DEBUG ((DEBUG_ERROR, "XhcMonitorAsyncRequests: Fail to Flush AsyncInt Mapped Memeory\n")); } // @@ -1509,9 +1674,12 @@ XhcMonitorAsyncRequests ( // ProcBuf = NULL; if (Urb->Result == EFI_USB_NOERROR) { - ASSERT (Urb->Completed <= Urb->DataLen); - - ProcBuf = AllocateZeroPool (Urb->Completed); + // + // Make sure the data received from HW is no more than expected. + // + if (Urb->Completed <= Urb->DataLen) { + ProcBuf = AllocateZeroPool (Urb->Completed); + } if (ProcBuf == NULL) { XhcUpdateAsyncRequest (Xhc, Urb); @@ -1537,7 +1705,7 @@ XhcMonitorAsyncRequests ( // his callback. Some drivers may has a lower TPL restriction. // gBS->RestoreTPL (OldTpl); - (Urb->Callback) (ProcBuf, Urb->Completed, Urb->Context, Urb->Result); + (Urb->Callback)(ProcBuf, Urb->Completed, Urb->Context, Urb->Result); OldTpl = gBS->RaiseTPL (XHC_TPL); } @@ -1565,18 +1733,20 @@ XhcMonitorAsyncRequests ( EFI_STATUS EFIAPI XhcPollPortStatusChange ( - IN USB_XHCI_INSTANCE *Xhc, - IN USB_DEV_ROUTE ParentRouteChart, - IN UINT8 Port, - IN EFI_USB_PORT_STATUS *PortState + IN USB_XHCI_INSTANCE *Xhc, + IN USB_DEV_ROUTE ParentRouteChart, + IN UINT8 Port, + IN EFI_USB_PORT_STATUS *PortState ) { - EFI_STATUS Status; - UINT8 Speed; - UINT8 SlotId; - USB_DEV_ROUTE RouteChart; + EFI_STATUS Status; + UINT8 Speed; + UINT8 SlotId; + UINT8 Retries; + USB_DEV_ROUTE RouteChart; - Status = EFI_SUCCESS; + Status = EFI_SUCCESS; + Retries = XHC_INIT_DEVICE_SLOT_RETRIES; if ((PortState->PortChangeStatus & (USB_PORT_STAT_C_CONNECTION | USB_PORT_STAT_C_ENABLE | USB_PORT_STAT_C_OVERCURRENT | USB_PORT_STAT_C_RESET)) == 0) { return EFI_SUCCESS; @@ -1587,13 +1757,14 @@ XhcPollPortStatusChange ( RouteChart.Route.RootPortNum = Port + 1; RouteChart.Route.TierNum = 1; } else { - if(Port < 14) { + if (Port < 14) { RouteChart.Route.RouteString = ParentRouteChart.Route.RouteString | (Port << (4 * (ParentRouteChart.Route.TierNum - 1))); } else { RouteChart.Route.RouteString = ParentRouteChart.Route.RouteString | (15 << (4 * (ParentRouteChart.Route.TierNum - 1))); } - RouteChart.Route.RootPortNum = ParentRouteChart.Route.RootPortNum; - RouteChart.Route.TierNum = ParentRouteChart.Route.TierNum + 1; + + RouteChart.Route.RootPortNum = ParentRouteChart.Route.RootPortNum; + RouteChart.Route.TierNum = ParentRouteChart.Route.TierNum + 1; } SlotId = XhcRouteStringToSlotId (Xhc, RouteChart); @@ -1606,7 +1777,8 @@ XhcPollPortStatusChange ( } if (((PortState->PortStatus & USB_PORT_STAT_ENABLE) != 0) && - ((PortState->PortStatus & USB_PORT_STAT_CONNECTION) != 0)) { + ((PortState->PortStatus & USB_PORT_STAT_CONNECTION) != 0)) + { // // Has a device attached, Identify device speed after port is enabled. // @@ -1618,23 +1790,34 @@ XhcPollPortStatusChange ( } else if ((PortState->PortStatus & USB_PORT_STAT_SUPER_SPEED) != 0) { Speed = EFI_USB_SPEED_SUPER; } - // - // Execute Enable_Slot cmd for attached device, initialize device context and assign device address. - // - SlotId = XhcRouteStringToSlotId (Xhc, RouteChart); - if ((SlotId == 0) && ((PortState->PortChangeStatus & USB_PORT_STAT_C_RESET) != 0)) { - if (Xhc->HcCParams.Data.Csz == 0) { - Status = XhcInitializeDeviceSlot (Xhc, ParentRouteChart, Port, RouteChart, Speed); - } else { - Status = XhcInitializeDeviceSlot64 (Xhc, ParentRouteChart, Port, RouteChart, Speed); + + do { + // + // Execute Enable_Slot cmd for attached device, initialize device context and assign device address. + // + SlotId = XhcRouteStringToSlotId (Xhc, RouteChart); + if ((SlotId == 0) && ((PortState->PortChangeStatus & USB_PORT_STAT_C_RESET) != 0)) { + if (Xhc->HcCParams.Data.Csz == 0) { + Status = XhcInitializeDeviceSlot (Xhc, ParentRouteChart, Port, RouteChart, Speed); + } else { + Status = XhcInitializeDeviceSlot64 (Xhc, ParentRouteChart, Port, RouteChart, Speed); + } } - } - } + + // + // According to the xHCI specification (section 4.6.5), "a USB Transaction + // Error Completion Code for an Address Device Command may be due to a Stall + // response from a device. Software should issue a Disable Slot Command for + // the Device Slot then an Enable Slot Command to recover from this error." + // Therefore, retry the device slot initialization if it fails due to a + // device error. + // + } while ((Status == EFI_DEVICE_ERROR) && (Retries-- != 0)); + } return Status; } - /** Calculate the device context index by endpoint address and direction. @@ -1646,19 +1829,20 @@ XhcPollPortStatusChange ( **/ UINT8 XhcEndpointToDci ( - IN UINT8 EpAddr, - IN UINT8 Direction + IN UINT8 EpAddr, + IN UINT8 Direction ) { - UINT8 Index; + UINT8 Index; if (EpAddr == 0) { return 1; } else { - Index = (UINT8) (2 * EpAddr); + Index = (UINT8)(2 * EpAddr); if (Direction == EfiUsbDataIn) { Index += 1; } + return Index; } } @@ -1684,7 +1868,8 @@ XhcBusDevAddrToSlotId ( for (Index = 0; Index < 255; Index++) { if (Xhc->UsbDevContext[Index + 1].Enabled && (Xhc->UsbDevContext[Index + 1].SlotId != 0) && - (Xhc->UsbDevContext[Index + 1].BusDevAddr == BusDevAddr)) { + (Xhc->UsbDevContext[Index + 1].BusDevAddr == BusDevAddr)) + { break; } } @@ -1717,7 +1902,8 @@ XhcRouteStringToSlotId ( for (Index = 0; Index < 255; Index++) { if (Xhc->UsbDevContext[Index + 1].Enabled && (Xhc->UsbDevContext[Index + 1].SlotId != 0) && - (Xhc->UsbDevContext[Index + 1].RouteString.Dword == RouteString.Dword)) { + (Xhc->UsbDevContext[Index + 1].RouteString.Dword == RouteString.Dword)) + { break; } } @@ -1741,12 +1927,12 @@ XhcRouteStringToSlotId ( EFI_STATUS EFIAPI XhcSyncEventRing ( - IN USB_XHCI_INSTANCE *Xhc, - IN EVENT_RING *EvtRing + IN USB_XHCI_INSTANCE *Xhc, + IN EVENT_RING *EvtRing ) { - UINTN Index; - TRB_TEMPLATE *EvtTrb1; + UINTN Index; + TRB_TEMPLATE *EvtTrb1; ASSERT (EvtRing != NULL); @@ -1763,8 +1949,8 @@ XhcSyncEventRing ( EvtTrb1++; - if ((UINTN)EvtTrb1 >= ((UINTN) EvtRing->EventRingSeg0 + sizeof (TRB_TEMPLATE) * EvtRing->TrbNumber)) { - EvtTrb1 = EvtRing->EventRingSeg0; + if ((UINTN)EvtTrb1 >= ((UINTN)EvtRing->EventRingSeg0 + sizeof (TRB_TEMPLATE) * EvtRing->TrbNumber)) { + EvtTrb1 = EvtRing->EventRingSeg0; EvtRing->EventRingCCS = (EvtRing->EventRingCCS) ? 0 : 1; } } @@ -1790,12 +1976,12 @@ XhcSyncEventRing ( EFI_STATUS EFIAPI XhcSyncTrsRing ( - IN USB_XHCI_INSTANCE *Xhc, - IN TRANSFER_RING *TrsRing + IN USB_XHCI_INSTANCE *Xhc, + IN TRANSFER_RING *TrsRing ) { - UINTN Index; - TRB_TEMPLATE *TrsTrb; + UINTN Index; + TRB_TEMPLATE *TrsTrb; ASSERT (TrsRing != NULL); // @@ -1808,18 +1994,19 @@ XhcSyncTrsRing ( if (TrsTrb->CycleBit != (TrsRing->RingPCS & BIT0)) { break; } + TrsTrb++; - if ((UINT8) TrsTrb->Type == TRB_TYPE_LINK) { - ASSERT (((LINK_TRB*)TrsTrb)->TC != 0); + if ((UINT8)TrsTrb->Type == TRB_TYPE_LINK) { + ASSERT (((LINK_TRB *)TrsTrb)->TC != 0); // // set cycle bit in Link TRB as normal // - ((LINK_TRB*)TrsTrb)->CycleBit = TrsRing->RingPCS & BIT0; + ((LINK_TRB *)TrsTrb)->CycleBit = TrsRing->RingPCS & BIT0; // // Toggle PCS maintained by software // TrsRing->RingPCS = (TrsRing->RingPCS & BIT0) ? 0 : 1; - TrsTrb = (TRB_TEMPLATE *) TrsRing->RingSeg0; // Use host address + TrsTrb = (TRB_TEMPLATE *)TrsRing->RingSeg0; // Use host address } } @@ -1856,9 +2043,9 @@ XhcSyncTrsRing ( EFI_STATUS EFIAPI XhcCheckNewEvent ( - IN USB_XHCI_INSTANCE *Xhc, - IN EVENT_RING *EvtRing, - OUT TRB_TEMPLATE **NewEvtTrb + IN USB_XHCI_INSTANCE *Xhc, + IN EVENT_RING *EvtRing, + OUT TRB_TEMPLATE **NewEvtTrb ) { ASSERT (EvtRing != NULL); @@ -1873,7 +2060,7 @@ XhcCheckNewEvent ( // // If the dequeue pointer is beyond the ring, then roll-back it to the begining of the ring. // - if ((UINTN)EvtRing->EventRingDequeue >= ((UINTN) EvtRing->EventRingSeg0 + sizeof (TRB_TEMPLATE) * EvtRing->TrbNumber)) { + if ((UINTN)EvtRing->EventRingDequeue >= ((UINTN)EvtRing->EventRingSeg0 + sizeof (TRB_TEMPLATE) * EvtRing->TrbNumber)) { EvtRing->EventRingDequeue = EvtRing->EventRingSeg0; } @@ -1893,9 +2080,9 @@ XhcCheckNewEvent ( EFI_STATUS EFIAPI XhcRingDoorBell ( - IN USB_XHCI_INSTANCE *Xhc, - IN UINT8 SlotId, - IN UINT8 Dci + IN USB_XHCI_INSTANCE *Xhc, + IN UINT8 SlotId, + IN UINT8 Dci ) { if (SlotId == 0) { @@ -1918,12 +2105,12 @@ XhcRingDoorBell ( **/ EFI_STATUS RingIntTransferDoorBell ( - IN USB_XHCI_INSTANCE *Xhc, - IN URB *Urb + IN USB_XHCI_INSTANCE *Xhc, + IN URB *Urb ) { - UINT8 SlotId; - UINT8 Dci; + UINT8 SlotId; + UINT8 Dci; SlotId = XhcBusDevAddrToSlotId (Xhc, Urb->Ep.BusAddr); Dci = XhcEndpointToDci (Urb->Ep.EpAddr, (UINT8)(Urb->Ep.Direction)); @@ -1946,11 +2133,11 @@ RingIntTransferDoorBell ( EFI_STATUS EFIAPI XhcInitializeDeviceSlot ( - IN USB_XHCI_INSTANCE *Xhc, - IN USB_DEV_ROUTE ParentRouteChart, - IN UINT16 ParentPort, - IN USB_DEV_ROUTE RouteChart, - IN UINT8 DeviceSpeed + IN USB_XHCI_INSTANCE *Xhc, + IN USB_DEV_ROUTE ParentRouteChart, + IN UINT16 ParentPort, + IN USB_DEV_ROUTE RouteChart, + IN UINT8 DeviceSpeed ) { EFI_STATUS Status; @@ -1971,17 +2158,18 @@ XhcInitializeDeviceSlot ( CmdTrb.Type = TRB_TYPE_EN_SLOT; Status = XhcCmdTransfer ( - Xhc, - (TRB_TEMPLATE *) (UINTN) &CmdTrb, - XHC_GENERIC_TIMEOUT, - (TRB_TEMPLATE **) (UINTN) &EvtTrb - ); + Xhc, + (TRB_TEMPLATE *)(UINTN)&CmdTrb, + XHC_GENERIC_TIMEOUT, + (TRB_TEMPLATE **)(UINTN)&EvtTrb + ); if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "XhcInitializeDeviceSlot: Enable Slot Failed, Status = %r\n", Status)); + DEBUG ((DEBUG_ERROR, "XhcInitializeDeviceSlot: Enable Slot Failed, Status = %r\n", Status)); return Status; } + ASSERT (EvtTrb->SlotId <= Xhc->MaxSlotsEn); - DEBUG ((EFI_D_INFO, "Enable Slot Successfully, The Slot ID = 0x%x\n", EvtTrb->SlotId)); + DEBUG ((DEBUG_INFO, "Enable Slot Successfully, The Slot ID = 0x%x\n", EvtTrb->SlotId)); SlotId = (UINT8)EvtTrb->SlotId; ASSERT (SlotId != 0); @@ -1995,12 +2183,12 @@ XhcInitializeDeviceSlot ( // 4.3.3 Device Slot Initialization // 1) Allocate an Input Context data structure (6.2.5) and initialize all fields to '0'. // - InputContext = UsbHcAllocateMem (Xhc->MemPool, sizeof (INPUT_CONTEXT)); + InputContext = UsbHcAllocateMem (Xhc->MemPool, sizeof (INPUT_CONTEXT), FALSE); ASSERT (InputContext != NULL); - ASSERT (((UINTN) InputContext & 0x3F) == 0); + ASSERT (((UINTN)InputContext & 0x3F) == 0); ZeroMem (InputContext, sizeof (INPUT_CONTEXT)); - Xhc->UsbDevContext[SlotId].InputContext = (VOID *) InputContext; + Xhc->UsbDevContext[SlotId].InputContext = (VOID *)InputContext; // // 2) Initialize the Input Control Context (6.2.5.1) of the Input Context by setting the A0 and A1 @@ -2021,14 +2209,15 @@ XhcInitializeDeviceSlot ( // // The device is behind of hub device. // - ParentSlotId = XhcRouteStringToSlotId(Xhc, ParentRouteChart); + ParentSlotId = XhcRouteStringToSlotId (Xhc, ParentRouteChart); ASSERT (ParentSlotId != 0); // - //if the Full/Low device attached to a High Speed Hub, Init the TTPortNum and TTHubSlotId field of slot context + // if the Full/Low device attached to a High Speed Hub, Init the TTPortNum and TTHubSlotId field of slot context // ParentDeviceContext = (DEVICE_CONTEXT *)Xhc->UsbDevContext[ParentSlotId].OutputContext; if ((ParentDeviceContext->Slot.TTPortNum == 0) && - (ParentDeviceContext->Slot.TTHubSlotId == 0)) { + (ParentDeviceContext->Slot.TTHubSlotId == 0)) + { if ((ParentDeviceContext->Slot.Speed == (EFI_USB_SPEED_HIGH + 1)) && (DeviceSpeed < EFI_USB_SPEED_HIGH)) { // // Full/Low device attached to High speed hub port that isolates the high speed signaling @@ -2055,9 +2244,9 @@ XhcInitializeDeviceSlot ( // // 4) Allocate and initialize the Transfer Ring for the Default Control Endpoint. // - EndpointTransferRing = AllocateZeroPool (sizeof (TRANSFER_RING)); + EndpointTransferRing = AllocateZeroPool (sizeof (TRANSFER_RING)); Xhc->UsbDevContext[SlotId].EndpointTransferRing[0] = EndpointTransferRing; - CreateTransferRing(Xhc, TR_RING_TRB_NUMBER, (TRANSFER_RING *)Xhc->UsbDevContext[SlotId].EndpointTransferRing[0]); + CreateTransferRing (Xhc, TR_RING_TRB_NUMBER, (TRANSFER_RING *)Xhc->UsbDevContext[SlotId].EndpointTransferRing[0]); // // 5) Initialize the Input default control Endpoint 0 Context (6.2.3). // @@ -2070,6 +2259,7 @@ XhcInitializeDeviceSlot ( } else { InputContext->EP[0].MaxPacketSize = 8; } + // // Initial value of Average TRB Length for Control endpoints would be 8B, Interrupt endpoints // 1KB, and Bulk and Isoch endpoints 3KB. @@ -2095,9 +2285,9 @@ XhcInitializeDeviceSlot ( // // 6) Allocate the Output Device Context data structure (6.2.1) and initialize it to '0'. // - OutputContext = UsbHcAllocateMem (Xhc->MemPool, sizeof (DEVICE_CONTEXT)); + OutputContext = UsbHcAllocateMem (Xhc->MemPool, sizeof (DEVICE_CONTEXT), FALSE); ASSERT (OutputContext != NULL); - ASSERT (((UINTN) OutputContext & 0x3F) == 0); + ASSERT (((UINTN)OutputContext & 0x3F) == 0); ZeroMem (OutputContext, sizeof (DEVICE_CONTEXT)); Xhc->UsbDevContext[SlotId].OutputContext = OutputContext; @@ -2109,7 +2299,7 @@ XhcInitializeDeviceSlot ( // // Fill DCBAA with PCI device address // - Xhc->DCBAA[SlotId] = (UINT64) (UINTN) PhyAddr; + Xhc->DCBAA[SlotId] = (UINT64)(UINTN)PhyAddr; // // 8) Issue an Address Device Command for the Device Slot, where the command points to the Input @@ -2120,22 +2310,25 @@ XhcInitializeDeviceSlot ( // gBS->Stall (XHC_RESET_RECOVERY_DELAY); ZeroMem (&CmdTrbAddr, sizeof (CmdTrbAddr)); - PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Xhc->UsbDevContext[SlotId].InputContext, sizeof (INPUT_CONTEXT)); + PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Xhc->UsbDevContext[SlotId].InputContext, sizeof (INPUT_CONTEXT)); CmdTrbAddr.PtrLo = XHC_LOW_32BIT (PhyAddr); CmdTrbAddr.PtrHi = XHC_HIGH_32BIT (PhyAddr); CmdTrbAddr.CycleBit = 1; CmdTrbAddr.Type = TRB_TYPE_ADDRESS_DEV; CmdTrbAddr.SlotId = Xhc->UsbDevContext[SlotId].SlotId; - Status = XhcCmdTransfer ( - Xhc, - (TRB_TEMPLATE *) (UINTN) &CmdTrbAddr, - XHC_GENERIC_TIMEOUT, - (TRB_TEMPLATE **) (UINTN) &EvtTrb - ); + Status = XhcCmdTransfer ( + Xhc, + (TRB_TEMPLATE *)(UINTN)&CmdTrbAddr, + XHC_GENERIC_TIMEOUT, + (TRB_TEMPLATE **)(UINTN)&EvtTrb + ); if (!EFI_ERROR (Status)) { - DeviceAddress = (UINT8) ((DEVICE_CONTEXT *) OutputContext)->Slot.DeviceAddress; - DEBUG ((EFI_D_INFO, " Address %d assigned successfully\n", DeviceAddress)); + DeviceAddress = (UINT8)((DEVICE_CONTEXT *)OutputContext)->Slot.DeviceAddress; + DEBUG ((DEBUG_INFO, " Address %d assigned successfully\n", DeviceAddress)); Xhc->UsbDevContext[SlotId].XhciDevAddr = DeviceAddress; + } else { + DEBUG ((DEBUG_ERROR, " Slot %d address not assigned successfully. Status = %r\n", SlotId, Status)); + XhcDisableSlotCmd (Xhc, SlotId); } return Status; @@ -2156,11 +2349,11 @@ XhcInitializeDeviceSlot ( EFI_STATUS EFIAPI XhcInitializeDeviceSlot64 ( - IN USB_XHCI_INSTANCE *Xhc, - IN USB_DEV_ROUTE ParentRouteChart, - IN UINT16 ParentPort, - IN USB_DEV_ROUTE RouteChart, - IN UINT8 DeviceSpeed + IN USB_XHCI_INSTANCE *Xhc, + IN USB_DEV_ROUTE ParentRouteChart, + IN UINT16 ParentPort, + IN USB_DEV_ROUTE RouteChart, + IN UINT8 DeviceSpeed ) { EFI_STATUS Status; @@ -2181,17 +2374,18 @@ XhcInitializeDeviceSlot64 ( CmdTrb.Type = TRB_TYPE_EN_SLOT; Status = XhcCmdTransfer ( - Xhc, - (TRB_TEMPLATE *) (UINTN) &CmdTrb, - XHC_GENERIC_TIMEOUT, - (TRB_TEMPLATE **) (UINTN) &EvtTrb - ); + Xhc, + (TRB_TEMPLATE *)(UINTN)&CmdTrb, + XHC_GENERIC_TIMEOUT, + (TRB_TEMPLATE **)(UINTN)&EvtTrb + ); if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "XhcInitializeDeviceSlot64: Enable Slot Failed, Status = %r\n", Status)); + DEBUG ((DEBUG_ERROR, "XhcInitializeDeviceSlot64: Enable Slot Failed, Status = %r\n", Status)); return Status; } + ASSERT (EvtTrb->SlotId <= Xhc->MaxSlotsEn); - DEBUG ((EFI_D_INFO, "Enable Slot Successfully, The Slot ID = 0x%x\n", EvtTrb->SlotId)); + DEBUG ((DEBUG_INFO, "Enable Slot Successfully, The Slot ID = 0x%x\n", EvtTrb->SlotId)); SlotId = (UINT8)EvtTrb->SlotId; ASSERT (SlotId != 0); @@ -2205,12 +2399,12 @@ XhcInitializeDeviceSlot64 ( // 4.3.3 Device Slot Initialization // 1) Allocate an Input Context data structure (6.2.5) and initialize all fields to '0'. // - InputContext = UsbHcAllocateMem (Xhc->MemPool, sizeof (INPUT_CONTEXT_64)); + InputContext = UsbHcAllocateMem (Xhc->MemPool, sizeof (INPUT_CONTEXT_64), FALSE); ASSERT (InputContext != NULL); - ASSERT (((UINTN) InputContext & 0x3F) == 0); + ASSERT (((UINTN)InputContext & 0x3F) == 0); ZeroMem (InputContext, sizeof (INPUT_CONTEXT_64)); - Xhc->UsbDevContext[SlotId].InputContext = (VOID *) InputContext; + Xhc->UsbDevContext[SlotId].InputContext = (VOID *)InputContext; // // 2) Initialize the Input Control Context (6.2.5.1) of the Input Context by setting the A0 and A1 @@ -2231,14 +2425,15 @@ XhcInitializeDeviceSlot64 ( // // The device is behind of hub device. // - ParentSlotId = XhcRouteStringToSlotId(Xhc, ParentRouteChart); + ParentSlotId = XhcRouteStringToSlotId (Xhc, ParentRouteChart); ASSERT (ParentSlotId != 0); // - //if the Full/Low device attached to a High Speed Hub, Init the TTPortNum and TTHubSlotId field of slot context + // if the Full/Low device attached to a High Speed Hub, Init the TTPortNum and TTHubSlotId field of slot context // ParentDeviceContext = (DEVICE_CONTEXT_64 *)Xhc->UsbDevContext[ParentSlotId].OutputContext; if ((ParentDeviceContext->Slot.TTPortNum == 0) && - (ParentDeviceContext->Slot.TTHubSlotId == 0)) { + (ParentDeviceContext->Slot.TTHubSlotId == 0)) + { if ((ParentDeviceContext->Slot.Speed == (EFI_USB_SPEED_HIGH + 1)) && (DeviceSpeed < EFI_USB_SPEED_HIGH)) { // // Full/Low device attached to High speed hub port that isolates the high speed signaling @@ -2265,9 +2460,9 @@ XhcInitializeDeviceSlot64 ( // // 4) Allocate and initialize the Transfer Ring for the Default Control Endpoint. // - EndpointTransferRing = AllocateZeroPool (sizeof (TRANSFER_RING)); + EndpointTransferRing = AllocateZeroPool (sizeof (TRANSFER_RING)); Xhc->UsbDevContext[SlotId].EndpointTransferRing[0] = EndpointTransferRing; - CreateTransferRing(Xhc, TR_RING_TRB_NUMBER, (TRANSFER_RING *)Xhc->UsbDevContext[SlotId].EndpointTransferRing[0]); + CreateTransferRing (Xhc, TR_RING_TRB_NUMBER, (TRANSFER_RING *)Xhc->UsbDevContext[SlotId].EndpointTransferRing[0]); // // 5) Initialize the Input default control Endpoint 0 Context (6.2.3). // @@ -2280,6 +2475,7 @@ XhcInitializeDeviceSlot64 ( } else { InputContext->EP[0].MaxPacketSize = 8; } + // // Initial value of Average TRB Length for Control endpoints would be 8B, Interrupt endpoints // 1KB, and Bulk and Isoch endpoints 3KB. @@ -2305,9 +2501,9 @@ XhcInitializeDeviceSlot64 ( // // 6) Allocate the Output Device Context data structure (6.2.1) and initialize it to '0'. // - OutputContext = UsbHcAllocateMem (Xhc->MemPool, sizeof (DEVICE_CONTEXT_64)); + OutputContext = UsbHcAllocateMem (Xhc->MemPool, sizeof (DEVICE_CONTEXT_64), FALSE); ASSERT (OutputContext != NULL); - ASSERT (((UINTN) OutputContext & 0x3F) == 0); + ASSERT (((UINTN)OutputContext & 0x3F) == 0); ZeroMem (OutputContext, sizeof (DEVICE_CONTEXT_64)); Xhc->UsbDevContext[SlotId].OutputContext = OutputContext; @@ -2319,7 +2515,7 @@ XhcInitializeDeviceSlot64 ( // // Fill DCBAA with PCI device address // - Xhc->DCBAA[SlotId] = (UINT64) (UINTN) PhyAddr; + Xhc->DCBAA[SlotId] = (UINT64)(UINTN)PhyAddr; // // 8) Issue an Address Device Command for the Device Slot, where the command points to the Input @@ -2330,27 +2526,30 @@ XhcInitializeDeviceSlot64 ( // gBS->Stall (XHC_RESET_RECOVERY_DELAY); ZeroMem (&CmdTrbAddr, sizeof (CmdTrbAddr)); - PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Xhc->UsbDevContext[SlotId].InputContext, sizeof (INPUT_CONTEXT_64)); + PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Xhc->UsbDevContext[SlotId].InputContext, sizeof (INPUT_CONTEXT_64)); CmdTrbAddr.PtrLo = XHC_LOW_32BIT (PhyAddr); CmdTrbAddr.PtrHi = XHC_HIGH_32BIT (PhyAddr); CmdTrbAddr.CycleBit = 1; CmdTrbAddr.Type = TRB_TYPE_ADDRESS_DEV; CmdTrbAddr.SlotId = Xhc->UsbDevContext[SlotId].SlotId; - Status = XhcCmdTransfer ( - Xhc, - (TRB_TEMPLATE *) (UINTN) &CmdTrbAddr, - XHC_GENERIC_TIMEOUT, - (TRB_TEMPLATE **) (UINTN) &EvtTrb - ); + Status = XhcCmdTransfer ( + Xhc, + (TRB_TEMPLATE *)(UINTN)&CmdTrbAddr, + XHC_GENERIC_TIMEOUT, + (TRB_TEMPLATE **)(UINTN)&EvtTrb + ); if (!EFI_ERROR (Status)) { - DeviceAddress = (UINT8) ((DEVICE_CONTEXT_64 *) OutputContext)->Slot.DeviceAddress; - DEBUG ((EFI_D_INFO, " Address %d assigned successfully\n", DeviceAddress)); + DeviceAddress = (UINT8)((DEVICE_CONTEXT_64 *)OutputContext)->Slot.DeviceAddress; + DEBUG ((DEBUG_INFO, " Address %d assigned successfully\n", DeviceAddress)); Xhc->UsbDevContext[SlotId].XhciDevAddr = DeviceAddress; + } else { + DEBUG ((DEBUG_ERROR, " Slot %d address not assigned successfully. Status = %r\n", SlotId, Status)); + XhcDisableSlotCmd64 (Xhc, SlotId); } + return Status; } - /** Disable the specified device slot. @@ -2363,8 +2562,8 @@ XhcInitializeDeviceSlot64 ( EFI_STATUS EFIAPI XhcDisableSlotCmd ( - IN USB_XHCI_INSTANCE *Xhc, - IN UINT8 SlotId + IN USB_XHCI_INSTANCE *Xhc, + IN UINT8 SlotId ) { EFI_STATUS Status; @@ -2380,14 +2579,15 @@ XhcDisableSlotCmd ( for (Index = 0; Index < 255; Index++) { if (!Xhc->UsbDevContext[Index + 1].Enabled || (Xhc->UsbDevContext[Index + 1].SlotId == 0) || - (Xhc->UsbDevContext[Index + 1].ParentRouteString.Dword != Xhc->UsbDevContext[SlotId].RouteString.Dword)) { + (Xhc->UsbDevContext[Index + 1].ParentRouteString.Dword != Xhc->UsbDevContext[SlotId].RouteString.Dword)) + { continue; } Status = XhcDisableSlotCmd (Xhc, Xhc->UsbDevContext[Index + 1].SlotId); if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "XhcDisableSlotCmd: failed to disable child, ignore error\n")); + DEBUG ((DEBUG_ERROR, "XhcDisableSlotCmd: failed to disable child, ignore error\n")); Xhc->UsbDevContext[Index + 1].SlotId = 0; } } @@ -2395,22 +2595,23 @@ XhcDisableSlotCmd ( // // Construct the disable slot command // - DEBUG ((EFI_D_INFO, "Disable device slot %d!\n", SlotId)); + DEBUG ((DEBUG_INFO, "Disable device slot %d!\n", SlotId)); ZeroMem (&CmdTrbDisSlot, sizeof (CmdTrbDisSlot)); CmdTrbDisSlot.CycleBit = 1; CmdTrbDisSlot.Type = TRB_TYPE_DIS_SLOT; CmdTrbDisSlot.SlotId = SlotId; - Status = XhcCmdTransfer ( - Xhc, - (TRB_TEMPLATE *) (UINTN) &CmdTrbDisSlot, - XHC_GENERIC_TIMEOUT, - (TRB_TEMPLATE **) (UINTN) &EvtTrb - ); + Status = XhcCmdTransfer ( + Xhc, + (TRB_TEMPLATE *)(UINTN)&CmdTrbDisSlot, + XHC_GENERIC_TIMEOUT, + (TRB_TEMPLATE **)(UINTN)&EvtTrb + ); if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "XhcDisableSlotCmd: Disable Slot Command Failed, Status = %r\n", Status)); + DEBUG ((DEBUG_ERROR, "XhcDisableSlotCmd: Disable Slot Command Failed, Status = %r\n", Status)); return Status; } + // // Free the slot's device context entry // @@ -2425,6 +2626,7 @@ XhcDisableSlotCmd ( if (RingSeg != NULL) { UsbHcFreeMem (Xhc->MemPool, RingSeg, sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER); } + FreePool (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Index]); Xhc->UsbDevContext[SlotId].EndpointTransferRing[Index] = NULL; } @@ -2447,6 +2649,7 @@ XhcDisableSlotCmd ( if (Xhc->UsbDevContext[SlotId].OutputContext != NULL) { UsbHcFreeMem (Xhc->MemPool, Xhc->UsbDevContext[SlotId].OutputContext, sizeof (DEVICE_CONTEXT)); } + // // Doesn't zero the entry because XhcAsyncInterruptTransfer() may be invoked to remove the established // asynchronous interrupt pipe after the device is disabled. It needs the device address mapping info to @@ -2470,8 +2673,8 @@ XhcDisableSlotCmd ( EFI_STATUS EFIAPI XhcDisableSlotCmd64 ( - IN USB_XHCI_INSTANCE *Xhc, - IN UINT8 SlotId + IN USB_XHCI_INSTANCE *Xhc, + IN UINT8 SlotId ) { EFI_STATUS Status; @@ -2487,14 +2690,15 @@ XhcDisableSlotCmd64 ( for (Index = 0; Index < 255; Index++) { if (!Xhc->UsbDevContext[Index + 1].Enabled || (Xhc->UsbDevContext[Index + 1].SlotId == 0) || - (Xhc->UsbDevContext[Index + 1].ParentRouteString.Dword != Xhc->UsbDevContext[SlotId].RouteString.Dword)) { + (Xhc->UsbDevContext[Index + 1].ParentRouteString.Dword != Xhc->UsbDevContext[SlotId].RouteString.Dword)) + { continue; } Status = XhcDisableSlotCmd64 (Xhc, Xhc->UsbDevContext[Index + 1].SlotId); if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "XhcDisableSlotCmd: failed to disable child, ignore error\n")); + DEBUG ((DEBUG_ERROR, "XhcDisableSlotCmd: failed to disable child, ignore error\n")); Xhc->UsbDevContext[Index + 1].SlotId = 0; } } @@ -2502,22 +2706,23 @@ XhcDisableSlotCmd64 ( // // Construct the disable slot command // - DEBUG ((EFI_D_INFO, "Disable device slot %d!\n", SlotId)); + DEBUG ((DEBUG_INFO, "Disable device slot %d!\n", SlotId)); ZeroMem (&CmdTrbDisSlot, sizeof (CmdTrbDisSlot)); CmdTrbDisSlot.CycleBit = 1; CmdTrbDisSlot.Type = TRB_TYPE_DIS_SLOT; CmdTrbDisSlot.SlotId = SlotId; - Status = XhcCmdTransfer ( - Xhc, - (TRB_TEMPLATE *) (UINTN) &CmdTrbDisSlot, - XHC_GENERIC_TIMEOUT, - (TRB_TEMPLATE **) (UINTN) &EvtTrb - ); + Status = XhcCmdTransfer ( + Xhc, + (TRB_TEMPLATE *)(UINTN)&CmdTrbDisSlot, + XHC_GENERIC_TIMEOUT, + (TRB_TEMPLATE **)(UINTN)&EvtTrb + ); if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "XhcDisableSlotCmd: Disable Slot Command Failed, Status = %r\n", Status)); + DEBUG ((DEBUG_ERROR, "XhcDisableSlotCmd: Disable Slot Command Failed, Status = %r\n", Status)); return Status; } + // // Free the slot's device context entry // @@ -2532,6 +2737,7 @@ XhcDisableSlotCmd64 ( if (RingSeg != NULL) { UsbHcFreeMem (Xhc->MemPool, RingSeg, sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER); } + FreePool (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Index]); Xhc->UsbDevContext[SlotId].EndpointTransferRing[Index] = NULL; } @@ -2552,8 +2758,9 @@ XhcDisableSlotCmd64 ( } if (Xhc->UsbDevContext[SlotId].OutputContext != NULL) { - UsbHcFreeMem (Xhc->MemPool, Xhc->UsbDevContext[SlotId].OutputContext, sizeof (DEVICE_CONTEXT_64)); + UsbHcFreeMem (Xhc->MemPool, Xhc->UsbDevContext[SlotId].OutputContext, sizeof (DEVICE_CONTEXT_64)); } + // // Doesn't zero the entry because XhcAsyncInterruptTransfer() may be invoked to remove the established // asynchronous interrupt pipe after the device is disabled. It needs the device address mapping info to @@ -2580,27 +2787,30 @@ XhcDisableSlotCmd64 ( UINT8 EFIAPI XhcInitializeEndpointContext ( - IN USB_XHCI_INSTANCE *Xhc, - IN UINT8 SlotId, - IN UINT8 DeviceSpeed, - IN INPUT_CONTEXT *InputContext, - IN USB_INTERFACE_DESCRIPTOR *IfDesc + IN USB_XHCI_INSTANCE *Xhc, + IN UINT8 SlotId, + IN UINT8 DeviceSpeed, + IN INPUT_CONTEXT *InputContext, + IN USB_INTERFACE_DESCRIPTOR *IfDesc ) { - USB_ENDPOINT_DESCRIPTOR *EpDesc; - UINTN NumEp; - UINTN EpIndex; - UINT8 EpAddr; - UINT8 Direction; - UINT8 Dci; - UINT8 MaxDci; - EFI_PHYSICAL_ADDRESS PhyAddr; - UINT8 Interval; - TRANSFER_RING *EndpointTransferRing; + USB_ENDPOINT_DESCRIPTOR *EpDesc; + UINTN NumEp; + UINTN EpIndex; + UINT8 EpAddr; + UINT8 Direction; + UINT8 Dci; + UINT8 MaxDci; + EFI_PHYSICAL_ADDRESS PhyAddr; + UINT8 Interval; + TRANSFER_RING *EndpointTransferRing; MaxDci = 0; NumEp = IfDesc->NumEndpoints; + if (NumEp == 0) { + MaxDci = 1; + } EpDesc = (USB_ENDPOINT_DESCRIPTOR *)(IfDesc + 1); for (EpIndex = 0; EpIndex < NumEp; EpIndex++) { @@ -2646,9 +2856,16 @@ XhcInitializeEndpointContext ( InputContext->EP[Dci-1].AverageTRBLength = 0x1000; if (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1] == NULL) { - EndpointTransferRing = AllocateZeroPool(sizeof (TRANSFER_RING)); - Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1] = (VOID *) EndpointTransferRing; - CreateTransferRing(Xhc, TR_RING_TRB_NUMBER, (TRANSFER_RING *)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1]); + EndpointTransferRing = AllocateZeroPool (sizeof (TRANSFER_RING)); + Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1] = (VOID *)EndpointTransferRing; + CreateTransferRing (Xhc, TR_RING_TRB_NUMBER, (TRANSFER_RING *)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1]); + DEBUG (( + DEBUG_INFO, + "Endpoint[%x]: Created BULK ring [%p~%p)\n", + EpDesc->EndpointAddress, + EndpointTransferRing->RingSeg0, + (UINTN)EndpointTransferRing->RingSeg0 + TR_RING_TRB_NUMBER * sizeof (TRB_TEMPLATE) + )); } break; @@ -2660,6 +2877,7 @@ XhcInitializeEndpointContext ( InputContext->EP[Dci-1].CErr = 0; InputContext->EP[Dci-1].EPType = ED_ISOCH_OUT; } + // // Get the bInterval from descriptor and init the the interval field of endpoint context. // Refer to XHCI 1.1 spec section 6.2.3.6. @@ -2677,7 +2895,7 @@ XhcInitializeEndpointContext ( // // Do not support isochronous transfer now. // - DEBUG ((EFI_D_INFO, "XhcInitializeEndpointContext: Unsupport ISO EP found, Transfer ring is not allocated.\n")); + DEBUG ((DEBUG_INFO, "XhcInitializeEndpointContext: Unsupport ISO EP found, Transfer ring is not allocated.\n")); EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length); continue; case USB_ENDPOINT_INTERRUPT: @@ -2688,6 +2906,7 @@ XhcInitializeEndpointContext ( InputContext->EP[Dci-1].CErr = 3; InputContext->EP[Dci-1].EPType = ED_INTERRUPT_OUT; } + InputContext->EP[Dci-1].AverageTRBLength = 0x1000; InputContext->EP[Dci-1].MaxESITPayload = EpDesc->MaxPacketSize; // @@ -2699,7 +2918,7 @@ XhcInitializeEndpointContext ( // Calculate through the bInterval field of Endpoint descriptor. // ASSERT (Interval != 0); - InputContext->EP[Dci-1].Interval = (UINT32)HighBitSet32((UINT32)Interval) + 3; + InputContext->EP[Dci-1].Interval = (UINT32)HighBitSet32 ((UINT32)Interval) + 3; } else if ((DeviceSpeed == EFI_USB_SPEED_HIGH) || (DeviceSpeed == EFI_USB_SPEED_SUPER)) { Interval = EpDesc->Interval; ASSERT (Interval >= 1 && Interval <= 16); @@ -2714,19 +2933,27 @@ XhcInitializeEndpointContext ( } if (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1] == NULL) { - EndpointTransferRing = AllocateZeroPool(sizeof (TRANSFER_RING)); - Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1] = (VOID *) EndpointTransferRing; - CreateTransferRing(Xhc, TR_RING_TRB_NUMBER, (TRANSFER_RING *)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1]); + EndpointTransferRing = AllocateZeroPool (sizeof (TRANSFER_RING)); + Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1] = (VOID *)EndpointTransferRing; + CreateTransferRing (Xhc, TR_RING_TRB_NUMBER, (TRANSFER_RING *)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1]); + DEBUG (( + DEBUG_INFO, + "Endpoint[%x]: Created INT ring [%p~%p)\n", + EpDesc->EndpointAddress, + EndpointTransferRing->RingSeg0, + (UINTN)EndpointTransferRing->RingSeg0 + TR_RING_TRB_NUMBER * sizeof (TRB_TEMPLATE) + )); } + break; case USB_ENDPOINT_CONTROL: // // Do not support control transfer now. // - DEBUG ((EFI_D_INFO, "XhcInitializeEndpointContext: Unsupport Control EP found, Transfer ring is not allocated.\n")); + DEBUG ((DEBUG_INFO, "XhcInitializeEndpointContext: Unsupport Control EP found, Transfer ring is not allocated.\n")); default: - DEBUG ((EFI_D_INFO, "XhcInitializeEndpointContext: Unknown EP found, Transfer ring is not allocated.\n")); + DEBUG ((DEBUG_INFO, "XhcInitializeEndpointContext: Unknown EP found, Transfer ring is not allocated.\n")); EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length); continue; } @@ -2736,8 +2963,8 @@ XhcInitializeEndpointContext ( ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingSeg0, sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER ); - PhyAddr &= ~((EFI_PHYSICAL_ADDRESS)0x0F); - PhyAddr |= (EFI_PHYSICAL_ADDRESS)((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingPCS; + PhyAddr &= ~((EFI_PHYSICAL_ADDRESS)0x0F); + PhyAddr |= (EFI_PHYSICAL_ADDRESS)((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingPCS; InputContext->EP[Dci-1].PtrLo = XHC_LOW_32BIT (PhyAddr); InputContext->EP[Dci-1].PtrHi = XHC_HIGH_32BIT (PhyAddr); @@ -2762,27 +2989,30 @@ XhcInitializeEndpointContext ( UINT8 EFIAPI XhcInitializeEndpointContext64 ( - IN USB_XHCI_INSTANCE *Xhc, - IN UINT8 SlotId, - IN UINT8 DeviceSpeed, - IN INPUT_CONTEXT_64 *InputContext, - IN USB_INTERFACE_DESCRIPTOR *IfDesc + IN USB_XHCI_INSTANCE *Xhc, + IN UINT8 SlotId, + IN UINT8 DeviceSpeed, + IN INPUT_CONTEXT_64 *InputContext, + IN USB_INTERFACE_DESCRIPTOR *IfDesc ) { - USB_ENDPOINT_DESCRIPTOR *EpDesc; - UINTN NumEp; - UINTN EpIndex; - UINT8 EpAddr; - UINT8 Direction; - UINT8 Dci; - UINT8 MaxDci; - EFI_PHYSICAL_ADDRESS PhyAddr; - UINT8 Interval; - TRANSFER_RING *EndpointTransferRing; + USB_ENDPOINT_DESCRIPTOR *EpDesc; + UINTN NumEp; + UINTN EpIndex; + UINT8 EpAddr; + UINT8 Direction; + UINT8 Dci; + UINT8 MaxDci; + EFI_PHYSICAL_ADDRESS PhyAddr; + UINT8 Interval; + TRANSFER_RING *EndpointTransferRing; MaxDci = 0; NumEp = IfDesc->NumEndpoints; + if (NumEp == 0) { + MaxDci = 1; + } EpDesc = (USB_ENDPOINT_DESCRIPTOR *)(IfDesc + 1); for (EpIndex = 0; EpIndex < NumEp; EpIndex++) { @@ -2828,9 +3058,16 @@ XhcInitializeEndpointContext64 ( InputContext->EP[Dci-1].AverageTRBLength = 0x1000; if (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1] == NULL) { - EndpointTransferRing = AllocateZeroPool(sizeof (TRANSFER_RING)); - Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1] = (VOID *) EndpointTransferRing; - CreateTransferRing(Xhc, TR_RING_TRB_NUMBER, (TRANSFER_RING *)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1]); + EndpointTransferRing = AllocateZeroPool (sizeof (TRANSFER_RING)); + Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1] = (VOID *)EndpointTransferRing; + CreateTransferRing (Xhc, TR_RING_TRB_NUMBER, (TRANSFER_RING *)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1]); + DEBUG (( + DEBUG_INFO, + "Endpoint64[%x]: Created BULK ring [%p~%p)\n", + EpDesc->EndpointAddress, + EndpointTransferRing->RingSeg0, + (UINTN)EndpointTransferRing->RingSeg0 + TR_RING_TRB_NUMBER * sizeof (TRB_TEMPLATE) + )); } break; @@ -2842,6 +3079,7 @@ XhcInitializeEndpointContext64 ( InputContext->EP[Dci-1].CErr = 0; InputContext->EP[Dci-1].EPType = ED_ISOCH_OUT; } + // // Get the bInterval from descriptor and init the the interval field of endpoint context. // Refer to XHCI 1.1 spec section 6.2.3.6. @@ -2859,7 +3097,7 @@ XhcInitializeEndpointContext64 ( // // Do not support isochronous transfer now. // - DEBUG ((EFI_D_INFO, "XhcInitializeEndpointContext64: Unsupport ISO EP found, Transfer ring is not allocated.\n")); + DEBUG ((DEBUG_INFO, "XhcInitializeEndpointContext64: Unsupport ISO EP found, Transfer ring is not allocated.\n")); EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length); continue; case USB_ENDPOINT_INTERRUPT: @@ -2870,6 +3108,7 @@ XhcInitializeEndpointContext64 ( InputContext->EP[Dci-1].CErr = 3; InputContext->EP[Dci-1].EPType = ED_INTERRUPT_OUT; } + InputContext->EP[Dci-1].AverageTRBLength = 0x1000; InputContext->EP[Dci-1].MaxESITPayload = EpDesc->MaxPacketSize; // @@ -2881,7 +3120,7 @@ XhcInitializeEndpointContext64 ( // Calculate through the bInterval field of Endpoint descriptor. // ASSERT (Interval != 0); - InputContext->EP[Dci-1].Interval = (UINT32)HighBitSet32((UINT32)Interval) + 3; + InputContext->EP[Dci-1].Interval = (UINT32)HighBitSet32 ((UINT32)Interval) + 3; } else if ((DeviceSpeed == EFI_USB_SPEED_HIGH) || (DeviceSpeed == EFI_USB_SPEED_SUPER)) { Interval = EpDesc->Interval; ASSERT (Interval >= 1 && Interval <= 16); @@ -2896,19 +3135,27 @@ XhcInitializeEndpointContext64 ( } if (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1] == NULL) { - EndpointTransferRing = AllocateZeroPool(sizeof (TRANSFER_RING)); - Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1] = (VOID *) EndpointTransferRing; - CreateTransferRing(Xhc, TR_RING_TRB_NUMBER, (TRANSFER_RING *)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1]); + EndpointTransferRing = AllocateZeroPool (sizeof (TRANSFER_RING)); + Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1] = (VOID *)EndpointTransferRing; + CreateTransferRing (Xhc, TR_RING_TRB_NUMBER, (TRANSFER_RING *)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1]); + DEBUG (( + DEBUG_INFO, + "Endpoint64[%x]: Created INT ring [%p~%p)\n", + EpDesc->EndpointAddress, + EndpointTransferRing->RingSeg0, + (UINTN)EndpointTransferRing->RingSeg0 + TR_RING_TRB_NUMBER * sizeof (TRB_TEMPLATE) + )); } + break; case USB_ENDPOINT_CONTROL: // // Do not support control transfer now. // - DEBUG ((EFI_D_INFO, "XhcInitializeEndpointContext64: Unsupport Control EP found, Transfer ring is not allocated.\n")); + DEBUG ((DEBUG_INFO, "XhcInitializeEndpointContext64: Unsupport Control EP found, Transfer ring is not allocated.\n")); default: - DEBUG ((EFI_D_INFO, "XhcInitializeEndpointContext64: Unknown EP found, Transfer ring is not allocated.\n")); + DEBUG ((DEBUG_INFO, "XhcInitializeEndpointContext64: Unknown EP found, Transfer ring is not allocated.\n")); EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length); continue; } @@ -2918,8 +3165,8 @@ XhcInitializeEndpointContext64 ( ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingSeg0, sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER ); - PhyAddr &= ~((EFI_PHYSICAL_ADDRESS)0x0F); - PhyAddr |= (EFI_PHYSICAL_ADDRESS)((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingPCS; + PhyAddr &= ~((EFI_PHYSICAL_ADDRESS)0x0F); + PhyAddr |= (EFI_PHYSICAL_ADDRESS)((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingPCS; InputContext->EP[Dci-1].PtrLo = XHC_LOW_32BIT (PhyAddr); InputContext->EP[Dci-1].PtrHi = XHC_HIGH_32BIT (PhyAddr); @@ -2943,23 +3190,24 @@ XhcInitializeEndpointContext64 ( EFI_STATUS EFIAPI XhcSetConfigCmd ( - IN USB_XHCI_INSTANCE *Xhc, - IN UINT8 SlotId, - IN UINT8 DeviceSpeed, - IN USB_CONFIG_DESCRIPTOR *ConfigDesc + IN USB_XHCI_INSTANCE *Xhc, + IN UINT8 SlotId, + IN UINT8 DeviceSpeed, + IN USB_CONFIG_DESCRIPTOR *ConfigDesc ) { - EFI_STATUS Status; - USB_INTERFACE_DESCRIPTOR *IfDesc; - UINT8 Index; - UINT8 Dci; - UINT8 MaxDci; - EFI_PHYSICAL_ADDRESS PhyAddr; + EFI_STATUS Status; + USB_INTERFACE_DESCRIPTOR *IfDesc; + UINT8 Index; + UINT8 Dci; + UINT8 MaxDci; + EFI_PHYSICAL_ADDRESS PhyAddr; CMD_TRB_CONFIG_ENDPOINT CmdTrbCfgEP; INPUT_CONTEXT *InputContext; DEVICE_CONTEXT *OutputContext; EVT_TRB_COMMAND_COMPLETION *EvtTrb; + // // 4.6.6 Configure Endpoint // @@ -2997,21 +3245,21 @@ XhcSetConfigCmd ( // configure endpoint // ZeroMem (&CmdTrbCfgEP, sizeof (CmdTrbCfgEP)); - PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, InputContext, sizeof (INPUT_CONTEXT)); + PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, InputContext, sizeof (INPUT_CONTEXT)); CmdTrbCfgEP.PtrLo = XHC_LOW_32BIT (PhyAddr); CmdTrbCfgEP.PtrHi = XHC_HIGH_32BIT (PhyAddr); CmdTrbCfgEP.CycleBit = 1; CmdTrbCfgEP.Type = TRB_TYPE_CON_ENDPOINT; CmdTrbCfgEP.SlotId = Xhc->UsbDevContext[SlotId].SlotId; - DEBUG ((EFI_D_INFO, "Configure Endpoint\n")); + DEBUG ((DEBUG_INFO, "Configure Endpoint\n")); Status = XhcCmdTransfer ( Xhc, - (TRB_TEMPLATE *) (UINTN) &CmdTrbCfgEP, + (TRB_TEMPLATE *)(UINTN)&CmdTrbCfgEP, XHC_GENERIC_TIMEOUT, - (TRB_TEMPLATE **) (UINTN) &EvtTrb + (TRB_TEMPLATE **)(UINTN)&EvtTrb ); if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "XhcSetConfigCmd: Config Endpoint Failed, Status = %r\n", Status)); + DEBUG ((DEBUG_ERROR, "XhcSetConfigCmd: Config Endpoint Failed, Status = %r\n", Status)); } else { Xhc->UsbDevContext[SlotId].ActiveConfiguration = ConfigDesc->ConfigurationValue; } @@ -3033,23 +3281,24 @@ XhcSetConfigCmd ( EFI_STATUS EFIAPI XhcSetConfigCmd64 ( - IN USB_XHCI_INSTANCE *Xhc, - IN UINT8 SlotId, - IN UINT8 DeviceSpeed, - IN USB_CONFIG_DESCRIPTOR *ConfigDesc + IN USB_XHCI_INSTANCE *Xhc, + IN UINT8 SlotId, + IN UINT8 DeviceSpeed, + IN USB_CONFIG_DESCRIPTOR *ConfigDesc ) { - EFI_STATUS Status; - USB_INTERFACE_DESCRIPTOR *IfDesc; - UINT8 Index; - UINT8 Dci; - UINT8 MaxDci; - EFI_PHYSICAL_ADDRESS PhyAddr; + EFI_STATUS Status; + USB_INTERFACE_DESCRIPTOR *IfDesc; + UINT8 Index; + UINT8 Dci; + UINT8 MaxDci; + EFI_PHYSICAL_ADDRESS PhyAddr; CMD_TRB_CONFIG_ENDPOINT CmdTrbCfgEP; INPUT_CONTEXT_64 *InputContext; DEVICE_CONTEXT_64 *OutputContext; EVT_TRB_COMMAND_COMPLETION *EvtTrb; + // // 4.6.6 Configure Endpoint // @@ -3077,7 +3326,7 @@ XhcSetConfigCmd64 ( if (Dci > MaxDci) { MaxDci = Dci; } - + IfDesc = (USB_INTERFACE_DESCRIPTOR *)((UINTN)IfDesc + IfDesc->Length); } @@ -3087,21 +3336,21 @@ XhcSetConfigCmd64 ( // configure endpoint // ZeroMem (&CmdTrbCfgEP, sizeof (CmdTrbCfgEP)); - PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, InputContext, sizeof (INPUT_CONTEXT_64)); + PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, InputContext, sizeof (INPUT_CONTEXT_64)); CmdTrbCfgEP.PtrLo = XHC_LOW_32BIT (PhyAddr); CmdTrbCfgEP.PtrHi = XHC_HIGH_32BIT (PhyAddr); CmdTrbCfgEP.CycleBit = 1; CmdTrbCfgEP.Type = TRB_TYPE_CON_ENDPOINT; CmdTrbCfgEP.SlotId = Xhc->UsbDevContext[SlotId].SlotId; - DEBUG ((EFI_D_INFO, "Configure Endpoint\n")); + DEBUG ((DEBUG_INFO, "Configure Endpoint\n")); Status = XhcCmdTransfer ( Xhc, - (TRB_TEMPLATE *) (UINTN) &CmdTrbCfgEP, + (TRB_TEMPLATE *)(UINTN)&CmdTrbCfgEP, XHC_GENERIC_TIMEOUT, - (TRB_TEMPLATE **) (UINTN) &EvtTrb + (TRB_TEMPLATE **)(UINTN)&EvtTrb ); if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "XhcSetConfigCmd64: Config Endpoint Failed, Status = %r\n", Status)); + DEBUG ((DEBUG_ERROR, "XhcSetConfigCmd64: Config Endpoint Failed, Status = %r\n", Status)); } else { Xhc->UsbDevContext[SlotId].ActiveConfiguration = ConfigDesc->ConfigurationValue; } @@ -3115,6 +3364,7 @@ XhcSetConfigCmd64 ( @param Xhc The XHCI Instance. @param SlotId The slot id to be configured. @param Dci The device context index of endpoint. + @param PendingUrb The pending URB to check completion status when stopping the end point. @retval EFI_SUCCESS Stop endpoint successfully. @retval Others Failed to stop endpoint. @@ -3123,16 +3373,40 @@ XhcSetConfigCmd64 ( EFI_STATUS EFIAPI XhcStopEndpoint ( - IN USB_XHCI_INSTANCE *Xhc, - IN UINT8 SlotId, - IN UINT8 Dci + IN USB_XHCI_INSTANCE *Xhc, + IN UINT8 SlotId, + IN UINT8 Dci, + IN URB *PendingUrb OPTIONAL ) { - EFI_STATUS Status; - EVT_TRB_COMMAND_COMPLETION *EvtTrb; - CMD_TRB_STOP_ENDPOINT CmdTrbStopED; + EFI_STATUS Status; + EVT_TRB_COMMAND_COMPLETION *EvtTrb; + CMD_TRB_STOP_ENDPOINT CmdTrbStopED; - DEBUG ((EFI_D_INFO, "XhcStopEndpoint: Slot = 0x%x, Dci = 0x%x\n", SlotId, Dci)); + DEBUG ((DEBUG_VERBOSE, "XhcStopEndpoint: Slot = 0x%x, Dci = 0x%x\n", SlotId, Dci)); + + // + // When XhcCheckUrbResult waits for the Stop_Endpoint completion, it also checks + // the PendingUrb completion status, because it's possible that the PendingUrb is + // finished just before stopping the end point, but after the looping check. + // + // The PendingUrb could be passed to XhcCmdTransfer to XhcExecTransfer to XhcCheckUrbResult + // through function parameter, but That will cause every consumer of XhcCmdTransfer, + // XhcExecTransfer and XhcCheckUrbResult pass a NULL PendingUrb. + // But actually only XhcCheckUrbResult is aware of the PendingUrb. + // So we choose to save the PendingUrb into the USB_XHCI_INSTANCE and use it in XhcCheckUrbResult. + // + ASSERT (Xhc->PendingUrb == NULL); + Xhc->PendingUrb = PendingUrb; + // + // Reset the URB result from Timeout to NoError. + // The USB result will be: + // changed to Timeout when Stop/StopInvalidLength Transfer Event is received, or + // remain NoError when Success/ShortPacket Transfer Event is received. + // + if (PendingUrb != NULL) { + PendingUrb->Result = EFI_USB_NOERROR; + } // // Send stop endpoint command to transit Endpoint from running to stop state @@ -3142,16 +3416,18 @@ XhcStopEndpoint ( CmdTrbStopED.Type = TRB_TYPE_STOP_ENDPOINT; CmdTrbStopED.EDID = Dci; CmdTrbStopED.SlotId = SlotId; - Status = XhcCmdTransfer ( - Xhc, - (TRB_TEMPLATE *) (UINTN) &CmdTrbStopED, - XHC_GENERIC_TIMEOUT, - (TRB_TEMPLATE **) (UINTN) &EvtTrb - ); - if (EFI_ERROR(Status)) { - DEBUG ((EFI_D_ERROR, "XhcStopEndpoint: Stop Endpoint Failed, Status = %r\n", Status)); + Status = XhcCmdTransfer ( + Xhc, + (TRB_TEMPLATE *)(UINTN)&CmdTrbStopED, + XHC_GENERIC_TIMEOUT, + (TRB_TEMPLATE **)(UINTN)&EvtTrb + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "XhcStopEndpoint: Stop Endpoint Failed, Status = %r\n", Status)); } + Xhc->PendingUrb = NULL; + return Status; } @@ -3169,16 +3445,16 @@ XhcStopEndpoint ( EFI_STATUS EFIAPI XhcResetEndpoint ( - IN USB_XHCI_INSTANCE *Xhc, - IN UINT8 SlotId, - IN UINT8 Dci + IN USB_XHCI_INSTANCE *Xhc, + IN UINT8 SlotId, + IN UINT8 Dci ) { EFI_STATUS Status; EVT_TRB_COMMAND_COMPLETION *EvtTrb; CMD_TRB_RESET_ENDPOINT CmdTrbResetED; - DEBUG ((EFI_D_INFO, "XhcResetEndpoint: Slot = 0x%x, Dci = 0x%x\n", SlotId, Dci)); + DEBUG ((DEBUG_INFO, "XhcResetEndpoint: Slot = 0x%x, Dci = 0x%x\n", SlotId, Dci)); // // Send stop endpoint command to transit Endpoint from running to stop state @@ -3188,14 +3464,14 @@ XhcResetEndpoint ( CmdTrbResetED.Type = TRB_TYPE_RESET_ENDPOINT; CmdTrbResetED.EDID = Dci; CmdTrbResetED.SlotId = SlotId; - Status = XhcCmdTransfer ( - Xhc, - (TRB_TEMPLATE *) (UINTN) &CmdTrbResetED, - XHC_GENERIC_TIMEOUT, - (TRB_TEMPLATE **) (UINTN) &EvtTrb - ); - if (EFI_ERROR(Status)) { - DEBUG ((EFI_D_ERROR, "XhcResetEndpoint: Reset Endpoint Failed, Status = %r\n", Status)); + Status = XhcCmdTransfer ( + Xhc, + (TRB_TEMPLATE *)(UINTN)&CmdTrbResetED, + XHC_GENERIC_TIMEOUT, + (TRB_TEMPLATE **)(UINTN)&EvtTrb + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "XhcResetEndpoint: Reset Endpoint Failed, Status = %r\n", Status)); } return Status; @@ -3217,10 +3493,10 @@ XhcResetEndpoint ( EFI_STATUS EFIAPI XhcSetTrDequeuePointer ( - IN USB_XHCI_INSTANCE *Xhc, - IN UINT8 SlotId, - IN UINT8 Dci, - IN URB *Urb + IN USB_XHCI_INSTANCE *Xhc, + IN UINT8 SlotId, + IN UINT8 Dci, + IN URB *Urb ) { EFI_STATUS Status; @@ -3228,27 +3504,27 @@ XhcSetTrDequeuePointer ( CMD_SET_TR_DEQ_POINTER CmdSetTRDeq; EFI_PHYSICAL_ADDRESS PhyAddr; - DEBUG ((EFI_D_INFO, "XhcSetTrDequeuePointer: Slot = 0x%x, Dci = 0x%x, Urb = 0x%x\n", SlotId, Dci, Urb)); + DEBUG ((DEBUG_VERBOSE, "XhcSetTrDequeuePointer: Slot = 0x%x, Dci = 0x%x, Urb = 0x%x\n", SlotId, Dci, Urb)); // // Send stop endpoint command to transit Endpoint from running to stop state // ZeroMem (&CmdSetTRDeq, sizeof (CmdSetTRDeq)); - PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Urb->Ring->RingEnqueue, sizeof (CMD_SET_TR_DEQ_POINTER)); + PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Urb->Ring->RingEnqueue, sizeof (CMD_SET_TR_DEQ_POINTER)); CmdSetTRDeq.PtrLo = XHC_LOW_32BIT (PhyAddr) | Urb->Ring->RingPCS; CmdSetTRDeq.PtrHi = XHC_HIGH_32BIT (PhyAddr); CmdSetTRDeq.CycleBit = 1; CmdSetTRDeq.Type = TRB_TYPE_SET_TR_DEQUE; CmdSetTRDeq.Endpoint = Dci; CmdSetTRDeq.SlotId = SlotId; - Status = XhcCmdTransfer ( - Xhc, - (TRB_TEMPLATE *) (UINTN) &CmdSetTRDeq, - XHC_GENERIC_TIMEOUT, - (TRB_TEMPLATE **) (UINTN) &EvtTrb - ); - if (EFI_ERROR(Status)) { - DEBUG ((EFI_D_ERROR, "XhcSetTrDequeuePointer: Set TR Dequeue Pointer Failed, Status = %r\n", Status)); + Status = XhcCmdTransfer ( + Xhc, + (TRB_TEMPLATE *)(UINTN)&CmdSetTRDeq, + XHC_GENERIC_TIMEOUT, + (TRB_TEMPLATE **)(UINTN)&EvtTrb + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "XhcSetTrDequeuePointer: Set TR Dequeue Pointer Failed, Status = %r\n", Status)); } return Status; @@ -3269,26 +3545,26 @@ XhcSetTrDequeuePointer ( EFI_STATUS EFIAPI XhcSetInterface ( - IN USB_XHCI_INSTANCE *Xhc, - IN UINT8 SlotId, - IN UINT8 DeviceSpeed, - IN USB_CONFIG_DESCRIPTOR *ConfigDesc, - IN EFI_USB_DEVICE_REQUEST *Request + IN USB_XHCI_INSTANCE *Xhc, + IN UINT8 SlotId, + IN UINT8 DeviceSpeed, + IN USB_CONFIG_DESCRIPTOR *ConfigDesc, + IN EFI_USB_DEVICE_REQUEST *Request ) { - EFI_STATUS Status; - USB_INTERFACE_DESCRIPTOR *IfDescActive; - USB_INTERFACE_DESCRIPTOR *IfDescSet; - USB_INTERFACE_DESCRIPTOR *IfDesc; - USB_ENDPOINT_DESCRIPTOR *EpDesc; - UINTN NumEp; - UINTN EpIndex; - UINT8 EpAddr; - UINT8 Direction; - UINT8 Dci; - UINT8 MaxDci; - EFI_PHYSICAL_ADDRESS PhyAddr; - VOID *RingSeg; + EFI_STATUS Status; + USB_INTERFACE_DESCRIPTOR *IfDescActive; + USB_INTERFACE_DESCRIPTOR *IfDescSet; + USB_INTERFACE_DESCRIPTOR *IfDesc; + USB_ENDPOINT_DESCRIPTOR *EpDesc; + UINTN NumEp; + UINTN EpIndex; + UINT8 EpAddr; + UINT8 Direction; + UINT8 Dci; + UINT8 MaxDci; + EFI_PHYSICAL_ADDRESS PhyAddr; + VOID *RingSeg; CMD_TRB_CONFIG_ENDPOINT CmdTrbCfgEP; INPUT_CONTEXT *InputContext; @@ -3317,18 +3593,18 @@ XhcSetInterface ( MaxDci = 0; IfDescActive = NULL; - IfDescSet = NULL; + IfDescSet = NULL; IfDesc = (USB_INTERFACE_DESCRIPTOR *)(ConfigDesc + 1); - while ((UINTN) IfDesc < ((UINTN) ConfigDesc + ConfigDesc->TotalLength)) { + while ((UINTN)IfDesc < ((UINTN)ConfigDesc + ConfigDesc->TotalLength)) { if ((IfDesc->DescriptorType == USB_DESC_TYPE_INTERFACE) && (IfDesc->Length >= sizeof (USB_INTERFACE_DESCRIPTOR))) { - if (IfDesc->InterfaceNumber == (UINT8) Request->Index) { + if (IfDesc->InterfaceNumber == (UINT8)Request->Index) { if (IfDesc->AlternateSetting == Xhc->UsbDevContext[SlotId].ActiveAlternateSetting[IfDesc->InterfaceNumber]) { // // Find out the active interface descriptor. // IfDescActive = IfDesc; - } else if (IfDesc->AlternateSetting == (UINT8) Request->Value) { + } else if (IfDesc->AlternateSetting == (UINT8)Request->Value) { // // Find out the interface descriptor to set. // @@ -3336,6 +3612,7 @@ XhcSetInterface ( } } } + IfDesc = (USB_INTERFACE_DESCRIPTOR *)((UINTN)IfDesc + IfDesc->Length); } @@ -3354,8 +3631,8 @@ XhcSetInterface ( // if ((IfDescActive != NULL) && (IfDescSet != NULL)) { - NumEp = IfDescActive->NumEndpoints; - EpDesc = (USB_ENDPOINT_DESCRIPTOR *) (IfDescActive + 1); + NumEp = IfDescActive->NumEndpoints; + EpDesc = (USB_ENDPOINT_DESCRIPTOR *)(IfDescActive + 1); for (EpIndex = 0; EpIndex < NumEp; EpIndex++) { while (EpDesc->DescriptorType != USB_DESC_TYPE_ENDPOINT) { EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length); @@ -3366,22 +3643,24 @@ XhcSetInterface ( continue; } - EpAddr = (UINT8) (EpDesc->EndpointAddress & 0x0F); - Direction = (UINT8) ((EpDesc->EndpointAddress & 0x80) ? EfiUsbDataIn : EfiUsbDataOut); + EpAddr = (UINT8)(EpDesc->EndpointAddress & 0x0F); + Direction = (UINT8)((EpDesc->EndpointAddress & 0x80) ? EfiUsbDataIn : EfiUsbDataOut); Dci = XhcEndpointToDci (EpAddr, Direction); ASSERT (Dci < 32); if (Dci > MaxDci) { MaxDci = Dci; } + // // XHCI 4.3.6 - Setting Alternate Interfaces // 1) Stop any Running Transfer Rings affected by the Alternate Interface setting. // - Status = XhcStopEndpoint (Xhc, SlotId, Dci); + Status = XhcStopEndpoint (Xhc, SlotId, Dci, NULL); if (EFI_ERROR (Status)) { return Status; } + // // XHCI 4.3.6 - Setting Alternate Interfaces // 2) Free Transfer Rings of all endpoints that will be affected by the Alternate Interface setting. @@ -3391,6 +3670,7 @@ XhcSetInterface ( if (RingSeg != NULL) { UsbHcFreeMem (Xhc->MemPool, RingSeg, sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER); } + FreePool (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci - 1]); Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci - 1] = NULL; } @@ -3430,26 +3710,26 @@ XhcSetInterface ( // 5) Issue and successfully complete a Configure Endpoint Command. // ZeroMem (&CmdTrbCfgEP, sizeof (CmdTrbCfgEP)); - PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, InputContext, sizeof (INPUT_CONTEXT)); + PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, InputContext, sizeof (INPUT_CONTEXT)); CmdTrbCfgEP.PtrLo = XHC_LOW_32BIT (PhyAddr); CmdTrbCfgEP.PtrHi = XHC_HIGH_32BIT (PhyAddr); CmdTrbCfgEP.CycleBit = 1; CmdTrbCfgEP.Type = TRB_TYPE_CON_ENDPOINT; CmdTrbCfgEP.SlotId = Xhc->UsbDevContext[SlotId].SlotId; - DEBUG ((EFI_D_INFO, "SetInterface: Configure Endpoint\n")); + DEBUG ((DEBUG_INFO, "SetInterface: Configure Endpoint\n")); Status = XhcCmdTransfer ( Xhc, - (TRB_TEMPLATE *) (UINTN) &CmdTrbCfgEP, + (TRB_TEMPLATE *)(UINTN)&CmdTrbCfgEP, XHC_GENERIC_TIMEOUT, - (TRB_TEMPLATE **) (UINTN) &EvtTrb + (TRB_TEMPLATE **)(UINTN)&EvtTrb ); if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "SetInterface: Config Endpoint Failed, Status = %r\n", Status)); + DEBUG ((DEBUG_ERROR, "SetInterface: Config Endpoint Failed, Status = %r\n", Status)); } else { // // Update the active AlternateSetting. // - Xhc->UsbDevContext[SlotId].ActiveAlternateSetting[(UINT8) Request->Index] = (UINT8) Request->Value; + Xhc->UsbDevContext[SlotId].ActiveAlternateSetting[(UINT8)Request->Index] = (UINT8)Request->Value; } } @@ -3471,26 +3751,26 @@ XhcSetInterface ( EFI_STATUS EFIAPI XhcSetInterface64 ( - IN USB_XHCI_INSTANCE *Xhc, - IN UINT8 SlotId, - IN UINT8 DeviceSpeed, - IN USB_CONFIG_DESCRIPTOR *ConfigDesc, - IN EFI_USB_DEVICE_REQUEST *Request + IN USB_XHCI_INSTANCE *Xhc, + IN UINT8 SlotId, + IN UINT8 DeviceSpeed, + IN USB_CONFIG_DESCRIPTOR *ConfigDesc, + IN EFI_USB_DEVICE_REQUEST *Request ) { - EFI_STATUS Status; - USB_INTERFACE_DESCRIPTOR *IfDescActive; - USB_INTERFACE_DESCRIPTOR *IfDescSet; - USB_INTERFACE_DESCRIPTOR *IfDesc; - USB_ENDPOINT_DESCRIPTOR *EpDesc; - UINTN NumEp; - UINTN EpIndex; - UINT8 EpAddr; - UINT8 Direction; - UINT8 Dci; - UINT8 MaxDci; - EFI_PHYSICAL_ADDRESS PhyAddr; - VOID *RingSeg; + EFI_STATUS Status; + USB_INTERFACE_DESCRIPTOR *IfDescActive; + USB_INTERFACE_DESCRIPTOR *IfDescSet; + USB_INTERFACE_DESCRIPTOR *IfDesc; + USB_ENDPOINT_DESCRIPTOR *EpDesc; + UINTN NumEp; + UINTN EpIndex; + UINT8 EpAddr; + UINT8 Direction; + UINT8 Dci; + UINT8 MaxDci; + EFI_PHYSICAL_ADDRESS PhyAddr; + VOID *RingSeg; CMD_TRB_CONFIG_ENDPOINT CmdTrbCfgEP; INPUT_CONTEXT_64 *InputContext; @@ -3519,18 +3799,18 @@ XhcSetInterface64 ( MaxDci = 0; IfDescActive = NULL; - IfDescSet = NULL; + IfDescSet = NULL; IfDesc = (USB_INTERFACE_DESCRIPTOR *)(ConfigDesc + 1); - while ((UINTN) IfDesc < ((UINTN) ConfigDesc + ConfigDesc->TotalLength)) { + while ((UINTN)IfDesc < ((UINTN)ConfigDesc + ConfigDesc->TotalLength)) { if ((IfDesc->DescriptorType == USB_DESC_TYPE_INTERFACE) && (IfDesc->Length >= sizeof (USB_INTERFACE_DESCRIPTOR))) { - if (IfDesc->InterfaceNumber == (UINT8) Request->Index) { + if (IfDesc->InterfaceNumber == (UINT8)Request->Index) { if (IfDesc->AlternateSetting == Xhc->UsbDevContext[SlotId].ActiveAlternateSetting[IfDesc->InterfaceNumber]) { // // Find out the active interface descriptor. // IfDescActive = IfDesc; - } else if (IfDesc->AlternateSetting == (UINT8) Request->Value) { + } else if (IfDesc->AlternateSetting == (UINT8)Request->Value) { // // Find out the interface descriptor to set. // @@ -3538,6 +3818,7 @@ XhcSetInterface64 ( } } } + IfDesc = (USB_INTERFACE_DESCRIPTOR *)((UINTN)IfDesc + IfDesc->Length); } @@ -3556,8 +3837,8 @@ XhcSetInterface64 ( // if ((IfDescActive != NULL) && (IfDescSet != NULL)) { - NumEp = IfDescActive->NumEndpoints; - EpDesc = (USB_ENDPOINT_DESCRIPTOR *) (IfDescActive + 1); + NumEp = IfDescActive->NumEndpoints; + EpDesc = (USB_ENDPOINT_DESCRIPTOR *)(IfDescActive + 1); for (EpIndex = 0; EpIndex < NumEp; EpIndex++) { while (EpDesc->DescriptorType != USB_DESC_TYPE_ENDPOINT) { EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length); @@ -3568,22 +3849,24 @@ XhcSetInterface64 ( continue; } - EpAddr = (UINT8) (EpDesc->EndpointAddress & 0x0F); - Direction = (UINT8) ((EpDesc->EndpointAddress & 0x80) ? EfiUsbDataIn : EfiUsbDataOut); + EpAddr = (UINT8)(EpDesc->EndpointAddress & 0x0F); + Direction = (UINT8)((EpDesc->EndpointAddress & 0x80) ? EfiUsbDataIn : EfiUsbDataOut); Dci = XhcEndpointToDci (EpAddr, Direction); ASSERT (Dci < 32); if (Dci > MaxDci) { MaxDci = Dci; } + // // XHCI 4.3.6 - Setting Alternate Interfaces // 1) Stop any Running Transfer Rings affected by the Alternate Interface setting. // - Status = XhcStopEndpoint (Xhc, SlotId, Dci); + Status = XhcStopEndpoint (Xhc, SlotId, Dci, NULL); if (EFI_ERROR (Status)) { return Status; } + // // XHCI 4.3.6 - Setting Alternate Interfaces // 2) Free Transfer Rings of all endpoints that will be affected by the Alternate Interface setting. @@ -3593,6 +3876,7 @@ XhcSetInterface64 ( if (RingSeg != NULL) { UsbHcFreeMem (Xhc->MemPool, RingSeg, sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER); } + FreePool (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci - 1]); Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci - 1] = NULL; } @@ -3632,26 +3916,26 @@ XhcSetInterface64 ( // 5) Issue and successfully complete a Configure Endpoint Command. // ZeroMem (&CmdTrbCfgEP, sizeof (CmdTrbCfgEP)); - PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, InputContext, sizeof (INPUT_CONTEXT_64)); + PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, InputContext, sizeof (INPUT_CONTEXT_64)); CmdTrbCfgEP.PtrLo = XHC_LOW_32BIT (PhyAddr); CmdTrbCfgEP.PtrHi = XHC_HIGH_32BIT (PhyAddr); CmdTrbCfgEP.CycleBit = 1; CmdTrbCfgEP.Type = TRB_TYPE_CON_ENDPOINT; CmdTrbCfgEP.SlotId = Xhc->UsbDevContext[SlotId].SlotId; - DEBUG ((EFI_D_INFO, "SetInterface64: Configure Endpoint\n")); + DEBUG ((DEBUG_INFO, "SetInterface64: Configure Endpoint\n")); Status = XhcCmdTransfer ( Xhc, - (TRB_TEMPLATE *) (UINTN) &CmdTrbCfgEP, + (TRB_TEMPLATE *)(UINTN)&CmdTrbCfgEP, XHC_GENERIC_TIMEOUT, - (TRB_TEMPLATE **) (UINTN) &EvtTrb + (TRB_TEMPLATE **)(UINTN)&EvtTrb ); if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "SetInterface64: Config Endpoint Failed, Status = %r\n", Status)); + DEBUG ((DEBUG_ERROR, "SetInterface64: Config Endpoint Failed, Status = %r\n", Status)); } else { // // Update the active AlternateSetting. // - Xhc->UsbDevContext[SlotId].ActiveAlternateSetting[(UINT8) Request->Index] = (UINT8) Request->Value; + Xhc->UsbDevContext[SlotId].ActiveAlternateSetting[(UINT8)Request->Index] = (UINT8)Request->Value; } } @@ -3671,15 +3955,16 @@ XhcSetInterface64 ( EFI_STATUS EFIAPI XhcEvaluateContext ( - IN USB_XHCI_INSTANCE *Xhc, - IN UINT8 SlotId, - IN UINT32 MaxPacketSize + IN USB_XHCI_INSTANCE *Xhc, + IN UINT8 SlotId, + IN UINT32 MaxPacketSize ) { EFI_STATUS Status; CMD_TRB_EVALUATE_CONTEXT CmdTrbEvalu; EVT_TRB_COMMAND_COMPLETION *EvtTrb; INPUT_CONTEXT *InputContext; + DEVICE_CONTEXT *OutputContext; EFI_PHYSICAL_ADDRESS PhyAddr; ASSERT (Xhc->UsbDevContext[SlotId].SlotId != 0); @@ -3687,29 +3972,34 @@ XhcEvaluateContext ( // // 4.6.7 Evaluate Context // - InputContext = Xhc->UsbDevContext[SlotId].InputContext; + InputContext = Xhc->UsbDevContext[SlotId].InputContext; + OutputContext = Xhc->UsbDevContext[SlotId].OutputContext; ZeroMem (InputContext, sizeof (INPUT_CONTEXT)); + CopyMem (&InputContext->EP[0], &OutputContext->EP[0], sizeof (ENDPOINT_CONTEXT)); + InputContext->InputControlContext.Dword2 |= BIT1; InputContext->EP[0].MaxPacketSize = MaxPacketSize; + InputContext->EP[0].EPState = 0; ZeroMem (&CmdTrbEvalu, sizeof (CmdTrbEvalu)); - PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, InputContext, sizeof (INPUT_CONTEXT)); + PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, InputContext, sizeof (INPUT_CONTEXT)); CmdTrbEvalu.PtrLo = XHC_LOW_32BIT (PhyAddr); CmdTrbEvalu.PtrHi = XHC_HIGH_32BIT (PhyAddr); CmdTrbEvalu.CycleBit = 1; CmdTrbEvalu.Type = TRB_TYPE_EVALU_CONTXT; CmdTrbEvalu.SlotId = Xhc->UsbDevContext[SlotId].SlotId; - DEBUG ((EFI_D_INFO, "Evaluate context\n")); + DEBUG ((DEBUG_INFO, "Evaluate context\n")); Status = XhcCmdTransfer ( Xhc, - (TRB_TEMPLATE *) (UINTN) &CmdTrbEvalu, + (TRB_TEMPLATE *)(UINTN)&CmdTrbEvalu, XHC_GENERIC_TIMEOUT, - (TRB_TEMPLATE **) (UINTN) &EvtTrb + (TRB_TEMPLATE **)(UINTN)&EvtTrb ); if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "XhcEvaluateContext: Evaluate Context Failed, Status = %r\n", Status)); + DEBUG ((DEBUG_ERROR, "XhcEvaluateContext: Evaluate Context Failed, Status = %r\n", Status)); } + return Status; } @@ -3726,15 +4016,16 @@ XhcEvaluateContext ( EFI_STATUS EFIAPI XhcEvaluateContext64 ( - IN USB_XHCI_INSTANCE *Xhc, - IN UINT8 SlotId, - IN UINT32 MaxPacketSize + IN USB_XHCI_INSTANCE *Xhc, + IN UINT8 SlotId, + IN UINT32 MaxPacketSize ) { EFI_STATUS Status; CMD_TRB_EVALUATE_CONTEXT CmdTrbEvalu; EVT_TRB_COMMAND_COMPLETION *EvtTrb; INPUT_CONTEXT_64 *InputContext; + DEVICE_CONTEXT_64 *OutputContext; EFI_PHYSICAL_ADDRESS PhyAddr; ASSERT (Xhc->UsbDevContext[SlotId].SlotId != 0); @@ -3742,33 +4033,37 @@ XhcEvaluateContext64 ( // // 4.6.7 Evaluate Context // - InputContext = Xhc->UsbDevContext[SlotId].InputContext; + InputContext = Xhc->UsbDevContext[SlotId].InputContext; + OutputContext = Xhc->UsbDevContext[SlotId].OutputContext; ZeroMem (InputContext, sizeof (INPUT_CONTEXT_64)); + CopyMem (&InputContext->EP[0], &OutputContext->EP[0], sizeof (ENDPOINT_CONTEXT_64)); + InputContext->InputControlContext.Dword2 |= BIT1; InputContext->EP[0].MaxPacketSize = MaxPacketSize; + InputContext->EP[0].EPState = 0; ZeroMem (&CmdTrbEvalu, sizeof (CmdTrbEvalu)); - PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, InputContext, sizeof (INPUT_CONTEXT_64)); + PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, InputContext, sizeof (INPUT_CONTEXT_64)); CmdTrbEvalu.PtrLo = XHC_LOW_32BIT (PhyAddr); CmdTrbEvalu.PtrHi = XHC_HIGH_32BIT (PhyAddr); CmdTrbEvalu.CycleBit = 1; CmdTrbEvalu.Type = TRB_TYPE_EVALU_CONTXT; CmdTrbEvalu.SlotId = Xhc->UsbDevContext[SlotId].SlotId; - DEBUG ((EFI_D_INFO, "Evaluate context\n")); + DEBUG ((DEBUG_INFO, "Evaluate context\n")); Status = XhcCmdTransfer ( Xhc, - (TRB_TEMPLATE *) (UINTN) &CmdTrbEvalu, + (TRB_TEMPLATE *)(UINTN)&CmdTrbEvalu, XHC_GENERIC_TIMEOUT, - (TRB_TEMPLATE **) (UINTN) &EvtTrb + (TRB_TEMPLATE **)(UINTN)&EvtTrb ); if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "XhcEvaluateContext64: Evaluate Context Failed, Status = %r\n", Status)); + DEBUG ((DEBUG_ERROR, "XhcEvaluateContext64: Evaluate Context Failed, Status = %r\n", Status)); } + return Status; } - /** Evaluate the slot context for hub device through XHCI's Configure_Endpoint cmd. @@ -3783,11 +4078,11 @@ XhcEvaluateContext64 ( **/ EFI_STATUS XhcConfigHubContext ( - IN USB_XHCI_INSTANCE *Xhc, - IN UINT8 SlotId, - IN UINT8 PortNum, - IN UINT8 TTT, - IN UINT8 MTT + IN USB_XHCI_INSTANCE *Xhc, + IN UINT8 SlotId, + IN UINT8 PortNum, + IN UINT8 TTT, + IN UINT8 MTT ) { EFI_STATUS Status; @@ -3811,29 +4106,30 @@ XhcConfigHubContext ( // // Copy the slot context from OutputContext to Input context // - CopyMem(&(InputContext->Slot), &(OutputContext->Slot), sizeof (SLOT_CONTEXT)); + CopyMem (&(InputContext->Slot), &(OutputContext->Slot), sizeof (SLOT_CONTEXT)); InputContext->Slot.Hub = 1; InputContext->Slot.PortNum = PortNum; InputContext->Slot.TTT = TTT; InputContext->Slot.MTT = MTT; ZeroMem (&CmdTrbCfgEP, sizeof (CmdTrbCfgEP)); - PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, InputContext, sizeof (INPUT_CONTEXT)); + PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, InputContext, sizeof (INPUT_CONTEXT)); CmdTrbCfgEP.PtrLo = XHC_LOW_32BIT (PhyAddr); CmdTrbCfgEP.PtrHi = XHC_HIGH_32BIT (PhyAddr); CmdTrbCfgEP.CycleBit = 1; CmdTrbCfgEP.Type = TRB_TYPE_CON_ENDPOINT; CmdTrbCfgEP.SlotId = Xhc->UsbDevContext[SlotId].SlotId; - DEBUG ((EFI_D_INFO, "Configure Hub Slot Context\n")); + DEBUG ((DEBUG_INFO, "Configure Hub Slot Context\n")); Status = XhcCmdTransfer ( - Xhc, - (TRB_TEMPLATE *) (UINTN) &CmdTrbCfgEP, - XHC_GENERIC_TIMEOUT, - (TRB_TEMPLATE **) (UINTN) &EvtTrb - ); + Xhc, + (TRB_TEMPLATE *)(UINTN)&CmdTrbCfgEP, + XHC_GENERIC_TIMEOUT, + (TRB_TEMPLATE **)(UINTN)&EvtTrb + ); if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "XhcConfigHubContext: Config Endpoint Failed, Status = %r\n", Status)); + DEBUG ((DEBUG_ERROR, "XhcConfigHubContext: Config Endpoint Failed, Status = %r\n", Status)); } + return Status; } @@ -3851,11 +4147,11 @@ XhcConfigHubContext ( **/ EFI_STATUS XhcConfigHubContext64 ( - IN USB_XHCI_INSTANCE *Xhc, - IN UINT8 SlotId, - IN UINT8 PortNum, - IN UINT8 TTT, - IN UINT8 MTT + IN USB_XHCI_INSTANCE *Xhc, + IN UINT8 SlotId, + IN UINT8 PortNum, + IN UINT8 TTT, + IN UINT8 MTT ) { EFI_STATUS Status; @@ -3879,30 +4175,29 @@ XhcConfigHubContext64 ( // // Copy the slot context from OutputContext to Input context // - CopyMem(&(InputContext->Slot), &(OutputContext->Slot), sizeof (SLOT_CONTEXT_64)); + CopyMem (&(InputContext->Slot), &(OutputContext->Slot), sizeof (SLOT_CONTEXT_64)); InputContext->Slot.Hub = 1; InputContext->Slot.PortNum = PortNum; InputContext->Slot.TTT = TTT; InputContext->Slot.MTT = MTT; ZeroMem (&CmdTrbCfgEP, sizeof (CmdTrbCfgEP)); - PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, InputContext, sizeof (INPUT_CONTEXT_64)); + PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, InputContext, sizeof (INPUT_CONTEXT_64)); CmdTrbCfgEP.PtrLo = XHC_LOW_32BIT (PhyAddr); CmdTrbCfgEP.PtrHi = XHC_HIGH_32BIT (PhyAddr); CmdTrbCfgEP.CycleBit = 1; CmdTrbCfgEP.Type = TRB_TYPE_CON_ENDPOINT; CmdTrbCfgEP.SlotId = Xhc->UsbDevContext[SlotId].SlotId; - DEBUG ((EFI_D_INFO, "Configure Hub Slot Context\n")); + DEBUG ((DEBUG_INFO, "Configure Hub Slot Context\n")); Status = XhcCmdTransfer ( - Xhc, - (TRB_TEMPLATE *) (UINTN) &CmdTrbCfgEP, - XHC_GENERIC_TIMEOUT, - (TRB_TEMPLATE **) (UINTN) &EvtTrb - ); + Xhc, + (TRB_TEMPLATE *)(UINTN)&CmdTrbCfgEP, + XHC_GENERIC_TIMEOUT, + (TRB_TEMPLATE **)(UINTN)&EvtTrb + ); if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "XhcConfigHubContext64: Config Endpoint Failed, Status = %r\n", Status)); + DEBUG ((DEBUG_ERROR, "XhcConfigHubContext64: Config Endpoint Failed, Status = %r\n", Status)); } + return Status; } - -