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