📄 usbhcdohcilib.c
字号:
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); }/***************************************************************************** destroyHost - tears down an HCD_HOST** RETURNS: N/A*/LOCAL VOID destroyHost ( pHCD_HOST pHost ) { pUSB_IRP pIrp; pHCD_PIPE pPipe; /* Mark host as being shut down */ pHost->shutdown = TRUE; /* release any pending IRPs */ while ((pIrp = usbListFirst (&pHost->rootIrps)) != NULL) cancelIrp (pHost, pIrp, S_usbHcdLib_IRP_CANCELED); while ((pIrp = usbListFirst (&pHost->busIrps)) != NULL) cancelIrp (pHost, pIrp, S_usbHcdLib_IRP_CANCELED); /* release any pending pipes */ while ((pPipe = usbListFirst (&pHost->pipes)) != NULL) destroyPipe (pHost, pPipe); /* Disable the HC */ HC_DWORD_OUT (OHCI_HC_CONTROL, 0); HC_DWORD_OUT (OHCI_HC_COMMAND_STATUS, OHCI_CS_HCR); /* restore original interrupt handler */ if (pHost->intInstalled) usbPciIntRestore (intHandler, pHost, pHost->pciCfgHdr.intLine); /* terminate/destroy interrupt handler thread */ if (pHost->intThread != NULL) { /* Terminate the interrupt service thread */ pHost->intThreadExitRequest = TRUE; OSS_SEM_GIVE (pHost->intPending); OSS_SEM_TAKE (pHost->intThreadExit, INT_TIMEOUT); OSS_THREAD_DESTROY (pHost->intThread); } /* release other resources */ if (pHost->hostMutex != NULL) OSS_MUTEX_DESTROY (pHost->hostMutex); if (pHost->intThreadExit != NULL) OSS_SEM_DESTROY (pHost->intThreadExit); if (pHost->intPending != NULL) OSS_SEM_DESTROY (pHost->intPending); if (pHost->handle != NULL) usbHandleDestroy (pHost->handle); /* release root hub per-port data */ if (pHost->pRhPortChange != NULL) OSS_FREE (pHost->pRhPortChange); /* eliminate DMA memory pool. * * NOTE: This automatically deletes any objects allocated within the * DMA memory pool, e.g., the OHCI HCCA. */ if (pHost->dmaPool != NULL) cacheDmaFree (pHost->dmaPool); OSS_FREE (pHost); }/***************************************************************************** fncAttach - Initialize the HCD and attach to specified bus(es)** The convention for the OHCI HCD is that the param passed in the HRB* is a pointer to a PCI_CFG_HEADER structure for the HC to be managed.** RETURNS: S_usbHcdLib_xxxx*/LOCAL int fncAttach ( pHRB_ATTACH pHrb ) { pHCD_HOST pHost; pPCI_CFG_HEADER pCfgHdr; UINT32 memBase; int i; int s; /* validate parameters */ if ((s = validateHrb (pHrb, sizeof (*pHrb))) != OK) return s; /* Check to make sure structures compiled to correct size */ if (OHCI_HCCA_ACTLEN != OHCI_HCCA_LEN || OHCI_ED_ACTLEN != OHCI_ED_LEN || OHCI_TD_GEN_ACTLEN != OHCI_TD_GEN_LEN || OHCI_TD_ISO_ACTLEN != OHCI_TD_ISO_LEN || TD_WRAPPER_ACTLEN != TD_WRAPPER_LEN) { return S_usbHcdLib_STRUCT_SIZE_FAULT; } /* determine io base address */ pCfgHdr = (pPCI_CFG_HEADER) pHrb->param; memBase = 0; for (i = 0; i < PCI_CFG_NUM_BASE_REG; i++) if ((pCfgHdr->baseReg [i] & PCI_CFG_BASE_IO) == 0 && (memBase = pCfgHdr->baseReg [i] & PCI_CFG_MEMBASE_MASK) != 0) break; if (memBase == 0) return S_usbHcdLib_HW_NOT_READY; /* create/initialize an HCD_HOST structure to manage the HC. */ if ((pHost = OSS_CALLOC (sizeof (*pHost))) == NULL) return S_usbHcdLib_OUT_OF_MEMORY; memcpy (&pHost->pciCfgHdr, pCfgHdr, sizeof (*pCfgHdr)); pHost->mngmtCallback = pHrb->mngmtCallback; pHost->mngmtCallbackParam = pHrb->mngmtCallbackParam; /* initialize pHost->memBase...cannot use HC_SET_BITS, etc. until * ioBase is initialized. */ pHost->memBase = (pUINT32) (memBase + USB_PCI_MEMIO_OFFSET()); /* * Create a semaphore to syncronize the host controller. This is used * to make the HC wait a frame for traffic to settle */ pHost->hcSyncSem = semBCreate(SEM_Q_FIFO, SEM_EMPTY); if (pHost->hcSyncSem == NULL) return S_usbHcdLib_OUT_OF_RESOURCES; /* Check the hardware revision level */ if ((HC_DWORD_IN (OHCI_HC_REVISION) & OHCI_RREV_REV_MASK) < REQUIRED_OHCI_LEVEL) return S_usbHcdLib_HW_NOT_READY; /* reset the host controller. * * NOTE: At the same time, we disable anything else which may be * enabled in the OHCI control register. * * NOTE: We allow the HC to revert to the nominal (default) frame * interval in response to the reset. */ HC_DWORD_OUT (OHCI_HC_CONTROL, 0); HC_DWORD_OUT (OHCI_HC_COMMAND_STATUS, OHCI_CS_HCR); if (!waitOnBits (pHost, OHCI_HC_COMMAND_STATUS, OHCI_CS_HCR, 0)) { destroyHost (pHost); return S_usbHcdLib_HW_NOT_READY; } /* Allocate structures, resources, etc. */ if ((pHost->dmaPool = cacheDmaMalloc (DMA_MEMORY_SIZE)) == NULL || (pHost->memPartId = memPartCreate (pHost->dmaPool, DMA_MEMORY_SIZE)) == NULL || (pHost->pRhPortChange = OSS_CALLOC (pHost->numPorts * sizeof (UINT32))) == NULL || (pHost->pHcca = DMA_MALLOC (sizeof (*pHost->pHcca), OHCI_HCCA_ALIGNMENT)) == NULL || (pHost->pIsochAnchorEd = DMA_MALLOC (sizeof (*pHost->pIsochAnchorEd), OHCI_TD_ISO_ALIGNMENT)) == NULL || usbHandleCreate (HCD_HOST_SIG, pH
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -