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

📄 sc2440pdd.cpp

📁 S3C2440A的windows ce 5.0 bsp包
💻 CPP
📖 第 1 页 / 共 5 页
字号:
        // so... just ignore it.
        goto EXIT;
    }

    if (fCompleted) {
        // Disable transfer interrupts until another transfer is issued.
        if (peps->dwEndPointNumber != 0) {
            DisableEndpointInterrupt(pContext, peps->dwEndPointNumber);
            ClearEndpointInterrupt(pContext, peps->dwEndPointNumber);
        }
        
        CompleteTransfer(pContext, peps, dwStatus);
        DEBUGMSG(ZONE_SEND, (_T("%s Tx Done  Ep%x %u\r\n"), pszFname, 
            dwEndpoint, 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();
}


// 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);

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

    LOCK_ENDPOINT(peps);
    DWORD dwEndPoint = peps->dwEndPointNumber;

    if (dwEndpoint == 0){
        BYTE bEP0IrqStatus = ReadIndexedReg(pContext, 0,IN_CSR1_REG_OFFSET);

        // The Setup Token is handled in HandleUSBEvents()
        // Handle End Of Status Packet (Zero Length Data 
        // Packet

        // Note that the SETUP TOKEN is decoded in Ufn_Read to 
        // determine if a GET_ or SET_ command is coming. That decoding 
        // sets the initial State Machine State to   
        // EP0_STATE_OUT_DATA_PHASE or EP0_STATE_IN_DATA_PHASE
        DWORD bWordCount = ReadIndexedReg(pContext, dwEndpoint, OUT_FIFO_CNT1_REG_OFFSET);
        switch(peps->dwEpState) {
           case EP0_STATE_OUT_DATA_PHASE:
               // Check For out packet read && receive fifo not empty -> out token event
               if ( (bEP0IrqStatus & OUT_PACKET_READY) && ( bWordCount) ){
                   DEBUGMSG(ZONE_RECEIVE, (_T("%s out token packet on endpoint 0 \r\n"),
                       pszFname));                
                   dwPendingEvents |= OUT_TRANSFER;
               }
               // status stage of control transfer; zero-length packet received
               else if ( (bEP0IrqStatus & OUT_PACKET_READY) && ( bWordCount == 0) ){                     
                   DEBUGMSG(ZONE_RECEIVE, (_T("%s status stage of control transfer on endpoint 0; UDCCS0 = 0x%x \r\n"),
                       pszFname, bEP0IrqStatus));
                   // clear OPR by writing a 1 to SO bit                       
                   peps->dwEpState = EP_STATE_IDLE; 
                   SetClearIndexedReg(pContext,0,OUT_CSR1_REG_OFFSET,
                       SERVICED_OUT_PKY_RDY, SET);
               }
               break;

               // IN Data Phase and IPR is cleared 
           case  EP0_STATE_IN_DATA_PHASE: 
               // Check For status stage - End control transfer; zero-length packet received
               if ( (bEP0IrqStatus &  OUT_PACKET_READY) && ( bWordCount == 0) ) {
                   dwPendingEvents = IN_TRANSFER;

                   DEBUGMSG(ZONE_SEND, (_T("%s In - end xfer; UDCCS0 = 0x%x \r\n"),
                       pszFname, bEP0IrqStatus));
               }
               else if ((bEP0IrqStatus &  IN_PACKET_READY) == 0) {
                   dwPendingEvents = IN_TRANSFER;
               }
               
               DEBUGMSG(ZONE_SEND, (_T("%s Data Phase In Token\r\n"), pszFname));
               break;

           default:    // EP_STATE_IDLE
               // During Normal ACK/NAK This State should never happen but it will
               // Force the State Machine into a known State if it does
               peps->dwEpState = EP_STATE_IDLE;  
               DEBUGMSG(ZONE_FUNCTION, (_T("%s EP0 Status =  %x \r\n"), 
                   pszFname, bEP0IrqStatus ));
               break;                   
        }

        DEBUGMSG(ZONE_FUNCTION, (_T("%s EP State =  %u \r\n"), 
            pszFname, peps->dwEpState ));
        DEBUGMSG(ZONE_FUNCTION, (_T("%s HE EP0 Status = %x,%u \r\n"), 
            pszFname, bEP0IrqStatus, peps->dwEpState ));
    }    
    else { // Any endpoint other than 0
        BYTE bEpIrqStat;

        if (peps->dwDirectionAssigned == USB_IN_TRANSFER){
            bEpIrqStat = ReadIndexedReg(pContext, dwEndPoint,IN_CSR1_REG_OFFSET);
            DEBUGMSG(ZONE_FUNCTION, (_T("%s HE EPIN Status = %x\r\n"), 
                pszFname, 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 SST EP%u \r\n"), 
                    pszFname, dwEndpoint));

                pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_SETUP_PACKET, (DWORD) &udr);
                // Must Clear both Send and Sent Stall
                SetClearIndexedReg(pContext,dwEndpoint, IN_CSR1_REG_OFFSET,
                    (IN_SEND_STALL  | IN_SENT_STALL), SET);
            }
            
            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;
            }

            DEBUGMSG(ZONE_FUNCTION, (_T("%s End EPIn Status =  %x \r\n"),
                pszFname, bEpIrqStat));
        }
        else {
            bEpIrqStat = ReadIndexedReg(pContext, dwEndPoint,OUT_CSR1_REG_OFFSET);
            // 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;
                udr.wIndex = (BYTE) dwEndpoint;
                udr.wLength =0;
                DisableEndpointInterrupt(pContext, dwEndpoint);
                DEBUGMSG(ZONE_FUNCTION, (_T("%s Got SST EP%u \r\n"), 
                    pszFname, dwEndpoint));
                pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_SETUP_PACKET, (DWORD) &udr);
                SetClearIndexedReg(pContext,dwEndpoint, OUT_CSR1_REG_OFFSET,
                    ( OUT_SEND_STALL | OUT_SENT_STALL), CLEAR);
            }
            
            // 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;
            }

            DEBUGMSG(ZONE_FUNCTION, (_T("%s End EPOut Status =  %x \r\n"),
                pszFname, bEpIrqStat ));
        }   

    }

    if (dwPendingEvents & IN_TRANSFER) {
        HandleTx(pContext, peps, 0);
    }
    else if (dwPendingEvents & OUT_TRANSFER) {
        HandleRx(pContext, peps);
    }

    FUNCTION_LEAVE_MSG();
    UNLOCK_ENDPOINT(peps);
}



// Process a SC2440 interrupt.
static
VOID
HandleUSBEvent(
               PCTRLR_PDD_CONTEXT pContext
               )
{
    SETFNAME();
    FUNCTION_ENTER_MSG();
    ValidateContext(pContext);

    EP_STATUS *peps  = GetEpStatus(pContext, 0);

    BYTE bEpIrqStat = ReadReg(pContext, EP_INT_REG_OFFSET);
    BYTE bUSBBusIrqStat = ReadReg(pContext, USB_INT_REG_OFFSET);

    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);
        }
    }

    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_ATTACH) {
            DEBUGMSG(ZONE_USB_EVENTS, (_T("%s Resume\r\n"), pszFname));
            pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_BUS_EVENTS, UFN_RESUME);
        }
    }

    if (bUSBBusIrqStat & USB_RESET_INTR) {
        pContext->fSpeedReported = FALSE;
        WriteReg(pContext, USB_INT_REG_OFFSET, USB_RESET_INTR);
        // 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;
        }

        peps->dwEpState = EP_STATE_IDLE;
        pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_BUS_EVENTS, UFN_RESET);

        // Enable the Suspend interrupt...
        SetClearReg(pContext, USB_INT_EN_REG_OFFSET, USB_SUSPEND_INTR, SET);

        DEBUGMSG(ZONE_USB_EVENTS, (_T("%s Reset\r\n"), pszFname));
    }

    // Setup Token Processing

    if (bEpIrqStat & EP0_INT_INTR) {
        //Read the Ep0 Interrupt Status Register
        BYTE bEP0IrqStatus = ReadIndexedReg(pContext, 0, IN_CSR1_REG_OFFSET);

        // Clear End Point 0 Interrupt
        ClearEndpointInterrupt(pContext, 0);
        DEBUGMSG(ZONE_USB_EVENTS, (_T("%s Status, %x\r\n"), pszFname, bEP0IrqStatus));

        if (bEP0IrqStatus & SETUP_END) {
            SetClearIndexedReg(pContext, 0, IN_CSR1_REG_OFFSET, SERVICED_SETUP_END, SET);

            peps->dwEpState = EP_STATE_IDLE;
            PSTransfer pTransfer = peps->pTransfer;

            // Make MDD think everything is ok. Host will retry last packet
            if(pTransfer) {
                CompleteTransfer(pContext, peps, UFN_NO_ERROR);
            }

            // The HW does not seem to work correctly. It takes some time to 
            // clear the setup end before the Setup Toke is correctly acked and
            // The Word Count register is loaded (note that opr is normally set here
            // during the same ISR pass as well. The HW manual says 
            // to unload the packet if opr is set as well. This time was 
            // determined experimentally
            StallExecution(100); // Wait for HW To clear SE

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

            bEP0IrqStatus &= ~SETUP_END;
        }
        
        // Set By USB if protocoll violation detected
        if (bEP0IrqStatus & EP0_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 = 0; // Ep 0
            udr.wLength =0;
            pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_SETUP_PACKET, (DWORD) &udr);

            // Must Clear both Send and Sent Stall
            SetClearIndexedReg(pContext,0, IN_CSR1_REG_OFFSET,
                (EP0_SEND_STALL | EP0_SEND_STALL), CLEAR);

            peps->dwEpState = EP_STATE_IDLE;
            bEP0IrqStatus &= ~EP0_SENT_STALL;
        }
        
        const DWORD dwSetupPacketSize = ReadIndexedReg(pContext, 0, 
            OUT_FIFO_CNT1_REG_OFFSET);
        
        // If a new Command receieved
        if (bEP0IrqStatus & EP0_OUT_PACKET_RDY) {
            BOOL  fUdrValid = TRUE;  // Indicate whether or not UDR was correctly 
            // decoded

            USB_DEVICE_REQUEST udr;
            udr.wLength = 0;                                         
            DWORD dwBytesRead;
            PBYTE pbUdr = (PBYTE) &udr;
            volatile ULONG *pulFifoReg = _GetDataRegister(0);
            for (dwBytesRead = 0; dwBytesRead < dwSetupPacketSize; dwBytesRead++) {
                pbUdr[dwBytesRead] = (UCHAR) *pulFifoReg;
            }

            // 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.        
            if (fUdrValid) {
                // Determine if this is a NO Data Packet
                if (udr.wLength > 0) {
                    // Determine transfer Direction
                    if (udr.bmRequestType & USB_ENDPOINT_DIRECTION_MASK) {
                        // Start the SW OUT State Machine
                        peps->dwEpState = EP0_STATE_IN_DATA_PHASE;                      
                    }
                    else {
                        // Start the SW OUT State Machine
                        peps->dwEpState = EP0_STATE_OUT_DATA_PHASE; 
                    }
                }
                else if ( (udr.bmRequestType  != USB_REQUEST_STANDARD) &&
                          (udr.bmRequestType  != USB_REQUEST_FOR_ENDPOINT)  ) { 
                        // Is it a Standard, Class, Vendor or Reserved Command
                        // The UDC HW needs the IPR bit set accordingly
                        // If it is No Data  - Vendor, Class or Reserved Command 

                        // ClientDriver will issue a SendControlStatusHandshake to 
                        // complete the transaction.

                        // Nothing left to do... transition to IDLE.
                        peps->dwEpState = EP_STATE_IDLE;              
                    }
                else { // Make sure the IPR Bit is Clear
                    // Must be 
                    //    (udr->wLength == 0) &&
                    //    (udr->bmRequestType  == USB_REQUEST_STANDARD)
                    SetClearIndexedReg(pContext, 0, OUT_CSR1_REG_OFFSET,
                        EP0_IN_PACKET_RDY, CLEAR);
                }
            }
            else {
                DEBUGMSG(ZONE_USB_EVENTS || ZONE_WARNING, (_T("%s Udr Invalid\r\n"), 
                    pszFname));

                // Udr read from the FIFO was invalid 
                // Ideally this should not hapen. This is a recovery mechanism if 
                // we get out of sync somehow.  

                // Client won't care and will see a reset to clean things up

                SetClearIndexedReg(pContext, 0, OUT_CSR1_REG_OFFSET,
                    DATA_END | SERVICED_OUT_PKY_RDY, SET);

                DEBUGCHK(FALSE);
                fUdrValid = FALSE;
            }
            
            if (fUdrValid) {
                // Only clear OPR if sending data back - else it will be done in 
                // ControlStatusHandshake
                if(udr.wLength == 0){
                    pContext->sendDataEnd = TRUE;
                }
                else {
                    // Clear Out Packet Ready - receive FIFO should be empty
                    SetClearIndexedReg(pContext,0,OUT_CSR1_REG_OFFSET,
                        SERVICED_OUT_PKY_RDY, SET);
                    pContext->sendDataEnd = FALSE;
                }

                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;
                }

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

            bEP0IrqStatus &= ~EP0_OUT_PACKET_RDY;
        }
        // If Out Packet ready and No Data then must be an End Transfer 

⌨️ 快捷键说明

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