📄 pdd.c
字号:
//------------------------------------------------------------------------------
//
// 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 + -