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

VxWorks

开发平台:

C/C++

  1. /* z8530Sio.c - Z8530 SCC Serial Communications Controller driver */
  2. /* Copyright 1995-1996 Wind River Systems, Inc. */
  3. /*
  4. modification history
  5. --------------------
  6. 01j,09jun97,mas  now uses BSP-defined macros for register access and reset
  7.  delay loop/count (SPR 8566); updated documentation.
  8. 01i,05jun97,db   fixed warning messages.
  9. 01h,23may97,db   added hardware options and modem control flow(SPR #1037).
  10. 01g,27dec96,dat  fixed spr 7683, int ack in wrong place (z8530IntRd).
  11. 01f,11jun96,dbt  fixed spr 6325. replaced everywhere *cr = 0 with *cr = zero.
  12.  Update Copyright.
  13. 01g,13oct95,ms   initialize all the non-BSP specific fields in z8530DevInit()
  14. 01f,21sep95,myz  fixed the interrupt race problem
  15. 01e,03aug95,myz  fixed the warning messages
  16. 01d,20jun95,ms   fixed comments for mangen
  17. 01c,15jun95,ms  updated for new driver structure
  18. 01b,28apr95,ms   z8530IntRd now only reads the data register once.
  19. 01a,21dec94,ms   written (using z8530Serial.c + the VxMon polled driver).
  20. */
  21. /*
  22. DESCRIPTION
  23. This is the driver for the Z8530 SCC (Serial Communications Controller).
  24. It uses the SCCs in asynchronous mode only.
  25. USAGE
  26. A Z8530_DUSART structure is used to describe the chip. This data structure
  27. contains two Z8530_CHAN structures which describe the chip's two serial
  28. channels.  Supported baud rates range from 50 to 38400.  The default baud
  29. rate is Z8530_DEFAULT_BAUD (9600).  The BSP may redefine this.
  30. The BSP's sysHwInit() routine typically calls sysSerialHwInit()
  31. which initializes all the values in the Z8530_DUSART structure (except
  32. the SIO_DRV_FUNCS) before calling z8530DevInit().
  33. The BSP's sysHwInit2() routine typically calls sysSerialHwInit2() which
  34. connects the chips interrupts via intConnect() (either the single
  35. interrupt z8530Int or the three interrupts z8530IntWr, z8530IntRd,
  36. and z8530IntEx).
  37. This driver handles setting of hardware options such as parity(odd, even) and
  38. number of data bits(5, 6, 7, 8).  Hardware flow control is provided with the
  39. signals CTS on transmit and DSR on read.  Refer to the target documentation
  40. for the RS232 port configuration.  The function HUPCL(hang up on last close) is
  41. supported.  Default hardware options are defined by Z8530_DEFAULT_OPTIONS.
  42. The BSP may redefine them.
  43. All device registers are accessed via BSP-defined macros so that memory-
  44. mapped as well as I/O space accesses can be supported.  The BSP may re-
  45. define the REG_8530_READ and REG_8530_WRITE macros as needed.  By default,
  46. they are defined as simple memory-mapped accesses.
  47. The BSP may define DATA_REG_8530_DIRECT to cause direct access to the Z8530
  48. data register, where hardware permits it.  By default, it is not defined.
  49. The BSP may redefine the macro for the channel reset delay Z8530_RESET_DELAY
  50. as well as the channel reset delay counter value Z8530_RESET_DELAY_COUNT as
  51. required.  The delay is defined as the minimum time between successive chip
  52. accesses (6 PCLKs + 200 nSec for a Z8530, 4 PCLKs for a Z85C30 or Z85230)
  53. plus an additional 4 PCLKs.  At a typical PCLK frequency of 10 MHz, each PCLK
  54. is 100 nSec, giving a minimum reset delay of:
  55. Z8530:  10 PCLKs + 200 nSec = 1200 nSec = 1.2 uSec
  56. Z85x30:  8 PCLKs            =  800 nSec = 0.8 uSec
  57. INCLUDE FILES: drv/sio/z8530Sio.h
  58. */
  59. #include "vxWorks.h"
  60. #include "sioLib.h"
  61. #include "intLib.h"
  62. #include "errno.h"
  63. #include "drv/sio/z8530Sio.h"
  64. #ifndef SIO_HUP
  65. #   define SIO_OPEN 0x100A
  66. #   define SIO_HUP 0x100B
  67. #endif
  68. /* forward static declarations */
  69. static void z8530InitChannel (Z8530_CHAN *);
  70. static int z8530Ioctl (SIO_CHAN *, int, void *);
  71. static int z8530TxStartup (SIO_CHAN *);
  72. static int z8530CallbackInstall (SIO_CHAN *, int, STATUS (*)(), void *);
  73. static int z8530PollInput (SIO_CHAN *, char *);
  74. static int z8530PollOutput (SIO_CHAN *, char);
  75. LOCAL   STATUS  z8530OptsSet (Z8530_CHAN *, UINT);
  76. LOCAL   STATUS  z8530Open (Z8530_CHAN * pChan );
  77. LOCAL   STATUS  z8530Hup (Z8530_CHAN * pChan );
  78. /* driver functions */
  79. static SIO_DRV_FUNCS z8530SioDrvFuncs = 
  80.     {
  81.     (int (*)())z8530Ioctl,
  82.     (int (*)())z8530TxStartup,
  83.     z8530CallbackInstall,
  84.     (int (*)())z8530PollInput,
  85.     (int (*)(SIO_CHAN *,char))z8530PollOutput
  86.     };
  87. /* defines */
  88. #ifndef Z8530_DEFAULT_BAUD
  89. #       define  Z8530_DEFAULT_BAUD      9600
  90. #endif
  91. #ifndef Z8530_DEFAULT_OPTIONS
  92.     /* no handshake, rcvr enabled, 8 data bits, 1 stop bit, no parity */
  93. #   define Z8530_DEFAULT_OPTIONS (CLOCAL | CREAD | CS8)
  94. #endif
  95. #ifndef REG_8530_READ
  96. #  define REG_8530_READ(reg,pVal) *(pVal) = (*(reg))
  97. #endif  /* REG_8530_READ */
  98. #ifndef REG_8530_WRITE
  99. #  define REG_8530_WRITE(reg,val) (*(reg) = (val))
  100. #endif  /* REG_8530_WRITE */
  101. #ifndef Z8530_RESET_DELAY_COUNT
  102. #  define Z8530_RESET_DELAY_COUNT 1000
  103. #endif  /* Z8530_REST_DELAY_COUNT */
  104. #ifndef Z8530_RESET_DELAY
  105. #  define Z8530_RESET_DELAY 
  106.         { 
  107.         int i; 
  108.         for (i = 0; i < Z8530_RESET_DELAY_COUNT; i++) 
  109.                 ; /* do nothing */ 
  110.         }
  111. #endif  /* Z8530_REST_DELAY */
  112. /******************************************************************************
  113. *
  114. * z8530DummyCallback - dummy callback routine.
  115. *
  116. * This routine is used as an intialization default only.
  117. *
  118. * RETURNS: ERROR always
  119. */ 
  120. static STATUS z8530DummyCallback (void)
  121.     {
  122.     return (ERROR);
  123.     }
  124. /******************************************************************************
  125. *
  126. * z8530TxStartup - start the interrupt transmitter.
  127. *
  128. * This routine starts the transmitter if it isn't already transmitting.
  129. * This routine should only be called in interrupt mode.
  130. *
  131. * RETURNS: OK always
  132. */
  133. static int z8530TxStartup
  134.     (
  135.     SIO_CHAN * pSioChan
  136.     )
  137.     {
  138.     Z8530_CHAN * pChan = (Z8530_CHAN *)pSioChan;
  139.     char         outChar;
  140.     int          lvl;
  141.     if ((*pChan->getTxChar) (pChan->getTxArg, &outChar) != ERROR)
  142. {
  143. lvl = intLock ();
  144. #ifndef DATA_REG_8530_DIRECT
  145. REG_8530_WRITE(pChan->cr, SCC_WR0_SEL_WR8); /* select data register */
  146. REG_8530_WRITE(pChan->cr, outChar);
  147. #else
  148. REG_8530_WRITE(pChan->dr, outChar);
  149. #endif  /* DATA_REG_8530_DIRECT */
  150. intUnlock (lvl);
  151. }
  152.     return (OK);
  153.     }
  154. /******************************************************************************
  155. *
  156. * z8530CallbackInstall - install ISR callbacks to get/put chars.
  157. *
  158. * This routine installs the specified type of callback routine and its
  159. * associated argument for use in read/write character buffer management
  160. * as defined in Stream I/O (SIO).
  161. *
  162. * RETURNS: OK or ENOSYS if unknown callback type.
  163. */ 
  164. static int z8530CallbackInstall
  165.     (
  166.     SIO_CHAN * pSioChan,
  167.     int callbackType,
  168.     STATUS (*callback)(),
  169.     void *      callbackArg
  170.     )
  171.     {
  172.     Z8530_CHAN * pChan = (Z8530_CHAN *)pSioChan;
  173.     switch (callbackType)
  174. {
  175. case SIO_CALLBACK_GET_TX_CHAR:
  176.     pChan->getTxChar = callback;
  177.     pChan->getTxArg = callbackArg;
  178.     return (OK);
  179. case SIO_CALLBACK_PUT_RCV_CHAR:
  180.     pChan->putRcvChar = callback;
  181.     pChan->putRcvArg = callbackArg;
  182.     return (OK);
  183. default:
  184.     return (ENOSYS);
  185. }
  186.     }
  187. /******************************************************************************
  188. *
  189. * z8530PollOutput - output a character in polled mode.
  190. *
  191. * This routine is called to transmit a single character when the driver is
  192. * set to polled mode (no interrupts).
  193. *
  194. * RETURNS: OK if a character arrived, EIO on device error, EAGAIN
  195. *    if the output buffer if full.
  196. */
  197. static int z8530PollOutput
  198.     (
  199.     SIO_CHAN * pSioChan,
  200.     char outChar
  201.     )
  202.     {
  203.     Z8530_CHAN *  pChan = (Z8530_CHAN *)pSioChan;
  204.     volatile char ch;
  205.     /* is the transitter ready to accept a character? */
  206.     REG_8530_READ(pChan->cr, &ch);
  207.     if ((ch & SCC_RR0_TX_EMPTY) == 0x00)
  208. return (EAGAIN);
  209.     /* write out the character */
  210. #ifndef DATA_REG_8530_DIRECT
  211.     REG_8530_WRITE(pChan->cr, SCC_WR0_SEL_WR8); /* select data register */
  212.     REG_8530_WRITE(pChan->cr, outChar);
  213. #else
  214.     REG_8530_WRITE(pChan->dr, outChar);
  215. #endif  /* DATA_REG_8530_DIRECT */
  216.     return (OK);
  217.     }
  218. /******************************************************************************
  219. *
  220. * z8530PollInput - poll the device for input.
  221. *
  222. * This routine is called to receive a single character when the driver is
  223. * set to polled mode (no interrupts).
  224. *
  225. * RETURNS: OK if a character arrived, EIO on device error, EAGAIN
  226. *    if the input buffer if empty.
  227. */
  228. static int z8530PollInput
  229.     (
  230.     SIO_CHAN * pSioChan,
  231.     char * thisChar
  232.     )
  233.     {
  234.     Z8530_CHAN *  pChan = (Z8530_CHAN *)pSioChan;
  235.     volatile char ch;
  236.     /* is a character available? */
  237.     REG_8530_READ(pChan->cr, &ch);
  238.     if ((ch & SCC_RR0_RX_AVAIL) == 0x00)
  239. return (EAGAIN);
  240.     /* yes, get a character */
  241. #ifndef DATA_REG_8530_DIRECT
  242.     REG_8530_WRITE(pChan->cr, SCC_WR0_SEL_WR8); /* select data register */
  243.     REG_8530_READ(pChan->cr, thisChar);
  244. #else
  245.     REG_8530_READ(pChan->dr, thisChar);
  246. #endif  /* DATA_REG_8530_DIRECT */
  247.     /* check for errors */
  248.     REG_8530_WRITE(pChan->cr, SCC_WR0_SEL_WR1); /* read reg 1 */
  249.     REG_8530_READ(pChan->cr, &ch);
  250.     if ((ch & 0x70) != 0) /* reset if errors */
  251.         REG_8530_WRITE(pChan->cr, SCC_WR0_ERR_RST);
  252.     return (OK);
  253.     }
  254. /******************************************************************************
  255. *
  256. * z8530ModeSet - set driver mode
  257. *
  258. * This routine sets the driver SIO mode.  Currently there are only two:
  259. * polled and interrupt.
  260. *
  261. * RETURNS: OK    if successful
  262. *          ERROR if illegal mode specified
  263. */
  264. static STATUS z8530ModeSet
  265.     (
  266.     Z8530_CHAN * pChan,
  267.     uint_t  newMode
  268.     )
  269.     {
  270.     int             oldlevel;
  271.     int             zero = 0;
  272.     volatile char * cr = pChan->cr;    /* SCC control reg adr */
  273.     if ((newMode != SIO_MODE_POLL) && (newMode != SIO_MODE_INT))
  274. return (ERROR);
  275.     oldlevel = intLock ();
  276.     pChan->mode = newMode;
  277.     if (pChan->mode == SIO_MODE_INT)
  278.         {
  279.         REG_8530_WRITE(cr, SCC_WR0_SEL_WR1); /* int and xfer mode */
  280.         REG_8530_WRITE(cr, SCC_WR1_INT_ALL_RX | SCC_WR1_TX_INT_EN);
  281.         }
  282.     else
  283.         {
  284.         REG_8530_WRITE(cr, SCC_WR0_SEL_WR1); /* no interrupts */
  285.         REG_8530_WRITE(cr, zero);
  286.         }
  287.     intUnlock(oldlevel);
  288.    
  289.     return (OK);
  290.     }
  291. /*******************************************************************************
  292. *
  293. * z8530InitChannel - initialize a single channel
  294. *
  295. * This routine initializes the specified Z8530 channel to a known and
  296. * quiescent state at a default baud rate, no handshake signals.  It is
  297. * called by z8530DevInit().
  298. *
  299. * RETURNS: N/A
  300. */
  301. static void z8530InitChannel
  302.     (
  303.     Z8530_CHAN * pChan
  304.     )
  305.     {
  306.     int             baudConstant;
  307.     int             zero = 0;
  308.     volatile char * cr = pChan->cr;    /* SCC control reg adr */
  309.     /* SCC_WR0_NULL_CODE sync the state machine */
  310.     REG_8530_WRITE(cr, zero);
  311.     REG_8530_WRITE(cr, zero);
  312.     /* reset any error or interrupts */
  313.     REG_8530_WRITE(cr, SCC_WR0_ERR_RST);
  314.     REG_8530_WRITE(cr, SCC_WR0_RST_INT);
  315.     /* write reg 9 - master interrupt control and reset */
  316.     REG_8530_WRITE(cr, SCC_WR0_SEL_WR9);
  317.     /* reset specified channel */
  318.     if (pChan->channel == SCC_CHANNEL_A)
  319.         REG_8530_WRITE(cr, SCC_WR9_CH_A_RST);      /* reset channel A */
  320.     else
  321.         REG_8530_WRITE(cr, SCC_WR9_CH_B_RST);      /* reset channel B */
  322.     /* Delay for about 1 uSec (typically) before further chip accesses */
  323.     Z8530_RESET_DELAY
  324.     /* initialize registers */
  325.     /* write reg 4 - misc parms & modes */
  326.     REG_8530_WRITE(cr, SCC_WR0_SEL_WR4);
  327.     REG_8530_WRITE(cr, SCC_WR4_1_STOP | SCC_WR4_16_CLOCK);
  328.     /* write reg 3 - receive params */
  329.     REG_8530_WRITE(cr, SCC_WR0_SEL_WR3);
  330.     REG_8530_WRITE(cr, (unsigned char)SCC_WR3_RX_8_BITS);
  331.     /* write reg 5 - tx params */
  332.     REG_8530_WRITE(cr, SCC_WR0_SEL_WR5);
  333.     REG_8530_WRITE(cr, (UINT8)(SCC_WR5_TX_8_BITS | SCC_WR5_DTR | SCC_WR5_RTS));
  334.     /* write reg 10 - misc tx/rx control */
  335.     REG_8530_WRITE(cr, SCC_WR0_SEL_WR10);
  336.     REG_8530_WRITE(cr, zero);             /* clear sync, loop, poll */
  337.     /* write reg 11 - clock mode */
  338.     REG_8530_WRITE(cr, SCC_WR0_SEL_WR11);
  339.     REG_8530_WRITE(cr, pChan->writeReg11);
  340.     /* write reg 15 - disable external/status interrupts */
  341.     REG_8530_WRITE(cr, SCC_WR0_SEL_WR15);
  342.     REG_8530_WRITE(cr, zero);
  343.     /*
  344.      * Calculate the baud rate constant for the default baud rate
  345.      * from the input clock (PCLK) frequency.  This assumes that
  346.      * the divide-by-16 bit is set (done in WR4 above).
  347.      */
  348.     baudConstant = ((pChan->baudFreq / 32) / pChan->baudRate) - 2;
  349.     /* write reg 12,13 - set baud rate */
  350.     REG_8530_WRITE(cr, SCC_WR0_SEL_WR12);     /* LSB of baud constant */
  351.     REG_8530_WRITE(cr, (char)baudConstant);
  352.     REG_8530_WRITE(cr, SCC_WR0_SEL_WR13);     /* MSB of baud constant */
  353.     REG_8530_WRITE(cr, (char)(baudConstant >> 8));
  354.     /* write reg 14 - misc control bits */
  355.     REG_8530_WRITE(cr, SCC_WR0_SEL_WR14);
  356.     REG_8530_WRITE(cr, pChan->writeReg14);
  357.     /* reset external interrupts and errors */
  358.     REG_8530_WRITE(cr, SCC_WR0_RST_INT);
  359.     REG_8530_WRITE(cr, SCC_WR0_ERR_RST);
  360.     /* write reg 3 - receive params */
  361.     REG_8530_WRITE(cr, SCC_WR0_SEL_WR3);
  362.     REG_8530_WRITE(cr, (unsigned char)(SCC_WR3_RX_8_BITS | SCC_WR3_RX_EN));
  363.     /* write reg 5 - tx params */
  364.     REG_8530_WRITE(cr, SCC_WR0_SEL_WR5);
  365.     REG_8530_WRITE(cr, (unsigned char)(SCC_WR5_TX_8_BITS | SCC_WR5_TX_EN |
  366.        SCC_WR5_DTR       | SCC_WR5_RTS    ));
  367.     /* write reg 2 - interrupt vector */
  368.     REG_8530_WRITE(cr, SCC_WR0_SEL_WR2);
  369.     REG_8530_WRITE(cr, pChan->intVec);
  370.     /* write reg 1 - disable interrupts and xfer mode */
  371.     REG_8530_WRITE(cr, SCC_WR0_SEL_WR1);
  372.     REG_8530_WRITE(cr, zero);
  373.     /* write reg 9 - enable master interrupt control */
  374.     REG_8530_WRITE(cr, SCC_WR0_SEL_WR9);
  375.     REG_8530_WRITE(cr, SCC_WR9_MIE | pChan->intType);
  376.     /* reset Tx CRC generator and any pending ext/status interrupts */
  377.     REG_8530_WRITE(cr, (UINT8)(SCC_WR0_RST_TX_CRC));
  378.     REG_8530_WRITE(cr, SCC_WR0_RST_INT);
  379.     REG_8530_WRITE(cr, SCC_WR0_RST_INT);
  380.     /* reset SCC register counter */
  381.     REG_8530_WRITE(cr, zero);
  382.     }
  383. /*******************************************************************************
  384. *
  385. * z8530Hup - hang up the modem control lines 
  386. *
  387. * Resets the RTS and DTR signals.
  388. *
  389. * RETURNS: OK
  390. */
  391. LOCAL STATUS z8530Hup
  392.     (
  393.     Z8530_CHAN * pChan          /* pointer to channel */
  394.     )
  395.     {
  396.     volatile    char *cr = pChan->cr;    /* SCC control reg adr */
  397.     FAST        int     oldlevel;       /* current interrupt level mask */
  398.     pChan->writeReg5 &= (~(SCC_WR5_DTR | SCC_WR5_RTS));
  399.     oldlevel = intLock ();
  400.     REG_8530_WRITE(cr, SCC_WR0_SEL_WR5);     
  401.     REG_8530_WRITE(cr, pChan->writeReg5);
  402.     intUnlock (oldlevel);
  403.     return (OK);
  404.     }    
  405. /*******************************************************************************
  406. *
  407. * z8530Open - Set the modem control lines 
  408. *
  409. * Set the modem control lines(RTS, DTR) TRUE if not already set.  
  410. * It also clears the receiver, transmitter and enables the fifo. 
  411. *
  412. * RETURNS: OK
  413. */
  414. LOCAL STATUS z8530Open
  415.     (
  416.     Z8530_CHAN * pChan          /* pointer to channel */
  417.     )
  418.     {
  419.     volatile    char *cr = pChan->cr;   /* SCC control reg adr */
  420.     FAST int     oldlevel;              /* current interrupt level mask */
  421.     char mask;
  422.     mask = pChan->writeReg5 & (SCC_WR5_DTR | SCC_WR5_RTS);
  423.     if (mask != (char)(SCC_WR5_DTR | SCC_WR5_RTS)) 
  424.         {
  425.         /* RTS and DTR not set yet */
  426.         pChan->writeReg5 |= (SCC_WR5_DTR | SCC_WR5_RTS);
  427.         oldlevel = intLock ();
  428.         /* set RTS and DTR TRUE */
  429.         REG_8530_WRITE(cr, SCC_WR0_SEL_WR5);     
  430.         REG_8530_WRITE(cr, pChan->writeReg5);
  431.         intUnlock (oldlevel);
  432.         }
  433.     return (OK);
  434.     }
  435. /*******************************************************************************
  436. *
  437. * z8530OptsSet - set the serial options
  438. *
  439. * Set the channel operating mode to that specified.  All sioLib options
  440. * are supported: CLOCAL, HUPCL, CREAD, CSIZE, PARENB, and PARODD.
  441. *
  442. * RETURNS:
  443. * Returns OK to indicate success, otherwise ERROR is returned
  444. */
  445. LOCAL STATUS z8530OptsSet
  446.     (
  447.     Z8530_CHAN * pChan,                 /* pointer to channel */
  448.     UINT options                        /* new hardware options */
  449.     )
  450.     {
  451.     FAST int    oldlevel;               /* current interrupt level mask */
  452.     volatile    char *cr = pChan->cr;   /* SCC control reg adr */
  453.     UINT8       wreg3, wreg4, wreg5;
  454.     wreg3 = wreg4 = wreg5 = 0;
  455.     
  456.     if (pChan == NULL || options & 0xffffff00)
  457.         return ERROR;
  458.     switch (options & CSIZE)
  459.         {
  460.         case CS5:
  461.             wreg3 = SCC_WR3_RX_5_BITS; /* select receive 5 bit data size */
  462.             wreg5 = SCC_WR5_TX_5_BITS; /* select transmit 5 bit data size */
  463.             break;
  464.         case CS6:
  465.             wreg3 = SCC_WR3_RX_6_BITS; /* select receive 6 bit data size */
  466.             wreg5 = SCC_WR5_TX_6_BITS; /* select transmit 6 bit data size */
  467.             break;
  468.         case CS7:
  469.             wreg3 = SCC_WR3_RX_7_BITS; /* select receive 7 bit data size */
  470.             wreg5 = SCC_WR5_TX_7_BITS; /* select transmit 7 bit data size */
  471.             break;
  472.         default:
  473.         case CS8:
  474.             wreg3 = SCC_WR3_RX_8_BITS; /* select receive 8 bit data size */ 
  475.             wreg5 = SCC_WR5_TX_8_BITS; /* select transmit 8 bit data size */
  476.             break;
  477.         }
  478.     if (options & STOPB)
  479.         wreg4 = SCC_WR4_2_STOP;         /* select 2 stop bits */
  480.     else
  481.         wreg4 = SCC_WR4_1_STOP;         /* select one stop bit */
  482.     
  483.     switch (options & (PARENB | PARODD))
  484.         {
  485.         case PARENB|PARODD:
  486.             wreg4 |= SCC_WR4_PAR_EN;
  487.             break;
  488.         case PARENB:
  489.             wreg4 |= (SCC_WR4_PAR_EN | SCC_WR4_PAR_EVEN);
  490.             break;
  491.         default:
  492.         case 0:
  493.             wreg4 &= (~SCC_WR4_PAR_EN);
  494.             break;
  495.         }
  496.     if (!(options & CLOCAL))
  497.         {
  498.         /* !clocal enables hardware flow control(DTR/DSR) */
  499.         wreg3 |= SCC_WR3_AUTO_EN;
  500.         wreg5 |= (unsigned char)(SCC_WR5_DTR | SCC_WR5_RTS);
  501.         }
  502.     if (options & CREAD)  
  503.         wreg3 |= SCC_WR3_RX_EN;
  504.     oldlevel = intLock ();
  505.     REG_8530_WRITE(cr, SCC_WR0_SEL_WR1); /* no interrupts */
  506.     REG_8530_WRITE(cr, 0);
  507.     REG_8530_WRITE(cr, SCC_WR0_ERR_RST);
  508.     REG_8530_WRITE(cr, SCC_WR0_RST_INT);
  509.     REG_8530_WRITE(cr, SCC_WR0_SEL_WR9); /* write register 9 - mstr int ctrl */
  510.     REG_8530_WRITE(cr, ((pChan->channel == SCC_CHANNEL_A) ?
  511.            SCC_WR9_CH_A_RST :           /* reset channel A */
  512.            SCC_WR9_CH_B_RST));          /* reset channel B */
  513.     REG_8530_WRITE(cr, SCC_WR0_SEL_WR4); /* write reg 4 - misc parms & modes */
  514.     REG_8530_WRITE(cr, (wreg4 | SCC_WR4_16_CLOCK));
  515.     wreg5 |= SCC_WR5_TX_EN;
  516.     REG_8530_WRITE(cr, SCC_WR0_SEL_WR5); /* tx params */
  517.     REG_8530_WRITE(cr, wreg5);
  518.     if (pChan->mode == SIO_MODE_INT)
  519.         {
  520.         REG_8530_WRITE(cr, SCC_WR0_SEL_WR1); /* int and xfer mode */
  521.         REG_8530_WRITE(cr, (SCC_WR1_INT_ALL_RX | SCC_WR1_TX_INT_EN));
  522.         /* re-enable interrupts */
  523.         REG_8530_WRITE(cr, SCC_WR0_SEL_WR9); /* master interrupt control */
  524.         REG_8530_WRITE(cr, (SCC_WR9_MIE | pChan->intType));
  525.         }
  526.     REG_8530_WRITE(cr, SCC_WR0_SEL_WR3); /* write reg 3 - receive params */
  527.     REG_8530_WRITE(cr, (unsigned char)wreg3);
  528.     intUnlock (oldlevel);
  529.     pChan->options   = options;           /* save new options */
  530.     pChan->writeReg5 = wreg5;
  531.     return OK;
  532.     }
  533. /*******************************************************************************
  534. *
  535. * z8530Ioctl - special device control
  536. *
  537. * This is a general access routine to special device- and driver-specific
  538. * functions and services.
  539. *
  540. * RETURNS: OK on success, EIO on device error, ENOSYS on unsupported request.
  541. */
  542. static int z8530Ioctl
  543.     (
  544.     SIO_CHAN * pSioChan, /* device to control */
  545.     int request, /* request code */
  546.     void * someArg /* some argument */
  547.     )
  548.     {
  549.     Z8530_CHAN *    pChan = (Z8530_CHAN *) pSioChan;
  550.     int             oldlevel; /* current interrupt level mask */
  551.     int             baudConstant;
  552.     volatile char * cr; /* SCC control reg adr */
  553.     int             arg = (int)someArg;
  554.     switch (request)
  555. {
  556. case SIO_BAUD_SET:
  557.     if (arg < 50 || arg > 38400)  /* illegal baud rate */
  558.         {
  559. return (EIO);
  560.         }
  561.             if (pChan->baudRate == arg)   /* current baud = requested baud */
  562.                 {
  563.                 return (OK);
  564.                 }
  565.     /*
  566.      * Calculate the baud rate constant for the new baud rate
  567.      * from the input clock (PCLK) frequency.  This assumes that the
  568.      * divide-by-16 bit is set in the Z8530 WR4 register (done in
  569.      * tyCoInitChannel).
  570.      */
  571.     baudConstant = ((pChan->baudFreq / 32) / arg) - 2;
  572.     cr = pChan->cr;
  573.     /* disable interrupts during chip access */
  574.     oldlevel = intLock ();
  575.     /* set the new baud rate */
  576.     REG_8530_WRITE(cr, SCC_WR0_SEL_WR12); /* LSB of baud constant */
  577.     REG_8530_WRITE(cr, (char)baudConstant);
  578.     REG_8530_WRITE(cr, SCC_WR0_SEL_WR13); /* MSB of baud constant */
  579.     REG_8530_WRITE(cr, (char)(baudConstant >> 8));
  580.     /* record new baud rate in channel control block */
  581.     pChan->baudRate = arg;
  582.     /* re-enable interrupts */
  583.     intUnlock (oldlevel);
  584.     return (OK);
  585. case SIO_BAUD_GET:
  586.     *(int *)arg = pChan->baudRate;  /* return current baud rate */
  587.     return (OK);
  588. case SIO_MODE_SET:
  589.     return (z8530ModeSet (pChan, arg) == OK ? OK : EIO);
  590. case SIO_MODE_GET:
  591.     *(int *)arg = pChan->mode;      /* return current SIO mode */
  592.     return (OK);
  593. case SIO_AVAIL_MODES_GET:
  594.     *(int *)arg = SIO_MODE_INT | SIO_MODE_POLL;
  595.     return (OK);
  596. case SIO_HW_OPTS_SET:
  597.             return ((z8530OptsSet (pChan, arg) == OK) ? OK : EIO);
  598.             break;
  599. case SIO_HW_OPTS_GET:
  600.             *(int *)arg = pChan->options;
  601.             break;
  602.         case SIO_HUP:
  603.             /* check if hupcl option is enabled */
  604.             if (pChan->options & HUPCL) 
  605.                 return (z8530Hup (pChan));
  606.             break;
  607.         case SIO_OPEN:
  608.             /* check if hupcl option is enabled */
  609.             if (pChan->options & HUPCL) 
  610.                 return (z8530Open (pChan));
  611.             break;
  612. default:
  613.     return (ENOSYS);
  614. }
  615. return (OK);
  616.     }
  617. /******************************************************************************
  618. *
  619. * z8530DevInit - intialize a Z8530_DUSART
  620. *
  621. * The BSP must have already initialized all the device addresses, etc in
  622. * Z8530_DUSART structure.  This routine initializes some SIO_CHAN
  623. * function pointers and then resets the chip to a quiescent state.
  624. *
  625. * RETURNS: N/A
  626. */
  627. void z8530DevInit
  628.     (
  629.     Z8530_DUSART * pDusart
  630.     )
  631.     {
  632.     /* disable interrupts during initialization */
  633.     int oldlevel = intLock();
  634.     /* initialize the driver function pointers in the SIO_CHAN's */
  635.     pDusart->portA.pDrvFuncs = &z8530SioDrvFuncs;
  636.     pDusart->portB.pDrvFuncs = &z8530SioDrvFuncs;
  637.     /* set the non BSP-specific constants */
  638.     pDusart->portA.baudRate = Z8530_DEFAULT_BAUD;
  639.     pDusart->portA.channel = SCC_CHANNEL_A;
  640.     pDusart->portA.getTxChar = z8530DummyCallback;
  641.     pDusart->portA.putRcvChar = z8530DummyCallback;
  642.     pDusart->portA.mode = 0; /* undefined */
  643.     pDusart->portA.options = Z8530_DEFAULT_OPTIONS;
  644.     pDusart->portB.baudRate = Z8530_DEFAULT_BAUD;
  645.     pDusart->portB.channel = SCC_CHANNEL_B;
  646.     pDusart->portB.getTxChar = z8530DummyCallback;
  647.     pDusart->portB.putRcvChar = z8530DummyCallback;
  648.     pDusart->portB.mode = 0; /* undefined */
  649.     pDusart->portB.options = Z8530_DEFAULT_OPTIONS;
  650.     /* reset the chip */
  651.     z8530InitChannel(&pDusart->portA);
  652.     z8530InitChannel(&pDusart->portB);
  653.     intUnlock(oldlevel);
  654.     }
  655. /*******************************************************************************
  656. *
  657. * z8530IntWr - handle a transmitter interrupt
  658. *
  659. * This routine handles write interrupts from the SCC.
  660. *
  661. * RETURNS: N/A
  662. */
  663. void z8530IntWr
  664.     (
  665.     Z8530_CHAN * pChan
  666.     )
  667.     {
  668.     char            outChar;
  669.     volatile char * cr = pChan->cr;
  670. #ifdef DATA_REG_8530_DIRECT
  671.     volatile char * dr = pChan->dr;
  672. #endif  /* DATA_REG_8530_DIRECT */
  673.     /* if a char is available, transmit it */
  674.     if ((*pChan->getTxChar) (pChan->getTxArg, &outChar) != ERROR)
  675. {
  676. #ifndef DATA_REG_8530_DIRECT
  677. REG_8530_WRITE(cr, SCC_WR0_SEL_WR8); /* select data register */
  678. REG_8530_WRITE(cr, outChar);
  679. #else
  680. REG_8530_WRITE(dr, outChar);
  681. #endif  /* DATA_REG_8530_DIRECT */
  682. }
  683.     /* else, reset tx interrupts */
  684.     else
  685. REG_8530_WRITE(cr, SCC_WR0_RST_TX_INT);
  686.     /* reset the interrupt */
  687.     REG_8530_WRITE(cr, SCC_WR0_RST_HI_IUS);
  688.     }
  689. /*****************************************************************************
  690. *
  691. * z8530IntRd - handle a reciever interrupt
  692. *
  693. * This routine handles read interrupts from the SCC.
  694. *
  695. * RETURNS: N/A
  696. */
  697. void z8530IntRd
  698.     (
  699.     Z8530_CHAN * pChan
  700.     )
  701.     {
  702.     volatile char * cr = pChan->cr;
  703.     volatile char   inchar;
  704. #ifdef DATA_REG_8530_DIRECT
  705.     volatile char * dr = pChan->dr;
  706. #endif  /* DATA_REG_8530_DIRECT */
  707.     BOOL            rx = FALSE;
  708.     /* reset the interrupt in the Z8530 */
  709.     REG_8530_WRITE(cr, SCC_WR0_RST_HI_IUS);
  710.     /*
  711.      * Receiver is FIFO based so there may be more than one char to read.
  712.      * Loop here until all chars are read.
  713.      */
  714.     do
  715.         {
  716.         /* see if character is valid, if not just read and discard it */
  717.         REG_8530_WRITE(cr, SCC_WR0_SEL_WR1); /* read register 1 */
  718.         REG_8530_READ(cr, &inchar);
  719.         if ((inchar & (SCC_RR1_CRC_ERR   |  /* framing error */
  720.        SCC_RR1_RX_OV_ERR |  /* receive overrun */
  721.        SCC_RR1_PAR_ERR))    /* parity error */
  722.     == 0)
  723.             rx = TRUE;
  724.         else
  725.             rx = FALSE;
  726.         /* read the received character */
  727. #ifndef DATA_REG_8530_DIRECT
  728.         REG_8530_WRITE(cr, SCC_WR0_SEL_WR8); /* select data register */
  729.         REG_8530_READ(cr, &inchar);
  730. #else
  731.         REG_8530_READ(dr, &inchar);
  732. #endif  /* DATA_REG_8530_DIRECT */
  733.         /* do callback if valid char */
  734.         if (rx)
  735.     (*pChan->putRcvChar) (pChan->putRcvArg, inchar);
  736.         /* See if more chars available */
  737.         REG_8530_READ(cr, &inchar);
  738.         } while (inchar & SCC_RR0_RX_AVAIL);
  739.     }
  740. /**********************************************************************
  741. *
  742. * z8530IntEx - handle error interrupts
  743. *
  744. * This routine handles miscellaneous interrupts on the SCC.
  745. *
  746. * RETURNS: N/A
  747. */
  748. void z8530IntEx
  749.     (
  750.     Z8530_CHAN * pChan
  751.     )
  752.     {
  753.     volatile char * cr = pChan->cr;
  754.     char            charStatus;
  755.     /* if Tx Underrun, reset it */
  756.     REG_8530_WRITE(cr, SCC_WR0_SEL_WR0); /* read register 0 */
  757.     REG_8530_READ(cr, &charStatus);
  758.     if (charStatus & SCC_RR0_TX_UND)
  759. REG_8530_WRITE(cr, SCC_WR0_RST_TX_UND);
  760.     REG_8530_WRITE(cr, SCC_WR0_ERR_RST); /* reset errors */
  761.     REG_8530_WRITE(cr, SCC_WR0_RST_INT); /* reset ext/status interrupt */
  762.     REG_8530_WRITE(cr, SCC_WR0_RST_HI_IUS); /* reset the interrupt */
  763.     }
  764. /********************************************************************************
  765. * z8530Int - handle all interrupts in one vector
  766. *
  767. * On some boards, all SCC interrupts for both ports share a single interrupt
  768. * vector. This is the ISR for such boards.
  769. * We determine from the parameter which SCC interrupted, then look at
  770. * the code to find out which channel and what kind of interrupt.
  771. *
  772. * RETURNS: N/A
  773. */
  774. void z8530Int
  775.     (
  776.     Z8530_DUSART * pDusart
  777.     )
  778.     {
  779.     volatile char * crA;
  780.     volatile char * crB;
  781.     Z8530_CHAN *    pChanA;
  782.     Z8530_CHAN *    pChanB;
  783.     char            intStatus;
  784.     char            charStatus;
  785.     char            thisCharA;
  786.     char            thisCharB;
  787.     BOOL            rxA = FALSE;
  788.     BOOL            rxB = FALSE;
  789. #ifdef DATA_REG_8530_DIRECT
  790.     volatile char * drA;
  791.     volatile char * drB;
  792. #endif  /* DATA_REG_8530_DIRECT */
  793.     /*
  794.      * We need to find out if the SCC interrupted.  We need to read
  795.      * the A channel of the SCC to find out if there are any pending
  796.      * interrupts.  Note that things are set up so that the A
  797.      * channel is channel 0, even though on the chip it is the one with
  798.      * the higher address.
  799.      */  
  800.     pChanA = &pDusart->portA; /* Load ch A control reg address */
  801.     crA    = pChanA->cr;
  802.     /* get pending interrupt flags from Z8530 (found only in ch A) */
  803.     REG_8530_WRITE(crA, SCC_WR0_SEL_WR3); /* read reg 3 */
  804.     REG_8530_READ(crA, &intStatus);
  805.     /* If no interrupt pending, interrupt was not from us; return immediately */
  806.     if (intStatus == 0)
  807.       return;
  808.     /* our interrupt; handle all pending interrupts */
  809.     pChanB = &pDusart->portB; /* Load ch B control reg address */
  810.     crB    = pChanB->cr;
  811. #ifdef DATA_REG_8530_DIRECT
  812.     drA = pChanA->dr;
  813.     drB = pChanB->dr;
  814. #endif  /* DATA_REG_8530_DIRECT */
  815.     /*
  816.      * service the interrupt by type with Tx ints being highest priority
  817.      * and ch A having priority over B.  Ignore Special Receive Conditions.
  818.      */
  819.     /* ch A Tx READY */
  820.     if ((intStatus & SCC_RR3_A_TX_IP) != 0)
  821.         {
  822. /* Either output the next character, */
  823. if ((*pChanA->getTxChar) (pChanA->getTxArg, &thisCharA) != ERROR)
  824.     {
  825. #ifndef DATA_REG_8530_DIRECT
  826.     REG_8530_WRITE(crA, SCC_WR0_SEL_WR8); /* select data register */
  827.             REG_8530_WRITE(crA, thisCharA);
  828. #else
  829.             REG_8530_WRITE(drA, thisCharA);
  830. #endif  /* DATA_REG_8530_DIRECT */
  831.     }
  832. /* or reset/stop the tx. */
  833.         else
  834.     REG_8530_WRITE(crA, SCC_WR0_RST_TX_INT);
  835. /* update interrupt status */
  836. intStatus &= ~SCC_RR3_A_TX_IP;
  837.         }
  838.  
  839.     /* ch B Tx READY */
  840.     if ((intStatus & SCC_RR3_B_TX_IP) != 0)
  841.         {
  842. /* Either output the next character, */
  843. if ((*pChanB->getTxChar) (pChanB->getTxArg, &thisCharB) != ERROR)
  844.     {
  845. #ifndef DATA_REG_8530_DIRECT
  846.     REG_8530_WRITE(crB, SCC_WR0_SEL_WR8); /* select data register */
  847.             REG_8530_WRITE(crB, thisCharB);
  848. #else
  849.             REG_8530_WRITE(drB, thisCharB);
  850. #endif  /* DATA_REG_8530_DIRECT */
  851.     }
  852. /* or reset/stop the tx. */
  853.         else
  854.     REG_8530_WRITE(crB, SCC_WR0_RST_TX_INT);
  855. /* update interrupt status */
  856. intStatus &= ~SCC_RR3_B_TX_IP;
  857.         }
  858.  
  859.     /* ch A Rx CHAR AVAILABLE */
  860.     if ((intStatus & SCC_RR3_A_RX_IP) != 0)
  861.         {
  862. /*
  863.  * Receiver is FIFO based so there may be more than one char to read.
  864.  * Loop here until all chars are read.
  865.  */
  866. do
  867.     {
  868.     /* see if character is valid, if not just read and discard it */
  869.     REG_8530_WRITE(crA, SCC_WR0_SEL_WR1); /* read register 1 */
  870.     REG_8530_READ(crA, &charStatus);
  871.     if ((charStatus & (SCC_RR1_CRC_ERR   |  /* framing error */
  872.        SCC_RR1_RX_OV_ERR |  /* receive overrun */
  873.        SCC_RR1_PAR_ERR))    /* parity error */
  874.         == 0)
  875.         rxA = TRUE;
  876.     else
  877. {
  878. rxA = FALSE;
  879.                 REG_8530_WRITE(crA, SCC_WR0_ERR_RST);  /* reset error */
  880. }
  881.     /* read the received character */
  882. #ifndef DATA_REG_8530_DIRECT
  883.     REG_8530_WRITE(crA, SCC_WR0_SEL_WR8); /* select data register */
  884.     REG_8530_READ(crA, &thisCharA);
  885. #else
  886.     REG_8530_READ(drA, &thisCharA);
  887. #endif  /* DATA_REG_8530_DIRECT */
  888.     /* do callback if valid char */
  889.     if (rxA)
  890. (*pChanA->putRcvChar) (pChanA->putRcvArg, thisCharA);
  891.     /* See if more chars available */
  892.     REG_8530_READ(crA, &charStatus);
  893.     } while (charStatus & SCC_RR0_RX_AVAIL);
  894. /* update interrupt status */
  895. intStatus &= ~SCC_RR3_A_RX_IP;
  896.         }
  897.  
  898.     /* ch B Rx CHAR AVAILABLE */
  899.     if ((intStatus & SCC_RR3_B_RX_IP) != 0)
  900.         {
  901. /*
  902.  * Receiver is FIFO based so there may be more than one char to read.
  903.  * Loop here until all chars are read.
  904.  */
  905. do
  906.     {
  907.     /* see if character is valid, if not just read and discard it */
  908.     REG_8530_WRITE(crB, SCC_WR0_SEL_WR1); /* read register 1 */
  909.     REG_8530_READ(crB, &charStatus);
  910.     if ((charStatus & (SCC_RR1_CRC_ERR   |  /* framing error */
  911.        SCC_RR1_RX_OV_ERR |  /* receive overrun */
  912.        SCC_RR1_PAR_ERR))    /* parity error */
  913.         == 0)
  914.         rxB = TRUE;
  915.     else
  916. {
  917. rxB = FALSE;
  918.                 REG_8530_WRITE(crB, SCC_WR0_ERR_RST);  /* reset error */
  919. }
  920.     /* read the received character */
  921. #ifndef DATA_REG_8530_DIRECT
  922.     REG_8530_WRITE(crB, SCC_WR0_SEL_WR8); /* select data register */
  923.     REG_8530_READ(crB, &thisCharB);
  924. #else
  925.     REG_8530_READ(drB, &thisCharB);
  926. #endif  /* DATA_REG_8530_DIRECT */
  927.     /* do callback if valid char */
  928.     if (rxB)
  929. (*pChanB->putRcvChar) (pChanB->putRcvArg, thisCharB);
  930.     /* See if more chars available */
  931.     REG_8530_READ(crB, &charStatus);
  932.     } while (charStatus & SCC_RR0_RX_AVAIL);
  933. /* update interrupt status */
  934. intStatus &= ~SCC_RR3_B_RX_IP;
  935.         }
  936.  
  937.     /* ch A EXTERNAL STATUS CHANGE */
  938.     if ((intStatus & SCC_RR3_A_EXT_IP) != 0)
  939.         {
  940. /* if Tx Underrun, reset it */
  941.         REG_8530_WRITE(crA, SCC_WR0_SEL_WR0); /* read register 0 */
  942.         REG_8530_READ(crA, &charStatus);
  943. if (charStatus & SCC_RR0_TX_UND)
  944.     REG_8530_WRITE(crA, SCC_WR0_RST_TX_UND);
  945. /* reset ext/status interrupt */
  946.         REG_8530_WRITE(crA, SCC_WR0_RST_INT);
  947.         }
  948.  
  949.     /* ch B EXTERNAL STATUS CHANGE */
  950.     if ((intStatus & SCC_RR3_B_EXT_IP) != 0)
  951.         {
  952. /* if Tx Underrun, reset it */
  953.         REG_8530_WRITE(crB, SCC_WR0_SEL_WR0); /* read register 0 */
  954.         REG_8530_READ(crB, &charStatus);
  955. if (charStatus & SCC_RR0_TX_UND)
  956.     REG_8530_WRITE(crB, SCC_WR0_RST_TX_UND);
  957. /* reset ext/status interrupt */
  958.         REG_8530_WRITE(crB, SCC_WR0_RST_INT);
  959.         }
  960.  
  961.     /* reset any error condition */
  962.     REG_8530_WRITE(crA, SCC_WR0_ERR_RST);
  963.     /* Reset the interrupt in the Z8530 */
  964.     REG_8530_WRITE(crA, SCC_WR0_RST_HI_IUS);
  965.     }