📄 pxa25xpdd.cpp
字号:
&g_pUDCBase->uddr9,
&g_pUDCBase->uddr10,
&g_pUDCBase->uddr11,
&g_pUDCBase->uddr12,
&g_pUDCBase->uddr13,
&g_pUDCBase->uddr14,
&g_pUDCBase->uddr15,
};
DEBUGCHK(dim(sc_rglpulDataRegs) == ENDPOINT_COUNT);
if (dwEndpoint < dim(sc_rglpulDataRegs)) {
lpulDataReg = sc_rglpulDataRegs[dwEndpoint];
}
return lpulDataReg;
} // _GetDataRegister
/*++
Routine Description:
Return the FIFO byte count register of an endpoint.
Arguments:
dwEndpoint - the target endpoint
Return Value:
The FIFO byte count register of an endpoint.
--*/
static
volatile ULONG *
_GetByteCountRegister(
DWORD dwEndpoint
)
{
volatile ULONG *lpulByteCountReg = NULL;
DEBUGCHK(EP_VALID(dwEndpoint));
// only inspect endpoints capable of OUT transactions
switch (dwEndpoint) {
case 2: lpulByteCountReg = (LPULONG) &g_pUDCBase->ubc2; break;
case 4: lpulByteCountReg = (LPULONG) &g_pUDCBase->ubc4; break;
case 7: lpulByteCountReg = (LPULONG) &g_pUDCBase->ubc7; break;
case 9: lpulByteCountReg = (LPULONG) &g_pUDCBase->ubc9; break;
case 12: lpulByteCountReg = (LPULONG) &g_pUDCBase->ubc12; break;
case 14: lpulByteCountReg = (LPULONG) &g_pUDCBase->ubc14; break;
default:
break;
}
return lpulByteCountReg;
}
/*++
Routine Description:
Enable the interrupt of an endpoint.
Arguments:
dwEndpoint - the target endpoint
Return Value:
None.
--*/
static
VOID
EnableEndpointInterrupt( PCTRLR_PDD_CONTEXT pPddContext, DWORD dwEndpoint )
{
SETFNAME();
FUNCTION_ENTER_MSG();
PREFAST_ASSERT(dwEndpoint <16 && pPddContext != NULL);
DEBUGMSG(ZONE_USB_EVENTS,(TEXT("EnableEndpointInterrupt (%d)"),dwEndpoint));
EnterCriticalSection(&pPddContext->csIsrCtrlAccess);
if ( dwEndpoint < 8 ) {
g_pUDCBase->uicr0 &= ~(1 << dwEndpoint);
DEBUGMSG(ZONE_PIPE,
(_T("%s endpoint %u interrupt enabled; ucir0 -> 0x%x \r\n"),
pszFname,
dwEndpoint,
g_pUDCBase->uicr0));
}
else if ( dwEndpoint < 16 ) {
g_pUDCBase->uicr1 &= ~(1 << (dwEndpoint % 8));
DEBUGMSG(ZONE_PIPE,
(_T("%s endpoint %u interrupt enabled; uicr1 -> 0x%x \r\n"),
pszFname,
dwEndpoint,
g_pUDCBase->uicr1));
}
else {
DEBUGCHK(FALSE);
}
LeaveCriticalSection(&pPddContext->csIsrCtrlAccess);
FUNCTION_LEAVE_MSG();
} // _EnableEpInterrupt
/*++
Routine Description:
Disable the interrupt of an endpoint.
Arguments:
dwEndpoint - the target endpoint
Return Value:
None.
--*/
static
VOID
DisableEndpointInterrupt(PCTRLR_PDD_CONTEXT pPddContext,DWORD dwEndpoint )
{
SETFNAME();
FUNCTION_ENTER_MSG();
PREFAST_ASSERT(dwEndpoint <16 && pPddContext != NULL);
DEBUGMSG(ZONE_USB_EVENTS,(TEXT("DisableEndpointInterrupt (%d)"),dwEndpoint));
EnterCriticalSection(&pPddContext->csIsrCtrlAccess);
if ( dwEndpoint <8 ) {
g_pUDCBase->uicr0 |= (1 << dwEndpoint);
DEBUGMSG(ZONE_PIPE,
(_T("%s EP %u Off; ucir0 -> 0x%x \r\n"),
pszFname,
dwEndpoint,
g_pUDCBase->uicr0));
}
else if (dwEndpoint < 16) {
g_pUDCBase->uicr1 |= (1 << (dwEndpoint % 8));
DEBUGMSG(ZONE_PIPE,
(_T("%s EP %u Off; uicr1 -> 0x%x \r\n"),
pszFname,
dwEndpoint,
g_pUDCBase->uicr1));
}
else {
DEBUGCHK(FALSE);
}
LeaveCriticalSection(&pPddContext->csIsrCtrlAccess);
FUNCTION_LEAVE_MSG();
return;
} // DisableEndpointInterrupt
// Clear the HW bits for an endpoint
static
VOID
ClearEndpointRegBits(
const EP_STATUS *peps
)
{
SETFNAME();
FUNCTION_ENTER_MSG();
DEBUGMSG(ZONE_FUNCTION,
(_T("%s Clearing ALL EP Bits \r\n"),
pszFname));
volatile ULONG *lpulStatusReg = peps->lpulUDCCSx;
PREFAST_DEBUGCHK(lpulStatusReg != NULL);
// Clear Unique Endpoint 0 bits.
if(peps->dwEndPointNumber == 0){
// Clear the Out Packet Ready
*lpulStatusReg |= (USB_UDCCS0_OPR |USB_UDCCS_FTF);
// Clear Input Packet ready
*lpulStatusReg &= ~USB_UDCCS0_IPR;
// Clear Setup Active
*lpulStatusReg &= ~USB_UDCCS0_SA;
// Remaing bits will be handled below...
}
// Clear Stall (Sent and Force) if not Isoch
if (peps->dwTypeSupported != USB_ENDPOINT_TYPE_ISOCHRONOUS ) {
*lpulStatusReg &= ~USB_UDCCS_FST; // Clear Force Stall
*lpulStatusReg |= USB_UDCCS_SST; //Clear Stall Sent
}
// Clear Remaining Endpoint Bits
if((peps->dwTypeSupported == USB_ENDPOINT_TYPE_ISOCHRONOUS )||
(peps->dwTypeSupported == USB_ENDPOINT_TYPE_BULK ) ||
(peps->dwTypeSupported == USB_ENDPOINT_TYPE_INTERRUPT)){
if (peps->dwDirectionSupported==USB_IN_TRANSFER) {
//Clear Packet Complete and Transmit Fifo Underrun
*lpulStatusReg |= (USB_UDCCS_TPC |USB_UDCCS_TUR |USB_UDCCS_FTF);
// Clear Short Packet
*lpulStatusReg &= ~USB_UDCCS_TSP;
}
else{ // USB_OUT_TRANSFER
//Clear Packet Complete
*lpulStatusReg |= USB_UDCCS_RPC;
if (peps->dwTypeSupported == USB_ENDPOINT_TYPE_ISOCHRONOUS ){
*lpulStatusReg |= USB_UDCCS_ROF; // Clear Receive Overflow
}
// Clear DMA Enable
*lpulStatusReg &= ~USB_UDCCS_DME;
}
}
FUNCTION_LEAVE_MSG();
}
// Reset an endpoint
static
VOID
ResetEndpoint(
PCTRLR_PDD_CONTEXT pContext,
EP_STATUS *peps
)
{
SETFNAME();
FUNCTION_ENTER_MSG();
DEBUGCHK(IS_VALID_XSC1_CONTEXT(pContext));
PREFAST_DEBUGCHK(peps);
// Clear any outstanding Interrupts
// Note that Endpoint 0 WILL NOT BE DISABLED
if (peps->dwEndPointNumber!=0)
DisableEndpointInterrupt(pContext,peps->dwEndPointNumber);
ClearEndpointRegBits(peps);
FUNCTION_LEAVE_MSG();
}
// Reset the (device and EP0).
static
VOID
ResetDevice(
PCTRLR_PDD_CONTEXT pContext
)
{
SETFNAME();
FUNCTION_ENTER_MSG();
DEBUGCHK(IS_VALID_XSC1_CONTEXT(pContext));
// Disable device interrupts - set Mask Registers
UDCCR_REM_DISABLE(g_pUDCBase->udccr);
g_pUDCBase->uicr0 = DISABLE_INTRS_0TO7; // Disable 0-7
g_pUDCBase->uicr1 = DISABLE_INTRS_0TO7; // Disable 8-15
g_pUDCBase->udccr |= USB_UDCCR_SRM; // Mask Remote/Suspend
// Clear outstanding device interrupts
g_pUDCBase->udccr |=(USB_UDCCR_RSTIR | USB_UDCCR_SUSIR | USB_UDCCR_RESIR);
// Disable USB interface
UDCCR_UDE_DISABLE(g_pUDCBase->udccr);
// Reset USB configuration
// Nothing to do for xscale
// Disable auto-enumeration
// Nothing to do for xscale
// Reset all endpoints
EP_STATUS * peps;
for (DWORD dwEndpoint = 0; dwEndpoint < ENDPOINT_COUNT; ++dwEndpoint) {
peps = GetEpStatus(pContext, dwEndpoint);
ResetEndpoint(pContext, peps);
}
// Clear outstanding Endpoint interrupts
g_pUDCBase->uisr0 = CLEAR_INTRS_0TO7; // Clear Enpoint Interrupts 0-7
g_pUDCBase->uisr1 = CLEAR_INTRS_8TO15; // Clear Enpoint Interrupts 8-15
FUNCTION_LEAVE_MSG();
}
#ifdef DEBUG
static
VOID
ValidateTransferDirection(
PCTRLR_PDD_CONTEXT pContext,
PEP_STATUS peps,
PSTransfer pTransfer
)
{
DEBUGCHK(pContext);
PREFAST_DEBUGCHK(peps);
PREFAST_DEBUGCHK(pTransfer);
if (peps->dwEndPointNumber != 0) {
DEBUGCHK(peps->dwDirectionSupported == pTransfer->dwFlags);
}
}
#else
#define ValidateTransferDirection(ptr1, ptr2, ptr3)
#endif
static DWORD ReceiveData(PEP_STATUS peps, PBYTE pBuffer, DWORD dwLength)
{
SETFNAME();
DEBUGMSG(ZONE_FUNCTION, (_T("%s pBuffer=0x%x, dwLength= 0x%x\r\n"),pszFname,pBuffer,dwLength));
PREFAST_ASSERT(pBuffer!=NULL);
DWORD dwTotalRead = 0;
while (dwLength && ((*(peps->lpulUDCCSx)) & USB_UDCCS0_RNE )!=0) { // All endpoint RNE are the same bit.
*pBuffer = (BYTE) *(peps->lpulUDDRx);
pBuffer ++;
dwLength --;
dwTotalRead ++;
}
DEBUGMSG(ZONE_FUNCTION, (_T("%s Complete dwTotalRead = 0x%x\r\n"),pszFname,dwTotalRead));
return dwTotalRead;
}
static DWORD XmitData(PEP_STATUS peps, PBYTE pBuffer, DWORD dwLength)
{
SETFNAME();
DEBUGMSG(ZONE_FUNCTION, (_T("%s pBuffer=0x%x, dwLength= 0x%x\r\n"),pszFname,pBuffer,dwLength));
PREFAST_ASSERT(pBuffer!=NULL);
DWORD dwTotalWrite = dwLength ;
while ( dwLength != 0 ) {
*(peps->lpulUDDRx) = *pBuffer ;
pBuffer ++;
dwLength --;
}
DEBUGMSG(ZONE_FUNCTION, (_T("%s Complete dwTotalWrite = 0x%x\r\n"),pszFname,dwTotalWrite));
return dwTotalWrite;
}
static
VOID
CompleteTransfer(
PCTRLR_PDD_CONTEXT pContext,
PEP_STATUS peps,
DWORD dwUsbError
)
{
SETFNAME();
FUNCTION_ENTER_MSG();
PSTransfer pTransfer = peps->pTransfer;
DEBUGCHK(pTransfer);
peps->pTransfer = NULL;
DEBUGMSG(ZONE_TRANSFER, (_T("%s Complete Transfer Error = 0x%x\r\n"),pszFname,dwUsbError));
pTransfer->dwUsbError = dwUsbError;
pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_TRANSFER_COMPLETE,
(DWORD) pTransfer);
FUNCTION_LEAVE_MSG();
}
// Read data from an endpoint.
static
VOID
HandleRx(
PCTRLR_PDD_CONTEXT pContext,
PEP_STATUS peps
)
{
BOOL fCompleted = FALSE;
SETFNAME();
FUNCTION_ENTER_MSG();
BOOL bContinue = TRUE;
while (bContinue) {
bContinue = FALSE;
ULONG ulUdccs = *(peps->lpulUDCCSx);
PSTransfer pTransfer = peps->pTransfer;
DEBUGMSG(ZONE_USB_EVENTS || ZONE_PIPE, (_T("%s ulUdccs = %u \r\n"), pszFname, ulUdccs));
if ((ulUdccs & USB_UDCCS_RFS)!=0 && pTransfer!=NULL &&
pTransfer->cbTransferred < pTransfer ->cbBuffer) { // Handle Unload Packet.
DWORD dwCurrentPermissions = GetCurrentPermissions();
DWORD dwSize = (pTransfer->cbTransferred< pTransfer->cbBuffer? pTransfer->cbBuffer-pTransfer->cbTransferred: 0);
dwSize = min(dwSize, peps->dwPacketSizeSupported );
DWORD dwReturnSize = 0;
DWORD dwError = UFN_NO_ERROR ;
SetProcPermissions(pTransfer->dwCallerPermissions);
__try {
dwReturnSize = ReceiveData(peps,(PBYTE)pTransfer->pvBuffer + pTransfer->cbTransferred , dwSize) ;
}
__except(EXCEPTION_EXECUTE_HANDLER) {
dwReturnSize = 0;
dwError =UFN_CLIENT_BUFFER_ERROR ;
}
SetProcPermissions(dwCurrentPermissions);
pTransfer->cbTransferred += dwReturnSize;
if (dwError == UFN_CLIENT_BUFFER_ERROR) { // We had error. Stall it.
ulUdccs |= USB_UDCCS_FST;
*(peps->lpulUDCCSx) = ulUdccs ;
CompleteTransfer(pContext, peps, UFN_CLIENT_BUFFER_ERROR);
continue;
}
bContinue = TRUE;
}
if (ulUdccs & USB_UDCCS_RPC ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -