?? st16c554sio.c
字號:
/* ST16C554Sio.c - ST16C554 serial driver *//*modification history--------------------01a,30dec04,xf written (using ST16C554Serial.c + the VxMon polled driver).*//*DESCRIPTIONThis is the driver for the ST16C554 UART Chip used on the PC 386.It uses the SCCs in asynchronous mode only.USAGEAn ST16C554_CHAN structure is used to describe the chip.The BSP's sysHwInit() routine typically calls sysSerialHwInit()which initializes all the register values in the ST16C554_CHAN structure(except the SIO_DRV_FUNCS) before calling ST16C554HrdInit().The BSP's sysHwInit2() routine typically calls sysSerialHwInit2() whichconnects the chips interrupt handler (ST16C554Int) via intConnect().IOCTL FUNCTIONSThis driver responds to all the same ioctl() codes as a normal serial driver;for more information, see the comments in sioLib.h. As initialized, theavailable baud rates are 110, 300, 600, 1200, 2400, 4800, 9600, 19200, and38400.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.INCLUDE FILES: drv/sio/ST16C554Sio.h*/#include "vxWorks.h"#include "iv.h"#include "intLib.h"#include "errnoLib.h"#include "drv/sio/ST16C554Sio.h"/* defines *//* This value is used to specify the maximum number of times ST16C554Int() * routine will read the 8250 Interrupt Identification Register before * returning. This value should optimally be derived from the BRDR. */#define ST16C554_IIR_READ_MAX 40#ifndef ST16C554_DEFAULT_BAUD# define ST16C554_DEFAULT_BAUD 9600#endif#ifndef SIO_HUP# define SIO_OPEN 0x100A# define SIO_HUP 0x100B#endif/********************************************************************//*****************************test define****************************/#define SIO_INIT_IER 0x100C/* locals *//* baudTable is a table of the available baud rates, and the values to write * to the UART's baud rate divisor {high, low} register. the formula is * 1843200(source) / (16 * baudrate) */static BAUD baudTable [] = { {50, 2304}, {75, 1536}, {110, 1047}, {134, 857}, {150, 768}, {300, 384}, {600, 192}, {1200, 96}, {2000, 58}, {2400, 48}, {3600,32}, {4800, 24}, {7200,16}, {9600, 12}, {19200, 6}, {38400, 3}, {57600, 2}, {115200, 1} };static SIO_DRV_FUNCS ST16C554SioDrvFuncs;/* forward declarations */LOCAL void ST16C554InitChannel (ST16C554_CHAN *);LOCAL int ST16C554Ioctl(ST16C554_CHAN *, int, int);LOCAL int ST16C554Startup(ST16C554_CHAN *pChan);LOCAL int ST16C554PRxChar (ST16C554_CHAN *pChan, char *ch);LOCAL int ST16C554PTxChar(ST16C554_CHAN *pChan, char ch);LOCAL STATUS ST16C554OptsSet (ST16C554_CHAN *, UINT);LOCAL STATUS ST16C554ModeSet (ST16C554_CHAN *, UINT);LOCAL STATUS ST16C554BaudSet (ST16C554_CHAN *, UINT);/******************************************************************************** ST16C554CallbackInstall - install ISR callbacks to get put chars.** This routine installs the callback functions for the driver** RETURNS: OK on success or ENOSYS on unsupported callback type.*/ static int ST16C554CallbackInstall ( SIO_CHAN * pSioChan, int callbackType, STATUS (*callback)(), void * callbackArg ) { ST16C554_CHAN * pChan = (ST16C554_CHAN *)pSioChan; switch (callbackType) { case SIO_CALLBACK_GET_TX_CHAR: pChan->getTxChar = callback; pChan->getTxArg = callbackArg; return (OK); case SIO_CALLBACK_PUT_RCV_CHAR: pChan->putRcvChar = callback; pChan->putRcvArg = callbackArg; return (OK); default: return (ENOSYS); } }/******************************************************************************** ST16C554HrdInit - initialize the chip** This routine is called to reset the chip in a quiescent state.* RETURNS: N/A*/void ST16C554HrdInit ( ST16C554_CHAN * pChan /* pointer to device */ ) { if (ST16C554SioDrvFuncs.ioctl == NULL) { ST16C554SioDrvFuncs.ioctl = (int (*)())ST16C554Ioctl; ST16C554SioDrvFuncs.txStartup = (int (*)())ST16C554Startup; ST16C554SioDrvFuncs.callbackInstall = ST16C554CallbackInstall; ST16C554SioDrvFuncs.pollInput = (int (*)())ST16C554PRxChar; ST16C554SioDrvFuncs.pollOutput = (int (*)(SIO_CHAN *,char))ST16C554PTxChar; } pChan->pDrvFuncs = &ST16C554SioDrvFuncs; ST16C554InitChannel(pChan); /* reset the channel */ }/********************************************************************************* ST16C554InitChannel - initialize a single channel*/static void ST16C554InitChannel ( ST16C554_CHAN * pChan /* pointer to device */ ) { int oldLevel; oldLevel = intLock (); /* set channel baud rate */ (void) ST16C554BaudSet(pChan, ST16C554_DEFAULT_BAUD); /* 8 data bits, 1 stop bit, no parity */ (*pChan->outByte) (pChan->lcr, (ST16C554_LCR_CS8 | ST16C554_LCR_1_STB | ST16C554_LCR_PDIS)); (*pChan->outByte) (pChan->mdc, (ST16C554_MCR_RTS | ST16C554_MCR_DTR | \ ST16C554_MCR_OUT2)); (*pChan->inByte) (pChan->data); /* clear the port */ /* disable interrupts */ (*pChan->outByte) (pChan->ier, 0x0); pChan->options = (CLOCAL | CREAD | CS8);/*defined in siolib.h*/ intUnlock (oldLevel); }/********************************************************************************* ST16C554Hup - hang up the modem control lines ** Resets the RTS and DTR signals.** RETURNS: OK*/LOCAL STATUS ST16C554Hup ( ST16C554_CHAN * pChan /* pointer to channel */ ) { FAST int oldlevel; /* current interrupt level mask */ oldlevel = intLock (); (*pChan->outByte) (pChan->mdc, ST16C554_MCR_OUT2); intUnlock (oldlevel); return (OK); } /********************************************************************************* ST16C554Open - Set the modem control lines ** Set the modem control lines(RTS, DTR) TRUE if not already set. * It also clears the receiver. ** RETURNS: OK*/LOCAL STATUS ST16C554Open ( ST16C554_CHAN * pChan /* pointer to channel */ ) { FAST int oldlevel; /* current interrupt level mask */ char mask; /* read modem control register */ mask = ((*pChan->inByte) (pChan->mdc)) & (ST16C554_MCR_RTS | ST16C554_MCR_DTR); if (mask != (ST16C554_MCR_RTS | ST16C554_MCR_DTR)) { /* RTS and DTR not set yet */ oldlevel = intLock (); /* set RTS and DTR TRUE */ (*pChan->outByte) (pChan->mdc, (ST16C554_MCR_RTS | ST16C554_MCR_DTR | \ ST16C554_MCR_OUT2)); intUnlock (oldlevel); } printf("\nOpen driver Success!"); return (OK); }/******************************************************************************** ST16C554BaudSet - change baud rate for channel** This routine sets the baud rate for the UART. The interrupts are disabled* during chip access.** RETURNS: OK to indicate success, otherwise ERROR is returned*/LOCAL STATUS ST16C554BaudSet ( ST16C554_CHAN * pChan, /* pointer to channel */ UINT baud /* requested baud rate */ ) { int oldlevel; STATUS status; FAST int ix; UINT8 lcr; /* disable interrupts during chip access */ oldlevel = intLock (); status = ERROR; for (ix = 0; ix < NELEMENTS (baudTable); ix++) { if (baudTable [ix].rate == baud) /* lookup baud rate value */ { lcr = (*pChan->inByte) (pChan->lcr); printf("\nLCR=%d\n",lcr); /*(*pChan->outByte) (pChan->lcr, ((char)(lcr))); (*pChan->outByte) (pChan->brdh, MSB (baudTable[ix].preset)); (*pChan->outByte) (pChan->brdl, LSB (baudTable[ix].preset)); (*pChan->outByte) (pChan->lcr, lcr);*/ (*pChan->outByte) (pChan->lcr, ((char)(lcr))|0x80); (*pChan->outByte) (pChan->brdh, 0x00); (*pChan->outByte) (pChan->brdl, 0x0C); (*pChan->outByte) (pChan->lcr, lcr); status = OK; break; } } intUnlock(oldlevel); printf("\n baudset driver Success!"); return (status); }/********************************************************************************* ST16C554ModeSet - 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 ST16C554ModeSet ( ST16C554_CHAN * pChan, /* pointer to channel */ UINT newMode /* mode requested */ ) { FAST int oldlevel; /* current interrupt level mask */ char ier, mask; if ((newMode != SIO_MODE_POLL) && (newMode != SIO_MODE_INT)) return (ERROR); oldlevel = intLock(); if (newMode == SIO_MODE_POLL) ier = 0x00; else { if (pChan->options & CLOCAL) ier = ST16C554_IER_RXRDY; else { mask = ((*pChan->inByte) (pChan->msr)) & ST16C554_MSR_CTS; /* if the CTS is asserted enable Tx interrupt */ if (mask & ST16C554_MSR_CTS) ier = (ST16C554_IER_TBE | ST16C554_IER_MSI); else ier = (ST16C554_IER_MSI); } } (*pChan->outByte) (pChan->ier, ier); pChan->channelMode = newMode; intUnlock(oldlevel); return (OK); }/********************************************************************************* ST16C554OptsSet - set the serial options** Set the channel operating mode to that specified. All sioLib options* are supported: CLOCAL, HUPCL, CREAD, CSIZE, PARENB, and PARODD.** RETURNS:* Returns OK to indicate success, otherwise ERROR is returned*/LOCAL STATUS ST16C554OptsSet ( ST16C554_CHAN * pChan, /* pointer to channel */ UINT options /* new hardware options */ ) { FAST int oldlevel; /* current interrupt level mask */ char lcr = 0; char mcr = ST16C554_MCR_OUT2; char ier; char mask; ier = (*pChan->inByte) (pChan->ier); if (pChan == NULL || options & 0xffffff00) return ERROR; switch (options & CSIZE) { case CS5: lcr = ST16C554_LCR_CS5; break; case CS6: lcr = ST16C554_LCR_CS6; break; case CS7: lcr = ST16C554_LCR_CS7; break; default: case CS8: lcr = ST16C554_LCR_CS8; break; } if (options & STOPB) lcr |= ST16C554_LCR_2_STB; else lcr |= ST16C554_LCR_1_STB; switch (options & (PARENB | PARODD)) { case PARENB|PARODD: lcr |= ST16C554_LCR_PEN; break; case PARENB: lcr |= (ST16C554_LCR_PEN | ST16C554_LCR_EPS); break; default: case 0: lcr |= ST16C554_LCR_PDIS; break; } (*pChan->outByte) (pChan->ier, 0x00); if (!(options & CLOCAL)) { /* !clocal enables hardware flow control(DTR/DSR) */ mcr |= (ST16C554_MCR_DTR | ST16C554_MCR_RTS); ier |= ST16C554_IER_MSI; /* enable modem status interrupt */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -