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

📄 pxa255_ufnpdd.cpp

📁 老外的一个开源项目
💻 CPP
📖 第 1 页 / 共 5 页
字号:
// Copyright (c) David Vescovi.  All rights reserved.
// Part of Project DrumStix
// Windows Embedded Developers Interest Group (WE-DIG) community project.
// http://www.we-dig.org
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*++

THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.

Module Name: 

pxa255_ufnpdd.CPP

Abstract:

pxa255 (XScale) CPU USB Function Platform-Dependent Driver.

--*/

#include <windows.h>
#include <ceddk.h>
#include <nkintr.h>
#include <devload.h>
#include <usbfn.h>
#include <ddkreg.h>
#include "bsp.h"

#ifndef SHIP_BUILD
#define STR_MODULE _T("UsbFnPdd!")
#define SETFNAME() LPCTSTR pszFname = STR_MODULE _T(__FUNCTION__) _T(":")
#else
#define SETFNAME()
#endif

#define ZONE_POWER           DEBUGZONE(8)

UFN_GENERATE_DPCURSETTINGS(UFN_DEFAULT_DPCURSETTINGS_NAME, 
    _T("Power"), _T(""), _T(""), _T(""), 
    DBG_ERROR | DBG_INIT);
//    DBG_USB_EVENTS | DBG_ERROR | DBG_INIT);


#define UDC_REG_PRIORITY_VAL    _T("Priority256")
#define UDC_DEFAULT_PRIORITY    100


typedef struct EP_STATUS {
	DWORD                   dwEndPointNumber;
	DWORD                   dwTypeSupported;
	DWORD                   dwDirectionSupported;
	DWORD                   dwPacketSizeSupported;
	BOOL                    fInitialized;
	BOOL                    fZeroPacketNeeded;
	BOOL                    fInIST;
	PSTransfer              pTransfer;
	volatile ULONG         *lpulUDCCSx;
	volatile ULONG         *lpulUDDRx;
	volatile ULONG         *lpulUBCRx;
	CRITICAL_SECTION        cs;
} *PEP_STATUS;

#define LOCK_ENDPOINT(peps)     EnterCriticalSection(&peps->cs)
#define UNLOCK_ENDPOINT(peps)   LeaveCriticalSection(&peps->cs)


// endpoint packet sizes
#define EP0_PACKET_SIZE     16
#define EP1_PACKET_SIZE     64
#define EP2_PACKET_SIZE     64
#define EP3_PACKET_SIZE     256
#define EP4_PACKET_SIZE     256
#define EP5_PACKET_SIZE     8
#define EP6_PACKET_SIZE     64
#define EP7_PACKET_SIZE     64
#define EP8_PACKET_SIZE     256
#define EP9_PACKET_SIZE     256
#define EPA_PACKET_SIZE     8
#define EPB_PACKET_SIZE     64
#define EPC_PACKET_SIZE     64
#define EPD_PACKET_SIZE     256
#define EPE_PACKET_SIZE     256
#define EPF_PACKET_SIZE     8


static EP_STATUS  g_rgEpStatus[]  = {
	{
		0,							// End Point Number
		USB_ENDPOINT_TYPE_CONTROL,	// type supported
		0,							// direction supported
		EP0_PACKET_SIZE,			// packet size supported (16 bytes)
	},
	{
		1,							// End Point Number
		USB_ENDPOINT_TYPE_BULK,		// BULK           
		USB_IN_TRANSFER,			// IN
		EP1_PACKET_SIZE,			// packet size supported (64 bytes)
	},
	{
		2,							// End Point Number
		USB_ENDPOINT_TYPE_BULK,		// BULK
		USB_OUT_TRANSFER,			// OUT
		EP2_PACKET_SIZE,			// packet size supported (64 bytes)
	},
	{
		3,							// End Point Number
		USB_ENDPOINT_TYPE_ISOCHRONOUS,	// ISOCHRONOUS
		USB_IN_TRANSFER,			// IN
		EP3_PACKET_SIZE,			// packet size supported (256 bytes)
	},
	{
		4,							// End Point Number
		USB_ENDPOINT_TYPE_ISOCHRONOUS,	// ISOCHRONOUS
		USB_OUT_TRANSFER,			// OUT
		EP4_PACKET_SIZE,			// packet size supported (256 bytes)
	},
	{
		5,							// End Point Number
		USB_ENDPOINT_TYPE_INTERRUPT,// INTERRUPT
		USB_IN_TRANSFER,			// IN
		EP5_PACKET_SIZE,			// packet size supported (8 bytes)
	},
	{
		6,							// End Point Number
		USB_ENDPOINT_TYPE_BULK,		// BULK			
		USB_IN_TRANSFER,			// IN
		EP6_PACKET_SIZE,			// packet size supported (64 bytes)
	},
	{
		7,							// End Point Number
		USB_ENDPOINT_TYPE_BULK,		// BULK
		USB_OUT_TRANSFER,			// OUT
		EP7_PACKET_SIZE,			// packet size supported (64 bytes)
	},
	{
		8,							// End Point Number
		USB_ENDPOINT_TYPE_ISOCHRONOUS,	// ISOCHRONOUS
		USB_IN_TRANSFER,			// IN
		EP8_PACKET_SIZE,			// packet size supported (256 bytes)
	},
	{
		9,							// End Point Number
		USB_ENDPOINT_TYPE_ISOCHRONOUS,	// ISOCHRONOUS
		USB_OUT_TRANSFER,			// OUT
		EP9_PACKET_SIZE,			// packet size supported (256 bytes)
	},
	{
		0xA,						// End Point Number
		USB_ENDPOINT_TYPE_INTERRUPT,// INTERRUPT
		USB_IN_TRANSFER,			// IN
		EPA_PACKET_SIZE,			// packet size supported (8	bytes)
	},
	{
		0xB,						// End Point Number
		USB_ENDPOINT_TYPE_BULK,		// BULK			
		USB_IN_TRANSFER,			// IN
		EPB_PACKET_SIZE,			// packet size supported (64 bytes)
	},
	{
		0xC,						// End Point Number
		USB_ENDPOINT_TYPE_BULK,		// BULK
		USB_OUT_TRANSFER,			// OUT
		EPC_PACKET_SIZE,			// packet size supported (64 bytes)
	},
	{
		0xD,						// End Point Number
		USB_ENDPOINT_TYPE_ISOCHRONOUS,	// ISOCHRONOUS
		USB_IN_TRANSFER,			// IN
		EPD_PACKET_SIZE,			// packet size supported (256 bytes)
	},
	{
		0xE,						// End Point Number
		USB_ENDPOINT_TYPE_ISOCHRONOUS,	// ISOCHRONOUS
		USB_OUT_TRANSFER,			// OUT
		EPE_PACKET_SIZE,			// packet size supported (256 bytes)
	},
	{
		0xF,						// End Point Number
		USB_ENDPOINT_TYPE_INTERRUPT,// INTERRUPT
		USB_IN_TRANSFER,			// IN
		EPF_PACKET_SIZE,			// packet size supported (8	bytes)
	}
};


#define ENDPOINT_COUNT  dim(g_rgEpStatus)
#define EP_VALID(x)     ((x) < ENDPOINT_COUNT)


typedef	enum {
	EP0Setup = 0,
	EP0Out,
	EP0In
} EP0_DIR;

typedef	struct EP0_REQUEST {
	EP0_DIR	eDir;
	BOOL fCompleted;
	DWORD dwExpectedSize;
	BOOL fBackupNext;
	USB_DEVICE_REQUEST udr;
	
} *PEP0_REQUEST;


typedef	struct CTRLR_PDD_CONTEXT {
	PVOID			  pvMddContext;
	DWORD			  dwSig;
	HANDLE			  hIST;
	HANDLE			  hevInterrupt;
	DWORD			  dwISTPriority;
	BOOL			  fRunning;
	BOOL			  fSpeedReported;
	CRITICAL_SECTION  csIsrCtrlAccess;
	BOOL			  attachedState;
	DWORD			  numInPacketsSent;
	PFN_UFN_MDD_NOTIFY pfnNotify;
	HANDLE			  hBusAccess;
	CEDEVICE_POWER_STATE cpsCurrent;

	EP0_REQUEST		  ep0Request;

	// Registry
	DWORD			  dwIOBase;
	DWORD			  dwIOLen;
	DWORD			  dwIrq;
	DWORD			  dwSysIntr;

	BOOL			  fEndpoint0AckNeeded;
	BOOL			  fExitIST;
	BOOL			  fRestartIST;
	BOOL			  fIgnoreReset;

	WORD			  wConfigurationValue;
	
	EP_STATUS		  rgEpStatus[ENDPOINT_COUNT];
} *PCTRLR_PDD_CONTEXT;

#define XSC1_SIG 'XSC1' // "XScale" signature

// determine whether the target endpoint can support OUT transfers
#define EP_OUT_CAPABLE(x)   ((x == 0) || (x == 2) || (x == 4) || (x == 7) || (x == 9) || (x == 12) || (x == 14))

// determine whether the target endpoint can support IN transfers
#define EP_IN_CAPABLE(x)    (( ! EP_OUT_CAPABLE(x) ) || (x == 0))


// Create Generic USB UDC In Endpoint  Control/Status Register (UDCCS) by
// Mapping to UDCCS1 bit definitions. All other "In" regs follow the same bit definition.
#define USB_UDCCS_TFS USB_UDCCS1_TFS // Tx FIFO has room for at least one packet
#define USB_UDCCS_TPC USB_UDCCS1_TPC // Packet sent and err/status bits valid
#define USB_UDCCS_FTF USB_UDCCS0_FTF // Flush the Tx FIFO
#define USB_UDCCS_TUR USB_UDCCS1_TUR // Tx FIFO experienced underrun
#define USB_UDCCS_SST USB_UDCCS1_SST // Write 1 to clear.  Stall was sent
#define USB_UDCCS_FST USB_UDCCS1_FST // Issue stall handshake
#define USB_UDCCS_TSP USB_UDCCS1_TSP // Short packet ready for transmission

// Create Generic USB UDC Out Endpoint  Control/Status Register (UDCCS) by
// Mapping to UDCCS2 bit definitions. All other "Out" regs follow the same bit definition.
#define USB_UDCCS_RFS  USB_UDCCS2_RFS  // Rx FIFO has 1 or more packets
#define USB_UDCCS_RPC  USB_UDCCS2_RPC  // Rx packet received and err/stats valid
#define USB_UDCCS_DME  USB_UDCCS2_DME  // DMA Enable
#define USB_UDCCS_RNE  USB_UDCCS2_RNE  // Receive FIFO is not empty
#define USB_UDCCS_RSP  USB_UDCCS2_RSP  // Short packet ready for reading

// Create Generic Mapping to Receive Registers
#define USB_UDCCS_ROF  USB_UDCCS4_ROF  // Receieve Overflow


#define DISABLE_INTRS_0TO7  0xFF  // Disable Interrupts 0 - 7
#define DISABLE_INTRS_8TO15 0xFF  // Disable Interrupts 8 - 15
#define CLEAR_INTRS_0TO7    0xFF  // Disable Interrupts 0 - 7
#define CLEAR_INTRS_8TO15   0xFF  // Disable Interrupts 8 - 15

// Mapping of ARM USB UDC Registers to User Space
volatile UDC_REG_T	*g_pUDCRegs		= NULL;
volatile GPIO_REG_T *g_pGPIORegs	= NULL;
volatile CLK_REG_T  *g_pCLKRegs		= NULL;

#define IN_TRANSFER     1
#define OUT_TRANSFER    2

#ifdef DEBUG

// Validate the Xscale context.
static
VOID
ValidateContext(
                PCTRLR_PDD_CONTEXT pContext
                )
{
    PREFAST_DEBUGCHK(pContext);
    DEBUGCHK(!pContext->hevInterrupt || pContext->hIST);
    DEBUGCHK(pContext->pfnNotify);
}

#else
#define ValidateContext(ptr)
#endif


// Cable attach/detach
static
void
HWCableAttach(BOOL AttachIt)
{
PHYSETAdrInfo phySET;

	if (AttachIt)
	{
		DEBUGMSG(ZONE_INIT, (TEXT("Gum::Cable ATTACH! \r\n")));
		g_pGPIORegs->GPSR1 = GPIO_41_USB_CONTROL;
		phySET.subcode = PHY_SET_ADDR;		// atomic operation
		phySET.address = PXA255_BASE_REG_PA_GPIO + offsetof(GPIO_REG_T,GPDR1);
		phySET.mask = GPIO_41_USB_CONTROL;
		phySET.value = GPIO_41_USB_CONTROL;	// set it
		KernelIoControl(IOCTL_HAL_PHYADR, &phySET, sizeof(phySET), NULL, 0, NULL);
	}
	else
	{
		DEBUGMSG(ZONE_INIT, (TEXT("Gum::Cable DETACH! \r\n")));
		g_pGPIORegs->GPCR1 = GPIO_41_USB_CONTROL;
		phySET.subcode = PHY_SET_ADDR;		// atomic operation
		phySET.address = PXA255_BASE_REG_PA_GPIO + offsetof(GPIO_REG_T,GPDR1);
		phySET.mask = GPIO_41_USB_CONTROL;
		phySET.value = 0;	// clear it
		KernelIoControl(IOCTL_HAL_PHYADR, &phySET, sizeof(phySET), NULL, 0, NULL);
	}
}

static
BOOL HWCheckCableAttached(void)
{
	return (g_pGPIORegs->GPLR1 & GPIO_35_CABLE_DETECT);
}

// Retrieve the endpoint status structure.
static
inline
PEP_STATUS
GetEpStatus(
            PCTRLR_PDD_CONTEXT pContext,
            DWORD dwEndpoint
            )
{
    PEP_STATUS peps;

    ValidateContext(pContext);
    DEBUGCHK(EP_VALID(dwEndpoint));

    peps = &pContext->rgEpStatus[dwEndpoint];
    DEBUGCHK(peps->dwEndPointNumber == dwEndpoint);

    return peps;
}

/*++

Routine Description:

Return the control/status register of an endpoint.

Arguments:

dwEndpoint - the target endpoint

Return Value:

The control/status register of the target endpoint.

--*/
static
volatile ULONG *
_GetControlStatusRegister(
                          DWORD        dwEndpoint
                          )
{
    volatile ULONG *lpulStatusReg = NULL;

    DEBUGCHK(EP_VALID(dwEndpoint));

    static volatile ULONG * const sc_rglpulStatusRegs[] = {
        &g_pUDCRegs->UDCCS0, 
        &g_pUDCRegs->UDCCS1, 
        &g_pUDCRegs->UDCCS2, 
        &g_pUDCRegs->UDCCS3, 
        &g_pUDCRegs->UDCCS4, 
        &g_pUDCRegs->UDCCS5, 
        &g_pUDCRegs->UDCCS6, 
        &g_pUDCRegs->UDCCS7, 
        &g_pUDCRegs->UDCCS8, 
        &g_pUDCRegs->UDCCS9, 
        &g_pUDCRegs->UDCCS10,
        &g_pUDCRegs->UDCCS11,
        &g_pUDCRegs->UDCCS12,
        &g_pUDCRegs->UDCCS13,
        &g_pUDCRegs->UDCCS14,
        &g_pUDCRegs->UDCCS15,
    };
    DEBUGCHK(dim(sc_rglpulStatusRegs) == ENDPOINT_COUNT);

    if (dwEndpoint < dim(sc_rglpulStatusRegs)) {
        lpulStatusReg = sc_rglpulStatusRegs[dwEndpoint];
    }
    
    return lpulStatusReg;
} // _GetControlStatusRegister

/*++

Routine Description:

Return the data register of an endpoint.

Arguments:

dwEndpoint - the target endpoint

Return Value:

The data register of the target endpoint.

⌨️ 快捷键说明

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