/** Create a ED @Param Ohc Device private data @retval ED descriptor pointer **/ ED_DESCRIPTOR * OhciCreateED ( USB_OHCI_HC_DEV *Ohc ) { ED_DESCRIPTOR *Ed; Ed = UsbHcAllocateMem(Ohc->MemPool, sizeof (ED_DESCRIPTOR)); if (Ed == NULL) { return NULL; } Ed->Word0.Skip = 1; Ed->TdTailPointer = NULL; Ed->Word2.TdHeadPointer = RIGHT_SHIFT_4 ((UINT32) NULL); Ed->NextED = NULL; return Ed; }
/** Create a ED @Param Ohc Device private data @retval ED descriptor pointer **/ ED_DESCRIPTOR * OhciCreateED ( USB_OHCI_HC_DEV *Ohc ) { ED_DESCRIPTOR *Ed; Ed = UsbHcAllocateMem(Ohc->MemPool, sizeof (ED_DESCRIPTOR)); if (Ed == NULL) { DEBUG ((EFI_D_INFO, "STV allocate ED fail !\r\n")); return NULL; } Ed->Word0.Skip = 1; Ed->TdTailPointer = 0; Ed->Word2.TdHeadPointer = 0; Ed->NextED = 0; return Ed; }
/** Create a TD @Param Ohc UHC private data @retval TD structure pointer **/ TD_DESCRIPTOR * OhciCreateTD ( IN USB_OHCI_HC_DEV *Ohc ) { TD_DESCRIPTOR *Td; Td = UsbHcAllocateMem(Ohc->MemPool, sizeof(TD_DESCRIPTOR)); if (Td == NULL) { return NULL; } Td->CurrBufferPointer = NULL; Td->NextTD = NULL; Td->BufferEndPointer = NULL; Td->NextTDPointer = NULL; return Td; }
/** Create a TD @Param Ohc UHC private data @retval TD structure pointer **/ TD_DESCRIPTOR * OhciCreateTD ( IN USB_OHCI_HC_DEV *Ohc ) { TD_DESCRIPTOR *Td; Td = UsbHcAllocateMem(Ohc->MemPool, sizeof(TD_DESCRIPTOR)); if (Td == NULL) { DEBUG ((EFI_D_INFO, "STV allocate TD fail !\r\n")); return NULL; } Td->CurrBufferPointer = 0; Td->NextTD = 0; Td->BufferEndPointer = 0; Td->NextTDPointer = 0; return Td; }
/** Create and intialize a TD. @param Uhc The UHCI device. @return The newly allocated and initialized TD. **/ UHCI_TD_SW * UhciCreateTd ( IN USB_HC_DEV *Uhc ) { UHCI_TD_SW *Td; Td = UsbHcAllocateMem (Uhc->MemPool, sizeof (UHCI_TD_SW)); if (Td == NULL) { return NULL; } Td->TdHw.NextLink = TD_LINK (NULL, FALSE, TRUE); Td->NextTd = NULL; Td->Data = NULL; Td->DataLen = 0; return Td; }
/** Create an initialize a new queue head. @param Uhc The UHCI device. @param Interval The polling interval for the queue. @return The newly created queue header. **/ UHCI_QH_SW * UhciCreateQh ( IN USB_HC_DEV *Uhc, IN UINTN Interval ) { UHCI_QH_SW *Qh; Qh = UsbHcAllocateMem (Uhc->MemPool, sizeof (UHCI_QH_SW)); if (Qh == NULL) { return NULL; } Qh->QhHw.HorizonLink = QH_HLINK (NULL, TRUE); Qh->QhHw.VerticalLink = QH_VLINK (NULL, TRUE); Qh->Interval = UhciConvertPollRate(Interval); Qh->TDs = NULL; Qh->NextQh = NULL; return Qh; }
/** Delete a single asynchronous interrupt transfer for the device and endpoint. @param Ehc The EHCI device. @param Data Current data not associated with a QTD. @param DataLen The length of the data. @param PktId Packet ID to use in the QTD. @param Toggle Data toggle to use in the QTD. @param MaxPacket Maximu packet length of the endpoint. @retval the pointer to the created QTD or NULL if failed to create one. **/ PEI_EHC_QTD * EhcCreateQtd ( IN PEI_USB2_HC_DEV *Ehc, IN UINT8 *Data, IN UINTN DataLen, IN UINT8 PktId, IN UINT8 Toggle, IN UINTN MaxPacket ) { PEI_EHC_QTD *Qtd; QTD_HW *QtdHw; UINTN Index; UINTN Len; UINTN ThisBufLen; ASSERT (Ehc != NULL); Qtd = UsbHcAllocateMem (Ehc, Ehc->MemPool, sizeof (PEI_EHC_QTD)); if (Qtd == NULL) { return NULL; } Qtd->Signature = EHC_QTD_SIG; Qtd->Data = Data; Qtd->DataLen = 0; InitializeListHead (&Qtd->QtdList); QtdHw = &Qtd->QtdHw; QtdHw->NextQtd = QTD_LINK (NULL, TRUE); QtdHw->AltNext = QTD_LINK (NULL, TRUE); QtdHw->Status = QTD_STAT_ACTIVE; QtdHw->Pid = PktId; QtdHw->ErrCnt = QTD_MAX_ERR; QtdHw->Ioc = 0; QtdHw->TotalBytes = 0; QtdHw->DataToggle = Toggle; // // Fill in the buffer points // if (Data != NULL) { Len = 0; for (Index = 0; Index <= QTD_MAX_BUFFER; Index++) { // // Set the buffer point (Check page 41 EHCI Spec 1.0). No need to // compute the offset and clear Reserved fields. This is already // done in the data point. // QtdHw->Page[Index] = EHC_LOW_32BIT (Data); QtdHw->PageHigh[Index] = EHC_HIGH_32BIT (Data); ThisBufLen = QTD_BUF_LEN - (EHC_LOW_32BIT (Data) & QTD_BUF_MASK); if (Len + ThisBufLen >= DataLen) { Len = DataLen; break; } Len += ThisBufLen; Data += ThisBufLen; } // // Need to fix the last pointer if the Qtd can't hold all the // user's data to make sure that the length is in the unit of // max packets. If it can hold all the data, there is no such // need. // if (Len < DataLen) { Len = Len - Len % MaxPacket; } QtdHw->TotalBytes = (UINT32) Len; Qtd->DataLen = Len; } return Qtd; }
/** Allocate and initialize a EHCI queue head. @param Ehci The EHCI device. @param Ep The endpoint to create queue head for. @retval the pointer to the created queue head or NULL if failed to create one. **/ PEI_EHC_QH * EhcCreateQh ( IN PEI_USB2_HC_DEV *Ehci, IN USB_ENDPOINT *Ep ) { PEI_EHC_QH *Qh; QH_HW *QhHw; Qh = UsbHcAllocateMem (Ehci, Ehci->MemPool, sizeof (PEI_EHC_QH)); if (Qh == NULL) { return NULL; } Qh->Signature = EHC_QH_SIG; Qh->NextQh = NULL; Qh->Interval = Ep->PollRate; InitializeListHead (&Qh->Qtds); QhHw = &Qh->QhHw; QhHw->HorizonLink = QH_LINK (NULL, 0, TRUE); QhHw->DeviceAddr = Ep->DevAddr; QhHw->Inactive = 0; QhHw->EpNum = Ep->EpAddr; QhHw->EpSpeed = Ep->DevSpeed; QhHw->DtCtrl = 0; QhHw->ReclaimHead = 0; QhHw->MaxPacketLen = (UINT32) Ep->MaxPacket; QhHw->CtrlEp = 0; QhHw->NakReload = QH_NAK_RELOAD; QhHw->HubAddr = Ep->HubAddr; QhHw->PortNum = Ep->HubPort; QhHw->Multiplier = 1; QhHw->DataToggle = Ep->Toggle; if (Ep->DevSpeed != EFI_USB_SPEED_HIGH) { QhHw->Status |= QTD_STAT_DO_SS; } switch (Ep->Type) { case EHC_CTRL_TRANSFER: // // Special initialization for the control transfer: // 1. Control transfer initialize data toggle from each QTD // 2. Set the Control Endpoint Flag (C) for low/full speed endpoint. // QhHw->DtCtrl = 1; if (Ep->DevSpeed != EFI_USB_SPEED_HIGH) { QhHw->CtrlEp = 1; } break; case EHC_INT_TRANSFER_ASYNC: case EHC_INT_TRANSFER_SYNC: // // Special initialization for the interrupt transfer // to set the S-Mask and C-Mask // QhHw->NakReload = 0; EhcInitIntQh (Ep, QhHw); break; case EHC_BULK_TRANSFER: if ((Ep->DevSpeed == EFI_USB_SPEED_HIGH) && (Ep->Direction == EfiUsbDataOut)) { QhHw->Status |= QTD_STAT_DO_PING; } break; } return Qh; }