Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:05

0001 /*
0002  *  This file contains the console driver chip level routines for the
0003  *  Zilog z85c30 chip.
0004  *
0005  *  The Zilog Z8530 is also available as:
0006  *
0007  *    + Intel 82530
0008  *    + AMD ???
0009  *
0010  *  COPYRIGHT (c) 1998 by Radstone Technology
0011  *
0012  *
0013  * THIS FILE IS PROVIDED TO YOU, THE USER, "AS IS", WITHOUT WARRANTY OF ANY
0014  * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
0015  * IMPLIED WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK
0016  * AS TO THE QUALITY AND PERFORMANCE OF ALL CODE IN THIS FILE IS WITH YOU.
0017  *
0018  * You are hereby granted permission to use, copy, modify, and distribute
0019  * this file, provided that this notice, plus the above copyright notice
0020  * and disclaimer, appears in all copies. Radstone Technology will provide
0021  * no support for this code.
0022  *
0023  *  COPYRIGHT (c) 1989-1997.
0024  *  On-Line Applications Research Corporation (OAR).
0025  *
0026  *  The license and distribution terms for this file may be
0027  *  found in the file LICENSE in this distribution or at
0028  *  http://www.rtems.org/license/LICENSE.
0029  */
0030 
0031 #include <rtems.h>
0032 #include <rtems/libio.h>
0033 #include <rtems/score/sysstate.h>
0034 #include <stdlib.h>
0035 
0036 #include <libchip/serial.h>
0037 #include <libchip/sersupp.h>
0038 #include "z85c30_p.h"
0039 
0040 /*
0041  * Flow control is only supported when using interrupts
0042  */
0043 
0044 const console_flow z85c30_flow_RTSCTS = {
0045   z85c30_negate_RTS,    /* deviceStopRemoteTx */
0046   z85c30_assert_RTS     /* deviceStartRemoteTx */
0047 };
0048 
0049 const console_flow z85c30_flow_DTRCTS = {
0050   z85c30_negate_DTR,    /* deviceStopRemoteTx */
0051   z85c30_assert_DTR     /* deviceStartRemoteTx */
0052 };
0053 
0054 /*
0055  * Exported driver function table
0056  */
0057 
0058 const console_fns z85c30_fns = {
0059   libchip_serial_default_probe,  /* deviceProbe */
0060   z85c30_open,                   /* deviceFirstOpen */
0061   NULL,                          /* deviceLastClose */
0062   NULL,                          /* deviceRead */
0063   z85c30_write_support_int,      /* deviceWrite */
0064   z85c30_initialize_interrupts,  /* deviceInitialize */
0065   z85c30_write_polled,           /* deviceWritePolled */
0066   NULL,                          /* deviceSetAttributes */
0067   true                           /* deviceOutputUsesInterrupts */
0068 };
0069 
0070 const console_fns z85c30_fns_polled = {
0071   libchip_serial_default_probe,      /* deviceProbe */
0072   z85c30_open,                       /* deviceFirstOpen */
0073   z85c30_close,                      /* deviceLastClose */
0074   z85c30_inbyte_nonblocking_polled,  /* deviceRead */
0075   z85c30_write_support_polled,       /* deviceWrite */
0076   z85c30_init,                       /* deviceInitialize */
0077   z85c30_write_polled,               /* deviceWritePolled */
0078   NULL,                              /* deviceSetAttributes */
0079   false                              /* deviceOutputUsesInterrupts */
0080 };
0081 
0082 #if (CPU_SIMPLE_VECTORED_INTERRUPTS == TRUE)
0083   extern void set_vector( rtems_isr_entry, rtems_vector_number, int );
0084 #endif
0085 
0086 /*
0087  *  z85c30_initialize_port
0088  *
0089  *  initialize a z85c30 Port
0090  */
0091 
0092 Z85C30_STATIC void z85c30_initialize_port(
0093   int minor
0094 )
0095 {
0096   uintptr_t       ulCtrlPort;
0097   uintptr_t       ulBaudDivisor;
0098   setRegister_f   setReg;
0099 
0100   ulCtrlPort = Console_Port_Tbl[minor]->ulCtrlPort1;
0101   setReg   = Console_Port_Tbl[minor]->setRegister;
0102 
0103   /*
0104    * Using register 4
0105    * Set up the clock rate is 16 times the data
0106    * rate, 8 bit sync char, 1 stop bit, no parity
0107    */
0108 
0109   (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR4, SCC_WR4_1_STOP | SCC_WR4_16_CLOCK );
0110 
0111   /*
0112    * Set up for 8 bits/character on receive with
0113    * receiver disable via register 3
0114    */
0115   (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR3, SCC_WR3_RX_8_BITS );
0116 
0117   /*
0118    * Set up for 8 bits/character on transmit
0119    * with transmitter disable via register 5
0120    */
0121   (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR5, SCC_WR5_TX_8_BITS );
0122 
0123   /*
0124    * Clear misc control bits
0125    */
0126   (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR10, 0x00 );
0127 
0128   /*
0129    * Setup the source of the receive and xmit
0130    * clock as BRG output and the transmit clock
0131    * as the output source for TRxC pin via register 11
0132    */
0133   (*setReg)(
0134     ulCtrlPort,
0135     SCC_WR0_SEL_WR11,
0136     SCC_WR11_OUT_BR_GEN | SCC_WR11_TRXC_OI |
0137       SCC_WR11_TX_BR_GEN | SCC_WR11_RX_BR_GEN
0138   );
0139 
0140   ulBaudDivisor = Z85C30_Baud(
0141     (uint32_t) Console_Port_Tbl[minor]->ulClock,
0142     (uint32_t) ((uintptr_t)Console_Port_Tbl[minor]->pDeviceParams)
0143   );
0144 
0145   /*
0146    * Setup the lower 8 bits time constants=1E.
0147    * If the time constans=1E, then the desire
0148    * baud rate will be equilvalent to 9600, via register 12.
0149    */
0150   (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR12, ulBaudDivisor & 0xff );
0151 
0152   /*
0153    * using register 13
0154    * Setup the upper 8 bits time constant
0155    */
0156   (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR13, (ulBaudDivisor>>8) & 0xff );
0157 
0158   /*
0159    * Enable the baud rate generator enable with clock from the
0160    * SCC's PCLK input via register 14.
0161    */
0162   (*setReg)(
0163     ulCtrlPort,
0164     SCC_WR0_SEL_WR14,
0165     SCC_WR14_BR_EN | SCC_WR14_BR_SRC | SCC_WR14_NULL
0166   );
0167 
0168   /*
0169    * We are only interested in CTS state changes
0170    */
0171   (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR15, SCC_WR15_CTS_IE );
0172 
0173   /*
0174    * Reset errors
0175    */
0176   (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_INT );
0177 
0178   (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_ERR_RST );
0179 
0180   /*
0181    * Enable the receiver via register 3
0182    */
0183   (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR3, SCC_WR3_RX_8_BITS | SCC_WR3_RX_EN );
0184 
0185   /*
0186    * Enable the transmitter pins set via register 5.
0187    */
0188   (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR5, SCC_WR5_TX_8_BITS | SCC_WR5_TX_EN );
0189 
0190   /*
0191    * Disable interrupts
0192    */
0193   (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR1, 0 );
0194 
0195   /*
0196    * Reset TX CRC
0197    */
0198   (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_TX_CRC );
0199 
0200   /*
0201    * Reset interrupts
0202    */
0203   (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_INT );
0204 }
0205 
0206 /*
0207  *  z85c30_open
0208  */
0209 
0210 Z85C30_STATIC int z85c30_open(
0211   int   major,
0212   int   minor,
0213   void *arg
0214 )
0215 {
0216 
0217   z85c30_initialize_port(minor);
0218 
0219   /*
0220    * Assert DTR
0221    */
0222 
0223   if (Console_Port_Tbl[minor]->pDeviceFlow !=&z85c30_flow_DTRCTS) {
0224     z85c30_assert_DTR(minor);
0225   }
0226 
0227   return(RTEMS_SUCCESSFUL);
0228 }
0229 
0230 /*
0231  *  z85c30_close
0232  */
0233 
0234 Z85C30_STATIC int z85c30_close(
0235   int   major,
0236   int   minor,
0237   void *arg
0238 )
0239 {
0240   /*
0241    * Negate DTR
0242    */
0243 
0244   if (Console_Port_Tbl[minor]->pDeviceFlow !=&z85c30_flow_DTRCTS) {
0245     z85c30_negate_DTR(minor);
0246   }
0247 
0248   return(RTEMS_SUCCESSFUL);
0249 }
0250 
0251 /*
0252  *  z85c30_init
0253  */
0254 
0255 Z85C30_STATIC void z85c30_init(int minor)
0256 {
0257   uintptr_t        ulCtrlPort;
0258   z85c30_context  *pz85c30Context;
0259   setRegister_f    setReg;
0260   getRegister_f    getReg;
0261 
0262   ulCtrlPort = Console_Port_Tbl[minor]->ulCtrlPort1;
0263   setReg     = Console_Port_Tbl[minor]->setRegister;
0264   getReg     = Console_Port_Tbl[minor]->getRegister;
0265 
0266   pz85c30Context = (z85c30_context *)malloc(sizeof(z85c30_context));
0267 
0268   Console_Port_Data[minor].pDeviceContext = (void *)pz85c30Context;
0269 
0270   pz85c30Context->ucModemCtrl = SCC_WR5_TX_8_BITS | SCC_WR5_TX_EN;
0271 
0272   if ( ulCtrlPort == Console_Port_Tbl[minor]->ulCtrlPort2 ) {
0273     /*
0274      * This is channel A
0275      */
0276     /*
0277      * Ensure port state machine is reset
0278      */
0279     (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0);
0280 
0281     (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR9, SCC_WR9_CH_A_RST);
0282 
0283   } else {
0284     /*
0285      * This is channel B
0286      */
0287     /*
0288      * Ensure port state machine is reset
0289      */
0290     (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0);
0291 
0292     (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR9, SCC_WR9_CH_B_RST);
0293   }
0294 }
0295 
0296 /*
0297  * These routines provide control of the RTS and DTR lines
0298  */
0299 
0300 /*
0301  *  z85c30_assert_RTS
0302  */
0303 
0304 Z85C30_STATIC int z85c30_assert_RTS(int minor)
0305 {
0306   rtems_interrupt_level  Irql;
0307   z85c30_context        *pz85c30Context;
0308   setRegister_f          setReg;
0309 
0310   setReg = Console_Port_Tbl[minor]->setRegister;
0311 
0312   pz85c30Context = (z85c30_context *) Console_Port_Data[minor].pDeviceContext;
0313 
0314   /*
0315    * Assert RTS
0316    */
0317 
0318   rtems_interrupt_disable(Irql);
0319     pz85c30Context->ucModemCtrl|=SCC_WR5_RTS;
0320     (*setReg)(
0321       Console_Port_Tbl[minor]->ulCtrlPort1,
0322       SCC_WR0_SEL_WR5,
0323       pz85c30Context->ucModemCtrl
0324     );
0325   rtems_interrupt_enable(Irql);
0326   return 0;
0327 }
0328 
0329 /*
0330  *  z85c30_negate_RTS
0331  */
0332 
0333 Z85C30_STATIC int z85c30_negate_RTS(int minor)
0334 {
0335   rtems_interrupt_level  Irql;
0336   z85c30_context        *pz85c30Context;
0337   setRegister_f          setReg;
0338 
0339   setReg = Console_Port_Tbl[minor]->setRegister;
0340 
0341   pz85c30Context = (z85c30_context *) Console_Port_Data[minor].pDeviceContext;
0342 
0343   /*
0344    * Negate RTS
0345    */
0346 
0347   rtems_interrupt_disable(Irql);
0348     pz85c30Context->ucModemCtrl&=~SCC_WR5_RTS;
0349     (*setReg)(
0350       Console_Port_Tbl[minor]->ulCtrlPort1,
0351       SCC_WR0_SEL_WR5,
0352       pz85c30Context->ucModemCtrl
0353     );
0354   rtems_interrupt_enable(Irql);
0355   return 0;
0356 }
0357 
0358 /*
0359  * These flow control routines utilise a connection from the local DTR
0360  * line to the remote CTS line
0361  */
0362 
0363 /*
0364  *  z85c30_assert_DTR
0365  */
0366 
0367 Z85C30_STATIC int z85c30_assert_DTR(int minor)
0368 {
0369   rtems_interrupt_level  Irql;
0370   z85c30_context        *pz85c30Context;
0371   setRegister_f          setReg;
0372 
0373   setReg = Console_Port_Tbl[minor]->setRegister;
0374 
0375   pz85c30Context = (z85c30_context *) Console_Port_Data[minor].pDeviceContext;
0376 
0377   /*
0378    * Assert DTR
0379    */
0380 
0381   rtems_interrupt_disable(Irql);
0382     pz85c30Context->ucModemCtrl|=SCC_WR5_DTR;
0383     (*setReg)(
0384       Console_Port_Tbl[minor]->ulCtrlPort1,
0385       SCC_WR0_SEL_WR5,
0386       pz85c30Context->ucModemCtrl
0387   );
0388   rtems_interrupt_enable(Irql);
0389   return 0;
0390 }
0391 
0392 /*
0393  *  z85c30_negate_DTR
0394  */
0395 
0396 Z85C30_STATIC int z85c30_negate_DTR(int minor)
0397 {
0398   rtems_interrupt_level  Irql;
0399   z85c30_context        *pz85c30Context;
0400   setRegister_f          setReg;
0401 
0402   setReg = Console_Port_Tbl[minor]->setRegister;
0403 
0404   pz85c30Context = (z85c30_context *) Console_Port_Data[minor].pDeviceContext;
0405 
0406   /*
0407    * Negate DTR
0408    */
0409 
0410   rtems_interrupt_disable(Irql);
0411     pz85c30Context->ucModemCtrl&=~SCC_WR5_DTR;
0412     (*setReg)(
0413       Console_Port_Tbl[minor]->ulCtrlPort1,
0414       SCC_WR0_SEL_WR5,
0415       pz85c30Context->ucModemCtrl
0416   );
0417   rtems_interrupt_enable(Irql);
0418   return 0;
0419 }
0420 
0421 /*
0422  *  z85c30_set_attributes
0423  *
0424  *  This function sets the SCC channel to reflect the requested termios
0425  *  port settings.
0426  */
0427 
0428 Z85C30_STATIC int z85c30_set_attributes(
0429   int                   minor,
0430   const struct termios *t
0431 )
0432 {
0433   uintptr_t              ulCtrlPort;
0434   uint32_t               ulBaudDivisor;
0435   uint32_t               wr3;
0436   uint32_t               wr4;
0437   uint32_t               wr5;
0438   int                    baud_requested;
0439   uint32_t               baud_number;
0440   setRegister_f          setReg;
0441   rtems_interrupt_level  Irql;
0442 
0443   ulCtrlPort = Console_Port_Tbl[minor]->ulCtrlPort1;
0444   setReg     = Console_Port_Tbl[minor]->setRegister;
0445 
0446   /*
0447    *  Calculate the baud rate divisor
0448    *
0449    *  Assert ensures there is no division by 0.
0450    */
0451 
0452   baud_requested = t->c_ospeed;
0453   if (!baud_requested)
0454     baud_requested = B9600;              /* default to 9600 baud */
0455 
0456   baud_number = (uint32_t) rtems_termios_baud_to_number( baud_requested );
0457   _Assert( baud_number != 0 );
0458 
0459   /*
0460    * POSIX says baud rate of zero is a request to hang up or disconnect.
0461    * This is not supported by this driver.
0462    */
0463   _Assert( baud_number != 0 );
0464   if (baud_number == 0) {
0465     return -1;
0466   }
0467 
0468   ulBaudDivisor = Z85C30_Baud(
0469     (uint32_t) Console_Port_Tbl[minor]->ulClock,
0470     baud_number
0471   );
0472 
0473   wr3 = SCC_WR3_RX_EN;
0474   wr4 = SCC_WR4_16_CLOCK;
0475   wr5 = SCC_WR5_TX_EN;
0476 
0477   /*
0478    *  Parity
0479    */
0480 
0481   if (t->c_cflag & PARENB) {
0482     wr4 |= SCC_WR4_PAR_EN;
0483     if (!(t->c_cflag & PARODD))
0484       wr4 |= SCC_WR4_PAR_EVEN;
0485   }
0486 
0487   /*
0488    *  Character Size
0489    */
0490 
0491   if (t->c_cflag & CSIZE) {
0492     switch (t->c_cflag & CSIZE) {
0493       case CS5:   break;
0494       case CS6:  wr3 |= SCC_WR3_RX_6_BITS;  wr5 |= SCC_WR5_TX_6_BITS;  break;
0495       case CS7:  wr3 |= SCC_WR3_RX_7_BITS;  wr5 |= SCC_WR5_TX_7_BITS;  break;
0496       case CS8:  wr3 |= SCC_WR3_RX_8_BITS;  wr5 |= SCC_WR5_TX_8_BITS;  break;
0497     }
0498   } else {
0499     wr3 |= SCC_WR3_RX_8_BITS;       /* default to 9600,8,N,1 */
0500     wr5 |= SCC_WR5_TX_8_BITS;       /* default to 9600,8,N,1 */
0501   }
0502 
0503   /*
0504    *  Stop Bits
0505    */
0506 
0507   if (t->c_cflag & CSTOPB) {
0508     wr4 |= SCC_WR4_2_STOP;                      /* 2 stop bits */
0509   } else {
0510     wr4 |= SCC_WR4_1_STOP;                      /* 1 stop bits */
0511   }
0512 
0513   /*
0514    *  Now actually set the chip
0515    */
0516 
0517   rtems_interrupt_disable(Irql);
0518     (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR4, wr4 );
0519     (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR3, wr3 );
0520     (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR5, wr5 );
0521 
0522     /*
0523      * Setup the lower 8 bits time constants=1E.
0524      * If the time constans=1E, then the desire
0525      * baud rate will be equilvalent to 9600, via register 12.
0526      */
0527 
0528     (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR12, ulBaudDivisor & 0xff );
0529 
0530     /*
0531      * using register 13
0532      * Setup the upper 8 bits time constant
0533      */
0534 
0535     (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR13, (ulBaudDivisor>>8) & 0xff );
0536 
0537   rtems_interrupt_enable(Irql);
0538 
0539   return 0;
0540 }
0541 
0542 /*
0543  *  z85c30_process
0544  *
0545  *  This is the per port ISR handler.
0546  */
0547 
0548 Z85C30_STATIC void z85c30_process(
0549   int        minor,
0550   uint8_t    ucIntPend
0551 )
0552 {
0553   uint32_t            ulCtrlPort;
0554   volatile uint8_t    z85c30_status;
0555   char                cChar;
0556   setRegister_f       setReg;
0557   getRegister_f       getReg;
0558 
0559   ulCtrlPort = Console_Port_Tbl[minor]->ulCtrlPort1;
0560   setReg     = Console_Port_Tbl[minor]->setRegister;
0561   getReg     = Console_Port_Tbl[minor]->getRegister;
0562 
0563   /*
0564    * Deal with any received characters
0565    */
0566 
0567   while (ucIntPend&SCC_RR3_B_RX_IP)
0568   {
0569     z85c30_status = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0);
0570     if (!Z85C30_Status_Is_RX_character_available(z85c30_status)) {
0571       break;
0572     }
0573 
0574     /*
0575      * Return the character read.
0576      */
0577 
0578     cChar = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD8);
0579 
0580     rtems_termios_enqueue_raw_characters(
0581       Console_Port_Data[minor].termios_data,
0582       &cChar,
0583       1
0584     );
0585   }
0586 
0587   /*
0588    *  There could be a race condition here if there is not yet a TX
0589    *  interrupt pending but the buffer is empty.  This condition has
0590    *  been seen before on other z8530 drivers but has not been seen
0591    *  with this one.  The typical solution is to use "vector includes
0592    *  status" or to only look at the interrupts actually pending
0593    *  in RR3.
0594    */
0595 
0596   while (true) {
0597     z85c30_status = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0);
0598     if (!Z85C30_Status_Is_TX_buffer_empty(z85c30_status)) {
0599       /*
0600        * We'll get another interrupt when
0601        * the transmitter holding reg. becomes
0602        * free again and we are clear to send
0603        */
0604       break;
0605     }
0606 
0607 #if 0
0608     if (!Z85C30_Status_Is_CTS_asserted(z85c30_status)) {
0609       /*
0610        * We can't transmit yet
0611        */
0612       (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_TX_INT);
0613       /*
0614        * The next state change of CTS will wake us up
0615        */
0616       break;
0617     }
0618 #endif
0619 
0620     rtems_termios_dequeue_characters(Console_Port_Data[minor].termios_data, 1);
0621     if (rtems_termios_dequeue_characters(
0622          Console_Port_Data[minor].termios_data, 1)) {
0623       if (Console_Port_Tbl[minor]->pDeviceFlow != &z85c30_flow_RTSCTS) {
0624         z85c30_negate_RTS(minor);
0625       }
0626       Console_Port_Data[minor].bActive = FALSE;
0627       z85c30_enable_interrupts(minor, SCC_ENABLE_ALL_INTR_EXCEPT_TX);
0628       (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_TX_INT);
0629       break;
0630     }
0631 
0632   }
0633 
0634   if (ucIntPend & SCC_RR3_B_EXT_IP) {
0635     /*
0636      * Clear the external status interrupt
0637      */
0638     (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_INT);
0639     z85c30_status = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0);
0640   }
0641 
0642   /*
0643    * Reset interrupts
0644    */
0645   (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_HI_IUS);
0646 }
0647 
0648 /*
0649  *  z85c30_isr
0650  *
0651  *  This is the ISR handler for each Z8530.
0652  */
0653 
0654 Z85C30_STATIC rtems_isr z85c30_isr(
0655   rtems_vector_number vector
0656 )
0657 {
0658   int                 minor;
0659   uint32_t            ulCtrlPort;
0660   volatile uint8_t    ucIntPend;
0661   volatile uint8_t    ucIntPendPort;
0662   getRegister_f       getReg;
0663 
0664   for (minor=0;minor<Console_Port_Count;minor++) {
0665     if(Console_Port_Tbl[minor]->ulIntVector == vector &&
0666        Console_Port_Tbl[minor]->deviceType == SERIAL_Z85C30 ) {
0667       ulCtrlPort = Console_Port_Tbl[minor]->ulCtrlPort2;
0668       getReg     = Console_Port_Tbl[minor]->getRegister;
0669       do {
0670         ucIntPend = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD3);
0671 
0672           /*
0673            * If this is channel A select channel A status
0674            */
0675 
0676           if (ulCtrlPort == Console_Port_Tbl[minor]->ulCtrlPort1) {
0677             ucIntPendPort = ucIntPend >> 3;
0678             ucIntPendPort &= 7;
0679           } else {
0680             ucIntPendPort = ucIntPend &= 7;
0681           }
0682 
0683           if (ucIntPendPort) {
0684             z85c30_process(minor, ucIntPendPort);
0685           }
0686       } while (ucIntPendPort);
0687     }
0688   }
0689 }
0690 
0691 /*
0692  *  z85c30_enable_interrupts
0693  *
0694  *  This routine enables the specified interrupts for this minor.
0695  */
0696 
0697 Z85C30_STATIC void z85c30_enable_interrupts(
0698   int minor,
0699   int interrupt_mask
0700 )
0701 {
0702   uint32_t       ulCtrlPort;
0703   setRegister_f  setReg;
0704 
0705   ulCtrlPort = Console_Port_Tbl[minor]->ulCtrlPort1;
0706   setReg     = Console_Port_Tbl[minor]->setRegister;
0707 
0708   (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR1, interrupt_mask);
0709 }
0710 
0711 /*
0712  *  z85c30_initialize_interrupts
0713  *
0714  *  This routine initializes the port to use interrupts.
0715  */
0716 
0717 Z85C30_STATIC void z85c30_initialize_interrupts(
0718   int minor
0719 )
0720 {
0721   uint32_t       ulCtrlPort1;
0722   setRegister_f  setReg;
0723 
0724   ulCtrlPort1 = Console_Port_Tbl[minor]->ulCtrlPort1;
0725   setReg      = Console_Port_Tbl[minor]->setRegister;
0726 
0727 
0728   z85c30_init(minor);
0729 
0730   Console_Port_Data[minor].bActive=FALSE;
0731 
0732   z85c30_initialize_port( minor );
0733 
0734   if (Console_Port_Tbl[minor]->pDeviceFlow != &z85c30_flow_RTSCTS) {
0735     z85c30_negate_RTS(minor);
0736   }
0737 
0738 #if (CPU_SIMPLE_VECTORED_INTERRUPTS == TRUE)
0739   set_vector(z85c30_isr, Console_Port_Tbl[minor]->ulIntVector, 1);
0740 #endif
0741 
0742   z85c30_enable_interrupts(minor, SCC_ENABLE_ALL_INTR_EXCEPT_TX);
0743 
0744   (*setReg)(ulCtrlPort1, SCC_WR0_SEL_WR2, 0);              /* XXX vector */
0745   (*setReg)(ulCtrlPort1, SCC_WR0_SEL_WR9, SCC_WR9_MIE);
0746 
0747   /*
0748    * Reset interrupts
0749    */
0750 
0751   (*setReg)(ulCtrlPort1, SCC_WR0_SEL_WR0, SCC_WR0_RST_INT);
0752 }
0753 
0754 /*
0755  *  z85c30_write_support_int
0756  *
0757  *  Console Termios output entry point.
0758  *
0759  */
0760 
0761 Z85C30_STATIC ssize_t z85c30_write_support_int(
0762   int   minor,
0763   const char *buf,
0764   size_t len)
0765 {
0766   uint32_t       Irql;
0767   uint32_t       ulCtrlPort;
0768   setRegister_f  setReg;
0769 
0770   ulCtrlPort = Console_Port_Tbl[minor]->ulCtrlPort1;
0771   setReg     = Console_Port_Tbl[minor]->setRegister;
0772 
0773   /*
0774    *  We are using interrupt driven output and termios only sends us
0775    *  one character at a time.
0776    */
0777 
0778   if ( !len )
0779     return 0;
0780 
0781   /*
0782    *  Put the character out and enable interrupts if necessary.
0783    */
0784 
0785   if (Console_Port_Tbl[minor]->pDeviceFlow != &z85c30_flow_RTSCTS) {
0786     z85c30_assert_RTS(minor);
0787   }
0788   rtems_interrupt_disable(Irql);
0789     if ( Console_Port_Data[minor].bActive == FALSE) {
0790       Console_Port_Data[minor].bActive = TRUE;
0791       z85c30_enable_interrupts(minor, SCC_ENABLE_ALL_INTR);
0792     }
0793     (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR8, *buf);
0794   rtems_interrupt_enable(Irql);
0795 
0796   return 0;
0797 }
0798 
0799 /*
0800  *  z85c30_inbyte_nonblocking_polled
0801  *
0802  *  This routine polls for a character.
0803  */
0804 
0805 Z85C30_STATIC int z85c30_inbyte_nonblocking_polled(
0806   int  minor
0807 )
0808 {
0809   volatile uint8_t    z85c30_status;
0810   uint32_t            ulCtrlPort;
0811   getRegister_f       getReg;
0812 
0813   ulCtrlPort = Console_Port_Tbl[minor]->ulCtrlPort1;
0814   getReg     = Console_Port_Tbl[minor]->getRegister;
0815 
0816   /*
0817    * return -1 if a character is not available.
0818    */
0819   z85c30_status = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0);
0820   if (!Z85C30_Status_Is_RX_character_available(z85c30_status)) {
0821     return -1;
0822   }
0823 
0824   /*
0825    * Return the character read.
0826    */
0827 
0828   return (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD8);
0829 }
0830 
0831 /*
0832  *  z85c30_write_support_polled
0833  *
0834  *  Console Termios output entry point.
0835  *
0836  */
0837 
0838 Z85C30_STATIC ssize_t z85c30_write_support_polled(
0839   int   minor,
0840   const char *buf,
0841   size_t len)
0842 {
0843   int nwrite=0;
0844 
0845   /*
0846    * poll each byte in the string out of the port.
0847    */
0848   while (nwrite < len) {
0849     z85c30_write_polled(minor, *buf++);
0850     nwrite++;
0851   }
0852 
0853   /*
0854    * return the number of bytes written.
0855    */
0856   return nwrite;
0857 }
0858 
0859 /*
0860  *  z85c30_write_polled
0861  *
0862  *  This routine transmits a character using polling.
0863  */
0864 
0865 Z85C30_STATIC void z85c30_write_polled(
0866   int   minor,
0867   char  cChar
0868 )
0869 {
0870   volatile uint8_t   z85c30_status;
0871   uint32_t           ulCtrlPort;
0872   getRegister_f      getReg;
0873   setRegister_f      setReg;
0874 
0875   ulCtrlPort = Console_Port_Tbl[minor]->ulCtrlPort1;
0876   getReg     = Console_Port_Tbl[minor]->getRegister;
0877   setReg     = Console_Port_Tbl[minor]->setRegister;
0878 
0879   /*
0880    * Wait for the Transmit buffer to indicate that it is empty.
0881    */
0882 
0883   z85c30_status = (*getReg)( ulCtrlPort, SCC_WR0_SEL_RD0 );
0884 
0885   while (!Z85C30_Status_Is_TX_buffer_empty(z85c30_status)) {
0886     /*
0887      * Yield while we wait
0888      */
0889 #if 0
0890     if (_System_state_Is_up(_System_state_Get())) {
0891       rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);
0892     }
0893 #endif
0894     z85c30_status = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0);
0895   }
0896 
0897   /*
0898    * Write the character.
0899    */
0900 
0901   (*setReg)( ulCtrlPort, SCC_WR0_SEL_WR8, cChar );
0902 }