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

VxWorks

开发平台:

C/C++

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