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

VxWorks

开发平台:

C/C++

  1. /* m68901Serial.c - MC68901 MFP tty driver */
  2. /* Copyright 1984-1993 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01c,30jan93,dzb  separated baud rate clocks from particular timer(s).
  8.  made second baud rate clock conditional on initialization.
  9.  removed BAUD structure.
  10. 01b,11jan93,caf  calculated baud rate from input clock, no more baudTable[].
  11. 01a,18dec92,caf  derived from version 01s of mv133/tyCoDrv.c, ansified.
  12. */
  13. /*
  14. DESCRIPTION
  15. This is the serial driver for the Motorola MC68901 Multi-Function Peripheral
  16. (MFP) chip.
  17. USER-CALLABLE ROUTINES
  18. Most of the routines in this driver are accessible only through the I/O
  19. system.  Two routines, however, must be called directly:  tyCoDrv() to
  20. initialize the driver, and tyCoDevCreate() to create devices.
  21. Before the driver can be used, it must be initialized by calling the
  22. routine tyCoDrv().  This routine should be called exactly once, before any
  23. reads, writes, or calls to tyCoDevCreate().  Normally, it is called by
  24. usrRoot() in usrConfig.c.
  25. Before a terminal can be used, it must be created, using tyCoDevCreate().
  26. Each port to be used should have exactly one device associated with it by
  27. calling this routine.
  28. IOCTL FUNCTIONS
  29. This driver responds to the same ioctl() codes as a normal tty driver;
  30. for more information, see the manual entry for tyLib.
  31. SEE ALSO
  32. tyLib
  33. */
  34. #include "vxWorks.h"
  35. #include "errnoLib.h"
  36. #include "iosLib.h"
  37. #include "memLib.h"
  38. #include "tyLib.h"
  39. #include "intLib.h"
  40. #include "iv.h"
  41. #include "drv/multi/m68901.h"
  42. IMPORT TY_CO_DEV tyCoDv; /* device descriptor */
  43. LOCAL int tyCoDrvNum; /* driver number assigned to this driver */
  44. /* forward declarations */
  45. LOCAL void tyCoStartup ();
  46. LOCAL int tyCoOpen ();
  47. LOCAL STATUS tyCoIoctl ();
  48. LOCAL void tyCoHrdInit ();
  49. /*******************************************************************************
  50. *
  51. * tyCoDrv - initialize the tty driver
  52. *
  53. * This routine initializes the serial driver, sets up interrupt vectors,
  54. * and performs hardware initialization of the serial ports.
  55. * This routine should be called exactly once, before any reads, writes, or
  56. * calls to tyCoDevCreate().  Normally, it is called by usrRoot() in
  57. * usrConfig.c.
  58. *
  59. * RETURNS: OK, or ERROR if the driver cannot be installed.
  60. *
  61. * SEE ALSO: tyCoDevCreate()
  62. */
  63. STATUS tyCoDrv (void)
  64.     {
  65.     /* check if driver already installed */
  66.     if (tyCoDrvNum > 0)
  67. return (OK);
  68.     tyCoHrdInit ();
  69.     tyCoDrvNum = iosDrvInstall (tyCoOpen, (FUNCPTR) NULL, tyCoOpen,
  70. (FUNCPTR) NULL, tyRead, tyWrite, tyCoIoctl);
  71.     return (tyCoDrvNum == ERROR ? ERROR : OK);
  72.     }
  73. /*******************************************************************************
  74. *
  75. * tyCoDevCreate - create a device for an on-board serial port
  76. *
  77. * This routine creates a device for a specified serial port.  Each port
  78. * to be used should have exactly one device associated with it by calling
  79. * this routine.
  80. *
  81. * For instance, to create the device "/tyCo/0", with buffer sizes of 512 bytes,
  82. * the proper call would be:
  83. * .CS
  84. *     tyCoDevCreate ("/tyCo/0", 0, 512, 512);
  85. * .CE
  86. *
  87. * RETURNS: OK, or ERROR if the driver is not installed, the channel is invalid,
  88. * or the device already exists.
  89. *
  90. * SEE ALSO: tyCoDrv()
  91. */
  92. STATUS tyCoDevCreate
  93.     (
  94.     char *      name,           /* name to use for this device      */
  95.     FAST int    channel,        /* physical channel for this device */
  96.     int         rdBufSize,      /* read buffer size, in bytes       */
  97.     int         wrtBufSize      /* write buffer size, in bytes      */
  98.     )
  99.     {
  100.     if (tyCoDrvNum <= 0)
  101. {
  102. errnoSet (S_ioLib_NO_DRIVER);
  103. return (ERROR);
  104. }
  105.     /* if this device already exists, don't create it */
  106.     if (tyCoDv.created || channel != 0)
  107. return (ERROR);
  108.     if (tyDevInit (&tyCoDv.tyDev, rdBufSize, wrtBufSize,
  109.    (FUNCPTR) tyCoStartup) != OK)
  110. {
  111. return (ERROR);
  112. }
  113.     /* enable the receiver and receiver error */
  114.     *tyCoDv.imra |= MFP_A_RX_FULL; /* unmask recv ints */
  115.     *tyCoDv.imra |= MFP_A_RX_ERR; /* unmask recv error ints */
  116.     /* mark the device as created, and add the device to the I/O system */
  117.     tyCoDv.created = TRUE;
  118.     return (iosDevAdd (&tyCoDv.tyDev.devHdr, name, tyCoDrvNum));
  119.     }
  120. /*******************************************************************************
  121. *
  122. * tyCoHrdInit - initialize the USART
  123. */
  124. LOCAL void tyCoHrdInit (void)
  125.     {
  126.     int lock = intLock (); /* LOCK INTERRUPTS */
  127.     /* 8 data bits, 1 stop bit, no parity */
  128.     *tyCoDv.ucr = MFP_UCR_16X | MFP_UCR_8BIT |
  129.                               MFP_UCR_1STOP | MFP_UCR_NO_PARITY;
  130.     /* set baud rate values w/ prescale=4 */
  131.     *tyCoDv.baud1 = tyCoDv.baudFreq / (128 * 9600);
  132.     if (tyCoDv.baud2 != NULL)
  133.         *tyCoDv.baud2 = tyCoDv.baudFreq / (128 * 9600);
  134.     /* enable the receivers and transmitters on both channels */
  135.     *tyCoDv.rsr  = MFP_RSR_RX_ENABLE;      /* enable rcvr status */
  136.     *tyCoDv.tsr  = MFP_TSR_TX_ENABLE;      /* enable xmit status */
  137.     *tyCoDv.iera |= MFP_A_RX_FULL;  /* enable recv int. */
  138.     *tyCoDv.iera |= MFP_A_RX_ERR;   /* enable recv error int. */
  139.     *tyCoDv.iera |= MFP_A_TX_EMPTY; /* enable transmit int. */
  140.     /* all interrupts are still masked out via the interrupt mask registers:
  141.      * turn the receiver on and off by twiddling the interrupt mask reg (IMRA),
  142.      * the receiver interrupt will be enabled in tyCoDevCreate,
  143.      * the transmitter interrupt will be enabled in tyCoStartup
  144.      */
  145.     intUnlock (lock); /* UNLOCK INTERRUPTS */
  146.     }
  147. /*******************************************************************************
  148. *
  149. * tyCoOpen - open file to USART
  150. */
  151. LOCAL int tyCoOpen
  152.     (
  153.     TY_CO_DEV *pTyCoDv,
  154.     char *name,
  155.     int mode
  156.     )
  157.     {
  158.     return ((int) pTyCoDv);
  159.     }
  160. /*******************************************************************************
  161. *
  162. * tyCoIoctl - special device control
  163. *
  164. * This routine handles FIOBAUDRATE requests and passes all others to tyIoctl().
  165. *
  166. * RETURNS: OK, or ERROR if the baud rate is invalid, or whatever tyIoctl()
  167. * returns.
  168. */
  169. LOCAL STATUS tyCoIoctl
  170.     (
  171.     TY_CO_DEV *pTyCoDv, /* device to control */
  172.     int request, /* request code */
  173.     int arg /* some argument */
  174.     )
  175.     {
  176.     STATUS status;
  177.     switch (request)
  178. {
  179.         case FIOBAUDRATE:
  180.             status = ERROR;
  181.             if ((arg >= tyCoDv.baudMin) && (arg <= tyCoDv.baudMax))
  182.                 {
  183. /* set baud rate values w/ prescale=4 */
  184. *tyCoDv.baud1 = tyCoDv.baudFreq / (128 * arg);
  185. if (tyCoDv.baud2 != NULL)
  186.     *tyCoDv.baud2 = tyCoDv.baudFreq / (128 * arg);
  187.                 status = OK;
  188.                 }
  189.             break;
  190. default:
  191.     status = tyIoctl (&pTyCoDv->tyDev, request, arg);
  192.     break;
  193. }
  194.     return (status);
  195.     }
  196. /*******************************************************************************
  197. *
  198. * tyCoTxInt - handle a transmitter interrupt
  199. *
  200. * This routine gets called to handle transmitter interrupts.
  201. * If there is another character to be transmitted, it sends it.  If
  202. * not, or if a device has never been created for this channel, just
  203. * disable the interrupt.
  204. *
  205. * NOMANUAL
  206. */
  207. void tyCoTxInt (void)
  208.     {
  209.     char outChar;
  210.     if (tyCoDv.created && tyITx (&tyCoDv.tyDev, &outChar) == OK)
  211. *tyCoDv.udr = outChar;
  212.     else
  213. *tyCoDv.imra &= ~MFP_A_TX_EMPTY; /* turn off transmitter */
  214.     }
  215. /*******************************************************************************
  216. *
  217. * tyCoRxInt - handle a receiver interrupt
  218. *
  219. * NOMANUAL
  220. */
  221. void tyCoRxInt (void)
  222.     {
  223.     tyIRd (&tyCoDv.tyDev, *tyCoDv.udr);
  224.     }
  225. /*******************************************************************************
  226. *
  227. * tyCoStartup - transmitter startup routine
  228. *
  229. * Call interrupt level character output routine.
  230. */
  231. LOCAL void tyCoStartup
  232.     (
  233.     TY_CO_DEV *pTyCoDv /* ty device to start up */
  234.     )
  235.     {
  236.     char outchar;
  237.     /* enable the transmitter and it should interrupt to write the next char */
  238.     if (tyITx (&pTyCoDv->tyDev, &outchar) == OK)
  239. *pTyCoDv->udr = outchar;
  240.     *tyCoDv.imra |= MFP_A_TX_EMPTY; /* turn on transmitter */
  241.     }