xref: /netbsd-src/sys/arch/sparc64/dev/sab.c (revision 4b896b232495b7a9b8b94a1cf1e21873296d53b8)
1 /*	$NetBSD: sab.c,v 1.16 2004/03/21 15:08:24 pk Exp $	*/
2 /*	$OpenBSD: sab.c,v 1.7 2002/04/08 17:49:42 jason Exp $	*/
3 
4 /*
5  * Copyright (c) 2001 Jason L. Wright (jason@thought.net)
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *	This product includes software developed by Jason L. Wright
19  * 4. The name of the author may not be used to endorse or promote products
20  *    derived from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
26  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
30  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  * Effort sponsored in part by the Defense Advanced Research Projects
35  * Agency (DARPA) and Air Force Research Laboratory, Air Force
36  * Materiel Command, USAF, under agreement number F30602-01-2-0537.
37  *
38  */
39 
40 /*
41  * SAB82532 Dual UART driver
42  */
43 
44 #include <sys/cdefs.h>
45 __KERNEL_RCSID(0, "$NetBSD: sab.c,v 1.16 2004/03/21 15:08:24 pk Exp $");
46 
47 #include <sys/types.h>
48 #include <sys/param.h>
49 #include <sys/systm.h>
50 #include <sys/device.h>
51 #include <sys/conf.h>
52 #include <sys/file.h>
53 #include <sys/ioctl.h>
54 #include <sys/kernel.h>
55 #include <sys/proc.h>
56 #include <sys/tty.h>
57 #include <sys/syslog.h>
58 
59 #include <machine/autoconf.h>
60 #include <machine/openfirm.h>
61 
62 #include <dev/cons.h>
63 
64 #include <dev/ebus/ebusreg.h>
65 #include <dev/ebus/ebusvar.h>
66 #include <sparc64/dev/sab82532reg.h>
67 
68 #define SABUNIT(x)		(minor(x) & 0x7ffff)
69 #define SABDIALOUT(x)		(minor(x) & 0x80000)
70 
71 #define	SABTTY_RBUF_SIZE	1024	/* must be divisible by 2 */
72 
73 struct sab_softc {
74 	struct device		sc_dv;
75 	struct intrhand *	sc_ih;
76 	bus_space_tag_t		sc_bt;
77 	bus_space_handle_t	sc_bh;
78 	struct sabtty_softc *	sc_child[SAB_NCHAN];
79 	u_int			sc_nchild;
80 	void *			sc_softintr;
81 	int			sc_node;
82 };
83 
84 struct sabtty_attach_args {
85 	u_int sbt_portno;
86 };
87 
88 struct sabtty_softc {
89 	struct device		sc_dv;
90 	struct sab_softc *	sc_parent;
91 	bus_space_tag_t		sc_bt;
92 	bus_space_handle_t	sc_bh;
93 	struct tty *		sc_tty;
94 	u_int			sc_portno;
95 	u_int8_t		sc_pvr_dtr, sc_pvr_dsr;
96 	u_int8_t		sc_imr0, sc_imr1;
97 	int			sc_openflags;
98 	u_char *		sc_txp;
99 	int			sc_txc;
100 	int			sc_flags;
101 #define SABTTYF_STOP		0x01
102 #define	SABTTYF_DONE		0x02
103 #define	SABTTYF_RINGOVERFLOW	0x04
104 #define	SABTTYF_CDCHG		0x08
105 #define	SABTTYF_CONS_IN		0x10
106 #define	SABTTYF_CONS_OUT	0x20
107 #define	SABTTYF_TXDRAIN		0x40
108 #define	SABTTYF_DONTDDB		0x80
109 	u_int8_t		sc_rbuf[SABTTY_RBUF_SIZE];
110 	u_int8_t		*sc_rend, *sc_rput, *sc_rget;
111 	u_int8_t		sc_polling, sc_pollrfc;
112 };
113 
114 struct sabtty_softc *sabtty_cons_input;
115 struct sabtty_softc *sabtty_cons_output;
116 
117 #define	SAB_READ(sc,r)		\
118     bus_space_read_1((sc)->sc_bt, (sc)->sc_bh, (r))
119 #define	SAB_WRITE(sc,r,v)	\
120     bus_space_write_1((sc)->sc_bt, (sc)->sc_bh, (r), (v))
121 #define	SAB_WRITE_BLOCK(sc,r,p,c)	\
122     bus_space_write_region_1((sc)->sc_bt, (sc)->sc_bh, (r), (p), (c))
123 
124 int sab_match(struct device *, struct cfdata *, void *);
125 void sab_attach(struct device *, struct device *, void *);
126 int sab_print(void *, const char *);
127 int sab_intr(void *);
128 
129 void sab_softintr(void *);
130 void sab_cnputc(dev_t, int);
131 int sab_cngetc(dev_t);
132 void sab_cnpollc(dev_t, int);
133 
134 int sabtty_match(struct device *, struct cfdata *, void *);
135 void sabtty_attach(struct device *, struct device *, void *);
136 void sabtty_start(struct tty *);
137 int sabtty_param(struct tty *, struct termios *);
138 int sabtty_intr(struct sabtty_softc *, int *);
139 void sabtty_softintr(struct sabtty_softc *);
140 int sabtty_mdmctrl(struct sabtty_softc *, int, int);
141 void sabtty_cec_wait(struct sabtty_softc *);
142 void sabtty_tec_wait(struct sabtty_softc *);
143 void sabtty_reset(struct sabtty_softc *);
144 void sabtty_flush(struct sabtty_softc *);
145 int sabtty_speed(int);
146 void sabtty_console_flags(struct sabtty_softc *);
147 void sabtty_cnpollc(struct sabtty_softc *, int);
148 void sabtty_shutdown(void *);
149 int sabttyparam(struct sabtty_softc *, struct tty *, struct termios *);
150 
151 void sabtty_cnputc(struct sabtty_softc *, int);
152 int sabtty_cngetc(struct sabtty_softc *);
153 void sabtty_abort(struct sabtty_softc *);
154 
155 CFATTACH_DECL(sab, sizeof(struct sab_softc),
156     sab_match, sab_attach, NULL, NULL);
157 
158 extern struct cfdriver sab_cd;
159 
160 CFATTACH_DECL(sabtty, sizeof(struct sabtty_softc),
161     sabtty_match, sabtty_attach, NULL, NULL);
162 
163 extern struct cfdriver sabtty_cd;
164 
165 dev_type_open(sabopen);
166 dev_type_close(sabclose);
167 dev_type_read(sabread);
168 dev_type_write(sabwrite);
169 dev_type_ioctl(sabioctl);
170 dev_type_stop(sabstop);
171 dev_type_tty(sabtty);
172 dev_type_poll(sabpoll);
173 
174 const struct cdevsw sabtty_cdevsw = {
175 	sabopen, sabclose, sabread, sabwrite, sabioctl,
176 	sabstop, sabtty, sabpoll, nommap, ttykqfilter, D_TTY
177 };
178 
179 struct sabtty_rate {
180 	int baud;
181 	int n, m;
182 };
183 
184 struct sabtty_rate sabtty_baudtable[] = {
185 	{      50,	35,     10 },
186 	{      75,	47,	9 },
187 	{     110,	32,	9 },
188 	{     134,	53,	8 },
189 	{     150,	47,	8 },
190 	{     200,	35,	8 },
191 	{     300,	47,	7 },
192 	{     600,	47,	6 },
193 	{    1200,	47,	5 },
194 	{    1800,	31,	5 },
195 	{    2400,	47,	4 },
196 	{    4800,	47,	3 },
197 	{    9600,	47,	2 },
198 	{   19200,	47,	1 },
199 	{   38400,	23,	1 },
200 	{   57600,	15,	1 },
201 	{  115200,	 7,	1 },
202 	{  230400,	 3,	1 },
203 	{  460800,	 1,	1 },
204 	{   76800,	11,	1 },
205 	{  153600,	 5,	1 },
206 	{  307200,	 3,	1 },
207 	{  614400,	 3,	0 },
208 	{  921600,	 0,	1 },
209 };
210 
211 int
212 sab_match(parent, match, aux)
213 	struct device *parent;
214 	struct cfdata *match;
215 	void *aux;
216 {
217 	struct ebus_attach_args *ea = aux;
218 	char *compat;
219 
220 	if (strcmp(ea->ea_name, "se") == 0)
221 		return (1);
222 
223 	compat = prom_getpropstring(ea->ea_node, "compatible");
224 	if (compat != NULL && !strcmp(compat, "sab82532"))
225 		return (1);
226 
227 	return (0);
228 }
229 
230 void
231 sab_attach(parent, self, aux)
232 	struct device *parent;
233 	struct device *self;
234 	void *aux;
235 {
236 	struct sab_softc *sc = (struct sab_softc *)self;
237 	struct ebus_attach_args *ea = aux;
238 	u_int8_t r;
239 	u_int i;
240 
241 	sc->sc_bt = ea->ea_bustag;
242 	sc->sc_node = ea->ea_node;
243 
244 	/* Use prom mapping, if available. */
245 	if (ea->ea_nvaddr)
246 		sparc_promaddr_to_handle(sc->sc_bt, ea->ea_vaddr[0], &sc->sc_bh);
247 	else if (bus_space_map(sc->sc_bt, EBUS_ADDR_FROM_REG(&ea->ea_reg[0]),
248 				 ea->ea_reg[0].size, 0, &sc->sc_bh) != 0) {
249 		printf(": can't map register space\n");
250 		return;
251 	}
252 
253 	sc->sc_ih = bus_intr_establish(ea->ea_bustag, ea->ea_intr[0],
254 	    IPL_TTY, sab_intr, sc);
255 	if (sc->sc_ih == NULL) {
256 		printf(": can't map interrupt\n");
257 		return;
258 	}
259 
260 	sc->sc_softintr = softintr_establish(IPL_TTY, sab_softintr, sc);
261 	if (sc->sc_softintr == NULL) {
262 		printf(": can't get soft intr\n");
263 		return;
264 	}
265 
266 	printf(": rev ");
267 	r = SAB_READ(sc, SAB_VSTR) & SAB_VSTR_VMASK;
268 	switch (r) {
269 	case SAB_VSTR_V_1:
270 		printf("1");
271 		break;
272 	case SAB_VSTR_V_2:
273 		printf("2");
274 		break;
275 	case SAB_VSTR_V_32:
276 		printf("3.2");
277 		break;
278 	default:
279 		printf("unknown(0x%x)", r);
280 		break;
281 	}
282 	printf("\n");
283 
284 	/* Let current output drain */
285 	DELAY(100000);
286 
287 	/* Set all pins, except DTR pins to be inputs */
288 	SAB_WRITE(sc, SAB_PCR, ~(SAB_PVR_DTR_A | SAB_PVR_DTR_B));
289 	/* Disable port interrupts */
290 	SAB_WRITE(sc, SAB_PIM, 0xff);
291 	SAB_WRITE(sc, SAB_PVR, SAB_PVR_DTR_A | SAB_PVR_DTR_B | SAB_PVR_MAGIC);
292 	SAB_WRITE(sc, SAB_IPC, SAB_IPC_ICPL);
293 
294 	for (i = 0; i < SAB_NCHAN; i++) {
295 		struct sabtty_attach_args sta;
296 
297 		sta.sbt_portno = i;
298 		sc->sc_child[i] = (struct sabtty_softc *)config_found_sm(self,
299 		    &sta, sab_print, sabtty_match);
300 		if (sc->sc_child[i] != NULL)
301 			sc->sc_nchild++;
302 	}
303 }
304 
305 int
306 sab_print(args, name)
307 	void *args;
308 	const char *name;
309 {
310 	struct sabtty_attach_args *sa = args;
311 
312 	if (name)
313 		aprint_normal("sabtty at %s", name);
314 	aprint_normal(" port %d", sa->sbt_portno);
315 	return (UNCONF);
316 }
317 
318 int
319 sab_intr(vsc)
320 	void *vsc;
321 {
322 	struct sab_softc *sc = vsc;
323 	int r = 0, needsoft = 0;
324 	u_int8_t gis;
325 
326 	gis = SAB_READ(sc, SAB_GIS);
327 
328 	/* channel A */
329 	if ((gis & (SAB_GIS_ISA1 | SAB_GIS_ISA0)) && sc->sc_child[0] &&
330 	    sc->sc_child[0]->sc_tty)
331 		r |= sabtty_intr(sc->sc_child[0], &needsoft);
332 
333 	/* channel B */
334 	if ((gis & (SAB_GIS_ISB1 | SAB_GIS_ISB0)) && sc->sc_child[1] &&
335 	    sc->sc_child[1]->sc_tty)
336 		r |= sabtty_intr(sc->sc_child[1], &needsoft);
337 
338 	if (needsoft)
339 		softintr_schedule(sc->sc_softintr);
340 
341 	return (r);
342 }
343 
344 void
345 sab_softintr(vsc)
346 	void *vsc;
347 {
348 	struct sab_softc *sc = vsc;
349 
350 	if (sc->sc_child[0] && sc->sc_child[0]->sc_tty)
351 		sabtty_softintr(sc->sc_child[0]);
352 	if (sc->sc_child[1] && sc->sc_child[1]->sc_tty)
353 		sabtty_softintr(sc->sc_child[1]);
354 }
355 
356 int
357 sabtty_match(parent, match, aux)
358 	struct device *parent;
359 	struct cfdata *match;
360 	void *aux;
361 {
362 	struct sabtty_attach_args *sa = aux;
363 
364 	if (sa->sbt_portno < SAB_NCHAN)
365 		return (1);
366 	return (0);
367 }
368 
369 void
370 sabtty_attach(parent, self, aux)
371 	struct device *parent;
372 	struct device *self;
373 	void *aux;
374 {
375 	struct sabtty_softc *sc = (struct sabtty_softc *)self;
376 	struct sabtty_attach_args *sa = aux;
377 	int r;
378 	int maj;
379 
380 	sc->sc_tty = ttymalloc();
381 	if (sc->sc_tty == NULL) {
382 		printf(": failed to allocate tty\n");
383 		return;
384 	}
385 	tty_attach(sc->sc_tty);
386 	sc->sc_tty->t_oproc = sabtty_start;
387 	sc->sc_tty->t_param = sabtty_param;
388 
389 	sc->sc_parent = (struct sab_softc *)parent;
390 	sc->sc_bt = sc->sc_parent->sc_bt;
391 	sc->sc_portno = sa->sbt_portno;
392 	sc->sc_rend = sc->sc_rbuf + SABTTY_RBUF_SIZE;
393 
394 	switch (sa->sbt_portno) {
395 	case 0:	/* port A */
396 		sc->sc_pvr_dtr = SAB_PVR_DTR_A;
397 		sc->sc_pvr_dsr = SAB_PVR_DSR_A;
398 		r = bus_space_subregion(sc->sc_bt, sc->sc_parent->sc_bh,
399 		    SAB_CHAN_A, SAB_CHANLEN, &sc->sc_bh);
400 		break;
401 	case 1:	/* port B */
402 		sc->sc_pvr_dtr = SAB_PVR_DTR_B;
403 		sc->sc_pvr_dsr = SAB_PVR_DSR_B;
404 		r = bus_space_subregion(sc->sc_bt, sc->sc_parent->sc_bh,
405 		    SAB_CHAN_B, SAB_CHANLEN, &sc->sc_bh);
406 		break;
407 	default:
408 		printf(": invalid channel: %u\n", sa->sbt_portno);
409 		return;
410 	}
411 	if (r != 0) {
412 		printf(": failed to allocate register subregion\n");
413 		return;
414 	}
415 
416 	sabtty_console_flags(sc);
417 
418 	if (sc->sc_flags & (SABTTYF_CONS_IN | SABTTYF_CONS_OUT)) {
419 		struct termios t;
420 		char *acc;
421 
422 		switch (sc->sc_flags & (SABTTYF_CONS_IN | SABTTYF_CONS_OUT)) {
423 		case SABTTYF_CONS_IN:
424 			acc = "input";
425 			break;
426 		case SABTTYF_CONS_OUT:
427 			acc = "output";
428 			break;
429 		case SABTTYF_CONS_IN|SABTTYF_CONS_OUT:
430 		default:
431 			acc = "i/o";
432 			break;
433 		}
434 
435 		t.c_ispeed= 0;
436 		t.c_ospeed = 9600;
437 		t.c_cflag = CREAD | CS8 | HUPCL;
438 		sc->sc_tty->t_ospeed = 0;
439 		sabttyparam(sc, sc->sc_tty, &t);
440 
441 		if (sc->sc_flags & SABTTYF_CONS_IN) {
442 			sabtty_cons_input = sc;
443 			cn_tab->cn_pollc = sab_cnpollc;
444 			cn_tab->cn_getc = sab_cngetc;
445 			maj = cdevsw_lookup_major(&sabtty_cdevsw);
446 			cn_tab->cn_dev = makedev(maj, self->dv_unit);
447 			shutdownhook_establish(sabtty_shutdown, sc);
448 		}
449 
450 		if (sc->sc_flags & SABTTYF_CONS_OUT) {
451 			sabtty_cons_output = sc;
452 			cn_tab->cn_putc = sab_cnputc;
453 			maj = cdevsw_lookup_major(&sabtty_cdevsw);
454 			cn_tab->cn_dev = makedev(maj, self->dv_unit);
455 		}
456 		printf(": console %s", acc);
457 	} else {
458 		/* Not a console... */
459 		sabtty_reset(sc);
460 	}
461 
462 	printf("\n");
463 }
464 
465 int
466 sabtty_intr(sc, needsoftp)
467 	struct sabtty_softc *sc;
468 	int *needsoftp;
469 {
470 	u_int8_t isr0, isr1;
471 	int i, len = 0, needsoft = 0, r = 0, clearfifo = 0;
472 
473 	isr0 = SAB_READ(sc, SAB_ISR0);
474 	isr1 = SAB_READ(sc, SAB_ISR1);
475 
476 	if (isr0 || isr1)
477 		r = 1;
478 
479 	if (isr0 & SAB_ISR0_RPF) {
480 		len = 32;
481 		clearfifo = 1;
482 	}
483 	if (isr0 & SAB_ISR0_TCD) {
484 		len = (32 - 1) & SAB_READ(sc, SAB_RBCL);
485 		clearfifo = 1;
486 	}
487 	if (isr0 & SAB_ISR0_TIME) {
488 		sabtty_cec_wait(sc);
489 		SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_RFRD);
490 	}
491 	if (isr0 & SAB_ISR0_RFO) {
492 		sc->sc_flags |= SABTTYF_RINGOVERFLOW;
493 		clearfifo = 1;
494 	}
495 	if (len != 0) {
496 		u_int8_t *ptr;
497 
498 		ptr = sc->sc_rput;
499 		for (i = 0; i < len; i++) {
500 			*ptr++ = SAB_READ(sc, SAB_RFIFO);
501 			if (ptr == sc->sc_rend)
502 				ptr = sc->sc_rbuf;
503 			if (ptr == sc->sc_rget) {
504 				if (ptr == sc->sc_rbuf)
505 					ptr = sc->sc_rend;
506 				ptr--;
507 				sc->sc_flags |= SABTTYF_RINGOVERFLOW;
508 			}
509 		}
510 		sc->sc_rput = ptr;
511 		needsoft = 1;
512 	}
513 
514 	if (clearfifo) {
515 		sabtty_cec_wait(sc);
516 		SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_RMC);
517 	}
518 
519 	if (isr0 & SAB_ISR0_CDSC) {
520 		sc->sc_flags |= SABTTYF_CDCHG;
521 		needsoft = 1;
522 	}
523 
524 	if (isr1 & SAB_ISR1_BRKT)
525 		sabtty_abort(sc);
526 
527 	if (isr1 & (SAB_ISR1_XPR | SAB_ISR1_ALLS)) {
528 		if ((SAB_READ(sc, SAB_STAR) & SAB_STAR_XFW) &&
529 		    (sc->sc_flags & SABTTYF_STOP) == 0) {
530 			if (sc->sc_txc < 32)
531 				len = sc->sc_txc;
532 			else
533 				len = 32;
534 
535 			if (len > 0) {
536 				SAB_WRITE_BLOCK(sc, SAB_XFIFO, sc->sc_txp, len);
537 				sc->sc_txp += len;
538 				sc->sc_txc -= len;
539 
540 				sabtty_cec_wait(sc);
541 				SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_XF);
542 
543 				/*
544 				 * Prevent the false end of xmit from
545 				 * confusing things below.
546 				 */
547 				isr1 &= ~SAB_ISR1_ALLS;
548 			}
549 		}
550 
551 		if ((sc->sc_txc == 0) || (sc->sc_flags & SABTTYF_STOP)) {
552 			if ((sc->sc_imr1 & SAB_IMR1_XPR) == 0) {
553 				sc->sc_imr1 |= SAB_IMR1_XPR;
554 				sc->sc_imr1 &= ~SAB_IMR1_ALLS;
555 				SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1);
556 			}
557 		}
558 	}
559 
560 	if ((isr1 & SAB_ISR1_ALLS) && ((sc->sc_txc == 0) ||
561 	    (sc->sc_flags & SABTTYF_STOP))) {
562 		if (sc->sc_flags & SABTTYF_TXDRAIN)
563 			wakeup(sc);
564 		sc->sc_flags &= ~SABTTYF_STOP;
565 		sc->sc_flags |= SABTTYF_DONE;
566 		sc->sc_imr1 |= SAB_IMR1_ALLS;
567 		SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1);
568 		needsoft = 1;
569 	}
570 
571 	if (needsoft)
572 		*needsoftp = needsoft;
573 	return (r);
574 }
575 
576 void
577 sabtty_softintr(sc)
578 	struct sabtty_softc *sc;
579 {
580 	struct tty *tp = sc->sc_tty;
581 	int s, flags;
582 	u_int8_t r;
583 
584 	if (tp == NULL)
585 		return;
586 
587 	if ((tp->t_state & TS_ISOPEN) == 0)
588 		return;
589 
590 	while (sc->sc_rget != sc->sc_rput) {
591 		int data;
592 		u_int8_t stat;
593 
594 		data = sc->sc_rget[0];
595 		stat = sc->sc_rget[1];
596 		sc->sc_rget += 2;
597 		if (stat & SAB_RSTAT_PE)
598 			data |= TTY_PE;
599 		if (stat & SAB_RSTAT_FE)
600 			data |= TTY_FE;
601 		if (sc->sc_rget == sc->sc_rend)
602 			sc->sc_rget = sc->sc_rbuf;
603 
604 		(*tp->t_linesw->l_rint)(data, tp);
605 	}
606 
607 	s = splhigh();
608 	flags = sc->sc_flags;
609 	sc->sc_flags &= ~(SABTTYF_DONE|SABTTYF_CDCHG|SABTTYF_RINGOVERFLOW);
610 	splx(s);
611 
612 	if (flags & SABTTYF_CDCHG) {
613 		s = spltty();
614 		r = SAB_READ(sc, SAB_VSTR) & SAB_VSTR_CD;
615 		splx(s);
616 
617 		(*tp->t_linesw->l_modem)(tp, r);
618 	}
619 
620 	if (flags & SABTTYF_RINGOVERFLOW)
621 		log(LOG_WARNING, "%s: ring overflow\n", sc->sc_dv.dv_xname);
622 
623 	if (flags & SABTTYF_DONE) {
624 		ndflush(&tp->t_outq, sc->sc_txp - tp->t_outq.c_cf);
625 		tp->t_state &= ~TS_BUSY;
626 		(*tp->t_linesw->l_start)(tp);
627 	}
628 }
629 
630 int
631 sabopen(dev, flags, mode, p)
632 	dev_t dev;
633 	int flags, mode;
634 	struct proc *p;
635 {
636 	struct sabtty_softc *sc;
637 	struct tty *tp;
638 	int s, s1;
639 
640 	sc = device_lookup(&sabtty_cd, SABUNIT(dev));
641 	if (sc == NULL)
642 		return (ENXIO);
643 
644 	tp = sc->sc_tty;
645 	tp->t_dev = dev;
646 
647 	if ((tp->t_state & TS_ISOPEN) == 0) {
648 		ttychars(tp);
649 		tp->t_iflag = TTYDEF_IFLAG;
650 		tp->t_oflag = TTYDEF_OFLAG;
651 		tp->t_cflag = TTYDEF_CFLAG;
652 		if (sc->sc_openflags & TIOCFLAG_CLOCAL)
653 			tp->t_cflag |= CLOCAL;
654 		if (sc->sc_openflags & TIOCFLAG_CRTSCTS)
655 			tp->t_cflag |= CRTSCTS;
656 		if (sc->sc_openflags & TIOCFLAG_MDMBUF)
657 			tp->t_cflag |= MDMBUF;
658 		tp->t_lflag = TTYDEF_LFLAG;
659 		tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
660 
661 		sc->sc_rput = sc->sc_rget = sc->sc_rbuf;
662 
663 		s = spltty();
664 
665 		ttsetwater(tp);
666 
667 		s1 = splhigh();
668 		sabtty_reset(sc);
669 		sabtty_param(tp, &tp->t_termios);
670 		sc->sc_imr0 = SAB_IMR0_PERR | SAB_IMR0_FERR | SAB_IMR0_PLLA;
671 		SAB_WRITE(sc, SAB_IMR0, sc->sc_imr0);
672 		sc->sc_imr1 = SAB_IMR1_BRK | SAB_IMR1_ALLS | SAB_IMR1_XDU |
673 		    SAB_IMR1_TIN | SAB_IMR1_CSC | SAB_IMR1_XMR | SAB_IMR1_XPR;
674 		SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1);
675 		SAB_WRITE(sc, SAB_CCR0, SAB_READ(sc, SAB_CCR0) | SAB_CCR0_PU);
676 		sabtty_cec_wait(sc);
677 		SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_XRES);
678 		sabtty_cec_wait(sc);
679 		SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_RRES);
680 		sabtty_cec_wait(sc);
681 		splx(s1);
682 
683 		sabtty_flush(sc);
684 
685 		if ((sc->sc_openflags & TIOCFLAG_SOFTCAR) ||
686 		    (SAB_READ(sc, SAB_VSTR) & SAB_VSTR_CD))
687 			tp->t_state |= TS_CARR_ON;
688 		else
689 			tp->t_state &= ~TS_CARR_ON;
690 	} else if ((tp->t_state & TS_XCLUDE) &&
691 	    (!suser(p->p_ucred, &p->p_acflag))) {
692 		return (EBUSY);
693 	} else {
694 		s = spltty();
695 	}
696 
697 	if ((flags & O_NONBLOCK) == 0) {
698 		while ((tp->t_cflag & CLOCAL) == 0 &&
699 		    (tp->t_state & TS_CARR_ON) == 0) {
700 			int error;
701 
702 			error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH,
703 			    "sabttycd", 0);
704 			if (error != 0) {
705 				splx(s);
706 				return (error);
707 			}
708 		}
709 	}
710 
711 	splx(s);
712 
713 	s = (*tp->t_linesw->l_open)(dev, tp);
714 	if (s != 0) {
715 		if (tp->t_state & TS_ISOPEN)
716 			return (s);
717 
718 		if (tp->t_cflag & HUPCL) {
719 			sabtty_mdmctrl(sc, 0, DMSET);
720 			(void)tsleep(sc, TTIPRI, ttclos, hz);
721 		}
722 
723 		if ((sc->sc_flags & (SABTTYF_CONS_IN | SABTTYF_CONS_OUT)) == 0) {
724 			/* Flush and power down if we're not the console */
725 			sabtty_flush(sc);
726 			sabtty_reset(sc);
727 		}
728 	}
729 	return (s);
730 }
731 
732 int
733 sabclose(dev, flags, mode, p)
734 	dev_t dev;
735 	int flags, mode;
736 	struct proc *p;
737 {
738 	struct sabtty_softc *sc = device_lookup(&sabtty_cd, SABUNIT(dev));
739 	struct sab_softc *bc = sc->sc_parent;
740 	struct tty *tp = sc->sc_tty;
741 	int s;
742 
743 	(*tp->t_linesw->l_close)(tp, flags);
744 
745 	s = spltty();
746 
747 	if ((tp->t_state & TS_ISOPEN) == 0) {
748 		/* Wait for output drain */
749 		sc->sc_imr1 &= ~SAB_IMR1_ALLS;
750 		SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1);
751 		sc->sc_flags |= SABTTYF_TXDRAIN;
752 		(void)tsleep(sc, TTIPRI, ttclos, 5 * hz);
753 		sc->sc_imr1 |= SAB_IMR1_ALLS;
754 		SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1);
755 		sc->sc_flags &= ~SABTTYF_TXDRAIN;
756 
757 		if (tp->t_cflag & HUPCL) {
758 			sabtty_mdmctrl(sc, 0, DMSET);
759 			(void)tsleep(bc, TTIPRI, ttclos, hz);
760 		}
761 
762 		if ((sc->sc_flags & (SABTTYF_CONS_IN | SABTTYF_CONS_OUT)) == 0) {
763 			/* Flush and power down if we're not the console */
764 			sabtty_flush(sc);
765 			sabtty_reset(sc);
766 		}
767 	}
768 
769 	ttyclose(tp);
770 	splx(s);
771 
772 	return (0);
773 }
774 
775 int
776 sabread(dev, uio, flags)
777 	dev_t dev;
778 	struct uio *uio;
779 	int flags;
780 {
781 	struct sabtty_softc *sc = device_lookup(&sabtty_cd, SABUNIT(dev));
782 	struct tty *tp = sc->sc_tty;
783 
784 	return ((*tp->t_linesw->l_read)(tp, uio, flags));
785 }
786 
787 int
788 sabwrite(dev, uio, flags)
789 	dev_t dev;
790 	struct uio *uio;
791 	int flags;
792 {
793 	struct sabtty_softc *sc = device_lookup(&sabtty_cd, SABUNIT(dev));
794 	struct tty *tp = sc->sc_tty;
795 
796 	return ((*tp->t_linesw->l_write)(tp, uio, flags));
797 }
798 
799 int
800 sabioctl(dev, cmd, data, flags, p)
801 	dev_t dev;
802 	u_long cmd;
803 	caddr_t data;
804 	int flags;
805 	struct proc *p;
806 {
807 	struct sabtty_softc *sc = device_lookup(&sabtty_cd, SABUNIT(dev));
808 	struct tty *tp = sc->sc_tty;
809 	int error;
810 
811 	error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flags, p);
812 	if (error >= 0)
813 		return (error);
814 
815 	error = ttioctl(tp, cmd, data, flags, p);
816 	if (error >= 0)
817 		return (error);
818 
819 	error = 0;
820 
821 	switch (cmd) {
822 	case TIOCSBRK:
823 		SAB_WRITE(sc, SAB_DAFO,
824 		    SAB_READ(sc, SAB_DAFO) | SAB_DAFO_XBRK);
825 		break;
826 	case TIOCCBRK:
827 		SAB_WRITE(sc, SAB_DAFO,
828 		    SAB_READ(sc, SAB_DAFO) & ~SAB_DAFO_XBRK);
829 		break;
830 	case TIOCSDTR:
831 		sabtty_mdmctrl(sc, TIOCM_DTR, DMBIS);
832 		break;
833 	case TIOCCDTR:
834 		sabtty_mdmctrl(sc, TIOCM_DTR, DMBIC);
835 		break;
836 	case TIOCMBIS:
837 		sabtty_mdmctrl(sc, *((int *)data), DMBIS);
838 		break;
839 	case TIOCMBIC:
840 		sabtty_mdmctrl(sc, *((int *)data), DMBIC);
841 		break;
842 	case TIOCMGET:
843 		*((int *)data) = sabtty_mdmctrl(sc, 0, DMGET);
844 		break;
845 	case TIOCMSET:
846 		sabtty_mdmctrl(sc, *((int *)data), DMSET);
847 		break;
848 	case TIOCGFLAGS:
849 		*((int *)data) = sc->sc_openflags;
850 		break;
851 	case TIOCSFLAGS:
852 		if (suser(p->p_ucred, &p->p_acflag))
853 			error = EPERM;
854 		else
855 			sc->sc_openflags = *((int *)data) &
856 			    (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL |
857 			     TIOCFLAG_CRTSCTS | TIOCFLAG_MDMBUF);
858 		break;
859 	default:
860 		error = ENOTTY;
861 	}
862 
863 	return (error);
864 }
865 
866 struct tty *
867 sabtty(dev)
868 	dev_t dev;
869 {
870 	struct sabtty_softc *sc = device_lookup(&sabtty_cd, SABUNIT(dev));
871 
872 	return (sc->sc_tty);
873 }
874 
875 void
876 sabstop(tp, flag)
877 	struct tty *tp;
878 	int flag;
879 {
880 	struct sabtty_softc *sc = device_lookup(&sabtty_cd, SABUNIT(tp->t_dev));
881 	int s;
882 
883 	s = spltty();
884 	if (tp->t_state & TS_BUSY) {
885 		if ((tp->t_state & TS_TTSTOP) == 0)
886 			tp->t_state |= TS_FLUSH;
887 		sc->sc_flags |= SABTTYF_STOP;
888 		sc->sc_imr1 &= ~SAB_IMR1_ALLS;
889 		SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1);
890 	}
891 	splx(s);
892 }
893 
894 int
895 sabpoll(dev, events, p)
896 	dev_t dev;
897 	int events;
898 	struct proc *p;
899 {
900 	struct sabtty_softc *sc = device_lookup(&sabtty_cd, SABUNIT(dev));
901 	struct tty *tp = sc->sc_tty;
902 
903 	return ((*tp->t_linesw->l_poll)(tp, events, p));
904 }
905 
906 int
907 sabtty_mdmctrl(sc, bits, how)
908 	struct sabtty_softc *sc;
909 	int bits, how;
910 {
911 	u_int8_t r;
912 	int s;
913 
914 	s = spltty();
915 	switch (how) {
916 	case DMGET:
917 		bits = 0;
918 		if (SAB_READ(sc, SAB_STAR) & SAB_STAR_CTS)
919 			bits |= TIOCM_CTS;
920 		if ((SAB_READ(sc, SAB_VSTR) & SAB_VSTR_CD) == 0)
921 			bits |= TIOCM_CD;
922 
923 		r = SAB_READ(sc, SAB_PVR);
924 		if ((r & sc->sc_pvr_dtr) == 0)
925 			bits |= TIOCM_DTR;
926 		if ((r & sc->sc_pvr_dsr) == 0)
927 			bits |= TIOCM_DSR;
928 
929 		r = SAB_READ(sc, SAB_MODE);
930 		if ((r & (SAB_MODE_RTS|SAB_MODE_FRTS)) == SAB_MODE_RTS)
931 			bits |= TIOCM_RTS;
932 		break;
933 	case DMSET:
934 		r = SAB_READ(sc, SAB_MODE);
935 		if (bits & TIOCM_RTS) {
936 			r &= ~SAB_MODE_FRTS;
937 			r |= SAB_MODE_RTS;
938 		} else
939 			r |= SAB_MODE_FRTS | SAB_MODE_RTS;
940 		SAB_WRITE(sc, SAB_MODE, r);
941 
942 		r = SAB_READ(sc, SAB_PVR);
943 		if (bits & TIOCM_DTR)
944 			r &= ~sc->sc_pvr_dtr;
945 		else
946 			r |= sc->sc_pvr_dtr;
947 		SAB_WRITE(sc, SAB_PVR, r);
948 		break;
949 	case DMBIS:
950 		if (bits & TIOCM_RTS) {
951 			r = SAB_READ(sc, SAB_MODE);
952 			r &= ~SAB_MODE_FRTS;
953 			r |= SAB_MODE_RTS;
954 			SAB_WRITE(sc, SAB_MODE, r);
955 		}
956 		if (bits & TIOCM_DTR) {
957 			r = SAB_READ(sc, SAB_PVR);
958 			r &= ~sc->sc_pvr_dtr;
959 			SAB_WRITE(sc, SAB_PVR, r);
960 		}
961 		break;
962 	case DMBIC:
963 		if (bits & TIOCM_RTS) {
964 			r = SAB_READ(sc, SAB_MODE);
965 			r |= SAB_MODE_FRTS | SAB_MODE_RTS;
966 			SAB_WRITE(sc, SAB_MODE, r);
967 		}
968 		if (bits & TIOCM_DTR) {
969 			r = SAB_READ(sc, SAB_PVR);
970 			r |= sc->sc_pvr_dtr;
971 			SAB_WRITE(sc, SAB_PVR, r);
972 		}
973 		break;
974 	}
975 	splx(s);
976 	return (bits);
977 }
978 
979 int
980 sabttyparam(sc, tp, t)
981 	struct sabtty_softc *sc;
982 	struct tty *tp;
983 	struct termios *t;
984 {
985 	int s, ospeed;
986 	tcflag_t cflag;
987 	u_int8_t dafo, r;
988 
989 	ospeed = sabtty_speed(t->c_ospeed);
990 	if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
991 		return (EINVAL);
992 
993 	s = spltty();
994 
995 	/* hang up line if ospeed is zero, otherwise raise dtr */
996 	sabtty_mdmctrl(sc, TIOCM_DTR,
997 	    (t->c_ospeed == 0) ? DMBIC : DMBIS);
998 
999 	dafo = SAB_READ(sc, SAB_DAFO);
1000 
1001 	cflag = t->c_cflag;
1002 
1003 	if (sc->sc_flags & (SABTTYF_CONS_IN | SABTTYF_CONS_OUT)) {
1004 		cflag |= CLOCAL;
1005 		cflag &= ~HUPCL;
1006 	}
1007 
1008 	if (cflag & CSTOPB)
1009 		dafo |= SAB_DAFO_STOP;
1010 	else
1011 		dafo &= ~SAB_DAFO_STOP;
1012 
1013 	dafo &= ~SAB_DAFO_CHL_CSIZE;
1014 	switch (cflag & CSIZE) {
1015 	case CS5:
1016 		dafo |= SAB_DAFO_CHL_CS5;
1017 		break;
1018 	case CS6:
1019 		dafo |= SAB_DAFO_CHL_CS6;
1020 		break;
1021 	case CS7:
1022 		dafo |= SAB_DAFO_CHL_CS7;
1023 		break;
1024 	default:
1025 		dafo |= SAB_DAFO_CHL_CS8;
1026 		break;
1027 	}
1028 
1029 	dafo &= ~SAB_DAFO_PARMASK;
1030 	if (cflag & PARENB) {
1031 		if (cflag & PARODD)
1032 			dafo |= SAB_DAFO_PAR_ODD;
1033 		else
1034 			dafo |= SAB_DAFO_PAR_EVEN;
1035 	} else
1036 		dafo |= SAB_DAFO_PAR_NONE;
1037 
1038 	if (ospeed != 0) {
1039 		SAB_WRITE(sc, SAB_BGR, ospeed & 0xff);
1040 		r = SAB_READ(sc, SAB_CCR2);
1041 		r &= ~(SAB_CCR2_BR9 | SAB_CCR2_BR8);
1042 		r |= (ospeed >> 2) & (SAB_CCR2_BR9 | SAB_CCR2_BR8);
1043 		SAB_WRITE(sc, SAB_CCR2, r);
1044 	}
1045 
1046 	r = SAB_READ(sc, SAB_MODE);
1047 	r |= SAB_MODE_RAC;
1048 	if (cflag & CRTSCTS) {
1049 		r &= ~(SAB_MODE_RTS | SAB_MODE_FCTS);
1050 		r |= SAB_MODE_FRTS;
1051 		sc->sc_imr1 &= ~SAB_IMR1_CSC;
1052 	} else {
1053 		r |= SAB_MODE_RTS | SAB_MODE_FCTS;
1054 		r &= ~SAB_MODE_FRTS;
1055 		sc->sc_imr1 |= SAB_IMR1_CSC;
1056 	}
1057 	SAB_WRITE(sc, SAB_MODE, r);
1058 	SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1);
1059 
1060 	tp->t_cflag = cflag;
1061 
1062 	splx(s);
1063 	return (0);
1064 }
1065 
1066 int
1067 sabtty_param(tp, t)
1068 	struct tty *tp;
1069 	struct termios *t;
1070 {
1071 	struct sabtty_softc *sc = device_lookup(&sabtty_cd, SABUNIT(tp->t_dev));
1072 
1073 	return (sabttyparam(sc, tp, t));
1074 }
1075 
1076 void
1077 sabtty_start(tp)
1078 	struct tty *tp;
1079 {
1080 	struct sabtty_softc *sc = device_lookup(&sabtty_cd, SABUNIT(tp->t_dev));
1081 	int s;
1082 
1083 	s = spltty();
1084 	if ((tp->t_state & (TS_TTSTOP | TS_TIMEOUT | TS_BUSY)) == 0) {
1085 		if (tp->t_outq.c_cc <= tp->t_lowat) {
1086 			if (tp->t_state & TS_ASLEEP) {
1087 				tp->t_state &= ~TS_ASLEEP;
1088 				wakeup(&tp->t_outq);
1089 			}
1090 			selwakeup(&tp->t_wsel);
1091 		}
1092 		if (tp->t_outq.c_cc) {
1093 			sc->sc_txc = ndqb(&tp->t_outq, 0);
1094 			sc->sc_txp = tp->t_outq.c_cf;
1095 			tp->t_state |= TS_BUSY;
1096 			sc->sc_imr1 &= ~(SAB_ISR1_XPR | SAB_ISR1_ALLS);
1097 			SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1);
1098 		}
1099 	}
1100 	splx(s);
1101 }
1102 
1103 void
1104 sabtty_cec_wait(sc)
1105 	struct sabtty_softc *sc;
1106 {
1107 	int i = 50000;
1108 
1109 	for (;;) {
1110 		if ((SAB_READ(sc, SAB_STAR) & SAB_STAR_CEC) == 0)
1111 			return;
1112 		if (--i == 0)
1113 			break;
1114 		DELAY(1);
1115 	}
1116 }
1117 
1118 void
1119 sabtty_tec_wait(sc)
1120 	struct sabtty_softc *sc;
1121 {
1122 	int i = 200000;
1123 
1124 	for (;;) {
1125 		if ((SAB_READ(sc, SAB_STAR) & SAB_STAR_TEC) == 0)
1126 			return;
1127 		if (--i == 0)
1128 			break;
1129 		DELAY(1);
1130 	}
1131 }
1132 
1133 void
1134 sabtty_reset(sc)
1135 	struct sabtty_softc *sc;
1136 {
1137 	/* power down */
1138 	SAB_WRITE(sc, SAB_CCR0, 0);
1139 
1140 	/* set basic configuration */
1141 	SAB_WRITE(sc, SAB_CCR0,
1142 	    SAB_CCR0_MCE | SAB_CCR0_SC_NRZ | SAB_CCR0_SM_ASYNC);
1143 	SAB_WRITE(sc, SAB_CCR1, SAB_CCR1_ODS | SAB_CCR1_BCR | SAB_CCR1_CM_7);
1144 	SAB_WRITE(sc, SAB_CCR2, SAB_CCR2_BDF | SAB_CCR2_SSEL | SAB_CCR2_TOE);
1145 	SAB_WRITE(sc, SAB_CCR3, 0);
1146 	SAB_WRITE(sc, SAB_CCR4, SAB_CCR4_MCK4 | SAB_CCR4_EBRG);
1147 	SAB_WRITE(sc, SAB_MODE, SAB_MODE_RTS | SAB_MODE_FCTS | SAB_MODE_RAC);
1148 	SAB_WRITE(sc, SAB_RFC,
1149 	    SAB_RFC_DPS | SAB_RFC_RFDF | SAB_RFC_RFTH_32CHAR);
1150 
1151 	/* clear interrupts */
1152 	sc->sc_imr0 = sc->sc_imr1 = 0xff;
1153 	SAB_WRITE(sc, SAB_IMR0, sc->sc_imr0);
1154 	SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1);
1155 	SAB_READ(sc, SAB_ISR0);
1156 	SAB_READ(sc, SAB_ISR1);
1157 }
1158 
1159 void
1160 sabtty_flush(sc)
1161 	struct sabtty_softc *sc;
1162 {
1163 	/* clear rx fifo */
1164 	sabtty_cec_wait(sc);
1165 	SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_RRES);
1166 
1167 	/* clear tx fifo */
1168 	sabtty_cec_wait(sc);
1169 	SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_XRES);
1170 }
1171 
1172 int
1173 sabtty_speed(rate)
1174 	int rate;
1175 {
1176 	int i, len, r;
1177 
1178 	if (rate == 0)
1179 		return (0);
1180 	len = sizeof(sabtty_baudtable)/sizeof(sabtty_baudtable[0]);
1181 	for (i = 0; i < len; i++) {
1182 		if (rate == sabtty_baudtable[i].baud) {
1183 			r = sabtty_baudtable[i].n |
1184 			    (sabtty_baudtable[i].m << 6);
1185 			return (r);
1186 		}
1187 	}
1188 	return (-1);
1189 }
1190 
1191 void
1192 sabtty_cnputc(sc, c)
1193 	struct sabtty_softc *sc;
1194 	int c;
1195 {
1196 	sabtty_tec_wait(sc);
1197 	SAB_WRITE(sc, SAB_TIC, c);
1198 	sabtty_tec_wait(sc);
1199 }
1200 
1201 int
1202 sabtty_cngetc(sc)
1203 	struct sabtty_softc *sc;
1204 {
1205 	u_int8_t r, len;
1206 
1207 again:
1208 	do {
1209 		r = SAB_READ(sc, SAB_STAR);
1210 	} while ((r & SAB_STAR_RFNE) == 0);
1211 
1212 	/*
1213 	 * Ok, at least one byte in RFIFO, ask for permission to access RFIFO
1214 	 * (I hate this chip... hate hate hate).
1215 	 */
1216 	sabtty_cec_wait(sc);
1217 	SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_RFRD);
1218 
1219 	/* Wait for RFIFO to come ready */
1220 	do {
1221 		r = SAB_READ(sc, SAB_ISR0);
1222 	} while ((r & SAB_ISR0_TCD) == 0);
1223 
1224 	len = SAB_READ(sc, SAB_RBCL) & (32 - 1);
1225 	if (len == 0)
1226 		goto again;	/* Shouldn't happen... */
1227 
1228 	r = SAB_READ(sc, SAB_RFIFO);
1229 
1230 	/*
1231 	 * Blow away everything left in the FIFO...
1232 	 */
1233 	sabtty_cec_wait(sc);
1234 	SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_RMC);
1235 	return (r);
1236 }
1237 
1238 void
1239 sabtty_cnpollc(sc, on)
1240 	struct sabtty_softc *sc;
1241 	int on;
1242 {
1243 	u_int8_t r;
1244 
1245 	if (on) {
1246 		if (sc->sc_polling)
1247 			return;
1248 		SAB_WRITE(sc, SAB_IPC, SAB_READ(sc, SAB_IPC) | SAB_IPC_VIS);
1249 		r = sc->sc_pollrfc = SAB_READ(sc, SAB_RFC);
1250 		r &= ~(SAB_RFC_RFDF);
1251 		SAB_WRITE(sc, SAB_RFC, r);
1252 		sabtty_cec_wait(sc);
1253 		SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_RRES);
1254 		sc->sc_polling = 1;
1255 	} else {
1256 		if (!sc->sc_polling)
1257 			return;
1258 		SAB_WRITE(sc, SAB_IPC, SAB_READ(sc, SAB_IPC) & ~SAB_IPC_VIS);
1259 		SAB_WRITE(sc, SAB_RFC, sc->sc_pollrfc);
1260 		sabtty_cec_wait(sc);
1261 		SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_RRES);
1262 		sc->sc_polling = 0;
1263 	}
1264 }
1265 
1266 void
1267 sab_cnputc(dev, c)
1268 	dev_t dev;
1269 	int c;
1270 {
1271 	struct sabtty_softc *sc = sabtty_cons_output;
1272 
1273 	if (sc == NULL)
1274 		return;
1275 	sabtty_cnputc(sc, c);
1276 }
1277 
1278 void
1279 sab_cnpollc(dev, on)
1280 	dev_t dev;
1281 	int on;
1282 {
1283 	struct sabtty_softc *sc = sabtty_cons_input;
1284 
1285 	sabtty_cnpollc(sc, on);
1286 }
1287 
1288 int
1289 sab_cngetc(dev)
1290 	dev_t dev;
1291 {
1292 	struct sabtty_softc *sc = sabtty_cons_input;
1293 
1294 	if (sc == NULL)
1295 		return (-1);
1296 	return (sabtty_cngetc(sc));
1297 }
1298 
1299 void
1300 sabtty_console_flags(sc)
1301 	struct sabtty_softc *sc;
1302 {
1303 	int node, channel, cookie;
1304 	char buf[255];
1305 
1306 	node = sc->sc_parent->sc_node;
1307 	channel = sc->sc_portno;
1308 
1309 	/* Default to channel 0 if there are no explicit prom args */
1310 	cookie = 0;
1311 
1312 	if (node == prom_instance_to_package(prom_stdin())) {
1313 		if (prom_getoption("input-device", buf, sizeof buf) == 0 &&
1314 			strcmp("ttyb", buf) == 0)
1315 				cookie = 1;
1316 
1317 		if (channel == cookie)
1318 			sc->sc_flags |= SABTTYF_CONS_IN;
1319 	}
1320 
1321 	/* Default to same channel if there are no explicit prom args */
1322 
1323 	if (node == prom_instance_to_package(prom_stdout())) {
1324 		if (prom_getoption("output-device", buf, sizeof buf) == 0 &&
1325 			strcmp("ttyb", buf) == 0)
1326 				cookie = 1;
1327 
1328 		if (channel == cookie)
1329 			sc->sc_flags |= SABTTYF_CONS_OUT;
1330 	}
1331 }
1332 
1333 void
1334 sabtty_abort(sc)
1335 	struct sabtty_softc *sc;
1336 {
1337 
1338 	if (sc->sc_flags & SABTTYF_CONS_IN) {
1339 #ifdef DDB
1340 		cn_trap();
1341 #else
1342 		callrom();
1343 #endif
1344 	}
1345 }
1346 
1347 void
1348 sabtty_shutdown(vsc)
1349 	void *vsc;
1350 {
1351 	struct sabtty_softc *sc = vsc;
1352 
1353 	/* Have to put the chip back into single char mode */
1354 	sc->sc_flags |= SABTTYF_DONTDDB;
1355 	SAB_WRITE(sc, SAB_RFC, SAB_READ(sc, SAB_RFC) & ~SAB_RFC_RFDF);
1356 	sabtty_cec_wait(sc);
1357 	SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_RRES);
1358 	sabtty_cec_wait(sc);
1359 }
1360