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

📄 triton.c

📁 Windows CE 6.0 BSP for the Beagle Board.
💻 C
📖 第 1 页 / 共 2 页
字号:
                    L"IOCTL_DDK_GET_DRIVER_IFC can be called only from "
                    L"device process (caller process id 0x%08x)\r\n",
                    GetCallerProcess()
                    ));
                SetLastError(ERROR_ACCESS_DENIED);
                break;
                }
            // Check input parameters
            if ((pInBuffer == NULL) || (inSize < sizeof(GUID)))
                {
                SetLastError(ERROR_INVALID_PARAMETER);
                break;
                }
            if (IsEqualGUID(pInBuffer, &DEVICE_IFC_TWL_GUID))
                {
                if (pOutSize != NULL) *pOutSize = sizeof(DEVICE_IFC_TWL);
                if (pOutBuffer == NULL || outSize < sizeof(DEVICE_IFC_TWL))
                    {
                    SetLastError(ERROR_INVALID_PARAMETER);
                    break;
                    }
                ifc.context = context;
                ifc.pfnReadRegs = TWL_ReadRegs;
                ifc.pfnWriteRegs = TWL_WriteRegs;
                ifc.pfnSetIntrEvent = TWL_SetIntrEvent;
                ifc.pfnIntrEnable = TWL_IntrEnable;
                ifc.pfnIntrDisable = TWL_IntrDisable;
                if (!CeSafeCopyMemory(pOutBuffer, &ifc, sizeof(DEVICE_IFC_TWL)))
                    {
                    SetLastError(ERROR_INVALID_PARAMETER);
                    break;
                    }
                rc = TRUE;
                break;
                }
            SetLastError(ERROR_INVALID_PARAMETER);
            break;
        case IOCTL_TWL_READREGS:
            if ((pInBuffer == NULL) || 
                (inSize < sizeof(IOCTL_TWL_READREGS_IN)))
                {
                SetLastError(ERROR_INVALID_PARAMETER);
                break;
                }
            address = ((IOCTL_TWL_READREGS_IN*)pInBuffer)->address;
            size = ((IOCTL_TWL_READREGS_IN*)pInBuffer)->size;
            if (pOutSize != NULL) *pOutSize = size;
            if ((pOutBuffer == NULL) || (outSize < size))
                {
                SetLastError(ERROR_INVALID_PARAMETER);
                break;
                }
            rc = ReadRegs(pDevice, address, pOutBuffer, size);
            break;
        case IOCTL_TWL_WRITEREGS:
            if ((pInBuffer == NULL) || 
                (inSize < sizeof(IOCTL_TWL_WRITEREGS_IN)))
                {
                SetLastError(ERROR_INVALID_PARAMETER);
                break;
                }
            address = ((IOCTL_TWL_WRITEREGS_IN*)pInBuffer)->address;
            size = ((IOCTL_TWL_WRITEREGS_IN*)pInBuffer)->size;
            if (inSize < (sizeof(IOCTL_TWL_WRITEREGS_IN) + size))
                {
                SetLastError(ERROR_INVALID_PARAMETER);
                break;
                }
            ((IOCTL_TWL_WRITEREGS_IN*)pInBuffer)++;
            rc = WriteRegs(pDevice, address, pInBuffer, size);
            break;
        }

cleanUp:
    DEBUGMSG(ZONE_FUNCTION, (L"-TWL_IOControl(rc = %d)\r\n", rc));
    return rc;
}

//------------------------------------------------------------------------------
//
//  Function:  TWL_InterruptThread
//
//  This function acts as the IST for the external irq.
//
DWORD
TWL_IntrThread(
    VOID *pContext
    )
{
    Device_t *pDevice = (Device_t*)pContext;
    DWORD id;
    UINT16 status;
    UINT16 currMask;

    // Loop until we are stopped...
    while (!pDevice->intrThreadExit) {
        // Wait for event
        WaitForSingleObject(pDevice->hIntrEvent, INFINITE);
        if (pDevice->intrThreadExit) break;

        // Get interrupt status register
        if (GetTritonIrqStatus(pDevice, &status) && GetTritonIrqMask(pDevice, &currMask)) {
            // Diable all interrupts
            SetTritonIrqMask(pDevice, status);

            // Process each unmasked interrupt
            status &= ~currMask;
            id = 0;
            while (status != 0) {
                if ((status & 0x0001) != 0) {
                    if (pDevice->hSetIntrEvent[id] != NULL) {
                        SetEvent(pDevice->hSetIntrEvent[id]);
                    }

                    // If this is a RTC alarm interrupt, let oal handle the interrupt.
                    if (id == TWL_INTR_RTCALM) {
                        KernelIoControl(IOCTL_HAL_RTC_ALARM, NULL, 0, NULL, 0, NULL);
                    }
                }
                status >>= 1;
                id++;
            }
        }
        // Set fake interrupt event
        if (pDevice->hSetIntrEvent[16] != NULL) {
            // Use pulse event there in case that event is already
            // signaled as associated with some interrupt...
            PulseEvent(pDevice->hSetIntrEvent[16]);
        }
        
        InterruptDone(pDevice->sysIntr);
    }

    return ERROR_SUCCESS;
}

//------------------------------------------------------------------------------
//
static
BOOL
TWL_ReadRegs(
    DWORD context, 
    DWORD address,
    UCHAR *pBuffer,
    DWORD size
    )
{
    BOOL rc = FALSE;
    Device_t *pDevice = (Device_t*)context;

    // Check if we get correct context
    if ((pDevice == NULL) || (pDevice->cookie != TWL_DEVICE_COOKIE))
        {
        DEBUGMSG(ZONE_ERROR, (L"ERROR: TWL_ReadRegs: "
            L"Incorrect context parameter\r\n"
            ));
        goto cleanUp;
        }

    rc = ReadRegs(pDevice, address, pBuffer, size);
    
cleanUp:
    return rc;
}

//------------------------------------------------------------------------------

static
BOOL
TWL_WriteRegs(
    DWORD context, 
    DWORD address,
    const UCHAR *pBuffer,
    DWORD size
    )
{
    BOOL rc = FALSE;
    Device_t *pDevice = (Device_t*)context;

    // Check if we get correct context
    if ((pDevice == NULL) || (pDevice->cookie != TWL_DEVICE_COOKIE))
        {
        DEBUGMSG(ZONE_ERROR, (L"ERROR: TWL_WriteRegs: "
            L"Incorrect context parameter\r\n"
            ));
        goto cleanUp;
        }

    rc = WriteRegs(pDevice, address, pBuffer, size);
    
cleanUp:
    return rc;
}


//------------------------------------------------------------------------------
// This function allows child drivers to register event to triton driver.
// When interrupt happends, triton driver will trigger the related event.
//
static
BOOL
TWL_SetIntrEvent(
    DWORD context,
    DWORD intrId,
    HANDLE hEvent
    )
{
    BOOL rc = FALSE;
    Device_t *pDevice = (Device_t*)context;

    // Check if we get correct context
    if ((pDevice == NULL) || (pDevice->cookie != TWL_DEVICE_COOKIE)) {
        DEBUGMSG(ZONE_ERROR, (L"ERROR: TWL_SetIntrEvent: "
            L"Incorrect context parameter\r\n"
            ));
        goto cleanUp;
    }

    if ((intrId > 16) && (intrId != (-1))) {
        DEBUGMSG(ZONE_ERROR, (L"ERROR: TWL_SetIntrEvent: "
            L"Incorrect interrupt Id %d\r\n", intrId
            ));
        goto cleanUp;
    }

    // Common interrupt is stored in last position
    if (intrId == (-1)) intrId = 16;

    // If handle isn't NULL we set new association, 
    // otherwise we delete it....
    if (hEvent != NULL) {
        if (pDevice->hSetIntrEvent[intrId] != NULL) {
            DEBUGMSG(ZONE_ERROR, (L"ERROR: TWL_SetIntrEvent: "
                L"Interrupt Id %d already associated with event\r\n"
                ));
            goto cleanUp;
        }
        rc = DuplicateHandle(
            GetCurrentProcess(), hEvent, GetCurrentProcess(),
            &pDevice->hSetIntrEvent[intrId], 0, FALSE, DUPLICATE_SAME_ACCESS
            );

        if (!rc) {
            DEBUGMSG(ZONE_ERROR, (L"ERROR: TWL_SetIntrEvent: "
                L"Event handler duplication failed\r\n"
                ));
            goto cleanUp;
        }
    }
    else {
        if (pDevice->hSetIntrEvent[intrId] == NULL) {
            DEBUGMSG(ZONE_ERROR, (L"ERROR: TWL_SetIntrEvent: "
                L"Interrupt Id %d isn't associated with event\r\n"
                ));
            goto cleanUp;
        }
        rc = CloseHandle(pDevice->hSetIntrEvent[intrId]);
        pDevice->hSetIntrEvent[intrId] = NULL;
    }
            
cleanUp:
    return rc;
}

//------------------------------------------------------------------------------
// Child driver can call this function to enable the sub interrupt.
//
static
BOOL 
TWL_IntrEnable(
    DWORD context, 
    DWORD intrId
    )
{
    BOOL rc = FALSE;
    Device_t *pDevice = (Device_t*)context;
    BYTE   mask;
    BYTE   offset;

    // Check if we get correct context
    if ((pDevice == NULL) || (pDevice->cookie != TWL_DEVICE_COOKIE)) {
        DEBUGMSG(ZONE_ERROR, (L"ERROR: TWL_IntrEnable: "
            L"Incorrect context parameter\r\n"
            ));
        goto cleanUp;
    }

    if (intrId > 16)
        {
        DEBUGMSG(ZONE_ERROR, (L"ERROR: TWL_IntrEnable: "
            L"Incorrect interrupt Id %d\r\n", intrId
            ));
        goto cleanUp;
        }

    // We have take critical section there to avoid concurrent
    // enable register modification

    if (intrId < 8) {
        offset = MENELAUS_INTMASK1_OFFSET;
    }
    else {
        offset = MENELAUS_INTMASK2_OFFSET;
        intrId -= 8;
    }

    EnterCriticalSection(&pDevice->cs);

    // Get actual mask
    if (!ReadRegs(pDevice, offset, &mask, sizeof(mask))) {
        goto cleanUp;
    }

    // Enable interrupt
    mask &= ~(1 << intrId);

    // Write it back
    if (!WriteRegs(pDevice, offset, &mask, sizeof(mask))) {
        goto cleanUp;
    }

    rc = TRUE;
    
cleanUp:
    LeaveCriticalSection(&pDevice->cs);
    return rc;
}

//------------------------------------------------------------------------------
// Child driver can call this fucntion to disable the sub interrupt.
//
static
BOOL 
TWL_IntrDisable(
    DWORD context, 
    DWORD intrId
    )
{
    BOOL rc = FALSE;
    Device_t *pDevice = (Device_t*)context;
    BYTE   mask;
    BYTE   offset;

    // Check if we get correct context
    if ((pDevice == NULL) || (pDevice->cookie != TWL_DEVICE_COOKIE)) {
        DEBUGMSG(ZONE_ERROR, (L"ERROR: TWL_IntrDisable: "
            L"Incorrect context parameter\r\n"
            ));
        goto cleanUp;
    }

    if (intrId > 16)
        {
        DEBUGMSG(ZONE_ERROR, (L"ERROR: TWL_IntrDisable: "
            L"Incorrect interrupt Id %d\r\n", intrId
            ));
        goto cleanUp;
        }
    
    if (intrId < 8)
        {
        offset = MENELAUS_INTMASK1_OFFSET;
        }
    else
        {
        offset = MENELAUS_INTMASK2_OFFSET;
        intrId -= 8;
        }

    // We have take critical section there to avoid concurrent
    // enable register modification
    EnterCriticalSection(&pDevice->cs);

    // Get actual mask
    if (!ReadRegs(pDevice, offset, &mask, sizeof(mask))) {
        goto cleanUp;
    }

    // Disable interrupt
    mask |= (1 << intrId);

    // Write it back
    if (!WriteRegs(pDevice, offset, &mask, sizeof(mask))) {
        goto cleanUp;
    }

    rc = TRUE;
    
cleanUp:
    LeaveCriticalSection(&pDevice->cs);
    return rc;
}

//------------------------------------------------------------------------------


//------------------------------------------------------------------------------

BOOL
ReadRegs(
    Device_t *pDevice,
    DWORD address,
    UCHAR *pBuffer,
    DWORD size
    )
{
    I2CTRANS trans;

    ZeroMemory(&trans,sizeof(trans));

    trans.mClk_HL_Divisor = I2C_CLOCK_100Khz;
    /* first write register address */
    trans.mOpCode[0] = I2C_OPCODE_WRITE;
    trans.mBufferOffset[0] = 0;
    trans.mTransLen[0] = 1;
    trans.mBuffer[0] = (BYTE)address;
    /* then read back data from that address */
    trans.mOpCode[1] = I2C_OPCODE_READ;
    trans.mBufferOffset[1] = 0;
    trans.mTransLen[1] = 1;

    I2CTransact(pDevice->hI2C, &trans);

    *pBuffer = trans.mBuffer[0];

    return (trans.mErrorCode == 0);
}

//------------------------------------------------------------------------------

BOOL
WriteRegs(
    Device_t *pDevice,
    DWORD address,
    const UCHAR *pBuffer,
    DWORD size
    )
{
    I2CTRANS trans;

    ZeroMemory(&trans,sizeof(trans));
    
    trans.mClk_HL_Divisor = I2C_CLOCK_100Khz;

    /* just write the register # then the data in one shot */
    trans.mOpCode[0] = I2C_OPCODE_WRITE;
    trans.mBufferOffset[0] = 0;
    trans.mTransLen[0] = 2;
    trans.mBuffer[0] = (BYTE)address;
    trans.mBuffer[1] = ((UCHAR*)pBuffer)[0];

    I2CTransact(pDevice->hI2C, &trans);

    return (trans.mErrorCode == 0);
}


//------------------------------------------------------------------------------
//
//  Function:  DllMain
//
//  Standard Windows DLL entry point.
//
BOOL
__stdcall
DllMain(
    HANDLE hDLL,
    DWORD reason,
    VOID *pReserved
    )
{
    switch (reason)
        {
        case DLL_PROCESS_ATTACH:
            DEBUGREGISTER(hDLL);
            DisableThreadLibraryCalls((HMODULE)hDLL);
            break;
        }
    return TRUE;
}

//------------------------------------------------------------------------------

⌨️ 快捷键说明

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