[BACK]Return to com.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / ic

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/sys/dev/ic/com.c between version 1.183 and 1.183.2.4

version 1.183, 2001/01/14 23:50:28 version 1.183.2.4, 2001/09/21 22:35:35
Line 71 
Line 71 
  *      @(#)com.c       7.5 (Berkeley) 5/16/91   *      @(#)com.c       7.5 (Berkeley) 5/16/91
  */   */
   
 #if defined(__sparc__) || defined(__sparc_v9__)  
 #define DDB_BREAK_CHAR  1       /* L1 or Stop key */  
 #endif  
   
 /*  /*
  * COM driver, uses National Semiconductor NS16450/NS16550AF UART   * COM driver, uses National Semiconductor NS16450/NS16550AF UART
  * Supports automatic hardware flow control on StarTech ST16C650A UART   * Supports automatic hardware flow control on StarTech ST16C650A UART
  */   */
   
   #include "opt_com.h"
 #include "opt_ddb.h"  #include "opt_ddb.h"
 #include "opt_ddbparam.h"  #include "opt_ddbparam.h"
 #include "opt_com.h"  #include "opt_kgdb.h"
   
 #include "rnd.h"  #include "rnd.h"
 #if NRND > 0 && defined(RND_COM)  #if NRND > 0 && defined(RND_COM)
 #include <sys/rnd.h>  #include <sys/rnd.h>
 #endif  #endif
   
   /*
    * Override cnmagic(9) macro before including <sys/systm.h>.
    * We need to know if cn_check_magic triggered debugger, so set a flag.
    * Callers of cn_check_magic must declare int cn_trapped = 0;
    * XXX: this is *ugly*!
    */
   #define cn_trap()                               \
           do {                                    \
                   console_debugger();             \
                   cn_trapped = 1;                 \
           } while (/* CONSTCOND */ 0)
   
 #include <sys/param.h>  #include <sys/param.h>
 #include <sys/systm.h>  #include <sys/systm.h>
 #include <sys/ioctl.h>  #include <sys/ioctl.h>
Line 120 
Line 129 
 #define com_lcr com_cfcr  #define com_lcr com_cfcr
 #include <dev/cons.h>  #include <dev/cons.h>
   
 #include "com.h"  
   
 #ifdef COM_HAYESP  #ifdef COM_HAYESP
 int comprobeHAYESP __P((bus_space_handle_t hayespioh, struct com_softc *sc));  int comprobeHAYESP __P((bus_space_handle_t hayespioh, struct com_softc *sc));
 #endif  #endif
   
 #if defined(DDB) || defined(KGDB)  
 static void com_enable_debugport __P((struct com_softc *));  static void com_enable_debugport __P((struct com_softc *));
 #endif  
 void    com_config      __P((struct com_softc *));  void    com_config      __P((struct com_softc *));
 void    com_shutdown    __P((struct com_softc *));  void    com_shutdown    __P((struct com_softc *));
 int     comspeed        __P((long, long));  int     comspeed        __P((long, long));
 static  u_char  cflag2lcr __P((tcflag_t));  static  u_char  cflag2lcr __P((tcflag_t));
 int     comparam        __P((struct tty *, struct termios *));  int     comparam        __P((struct tty *, struct termios *));
 void    comstart        __P((struct tty *));  void    comstart        __P((struct tty *));
 void    comstop         __P((struct tty *, int));  
 int     comhwiflow      __P((struct tty *, int));  int     comhwiflow      __P((struct tty *, int));
   
 void    com_loadchannelregs __P((struct com_softc *));  void    com_loadchannelregs __P((struct com_softc *));
Line 146  void tiocm_to_com __P((struct com_softc 
Line 151  void tiocm_to_com __P((struct com_softc 
 int     com_to_tiocm    __P((struct com_softc *));  int     com_to_tiocm    __P((struct com_softc *));
 void    com_iflush      __P((struct com_softc *));  void    com_iflush      __P((struct com_softc *));
   
 int     com_common_getc __P((bus_space_tag_t, bus_space_handle_t));  int     com_common_getc __P((dev_t, bus_space_tag_t, bus_space_handle_t));
 void    com_common_putc __P((bus_space_tag_t, bus_space_handle_t, int));  void    com_common_putc __P((dev_t, bus_space_tag_t, bus_space_handle_t, int));
   
 /* XXX: These belong elsewhere */  int cominit             __P((bus_space_tag_t, bus_addr_t, int, int, tcflag_t,
                                bus_space_handle_t *));
   
   /* XXX: This belongs elsewhere */
 cdev_decl(com);  cdev_decl(com);
 bdev_decl(com);  
   
 int     comcngetc       __P((dev_t));  int     comcngetc       __P((dev_t));
 void    comcnputc       __P((dev_t, int));  void    comcnputc       __P((dev_t, int));
Line 192  static bus_space_handle_t comconsioh;
Line 199  static bus_space_handle_t comconsioh;
 static int      comconsattached;  static int      comconsattached;
 static int comconsrate;  static int comconsrate;
 static tcflag_t comconscflag;  static tcflag_t comconscflag;
   static struct cnm_state com_cnm_state;
   
 static int ppscap =  static int ppscap =
         PPS_TSFMT_TSPEC |          PPS_TSFMT_TSPEC |
Line 382  comprobeHAYESP(hayespioh, sc)
Line 390  comprobeHAYESP(hayespioh, sc)
 }  }
 #endif  #endif
   
 #if defined(DDB) || defined(KGDB)  
 static void  static void
 com_enable_debugport(sc)  com_enable_debugport(sc)
         struct com_softc *sc;          struct com_softc *sc;
Line 399  com_enable_debugport(sc)
Line 406  com_enable_debugport(sc)
         COM_UNLOCK(sc);          COM_UNLOCK(sc);
         splx(s);          splx(s);
 }  }
 #endif  
   
 void  void
 com_attach_subr(sc)  com_attach_subr(sc)
Line 436  com_attach_subr(sc)
Line 442  com_attach_subr(sc)
         }          }
   
 #ifdef COM_HAYESP  #ifdef COM_HAYESP
           sc->sc_prescaler = 0;                   /* set prescaler to x1. */
   
         /* Look for a Hayes ESP board. */          /* Look for a Hayes ESP board. */
         for (hayespp = hayesp_ports; *hayespp != 0; hayespp++) {          for (hayespp = hayesp_ports; *hayespp != 0; hayespp++) {
                 bus_space_handle_t hayespioh;                  bus_space_handle_t hayespioh;
Line 627  com_config(sc)
Line 635  com_config(sc)
         }          }
 #endif  #endif
   
 #ifdef DDB          if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE|COM_HW_KGDB))
         if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE))  
                 com_enable_debugport(sc);                  com_enable_debugport(sc);
 #endif  
   
 #ifdef KGDB  
         /*  
          * Allow kgdb to "take over" this port.  If this is  
          * the kgdb device, it has exclusive use.  
          */  
         if (ISSET(sc->sc_hwflags, COM_HW_KGDB))  
                 com_enable_debugport(sc);  
 #endif  
 }  }
   
 int  int
Line 752  com_shutdown(sc)
Line 749  com_shutdown(sc)
         }          }
   
         /* Turn off interrupts. */          /* Turn off interrupts. */
 #ifdef DDB  
         if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE))          if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
                 sc->sc_ier = IER_ERXRDY; /* interrupt on break */                  sc->sc_ier = IER_ERXRDY; /* interrupt on break */
         else          else
 #endif  
                 sc->sc_ier = 0;                  sc->sc_ier = 0;
         bus_space_write_1(sc->sc_iot, sc->sc_ioh, com_ier, sc->sc_ier);          bus_space_write_1(sc->sc_iot, sc->sc_ioh, com_ier, sc->sc_ier);
   
Line 986  comwrite(dev, uio, flag)
Line 981  comwrite(dev, uio, flag)
         return ((*tp->t_linesw->l_write)(tp, uio, flag));          return ((*tp->t_linesw->l_write)(tp, uio, flag));
 }  }
   
   int
   compoll(dev, events, p)
           dev_t dev;
           int events;
           struct proc *p;
   {
           struct com_softc *sc = device_lookup(&com_cd, COMUNIT(dev));
           struct tty *tp = sc->sc_tty;
   
           if (COM_ISALIVE(sc) == 0)
                   return (EIO);
   
           return ((*tp->t_linesw->l_poll)(tp, events, p));
   }
   
 struct tty *  struct tty *
 comtty(dev)  comtty(dev)
         dev_t dev;          dev_t dev;
Line 1348  comparam(tp, t)
Line 1358  comparam(tp, t)
         struct termios *t;          struct termios *t;
 {  {
         struct com_softc *sc = device_lookup(&com_cd, COMUNIT(tp->t_dev));          struct com_softc *sc = device_lookup(&com_cd, COMUNIT(tp->t_dev));
         int ospeed = comspeed(t->c_ospeed, sc->sc_frequency);          int ospeed;
         u_char lcr;          u_char lcr;
         int s;          int s;
   
         if (COM_ISALIVE(sc) == 0)          if (COM_ISALIVE(sc) == 0)
                 return (EIO);                  return (EIO);
   
   #ifdef COM_HAYESP
           if (ISSET(sc->sc_hwflags, COM_HW_HAYESP)) {
                   int prescaler, speed;
   
                   /*
                    * Calculate UART clock prescaler.  It should be in
                    * range of 0 .. 3.
                    */
                   for (prescaler = 0, speed = t->c_ospeed; prescaler < 4;
                       prescaler++, speed /= 2)
                           if ((ospeed = comspeed(speed, sc->sc_frequency)) > 0)
                                   break;
   
                   if (prescaler == 4)
                           return (EINVAL);
                   sc->sc_prescaler = prescaler;
           } else
   #endif
           ospeed = comspeed(t->c_ospeed, sc->sc_frequency);
   
         /* Check requested parameters. */          /* Check requested parameters. */
         if (ospeed < 0)          if (ospeed < 0)
                 return (EINVAL);                  return (EINVAL);
Line 1567  com_loadchannelregs(sc)
Line 1597  com_loadchannelregs(sc)
         bus_space_write_1(iot, ioh, com_lcr, sc->sc_lcr);          bus_space_write_1(iot, ioh, com_lcr, sc->sc_lcr);
         bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr_active = sc->sc_mcr);          bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr_active = sc->sc_mcr);
         bus_space_write_1(iot, ioh, com_fifo, sc->sc_fifo);          bus_space_write_1(iot, ioh, com_fifo, sc->sc_fifo);
   #ifdef COM_HAYESP
           if (ISSET(sc->sc_hwflags, COM_HW_HAYESP)) {
                   bus_space_write_1(iot, sc->sc_hayespioh, HAYESP_CMD1,
                       HAYESP_SETPRESCALER);
                   bus_space_write_1(iot, sc->sc_hayespioh, HAYESP_CMD2,
                       sc->sc_prescaler);
           }
   #endif
   
         bus_space_write_1(iot, ioh, com_ier, sc->sc_ier);          bus_space_write_1(iot, ioh, com_ier, sc->sc_ier);
 }  }
Line 1998  comintr(arg)
Line 2036  comintr(arg)
         put = sc->sc_rbput;          put = sc->sc_rbput;
         cc = sc->sc_rbavail;          cc = sc->sc_rbavail;
   
         do {  again:  do {
                 u_char  msr, delta;                  u_char  msr, delta;
   
                 lsr = bus_space_read_1(iot, ioh, com_lsr);                  lsr = bus_space_read_1(iot, ioh, com_lsr);
 #if defined(DDB) || defined(KGDB)  
                 if (ISSET(lsr, LSR_BI)) {                  if (ISSET(lsr, LSR_BI)) {
 #ifndef DDB_BREAK_CHAR                          int cn_trapped = 0;
 #ifdef DDB                          cn_check_magic(sc->sc_tty->t_dev,
                         if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {                                         CNC_BREAK, com_cnm_state);
                                 console_debugger();                          if (cn_trapped)
                                 continue;                                  continue;
                         }  #if defined(KGDB)
 #endif  
 #ifdef KGDB  
                         if (ISSET(sc->sc_hwflags, COM_HW_KGDB)) {                          if (ISSET(sc->sc_hwflags, COM_HW_KGDB)) {
                                 kgdb_connect(1);                                  kgdb_connect(1);
                                 continue;                                  continue;
                         }                          }
 #endif  #endif
 #endif  
                 }                  }
 #endif /* DDB || KGDB */  
   
                 if (ISSET(lsr, LSR_RCV_MASK) &&                  if (ISSET(lsr, LSR_RCV_MASK) &&
                     !ISSET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED)) {                      !ISSET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED)) {
                         while (cc > 0) {                          while (cc > 0) {
                                   int cn_trapped = 0;
                                 put[0] = bus_space_read_1(iot, ioh, com_data);                                  put[0] = bus_space_read_1(iot, ioh, com_data);
                                 put[1] = lsr;                                  put[1] = lsr;
 #if defined(DDB) && defined(DDB_BREAK_CHAR)                                  cn_check_magic(sc->sc_tty->t_dev,
                                 if (put[0] == DDB_BREAK_CHAR &&                                                 put[0], com_cnm_state);
                                     ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {                                  if (cn_trapped) {
                                         console_debugger();  
   
                                         lsr = bus_space_read_1(iot, ioh, com_lsr);                                          lsr = bus_space_read_1(iot, ioh, com_lsr);
                                         if (!ISSET(lsr, LSR_RCV_MASK))                                          if (!ISSET(lsr, LSR_RCV_MASK))
                                                 break;                                                  break;
   
                                         continue;                                          continue;
                                 }                                  }
 #endif  
                                 put += 2;                                  put += 2;
                                 if (put >= end)                                  if (put >= end)
                                         put = sc->sc_rbuf;                                          put = sc->sc_rbuf;
Line 2083  comintr(arg)
Line 2114  comintr(arg)
                                 bus_space_write_1(iot, ioh, com_ier, 0);                                  bus_space_write_1(iot, ioh, com_ier, 0);
                                 delay(10);                                  delay(10);
                                 bus_space_write_1(iot, ioh, com_ier,sc->sc_ier);                                  bus_space_write_1(iot, ioh, com_ier,sc->sc_ier);
                                 iir = IIR_NOPEND;  
                                 continue;                                  continue;
                         }                          }
                 }                  }
Line 2156  comintr(arg)
Line 2186  comintr(arg)
   
                         sc->sc_st_check = 1;                          sc->sc_st_check = 1;
                 }                  }
         } while (!ISSET((iir = bus_space_read_1(iot, ioh, com_iir)), IIR_NOPEND));          } while (ISSET((iir = bus_space_read_1(iot, ioh, com_iir)), IIR_RXRDY)
               || ((iir & IIR_IMASK) == 0));
   
         /*          /*
          * Done handling any receive interrupts. See if data can be           * Done handling any receive interrupts. See if data can be
Line 2197  comintr(arg)
Line 2228  comintr(arg)
                         }                          }
                 }                  }
         }          }
   
           if (!ISSET((iir = bus_space_read_1(iot, ioh, com_iir)), IIR_NOPEND))
                   goto again;
   
         COM_UNLOCK(sc);          COM_UNLOCK(sc);
   
         /* Wake up the poller. */          /* Wake up the poller. */
Line 2223  comintr(arg)
Line 2258  comintr(arg)
 /*  /*
  * The following functions are polled getc and putc routines, shared   * The following functions are polled getc and putc routines, shared
  * by the console and kgdb glue.   * by the console and kgdb glue.
    *
    * The read-ahead code is so that you can detect pending in-band
    * cn_magic in polled mode while doing output rather than having to
    * wait until the kernel decides it needs input.
  */   */
   
 #if defined(DDB) && defined(DDB_BREAK_CHAR)  #define MAX_READAHEAD   20
 #define MAX_UNGETC      20  static int com_readahead[MAX_READAHEAD];
 static int com_ungetc[MAX_UNGETC];  static int com_readaheadcount = 0;
 static int com_ungetccount = 0;  
 #endif  
   
 int  int
 com_common_getc(iot, ioh)  com_common_getc(dev, iot, ioh)
           dev_t dev;
         bus_space_tag_t iot;          bus_space_tag_t iot;
         bus_space_handle_t ioh;          bus_space_handle_t ioh;
 {  {
         int s = splserial();          int s = splserial();
         u_char stat, c;          u_char stat, c;
   
 #if defined(DDB) && defined(DDB_BREAK_CHAR)  
         /* got a character from reading things earlier */          /* got a character from reading things earlier */
         if (com_ungetccount > 0) {          if (com_readaheadcount > 0) {
                 int i;                  int i;
   
                 c = com_ungetc[0];                  c = com_readahead[0];
                 for (i = 1; i < com_ungetccount; i++) {                  for (i = 1; i < com_readaheadcount; i++) {
                         com_ungetc[i -1] = com_ungetc[i];                          com_readahead[i-1] = com_readahead[i];
                 }                  }
                 com_ungetccount--;                  com_readaheadcount--;
                 splx(s);                  splx(s);
                 return (c);                  return (c);
         }          }
 #endif  
   
         /* block until a character becomes available */          /* block until a character becomes available */
         while (!ISSET(stat = bus_space_read_1(iot, ioh, com_lsr), LSR_RXRDY))          while (!ISSET(stat = bus_space_read_1(iot, ioh, com_lsr), LSR_RXRDY))
Line 2260  com_common_getc(iot, ioh)
Line 2296  com_common_getc(iot, ioh)
   
         c = bus_space_read_1(iot, ioh, com_data);          c = bus_space_read_1(iot, ioh, com_data);
         stat = bus_space_read_1(iot, ioh, com_iir);          stat = bus_space_read_1(iot, ioh, com_iir);
 #if defined(DDB) && defined(DDB_BREAK_CHAR)          {
         if (c == DDB_BREAK_CHAR) {                  int cn_trapped = 0; /* unused */
   #ifdef DDB
                 extern int db_active;                  extern int db_active;
                   if (!db_active)
                 if (db_active == 0) {  
                         console_debugger();  
                 }  
         }  
 #endif  #endif
                           cn_check_magic(dev, c, com_cnm_state);
           }
         splx(s);          splx(s);
         return (c);          return (c);
 }  }
   
 void  void
 com_common_putc(iot, ioh, c)  com_common_putc(dev, iot, ioh, c)
           dev_t dev;
         bus_space_tag_t iot;          bus_space_tag_t iot;
         bus_space_handle_t ioh;          bus_space_handle_t ioh;
         int c;          int c;
Line 2282  com_common_putc(iot, ioh, c)
Line 2318  com_common_putc(iot, ioh, c)
         int s = splserial();          int s = splserial();
         int timo;          int timo;
   
 #if defined(DDB) && defined(DDB_BREAK_CHAR)  
         int cin, stat;          int cin, stat;
         if (com_ungetccount < MAX_UNGETC          if (com_readaheadcount < MAX_READAHEAD
              && ISSET(stat = bus_space_read_1(iot, ioh, com_lsr), LSR_RXRDY)) {               && ISSET(stat = bus_space_read_1(iot, ioh, com_lsr), LSR_RXRDY)) {
                   int cn_trapped = 0;
                 cin = bus_space_read_1(iot, ioh, com_data);                  cin = bus_space_read_1(iot, ioh, com_data);
                 stat = bus_space_read_1(iot, ioh, com_iir);                  stat = bus_space_read_1(iot, ioh, com_iir);
                 if (cin == DDB_BREAK_CHAR) {                  cn_check_magic(dev, cin, com_cnm_state);
                         console_debugger();                  com_readahead[com_readaheadcount++] = cin;
                 }  
                 com_ungetc[com_ungetccount++] = cin;  
         }          }
 #endif  
   
         /* wait for any pending transmission to finish */          /* wait for any pending transmission to finish */
         timo = 150000;          timo = 150000;
Line 2366  comcnattach(iot, iobase, rate, frequency
Line 2399  comcnattach(iot, iobase, rate, frequency
                 return (res);                  return (res);
   
         cn_tab = &comcons;          cn_tab = &comcons;
           cn_init_magic(&com_cnm_state);
           cn_set_magic("\047\001"); /* default magic is BREAK */
   
         comconstag = iot;          comconstag = iot;
         comconsaddr = iobase;          comconsaddr = iobase;
Line 2379  int
Line 2414  int
 comcngetc(dev)  comcngetc(dev)
         dev_t dev;          dev_t dev;
 {  {
           return (com_common_getc(dev, comconstag, comconsioh));
         return (com_common_getc(comconstag, comconsioh));  
 }  }
   
 /*  /*
Line 2391  comcnputc(dev, c)
Line 2425  comcnputc(dev, c)
         dev_t dev;          dev_t dev;
         int c;          int c;
 {  {
           com_common_putc(dev, comconstag, comconsioh, c);
         com_common_putc(comconstag, comconsioh, c);  
 }  }
   
 void  void
Line 2413  com_kgdb_attach(iot, iobase, rate, frequ
Line 2446  com_kgdb_attach(iot, iobase, rate, frequ
 {  {
         int res;          int res;
   
           printf("com_kgdb_attach\n");
   
         if (iot == comconstag && iobase == comconsaddr)          if (iot == comconstag && iobase == comconsaddr)
                 return (EBUSY); /* cannot share with console */                  return (EBUSY); /* cannot share with console */
   
Line 2434  int
Line 2469  int
 com_kgdb_getc(arg)  com_kgdb_getc(arg)
         void *arg;          void *arg;
 {  {
           return (com_common_getc(NODEV, com_kgdb_iot, com_kgdb_ioh));
         return (com_common_getc(com_kgdb_iot, com_kgdb_ioh));  
 }  }
   
 /* ARGSUSED */  /* ARGSUSED */
Line 2444  com_kgdb_putc(arg, c)
Line 2478  com_kgdb_putc(arg, c)
         void *arg;          void *arg;
         int c;          int c;
 {  {
           com_common_putc(NODEV, com_kgdb_iot, com_kgdb_ioh, c);
         return (com_common_putc(com_kgdb_iot, com_kgdb_ioh, c));  
 }  }
 #endif /* KGDB */  #endif /* KGDB */
   

Legend:
Removed from v.1.183  
changed lines
  Added in v.1.183.2.4

CVSweb <webmaster@jp.NetBSD.org>