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

VxWorks

开发平台:

C/C++

  1. /* ixp425Sio.c - IXP425 UART tty driver */
  2. /* Copyright 2002 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01b,06nov02,jb  Fix compile warning
  8. 01a,05jun02,jb  initial version...
  9. */
  10. /*
  11. DESCRIPTION
  12. This is the driver for the Intel IXP425 internal UART. This device comprises an 
  13. asynchronous receiver/transmitter, a baud rate generator, and some modem control 
  14. capability. 
  15. An IXP425_SIO_CHAN structure is used to describe the serial channel. This data 
  16. structure is defined in ixp425Sio.h.
  17. Only asynchronous serial operation is supported by this driver.
  18. The default serial settings are 8 data bits, 1 stop bit, no parity, 9600
  19. baud, and software flow control.  
  20. USAGE
  21. The BSP's sysHwInit() routine typically calls sysSerialHwInit(),
  22. which creates the IXP425_SIO_CHAN structure and initializes all the values in the
  23. structure (except the SIO_DRV_FUNCS) before calling ixp425SioDevInit().
  24. The BSP's sysHwInit2() routine typically calls sysSerialHwInit2(), which
  25. connects the chips interrupts via intConnect() (either the single
  26. interrupt 'ixp425SioInt' or the two interrupts 'ixp425SioIntWr', 'ixp425SioIntRd').
  27. This driver handles setting of hardware options such as parity(odd, even) and
  28. number of data bits(5, 6, 7, 8). Hardware flow control is provided with the
  29. handshakes RTS/CTS.
  30. INCLUDE FILES: ixp425Sio.h
  31. SEE ALSO:
  32. .I "ixp425 Data Sheet,"
  33. */
  34. /* includes */
  35. #include "vxWorks.h"
  36. #include "intLib.h"
  37. #include "errnoLib.h"
  38. #include "errno.h"
  39. #include "sioLib.h"
  40. #include "stdio.h"
  41. #include "ixp425Sio.h"
  42. #define IXP425_SIO_MIN_RATE 9600
  43. #define IXP425_SIO_MAX_RATE 921600
  44. #define IXP425_SIO_DEF_OPTS (CLOCAL | CREAD | CS8)
  45. #define REG(reg, pchan) 
  46.  (*(volatile UINT32 *)((UINT32)pchan->regs + (reg * pchan->regDelta)))
  47. #define REGPTR(reg, pchan) 
  48.  ((volatile UINT32 *)((UINT32)pchan->regs + (reg * pchan->regDelta)))
  49. /* for backward compatibility */
  50. #ifndef SIO_HUP
  51.     #define SIO_OPEN 0x100A /* open channel, raise DTR, RTS */
  52.     #define SIO_HUP 0x100B /* hang-up, lower DTR, RTS */
  53. #endif
  54. /* static forward declarations */
  55. LOCAL  int  ixp425SioCallbackInstall (SIO_CHAN *, int, STATUS (*)(), void *);
  56. LOCAL  STATUS  ixp425SioDummyCallback ();
  57. LOCAL  void  ixp425SioInitChannel (IXP425_SIO_CHAN *);
  58. LOCAL   STATUS  ixp425SioBaudSet (IXP425_SIO_CHAN *, UINT);
  59. LOCAL  STATUS  ixp425SioModeSet (IXP425_SIO_CHAN *, UINT);
  60. LOCAL  STATUS  ixp425SioIoctl (IXP425_SIO_CHAN *, int, int);
  61. LOCAL  void  ixp425SioTxStartup (IXP425_SIO_CHAN *);
  62. LOCAL  int  ixp425SioPollOutput (IXP425_SIO_CHAN *, char);
  63. LOCAL  int  ixp425SioPollInput (IXP425_SIO_CHAN *, char *);
  64. LOCAL  STATUS  ixp425SioOptsSet (IXP425_SIO_CHAN *, UINT);
  65. LOCAL void ixp425SioIntRd (IXP425_SIO_CHAN * pChan);
  66. /* driver functions */
  67. static SIO_DRV_FUNCS ixp425SioDrvFuncs =
  68.     {
  69.     (int (*)())ixp425SioIoctl,
  70.     (int (*)())ixp425SioTxStartup,
  71.     (int (*)())ixp425SioCallbackInstall,
  72.     (int (*)())ixp425SioPollInput,
  73.     (int (*)(SIO_CHAN *,char))ixp425SioPollOutput
  74.     };
  75. /******************************************************************************
  76. *
  77. * ixp425SioDummyCallback - dummy callback routine.
  78. */
  79. LOCAL STATUS ixp425SioDummyCallback (void)
  80.     {
  81.     return (ERROR);
  82.     }
  83. /******************************************************************************
  84. *
  85. * ixp425SioDevInit - initialise a UART channel
  86. *
  87. * This routine initialises some SIO_CHAN function pointers and then resets
  88. * the chip in a quiescent state.  Before this routine is called, the BSP
  89. * must already have initialised all the device addresses, etc. in the
  90. * IXP425_SIO_CHAN structure.
  91. *
  92. * RETURNS: N/A
  93. */
  94. void ixp425SioDevInit
  95.     (
  96.     IXP425_SIO_CHAN * pChan /* pointer to channel */
  97.     )
  98.     {
  99.     int oldlevel = intLock ();
  100.     /* Initialise the driver function pointers in the SIO_CHAN's */
  101.     pChan->pDrvFuncs = &ixp425SioDrvFuncs;
  102. #ifdef IXP425_SIO_DEBUG
  103.     /* Initialise counter statistics */
  104.     pChan->rxCount = 0;
  105.     pChan->txCount = 0;
  106.     pChan->overrunErr = 0;
  107.     pChan->parityErr = 0;
  108.     pChan->framingErr = 0;
  109.     pChan->breakErr = 0;
  110. #endif
  111.     /* Set the non BSP-specific constants */
  112.     pChan->getTxChar    = ixp425SioDummyCallback;
  113.     pChan->putRcvChar   = ixp425SioDummyCallback;
  114.     pChan->options      = IXP425_SIO_DEF_OPTS;
  115.     pChan->mcr = MCR_OUT2;
  116.     /* 
  117.      * Mode 0 is undefined. However the VxWorks ttyDrv will issue
  118.      * an ioctl for mode set to change to interrupt mode when it 
  119.      * needs to use the UART.
  120.      */ 
  121.     pChan->channelMode  = 0;
  122.     /* Enable the device */
  123.     pChan->ier = IER_UUE;
  124.     /* Set hardware opts and baud rate */
  125.     ixp425SioInitChannel (pChan);
  126.     intUnlock (oldlevel);
  127.     }
  128. /*******************************************************************************
  129. *
  130. * ixp425SioInitChannel - initialise UART
  131. *
  132. * Initialise the number of data bits, parity and set the selected
  133. * baud rate. Set the modem control signals if the option is selected.
  134. *
  135. * RETURNS: N/A
  136. */
  137. LOCAL void ixp425SioInitChannel
  138.     (
  139.     IXP425_SIO_CHAN * pChan /* pointer to channel */
  140.     )
  141.     {
  142.     /* set the requested baud rate */
  143.     ixp425SioBaudSet(pChan, pChan->baudRate);
  144.     /* set the options */
  145.     ixp425SioOptsSet(pChan, pChan->options);
  146.     }
  147. /*******************************************************************************
  148. *
  149. * ixp425SioOptsSet - set the serial options
  150. *
  151. * Set the channel operating mode to that specified.  The following sioLib options
  152. * are supported: CLOCAL, CREAD, CSIZE, PARENB, and PARODD.
  153. * The HUPCL option is not supported for now.
  154. *
  155. * Note, this routine disables the transmitter.  The calling routine
  156. * may have to re-enable it.
  157. *
  158. * RETURNS:
  159. * Returns OK to indicate success, otherwise ERROR is returned
  160. */
  161. LOCAL STATUS ixp425SioOptsSet
  162.     (
  163.     IXP425_SIO_CHAN * pChan, /* pointer to channel */
  164.     UINT options /* new hardware options */
  165.     )
  166.     {
  167.     FAST int     oldlevel; /* current interrupt level mask */
  168.     pChan->lcr = 0; 
  169.     pChan->mcr &= (~MCR_RTS); /* clear RTS bit */
  170.     
  171.     if (pChan == NULL || options & 0xffffff00)
  172. return ERROR;
  173.     switch (options & CSIZE)
  174. {
  175. case CS5:
  176.     pChan->lcr = CHAR_LEN_5; break;
  177. case CS6:
  178.     pChan->lcr = CHAR_LEN_6; break;
  179. case CS7:
  180.     pChan->lcr = CHAR_LEN_7; break;
  181. case CS8:
  182. default:
  183.     pChan->lcr = CHAR_LEN_8; break;
  184. }
  185.     if (options & STOPB)
  186. pChan->lcr |= LCR_STB_2;
  187.     else
  188. pChan->lcr |= LCR_STB_1;
  189.     
  190.     switch (options & (PARENB | PARODD))
  191. {
  192. case PARENB|PARODD:
  193.     pChan->lcr |= LCR_PEN; break;
  194. case PARENB:
  195.     pChan->lcr |= (LCR_PEN | LCR_EPS); break;
  196. default:
  197. case 0:
  198.     pChan->lcr |= LCR_PDIS; break;
  199. }
  200.     REG(IER, pChan) = IER_UUE; /* disable interrupts, enable UART */
  201.     if (!(options & CLOCAL)) /* use hardware flow control (RTS/CTS) */
  202. {
  203. pChan->mcr |= MCR_RTS;
  204.      pChan->ier &= (~IER_TIE); 
  205. pChan->ier |= IER_MIE;  /* enable modem status interrupt */
  206. }
  207.     else
  208.         pChan->ier &= (~IER_MIE); /* software flow ctrl */ 
  209.     oldlevel = intLock();
  210.     REG(LCR, pChan) = (unsigned int) pChan->lcr;
  211.     REG(MCR, pChan) = (unsigned int) pChan->mcr;
  212.     /* Enable FIFOs and set trigger level */
  213.     REG(FCR, pChan) = (unsigned int) (FCR_RESETRF | FCR_RESETTF | FCR_TRFIFOE);
  214.     REG(FCR, pChan) |= (unsigned int) (FCR_ITL_32);
  215.     if (options & CREAD)  
  216. pChan->ier |= (IER_RAVIE | IER_RTOIE);
  217.     if (pChan->channelMode == SIO_MODE_INT)
  218. {
  219. pChan->ier |= IER_RLSE;
  220.         REG(IER, pChan) = (unsigned int) pChan->ier;
  221.         }
  222.     intUnlock (oldlevel);
  223.     pChan->options = options;
  224.     return OK;
  225.     }
  226.     
  227. /******************************************************************************
  228. *
  229. * ixp425SioBaudSet - change baud rate for channel
  230. *
  231. * This routine sets the baud rate for the UART. The interrupts are disabled
  232. * during chip access.
  233. *
  234. * RETURNS: OK
  235. */
  236. LOCAL STATUS  ixp425SioBaudSet
  237.     (
  238.     IXP425_SIO_CHAN * pChan, /* pointer to channel */
  239.     UINT    baud /* requested baud rate */
  240.     )
  241.     {
  242.     FAST int   oldlevel;
  243.     /* disable interrupts during chip access */
  244.     oldlevel = intLock ();
  245.     /* Enable access to the divisor latches by setting DLAB in LCR. */
  246.     REG(LCR, pChan) = (unsigned int) (LCR_DLAB | pChan->lcr);
  247.     /* Set divisor latches. */
  248.     REG(DLL, pChan) = (unsigned int) (pChan->xtal/(16 * baud));
  249.     REG(DLM, pChan) = (unsigned int) ((pChan->xtal/(16 * baud)) >> 8);
  250.     /* Restore line control register */
  251.     REG(LCR, pChan) = (unsigned int) pChan->lcr;
  252.     pChan->baudRate = baud;
  253.  
  254.     intUnlock (oldlevel);
  255.     return (OK);
  256.     }
  257. /*******************************************************************************
  258. *
  259. * ixp425SioModeSet - change channel mode setting
  260. *
  261. * This driver supports both polled and interrupt modes and is capable of
  262. * switching between modes dynamically. 
  263. *
  264. * If interrupt mode is desired this routine enables the channel's receiver 
  265. * interrupt. The transmitter interrupt is enabled in TxStartup(). If the modem 
  266. * control option is TRUE, the Tx interrupt is disabled if the CTS signal is FALSE.
  267. * It is enabled otherwise. 
  268. *
  269. * If polled mode is desired the device interrupts are disabled. 
  270. *
  271. * RETURNS:
  272. * Returns a status of OK if the mode was set else ERROR.
  273. */
  274. LOCAL STATUS ixp425SioModeSet
  275.     (
  276.     IXP425_SIO_CHAN * pChan, /* pointer to channel */
  277.     UINT newMode /* mode requested */
  278.     )
  279.     {
  280.     FAST int     oldlevel; /* current interrupt level mask */
  281.     char mask;
  282.     if ((newMode != SIO_MODE_POLL) && (newMode != SIO_MODE_INT))
  283. return (ERROR);
  284.            
  285.     oldlevel = intLock ();
  286.     if (newMode == SIO_MODE_INT)
  287. {
  288. if (pChan->options & CLOCAL)
  289.     {
  290.     pChan->ier |= (IER_RAVIE | IER_RTOIE | IER_RLSE);
  291.             REG(IER, pChan) = (unsigned int) pChan->ier;
  292.     }
  293. else  
  294.     {
  295.     mask = REG(MSR, pChan) & MSR_CTS;
  296.         /* if the CTS is asserted enable Tx interrupt */
  297.         if (mask & MSR_CTS)
  298. pChan->ier |= IER_TIE;
  299.     else
  300. pChan->ier &= (~IER_TIE); /* disable Tx interrupt */
  301.     REG(IER, pChan) = (unsigned int) pChan->ier; 
  302.     }
  303. }
  304.     else /* Polled mode */
  305.         {
  306.         REG(IER, pChan) = (unsigned int) IER_UUE;   
  307. }
  308.     pChan->channelMode = newMode;
  309.     intUnlock (oldlevel);
  310.     return (OK);
  311.    }
  312. /*******************************************************************************
  313. *
  314. * ixp425SioIoctl - special device control
  315. *
  316. * Includes commands to get/set baud rate, mode(INT,POLL), hardware options(
  317. * parity, number of data bits), and modem control(RTS/CTS).
  318. *
  319. * RETURNS: OK on success, EIO on device error, ENOSYS on unsupported
  320. *          request.
  321. */
  322. LOCAL STATUS ixp425SioIoctl
  323.     (
  324.     IXP425_SIO_CHAN *  pChan, /* pointer to channel */
  325.     int request, /* request code */
  326.     int         arg /* some argument */
  327.     )
  328.     {
  329.     FAST STATUS  status;
  330.     status = OK;
  331.     switch (request)
  332. {
  333. case SIO_BAUD_SET:
  334.     if (arg < IXP425_SIO_MIN_RATE || arg > IXP425_SIO_MAX_RATE)
  335. status = EIO; /* baud rate out of range */
  336.     else
  337.         status = ixp425SioBaudSet (pChan, arg);
  338.     break;
  339.         case SIO_BAUD_GET:
  340.             *(int *)arg = pChan->baudRate;
  341.             break; 
  342.         case SIO_MODE_SET:
  343.     status = (ixp425SioModeSet (pChan, arg) == OK) ? OK : EIO;
  344.             break;          
  345.         case SIO_MODE_GET:
  346.             *(int *)arg = pChan->channelMode;
  347.             break;
  348.         case SIO_AVAIL_MODES_GET:
  349.             *(int *)arg = SIO_MODE_INT | SIO_MODE_POLL;
  350.             break;
  351.         case SIO_HW_OPTS_SET:
  352.          status = (ixp425SioOptsSet (pChan, arg) == OK) ? OK : EIO;
  353.          break;
  354.         case SIO_HW_OPTS_GET:
  355.             *(int *)arg = pChan->options;
  356.             break;
  357.         case SIO_HUP:
  358.     /* Does nothing for now */
  359.             break;
  360. case SIO_OPEN:
  361.             /* Does nothing for now */
  362.     break;
  363.         default:
  364.             status = ENOSYS;
  365. }
  366.     return (status);
  367.     }
  368. /*******************************************************************************
  369. *
  370. * ixp425SioIntWr - handle a transmitter interrupt 
  371. *
  372. * This routine handles write interrupts from the UART. It reads a character
  373. * and puts it in the transmit holding register of the device for transfer.
  374. * If there are no more characters to transmit, transmission is disabled by 
  375. * clearing the transmit interrupt enable bit in the IER(int enable register).
  376. * Any pending recieve data is also serviced.
  377. *
  378. * RETURNS: N/A
  379. *
  380. */
  381. void ixp425SioIntWr 
  382.     (
  383.     IXP425_SIO_CHAN * pChan /* pointer to channel */
  384.     )
  385.     {
  386.     char    outChar;
  387.     unsigned int charCnt = 0;
  388.     while( (charCnt < IXP425_SIO_MAX_CNT) )
  389.         {
  390. if((*pChan->getTxChar) (pChan->getTxArg, &outChar) != ERROR)
  391.     {
  392. /*
  393.  * At the time of this writing the TDRQ bit of the LSR is not working so we 
  394.  * can't check for character overuns. We get around this by making sure we only ever
  395.  * write less then the size of the FIFO per ISR as represented by IXP425_SIO_MAX_CNT.
  396.  */
  397.     REG(THR, pChan) = (unsigned int)outChar;
  398. #ifdef IXP425_SIO_DEBUG
  399.     pChan->txCount++;
  400. #endif
  401.     charCnt++;
  402.     }
  403. else
  404.     {
  405.     break;
  406.     }
  407. }
  408.     if (charCnt == 0)
  409.         pChan->ier &= (~IER_TIE); /* disable Tx Int */
  410.     /* Service any pending receive characters */
  411.     ixp425SioIntRd(pChan);
  412.     }
  413. /*******************************************************************************
  414. *
  415. * ixp425SioIntRd - handle a receiver interrupt 
  416. *
  417. * This routine handles read interrupts from the UART.
  418. *
  419. * RETURNS: N/A
  420. *
  421. */
  422. void ixp425SioIntRd
  423.     (
  424.     IXP425_SIO_CHAN * pChan /* pointer to channel */
  425.     )
  426.     {
  427.     char inchar;
  428.     volatile char lsr;
  429.     unsigned int charCnt = IXP425_SIO_MAX_CNT;
  430.     lsr = REG(LSR, pChan);
  431.     while( (lsr & LSR_DR) && (charCnt != 0) )
  432.         {
  433. inchar = REG(RBR, pChan);
  434. (*pChan->putRcvChar)(pChan->putRcvArg, inchar);
  435. #ifdef IXP425_SIO_DEBUG
  436. pChan->rxCount++;
  437. #endif
  438. --charCnt;
  439. lsr = REG(LSR, pChan);
  440.         }
  441.     }
  442. #ifdef IXP425_SIO_DEBUG
  443. /*******************************************************************************
  444. *
  445. * ixp425SioIntErr - handle an error interrupt 
  446. *
  447. * This routine handles error interrupts from the UART. 
  448. *
  449. * RETURNS: N/A
  450. *
  451. */
  452. void ixp425SioIntErr 
  453.     (
  454.     IXP425_SIO_CHAN * pChan, /* pointer to channel */
  455.     char intErr
  456.     )
  457.     {
  458.     if(intErr & LSR_OE)
  459.         pChan->overrunErr++;
  460.     if(intErr & LSR_PE)
  461.         pChan->parityErr++;
  462.     if(intErr & LSR_FE)
  463.         pChan->framingErr++;
  464.     if(intErr & LSR_BI)
  465.         pChan->breakErr++;
  466.     }
  467. #endif
  468. /*******************************************************************************
  469. *
  470. * ixp425SioInt - interrupt level processing
  471. *
  472. * This function handles four sources of interrupts from the UART. They are
  473. * prioritized in the following order by the Interrupt Identification Register
  474. * 'Receiver Line Status', 'Received Data Ready', 'Transmit Holding Register Empty'
  475. * and 'Modem Status'.
  476. *
  477. * When a modem status interrupt occurs, the transmit interrupt is enabled if
  478. * the CTS signal is TRUE.
  479. *
  480. * RETURNS: N/A
  481. */
  482. void ixp425SioInt
  483.     (
  484.     IXP425_SIO_CHAN * pChan /* pointer to channel */
  485.     )
  486.     {
  487.     FAST volatile char        intStatus;
  488.     /* read the Interrrupt Identification Register */
  489.     intStatus = (char)((REG(IIR, pChan)) & 0x0f);
  490.     REG(IER,pChan) = 0; /* disable interrupts */
  491.     switch (intStatus)
  492. {
  493. case IIR_RLS: /* overrun,parity error and break interrupt */
  494.             intStatus = REG(LSR, pChan); /* read LSR to reset interrupt */
  495. #ifdef IXP425_SIO_DEBUG
  496.     ixp425SioIntErr (pChan, intStatus);
  497. #endif
  498.     break;
  499.         case IIR_RDA: /* received data available */
  500. case IIR_TIMEOUT: 
  501.             ixp425SioIntRd (pChan);
  502.             break;
  503.         case IIR_THRE:  /* transmitter holding register empty */
  504.     ixp425SioIntWr (pChan);
  505.             break;
  506. case IIR_MSTAT: /* modem status register */
  507.    {
  508.    char msr;
  509.    msr = REG(MSR, pChan);
  510.    /* if CTS is asserted by modem, enable tx interrupt */
  511.    if ((msr & MSR_CTS) && (msr & MSR_DCTS)) 
  512.     pChan->ier |= IER_TIE;
  513.            else
  514.             pChan->ier &= (~IER_TIE); 
  515.    }
  516.    break;
  517.         default:
  518.     break;
  519.         }
  520.     REG(IER, pChan) = (unsigned int) pChan->ier; /* re-enable interrupts */
  521.     }
  522. /*******************************************************************************
  523. *
  524. * ixp425SioTxStartup - transmitter startup routine
  525. *
  526. * Call interrupt level character output routine and enable interrupt if it is
  527. * in interrupt mode with no hardware flow control.
  528. * If the option for hardware flow control is enabled and CTS is set TRUE,
  529. * then the Tx interrupt is enabled.
  530. * RETURNS: N/A
  531. */
  532. LOCAL void ixp425SioTxStartup
  533.     (
  534.     IXP425_SIO_CHAN * pChan  /* pointer to channel */
  535.     )
  536.     {
  537.     char mask;
  538.     if (pChan->channelMode == SIO_MODE_INT)
  539.         {
  540. if (pChan->options & CLOCAL) /* Software flow control */
  541.     {
  542.     pChan->ier |= IER_TIE;
  543.             REG(IER, pChan) = (unsigned int) pChan->ier;
  544.     }
  545. else
  546.     {
  547.     mask = REG(MSR, pChan) & MSR_CTS;
  548.     if (mask & MSR_CTS)
  549. pChan->ier |= IER_TIE;
  550.     else
  551. pChan->ier &= (~IER_TIE);
  552.     REG(IER, pChan) = (unsigned int) pChan->ier;
  553.     }
  554.         }
  555.     }
  556. /******************************************************************************
  557. *
  558. * ixp425SioPollOutput - output a character in polled mode. Used by the 
  559. * Windriver debug agent.
  560. *
  561. * RETURNS: OK if a character arrived, EIO on device error, EAGAIN
  562. * if the output buffer if full.
  563. */
  564. LOCAL int ixp425SioPollOutput
  565.     (
  566.     IXP425_SIO_CHAN *  pChan, /* pointer to channel */
  567.     char            outChar /* char to send */
  568.     )
  569.     {
  570.     char pollStatus = REG(LSR, pChan);
  571.     char msr = REG(MSR, pChan);
  572.     if (!(pollStatus & LSR_TDRQ))
  573.         return (EAGAIN);
  574.     if (!(pChan->options & CLOCAL))  /* hardare flow control */
  575.      {
  576.      if (msr & MSR_CTS)
  577.         {
  578.      REG(THR, pChan) = outChar;
  579. #ifdef IXP425_SIO_DEBUG
  580. pChan->txCount++;
  581. #endif
  582. }
  583. else
  584. return (EAGAIN);
  585. }
  586.     else
  587.         {
  588.     REG(THR, pChan) = outChar;       /* transmit character */
  589. #ifdef IXP425_SIO_DEBUG
  590. pChan->txCount++;
  591. #endif
  592. }
  593.     return (OK);
  594.     }
  595. /******************************************************************************
  596. *
  597. * ixp425SioPollInput - poll the device for input. Used by the Windriver
  598. * debug agent.
  599. *
  600. * RETURNS: OK if a character arrived, EIO on device error, EAGAIN
  601. * if the input buffer if empty.
  602. */
  603. LOCAL int ixp425SioPollInput
  604.     (
  605.     IXP425_SIO_CHAN *  pChan, /* pointer to channel */
  606.     char *          pChar  /* pointer to char */
  607.     )
  608.     {
  609.     char pollStatus = REG(LSR, pChan);
  610.     if (!(pollStatus & LSR_DR))
  611.         return (EAGAIN);
  612.     *pChar = REG(RBR, pChan);
  613. #ifdef IXP425_SIO_DEBUG
  614.     pChan->rxCount++;
  615. #endif
  616.     return (OK);
  617.     }
  618. /******************************************************************************
  619. *
  620. * ixp425SioCallbackInstall - install ISR callbacks to get/put chars.
  621. *
  622. * This routine installs the callback functions for the driver
  623. *
  624. * RETURNS: OK on success or ENOSYS on unsupported callback type.
  625. */
  626. LOCAL int ixp425SioCallbackInstall
  627.     (
  628.     SIO_CHAN *  pSioChan, /* pointer to device to control */
  629.     int         callbackType, /* callback type(tx or receive) */
  630.     STATUS      (*callback)(), /* pointer to callback function */
  631.     void *      callbackArg /* callback function argument */
  632.     )
  633.     {
  634.     IXP425_SIO_CHAN * pChan = (IXP425_SIO_CHAN *)pSioChan;
  635.     switch (callbackType)
  636.         {
  637.         case SIO_CALLBACK_GET_TX_CHAR:
  638.             pChan->getTxChar    = callback;
  639.             pChan->getTxArg     = callbackArg;
  640.             return (OK);
  641.         case SIO_CALLBACK_PUT_RCV_CHAR:
  642.             pChan->putRcvChar   = callback;
  643.             pChan->putRcvArg    = callbackArg;
  644.             return (OK);
  645.         default:
  646.             return (ENOSYS);
  647.         }
  648.     }
  649. /******************************************************************************
  650. *
  651. * ixp425SioStatsShow - display UART error statistics.
  652. *
  653. * PRE: This routine requires that printf() is available.
  654. *
  655. * RETURNS: N/A
  656. */
  657. void ixp425SioStatsShow
  658.     (
  659.     IXP425_SIO_CHAN * pChan
  660.     )
  661.     {
  662.     printf("nIXP425 UART Statistics:");
  663. #ifdef IXP425_SIO_DEBUG
  664.     printf("nrxCount:t%u", pChan->rxCount);
  665.     printf("ntxCount:t%u", pChan->txCount);
  666.     printf("noverrun Errors:t%u", pChan->overrunErr);
  667.     printf("nparity Errors:t%u", pChan->parityErr);
  668.     printf("nframing Errors:t%u", pChan->framingErr);
  669.     printf("nbreak Errors:t%un", pChan->breakErr);
  670. #else
  671.     printf("nUART statistics not availablen");
  672. #endif /* IXP425_SIO_DEBUG */
  673.     }