diff --git a/MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c b/MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c index 3161ede949..6cf4aefea6 100644 --- a/MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c +++ b/MdeModulePkg/Bus/Pci/EhciDxe/Ehci.c @@ -969,7 +969,8 @@ EhcAsyncInterruptTransfer ( // // Validate parameters // - if (!EHCI_IS_DATAIN (EndPointAddress)) { + if (!(EndPointAddress >= 0x01 && EndPointAddress <= 0x0F) + && !(EndPointAddress >= 0x81 && EndPointAddress <= 0x8F)) { return EFI_INVALID_PARAMETER; } @@ -1118,7 +1119,8 @@ EhcSyncInterruptTransfer ( return EFI_INVALID_PARAMETER; } - if (!EHCI_IS_DATAIN (EndPointAddress)) { + if (!(EndPointAddress >= 0x01 && EndPointAddress <= 0x0F) + && !(EndPointAddress >= 0x81 && EndPointAddress <= 0x8F)) { return EFI_INVALID_PARAMETER; } diff --git a/MdeModulePkg/Bus/Pci/EhciDxe/Ehci.h b/MdeModulePkg/Bus/Pci/EhciDxe/Ehci.h index 07abcaf82c..d6f0003557 100644 --- a/MdeModulePkg/Bus/Pci/EhciDxe/Ehci.h +++ b/MdeModulePkg/Bus/Pci/EhciDxe/Ehci.h @@ -139,8 +139,8 @@ struct _USB2_HC_DEV { // // Peroidic (interrupt) transfer schedule data: // - VOID *PeriodFrame; // Mapped as common buffer - VOID *PeriodFrameHost; + VOID *PeriodFrame; // the buffer pointed by this pointer is used to store pci bus address of the QH descriptor. + VOID *PeriodFrameHost; // the buffer pointed by this pointer is used to store host memory address of the QH descriptor. VOID *PeriodFrameMap; EHC_QH *PeriodOne; @@ -152,7 +152,6 @@ struct _USB2_HC_DEV { UINT32 HcStructParams; // Cache of HC structure parameter, EHC_HCSPARAMS_OFFSET UINT32 HcCapParams; // Cache of HC capability parameter, HCCPARAMS UINT32 CapLen; // Capability length - UINT32 High32bitAddr; // // Misc diff --git a/MdeModulePkg/Bus/Pci/EhciDxe/EhciReg.c b/MdeModulePkg/Bus/Pci/EhciDxe/EhciReg.c index 7a533d78e1..0b8187a52d 100644 --- a/MdeModulePkg/Bus/Pci/EhciDxe/EhciReg.c +++ b/MdeModulePkg/Bus/Pci/EhciDxe/EhciReg.c @@ -564,7 +564,7 @@ EhcInitHC ( // Allocate the periodic frame and associated memeory // management facilities if not already done. // - if (Ehc->PeriodFrameHost != NULL) { + if (Ehc->PeriodFrame != NULL) { EhcFreeSched (Ehc); } @@ -573,24 +573,20 @@ EhcInitHC ( if (EFI_ERROR (Status)) { return Status; } - // - // 1. Program the CTRLDSSEGMENT register with the high 32 bit addr - // - EhcWriteOpReg (Ehc, EHC_CTRLDSSEG_OFFSET, Ehc->High32bitAddr); // - // 2. Clear USBINTR to disable all the interrupt. UEFI works by polling + // 1. Clear USBINTR to disable all the interrupt. UEFI works by polling // EhcWriteOpReg (Ehc, EHC_USBINTR_OFFSET, 0); // - // 3. Program periodic frame list, already done in EhcInitSched - // 4. Start the Host Controller + // 2. Program periodic frame list, already done in EhcInitSched + // 3. Start the Host Controller // EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_RUN); // - // 5. Set all ports routing to EHC + // 4. Set all ports routing to EHC // EhcSetOpRegBit (Ehc, EHC_CONFIG_FLAG_OFFSET, CONFIGFLAG_ROUTE_EHC); diff --git a/MdeModulePkg/Bus/Pci/EhciDxe/EhciSched.c b/MdeModulePkg/Bus/Pci/EhciDxe/EhciSched.c index c1d44f5282..2086206404 100644 --- a/MdeModulePkg/Bus/Pci/EhciDxe/EhciSched.c +++ b/MdeModulePkg/Bus/Pci/EhciDxe/EhciSched.c @@ -116,7 +116,6 @@ EhcInitSched ( UINTN Pages; UINTN Bytes; UINTN Index; - UINT32 *Desc; EFI_STATUS Status; EFI_PHYSICAL_ADDRESS PciAddr; @@ -159,10 +158,17 @@ EhcInitSched ( return EFI_OUT_OF_RESOURCES; } - Ehc->PeriodFrameHost = Buf; - Ehc->PeriodFrame = (VOID *) ((UINTN) PhyAddr); + Ehc->PeriodFrame = Buf; Ehc->PeriodFrameMap = Map; - Ehc->High32bitAddr = EHC_HIGH_32BIT (PhyAddr); + + // + // Program the FRAMELISTBASE register with the low 32 bit addr + // + EhcWriteOpReg (Ehc, EHC_FRAME_BASE_OFFSET, EHC_LOW_32BIT (PhyAddr)); + // + // Program the CTRLDSSEGMENT register with the high 32 bit addr + // + EhcWriteOpReg (Ehc, EHC_CTRLDSSEG_OFFSET, EHC_HIGH_32BIT (PhyAddr)); // // Init memory pool management then create the helper @@ -172,30 +178,40 @@ EhcInitSched ( Ehc->MemPool = UsbHcInitMemPool ( PciIo, EHC_BIT_IS_SET (Ehc->HcCapParams, HCCP_64BIT), - Ehc->High32bitAddr + EHC_HIGH_32BIT (PhyAddr) ); if (Ehc->MemPool == NULL) { - return EFI_OUT_OF_RESOURCES; + goto ErrorExit; } Status = EhcCreateHelpQ (Ehc); if (EFI_ERROR (Status)) { - return Status; + goto ErrorExit; } // // Initialize the frame list entries then set the registers // - Desc = (UINT32 *) Ehc->PeriodFrameHost; - - for (Index = 0; Index < EHC_FRAME_LEN; Index++) { - PciAddr = UsbHcGetPciAddressForHostMem (Ehc->MemPool, Ehc->PeriodOne, sizeof (EHC_QH)); - Desc[Index] = QH_LINK (PciAddr, EHC_TYPE_QH, FALSE); + Ehc->PeriodFrameHost = AllocateZeroPool (EHC_FRAME_LEN * sizeof (UINTN)); + if (Ehc->PeriodFrameHost == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ErrorExit; } - EhcWriteOpReg (Ehc, EHC_FRAME_BASE_OFFSET, EHC_LOW_32BIT (Ehc->PeriodFrame)); + PciAddr = UsbHcGetPciAddressForHostMem (Ehc->MemPool, Ehc->PeriodOne, sizeof (EHC_QH)); + + for (Index = 0; Index < EHC_FRAME_LEN; Index++) { + // + // Store the pci bus address of the QH in period frame list which will be accessed by pci bus master. + // + ((UINT32 *)(Ehc->PeriodFrame))[Index] = QH_LINK (PciAddr, EHC_TYPE_QH, FALSE); + // + // Store the host address of the QH in period frame list which will be accessed by host. + // + ((UINTN *)(Ehc->PeriodFrameHost))[Index] = (UINTN)Ehc->PeriodOne; + } // // Second initialize the asynchronous schedule: @@ -205,6 +221,26 @@ EhcInitSched ( PciAddr = UsbHcGetPciAddressForHostMem (Ehc->MemPool, Ehc->ReclaimHead, sizeof (EHC_QH)); EhcWriteOpReg (Ehc, EHC_ASYNC_HEAD_OFFSET, EHC_LOW_32BIT (PciAddr)); return EFI_SUCCESS; + +ErrorExit: + PciIo->FreeBuffer (PciIo, Pages, Buf); + PciIo->Unmap (PciIo, Map); + + if (Ehc->PeriodOne != NULL) { + UsbHcFreeMem (Ehc->MemPool, Ehc->PeriodOne, sizeof (EHC_QH)); + Ehc->PeriodOne = NULL; + } + + if (Ehc->ReclaimHead != NULL) { + UsbHcFreeMem (Ehc->MemPool, Ehc->ReclaimHead, sizeof (EHC_QH)); + Ehc->ReclaimHead = NULL; + } + + if (Ehc->ShortReadStop != NULL) { + UsbHcFreeMem (Ehc->MemPool, Ehc->ShortReadStop, sizeof (EHC_QTD)); + Ehc->ShortReadStop = NULL; + } + return Status; } @@ -244,7 +280,7 @@ EhcFreeSched ( Ehc->MemPool = NULL; } - if (Ehc->PeriodFrameHost != NULL) { + if (Ehc->PeriodFrame != NULL) { PciIo = Ehc->PciIo; ASSERT (PciIo != NULL); @@ -253,11 +289,15 @@ EhcFreeSched ( PciIo->FreeBuffer ( PciIo, EFI_SIZE_TO_PAGES (EFI_PAGE_SIZE), - Ehc->PeriodFrameHost + Ehc->PeriodFrame ); + Ehc->PeriodFrame = NULL; + } + + if (Ehc->PeriodFrameHost != NULL) { + FreePool (Ehc->PeriodFrameHost); Ehc->PeriodFrameHost = NULL; - Ehc->PeriodFrame = NULL; } } @@ -293,7 +333,7 @@ EhcLinkQhToAsync ( Head->NextQh = Qh; PciAddr = UsbHcGetPciAddressForHostMem (Ehc->MemPool, Head, sizeof (EHC_QH)); - Qh->QhHw.HorizonLink = QH_LINK (PciAddr, EHC_TYPE_QH, FALSE);; + Qh->QhHw.HorizonLink = QH_LINK (PciAddr, EHC_TYPE_QH, FALSE); PciAddr = UsbHcGetPciAddressForHostMem (Ehc->MemPool, Qh, sizeof (EHC_QH)); Head->QhHw.HorizonLink = QH_LINK (PciAddr, EHC_TYPE_QH, FALSE); } @@ -358,21 +398,18 @@ EhcLinkQhToPeriod ( IN EHC_QH *Qh ) { - UINT32 *Frames; UINTN Index; EHC_QH *Prev; EHC_QH *Next; EFI_PHYSICAL_ADDRESS PciAddr; - Frames = Ehc->PeriodFrameHost; - for (Index = 0; Index < EHC_FRAME_LEN; Index += Qh->Interval) { // // First QH can't be NULL because we always keep PeriodOne // heads on the frame list // - ASSERT (!EHC_LINK_TERMINATED (Frames[Index])); - Next = EHC_ADDR (Ehc->High32bitAddr, Frames[Index]); + ASSERT (!EHC_LINK_TERMINATED (((UINT32*)Ehc->PeriodFrame)[Index])); + Next = (EHC_QH*)((UINTN*)Ehc->PeriodFrameHost)[Index]; Prev = NULL; // @@ -439,7 +476,8 @@ EhcLinkQhToPeriod ( PciAddr = UsbHcGetPciAddressForHostMem (Ehc->MemPool, Qh, sizeof (EHC_QH)); if (Prev == NULL) { - Frames[Index] = QH_LINK (PciAddr, EHC_TYPE_QH, FALSE); + ((UINT32*)Ehc->PeriodFrame)[Index] = QH_LINK (PciAddr, EHC_TYPE_QH, FALSE); + ((UINTN*)Ehc->PeriodFrameHost)[Index] = (UINTN)Qh; } else { Prev->NextQh = Qh; Prev->QhHw.HorizonLink = QH_LINK (PciAddr, EHC_TYPE_QH, FALSE); @@ -462,20 +500,17 @@ EhcUnlinkQhFromPeriod ( IN EHC_QH *Qh ) { - UINT32 *Frames; UINTN Index; EHC_QH *Prev; EHC_QH *This; - Frames = Ehc->PeriodFrameHost; - for (Index = 0; Index < EHC_FRAME_LEN; Index += Qh->Interval) { // // Frame link can't be NULL because we always keep PeroidOne // on the frame list // - ASSERT (!EHC_LINK_TERMINATED (Frames[Index])); - This = EHC_ADDR (Ehc->High32bitAddr, Frames[Index]); + ASSERT (!EHC_LINK_TERMINATED (((UINT32*)Ehc->PeriodFrame)[Index])); + This = (EHC_QH*)((UINTN*)Ehc->PeriodFrameHost)[Index]; Prev = NULL; // @@ -499,7 +534,8 @@ EhcUnlinkQhFromPeriod ( // // Qh is the first entry in the frame // - Frames[Index] = Qh->QhHw.HorizonLink; + ((UINT32*)Ehc->PeriodFrame)[Index] = Qh->QhHw.HorizonLink; + ((UINTN*)Ehc->PeriodFrameHost)[Index] = (UINTN)Qh->NextQh; } else { Prev->NextQh = Qh->NextQh; Prev->QhHw.HorizonLink = Qh->QhHw.HorizonLink; diff --git a/MdeModulePkg/Bus/Pci/EhciDxe/UsbHcMem.c b/MdeModulePkg/Bus/Pci/EhciDxe/UsbHcMem.c index 069ee5f575..5194d540a7 100644 --- a/MdeModulePkg/Bus/Pci/EhciDxe/UsbHcMem.c +++ b/MdeModulePkg/Bus/Pci/EhciDxe/UsbHcMem.c @@ -218,15 +218,15 @@ UsbHcAllocMemFromBlock ( NEXT_BIT (Byte, Bit); } - return Block->Buf + (StartByte * 8 + StartBit) * USBHC_MEM_UNIT; + return Block->BufHost + (StartByte * 8 + StartBit) * USBHC_MEM_UNIT; } /** - Get the pci memory address according to the allocated host memory address. + Calculate the corresponding pci bus address according to the Mem parameter. @param Pool The memory pool of the host controller. - @param Mem The memory to free. - @param Size The size of the memory to free. + @param Mem The pointer to host memory. + @param Size The size of the memory region. @return the pci memory address **/ @@ -251,7 +251,7 @@ UsbHcGetPciAddressForHostMem ( // scan the memory block list for the memory block that // completely contains the allocated memory. // - if ((Block->Buf <= (UINT8 *) Mem) && (((UINT8 *) Mem + AllocSize) <= (Block->Buf + Block->BufLen))) { + if ((Block->BufHost <= (UINT8 *) Mem) && (((UINT8 *) Mem + AllocSize) <= (Block->BufHost + Block->BufLen))) { break; } } @@ -522,12 +522,12 @@ UsbHcFreeMem ( // scan the memory block list for the memory block that // completely contains the memory to free. // - if ((Block->Buf <= ToFree) && ((ToFree + AllocSize) <= (Block->Buf + Block->BufLen))) { + if ((Block->BufHost <= ToFree) && ((ToFree + AllocSize) <= (Block->BufHost + Block->BufLen))) { // // compute the start byte and bit in the bit array // - Byte = ((ToFree - Block->Buf) / USBHC_MEM_UNIT) / 8; - Bit = ((ToFree - Block->Buf) / USBHC_MEM_UNIT) % 8; + Byte = ((ToFree - Block->BufHost) / USBHC_MEM_UNIT) / 8; + Bit = ((ToFree - Block->BufHost) / USBHC_MEM_UNIT) % 8; // // reset associated bits in bit arry diff --git a/MdeModulePkg/Bus/Pci/EhciDxe/UsbHcMem.h b/MdeModulePkg/Bus/Pci/EhciDxe/UsbHcMem.h index 3394c9b99e..f851868d10 100644 --- a/MdeModulePkg/Bus/Pci/EhciDxe/UsbHcMem.h +++ b/MdeModulePkg/Bus/Pci/EhciDxe/UsbHcMem.h @@ -139,11 +139,11 @@ UsbHcFreeMem ( ); /** - Get the pci memory address according to the allocated host memory address. + Calculate the corresponding pci bus address according to the Mem parameter. @param Pool The memory pool of the host controller. - @param Mem The memory to free. - @param Size The size of the memory to free. + @param Mem The pointer to host memory. + @param Size The size of the memory region. @return the pci memory address **/