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

VxWorks

开发平台:

C/C++

  1. /* m68901Sio.c - MC68901 MFP tty driver */
  2. /* Copyright 1984-2002 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01c,24apr02,pmr  SPR 75161: returning int from m68901TxStartup() as required.
  8. 01b,08nov96,dgp  doc: final formatting
  9. 01a,25may96,sub  wrote from m68901Serial.c
  10. */
  11. /*
  12. DESCRIPTION
  13. This is the SIO driver for the Motorola MC68901 Multi-Function Peripheral
  14. (MFP) chip.
  15. USER-CALLABLE ROUTINES
  16. Most of the routines in this driver are accessible only through the I/O
  17. system.  However, one routine must be called directly:  m68901DevInit()
  18. initializes the driver.  Normally, it is called by sysSerialHwInit()
  19. in sysSerial.c
  20. IOCTL FUNCTIONS
  21. This driver responds to the same ioctl() codes as other tty drivers;
  22. for more information, see the manual entry for tyLib.
  23. SEE ALSO
  24. tyLib
  25. */
  26. /* includes */
  27. #include "vxWorks.h"
  28. #include "errnoLib.h"
  29. #include "iosLib.h"
  30. #include "memLib.h"
  31. #include "tyLib.h"
  32. #include "intLib.h"
  33. #include "iv.h"
  34. #include "drv/sio/m68901Sio.h"
  35. /* defines */
  36. #define DEFAULT_BAUD  9600
  37. /* forward declarations */
  38. LOCAL void m68901InitChannel (M68901_CHAN *);
  39. LOCAL int  m68901Ioctl (SIO_CHAN *, int, void *);
  40. LOCAL int   m68901TxStartup (SIO_CHAN *);
  41. LOCAL int  m68901CallBackInstall (SIO_CHAN *,int, STATUS (*)(), void *);
  42. LOCAL int  m68901PollInput (SIO_CHAN *, char *);
  43. LOCAL int  m68901PollOutput (SIO_CHAN *, char);
  44. LOCAL int m68901ModeSet(M68901_CHAN *, uint_t); 
  45. /* locals */
  46. LOCAL SIO_DRV_FUNCS m68901SioDrvFuncs =
  47.     {
  48.     (int (*) ()) m68901Ioctl,
  49.     (int (*) ()) m68901TxStartup,
  50.     (int (*) ()) m68901CallBackInstall,
  51.     (int (*) ()) m68901PollInput,
  52.     (int (*) (SIO_CHAN *, char)) m68901PollOutput
  53.     };
  54. /*******************************************************************************
  55. *
  56. *  m68901DummyCallback - dummy callback routine.
  57. */
  58. LOCAL STATUS m68901DummyCallback (void)
  59.     {
  60.     return(ERROR);
  61.     }
  62. /*******************************************************************************
  63. *
  64. * m68901InitChannel - initialize a single channel
  65. *
  66. */
  67. LOCAL void m68901InitChannel 
  68.     (
  69.     M68901_CHAN  *pChan
  70.     )
  71.     {
  72.     int lock = intLock ();
  73.     /* 8 data bits, 1 stop bit, no parity */
  74.     *pChan->ucr = (char)(MFP_UCR_16X | MFP_UCR_8BIT |
  75.         MFP_UCR_1STOP | MFP_UCR_NO_PARITY);
  76.     /* set baud rate values w/ prescale=4 */
  77.     *pChan->baud1 = pChan->baudFreq / (128 * 9600);
  78.     if (pChan->baud2 != NULL)
  79.         *pChan->baud2 = pChan->baudFreq / (128 * 9600);
  80.     /* enable the receivers and transmitters on both channels */
  81.     *pChan->rsr  = MFP_RSR_RX_ENABLE;      /* enable rcvr status */
  82.     *pChan->tsr  = MFP_TSR_TX_ENABLE;      /* enable xmit status */
  83.     intUnlock (lock);
  84.     }
  85. /*******************************************************************************
  86. *
  87. * m68901Ioctl - special device control
  88. *
  89. *
  90. * RETURNS: OK on success, EIO on device error, ENOSYS on 
  91. * unsupported requests.
  92. */
  93. LOCAL STATUS m68901Ioctl
  94.     (
  95.     SIO_CHAN *pSioChan, /* device to control */
  96.     int request, /* request code */
  97.     void * arg /* some argument */
  98.     )
  99.     {
  100.     M68901_CHAN *pChan = (M68901_CHAN  *)pSioChan;
  101.     switch (request)
  102. {
  103.         case SIO_BAUD_SET:
  104.             if (((int)arg >= pChan->baudMin) && ((int)arg <= pChan->baudMax))
  105.                 {
  106. /* set baud rate values w/ prescale=4 */
  107. *pChan->baud1 = pChan->baudFreq / (128 * (int)arg);
  108. if (pChan->baud2 != NULL)
  109.     *pChan->baud2 = pChan->baudFreq / (128 * (int)arg);
  110. pChan->baudRate = (int)arg; 
  111. return (OK);
  112.                 }
  113.     return (EIO);
  114.     
  115. case SIO_BAUD_GET:
  116.     *(int *)arg = pChan->baudRate;
  117.     return (OK);
  118. case SIO_MODE_SET:
  119.     return (m68901ModeSet (pChan,(uint_t)arg) == OK ? OK: EIO);
  120. case SIO_MODE_GET:
  121.     *(int *)arg = pChan->mode;
  122.     return (OK);
  123. case SIO_AVAIL_MODES_GET:
  124.     *(int *)arg = SIO_MODE_INT | SIO_MODE_POLL;
  125.     return (OK);
  126. default:
  127.     return (ENOSYS);
  128. }
  129.     }
  130. /*******************************************************************************
  131. *
  132. * m68901DevInit - initialize a M68901_CHAN structure
  133. *
  134. * This routine initializes the driver
  135. * function pointers and then resets the chip to a quiescent state.
  136. * The BSP must have already initialized all the device addresses and the
  137. * `baudFreq' fields in the M68901_CHAN structure before passing it to
  138. * this routine.
  139. *
  140. * RETURNS: N/A
  141. */
  142. void m68901DevInit
  143.     (
  144.     M68901_CHAN * pChan
  145.     )
  146.     {
  147.     int oldlevel = intLock ();
  148.     pChan->pDrvFuncs = &m68901SioDrvFuncs;
  149.     pChan->baudRate = DEFAULT_BAUD;
  150.     pChan->getTxChar = m68901DummyCallback;
  151.     pChan->putRcvChar = m68901DummyCallback;
  152.     pChan->mode = 0; /* undefined */
  153.     /* reset the chip */
  154.     m68901InitChannel (pChan);
  155.     intUnlock (oldlevel);
  156.     }
  157. /*******************************************************************************
  158. *
  159. * m68901IntWr - handle a transmitter interrupt
  160. *
  161. * This routine gets called to handle transmitter interrupts.
  162. *
  163. * NOMANUAL
  164. */
  165. void m68901IntWr 
  166.     (
  167.     M68901_CHAN * pChan
  168.     )
  169.     {
  170.     char outChar;
  171.     volatile char *dr = pChan->udr; /* USART data register */
  172.     
  173.     if ((*pChan->getTxChar) (pChan->getTxArg, &outChar) != ERROR)
  174. *dr = outChar;
  175.     else
  176. *pChan->imra &= ~MFP_A_TX_EMPTY; /* turn off transmitter */
  177.     }
  178. /*******************************************************************************
  179. *
  180. * m68901IntRd - handle a receiver interrupt
  181. *
  182. * NOMANUAL
  183. */
  184. void m68901IntRd 
  185.     (
  186.     M68901_CHAN *pChan
  187.     )
  188.     {
  189.     volatile char *dr = pChan->udr;
  190.     char inChar;
  191.     inChar = *dr;
  192.     (*pChan->putRcvChar) (pChan->putRcvArg, inChar);
  193.     }
  194. /*******************************************************************************
  195. *
  196. * m68901TxStartup - transmitter startup routine
  197. *
  198. * Call interrupt level character output routine.
  199. */
  200. LOCAL int m68901TxStartup
  201.     (
  202.     SIO_CHAN *pSioChan
  203.     )
  204.     {
  205.     M68901_CHAN * pChan = (M68901_CHAN *)pSioChan;
  206.     
  207.     char outchar;
  208.     /* enable the transmitter and it should interrupt to write the next char */
  209.     if ((*pChan->getTxChar) (pChan->getTxArg, &outchar) !=ERROR)
  210. *pChan->udr = outchar;
  211.     *pChan->imra |= MFP_A_TX_EMPTY; /* turn on transmitter */
  212.     return (OK);
  213.     }
  214. /*******************************************************************************
  215. *
  216. * m68901CallBackInstall -  install ISR callbacks to get/put chars
  217. *
  218. */
  219. LOCAL int m68901CallBackInstall 
  220.     (
  221.     SIO_CHAN * pSioChan,
  222.     int callbackType, 
  223.     STATUS (*callback)(), 
  224.     void *  callbackArg
  225.     )
  226.     {
  227.     M68901_CHAN * pChan = (M68901_CHAN *)pSioChan;
  228.     
  229.     switch (callbackType)
  230. {
  231. case SIO_CALLBACK_GET_TX_CHAR:
  232.     pChan->getTxChar = callback;
  233.     pChan->getTxArg  = callbackArg;
  234.     return (OK);
  235. case SIO_CALLBACK_PUT_RCV_CHAR:
  236.     pChan->putRcvChar= callback;
  237.     pChan->putRcvArg = callbackArg;
  238.     return (OK);
  239. default:
  240.     return(ENOSYS);
  241. }
  242.     }
  243. /*******************************************************************************
  244. *
  245. * m68901PollOutput - output a character in polled mode.
  246. *
  247. * RETURNS:  OK if a character arrived, EIO on device error, EAGAIN if
  248. * the output buffer is full.
  249. */
  250. LOCAL int m68901PollOutput
  251.     (
  252.     SIO_CHAN * pSioChan,
  253.     char       outChar
  254.     )
  255.     {
  256.     M68901_CHAN * pChan = (M68901_CHAN *) pSioChan;
  257.     if (( *(char *)pChan->tsr & MFP_TSR_BUFFER_EMPTY) == 0)
  258. return (EAGAIN);
  259.     *pChan->udr = outChar;
  260.     return (OK);
  261.     }
  262. /*******************************************************************************
  263. *
  264. * m68901PollInput - poll device for input
  265. *
  266. * RETURNS:  OK if a character arrived, EIO on device error, EAGAIN if
  267. * the input buffer is empty.
  268. */
  269. LOCAL int m68901PollInput
  270.     (
  271.     SIO_CHAN * pSioChan,
  272.     char     * outChar
  273.     )
  274.     {
  275.     M68901_CHAN * pChan = (M68901_CHAN *) pSioChan;
  276.     if (( *(char *)pChan->rsr & MFP_RSR_BUFFER_FULL) == 0)
  277. return (EAGAIN);
  278.     *outChar = *(char *)pChan->udr;
  279.     return (OK);
  280.     }
  281. /******************************************************************************
  282. *
  283. * m68901ModeSet - toggle between interrupt and polled mode.
  284. *
  285. * RETURNS: OK on success, EIO on unsupported mode.
  286. */
  287. LOCAL int m68901ModeSet
  288.     (
  289.     M68901_CHAN * pChan, /* channel */
  290.     uint_t     newMode           /* new mode */
  291.     )
  292.     {
  293.     int oldlevel;
  294.     
  295.     if ((newMode != SIO_MODE_POLL) && (newMode != SIO_MODE_INT))
  296. return (EIO);
  297.     /* set the new mode */
  298.     oldlevel = intLock();
  299.     
  300.     pChan->mode = newMode;
  301.     if (pChan->mode == SIO_MODE_INT)
  302. {
  303. *pChan->iera |= MFP_A_RX_FULL;  /* enable recv int. */
  304. *pChan->iera |= MFP_A_RX_ERR;   /* enable recv error int. */
  305. *pChan->iera |= MFP_A_TX_EMPTY; /* enable transmit int. */
  306. *pChan->imra |= MFP_A_RX_FULL; /* unmask recv ints */
  307. *pChan->imra |= MFP_A_RX_ERR; /* unmask recv error ints */
  308. }
  309.     else
  310. {
  311. *pChan->iera &= ~MFP_A_RX_FULL;  /* disable recv int. */
  312. *pChan->iera &= ~MFP_A_RX_ERR;   /* disable recv error int. */
  313. *pChan->iera &= ~MFP_A_TX_EMPTY; /* disable transmit int. */
  314. *pChan->imra &= ~MFP_A_RX_FULL; /* mask recv ints */
  315. *pChan->imra &= ~MFP_A_RX_ERR; /* mask recv error ints */
  316. *pChan->imra &= ~MFP_A_TX_EMPTY;/* mask recv ints */
  317. }
  318.     
  319.     intUnlock(oldlevel);
  320.     return (OK);
  321.     }