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

VxWorks

开发平台:

C/C++

  1. /* ppc403Sio.c - ppc403GA serial driver */
  2. /* Copyright 1984-2001 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01g,18oct01,dat  Documentation fixes
  8. 01f,30aug01,pch  Remove #include "arch/ppc/ppc403.h".  For PPC403, it is
  9.  brought in by vxWorks.h.  ppc403Sio.c is not built for
  10.  other CPU types, but the #include causes warnings during
  11.  dependency generation.
  12. 01e,07aug97,tam  removed clearing of EXIRS[SRI] bit in ppc403IntRd() (SPR 9114)
  13. 01d,06nov96,dgp  doc: final formatting
  14. 01c,28oct96,tam  fixed typo in ppc403DummyCallback to build man pages.
  15. 01b,12jul96,tam  corrected code to avoid getting spurious interrupt when 
  16.  interrupt nesting's enabled.
  17. 01a,13feb96,tam  written (using evb403_diab/tyCoDrv.c version 01a).
  18. */
  19. /*
  20. DESCRIPTION
  21. This is the driver for PPC403GA serial port on the on-chip peripheral bus.
  22. The SPU (serial port unit) consists of three main elements: receiver,
  23. transmitter, and baud-rate generator.  For details, refer to the 
  24. .I PPC403GA Embedded Controller User's Manual.
  25. USAGE
  26. A PPC403_CHAN structure is used to describe the chip. This data structure
  27. contains the single serial channel.
  28. The BSP's sysHwInit() routine typically calls sysSerialHwInit()
  29. which initializes all the values in the PPC403_CHAN structure (except
  30. the SIO_DRV_FUNCS) before calling ppc403DevInit().
  31. The BSP's sysHwInit2() routine typically calls sysSerialHwInit2() which
  32. connects the chip interrupt routines ppc403IntWr() and ppc403IntRd() via 
  33. intConnect().
  34. IOCTL FUNCTIONS
  35. This driver responds to the same ioctl() codes as other SIO drivers; for 
  36. more information, see sioLib.h.
  37. INCLUDE FILES: drv/sio/ppc403Sio.h
  38. */
  39. #include "vxWorks.h"
  40. #include "iv.h"
  41. #include "intLib.h"
  42. #include "errnoLib.h"
  43. #include "vxLib.h"
  44. #include "drv/sio/ppc403Sio.h"
  45. /* forward declarations */
  46. static void ppc403InitChannel (PPC403_CHAN *);
  47. static int ppc403Ioctl(SIO_CHAN *,int,int);
  48. static int ppc403Startup(SIO_CHAN *pSioChan);
  49. static int ppc403CallbackInstall(SIO_CHAN *,int,STATUS (*callback)(),void *);
  50. static int ppc403PRxChar (SIO_CHAN *pSioChan,char *ch);
  51. static int ppc403PTxChar(SIO_CHAN *pSioChan,char ch);
  52. /* driver functions */
  53. static SIO_DRV_FUNCS ppc403SioDrvFuncs =
  54.     {
  55.     (int (*)())ppc403Ioctl,
  56.     (int (*)())ppc403Startup,
  57.     ppc403CallbackInstall,
  58.     (int (*)())ppc403PRxChar,
  59.     (int (*)(SIO_CHAN *,char))ppc403PTxChar
  60.     };
  61. /******************************************************************************
  62. *
  63. * ppc403DummyCallback - dummy callback routine
  64. *
  65. * RETURNS: ERROR (always).
  66. */ 
  67. STATUS ppc403DummyCallback (void)
  68.     {
  69.     return (ERROR);
  70.     }
  71. /******************************************************************************
  72. *
  73. * ppc403CallbackInstall - install callbacks to get/put chars
  74. *
  75. * RETURNS:
  76. * Returns OK, or ENOSYS for an unsupported callback type.
  77. */
  78. static int ppc403CallbackInstall
  79.     (
  80.     SIO_CHAN *  pSioChan,
  81.     int         callbackType,
  82.     STATUS      (*callback)(),
  83.     void *      callbackArg
  84.     )
  85.     {
  86.     PPC403_CHAN * pChan = (PPC403_CHAN *)pSioChan;
  87.     
  88.     switch (callbackType)
  89.         {
  90.         case SIO_CALLBACK_GET_TX_CHAR:
  91.             pChan->getTxChar    = callback;
  92.             pChan->getTxArg     = callbackArg;
  93.             return (OK);
  94.         case SIO_CALLBACK_PUT_RCV_CHAR:
  95.             pChan->putRcvChar   = callback;
  96.             pChan->putRcvArg    = callbackArg;
  97.             return (OK);
  98.         default:
  99.             return (ENOSYS);
  100.         }
  101.     }
  102. /******************************************************************************
  103. *
  104. * ppc403DevInit - initialize the serial port unit
  105. *
  106. * The BSP must already have initialized all the device addresses in the
  107. * PPC403_CHAN structure. This routine initializes some SIO_CHAN
  108. * function pointers and then resets the chip in a quiescent state.
  109. *
  110. * RETURNS: N/A.
  111. */
  112. void ppc403DevInit
  113.     (
  114.     PPC403_CHAN * pChan
  115.     )
  116.     {
  117.     /* initialize the driver function pointers in the SIO_CHAN's */
  118.     pChan->pDrvFuncs    = &ppc403SioDrvFuncs;
  119.     /* set the non BSP-specific constants */
  120.     pChan->baudRate     = DEFAULT_BAUD;
  121.     pChan->getTxChar    = ppc403DummyCallback;
  122.     pChan->putRcvChar   = ppc403DummyCallback;
  123.     pChan->mode         = 0;        /* undefined */
  124.     /* reset the chip */
  125.     ppc403InitChannel(pChan);
  126.     }
  127. /******************************************************************************
  128. *
  129. * ppc403ModeSet - change mode of device
  130. *
  131. * Implements the MODE_SET ioctl.
  132. *
  133. * RETURNS:
  134. * Returns OK, or ERROR for an invalid mode type.
  135. */
  136. static STATUS ppc403ModeSet
  137.     (
  138.     PPC403_CHAN * pChan,
  139.     uint_t      newMode
  140.     )
  141.     {
  142.     int oldlevel;
  143.     int oldExier;
  144.     if ((newMode != SIO_MODE_POLL) && (newMode != SIO_MODE_INT))
  145.         return (ERROR);
  146.     oldlevel = intLock ();
  147.     pChan->mode = newMode;
  148.     if (pChan->mode == SIO_MODE_INT)
  149.         {
  150. /* Program chip in interrupt mode */
  151. oldExier = vxExierDisable (_PPC403_EXI_STI); 
  152. /* disable transmitter interrupt - EXIER level */
  153. *pChan->sptc &= ~ _SPTC_TIE_MASK & ~_SPTC_EIE_MASK & ~_SPTC_DME_TBR;
  154. /* disable transmitter interrupts - SPTC level */
  155. *pChan->sprc |= _SPRC_EIE_MASK | _SPRC_DME_RXRDY;
  156. /* enable Receiver interrupts - SPRC level */
  157. vxExierEnable (_PPC403_EXI_SRI); 
  158. /* enable Receiver interrupt - EXIER level */
  159.         }
  160.     else
  161.         {
  162. /* Program chip in polling mode */
  163. oldExier = vxExierDisable (_PPC403_EXI_SRI); 
  164. /* disable Receiver interrupt - EXIER level   */
  165. oldExier = vxExierDisable (_PPC403_EXI_STI); 
  166. /* disable Transmitter interrupt - EXIER level */
  167. *pChan->sptc &= ~ _SPTC_TIE_MASK & ~_SPTC_EIE_MASK & ~_SPTC_DME_TBR;
  168. /* disable Transmitter interrupts - SPTC level */
  169. *pChan->sprc &= ~_SPRC_EIE_MASK & ~_SPRC_DME_RXRDY;
  170. /* disable Receiver interrupts - SPRC level */
  171. *pChan->sptc  = _SPTC_ET_ENABLE; /* enable transmiter */
  172. *pChan->sprc  = _SPRC_ER_ENABLE; /* enable receiver */
  173.         }
  174.     intUnlock(oldlevel);
  175.     return (OK);
  176.     }
  177. /*******************************************************************************
  178. *
  179. * ppc403InitChannel  - initialize a single channel
  180. *
  181. * RETURNS: N/A.
  182. */
  183. static void ppc403InitChannel
  184.     (
  185.     PPC403_CHAN *pChan
  186.     )
  187.     {
  188.     char inchar;
  189.     int  oldLevel = intLock ();
  190.     /*
  191.      * Receiver Command Register: Receiver enabled & DMA + RBR interrupt +
  192.      * Receiver error interrupt disabled & RTS controlled by software.
  193.      */
  194.     *pChan->sprc  = _SPRC_DME_DISABLE | _SPRC_ER_ENABLE;
  195.     /* 
  196.      * SPU Control Register: Normal Operation & 8 Data Bits & RTS + DTR
  197.      * active & 1 stop bit & no parity.
  198.      */
  199.     *pChan->spctl = _SPCTL_LM_NORM | _SPCTL_DB_8_BITS | _SPCTL_RTS_ACTIVE |
  200.                     _SPCTL_DTR_ACTIVE | _SPCTL_SB_1_BIT;
  201.     /* 
  202.      * Transmitter Command Register: Transmitter enabled & DMA + TBR interrupt
  203.      * + Transmitter Empty interrupt + Transmitter error interrupt disabled & 
  204.      * Stop mode when CTS active enabled & Transmit Break + Pattern Generation
  205.      * mode disabled.
  206.      */
  207.     *pChan->sptc  = _SPTC_DME_DISABLE | _SPTC_SPE_MASK | _SPTC_ET_ENABLE;
  208.     /* read Receive Buffer */
  209.     inchar = *pChan->sprb; /* clear the port */
  210.     *pChan->spls = 0xf8; /* reset bits 0-4 of SPLS */
  211.     vxExisrClear (_PPC403_EXI_SRI);  /* clear Receiver interrupt Status */ 
  212.     /* enable receiver interrupts */
  213.     *pChan->sprc |= _SPRC_DME_RXRDY | _SPRC_EIE_MASK;
  214. /* enable Receiver RBR and error interrupts */
  215.     vxExierEnable (_PPC403_EXI_SRI); /* enable Receiver  interrupt */
  216.     intUnlock (oldLevel);
  217.     }
  218. /*******************************************************************************
  219. *
  220. * ppc403Ioctl - special device control
  221. *
  222. * RETURNS: 
  223. * Returns OK on success, EIO on device error, ENOSYS on unsupported
  224. * request.
  225. */
  226. static int ppc403Ioctl
  227.     (
  228.     SIO_CHAN * pSioChan, /* device to control */
  229.     int request, /* request code */
  230.     int arg /* some argument */
  231.     )
  232.     {
  233.     PPC403_CHAN * pChan = (PPC403_CHAN *) pSioChan;
  234.     int status = OK;
  235.     int baud;
  236.     switch (request)
  237.         {
  238.         case SIO_BAUD_SET:
  239.             if (arg <= 0)
  240.                 status = EIO;
  241.             else
  242.                 {
  243.                 baud = ((pChan->clkFreq / arg) >> 4) - 1;
  244.                 *(char *) _PPC403GA_BRDH = (baud & 0xff00) >> 8;
  245.                 *(char *) _PPC403GA_BRDL = baud & 0x00ff;
  246. pChan->baudRate = arg;
  247. status = OK;
  248.                 }
  249.             break;
  250. case SIO_BAUD_GET:
  251.     *(int *)arg = pChan->baudRate;
  252.     return (OK);
  253. case SIO_MODE_SET:
  254.             if (!(arg == SIO_MODE_POLL || arg == SIO_MODE_INT))
  255.                 {
  256.                 status = EIO;
  257.                 break;
  258.                 }
  259.     status = (ppc403ModeSet (pChan, arg) == OK ? OK : EIO);
  260.     break;
  261. case SIO_MODE_GET:
  262.     *(int *)arg = pChan->mode;
  263.     return (OK);
  264. case SIO_AVAIL_MODES_GET:
  265.     *(int *)arg = SIO_MODE_INT | SIO_MODE_POLL;
  266.     return (OK);
  267.         case SIO_HW_OPTS_SET:
  268.         case SIO_HW_OPTS_GET:
  269.         default:
  270.             status = ENOSYS;
  271.         }
  272.     return (status);
  273.     }
  274. /*******************************************************************************
  275. *
  276. * ppc403IntWr - handle a transmitter interrupt
  277. *
  278. * This routine handles write interrupts from the serial communication 
  279. * controller.
  280. *
  281. * RETURNS: N/A
  282. */
  283. void ppc403IntWr 
  284.     (
  285.     PPC403_CHAN * pChan
  286.     )
  287.     {
  288.     unsigned char dummy;
  289.     unsigned char outchar;
  290.     dummy = *pChan->spls;
  291.     dummy &= _SPLS_RX_ERR;
  292.     if (dummy != 0) /* any error detected */
  293.         {
  294.         *pChan->spls = _SPLS_RX_ERR; /* reset error status bits */
  295.         return;
  296.         }
  297.     dummy = *pChan->sphs;
  298.     if (dummy & (_SPHS_DIS_MASK | _SPHS_CS_MASK))
  299.         {
  300.         *pChan->sphs = _SPHS_DIS_MASK | _SPHS_CS_MASK; 
  301. /* reset DIS & CS bits */
  302.         return;
  303.         }
  304.     /* output character or disable transmitter intr if no more characters*/
  305.     if ((*pChan->getTxChar) (pChan->getTxArg, &outchar) != ERROR)
  306.         *pChan->sptb = outchar;
  307.     else
  308.         *pChan->sptc &= ~ _SPTC_TIE_MASK & ~_SPTC_EIE_MASK & ~_SPTC_DME_TBR;
  309.     }
  310. /*****************************************************************************
  311. *
  312. * ppc403IntRd - handle a receiver interrupt
  313. *
  314. * This routine handles read interrupts from the serial commonication 
  315. * controller.
  316. *
  317. * RETURNS: N/A
  318. */
  319. void ppc403IntRd
  320.     (
  321.     PPC403_CHAN * pChan
  322.     )
  323.     {
  324.     unsigned char dummy;
  325.     unsigned char inchar;
  326.     int status = OK;
  327.     dummy = *pChan->spls;
  328.     dummy &= _SPLS_RX_ERR;
  329.     while (dummy != 0) /* any error detected */
  330.         {
  331. *pChan->spls = _SPLS_RX_ERR; /* reset error status bits */
  332.         status = ERROR;
  333. dummy = *pChan->spls & _SPLS_RX_ERR; 
  334.         }
  335.     inchar = *pChan->sprb; /* read input char */
  336.     *pChan->spls = _SPLS_RBR_MASK;  /* reset Receive buffer ready bit */
  337.     /*
  338.      * NOTE: the receiver interrupt status bit EXIRS[SRI] has already been
  339.      * cleared in the generic interrupt handler sysPpc403IntHandler() 
  340.      * (ppc403Intr.c), so there's no need to do it here.
  341.      */
  342.     if (status == OK)
  343. {
  344.         (*pChan->putRcvChar) (pChan->putRcvArg, inchar);
  345. }
  346.     }
  347. /**********************************************************************
  348. *
  349. * ppc403IntEx - handle error interrupts
  350. *
  351. * This routine handles miscellaneous interrupts on the seial communication
  352. * controller.
  353. *
  354. * RETURNS: N/A
  355. */
  356. void ppc403IntEx
  357.     (
  358.     PPC403_CHAN * pChan
  359.     )
  360.     {
  361.     }
  362. /*******************************************************************************
  363. *
  364. * ppc403Startup - transmitter startup routine
  365. *
  366. * Call interrupt level character output routine.
  367. *
  368. * RETURNS:
  369. * Returns OK, always.
  370. */
  371. static int ppc403Startup
  372.     (
  373.     SIO_CHAN *pSioChan /* device to start up */
  374.     )
  375.     {
  376.     PPC403_CHAN * pChan = (PPC403_CHAN *) pSioChan;
  377.     int lock;
  378.     /* enable the transmitter and it should interrupt to write the next char */
  379.     
  380.     if (((PPC403_CHAN *)pSioChan)->mode != SIO_MODE_POLL)
  381.      {
  382.      lock = intLock ();
  383. /* enable Transmit empty & Transmit error interrupts */
  384.      *pChan->sptc |= _SPTC_TIE_MASK|_SPTC_EIE_MASK;
  385.      vxExierEnable (_PPC403_EXI_STI);     /* enable Transmitter interrupt */
  386.      intUnlock (lock);
  387.      }
  388.     return (OK);
  389.     }
  390. /******************************************************************************
  391. *
  392. * ppc403PRxChar - poll the device for input
  393. *
  394. * RETURNS:
  395. * Returns OK if a character arrived, ERROR on device error, EAGAIN
  396. * if the input buffer if empty.
  397. */
  398. static int ppc403PRxChar
  399.     (
  400.     SIO_CHAN *pSioChan,
  401.     char *ch
  402.     )
  403.     {
  404.     PPC403_CHAN * pChan = (PPC403_CHAN *) pSioChan;
  405.     /* wait for RBR full */
  406.     if (((*pChan->spls) & _SPLS_RBR_MASK) != _SPLS_RBR_FULL) return (EAGAIN);
  407.     *ch = *(pChan->sprb); 
  408.     return(OK);
  409.     }
  410. /******************************************************************************
  411. *
  412. * ppc403PTxChar - output a character in polled mode
  413. *
  414. * RETURNS:
  415. * Returns OK if a character arrived, ERROR on device error, EAGAIN
  416. * if the output buffer if full.
  417. */
  418. static int ppc403PTxChar
  419.     (
  420.     SIO_CHAN *pSioChan,
  421.     char ch                   /* character to output */
  422.     )
  423.     {
  424.     PPC403_CHAN * pChan = (PPC403_CHAN *) pSioChan;
  425.     /* wait for TBR empty */
  426.     if (((*pChan->spls) & _SPLS_TBR_MASK) != _SPLS_TBR_EMPTY) return (EAGAIN);
  427.     *(pChan->sptb) = ch; 
  428.     return(OK);
  429.     }