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