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

📄 sc2440pdd.cpp

📁 三星ARM9系列CPU S3C2440A的WINCE 5.0下的BSP
💻 CPP
📖 第 1 页 / 共 5 页
字号:
        }

        SetProcPermissions(dwCurrentPermissions);
    }   
    else {
        // It is possible for an interrupt to come in while still in this 
        // function for first pass of transfer. If this happens it is possible
        // to complete the transfer and have that interrupt be unnecessary
        // so... just ignore it.
        goto EXIT;
    }


    if (fCompleted) {
        // Disable transfer interrupts until another transfer is issued.
#if 1        
        if (peps->dwEndpointNumber != 0) {
            DisableEndpointInterrupt(pContext, peps->dwEndpointNumber);
        }
#endif

        DEBUGMSG(ZONE_SEND, (_T("%s Tx Done  Ep%x  Status %u\r\n"), pszFname, 
            dwEndpoint, dwStatus));
        CompleteTransfer(pContext, peps, dwStatus);
    }
    else {
        DEBUGMSG(ZONE_SEND, (_T("%s Tx EP%x BufferSize=%u, Xfrd=%u\r\n"), 
            pszFname, dwEndpoint, pTransfer->cbBuffer, pTransfer->cbTransferred));
    }

EXIT:
    FUNCTION_LEAVE_MSG();

    return bRet;
}


static
VOID
HandleEndpoint0Event(
                    PCTRLR_PDD_CONTEXT  pContext
                    )
{
    SETFNAME();
    FUNCTION_ENTER_MSG();

    ValidateContext(pContext);
    DEBUGCHK(pContext->fRunning);

    PEP_STATUS peps = GetEpStatus(pContext, 0);
    LOCK_ENDPOINT(peps);

    ClearEndpointInterrupt(pContext, 0);
    BYTE bEP0IrqStatus = ReadIndexedReg(pContext, 0, EP0_CSR_REG_OFFSET);

    DEBUGMSG(ZONE_USB_EVENTS, (_T("%s EP0_CSR_REG = 0x%02x. Data phase = %u\r\n"), 
        pszFname, bEP0IrqStatus, pContext->Ep0State));

    // Write 0 to SEND_STALL and SENT_STALL to clear them, so we need to 
    // leave them unchanged by default.
    BYTE bEp0CsrToWrite = 0;

    if (bEP0IrqStatus & SETUP_END) {
        bEp0CsrToWrite |= SERVICED_SETUP_END;

        pContext->Ep0State = EP0_STATE_IDLE;
        PSTransfer pTransfer = peps->pTransfer;

        // Make MDD think everything is ok.
        if(pTransfer) {
            pContext->sendDataEnd = FALSE;
            CompleteTransfer(pContext, peps, UFN_NO_ERROR);
        }

        DEBUGMSG(ZONE_USB_EVENTS, (_T("%s Setup End, %x\r\n"), 
            pszFname, bEP0IrqStatus));
    }

    // Set By USB if protocol violation detected
    if (bEP0IrqStatus & EP0_SENT_STALL) {
        // Must Clear both Send and Sent Stall
        pContext->Ep0State = EP0_STATE_IDLE;
    }

    BOOL fSendUdr = FALSE;
    
    DWORD cbFifo = ReadIndexedReg(pContext, 0, OUT_FIFO_CNT1_REG_OFFSET);
    BOOL fCompleted = FALSE;
    DWORD dwStatus;

    if (pContext->Ep0State == EP0_STATE_IDLE) {
        if (bEP0IrqStatus & EP0_OUT_PACKET_RDY) {
            if (pContext->fSpeedReported == FALSE) {
                // After Every Reset Notify MDD of Speed setting.
                // This device can only support FULL Speed.
                pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_BUS_SPEED,
                    BS_FULL_SPEED);
                pContext->fSpeedReported = TRUE;
            }
            
            // New setup packet
            const DWORD cbOutFifo = ReadIndexedReg(pContext, 0, 
                OUT_FIFO_CNT1_REG_OFFSET);

            PBYTE pbUdr = (PBYTE) &pContext->udr;
            volatile ULONG *pulFifoReg = _GetDataRegister(0);
            
            DWORD cbBytesRemaining = cbOutFifo;
            while (cbBytesRemaining--) {
                *pbUdr++ = (BYTE) *pulFifoReg;
            }

            if (cbOutFifo != sizeof(pContext->udr)) {
                DEBUGMSG(ZONE_ERROR, (_T("%s Setup packet was only %x bytes!\r\n"),
                    pszFname, cbOutFifo));
                
                // Ideally this should not hapen. This is a recovery mechanism if 
                // we get out of sync somehow.  
                bEp0CsrToWrite |= (EP0_SEND_STALL | SERVICED_OUT_PKY_RDY | 
                    DATA_END);
            }
            else {
                // Parse the Setup Command this is necessary to Configure the 
                // SW State Machine and to set bits to enable the HW to 
                // ACK/NAK correctly.
                
                // Determine if this is a NO Data Packet
                if (pContext->udr.wLength > 0) {
                    // Determine transfer Direction
                    if (pContext->udr.bmRequestType & USB_ENDPOINT_DIRECTION_MASK) {
                        // Start the SW OUT State Machine
                        pContext->Ep0State = EP0_STATE_IN_DATA_PHASE;                      
                    }
                    else {
                        // Start the SW OUT State Machine
                        pContext->Ep0State = EP0_STATE_OUT_DATA_PHASE; 
                    }

                    pContext->sendDataEnd = FALSE;
                }
                else { // udr.wLength == 0
                    // ClientDriver will issue a SendControlStatusHandshake to 
                    // complete the transaction.
                    pContext->sendDataEnd = TRUE;

                    // Nothing left to do... stay in IDLE.
                    DEBUGCHK(pContext->Ep0State == EP0_STATE_IDLE);
                }

                fSendUdr = TRUE;
            }
        }
    }
    else if (pContext->Ep0State == EP0_STATE_OUT_DATA_PHASE) {
        if (bEP0IrqStatus & OUT_PACKET_READY) {
            bEp0CsrToWrite |= SERVICED_OUT_PKY_RDY;
            
            // Check For out packet read && receive fifo not empty -> out token event
            if (cbFifo) {
                DEBUGMSG(ZONE_RECEIVE, (_T("%s out token packet on endpoint 0 \r\n"),
                    pszFname));                
                bEp0CsrToWrite |= HandleRx(pContext, peps, &fCompleted, &dwStatus);
            }
            // status stage of control transfer; zero-length packet received
            else {                     
                DEBUGMSG(ZONE_RECEIVE, (_T("%s status stage of control transfer on endpoint 0\r\n"),
                    pszFname));
                pContext->Ep0State = EP0_STATE_IDLE;
            }
        }
    }
    else {
        DEBUGMSG(ZONE_SEND, (_T("%s Data Phase In Token\r\n"), pszFname));
        
        DEBUGCHK(pContext->Ep0State == EP0_STATE_IN_DATA_PHASE);

        BOOL bHandleTx = FALSE;

        // IN Data Phase and IPR is cleared 
        // Check For status stage - End control transfer; zero-length packet received
        if ( (bEP0IrqStatus &  OUT_PACKET_READY) && (cbFifo == 0) ) {
            bHandleTx = TRUE;

            DEBUGMSG(ZONE_SEND, (_T("%s In - end xfer\r\n"),
                pszFname));
        }
        else if ((bEP0IrqStatus & EP0_IN_PACKET_RDY) == 0) {
            bHandleTx = TRUE;
        }

        if (bHandleTx) {
            bEp0CsrToWrite |= HandleTx(pContext, peps, 0);
        }
    }

    // Clear any interrupts
    DEBUGMSG(ZONE_COMMENT, (_T("%s Writing 0x%02x to EP0_CSR\r\n"), pszFname, bEp0CsrToWrite));
    WriteIndexedReg(pContext, 0, EP0_CSR_REG_OFFSET, bEp0CsrToWrite);

    if (fCompleted) {
        CompleteTransfer(pContext, peps, dwStatus);
    }

    if (fSendUdr) {
        pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_SETUP_PACKET, (DWORD) &pContext->udr);
    }

    FUNCTION_LEAVE_MSG();
    UNLOCK_ENDPOINT(peps);
}


// Process an endpoint interrupt.  Call interrupt-specific handler.
static
VOID
HandleEndpointEvent(
                    PCTRLR_PDD_CONTEXT  pContext,
                    DWORD               dwEndpoint,
                    DWORD               epIrqStat
                    )
{
    SETFNAME();
    FUNCTION_ENTER_MSG();

    ValidateContext(pContext);
    DEBUGCHK(pContext->fRunning);
    DEBUGCHK(dwEndpoint != 0);

    DWORD dwPendingEvents = 0;
    EP_STATUS *peps = GetEpStatus(pContext, dwEndpoint);
    PREFAST_DEBUGCHK(peps);

    LOCK_ENDPOINT(peps);

    ClearEndpointInterrupt(pContext, dwEndpoint);

    BYTE bEpIrqStat;
    BYTE bEpIrqStatToWrite;
    DWORD dwIndexRegOffset;
	
    if (peps->dwDirectionAssigned == USB_IN_TRANSFER) {
        dwIndexRegOffset = IN_CSR1_REG_OFFSET;
    }
    else {
        dwIndexRegOffset = OUT_CSR1_REG_OFFSET;
    }

    bEpIrqStat = ReadIndexedReg(pContext, dwEndpoint, dwIndexRegOffset);

    if (peps->dwDirectionAssigned == USB_IN_TRANSFER) {
        bEpIrqStatToWrite = bEpIrqStat & (IN_SEND_STALL  | IN_SENT_STALL) & 
            ~(IN_CLR_DATA_TOGGLE);
        DEBUGMSG(ZONE_COMMENT, (_T("%s Endpoint %u IN_CSR1_REG = 0x%02x\r\n"), 
            pszFname, dwEndpoint, bEpIrqStat));

        // Stall "acknowledged" from Host
        if (bEpIrqStat & IN_SENT_STALL) {
            USB_DEVICE_REQUEST udr;
            udr.bmRequestType = USB_REQUEST_FOR_ENDPOINT;
            udr.bRequest = USB_REQUEST_CLEAR_FEATURE;
            udr.wValue = USB_FEATURE_ENDPOINT_STALL;
            udr.wIndex = USB_ENDPOINT_DIRECTION_MASK | (BYTE) dwEndpoint;
            udr.wLength = 0;

            DisableEndpointInterrupt(pContext, dwEndpoint);

            DEBUGMSG(ZONE_PIPE, (_T("%s Got IN_SENT_STALL EP%u \r\n"), 
                pszFname, dwEndpoint));

            pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_SETUP_PACKET, (DWORD) &udr);
            // Must Clear both Send and Sent Stall
            bEpIrqStatToWrite &= ~(IN_SEND_STALL  | IN_SENT_STALL);
        }
        
        if( !(bEpIrqStat & IN_PACKET_READY) ) {// If Transmit Complete 
            // send another
            DEBUGMSG(ZONE_SEND, (_T("%s Transmit packet complete on endpoint %u \r\n"), 
                pszFname, dwEndpoint));
            dwPendingEvents = IN_TRANSFER;
        }
    }
    else {
        bEpIrqStatToWrite = bEpIrqStat & (OUT_SEND_STALL | OUT_SENT_STALL) &
            ~(OUT_CLR_DATA_TOGGLE);
        DEBUGMSG(ZONE_COMMENT, (_T("%s Endpoint %u OUT_CSR1_REG = 0x%02x\r\n"), 
            pszFname, dwEndpoint, bEpIrqStat));
        
        // Stall "acknowledged" from Host
        if (bEpIrqStat & OUT_SENT_STALL) {
            USB_DEVICE_REQUEST udr;
            udr.bmRequestType = USB_REQUEST_FOR_ENDPOINT;
            udr.bRequest = USB_REQUEST_CLEAR_FEATURE;
            udr.wValue = USB_FEATURE_ENDPOINT_STALL;
            PREFAST_SUPPRESS(12006, "Buffer access index expression 'udr.wIndex=(USHORT)dwEndpoint' is being truncated in a shortening cast.");
            udr.wIndex = (USHORT) dwEndpoint;
            udr.wLength = 0;
            
            DisableEndpointInterrupt(pContext, dwEndpoint);

            DEBUGMSG(ZONE_PIPE, (_T("%s Got OUT_SENT_STALL EP%u \r\n"), 
                pszFname, dwEndpoint));

            pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_SETUP_PACKET, (DWORD) &udr);
            // Must Clear both Send and Sent Stall
            bEpIrqStatToWrite &= ~(OUT_SEND_STALL | OUT_SENT_STALL);
        }
        
        // receive packet complete && receive fifo not empty -> out token + data rx event
        if (bEpIrqStat & OUT_PACKET_READY) {
            DEBUGMSG(ZONE_RECEIVE, (_T("%s received packet complete on endpoint %u\r\n"), 
                pszFname, dwEndpoint ));
            // the UDC combines the OUT token event with the Data RX event
            dwPendingEvents = OUT_TRANSFER;
        }
    }

    BOOL fCompleted = FALSE;
    DWORD dwStatus;

    if (dwPendingEvents == IN_TRANSFER) {
        bEpIrqStatToWrite |= HandleTx(pContext, peps, 0); 
    }
    else if (dwPendingEvents == OUT_TRANSFER) {
        bEpIrqStatToWrite |= HandleRx(pContext, peps, &fCompleted, &dwStatus);
        // We have not yet cleared the interrupt so no other packets
        // should be in the FIFO.
        DEBUGCHK(ReadIndexedReg(pContext, peps->dwEndpointNumber, OUT_FIFO_CNT1_REG_OFFSET) == 0);
    }

    if (fCompleted) {
        // Disable transfer interrupts until another transfer is issued.
        DisableEndpointInterrupt(pContext, peps->dwEndpointNumber);
	}

    DEBUGMSG(ZONE_COMMENT, (_T("%s Writing 0x%02x to index 0x%02x\r\n"), pszFname, 
        bEpIrqStatToWrite, dwIndexRegOffset));
    WriteIndexedReg(pContext, dwEndpoint, dwIndexRegOffset, bEpIrqStatToWrite);

    if (fCompleted) {
        CompleteTransfer(pContext, peps, dwStatus);
	}
	
	
  
	FUNCTION_LEAVE_MSG();
    UNLOCK_ENDPOINT(peps);
}


// Process USB Bus interrupt
static
VOID
HandleUSBBusIrq(
                    PCTRLR_PDD_CONTEXT  pContext,
                    BYTE                bUSBBusIrqStat
                    )
{
    SETFNAME();
    FUNCTION_ENTER_MSG();
    
#if 0
        if (bUSBBusIrqStat & USB_SUSPEND_INTR) {
            WriteReg(pContext, USB_INT_REG_OFFSET, USB_SUSPEND_INTR);
            
            // Disable the interrupt
            SetClearReg(pContext, USB_INT_EN_REG_OFFSET, USB_SUSPEND_INTR, CLEAR);

            // Enable resume interrupt
            SetClearReg(pContext, USB_INT_EN_REG_OFFSET, USB_RESUME_INTR, SET);

            if (pContext->attachedState == UFN_ATTACH) {
                DEBUGMSG(ZONE_USB_EVENTS, (_T("%s Suspend\r\n"), pszFname));
    //            pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_BUS_EVENTS, UFN_SUSPEND);

                pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_BUS_EVENTS, UFN_DETACH);
                pContext->attachedState = UFN_DETACH;
            }
        }

        if (bUSBBusIrqStat & USB_RESUME_INTR) {
            WriteReg(pContext, USB_INT_REG_OFFSET, USB_RESUME_INTR);
            
            // Disable the interrupt
            SetClearReg(pContext, USB_INT_EN_REG_OFFSET, USB_RESUME_INTR, CLEAR);

            // Enable suspend interrupt
            SetClearReg(pContext, USB_INT_EN_REG_OFFSET, USB_SUSPEND_INTR, SET);

            if (pContext->attachedState == UFN_DETACH) {
                DEBUGMSG(ZONE_USB_EVENTS, (_T("%s Resume\r\n"), pszFname));
    //            pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_BUS_EVENTS, UFN_RESUME);
                pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_BUS_EVENTS, UFN_ATTACH);
                pContext->attachedState = UFN_ATTACH;
            }
        }
#endif

        if (bUSBBusIrqStat & USB_RESET_INTR) {
            WriteReg(pContext, USB_INT_REG_OFFSET, USB_RESET_INTR);
            
            DEBUGMSG(ZONE_USB_EVENTS, (_T("%s Reset\r\n"), pszFname));
            
            pContext->fSpeedReported = FALSE;

#if 0
            // 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_DETACH);
                pContext->attachedState = UFN_DETACH;
            }

            if (pContext->attachedState == UFN_DETACH){
                pContext->pfnNotify(pContext->pvMddContext,
                    UFN_MSG_BUS_EVENTS, UFN_ATTACH);
                pContext->attachedState = UFN_ATTACH;
            }
#endif

            if (pContext->attachedState == UFN_DETACH){
                pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_BUS_EVENTS, UFN_ATTACH);
                pContext->attachedState = UFN_ATTACH;

⌨️ 快捷键说明

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