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

📄 pdd.c

📁 Microsoft WinCE 6.0 BSP FINAL release source code for use with the i.MX27ADS TO2 WCE600_FINAL_MX27_S
💻 C
📖 第 1 页 / 共 5 页
字号:
//------------------------------------------------------------------------------
//
// Copyright (C) 2005-2006, Freescale Semiconductor, Inc. All Rights Reserved.
// THIS SOURCE CODE, AND ITS USE AND DISTRIBUTION, IS SUBJECT TO THE TERMS
// AND CONDITIONS OF THE APPLICABLE LICENSE AGREEMENT
//
//------------------------------------------------------------------------------ 
//
//  File:  pdd.c
// 
//  This file contains USB function PDD implementation. Actual implementation
//  doesn't use DMA transfers and it doesn't support ISO endpoints.
//
//#pragma optimize( "", off )
#include <windows.h>
#include <nkintr.h>
#include <pm.h>
#include <ceddk.h>
#include <cebus.h>
#include <usbfntypes.h>
#include <usbfn.h>
#include "csp.h"
#include "usbd.h"
#if 1 /*ERIC0907*/
#include <mx27_usbname.h>
#include <mx27_usbcommon.h>
#else
#include <mx31_usbname.h>
#include <mx31_usbcommon.h>
#endif

#include "celog.h"

#define USB_TIMEOUT 10000
#define IDLE_TIMEOUT 3000


#define MTP_SUPPORT

//#undef 1
//#define 1 0
//#undef DEBUGMSG
//#define DEBUGMSG(a,b) RETAILMSG(1,b)

//------------------------------------------------------------------------------
//
//  Global:  dpCurSettings
//
#ifdef DEBUG

#define ZONE_INTERRUPTS         DEBUGZONE(8)
#define ZONE_POWER              DEBUGZONE(9)
#define ZONE_PDD                DEBUGZONE(15)
#define ZONE_WARNING            DEBUGZONE(1)

extern DBGPARAM dpCurSettings = {
    L"UsbFn", {
            L"Error",       L"Warning",     L"Init",        L"Transfer",
            L"Pipe",        L"Send",        L"Receive",     L"USB Events",
            L"Interrupts",  L"Power",       L"",            L"",
            L"Function",    L"Comments",    L"",            L"PDD"
    },
    DBG_ERROR|DBG_INIT
};

#endif

CRITICAL_SECTION g_csRegister;


#define UFN_MORE_DATA       UFN_NOT_COMPLETE_ERROR

#define LOCK() EnterCriticalSection(&g_csRegister)
#define UNLOCK() LeaveCriticalSection(&g_csRegister)


extern DWORD GetDeviceRegistryParams(
                                     LPCWSTR context, VOID *pBase, DWORD count, 
                                     const DEVICE_REGISTRY_PARAM params[]
) ;
extern void SetULPIToClientMode(CSP_USB_REGS *regs);
//extern void SetPHYPowerMgmt(CSP_USB_REGS* pRegs, BOOL fSuspend);
static  BOOL SetDeviceTestMode( USBFN_PDD *pPdd, int iTestMode );

static void PrimeQh0ForZeroTransfer(USBFN_PDD *pPdd, BOOL bIN );
static void FlushEndpoint( USBFN_PDD *pPdd, DWORD epNum, BOOL bIsReceive );


#define TDVirtual(td) (PUSBD_dTD_R_T)DescriptorVirtual(pPdd,(((DWORD)td)<<5))
#define DataVirtual(bp) (UCHAR *)DescriptorVirtual(pPdd,(((DWORD)bp)<<12))

DWORD WINAPI UfnPdd_Start(VOID *pPddContext);
DWORD WINAPI UfnPdd_IssueTransfer(
                                  VOID *pPddContext, DWORD endPoint, STransfer *pTransfer
                                  );
static void 
memdump(unsigned char * data,   unsigned short num_bytes, unsigned short offset    );

PHYSICAL_ADDRESS phyAddr_TD1;
PHYSICAL_ADDRESS phyAddr_TD2;

PVOID Buffer_Td1;
PVOID Buffer_Td2;

DMA_ADAPTER_OBJECT Adapter1;
DMA_ADAPTER_OBJECT Adapter2;

//------------------------------------------------------------------------------
//  Device registry parameters

static const DEVICE_REGISTRY_PARAM g_deviceRegParams[] = {
        {
        L"MemBase", PARAM_DWORD, TRUE, offset(USBFN_PDD, memBase),
            fieldsize(USBFN_PDD, memBase), NULL
        }, { 
        L"MemLen", PARAM_DWORD, TRUE, offset(USBFN_PDD, memLen),
            fieldsize(USBFN_PDD, memLen), NULL
        }, { 
        L"Irq", PARAM_DWORD, TRUE, offset(USBFN_PDD, irq),
            fieldsize(USBFN_PDD, irq), NULL
        }, { 
            L"Priority256", PARAM_DWORD, FALSE, offset(USBFN_PDD, priority256),
                fieldsize(USBFN_PDD, priority256), (void *)100
        }, { 
            L"OTGSupport", PARAM_DWORD, FALSE, offset(USBFN_PDD, IsOTGSupport),
                fieldsize(USBFN_PDD, IsOTGSupport), (void *)0
        }, {
            L"OTGGroup", PARAM_STRING, TRUE, offset(USBFN_PDD, szOTGGroup),
                fieldsize(USBFN_PDD, szOTGGroup), NULL
        }

};

//------------------------------------------------------------------------------
//
//  Function:  Log2
//
//  Trivial log with base 2 function used in EP configuration.
//
static DWORD Log2(DWORD value)
{
    DWORD rc = 0;
    while (value != 0)
    {
        value >>= 1;
        rc++;
    }
    if (rc > 0)
        rc--;

    return rc;
}

//-------------------------------------------------------------
// 
//  Function: DescriptorPhy
//
//  This function is to calculate the descriptor in physical address
//
//  Parameters:
//       pPdd - Pointer to the USBFN_PDD structure
//       vaddr - virtual address of the descriptor
//
//  Return:
//       Physical address of descriptor
//
//--------------------------------------------------------------
DWORD DescriptorPhy(USBFN_PDD *pPdd, DWORD vaddr)
{
    DWORD r=vaddr-(DWORD)(pPdd->qhbuffer)+pPdd->qhbuf_phy;
    return r;
}

//-------------------------------------------------------------
// 
//  Function: DescriptorVirtual
//
//  This function is to calculate the descriptor in virtual address
//
//  Parameters:
//       pPdd - Pointer to the USBFN_PDD structure
//       paddr - physical address of the descriptor
//
//  Return:
//       Virtual address of descriptor
//
//--------------------------------------------------------------
DWORD DescriptorVirtual(USBFN_PDD *pPdd, DWORD paddr)
{
    DWORD r=paddr-pPdd->qhbuf_phy+(DWORD)(pPdd->qhbuffer);
    return r;
}

//-------------------------------------------------------------
// 
//  Function: GetSetupPacket
//
//  This function is to retrieve the setup packet data 
//
//  Parameters:
//       [IN]  pPdd - Pointer to structure USBFN_PDD
//       [OUT] data - Pointer to an array of DWORD 
//
//  Return:
//       The setup packet would be copied to parameter "data"
//
//--------------------------------------------------------------

static GetSetupPacket(USBFN_PDD *pPdd, PDWORD data)
{
    USB_USBCMD_T cmd;
    DWORD *temp=(DWORD *)&cmd;
    *temp=0;
    
    // indicate we've read out this setup
    OUTREG32(&pPdd->pUSBDRegs->OTG.ENDPTSETUPSTAT, 1);

    while (1)
    {

       // RETAILMSG(1, (TEXT("Setup packet\r\n")));
        // Write '1' to Setup Tripwire (SUTW) in USBCMD register.
        *temp=INREG32(&pPdd->pUSBDRegs->OTG.USBCMD);    
        cmd.SUTW=1;
        OUTREG32(&pPdd->pUSBDRegs->OTG.USBCMD, *temp);    
        
        //Duplicate contents of dQH.SetupBuffer into local software byte array.
        data[0] = (DWORD)pPdd->qhbuffer->qh[0].SB0;
        data[1] = (DWORD)pPdd->qhbuffer->qh[0].SB1;

        pPdd->qhbuffer->qh[0].SB0=0;
        pPdd->qhbuffer->qh[0].SB1=0;

        DEBUGMSG(1, (TEXT("GetSetupPacket %8.8lx%8.8lx\r\n"),data[0],data[1] ));

        *temp=INREG32(&pPdd->pUSBDRegs->OTG.USBCMD);    
        
        // check whether a new setup was received while we were retrieving the setup,
        // and retrieve again if so.
        if (cmd.SUTW)    
            break;    
    }
    *temp=0; cmd.SUTW=1;
    CLRREG32(&pPdd->pUSBDRegs->OTG.USBCMD, *temp);    
    //
    
    // doc claims ENDPTCOMPLETE is set both for Setup and OUT transactions, so it can be normal
    // to have to clear complete now.
    if (INREG32(&(pPdd->pUSBDRegs->OTG.ENDPTCOMPLETE)) & 0x1)
    {
            OUTREG32(&(pPdd->pUSBDRegs->OTG.ENDPTCOMPLETE), 1);    
    }
    
    if ( pPdd->ep[0]->pTransfer )
    {
        DEBUGMSG(1, 
                (TEXT("####### GetSetupPacket: Transfer was in progress on EP0 (EPSTAT 0x%x, status 0x%x)\r\n"),
            INREG32(&(pPdd->pUSBDRegs->OTG.ENDPTSTATUS)),
            pPdd->qhbuffer->qh[0].dtd.status
            ) );
        
        // that transfer should be aborted.  If EPSTAT was set then it needs also to be flushed
    }
    
    if ( INREG32(&(pPdd->pUSBDRegs->OTG.ENDPTSTATUS)) & 0x1)
    {        
        DEBUGMSG(1, (TEXT("####### GetSetupPacket: Flushing EP 0 (EPSTATUS 0x%x, QH0:0x%x)\r\n"),
            INREG32(&(pPdd->pUSBDRegs->OTG.ENDPTSTATUS)),
            pPdd->qhbuffer->qh[0].dtd.status) );
        
        OUTREG32(&pPdd->pUSBDRegs->OTG.ENDPTFLUSH,1);
        /*
        Software note: this operation may take a large amount of time depending on the USB bus
        activity. It is not desirable to have this wait loop within an interrupt service routine.
        *
        * This flush should not normally happen.  Setup only comes while an endpoint is primed, under
        * protocol failure conditions.  Otherwise OUT and IN always complete normally since it is the
        * host which sends SETUP and host which drives the IN/OUT protocol on the control ep.
        */
        
        while (1)
        {
            if ( (INREG32(&pPdd->pUSBDRegs->OTG.ENDPTFLUSH) & 1) == 0 )
                break;
        }
    }
    
}

//-------------------------------------------------------------
// 
//  Function: InitQh0
//
//  This is used to initialise for EP0, where many transactions are set-up transactions.
//  Where actual data is required, this QH is initialised instead through the normal IssueTransfer method.
//
//  Parameters: 
//      pPdd - Pointer to USBFN_PDD
//      len - no of bytes to transfer
//      pTransfer - Pointer to STransfer
//
//  Return: NULL
//
//------------------------------------------------------------------
static void 
InitQh0(USBFN_PDD *pPdd, DWORD len, STransfer *pTransfer)
{
    volatile CSP_USB_REG * pOtgReg=&(pPdd->pUSBDRegs->OTG);
    int retry = 0;

    LOCK();

    pPdd->ep[0]->pTransfer = NULL;
    pPdd->ep[0]->pMappedBufPtr = 0;
    pPdd->ep[0]->dwNextPageIdx = 0;
    pPdd->ep[0]->dwNumPages = 0;
    pPdd->ep[0]->bPagesLocked = FALSE;

    pPdd->ep[USBD_EP_COUNT-1]->pTransfer = NULL;
    pPdd->ep[USBD_EP_COUNT-1]->pMappedBufPtr = 0;
    pPdd->ep[USBD_EP_COUNT-1]->dwNextPageIdx = 0;
    pPdd->ep[USBD_EP_COUNT-1]->dwNumPages = 0;
    pPdd->ep[USBD_EP_COUNT-1]->bPagesLocked = FALSE;

    memset(&pPdd->qhbuffer->qh[0], 0, sizeof(USBD_dQH_T));
    memset(&pPdd->qhbuffer->qh[1], 0, sizeof(USBD_dQH_T));
    memset(&pPdd->qhbuffer->td[0], 0, sizeof(USBD_dTD_R_T));
    memset(&pPdd->qhbuffer->td[1], 0, sizeof(USBD_dTD_R_T));
    pPdd->qhbuffer->bPrimed[0] = FALSE;
    pPdd->qhbuffer->bPrimed[USBD_EP_COUNT-1] = FALSE;


    DEBUGMSG(1,(L"Initqh0, %x", pPdd->qhbuffer->qh[0].dtd.status));
again:        
    if ((pPdd->qhbuffer->qh[0].SB0||pPdd->qhbuffer->qh[0].SB1) && (retry))
    {
        DWORD data[2];

        DEBUGMSG(ZONE_WARNING,(_T("Setup not processed (SETUPSTAT=0x%x)??? %x, %x\r\n"), 
                    INREG32(&pOtgReg->ENDPTSETUPSTAT),
                    pPdd->qhbuffer->qh[0].SB0, pPdd->qhbuffer->qh[0].SB1));

        GetSetupPacket(pPdd, data);

        //OUTREG32(&pOtgReg->ENDPTSETUPSTAT, INREG32(&pOtgReg->ENDPTSETUPSTAT));
        DEBUGMSG(ZONE_WARNING,(L"New setup received when priming=%x, %x\r\n", data[0], data[1]));

        DEBUGCHK ( pPdd->ep[0]->bPagesLocked == 0 );

        UNLOCK();
        pPdd->pfnNotify(pPdd->pMddContext, UFN_MSG_SETUP_PACKET, (DWORD)data);
        LOCK();
    }

    memset(&(pPdd->qhbuffer->qh[0]),0, sizeof(USBD_dQH_T));
    pPdd->qhbuffer->bPrimed[0] = FALSE;

    // Endpoint 0 
    pPdd->qhbuffer->qh[0].ios=1;
    pPdd->qhbuffer->qh[0].mpl=USB_FULL_HIGH_SPEED_CONTROL_MAX_PACKET_SIZE;    
    pPdd->qhbuffer->qh[0].zlt=1;
    //overlayer  default
    {
        DWORD t;
        t=DescriptorPhy(pPdd, (DWORD)&(pPdd->qhbuffer->td[0]));
        t>>=5;
        pPdd->qhbuffer->qh[0].dtd.next_dtd=t;
    }

    OUTREG32(&pOtgReg->ENDPTSETUPSTAT, 0xffff);

    memset (&(pPdd->qhbuffer->td[0]), 0, sizeof(USBD_dTD_T));
    pPdd->qhbuffer->td[0].T=1;
    pPdd->qhbuffer->td[0].next_dtd=0xDEAD;
    pPdd->qhbuffer->td[0].status=0x80;            // Active
    pPdd->qhbuffer->td[0].ioc=1;
    pPdd->qhbuffer->td[0].tb=len; 


    OUTREG32(&pOtgReg->ENDPTPRIME, 0x1);  // prime Out transition
    while(INREG32(&pOtgReg->ENDPTPRIME) & 0x1)
    {
        ;
    }

    if ((INREG32(&pOtgReg->ENDPTSTATUS)&1)==0)
    {
        DWORD data[2];

⌨️ 快捷键说明

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