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

📄 sc2440pdd.cpp

📁 基于WinCE5.0平台的三星S3C2440的BSP包更新.
💻 CPP
📖 第 1 页 / 共 5 页
字号:

    // 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_PKT_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_PKT_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 & IN_PACKET_READY) == 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;
            udr.wIndex = (BYTE) 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) {
        if (peps->pTransfer) {
            bEpIrqStatToWrite |= HandleRx(pContext, peps, &fCompleted, &dwStatus);
        }
        else {
            // FIFO unload failed, so leave OUT_PKT_RDY bit alone.
            DEBUGMSG(ZONE_WARNING, (_T("  %s failed to unload FIFO, so preserving OUT_PKT_RDY bit."), pszFname));
            bEpIrqStatToWrite |= OUT_PACKET_READY;
        }
    }

    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;
            }
            
            pContext->Ep0State = EP0_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);
        }

    FUNCTION_LEAVE_MSG();
}


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

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

    while (bEpIrqStat || bUSBBusIrqStat) {
        if (bUSBBusIrqStat) {
            DEBUGMSG(ZONE_COMMENT, (_T("%s USB_INT_REG = 0x%02x\r\n"), 
                pszFname, bUSBBusIrqStat));
            HandleUSBBusIrq(pContext, bUSBBusIrqStat);
        }

        if (bEpIrqStat) {
            DEBUGMSG(ZONE_COMMENT, (_T("%s EP_INT_REG = 0x%02x\r\n"), 
                pszFname, bEpIrqStat));

            if (bEpIrqStat & EP0_INT_INTR) {
                HandleEndpoint0Event(pContext);
            }
            
            // Process All Other (besides EP0) Endpoints
            for (DWORD dwEndpoint = 1; dwEndpoint < ENDPOINT_COUNT; ++dwEndpoint) {
                // Check the Interrupt Mask 
                // Check the Interrupt Status 
                BYTE bEpBit =  EpToIrqStatBit(dwEndpoint);
                if (bEpIrqStat & bEpBit) {
                    HandleEndpointEvent(pContext, dwEndpoint, bEpIrqStat);
                }
            }
        }

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

⌨️ 快捷键说明

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