X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=MdeModulePkg%2FBus%2FPci%2FUhciDxe%2FUhciSched.c;h=12afbec852c049a4d0fcace876138728f06e613b;hp=671a54205a5e28c6bd51400362179542909e1ff9;hb=9d510e61fceee7b92955ef9a3c20343752d8ce3f;hpb=6d3ea23f1183f3378a53e44d34c0a27aebec7d9a diff --git a/MdeModulePkg/Bus/Pci/UhciDxe/UhciSched.c b/MdeModulePkg/Bus/Pci/UhciDxe/UhciSched.c index 671a54205a..12afbec852 100644 --- a/MdeModulePkg/Bus/Pci/UhciDxe/UhciSched.c +++ b/MdeModulePkg/Bus/Pci/UhciDxe/UhciSched.c @@ -2,14 +2,8 @@ The EHCI register operation routines. -Copyright (c) 2007 - 2009, 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) 2007 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -38,6 +32,7 @@ UhciInitFrameList ( UINTN Pages; UINTN Bytes; UINTN Index; + EFI_PHYSICAL_ADDRESS PhyAddr; // // The Frame List is a common buffer that will be @@ -75,8 +70,14 @@ UhciInitFrameList ( goto ON_ERROR; } - Uhc->FrameBase = (UINT32 *) (UINTN) MappedAddr; - Uhc->FrameMapping = Mapping; + Uhc->FrameBase = (UINT32 *) (UINTN) Buffer; + Uhc->FrameMapping = Mapping; + + // + // Tell the Host Controller where the Frame List lies, + // by set the Frame List Base Address Register. + // + UhciSetFrameListBaseAddr (Uhc->PciIo, (VOID *) (UINTN) MappedAddr); // // Allocate the QH used by sync interrupt/control/bulk transfer. @@ -101,10 +102,12 @@ UhciInitFrameList ( // Each frame entry is linked to this sequence of QH. These QH // will remain on the schedul, never got removed // - Uhc->SyncIntQh->QhHw.HorizonLink = QH_HLINK (Uhc->CtrlQh, FALSE); + PhyAddr = UsbHcGetPciAddressForHostMem (Uhc->MemPool, Uhc->CtrlQh, sizeof (UHCI_QH_HW)); + Uhc->SyncIntQh->QhHw.HorizonLink = QH_HLINK (PhyAddr, FALSE); Uhc->SyncIntQh->NextQh = Uhc->CtrlQh; - Uhc->CtrlQh->QhHw.HorizonLink = QH_HLINK (Uhc->BulkQh, FALSE); + PhyAddr = UsbHcGetPciAddressForHostMem (Uhc->MemPool, Uhc->BulkQh, sizeof (UHCI_QH_HW)); + Uhc->CtrlQh->QhHw.HorizonLink = QH_HLINK (PhyAddr, FALSE); Uhc->CtrlQh->NextQh = Uhc->BulkQh; // @@ -112,19 +115,22 @@ UhciInitFrameList ( // in supporting the full speed bandwidth reclamation in the previous // mentioned form. Most new platforms don't suffer it. // - Uhc->BulkQh->QhHw.HorizonLink = QH_HLINK (Uhc->BulkQh, FALSE); + Uhc->BulkQh->QhHw.HorizonLink = QH_HLINK (PhyAddr, FALSE); Uhc->BulkQh->NextQh = NULL; + Uhc->FrameBaseHostAddr = AllocateZeroPool (4096); + if (Uhc->FrameBaseHostAddr == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_ERROR; + } + + PhyAddr = UsbHcGetPciAddressForHostMem (Uhc->MemPool, Uhc->SyncIntQh, sizeof (UHCI_QH_HW)); for (Index = 0; Index < UHCI_FRAME_NUM; Index++) { - Uhc->FrameBase[Index] = QH_HLINK (Uhc->SyncIntQh, FALSE); + Uhc->FrameBase[Index] = QH_HLINK (PhyAddr, FALSE); + Uhc->FrameBaseHostAddr[Index] = (UINT32)(UINTN)Uhc->SyncIntQh; } - // - // Tell the Host Controller where the Frame List lies, - // by set the Frame List Base Address Register. - // - UhciSetFrameListBaseAddr (Uhc->PciIo, (VOID *) (Uhc->FrameBase)); return EFI_SUCCESS; ON_ERROR: @@ -169,6 +175,10 @@ UhciDestoryFrameList ( (VOID *) Uhc->FrameBase ); + if (Uhc->FrameBaseHostAddr != NULL) { + FreePool (Uhc->FrameBaseHostAddr); + } + if (Uhc->SyncIntQh != NULL) { UsbHcFreeMem (Uhc->MemPool, Uhc->SyncIntQh, sizeof (UHCI_QH_SW)); } @@ -181,10 +191,11 @@ UhciDestoryFrameList ( UsbHcFreeMem (Uhc->MemPool, Uhc->BulkQh, sizeof (UHCI_QH_SW)); } - Uhc->FrameBase = NULL; - Uhc->SyncIntQh = NULL; - Uhc->CtrlQh = NULL; - Uhc->BulkQh = NULL; + Uhc->FrameBase = NULL; + Uhc->FrameBaseHostAddr = NULL; + Uhc->SyncIntQh = NULL; + Uhc->CtrlQh = NULL; + Uhc->BulkQh = NULL; } @@ -224,29 +235,33 @@ UhciConvertPollRate ( Link a queue head (for asynchronous interrupt transfer) to the frame list. - @param FrameBase The base of the frame list. + @param Uhc The UHCI device. @param Qh The queue head to link into. **/ VOID UhciLinkQhToFrameList ( - UINT32 *FrameBase, + USB_HC_DEV *Uhc, UHCI_QH_SW *Qh ) { UINTN Index; UHCI_QH_SW *Prev; UHCI_QH_SW *Next; + EFI_PHYSICAL_ADDRESS PhyAddr; + EFI_PHYSICAL_ADDRESS QhPciAddr; - ASSERT ((FrameBase != NULL) && (Qh != NULL)); + ASSERT ((Uhc->FrameBase != NULL) && (Qh != NULL)); + + QhPciAddr = UsbHcGetPciAddressForHostMem (Uhc->MemPool, Qh, sizeof (UHCI_QH_HW)); for (Index = 0; Index < UHCI_FRAME_NUM; Index += Qh->Interval) { // // First QH can't be NULL because we always keep static queue // heads on the frame list // - ASSERT (!LINK_TERMINATED (FrameBase[Index])); - Next = UHCI_ADDR (FrameBase[Index]); + ASSERT (!LINK_TERMINATED (Uhc->FrameBase[Index])); + Next = (UHCI_QH_SW*)(UINTN)Uhc->FrameBaseHostAddr[Index]; Prev = NULL; // @@ -266,10 +281,9 @@ UhciLinkQhToFrameList ( while (Next->Interval > Qh->Interval) { Prev = Next; Next = Next->NextQh; + ASSERT (Next != NULL); } - ASSERT (Next != NULL); - // // The entry may have been linked into the frame by early insertation. // For example: if insert a Qh with Qh.Interval == 4, and there is a Qh @@ -298,7 +312,8 @@ UhciLinkQhToFrameList ( Prev->NextQh = Qh; Qh->QhHw.HorizonLink = Prev->QhHw.HorizonLink; - Prev->QhHw.HorizonLink = QH_HLINK (Qh, FALSE); + + Prev->QhHw.HorizonLink = QH_HLINK (QhPciAddr, FALSE); break; } @@ -309,14 +324,16 @@ UhciLinkQhToFrameList ( // if (Qh->NextQh == NULL) { Qh->NextQh = Next; - Qh->QhHw.HorizonLink = QH_HLINK (Next, FALSE); + PhyAddr = UsbHcGetPciAddressForHostMem (Uhc->MemPool, Next, sizeof (UHCI_QH_HW)); + Qh->QhHw.HorizonLink = QH_HLINK (PhyAddr, FALSE); } if (Prev == NULL) { - FrameBase[Index] = QH_HLINK (Qh, FALSE); + Uhc->FrameBase[Index] = QH_HLINK (QhPciAddr, FALSE); + Uhc->FrameBaseHostAddr[Index] = (UINT32)(UINTN)Qh; } else { Prev->NextQh = Qh; - Prev->QhHw.HorizonLink = QH_HLINK (Qh, FALSE); + Prev->QhHw.HorizonLink = QH_HLINK (QhPciAddr, FALSE); } } } @@ -327,29 +344,29 @@ UhciLinkQhToFrameList ( the precedence node, and pointer there next to QhSw's next. - @param FrameBase The base address of the frame list. + @param Uhc The UHCI device. @param Qh The queue head to unlink. **/ VOID UhciUnlinkQhFromFrameList ( - UINT32 *FrameBase, - UHCI_QH_SW *Qh + USB_HC_DEV *Uhc, + UHCI_QH_SW *Qh ) { UINTN Index; UHCI_QH_SW *Prev; UHCI_QH_SW *This; - ASSERT ((FrameBase != NULL) && (Qh != NULL)); + ASSERT ((Uhc->FrameBase != NULL) && (Qh != NULL)); for (Index = 0; Index < UHCI_FRAME_NUM; Index += Qh->Interval) { // // Frame link can't be NULL because we always keep static // queue heads on the frame list // - ASSERT (!LINK_TERMINATED (FrameBase[Index])); - This = UHCI_ADDR (FrameBase[Index]); + ASSERT (!LINK_TERMINATED (Uhc->FrameBase[Index])); + This = (UHCI_QH_SW*)(UINTN)Uhc->FrameBaseHostAddr[Index]; Prev = NULL; // @@ -373,7 +390,8 @@ UhciUnlinkQhFromFrameList ( // // Qh is the first entry in the frame // - FrameBase[Index] = Qh->QhHw.HorizonLink; + Uhc->FrameBase[Index] = Qh->QhHw.HorizonLink; + Uhc->FrameBaseHostAddr[Index] = (UINT32)(UINTN)Qh->NextQh; } else { Prev->NextQh = Qh->NextQh; Prev->QhHw.HorizonLink = Qh->QhHw.HorizonLink; @@ -495,7 +513,7 @@ UhciCheckTdStatus ( // terminate the transfer // if (!IsLow && (TdHw->ShortPacket == 1) && (Len < Td->DataLen)) { - DEBUG ((EFI_D_INFO, "UhciCheckTdStatus: short packet read occured\n")); + DEBUG ((EFI_D_VERBOSE, "UhciCheckTdStatus: short packet read occured\n")); Finished = TRUE; goto ON_EXIT; @@ -552,12 +570,23 @@ UhciExecuteTransfer ( UINTN Delay; BOOLEAN Finished; EFI_STATUS Status; + BOOLEAN InfiniteLoop; - Finished = FALSE; - Status = EFI_SUCCESS; - Delay = (TimeOut * UHC_1_MILLISECOND / UHC_SYNC_POLL_INTERVAL) + 1; + Finished = FALSE; + Status = EFI_SUCCESS; + Delay = TimeOut * UHC_1_MILLISECOND; + InfiniteLoop = FALSE; - for (Index = 0; Index < Delay; Index++) { + // + // According to UEFI spec section 16.2.4, If Timeout is 0, then the caller + // must wait for the function to be completed until EFI_SUCCESS or EFI_DEVICE_ERROR + // is returned. + // + if (TimeOut == 0) { + InfiniteLoop = TRUE; + } + + for (Index = 0; InfiniteLoop || (Index < Delay); Index++) { Finished = UhciCheckTdStatus (Uhc, Td, IsLow, QhResult); // @@ -567,7 +596,7 @@ UhciExecuteTransfer ( break; } - gBS->Stall (UHC_SYNC_POLL_INTERVAL); + gBS->Stall (UHC_1_MICROSECOND); } if (!Finished) { @@ -592,6 +621,7 @@ UhciExecuteTransfer ( /** Update Async Request, QH and TDs. + @param Uhc The UHCI device. @param AsyncReq The UHCI asynchronous transfer to update. @param Result Transfer reslut. @param NextToggle The toggle of next data. @@ -599,6 +629,7 @@ UhciExecuteTransfer ( **/ VOID UhciUpdateAsyncReq ( + IN USB_HC_DEV *Uhc, IN UHCI_ASYNC_REQUEST *AsyncReq, IN UINT32 Result, IN UINT32 NextToggle @@ -627,7 +658,7 @@ UhciUpdateAsyncReq ( Td->TdHw.Status |= USBTD_ACTIVE; } - UhciLinkTdToQh (Qh, FirstTd); + UhciLinkTdToQh (Uhc, Qh, FirstTd); return ; } } @@ -643,7 +674,6 @@ UhciUpdateAsyncReq ( @param EndPoint EndPoint Address. @param DataLen Data length. @param Interval Polling Interval when inserted to frame list. - @param Mapping Mapping value. @param Data Data buffer, unmapped. @param Callback Callback after interrupt transfeer. @param Context Callback Context passed as function parameter. @@ -663,7 +693,6 @@ UhciCreateAsyncReq ( IN UINT8 EndPoint, IN UINTN DataLen, IN UINTN Interval, - IN VOID *Mapping, IN UINT8 *Data, IN EFI_ASYNC_USB_TRANSFER_CALLBACK Callback, IN VOID *Context, @@ -686,7 +715,6 @@ UhciCreateAsyncReq ( AsyncReq->EndPoint = EndPoint; AsyncReq->DataLen = DataLen; AsyncReq->Interval = UhciConvertPollRate(Interval); - AsyncReq->Mapping = Mapping; AsyncReq->Data = Data; AsyncReq->Callback = Callback; AsyncReq->Context = Context; @@ -724,12 +752,8 @@ UhciFreeAsyncReq ( UhciDestoryTds (Uhc, AsyncReq->FirstTd); UsbHcFreeMem (Uhc->MemPool, AsyncReq->QhSw, sizeof (UHCI_QH_SW)); - if (AsyncReq->Mapping != NULL) { - Uhc->PciIo->Unmap (Uhc->PciIo, AsyncReq->Mapping); - } - if (AsyncReq->Data != NULL) { - gBS->FreePool (AsyncReq->Data); + UsbHcFreeMem (Uhc->MemPool, AsyncReq->Data, AsyncReq->DataLen); } gBS->FreePool (AsyncReq); @@ -759,7 +783,7 @@ UhciUnlinkAsyncReq ( ASSERT ((Uhc != NULL) && (AsyncReq != NULL)); RemoveEntryList (&(AsyncReq->Link)); - UhciUnlinkQhFromFrameList (Uhc->FrameBase, AsyncReq->QhSw); + UhciUnlinkQhFromFrameList (Uhc, AsyncReq->QhSw); if (FreeNow) { UhciFreeAsyncReq (Uhc, AsyncReq); @@ -971,11 +995,12 @@ UhciMonitorAsyncReqList ( // // Copy the data to temporary buffer if there are some - // data transferred. We may have zero-length packet + // data transferred. We may have zero-length packet. + // Make sure the data received from HW is no more than expected. // Data = NULL; - if (QhResult.Complete != 0) { + if ((QhResult.Complete != 0) && (QhResult.Complete <= AsyncReq->DataLen)) { Data = AllocatePool (QhResult.Complete); if (Data == NULL) { @@ -985,7 +1010,7 @@ UhciMonitorAsyncReqList ( CopyMem (Data, AsyncReq->FirstTd->Data, QhResult.Complete); } - UhciUpdateAsyncReq (AsyncReq, QhResult.Result, QhResult.NextToggle); + UhciUpdateAsyncReq (Uhc, AsyncReq, QhResult.Result, QhResult.NextToggle); // // Now, either transfer is SUCCESS or met errors since