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

📄 usbhcdsl811hslib.c

📁 有关vxworks 的host 的源程序
💻 C
📖 第 1 页 / 共 5 页
字号:
 * Each UHCI_QH must be aligned to a 16 byte boundary.
 */

typedef union qh_wrapper
    {
    VOLATILE UHCI_QH qh;	/* standard UHCI QH, 8 bytes */
        struct
        {
        VOLATILE UINT32 reserved [2]; /* 2 DWORDs used by QH */
        UINT32 reserved1;	    /* 1 DWORD pad */
        struct irp_workspace *pWork;/* workspace which owns QH */
        } sw;
    } QH_WRAPPER, *pQH_WRAPPER;

#define QH_WRAPPER_LEN	    16
#define QH_WRAPPER_ACTLEN   sizeof (QH_WRAPPER)

#define INT_ANCHOR_LIST_SIZE	(QH_WRAPPER_ACTLEN * UHCI_FRAME_LIST_ENTRIES)


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

    UINT32 time;	    /* bandwidth (time) allocated to pipe */

    } HCD_PIPE, *pHCD_PIPE;


/*
 * IRP_WORKSPACE
 *
 * Associates QHs and TDs with the IRPs they are currently servicing.
 *
 * Note: The pTdInUse and pTdFree lists use the TD_WRAPPER.sw.pNext field to 
 * maintain lists of TDs.  When TDs are scheduled, their UHCI_TD.linkPtr
 * fields are also used to link the TDs in the correct order.  The reader
 * must be aware that the UHCI_TD.linkPtr fields are formatted for direct
 * access by the UHCI PCI controller, and may not be dereferenced directly
 * by software.  Instead, the TD_FROM_PCIPTR() macro may be used to 
 * dereference the UHCI_TD.linkPtr field if necessary.	There is no such
 * restriction for the TD_WRAPPER.sw.pNext field.
 *
 * Note also that the linkPtr field uses the UHC convention that the end 
 * of a TD list is marked by a pointer with only the UHC_LINK_TERMINATE bit 
 * set (unlike the more conventional use of NULL to mark end of list).
 */

typedef struct irp_workspace
    {
    pHCD_PIPE pPipe;		/* pointer to pipe for this IRP */
    pUSB_IRP pIrp;	    /* pointer to parent IRP */

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

    SL811_IO_CFG sl811CfgHdr;	/* SL811 IO config */
    UINT16 uhcAttributes;	/* vendor/model specific attributes */
    UINT32 ioBase;	    	/* Base I/O address */
    UINT32 ioBaseData;	    	/* Base I/O data address */

    USB_HCD_MNGMT_CALLBACK mngmtCallback; /* callback routine for mngmt evt */
    pVOID mngmtCallbackParam;	/* caller-defined parameter */

    MUTEX_HANDLE hostMutex;	/* guards host structure */

    int 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 */
    UINT8 intBits;	    	/* interrupt bits */
    int  xmitPending;
    BOOL sofPending;

    UINT16 rootAddress; 	/* current address of root hub */
    UINT8 configValue;		/* current configuration value */
    BOOL powered [SL811_PORTS];	/* TRUE if port is powered */
    BOOL cSuspend [SL811_PORTS]; /* TRUE if suspend status change */
    BOOL cReset [SL811_PORTS];	/* TRUE if reset status change */

    /* added DGJ */
    BOOL connected[SL811_PORTS];/* TRUE if port is connected to device*/
    BOOL suspended[SL811_PORTS];/* TRUE if port is suspended */
    BOOL enabled[SL811_PORTS];  /* TRUE if port is enabled */
    BOOL lowSpeed[SL811_PORTS]; /* TRUE if port is lowSpeed */
    BOOL cConnect[SL811_PORTS]; /* TRUE if connection status change */
    BOOL cEnable[SL811_PORTS];  /* TRUE if enabled 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 */
    /* added DGJ */  
    VOLATILE UHCI_QH *pCurrentQH;   /* current QH in progress */
    VOLATILE UHCI_TD *pCurrentTD;   /* current TD in progress */
    char eof;


    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 gSuspended;	     	/* TRUE when global suspend is TRUE */

    SEM_ID hcSyncSem;           /* syncronization semaphore */

    UINT16 frameNo;             /* frame number. */
    void *nextTDQH;             /* next TD or QH to send */

    } 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)

/* Language descriptor */

LOCAL USB_LANGUAGE_DESCR langDescr =
    {sizeof (USB_LANGUAGE_DESCR), USB_DESCR_STRING, 
    {TO_LITTLEW (UNICODE_ENGLISH)}};

static  pHCD_HOST pDbgHost=NULL;

/***************************************************************************
*
* sl811Reset - reset the SL811HS controller chip and attached USB devices
*
*
* RETURNS: N/A
*/
void sl811Reset(pHCD_HOST pHost)
{
  UINT8 status;

  DBG_PRINTF(("R"));
  DBG_LOG("Reset\n",1,2,3,4,5,6);

  /* disable all interrupts  */
  SL811_REG_WRITE(SL811HS_IER, 0);

  SL811_REG_WRITE(SL811HS_CTRL_REG_1, 0);

  OSS_THREAD_SLEEP(500);

  /* clear interrupt status reg */
  SL811_REG_WRITE(SL811HS_INT_STAT_REG, 0xFF);

  /* check connection status */
  status = SL811_REG_READ(SL811HS_INT_STAT_REG);

  /* Check if device is removed */
  if (status & 0x40) 
    {
      pHost->connected[0] = FALSE;
      DBG_LOG("sl881Reset : No device or no power\n",1,2,3,4,5,6);
    }
  else 
    {
      pHost->connected[0] = TRUE;

      if (!(status & 0x80 ))
	{	
	  /* slow speed device connected directly to root-hub */
	  SL811_REG_WRITE(SL811HS_SOFCNTH_CTRL_2, 0xEE);
	  SL811_REG_WRITE(SL811HS_SOFCNTL_REV, 0xE0);
	  SL811_REG_WRITE(SL811HS_CTRL_REG_1, 0x29);
	  OSS_THREAD_SLEEP(10);
	  SL811_REG_WRITE(SL811HS_CTRL_REG_1, 0x21);
	  pHost->lowSpeed[0] = TRUE;
	  DBG_LOG("sl881Reset : Low speed device connected\n",1,2,3,4,5,6);
	}
      else
	{
	  /* full speed device connect directly to root hub */
	  SL811_REG_WRITE(SL811HS_SOFCNTH_CTRL_2, 0xAE);
	  SL811_REG_WRITE(SL811HS_SOFCNTL_REV, 0xE0);
	  SL811_REG_WRITE(SL811HS_CTRL_REG_1, 0xd);
	  OSS_THREAD_SLEEP(10);
	  SL811_REG_WRITE(SL811HS_CTRL_REG_1, 0x5);
	  pHost->lowSpeed[0] = FALSE;
	  DBG_LOG("sl881Reset : Full speed device connected\n",1,2,3,4,5,6);
	}

      /* start the SOF or EOP */
      SL811_REG_WRITE(SL811HS_PID_DEVEND_A, 0x50) ;  
      SL811_REG_WRITE(SL811HS_DEVADDR_TCNT_A, 0) ;
      SL811_REG_WRITE(SL811HS_CTRL_REG_A, 1) ;
    }

  pHost->frameNo = 0;

  OSS_THREAD_SLEEP(25);

  /* clear interrupt status reg */
  SL811_REG_WRITE(SL811HS_INT_STAT_REG, 0xFF);

  /* Enable interrupts */
  SL811_REG_WRITE(SL811HS_IER, pHost->intBits);

  pHost->xmitPending = 0;
  pHost->sofPending = FALSE;
}

#ifndef INCLUDE_USB_PCI
/***************************************************************************
*
* sl811DcrInit -
*
* RETURNS: N/A
*/
LOCAL void sl811DcrInit()
{
  int regValue = 0;
  printf ("Enter sl811DcrInit\n");
  
   /* IRQ0 from SL811HS daugther card is edge sensitive */
   regValue = sysDcrUictrGet() | 0x00000040; 
   sysDcrUictrSet(regValue); /* set int trigger levels */

  /* Configure the DCR CR0 register */   
  /* Disable GPIO 17 to enable IRQ0 as an interrupt */   
  regValue = sysDcrCr0Get() & ~CR0_GPIO_17_EN;
  sysDcrCr0Set(regValue);
  /* printf ("dcrInit: DCR CR0 reg value = 0x%x\n", sysDcrCr0Get()); */

  /* Configure the DCR CR1 register to set the enable pin */   
  regValue = sysDcrCr1Get() | CR1_PCI_PW_EN;
  sysDcrCr1Set(regValue);
  /* printf ("dcrInit: DCR CR1 reg value = 0x%x\n", sysDcrCr1Get()); */
  
  /* Configure the EBC Configuration Register EBC0_CFG */
  sysDcrEbcSet (EBC_CFG, 0xb84c0000);
  
  /* Configure the Peripheral Bank 2 Configuration Reg	*/
  sysDcrEbcSet (EBC_B2CR, 0x700f8000);
  
  /* Configure the Peripheral Bank 2 Access Reg */
  sysDcrEbcSet (EBC_B2AP, 0x090ffe00);
}
#endif


/***************************************************************************
*
* sl811Init - initialize the SL811HS controller chip
*
*
* Adapted from SL811HS Application Notes, page 12
*
* RETURNS: N/A
*/
LOCAL void sl811Init(pHCD_HOST pHost)
{
  UINT8 status;

  /* disable all interrupts  */
  SL811_REG_WRITE(SL811HS_IER, 0);

  SL811_REG_WRITE(SL811HS_CTRL_REG_1, 0);

  OSS_THREAD_SLEEP(500);

  /* clear interrupt status reg */
  SL811_REG_WRITE(SL811HS_INT_STAT_REG, 0xFF);

  /* check connection status */
  status = SL811_REG_READ(SL811HS_INT_STAT_REG);

  if (status & 0x40) 
    {
      pHost->connected[0] = FALSE;
      DBG_LOG("sl881Init : No device or no power\n",1,2,3,4,5,6);
    }
  else 
    {
      pHost->connected[0] = TRUE;

      if (!(status & 0x80 ))
	{	
	  /* slow speed device connected directly to root-hub */
	  pHost->lowSpeed[0] = TRUE;
	  DBG_LOG("sl881Init : Low speed device connected\n",1,2,3,4,5,6);
	}
      else
	{
	  /* full speed device connect directly to root hub */
	  pHost->lowSpeed[0] = FALSE;
	  DBG_LOG("sl881Reset : Full speed device connected\n",1,2,3,4,5,6);
	}
    }
}


/***************************************************************************
*
* fetchTD - follow a QH to get a TD 
*
*
*
* RETURNS: pointer to next TD in QH, NULL if no more TDs remaning in QH
*/
LOCAL void *fetchTD(pHCD_HOST pHost, BOOL vertical)
{
  void *pTD = NULL;
  BOOL gotTD = FALSE;

  /* Special processing if this QH should process TD depth first */
  if (!vertical) goto step10;

  while (!gotTD)
    {
      /* is element pointer an inactive entry ? */
      if (UHC_FROM_LITTLEL(pHost->pCurrentQH->tdLink) & UHCI_LINK_TERMINATE)
	{
	  /* element pointer inactive. Follow horizontal link */
	step10:
          if (UHC_FROM_LITTLEL(pHost->pCurrentQH->qhLink) & UHCI_LINK_TERMINATE)
            {
              return(pTD);
            }

	  pHost->pCurrentQH = (UHCI_QH *) (UHC_FROM_LITTLEL(pHost->pCurrentQH->qhLink) & 
	    UHCI_LINK_PTR_MASK);
	  
          if ((UHC_FROM_LITTLEL(pHost->pCurrentQH->tdLink) & UHCI_LINK_TERMINATE)
              && (UHC_FROM_LITTLEL(pHost->pCurrentQH->qhLink) & UHCI_LINK_TERMINATE))
            {
              /* header pointer inactive. Leave function and then idle */
              gotTD = TRUE;
            }
	  
	  continue;
	}
      /* element pointer not inactive. Is element pointer pointing to a QH ?*/
      else if (UHC_FROM_LITTLEL(pHost->pCurrentQH->tdLink) & UHCI_LINK_QH)
	{
	  /* element pointer points to a QH. Get next QH from vertical link */
	  /* and continue processing */
	  pHost->pCurrentQH = (UHCI_QH *) (UHC_FROM_LITTLEL(pHost->pCurrentQH->tdLink) & 
	    UHCI_LINK_PTR_MASK);

	  continue;
	}
      /* element pointer points to a TD. return it */
      else
	{
	  gotTD = TRUE;
	  pTD = (void *) (UHC_FROM_LITTLEL(pHost->pCurrentQH->tdLink) & UHCI_LINK_PTR_MASK);
	}
    }

  return(pTD);
}

/***************************************************************************
*
* execute TD - execute a TD
*
*
*

⌨️ 快捷键说明

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