/**\r
Create a new URB for a new transaction.\r
\r
- @param Xhc The XHCI Instance\r
- @param BusAddr The logical device address assigned by UsbBus driver\r
- @param EpAddr Endpoint addrress\r
- @param DevSpeed The device speed\r
- @param MaxPacket The max packet length of the endpoint\r
- @param Type The transaction type\r
- @param Request The standard USB request for control transfer\r
- @param Data The user data to transfer\r
- @param DataLen The length of data buffer\r
- @param Callback The function to call when data is transferred\r
- @param Context The context to the callback\r
+ @param Xhc The XHCI Instance\r
+ @param BusAddr The logical device address assigned by UsbBus driver\r
+ @param EpAddr Endpoint addrress\r
+ @param DevSpeed The device speed\r
+ @param MaxPacket The max packet length of the endpoint\r
+ @param Type The transaction type\r
+ @param Request The standard USB request for control transfer\r
+ @param AllocateCommonBuffer Indicate whether need to allocate common buffer for data transfer\r
+ @param Data The user data to transfer, NULL if AllocateCommonBuffer is TRUE\r
+ @param DataLen The length of data buffer\r
+ @param Callback The function to call when data is transferred\r
+ @param Context The context to the callback\r
\r
@return Created URB or NULL\r
\r
IN UINTN MaxPacket,\r
IN UINTN Type,\r
IN EFI_USB_DEVICE_REQUEST *Request,\r
+ IN BOOLEAN AllocateCommonBuffer,\r
IN VOID *Data,\r
IN UINTN DataLen,\r
IN EFI_ASYNC_USB_TRANSFER_CALLBACK Callback,\r
Ep->Type = Type;\r
\r
Urb->Request = Request;\r
+ if (AllocateCommonBuffer) {\r
+ ASSERT (Data == NULL);\r
+ Status = Xhc->PciIo->AllocateBuffer (\r
+ Xhc->PciIo,\r
+ AllocateAnyPages,\r
+ EfiBootServicesData,\r
+ EFI_SIZE_TO_PAGES (DataLen),\r
+ &Data,\r
+ 0\r
+ );\r
+ if (EFI_ERROR (Status) || (Data == NULL)) {\r
+ FreePool (Urb);\r
+ return NULL;\r
+ }\r
+ }\r
Urb->Data = Data;\r
Urb->DataLen = DataLen;\r
+ Urb->AllocateCommonBuffer = AllocateCommonBuffer;\r
Urb->Callback = Callback;\r
Urb->Context = Context;\r
\r
ASSERT_EFI_ERROR (Status);\r
if (EFI_ERROR (Status)) {\r
DEBUG ((EFI_D_ERROR, "XhcCreateUrb: XhcCreateTransferTrb Failed, Status = %r\n", Status));\r
- FreePool (Urb);\r
+ XhcFreeUrb (Xhc, Urb);\r
Urb = NULL;\r
}\r
\r
Xhc->PciIo->Unmap (Xhc->PciIo, Urb->DataMap);\r
}\r
\r
+ if (Urb->AllocateCommonBuffer) {\r
+ Xhc->PciIo->FreeBuffer (\r
+ Xhc->PciIo,\r
+ EFI_SIZE_TO_PAGES (Urb->DataLen),\r
+ Urb->Data\r
+ );\r
+ }\r
+\r
FreePool (Urb);\r
}\r
\r
// No need to remap.\r
//\r
if ((Urb->Data != NULL) && (Urb->DataMap == NULL)) {\r
- if (((UINT8) (Urb->Ep.Direction)) == EfiUsbDataIn) {\r
- MapOp = EfiPciIoOperationBusMasterWrite;\r
+ if (Urb->AllocateCommonBuffer) {\r
+ MapOp = EfiPciIoOperationBusMasterCommonBuffer;\r
} else {\r
- MapOp = EfiPciIoOperationBusMasterRead;\r
+ if (((UINT8) (Urb->Ep.Direction)) == EfiUsbDataIn) {\r
+ MapOp = EfiPciIoOperationBusMasterWrite;\r
+ } else {\r
+ MapOp = EfiPciIoOperationBusMasterRead;\r
+ }\r
}\r
\r
Len = Urb->DataLen;\r
}\r
\r
RemoveEntryList (&Urb->UrbList);\r
- FreePool (Urb->Data);\r
XhcFreeUrb (Xhc, Urb);\r
return EFI_SUCCESS;\r
}\r
}\r
\r
RemoveEntryList (&Urb->UrbList);\r
- FreePool (Urb->Data);\r
XhcFreeUrb (Xhc, Urb);\r
}\r
}\r
IN VOID *Context\r
)\r
{\r
- VOID *Data;\r
URB *Urb;\r
\r
- Data = AllocateZeroPool (DataLen);\r
- if (Data == NULL) {\r
- DEBUG ((DEBUG_ERROR, "%a: failed to allocate buffer\n", __FUNCTION__));\r
- return NULL;\r
- }\r
-\r
Urb = XhcCreateUrb (\r
Xhc,\r
BusAddr,\r
MaxPacket,\r
XHC_INT_TRANSFER_ASYNC,\r
NULL,\r
- Data,\r
+ TRUE,\r
+ NULL,\r
DataLen,\r
Callback,\r
Context\r
);\r
if (Urb == NULL) {\r
DEBUG ((DEBUG_ERROR, "%a: failed to create URB\n", __FUNCTION__));\r
- FreePool (Data);\r
return NULL;\r
}\r
\r
}\r
}\r
\r
-/**\r
- Flush data from PCI controller specific address to mapped system\r
- memory address.\r
-\r
- @param Xhc The XHCI device.\r
- @param Urb The URB to unmap.\r
-\r
- @retval EFI_SUCCESS Success to flush data to mapped system memory.\r
- @retval EFI_DEVICE_ERROR Fail to flush data to mapped system memory.\r
-\r
-**/\r
-EFI_STATUS\r
-XhcFlushAsyncIntMap (\r
- IN USB_XHCI_INSTANCE *Xhc,\r
- IN URB *Urb\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_PHYSICAL_ADDRESS PhyAddr;\r
- EFI_PCI_IO_PROTOCOL_OPERATION MapOp;\r
- EFI_PCI_IO_PROTOCOL *PciIo;\r
- UINTN Len;\r
- VOID *Map;\r
-\r
- PciIo = Xhc->PciIo;\r
- Len = Urb->DataLen;\r
-\r
- if (Urb->Ep.Direction == EfiUsbDataIn) {\r
- MapOp = EfiPciIoOperationBusMasterWrite;\r
- } else {\r
- MapOp = EfiPciIoOperationBusMasterRead;\r
- }\r
-\r
- if (Urb->DataMap != NULL) {\r
- Status = PciIo->Unmap (PciIo, Urb->DataMap);\r
- if (EFI_ERROR (Status)) {\r
- goto ON_ERROR;\r
- }\r
- }\r
-\r
- Urb->DataMap = NULL;\r
-\r
- Status = PciIo->Map (PciIo, MapOp, Urb->Data, &Len, &PhyAddr, &Map);\r
- if (EFI_ERROR (Status) || (Len != Urb->DataLen)) {\r
- goto ON_ERROR;\r
- }\r
-\r
- Urb->DataPhy = (VOID *) ((UINTN) PhyAddr);\r
- Urb->DataMap = Map;\r
- return EFI_SUCCESS;\r
-\r
-ON_ERROR:\r
- return EFI_DEVICE_ERROR;\r
-}\r
-\r
/**\r
Interrupt transfer periodic check handler.\r
\r
UINT8 *ProcBuf;\r
URB *Urb;\r
UINT8 SlotId;\r
- EFI_STATUS Status;\r
EFI_TPL OldTpl;\r
\r
OldTpl = gBS->RaiseTPL (XHC_TPL);\r
continue;\r
}\r
\r
- //\r
- // Flush any PCI posted write transactions from a PCI host\r
- // bridge to system memory.\r
- //\r
- Status = XhcFlushAsyncIntMap (Xhc, Urb);\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "XhcMonitorAsyncRequests: Fail to Flush AsyncInt Mapped Memeory\n"));\r
- }\r
-\r
//\r
// Allocate a buffer then copy the transferred data for user.\r
// If failed to allocate the buffer, update the URB for next\r