usbhcduhcilib.c

来自「cpc-1631的BSP包for VxWorks操作系统」· C语言 代码 · 共 2,337 行 · 第 1/5 页

C
2,337
字号
    UINT16 qhCount;	    /* count of QHs allocated for IRP */
    pQH_WRAPPER pQh;		/* pointer to QH for this transfer */

    UINT16 tdCount;	    /* count of TDs allocated for IRP */
    pTD_WRAPPER pTdPool;	/* pointer to block of TDs allocated */
    pTD_WRAPPER pTdFree;	/* unused TDs */
    pTD_WRAPPER pTdInUse;	/* first TD in use */
    pTD_WRAPPER pLastTdInUse;	    /* pointer to last TD */

    UINT32 nanoseconds; 	/* bus time required for TDs in use */

    UINT16 bfrNo;	    /* highest IRP bfrList[] serviced */
    UINT32 bfrOffset;		/* offset into bfrList[].pBfr */
    BOOL zeroLenMapped; 	/* TRUE when zero len bfrList [] serviced */

    UINT16 interval;		/* how often interrupt xfr scheduled */

    UINT32 isochTdsCreated;	/* count of isoch TDs created, in total */
    UINT32 frameCount;		/* count of frames used for isoch pipe */
    UINT32 bytesSoFar;		/* bytes transferred so far for isoch pipe */

    UINT16 isochNext;		/* next isoch frame number to schedule */
    UINT16 isochCount;		/* count of isoch frames scheduled */
    pTD_WRAPPER pNextIsochTd;	    /* next isoch TD to schedule */

    BOOL irpRunning;		/* TRUE once IRP scheduled onto bus */
    UINT32 startTime;		/* time when IRP was scheduled onto bus */

    } IRP_WORKSPACE, *pIRP_WORKSPACE;


/*
 * 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)}};


/***************************************************************************
*
* uhciByteRead - Read a 8 bit value from the UHCI controller.
*
* RETURNS: A big-endian adjusted UINT8
*/
 
UINT32 uhciByteRead
    (
    UINT32 offset
    )
    {
    CACHE_PIPE_FLUSH ();
 
    return USB_PCI_BYTE_IN (offset);
    }

char uhciread(char offet)
{
sysInByte(0xfe00a000+offet);
}
/*
void usb_set_bit(char p,char val)
{
sysOutWord((0xfe00a000+p),sysInWord(0xfe00a000+p)|val);
}

void usb_clr_bit(char p,char val)
{
sysOutWord((0xfe00a000+p),sysInWord(0xfe00a000+p)&(~val));
}

void usb_set_bit1(char p,char val)
{
UHC_WORD_OUT (p, UHC_WORD_IN (p) | (val));
}*/
/***************************************************************************
*
* uhciWordRead - Read a 16 bit value from the UHCI controller.
*
* RETURNS: A big-endian adjusted UINT16
*/
 
UINT32 uhciWordRead
    (
    UINT32 offset
    )
    {
    CACHE_PIPE_FLUSH ();
 
    return USB_PCI_WORD_IN (offset);
    }

/***************************************************************************
*
* 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;
    }

⌨️ 快捷键说明

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