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

📄 sc2440pdd.cpp

📁 三星ARM9系列CPU S3C2440A的WINCE 5.0下的BSP
💻 CPP
📖 第 1 页 / 共 5 页
字号:
            }
            
            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);

 //  RETAILMSG(1, (TEXT(" Hnt\r\n")));

  //  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);
   // }
    
    FUNCTION_LEAVE_MSG();
}


/****************************************************************
@doc INTERNAL

@func VOID | SerUSB_InternalMapRegisterAddresses |
This routine maps the ASIC registers. 
It's an artifact of this
implementation.

@rdesc None.
****************************************************************/
static
DWORD MapRegisterSet(PCTRLR_PDD_CONTEXT pContext)
{
    SETFNAME();
    FUNCTION_ENTER_MSG();

    PREFAST_DEBUGCHK(pContext);

    DEBUGCHK(g_pUDCBase == NULL);

    PBYTE   pVMem;
    DWORD   dwRet = ERROR_SUCCESS;

    // Map CSR registers.
    pVMem = (PBYTE)VirtualAlloc(0, PAGE_SIZE, MEM_RESERVE, PAGE_NOACCESS);

    if (pVMem) {
        BOOL fSuccess = VirtualCopy(pVMem, (LPVOID)pContext->dwIOBase,
            pContext->dwIOLen, PAGE_READWRITE | PAGE_NOCACHE);
        if (!fSuccess) {
            VirtualFree(pVMem, 0, MEM_RELEASE);
            dwRet = GetLastError();
            DEBUGMSG(ZONE_ERROR, (_T("%s Virtual Copy: FAILED\r\n"), pszFname));
        }
        else {
            g_pUDCBase = pVMem + BASE_REGISTER_OFFSET;

            DEBUGMSG(ZONE_INIT, (_T("%s VirtualCopy Succeeded, pVMem:%x\r\n"), 
                pszFname, pVMem));
        }
    } 
    else {
        dwRet = GetLastError();
        DEBUGMSG(ZONE_ERROR, (_T("%s Virtual Alloc: FAILED\r\n"), pszFname));
    }

    FUNCTION_LEAVE_MSG();
    
    return dwRet;
}

/*++

Routine Description:

Deallocate register space.

Arguments:

None.

Return Value:

None.

--*/
static
VOID
UnmapRegisterSet(PCTRLR_PDD_CONTEXT pContext)
{
    // Unmap any memory areas that we may have mapped.
    if (g_pUDCBase) {
        VirtualFree((PVOID) g_pUDCBase, 0, MEM_RELEASE);
        g_pUDCBase = NULL;
    }
}


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

    while (!pContext->fExitIST) {
        pContext->fRestartIST = FALSE;

        // Enable Suspend Mode in the Power Register
//        SetClearReg(pContext, PWR_REG_OFFSET, SUSPEND_MODE_ENABLE_CTRL, SET);

        // Disable All Endpoint interrupts
        WriteReg(pContext, EP_INT_EN_REG_OFFSET, 0); // Disable All

        // Enable Device interrupts
        WriteReg(pContext, USB_INT_EN_REG_OFFSET, (USB_RESET_INTR));// | USB_SUSPEND_INTR));

        // Enable Endpoint interrupt 0
        EnableEndpointInterrupt(pContext, 0);

        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_INIT, (_T("%s WaitForMultipleObjects failed. Exiting IST.\r\n"), 
                    pszFname));
                break;
            }
        }

        // Disable Device  interrupts - write Zeros to Disable
        WriteReg(pContext, USB_INT_EN_REG_OFFSET, 0 );

        // Disable endpoint interrupts - write Zeros to Disable
        WriteReg(pContext, EP_INT_EN_REG_OFFSET, 0);
        
        // Clear any outstanding device & endpoint interrupts
        // USB Device Interrupt Status - Write a '1' to Clear 
        WriteReg(pContext, USB_INT_REG_OFFSET, 
            (USB_RESET_INTR | USB_RESUME_INTR | USB_SUSPEND_INTR));
        // End point Interrupt Status - Write a '1' to Clear
        WriteReg(pContext, EP_INT_REG_OFFSET, CLEAR_ALL_EP_INTRS);

        // Send detach
        pContext->pfnNotify(pContext->pvMddContext, 
            UFN_MSG_BUS_EVENTS, UFN_DETACH);

        pContext->fSpeedReported = FALSE;
        pContext->attachedState = UFN_DETACH;
    }

    FUNCTION_LEAVE_MSG();

    return 0;
}

static
VOID
StartTransfer(
              PCTRLR_PDD_CONTEXT pContext,
              PEP_STATUS peps,
              PSTransfer pTransfer
              )
{
    SETFNAME();

    DEBUGCHK(pContext);
    PREFAST_DEBUGCHK(peps);

    DEBUGCHK(!peps->pTransfer);
    ValidateTransferDirection(pContext, peps, pTransfer);

    LOCK_ENDPOINT(peps);
    FUNCTION_ENTER_MSG();

    DEBUGMSG(ZONE_TRANSFER, (_T("%s Setting up %s transfer on ep %u for %u bytes\r\n"),
        pszFname, (pTransfer->dwFlags == USB_IN_TRANSFER) ? _T("in") : _T("out"),
        peps->dwEndpointNumber, pTransfer->cbBuffer));

    // Enable transfer interrupts.
    peps->pTransfer = pTransfer;

    if (pTransfer->dwFlags == USB_IN_TRANSFER) {
        // Must Clear both Send and Sent Stall - the HW is setting this bit 
        // during the Endpoint initialization process. It must be cleared here 
        // to insure proper operation.
//        SetClearIndexedReg(pContext, peps->dwEndpointNumber, IN_CSR1_REG_OFFSET,
//            (IN_SEND_STALL | IN_SENT_STALL), CLEAR);               

        if (peps->dwEndpointNumber == 0) {
            if ( (pTransfer->cbBuffer < pContext->udr.wLength) &&
                 (pTransfer->cbBuffer != 0) &&
                 ( (pTransfer->cbBuffer % peps->dwPacketSizeAssigned) == 0 ) ) {
                // This transfer will need a 0-length packet to terminate it.
                pTransfer->pvPddData = (PVOID) 1;
            }
            
            BYTE bEP0IrqStatus = ReadIndexedReg(pContext, 0, EP0_CSR_REG_OFFSET);

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

            if (bEP0IrqStatus & EP0_OUT_PACKET_RDY) {
                bEp0CsrToWrite |= SERVICED_OUT_PKY_RDY;
                DEBUGMSG(ZONE_COMMENT, (_T("%s Writing 0x%02x to EP0_CSR_REG\r\n"), pszFname, bEp0CsrToWrite));
                WriteIndexedReg(pContext, 0, EP0_CSR_REG_OFFSET, bEp0CsrToWrite);
                bEp0CsrToWrite &= ~SERVICED_OUT_PKY_RDY;
            }

            bEp0CsrToWrite |= HandleTx(pContext, peps, 0);
            
            DEBUGMSG(ZONE_COMMENT, (_T("%s Writing 0x%02x to EP0_CSR_REG\r\n"), pszFname, bEp0CsrToWrite));
            WriteIndexedReg(pContext, 0, EP0_CSR_REG_OFFSET, bEp0CsrToWrite);
        }
        else {
            BYTE bIrqStatus = ReadIndexedReg(pContext, 0, IN_CSR1_REG_OFFSET);

            // Write 0 to SEND_STALL and SENT_STALL to clear them, so we need to 
            // leave them unchanged by default.
            BYTE bEpStatToWrite = (bIrqStatus & (IN_SENT_STALL & IN_SEND_STALL));

            bEpStatToWrite |= HandleTx(pContext, peps, 1);

            DEBUGMSG(ZONE_COMMENT, (_T("%s Writing 0x%02x to IN_CSR1_REG\r\n"), pszFname));
            WriteIndexedReg(pContext, peps->dwEndpointNumber, 
                IN_CSR1_REG_OFFSET, bEpStatToWrite);
        }
    }
    else {
        if (peps->dwEndpointNumber == 0) {
            BYTE bEP0IrqStatus = ReadIndexedReg(pContext, 0, EP0_CSR_REG_OFFSET);

            // Write 0 to SEND_STALL and SENT_STALL to clear them, so we need to 
            // leave them unchanged by default.
            BYTE bEp0CsrToWrite = (bEP0IrqStatus & EP0_STALL_BITS);
            
            // Mark that we are done with the setup packet. The IST will take care
            // of the data transfer.
            if (bEP0IrqStatus & EP0_OUT_PACKET_RDY) {
                bEp0CsrToWrite |= SERVICED_OUT_PKY_RDY;
                DEBUGMSG(ZONE_COMMENT, (_T("%s Writing 0x%02x to EP0_CSR_REG\r\n"), pszFname, bEp0CsrToWrite));
                WriteIndexedReg(pContext, 0, EP0_CSR_REG_OFFSET, bEp0CsrToWrite);
            }
        }
        else {
            EnableEndpointInterrupt(pContext, peps->dwEndpointNumber);

            // There may be a packet available.  If so process it...
            BYTE bEpIrqStat = ReadIndexedReg(pContext, peps->dwEndpointNumber,
                OUT_CSR1_REG_OFFSET);
            
            if (bEpIrqStat & OUT_PACKET_READY) {
                BOOL fCompleted;
                DWORD dwStatus;
                BYTE bToWrite = HandleRx(pContext, peps, &fCompleted, &dwStatus);
                DEBUGMSG(ZONE_COMMENT, (_T("%s Writing 0x%02x to OUT_CSR1_REG\r\n"), pszFname, 
                    bToWrite));

                // There should be no double-buffering
                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);
                }

                WriteIndexedReg(pContext, peps->dwEndpointNumber, OUT_CSR1_REG_OFFSET, bToWrite);
                
                if (fCompleted) {
                    CompleteTransfer(pContext, peps, dwStatus);
                }    
            }
        }
    }
    
    FUNCTION_LEAVE_MSG();

    UNLOCK_ENDPOINT(peps);
}
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->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);
    StartTransfer(pContext, peps, pTransfer);

    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);
    CompleteTransfer(pContext, peps, UFN_CANCELED_ERROR);

    if (dwEndpoint == 0) {
        pContext->Ep0State = EP0_STATE_IDLE;
    }
    
    ResetEndpoint( pContext,peps);

    UNLOCK_ENDPOINT(peps);

    FUNCTION_LEAVE_MSG();

    return ERROR_SUCCESS;
}


/////////////////////////////// jassi ////////////////////////////////
#define CLKCON_USBD (1<<7)

volatile S3C2440A_CLKPWR_REG *pCLKPWR	= NULL;		// Clock power registers (needed to enable I2S and SPI clocks)
volatile S3C2440A_IOPORT_REG *pIOPregs	= NULL;

⌨️ 快捷键说明

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