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

📄 pl011pdd.c

📁 ARM9基于WINDOWSCE的BSP源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
*   The content of this file or document is CONFIDENTIAL and PROPRIETARY
*   to Jade Technologies Co., Ltd.  It is subjected to the terms of a
*   License Agreement between Licensee and Jade Technologies Co., Ltd.
*   restricting among other things, the use, reproduction, distribution
*   and transfer.  Each of the embodiments, including this information 
*   and any derivative work shall retain this copyright notice.
* 
*   Copyright (c) 2004 - 2005 Jade Technologies Co., Ltd. 
*   All rights reserved.
*/
// ----------------------------------------------------------------
// File:     PL011pdd.c,v
// Revision: 1.2
// ----------------------------------------------------------------
// $
//
// NOTE:
//      This code contains code to support DMA. This is untested
//       and is left here as an example only.
//

#include <windows.h>    // Main include file for Windows development
#include <ceddk.h>      // CE device driver types, constants, and functions
#include <devload.h>    // Device loader structures and defines (OpenDeviceKey API)
#include <serhw.h>      // Hardware-independent structures, defines and interfaces (HW_VTBL, HWOBJ)
#include <serdbg.h>     // Serial device driver debug zone definitions
#include <dma.h>
#include <platform.h>
#include <board.h>
#include <oalintr.h>

#include "PL011api.h"   // PL011 UART API
#include "PL011.h"      // PL011 UART register and bit definitions

// Watermark info
const PTCHAR part_name = { TEXT("Windows CE  UART Device Driver") };
const PTCHAR part_num = { TEXT("OS005-SW-70002-r0p0-00REL0") }; 

// PL011 serial device driver registry value names (all DWORDs)
//
#define REG_DEVINDEX_VAL_NAME       TEXT("DeviceArrayIndex") 
#define REG_IOBASE_VAL_NAME         TEXT("IoBase")
#define REG_SYSINTR_VAL_NAME        TEXT("SysIntr")
#define REG_DMA_VAL_NAME            TEXT("DMA")
#define REG_COM_ID                  TEXT("Order")

// DEBUGMSG helper macros
//
#define DRV_PREFIX                  TEXT("COM")
#define MSG_PREFIX                  TEXT(" ") DRV_PREFIX TEXT(": ")
#define MSG_SUFFIX                  TEXT("\r\n")

#define HEAD_TEXT(msg)              (MSG_PREFIX TEXT("+") TEXT(##msg) MSG_SUFFIX)
#define BODY_TEXT(msg)              (MSG_PREFIX TEXT(" ") TEXT(##msg) MSG_SUFFIX)
#define TAIL_TEXT(msg)              (MSG_PREFIX TEXT("-") TEXT(##msg) MSG_SUFFIX)

#define SUCCEEDED_OR_FAILED(exp)    ((exp) ? TEXT("SUCCEEDED") : TEXT("FAILED"))

#ifndef MIN
    #define MIN(x,y)        ((x) < (y) ? (x) : (y))
#endif

// Types

// Serial event callback type
//
typedef VOID (*EVENT_FUNC)(VOID *pMDDContext, ULONG fEvents);

//UART DMA struct
typedef struct tagUART_DMAInfo {
    DWORD               OpenCnt;    // @field Protects use of this port
//Rx
    HANDLE              hRxUDmaISTEvent;
    DWORD               dwRxDMASysIntr;
    UCHAR               ucRxDMAChannel;
    PDWORD              pdwRxDestPageList;
    PVOID               pvRxDestBuffer;
    DWORD               dwRxDestSize;

//Tx
    HANDLE              hTxUDmaISTEvent;
    DWORD               dwTxDMASysIntr;
    UCHAR               ucTxDMAChannel;
    PDWORD              pdwTxSourcePageList;
    PVOID               pvTxSourceBuffer;
    DWORD               dwTxSourceSize;
}UART_DMA_INFO, *PUART_DMA_INFO;
//End of UART DMA struct

//UART ID to connect to DMA
#define UART0_Rx_ID         5
#define UART0_Tx_ID         6
#define UART1_Rx_ID         3
#define UART1_Tx_ID         4
//UART Rx FIFO Watermark
#define UART_FIFO_Rx_LEVEL  12

// PDD context type
//
typedef struct tagPDD_CONTEXT
{
    VOID                *pMDDContext;       // First argument in MDD callbacks.
    HWOBJ               *pHWObj;            // The MDD doesn't free the HWOBJ, we have to
    PL011_CONTEXT       *pPL011;            // PL011 (UART) context (for PL011 API)

    PUCHAR              pBaseAddress;       // Start of serial registers - mapped

    HANDLE              hevTxReady;         // Event object for signalling transmitter ready / not full
    CRITICAL_SECTION    cs;                 // For using this context, thread-safely

    ULONG               nOpenCount;         // Just for debug checks (the MDD manages concurrent opens)
    BOOL                fIRMode;            // IR mode (FALSE or TRUE)

    COMMPROP            CommProp;           // COMMPROP (Comm Properties) structure
    DCB                 dcb;                // DCB (Device Control Block) structure
    ULONG               fCommErrors;        // Comm error flags

    ULONG               fInterrupts;        // Shadowed interrupt flags, updated by HWGetIntrType
    ULONG               fModemStatus;       // Modem status flags, updated by HWModemIntrHandler
    ULONG               nDroppedBytes;      // Number of dropped bytes
    BOOL                fCTSFlowOff;        // CTS flow control state (flowed-off | not flowed-off)
    BOOL                fDSRFlowOff;        // DSR flow control state (flowed-off | not flowed-off)
    BOOL                fAddTxIntr;         // Force HWGetIntrType to return an INTR_TX

//DMA related members.
    UART_DMA_INFO       uart_DMA_Info;  // struct to store UART-DMA related information
    DWORD               DMA_Enable;     // DMA_UART ON or OFF
    DWORD               ComId;          // which com port is used, 0 or 1?
    BOOL                No_DMA_timeout; // If timeout happens to Rx, disable DMA
} PDD_CONTEXT;


// Public function prototypes (external linkage, called by MDD)

// GetSerialObject is the only function that needs external linkage; it's used in the MDD to get
//  a device-independent function-table for serial port device driver PDDs.
//
PHWOBJ  GetSerialObject(DWORD DeviceArrayIndex);

// Define some internally used functions
BOOL    DMA_Close(PUART_DMA_INFO pOpenHead);



// Private DDSI function prototypes (static linkage)

// These functions are private to the PDD and are invoked by the MDD through a function table (in
//  the HWOBJ returned from GetSerialObject).
//
static PVOID PDD_Init(ULONG Identifier, PVOID pMDDContext, PHWOBJ pHWObj);
static BOOL  PDD_PostInit(PDD_CONTEXT *pPDDContext);
static BOOL  PDD_Deinit(PDD_CONTEXT *pPDDContext);
static BOOL  PDD_Open(PDD_CONTEXT *pPDDContext);
static ULONG PDD_Close(PDD_CONTEXT *pPDDContext);
static INTERRUPT_TYPE PDD_GetIntrType(PDD_CONTEXT *pPDDContext);
static ULONG PDD_RxIntrHandler(PDD_CONTEXT *pPDDContext, PUCHAR pRxBuffer, ULONG *pBuffLen);
static VOID  PDD_TxIntrHandler(PDD_CONTEXT *pPDDContext, PUCHAR pTxBuffer, ULONG *pBuffLen);
static VOID  PDD_ModemIntrHandler(PDD_CONTEXT *pPDDContext);
static VOID  PDD_LineIntrHandler(PDD_CONTEXT *pPDDContext);
static ULONG PDD_GetRxBufferSize(PDD_CONTEXT *pPDDContext);
static BOOL  PDD_PowerOff(PDD_CONTEXT *pPDDContext);
static BOOL  PDD_PowerOn(PDD_CONTEXT *pPDDContext);
static VOID  PDD_ClearDTR(PDD_CONTEXT *pPDDContext);
static VOID  PDD_SetDTR(PDD_CONTEXT *pPDDContext);
static VOID  PDD_ClearRTS(PDD_CONTEXT *pPDDContext);
static VOID  PDD_SetRTS(PDD_CONTEXT *pPDDContext);
static BOOL  PDD_EnableIR(PDD_CONTEXT *pPDDContext, ULONG BaudRate);
static BOOL  PDD_DisableIR(PDD_CONTEXT *pPDDContext);
static VOID  PDD_ClearBreak(PDD_CONTEXT *pPDDContext);
static VOID  PDD_SetBreak(PDD_CONTEXT *pPDDContext);
static BOOL  PDD_XmitComChar(PDD_CONTEXT *pPDDContext, UCHAR ComChar);
static ULONG PDD_GetStatus(PDD_CONTEXT *pPDDContext, LPCOMSTAT lpStat);
static VOID  PDD_Reset(PDD_CONTEXT *pPDDContext);
static VOID  PDD_GetModemStatus(PDD_CONTEXT *pPDDContext, PULONG pModemStatus);
static VOID  PDD_GetCommProperties(PDD_CONTEXT *pPDDContext, LPCOMMPROP lpCommProp);
static VOID  PDD_PurgeComm(PDD_CONTEXT *pPDDContext, DWORD fdwAction);
static BOOL  PDD_SetDCB(PDD_CONTEXT *pPDDContext, LPDCB lpDCB);
static ULONG PDD_SetCommTimeouts(PDD_CONTEXT *pPDDContext, LPCOMMTIMEOUTS lpCommTimeouts);
static BOOL  PDD_Ioctl(PDD_CONTEXT *pPDDContext,
                       DWORD dwCode,
                       PBYTE pBufIn,
                       DWORD dwLenIn,
                       PBYTE pBufOut,
                       DWORD dwLenOut,
                       PDWORD pdwActualOut);


// Private, implementation, function prototypes
//
static BOOL ProcessLineStatus(PDD_CONTEXT *pPDDContext, ULONG fLineStatus);
static LONG GetRegistryData(LPCTSTR szKey, DWORD *pdwIOBase, DWORD *pdwSysIntr, DWORD *ComId, DWORD *DMA_Enable);


// Inline helpers
//
__inline static LONG GetRegistryDWORD(HKEY hKey, LPCTSTR szValueName, DWORD *pdwValue)
{
    DWORD dwDataSize = sizeof(DWORD);

    return RegQueryValueEx(hKey,
                           szValueName,
                           NULL,
                           NULL,
                           (LPBYTE)pdwValue,
                           &dwDataSize);
}


// Virtual-function table (DDSI) for serial port PDD (used by serial MDD)
//
static const HW_VTBL VTbl =
{
    PDD_Init,
    PDD_PostInit,
    PDD_Deinit,
    PDD_Open,
    PDD_Close,
    PDD_GetIntrType,
    PDD_RxIntrHandler,
    PDD_TxIntrHandler,
    PDD_ModemIntrHandler,
    PDD_LineIntrHandler,
    PDD_GetRxBufferSize,
    PDD_PowerOff,
    PDD_PowerOn,
    PDD_ClearDTR,
    PDD_SetDTR,
    PDD_ClearRTS,
    PDD_SetRTS,
    PDD_EnableIR,
    PDD_DisableIR,
    PDD_ClearBreak,
    PDD_SetBreak,
    PDD_XmitComChar,
    PDD_GetStatus,
    PDD_Reset,
    PDD_GetModemStatus,
    PDD_GetCommProperties,
    PDD_PurgeComm,
    PDD_SetDCB,
    PDD_SetCommTimeouts,
    PDD_Ioctl
};


// The MDD calls GetSerialObject to get a device-independent function table, filled with device-
//  dependent function pointers; this enables a single MDD to be used for different PDDs.
//
PHWOBJ GetSerialObject(DWORD DeviceArrayIndex)
{
    HWOBJ *pSerObj;

    // Unlike many other serial samples, we do not have a statically allocated array of HWObjs.
    //  Instead, we allocate a new HWObj for each instance of the driver. The MDD will always call
    //  GetSerialObject/HWInit/HWDeinit in that order, so we can do the alloc here and do any
    //  subsequent free in HWDeInit.

    // Allocate space for the HWOBJ (no need to use LPTR or LMEM_ZEROINIT to initialise the memory
    //  to zero because we will be explicitly initialising each member of the open context next).
    //
    pSerObj = (HWOBJ*)LocalAlloc(LMEM_FIXED , sizeof(HWOBJ));
    if (pSerObj == NULL)
        return NULL;

    // Fill in the HWObj structure that we just allocated.
    //
    if ( DeviceArrayIndex == 0 )
    	{
    pSerObj->BindFlags = THREAD_AT_OPEN;    // Have MDD create thread when device is first opened
    pSerObj->dwIntID   = SYSINTR_UNDEFINED; // HWInit sets this field with the actual SYSINTR value
    pSerObj->pFuncTbl  = (HW_VTBL*)&VTbl;   // Return pointer to appropriate functions
    	}
else if ( DeviceArrayIndex == 1 )
		{
    pSerObj->BindFlags = THREAD_AT_OPEN;    // Have MDD create thread when device is first opened
    pSerObj->dwIntID   = SYSINTR_UNDEFINED; // HWInit sets this field with the actual SYSINTR value
    pSerObj->pFuncTbl  = (HW_VTBL*)&VTbl;   // Return pointer to appropriate functions
    	}
    // Now return this structure to the MDD.
    //
    return pSerObj;
}


PVOID PDD_Init(ULONG Identifier, PVOID pMDDContext, PHWOBJ pHWObj)
{
    PDD_CONTEXT *pPDDContext = NULL;
    LONG  lRC;
    DWORD dwIOBase;
    LPVOID pBaseAddr;

    DEBUGMSG(ZONE_INIT | ZONE_FUNCTION,
        (HEAD_TEXT("PDD_Init(\"%s\", %#08x, %#08x)"), (LPCTSTR)Identifier, pMDDContext, pHWObj));

    DEBUGMSG( TRUE, (TEXT("MODULE NAME: %s\r\n"),part_name) );
    DEBUGMSG( TRUE, (TEXT("MODULE VERSION: %s\r\n"),part_num) );

	RETAILMSG( TRUE, (TEXT("MODULE NAME: %s\r\n"),part_name) );
{
//pin mux		
		PHYSICAL_ADDRESS PhysicalIoBase;
		volatile unsigned long *GPIO_ADD;
		PhysicalIoBase.HighPart = 0;
		PhysicalIoBase.LowPart = 0x2002B420;
		GPIO_ADD = (unsigned long *)MmMapIoSpace( PhysicalIoBase, 0x100 ,FALSE );
		RETAILMSG(0,(TEXT("GPIO_ADD = 0x%x\r\n"),GPIO_ADD));

		*(volatile long *)GPIO_ADD	|= 0xF0;		
 
	}

    if ((Identifier == 0) || (pMDDContext == NULL) || (pHWObj == NULL))
        goto exit_point;

    // Allocate space for the PDD context (using LMEM_ZEROINIT will ensure Deinit doesn't mistake
    //  any uninitialised members for valid objects, should Init fail)
    //
    pPDDContext = (PDD_CONTEXT*)LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, sizeof(PDD_CONTEXT));
    if (pPDDContext == NULL)
        goto exit_point;

    pPDDContext->pMDDContext = pMDDContext;
    pPDDContext->pHWObj      = pHWObj;
    pPDDContext->pBaseAddress = NULL;

    if ((lRC = GetRegistryData((LPCTSTR)Identifier, &dwIOBase, &pHWObj->dwIntID,
        &pPDDContext->ComId, &pPDDContext->DMA_Enable)) != ERROR_SUCCESS)
    {
        DEBUGMSG(ZONE_INIT | ZONE_ERROR,
            (BODY_TEXT("PDD_Init: Failed to get registry data [error = %d]"), lRC));
        goto fail_point;
    }

    // New for .NET we need to VirtualAlloc/VirtualCopy the IO addresses as the system
    //  protection has increased - we can't use just the OEMAddressTable mappings
    if (!(pBaseAddr = VirtualAlloc (NULL, 0x1000, MEM_RESERVE, PAGE_NOACCESS)))
    {
        DEBUGMSG(ZONE_INIT | ZONE_ERROR, (BODY_TEXT("PDD_Init: VirtualAlloc Failed")));
        goto fail_point;
    }

    if (!VirtualCopy (pBaseAddr, (LPVOID)dwIOBase, 0x1000, PAGE_READWRITE | PAGE_NOCACHE))
    {
        DEBUGMSG(ZONE_INIT | ZONE_ERROR, (BODY_TEXT("PDD_Init: VirtualCopy Failed")));
        VirtualFree (pBaseAddr, 0, MEM_RELEASE);
        goto fail_point;
    }

    pPDDContext->pBaseAddress = pBaseAddr;

    if ((pPDDContext->pPL011 = PL011Create((ULONG)pBaseAddr)) == NULL)
    {
        DEBUGMSG(ZONE_INIT | ZONE_ERROR,
            (BODY_TEXT("PDD_Init: Failed to create PL011 context")));
        goto fail_point;
    }

    if ((pPDDContext->hevTxReady = CreateEvent(0, FALSE, FALSE, NULL)) == NULL)
    {
        DEBUGMSG(ZONE_INIT | ZONE_ERROR,
            (BODY_TEXT("PDD_Init: Failed to create Win32 event object")));
        goto fail_point;
    }

    // For using this context, thread-safely
    //
    InitializeCriticalSection(&(pPDDContext->cs));

    pPDDContext->nOpenCount  = 0;       // Just for debug checks (the MDD manages concurrent opens)
    pPDDContext->fIRMode     = FALSE;   // Select wired by default

    // Set up our Comm Properties data
    //
    pPDDContext->CommProp.wPacketLength       = 0xFFFF;
    pPDDContext->CommProp.wPacketVersion      = 0xFFFF;

⌨️ 快捷键说明

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