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

📄 pdd.c

📁 freescale i.mx31 BSP CE5.0全部源码
💻 C
📖 第 1 页 / 共 5 页
字号:
                    {
                        CheckEndpoint(pPdd, i );
                    }                
                }
            } while (INREG32(&pUSBDRegs->OTG.ENDPTSETUPSTAT) ||INREG32(&pUSBDRegs->OTG.ENDPTCOMPLETE));
        }
    }

    while (!pPdd->exitIntrThread)
    {
        DWORD dwErr = 0; 

        if (pPdd->IsOTGSupport)
            timeout = INFINITE;

        // Wait for interrupt from USB controller
        dwErr = WaitForSingleObject(pPdd->hIntrEvent, timeout); 
        if (dwErr == WAIT_TIMEOUT)
        {
            // Now I am ready to put the transceiver into suspend mode.
            // But be aware there is a device attach when boot up            
            USB_CTRL_T ctrl;
            DWORD *temp3;
            USB_PORTSC_T portsc;
            DWORD *temp = (DWORD *)&portsc;
            
            *temp = INREG32(&(pUSBDRegs)->OTG.PORTSC);
            if ((portsc.SUSP == 0) && (pPdd->devState == 1))
            {
                // there is a device attached, don't do anything
                timeout = INFINITE;
                continue;             
            }

            // If there is a device attached at this time
            // Handling of device attach
            // Even though it is pure client, still, we have no other way to isolate the 
            // host from the device, we need to use ID pin to detect.
            if (portsc.SUSP == 0)
            {
                USB_OTGSC_T otgsc;          
                DWORD *temp4 = (DWORD *)&otgsc;
                
                *temp4 = INREG32(&(pUSBDRegs)->OTG.OTGSC);
                timeout = IDLE_TIMEOUT;
                if (otgsc.ID != 0)
                {
                    DEBUGMSG(1, (TEXT("Port is not suspend and no A-device is detected\r\n")));
                    LOCK();
                    USBControllerRun(pUSBDRegs, FALSE);
                    HardwareInitialize(pUSBDRegs);
                    UfnPdd_Start(pPdd);
                    USBControllerRun(pUSBDRegs, TRUE);
                    UNLOCK();                    
                    goto PROCESS_INTERRUPT;
                }
            }


            // Now the device is not attached
            // Check and make sure all wakeup interrupt are enabled
            temp3 = (DWORD *)&ctrl;
            *temp3 = INREG32(&pUSBDRegs->USB_CTRL);
            ctrl.OWIE = 1;
            ctrl.OUIE = 1;
            OUTREG32(&pUSBDRegs->USB_CTRL, *temp3);
            
            // stop the controller before accessing the ULPI
            LOCK();
            USBControllerRun(pUSBDRegs, FALSE);

            // May need to set ULPI here
            // It is not waking up now ...must be something wrong
            *temp = INREG32(&(pUSBDRegs)->OTG.PORTSC);
            if (portsc.PHCD == 0)
                SetULPIToClientMode(pUSBDRegs);
            
            portsc.PHCD = 1;
            OUTREG32(&(pUSBDRegs)->OTG.PORTSC, *temp);

            //DEBUGMSG(1, (TEXT("Lower core voltage now with portsc(0x%x) usbctrl(0x%x)\r\n"), INREG32(&(pUSBDRegs)->OTG.PORTSC), INREG32(&pUSBDRegs->USB_CTRL)));
            {
                BOOL bTemp;

                if (pPdd->bUSBPanicMode == TRUE)
                {
                    bTemp = DDKClockDisablePanicMode();
                    //RETAILMSG(1, (TEXT("DDKClockDisablePanicMode = 0x%x\r\n"), bTemp));
                    pPdd->bUSBPanicMode = FALSE;
                }
            }
            
            if (pPdd->bUSBCoreClk == TRUE)
            {
                pPdd->bUSBCoreClk = FALSE;
                USBClockDisable(TRUE);
            }
            UNLOCK();
            // Now we can stop the USB clock
            DEBUGMSG(1, (TEXT("PDD - SUSPEND\r\n")));
            timeout = INFINITE;
            continue;
        }
        
PROCESS_INTERRUPT:
        LOCK();
        if (pPdd->bUSBCoreClk == FALSE)
        {
            USBClockDisable(FALSE);
            pPdd->bUSBCoreClk = TRUE;
        }

        if (pPdd->bUSBPanicMode == FALSE)
        {
            DDKClockEnablePanicMode();
            pPdd->bUSBPanicMode = TRUE;
            DEBUGMSG(1, (TEXT("DDKClockEnablePanicMode\r\n")));                
            DEBUGMSG(1, (TEXT("WakeUp - PORTSC: 0x%x\r\n"), INREG32(&pUSBDRegs->OTG.PORTSC[0])));
        }

        if (INREG32(&pUSBDRegs->OTG.PORTSC[0]) & 0x800000)
        {
            // Clear the PHCD
            CLRREG32(&pUSBDRegs->OTG.PORTSC[0], INREG32(&pUSBDRegs->OTG.PORTSC[0]) & 0x800000);
            // Force Resume bit
            OUTREG32(&pUSBDRegs->OTG.PORTSC[0], INREG32(&pUSBDRegs->OTG.PORTSC[0])|0x40); 
            DEBUGMSG(1, (TEXT("Force resume\r\n")));
        }
        UNLOCK();        

        InterruptDone(pPdd->sysIntr);  

        CeLogMsg(_T("Intr:Signalled"));

        {
            USB_CTRL_T ctrl;
            temp = (DWORD *)&ctrl;
            *temp = INREG32(&pUSBDRegs->USB_CTRL);

            if (ctrl.OWIR == 1)
            {
                *temp = 0;
                ctrl.OWIE = 1;
                CLRREG32(&pUSBDRegs->USB_CTRL, *temp);
                // We move to here since only when we have wakeup should we
                // set the Run bit of USB Controller again.
                USBControllerRun(pUSBDRegs, TRUE);
            }
        }
        // Exit thread when we are asked so...
        if (pPdd->exitIntrThread)
        {
            break;
        }

        if ( pPdd->bEnterTestMode )
        {
            LOCK();
            SetDeviceTestMode( pPdd, pPdd->iTestMode );

            /* clear whatever interrupt there was */
            temp=(DWORD *)&source;
            *temp = INREG32(&pUSBDRegs->OTG.USBSTS);


            // Clear source bits
            OUTREG32(&pUSBDRegs->OTG.USBSTS, *temp);
              

            /* 
             * when device is in test mode, there is no longer any more normal operation and
             * we could just busy-stall here, since exit from the mode is via power-off.
             */
            pPdd->exitIntrThread = TRUE;
            UNLOCK();
            break;
        }

        if (pPdd->m_CurSelfPowerState == D3 || pPdd->m_CurSelfPowerState == D4) 
        {
            pPdd->m_CurSelfPowerState = D2;
            UpdateDevicePower(pPdd);
        }
        

        temp=(DWORD *)&source;
        // Get interrupt source        
        *temp = INREG32(&pUSBDRegs->OTG.USBSTS);        
       
        do
        {
            
            // Clear the reg
            OUTREG32(&pUSBDRegs->OTG.USBSTS, *temp);
            
            if (source.URI)
            {
                HandleUSBReset(pPdd);
            }

            if (source.SLI) 
            {
                CeLogMsg(_T("Intr:SLI"));                
                LOCK();
                DevStatEvent(pPdd); // Handle device state change                
                if ((pPdd->devState == 0) && (pPdd->IsOTGSupport == 0))
                    timeout = IDLE_TIMEOUT;
                UNLOCK();
            }

            // USB Interrupt
            if (source.UI)
            {
                CeLogMsg(_T("Intr:UI SETUPSTAT %x ENDPTCOMP %x"),
                        INREG32(&pUSBDRegs->OTG.ENDPTSETUPSTAT),
                        INREG32(&pUSBDRegs->OTG.ENDPTCOMPLETE) );

                while (INREG32(&pUSBDRegs->OTG.ENDPTSETUPSTAT) || INREG32(&pUSBDRegs->OTG.ENDPTCOMPLETE))
                {
                    if (INREG32(&pUSBDRegs->OTG.ENDPTSETUPSTAT)) 
                        SetupEvent(pPdd);  // locks internally, and checks setupstat internally

                    if (INREG32(&pUSBDRegs->OTG.ENDPTCOMPLETE))
                    {
                        for (i=0;i<USBD_EP_COUNT;i++)
                        {
                            // check endpoint sees if endptcomplete bit is set for individual endpoint i
                            CheckEndpoint(pPdd, i );  // locks internally, and checks regs internally
                            // and clears the endptcomplete bit for that endpoint
                        }
                    }
                }
            }


            *temp = INREG32(&pUSBDRegs->OTG.USBSTS);
 
            if ((*temp & 0xffffff6f)==0)
            {
                CeLogMsg(_T("Intr:Done"));
                //CheckForEventLost(pPdd,k);                

                break;
            }

        }  while (1);    

        if (pPdd->bResume)
        {
            CeLogMsg(_T("Resume"));
            
            //RETAILMSG(1, (TEXT("+UFN_DETACH called\r\n")));
            pPdd->pfnNotify(pPdd->pMddContext, UFN_MSG_BUS_EVENTS, UFN_DETACH);        
            //RETAILMSG(1, (TEXT("-UFN_DETACH called\r\n")));
            
            LOCK();
            // Don't process other changes (we are disconnected)
            pPdd->devState=0;

            pPdd->bResume = FALSE;


            // SetSelfPowerState to D4
            pPdd->m_CurSelfPowerState = D4; // Do we need set to D3 as wake up source?
            UpdateDevicePower(pPdd);     

            OUTREG32(&pPdd->pUSBDRegs->OTG.T_154H.USBADR, 0);    

            UNLOCK();

            if (pPdd->IsOTGSupport)
            {
                InterruptDisable(pPdd->sysIntr);
                // wait for client function class and make sure everything is disconnected
                // this is not a very good design but since we need to make sure we can get proper
                // disconnect before we switch back to XVR, we have to do that especially on Active Sync.
                //RETAILMSG(1, (TEXT("Leave Client back to XVR mode\r\n")));
                Sleep(500);
                SetEvent(hXcvr);
                goto XCVR_SIG;
            }
        }

        // Handle detach condition for OTG
        LOCK();
        if (pPdd->IsOTGSupport && pPdd->devState == 0)
        {
            USB_PORTSC_T state;
            USB_OTGSC_T otgsc;          
            DWORD *temp2;
            DWORD *temp3;

            temp2 = (DWORD *)&state;
            *temp2 = INREG32(&pUSBDRegs->OTG.PORTSC[0]);

            temp3 = (DWORD *)&otgsc;
            *temp3 = INREG32(&pUSBDRegs->OTG.OTGSC);

            CeLogMsg(_T("Detach: PORTSC 0x%x"), *temp2);

            if ((state.SUSP == 1) || (otgsc.ID == 0))
            {
                DEBUGMSG(1, (TEXT("Device Detach, with susp(%d), id(%d)\r\n"), state.SUSP, otgsc.ID));
                if (otgsc.IDIS)
                {
                    // clear the register. since other is not used, we can simply 
                    // use the SETREG32 instead of OUTREG32
                    *temp3 = 0;
                    otgsc.IDIS = 1;                 
                    SETREG32(&pUSBDRegs->OTG.OTGSC, *temp3);
                }
                UNLOCK();
                InterruptDisable(pPdd->sysIntr);
                SetEvent(hXcvr);
                goto XCVR_SIG;
            }
        }

        if ((pPdd->IsOTGSupport == 0) && (pPdd->devState == 0))
            timeout = IDLE_TIMEOUT;

        UNLOCK();
    }

    if (pPdd->bEnterTestMode)
    {
        RETAILMSG(1, (TEXT("USBOTG Client Test Mode set and loop forever\r\n")));
        pPdd->bEnterTestMode = FALSE;
        while(1);
    }

    return ERROR_SUCCESS;
}


//-----------------------------------------------------------------
//
//  Function: BuildTdBufferList
//  
//  Given a mapped endpoint and a TransferDescriptor and a length of data to put into it,
//  build the list of buffer pointers from previously locked page data (including current page).
//  ep is current endpoint, pTd points to the TD being built in uncached mem
//
//  Parameter: 
//
//      [IN] ep - endpoint to be processed
//      [IN] pTd - pointer to transfer descriptor
//      [IN] len - transfer length
//
//  Return:
//
//      NULL
//
//-------------------------------------------------------------------
static void BuildTdBufferList( USBFN_EP *ep, PUSBD_dTD_R_T pTd, DWORD len )
{
    DWORD dwOffset;
    DWORD dwPageIdx;

    if ( len > 0 )
    {
        dwPageIdx = ep->dwNextPageIdx;
        DEBUGCHK( dwPageIdx < ep->dwNumPages );


        pTd->bp0 = (ep->pdwPageList[dwPageIdx++] << UserKInfo[KINX_PFN_SHIFT]) >> 12;

        // get current buffer pointer's offset into first page
        pTd->curr_off = dwOffset = ((DWORD)ep->pMappedBufPtr) & (UserKInfo[KINX_PAGESIZE] - 1);  

        /* the first buffer page will contain either one MAX_SIZE_PER_BP or less (if there was an offset) */
        if ( len > (MAX_SIZE_PER_BP - dwOffset) )
            len -= (MAX_SIZE_PER_BP - dwOffset);   
        else
            len = 0;   // first bp contains all the data 

        // continue to buffer page 1
        if ( len > 0 )
        {
            DEBUGCHK( dwPageIdx < ep->dwNumPages );

            pTd->bp1 = (ep->pdwPageList[dwPageIdx++] << UserKInfo[KINX_PFN_SHIFT])>>12;

            // each of the following pages will start at offset 0 
            if ( len > MAX_SIZE_PER_BP )
                len -= MAX_SIZE_PER_BP;
            else
                len = 0;

            // continue to buffer page 2
            if ( len > 0 )
            {
                DEBUGCHK( dwPage

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -