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

VxWorks

开发平台:

C/C++

  1. /* m5204Sio.c - m5204 Serial Communications driver */
  2. /* Copyright 1984-1996 Wind River Systems, Inc. */
  3. /*
  4. modification history
  5. --------------------
  6. 01b,05may97,mem  changed baud rate calculation to round rather than
  7.  truncate when dividing.  Reduces error at high baud rates.
  8. 01a,10dec96,mem  written.
  9. */
  10. /*
  11. DESCRIPTION
  12. This is the driver for the UART contained in the m5204 Microcontroller.
  13. Only asynchronous serial operation is supported by this driver.  The
  14. default serial settings are 8 data bits, 1 stop bit, no parity, 9600
  15. buad, and software flow control.  These default settings can be
  16. overridden by setting the M5204_CHAN options and baudRate fields to
  17. the desired values before calling m5204DevInit.  See sioLib.h for
  18. options values.  The defaults for the module can be changed by
  19. redefining the macros M5204_DEFAULT_OPTIONS and M5204_DEFAULT_BAUD and
  20. recompiling this driver.
  21. This driver uses the system clock as the input to the baud rate
  22. generator.  The clkRate field must be set to the system clock rate in
  23. HZ for the baud rate calculations to work correctly.  The actual range
  24. of supported baud rates depends on the system clock speed.  For example,
  25. with a 25MHz system clock, the lowest baud rate is 24, and the highest
  26. is over 38400.  Because the baud rate values are calculated on request,
  27. there is no checking that the requested baud rate is standard, you can
  28. set the UART to operate at 4357 baud if you wish.
  29. USAGE
  30. A M5204_CHAN structure is used to describe the chip.
  31. The BSP's sysHwInit() routine typically calls sysSerialHwInit()
  32. which initializes all the H/W addresses in the M5204_CHAN structure
  33. before calling m5204DevInit().  This enables the chip to operate in
  34. polled mode, but not interrupt mode.  Calling m5204DevInit2() from
  35. the sysSerialHwInit2() routine allows interrupts to be enabled and
  36. interrupt mode operation to be used.
  37. .CS
  38. i.e.
  39. #include "drv/multi/m5204Sio.h"
  40. M5204_CHAN m5204Uart; /@ my device structure @/
  41. #define INT_VEC_UART (24+3) /@ use single vector, #27 @/
  42. sysSerialHwInit()
  43.     {
  44.     /@ initialize the register pointers/data for uart @/
  45.     m5204Uart.clkRate = MASTER_CLOCK;
  46.     m5204Uart.intVec = INT_VEC_UART;
  47.     m5204Uart.mr = M5204_UART_MR(SIM_BASE);
  48.     m5204Uart.sr = M5204_UART_SR(SIM_BASE);
  49.     m5204Uart.csr = M5204_UART_CSR(SIM_BASE);
  50.     m5204Uart.cr = M5204_UART_CR(SIM_BASE);
  51.     m5204Uart.rb = M5204_UART_RB(SIM_BASE);
  52.     m5204Uart.tb = M5204_UART_TB(SIM_BASE);
  53.     m5204Uart.ipcr = M5204_UART_IPCR(SIM_BASE);
  54.     m5204Uart.acr = M5204_UART_ACR(SIM_BASE);
  55.     m5204Uart.isr = M5204_UART_ISR(SIM_BASE);
  56.     m5204Uart.imr = M5204_UART_IMR(SIM_BASE);
  57.     m5204Uart.bg1 = M5204_UART_BG1(SIM_BASE);
  58.     m5204Uart.bg2 = M5204_UART_BG2(SIM_BASE);
  59.     m5204Uart.ivr = M5204_UART_IVR(SIM_BASE);
  60.     m5204Uart.ip = M5204_UART_IP(SIM_BASE);
  61.     m5204Uart.op1 = M5204_UART_OP1(SIM_BASE);
  62.     m5204Uart.op2 = M5204_UART_OP2(SIM_BASE);
  63.     m5204DevInit (&m5204Uart);
  64.     }
  65. .CE
  66. The BSP's sysHwInit2() routine typically calls sysSerialHwInit2() which
  67. connects the chips interrupts via intConnect() to the single
  68. interrupt handler m5204Int.  After the interrupt service routines are 
  69. connected, the user then calls m5204DevInit2() to allow the driver to 
  70. turn on interrupt enable bits.
  71. .CS
  72. i.e.
  73. sysSerialHwInit2 ()
  74.     {
  75.     /@ connect single vector for 5204 @/
  76.     intConnect (INUM_TO_IVEC(MY_VEC), m5204Int, (int)&m5204Uart);
  77.     ...
  78.     /@ allow interrupts to be enabled @/
  79.     m5204DevInit2 (&m5204Uart);
  80.     }
  81. .CE
  82. SPECIAL CONSIDERATIONS:
  83. The CLOCAL hardware option presumes that CTS outputs are wired as
  84. necessary.  If not wired correctly, then the user must not select the
  85. CLOCAL option.  CLOCAL is not one of the default options for this
  86. reason.
  87. As to the output port, this driver does not manipulate the output port,
  88. or it's configuration register in any way.  As stated above, if the user
  89. selects the CLOCAL option then the output port bit must be wired correctly
  90. or the hardware flow control will not function as desired.
  91. INCLUDE FILES: drv/sio/m5204Sio.h
  92. */
  93. #include "vxWorks.h"
  94. #include "sioLib.h"
  95. #include "intLib.h"
  96. #include "errno.h"
  97. #include "drv/multi/m5204.h"
  98. #include "drv/sio/m5204Sio.h"
  99. /* forward static declarations */
  100. LOCAL STATUS m5204ModeSet (M5204_CHAN *, UINT);
  101. LOCAL STATUS m5204BaudSet (M5204_CHAN *, UINT);
  102. LOCAL STATUS m5204OptsSet (M5204_CHAN *, UINT);
  103. LOCAL int    m5204Ioctl (M5204_CHAN *, int, void *);
  104. LOCAL int    m5204TxStartup (M5204_CHAN *);
  105. LOCAL int    m5204CallbackInstall (M5204_CHAN *, int, STATUS (*)(), void *);
  106. LOCAL int    m5204PollInput (M5204_CHAN *, char *);
  107. LOCAL int    m5204PollOutput (M5204_CHAN*, char);
  108. LOCAL STATUS m5204DummyCallback (void);
  109.       void m5204AcrSetClr (M5204_CHAN * pChan, UCHAR setBits, UCHAR clearBits);
  110.       void m5204ImrSetClr (M5204_CHAN * pChan, UCHAR setBits, UCHAR clearBits);
  111. /* driver functions */
  112. LOCAL SIO_DRV_FUNCS m5204SioDrvFuncs =
  113.     {
  114.     (int (*)(SIO_CHAN *, int, void *))m5204Ioctl,
  115.     (int (*)(SIO_CHAN *))m5204TxStartup,
  116.     (int (*)())m5204CallbackInstall,
  117.     (int (*)(SIO_CHAN *, char*))m5204PollInput,
  118.     (int (*)(SIO_CHAN *, char))m5204PollOutput
  119.     };
  120. /* typedefs */
  121. /* defines */
  122. #ifndef M5204_DEFAULT_BAUD
  123. #   define M5204_DEFAULT_BAUD  9600
  124. #endif
  125. #ifndef M5204_DEFAULT_OPTIONS
  126.     /* no handshake, rcvr enabled, 8 data bits, 1 stop bit, no parity */
  127. #   define M5204_DEFAULT_OPTIONS (CREAD | CS8)
  128. #endif
  129. /* Hardware read/write routines.  Can be redefined to create drivers
  130.  * for boards with special i/o access procedures. The reg pointer
  131.  * arguments are the register pointers from the M5204_CHAN structure.
  132.  */
  133. #ifndef M5204_READ
  134. #   define M5204_READ(x) (*x) /* argument is register pointer */
  135. #endif
  136. #ifndef M5204_WRITE
  137. #   define M5204_WRITE(x,y) (*x = y) /* args are reg ptr and data */
  138. #endif
  139. #define MAX_OPTIONS (0xff)
  140. /******************************************************************************
  141. *
  142. * m5204DevInit - intialize a M5204_CHAN
  143. *
  144. * The BSP must have already initialized all the device addresses, etc in
  145. * m5204_CHAN structure. This routine initializes some transmitter &
  146. * receiver status values to be used in the interrupt mask register and then
  147. * resets the chip to a quiescent state.
  148. *
  149. * RETURNS: N/A
  150. */
  151. void m5204DevInit
  152.     (
  153.     M5204_CHAN * pChan
  154.     )
  155.     {
  156.     int oldlevel;
  157.     
  158.     pChan->pDrvFuncs = &m5204SioDrvFuncs;
  159.     pChan->getTxChar = m5204DummyCallback;
  160.     pChan->putRcvChar = m5204DummyCallback;
  161.     pChan->mode = 0; /* undefined */
  162.     pChan->intEnable = FALSE;
  163.     pChan->acrCopy = 0;
  164.     pChan->imrCopy = 0;
  165.     pChan->oprCopy = 0;
  166.     if (pChan->options == 0 || pChan->options > MAX_OPTIONS)
  167. pChan->options = M5204_DEFAULT_OPTIONS;
  168.     /* baud rate range is determined by calculation. */
  169.     if (pChan->baudRate)
  170. {
  171. UINT val;
  172. val = ((pChan->clkRate / pChan->baudRate) + 16) / 32;
  173. if ((val < 2) || (val > 0xffff))
  174.     pChan->baudRate = M5204_DEFAULT_BAUD;
  175. }
  176.     else
  177. pChan->baudRate = M5204_DEFAULT_BAUD;
  178.     oldlevel =  intLock ();
  179.     m5204ImrSetClr (pChan, 0, ~0);
  180.     m5204AcrSetClr (pChan, 0, M5204_UART_ACR_IEC);
  181.     /* Use internal timer */
  182.     M5204_WRITE (pChan->csr,
  183.  M5204_UART_CSR_TIMER_RX | M5204_UART_CSR_TIMER_TX);
  184.     /* Reset the transmitters  & receivers  */
  185.     M5204_WRITE (pChan->cr, M5204_UART_CR_RESET_RX);
  186.     M5204_WRITE (pChan->cr, M5204_UART_CR_RESET_TX);
  187.     M5204_WRITE (pChan->cr, M5204_UART_CR_RESET_ERR);
  188.     /* TX is disabled */
  189.     m5204OptsSet (pChan, pChan->options);
  190.     m5204BaudSet (pChan, pChan->baudRate);
  191.     intUnlock (oldlevel);
  192.     }
  193. /******************************************************************************
  194. *
  195. * m5204DevInit2 - intialize a M5204_CHAN, part 2
  196. *
  197. * This routine is called as part of sysSerialHwInit2() and tells
  198. * the driver that interrupt vectors are connected and that it is
  199. * safe to allow interrupts to be enabled.
  200. *
  201. * RETURNS: N/A
  202. */
  203. void m5204DevInit2
  204.     (
  205.     M5204_CHAN * pChan
  206.     )
  207.     {
  208.     /* Allow interrupt mode */
  209.     pChan->intEnable = TRUE;
  210.     M5204_WRITE(pChan->ivr, pChan->intVec);
  211.     m5204ModeSet (pChan, pChan->mode);
  212.     }
  213. /******************************************************************************
  214. *
  215. * m5204ImrSetClr - set and clear bits in the UART's interrupt mask register
  216. *
  217. * This routine sets and clears bits in the UART's IMR.
  218. *
  219. * This routine sets and clears bits in a local copy of the IMR, then
  220. * writes that local copy to the UART.  This means that all changes to
  221. * the IMR must go through this routine.  Otherwise, any direct changes
  222. * to the IMR would be lost the next time this routine is called.
  223. *
  224. * Set has priority over clear.  Thus you can use this routine to update
  225. * multiple bit fields by specifying the field mask as the clear bits.
  226. *
  227. * RETURNS: N/A
  228. */
  229. void m5204ImrSetClr
  230.     (
  231.     M5204_CHAN * pChan,
  232.     UCHAR setBits,       /* which bits to set in the IMR   */
  233.     UCHAR clearBits      /* which bits to clear in the IMR */
  234.     )
  235.     {
  236.     pChan->imrCopy = ((pChan->imrCopy & ~clearBits) | setBits);
  237.     M5204_WRITE (pChan->imr, pChan->imrCopy);
  238.     }
  239. /******************************************************************************
  240. *
  241. * m5204Imr - return current interrupt mask register contents
  242. *
  243. * This routine returns the interrupt mask register contents.  The imr
  244. * is not directly readable, a copy of the last value written is kept
  245. * in the UART data structure.
  246. *
  247. * RETURNS: Returns interrupt mask register contents.
  248. */
  249. UCHAR m5204Imr
  250.     (
  251.     M5204_CHAN * pChan
  252.     )
  253.     {
  254.     return pChan->imrCopy;
  255.     }
  256. /******************************************************************************
  257. *
  258. * m5204AcrSetClr - set and clear bits in the UART's aux control register
  259. *
  260. * This routine sets and clears bits in the UART's ACR.
  261. *
  262. * This routine sets and clears bits in a local copy of the ACR, then
  263. * writes that local copy to the UART.  This means that all changes to
  264. * the ACR must go through this routine.  Otherwise, any direct changes
  265. * to the ACR would be lost the next time this routine is called.
  266. *
  267. * Set has priority over clear.  Thus you can use this routine to update
  268. * multiple bit fields by specifying the field mask as the clear bits.
  269. *
  270. * RETURNS: N/A
  271. */
  272. void m5204AcrSetClr
  273.     (
  274.     M5204_CHAN * pChan,
  275.     UCHAR setBits,       /* which bits to set in the ACR   */
  276.     UCHAR clearBits      /* which bits to clear in the ACR */
  277.     )
  278.     {
  279.     pChan->acrCopy = ((pChan->acrCopy &  ~clearBits) | setBits);
  280.     M5204_WRITE (pChan->acr, pChan->acrCopy);
  281.     }
  282. /******************************************************************************
  283. *
  284. * m5204Acr - return aux control register contents
  285. *
  286. * This routine returns the auxilliary control register contents.  The acr
  287. * is not directly readable, a copy of the last value written is kept
  288. * in the UART data structure.
  289. *
  290. * RETURNS: Returns auxilliary control register (acr) contents.
  291. */
  292. UCHAR m5204Acr
  293.     (
  294.     M5204_CHAN * pChan
  295.     )
  296.     {
  297.     return pChan->acrCopy;
  298.     }
  299. /******************************************************************************
  300. *
  301. * m5204OprSetClr - set and clear bits in the output port register
  302. *
  303. * This routine sets and clears bits in the UART's OPR.
  304. *
  305. * A copy of the current opr contents is kept in the UART data structure.
  306. *
  307. * RETURNS: N/A
  308. */
  309. void m5204OprSetClr
  310.     (
  311.     M5204_CHAN * pChan,
  312.     UCHAR setBits,       /* which bits to set in the OPR   */
  313.     UCHAR clearBits      /* which bits to clear in the OPR */
  314.     )
  315.     {
  316.     pChan->oprCopy = ((pChan->oprCopy &  ~clearBits) | setBits);
  317.     M5204_WRITE (pChan->op2, clearBits);
  318.     M5204_WRITE (pChan->op1, setBits);
  319.     }
  320. /******************************************************************************
  321. *
  322. * m5204Opr - return the current state of the output register
  323. *
  324. * This routine returns the current state of the output register from
  325. * the saved copy in the UART data structure.  The actual opr contents
  326. * are not directly readable.
  327. *
  328. * RETURNS: Returns the current output register state.
  329. */
  330. UCHAR m5204Opr
  331.     (
  332.     M5204_CHAN * pChan
  333.     )
  334.     {
  335.     return pChan->oprCopy;
  336.     }
  337. /******************************************************************************
  338. *
  339. * m5204DummyCallback - dummy callback routine.
  340. *
  341. * RETURNS:
  342. * Always returns ERROR
  343. */
  344. LOCAL STATUS m5204DummyCallback (void)
  345.     {
  346.     return (ERROR);
  347.     }
  348. /******************************************************************************
  349. *
  350. * m5204TxStartup - start the interrupt transmitter.
  351. *
  352. * This routine enables the transmitters for the specified UART channel so that
  353. * the UART channel will interrupt the CPU when TxRDY bit in the status
  354. * register is set.
  355. *
  356. * Just enable the transmitter, don't output.  The driver may have just
  357. * switched from POLL mode and may still be outputting a character.
  358. *
  359. * RETURNS:
  360. * Returns OK on success, or EIO on hardware error.
  361. */
  362. LOCAL int m5204TxStartup
  363.     (
  364.     M5204_CHAN * pChan
  365.     )
  366.     {
  367.     M5204_WRITE (pChan->cr, M5204_UART_CR_TX_ENABLE);
  368.     return (OK);
  369.     }
  370. /******************************************************************************
  371. *
  372. * m5204CallbackInstall - install ISR callbacks to get/put chars.
  373. *
  374. * This driver allows interrupt callbacks, for transmitting characters
  375. * and receiving characters. In general, drivers may support other types
  376. * of callbacks too.
  377. *
  378. * RETURNS:
  379. * Returns OK on success, or ENOSYS for an unsupported callback type.
  380. */
  381. LOCAL int m5204CallbackInstall
  382.     (
  383.     M5204_CHAN * pChan,
  384.     int callbackType,
  385.     STATUS (*callback)(),
  386.     void *      callbackArg
  387.     )
  388.     {
  389.     switch (callbackType)
  390.         {
  391. case SIO_CALLBACK_GET_TX_CHAR:
  392.     pChan->getTxChar = callback;
  393.     pChan->getTxArg = callbackArg;
  394.     return (OK);
  395. case SIO_CALLBACK_PUT_RCV_CHAR:
  396.     pChan->putRcvChar = callback;
  397.     pChan->putRcvArg = callbackArg;
  398.     return (OK);
  399. default:
  400.     return (ENOSYS);
  401. }
  402.     }
  403. /******************************************************************************
  404. *
  405. * m5204PollOutput - output a character in polled mode.
  406. *
  407. * This routine polls the status register to see if the TxRDY bit has been set.
  408. * This signals that the transmit holding register is empty and that the
  409. * UART is ready for transmission.
  410. *
  411. * RETURNS:
  412. * Returns OK if a character sent, EIO on device error, EAGAIN
  413. * if the output buffer is full.
  414. */
  415. LOCAL int m5204PollOutput
  416.     (
  417.     M5204_CHAN *pChan,
  418.     char outChar
  419.     )
  420.     {
  421.     char statusReg;
  422.     statusReg = M5204_READ (pChan->sr);
  423.     /* is the transitter ready to accept a character? */
  424.     if ((statusReg & M5204_UART_SR_TXRDY) == 0x00)
  425. return (EAGAIN);
  426.     /* write out the character */
  427.     M5204_WRITE (pChan->tb, outChar);
  428.     return (OK);
  429.     }
  430. /******************************************************************************
  431. *
  432. * m5204PollInput - poll the device for input.
  433. *
  434. * This routine polls the status register to see if the RxRDY bit is set.
  435. * This gets set when the UART receives a character and signals the
  436. * pressence of a character in the receive buffer.
  437. *
  438. * RETURNS:
  439. * Returns OK if a character arrived, EIO on device error, EAGAIN
  440. * if the input buffer if empty.
  441. */
  442. LOCAL int m5204PollInput
  443.     (
  444.     M5204_CHAN *pChan,
  445.     char * thisChar
  446.     )
  447.     {
  448.     char statusReg;
  449.     statusReg = M5204_READ (pChan->sr);
  450.     if ((statusReg & M5204_UART_SR_RXRDY) == 0x00)
  451. return (EAGAIN);
  452.     *thisChar = M5204_READ (pChan->rb);
  453.     return (OK);
  454.     }
  455. /******************************************************************************
  456. *
  457. * m5204ModeSet - change channel mode setting
  458. *
  459. * This driver supports both polled and interrupt modes and is capable of
  460. * switching between modes dynamically. If interrupt mode is desired this
  461. * routine enables the channels receiver, transmitter interrupt and the
  462. * received break condition interrupt. If polled mode is desired the xmitrs for
  463. * the specified channel is enabled.
  464. *
  465. * RETURNS:
  466. * Returns a status of OK if the mode was set else ERROR.
  467. */
  468. LOCAL STATUS m5204ModeSet
  469.     (
  470.     M5204_CHAN * pChan,
  471.     UINT newMode
  472.     )
  473.     {
  474.     int oldlevel;
  475.     if ((newMode != SIO_MODE_POLL) && (newMode != SIO_MODE_INT))
  476. return (ERROR);
  477.     oldlevel = intLock ();
  478.     if (newMode == SIO_MODE_INT && pChan->intEnable)
  479.         {
  480. /* Enable the interrupts for receiver/transmitter conditions */
  481. m5204ImrSetClr (pChan, M5204_UART_IMR_TXRDY | M5204_UART_IMR_RXRDY, 0);
  482.         }
  483.     else
  484.         {
  485. /* Disable interrupts and enable the transmitter for the channel */
  486. m5204ImrSetClr (pChan, 0, M5204_UART_IMR_TXRDY | M5204_UART_IMR_RXRDY);
  487. M5204_WRITE (pChan->cr, M5204_UART_CR_TX_ENABLE);
  488.         }
  489.     intUnlock (oldlevel);
  490.     pChan->mode = newMode;
  491.     return (OK);
  492.     }
  493. /******************************************************************************
  494. *
  495. * m5204BaudSet - change baud rate for channel
  496. *
  497. * This routine sets the baud rate for the UART. The interrupts are disabled
  498. * during chip access.
  499. *
  500. * RETURNS:
  501. * Returns a status of OK if the baud rate was set else ERROR.
  502. */
  503. LOCAL STATUS  m5204BaudSet
  504.     (
  505.     M5204_CHAN * pChan,
  506.     UINT baud
  507.     )
  508.     {
  509.     UINT val;
  510.     int oldlevel;
  511.     if (!baud)
  512. return (ERROR);
  513.     val = ((pChan->clkRate / baud) + 16) / 32;
  514.     if ((val < 2) || (val > 0xffff))
  515. return (ERROR);
  516.     oldlevel = intLock ();
  517.     M5204_WRITE (pChan->bg1, val >> 8);
  518.     M5204_WRITE (pChan->bg2, val);
  519.     intUnlock (oldlevel);
  520.     return (OK);
  521.     }
  522. /******************************************************************************
  523. *
  524. * m5204OptsSet - set the serial options
  525. *
  526. * Set the channel operating mode to that specified.  All sioLib options
  527. * are supported: CLOCAL, CREAD, CSIZE, PARENB, and PARODD.
  528. *
  529. * Note, this routine disables the transmitter.  The calling routine
  530. * may have to re-enable it.
  531. *
  532. * RETURNS:
  533. * Returns OK to indicate success, otherwise ERROR is returned
  534. */
  535. LOCAL STATUS m5204OptsSet
  536.     (
  537.     M5204_CHAN * pChan, /* ptr to channel */
  538.     UINT options /* new hardware options */
  539.     )
  540.     {
  541.     int mr1Value;
  542.     int mr2Value;
  543.     int lvl;
  544.     if (pChan == NULL || options & 0xffffff00)
  545. return (ERROR);
  546.     /* Reset the transmitters  & receivers  */
  547.     switch (options & CSIZE)
  548. {
  549. case CS5:
  550.     mr1Value = M5204_UART_MR1_BITS_CHAR_5;
  551.     break;
  552. case CS6:
  553.     mr1Value = M5204_UART_MR1_BITS_CHAR_6;
  554.     break;
  555. case CS7:
  556.     mr1Value = M5204_UART_MR1_BITS_CHAR_7;
  557.     break;
  558. default:
  559. case CS8:
  560.     mr1Value = M5204_UART_MR1_BITS_CHAR_8;
  561.     break;
  562. }
  563.     if (options & STOPB)
  564. mr2Value = M5204_UART_MR2_STOP_BITS_2;
  565.     else
  566. mr2Value = M5204_UART_MR2_STOP_BITS_1;
  567.     switch (options & (PARENB|PARODD))
  568. {
  569. case PARENB|PARODD:
  570.     mr1Value |= M5204_UART_MR1_ODD_PARITY;
  571.     break;
  572. case PARENB:
  573.     mr1Value |= M5204_UART_MR1_EVEN_PARITY;
  574.     break;
  575. case PARODD:
  576.     mr1Value |= M5204_UART_MR1_PAR_MODE_MULTI;
  577.     break;
  578. default:
  579. case 0:
  580.     mr1Value |= M5204_UART_MR1_NO_PARITY; break;
  581. }
  582.     if (options & CLOCAL)
  583. {
  584. /* clocal enables hardware flow control */
  585. mr1Value |= M5204_UART_MR1_RX_RTS;
  586. mr2Value |= M5204_UART_MR2_TX_CTS;
  587. }
  588.     lvl = intLock ();
  589.     /* now reset the channel mode registers */
  590.     M5204_WRITE (pChan->cr, M5204_UART_CR_RESET_MODE_PTR
  591.  | M5204_UART_CR_RX_DISABLE
  592.  | M5204_UART_CR_TX_DISABLE);
  593.     M5204_WRITE (pChan->cr, M5204_UART_CR_RESET_TX);
  594.     M5204_WRITE (pChan->cr, M5204_UART_CR_RESET_RX);
  595.     M5204_WRITE (pChan->mr, mr1Value);  /* mode register 1  */
  596.     M5204_WRITE (pChan->mr, mr2Value);  /* mode register 2  */
  597.     if (options & CREAD)
  598. M5204_WRITE (pChan->cr, M5204_UART_CR_RX_ENABLE);
  599.     intUnlock (lvl);
  600.     pChan->options = options;
  601.     return (OK);
  602.     }
  603. /******************************************************************************
  604. *
  605. * m5204Ioctl - special device control
  606. *
  607. * RETURNS:
  608. * Returns OK on success, EIO on device error, ENOSYS on unsupported
  609. * request.
  610. */
  611. LOCAL int m5204Ioctl
  612.     (
  613.     M5204_CHAN * pChan, /* device to control */
  614.     int request, /* request code */
  615.     void * someArg /* some argument */
  616.     )
  617.     {
  618.     STATUS result;
  619.     int     arg = (int)someArg;
  620.     switch (request)
  621. {
  622. case SIO_BAUD_SET:
  623.     return (m5204BaudSet (pChan, arg) == OK ? OK : EIO);
  624. case SIO_BAUD_GET:
  625.     *(int *)arg = pChan->baudRate;
  626.     return (OK);
  627. case SIO_MODE_SET:
  628.     return (m5204ModeSet (pChan, arg) == OK ? OK : EIO);
  629. case SIO_MODE_GET:
  630.     *(int *)arg = pChan->mode;
  631.     return (OK);
  632. case SIO_AVAIL_MODES_GET:
  633.     *(int *)arg = SIO_MODE_INT | SIO_MODE_POLL;
  634.     return (OK);
  635. case SIO_HW_OPTS_SET:
  636.     /* change options, then set mode to restart chip correctly */
  637.     result = m5204OptsSet (pChan, arg);
  638.     m5204ModeSet (pChan, pChan->mode);
  639.     return result;
  640. case SIO_HW_OPTS_GET:
  641.     return pChan->options;
  642. default:
  643.     return (ENOSYS);
  644. }
  645.     }
  646. /******************************************************************************
  647. *
  648. * m5204IntWr - handle a transmitter interrupt
  649. *
  650. * This routine handles write interrupts from the UART. This isr is invoked
  651. * when the TxRDY bit in the interrupt status register has been set. If there
  652. * is no character to transmit the transmitter is disabled.
  653. *
  654. * RETURNS: N/A
  655. */
  656. LOCAL void m5204IntWr
  657.     (
  658.     M5204_CHAN * pChan
  659.     )
  660.     {
  661.     char            outChar;
  662.     if ((*pChan->getTxChar) (pChan->getTxArg, &outChar) != ERROR)
  663. {
  664. /* if char available, tx it */
  665. M5204_WRITE (pChan->tb, outChar);
  666. }
  667.     else
  668.         {
  669. M5204_WRITE (pChan->cr, M5204_UART_CR_TX_DISABLE);
  670.         }
  671.     }
  672. /*****************************************************************************
  673. *
  674. * m5204IntRd - handle a reciever interrupt
  675. *
  676. * This routine handles read interrupts from the UART.
  677. * The UART has been programmed to generate read interrupts when the RXRDY
  678. * status bit has been set in the interrupt status register. When a character
  679. * has been received it is removed from the receive buffer.
  680. *
  681. * RETURNS: N/A
  682. */
  683. LOCAL void m5204IntRd
  684.     (
  685.     M5204_CHAN * pChan
  686.     )
  687.     {
  688.     UCHAR inchar;
  689.     while (M5204_READ(pChan->sr) & M5204_UART_SR_RXRDY)
  690.         {
  691. inchar = M5204_READ (pChan->rb);
  692. (*pChan->putRcvChar) (pChan->putRcvArg, inchar);
  693. if (pChan->mode != SIO_MODE_INT)
  694.     break;
  695.         }
  696.     }
  697. /*******************************************************************************
  698. *
  699. * m5204Int - handle all interrupts in one vector
  700. *
  701. * All interrupts share a single interrupt vector.
  702. * We identify each interrupting source and service it.
  703. * We must service all interrupt sources for those systems with edge-
  704. * sensitive interrupt controllers.
  705. *
  706. * RETURNS: N/A
  707. */
  708. void m5204Int
  709.     (
  710.     M5204_CHAN * pChan
  711.     )
  712.     {
  713.     UCHAR        intStatus;
  714.     /* loop until all sources have been handled */
  715.     while (intStatus = (M5204_READ(pChan->isr) & pChan->imrCopy))
  716. {
  717. if (intStatus & M5204_UART_ISR_TXRDY)
  718.     m5204IntWr (pChan);
  719. if (intStatus & M5204_UART_ISR_RXRDY)
  720.     m5204IntRd (pChan);
  721. if (pChan->mode != SIO_MODE_INT)
  722.     break;
  723. }
  724.     }