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

📄 usbhcdohcilib.c

📁 VxWorks BSP for S3C2510A
💻 C
📖 第 1 页 / 共 5 页
字号:


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

LOCAL UINT16 getFrameNo
    (
    pHCD_HOST pHost
    )

    {
    return OHCI_FMN_FN (HC_DWORD_IN (OHCI_HC_FM_NUMBER));
    }


/***************************************************************************
*
* setFrameInterval - sets OHCI frame interval 
*
* RETURNS: N/A
*/

LOCAL VOID setFrameInterval
    (
    pHCD_HOST pHost,
    UINT16 sofInterval
    )

    {
    UINT32 fmi;

    fmi = HC_DWORD_IN (OHCI_HC_FM_INTERVAL) & ~OHCI_FMI_FIT;
    fmi ^= OHCI_FMI_FIT;

    fmi |= OHCI_FMI_FI_FMT (sofInterval);
    fmi |= OHCI_FMI_FSMPS_FMT (((sofInterval - MAX_FRAME_OVERHEAD) * 6) / 7);

    HC_DWORD_OUT (OHCI_HC_FM_INTERVAL, fmi);

    pHost->sofInterval = sofInterval;
    }


/***************************************************************************
*
* hcSynch - give the host controller a chance to synchronize
*
* RETURNS: N/A
*/

LOCAL VOID hcSynch
    (
    pHCD_HOST pHost
    )

    {
    UINT16 currentFrameNo = getFrameNo (pHost);

    while (getFrameNo (pHost) == currentFrameNo);
	semTake (pHost->hcSyncSem, 1);

	semTake (pHost->hcSyncSem, 1);

    }


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


/***************************************************************************
*
* 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 <= OHCI_INT_ED_COUNT */
    )

    {
    UINT16 i;

    /* Select an interval which is the largest power of two less than or
     * equal to the requested interval.
     */

    for (i = 2; i < OHCI_INT_ED_COUNT + 1; i <<= 1)
	{
	if (i > interval)
	    break;
	}

    return i >> 1;
    }


/***************************************************************************
*
* freeIrpWorkspace - releases IRP_WORKSPACE
*
* Releases the IRP_WORKSPACE associated with an IRP (if there is one).
*
* RETURNS: N/A
*/

LOCAL VOID freeIrpWorkspace
    (
    pHCD_HOST pHost,
    pUSB_IRP pIrp
    )

    {
    pIRP_WORKSPACE pWork = (pIRP_WORKSPACE) pIrp->hcdPtr;

    if (pWork != NULL)
	{
	OSS_FREE (pWork);
	pIrp->hcdPtr = NULL;
	}
    }


/***************************************************************************
*
* allocIrpWorkspace - creates workspace for IRP
*
* Creates an IRP_WORKSPACE structure to manage the IRP data transfer.
*
* RETURNS: TRUE if successful, else FALSE
*/

LOCAL BOOL allocIrpWorkspace
    (
    pHCD_HOST pHost,
    pHCD_PIPE pPipe,
    pUSB_IRP pIrp
    )

    {
    pIRP_WORKSPACE pWork;


    /* Allocate IRP_WORKSPACE */

    if ((pWork = OSS_CALLOC (sizeof (*pWork))) == NULL)
	return FALSE;

    pIrp->hcdPtr = pWork;
    pWork->pPipe = pPipe;
    pWork->pIrp = pIrp;

    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 && 
			       pPipe->speed == USB_SPEED_LOW)
	return TRUE;

    return FALSE;
    }


/***************************************************************************
*
* dirFromPid - returns USB_DIR_xxxx based on USB_PID_xxxx
*
* RETURNS: USB_DIR_xxxx
*/

LOCAL UINT16 dirFromPid
    (
    UINT16 pid
    )

    {
    switch (pid)
	{
	case USB_PID_SETUP:
	case USB_PID_OUT:	
		return USB_DIR_OUT;
	case USB_PID_IN:	
		return USB_DIR_IN;
	default:	    
		return USB_DIR_IN;
	}
    }


/***************************************************************************
*
* unscheduleIsochPipe - removes an isoch pipe from the schedule
*
* RETURNS: N/A
*/

LOCAL VOID unscheduleIsochPipe
    (
    pHCD_HOST pHost,
    pHCD_PIPE pPipe
    )

    {
    pUINT32 pPciPtrToEd;
    pED_WRAPPER pCurEd;


    /* Note: Instead of halting periodic transfers before delinking, we 
     * immediately delink them and afterward wait for the next frame to start...
     * This ensures that caller won't de-allocate the structures while the
     * HC may still be referencing them.
     */

    /* Walk the isoch. list until we find the ED to be removed. */

    pPciPtrToEd = (pUINT32) &pHost->pIsochAnchorEd->ed.nextEd;

    while ((pCurEd = ED_FROM_PCIPTR (*pPciPtrToEd)) != pPipe->pEd)
	{
	pPciPtrToEd = (pUINT32) &pCurEd->ed.nextEd;
	}

    *pPciPtrToEd = pPipe->pEd->ed.nextEd;
    DMA_FLUSH (pPciPtrToEd, sizeof (*pPciPtrToEd));


    /*  
     * shutOffListProcessing() halts isoch, interrupt and bulk transfers 
     * when a device is disconnected, we make sure they are re-enabled.
     */
 
    HC_SET_BITS(OHCI_HC_CONTROL,OHCI_CTL_PLE);
    HC_SET_BITS(OHCI_HC_CONTROL,OHCI_CTL_IE);
    HC_SET_BITS(OHCI_HC_CONTROL,OHCI_CTL_BLE);

    /* Wait for the HC to make sure the structure is really released. */

    hcSynch (pHost);
    }
    

/***************************************************************************
*
* scheduleIsochPipe - inserts isoch pipe into the schedule
*
* Schedules an isochronous transfer for the first time.
*
* RETURNS: N/A
*/

LOCAL VOID scheduleIsochPipe
    (
    pHCD_HOST pHost,
    pHCD_PIPE pPipe
    )

    {
    pED_WRAPPER pLastEd;
    pED_WRAPPER pNextEd;


    /* Flush the ED out of the cache before giving it to the HC. */

    DMA_FLUSH (pPipe->pEd, sizeof (*pPipe->pEd));


    /* Append this ED to the end of the isoch. list. */

    pLastEd = pHost->pIsochAnchorEd;

    while ((pNextEd = ED_FROM_PCIPTR (pLastEd->ed.nextEd)) != NULL)
	pLastEd = pNextEd;


    pLastEd->ed.nextEd = TO_LITTLEL (TO_PCIPTR (pPipe->pEd));
    DMA_FLUSH (&pLastEd->ed.nextEd, sizeof (pLastEd->ed.nextEd));
    }


/***************************************************************************
*
* unscheduleInterruptPipe - removes interrupt pipe from the schedule
*
* RETURNS: N/A
*/

LOCAL VOID unscheduleInterruptPipe
    (
    pHCD_HOST pHost,
    pHCD_PIPE pPipe
    )

    {
    pUINT32 pPciPtrToEd;
    pED_WRAPPER pCurEd;
    UINT16 i;


    /* Note: Instead of halting periodic transfers before delinking, we 
     * immediately delink them and afterward wait for the next frame to start...
     * This ensures that caller won't de-allocate the structures while the
     * HC may still be referencing them.
     */

    /* Remove the pipe from the interrupt lists. */

    for (i = 0; i < OHCI_INT_ED_COUNT; i += pPipe->actInterval)
	{
	/* Walk this list until we find the ED to be removed. */

	pPciPtrToEd = &pHost->pHcca->intEdTable [i];

	while ((pCurEd = ED_FROM_PCIPTR (*pPciPtrToEd)) != pHost->pIsochAnchorEd &&
		pCurEd->sw.pPipe->actInterval >= pPipe->actInterval &&
		pCurEd != pPipe->pEd)
	    {
	    pPciPtrToEd = (pUINT32) &pCurEd->ed.nextEd;
	    }

	if (pCurEd == pPipe->pEd)
	    {
	    *pPciPtrToEd = pPipe->pEd->ed.nextEd;
	    DMA_FLUSH (pPciPtrToEd, sizeof (*pPciPtrToEd));
	    }
	}

    /*  
     * shutOffListProcessing() halts isoch, interrupt and bulk transfers 
     * when a device is disconnected, we make sure they are re-enabled.
     */                 
 
    HC_SET_BITS(OHCI_HC_CONTROL,OHCI_CTL_PLE);
    HC_SET_BITS(OHCI_HC_CONTROL,OHCI_CTL_IE);
    HC_SET_BITS(OHCI_HC_CONTROL,OHCI_CTL_BLE);

    /* Wait for the HC to make sure the structure is really released. */

    hcSynch (pHost);
    }
    

/***************************************************************************
*
* scheduleInterruptPipe - inserts interrupt pipe into the schedule
*
* Schedules an interrupt transfer repeatedly in the frame list as
* indicated by the service interval.
*
* RETURNS: N/A
*/

LOCAL VOID scheduleInterruptPipe
    (
    pHCD_HOST pHost,
    pHCD_PIPE pPipe
    )

    {
    pUINT32 pPciPtrToEd;
    pED_WRAPPER pCurEd;
    UINT16 i;


    /* Schedule the pipe onto the interrupt lists. */

    for (i = 0; i < OHCI_INT_ED_COUNT; i += pPipe->actInterval)
	{
	/* Walk this list until we hit the isoch. anchor or until we
	 * find an pipe with a smaller interval (higher frequency).
	 */

	pPciPtrToEd = &pHost->pHcca->intEdTable [i];

	while ((pCurEd = ED_FROM_PCIPTR (*pPciPtrToEd)) != pHost->pIsochAnchorEd &&
		pCurEd->sw.pPipe->actInterval >= pPipe->actInterval &&
		pCurEd != pPipe->pEd)
	    {
	    pPciPtrToEd = (pUINT32) &pCurEd->ed.nextEd;
	    }

	if (pCurEd != pPipe->pEd)
	    {
	    if (i == 0)
		{
		pPipe->pEd->ed.nextEd = *pPciPtrToEd;
		DMA_FLUSH (pPipe->pEd, sizeof (*pPipe->pEd));
		}

	    *pPciPtrToEd = TO_LITTLEL (TO_PCIPTR (pPipe->pEd));
	    DMA_FLUSH (pPciPtrToEd, sizeof (*pPciPtrToEd));
	    }
	}
    }


/***************************************************************************
*
* unscheduleControlPipe - removes control pipe from the schedule
*
* RETURNS: N/A
*/

LOCAL VOID unscheduleControlPipe
    (
    pHCD_HOST pHost,
    pHCD_PIPE pPipe
    )

⌨️ 快捷键说明

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