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