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

📄 sc2440pdd.cpp

📁 S3C2440A的windows ce 5.0 bsp包
💻 CPP
📖 第 1 页 / 共 5 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
#include <windows.h>
#include <nkintr.h>
#include <ddkreg.h>
#include "sc2440pdd.h"


#define UDC_REG_PRIORITY_VAL _T("Priority256")

#define EP_STATE_IDLE 0
#define EP0_STATE_IN_DATA_PHASE  1
#define EP0_STATE_END_XFER_PHASE  2
#define EP0_STATE_OUT_DATA_PHASE 3

#define IN_TRANSFER  1
#define OUT_TRANSFER 2


typedef struct EP_STATUS {
    DWORD                   dwEndPointNumber;
    DWORD                   dwDirectionAssigned;
    DWORD                   dwPacketSizeAssigned;
    BOOL                    fInitialized;
    DWORD                   dwEpState;
    DWORD                   dwEndpointType;
    PSTransfer              pTransfer;
    CRITICAL_SECTION        cs;
} *PEP_STATUS;

#define LOCK_ENDPOINT(peps)     EnterCriticalSection(&peps->cs)
#define UNLOCK_ENDPOINT(peps)   LeaveCriticalSection(&peps->cs)


#define EP_0_PACKET_SIZE    0x8    // Could also be 16 but they recommend 8  


static const EP_STATUS g_rgEpStatus[]  = {
    { 
        0x0,
    },
    { 
        0x1,
    },
    { 
        0x2,
    },
    { 
        0x3,
    },
    { 
        0x4,
    }
};


#define ENDPOINT_COUNT  dim(g_rgEpStatus)
#define EP_VALID(x) ((x) < ENDPOINT_COUNT)


#define DEFAULT_PRIORITY 100

typedef struct CTRL_PDD_CONTEXT {
    PVOID             pvMddContext;
    DWORD             dwSig;
    HANDLE            hIST;
    HANDLE            hevInterrupt;
    BOOL              fRunning;
    CRITICAL_SECTION  csIndexedRegisterAccess;
    BOOL              fSpeedReported;
    BOOL              fRestartIST;
    BOOL              fExitIST;
    BOOL              attachedState;
    BOOL              sendDataEnd;
    // registry 
    DWORD             dwIOBase;
    DWORD             dwSysIntr;
    DWORD             dwIrq;
    DWORD             dwIOLen;
    DWORD             dwISTPriority;

    EP_STATUS         rgEpStatus[ENDPOINT_COUNT];
    
    PFN_UFN_MDD_NOTIFY      pfnNotify;
    HANDLE                  hBusAccess;
    CEDEVICE_POWER_STATE    cpsCurrent;
} *PCTRLR_PDD_CONTEXT;

#define SC2440_SIG '2440' // "SC2440" signature

#define IS_VALID_SC2440_CONTEXT(ptr) \
    ( (ptr != NULL) && (ptr->dwSig == SC2440_SIG) )


#ifdef DEBUG

#define ZONE_POWER           DEBUGZONE(8)

UFN_GENERATE_DPCURSETTINGS(UFN_DEFAULT_DPCURSETTINGS_NAME, 
    _T("Power"), _T(""), _T(""), _T(""), 
    DBG_ERROR | DBG_INIT); 

// Validate the context.
static
VOID
ValidateContext(
                PCTRLR_PDD_CONTEXT pContext
                )
{
    PREFAST_DEBUGCHK(pContext);
    DEBUGCHK(pContext->dwSig == SC2440_SIG);
    DEBUGCHK(!pContext->hevInterrupt || pContext->hIST);
    DEBUGCHK(VALID_DX(pContext->cpsCurrent));
    DEBUGCHK(pContext->pfnNotify);
}

#else
#define ValidateContext(ptr)
#endif

volatile BYTE *g_pUDCBase;

#define CTRLR_BASE_REG_ADDR(offset) ((volatile ULONG*) ( (g_pUDCBase) + (offset)))


// Read a register.
inline
BYTE
ReadReg(
        PCTRLR_PDD_CONTEXT pContext,
        DWORD dwOffset
        )
{
    DEBUGCHK(IS_VALID_SC2440_CONTEXT(pContext));

    volatile ULONG *pbReg = CTRLR_BASE_REG_ADDR(dwOffset);
    BYTE bValue = (BYTE) *pbReg;
    return bValue;
}


// Write a register.
inline
VOID
WriteReg(
         PCTRLR_PDD_CONTEXT pContext,
         DWORD dwOffset,
         BYTE bValue
         )
{
    DEBUGCHK(IS_VALID_SC2440_CONTEXT(pContext));

    volatile ULONG *pbReg = CTRLR_BASE_REG_ADDR(dwOffset);
    *pbReg = (ULONG) bValue;
}



// Calling with dwMask = 0 and SET reads and writes the contents unchanged.
inline
BYTE
SetClearReg(
            PCTRLR_PDD_CONTEXT pContext,
            DWORD dwOffset,
            BYTE dwMask,
            BOOL  bSet
            )
{
    DEBUGCHK(IS_VALID_SC2440_CONTEXT(pContext));

    volatile ULONG *pbReg = CTRLR_BASE_REG_ADDR(dwOffset);
    BYTE bValue = (BYTE) *pbReg;

    if (bSet) {
        bValue |= dwMask;
    }
    else {
        bValue &= ~dwMask;
    }

    *pbReg = bValue;

    return bValue;
}
// Calling with dwMask = 0 and SET reads and writes the contents unchanged.
inline
BYTE
SetClearIndexedReg(
                   PCTRLR_PDD_CONTEXT pContext,
                   DWORD dwEndpoint,
                   DWORD dwOffset,
                   BYTE dwMask,
                   BOOL  bSet
                   )
{
    DEBUGCHK(IS_VALID_SC2440_CONTEXT(pContext));
    BYTE bValue = 0;


    EnterCriticalSection(&pContext->csIndexedRegisterAccess);
    // Write the EP number to the index reg
    WriteReg(pContext, IDXADDR_REG_OFFSET, (BYTE) dwEndpoint);    
    // Now Write the Register associated with this Endpoint for a given offset
    bValue = SetClearReg(pContext, dwOffset, dwMask, bSet);
    LeaveCriticalSection(&pContext->csIndexedRegisterAccess);

    return bValue;
}
#define SET   TRUE
#define CLEAR FALSE



// Read an indexed register.
inline
BYTE
ReadIndexedReg(
               PCTRLR_PDD_CONTEXT pContext,
               DWORD dwEndpoint,
               DWORD regOffset
               )
{
    DEBUGCHK(IS_VALID_SC2440_CONTEXT(pContext));

    EnterCriticalSection(&pContext->csIndexedRegisterAccess);
    // Write the EP number to the index reg
    WriteReg(pContext, IDXADDR_REG_OFFSET, (BYTE) dwEndpoint);
    // Now Read the Register associated with this Endpoint for a given offset
    BYTE bValue = ReadReg(pContext, regOffset);
    LeaveCriticalSection(&pContext->csIndexedRegisterAccess);
    return bValue;
}


// Write an indexed register.
inline
VOID
WriteIndexedReg(
                PCTRLR_PDD_CONTEXT pContext,
                DWORD dwIndex,
                DWORD regOffset,
                BYTE  bValue
                )
{  
    DEBUGCHK(IS_VALID_SC2440_CONTEXT(pContext));

    EnterCriticalSection(&pContext->csIndexedRegisterAccess);
    // Write the EP number to the index reg
    WriteReg(pContext, IDXADDR_REG_OFFSET, (BYTE) dwIndex);    
    // Now Write the Register associated with this Endpoint for a given offset
    WriteReg(pContext, regOffset, bValue);
    LeaveCriticalSection(&pContext->csIndexedRegisterAccess);
}

/*++

Routine Description:

Return the data register of an endpoint.

Arguments:

dwEndpoint - the target endpoint

Return Value:

The data register of the target endpoint.

--*/
static
volatile ULONG*
_GetDataRegister(
                 DWORD        dwEndpoint    
                 )
{
    volatile ULONG *pulDataReg = NULL;

    //
    // find the data register (non-uniform offset)
    //
    switch (dwEndpoint) {
        case  0: pulDataReg = CTRLR_BASE_REG_ADDR(EP0_FIFO_REG_OFFSET);  break;
        case  1: pulDataReg = CTRLR_BASE_REG_ADDR(EP1_FIFO_REG_OFFSET);  break;
        case  2: pulDataReg = CTRLR_BASE_REG_ADDR(EP2_FIFO_REG_OFFSET);  break;
        case  3: pulDataReg = CTRLR_BASE_REG_ADDR(EP3_FIFO_REG_OFFSET);  break;
        case  4: pulDataReg = CTRLR_BASE_REG_ADDR(EP4_FIFO_REG_OFFSET);  break;
        default:
            DEBUGCHK(FALSE);
            break;
    }

    return pulDataReg;
} // _GetDataRegister


// Retrieve the endpoint status structure.
inline
static
PEP_STATUS
GetEpStatus(
            PCTRLR_PDD_CONTEXT pContext,
            DWORD dwEndpoint
            )
{
    ValidateContext(pContext);
    DEBUGCHK(EP_VALID(dwEndpoint));

    PEP_STATUS peps = &pContext->rgEpStatus[dwEndpoint];

    return peps;
}


// Return the irq bit for this endpoint.
inline
static
BYTE
EpToIrqStatBit(
               DWORD dwEndpoint
               )
{
    DEBUGCHK(EP_VALID(dwEndpoint));

    return (1 << (BYTE)dwEndpoint);
}

/*++

Routine Description:

Enable the interrupt of an endpoint.

Arguments:

dwEndpoint - the target endpoint

Return Value:

None.

--*/
static
VOID
EnableEndpointInterrupt(
                        PCTRLR_PDD_CONTEXT pContext,
                        DWORD        dwEndpoint
                        )
{    
    SETFNAME();
    FUNCTION_ENTER_MSG();

    // End Point Zero is always enabled (after Run)
    if (dwEndpoint == 0) {
        FUNCTION_LEAVE_MSG();
        return;
    }

    // Disable the Endpoint Interrupt
    BYTE irqEnBit = EpToIrqStatBit(dwEndpoint);
    SetClearReg(pContext, EP_INT_EN_REG_OFFSET, irqEnBit, SET);

    FUNCTION_LEAVE_MSG();          
} // _EnableEpInterrupt


/*++

Routine Description:

Disable the interrupt of an endpoint.

Arguments:

dwEndpoint - the target endpoint

Return Value:

None.

--*/
static
VOID
DisableEndpointInterrupt(
                         PCTRLR_PDD_CONTEXT pContext,
                         DWORD        dwEndpoint
                         )
{    
    SETFNAME();
    FUNCTION_ENTER_MSG();

    // End Point Zero is always enabled (after Run)
    if (dwEndpoint == 0) {
        FUNCTION_LEAVE_MSG();
        return;
    }

    // Enable the Endpoint Interrupt
    BYTE irqEnBit = EpToIrqStatBit(dwEndpoint);
    SetClearReg(pContext, EP_INT_EN_REG_OFFSET, irqEnBit, CLEAR);

⌨️ 快捷键说明

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