📄 ixp425sio.c
字号:
/* ixp425Sio.c - IXP425 UART tty driver *//* Copyright 2002 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01d,31jan03,jb3 Fix warning: unused variable .01c,30jan03,jb3 Fix SPR 85040 Serialdata corruption.01b,06nov02,jb Fix compile warning01a,05jun02,jb initial version...*//*DESCRIPTIONThis is the driver for the Intel IXP425 internal UART. This device comprises an asynchronous receiver/transmitter, a baud rate generator, and some modem control capability. An IXP425_SIO_CHAN structure is used to describe the serial channel. This data structure is defined in ixp425Sio.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 IXP425_SIO_CHAN structure and initializes all the values in thestructure (except the SIO_DRV_FUNCS) before calling ixp425SioDevInit().The BSP's sysHwInit2() routine typically calls sysSerialHwInit2(), whichconnects the chips interrupts via intConnect() (either the singleinterrupt 'ixp425SioInt' or the two interrupts 'ixp425SioIntWr', 'ixp425SioIntRd').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.INCLUDE FILES: ixp425Sio.hSEE ALSO:.I "ixp425 Data Sheet,"*//* includes */#include "vxWorks.h"#include "intLib.h"#include "errnoLib.h"#include "errno.h"#include "sioLib.h"#include "stdio.h"#include "ixp425Sio.h"#define IXP425_SIO_MIN_RATE 9600#define IXP425_SIO_MAX_RATE 921600#define IXP425_SIO_DEF_OPTS (CLOCAL | CREAD | CS8)#define REG(reg, pchan) \ (*(volatile UINT32 *)((UINT32)pchan->regs + (reg * pchan->regDelta)))#define REGPTR(reg, pchan) \ ((volatile UINT32 *)((UINT32)pchan->regs + (reg * pchan->regDelta)))/* for backward compatibility */#ifndef SIO_HUP #define SIO_OPEN 0x100A /* open channel, raise DTR, RTS */ #define SIO_HUP 0x100B /* hang-up, lower DTR, RTS */#endif/* static forward declarations */LOCAL int ixp425SioCallbackInstall (SIO_CHAN *, int, STATUS (*)(), void *);LOCAL STATUS ixp425SioDummyCallback ();LOCAL void ixp425SioInitChannel (IXP425_SIO_CHAN *);LOCAL STATUS ixp425SioBaudSet (IXP425_SIO_CHAN *, UINT);LOCAL STATUS ixp425SioModeSet (IXP425_SIO_CHAN *, UINT);LOCAL STATUS ixp425SioIoctl (IXP425_SIO_CHAN *, int, int);LOCAL void ixp425SioTxStartup (IXP425_SIO_CHAN *);LOCAL int ixp425SioPollOutput (IXP425_SIO_CHAN *, char);LOCAL int ixp425SioPollInput (IXP425_SIO_CHAN *, char *);LOCAL STATUS ixp425SioOptsSet (IXP425_SIO_CHAN *, UINT);LOCAL void ixp425SioIntRd (IXP425_SIO_CHAN * pChan);/* driver functions */static SIO_DRV_FUNCS ixp425SioDrvFuncs = { (int (*)())ixp425SioIoctl, (int (*)())ixp425SioTxStartup, (int (*)())ixp425SioCallbackInstall, (int (*)())ixp425SioPollInput, (int (*)(SIO_CHAN *,char))ixp425SioPollOutput };/******************************************************************************** ixp425SioDummyCallback - dummy callback routine.*/LOCAL STATUS ixp425SioDummyCallback (void) { return (ERROR); }/******************************************************************************** ixp425SioDevInit - initialise a UART channel** This routine initialises some SIO_CHAN function pointers and then resets* the chip in a quiescent state. Before this routine is called, the BSP* must already have initialised all the device addresses, etc. in the* IXP425_SIO_CHAN structure.** RETURNS: N/A*/void ixp425SioDevInit ( IXP425_SIO_CHAN * pChan /* pointer to channel */ ) { int oldlevel = intLock (); /* Initialise the driver function pointers in the SIO_CHAN's */ pChan->pDrvFuncs = &ixp425SioDrvFuncs;#ifdef IXP425_SIO_DEBUG /* Initialise counter statistics */ pChan->rxCount = 0; pChan->txCount = 0; pChan->overrunErr = 0; pChan->parityErr = 0; pChan->framingErr = 0; pChan->breakErr = 0;#endif /* Set the non BSP-specific constants */ pChan->getTxChar = ixp425SioDummyCallback; pChan->putRcvChar = ixp425SioDummyCallback; pChan->options = IXP425_SIO_DEF_OPTS; pChan->mcr = MCR_OUT2; /* * Mode 0 is undefined. However the VxWorks ttyDrv will issue * an ioctl for mode set to change to interrupt mode when it * needs to use the UART. */ pChan->channelMode = 0; /* Enable the device */ pChan->ier = IER_UUE; /* Set hardware opts and baud rate */ ixp425SioInitChannel (pChan); intUnlock (oldlevel); }/********************************************************************************* ixp425SioInitChannel - initialise UART** Initialise 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 ixp425SioInitChannel ( IXP425_SIO_CHAN * pChan /* pointer to channel */ ) { /* set the requested baud rate */ ixp425SioBaudSet(pChan, pChan->baudRate); /* set the options */ ixp425SioOptsSet(pChan, pChan->options); }/********************************************************************************* ixp425SioOptsSet - set the serial options** Set the channel operating mode to that specified. The following sioLib options* are supported: CLOCAL, CREAD, CSIZE, PARENB, and PARODD.* The HUPCL option is not supported for now.** 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 ixp425SioOptsSet ( IXP425_SIO_CHAN * pChan, /* pointer to channel */ UINT options /* new hardware options */ ) { FAST int oldlevel; /* current interrupt level mask */ pChan->lcr = 0; pChan->mcr &= (~MCR_RTS); /* clear RTS bit */ 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; case CS8: default: pChan->lcr = CHAR_LEN_8; break; } if (options & STOPB) pChan->lcr |= LCR_STB_2; else pChan->lcr |= LCR_STB_1; 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 |= LCR_PDIS; break; } REG(IER, pChan) = IER_UUE; /* disable interrupts, enable UART */ if (!(options & CLOCAL)) /* use hardware flow control (RTS/CTS) */ { pChan->mcr |= MCR_RTS; pChan->ier &= (~IER_TIE); pChan->ier |= IER_MIE; /* enable modem status interrupt */ } else pChan->ier &= (~IER_MIE); /* software flow ctrl */ oldlevel = intLock(); REG(LCR, pChan) = (unsigned int) pChan->lcr; REG(MCR, pChan) = (unsigned int) pChan->mcr; /* Enable FIFOs and set trigger level */ REG(FCR, pChan) = (unsigned int) (FCR_RESETRF | FCR_RESETTF | FCR_TRFIFOE | FCR_ITL_32);/* (FCR_ITL_32); */ if (options & CREAD) pChan->ier |= (IER_RAVIE | IER_RTOIE); if (pChan->channelMode == SIO_MODE_INT) { pChan->ier |= IER_RLSE; REG(IER, pChan) = (unsigned int) pChan->ier; } intUnlock (oldlevel); pChan->options = options; return OK; } /******************************************************************************** ixp425SioBaudSet - 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 ixp425SioBaudSet ( IXP425_SIO_CHAN * pChan, /* pointer to channel */ UINT baud /* requested baud rate */ ) { FAST int oldlevel; /* disable interrupts during chip access */ oldlevel = intLock (); /* Enable access to the divisor latches by setting DLAB in LCR. */ REG(LCR, pChan) = (unsigned int) (LCR_DLAB | pChan->lcr); /* Set divisor latches. */ REG(DLL, pChan) = (unsigned int) (pChan->xtal/(16 * baud)); REG(DLM, pChan) = (unsigned int) ((pChan->xtal/(16 * baud)) >> 8); /* Restore line control register */ REG(LCR, pChan) = (unsigned int) pChan->lcr; pChan->baudRate = baud; intUnlock (oldlevel); return (OK); }/********************************************************************************* ixp425SioModeSet - 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 channel's receiver * interrupt. The transmitter interrupt is enabled in TxStartup(). 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 ixp425SioModeSet ( IXP425_SIO_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) { if (pChan->options & CLOCAL) { pChan->ier |= (IER_RAVIE | IER_RTOIE | IER_RLSE); REG(IER, pChan) = (unsigned int) pChan->ier; } else { mask = REG(MSR, pChan) & MSR_CTS; /* if the CTS is asserted enable Tx interrupt */ if (mask & MSR_CTS) pChan->ier |= IER_TIE; else pChan->ier &= (~IER_TIE); /* disable Tx interrupt */ REG(IER, pChan) = (unsigned int) pChan->ier; } } else /* Polled mode */ { REG(IER, pChan) = (unsigned int) IER_UUE; } pChan->channelMode = newMode; intUnlock (oldlevel); return (OK); }/********************************************************************************* ixp425SioIoctl - special device control** Includes commands to get/set baud rate, mode(INT,POLL), hardware options(* parity, number of data bits), and modem control(RTS/CTS).** RETURNS: OK on success, EIO on device error, ENOSYS on unsupported* request.*/LOCAL STATUS ixp425SioIoctl ( IXP425_SIO_CHAN * pChan, /* pointer to channel */ int request, /* request code */ int arg /* some argument */ ) { FAST STATUS status; status = OK; switch (request) { case SIO_BAUD_SET: if (arg < IXP425_SIO_MIN_RATE || arg > IXP425_SIO_MAX_RATE) status = EIO; /* baud rate out of range */ else status = ixp425SioBaudSet (pChan, arg);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -