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

VxWorks

开发平台:

C/C++

  1. /* m68681Sio.c - M68681 serial communications driver */
  2. /* Copyright 1984-1996 Wind River Systems, Inc. */
  3. /*
  4. modification history
  5. --------------------
  6. 01d,18dec96,db   fixed bugs in m68681OptsSet() and m68681Ioctl().(SPR #7641).
  7.  changed M68681_DEFAULT_OPTIONS to disable hardware handshake.
  8. 01e,06nov96,dgp  doc: final formatting
  9. 01d,03jun96,dat  added m68681Opr, m68681Opcr, m68681OpcrSetClr, m68681OprSetClr
  10. 01c,21may96,dat  m68681Int loops until all sources serviced.
  11. 01b,29mar96,dat  more comments, added m68681OptsSet(), m68681AcrSetClr()
  12. 01a,14feb96,dds  written.
  13. */
  14. /*
  15. DESCRIPTION
  16. This is the driver for the M68681 DUART. This device includes two universal
  17. asynchronous receiver/transmitters, a baud rate generator, and a counter/timer
  18. device.  This driver module provides control of the two serial channels and
  19. the baud-rate generator.  The counter timer is controlled by a separate
  20. driver, src/drv/timer/m68681Timer.c.
  21. A M68681_DUART structure is used to describe the chip. This data structure
  22. contains two M68681_CHAN structures which describe the chip's two serial
  23. channels.  The M68681_DUART structure is defined in m68681Sio.h.
  24. Only asynchronous serial operation is supported by this driver.
  25. The default serial settings are 8 data bits, 1 stop bit, no parity, 9600
  26. baud, and software flow control.  These default settings can be overridden
  27. on a channel-by-channel basis by setting the M68681_CHAN options and `baudRate'
  28. fields to the desired values before calling m68681DevInit().  See sioLib.h
  29. for option values.  The defaults for the module can be changed by
  30. redefining the macros M68681_DEFAULT_OPTIONS and M68681_DEFAULT_BAUD and
  31. recompiling this driver.
  32. This driver supports baud rates of 75, 110, 134.5, 150, 300, 600, 1200,
  33. 2000, 2400, 4800, 1800, 9600, 19200, and 38400.
  34. USAGE
  35. The BSP's sysHwInit() routine typically calls sysSerialHwInit()
  36. which initializes all the hardware addresses in the M68681_DUART structure
  37. before calling m68681DevInit().  This enables the chip to operate in
  38. polled mode, but not in interrupt mode.  Calling m68681DevInit2() from
  39. the sysSerialHwInit2() routine allows interrupts to be enabled and
  40. interrupt-mode operation to be used.
  41. The following example shows the first part of the initialization thorugh
  42. calling m68681DevInit():
  43. .CS
  44. #include "drv/sio/m68681Sio.h"
  45. M68681_DUART myDuart; /@ my device structure @/
  46. #define MY_VEC (71) /@ use single vector, #71 @/
  47. sysSerialHwInit()
  48.     {
  49.     /@ initialize the register pointers for portA @/
  50.     myDuart.portA.mr = M68681_MRA;
  51.     myDuart.portA.sr = M68681_SRA;
  52.     myDuart.portA.csr = M68681_CSRA;
  53.     myDuart.portA.cr = M68681_CRA;
  54.     myDuart.portA.rb = M68681_RHRA;
  55.     myDuart.portA.tb = M68681_THRA;
  56.     /@ initialize the register pointers for portB @/
  57.     myDuart.portB.mr = M68681_MRB;
  58.     ...
  59.     /@ initialize the register pointers/data for main duart @/
  60.     myDuart.ivr = MY_VEC;
  61.     myDuart.ipcr = M68681_IPCR;
  62.     myDuart.acr = M68681_ACR;
  63.     myDuart.isr = M68681_ISR;
  64.     myDuart.imr = M68681_IMR;
  65.     myDuart.ip = M68681_IP;
  66.     myDuart.opcr = M68681_OPCR;
  67.     myDuart.sopbc = M68681_SOPBC;
  68.     myDuart.ropbc = M68681_ROPBC;
  69.     myDuart.ctroff = M68681_CTROFF;
  70.     myDuart.ctron = M68681_CTRON;
  71.     myDuart.ctlr = M68681_CTLR;
  72.     myDuart.ctur = M68681_CTUR;
  73.     m68681DevInit (&myDuart);
  74.     }
  75. .CE
  76. The BSP's sysHwInit2() routine typically calls sysSerialHwInit2() which
  77. connects the chips interrupts via intConnect() to the single
  78. interrupt handler m68681Int().  After the interrupt service routines are 
  79. connected, the user then calls m68681DevInit2() to allow the driver to 
  80. turn on interrupt enable bits, as shown in the following example:
  81. .CS
  82. sysSerialHwInit2 ()
  83.     {
  84.     /@ connect single vector for 68681 @/
  85.     intConnect (INUM_TO_IVEC(MY_VEC), m68681Int, (int)&myDuart);
  86.     ...
  87.     /@ allow interrupts to be enabled @/
  88.     m68681DevInit2 (&myDuart);
  89.     }
  90. .CE
  91. SPECIAL CONSIDERATIONS:
  92. The CLOCAL hardware option presumes that OP0 and OP1 output bits are wired
  93. to the CTS outputs for channel 0 and channel 1 respectively.  If not wired
  94. correctly, then the user must not select the CLOCAL option.  CLOCAL is
  95. not one of the default options for this reason.
  96. This driver does not manipulate the output port
  97. or its configuration register in any way.  If the user
  98. selects the CLOCAL option, then the output port bit must be wired correctly
  99. or the hardware flow control will not function correctly.
  100. INCLUDE FILES: drv/sio/m68681Sio.h
  101. */
  102. #include "vxWorks.h"
  103. #include "sioLib.h"
  104. #include "intLib.h"
  105. #include "errno.h"
  106. #include "drv/sio/m68681Sio.h"
  107. /* forward static declarations */
  108. LOCAL void   m68681InitChannel (M68681_CHAN *, M68681_DUART *);
  109. LOCAL void   m68681InitStruct (M68681_CHAN *);
  110. LOCAL STATUS m68681ModeSet (M68681_CHAN *, UINT);
  111. LOCAL STATUS m68681BaudSet (M68681_CHAN *, UINT);
  112. LOCAL STATUS m68681OptsSet (M68681_CHAN *, UINT);
  113. LOCAL int    m68681Ioctl (M68681_CHAN *, int, void *);
  114. LOCAL int    m68681TxStartup (M68681_CHAN *);
  115. LOCAL int    m68681CallbackInstall (M68681_CHAN *, int, STATUS (*)(), void *);
  116. LOCAL int    m68681PollInput (M68681_CHAN *, char *);
  117. LOCAL int    m68681PollOutput (M68681_CHAN*, char);
  118. /* driver functions */
  119. LOCAL SIO_DRV_FUNCS m68681SioDrvFuncs =
  120.     {
  121.     (int (*)(SIO_CHAN *, int, void *))m68681Ioctl,
  122.     (int (*)(SIO_CHAN *))m68681TxStartup,
  123.     (int (*)())m68681CallbackInstall,
  124.     (int (*)(SIO_CHAN *, char*))m68681PollInput,
  125.     (int (*)(SIO_CHAN *, char))m68681PollOutput
  126.     };
  127. /* typedefs */
  128. typedef struct        /* M68681_BAUD */
  129.     {
  130.     int rate; /* a baud rate */
  131.     UCHAR csrVal; /* rate to write to the csr reg to get that baud rate */
  132.     UCHAR baudBit; /* baud rate select bit, in ACR */
  133.     } M68681_BAUD;
  134. /*
  135.  * BaudTable is a table of the available baud rates, and the values to write
  136.  * to the csr reg to get those rates
  137.  */
  138. #define SET1 0
  139. #define SET2 M68681_ACR_BRG_SELECT
  140. LOCAL M68681_BAUD baudTable [] =
  141.     {
  142.     {75,        M68681_CSR_RX_75    | M68681_CSR_TX_75, SET2},
  143.     {110,       M68681_CSR_RX_110   | M68681_CSR_TX_110, SET2},
  144.     {134,       M68681_CSR_RX_134_5 | M68681_CSR_TX_134_5, SET2},
  145.     {150,       M68681_CSR_RX_150   | M68681_CSR_TX_150, SET2},
  146.     {300,       M68681_CSR_RX_300   | M68681_CSR_TX_300, SET2},
  147.     {600,       M68681_CSR_RX_600   | M68681_CSR_TX_600, SET2},
  148.     {1200,      M68681_CSR_RX_1200  | M68681_CSR_TX_1200, SET2},
  149.     {2000,      M68681_CSR_RX_2000  | M68681_CSR_TX_2000, SET2},
  150.     {2400,      M68681_CSR_RX_2400  | M68681_CSR_TX_2400, SET2},
  151.     {4800,      M68681_CSR_RX_4800  | M68681_CSR_TX_4800, SET2},
  152.     {1800,      M68681_CSR_RX_1800  | M68681_CSR_TX_1800, SET2},
  153.     {9600,      M68681_CSR_RX_9600  | M68681_CSR_TX_9600, SET2},
  154.     {19200,     M68681_CSR_RX_19200 | M68681_CSR_TX_19200, SET2},
  155.     {38400,     M68681_CSR_RX_38400 | M68681_CSR_TX_38400, SET1}
  156.     };
  157. #undef SET1
  158. #undef SET2
  159. /* defines */
  160. #ifndef M68681_DEFAULT_BAUD
  161. #   define M68681_DEFAULT_BAUD  9600
  162. #endif
  163. #ifndef M68681_DEFAULT_OPTIONS
  164.     /* no handshake, rcvr enabled, 8 data bits, 1 stop bit, no parity */
  165. #   define M68681_DEFAULT_OPTIONS (CLOCAL | CREAD | CS8)
  166. #endif
  167. /* Hardware read/write routines.  Can be redefined to create drivers
  168.  * for boards with special i/o access procedures. The reg pointer
  169.  * arguments are the register pointers from the M68681_CHAN or
  170.  * M68681_DUART structure.
  171.  */
  172. #ifndef M68681_READ
  173. #   define M68681_READ(x) (*x) /* argument is register pointer */
  174. #endif
  175. #ifndef M68681_WRITE
  176. #   define M68681_WRITE(x,y) (*x = y) /* args are reg ptr and data */
  177. #endif
  178. #define MAX_OPTIONS (0xff)
  179. #define MAX_BAUD (38400)
  180. /******************************************************************************
  181. *
  182. * m68681DevInit - intialize a M68681_DUART
  183. *
  184. * The BSP must already have initialized all the device addresses and
  185. * register pointers in the M68681_DUART structure as described in
  186. * `m68681Sio'. This routine initializes some transmitter and receiver status
  187. * values to be used in the interrupt mask register and then resets the chip
  188. * to a quiescent state.
  189. *
  190. * RETURNS: N/A
  191. */
  192. void m68681DevInit
  193.     (
  194.     M68681_DUART * pDuart
  195.     )
  196.     {
  197.     int oldlevel;
  198.     char resetTimer;
  199.     pDuart->intEnable = FALSE;
  200.     pDuart->tickRtn             = NULL;
  201.     pDuart->tickArg             = 0;
  202.     m68681ImrSetClr (pDuart, 0, -1);
  203.     m68681AcrSetClr (pDuart, 0, -1);
  204.     m68681OpcrSetClr(pDuart, 0, -1);
  205.     m68681OprSetClr (pDuart, 0, -1);
  206.     pDuart->portA.pDuart = pDuart;
  207.     pDuart->portA.xmitEnb = M68681_IMR_TX_RDY_A;
  208.     pDuart->portA.rcvrEnb = M68681_IMR_RX_RDY_A;
  209.     pDuart->portA.channel = M68681_CHANNEL_A;
  210.     pDuart->portB.pDuart = pDuart;
  211.     pDuart->portB.xmitEnb = M68681_IMR_TX_RDY_B;
  212.     pDuart->portB.rcvrEnb = M68681_IMR_RX_RDY_B;
  213.     pDuart->portB.channel = M68681_CHANNEL_B;
  214.     m68681InitStruct (&pDuart->portA);
  215.     m68681InitStruct (&pDuart->portB);
  216.     oldlevel =  intLock ();
  217.     /* Clear the interrupt mask register */
  218.     m68681ImrSetClr (pDuart, 0 , M68681_IMR_CLEAR);
  219.     m68681InitChannel (&pDuart->portA, pDuart);
  220.     m68681InitChannel (&pDuart->portB, pDuart);
  221.     resetTimer                   = M68681_READ (pDuart->ctroff);
  222.     intUnlock (oldlevel);
  223.     }
  224. /******************************************************************************
  225. *
  226. * m68681DevInit2 - intialize a M68681_DUART, part 2
  227. *
  228. * This routine is called as part of sysSerialHwInit2().  It tells
  229. * the driver that interrupt vectors are connected and that it is
  230. * safe to allow interrupts to be enabled.
  231. *
  232. * RETURNS: N/A
  233. */
  234. void m68681DevInit2
  235.     (
  236.     M68681_DUART * pDuart
  237.     )
  238.     {
  239.     /* Allow interrupt mode */
  240.     pDuart->intEnable = TRUE;
  241.     /* call ModeSet, to startup devices if needed */
  242.     m68681ModeSet (&pDuart->portA, pDuart->portA.mode);
  243.     m68681ModeSet (&pDuart->portB, pDuart->portB.mode);
  244.     }
  245. /*******************************************************************************
  246. *
  247. * m68681ImrSetClr - set and clear bits in the DUART interrupt-mask register
  248. *
  249. * This routine sets and clears bits in the DUART interrupt-mask register (IMR).
  250. * It sets and clears bits in a local copy of the IMR, then
  251. * writes that local copy to the DUART.  This means that all changes to
  252. * the IMR must be performed by this routine.  Any direct changes
  253. * to the IMR are lost the next time this routine is called.
  254. *
  255. * Set has priority over clear.  Thus you can use this routine to update
  256. * multiple bit fields by specifying the field mask as the clear bits.
  257. *
  258. * RETURNS: N/A
  259. */
  260. void m68681ImrSetClr
  261.     (
  262.     M68681_DUART * pDuart,
  263.     UCHAR setBits,       /* which bits to set in the IMR   */
  264.     UCHAR clearBits      /* which bits to clear in the IMR */
  265.     )
  266.     {
  267.     pDuart->imrCopy = ((pDuart->imrCopy & ~clearBits) | setBits);
  268.     M68681_WRITE (pDuart->imr, pDuart->imrCopy);
  269.     }
  270. /*******************************************************************************
  271. *
  272. * m68681Imr - return the current contents of the DUART interrupt-mask register
  273. *
  274. * This routine returns the contents of the interrupt-mask register (IMR).  
  275. * The IMR is not directly readable; a copy of the last value written is kept
  276. * in the DUART data structure.
  277. *
  278. * RETURNS: The contents of the interrupt-mask register.
  279. */
  280. UCHAR m68681Imr
  281.     (
  282.     M68681_DUART * pDuart
  283.     )
  284.     {
  285.     return pDuart->imrCopy;
  286.     }
  287. /*******************************************************************************
  288. *
  289. * m68681AcrSetClr - set and clear bits in the DUART auxiliary control register
  290. *
  291. * This routine sets and clears bits in the DUART auxiliary control register
  292. * (ACR).  It sets and clears bits in a local copy of the ACR, then
  293. * writes that local copy to the DUART.  This means that all changes to
  294. * the ACR must be performed by this routine.  Any direct changes
  295. * to the ACR are lost the next time this routine is called.
  296. *
  297. * Set has priority over clear.  Thus you can use this routine to update
  298. * multiple bit fields by specifying the field mask as the clear bits.
  299. *
  300. * RETURNS: N/A
  301. */
  302. void m68681AcrSetClr
  303.     (
  304.     M68681_DUART * pDuart,
  305.     UCHAR setBits,       /* which bits to set in the ACR   */
  306.     UCHAR clearBits      /* which bits to clear in the ACR */
  307.     )
  308.     {
  309.     pDuart->acrCopy = ((pDuart->acrCopy &  ~clearBits) | setBits);
  310.     M68681_WRITE (pDuart->acr, pDuart->acrCopy);
  311.     }
  312. /*******************************************************************************
  313. *
  314. * m68681Acr - return the contents of the DUART auxiliary control register
  315. *
  316. * This routine returns the contents of the auxilliary control register (ACR).
  317. * The ACR is not directly readable; a copy of the last value written is kept
  318. * in the DUART data structure.
  319. *
  320. * RETURNS: The contents of the auxilliary control register.
  321. */
  322. UCHAR m68681Acr
  323.     (
  324.     M68681_DUART * pDuart
  325.     )
  326.     {
  327.     return pDuart->acrCopy;
  328.     }
  329. /*******************************************************************************
  330. *
  331. * m68681OprSetClr - set and clear bits in the DUART output port register
  332. *
  333. * This routine sets and clears bits in the DUART output port register
  334. * (OPR).  It sets and clears bits in a local copy of the OPR, then writes
  335. * that local copy to the DUART.  This means that all changes to the OPR must
  336. * be performed by this routine.  Any direct changes to the OPR are lost the
  337. * next time this routine is called.
  338. *
  339. * Set has priority over clear.  Thus you can use this routine to update
  340. * multiple bit fields by specifying the field mask as the clear bits.
  341. *
  342. * RETURNS: N/A
  343. */
  344. void m68681OprSetClr
  345.     (
  346.     M68681_DUART * pDuart,
  347.     UCHAR setBits,       /* which bits to set in the OPR   */
  348.     UCHAR clearBits      /* which bits to clear in the OPR */
  349.     )
  350.     {
  351.     pDuart->oprCopy = ((pDuart->oprCopy &  ~clearBits) | setBits);
  352.     M68681_WRITE (pDuart->ropbc, clearBits);
  353.     M68681_WRITE (pDuart->sopbc, setBits);
  354.     }
  355. /*******************************************************************************
  356. *
  357. * m68681Opr - return the current state of the DUART output port register
  358. *
  359. * This routine returns the current state of the output port register (OPR) 
  360. * from the saved copy in the DUART data structure.  The actual OPR contents
  361. * are not directly readable.
  362. *
  363. * RETURNS: The current state of the output port register.
  364. */
  365. UCHAR m68681Opr
  366.     (
  367.     M68681_DUART * pDuart
  368.     )
  369.     {
  370.     return pDuart->oprCopy;
  371.     }
  372. /*******************************************************************************
  373. *
  374. * m68681OpcrSetClr - set and clear bits in the DUART output port configuration register
  375. *
  376. * This routine sets and clears bits in the DUART output port configuration
  377. * register (OPCR).  It sets and clears bits in a local copy of the OPCR,
  378. * then writes that local copy to the DUART.  This means that all changes to
  379. * the OPCR must be performed by this routine.  Any direct changes to the
  380. * OPCR are lost the next time this routine is called.
  381. *
  382. * Set has priority over clear.  Thus you can use this routine to update
  383. * multiple bit fields by specifying the field mask as the clear bits.
  384. *
  385. * RETURNS: N/A
  386. */
  387. void m68681OpcrSetClr
  388.     (
  389.     M68681_DUART * pDuart,
  390.     UCHAR setBits,       /* which bits to set in the OPCR   */
  391.     UCHAR clearBits      /* which bits to clear in the OPCR */
  392.     )
  393.     {
  394.     pDuart->opcrCopy = ((pDuart->opcrCopy &  ~clearBits) | setBits);
  395.     M68681_WRITE (pDuart->opcr, pDuart->opcrCopy);
  396.     }
  397. /*******************************************************************************
  398. *
  399. * m68681Opcr - return the state of the DUART output port configuration register
  400. *
  401. * This routine returns the state of the output port configuration register
  402. * (OPCR) from the saved copy in the DUART data structure.  The actual OPCR
  403. * contents are not directly readable.
  404. *
  405. * RETURNS: The state of the output port configuration register.
  406. */
  407. UCHAR m68681Opcr
  408.     (
  409.     M68681_DUART * pDuart
  410.     )
  411.     {
  412.     return pDuart->opcrCopy;
  413.     }
  414. /******************************************************************************
  415. *
  416. * m68681DummyCallback - dummy callback routine.
  417. *
  418. * RETURNS:
  419. * Always returns ERROR
  420. */
  421. LOCAL STATUS m68681DummyCallback (void)
  422.     {
  423.     return (ERROR);
  424.     }
  425. /******************************************************************************
  426. *
  427. * m68681TxStartup - start the interrupt transmitter.
  428. *
  429. * This routine enables the transmitters for the specified DUART channel so that
  430. * the DUART channel will interrupt the CPU when TxRDY bit in the status
  431. * register is set.
  432. *
  433. * RETURNS:
  434. * Returns OK on success, or EIO on hardware error.
  435. */
  436. LOCAL int m68681TxStartup
  437.     (
  438.     M68681_CHAN * pChan
  439.     )
  440.     {
  441.     char   outChar;
  442.     int    lvl;
  443.     if ((*pChan->getTxChar) (pChan->getTxArg, &outChar) != ERROR)
  444. {
  445. lvl = intLock ();
  446. M68681_WRITE (pChan->cr, M68681_CR_TX_ENABLE);
  447. M68681_WRITE (pChan->tb, outChar);
  448. intUnlock (lvl);
  449. }
  450.     return (OK);
  451.     }
  452. /******************************************************************************
  453. *
  454. * m68681CallbackInstall - install ISR callbacks to get/put chars.
  455. *
  456. * This driver allows interrupt callbacks, for transmitting characters
  457. * and receiving characters. In general, drivers may support other types
  458. * of callbacks too.
  459. *
  460. * RETURNS:
  461. * Returns OK on success, or ENOSYS for an unsupported callback type.
  462. */
  463. LOCAL int m68681CallbackInstall
  464.     (
  465.     M68681_CHAN * pChan,
  466.     int callbackType,
  467.     STATUS (*callback)(),
  468.     void *      callbackArg
  469.     )
  470.     {
  471.     switch (callbackType)
  472.         {
  473. case SIO_CALLBACK_GET_TX_CHAR:
  474.     pChan->getTxChar = callback;
  475.     pChan->getTxArg = callbackArg;
  476.     return (OK);
  477. case SIO_CALLBACK_PUT_RCV_CHAR:
  478.     pChan->putRcvChar = callback;
  479.     pChan->putRcvArg = callbackArg;
  480.     return (OK);
  481. default:
  482.     return (ENOSYS);
  483. }
  484.     }
  485. /******************************************************************************
  486. *
  487. * m68681PollOutput - output a character in polled mode.
  488. *
  489. * This routine polls the status register to see if the TxRDY bit has been set.
  490. * This signals that the transmit holding register is empty and that the
  491. * specified DUART channel is ready for transmission.
  492. *
  493. * RETURNS:
  494. * Returns OK if a character sent, EIO on device error, EAGAIN
  495. * if the output buffer is full.
  496. */
  497. LOCAL int m68681PollOutput
  498.     (
  499.     M68681_CHAN * pChan,
  500.     char outChar
  501.     )
  502.     {
  503.     char statusReg;
  504.     statusReg = M68681_READ (pChan->sr);
  505.     /* is the transitter ready to accept a character? */
  506.     if ((statusReg & M68681_SR_TXRDY) == 0x00)
  507. return (EAGAIN);
  508.     /* write out the character */
  509.     M68681_WRITE (pChan->tb, outChar);
  510.     return (OK);
  511.     }
  512. /******************************************************************************
  513. *
  514. * m68681PollInput - poll the device for input.
  515. *
  516. * This routine polls the status register to see if the RxRDY bit is set.
  517. * This gets set when the DUART receives a character and signals the
  518. * pressence of a character in the channels receive buffer.
  519. *
  520. * RETURNS:
  521. * Returns OK if a character arrived, EIO on device error, EAGAIN
  522. * if the input buffer if empty.
  523. */
  524. LOCAL int m68681PollInput
  525.     (
  526.     M68681_CHAN * pChan,
  527.     char * thisChar
  528.     )
  529.     {
  530.     char statusReg;
  531.     statusReg = M68681_READ (pChan->sr);
  532.     if ((statusReg & M68681_SR_RXRDY) == 0x00)
  533. return (EAGAIN);
  534.     M68681_WRITE (thisChar, *pChan->rb);
  535.     return (OK);
  536.     }
  537. /******************************************************************************
  538. *
  539. * m68681ModeSet - change channel mode setting
  540. *
  541. * This driver supports both polled and interrupt modes and is capable of
  542. * switching between modes dynamically. If interrupt mode is desired this
  543. * routine enables the channels receiver, transmitter interrupt and the
  544. * received break condition interrupt. If polled mode is desired the xmitrs for
  545. * the specified channel is enabled.
  546. *
  547. * RETURNS:
  548. * Returns a status of OK if the mode was set else ERROR.
  549. */
  550. LOCAL STATUS m68681ModeSet
  551.     (
  552.     M68681_CHAN * pChan,
  553.     UINT newMode
  554.     )
  555.     {
  556.     int oldlevel;
  557.     if ((newMode != SIO_MODE_POLL) && (newMode != SIO_MODE_INT))
  558. return (ERROR);
  559.     oldlevel = intLock ();
  560.     if (newMode == SIO_MODE_INT
  561.      && pChan->pDuart->intEnable)
  562.         {
  563. /* Enable the interrupts for receiver/transmitter conditions */
  564. m68681ImrSetClr (pChan->pDuart, (pChan->rcvrEnb | pChan->xmitEnb), 0);
  565.         }
  566.     else
  567.         {
  568. /* Disable interrupts and enable the transmitter for the channel */
  569. m68681ImrSetClr (pChan->pDuart, 0, (pChan->rcvrEnb | pChan->xmitEnb));
  570. M68681_WRITE (pChan->cr, M68681_CR_TX_ENABLE);
  571.         }
  572.     intUnlock (oldlevel);
  573.     pChan->mode = newMode;
  574.     return (OK);
  575.     }
  576. /******************************************************************************
  577. *
  578. * m68681BaudSet - change baud rate for channel
  579. *
  580. * This routine sets the baud rate for the DUART. The interrupts are disabled
  581. * during chip access.
  582. *
  583. * RETURNS:
  584. * Returns a status of OK if the baud rate was set else ERROR.
  585. */
  586. LOCAL STATUS  m68681BaudSet
  587.     (
  588.     M68681_CHAN * pChan,
  589.     UINT baud
  590.     )
  591.     {
  592.     int ix, oldlevel = intLock ();
  593.     STATUS status = ERROR;
  594.     for (ix = 0; ix < NELEMENTS (baudTable); ix ++)
  595.         {
  596. if (baudTable [ix].rate == baud)
  597.     {
  598.     m68681AcrSetClr (pChan->pDuart, baudTable[ix].baudBit,
  599.     M68681_ACR_BRG_SELECT);
  600.     M68681_WRITE (pChan->csr, baudTable [ix].csrVal);
  601.     pChan->baudRate = baud;
  602.     status = OK;
  603.     break;
  604.     }
  605.         }
  606.     intUnlock (oldlevel);
  607.     return (status);
  608.     }
  609. /*******************************************************************************
  610. *
  611. * m68681InitStruct - initializes the channel structure
  612. *
  613. * This routine initializes the specified channels driver functions.
  614. *
  615. * RETURNS: N/A.
  616. */
  617. LOCAL void m68681InitStruct
  618.     (
  619.     M68681_CHAN * pChan
  620.     )
  621.     {
  622.     pChan->sio.pDrvFuncs= &m68681SioDrvFuncs;
  623.     pChan->getTxChar = m68681DummyCallback;
  624.     pChan->putRcvChar = m68681DummyCallback;
  625.     pChan->mode = 0; /* undefined */
  626.     if (pChan->options == 0 || pChan->options > MAX_OPTIONS)
  627. pChan->options = M68681_DEFAULT_OPTIONS;
  628.     if (pChan->baudRate == 0 || pChan->baudRate > MAX_BAUD)
  629. pChan->baudRate = M68681_DEFAULT_BAUD;
  630.     }
  631. /*******************************************************************************
  632. *
  633. * m68681InitChannel - initialize a single channel
  634. *
  635. * This routine initializes the specified channel.  It is required
  636. * that the transmitters and receivers have been issued s/w reset commands
  637. * before the mode registers, clock select registers, auxillary clock
  638. * registers & output port configuration registers are changed.
  639. *
  640. * This routine only sets the initial state as part of m68681DevInit.  The
  641. * user can change this state through ioct clommands as desired.
  642. *
  643. * RETURNS: N/A.
  644. */
  645. LOCAL void m68681InitChannel
  646.     (
  647.     M68681_CHAN * pChan,
  648.     M68681_DUART * pDuart
  649.     )
  650.     {
  651.     /* Reset the transmitters  & receivers  */
  652.     M68681_WRITE (pChan->cr, M68681_CR_RST_BRK_INT_CMD);
  653.     M68681_WRITE (pChan->cr, M68681_CR_RST_ERR_STS_CMD);
  654.     m68681OptsSet (pChan, pChan->options); /* TX is disabled */
  655.     m68681BaudSet (pChan, pChan->baudRate);
  656.     }
  657. /*******************************************************************************
  658. *
  659. * m68681OptsSet - set the serial options
  660. *
  661. * Set the channel operating mode to that specified.  All sioLib options
  662. * are supported: CLOCAL, CREAD, CSIZE, PARENB, and PARODD.
  663. *
  664. * Note, this routine disables the transmitter.  The calling routine
  665. * may have to re-enable it.
  666. *
  667. * RETURNS:
  668. * Returns OK to indicate success, otherwise ERROR is returned
  669. */
  670. LOCAL STATUS m68681OptsSet
  671.     (
  672.     M68681_CHAN * pChan, /* ptr to channel */
  673.     UINT options /* new hardware options */
  674.     )
  675.     {
  676.     int mr1Value = 0;
  677.     int mr2Value = 0;
  678.     int lvl;
  679.     if (pChan == NULL || options & 0xffffff00)
  680. return ERROR;
  681.     /* Reset the transmitters  & receivers  */
  682.     switch (options & CSIZE)
  683. {
  684. case CS5:
  685.     mr1Value = M68681_MR1_BITS_CHAR_5; break;
  686. case CS6:
  687.     mr1Value = M68681_MR1_BITS_CHAR_6; break;
  688. case CS7:
  689.     mr1Value = M68681_MR1_BITS_CHAR_7; break;
  690. default:
  691. case CS8:
  692.     mr1Value = M68681_MR1_BITS_CHAR_8; break;
  693. }
  694.     if (options & STOPB)
  695. mr2Value = M68681_MR2_STOP_BITS_2;
  696.     else
  697. mr2Value = M68681_MR2_STOP_BITS_1;
  698.     switch (options & (PARENB|PARODD))
  699. {
  700. case PARENB|PARODD:
  701.     mr1Value |= M68681_MR1_ODD_PARITY; break;
  702. case PARENB:
  703.     mr1Value |= M68681_MR1_EVEN_PARITY; break;
  704. case PARODD:
  705.     mr1Value |= M68681_MR1_PAR_MODE_MULTI; break;
  706. default:
  707. case 0:
  708.     mr1Value |= M68681_MR1_NO_PARITY; break;
  709. }
  710.     if (!(options & CLOCAL))
  711. {
  712. /* clocal disables hardware flow control */
  713. mr1Value |= M68681_MR1_RX_RTS;
  714. mr2Value |= M68681_MR2_TX_CTS;
  715. }
  716.     lvl = intLock ();
  717.     /* now reset the channel mode registers */
  718.     M68681_WRITE (pChan->cr, M68681_CR_RST_MR_PTR_CMD | M68681_CR_RX_DISABLE |
  719.                       M68681_CR_TX_DISABLE);
  720.     M68681_WRITE (pChan->cr, M68681_CR_RST_TX_CMD);
  721.     M68681_WRITE (pChan->cr, M68681_CR_RST_RX_CMD);
  722.     M68681_WRITE (pChan->mr, mr1Value);  /* mode register 1  */
  723.     M68681_WRITE (pChan->mr, mr2Value);  /* mode register 2  */
  724.     if (options & CREAD)
  725. M68681_WRITE (pChan->cr, M68681_CR_RX_ENABLE);
  726.     intUnlock (lvl);
  727.     pChan->options = options;
  728.     return OK;
  729.     }
  730. /*******************************************************************************
  731. *
  732. * m68681Ioctl - special device control
  733. *
  734. * RETURNS:
  735. * Returns OK on success, EIO on device error, ENOSYS on unsupported
  736. * request.
  737. */
  738. LOCAL int m68681Ioctl
  739.     (
  740.     M68681_CHAN * pChan, /* device to control */
  741.     int request, /* request code */
  742.     void * someArg /* some argument */
  743.     )
  744.     {
  745.     STATUS result;
  746.     int     arg = (int)someArg;
  747.     switch (request)
  748. {
  749. case SIO_BAUD_SET:
  750.     return (m68681BaudSet (pChan, arg) == OK ? OK : EIO);
  751. case SIO_BAUD_GET:
  752.     *(int *)arg = pChan->baudRate;
  753.     return (OK);
  754. case SIO_MODE_SET:
  755.     return (m68681ModeSet (pChan, arg) == OK ? OK : EIO);
  756. case SIO_MODE_GET:
  757.     *(int *)arg = pChan->mode;
  758.     return (OK);
  759. case SIO_AVAIL_MODES_GET:
  760.     *(int *)arg = SIO_MODE_INT | SIO_MODE_POLL;
  761.     return (OK);
  762. case SIO_HW_OPTS_SET:
  763.     /* change options, then set mode to restart chip correctly */
  764.     result = m68681OptsSet (pChan, arg);
  765.     m68681ModeSet (pChan, pChan->mode);
  766.     return result;
  767. case SIO_HW_OPTS_GET:
  768.     *(int *)arg = pChan->options;
  769.     return (OK);
  770. default:
  771.     return (ENOSYS);
  772. }
  773.     }
  774. /*******************************************************************************
  775. *
  776. * m68681IntWr - handle a transmitter interrupt
  777. *
  778. * This routine handles write interrupts from the DUART. This isr is invoked
  779. * when the TxRDY bit in the interrupt status register has been set. If there
  780. * is no character to transmit the transmitter for the channel is disabled.
  781. *
  782. * RETURNS: N/A
  783. */
  784. LOCAL void m68681IntWr
  785.     (
  786.     M68681_CHAN * pChan
  787.     )
  788.     {
  789.     char            outChar;
  790.     volatile UCHAR  *tb = pChan->tb;
  791.     if ((*pChan->getTxChar) (pChan->getTxArg, &outChar) != ERROR)
  792. {
  793. M68681_WRITE (tb, outChar);    /* if char available, tx it */
  794. }
  795.     else
  796.         {
  797. M68681_WRITE (pChan->cr, M68681_CR_TX_DISABLE);
  798.         }
  799.     }
  800. /*****************************************************************************
  801. *
  802. * m68681IntRd - handle a reciever interrupt
  803. *
  804. * This routine handles read interrupts from the DUART.
  805. * The DUART has been programmed to generate read interrupts when the RXRDY
  806. * status bit has been set in the interrupt status register. When a character
  807. * has been  received it is removed from the channels receive buffer.
  808. *
  809. * RETURNS: N/A
  810. */
  811. LOCAL void m68681IntRd
  812.     (
  813.     M68681_CHAN * pChan
  814.     )
  815.     {
  816.     volatile UCHAR  *rb = pChan->rb;
  817.     UCHAR            inchar;
  818.     char             statusReg;
  819.     statusReg = M68681_READ (pChan->sr);
  820.     while ((statusReg & M68681_SR_RXRDY) != 0x00)
  821.         {
  822. inchar = M68681_READ (rb);
  823. (*pChan->putRcvChar) (pChan->putRcvArg, inchar);
  824. if (pChan->mode != SIO_MODE_INT)
  825.     break;
  826. statusReg = M68681_READ (pChan->sr);
  827.         }
  828.     }
  829. /*******************************************************************************
  830. *
  831. * m68681Int - handle all DUART interrupts in one vector
  832. *
  833. * This routine handles all interrupts in a single interrupt vector.
  834. * It identifies and services each interrupting source in turn, using
  835. * edge-sensitive interrupt controllers.
  836. *
  837. * RETURNS: N/A
  838. */
  839. void m68681Int
  840.     (
  841.     M68681_DUART * pDuart
  842.     )
  843.     {
  844.     UCHAR         intStatus;
  845.     volatile UCHAR      resetTimer;
  846.     /* loop until all sources have been handled */
  847.     while ((intStatus = (M68681_READ(pDuart->isr) & pDuart->imrCopy)) != 0)
  848. {
  849. if ((intStatus & M68681_ISR_TX_RDY_A_INT) != 0)
  850.     m68681IntWr (&pDuart->portA);
  851. if ((intStatus & M68681_ISR_RX_RDY_A_INT) != 0)
  852.     m68681IntRd (&pDuart->portA);
  853. if ((intStatus & M68681_ISR_TX_RDY_B_INT) != 0)
  854.     m68681IntWr (&pDuart->portB);
  855.      
  856. if ((intStatus & M68681_ISR_RX_RDY_B_INT) != 0)
  857.     m68681IntRd (&pDuart->portB);
  858. if (intStatus & M68681_ISR_CTR_RDY_INT)
  859.     {
  860.     if (pDuart->tickRtn != NULL)
  861. (*pDuart->tickRtn) (pDuart->tickArg);
  862.     else
  863. /* Clear the timer int */
  864. resetTimer = M68681_READ (pDuart->ctroff);
  865.     }
  866. }
  867.     }