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

📄 s3c6410otgdevice.cpp

📁 6410BSP3
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    FUNCTION_ENTER_MSG();

    ValidateContext(pContext);
    PREFAST_DEBUGCHK(peps);

    // Since Reset can be called before/after an Endpoint has been configured,
    // it is best to clear all IN and OUT bits associated with endpoint.
    DWORD dwEndpoint = peps->dwEndpointNumber;

    // All Endpoints interrupt register clear
    if(dwEndpoint == 0)
    {
        WriteEPSpecificReg(dwEndpoint, DIEPINT, 0x3f);
        WriteEPSpecificReg(dwEndpoint, DOEPINT, 0x3f);
    }
    else if (dwEndpoint < ENDPOINT_COUNT)
    {
        WriteEPSpecificReg(dwEndpoint, DIEPINT, 0x3f);
        WriteEPSpecificReg(dwEndpoint, DOEPINT, 0x3f);
        DisableEndpointInterrupt(pContext, peps->dwEndpointNumber, peps->dwDirectionAssigned);
    }

    FUNCTION_LEAVE_MSG();
}


// Initialize OTG device register
static
VOID
InitDevice(
    PCTRLR_PDD_CONTEXT     pContext
    )
{
    WriteReg(GUSBCFG, NP_TXFIFO_REWIND_EN | TURNAROUND_TIME | PHYIF_16BIT | 0x7<<HS_FS_TIMEOUT);
    WriteReg(DCFG, 0x1f<<IN_EP_MISS_CNT_IDX | DEVICE_SPEED_HIGH);               
    WriteReg(DAINTMSK, EP0_OUT_INT | EP0_IN_INT);        // EP0 IN,OUT interrupt Unmask

    WriteReg(GOTGCTL,SESSION_REQUEST);
    WriteReg(GRXFSIZ, RXFIFO_DEPTH);                        // Rx FIFO Size
    WriteReg(GNPTXFSIZ, NPTXFIFO_DEPTH<<NPTXFIFO_DEPTH_IDX | RXFIFO_DEPTH<<0);        // Non Periodic Tx FIFO Size
    WriteReg(DOEPMSK, SETUP_PHASE_DONE | XFER_COMPLETE);
    WriteReg(DIEPMSK, TIMEOUT_CONDITION | XFER_COMPLETE);

    WriteReg(GINTMSK, INT_RESUME | INT_OUT_EP | INT_IN_EP | INT_EPMIS | INT_SDE | INT_RESET | INT_SUSPEND | INT_OTG);    //gint unmask
    WriteReg(GAHBCFG, NPTXFEMPLVL_COMPLETE_EMPTY | MODE_DMA | BURST_SINGLE | GBL_INT_UNMASK);

    WriteReg(GRSTCTL, TXFFLSH | RXFFLSH);
    while(!((ReadReg(GRSTCTL) & (TXFFLSH | RXFFLSH))==0)); // Wait Until the FIFO Flush bit Cleared
}

static
VOID
InitPDDContext(
    PCTRLR_PDD_CONTEXT     pContext
    )
{
    pContext->dwPipelinedEP = 0;
    pContext->bRingBufferFull = FALSE;
    pContext->dwPipelinedStrIdx = pContext->dwPipelinedEndIdx = 0;
    pContext->dwPipelinedXferSize = 1024*64;

    pContext->dwXmittingEP = 0;
    pContext->dwXmitReadyCnt = 0;
    pContext->bOutEPDMAStartFlag = FALSE;
    
    for(DWORD i=0; i<ENDPOINT_COUNT; ++i) 
    {
        pContext->dwInEPRunning[i] = 0;
        for(DWORD depth=0; depth<PIPELINED_FIFO_DEPTH; depth++)
            pContext->dwPipelinedXfered[i][depth] = 0;
    }
}

static 
inline
VOID
SetSoftDisconnect()
{
    SetClearReg(DCTL, SOFT_DISCONNECT, SET);
}


// This function is used to dicconnect to host.
// As long as this function is called, the host will not see that the device is connected,
// and the device will not receive signals on the USB.
static
inline
VOID
ClearSoftDisconnect()
{
    SetClearReg(DCTL, SOFT_DISCONNECT, CLEAR);
}


// USB signal mask to prevent unwanted leakage
// This function should be called before USB PHY is used
void MaskUSBSignal(
    PCTRLR_PDD_CONTEXT     pContext
    )
{
    volatile DWORD dwRegValue;
    dwRegValue = pContext->pSYSCONregs->OTHERS;
    dwRegValue |= USB_SIG_MASK;
    pContext->pSYSCONregs->OTHERS = dwRegValue;
}


// All module state machines (except the AHB Slave Unit) are reset to the IDLE state,
// and all the transmit FIFOs and the receive FIFO are flushed.
static
void
SoftResetCore(
    PCTRLR_PDD_CONTEXT     pContext
    )
{
    WriteReg(GRSTCTL, CSFTRST);
    while(!(ReadReg(GRSTCTL) & AHBIDLE)); // Wait until AHB Master IDLE
}


// Reset the device and EP0.
static
VOID
ResetDevice(
    PCTRLR_PDD_CONTEXT     pContext
    )
{
    SETFNAME();
    FUNCTION_ENTER_MSG();

    DEBUGCHK(IS_VALID_SC6410_CONTEXT(pContext));

    SoftResetCore(pContext);
    InitDevice(pContext);

    // Reset all endpoints
    for (DWORD dwEpIdx = 0; dwEpIdx < ENDPOINT_COUNT; ++dwEpIdx)
    {
        EP_STATUS *peps = GetEpStatus(pContext, dwEpIdx);
        ResetEndpoint(pContext, peps);
    }

    FUNCTION_LEAVE_MSG();
}


// After transmit a packet, this function should be called to let MDD know.
static
VOID
CompleteTransfer(
    PCTRLR_PDD_CONTEXT     pContext,
    PEP_STATUS             peps,
    DWORD                 dwUsbError
    )
{
    SETFNAME();
    FUNCTION_ENTER_MSG();

    PSTransfer pTransfer = peps->pTransfer;
    
    peps->pTransfer = NULL;

    pTransfer->dwUsbError = dwUsbError;
    pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_TRANSFER_COMPLETE, (DWORD) pTransfer);

    FUNCTION_LEAVE_MSG();
}


// Wating until TxFIFO Empty ++//
static
BOOL
WatiForTxFIFOEmpty(
    DWORD dwWaitCount
    )
{
    for(DWORD i = 0 ; i < dwWaitCount ; i++)
    {
        if(ReadReg(GINTSTS) & INT_TX_FIFO_EMPTY)
        {
            break;
        }
        Sleep(1);
        if (i >= (dwWaitCount-1))
        {
            RETAILMSG(UFN_ZONE_ERROR,(_T("TX FIFO Not Empty Error!!! Wait Coutnt %d - StartPreparedInTrasfer\r\n"),i));
            return FALSE;
        }
    }
    return TRUE;
}    
// Wating until TxFIFO Empty --//


// This function is only vaild in debug build.
#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->dwDirectionAssigned == pTransfer->dwFlags);
    }
}
#else
#define ValidateTransferDirection(ptr1, ptr2, ptr3)
#endif


#if TEST_MODE_SUPPORT
static BOOL
CheckForUSBTestModeRequest(
    PCTRLR_PDD_CONTEXT pContext
    )
{
    bool fTest = FALSE;

    volatile DWORD dwDCTL;

    PEP_STATUS peps = GetEpStatus(pContext, 0);
    LOCK_ENDPOINT(peps);
    
    // is this a request to enter a test mode?
    if( pContext->UDR.bmRequestType     == (USB_REQUEST_HOST_TO_DEVICE | USB_REQUEST_STANDARD | USB_REQUEST_FOR_DEVICE)
            && pContext->UDR.bRequest     == USB_REQUEST_SET_FEATURE
            && pContext->UDR.wValue     == USB_FEATURE_TEST_MODE
            && (pContext->UDR.wIndex & 0xFF) == 0) 
    {
        pContext->sendDataEnd = TRUE;
        pContext->Ep0State = EP0_STATE_IDLE;       


        RETAILMSG(UFN_ZONE_USB_EVENTS, (_T("USBF:USB_FEATURE_TEST_MODE\r\n")));
        // Set TEST MODE

        RETAILMSG(UFN_ZONE_USB_EVENTS, (_T("USBF:TEST_FORCE_ENABLE\r\n")));
        //Set Test Force Enable
        WriteReg(DIEPTSIZ0, 1<<PACKET_COUTNT_IDX | 0);
        WriteReg(DIEPCTL0, EP_ENABLE | CLEAR_NAK | 3<<0);    //ep0 enable, clear nak, 8byte

        dwDCTL = ReadReg(DCTL);
        TM_Enabled(dwDCTL);
        WriteReg(DCTL, dwDCTL);


        USHORT wTestMode = pContext->UDR.wIndex >> 8;

        switch( wTestMode)
        {
            case USB_TEST_J:

                RETAILMSG(UFN_ZONE_USB_EVENTS, (_T("USBF:USB_TEST_J\r\n")));
                WriteReg(DIEPTSIZ0, 1<<PACKET_COUTNT_IDX | 0);
                WriteReg(DIEPCTL0, EP_ENABLE | CLEAR_NAK | 3<<0);    //ep0 enable, clear nak, 8byte
                dwDCTL = ReadReg( DCTL);
                TM_J_Selected(dwDCTL);                    
                WriteReg(DCTL, dwDCTL);                
            break;

            case USB_TEST_K:

                RETAILMSG(UFN_ZONE_USB_EVENTS, (_T("USBF:USB_TEST_K\r\n")));
                WriteReg(DIEPTSIZ0, 1<<PACKET_COUTNT_IDX | 0);
                WriteReg(DIEPCTL0, EP_ENABLE | CLEAR_NAK | 3<<0);    //ep0 enable, clear nak, 8byte
                dwDCTL = ReadReg( DCTL);
                TM_K_Selected(dwDCTL);                    
                WriteReg(DCTL, dwDCTL);                
                
            break;

            case USB_TEST_SE0_NAK:

                RETAILMSG(UFN_ZONE_USB_EVENTS, (_T("USBF:USB_TEST_SE0_NAK\r\n")));
                WriteReg(DIEPTSIZ0, 1<<PACKET_COUTNT_IDX | 0);
                WriteReg(DIEPCTL0, EP_ENABLE | CLEAR_NAK | 3<<0);    //ep0 enable, clear nak, 8byte
                dwDCTL = ReadReg( DCTL);
                TM_SN_Selected(dwDCTL);                    
                WriteReg(DCTL, dwDCTL);                
            break;

            case USB_TEST_PACKET:
            {
                RETAILMSG(UFN_ZONE_USB_EVENTS, (_T("USBF:USB_TEST_PACKET\r\n")));
                DWORD cbWritten = 0;
                WORD WriteData = 0;

                memcpy( pContext->pVAddrEP[0][IN_EP] ,ahwTestPkt, TEST_PKT_SIZE);
                WatiForTxFIFOEmpty(100);    
                WriteReg(DIEPDMA0, pContext->pPAddrEP[0][IN_EP]);
                
                WriteReg(DIEPTSIZ0, 1<<PACKET_COUTNT_IDX | 0);
                WriteReg(DIEPCTL0, EP_ENABLE | CLEAR_NAK | 3<<0);    //ep0 enable, clear nak, 8byte
                WriteReg(DIEPTSIZ0, 1<<PACKET_COUTNT_IDX | TEST_PKT_SIZE); 
                WriteReg(DIEPCTL0, EP_ENABLE | CLEAR_NAK | EP0_MAX_PK_SIZ);    //ep0 enable, clear nak, 64byte

                WatiForTxFIFOEmpty(100);    

                dwDCTL = ReadReg(DCTL);
                TM_PKT_Selected(dwDCTL);        
                RETAILMSG(UFN_ZONE_USB_EVENTS,(_T("USBF:DCTL : 0x%x\r\n"),dwDCTL));                
                WriteReg(DCTL, dwDCTL);
            }
            break;


            case USB_TEST_FORCE_ENABLE:
                RETAILMSG(UFN_ZONE_USB_EVENTS, (_T("USBF:TEST_FORCE_ENABLE\r\n")));
                //Set Test Force Enable
                WriteReg(DIEPTSIZ0, 1<<PACKET_COUTNT_IDX | 0);
                WriteReg(DIEPCTL0, EP_ENABLE | CLEAR_NAK | 3<<0);    //ep0 enable, clear nak, 8byte

                dwDCTL = ReadReg(DCTL);
                TM_Enabled(dwDCTL);
                WriteReg(DCTL, dwDCTL);
            break;                
        }
        
        fTest = TRUE;
    }

    UNLOCK_ENDPOINT(peps);

    return fTest;
}
#endif


// Process an endpoint0 interrupt.  
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);

    // Write 0 to SEND_STALL and SENT_STALL to clear them, so we need to
    // leave them unchanged by default.
    BOOL fSendUDR = FALSE;
    BOOL fCompleted = FALSE;
    DWORD dwStatus;

    if (pContext->Ep0State == EP0_STATE_IDLE)
    {
        if (pContext->fSpeedReported == FALSE)
        {
            // After Every Reset Notify MDD of Speed setting.
            // This device can support both FULL and HIGH speed.
            // It will be process in HandleUSBBusIrq INT_SDE.
            if (pContext->dwDetectedSpeed == USB_FULL)
            {
                pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_BUS_SPEED, BS_FULL_SPEED);
            }
            else if(pContext->dwDetectedSpeed == USB_HIGH)
            {
                pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_BUS_SPEED, BS_HIGH_SPEED);
            }
            else
            {
                DEBUGMSG(ZONE_ERROR,(_T("SPEED Exeption LowSpeed \r\n")));
            }
            pContext->fSpeedReported = TRUE;
        }
        
        if (pContext->bRdySetupPkt == TRUE)    
        {
            pContext->bRdySetupPkt = FALSE;

            // Initialize EP0 Out DMA to get a SetUp packet            
            WriteReg(DOEPDMA0, pContext->pPAddrEP[0][OUT_EP]);
            WriteReg(DOEPTSIZ0, 1<<SETUP_PKT_CNT_IDX | 1<<PACKET_COUTNT_IDX | 8);
            WriteReg(DOEPCTL0, EP_ENABLE | CLEAR_NAK | EP0_MAX_PK_SIZ);
        }
        else
        {
            PDWORD pbUDR = (PDWORD) &pContext->UDR;
               memcpy(pbUDR, pContext->pVAddrEP[0][OUT_EP] ,sizeof(pContext->UDR));
    
#if TEST_MODE_SUPPORT         
            if(CheckForUSBTestModeRequest(pContext)) //for testmode
            {
                // DO NOTHING
            }
            else if (8 != sizeof(pContext->UDR))
#else
            if (8 != sizeof(pContext->UDR))
#endif
            {
                DEBUGMSG(ZONE_ERROR, (_T("%s Setup packet was only !!\r\n"), pszFname));
                // Ideally this should not hapen. This is a recovery mechanism if
                // we get out of sync somehow.
            }
            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 IN State Machine
                        pContext->Ep0State = EP0_STATE_IN_DATA_PHASE;
                    }
                    else
                    {
                        // Start the SW OUT State Machine

⌨️ 快捷键说明

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