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

📄 ns16550sio_x86.c

📁 vxworks下16550SIO Drv
💻 C
📖 第 1 页 / 共 2 页
字号:
/* ns16550Sio.c - NS 16550 UART tty driver *//* Copyright 1984-1997 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------2002-12-6 23:00 ;3g;donleo;for x86 16550.01i,17sep97,dat  fixed merge problems that caused baud rate setting to fail.01h,06mar97,dat  SPR 7899, max baud rate set to 115200.01g,08may97,db   added hardware options and modem control(SPRs #7570, #7082).01f,18dec95,myz  added case IIR_TIMEOUT in ns16550Int routine.01e,28nov95,myz  fixed bugs to work at 19200 baud or above with heavy traffic.01d,09nov95,jdi  doc: style cleanup.01c,02nov95,myz  undo 01b fix01b,02nov95,p_m  added test for 960CA and 960JX around access to lcr field		 in order to compile on all architectures.01a,24oct95,myz  written from ns16550Serial.c.*//*DESCRIPTIONThis is the driver for the NS16552 DUART. This device includes two universalasynchronous receiver/transmitters, a baud rate generator, and a complete modem control capability. A NS16550_CHAN structure is used to describe the serial channel. This data structure is defined in ns16550Sio.h.Only asynchronous serial operation is supported by this driver.The default serial settings are 8 data bits, 1 stop bit, no parity, 9600baud, and software flow control.  USAGEThe BSP's sysHwInit() routine typically calls sysSerialHwInit(),which creates the NS16550_CHAN structure and initializes all the values in the structure (except the SIO_DRV_FUNCS) before calling ns16550DevInit().The BSP's sysHwInit2() routine typically calls sysSerialHwInit2(), whichconnects the chips interrupts via intConnect() (either the singleinterrupt `ns16550Int' or the three interrupts `ns16550IntWr', `ns16550IntRd',and `ns16550IntEx').This driver handles setting of hardware options such as parity(odd, even) andnumber of data bits(5, 6, 7, 8). Hardware flow control is provided with thehandshakes RTS/CTS. The function HUPCL(hang up on last close) is available.When hardware flow control is enabled, the signals RTS and DTR are set TRUE and remain set until a HUPCL is performed. INCLUDE FILES: drv/sio/ns16552Sio.h*//* includes */#include "vxWorks.h"#include "intLib.h"#include "errnoLib.h"#include "errno.h"#include "sioLib.h"#include "drv/sio/ns16552Sio.h"/* local defines       */#ifndef SIO_HUP#   define SIO_OPEN	0x100A#   define SIO_HUP	0x100B#endif/* min/max baud rate */ #define X86_16550	1 #define NS16550_MIN_RATE 50#define NS16550_MAX_RATE 115200#define REG(reg, pchan) \ (*(volatile UINT8 *)((UINT32)pchan->regs + (reg * pchan->regDelta)))#define REGPTR(reg, pchan) \ ((volatile UINT8 *)((UINT32)pchan->regs + (reg * pchan->regDelta)))#define X86_REG_OUT(reg,pchan,value) \	(sysOutByte((UINT32)pchan->regs + (reg * pchan->regDelta),value))#define X86_REG_IN(reg,pchan) \	(sysInByte((UINT32)pchan->regs + (reg * pchan->regDelta)))	/* static forward declarations 预先声明*/LOCAL 	int 	ns16550CallbackInstall (SIO_CHAN *, int, STATUS (*)(), void *);LOCAL 	STATUS 	ns16550DummyCallback ();LOCAL 	void 	ns16550InitChannel (NS16550_CHAN *);LOCAL   STATUS  ns16550BaudSet (NS16550_CHAN *, UINT);LOCAL 	STATUS  ns16550ModeSet (NS16550_CHAN *, UINT);LOCAL 	STATUS 	ns16550Ioctl (NS16550_CHAN *, int, int);LOCAL 	void 	ns16550TxStartup (NS16550_CHAN *);LOCAL 	int 	ns16550PollOutput (NS16550_CHAN *, char);LOCAL 	int 	ns16550PollInput (NS16550_CHAN *, char *);LOCAL 	STATUS 	ns16550OptsSet (NS16550_CHAN *, UINT);LOCAL 	STATUS 	ns16550Open (NS16550_CHAN * pChan );LOCAL 	STATUS 	ns16550Hup (NS16550_CHAN * pChan );/* driver functions */static SIO_DRV_FUNCS ns16550SioDrvFuncs =    {    (int (*)())ns16550Ioctl,    (int (*)())ns16550TxStartup,    ns16550CallbackInstall,    (int (*)())ns16550PollInput,    (int (*)(SIO_CHAN *,char))ns16550PollOutput    };/******************************************************************************** ns16550DummyCallback - dummy callback routine.*/LOCAL STATUS ns16550DummyCallback (void)    {    return (ERROR);    }/******************************************************************************** ns16550DevInit - intialize an NS16550 channel** This routine initializes some SIO_CHAN function pointers and then resets* the chip in a quiescent state.  Before this routine is called, the BSP* must already have initialized all the device addresses, etc. in the* NS16550_CHAN structure.** RETURNS: N/A*/void ns16550DevInit    (    NS16550_CHAN * pChan	/* pointer to channel */    )    {    int oldlevel = intLock ();    /* initialize the driver function pointers in the SIO_CHAN's */    pChan->pDrvFuncs    = &ns16550SioDrvFuncs;    /* set the non BSP-specific constants */    pChan->getTxChar    = ns16550DummyCallback;    pChan->putRcvChar   = ns16550DummyCallback;    pChan->channelMode  = 0;    /* undefined */    pChan->options      = (CLOCAL | CREAD | CS8);    pChan->mcr		= MCR_OUT2;    /* reset the chip */    ns16550InitChannel (pChan);    intUnlock (oldlevel);    }/********************************************************************************* ns16550InitChannel - initialize UART** Initialize the number of data bits, parity and set the selected* baud rate.* Set the modem control signals if the option is selected.** RETURNS: N/A*/LOCAL void ns16550InitChannel    (    NS16550_CHAN * pChan	/* pointer to channel */	    )    {    /* set the requested baud rate */    ns16550BaudSet(pChan, pChan->baudRate);    /* set the options */    ns16550OptsSet(pChan, pChan->options);    }/********************************************************************************* ns16550OptsSet - set the serial options** Set the channel operating mode to that specified.  All sioLib options* are supported: CLOCAL, HUPCL, CREAD, CSIZE, PARENB, and PARODD.* When the HUPCL option is enabled, a connection is closed on the last* close() call and opened on each open() call.** Note, this routine disables the transmitter.  The calling routine* may have to re-enable it.** RETURNS:* Returns OK to indicate success, otherwise ERROR is returned*/LOCAL STATUS ns16550OptsSet    (    NS16550_CHAN * pChan,	/* pointer to channel */    UINT options		/* new hardware options */    )    {    FAST int     oldlevel;		/* current interrupt level mask */    pChan->lcr = 0;     pChan->mcr &= (~(MCR_RTS | MCR_DTR)); /* clear RTS and DTR bits */        if (pChan == NULL || options & 0xffffff00)	return ERROR;    switch (options & CSIZE)	{	case CS5:	    pChan->lcr = CHAR_LEN_5; break;	case CS6:	    pChan->lcr = CHAR_LEN_6; break;	case CS7:	    pChan->lcr = CHAR_LEN_7; break;	default:	case CS8:	    pChan->lcr = CHAR_LEN_8; break;	}    if (options & STOPB)	pChan->lcr |= LCR_STB;    else	pChan->lcr |= ONE_STOP;        switch (options & (PARENB | PARODD))	{	case PARENB|PARODD:	    pChan->lcr |= LCR_PEN; break;	case PARENB:	    pChan->lcr |= (LCR_PEN | LCR_EPS); break;	default:	case 0:	    pChan->lcr |= PARITY_NONE; break;	}#if X86_16550	X86_REG_OUT(IER,pChan,0);#else     REG(IER, pChan) = 0;#endif     if (!(options & CLOCAL))	{	/* !clocal enables hardware flow control(DTR/DSR) */	pChan->mcr |= (MCR_DTR | MCR_RTS);    	pChan->ier &= (~TxFIFO_BIT); 	pChan->ier |= IER_EMSI;    /* enable modem status interrupt */	}    else        pChan->ier &= ~IER_EMSI; /* disable modem status interrupt */     oldlevel = intLock ();#if X86_16550	X86_REG_OUT(LCR,pChan,pChan->lcr);	X86_REG_OUT(MCR,pChan,pChan->mcr);	X86_REG_OUT(FCR,pChan,(RxCLEAR | TxCLEAR | FIFO_ENABLE) );#else    REG(LCR, pChan) = pChan->lcr;    REG(MCR, pChan) = pChan->mcr;    /* now reset the channel mode registers */    REG(FCR, pChan) = (RxCLEAR | TxCLEAR | FIFO_ENABLE);#endif    if (options & CREAD)  	pChan->ier |= RxFIFO_BIT;    if (pChan->channelMode == SIO_MODE_INT)	{#if X86_16550		X86_REG_OUT(IER,pChan,pChan->ier);#else		        REG(IER, pChan) = pChan->ier;#endif    }    intUnlock (oldlevel);    pChan->options = options;    return OK;    }/********************************************************************************* ns16550Hup - hang up the modem control lines ** Resets the RTS and DTR signals and clears both the receiver and* transmitter sections.** RETURNS: OK*/LOCAL STATUS ns16550Hup    (    NS16550_CHAN * pChan 	/* pointer to channel */    )    {    FAST int     oldlevel;	/* current interrupt level mask */    oldlevel = intLock ();    pChan->mcr &= (~(MCR_RTS | MCR_DTR));#if X86_16550	X86_REG_OUT(MCR,pChan,pChan->mcr);	X86_REG_OUT(FCR,pChan,(RxCLEAR | TxCLEAR) );#else    REG(MCR, pChan) = pChan->mcr;    REG(FCR, pChan) = (RxCLEAR | TxCLEAR); #endif    intUnlock (oldlevel);    return (OK);    }    /********************************************************************************* ns16550Open - Set the modem control lines ** Set the modem control lines(RTS, DTR) TRUE if not already set.  * It also clears the receiver, transmitter and enables the fifo. ** RETURNS: OK*/LOCAL STATUS ns16550Open    (    NS16550_CHAN * pChan 	/* pointer to channel */    )    {    FAST int     oldlevel;	/* current interrupt level mask */    char mask;#if X86_16550	mask = X86_REG_IN(MCR,pChan) & (MCR_RTS | MCR_DTR);#else     mask = REG(MCR, pChan) & (MCR_RTS | MCR_DTR);#endif     if (mask != (MCR_RTS | MCR_DTR))     	{    	/* RTS and DTR not set yet */    	oldlevel = intLock ();	/* set RTS and DTR TRUE */    	pChan->mcr |= (MCR_DTR | MCR_RTS); #if X86_16550		X86_REG_OUT(MCR,pChan,pChan->mcr);		X86_REG_OUT(FCR,pChan,RxCLEAR | TxCLEAR | FIFO_ENABLE );#else    	REG(MCR, pChan) = pChan->mcr;     	/* clear Tx and receive and enable FIFO */        REG(FCR, pChan) = (RxCLEAR | TxCLEAR | FIFO_ENABLE);#endif    	intUnlock (oldlevel);	}    return (OK);    }/******************************************************************************** ns16550BaudSet - change baud rate for channel** This routine sets the baud rate for the UART. The interrupts are disabled* during chip access.** RETURNS: OK*//*寄存器设置*/LOCAL STATUS  ns16550BaudSet    (    NS16550_CHAN * pChan,	/* pointer to channel */    UINT	   baud		/* requested baud rate */    )    {    int   oldlevel;    /* disable interrupts during chip access */    oldlevel = intLock ();    /* Enable access to the divisor latches by setting DLAB in LCR. */#if X86_16550	X86_REG_OUT(LCR,pChan,LCR_DLAB | pChan->lcr);	X86_REG_OUT(DLL,pChan,pChan->xtal/(16 * baud));	X86_REG_OUT(DLM,pChan,(pChan->xtal/(16 * baud)) >> 8);	X86_REG_OUT(LCR,pChan,pChan->lcr);#else    REG(LCR, pChan) = LCR_DLAB | pChan->lcr;    /* Set divisor latches. */    REG(DLL, pChan) = pChan->xtal/(16 * baud);    REG(DLM, pChan) = (pChan->xtal/(16 * baud)) >> 8;    /* Restore line control register */    REG(LCR, pChan) = pChan->lcr;#endif    pChan->baudRate = baud;     intUnlock (oldlevel);    return (OK);    }/********************************************************************************* ns16550ModeSet - change channel mode setting** This driver supports both polled and interrupt modes and is capable of* switching between modes dynamically. ** If interrupt mode is desired this routine enables the channels receiver and * transmitter interrupts. If the modem control option is TRUE, the Tx interrupt* is disabled if the CTS signal is FALSE. It is enabled otherwise. ** If polled mode is desired the device interrupts are disabled. ** RETURNS:* Returns a status of OK if the mode was set else ERROR.*/LOCAL STATUS ns16550ModeSet    (    NS16550_CHAN * pChan,	/* pointer to channel */    UINT	newMode		/* mode requested */    )    {    FAST int     oldlevel;	/* current interrupt level mask */    char mask;    if ((newMode != SIO_MODE_POLL) && (newMode != SIO_MODE_INT))	return (ERROR);               oldlevel = intLock ();    if (newMode == SIO_MODE_INT)	{        /* Enable appropriate interrupts */			if (pChan->options & CLOCAL) #if X86_16550				X86_REG_OUT(IER,pChan,pChan->ier | RxFIFO_BIT | TxFIFO_BIT);#else                	REG(IER, pChan) = pChan->ier | RxFIFO_BIT | TxFIFO_BIT;#endif	else  		{#if X86_16550		mask = X86_REG_IN(MSR,pChan) & MSR_CTS;#else 		mask = REG(MSR, pChan) & MSR_CTS;

⌨️ 快捷键说明

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