?? usbehcdutil.c
字號:
/* Free the siTD data structure */ memPartFree(ehcdmemPartID, pHeadFreeSITD->pAllocatedMem); } /* Update the head and tail pointers to NULL */ pHeadFreeSITD = NULL; pTailFreeSITD = NULL; /* Release the event */ OS_RELEASE_EVENT(g_ListAccessEvent); OS_LOG_MESSAGE_LOW(EHCD,"usbEhcdFreeAllLists - Exit\n",0,0,0,0); return; } /* End of function usbEhcdFreeAllLists() */ /***************************************************************************** usbEhcdFormEmptyQH - forms an empty QH and populates it.** This function is checks if a QH can be retrieved from the free list. If a* QH cannot be retrieved, creates an empty QH. After retrieving a valid QH,* populates the fields of the QH.** RETURNS: Pointer to the USB_EHCD_QH data structure.** ERRNO:* None.** \NOMANUAL*/pUSB_EHCD_QH usbEhcdFormEmptyQH(VOID) { /* To hold the pointer to the Queue Head */ pUSB_EHCD_QH pQH = NULL; /* To hold the pointer to the allocated memory */ VOID * pAllocatedMem = NULL; OS_LOG_MESSAGE_LOW(EHCD,"usbEhcdFormEmptyQH - Entry\n",0,0,0,0); /* Get a free QH from the free list */ pQH = usbEhcdGetFreeQH(); /* If the free list is empty, allocate memory and align it */ if (NULL == pQH) { /* Allocate memory considering that the QH is aligned to 32 bytes */ pAllocatedMem = memPartAlignedAlloc (ehcdmemPartID, sizeof(USB_EHCD_QH), USB_EHCD_HC_DATA_STRUCTURE_ALIGNMENT); /* Check if memory allocation is successful */ if (NULL == pAllocatedMem) { OS_LOG_MESSAGE_HIGH(EHCD,"usbEhcdFormEmptyQH - memory not allocated for \ QH\n",0,0,0,0); return NULL; } /* Align the memory */ pQH = usbEhcdAlign(pAllocatedMem, USB_EHCD_HC_DATA_STRUCTURE_ALIGNMENT); /* Initialize all the elements of the Queue Head */ OS_MEMSET(pQH, 0, sizeof(USB_EHCD_QH)); /* Store the allocated memory in aligned QH */ pQH->pAllocatedMem = pAllocatedMem; } /* Populate the fields of the QH - Start */ /* * This field indicates to the hardware that * the item referenced by the link pointer is a QH */ USB_EHCD_SET_BITFIELD(QH, pQH->uQueueHeadHorizontalLinkPointer, USB_EHCD_TYPE_QH, HORIZONTAL_LINK_POINTER_TYPE); /* * Indicate that there are no valid TDs * in this queue as the QH is newly created */ USB_EHCD_SET_BITFIELD(QH, pQH->uNextQtdPointer, USB_EHCD_INVALID_LINK, NEXTQTD_POINTER_T); USB_EHCD_SET_BITFIELD(QH, pQH->uAlternateNextQtdPointer, USB_EHCD_INVALID_LINK, ALTERNATE_NEXTQTDPOINTER_T); /* Populate the fields of the QH - End */ OS_LOG_MESSAGE_LOW(EHCD,"usbEhcdFormEmptyQH - Exit\n",0,0,0,0); return pQH; } /* End of function usbEhcdFormEmptyQH() *//***************************************************************************** usbEhcdFormEmptyQTD - forms an empty QTD and populates it.** This function is checks if a QTD can be retrieved from the free list. If a* QTD cannot be retrieved, creates an empty QTD. After retrieving a valid QTD,* populates the fields of the QTD.** RETURNS: Pointer to the USB_EHCD_QTD data structure.** ERRNO:* None.** \NOMANUAL*/pUSB_EHCD_QTD usbEhcdFormEmptyQTD(VOID) { /* To hold the pointer to the QTD */ pUSB_EHCD_QTD pQTD = NULL; /* To hold the pointer to the allocated memory */ VOID * pAllocatedMem = NULL; /* Get a free QTD from the free list */ pQTD = usbEhcdGetFreeQTD(); /* If the free list is empty, allocate memory and align it */ if (NULL == pQTD) { /* Allocate memory considering that the QH is aligned to 32 bytes */ pAllocatedMem = memPartAlignedAlloc (ehcdmemPartID, sizeof(USB_EHCD_QTD), USB_EHCD_HC_DATA_STRUCTURE_ALIGNMENT); /* Check if memory allocation is successful */ if (NULL == pAllocatedMem) { OS_LOG_MESSAGE_HIGH(EHCD,"usbEhcdFormEmptyQTD - memory not allocated for \ QTD\n",0,0,0,0); return NULL; } /* Align the memory */ pQTD = usbEhcdAlign(pAllocatedMem, USB_EHCD_HC_DATA_STRUCTURE_ALIGNMENT); /* Initialize all the elements of the Queue Head */ OS_MEMSET(pQTD, 0, sizeof(USB_EHCD_QTD)); /* Store the allocated memory in aligned QTD */ pQTD->pAllocatedMem = pAllocatedMem; } /* Populate the fields of the QTD - Start */ /* Invalidate Link pointer */ USB_EHCD_SET_BITFIELD(QTD, pQTD->uNextQTDPointer, USB_EHCD_INVALID_LINK, NEXTQTD_POINTER_T ); USB_EHCD_SET_BITFIELD(QTD, pQTD->uAlternateNextQTDPointer, USB_EHCD_INVALID_LINK, ALTERNATE_NEXTQTDPOINTER_T ); /* Indicate that a maximum of 2 errors is acceptable during a transfer */ USB_EHCD_SET_BITFIELD(QTD, pQTD->uTransferInfo, USB_EHCD_MAX_ERRORS, TOKEN_CERR ); /* Enable the HC to start executing the Transaction */ USB_EHCD_SET_BITFIELD(QTD, pQTD->uTransferInfo, USB_EHCD_QTD_STATUS_ACTIVE, TOKEN_STATUS); /* Populate the fields of the QTD - End */ return pQTD; } /* End of usbEhcdFormEmptyQTD() *//***************************************************************************** usbEhcdFillQTDBuffer - populates the buffer pointers of the QTD.** This function is used to populate the buffer pointer fields of the QTD.** <pQTD> - Pointer to the QTD.* <pBuffer> - Pointer to the start of the buffer* <uSize> - Size of the data to be filled.* RETURNS: Returns the number of bytes which were filled in qTD.** ERRNO:* None.** \NOMANUAL*/UINT32 usbEhcdFillQTDBuffer ( pUSB_EHCD_QTD pQTD, /* Pointer to the QTD */ VOID * pBuffer, /* Pointer to the start of the buffer */ UINT32 uSize, /* Size of the buffer to be filled */ UINT32 uMaxPacketSize /* Maximum packet size */ ) { /* To hold the index into the buffer pointers of the qTD */ UINT32 uIndex; UINT32 actualSize; /* Check the validity of the parameters */ if(NULL == pQTD || NULL == pBuffer || 0 == uSize) { return 0; } /* Fill qTD's buffer pointer */ USB_EHCD_SET_BITFIELD(QTD, pQTD->uBufferPagePointerList[0], (((unsigned)USB_EHCD_CONVERT_TO_PCI(pBuffer)) >> 12), BUFFER_POINTER); /* Fill qTD's current offset into the buffer pointer */ USB_EHCD_SET_BITFIELD(QTD, pQTD->uBufferPagePointerList[0], ((unsigned)USB_EHCD_CONVERT_TO_PCI(pBuffer) & 0xFFF), BUFFERPOINTER_CURRENT_OFFSET); /* Fill the number of bytes to transfer - * Totally 5 * 4K bytes can be * transferred using 1 qTD. */ actualSize = (uSize <= (USB_EHCD_QTD_MAX_TRANSFER_SIZE - USB_EHCD_GET_BITFIELD(QTD, pQTD->uBufferPagePointerList[0], BUFFERPOINTER_CURRENT_OFFSET))) ? uSize:(USB_EHCD_QTD_MAX_TRANSFER_SIZE - USB_EHCD_GET_BITFIELD(QTD, pQTD->uBufferPagePointerList[0], BUFFERPOINTER_CURRENT_OFFSET)); pQTD->uBytesToTransfer = actualSize; /* If uSize is more than BytesToTransfer for this QTD * 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(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( QTD, pQTD->uBufferPagePointerList[uIndex], (USB_EHCD_GET_BITFIELD(QTD, pQTD->uBufferPagePointerList[0], BUFFER_POINTER) + uIndex), BUFFER_POINTER); } /* Return the number of bytes being transfered by this qTD */ return (USB_EHCD_GET_BITFIELD(QTD, pQTD->uTransferInfo, TOKEN_TOTAL_BYTES_TO_TRANSFER)); } /* 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.** <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_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; /* 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(); /* 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(pQTD, pTransferBuffer + uBytesTransfered, uTransferLength - uBytesTransfered, uMaximumPacketSize); /* Update the data toggle bit */ USB_EHCD_SET_BITFIELD(QTD, pQTD->uTransferInfo, uToggle, TOKEN_DT); /* Update PID field of the qTD */ USB_EHCD_SET_BITFIELD(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) { /* Create 1 more qTD */ pQTD->pNext = usbEhcdFormEmptyQTD(); /* 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() */ /* Flush the contents of the cache to the RAM */ CACHE_DMA_FLUSH((char*)pQTD+pUSB_EHCD_QTD_pNext_OFFSET, sizeof(UINT32)); /* Invalidate the cache */ CACHE_DMA_INVALIDATE((char*)pQTD+pUSB_EHCD_QTD_pNext_OFFSET, sizeof(UINT32)); /* Update the HC's link pointers */ USB_EHCD_SET_BITFIELD(QTD, pQTD->uNextQTDPointer, (((unsigned)USB_EHCD_CONVERT_TO_PCI(pQTD->pNext)) >> 5), NEXTQTD_POINTER); /* Indicate that this is not the last element in the queue */ USB_EHCD_SET_BITFIELD(QTD, pQTD->uNextQTDPointer, 0, NEXTQTD_POINTER_T); /* Flush the contents of the cache to the RAM */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -