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

📄 evbns16550sio.c

📁 IXP425的BSP代码
💻 C
字号:
/* evbNs16550Sio.c - NS16550 serial driver for the IBM PPC403GA evaluation *//*  		     board. 						   *//* Copyright 1984-1996 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01b,06nov96,dgp  doc: final formatting01a,07mar96,tam  written (using i8250Sio.c).*//*DESCRIPTIONThis is the driver for the National NS 16550 UART Chip used on the IBM PPC403GA evaluation board.It uses the SCCs in asynchronous mode only.USAGEAn EVBNS16550_CHAN structure is used to describe the chip.The BSP's sysHwInit() routine typically calls sysSerialHwInit()which initializes all the register values in the EVBNS16550_CHAN structure(except the SIO_DRV_FUNCS) before calling evbNs16550HrdInit().The BSP's sysHwInit2() routine typically calls sysSerialHwInit2() whichconnects the chip interrupt handler evbNs16550Int() via intConnect().IOCTL FUNCTIONSThis driver responds to the same ioctl() codes as other serial drivers;for more information, see sioLib.h.INCLUDE FILES: drv/sio/evbNs16550Sio.h*/#include "vxWorks.h"#include "iv.h"#include "intLib.h"#include "errnoLib.h"#include "drv/sio/evbNs16550Sio.h"/* locals */static SIO_DRV_FUNCS evbNs16550SioDrvFuncs;/* forward declarations */static void evbNs16550InitChannel (EVBNS16550_CHAN *);static int  evbNs16550Ioctl(EVBNS16550_CHAN *,int,int);static int  evbNs16550Startup(SIO_CHAN *pSioChan);static int  evbNs16550PRxChar (SIO_CHAN *pSioChan,char *ch);static int  evbNs16550PTxChar(SIO_CHAN *pSioChan,char ch);/******************************************************************************** evbNs16550CallbackInstall - install ISR callbacks to get put chars.*/ static int evbNs16550CallbackInstall    (    SIO_CHAN *  pSioChan,    int         callbackType,    STATUS      (*callback)(),    void *      callbackArg    )    {    EVBNS16550_CHAN * pChan = (EVBNS16550_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);        }    }/******************************************************************************** evbNs16550HrdInit - initialize the NS 16550 chip** This routine is called to reset the NS 16550 chip to a quiescent state.*/void evbNs16550HrdInit    (    EVBNS16550_CHAN *pChan    )    {    (*pChan->outByte) (pChan->ier,0x0);  /* disable interrupts */    if (evbNs16550SioDrvFuncs.ioctl == NULL)	{	evbNs16550SioDrvFuncs.ioctl	= (int (*)()) evbNs16550Ioctl;	evbNs16550SioDrvFuncs.txStartup	= (int (*)()) evbNs16550Startup;	evbNs16550SioDrvFuncs.callbackInstall = evbNs16550CallbackInstall;	evbNs16550SioDrvFuncs.pollInput	= (int (*)()) evbNs16550PRxChar;	evbNs16550SioDrvFuncs.pollOutput= (int (*)(SIO_CHAN *,char)) 				     	  evbNs16550PTxChar;	}    pChan->pDrvFuncs = &evbNs16550SioDrvFuncs;    }/********************************************************************************* evbNs16550InitChannel  - initialize a single channel*/static void evbNs16550InitChannel    (    EVBNS16550_CHAN *pChan    )    {    int oldLevel;    oldLevel = intLock ();    /* 8 data bits, 1 stop bit, no parity */    (*pChan->outByte) (pChan->lcr, 0x03);    /* enable the receiver and transmitter */    (*pChan->outByte) (pChan->mdc, 0x0b);    (*pChan->inByte) (pChan->data);	/* clear the port */    /* enables interrupts  */    (*pChan->outByte) (pChan->ier,0x1);        intUnlock (oldLevel);    }/********************************************************************************* evbNs16550Ioctl - special device control** RETURNS: OK on success, EIO on device error, ENOSYS on unsupported*          request.*/static int evbNs16550Ioctl    (    EVBNS16550_CHAN *pChan,	/* device to control */    int request,		/* request code */    int arg			/* some argument */    )    {    int status;    int oldlevel;    int preset;    switch (request)	{	case SIO_BAUD_SET:            oldlevel = intLock();	    preset = (pChan->clkFreq / arg) >> 4;    	    (*pChan->outByte) (pChan->lcr, (char)0x83);    	    (*pChan->outByte) (pChan->brdh, MSB (preset));    	    (*pChan->outByte) (pChan->brdl, LSB (preset));    	    (*pChan->outByte) (pChan->lcr, 0x03);            pChan->baudRate = arg;	    status = OK;            intUnlock(oldlevel);	    break;        case SIO_BAUD_GET:            *(int *)arg = pChan->baudRate;            status = OK;            break;	case SIO_MODE_SET:            if (!(arg == SIO_MODE_POLL || arg == SIO_MODE_INT))                {                status = EIO;                break;                }            oldlevel = intLock();           	    /* only reset the channel if it hasn't done yet */	    if (!pChan->channelMode)                evbNs16550InitChannel(pChan);            if (arg == SIO_MODE_POLL)                (*pChan->outByte) (pChan->ier, 0x00);            else                (*pChan->outByte) (pChan->ier, 0x01);                        pChan->channelMode = arg;                        intUnlock(oldlevel);            status = OK;	    break;        case SIO_MODE_GET:            *(int *)arg = pChan->channelMode;            return (OK);        case SIO_AVAIL_MODES_GET:            *(int *)arg = SIO_MODE_INT | SIO_MODE_POLL;            return (OK);	default:	    status = ENOSYS;	    break;	}    return (status);    }/********************************************************************************* evbNs16550Int - handle a receiver/transmitter interrupt for the NS 16550 chip** This routine is called to handle interrupts.* If there is another character to be transmitted, it sends it.  If* the interrupt handler is called erroneously (for example, if a device* has never been created for the channel), it* disables the interrupt.*/void evbNs16550Int    (    EVBNS16550_CHAN  *pChan     )    {    char outChar;    char interruptID;    char lineStatus;    int ix = 0;        interruptID = (*pChan->inByte) ( pChan->iid );    do {	interruptID &= 0x06;        if (interruptID == 0x06)            lineStatus = (*pChan->inByte) (pChan->lst);        else if (interruptID == 0x04)	    {            if (pChan->putRcvChar != NULL)	        (*pChan->putRcvChar)( pChan->putRcvArg,                               (*pChan->inByte) (pChan->data) );	    else	        (*pChan->inByte) (pChan->data);	    }        else if (interruptID == 0x02)	    {            if ((pChan->getTxChar != NULL) &&                (*pChan->getTxChar) (pChan->getTxArg, &outChar) == OK )	        (*pChan->outByte) (pChan->data, outChar);            else	        (*pChan->outByte) (pChan->ier, 0x01);	    }        interruptID = (*pChan->inByte) (pChan->iid);	} while (((interruptID & 0x01) == 0) && (ix++ < 10));    }/********************************************************************************* evbNs16550Startup - transmitter startup routine** Call interrupt level character output routine.*/static int evbNs16550Startup    (    SIO_CHAN *pSioChan		/* tty device to start up */    )    {    /* enable the transmitter and it should interrupt to write the next char */        if (((EVBNS16550_CHAN *)pSioChan)->channelMode != SIO_MODE_POLL)        (*((EVBNS16550_CHAN *)pSioChan)->outByte) 	( ((EVBNS16550_CHAN *)pSioChan)->ier, 0x03);    return (OK);    }/******************************************************************************** evbNs16550PRxChar - poll the device for input.** RETURNS: OK if a character arrived, ERROR on device error, EAGAIN*          if the input buffer if empty.*/static int evbNs16550PRxChar    (    SIO_CHAN *pSioChan,    char *ch    )    {    /* wait for Data */    if ( ( (*((EVBNS16550_CHAN *)pSioChan)->inByte)			  (((EVBNS16550_CHAN *)pSioChan)->lst) & 0x01 ) == 0 )        return(EAGAIN);    *ch = ( *((EVBNS16550_CHAN *)pSioChan)->inByte) 	  ( ((EVBNS16550_CHAN *)pSioChan)->data );    return(OK);    }/******************************************************************************** evbNs16550PTxChar - output a character in polled mode.** RETURNS: OK if a character arrived, ERROR on device error, EAGAIN*          if the output buffer if full.*/static int evbNs16550PTxChar    (    SIO_CHAN *pSioChan,    char ch                   /* character to output */    )    {    /* wait for Empty */    if ( ( (*((EVBNS16550_CHAN *)pSioChan)->inByte)			  (((EVBNS16550_CHAN *)pSioChan)->lst) & 0x40 ) == 0 )              return(EAGAIN);    (*((EVBNS16550_CHAN *)pSioChan)->outByte)     (((EVBNS16550_CHAN *)pSioChan)->data, ch);    return(OK);    }

⌨️ 快捷键说明

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