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

📄 usbohciisr.c

📁 风河的vxworks-6.3 FOR amcc440epx BSP!
💻 C
📖 第 1 页 / 共 2 页
字号:
    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 + -