📄 usbhcdohcilib.c
字号:
else pWork->isochNext = FINDEX (pIrp->startFrame); } /* Assign TDs to direct data transfer. */ assignTds (pHost, pPipe, pIrp, pWork); }/***************************************************************************** cancelIrp - cancel's an outstanding IRP** If the IRP's result code is not PENDING, then we cannot cancel* the IRP as it has either already completed or it is not yet enqueued.** RETURNS: OK if IRP canceled* S_usbHcdLib_CANNOT_CANCEL if IRP already completed*/LOCAL int cancelIrp ( pHCD_HOST pHost, pUSB_IRP pIrp, int result /* error to assign to IRP */ ) { pIRP_WORKSPACE pWork; pHCD_PIPE pPipe; int s = OK; if (pIrp->result != PENDING) s = S_usbHcdLib_CANNOT_CANCEL; else { /* The IRP is pending. Unlink it. */ usbListUnlink (&pIrp->hcdLink); /* If this IRP is a "bus" IRP - as opposed to a root IRP - then * remove it from the HC's work list. */ if ((pWork = (pIRP_WORKSPACE) pIrp->hcdPtr) != NULL && pWork->pPipe->busAddress != pHost->rootAddress) { /* Remove QHs/TDs from the work list and release workspace. */ pPipe = pWork->pPipe; unscheduleIrp (pHost, pIrp, pWork); freeIrpWorkspace (pHost, pIrp); /* This may create an opportunity to schedule other IRPs. */ scheduleOtherIrps (pHost, pPipe); } setIrpResult (pIrp, result); } return s; }/***************************************************************************** shutOffListProcessing - shut of host controller interrupts for list proc.** Permits the host controller from processing the periodic, interrupt and bulk* TD lists.** RETURNS: N/A.*/LOCAL void shutOffListProcessing ( pHCD_HOST pHost ) { UINT32 controlRegChange; hcSynch (pHost); /* * Read the register and mask off the bits that denote list processing * is enabled */ /* Periodic List = Isoc transfers */ controlRegChange = HC_DWORD_IN (OHCI_HC_CONTROL) & (OHCI_CTL_PLE); pHost->pHcControlReg = controlRegChange; HC_CLR_BITS (OHCI_HC_CONTROL, pHost->pHcControlReg); /* Interrupt List = Interrupt transfers */ controlRegChange = HC_DWORD_IN (OHCI_HC_CONTROL) &(OHCI_CTL_IE); pHost->pHcControlReg = controlRegChange; HC_CLR_BITS (OHCI_HC_CONTROL, pHost->pHcControlReg); /* Bulk List = Bulk transfers */ controlRegChange = HC_DWORD_IN (OHCI_HC_CONTROL) & OHCI_CTL_BLE; pHost->pHcControlReg = controlRegChange; HC_CLR_BITS (OHCI_HC_CONTROL, pHost->pHcControlReg); }/***************************************************************************** isHubStatus - checks status on root hub** RETURNS: hub and port status bitmap as defined by USB*/LOCAL UINT8 isHubStatus ( pHCD_HOST pHost ) { UINT8 hubStatus = 0; UINT16 port; UINT32 portRegOffset; UINT32 portChange; UINT32 hcRhPortStatusReg; for (port = 0; port < pHost->numPorts; port++) { portRegOffset = OHCI_HC_RH_PORT_STATUS + port * sizeof (UINT32); /* Read & clear pending change status */ hcRhPortStatusReg = HC_DWORD_IN (portRegOffset); portChange = hcRhPortStatusReg & (OHCI_RHPS_CSC | OHCI_RHPS_PESC | OHCI_RHPS_PSSC | OHCI_RHPS_OCIC | OHCI_RHPS_PRSC); if (portChange != 0) HC_DWORD_OUT (portRegOffset, portChange); hcSynch (pHost); /* Combine the change bits reported by the HC with those we * already know about. Then report if a change is pending. */ pHost->pRhPortChange [port] |= portChange; if ((pHost->pRhPortChange [port] & (OHCI_RHPS_CSC | OHCI_RHPS_PESC | OHCI_RHPS_PSSC | OHCI_RHPS_OCIC | OHCI_RHPS_PRSC)) != 0) { hubStatus |= USB_HUB_ENDPOINT_STS_PORT0 << port; } /* there was a change - a device has been plugged, or unplugged */ if ( (hcRhPortStatusReg & OHCI_RHPS_CSC) !=0) /* A device has been unplugged */ if ( (hcRhPortStatusReg & OHCI_RHPS_CCS) == 0 ) { /* Stop the host controller from processing TD's */ shutOffListProcessing (pHost); } } return hubStatus; }/***************************************************************************** serviceRootIrps - Services root hub transactions** RETURNS: N/A*/LOCAL VOID serviceRootIrps ( pHCD_HOST pHost ) { UINT8 hubStatus; UINT16 irpCount; pUSB_IRP pIrp; if ((hubStatus = isHubStatus (pHost)) != 0) { for (irpCount = pHost->rootIrpCount; irpCount > 0; irpCount--) { pIrp = usbListFirst (&pHost->rootIrps); --pHost->rootIrpCount; usbListUnlink (&pIrp->hcdLink); *(pIrp->bfrList [0].pBfr) = hubStatus; pIrp->bfrList [0].actLen = 1; setIrpResult (pIrp, OK); } } }/***************************************************************************** processInterrupt - process a hardware interrupt from the HC** Determine the cause of a hardware interrupt and service it. If the* interrupt results in the completion of one or more IRPs, handle the* completion processing for those IRPs.** RETURNS: N/A*/LOCAL VOID processInterrupt ( pHCD_HOST pHost ) { UINT32 intBits = HC_DWORD_IN (OHCI_HC_INT_STATUS) & INT_ENABLE_MASK; /* evaluate the interrupt condition */ if ((intBits & OHCI_INT_SO) != 0) { /* Scheduling overrun detected. Record it. */ pHost->errScheduleOverrun++; HC_DWORD_OUT (OHCI_HC_INT_STATUS, OHCI_INT_SO); /* acknowledge */ } if ((intBits & OHCI_INT_UE) != 0) { /* Unrecoverable error detected. Record it. */ pHost->errUnrecoverable++; HC_DWORD_OUT (OHCI_HC_INT_STATUS, OHCI_INT_UE); /* acknowledge */ } if ((intBits & OHCI_INT_RD) != 0) { /* Resume detected. */ if (pHost->mngmtCallback != NULL) (*pHost->mngmtCallback) (pHost->mngmtCallbackParam, pHost->handle, 0 /* bus number */, HCD_MNGMT_RESUME); HC_DWORD_OUT (OHCI_HC_INT_STATUS, OHCI_INT_RD); /* acknowledge */ } if ((intBits & OHCI_INT_RHSC) != 0) { /* Root host change detected. */ serviceRootIrps (pHost); HC_DWORD_OUT (OHCI_HC_INT_STATUS, OHCI_INT_RHSC); /* acknowledge */ } if ((intBits & OHCI_INT_WDH) != 0) { /* The HC has updated the done queue. This implies completion * of one or more USB transactions detected. */ serviceBusIrps (pHost); pHost->pHcca->doneHead = 0; HC_DWORD_OUT (OHCI_HC_INT_STATUS, OHCI_INT_WDH); /* acknowledge */ } /* Re-enable HC interrupts */ HC_DWORD_OUT (OHCI_HC_INT_ENABLE, INT_ENABLE_MASK); }/***************************************************************************** checkIrpTimeout - Checks for IRPs which may have timed-out** RETURNS: N/A*/LOCAL VOID checkIrpTimeout ( pHCD_HOST pHost /* host to check */ ) { pUSB_IRP pIrp; pUSB_IRP pNextIrp; pIRP_WORKSPACE pWork; UINT32 now; /* Search for one or more IRPs which have been completed * (or partially completed). */ now = OSS_TIME (); pIrp = usbListFirst (&pHost->busIrps); while (pIrp != NULL) { pNextIrp = usbListNext (&pIrp->hcdLink); pWork = (pIRP_WORKSPACE) pIrp->hcdPtr; if (pIrp->timeout != USB_TIMEOUT_NONE && pWork->irpRunning && now - pWork->startTime > pIrp->timeout) { /* This IRP has exceeded its run time. */ cancelIrp (pHost, pIrp, S_usbHcdLib_TIMEOUT); } pIrp = pNextIrp; } }/***************************************************************************** intThread - Thread invoked when hardware interrupts are detected** By convention, the <param> to this thread is a pointer to an HCD_HOST.* This thread waits on the intPending semaphore in the HCD_HOST which is* signalled by the actual interrupt handler. This thread will continue* to process interrupts until intThreadExitRequest is set to TRUE in the* HCD_HOST structure.** This thread wakes up every HC_TIMEOUT_SRVC_INTERVAL milliseconds and * checks for IRPs which may have timed-out.** RETURNS: N/A*/LOCAL VOID intThread ( pVOID param ) { pHCD_HOST pHost = (pHCD_HOST) param; UINT32 interval; UINT32 now; UINT32 lastTime = OSS_TIME (); do { /* Wait for an interrupt to be signalled. */ now = OSS_TIME (); interval = HC_TIMEOUT_SRVC_INTERVAL - min (now - lastTime, HC_TIMEOUT_SRVC_INTERVAL); if (OSS_SEM_TAKE (pHost->intPending, interval) == OK) { /* semaphore was signalled, int pending */ if (!pHost->intThreadExitRequest) { OSS_MUTEX_TAKE (pHost->hostMutex, OSS_BLOCK); processInterrupt (pHost); OSS_MUTEX_RELEASE (pHost->hostMutex); } } if ((now = OSS_TIME ()) - lastTime >= HC_TIMEOUT_SRVC_INTERVAL) { /* check for timed-out IRPs */ lastTime = now; /* Look for IRPs which may have timed-out. */ OSS_MUTEX_TAKE (pHost->hostMutex, OSS_BLOCK); checkIrpTimeout (pHost); OSS_MUTEX_RELEASE (pHost->hostMutex); } } while (!pHost->intThreadExitRequest); /* Signal that we've acknowledged the exit request */ OSS_SEM_GIVE (pHost->intThreadExit); }/***************************************************************************** intHandler - hardware interrupt handler** This is the actual routine which receives hardware interrupts from the* HC. This routine immediately reflects the interrupt to the intThread.* interrupt handlers have execution restrictions which are not imposed* on normal threads...So, this scheme gives the intThread complete* flexibility to call other services and libraries while processing the* interrupt condition.** RETURNS: N/A*/LOCAL VOID intHandler ( pVOID param ) { pHCD_HOST pHost = (pHCD_HOST) param; /* Is there an interrupt pending in the OHCI interrupt status reg? */ if ((HC_DWORD_IN (OHCI_HC_INT_STATUS) & INT_ENABLE_MASK) != 0) { pHost->intCount++; /* Disable further interrupts until the intThread takes over */ HC_DWORD_OUT (OHCI_HC_INT_DISABLE, OHCI_INT_MIE); /* Signal the interrupt thread to process the interrupt. */ OSS_SEM_GIVE (pHost->intPending); } /* Prevent the hcSync routine from busy waiting. */ if(pHost->hcSyncSem) semGive (pHost->hcSyncSem); }/***************************************************************************** validateHrb - validate an HRB** Checks the HRB length set in the HRB_HEADER against the <expectedLen>* passed by the caller. ** RETURNS: S_usbHcdLib_xxxx*/LOCAL int validateHrb ( pVOID pHrb, UINT16 expectedLen ) { pHRB_HEADER pHeader = (pHRB_HEADER) pHrb; if (pHeader->hrbLength != expectedLen) return S_usbHcdLib_BAD_PARAM; return OK; }/***************************************************************************** destroyPipe - tears down an HCD_PIPE** RETURNS: N/A*/LOCAL void destroyPipe ( pHCD_HOST pHost, pHCD_PIPE pPipe ) { if (pPipe->pEd != NULL) { /* Release ED allocated for pipe. */ unschedulePipe (pHost, pPipe); DMA_FREE (pPipe->pEd); } /* Release bandwidth associated with pipe. */ pHost->nanoseconds -= pPipe->time; /* Release pipe */ usbListUnlink (&pPipe->link); usbHandleDestroy (pPipe->pipeHandle); OSS_FREE (pPipe); }/****************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -