📄 pxa255_ufnpdd.cpp
字号:
}
// Device Event
if (ulUdccr) {
if ( (ulUdccr & ( USB_UDCCR_SUSIR | USB_UDCCR_RESIR))!= NULL) // Suspend Resume.
{
/*
if (pContext->attachedState == UFN_DETACH && HWCheckCableAttached())
{
pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_BUS_EVENTS, UFN_ATTACH);
pContext->attachedState = UFN_ATTACH;
HWCableAttach(TRUE);
SetRequestInfo(&pContext->ep0Request, EP0Setup);
}
else if (pContext->attachedState == UFN_ATTACH && !HWCheckCableAttached())
{
pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_BUS_EVENTS, UFN_DETACH);
pContext->attachedState = UFN_DETACH;
HWCableAttach(FALSE);
SetRequestInfo(&pContext->ep0Request, EP0Setup);
}
*/
}
if ((ulUdccr & USB_UDCCR_RSTIR)!=0 && !pContext->fIgnoreReset)
{
DEBUGCHK(pContext->fRunning);
// Disable Double Buffering on Endpoints 1 and 2
g_pUDCRegs->RSVD0[0] &= ~(0x06);
// Reset Has been report multiple time . Ignore following one.
pContext->fIgnoreReset = TRUE;
DEBUGMSG(ZONE_USB_EVENTS, (_T("%s Reset\r\n"), pszFname));
// If the cable was connected to a host at boot, the attach interrupt
// will be missed. Generate it here.
if ((pContext->attachedState != UFN_ATTACH)){
pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_BUS_EVENTS, UFN_ATTACH);
pContext->attachedState = UFN_ATTACH;
HWCableAttach(TRUE);
}
pContext->fSpeedReported = FALSE;
pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_BUS_EVENTS, UFN_RESET);
SetRequestInfo(&pContext->ep0Request, EP0Setup);
}
}
if(ulIsr0 & USB_UISR0_IR0) {
ServiceEP0(pContext);
}
// inspect each interrupt/status register for a pending interrupt
if (ulIsr0) {
for (ulI = 1; ulI < 8; ulI += 1) {
if (ulIsr0 & (1 << ulI)){
// an interrupt is pending, notify the function driver
HandleEndpointEvent(pContext, ulI);
}
}
}
if (ulIsr1) {
for (ulI = 0; ulI < 8; ulI += 1) {
// an interrupt is pending, notify the function driver
if (ulIsr1 & (1 << ulI)) {
HandleEndpointEvent(pContext, (8 + ulI) );
}
}
}
}
FUNCTION_LEAVE_MSG();
}
// interrupt service routine.
static
DWORD
WINAPI
ISTMain(
LPVOID lpParameter
)
{
SETFNAME();
FUNCTION_ENTER_MSG();
PCTRLR_PDD_CONTEXT pContext = (PCTRLR_PDD_CONTEXT) lpParameter;
ValidateContext(pContext);
CeSetThreadPriority(pContext->hIST, pContext->dwISTPriority);
// Enable Acking
while (!pContext->fExitIST) {
pContext->fRestartIST = FALSE;
pContext->fEndpoint0AckNeeded = FALSE;
// Start clock
g_pCLKRegs->CKEN |= CKEN_USB;
// Disable USB interface
UDCCR_UDE_DISABLE(g_pUDCRegs->UDCCR);//g_pUDCRegs->udccr &= ~USB_UDCCR_UDE
// We are currently disconnected. Make sure that we have been
// disconnected long enough for the host to notice.
Sleep(1); // USB spec 7.1.7 says disconnect requires >= 2.5 us
// Disable All endpoint Interrupt.
g_pUDCRegs->UICR0 = DISABLE_INTRS_0TO7; // Endpoints 0-7
g_pUDCRegs->UICR1 = DISABLE_INTRS_0TO7; // Endpoints 8-15
// Clear any outstanding endpoint interrupts
g_pUDCRegs->UISR0 = CLEAR_INTRS_0TO7; // Clear Enpoint Interrupts 0-7
g_pUDCRegs->UISR1 = CLEAR_INTRS_8TO15; // Clear Enpoint Interrupts 8-15
// Enable USB interface , Enable Reset Interrupt, Enable Suspen/Resume Interrupt
// Clear any outstanding device interrupts
g_pUDCRegs->UDCCR = USB_UDCCR_UDE |USB_UDCCR_RSM| (USB_UDCCR_RSTIR | USB_UDCCR_SUSIR | USB_UDCCR_RESIR);
// Enable (UnMask) Endpoint 0 interrupts
EnableEndpointInterrupt( pContext, 0 );
SetRequestInfo(&pContext->ep0Request, EP0Setup);
//g_pUDCRegs->rsvd0[1] |= 0x04;
//g_pUDCRegs->rsvd0[1] &= ~0x80;
pContext->fIgnoreReset = FALSE;
//DV // initial cable check
if (HWCheckCableAttached())
{
HWCableAttach(TRUE);
pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_BUS_EVENTS, UFN_ATTACH);
}
while (TRUE) {
DWORD dwWait = WaitForSingleObject(pContext->hevInterrupt, INFINITE);
if (pContext->fExitIST || pContext->fRestartIST) {
break;
}
if (dwWait == WAIT_OBJECT_0) {
HandleUSBEvent(pContext);
InterruptDone(pContext->dwSysIntr);
}
else {
DEBUGMSG(ZONE_ERROR, (_T("%s WaitForMultipleObjects failed. Exiting IST.\r\n"),
pszFname));
pContext->fExitIST = TRUE;
break;
}
}
// Disable USB interface
UDCCR_UDE_DISABLE(g_pUDCRegs->UDCCR);//g_pUDCRegs->udccr &= ~USB_UDCCR_UDE
// Disable Bus Reset interrupts
UDCCR_REM_DISABLE(g_pUDCRegs->UDCCR);//g_pUDCRegs->udccr &= ~USB_UDCCR_REM
// Disable (Mask) Endpoint 0 interrupts
g_pUDCRegs->UICR0 |= USB_UICR0_IM0;
// Stop clock
g_pCLKRegs->CKEN &= ~CKEN_USB;
// Send detach
pContext->pfnNotify(pContext->pvMddContext,
UFN_MSG_BUS_EVENTS, UFN_DETACH);
pContext->attachedState = UFN_DETACH;
pContext->fSpeedReported = FALSE;
}
FUNCTION_LEAVE_MSG();
return 0;
}
/*++
Routine Description:
Deallocate register space.
Arguments:
None.
Return Value:
None.
--*/
static
VOID UnmapRegisterSet(void)
{
if (g_pGPIORegs)
{
VirtualFree((PVOID) g_pGPIORegs, 0, MEM_RELEASE);
g_pGPIORegs = NULL;
}
if (g_pCLKRegs)
{
VirtualFree((PVOID) g_pCLKRegs, 0, MEM_RELEASE);
g_pCLKRegs = NULL;
}
if (g_pUDCRegs) {
VirtualFree((PVOID) g_pUDCRegs, 0, MEM_RELEASE);
g_pUDCRegs = NULL;
}
}
/*++
Routine Description:
Map the base I/O address of the XScale UDC to virtual memory.
Arguments:
None.
Return Value:
Success.
--*/
static
DWORD MapRegisterSet(PCTRLR_PDD_CONTEXT pContext)
{
SETFNAME();
FUNCTION_ENTER_MSG();
PREFAST_DEBUGCHK(pContext);
DEBUGCHK(g_pUDCRegs == NULL);
DEBUGCHK(g_pGPIORegs == NULL);
DEBUGCHK(g_pCLKRegs == NULL);
DWORD dwRet = ERROR_SUCCESS;
PHYSICAL_ADDRESS RegPA;
if (g_pUDCRegs == NULL)
{
RegPA.QuadPart = pContext->dwIOBase;
g_pUDCRegs = (volatile UDC_REG_T *) MmMapIoSpace(RegPA, pContext->dwIOLen, FALSE);
}
if (g_pGPIORegs == NULL)
{
RegPA.QuadPart = PXA255_BASE_REG_PA_GPIO;
g_pGPIORegs = (volatile GPIO_REG_T *) MmMapIoSpace(RegPA, sizeof(GPIO_REG_T), FALSE);
}
if (g_pCLKRegs == NULL)
{
RegPA.QuadPart = PXA255_BASE_REG_PA_CLK;
g_pCLKRegs = (volatile CLK_REG_T *) MmMapIoSpace(RegPA, sizeof(CLK_REG_T), FALSE);
}
if (!g_pUDCRegs || !g_pGPIORegs || !g_pCLKRegs)
{
dwRet = GetLastError();
DEBUGMSG(ZONE_ERROR, (_T("%s Virtual Alloc: FAILED\r\n"), pszFname));
UnmapRegisterSet();
}
FUNCTION_LEAVE_MSG();
return dwRet;
}
static
VOID
StartTransfer(
PCTRLR_PDD_CONTEXT pContext,
PEP_STATUS peps,
PSTransfer pTransfer
)
{
SETFNAME();
FUNCTION_ENTER_MSG();
PREFAST_DEBUGCHK(pContext);
PREFAST_DEBUGCHK(peps);
DEBUGCHK(!peps->pTransfer);
ValidateTransferDirection(pContext, peps, pTransfer);
DEBUGMSG(ZONE_TRANSFER, (_T("%s Xfer ep %u for %u bytes\r\n"),
pszFname, peps->dwEndPointNumber, pTransfer->cbBuffer));
// Enable transfer interrupts.
peps->pTransfer = pTransfer;
// Enable transfer interrupts.
if (peps->dwEndPointNumber == 0) {
peps->fZeroPacketNeeded = TRUE;
if ((pTransfer->dwFlags & USB_IN_TRANSFER) != 0) {
DEBUGCHK(pContext->ep0Request.eDir == EP0In);
}
else {
DEBUGCHK(pContext->ep0Request.eDir == EP0Out);
}
if (!peps->fInIST) {
ServiceSetup(pContext,peps);
}
}
else {
EnableEndpointInterrupt(pContext,peps->dwEndPointNumber);
peps->fZeroPacketNeeded = ((pTransfer->cbBuffer== 0 || pTransfer->pvBuffer== 0) && (pTransfer->dwFlags & USB_IN_TRANSFER) != 0) ;
// Note For the Xscale the HW NAKs IN requests and DOES NOT let SW
// know that the Host is trying to send a request. SO... Start the Transfer
// In Now!
// Start the Transfer
if(!peps->fInIST) {
if ((pTransfer->dwFlags & USB_IN_TRANSFER) != 0) {
pContext->numInPacketsSent = 0;
HandleTx(pContext,peps);
}
else{
HandleRx(pContext,peps);
}
}
}
FUNCTION_LEAVE_MSG();
}
DWORD
WINAPI
UfnPdd_IssueTransfer(
PVOID pvPddContext,
DWORD dwEndpoint,
PSTransfer pTransfer
)
{
SETFNAME();
FUNCTION_ENTER_MSG();
DEBUGCHK(EP_VALID(dwEndpoint));
PCTRLR_PDD_CONTEXT pContext = (PCTRLR_PDD_CONTEXT) pvPddContext;
ValidateContext(pContext);
PEP_STATUS peps = GetEpStatus(pContext, dwEndpoint);
LOCK_ENDPOINT(peps);
DEBUGCHK(peps->fInitialized);
DEBUGCHK(pTransfer->dwUsbError == UFN_NOT_COMPLETE_ERROR);
DEBUGCHK(pTransfer->cbTransferred == 0);
DWORD dwRet = ERROR_SUCCESS;
// Note For the HW NAKs IN requests and DOES NOT let SW
// know that the Host is trying to send a request. SO... Start the Transfer
// In Now!
// Start the Transfer
DEBUGCHK(peps->pTransfer == NULL);
if (peps->dwEndPointNumber == 0) {
if ((pTransfer->dwFlags & USB_IN_TRANSFER)!= 0 ) {
if (pContext->ep0Request.eDir != EP0In) {
DEBUGMSG(ZONE_WARNING, (_T("%s EP0 is not in IN state. State = %u\r\n"),
pszFname, pContext->ep0Request.eDir));
dwRet = ERROR_NOT_READY;
goto EXIT;
}
}
else {
if (pContext->ep0Request.eDir != EP0Out) {
DEBUGMSG(ZONE_WARNING, (_T("%s EP0 is not in OUT state. State = %u\r\n"),
pszFname, pContext->ep0Request.eDir));
dwRet = ERROR_NOT_READY;
goto EXIT;
}
}
}
StartTransfer(pContext, peps, pTransfer);
EXIT:
UNLOCK_ENDPOINT(peps);
FUNCTION_LEAVE_MSG();
return dwRet;
}
DWORD
WINAPI
UfnPdd_AbortTransfer(
PVOID pvPddContext,
DWORD dwEndpoint,
PSTransfer pTransfer
)
{
SETFNAME();
FUNCTION_ENTER_MSG();
PREFAST_DEBUGCHK(pTransfer);
DEBUGCHK(EP_VALID(dwEndpoint));
PCTRLR_PDD_CONTEXT pContext = (PCTRLR_PDD_CONTEXT) pvPddContext;
ValidateContext(pContext);
PEP_STATUS peps = GetEpStatus(pContext, dwEndpoint);
LOCK_ENDPOINT(peps);
DEBUGCHK(peps->fInitialized);
ValidateTransferDirection(pContext, peps, pTransfer);
DEBUGCHK(pTransfer == peps->pTransfer);
if (dwEndpoint == 0) {
pContext->fEndpoint0AckNeeded = FALSE;
}
ResetEndpoint(pContext, peps);
CompleteTransfer(pContext, peps, UFN_CANCELED_ERROR);
UNLOCK_ENDPOINT(peps);
FUNCTION_LEAVE_MSG();
return ERROR_SUCCESS;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -