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