📄 pxa25xpdd.cpp
字号:
//
// 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:
pxa25xpdd.CPP
Abstract:
pxa25x (XScale) CPU USB Function Platform-Dependent Driver.
--*/
#include "pxa25xpdd.h"
#include <ddkreg.h>
#define ZONE_POWER DEBUGZONE(8)
UFN_GENERATE_DPCURSETTINGS(UFN_DEFAULT_DPCURSETTINGS_NAME,
_T("Power"), _T(""), _T(""), _T(""),
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;
PVOID pvLibContext;
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
#define IS_VALID_XSC1_CONTEXT(ptr) \
( (ptr != NULL) && (ptr->dwSig == XSC1_SIG) )
// 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_REGS *g_pUDCBase;
#define IN_TRANSFER 1
#define OUT_TRANSFER 2
// Forward Declaration Here
extern "C" {
BOOL InitClock();
BOOL StartClock(unsigned int,BOOL);
BOOL StopClock(unsigned int,BOOL);
}
#ifdef DEBUG
// Validate the Xscale context.
static
VOID
ValidateContext(
PCTRLR_PDD_CONTEXT pContext
)
{
PREFAST_DEBUGCHK(pContext);
DEBUGCHK(pContext->dwSig == XSC1_SIG);
DEBUGCHK(!pContext->hevInterrupt || pContext->hIST);
DEBUGCHK(pContext->pfnNotify);
}
#else
#define ValidateContext(ptr)
#endif
// 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_pUDCBase->udccs0,
&g_pUDCBase->udccs1,
&g_pUDCBase->udccs2,
&g_pUDCBase->udccs3,
&g_pUDCBase->udccs4,
&g_pUDCBase->udccs5,
&g_pUDCBase->udccs6,
&g_pUDCBase->udccs7,
&g_pUDCBase->udccs8,
&g_pUDCBase->udccs9,
&g_pUDCBase->udccs10,
&g_pUDCBase->udccs11,
&g_pUDCBase->udccs12,
&g_pUDCBase->udccs13,
&g_pUDCBase->udccs14,
&g_pUDCBase->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.
--*/
static
volatile ULONG *
_GetDataRegister(
DWORD dwEndpoint
)
{
volatile ULONG *lpulDataReg = NULL;
DEBUGCHK(EP_VALID(dwEndpoint));
static volatile ULONG * const sc_rglpulDataRegs[] = {
&g_pUDCBase->uddr0,
&g_pUDCBase->uddr1,
&g_pUDCBase->uddr2,
&g_pUDCBase->uddr3,
&g_pUDCBase->uddr4,
&g_pUDCBase->uddr5,
&g_pUDCBase->uddr6,
&g_pUDCBase->uddr7,
&g_pUDCBase->uddr8,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -