Home | History | Annotate | Line # | Download | only in sbus
spif.c revision 1.2
      1 /*	$NetBSD: spif.c,v 1.2 2005/02/27 00:27:48 perry 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.2 2005/02/27 00:27:48 perry 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, p)
    326 	dev_t dev;
    327 	int flags;
    328 	int mode;
    329 	struct proc *p;
    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) && p->p_ucred->cr_uid != 0) {
    388 		return (EBUSY);
    389 	} else {
    390 		s = spltty();
    391 	}
    392 
    393 	if (!ISSET(flags, O_NONBLOCK)) {
    394 		while (!ISSET(tp->t_cflag, CLOCAL) &&
    395 		    !ISSET(tp->t_state, TS_CARR_ON)) {
    396 			int error;
    397 			error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH,
    398 			    "sttycd", 0);
    399 			if (error != 0) {
    400 				splx(s);
    401 				return (error);
    402 			}
    403 		}
    404 	}
    405 
    406 	splx(s);
    407 
    408 	return ((*tp->t_linesw->l_open)(dev, tp));
    409 }
    410 
    411 int
    412 stty_close(dev, flags, mode, p)
    413 	dev_t dev;
    414 	int flags;
    415 	int mode;
    416 	struct proc *p;
    417 {
    418 	struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(dev)];
    419 	struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)];
    420 	struct spif_softc *csc = sp->sp_sc;
    421 	struct tty *tp = sp->sp_tty;
    422 	int port = SPIF_PORT(dev);
    423 	int s;
    424 
    425 	(*tp->t_linesw->l_close)(tp, flags);
    426 	s = spltty();
    427 
    428 	if (ISSET(tp->t_cflag, HUPCL) || !ISSET(tp->t_state, TS_ISOPEN)) {
    429 		stty_modem_control(sp, 0, DMSET);
    430 		STC_WRITE(csc, STC_CAR, port);
    431 		STC_WRITE(csc, STC_CCR,
    432 		    CD180_CCR_CMD_RESET|CD180_CCR_RESETCHAN);
    433 	}
    434 
    435 	splx(s);
    436 	ttyclose(tp);
    437 	return (0);
    438 }
    439 
    440 int
    441 stty_ioctl(dev, cmd, data, flags, p)
    442 	dev_t dev;
    443 	u_long cmd;
    444 	caddr_t data;
    445 	int flags;
    446 	struct proc *p;
    447 {
    448 	struct stty_softc *stc = stty_cd.cd_devs[SPIF_CARD(dev)];
    449 	struct stty_port *sp = &stc->sc_port[SPIF_PORT(dev)];
    450 	struct spif_softc *sc = sp->sp_sc;
    451 	struct tty *tp = sp->sp_tty;
    452 	int error;
    453 
    454 	error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flags, p);
    455 	if (error >= 0)
    456 		return (error);
    457 
    458 	error = ttioctl(tp, cmd, data, flags, p);
    459 	if (error >= 0)
    460 		return (error);
    461 
    462 	error = 0;
    463 
    464 	switch (cmd) {
    465 	case TIOCSBRK:
    466 		SET(sp->sp_flags, STTYF_SET_BREAK);
    467 		STC_WRITE(sc, STC_CAR, sp->sp_channel);
    468 		STC_WRITE(sc, STC_SRER,
    469 		    STC_READ(sc, STC_SRER) | CD180_SRER_TXD);
    470 		break;
    471 	case TIOCCBRK:
    472 		SET(sp->sp_flags, STTYF_CLR_BREAK);
    473 		STC_WRITE(sc, STC_CAR, sp->sp_channel);
    474 		STC_WRITE(sc, STC_SRER,
    475 		    STC_READ(sc, STC_SRER) | CD180_SRER_TXD);
    476 		break;
    477 	case TIOCSDTR:
    478 		stty_modem_control(sp, TIOCM_DTR, DMBIS);
    479 		break;
    480 	case TIOCCDTR:
    481 		stty_modem_control(sp, TIOCM_DTR, DMBIC);
    482 		break;
    483 	case TIOCMBIS:
    484 		stty_modem_control(sp, *((int *)data), DMBIS);
    485 		break;
    486 	case TIOCMBIC:
    487 		stty_modem_control(sp, *((int *)data), DMBIC);
    488 		break;
    489 	case TIOCMGET:
    490 		*((int *)data) = stty_modem_control(sp, 0, DMGET);
    491 		break;
    492 	case TIOCMSET:
    493 		stty_modem_control(sp, *((int *)data), DMSET);
    494 		break;
    495 	case TIOCGFLAGS:
    496 		*((int *)data) = sp->sp_openflags;
    497 		break;
    498 	case TIOCSFLAGS:
    499 		if( suser(p->p_ucred, &p->p_acflag) )
    500 			error = EPERM;
    501 		else
    502 			sp->sp_openflags = *((int *)data) &
    503 			    (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL |
    504 			     TIOCFLAG_CRTSCTS | TIOCFLAG_MDMBUF);
    505 		break;
    506 	default:
    507 		error = ENOTTY;
    508 	}
    509 
    510 	return (error);
    511 }
    512 
    513 int
    514 stty_modem_control(sp, bits, how)
    515 	struct stty_port *sp;
    516 	int bits, how;
    517 {
    518 	struct spif_softc *csc = sp->sp_sc;
    519 	struct tty *tp = sp->sp_tty;
    520 	int s, msvr;
    521 
    522 	s = spltty();
    523 	STC_WRITE(csc, STC_CAR, sp->sp_channel);
    524 
    525 	switch (how) {
    526 	case DMGET:
    527 		bits = TIOCM_LE;
    528 		if (DTR_READ(csc, sp->sp_channel))
    529 			bits |= TIOCM_DTR;
    530 		msvr = STC_READ(csc, STC_MSVR);
    531 		if (ISSET(msvr, CD180_MSVR_DSR))
    532 			bits |= TIOCM_DSR;
    533 		if (ISSET(msvr, CD180_MSVR_CD))
    534 			bits |= TIOCM_CD;
    535 		if (ISSET(msvr, CD180_MSVR_CTS))
    536 			bits |= TIOCM_CTS;
    537 		if (ISSET(msvr, CD180_MSVR_RTS))
    538 			bits |= TIOCM_RTS;
    539 		break;
    540 	case DMSET:
    541 		DTR_WRITE(csc, sp->sp_channel, ISSET(bits, TIOCM_DTR) ? 1 : 0);
    542 		if (ISSET(bits, TIOCM_RTS))
    543 			STC_WRITE(csc, STC_MSVR,
    544 			    STC_READ(csc, STC_MSVR) & (~CD180_MSVR_RTS));
    545 		else
    546 			STC_WRITE(csc, STC_MSVR,
    547 			    STC_READ(csc, STC_MSVR) | CD180_MSVR_RTS);
    548 		break;
    549 	case DMBIS:
    550 		if (ISSET(bits, TIOCM_DTR))
    551 			DTR_WRITE(csc, sp->sp_channel, 1);
    552 		if (ISSET(bits, TIOCM_RTS) && !ISSET(tp->t_cflag, CRTSCTS))
    553 			STC_WRITE(csc, STC_MSVR,
    554 			    STC_READ(csc, STC_MSVR) & (~CD180_MSVR_RTS));
    555 		break;
    556 	case DMBIC:
    557 		if (ISSET(bits, TIOCM_DTR))
    558 			DTR_WRITE(csc, sp->sp_channel, 0);
    559 		if (ISSET(bits, TIOCM_RTS))
    560 			STC_WRITE(csc, STC_MSVR,
    561 			    STC_READ(csc, STC_MSVR) | CD180_MSVR_RTS);
    562 		break;
    563 	}
    564 
    565 	splx(s);
    566 	return (bits);
    567 }
    568 
    569 int
    570 stty_param(tp, t)
    571 	struct tty *tp;
    572 	struct termios *t;
    573 {
    574 	struct stty_softc *st = stty_cd.cd_devs[SPIF_CARD(tp->t_dev)];
    575 	struct stty_port *sp = &st->sc_port[SPIF_PORT(tp->t_dev)];
    576 	struct spif_softc *sc = sp->sp_sc;
    577 	u_int8_t rbprl, rbprh, tbprl, tbprh;
    578 	int s, opt;
    579 
    580 	if (t->c_ospeed &&
    581 	    stty_compute_baud(t->c_ospeed, sc->sc_osc, &tbprl, &tbprh))
    582 		return (EINVAL);
    583 
    584 	if (t->c_ispeed &&
    585 	    stty_compute_baud(t->c_ispeed, sc->sc_osc, &rbprl, &rbprh))
    586 		return (EINVAL);
    587 
    588 	s = spltty();
    589 
    590 	/* hang up line if ospeed is zero, otherwise raise DTR */
    591 	stty_modem_control(sp, TIOCM_DTR,
    592 	    (t->c_ospeed == 0 ? DMBIC : DMBIS));
    593 
    594 	STC_WRITE(sc, STC_CAR, sp->sp_channel);
    595 
    596 	opt = 0;
    597 	if (ISSET(t->c_cflag, PARENB)) {
    598 		opt |= CD180_COR1_PARMODE_NORMAL;
    599 		opt |= (ISSET(t->c_cflag, PARODD) ?
    600 				CD180_COR1_ODDPAR :
    601 				CD180_COR1_EVENPAR);
    602 	}
    603 	else
    604 		opt |= CD180_COR1_PARMODE_NO;
    605 
    606 	if (!ISSET(t->c_iflag, INPCK))
    607 		opt |= CD180_COR1_IGNPAR;
    608 
    609 	if (ISSET(t->c_cflag, CSTOPB))
    610 		opt |= CD180_COR1_STOP2;
    611 
    612 	switch (t->c_cflag & CSIZE) {
    613 	case CS5:
    614 		opt |= CD180_COR1_CS5;
    615 		break;
    616 	case CS6:
    617 		opt |= CD180_COR1_CS6;
    618 		break;
    619 	case CS7:
    620 		opt |= CD180_COR1_CS7;
    621 		break;
    622 	default:
    623 		opt |= CD180_COR1_CS8;
    624 		break;
    625 	}
    626 	STC_WRITE(sc, STC_COR1, opt);
    627 	stty_write_ccr(sc, CD180_CCR_CMD_COR|CD180_CCR_CORCHG1);
    628 
    629 	opt = CD180_COR2_ETC;
    630 	if (ISSET(t->c_cflag, CRTSCTS))
    631 		opt |= CD180_COR2_CTSAE;
    632 	STC_WRITE(sc, STC_COR2, opt);
    633 	stty_write_ccr(sc, CD180_CCR_CMD_COR|CD180_CCR_CORCHG2);
    634 
    635 	STC_WRITE(sc, STC_COR3, STTY_RX_FIFO_THRESHOLD);
    636 	stty_write_ccr(sc, CD180_CCR_CMD_COR|CD180_CCR_CORCHG3);
    637 
    638 	STC_WRITE(sc, STC_SCHR1, 0x11);
    639 	STC_WRITE(sc, STC_SCHR2, 0x13);
    640 	STC_WRITE(sc, STC_SCHR3, 0x11);
    641 	STC_WRITE(sc, STC_SCHR4, 0x13);
    642 	STC_WRITE(sc, STC_RTPR, 0x12);
    643 
    644 	STC_WRITE(sc, STC_MCOR1, CD180_MCOR1_CDZD | STTY_RX_DTR_THRESHOLD);
    645 	STC_WRITE(sc, STC_MCOR2, CD180_MCOR2_CDOD);
    646 	STC_WRITE(sc, STC_MCR, 0);
    647 
    648 	if (t->c_ospeed) {
    649 		STC_WRITE(sc, STC_TBPRH, tbprh);
    650 		STC_WRITE(sc, STC_TBPRL, tbprl);
    651 	}
    652 
    653 	if (t->c_ispeed) {
    654 		STC_WRITE(sc, STC_RBPRH, rbprh);
    655 		STC_WRITE(sc, STC_RBPRL, rbprl);
    656 	}
    657 
    658 	stty_write_ccr(sc, CD180_CCR_CMD_CHAN |
    659 	    CD180_CCR_CHAN_TXEN | CD180_CCR_CHAN_RXEN);
    660 
    661 	sp->sp_carrier = STC_READ(sc, STC_MSVR) & CD180_MSVR_CD;
    662 
    663 	splx(s);
    664 	return (0);
    665 }
    666 
    667 int
    668 stty_read(dev, uio, flags)
    669 	dev_t dev;
    670 	struct uio *uio;
    671 	int flags;
    672 {
    673 	struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(dev)];
    674 	struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)];
    675 	struct tty *tp = sp->sp_tty;
    676 
    677 	return ((*tp->t_linesw->l_read)(tp, uio, flags));
    678 }
    679 
    680 int
    681 stty_write(dev, uio, flags)
    682 	dev_t dev;
    683 	struct uio *uio;
    684 	int flags;
    685 {
    686 	struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(dev)];
    687 	struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)];
    688 	struct tty *tp = sp->sp_tty;
    689 
    690 	return ((*tp->t_linesw->l_write)(tp, uio, flags));
    691 }
    692 
    693 int
    694 stty_poll(dev, events, p)
    695 	dev_t dev;
    696 	int events;
    697 	struct proc *p;
    698 {
    699 	struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(dev)];
    700 	struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)];
    701 	struct tty *tp = sp->sp_tty;
    702 
    703 	return ((*tp->t_linesw->l_poll)(tp, events, p));
    704 }
    705 
    706 struct tty *
    707 stty_tty(dev)
    708 	dev_t dev;
    709 {
    710 	struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(dev)];
    711 	struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)];
    712 
    713 	return (sp->sp_tty);
    714 }
    715 
    716 void
    717 stty_stop(tp, flags)
    718 	struct tty *tp;
    719 	int flags;
    720 {
    721 	struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(tp->t_dev)];
    722 	struct stty_port *sp = &sc->sc_port[SPIF_PORT(tp->t_dev)];
    723 	int s;
    724 
    725 	s = spltty();
    726 	if (ISSET(tp->t_state, TS_BUSY)) {
    727 		if (!ISSET(tp->t_state, TS_TTSTOP))
    728 			SET(tp->t_state, TS_FLUSH);
    729 		SET(sp->sp_flags, STTYF_STOP);
    730 	}
    731 	splx(s);
    732 }
    733 
    734 void
    735 stty_start(tp)
    736 	struct tty *tp;
    737 {
    738 	struct stty_softc *stc = stty_cd.cd_devs[SPIF_CARD(tp->t_dev)];
    739 	struct stty_port *sp = &stc->sc_port[SPIF_PORT(tp->t_dev)];
    740 	struct spif_softc *sc = sp->sp_sc;
    741 	int s;
    742 
    743 	s = spltty();
    744 
    745 	if (!ISSET(tp->t_state, TS_TTSTOP | TS_TIMEOUT | TS_BUSY)) {
    746 		if (tp->t_outq.c_cc <= tp->t_lowat) {
    747 			if (ISSET(tp->t_state, TS_ASLEEP)) {
    748 				CLR(tp->t_state, TS_ASLEEP);
    749 				wakeup(&tp->t_outq);
    750 			}
    751 			selwakeup(&tp->t_wsel);
    752 		}
    753 		if (tp->t_outq.c_cc) {
    754 			sp->sp_txc = ndqb(&tp->t_outq, 0);
    755 			sp->sp_txp = tp->t_outq.c_cf;
    756 			SET(tp->t_state, TS_BUSY);
    757 			STC_WRITE(sc, STC_CAR, sp->sp_channel);
    758 			STC_WRITE(sc, STC_SRER,
    759 			    STC_READ(sc, STC_SRER) | CD180_SRER_TXD);
    760 		}
    761 	}
    762 
    763 	splx(s);
    764 }
    765 
    766 int
    767 spif_stcintr_rxexception(sc, needsoftp)
    768 	struct spif_softc *sc;
    769 	int *needsoftp;
    770 {
    771 	struct stty_port *sp;
    772 	u_int8_t channel, *ptr;
    773 
    774 	channel = CD180_GSCR_CHANNEL(STC_READ(sc, STC_GSCR1));
    775 	sp = &sc->sc_ttys->sc_port[channel];
    776 	ptr = sp->sp_rput;
    777 	*ptr++ = STC_READ(sc, STC_RCSR);
    778 	*ptr++ = STC_READ(sc, STC_RDR);
    779 	if (ptr == sp->sp_rend)
    780 		ptr = sp->sp_rbuf;
    781 	if (ptr == sp->sp_rget) {
    782 		if (ptr == sp->sp_rbuf)
    783 			ptr = sp->sp_rend;
    784 		ptr -= 2;
    785 		SET(sp->sp_flags, STTYF_RING_OVERFLOW);
    786 	}
    787 	STC_WRITE(sc, STC_EOSRR, 0);
    788 	*needsoftp = 1;
    789 	sp->sp_rput = ptr;
    790 	return (1);
    791 }
    792 
    793 int
    794 spif_stcintr_rx(sc, needsoftp)
    795 	struct spif_softc *sc;
    796 	int *needsoftp;
    797 {
    798 	struct stty_port *sp;
    799 	u_int8_t channel, *ptr, cnt, rcsr;
    800 	int i;
    801 
    802 	channel = CD180_GSCR_CHANNEL(STC_READ(sc, STC_GSCR1));
    803 	sp = &sc->sc_ttys->sc_port[channel];
    804 	ptr = sp->sp_rput;
    805 	cnt = STC_READ(sc, STC_RDCR);
    806 	for (i = 0; i < cnt; i++) {
    807 		*ptr++ = 0;
    808 		rcsr = STC_READ(sc, STC_RCSR);
    809 		*ptr++ = STC_READ(sc, STC_RDR);
    810 		if (ptr == sp->sp_rend)
    811 			ptr = sp->sp_rbuf;
    812 		if (ptr == sp->sp_rget) {
    813 			if (ptr == sp->sp_rbuf)
    814 				ptr = sp->sp_rend;
    815 			ptr -= 2;
    816 			SET(sp->sp_flags, STTYF_RING_OVERFLOW);
    817 			break;
    818 		}
    819 	}
    820 	STC_WRITE(sc, STC_EOSRR, 0);
    821 	if (cnt) {
    822 		*needsoftp = 1;
    823 		sp->sp_rput = ptr;
    824 	}
    825 	return (1);
    826 }
    827 
    828 int
    829 spif_stcintr_tx(sc, needsoftp)
    830 	struct spif_softc *sc;
    831 	int *needsoftp;
    832 {
    833 	struct stty_port *sp;
    834 	u_int8_t channel, ch;
    835 	int cnt = 0;
    836 
    837 	channel = CD180_GSCR_CHANNEL(STC_READ(sc, STC_GSCR1));
    838 	sp = &sc->sc_ttys->sc_port[channel];
    839 	if (!ISSET(sp->sp_flags, STTYF_STOP)) {
    840 		if (ISSET(sp->sp_flags, STTYF_SET_BREAK)) {
    841 			STC_WRITE(sc, STC_TDR, 0);
    842 			STC_WRITE(sc, STC_TDR, 0x81);
    843 			CLR(sp->sp_flags, STTYF_SET_BREAK);
    844 			cnt += 2;
    845 		}
    846 		if (ISSET(sp->sp_flags, STTYF_CLR_BREAK)) {
    847 			STC_WRITE(sc, STC_TDR, 0);
    848 			STC_WRITE(sc, STC_TDR, 0x83);
    849 			CLR(sp->sp_flags, STTYF_CLR_BREAK);
    850 			cnt += 2;
    851 		}
    852 
    853 		while (sp->sp_txc > 0 && cnt < (CD180_TX_FIFO_SIZE-1)) {
    854 			ch = *sp->sp_txp;
    855 			sp->sp_txc--;
    856 			sp->sp_txp++;
    857 
    858 			if (ch == 0) {
    859 				STC_WRITE(sc, STC_TDR, ch);
    860 				cnt++;
    861 			}
    862 			STC_WRITE(sc, STC_TDR, ch);
    863 			cnt++;
    864 		}
    865 	}
    866 
    867 	if (sp->sp_txc == 0 ||
    868 	    ISSET(sp->sp_flags, STTYF_STOP)) {
    869 		STC_WRITE(sc, STC_SRER, STC_READ(sc, STC_SRER) &
    870 		    (~CD180_SRER_TXD));
    871 		CLR(sp->sp_flags, STTYF_STOP);
    872 		SET(sp->sp_flags, STTYF_DONE);
    873 		*needsoftp = 1;
    874 	}
    875 
    876 	STC_WRITE(sc, STC_EOSRR, 0);
    877 
    878 	return (1);
    879 }
    880 
    881 int
    882 spif_stcintr_mx(sc, needsoftp)
    883 	struct spif_softc *sc;
    884 	int *needsoftp;
    885 {
    886 	struct stty_port *sp;
    887 	u_int8_t channel, mcr;
    888 
    889 	channel = CD180_GSCR_CHANNEL(STC_READ(sc, STC_GSCR1));
    890 	sp = &sc->sc_ttys->sc_port[channel];
    891 	mcr = STC_READ(sc, STC_MCR);
    892 	if (mcr & CD180_MCR_CD) {
    893 		SET(sp->sp_flags, STTYF_CDCHG);
    894 		*needsoftp = 1;
    895 	}
    896 	STC_WRITE(sc, STC_MCR, 0);
    897 	STC_WRITE(sc, STC_EOSRR, 0);
    898 	return (1);
    899 }
    900 
    901 int
    902 spif_stcintr(vsc)
    903 	void *vsc;
    904 {
    905 	struct spif_softc *sc = (struct spif_softc *)vsc;
    906 	int needsoft = 0, r = 0, i;
    907 	u_int8_t ar;
    908 
    909 	for (i = 0; i < 8; i++) {
    910 		ar = ISTC_READ(sc, STC_RRAR) & CD180_GSVR_IMASK;
    911 		if (ar == CD180_GSVR_RXGOOD)
    912 			r |= spif_stcintr_rx(sc, &needsoft);
    913 		else if (ar == CD180_GSVR_RXEXCEPTION)
    914 			r |= spif_stcintr_rxexception(sc, &needsoft);
    915 	}
    916 
    917 	for (i = 0; i < 8; i++) {
    918 		ar = ISTC_READ(sc, STC_TRAR) & CD180_GSVR_IMASK;
    919 		if (ar == CD180_GSVR_TXDATA)
    920 			r |= spif_stcintr_tx(sc, &needsoft);
    921 	}
    922 
    923 	for (i = 0; i < 8; i++) {
    924 		ar = ISTC_READ(sc, STC_MRAR) & CD180_GSVR_IMASK;
    925 		if (ar == CD180_GSVR_STATCHG)
    926 			r |= spif_stcintr_mx(sc, &needsoft);
    927 	}
    928 
    929 	if (needsoft)
    930 		softintr_schedule(sc->sc_softih);
    931 	return (r);
    932 }
    933 
    934 void
    935 spif_softintr(vsc)
    936 	void *vsc;
    937 {
    938 	struct spif_softc *sc = (struct spif_softc *)vsc;
    939 	struct stty_softc *stc = sc->sc_ttys;
    940 	int r = 0, i, data, s, flags;
    941 	u_int8_t stat, msvr;
    942 	struct stty_port *sp;
    943 	struct tty *tp;
    944 
    945 	if (stc != NULL) {
    946 		for (i = 0; i < stc->sc_nports; i++) {
    947 			sp = &stc->sc_port[i];
    948 			tp = sp->sp_tty;
    949 
    950 			if (!ISSET(tp->t_state, TS_ISOPEN))
    951 				continue;
    952 
    953 			while (sp->sp_rget != sp->sp_rput) {
    954 				stat = sp->sp_rget[0];
    955 				data = sp->sp_rget[1];
    956 				sp->sp_rget += 2;
    957 				if (sp->sp_rget == sp->sp_rend)
    958 					sp->sp_rget = sp->sp_rbuf;
    959 
    960 				if (stat & (CD180_RCSR_BE | CD180_RCSR_FE))
    961 					data |= TTY_FE;
    962 
    963 				if (stat & CD180_RCSR_PE)
    964 					data |= TTY_PE;
    965 
    966 				(*tp->t_linesw->l_rint)(data, tp);
    967 				r = 1;
    968 			}
    969 
    970 			s = splhigh();
    971 			flags = sp->sp_flags;
    972 			CLR(sp->sp_flags, STTYF_DONE | STTYF_CDCHG |
    973 			    STTYF_RING_OVERFLOW);
    974 			splx(s);
    975 
    976 			if (ISSET(flags, STTYF_CDCHG)) {
    977 				s = spltty();
    978 				STC_WRITE(sc, STC_CAR, i);
    979 				msvr = STC_READ(sc, STC_MSVR);
    980 				splx(s);
    981 
    982 				sp->sp_carrier = msvr & CD180_MSVR_CD;
    983 				(*tp->t_linesw->l_modem)(tp,
    984 				    sp->sp_carrier);
    985 				r = 1;
    986 			}
    987 
    988 			if (ISSET(flags, STTYF_RING_OVERFLOW)) {
    989 				log(LOG_WARNING, "%s-%x: ring overflow\n",
    990 					stc->sc_dev.dv_xname, i);
    991 				r = 1;
    992 			}
    993 
    994 			if (ISSET(flags, STTYF_DONE)) {
    995 				ndflush(&tp->t_outq,
    996 				    sp->sp_txp - tp->t_outq.c_cf);
    997 				CLR(tp->t_state, TS_BUSY);
    998 				(*tp->t_linesw->l_start)(tp);
    999 				r = 1;
   1000 			}
   1001 		}
   1002 	}
   1003 }
   1004 
   1005 void
   1006 stty_write_ccr(sc, val)
   1007 	struct spif_softc *sc;
   1008 	u_int8_t val;
   1009 {
   1010 	int tries = 100000;
   1011 
   1012 	while (STC_READ(sc, STC_CCR) && tries--)
   1013 		/*EMPTY*/;
   1014 	if (tries == 0)
   1015 		printf("%s: ccr timeout\n", sc->sc_dev.dv_xname);
   1016 	STC_WRITE(sc, STC_CCR, val);
   1017 }
   1018 
   1019 int
   1020 stty_compute_baud(speed, clock, bprlp, bprhp)
   1021 	speed_t speed;
   1022 	int clock;
   1023 	u_int8_t *bprlp, *bprhp;
   1024 {
   1025 	u_int32_t rate;
   1026 
   1027 	rate = (2 * clock) / (16 * speed);
   1028 	if (rate & 1)
   1029 		rate = (rate >> 1) + 1;
   1030 	else
   1031 		rate = rate >> 1;
   1032 
   1033 	if (rate > 0xffff || rate == 0)
   1034 		return (1);
   1035 
   1036 	*bprlp = rate & 0xff;
   1037 	*bprhp = (rate >> 8) & 0xff;
   1038 	return (0);
   1039 }
   1040 
   1041 int
   1042 sbpp_match(parent, vcf, aux)
   1043 	struct device *parent;
   1044 	struct cfdata *vcf;
   1045 	void *aux;
   1046 {
   1047 	struct spif_softc *sc = (struct spif_softc *)parent;
   1048 
   1049 	return (aux == sbpp_match && sc->sc_bpps == NULL);
   1050 }
   1051 
   1052 void
   1053 sbpp_attach(parent, dev, aux)
   1054 	struct device *parent, *dev;
   1055 	void *aux;
   1056 {
   1057 	struct spif_softc *sc = (struct spif_softc *)parent;
   1058 	struct sbpp_softc *psc = (struct sbpp_softc *)dev;
   1059 	int port;
   1060 
   1061 	sc->sc_bpps = psc;
   1062 
   1063 	for (port = 0; port < sc->sc_npar; port++) {
   1064 	}
   1065 
   1066 	psc->sc_nports = port;
   1067 	printf(": %d port%s\n", port, port == 1 ? "" : "s");
   1068 }
   1069 
   1070 int
   1071 sbpp_open(dev, flags, mode, p)
   1072 	dev_t dev;
   1073 	int flags;
   1074 	int mode;
   1075 	struct proc *p;
   1076 {
   1077 	return (ENXIO);
   1078 }
   1079 
   1080 int
   1081 sbpp_close(dev, flags, mode, p)
   1082 	dev_t dev;
   1083 	int flags;
   1084 	int mode;
   1085 	struct proc *p;
   1086 {
   1087 	return (ENXIO);
   1088 }
   1089 
   1090 int
   1091 spif_ppcintr(v)
   1092 	void *v;
   1093 {
   1094 	return (0);
   1095 }
   1096 
   1097 int
   1098 sbpp_read(dev, uio, flags)
   1099 	dev_t dev;
   1100 	struct uio *uio;
   1101 	int flags;
   1102 {
   1103 	return (sbpp_rw(dev, uio));
   1104 }
   1105 
   1106 int
   1107 sbpp_write(dev, uio, flags)
   1108 	dev_t dev;
   1109 	struct uio *uio;
   1110 	int flags;
   1111 {
   1112 	return (sbpp_rw(dev, uio));
   1113 }
   1114 
   1115 int
   1116 sbpp_rw(dev, uio)
   1117 	dev_t dev;
   1118 	struct uio *uio;
   1119 {
   1120 	return (ENXIO);
   1121 }
   1122 
   1123 int
   1124 sbpp_poll(dev, events, p)
   1125 	dev_t dev;
   1126 	int events;
   1127 	struct proc *p;
   1128 {
   1129 	return (seltrue(dev, events, p));
   1130 }
   1131 
   1132 int
   1133 sbpp_ioctl(dev, cmd, data, flags, p)
   1134 	dev_t dev;
   1135 	u_long cmd;
   1136 	caddr_t data;
   1137 	int flags;
   1138 	struct proc *p;
   1139 {
   1140 	int error;
   1141 
   1142 	error = ENOTTY;
   1143 
   1144 	return (error);
   1145 }
   1146 
   1147 #endif /* NSPIF */
   1148