Home | History | Annotate | Line # | Download | only in sbus
spif.c revision 1.5
      1 /*	$NetBSD: spif.c,v 1.5 2006/05/14 21:47:00 elad Exp $	*/
      2 /*	$OpenBSD: spif.c,v 1.12 2003/10/03 16:44:51 miod Exp $	*/
      3 
      4 /*
      5  * Copyright (c) 1999-2002 Jason L. Wright (jason (at) thought.net)
      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  *
     17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     20  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
     21  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     23  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     25  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
     26  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     27  * POSSIBILITY OF SUCH DAMAGE.
     28  *
     29  * Effort sponsored in part by the Defense Advanced Research Projects
     30  * Agency (DARPA) and Air Force Research Laboratory, Air Force
     31  * Materiel Command, USAF, under agreement number F30602-01-2-0537.
     32  *
     33  */
     34 
     35 /*
     36  * Driver for the SUNW,spif: 8 serial, 1 parallel sbus board
     37  * based heavily on Iain Hibbert's driver for the MAGMA cards
     38  */
     39 
     40 /* Ported to NetBSD 2.0 by Hauke Fath */
     41 
     42 
     43 #include <sys/cdefs.h>
     44 __KERNEL_RCSID(0, "$NetBSD: spif.c,v 1.5 2006/05/14 21:47:00 elad Exp $");
     45 
     46 #include "spif.h"
     47 #if NSPIF > 0
     48 
     49 #include <sys/param.h>
     50 #include <sys/systm.h>
     51 #include <sys/proc.h>
     52 #include <sys/device.h>
     53 #include <sys/file.h>
     54 #include <sys/ioctl.h>
     55 #include <sys/malloc.h>
     56 #include <sys/tty.h>
     57 #include <sys/time.h>
     58 #include <sys/kernel.h>
     59 #include <sys/syslog.h>
     60 #include <sys/conf.h>
     61 #include <sys/errno.h>
     62 
     63 #include <machine/bus.h>
     64 #include <machine/intr.h>
     65 #include <machine/autoconf.h>
     66 #include <machine/promlib.h>
     67 
     68 #include <dev/sbus/sbusvar.h>
     69 
     70 #include <dev/sbus/spifvar.h>
     71 #include <dev/sbus/spifreg.h>
     72 
     73 
     74 /* Autoconfig stuff */
     75 
     76 CFATTACH_DECL(spif, sizeof(struct spif_softc),
     77     spif_match, spif_attach, NULL, NULL);
     78 
     79 CFATTACH_DECL(stty, sizeof(struct stty_softc),
     80     stty_match, stty_attach, NULL, NULL);
     81 
     82 CFATTACH_DECL(sbpp, sizeof(struct sbpp_softc),
     83     sbpp_match, sbpp_attach, NULL, NULL);
     84 
     85 extern struct cfdriver spif_cd;
     86 extern struct cfdriver stty_cd;
     87 extern struct cfdriver sbpp_cd;
     88 
     89 dev_type_open(stty_open);
     90 dev_type_close(stty_close);
     91 dev_type_read(stty_read);
     92 dev_type_write(stty_write);
     93 dev_type_ioctl(stty_ioctl);
     94 dev_type_stop(stty_stop);
     95 dev_type_tty(stty_tty);
     96 dev_type_poll(stty_poll);
     97 
     98 const struct cdevsw stty_cdevsw = {
     99 	stty_open, stty_close, stty_read, stty_write, stty_ioctl,
    100 	stty_stop, stty_tty, stty_poll, nommap, ttykqfilter, D_TTY
    101 };
    102 
    103 dev_type_open(sbpp_open);
    104 dev_type_close(sbpp_close);
    105 dev_type_read(sbpp_read);
    106 dev_type_write(sbpp_write);
    107 dev_type_ioctl(sbpp_ioctl);
    108 dev_type_poll(sbpp_poll);
    109 
    110 const struct cdevsw sbpp_cdevsw = {
    111 	sbpp_open, sbpp_close, sbpp_read, sbpp_write, sbpp_ioctl,
    112 	nostop, notty, sbpp_poll, nommap, nokqfilter,
    113 };
    114 
    115 
    116 /* normal STC access */
    117 #define	STC_WRITE(sc,r,v)	\
    118     bus_space_write_1((sc)->sc_bustag, (sc)->sc_stch, (r), (v))
    119 #define	STC_READ(sc,r)		\
    120     bus_space_read_1((sc)->sc_bustag, (sc)->sc_stch, (r))
    121 
    122 /* IACK STC access */
    123 #define	ISTC_WRITE(sc,r,v)	\
    124     bus_space_write_1((sc)->sc_bustag, (sc)->sc_istch, (r), (v))
    125 #define	ISTC_READ(sc,r)		\
    126     bus_space_read_1((sc)->sc_bustag, (sc)->sc_istch, (r))
    127 
    128 /* PPC access */
    129 #define	PPC_WRITE(sc,r,v)	\
    130     bus_space_write_1((sc)->sc_bustag, (sc)->sc_ppch, (r), (v))
    131 #define	PPC_READ(sc,r)		\
    132     bus_space_read_1((sc)->sc_bustag, (sc)->sc_ppch, (r))
    133 
    134 #define	DTR_WRITE(sc,port,v)						\
    135     do {								\
    136 	sc->sc_ttys->sc_port[(port)].sp_dtr = v;			\
    137 	bus_space_write_1((sc)->sc_bustag,				\
    138 	    sc->sc_dtrh, port, (v == 0) ? 1 : 0);			\
    139     } while (0)
    140 
    141 #define	DTR_READ(sc,port)	((sc)->sc_ttys->sc_port[(port)].sp_dtr)
    142 
    143 
    144 int
    145 spif_match(parent, vcf, aux)
    146 	struct device *parent;
    147 	struct cfdata *vcf;
    148 	void *aux;
    149 {
    150 	struct sbus_attach_args *sa = aux;
    151 
    152 	if (strcmp(vcf->cf_name, sa->sa_name) &&
    153 	    strcmp("SUNW,spif", sa->sa_name))
    154 		return (0);
    155 	return (1);
    156 }
    157 
    158 void
    159 spif_attach(parent, self, aux)
    160 	struct device *parent, *self;
    161 	void *aux;
    162 {
    163 	struct spif_softc *sc = (struct spif_softc *)self;
    164 	struct sbus_attach_args *sa = aux;
    165 
    166 	if (sa->sa_nintr != 2) {
    167 		printf(": expected %d interrupts, got %d\n", 2, sa->sa_nintr);
    168 		return;
    169 	}
    170 
    171 	if (sa->sa_nreg != 1) {
    172 		printf(": expected %d registers, got %d\n", 1, sa->sa_nreg);
    173 		return;
    174 	}
    175 
    176 	sc->sc_bustag = sa->sa_bustag;
    177 	if (sbus_bus_map(sa->sa_bustag, sa->sa_slot,
    178 	    sa->sa_offset, sa->sa_size,
    179 	    0, &sc->sc_regh) != 0) {
    180 		printf(": can't map registers\n");
    181 		return;
    182 	}
    183 
    184 	if (bus_space_subregion(sc->sc_bustag, sc->sc_regh,
    185 	    DTR_REG_OFFSET, DTR_REG_LEN, &sc->sc_dtrh) != 0) {
    186 		printf(": can't map dtr regs\n");
    187 		goto fail_unmapregs;
    188 	}
    189 
    190 	if (bus_space_subregion(sc->sc_bustag, sc->sc_regh,
    191 	    STC_REG_OFFSET, STC_REG_LEN, &sc->sc_stch) != 0) {
    192 		printf(": can't map dtr regs\n");
    193 		goto fail_unmapregs;
    194 	}
    195 
    196 	if (bus_space_subregion(sc->sc_bustag, sc->sc_regh,
    197 	    ISTC_REG_OFFSET, ISTC_REG_LEN, &sc->sc_istch) != 0) {
    198 		printf(": can't map dtr regs\n");
    199 		goto fail_unmapregs;
    200 	}
    201 
    202 	if (bus_space_subregion(sc->sc_bustag, sc->sc_regh,
    203 	    PPC_REG_OFFSET, PPC_REG_LEN, &sc->sc_ppch) != 0) {
    204 		printf(": can't map dtr regs\n");
    205 		goto fail_unmapregs;
    206 	}
    207 
    208 	sc->sc_ppcih = bus_intr_establish(sa->sa_bustag,
    209 	    sa->sa_intr[PARALLEL_INTR].oi_pri, IPL_SERIAL, spif_ppcintr, sc);
    210 	if (sc->sc_ppcih == NULL) {
    211 		printf(": failed to establish ppc interrupt\n");
    212 		goto fail_unmapregs;
    213 	}
    214 
    215 	sc->sc_stcih = bus_intr_establish(sa->sa_bustag,
    216 	    sa->sa_intr[SERIAL_INTR].oi_pri, IPL_SERIAL, spif_stcintr, sc);
    217 	if (sc->sc_stcih == NULL) {
    218 		printf(": failed to establish stc interrupt\n");
    219 		goto fail_unmapregs;
    220 	}
    221 
    222 	sc->sc_softih = softintr_establish(IPL_TTY, spif_softintr, sc);
    223 	if (sc->sc_softih == NULL) {
    224 		printf(": can't get soft intr\n");
    225 		goto fail_unmapregs;
    226 	}
    227 
    228 	sc->sc_node = sa->sa_node;
    229 
    230 	sc->sc_rev = prom_getpropint(sc->sc_node, "revlev", 0);
    231 
    232 	sc->sc_osc = prom_getpropint(sc->sc_node, "verosc", 0);
    233 	switch (sc->sc_osc) {
    234 	case SPIF_OSC10:
    235 		sc->sc_osc = 10000000;
    236 		break;
    237 	case SPIF_OSC9:
    238 	default:
    239 		sc->sc_osc = 9830400;
    240 		break;
    241 	}
    242 
    243 	sc->sc_nser = 8;
    244 	sc->sc_npar = 1;
    245 
    246 	sc->sc_rev2 = STC_READ(sc, STC_GFRCR);
    247 	STC_WRITE(sc, STC_GSVR, 0);
    248 
    249 	stty_write_ccr(sc, CD180_CCR_CMD_RESET | CD180_CCR_RESETALL);
    250 	while (STC_READ(sc, STC_GSVR) != 0xff);
    251 	while (STC_READ(sc, STC_GFRCR) != sc->sc_rev2);
    252 
    253 	STC_WRITE(sc, STC_PPRH, CD180_PPRH);
    254 	STC_WRITE(sc, STC_PPRL, CD180_PPRL);
    255 	STC_WRITE(sc, STC_MSMR, SPIF_MSMR);
    256 	STC_WRITE(sc, STC_TSMR, SPIF_TSMR);
    257 	STC_WRITE(sc, STC_RSMR, SPIF_RSMR);
    258 	STC_WRITE(sc, STC_GSVR, 0);
    259 	STC_WRITE(sc, STC_GSCR1, 0);
    260 	STC_WRITE(sc, STC_GSCR2, 0);
    261 	STC_WRITE(sc, STC_GSCR3, 0);
    262 
    263 	printf(": rev %x chiprev %x osc %sMHz\n",
    264 	    sc->sc_rev, sc->sc_rev2, clockfreq(sc->sc_osc));
    265 
    266 	(void)config_found(self, stty_match, NULL);
    267 	(void)config_found(self, sbpp_match, NULL);
    268 
    269 	return;
    270 
    271 fail_unmapregs:
    272 	bus_space_unmap(sa->sa_bustag, sc->sc_regh, sa->sa_size);
    273 }
    274 
    275 int
    276 stty_match(parent, vcf, aux)
    277 	struct device *parent;
    278 	struct cfdata *vcf;
    279 	void *aux;
    280 {
    281 	struct spif_softc *sc = (struct spif_softc *)parent;
    282 
    283 	return (aux == stty_match && sc->sc_ttys == NULL);
    284 }
    285 
    286 void
    287 stty_attach(parent, dev, aux)
    288 	struct device *parent, *dev;
    289 	void *aux;
    290 {
    291 	struct spif_softc *sc = (struct spif_softc *)parent;
    292 	struct stty_softc *ssc = (struct stty_softc *)dev;
    293 	int port;
    294 
    295 	sc->sc_ttys = ssc;
    296 
    297 	for (port = 0; port < sc->sc_nser; port++) {
    298 		struct stty_port *sp = &ssc->sc_port[port];
    299 		struct tty *tp;
    300 
    301 		DTR_WRITE(sc, port, 0);
    302 
    303 		tp = ttymalloc();
    304 
    305 		tp->t_oproc = stty_start;
    306 		tp->t_param = stty_param;
    307 
    308 		sp->sp_tty = tp;
    309 		sp->sp_sc = sc;
    310 		sp->sp_channel = port;
    311 
    312 		sp->sp_rbuf = malloc(STTY_RBUF_SIZE, M_DEVBUF, M_NOWAIT);
    313 		if(sp->sp_rbuf == NULL)
    314 			break;
    315 
    316 		sp->sp_rend = sp->sp_rbuf + STTY_RBUF_SIZE;
    317 	}
    318 
    319 	ssc->sc_nports = port;
    320 
    321 	printf(": %d tty%s\n", port, port == 1 ? "" : "s");
    322 }
    323 
    324 int
    325 stty_open(dev, flags, mode, l)
    326 	dev_t dev;
    327 	int flags;
    328 	int mode;
    329 	struct lwp *l;
    330 {
    331 	struct spif_softc *csc;
    332 	struct stty_softc *sc;
    333 	struct stty_port *sp;
    334 	struct tty *tp;
    335 	int card = SPIF_CARD(dev);
    336 	int port = SPIF_PORT(dev);
    337 	int s;
    338 
    339 	if (card >= stty_cd.cd_ndevs || card >= spif_cd.cd_ndevs)
    340 		return (ENXIO);
    341 
    342 	sc = stty_cd.cd_devs[card];
    343 	csc = spif_cd.cd_devs[card];
    344 	if (sc == NULL || csc == NULL)
    345 		return (ENXIO);
    346 
    347 	if (port >= sc->sc_nports)
    348 		return (ENXIO);
    349 
    350 	sp = &sc->sc_port[port];
    351 	tp = sp->sp_tty;
    352 	tp->t_dev = dev;
    353 
    354 	if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
    355 		ttychars(tp);
    356 		tp->t_iflag = TTYDEF_IFLAG;
    357 		tp->t_oflag = TTYDEF_OFLAG;
    358 		tp->t_cflag = TTYDEF_CFLAG;
    359 		if (ISSET(sp->sp_openflags, TIOCFLAG_CLOCAL))
    360 			SET(tp->t_cflag, CLOCAL);
    361 		if (ISSET(sp->sp_openflags, TIOCFLAG_CRTSCTS))
    362 			SET(tp->t_cflag, CRTSCTS);
    363 		if (ISSET(sp->sp_openflags, TIOCFLAG_MDMBUF))
    364 			SET(tp->t_cflag, MDMBUF);
    365 		tp->t_lflag = TTYDEF_LFLAG;
    366 		tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
    367 
    368 		sp->sp_rput = sp->sp_rget = sp->sp_rbuf;
    369 
    370 		s = spltty();
    371 
    372 		STC_WRITE(csc, STC_CAR, sp->sp_channel);
    373 		stty_write_ccr(csc, CD180_CCR_CMD_RESET|CD180_CCR_RESETCHAN);
    374 		STC_WRITE(csc, STC_CAR, sp->sp_channel);
    375 
    376 		stty_param(tp, &tp->t_termios);
    377 
    378 		ttsetwater(tp);
    379 
    380 		STC_WRITE(csc, STC_SRER, CD180_SRER_CD | CD180_SRER_RXD);
    381 
    382 		if (ISSET(sp->sp_openflags, TIOCFLAG_SOFTCAR) || sp->sp_carrier)
    383 			SET(tp->t_state, TS_CARR_ON);
    384 		else
    385 			CLR(tp->t_state, TS_CARR_ON);
    386 	}
    387 	else if (ISSET(tp->t_state, TS_XCLUDE) &&
    388 		 kauth_authorize_generic(l->l_proc->p_cred, KAUTH_GENERIC_ISSUSER, &l->l_proc->p_acflag) != 0) {
    389 		return (EBUSY);
    390 	} else {
    391 		s = spltty();
    392 	}
    393 
    394 	if (!ISSET(flags, O_NONBLOCK)) {
    395 		while (!ISSET(tp->t_cflag, CLOCAL) &&
    396 		    !ISSET(tp->t_state, TS_CARR_ON)) {
    397 			int error;
    398 			error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH,
    399 			    "sttycd", 0);
    400 			if (error != 0) {
    401 				splx(s);
    402 				return (error);
    403 			}
    404 		}
    405 	}
    406 
    407 	splx(s);
    408 
    409 	return ((*tp->t_linesw->l_open)(dev, tp));
    410 }
    411 
    412 int
    413 stty_close(dev, flags, mode, l)
    414 	dev_t dev;
    415 	int flags;
    416 	int mode;
    417 	struct lwp *l;
    418 {
    419 	struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(dev)];
    420 	struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)];
    421 	struct spif_softc *csc = sp->sp_sc;
    422 	struct tty *tp = sp->sp_tty;
    423 	int port = SPIF_PORT(dev);
    424 	int s;
    425 
    426 	(*tp->t_linesw->l_close)(tp, flags);
    427 	s = spltty();
    428 
    429 	if (ISSET(tp->t_cflag, HUPCL) || !ISSET(tp->t_state, TS_ISOPEN)) {
    430 		stty_modem_control(sp, 0, DMSET);
    431 		STC_WRITE(csc, STC_CAR, port);
    432 		STC_WRITE(csc, STC_CCR,
    433 		    CD180_CCR_CMD_RESET|CD180_CCR_RESETCHAN);
    434 	}
    435 
    436 	splx(s);
    437 	ttyclose(tp);
    438 	return (0);
    439 }
    440 
    441 int
    442 stty_ioctl(dev, cmd, data, flags, l)
    443 	dev_t dev;
    444 	u_long cmd;
    445 	caddr_t data;
    446 	int flags;
    447 	struct lwp *l;
    448 {
    449 	struct stty_softc *stc = stty_cd.cd_devs[SPIF_CARD(dev)];
    450 	struct stty_port *sp = &stc->sc_port[SPIF_PORT(dev)];
    451 	struct spif_softc *sc = sp->sp_sc;
    452 	struct tty *tp = sp->sp_tty;
    453 	int error;
    454 
    455 	error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flags, l);
    456 	if (error >= 0)
    457 		return (error);
    458 
    459 	error = ttioctl(tp, cmd, data, flags, l);
    460 	if (error >= 0)
    461 		return (error);
    462 
    463 	error = 0;
    464 
    465 	switch (cmd) {
    466 	case TIOCSBRK:
    467 		SET(sp->sp_flags, STTYF_SET_BREAK);
    468 		STC_WRITE(sc, STC_CAR, sp->sp_channel);
    469 		STC_WRITE(sc, STC_SRER,
    470 		    STC_READ(sc, STC_SRER) | CD180_SRER_TXD);
    471 		break;
    472 	case TIOCCBRK:
    473 		SET(sp->sp_flags, STTYF_CLR_BREAK);
    474 		STC_WRITE(sc, STC_CAR, sp->sp_channel);
    475 		STC_WRITE(sc, STC_SRER,
    476 		    STC_READ(sc, STC_SRER) | CD180_SRER_TXD);
    477 		break;
    478 	case TIOCSDTR:
    479 		stty_modem_control(sp, TIOCM_DTR, DMBIS);
    480 		break;
    481 	case TIOCCDTR:
    482 		stty_modem_control(sp, TIOCM_DTR, DMBIC);
    483 		break;
    484 	case TIOCMBIS:
    485 		stty_modem_control(sp, *((int *)data), DMBIS);
    486 		break;
    487 	case TIOCMBIC:
    488 		stty_modem_control(sp, *((int *)data), DMBIC);
    489 		break;
    490 	case TIOCMGET:
    491 		*((int *)data) = stty_modem_control(sp, 0, DMGET);
    492 		break;
    493 	case TIOCMSET:
    494 		stty_modem_control(sp, *((int *)data), DMSET);
    495 		break;
    496 	case TIOCGFLAGS:
    497 		*((int *)data) = sp->sp_openflags;
    498 		break;
    499 	case TIOCSFLAGS:
    500 		if (kauth_authorize_generic(l->l_proc->p_cred, KAUTH_GENERIC_ISSUSER, &l->l_proc->p_acflag) )
    501 			error = EPERM;
    502 		else
    503 			sp->sp_openflags = *((int *)data) &
    504 			    (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL |
    505 			     TIOCFLAG_CRTSCTS | TIOCFLAG_MDMBUF);
    506 		break;
    507 	default:
    508 		error = ENOTTY;
    509 	}
    510 
    511 	return (error);
    512 }
    513 
    514 int
    515 stty_modem_control(sp, bits, how)
    516 	struct stty_port *sp;
    517 	int bits, how;
    518 {
    519 	struct spif_softc *csc = sp->sp_sc;
    520 	struct tty *tp = sp->sp_tty;
    521 	int s, msvr;
    522 
    523 	s = spltty();
    524 	STC_WRITE(csc, STC_CAR, sp->sp_channel);
    525 
    526 	switch (how) {
    527 	case DMGET:
    528 		bits = TIOCM_LE;
    529 		if (DTR_READ(csc, sp->sp_channel))
    530 			bits |= TIOCM_DTR;
    531 		msvr = STC_READ(csc, STC_MSVR);
    532 		if (ISSET(msvr, CD180_MSVR_DSR))
    533 			bits |= TIOCM_DSR;
    534 		if (ISSET(msvr, CD180_MSVR_CD))
    535 			bits |= TIOCM_CD;
    536 		if (ISSET(msvr, CD180_MSVR_CTS))
    537 			bits |= TIOCM_CTS;
    538 		if (ISSET(msvr, CD180_MSVR_RTS))
    539 			bits |= TIOCM_RTS;
    540 		break;
    541 	case DMSET:
    542 		DTR_WRITE(csc, sp->sp_channel, ISSET(bits, TIOCM_DTR) ? 1 : 0);
    543 		if (ISSET(bits, TIOCM_RTS))
    544 			STC_WRITE(csc, STC_MSVR,
    545 			    STC_READ(csc, STC_MSVR) & (~CD180_MSVR_RTS));
    546 		else
    547 			STC_WRITE(csc, STC_MSVR,
    548 			    STC_READ(csc, STC_MSVR) | CD180_MSVR_RTS);
    549 		break;
    550 	case DMBIS:
    551 		if (ISSET(bits, TIOCM_DTR))
    552 			DTR_WRITE(csc, sp->sp_channel, 1);
    553 		if (ISSET(bits, TIOCM_RTS) && !ISSET(tp->t_cflag, CRTSCTS))
    554 			STC_WRITE(csc, STC_MSVR,
    555 			    STC_READ(csc, STC_MSVR) & (~CD180_MSVR_RTS));
    556 		break;
    557 	case DMBIC:
    558 		if (ISSET(bits, TIOCM_DTR))
    559 			DTR_WRITE(csc, sp->sp_channel, 0);
    560 		if (ISSET(bits, TIOCM_RTS))
    561 			STC_WRITE(csc, STC_MSVR,
    562 			    STC_READ(csc, STC_MSVR) | CD180_MSVR_RTS);
    563 		break;
    564 	}
    565 
    566 	splx(s);
    567 	return (bits);
    568 }
    569 
    570 int
    571 stty_param(tp, t)
    572 	struct tty *tp;
    573 	struct termios *t;
    574 {
    575 	struct stty_softc *st = stty_cd.cd_devs[SPIF_CARD(tp->t_dev)];
    576 	struct stty_port *sp = &st->sc_port[SPIF_PORT(tp->t_dev)];
    577 	struct spif_softc *sc = sp->sp_sc;
    578 	u_int8_t rbprl, rbprh, tbprl, tbprh;
    579 	int s, opt;
    580 
    581 	if (t->c_ospeed &&
    582 	    stty_compute_baud(t->c_ospeed, sc->sc_osc, &tbprl, &tbprh))
    583 		return (EINVAL);
    584 
    585 	if (t->c_ispeed &&
    586 	    stty_compute_baud(t->c_ispeed, sc->sc_osc, &rbprl, &rbprh))
    587 		return (EINVAL);
    588 
    589 	s = spltty();
    590 
    591 	/* hang up line if ospeed is zero, otherwise raise DTR */
    592 	stty_modem_control(sp, TIOCM_DTR,
    593 	    (t->c_ospeed == 0 ? DMBIC : DMBIS));
    594 
    595 	STC_WRITE(sc, STC_CAR, sp->sp_channel);
    596 
    597 	opt = 0;
    598 	if (ISSET(t->c_cflag, PARENB)) {
    599 		opt |= CD180_COR1_PARMODE_NORMAL;
    600 		opt |= (ISSET(t->c_cflag, PARODD) ?
    601 				CD180_COR1_ODDPAR :
    602 				CD180_COR1_EVENPAR);
    603 	}
    604 	else
    605 		opt |= CD180_COR1_PARMODE_NO;
    606 
    607 	if (!ISSET(t->c_iflag, INPCK))
    608 		opt |= CD180_COR1_IGNPAR;
    609 
    610 	if (ISSET(t->c_cflag, CSTOPB))
    611 		opt |= CD180_COR1_STOP2;
    612 
    613 	switch (t->c_cflag & CSIZE) {
    614 	case CS5:
    615 		opt |= CD180_COR1_CS5;
    616 		break;
    617 	case CS6:
    618 		opt |= CD180_COR1_CS6;
    619 		break;
    620 	case CS7:
    621 		opt |= CD180_COR1_CS7;
    622 		break;
    623 	default:
    624 		opt |= CD180_COR1_CS8;
    625 		break;
    626 	}
    627 	STC_WRITE(sc, STC_COR1, opt);
    628 	stty_write_ccr(sc, CD180_CCR_CMD_COR|CD180_CCR_CORCHG1);
    629 
    630 	opt = CD180_COR2_ETC;
    631 	if (ISSET(t->c_cflag, CRTSCTS))
    632 		opt |= CD180_COR2_CTSAE;
    633 	STC_WRITE(sc, STC_COR2, opt);
    634 	stty_write_ccr(sc, CD180_CCR_CMD_COR|CD180_CCR_CORCHG2);
    635 
    636 	STC_WRITE(sc, STC_COR3, STTY_RX_FIFO_THRESHOLD);
    637 	stty_write_ccr(sc, CD180_CCR_CMD_COR|CD180_CCR_CORCHG3);
    638 
    639 	STC_WRITE(sc, STC_SCHR1, 0x11);
    640 	STC_WRITE(sc, STC_SCHR2, 0x13);
    641 	STC_WRITE(sc, STC_SCHR3, 0x11);
    642 	STC_WRITE(sc, STC_SCHR4, 0x13);
    643 	STC_WRITE(sc, STC_RTPR, 0x12);
    644 
    645 	STC_WRITE(sc, STC_MCOR1, CD180_MCOR1_CDZD | STTY_RX_DTR_THRESHOLD);
    646 	STC_WRITE(sc, STC_MCOR2, CD180_MCOR2_CDOD);
    647 	STC_WRITE(sc, STC_MCR, 0);
    648 
    649 	if (t->c_ospeed) {
    650 		STC_WRITE(sc, STC_TBPRH, tbprh);
    651 		STC_WRITE(sc, STC_TBPRL, tbprl);
    652 	}
    653 
    654 	if (t->c_ispeed) {
    655 		STC_WRITE(sc, STC_RBPRH, rbprh);
    656 		STC_WRITE(sc, STC_RBPRL, rbprl);
    657 	}
    658 
    659 	stty_write_ccr(sc, CD180_CCR_CMD_CHAN |
    660 	    CD180_CCR_CHAN_TXEN | CD180_CCR_CHAN_RXEN);
    661 
    662 	sp->sp_carrier = STC_READ(sc, STC_MSVR) & CD180_MSVR_CD;
    663 
    664 	splx(s);
    665 	return (0);
    666 }
    667 
    668 int
    669 stty_read(dev, uio, flags)
    670 	dev_t dev;
    671 	struct uio *uio;
    672 	int flags;
    673 {
    674 	struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(dev)];
    675 	struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)];
    676 	struct tty *tp = sp->sp_tty;
    677 
    678 	return ((*tp->t_linesw->l_read)(tp, uio, flags));
    679 }
    680 
    681 int
    682 stty_write(dev, uio, flags)
    683 	dev_t dev;
    684 	struct uio *uio;
    685 	int flags;
    686 {
    687 	struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(dev)];
    688 	struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)];
    689 	struct tty *tp = sp->sp_tty;
    690 
    691 	return ((*tp->t_linesw->l_write)(tp, uio, flags));
    692 }
    693 
    694 int
    695 stty_poll(dev, events, l)
    696 	dev_t dev;
    697 	int events;
    698 	struct lwp *l;
    699 {
    700 	struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(dev)];
    701 	struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)];
    702 	struct tty *tp = sp->sp_tty;
    703 
    704 	return ((*tp->t_linesw->l_poll)(tp, events, l));
    705 }
    706 
    707 struct tty *
    708 stty_tty(dev)
    709 	dev_t dev;
    710 {
    711 	struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(dev)];
    712 	struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)];
    713 
    714 	return (sp->sp_tty);
    715 }
    716 
    717 void
    718 stty_stop(tp, flags)
    719 	struct tty *tp;
    720 	int flags;
    721 {
    722 	struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(tp->t_dev)];
    723 	struct stty_port *sp = &sc->sc_port[SPIF_PORT(tp->t_dev)];
    724 	int s;
    725 
    726 	s = spltty();
    727 	if (ISSET(tp->t_state, TS_BUSY)) {
    728 		if (!ISSET(tp->t_state, TS_TTSTOP))
    729 			SET(tp->t_state, TS_FLUSH);
    730 		SET(sp->sp_flags, STTYF_STOP);
    731 	}
    732 	splx(s);
    733 }
    734 
    735 void
    736 stty_start(tp)
    737 	struct tty *tp;
    738 {
    739 	struct stty_softc *stc = stty_cd.cd_devs[SPIF_CARD(tp->t_dev)];
    740 	struct stty_port *sp = &stc->sc_port[SPIF_PORT(tp->t_dev)];
    741 	struct spif_softc *sc = sp->sp_sc;
    742 	int s;
    743 
    744 	s = spltty();
    745 
    746 	if (!ISSET(tp->t_state, TS_TTSTOP | TS_TIMEOUT | TS_BUSY)) {
    747 		if (tp->t_outq.c_cc <= tp->t_lowat) {
    748 			if (ISSET(tp->t_state, TS_ASLEEP)) {
    749 				CLR(tp->t_state, TS_ASLEEP);
    750 				wakeup(&tp->t_outq);
    751 			}
    752 			selwakeup(&tp->t_wsel);
    753 		}
    754 		if (tp->t_outq.c_cc) {
    755 			sp->sp_txc = ndqb(&tp->t_outq, 0);
    756 			sp->sp_txp = tp->t_outq.c_cf;
    757 			SET(tp->t_state, TS_BUSY);
    758 			STC_WRITE(sc, STC_CAR, sp->sp_channel);
    759 			STC_WRITE(sc, STC_SRER,
    760 			    STC_READ(sc, STC_SRER) | CD180_SRER_TXD);
    761 		}
    762 	}
    763 
    764 	splx(s);
    765 }
    766 
    767 int
    768 spif_stcintr_rxexception(sc, needsoftp)
    769 	struct spif_softc *sc;
    770 	int *needsoftp;
    771 {
    772 	struct stty_port *sp;
    773 	u_int8_t channel, *ptr;
    774 
    775 	channel = CD180_GSCR_CHANNEL(STC_READ(sc, STC_GSCR1));
    776 	sp = &sc->sc_ttys->sc_port[channel];
    777 	ptr = sp->sp_rput;
    778 	*ptr++ = STC_READ(sc, STC_RCSR);
    779 	*ptr++ = STC_READ(sc, STC_RDR);
    780 	if (ptr == sp->sp_rend)
    781 		ptr = sp->sp_rbuf;
    782 	if (ptr == sp->sp_rget) {
    783 		if (ptr == sp->sp_rbuf)
    784 			ptr = sp->sp_rend;
    785 		ptr -= 2;
    786 		SET(sp->sp_flags, STTYF_RING_OVERFLOW);
    787 	}
    788 	STC_WRITE(sc, STC_EOSRR, 0);
    789 	*needsoftp = 1;
    790 	sp->sp_rput = ptr;
    791 	return (1);
    792 }
    793 
    794 int
    795 spif_stcintr_rx(sc, needsoftp)
    796 	struct spif_softc *sc;
    797 	int *needsoftp;
    798 {
    799 	struct stty_port *sp;
    800 	u_int8_t channel, *ptr, cnt, rcsr;
    801 	int i;
    802 
    803 	channel = CD180_GSCR_CHANNEL(STC_READ(sc, STC_GSCR1));
    804 	sp = &sc->sc_ttys->sc_port[channel];
    805 	ptr = sp->sp_rput;
    806 	cnt = STC_READ(sc, STC_RDCR);
    807 	for (i = 0; i < cnt; i++) {
    808 		*ptr++ = 0;
    809 		rcsr = STC_READ(sc, STC_RCSR);
    810 		*ptr++ = STC_READ(sc, STC_RDR);
    811 		if (ptr == sp->sp_rend)
    812 			ptr = sp->sp_rbuf;
    813 		if (ptr == sp->sp_rget) {
    814 			if (ptr == sp->sp_rbuf)
    815 				ptr = sp->sp_rend;
    816 			ptr -= 2;
    817 			SET(sp->sp_flags, STTYF_RING_OVERFLOW);
    818 			break;
    819 		}
    820 	}
    821 	STC_WRITE(sc, STC_EOSRR, 0);
    822 	if (cnt) {
    823 		*needsoftp = 1;
    824 		sp->sp_rput = ptr;
    825 	}
    826 	return (1);
    827 }
    828 
    829 int
    830 spif_stcintr_tx(sc, needsoftp)
    831 	struct spif_softc *sc;
    832 	int *needsoftp;
    833 {
    834 	struct stty_port *sp;
    835 	u_int8_t channel, ch;
    836 	int cnt = 0;
    837 
    838 	channel = CD180_GSCR_CHANNEL(STC_READ(sc, STC_GSCR1));
    839 	sp = &sc->sc_ttys->sc_port[channel];
    840 	if (!ISSET(sp->sp_flags, STTYF_STOP)) {
    841 		if (ISSET(sp->sp_flags, STTYF_SET_BREAK)) {
    842 			STC_WRITE(sc, STC_TDR, 0);
    843 			STC_WRITE(sc, STC_TDR, 0x81);
    844 			CLR(sp->sp_flags, STTYF_SET_BREAK);
    845 			cnt += 2;
    846 		}
    847 		if (ISSET(sp->sp_flags, STTYF_CLR_BREAK)) {
    848 			STC_WRITE(sc, STC_TDR, 0);
    849 			STC_WRITE(sc, STC_TDR, 0x83);
    850 			CLR(sp->sp_flags, STTYF_CLR_BREAK);
    851 			cnt += 2;
    852 		}
    853 
    854 		while (sp->sp_txc > 0 && cnt < (CD180_TX_FIFO_SIZE-1)) {
    855 			ch = *sp->sp_txp;
    856 			sp->sp_txc--;
    857 			sp->sp_txp++;
    858 
    859 			if (ch == 0) {
    860 				STC_WRITE(sc, STC_TDR, ch);
    861 				cnt++;
    862 			}
    863 			STC_WRITE(sc, STC_TDR, ch);
    864 			cnt++;
    865 		}
    866 	}
    867 
    868 	if (sp->sp_txc == 0 ||
    869 	    ISSET(sp->sp_flags, STTYF_STOP)) {
    870 		STC_WRITE(sc, STC_SRER, STC_READ(sc, STC_SRER) &
    871 		    (~CD180_SRER_TXD));
    872 		CLR(sp->sp_flags, STTYF_STOP);
    873 		SET(sp->sp_flags, STTYF_DONE);
    874 		*needsoftp = 1;
    875 	}
    876 
    877 	STC_WRITE(sc, STC_EOSRR, 0);
    878 
    879 	return (1);
    880 }
    881 
    882 int
    883 spif_stcintr_mx(sc, needsoftp)
    884 	struct spif_softc *sc;
    885 	int *needsoftp;
    886 {
    887 	struct stty_port *sp;
    888 	u_int8_t channel, mcr;
    889 
    890 	channel = CD180_GSCR_CHANNEL(STC_READ(sc, STC_GSCR1));
    891 	sp = &sc->sc_ttys->sc_port[channel];
    892 	mcr = STC_READ(sc, STC_MCR);
    893 	if (mcr & CD180_MCR_CD) {
    894 		SET(sp->sp_flags, STTYF_CDCHG);
    895 		*needsoftp = 1;
    896 	}
    897 	STC_WRITE(sc, STC_MCR, 0);
    898 	STC_WRITE(sc, STC_EOSRR, 0);
    899 	return (1);
    900 }
    901 
    902 int
    903 spif_stcintr(vsc)
    904 	void *vsc;
    905 {
    906 	struct spif_softc *sc = (struct spif_softc *)vsc;
    907 	int needsoft = 0, r = 0, i;
    908 	u_int8_t ar;
    909 
    910 	for (i = 0; i < 8; i++) {
    911 		ar = ISTC_READ(sc, STC_RRAR) & CD180_GSVR_IMASK;
    912 		if (ar == CD180_GSVR_RXGOOD)
    913 			r |= spif_stcintr_rx(sc, &needsoft);
    914 		else if (ar == CD180_GSVR_RXEXCEPTION)
    915 			r |= spif_stcintr_rxexception(sc, &needsoft);
    916 	}
    917 
    918 	for (i = 0; i < 8; i++) {
    919 		ar = ISTC_READ(sc, STC_TRAR) & CD180_GSVR_IMASK;
    920 		if (ar == CD180_GSVR_TXDATA)
    921 			r |= spif_stcintr_tx(sc, &needsoft);
    922 	}
    923 
    924 	for (i = 0; i < 8; i++) {
    925 		ar = ISTC_READ(sc, STC_MRAR) & CD180_GSVR_IMASK;
    926 		if (ar == CD180_GSVR_STATCHG)
    927 			r |= spif_stcintr_mx(sc, &needsoft);
    928 	}
    929 
    930 	if (needsoft)
    931 		softintr_schedule(sc->sc_softih);
    932 	return (r);
    933 }
    934 
    935 void
    936 spif_softintr(vsc)
    937 	void *vsc;
    938 {
    939 	struct spif_softc *sc = (struct spif_softc *)vsc;
    940 	struct stty_softc *stc = sc->sc_ttys;
    941 	int r = 0, i, data, s, flags;
    942 	u_int8_t stat, msvr;
    943 	struct stty_port *sp;
    944 	struct tty *tp;
    945 
    946 	if (stc != NULL) {
    947 		for (i = 0; i < stc->sc_nports; i++) {
    948 			sp = &stc->sc_port[i];
    949 			tp = sp->sp_tty;
    950 
    951 			if (!ISSET(tp->t_state, TS_ISOPEN))
    952 				continue;
    953 
    954 			while (sp->sp_rget != sp->sp_rput) {
    955 				stat = sp->sp_rget[0];
    956 				data = sp->sp_rget[1];
    957 				sp->sp_rget += 2;
    958 				if (sp->sp_rget == sp->sp_rend)
    959 					sp->sp_rget = sp->sp_rbuf;
    960 
    961 				if (stat & (CD180_RCSR_BE | CD180_RCSR_FE))
    962 					data |= TTY_FE;
    963 
    964 				if (stat & CD180_RCSR_PE)
    965 					data |= TTY_PE;
    966 
    967 				(*tp->t_linesw->l_rint)(data, tp);
    968 				r = 1;
    969 			}
    970 
    971 			s = splhigh();
    972 			flags = sp->sp_flags;
    973 			CLR(sp->sp_flags, STTYF_DONE | STTYF_CDCHG |
    974 			    STTYF_RING_OVERFLOW);
    975 			splx(s);
    976 
    977 			if (ISSET(flags, STTYF_CDCHG)) {
    978 				s = spltty();
    979 				STC_WRITE(sc, STC_CAR, i);
    980 				msvr = STC_READ(sc, STC_MSVR);
    981 				splx(s);
    982 
    983 				sp->sp_carrier = msvr & CD180_MSVR_CD;
    984 				(*tp->t_linesw->l_modem)(tp,
    985 				    sp->sp_carrier);
    986 				r = 1;
    987 			}
    988 
    989 			if (ISSET(flags, STTYF_RING_OVERFLOW)) {
    990 				log(LOG_WARNING, "%s-%x: ring overflow\n",
    991 					stc->sc_dev.dv_xname, i);
    992 				r = 1;
    993 			}
    994 
    995 			if (ISSET(flags, STTYF_DONE)) {
    996 				ndflush(&tp->t_outq,
    997 				    sp->sp_txp - tp->t_outq.c_cf);
    998 				CLR(tp->t_state, TS_BUSY);
    999 				(*tp->t_linesw->l_start)(tp);
   1000 				r = 1;
   1001 			}
   1002 		}
   1003 	}
   1004 }
   1005 
   1006 void
   1007 stty_write_ccr(sc, val)
   1008 	struct spif_softc *sc;
   1009 	u_int8_t val;
   1010 {
   1011 	int tries = 100000;
   1012 
   1013 	while (STC_READ(sc, STC_CCR) && tries--)
   1014 		/*EMPTY*/;
   1015 	if (tries == 0)
   1016 		printf("%s: ccr timeout\n", sc->sc_dev.dv_xname);
   1017 	STC_WRITE(sc, STC_CCR, val);
   1018 }
   1019 
   1020 int
   1021 stty_compute_baud(speed, clock, bprlp, bprhp)
   1022 	speed_t speed;
   1023 	int clock;
   1024 	u_int8_t *bprlp, *bprhp;
   1025 {
   1026 	u_int32_t rate;
   1027 
   1028 	rate = (2 * clock) / (16 * speed);
   1029 	if (rate & 1)
   1030 		rate = (rate >> 1) + 1;
   1031 	else
   1032 		rate = rate >> 1;
   1033 
   1034 	if (rate > 0xffff || rate == 0)
   1035 		return (1);
   1036 
   1037 	*bprlp = rate & 0xff;
   1038 	*bprhp = (rate >> 8) & 0xff;
   1039 	return (0);
   1040 }
   1041 
   1042 int
   1043 sbpp_match(parent, vcf, aux)
   1044 	struct device *parent;
   1045 	struct cfdata *vcf;
   1046 	void *aux;
   1047 {
   1048 	struct spif_softc *sc = (struct spif_softc *)parent;
   1049 
   1050 	return (aux == sbpp_match && sc->sc_bpps == NULL);
   1051 }
   1052 
   1053 void
   1054 sbpp_attach(parent, dev, aux)
   1055 	struct device *parent, *dev;
   1056 	void *aux;
   1057 {
   1058 	struct spif_softc *sc = (struct spif_softc *)parent;
   1059 	struct sbpp_softc *psc = (struct sbpp_softc *)dev;
   1060 	int port;
   1061 
   1062 	sc->sc_bpps = psc;
   1063 
   1064 	for (port = 0; port < sc->sc_npar; port++) {
   1065 	}
   1066 
   1067 	psc->sc_nports = port;
   1068 	printf(": %d port%s\n", port, port == 1 ? "" : "s");
   1069 }
   1070 
   1071 int
   1072 sbpp_open(dev, flags, mode, l)
   1073 	dev_t dev;
   1074 	int flags;
   1075 	int mode;
   1076 	struct lwp *l;
   1077 {
   1078 	return (ENXIO);
   1079 }
   1080 
   1081 int
   1082 sbpp_close(dev, flags, mode, l)
   1083 	dev_t dev;
   1084 	int flags;
   1085 	int mode;
   1086 	struct lwp *l;
   1087 {
   1088 	return (ENXIO);
   1089 }
   1090 
   1091 int
   1092 spif_ppcintr(v)
   1093 	void *v;
   1094 {
   1095 	return (0);
   1096 }
   1097 
   1098 int
   1099 sbpp_read(dev, uio, flags)
   1100 	dev_t dev;
   1101 	struct uio *uio;
   1102 	int flags;
   1103 {
   1104 	return (sbpp_rw(dev, uio));
   1105 }
   1106 
   1107 int
   1108 sbpp_write(dev, uio, flags)
   1109 	dev_t dev;
   1110 	struct uio *uio;
   1111 	int flags;
   1112 {
   1113 	return (sbpp_rw(dev, uio));
   1114 }
   1115 
   1116 int
   1117 sbpp_rw(dev, uio)
   1118 	dev_t dev;
   1119 	struct uio *uio;
   1120 {
   1121 	return (ENXIO);
   1122 }
   1123 
   1124 int
   1125 sbpp_poll(dev, events, l)
   1126 	dev_t dev;
   1127 	int events;
   1128 	struct lwp *l;
   1129 {
   1130 	return (seltrue(dev, events, l));
   1131 }
   1132 
   1133 int
   1134 sbpp_ioctl(dev, cmd, data, flags, l)
   1135 	dev_t dev;
   1136 	u_long cmd;
   1137 	caddr_t data;
   1138 	int flags;
   1139 	struct lwp *l;
   1140 {
   1141 	int error;
   1142 
   1143 	error = ENOTTY;
   1144 
   1145 	return (error);
   1146 }
   1147 
   1148 #endif /* NSPIF */
   1149