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

📄 pdd.c

📁 基于AU1200的CPLD的wince下的驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
// Copyright (c) 2004 BSQUARE 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.
//
#include <windows.h>
#include <bceddk.h>
#include <ddkreg.h>
#define USE_NEW_SERIAL_MODEL
#include <serhw.h>
#include <serdbg.h>
#include "platform.h"
#include "pdd.h"
#include <gpio.h>    // SmartOne add
#include "ldrarg.h"  // SmartOne add


//------------------------------------------------------------------------------
// Grobal variable

BOOL bTxIntEn;       // SmartOne add
//------------------------------------------------------------------------------


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

//#define UART_INTEN_TX_OFF  (UART_INTEN_LIE|UART_INTEN_RIE|UART_INTEN_MIE)  // SmartOne del
////#define UART_INTEN_TX_OFF  (UART_INTEN_LIE|UART_INTEN_RIE)    // SmartOne add // 我们只使用TX,RX,GPIO9 10设为通用的GPIO,所以MIE改须去掉
////#define UART_INTEN_TX_ON   (UART_INTEN_TX_OFF|UART_INTEN_TIE)
#define UART_INTEN_TX_OFF  (RX_INT_ENB_BIT)    
#define UART_INTEN_TX_ON   (TX_INT_ENB_BIT|RX_INT_ENB_BIT)

#define ENABLE_TX_INT(pCpld)         {pCpld->uartIntEnable = UART_INTEN_TX_ON; bTxIntEn = TRUE;}
#define DISABLE_TX_INT(pCpld)        {pCpld->uartIntEnable = UART_INTEN_TX_OFF; bTxIntEn = FALSE;}
#define DISABLE_ALL_INT(pCpld)       {pCpld->uartIntEnable &= ~UART_INTEN_TX_ON; bTxIntEn = FALSE;}


#define INP32(a)           ((UCHAR)READ_PORT_ULONG((ULONG*)(a)))
#define OUT32(a, v)        WRITE_PORT_ULONG((ULONG*)(a), (v))

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

typedef struct {
	//AU1X00_UART *pPortBase;                    // Mapped virtual address of uart ports
	CPLD *pPortBase;                    // Mapped virtual address of uart ports
	ULONG irq;                          // IRQ readed from registry
	ULONG sysIntr;                      // Assigned SYSINTR

	PVOID pMdd;                         // MDD context

	BOOL  open;                         // Is device open?
	DCB   dcb;                          // Serial port DCB

	ULONG commErrors;                   // How many errors occured
	ULONG overrunCount;                 // How many chars was missed

	ULONG txFifoLength;                 // TX FIFO length
	ULONG txFifoThresh;                 // TX FIFO threshold
	ULONG rxFifoLength;                 // RX FIFO length (not used...)
	ULONG rxFifoThresh;                 // RX FIFO threshold (not used...)

	BOOL  powerOff;                     // Are we power-off?
	UCHAR fifoCtrl;                     // fifoctrl register on power-off
	UCHAR lineCtrl;                     // linectrl register on power-off
	UCHAR mdmCtrl;                      // mdmctrl register on power-off
	UCHAR clkDiv;                       // clckdiv register on power-off

	BOOL  addTxIntr;                    // Should we add software TX interrupt?
	BOOL  flowOffCTS;                   // Is CTS down?
	BOOL  flowOffDSR;                   // Is DSR down?

	CRITICAL_SECTION hwCS;              // Guard access to HW registers
	CRITICAL_SECTION txCS;              // Guard HWXmitComChar
	HANDLE txEvent;                     // Signal TX interrupt for HWXmitComChar
} UARTPDD;

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

static HW_VTBL g_pddVTbl = {
	HWInit, 
	HWPostInit,
	HWDeinit, 
	HWOpen, 
	HWClose, 
	HWGetInterruptType,
	HWRxIntr, 
	HWTxIntr, 
	HWModemIntr, 
	HWLineIntr, 
	HWGetRxBufferSize,
	HWPowerOff, 
	HWPowerOn, 
	HWClearDTR, 
	HWSetDTR, 
	HWClearRTS, 
	HWSetRTS,
	HWEnableIR, 
	HWDisableIR, 
	HWClearBreak, 
	HWSetBreak, 
	HWXmitComChar,
	HWGetStatus, 
	HWReset, 
	HWGetModemStatus, 
	HWGetCommProperties,
	HWPurgeComm, 
	HWSetDCB, 
	HWSetCommTimeouts, 
	HWIOCtl
};

//------------------------------------------------------------------------------
// Table used to convert "UnitIndex" from registry into physical addresses
// and IRQs. Au1x00.h only defines those UARTs that the CPU supports so we use
// that to manage available UARTs.
typedef struct {
	ULONG UartPhysAddr;
	ULONG UartIrq;
} UART_CONFIG;

static UART_CONFIG UartConfig[] = {

#ifdef UART0_PHYS_ADDR
	{ UART0_PHYS_ADDR, HWINTR_UART0 },
#else
	{ 0, 0 },
#endif

#ifdef UART1_PHYS_ADDR
	{ UART1_PHYS_ADDR, HWINTR_UART1 },
#else
	{ 0, 0 },
#endif

#ifdef UART2_PHYS_ADDR
	{ UART2_PHYS_ADDR, HWINTR_UART2 },
#else
	{ 0, 0 },
#endif

#ifdef UART3_PHYS_ADDR
	{ UART3_PHYS_ADDR, HWINTR_UART3 },
#else
	{ 0, 0 },
#endif

#ifdef CPLD_PHYSADDR
	{ CPLD_PHYSADDR, HWINTR_GPIO7 },
#else
	{ 0, 0 },
#endif
};


#define UART_CONFIG_SIZE (sizeof(UartConfig)/sizeof(UART_CONFIG))


static BOOT_ARGS *pBootArgs = (BOOT_ARGS*)(BOOT_ARG_PTR + KSEG1_OFFSET); // SmartOne add

//------------------------------------------------------------------------------
//
// Function:     ReadLineStat
//
// Description:  This function reads line status register and it calls back
//               MDD if line event occurs. This must be done in this way
//               because register bits are cleared on read.
//

static VOID ResetUart(UARTPDD *pPdd)
{
    CPLD* pCpld = pPdd->pPortBase;

	// 复位 uart,写一个高的脉冲
	pCpld->uartCtrl &= ~UART_RESET_BIT;
	HalStallExecution(1); // 100ns
	pCpld->uartCtrl |= UART_RESET_BIT;
	HalStallExecution(8); // 800ns
	pCpld->uartCtrl &= ~UART_RESET_BIT;

    return ;
}

static VOID EnableUart(UARTPDD *pPdd, BOOL bOn)
{
    CPLD* pCpld = pPdd->pPortBase;

	if(bOn) {
		HalStallExecution(1);               // 100ns
		pCpld->uartCtrl |= UART_ENABLE_BIT;             // don't change fifo status
		HalStallExecution(1 * 1000 * 100);  // 1ms     
	}
	else {
		HalStallExecution(1);               // 100ns
		pCpld->uartCtrl &= ~UART_ENABLE_BIT;             // don't change fifo status
		HalStallExecution(1 * 1000 * 100);  // 1ms  
	}

    return ;
}

static VOID EnableRxFifo(UARTPDD *pPdd, BOOL bOn)
{
    CPLD* pCpld = pPdd->pPortBase;

	if(!bOn)
	    pCpld->uartCtrl |= UART_RX_FIFO_ENB_BIT; 
	else
		pCpld->uartCtrl &= ~UART_RX_FIFO_ENB_BIT; 

    return ;
}

//------------------------------------------------------------------------------
//
// Function:     ReadLineStat
//
// Description:  This function reads line status register and it calls back
//               MDD if line event occurs. This must be done in this way
//               because register bits are cleared on read.
//

static UCHAR ReadLineStat(UARTPDD *pPdd)
{
#if 0
	UCHAR lineStat;
	ULONG events;

	// Nothing happen yet...   
	events = 0;

	// Read line status register (it clear most bits)
	lineStat = INP32(&pPdd->pPortBase->linestat);

	// Check for errors
	if ((lineStat&(UART_LINESTAT_OE|UART_LINESTAT_PE|UART_LINESTAT_FE)) != 0) {
		if ((lineStat & UART_LINESTAT_OE) != 0) {
			pPdd->overrunCount++;
			pPdd->commErrors |= CE_OVERRUN;
		}
		if ((lineStat & UART_LINESTAT_PE) != 0) pPdd->commErrors |= CE_RXPARITY;
		if ((lineStat & UART_LINESTAT_FE) != 0) pPdd->commErrors |= CE_FRAME;
		events |= EV_ERR;
	}

	// And for break
	if ((lineStat&UART_LINESTAT_BI) != 0) events |= EV_BREAK;

	// Let MDD know if something happen
	if (events != 0) EvaluateEventFlag(pPdd->pMdd, events);

	return lineStat;
#endif

#if 1
    UCHAR lineStat;
    CPLD* pCpld = pPdd->pPortBase;

    lineStat = pCpld->uartStatus;

    return lineStat;
#endif
}

//------------------------------------------------------------------------------
//
// Function:     ReadModemStat
//
// Description:  This function reads modem status register and it calls back
//               MDD if modem event occurs. This must be done in this way
//               because register bits are cleared on read.
//

static UCHAR ReadModemStat(UARTPDD *pPdd)
{
	UCHAR modemStat = 0;
#if 0	
	ULONG events;

	// Nothing happen yet...   
	events = 0;

	modemStat = INP32(&pPdd->pPortBase->mdmstat);

	// For changes, we use callback to evaluate the event
	if ((modemStat & UART_MDMSTAT_DC) != 0)  events |= EV_CTS;
	if ((modemStat & UART_MDMSTAT_DR) != 0)  events |= EV_DSR;
	if ((modemStat & UART_MDMSTAT_TRI) != 0) events |= EV_RING;
	if ((modemStat & UART_MDMSTAT_DD) != 0)  events |= EV_RLSD;

	// Let MDD know if something happen
	if (events != 0) EvaluateEventFlag(pPdd->pMdd, events);
#endif
	return modemStat;
}


//------------------------------------------------------------------------------
//
// Function:     SetBaudRate
//
// Description:  This function sets baud rate.
//

static BOOL SetBaudRate(UARTPDD *pPdd, ULONG baudRate)
{
	////ULONG divider;
	BOOL ok = FALSE;
	CPLD* pCpld = pPdd->pPortBase;

	//RETAILMSG(1, (L"+cplduart::SetBaudRate 01 %d\r\n", baudRate));
	
	// Check baud rate values
	if (baudRate != 9600 && baudRate != 38400) goto cleanUp;
	
    // only support two type of baud rate, one is 9600, another is 38400.
	EnterCriticalSection(&pPdd->hwCS);
    if(baudRate == 38400) {
	    pCpld->uartCtrl |= UART_SET_BAUDRATE_BIT;      // 38400
	    //RETAILMSG(1, (L"+cplduart::SetBaudRate 02 %d\r\n", baudRate));
    }
    else { 
	    pCpld->uartCtrl &= ~UART_SET_BAUDRATE_BIT;     // 9600
	    //RETAILMSG(1, (L"+cplduart::SetBaudRate 03 %d\r\n", baudRate)); 
    }
	LeaveCriticalSection(&pPdd->hwCS);

#if 0
	// Check baud rate values
	if (baudRate < 110 || baudRate > 1546875) goto cleanUp;

	// Calculate divider
	divider = GetPBUSSpeed() / (16 * baudRate);

	EnterCriticalSection(&pPdd->hwCS);
	OUT32(&pPdd->pPortBase->clkdiv, divider);
	LeaveCriticalSection(&pPdd->hwCS);
#endif
	ok = TRUE;

cleanUp:
	return ok;
}

//------------------------------------------------------------------------------
//
// Function:     SetWordLength
//
// Description:  This function sets word length.
//

static BOOL SetWordLength(UARTPDD *pPdd, UCHAR wordLength)
{
	////UCHAR lineCtrl;
	BOOL ok = FALSE;

	//RETAILMSG(1, (L"+cplduart::SetWordLength %d\r\n", wordLength));
	if (wordLength != 8) goto cleanUp;   // cpld里己经固定为8bit数据位
#if 0
	if (wordLength < 5 || wordLength > 8) goto cleanUp;

	EnterCriticalSection(&pPdd->hwCS);
	lineCtrl = INP32(&pPdd->pPortBase->linectrl);
	lineCtrl = (lineCtrl & 0x03)|(wordLength - 5);
	OUT32(&pPdd->pPortBase->linectrl, lineCtrl);
	LeaveCriticalSection(&pPdd->hwCS);
#endif
	ok = TRUE;

cleanUp:
	return ok;
}

//------------------------------------------------------------------------------
//
// Function:     SetParity
//
// Description:  This function sets parity.
//

static BOOL SetParity(UARTPDD *pPdd, UCHAR parity)
{
	////UCHAR lineCtrl;
	BOOL ok = FALSE;
	////UCHAR mask;
#if 0
	switch (parity) {
	case NOPARITY:
		mask = 0;
		break;
	case ODDPARITY:
		mask = UART_LINECTRL_PE | (0 << 4);
		break;
	case EVENPARITY:
		mask = UART_LINECTRL_PE | (1 << 4);
		break;
	case MARKPARITY:
		mask = UART_LINECTRL_PE | (2 << 4);
		break;
	case SPACEPARITY:

⌨️ 快捷键说明

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