📄 ixdp2400sio.c
字号:
/* ixp2400Sio.c - ixp2400 UART functionally compatible with National Semiconductor's 16550D UART driver *//* Copyright 2001 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01a,1apr02,vgd written from ns16550sio.c 01j.*//*DESCRIPTIONThis is the driver for ixp2400 UART which is functinally compatible with National semiconductor's PC16550D for basic receive and transmit.This device includes one universal asynchronous receiver/transmitters and a baud rate generator. modem control capability is not supported.A IXP2400_CHAN structure is used to describe the serial channel. This data structure is defined in ixdp2400Sio.h.Only asynchronous serial operation is supported by this driver.The default serial settings are 8 data bits, 1 stop bit, no parity, 115200baud, and software flow control. USAGEThe BSP's sysHwInit() routine typically calls sysSerialHwInit(),which creates the IXP2400_CHAN structure and initializes all the values in the structure (except the SIO_DRV_FUNCS) before calling ixp2400DevInit().The BSP's sysHwInit2() routine typically calls sysSerialHwInit2(), whichconnects the chips interrupts via intConnect() (either the singleinterrupt `ixp2400Int' or the three interrupts `ixp2400IntWr', `ixp2400IntRd',and `ixp2400IntEx').This driver handles setting of hardware options such as parity(odd, even) andnumber of data bits(5, 6, 7, 8). The function HUPCL(hang up on last close) is not availableas modem controls are not supported by this UART.INCLUDE FILES: ixdp2400Sio.h*//* includes */#include "vxWorks.h"#include "intLib.h"#include "errnoLib.h"#include "errno.h"#include "sioLib.h"#include "ixdp2400Sio.h"#include "ixdp2400Misc.h"#define IXP2400#if defined (IXP2400)#define NO_MODEM_CNTRL#define UART_DEBUG 0#endif#ifndef SIO_HUP# define SIO_OPEN 0x100A# define SIO_HUP 0x100B#endif/* min/max baud rate */#define IXP2400_MIN_RATE 50#define IXP2400_MAX_RATE 115200#if (_BYTE_ORDER == _BIG_ENDIAN)#define REG(reg, pchan) \ (*(volatile UINT8 *)(((UINT32)pchan->regs + (reg * pchan->regDelta))^3))#define REGPTR(reg, pchan) \ ((volatile UINT8 *)(((UINT32)pchan->regs + (reg * pchan->regDelta))^3))#else#define REG(reg, pchan) \ (*(volatile UINT8 *)((UINT32)pchan->regs + (reg * pchan->regDelta)))#define REGPTR(reg, pchan) \ ((volatile UINT8 *)((UINT32)pchan->regs + (reg * pchan->regDelta)))#endif /*BYTE_ORDER*//* static forward declarations */LOCAL int ixp2400CallbackInstall (SIO_CHAN *, int, STATUS (*)(), void *);LOCAL STATUS ixp2400DummyCallback ();LOCAL void ixp2400InitChannel (IXP2400_CHAN *);LOCAL STATUS ixp2400BaudSet (IXP2400_CHAN *, UINT);LOCAL STATUS ixp2400ModeSet (IXP2400_CHAN *, UINT);LOCAL STATUS ixp2400Ioctl (IXP2400_CHAN *, int, int);LOCAL int ixp2400TxStartup (IXP2400_CHAN *);LOCAL int ixp2400PollOutput (IXP2400_CHAN *, char);LOCAL int ixp2400PollInput (IXP2400_CHAN *, char *);LOCAL STATUS ixp2400OptsSet (IXP2400_CHAN *, UINT);#if defined(NO_MODEM_CNTRL)#elseLOCAL STATUS ixp2400Open (IXP2400_CHAN * pChan );LOCAL STATUS ixp2400Hup (IXP2400_CHAN * pChan );#endif/* driver functions */LOCAL SIO_DRV_FUNCS ixp2400SioDrvFuncs = { (int (*)())ixp2400Ioctl, (int (*)())ixp2400TxStartup, (int (*)())ixp2400CallbackInstall, (int (*)())ixp2400PollInput, (int (*)(SIO_CHAN *,char))ixp2400PollOutput };/******************************************************************************** ixp2400DummyCallback - dummy callback routine.*/LOCAL STATUS ixp2400DummyCallback (void) { return (ERROR); }/******************************************************************************** ixp2400DevInit - intialize an UART 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* IXP2400_CHAN structure.** RETURNS: N/A*/void ixp2400DevInit ( IXP2400_CHAN * pChan /* pointer to channel */ ) { int oldlevel = intLock (); /* initialize the driver function pointers in the SIO_CHAN's */ pChan->pDrvFuncs = &ixp2400SioDrvFuncs; /* set the non BSP-specific constants */ pChan->getTxChar = ixp2400DummyCallback; pChan->putRcvChar = ixp2400DummyCallback; pChan->channelMode = 0; /* undefined */ pChan->options = (CLOCAL | CREAD | CS8); #if defined(NO_MODEM_CNTRL)#else pChan->mcr = MCR_OUT2;#endif /* reset the chip */ ixp2400InitChannel (pChan); intUnlock (oldlevel); }/********************************************************************************* ixp2400InitChannel - 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 ixp2400InitChannel ( IXP2400_CHAN * pChan /* pointer to channel */ ) {#if defined(IXP2400) FAST int key;#endif /* set the requested baud rate */ ixp2400BaudSet(pChan, pChan->baudRate);#if defined(IXP2400) key=intLock(); /*enable the UART*/ pChan->ier = 0x40; intUnlock (key);#endif /* set the options */ ixp2400OptsSet(pChan, pChan->options); }/********************************************************************************* ixp2400OptsSet - set the serial options** Set the channel operating mode to that specified. All sioLib options* are supported: CREAD, CSIZE, PARENB, and PARODD except HUPCLand CLOCAL.*** 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 ixp2400OptsSet ( IXP2400_CHAN * pChan, /* pointer to channel */ UINT options /* new hardware options */ ) { FAST int oldlevel; /* current interrupt level mask */ pChan->lcr = 0; #if defined(NO_MODEM_CNTRL)#else pChan->mcr &= (~(MCR_RTS | MCR_DTR)); /* clear RTS and DTR bits */#endif 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; } oldlevel = intLock ();#if defined(NO_MODEM_CNTRL)#else REG(IER, pChan) = 0; 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 */ #endif REG(LCR, pChan) = pChan->lcr;#if defined(NO_MODEM_CNTRL)#else REG(MCR, pChan) = pChan->mcr;#endif /* now reset the channel mode registers */ REG(FCR, pChan) = (RxCLEAR | TxCLEAR | FIFO_ENABLE); if (options & CREAD) pChan->ier |= RxFIFO_BIT; if (pChan->channelMode == SIO_MODE_INT) { REG(IER, pChan) = pChan->ier; } intUnlock (oldlevel); pChan->options = options; return OK; }#if defined(NO_MODEM_CNTRL)#else/********************************************************************************* ixp2400Hup - hang up the modem control lines ** Resets the RTS and DTR signals and clears both the receiver and* transmitter sections.** RETURNS: OK*/LOCAL STATUS ixp2400Hup ( IXP2400_CHAN * pChan /* pointer to channel */ ) { FAST int oldlevel; /* current interrupt level mask */ oldlevel = intLock (); pChan->mcr &= (~(MCR_RTS | MCR_DTR)); REG(MCR, pChan) = pChan->mcr; REG(FCR, pChan) = (RxCLEAR | TxCLEAR); intUnlock (oldlevel); return (OK); } /********************************************************************************* ixp2400Open - 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 ixp2400Open ( IXP2400_CHAN * pChan /* pointer to channel */ ) { FAST int oldlevel; /* current interrupt level mask */ char mask; mask = REG(MCR, pChan) & (MCR_RTS | MCR_DTR); 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); REG(MCR, pChan) = pChan->mcr; /* clear Tx and receive and enable FIFO */ REG(FCR, pChan) = (RxCLEAR | TxCLEAR | FIFO_ENABLE); intUnlock (oldlevel); } return (OK); }#endif/******************************************************************************** ixp2400BaudSet - 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 ixp2400BaudSet ( IXP2400_CHAN * pChan, /* pointer to channel */ UINT baud /* requested baud rate */ ) { int oldlevel;#if defined(IXP2400) int divisor = ((pChan->xtal) / (16 * baud));#else int divisor = ((pChan->xtal + (8 * baud)) / (16 * baud));#endif /* disable interrupts during chip access */ oldlevel = intLock (); /* Enable access to the divisor latches by setting DLAB in LCR. */ REG(LCR, pChan) = LCR_DLAB | pChan->lcr; /* Set divisor latches. */ REG(DLL,pChan) = divisor; REG(DLM,pChan) = (divisor >> 8); /* Restore line control register */ REG(LCR, pChan) = pChan->lcr; pChan->baudRate = baud; intUnlock (oldlevel); return (OK); }/********************************************************************************* ixp2400ModeSet - 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 polled mode is desired the device interrupts are disabled. ** RETURNS:* Returns a status of OK if the mode was set else ERROR.*/LOCAL STATUS ixp2400ModeSet ( IXP2400_CHAN * pChan, /* pointer to channel */ UINT newMode /* mode requested */ )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -