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

📄 usbhcdohcilib.c

📁 基于VXWORK环境的ARM9 S2410的USB驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
/* usbHcdOhciLib.c - Host Controller Driver (HCD) for OHCI *//* Copyright 2000-2002 Wind River Systems, Inc. *//*Modification history--------------------01p,22may02,wef  Fix SPR 73864 - USB crashes when cable is disconnected while 		 iscoh transfer is in progress - valid only on PPC, MIPS and 		 STRONGARM, not X86.010,29apr02,wef  Fix SPR's 71274, 71273 and clean up fncAttach().01p,18mar02,h_k  made buffer swap's in several places - spr # 73896 and 73920.01o,05feb01,wef  explicitly power to ports on initial HC attachment.01k,13dec01,wef  merge from veloce view01j,24jul01,wef  Fixed SPR #6861701i,23jul01,wef  Fixed SPR #68202 and SPR #6820901h,01jan01,wef  Fixed alignment problems w/ code, general clean up01g,12apr00,wef  Fixed uninitialized variable warning: controlin assignTds(),		 fixed a comment that was messing up the man page generation01f,27mar00,rcb  Fix bug in scheduling interrupt EDs which allowed an ED		 to be circularly-linked.01e,20mar00,rcb  Flush all cache buffers during assignTds() to avoid 		 cache-line boundary problems with some CPU architectures		 (e.g., MIPS).01d,17mar00,rcb  Add code to update tdHead in ED structure when removing		 TDs from queue...corrects bug which allowed OHCI ctlr		 to try to process an aborted TD.01c,10mar00,rcb  Fix bug in pipe destroy logic which attempted to free		 non-existent EDs for root hub.		 Add "volatile" declaration in HC_DWORD_IN/OUT().01b,26jan00,rcb  Change references to "bytesPerFrame" to "bandwidth" in		 pipe creation logic.		 Modify isoch. timing to maintain rate as specified by		 pipe bandwidth parameter.		 Fix big vs. little-endian bug in unscheduleControlIrp()		 and unscheduleBulkIrp().01a,05oct99,rcb  First.*//*DESCRIPTIONThis is the HCD (host controller driver) for OHCI.  This file implementslow-level functions required by the client (typically the USBD) to talk tothe underlying USB host controller hardware.  The <param> to the HRB_ATTACH request should be a pointer to a PCI_CFG_HEADER which contains the PCI configuration header for theOpenHCI host controller to be managed.	Each invocation of the HRB_ATTACHfunction will return an HCD_CLIENT_HANDLE for which a single host controllerwill be exposed.NOTE: This HCD implementation assumes that the caller has already initializedthe osServices and handleFuncs libraries by calling ossInitialize() andusbHandleInitialize(), respectively.  The USBD implementation guarantees thatthese libraries have been initialized prior to invoking the HCD.Regarding IRP callbacks...There are two callback function pointers in each IRP, <usbdCallback> and<userCallback>.  By convention, if a non-NULL <usbdCallback> is supplied,then the HCD invokes only the <usbdCallback> upon IRP completion - and it isthe USBD's responsibility to invoke the <userCallback>.  If no <usbdCallback>is provided, then the HCD invokes the <userCallback> directly.	Typically, all IRPs are delivered to the HCD through the USBD and a non-NULL <usbdCallback>will in fact be provided.Regarding OHCI frame lists...We use the OHCI frame list largely as anticipated in the OpenHCI specification.Each of the 32 interrupt list heads points either to an interrupt ED (endpointdescriptor) or to an isochronous ED "anchor" (at which point all 32 lists converge).  When one or more interrupt pipes are created, EDs for these pipes will be inserted in the interrupt list one or more times, corresponding to thedesired interrupt polling interval.  The last interrupt ED in each list points to the common isochronous anchor ED.  While clients can request any interrupt service interval they like, the algorithms here always choose aninterval which is the largest power of 2 less than or equal to the client'sdesired interval.  For example, if a client requests an interval of 20msec, theHCD will select a real interval of 16msec.  In each frame work list, the leastfrequently scheduled EDs appear ahead of more frequently scheduled EDs.  Sinceonly a single ED is actually created for each interrupt transfer, the individualframe lists actually "merge" at each interrupt ED.   The OpenHCI host controller maintains separate lists for control and bulktransfers.  OpenHCI allows for a control/bulk service ratio, so the control listcan be serviced n times for each servicing of the bulk list.  In the presentimplementation, we use a service ratio of 3:1.Regarding bus time calculations...The host controller driver is responsible for ensuring that certain kinds ofscheduled transfers never exceed the time available in a USB frame.  The HCD and the USBD work cooperatively to ensure this.  For its part, the USBD never allows isochronous and interrupt transfers to be scheduled which would exceed 90% of the bus bandwidth.  However, the USBD will freely allow control and bulk pipes to be created, as these types of transfers take whatever bus time is left over after isochronous and interrupt transfers have been schedule - and theHCD gives priority to control transfers.The HCD keeps a running total of the worst case amount of bus time alloted to active isochronous and interrupt transfers.  As for control and bulk transfers,the HC theoretically allows us to schedule as many of them as we desire, and itkeeps track of how much time remains in each frame, executing only as many ofthese transfers as will fit.  However, the HC requires that the driver scheduleonly as many low speed control transfers (as opposed to full speed controltransfers) as can actually fit within the frame.  Therefore, after taking intoaccount the time already allotted to isochronous and interrupt transfers, theHCD only schedules as many low speed control transfers as can fit within thecurrent frame - and full speed control and bulk transfers follow. *//* includes */#include "usb/usbPlatform.h"#include "string.h"#include "memLib.h"	    /* memory sub-allocation functions */#include "cacheLib.h"		/* cache functions */#include "semLib.h"		/* cache functions */#include "usb/ossLib.h"#include "usb/usbHandleLib.h"#include "usb/pciConstants.h"#include "usb/usbPciLib.h"#include "usb/usbLib.h"#include "drv/usb/usbHcd.h"#include "drv/usb/usbOhci.h"#include "drv/usb/usbHcdOhciLib.h"/* defines */#define PENDING 	1#define HCD_HOST_SIG	    ((UINT32) 0x00cd0080)#define HCD_PIPE_SIG	    ((UINT32) 0x00cd0081)#define MAX_INT_DEPTH	    8	    /* max depth of pending interrupts */#define INT_TIMEOUT	5000	/* wait 5 seconds for int routine to exit */#define BIT_TIMEOUT	1000	/* max time to wait for a bit change */#define HC_TIMEOUT_SRVC_INTERVAL    1000    /* milliseconds *//* HC_HOST_DELAY and HC_HUB_LS_SETUP are host-controller specific. * The following values are estimates for the OHCI controller. */#define HC_HOST_DELAY	((UINT32) 500L)     /* 500 ns, est. */#define HC_HUB_LS_SETUP ((UINT32) 500L)     /* 500 ns, est. *//* OHCI constants unique to this driver implementation. */#define REQUIRED_OHCI_LEVEL 0x10    /* OHCI rev 1.0 or higher */#define MAX_FRAME_OVERHEAD  210 /* cf. OHCI spec. sec 5.4 */#define MAX_ROOT_PORTS	    8	/* max root hub ports we support */#define OHCI_HUB_CONTR_CURRENT	0   /* root hub controller current */#define OHCI_HUB_INTERVAL   255 /* root hub polling interval */#define TD_COUNT_GEN	    2	/* count of TDs for generic pipe */#define TD_COUNT_ISO	    16	/* count of TDs for isoch pipe */#ifndef USB_BUFFER_SWAP#define USB_BUFFER_SWAP(pBuf,len)   /* default: don't swap buffers */#endif  /* USB_BUFFER_SWAP */#ifndef SYS_OHCI_RESET#define SYS_OHCI_RESET()	/* default: don't need reset */#endif  /* SYS_OHCI_RESET *//* * MEMORY *  * To improve performance, a single block of (probably) "non-cached" * memory is allocated.  Then, all OHCI control structures are sub-allocated * from this block as needed.  The vxWorks CACHE_DMA_FLUSH/INVALIDATE macros * are used to ensure that this memory is flushed/invalidated at the correct * times (assuming that cacheable-memory *might* be allocated). */#define DMA_MEMORY_SIZE 	0x10000 /* 64k *//*  Ensure that alignment is actually a multiple of the cache line size */#ifdef _CACHE_ALIGN_SIZE#define DMA_MALLOC(bytes, alignment)    \    memPartAlignedAlloc (pHost->memPartId, \			 bytes, \			 max(alignment, _CACHE_ALIGN_SIZE))#else#define DMA_MALLOC(bytes, alignment)    \    memPartAlignedAlloc (pHost->memPartId, bytes, alignment)#endif#define DMA_FREE(pBfr)		memPartFree (pHost->memPartId, (char *) pBfr)#define DMA_FLUSH(pBfr, bytes)	    CACHE_DMA_FLUSH (pBfr, bytes)#define DMA_INVALIDATE(pBfr, bytes) CACHE_DMA_INVALIDATE (pBfr, bytes)#define USER_FLUSH(pBfr, bytes)     CACHE_USER_FLUSH (pBfr, bytes)#define USER_INVALIDATE(pBfr,bytes) CACHE_USER_INVALIDATE (pBfr, bytes)/* HC I/O access macros. * * NOTE: These macros assume that the calling function defines pHost. *  * NOTE: These macros also require that the register offset, p, be evenly * divisible by 4, e.g., UINT32 access only. */#define HC_DWORD_IN(p)     ohciLongRead(pHost, p)#define HC_DWORD_OUT(p,d)   *((volatile UINT32 *) (pHost->memBase \					 + (p) / 4))  = TO_LITTLEL (d)#define HC_SET_BITS(p,bits) HC_DWORD_OUT (p, HC_DWORD_IN (p) | (bits))#define HC_CLR_BITS(p,bits) HC_DWORD_OUT (p, HC_DWORD_IN (p) & ~(bits))/* FINDEX() creates a valid OHCI frame number from the argument. */#define FINDEX(f)   ((f) & (OHCI_FRAME_WINDOW - 1))/* * The HCD adds HC_FRAME_SKIP to the current frame counter to determine * the first available frame for scheduling. This introduces a latency at * the beginning of each IRP, but also helps to ensure that the HC won't * run ahead of the HCD while the HCD is scheduling a transaction. */#define HC_FRAME_SKIP	    2/* defaults for IRPs which don't specify corresponding values */#define DEFAULT_PACKET_SIZE 8	/* max packet size */#define DEFAULT_INTERVAL    32	/* interrupt pipe srvc interval *//* defines for emulated USB descriptors */#define USB_RELEASE	0x0110	/* USB level supported by this code */#define HC_MAX_PACKET_SIZE  8    #define HC_CONFIG_VALUE     1#define HC_STATUS_ENDPOINT_ADRS (1 | USB_ENDPOINT_IN)/* string identifiers */#define UNICODE_ENGLISH     0x409#define HC_STR_MFG	1#define HC_STR_MFG_VAL	    "Wind River Systems"#define HC_STR_PROD	2#define HC_STR_PROD_VAL     "OHCI Root Hub"/* PCI pointer macros */#define TO_PCIPTR(p)	    (((p) == NULL) ? 0 : USB_MEM_TO_PCI (p))#define FROM_PCIPTR(d)	    (((d) == 0) ? 0 : USB_PCI_TO_MEM (d))#define ED_FROM_PCIPTR(d)   ((pED_WRAPPER) (FROM_PCIPTR (FROM_LITTLEL (d))))#define TD_FROM_PCIPTR(d)   ((pTD_WRAPPER) (FROM_PCIPTR (FROM_LITTLEL (d))))/* interrupt definitions */#define INT_ENABLE_MASK \    (OHCI_INT_WDH | OHCI_INT_RD | OHCI_INT_UE | OHCI_INT_RHSC | OHCI_INT_MIE)/* typedefs *//* * ED_WRAPPER * * ED_WRAPPER combines the OHCI_ED with software-specific data. */typedef union ed_wrapper    {    VOLATILE OHCI_ED ed;	/* OHCI ED, 16 bytes */    struct	{	UINT8 resvd [sizeof (OHCI_ED)];	/* space used by OHCI ED */	struct hcd_pipe *pPipe;		/* pointer to owning pipe */	} sw;    } ED_WRAPPER, *pED_WRAPPER;/* * TD_WRAPPER * * OHCI defines two TD formats: "general" for ctl/bulk/int and "isochronous". * The TD_WRAPPER combines these structures with software-specific data. */typedef union td_wrapper    {    VOLATILE OHCI_TD_GEN tdg;		/* ctl/bulk/int OHCI TD, 16 bytes */    VOLATILE OHCI_TD_ISO tdi;		/* isochronous OHCI TD, 32 bytes */    struct	{	UINT8 resvd [sizeof (OHCI_TD_ISO)]; /* space used by OHCI TD */	struct irp_workspace *pWork;	/* pointer to IRP workspace */	UINT32 nanoseconds; 		/* exec time for this TD */	UINT32 curBfrPtr;		/* original cbp for this TD */	union td_wrapper *doneLink;     /* used when handling done queue */	UINT32 inUse;			/* non-zero if TD in use */	UINT32 pad [3];			/* pad to an even 64 bytes */	} sw;    } TD_WRAPPER, *pTD_WRAPPER;#define TD_WRAPPER_LEN	    64			/* expected TD_WRAPPER length */#define TD_WRAPPER_ACTLEN   sizeof (TD_WRAPPER)	/* actual *//* * HCD_PIPE * * HCD_PIPE maintains all information about an active pipe. */typedef struct hcd_pipe    {    HCD_PIPE_HANDLE pipeHandle;	/* handle assigned to pipe */    LINK link;			/* linked list of pipes */    UINT16 busAddress;		/* bus address of USB device */    UINT16 endpoint;		/* device endpoint */    UINT16 transferType;	/* transfer type */    UINT16 direction;		/* transfer/pipe direction */    UINT16 speed;		/* transfer speed */    UINT16 maxPacketSize;	/* packet size */    UINT32 bandwidth;		/* bandwidth required by pipe */    UINT16 interval;		/* service interval */    UINT16 actInterval; 	/* service interval we really use */    UINT32 time;		/* bandwidth (time) allocated to pipe */    pED_WRAPPER pEd;		/* ED allocated for this pipe */    UINT16 tdCount;		/* number of TDs allocated for pipe */    UINT16 freeTdCount; 	/* count of TDs currently available */    UINT16 freeTdIndex; 	/* first available TD */    pTD_WRAPPER pTds;		/* pointer to TD(s) */    } HCD_PIPE, *pHCD_PIPE;/* * IRP_WORKSPACE * * Associates EDs and TDs with the IRPs they are currently servicing. */typedef struct irp_workspace    {    pHCD_PIPE pPipe;		/* pointer to pipe for this IRP */    pUSB_IRP pIrp;		    /* pointer to parent IRP */    UINT16 bfrNo;		/* highest IRP bfrList[] serviced */    UINT32 bfrOffset;		/* offset into bfrList[].pBfr */    BOOL zeroLenMapped; 	/* TRUE when zero len bfrList [] serviced */    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 */    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 * host controller (HC). */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 HC */    VOLATILE UINT32 * memBase;	    /* Base 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 rootAddress; 	/* current address of root hub */    UINT8 configValue;		/* current configuration value */    UINT16 numPorts;		/* number of root ports */    UINT16 pwrOn2PwrGood;	/* Power ON to power good time. */    pUINT32 pRhPortChange;	/* port change status */    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 */    pOHCI_HCCA pHcca;		/* OHCI HCCA */    pED_WRAPPER pIsochAnchorEd;	/* Anchor for isochronous transfers */    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 */    UINT32 errScheduleOverrun;	/* count of schedule overrun errors */    UINT32 errUnrecoverable;	/* count of unrecoverabl HC errors */    UINT32 pHcControlReg;	/* Control Register Copy */    SEM_ID hcSyncSem;		/* syncronization semaphore */    } HCD_HOST, *pHCD_HOST;/* locals *//* Language descriptor */LOCAL USB_LANGUAGE_DESCR langDescr =    {sizeof (USB_LANGUAGE_DESCR), USB_DESCR_STRING,     {TO_LITTLEW (UNICODE_ENGLISH)}};/***************************************************************************** ohciLongRead - Read a 32 bit value from the OHCI controller.** RETURNS: A big-endian adjusted UINT32 */LOCAL UINT32 ohciLongRead    (    pHCD_HOST pHost,    UINT32 offset    )    {    CACHE_PIPE_FLUSH ();    return FROM_LITTLEL (*((volatile UINT32 *) (pHost->memBase + \					(offset) / 4)));    }/***************************************************************************** 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,    UINT32 p,    UINT32 bitMask,    UINT32 bitState    )    {    UINT32 start = OSS_TIME ();    BOOL desiredState;    while (!(desiredState = ((HC_DWORD_IN (p) & bitMask) == bitState)) && \	    OSS_TIME () - start < BIT_TIMEOUT)	;    return desiredState;        }/***************************************************************************** getFrameNo - returns current hardware frame number** RETURNS: value of current frame number*/

⌨️ 快捷键说明

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