Home | History | Annotate | Line # | Download | only in ic
com.c revision 1.12.2.12
      1        1.1      cgd /*-
      2   1.12.2.7  mycroft  * Copyright (c) 1993 Charles Hannum.
      3        1.1      cgd  * Copyright (c) 1991 The Regents of the University of California.
      4        1.1      cgd  * All rights reserved.
      5        1.1      cgd  *
      6        1.1      cgd  * Redistribution and use in source and binary forms, with or without
      7        1.1      cgd  * modification, are permitted provided that the following conditions
      8        1.1      cgd  * are met:
      9        1.1      cgd  * 1. Redistributions of source code must retain the above copyright
     10        1.1      cgd  *    notice, this list of conditions and the following disclaimer.
     11        1.1      cgd  * 2. Redistributions in binary form must reproduce the above copyright
     12        1.1      cgd  *    notice, this list of conditions and the following disclaimer in the
     13        1.1      cgd  *    documentation and/or other materials provided with the distribution.
     14        1.1      cgd  * 3. All advertising materials mentioning features or use of this software
     15        1.1      cgd  *    must display the following acknowledgement:
     16        1.1      cgd  *	This product includes software developed by the University of
     17        1.1      cgd  *	California, Berkeley and its contributors.
     18        1.1      cgd  * 4. Neither the name of the University nor the names of its contributors
     19        1.1      cgd  *    may be used to endorse or promote products derived from this software
     20        1.1      cgd  *    without specific prior written permission.
     21        1.1      cgd  *
     22        1.1      cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     23        1.1      cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     24        1.1      cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     25        1.1      cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     26        1.1      cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     27        1.1      cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     28        1.1      cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     29        1.1      cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     30        1.1      cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     31        1.1      cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     32        1.1      cgd  * SUCH DAMAGE.
     33        1.1      cgd  *
     34        1.7      cgd  *	from: @(#)com.c	7.5 (Berkeley) 5/16/91
     35  1.12.2.12  mycroft  *	$Id: com.c,v 1.12.2.12 1993/10/17 05:34:20 mycroft Exp $
     36        1.1      cgd  */
     37        1.1      cgd 
     38        1.1      cgd /*
     39   1.12.2.2  mycroft  * COM driver, based originally on HP dca driver
     40        1.1      cgd  * uses National Semiconductor NS16450/NS16550AF UART
     41        1.1      cgd  */
     42  1.12.2.12  mycroft #include <sys/param.h>
     43  1.12.2.12  mycroft #include <sys/systm.h>
     44  1.12.2.12  mycroft #include <sys/ioctl.h>
     45  1.12.2.12  mycroft #include <sys/select.h>
     46  1.12.2.12  mycroft #include <sys/tty.h>
     47  1.12.2.12  mycroft #include <sys/proc.h>
     48  1.12.2.12  mycroft #include <sys/user.h>
     49  1.12.2.12  mycroft #include <sys/conf.h>
     50  1.12.2.12  mycroft #include <sys/file.h>
     51  1.12.2.12  mycroft #include <sys/uio.h>
     52  1.12.2.12  mycroft #include <sys/kernel.h>
     53  1.12.2.12  mycroft #include <sys/syslog.h>
     54  1.12.2.12  mycroft #include <sys/types.h>
     55  1.12.2.12  mycroft #include <sys/device.h>
     56        1.1      cgd 
     57  1.12.2.12  mycroft #include <machine/cpu.h>
     58  1.12.2.12  mycroft #include <machine/pio.h>
     59   1.12.2.3  mycroft 
     60  1.12.2.12  mycroft #include <i386/isa/isavar.h>
     61  1.12.2.12  mycroft #include <i386/isa/icu.h>
     62  1.12.2.12  mycroft #include <i386/isa/comreg.h>
     63        1.1      cgd 
     64   1.12.2.2  mycroft struct com_softc {
     65   1.12.2.2  mycroft 	struct	device sc_dev;
     66   1.12.2.2  mycroft 	struct	isadev sc_id;
     67   1.12.2.2  mycroft 	struct	intrhand sc_ih;
     68   1.12.2.2  mycroft 
     69   1.12.2.2  mycroft 	u_short	sc_iobase;
     70   1.12.2.2  mycroft 	u_char	sc_flags;
     71   1.12.2.2  mycroft #define	COM_SOFTCAR	0x01
     72   1.12.2.2  mycroft #define	COM_FIFO	0x02
     73        1.1      cgd };
     74   1.12.2.2  mycroft /* XXXX should be in com_softc, but not ready for that yet */
     75   1.12.2.2  mycroft #include "com.h"
     76   1.12.2.2  mycroft struct	tty *com_tty[NCOM];
     77        1.1      cgd 
     78        1.1      cgd int	comdefaultrate = TTYDEF_SPEED;
     79        1.1      cgd 
     80   1.12.2.2  mycroft static int comprobe __P((struct device *, struct cfdata *, void *));
     81   1.12.2.2  mycroft static void comforceintr __P((void *));
     82   1.12.2.2  mycroft static void comattach __P((struct device *, struct device *, void *));
     83   1.12.2.9  mycroft static int comintr __P((struct com_softc *));
     84        1.1      cgd 
     85   1.12.2.2  mycroft struct cfdriver comcd =
     86  1.12.2.11  mycroft { NULL, "com", comprobe, comattach, DV_TTY, sizeof (struct com_softc) };
     87        1.1      cgd 
     88   1.12.2.2  mycroft int comparam __P((struct tty *, struct termios *));
     89   1.12.2.2  mycroft void comstart __P((struct tty *));
     90   1.12.2.2  mycroft 
     91   1.12.2.2  mycroft int	comconsole = -1;
     92   1.12.2.2  mycroft int	comconsinit;
     93   1.12.2.2  mycroft int	commajor;
     94   1.12.2.2  mycroft extern	struct tty *constty;
     95        1.1      cgd 
     96   1.12.2.2  mycroft #define	COMUNIT(x)		(minor(x))
     97        1.1      cgd 
     98   1.12.2.2  mycroft #define	bis(c, b)	do { const register u_short com_ad = (c); \
     99   1.12.2.2  mycroft 			     outb(com_ad, inb(com_ad) | (b)); } while(0)
    100   1.12.2.2  mycroft #define	bic(c, b)	do { const register u_short com_ad = (c); \
    101   1.12.2.2  mycroft 			     outb(com_ad, inb(com_ad) &~ (b)); } while(0)
    102   1.12.2.2  mycroft 
    103   1.12.2.2  mycroft static int
    104   1.12.2.2  mycroft comspeed(speed)
    105   1.12.2.2  mycroft 	int speed;
    106   1.12.2.2  mycroft {
    107   1.12.2.2  mycroft #define	divrnd(n, q)	(((n)*2/(q)+1)/2)	/* divide and round off */
    108   1.12.2.2  mycroft 
    109   1.12.2.2  mycroft 	int x, err;
    110   1.12.2.2  mycroft 
    111   1.12.2.2  mycroft 	if (speed == 0)
    112   1.12.2.2  mycroft 		return 0;
    113   1.12.2.2  mycroft 	if (speed < 0)
    114   1.12.2.2  mycroft 		return -1;
    115   1.12.2.2  mycroft 	x = divrnd((COM_FREQ / 16), speed);
    116   1.12.2.2  mycroft 	if (x <= 0)
    117   1.12.2.2  mycroft 		return -1;
    118   1.12.2.2  mycroft 	err = divrnd((COM_FREQ / 16) * 1000, speed * x) - 1000;
    119   1.12.2.2  mycroft 	if (err < 0)
    120   1.12.2.2  mycroft 		err = -err;
    121   1.12.2.2  mycroft 	if (err > COM_TOLERANCE)
    122   1.12.2.2  mycroft 		return -1;
    123   1.12.2.2  mycroft 	return x;
    124   1.12.2.2  mycroft 
    125   1.12.2.2  mycroft #undef	divrnd(n, q)
    126   1.12.2.2  mycroft }
    127   1.12.2.2  mycroft 
    128   1.12.2.2  mycroft static int
    129   1.12.2.2  mycroft _comprobe(iobase)
    130   1.12.2.2  mycroft 	u_short iobase;
    131        1.1      cgd {
    132   1.12.2.2  mycroft 
    133        1.1      cgd 	/* force access to id reg */
    134   1.12.2.2  mycroft 	outb(iobase + com_cfcr, 0);
    135   1.12.2.2  mycroft 	outb(iobase + com_iir, 0);
    136   1.12.2.2  mycroft 	if (inb(iobase + com_iir) & 0x38)
    137   1.12.2.2  mycroft 		return 0;
    138   1.12.2.2  mycroft 	outb(iobase + com_ier, 0);
    139   1.12.2.2  mycroft 	return 1;
    140   1.12.2.2  mycroft }
    141   1.12.2.2  mycroft 
    142   1.12.2.2  mycroft static int
    143   1.12.2.2  mycroft comprobe(parent, cf, aux)
    144   1.12.2.2  mycroft 	struct device *parent;
    145   1.12.2.2  mycroft 	struct cfdata *cf;
    146   1.12.2.2  mycroft 	void *aux;
    147   1.12.2.2  mycroft {
    148   1.12.2.2  mycroft 	struct	isa_attach_args *ia = aux;
    149   1.12.2.2  mycroft 	u_short	iobase = ia->ia_iobase;
    150   1.12.2.2  mycroft 
    151   1.12.2.3  mycroft 	if (iobase == IOBASEUNK)
    152   1.12.2.3  mycroft 		return 0;
    153   1.12.2.3  mycroft 
    154   1.12.2.2  mycroft 	if (!_comprobe(iobase))
    155   1.12.2.2  mycroft 		return 0;
    156   1.12.2.2  mycroft 
    157   1.12.2.3  mycroft 	if (ia->ia_irq == IRQUNK) {
    158   1.12.2.3  mycroft 		ia->ia_irq = isa_discoverintr(comforceintr, aux);
    159   1.12.2.3  mycroft 		if (ia->ia_irq == IRQNONE)
    160   1.12.2.3  mycroft 			return 0;
    161   1.12.2.3  mycroft 	}
    162   1.12.2.2  mycroft 
    163   1.12.2.4  mycroft 	/* disable interrupts */
    164   1.12.2.4  mycroft 	outb(iobase + com_mcr, 0);
    165   1.12.2.4  mycroft 	outb(iobase + com_ier, 0);
    166   1.12.2.4  mycroft 
    167   1.12.2.2  mycroft 	ia->ia_iosize = COM_NPORTS;
    168   1.12.2.2  mycroft 	ia->ia_drq = DRQUNK;
    169   1.12.2.2  mycroft 	ia->ia_msize = 0;
    170   1.12.2.2  mycroft 	return 1;
    171   1.12.2.2  mycroft }
    172   1.12.2.2  mycroft 
    173   1.12.2.2  mycroft static void
    174   1.12.2.2  mycroft comforceintr(aux)
    175   1.12.2.2  mycroft 	void *aux;
    176   1.12.2.2  mycroft {
    177   1.12.2.2  mycroft 	struct	isa_attach_args *ia = aux;
    178   1.12.2.2  mycroft 	u_short	iobase = ia->ia_iobase;
    179   1.12.2.2  mycroft 
    180   1.12.2.4  mycroft #if 0
    181   1.12.2.4  mycroft 	/*
    182   1.12.2.4  mycroft 	 * As usual, the PC compatible world isn't.  We'd like to use the
    183   1.12.2.4  mycroft 	 * loopback feature to generate an interrupt, but alas, some lame
    184   1.12.2.4  mycroft 	 * clones don't support it.
    185   1.12.2.4  mycroft 	 */
    186   1.12.2.2  mycroft 	outb(iobase + com_mcr, MCR_IENABLE | MCR_LOOPBACK);
    187   1.12.2.2  mycroft 	outb(iobase + com_ier, IER_EMSC);
    188   1.12.2.2  mycroft 	outb(iobase + com_mcr, MCR_IENABLE | MCR_LOOPBACK | MCR_DRS);
    189   1.12.2.2  mycroft 	outb(iobase + com_mcr, MCR_IENABLE | MCR_LOOPBACK);
    190   1.12.2.4  mycroft #else
    191   1.12.2.4  mycroft 	/*
    192   1.12.2.4  mycroft 	 * So instead we try to force the transmit buffer empty (though
    193   1.12.2.4  mycroft 	 * it probably is already).
    194   1.12.2.4  mycroft 	 */
    195   1.12.2.4  mycroft 	outb(iobase + com_cfcr, CFCR_8BITS);	/* turn off DLAB */
    196   1.12.2.2  mycroft 	outb(iobase + com_ier, 0);
    197   1.12.2.4  mycroft 	outb(iobase + com_fifo, 0);
    198   1.12.2.4  mycroft 	outb(iobase + com_lsr, LSR_TXRDY | LSR_TSRE);
    199   1.12.2.4  mycroft 	outb(iobase + com_mcr, MCR_IENABLE);
    200   1.12.2.4  mycroft 	outb(iobase + com_ier, IER_ETXRDY);
    201   1.12.2.4  mycroft #endif
    202   1.12.2.2  mycroft }
    203   1.12.2.2  mycroft 
    204   1.12.2.2  mycroft static void
    205   1.12.2.2  mycroft comattach(parent, self, aux)
    206   1.12.2.2  mycroft 	struct device *parent, *self;
    207   1.12.2.2  mycroft 	void *aux;
    208   1.12.2.2  mycroft {
    209   1.12.2.2  mycroft 	struct	com_softc *sc = (struct com_softc *)self;
    210   1.12.2.2  mycroft 	struct	isa_attach_args *ia = aux;
    211   1.12.2.2  mycroft 	u_short	iobase = ia->ia_iobase;
    212   1.12.2.2  mycroft 	struct	tty *tp;
    213   1.12.2.2  mycroft 	u_char	unit = sc->sc_dev.dv_unit;
    214        1.1      cgd 
    215   1.12.2.2  mycroft 	if (iobase == comconsole)
    216   1.12.2.2  mycroft 		delay(1000);
    217        1.1      cgd 
    218   1.12.2.2  mycroft 	sc->sc_iobase = iobase;
    219   1.12.2.2  mycroft 	sc->sc_flags = 0;
    220        1.1      cgd 
    221        1.1      cgd 	/* look for a NS 16550AF UART with FIFOs */
    222   1.12.2.2  mycroft 	outb(iobase + com_fifo,
    223   1.12.2.9  mycroft 	     FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_8);
    224   1.12.2.2  mycroft 	delay(100);
    225   1.12.2.2  mycroft 	if ((inb(iobase + com_iir) & IIR_FIFO_MASK) == IIR_FIFO_MASK) {
    226   1.12.2.2  mycroft 		sc->sc_flags |= COM_FIFO;
    227   1.12.2.4  mycroft 		printf(": ns16550\n");
    228   1.12.2.2  mycroft 	} else
    229   1.12.2.4  mycroft 		printf(": ns8250 or ns16450\n");
    230   1.12.2.9  mycroft 	outb(iobase + com_fifo, 0);
    231   1.12.2.3  mycroft 	isa_establish(&sc->sc_id, &sc->sc_dev);
    232   1.12.2.3  mycroft 
    233   1.12.2.3  mycroft 	sc->sc_ih.ih_fun = comintr;
    234   1.12.2.3  mycroft 	sc->sc_ih.ih_arg = sc;
    235   1.12.2.3  mycroft 	intr_establish(ia->ia_irq, &sc->sc_ih, DV_TTY);
    236   1.12.2.2  mycroft 
    237   1.12.2.2  mycroft 	outb(iobase + com_ier, 0);
    238   1.12.2.2  mycroft 	outb(iobase + com_mcr, MCR_IENABLE);
    239   1.12.2.2  mycroft 
    240        1.1      cgd 	/*
    241        1.1      cgd 	 * Need to reset baud rate, etc. of next print so reset comconsinit.
    242        1.1      cgd 	 * Also make sure console is always "hardwired"
    243        1.1      cgd 	 */
    244   1.12.2.2  mycroft 	if (iobase == comconsole) {
    245   1.12.2.2  mycroft 		constty = com_tty[unit] = ttymalloc();
    246        1.1      cgd 		comconsinit = 0;
    247   1.12.2.2  mycroft 		sc->sc_flags |= COM_SOFTCAR;
    248        1.1      cgd 	}
    249        1.1      cgd }
    250        1.1      cgd 
    251   1.12.2.2  mycroft int
    252   1.12.2.2  mycroft comopen(dev, flag, mode, p)
    253   1.12.2.2  mycroft 	dev_t dev;
    254   1.12.2.2  mycroft 	int flag, mode;
    255   1.12.2.2  mycroft 	struct proc *p;
    256        1.1      cgd {
    257   1.12.2.2  mycroft 	int	unit = COMUNIT(dev);
    258   1.12.2.2  mycroft 	struct	com_softc *sc;
    259   1.12.2.2  mycroft 	u_short	iobase;
    260   1.12.2.2  mycroft 	struct	tty *tp;
    261   1.12.2.2  mycroft 	int	s;
    262   1.12.2.2  mycroft 	int	error = 0;
    263   1.12.2.2  mycroft 
    264   1.12.2.2  mycroft 	if (unit >= comcd.cd_ndevs)
    265   1.12.2.2  mycroft 		return ENXIO;
    266   1.12.2.2  mycroft 	sc = comcd.cd_devs[unit];
    267   1.12.2.2  mycroft 	if (!sc)
    268   1.12.2.2  mycroft 		return ENXIO;
    269   1.12.2.2  mycroft 
    270   1.12.2.2  mycroft 	if (!com_tty[unit])
    271       1.11  mycroft 		tp = com_tty[unit] = ttymalloc();
    272   1.12.2.2  mycroft 	else
    273        1.8  deraadt 		tp = com_tty[unit];
    274   1.12.2.2  mycroft 
    275        1.1      cgd 	tp->t_oproc = comstart;
    276        1.1      cgd 	tp->t_param = comparam;
    277        1.1      cgd 	tp->t_dev = dev;
    278        1.1      cgd 	if ((tp->t_state & TS_ISOPEN) == 0) {
    279        1.1      cgd 		tp->t_state |= TS_WOPEN;
    280        1.1      cgd 		ttychars(tp);
    281   1.12.2.2  mycroft 		/* preserve previous speed, if any */
    282        1.1      cgd 		if (tp->t_ispeed == 0) {
    283        1.1      cgd 			tp->t_iflag = TTYDEF_IFLAG;
    284        1.1      cgd 			tp->t_oflag = TTYDEF_OFLAG;
    285        1.1      cgd 			tp->t_cflag = TTYDEF_CFLAG;
    286        1.1      cgd 			tp->t_lflag = TTYDEF_LFLAG;
    287        1.1      cgd 			tp->t_ispeed = tp->t_ospeed = comdefaultrate;
    288        1.1      cgd 		}
    289        1.1      cgd 		comparam(tp, &tp->t_termios);
    290        1.1      cgd 		ttsetwater(tp);
    291   1.12.2.2  mycroft 	} else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0)
    292   1.12.2.2  mycroft 		return EBUSY;
    293   1.12.2.2  mycroft 
    294   1.12.2.1  mycroft 	s = spltty();
    295   1.12.2.2  mycroft 	iobase = sc->sc_iobase;
    296   1.12.2.9  mycroft 	/* flush any pending I/O */
    297   1.12.2.9  mycroft 	if (sc->sc_flags & COM_FIFO)
    298   1.12.2.9  mycroft 		outb(iobase + com_fifo,
    299   1.12.2.9  mycroft 		     FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_8);
    300   1.12.2.9  mycroft 	(void) inb(iobase + com_lsr);
    301   1.12.2.9  mycroft 	(void) inb(iobase + com_data);
    302   1.12.2.9  mycroft 	/* you turn me on, baby */
    303   1.12.2.2  mycroft 	outb(iobase + com_mcr, MCR_DTR | MCR_RTS | MCR_IENABLE);
    304   1.12.2.2  mycroft 	outb(iobase + com_ier, IER_ERXRDY | IER_ETXRDY | IER_ERLS | IER_EMSC);
    305   1.12.2.2  mycroft 
    306   1.12.2.2  mycroft 	if (sc->sc_flags & COM_SOFTCAR || inb(iobase + com_msr) & MSR_DCD)
    307        1.1      cgd 		tp->t_state |= TS_CARR_ON;
    308   1.12.2.2  mycroft 	else
    309   1.12.2.7  mycroft 		tp->t_state &=~ TS_CARR_ON;
    310   1.12.2.2  mycroft 	while ((flag & O_NONBLOCK) == 0 && (tp->t_cflag & CLOCAL) == 0 &&
    311        1.1      cgd 	       (tp->t_state & TS_CARR_ON) == 0) {
    312   1.12.2.2  mycroft 		/* wait for carrier; allow signals */
    313        1.1      cgd 		tp->t_state |= TS_WOPEN;
    314       1.11  mycroft 		if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
    315   1.12.2.2  mycroft 		    ttopen, 0)) {
    316   1.12.2.2  mycroft 			splx(s);
    317   1.12.2.2  mycroft 			return error;
    318   1.12.2.2  mycroft 		}
    319        1.1      cgd 	}
    320   1.12.2.1  mycroft 	splx(s);
    321   1.12.2.2  mycroft 
    322   1.12.2.2  mycroft 	return (*linesw[tp->t_line].l_open)(dev, tp);
    323        1.1      cgd }
    324        1.1      cgd 
    325   1.12.2.2  mycroft int
    326   1.12.2.2  mycroft comclose(dev, flag)
    327        1.1      cgd 	dev_t dev;
    328   1.12.2.2  mycroft 	int flag;
    329        1.1      cgd {
    330   1.12.2.2  mycroft 	int	unit = COMUNIT(dev);
    331   1.12.2.2  mycroft 	struct	com_softc *sc = comcd.cd_devs[unit];
    332   1.12.2.2  mycroft 	u_short	iobase = sc->sc_iobase;
    333   1.12.2.2  mycroft 	struct	tty *tp = com_tty[unit];
    334        1.1      cgd 
    335        1.1      cgd 	(*linesw[tp->t_line].l_close)(tp, flag);
    336   1.12.2.2  mycroft 	bic(iobase + com_cfcr, CFCR_SBREAK);
    337   1.12.2.2  mycroft 	outb(iobase + com_ier, 0);
    338   1.12.2.2  mycroft 	if (tp->t_cflag & HUPCL)
    339   1.12.2.2  mycroft 		bic(iobase + com_mcr, MCR_DTR | MCR_RTS);
    340        1.1      cgd 	ttyclose(tp);
    341   1.12.2.2  mycroft #ifdef notyet /* XXXX */
    342   1.12.2.2  mycroft 	if (iobase != comconsole) {
    343   1.12.2.2  mycroft 		ttyfree(tp);
    344   1.12.2.2  mycroft 		com_tty[unit] = (struct tty *)NULL;
    345   1.12.2.2  mycroft 	}
    346   1.12.2.2  mycroft #endif
    347   1.12.2.2  mycroft 	return 0;
    348        1.1      cgd }
    349        1.1      cgd 
    350   1.12.2.2  mycroft int
    351        1.1      cgd comread(dev, uio, flag)
    352        1.1      cgd 	dev_t dev;
    353        1.1      cgd 	struct uio *uio;
    354   1.12.2.2  mycroft 	int flag;
    355        1.1      cgd {
    356   1.12.2.2  mycroft 	struct	tty *tp = com_tty[COMUNIT(dev)];
    357        1.1      cgd 
    358   1.12.2.2  mycroft 	return (*linesw[tp->t_line].l_read)(tp, uio, flag);
    359        1.1      cgd }
    360        1.1      cgd 
    361   1.12.2.2  mycroft int
    362        1.1      cgd comwrite(dev, uio, flag)
    363        1.1      cgd 	dev_t dev;
    364        1.1      cgd 	struct uio *uio;
    365   1.12.2.2  mycroft 	int flag;
    366        1.1      cgd {
    367   1.12.2.2  mycroft 	struct	tty *tp = com_tty[COMUNIT(dev)];
    368        1.1      cgd 
    369   1.12.2.7  mycroft #if 0
    370   1.12.2.2  mycroft 	/* XXXX what is this for? */
    371   1.12.2.2  mycroft 	if (constty == tp)
    372        1.1      cgd 		constty = NULL;
    373   1.12.2.7  mycroft #endif
    374   1.12.2.2  mycroft 	return (*linesw[tp->t_line].l_write)(tp, uio, flag);
    375        1.1      cgd }
    376        1.1      cgd 
    377   1.12.2.2  mycroft static u_char
    378   1.12.2.2  mycroft tiocm_xxx2mcr(data)
    379   1.12.2.2  mycroft 	int data;
    380   1.12.2.2  mycroft {
    381   1.12.2.2  mycroft 	u_char m = 0;
    382   1.12.2.2  mycroft 	if (data & TIOCM_DTR)
    383   1.12.2.2  mycroft 		m |= MCR_DTR;
    384   1.12.2.2  mycroft 	if (data & TIOCM_RTS)
    385   1.12.2.2  mycroft 		m |= MCR_RTS;
    386   1.12.2.2  mycroft 	return m;
    387        1.1      cgd }
    388        1.1      cgd 
    389   1.12.2.2  mycroft int
    390        1.1      cgd comioctl(dev, cmd, data, flag)
    391        1.1      cgd 	dev_t dev;
    392   1.12.2.2  mycroft 	int cmd;
    393        1.1      cgd 	caddr_t data;
    394   1.12.2.2  mycroft 	int flag;
    395        1.1      cgd {
    396   1.12.2.2  mycroft 	int	unit = COMUNIT(dev);
    397   1.12.2.2  mycroft 	struct	com_softc *sc = comcd.cd_devs[unit];
    398   1.12.2.2  mycroft 	u_short	iobase = sc->sc_iobase;
    399   1.12.2.2  mycroft 	struct	tty *tp = com_tty[unit];
    400   1.12.2.2  mycroft 	int	error;
    401   1.12.2.2  mycroft 
    402   1.12.2.7  mycroft 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
    403   1.12.2.7  mycroft 	if (error >= 0)
    404   1.12.2.2  mycroft 		return error;
    405   1.12.2.7  mycroft 	error = ttioctl(tp, cmd, data, flag);
    406   1.12.2.7  mycroft 	if (error >= 0)
    407   1.12.2.2  mycroft 		return error;
    408        1.1      cgd 
    409        1.1      cgd 	switch (cmd) {
    410   1.12.2.2  mycroft 	    case TIOCSBRK:
    411   1.12.2.2  mycroft 		bis(iobase + com_cfcr, CFCR_SBREAK);
    412        1.1      cgd 		break;
    413   1.12.2.2  mycroft 	    case TIOCCBRK:
    414   1.12.2.2  mycroft 		bic(iobase + com_cfcr, CFCR_SBREAK);
    415        1.1      cgd 		break;
    416   1.12.2.2  mycroft 	    case TIOCSDTR:
    417   1.12.2.2  mycroft 		bis(iobase + com_mcr, MCR_DTR | MCR_RTS);
    418        1.1      cgd 		break;
    419   1.12.2.2  mycroft 	    case TIOCCDTR:
    420   1.12.2.2  mycroft 		bic(iobase + com_mcr, MCR_DTR | MCR_RTS);
    421   1.12.2.2  mycroft 		break;
    422   1.12.2.2  mycroft 	    case TIOCMSET:
    423   1.12.2.2  mycroft 		outb(iobase + com_mcr, tiocm_xxx2mcr(*(int *)data) | MCR_IENABLE);
    424   1.12.2.2  mycroft 		break;
    425   1.12.2.2  mycroft 	    case TIOCMBIS:
    426   1.12.2.2  mycroft 		bis(iobase + com_mcr, tiocm_xxx2mcr(*(int *)data));
    427   1.12.2.2  mycroft 		break;
    428   1.12.2.2  mycroft 	    case TIOCMBIC:
    429   1.12.2.2  mycroft 		bic(iobase + com_mcr, tiocm_xxx2mcr(*(int *)data));
    430   1.12.2.2  mycroft 		break;
    431   1.12.2.2  mycroft 	    case TIOCMGET:
    432   1.12.2.2  mycroft 		{
    433   1.12.2.2  mycroft 			u_char	m = inb(iobase + com_mcr);
    434   1.12.2.2  mycroft 			int	bits = 0;
    435   1.12.2.2  mycroft 
    436   1.12.2.2  mycroft 			m = inb(iobase + com_mcr);
    437   1.12.2.2  mycroft 			if (m & MCR_DTR)
    438   1.12.2.2  mycroft 				bits |= TIOCM_DTR;
    439   1.12.2.2  mycroft 			if (m & MCR_RTS)
    440   1.12.2.2  mycroft 				bits |= TIOCM_RTS;
    441   1.12.2.2  mycroft 			m = inb(iobase + com_msr);
    442   1.12.2.9  mycroft 			if (m & MSR_DCD)
    443   1.12.2.9  mycroft 				bits |= TIOCM_CD;
    444   1.12.2.2  mycroft 			if (m & MSR_CTS)
    445   1.12.2.2  mycroft 				bits |= TIOCM_CTS;
    446   1.12.2.2  mycroft 			if (m & MSR_DSR)
    447   1.12.2.2  mycroft 				bits |= TIOCM_DSR;
    448   1.12.2.2  mycroft 			if (m & (MSR_RI | MSR_TERI))
    449   1.12.2.2  mycroft 				bits |= TIOCM_RI;
    450   1.12.2.2  mycroft 			if (inb(iobase + com_ier))
    451   1.12.2.2  mycroft 				bits |= TIOCM_LE;
    452   1.12.2.2  mycroft 			*(int *)data = bits;
    453   1.12.2.2  mycroft 			break;
    454   1.12.2.2  mycroft 		}
    455        1.1      cgd 		break;
    456   1.12.2.2  mycroft 	    default:
    457   1.12.2.2  mycroft 		return ENOTTY;
    458        1.1      cgd 	}
    459   1.12.2.2  mycroft 
    460   1.12.2.2  mycroft 	return 0;
    461        1.1      cgd }
    462        1.1      cgd 
    463   1.12.2.2  mycroft int
    464        1.1      cgd comparam(tp, t)
    465   1.12.2.2  mycroft 	struct tty *tp;
    466   1.12.2.2  mycroft 	struct termios *t;
    467        1.1      cgd {
    468   1.12.2.2  mycroft 	int	unit = COMUNIT(tp->t_dev);
    469   1.12.2.2  mycroft 	struct	com_softc *sc = comcd.cd_devs[unit];
    470   1.12.2.2  mycroft 	u_short	iobase = sc->sc_iobase;
    471   1.12.2.2  mycroft 	int	ospeed = comspeed(t->c_ospeed);
    472   1.12.2.2  mycroft 	u_char	cflag = t->c_cflag;
    473   1.12.2.2  mycroft 	u_char	cfcr;
    474   1.12.2.9  mycroft 	int	s;
    475        1.1      cgd 
    476        1.1      cgd 	/* check requested parameters */
    477   1.12.2.9  mycroft 	if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
    478   1.12.2.9  mycroft 	        return EINVAL;
    479   1.12.2.2  mycroft 
    480   1.12.2.2  mycroft 	switch (cflag & CSIZE) {
    481   1.12.2.2  mycroft 	    case CS5:
    482   1.12.2.2  mycroft 		cfcr = CFCR_5BITS;
    483   1.12.2.2  mycroft 		break;
    484   1.12.2.2  mycroft 	    case CS6:
    485   1.12.2.2  mycroft 		cfcr = CFCR_6BITS;
    486   1.12.2.2  mycroft 		break;
    487   1.12.2.2  mycroft 	    case CS7:
    488   1.12.2.2  mycroft 		cfcr = CFCR_7BITS;
    489   1.12.2.2  mycroft 		break;
    490   1.12.2.2  mycroft 	    case CS8:
    491   1.12.2.2  mycroft 		cfcr = CFCR_8BITS;
    492   1.12.2.2  mycroft 		break;
    493        1.1      cgd 	}
    494   1.12.2.2  mycroft 	if (cflag & PARENB) {
    495        1.1      cgd 		cfcr |= CFCR_PENAB;
    496   1.12.2.2  mycroft 		if ((cflag & PARODD) == 0)
    497        1.1      cgd 			cfcr |= CFCR_PEVEN;
    498        1.1      cgd 	}
    499   1.12.2.2  mycroft 	if (cflag & CSTOPB)
    500        1.1      cgd 		cfcr |= CFCR_STOPB;
    501   1.12.2.9  mycroft 
    502   1.12.2.9  mycroft 	s = spltty();
    503   1.12.2.9  mycroft 
    504   1.12.2.9  mycroft 	/* and copy to tty */
    505   1.12.2.9  mycroft 	tp->t_ispeed = t->c_ispeed;
    506   1.12.2.9  mycroft 	tp->t_ospeed = t->c_ospeed;
    507   1.12.2.9  mycroft 	tp->t_cflag = cflag;
    508   1.12.2.9  mycroft 
    509   1.12.2.9  mycroft 	if (ospeed == 0)
    510   1.12.2.9  mycroft 		bic(iobase + com_mcr, MCR_DTR | MCR_RTS);
    511   1.12.2.9  mycroft 	else
    512   1.12.2.9  mycroft 		bis(iobase + com_mcr, MCR_DTR | MCR_RTS);
    513   1.12.2.9  mycroft 
    514   1.12.2.9  mycroft 	outb(iobase + com_cfcr, cfcr | CFCR_DLAB);
    515   1.12.2.9  mycroft 	outb(iobase + com_dlbl, ospeed);
    516   1.12.2.9  mycroft 	outb(iobase + com_dlbh, ospeed>>8);
    517   1.12.2.2  mycroft 	outb(iobase + com_cfcr, cfcr);
    518        1.1      cgd 
    519   1.12.2.2  mycroft 	/* when not using CRTS_IFLOW, RTS follows DTR */
    520   1.12.2.2  mycroft 	if ((cflag & CRTS_IFLOW) == 0) {
    521   1.12.2.2  mycroft 		u_char	mcr = inb(iobase + com_mcr);
    522   1.12.2.2  mycroft 
    523   1.12.2.2  mycroft 		if (mcr & MCR_DTR)
    524   1.12.2.2  mycroft 			if ((mcr & MCR_RTS) == 0)
    525   1.12.2.2  mycroft 				outb(iobase + com_mcr, mcr | MCR_RTS);
    526   1.12.2.2  mycroft 			else
    527   1.12.2.2  mycroft 				;
    528   1.12.2.2  mycroft 		else
    529   1.12.2.2  mycroft 			if (mcr & MCR_RTS)
    530   1.12.2.2  mycroft 				outb(iobase + com_mcr, mcr &~ MCR_RTS);
    531   1.12.2.2  mycroft 			else
    532   1.12.2.2  mycroft 				;
    533   1.12.2.2  mycroft 	}
    534        1.1      cgd 
    535   1.12.2.9  mycroft 	splx(s);
    536   1.12.2.9  mycroft 
    537   1.12.2.2  mycroft 	return 0;
    538        1.1      cgd }
    539        1.1      cgd 
    540       1.12  deraadt void
    541        1.1      cgd comstart(tp)
    542   1.12.2.2  mycroft 	struct tty *tp;
    543        1.1      cgd {
    544   1.12.2.2  mycroft 	int	unit = COMUNIT(tp->t_dev);
    545   1.12.2.2  mycroft 	struct	com_softc *sc = comcd.cd_devs[unit];
    546   1.12.2.2  mycroft 	u_short	iobase = sc->sc_iobase;
    547   1.12.2.2  mycroft 	int	s;
    548        1.1      cgd 
    549        1.1      cgd 	s = spltty();
    550   1.12.2.2  mycroft 	if (tp->t_state & (TS_TTSTOP | TS_BUSY))
    551   1.12.2.2  mycroft 		goto out;
    552   1.12.2.2  mycroft 	if (tp->t_cflag & CCTS_OFLOW && (inb(iobase + com_mcr) & MSR_CTS) == 0)
    553        1.1      cgd 		goto out;
    554       1.11  mycroft 	if (tp->t_outq.c_cc <= tp->t_lowat) {
    555   1.12.2.2  mycroft 		if (tp->t_state & TS_ASLEEP) {
    556   1.12.2.7  mycroft 			tp->t_state &=~ TS_ASLEEP;
    557       1.11  mycroft 			wakeup((caddr_t)&tp->t_outq);
    558        1.1      cgd 		}
    559        1.7      cgd 		selwakeup(&tp->t_wsel);
    560        1.1      cgd 	}
    561       1.11  mycroft 	if (tp->t_outq.c_cc == 0)
    562        1.1      cgd 		goto out;
    563   1.12.2.2  mycroft 	tp->t_state |= TS_BUSY;
    564   1.12.2.2  mycroft 	if ((inb(iobase + com_lsr) & LSR_TXRDY) == 0)
    565   1.12.2.2  mycroft 		goto out;
    566   1.12.2.2  mycroft 	if (sc->sc_flags & COM_FIFO) {
    567   1.12.2.2  mycroft 		u_char buffer[16], *cp = buffer;
    568   1.12.2.2  mycroft 		int n = q_to_b(&tp->t_outq, cp, sizeof buffer);
    569   1.12.2.2  mycroft 		do {
    570   1.12.2.2  mycroft 			outb(iobase + com_data, *cp++);
    571   1.12.2.2  mycroft 		} while (--n);
    572   1.12.2.2  mycroft 	} else
    573   1.12.2.2  mycroft 		outb(iobase + com_data, getc(&tp->t_outq));
    574   1.12.2.2  mycroft     out:
    575        1.1      cgd 	splx(s);
    576        1.1      cgd }
    577        1.1      cgd 
    578        1.1      cgd /*
    579        1.1      cgd  * Stop output on a line.
    580        1.1      cgd  */
    581   1.12.2.2  mycroft void
    582        1.1      cgd comstop(tp, flag)
    583   1.12.2.2  mycroft 	struct tty *tp;
    584        1.1      cgd {
    585   1.12.2.2  mycroft 	int	s;
    586        1.1      cgd 
    587        1.1      cgd 	s = spltty();
    588   1.12.2.9  mycroft 	if (tp->t_state & TS_BUSY)
    589   1.12.2.2  mycroft 		if ((tp->t_state & TS_TTSTOP) == 0)
    590        1.1      cgd 			tp->t_state |= TS_FLUSH;
    591        1.1      cgd 	splx(s);
    592        1.1      cgd }
    593        1.1      cgd 
    594   1.12.2.2  mycroft static void
    595   1.12.2.2  mycroft comeint(sc, stat)
    596   1.12.2.2  mycroft 	struct com_softc *sc;
    597   1.12.2.2  mycroft 	int stat;
    598   1.12.2.2  mycroft {
    599   1.12.2.2  mycroft 	u_short	iobase = sc->sc_iobase;
    600   1.12.2.2  mycroft 	struct	tty *tp = com_tty[sc->sc_dev.dv_unit];
    601   1.12.2.2  mycroft 	int	c;
    602        1.1      cgd 
    603   1.12.2.2  mycroft 	c = inb(iobase + com_data);
    604   1.12.2.2  mycroft 	if ((tp->t_state & TS_ISOPEN) == 0)
    605   1.12.2.2  mycroft 		return;
    606   1.12.2.2  mycroft 	if (stat & (LSR_BI | LSR_FE))
    607   1.12.2.2  mycroft 		c |= TTY_FE;
    608   1.12.2.2  mycroft 	else if (stat & LSR_PE)
    609   1.12.2.2  mycroft 		c |= TTY_PE;
    610   1.12.2.2  mycroft 	else if (stat & LSR_OE) {
    611   1.12.2.2  mycroft 		c |= TTY_PE;		/* XXX ought to have its own define */
    612  1.12.2.11  mycroft 		log(LOG_WARNING, "%s: silo overflow\n", sc->sc_dev.dv_xname);
    613   1.12.2.2  mycroft 	}
    614   1.12.2.2  mycroft 	/* XXXX put in FIFO and process later */
    615   1.12.2.2  mycroft 	(*linesw[tp->t_line].l_rint)(c, tp);
    616   1.12.2.2  mycroft }
    617        1.1      cgd 
    618   1.12.2.2  mycroft static void
    619   1.12.2.2  mycroft commint(sc)
    620   1.12.2.2  mycroft 	struct com_softc *sc;
    621   1.12.2.2  mycroft {
    622   1.12.2.2  mycroft 	u_short	iobase = sc->sc_iobase;
    623   1.12.2.2  mycroft 	struct	tty *tp = com_tty[sc->sc_dev.dv_unit];
    624   1.12.2.2  mycroft 	u_char	stat;
    625        1.1      cgd 
    626   1.12.2.2  mycroft 	stat = inb(iobase + com_msr);
    627   1.12.2.2  mycroft 	if (stat & MSR_DDCD && (sc->sc_flags & COM_SOFTCAR) == 0) {
    628   1.12.2.2  mycroft 		if (stat & MSR_DCD)
    629   1.12.2.2  mycroft 			(void)(*linesw[tp->t_line].l_modem)(tp, 1);
    630   1.12.2.2  mycroft 		else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0)
    631   1.12.2.2  mycroft 			bic(iobase + com_mcr, MCR_DTR | MCR_RTS);
    632   1.12.2.2  mycroft 	} else if (stat & MSR_DCTS && tp->t_state & TS_ISOPEN &&
    633   1.12.2.2  mycroft 		   tp->t_cflag & CRTSCTS) {
    634   1.12.2.2  mycroft 		/* the line is up and we want to do rts/cts flow control */
    635   1.12.2.2  mycroft 		if (stat & MSR_CTS) {
    636   1.12.2.2  mycroft 			tp->t_state &=~ TS_TTSTOP;
    637   1.12.2.2  mycroft 			ttstart(tp);
    638   1.12.2.2  mycroft 		} else
    639   1.12.2.2  mycroft 			tp->t_state |= TS_TTSTOP;
    640   1.12.2.2  mycroft 	}
    641   1.12.2.2  mycroft }
    642        1.1      cgd 
    643   1.12.2.2  mycroft static int
    644   1.12.2.9  mycroft comintr(sc)
    645   1.12.2.9  mycroft 	struct com_softc *sc;
    646   1.12.2.2  mycroft {
    647   1.12.2.2  mycroft 	u_short	iobase = sc->sc_iobase;
    648   1.12.2.2  mycroft 	struct	tty *tp;
    649   1.12.2.2  mycroft 	u_char	code;
    650   1.12.2.2  mycroft 
    651   1.12.2.2  mycroft 	code = inb(iobase + com_iir);
    652   1.12.2.2  mycroft 	if (code & IIR_NOPEND)
    653   1.12.2.2  mycroft 		return 0;
    654        1.1      cgd 
    655   1.12.2.2  mycroft 	for (;;) {
    656   1.12.2.2  mycroft 		switch (code & IIR_IMASK) {
    657   1.12.2.2  mycroft 		    case IIR_RXRDY:
    658   1.12.2.2  mycroft 		    case IIR_RXTOUT:
    659   1.12.2.2  mycroft 			tp = com_tty[sc->sc_dev.dv_unit];
    660   1.12.2.2  mycroft 			/* XXXX put in FIFO and process later */
    661   1.12.2.2  mycroft #define	RCVBYTE() \
    662   1.12.2.2  mycroft 			code = inb(iobase + com_data); \
    663   1.12.2.2  mycroft 			if (tp->t_state & TS_ISOPEN) \
    664   1.12.2.2  mycroft 				(*linesw[tp->t_line].l_rint)(code, tp)
    665   1.12.2.2  mycroft 			RCVBYTE();
    666   1.12.2.2  mycroft 			if (sc->sc_flags & COM_FIFO)
    667   1.12.2.2  mycroft 				while (code = inb(iobase + com_lsr) & LSR_RCV_MASK) {
    668   1.12.2.2  mycroft 					if (code == LSR_RXRDY) {
    669   1.12.2.2  mycroft 						RCVBYTE();
    670   1.12.2.2  mycroft 					} else
    671   1.12.2.2  mycroft 						comeint(sc, code);
    672   1.12.2.2  mycroft 				}
    673   1.12.2.2  mycroft 			break;
    674   1.12.2.2  mycroft 		    case IIR_TXRDY:
    675   1.12.2.2  mycroft 			tp = com_tty[sc->sc_dev.dv_unit];
    676   1.12.2.9  mycroft 			tp->t_state &=~ TS_BUSY;
    677  1.12.2.10  mycroft 			if (tp->t_state & TS_FLUSH)
    678   1.12.2.9  mycroft 				tp->t_state &=~ TS_FLUSH;
    679  1.12.2.10  mycroft 			else
    680   1.12.2.9  mycroft 				if (tp->t_line)
    681   1.12.2.9  mycroft 					(*linesw[tp->t_line].l_start)(tp);
    682   1.12.2.9  mycroft 				else
    683   1.12.2.9  mycroft 					comstart(tp);
    684   1.12.2.2  mycroft 			break;
    685   1.12.2.2  mycroft 		    case IIR_RLS:
    686   1.12.2.2  mycroft 			comeint(sc, inb(iobase + com_lsr));
    687   1.12.2.2  mycroft 			break;
    688   1.12.2.2  mycroft 		    default:
    689  1.12.2.11  mycroft 			log(LOG_WARNING, "%s: weird iir=0x%x\n",
    690  1.12.2.11  mycroft 			    sc->sc_dev.dv_xname, code);
    691   1.12.2.2  mycroft 			/* fall through */
    692   1.12.2.2  mycroft 		    case IIR_MLSC:
    693   1.12.2.2  mycroft 			commint(sc);
    694   1.12.2.2  mycroft 			break;
    695   1.12.2.2  mycroft 		}
    696   1.12.2.2  mycroft 
    697   1.12.2.2  mycroft 		code = inb(iobase + com_iir);
    698   1.12.2.2  mycroft 		if (code & IIR_NOPEND)
    699   1.12.2.2  mycroft 			return 1;
    700        1.1      cgd 	}
    701        1.1      cgd }
    702        1.1      cgd 
    703   1.12.2.2  mycroft /* XXXXXXXXXXXXXXXX ---- gremlins below here ---- XXXXXXXXXXXXXXXX */
    704   1.12.2.2  mycroft 
    705   1.12.2.2  mycroft #if 0
    706        1.1      cgd /*
    707        1.1      cgd  * Following are all routines needed for COM to act as console
    708        1.1      cgd  */
    709        1.1      cgd #include "i386/i386/cons.h"
    710        1.1      cgd 
    711        1.1      cgd comcnprobe(cp)
    712        1.1      cgd 	struct consdev *cp;
    713        1.1      cgd {
    714   1.12.2.2  mycroft 	/* XXXX */
    715   1.12.2.2  mycroft 	if (!_comprobe(CONADDR))
    716   1.12.2.2  mycroft 		return CN_DEAD;
    717        1.1      cgd 
    718        1.1      cgd 	/* locate the major number */
    719        1.1      cgd 	for (commajor = 0; commajor < nchrdev; commajor++)
    720        1.1      cgd 		if (cdevsw[commajor].d_open == comopen)
    721        1.1      cgd 			break;
    722        1.1      cgd 
    723        1.1      cgd 	/* initialize required fields */
    724        1.2      cgd 	cp->cn_dev = makedev(commajor, unit);
    725        1.1      cgd #ifdef	COMCONSOLE
    726        1.1      cgd 	cp->cn_pri = CN_REMOTE;		/* Force a serial port console */
    727        1.1      cgd #else
    728        1.1      cgd 	cp->cn_pri = CN_NORMAL;
    729        1.1      cgd #endif
    730        1.1      cgd }
    731        1.1      cgd 
    732        1.1      cgd comcninit(cp)
    733        1.1      cgd 	struct consdev *cp;
    734        1.1      cgd {
    735   1.12.2.2  mycroft 	int unit = COMUNIT(cp->cn_dev);
    736        1.1      cgd 
    737   1.12.2.2  mycroft 	comconsole = CONADDR;
    738   1.12.2.2  mycroft 	comconsinit = 0;
    739        1.1      cgd }
    740        1.1      cgd 
    741        1.1      cgd cominit(unit, rate)
    742        1.1      cgd 	int unit, rate;
    743        1.1      cgd {
    744   1.12.2.2  mycroft 	int com;
    745        1.1      cgd 	int s;
    746        1.1      cgd 	short stat;
    747        1.1      cgd 
    748        1.1      cgd 	com = com_addr[unit];
    749        1.1      cgd 	s = splhigh();
    750        1.1      cgd 	outb(com+com_cfcr, CFCR_DLAB);
    751   1.12.2.2  mycroft 	rate = COM_BAUDDIV(rate);
    752        1.1      cgd 	outb(com+com_data, rate & 0xFF);
    753        1.1      cgd 	outb(com+com_ier, rate >> 8);
    754        1.1      cgd 	outb(com+com_cfcr, CFCR_8BITS);
    755        1.1      cgd 	outb(com+com_ier, IER_ERXRDY | IER_ETXRDY);
    756        1.2      cgd 	outb(com+com_fifo, FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_4);
    757        1.1      cgd 	stat = inb(com+com_iir);
    758        1.1      cgd 	splx(s);
    759        1.1      cgd }
    760        1.1      cgd 
    761        1.1      cgd comcngetc(dev)
    762        1.1      cgd {
    763   1.12.2.2  mycroft 	com = com_addr[COMUNIT(dev)];
    764        1.1      cgd 	short stat;
    765        1.1      cgd 	int c, s;
    766        1.1      cgd 
    767        1.1      cgd 	s = splhigh();
    768        1.1      cgd 	while (((stat = inb(com+com_lsr)) & LSR_RXRDY) == 0)
    769        1.1      cgd 		;
    770        1.1      cgd 	c = inb(com+com_data);
    771        1.1      cgd 	stat = inb(com+com_iir);
    772        1.1      cgd 	splx(s);
    773   1.12.2.2  mycroft 	return c;
    774        1.1      cgd }
    775        1.1      cgd 
    776        1.1      cgd /*
    777        1.1      cgd  * Console kernel output character routine.
    778        1.1      cgd  */
    779        1.1      cgd comcnputc(dev, c)
    780        1.1      cgd 	dev_t dev;
    781   1.12.2.2  mycroft 	int c;
    782        1.1      cgd {
    783   1.12.2.2  mycroft 	com = com_addr[COMUNIT(dev)];
    784   1.12.2.2  mycroft 	int timo;
    785        1.1      cgd 	short stat;
    786        1.1      cgd 	int s = splhigh();
    787        1.1      cgd 
    788        1.1      cgd 	if (comconsinit == 0) {
    789   1.12.2.2  mycroft 		(void) cominit(COMUNIT(dev), comdefaultrate);
    790        1.1      cgd 		comconsinit = 1;
    791        1.1      cgd 	}
    792        1.1      cgd 	/* wait for any pending transmission to finish */
    793        1.1      cgd 	timo = 50000;
    794        1.1      cgd 	while (((stat = inb(com+com_lsr)) & LSR_TXRDY) == 0 && --timo)
    795        1.1      cgd 		;
    796        1.1      cgd 	outb(com+com_data, c);
    797        1.1      cgd 	/* wait for this transmission to complete */
    798        1.1      cgd 	timo = 1500000;
    799        1.1      cgd 	while (((stat = inb(com+com_lsr)) & LSR_TXRDY) == 0 && --timo)
    800        1.1      cgd 		;
    801        1.1      cgd 	/* clear any interrupts generated by this transmission */
    802        1.1      cgd 	stat = inb(com+com_iir);
    803        1.1      cgd 	splx(s);
    804        1.1      cgd }
    805        1.3      cgd #endif
    806