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

VxWorks

开发平台:

C/C++

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