xref: /openbsd/sys/dev/sbus/spif.c (revision 4bdff4be)
1 /*	$OpenBSD: spif.c,v 1.27 2022/07/02 08:50:42 visa 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	sbppkqfilter(dev_t, struct knote *);
94 int	sbppioctl(dev_t, u_long, caddr_t, int, struct proc *);
95 
96 const struct cfattach spif_ca = {
97 	sizeof (struct spif_softc), spifmatch, spifattach
98 };
99 
100 struct cfdriver spif_cd = {
101 	NULL, "spif", DV_DULL
102 };
103 
104 const struct cfattach stty_ca = {
105 	sizeof(struct stty_softc), sttymatch, sttyattach
106 };
107 
108 struct cfdriver stty_cd = {
109 	NULL, "stty", DV_TTY
110 };
111 
112 const struct cfattach sbpp_ca = {
113 	sizeof(struct sbpp_softc), sbppmatch, sbppattach
114 };
115 
116 struct cfdriver sbpp_cd = {
117 	NULL, "sbpp", DV_DULL
118 };
119 
120 /* normal STC access */
121 #define	STC_WRITE(sc,r,v)	\
122     bus_space_write_1((sc)->sc_bustag, (sc)->sc_stch, (r), (v))
123 #define	STC_READ(sc,r)		\
124     bus_space_read_1((sc)->sc_bustag, (sc)->sc_stch, (r))
125 
126 /* IACK STC access */
127 #define	ISTC_WRITE(sc,r,v)	\
128     bus_space_write_1((sc)->sc_bustag, (sc)->sc_istch, (r), (v))
129 #define	ISTC_READ(sc,r)		\
130     bus_space_read_1((sc)->sc_bustag, (sc)->sc_istch, (r))
131 
132 /* PPC access */
133 #define	PPC_WRITE(sc,r,v)	\
134     bus_space_write_1((sc)->sc_bustag, (sc)->sc_ppch, (r), (v))
135 #define	PPC_READ(sc,r)		\
136     bus_space_read_1((sc)->sc_bustag, (sc)->sc_ppch, (r))
137 
138 #define	DTR_WRITE(sc,port,v)						\
139     do {								\
140 	sc->sc_ttys->sc_port[(port)].sp_dtr = v;			\
141 	bus_space_write_1((sc)->sc_bustag,				\
142 	    sc->sc_dtrh, port, (v == 0) ? 1 : 0);			\
143     } while (0)
144 
145 #define	DTR_READ(sc,port)	((sc)->sc_ttys->sc_port[(port)].sp_dtr)
146 
147 int
148 spifmatch(struct device *parent, void *vcf, void *aux)
149 {
150 	struct cfdata *cf = vcf;
151 	struct sbus_attach_args *sa = aux;
152 
153 	if (strcmp(cf->cf_driver->cd_name, sa->sa_name) &&
154 	    strcmp("SUNW,spif", sa->sa_name))
155 		return (0);
156 	return (1);
157 }
158 
159 void
160 spifattach(struct device *parent, struct device *self, void *aux)
161 {
162 	struct spif_softc *sc = (struct spif_softc *)self;
163 	struct sbus_attach_args *sa = aux;
164 
165 	if (sa->sa_nintr != 2) {
166 		printf(": expected %d interrupts, got %d\n", 2, sa->sa_nintr);
167 		return;
168 	}
169 
170 	if (sa->sa_nreg != 1) {
171 		printf(": expected %d registers, got %d\n", 1, sa->sa_nreg);
172 		return;
173 	}
174 
175 	sc->sc_bustag = sa->sa_bustag;
176 	if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot,
177 	    sa->sa_reg[0].sbr_offset, sa->sa_reg[0].sbr_size,
178 	    0, 0, &sc->sc_regh) != 0) {
179 		printf(": can't map registers\n");
180 		return;
181 	}
182 
183 	if (bus_space_subregion(sc->sc_bustag, sc->sc_regh,
184 	    DTR_REG_OFFSET, DTR_REG_LEN, &sc->sc_dtrh) != 0) {
185 		printf(": can't map dtr regs\n");
186 		goto fail_unmapregs;
187 	}
188 
189 	if (bus_space_subregion(sc->sc_bustag, sc->sc_regh,
190 	    STC_REG_OFFSET, STC_REG_LEN, &sc->sc_stch) != 0) {
191 		printf(": can't map dtr regs\n");
192 		goto fail_unmapregs;
193 	}
194 
195 	if (bus_space_subregion(sc->sc_bustag, sc->sc_regh,
196 	    ISTC_REG_OFFSET, ISTC_REG_LEN, &sc->sc_istch) != 0) {
197 		printf(": can't map dtr regs\n");
198 		goto fail_unmapregs;
199 	}
200 
201 	if (bus_space_subregion(sc->sc_bustag, sc->sc_regh,
202 	    PPC_REG_OFFSET, PPC_REG_LEN, &sc->sc_ppch) != 0) {
203 		printf(": can't map dtr regs\n");
204 		goto fail_unmapregs;
205 	}
206 
207 	sc->sc_ppcih = bus_intr_establish(sa->sa_bustag,
208 	    sa->sa_intr[PARALLEL_INTR].sbi_pri, IPL_TTY, 0, spifppcintr, sc,
209 	    self->dv_xname);
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].sbi_pri, IPL_TTY, 0, spifstcintr, sc,
217 	    self->dv_xname);
218 	if (sc->sc_stcih == NULL) {
219 		printf(": failed to establish stc interrupt\n");
220 		goto fail_unmapregs;
221 	}
222 
223 	sc->sc_softih = softintr_establish(IPL_TTY, spifsoftintr, sc);
224 	if (sc->sc_softih == NULL) {
225 		printf(": can't get soft intr\n");
226 		goto fail_unmapregs;
227 	}
228 
229 	sc->sc_node = sa->sa_node;
230 
231 	sc->sc_rev = getpropint(sc->sc_node, "revlev", 0);
232 
233 	sc->sc_osc = getpropint(sc->sc_node, "verosc", 0);
234 	switch (sc->sc_osc) {
235 	case SPIF_OSC10:
236 		sc->sc_osc = 10000000;
237 		break;
238 	case SPIF_OSC9:
239 	default:
240 		sc->sc_osc = 9830400;
241 		break;
242 	}
243 
244 	sc->sc_nser = 8;
245 	sc->sc_npar = 1;
246 
247 	sc->sc_rev2 = STC_READ(sc, STC_GFRCR);
248 	STC_WRITE(sc, STC_GSVR, 0);
249 
250 	stty_write_ccr(sc, CD180_CCR_CMD_RESET | CD180_CCR_RESETALL);
251 	while (STC_READ(sc, STC_GSVR) != 0xff);
252 	while (STC_READ(sc, STC_GFRCR) != sc->sc_rev2);
253 
254 	STC_WRITE(sc, STC_PPRH, CD180_PPRH);
255 	STC_WRITE(sc, STC_PPRL, CD180_PPRL);
256 	STC_WRITE(sc, STC_MSMR, SPIF_MSMR);
257 	STC_WRITE(sc, STC_TSMR, SPIF_TSMR);
258 	STC_WRITE(sc, STC_RSMR, SPIF_RSMR);
259 	STC_WRITE(sc, STC_GSVR, 0);
260 	STC_WRITE(sc, STC_GSCR1, 0);
261 	STC_WRITE(sc, STC_GSCR2, 0);
262 	STC_WRITE(sc, STC_GSCR3, 0);
263 
264 	printf(": rev %x chiprev %x osc %sMHz\n",
265 	    sc->sc_rev, sc->sc_rev2, clockfreq(sc->sc_osc));
266 
267 	(void)config_found(self, sttymatch, NULL);
268 	(void)config_found(self, sbppmatch, NULL);
269 
270 	return;
271 
272 fail_unmapregs:
273 	bus_space_unmap(sa->sa_bustag, sc->sc_regh, sa->sa_reg[0].sbr_size);
274 }
275 
276 int
277 sttymatch(struct device *parent, void *vcf, void *aux)
278 {
279 	struct spif_softc *sc = (struct spif_softc *)parent;
280 
281 	return (aux == sttymatch && sc->sc_ttys == NULL);
282 }
283 
284 void
285 sttyattach(struct device *parent, struct device *dev, void *aux)
286 {
287 	struct spif_softc *sc = (struct spif_softc *)parent;
288 	struct stty_softc *ssc = (struct stty_softc *)dev;
289 	int port;
290 
291 	sc->sc_ttys = ssc;
292 
293 	for (port = 0; port < sc->sc_nser; port++) {
294 		struct stty_port *sp = &ssc->sc_port[port];
295 		struct tty *tp;
296 
297 		DTR_WRITE(sc, port, 0);
298 
299 		tp = ttymalloc(0);
300 
301 		tp->t_oproc = stty_start;
302 		tp->t_param = stty_param;
303 
304 		sp->sp_tty = tp;
305 		sp->sp_sc = sc;
306 		sp->sp_channel = port;
307 
308 		sp->sp_rbuf = malloc(STTY_RBUF_SIZE, M_DEVBUF, M_NOWAIT);
309 		if(sp->sp_rbuf == NULL)
310 			break;
311 
312 		sp->sp_rend = sp->sp_rbuf + STTY_RBUF_SIZE;
313 	}
314 
315 	ssc->sc_nports = port;
316 
317 	printf(": %d tty%s\n", port, port == 1 ? "" : "s");
318 }
319 
320 int
321 sttyopen(dev_t dev, int flags, int mode, struct proc *p)
322 {
323 	struct spif_softc *csc;
324 	struct stty_softc *sc;
325 	struct stty_port *sp;
326 	struct tty *tp;
327 	int card = SPIF_CARD(dev);
328 	int port = SPIF_PORT(dev);
329 	int s;
330 
331 	if (card >= stty_cd.cd_ndevs || card >= spif_cd.cd_ndevs)
332 		return (ENXIO);
333 
334 	sc = stty_cd.cd_devs[card];
335 	csc = spif_cd.cd_devs[card];
336 	if (sc == NULL || csc == NULL)
337 		return (ENXIO);
338 
339 	if (port >= sc->sc_nports)
340 		return (ENXIO);
341 
342 	sp = &sc->sc_port[port];
343 	tp = sp->sp_tty;
344 	tp->t_dev = dev;
345 
346 	if (!ISSET(tp->t_state, TS_ISOPEN)) {
347 		SET(tp->t_state, TS_WOPEN);
348 
349 		ttychars(tp);
350 		tp->t_iflag = TTYDEF_IFLAG;
351 		tp->t_oflag = TTYDEF_OFLAG;
352 		tp->t_cflag = TTYDEF_CFLAG;
353 		if (ISSET(sp->sp_openflags, TIOCFLAG_CLOCAL))
354 			SET(tp->t_cflag, CLOCAL);
355 		if (ISSET(sp->sp_openflags, TIOCFLAG_CRTSCTS))
356 			SET(tp->t_cflag, CRTSCTS);
357 		if (ISSET(sp->sp_openflags, TIOCFLAG_MDMBUF))
358 			SET(tp->t_cflag, MDMBUF);
359 		tp->t_lflag = TTYDEF_LFLAG;
360 		tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
361 
362 		sp->sp_rput = sp->sp_rget = sp->sp_rbuf;
363 
364 		s = spltty();
365 
366 		STC_WRITE(csc, STC_CAR, sp->sp_channel);
367 		stty_write_ccr(csc, CD180_CCR_CMD_RESET|CD180_CCR_RESETCHAN);
368 		STC_WRITE(csc, STC_CAR, sp->sp_channel);
369 
370 		stty_param(tp, &tp->t_termios);
371 
372 		ttsetwater(tp);
373 
374 		STC_WRITE(csc, STC_SRER, CD180_SRER_CD | CD180_SRER_RXD);
375 
376 		if (ISSET(sp->sp_openflags, TIOCFLAG_SOFTCAR) || sp->sp_carrier)
377 			SET(tp->t_state, TS_CARR_ON);
378 		else
379 			CLR(tp->t_state, TS_CARR_ON);
380 	}
381 	else if (ISSET(tp->t_state, TS_XCLUDE) && suser(p) != 0) {
382 		return (EBUSY);
383 	} else {
384 		s = spltty();
385 	}
386 
387 	if (!ISSET(flags, O_NONBLOCK)) {
388 		while (!ISSET(tp->t_cflag, CLOCAL) &&
389 		    !ISSET(tp->t_state, TS_CARR_ON)) {
390 			int error;
391 
392 			SET(tp->t_state, TS_WOPEN);
393 			error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH,
394 			    ttopen);
395 			if (error != 0) {
396 				splx(s);
397 				CLR(tp->t_state, TS_WOPEN);
398 				return (error);
399 			}
400 		}
401 	}
402 
403 	splx(s);
404 
405 	return ((*linesw[tp->t_line].l_open)(dev, tp, p));
406 }
407 
408 int
409 sttyclose(dev_t dev, int flags, int mode, struct proc *p)
410 {
411 	struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(dev)];
412 	struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)];
413 	struct spif_softc *csc = sp->sp_sc;
414 	struct tty *tp = sp->sp_tty;
415 	int port = SPIF_PORT(dev);
416 	int s;
417 
418 	(*linesw[tp->t_line].l_close)(tp, flags, p);
419 	s = spltty();
420 
421 	if (ISSET(tp->t_cflag, HUPCL) || !ISSET(tp->t_state, TS_ISOPEN)) {
422 		stty_modem_control(sp, 0, DMSET);
423 		STC_WRITE(csc, STC_CAR, port);
424 		STC_WRITE(csc, STC_CCR,
425 		    CD180_CCR_CMD_RESET|CD180_CCR_RESETCHAN);
426 	}
427 
428 	splx(s);
429 	ttyclose(tp);
430 	return (0);
431 }
432 
433 int
434 sttyioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p)
435 {
436 	struct stty_softc *stc = stty_cd.cd_devs[SPIF_CARD(dev)];
437 	struct stty_port *sp = &stc->sc_port[SPIF_PORT(dev)];
438 	struct spif_softc *sc = sp->sp_sc;
439 	struct tty *tp = sp->sp_tty;
440 	int error;
441 
442 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flags, p);
443 	if (error >= 0)
444 		return (error);
445 
446 	error = ttioctl(tp, cmd, data, flags, p);
447 	if (error >= 0)
448 		return (error);
449 
450 	error = 0;
451 
452 	switch (cmd) {
453 	case TIOCSBRK:
454 		SET(sp->sp_flags, STTYF_SET_BREAK);
455 		STC_WRITE(sc, STC_CAR, sp->sp_channel);
456 		STC_WRITE(sc, STC_SRER,
457 		    STC_READ(sc, STC_SRER) | CD180_SRER_TXD);
458 		break;
459 	case TIOCCBRK:
460 		SET(sp->sp_flags, STTYF_CLR_BREAK);
461 		STC_WRITE(sc, STC_CAR, sp->sp_channel);
462 		STC_WRITE(sc, STC_SRER,
463 		    STC_READ(sc, STC_SRER) | CD180_SRER_TXD);
464 		break;
465 	case TIOCSDTR:
466 		stty_modem_control(sp, TIOCM_DTR, DMBIS);
467 		break;
468 	case TIOCCDTR:
469 		stty_modem_control(sp, TIOCM_DTR, DMBIC);
470 		break;
471 	case TIOCMBIS:
472 		stty_modem_control(sp, *((int *)data), DMBIS);
473 		break;
474 	case TIOCMBIC:
475 		stty_modem_control(sp, *((int *)data), DMBIC);
476 		break;
477 	case TIOCMGET:
478 		*((int *)data) = stty_modem_control(sp, 0, DMGET);
479 		break;
480 	case TIOCMSET:
481 		stty_modem_control(sp, *((int *)data), DMSET);
482 		break;
483 	case TIOCGFLAGS:
484 		*((int *)data) = sp->sp_openflags;
485 		break;
486 	case TIOCSFLAGS:
487 		if (suser(p))
488 			error = EPERM;
489 		else
490 			sp->sp_openflags = *((int *)data) &
491 			    (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL |
492 			     TIOCFLAG_CRTSCTS | TIOCFLAG_MDMBUF);
493 		break;
494 	default:
495 		error = ENOTTY;
496 	}
497 
498 	return (error);
499 }
500 
501 int
502 stty_modem_control(struct stty_port *sp, int bits, int how)
503 {
504 	struct spif_softc *csc = sp->sp_sc;
505 	struct tty *tp = sp->sp_tty;
506 	int s, msvr;
507 
508 	s = spltty();
509 	STC_WRITE(csc, STC_CAR, sp->sp_channel);
510 
511 	switch (how) {
512 	case DMGET:
513 		bits = TIOCM_LE;
514 		if (DTR_READ(csc, sp->sp_channel))
515 			bits |= TIOCM_DTR;
516 		msvr = STC_READ(csc, STC_MSVR);
517 		if (ISSET(msvr, CD180_MSVR_DSR))
518 			bits |= TIOCM_DSR;
519 		if (ISSET(msvr, CD180_MSVR_CD))
520 			bits |= TIOCM_CD;
521 		if (ISSET(msvr, CD180_MSVR_CTS))
522 			bits |= TIOCM_CTS;
523 		if (ISSET(msvr, CD180_MSVR_RTS))
524 			bits |= TIOCM_RTS;
525 		break;
526 	case DMSET:
527 		DTR_WRITE(csc, sp->sp_channel, ISSET(bits, TIOCM_DTR) ? 1 : 0);
528 		if (ISSET(bits, TIOCM_RTS))
529 			STC_WRITE(csc, STC_MSVR,
530 			    STC_READ(csc, STC_MSVR) & (~CD180_MSVR_RTS));
531 		else
532 			STC_WRITE(csc, STC_MSVR,
533 			    STC_READ(csc, STC_MSVR) | CD180_MSVR_RTS);
534 		break;
535 	case DMBIS:
536 		if (ISSET(bits, TIOCM_DTR))
537 			DTR_WRITE(csc, sp->sp_channel, 1);
538 		if (ISSET(bits, TIOCM_RTS) && !ISSET(tp->t_cflag, CRTSCTS))
539 			STC_WRITE(csc, STC_MSVR,
540 			    STC_READ(csc, STC_MSVR) & (~CD180_MSVR_RTS));
541 		break;
542 	case DMBIC:
543 		if (ISSET(bits, TIOCM_DTR))
544 			DTR_WRITE(csc, sp->sp_channel, 0);
545 		if (ISSET(bits, TIOCM_RTS))
546 			STC_WRITE(csc, STC_MSVR,
547 			    STC_READ(csc, STC_MSVR) | CD180_MSVR_RTS);
548 		break;
549 	}
550 
551 	splx(s);
552 	return (bits);
553 }
554 
555 int
556 stty_param(struct tty *tp, struct termios *t)
557 {
558 	struct stty_softc *st = stty_cd.cd_devs[SPIF_CARD(tp->t_dev)];
559 	struct stty_port *sp = &st->sc_port[SPIF_PORT(tp->t_dev)];
560 	struct spif_softc *sc = sp->sp_sc;
561 	u_int8_t rbprl, rbprh, tbprl, tbprh;
562 	int s, opt;
563 
564 	if (t->c_ospeed &&
565 	    stty_compute_baud(t->c_ospeed, sc->sc_osc, &tbprl, &tbprh))
566 		return (EINVAL);
567 
568 	if (t->c_ispeed &&
569 	    stty_compute_baud(t->c_ispeed, sc->sc_osc, &rbprl, &rbprh))
570 		return (EINVAL);
571 
572 	s = spltty();
573 
574 	/* hang up line if ospeed is zero, otherwise raise DTR */
575 	stty_modem_control(sp, TIOCM_DTR,
576 	    (t->c_ospeed == 0 ? DMBIC : DMBIS));
577 
578 	STC_WRITE(sc, STC_CAR, sp->sp_channel);
579 
580 	opt = 0;
581 	if (ISSET(t->c_cflag, PARENB)) {
582 		opt |= CD180_COR1_PARMODE_NORMAL;
583 		opt |= (ISSET(t->c_cflag, PARODD) ?
584 				CD180_COR1_ODDPAR :
585 				CD180_COR1_EVENPAR);
586 	}
587 	else
588 		opt |= CD180_COR1_PARMODE_NO;
589 
590 	if (!ISSET(t->c_iflag, INPCK))
591 		opt |= CD180_COR1_IGNPAR;
592 
593 	if (ISSET(t->c_cflag, CSTOPB))
594 		opt |= CD180_COR1_STOP2;
595 
596 	switch (t->c_cflag & CSIZE) {
597 	case CS5:
598 		opt |= CD180_COR1_CS5;
599 		break;
600 	case CS6:
601 		opt |= CD180_COR1_CS6;
602 		break;
603 	case CS7:
604 		opt |= CD180_COR1_CS7;
605 		break;
606 	default:
607 		opt |= CD180_COR1_CS8;
608 		break;
609 	}
610 	STC_WRITE(sc, STC_COR1, opt);
611 	stty_write_ccr(sc, CD180_CCR_CMD_COR|CD180_CCR_CORCHG1);
612 
613 	opt = CD180_COR2_ETC;
614 	if (ISSET(t->c_cflag, CRTSCTS))
615 		opt |= CD180_COR2_CTSAE;
616 	STC_WRITE(sc, STC_COR2, opt);
617 	stty_write_ccr(sc, CD180_CCR_CMD_COR|CD180_CCR_CORCHG2);
618 
619 	STC_WRITE(sc, STC_COR3, STTY_RX_FIFO_THRESHOLD);
620 	stty_write_ccr(sc, CD180_CCR_CMD_COR|CD180_CCR_CORCHG3);
621 
622 	STC_WRITE(sc, STC_SCHR1, 0x11);
623 	STC_WRITE(sc, STC_SCHR2, 0x13);
624 	STC_WRITE(sc, STC_SCHR3, 0x11);
625 	STC_WRITE(sc, STC_SCHR4, 0x13);
626 	STC_WRITE(sc, STC_RTPR, 0x12);
627 
628 	STC_WRITE(sc, STC_MCOR1, CD180_MCOR1_CDZD | STTY_RX_DTR_THRESHOLD);
629 	STC_WRITE(sc, STC_MCOR2, CD180_MCOR2_CDOD);
630 	STC_WRITE(sc, STC_MCR, 0);
631 
632 	if (t->c_ospeed) {
633 		STC_WRITE(sc, STC_TBPRH, tbprh);
634 		STC_WRITE(sc, STC_TBPRL, tbprl);
635 	}
636 
637 	if (t->c_ispeed) {
638 		STC_WRITE(sc, STC_RBPRH, rbprh);
639 		STC_WRITE(sc, STC_RBPRL, rbprl);
640 	}
641 
642 	stty_write_ccr(sc, CD180_CCR_CMD_CHAN |
643 	    CD180_CCR_CHAN_TXEN | CD180_CCR_CHAN_RXEN);
644 
645 	sp->sp_carrier = STC_READ(sc, STC_MSVR) & CD180_MSVR_CD;
646 
647 	splx(s);
648 	return (0);
649 }
650 
651 int
652 sttyread(dev_t dev, struct uio *uio, int flags)
653 {
654 	struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(dev)];
655 	struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)];
656 	struct tty *tp = sp->sp_tty;
657 
658 	return ((*linesw[tp->t_line].l_read)(tp, uio, flags));
659 }
660 
661 int
662 sttywrite(dev_t dev, struct uio *uio, int flags)
663 {
664 	struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(dev)];
665 	struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)];
666 	struct tty *tp = sp->sp_tty;
667 
668 	return ((*linesw[tp->t_line].l_write)(tp, uio, flags));
669 }
670 
671 struct tty *
672 sttytty(dev_t dev)
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 
677 	return (sp->sp_tty);
678 }
679 
680 int
681 sttystop(struct tty *tp, int flags)
682 {
683 	struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(tp->t_dev)];
684 	struct stty_port *sp = &sc->sc_port[SPIF_PORT(tp->t_dev)];
685 	int s;
686 
687 	s = spltty();
688 	if (ISSET(tp->t_state, TS_BUSY)) {
689 		if (!ISSET(tp->t_state, TS_TTSTOP))
690 			SET(tp->t_state, TS_FLUSH);
691 		SET(sp->sp_flags, STTYF_STOP);
692 	}
693 	splx(s);
694 	return (0);
695 }
696 
697 void
698 stty_start(struct tty *tp)
699 {
700 	struct stty_softc *stc = stty_cd.cd_devs[SPIF_CARD(tp->t_dev)];
701 	struct stty_port *sp = &stc->sc_port[SPIF_PORT(tp->t_dev)];
702 	struct spif_softc *sc = sp->sp_sc;
703 	int s;
704 
705 	s = spltty();
706 
707 	if (!ISSET(tp->t_state, TS_TTSTOP | TS_TIMEOUT | TS_BUSY)) {
708 		ttwakeupwr(tp);
709 		if (tp->t_outq.c_cc) {
710 			sp->sp_txc = ndqb(&tp->t_outq, 0);
711 			sp->sp_txp = tp->t_outq.c_cf;
712 			SET(tp->t_state, TS_BUSY);
713 			STC_WRITE(sc, STC_CAR, sp->sp_channel);
714 			STC_WRITE(sc, STC_SRER,
715 			    STC_READ(sc, STC_SRER) | CD180_SRER_TXD);
716 		}
717 	}
718 
719 	splx(s);
720 }
721 
722 int
723 spifstcintr_rxexception(struct spif_softc *sc, int *needsoftp)
724 {
725 	struct stty_port *sp;
726 	u_int8_t channel, *ptr;
727 
728 	channel = CD180_GSCR_CHANNEL(STC_READ(sc, STC_GSCR1));
729 	sp = &sc->sc_ttys->sc_port[channel];
730 	ptr = sp->sp_rput;
731 	*ptr++ = STC_READ(sc, STC_RCSR);
732 	*ptr++ = STC_READ(sc, STC_RDR);
733 	if (ptr == sp->sp_rend)
734 		ptr = sp->sp_rbuf;
735 	if (ptr == sp->sp_rget) {
736 		if (ptr == sp->sp_rbuf)
737 			ptr = sp->sp_rend;
738 		ptr -= 2;
739 		SET(sp->sp_flags, STTYF_RING_OVERFLOW);
740 	}
741 	STC_WRITE(sc, STC_EOSRR, 0);
742 	*needsoftp = 1;
743 	sp->sp_rput = ptr;
744 	return (1);
745 }
746 
747 int
748 spifstcintr_rx(struct spif_softc *sc, int *needsoftp)
749 {
750 	struct stty_port *sp;
751 	u_int8_t channel, *ptr, cnt, rcsr;
752 	int i;
753 
754 	channel = CD180_GSCR_CHANNEL(STC_READ(sc, STC_GSCR1));
755 	sp = &sc->sc_ttys->sc_port[channel];
756 	ptr = sp->sp_rput;
757 	cnt = STC_READ(sc, STC_RDCR);
758 	for (i = 0; i < cnt; i++) {
759 		*ptr++ = 0;
760 		rcsr = STC_READ(sc, STC_RCSR);
761 		*ptr++ = STC_READ(sc, STC_RDR);
762 		if (ptr == sp->sp_rend)
763 			ptr = sp->sp_rbuf;
764 		if (ptr == sp->sp_rget) {
765 			if (ptr == sp->sp_rbuf)
766 				ptr = sp->sp_rend;
767 			ptr -= 2;
768 			SET(sp->sp_flags, STTYF_RING_OVERFLOW);
769 			break;
770 		}
771 	}
772 	STC_WRITE(sc, STC_EOSRR, 0);
773 	if (cnt) {
774 		*needsoftp = 1;
775 		sp->sp_rput = ptr;
776 	}
777 	return (1);
778 }
779 
780 int
781 spifstcintr_tx(struct spif_softc *sc, int *needsoftp)
782 {
783 	struct stty_port *sp;
784 	u_int8_t channel, ch;
785 	int cnt = 0;
786 
787 	channel = CD180_GSCR_CHANNEL(STC_READ(sc, STC_GSCR1));
788 	sp = &sc->sc_ttys->sc_port[channel];
789 	if (!ISSET(sp->sp_flags, STTYF_STOP)) {
790 		if (ISSET(sp->sp_flags, STTYF_SET_BREAK)) {
791 			STC_WRITE(sc, STC_TDR, 0);
792 			STC_WRITE(sc, STC_TDR, 0x81);
793 			CLR(sp->sp_flags, STTYF_SET_BREAK);
794 			cnt += 2;
795 		}
796 		if (ISSET(sp->sp_flags, STTYF_CLR_BREAK)) {
797 			STC_WRITE(sc, STC_TDR, 0);
798 			STC_WRITE(sc, STC_TDR, 0x83);
799 			CLR(sp->sp_flags, STTYF_CLR_BREAK);
800 			cnt += 2;
801 		}
802 
803 		while (sp->sp_txc > 0 && cnt < (CD180_TX_FIFO_SIZE-1)) {
804 			ch = *sp->sp_txp;
805 			sp->sp_txc--;
806 			sp->sp_txp++;
807 
808 			if (ch == 0) {
809 				STC_WRITE(sc, STC_TDR, ch);
810 				cnt++;
811 			}
812 			STC_WRITE(sc, STC_TDR, ch);
813 			cnt++;
814 		}
815 	}
816 
817 	if (sp->sp_txc == 0 ||
818 	    ISSET(sp->sp_flags, STTYF_STOP)) {
819 		STC_WRITE(sc, STC_SRER, STC_READ(sc, STC_SRER) &
820 		    (~CD180_SRER_TXD));
821 		CLR(sp->sp_flags, STTYF_STOP);
822 		SET(sp->sp_flags, STTYF_DONE);
823 		*needsoftp = 1;
824 	}
825 
826 	STC_WRITE(sc, STC_EOSRR, 0);
827 
828 	return (1);
829 }
830 
831 int
832 spifstcintr_mx(struct spif_softc *sc, int *needsoftp)
833 {
834 	struct stty_port *sp;
835 	u_int8_t channel, mcr;
836 
837 	channel = CD180_GSCR_CHANNEL(STC_READ(sc, STC_GSCR1));
838 	sp = &sc->sc_ttys->sc_port[channel];
839 	mcr = STC_READ(sc, STC_MCR);
840 	if (mcr & CD180_MCR_CD) {
841 		SET(sp->sp_flags, STTYF_CDCHG);
842 		*needsoftp = 1;
843 	}
844 	STC_WRITE(sc, STC_MCR, 0);
845 	STC_WRITE(sc, STC_EOSRR, 0);
846 	return (1);
847 }
848 
849 int
850 spifstcintr(void *vsc)
851 {
852 	struct spif_softc *sc = (struct spif_softc *)vsc;
853 	int needsoft = 0, r = 0, i;
854 	u_int8_t ar;
855 
856 	for (i = 0; i < 8; i++) {
857 		ar = ISTC_READ(sc, STC_RRAR) & CD180_GSVR_IMASK;
858 		if (ar == CD180_GSVR_RXGOOD)
859 			r |= spifstcintr_rx(sc, &needsoft);
860 		else if (ar == CD180_GSVR_RXEXCEPTION)
861 			r |= spifstcintr_rxexception(sc, &needsoft);
862 	}
863 
864 	for (i = 0; i < 8; i++) {
865 		ar = ISTC_READ(sc, STC_TRAR) & CD180_GSVR_IMASK;
866 		if (ar == CD180_GSVR_TXDATA)
867 			r |= spifstcintr_tx(sc, &needsoft);
868 	}
869 
870 	for (i = 0; i < 8; i++) {
871 		ar = ISTC_READ(sc, STC_MRAR) & CD180_GSVR_IMASK;
872 		if (ar == CD180_GSVR_STATCHG)
873 			r |= spifstcintr_mx(sc, &needsoft);
874 	}
875 
876 	if (needsoft)
877 		softintr_schedule(sc->sc_softih);
878 	return (r);
879 }
880 
881 void
882 spifsoftintr(void *vsc)
883 {
884 	struct spif_softc *sc = (struct spif_softc *)vsc;
885 	struct stty_softc *stc = sc->sc_ttys;
886 	int r = 0, i, data, s, flags;
887 	u_int8_t stat, msvr;
888 	struct stty_port *sp;
889 	struct tty *tp;
890 
891 	if (stc != NULL) {
892 		for (i = 0; i < stc->sc_nports; i++) {
893 			sp = &stc->sc_port[i];
894 			tp = sp->sp_tty;
895 
896 			if (!ISSET(tp->t_state, TS_ISOPEN))
897 				continue;
898 
899 			while (sp->sp_rget != sp->sp_rput) {
900 				stat = sp->sp_rget[0];
901 				data = sp->sp_rget[1];
902 				sp->sp_rget += 2;
903 				if (sp->sp_rget == sp->sp_rend)
904 					sp->sp_rget = sp->sp_rbuf;
905 
906 				if (stat & (CD180_RCSR_BE | CD180_RCSR_FE))
907 					data |= TTY_FE;
908 
909 				if (stat & CD180_RCSR_PE)
910 					data |= TTY_PE;
911 
912 				(*linesw[tp->t_line].l_rint)(data, tp);
913 				r = 1;
914 			}
915 
916 			s = splhigh();
917 			flags = sp->sp_flags;
918 			CLR(sp->sp_flags, STTYF_DONE | STTYF_CDCHG |
919 			    STTYF_RING_OVERFLOW);
920 			splx(s);
921 
922 			if (ISSET(flags, STTYF_CDCHG)) {
923 				s = spltty();
924 				STC_WRITE(sc, STC_CAR, i);
925 				msvr = STC_READ(sc, STC_MSVR);
926 				splx(s);
927 
928 				sp->sp_carrier = msvr & CD180_MSVR_CD;
929 				(*linesw[tp->t_line].l_modem)(tp,
930 				    sp->sp_carrier);
931 				r = 1;
932 			}
933 
934 			if (ISSET(flags, STTYF_RING_OVERFLOW)) {
935 				log(LOG_WARNING, "%s-%x: ring overflow\n",
936 					stc->sc_dev.dv_xname, i);
937 				r = 1;
938 			}
939 
940 			if (ISSET(flags, STTYF_DONE)) {
941 				ndflush(&tp->t_outq,
942 				    sp->sp_txp - tp->t_outq.c_cf);
943 				CLR(tp->t_state, TS_BUSY);
944 				(*linesw[tp->t_line].l_start)(tp);
945 				r = 1;
946 			}
947 		}
948 	}
949 }
950 
951 void
952 stty_write_ccr(struct spif_softc *sc, u_int8_t val)
953 {
954 	int tries = 100000;
955 
956 	while (STC_READ(sc, STC_CCR) && tries--)
957 		/*EMPTY*/;
958 	if (tries == 0)
959 		printf("%s: ccr timeout\n", sc->sc_dev.dv_xname);
960 	STC_WRITE(sc, STC_CCR, val);
961 }
962 
963 int
964 stty_compute_baud(speed_t speed, int clock, u_int8_t *bprlp, u_int8_t *bprhp)
965 {
966 	u_int32_t rate;
967 
968 	rate = (2 * clock) / (16 * speed);
969 	if (rate & 1)
970 		rate = (rate >> 1) + 1;
971 	else
972 		rate = rate >> 1;
973 
974 	if (rate > 0xffff || rate == 0)
975 		return (1);
976 
977 	*bprlp = rate & 0xff;
978 	*bprhp = (rate >> 8) & 0xff;
979 	return (0);
980 }
981 
982 int
983 sbppmatch(struct device *parent, void *vcf, void *aux)
984 {
985 	struct spif_softc *sc = (struct spif_softc *)parent;
986 
987 	return (aux == sbppmatch && sc->sc_bpps == NULL);
988 }
989 
990 void
991 sbppattach(struct device *parent, struct device *dev, void *aux)
992 {
993 	struct spif_softc *sc = (struct spif_softc *)parent;
994 	struct sbpp_softc *psc = (struct sbpp_softc *)dev;
995 	int port;
996 
997 	sc->sc_bpps = psc;
998 
999 	for (port = 0; port < sc->sc_npar; port++) {
1000 	}
1001 
1002 	psc->sc_nports = port;
1003 	printf(": %d port%s\n", port, port == 1 ? "" : "s");
1004 }
1005 
1006 int
1007 sbppopen(dev_t dev, int flags, int mode, struct proc *p)
1008 {
1009 	return (ENXIO);
1010 }
1011 
1012 int
1013 sbppclose(dev_t dev, int flags, int mode, struct proc *p)
1014 {
1015 	return (ENXIO);
1016 }
1017 
1018 int
1019 spifppcintr(void *v)
1020 {
1021 	return (0);
1022 }
1023 
1024 int
1025 sbppread(dev_t dev, struct uio *uio, int flags)
1026 {
1027 	return (sbpp_rw(dev, uio));
1028 }
1029 
1030 int
1031 sbppwrite(dev_t dev, struct uio *uio, int flags)
1032 {
1033 	return (sbpp_rw(dev, uio));
1034 }
1035 
1036 int
1037 sbpp_rw(dev_t dev, struct uio *uio)
1038 {
1039 	return (ENXIO);
1040 }
1041 
1042 int
1043 sbppkqfilter(dev_t dev, struct knote *kn)
1044 {
1045 	return (seltrue_kqfilter(dev, kn));
1046 }
1047 
1048 int
1049 sbppioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p)
1050 {
1051 	int error;
1052 
1053 	error = ENOTTY;
1054 
1055 	return (error);
1056 }
1057