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