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

VxWorks

开发平台:

C/C++

  1. /* m68360Sio.c - Motorola MC68360 SCC UART serial driver */
  2. /* Copyright 1984-2002 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01g,24apr02,pmr  SPR 75161: returning int from m68360Startup() as required.
  8. 01f,28may96,dat  fixed SPR #5526, baud rate divisor calculation
  9. 01e,10oct95,ms   made poll input routine work if len(RX FIFO)>1 (SPR #5130).
  10. 01d,08sep95,myz  fixed the SPR #4678
  11. 01c,20jun95,ms   fixed comments for mangen
  12. 01b,15jun95,ms   updated for new driver structure
  13. 01a,22may95,myz  written (using m68360Serial.c).
  14. */
  15. /*
  16. DESCRIPTION
  17. This is the driver for the SCC's in the internal Communications Processor (CP)
  18. of the Motorola MC68360.  This driver only supports the SCC's in asynchronous
  19. UART mode.
  20. USAGE
  21. A m68360_CHAN structure is used to describe the chip.
  22. The BSP's sysHwInit() routine typically calls sysSerialHwInit()
  23. which initializes all the values in the M68360_CHAN structure (except
  24. the SIO_DRV_FUNCS) before calling m68360DevInit().
  25. The BSP's sysHwInit2() routine typically calls sysSerialHwInit2() which
  26. connects the chips interrupt (m68360Int) via intConnect().
  27. INCLUDE FILES: drv/sio/m68360Sio.h
  28. */
  29. /* includes */
  30. #include "vxWorks.h"
  31. #include "intLib.h"
  32. #include "errno.h"
  33. #include "sioLib.h"
  34. #include "drv/sio/m68360Sio.h"
  35. /* defines */
  36. #define DEFAULT_BAUD 9600
  37. /* forward declarations */
  38. static STATUS m68360Ioctl (M68360_CHAN *pChan,int request,int arg);
  39. static void   m68360ResetChannel (M68360_CHAN *pChan);
  40. static int    m68360PollOutput (SIO_CHAN *,char);
  41. static int    m68360PollInput (SIO_CHAN *,char *);
  42. static int    m68360Startup (M68360_CHAN *);
  43. static int    m68360CallbackInstall (SIO_CHAN *, int, STATUS (*)(), void *);
  44. /* local driver function table */
  45. static SIO_DRV_FUNCS m68360SioDrvFuncs =
  46.     {
  47.     (int (*)())m68360Ioctl,
  48.     (int (*)())m68360Startup,
  49.     (int (*)())m68360CallbackInstall,
  50.     (int (*)())m68360PollInput,
  51.     (int (*)(SIO_CHAN *,char))m68360PollOutput
  52.     };
  53. /*******************************************************************************
  54. *
  55. * m68360DevInit - initialize the SCC
  56. *
  57. * This routine is called to initialize the chip to a quiescent state.
  58. */
  59. void m68360DevInit
  60.     (
  61.     M68360_CHAN *pChan
  62.     )
  63.     {
  64.     /* masks off this SCC's interrupt. */
  65.     *M360_CPM_CIMR(pChan->regBase) &=
  66.          (~(CPIC_CIXR_SCC4 << (3 - (pChan->uart.sccNum - 1) )));
  67.     pChan->baudRate = DEFAULT_BAUD;
  68.     pChan->pDrvFuncs = &m68360SioDrvFuncs;
  69.     }
  70. /*******************************************************************************
  71. *
  72. * m68360ResetChannel - initialize the SCC
  73. */
  74. static void m68360ResetChannel 
  75.     (
  76.     M68360_CHAN *pChan
  77.     )
  78.     {
  79.     int scc; /* the SCC number being initialized */
  80.     int baud; /* the baud rate generator being used */
  81.     int frame;
  82.     int oldlevel = intLock (); /* LOCK INTERRUPTS */
  83.  
  84.     scc = pChan->uart.sccNum - 1; /* get SCC number */
  85.     baud = pChan->bgrNum - 1; /* get BRG number */
  86.     pChan->uart.intMask = CPIC_CIXR_SCC4 << (3 - scc);
  87.     /* set up SCC as NMSI */
  88.  
  89.     *M360_CPM_SICR(pChan->regBase) |= (UINT32) (baud << (scc << 3));
  90.     *M360_CPM_SICR(pChan->regBase) |= (UINT32) ((baud << 3) << (scc << 3));
  91.  
  92.     /* reset baud rate generator */
  93.  
  94.     *pChan->pBaud |= BRG_CR_RST;
  95.     while (*pChan->pBaud & BRG_CR_RST);
  96.     m68360Ioctl (pChan, SIO_BAUD_SET, pChan->baudRate);
  97.     /* set up transmit buffer descriptors */
  98.     pChan->uart.txBdBase = (SCC_BUF *) (pChan->regBase +
  99.  ((UINT32) pChan->uart.txBdBase & 0xfff));
  100.     pChan->uart.pScc->param.tbase = (UINT16) ((UINT32) pChan->uart.txBdBase &
  101. 0xfff);
  102.     pChan->uart.pScc->param.tbptr = (UINT16) ((UINT32) pChan->uart.txBdBase &
  103. 0xfff);
  104.     pChan->uart.txBdNext = 0;
  105.     /* initialize each transmit buffer descriptor */
  106.     for (frame = 0; frame < pChan->uart.txBdNum; frame++)
  107.         {
  108.         pChan->uart.txBdBase[frame].statusMode = SCC_UART_TX_BD_INT;
  109.         pChan->uart.txBdBase[frame].dataPointer = pChan->uart.txBufBase +
  110.                                                 (frame * pChan->uart.txBufSize);
  111.         }
  112.     /* set the last BD to wrap to the first */
  113.     pChan->uart.txBdBase[(frame - 1)].statusMode |= SCC_UART_TX_BD_WRAP;
  114.     /* set up receive buffer descriptors */
  115.     pChan->uart.rxBdBase = (SCC_BUF *) (pChan->regBase +
  116.          ((UINT32) pChan->uart.rxBdBase & 0xfff));
  117.     pChan->uart.pScc->param.rbase = (UINT16) ((UINT32) pChan->uart.rxBdBase &
  118. 0xfff);
  119.     pChan->uart.pScc->param.rbptr = (UINT16) ((UINT32) pChan->uart.rxBdBase &
  120. 0xfff);
  121.     pChan->uart.rxBdNext = 0;
  122.     /* initialize each receive buffer descriptor */
  123.     for (frame = 0; frame < pChan->uart.rxBdNum; frame++)
  124.         {
  125.         pChan->uart.rxBdBase[frame].statusMode = SCC_UART_RX_BD_EMPTY |
  126.                                                SCC_UART_RX_BD_INT;
  127.         pChan->uart.rxBdBase[frame].dataLength = 1; /* char oriented */
  128.         pChan->uart.rxBdBase[frame].dataPointer = pChan->uart.rxBufBase + frame;
  129.         }
  130.     /* set the last BD to wrap to the first */
  131.     pChan->uart.rxBdBase[(frame - 1)].statusMode |= SCC_UART_TX_BD_WRAP;
  132.     /* set SCC attributes to UART mode */
  133.     pChan->uart.pSccReg->gsmrl = SCC_GSMRL_RDCR_X16 | SCC_GSMRL_TDCR_X16 |
  134.    SCC_GSMRL_UART;
  135.     pChan->uart.pSccReg->gsmrh = SCC_GSMRH_RFW      | SCC_GSMRH_TFL;
  136.     pChan->uart.pSccReg->psmr  = SCC_UART_PSMR_FLC  | SCC_UART_PSMR_CL_8BIT;
  137.     pChan->uart.pSccReg->dsr  = 0x7e7e; /* no fractional stop bits */
  138.     pChan->uart.pScc->param.rfcr  = 0x18; /* supervisor data access */
  139.     pChan->uart.pScc->param.tfcr  = 0x18; /* supervisor data access */
  140.     pChan->uart.pScc->param.mrblr = 0x1; /* one character rx buffers */
  141.     /* initialize parameter the SCC RAM */
  142.     ((SCC_UART_PROTO *)pChan->uart.pScc->prot)->maxIdl      = 0x0;
  143.     ((SCC_UART_PROTO *)pChan->uart.pScc->prot)->brkcr       = 0x1;
  144.     ((SCC_UART_PROTO *)pChan->uart.pScc->prot)->parec       = 0x0;
  145.     ((SCC_UART_PROTO *)pChan->uart.pScc->prot)->frmer       = 0x0;
  146.     ((SCC_UART_PROTO *)pChan->uart.pScc->prot)->nosec       = 0x0;
  147.     ((SCC_UART_PROTO *)pChan->uart.pScc->prot)->brkec       = 0x0;
  148.     ((SCC_UART_PROTO *)pChan->uart.pScc->prot)->uaddr1      = 0x0;
  149.     ((SCC_UART_PROTO *)pChan->uart.pScc->prot)->uaddr2      = 0x0;
  150.     ((SCC_UART_PROTO *)pChan->uart.pScc->prot)->toseq       = 0x0;
  151.     ((SCC_UART_PROTO *)pChan->uart.pScc->prot)->character1  = 0x8000;
  152.     ((SCC_UART_PROTO *)pChan->uart.pScc->prot)->character2  = 0x8000;
  153.     ((SCC_UART_PROTO *)pChan->uart.pScc->prot)->character3  = 0x8000;
  154.     ((SCC_UART_PROTO *)pChan->uart.pScc->prot)->character4  = 0x8000;
  155.     ((SCC_UART_PROTO *)pChan->uart.pScc->prot)->character5  = 0x8000;
  156.     ((SCC_UART_PROTO *)pChan->uart.pScc->prot)->character6  = 0x8000;
  157.     ((SCC_UART_PROTO *)pChan->uart.pScc->prot)->character7  = 0x8000;
  158.     ((SCC_UART_PROTO *)pChan->uart.pScc->prot)->character8  = 0x8000;
  159.     ((SCC_UART_PROTO *)pChan->uart.pScc->prot)->rccm        = 0x8000;
  160.     pChan->uart.pSccReg->scce = 0xffff; /* clr events */
  161.     /* enables the transmitter and receiver  */
  162.     pChan->uart.pSccReg->gsmrl |= SCC_GSMRL_ENR | SCC_GSMRL_ENT;
  163.     /* unmask interrupt */
  164.     pChan->uart.pSccReg->sccm = SCC_UART_SCCX_RX | SCC_UART_SCCX_TX;
  165.     *M360_CPM_CIMR(pChan->regBase) |= pChan->uart.intMask;
  166.     intUnlock (oldlevel); /* UNLOCK INTERRUPTS */
  167.     }
  168. /*******************************************************************************
  169. *
  170. * m68360Ioctl - special device control
  171. *
  172. * RETURNS: OK on success, EIO on device error, ENOSYS on unsupported
  173. *          request.
  174. *
  175. */
  176. LOCAL STATUS m68360Ioctl
  177.     (
  178.     M68360_CHAN *pChan, /* device to control */
  179.     int request, /* request code */
  180.     int arg /* some argument */
  181.     )
  182.     {
  183.     int baudRate;
  184.     int oldlevel;
  185.     STATUS status = OK;
  186.     switch (request)
  187. {
  188. case SIO_BAUD_SET:
  189.             if (arg >=  50 && arg <= 38400) /* could go higher... */
  190. {
  191. /* calculate proper counter value, then enable BRG */
  192.                 baudRate = (pChan->clockRate / (16 * arg)) - 1;
  193. if (baudRate > 0xfff)
  194.                     *pChan->pBaud = (BRG_CR_CD & ((baudRate / 16) << 1)) |
  195.        BRG_CR_EN | BRG_CR_DIV16;
  196.                 else
  197.                     *pChan->pBaud = (BRG_CR_CD & (baudRate << 1)) |
  198.        BRG_CR_EN;
  199.                 pChan->baudRate = arg;
  200. }
  201.             else
  202.         status = EIO;
  203.     break;
  204.     
  205. case SIO_BAUD_GET:
  206.     *(int *)arg = pChan->baudRate;
  207.     break;
  208. case SIO_MODE_SET:
  209.             if (!((int)arg == SIO_MODE_POLL || (int)arg == SIO_MODE_INT))
  210.                 {
  211.                 status = EIO;
  212.                 break;
  213.                 }
  214.             /* lock interrupt  */
  215.             oldlevel = intLock();
  216.             /* initialize channel on first MODE_SET */
  217.             if (!pChan->channelMode)
  218.                 m68360ResetChannel(pChan);
  219.             /*
  220.              * if switching from POLL to INT mode, wait for all characters to
  221.              * clear the output pins
  222.              */
  223.             if ((pChan->channelMode == SIO_MODE_POLL) && (arg == SIO_MODE_INT))
  224.                 {
  225. int i;
  226.                 for (i=0; i < pChan->uart.txBdNum; i++)
  227.                     while (pChan->uart.txBdBase
  228.                            [(pChan->uart.txBdNext + i) % pChan->uart.txBdNum].
  229.                            statusMode & SCC_UART_TX_BD_READY);
  230.                 }
  231.             if (arg == SIO_MODE_INT)
  232. {
  233.                 *M360_CPM_CISR(pChan->regBase) = pChan->uart.intMask
  234.                     ;   /* reset the SCC's interrupt status bit */
  235. *M360_CPM_CIMR(pChan->regBase) |= pChan->uart.intMask
  236.                     ;   /* enable this SCC's interrupt  */
  237. pChan->uart.pSccReg->scce = SCC_UART_SCCX_RX
  238.                     ;   /* reset the receiver status bit */ 
  239.                 pChan->uart.pSccReg->sccm = SCC_UART_SCCX_RX | SCC_UART_SCCX_TX
  240.                     ;   /* enables the receive and transmit interrupts */
  241. }
  242.             else
  243. {
  244.                 pChan->uart.pSccReg->sccm = 0
  245.                     ;   /* mask off the receive and transmit interrupts */
  246. *M360_CPM_CIMR(pChan->regBase) &= (~(pChan->uart.intMask));
  247.                     ;   /* mask off this SCC's interrupt */ 
  248.                 }
  249.             pChan->channelMode = arg;
  250.             intUnlock(oldlevel);
  251.             break;
  252.         case SIO_MODE_GET:
  253.             *(int *)arg = pChan->channelMode;
  254.             return (OK);
  255.         case SIO_AVAIL_MODES_GET:
  256.             *(int *)arg = SIO_MODE_INT | SIO_MODE_POLL;
  257.             return (OK);
  258. default:
  259.     status = ENOSYS;
  260. }
  261.     return (status);
  262.     }
  263. /*******************************************************************************
  264. *
  265. * m68360Int - handle an SCC interrupt
  266. *
  267. * This routine gets called to handle SCC interrupts.
  268. */
  269. void m68360Int
  270.     (
  271.     M68360_CHAN *pChan
  272.     )
  273.     {
  274.     char outChar;
  275.     FAST UINT16 dataLen = 0;
  276.     /* check for a receive event */
  277.     if (pChan->uart.pSccReg->scce & SCC_UART_SCCX_RX)
  278. {
  279.         pChan->uart.pSccReg->scce = SCC_UART_SCCX_RX;
  280. while (!(pChan->uart.rxBdBase[pChan->uart.rxBdNext].statusMode &
  281.  SCC_UART_RX_BD_EMPTY))
  282.     {
  283.     /* process all filled receive buffers */
  284.     outChar = pChan->uart.rxBdBase[pChan->uart.rxBdNext].dataPointer[0];
  285.             pChan->uart.rxBdBase[pChan->uart.rxBdNext].statusMode |=
  286.                 SCC_UART_RX_BD_EMPTY;
  287.             /* incr BD count */
  288.             pChan->uart.rxBdNext = (pChan->uart.rxBdNext + 1) %
  289.                                   pChan->uart.rxBdNum;
  290.             /* acknowledge interrupt */
  291.             pChan->uart.pSccReg->scce = SCC_UART_SCCX_RX;
  292.     (*pChan->putRcvChar) (pChan->putRcvArg,outChar);
  293.     if (pChan->channelMode == SIO_MODE_POLL)
  294. break;
  295.     }
  296. }
  297.     /* check for a transmit event and if a character needs to be output */
  298.     if ( (pChan->uart.pSccReg->scce & SCC_UART_SCCX_TX) &&
  299.          (pChan->channelMode != SIO_MODE_POLL) )
  300. {
  301.         pChan->uart.pSccReg->scce = SCC_UART_SCCX_TX;
  302.     
  303.         if ((*pChan->getTxChar) (pChan->getTxArg, &outChar) == OK)
  304.     {
  305.     do
  306.         {
  307.         pChan->uart.txBdBase[pChan->uart.txBdNext].dataPointer[dataLen++]
  308.     = outChar;
  309.                 if (pChan->channelMode == SIO_MODE_POLL)
  310.                     break;
  311.         }
  312.     while ((dataLen < pChan->uart.txBufSize) &&
  313.                    ((*pChan->getTxChar) (pChan->getTxArg, &outChar)
  314.        == OK));
  315.     pChan->uart.txBdBase[pChan->uart.txBdNext].dataLength  = dataLen;
  316.             /* acknowledge interrupt */
  317.             pChan->uart.pSccReg->scce = SCC_UART_SCCX_TX;
  318.     /* send transmit buffer */
  319.     pChan->uart.txBdBase[pChan->uart.txBdNext].statusMode |=
  320.         SCC_UART_TX_BD_READY;
  321.     /* incr BD count */
  322.       pChan->uart.txBdNext = (pChan->uart.txBdNext+ 1) % pChan->uart.txBdNum;
  323.     }
  324. }
  325.     /* acknowledge all other interrupts - ignore events */
  326.     pChan->uart.pSccReg->scce = (pChan->uart.pSccReg->scce & ~(SCC_UART_SCCX_RX |
  327.                                SCC_UART_SCCX_TX));
  328.     *M360_CPM_CISR(pChan->regBase) = pChan->uart.intMask;
  329.     }
  330. /*******************************************************************************
  331. *
  332. * m68360Startup - transmitter startup routine
  333. */
  334. static int m68360Startup
  335.     (
  336.     M68360_CHAN *pChan /* ty device to start up */
  337.     )
  338.     {
  339.     char outChar;
  340.     FAST UINT16 dataLen = 0;
  341.     if (pChan->channelMode == SIO_MODE_POLL)
  342. return (ENOSYS);
  343.     /* check if buffer is ready and if a character needs to be output */
  344.     if ((!(pChan->uart.txBdBase[pChan->uart.txBdNext].statusMode &
  345.    SCC_UART_TX_BD_READY)) &&
  346.         ((*pChan->getTxChar) (pChan->getTxArg, &outChar) == OK))
  347. {
  348. do
  349.     {
  350.     pChan->uart.txBdBase[pChan->uart.txBdNext].dataPointer[dataLen++] =
  351. outChar;
  352.     }
  353. while ((dataLen < pChan->uart.txBufSize) &&
  354.                ((*pChan->getTxChar) (pChan->getTxArg, &outChar)
  355.                == OK)); /* fill buffer */
  356. /* send transmit buffer */
  357. pChan->uart.txBdBase[pChan->uart.txBdNext].dataLength  = dataLen;
  358. pChan->uart.txBdBase[pChan->uart.txBdNext].statusMode |=
  359.     SCC_UART_TX_BD_READY;
  360. /* incr BD count */
  361.         pChan->uart.txBdNext = (pChan->uart.txBdNext + 1) % pChan->uart.txBdNum;
  362. }
  363.     return (OK);
  364.     }
  365. /******************************************************************************
  366. *
  367. * m68360PollInput - poll the device for input.
  368. *
  369. * RETURNS: OK if a character arrived, ERROR on device error, EAGAIN
  370. *          if the input buffer is empty.
  371. */
  372. static int m68360PollInput
  373.     (
  374.     SIO_CHAN *   pSioChan,
  375.     char *      thisChar
  376.     )
  377.     {
  378.     M68360_CHAN * pChan = (M68360_CHAN *)pSioChan;
  379.     if ( !(pChan->uart.pSccReg->scce & SCC_UART_SCCX_RX) )
  380.         return (EAGAIN); 
  381.     if (pChan->uart.rxBdBase[pChan->uart.rxBdNext].statusMode &
  382.  SCC_UART_RX_BD_EMPTY)
  383.         return (EAGAIN);
  384.     /* get a character */
  385.     *thisChar = pChan->uart.rxBdBase[pChan->uart.rxBdNext].dataPointer[0];
  386.     /* set the empty bit */
  387.     pChan->uart.rxBdBase[pChan->uart.rxBdNext].statusMode |=
  388.                 SCC_UART_RX_BD_EMPTY;
  389.     /* incr BD count */
  390.     pChan->uart.rxBdNext = (pChan->uart.rxBdNext + 1) %
  391.                                   pChan->uart.rxBdNum;
  392.     /* only clear RX event if no more characters are ready */
  393.     if (pChan->uart.rxBdBase[pChan->uart.rxBdNext].statusMode &
  394.          SCC_UART_RX_BD_EMPTY)
  395.         pChan->uart.pSccReg->scce = SCC_UART_SCCX_RX;
  396.     return (OK);
  397.     }
  398. /******************************************************************************
  399. *
  400. * m68360PollOutput - output a character in polled mode.
  401. *
  402. * RETURNS: OK if a character arrived, ERROR on device error, EAGAIN
  403. *          if the output buffer if full.
  404. */
  405. static int m68360PollOutput
  406.     (
  407.     SIO_CHAN *   pSioChan,
  408.     char        outChar
  409.     )
  410.     {
  411.     M68360_CHAN * pChan = (M68360_CHAN *)pSioChan;
  412.     /* is the transmitter ready to accept a character? */
  413.     if (pChan->uart.txBdBase[pChan->uart.txBdNext].statusMode &
  414. SCC_UART_TX_BD_READY)
  415. return(EAGAIN);
  416.     /* reset the transmitter status bit */
  417.     pChan->uart.pSccReg->scce = SCC_UART_SCCX_TX;
  418.     /* write out the character */
  419.     pChan->uart.txBdBase[pChan->uart.txBdNext].dataPointer[0] = outChar;
  420.     pChan->uart.txBdBase[pChan->uart.txBdNext].dataLength  = 1;
  421.     /* send transmit buffer */
  422.     pChan->uart.txBdBase[pChan->uart.txBdNext].statusMode |=
  423. SCC_UART_TX_BD_READY;
  424.     pChan->uart.txBdNext = (pChan->uart.txBdNext + 1) % pChan->uart.txBdNum;
  425.     return (OK);
  426.     }
  427. /******************************************************************************
  428. *
  429. * m68360CallbackInstall - install ISR callbacks to get put chars.
  430. */
  431. static int m68360CallbackInstall
  432.     (
  433.     SIO_CHAN *  pSioChan,
  434.     int         callbackType,
  435.     STATUS      (*callback)(),
  436.     void *      callbackArg
  437.     )
  438.     {
  439.     M68360_CHAN * pChan = (M68360_CHAN *)pSioChan;
  440.     switch (callbackType)
  441.         {
  442.         case SIO_CALLBACK_GET_TX_CHAR:
  443.             pChan->getTxChar    = callback;
  444.             pChan->getTxArg     = callbackArg;
  445.             return (OK);
  446.         case SIO_CALLBACK_PUT_RCV_CHAR:
  447.             pChan->putRcvChar   = callback;
  448.             pChan->putRcvArg    = callbackArg;
  449.             return (OK);
  450.         default:
  451.             return (ENOSYS);
  452.         }
  453.     }