📄 usbehcdutil.c
字号:
* and BytesToTransfer is not multiple of maximum packet * size supported by endpoint, then for IN transaction * BytesToTransfer should change to next multiple of * maximum packet size */ if ((uSize > pQTD->uBytesToTransfer) && (pQTD->uBytesToTransfer % uMaxPacketSize)) { pQTD->uBytesToTransfer = pQTD->uBytesToTransfer - (pQTD->uBytesToTransfer % uMaxPacketSize); } USB_EHCD_SET_BITFIELD(index, QTD, pQTD->uTransferInfo, pQTD->uBytesToTransfer, TOKEN_TOTAL_BYTES_TO_TRANSFER); /* Update other buffer pointer fields of the qTD . * Each buffer pointer will be pointing to a different page */ for(uIndex = 1; 5 > uIndex; ++uIndex) { USB_EHCD_SET_BITFIELD(index, QTD, pQTD->uBufferPagePointerList[uIndex], (USB_EHCD_GET_BITFIELD(index, QTD, pQTD->uBufferPagePointerList[0], BUFFER_POINTER) + uIndex), BUFFER_POINTER); } /* Return the number of bytes being transfered by this qTD */ return (pQTD->uBytesToTransfer); } /* End of usbEhcdFillQTDBuffer() */ /***************************************************************************** usbEhcdCreateQTDs - creates TDs and populates them.** This function is used to create TDs for a data transfer and to populate the* fields of the TDs.** <pHCDData> - Pointer to the USB_EHCD_DATA structure* <ppDataHead> - Pointer holding the pointer to the* head of the list of QTDS.* <ppDataTail> - Pointer holding the pointer to the* tail of the list of QTDS.* <pTransferBuffer> - Data buffer* <uTransferLength> - length of the data buffer* <uToggle> - initial toggle value* <uPID> - PID value* RETURNS: Returns TRUE if the QTDs are created successfully.* Returns FALSE if the QTDs are not created successfully.** ERRNO:* None.** \NOMANUAL*/BOOLEAN usbEhcdCreateQTDs ( pUSB_EHCD_DATA pHCDData,/* Pointer to the USB_EHCD_DATA structure */ pUSB_EHCD_QTD *ppDataHead,/* Pointer to the head QTD */ pUSB_EHCD_QTD *ppDataTail,/* Pointer to the tail QTD */ UCHAR * pTransferBuffer,/* Transfer buffer */ UINT32 uTransferLength,/* Transfer length */ UINT32 uMaximumPacketSize, /* Maximum packet size */ UINT8 uToggle, /* Initial toggle value */ UINT8 uPID /* PID value */ ) { /* Pointer to the current qTD */ pUSB_EHCD_QTD pQTD = NULL; /* To hold the temporary pointer to the qTD */ pUSB_EHCD_QTD pTempQTD = NULL; /* To hold the number of bytes transferred */ UINT32 uBytesTransfered = 0; /* To hold the HCD bus index */ UINT32 index = pHCDData->uBusIndex; /* Check the validity of the parameters */ if (NULL == ppDataHead || NULL == ppDataTail || NULL == pTransferBuffer) { OS_LOG_MESSAGE_HIGH(EHCD,"Parameters are not valid\n",0,0,0,0); return FALSE; } /* Create the 1st TD needed for the transfer */ pQTD = *ppDataHead = usbEhcdFormEmptyQTD(pHCDData); /* If unable to create the TD, return FALSE */ if(NULL == pQTD) { return FALSE; } /* This loop gets executed till all the TDs are created */ while (uBytesTransfered < uTransferLength) { /* Populate the TD's buffer pointers */ uBytesTransfered += usbEhcdFillQTDBuffer(index, pQTD, pTransferBuffer + uBytesTransfered, uTransferLength - uBytesTransfered, uMaximumPacketSize); /* Update the data toggle bit */ USB_EHCD_SET_BITFIELD(index, QTD, pQTD->uTransferInfo, uToggle, TOKEN_DT); /* Update PID field of the qTD */ USB_EHCD_SET_BITFIELD(index, QTD, pQTD->uTransferInfo, uPID, TOKEN_PID_CODE); /* Flush the contents of the cache to the RAM */ CACHE_DMA_FLUSH(pQTD, sizeof(USB_EHCD_QTD)); /* Invalidate the cache */ CACHE_DMA_INVALIDATE(pQTD, sizeof(USB_EHCD_QTD)); /* If the bytes transfered is less than the total transfer size */ if(uBytesTransfered < uTransferLength) { /* Temporay pointer to hold the QTD next pointer */ PUCHAR pQTDTemp = NULL; /* Create 1 more qTD */ pQTD->pNext = usbEhcdFormEmptyQTD(pHCDData); /* Check if memory allocation is a failure */ if(NULL == pQTD->pNext) { /* Free up all the TDs created */ for(pQTD = *ppDataHead; NULL != pQTD; pQTD = pQTD->pNext) { pTempQTD = pQTD->pNext; OS_ASSERT(NULL != pQTD->pAllocatedMem); OS_FREE(pQTD->pAllocatedMem); pQTD = pTempQTD; } /* Return FALSE */ return FALSE; }/* End of if() */ /* Fetch the host controller accessible region */ pQTDTemp = (PUCHAR) pQTD->pNext; pQTDTemp += USB_EHCD_QTD_HEADER_SIZE; /* Update the HC's link pointers */ USB_EHCD_SET_BITFIELD(index, QTD, pQTD->uNextQTDPointer, (((unsigned)USB_EHCD_CONVERT_TO_BUS_MEM( index,pQTDTemp)) >> 5), NEXTQTD_POINTER); /* Indicate that this is not the last element in the queue */ USB_EHCD_SET_BITFIELD(index, QTD, pQTD->uNextQTDPointer, 0, NEXTQTD_POINTER_T); /* Flush the contents of the cache to the RAM */ CACHE_DMA_FLUSH(((char*)pQTD+USB_EHCD_QTD_HEADER_SIZE), sizeof(UINT32)); /* Invalidate the cache */ CACHE_DMA_INVALIDATE((char*)pQTD+USB_EHCD_QTD_HEADER_SIZE, sizeof(UINT32)); /* Update the next element as the current qTD element */ pQTD = pQTD->pNext; /* * There are no other elements in the queue * after the newly created element. */ pQTD->pNext = NULL; } /* End of if(uBytesTransfered < uTransferLength) */ } /* End of while (uBytesTransfered < uTransferLength) */ /* Update the tail pointer */ *ppDataTail = pQTD; /* Return TRUE from the function */ return TRUE; } /* End of function usbEhcdCreateQTDs() *//***************************************************************************** usbEhcdUpdateNonIsochStatusAndBytes - updates the status of the* transfer and the number of bytes transferred.** This function is used to update the status of the non-isochronous* transfer and the number of bytes transferred.** <pHead> - Pointer to the head of the list of QTDS.* <pTail> - Pointer to the tail of the list of QTDS.* <pUrb> - Pointer to the URB.** RETURNS: None.** ERRNO:* None.** \NOMANUAL*/VOID usbEhcdUpdateNonIsochStatusAndBytes ( UINT8 index, /* index of the host controller */ pUSB_EHCD_QTD pHead, /* Pointer to the head QTD */ pUSB_EHCD_QTD pTail, /* Pointer to the tail QTD */ pUSBHST_URB pUrb /* Pointer to the URB */ ) { /* To hold the status of the TD */ UINT8 uStatus = 0; /* Flag indicating that it is a control transfer request */ BOOLEAN bIsControl = FALSE; OS_LOG_MESSAGE_LOW(EHCD,"usbEhcdUpdateNonIsochStatusAndBytes - Entry",0,0,0,0); /* WARNING : No parameter validation is done as this function is * used internally by the EHCD * Assumption is that valid parameters are passed by the EHCD. */ /* Extract the status of the qTD */ uStatus = (UINT8)USB_EHCD_GET_BITFIELD(index, QTD, pTail->uTransferInfo, TOKEN_STATUS); /* Update the URB status based on the status parameter */ if (0 == uStatus) { pUrb->nStatus = USBHST_SUCCESS; } /* Data buffer error- can be underrun or overrun. Should be checked */ else if (0 != (uStatus & USB_EHCD_QTD_STATUS_DATA_BUFFER_ERROR)) { pUrb->nStatus = USBHST_BUFFER_UNDERRUN_ERROR; } /* * babble error - this is set along with halt- so this condition * should always fail. Mentioned here for completion */ else if (0 != (uStatus & USB_EHCD_QTD_STATUS_BABBLE_DETECTED)) { pUrb->nStatus = USBHST_STALL_ERROR; } /* * Transaction error. * Can be Timeout, CRC or bad PID */ else if (0 != (uStatus & USB_EHCD_QTD_STATUS_XACTERR)) { pUrb->nStatus = USBHST_TIMEOUT; } /* This is set only for a full/ low speed periodic transfer */ else if (0 != (uStatus & USB_EHCD_QTD_STATUS_MISSED_UFRAME)) { pUrb->nStatus = USBHST_FAILURE; } /* Halted error condition */ else if (0 != (uStatus & USB_EHCD_QTD_STATUS_HALTED)) { pUrb->nStatus = USBHST_STALL_ERROR; } /* Invalidate the cache */ CACHE_DMA_INVALIDATE(pHead, sizeof(USB_EHCD_QTD)); /* If it is a SETUP PID, jump to next TD */ if(USB_EHCD_SETUP_PID == USB_EHCD_GET_BITFIELD(index, QTD, pHead->uTransferInfo, TOKEN_PID_CODE)) { pHead = pHead->pNext; bIsControl = TRUE; } /* Update the number of bytes transferred to be 0 initially */ pUrb->uTransferLength = 0; /* * This loop traverses the queue of requests * and updates the number of bytes transferred */ do { /* Invalidate the cache */ CACHE_DMA_INVALIDATE(pHead, sizeof(USB_EHCD_QTD)); /* Check if the TD has been processed */ if(0 == (USB_EHCD_GET_BITFIELD(index, QTD, pHead->uTransferInfo, TOKEN_STATUS) & USB_EHCD_QTD_STATUS_ACTIVE)) { /* Check if it is a control transfer & we have reached tail */ if((TRUE == bIsControl) && (pHead == pTail)) { break; } /* Update the number of bytes transfered */ pUrb->uTransferLength += (pHead->uBytesToTransfer - USB_EHCD_GET_BITFIELD(index, QTD, pHead->uTransferInfo, TOKEN_TOTAL_BYTES_TO_TRANSFER)); } /* End of if(0 == (pHead->dword2.status & */ else { break; } /* End of else */ /* If all TDs have been processed, break */ if(pHead == pTail) { break; } /* Move on to next TD */ pHead = pHead->pNext; }while(1); return; }/***************************************************************************** usbEhcdUpdateITDData - updates the number of bytes transferred.** This function is used to update the number of bytes* transferred and status in a isochronous transfer.** <index> - index of the host controller* <pHead> - Pointer to the head of the list of ITDS.* <pTail> - Pointer to the tail of the list of ITDS.* <pPacketDes> - Pointer to the Packet descriptor* transferred.* <uMicroFrameMask> -* RETURNS: None.** ERRNO:* None.** \NOMANUAL*/VOID usbEhcdUpdateITDData ( UINT8 index, /* index of the host controller */ pUSB_EHCD_ITD pHead, /* Pointer to the head QTD */ pUSB_EHCD_ITD pTail, /* Pointer to the tail QTD */ pUSBHST_ISO_PACKET_DESC pPacketDes, /* Pointer to the Packet descriptor */ UINT8 uMicroFrameMask ) { UINT32 uCount = 0; UINT8 uStatus; UINT8 uMicroFrameIndex; OS_LOG_MESSAGE_LOW(EHCD,"usbEhcdUpdateITDData - Entry",0,0,0,0); /* Check the validity of the parameters */ if(NULL == pHead || NULL == pTail || NULL == pPacketDes) { OS_LOG_MESSAGE_HIGH(EHCD,"usbEhcdUpdateITDData - parameters \ are not valid\n",0,0,0,0); return; } /* * This loop traverses the queue of requests * and updates the number of bytes transferred and status */ do { /* Invalidate the cache */ CACHE_DMA_INVALIDATE(pHead, sizeof(USB_EHCD_ITD)); for (uMicroFrameIndex=0; USB_EHCD_MAX_MICROFRAME_NUMBER > uMicroFrameIndex; uMicroFrameIndex++) { if((uMicroFrameMask >> uMicroFrameIndex) & 0x01) { /* Update the length of each microframe */ pPacketDes[uCount].uLength = USB_EHCD_GET_BITFIELD(index, ITD, pHead->uTransactionStatusControlList[uMicroFrameIndex], TRANSACTION_LENGTH); /* Update the Status of each microframe */ pPacketDes[uCount].nStatus = USB_EHCD_GET_BITFIELD(index,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -