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

📄 usbhcdohcilib.c

📁 基于VXWORK环境的ARM9 S2410的USB驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
		HC_SET_BITS (OHCI_HC_COMMAND_STATUS, OHCI_CS_CLF);		break;	    case USB_XFRTYPE_BULK:		HC_SET_BITS (OHCI_HC_COMMAND_STATUS, OHCI_CS_BLF);		break;	    }	}    }/***************************************************************************** scheduleOtherIrps - schedules other IRPs if TDs are available on a pipe** RETURNS: N/A*/LOCAL VOID scheduleOtherIrps    (    pHCD_HOST pHost,    pHCD_PIPE pPipe    )    {    pUSB_IRP pIrp;    pUSB_IRP pNextIrp;    pIRP_WORKSPACE pWork;    pIrp = usbListFirst (&pHost->busIrps);    while (pIrp != NULL && pPipe->freeTdCount > 0)	{	pNextIrp = usbListNext (&pIrp->hcdLink);	pWork = (pIRP_WORKSPACE) pIrp->hcdPtr;	if (pWork->pPipe == pPipe)	    assignTds (pHost, pPipe, pIrp, pWork);	pIrp = pNextIrp;	}    }/***************************************************************************** releaseTd - Update an IRP based on a completed IRP.** Sets <result> field in <pIrp> to OK or S_usbHcdLib_xxx if IRP completed.** NOTE: Automatically reschedules TDs.** RETURNS: N/A*/LOCAL VOID releaseTd    (    pHCD_HOST pHost,    pHCD_PIPE pPipe,    pUSB_IRP pIrp,    pIRP_WORKSPACE pWork,    pTD_WRAPPER pTd    )    {    pUSB_BFR_LIST pBfrList;    UINT32 control;    UINT32 curBfrPtr;    UINT32 bfrEnd;    UINT32 tdHead;    UINT16 frameCount;    UINT16 psw;    UINT16 actLen;    BOOL underrun = FALSE;    UINT16 i;        /*     * In some case, transmitted data is still used at either drivers or     * applications and need to be re-swapped if they are swapped before     * sending.     */    if (pIrp->bfrList[pWork->bfrNo].pid == USB_PID_SETUP ||	pIrp->bfrList[pWork->bfrNo].pid == USB_PID_OUT)	{	if (pTd->sw.curBfrPtr != 0)	    {	    if (FROM_LITTLEL (pTd->tdg.cbp) == 0)		{		/*		 * By default USB_BUFFER_SWAP is a no-op, but it can be		 * overridden in BSP stubs as necessary.		 */		USB_BUFFER_SWAP ((pVOID *) pTd->sw.curBfrPtr,			FROM_LITTLEL (pTd->tdg.be) - pTd->sw.curBfrPtr + 1);		}	    else		{		/*		 * By default USB_BUFFER_SWAP is a no-op, but it can be		 * overridden in BSP stubs as necessary.		 */		USB_BUFFER_SWAP ((pVOID *) pTd->sw.curBfrPtr,			FROM_LITTLEL (pTd->tdg.cbp) - pTd->sw.curBfrPtr + 1);		}	    }	}    /* Release the bandwidth this TD was consuming. */    pHost->nanoseconds -= pTd->sw.nanoseconds;    /* Examine the TD. */    control = FROM_LITTLEL (pTd->tdg.control);    switch (OHCI_TGCTL_CC (control))	{	case OHCI_CC_NO_ERROR:			break;	case OHCI_CC_CRC:	case OHCI_CC_NO_RESPONSE:			pIrp->result = S_usbHcdLib_CRC_TIMEOUT; 		break;	case OHCI_CC_BITSTUFF:			pIrp->result = S_usbHcdLib_BITSTUFF_FAULT;  		break;	case OHCI_CC_STALL:     		pIrp->result = S_usbHcdLib_STALLED;     		break;	case OHCI_CC_DATA_TOGGLE:			pIrp->result = S_usbHcdLib_DATA_TOGGLE_FAULT; 		break;	case OHCI_CC_PID_CHECK:	case OHCI_CC_UNEXPECTED_PID: 		pIrp->result = S_usbHcdLib_PID_FAULT;			break;	case OHCI_CC_DATA_OVERRUN:	case OHCI_CC_DATA_UNDERRUN:	case OHCI_CC_BFR_OVERRUN:	case OHCI_CC_BFR_UNDERRUN:			pIrp->result = S_usbHcdLib_DATA_BFR_FAULT;  		break;	default:				pIrp->result = S_usbHcdLib_GENERAL_FAULT;   		break;	}    /* If there was an error, then the HC will have halted the ED.  Un-halt     * it so future transfers can take place.     */    tdHead = FROM_LITTLEL (pPipe->pEd->ed.tdHead);    if (pIrp->result != PENDING)	{	pPipe->pEd->ed.tdHead = TO_LITTLEL (tdHead & ~OHCI_PTR_HALTED);	DMA_FLUSH (&pPipe->pEd->ed.tdHead, sizeof (pPipe->pEd->ed.tdHead));	}    /* If ok so far, calculate the actual amount of data transferred. */    if (pIrp->result == PENDING)	{	pBfrList = &pIrp->bfrList [pWork->bfrNo];	/* Note: In following assignment: pTd->tdg.be == pTd->tdi.be */	bfrEnd = FROM_LITTLEL (pTd->tdg.be);	if (pPipe->transferType == USB_XFRTYPE_ISOCH)	    {	    /* For an isoch transfer make sure each frame was executed. */	    frameCount = OHCI_TICTL_FC (control);	    /*	     * Re-swap packet status words before reading if they are swapped	     * at transmit.	     * By default USB_BUFFER_SWAP is a no-op, but it can be	     * overridden in BSP stubs as necessary.	     */	    USB_BUFFER_SWAP ((pVOID *) &pTd->tdi.psw [0],			     frameCount * sizeof (UINT16));	    for (actLen = i = 0; i < frameCount; i++)		{		psw = FROM_LITTLEW (pTd->tdi.psw [i]);		if (OHCI_TIPSW_CC (psw) != OHCI_CC_NO_ERROR)		    {		    pIrp->result = S_usbHcdLib_ISOCH_FAULT;		    break;		    }		}	    actLen = bfrEnd - pTd->sw.curBfrPtr + 1;	    }	else	    {	    /* For a general transfer, calculate the actual data transferred */	    curBfrPtr = FROM_LITTLEL (pTd->tdg.cbp);	    if (pTd->sw.curBfrPtr == 0)		{		/* we requested a 0-length transfer */		actLen = 0;		}	    else		{		/* we requested a transfer of non-zero length */		if (curBfrPtr == 0)		    {		    /* transfer was successful...full length requested. */		    actLen = bfrEnd - pTd->sw.curBfrPtr + 1;		    }		else		    {		    /* short packet was transferred.  curBfrPtr addresses		     * the byte following the last byte transferred.		     */		    actLen = curBfrPtr - pTd->sw.curBfrPtr;		    }		}	    /* Update the IRP's data toggle. */	    pIrp->dataToggle = ((tdHead & OHCI_PTR_TGL_CARRY) == 0) ? 	    USB_DATA0 : USB_DATA1;	    } 		/* Update the BFR_LIST entry and check for underrun. */	pBfrList->actLen += actLen;	if (pTd->sw.curBfrPtr != 0 &&	    actLen < bfrEnd - pTd->sw.curBfrPtr + 1)	    {	    underrun = TRUE;	    if ((pIrp->flags & USB_FLAG_SHORT_FAIL) != 0)		{		pIrp->result = S_usbHcdLib_SHORT_PACKET;		}	    }	if (pBfrList->actLen == pBfrList->bfrLen || underrun)	    {	    pWork->bfrNo++;	    pWork->bfrOffset = 0;	    pWork->zeroLenMapped = FALSE;	    }	}    /* Indicate that the TD is no longer in use. */    memset (pTd, 0, sizeof (*pTd));    pPipe->freeTdCount++;        /* Check if the IRP is complete. */    if (pIrp->result == PENDING)	{	if (pWork->bfrNo == pIrp->bfrCount)	    {	    /* Yes, all buffers for the IRP have been processed. */	    pIrp->result = OK;	    }	else	    {	    /* No, schedule more work for the IRP. */	    assignTds (pHost, pPipe, pIrp, pWork);	    }	}    /* If this is an isochronous pipe and if we've fully mapped the current     * IRP, then check if there are other IRPs which need to be scheduled.     */    if (pPipe->transferType == USB_XFRTYPE_ISOCH &&			       ((pWork->bfrNo + 1 == pIrp->bfrCount && 			       pWork->bfrOffset == 			       pIrp->bfrList [pWork->bfrNo].bfrLen) ||			       pWork->bfrNo == pIrp->bfrCount))	{	scheduleOtherIrps (pHost, pPipe);	}    /* If the IRP is complete, invalidate the cache for any input buffers. */    if (pIrp->result != PENDING)	{	for (i = 0; i < pIrp->bfrCount; i++)	    {	    pBfrList = &pIrp->bfrList [i];		    if (pBfrList->pid == USB_PID_IN && pBfrList->actLen > 0)		{		USER_INVALIDATE (pBfrList->pBfr, pBfrList->actLen);		/* 	 	 * By default USB_BUFFER_SWAP is a no-op, but can be		 * overridden in BSP stubs as necessary.	 	 */		USB_BUFFER_SWAP ((pVOID *) pBfrList->pBfr, pBfrList->actLen);		}	    }	}    }/***************************************************************************** unscheduleIrp - unschedules IRP** RETURNS: N/A*/LOCAL VOID unscheduleIrp    (    pHCD_HOST pHost,    pUSB_IRP pIrp,    pIRP_WORKSPACE pWork        )    {    pHCD_PIPE pPipe = pWork->pPipe;    UINT16 i;    UINT16 tdIndex;    BOOL tdDeleted;    /* If the IRP has no workspace, then it cannot be using TDs, so return      * immediately.     */    if (pWork == NULL)	return;    /* Halt processing on this ED. */    pPipe->pEd->ed.control |= TO_LITTLEL (OHCI_EDCTL_SKIP);    DMA_FLUSH (&pPipe->pEd->ed.control, sizeof (pPipe->pEd->ed.control));    hcSynch (pHost);    /* Search the pipe which owns this IRP to see if any of its TDs are     * in use by this IRP.  If so, release them and allow another IRP (if     * one exists) to use them.     */    tdIndex = pPipe->freeTdIndex;    for (i = 0; i < pPipe->tdCount; i++)	{	tdDeleted = FALSE;	if (pPipe->pTds [tdIndex].sw.pWork == pWork)	    {	    pPipe->freeTdCount++;	    memset (&pPipe->pTds [tdIndex], 0, sizeof (pPipe->pTds [tdIndex]));	    tdDeleted = TRUE;	    }	if (++tdIndex == pPipe->tdCount)	    tdIndex = 0;	/* If we deleted this TD, then advance head of TD list. */	if (tdDeleted)	    {	    pPipe->pEd->ed.tdHead = 	    TO_LITTLEL (TO_PCIPTR (&pPipe->pTds [tdIndex]));	    DMA_FLUSH (&pPipe->pEd->ed.tdHead, sizeof (pPipe->pEd->ed.tdHead));	    }	}        /* Allow the ED to resume. */    pPipe->pEd->ed.control &= ~(TO_LITTLEL (OHCI_EDCTL_SKIP));    DMA_FLUSH (&pPipe->pEd->ed.control, sizeof (pPipe->pEd->ed.control));    }/***************************************************************************** serviceBusIrps - Services completed USB transactions** RETURNS: N/A*/LOCAL VOID serviceBusIrps    (    pHCD_HOST pHost    )    {    UINT32 pciPtrToTd;    pTD_WRAPPER pFirstTd;    pTD_WRAPPER pTd;    pUSB_IRP pIrp;    pIRP_WORKSPACE pWork;    LIST_HEAD completeIrps = {0};    /* Walk the list of complete TDs and update the status of their     * respective IRPs.     *     * NOTE: TDs are in reverse order on the list...That is, the TDs     * which executed first are behind TDs which executed later.  We     * need to process them in the order in which they executed.     */    DMA_INVALIDATE (&pHost->pHcca->doneHead, sizeof (pHost->pHcca->doneHead));    pFirstTd = NULL;    pciPtrToTd = pHost->pHcca->doneHead & TO_LITTLEL (OHCI_PTR_MEM_MASK);    while ((pTd = TD_FROM_PCIPTR (pciPtrToTd)) != NULL)	{	DMA_INVALIDATE (pTd, sizeof (*pTd));	pTd->sw.doneLink = pFirstTd;	pFirstTd = pTd;	pciPtrToTd = pTd->tdg.nextTd & TO_LITTLEL (OHCI_PTR_MEM_MASK);	}    /* pFirstTd now points to a list of TDs in the order in which they     * were completed.     */    while (pFirstTd != NULL)	{	pTd = pFirstTd;	pFirstTd = pTd->sw.doneLink;	pIrp = pTd->sw.pWork->pIrp;	releaseTd (pHost, pTd->sw.pWork->pPipe, pIrp, pTd->sw.pWork, pTd);	if (pIrp->result != PENDING)	    {	    /* IRP is finished...move it to the list of completed IRPs. */	    usbListUnlink (&pIrp->hcdLink);	    usbListLink (&completeIrps, pIrp, &pIrp->hcdLink, LINK_TAIL);	    }	}    /* Invoke IRP callbacks for all completed IRPs. */    while ((pIrp = usbListFirst (&completeIrps)) != NULL)	{	usbListUnlink (&pIrp->hcdLink);	/* See if other IRPs can take advantage of freed TDs. */	pWork = (pIRP_WORKSPACE) pIrp->hcdPtr;	if (pIrp->result != OK)	    unscheduleIrp (pHost, pIrp, pWork);	scheduleOtherIrps (pHost, pWork->pPipe);	/* Release IRP workspace and invoke callback. */	freeIrpWorkspace (pHost, pIrp);	setIrpResult (pIrp, pIrp->result);	}    }/***************************************************************************** scheduleIrp - schedules IRP for execution** RETURNS: N/A*/LOCAL VOID scheduleIrp    (    pHCD_HOST pHost,    pHCD_PIPE pPipe,    pUSB_IRP pIrp    )    {    pIRP_WORKSPACE pWork = (pIRP_WORKSPACE) pIrp->hcdPtr;    /* Mark the time the IRP started */    pWork->irpRunning = TRUE;	    /* running... */    pWork->startTime = OSS_TIME (); /* and its start time */    /* Assign starting frame number for isoch transfers */    if (pPipe->transferType == USB_XFRTYPE_ISOCH)	{	if ((pIrp->flags & USB_FLAG_ISO_ASAP) != 0)	    pWork->isochNext = FINDEX (getFrameNo (pHost) + HC_FRAME_SKIP);

⌨️ 快捷键说明

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