sab.c revision 1.14 1 /* $NetBSD: sab.c,v 1.14 2003/07/15 03:36:07 lukem 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 (at) 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.14 2003/07/15 03:36:07 lukem 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 u_int options;
1305 char buf[255];
1306
1307 node = sc->sc_parent->sc_node;
1308 channel = sc->sc_portno;
1309
1310 options = OF_finddevice("/options");
1311
1312 /* Default to channel 0 if there are no explicit prom args */
1313 cookie = 0;
1314
1315 if (node == OF_instance_to_package(OF_stdin())) {
1316 if (OF_getprop(options, "input-device", buf,
1317 sizeof(buf)) != -1) {
1318 if (strcmp("ttyb", buf) == 0)
1319 cookie = 1;
1320 }
1321
1322 if (channel == cookie)
1323 sc->sc_flags |= SABTTYF_CONS_IN;
1324 }
1325
1326 /* Default to same channel if there are no explicit prom args */
1327
1328 if (node == OF_instance_to_package(OF_stdout())) {
1329 if (OF_getprop(options, "output-device", buf,
1330 sizeof(buf)) != -1) {
1331 if (strcmp("ttyb", buf) == 0)
1332 cookie = 1;
1333 }
1334
1335 if (channel == cookie)
1336 sc->sc_flags |= SABTTYF_CONS_OUT;
1337 }
1338 }
1339
1340 void
1341 sabtty_abort(sc)
1342 struct sabtty_softc *sc;
1343 {
1344
1345 if (sc->sc_flags & SABTTYF_CONS_IN) {
1346 #ifdef DDB
1347 cn_trap();
1348 #else
1349 callrom();
1350 #endif
1351 }
1352 }
1353
1354 void
1355 sabtty_shutdown(vsc)
1356 void *vsc;
1357 {
1358 struct sabtty_softc *sc = vsc;
1359
1360 /* Have to put the chip back into single char mode */
1361 sc->sc_flags |= SABTTYF_DONTDDB;
1362 SAB_WRITE(sc, SAB_RFC, SAB_READ(sc, SAB_RFC) & ~SAB_RFC_RFDF);
1363 sabtty_cec_wait(sc);
1364 SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_RRES);
1365 sabtty_cec_wait(sc);
1366 }
1367