Home | History | Annotate | Line # | Download | only in dev
dcm.c revision 1.57
      1  1.57   thorpej /*	$NetBSD: dcm.c,v 1.57 2003/03/06 18:24:52 thorpej Exp $	*/
      2  1.42   thorpej 
      3  1.42   thorpej /*-
      4  1.42   thorpej  * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
      5  1.42   thorpej  * All rights reserved.
      6  1.42   thorpej  *
      7  1.42   thorpej  * This code is derived from software contributed to The NetBSD Foundation
      8  1.42   thorpej  * by Jason R. Thorpe.
      9  1.42   thorpej  *
     10  1.42   thorpej  * Redistribution and use in source and binary forms, with or without
     11  1.42   thorpej  * modification, are permitted provided that the following conditions
     12  1.42   thorpej  * are met:
     13  1.42   thorpej  * 1. Redistributions of source code must retain the above copyright
     14  1.42   thorpej  *    notice, this list of conditions and the following disclaimer.
     15  1.42   thorpej  * 2. Redistributions in binary form must reproduce the above copyright
     16  1.42   thorpej  *    notice, this list of conditions and the following disclaimer in the
     17  1.42   thorpej  *    documentation and/or other materials provided with the distribution.
     18  1.42   thorpej  * 3. All advertising materials mentioning features or use of this software
     19  1.42   thorpej  *    must display the following acknowledgement:
     20  1.42   thorpej  *	This product includes software developed by the NetBSD
     21  1.42   thorpej  *	Foundation, Inc. and its contributors.
     22  1.42   thorpej  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23  1.42   thorpej  *    contributors may be used to endorse or promote products derived
     24  1.42   thorpej  *    from this software without specific prior written permission.
     25  1.42   thorpej  *
     26  1.42   thorpej  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27  1.42   thorpej  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28  1.42   thorpej  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29  1.42   thorpej  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30  1.42   thorpej  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31  1.42   thorpej  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32  1.42   thorpej  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33  1.42   thorpej  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34  1.42   thorpej  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35  1.42   thorpej  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36  1.42   thorpej  * POSSIBILITY OF SUCH DAMAGE.
     37  1.42   thorpej  */
     38  1.15       cgd 
     39   1.1       cgd /*
     40   1.1       cgd  * Copyright (c) 1988 University of Utah.
     41  1.14   mycroft  * Copyright (c) 1982, 1986, 1990, 1993
     42  1.14   mycroft  *	The Regents of the University of California.  All rights reserved.
     43   1.1       cgd  *
     44   1.1       cgd  * This code is derived from software contributed to Berkeley by
     45   1.1       cgd  * the Systems Programming Group of the University of Utah Computer
     46   1.1       cgd  * Science Department.
     47   1.1       cgd  *
     48   1.1       cgd  * Redistribution and use in source and binary forms, with or without
     49   1.1       cgd  * modification, are permitted provided that the following conditions
     50   1.1       cgd  * are met:
     51   1.1       cgd  * 1. Redistributions of source code must retain the above copyright
     52   1.1       cgd  *    notice, this list of conditions and the following disclaimer.
     53   1.1       cgd  * 2. Redistributions in binary form must reproduce the above copyright
     54   1.1       cgd  *    notice, this list of conditions and the following disclaimer in the
     55   1.1       cgd  *    documentation and/or other materials provided with the distribution.
     56   1.1       cgd  * 3. All advertising materials mentioning features or use of this software
     57   1.1       cgd  *    must display the following acknowledgement:
     58   1.1       cgd  *	This product includes software developed by the University of
     59   1.1       cgd  *	California, Berkeley and its contributors.
     60   1.1       cgd  * 4. Neither the name of the University nor the names of its contributors
     61   1.1       cgd  *    may be used to endorse or promote products derived from this software
     62   1.1       cgd  *    without specific prior written permission.
     63   1.1       cgd  *
     64   1.1       cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     65   1.1       cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     66   1.1       cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     67   1.1       cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     68   1.1       cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     69   1.1       cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     70   1.1       cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     71   1.1       cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     72   1.1       cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     73   1.1       cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     74   1.1       cgd  * SUCH DAMAGE.
     75   1.1       cgd  *
     76  1.14   mycroft  * from Utah: $Hdr: dcm.c 1.29 92/01/21$
     77  1.14   mycroft  *
     78  1.15       cgd  *	@(#)dcm.c	8.4 (Berkeley) 1/12/94
     79   1.1       cgd  */
     80   1.1       cgd 
     81   1.1       cgd /*
     82   1.1       cgd  * TODO:
     83   1.1       cgd  *	Timeouts
     84   1.1       cgd  *	Test console support.
     85   1.1       cgd  */
     86   1.1       cgd 
     87   1.1       cgd /*
     88   1.1       cgd  *  98642/MUX
     89   1.1       cgd  */
     90  1.50  gmcgarry 
     91  1.50  gmcgarry #include <sys/cdefs.h>
     92  1.57   thorpej __KERNEL_RCSID(0, "$NetBSD: dcm.c,v 1.57 2003/03/06 18:24:52 thorpej Exp $");
     93  1.47     lukem 
     94  1.47     lukem #include "opt_kgdb.h"
     95  1.47     lukem 
     96  1.13   mycroft #include <sys/param.h>
     97  1.13   mycroft #include <sys/systm.h>
     98  1.13   mycroft #include <sys/ioctl.h>
     99  1.13   mycroft #include <sys/proc.h>
    100  1.13   mycroft #include <sys/tty.h>
    101  1.13   mycroft #include <sys/conf.h>
    102  1.13   mycroft #include <sys/file.h>
    103  1.13   mycroft #include <sys/uio.h>
    104  1.13   mycroft #include <sys/kernel.h>
    105  1.13   mycroft #include <sys/syslog.h>
    106  1.13   mycroft #include <sys/time.h>
    107  1.34   thorpej #include <sys/device.h>
    108  1.13   mycroft 
    109  1.24   thorpej #include <machine/autoconf.h>
    110  1.14   mycroft #include <machine/cpu.h>
    111  1.39   thorpej #include <machine/intr.h>
    112  1.14   mycroft 
    113  1.22   thorpej #include <dev/cons.h>
    114  1.22   thorpej 
    115  1.34   thorpej #include <hp300/dev/dioreg.h>
    116  1.34   thorpej #include <hp300/dev/diovar.h>
    117  1.34   thorpej #include <hp300/dev/diodevs.h>
    118  1.13   mycroft #include <hp300/dev/dcmreg.h>
    119   1.1       cgd 
    120   1.1       cgd #ifndef DEFAULT_BAUD_RATE
    121   1.1       cgd #define DEFAULT_BAUD_RATE 9600
    122   1.1       cgd #endif
    123   1.1       cgd 
    124   1.1       cgd struct speedtab dcmspeedtab[] = {
    125  1.36    scottr 	{	0,	BR_0		},
    126  1.36    scottr 	{	50,	BR_50		},
    127  1.36    scottr 	{	75,	BR_75		},
    128  1.36    scottr 	{	110,	BR_110		},
    129  1.36    scottr 	{	134,	BR_134		},
    130  1.36    scottr 	{	150,	BR_150		},
    131  1.36    scottr 	{	300,	BR_300		},
    132  1.36    scottr 	{	600,	BR_600		},
    133  1.36    scottr 	{	1200,	BR_1200		},
    134  1.36    scottr 	{	1800,	BR_1800		},
    135  1.36    scottr 	{	2400,	BR_2400		},
    136  1.36    scottr 	{	4800,	BR_4800		},
    137  1.36    scottr 	{	9600,	BR_9600		},
    138  1.36    scottr 	{	19200,	BR_19200	},
    139  1.36    scottr 	{	38400,	BR_38400	},
    140  1.36    scottr 	{	-1,	-1		},
    141   1.1       cgd };
    142   1.1       cgd 
    143   1.1       cgd /* u-sec per character based on baudrate (assumes 1 start/8 data/1 stop bit) */
    144   1.1       cgd #define	DCM_USPERCH(s)	(10000000 / (s))
    145   1.1       cgd 
    146   1.1       cgd /*
    147   1.1       cgd  * Per board interrupt scheme.  16.7ms is the polling interrupt rate
    148   1.1       cgd  * (16.7ms is about 550 baud, 38.4k is 72 chars in 16.7ms).
    149   1.1       cgd  */
    150   1.1       cgd #define DIS_TIMER	0
    151   1.1       cgd #define DIS_PERCHAR	1
    152   1.1       cgd #define DIS_RESET	2
    153   1.1       cgd 
    154   1.1       cgd int	dcmistype = -1;		/* -1 == dynamic, 0 == timer, 1 == perchar */
    155   1.1       cgd int     dcminterval = 5;	/* interval (secs) between checks */
    156   1.1       cgd struct	dcmischeme {
    157   1.1       cgd 	int	dis_perchar;	/* non-zero if interrupting per char */
    158   1.1       cgd 	long	dis_time;	/* last time examined */
    159   1.1       cgd 	int	dis_intr;	/* recv interrupts during last interval */
    160   1.1       cgd 	int	dis_char;	/* characters read during last interval */
    161  1.20   thorpej };
    162   1.1       cgd 
    163   1.1       cgd #ifdef KGDB
    164   1.1       cgd /*
    165   1.1       cgd  * Kernel GDB support
    166   1.1       cgd  */
    167  1.14   mycroft #include <machine/remote-sl.h>
    168   1.1       cgd 
    169   1.1       cgd extern dev_t kgdb_dev;
    170   1.1       cgd extern int kgdb_rate;
    171   1.1       cgd extern int kgdb_debug_init;
    172   1.1       cgd #endif
    173   1.1       cgd 
    174  1.14   mycroft /* #define DCMSTATS */
    175   1.1       cgd 
    176   1.1       cgd #ifdef DEBUG
    177   1.1       cgd int	dcmdebug = 0x0;
    178   1.1       cgd #define DDB_SIOERR	0x01
    179   1.1       cgd #define DDB_PARAM	0x02
    180   1.1       cgd #define DDB_INPUT	0x04
    181   1.1       cgd #define DDB_OUTPUT	0x08
    182   1.1       cgd #define DDB_INTR	0x10
    183   1.1       cgd #define DDB_IOCTL	0x20
    184   1.1       cgd #define DDB_INTSCHM	0x40
    185   1.1       cgd #define DDB_MODEM	0x80
    186   1.1       cgd #define DDB_OPENCLOSE	0x100
    187   1.1       cgd #endif
    188   1.1       cgd 
    189  1.14   mycroft #ifdef DCMSTATS
    190   1.1       cgd #define	DCMRBSIZE	94
    191   1.1       cgd #define DCMXBSIZE	24
    192   1.1       cgd 
    193   1.1       cgd struct	dcmstats {
    194   1.1       cgd 	long	xints;		    /* # of xmit ints */
    195   1.1       cgd 	long	xchars;		    /* # of xmit chars */
    196   1.1       cgd 	long	xempty;		    /* times outq is empty in dcmstart */
    197   1.1       cgd 	long	xrestarts;	    /* times completed while xmitting */
    198   1.1       cgd 	long	rints;		    /* # of recv ints */
    199   1.1       cgd 	long	rchars;		    /* # of recv chars */
    200   1.1       cgd 	long	xsilo[DCMXBSIZE+2]; /* times this many chars xmit on one int */
    201   1.1       cgd 	long	rsilo[DCMRBSIZE+2]; /* times this many chars read on one int */
    202  1.20   thorpej };
    203   1.1       cgd #endif
    204   1.1       cgd 
    205  1.44   thorpej #define DCMUNIT(x)		(minor(x) & 0x7ffff)
    206  1.44   thorpej #define	DCMDIALOUT(x)		(minor(x) & 0x80000)
    207  1.20   thorpej #define	DCMBOARD(x)		(((x) >> 2) & 0x3f)
    208  1.20   thorpej #define DCMPORT(x)		((x) & 3)
    209   1.1       cgd 
    210   1.1       cgd /*
    211   1.1       cgd  * Conversion from "HP DCE" to almost-normal DCE: on the 638 8-port mux,
    212   1.1       cgd  * the distribution panel uses "HP DCE" conventions.  If requested via
    213   1.1       cgd  * the device flags, we swap the inputs to something closer to normal DCE,
    214   1.1       cgd  * allowing a straight-through cable to a DTE or a reversed cable
    215   1.1       cgd  * to a DCE (reversing 2-3, 4-5, 8-20 and leaving 6 unconnected;
    216   1.1       cgd  * this gets "DCD" on pin 20 and "CTS" on 4, but doesn't connect
    217   1.1       cgd  * DSR or make RTS work, though).  The following gives the full
    218   1.1       cgd  * details of a cable from this mux panel to a modem:
    219   1.1       cgd  *
    220   1.1       cgd  *		     HP		    modem
    221   1.1       cgd  *		name	pin	pin	name
    222   1.1       cgd  * HP inputs:
    223   1.1       cgd  *		"Rx"	 2	 3	Tx
    224   1.1       cgd  *		CTS	 4	 5	CTS	(only needed for CCTS_OFLOW)
    225   1.1       cgd  *		DCD	20	 8	DCD
    226   1.1       cgd  *		"DSR"	 9	 6	DSR	(unneeded)
    227   1.1       cgd  *		RI	22	22	RI	(unneeded)
    228   1.1       cgd  *
    229   1.1       cgd  * HP outputs:
    230   1.1       cgd  *		"Tx"	 3	 2	Rx
    231   1.1       cgd  *		"DTR"	 6	not connected
    232   1.1       cgd  *		"RTS"	 8	20	DTR
    233   1.1       cgd  *		"SR"	23	 4	RTS	(often not needed)
    234   1.1       cgd  */
    235   1.1       cgd #define hp2dce_in(ibits)	(iconv[(ibits) & 0xf])
    236   1.1       cgd static char iconv[16] = {
    237   1.1       cgd 	0,		MI_DM,		MI_CTS,		MI_CTS|MI_DM,
    238   1.1       cgd 	MI_CD,		MI_CD|MI_DM,	MI_CD|MI_CTS,	MI_CD|MI_CTS|MI_DM,
    239   1.1       cgd 	MI_RI,		MI_RI|MI_DM,	MI_RI|MI_CTS,	MI_RI|MI_CTS|MI_DM,
    240   1.1       cgd 	MI_RI|MI_CD,	MI_RI|MI_CD|MI_DM, MI_RI|MI_CD|MI_CTS,
    241   1.1       cgd 	MI_RI|MI_CD|MI_CTS|MI_DM
    242   1.1       cgd };
    243   1.1       cgd 
    244  1.21   thorpej /*
    245  1.21   thorpej  * Note that 8-port boards appear as 2 4-port boards at consecutive
    246  1.21   thorpej  * select codes.
    247  1.21   thorpej  */
    248  1.21   thorpej #define	NDCMPORT	4
    249  1.20   thorpej 
    250  1.20   thorpej struct	dcm_softc {
    251  1.34   thorpej 	struct	device sc_dev;		/* generic device glue */
    252  1.20   thorpej 	struct	dcmdevice *sc_dcm;	/* pointer to hardware */
    253  1.20   thorpej 	struct	tty *sc_tty[NDCMPORT];	/* our tty instances */
    254  1.20   thorpej 	struct	modemreg *sc_modem[NDCMPORT]; /* modem control */
    255  1.20   thorpej 	char	sc_mcndlast[NDCMPORT];	/* XXX last modem status for port */
    256  1.20   thorpej 	short	sc_softCAR;		/* mask of ports with soft-carrier */
    257  1.20   thorpej 	struct	dcmischeme sc_scheme;	/* interrupt scheme for board */
    258  1.20   thorpej 
    259  1.20   thorpej 	/*
    260  1.20   thorpej 	 * Mask of soft-carrier bits in config flags.
    261  1.20   thorpej 	 */
    262  1.20   thorpej #define	DCM_SOFTCAR	0x0000000f
    263  1.20   thorpej 
    264  1.20   thorpej 	int	sc_flags;		/* misc. configuration info */
    265  1.20   thorpej 
    266  1.20   thorpej 	/*
    267  1.20   thorpej 	 * Bits for sc_flags
    268  1.20   thorpej 	 */
    269  1.20   thorpej #define	DCM_ACTIVE	0x00000001	/* indicates board is alive */
    270  1.24   thorpej #define	DCM_ISCONSOLE	0x00000002	/* indicates board is console */
    271  1.20   thorpej #define	DCM_STDDCE	0x00000010	/* re-map DCE to standard */
    272  1.20   thorpej #define	DCM_FLAGMASK	(DCM_STDDCE)	/* mask of valid bits in config flags */
    273  1.20   thorpej 
    274  1.20   thorpej #ifdef DCMSTATS
    275  1.20   thorpej 	struct	dcmstats sc_stats;	/* metrics gathering */
    276  1.20   thorpej #endif
    277  1.34   thorpej };
    278  1.34   thorpej 
    279  1.36    scottr int	dcmintr __P((void *));
    280  1.36    scottr void	dcmpint __P((struct dcm_softc *, int, int));
    281  1.36    scottr void	dcmrint __P((struct dcm_softc *));
    282  1.36    scottr void	dcmreadbuf __P((struct dcm_softc *, int));
    283  1.36    scottr void	dcmxint __P((struct dcm_softc *, int));
    284  1.36    scottr void	dcmmint __P((struct dcm_softc *, int, int));
    285  1.36    scottr 
    286  1.36    scottr int	dcmparam __P((struct tty *, struct termios *));
    287  1.36    scottr void	dcmstart __P((struct tty *));
    288  1.36    scottr int	dcmmctl __P((dev_t, int, int));
    289  1.36    scottr void	dcmsetischeme __P((int, int));
    290  1.22   thorpej void	dcminit __P((struct dcmdevice *, int, int));
    291  1.22   thorpej 
    292  1.34   thorpej int	dcmselftest __P((struct dcm_softc *));
    293  1.34   thorpej 
    294  1.48  gmcgarry int	dcmcnattach __P((bus_space_tag_t, bus_addr_t, int));
    295  1.36    scottr int	dcmcngetc __P((dev_t));
    296  1.36    scottr void	dcmcnputc __P((dev_t, int));
    297  1.36    scottr 
    298  1.38    scottr int	dcmmatch __P((struct device *, struct cfdata *, void *));
    299  1.38    scottr void	dcmattach __P((struct device *, struct device *, void *));
    300  1.38    scottr 
    301  1.54   thorpej CFATTACH_DECL(dcm, sizeof(struct dcm_softc),
    302  1.54   thorpej     dcmmatch, dcmattach, NULL, NULL);
    303  1.38    scottr 
    304  1.48  gmcgarry /*
    305  1.48  gmcgarry  * Stuff for DCM console support.  This could probably be done a little
    306  1.48  gmcgarry  * better.
    307  1.48  gmcgarry  */
    308  1.48  gmcgarry static	struct dcmdevice *dcm_cn = NULL;	/* pointer to hardware */
    309  1.48  gmcgarry static	int dcmconsinit;			/* has been initialized */
    310  1.48  gmcgarry /* static	int dcm_lastcnpri = CN_DEAD; */	/* XXX last priority */
    311  1.48  gmcgarry 
    312  1.48  gmcgarry static struct consdev dcm_cons = {
    313  1.57   thorpej        NULL,
    314  1.57   thorpej        NULL,
    315  1.57   thorpej        dcmcngetc,
    316  1.57   thorpej        dcmcnputc,
    317  1.57   thorpej        nullcnpollc,
    318  1.57   thorpej        NULL,
    319  1.57   thorpej        NULL,
    320  1.57   thorpej        NULL,
    321  1.57   thorpej        NODEV,
    322  1.57   thorpej        CN_REMOTE
    323  1.48  gmcgarry };
    324  1.48  gmcgarry int	dcmconscode;
    325  1.48  gmcgarry int	dcmdefaultrate = DEFAULT_BAUD_RATE;
    326  1.48  gmcgarry int	dcmconbrdbusy = 0;
    327  1.48  gmcgarry 
    328  1.43   thorpej extern struct cfdriver dcm_cd;
    329  1.38    scottr 
    330  1.52   gehenna dev_type_open(dcmopen);
    331  1.52   gehenna dev_type_close(dcmclose);
    332  1.52   gehenna dev_type_read(dcmread);
    333  1.52   gehenna dev_type_write(dcmwrite);
    334  1.52   gehenna dev_type_ioctl(dcmioctl);
    335  1.52   gehenna dev_type_stop(dcmstop);
    336  1.52   gehenna dev_type_tty(dcmtty);
    337  1.52   gehenna dev_type_poll(dcmpoll);
    338  1.52   gehenna 
    339  1.52   gehenna const struct cdevsw dcm_cdevsw = {
    340  1.52   gehenna 	dcmopen, dcmclose, dcmread, dcmwrite, dcmioctl,
    341  1.56  jdolecek 	dcmstop, dcmtty, dcmpoll, nommap, ttykqfilter, D_TTY
    342  1.52   gehenna };
    343  1.52   gehenna 
    344  1.34   thorpej int
    345  1.34   thorpej dcmmatch(parent, match, aux)
    346  1.34   thorpej 	struct device *parent;
    347  1.34   thorpej 	struct cfdata *match;
    348  1.34   thorpej 	void *aux;
    349  1.34   thorpej {
    350  1.34   thorpej 	struct dio_attach_args *da = aux;
    351  1.34   thorpej 
    352  1.34   thorpej 	switch (da->da_id) {
    353  1.34   thorpej 	case DIO_DEVICE_ID_DCM:
    354  1.34   thorpej 	case DIO_DEVICE_ID_DCMREM:
    355  1.34   thorpej 		return (1);
    356  1.34   thorpej 	}
    357  1.34   thorpej 
    358  1.34   thorpej 	return (0);
    359  1.34   thorpej }
    360  1.20   thorpej 
    361  1.34   thorpej void
    362  1.34   thorpej dcmattach(parent, self, aux)
    363  1.34   thorpej 	struct device *parent, *self;
    364  1.34   thorpej 	void *aux;
    365  1.34   thorpej {
    366  1.34   thorpej 	struct dcm_softc *sc = (struct dcm_softc *)self;
    367  1.34   thorpej 	struct dio_attach_args *da = aux;
    368  1.34   thorpej 	struct dcmdevice *dcm;
    369  1.34   thorpej 	int brd = self->dv_unit;
    370  1.34   thorpej 	int scode = da->da_scode;
    371  1.38    scottr 	int i, mbits, code, ipl;
    372  1.20   thorpej 
    373  1.36    scottr 	sc->sc_flags = 0;
    374  1.36    scottr 
    375  1.48  gmcgarry 	if (scode == dcmconscode) {
    376  1.48  gmcgarry 		dcm = dcm_cn;
    377  1.24   thorpej 		sc->sc_flags |= DCM_ISCONSOLE;
    378  1.24   thorpej 
    379  1.24   thorpej 		/*
    380  1.24   thorpej 		 * We didn't know which unit this would be during
    381  1.24   thorpej 		 * the console probe, so we have to fixup cn_dev here.
    382  1.24   thorpej 		 * Note that we always assume port 1 on the board.
    383  1.24   thorpej 		 */
    384  1.52   gehenna 		cn_tab->cn_dev = makedev(cdevsw_lookup_major(&dcm_cdevsw),
    385  1.52   gehenna 					 (brd << 2) | DCMCONSPORT);
    386  1.34   thorpej 	} else {
    387  1.34   thorpej 		dcm = (struct dcmdevice *)iomap(dio_scodetopa(da->da_scode),
    388  1.34   thorpej 		    da->da_size);
    389  1.34   thorpej 		if (dcm == NULL) {
    390  1.34   thorpej 			printf("\n%s: can't map registers\n",
    391  1.34   thorpej 			    sc->sc_dev.dv_xname);
    392  1.34   thorpej 			return;
    393  1.34   thorpej 		}
    394  1.34   thorpej 	}
    395  1.34   thorpej 
    396  1.34   thorpej 	sc->sc_dcm = dcm;
    397  1.34   thorpej 
    398  1.34   thorpej 	ipl = DIO_IPL(dcm);
    399  1.34   thorpej 	printf(" ipl %d", ipl);
    400  1.34   thorpej 
    401  1.38    scottr 	/*
    402  1.38    scottr 	 * XXX someone _should_ fix this; the self test screws
    403  1.38    scottr 	 * autoconfig messages.
    404  1.38    scottr 	 */
    405  1.38    scottr 	if ((sc->sc_flags & DCM_ISCONSOLE) && dcmselftest(sc)) {
    406  1.34   thorpej 		printf("\n%s: self-test failed\n", sc->sc_dev.dv_xname);
    407  1.34   thorpej 		return;
    408  1.24   thorpej 	}
    409  1.20   thorpej 
    410  1.20   thorpej 	/* Extract configuration info from flags. */
    411  1.34   thorpej 	sc->sc_softCAR = self->dv_cfdata->cf_flags & DCM_SOFTCAR;
    412  1.36    scottr 	sc->sc_flags |= self->dv_cfdata->cf_flags & DCM_FLAGMASK;
    413  1.20   thorpej 
    414  1.20   thorpej 	/* Mark our unit as configured. */
    415  1.20   thorpej 	sc->sc_flags |= DCM_ACTIVE;
    416  1.20   thorpej 
    417  1.20   thorpej 	/* Establish the interrupt handler. */
    418  1.41   thorpej 	(void) dio_intr_establish(dcmintr, sc, ipl, IPL_TTY);
    419  1.20   thorpej 
    420   1.1       cgd 	if (dcmistype == DIS_TIMER)
    421   1.1       cgd 		dcmsetischeme(brd, DIS_RESET|DIS_TIMER);
    422   1.1       cgd 	else
    423   1.1       cgd 		dcmsetischeme(brd, DIS_RESET|DIS_PERCHAR);
    424   1.1       cgd 
    425   1.1       cgd 	/* load pointers to modem control */
    426  1.20   thorpej 	sc->sc_modem[0] = &dcm->dcm_modem0;
    427  1.20   thorpej 	sc->sc_modem[1] = &dcm->dcm_modem1;
    428  1.20   thorpej 	sc->sc_modem[2] = &dcm->dcm_modem2;
    429  1.20   thorpej 	sc->sc_modem[3] = &dcm->dcm_modem3;
    430  1.20   thorpej 
    431   1.1       cgd 	/* set DCD (modem) and CTS (flow control) on all ports */
    432  1.20   thorpej 	if (sc->sc_flags & DCM_STDDCE)
    433   1.1       cgd 		mbits = hp2dce_in(MI_CD|MI_CTS);
    434   1.1       cgd 	else
    435   1.1       cgd 		mbits = MI_CD|MI_CTS;
    436  1.20   thorpej 
    437  1.20   thorpej 	for (i = 0; i < NDCMPORT; i++)
    438  1.20   thorpej 		sc->sc_modem[i]->mdmmsk = mbits;
    439   1.1       cgd 
    440  1.38    scottr 	/*
    441  1.38    scottr 	 * Get current state of mdmin register on all ports, so that
    442  1.38    scottr 	 * deltas will work properly.
    443  1.38    scottr 	 */
    444  1.38    scottr 	for (i = 0; i < NDCMPORT; i++) {
    445  1.38    scottr 		code = sc->sc_modem[i]->mdmin;
    446  1.38    scottr 		if (sc->sc_flags & DCM_STDDCE)
    447  1.38    scottr 			code = hp2dce_in(code);
    448  1.38    scottr 		sc->sc_mcndlast[i] = code;
    449  1.38    scottr 	}
    450  1.38    scottr 
    451   1.1       cgd 	dcm->dcm_ic = IC_IE;		/* turn all interrupts on */
    452  1.20   thorpej 
    453   1.1       cgd 	/*
    454  1.24   thorpej 	 * Need to reset baud rate, etc. of next print so reset dcmconsinit.
    455   1.1       cgd 	 * Also make sure console is always "hardwired"
    456   1.1       cgd 	 */
    457  1.24   thorpej 	if (sc->sc_flags & DCM_ISCONSOLE) {
    458   1.1       cgd 		dcmconsinit = 0;
    459  1.24   thorpej 		sc->sc_softCAR |= (1 << DCMCONSPORT);
    460  1.31  christos 		printf(": console on port %d\n", DCMCONSPORT);
    461  1.20   thorpej 	} else
    462  1.31  christos 		printf("\n");
    463  1.20   thorpej 
    464  1.20   thorpej #ifdef KGDB
    465  1.52   gehenna 	if (cdevsw_lookup(kgdb_dev) == &dcm_cdevsw &&
    466  1.20   thorpej 	    DCMBOARD(DCMUNIT(kgdb_dev)) == brd) {
    467  1.24   thorpej 		if (dcmconsole == DCMUNIT(kgdb_dev))	/* XXX fixme */
    468  1.20   thorpej 			kgdb_dev = NODEV; /* can't debug over console port */
    469  1.20   thorpej #ifndef KGDB_CHEAT
    470  1.20   thorpej 		/*
    471  1.20   thorpej 		 * The following could potentially be replaced
    472  1.20   thorpej 		 * by the corresponding code in dcmcnprobe.
    473  1.20   thorpej 		 */
    474  1.20   thorpej 		else {
    475  1.22   thorpej 			dcminit(dcm, DCMPORT(DCMUNIT(kgdb_dev)),
    476  1.22   thorpej 			    kgdb_rate);
    477  1.20   thorpej 			if (kgdb_debug_init) {
    478  1.34   thorpej 				printf("%s port %d: ", sc->sc_dev.dv_xname,
    479  1.20   thorpej 				    DCMPORT(DCMUNIT(kgdb_dev)));
    480  1.20   thorpej 				kgdb_connect(1);
    481  1.20   thorpej 			} else
    482  1.31  christos 				printf("%s port %d: kgdb enabled\n",
    483  1.34   thorpej 				    sc->sc_dev.dv_xname,
    484  1.20   thorpej 				    DCMPORT(DCMUNIT(kgdb_dev)));
    485  1.20   thorpej 		}
    486  1.20   thorpej 		/* end could be replaced */
    487  1.34   thorpej #endif /* KGDB_CHEAT */
    488   1.1       cgd 	}
    489  1.34   thorpej #endif /* KGDB */
    490   1.1       cgd }
    491   1.1       cgd 
    492   1.1       cgd /* ARGSUSED */
    493  1.17   mycroft int
    494   1.1       cgd dcmopen(dev, flag, mode, p)
    495   1.1       cgd 	dev_t dev;
    496   1.1       cgd 	int flag, mode;
    497   1.1       cgd 	struct proc *p;
    498   1.1       cgd {
    499  1.20   thorpej 	struct dcm_softc *sc;
    500  1.20   thorpej 	struct tty *tp;
    501  1.20   thorpej 	int unit, brd, port;
    502  1.18   thorpej 	int error = 0, mbits, s;
    503   1.1       cgd 
    504  1.20   thorpej 	unit = DCMUNIT(dev);
    505  1.20   thorpej 	brd = DCMBOARD(unit);
    506  1.20   thorpej 	port = DCMPORT(unit);
    507  1.20   thorpej 
    508  1.34   thorpej 	if (brd >= dcm_cd.cd_ndevs || port >= NDCMPORT ||
    509  1.34   thorpej 	    (sc = dcm_cd.cd_devs[brd]) == NULL)
    510  1.34   thorpej 		return (ENXIO);
    511  1.20   thorpej 
    512  1.20   thorpej 	if ((sc->sc_flags & DCM_ACTIVE) == 0)
    513  1.20   thorpej 		return (ENXIO);
    514  1.20   thorpej 
    515  1.28   thorpej 	if (sc->sc_tty[port] == NULL) {
    516  1.20   thorpej 		tp = sc->sc_tty[port] = ttymalloc();
    517  1.28   thorpej 		tty_attach(tp);
    518  1.28   thorpej 	} else
    519  1.20   thorpej 		tp = sc->sc_tty[port];
    520  1.20   thorpej 
    521   1.1       cgd 	tp->t_oproc = dcmstart;
    522   1.1       cgd 	tp->t_param = dcmparam;
    523   1.1       cgd 	tp->t_dev = dev;
    524  1.18   thorpej 
    525  1.44   thorpej 	if ((tp->t_state & TS_ISOPEN) &&
    526  1.44   thorpej 	    (tp->t_state & TS_XCLUDE) &&
    527  1.44   thorpej 	    p->p_ucred->cr_uid != 0)
    528  1.44   thorpej 		return (EBUSY);
    529  1.44   thorpej 
    530  1.44   thorpej 	s = spltty();
    531  1.44   thorpej 
    532  1.44   thorpej 	if ((tp->t_state & TS_ISOPEN) == 0 && tp->t_wopen == 0) {
    533  1.18   thorpej 		/*
    534  1.18   thorpej 		 * Sanity clause: reset the card on first open.
    535  1.18   thorpej 		 * The card might be left in an inconsistent state
    536  1.18   thorpej 		 * if the card memory is read inadvertently.
    537  1.18   thorpej 		 */
    538  1.22   thorpej 		dcminit(sc->sc_dcm, port, dcmdefaultrate);
    539  1.18   thorpej 
    540   1.1       cgd 		ttychars(tp);
    541  1.18   thorpej 		tp->t_iflag = TTYDEF_IFLAG;
    542  1.18   thorpej 		tp->t_oflag = TTYDEF_OFLAG;
    543  1.18   thorpej 		tp->t_cflag = TTYDEF_CFLAG;
    544  1.18   thorpej 		tp->t_lflag = TTYDEF_LFLAG;
    545  1.18   thorpej 		tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
    546  1.18   thorpej 
    547   1.1       cgd 		(void) dcmparam(tp, &tp->t_termios);
    548   1.1       cgd 		ttsetwater(tp);
    549  1.18   thorpej 
    550  1.44   thorpej 		/* Set modem control state. */
    551  1.44   thorpej 		mbits = MO_ON;
    552  1.44   thorpej 		if (sc->sc_flags & DCM_STDDCE)
    553  1.44   thorpej 			mbits |= MO_SR;	/* pin 23, could be used as RTS */
    554  1.44   thorpej 
    555  1.44   thorpej 		(void) dcmmctl(dev, mbits, DMSET);	/* enable port */
    556  1.20   thorpej 
    557  1.44   thorpej 		/* Set soft-carrier if so configured. */
    558  1.44   thorpej 		if ((sc->sc_softCAR & (1 << port)) ||
    559  1.44   thorpej 		    (dcmmctl(dev, MO_OFF, DMGET) & MI_CD))
    560  1.44   thorpej 			tp->t_state |= TS_CARR_ON;
    561  1.44   thorpej 	}
    562  1.18   thorpej 
    563  1.44   thorpej 	splx(s);
    564  1.18   thorpej 
    565   1.1       cgd #ifdef DEBUG
    566   1.1       cgd 	if (dcmdebug & DDB_MODEM)
    567  1.31  christos 		printf("%s: dcmopen port %d softcarr %c\n",
    568  1.34   thorpej 		       sc->sc_dev.dv_xname, port,
    569  1.20   thorpej 		       (tp->t_state & TS_CARR_ON) ? '1' : '0');
    570   1.1       cgd #endif
    571  1.18   thorpej 
    572  1.44   thorpej 	error = ttyopen(tp, DCMDIALOUT(dev), (flag & O_NONBLOCK));
    573  1.44   thorpej 	if (error)
    574  1.44   thorpej 		goto bad;
    575   1.1       cgd 
    576   1.1       cgd #ifdef DEBUG
    577   1.1       cgd 	if (dcmdebug & DDB_OPENCLOSE)
    578  1.31  christos 		printf("%s port %d: dcmopen: st %x fl %x\n",
    579  1.34   thorpej 			sc->sc_dev.dv_xname, port, tp->t_state, tp->t_flags);
    580   1.1       cgd #endif
    581  1.45       eeh 	error = (*tp->t_linesw->l_open)(dev, tp);
    582  1.18   thorpej 
    583  1.44   thorpej  bad:
    584   1.1       cgd 	return (error);
    585   1.1       cgd }
    586   1.1       cgd 
    587   1.1       cgd /*ARGSUSED*/
    588  1.17   mycroft int
    589   1.1       cgd dcmclose(dev, flag, mode, p)
    590   1.1       cgd 	dev_t dev;
    591   1.1       cgd 	int flag, mode;
    592   1.1       cgd 	struct proc *p;
    593   1.1       cgd {
    594  1.20   thorpej 	int s, unit, board, port;
    595  1.20   thorpej 	struct dcm_softc *sc;
    596  1.20   thorpej 	struct tty *tp;
    597   1.1       cgd 
    598  1.20   thorpej 	unit = DCMUNIT(dev);
    599  1.20   thorpej 	board = DCMBOARD(unit);
    600  1.20   thorpej 	port = DCMPORT(unit);
    601  1.20   thorpej 
    602  1.34   thorpej 	sc = dcm_cd.cd_devs[board];
    603  1.20   thorpej 	tp = sc->sc_tty[port];
    604  1.20   thorpej 
    605  1.45       eeh 	(*tp->t_linesw->l_close)(tp, flag);
    606  1.18   thorpej 
    607  1.18   thorpej 	s = spltty();
    608  1.18   thorpej 
    609  1.44   thorpej 	if (tp->t_cflag & HUPCL || tp->t_wopen != 0 ||
    610  1.18   thorpej 	    (tp->t_state & TS_ISOPEN) == 0)
    611   1.1       cgd 		(void) dcmmctl(dev, MO_OFF, DMSET);
    612   1.1       cgd #ifdef DEBUG
    613   1.1       cgd 	if (dcmdebug & DDB_OPENCLOSE)
    614  1.31  christos 		printf("%s port %d: dcmclose: st %x fl %x\n",
    615  1.34   thorpej 			sc->sc_dev.dv_xname, port, tp->t_state, tp->t_flags);
    616   1.1       cgd #endif
    617  1.18   thorpej 	splx(s);
    618   1.1       cgd 	ttyclose(tp);
    619  1.12   mycroft #if 0
    620  1.28   thorpej 	tty_detach(tp);
    621   1.7   mycroft 	ttyfree(tp);
    622  1.20   thorpej 	sc->sc_tty[port] == NULL;
    623  1.12   mycroft #endif
    624   1.1       cgd 	return (0);
    625   1.1       cgd }
    626   1.1       cgd 
    627  1.17   mycroft int
    628   1.1       cgd dcmread(dev, uio, flag)
    629   1.1       cgd 	dev_t dev;
    630   1.1       cgd 	struct uio *uio;
    631  1.14   mycroft 	int flag;
    632   1.1       cgd {
    633  1.20   thorpej 	int unit, board, port;
    634  1.20   thorpej 	struct dcm_softc *sc;
    635  1.36    scottr 	struct tty *tp;
    636  1.20   thorpej 
    637  1.20   thorpej 	unit = DCMUNIT(dev);
    638  1.20   thorpej 	board = DCMBOARD(unit);
    639  1.20   thorpej 	port = DCMPORT(unit);
    640  1.20   thorpej 
    641  1.34   thorpej 	sc = dcm_cd.cd_devs[board];
    642  1.20   thorpej 	tp = sc->sc_tty[port];
    643  1.14   mycroft 
    644  1.45       eeh 	return ((*tp->t_linesw->l_read)(tp, uio, flag));
    645   1.1       cgd }
    646   1.1       cgd 
    647  1.17   mycroft int
    648   1.1       cgd dcmwrite(dev, uio, flag)
    649   1.1       cgd 	dev_t dev;
    650   1.1       cgd 	struct uio *uio;
    651  1.14   mycroft 	int flag;
    652   1.1       cgd {
    653  1.20   thorpej 	int unit, board, port;
    654  1.20   thorpej 	struct dcm_softc *sc;
    655  1.36    scottr 	struct tty *tp;
    656  1.20   thorpej 
    657  1.20   thorpej 	unit = DCMUNIT(dev);
    658  1.20   thorpej 	board = DCMBOARD(unit);
    659  1.20   thorpej 	port = DCMPORT(unit);
    660  1.20   thorpej 
    661  1.34   thorpej 	sc = dcm_cd.cd_devs[board];
    662  1.20   thorpej 	tp = sc->sc_tty[port];
    663  1.14   mycroft 
    664  1.45       eeh 	return ((*tp->t_linesw->l_write)(tp, uio, flag));
    665  1.46       scw }
    666  1.46       scw 
    667  1.46       scw int
    668  1.46       scw dcmpoll(dev, events, p)
    669  1.46       scw 	dev_t dev;
    670  1.46       scw 	int events;
    671  1.46       scw 	struct proc *p;
    672  1.46       scw {
    673  1.46       scw 	int unit, board, port;
    674  1.46       scw 	struct dcm_softc *sc;
    675  1.46       scw 	struct tty *tp;
    676  1.46       scw 
    677  1.46       scw 	unit = DCMUNIT(dev);
    678  1.46       scw 	board = DCMBOARD(unit);
    679  1.46       scw 	port = DCMPORT(unit);
    680  1.46       scw 
    681  1.46       scw 	sc = dcm_cd.cd_devs[board];
    682  1.46       scw 	tp = sc->sc_tty[port];
    683  1.46       scw 
    684  1.46       scw 	return ((*tp->t_linesw->l_poll)(tp, events, p));
    685   1.1       cgd }
    686  1.17   mycroft 
    687  1.17   mycroft struct tty *
    688  1.17   mycroft dcmtty(dev)
    689  1.17   mycroft 	dev_t dev;
    690  1.17   mycroft {
    691  1.20   thorpej 	int unit, board, port;
    692  1.20   thorpej 	struct dcm_softc *sc;
    693  1.17   mycroft 
    694  1.20   thorpej 	unit = DCMUNIT(dev);
    695  1.20   thorpej 	board = DCMBOARD(unit);
    696  1.20   thorpej 	port = DCMPORT(unit);
    697  1.20   thorpej 
    698  1.34   thorpej 	sc = dcm_cd.cd_devs[board];
    699  1.20   thorpej 
    700  1.20   thorpej 	return (sc->sc_tty[port]);
    701  1.17   mycroft }
    702   1.1       cgd 
    703  1.17   mycroft int
    704  1.23   thorpej dcmintr(arg)
    705  1.23   thorpej 	void *arg;
    706   1.1       cgd {
    707  1.23   thorpej 	struct dcm_softc *sc = arg;
    708  1.20   thorpej 	struct dcmdevice *dcm = sc->sc_dcm;
    709  1.20   thorpej 	struct dcmischeme *dis = &sc->sc_scheme;
    710  1.34   thorpej 	int brd = sc->sc_dev.dv_unit;
    711  1.20   thorpej 	int code, i;
    712   1.1       cgd 	int pcnd[4], mcode, mcnd[4];
    713   1.1       cgd 
    714   1.1       cgd 	/*
    715  1.36    scottr 	 * Do all guarded accesses right off to minimize
    716   1.1       cgd 	 * block out of hardware.
    717   1.1       cgd 	 */
    718   1.1       cgd 	SEM_LOCK(dcm);
    719   1.1       cgd 	if ((dcm->dcm_ic & IC_IR) == 0) {
    720   1.1       cgd 		SEM_UNLOCK(dcm);
    721   1.1       cgd 		return (0);
    722   1.1       cgd 	}
    723   1.1       cgd 	for (i = 0; i < 4; i++) {
    724   1.1       cgd 		pcnd[i] = dcm->dcm_icrtab[i].dcm_data;
    725   1.1       cgd 		dcm->dcm_icrtab[i].dcm_data = 0;
    726  1.20   thorpej 		code = sc->sc_modem[i]->mdmin;
    727  1.20   thorpej 		if (sc->sc_flags & DCM_STDDCE)
    728   1.1       cgd 			code = hp2dce_in(code);
    729   1.1       cgd 		mcnd[i] = code;
    730   1.1       cgd 	}
    731   1.1       cgd 	code = dcm->dcm_iir & IIR_MASK;
    732   1.1       cgd 	dcm->dcm_iir = 0;	/* XXX doc claims read clears interrupt?! */
    733   1.1       cgd 	mcode = dcm->dcm_modemintr;
    734   1.1       cgd 	dcm->dcm_modemintr = 0;
    735   1.1       cgd 	SEM_UNLOCK(dcm);
    736   1.1       cgd 
    737   1.1       cgd #ifdef DEBUG
    738   1.1       cgd 	if (dcmdebug & DDB_INTR) {
    739  1.31  christos 		printf("%s: dcmintr: iir %x pc %x/%x/%x/%x ",
    740  1.34   thorpej 		       sc->sc_dev.dv_xname, code, pcnd[0], pcnd[1],
    741  1.20   thorpej 		       pcnd[2], pcnd[3]);
    742  1.31  christos 		printf("miir %x mc %x/%x/%x/%x\n",
    743   1.1       cgd 		       mcode, mcnd[0], mcnd[1], mcnd[2], mcnd[3]);
    744   1.1       cgd 	}
    745   1.1       cgd #endif
    746   1.1       cgd 	if (code & IIR_TIMEO)
    747  1.20   thorpej 		dcmrint(sc);
    748   1.1       cgd 	if (code & IIR_PORT0)
    749  1.20   thorpej 		dcmpint(sc, 0, pcnd[0]);
    750   1.1       cgd 	if (code & IIR_PORT1)
    751  1.20   thorpej 		dcmpint(sc, 1, pcnd[1]);
    752   1.1       cgd 	if (code & IIR_PORT2)
    753  1.20   thorpej 		dcmpint(sc, 2, pcnd[2]);
    754   1.1       cgd 	if (code & IIR_PORT3)
    755  1.20   thorpej 		dcmpint(sc, 3, pcnd[3]);
    756   1.1       cgd 	if (code & IIR_MODM) {
    757   1.1       cgd 		if (mcode == 0 || mcode & 0x1)	/* mcode==0 -> 98642 board */
    758  1.20   thorpej 			dcmmint(sc, 0, mcnd[0]);
    759   1.1       cgd 		if (mcode & 0x2)
    760  1.20   thorpej 			dcmmint(sc, 1, mcnd[1]);
    761   1.1       cgd 		if (mcode & 0x4)
    762  1.20   thorpej 			dcmmint(sc, 2, mcnd[2]);
    763   1.1       cgd 		if (mcode & 0x8)
    764  1.20   thorpej 			dcmmint(sc, 3, mcnd[3]);
    765   1.1       cgd 	}
    766   1.1       cgd 
    767   1.1       cgd 	/*
    768   1.1       cgd 	 * Chalk up a receiver interrupt if the timer running or one of
    769   1.1       cgd 	 * the ports reports a special character interrupt.
    770   1.1       cgd 	 */
    771   1.1       cgd 	if ((code & IIR_TIMEO) ||
    772   1.1       cgd 	    ((pcnd[0]|pcnd[1]|pcnd[2]|pcnd[3]) & IT_SPEC))
    773   1.1       cgd 		dis->dis_intr++;
    774   1.1       cgd 	/*
    775   1.1       cgd 	 * See if it is time to check/change the interrupt rate.
    776   1.1       cgd 	 */
    777   1.1       cgd 	if (dcmistype < 0 &&
    778   1.1       cgd 	    (i = time.tv_sec - dis->dis_time) >= dcminterval) {
    779   1.1       cgd 		/*
    780   1.1       cgd 		 * If currently per-character and averaged over 70 interrupts
    781   1.1       cgd 		 * per-second (66 is threshold of 600 baud) in last interval,
    782   1.1       cgd 		 * switch to timer mode.
    783   1.1       cgd 		 *
    784   1.1       cgd 		 * XXX decay counts ala load average to avoid spikes?
    785   1.1       cgd 		 */
    786   1.1       cgd 		if (dis->dis_perchar && dis->dis_intr > 70 * i)
    787   1.1       cgd 			dcmsetischeme(brd, DIS_TIMER);
    788   1.1       cgd 		/*
    789   1.1       cgd 		 * If currently using timer and had more interrupts than
    790   1.1       cgd 		 * received characters in the last interval, switch back
    791   1.1       cgd 		 * to per-character.  Note that after changing to per-char
    792   1.1       cgd 		 * we must process any characters already in the queue
    793   1.1       cgd 		 * since they may have arrived before the bitmap was setup.
    794   1.1       cgd 		 *
    795   1.1       cgd 		 * XXX decay counts?
    796   1.1       cgd 		 */
    797   1.1       cgd 		else if (!dis->dis_perchar && dis->dis_intr > dis->dis_char) {
    798   1.1       cgd 			dcmsetischeme(brd, DIS_PERCHAR);
    799  1.20   thorpej 			dcmrint(sc);
    800   1.1       cgd 		}
    801   1.1       cgd 		dis->dis_intr = dis->dis_char = 0;
    802   1.1       cgd 		dis->dis_time = time.tv_sec;
    803   1.1       cgd 	}
    804   1.1       cgd 	return (1);
    805   1.1       cgd }
    806   1.1       cgd 
    807   1.1       cgd /*
    808   1.1       cgd  *  Port interrupt.  Can be two things:
    809   1.1       cgd  *	First, it might be a special character (exception interrupt);
    810   1.1       cgd  *	Second, it may be a buffer empty (transmit interrupt);
    811   1.1       cgd  */
    812  1.36    scottr void
    813  1.20   thorpej dcmpint(sc, port, code)
    814  1.20   thorpej 	struct dcm_softc *sc;
    815  1.20   thorpej 	int port, code;
    816   1.1       cgd {
    817   1.1       cgd 
    818   1.1       cgd 	if (code & IT_SPEC)
    819  1.20   thorpej 		dcmreadbuf(sc, port);
    820   1.1       cgd 	if (code & IT_TX)
    821  1.20   thorpej 		dcmxint(sc, port);
    822   1.1       cgd }
    823   1.1       cgd 
    824  1.36    scottr void
    825  1.20   thorpej dcmrint(sc)
    826  1.20   thorpej 	struct dcm_softc *sc;
    827   1.1       cgd {
    828  1.20   thorpej 	int port;
    829   1.1       cgd 
    830  1.20   thorpej 	for (port = 0; port < NDCMPORT; port++)
    831  1.20   thorpej 		dcmreadbuf(sc, port);
    832   1.1       cgd }
    833   1.1       cgd 
    834  1.36    scottr void
    835  1.20   thorpej dcmreadbuf(sc, port)
    836  1.20   thorpej 	struct dcm_softc *sc;
    837  1.20   thorpej 	int port;
    838   1.1       cgd {
    839  1.20   thorpej 	struct dcmdevice *dcm = sc->sc_dcm;
    840  1.20   thorpej 	struct dcmpreg *pp = dcm_preg(dcm, port);
    841  1.20   thorpej 	struct dcmrfifo *fifo;
    842  1.38    scottr 	struct tty *tp;
    843  1.20   thorpej 	int c, stat;
    844  1.20   thorpej 	u_int head;
    845   1.1       cgd 	int nch = 0;
    846  1.14   mycroft #ifdef DCMSTATS
    847  1.20   thorpej 	struct dcmstats *dsp = &sc->sc_stats;
    848   1.1       cgd 
    849   1.1       cgd 	dsp->rints++;
    850   1.1       cgd #endif
    851  1.38    scottr 	tp = sc->sc_tty[port];
    852  1.40    scottr 	if (tp == NULL)
    853  1.38    scottr 		return;
    854  1.38    scottr 
    855   1.1       cgd 	if ((tp->t_state & TS_ISOPEN) == 0) {
    856   1.1       cgd #ifdef KGDB
    857  1.52   gehenna 		int maj;
    858  1.52   gehenna 
    859  1.52   gehenna 		maj = cdevsw_lookup_major(&dcm_cdevsw);
    860  1.52   gehenna 
    861  1.52   gehenna 		if ((makedev(maj, minor(tp->t_dev)) == kgdb_dev) &&
    862   1.1       cgd 		    (head = pp->r_head & RX_MASK) != (pp->r_tail & RX_MASK) &&
    863  1.14   mycroft 		    dcm->dcm_rfifos[3-port][head>>1].data_char == FRAME_START) {
    864   1.1       cgd 			pp->r_head = (head + 2) & RX_MASK;
    865   1.1       cgd 			kgdb_connect(0);	/* trap into kgdb */
    866   1.1       cgd 			return;
    867   1.1       cgd 		}
    868   1.1       cgd #endif /* KGDB */
    869   1.1       cgd 		pp->r_head = pp->r_tail & RX_MASK;
    870   1.1       cgd 		return;
    871   1.1       cgd 	}
    872   1.1       cgd 
    873   1.1       cgd 	head = pp->r_head & RX_MASK;
    874   1.1       cgd 	fifo = &dcm->dcm_rfifos[3-port][head>>1];
    875   1.1       cgd 	/*
    876   1.1       cgd 	 * XXX upper bound on how many chars we will take in one swallow?
    877   1.1       cgd 	 */
    878   1.1       cgd 	while (head != (pp->r_tail & RX_MASK)) {
    879   1.1       cgd 		/*
    880   1.1       cgd 		 * Get character/status and update head pointer as fast
    881   1.1       cgd 		 * as possible to make room for more characters.
    882   1.1       cgd 		 */
    883   1.1       cgd 		c = fifo->data_char;
    884   1.1       cgd 		stat = fifo->data_stat;
    885   1.1       cgd 		head = (head + 2) & RX_MASK;
    886   1.1       cgd 		pp->r_head = head;
    887   1.1       cgd 		fifo = head ? fifo+1 : &dcm->dcm_rfifos[3-port][0];
    888   1.1       cgd 		nch++;
    889   1.1       cgd 
    890   1.1       cgd #ifdef DEBUG
    891   1.1       cgd 		if (dcmdebug & DDB_INPUT)
    892  1.31  christos 			printf("%s port %d: dcmreadbuf: c%x('%c') s%x f%x h%x t%x\n",
    893  1.34   thorpej 			       sc->sc_dev.dv_xname, port,
    894  1.20   thorpej 			       c&0xFF, c, stat&0xFF,
    895   1.1       cgd 			       tp->t_flags, head, pp->r_tail);
    896   1.1       cgd #endif
    897   1.1       cgd 		/*
    898   1.1       cgd 		 * Check for and handle errors
    899   1.1       cgd 		 */
    900   1.1       cgd 		if (stat & RD_MASK) {
    901   1.1       cgd #ifdef DEBUG
    902   1.1       cgd 			if (dcmdebug & (DDB_INPUT|DDB_SIOERR))
    903  1.31  christos 				printf("%s port %d: dcmreadbuf: err: c%x('%c') s%x\n",
    904  1.34   thorpej 				       sc->sc_dev.dv_xname, port,
    905  1.20   thorpej 				       stat, c&0xFF, c);
    906   1.1       cgd #endif
    907   1.1       cgd 			if (stat & (RD_BD | RD_FE))
    908   1.1       cgd 				c |= TTY_FE;
    909   1.1       cgd 			else if (stat & RD_PE)
    910   1.1       cgd 				c |= TTY_PE;
    911   1.1       cgd 			else if (stat & RD_OVF)
    912   1.1       cgd 				log(LOG_WARNING,
    913  1.20   thorpej 				    "%s port %d: silo overflow\n",
    914  1.34   thorpej 				    sc->sc_dev.dv_xname, port);
    915   1.1       cgd 			else if (stat & RD_OE)
    916   1.1       cgd 				log(LOG_WARNING,
    917  1.20   thorpej 				    "%s port %d: uart overflow\n",
    918  1.34   thorpej 				    sc->sc_dev.dv_xname, port);
    919   1.1       cgd 		}
    920  1.45       eeh 		(*tp->t_linesw->l_rint)(c, tp);
    921   1.1       cgd 	}
    922  1.20   thorpej 	sc->sc_scheme.dis_char += nch;
    923  1.20   thorpej 
    924  1.14   mycroft #ifdef DCMSTATS
    925   1.1       cgd 	dsp->rchars += nch;
    926   1.1       cgd 	if (nch <= DCMRBSIZE)
    927   1.1       cgd 		dsp->rsilo[nch]++;
    928   1.1       cgd 	else
    929   1.1       cgd 		dsp->rsilo[DCMRBSIZE+1]++;
    930   1.1       cgd #endif
    931   1.1       cgd }
    932   1.1       cgd 
    933  1.36    scottr void
    934  1.20   thorpej dcmxint(sc, port)
    935  1.20   thorpej 	struct dcm_softc *sc;
    936  1.20   thorpej 	int port;
    937   1.1       cgd {
    938  1.38    scottr 	struct tty *tp;
    939  1.38    scottr 
    940  1.38    scottr 	tp = sc->sc_tty[port];
    941  1.38    scottr 	if (tp == NULL || (tp->t_state & TS_ISOPEN) == 0)
    942  1.38    scottr 		return;
    943  1.20   thorpej 
    944   1.1       cgd 	tp->t_state &= ~TS_BUSY;
    945   1.1       cgd 	if (tp->t_state & TS_FLUSH)
    946   1.1       cgd 		tp->t_state &= ~TS_FLUSH;
    947  1.45       eeh 	(*tp->t_linesw->l_start)(tp);
    948   1.1       cgd }
    949   1.1       cgd 
    950  1.36    scottr void
    951  1.20   thorpej dcmmint(sc, port, mcnd)
    952  1.20   thorpej 	struct dcm_softc *sc;
    953  1.20   thorpej 	int port, mcnd;
    954   1.1       cgd {
    955   1.1       cgd 	int delta;
    956  1.20   thorpej 	struct tty *tp;
    957  1.20   thorpej 	struct dcmdevice *dcm = sc->sc_dcm;
    958  1.20   thorpej 
    959  1.20   thorpej 	tp = sc->sc_tty[port];
    960  1.38    scottr 	if (tp == NULL || (tp->t_state & TS_ISOPEN) == 0)
    961  1.38    scottr 		return;
    962   1.1       cgd 
    963   1.1       cgd #ifdef DEBUG
    964   1.1       cgd 	if (dcmdebug & DDB_MODEM)
    965  1.31  christos 		printf("%s port %d: dcmmint: mcnd %x mcndlast %x\n",
    966  1.34   thorpej 		       sc->sc_dev.dv_xname, port, mcnd, sc->sc_mcndlast[port]);
    967   1.1       cgd #endif
    968  1.20   thorpej 	delta = mcnd ^ sc->sc_mcndlast[port];
    969  1.20   thorpej 	sc->sc_mcndlast[port] = mcnd;
    970   1.1       cgd 	if ((delta & MI_CTS) && (tp->t_state & TS_ISOPEN) &&
    971  1.55  gmcgarry 	    (tp->t_cflag & CCTS_OFLOW)) {
    972   1.1       cgd 		if (mcnd & MI_CTS) {
    973   1.1       cgd 			tp->t_state &= ~TS_TTSTOP;
    974   1.1       cgd 			ttstart(tp);
    975   1.1       cgd 		} else
    976   1.1       cgd 			tp->t_state |= TS_TTSTOP;	/* inline dcmstop */
    977   1.1       cgd 	}
    978   1.1       cgd 	if (delta & MI_CD) {
    979   1.1       cgd 		if (mcnd & MI_CD)
    980  1.45       eeh 			(void)(*tp->t_linesw->l_modem)(tp, 1);
    981  1.20   thorpej 		else if ((sc->sc_softCAR & (1 << port)) == 0 &&
    982  1.45       eeh 		    (*tp->t_linesw->l_modem)(tp, 0) == 0) {
    983  1.20   thorpej 			sc->sc_modem[port]->mdmout = MO_OFF;
    984   1.1       cgd 			SEM_LOCK(dcm);
    985  1.20   thorpej 			dcm->dcm_modemchng |= (1 << port);
    986   1.1       cgd 			dcm->dcm_cr |= CR_MODM;
    987   1.1       cgd 			SEM_UNLOCK(dcm);
    988   1.1       cgd 			DELAY(10); /* time to change lines */
    989   1.1       cgd 		}
    990   1.1       cgd 	}
    991   1.1       cgd }
    992   1.1       cgd 
    993  1.17   mycroft int
    994  1.13   mycroft dcmioctl(dev, cmd, data, flag, p)
    995   1.1       cgd 	dev_t dev;
    996  1.36    scottr 	u_long cmd;
    997   1.1       cgd 	caddr_t data;
    998  1.13   mycroft 	int flag;
    999  1.13   mycroft 	struct proc *p;
   1000   1.1       cgd {
   1001  1.20   thorpej 	struct dcm_softc *sc;
   1002  1.20   thorpej 	struct tty *tp;
   1003  1.20   thorpej 	struct dcmdevice *dcm;
   1004  1.20   thorpej 	int board, port, unit = DCMUNIT(dev);
   1005   1.1       cgd 	int error, s;
   1006  1.20   thorpej 
   1007  1.20   thorpej 	port = DCMPORT(unit);
   1008  1.20   thorpej 	board = DCMBOARD(unit);
   1009  1.20   thorpej 
   1010  1.34   thorpej 	sc = dcm_cd.cd_devs[board];
   1011  1.20   thorpej 	dcm = sc->sc_dcm;
   1012  1.20   thorpej 	tp = sc->sc_tty[port];
   1013   1.1       cgd 
   1014   1.1       cgd #ifdef DEBUG
   1015   1.1       cgd 	if (dcmdebug & DDB_IOCTL)
   1016  1.37    scottr 		printf("%s port %d: dcmioctl: cmd %lx data %x flag %x\n",
   1017  1.34   thorpej 		       sc->sc_dev.dv_xname, port, cmd, *data, flag);
   1018   1.1       cgd #endif
   1019  1.51    atatat 
   1020  1.45       eeh 	error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, p);
   1021  1.51    atatat 	if (error != EPASSTHROUGH)
   1022   1.1       cgd 		return (error);
   1023  1.51    atatat 
   1024  1.13   mycroft 	error = ttioctl(tp, cmd, data, flag, p);
   1025  1.51    atatat 	if (error != EPASSTHROUGH)
   1026   1.1       cgd 		return (error);
   1027   1.1       cgd 
   1028   1.1       cgd 	switch (cmd) {
   1029   1.1       cgd 	case TIOCSBRK:
   1030   1.1       cgd 		/*
   1031   1.1       cgd 		 * Wait for transmitter buffer to empty
   1032   1.1       cgd 		 */
   1033   1.1       cgd 		s = spltty();
   1034   1.1       cgd 		while (dcm->dcm_thead[port].ptr != dcm->dcm_ttail[port].ptr)
   1035   1.1       cgd 			DELAY(DCM_USPERCH(tp->t_ospeed));
   1036   1.1       cgd 		SEM_LOCK(dcm);
   1037   1.1       cgd 		dcm->dcm_cmdtab[port].dcm_data |= CT_BRK;
   1038   1.1       cgd 		dcm->dcm_cr |= (1 << port);	/* start break */
   1039   1.1       cgd 		SEM_UNLOCK(dcm);
   1040   1.1       cgd 		splx(s);
   1041   1.1       cgd 		break;
   1042   1.1       cgd 
   1043   1.1       cgd 	case TIOCCBRK:
   1044   1.1       cgd 		SEM_LOCK(dcm);
   1045   1.1       cgd 		dcm->dcm_cmdtab[port].dcm_data |= CT_BRK;
   1046   1.1       cgd 		dcm->dcm_cr |= (1 << port);	/* end break */
   1047   1.1       cgd 		SEM_UNLOCK(dcm);
   1048   1.1       cgd 		break;
   1049   1.1       cgd 
   1050   1.1       cgd 	case TIOCSDTR:
   1051   1.1       cgd 		(void) dcmmctl(dev, MO_ON, DMBIS);
   1052   1.1       cgd 		break;
   1053   1.1       cgd 
   1054   1.1       cgd 	case TIOCCDTR:
   1055   1.1       cgd 		(void) dcmmctl(dev, MO_ON, DMBIC);
   1056   1.1       cgd 		break;
   1057   1.1       cgd 
   1058   1.1       cgd 	case TIOCMSET:
   1059   1.1       cgd 		(void) dcmmctl(dev, *(int *)data, DMSET);
   1060   1.1       cgd 		break;
   1061   1.1       cgd 
   1062   1.1       cgd 	case TIOCMBIS:
   1063   1.1       cgd 		(void) dcmmctl(dev, *(int *)data, DMBIS);
   1064   1.1       cgd 		break;
   1065   1.1       cgd 
   1066   1.1       cgd 	case TIOCMBIC:
   1067   1.1       cgd 		(void) dcmmctl(dev, *(int *)data, DMBIC);
   1068   1.1       cgd 		break;
   1069   1.1       cgd 
   1070   1.1       cgd 	case TIOCMGET:
   1071   1.1       cgd 		*(int *)data = dcmmctl(dev, 0, DMGET);
   1072   1.1       cgd 		break;
   1073  1.18   thorpej 
   1074  1.18   thorpej 	case TIOCGFLAGS: {
   1075  1.18   thorpej 		int bits = 0;
   1076  1.18   thorpej 
   1077  1.20   thorpej 		if ((sc->sc_softCAR & (1 << port)))
   1078  1.18   thorpej 			bits |= TIOCFLAG_SOFTCAR;
   1079  1.18   thorpej 
   1080  1.18   thorpej 		if (tp->t_cflag & CLOCAL)
   1081  1.18   thorpej 			bits |= TIOCFLAG_CLOCAL;
   1082  1.18   thorpej 
   1083  1.18   thorpej 		*(int *)data = bits;
   1084  1.18   thorpej 		break;
   1085  1.18   thorpej 	}
   1086  1.18   thorpej 
   1087  1.18   thorpej 	case TIOCSFLAGS: {
   1088  1.18   thorpej 		int userbits;
   1089  1.18   thorpej 
   1090  1.18   thorpej 		error = suser(p->p_ucred, &p->p_acflag);
   1091  1.18   thorpej 		if (error)
   1092  1.18   thorpej 			return (EPERM);
   1093  1.18   thorpej 
   1094  1.18   thorpej 		userbits = *(int *)data;
   1095  1.18   thorpej 
   1096  1.18   thorpej 		if ((userbits & TIOCFLAG_SOFTCAR) ||
   1097  1.24   thorpej 		    ((sc->sc_flags & DCM_ISCONSOLE) &&
   1098  1.24   thorpej 		    (port == DCMCONSPORT)))
   1099  1.20   thorpej 			sc->sc_softCAR |= (1 << port);
   1100  1.18   thorpej 
   1101  1.18   thorpej 		if (userbits & TIOCFLAG_CLOCAL)
   1102  1.18   thorpej 			tp->t_cflag |= CLOCAL;
   1103  1.18   thorpej 
   1104  1.18   thorpej 		break;
   1105  1.18   thorpej 	}
   1106   1.1       cgd 
   1107   1.1       cgd 	default:
   1108  1.51    atatat 		return (EPASSTHROUGH);
   1109   1.1       cgd 	}
   1110   1.1       cgd 	return (0);
   1111   1.1       cgd }
   1112   1.1       cgd 
   1113  1.17   mycroft int
   1114   1.1       cgd dcmparam(tp, t)
   1115  1.36    scottr 	struct tty *tp;
   1116  1.36    scottr 	struct termios *t;
   1117   1.1       cgd {
   1118  1.20   thorpej 	struct dcm_softc *sc;
   1119  1.20   thorpej 	struct dcmdevice *dcm;
   1120  1.20   thorpej 	int unit, board, port, mode, cflag = t->c_cflag;
   1121   1.1       cgd 	int ospeed = ttspeedtab(t->c_ospeed, dcmspeedtab);
   1122   1.1       cgd 
   1123  1.20   thorpej 	unit = DCMUNIT(tp->t_dev);
   1124  1.20   thorpej 	board = DCMBOARD(unit);
   1125  1.20   thorpej 	port = DCMPORT(unit);
   1126  1.20   thorpej 
   1127  1.34   thorpej 	sc = dcm_cd.cd_devs[board];
   1128  1.20   thorpej 	dcm = sc->sc_dcm;
   1129  1.20   thorpej 
   1130   1.1       cgd 	/* check requested parameters */
   1131   1.1       cgd         if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
   1132   1.1       cgd                 return (EINVAL);
   1133   1.1       cgd         /* and copy to tty */
   1134   1.1       cgd         tp->t_ispeed = t->c_ispeed;
   1135   1.1       cgd         tp->t_ospeed = t->c_ospeed;
   1136   1.1       cgd         tp->t_cflag = cflag;
   1137   1.1       cgd 	if (ospeed == 0) {
   1138  1.20   thorpej 		(void) dcmmctl(DCMUNIT(tp->t_dev), MO_OFF, DMSET);
   1139   1.1       cgd 		return (0);
   1140   1.1       cgd 	}
   1141   1.1       cgd 
   1142   1.1       cgd 	mode = 0;
   1143   1.1       cgd 	switch (cflag&CSIZE) {
   1144   1.1       cgd 	case CS5:
   1145   1.1       cgd 		mode = LC_5BITS; break;
   1146   1.1       cgd 	case CS6:
   1147   1.1       cgd 		mode = LC_6BITS; break;
   1148   1.1       cgd 	case CS7:
   1149   1.1       cgd 		mode = LC_7BITS; break;
   1150   1.1       cgd 	case CS8:
   1151   1.1       cgd 		mode = LC_8BITS; break;
   1152   1.1       cgd 	}
   1153   1.1       cgd 	if (cflag&PARENB) {
   1154   1.1       cgd 		if (cflag&PARODD)
   1155   1.1       cgd 			mode |= LC_PODD;
   1156   1.1       cgd 		else
   1157   1.1       cgd 			mode |= LC_PEVEN;
   1158   1.1       cgd 	}
   1159   1.1       cgd 	if (cflag&CSTOPB)
   1160   1.1       cgd 		mode |= LC_2STOP;
   1161   1.1       cgd 	else
   1162   1.1       cgd 		mode |= LC_1STOP;
   1163   1.1       cgd #ifdef DEBUG
   1164   1.1       cgd 	if (dcmdebug & DDB_PARAM)
   1165  1.31  christos 		printf("%s port %d: dcmparam: cflag %x mode %x speed %d uperch %d\n",
   1166  1.34   thorpej 		       sc->sc_dev.dv_xname, port, cflag, mode, tp->t_ospeed,
   1167   1.1       cgd 		       DCM_USPERCH(tp->t_ospeed));
   1168   1.1       cgd #endif
   1169   1.1       cgd 
   1170   1.1       cgd 	/*
   1171   1.1       cgd 	 * Wait for transmitter buffer to empty.
   1172   1.1       cgd 	 */
   1173   1.1       cgd 	while (dcm->dcm_thead[port].ptr != dcm->dcm_ttail[port].ptr)
   1174   1.1       cgd 		DELAY(DCM_USPERCH(tp->t_ospeed));
   1175   1.1       cgd 	/*
   1176   1.1       cgd 	 * Make changes known to hardware.
   1177   1.1       cgd 	 */
   1178   1.1       cgd 	dcm->dcm_data[port].dcm_baud = ospeed;
   1179   1.1       cgd 	dcm->dcm_data[port].dcm_conf = mode;
   1180   1.1       cgd 	SEM_LOCK(dcm);
   1181   1.1       cgd 	dcm->dcm_cmdtab[port].dcm_data |= CT_CON;
   1182   1.1       cgd 	dcm->dcm_cr |= (1 << port);
   1183   1.1       cgd 	SEM_UNLOCK(dcm);
   1184   1.1       cgd 	/*
   1185   1.1       cgd 	 * Delay for config change to take place. Weighted by baud.
   1186   1.1       cgd 	 * XXX why do we do this?
   1187   1.1       cgd 	 */
   1188   1.1       cgd 	DELAY(16 * DCM_USPERCH(tp->t_ospeed));
   1189   1.1       cgd 	return (0);
   1190   1.1       cgd }
   1191   1.1       cgd 
   1192   1.9   deraadt void
   1193   1.1       cgd dcmstart(tp)
   1194  1.36    scottr 	struct tty *tp;
   1195   1.1       cgd {
   1196  1.20   thorpej 	struct dcm_softc *sc;
   1197  1.20   thorpej 	struct dcmdevice *dcm;
   1198  1.20   thorpej 	struct dcmpreg *pp;
   1199  1.20   thorpej 	struct dcmtfifo *fifo;
   1200  1.20   thorpej 	char *bp;
   1201  1.20   thorpej 	u_int head, tail, next;
   1202  1.20   thorpej 	int unit, board, port, nch;
   1203   1.1       cgd 	char buf[16];
   1204   1.1       cgd 	int s;
   1205  1.14   mycroft #ifdef DCMSTATS
   1206  1.20   thorpej 	struct dcmstats *dsp = &sc->sc_stats;
   1207   1.1       cgd 	int tch = 0;
   1208   1.1       cgd #endif
   1209   1.1       cgd 
   1210  1.20   thorpej 	unit = DCMUNIT(tp->t_dev);
   1211  1.20   thorpej 	board = DCMBOARD(unit);
   1212  1.20   thorpej 	port = DCMPORT(unit);
   1213  1.20   thorpej 
   1214  1.34   thorpej 	sc = dcm_cd.cd_devs[board];
   1215  1.20   thorpej 	dcm = sc->sc_dcm;
   1216  1.20   thorpej 
   1217   1.1       cgd 	s = spltty();
   1218  1.14   mycroft #ifdef DCMSTATS
   1219   1.1       cgd 	dsp->xints++;
   1220   1.1       cgd #endif
   1221   1.1       cgd #ifdef DEBUG
   1222   1.1       cgd 	if (dcmdebug & DDB_OUTPUT)
   1223  1.31  christos 		printf("%s port %d: dcmstart: state %x flags %x outcc %d\n",
   1224  1.34   thorpej 		       sc->sc_dev.dv_xname, port, tp->t_state, tp->t_flags,
   1225   1.7   mycroft 		       tp->t_outq.c_cc);
   1226   1.1       cgd #endif
   1227   1.1       cgd 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
   1228   1.1       cgd 		goto out;
   1229   1.7   mycroft 	if (tp->t_outq.c_cc <= tp->t_lowat) {
   1230   1.1       cgd 		if (tp->t_state&TS_ASLEEP) {
   1231   1.1       cgd 			tp->t_state &= ~TS_ASLEEP;
   1232   1.7   mycroft 			wakeup((caddr_t)&tp->t_outq);
   1233   1.1       cgd 		}
   1234   1.2       cgd 		selwakeup(&tp->t_wsel);
   1235   1.1       cgd 	}
   1236   1.7   mycroft 	if (tp->t_outq.c_cc == 0) {
   1237  1.14   mycroft #ifdef DCMSTATS
   1238   1.1       cgd 		dsp->xempty++;
   1239   1.1       cgd #endif
   1240   1.1       cgd 		goto out;
   1241   1.1       cgd 	}
   1242   1.1       cgd 
   1243   1.1       cgd 	pp = dcm_preg(dcm, port);
   1244   1.1       cgd 	tail = pp->t_tail & TX_MASK;
   1245   1.1       cgd 	next = (tail + 1) & TX_MASK;
   1246   1.1       cgd 	head = pp->t_head & TX_MASK;
   1247   1.1       cgd 	if (head == next)
   1248   1.1       cgd 		goto out;
   1249   1.1       cgd 	fifo = &dcm->dcm_tfifos[3-port][tail];
   1250   1.1       cgd again:
   1251   1.1       cgd 	nch = q_to_b(&tp->t_outq, buf, (head - next) & TX_MASK);
   1252  1.14   mycroft #ifdef DCMSTATS
   1253   1.1       cgd 	tch += nch;
   1254   1.1       cgd #endif
   1255   1.1       cgd #ifdef DEBUG
   1256   1.1       cgd 	if (dcmdebug & DDB_OUTPUT)
   1257  1.31  christos 		printf("\thead %x tail %x nch %d\n", head, tail, nch);
   1258   1.1       cgd #endif
   1259   1.1       cgd 	/*
   1260   1.1       cgd 	 * Loop transmitting all the characters we can.
   1261   1.1       cgd 	 */
   1262   1.1       cgd 	for (bp = buf; --nch >= 0; bp++) {
   1263   1.1       cgd 		fifo->data_char = *bp;
   1264   1.1       cgd 		pp->t_tail = next;
   1265   1.1       cgd 		/*
   1266   1.1       cgd 		 * If this is the first character,
   1267   1.1       cgd 		 * get the hardware moving right now.
   1268   1.1       cgd 		 */
   1269   1.1       cgd 		if (bp == buf) {
   1270   1.1       cgd 			tp->t_state |= TS_BUSY;
   1271   1.1       cgd 			SEM_LOCK(dcm);
   1272   1.1       cgd 			dcm->dcm_cmdtab[port].dcm_data |= CT_TX;
   1273   1.1       cgd 			dcm->dcm_cr |= (1 << port);
   1274   1.1       cgd 			SEM_UNLOCK(dcm);
   1275   1.1       cgd 		}
   1276   1.1       cgd 		tail = next;
   1277   1.1       cgd 		fifo = tail ? fifo+1 : &dcm->dcm_tfifos[3-port][0];
   1278   1.1       cgd 		next = (next + 1) & TX_MASK;
   1279   1.1       cgd 	}
   1280   1.1       cgd 	/*
   1281   1.1       cgd 	 * Head changed while we were loading the buffer,
   1282   1.1       cgd 	 * go back and load some more if we can.
   1283   1.1       cgd 	 */
   1284   1.7   mycroft 	if (tp->t_outq.c_cc && head != (pp->t_head & TX_MASK)) {
   1285  1.14   mycroft #ifdef DCMSTATS
   1286   1.1       cgd 		dsp->xrestarts++;
   1287   1.1       cgd #endif
   1288   1.1       cgd 		head = pp->t_head & TX_MASK;
   1289   1.1       cgd 		goto again;
   1290   1.1       cgd 	}
   1291   1.1       cgd 
   1292   1.1       cgd 	/*
   1293   1.1       cgd 	 * Kick it one last time in case it finished while we were
   1294   1.1       cgd 	 * loading the last bunch.
   1295   1.1       cgd 	 */
   1296   1.1       cgd 	if (bp > &buf[1]) {
   1297   1.1       cgd 		tp->t_state |= TS_BUSY;
   1298   1.1       cgd 		SEM_LOCK(dcm);
   1299   1.1       cgd 		dcm->dcm_cmdtab[port].dcm_data |= CT_TX;
   1300   1.1       cgd 		dcm->dcm_cr |= (1 << port);
   1301   1.1       cgd 		SEM_UNLOCK(dcm);
   1302   1.1       cgd 	}
   1303   1.1       cgd #ifdef DEBUG
   1304   1.1       cgd 	if (dcmdebug & DDB_INTR)
   1305  1.37    scottr 		printf("%s port %d: dcmstart: head %x tail %x outqcc %d\n",
   1306  1.34   thorpej 		    sc->sc_dev.dv_xname, port, head, tail, tp->t_outq.c_cc);
   1307   1.1       cgd #endif
   1308   1.1       cgd out:
   1309  1.14   mycroft #ifdef DCMSTATS
   1310   1.1       cgd 	dsp->xchars += tch;
   1311   1.1       cgd 	if (tch <= DCMXBSIZE)
   1312   1.1       cgd 		dsp->xsilo[tch]++;
   1313   1.1       cgd 	else
   1314   1.1       cgd 		dsp->xsilo[DCMXBSIZE+1]++;
   1315   1.1       cgd #endif
   1316   1.1       cgd 	splx(s);
   1317   1.1       cgd }
   1318   1.1       cgd 
   1319   1.1       cgd /*
   1320   1.1       cgd  * Stop output on a line.
   1321   1.1       cgd  */
   1322  1.29   mycroft void
   1323   1.1       cgd dcmstop(tp, flag)
   1324  1.36    scottr 	struct tty *tp;
   1325  1.14   mycroft 	int flag;
   1326   1.1       cgd {
   1327   1.1       cgd 	int s;
   1328   1.1       cgd 
   1329   1.1       cgd 	s = spltty();
   1330   1.1       cgd 	if (tp->t_state & TS_BUSY) {
   1331   1.1       cgd 		/* XXX is there some way to safely stop transmission? */
   1332   1.1       cgd 		if ((tp->t_state&TS_TTSTOP) == 0)
   1333   1.1       cgd 			tp->t_state |= TS_FLUSH;
   1334   1.1       cgd 	}
   1335   1.1       cgd 	splx(s);
   1336   1.1       cgd }
   1337   1.1       cgd 
   1338   1.1       cgd /*
   1339   1.1       cgd  * Modem control
   1340   1.1       cgd  */
   1341  1.36    scottr int
   1342   1.1       cgd dcmmctl(dev, bits, how)
   1343   1.1       cgd 	dev_t dev;
   1344   1.1       cgd 	int bits, how;
   1345   1.1       cgd {
   1346  1.20   thorpej 	struct dcm_softc *sc;
   1347  1.20   thorpej 	struct dcmdevice *dcm;
   1348  1.20   thorpej 	int s, unit, brd, port, hit = 0;
   1349  1.20   thorpej 
   1350  1.20   thorpej 	unit = DCMUNIT(dev);
   1351  1.20   thorpej 	brd = DCMBOARD(unit);
   1352  1.20   thorpej 	port = DCMPORT(unit);
   1353  1.34   thorpej 
   1354  1.34   thorpej 	sc = dcm_cd.cd_devs[brd];
   1355  1.20   thorpej 	dcm = sc->sc_dcm;
   1356   1.1       cgd 
   1357   1.1       cgd #ifdef DEBUG
   1358   1.1       cgd 	if (dcmdebug & DDB_MODEM)
   1359  1.31  christos 		printf("%s port %d: dcmmctl: bits 0x%x how %x\n",
   1360  1.34   thorpej 		       sc->sc_dev.dv_xname, port, bits, how);
   1361   1.1       cgd #endif
   1362   1.1       cgd 
   1363   1.1       cgd 	s = spltty();
   1364  1.20   thorpej 
   1365   1.1       cgd 	switch (how) {
   1366   1.1       cgd 	case DMSET:
   1367  1.20   thorpej 		sc->sc_modem[port]->mdmout = bits;
   1368   1.1       cgd 		hit++;
   1369   1.1       cgd 		break;
   1370   1.1       cgd 
   1371   1.1       cgd 	case DMBIS:
   1372  1.20   thorpej 		sc->sc_modem[port]->mdmout |= bits;
   1373   1.1       cgd 		hit++;
   1374   1.1       cgd 		break;
   1375   1.1       cgd 
   1376   1.1       cgd 	case DMBIC:
   1377  1.20   thorpej 		sc->sc_modem[port]->mdmout &= ~bits;
   1378   1.1       cgd 		hit++;
   1379   1.1       cgd 		break;
   1380   1.1       cgd 
   1381   1.1       cgd 	case DMGET:
   1382  1.20   thorpej 		bits = sc->sc_modem[port]->mdmin;
   1383  1.20   thorpej 		if (sc->sc_flags & DCM_STDDCE)
   1384   1.1       cgd 			bits = hp2dce_in(bits);
   1385   1.1       cgd 		break;
   1386   1.1       cgd 	}
   1387   1.1       cgd 	if (hit) {
   1388   1.1       cgd 		SEM_LOCK(dcm);
   1389   1.1       cgd 		dcm->dcm_modemchng |= 1<<(unit & 3);
   1390   1.1       cgd 		dcm->dcm_cr |= CR_MODM;
   1391   1.1       cgd 		SEM_UNLOCK(dcm);
   1392   1.1       cgd 		DELAY(10); /* delay until done */
   1393  1.49  gmcgarry 		splx(s);
   1394   1.1       cgd 	}
   1395   1.1       cgd 	return (bits);
   1396   1.1       cgd }
   1397   1.1       cgd 
   1398   1.1       cgd /*
   1399   1.1       cgd  * Set board to either interrupt per-character or at a fixed interval.
   1400   1.1       cgd  */
   1401  1.36    scottr void
   1402   1.1       cgd dcmsetischeme(brd, flags)
   1403   1.1       cgd 	int brd, flags;
   1404   1.1       cgd {
   1405  1.34   thorpej 	struct dcm_softc *sc = dcm_cd.cd_devs[brd];
   1406  1.20   thorpej 	struct dcmdevice *dcm = sc->sc_dcm;
   1407  1.20   thorpej 	struct dcmischeme *dis = &sc->sc_scheme;
   1408  1.20   thorpej 	int i;
   1409   1.1       cgd 	u_char mask;
   1410   1.1       cgd 	int perchar = flags & DIS_PERCHAR;
   1411   1.1       cgd 
   1412   1.1       cgd #ifdef DEBUG
   1413   1.1       cgd 	if (dcmdebug & DDB_INTSCHM)
   1414  1.31  christos 		printf("%s: dcmsetischeme(%d): cur %d, ints %d, chars %d\n",
   1415  1.34   thorpej 		       sc->sc_dev.dv_xname, perchar, dis->dis_perchar,
   1416   1.1       cgd 		       dis->dis_intr, dis->dis_char);
   1417   1.1       cgd 	if ((flags & DIS_RESET) == 0 && perchar == dis->dis_perchar) {
   1418  1.31  christos 		printf("%s: dcmsetischeme: redundent request %d\n",
   1419  1.34   thorpej 		       sc->sc_dev.dv_xname, perchar);
   1420   1.1       cgd 		return;
   1421   1.1       cgd 	}
   1422   1.1       cgd #endif
   1423   1.1       cgd 	/*
   1424   1.1       cgd 	 * If perchar is non-zero, we enable interrupts on all characters
   1425   1.1       cgd 	 * otherwise we disable perchar interrupts and use periodic
   1426   1.1       cgd 	 * polling interrupts.
   1427   1.1       cgd 	 */
   1428   1.1       cgd 	dis->dis_perchar = perchar;
   1429   1.1       cgd 	mask = perchar ? 0xf : 0x0;
   1430   1.1       cgd 	for (i = 0; i < 256; i++)
   1431   1.1       cgd 		dcm->dcm_bmap[i].data_data = mask;
   1432   1.1       cgd 	/*
   1433   1.1       cgd 	 * Don't slow down tandem mode, interrupt on flow control
   1434   1.1       cgd 	 * chars for any port on the board.
   1435   1.1       cgd 	 */
   1436   1.1       cgd 	if (!perchar) {
   1437  1.36    scottr 		struct tty *tp;
   1438   1.1       cgd 		int c;
   1439   1.1       cgd 
   1440  1.20   thorpej 		for (i = 0; i < NDCMPORT; i++) {
   1441  1.20   thorpej 			tp = sc->sc_tty[i];
   1442  1.20   thorpej 
   1443   1.1       cgd 			if ((c = tp->t_cc[VSTART]) != _POSIX_VDISABLE)
   1444   1.1       cgd 				dcm->dcm_bmap[c].data_data |= (1 << i);
   1445   1.1       cgd 			if ((c = tp->t_cc[VSTOP]) != _POSIX_VDISABLE)
   1446   1.1       cgd 				dcm->dcm_bmap[c].data_data |= (1 << i);
   1447   1.1       cgd 		}
   1448   1.1       cgd 	}
   1449   1.1       cgd 	/*
   1450   1.1       cgd 	 * Board starts with timer disabled so if first call is to
   1451   1.1       cgd 	 * set perchar mode then we don't want to toggle the timer.
   1452   1.1       cgd 	 */
   1453   1.1       cgd 	if (flags == (DIS_RESET|DIS_PERCHAR))
   1454   1.1       cgd 		return;
   1455   1.1       cgd 	/*
   1456   1.1       cgd 	 * Toggle card 16.7ms interrupts (we first make sure that card
   1457   1.1       cgd 	 * has cleared the bit so it will see the toggle).
   1458   1.1       cgd 	 */
   1459   1.1       cgd 	while (dcm->dcm_cr & CR_TIMER)
   1460   1.1       cgd 		;
   1461   1.1       cgd 	SEM_LOCK(dcm);
   1462   1.1       cgd 	dcm->dcm_cr |= CR_TIMER;
   1463   1.1       cgd 	SEM_UNLOCK(dcm);
   1464   1.1       cgd }
   1465   1.1       cgd 
   1466  1.22   thorpej void
   1467  1.22   thorpej dcminit(dcm, port, rate)
   1468  1.22   thorpej 	struct dcmdevice *dcm;
   1469  1.22   thorpej 	int port, rate;
   1470  1.22   thorpej {
   1471  1.22   thorpej 	int s, mode;
   1472  1.22   thorpej 
   1473  1.22   thorpej 	mode = LC_8BITS | LC_1STOP;
   1474  1.22   thorpej 
   1475  1.22   thorpej 	s = splhigh();
   1476  1.22   thorpej 
   1477  1.22   thorpej 	/*
   1478  1.22   thorpej 	 * Wait for transmitter buffer to empty.
   1479  1.22   thorpej 	 */
   1480  1.22   thorpej 	while (dcm->dcm_thead[port].ptr != dcm->dcm_ttail[port].ptr)
   1481  1.22   thorpej 		DELAY(DCM_USPERCH(rate));
   1482  1.22   thorpej 
   1483  1.22   thorpej 	/*
   1484  1.22   thorpej 	 * Make changes known to hardware.
   1485  1.22   thorpej 	 */
   1486  1.22   thorpej 	dcm->dcm_data[port].dcm_baud = ttspeedtab(rate, dcmspeedtab);
   1487  1.22   thorpej 	dcm->dcm_data[port].dcm_conf = mode;
   1488  1.22   thorpej 	SEM_LOCK(dcm);
   1489  1.22   thorpej 	dcm->dcm_cmdtab[port].dcm_data |= CT_CON;
   1490  1.22   thorpej 	dcm->dcm_cr |= (1 << port);
   1491  1.22   thorpej 	SEM_UNLOCK(dcm);
   1492  1.22   thorpej 
   1493  1.22   thorpej 	/*
   1494  1.22   thorpej 	 * Delay for config change to take place. Weighted by baud.
   1495  1.22   thorpej 	 * XXX why do we do this?
   1496  1.22   thorpej 	 */
   1497  1.22   thorpej 	DELAY(16 * DCM_USPERCH(rate));
   1498  1.22   thorpej 	splx(s);
   1499  1.22   thorpej }
   1500  1.22   thorpej 
   1501   1.1       cgd /*
   1502  1.34   thorpej  * Empirically derived self-test magic
   1503  1.34   thorpej  */
   1504  1.34   thorpej int
   1505  1.34   thorpej dcmselftest(sc)
   1506  1.34   thorpej 	struct dcm_softc *sc;
   1507  1.34   thorpej {
   1508  1.34   thorpej 	struct dcmdevice *dcm = sc->sc_dcm;
   1509  1.36    scottr 	int timo = 0;
   1510  1.36    scottr 	int s, rv;
   1511  1.34   thorpej 
   1512  1.35   thorpej 	rv = 1;
   1513  1.35   thorpej 
   1514  1.35   thorpej 	s = splhigh();
   1515  1.34   thorpej 	dcm->dcm_rsid = DCMRS;
   1516  1.34   thorpej 	DELAY(50000);	/* 5000 is not long enough */
   1517  1.34   thorpej 	dcm->dcm_rsid = 0;
   1518  1.34   thorpej 	dcm->dcm_ic = IC_IE;
   1519  1.34   thorpej 	dcm->dcm_cr = CR_SELFT;
   1520  1.35   thorpej 	while ((dcm->dcm_ic & IC_IR) == 0) {
   1521  1.34   thorpej 		if (++timo == 20000)
   1522  1.35   thorpej 			goto out;
   1523  1.35   thorpej 		DELAY(1);
   1524  1.35   thorpej 	}
   1525  1.34   thorpej 	DELAY(50000);	/* XXX why is this needed ???? */
   1526  1.35   thorpej 	while ((dcm->dcm_iir & IIR_SELFT) == 0) {
   1527  1.34   thorpej 		if (++timo == 400000)
   1528  1.35   thorpej 			goto out;
   1529  1.35   thorpej 		DELAY(1);
   1530  1.35   thorpej 	}
   1531  1.34   thorpej 	DELAY(50000);	/* XXX why is this needed ???? */
   1532  1.34   thorpej 	if (dcm->dcm_stcon != ST_OK) {
   1533  1.34   thorpej #if 0
   1534  1.34   thorpej 		if (hd->hp_args->hw_sc != conscode)
   1535  1.34   thorpej 			printf("dcm%d: self test failed: %x\n",
   1536  1.34   thorpej 			       brd, dcm->dcm_stcon);
   1537  1.34   thorpej #endif
   1538  1.35   thorpej 		goto out;
   1539  1.34   thorpej 	}
   1540  1.34   thorpej 	dcm->dcm_ic = IC_ID;
   1541  1.35   thorpej 	rv = 0;
   1542  1.35   thorpej 
   1543  1.35   thorpej  out:
   1544  1.34   thorpej 	splx(s);
   1545  1.35   thorpej 	return (rv);
   1546  1.34   thorpej }
   1547  1.34   thorpej 
   1548  1.34   thorpej /*
   1549   1.1       cgd  * Following are all routines needed for DCM to act as console
   1550   1.1       cgd  */
   1551   1.1       cgd 
   1552  1.24   thorpej int
   1553  1.48  gmcgarry dcmcnattach(bus_space_tag_t bst, bus_addr_t addr, int scode)
   1554   1.1       cgd {
   1555  1.48  gmcgarry         bus_space_handle_t bsh;
   1556  1.48  gmcgarry         caddr_t va;
   1557  1.48  gmcgarry         struct dcmdevice *dcm;
   1558  1.52   gehenna 	int maj;
   1559  1.48  gmcgarry 
   1560  1.48  gmcgarry         if (bus_space_map(bst, addr, DIOCSIZE, 0, &bsh))
   1561  1.48  gmcgarry                 return (1);
   1562  1.48  gmcgarry 
   1563  1.48  gmcgarry         va = bus_space_vaddr(bst, bsh);
   1564  1.48  gmcgarry 	dcm = (struct dcmdevice *)va;
   1565   1.1       cgd 
   1566  1.20   thorpej 	switch (dcm->dcm_rsid) {
   1567  1.48  gmcgarry #ifdef CONSCODE
   1568   1.1       cgd 	case DCMID:
   1569  1.48  gmcgarry #endif
   1570   1.1       cgd 	case DCMID|DCMCON:
   1571   1.1       cgd 		break;
   1572   1.1       cgd 	default:
   1573  1.48  gmcgarry 		goto error;
   1574  1.22   thorpej 	}
   1575  1.24   thorpej 
   1576  1.48  gmcgarry 	dcminit(dcm, DCMCONSPORT, dcmdefaultrate);
   1577  1.48  gmcgarry         dcmconsinit = 1;
   1578  1.48  gmcgarry 	dcmconscode = scode;
   1579  1.48  gmcgarry         dcm_cn = dcm;
   1580  1.48  gmcgarry 
   1581  1.48  gmcgarry         /* locate the major number */
   1582  1.52   gehenna         maj = cdevsw_lookup_major(&dcm_cdevsw);
   1583  1.48  gmcgarry 
   1584  1.48  gmcgarry         /* initialize required fields */
   1585  1.48  gmcgarry         cn_tab = &dcm_cons;
   1586  1.52   gehenna         cn_tab->cn_dev = makedev(maj, 0);
   1587  1.22   thorpej 
   1588   1.1       cgd #ifdef KGDB_CHEAT
   1589  1.24   thorpej 	/* XXX this needs to be fixed. */
   1590   1.1       cgd 	/*
   1591   1.1       cgd 	 * This doesn't currently work, at least not with ite consoles;
   1592   1.1       cgd 	 * the console hasn't been initialized yet.
   1593   1.1       cgd 	 */
   1594  1.52   gehenna 	if (major(kgdb_dev) == maj &&
   1595  1.20   thorpej 	    DCMBOARD(DCMUNIT(kgdb_dev)) == DCMBOARD(unit)) {
   1596  1.22   thorpej 		dcminit(dcm_cn, DCMPORT(DCMUNIT(kgdb_dev)), kgdb_rate);
   1597   1.1       cgd 		if (kgdb_debug_init) {
   1598   1.1       cgd 			/*
   1599   1.1       cgd 			 * We assume that console is ready for us...
   1600   1.1       cgd 			 * this assumes that a dca or ite console
   1601   1.1       cgd 			 * has been selected already and will init
   1602   1.1       cgd 			 * on the first putc.
   1603   1.1       cgd 			 */
   1604  1.31  christos 			printf("dcm%d: ", DCMUNIT(kgdb_dev));
   1605   1.1       cgd 			kgdb_connect(1);
   1606   1.1       cgd 		}
   1607   1.1       cgd 	}
   1608   1.1       cgd #endif
   1609   1.1       cgd 
   1610  1.20   thorpej 
   1611  1.48  gmcgarry         return (0);
   1612  1.48  gmcgarry 
   1613  1.48  gmcgarry error:
   1614  1.48  gmcgarry         bus_space_unmap(bst, bsh, DIOCSIZE);
   1615  1.48  gmcgarry         return (1);
   1616   1.1       cgd }
   1617   1.1       cgd 
   1618  1.24   thorpej /* ARGSUSED */
   1619  1.17   mycroft int
   1620   1.1       cgd dcmcngetc(dev)
   1621   1.1       cgd 	dev_t dev;
   1622   1.1       cgd {
   1623  1.20   thorpej 	struct dcmrfifo *fifo;
   1624  1.20   thorpej 	struct dcmpreg *pp;
   1625  1.20   thorpej 	u_int head;
   1626  1.24   thorpej 	int s, c, stat;
   1627  1.22   thorpej 
   1628  1.24   thorpej 	pp = dcm_preg(dcm_cn, DCMCONSPORT);
   1629  1.20   thorpej 
   1630   1.1       cgd 	s = splhigh();
   1631   1.1       cgd 	head = pp->r_head & RX_MASK;
   1632  1.24   thorpej 	fifo = &dcm_cn->dcm_rfifos[3-DCMCONSPORT][head>>1];
   1633   1.1       cgd 	while (head == (pp->r_tail & RX_MASK))
   1634   1.1       cgd 		;
   1635   1.1       cgd 	/*
   1636   1.1       cgd 	 * If board interrupts are enabled, just let our received char
   1637   1.1       cgd 	 * interrupt through in case some other port on the board was
   1638   1.1       cgd 	 * busy.  Otherwise we must clear the interrupt.
   1639   1.1       cgd 	 */
   1640  1.22   thorpej 	SEM_LOCK(dcm_cn);
   1641  1.22   thorpej 	if ((dcm_cn->dcm_ic & IC_IE) == 0)
   1642  1.22   thorpej 		stat = dcm_cn->dcm_iir;
   1643  1.22   thorpej 	SEM_UNLOCK(dcm_cn);
   1644   1.1       cgd 	c = fifo->data_char;
   1645   1.1       cgd 	stat = fifo->data_stat;
   1646   1.1       cgd 	pp->r_head = (head + 2) & RX_MASK;
   1647   1.1       cgd 	splx(s);
   1648   1.1       cgd 	return (c);
   1649   1.1       cgd }
   1650   1.1       cgd 
   1651   1.1       cgd /*
   1652   1.1       cgd  * Console kernel output character routine.
   1653   1.1       cgd  */
   1654  1.24   thorpej /* ARGSUSED */
   1655  1.16   mycroft void
   1656   1.1       cgd dcmcnputc(dev, c)
   1657   1.1       cgd 	dev_t dev;
   1658   1.1       cgd 	int c;
   1659   1.1       cgd {
   1660  1.20   thorpej 	struct dcmpreg *pp;
   1661   1.1       cgd 	unsigned tail;
   1662  1.36    scottr 	int s, stat;
   1663  1.22   thorpej 
   1664  1.24   thorpej 	pp = dcm_preg(dcm_cn, DCMCONSPORT);
   1665  1.20   thorpej 
   1666   1.1       cgd 	s = splhigh();
   1667   1.1       cgd #ifdef KGDB
   1668   1.1       cgd 	if (dev != kgdb_dev)
   1669   1.1       cgd #endif
   1670   1.1       cgd 	if (dcmconsinit == 0) {
   1671  1.24   thorpej 		dcminit(dcm_cn, DCMCONSPORT, dcmdefaultrate);
   1672   1.1       cgd 		dcmconsinit = 1;
   1673   1.1       cgd 	}
   1674   1.1       cgd 	tail = pp->t_tail & TX_MASK;
   1675   1.1       cgd 	while (tail != (pp->t_head & TX_MASK))
   1676   1.1       cgd 		;
   1677  1.24   thorpej 	dcm_cn->dcm_tfifos[3-DCMCONSPORT][tail].data_char = c;
   1678   1.1       cgd 	pp->t_tail = tail = (tail + 1) & TX_MASK;
   1679  1.22   thorpej 	SEM_LOCK(dcm_cn);
   1680  1.24   thorpej 	dcm_cn->dcm_cmdtab[DCMCONSPORT].dcm_data |= CT_TX;
   1681  1.24   thorpej 	dcm_cn->dcm_cr |= (1 << DCMCONSPORT);
   1682  1.22   thorpej 	SEM_UNLOCK(dcm_cn);
   1683   1.1       cgd 	while (tail != (pp->t_head & TX_MASK))
   1684   1.1       cgd 		;
   1685   1.1       cgd 	/*
   1686   1.1       cgd 	 * If board interrupts are enabled, just let our completion
   1687   1.1       cgd 	 * interrupt through in case some other port on the board
   1688   1.1       cgd 	 * was busy.  Otherwise we must clear the interrupt.
   1689   1.1       cgd 	 */
   1690  1.22   thorpej 	if ((dcm_cn->dcm_ic & IC_IE) == 0) {
   1691  1.22   thorpej 		SEM_LOCK(dcm_cn);
   1692  1.22   thorpej 		stat = dcm_cn->dcm_iir;
   1693  1.22   thorpej 		SEM_UNLOCK(dcm_cn);
   1694   1.1       cgd 	}
   1695   1.1       cgd 	splx(s);
   1696   1.1       cgd }
   1697