nvr4101DSIUSio.c
上传用户:luoyougen
上传日期:2008-05-12
资源大小:23136k
文件大小:12k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* nvr4101DSIUSio.c - NEC VR4101 DSIU UART tty driver */
  2. /* Copyright 1984-2002 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01b,24apr02,pmr  SPR 75161: returning int from nvr4101DSIUTxStartup() as
  8.                  required.
  9. 01a,23jun97,sru  written.
  10. */
  11. /*
  12. DESCRIPTION
  13. This is the device driver for the nvr4101 DSIU UART.
  14. USAGE
  15. An NVR4101_DSIU_CHAN data structure is used to describe the DSIU.
  16. The BSP's sysHwInit() routine typically calls sysSerialHwInit(), which
  17. should pass a pointer to an uninitialized NVR4101_DSIU_CHAN structure to
  18. nvr4101DSIUDevInit().  The BSP's sysHwInit2() routine typically calls
  19. sysSerialHwInit2(), which connects the chip's interrupts via
  20. intConnect().
  21. INCLUDE FILES: drv/sio/nvr4101DSIUSio.h
  22. */
  23. #include "vxWorks.h"
  24. #include "intLib.h"
  25. #include "logLib.h"
  26. #include "errnoLib.h"
  27. #include "errno.h"
  28. #include "sioLib.h"
  29. #include "memLib.h"
  30. #include "stdlib.h"
  31. #include "drv/multi/nvr4101.h"
  32. #include "drv/sio/nvr4101DSIUSio.h"
  33. /* local defines */
  34. #define RX_DSIU_INT_SOURCES VR4101_INTSR0
  35. #define TX_DSIU_INT_SOURCES VR4101_INTST0
  36. #define RX_ICU_INT_SOURCES  VR4101_ICU_SIU_INTSR0
  37. #define TX_ICU_INT_SOURCES  VR4101_ICU_SIU_INTST0
  38. /* min/max baud rate */
  39. #define NVR4101_MIN_RATE 1200
  40. #define NVR4101_MAX_RATE 115200
  41. typedef struct /* BAUD */
  42.     {
  43.     int rate;        /* baud rate */
  44.     int cntl;        /* control bits */
  45.     } BAUD;
  46. LOCAL BAUD baudTable [] =
  47.     {
  48.     {   1200, 0},
  49.     {   2400, 1},
  50.     {   4800, 2},
  51.     {   9600, 3},
  52.     {  19200, 4},
  53.     {  38400, 5},
  54.     {  57600, 6},
  55.     { 115200, 7}
  56.     };
  57. /* function prototypes */
  58. LOCAL int nvr4101DSIUCallbackInstall (SIO_CHAN *, int, STATUS (*)(), void *);
  59. LOCAL STATUS nvr4101DSIUDummyCallback ();
  60. LOCAL void nvr4101DSIUInitChannel (NVR4101_DSIU_CHAN *);
  61. LOCAL STATUS nvr4101DSIUIoctl (NVR4101_DSIU_CHAN *, int, int);
  62. LOCAL int nvr4101DSIUTxStartup (NVR4101_DSIU_CHAN *);
  63. LOCAL int nvr4101DSIUPollOutput (NVR4101_DSIU_CHAN *, char);
  64. LOCAL int nvr4101DSIUPollInput (NVR4101_DSIU_CHAN *, char *);
  65. LOCAL void nvr4101DSIUIntMask ();
  66. LOCAL void nvr4101DSIUIntUnmask ();
  67. /* driver functions */
  68. LOCAL SIO_DRV_FUNCS nvr4101DSIUSioDrvFuncs =
  69.     {
  70.     (int (*)())nvr4101DSIUIoctl,
  71.     (int (*)())nvr4101DSIUTxStartup,
  72.     (int (*)())nvr4101DSIUCallbackInstall,
  73.     (int (*)())nvr4101DSIUPollInput,
  74.     (int (*)(SIO_CHAN *,char))nvr4101DSIUPollOutput
  75.     };
  76. /******************************************************************************
  77. *
  78. * nvr4101DSIUDummyCallback - dummy callback routine.
  79. */
  80. LOCAL STATUS nvr4101DSIUDummyCallback (void)
  81.     {
  82.     return (ERROR);
  83.     }
  84. /******************************************************************************
  85. *
  86. * nvr4101DSIUDevInit - initialization of the NVR4101DSIU DSIU.
  87. *
  88. * This routine initializes some SIO_CHAN function pointers and then resets
  89. * the chip in a quiescent state.  The caller needs to initialize the
  90. * channel structure with the requested word length and parity.
  91. *
  92. * RETURNS: N/A
  93. */
  94. void nvr4101DSIUDevInit
  95.     (
  96.     NVR4101_DSIU_CHAN * pChan
  97.     )
  98.     {
  99.     int oldlevel;
  100.     oldlevel = intLock ();
  101.     /* initialize the driver function pointers in the SIO_CHAN's */
  102.     pChan->sio.pDrvFuncs = &nvr4101DSIUSioDrvFuncs;
  103.     pChan->getTxChar = nvr4101DSIUDummyCallback;
  104.     pChan->putRcvChar = nvr4101DSIUDummyCallback;
  105.     /* set the DSIU state variables */
  106.     pChan->txActive = FALSE;
  107.     pChan->channelMode = -1;  /* so ioctl will notice first change */
  108.     /* reset the DSIU */
  109.     nvr4101DSIUInitChannel (pChan);
  110.     intUnlock (oldlevel);
  111.     }
  112. /*******************************************************************************
  113. *
  114. * nvr4101DSIUInitChannel - initialize UART
  115. *
  116. * RETURNS: N/A.
  117. */
  118. LOCAL void nvr4101DSIUInitChannel
  119.     (
  120.     NVR4101_DSIU_CHAN *pChan
  121.     )
  122.     {
  123.     /* forcibly reset the DSIU */
  124.     *VR4101_DSIURESETREG = VR4101_DSIURST;
  125.     /*
  126.      * Enable data reception, 1 stop bit, user-selected parity and 
  127.      * user-selected word length.
  128.      */
  129.     *VR4101_ASIM00REG = VR4101_ASIM00REG_RESERVED | /* mandatory "1" bit */
  130.        VR4101_RXE0 |     /* enable reception */
  131.        VR4101_DSIU_STOPBITS_1 |    /* 1 stop bit */
  132. #if 1
  133.        (pChan->parityStyle << VR4101_DSIU_PAR_SHIFT) |
  134.        ((pChan->wordLength == 7) ? VR4101_DSIU_CHARLEN_7 :
  135.            VR4101_DSIU_CHARLEN_8);
  136. #else
  137.        VR4101_DSIU_PAR_EVEN |
  138. VR4101_DSIU_CHARLEN_7;
  139. #endif
  140.     /*
  141.      * Unmask the desired interrupts.  Note that the (D)SIU summary interrupt
  142.      * bit within the VR4101_ICU_MSYSINTREG register is _not_ enabled
  143.      * by this driver.  This allows other parts of the BSP to
  144.      * selectively enable or disable the entire (D)SIU using the summary bit, 
  145.      * and hides the details of the specific unmasked (D)SIU interrupts within 
  146.      * this driver. 
  147.      */
  148.     nvr4101DSIUIntUnmask ();
  149.     }
  150. /*******************************************************************************
  151. *
  152. * nvr4101DSIUIoctl - special device control
  153. *
  154. * RETURNS: OK on success, EIO on device error, ENOSYS on unsupported
  155. *          request.
  156. */
  157. LOCAL STATUS nvr4101DSIUIoctl
  158.     (
  159.     NVR4101_DSIU_CHAN *pChan, /* device to control */
  160.     int        request, /* request code */
  161.     int        arg /* some argument */
  162.     )
  163.     {
  164.     int oldlevel;
  165.     STATUS status;
  166.     int i;
  167.     status = OK;
  168.     switch (request)
  169. {
  170. case SIO_BAUD_SET:
  171.             status = EIO;  /* assume baud rate out of range */
  172.             for (i = 0; i < NELEMENTS (baudTable); i++)
  173.                 {
  174.                 if (baudTable [i].rate == (int)arg)
  175.                     {
  176.     pChan->baudRate = arg;
  177.     oldlevel = intLock ();
  178.     *VR4101_BPRM0REG = baudTable [i].cntl | VR4101_BRCE0;
  179.     intUnlock (oldlevel);
  180.                     status = OK;
  181.                     break;
  182.                     }
  183.         }
  184.     break;
  185.         case SIO_BAUD_GET:
  186.             *(int *)arg = pChan->baudRate;
  187.             break; 
  188.         case SIO_MODE_SET:
  189.             if ((arg != SIO_MODE_POLL) && (arg != SIO_MODE_INT))
  190.                 {
  191.                 status = EIO;
  192.                 break;
  193.                 }
  194.            
  195.     if (arg != pChan->channelMode)
  196. {
  197. if (arg == SIO_MODE_INT)
  198.     {
  199.     /* clear all pending interrupts */
  200.     *VR4101_INTR0REG = TX_DSIU_INT_SOURCES | 
  201.        RX_DSIU_INT_SOURCES;
  202.     /* mark that we're not awaiting xmit interrupt */
  203.     pChan->txActive = FALSE;
  204.     /* Enable appropriate interrupts */
  205.     nvr4101DSIUIntUnmask ();
  206.     }
  207. else
  208.     {
  209.     /* Disable the interrupts */ 
  210.     
  211.     nvr4101DSIUIntMask ();
  212.     }
  213. pChan->channelMode = arg;
  214. }
  215.             break;          
  216.         case SIO_MODE_GET:
  217.             *(int *)arg = pChan->channelMode;
  218.             break;
  219.         case SIO_AVAIL_MODES_GET:
  220.             *(int *)arg = SIO_MODE_INT | SIO_MODE_POLL;
  221.             break;
  222.         case SIO_HW_OPTS_SET:
  223.         case SIO_HW_OPTS_GET:
  224.         default:
  225.             status = ENOSYS;
  226. }
  227.     return (status);
  228.     }
  229. /********************************************************************************
  230. * nvr4101DSIUInt - interrupt level processing
  231. *
  232. * This routine handles interrupts from the DSIU.
  233. *
  234. * RETURNS: N/A
  235. */
  236. void nvr4101DSIUInt
  237.     (
  238.     NVR4101_DSIU_CHAN *pChan
  239.     )
  240.     {
  241.     UINT16  statusReg;
  242.     char outChar;
  243.     /* get status from the DSIU (not ICU) subsystem.  */
  244.     statusReg = *VR4101_INTR0REG;
  245.     /* write status value back out to clear the various sources */
  246.     *VR4101_INTR0REG = statusReg;
  247.     /* handle receiver interrupt */
  248.     if (statusReg & RX_DSIU_INT_SOURCES)
  249. {
  250. (*pChan->putRcvChar) (pChan->putRcvArg, (char) *VR4101_RXB0LREG);
  251.       
  252. }
  253.     /* handle transmitter interrupt */
  254.     if (statusReg & TX_DSIU_INT_SOURCES)
  255. {
  256. if ((*pChan->getTxChar) (pChan->getTxArg, &outChar) != ERROR)
  257.     {
  258.     /* transmit the next character */
  259.     *VR4101_TXS0LREG = (UINT16) outChar;
  260.     }
  261. else
  262.     {
  263.     /* note that TxStartup will need to generate next character */
  264.     pChan->txActive = FALSE;
  265.     }
  266. }
  267.     }
  268. /*******************************************************************************
  269. *
  270. * nvr4101DSIUTxStartup - transmitter startup routine.
  271. *
  272. * This routine is called to restart data output.  the VR4101 does not
  273. * provide a mechanism to regenerate a transmit interrupt, so this
  274. * function needs to perform the work involved in setting up the data
  275. * transmission.
  276. *
  277. * RETURNS: OK, or ENOSYS if in polled mode.
  278. */
  279. LOCAL int nvr4101DSIUTxStartup
  280.     (
  281.     NVR4101_DSIU_CHAN *pChan 
  282.     )
  283.     {
  284.     char outChar;
  285.     int oldLevel;
  286.     if (pChan->channelMode == SIO_MODE_INT)
  287. {
  288. oldLevel = intLock ();
  289. /* ignore request if expecting transmitter interrupt */
  290. if (pChan->txActive)
  291.     {
  292.     intUnlock (oldLevel);
  293.     return (OK);
  294.     }
  295. /* mark that we've started transmission */
  296. pChan->txActive = TRUE;
  297. intUnlock (oldLevel);
  298. /* initiate transmission of the next character */
  299. (void) (*pChan->getTxChar) (pChan->getTxArg, &outChar);
  300. *VR4101_TXS0LREG = (UINT16) outChar;
  301. return (OK);
  302. }
  303.     else 
  304. {
  305. return (ENOSYS);
  306. }
  307.     }
  308. /******************************************************************************
  309. *
  310. * nvr4101DSIUPollOutput - output a character in polled mode.
  311. *
  312. * RETURNS: OK if a character arrived, EIO on device error, EAGAIN
  313. *          if the output buffer if full.
  314. */
  315. LOCAL int nvr4101DSIUPollOutput
  316.     (
  317.     NVR4101_DSIU_CHAN *  pChan,
  318.     char            outChar
  319.     )
  320.     {
  321.     /* if transmitting, come back later */
  322.     if (*VR4101_ASIS0REG & VR4101_SOT0)
  323. return (EAGAIN);
  324.     /* transmit the character */
  325.     *VR4101_TXS0LREG = (UINT16) outChar;
  326.     return (OK);
  327.     }
  328. /******************************************************************************
  329. *
  330. * nvr4101DSIUPollInput - poll the device for input.
  331. *
  332. * RETURNS: OK if a character arrived, EIO on device error, EAGAIN
  333. *          if the input buffer if empty.
  334. */
  335. LOCAL int nvr4101DSIUPollInput
  336.     (
  337.     NVR4101_DSIU_CHAN *  pChan,
  338.     char *          thisChar
  339.     )
  340.     {
  341.     /* if no receive interrupt, come back later */
  342.     if (! (*VR4101_INTR0REG & RX_DSIU_INT_SOURCES))
  343. return (EAGAIN);
  344.     /* receive the character */
  345.     *thisChar = (char) *VR4101_RXB0LREG;
  346.     /* clear the interrupt */
  347.     *VR4101_INTR0REG = RX_DSIU_INT_SOURCES;
  348.     return (OK);
  349.     }
  350. /******************************************************************************
  351. *
  352. * nvr4101DSIUCallbackInstall - install ISR callbacks to get/put chars.
  353. */
  354. LOCAL int nvr4101DSIUCallbackInstall
  355.     (
  356.     SIO_CHAN *  pSioChan,
  357.     int         callbackType,
  358.     STATUS      (*callback)(),
  359.     void *      callbackArg
  360.     )
  361.     {
  362.     NVR4101_DSIU_CHAN * pChan = (NVR4101_DSIU_CHAN *) pSioChan;
  363.     switch (callbackType)
  364.         {
  365.         case SIO_CALLBACK_GET_TX_CHAR:
  366.             pChan->getTxChar    = callback;
  367.             pChan->getTxArg     = callbackArg;
  368.             return (OK);
  369.         case SIO_CALLBACK_PUT_RCV_CHAR:
  370.             pChan->putRcvChar   = callback;
  371.             pChan->putRcvArg    = callbackArg;
  372.             return (OK);
  373.         default:
  374.             return (ENOSYS);
  375.         }
  376.     }
  377. /******************************************************************************
  378. *
  379. * nvr4101DSIUIntMask - Mask interrupts from the DSIU.
  380. * This function masks all possible interrupts from the DSIU subsystem.
  381. *
  382. * RETURNS: N/A
  383. */
  384. void nvr4101DSIUIntMask()
  385.     {
  386.     int oldLevel = intLock ();
  387.     *VR4101_ICU_MSIUINTREG &= ~(RX_ICU_INT_SOURCES | TX_ICU_INT_SOURCES);
  388.     intUnlock (oldLevel);
  389.     }
  390. /******************************************************************************
  391. *
  392. * nvr4101DSIUIntUnmask - Unmask interrupts from the DSIU.
  393. * This function unmasks all desired interrupts from the DSIU subsystem.
  394. *
  395. * RETURNS: N/A
  396. */
  397. void nvr4101DSIUIntUnmask()
  398.     {
  399.     int oldLevel = intLock ();
  400.     *VR4101_ICU_MSIUINTREG |= (RX_ICU_INT_SOURCES | TX_ICU_INT_SOURCES);
  401.     intUnlock (oldLevel);
  402.     }