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