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

📄 m68562sio.c

📁 IXP425的BSP代码
💻 C
字号:
/* m68562Sio.c - MC68562 DUSCC serial driver *//* Copyright 1984-1995 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01g,14nov95,myz   rework last fix01f,14nov95,myz   undo last fix and fixed SPR #543701e,08sep95,myz   fixed the SPR #467801d,03aug95,myz   fixed the warning messages01c,20jun95,ms    fixed comments for mangen01b,15jun95,ms    updated for new driver structure01a,14apr95,myz   written (using m68562Serial.c + the VxMon polled driver).*//*DESCRIPTIONThis is the driver for the MC68562 DUSCC serial chip.It uses the DUSCC in asynchronous mode only.USAGEA M68562_QUSART structure is used to describe the chip. This data structurecontains M68562_CHAN structures which describe the chip's serial channels.The BSP's sysHwInit() routine typically calls sysSerialHwInit()which initializes all the values in the M68562_QUSART structure (exceptthe SIO_DRV_FUNCS) before calling m68562HrdInit().The BSP's sysHwInit2() routine typically calls sysSerialHwInit2() whichconnects the chips interrupts (m68562RxTxErrInt, m68562RxInt, andm68562TxInt) via intConnect().IOCTLThis driver responds to the same ioctl() codes as a normal serial driver.See the file sioLib.h for more information.INCLUDE FILES: drv/sio/m68562Sio.h*/#include "vxWorks.h"#include "iv.h"#include "intLib.h"#include "errnoLib.h"#include "drv/sio/m68562Sio.h"#define BIT(val,bit)    ((val & bit) == bit)/* forward declarations */static int m68562Startup (M68562_CHAN *pChan);static int m68562Ioctl (M68562_CHAN *pChan,int request,int arg);static void m68562ResetChannel (M68562_CHAN *pChan);static int m68562PTxChar (M68562_CHAN *pChan,char ch);static int m68562PRxChar (M68562_CHAN *pChan,char *ch);static int m68562CallbackInstall (SIO_CHAN *, int, STATUS (*)(), void *);typedef struct	       /* BAUD */    {    int rate;	       /* a baud rate */    char xmtVal;       /* rate to write to the Transmitter Timing Register */    char rcvVal;       /* rate to write to the Reciever Timing Register */    }      BAUD;/*  * baudTable is a table of the available baud rates, and the values to  * write to the csr reg to get those rates  */static BAUD baudTable [] =        {        {50,	DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_50,	DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_50 },        {75,	DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_75,	DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_75 },        {110,	DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_110,	DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_110},        {134,	DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_134_5,	DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_134_5},        {150,	DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_150,	DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_150},        {200,	DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_200,	DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_200},        {300,	DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_300,	DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_300},        {600,	DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_600,	DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_600},        {1050,	DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_1050,	DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_1050},        {1200,	DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_1200,	DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_1200},        {2000,	DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_2000,	DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_2000},        {2400,	DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_2400,	DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_2400},        {4800,	DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_4800,	DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_4800},        {9600,	DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_9600,	DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_9600},        {19200,	DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_19200,	DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_19200},        {38400,	DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_38400,	DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_38400} };/* local driver function table */static SIO_DRV_FUNCS m68562SioDrvFuncs =    {    (int (*)())m68562Ioctl,    (int (*)())m68562Startup,    m68562CallbackInstall,    (int (*)())m68562PRxChar,    (int (*)(SIO_CHAN *,char))m68562PTxChar    };/********************************************************************************* m68562HrdInit - initialize the DUSCC** The BSP must have already initialized all the device addresses, etc in* M68562_DUSART structure. This routine resets the chip in a quiescent state.*/void m68562HrdInit    (    M68562_QUSART *pQusart    )    {    register int ix;    int	lock = intLock ();      /* LOCK INTERRUPTS */    for (ix = 0; ix < pQusart->numChannels; ix ++)        pQusart->channel[ix].pDrvFuncs      = &m68562SioDrvFuncs;    /* initialize general registers of the device */    *(pQusart->gsr)  = (char) 0xff;    *(pQusart->ivr)  = pQusart->int_vec;   /* initialize vector register */    /* enable a, enable b, modify vec w/stat, present vec to cpu */    *(pQusart->icr)  = DUSCC_ICR_CHAN_B_MAST_INT_EN |                       DUSCC_ICR_CHAN_A_MAST_INT_EN |                       DUSCC_ICR_VECT_INCLDS_STATUS | DUSCC_ICR_VECT_MODE_VECT;    for (ix = 0; ix < pQusart->numChannels; ix ++)        {	/* execute reset commands */	*(pQusart->channel[ix].ccr) = DUSCC_CCR_TX_RESET_TX;	*(pQusart->channel[ix].ccr) = DUSCC_CCR_RX_RESET_RX;	*(pQusart->channel[ix].ccr) = (unsigned char)DUSCC_CCR_CT_STOP;	*(pQusart->channel[ix].ccr) = (unsigned char)DUSCC_CCR_DPLL_DISABLE_DPLL	; 	/* initialize registers */	*(pQusart->channel[ix].cmr1) = (char) 0x0;	*(pQusart->channel[ix].cmr2) = (char) 0x0;	*(pQusart->channel[ix].tpr)  = (char) 0x0;	*(pQusart->channel[ix].rpr)  = (char) 0x0;	*(pQusart->channel[ix].omr)  = (char) 0x0;	*(pQusart->channel[ix].pcr)  = (char) 0x0;	*(pQusart->channel[ix].rsr)  = (char) 0xff;	*(pQusart->channel[ix].trsr) = (char) 0xff;	*(pQusart->channel[ix].ictsr) = DUSCC_ICTSR_CT_ZERO_COUNT;	*(pQusart->channel[ix].ier)  = (char) 0x0;        m68562ResetChannel(&(pQusart->channel[ix]));	        }    intUnlock (lock);		/* UNLOCK INTERRUPTS */    }/********************************************************************************* m68562ResetChannel - reset a single channel*/static void m68562ResetChannel    (    M68562_CHAN *pChan    )    {    /* 8 data bits, 1 stop bit, no parity, set for 9600 baud */    /*     * DUSCC Initialization Procedures (from Dec 1987 Signetics app note)     *     * "Note that whenever a change is made in the channel mode registers,     *  the transmitter and receiver should first be disabled.  Also, before     *  any change is made in the transmit parameter register (TPR) or the     *  transmit timing register (TTR), the transmitter should be disabled.     *  After a change(s) has been completed, the trasmitter should be reset;      *  then enabled.     *     * "If changes are made in either the receive parameter register (RPR)     *  or the receive timing register (RTR), the receiver should be disabled.     *  After a changes(s) has been completed, the the receiver should be     *  reset; then enabled."     */    /* disable transmitter and receiver */    *pChan->ccr = DUSCC_CCR_TX_DISABLE_TX;    *pChan->ccr = DUSCC_CCR_RX_DISABLE_RX;    /* configure transmitter and receiver */    *pChan->cmr1 = DUSCC_CMR1_ASYNC;    *pChan->cmr2 = DUSCC_CMR2_DTI_POLL_OR_INT;    *pChan->tpr  = DUSCC_TPR_ASYNC_1 | DUSCC_TPR_8BITS;    *pChan->ttr  = DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_9600;    *pChan->rtr  = DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_9600;    *pChan->rpr  = DUSCC_RPR_8BITS;    *pChan->omr |= DUSCC_OMR_TXRDY_FIFO_EMPTY |                    DUSCC_OMR_TX_RES_CHAR_LENGTH_TPR;    /* reset transmitter and receiver */    *pChan->ccr = DUSCC_CCR_TX_RESET_TX;    *pChan->ccr = DUSCC_CCR_RX_RESET_RX;    /* enable transmitter and receiver */    *pChan->ccr = DUSCC_CCR_TX_ENABLE_TX;    *pChan->ccr = DUSCC_CCR_RX_ENABLE_RX;    }/********************************************************************************* m68562Ioctl - special device control** RETURNS: OK on success, EIO on device error, ENOSYS on unsupported*          request.*/static STATUS m68562Ioctl    (    M68562_CHAN *pChan,	/* device to control */    int request,	/* request code      */    int arg		/* some argument     */    )    {    register int ix;    STATUS status;    int oldlevel;    switch (request)        {	case SIO_BAUD_SET:	    status = EIO;	    for (ix = 0; ix < NELEMENTS (baudTable); ix ++)		if (baudTable [ix].rate == arg)		    {		    status = OK;	/* baud rate is valid */		    /*		     * Only set baud rate if the hardware needs it.		     * Setting the baud rate to 9600 when the baud		     * rate is already 9600, for example, would		     * unnecessarily disable the serial channel and		     * possibly drop characters.		     */		    if ((*pChan->ttr != baudTable [ix].xmtVal) ||			(*pChan->rtr != baudTable [ix].rcvVal))			{                        oldlevel = intLock();			/* disable transmitter and receiver */			*pChan->ccr = DUSCC_CCR_TX_DISABLE_TX;			*pChan->ccr = DUSCC_CCR_RX_DISABLE_RX;			/* configure transmitter and receiver */			*pChan->ttr = baudTable [ix].xmtVal;			*pChan->rtr = baudTable [ix].rcvVal;			/* reset transmitter and receiver */			*pChan->ccr = DUSCC_CCR_TX_RESET_TX;			*pChan->ccr = DUSCC_CCR_RX_RESET_RX;			/* enable transmitter and receiver */			*pChan->ccr = DUSCC_CCR_TX_ENABLE_TX;			*pChan->ccr = DUSCC_CCR_RX_ENABLE_RX;			intUnlock(oldlevel);			break;			}		    }	    break;        case SIO_BAUD_GET:            status = EIO;               /* baud rate out of range */            /* disable interrupts during chip access */            oldlevel = intLock ();            for (ix = 0; ix < NELEMENTS (baudTable); ix ++)                if (baudTable [ix].rcvVal == *pChan->rtr)                    {                    *(int *)arg = baudTable [ix].rate;                    status = OK;        /* baud rate is valid */                    }            intUnlock (oldlevel);            break;        case SIO_MODE_SET:            if (!((int)arg == SIO_MODE_POLL || (int)arg == SIO_MODE_INT))                {                status = EIO;                break;                }            /* lock interrupt  */            oldlevel = intLock();            if (arg == SIO_MODE_INT)                *pChan->ier = DUSCC_IER_RXRDY | DUSCC_IER_RSR_5_4;             else                *pChan->ier = 0;            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);    }/********************************************************************************* m68562RxTxErrInt - handle a receiver/transmitter error interrupt** Only the receive overrun condition is handled.** RETURNS: N/A*/void m68562RxTxErrInt    (    M68562_CHAN *pChan    )    {    if (BIT (*pChan->rsr, DUSCC_RSR_ASYNC_OVERN_ERROR))	*pChan->rsr = DUSCC_RSR_ASYNC_OVERN_ERROR;	/* "1" clears bit */    }/********************************************************************************* m68562RxInt - handle a receiver interrupt** RETURNS: N/A*/void m68562RxInt    (    M68562_CHAN *pChan    )    {    /* drain receive FIFO */    do        {	(*pChan->putRcvChar) (pChan->putRcvArg, *pChan->rx_data);        }    while ( ( (*pChan->pQusart->gsr) &  	   (DUSCC_GSR_A_RXRDY << ((pChan->chan_num)*4) ) ) && 	   pChan->channelMode != SIO_MODE_POLL );     }/********************************************************************************* m68562TxInt - handle a transmitter 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,* disable the interrupt.** RETURNS: N/A*/void m68562TxInt    (    M68562_CHAN *pChan    )    {    char outChar;    do                                          /* fill transmit FIFO */        {        if ((*pChan->getTxChar) (pChan->getTxArg, &outChar) == OK)            *pChan->tx_data = outChar;        else            {            *pChan->ier &= ~DUSCC_IER_TXRDY;  /* turn off transmitter */            break;            }        }        while ( (*pChan->pQusart->gsr) & 		 (DUSCC_GSR_A_TXRDY << ((pChan->chan_num)*4) ) );    }/******************************************************************************** m68562PRxChar - poll the device for input.** RETURNS: OK if a character arrived, ERROR on device error, EAGAIN*          if the input buffer if empty.*/static int m68562PRxChar    (    M68562_CHAN *pChan,    char *ch    )    {    /* wait for Data */    if (! ( (*pChan->pQusart->gsr) &              (DUSCC_GSR_A_RXRDY << ((pChan->chan_num)*4) ) ) )        return(EAGAIN);    *ch = *pChan->rx_data;    return(OK);    }/******************************************************************************** m68562PTxChar - 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 m68562PTxChar    (    M68562_CHAN *pChan,    char ch                   /* character to output */    )    {    /* check for Empty */    if (! ( (*pChan->pQusart->gsr) &               (DUSCC_GSR_A_TXRDY << ((pChan->chan_num)*4) ) ) )         return(EAGAIN);    *pChan->tx_data = ch;    return(OK);    }/********************************************************************************* m68562Startup - transmitter startup routine** Call interrupt level character output routine for DUSCC.*/static int m68562Startup    (    M68562_CHAN * pChan  	/* device to start up */     )    {    char outChar;    if ( pChan->channelMode == SIO_MODE_INT )        {	if ( (*pChan->getTxChar) (pChan->getTxArg, &outChar) == OK)            *pChan->tx_data  = outChar;	        *pChan->ier |= DUSCC_IER_TXRDY;        return (OK);        }    else        return (ERROR);    }/******************************************************************************** m68562CallbackInstall - install ISR callbacks to get put chars.*/static int m68562CallbackInstall    (    SIO_CHAN *  pSioChan,    int         callbackType,    STATUS      (*callback)(),    void *      callbackArg    )    {    M68562_CHAN * pChan = (M68562_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);        }    }

⌨️ 快捷键说明

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