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