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

📄 wd8250serial.c

📁 IXP425的BSP代码
💻 C
字号:
/* wd8250Serial.c - Western Digital 8250 serial driver *//* Copyright 1984-1992 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01s,05may93,caf  tweaked for ansi.01r,01dec92,jdi  NOMANUAL for tyCoInt() - SPR 1808.01q,28oct92,caf  tweaked tyCoDevCreate() documentation and parm checking.01p,02oct92,caf  derived from version 01o of star/tyCoDrv.c.01o,15sep92,caf  made board-independent.  removed ARGSUSED and ttyStatus().                 changed "recieve" to "receive".  added delay after setting                 baud rate in tyCoIoctl() to satisfy validation suite.                 ansified.01n,18jul92,smb  Changed errno.h to errnoLib.h.01m,09jun92,ajm  5.1 merge01l,21jan92,gae  disabled transmitter in tyClrInts() instead of uselessly		   re-reading status register.01k,14jan92,jdi  documentation cleanup.01j,06jan92,ajm  updated for FCS.01i,06nov91,ajm  fixed tyCoInt to handle ints in prio order, and clear error		  conditions more gracefully.01i,11oct91,jdi  documentation cleanup.01h,16jul91,ajm  added routine to merely clear all UART ints per channel01g,06jun91,ajm  fixed intHandler to read rec/trans buffer on error conditions01f,28may91,ajm  fixed pointer problem in tyCoInt routine01e,25may91,gae  WRS-ized.01d,30aug90,ajm  fixed tyCoDetermine to use MASK thus correctly clearing		  UART error conditions (DOPE!!)01c,07aug90,ajm  made tyCoHrdInit global for use by prom exception handler01b,25apr90,ajm  added tyCoDetermine to intConnects.  This routine determines		  whether we have a reciever or transmit interrupt.01a,23apr90,ajm  written.*//*DESCRIPTIONThis is the driver for the Western Digital 8250 serial chip.USER-CALLABLE ROUTINESMost of the routines in this driver are accessible only through the I/Osystem.  Two routines, however, must be called directly:  tyCoDrv() toinitialize the driver, and tyCoDevCreate() to create devices.Before the driver can be used, it must be initialized by calling theroutine tyCoDrv().  This routine should be called exactly once, before anyreads, writes, or calls to tyCoDevCreate().  Normally, it is called byusrRoot() in usrConfig.c.Before a terminal can be used, it must be created, using tyCoDevCreate().Each port to be used should have exactly one device associated with it bycalling this routine.IOCTL FUNCTIONSThis driver responds to the same ioctl() codes as a normal tty driver; for moreinformation, see the manual entry for tyLib.SEE ALSOtyLib*/#include "vxWorks.h"#include "errnoLib.h"#include "iv.h"#include "ioLib.h"#include "iosLib.h"#include "memLib.h"#include "tyLib.h"#include "config.h"#include "drv/serial/wd8250.h"#define DEFAULT_BAUD    9600            /* default uart baud rate */typedef struct			/* BAUD */    {    int rate;		/* a baud rate */    char msbyte;	/* most significant byte to write to the lc register */     char lsbyte;	/* least significant byte to write to the ie register */    } BAUD;IMPORT TY_CO_DEV tyCoDv [];/* baudTable is a table of the available baud rates, and the values to write   to the csr reg to get those rates */LOCAL BAUD baudTable [] =    {    {50,    MSB(WD_BAUD_50),    LSB(WD_BAUD_50) },    {75,    MSB(WD_BAUD_75),    LSB(WD_BAUD_75) },    {110,   MSB(WD_BAUD_110),   LSB(WD_BAUD_110)},    {134,   MSB(WD_BAUD_134_5), LSB(WD_BAUD_134_5)},    {150,   MSB(WD_BAUD_150),   LSB(WD_BAUD_150)},    {300,   MSB(WD_BAUD_300),   LSB(WD_BAUD_300)},    {600,   MSB(WD_BAUD_600),   LSB(WD_BAUD_600)},    {1200,  MSB(WD_BAUD_1200),  LSB(WD_BAUD_1200)},    {1800,  MSB(WD_BAUD_1800),  LSB(WD_BAUD_1800)},    {2000,  MSB(WD_BAUD_2000),  LSB(WD_BAUD_2000)},    {2400,  MSB(WD_BAUD_2400),  LSB(WD_BAUD_2400)},    {4800,  MSB(WD_BAUD_4800),  LSB(WD_BAUD_4800)},    {7200,  MSB(WD_BAUD_7200),  LSB(WD_BAUD_7200)},    {9600,  MSB(WD_BAUD_9600),  LSB(WD_BAUD_9600)},    {19200, MSB(WD_BAUD_19200), LSB(WD_BAUD_19200)},    {38400, MSB(WD_BAUD_38400), LSB(WD_BAUD_38400)},    {56000, MSB(WD_BAUD_56000), LSB(WD_BAUD_56000)}     };LOCAL int tyCoDrvNum;		/* driver number assigned to this driver *//* forward declarations */LOCAL void 	tyCoStartup ();LOCAL int 	tyCoOpen ();LOCAL STATUS 	tyCoIoctl ();LOCAL void 	tyCoTxInt ();LOCAL void 	tyCoRxInt ();void 		tyCoInt ();/* external forwards */void 		tyCoHrdInit ();int  		tyClrInts ();/********************************************************************************* tyCoDrv - initialize the tty driver** This routine initializes the driver, sets up interrupt vectors,* and performs hardware initialization of the serial ports.** This routine should be called exactly once, before any reads, writes, or* calls to tyCoDevCreate().  Normally, it is called by usrRoot() in* usrConfig.c.* * RETURNS: OK, or ERROR if the driver cannot be installed.** SEE ALSO: tyCoDevCreate()*/STATUS tyCoDrv (void)    {    /* check if driver already installed */         if (tyCoDrvNum > 0)	return (OK);    tyCoHrdInit (0);	/* initialize uart 0 */    tyCoHrdInit (1);	/* initialize uart 1 */    tyCoDrvNum = iosDrvInstall (tyCoOpen, (FUNCPTR) NULL, tyCoOpen,				(FUNCPTR) NULL, tyRead, tyWrite, tyCoIoctl);    return (tyCoDrvNum == ERROR ? ERROR : OK);    }/********************************************************************************* tyCoDevCreate - create a device for an on-board serial port** This routine creates a device for a specified serial port.  Each port* to be used should have exactly one device associated with it by calling* this routine.** For instance, to create the device "/tyCo/0", with buffer sizes of 512 bytes,* the proper call would be:* .CS*     tyCoDevCreate ("/tyCo/0", 0, 512, 512);* .CE* * RETURNS: OK, or ERROR if the driver is not installed, the channel is invalid,* or the device already exists.** SEE ALSO: tyCoDrv()*/STATUS tyCoDevCreate    (    char *      name,           /* name to use for this device      */    FAST int    channel,        /* physical channel for this device */    int         rdBufSize,      /* read buffer size, in bytes       */    int         wrtBufSize      /* write buffer size, in bytes      */    )    {    FAST TY_CO_DEV *pTyCoDv = &tyCoDv [channel];    if (tyCoDrvNum <= 0)	{	errnoSet (S_ioLib_NO_DRIVER);	return (ERROR);	}    /* if this doesn't represent a valid channel, don't do it */    if (channel < 0 || channel >= tyCoDv [0].numChannels)	return (ERROR);    /* if this device already exists, don't create it */    if (pTyCoDv->created)	return (ERROR);    /* initialize the ty descriptor, and turn on the bit for this     * receiver in the interrupt mask */    if (tyDevInit (&pTyCoDv->tyDev, rdBufSize, wrtBufSize,		   (FUNCPTR) tyCoStartup) != OK)	{        return (ERROR);	}    if (channel)	*(volatile UINT8 *) IO_MASK_REG |= UART_B_MSK; /* board level enable */    else	*(volatile UINT8 *) IO_MASK_REG |= UART_A_MSK; /* board level enable */    *pTyCoDv->int_enable = IE_RCV_LS|IE_DATA_RDY;    /* Mark the device as created, and add the device to the I/O system */    pTyCoDv->created = TRUE;    return (iosDevAdd (&pTyCoDv->tyDev.devHdr, name, tyCoDrvNum));    }/********************************************************************************* tyCoHrdInit - initialize the Western Digital 8250 UART.** This routine initializes the Western Digital 8250 UART for the VxWorks * environment. ** RETURNS: N/A** NOMANUAL*/void tyCoHrdInit    (    int channel    )    {    FAST TY_CO_DEV *pTyCoDv = &tyCoDv [channel];    FAST int       statusReg;           /* previous value of status reg */    FAST int       ix;                  /* index for baud lookup        */    unsigned char  staleValue;		/* read value from CSR's	*/    statusReg = intLock ();    /*     * channel initialiazation 8 data bits, 1 stop bit, no parity,     * set for 9600 baud     */    *pTyCoDv->int_enable = 0x00; 	/* disable ints */#ifdef	SYS_WB_FLUSH    sysWbFlush();#endif	/* SYS_WB_FLUSH */    tyClrInts(channel);	    /*    * Set baud rate.  See the 8250 manual for details.    */    for (ix = 0; ix < NELEMENTS (baudTable); ix++)     {	if (baudTable [ix].rate == DEFAULT_BAUD)	 {    	    *pTyCoDv->line_ctl = LC_DLAB_ENABLE|LC_LENGTH_8;	/* baud setup */#ifdef	SYS_WB_FLUSH	    sysWbFlush();#endif	/* SYS_WB_FLUSH */	    *pTyCoDv->int_enable = baudTable[ix].msbyte;	/* baud msbyte*/#ifdef	SYS_WB_FLUSH	    sysWbFlush();#endif	/* SYS_WB_FLUSH */	    *pTyCoDv->receive_trans = baudTable[ix].lsbyte;	/* baud lsbyte*/#ifdef	SYS_WB_FLUSH	    sysWbFlush();#endif	/* SYS_WB_FLUSH */	 }     }    /* 8 bits, no parity, spacing, one stop bit */    *pTyCoDv->line_ctl = LC_LENGTH_8|LC_PARITY_OFF|LC_STOP_1;    /* flush old data */    while (*pTyCoDv->line_stat & LS_DATA_RDY)         staleValue = *pTyCoDv->receive_trans;    /*     * all interrupts are masked out: the receiver interrupt will be enabled     * in the tyCoDevCreate     */    intUnlock (statusReg);    } /********************************************************************************* tyCoOpen - open file to Western Digital uart*/LOCAL int tyCoOpen    (    TY_CO_DEV *pTyCoDv,    char *name,    int mode    )    {    return ((int) pTyCoDv);    }/********************************************************************************* tyCoIoctl - special device control** This routine handles baud rate requests, and passes all other requests* to tyIoctl().** RETURNS: OK, or ERROR if invalid baud rate, or whatever tyIoctl() returns.*/LOCAL STATUS tyCoIoctl    (    TY_CO_DEV *pTyCoDv,	/* device to control */    int request,	/* request code      */    int arg		/* some argument     */    )    {    FAST UCHAR 	lineCtl;    FAST UCHAR 	enableReg;    FAST STATUS status;    FAST int 	ix;    switch (request)	{	case FIOBAUDRATE:	    status = ERROR;	    for (ix = 0; ix < NELEMENTS (baudTable); ix++)		{		if (baudTable [ix].rate == arg)	/* lookup baud rate value */		    {		    lineCtl = *pTyCoDv->line_ctl; 	/* save for later */		    enableReg = *pTyCoDv->int_enable;	/* save for later */		    /* setup baud rate */		    *pTyCoDv->line_ctl = LC_DLAB_ENABLE|LC_LENGTH_8; #ifdef	SYS_WB_FLUSH		    sysWbFlush();#endif	/* SYS_WB_FLUSH */		    /* setup baud msbyte */		    *pTyCoDv->int_enable = baudTable[ix].msbyte;#ifdef	SYS_WB_FLUSH		    sysWbFlush();#endif	/* SYS_WB_FLUSH */		    /* setup baud lsbyte */		    *pTyCoDv->receive_trans = baudTable[ix].lsbyte;#ifdef	SYS_WB_FLUSH		    sysWbFlush();#endif	/* SYS_WB_FLUSH */    		    *pTyCoDv->line_ctl = lineCtl;   /* reset line cntl reg */#ifdef	SYS_WB_FLUSH		    sysWbFlush();#endif	/* SYS_WB_FLUSH */    		    *pTyCoDv->int_enable = enableReg;/* reset int enable reg */#ifdef	SYS_WB_FLUSH		    sysWbFlush();#endif	/* SYS_WB_FLUSH */		    /* sync up after changing baud rate */		    taskDelay (sysClkRateGet () / 4 + 1);		    status = OK;		    break;		    }		}	    break;	default:	    status = tyIoctl (&pTyCoDv->tyDev, request, arg);	    break;	}    return (status);    }/********************************************************************************* tyCoRxInt - handle a receiver interrupt** This routine gets called at interrupt level to handle a receiver interrupt.*/LOCAL void tyCoRxInt    (    TY_CO_DEV *pTyCoDv    )    {    (void)tyIRd (&pTyCoDv->tyDev, *pTyCoDv->receive_trans);    }/********************************************************************************* tyCoTxInt - handle a transmitter interrupt** This routine gets called from interrupt level to handle a xmitter interrupt.* If there is another character to be transmitted, it sends it.  If* not, or if a device has never been created for this channel, we just* disable the interrupt.*/LOCAL void tyCoTxInt    (    TY_CO_DEV *pTyCoDv    )    {    char outChar;    if (pTyCoDv->created &&	tyITx (&pTyCoDv->tyDev, &outChar) == OK)	{	*pTyCoDv->receive_trans = outChar; 	sysWbFlush();	*pTyCoDv->int_enable |= IE_THRE_EMPTY; 	sysWbFlush();	}    else	{	/* turn off the transmitter */	*pTyCoDv->int_enable &= ~IE_THRE_EMPTY; 	sysWbFlush();	}    }/********************************************************************************* tyCoStartup - transmitter startup routine** Call interrupt level character output routine for the Western Digital UART.*/LOCAL void tyCoStartup    (    TY_CO_DEV *pTyCoDv		/* ty device to start up */    )    {    char outChar;    if (pTyCoDv->created && tyITx (&pTyCoDv->tyDev, &outChar) == OK)	{	*pTyCoDv->receive_trans = outChar;	sysWbFlush();	*pTyCoDv->int_enable |= IE_THRE_EMPTY;	sysWbFlush();	}    }/********************************************************************************* tyCoInt - is the interrupt a receive or transmit interrupt** Read the UART interrupt status register to determine what type of* interrupt we are looking at.** NOMANUAL*/void tyCoInt    (    TY_CO_DEV *pTyCoDv				/* device to control */    )    {    FAST UCHAR status;    FAST UCHAR staleValue;    while ((status = *pTyCoDv->int_id) != IID_NONE_PEND)	{        if ((status&IID_MASK) == IID_RCV_LS)	    {			/* break, serialization error, modem status */	    staleValue = *pTyCoDv->line_stat;		    pTyCoDv->lastBreak = (int) staleValue;		    ++pTyCoDv->breakError;		    }        else if ((status&IID_MASK) == IID_DATA_RDY)            tyCoRxInt(pTyCoDv);	/* receive interrupt */        else if ((status&IID_MASK) == IID_THRE)            tyCoTxInt(pTyCoDv);	/* transmit interrupt */        else if ((status&IID_MASK) == IID_MODEM_STAT)	    {			/* rs232 state change, or nothing pending */	    staleValue = *pTyCoDv->modem_stat;	    pTyCoDv->lastState = (int) staleValue;		    ++pTyCoDv->stateChange;	    }	}    }/********************************************************************************* tyClrInts - clear pending interrupts on the Western Digital 8250 UART.** This routine clears all pending interrupt conditions on the given* channel. ** NOMANUAL*/int tyClrInts    (    int channel    )    {    FAST TY_CO_DEV      *pTyCoDv = &tyCoDv [channel];    FAST UCHAR 		staleValue;	/* read value from CSR's	*/    FAST UCHAR 		status;		/* uart interrupt status	*/    while ((status = *pTyCoDv->int_id) != IID_NONE_PEND)        {        if ((status & IID_MASK) == IID_RCV_LS)	    staleValue = *pTyCoDv->line_stat;	else if ((status & IID_MASK) == IID_DATA_RDY)    	    staleValue = *pTyCoDv->receive_trans;	else if ((status & IID_MASK) == IID_THRE)	    *pTyCoDv->int_enable &= ~IE_THRE_EMPTY; /* turn off the xmitter */	else if ((status & IID_MASK) == IID_MODEM_STAT)	    staleValue = *pTyCoDv->modem_stat;	}    } 

⌨️ 快捷键说明

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