45 Status = Uhc->PciIo->AllocateBuffer (
54 if (EFI_ERROR (Status)) {
55 return EFI_OUT_OF_RESOURCES;
58 Status = Uhc->PciIo->Map (
67 if (EFI_ERROR (Status) || (Bytes != 4096)) {
68 Status = EFI_UNSUPPORTED;
72 Uhc->FrameBase = (UINT32 *)(
UINTN)Buffer;
73 Uhc->FrameMapping = Mapping;
91 if ((Uhc->SyncIntQh ==
NULL) || (Uhc->CtrlQh ==
NULL) || (Uhc->BulkQh ==
NULL)) {
92 Uhc->PciIo->Unmap (Uhc->PciIo, Mapping);
93 Status = EFI_OUT_OF_RESOURCES;
105 Uhc->SyncIntQh->QhHw.HorizonLink = QH_HLINK (PhyAddr,
FALSE);
106 Uhc->SyncIntQh->NextQh = Uhc->CtrlQh;
109 Uhc->CtrlQh->QhHw.HorizonLink = QH_HLINK (PhyAddr,
FALSE);
110 Uhc->CtrlQh->NextQh = Uhc->BulkQh;
117 Uhc->BulkQh->QhHw.HorizonLink = QH_HLINK (PhyAddr,
FALSE);
119 Uhc->BulkQh->NextQh =
NULL;
122 if (Uhc->FrameBaseHostAddr ==
NULL) {
123 Status = EFI_OUT_OF_RESOURCES;
128 for (Index = 0; Index < UHCI_FRAME_NUM; Index++) {
129 Uhc->FrameBase[Index] = QH_HLINK (PhyAddr,
FALSE);
130 Uhc->FrameBaseHostAddr[Index] = (UINT32)(
UINTN)Uhc->SyncIntQh;
136 if (Uhc->SyncIntQh !=
NULL) {
140 if (Uhc->CtrlQh !=
NULL) {
144 if (Uhc->BulkQh !=
NULL) {
148 Uhc->PciIo->FreeBuffer (Uhc->PciIo, Pages, Buffer);
168 Uhc->PciIo->Unmap (Uhc->PciIo, Uhc->FrameMapping);
170 Uhc->PciIo->FreeBuffer (
173 (VOID *)Uhc->FrameBase
176 if (Uhc->FrameBaseHostAddr !=
NULL) {
180 if (Uhc->SyncIntQh !=
NULL) {
184 if (Uhc->CtrlQh !=
NULL) {
188 if (Uhc->BulkQh !=
NULL) {
192 Uhc->FrameBase =
NULL;
193 Uhc->FrameBaseHostAddr =
NULL;
194 Uhc->SyncIntQh =
NULL;
215 ASSERT (Interval != 0);
230 while (Interval != 0) {
235 return (
UINTN)1 << (BitCount - 1);
258 ASSERT ((Uhc->FrameBase !=
NULL) && (Qh !=
NULL));
262 for (Index = 0; Index < UHCI_FRAME_NUM; Index += Qh->Interval) {
267 ASSERT (!LINK_TERMINATED (Uhc->FrameBase[Index]));
285 while (Next->Interval > Qh->Interval) {
288 ASSERT (Next !=
NULL);
304 if (Next->Interval == Qh->Interval) {
310 ASSERT ((Index == 0) && (Qh->NextQh ==
NULL));
318 Qh->QhHw.HorizonLink = Prev->QhHw.HorizonLink;
320 Prev->QhHw.HorizonLink = QH_HLINK (QhPciAddr,
FALSE);
329 if (Qh->NextQh ==
NULL) {
332 Qh->QhHw.HorizonLink = QH_HLINK (PhyAddr,
FALSE);
336 Uhc->FrameBase[Index] = QH_HLINK (QhPciAddr,
FALSE);
337 Uhc->FrameBaseHostAddr[Index] = (UINT32)(
UINTN)Qh;
340 Prev->QhHw.HorizonLink = QH_HLINK (QhPciAddr,
FALSE);
364 ASSERT ((Uhc->FrameBase !=
NULL) && (Qh !=
NULL));
366 for (Index = 0; Index < UHCI_FRAME_NUM; Index += Qh->Interval) {
371 ASSERT (!LINK_TERMINATED (Uhc->FrameBase[Index]));
379 while ((This !=
NULL) && (This != Qh)) {
396 Uhc->FrameBase[Index] = Qh->QhHw.HorizonLink;
397 Uhc->FrameBaseHostAddr[Index] = (UINT32)(
UINTN)Qh->NextQh;
399 Prev->NextQh = Qh->NextQh;
400 Prev->QhHw.HorizonLink = Qh->QhHw.HorizonLink;
437 QhResult->Result = EFI_USB_NOERROR;
438 QhResult->NextToggle = (UINT8)Td->TdHw.DataToggle;
439 QhResult->Complete = 0;
443 State = (UINT8)TdHw->Status;
459 if ((State & USBTD_STALLED) != 0) {
460 if ((State & USBTD_BABBLE) != 0) {
461 QhResult->Result |= EFI_USB_ERR_BABBLE;
462 }
else if (TdHw->ErrorCount != 0) {
463 QhResult->Result |= EFI_USB_ERR_STALL;
466 if ((State & USBTD_CRC) != 0) {
467 QhResult->Result |= EFI_USB_ERR_CRC;
470 if ((State & USBTD_BUFFERR) != 0) {
471 QhResult->Result |= EFI_USB_ERR_BUFFER;
474 if ((Td->TdHw.Status & USBTD_BITSTUFF) != 0) {
475 QhResult->Result |= EFI_USB_ERR_BITSTUFF;
478 if (TdHw->ErrorCount == 0) {
479 QhResult->Result |= EFI_USB_ERR_TIMEOUT;
484 }
else if ((State & USBTD_ACTIVE) != 0) {
488 QhResult->Result |= EFI_USB_ERR_NOTEXECUTE;
498 QhResult->NextToggle = (UINT8)(1 - (UINT8)TdHw->DataToggle);
504 Len = (TdHw->ActualLen + 1) & 0x7FF;
506 if (TdHw->PidCode != SETUP_PACKET_ID) {
507 QhResult->Complete += Len;
514 if (!IsLow && (TdHw->ShortPacket == 1) && (Len < Td->DataLen)) {
515 DEBUG ((DEBUG_VERBOSE,
"UhciCheckTdStatus: short packet read occurred\n"));
531 QhResult->Result |= EFI_USB_ERR_SYSTEM;
536 Uhc->PciIo->Flush (Uhc->PciIo);
571 BOOLEAN InfiniteLoop;
575 Delay = TimeOut * UHC_1_MILLISECOND;
576 InfiniteLoop =
FALSE;
587 for (Index = 0; InfiniteLoop || (Index < Delay); Index++) {
597 gBS->Stall (UHC_1_MICROSECOND);
601 DEBUG ((DEBUG_ERROR,
"UhciExecuteTransfer: execution not finished for %dms\n", (UINT32)TimeOut));
605 Status = EFI_TIMEOUT;
606 }
else if (QhResult->Result != EFI_USB_NOERROR) {
607 DEBUG ((DEBUG_ERROR,
"UhciExecuteTransfer: execution failed with result %x\n", QhResult->Result));
611 Status = EFI_DEVICE_ERROR;
639 FirstTd = AsyncReq->FirstTd;
641 if (Result == EFI_USB_NOERROR) {
651 for (Td = FirstTd; Td !=
NULL; Td = Td->NextTd) {
652 Td->TdHw.DataToggle = NextToggle;
654 Td->TdHw.Status |= USBTD_ACTIVE;
701 if (AsyncReq ==
NULL) {
702 return EFI_OUT_OF_RESOURCES;
708 AsyncReq->Signature = UHCI_ASYNC_INT_SIGNATURE;
709 AsyncReq->DevAddr = DevAddr;
710 AsyncReq->EndPoint = EndPoint;
711 AsyncReq->DataLen = DataLen;
713 AsyncReq->Data = Data;
714 AsyncReq->Callback = Callback;
715 AsyncReq->Context = Context;
717 AsyncReq->FirstTd = FirstTd;
718 AsyncReq->IsLow = IsLow;
744 ASSERT ((Uhc !=
NULL) && (AsyncReq !=
NULL));
749 if (AsyncReq->Data !=
NULL) {
750 UsbHcFreeMem (Uhc->MemPool, AsyncReq->Data, AsyncReq->DataLen);
753 gBS->FreePool (AsyncReq);
776 ASSERT ((Uhc !=
NULL) && (AsyncReq !=
NULL));
788 AsyncReq->QhSw->QhHw.VerticalLink = QH_VLINK (
NULL,
TRUE);
789 AsyncReq->Recycle = Uhc->RecycleWait;
790 Uhc->RecycleWait = AsyncReq;
834 Link = Uhc->AsyncIntList.ForwardLink;
837 AsyncReq = UHCI_ASYNC_INT_FROM_LINK (Link);
838 Link = Link->ForwardLink;
840 if ((AsyncReq->DevAddr == DevAddr) && (AsyncReq->EndPoint == EndPoint)) {
844 }
while (Link != &(Uhc->AsyncIntList));
847 return EFI_NOT_FOUND;
855 *Toggle = QhResult.NextToggle;
890 while (Req !=
NULL) {
896 Uhc->Recycle = Uhc->RecycleWait;
897 Uhc->RecycleWait =
NULL;
922 Head = &(Uhc->AsyncIntList);
929 AsyncReq = UHCI_ASYNC_INT_FROM_LINK (Head->ForwardLink);
971 Link = Uhc->AsyncIntList.ForwardLink;
974 AsyncReq = UHCI_ASYNC_INT_FROM_LINK (Link);
975 Link = Link->ForwardLink;
977 Finished =
UhciCheckTdStatus (Uhc, AsyncReq->FirstTd, AsyncReq->IsLow, &QhResult);
990 if ((QhResult.Complete != 0) && (QhResult.Complete <= AsyncReq->DataLen)) {
997 CopyMem (Data, AsyncReq->FirstTd->Data, QhResult.Complete);
1007 if (QhResult.Result == EFI_USB_NOERROR) {
1008 AsyncReq->Callback (Data, QhResult.Complete, AsyncReq->Context, QhResult.Result);
1020 AsyncReq->Callback (
NULL, 0, AsyncReq->Context, QhResult.Result);
1024 gBS->FreePool (Data);
1026 }
while (Link != &(Uhc->AsyncIntList));
BOOLEAN EFIAPI IsListEmpty(IN CONST LIST_ENTRY *ListHead)
LIST_ENTRY *EFIAPI InsertHeadList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
LIST_ENTRY *EFIAPI RemoveEntryList(IN CONST LIST_ENTRY *Entry)
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
EFI_PHYSICAL_ADDRESS UsbHcGetPciAddressForHostMem(IN USBHC_MEM_POOL *Pool, IN VOID *Mem, IN UINTN Size)
VOID UsbHcFreeMem(IN USBHC_MEM_POOL *Pool, IN VOID *Mem, IN UINTN Size)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
#define DEBUG(Expression)
@ EfiPciIoOperationBusMasterCommonBuffer
EFI_STATUS(EFIAPI * EFI_ASYNC_USB_TRANSFER_CALLBACK)(IN VOID *Data, IN UINTN DataLength, IN VOID *Context, IN UINT32 Status)
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
UINT64 EFI_PHYSICAL_ADDRESS
#define EFI_SIZE_TO_PAGES(Size)
VOID UhciDumpQh(IN UHCI_QH_SW *QhSw)
VOID UhciDumpTds(IN UHCI_TD_SW *TdSw)
VOID UhciDestoryTds(IN USB_HC_DEV *Uhc, IN UHCI_TD_SW *FirstTd)
VOID UhciLinkTdToQh(IN USB_HC_DEV *Uhc, IN UHCI_QH_SW *Qh, IN UHCI_TD_SW *Td)
UHCI_QH_SW * UhciCreateQh(IN USB_HC_DEV *Uhc, IN UINTN Interval)
BOOLEAN UhciIsHcWorking(IN EFI_PCI_IO_PROTOCOL *PciIo)
VOID UhciSetFrameListBaseAddr(IN EFI_PCI_IO_PROTOCOL *PciIo, IN VOID *Addr)
VOID UhciAckAllInterrupt(IN USB_HC_DEV *Uhc)
VOID UhciFreeAsyncReq(IN USB_HC_DEV *Uhc, IN UHCI_ASYNC_REQUEST *AsyncReq)
EFI_STATUS UhciInitFrameList(IN USB_HC_DEV *Uhc)
EFI_STATUS UhciExecuteTransfer(IN USB_HC_DEV *Uhc, IN UHCI_QH_SW *Qh, IN UHCI_TD_SW *Td, IN UINTN TimeOut, IN BOOLEAN IsLow, OUT UHCI_QH_RESULT *QhResult)
VOID UhciFreeAllAsyncReq(IN USB_HC_DEV *Uhc)
VOID EFIAPI UhciMonitorAsyncReqList(IN EFI_EVENT Event, IN VOID *Context)
BOOLEAN UhciCheckTdStatus(IN USB_HC_DEV *Uhc, IN UHCI_TD_SW *Td, IN BOOLEAN IsLow, OUT UHCI_QH_RESULT *QhResult)
VOID UhciRecycleAsyncReq(IN USB_HC_DEV *Uhc)
VOID UhciLinkQhToFrameList(USB_HC_DEV *Uhc, UHCI_QH_SW *Qh)
VOID UhciUpdateAsyncReq(IN USB_HC_DEV *Uhc, IN UHCI_ASYNC_REQUEST *AsyncReq, IN UINT32 Result, IN UINT32 NextToggle)
VOID UhciDestoryFrameList(IN USB_HC_DEV *Uhc)
VOID UhciUnlinkAsyncReq(IN USB_HC_DEV *Uhc, IN UHCI_ASYNC_REQUEST *AsyncReq, IN BOOLEAN FreeNow)
EFI_STATUS UhciRemoveAsyncReq(IN USB_HC_DEV *Uhc, IN UINT8 DevAddr, IN UINT8 EndPoint, OUT UINT8 *Toggle)
UINTN UhciConvertPollRate(IN UINTN Interval)
EFI_STATUS UhciCreateAsyncReq(IN USB_HC_DEV *Uhc, IN UHCI_QH_SW *Qh, IN UHCI_TD_SW *FirstTd, IN UINT8 DevAddr, IN UINT8 EndPoint, IN UINTN DataLen, IN UINTN Interval, IN UINT8 *Data, IN EFI_ASYNC_USB_TRANSFER_CALLBACK Callback, IN VOID *Context, IN BOOLEAN IsLow)
VOID UhciUnlinkQhFromFrameList(USB_HC_DEV *Uhc, UHCI_QH_SW *Qh)