xref: /openbsd-src/sys/dev/sbus/spif.c (revision a28daedfc357b214be5c701aa8ba8adb29a7f1c2)
1 /*	$OpenBSD: spif.c,v 1.13 2006/03/04 13:00:55 miod 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();
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) && p->p_ucred->cr_uid != 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));
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);
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 		if (tp->t_outq.c_cc <= tp->t_lowat) {
744 			if (ISSET(tp->t_state, TS_ASLEEP)) {
745 				CLR(tp->t_state, TS_ASLEEP);
746 				wakeup(&tp->t_outq);
747 			}
748 			selwakeup(&tp->t_wsel);
749 		}
750 		if (tp->t_outq.c_cc) {
751 			sp->sp_txc = ndqb(&tp->t_outq, 0);
752 			sp->sp_txp = tp->t_outq.c_cf;
753 			SET(tp->t_state, TS_BUSY);
754 			STC_WRITE(sc, STC_CAR, sp->sp_channel);
755 			STC_WRITE(sc, STC_SRER,
756 			    STC_READ(sc, STC_SRER) | CD180_SRER_TXD);
757 		}
758 	}
759 
760 	splx(s);
761 }
762 
763 int
764 spifstcintr_rxexception(sc, needsoftp)
765 	struct spif_softc *sc;
766 	int *needsoftp;
767 {
768 	struct stty_port *sp;
769 	u_int8_t channel, *ptr;
770 
771 	channel = CD180_GSCR_CHANNEL(STC_READ(sc, STC_GSCR1));
772 	sp = &sc->sc_ttys->sc_port[channel];
773 	ptr = sp->sp_rput;
774 	*ptr++ = STC_READ(sc, STC_RCSR);
775 	*ptr++ = STC_READ(sc, STC_RDR);
776 	if (ptr == sp->sp_rend)
777 		ptr = sp->sp_rbuf;
778 	if (ptr == sp->sp_rget) {
779 		if (ptr == sp->sp_rbuf)
780 			ptr = sp->sp_rend;
781 		ptr -= 2;
782 		SET(sp->sp_flags, STTYF_RING_OVERFLOW);
783 	}
784 	STC_WRITE(sc, STC_EOSRR, 0);
785 	*needsoftp = 1;
786 	sp->sp_rput = ptr;
787 	return (1);
788 }
789 
790 int
791 spifstcintr_rx(sc, needsoftp)
792 	struct spif_softc *sc;
793 	int *needsoftp;
794 {
795 	struct stty_port *sp;
796 	u_int8_t channel, *ptr, cnt, rcsr;
797 	int i;
798 
799 	channel = CD180_GSCR_CHANNEL(STC_READ(sc, STC_GSCR1));
800 	sp = &sc->sc_ttys->sc_port[channel];
801 	ptr = sp->sp_rput;
802 	cnt = STC_READ(sc, STC_RDCR);
803 	for (i = 0; i < cnt; i++) {
804 		*ptr++ = 0;
805 		rcsr = STC_READ(sc, STC_RCSR);
806 		*ptr++ = STC_READ(sc, STC_RDR);
807 		if (ptr == sp->sp_rend)
808 			ptr = sp->sp_rbuf;
809 		if (ptr == sp->sp_rget) {
810 			if (ptr == sp->sp_rbuf)
811 				ptr = sp->sp_rend;
812 			ptr -= 2;
813 			SET(sp->sp_flags, STTYF_RING_OVERFLOW);
814 			break;
815 		}
816 	}
817 	STC_WRITE(sc, STC_EOSRR, 0);
818 	if (cnt) {
819 		*needsoftp = 1;
820 		sp->sp_rput = ptr;
821 	}
822 	return (1);
823 }
824 
825 int
826 spifstcintr_tx(sc, needsoftp)
827 	struct spif_softc *sc;
828 	int *needsoftp;
829 {
830 	struct stty_port *sp;
831 	u_int8_t channel, ch;
832 	int cnt = 0;
833 
834 	channel = CD180_GSCR_CHANNEL(STC_READ(sc, STC_GSCR1));
835 	sp = &sc->sc_ttys->sc_port[channel];
836 	if (!ISSET(sp->sp_flags, STTYF_STOP)) {
837 		if (ISSET(sp->sp_flags, STTYF_SET_BREAK)) {
838 			STC_WRITE(sc, STC_TDR, 0);
839 			STC_WRITE(sc, STC_TDR, 0x81);
840 			CLR(sp->sp_flags, STTYF_SET_BREAK);
841 			cnt += 2;
842 		}
843 		if (ISSET(sp->sp_flags, STTYF_CLR_BREAK)) {
844 			STC_WRITE(sc, STC_TDR, 0);
845 			STC_WRITE(sc, STC_TDR, 0x83);
846 			CLR(sp->sp_flags, STTYF_CLR_BREAK);
847 			cnt += 2;
848 		}
849 
850 		while (sp->sp_txc > 0 && cnt < (CD180_TX_FIFO_SIZE-1)) {
851 			ch = *sp->sp_txp;
852 			sp->sp_txc--;
853 			sp->sp_txp++;
854 
855 			if (ch == 0) {
856 				STC_WRITE(sc, STC_TDR, ch);
857 				cnt++;
858 			}
859 			STC_WRITE(sc, STC_TDR, ch);
860 			cnt++;
861 		}
862 	}
863 
864 	if (sp->sp_txc == 0 ||
865 	    ISSET(sp->sp_flags, STTYF_STOP)) {
866 		STC_WRITE(sc, STC_SRER, STC_READ(sc, STC_SRER) &
867 		    (~CD180_SRER_TXD));
868 		CLR(sp->sp_flags, STTYF_STOP);
869 		SET(sp->sp_flags, STTYF_DONE);
870 		*needsoftp = 1;
871 	}
872 
873 	STC_WRITE(sc, STC_EOSRR, 0);
874 
875 	return (1);
876 }
877 
878 int
879 spifstcintr_mx(sc, needsoftp)
880 	struct spif_softc *sc;
881 	int *needsoftp;
882 {
883 	struct stty_port *sp;
884 	u_int8_t channel, mcr;
885 
886 	channel = CD180_GSCR_CHANNEL(STC_READ(sc, STC_GSCR1));
887 	sp = &sc->sc_ttys->sc_port[channel];
888 	mcr = STC_READ(sc, STC_MCR);
889 	if (mcr & CD180_MCR_CD) {
890 		SET(sp->sp_flags, STTYF_CDCHG);
891 		*needsoftp = 1;
892 	}
893 	STC_WRITE(sc, STC_MCR, 0);
894 	STC_WRITE(sc, STC_EOSRR, 0);
895 	return (1);
896 }
897 
898 int
899 spifstcintr(vsc)
900 	void *vsc;
901 {
902 	struct spif_softc *sc = (struct spif_softc *)vsc;
903 	int needsoft = 0, r = 0, i;
904 	u_int8_t ar;
905 
906 	for (i = 0; i < 8; i++) {
907 		ar = ISTC_READ(sc, STC_RRAR) & CD180_GSVR_IMASK;
908 		if (ar == CD180_GSVR_RXGOOD)
909 			r |= spifstcintr_rx(sc, &needsoft);
910 		else if (ar == CD180_GSVR_RXEXCEPTION)
911 			r |= spifstcintr_rxexception(sc, &needsoft);
912 	}
913 
914 	for (i = 0; i < 8; i++) {
915 		ar = ISTC_READ(sc, STC_TRAR) & CD180_GSVR_IMASK;
916 		if (ar == CD180_GSVR_TXDATA)
917 			r |= spifstcintr_tx(sc, &needsoft);
918 	}
919 
920 	for (i = 0; i < 8; i++) {
921 		ar = ISTC_READ(sc, STC_MRAR) & CD180_GSVR_IMASK;
922 		if (ar == CD180_GSVR_STATCHG)
923 			r |= spifstcintr_mx(sc, &needsoft);
924 	}
925 
926 	if (needsoft)
927 		softintr_schedule(sc->sc_softih);
928 	return (r);
929 }
930 
931 void
932 spifsoftintr(vsc)
933 	void *vsc;
934 {
935 	struct spif_softc *sc = (struct spif_softc *)vsc;
936 	struct stty_softc *stc = sc->sc_ttys;
937 	int r = 0, i, data, s, flags;
938 	u_int8_t stat, msvr;
939 	struct stty_port *sp;
940 	struct tty *tp;
941 
942 	if (stc != NULL) {
943 		for (i = 0; i < stc->sc_nports; i++) {
944 			sp = &stc->sc_port[i];
945 			tp = sp->sp_tty;
946 
947 			if (!ISSET(tp->t_state, TS_ISOPEN))
948 				continue;
949 
950 			while (sp->sp_rget != sp->sp_rput) {
951 				stat = sp->sp_rget[0];
952 				data = sp->sp_rget[1];
953 				sp->sp_rget += 2;
954 				if (sp->sp_rget == sp->sp_rend)
955 					sp->sp_rget = sp->sp_rbuf;
956 
957 				if (stat & (CD180_RCSR_BE | CD180_RCSR_FE))
958 					data |= TTY_FE;
959 
960 				if (stat & CD180_RCSR_PE)
961 					data |= TTY_PE;
962 
963 				(*linesw[tp->t_line].l_rint)(data, tp);
964 				r = 1;
965 			}
966 
967 			s = splhigh();
968 			flags = sp->sp_flags;
969 			CLR(sp->sp_flags, STTYF_DONE | STTYF_CDCHG |
970 			    STTYF_RING_OVERFLOW);
971 			splx(s);
972 
973 			if (ISSET(flags, STTYF_CDCHG)) {
974 				s = spltty();
975 				STC_WRITE(sc, STC_CAR, i);
976 				msvr = STC_READ(sc, STC_MSVR);
977 				splx(s);
978 
979 				sp->sp_carrier = msvr & CD180_MSVR_CD;
980 				(*linesw[tp->t_line].l_modem)(tp,
981 				    sp->sp_carrier);
982 				r = 1;
983 			}
984 
985 			if (ISSET(flags, STTYF_RING_OVERFLOW)) {
986 				log(LOG_WARNING, "%s-%x: ring overflow\n",
987 					stc->sc_dev.dv_xname, i);
988 				r = 1;
989 			}
990 
991 			if (ISSET(flags, STTYF_DONE)) {
992 				ndflush(&tp->t_outq,
993 				    sp->sp_txp - tp->t_outq.c_cf);
994 				CLR(tp->t_state, TS_BUSY);
995 				(*linesw[tp->t_line].l_start)(tp);
996 				r = 1;
997 			}
998 		}
999 	}
1000 }
1001 
1002 void
1003 stty_write_ccr(sc, val)
1004 	struct spif_softc *sc;
1005 	u_int8_t val;
1006 {
1007 	int tries = 100000;
1008 
1009 	while (STC_READ(sc, STC_CCR) && tries--)
1010 		/*EMPTY*/;
1011 	if (tries == 0)
1012 		printf("%s: ccr timeout\n", sc->sc_dev.dv_xname);
1013 	STC_WRITE(sc, STC_CCR, val);
1014 }
1015 
1016 int
1017 stty_compute_baud(speed, clock, bprlp, bprhp)
1018 	speed_t speed;
1019 	int clock;
1020 	u_int8_t *bprlp, *bprhp;
1021 {
1022 	u_int32_t rate;
1023 
1024 	rate = (2 * clock) / (16 * speed);
1025 	if (rate & 1)
1026 		rate = (rate >> 1) + 1;
1027 	else
1028 		rate = rate >> 1;
1029 
1030 	if (rate > 0xffff || rate == 0)
1031 		return (1);
1032 
1033 	*bprlp = rate & 0xff;
1034 	*bprhp = (rate >> 8) & 0xff;
1035 	return (0);
1036 }
1037 
1038 int
1039 sbppmatch(parent, vcf, aux)
1040 	struct device *parent;
1041 	void *vcf, *aux;
1042 {
1043 	struct spif_softc *sc = (struct spif_softc *)parent;
1044 
1045 	return (aux == sbppmatch && sc->sc_bpps == NULL);
1046 }
1047 
1048 void
1049 sbppattach(parent, dev, aux)
1050 	struct device *parent, *dev;
1051 	void *aux;
1052 {
1053 	struct spif_softc *sc = (struct spif_softc *)parent;
1054 	struct sbpp_softc *psc = (struct sbpp_softc *)dev;
1055 	int port;
1056 
1057 	sc->sc_bpps = psc;
1058 
1059 	for (port = 0; port < sc->sc_npar; port++) {
1060 	}
1061 
1062 	psc->sc_nports = port;
1063 	printf(": %d port%s\n", port, port == 1 ? "" : "s");
1064 }
1065 
1066 int
1067 sbppopen(dev, flags, mode, p)
1068 	dev_t dev;
1069 	int flags;
1070 	int mode;
1071 	struct proc *p;
1072 {
1073 	return (ENXIO);
1074 }
1075 
1076 int
1077 sbppclose(dev, flags, mode, p)
1078 	dev_t dev;
1079 	int flags;
1080 	int mode;
1081 	struct proc *p;
1082 {
1083 	return (ENXIO);
1084 }
1085 
1086 int
1087 spifppcintr(v)
1088 	void *v;
1089 {
1090 	return (0);
1091 }
1092 
1093 int
1094 sbppread(dev, uio, flags)
1095 	dev_t dev;
1096 	struct uio *uio;
1097 	int flags;
1098 {
1099 	return (sbpp_rw(dev, uio));
1100 }
1101 
1102 int
1103 sbppwrite(dev, uio, flags)
1104 	dev_t dev;
1105 	struct uio *uio;
1106 	int flags;
1107 {
1108 	return (sbpp_rw(dev, uio));
1109 }
1110 
1111 int
1112 sbpp_rw(dev, uio)
1113 	dev_t dev;
1114 	struct uio *uio;
1115 {
1116 	return (ENXIO);
1117 }
1118 
1119 int
1120 sbpppoll(dev, events, p)
1121 	dev_t dev;
1122 	int events;
1123 	struct proc *p;
1124 {
1125 	return (seltrue(dev, events, p));
1126 }
1127 
1128 int
1129 sbppioctl(dev, cmd, data, flags, p)
1130 	dev_t dev;
1131 	u_long cmd;
1132 	caddr_t data;
1133 	int flags;
1134 	struct proc *p;
1135 {
1136 	int error;
1137 
1138 	error = ENOTTY;
1139 
1140 	return (error);
1141 }
1142