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

VxWorks

开发平台:

C/C++

  1. /* m68562Sio.c - MC68562 DUSCC serial driver */
  2. /* Copyright 1984-1995 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01g,14nov95,myz   rework last fix
  8. 01f,14nov95,myz   undo last fix and fixed SPR #5437
  9. 01e,08sep95,myz   fixed the SPR #4678
  10. 01d,03aug95,myz   fixed the warning messages
  11. 01c,20jun95,ms    fixed comments for mangen
  12. 01b,15jun95,ms    updated for new driver structure
  13. 01a,14apr95,myz   written (using m68562Serial.c + the VxMon polled driver).
  14. */
  15. /*
  16. DESCRIPTION
  17. This is the driver for the MC68562 DUSCC serial chip.
  18. It uses the DUSCC in asynchronous mode only.
  19. USAGE
  20. A M68562_QUSART structure is used to describe the chip. This data structure
  21. contains M68562_CHAN structures which describe the chip's serial channels.
  22. The BSP's sysHwInit() routine typically calls sysSerialHwInit()
  23. which initializes all the values in the M68562_QUSART structure (except
  24. the SIO_DRV_FUNCS) before calling m68562HrdInit().
  25. The BSP's sysHwInit2() routine typically calls sysSerialHwInit2() which
  26. connects the chips interrupts (m68562RxTxErrInt, m68562RxInt, and
  27. m68562TxInt) via intConnect().
  28. IOCTL
  29. This driver responds to the same ioctl() codes as a normal serial driver.
  30. See the file sioLib.h for more information.
  31. INCLUDE FILES: drv/sio/m68562Sio.h
  32. */
  33. #include "vxWorks.h"
  34. #include "iv.h"
  35. #include "intLib.h"
  36. #include "errnoLib.h"
  37. #include "drv/sio/m68562Sio.h"
  38. #define BIT(val,bit)    ((val & bit) == bit)
  39. /* forward declarations */
  40. static int m68562Startup (M68562_CHAN *pChan);
  41. static int m68562Ioctl (M68562_CHAN *pChan,int request,int arg);
  42. static void m68562ResetChannel (M68562_CHAN *pChan);
  43. static int m68562PTxChar (M68562_CHAN *pChan,char ch);
  44. static int m68562PRxChar (M68562_CHAN *pChan,char *ch);
  45. static int m68562CallbackInstall (SIO_CHAN *, int, STATUS (*)(), void *);
  46. typedef struct        /* BAUD */
  47.     {
  48.     int rate;        /* a baud rate */
  49.     char xmtVal;       /* rate to write to the Transmitter Timing Register */
  50.     char rcvVal;       /* rate to write to the Reciever Timing Register */
  51.     }      BAUD;
  52. /* 
  53.  * baudTable is a table of the available baud rates, and the values to 
  54.  * write to the csr reg to get those rates 
  55.  */
  56. static BAUD baudTable [] =
  57.         {
  58.         {50,
  59. DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_50,
  60. DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_50 },
  61.         {75,
  62. DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_75,
  63. DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_75 },
  64.         {110,
  65. DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_110,
  66. DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_110},
  67.         {134,
  68. DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_134_5,
  69. DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_134_5},
  70.         {150,
  71. DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_150,
  72. DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_150},
  73.         {200,
  74. DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_200,
  75. DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_200},
  76.         {300,
  77. DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_300,
  78. DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_300},
  79.         {600,
  80. DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_600,
  81. DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_600},
  82.         {1050,
  83. DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_1050,
  84. DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_1050},
  85.         {1200,
  86. DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_1200,
  87. DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_1200},
  88.         {2000,
  89. DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_2000,
  90. DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_2000},
  91.         {2400,
  92. DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_2400,
  93. DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_2400},
  94.         {4800,
  95. DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_4800,
  96. DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_4800},
  97.         {9600,
  98. DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_9600,
  99. DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_9600},
  100.         {19200,
  101. DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_19200,
  102. DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_19200},
  103.         {38400,
  104. DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_38400,
  105. DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_38400} };
  106. /* local driver function table */
  107. static SIO_DRV_FUNCS m68562SioDrvFuncs =
  108.     {
  109.     (int (*)())m68562Ioctl,
  110.     (int (*)())m68562Startup,
  111.     m68562CallbackInstall,
  112.     (int (*)())m68562PRxChar,
  113.     (int (*)(SIO_CHAN *,char))m68562PTxChar
  114.     };
  115. /*******************************************************************************
  116. *
  117. * m68562HrdInit - initialize the DUSCC
  118. *
  119. * The BSP must have already initialized all the device addresses, etc in
  120. * M68562_DUSART structure. This routine resets the chip in a quiescent state.
  121. */
  122. void m68562HrdInit
  123.     (
  124.     M68562_QUSART *pQusart
  125.     )
  126.     {
  127.     register int ix;
  128.     int lock = intLock ();      /* LOCK INTERRUPTS */
  129.     for (ix = 0; ix < pQusart->numChannels; ix ++)
  130.         pQusart->channel[ix].pDrvFuncs      = &m68562SioDrvFuncs;
  131.     /* initialize general registers of the device */
  132.     *(pQusart->gsr)  = (char) 0xff;
  133.     *(pQusart->ivr)  = pQusart->int_vec;   /* initialize vector register */
  134.     /* enable a, enable b, modify vec w/stat, present vec to cpu */
  135.     *(pQusart->icr)  = DUSCC_ICR_CHAN_B_MAST_INT_EN |
  136.                        DUSCC_ICR_CHAN_A_MAST_INT_EN |
  137.                        DUSCC_ICR_VECT_INCLDS_STATUS | DUSCC_ICR_VECT_MODE_VECT;
  138.     for (ix = 0; ix < pQusart->numChannels; ix ++)
  139.         {
  140. /* execute reset commands */
  141. *(pQusart->channel[ix].ccr) = DUSCC_CCR_TX_RESET_TX;
  142. *(pQusart->channel[ix].ccr) = DUSCC_CCR_RX_RESET_RX;
  143. *(pQusart->channel[ix].ccr) = (unsigned char)DUSCC_CCR_CT_STOP;
  144. *(pQusart->channel[ix].ccr) = (unsigned char)DUSCC_CCR_DPLL_DISABLE_DPLL
  145. /* initialize registers */
  146. *(pQusart->channel[ix].cmr1) = (char) 0x0;
  147. *(pQusart->channel[ix].cmr2) = (char) 0x0;
  148. *(pQusart->channel[ix].tpr)  = (char) 0x0;
  149. *(pQusart->channel[ix].rpr)  = (char) 0x0;
  150. *(pQusart->channel[ix].omr)  = (char) 0x0;
  151. *(pQusart->channel[ix].pcr)  = (char) 0x0;
  152. *(pQusart->channel[ix].rsr)  = (char) 0xff;
  153. *(pQusart->channel[ix].trsr) = (char) 0xff;
  154. *(pQusart->channel[ix].ictsr) = DUSCC_ICTSR_CT_ZERO_COUNT;
  155. *(pQusart->channel[ix].ier)  = (char) 0x0;
  156.         m68562ResetChannel(&(pQusart->channel[ix]));
  157.         }
  158.     intUnlock (lock); /* UNLOCK INTERRUPTS */
  159.     }
  160. /*******************************************************************************
  161. *
  162. * m68562ResetChannel - reset a single channel
  163. */
  164. static void m68562ResetChannel
  165.     (
  166.     M68562_CHAN *pChan
  167.     )
  168.     {
  169.     /* 8 data bits, 1 stop bit, no parity, set for 9600 baud */
  170.     /*
  171.      * DUSCC Initialization Procedures (from Dec 1987 Signetics app note)
  172.      *
  173.      * "Note that whenever a change is made in the channel mode registers,
  174.      *  the transmitter and receiver should first be disabled.  Also, before
  175.      *  any change is made in the transmit parameter register (TPR) or the
  176.      *  transmit timing register (TTR), the transmitter should be disabled.
  177.      *  After a change(s) has been completed, the trasmitter should be reset; 
  178.      *  then enabled.
  179.      *
  180.      * "If changes are made in either the receive parameter register (RPR)
  181.      *  or the receive timing register (RTR), the receiver should be disabled.
  182.      *  After a changes(s) has been completed, the the receiver should be
  183.      *  reset; then enabled."
  184.      */
  185.     /* disable transmitter and receiver */
  186.     *pChan->ccr = DUSCC_CCR_TX_DISABLE_TX;
  187.     *pChan->ccr = DUSCC_CCR_RX_DISABLE_RX;
  188.     /* configure transmitter and receiver */
  189.     *pChan->cmr1 = DUSCC_CMR1_ASYNC;
  190.     *pChan->cmr2 = DUSCC_CMR2_DTI_POLL_OR_INT;
  191.     *pChan->tpr  = DUSCC_TPR_ASYNC_1 | DUSCC_TPR_8BITS;
  192.     *pChan->ttr  = DUSCC_TTR_CLK_BRG | DUSCC_TTR_BAUD_9600;
  193.     *pChan->rtr  = DUSCC_RTR_CLK_BRG | DUSCC_RTR_BAUD_9600;
  194.     *pChan->rpr  = DUSCC_RPR_8BITS;
  195.     *pChan->omr |= DUSCC_OMR_TXRDY_FIFO_EMPTY |
  196.                     DUSCC_OMR_TX_RES_CHAR_LENGTH_TPR;
  197.     /* reset transmitter and receiver */
  198.     *pChan->ccr = DUSCC_CCR_TX_RESET_TX;
  199.     *pChan->ccr = DUSCC_CCR_RX_RESET_RX;
  200.     /* enable transmitter and receiver */
  201.     *pChan->ccr = DUSCC_CCR_TX_ENABLE_TX;
  202.     *pChan->ccr = DUSCC_CCR_RX_ENABLE_RX;
  203.     }
  204. /*******************************************************************************
  205. *
  206. * m68562Ioctl - special device control
  207. *
  208. * RETURNS: OK on success, EIO on device error, ENOSYS on unsupported
  209. *          request.
  210. */
  211. static STATUS m68562Ioctl
  212.     (
  213.     M68562_CHAN *pChan, /* device to control */
  214.     int request, /* request code      */
  215.     int arg /* some argument     */
  216.     )
  217.     {
  218.     register int ix;
  219.     STATUS status;
  220.     int oldlevel;
  221.     switch (request)
  222.         {
  223. case SIO_BAUD_SET:
  224.     status = EIO;
  225.     for (ix = 0; ix < NELEMENTS (baudTable); ix ++)
  226. if (baudTable [ix].rate == arg)
  227.     {
  228.     status = OK; /* baud rate is valid */
  229.     /*
  230.      * Only set baud rate if the hardware needs it.
  231.      * Setting the baud rate to 9600 when the baud
  232.      * rate is already 9600, for example, would
  233.      * unnecessarily disable the serial channel and
  234.      * possibly drop characters.
  235.      */
  236.     if ((*pChan->ttr != baudTable [ix].xmtVal) ||
  237. (*pChan->rtr != baudTable [ix].rcvVal))
  238. {
  239.                         oldlevel = intLock();
  240. /* disable transmitter and receiver */
  241. *pChan->ccr = DUSCC_CCR_TX_DISABLE_TX;
  242. *pChan->ccr = DUSCC_CCR_RX_DISABLE_RX;
  243. /* configure transmitter and receiver */
  244. *pChan->ttr = baudTable [ix].xmtVal;
  245. *pChan->rtr = baudTable [ix].rcvVal;
  246. /* reset transmitter and receiver */
  247. *pChan->ccr = DUSCC_CCR_TX_RESET_TX;
  248. *pChan->ccr = DUSCC_CCR_RX_RESET_RX;
  249. /* enable transmitter and receiver */
  250. *pChan->ccr = DUSCC_CCR_TX_ENABLE_TX;
  251. *pChan->ccr = DUSCC_CCR_RX_ENABLE_RX;
  252. intUnlock(oldlevel);
  253. break;
  254. }
  255.     }
  256.     break;
  257.         case SIO_BAUD_GET:
  258.             status = EIO;               /* baud rate out of range */
  259.             /* disable interrupts during chip access */
  260.             oldlevel = intLock ();
  261.             for (ix = 0; ix < NELEMENTS (baudTable); ix ++)
  262.                 if (baudTable [ix].rcvVal == *pChan->rtr)
  263.                     {
  264.                     *(int *)arg = baudTable [ix].rate;
  265.                     status = OK;        /* baud rate is valid */
  266.                     }
  267.             intUnlock (oldlevel);
  268.             break;
  269.         case SIO_MODE_SET:
  270.             if (!((int)arg == SIO_MODE_POLL || (int)arg == SIO_MODE_INT))
  271.                 {
  272.                 status = EIO;
  273.                 break;
  274.                 }
  275.             /* lock interrupt  */
  276.             oldlevel = intLock();
  277.             if (arg == SIO_MODE_INT)
  278.                 *pChan->ier = DUSCC_IER_RXRDY | DUSCC_IER_RSR_5_4; 
  279.             else
  280.                 *pChan->ier = 0;
  281.             pChan->channelMode = arg;
  282.             intUnlock(oldlevel);
  283.             status = OK;
  284.             break;
  285.         case SIO_MODE_GET:
  286.             *(int *)arg = pChan->channelMode;
  287.             return (OK);
  288.         case SIO_AVAIL_MODES_GET:
  289.             *(int *)arg = SIO_MODE_INT | SIO_MODE_POLL;
  290.             return (OK);
  291.             
  292. default:
  293.     status = ENOSYS;
  294.     break;
  295.         }
  296.     return (status);
  297.     }
  298. /*******************************************************************************
  299. *
  300. * m68562RxTxErrInt - handle a receiver/transmitter error interrupt
  301. *
  302. * Only the receive overrun condition is handled.
  303. *
  304. * RETURNS: N/A
  305. */
  306. void m68562RxTxErrInt
  307.     (
  308.     M68562_CHAN *pChan
  309.     )
  310.     {
  311.     if (BIT (*pChan->rsr, DUSCC_RSR_ASYNC_OVERN_ERROR))
  312. *pChan->rsr = DUSCC_RSR_ASYNC_OVERN_ERROR; /* "1" clears bit */
  313.     }
  314. /*******************************************************************************
  315. *
  316. * m68562RxInt - handle a receiver interrupt
  317. *
  318. * RETURNS: N/A
  319. */
  320. void m68562RxInt
  321.     (
  322.     M68562_CHAN *pChan
  323.     )
  324.     {
  325.     /* drain receive FIFO */
  326.     do
  327.         {
  328. (*pChan->putRcvChar) (pChan->putRcvArg, *pChan->rx_data);
  329.         }
  330.     while ( ( (*pChan->pQusart->gsr) &  
  331.    (DUSCC_GSR_A_RXRDY << ((pChan->chan_num)*4) ) ) && 
  332.    pChan->channelMode != SIO_MODE_POLL ); 
  333.     }
  334. /*******************************************************************************
  335. *
  336. * m68562TxInt - handle a transmitter interrupt
  337. *
  338. * If there is another character to be transmitted, it sends it.  If
  339. * not, or if a device has never been created for this channel,
  340. * disable the interrupt.
  341. *
  342. * RETURNS: N/A
  343. */
  344. void m68562TxInt
  345.     (
  346.     M68562_CHAN *pChan
  347.     )
  348.     {
  349.     char outChar;
  350.     do                                          /* fill transmit FIFO */
  351.         {
  352.         if ((*pChan->getTxChar) (pChan->getTxArg, &outChar) == OK)
  353.             *pChan->tx_data = outChar;
  354.         else
  355.             {
  356.             *pChan->ier &= ~DUSCC_IER_TXRDY;  /* turn off transmitter */
  357.             break;
  358.             }
  359.         }
  360.         while ( (*pChan->pQusart->gsr) & 
  361.  (DUSCC_GSR_A_TXRDY << ((pChan->chan_num)*4) ) );
  362.     }
  363. /******************************************************************************
  364. *
  365. * m68562PRxChar - poll the device for input.
  366. *
  367. * RETURNS: OK if a character arrived, ERROR on device error, EAGAIN
  368. *          if the input buffer if empty.
  369. */
  370. static int m68562PRxChar
  371.     (
  372.     M68562_CHAN *pChan,
  373.     char *ch
  374.     )
  375.     {
  376.     /* wait for Data */
  377.     if (! ( (*pChan->pQusart->gsr) &
  378.               (DUSCC_GSR_A_RXRDY << ((pChan->chan_num)*4) ) ) )
  379.         return(EAGAIN);
  380.     *ch = *pChan->rx_data;
  381.     return(OK);
  382.     }
  383. /******************************************************************************
  384. *
  385. * m68562PTxChar - output a character in polled mode.
  386. *
  387. * RETURNS: OK if a character arrived, ERROR on device error, EAGAIN
  388. *          if the output buffer if full.
  389. */
  390. static int m68562PTxChar
  391.     (
  392.     M68562_CHAN *pChan,
  393.     char ch                   /* character to output */
  394.     )
  395.     {
  396.     /* check for Empty */
  397.     if (! ( (*pChan->pQusart->gsr) &
  398.                (DUSCC_GSR_A_TXRDY << ((pChan->chan_num)*4) ) ) ) 
  399.         return(EAGAIN);
  400.     *pChan->tx_data = ch;
  401.     return(OK);
  402.     }
  403. /*******************************************************************************
  404. *
  405. * m68562Startup - transmitter startup routine
  406. *
  407. * Call interrupt level character output routine for DUSCC.
  408. */
  409. static int m68562Startup
  410.     (
  411.     M68562_CHAN * pChan   /* device to start up */ 
  412.     )
  413.     {
  414.     char outChar;
  415.     if ( pChan->channelMode == SIO_MODE_INT )
  416.         {
  417. if ( (*pChan->getTxChar) (pChan->getTxArg, &outChar) == OK)
  418.             *pChan->tx_data  = outChar;
  419.         *pChan->ier |= DUSCC_IER_TXRDY;
  420.         return (OK);
  421.         }
  422.     else
  423.         return (ERROR);
  424.     }
  425. /******************************************************************************
  426. *
  427. * m68562CallbackInstall - install ISR callbacks to get put chars.
  428. */
  429. static int m68562CallbackInstall
  430.     (
  431.     SIO_CHAN *  pSioChan,
  432.     int         callbackType,
  433.     STATUS      (*callback)(),
  434.     void *      callbackArg
  435.     )
  436.     {
  437.     M68562_CHAN * pChan = (M68562_CHAN *)pSioChan;
  438.     switch (callbackType)
  439.         {
  440.         case SIO_CALLBACK_GET_TX_CHAR:
  441.             pChan->getTxChar    = callback;
  442.             pChan->getTxArg     = callbackArg;
  443.             return (OK);
  444.         case SIO_CALLBACK_PUT_RCV_CHAR:
  445.             pChan->putRcvChar   = callback;
  446.             pChan->putRcvArg    = callbackArg;
  447.             return (OK);
  448.         default:
  449.             return (ENOSYS);
  450.         }
  451.     }