PEIM to produce gPeiUsb2HostControllerPpiGuid based on gPeiUsbControllerPpiGuid\r
which is used to enable recovery function from USB Drivers.\r
\r
-Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2014 - 2017, Intel Corporation. All rights reserved.<BR>\r
\r
This program and the accompanying materials\r
are licensed and made available under the terms and conditions\r
return;\r
}\r
\r
+ IoMmuUnmap (Urb->DataMap);\r
+\r
FreePool (Urb);\r
}\r
\r
UINTN TotalLen;\r
UINTN Len;\r
UINTN TrbNum;\r
+ EDKII_IOMMU_OPERATION MapOp;\r
+ EFI_PHYSICAL_ADDRESS PhyAddr;\r
+ VOID *Map;\r
+ EFI_STATUS Status;\r
\r
SlotId = XhcPeiBusDevAddrToSlotId (Xhc, Urb->Ep.BusAddr);\r
if (SlotId == 0) {\r
EPType = (UINT8) ((DEVICE_CONTEXT_64 *)OutputContext)->EP[Dci-1].EPType;\r
}\r
\r
- Urb->DataPhy = Urb->Data;\r
+ //\r
+ // No need to remap.\r
+ //\r
+ if ((Urb->Data != NULL) && (Urb->DataMap == NULL)) {\r
+ if (((UINT8) (Urb->Ep.Direction)) == EfiUsbDataIn) {\r
+ MapOp = EdkiiIoMmuOperationBusMasterWrite;\r
+ } else {\r
+ MapOp = EdkiiIoMmuOperationBusMasterRead;\r
+ }\r
+\r
+ Len = Urb->DataLen;\r
+ Status = IoMmuMap (MapOp, Urb->Data, &Len, &PhyAddr, &Map);\r
+\r
+ if (EFI_ERROR (Status) || (Len != Urb->DataLen)) {\r
+ DEBUG ((DEBUG_ERROR, "XhcCreateTransferTrb: Fail to map Urb->Data.\n"));\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Urb->DataPhy = (VOID *) ((UINTN) PhyAddr);\r
+ Urb->DataMap = Map;\r
+ }\r
\r
//\r
// Construct the TRB\r
// 8) Issue an Address Device Command for the Device Slot, where the command points to the Input\r
// Context data structure described above.\r
//\r
+ // Delay 10ms to meet TRSTRCY delay requirement in usb 2.0 spec chapter 7.1.7.5 before sending SetAddress() request\r
+ // to device.\r
+ //\r
+ MicroSecondDelay (XHC_RESET_RECOVERY_DELAY);\r
ZeroMem (&CmdTrbAddr, sizeof (CmdTrbAddr));\r
PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Xhc->UsbDevContext[SlotId].InputContext, sizeof (INPUT_CONTEXT));\r
CmdTrbAddr.PtrLo = XHC_LOW_32BIT (PhyAddr);\r
// 8) Issue an Address Device Command for the Device Slot, where the command points to the Input\r
// Context data structure described above.\r
//\r
+ // Delay 10ms to meet TRSTRCY delay requirement in usb 2.0 spec chapter 7.1.7.5 before sending SetAddress() request\r
+ // to device.\r
+ //\r
+ MicroSecondDelay (XHC_RESET_RECOVERY_DELAY);\r
ZeroMem (&CmdTrbAddr, sizeof (CmdTrbAddr));\r
PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Xhc->UsbDevContext[SlotId].InputContext, sizeof (INPUT_CONTEXT_64));\r
CmdTrbAddr.PtrLo = XHC_LOW_32BIT (PhyAddr);\r
InputContext->EP[Dci-1].CErr = 0;\r
InputContext->EP[Dci-1].EPType = ED_ISOCH_OUT;\r
}\r
+ //\r
+ // Get the bInterval from descriptor and init the the interval field of endpoint context.\r
+ // Refer to XHCI 1.1 spec section 6.2.3.6.\r
+ //\r
+ if (DeviceSpeed == EFI_USB_SPEED_FULL) {\r
+ Interval = EpDesc->Interval;\r
+ ASSERT (Interval >= 1 && Interval <= 16);\r
+ InputContext->EP[Dci-1].Interval = Interval + 2;\r
+ } else if ((DeviceSpeed == EFI_USB_SPEED_HIGH) || (DeviceSpeed == EFI_USB_SPEED_SUPER)) {\r
+ Interval = EpDesc->Interval;\r
+ ASSERT (Interval >= 1 && Interval <= 16);\r
+ InputContext->EP[Dci-1].Interval = Interval - 1;\r
+ }\r
+\r
//\r
// Do not support isochronous transfer now.\r
//\r
InputContext->EP[Dci-1].CErr = 0;\r
InputContext->EP[Dci-1].EPType = ED_ISOCH_OUT;\r
}\r
+ //\r
+ // Get the bInterval from descriptor and init the the interval field of endpoint context.\r
+ // Refer to XHCI 1.1 spec section 6.2.3.6.\r
+ //\r
+ if (DeviceSpeed == EFI_USB_SPEED_FULL) {\r
+ Interval = EpDesc->Interval;\r
+ ASSERT (Interval >= 1 && Interval <= 16);\r
+ InputContext->EP[Dci-1].Interval = Interval + 2;\r
+ } else if ((DeviceSpeed == EFI_USB_SPEED_HIGH) || (DeviceSpeed == EFI_USB_SPEED_SUPER)) {\r
+ Interval = EpDesc->Interval;\r
+ ASSERT (Interval >= 1 && Interval <= 16);\r
+ InputContext->EP[Dci-1].Interval = Interval - 1;\r
+ }\r
+\r
//\r
// Do not support isochronous transfer now.\r
//\r
UINT64 *ScratchEntry;\r
EFI_PHYSICAL_ADDRESS ScratchEntryPhy;\r
UINT32 Index;\r
+ UINTN *ScratchEntryMap;\r
EFI_STATUS Status;\r
\r
//\r
Xhc->MaxScratchpadBufs = MaxScratchpadBufs;\r
ASSERT (MaxScratchpadBufs <= 1023);\r
if (MaxScratchpadBufs != 0) {\r
+ //\r
+ // Allocate the buffer to record the Mapping for each scratch buffer in order to Unmap them\r
+ //\r
+ ScratchEntryMap = AllocateZeroPool (sizeof (UINTN) * MaxScratchpadBufs);\r
+ ASSERT (ScratchEntryMap != NULL);\r
+ Xhc->ScratchEntryMap = ScratchEntryMap;\r
+\r
//\r
// Allocate the buffer to record the host address for each entry\r
//\r
EFI_SIZE_TO_PAGES (MaxScratchpadBufs * sizeof (UINT64)),\r
Xhc->PageSize,\r
(VOID **) &ScratchBuf,\r
- &ScratchPhy\r
+ &ScratchPhy,\r
+ &Xhc->ScratchMap\r
);\r
ASSERT_EFI_ERROR (Status);\r
\r
EFI_SIZE_TO_PAGES (Xhc->PageSize),\r
Xhc->PageSize,\r
(VOID **) &ScratchEntry[Index],\r
- &ScratchEntryPhy\r
+ &ScratchEntryPhy,\r
+ (VOID **) &ScratchEntryMap[Index]\r
);\r
ASSERT_EFI_ERROR (Status);\r
ZeroMem ((VOID *) (UINTN) ScratchEntry[Index], Xhc->PageSize);\r
//\r
// Free Scratchpad Buffers\r
//\r
- UsbHcFreeAlignedPages ((VOID*) (UINTN) ScratchEntry[Index], EFI_SIZE_TO_PAGES (Xhc->PageSize));\r
+ UsbHcFreeAlignedPages ((VOID*) (UINTN) ScratchEntry[Index], EFI_SIZE_TO_PAGES (Xhc->PageSize), (VOID *) Xhc->ScratchEntryMap[Index]);\r
}\r
//\r
// Free Scratchpad Buffer Array\r
//\r
- UsbHcFreeAlignedPages (Xhc->ScratchBuf, EFI_SIZE_TO_PAGES (Xhc->MaxScratchpadBufs * sizeof (UINT64)));\r
+ UsbHcFreeAlignedPages (Xhc->ScratchBuf, EFI_SIZE_TO_PAGES (Xhc->MaxScratchpadBufs * sizeof (UINT64)), Xhc->ScratchMap);\r
+ FreePool (Xhc->ScratchEntryMap);\r
FreePool (Xhc->ScratchEntry);\r
}\r
\r