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

VxWorks

开发平台:

C/C++

  1. /* m68302Serial.c - Motorola MC68302 tty driver*/
  2. /* Copyright 1984-1997 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01m,06aug97,dat  fixed race condition SPR 5578
  8. 01l,01dec92,jdi  NOMANUAL for tyCoInt() - SPR 1808.
  9. 01k,28oct92,caf  tweaked tyCoDevCreate() documentation and parm checking.
  10. 01j,22oct92,jcf  increased transmit buffer size.
  11. 01i,10aug92,caf  ansified.
  12. 01h,28jul92,caf  fixed ansi warnings.
  13. 01g,18jul92,smb  Changed errno.h to errnoLib.h.
  14. 01f,26may92,rrr  the tree shuffle
  15. 01e,24jan92,jdi  documentation cleanup.
  16. 01d,08jan92,caf  reduced size of transmit buffers (SPR 1243).
  17.  fixed baud rate in tyCoHrdInit() (SPR 1262).
  18. 01c,04oct91,rrr  passed through the ansification filter
  19.   -changed VOID to void
  20.   -changed copyright notice
  21. 01b,26sep91,jdi  documentation cleanup.
  22. 01a,19sep91,jcf  written.
  23. */
  24. /*
  25. DESCRIPTION
  26. This is the driver for the internal Communications Processor (CP)
  27. of the Motorola MC68302.
  28. USER-CALLABLE ROUTINES
  29. Most of the routines in this driver are accessible only through the I/O
  30. system.  Two routines, however, must be called directly:  tyCoDrv() to
  31. initialize the driver, and tyCoDevCreate() to create devices.
  32. Before the driver can be used, it must be initialized by calling the
  33. routine tyCoDrv().  This routine should be called exactly once, before any
  34. reads, writes, or calls to tyCoDevCreate().  Normally, it is called from
  35. usrRoot() in usrConfig.c.
  36. Before a terminal can be used, it must be created using tyCoDevCreate().
  37. Each port to be used should have exactly one device associated with it by
  38. calling this routine.
  39. IOCTL FUNCTIONS
  40. This driver responds to the same ioctl() codes as a normal tty driver; for
  41. more information, see the manual entry for tyLib.  The available baud
  42. rates are 300, 600, 1200, 2400, 4800, 9600 and 19200.
  43. SEE ALSO
  44. tyLib
  45. */
  46. /* includes */
  47. #include "vxWorks.h"
  48. #include "iosLib.h"
  49. #include "memLib.h"
  50. #include "tyLib.h"
  51. #include "iv.h"
  52. #include "intLib.h"
  53. #include "errnoLib.h"
  54. #include "config.h"
  55. /* defines */
  56. #define DEFAULT_BAUD 9600
  57. /* globals */
  58. IMPORT TY_CO_DEV tyCoDv []; /* device descriptors */
  59. /* locals */
  60. LOCAL int tyCoDrvNum; /* driver number assigned to this driver */
  61. typedef struct /* BAUD */
  62.     {
  63.     int    clockRate; /* system clock rate */
  64.     int    baudRate; /* a baud rate */
  65.     UINT16 timeConstant; /* time constant for scc scon register */
  66.     } BAUD;
  67. LOCAL BAUD baudTable [] = /* three CPU clock rates are supported */
  68.     {
  69.     /* 20.0 MHz CPU clock */
  70.     {20000000, 300, 0x823}, {20000000, 600, 0x40f},
  71.     {20000000, 1200, 0x822}, {20000000, 2400, 0x410},
  72.     {20000000, 4800, 0x206}, {20000000, 9600, 0x102},
  73.     {20000000, 19200, 0x080},
  74.     /* 16.7 MHz CPU clock */
  75.     {16666666, 300, 0x6c7}, {16666666, 600, 0xd8e},
  76.     {16666666, 1200, 0x6c6}, {16666666, 2400, 0x362},
  77.     {16666666, 4800, 0x1b0}, {16666666, 9600, 0xd8},
  78.     {16666666, 19200, 0x6a},
  79.     /* 16 MHz CPU clock */
  80.     {16000000, 300, 0x683}, {16000000, 600, 0xd04},
  81.     {16000000, 1200, 0x682}, {16000000, 2400, 0x340},
  82.     {16000000, 4800, 0x19e}, {16000000, 9600, 0xce},
  83.     {16000000, 19200, 0x66}
  84.     };
  85. /* forward declarations */
  86. LOCAL void tyCoStartup ();
  87. LOCAL int tyCoOpen ();
  88. LOCAL STATUS tyCoIoctl ();
  89. void tyCoInt ();
  90. LOCAL void tyCoHrdInit ();
  91. /*******************************************************************************
  92. *
  93. * tyCoDrv - initialize the tty driver
  94. *
  95. * This routine initializes the serial driver, sets up interrupt vectors,
  96. * and performs hardware initialization of the serial ports.
  97. *
  98. * This routine should be called exactly once, before any reads, writes, or
  99. * calls to tyCoDevCreate().  Normally, it is called from usrRoot() in
  100. * usrConfig.c.
  101. *
  102. * RETURNS: OK, or ERROR if the driver cannot be installed.
  103. *
  104. * SEE ALSO: tyCoDevCreate()
  105. */
  106. STATUS tyCoDrv (void)
  107.     {
  108.     /* check if driver already installed */
  109.     if (tyCoDrvNum > 0)
  110. return (OK);
  111.     tyCoHrdInit ();
  112.     tyCoDrvNum = iosDrvInstall (tyCoOpen, (FUNCPTR) NULL, tyCoOpen,
  113. (FUNCPTR) NULL, tyRead, tyWrite, tyCoIoctl);
  114.     return (tyCoDrvNum == ERROR ? ERROR : OK);
  115.     }
  116. /*******************************************************************************
  117. *
  118. * tyCoDevCreate - create a device for an on-board serial port
  119. *
  120. * This routine creates a device on a specified serial port.  Each port
  121. * to be used should have exactly one device associated with it by calling
  122. * this routine.
  123. *
  124. * For instance, to create the device "/tyCo/0", with buffer sizes of 512 bytes,
  125. * the proper call would be:
  126. * .CS
  127. *    tyCoDevCreate ("/tyCo/0", 0, 512, 512);
  128. * .CE
  129. *
  130. * RETURNS:
  131. * OK, or ERROR if the driver is not installed, the channel is invalid, or
  132. * the device already exists.
  133. *
  134. * SEE ALSO: tyCoDrv()
  135. */
  136. STATUS tyCoDevCreate
  137.     (
  138.     char *      name,           /* name to use for this device      */
  139.     FAST int    channel,        /* physical channel for this device */
  140.     int         rdBufSize,      /* read buffer size, in bytes       */
  141.     int         wrtBufSize      /* write buffer size, in bytes      */
  142.     )
  143.     {
  144.     if (tyCoDrvNum <= 0)
  145. {
  146. errnoSet (S_ioLib_NO_DRIVER);
  147. return (ERROR);
  148. }
  149.     /* if this doesn't represent a valid channel, don't do it */
  150.     if (channel < 0 || channel >= tyCoDv [0].numChannels)
  151.         return (ERROR);
  152.     /* if this device already exists, don't create it */
  153.     if (tyCoDv[channel].created )
  154. return (ERROR);
  155.     if (tyDevInit (&tyCoDv[channel].tyDev, rdBufSize, wrtBufSize,
  156.    (FUNCPTR) tyCoStartup)!= OK)
  157. return (ERROR);
  158.     /* enable the receiver and transmitter of the channel's scc */
  159.     tyCoDv[channel].pSccReg->scm |= UART_SCM_ENR | UART_SCM_ENT;
  160.     /* mark the device as created, and add the device to the I/O system */
  161.     tyCoDv[channel].created = TRUE;
  162.     return (iosDevAdd (&tyCoDv[channel].tyDev.devHdr, name, tyCoDrvNum));
  163.     }
  164. /*******************************************************************************
  165. *
  166. * tyCoHrdInit - initialize the USART
  167. */
  168. LOCAL void tyCoHrdInit (void)
  169.     {
  170.     int channel;
  171.     int frame;
  172.     int iy;
  173.     TY_CO_DEV *pDv;
  174.     int oldlevel = intLock (); /* LOCK INTERRUPTS */
  175.     *IMP_CR = (CR_RST | CR_FLG); /* RESET the CP */
  176.     while (*IMP_CR != 0)  /* Wait for reset to finish */
  177. ;
  178.     *IMP_SIMASK = 0xffff;
  179.     *IMP_SIMODE = 0x0000; /* NMSI for all channels */
  180.     for (channel = 0; channel < NUM_TTY; channel ++)
  181. {
  182. pDv = &tyCoDv[channel]; /* pDv points to device */
  183. for (iy = 0; iy < NELEMENTS (baudTable); iy++)
  184.     {
  185.     if ((baudTable [iy].clockRate == tyCoDv [0].clockRate) &&
  186. (baudTable [iy].baudRate == DEFAULT_BAUD))
  187. { /* set default baud rate */
  188. pDv->pSccReg->scon = baudTable [iy].timeConstant;
  189. break;
  190. }
  191.     }
  192. pDv->pSccReg->scm = UART_SCM_ASYNC | UART_SCM_MANUAL |
  193.   UART_SCM_8BIT | UART_SCM_RTSM;
  194. pDv->pSccReg->dsr = 0x7e7e; /* no fractional stop bits */
  195. pDv->pScc->param.rfcr = 0x50; /* sup. data access */
  196. pDv->pScc->param.tfcr = 0x50; /* sup. data access */
  197. pDv->pScc->param.mrblr = 0x1; /* one character rx buffers */
  198.   /* next receive buffer */
  199. pDv->rxBdNext = 0;
  200. for (frame = 0; frame < 8; frame ++)
  201.     {
  202.     pDv->pScc->rxBd[frame].statusMode = UART_RX_BD_EMPTY |
  203.   UART_RX_BD_INT;
  204.     pDv->pScc->rxBd[frame].dataLength = 1;
  205.     pDv->pScc->rxBd[frame].dataPointer = (char *)((channel << 3) +
  206.            frame + 0x180 +
  207.    (int)IMP_BASE_ADRS);
  208.     }
  209. pDv->pScc->rxBd[7].statusMode  |= UART_RX_BD_WRAP;
  210. pDv->pScc->txBd[0].statusMode = UART_TX_BD_INT | UART_TX_BD_WRAP;
  211. pDv->pScc->txBd[0].dataLength = 0x80;
  212. pDv->pScc->txBd[0].dataPointer = (char *)(channel * 0x80 +
  213.    (int)IMP_BASE_ADRS);
  214. ((PROT_UART *)pDv->pScc->prot)->maxIdl = 0x0;
  215. ((PROT_UART *)pDv->pScc->prot)->idlc = 0x0;
  216. ((PROT_UART *)pDv->pScc->prot)->brkcr = 0x0;
  217. ((PROT_UART *)pDv->pScc->prot)->parec = 0x0;
  218. ((PROT_UART *)pDv->pScc->prot)->frmec = 0x0;
  219. ((PROT_UART *)pDv->pScc->prot)->nosec = 0x0;
  220. ((PROT_UART *)pDv->pScc->prot)->brkec = 0x0;
  221. ((PROT_UART *)pDv->pScc->prot)->uaddr1 = 0x0;
  222. ((PROT_UART *)pDv->pScc->prot)->uaddr2 = 0x0;
  223. ((PROT_UART *)pDv->pScc->prot)->cntChar1 = 0x8000;
  224. pDv->pSccReg->scce = 0xff; /* clr events */
  225. pDv->pSccReg->sccm = UART_SCCE_RX | UART_SCCE_TX; /* unmask int */
  226. }
  227.     *IMP_IMR |= INT_SCC1 | INT_SCC2 | INT_SCC3; /* unmask int */
  228.     intUnlock (oldlevel); /* UNLOCK INTERRUPTS */
  229.     }
  230. /*******************************************************************************
  231. *
  232. * tyCoOpen - open file to USART
  233. */
  234. LOCAL int tyCoOpen
  235.     (
  236.     TY_CO_DEV *pTyCoDv,
  237.     char *name,
  238.     int mode
  239.     )
  240.     {
  241.     return ((int) pTyCoDv);
  242.     }
  243. /*******************************************************************************
  244. *
  245. * tyCoIoctl - special device control
  246. *
  247. * This routine handles FIOBAUDRATE requests and passes all others to tyIoctl.
  248. *
  249. * RETURNS: OK or ERROR if invalid baud rate, or whatever tyIoctl returns.
  250. */
  251. LOCAL STATUS tyCoIoctl
  252.     (
  253.     TY_CO_DEV *pTyCoDv, /* device to control */
  254.     int request, /* request code */
  255.     int arg /* some argument */
  256.     )
  257.     {
  258.     int ix;
  259.     UINT16 scon;
  260.     STATUS status;
  261.     switch (request)
  262. {
  263. case FIOBAUDRATE:
  264.     status = ERROR;
  265.     for (ix = 0; ix < NELEMENTS (baudTable); ix++)
  266. {
  267. if ((baudTable [ix].clockRate == tyCoDv [0].clockRate) &&
  268.     (baudTable [ix].baudRate == arg))
  269.     {
  270.     scon  = pTyCoDv->pSccReg->scon & 0xf000;
  271.     scon |= baudTable [ix].timeConstant;
  272.     pTyCoDv->pSccReg->scon = scon;
  273.     status = OK;
  274.     break;
  275.     }
  276. }
  277.     break;
  278. default:
  279.     status = tyIoctl (&pTyCoDv->tyDev, request, arg);
  280.     break;
  281. }
  282.     return (status);
  283.     }
  284. /*******************************************************************************
  285. *
  286. * tyCoInt - handle a SCC interrupt
  287. *
  288. * This routine gets called to handle SCC interrupts.
  289. *
  290. * NOMANUAL
  291. */
  292. void tyCoInt
  293.     (
  294.     TY_CO_DEV *pDv
  295.     )
  296.     {
  297.     char outChar;
  298.     FAST UINT16   dataLen = 0;
  299.     FAST UINT8    event = pDv->pSccReg->scce;
  300.     /* acknowledge interrupt */
  301.     pDv->pSccReg->scce = event; /* clear events */
  302.     *IMP_ISR = pDv->intAck; /* ack. interrupt */
  303.     if (!pDv->created)
  304. return;
  305.     if ((event & UART_SCCE_TX) && (tyITx (&pDv->tyDev, &outChar) == OK))
  306. {
  307. do
  308.     {
  309.     pDv->pScc->txBd[0].dataPointer[dataLen++] = outChar;
  310.     }
  311. while ((dataLen < 0x80) && (tyITx (&pDv->tyDev, &outChar) == OK));
  312. pDv->pScc->txBd[0].dataLength  = dataLen;
  313. pDv->pScc->txBd[0].statusMode |= UART_TX_BD_READY;
  314. }
  315.     if (event & UART_SCCE_RX)
  316. while (!(pDv->pScc->rxBd[pDv->rxBdNext].statusMode & UART_RX_BD_EMPTY))
  317.     {
  318.     tyIRd (&pDv->tyDev, pDv->pScc->rxBd[pDv->rxBdNext].dataPointer[0]);
  319.     pDv->pScc->rxBd[pDv->rxBdNext].statusMode |= UART_RX_BD_EMPTY;
  320.     pDv->rxBdNext = (pDv->rxBdNext + 1) & 0x7;
  321.     }
  322.     /* all other events ignored */
  323.     }
  324. /*******************************************************************************
  325. *
  326. * tyCoStartup - transmitter startup routine
  327. */
  328. LOCAL void tyCoStartup
  329.     (
  330.     TY_CO_DEV *pDv /* ty device to start up */
  331.     )
  332.     {
  333.     char outChar;
  334.     FAST int dataLen = 0;
  335.     if ((!(pDv->pScc->txBd[0].statusMode & UART_TX_BD_READY)) &&
  336.         (tyITx (&pDv->tyDev, &outChar) == OK))
  337. {
  338. do
  339.     {
  340.     pDv->pScc->txBd[0].dataPointer[dataLen++] = outChar;
  341.     }
  342. while ((dataLen < 0x80) && (tyITx (&pDv->tyDev, &outChar) == OK));
  343. pDv->pScc->txBd[0].dataLength  = dataLen;
  344. pDv->pScc->txBd[0].statusMode |= UART_TX_BD_READY;
  345. }
  346.     }