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