Home | History | Annotate | Line # | Download | only in ic
com.c revision 1.82.4.1
      1  1.82.4.1       mrg /*	$NetBSD: com.c,v 1.82.4.1 1996/06/02 09:08:00 mrg Exp $	*/
      2      1.38       cgd 
      3       1.1       cgd /*-
      4      1.71   mycroft  * Copyright (c) 1993, 1994, 1995, 1996
      5      1.71   mycroft  *	Charles M. Hannum.  All rights reserved.
      6       1.1       cgd  * Copyright (c) 1991 The Regents of the University of California.
      7       1.1       cgd  * All rights reserved.
      8       1.1       cgd  *
      9       1.1       cgd  * Redistribution and use in source and binary forms, with or without
     10       1.1       cgd  * modification, are permitted provided that the following conditions
     11       1.1       cgd  * are met:
     12       1.1       cgd  * 1. Redistributions of source code must retain the above copyright
     13       1.1       cgd  *    notice, this list of conditions and the following disclaimer.
     14       1.1       cgd  * 2. Redistributions in binary form must reproduce the above copyright
     15       1.1       cgd  *    notice, this list of conditions and the following disclaimer in the
     16       1.1       cgd  *    documentation and/or other materials provided with the distribution.
     17       1.1       cgd  * 3. All advertising materials mentioning features or use of this software
     18       1.1       cgd  *    must display the following acknowledgement:
     19       1.1       cgd  *	This product includes software developed by the University of
     20       1.1       cgd  *	California, Berkeley and its contributors.
     21       1.1       cgd  * 4. Neither the name of the University nor the names of its contributors
     22       1.1       cgd  *    may be used to endorse or promote products derived from this software
     23       1.1       cgd  *    without specific prior written permission.
     24       1.1       cgd  *
     25       1.1       cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     26       1.1       cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     27       1.1       cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     28       1.1       cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     29       1.1       cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     30       1.1       cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     31       1.1       cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     32       1.1       cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     33       1.1       cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     34       1.1       cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     35       1.1       cgd  * SUCH DAMAGE.
     36       1.1       cgd  *
     37      1.38       cgd  *	@(#)com.c	7.5 (Berkeley) 5/16/91
     38       1.1       cgd  */
     39       1.1       cgd 
     40       1.1       cgd /*
     41       1.1       cgd  * COM driver, based on HP dca driver
     42       1.1       cgd  * uses National Semiconductor NS16450/NS16550AF UART
     43       1.1       cgd  */
     44      1.14   mycroft #include <sys/param.h>
     45      1.14   mycroft #include <sys/systm.h>
     46      1.14   mycroft #include <sys/ioctl.h>
     47      1.14   mycroft #include <sys/select.h>
     48      1.14   mycroft #include <sys/tty.h>
     49      1.14   mycroft #include <sys/proc.h>
     50      1.14   mycroft #include <sys/user.h>
     51      1.14   mycroft #include <sys/conf.h>
     52      1.14   mycroft #include <sys/file.h>
     53      1.14   mycroft #include <sys/uio.h>
     54      1.14   mycroft #include <sys/kernel.h>
     55      1.14   mycroft #include <sys/syslog.h>
     56      1.14   mycroft #include <sys/types.h>
     57      1.21   mycroft #include <sys/device.h>
     58      1.14   mycroft 
     59      1.82   mycroft #include <machine/bus.h>
     60      1.78       cgd #include <machine/intr.h>
     61      1.14   mycroft 
     62      1.49       cgd #include <dev/isa/isavar.h>
     63      1.47       cgd #include <dev/isa/comreg.h>
     64      1.74       cgd #include <dev/isa/comvar.h>
     65      1.60       cgd #include <dev/ic/ns16550reg.h>
     66      1.65  christos #ifdef COM_HAYESP
     67      1.65  christos #include <dev/ic/hayespreg.h>
     68      1.65  christos #endif
     69      1.62   mycroft #define	com_lcr	com_cfcr
     70      1.14   mycroft 
     71      1.77       cgd #include "com.h"
     72      1.77       cgd 
     73      1.80  christos 
     74      1.64  christos #define	COM_IBUFSIZE	(2 * 512)
     75      1.57   mycroft #define	COM_IHIGHWATER	((3 * COM_IBUFSIZE) / 4)
     76      1.57   mycroft 
     77      1.21   mycroft struct com_softc {
     78      1.21   mycroft 	struct device sc_dev;
     79      1.49       cgd 	void *sc_ih;
     80      1.50   mycroft 	struct tty *sc_tty;
     81       1.1       cgd 
     82      1.33   mycroft 	int sc_overflows;
     83      1.57   mycroft 	int sc_floods;
     84      1.57   mycroft 	int sc_errors;
     85      1.57   mycroft 
     86      1.66   mycroft 	int sc_halt;
     87      1.66   mycroft 
     88      1.41   mycroft 	int sc_iobase;
     89      1.65  christos #ifdef COM_HAYESP
     90      1.65  christos 	int sc_hayespbase;
     91      1.65  christos #endif
     92      1.75       cgd 
     93      1.75       cgd 	bus_chipset_tag_t sc_bc;
     94      1.75       cgd 	bus_io_handle_t sc_ioh;
     95      1.75       cgd 	bus_io_handle_t sc_hayespioh;
     96      1.75       cgd 
     97      1.22       cgd 	u_char sc_hwflags;
     98      1.29   mycroft #define	COM_HW_NOIEN	0x01
     99      1.22       cgd #define	COM_HW_FIFO	0x02
    100      1.65  christos #define	COM_HW_HAYESP	0x04
    101      1.22       cgd #define	COM_HW_CONSOLE	0x40
    102      1.22       cgd 	u_char sc_swflags;
    103      1.22       cgd #define	COM_SW_SOFTCAR	0x01
    104      1.22       cgd #define	COM_SW_CLOCAL	0x02
    105      1.22       cgd #define	COM_SW_CRTSCTS	0x04
    106      1.25       cgd #define	COM_SW_MDMBUF	0x08
    107      1.69   mycroft 	u_char sc_msr, sc_mcr, sc_lcr, sc_ier;
    108      1.57   mycroft 	u_char sc_dtr;
    109      1.57   mycroft 
    110      1.57   mycroft 	u_char *sc_ibuf, *sc_ibufp, *sc_ibufhigh, *sc_ibufend;
    111      1.57   mycroft 	u_char sc_ibufs[2][COM_IBUFSIZE];
    112      1.29   mycroft };
    113      1.21   mycroft 
    114      1.75       cgd #ifdef COM_HAYESP
    115      1.75       cgd int comprobeHAYESP __P((bus_io_handle_t hayespioh, struct com_softc *sc));
    116      1.75       cgd #endif
    117      1.80  christos void	comdiag		__P((void *));
    118      1.80  christos int	comspeed	__P((long));
    119      1.80  christos int	comparam	__P((struct tty *, struct termios *));
    120      1.80  christos void	comstart	__P((struct tty *));
    121      1.80  christos void	compoll		__P((void *));
    122      1.80  christos 
    123      1.80  christos /* XXX: These belong elsewhere */
    124      1.80  christos cdev_decl(com);
    125      1.80  christos bdev_decl(com);
    126      1.80  christos 
    127      1.80  christos struct consdev;
    128      1.80  christos void	comcnprobe	__P((struct consdev *));
    129      1.80  christos void	comcninit	__P((struct consdev *));
    130      1.80  christos int	comcngetc	__P((dev_t));
    131      1.80  christos void	comcnputc	__P((dev_t, int));
    132      1.80  christos void	comcnpollc	__P((dev_t, int));
    133      1.80  christos 
    134      1.80  christos static u_char tiocm_xxx2mcr __P((int));
    135       1.1       cgd 
    136      1.76   thorpej /*
    137      1.76   thorpej  * XXX the following two cfattach structs should be different, and possibly
    138      1.76   thorpej  * XXX elsewhere.
    139      1.76   thorpej  */
    140      1.77       cgd int comprobe __P((struct device *, void *, void *));
    141      1.77       cgd void comattach __P((struct device *, struct device *, void *));
    142      1.77       cgd 
    143      1.77       cgd #if NCOM_ISA
    144      1.76   thorpej struct cfattach com_isa_ca = {
    145      1.76   thorpej 	sizeof(struct com_softc), comprobe, comattach
    146      1.76   thorpej };
    147      1.77       cgd #endif
    148      1.76   thorpej 
    149      1.77       cgd #if NCOM_COMMULTI
    150      1.77       cgd struct cfattach com_commulti_ca = {
    151      1.76   thorpej 	sizeof(struct com_softc), comprobe, comattach
    152      1.76   thorpej };
    153      1.77       cgd #endif
    154      1.75       cgd 
    155      1.76   thorpej struct cfdriver com_cd = {
    156      1.76   thorpej 	NULL, "com", DV_TTY
    157       1.1       cgd };
    158       1.1       cgd 
    159      1.80  christos void cominit __P((bus_chipset_tag_t, bus_io_handle_t, int));
    160      1.76   thorpej 
    161       1.1       cgd #ifdef COMCONSOLE
    162      1.75       cgd int	comdefaultrate = CONSPEED;		/* XXX why set default? */
    163       1.1       cgd #else
    164      1.66   mycroft int	comdefaultrate = TTYDEF_SPEED;
    165       1.1       cgd #endif
    166      1.75       cgd int	comconsaddr;
    167       1.1       cgd int	comconsinit;
    168      1.75       cgd int	comconsattached;
    169      1.75       cgd bus_chipset_tag_t comconsbc;
    170      1.75       cgd bus_io_handle_t comconsioh;
    171      1.79       cgd tcflag_t comconscflag = TTYDEF_CFLAG;
    172      1.75       cgd 
    173       1.1       cgd int	commajor;
    174      1.57   mycroft int	comsopen = 0;
    175      1.57   mycroft int	comevents = 0;
    176       1.1       cgd 
    177       1.1       cgd #ifdef KGDB
    178      1.14   mycroft #include <machine/remote-sl.h>
    179       1.1       cgd extern int kgdb_dev;
    180       1.1       cgd extern int kgdb_rate;
    181       1.1       cgd extern int kgdb_debug_init;
    182       1.1       cgd #endif
    183       1.1       cgd 
    184      1.21   mycroft #define	COMUNIT(x)	(minor(x))
    185       1.1       cgd 
    186      1.62   mycroft /* Macros to clear/set/test flags. */
    187      1.62   mycroft #define	SET(t, f)	(t) |= (f)
    188      1.62   mycroft #define	CLR(t, f)	(t) &= ~(f)
    189      1.62   mycroft #define	ISSET(t, f)	((t) & (f))
    190      1.21   mycroft 
    191      1.21   mycroft int
    192      1.21   mycroft comspeed(speed)
    193      1.21   mycroft 	long speed;
    194       1.1       cgd {
    195      1.21   mycroft #define	divrnd(n, q)	(((n)*2/(q)+1)/2)	/* divide and round off */
    196      1.21   mycroft 
    197      1.21   mycroft 	int x, err;
    198      1.21   mycroft 
    199      1.21   mycroft 	if (speed == 0)
    200      1.21   mycroft 		return 0;
    201      1.21   mycroft 	if (speed < 0)
    202      1.21   mycroft 		return -1;
    203      1.21   mycroft 	x = divrnd((COM_FREQ / 16), speed);
    204      1.21   mycroft 	if (x <= 0)
    205      1.21   mycroft 		return -1;
    206      1.21   mycroft 	err = divrnd((COM_FREQ / 16) * 1000, speed * x) - 1000;
    207      1.21   mycroft 	if (err < 0)
    208      1.21   mycroft 		err = -err;
    209      1.21   mycroft 	if (err > COM_TOLERANCE)
    210      1.21   mycroft 		return -1;
    211      1.21   mycroft 	return x;
    212      1.21   mycroft 
    213      1.21   mycroft #undef	divrnd(n, q)
    214      1.21   mycroft }
    215      1.21   mycroft 
    216      1.21   mycroft int
    217      1.75       cgd comprobe1(bc, ioh, iobase)
    218      1.75       cgd 	bus_chipset_tag_t bc;
    219      1.75       cgd 	bus_io_handle_t ioh;
    220      1.41   mycroft 	int iobase;
    221      1.21   mycroft {
    222      1.21   mycroft 
    223       1.1       cgd 	/* force access to id reg */
    224      1.75       cgd 	bus_io_write_1(bc, ioh, com_lcr, 0);
    225      1.75       cgd 	bus_io_write_1(bc, ioh, com_iir, 0);
    226      1.75       cgd 	if (bus_io_read_1(bc, ioh, com_iir) & 0x38)
    227      1.21   mycroft 		return 0;
    228      1.21   mycroft 
    229      1.21   mycroft 	return 1;
    230       1.1       cgd }
    231       1.1       cgd 
    232      1.65  christos #ifdef COM_HAYESP
    233      1.65  christos int
    234      1.75       cgd comprobeHAYESP(hayespioh, sc)
    235      1.75       cgd 	bus_io_handle_t hayespioh;
    236      1.64  christos 	struct com_softc *sc;
    237      1.64  christos {
    238      1.65  christos 	char	val, dips;
    239      1.64  christos 	int	combaselist[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
    240      1.75       cgd 	bus_chipset_tag_t bc = sc->sc_bc;
    241      1.64  christos 
    242      1.64  christos 	/*
    243      1.64  christos 	 * Hayes ESP cards have two iobases.  One is for compatibility with
    244      1.64  christos 	 * 16550 serial chips, and at the same ISA PC base addresses.  The
    245      1.64  christos 	 * other is for ESP-specific enhanced features, and lies at a
    246      1.65  christos 	 * different addressing range entirely (0x140, 0x180, 0x280, or 0x300).
    247      1.64  christos 	 */
    248      1.64  christos 
    249      1.64  christos 	/* Test for ESP signature */
    250      1.75       cgd 	if ((bus_io_read_1(bc, hayespioh, 0) & 0xf3) == 0)
    251      1.65  christos 		return 0;
    252      1.64  christos 
    253      1.64  christos 	/*
    254      1.64  christos 	 * ESP is present at ESP enhanced base address; unknown com port
    255      1.64  christos 	 */
    256      1.64  christos 
    257      1.64  christos 	/* Get the dip-switch configurations */
    258      1.75       cgd 	bus_io_write_1(bc, hayespioh, HAYESP_CMD1, HAYESP_GETDIPS);
    259      1.75       cgd 	dips = bus_io_read_1(bc, hayespioh, HAYESP_STATUS1);
    260      1.64  christos 
    261      1.64  christos 	/* Determine which com port this ESP card services: bits 0,1 of  */
    262      1.64  christos 	/*  dips is the port # (0-3); combaselist[val] is the com_iobase */
    263      1.65  christos 	if (sc->sc_iobase != combaselist[dips & 0x03])
    264      1.65  christos 		return 0;
    265      1.65  christos 
    266      1.65  christos 	printf(": ESP");
    267      1.64  christos 
    268      1.65  christos  	/* Check ESP Self Test bits. */
    269      1.64  christos 	/* Check for ESP version 2.0: bits 4,5,6 == 010 */
    270      1.75       cgd 	bus_io_write_1(bc, hayespioh, HAYESP_CMD1, HAYESP_GETTEST);
    271      1.75       cgd 	val = bus_io_read_1(bc, hayespioh, HAYESP_STATUS1); /* Clear reg 1 */
    272      1.75       cgd 	val = bus_io_read_1(bc, hayespioh, HAYESP_STATUS2);
    273      1.64  christos 	if ((val & 0x70) < 0x20) {
    274      1.64  christos 		printf("-old (%o)", val & 0x70);
    275      1.64  christos 		/* we do not support the necessary features */
    276      1.65  christos 		return 0;
    277      1.64  christos 	}
    278      1.64  christos 
    279      1.64  christos 	/* Check for ability to emulate 16550: bit 8 == 1 */
    280      1.64  christos 	if ((dips & 0x80) == 0) {
    281      1.64  christos 		printf(" slave");
    282      1.64  christos 		/* XXX Does slave really mean no 16550 support?? */
    283      1.65  christos 		return 0;
    284      1.64  christos 	}
    285      1.64  christos 
    286      1.64  christos 	/*
    287      1.64  christos 	 * If we made it this far, we are a full-featured ESP v2.0 (or
    288      1.64  christos 	 * better), at the correct com port address.
    289      1.64  christos 	 */
    290      1.64  christos 
    291      1.65  christos 	SET(sc->sc_hwflags, COM_HW_HAYESP);
    292      1.73    scottr 	printf(", 1024 byte fifo\n");
    293      1.65  christos 	return 1;
    294      1.64  christos }
    295      1.65  christos #endif
    296      1.64  christos 
    297      1.21   mycroft int
    298      1.40   mycroft comprobe(parent, match, aux)
    299      1.40   mycroft 	struct device *parent;
    300      1.40   mycroft 	void *match, *aux;
    301      1.29   mycroft {
    302      1.75       cgd 	bus_chipset_tag_t bc;
    303      1.75       cgd 	bus_io_handle_t ioh;
    304      1.75       cgd 	int iobase, needioh;
    305      1.75       cgd 	int rv = 1;
    306      1.75       cgd 
    307      1.76   thorpej 	/*
    308      1.76   thorpej 	 * XXX should be broken out into functions for isa probe and
    309      1.76   thorpej 	 * XXX for commulti probe, with a helper function that contains
    310      1.76   thorpej 	 * XXX most of the interesting stuff.
    311      1.76   thorpej 	 */
    312      1.77       cgd #if NCOM_ISA
    313      1.75       cgd 	if (!strcmp(parent->dv_cfdata->cf_driver->cd_name, "isa")) {
    314      1.75       cgd 		struct isa_attach_args *ia = aux;
    315      1.75       cgd 
    316      1.75       cgd 		bc = ia->ia_bc;
    317      1.75       cgd 		iobase = ia->ia_iobase;
    318      1.75       cgd 		needioh = 1;
    319      1.77       cgd 	} else
    320      1.77       cgd #endif
    321      1.77       cgd #if NCOM_COMMULTI
    322      1.77       cgd 	if (1) {
    323      1.80  christos 		struct cfdata *cf = match;
    324      1.75       cgd 		struct commulti_attach_args *ca = aux;
    325      1.75       cgd 
    326      1.75       cgd 		if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != ca->ca_slave)
    327      1.75       cgd 			return (0);
    328      1.75       cgd 
    329      1.75       cgd 		bc = ca->ca_bc;
    330      1.75       cgd 		iobase = ca->ca_iobase;
    331      1.75       cgd 		ioh = ca->ca_ioh;
    332      1.75       cgd 		needioh = 0;
    333      1.77       cgd 	} else
    334      1.77       cgd #endif
    335      1.77       cgd 		return(0);			/* This cannot happen */
    336      1.75       cgd 
    337      1.75       cgd 	/* if it's in use as console, it's there. */
    338      1.75       cgd 	if (iobase == comconsaddr && !comconsattached)
    339      1.75       cgd 		goto out;
    340      1.75       cgd 
    341      1.75       cgd 	if (needioh && bus_io_map(bc, iobase, COM_NPORTS, &ioh)) {
    342      1.75       cgd 		rv = 0;
    343      1.75       cgd 		goto out;
    344      1.75       cgd 	}
    345      1.75       cgd 	rv = comprobe1(bc, ioh, iobase);
    346      1.75       cgd 	if (needioh)
    347      1.75       cgd 		bus_io_unmap(bc, ioh, COM_NPORTS);
    348      1.21   mycroft 
    349      1.75       cgd out:
    350      1.77       cgd #if NCOM_ISA
    351      1.75       cgd 	if (rv && !strcmp(parent->dv_cfdata->cf_driver->cd_name, "isa")) {
    352      1.75       cgd 		struct isa_attach_args *ia = aux;
    353      1.21   mycroft 
    354      1.75       cgd 		ia->ia_iosize = COM_NPORTS;
    355      1.75       cgd 		ia->ia_msize = 0;
    356      1.75       cgd 	}
    357      1.77       cgd #endif
    358      1.75       cgd 	return (rv);
    359      1.21   mycroft }
    360       1.1       cgd 
    361      1.29   mycroft void
    362      1.29   mycroft comattach(parent, self, aux)
    363      1.29   mycroft 	struct device *parent, *self;
    364      1.29   mycroft 	void *aux;
    365      1.29   mycroft {
    366      1.29   mycroft 	struct com_softc *sc = (void *)self;
    367      1.75       cgd 	int iobase, irq;
    368      1.75       cgd 	bus_chipset_tag_t bc;
    369      1.75       cgd 	bus_io_handle_t ioh;
    370      1.65  christos #ifdef COM_HAYESP
    371      1.65  christos 	int	hayesp_ports[] = { 0x140, 0x180, 0x280, 0x300, 0 };
    372      1.65  christos 	int	*hayespp;
    373      1.65  christos #endif
    374       1.1       cgd 
    375      1.76   thorpej 	/*
    376      1.76   thorpej 	 * XXX should be broken out into functions for isa attach and
    377      1.76   thorpej 	 * XXX for commulti attach, with a helper function that contains
    378      1.76   thorpej 	 * XXX most of the interesting stuff.
    379      1.76   thorpej 	 */
    380      1.75       cgd 	sc->sc_hwflags = 0;
    381      1.75       cgd 	sc->sc_swflags = 0;
    382      1.77       cgd #if NCOM_ISA
    383      1.75       cgd 	if (!strcmp(parent->dv_cfdata->cf_driver->cd_name, "isa")) {
    384      1.75       cgd 		struct isa_attach_args *ia = aux;
    385      1.75       cgd 
    386      1.75       cgd 		/*
    387      1.75       cgd 		 * We're living on an isa.
    388      1.75       cgd 		 */
    389      1.75       cgd 		iobase = ia->ia_iobase;
    390      1.75       cgd 		bc = ia->ia_bc;
    391      1.75       cgd 	        if (iobase != comconsaddr) {
    392      1.75       cgd 	                if (bus_io_map(bc, iobase, COM_NPORTS, &ioh))
    393      1.75       cgd 				panic("comattach: io mapping failed");
    394      1.75       cgd 		} else
    395      1.75       cgd 	                ioh = comconsioh;
    396      1.75       cgd 		irq = ia->ia_irq;
    397      1.77       cgd 	} else
    398      1.77       cgd #endif
    399      1.77       cgd #if NCOM_COMMULTI
    400      1.77       cgd 	if (1) {
    401      1.75       cgd 		struct commulti_attach_args *ca = aux;
    402      1.75       cgd 
    403      1.75       cgd 		/*
    404      1.75       cgd 		 * We're living on a commulti.
    405      1.75       cgd 		 */
    406      1.75       cgd 		iobase = ca->ca_iobase;
    407      1.75       cgd 		bc = ca->ca_bc;
    408      1.75       cgd 		ioh = ca->ca_ioh;
    409      1.75       cgd 		irq = IRQUNK;
    410      1.75       cgd 
    411      1.75       cgd 		if (ca->ca_noien)
    412      1.75       cgd 			sc->sc_hwflags |= COM_HW_NOIEN;
    413      1.77       cgd 	} else
    414      1.77       cgd #endif
    415      1.77       cgd 		panic("comattach: impossible");
    416      1.75       cgd 
    417      1.75       cgd 	sc->sc_bc = bc;
    418      1.75       cgd 	sc->sc_ioh = ioh;
    419      1.21   mycroft 	sc->sc_iobase = iobase;
    420      1.21   mycroft 
    421      1.75       cgd 	if (iobase == comconsaddr) {
    422      1.75       cgd 		comconsattached = 1;
    423      1.75       cgd 
    424      1.75       cgd 		/*
    425      1.75       cgd 		 * Need to reset baud rate, etc. of next print so reset
    426      1.75       cgd 		 * comconsinit.  Also make sure console is always "hardwired".
    427      1.75       cgd 		 */
    428      1.75       cgd 		delay(1000);			/* wait for output to finish */
    429      1.75       cgd 		comconsinit = 0;
    430      1.75       cgd 		SET(sc->sc_hwflags, COM_HW_CONSOLE);
    431      1.75       cgd 		SET(sc->sc_swflags, COM_SW_SOFTCAR);
    432      1.75       cgd 	}
    433      1.26       cgd 
    434      1.65  christos #ifdef COM_HAYESP
    435      1.65  christos 	/* Look for a Hayes ESP board. */
    436      1.75       cgd 	for (hayespp = hayesp_ports; *hayespp != 0; hayespp++) {
    437      1.75       cgd 		bus_io_handle_t hayespioh;
    438      1.75       cgd 
    439      1.75       cgd #define	HAYESP_NPORTS	8			/* XXX XXX XXX ??? ??? ??? */
    440      1.75       cgd 		if (bus_io_map(bc, *hayespp, HAYESP_NPORTS, &hayespioh))
    441      1.75       cgd 			continue;
    442      1.75       cgd 		if (comprobeHAYESP(hayespioh, sc)) {
    443      1.65  christos 			sc->sc_hayespbase = *hayespp;
    444      1.75       cgd 			sc->sc_hayespioh = hayespioh;
    445      1.65  christos 			break;
    446      1.65  christos 		}
    447      1.75       cgd 		bus_io_unmap(bc, hayespioh, HAYESP_NPORTS);
    448      1.75       cgd 	}
    449      1.65  christos 	/* No ESP; look for other things. */
    450      1.65  christos 	if (*hayespp == 0) {
    451      1.65  christos #endif
    452      1.64  christos 
    453       1.1       cgd 	/* look for a NS 16550AF UART with FIFOs */
    454      1.75       cgd 	bus_io_write_1(bc, ioh, com_fifo,
    455      1.21   mycroft 	    FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_14);
    456      1.20   mycroft 	delay(100);
    457      1.75       cgd 	if (ISSET(bus_io_read_1(bc, ioh, com_iir), IIR_FIFO_MASK) == IIR_FIFO_MASK)
    458      1.75       cgd 		if (ISSET(bus_io_read_1(bc, ioh, com_fifo), FIFO_TRIGGER_14) == FIFO_TRIGGER_14) {
    459      1.62   mycroft 			SET(sc->sc_hwflags, COM_HW_FIFO);
    460      1.29   mycroft 			printf(": ns16550a, working fifo\n");
    461      1.21   mycroft 		} else
    462      1.56       jtc 			printf(": ns16550, broken fifo\n");
    463      1.21   mycroft 	else
    464      1.56       jtc 		printf(": ns8250 or ns16450, no fifo\n");
    465      1.75       cgd 	bus_io_write_1(bc, ioh, com_fifo, 0);
    466      1.65  christos #ifdef COM_HAYESP
    467      1.65  christos 	}
    468      1.65  christos #endif
    469      1.21   mycroft 
    470      1.21   mycroft 	/* disable interrupts */
    471      1.75       cgd 	bus_io_write_1(bc, ioh, com_ier, 0);
    472      1.75       cgd 	bus_io_write_1(bc, ioh, com_mcr, 0);
    473       1.1       cgd 
    474      1.78       cgd 	if (irq != IRQUNK) {
    475      1.78       cgd #if NCOM_ISA
    476      1.78       cgd 		if (!strcmp(parent->dv_cfdata->cf_driver->cd_name, "isa")) {
    477      1.78       cgd 			struct isa_attach_args *ia = aux;
    478      1.78       cgd 
    479      1.78       cgd 			sc->sc_ih = isa_intr_establish(ia->ia_ic, irq,
    480      1.78       cgd 			    IST_EDGE, IPL_TTY, comintr, sc);
    481      1.78       cgd 		} else
    482      1.78       cgd #endif
    483      1.78       cgd 			panic("comattach: IRQ but can't have one");
    484      1.78       cgd 	}
    485      1.30   mycroft 
    486       1.1       cgd #ifdef KGDB
    487       1.2       cgd 	if (kgdb_dev == makedev(commajor, unit)) {
    488      1.75       cgd 		if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
    489       1.1       cgd 			kgdb_dev = -1;	/* can't debug over console port */
    490       1.1       cgd 		else {
    491      1.80  christos 			cominit(bc, ioh, kgdb_rate);
    492       1.1       cgd 			if (kgdb_debug_init) {
    493       1.1       cgd 				/*
    494       1.1       cgd 				 * Print prefix of device name,
    495       1.1       cgd 				 * let kgdb_connect print the rest.
    496       1.1       cgd 				 */
    497      1.21   mycroft 				printf("%s: ", sc->sc_dev.dv_xname);
    498       1.1       cgd 				kgdb_connect(1);
    499       1.1       cgd 			} else
    500      1.21   mycroft 				printf("%s: kgdb enabled\n",
    501      1.21   mycroft 				    sc->sc_dev.dv_xname);
    502       1.1       cgd 		}
    503       1.1       cgd 	}
    504       1.1       cgd #endif
    505      1.21   mycroft 
    506      1.75       cgd 	/* XXX maybe move up some? */
    507      1.75       cgd 	if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
    508      1.75       cgd 		printf("%s: console\n", sc->sc_dev.dv_xname);
    509       1.1       cgd }
    510       1.1       cgd 
    511      1.21   mycroft int
    512      1.21   mycroft comopen(dev, flag, mode, p)
    513      1.21   mycroft 	dev_t dev;
    514      1.21   mycroft 	int flag, mode;
    515      1.21   mycroft 	struct proc *p;
    516       1.1       cgd {
    517      1.21   mycroft 	int unit = COMUNIT(dev);
    518      1.21   mycroft 	struct com_softc *sc;
    519      1.75       cgd 	bus_chipset_tag_t bc;
    520      1.75       cgd 	bus_io_handle_t ioh;
    521      1.21   mycroft 	struct tty *tp;
    522      1.21   mycroft 	int s;
    523       1.1       cgd 	int error = 0;
    524       1.1       cgd 
    525      1.76   thorpej 	if (unit >= com_cd.cd_ndevs)
    526      1.21   mycroft 		return ENXIO;
    527      1.76   thorpej 	sc = com_cd.cd_devs[unit];
    528      1.29   mycroft 	if (!sc)
    529      1.21   mycroft 		return ENXIO;
    530      1.21   mycroft 
    531  1.82.4.1       mrg 	if (!sc->sc_tty) {
    532      1.50   mycroft 		tp = sc->sc_tty = ttymalloc();
    533  1.82.4.1       mrg 		tty_attach(tp);
    534  1.82.4.1       mrg 	} else
    535      1.50   mycroft 		tp = sc->sc_tty;
    536      1.21   mycroft 
    537       1.1       cgd 	tp->t_oproc = comstart;
    538       1.1       cgd 	tp->t_param = comparam;
    539       1.1       cgd 	tp->t_dev = dev;
    540      1.62   mycroft 	if (!ISSET(tp->t_state, TS_ISOPEN)) {
    541      1.62   mycroft 		SET(tp->t_state, TS_WOPEN);
    542       1.1       cgd 		ttychars(tp);
    543      1.16        ws 		tp->t_iflag = TTYDEF_IFLAG;
    544      1.16        ws 		tp->t_oflag = TTYDEF_OFLAG;
    545      1.79       cgd 		if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
    546      1.79       cgd 			tp->t_cflag = comconscflag;
    547      1.79       cgd 		else
    548      1.79       cgd 			tp->t_cflag = TTYDEF_CFLAG;
    549      1.62   mycroft 		if (ISSET(sc->sc_swflags, COM_SW_CLOCAL))
    550      1.62   mycroft 			SET(tp->t_cflag, CLOCAL);
    551      1.62   mycroft 		if (ISSET(sc->sc_swflags, COM_SW_CRTSCTS))
    552      1.62   mycroft 			SET(tp->t_cflag, CRTSCTS);
    553      1.62   mycroft 		if (ISSET(sc->sc_swflags, COM_SW_MDMBUF))
    554      1.62   mycroft 			SET(tp->t_cflag, MDMBUF);
    555      1.16        ws 		tp->t_lflag = TTYDEF_LFLAG;
    556      1.16        ws 		tp->t_ispeed = tp->t_ospeed = comdefaultrate;
    557      1.57   mycroft 
    558      1.57   mycroft 		s = spltty();
    559      1.57   mycroft 
    560       1.1       cgd 		comparam(tp, &tp->t_termios);
    561       1.1       cgd 		ttsetwater(tp);
    562      1.21   mycroft 
    563      1.57   mycroft 		if (comsopen++ == 0)
    564      1.57   mycroft 			timeout(compoll, NULL, 1);
    565      1.57   mycroft 
    566      1.57   mycroft 		sc->sc_ibufp = sc->sc_ibuf = sc->sc_ibufs[0];
    567      1.57   mycroft 		sc->sc_ibufhigh = sc->sc_ibuf + COM_IHIGHWATER;
    568      1.57   mycroft 		sc->sc_ibufend = sc->sc_ibuf + COM_IBUFSIZE;
    569      1.57   mycroft 
    570      1.75       cgd 		bc = sc->sc_bc;
    571      1.75       cgd 		ioh = sc->sc_ioh;
    572      1.65  christos #ifdef COM_HAYESP
    573      1.64  christos 		/* Setup the ESP board */
    574      1.65  christos 		if (ISSET(sc->sc_hwflags, COM_HW_HAYESP)) {
    575      1.75       cgd 			bus_io_handle_t hayespioh = sc->sc_hayespioh;
    576      1.65  christos 
    577      1.75       cgd 			bus_io_write_1(bc, ioh, com_fifo,
    578      1.64  christos 			     FIFO_DMA_MODE|FIFO_ENABLE|
    579      1.64  christos 			     FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_8);
    580      1.65  christos 
    581      1.64  christos 			/* Set 16550 compatibility mode */
    582      1.75       cgd 			bus_io_write_1(bc, hayespioh, HAYESP_CMD1, HAYESP_SETMODE);
    583      1.75       cgd 			bus_io_write_1(bc, hayespioh, HAYESP_CMD2,
    584      1.65  christos 			     HAYESP_MODE_FIFO|HAYESP_MODE_RTS|
    585      1.65  christos 			     HAYESP_MODE_SCALE);
    586      1.65  christos 
    587      1.64  christos 			/* Set RTS/CTS flow control */
    588      1.75       cgd 			bus_io_write_1(bc, hayespioh, HAYESP_CMD1, HAYESP_SETFLOWTYPE);
    589      1.75       cgd 			bus_io_write_1(bc, hayespioh, HAYESP_CMD2, HAYESP_FLOW_RTS);
    590      1.75       cgd 			bus_io_write_1(bc, hayespioh, HAYESP_CMD2, HAYESP_FLOW_CTS);
    591      1.65  christos 
    592      1.64  christos 			/* Set flow control levels */
    593      1.75       cgd 			bus_io_write_1(bc, hayespioh, HAYESP_CMD1, HAYESP_SETRXFLOW);
    594      1.75       cgd 			bus_io_write_1(bc, hayespioh, HAYESP_CMD2,
    595      1.65  christos 			     HAYESP_HIBYTE(HAYESP_RXHIWMARK));
    596      1.75       cgd 			bus_io_write_1(bc, hayespioh, HAYESP_CMD2,
    597      1.65  christos 			     HAYESP_LOBYTE(HAYESP_RXHIWMARK));
    598      1.75       cgd 			bus_io_write_1(bc, hayespioh, HAYESP_CMD2,
    599      1.65  christos 			     HAYESP_HIBYTE(HAYESP_RXLOWMARK));
    600      1.75       cgd 			bus_io_write_1(bc, hayespioh, HAYESP_CMD2,
    601      1.65  christos 			     HAYESP_LOBYTE(HAYESP_RXLOWMARK));
    602      1.65  christos 		} else
    603      1.65  christos #endif
    604      1.65  christos 		if (ISSET(sc->sc_hwflags, COM_HW_FIFO))
    605      1.64  christos 			/* Set the FIFO threshold based on the receive speed. */
    606      1.75       cgd 			bus_io_write_1(bc, ioh, com_fifo,
    607      1.36   mycroft 			    FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST |
    608      1.36   mycroft 			    (tp->t_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8));
    609      1.21   mycroft 		/* flush any pending I/O */
    610      1.75       cgd 		while (ISSET(bus_io_read_1(bc, ioh, com_lsr), LSR_RXRDY))
    611      1.75       cgd 			(void) bus_io_read_1(bc, ioh, com_data);
    612      1.21   mycroft 		/* you turn me on, baby */
    613      1.26       cgd 		sc->sc_mcr = MCR_DTR | MCR_RTS;
    614      1.62   mycroft 		if (!ISSET(sc->sc_hwflags, COM_HW_NOIEN))
    615      1.62   mycroft 			SET(sc->sc_mcr, MCR_IENABLE);
    616      1.75       cgd 		bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
    617      1.69   mycroft 		sc->sc_ier = IER_ERXRDY | IER_ERLS | IER_EMSC;
    618      1.75       cgd 		bus_io_write_1(bc, ioh, com_ier, sc->sc_ier);
    619      1.21   mycroft 
    620      1.75       cgd 		sc->sc_msr = bus_io_read_1(bc, ioh, com_msr);
    621      1.62   mycroft 		if (ISSET(sc->sc_swflags, COM_SW_SOFTCAR) ||
    622      1.62   mycroft 		    ISSET(sc->sc_msr, MSR_DCD) || ISSET(tp->t_cflag, MDMBUF))
    623      1.62   mycroft 			SET(tp->t_state, TS_CARR_ON);
    624      1.21   mycroft 		else
    625      1.62   mycroft 			CLR(tp->t_state, TS_CARR_ON);
    626      1.62   mycroft 	} else if (ISSET(tp->t_state, TS_XCLUDE) && p->p_ucred->cr_uid != 0)
    627      1.21   mycroft 		return EBUSY;
    628      1.62   mycroft 	else
    629      1.57   mycroft 		s = spltty();
    630      1.21   mycroft 
    631      1.21   mycroft 	/* wait for carrier if necessary */
    632      1.62   mycroft 	if (!ISSET(flag, O_NONBLOCK))
    633      1.62   mycroft 		while (!ISSET(tp->t_cflag, CLOCAL) &&
    634      1.62   mycroft 		    !ISSET(tp->t_state, TS_CARR_ON)) {
    635      1.62   mycroft 			SET(tp->t_state, TS_WOPEN);
    636      1.62   mycroft 			error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH,
    637      1.62   mycroft 			    ttopen, 0);
    638      1.21   mycroft 			if (error) {
    639      1.21   mycroft 				/* XXX should turn off chip if we're the
    640      1.21   mycroft 				   only waiter */
    641      1.21   mycroft 				splx(s);
    642      1.21   mycroft 				return error;
    643      1.21   mycroft 			}
    644      1.21   mycroft 		}
    645      1.21   mycroft 	splx(s);
    646      1.21   mycroft 
    647      1.21   mycroft 	return (*linesw[tp->t_line].l_open)(dev, tp);
    648       1.1       cgd }
    649       1.1       cgd 
    650      1.21   mycroft int
    651       1.1       cgd comclose(dev, flag, mode, p)
    652       1.1       cgd 	dev_t dev;
    653       1.1       cgd 	int flag, mode;
    654       1.1       cgd 	struct proc *p;
    655       1.1       cgd {
    656      1.21   mycroft 	int unit = COMUNIT(dev);
    657      1.76   thorpej 	struct com_softc *sc = com_cd.cd_devs[unit];
    658      1.50   mycroft 	struct tty *tp = sc->sc_tty;
    659      1.75       cgd 	bus_chipset_tag_t bc = sc->sc_bc;
    660      1.75       cgd 	bus_io_handle_t ioh = sc->sc_ioh;
    661      1.57   mycroft 	int s;
    662      1.57   mycroft 
    663      1.57   mycroft 	/* XXX This is for cons.c. */
    664      1.62   mycroft 	if (!ISSET(tp->t_state, TS_ISOPEN))
    665      1.57   mycroft 		return 0;
    666      1.21   mycroft 
    667       1.1       cgd 	(*linesw[tp->t_line].l_close)(tp, flag);
    668      1.57   mycroft 	s = spltty();
    669      1.62   mycroft 	CLR(sc->sc_lcr, LCR_SBREAK);
    670      1.75       cgd 	bus_io_write_1(bc, ioh, com_lcr, sc->sc_lcr);
    671      1.75       cgd 	bus_io_write_1(bc, ioh, com_ier, 0);
    672      1.62   mycroft 	if (ISSET(tp->t_cflag, HUPCL) &&
    673      1.62   mycroft 	    !ISSET(sc->sc_swflags, COM_SW_SOFTCAR)) {
    674      1.57   mycroft 		/* XXX perhaps only clear DTR */
    675      1.75       cgd 		bus_io_write_1(bc, ioh, com_mcr, 0);
    676      1.57   mycroft 	}
    677      1.62   mycroft 	CLR(tp->t_state, TS_BUSY | TS_FLUSH);
    678      1.57   mycroft 	if (--comsopen == 0)
    679      1.57   mycroft 		untimeout(compoll, NULL);
    680      1.57   mycroft 	splx(s);
    681       1.1       cgd 	ttyclose(tp);
    682      1.21   mycroft #ifdef notyet /* XXXX */
    683      1.75       cgd 	if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
    684      1.21   mycroft 		ttyfree(tp);
    685      1.50   mycroft 		sc->sc_tty = 0;
    686      1.21   mycroft 	}
    687      1.13       cgd #endif
    688      1.21   mycroft 	return 0;
    689       1.1       cgd }
    690       1.1       cgd 
    691      1.21   mycroft int
    692       1.1       cgd comread(dev, uio, flag)
    693       1.1       cgd 	dev_t dev;
    694       1.1       cgd 	struct uio *uio;
    695      1.21   mycroft 	int flag;
    696       1.1       cgd {
    697      1.76   thorpej 	struct com_softc *sc = com_cd.cd_devs[COMUNIT(dev)];
    698      1.52   mycroft 	struct tty *tp = sc->sc_tty;
    699       1.1       cgd 
    700       1.1       cgd 	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
    701       1.1       cgd }
    702       1.1       cgd 
    703      1.21   mycroft int
    704       1.1       cgd comwrite(dev, uio, flag)
    705       1.1       cgd 	dev_t dev;
    706       1.1       cgd 	struct uio *uio;
    707      1.21   mycroft 	int flag;
    708       1.1       cgd {
    709      1.76   thorpej 	struct com_softc *sc = com_cd.cd_devs[COMUNIT(dev)];
    710      1.52   mycroft 	struct tty *tp = sc->sc_tty;
    711       1.1       cgd 
    712       1.1       cgd 	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
    713       1.1       cgd }
    714      1.50   mycroft 
    715      1.50   mycroft struct tty *
    716      1.50   mycroft comtty(dev)
    717      1.50   mycroft 	dev_t dev;
    718      1.50   mycroft {
    719      1.76   thorpej 	struct com_softc *sc = com_cd.cd_devs[COMUNIT(dev)];
    720      1.52   mycroft 	struct tty *tp = sc->sc_tty;
    721      1.50   mycroft 
    722      1.52   mycroft 	return (tp);
    723      1.50   mycroft }
    724       1.1       cgd 
    725      1.21   mycroft static u_char
    726      1.21   mycroft tiocm_xxx2mcr(data)
    727      1.21   mycroft 	int data;
    728      1.21   mycroft {
    729      1.21   mycroft 	u_char m = 0;
    730      1.21   mycroft 
    731      1.62   mycroft 	if (ISSET(data, TIOCM_DTR))
    732      1.62   mycroft 		SET(m, MCR_DTR);
    733      1.62   mycroft 	if (ISSET(data, TIOCM_RTS))
    734      1.62   mycroft 		SET(m, MCR_RTS);
    735      1.21   mycroft 	return m;
    736       1.1       cgd }
    737       1.1       cgd 
    738      1.21   mycroft int
    739      1.19   mycroft comioctl(dev, cmd, data, flag, p)
    740       1.1       cgd 	dev_t dev;
    741      1.39       cgd 	u_long cmd;
    742       1.1       cgd 	caddr_t data;
    743      1.19   mycroft 	int flag;
    744      1.19   mycroft 	struct proc *p;
    745       1.1       cgd {
    746      1.21   mycroft 	int unit = COMUNIT(dev);
    747      1.76   thorpej 	struct com_softc *sc = com_cd.cd_devs[unit];
    748      1.50   mycroft 	struct tty *tp = sc->sc_tty;
    749      1.75       cgd 	bus_chipset_tag_t bc = sc->sc_bc;
    750      1.75       cgd 	bus_io_handle_t ioh = sc->sc_ioh;
    751      1.21   mycroft 	int error;
    752      1.21   mycroft 
    753      1.19   mycroft 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
    754       1.1       cgd 	if (error >= 0)
    755      1.21   mycroft 		return error;
    756      1.19   mycroft 	error = ttioctl(tp, cmd, data, flag, p);
    757       1.1       cgd 	if (error >= 0)
    758      1.21   mycroft 		return error;
    759       1.1       cgd 
    760       1.1       cgd 	switch (cmd) {
    761       1.1       cgd 	case TIOCSBRK:
    762      1.62   mycroft 		SET(sc->sc_lcr, LCR_SBREAK);
    763      1.75       cgd 		bus_io_write_1(bc, ioh, com_lcr, sc->sc_lcr);
    764       1.1       cgd 		break;
    765       1.1       cgd 	case TIOCCBRK:
    766      1.62   mycroft 		CLR(sc->sc_lcr, LCR_SBREAK);
    767      1.75       cgd 		bus_io_write_1(bc, ioh, com_lcr, sc->sc_lcr);
    768       1.1       cgd 		break;
    769       1.1       cgd 	case TIOCSDTR:
    770      1.62   mycroft 		SET(sc->sc_mcr, sc->sc_dtr);
    771      1.75       cgd 		bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
    772       1.1       cgd 		break;
    773       1.1       cgd 	case TIOCCDTR:
    774      1.62   mycroft 		CLR(sc->sc_mcr, sc->sc_dtr);
    775      1.75       cgd 		bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
    776       1.1       cgd 		break;
    777       1.1       cgd 	case TIOCMSET:
    778      1.62   mycroft 		CLR(sc->sc_mcr, MCR_DTR | MCR_RTS);
    779       1.1       cgd 	case TIOCMBIS:
    780      1.62   mycroft 		SET(sc->sc_mcr, tiocm_xxx2mcr(*(int *)data));
    781      1.75       cgd 		bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
    782       1.1       cgd 		break;
    783       1.1       cgd 	case TIOCMBIC:
    784      1.62   mycroft 		CLR(sc->sc_mcr, tiocm_xxx2mcr(*(int *)data));
    785      1.75       cgd 		bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
    786       1.1       cgd 		break;
    787      1.21   mycroft 	case TIOCMGET: {
    788      1.21   mycroft 		u_char m;
    789      1.21   mycroft 		int bits = 0;
    790      1.21   mycroft 
    791      1.21   mycroft 		m = sc->sc_mcr;
    792      1.62   mycroft 		if (ISSET(m, MCR_DTR))
    793      1.62   mycroft 			SET(bits, TIOCM_DTR);
    794      1.62   mycroft 		if (ISSET(m, MCR_RTS))
    795      1.62   mycroft 			SET(bits, TIOCM_RTS);
    796      1.21   mycroft 		m = sc->sc_msr;
    797      1.62   mycroft 		if (ISSET(m, MSR_DCD))
    798      1.62   mycroft 			SET(bits, TIOCM_CD);
    799      1.62   mycroft 		if (ISSET(m, MSR_CTS))
    800      1.62   mycroft 			SET(bits, TIOCM_CTS);
    801      1.62   mycroft 		if (ISSET(m, MSR_DSR))
    802      1.62   mycroft 			SET(bits, TIOCM_DSR);
    803      1.62   mycroft 		if (ISSET(m, MSR_RI | MSR_TERI))
    804      1.62   mycroft 			SET(bits, TIOCM_RI);
    805      1.75       cgd 		if (bus_io_read_1(bc, ioh, com_ier))
    806      1.62   mycroft 			SET(bits, TIOCM_LE);
    807      1.21   mycroft 		*(int *)data = bits;
    808       1.1       cgd 		break;
    809      1.21   mycroft 	}
    810      1.22       cgd 	case TIOCGFLAGS: {
    811      1.62   mycroft 		int driverbits, userbits = 0;
    812      1.22       cgd 
    813      1.62   mycroft 		driverbits = sc->sc_swflags;
    814      1.62   mycroft 		if (ISSET(driverbits, COM_SW_SOFTCAR))
    815      1.62   mycroft 			SET(userbits, TIOCFLAG_SOFTCAR);
    816      1.62   mycroft 		if (ISSET(driverbits, COM_SW_CLOCAL))
    817      1.62   mycroft 			SET(userbits, TIOCFLAG_CLOCAL);
    818      1.62   mycroft 		if (ISSET(driverbits, COM_SW_CRTSCTS))
    819      1.62   mycroft 			SET(userbits, TIOCFLAG_CRTSCTS);
    820      1.62   mycroft 		if (ISSET(driverbits, COM_SW_MDMBUF))
    821      1.62   mycroft 			SET(userbits, TIOCFLAG_MDMBUF);
    822      1.22       cgd 
    823      1.62   mycroft 		*(int *)data = userbits;
    824      1.22       cgd 		break;
    825      1.22       cgd 	}
    826      1.22       cgd 	case TIOCSFLAGS: {
    827      1.22       cgd 		int userbits, driverbits = 0;
    828      1.22       cgd 
    829      1.23       cgd 		error = suser(p->p_ucred, &p->p_acflag);
    830      1.23       cgd 		if (error != 0)
    831      1.23       cgd 			return(EPERM);
    832      1.22       cgd 
    833      1.22       cgd 		userbits = *(int *)data;
    834      1.62   mycroft 		if (ISSET(userbits, TIOCFLAG_SOFTCAR) ||
    835      1.62   mycroft 		    ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
    836      1.62   mycroft 			SET(driverbits, COM_SW_SOFTCAR);
    837      1.62   mycroft 		if (ISSET(userbits, TIOCFLAG_CLOCAL))
    838      1.62   mycroft 			SET(driverbits, COM_SW_CLOCAL);
    839      1.62   mycroft 		if (ISSET(userbits, TIOCFLAG_CRTSCTS))
    840      1.62   mycroft 			SET(driverbits, COM_SW_CRTSCTS);
    841      1.62   mycroft 		if (ISSET(userbits, TIOCFLAG_MDMBUF))
    842      1.62   mycroft 			SET(driverbits, COM_SW_MDMBUF);
    843      1.22       cgd 
    844      1.23       cgd 		sc->sc_swflags = driverbits;
    845      1.22       cgd 		break;
    846      1.22       cgd 	}
    847       1.1       cgd 	default:
    848      1.21   mycroft 		return ENOTTY;
    849       1.1       cgd 	}
    850      1.21   mycroft 
    851      1.21   mycroft 	return 0;
    852       1.1       cgd }
    853       1.1       cgd 
    854      1.21   mycroft int
    855       1.1       cgd comparam(tp, t)
    856      1.21   mycroft 	struct tty *tp;
    857      1.21   mycroft 	struct termios *t;
    858       1.1       cgd {
    859      1.76   thorpej 	struct com_softc *sc = com_cd.cd_devs[COMUNIT(tp->t_dev)];
    860      1.75       cgd 	bus_chipset_tag_t bc = sc->sc_bc;
    861      1.75       cgd 	bus_io_handle_t ioh = sc->sc_ioh;
    862      1.21   mycroft 	int ospeed = comspeed(t->c_ospeed);
    863      1.62   mycroft 	u_char lcr;
    864      1.57   mycroft 	tcflag_t oldcflag;
    865      1.21   mycroft 	int s;
    866      1.21   mycroft 
    867       1.1       cgd 	/* check requested parameters */
    868      1.21   mycroft 	if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
    869      1.21   mycroft 		return EINVAL;
    870      1.21   mycroft 
    871      1.66   mycroft 	lcr = ISSET(sc->sc_lcr, LCR_SBREAK);
    872      1.62   mycroft 
    873      1.62   mycroft 	switch (ISSET(t->c_cflag, CSIZE)) {
    874       1.1       cgd 	case CS5:
    875      1.62   mycroft 		SET(lcr, LCR_5BITS);
    876      1.21   mycroft 		break;
    877       1.1       cgd 	case CS6:
    878      1.62   mycroft 		SET(lcr, LCR_6BITS);
    879      1.21   mycroft 		break;
    880       1.1       cgd 	case CS7:
    881      1.62   mycroft 		SET(lcr, LCR_7BITS);
    882      1.21   mycroft 		break;
    883       1.1       cgd 	case CS8:
    884      1.62   mycroft 		SET(lcr, LCR_8BITS);
    885      1.21   mycroft 		break;
    886       1.1       cgd 	}
    887      1.62   mycroft 	if (ISSET(t->c_cflag, PARENB)) {
    888      1.62   mycroft 		SET(lcr, LCR_PENAB);
    889      1.62   mycroft 		if (!ISSET(t->c_cflag, PARODD))
    890      1.62   mycroft 			SET(lcr, LCR_PEVEN);
    891       1.1       cgd 	}
    892      1.62   mycroft 	if (ISSET(t->c_cflag, CSTOPB))
    893      1.62   mycroft 		SET(lcr, LCR_STOPB);
    894      1.62   mycroft 
    895      1.62   mycroft 	sc->sc_lcr = lcr;
    896       1.1       cgd 
    897      1.21   mycroft 	s = spltty();
    898      1.35   mycroft 
    899      1.62   mycroft 	if (ospeed == 0) {
    900      1.62   mycroft 		CLR(sc->sc_mcr, MCR_DTR);
    901      1.75       cgd 		bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
    902      1.62   mycroft 	}
    903      1.36   mycroft 
    904      1.36   mycroft 	/*
    905      1.36   mycroft 	 * Set the FIFO threshold based on the receive speed, if we are
    906      1.36   mycroft 	 * changing it.
    907      1.36   mycroft 	 */
    908      1.66   mycroft #if 1
    909      1.65  christos 	if (tp->t_ispeed != t->c_ispeed) {
    910      1.66   mycroft #else
    911      1.66   mycroft 	if (1) {
    912      1.66   mycroft #endif
    913      1.66   mycroft 		if (ospeed != 0) {
    914      1.66   mycroft 			/*
    915      1.66   mycroft 			 * Make sure the transmit FIFO is empty before
    916      1.67   mycroft 			 * proceeding.  If we don't do this, some revisions
    917      1.67   mycroft 			 * of the UART will hang.  Interestingly enough,
    918      1.67   mycroft 			 * even if we do this will the last character is
    919      1.67   mycroft 			 * still being pushed out, they don't hang.  This
    920      1.67   mycroft 			 * seems good enough.
    921      1.66   mycroft 			 */
    922      1.66   mycroft 			while (ISSET(tp->t_state, TS_BUSY)) {
    923      1.66   mycroft 				int error;
    924      1.66   mycroft 
    925      1.66   mycroft 				++sc->sc_halt;
    926      1.66   mycroft 				error = ttysleep(tp, &tp->t_outq,
    927      1.66   mycroft 				    TTOPRI | PCATCH, "comprm", 0);
    928      1.66   mycroft 				--sc->sc_halt;
    929      1.66   mycroft 				if (error) {
    930      1.66   mycroft 					splx(s);
    931      1.66   mycroft 					comstart(tp);
    932      1.66   mycroft 					return (error);
    933      1.66   mycroft 				}
    934      1.66   mycroft 			}
    935      1.66   mycroft 
    936      1.75       cgd 			bus_io_write_1(bc, ioh, com_lcr, lcr | LCR_DLAB);
    937      1.75       cgd 			bus_io_write_1(bc, ioh, com_dlbl, ospeed);
    938      1.75       cgd 			bus_io_write_1(bc, ioh, com_dlbh, ospeed >> 8);
    939      1.75       cgd 			bus_io_write_1(bc, ioh, com_lcr, lcr);
    940      1.66   mycroft 			SET(sc->sc_mcr, MCR_DTR);
    941      1.75       cgd 			bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
    942      1.66   mycroft 		} else
    943      1.75       cgd 			bus_io_write_1(bc, ioh, com_lcr, lcr);
    944      1.66   mycroft 
    945      1.66   mycroft 		if (!ISSET(sc->sc_hwflags, COM_HW_HAYESP) &&
    946      1.66   mycroft 		    ISSET(sc->sc_hwflags, COM_HW_FIFO))
    947      1.75       cgd 			bus_io_write_1(bc, ioh, com_fifo,
    948      1.57   mycroft 			    FIFO_ENABLE |
    949      1.36   mycroft 			    (t->c_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8));
    950      1.57   mycroft 	} else
    951      1.75       cgd 		bus_io_write_1(bc, ioh, com_lcr, lcr);
    952      1.21   mycroft 
    953      1.22       cgd 	/* When not using CRTSCTS, RTS follows DTR. */
    954      1.62   mycroft 	if (!ISSET(t->c_cflag, CRTSCTS)) {
    955      1.62   mycroft 		if (ISSET(sc->sc_mcr, MCR_DTR)) {
    956      1.62   mycroft 			if (!ISSET(sc->sc_mcr, MCR_RTS)) {
    957      1.62   mycroft 				SET(sc->sc_mcr, MCR_RTS);
    958      1.75       cgd 				bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
    959      1.62   mycroft 			}
    960      1.21   mycroft 		} else {
    961      1.62   mycroft 			if (ISSET(sc->sc_mcr, MCR_RTS)) {
    962      1.62   mycroft 				CLR(sc->sc_mcr, MCR_RTS);
    963      1.75       cgd 				bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
    964      1.62   mycroft 			}
    965      1.21   mycroft 		}
    966      1.57   mycroft 		sc->sc_dtr = MCR_DTR | MCR_RTS;
    967      1.57   mycroft 	} else
    968      1.57   mycroft 		sc->sc_dtr = MCR_DTR;
    969      1.21   mycroft 
    970      1.57   mycroft 	/* and copy to tty */
    971      1.57   mycroft 	tp->t_ispeed = t->c_ispeed;
    972      1.57   mycroft 	tp->t_ospeed = t->c_ospeed;
    973      1.57   mycroft 	oldcflag = tp->t_cflag;
    974      1.57   mycroft 	tp->t_cflag = t->c_cflag;
    975      1.25       cgd 
    976      1.25       cgd 	/*
    977      1.57   mycroft 	 * If DCD is off and MDMBUF is changed, ask the tty layer if we should
    978      1.57   mycroft 	 * stop the device.
    979      1.25       cgd 	 */
    980      1.62   mycroft 	if (!ISSET(sc->sc_msr, MSR_DCD) &&
    981      1.62   mycroft 	    !ISSET(sc->sc_swflags, COM_SW_SOFTCAR) &&
    982      1.62   mycroft 	    ISSET(oldcflag, MDMBUF) != ISSET(tp->t_cflag, MDMBUF) &&
    983      1.57   mycroft 	    (*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
    984      1.62   mycroft 		CLR(sc->sc_mcr, sc->sc_dtr);
    985      1.75       cgd 		bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
    986      1.21   mycroft 	}
    987       1.1       cgd 
    988      1.66   mycroft 	/* Just to be sure... */
    989      1.21   mycroft 	splx(s);
    990      1.66   mycroft 	comstart(tp);
    991      1.21   mycroft 	return 0;
    992       1.1       cgd }
    993      1.21   mycroft 
    994      1.12   deraadt void
    995       1.1       cgd comstart(tp)
    996      1.21   mycroft 	struct tty *tp;
    997       1.1       cgd {
    998      1.76   thorpej 	struct com_softc *sc = com_cd.cd_devs[COMUNIT(tp->t_dev)];
    999      1.75       cgd 	bus_chipset_tag_t bc = sc->sc_bc;
   1000      1.75       cgd 	bus_io_handle_t ioh = sc->sc_ioh;
   1001      1.21   mycroft 	int s;
   1002      1.21   mycroft 
   1003       1.1       cgd 	s = spltty();
   1004      1.69   mycroft 	if (ISSET(tp->t_state, TS_BUSY))
   1005      1.70   mycroft 		goto out;
   1006      1.69   mycroft 	if (ISSET(tp->t_state, TS_TIMEOUT | TS_TTSTOP) ||
   1007      1.69   mycroft 	    sc->sc_halt > 0)
   1008      1.69   mycroft 		goto stopped;
   1009      1.62   mycroft 	if (ISSET(tp->t_cflag, CRTSCTS) && !ISSET(sc->sc_msr, MSR_CTS))
   1010      1.69   mycroft 		goto stopped;
   1011      1.61   mycroft 	if (tp->t_outq.c_cc <= tp->t_lowat) {
   1012      1.62   mycroft 		if (ISSET(tp->t_state, TS_ASLEEP)) {
   1013      1.62   mycroft 			CLR(tp->t_state, TS_ASLEEP);
   1014      1.62   mycroft 			wakeup(&tp->t_outq);
   1015      1.61   mycroft 		}
   1016      1.61   mycroft 		if (tp->t_outq.c_cc == 0)
   1017      1.69   mycroft 			goto stopped;
   1018      1.61   mycroft 		selwakeup(&tp->t_wsel);
   1019      1.61   mycroft 	}
   1020      1.62   mycroft 	SET(tp->t_state, TS_BUSY);
   1021      1.64  christos 
   1022      1.70   mycroft 	if (!ISSET(sc->sc_ier, IER_ETXRDY)) {
   1023      1.70   mycroft 		SET(sc->sc_ier, IER_ETXRDY);
   1024      1.75       cgd 		bus_io_write_1(bc, ioh, com_ier, sc->sc_ier);
   1025      1.70   mycroft 	}
   1026      1.65  christos #ifdef COM_HAYESP
   1027      1.65  christos 	if (ISSET(sc->sc_hwflags, COM_HW_HAYESP)) {
   1028      1.64  christos 		u_char buffer[1024], *cp = buffer;
   1029      1.64  christos 		int n = q_to_b(&tp->t_outq, cp, sizeof buffer);
   1030      1.64  christos 		do
   1031      1.75       cgd 			bus_io_write_1(bc, ioh, com_data, *cp++);
   1032      1.64  christos 		while (--n);
   1033      1.64  christos 	}
   1034      1.65  christos 	else
   1035      1.65  christos #endif
   1036      1.65  christos 	if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) {
   1037      1.21   mycroft 		u_char buffer[16], *cp = buffer;
   1038      1.21   mycroft 		int n = q_to_b(&tp->t_outq, cp, sizeof buffer);
   1039      1.21   mycroft 		do {
   1040      1.75       cgd 			bus_io_write_1(bc, ioh, com_data, *cp++);
   1041      1.21   mycroft 		} while (--n);
   1042      1.21   mycroft 	} else
   1043      1.75       cgd 		bus_io_write_1(bc, ioh, com_data, getc(&tp->t_outq));
   1044      1.70   mycroft out:
   1045      1.69   mycroft 	splx(s);
   1046      1.69   mycroft 	return;
   1047      1.69   mycroft stopped:
   1048      1.69   mycroft 	if (ISSET(sc->sc_ier, IER_ETXRDY)) {
   1049      1.69   mycroft 		CLR(sc->sc_ier, IER_ETXRDY);
   1050      1.75       cgd 		bus_io_write_1(bc, ioh, com_ier, sc->sc_ier);
   1051      1.69   mycroft 	}
   1052       1.1       cgd 	splx(s);
   1053       1.1       cgd }
   1054      1.21   mycroft 
   1055       1.1       cgd /*
   1056       1.1       cgd  * Stop output on a line.
   1057       1.1       cgd  */
   1058      1.80  christos int
   1059       1.1       cgd comstop(tp, flag)
   1060      1.21   mycroft 	struct tty *tp;
   1061      1.80  christos 	int flag;
   1062       1.1       cgd {
   1063      1.21   mycroft 	int s;
   1064       1.1       cgd 
   1065       1.1       cgd 	s = spltty();
   1066      1.62   mycroft 	if (ISSET(tp->t_state, TS_BUSY))
   1067      1.62   mycroft 		if (!ISSET(tp->t_state, TS_TTSTOP))
   1068      1.62   mycroft 			SET(tp->t_state, TS_FLUSH);
   1069       1.1       cgd 	splx(s);
   1070      1.80  christos 	return 0;
   1071       1.1       cgd }
   1072       1.1       cgd 
   1073      1.33   mycroft void
   1074      1.33   mycroft comdiag(arg)
   1075      1.33   mycroft 	void *arg;
   1076      1.33   mycroft {
   1077      1.33   mycroft 	struct com_softc *sc = arg;
   1078      1.57   mycroft 	int overflows, floods;
   1079      1.33   mycroft 	int s;
   1080      1.33   mycroft 
   1081      1.33   mycroft 	s = spltty();
   1082      1.57   mycroft 	sc->sc_errors = 0;
   1083      1.33   mycroft 	overflows = sc->sc_overflows;
   1084      1.33   mycroft 	sc->sc_overflows = 0;
   1085      1.57   mycroft 	floods = sc->sc_floods;
   1086      1.57   mycroft 	sc->sc_floods = 0;
   1087      1.57   mycroft 	splx(s);
   1088      1.57   mycroft 
   1089      1.57   mycroft 	log(LOG_WARNING, "%s: %d silo overflow%s, %d ibuf overflow%s\n",
   1090      1.57   mycroft 	    sc->sc_dev.dv_xname,
   1091      1.57   mycroft 	    overflows, overflows == 1 ? "" : "s",
   1092      1.57   mycroft 	    floods, floods == 1 ? "" : "s");
   1093      1.57   mycroft }
   1094      1.57   mycroft 
   1095      1.57   mycroft void
   1096      1.57   mycroft compoll(arg)
   1097      1.57   mycroft 	void *arg;
   1098      1.57   mycroft {
   1099      1.57   mycroft 	int unit;
   1100      1.57   mycroft 	struct com_softc *sc;
   1101      1.57   mycroft 	struct tty *tp;
   1102      1.57   mycroft 	register u_char *ibufp;
   1103      1.57   mycroft 	u_char *ibufend;
   1104      1.57   mycroft 	register int c;
   1105      1.57   mycroft 	int s;
   1106      1.57   mycroft 	static int lsrmap[8] = {
   1107      1.57   mycroft 		0,      TTY_PE,
   1108      1.57   mycroft 		TTY_FE, TTY_PE|TTY_FE,
   1109      1.57   mycroft 		TTY_FE, TTY_PE|TTY_FE,
   1110      1.57   mycroft 		TTY_FE, TTY_PE|TTY_FE
   1111      1.57   mycroft 	};
   1112      1.57   mycroft 
   1113      1.57   mycroft 	s = spltty();
   1114      1.57   mycroft 	if (comevents == 0) {
   1115      1.57   mycroft 		splx(s);
   1116      1.57   mycroft 		goto out;
   1117      1.57   mycroft 	}
   1118      1.57   mycroft 	comevents = 0;
   1119      1.33   mycroft 	splx(s);
   1120      1.33   mycroft 
   1121      1.76   thorpej 	for (unit = 0; unit < com_cd.cd_ndevs; unit++) {
   1122      1.76   thorpej 		sc = com_cd.cd_devs[unit];
   1123      1.57   mycroft 		if (sc == 0 || sc->sc_ibufp == sc->sc_ibuf)
   1124      1.57   mycroft 			continue;
   1125      1.57   mycroft 
   1126      1.57   mycroft 		tp = sc->sc_tty;
   1127      1.57   mycroft 
   1128      1.57   mycroft 		s = spltty();
   1129      1.57   mycroft 
   1130      1.57   mycroft 		ibufp = sc->sc_ibuf;
   1131      1.57   mycroft 		ibufend = sc->sc_ibufp;
   1132      1.61   mycroft 
   1133      1.61   mycroft 		if (ibufp == ibufend) {
   1134      1.61   mycroft 			splx(s);
   1135      1.61   mycroft 			continue;
   1136      1.61   mycroft 		}
   1137      1.57   mycroft 
   1138      1.57   mycroft 		sc->sc_ibufp = sc->sc_ibuf = (ibufp == sc->sc_ibufs[0]) ?
   1139      1.57   mycroft 					     sc->sc_ibufs[1] : sc->sc_ibufs[0];
   1140      1.57   mycroft 		sc->sc_ibufhigh = sc->sc_ibuf + COM_IHIGHWATER;
   1141      1.57   mycroft 		sc->sc_ibufend = sc->sc_ibuf + COM_IBUFSIZE;
   1142      1.57   mycroft 
   1143      1.62   mycroft 		if (tp == 0 || !ISSET(tp->t_state, TS_ISOPEN)) {
   1144      1.57   mycroft 			splx(s);
   1145      1.57   mycroft 			continue;
   1146      1.57   mycroft 		}
   1147      1.57   mycroft 
   1148      1.62   mycroft 		if (ISSET(tp->t_cflag, CRTSCTS) &&
   1149      1.62   mycroft 		    !ISSET(sc->sc_mcr, MCR_RTS)) {
   1150      1.62   mycroft 			/* XXX */
   1151      1.62   mycroft 			SET(sc->sc_mcr, MCR_RTS);
   1152      1.75       cgd 			bus_io_write_1(sc->sc_bc, sc->sc_ioh, com_mcr,
   1153      1.75       cgd 			    sc->sc_mcr);
   1154      1.62   mycroft 		}
   1155      1.57   mycroft 
   1156      1.57   mycroft 		splx(s);
   1157      1.57   mycroft 
   1158      1.57   mycroft 		while (ibufp < ibufend) {
   1159      1.57   mycroft 			c = *ibufp++;
   1160      1.57   mycroft 			if (*ibufp & LSR_OE) {
   1161      1.57   mycroft 				sc->sc_overflows++;
   1162      1.57   mycroft 				if (sc->sc_errors++ == 0)
   1163      1.57   mycroft 					timeout(comdiag, sc, 60 * hz);
   1164      1.57   mycroft 			}
   1165      1.57   mycroft 			/* This is ugly, but fast. */
   1166      1.57   mycroft 			c |= lsrmap[(*ibufp++ & (LSR_BI|LSR_FE|LSR_PE)) >> 2];
   1167      1.57   mycroft 			(*linesw[tp->t_line].l_rint)(c, tp);
   1168      1.57   mycroft 		}
   1169      1.57   mycroft 	}
   1170      1.57   mycroft 
   1171      1.57   mycroft out:
   1172      1.57   mycroft 	timeout(compoll, NULL, 1);
   1173      1.21   mycroft }
   1174       1.1       cgd 
   1175      1.21   mycroft int
   1176      1.49       cgd comintr(arg)
   1177      1.49       cgd 	void *arg;
   1178      1.21   mycroft {
   1179      1.49       cgd 	struct com_softc *sc = arg;
   1180      1.75       cgd 	bus_chipset_tag_t bc = sc->sc_bc;
   1181      1.75       cgd 	bus_io_handle_t ioh = sc->sc_ioh;
   1182      1.21   mycroft 	struct tty *tp;
   1183      1.55   mycroft 	u_char lsr, data, msr, delta;
   1184      1.69   mycroft #ifdef COM_DEBUG
   1185      1.72   mycroft 	int n;
   1186      1.69   mycroft 	struct {
   1187      1.72   mycroft 		u_char iir, lsr, msr;
   1188      1.69   mycroft 	} iter[32];
   1189      1.69   mycroft #endif
   1190      1.55   mycroft 
   1191      1.72   mycroft #ifdef COM_DEBUG
   1192      1.72   mycroft 	n = 0;
   1193      1.75       cgd 	if (ISSET(iter[n].iir = bus_io_read_1(bc, ioh, com_iir), IIR_NOPEND))
   1194      1.72   mycroft 		return (0);
   1195      1.72   mycroft #else
   1196      1.75       cgd 	if (ISSET(bus_io_read_1(bc, ioh, com_iir), IIR_NOPEND))
   1197      1.55   mycroft 		return (0);
   1198      1.72   mycroft #endif
   1199      1.21   mycroft 
   1200      1.55   mycroft 	tp = sc->sc_tty;
   1201      1.21   mycroft 
   1202      1.21   mycroft 	for (;;) {
   1203      1.69   mycroft #ifdef COM_DEBUG
   1204      1.69   mycroft 		iter[n].lsr =
   1205      1.69   mycroft #endif
   1206      1.75       cgd 		lsr = bus_io_read_1(bc, ioh, com_lsr);
   1207      1.55   mycroft 
   1208      1.69   mycroft 		if (ISSET(lsr, LSR_RXRDY)) {
   1209      1.57   mycroft 			register u_char *p = sc->sc_ibufp;
   1210      1.57   mycroft 
   1211      1.57   mycroft 			comevents = 1;
   1212      1.55   mycroft 			do {
   1213      1.75       cgd 				data = bus_io_read_1(bc, ioh, com_data);
   1214      1.62   mycroft 				if (ISSET(lsr, LSR_BI)) {
   1215      1.72   mycroft #ifdef notdef
   1216      1.69   mycroft 					printf("break %02x %02x %02x %02x\n",
   1217      1.69   mycroft 					    sc->sc_msr, sc->sc_mcr, sc->sc_lcr,
   1218      1.69   mycroft 					    sc->sc_dtr);
   1219      1.69   mycroft #endif
   1220      1.57   mycroft #ifdef DDB
   1221      1.75       cgd 					if (ISSET(sc->sc_hwflags,
   1222      1.75       cgd 					    COM_HW_CONSOLE)) {
   1223      1.58   mycroft 						Debugger();
   1224      1.58   mycroft 						goto next;
   1225      1.59   mycroft 					}
   1226      1.21   mycroft #endif
   1227      1.62   mycroft 				}
   1228      1.57   mycroft 				if (p >= sc->sc_ibufend) {
   1229      1.57   mycroft 					sc->sc_floods++;
   1230      1.57   mycroft 					if (sc->sc_errors++ == 0)
   1231      1.57   mycroft 						timeout(comdiag, sc, 60 * hz);
   1232      1.57   mycroft 				} else {
   1233      1.57   mycroft 					*p++ = data;
   1234      1.57   mycroft 					*p++ = lsr;
   1235      1.57   mycroft 					if (p == sc->sc_ibufhigh &&
   1236      1.62   mycroft 					    ISSET(tp->t_cflag, CRTSCTS)) {
   1237      1.62   mycroft 						/* XXX */
   1238      1.62   mycroft 						CLR(sc->sc_mcr, MCR_RTS);
   1239      1.75       cgd 						bus_io_write_1(bc, ioh, com_mcr,
   1240      1.75       cgd 						    sc->sc_mcr);
   1241      1.62   mycroft 					}
   1242      1.55   mycroft 				}
   1243      1.57   mycroft 			next:
   1244      1.69   mycroft #ifdef COM_DEBUG
   1245      1.69   mycroft 				if (++n >= 32)
   1246      1.69   mycroft 					goto ohfudge;
   1247      1.69   mycroft 				iter[n].lsr =
   1248      1.69   mycroft #endif
   1249      1.75       cgd 				lsr = bus_io_read_1(bc, ioh, com_lsr);
   1250      1.69   mycroft 			} while (ISSET(lsr, LSR_RXRDY));
   1251      1.57   mycroft 
   1252      1.57   mycroft 			sc->sc_ibufp = p;
   1253      1.55   mycroft 		}
   1254      1.69   mycroft #ifdef COM_DEBUG
   1255      1.62   mycroft 		else if (ISSET(lsr, LSR_BI|LSR_FE|LSR_PE|LSR_OE))
   1256      1.62   mycroft 			printf("weird lsr %02x\n", lsr);
   1257      1.62   mycroft #endif
   1258      1.55   mycroft 
   1259      1.69   mycroft #ifdef COM_DEBUG
   1260      1.69   mycroft 		iter[n].msr =
   1261      1.69   mycroft #endif
   1262      1.75       cgd 		msr = bus_io_read_1(bc, ioh, com_msr);
   1263      1.55   mycroft 
   1264      1.55   mycroft 		if (msr != sc->sc_msr) {
   1265      1.55   mycroft 			delta = msr ^ sc->sc_msr;
   1266      1.55   mycroft 			sc->sc_msr = msr;
   1267      1.62   mycroft 			if (ISSET(delta, MSR_DCD) &&
   1268      1.62   mycroft 			    !ISSET(sc->sc_swflags, COM_SW_SOFTCAR) &&
   1269      1.62   mycroft 			    (*linesw[tp->t_line].l_modem)(tp, ISSET(msr, MSR_DCD)) == 0) {
   1270      1.62   mycroft 				CLR(sc->sc_mcr, sc->sc_dtr);
   1271      1.75       cgd 				bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
   1272      1.55   mycroft 			}
   1273      1.62   mycroft 			if (ISSET(delta & msr, MSR_CTS) &&
   1274      1.62   mycroft 			    ISSET(tp->t_cflag, CRTSCTS)) {
   1275      1.55   mycroft 				/* the line is up and we want to do rts/cts flow control */
   1276      1.57   mycroft 				(*linesw[tp->t_line].l_start)(tp);
   1277      1.55   mycroft 			}
   1278      1.55   mycroft 		}
   1279      1.55   mycroft 
   1280      1.62   mycroft 		if (ISSET(lsr, LSR_TXRDY) && ISSET(tp->t_state, TS_BUSY)) {
   1281      1.68   mycroft 			CLR(tp->t_state, TS_BUSY | TS_FLUSH);
   1282      1.66   mycroft 			if (sc->sc_halt > 0)
   1283      1.66   mycroft 				wakeup(&tp->t_outq);
   1284      1.69   mycroft 			(*linesw[tp->t_line].l_start)(tp);
   1285      1.62   mycroft 		}
   1286      1.62   mycroft 
   1287      1.69   mycroft #ifdef COM_DEBUG
   1288      1.69   mycroft 		if (++n >= 32)
   1289      1.69   mycroft 			goto ohfudge;
   1290      1.75       cgd 		if (ISSET(iter[n].iir = bus_io_read_1(bc, ioh, com_iir), IIR_NOPEND))
   1291      1.72   mycroft 			return (1);
   1292      1.72   mycroft #else
   1293      1.75       cgd 		if (ISSET(bus_io_read_1(bc, ioh, com_iir), IIR_NOPEND))
   1294      1.72   mycroft 			return (1);
   1295      1.69   mycroft #endif
   1296       1.1       cgd 	}
   1297      1.69   mycroft #ifdef COM_DEBUG
   1298      1.69   mycroft ohfudge:
   1299      1.69   mycroft 	printf("comintr: too many iterations");
   1300      1.69   mycroft 	for (n = 0; n < 32; n++) {
   1301      1.69   mycroft 		if ((n % 4) == 0)
   1302      1.72   mycroft 			printf("\ncomintr: iter[%02d]", n);
   1303      1.72   mycroft 		printf("  %02x %02x %02x", iter[n].iir, iter[n].lsr, iter[n].msr);
   1304      1.69   mycroft 	}
   1305      1.69   mycroft 	printf("\n");
   1306      1.72   mycroft 	printf("comintr: msr %02x mcr %02x lcr %02x ier %02x\n",
   1307      1.72   mycroft 	    sc->sc_msr, sc->sc_mcr, sc->sc_lcr, sc->sc_ier);
   1308      1.72   mycroft 	printf("comintr: state %08x cc %d\n", sc->sc_tty->t_state,
   1309      1.72   mycroft 	    sc->sc_tty->t_outq.c_cc);
   1310      1.69   mycroft #endif
   1311       1.1       cgd }
   1312       1.1       cgd 
   1313       1.1       cgd /*
   1314       1.1       cgd  * Following are all routines needed for COM to act as console
   1315       1.1       cgd  */
   1316      1.17       cgd #include <dev/cons.h>
   1317       1.1       cgd 
   1318      1.48   mycroft void
   1319       1.1       cgd comcnprobe(cp)
   1320       1.1       cgd 	struct consdev *cp;
   1321       1.1       cgd {
   1322      1.80  christos 	/* XXX NEEDS TO BE FIXED XXX */
   1323      1.80  christos 	bus_chipset_tag_t bc = 0;
   1324      1.75       cgd 	bus_io_handle_t ioh;
   1325      1.75       cgd 	int found;
   1326      1.75       cgd 
   1327      1.75       cgd 	if (bus_io_map(bc, CONADDR, COM_NPORTS, &ioh)) {
   1328      1.75       cgd 		cp->cn_pri = CN_DEAD;
   1329      1.75       cgd 		return;
   1330      1.75       cgd 	}
   1331      1.75       cgd 	found = comprobe1(bc, ioh, CONADDR);
   1332      1.75       cgd 	bus_io_unmap(bc, ioh, COM_NPORTS);
   1333      1.75       cgd 	if (!found) {
   1334      1.21   mycroft 		cp->cn_pri = CN_DEAD;
   1335      1.21   mycroft 		return;
   1336      1.21   mycroft 	}
   1337       1.1       cgd 
   1338       1.1       cgd 	/* locate the major number */
   1339       1.1       cgd 	for (commajor = 0; commajor < nchrdev; commajor++)
   1340       1.1       cgd 		if (cdevsw[commajor].d_open == comopen)
   1341       1.1       cgd 			break;
   1342       1.1       cgd 
   1343       1.1       cgd 	/* initialize required fields */
   1344      1.29   mycroft 	cp->cn_dev = makedev(commajor, CONUNIT);
   1345       1.1       cgd #ifdef	COMCONSOLE
   1346       1.1       cgd 	cp->cn_pri = CN_REMOTE;		/* Force a serial port console */
   1347       1.1       cgd #else
   1348       1.1       cgd 	cp->cn_pri = CN_NORMAL;
   1349       1.1       cgd #endif
   1350       1.1       cgd }
   1351       1.1       cgd 
   1352      1.48   mycroft void
   1353       1.1       cgd comcninit(cp)
   1354       1.1       cgd 	struct consdev *cp;
   1355       1.1       cgd {
   1356       1.1       cgd 
   1357      1.75       cgd #if 0
   1358      1.75       cgd 	XXX NEEDS TO BE FIXED XXX
   1359      1.75       cgd 	comconsbc = ???;
   1360      1.75       cgd #endif
   1361      1.75       cgd 	if (bus_io_map(comconsbc, CONADDR, COM_NPORTS, &comconsioh))
   1362      1.75       cgd 		panic("comcninit: mapping failed");
   1363      1.75       cgd 
   1364      1.75       cgd 	cominit(comconsbc, comconsioh, comdefaultrate);
   1365      1.75       cgd 	comconsaddr = CONADDR;
   1366      1.21   mycroft 	comconsinit = 0;
   1367       1.1       cgd }
   1368       1.1       cgd 
   1369      1.80  christos void
   1370      1.75       cgd cominit(bc, ioh, rate)
   1371      1.75       cgd 	bus_chipset_tag_t bc;
   1372      1.75       cgd 	bus_io_handle_t ioh;
   1373      1.75       cgd 	int rate;
   1374       1.1       cgd {
   1375      1.21   mycroft 	int s = splhigh();
   1376      1.21   mycroft 	u_char stat;
   1377       1.1       cgd 
   1378      1.75       cgd 	bus_io_write_1(bc, ioh, com_lcr, LCR_DLAB);
   1379      1.21   mycroft 	rate = comspeed(comdefaultrate);
   1380      1.75       cgd 	bus_io_write_1(bc, ioh, com_dlbl, rate);
   1381      1.75       cgd 	bus_io_write_1(bc, ioh, com_dlbh, rate >> 8);
   1382      1.75       cgd 	bus_io_write_1(bc, ioh, com_lcr, LCR_8BITS);
   1383      1.75       cgd 	bus_io_write_1(bc, ioh, com_ier, IER_ERXRDY | IER_ETXRDY);
   1384      1.75       cgd 	bus_io_write_1(bc, ioh, com_fifo, FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_4);
   1385      1.75       cgd 	stat = bus_io_read_1(bc, ioh, com_iir);
   1386       1.1       cgd 	splx(s);
   1387       1.1       cgd }
   1388       1.1       cgd 
   1389      1.80  christos int
   1390       1.1       cgd comcngetc(dev)
   1391      1.21   mycroft 	dev_t dev;
   1392       1.1       cgd {
   1393      1.21   mycroft 	int s = splhigh();
   1394      1.75       cgd 	bus_chipset_tag_t bc = comconsbc;
   1395      1.75       cgd 	bus_io_handle_t ioh = comconsioh;
   1396      1.21   mycroft 	u_char stat, c;
   1397       1.1       cgd 
   1398      1.75       cgd 	while (!ISSET(stat = bus_io_read_1(bc, ioh, com_lsr), LSR_RXRDY))
   1399       1.1       cgd 		;
   1400      1.75       cgd 	c = bus_io_read_1(bc, ioh, com_data);
   1401      1.75       cgd 	stat = bus_io_read_1(bc, ioh, com_iir);
   1402       1.1       cgd 	splx(s);
   1403      1.21   mycroft 	return c;
   1404       1.1       cgd }
   1405       1.1       cgd 
   1406       1.1       cgd /*
   1407       1.1       cgd  * Console kernel output character routine.
   1408       1.1       cgd  */
   1409      1.48   mycroft void
   1410       1.1       cgd comcnputc(dev, c)
   1411       1.1       cgd 	dev_t dev;
   1412      1.21   mycroft 	int c;
   1413       1.1       cgd {
   1414      1.21   mycroft 	int s = splhigh();
   1415      1.75       cgd 	bus_chipset_tag_t bc = comconsbc;
   1416      1.75       cgd 	bus_io_handle_t ioh = comconsioh;
   1417      1.21   mycroft 	u_char stat;
   1418       1.1       cgd 	register int timo;
   1419       1.1       cgd 
   1420       1.1       cgd #ifdef KGDB
   1421       1.1       cgd 	if (dev != kgdb_dev)
   1422       1.1       cgd #endif
   1423       1.1       cgd 	if (comconsinit == 0) {
   1424      1.80  christos 		cominit(bc, ioh, comdefaultrate);
   1425       1.1       cgd 		comconsinit = 1;
   1426       1.1       cgd 	}
   1427       1.1       cgd 	/* wait for any pending transmission to finish */
   1428       1.1       cgd 	timo = 50000;
   1429      1.75       cgd 	while (!ISSET(stat = bus_io_read_1(bc, ioh, com_lsr), LSR_TXRDY) && --timo)
   1430       1.1       cgd 		;
   1431      1.75       cgd 	bus_io_write_1(bc, ioh, com_data, c);
   1432       1.1       cgd 	/* wait for this transmission to complete */
   1433       1.1       cgd 	timo = 1500000;
   1434      1.75       cgd 	while (!ISSET(stat = bus_io_read_1(bc, ioh, com_lsr), LSR_TXRDY) && --timo)
   1435       1.1       cgd 		;
   1436       1.1       cgd 	/* clear any interrupts generated by this transmission */
   1437      1.75       cgd 	stat = bus_io_read_1(bc, ioh, com_iir);
   1438       1.1       cgd 	splx(s);
   1439      1.37   mycroft }
   1440      1.37   mycroft 
   1441      1.37   mycroft void
   1442      1.37   mycroft comcnpollc(dev, on)
   1443      1.37   mycroft 	dev_t dev;
   1444      1.37   mycroft 	int on;
   1445      1.37   mycroft {
   1446      1.37   mycroft 
   1447       1.2       cgd }
   1448