root/arch/i386/isa/pccom.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. comspeed
  2. comprobe1
  3. comprobe
  4. comattach
  5. com_detach
  6. com_activate
  7. comopen
  8. comclose
  9. compwroff
  10. com_raisedtr
  11. comread
  12. comwrite
  13. comtty
  14. tiocm_xxx2mcr
  15. comioctl
  16. comparam
  17. comhwiflow
  18. comstart
  19. comstop
  20. comdiag
  21. comsoft
  22. kgdbintr
  23. comintr
  24. pccom_xr16850_fifo_init
  25. comcnprobe
  26. com_common_getc
  27. com_common_putc
  28. comcninit
  29. cominit
  30. comcngetc
  31. comcnputc
  32. comcnpollc
  33. com_kgdb_attach
  34. com_kgdb_getc
  35. com_kgdb_putc

    1 /*      $OpenBSD: pccom.c,v 1.61 2007/05/09 14:32:17 deraadt Exp $      */
    2 /*      $NetBSD: com.c,v 1.82.4.1 1996/06/02 09:08:00 mrg Exp $ */
    3 
    4 /*
    5  * Copyright (c) 1997 - 1999, Jason Downs.  All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. Neither the name(s) of the author(s) nor the name OpenBSD
   16  *    may be used to endorse or promote products derived from this software
   17  *    without specific prior written permission.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
   20  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   22  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
   23  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
   25  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
   26  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29  * SUCH DAMAGE.
   30  */
   31 /*-
   32  * Copyright (c) 1993, 1994, 1995, 1996
   33  *      Charles M. Hannum.  All rights reserved.
   34  * Copyright (c) 1991 The Regents of the University of California.
   35  * All rights reserved.
   36  *
   37  * Redistribution and use in source and binary forms, with or without
   38  * modification, are permitted provided that the following conditions
   39  * are met:
   40  * 1. Redistributions of source code must retain the above copyright
   41  *    notice, this list of conditions and the following disclaimer.
   42  * 2. Redistributions in binary form must reproduce the above copyright
   43  *    notice, this list of conditions and the following disclaimer in the
   44  *    documentation and/or other materials provided with the distribution.
   45  * 3. Neither the name of the University nor the names of its contributors
   46  *    may be used to endorse or promote products derived from this software
   47  *    without specific prior written permission.
   48  *
   49  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   50  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   51  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   52  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   53  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   54  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   55  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   56  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   57  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   58  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   59  * SUCH DAMAGE.
   60  *
   61  *      @(#)com.c       7.5 (Berkeley) 5/16/91
   62  */
   63 
   64 /*
   65  * PCCOM driver, uses National Semiconductor NS16450/NS16550AF UART
   66  */
   67 #include <sys/param.h>
   68 #include <sys/systm.h>
   69 #include <sys/ioctl.h>
   70 #include <sys/selinfo.h>
   71 #include <sys/tty.h>
   72 #include <sys/proc.h>
   73 #include <sys/user.h>
   74 #include <sys/conf.h>
   75 #include <sys/file.h>
   76 #include <sys/uio.h>
   77 #include <sys/kernel.h>
   78 #include <sys/syslog.h>
   79 #include <sys/types.h>
   80 #include <sys/device.h>
   81 #include <sys/vnode.h>
   82 #include <sys/timeout.h>
   83 
   84 #include <machine/bus.h>
   85 #include <machine/intr.h>
   86 
   87 #include <dev/cons.h>
   88 #include <dev/isa/isavar.h>
   89 #include <dev/ic/comreg.h>
   90 #include <dev/ic/ns16550reg.h>
   91 #define com_lcr com_cfcr
   92 #ifdef DDB
   93 #include <ddb/db_var.h>
   94 #endif
   95 
   96 #include "pccomvar.h"
   97 #include "pccom.h"
   98 
   99 /* XXX: These belong elsewhere */
  100 cdev_decl(com);
  101 
  102 static u_char tiocm_xxx2mcr(int);
  103 
  104 void pccom_xr16850_fifo_init(bus_space_tag_t, bus_space_handle_t);
  105 
  106 /*
  107  * XXX the following two cfattach structs should be different, and possibly
  108  * XXX elsewhere.
  109  */
  110 int     comprobe(struct device *, void *, void *);
  111 void    comattach(struct device *, struct device *, void *);
  112 void    compwroff(struct com_softc *);
  113 
  114 #if NPCCOM_ISA
  115 struct cfattach pccom_isa_ca = {
  116         sizeof(struct com_softc), comprobe, comattach
  117 };
  118 #endif
  119 
  120 #if NPCCOM_ISAPNP
  121 struct cfattach pccom_isapnp_ca = {
  122         sizeof(struct com_softc), comprobe, comattach
  123 };
  124 #endif
  125 
  126 #if NPCCOM_COMMULTI
  127 struct cfattach pccom_commulti_ca = {
  128         sizeof(struct com_softc), comprobe, comattach
  129 };
  130 #endif
  131 
  132 struct cfdriver pccom_cd = {
  133         NULL, "pccom", DV_TTY
  134 };
  135 
  136 void cominit(bus_space_tag_t, bus_space_handle_t, int);
  137 
  138 #ifndef CONSPEED
  139 #define CONSPEED B9600
  140 #endif
  141 
  142 #if defined(COMCONSOLE) || defined(PCCOMCONSOLE)
  143 int     comdefaultrate = CONSPEED;              /* XXX why set default? */
  144 #else
  145 int     comdefaultrate = TTYDEF_SPEED;
  146 #endif
  147 bus_addr_t comconsaddr;
  148 int     comconsinit;
  149 int     comconsattached;
  150 bus_space_tag_t comconsiot;
  151 bus_space_handle_t comconsioh;
  152 tcflag_t comconscflag = TTYDEF_CFLAG;
  153 
  154 int     commajor;
  155 int     comsopen = 0;
  156 
  157 #ifdef KGDB
  158 #include <sys/kgdb.h>
  159 
  160 bus_addr_t com_kgdb_addr;
  161 bus_space_tag_t com_kgdb_iot;
  162 bus_space_handle_t com_kgdb_ioh;
  163 
  164 int     com_kgdb_getc(void *);
  165 void    com_kgdb_putc(void *, int);
  166 #endif /* KGDB */
  167 
  168 #define DEVUNIT(x)      (minor(x) & 0x7f)
  169 #define DEVCUA(x)       (minor(x) & 0x80)
  170 
  171 /* Macros for determining bus type. */
  172 #if NPCCOM_ISA || NPCCOM_PCMCIA
  173 #define IS_ISA(parent) \
  174         (!strcmp((parent)->dv_cfdata->cf_driver->cd_name, "isa") || \
  175          !strcmp((parent)->dv_cfdata->cf_driver->cd_name, "pcmcia"))
  176 #elif NPCCOM_ISA
  177 #define IS_ISA(parent) \
  178         !strcmp((parent)->dv_cfdata->cf_driver->cd_name, "isa")
  179 #elif NPCCOM_ISAPNP
  180 #define IS_ISA(parent) 0
  181 #endif
  182 
  183 #if NPCCOM_ISAPNP
  184 #define IS_ISAPNP(parent) \
  185          !strcmp((parent)->dv_cfdata->cf_driver->cd_name, "isapnp")
  186 #else
  187 #define IS_ISAPNP(parent)       0
  188 #endif
  189 
  190 int
  191 comspeed(long freq, long speed)
  192 {
  193 #define divrnd(n, q)    (((n)*2/(q)+1)/2)       /* divide and round off */
  194 
  195         int x, err;
  196 
  197         if (speed == 0)
  198                 return 0;
  199         if (speed < 0)
  200                 return -1;
  201         x = divrnd((freq / 16), speed);
  202         if (x <= 0)
  203                 return -1;
  204         err = divrnd((quad_t)freq * 1000 / 16, speed * x) - 1000;
  205         if (err < 0)
  206                 err = -err;
  207         if (err > COM_TOLERANCE)
  208                 return -1;
  209         return x;
  210 
  211 #undef  divrnd
  212 }
  213 
  214 int
  215 comprobe1(bus_space_tag_t iot, bus_space_handle_t ioh)
  216 {
  217         int i, k;
  218 
  219         /* force access to id reg */
  220         bus_space_write_1(iot, ioh, com_lcr, 0);
  221         bus_space_write_1(iot, ioh, com_iir, 0);
  222         for (i = 0; i < 32; i++) {
  223                 k = bus_space_read_1(iot, ioh, com_iir);
  224                 if (k & 0x38) {
  225                         bus_space_read_1(iot, ioh, com_data); /* cleanup */
  226                 } else
  227                         break;
  228         }
  229         if (i >= 32) 
  230             return 0;
  231 
  232         return 1;
  233 }
  234 
  235 int
  236 comprobe(struct device *parent, void *match, void *aux)
  237 {
  238         bus_space_tag_t iot;
  239         bus_space_handle_t ioh;
  240         int iobase, needioh;
  241         int rv = 1;
  242 
  243         /*
  244          * XXX should be broken out into functions for isa probe and
  245          * XXX for commulti probe, with a helper function that contains
  246          * XXX most of the interesting stuff.
  247          */
  248 /* #if NPCCOM_ISA || NPCCOM_PCMCIA || NPCCOM_ISAPNP */
  249 #if NPCCOM_ISA || NPCCOM_ISAPNP
  250         if (IS_ISA(parent) || IS_ISAPNP(parent)) {
  251                 struct isa_attach_args *ia = aux;
  252 
  253                 iot = ia->ia_iot;
  254                 iobase = ia->ia_iobase;
  255                 if (IS_ISAPNP(parent)) {
  256                         ioh = ia->ia_ioh;
  257                         needioh = 0;
  258                 } else
  259                         needioh = 1;
  260         } else
  261 #endif
  262 #if NPCCOM_COMMULTI
  263         if (1) {
  264                 struct cfdata *cf = match;
  265                 struct commulti_attach_args *ca = aux;
  266  
  267                 if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != ca->ca_slave)
  268                         return (0);
  269 
  270                 iot = ca->ca_iot;
  271                 iobase = ca->ca_iobase;
  272                 ioh = ca->ca_ioh;
  273                 needioh = 0;
  274         } else
  275 #endif
  276                 return(0);                      /* This cannot happen */
  277 
  278 #ifdef KGDB
  279         if (iobase == com_kgdb_addr)
  280                 goto out;
  281 #endif /* KGDB */
  282 
  283         /* if it's in use as console, it's there. */
  284         if (iobase == comconsaddr && !comconsattached)
  285                 goto out;
  286 
  287         if (needioh && bus_space_map(iot, iobase, COM_NPORTS, 0, &ioh)) {
  288                 rv = 0;
  289                 goto out;
  290         }
  291         rv = comprobe1(iot, ioh);
  292         if (needioh)
  293                 bus_space_unmap(iot, ioh, COM_NPORTS);
  294 
  295 out:
  296 /* #if NPCCOM_ISA || NPCCOM_PCMCIA */
  297 #if NPCCOM_ISA
  298         if (rv) {
  299                 struct isa_attach_args *ia = aux;
  300 
  301                 ia->ia_iosize = COM_NPORTS;
  302                 ia->ia_msize = 0;
  303         }
  304 #endif
  305         return (rv);
  306 }
  307 
  308 void
  309 comattach(struct device *parent, struct device *self, void *aux)
  310 {
  311         struct com_softc *sc = (void *)self;
  312         bus_addr_t iobase;
  313         bus_space_tag_t iot;
  314         bus_space_handle_t ioh;
  315         int irq;
  316 
  317         /*
  318          * XXX should be broken out into functions for isa attach and
  319          * XXX for commulti attach, with a helper function that contains
  320          * XXX most of the interesting stuff.
  321          */
  322 /* #if NPCCOM_ISA || NPCCOM_PCMCIA || NPCCOM_ISAPNP */
  323 #if NPCCOM_ISA || NPCCOM_ISAPNP
  324         if (IS_ISA(parent) || IS_ISAPNP(parent)) {
  325                 struct isa_attach_args *ia = aux;
  326 
  327                 /*
  328                  * We're living on an isa.
  329                  */
  330                 iobase = ia->ia_iobase;
  331                 iot = ia->ia_iot;
  332                 if (IS_ISAPNP(parent)) {
  333                         /* No console support! */
  334                         ioh = ia->ia_ioh;
  335                 } else {
  336 #ifdef KGDB
  337                         if ((iobase != comconsaddr) &&
  338                             (iobase != com_kgdb_addr)) {
  339 #else
  340                         if (iobase != comconsaddr) {
  341 #endif /* KGDB */
  342                                 if (bus_space_map(iot, iobase, COM_NPORTS, 0, &ioh))
  343                                         panic("comattach: io mapping failed");
  344                         } else
  345 #ifdef KGDB
  346                                 if (iobase == comconsaddr) {
  347                                         ioh = comconsioh;
  348                                 } else {
  349                                         ioh = com_kgdb_ioh;
  350                                 }
  351 #else
  352                                 ioh = comconsioh;
  353 #endif /* KGDB */
  354                 }
  355                 irq = ia->ia_irq;
  356         } else
  357 #endif
  358 #if NPCCOM_COMMULTI
  359         if (1) {
  360                 struct commulti_attach_args *ca = aux;
  361 
  362                 /*
  363                  * We're living on a commulti.
  364                  */
  365                 iobase = ca->ca_iobase;
  366                 iot = ca->ca_iot;
  367                 ioh = ca->ca_ioh;
  368                 irq = IRQUNK;
  369 
  370                 if (ca->ca_noien)
  371                         SET(sc->sc_hwflags, COM_HW_NOIEN);
  372         } else
  373 #endif
  374                 panic("comattach: impossible");
  375 
  376         sc->sc_iot = iot;
  377         sc->sc_ioh = ioh;
  378         sc->sc_iobase = iobase;
  379         sc->sc_frequency = COM_FREQ;
  380 
  381         sc->sc_hwflags = 0;
  382         sc->sc_swflags = 0;
  383 
  384         if (irq != IRQUNK) {
  385                 /* disable interrupts */
  386                 bus_space_write_1(iot, ioh, com_ier, 0);
  387 
  388 /* #if NPCCOM_ISA || NPCCOM_PCMCIA || NPCCOM_ISAPNP */
  389 #if NPCCOM_ISA || NPCCOM_ISAPNP
  390                 if (IS_ISA(parent) || IS_ISAPNP(parent)) {
  391                         struct isa_attach_args *ia = aux;
  392 
  393 #ifdef KGDB
  394                         if (iobase == com_kgdb_addr) {
  395                                 sc->sc_ih = isa_intr_establish(ia->ia_ic, irq,
  396                                     IST_EDGE, IPL_HIGH, kgdbintr, sc,
  397                                     sc->sc_dev.dv_xname);
  398                         } else {
  399                                 sc->sc_ih = isa_intr_establish(ia->ia_ic, irq,
  400                                     IST_EDGE, IPL_HIGH, comintr, sc,
  401                                     sc->sc_dev.dv_xname);
  402                         }
  403 #else
  404                         sc->sc_ih = isa_intr_establish(ia->ia_ic, irq,
  405                             IST_EDGE, IPL_HIGH, comintr, sc,
  406                             sc->sc_dev.dv_xname);
  407 #endif /* KGDB */
  408                 } else
  409 #endif
  410                         panic("comattach: IRQ but can't have one");
  411         }
  412 
  413         com_attach_subr(sc);
  414 }
  415 
  416 int
  417 com_detach(struct device *self, int flags)
  418 {
  419         struct com_softc *sc = (struct com_softc *)self;
  420         int maj, mn;
  421 
  422         /* locate the major number */
  423         for (maj = 0; maj < nchrdev; maj++)
  424                 if (cdevsw[maj].d_open == comopen)
  425                         break;
  426 
  427         /* Nuke the vnodes for any open instances. */
  428         mn = self->dv_unit;
  429         vdevgone(maj, mn, mn, VCHR);
  430 
  431         /* XXX a symbolic constant for the cua bit would be nicer. */
  432         mn |= 0x80;
  433         vdevgone(maj, mn, mn, VCHR);
  434 
  435         /* Detach and free the tty. */
  436         if (sc->sc_tty) {
  437                 ttyfree(sc->sc_tty);
  438         }
  439 
  440         timeout_del(&sc->sc_dtr_tmo);
  441         timeout_del(&sc->sc_diag_tmo);
  442 
  443         return (0);
  444 }
  445 
  446 int
  447 com_activate(struct device *self, enum devact act)
  448 {
  449         struct com_softc *sc = (struct com_softc *)self;
  450         int s, rv = 0;
  451 
  452         /* XXX splserial, when we get that.  */
  453         s = spltty();
  454         switch (act) {
  455         case DVACT_ACTIVATE:
  456                 break;
  457 
  458         case DVACT_DEACTIVATE:
  459 #ifdef KGDB
  460                 if (sc->sc_hwflags & (COM_HW_CONSOLE|COM_HW_KGDB)) {
  461 #else
  462                 if (sc->sc_hwflags & COM_HW_CONSOLE) {
  463 #endif /* KGDB */
  464                         rv = EBUSY;
  465                         break;
  466                 }
  467 
  468                 if (sc->disable != NULL && sc->enabled != 0) {
  469                         (*sc->disable)(sc);
  470                         sc->enabled = 0;
  471                 }
  472                 break;
  473         }
  474         splx(s);
  475         return (rv);
  476 }
  477 
  478 int
  479 comopen(dev_t dev, int flag, int mode, struct proc *p)
  480 {
  481         int unit = DEVUNIT(dev);
  482         struct com_softc *sc;
  483         bus_space_tag_t iot;
  484         bus_space_handle_t ioh;
  485         struct tty *tp;
  486         int s;
  487         int error = 0;
  488  
  489         if (unit >= pccom_cd.cd_ndevs)
  490                 return ENXIO;
  491         sc = pccom_cd.cd_devs[unit];
  492         if (!sc)
  493                 return ENXIO;
  494 
  495 #ifdef KGDB
  496         /*
  497          * If this is the kgdb port, no other use is permitted.
  498          */
  499         if (ISSET(sc->sc_hwflags, COM_HW_KGDB))
  500                 return (EBUSY);
  501 #endif /* KGDB */
  502 
  503         s = spltty();
  504         if (!sc->sc_tty) {
  505                 tp = sc->sc_tty = ttymalloc();
  506         } else
  507                 tp = sc->sc_tty;
  508         splx(s);
  509 
  510         tp->t_oproc = comstart;
  511         tp->t_param = comparam;
  512         tp->t_hwiflow = comhwiflow;
  513         tp->t_dev = dev;
  514         if (!ISSET(tp->t_state, TS_ISOPEN)) {
  515                 SET(tp->t_state, TS_WOPEN);
  516                 ttychars(tp);
  517                 tp->t_iflag = TTYDEF_IFLAG;
  518                 tp->t_oflag = TTYDEF_OFLAG;
  519                 if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
  520                         tp->t_cflag = comconscflag;
  521                 else
  522                         tp->t_cflag = TTYDEF_CFLAG;
  523                 if (ISSET(sc->sc_swflags, COM_SW_CLOCAL))
  524                         SET(tp->t_cflag, CLOCAL);
  525                 if (ISSET(sc->sc_swflags, COM_SW_CRTSCTS))
  526                         SET(tp->t_cflag, CRTSCTS);
  527                 if (ISSET(sc->sc_swflags, COM_SW_MDMBUF))
  528                         SET(tp->t_cflag, MDMBUF);
  529                 tp->t_lflag = TTYDEF_LFLAG;
  530                 tp->t_ispeed = tp->t_ospeed = comdefaultrate;
  531 
  532                 s = spltty();
  533 
  534                 iot = sc->sc_iot;
  535                 ioh = sc->sc_ioh;
  536 
  537                 /*
  538                  * Wake up the sleepy heads.
  539                  */
  540                 switch (sc->sc_uarttype) {
  541                 case COM_UART_ST16650:
  542                 case COM_UART_ST16650V2:
  543                 case COM_UART_ST16C654:
  544                 case COM_UART_XR16850:
  545                 case COM_UART_OX16C950:
  546                         bus_space_write_1(iot, ioh, com_lcr, LCR_EFR);
  547                         bus_space_write_1(iot, ioh, com_efr, EFR_ECB);
  548                         bus_space_write_1(iot, ioh, com_ier, 0);
  549                         bus_space_write_1(iot, ioh, com_efr, 0);
  550                         bus_space_write_1(iot, ioh, com_lcr, 0);
  551                         break;
  552                 case COM_UART_TI16750:
  553                         bus_space_write_1(iot, ioh, com_ier, 0);
  554                         break;
  555                 }
  556 
  557                 sc->sc_initialize = 1;
  558                 comparam(tp, &tp->t_termios);
  559                 ttsetwater(tp);
  560 
  561                 sc->sc_rxput = sc->sc_rxget = sc->sc_tbc = 0;
  562 
  563                 if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) {
  564                         u_int8_t fifo = FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST;
  565                         u_int8_t lcr;
  566 
  567                         switch (sc->sc_uarttype) {
  568                         case COM_UART_ST16650V2:
  569                                 if (tp->t_ispeed <= 1200)
  570                                         fifo |= FIFO_RCV_TRIGGER_8|FIFO_XMT_TRIGGER_8; /* XXX */
  571                                 else
  572                                         fifo |= FIFO_RCV_TRIGGER_28|FIFO_XMT_TRIGGER_30;
  573                                 break;
  574                         case COM_UART_ST16C654:
  575                                 if (tp->t_ispeed <= 1200)
  576                                         fifo |= FIFO_RCV3_TRIGGER_8|FIFO_XMT3_TRIGGER_8; /* XXX */
  577                                 else
  578                                         fifo |= FIFO_RCV3_TRIGGER_60|FIFO_XMT3_TRIGGER_56;
  579                                 break;
  580                         case COM_UART_XR16850:
  581                         case COM_UART_OX16C950:
  582                                 pccom_xr16850_fifo_init(iot, ioh);
  583                                 if (tp->t_ispeed <= 1200)
  584                                         fifo |= FIFO_RCV3_TRIGGER_8|FIFO_XMT3_TRIGGER_8; /* XXX */
  585                                 else
  586                                         fifo |= FIFO_RCV3_TRIGGER_60|FIFO_XMT3_TRIGGER_56;
  587                                 break;
  588                         case COM_UART_TI16750:
  589                                 fifo |= FIFO_ENABLE_64BYTE;
  590                                 lcr = bus_space_read_1(iot, ioh, com_lcr);
  591                                 bus_space_write_1(iot, ioh, com_lcr,
  592                                     lcr | LCR_DLAB);
  593                         default:
  594                                 if (tp->t_ispeed <= 1200)
  595                                         fifo |= FIFO_TRIGGER_1;
  596                                 else
  597                                         fifo |= FIFO_TRIGGER_8;
  598                         }
  599 
  600                         /*
  601                          * (Re)enable and drain FIFOs.
  602                          *
  603                          * Certain SMC chips cause problems if the FIFOs are
  604                          * enabled while input is ready. Turn off the FIFO
  605                          * if necessary to clear the input. Test the input
  606                          * ready bit after enabling the FIFOs to handle races
  607                          * between enabling and fresh input.
  608                          *
  609                          * Set the FIFO threshold based on the receive speed.
  610                          */
  611                         for (;;) {
  612                                 bus_space_write_1(iot, ioh, com_fifo, 0);
  613                                 delay(100);
  614                                 (void) bus_space_read_1(iot, ioh, com_data);
  615                                 bus_space_write_1(iot, ioh, com_fifo, fifo |
  616                                     FIFO_RCV_RST | FIFO_XMT_RST);
  617                                 delay(100);
  618                                 if(!ISSET(bus_space_read_1(iot, ioh,
  619                                     com_lsr), LSR_RXRDY))
  620                                         break;
  621                         }
  622                         if (sc->sc_uarttype == COM_UART_TI16750)
  623                                 bus_space_write_1(iot, ioh, com_lcr, lcr);
  624                 }
  625 
  626                 /* flush any pending I/O */
  627                 while (ISSET(bus_space_read_1(iot, ioh, com_lsr), LSR_RXRDY))
  628                         (void) bus_space_read_1(iot, ioh, com_data);
  629                 /* you turn me on, baby */
  630                 sc->sc_mcr = MCR_DTR | MCR_RTS;
  631                 if (!ISSET(sc->sc_hwflags, COM_HW_NOIEN))
  632                         SET(sc->sc_mcr, MCR_IENABLE);
  633                 bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
  634                 sc->sc_ier = IER_ERXRDY | IER_ERLS | IER_EMSC;
  635                 bus_space_write_1(iot, ioh, com_ier, sc->sc_ier);
  636 
  637                 sc->sc_msr = bus_space_read_1(iot, ioh, com_msr);
  638                 if (ISSET(sc->sc_swflags, COM_SW_SOFTCAR) || DEVCUA(dev) ||
  639                     ISSET(sc->sc_msr, MSR_DCD) || ISSET(tp->t_cflag, MDMBUF))
  640                         SET(tp->t_state, TS_CARR_ON);
  641                 else
  642                         CLR(tp->t_state, TS_CARR_ON);
  643         } else if (ISSET(tp->t_state, TS_XCLUDE) && p->p_ucred->cr_uid != 0)
  644                 return EBUSY;
  645         else
  646                 s = spltty();
  647 
  648         if (DEVCUA(dev)) {
  649                 if (ISSET(tp->t_state, TS_ISOPEN)) {
  650                         /* Ah, but someone already is dialed in... */
  651                         splx(s);
  652                         return EBUSY;
  653                 }
  654                 sc->sc_cua = 1;         /* We go into CUA mode */
  655         } else {
  656                 /* tty (not cua) device; wait for carrier if necessary */
  657                 if (ISSET(flag, O_NONBLOCK)) {
  658                         if (sc->sc_cua) {
  659                                 /* Opening TTY non-blocking... but the CUA is busy */
  660                                 splx(s);
  661                                 return EBUSY;
  662                         }
  663                 } else {
  664                         while (sc->sc_cua ||
  665                                (!ISSET(tp->t_cflag, CLOCAL) &&
  666                                 !ISSET(tp->t_state, TS_CARR_ON))) {
  667                                 SET(tp->t_state, TS_WOPEN);
  668                                 error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH, ttopen, 0);
  669                                 /*
  670                                  * If TS_WOPEN has been reset, that means the cua device
  671                                  * has been closed.  We don't want to fail in that case,
  672                                  * so just go around again.
  673                                  */
  674                                 if (error && ISSET(tp->t_state, TS_WOPEN)) {
  675                                         CLR(tp->t_state, TS_WOPEN);
  676                                         if (!sc->sc_cua && !ISSET(tp->t_state, TS_ISOPEN))
  677                                                 compwroff(sc);
  678                                         splx(s);
  679                                         return error;
  680                                 }
  681                         }
  682                 }
  683         }
  684         splx(s);
  685         return (*linesw[tp->t_line].l_open)(dev, tp);
  686 }
  687  
  688 int
  689 comclose(dev_t dev, int flag, int mode, struct proc *p)
  690 {
  691         int unit = DEVUNIT(dev);
  692         struct com_softc *sc = pccom_cd.cd_devs[unit];
  693         bus_space_tag_t iot = sc->sc_iot;
  694         bus_space_handle_t ioh = sc->sc_ioh;
  695         struct tty *tp = sc->sc_tty;
  696         int s;
  697 
  698         /* XXX This is for cons.c. */
  699         if (!ISSET(tp->t_state, TS_ISOPEN))
  700                 return 0;
  701 
  702         (*linesw[tp->t_line].l_close)(tp, flag);
  703         s = spltty();
  704         if (ISSET(tp->t_state, TS_WOPEN)) {
  705                 /* tty device is waiting for carrier; drop dtr then re-raise */
  706                 CLR(sc->sc_mcr, MCR_DTR | MCR_RTS);
  707                 bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
  708                 timeout_add(&sc->sc_dtr_tmo, hz * 2);
  709         } else {
  710                 /* no one else waiting; turn off the uart */
  711                 compwroff(sc);
  712         }
  713         CLR(tp->t_state, TS_BUSY | TS_FLUSH);
  714         sc->sc_cua = 0;
  715         splx(s);
  716         ttyclose(tp);
  717 
  718 #ifdef notyet /* XXXX */
  719         if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
  720                 ttyfree(tp);
  721                 sc->sc_tty = 0;
  722         }
  723 #endif
  724         return 0;
  725 }
  726 
  727 void
  728 compwroff(struct com_softc *sc)
  729 {
  730         bus_space_tag_t iot = sc->sc_iot;
  731         bus_space_handle_t ioh = sc->sc_ioh;
  732         struct tty *tp = sc->sc_tty;
  733 
  734         CLR(sc->sc_lcr, LCR_SBREAK);
  735         bus_space_write_1(iot, ioh, com_lcr, sc->sc_lcr);
  736         bus_space_write_1(iot, ioh, com_ier, 0);
  737         if (ISSET(tp->t_cflag, HUPCL) &&
  738             !ISSET(sc->sc_swflags, COM_SW_SOFTCAR)) {
  739                 /* XXX perhaps only clear DTR */
  740                 sc->sc_mcr = 0;
  741                 bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
  742         }
  743 
  744         /*
  745          * Turn FIFO off; enter sleep mode if possible.
  746          */
  747         bus_space_write_1(iot, ioh, com_fifo, 0);
  748         delay(100);
  749         (void) bus_space_read_1(iot, ioh, com_data);
  750         delay(100);
  751         bus_space_write_1(iot, ioh, com_fifo,
  752                           FIFO_RCV_RST | FIFO_XMT_RST);
  753 
  754         switch (sc->sc_uarttype) {
  755         case COM_UART_ST16650:
  756         case COM_UART_ST16650V2:
  757         case COM_UART_ST16C654:
  758         case COM_UART_XR16850:
  759         case COM_UART_OX16C950:
  760                 bus_space_write_1(iot, ioh, com_lcr, LCR_EFR);
  761                 bus_space_write_1(iot, ioh, com_efr, EFR_ECB);
  762                 bus_space_write_1(iot, ioh, com_ier, IER_SLEEP);
  763                 bus_space_write_1(iot, ioh, com_lcr, 0);
  764                 break;
  765         case COM_UART_TI16750:
  766                 bus_space_write_1(iot, ioh, com_ier, IER_SLEEP);
  767                 break;
  768         }
  769 }
  770 
  771 void
  772 com_raisedtr(void *arg)
  773 {
  774         struct com_softc *sc = arg;
  775 
  776         SET(sc->sc_mcr, MCR_DTR | MCR_RTS);
  777         bus_space_write_1(sc->sc_iot, sc->sc_ioh, com_mcr, sc->sc_mcr);
  778 }
  779 
  780 int
  781 comread(dev_t dev, struct uio *uio, int flag)
  782 {
  783         struct com_softc *sc = pccom_cd.cd_devs[DEVUNIT(dev)];
  784         struct tty *tp = sc->sc_tty;
  785  
  786         return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
  787 }
  788  
  789 int
  790 comwrite(dev_t dev, struct uio *uio, int flag)
  791 {
  792         struct com_softc *sc = pccom_cd.cd_devs[DEVUNIT(dev)];
  793         struct tty *tp = sc->sc_tty;
  794  
  795         return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
  796 }
  797 
  798 struct tty *
  799 comtty(dev_t dev)
  800 {
  801         struct com_softc *sc = pccom_cd.cd_devs[DEVUNIT(dev)];
  802         struct tty *tp = sc->sc_tty;
  803 
  804         return (tp);
  805 }
  806  
  807 static u_char
  808 tiocm_xxx2mcr(int data)
  809 {
  810         u_char m = 0;
  811 
  812         if (ISSET(data, TIOCM_DTR))
  813                 SET(m, MCR_DTR);
  814         if (ISSET(data, TIOCM_RTS))
  815                 SET(m, MCR_RTS);
  816         return m;
  817 }
  818 
  819 int
  820 comioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
  821 {
  822         int unit = DEVUNIT(dev);
  823         struct com_softc *sc = pccom_cd.cd_devs[unit];
  824         struct tty *tp = sc->sc_tty;
  825         bus_space_tag_t iot = sc->sc_iot;
  826         bus_space_handle_t ioh = sc->sc_ioh;
  827         int error;
  828 
  829         error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
  830         if (error >= 0)
  831                 return error;
  832         error = ttioctl(tp, cmd, data, flag, p);
  833         if (error >= 0)
  834                 return error;
  835 
  836         switch (cmd) {
  837         case TIOCSBRK:
  838                 SET(sc->sc_lcr, LCR_SBREAK);
  839                 bus_space_write_1(iot, ioh, com_lcr, sc->sc_lcr);
  840                 break;
  841         case TIOCCBRK:
  842                 CLR(sc->sc_lcr, LCR_SBREAK);
  843                 bus_space_write_1(iot, ioh, com_lcr, sc->sc_lcr);
  844                 break;
  845         case TIOCSDTR:
  846                 SET(sc->sc_mcr, sc->sc_dtr);
  847                 bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
  848                 break;
  849         case TIOCCDTR:
  850                 CLR(sc->sc_mcr, sc->sc_dtr);
  851                 bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
  852                 break;
  853         case TIOCMSET:
  854                 CLR(sc->sc_mcr, MCR_DTR | MCR_RTS);
  855         case TIOCMBIS:
  856                 SET(sc->sc_mcr, tiocm_xxx2mcr(*(int *)data));
  857                 bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
  858                 break;
  859         case TIOCMBIC:
  860                 CLR(sc->sc_mcr, tiocm_xxx2mcr(*(int *)data));
  861                 bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
  862                 break;
  863         case TIOCMGET: {
  864                 u_char m;
  865                 int bits = 0;
  866 
  867                 m = sc->sc_mcr;
  868                 if (ISSET(m, MCR_DTR))
  869                         SET(bits, TIOCM_DTR);
  870                 if (ISSET(m, MCR_RTS))
  871                         SET(bits, TIOCM_RTS);
  872                 m = sc->sc_msr;
  873                 if (ISSET(m, MSR_DCD))
  874                         SET(bits, TIOCM_CD);
  875                 if (ISSET(m, MSR_CTS))
  876                         SET(bits, TIOCM_CTS);
  877                 if (ISSET(m, MSR_DSR))
  878                         SET(bits, TIOCM_DSR);
  879                 if (ISSET(m, MSR_RI | MSR_TERI))
  880                         SET(bits, TIOCM_RI);
  881                 if (bus_space_read_1(iot, ioh, com_ier))
  882                         SET(bits, TIOCM_LE);
  883                 *(int *)data = bits;
  884                 break;
  885         }
  886         case TIOCGFLAGS: {
  887                 int driverbits, userbits = 0;
  888 
  889                 driverbits = sc->sc_swflags;
  890                 if (ISSET(driverbits, COM_SW_SOFTCAR))
  891                         SET(userbits, TIOCFLAG_SOFTCAR);
  892                 if (ISSET(driverbits, COM_SW_CLOCAL))
  893                         SET(userbits, TIOCFLAG_CLOCAL);
  894                 if (ISSET(driverbits, COM_SW_CRTSCTS))
  895                         SET(userbits, TIOCFLAG_CRTSCTS);
  896                 if (ISSET(driverbits, COM_SW_MDMBUF))
  897                         SET(userbits, TIOCFLAG_MDMBUF);
  898 
  899                 *(int *)data = userbits;
  900                 break;
  901         }
  902         case TIOCSFLAGS: {
  903                 int userbits, driverbits = 0;
  904 
  905                 error = suser(p, 0); 
  906                 if (error != 0)
  907                         return(EPERM); 
  908 
  909                 userbits = *(int *)data;
  910                 if (ISSET(userbits, TIOCFLAG_SOFTCAR) ||
  911                     ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
  912                         SET(driverbits, COM_SW_SOFTCAR);
  913                 if (ISSET(userbits, TIOCFLAG_CLOCAL))
  914                         SET(driverbits, COM_SW_CLOCAL);
  915                 if (ISSET(userbits, TIOCFLAG_CRTSCTS))
  916                         SET(driverbits, COM_SW_CRTSCTS);
  917                 if (ISSET(userbits, TIOCFLAG_MDMBUF))
  918                         SET(driverbits, COM_SW_MDMBUF);
  919 
  920                 sc->sc_swflags = driverbits;
  921                 break;
  922         }
  923         default:
  924                 return ENOTTY;
  925         }
  926 
  927         return 0;
  928 }
  929 
  930 int
  931 comparam(struct tty *tp, struct termios *t)
  932 {
  933         struct com_softc *sc = pccom_cd.cd_devs[DEVUNIT(tp->t_dev)];
  934         bus_space_tag_t iot = sc->sc_iot;
  935         bus_space_handle_t ioh = sc->sc_ioh;
  936         int ospeed = comspeed(sc->sc_frequency, t->c_ospeed);
  937         u_int8_t lcr;
  938         tcflag_t oldcflag;
  939         int s;
  940 
  941         /* check requested parameters */
  942         if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
  943                 return EINVAL;
  944 
  945         lcr = ISSET(sc->sc_lcr, LCR_SBREAK);
  946 
  947         switch (ISSET(t->c_cflag, CSIZE)) {
  948         case CS5:
  949                 SET(lcr, LCR_5BITS);
  950                 break;
  951         case CS6:
  952                 SET(lcr, LCR_6BITS);
  953                 break;
  954         case CS7:
  955                 SET(lcr, LCR_7BITS);
  956                 break;
  957         case CS8:
  958                 SET(lcr, LCR_8BITS);
  959                 break;
  960         }
  961         if (ISSET(t->c_cflag, PARENB)) {
  962                 SET(lcr, LCR_PENAB);
  963                 if (!ISSET(t->c_cflag, PARODD))
  964                         SET(lcr, LCR_PEVEN);
  965         }
  966         if (ISSET(t->c_cflag, CSTOPB))
  967                 SET(lcr, LCR_STOPB);
  968 
  969         sc->sc_lcr = lcr;
  970 
  971         s = spltty();
  972 
  973         if (ospeed == 0) {
  974                 CLR(sc->sc_mcr, MCR_DTR);
  975                 bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
  976         }
  977 
  978         /*
  979          * Set the FIFO threshold based on the receive speed, if we are
  980          * changing it.
  981          */
  982         if (sc->sc_initialize || (tp->t_ispeed != t->c_ispeed)) {
  983                 sc->sc_initialize = 0;
  984 
  985                 if (ospeed != 0) {
  986                         /*
  987                          * Make sure the transmit FIFO is empty before
  988                          * proceeding.  If we don't do this, some revisions
  989                          * of the UART will hang.  Interestingly enough,
  990                          * even if we do this while the last character is
  991                          * still being pushed out, they don't hang.  This
  992                          * seems good enough.
  993                          */
  994                         while (ISSET(tp->t_state, TS_BUSY)) {
  995                                 int error;
  996 
  997                                 ++sc->sc_halt;
  998                                 error = ttysleep(tp, &tp->t_outq,
  999                                     TTOPRI | PCATCH, "comprm", 0);
 1000                                 --sc->sc_halt;
 1001                                 if (error) {
 1002                                         splx(s);
 1003                                         comstart(tp);
 1004                                         return (error);
 1005                                 }
 1006                         }
 1007 
 1008                         bus_space_write_1(iot, ioh, com_lcr, lcr | LCR_DLAB);
 1009                         bus_space_write_1(iot, ioh, com_dlbl, ospeed);
 1010                         bus_space_write_1(iot, ioh, com_dlbh, ospeed >> 8);
 1011                         bus_space_write_1(iot, ioh, com_lcr, lcr);
 1012                         SET(sc->sc_mcr, MCR_DTR);
 1013                         bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
 1014                 } else
 1015                         bus_space_write_1(iot, ioh, com_lcr, lcr);
 1016 
 1017                 if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) {
 1018                         u_int8_t fifo = FIFO_ENABLE;
 1019                         u_int8_t lcr2;
 1020 
 1021                         switch (sc->sc_uarttype) {
 1022                         case COM_UART_ST16650V2:
 1023                                 if (t->c_ispeed <= 1200)
 1024                                         fifo |= FIFO_RCV_TRIGGER_8|FIFO_XMT_TRIGGER_8; /* XXX */
 1025                                 else
 1026                                         fifo |= FIFO_RCV_TRIGGER_28|FIFO_XMT_TRIGGER_30;
 1027                                 break;
 1028                         case COM_UART_ST16C654:
 1029                         case COM_UART_XR16850:
 1030                         case COM_UART_OX16C950:
 1031                                 if (t->c_ispeed <= 1200)
 1032                                         fifo |= FIFO_RCV3_TRIGGER_8|FIFO_XMT3_TRIGGER_8; /* XXX */
 1033                                 else
 1034                                         fifo |= FIFO_RCV3_TRIGGER_60|FIFO_XMT3_TRIGGER_56;
 1035                                 break;
 1036                         case COM_UART_TI16750:
 1037                                 fifo |= FIFO_ENABLE_64BYTE;
 1038                                 lcr2 = bus_space_read_1(iot, ioh, com_lcr);
 1039                                 bus_space_write_1(iot, ioh, com_lcr,
 1040                                     lcr2 | LCR_DLAB);
 1041                         default:
 1042                                 if (t->c_ispeed <= 1200)
 1043                                         fifo |= FIFO_TRIGGER_1;
 1044                                 else
 1045                                         fifo |= FIFO_TRIGGER_8;
 1046                         }
 1047                         bus_space_write_1(iot, ioh, com_fifo, fifo);
 1048 
 1049                         if (sc->sc_uarttype == COM_UART_TI16750)
 1050                                 bus_space_write_1(iot, ioh, com_lcr, lcr2);
 1051                 }
 1052         } else
 1053                 bus_space_write_1(iot, ioh, com_lcr, lcr);
 1054 
 1055         /* When not using CRTSCTS, RTS follows DTR. */
 1056         if (!ISSET(t->c_cflag, CRTSCTS)) {
 1057                 if (ISSET(sc->sc_mcr, MCR_DTR)) {
 1058                         if (!ISSET(sc->sc_mcr, MCR_RTS)) {
 1059                                 SET(sc->sc_mcr, MCR_RTS);
 1060                                 bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
 1061                         }
 1062                 } else {
 1063                         if (ISSET(sc->sc_mcr, MCR_RTS)) {
 1064                                 CLR(sc->sc_mcr, MCR_RTS);
 1065                                 bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
 1066                         }
 1067                 }
 1068                 sc->sc_dtr = MCR_DTR | MCR_RTS;
 1069         } else
 1070                 sc->sc_dtr = MCR_DTR;
 1071 
 1072         /* and copy to tty */
 1073         tp->t_ispeed = t->c_ispeed;
 1074         tp->t_ospeed = t->c_ospeed;
 1075         oldcflag = tp->t_cflag;
 1076         tp->t_cflag = t->c_cflag;
 1077 
 1078         /*
 1079          * If DCD is off and MDMBUF is changed, ask the tty layer if we should
 1080          * stop the device.
 1081          */
 1082         if (!ISSET(sc->sc_msr, MSR_DCD) &&
 1083             !ISSET(sc->sc_swflags, COM_SW_SOFTCAR) &&
 1084             ISSET(oldcflag, MDMBUF) != ISSET(tp->t_cflag, MDMBUF) &&
 1085             (*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
 1086                 CLR(sc->sc_mcr, sc->sc_dtr);
 1087                 bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
 1088         }
 1089 
 1090         /* Just to be sure... */
 1091         splx(s);
 1092         comstart(tp);
 1093         return 0;
 1094 }
 1095 
 1096 /*
 1097  * (un)block input via hw flowcontrol
 1098  */
 1099 int
 1100 comhwiflow(struct tty *tp, int block)
 1101 {
 1102         struct com_softc *sc = pccom_cd.cd_devs[DEVUNIT(tp->t_dev)];
 1103         bus_space_tag_t iot = sc->sc_iot;
 1104         bus_space_handle_t ioh = sc->sc_ioh;
 1105         int     s;
 1106 
 1107 /*
 1108  * XXX
 1109  * Is spltty needed at all ? sc->sc_mcr is only in comsoft() not comintr()
 1110  */
 1111         s = spltty();
 1112         if (block) {
 1113                 /* When not using CRTSCTS, RTS follows DTR. */
 1114                 if (ISSET(tp->t_cflag, MDMBUF)) {
 1115                         CLR(sc->sc_mcr, (MCR_DTR | MCR_RTS));
 1116                         bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
 1117                 }
 1118                 else {
 1119                         CLR(sc->sc_mcr, MCR_RTS);
 1120                         bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
 1121                 }
 1122         }
 1123         else {
 1124                 /* When not using CRTSCTS, RTS follows DTR. */
 1125                 if (ISSET(tp->t_cflag, MDMBUF)) {
 1126                         SET(sc->sc_mcr, (MCR_DTR | MCR_RTS));
 1127                         bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
 1128                 }
 1129                 else {
 1130                         SET(sc->sc_mcr, MCR_RTS);
 1131                         bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
 1132                 }
 1133         }
 1134         splx(s);
 1135         return 1;
 1136 }
 1137 
 1138 void
 1139 comstart(struct tty *tp)
 1140 {
 1141         struct com_softc *sc = pccom_cd.cd_devs[DEVUNIT(tp->t_dev)];
 1142         bus_space_tag_t iot = sc->sc_iot;
 1143         bus_space_handle_t ioh = sc->sc_ioh;
 1144         int s, count;
 1145 
 1146         s = spltty();
 1147         if (ISSET(tp->t_state, TS_BUSY))
 1148                 goto out;
 1149         if (ISSET(tp->t_state, TS_TIMEOUT | TS_TTSTOP) || sc->sc_halt > 0)
 1150                 goto stopped;
 1151         if (ISSET(tp->t_cflag, CRTSCTS) && !ISSET(sc->sc_msr, MSR_CTS))
 1152                 goto stopped;
 1153         if (tp->t_outq.c_cc <= tp->t_lowat) {
 1154                 if (ISSET(tp->t_state, TS_ASLEEP)) {
 1155                         CLR(tp->t_state, TS_ASLEEP);
 1156                         wakeup((caddr_t)&tp->t_outq);
 1157                 }
 1158                 selwakeup(&tp->t_wsel);
 1159         }
 1160         count = ndqb(&tp->t_outq, 0);
 1161         splhigh();
 1162         if (count > 0) {
 1163                 int n;
 1164 
 1165                 SET(tp->t_state, TS_BUSY);
 1166                 if (!ISSET(sc->sc_ier, IER_ETXRDY)) {
 1167                         SET(sc->sc_ier, IER_ETXRDY);
 1168                         bus_space_write_1(iot, ioh, com_ier, sc->sc_ier);
 1169                 }
 1170                 n = sc->sc_fifolen;
 1171                 if (n > count)
 1172                         n = count;
 1173                 sc->sc_tba = tp->t_outq.c_cf;
 1174                 while (--n >= 0) {
 1175                         bus_space_write_1(iot, ioh, com_data, *sc->sc_tba++);
 1176                         --count;
 1177                 }
 1178                 sc->sc_tbc = count;
 1179                 goto out;
 1180         }
 1181 stopped:
 1182         if (ISSET(sc->sc_ier, IER_ETXRDY)) {
 1183                 CLR(sc->sc_ier, IER_ETXRDY);
 1184                 bus_space_write_1(iot, ioh, com_ier, sc->sc_ier);
 1185         }
 1186 out:
 1187         splx(s);
 1188         return;
 1189 }
 1190 
 1191 /*
 1192  * Stop output on a line.
 1193  */
 1194 int
 1195 comstop(struct tty *tp, int flag)
 1196 {
 1197         int s;
 1198         struct com_softc *sc = pccom_cd.cd_devs[DEVUNIT(tp->t_dev)];
 1199 
 1200         s = splhigh();
 1201         if (ISSET(tp->t_state, TS_BUSY)) {
 1202                 sc->sc_tbc = 0;
 1203                 if (!ISSET(tp->t_state, TS_TTSTOP))
 1204                         SET(tp->t_state, TS_FLUSH);
 1205         }
 1206         splx(s);
 1207         return 0;
 1208 }
 1209 
 1210 void
 1211 comdiag(void *arg)
 1212 {
 1213         struct com_softc *sc = arg;
 1214         int overflows;
 1215         int s;
 1216 
 1217         s = spltty();
 1218         overflows = sc->sc_overflows;
 1219         sc->sc_overflows = 0;
 1220         splx(s);
 1221 
 1222         if (overflows)
 1223                 log(LOG_WARNING, "%s: %d silo overflow%s\n",
 1224                     sc->sc_dev.dv_xname, overflows, overflows == 1 ? "" : "s");
 1225 }
 1226 
 1227 #ifdef PCCOM_DEBUG
 1228 int     maxcc = 0;
 1229 #endif
 1230 
 1231 void
 1232 comsoft(void)
 1233 {
 1234         struct com_softc        *sc;
 1235         struct tty *tp;
 1236         struct linesw   *line;
 1237         int     unit, s, c;
 1238         u_int rxget;
 1239         static int lsrmap[8] = {
 1240                 0,      TTY_PE,
 1241                 TTY_FE, TTY_PE|TTY_FE,
 1242                 TTY_FE, TTY_PE|TTY_FE,
 1243                 TTY_FE, TTY_PE|TTY_FE
 1244         };
 1245 
 1246         for (unit = 0; unit < pccom_cd.cd_ndevs; unit++) {
 1247                 sc = pccom_cd.cd_devs[unit];
 1248                 if (sc == NULL)
 1249                         continue;
 1250                 tp = sc->sc_tty;
 1251 /*
 1252  * XXX only use (tp == NULL) ???
 1253  */
 1254                 if (tp == NULL || !ISSET(tp->t_state, TS_ISOPEN | TS_WOPEN))
 1255                         continue;
 1256                 line = &linesw[tp->t_line];
 1257 /*
 1258  * XXX where do we _really_ need spltty(), if at all ???
 1259  */
 1260                 s = spltty();
 1261                 rxget = sc->sc_rxget;
 1262                 while (rxget != sc->sc_rxput) {
 1263                         u_int8_t lsr;
 1264 
 1265                         lsr = sc->sc_rxbuf[rxget];
 1266                         rxget = (rxget + 1) & RBUFMASK;
 1267                         if (ISSET(lsr, LSR_RCV_MASK)) {
 1268                                 c = sc->sc_rxbuf[rxget];
 1269                                 if (ISSET(lsr, LSR_OE)) {
 1270                                         sc->sc_overflows++;
 1271                                         if (sc->sc_errors++ == 0)
 1272                                                 timeout_add(&sc->sc_diag_tmo, 60 * hz);
 1273                                 }
 1274                                 rxget = (rxget + 1) & RBUFMASK;
 1275                                 c |= lsrmap[(lsr & (LSR_BI|LSR_FE|LSR_PE)) >> 2];
 1276                                 line->l_rint(c, tp);
 1277                         }
 1278                         else if (ISSET(lsr, LSR_TXRDY)) {
 1279                                 CLR(tp->t_state, TS_BUSY);
 1280                                 if (ISSET(tp->t_state, TS_FLUSH))
 1281                                         CLR(tp->t_state, TS_FLUSH);
 1282                                 else
 1283                                         ndflush(&tp->t_outq,
 1284                                         (int)(sc->sc_tba - tp->t_outq.c_cf));
 1285                                 if (sc->sc_halt > 0)
 1286                                         wakeup(&tp->t_outq);
 1287                                 line->l_start(tp);
 1288                         }
 1289                         else if (lsr == 0) {
 1290                                 u_int8_t msr;
 1291 
 1292                                 msr = sc->sc_rxbuf[rxget];
 1293                                 rxget = (rxget + 1) & RBUFMASK;
 1294                                 if (ISSET(msr, MSR_DDCD) &&
 1295                                    !ISSET(sc->sc_swflags, COM_SW_SOFTCAR)) {
 1296                                         if (ISSET(msr, MSR_DCD))
 1297                                                 line->l_modem(tp, 1);
 1298                                         else if (line->l_modem(tp, 0) == 0) {
 1299                                                 CLR(sc->sc_mcr, sc->sc_dtr);
 1300                                                 bus_space_write_1(sc->sc_iot,
 1301                                                                sc->sc_ioh,
 1302                                                                com_mcr,
 1303                                                                sc->sc_mcr);
 1304                                         }
 1305                                 }
 1306                                 if (ISSET(msr, MSR_DCTS) &&
 1307                                     ISSET(msr, MSR_CTS) &&
 1308                                     ISSET(tp->t_cflag, CRTSCTS))
 1309                                         line->l_start(tp);
 1310                         }
 1311                 }
 1312                 sc->sc_rxget = rxget;
 1313 /*
 1314  * XXX this is the place where we could unblock the input
 1315  */
 1316                 splx(s);
 1317         }
 1318 }
 1319 
 1320 #ifdef KGDB
 1321 
 1322 /*
 1323  * If a line break is set, or data matches one of the characters
 1324  * gdb uses to signal a connection, then start up kgdb. Just gobble
 1325  * any other data. Done in a stand alone function because comintr
 1326  * does tty stuff and we don't have one.
 1327  */
 1328 
 1329 int
 1330 kgdbintr(void *arg)
 1331 {
 1332         struct com_softc *sc = arg;
 1333         bus_space_tag_t iot = sc->sc_iot;
 1334         bus_space_handle_t ioh = sc->sc_ioh;
 1335         u_char lsr, data, msr, delta;
 1336 
 1337         if (!ISSET(sc->sc_hwflags, COM_HW_KGDB))
 1338                 return(0);
 1339 
 1340         for (;;) {
 1341                 lsr = bus_space_read_1(iot, ioh, com_lsr);
 1342                 if (ISSET(lsr, LSR_RXRDY)) {
 1343                         do {
 1344                                 data = bus_space_read_1(iot, ioh, com_data);
 1345                                 if (data == 3 || data == '$' || data == '+' ||
 1346                                     ISSET(lsr, LSR_BI)) {
 1347                                         kgdb_connect(1);
 1348                                         data = 0;
 1349                                 }
 1350                                 lsr = bus_space_read_1(iot, ioh, com_lsr);
 1351                         } while (ISSET(lsr, LSR_RXRDY));
 1352 
 1353                 }
 1354                 if (ISSET(lsr, LSR_BI|LSR_FE|LSR_PE|LSR_OE))
 1355                         printf("weird lsr %02x\n", lsr);
 1356 
 1357                 msr = bus_space_read_1(iot, ioh, com_msr);
 1358 
 1359                 if (msr != sc->sc_msr) {
 1360                         delta = msr ^ sc->sc_msr;
 1361                         sc->sc_msr = msr;
 1362                         if (ISSET(delta, MSR_DCD)) {
 1363                                 if (!ISSET(sc->sc_swflags, COM_SW_SOFTCAR)) {
 1364                                         CLR(sc->sc_mcr, sc->sc_dtr);
 1365                                         bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
 1366                                 }
 1367                         }
 1368                 }
 1369                 if (ISSET(bus_space_read_1(iot, ioh, com_iir), IIR_NOPEND))
 1370                         return (1);
 1371         }
 1372 }
 1373 #endif /* KGDB */
 1374 
 1375 int
 1376 comintr(void *arg)
 1377 {
 1378         struct com_softc *sc = arg;
 1379         struct tty *tp = sc->sc_tty;
 1380         bus_space_tag_t iot = sc->sc_iot;
 1381         bus_space_handle_t ioh = sc->sc_ioh;
 1382         u_int8_t lsr, c;
 1383         u_int   rxput;
 1384 
 1385         if (!sc->sc_tty)
 1386                 return (0);     /* can't do squat. */
 1387 
 1388         if (ISSET(bus_space_read_1(iot, ioh, com_iir), IIR_NOPEND))
 1389                 return (0);
 1390 
 1391         rxput = sc->sc_rxput;
 1392         do {
 1393                 u_int8_t msr, delta;
 1394 
 1395                 for (;;) {
 1396                         lsr = bus_space_read_1(iot, ioh, com_lsr);
 1397                         if (!ISSET(lsr, LSR_RCV_MASK))
 1398                                 break;
 1399                         c = bus_space_read_1(iot, ioh, com_data);
 1400                         if (ISSET(lsr, LSR_BI)) {
 1401 #ifdef DDB
 1402                                 if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
 1403                                         if (db_console)
 1404                                                 Debugger();
 1405                                         continue;
 1406                                 }
 1407 #endif
 1408                                 c = 0;
 1409                         }
 1410 
 1411                         sc->sc_rxbuf[rxput] = lsr;
 1412                         rxput = (rxput + 1) & RBUFMASK;
 1413                         sc->sc_rxbuf[rxput] = c;
 1414                         rxput = (rxput + 1) & RBUFMASK;
 1415                 }
 1416                 msr = bus_space_read_1(iot, ioh, com_msr);
 1417                 delta = msr ^ sc->sc_msr;
 1418 
 1419                 ttytstamp(tp, sc->sc_msr & MSR_CTS, msr & MSR_CTS,
 1420                     sc->sc_msr & MSR_DCD, msr & MSR_DCD);
 1421 
 1422                 if (!ISSET(delta, MSR_DCD | MSR_CTS | MSR_RI | MSR_DSR))
 1423                         continue;
 1424                 sc->sc_msr = msr;
 1425 /*
 1426  * stop output straight away if CTS drops and RTS/CTS flowcontrol is used
 1427  * XXX what about DTR/DCD flowcontrol (ISSET(t_cflag, MDMBUF))
 1428  */
 1429                 msr = (msr & 0xf0) | (delta >> 4);
 1430                 if (ISSET(tp->t_cflag, CRTSCTS) && ISSET(msr, MSR_DCTS)) {
 1431                         if (!ISSET(msr, MSR_CTS))
 1432                                 sc->sc_tbc = 0;
 1433                 }
 1434                 sc->sc_rxbuf[rxput] = 0;
 1435                 rxput = (rxput + 1) & RBUFMASK;
 1436                 sc->sc_rxbuf[rxput] = msr;
 1437                 rxput = (rxput + 1) & RBUFMASK;
 1438         } while (!ISSET(bus_space_read_1(iot, ioh, com_iir), IIR_NOPEND));
 1439         if (ISSET(lsr, LSR_TXRDY)) {
 1440                 if (sc->sc_tbc > 0) {
 1441                         int     n;
 1442 
 1443                         n = sc->sc_fifolen;
 1444                         if (n > sc->sc_tbc)
 1445                                 n = sc->sc_tbc;
 1446                         while (--n >= 0) {
 1447                                 bus_space_write_1(iot, ioh, com_data, *sc->sc_tba++);
 1448                                 --sc->sc_tbc;
 1449                         }
 1450                 }
 1451                 else if (ISSET(tp->t_state, TS_BUSY)) {
 1452                         sc->sc_rxbuf[rxput] = lsr;
 1453                         rxput = (rxput + 1) & RBUFMASK;
 1454                 }
 1455         }
 1456         if (sc->sc_rxput != rxput) {
 1457 /*
 1458  * XXX
 1459  * This is the place to do input flow control by dropping RTS or DTR.
 1460  * However, 115200 bps transfers get maxcc only up to 112 while there's
 1461  * room for 512 so should we bother ?
 1462  */
 1463 #ifdef PCCOM_DEBUG
 1464                 int     cc;
 1465 
 1466                 cc = rxput - sc->sc_rxget;
 1467                 if (cc < 0)
 1468                         cc += RBUFSIZE;
 1469                 if (cc > maxcc)
 1470                         maxcc = cc;
 1471 #endif
 1472                 sc->sc_rxput = rxput;
 1473                 setsofttty();
 1474         }
 1475         return 1;
 1476 }
 1477 
 1478 void
 1479 pccom_xr16850_fifo_init(bus_space_tag_t iot, bus_space_handle_t ioh)
 1480 {
 1481         u_int8_t lcr, efr, fctl;
 1482 
 1483         lcr = bus_space_read_1(iot, ioh, com_lcr);
 1484         bus_space_write_1(iot, ioh, com_lcr, LCR_EFR);
 1485         efr = bus_space_read_1(iot, ioh, com_efr);
 1486         bus_space_write_1(iot, ioh, com_efr, efr | EFR_ECB);
 1487         fctl = bus_space_read_1(iot, ioh, com_fctl);
 1488         bus_space_write_1(iot, ioh, com_fctl, fctl | FCTL_TRIGGER3);
 1489         bus_space_write_1(iot, ioh, com_lcr, lcr);
 1490 }
 1491 
 1492 /*
 1493  * Following are all routines needed for PCCOM to act as console
 1494  */
 1495 
 1496 void
 1497 comcnprobe(struct consdev *cp)
 1498 {
 1499         /* XXX NEEDS TO BE FIXED XXX */
 1500         bus_space_tag_t iot = 0;
 1501         bus_space_handle_t ioh;
 1502         int found;
 1503 
 1504         if (bus_space_map(iot, CONADDR, COM_NPORTS, 0, &ioh))
 1505                 return;
 1506         found = comprobe1(iot, ioh);
 1507         bus_space_unmap(iot, ioh, COM_NPORTS);
 1508         if (!found)
 1509                 return;
 1510 
 1511         /* locate the major number */
 1512         for (commajor = 0; commajor < nchrdev; commajor++)
 1513                 if (cdevsw[commajor].d_open == comopen)
 1514                         break;
 1515 
 1516         /* initialize required fields */
 1517         cp->cn_dev = makedev(commajor, CONUNIT);
 1518 #if defined(COMCONSOLE) || defined(PCCOMCONSOLE)
 1519         cp->cn_pri = CN_REMOTE;         /* Force a serial port console */
 1520 #else
 1521         cp->cn_pri = CN_NORMAL;
 1522 #endif
 1523 }
 1524 
 1525 /*
 1526  * The following functions are polled getc and putc routines, shared
 1527  * by the console and kgdb glue.
 1528  */
 1529 
 1530 int
 1531 com_common_getc(bus_space_tag_t iot, bus_space_handle_t ioh)
 1532 {
 1533         int s = splhigh();
 1534         u_char stat, c;
 1535 
 1536         /* block until a character becomes available */
 1537         while (!ISSET(stat = bus_space_read_1(iot, ioh, com_lsr), LSR_RXRDY))
 1538                 continue;
 1539 
 1540         c = bus_space_read_1(iot, ioh, com_data);
 1541         /* clear any interrupts generated by this transmission */
 1542         stat = bus_space_read_1(iot, ioh, com_iir);
 1543         splx(s);
 1544         return (c);
 1545 }
 1546 
 1547 void
 1548 com_common_putc(bus_space_tag_t iot, bus_space_handle_t ioh, int c)
 1549 {
 1550         int s = splhigh();
 1551         int timo;
 1552 
 1553         /* wait for any pending transmission to finish */
 1554         timo = 150000;
 1555         while (!ISSET(bus_space_read_1(iot, ioh, com_lsr), LSR_TXRDY) && --timo)
 1556                 continue;
 1557 
 1558         bus_space_write_1(iot, ioh, com_data, c);
 1559 
 1560         /* wait for this transmission to complete */
 1561         timo = 1500000;
 1562         while (!ISSET(bus_space_read_1(iot, ioh, com_lsr), LSR_TXRDY) && --timo)
 1563                 continue;
 1564 
 1565         splx(s);
 1566 }
 1567 
 1568 /*
 1569  * Following are all routines needed for COM to act as console
 1570  */
 1571 
 1572 void
 1573 comcninit(struct consdev *cp)
 1574 {
 1575 
 1576 #if 0
 1577         XXX NEEDS TO BE FIXED XXX
 1578         comconsiot = ???;
 1579 #endif
 1580 
 1581 #ifdef CONADDR_OVERRIDE
 1582         comconsaddr = CONADDR;
 1583 #else
 1584         const int comports[4] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
 1585         int unit = minor(cp->cn_dev);
 1586 
 1587         if (unit >= 0 && unit < 4)
 1588                 comconsaddr = comports[unit];
 1589         else
 1590                 comconsaddr = CONADDR;
 1591 #endif
 1592 
 1593         if (bus_space_map(comconsiot, comconsaddr, COM_NPORTS, 0, &comconsioh))
 1594                 panic("comcninit: mapping failed");
 1595 
 1596         cominit(comconsiot, comconsioh, comdefaultrate);
 1597         comconsinit = 0;
 1598 }
 1599 
 1600 void
 1601 cominit(bus_space_tag_t iot, bus_space_handle_t ioh, int rate)
 1602 {
 1603         int s = splhigh();
 1604         u_int8_t stat;
 1605 
 1606         bus_space_write_1(iot, ioh, com_lcr, LCR_DLAB);
 1607         rate = comspeed(COM_FREQ, rate); /* XXX not comdefaultrate? */
 1608         bus_space_write_1(iot, ioh, com_dlbl, rate);
 1609         bus_space_write_1(iot, ioh, com_dlbh, rate >> 8);
 1610         bus_space_write_1(iot, ioh, com_lcr, LCR_8BITS);
 1611         bus_space_write_1(iot, ioh, com_mcr, MCR_DTR | MCR_RTS);
 1612         bus_space_write_1(iot, ioh, com_ier, IER_ERXRDY | IER_ETXRDY);
 1613         bus_space_write_1(iot, ioh, com_fifo,
 1614             FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_4);
 1615         stat = bus_space_read_1(iot, ioh, com_iir);
 1616         splx(s);
 1617 }
 1618 
 1619 int
 1620 comcngetc(dev_t dev)
 1621 {
 1622         return (com_common_getc(comconsiot, comconsioh));
 1623 }
 1624 
 1625 /*
 1626  * Console kernel output character routine.
 1627  */
 1628 void
 1629 comcnputc(dev_t dev, int c)
 1630 {
 1631 #if 0
 1632         /* XXX not needed? */
 1633         bus_space_tag_t iot = comconsiot;
 1634         bus_space_handle_t ioh = comconsioh;
 1635 
 1636         if (comconsinit == 0) {
 1637                 cominit(iot, ioh, comdefaultrate);
 1638                 comconsinit = 1;
 1639         }
 1640 #endif
 1641         com_common_putc(comconsiot, comconsioh, c);
 1642 }
 1643 
 1644 void
 1645 comcnpollc(dev_t dev, int on)
 1646 {
 1647 
 1648 }
 1649 
 1650 #ifdef KGDB
 1651 int
 1652 com_kgdb_attach(bus_space_tag_t iot, bus_addr_t iobase, int rate, int frequency,
 1653     tcflag_t cflag)
 1654 {
 1655         if (iot == comconsiot && iobase == comconsaddr) {
 1656                 return (EBUSY); /* cannot share with console */
 1657         }
 1658 
 1659         com_kgdb_iot = iot;
 1660         com_kgdb_addr = iobase;
 1661 
 1662         if (bus_space_map(com_kgdb_iot, com_kgdb_addr, COM_NPORTS, 0,
 1663             &com_kgdb_ioh))
 1664                 panic("com_kgdb_attach: mapping failed");
 1665 
 1666         /* XXX We currently don't respect KGDBMODE? */
 1667         cominit(com_kgdb_iot, com_kgdb_ioh, rate);
 1668 
 1669         kgdb_attach(com_kgdb_getc, com_kgdb_putc, NULL);
 1670         kgdb_dev = 123; /* unneeded, only to satisfy some tests */
 1671 
 1672         return (0);
 1673 }
 1674 
 1675 /* ARGSUSED */
 1676 int
 1677 com_kgdb_getc(void *arg)
 1678 {
 1679 
 1680         return (com_common_getc(com_kgdb_iot, com_kgdb_ioh));
 1681 }
 1682 
 1683 /* ARGSUSED */
 1684 void
 1685 com_kgdb_putc(void *arg, int c)
 1686 {
 1687 
 1688         return (com_common_putc(com_kgdb_iot, com_kgdb_ioh, c));
 1689 }
 1690 #endif /* KGDB */

/* [<][>][^][v][top][bottom][index][help] */