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