39 return EFI_OUT_OF_RESOURCES;
42 Qtd->QtdHw.Status = QTD_STAT_HALTED;
43 Ehc->ShortReadStop = Qtd;
51 Ep.Direction = EfiUsbDataIn;
52 Ep.DevSpeed = EFI_USB_SPEED_HIGH;
57 Ep.Type = EHC_BULK_TRANSFER;
63 return EFI_OUT_OF_RESOURCES;
69 QhHw->Status = QTD_STAT_HALTED;
70 QhHw->ReclaimHead = 1;
72 Ehc->ReclaimHead = Qh;
78 Ep.Type = EHC_INT_TRANSFER_SYNC;
83 return EFI_OUT_OF_RESOURCES;
86 Qh->QhHw.Status = QTD_STAT_HALTED;
128 Status = PciIo->AllocateBuffer (
137 if (EFI_ERROR (Status)) {
138 return EFI_OUT_OF_RESOURCES;
141 Status = PciIo->Map (
150 if (EFI_ERROR (Status) || (Bytes != 4096)) {
151 PciIo->FreeBuffer (PciIo, Pages, Buf);
152 return EFI_OUT_OF_RESOURCES;
155 Ehc->PeriodFrame = Buf;
156 Ehc->PeriodFrameMap = Map;
161 EhcWriteOpReg (Ehc, EHC_FRAME_BASE_OFFSET, EHC_LOW_32BIT (PhyAddr));
165 EhcWriteOpReg (Ehc, EHC_CTRLDSSEG_OFFSET, EHC_HIGH_32BIT (PhyAddr));
174 Ehc->Support64BitDma,
175 EHC_HIGH_32BIT (PhyAddr)
178 if (Ehc->MemPool ==
NULL) {
179 Status = EFI_OUT_OF_RESOURCES;
185 if (EFI_ERROR (Status)) {
193 if (Ehc->PeriodFrameHost ==
NULL) {
194 Status = EFI_OUT_OF_RESOURCES;
200 for (Index = 0; Index < EHC_FRAME_LEN; Index++) {
204 ((UINT32 *)(Ehc->PeriodFrame))[Index] = QH_LINK (PciAddr, EHC_TYPE_QH,
FALSE);
208 ((
UINTN *)(Ehc->PeriodFrameHost))[Index] = (
UINTN)Ehc->PeriodOne;
217 EhcWriteOpReg (Ehc, EHC_ASYNC_HEAD_OFFSET, EHC_LOW_32BIT (PciAddr));
221 if (Ehc->PeriodOne !=
NULL) {
223 Ehc->PeriodOne =
NULL;
226 if (Ehc->ReclaimHead !=
NULL) {
228 Ehc->ReclaimHead =
NULL;
231 if (Ehc->ShortReadStop !=
NULL) {
233 Ehc->ShortReadStop =
NULL;
237 PciIo->FreeBuffer (PciIo, Pages, Buf);
238 PciIo->Unmap (PciIo, Map);
259 if (Ehc->PeriodOne !=
NULL) {
261 Ehc->PeriodOne =
NULL;
264 if (Ehc->ReclaimHead !=
NULL) {
266 Ehc->ReclaimHead =
NULL;
269 if (Ehc->ShortReadStop !=
NULL) {
271 Ehc->ShortReadStop =
NULL;
274 if (Ehc->MemPool !=
NULL) {
279 if (Ehc->PeriodFrame !=
NULL) {
281 ASSERT (PciIo !=
NULL);
283 PciIo->Unmap (PciIo, Ehc->PeriodFrameMap);
291 Ehc->PeriodFrame =
NULL;
294 if (Ehc->PeriodFrameHost !=
NULL) {
296 Ehc->PeriodFrameHost =
NULL;
325 Head = Ehc->ReclaimHead;
327 Qh->NextQh = Head->NextQh;
331 Qh->QhHw.HorizonLink = QH_LINK (PciAddr, EHC_TYPE_QH,
FALSE);
333 Head->QhHw.HorizonLink = QH_LINK (PciAddr, EHC_TYPE_QH,
FALSE);
354 ASSERT (Ehc->ReclaimHead->NextQh == Qh);
361 Head = Ehc->ReclaimHead;
363 Head->NextQh = Qh->NextQh;
367 Head->QhHw.HorizonLink = QH_LINK (PciAddr, EHC_TYPE_QH,
FALSE);
374 if (EFI_ERROR (Status)) {
375 DEBUG ((DEBUG_ERROR,
"EhcUnlinkQhFromAsync: Failed to synchronize with doorbell\n"));
399 for (Index = 0; Index < EHC_FRAME_LEN; Index += Qh->Interval) {
404 ASSERT (!EHC_LINK_TERMINATED (((UINT32 *)Ehc->PeriodFrame)[Index]));
405 Next = (
EHC_QH *)((
UINTN *)Ehc->PeriodFrameHost)[Index];
418 while (Next->Interval > Qh->Interval) {
423 ASSERT (Next !=
NULL);
438 if (Next->Interval == Qh->Interval) {
444 ASSERT ((Index == 0) && (Qh->NextQh ==
NULL));
452 Qh->QhHw.HorizonLink = Prev->QhHw.HorizonLink;
454 Prev->QhHw.HorizonLink = QH_LINK (PciAddr, EHC_TYPE_QH,
FALSE);
463 if (Qh->NextQh ==
NULL) {
466 Qh->QhHw.HorizonLink = QH_LINK (PciAddr, EHC_TYPE_QH,
FALSE);
472 ((UINT32 *)Ehc->PeriodFrame)[Index] = QH_LINK (PciAddr, EHC_TYPE_QH,
FALSE);
473 ((
UINTN *)Ehc->PeriodFrameHost)[Index] = (
UINTN)Qh;
476 Prev->QhHw.HorizonLink = QH_LINK (PciAddr, EHC_TYPE_QH,
FALSE);
499 for (Index = 0; Index < EHC_FRAME_LEN; Index += Qh->Interval) {
504 ASSERT (!EHC_LINK_TERMINATED (((UINT32 *)Ehc->PeriodFrame)[Index]));
505 This = (
EHC_QH *)((
UINTN *)Ehc->PeriodFrameHost)[Index];
512 while ((This !=
NULL) && (This != Qh)) {
529 ((UINT32 *)Ehc->PeriodFrame)[Index] = Qh->QhHw.HorizonLink;
530 ((
UINTN *)Ehc->PeriodFrameHost)[Index] = (
UINTN)Qh->NextQh;
532 Prev->NextQh = Qh->NextQh;
533 Prev->QhHw.HorizonLink = Qh->QhHw.HorizonLink;
561 ASSERT ((Ehc !=
NULL) && (Urb !=
NULL) && (Urb->Qh !=
NULL));
566 Urb->Result = EFI_USB_NOERROR;
569 Urb->Result |= EFI_USB_ERR_SYSTEM;
574 Qtd = EFI_LIST_CONTAINER (Entry,
EHC_QTD, QtdList);
576 State = (UINT8)QtdHw->Status;
578 if (EHC_BIT_IS_SET (State, QTD_STAT_HALTED)) {
583 if ((State & QTD_STAT_ERR_MASK) == 0) {
584 Urb->Result |= EFI_USB_ERR_STALL;
587 if (EHC_BIT_IS_SET (State, QTD_STAT_BABBLE_ERR)) {
588 Urb->Result |= EFI_USB_ERR_BABBLE;
591 if (EHC_BIT_IS_SET (State, QTD_STAT_BUFF_ERR)) {
592 Urb->Result |= EFI_USB_ERR_BUFFER;
595 if (EHC_BIT_IS_SET (State, QTD_STAT_TRANS_ERR) && (QtdHw->ErrCnt == 0)) {
596 Urb->Result |= EFI_USB_ERR_TIMEOUT;
601 }
else if (EHC_BIT_IS_SET (State, QTD_STAT_ACTIVE)) {
605 Urb->Result |= EFI_USB_ERR_NOTEXECUTE;
614 if (QtdHw->Pid != QTD_PID_SETUP) {
615 Urb->Completed += Qtd->DataLen - QtdHw->TotalBytes;
618 if ((QtdHw->TotalBytes != 0) && (QtdHw->Pid == QTD_PID_INPUT)) {
628 if (QtdHw->AltNext == QTD_LINK (PciAddr,
FALSE)) {
629 DEBUG ((DEBUG_VERBOSE,
"EhcCheckUrbResult: Short packet read, break\n"));
635 DEBUG ((DEBUG_VERBOSE,
"EhcCheckUrbResult: Short packet read, continue\n"));
650 Urb->DataToggle = (UINT8)Urb->Qh->QhHw.DataToggle;
678 BOOLEAN InfiniteLoop;
681 Loop = TimeOut * EHC_1_MILLISECOND;
683 InfiniteLoop =
FALSE;
694 for (Index = 0; InfiniteLoop || (Index < Loop); Index++) {
701 gBS->Stall (EHC_1_MICROSECOND);
705 DEBUG ((DEBUG_VERBOSE,
"EhcExecTransfer: transfer not finished in %dms\n", (UINT32)TimeOut));
708 Status = EFI_TIMEOUT;
709 }
else if (Urb->Result != EFI_USB_NOERROR) {
710 DEBUG ((DEBUG_ERROR,
"EhcExecTransfer: transfer failed with %x\n", Urb->Result));
713 Status = EFI_DEVICE_ERROR;
737 OUT UINT8 *DataToggle
745 Direction = (((EpNum & 0x80) != 0) ? EfiUsbDataIn : EfiUsbDataOut);
749 Urb = EFI_LIST_CONTAINER (Entry,
URB, UrbList);
751 if ((Urb->Ep.DevAddr == DevAddr) && (Urb->Ep.EpAddr == EpNum) &&
752 (Urb->Ep.Direction == Direction))
759 *DataToggle = Urb->DataToggle;
764 gBS->FreePool (Urb->Data);
770 return EFI_NOT_FOUND;
789 Urb = EFI_LIST_CONTAINER (Entry,
URB, UrbList);
794 gBS->FreePool (Urb->Data);
839 DEBUG ((DEBUG_ERROR,
"%a: failed to allocate buffer\n", __func__));
851 EHC_INT_TRANSFER_ASYNC,
861 DEBUG ((DEBUG_ERROR,
"%a: failed to create URB\n", __func__));
862 gBS->FreePool (Data);
903 if (Urb->Ep.Direction == EfiUsbDataIn) {
909 Status = PciIo->Unmap (PciIo, Urb->DataMap);
910 if (EFI_ERROR (Status)) {
916 Status = PciIo->Map (PciIo, MapOp, Urb->Data, &Len, &PhyAddr, &Map);
917 if (EFI_ERROR (Status) || (Len != Urb->DataLen)) {
921 Urb->DataPhy = (VOID *)((
UINTN)PhyAddr);
926 return EFI_DEVICE_ERROR;
952 if (Urb->Result == EFI_USB_NOERROR) {
956 Qtd = EFI_LIST_CONTAINER (Entry,
EHC_QTD, QtdList);
958 if (FirstQtd ==
NULL) {
971 QtdHw->Status = QTD_STAT_ACTIVE;
972 QtdHw->ErrCnt = QTD_MAX_ERR;
974 QtdHw->TotalBytes = (UINT32)Qtd->DataLen;
979 QtdHw->Page[0] = EHC_LOW_32BIT (PciAddr);
980 QtdHw->PageHigh[0] = EHC_HIGH_32BIT (PciAddr);
989 QhHw = &Urb->Qh->QhHw;
990 QhHw->CurQtd = QTD_LINK (0,
TRUE);
998 QhHw->TotalBytes = 0;
1000 for (Index = 0; Index < 5; Index++) {
1001 QhHw->Page[Index] = 0;
1002 QhHw->PageHigh[Index] = 0;
1006 QhHw->NextQtd = QTD_LINK (PciAddr,
FALSE);
1035 OldTpl =
gBS->RaiseTPL (EHC_TPL);
1039 Urb = EFI_LIST_CONTAINER (Entry,
URB, UrbList);
1056 if (EFI_ERROR (Status)) {
1057 DEBUG ((DEBUG_ERROR,
"EhcMonitorAsyncRequests: Fail to Flush AsyncInt Mapped Memeory\n"));
1067 if (Urb->Result == EFI_USB_NOERROR) {
1071 if (Urb->Completed <= Urb->DataLen) {
1075 if (ProcBuf ==
NULL) {
1080 CopyMem (ProcBuf, Urb->Data, Urb->Completed);
1095 if (Urb->Callback !=
NULL) {
1100 gBS->RestoreTPL (OldTpl);
1101 (Urb->Callback)(ProcBuf, Urb->Completed, Urb->Context, Urb->Result);
1102 OldTpl =
gBS->RaiseTPL (EHC_TPL);
1105 if (ProcBuf !=
NULL) {
1110 gBS->RestoreTPL (OldTpl);
LIST_ENTRY *EFIAPI InsertHeadList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
#define BASE_LIST_FOR_EACH_SAFE(Entry, NextEntry, ListHead)
#define BASE_LIST_FOR_EACH(Entry, ListHead)
LIST_ENTRY *EFIAPI RemoveEntryList(IN CONST LIST_ENTRY *Entry)
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID EhcDumpQh(IN EHC_QH *Qh, IN CHAR8 *Msg, IN BOOLEAN DumpBuf)
URB * EhciInsertAsyncIntTransfer(IN USB2_HC_DEV *Ehc, IN UINT8 DevAddr, IN UINT8 EpAddr, IN UINT8 DevSpeed, IN UINT8 Toggle, IN UINTN MaxPacket, IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Hub, IN UINTN DataLen, IN EFI_ASYNC_USB_TRANSFER_CALLBACK Callback, IN VOID *Context, IN UINTN Interval)
BOOLEAN EhcCheckUrbResult(IN USB2_HC_DEV *Ehc, IN URB *Urb)
EFI_STATUS EhcInitSched(IN USB2_HC_DEV *Ehc)
EFI_STATUS EhciDelAsyncIntTransfer(IN USB2_HC_DEV *Ehc, IN UINT8 DevAddr, IN UINT8 EpNum, OUT UINT8 *DataToggle)
VOID EhcLinkQhToAsync(IN USB2_HC_DEV *Ehc, IN EHC_QH *Qh)
VOID EhcUpdateAsyncRequest(IN USB2_HC_DEV *Ehc, IN URB *Urb)
VOID EhcFreeSched(IN USB2_HC_DEV *Ehc)
VOID EFIAPI EhcMonitorAsyncRequests(IN EFI_EVENT Event, IN VOID *Context)
EFI_STATUS EhcCreateHelpQ(IN USB2_HC_DEV *Ehc)
EFI_STATUS EhcExecTransfer(IN USB2_HC_DEV *Ehc, IN URB *Urb, IN UINTN TimeOut)
VOID EhcUnlinkQhFromPeriod(IN USB2_HC_DEV *Ehc, IN EHC_QH *Qh)
VOID EhciDelAllAsyncIntTransfers(IN USB2_HC_DEV *Ehc)
VOID EhcLinkQhToPeriod(IN USB2_HC_DEV *Ehc, IN EHC_QH *Qh)
VOID EhcUnlinkQhFromAsync(IN USB2_HC_DEV *Ehc, IN EHC_QH *Qh)
EFI_STATUS EhcFlushAsyncIntMap(IN USB2_HC_DEV *Ehc, IN URB *Urb)
EHC_QTD * EhcCreateQtd(IN USB2_HC_DEV *Ehc, IN UINT8 *Data, IN UINT8 *DataPhy, IN UINTN DataLen, IN UINT8 PktId, IN UINT8 Toggle, IN UINTN MaxPacket)
EHC_QH * EhcCreateQh(IN USB2_HC_DEV *Ehci, IN USB_ENDPOINT *Ep)
URB * EhcCreateUrb(IN USB2_HC_DEV *Ehc, IN UINT8 DevAddr, IN UINT8 EpAddr, IN UINT8 DevSpeed, IN UINT8 Toggle, IN UINTN MaxPacket, IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Hub, IN UINTN Type, IN EFI_USB_DEVICE_REQUEST *Request, IN VOID *Data, IN UINTN DataLen, IN EFI_ASYNC_USB_TRANSFER_CALLBACK Callback, IN VOID *Context, IN UINTN Interval)
VOID EhcFreeUrb(IN USB2_HC_DEV *Ehc, IN URB *Urb)
EFI_PHYSICAL_ADDRESS UsbHcGetPciAddressForHostMem(IN USBHC_MEM_POOL *Pool, IN VOID *Mem, IN UINTN Size)
EFI_STATUS UsbHcFreeMemPool(IN USBHC_MEM_POOL *Pool)
VOID UsbHcFreeMem(IN USBHC_MEM_POOL *Pool, IN VOID *Mem, IN UINTN Size)
USBHC_MEM_POOL * UsbHcInitMemPool(IN EFI_PCI_IO_PROTOCOL *PciIo, IN BOOLEAN Check4G, IN UINT32 Which4G)
VOID EhcWriteOpReg(IN USB2_HC_DEV *Ehc, IN UINT32 Offset, IN UINT32 Data)
EFI_STATUS EhcSetAndWaitDoorBell(IN USB2_HC_DEV *Ehc, IN UINT32 Timeout)
BOOLEAN EhcIsHalt(IN USB2_HC_DEV *Ehc)
BOOLEAN EhcIsSysError(IN USB2_HC_DEV *Ehc)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
#define OFFSET_OF(TYPE, Field)
#define DEBUG(Expression)
EFI_PCI_IO_PROTOCOL_OPERATION
@ EfiPciIoOperationBusMasterWrite
@ EfiPciIoOperationBusMasterRead
@ 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)