📄 nvr4101siusio.c
字号:
/* nvr4101SIUSio.c - NEC VR4101 SIU UART tty driver *//* Copyright 1984-2002 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01b,24apr02,pmr SPR 75161: returning int from nvr4101SIUTxStartup() as required.01a,11jun97,sru written.*//*DESCRIPTIONThis is the device driver for the nvr4101 UART.USAGEA NVR4101_CHAN data structure is used to describe the SIU.The BSP's sysHwInit() routine typically calls sysSerialHwInit(), whichshould pass a pointer to an uninitialized NVR4101_CHAN structure tonvr4101SIUDevInit(). The BSP's sysHwInit2() routine typically callssysSerialHwInit2(), which connects the chip's interrupts viaintConnect().INCLUDE FILES: drv/sio/nvr4101SIUSio.h*/#include "vxWorks.h"#include "intLib.h"#include "logLib.h"#include "errnoLib.h"#include "errno.h"#include "sioLib.h"#include "memLib.h"#include "stdlib.h"#include "drv/multi/nvr4101.h"#include "drv/sio/nvr4101SIUSio.h"/* local defines */#define RX_INT_SOURCES (VR4101_ICU_SIU_RXG | /* 1-char reception end */ \ VR4101_ICU_SIU_RXE | /* rx DMA 2-page end */ \ VR4101_ICU_SIU_RXI) /* rx DMA 1-page end */#define TX_INT_SOURCES (VR4101_ICU_SIU_TXI | /* tx DMA 1-page end */ \ VR4101_ICU_SIU_TXE) /* tx DMA 2-page end *//* min/max baud rate */#define NVR4101_MIN_RATE 1200#define NVR4101_MAX_RATE 115200typedef struct /* BAUD */ { int rate; /* baud rate */ int cntl; /* control bits */ } BAUD;LOCAL BAUD baudTable [] = { { 1200, 0}, { 2400, 1}, { 4800, 2}, { 9600, 3}, { 19200, 4}, { 38400, 5}, { 57600, 6}, { 115200, 7} };LOCAL char txrxBuf [3 * DMA_PAGE_SIZE];/* function prototypes */LOCAL int nvr4101SIUCallbackInstall (SIO_CHAN *, int, STATUS (*)(), void *);LOCAL STATUS nvr4101SIUDummyCallback ();LOCAL void nvr4101SIUInitChannel (NVR4101_SIU_CHAN *);LOCAL STATUS nvr4101SIUIoctl (NVR4101_SIU_CHAN *, int, int);LOCAL int nvr4101SIUTxStartup (NVR4101_SIU_CHAN *);LOCAL int nvr4101SIUPollOutput (NVR4101_SIU_CHAN *, char);LOCAL int nvr4101SIUPollInput (NVR4101_SIU_CHAN *, char *);LOCAL void nvr4101SIUIntMask ();LOCAL void nvr4101SIUIntUnmask ();LOCAL UINT16 nvr4101SIUCharToTxWord (char outChar);LOCAL char nvr4101SIURxWordToChar (UINT16 inWord);LOCAL void nvr4101SIUTxOutput (NVR4101_SIU_CHAN *pChan, char outChar);/* driver functions */LOCAL SIO_DRV_FUNCS nvr4101SIUSioDrvFuncs = { (int (*)())nvr4101SIUIoctl, (int (*)())nvr4101SIUTxStartup, (int (*)())nvr4101SIUCallbackInstall, (int (*)())nvr4101SIUPollInput, (int (*)(SIO_CHAN *,char))nvr4101SIUPollOutput };/******************************************************************************** nvr4101SIUDummyCallback - dummy callback routine.*/LOCAL STATUS nvr4101SIUDummyCallback (void) { return (ERROR); }/******************************************************************************** nvr4101SIUDevInit - initialization of the NVR4101SIU SIU.** This routine initializes some SIO_CHAN function pointers and then resets* the chip in a quiescent state. No initialization of the NVR4101_SIU_CHAN* structure is required before this routine is called.** RETURNS: N/A*/void nvr4101SIUDevInit ( NVR4101_SIU_CHAN * pChan ) { int oldlevel; oldlevel = intLock (); /* initialize the driver function pointers in the SIO_CHAN's */ pChan->sio.pDrvFuncs = &nvr4101SIUSioDrvFuncs; pChan->getTxChar = nvr4101SIUDummyCallback; pChan->putRcvChar = nvr4101SIUDummyCallback; /* set the SIU state variables */ pChan->txActive = FALSE; pChan->channelMode = -1; /* so ioctl will notice first change */ /* construct pointers to rx/tx buffers aligned with DMA boundaries */ pChan->pTxBuf = (char *) ROUND_UP ((int) txrxBuf, DMA_PAGE_SIZE); pChan->pTxBuf = (char *) K0_TO_K1 (pChan->pTxBuf); pChan->pRxBuf = pChan->pTxBuf + DMA_PAGE_SIZE; /* construct pointers to the 2nd-to-last word in each buffer */ pChan->pTxWord = ((UINT16 *) (pChan->pTxBuf + DMA_PAGE_SIZE)) - 2; pChan->pRxWord = ((UINT16 *) (pChan->pRxBuf + DMA_PAGE_SIZE)) - 2; /* make the last word a word of all stop bits */ pChan->pTxWord[1] = ~0; pChan->pTxWord[1] = ~0; /* reset the SIU */ nvr4101SIUInitChannel (pChan); intUnlock (oldlevel); }/********************************************************************************* nvr4101SIUInitChannel - initialize UART** RETURNS: N/A.*/LOCAL void nvr4101SIUInitChannel ( NVR4101_SIU_CHAN *pChan ) { UINT32 rxAdr; /* enable SIU clock from within the CIU subsystem */ *VR4101_CMUCLKMSK |= VR4101_MSKSIU; /* forcibly reset the SIU */ *VR4101_SIUCNTREG |= VR4101_SIU_SRST; /* * Set transmit length of 1 start bit, 8 data bits, 1 stop bit, * no parity. (1+8+1 = 10). The receive length is identical, * except that the stop bit is not included in the calculation, * so the receive length is one less than the transmit length. */ *VR4101_SIUDLENGTHREG = (10 << VR4101_SIU_TX_CHAR_WIDTH_SHIFT) | (9 << VR4101_SIU_RX_CHAR_WIDTH_SHIFT) | VR4101_SIU_STOP_BITS_1; /* * Select RS232 mode, and set transmit and receive DMA stop * addresses at page 1 boundary. */ *VR4101_SIUCNTREG = VR4101_SIU_RS232_MODE | VR4101_SIU_RSP | VR4101_SIU_TSP; /* Confirm that DTR and RTS are high. */ *VR4101_SIURS232CREG = VR4101_SIU_DTR | VR4101_SIU_RTS; /* Set receive DMA address pointer */ rxAdr = K0_TO_K1 (pChan->pRxWord); *VR4101_SRXDMAADRLREG = (UINT16) rxAdr; *VR4101_SRXDMAADRHREG = (UINT16) (rxAdr >> 16); /* enable the receiver */ *VR4101_SIUCNTREG |= VR4101_SIU_RXE; /* * unmask the desired interrupts. Note that the SIU summary interrupt * bit within the VR4101_ICU_MSYSINTREG register is _not_ enabled * by this driver. This allows other parts of the BSP to * selectively enable or disable the entire SIU using the summary bit, * and hides the details of the specific unmasked SIU interrupts within * this driver. */ nvr4101SIUIntUnmask (); }/********************************************************************************* nvr4101SIUIoctl - special device control** RETURNS: OK on success, EIO on device error, ENOSYS on unsupported* request.*/LOCAL STATUS nvr4101SIUIoctl ( NVR4101_SIU_CHAN *pChan, /* device to control */ int request, /* request code */ int arg /* some argument */ ) { int oldlevel; STATUS status; int i; status = OK; switch (request) { case SIO_BAUD_SET: status = EIO; /* assume baud rate out of range */ for (i = 0; i < NELEMENTS (baudTable); i++) { if (baudTable [i].rate == (int)arg) { pChan->baudRate = arg; oldlevel = intLock (); *VR4101_SIUBAUDSELREG = baudTable [i].cntl; intUnlock (oldlevel); status = OK; break; } } break; case SIO_BAUD_GET: *(int *)arg = pChan->baudRate; break; case SIO_MODE_SET: if ((arg != SIO_MODE_POLL) && (arg != SIO_MODE_INT)) { status = EIO; break; } if (arg != pChan->channelMode) { if (arg == SIO_MODE_INT) { /* clear all pending interrupts */ *VR4101_SIUINTREG = TX_INT_SOURCES | RX_INT_SOURCES; /* mark that we're not awaiting xmit interrupt */ pChan->txActive = FALSE; /* Enable appropriate interrupts */ nvr4101SIUIntUnmask (); } else { /* Disable the interrupts */ nvr4101SIUIntMask (); } pChan->channelMode = arg; } break; case SIO_MODE_GET: *(int *)arg = pChan->channelMode; break; case SIO_AVAIL_MODES_GET: *(int *)arg = SIO_MODE_INT | SIO_MODE_POLL; break; case SIO_HW_OPTS_SET: case SIO_HW_OPTS_GET: default: status = ENOSYS; } return (status);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -