⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usbhcduhcilib.c

📁 T2.0 USB driver.rar T2.0 USB driver.rar
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * HCD_HOST * * HCD_HOST maintains all information about a connection to a specific * universal host controller (UHC). */typedef struct hcd_host    {    HCD_CLIENT_HANDLE handle;	/* handle associated with host */    BOOL shutdown;	    	/* TRUE during shutdown */    PCI_CFG_HEADER pciCfgHdr;	/* PCI config header for UHC */    UINT16 uhcAttributes;	/* vendor/model specific attributes */    UINT32 ioBase;	    	/* Base I/O address */    USB_HCD_MNGMT_CALLBACK mngmtCallback; /* callback routine for mngmt evt */    pVOID mngmtCallbackParam;	/* caller-defined parameter */    MUTEX_HANDLE hostMutex;	/* guards host structure */    THREAD_HANDLE intThread;	/* Thread used to handle interrupts */    SEM_HANDLE intPending;	/* semaphore indicates int pending */    BOOL intThreadExitRequest;	/* TRUE when intThread should terminate */    SEM_HANDLE intThreadExit;	/* signalled when int thread exits */    UINT32 intCount;		/* number of interrupts processed */    BOOL intInstalled;		/* TRUE when h/w int handler installed */    UINT16 intBits;	    	/* interrupt bits */    UINT16 rootAddress; 	/* current address of root hub */    UINT8 configValue;		/* current configuration value */    BOOL powered [UHCI_PORTS];	/* TRUE if port is powered */    BOOL cSuspend [UHCI_PORTS]; /* TRUE if suspend status change */    BOOL cReset [UHCI_PORTS];	/* TRUE if reset status change */    /* descriptor fields order-dependent */    USB_DEVICE_DESCR devDescr;	    /* standard device descriptor */    USB_CONFIG_DESCR configDescr;   /* standard config descriptor */    USB_INTERFACE_DESCR ifDescr;    /* standard interface descriptor */    USB_ENDPOINT_DESCR endpntDescr; /* standard endpoint descriptor */    USB_HUB_DESCR hubDescr;	/* root hub descriptor */    LIST_HEAD pipes;		/* active pipes */    UINT16 rootIrpCount;	/* count of entries on pRootIrps */    LIST_HEAD rootIrps; 	/* IRPs pending on root hub */    LIST_HEAD busIrps;		/* IRPs pending on devices not */			    	/* including root hub */    char *dmaPool;	    	/* memory alloc'd by cacheDmaMalloc() */    PART_ID memPartId;		/* memory partition ID */    pUHCI_FRAME_LIST pFrameList;    /* UHC frame list */    pQH_WRAPPER pIntAnchorQhs;	    /* UHC QH "anchor" list */    pQH_WRAPPER pCtlAnchorQh;	    /* Anchor for ctl transfer QHs */    pQH_WRAPPER pLastCtlQh;	/* pointer to last ctl QH in use */    pQH_WRAPPER pBulkAnchorQh;	    /* Anchor for bulk transfer QHs */    UINT32 pciPtrToBulkAnchorQh;    /* pre-calculated PCIPTR */    pQH_WRAPPER pLastBulkQh;	    /* pointer to last bulk QH in use */    UINT32 hostErrCount;	/* incremented if host ctlr reports err */    UINT32 nanoseconds; 	/* current worst case of bus time */		    		/* required for scheduled TDs */    UINT16 sofInterval; 	/* current SOF interval */    BOOL suspended;	     	/* TRUE when global suspend is TRUE */    SEM_ID hcSyncSem;           /* syncronization semaphore */    } HCD_HOST, *pHCD_HOST;/* locals *//* UHC vendor/device table. * * The following table defines the features/operating modes we use for * UHCI controllers with which we've tested.   * * Intel PIIX4: Hard system crashes have been observed when enabling * bandwidth reclamation on the PIIX4.	There are unconfirmed reports * that the PIIX3 can consume all available PCI bandwidth when all QHs * on the bandwidth reclamation loop are complete, thus hanging the * system.  We surmise that this may also be the cause of the problems * observed on the PIIX4. * * ViaTech: The ViaTech parts appear to work fine with bandwidth * reclamation enabled. */#define UHC_ATTR_INTEL_PIIX (UHC_ATTR_HC_SYNCH)#define UHC_ATTR_VIATECH    (UHC_ATTR_HC_SYNCH | UHC_ATTR_BW_RECLAMATION)LOCAL UHC_TABLE uhcTable [] = {    {PCI_VID_INTEL, PCI_DID_INTEL_PIIX3,    UHC_ATTR_INTEL_PIIX},    {PCI_VID_INTEL, PCI_DID_INTEL_PIIX4,    UHC_ATTR_INTEL_PIIX},    {PCI_VID_VIATECH,	PCI_DID_VIATECH_82C586, UHC_ATTR_VIATECH},    {0, 	0,	    0}};/* Language descriptor */LOCAL USB_LANGUAGE_DESCR langDescr =    {sizeof (USB_LANGUAGE_DESCR), USB_DESCR_STRING,     {TO_LITTLEW (UNICODE_ENGLISH)}};/***************************************************************************** getUhcAttributes - get attributes based on type of UHCI controller** Based on information in the PCI configuration header passed by the* caller, searches for a matching entry in the uhcTable[].  If one is* found, returns the corresponding attribute value.  If no entry is* found, returns the default value.** RETURNS: UINT16 vector containing UHC attributes*/LOCAL UINT16 getUhcAttributes    (    pPCI_CFG_HEADER pCfgHdr    )    {    pUHC_TABLE pTable;    for (pTable = &uhcTable [0]; pTable->pciVendorId != 0; pTable++)	if (pTable->pciVendorId == pCfgHdr->vendorId &&	    pTable->pciDeviceId == pCfgHdr->deviceId)	    {	    return pTable->uhcAttributes;	    }    return UHC_ATTR_DEFAULT;    }/***************************************************************************** waitOnBits - wait for a word register bit to reach the desired state** RETURNS: TRUE if successful, else FALSE if desired bit state not detected*/LOCAL BOOL waitOnBits    (    pHCD_HOST pHost,    UINT16 p,    UINT16 bitMask,    UINT16 bitState    )    {    UINT32 start = OSS_TIME ();    BOOL desiredState;    while (!(desiredState = ((UHC_WORD_IN (p) & bitMask) == bitState)) && 	OSS_TIME () - start < BIT_TIMEOUT)	;    return desiredState;        }/***************************************************************************** getFrameNo - returns current hardware frame number** RETURNS: value of current frame number*/LOCAL UINT16 getFrameNo    (    pHCD_HOST pHost    )    {    return FINDEX (UHC_WORD_IN (UHCI_FRNUM));    }/***************************************************************************** setIrpResult - sets result in IRP and executes IRP callback** RETURNS: value from Irp result field*/LOCAL int setIrpResult    (    pUSB_IRP pIrp,    int result    )    {    if (result != PENDING)	{	pIrp->result = result;	if (pIrp->usbdCallback != NULL)	    (*pIrp->usbdCallback) (pIrp);	else if (pIrp->userCallback != NULL)	    (*pIrp->userCallback) (pIrp);	}    return result;    }/***************************************************************************** planAheadTime - returns "plan-ahead time"** The "plan ahead interval" is the maximum time that code should "plan* ahead when setting up work for the UHC.  It is expected that interrupt* latency will never exceed one half of this time.** RETURNS: plan ahead time in msec*/LOCAL UINT16 planAheadTime    (    pHCD_HOST pHost    )    {    return PLAN_AHEAD_TIME;    }/***************************************************************************** calcIntInterval - calculates the scheduling interval for interrupt transfer** RETURNS: Actual interval to be used for interrupt transfer*/LOCAL UINT16 calcIntInterval    (    UINT16 interval	/* 1 <= requested interval <= 255 */    )    {    UINT16 i;    /* Select an interval which is the largest power of two less than or     * equal to the requested interval.     */    for (i = 2; i < 256; i <<= 1)	{	if (i > interval)	    break;	}    return i >> 1;    }/***************************************************************************** calcQhTd - calculates number of QHs and TDs to be allocated for IRP** Calculates the number of TDs/QHs which need to be allocated for <pIrp>* in order to complete the IRP or manage it through at least the "plan* ahead interval."  Returns number of TDs in <pTdCount> and QHs in* <pQhCount>.** RETURNS: N/A*/LOCAL VOID calcQhTd    (    pHCD_HOST pHost,    pHCD_PIPE pPipe,    pUSB_IRP pIrp,    pUINT16 pQhCount,    pUINT16 pTdCount    )    {    UINT16 qhCount = 0;    UINT16 tdCount = 0;    UINT16 trialTdCount;    UINT32 bytesPerFrame;    /* The calculation of TDs/QHs varies based on the type of transfer */    switch (pPipe->transferType)    {    case USB_XFRTYPE_ISOCH:	/* IRPs for isochronous transfers have one or more bfrList[]	 * entries which requires a variable number of TDs.  There	 * will be a single TD per frame, and the number of TDs	 * is bounded by the "plan ahead time".	 *	 * NOTE: for isoch transfers, maxPacketSize is the number	 * of bytes to be transmitted each frame.	 */	qhCount = 0;	bytesPerFrame = pPipe->bandwidth / 1000L;	trialTdCount = (pIrp->transferLen + bytesPerFrame - 1) 			/ bytesPerFrame;	tdCount = min (trialTdCount, planAheadTime (pHost));	break;    case USB_XFRTYPE_INTERRUPT:	/* IRPs for interrupt transfers have one or more bfrList[] 	 * entries.  Each IRP requires a single QHs which may be linked	 * into multiple frame lists (to allow it to be scheduled 	 * periodically) plus a variable number of TDs.	 */	qhCount = 1;	trialTdCount = (pIrp->transferLen + pPipe->maxPacketSize - 1)			/ pPipe->maxPacketSize;	tdCount = min (trialTdCount, MAX_IRP_TDS);	break;    case USB_XFRTYPE_CONTROL:	/* IRPs for control transfers have two or more bfrList[]	 * entries.  We need one QH for the transfer plus one TD	 * for the Setup packet (first bfrList[] entry) plus	 * a variable number of TDs for the additional bfr list entries	 * plus a final TD for the status packet.  There is an overriding 	 * limit on the number of TDs per control IRP set at MAX_IRP_TDS.	 * 	 * NOTE: For low-speed control transfers, we impose a limit of	 * one oustanding TD at a time.	 */	qhCount = 1;	if (pPipe->speed == USB_SPEED_LOW)	    {	    tdCount = 1;	    }	else	    {		    tdCount = 2;	/* for Setup and status packets */	    if (pIrp->bfrCount > 1)		{		trialTdCount = (pIrp->transferLen - pIrp->bfrList [0].bfrLen 				+ pPipe->maxPacketSize - 1) 				/ pPipe->maxPacketSize;		tdCount += min (trialTdCount, MAX_IRP_TDS - tdCount);		}	    }	break;    case USB_XFRTYPE_BULK:	/* IRPs for bulk transfers have one or more bfrList[] entries.		 * Each IRP requires a single QH plus a variable number of TDs.	 */	qhCount = 1;	trialTdCount = (pIrp->transferLen + pPipe->maxPacketSize - 1)			/ pPipe->maxPacketSize;	tdCount = min (trialTdCount, MAX_IRP_TDS);	break;    }    /* return results */    if (pQhCount != NULL)	   *pQhCount = qhCount;    if (pTdCount != NULL)	    *pTdCount = tdCount;    }/***************************************************************************** freeIrpWorkspace - releases IRP_WORKSPACE and related QHs and TDs** Releases all QHs and TDs associated with an IRP_WORKSPACE and frees* the IRP_WORKSPACE structure itself.** RETURNS: N/A*/LOCAL VOID freeIrpWorkspace    (    pHCD_HOST pHost,    pUSB_IRP pIrp    )    {    pIRP_WORKSPACE pWork = (pIRP_WORKSPACE) pIrp->hcdPtr;    if (pWork != NULL)	{	if (pWork->pQh != NULL)	    DMA_FREE (pWork->pQh);	if (pWork->pTdPool != NULL)	    DMA_FREE (pWork->pTdPool);	OSS_FREE (pWork);	pIrp->hcdPtr = NULL;	}    }/***************************************************************************** allocIrpWorkspace - allocates QH and TD structures for IRP** Calculates the required number of QH and TD structures for an IRP* and allocates aligned memory.  Also creates an IRP_WORKSPACE structure* to manage the QHs and TDs allocated for the IRP and links it into the* IRP.** RETURNS: TRUE if successful, else FALSE*/LOCAL BOOL allocIrpWorkspace    (    pHCD_HOST pHost,    pHCD_PIPE pPipe,    pUSB_IRP pIrp    )    {    pIRP_WORKSPACE pWork;    UINT16 tdLen;    UINT16 i;    /* Allocate IRP_WORKSPACE */    if ((pWork = OSS_CALLOC (sizeof (*pWork))) == NULL)	return FALSE;    pIrp->hcdPtr = pWork;    pWork->pPipe = pPipe;    pWork->pIrp = pIrp;    /* Calculate number of QHs and TDs */    calcQhTd (pHost, pPipe, pIrp, &pWork->qhCount, &pWork->tdCount);    /* Allocate QHs and TDs */    if (pWork->qhCount > 0)	{	if ((pWork->pQh = DMA_MALLOC (sizeof (QH_WRAPPER), 	    UHCI_QH_ALIGNMENT)) == NULL)	    {	    freeIrpWorkspace (pHost, pIrp);	    return FALSE;	    }	memset (pWork->pQh, 0, sizeof (QH_WRAPPER));	pWork->pQh->sw.pWork = pWork;	pWork->pQh->qh.tdLink = UHC_END_OF_LIST;	}    if (pWork->tdCount > 0)	{	tdLen = pWork->tdCount * sizeof (TD_WRAPPER);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -