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

📄 usbhcdsl811hslib.c

📁 有关vxworks 的host 的源程序
💻 C
📖 第 1 页 / 共 5 页
字号:
* RETURNS: 
*/
LOCAL void executeTD(pHCD_HOST pHost)
{
  UINT32 ctlSts, token;
  UINT8 *buffer;
  SL11XACTION xact;
  BOOL lowSpeedDevice, isoXfer;
  UINT8 tmp = 0;
  
  /* get control/status */
  ctlSts = FROM_LITTLEL(pHost->pCurrentTD->ctlSts);

  /* get token */
  token = FROM_LITTLEL(pHost->pCurrentTD->token);

  /* get buffer */
  buffer = (UINT8 *) (UHC_FROM_LITTLEL(pHost->pCurrentTD->bfrPtr));

  /* get speed */
  lowSpeedDevice = ctlSts & UHCI_TDCS_LOWSPEED;

  /* iso xfer ? */
  isoXfer = ctlSts & UHCI_TDCS_ISOCH;

  /* get data len */
  xact.dlen = UHCI_TDTOK_MAXLEN(token);

  /* get endpoint */
  xact.ep = UHCI_TDTOK_ENDPT(token);

  /* get device address */
  xact.addr = UHCI_TDTOK_DEVADRS(token);

  /* get packet id */
  xact.pid = UHCI_TDTOK_PID(token);

  /* set pid and ep register */
  SL811_REG_WRITE(SL811HS_PID_DEVEND_A, ((xact.pid & 0xf) << 4) | xact.ep);

  /* set usb address register */
  SL811_REG_WRITE(SL811HS_DEVADDR_TCNT_A, xact.addr);

  /* set length register */
  SL811_REG_WRITE(SL811HS_BASE_LEN_A, xact.dlen);

  /* set base address register */
  SL811_REG_WRITE(SL811HS_BASE_ADDR_A, 0x10);

  /* move output data to buffer */
  if ((xact.pid == USB_PID_SETUP) || (xact.pid == USB_PID_OUT))
    {
      int   i,j;
#ifdef SL811HS_LOG
      int   l=xact.dlen;
      UINT8 *b=buffer;
#endif

      /* SL811_BUF_WRITE(0x10,buffer,xact.dlen); */
      for (i=0,j=0x10; i<xact.dlen; j++,i++) {SL811_REG_WRITE(j,buffer[i]);}

#ifdef SL811HS_LOG
        {
        char dbgStr[1500]="    OUT ";
        for ( i=0;i<l;i++ )
            {
            sprintf(dbgStr+8+(i*3),"%02x ",b[i]);
            } /* end of for () */
        sprintf(dbgStr+8+(i*3),"\n");
        DBG_LOG(dbgStr,1,2,3,4,5,6);
        }
#endif
    }

  /* figure out CTRL REG A */
  if (lowSpeedDevice &&  (!(pHost->lowSpeed[0])))
    tmp |= SL811HS_HCTLMASK_PREAMBLE;

  if (token & (UINT32)(UHCI_TDTOK_DATA_TOGGLE)) tmp |= SL811HS_HCTLMASK_SEQ;

  if (isoXfer) tmp |= SL811HS_HCTLMASK_ISOCH;

  if ((xact.pid == USB_PID_SETUP) || (xact.pid == USB_PID_OUT))
    tmp |= SL811HS_HCTLMASK_WRITE;
  else tmp |= SL811HS_HCTLMASK_SEQ;
    
  /* start the xfer */
  tmp |= SL811HS_HCTLMASK_ARM | SL811HS_HCTLMASK_ENBLEP;

  SL811_REG_WRITE(SL811HS_CTRL_REG_A, tmp);
}

/***************************************************************************
*
* getFrameNo - returns current hardware frame number
*
* RETURNS: value of current frame number
*/

LOCAL UINT16 getFrameNo
    (
    pHCD_HOST pHost
    )

    {
      return FINDEX(pHost->frameNo);
    }


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

	if ((pWork->pTdPool = DMA_MALLOC (tdLen, UHCI_TD_ALIGNMENT)) == NULL)
	    {
	    freeIrpWorkspace (pHost, pIrp);
	    return FALSE;
	    }

	memset (pWork->pTdPool, 0, tdLen);
	}


    /* Create a chain of TDs in the "free" list */

    pWork->pTdInUse = pWork->pTdFree = NULL;

    for (i = 0; i < pWork->tdCount; i++)
	{
	pWork->pTdPool [i].sw.pWork = pWork;

	pWork->pTdPool [i].sw.pNext = pWork->pTdFree;
	pWork->pTdFree = &pWork->pTdPool [i];
	}


    /* Initialize the pointer to the last TD in use */

    pWork->pLastTdInUse = NULL;


    return TRUE;
    }


/***************************************************************************
*
* isBandwidthTracked - determines if bandwidth is tracked for this transfer
*
* Since the USBD has already reserved adequate bandwidth for isochronous
* and interrupt transfers, we only track low speed control transfers.
*
* RETURNS: TRUE if bandwidth tracked, else FALSE.
*/

LOCAL BOOL isBandwidthTracked
    (
    pHCD_PIPE pPipe
    )

    {

    if (pPipe->transferType == USB_XFRTYPE_CONTROL &&

⌨️ 快捷键说明

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