📄 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 + -