990 lines
55 KiB
C
990 lines
55 KiB
C
/* usbEhcdUtil.h - Utility Functions for EHCI */
|
|
|
|
/* Copyright 2004-2005 Wind River Systems, Inc.
|
|
|
|
This software includes software licensed to Wind River Systems, Inc.
|
|
by Wipro, Ltd. Wind River licensees may use this software according
|
|
to the terms of their Wind River license agreement(s) applicable to
|
|
this software.
|
|
*/
|
|
|
|
/*
|
|
Modification history
|
|
--------------------
|
|
01h,28mar05,pdg non-PCI changes
|
|
01g,22mar05,mta 64-bit support added (SPR #104950)
|
|
01f,02feb05,pdg Fix for multiple device connection/disconnection
|
|
01e,03aug04,ami Warning Messages Removed
|
|
01d,23Jul03,gpd Incorporated the changes identified during testing on MIPS
|
|
01c,03Jul03,gpd fixed the bug with asynchronous schedule updation.
|
|
Added separate reclamation lists for asynchronous and periodic
|
|
Added reclamation lists for asynch and periodic request
|
|
cancellation.
|
|
01b,26jun03,psp changing the code to WRS standards.
|
|
01a,25apr03,ram written.
|
|
*/
|
|
|
|
/*
|
|
DESCRIPTION
|
|
This contains the prototypes of the utility functions
|
|
which are used by the EHCI Driver.
|
|
*/
|
|
|
|
/*
|
|
INTERNAL
|
|
*******************************************************************************
|
|
* Filename : usbEhcdUtil.h
|
|
*
|
|
* Copyright :
|
|
*
|
|
* THE COPYRIGHT IN THE CONTENTS OF THIS SOFTWARE VEST WITH WIPRO
|
|
* LIMITED A COMPANY INCORPORATED UNDER THE LAWS OF INDIA AND HAVING
|
|
* ITS REGISTERED OFFICE AT DODDAKANNELLI SARJAPUR ROAD BANGALORE
|
|
* 560 035. DISTRIBUTION OR COPYING OF THIS SOFTWARE BY
|
|
* ANY INDIVIDUAL OR ENTITY OTHER THAN THE ADDRESSEE IS STRICTLY
|
|
* PROHIBITED AND MAY INCUR LEGAL LIABILITY. IF YOU ARE NOT THE
|
|
* ADDRESSEE PLEASE NOTIFY US IMMEDIATELY BY PHONE OR BY RETURN EMAIL.
|
|
* THE ADDRESSEE IS ADVISED TO MAINTAIN THE PROPRIETARY INTERESTS OF
|
|
* THIS COPYRIGHT AS PER APPLICABLE LAWS.
|
|
*
|
|
*
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
#ifndef __INCusbEhcdUtilh
|
|
#define __INCusbEhcdUtilh
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
|
|
/* defines */
|
|
|
|
/*Macro to Initialize USB_USB_EHCD_PIPE */
|
|
#define USB_EHCD_PIPE_INITIALIZE(pEHCDPipe) \
|
|
{ \
|
|
OS_MEMSET(pEHCDPipe, 0, sizeof(USB_EHCD_PIPE)); \
|
|
pEHCDPipe->PipeDeletedFlag = FALSE; \
|
|
}
|
|
|
|
/* Macro to Add QH to asynchronousschedule */
|
|
#define USB_EHCD_ADD_TO_HC_ASYNCH_SCHEDULE(pHCDData, \
|
|
pQH) \
|
|
{ \
|
|
/* To hold the field returned by GET_FIELD macro. */ \
|
|
UINT32 getField; \
|
|
/* Temporary pointer to hold the queue head */ \
|
|
PUCHAR pQhPtr = NULL; \
|
|
\
|
|
UINT32 uBusIndex = pHCDData->uBusIndex;/* bus index */ \
|
|
\
|
|
CACHE_DMA_INVALIDATE(pHCDData->pAsynchTailPipe->pQH, sizeof(USB_EHCD_QH)); \
|
|
\
|
|
getField = USB_EHCD_GET_BITFIELD(uBusIndex, \
|
|
QH, \
|
|
pHCDData->pAsynchTailPipe->pQH->uQueueHeadHorizontalLinkPointer,\
|
|
HORIZONTAL_LINK_POINTER ); \
|
|
\
|
|
USB_EHCD_SET_BITFIELD(uBusIndex, \
|
|
QH, pQH->uQueueHeadHorizontalLinkPointer, \
|
|
getField, HORIZONTAL_LINK_POINTER ); \
|
|
\
|
|
\
|
|
/* Disable the asynchronous schedule */ \
|
|
\
|
|
USB_EHCD_CLR_BIT(pHCDData, \
|
|
USBCMD, \
|
|
ASYNCH_SCHEDULE_ENABLE); \
|
|
\
|
|
while ((USB_EHCD_GET_FIELD(pHCDData, \
|
|
USBCMD, \
|
|
ASYNCH_SCHEDULE_ENABLE) != 0) || \
|
|
(USB_EHCD_GET_FIELD(pHCDData, \
|
|
USBSTS, \
|
|
ASYCHRONOUS_SCHEDULE_STATUS) !=0)) \
|
|
OS_DELAY_MS(1); \
|
|
\
|
|
pQhPtr = (PUCHAR) pQH; \
|
|
pQhPtr += USB_EHCD_QH_HEADER_SIZE; \
|
|
/* Update the tail's next pointer */ \
|
|
USB_EHCD_SET_BITFIELD(uBusIndex, \
|
|
QH, \
|
|
pHCDData->pAsynchTailPipe->pQH->uQueueHeadHorizontalLinkPointer,\
|
|
((unsigned)USB_EHCD_CONVERT_TO_BUS_MEM( \
|
|
pHCDData->uBusIndex,pQhPtr) >> 5), \
|
|
HORIZONTAL_LINK_POINTER ); \
|
|
\
|
|
\
|
|
/* This USB_EHCD_PIPE pointer's next element is the tail's next element*/ \
|
|
pQH->pHCDPipe->pNext = pHCDData->pAsynchTailPipe->pNext; \
|
|
\
|
|
CACHE_DMA_FLUSH(pQH, sizeof(USB_EHCD_QH)); \
|
|
\
|
|
CACHE_DMA_FLUSH(pHCDData->pAsynchTailPipe->pQH, sizeof(USB_EHCD_QH)); \
|
|
\
|
|
\
|
|
/* Enable the asynchronous schedule */ \
|
|
\
|
|
USB_EHCD_SET_BIT(pHCDData, \
|
|
USBCMD, \
|
|
ASYNCH_SCHEDULE_ENABLE); \
|
|
\
|
|
while ((USB_EHCD_GET_FIELD(pHCDData, \
|
|
USBCMD, \
|
|
ASYNCH_SCHEDULE_ENABLE) == 0) || \
|
|
(USB_EHCD_GET_FIELD(pHCDData, \
|
|
USBSTS, \
|
|
ASYCHRONOUS_SCHEDULE_STATUS) ==0)) \
|
|
OS_DELAY_MS(1); \
|
|
\
|
|
/* The tail pointer's next points to this QH's USB_EHCD_PIPE pointer */ \
|
|
pHCDData->pAsynchTailPipe->pNext = pQH->pHCDPipe; \
|
|
\
|
|
/* Make this as the tail element */ \
|
|
pHCDData->pAsynchTailPipe = pQH->pHCDPipe; \
|
|
}
|
|
|
|
/* Macro to Add QH to Interrupt Schedule */
|
|
#define USB_EHCD_ADD_TO_HC_INTERRUPT_SCHEDULE(pHCDData, \
|
|
uListIndex, \
|
|
pQH) \
|
|
{ \
|
|
/* To hold the field returned by GET_FIELD macro. */ \
|
|
UINT32 getField; \
|
|
\
|
|
UINT32 uBusIndex = pHCDData->uBusIndex;/* bus index */ \
|
|
\
|
|
/* Pointer to the tail of the list */ \
|
|
pUSB_EHCD_QH pTailQH = NULL; \
|
|
\
|
|
/* temporary pointer to hold the queue head */ \
|
|
PUCHAR pQhPtr = NULL; \
|
|
\
|
|
/* Copy the tail of the list */ \
|
|
pTailQH = (pUSB_EHCD_QH)pHCDData->TreeListData[uListIndex].pTailPointer; \
|
|
\
|
|
/* Retrieve the HCD accessible pointer */ \
|
|
\
|
|
pTailQH =(pUSB_EHCD_QH) ((UINT32)pTailQH -USB_EHCD_QH_HEADER_SIZE); \
|
|
\
|
|
CACHE_DMA_INVALIDATE(pTailQH, sizeof(USB_EHCD_QH)); \
|
|
\
|
|
/* Copy the next data structure type from the tail element */ \
|
|
getField = USB_EHCD_GET_BITFIELD(pHCDData->uBusIndex, \
|
|
QH, \
|
|
pTailQH->uQueueHeadHorizontalLinkPointer, \
|
|
HORIZONTAL_LINK_POINTER_TYPE); \
|
|
\
|
|
USB_EHCD_SET_BITFIELD(pHCDData->uBusIndex, \
|
|
QH,pQH->uQueueHeadHorizontalLinkPointer, \
|
|
getField, HORIZONTAL_LINK_POINTER_TYPE ); \
|
|
\
|
|
/* \
|
|
* Copy tail element's 't' type which indicates whether the next \
|
|
* data structure is a valid data structure \
|
|
*/ \
|
|
/* pQH->dword0.t = pTailQH->dword0.t; */ \
|
|
\
|
|
getField = USB_EHCD_GET_BITFIELD(uBusIndex, \
|
|
QH, \
|
|
pTailQH->uQueueHeadHorizontalLinkPointer, \
|
|
HORIZONTAL_LINK_POINTER_T); \
|
|
\
|
|
USB_EHCD_SET_BITFIELD(uBusIndex, \
|
|
QH,pQH->uQueueHeadHorizontalLinkPointer, \
|
|
getField, \
|
|
HORIZONTAL_LINK_POINTER_T); \
|
|
\
|
|
/* The QH's next pointer should point to the tail's next element */ \
|
|
/* pQH->dword0.queue_head_horizontal_link_pointer = \
|
|
pTailQH->dword0.queue_head_horizontal_link_pointer; */ \
|
|
getField = USB_EHCD_GET_BITFIELD(uBusIndex, \
|
|
QH, \
|
|
pTailQH->uQueueHeadHorizontalLinkPointer, \
|
|
HORIZONTAL_LINK_POINTER); \
|
|
\
|
|
USB_EHCD_SET_BITFIELD(uBusIndex, \
|
|
QH,pQH->uQueueHeadHorizontalLinkPointer, \
|
|
getField, \
|
|
HORIZONTAL_LINK_POINTER); \
|
|
\
|
|
\
|
|
/* Update the next pointer of the QH */ \
|
|
pQH->pNext = pTailQH->pNext; \
|
|
\
|
|
CACHE_DMA_FLUSH(pQH, sizeof(USB_EHCD_QH)); \
|
|
\
|
|
/* Update the tail's next pointer */ \
|
|
pTailQH->pNext = pQH; \
|
|
\
|
|
/* Update the tail pointer */ \
|
|
pHCDData->TreeListData[uListIndex].pTailPointer = (pVOID)((UINT32)pQH + \
|
|
USB_EHCD_QH_HEADER_SIZE); \
|
|
\
|
|
\
|
|
\
|
|
/* Make the Queue Head point to the host controller accessable region \
|
|
* by adding the offest USB_EHCD_QH_HEADER_SIZE to queue head */ \
|
|
\
|
|
pQhPtr = (PUCHAR)pQH; \
|
|
pQhPtr += USB_EHCD_QH_HEADER_SIZE; \
|
|
\
|
|
\
|
|
/* Update the next element of the tail pointer */ \
|
|
/* pTailQH->dword0.queue_head_horizontal_link_pointer = \
|
|
(unsigned) (pQH) >> 5; */ \
|
|
USB_EHCD_SET_BITFIELD(uBusIndex, \
|
|
QH,pTailQH->uQueueHeadHorizontalLinkPointer, \
|
|
(((unsigned)(USB_EHCD_CONVERT_TO_BUS_MEM( \
|
|
pHCDData->uBusIndex,pQhPtr))) >> 5), \
|
|
HORIZONTAL_LINK_POINTER); \
|
|
\
|
|
CACHE_DMA_FLUSH(pTailQH, sizeof(USB_EHCD_QH)); \
|
|
}
|
|
/* Macro to add pointer to USB_EHCD_PIPE in Asynch Reclamation List */
|
|
#define USB_EHCD_ADD_TO_ASYNCH_RECLAMATION_LIST(pHCDData, \
|
|
pHCDPipe) \
|
|
{ \
|
|
/* Exclusively access the list */ \
|
|
OS_WAIT_FOR_EVENT(pHCDData->ReclamationListSynchEventID, OS_WAIT_INFINITE);\
|
|
\
|
|
/* Add to the list */ \
|
|
pHCDPipe->pNext = pHCDData->pAsynchReclamationListHead; \
|
|
\
|
|
/* Update the asynch reclamation list head */ \
|
|
pHCDData->pAsynchReclamationListHead = pHCDPipe; \
|
|
\
|
|
/* Release the exclusive access */ \
|
|
OS_RELEASE_EVENT(pHCDData->ReclamationListSynchEventID); \
|
|
}
|
|
|
|
/* Macro to add pointer to USB_EHCD_PIPE in Periodic Reclamation List */
|
|
#define USB_EHCD_ADD_TO_PERIODIC_RECLAMATION_LIST(pHCDData, \
|
|
pHCDPipe) \
|
|
{ \
|
|
/* Exclusively access the list */ \
|
|
OS_WAIT_FOR_EVENT(pHCDData->ReclamationListSynchEventID, OS_WAIT_INFINITE);\
|
|
\
|
|
/* Add to the list */ \
|
|
pHCDPipe->pNext = pHCDData->pPeriodicReclamationListHead; \
|
|
\
|
|
/* Update the periodic reclamation list head */ \
|
|
pHCDData->pPeriodicReclamationListHead = pHCDPipe; \
|
|
\
|
|
/* Release the exclusive access */ \
|
|
OS_RELEASE_EVENT(pHCDData->ReclamationListSynchEventID); \
|
|
}
|
|
|
|
/* Macro to add pointer to USB_EHCD_PIPE in Isoch pipe List */
|
|
#define USB_EHCD_ADD_TO_ISOCH_PIPE_LIST(pHCDData, \
|
|
pHCDPipe) \
|
|
{ \
|
|
/* Exclusively access the list */ \
|
|
OS_WAIT_FOR_EVENT(pHCDData->ReclamationListSynchEventID, OS_WAIT_INFINITE);\
|
|
\
|
|
/* Add to the list */ \
|
|
pHCDPipe->pNext = pHCDData->pIsochPipeList; \
|
|
\
|
|
/* Update the asynch reclamation list head */ \
|
|
pHCDData->pIsochPipeList = pHCDPipe; \
|
|
\
|
|
/* Release the exclusive access */ \
|
|
OS_RELEASE_EVENT(pHCDData->ReclamationListSynchEventID); \
|
|
}
|
|
|
|
/* Macro to add pointer to USB_EHCD_PIPE in Isoch pipe List */
|
|
#define USB_EHCD_REMOVE_ISOCH_PIPE(pHCDData, \
|
|
pHCDPipe) \
|
|
{ \
|
|
pUSB_EHCD_PIPE pTempPipe; \
|
|
\
|
|
if (pHCDPipe == pHCDData->pIsochPipeList) \
|
|
{ \
|
|
/* If it is the hesd element, \
|
|
* update the head of list to next pointer */ \
|
|
pHCDData->pIsochPipeList = pHCDPipe->pNext; \
|
|
} \
|
|
else \
|
|
{ \
|
|
/* Search for the pipe in the list */ \
|
|
for (pTempPipe = pHCDData->pIsochPipeList; \
|
|
(NULL != pTempPipe) && \
|
|
(pHCDPipe != pTempPipe->pNext); \
|
|
pTempPipe = pTempPipe->pNext); \
|
|
\
|
|
/* If Pipe not found, Assert an error */ \
|
|
OS_ASSERT(NULL != pTempPipe); \
|
|
pTempPipe->pNext = pHCDPipe->pNext; \
|
|
} \
|
|
}
|
|
|
|
|
|
/* Macro to add request to the list of asynchronous requests to be removed */
|
|
#define USB_EHCD_ADD_TO_ASYNCH_REQUEST_REMOVAL_LIST(pHCDData, \
|
|
pRequestInfo) \
|
|
{ \
|
|
/* Exclusively access the list */ \
|
|
OS_WAIT_FOR_EVENT(pHCDData->ReclamationListSynchEventID, OS_WAIT_INFINITE);\
|
|
\
|
|
/* Add to the list */ \
|
|
pRequestInfo->pListRequest = pHCDData->pHeadAsynchCancelList; \
|
|
\
|
|
/* Update the asynch cancel request list */ \
|
|
pHCDData->pHeadAsynchCancelList = pRequestInfo; \
|
|
\
|
|
/* Release the exclusive access */ \
|
|
OS_RELEASE_EVENT(pHCDData->ReclamationListSynchEventID); \
|
|
}
|
|
|
|
/* Macro to add request to the list of periodic requests to be removed */
|
|
#define USB_EHCD_ADD_TO_PERIODIC_REQUEST_REMOVAL_LIST(pHCDData, \
|
|
pRequestInfo) \
|
|
{ \
|
|
/* Exclusively access the list */ \
|
|
OS_WAIT_FOR_EVENT(pHCDData->ReclamationListSynchEventID, OS_WAIT_INFINITE);\
|
|
\
|
|
/* Add to the periodic list */ \
|
|
pRequestInfo->pListRequest = pHCDData->pHeadPeriodicCancelList; \
|
|
\
|
|
/* Update the periodic cancel request list */ \
|
|
pHCDData->pHeadPeriodicCancelList = pRequestInfo; \
|
|
\
|
|
/* Release the exclusive access */ \
|
|
OS_RELEASE_EVENT(pHCDData->ReclamationListSynchEventID); \
|
|
}
|
|
|
|
/*Macro to add the request to Request list maintained Host Controller Driver */
|
|
#define USB_EHCD_ADD_TO_HCD_REQUEST_LIST(pHCDData, \
|
|
pRequest) \
|
|
{ \
|
|
/* \
|
|
* If there is no element in the list, \
|
|
* make the head and tail point to the request \
|
|
*/ \
|
|
if (NULL == pHCDData->pRequestQueueHead) \
|
|
{ \
|
|
pHCDData->pRequestQueueHead = pRequest; \
|
|
pHCDData->pRequestQueueTail = pRequest; \
|
|
} \
|
|
else \
|
|
{ \
|
|
/* Update the next pointer of the tail element */ \
|
|
pHCDData->pRequestQueueTail->pListRequest = pRequest; \
|
|
/* Update the tail element to point to the request */ \
|
|
pHCDData->pRequestQueueTail = pRequest; \
|
|
} \
|
|
\
|
|
}
|
|
|
|
/*Macro to add the request to requests list maintained for the endpoint. */
|
|
#define USB_EHCD_ADD_TO_ENDPOINT_LIST(pHCDData, \
|
|
pRequest) \
|
|
{ \
|
|
\
|
|
/* \
|
|
* If there is no element in the list, \
|
|
* make the head and tail point to the request \
|
|
*/ \
|
|
if (NULL == pRequest->pHCDPipe->pRequestQueueHead) \
|
|
{ \
|
|
pRequest->pHCDPipe->pRequestQueueHead = pRequest; \
|
|
pRequest->pHCDPipe->pRequestQueueTail = pRequest; \
|
|
} \
|
|
else \
|
|
{ \
|
|
/* Update the next pointer of the tail element */ \
|
|
pRequest->pHCDPipe->pRequestQueueTail->pNext = pRequest; \
|
|
/* Update the tail element to point to the request */ \
|
|
pRequest->pHCDPipe->pRequestQueueTail = pRequest; \
|
|
} \
|
|
}
|
|
|
|
/* This macro is used to to delete the request from request list maintained
|
|
* for the endpoint */
|
|
#define USB_EHCD_DELETE_FROM_ENDPOINT_LIST(pRequestInfo) \
|
|
{ \
|
|
\
|
|
/* Remove the request from the Endpoint list - Start */ \
|
|
\
|
|
/* Extract the pipe pointer for the request */ \
|
|
\
|
|
pUSB_EHCD_PIPE pHCDPipe = pRequestInfo->pHCDPipe; \
|
|
\
|
|
/* Check if it is the head element */ \
|
|
\
|
|
if (pRequestInfo == pHCDPipe->pRequestQueueHead) \
|
|
{ \
|
|
/* If it is the only element, \
|
|
* update the head and tail pointers to NULL */ \
|
|
\
|
|
if (pRequestInfo == pHCDPipe->pRequestQueueTail) \
|
|
{ \
|
|
pHCDPipe->pRequestQueueTail = NULL; \
|
|
pHCDPipe->pRequestQueueHead = NULL; \
|
|
\
|
|
} \
|
|
\
|
|
/* Update the head element */ \
|
|
else \
|
|
{ \
|
|
pHCDPipe->pRequestQueueHead = pRequestInfo->pNext; \
|
|
} \
|
|
} \
|
|
\
|
|
/* if it is not head element */ \
|
|
else \
|
|
{ \
|
|
pUSB_EHCD_REQUEST_INFO pTempRequestInfo; \
|
|
\
|
|
/* Search for the request in the list */ \
|
|
\
|
|
for (pTempRequestInfo = pHCDPipe->pRequestQueueHead; \
|
|
(NULL != pTempRequestInfo) && \
|
|
(pTempRequestInfo->pNext != pRequestInfo); \
|
|
pTempRequestInfo = pTempRequestInfo->pNext); \
|
|
\
|
|
if (pTempRequestInfo != NULL) \
|
|
{ \
|
|
/* Update the next pointers */ \
|
|
pTempRequestInfo->pNext = pRequestInfo->pNext; \
|
|
} \
|
|
} \
|
|
/* Remove the request from the Endpoint list - End */ \
|
|
\
|
|
}
|
|
|
|
/* This macro is used to to delete the request from request list maintained
|
|
* for the endpoint */
|
|
#define USB_EHCD_DELETE_FROM_HCD_LIST(pRequestInfo, pEHCDData) \
|
|
{ \
|
|
\
|
|
/* If this is the head element */ \
|
|
\
|
|
if (pRequestInfo == pEHCDData->pRequestQueueHead) \
|
|
{ \
|
|
/* Update the head of the request list */ \
|
|
pEHCDData->pRequestQueueHead = pRequestInfo->pListRequest; \
|
|
\
|
|
/* Update the tail to NULL if the head is NULL */ \
|
|
if (NULL == pEHCDData->pRequestQueueHead) \
|
|
{ \
|
|
pEHCDData->pRequestQueueTail = NULL; \
|
|
} \
|
|
} \
|
|
else \
|
|
{ \
|
|
/* if it is not head element */ \
|
|
pUSB_EHCD_REQUEST_INFO pTempRequestInfo; \
|
|
\
|
|
/* Search for the request in the list */ \
|
|
\
|
|
for (pTempRequestInfo = pEHCDData->pRequestQueueHead; \
|
|
(NULL != pTempRequestInfo) && \
|
|
(pTempRequestInfo->pListRequest != pRequestInfo); \
|
|
pTempRequestInfo = pTempRequestInfo->pListRequest); \
|
|
\
|
|
/* If the temporary request pointer is NULL, \
|
|
* it is an error \
|
|
*/ \
|
|
OS_ASSERT(NULL != pTempRequestInfo); \
|
|
\
|
|
/* Update the next pointers */ \
|
|
pTempRequestInfo->pListRequest = pRequestInfo->pListRequest; \
|
|
\
|
|
/* If List Request for TempRequest is NULL, the update \
|
|
Tail to Temp request */ \
|
|
\
|
|
if (NULL == pTempRequestInfo->pListRequest) \
|
|
{ \
|
|
pEHCDData->pRequestQueueTail = pTempRequestInfo; \
|
|
} \
|
|
} \
|
|
}
|
|
|
|
/* This macro is used to to delete the request from request list maintained
|
|
* for the endpoint */
|
|
#define USB_EHCD_UNLINK_ISOCH_REQ(pEHCDData, pRequestInfo, uSpeed) \
|
|
{ \
|
|
/* If it is a full speed isochronous endpoint, \
|
|
* update the SITD's link pointers */ \
|
|
\
|
|
if (USBHST_FULL_SPEED == uSpeed) \
|
|
{ \
|
|
\
|
|
/* Pointer to the SITD data structure */ \
|
|
\
|
|
pUSB_EHCD_SITD pSITD = NULL; \
|
|
\
|
|
/* Unlinking all SITDs from hardware frame list. */ \
|
|
\
|
|
/* Extract the head of the request */ \
|
|
pSITD = (pUSB_EHCD_SITD)pRequestInfo->pHead; \
|
|
\
|
|
/* Remove all the SITDs from request list. */ \
|
|
while (NULL != pSITD) \
|
|
{ \
|
|
usbEhcdUnLinkSITD(pEHCDData, pSITD); \
|
|
pSITD = pSITD->pVerticalNext; \
|
|
} \
|
|
\
|
|
} /* End of Full speed isochronous endpoint removal handling */\
|
|
\
|
|
/* It is a high speed endpoint, update the ITD's link pointers */ \
|
|
else \
|
|
{ \
|
|
/* Pointer to the ITD data structure */ \
|
|
\
|
|
pUSB_EHCD_ITD pITD = NULL; \
|
|
\
|
|
/* Unlinking all ITDs from hardware frame list. */ \
|
|
\
|
|
/* Extract the head of the request */ \
|
|
pITD = (pUSB_EHCD_ITD)pRequestInfo->pHead; \
|
|
\
|
|
/* Remove all the SITDs from request list. */ \
|
|
while (NULL != pITD) \
|
|
{ \
|
|
usbEhcdUnLinkITD(pEHCDData, pITD); \
|
|
pITD = pITD->pVerticalNext; \
|
|
} \
|
|
\
|
|
}/* End of high speed isochronous endpoint removal handling */ \
|
|
}
|
|
|
|
|
|
/* This macro is used to calculate the bandwidth occupied in the frame */
|
|
#define USB_EHCD_CALCULATE_FRAME_BANDWIDTH(pEHCDData, uFrameIndex, uCalBandwidth) \
|
|
{ \
|
|
/* To hold the index into the microframe array */ \
|
|
UINT32 uMicroFrameCount = 0; \
|
|
\
|
|
/* This loop adds up the bandwidth in every microframe */ \
|
|
for (uMicroFrameCount = 0; \
|
|
uMicroFrameCount < USB_EHCD_MAX_MICROFRAME_NUMBER; \
|
|
uMicroFrameCount++) \
|
|
{ \
|
|
uCalBandwidth += \
|
|
pEHCDData->FrameBandwidth[uFrameIndex][uMicroFrameCount]; \
|
|
} \
|
|
}
|
|
|
|
/*This macro is used to calculate the bandwidth occupied in the microframes
|
|
specified by the mask. */
|
|
#define USB_EHCD_CALCULATE_BW_MICROFRAMES(pHCDData, \
|
|
uFrameMask, \
|
|
uFrameIndex, \
|
|
uCalBandwidth) \
|
|
{ \
|
|
/* To hold the index into the microframes in a frame */ \
|
|
UINT8 uIndex = 0; \
|
|
\
|
|
/* \
|
|
* If this microframe is to be acounted \
|
|
* for bandwidth calculation, calculate \
|
|
*/ \
|
|
for (uIndex = 0; USB_EHCD_MAX_MICROFRAME_NUMBER > uIndex; uIndex++) \
|
|
{ \
|
|
/* Check if this microframe's bandwidth is to be calculated */ \
|
|
if (0 != ((uFrameMask >> uIndex) & 0x01)) \
|
|
{ \
|
|
uCalBandwidth += pHCDData->FrameBandwidth[uFrameIndex][uIndex]; \
|
|
} \
|
|
} \
|
|
}
|
|
/* This macro is used to calculate the traversal count */
|
|
#define USB_EHCD_CALCULATE_TRAVERSAL_COUNT(uPollInterval, uTraversalCount) \
|
|
{ \
|
|
/* \
|
|
* If the pollinterval is between 32(not including 32) and 16 \
|
|
* the list needs to be traversed once \
|
|
*/ \
|
|
if (16 <= uPollInterval) \
|
|
{ \
|
|
uTraversalCount = 1; \
|
|
} \
|
|
/* Pollinterval lies between 8 and 16(excluded) */ \
|
|
else if (8 <= uPollInterval) \
|
|
{ \
|
|
uTraversalCount = 2; \
|
|
} \
|
|
/* Pollinterval lies between 4 and 8(excluded) */ \
|
|
else if (4 <= uPollInterval) \
|
|
{ \
|
|
uTraversalCount = 3; \
|
|
} \
|
|
/* Pollinterval lies between 2 and 4(excluded) */ \
|
|
else if (2 <= uPollInterval) \
|
|
{ \
|
|
uTraversalCount = 4; \
|
|
} \
|
|
/* Polling interval is 1 */ \
|
|
else \
|
|
{ \
|
|
uTraversalCount = 5; \
|
|
} \
|
|
}
|
|
|
|
/* This macro is used to calculate the traversal count */
|
|
#define USB_EHCD_CALCULATE_LEAF_START_INDEX(uPollInterval, uTreeListCount) \
|
|
{ \
|
|
/* \
|
|
* If the pollinterval is between 32(not including 32) and 16 \
|
|
* the list needs to be traversed once \
|
|
*/ \
|
|
if (16 <= uPollInterval) \
|
|
{ \
|
|
uTraversalCount = 1; \
|
|
} \
|
|
/* Pollinterval lies between 8 and 16(excluded) */ \
|
|
else if (8 <= uPollInterval) \
|
|
{ \
|
|
uTraversalCount = 2; \
|
|
} \
|
|
/* Pollinterval lies between 4 and 8(excluded) */ \
|
|
else if (4 <= uPollInterval) \
|
|
{ \
|
|
uTraversalCount = 3; \
|
|
} \
|
|
/* Pollinterval lies between 2 and 4(excluded) */ \
|
|
else if (2 <= uPollInterval) \
|
|
{ \
|
|
uTraversalCount = 4; \
|
|
} \
|
|
/* Polling interval is 1 */ \
|
|
else \
|
|
{ \
|
|
uTraversalCount = 5; \
|
|
} \
|
|
}
|
|
|
|
#define USB_EHCD_GET_POLL_INTERVAL(uPollInterval) \
|
|
{ \
|
|
/* Calculate the polling interval in terms of frames */ \
|
|
\
|
|
if (0 != (uPollInterval % USB_EHCD_MAX_MICROFRAME_NUMBER)) \
|
|
{ \
|
|
uPollInterval = 1; \
|
|
} \
|
|
else \
|
|
{ \
|
|
uPollInterval /= USB_EHCD_MAX_MICROFRAME_NUMBER; \
|
|
} \
|
|
\
|
|
/* If the bandwidth is more than what is supported, \
|
|
* update the polling interval to the supported polling interval \
|
|
*/ \
|
|
\
|
|
if (USB_EHCD_MAX_USB11_INTERRUPT_POLL_INTERVAL < \
|
|
uPollInterval) \
|
|
{ \
|
|
uPollInterval = USB_EHCD_MAX_USB11_INTERRUPT_POLL_INTERVAL; \
|
|
} \
|
|
}
|
|
|
|
#define USB_EHCD_GET_ISOCH_BANDWIDTH(pHCDData, IsochBW) \
|
|
{ \
|
|
UINT32 uFrameIndex, uUFrameIndex; \
|
|
for (uFrameIndex = 0; \
|
|
USB_EHCD_MAX_FRAMELIST_SIZE > uFrameIndex; \
|
|
uFrameIndex++) \
|
|
{ \
|
|
for (uUFrameIndex = 0; \
|
|
USB_EHCD_MAX_MICROFRAME_NUMBER > uUFrameIndex; \
|
|
uUFrameIndex++) \
|
|
{ \
|
|
IsochBW[uFrameIndex][uUFrameIndex] \
|
|
= pHCDData->FrameListData[uFrameIndex]. \
|
|
uBandwidth[uUFrameIndex]; \
|
|
} \
|
|
} \
|
|
}
|
|
|
|
#define USB_EHCD_GET_INTERRUPT_BANDWIDTH(pHCDData, InterruptBW) \
|
|
{ \
|
|
UINT32 uFrameIndex, uUFrameIndex; \
|
|
for (uFrameIndex = 0; \
|
|
USB_EHCD_MAX_TREE_NODES > uFrameIndex; \
|
|
uFrameIndex++) \
|
|
{ \
|
|
for (uUFrameIndex = 0; \
|
|
USB_EHCD_MAX_MICROFRAME_NUMBER > uUFrameIndex; \
|
|
uUFrameIndex++) \
|
|
{ \
|
|
InterruptBW[uFrameIndex][uUFrameIndex] \
|
|
= pHCDData->TreeListData[uFrameIndex]. \
|
|
uBandwidth[uUFrameIndex]; \
|
|
} \
|
|
} \
|
|
}
|
|
|
|
|
|
#define USB_EHCD_GET_FRAME_BANDWIDTH(pHCDData, IsochBW, InterruptBW, pTotalFrameBW) \
|
|
{ \
|
|
UINT32 uFrameIndex, uUFrameIndex, uBandwidth, uTreeListIndex; \
|
|
/* This loop calculates bandwidth for each frame */ \
|
|
\
|
|
for (uFrameIndex =0; \
|
|
USB_EHCD_MAX_FRAMELIST_SIZE > uFrameIndex; \
|
|
uFrameIndex++) \
|
|
{ \
|
|
/* This loop will calculates bandwidth for \
|
|
each microframes in a frame */ \
|
|
\
|
|
for (uUFrameIndex = 0; \
|
|
USB_EHCD_MAX_MICROFRAME_NUMBER > uUFrameIndex; \
|
|
uUFrameIndex++) \
|
|
{ \
|
|
\
|
|
/* Copy the bandwidth occupied \
|
|
* in the frame by isochronous endpoints \
|
|
*/ \
|
|
uBandwidth = IsochBW[uFrameIndex][uUFrameIndex]; \
|
|
\
|
|
/* Hold the index of the list into the periodic tree */ \
|
|
\
|
|
uTreeListIndex \
|
|
= pHCDData->FrameListData[uFrameIndex].uNextListIndex; \
|
|
\
|
|
/* This loop calculates the bandwidth for \
|
|
tree list data in the microframe \
|
|
*/ \
|
|
\
|
|
for (; ((int)uTreeListIndex != USB_EHCD_NO_LIST); \
|
|
uTreeListIndex \
|
|
= pHCDData->TreeListData[uTreeListIndex]. \
|
|
uNextListIndex) \
|
|
\
|
|
{ \
|
|
uBandwidth += \
|
|
InterruptBW[uTreeListIndex][uUFrameIndex]; \
|
|
} \
|
|
\
|
|
pTotalFrameBW[uFrameIndex] += uBandwidth; \
|
|
} /* End of loop for each microframe */ \
|
|
} /* End of loop for each frame */ \
|
|
\
|
|
}
|
|
|
|
|
|
|
|
/* function declarations */
|
|
|
|
extern VOID usbEhcdFreeAllLists(VOID);
|
|
|
|
extern VOID * usbEhcdAlign
|
|
(
|
|
VOID * pMemory,
|
|
UINT32 uAlignment
|
|
);
|
|
|
|
extern pUSB_EHCD_QH usbEhcdFormEmptyQH
|
|
(
|
|
pUSB_EHCD_DATA pHCDData
|
|
);
|
|
|
|
extern INT32 usbEhcdCalculateBusTime
|
|
(
|
|
UINT32 uSpeed,
|
|
UINT32 uDirection,
|
|
UINT32 uPipeType,
|
|
UINT32 uDataByteCount
|
|
);
|
|
|
|
extern BOOLEAN usbEhcdCheckBandwidth
|
|
(
|
|
pUSB_EHCD_DATA pHCDData,
|
|
ULONG uBandwidth,
|
|
UINT32 uSpeed,
|
|
pUSBHST_ENDPOINT_DESCRIPTOR pEndpointDesc,
|
|
UINT32 * puListIndex,
|
|
UINT32 * puMicroFrameMask
|
|
);
|
|
|
|
extern BOOLEAN usbEhcdAddToFreeQHList
|
|
(
|
|
pUSB_EHCD_QH pQH
|
|
);
|
|
|
|
extern BOOLEAN usbEhcdAddToFreeQTDList
|
|
(
|
|
pUSB_EHCD_QTD pQTD
|
|
);
|
|
|
|
extern BOOLEAN usbEhcdAddToFreeITDList
|
|
(
|
|
pUSB_EHCD_ITD pITD
|
|
);
|
|
|
|
extern BOOLEAN usbEhcdAddToFreeSITDList
|
|
(
|
|
pUSB_EHCD_SITD pSITD
|
|
);
|
|
|
|
extern pUSB_EHCD_QTD usbEhcdGetFreeQTD
|
|
(
|
|
UINT32 uSize
|
|
);
|
|
|
|
extern pUSB_EHCD_QH usbEhcdGetFreeQH
|
|
(
|
|
UINT32 uSize
|
|
);
|
|
|
|
extern pUSB_EHCD_ITD usbEhcdGetFreeITD
|
|
(
|
|
UINT32 uSize
|
|
);
|
|
|
|
extern pUSB_EHCD_SITD usbEhcdGetFreeSITD
|
|
(
|
|
UINT32 uSize
|
|
);
|
|
|
|
extern pUSB_EHCD_QTD usbEhcdFormEmptyQTD
|
|
(
|
|
pUSB_EHCD_DATA pHCDData
|
|
);
|
|
|
|
extern VOID usbEhcdUpdateNonIsochStatusAndBytes
|
|
(
|
|
UINT8 index,
|
|
pUSB_EHCD_QTD pHead,
|
|
pUSB_EHCD_QTD pTail,
|
|
pUSBHST_URB pUrb
|
|
);
|
|
|
|
extern VOID usbEhcdUpdateITDData
|
|
(
|
|
UINT8 index,
|
|
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
|
|
);
|
|
|
|
extern VOID usbEhcdUpdateSITDData
|
|
(
|
|
UINT8 index,
|
|
pUSB_EHCD_SITD pHead, /* Pointer to the head QTD */
|
|
pUSB_EHCD_SITD pTail, /* Pointer to the tail QTD */
|
|
pUSBHST_ISO_PACKET_DESC pPacketDes /* Pointer to the Packet descriptor */
|
|
);
|
|
|
|
extern VOID usbEhcdUnLinkSITD
|
|
(
|
|
pUSB_EHCD_DATA pHCDData, /* Pointer to the EHCD_DATA structure */
|
|
pUSB_EHCD_SITD pSITD /* Pointer to the tail SITD */
|
|
);
|
|
|
|
extern VOID usbEhcdUnLinkITD
|
|
(
|
|
pUSB_EHCD_DATA pHCDData, /* Pointer to the EHCD_DATA structure */
|
|
pUSB_EHCD_ITD pITD /* Pointer to the tail SITD */
|
|
);
|
|
|
|
extern BOOLEAN usbEhcdCopyRHInterruptData
|
|
(
|
|
pUSB_EHCD_DATA pHCDData,
|
|
UINT32 uStatusChange
|
|
);
|
|
|
|
extern BOOLEAN usbEhcdUpdateBandwidth
|
|
(
|
|
pUSB_EHCD_DATA pHCDData
|
|
);
|
|
|
|
extern UINT32 usbEhcdFillQTDBuffer
|
|
(
|
|
UINT8 index,
|
|
pUSB_EHCD_QTD pQTD,
|
|
VOID * pBuffer,
|
|
UINT32 uSize,
|
|
UINT32 uMaxPacketSize
|
|
);
|
|
extern BOOLEAN usbEhcdCreateQTDs
|
|
(
|
|
pUSB_EHCD_DATA pHCDData,
|
|
pUSB_EHCD_QTD *ppDataHead,
|
|
pUSB_EHCD_QTD *ppDataTail,
|
|
UCHAR * pTransferBuffer,
|
|
UINT32 uTransferLength,
|
|
UINT32 uMaximumPacketSize,
|
|
UINT8 uToggle,
|
|
UINT8 uPID
|
|
);
|
|
extern VOID usbEhcdLinkITDs
|
|
(
|
|
pUSB_EHCD_PIPE pHCDPipe,
|
|
pUSB_EHCD_DATA pHCDData,
|
|
UINT32 uFrameNumber,
|
|
pUSB_EHCD_ITD pHead,
|
|
pUSB_EHCD_ITD pTail
|
|
);
|
|
|
|
extern VOID usbEhcdLinkSITDs
|
|
(
|
|
pUSB_EHCD_PIPE pHCDPipe,
|
|
pUSB_EHCD_DATA pHCDData,
|
|
UINT32 uFrameNumber,
|
|
pUSB_EHCD_SITD pHead,
|
|
pUSB_EHCD_SITD pTail
|
|
);
|
|
|
|
extern BOOLEAN usbEhcdGenerateITDs
|
|
(
|
|
pUSB_EHCD_DATA pHCDData,
|
|
pUSB_EHCD_PIPE pHCDPipe,
|
|
pUSB_EHCD_ITD *ppHead,
|
|
pUSB_EHCD_ITD *ppTail,
|
|
UCHAR *pBuffer,
|
|
UINT32 uPktCnt,
|
|
pUSBHST_ISO_PACKET_DESC pIsocPktDesc
|
|
);
|
|
|
|
extern BOOLEAN usbEhcdGenerateSITDs
|
|
(
|
|
pUSB_EHCD_DATA pHCDData,
|
|
pUSB_EHCD_PIPE pHCDPipe,
|
|
pUSB_EHCD_SITD *ppDataHead,
|
|
pUSB_EHCD_SITD *ppDataTail,
|
|
UCHAR *pTransferBuffer,
|
|
UINT32 uPktCnt,
|
|
pUSBHST_ISO_PACKET_DESC pIsocPktDesc
|
|
);
|
|
|
|
extern USBHST_STATUS usbEhcdSubBandwidth
|
|
(
|
|
pUSB_EHCD_DATA pHCDData,
|
|
UINT32 uDeviceAddress,
|
|
UINT32 uDeviceSpeed,
|
|
pUSBHST_INTERFACE_DESCRIPTOR pInterfaceDesc,
|
|
UINT32 * pTotalFrameBW
|
|
);
|
|
|
|
extern USBHST_STATUS usbEhcdSubDeviceBandwidth
|
|
(
|
|
pUSB_EHCD_DATA pHCDData,
|
|
UINT32 uDeviceAddress,
|
|
UINT32 * pTotalFrameBW
|
|
);
|
|
|
|
extern BOOLEAN usbEhcdAddBandwidth
|
|
(
|
|
UINT32 uDeviceSpeed,
|
|
pUSBHST_INTERFACE_DESCRIPTOR pInterfaceDesc,
|
|
UINT32 * pTotalFrameBW
|
|
);
|
|
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* End of __INCusbEhcdUtilh */
|
|
/************************* End of file usbEhcdUtil.h***************************/
|
|
|
|
|
|
|