📄 cd2400sio.c
字号:
/* cd2400Sio.c - CL-CD2400 MPCC serial driver *//* Copyright 1984-1995 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01h,20nov96,dds SPR 5438: Added interrupt locking to cd2400Startup () routine.01g,01dec95,myz removed waiting for transmitter done loop in ioctl SIO_MODE_SET01f,16nov95,myz reworked SPR #4678 about the baud rate problem with WDB agent01e,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,05mar95,myz written (using cd2400Serial.c + the VxMon polled driver).*//*DESCRIPTIONThis is the driver for the Cirus Logic CD2400 MPCC. It uses the SCC's inasynchronous mode.USAGEA CD2400_QUSART structure is used to describe the chip. This data structurecontains four CD2400_CHAN structure which describe the chip's four serialchannels.The BSP's sysHwInit() routine typically calls sysSerialHwInit()which initializes all the values in the CD2400_QUSART structure (exceptthe SIO_DRV_FUNCS) before calling cd2400HrdInit().The BSP's sysHwInit2() routine typically calls sysSerialHwInit2() whichconnects the chips interrupts (cd2400Int, cd2400IntRx, andcd2400IntTx) via intConnect().IOCTL FUNCTIONSThis driver responds to the same ioctl() codes as a normal serial driver; formore information, see the comments in sioLib.h. The available baud ratesare: 50, 110, 150, 300, 600, 1200, 2400, 3600, 4800, 7200, 9600,19200, and 38400.INCLUDE FILES: drv/sio/cd2400Sio.h*/#include "vxWorks.h"#include "sioLib.h"#include "intLib.h"#include "errno.h"#include "drv/sio/cd2400Sio.h"#define DEFAULT_BAUD 9600/* forward declarations */static int cd2400Ioctl (SIO_CHAN *, int, void *);static int cd2400Startup (SIO_CHAN * );static int cd2400PRxChar (SIO_CHAN *, char *);static int cd2400PTxChar (SIO_CHAN *, char);static void cd2400ChanIntEnDisable (CD2400_CHAN *, int);static void cd2400SetMode (CD2400_CHAN *, int);static int cd2400CallbackInstall (SIO_CHAN *, int, STATUS (*)(), void *);static void cd2400InitChannel(CD2400_CHAN *);/* channel descriptors */typedef struct /* BAUD */ { USHORT rate; /* baud rate */ USHORT timeConstant; /* time constant */ char tcor; /* transmit clock option register value */ char rcor; /* receive clock option register value */ } BAUD;static BAUD baudTable [] = { { 50, 2048, (unsigned char)TCOR_CLK4, RCOR_CLK4 }, { 110, 2048, (unsigned char)TCOR_CLK4, RCOR_CLK4 }, { 150, 2048, (unsigned char)TCOR_CLK4, RCOR_CLK4 }, { 300, 512, TCOR_CLK3, RCOR_CLK3 }, { 600, 512, TCOR_CLK3, RCOR_CLK3 }, { 1200, 128, TCOR_CLK2, RCOR_CLK2 }, { 2400, 128, TCOR_CLK2, RCOR_CLK2 }, { 3600, 32, TCOR_CLK1, RCOR_CLK1 }, { 4800, 32, TCOR_CLK1, RCOR_CLK1 }, { 7200, 32, TCOR_CLK1, RCOR_CLK1 }, { 9600, 32, TCOR_CLK1, RCOR_CLK1 }, { 19200, 8, TCOR_CLK0, RCOR_CLK0 }, { 38400, 8, TCOR_CLK0, RCOR_CLK0 } };/* local driver function table */static SIO_DRV_FUNCS cd2400SioDrvFuncs = { (int (*)())cd2400Ioctl, (int (*)())cd2400Startup, cd2400CallbackInstall, (int (*)())cd2400PRxChar, (int (*)(SIO_CHAN *,char))cd2400PTxChar };/********************************************************************************* cd2400HrdInit - initialize the chip** This routine initializes the chip and the four channels.*/void cd2400HrdInit ( CD2400_QUSART * pQusart /* chip to reset */ ) { FAST int oldlevel; /* current interrupt level mask */ int ix; oldlevel = intLock (); /* disable interrupts during init */ /* make sure the driver function pointers are installed */ for (ix = 0; ix < N_CHANNELS; ix++) pQusart->channel[ix].pDrvFuncs = &cd2400SioDrvFuncs; while (*MPCC_CCR) ; /* make sure no outstanding commands */ *MPCC_CCR = CCR_RESET_ALL; /* reset chip */ while (*MPCC_CCR) ; /* make sure we are done */ while (*MPCC_GFRCR == 0) ; /* wait for it to be non-zero */ *MPCC_TPR = 0x0a; /* Timer Peroid Register */ *MPCC_PILR1 = 0x00; /* Priority Interrupt Level Register */ *MPCC_PILR2 = 0x02; /* Priority Interrupt Level Register */ *MPCC_PILR3 = 0x03; /* Priority Interrupt Level Register */ for (ix = 0; ix < N_CHANNELS; ix++) cd2400InitChannel (&pQusart->channel[ix]); intUnlock (oldlevel); }/********************************************************************************* cd2400InitChannel - initialize a single channel*/static void cd2400InitChannel ( CD2400_CHAN * pChan /* channel to reset */ ) { int oldlevel; /* current interrupt level mask */ CD2400_QUSART * pQusart = pChan->pQusart; oldlevel = intLock (); /* disable interrupts during init */ /* initialize registers */ *MPCC_CAR = pChan->chan_num; *MPCC_LIVR = pChan->int_vec; *MPCC_COR1 = COR1_NO_PARITY | COR1_8BITS; *MPCC_COR2 = 0x00; *MPCC_COR3 = COR3_1STOP_BIT; *MPCC_COR4 = 0x00; /* no modem control for now */ *MPCC_COR5 = 0x00; /* no modem control for now */ *MPCC_COR6 = COR6_NORMAL_CR_NL | COR6_BRK_EXCEPTION | COR6_PARITY_EXCEPTION; *MPCC_COR7 = COR7_NORMAL_CR_NL; *MPCC_CMR = CMR_RX_INTERRUPT | CMR_TX_INTERRUPT | CMR_ASYNC_MODE; *MPCC_TBPR = BPR_9600; *MPCC_TCOR = TCOR_CLK1; *MPCC_RBPR = BPR_9600; *MPCC_RCOR = RCOR_CLK1; *MPCC_CPSR = CPSR_CRC_V41; *MPCC_SCHR1 = 0x00; *MPCC_SCHR2 = 0x00; *MPCC_SCHR3 = 0x00; /* Special Char Reg 3 */ *MPCC_SCHR4 = 0x00; /* Special Char Reg 4 */ *MPCC_SCRL = 0x00; /* Special Char Range Low */ *MPCC_SCRH = 0x00; /* Special Char Range High */ *MPCC_RTPRL = 0x01; /* set timeout high - ONLY DMA mode */ *MPCC_RTPRH = 0x00; /* so this should not be used for now */ while (*MPCC_CCR) ; /* make sure no outstanding commands */ *MPCC_CCR = CCR_INIT_CHANNEL; while (*MPCC_CCR) ; /* make sure we are done */ *MPCC_CCR = CCR_ENABLE_TRANS | CCR_ENABLE_REC; /* enable Tx and Rx */ while (*MPCC_CCR) ; *MPCC_IER = 0; /* disable interrupt */ *MPCC_MSVRDTR = MSVR_DTR; *MPCC_MSVRRTS = MSVR_RTS; pChan->created = TRUE; intUnlock (oldlevel); }/********************************************************************************* cd2400Ioctl - special device control** This routine handles SIO_BAUD_SET and SIO_RESET requests.** RETURNS: OK on success, EIO on device error, ENOSYS on unsupported* request.*/static int cd2400Ioctl ( SIO_CHAN * pSioChan, /* device to control */ int request, /* request code */ void * arg /* some argument */ ) { int oldlevel; /* current interrupt level mask */ FAST int ix; STATUS status; USHORT rcvBaud; char rcvFreq; CD2400_QUSART * pQusart = ((CD2400_CHAN *)pSioChan)->pQusart; switch (request) { case SIO_BAUD_SET: status = EIO; /* baud rate out of range */ /* disable interrupts during chip access */ oldlevel = intLock (); *MPCC_CAR = ((CD2400_CHAN *)pSioChan)->chan_num; /* channel */ for (ix = 0; ix < NELEMENTS (baudTable); ix++) { if (baudTable [ix].rate == (int)arg) { *MPCC_TBPR = ( (pQusart->baudClkFreq / baudTable [ix].timeConstant) / (int)arg ) - 1; *MPCC_TCOR = baudTable [ix].tcor; *MPCC_RBPR = ( (pQusart->baudClkFreq / baudTable [ix].timeConstant) / (int)arg ) - 1; *MPCC_RCOR = baudTable [ix].rcor; status = OK; break; } } intUnlock (oldlevel); break; case SIO_BAUD_GET: status = EIO; /* baud rate out of range */ /* disable interrupts during chip access */ oldlevel = intLock (); *MPCC_CAR = ((CD2400_CHAN *)pSioChan)->chan_num; /* channel */ rcvBaud = (unsigned char)(*MPCC_RBPR); rcvFreq = (*MPCC_RCOR) & 0x7; /* masked off unwanted bits */ for (ix = 0; ix < NELEMENTS (baudTable); ix++) { if ( (rcvBaud == ( (pQusart->baudClkFreq / baudTable [ix].timeConstant) / baudTable [ix].rate) - 1) && (rcvFreq == baudTable [ix].rcor) ) { *(int *)arg = baudTable [ix].rate; status = OK; } } 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(); cd2400SetMode ((CD2400_CHAN *)pSioChan, (int)arg); ((CD2400_CHAN *)pSioChan)->channelMode = (int)arg;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -