📄 pxa255_ufnpdd.cpp
字号:
// 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 + -