Home | History | Annotate | Line # | Download | only in dev
mfc.c revision 1.7
      1 /*	$NetBSD: mfc.c,v 1.7 1995/09/29 13:51:57 chopps Exp $ */
      2 
      3 /*
      4  * Copyright (c) 1994 Michael L. Hitch
      5  * Copyright (c) 1982, 1990 The Regents of the University of California.
      6  * All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  * 2. Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in the
     15  *    documentation and/or other materials provided with the distribution.
     16  * 3. All advertising materials mentioning features or use of this software
     17  *    must display the following acknowledgement:
     18  *	This product includes software developed by the University of
     19  *	California, Berkeley and its contributors.
     20  * 4. Neither the name of the University nor the names of its contributors
     21  *    may be used to endorse or promote products derived from this software
     22  *    without specific prior written permission.
     23  *
     24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     34  * SUCH DAMAGE.
     35  */
     36 
     37 #include <sys/param.h>
     38 #include <sys/systm.h>
     39 #include <sys/kernel.h>
     40 #include <sys/device.h>
     41 #include <sys/tty.h>
     42 #include <sys/proc.h>
     43 #include <sys/conf.h>
     44 #include <sys/file.h>
     45 #include <sys/malloc.h>
     46 #include <sys/uio.h>
     47 #include <sys/kernel.h>
     48 #include <sys/syslog.h>
     49 #include <sys/queue.h>
     50 #include <machine/cpu.h>
     51 #include <amiga/amiga/device.h>
     52 #include <amiga/amiga/isr.h>
     53 #include <amiga/amiga/custom.h>
     54 #include <amiga/amiga/cia.h>
     55 #include <amiga/amiga/cc.h>
     56 #include <amiga/dev/zbusvar.h>
     57 
     58 #include <dev/cons.h>
     59 
     60 #include "mfcs.h"
     61 
     62 #ifndef SEROBUF_SIZE
     63 #define SEROBUF_SIZE	128
     64 #endif
     65 #ifndef SERIBUF_SIZE
     66 #define SERIBUF_SIZE	1024
     67 #endif
     68 
     69 #define splser()	spl6()
     70 
     71 /*
     72  * 68581 DUART registers
     73  */
     74 struct mfc_regs {
     75 	volatile u_char du_mr1a;
     76 #define	du_mr2a		du_mr1a
     77 	u_char pad0;
     78 	volatile u_char du_csra;
     79 #define	du_sra		du_csra
     80 	u_char pad2;
     81 	volatile u_char du_cra;
     82 	u_char pad4;
     83 	volatile u_char du_tba;
     84 #define	du_rba		du_tba
     85 	u_char pad6;
     86 	volatile u_char du_acr;
     87 #define	du_ipcr		du_acr
     88 	u_char pad8;
     89 	volatile u_char du_imr;
     90 #define	du_isr		du_imr
     91 	u_char pad10;
     92 	volatile u_char du_ctur;
     93 #define	du_cmsb		du_ctur
     94 	u_char pad12;
     95 	volatile u_char du_ctlr;
     96 #define	du_clsb		du_ctlr
     97 	u_char pad14;
     98 	volatile u_char du_mr1b;
     99 #define	du_mr2b		du_mr1b
    100 	u_char pad16;
    101 	volatile u_char du_csrb;
    102 #define	du_srb		du_csrb
    103 	u_char pad18;
    104 	volatile u_char du_crb;
    105 	u_char pad20;
    106 	volatile u_char du_tbb;
    107 #define	du_rbb		du_tbb
    108 	u_char pad22;
    109 	volatile u_char du_ivr;
    110 	u_char pad24;
    111 	volatile u_char du_opcr;
    112 #define	du_ip		du_opcr
    113 	u_char pad26;
    114 	volatile u_char du_btst;
    115 #define	du_strc		du_btst
    116 	u_char pad28;
    117 	volatile u_char du_btrst;
    118 #define	du_stpc		du_btrst
    119 	u_char pad30;
    120 };
    121 
    122 /*
    123  * 68681 DUART serial port registers
    124  */
    125 struct duart_regs {
    126 	volatile u_char ch_mr1;
    127 #define	ch_mr2		ch_mr1
    128 	u_char pad0;
    129 	volatile u_char	ch_csr;
    130 #define	ch_sr		ch_csr
    131 	u_char pad1;
    132 	volatile u_char	ch_cr;
    133 	u_char pad2;
    134 	volatile u_char	ch_tb;
    135 #define	ch_rb		ch_tb
    136 	u_char pad3;
    137 };
    138 
    139 struct mfc_softc {
    140 	struct	device sc_dev;
    141 	struct	isr sc_isr;
    142 	struct	mfc_regs *sc_regs;
    143 	u_long	clk_frq;
    144 	u_short	ct_val;
    145 	u_char	ct_usecnt;
    146 	u_char	imask;
    147 	u_char	mfc_iii;
    148 	u_char	last_ip;
    149 };
    150 
    151 #if NMFCS > 0
    152 struct mfcs_softc {
    153 	struct	device sc_dev;
    154 	struct	tty *sc_tty;
    155 	struct	duart_regs *sc_duart;
    156 	struct	mfc_regs *sc_regs;
    157 	struct	mfc_softc *sc_mfc;
    158 	long	flags;			/* XXX */
    159 #define CT_USED	1			/* CT in use */
    160 	u_short	*rptr, *wptr, incnt, ovfl;
    161 	u_short	inbuf[SERIBUF_SIZE];
    162 	char	*ptr, *end;
    163 	char	outbuf[SEROBUF_SIZE];
    164 };
    165 #endif
    166 
    167 #if NMFCP > 0
    168 struct mfcp_softc {
    169 };
    170 #endif
    171 
    172 struct mfc_args {
    173 	struct zbus_args zargs;
    174 	char	*subdev;
    175 	char	unit;
    176 };
    177 
    178 int mfcprint __P((void *auxp, char *));
    179 void mfcattach __P((struct device *, struct device *, void *));
    180 int mfcmatch __P((struct device *, struct cfdata *, void *));
    181 #if NMFCS > 0
    182 void mfcsattach __P((struct device *, struct device *, void *));
    183 int mfcsmatch __P((struct device *, struct cfdata *, void *));
    184 #endif
    185 #if NMFCP > 0
    186 void mfcpattach __P((struct device *, struct device *, void *));
    187 int mfcpmatch __P((struct device *, struct cfdata *, void *));
    188 #endif
    189 int mfcintr __P((struct mfc_softc *));
    190 void mfcsmint __P((register int unit));
    191 
    192 struct cfdriver mfccd = {
    193 	NULL, "mfc", (cfmatch_t) mfcmatch, mfcattach,
    194 	DV_DULL, sizeof(struct mfc_softc), NULL, 0 };
    195 
    196 #if NMFCS > 0
    197 struct cfdriver mfcscd = {
    198 	NULL, "mfcs", (cfmatch_t) mfcsmatch, mfcsattach,
    199 	DV_TTY, sizeof(struct mfcs_softc), NULL, 0 };
    200 #endif
    201 
    202 #if NMFCP > 0
    203 struct cfdriver mfcpcd = {
    204 	NULL, "mfcp", (cfmatch_t) mfcpmatch, mfcpattach,
    205 	DV_DULL, sizeof(struct mfcp_softc), NULL, 0 };
    206 #endif
    207 
    208 int	mfcsstart(), mfcsparam(), mfcshwiflow();
    209 int	mfcs_active;
    210 int	mfcsdefaultrate = 38400 /*TTYDEF_SPEED*/;
    211 int	mfcsswflags[NMFCS];
    212 #define SWFLAGS(dev) (mfcsswflags[dev & 31] | (((dev) & 0x80) == 0 ? TIOCFLAG_SOFTCAR : 0))
    213 
    214 struct	vbl_node mfcs_vbl_node[NMFCS];
    215 
    216 #ifdef notyet
    217 /*
    218  * MultiFaceCard III, II+ (not supported yet), and
    219  * SerialMaster 500+ (not supported yet)
    220  * baud rate tables for BRG set 1 [not used yet]
    221  */
    222 
    223 struct speedtab mfcs3speedtab1[] = {
    224 	0,	0,
    225 	100,	0x00,
    226 	220,	0x11,
    227 	600,	0x44,
    228 	1200,	0x55,
    229 	2400,	0x66,
    230 	4800,	0x88,
    231 	9600,	0x99,
    232 	19200,	0xbb,
    233 	115200,	0xcc,
    234 	-1,	-1
    235 };
    236 
    237 /*
    238  * MultiFaceCard II, I, and SerialMaster 500
    239  * baud rate tables for BRG set 1 [not used yet]
    240  */
    241 
    242 struct speedtab mfcs2speedtab1[] = {
    243 	0,	0,
    244 	50,	0x00,
    245 	110,	0x11,
    246 	300,	0x44,
    247 	600,	0x55,
    248 	1200,	0x66,
    249 	2400,	0x88,
    250  	4800,	0x99,
    251 	9600,	0xbb,
    252 	38400,	0xcc,
    253 	-1,	-1
    254 };
    255 #endif
    256 
    257 /*
    258  * MultiFaceCard III, II+ (not supported yet), and
    259  * SerialMaster 500+ (not supported yet)
    260  * baud rate tables for BRG set 2
    261  */
    262 
    263 struct speedtab mfcs3speedtab2[] = {
    264 	0,	0,
    265 	150,	0x00,
    266 	200,	0x11,
    267 	300,	0x33,
    268 	600,	0x44,
    269 	1200,	0x55,
    270 	2400,	0x66,
    271 	4800,	0x88,
    272 	9600,	0x99,
    273 	19200,	0xbb,
    274 	38400,	0xcc,
    275 	-1,	-1
    276 };
    277 
    278 /*
    279  * MultiFaceCard II, I, and SerialMaster 500
    280  * baud rate tables for BRG set 2
    281  */
    282 
    283 struct speedtab mfcs2speedtab2[] = {
    284 	0,	0,
    285 	75,	0x00,
    286 	100,	0x11,
    287 	150,	0x33,
    288 	300,	0x44,
    289 	600,	0x55,
    290 	1200,	0x66,
    291 	2400,	0x88,
    292  	4800,	0x99,
    293 	9600,	0xbb,
    294 	19200,	0xcc,
    295 	-1,	-1
    296 };
    297 
    298 /*
    299  * if we are an bsc/Alf Data MultFaceCard (I, II, and III)
    300  */
    301 int
    302 mfcmatch(pdp, cdp, auxp)
    303 	struct device *pdp;
    304 	struct cfdata *cdp;
    305 	void *auxp;
    306 {
    307 	struct zbus_args *zap;
    308 
    309 	zap = auxp;
    310 	if (zap->manid == 2092 &&
    311 	    (zap->prodid == 16 || zap->prodid == 17 || zap->prodid == 18))
    312 
    313 		return(1);
    314 	return(0);
    315 }
    316 
    317 void
    318 mfcattach(pdp, dp, auxp)
    319 	struct device *pdp, *dp;
    320 	void *auxp;
    321 {
    322 	struct mfc_softc *scc;
    323 	struct zbus_args *zap;
    324 	struct mfc_args ma;
    325 	int unit;
    326 	struct mfc_regs *rp;
    327 
    328 	zap = auxp;
    329 
    330 	printf ("\n");
    331 
    332 	scc = (struct mfc_softc *)dp;
    333 	unit = scc->sc_dev.dv_unit;
    334 	scc->sc_regs = rp = zap->va;
    335 	if (zap->prodid == 18)
    336 		scc->mfc_iii = 3;
    337 	scc->clk_frq = scc->mfc_iii ? 230400 : 115200;
    338 
    339 	rp->du_opcr = 0x00;		/* configure output port? */
    340 	rp->du_btrst = 0x0f;		/* clear modem lines */
    341 	rp->du_ivr = 0;			/* IVR */
    342 	rp->du_imr = 0;			/* IMR */
    343 	rp->du_acr = 0xe0;		/* baud rate generate set 2 */
    344 	rp->du_ctur = 0;
    345 	rp->du_ctlr = 4;
    346 	rp->du_csra = 0xcc;		/* clock select = 38400 */
    347 	rp->du_cra = 0x10;		/* reset mode register ptr */
    348 	rp->du_cra = 0x20;
    349 	rp->du_cra = 0x30;
    350 	rp->du_cra = 0x40;
    351 	rp->du_mr1a = 0x93;		/* MRA1 */
    352 	rp->du_mr2a = 0x17;		/* MRA2 */
    353 	rp->du_csrb = 0xcc;		/* clock select = 38400 */
    354 	rp->du_crb = 0x10;		/* reset mode register ptr */
    355 	rp->du_crb = 0x20;
    356 	rp->du_crb = 0x30;
    357 	rp->du_crb = 0x40;
    358 	rp->du_mr1b = 0x93;		/* MRB1 */
    359 	rp->du_mr2b = 0x17;		/* MRB2 */
    360 	rp->du_cra = 0x05;		/* enable A Rx & Tx */
    361 	rp->du_crb = 0x05;		/* enable B Rx & Tx */
    362 
    363 	scc->sc_isr.isr_intr = mfcintr;
    364 	scc->sc_isr.isr_arg = scc;
    365 	scc->sc_isr.isr_ipl = 6;
    366 	add_isr(&scc->sc_isr);
    367 
    368 	/* configure ports */
    369 	bcopy(zap, &ma.zargs, sizeof(struct zbus_args));
    370 	ma.subdev = "mfcs";
    371 	ma.unit = unit * 2;
    372 	config_found(dp, &ma, mfcprint);
    373 	ma.unit = unit * 2 + 1;
    374 	config_found(dp, &ma, mfcprint);
    375 	ma.subdev = "mfcp";
    376 	ma.unit = unit;
    377 	config_found(dp, &ma, mfcprint);
    378 }
    379 
    380 /*
    381  *
    382  */
    383 int
    384 mfcsmatch(pdp, cdp, auxp)
    385 	struct device *pdp;
    386 	struct cfdata *cdp;
    387 	void *auxp;
    388 {
    389 	struct mfc_args *ma;
    390 
    391 	ma = auxp;
    392 	if (strcmp(ma->subdev, "mfcs") == 0)
    393 		return (1);
    394 	return (0);
    395 }
    396 
    397 void
    398 mfcsattach(pdp, dp, auxp)
    399 	struct device *pdp, *dp;
    400 	void *auxp;
    401 {
    402 	int unit;
    403 	struct mfcs_softc *sc;
    404 	struct mfc_softc *scc;
    405 	struct mfc_args *ma;
    406 	struct mfc_regs *rp;
    407 
    408 	sc = (struct mfcs_softc *) dp;
    409 	scc = (struct mfc_softc *) pdp;
    410 	ma = auxp;
    411 
    412 	if (dp) {
    413 		printf (": input fifo %d output fifo %d\n", SERIBUF_SIZE,
    414 		    SEROBUF_SIZE);
    415 		alloc_sicallback();
    416 	}
    417 
    418 	unit = ma->unit;
    419 	mfcs_active |= 1 << unit;
    420 	sc->rptr = sc->wptr = sc->inbuf;
    421 	sc->sc_mfc = scc;
    422 	sc->sc_regs = rp = scc->sc_regs;
    423 	sc->sc_duart = (struct duart_regs *) ((unit & 1) ? &rp->du_mr1b :
    424 	    &rp->du_mr1a);
    425 	/*
    426 	 * should have only one vbl routine to handle all ports?
    427 	 */
    428 	mfcs_vbl_node[unit].function = (void (*) (void *)) mfcsmint;
    429 	mfcs_vbl_node[unit].data = (void *) unit;
    430 	add_vbl_function(&mfcs_vbl_node[unit], 1, (void *) unit);
    431 }
    432 
    433 /*
    434  * print diag if pnp is NULL else just extra
    435  */
    436 int
    437 mfcprint(auxp, pnp)
    438 	void *auxp;
    439 	char *pnp;
    440 {
    441 	if (pnp == NULL)
    442 		return(UNCONF);
    443 	return(QUIET);
    444 }
    445 
    446 int
    447 mfcsopen(dev, flag, mode, p)
    448 	dev_t dev;
    449 	int flag, mode;
    450 	struct proc *p;
    451 {
    452 	struct tty *tp;
    453 	struct mfcs_softc *sc;
    454 	int unit, error, s;
    455 
    456 	error = 0;
    457 	unit = dev & 0x1f;
    458 
    459 	if (unit >= mfcscd.cd_ndevs || (mfcs_active & (1 << unit)) == 0)
    460 		return (ENXIO);
    461 	sc = mfcscd.cd_devs[unit];
    462 
    463 	s = spltty();
    464 
    465 	if (sc->sc_tty)
    466 		tp = sc->sc_tty;
    467 	else
    468 		tp = sc->sc_tty = ttymalloc();
    469 
    470 	tp->t_oproc = (void (*) (struct tty *)) mfcsstart;
    471 	tp->t_param = mfcsparam;
    472 	tp->t_dev = dev;
    473 	tp->t_hwiflow = mfcshwiflow;
    474 
    475 	if ((tp->t_state & TS_ISOPEN) == 0) {
    476 		tp->t_state |= TS_WOPEN;
    477 		ttychars(tp);
    478 		if (tp->t_ispeed == 0) {
    479 			/*
    480 			 * only when cleared do we reset to defaults.
    481 			 */
    482 			tp->t_iflag = TTYDEF_IFLAG;
    483 			tp->t_oflag = TTYDEF_OFLAG;
    484 			tp->t_cflag = TTYDEF_CFLAG;
    485 			tp->t_lflag = TTYDEF_LFLAG;
    486 			tp->t_ispeed = tp->t_ospeed = mfcsdefaultrate;
    487 		}
    488 		/*
    489 		 * do these all the time
    490 		 */
    491 		if (mfcsswflags[unit] & TIOCFLAG_CLOCAL)
    492 			tp->t_cflag |= CLOCAL;
    493 		if (mfcsswflags[unit] & TIOCFLAG_CRTSCTS)
    494 			tp->t_cflag |= CRTSCTS;
    495 		if (mfcsswflags[unit] & TIOCFLAG_MDMBUF)
    496 			tp->t_cflag |= MDMBUF;
    497 		mfcsparam(tp, &tp->t_termios);
    498 		ttsetwater(tp);
    499 
    500 		(void)mfcsmctl(dev, TIOCM_DTR | TIOCM_RTS, DMSET);
    501 		if ((SWFLAGS(dev) & TIOCFLAG_SOFTCAR) ||
    502 		    (mfcsmctl(dev, 0, DMGET) & TIOCM_CD))
    503 			tp->t_state |= TS_CARR_ON;
    504 		else
    505 			tp->t_state &= ~TS_CARR_ON;
    506 	} else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) {
    507 		splx(s);
    508 		return(EBUSY);
    509 	}
    510 
    511 	/*
    512 	 * if NONBLOCK requested, ignore carrier
    513 	 */
    514 	if (flag & O_NONBLOCK)
    515 		goto done;
    516 
    517 	/*
    518 	 * block waiting for carrier
    519 	 */
    520 	while ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0) {
    521 		tp->t_state |= TS_WOPEN;
    522 		error = ttysleep(tp, (caddr_t)&tp->t_rawq,
    523 		    TTIPRI | PCATCH, ttopen, 0);
    524 		if (error) {
    525 			splx(s);
    526 			return(error);
    527 		}
    528 	}
    529 done:
    530 	/* This is a way to handle lost XON characters */
    531 	if ((flag & O_TRUNC) && (tp->t_state & TS_TTSTOP)) {
    532 		tp->t_state &= ~TS_TTSTOP;
    533 	        ttstart (tp);
    534 	}
    535 
    536 	splx(s);
    537 	/*
    538 	 * Reset the tty pointer, as there could have been a dialout
    539 	 * use of the tty with a dialin open waiting.
    540 	 */
    541 	tp->t_dev = dev;
    542 	return((*linesw[tp->t_line].l_open)(dev, tp));
    543 }
    544 
    545 /*ARGSUSED*/
    546 int
    547 mfcsclose(dev, flag, mode, p)
    548 	dev_t dev;
    549 	int flag, mode;
    550 	struct proc *p;
    551 {
    552 	struct tty *tp;
    553 	int unit;
    554 	struct mfcs_softc *sc = mfcscd.cd_devs[dev & 31];
    555 	struct mfc_softc *scc= sc->sc_mfc;
    556 
    557 	unit = dev & 31;
    558 
    559 	tp = sc->sc_tty;
    560 	(*linesw[tp->t_line].l_close)(tp, flag);
    561 	sc->sc_duart->ch_cr = 0x70;			/* stop break */
    562 
    563 	scc->imask &= ~(0x7 << ((unit & 1) * 4));
    564 	scc->sc_regs->du_imr = scc->imask;
    565 	if (sc->flags & CT_USED) {
    566 		--scc->ct_usecnt;
    567 		sc->flags &= ~CT_USED;
    568 	}
    569 
    570 	/*
    571 	 * If the device is closed, it's close, no matter whether we deal with
    572 	 * modem control signals nor not.
    573 	 */
    574 #if 0
    575 	if (tp->t_cflag & HUPCL || tp->t_state & TS_WOPEN ||
    576 	    (tp->t_state & TS_ISOPEN) == 0)
    577 #endif
    578 		(void) mfcsmctl(dev, 0, DMSET);
    579 	ttyclose(tp);
    580 #if not_yet
    581 	if (tp != &mfcs_cons) {
    582 		remove_vbl_function(&mfcs_vbl_node[unit]);
    583 		ttyfree(tp);
    584 		sc->sc_tty = (struct tty *) NULL;
    585 	}
    586 #endif
    587 	return (0);
    588 }
    589 
    590 int
    591 mfcsread(dev, uio, flag)
    592 	dev_t dev;
    593 	struct uio *uio;
    594 	int flag;
    595 {
    596 	struct mfcs_softc *sc = mfcscd.cd_devs[dev & 31];
    597 	struct tty *tp = sc->sc_tty;
    598 	if (tp == NULL)
    599 		return(ENXIO);
    600 	return((*linesw[tp->t_line].l_read)(tp, uio, flag));
    601 }
    602 
    603 int
    604 mfcswrite(dev, uio, flag)
    605 	dev_t dev;
    606 	struct uio *uio;
    607 	int flag;
    608 {
    609 	struct mfcs_softc *sc = mfcscd.cd_devs[dev & 31];
    610 	struct tty *tp = sc->sc_tty;
    611 
    612 	if (tp == NULL)
    613 		return(ENXIO);
    614 	return((*linesw[tp->t_line].l_write)(tp, uio, flag));
    615 }
    616 
    617 struct tty *
    618 mfcstty(dev)
    619 	dev_t dev;
    620 {
    621 	struct mfcs_softc *sc = mfcscd.cd_devs[dev & 31];
    622 
    623 	return (sc->sc_tty);
    624 }
    625 
    626 int
    627 mfcsioctl(dev, cmd, data, flag, p)
    628 	dev_t	dev;
    629 	caddr_t data;
    630 	struct proc *p;
    631 {
    632 	register struct tty *tp;
    633 	register int unit = dev & 31;
    634 	register int error;
    635 	struct mfcs_softc *sc = mfcscd.cd_devs[dev & 31];
    636 
    637 	tp = sc->sc_tty;
    638 	if (!tp)
    639 		return ENXIO;
    640 
    641 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
    642 	if (error >= 0)
    643 		return(error);
    644 
    645 	error = ttioctl(tp, cmd, data, flag, p);
    646 	if (error >= 0)
    647 		return(error);
    648 
    649 	switch (cmd) {
    650 	case TIOCSBRK:
    651 		sc->sc_duart->ch_cr = 0x60;		/* start break */
    652 		break;
    653 
    654 	case TIOCCBRK:
    655 		sc->sc_duart->ch_cr = 0x70;		/* stop break */
    656 		break;
    657 
    658 	case TIOCSDTR:
    659 		(void) mfcsmctl(dev, TIOCM_DTR | TIOCM_RTS, DMBIS);
    660 		break;
    661 
    662 	case TIOCCDTR:
    663 		(void) mfcsmctl(dev, TIOCM_DTR | TIOCM_RTS, DMBIC);
    664 		break;
    665 
    666 	case TIOCMSET:
    667 		(void) mfcsmctl(dev, *(int *) data, DMSET);
    668 		break;
    669 
    670 	case TIOCMBIS:
    671 		(void) mfcsmctl(dev, *(int *) data, DMBIS);
    672 		break;
    673 
    674 	case TIOCMBIC:
    675 		(void) mfcsmctl(dev, *(int *) data, DMBIC);
    676 		break;
    677 
    678 	case TIOCMGET:
    679 		*(int *)data = mfcsmctl(dev, 0, DMGET);
    680 		break;
    681 	case TIOCGFLAGS:
    682 		*(int *)data = SWFLAGS(dev);
    683 		break;
    684 	case TIOCSFLAGS:
    685 		error = suser(p->p_ucred, &p->p_acflag);
    686 		if (error != 0)
    687 			return(EPERM);
    688 
    689 		mfcsswflags[unit] = *(int *)data;
    690                 mfcsswflags[unit] &= /* only allow valid flags */
    691                   (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL | TIOCFLAG_CRTSCTS);
    692 		/* XXXX need to change duart parameters? */
    693 		break;
    694 	default:
    695 		return(ENOTTY);
    696 	}
    697 
    698 	return(0);
    699 }
    700 
    701 int
    702 mfcsparam(tp, t)
    703 	struct tty *tp;
    704 	struct termios *t;
    705 {
    706 	int cfcr, cflag, unit, ospeed;
    707 	struct mfcs_softc *sc = mfcscd.cd_devs[tp->t_dev & 31];
    708 	struct mfc_softc *scc= sc->sc_mfc;
    709 
    710 	cflag = t->c_cflag;
    711 	unit = tp->t_dev & 31;
    712 	if (sc->flags & CT_USED) {
    713 		--scc->ct_usecnt;
    714 		sc->flags &= ~CT_USED;
    715 	}
    716 	ospeed = ttspeedtab(t->c_ospeed, scc->mfc_iii ? mfcs3speedtab2 :
    717 	    mfcs2speedtab2);
    718 
    719 	/*
    720 	 * If Baud Rate Generator can't generate requested speed,
    721 	 * try to use the counter/timer.
    722 	 */
    723 	if (ospeed < 0 && (scc->clk_frq % t->c_ospeed) == 0) {
    724 		ospeed = scc->clk_frq / t->c_ospeed;	/* divisor */
    725 		if (scc->ct_usecnt > 0 && scc->ct_val != ospeed)
    726 			ospeed = -1;
    727 		else {
    728 			scc->sc_regs->du_ctur = ospeed >> 8;
    729 			scc->sc_regs->du_ctlr = ospeed;
    730 			scc->ct_val = ospeed;
    731 			++scc->ct_usecnt;
    732 			sc->flags |= CT_USED;
    733 			ospeed = 0xdd;
    734 		}
    735 	}
    736 	/* XXXX 68681 duart could handle split speeds */
    737 	if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
    738 		return(EINVAL);
    739 
    740 	/* XXXX handle parity, character size, stop bits, flow control */
    741 
    742 	/*
    743 	 * copy to tty
    744 	 */
    745 	tp->t_ispeed = t->c_ispeed;
    746 	tp->t_ospeed = t->c_ospeed;
    747 	tp->t_cflag = cflag;
    748 
    749 	/*
    750 	 * enable interrupts
    751 	 */
    752 	scc->imask |= (0x2 << ((unit & 1) * 4)) | 0x80;
    753 	scc->sc_regs->du_imr = scc->imask;
    754 #if defined(DEBUG) && 0
    755 	printf("mfcsparam: speed %d => %x ct %d imask %x cflag %x\n",
    756 	    t->c_ospeed, ospeed, scc->ct_val, scc->imask, cflag);
    757 #endif
    758 	if (ospeed == 0)
    759 		(void)mfcsmctl(tp->t_dev, 0, DMSET);	/* hang up line */
    760 	else {
    761 		/*
    762 		 * (re)enable DTR
    763 		 * and set baud rate. (8 bit mode)
    764 		 */
    765 		(void)mfcsmctl(tp->t_dev, TIOCM_DTR | TIOCM_RTS, DMSET);
    766 		sc->sc_duart->ch_csr = ospeed;
    767 	}
    768 	return(0);
    769 }
    770 
    771 int mfcshwiflow(tp, flag)
    772         struct tty *tp;
    773         int flag;
    774 {
    775 	struct mfcs_softc *sc = mfcscd.cd_devs[tp->t_dev & 31];
    776 	int unit = tp->t_dev & 1;
    777 
    778         if (flag)
    779 		sc->sc_regs->du_btrst = 1 << unit;
    780 	else
    781 		sc->sc_regs->du_btst = 1 << unit;
    782         return 1;
    783 }
    784 
    785 int
    786 mfcsstart(tp)
    787 	struct tty *tp;
    788 {
    789 	int cc, s, unit;
    790 	struct mfcs_softc *sc = mfcscd.cd_devs[tp->t_dev & 31];
    791 	struct mfc_softc *scc= sc->sc_mfc;
    792 
    793 	if ((tp->t_state & TS_ISOPEN) == 0)
    794 		return;
    795 
    796 	unit = tp->t_dev & 1;
    797 
    798 	s = splser();
    799 	if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP))
    800 		goto out;
    801 
    802 	cc = tp->t_outq.c_cc;
    803 	if (cc <= tp->t_lowat) {
    804 		if (tp->t_state & TS_ASLEEP) {
    805 			tp->t_state &= ~TS_ASLEEP;
    806 			wakeup((caddr_t) & tp->t_outq);
    807 		}
    808 		selwakeup(&tp->t_wsel);
    809 	}
    810 	if (cc == 0 || (tp->t_state & TS_BUSY))
    811 		goto out;
    812 
    813 	/*
    814 	 * We only do bulk transfers if using CTSRTS flow control, not for
    815 	 * (probably sloooow) ixon/ixoff devices.
    816 	 */
    817 	if ((tp->t_cflag & CRTSCTS) == 0)
    818 		cc = 1;
    819 
    820 	/*
    821 	 * Limit the amount of output we do in one burst
    822 	 * to prevent hogging the CPU.
    823 	 */
    824 	if (cc > SEROBUF_SIZE)
    825 		cc = SEROBUF_SIZE;
    826 	cc = q_to_b(&tp->t_outq, sc->outbuf, cc);
    827 	if (cc > 0) {
    828 		tp->t_state |= TS_BUSY;
    829 
    830 		sc->ptr = sc->outbuf;
    831 		sc->end = sc->outbuf + cc;
    832 
    833 		/*
    834 		 * Get first character out, then have TBE-interrupts blow out
    835 		 * further characters, until buffer is empty, and TS_BUSY gets
    836 		 * cleared.
    837 		 */
    838 		sc->sc_duart->ch_tb = *sc->ptr++;
    839 		scc->imask |= 1 << (unit * 4);
    840 		sc->sc_regs->du_imr = scc->imask;
    841 	}
    842 out:
    843 	splx(s);
    844 }
    845 
    846 /*
    847  * Stop output on a line.
    848  */
    849 /*ARGSUSED*/
    850 int
    851 mfcsstop(tp, flag)
    852 	struct tty *tp;
    853 {
    854 	int s;
    855 
    856 	s = splser();
    857 	if (tp->t_state & TS_BUSY) {
    858 		if ((tp->t_state & TS_TTSTOP) == 0)
    859 			tp->t_state |= TS_FLUSH;
    860 	}
    861 	splx(s);
    862 }
    863 
    864 int
    865 mfcsmctl(dev, bits, how)
    866 	dev_t dev;
    867 	int bits, how;
    868 {
    869 	int unit, s;
    870 	u_char ub;
    871 	struct mfcs_softc *sc = mfcscd.cd_devs[dev & 31];
    872 
    873 	unit = dev & 1;
    874 
    875 	/*
    876 	 * convert TIOCM* mask into CIA mask
    877 	 * which is active low
    878 	 */
    879 	if (how != DMGET) {
    880 		ub = 0;
    881 		/*
    882 		 * need to save current state of DTR & RTS ?
    883 		 */
    884 		if (bits & TIOCM_DTR)
    885 			ub |= 0x04 << unit;
    886 		if (bits & TIOCM_RTS)
    887 			ub |= 0x01 << unit;
    888 	}
    889 	s = splser();
    890 	switch (how) {
    891 	case DMSET:
    892 		sc->sc_regs->du_btst = ub;
    893 		sc->sc_regs->du_btrst = ub ^ (0x05 << unit);
    894 		break;
    895 
    896 	case DMBIC:
    897 		sc->sc_regs->du_btrst = ub;
    898 		ub = ~sc->sc_regs->du_ip;
    899 		break;
    900 
    901 	case DMBIS:
    902 		sc->sc_regs->du_btst = ub;
    903 		ub = ~sc->sc_regs->du_ip;
    904 		break;
    905 
    906 	case DMGET:
    907 		ub = ~sc->sc_regs->du_ip;
    908 		break;
    909 	}
    910 	(void)splx(s);
    911 
    912 	/* XXXX should keep DTR & RTS states in softc? */
    913 	bits = TIOCM_DTR | TIOCM_RTS;
    914 	if (ub & (1 << unit))
    915 		bits |= TIOCM_CTS;
    916 	if (ub & (4 << unit))
    917 		bits |= TIOCM_DSR;
    918 	if (ub & (0x10 << unit))
    919 		bits |= TIOCM_CD;
    920 	/* XXXX RI is not supported on all boards */
    921 	if (sc->sc_regs->pad26 & (1 << unit))
    922 		bits |= TIOCM_RI;
    923 
    924 	return(bits);
    925 }
    926 
    927 /*
    928  * Level 6 interrupt processing for the MultiFaceCard 68681 DUART
    929  */
    930 
    931 int
    932 mfcintr (scc)
    933 	struct mfc_softc *scc;
    934 {
    935 	struct mfcs_softc *sc;
    936 	struct mfc_regs *regs;
    937 	struct tty *tp;
    938 	int istat, unit;
    939 	u_short c;
    940 
    941 	regs = scc->sc_regs;
    942 	istat = regs->du_isr & scc->imask;
    943 	if (istat == 0)
    944 		return (0);
    945 	unit = scc->sc_dev.dv_unit * 2;
    946 	if (istat & 0x02) {		/* channel A receive interrupt */
    947 		sc = mfcscd.cd_devs[unit];
    948 		while (1) {
    949 			c = regs->du_sra << 8;
    950 			if ((c & 0x0100) == 0)
    951 				break;
    952 			c |= regs->du_rba;
    953 			if (sc->incnt == SERIBUF_SIZE)
    954 				++sc->ovfl;
    955 			else {
    956 				*sc->wptr++ = c;
    957 				if (sc->wptr == sc->inbuf + SERIBUF_SIZE)
    958 					sc->wptr = sc->inbuf;
    959 				++sc->incnt;
    960 				if (sc->incnt > SERIBUF_SIZE - 16)
    961 					regs->du_btrst = 1;
    962 			}
    963 			if (c & 0x1000)
    964 				regs->du_cra = 0x40;
    965 		}
    966 	}
    967 	if (istat & 0x20) {		/* channel B receive interrupt */
    968 		sc = mfcscd.cd_devs[unit + 1];
    969 		while (1) {
    970 			c = regs->du_srb << 8;
    971 			if ((c & 0x0100) == 0)
    972 				break;
    973 			c |= regs->du_rbb;
    974 			if (sc->incnt == SERIBUF_SIZE)
    975 				++sc->ovfl;
    976 			else {
    977 				*sc->wptr++ = c;
    978 				if (sc->wptr == sc->inbuf + SERIBUF_SIZE)
    979 					sc->wptr = sc->inbuf;
    980 				++sc->incnt;
    981 				if (sc->incnt > SERIBUF_SIZE - 16)
    982 					regs->du_btrst = 2;
    983 			}
    984 			if (c & 0x1000)
    985 				regs->du_crb = 0x40;
    986 		}
    987 	}
    988 	if (istat & 0x01) {		/* channel A transmit interrupt */
    989 		sc = mfcscd.cd_devs[unit];
    990 		tp = sc->sc_tty;
    991 		if (sc->ptr == sc->end) {
    992 			tp->t_state &= ~(TS_BUSY | TS_FLUSH);
    993 			scc->imask &= ~0x01;
    994 			regs->du_imr = scc->imask;
    995 			add_sicallback (tp->t_line ?
    996 			    linesw[tp->t_line].l_start : mfcsstart,
    997 			    tp, NULL);
    998 
    999 		}
   1000 		else
   1001 			regs->du_tba = *sc->ptr++;
   1002 	}
   1003 	if (istat & 0x10) {		/* channel B transmit interrupt */
   1004 		sc = mfcscd.cd_devs[unit + 1];
   1005 		tp = sc->sc_tty;
   1006 		if (sc->ptr == sc->end) {
   1007 			tp->t_state &= ~(TS_BUSY | TS_FLUSH);
   1008 			scc->imask &= ~0x10;
   1009 			regs->du_imr = scc->imask;
   1010 			add_sicallback (tp->t_line ?
   1011 			    linesw[tp->t_line].l_start : mfcsstart,
   1012 			    tp, NULL);
   1013 		}
   1014 		else
   1015 			regs->du_tbb = *sc->ptr++;
   1016 	}
   1017 	if (istat & 0x80) {		/* input port change interrupt */
   1018 		c = regs->du_ipcr;
   1019 		printf ("%s: ipcr %02x", scc->sc_dev.dv_xname, c);
   1020 	}
   1021 	return(1);
   1022 }
   1023 
   1024 int
   1025 mfcsxintr(unit)
   1026 	int unit;
   1027 {
   1028 	int s1, s2, ovfl;
   1029 	struct mfcs_softc *sc = mfcscd.cd_devs[unit];
   1030 	struct tty *tp = sc->sc_tty;
   1031 
   1032 	/*
   1033 	 * Make sure we're not interrupted by another
   1034 	 * vbl, but allow level6 ints
   1035 	 */
   1036 	s1 = spltty();
   1037 
   1038 	/*
   1039 	 * pass along any acumulated information
   1040 	 * while input is not blocked
   1041 	 */
   1042 	while (sc->incnt && (tp->t_state & TS_TBLOCK) == 0) {
   1043 		/*
   1044 		 * no collision with ser_fastint()
   1045 		 */
   1046 		mfcseint(unit, *sc->rptr++);
   1047 
   1048 		ovfl = 0;
   1049 		/* lock against mfcs_fastint() */
   1050 		s2 = splser();
   1051 		--sc->incnt;
   1052 		if (sc->rptr == sc->inbuf + SERIBUF_SIZE)
   1053 			sc->rptr = sc->inbuf;
   1054 		if (sc->ovfl != 0) {
   1055 			ovfl = sc->ovfl;
   1056 			sc->ovfl = 0;
   1057 		}
   1058 		splx(s2);
   1059 		if (ovfl != 0)
   1060 			log(LOG_WARNING, "%s: %d buffer overflow!\n",
   1061 			    sc->sc_dev.dv_xname, ovfl);
   1062 	}
   1063 	if (sc->incnt == 0 && (tp->t_state & TS_TBLOCK) == 0) {
   1064 		sc->sc_regs->du_btst = 1 << unit;	/* XXXX */
   1065 	}
   1066 	splx(s1);
   1067 }
   1068 
   1069 int
   1070 mfcseint(unit, stat)
   1071 	int unit, stat;
   1072 {
   1073 	struct mfcs_softc *sc = mfcscd.cd_devs[unit];
   1074 	struct tty *tp;
   1075 	u_char ch;
   1076 	int c;
   1077 
   1078 	tp = sc->sc_tty;
   1079 	ch = stat & 0xff;
   1080 	c = ch;
   1081 
   1082 	if ((tp->t_state & TS_ISOPEN) == 0) {
   1083 #ifdef KGDB
   1084 		/* we don't care about parity errors */
   1085 		if (kgdb_dev == makedev(sermajor, unit) && c == FRAME_END)
   1086 			kgdb_connect(0);	/* trap into kgdb */
   1087 #endif
   1088 		return;
   1089 	}
   1090 
   1091 	/*
   1092 	 * Check for break and (if enabled) parity error.
   1093 	 */
   1094 	if (stat & 0xc000)
   1095 		c |= TTY_FE;
   1096 	else if (stat & 0x2000)
   1097 			c |= TTY_PE;
   1098 
   1099 	if (stat & 0x1000)
   1100 		log(LOG_WARNING, "%s: fifo overflow\n",
   1101 		    ((struct mfcs_softc *)mfcscd.cd_devs[unit])->sc_dev.dv_xname);
   1102 
   1103 	(*linesw[tp->t_line].l_rint)(c, tp);
   1104 }
   1105 
   1106 /*
   1107  * This interrupt is periodically invoked in the vertical blank
   1108  * interrupt.  It's used to keep track of the modem control lines
   1109  * and (new with the fast_int code) to move accumulated data
   1110  * up into the tty layer.
   1111  */
   1112 void
   1113 mfcsmint(unit)
   1114 	int unit;
   1115 {
   1116 	struct tty *tp;
   1117 	struct mfcs_softc *sc = mfcscd.cd_devs[unit];
   1118 	u_char stat, last, istat;
   1119 
   1120 	tp = sc->sc_tty;
   1121 	if (!tp)
   1122 		return;
   1123 
   1124 	if ((tp->t_state & (TS_ISOPEN | TS_WOPEN)) == 0) {
   1125 		sc->rptr = sc->wptr = sc->inbuf;
   1126 		sc->incnt = 0;
   1127 		return;
   1128 	}
   1129 	/*
   1130 	 * empty buffer
   1131 	 */
   1132 	mfcsxintr(unit);
   1133 
   1134 	stat = ~sc->sc_regs->du_ip;
   1135 	last = sc->sc_mfc->last_ip;
   1136 	sc->sc_mfc->last_ip = stat;
   1137 
   1138 	/*
   1139 	 * check whether any interesting signal changed state
   1140 	 */
   1141 	istat = stat ^ last;
   1142 
   1143 	if ((istat & (0x10 << (unit & 1))) && 		/* CD changed */
   1144 	    (SWFLAGS(tp->t_dev) & TIOCFLAG_SOFTCAR) == 0) {
   1145 		if (stat & (0x10 << (unit & 1)))
   1146 			(*linesw[tp->t_line].l_modem)(tp, 1);
   1147 		else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
   1148 			sc->sc_regs->du_btrst = 0x0a << (unit & 1);
   1149 		}
   1150 	}
   1151 }
   1152