📄 usbohciisr.c
字号:
UINT8 uHostControllerIndex ) { /* To hold the value read from the interrupt status registers */ UINT32 uInterruptStatus = 0; /* To hold the pointer to the host controller information */ PUSB_OHCI_INFORMATION pOhciControllerInfo = NULL; /* * To hold the pointer to the pipe pending for deletion or cancellation * for transfer. */ PUSB_OHCI_ENDPOINT_DESCRIPTOR pEndpointDescriptor = NULL; UINT32 uRegReadValue = 0; /* Check whether the host controller index is valid */ if (uHostControllerIndex >= maxOhciCount) { /* Debug print */ OS_LOG_MESSAGE_LOW( OHCD, "Entering the function: usbOhciProcessInterrupts().\n", 0, 0, 0, 0); /* Invalid host controller index */ return; } /* Obtain the pointer to the host controller information */ pOhciControllerInfo = &usbOhciControllerInfo[uHostControllerIndex];#ifndef USB_OHCI_POLLING_MODE /* Disable the interrupts */ USB_OHCI_REG_WRITE (uHostControllerIndex, (pOhciControllerInfo->uBaseAddress + USB_OHCI_INTERRUPT_DISABLE_REGISTER_OFFSET), USB_OHCI_INTERRUPT_MASK);#endif /* End of #ifndef USB_OHCI_POLLING_MODE */ /* Read the contents of the HC Interrupt Status register */ uInterruptStatus = USB_OHCI_REG_READ (uHostControllerIndex, pOhciControllerInfo->uBaseAddress + USB_OHCI_INTERRUPT_STATUS_REGISTER_OFFSET); /* Read the contents of the control register */ uRegReadValue = USB_OHCI_REG_READ(uHostControllerIndex, pOhciControllerInfo->uBaseAddress + USB_OHCI_CONTROL_REGISTER_OFFSET); /* Check if there are elements in the endpoint disabled list */ if (pOhciControllerInfo->pDisabledEndpointListHead != NULL) { uInterruptStatus &= (USB_OHCI_INTERRUPT_MASK | USB_OHCI_INTERRUPT_STATUS_SOF); } else { uInterruptStatus &= USB_OHCI_INTERRUPT_MASK; USB_OHCI_REG_WRITE (uHostControllerIndex, (pOhciControllerInfo->uBaseAddress + USB_OHCI_INTERRUPT_STATUS_REGISTER_OFFSET), (uInterruptStatus & USB_OHCI_INTERRUPT_STATUS_SOF)); } /* Check whether an interrupt is pending */ if (uInterruptStatus != 0) { /* * Check whether the Write Back Done Head interrupt is pending. * * NOTE: Check for the Write Back Done Head interrupt before checking * the SOF interrupt. This is because the SOF interrupt is used * for cancelling the transfers. * * However, the transfer which is marked for cancellation could * have been completed. Hence, Write Back Done Head interrupt * should be checked before attempting to cancel a transfer * (i.e. servicing the SOF interrupt). */ if ((uInterruptStatus & USB_OHCI_INTERRUPT_STATUS_DONE_HEAD) == USB_OHCI_INTERRUPT_STATUS_DONE_HEAD) { /* To hold the head pointer to the list of transfers completed */ PVOID pTransferCompletion = NULL; /* To hold the pointer to the HCCA */ PUSB_OHCI_HCCA pHCCA = NULL; /* * Obtain the contents of the transfer done head in the host * controller communication area. This value corresponds to the * head of the list of transfers completed. */ /* Invalidate the cache */ DMA_INVALIDATE(pOhciControllerInfo->pHccaAligned,sizeof(USB_OHCI_HCCA)); /* Retrieve the HCCA information */ pHCCA = pOhciControllerInfo->pHccaAligned; /* Invalidate the HCCADone head cache *//* DMA_INVALIDATE(&pHCCA->uHccaDoneHead, sizeof(UINT32));*/ DMA_INVALIDATE(pHCCA + USB_OHCI_HCCA_DONEHEAD_OFFSET , sizeof(UINT32)); /* Retrieve the HCCA Done head */ pTransferCompletion = (PVOID)pHCCA->uHccaDoneHead; /* Retrieve the virtual address */ pTransferCompletion = (PVOID)USB_OHCD_CONVERT_FROM_BUS_MEM( uHostControllerIndex, (USB_OHCD_SWAP_DATA(uHostControllerIndex, (UINT32)pTransferCompletion))); /* Debug print */ OS_LOG_MESSAGE_LOW ( OHCD, "%d: Received Write Back Done Head interrupt, TD [0x%08X]\n", uHostControllerIndex, (UINT32) pTransferCompletion, 0, 0); /* Clear the write back done head interrupt */ USB_OHCI_REG_WRITE (uHostControllerIndex, (pOhciControllerInfo->uBaseAddress + USB_OHCI_INTERRUPT_STATUS_REGISTER_OFFSET), USB_OHCI_INTERRUPT_STATUS_DONE_HEAD); /* Call the function to process the done head interrupt */ usbOhciProcessTransferCompletion (uHostControllerIndex, pTransferCompletion); } /* * NOTE: The least significant bit of the HccaDoneHead is set to 1 * to indicate whether an unmasked HcInterruptStatus was set * when HccaDoneHead was written. * * HANDLING OF THE ABOVE INTERRUPT CONDITION IS PENDING. */ /* Check whether the SOF interrupt is pending */ if ((uInterruptStatus & USB_OHCI_INTERRUPT_STATUS_SOF) == USB_OHCI_INTERRUPT_STATUS_SOF) { /* Clear the SOF interrupt */ USB_OHCI_REG_WRITE (uHostControllerIndex, (pOhciControllerInfo->uBaseAddress + USB_OHCI_INTERRUPT_STATUS_REGISTER_OFFSET), USB_OHCI_INTERRUPT_STATUS_SOF); /* Wait for the 'endpoint list access event' before updating the * list. This event is important to prevent simultaneous updation of * the endpoint descriptor list. */ OS_WAIT_FOR_EVENT(pOhciControllerInfo->endpointListAccessEvent, OS_WAIT_INFINITE); /* * Obtain the pointer to the pipe marked for deletion or * cancellation of transfer. */ pEndpointDescriptor = pOhciControllerInfo->pDisabledEndpointListHead; /* * For all the pipes marked for deletion or cancellation of * transfer, signal the event for deletion of pipe or cancellation * of transfers. */ while (pEndpointDescriptor != NULL) { /* * Obtain the pointer to the next pipe marked for deletion * or transfer cancellation. * * NOTE: This step is very important if the ISR is run as a * task. Especially if the ISR task if of the same * priority as the other task. It might happen that * the task waiting for the pipe to be deleted is * scheduled. This task will delete the pipe. Hence, * the operation to obtain the next pipe marked for * deletion will crash. */ pOhciControllerInfo->pDisabledEndpointListHead = pEndpointDescriptor->pNextEndpointDescriptorToBeDisabled; /* * Signal the event for the deletion of the pipe or * cancellation of transfers. */ OS_RELEASE_EVENT (pEndpointDescriptor->DisableEndpointEvent); /* * Update the pointer to the next pipe marked for deletion * or transfer cancellation. */ pEndpointDescriptor = pOhciControllerInfo->pDisabledEndpointListHead; } /* End of while (NULL != pEndpointDescriptor) */ /* Release the 'endpoint list access event' before updating the * list. This event is important to prevent simultaneous updation of * the endpoint descriptor list. */ OS_RELEASE_EVENT(pOhciControllerInfo->endpointListAccessEvent); } /* End of if ((uInterruptStatus ...)) */ /* Check whether the root hub status change interrupt is pending */ if ((uInterruptStatus & USB_OHCI_INTERRUPT_STATUS_RHSC) == USB_OHCI_INTERRUPT_STATUS_RHSC) { /* Clear the root hub status change interrupt */ USB_OHCI_REG_WRITE (uHostControllerIndex, (pOhciControllerInfo->uBaseAddress + USB_OHCI_INTERRUPT_STATUS_REGISTER_OFFSET), USB_OHCI_INTERRUPT_STATUS_RHSC);#if (CPU == SH7750) /* * As long as any of the status change bits are set in the Root hub * port registers, the Root hub status change interrupt does not * get cleared only in the case of * the onboard host controller. Due to this reason, the RHSC * interrupt is generated frequently. Because of this, * the "usbOhciIsr" thread does not allow any tasks of * lower priority to be executed if the scheduling mode is a * priority based scheduling. * This is done to explicitly reschedule * other threads in the system. */ OS_RESCHEDULE_THREAD();#endif /* * Check whether the status change request is pending for * the root hub. */ if (pOhciControllerInfo->pRootHubInterruptRequest != NULL) { /* Call the function to process the root hub status change */ usbOhciProcessRootHubStatusChange (uHostControllerIndex); } } /* Check whether the resume detect interrupt is pending */ if ((uInterruptStatus & USB_OHCI_INTERRUPT_STATUS_RESUME_DETECT) == USB_OHCI_INTERRUPT_STATUS_RESUME_DETECT) { /* Clear the resume detect interrupt */ USB_OHCI_REG_WRITE (uHostControllerIndex, (pOhciControllerInfo->uBaseAddress + USB_OHCI_INTERRUPT_STATUS_REGISTER_OFFSET), USB_OHCI_INTERRUPT_STATUS_RESUME_DETECT); /* * Check whether the remote wakeup feature is enabled for * the root hub. */ if (pOhciControllerInfo->bRemoteWakeupEnabled) { /* Service the remote wakeup interrupt */ /* PENDING */ } } } /* End of if (uInterruptStatus != 0) */#ifndef USB_OHCI_POLLING_MODE /* Enable the interrupts */ USB_OHCI_REG_WRITE (uHostControllerIndex, (pOhciControllerInfo->uBaseAddress + USB_OHCI_INTERRUPT_ENABLE_REGISTER_OFFSET), USB_OHCI_INTERRUPT_MASK);#endif /* End of #ifndef USB_OHCI_POLLING_MODE */ return; } /* End of function usbOhciProcessInterrupts () *//* End of File usbOhciIsr.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -