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

VxWorks

开发平台:

C/C++

  1. /* m68562Serial.c - MC68562 DUSCC tty driver */
  2. /* Copyright 1984-1993 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01o,07jul93,vin  changed *pTyCoDv->omr = DUSCC_OMR_T....
  8.                  to      *pTyCoDv->omr |= DUSCC_OMR_T.... in 
  9.  tyCoResetChannel ();
  10. 01n,01dec92,jdi  NOMANUAL tyCoRxTxErrInt(), tyCoRxInt(), tyCoTxInt() - SPR 1808.
  11. 01m,27oct92,caf  don't set the baud rate if it is already correct (SPR 1721).
  12.  don't write to the general status register in tyCoStartup().
  13.  tweaked tyCoDevCreate() documentation.
  14. 01l,22oct92,caf  improved DUSCC initialization procedures (SPR 1689),
  15.  fixed tyCoRxTxErrInt().
  16. 01k,01sep92,caf  ansified.  fixed parameter check in tyCoDevCreate().
  17. 01j,18jul92,smb  Changed errno.h to errnoLib.h.
  18. 01i,01jul92,caf  made board-independent (from vers 01h of frc40/tyCoDrv.c).
  19. 01h,26may92,rrr  the tree shuffle
  20. 01g,01may92,caf  fixed gsr access in tyCoStartup() (SPR #1355).
  21.                  silenced ansi warnings.
  22. 01f,08jan92,jdi  documentation cleanup.
  23. 01e,04oct91,rrr  passed through the ansification filter
  24.                   -changed VOID to void
  25.                   -changed copyright notice
  26. 01d,18aug91,jdi  documentation cleanup.
  27. 01c,30jul91,jpb  fixed bug in tyCoTxInt (see frc33 01i,21jul91,caf)
  28. 01b,25jul91,jpb  fill transmit FIFO, and fixed documentation.
  29. 01a,07jul91,jpb  reformatted according to WRS conventions.
  30. */
  31. /*
  32. DESCRIPTION
  33. This is the driver for the MC68562 DUSCC serial chip.
  34. It uses the DUSCC in asynchronous mode only.
  35. USER-CALLABLE ROUTINES
  36. Most of the routines in this driver are accessible only through the I/O
  37. system.  Two routines, however, must be called directly:  tyCoDrv() to
  38. initialize the driver, and tyCoDevCreate() to create devices.
  39. TYCODRV
  40. Before the driver can be used, it must be initialized by calling tyCoDrv().
  41. This routine should be called exactly once, before any reads, writes, or
  42. calls to tyCoDevCreate().  Normally, it is called by usrRoot() in usrConfig.c.
  43. Before a terminal can be used, it must be created using tyCoDevCreate().
  44. Each port to be used should have exactly one device associated with it
  45. by calling this routine.
  46. IOCTL
  47. This driver responds to the same ioctl() codes as a normal tty driver.
  48. See the manual entry for tyLib for more information.
  49. SEE ALSO: tyLib
  50. */
  51. #include "vxWorks.h"
  52. #include "iv.h"
  53. #include "ioLib.h"
  54. #include "iosLib.h"
  55. #include "memLib.h"
  56. #include "tyLib.h"
  57. #include "intLib.h"
  58. #include "errnoLib.h"
  59. #include "drv/multi/m68562.h"
  60. #define BIT(val,bit)    ((val & bit) == bit)
  61. typedef struct        /* BAUD */
  62.     {
  63.     int rate;        /* a baud rate */
  64.     char xmtVal;       /* rate to write to the Transmitter Timing Register */
  65.     char rcvVal;       /* rate to write to the Reciever Timing Register */
  66.     }      BAUD;
  67. IMPORT TY_CO_DEV tyCoDv []; /* device descriptors */
  68. /* 
  69.  * baudTable is a table of the available baud rates, and the values to 
  70.  * write to the csr reg to get those rates 
  71.  */
  72. LOCAL BAUD baudTable [] =
  73.         {
  74.         {50,
  75. DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_50,
  76. DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_50 },
  77.         {75,
  78. DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_75,
  79. DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_75 },
  80.         {110,
  81. DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_110,
  82. DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_110},
  83.         {134,
  84. DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_134_5,
  85. DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_134_5},
  86.         {150,
  87. DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_150,
  88. DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_150},
  89.         {200,
  90. DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_200,
  91. DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_200},
  92.         {300,
  93. DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_300,
  94. DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_300},
  95.         {600,
  96. DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_600,
  97. DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_600},
  98.         {1050,
  99. DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_1050,
  100. DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_1050},
  101.         {1200,
  102. DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_1200,
  103. DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_1200},
  104.         {2000,
  105. DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_2000,
  106. DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_2000},
  107.         {2400,
  108. DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_2400,
  109. DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_2400},
  110.         {4800,
  111. DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_4800,
  112. DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_4800},
  113.         {9600,
  114. DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_9600,
  115. DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_9600},
  116.         {19200,
  117. DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_19200,
  118. DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_19200},
  119.         {38400,
  120. DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_38400,
  121. DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_38400} };
  122. LOCAL int tyCoDrvNum; /* driver number assigned to this driver */
  123. /* forward declarations */
  124. LOCAL void tyCoStartup ();
  125. LOCAL int tyCoOpen ();
  126. LOCAL STATUS tyCoIoctl ();
  127. void tyCoTxInt ();
  128. void tyCoRxInt ();
  129. void tyCoRxTxErrInt ();
  130. LOCAL void tyCoHrdInit ();
  131. LOCAL void tyCoResetChannel ();
  132. /*******************************************************************************
  133. *
  134. * tyCoDrv - tty driver initialization routine
  135. *
  136. * This routine initializes the driver, sets up interrupt vectors, and
  137. * performs hardware initialization of the serial ports.
  138. *
  139. * This routine should be called exactly once, before any reads, writes, or
  140. * calls to tyCoDevCreate().  Normally, it is called by usrRoot() in usrConfig.c.
  141. *
  142. * RETURNS: OK, or ERROR if the driver cannot be installed.
  143. */
  144. STATUS tyCoDrv (void)
  145.     {
  146.     /* check if driver already installed */
  147.     if (tyCoDrvNum > 0)
  148. return (OK);
  149.     tyCoHrdInit ();
  150.     tyCoDrvNum = iosDrvInstall (tyCoOpen, (FUNCPTR) NULL, tyCoOpen,
  151. (FUNCPTR) NULL, tyRead, tyWrite, tyCoIoctl);
  152.     return (tyCoDrvNum == ERROR ? ERROR : OK);
  153.     }
  154. /*******************************************************************************
  155. *
  156. * tyCoDevCreate - create a device for an on-board serial port
  157. *
  158. * This routine creates a device on a specified serial port.  Each port
  159. * to be used should have exactly one device associated with it by calling
  160. * this routine.
  161. *
  162. * For instance, to create the device "/tyCo/0", with a buffer size of 512 bytes,
  163. * the proper call would be:
  164. *
  165. * .CS
  166. *     tyCoDevCreate ("/tyCo/0", 0, 512, 512);
  167. * .CE
  168. *
  169. * RETURNS: OK, or ERROR if the driver is not installed, the channel is invalid,
  170. * or the device already exists.
  171. */
  172. STATUS tyCoDevCreate
  173.     (
  174.     char *      name,           /* name to use for this device      */
  175.     FAST int    channel,        /* physical channel for this device */
  176.     int         rdBufSize,      /* read buffer size, in bytes       */
  177.     int         wrtBufSize      /* write buffer size, in bytes      */
  178.     )
  179.     {
  180.     if (tyCoDrvNum <= 0)
  181.         {
  182. errnoSet (S_ioLib_NO_DRIVER);
  183. return (ERROR);
  184.         }
  185.     /* check for valid channel and if device already exists, don't create it */
  186.     if (channel < 0 || channel >= tyCoDv [0].numChannels)
  187. return (ERROR);
  188.     if (tyCoDv[channel].created)
  189. return (ERROR);
  190.     /*
  191.      * initialize the ty descriptor, and turn on the bit for this receiver in
  192.      * the interrupt mask
  193.      */
  194.     if (tyDevInit (&tyCoDv[channel].tyDev, rdBufSize, wrtBufSize,
  195.    (FUNCPTR) tyCoStartup) != OK)
  196.         {
  197. return (ERROR);
  198.         }
  199.     *tyCoDv[channel].ier = DUSCC_IER_RXRDY | DUSCC_IER_RSR_5_4;
  200.     /* mark the device as created, and add the device to the I/O system */
  201.     tyCoDv[channel].created = TRUE;
  202.     return (iosDevAdd (&tyCoDv[channel].tyDev.devHdr, name, tyCoDrvNum));
  203.     }
  204. /*******************************************************************************
  205. *
  206. * tyCoHrdInit - initialize the DUSCC
  207. */
  208. LOCAL void tyCoHrdInit (void)
  209.     {
  210.     int ix;
  211.     int lock = intLock ();      /* LOCK INTERRUPTS */
  212.     for (ix = 0; ix < tyCoDv [0].numChannels; ix ++)
  213.         tyCoResetChannel (tyCoDv + ix);
  214.     intUnlock (lock); /* UNLOCK INTERRUPTS */
  215.     }
  216. /*******************************************************************************
  217. *
  218. * tyCoResetChannel - reset a single channel
  219. */
  220. LOCAL void tyCoResetChannel
  221.     (
  222.     TY_CO_DEV *pTyCoDv
  223.     )
  224.     {
  225.     /* 8 data bits, 1 stop bit, no parity, set for 9600 baud */
  226.     /*
  227.      * DUSCC Initialization Procedures (from Dec 1987 Signetics app note)
  228.      *
  229.      * "Note that whenever a change is made in the channel mode registers,
  230.      *  the transmitter and receiver should first be disabled.  Also, before
  231.      *  any change is made in the transmit parameter register (TPR) or the
  232.      *  transmit timing register (TTR), the transmitter should be disabled.
  233.      *  After a change(s) has been completed, the trasmitter should be reset; 
  234.      *  then enabled.
  235.      *
  236.      * "If changes are made in either the receive parameter register (RPR)
  237.      *  or the receive timing register (RTR), the receiver should be disabled.
  238.      *  After a changes(s) has been completed, the the receiver should be
  239.      *  reset; then enabled."
  240.      */
  241.     /* disable transmitter and receiver */
  242.     *pTyCoDv->ccr = DUSCC_CCR_TX_DISABLE_TX;
  243.     *pTyCoDv->ccr = DUSCC_CCR_RX_DISABLE_RX;
  244.     /* configure transmitter and receiver */
  245.     *pTyCoDv->cmr1 = DUSCC_CMR1_ASYNC;
  246.     *pTyCoDv->cmr2 = DUSCC_CMR2_DTI_POLL_OR_INT;
  247.     *pTyCoDv->tpr  = DUSCC_TPR_ASYNC_1 | DUSCC_TPR_8BITS;
  248.     *pTyCoDv->ttr  = DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_9600;
  249.     *pTyCoDv->rpr  = DUSCC_RPR_8BITS;
  250.     *pTyCoDv->rtr  = DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_9600;
  251.     *pTyCoDv->omr |= DUSCC_OMR_TXRDY_FIFO_EMPTY |
  252.                     DUSCC_OMR_TX_RES_CHAR_LENGTH_TPR;
  253.     /* reset transmitter and receiver */
  254.     *pTyCoDv->ccr = DUSCC_CCR_TX_RESET_TX;
  255.     *pTyCoDv->ccr = DUSCC_CCR_RX_RESET_RX;
  256.     /* enable transmitter and receiver */
  257.     *pTyCoDv->ccr = DUSCC_CCR_TX_ENABLE_TX;
  258.     *pTyCoDv->ccr = DUSCC_CCR_RX_ENABLE_RX;
  259.     /*
  260.      * all interrupts are masked out: the receiver interrupt will be
  261.      * enabled in the tyCoDevCreate
  262.      */
  263.     }
  264. /*******************************************************************************
  265. *
  266. * tyCoOpen - open file to DUSCC
  267. *
  268. * RETURNS: device number.
  269. */
  270. LOCAL int tyCoOpen
  271.     (
  272.     TY_CO_DEV *pTyCoDv,
  273.     char *name,
  274.     int mode
  275.     )
  276.     {
  277.     return ((int) pTyCoDv);
  278.     }
  279. /*******************************************************************************
  280. *
  281. * tyCoIoctl - special device control
  282. *
  283. * This routine handles baud rate requests, and passes all others to tyIoctl.
  284. *
  285. * RETURNS: OK or ERROR if invalid baud rate or whatever tyIoctl returns.
  286. */
  287. LOCAL STATUS tyCoIoctl
  288.     (
  289.     TY_CO_DEV *pTyCoDv, /* device to control */
  290.     int request, /* request code      */
  291.     int arg /* some argument     */
  292.     )
  293.     {
  294.     int ix;
  295.     STATUS status;
  296.     switch (request)
  297.         {
  298. case FIOBAUDRATE:
  299.     status = ERROR;
  300.     for (ix = 0; ix < NELEMENTS (baudTable); ix ++)
  301. if (baudTable [ix].rate == arg)
  302.     {
  303.     status = OK; /* baud rate is valid */
  304.     /*
  305.      * Only set baud rate if the hardware needs it.
  306.      * Setting the baud rate to 9600 when the baud
  307.      * rate is already 9600, for example, would
  308.      * unnecessarily disable the serial channel and
  309.      * possibly drop characters.
  310.      */
  311.     if ((*pTyCoDv->ttr != baudTable [ix].xmtVal) ||
  312. (*pTyCoDv->rtr != baudTable [ix].rcvVal))
  313. {
  314. /* disable transmitter and receiver */
  315. *pTyCoDv->ccr = DUSCC_CCR_TX_DISABLE_TX;
  316. *pTyCoDv->ccr = DUSCC_CCR_RX_DISABLE_RX;
  317. /* configure transmitter and receiver */
  318. *pTyCoDv->ttr = baudTable [ix].xmtVal;
  319. *pTyCoDv->rtr = baudTable [ix].rcvVal;
  320. /* reset transmitter and receiver */
  321. *pTyCoDv->ccr = DUSCC_CCR_TX_RESET_TX;
  322. *pTyCoDv->ccr = DUSCC_CCR_RX_RESET_RX;
  323. /* enable transmitter and receiver */
  324. *pTyCoDv->ccr = DUSCC_CCR_TX_ENABLE_TX;
  325. *pTyCoDv->ccr = DUSCC_CCR_RX_ENABLE_RX;
  326. break;
  327. }
  328.     }
  329.     break;
  330. default:
  331.     status = tyIoctl (&pTyCoDv->tyDev, request, arg);
  332.     break;
  333.         }
  334.     return (status);
  335.     }
  336. /*******************************************************************************
  337. *
  338. * tyCoRxTxErrInt - handle a receiver/transmitter error status interrupt
  339. *
  340. * Only the receive overrun condition is handled.
  341. *
  342. * RETURNS: N/A
  343. *
  344. * NOMANUAL
  345. */
  346. void tyCoRxTxErrInt
  347.     (
  348.     FAST TY_CO_DEV *pTyCoDv
  349.     )
  350.     {
  351.     if (BIT (*pTyCoDv->rsr, DUSCC_RSR_ASYNC_OVERN_ERROR))
  352. *pTyCoDv->rsr = DUSCC_RSR_ASYNC_OVERN_ERROR; /* "1" clears bit */
  353.     }
  354. /*******************************************************************************
  355. *
  356. * tyCoRxInt - handle a receiver interrupt
  357. *
  358. * RETURNS: N/A
  359. *
  360. * NOMANUAL
  361. */
  362. void tyCoRxInt
  363.     (
  364.     FAST TY_CO_DEV *pTyCoDv
  365.     )
  366.     {
  367.     /* drain receive FIFO */
  368.     do
  369.         {
  370. (void) tyIRd (&pTyCoDv->tyDev, *pTyCoDv->rx_data);
  371.         }
  372.     while (BIT (*pTyCoDv->gsr, pTyCoDv->rx_rdy));
  373.     }
  374. /*******************************************************************************
  375. *
  376. * tyCoTxInt - handle a transmitter interrupt
  377. *
  378. * If there is another character to be transmitted, it sends it.  If
  379. * not, or if a device has never been created for this channel,
  380. * disable the interrupt.
  381. *
  382. * RETURNS: N/A
  383. *
  384. * NOMANUAL
  385. */
  386. void tyCoTxInt
  387.     (
  388.     FAST TY_CO_DEV *pTyCoDv
  389.     )
  390.     {
  391.     char outChar;
  392.     if (pTyCoDv->created)
  393.         {
  394.         do                                          /* fill transmit FIFO */
  395.             {
  396.             if (tyITx (&pTyCoDv->tyDev, &outChar) == OK)
  397.                 *pTyCoDv->tx_data = outChar;
  398.             else
  399.                 {
  400.                 *pTyCoDv->ier &= ~DUSCC_IER_TXRDY;  /* turn off transmitter */
  401.                 break;
  402.                 }
  403.             }
  404.         while (BIT (*pTyCoDv->gsr, pTyCoDv->tx_rdy));
  405.         }
  406.     else
  407.         {
  408. *pTyCoDv->ier &= ~DUSCC_IER_TXRDY; /* turn off the transmitter */
  409.         }
  410.     }
  411. /*******************************************************************************
  412. *
  413. * tyCoStartup - transmitter startup routine
  414. *
  415. * Call interrupt level character output routine for DUSCC.
  416. */
  417. LOCAL void tyCoStartup
  418.     (
  419.     FAST TY_CO_DEV *pTyCoDv /* ty device to start up */
  420.     )
  421.     {
  422.     char outChar;
  423.     if (pTyCoDv->created && tyITx (&pTyCoDv->tyDev, &outChar) == OK)
  424.         {
  425.         *pTyCoDv->tx_data  = outChar;
  426.         *pTyCoDv->ier     |= DUSCC_IER_TXRDY;
  427.         }
  428.     }