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