Annotation of sys/arch/mvme88k/dev/dart.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: dart.c,v 1.49 2007/05/19 20:35:20 miod Exp $ */
! 2:
! 3: /*
! 4: * Mach Operating System
! 5: * Copyright (c) 1993-1991 Carnegie Mellon University
! 6: * All Rights Reserved.
! 7: *
! 8: * Permission to use, copy, modify and distribute this software and its
! 9: * documentation is hereby granted, provided that both the copyright
! 10: * notice and this permission notice appear in all copies of the
! 11: * software, derivative works or modified versions, and any portions
! 12: * thereof, and that both notices appear in supporting documentation.
! 13: *
! 14: * CARNEGIE MELLON AND OMRON ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS"
! 15: * CONDITION. CARNEGIE MELLON AND OMRON DISCLAIM ANY LIABILITY OF ANY KIND
! 16: * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
! 17: *
! 18: * Carnegie Mellon requests users of this software to return to
! 19: *
! 20: * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
! 21: * School of Computer Science
! 22: * Carnegie Mellon University
! 23: * Pittsburgh PA 15213-3890
! 24: *
! 25: * any improvements or extensions that they make and grant Carnegie the
! 26: * rights to redistribute these changes.
! 27: */
! 28:
! 29: #include <sys/param.h>
! 30: #include <sys/ioctl.h>
! 31: #include <sys/proc.h>
! 32: #include <sys/tty.h>
! 33: #include <sys/systm.h>
! 34: #include <sys/device.h>
! 35:
! 36: #include <machine/autoconf.h>
! 37: #include <machine/conf.h>
! 38: #include <machine/cpu.h>
! 39:
! 40: #include <dev/cons.h>
! 41:
! 42: #include <machine/mvme188.h>
! 43: #include <mvme88k/dev/sysconreg.h>
! 44: #include <mvme88k/dev/dartreg.h>
! 45:
! 46: #ifdef DDB
! 47: #include <ddb/db_var.h>
! 48: #endif
! 49:
! 50: #define NDARTPORTS 2 /* Number of ports */
! 51:
! 52: struct dart_info {
! 53: struct tty *tty;
! 54: u_char dart_swflags;
! 55: };
! 56:
! 57: /* saved registers */
! 58: struct dart_sv_reg {
! 59: u_int8_t sv_mr1[NDARTPORTS];
! 60: u_int8_t sv_mr2[NDARTPORTS];
! 61: u_int8_t sv_csr[NDARTPORTS];
! 62: u_int8_t sv_cr[NDARTPORTS];
! 63: u_int8_t sv_imr;
! 64: };
! 65:
! 66: struct dartsoftc {
! 67: struct device sc_dev;
! 68: bus_space_tag_t sc_iot;
! 69: bus_space_handle_t sc_ioh;
! 70: struct intrhand sc_ih;
! 71:
! 72: struct dart_sv_reg sc_sv_reg;
! 73: struct dart_info sc_dart[NDARTPORTS];
! 74: };
! 75:
! 76: int dartmatch(struct device *parent, void *self, void *aux);
! 77: void dartattach(struct device *parent, struct device *self, void *aux);
! 78:
! 79: struct cfattach dart_ca = {
! 80: sizeof(struct dartsoftc), dartmatch, dartattach
! 81: };
! 82:
! 83: struct cfdriver dart_cd = {
! 84: NULL, "dart", DV_TTY
! 85: };
! 86:
! 87: /* console is on the first port */
! 88: #define CONS_PORT A_PORT
! 89:
! 90: /* prototypes */
! 91: cons_decl(dart);
! 92: int dart_speed(int);
! 93: struct tty *darttty(dev_t);
! 94: void dartstart(struct tty *);
! 95: int dartmctl(dev_t, int, int);
! 96: int dartparam(struct tty *, struct termios *);
! 97: void dartmodemtrans(struct dartsoftc *, unsigned int, unsigned int);
! 98: void dartrint(struct dartsoftc *, int);
! 99: void dartxint(struct dartsoftc *, int);
! 100: int dartintr(void *);
! 101:
! 102: /*
! 103: * DUART registers are mapped as the least-significant byte of 32-bit
! 104: * addresses. The following macros hide this.
! 105: */
! 106:
! 107: #define DART_SIZE 0x40
! 108: #define dart_read(sc, reg) \
! 109: bus_space_read_1((sc)->sc_iot, (sc)->sc_ioh, 3 + ((reg) << 2))
! 110: #define dart_write(sc, reg, val) \
! 111: bus_space_write_1((sc)->sc_iot, (sc)->sc_ioh, 3 + ((reg) << 2), (val))
! 112:
! 113: #define DART_PORT(dev) minor(dev)
! 114:
! 115: int
! 116: dartmatch(struct device *parent, void *cf, void *aux)
! 117: {
! 118: struct confargs *ca = aux;
! 119: bus_space_handle_t ioh;
! 120: int rc;
! 121:
! 122: if (brdtyp != BRD_188)
! 123: return (0);
! 124:
! 125: /*
! 126: * We do not accept empty locators here...
! 127: */
! 128: if (ca->ca_paddr != DART_BASE)
! 129: return (0);
! 130:
! 131: if (bus_space_map(ca->ca_iot, ca->ca_paddr, DART_SIZE, 0, &ioh) != 0)
! 132: return (0);
! 133: rc = badaddr((vaddr_t)bus_space_vaddr(ca->ca_iot, ioh), 4);
! 134: bus_space_unmap(ca->ca_iot, ca->ca_paddr, DART_SIZE);
! 135:
! 136: return (rc == 0);
! 137: }
! 138:
! 139: void
! 140: dartattach(struct device *parent, struct device *self, void *aux)
! 141: {
! 142: struct dartsoftc *sc = (struct dartsoftc *)self;
! 143: struct confargs *ca = aux;
! 144: bus_space_handle_t ioh;
! 145:
! 146: if (ca->ca_ipl < 0)
! 147: ca->ca_ipl = IPL_TTY;
! 148:
! 149: sc->sc_iot = ca->ca_iot;
! 150: if (bus_space_map(sc->sc_iot, ca->ca_paddr, DART_SIZE, 0, &ioh) != 0) {
! 151: printf(": can't map registers!\n");
! 152: return;
! 153: }
! 154: sc->sc_ioh = ioh;
! 155:
! 156: /* save standard initialization */
! 157: sc->sc_sv_reg.sv_mr1[A_PORT] = PARDIS | RXRTS | CL8;
! 158: sc->sc_sv_reg.sv_mr2[A_PORT] = /* TXCTS | */ SB1;
! 159: sc->sc_sv_reg.sv_csr[A_PORT] = BD9600;
! 160: sc->sc_sv_reg.sv_cr[A_PORT] = TXEN | RXEN;
! 161:
! 162: sc->sc_sv_reg.sv_mr1[B_PORT] = PARDIS | RXRTS | CL8;
! 163: sc->sc_sv_reg.sv_mr2[B_PORT] = /* TXCTS | */ SB1;
! 164: sc->sc_sv_reg.sv_csr[B_PORT] = BD9600;
! 165: sc->sc_sv_reg.sv_cr[B_PORT] = TXEN | RXEN;
! 166:
! 167: /* Start out with Tx and RX interrupts disabled */
! 168: /* Enable input port change interrupt */
! 169: sc->sc_sv_reg.sv_imr = IIPCHG;
! 170:
! 171: /*
! 172: * Although we are still running using the BUG routines,
! 173: * this device will be elected as the console after
! 174: * autoconf.
! 175: * We do not even test since we know we are an MVME188 and
! 176: * console is always on the first port.
! 177: */
! 178: printf(": console");
! 179:
! 180: /* reset port a */
! 181: dart_write(sc, DART_CRA, RXRESET | TXDIS | RXDIS);
! 182: DELAY_CR;
! 183: dart_write(sc, DART_CRA, TXRESET | TXDIS | RXDIS);
! 184: DELAY_CR;
! 185: dart_write(sc, DART_CRA, ERRRESET | TXDIS | RXDIS);
! 186: DELAY_CR;
! 187: dart_write(sc, DART_CRA, BRKINTRESET | TXDIS | RXDIS);
! 188: DELAY_CR;
! 189: dart_write(sc, DART_CRA, MRRESET | TXDIS | RXDIS);
! 190: DELAY_CR;
! 191:
! 192: /* reset port b */
! 193: dart_write(sc, DART_CRB, RXRESET | TXDIS | RXDIS);
! 194: DELAY_CR;
! 195: dart_write(sc, DART_CRB, TXRESET | TXDIS | RXDIS);
! 196: DELAY_CR;
! 197: dart_write(sc, DART_CRB, ERRRESET | TXDIS | RXDIS);
! 198: DELAY_CR;
! 199: dart_write(sc, DART_CRB, BRKINTRESET | TXDIS | RXDIS);
! 200: DELAY_CR;
! 201: dart_write(sc, DART_CRB, MRRESET | TXDIS | RXDIS);
! 202: DELAY_CR;
! 203:
! 204: /* initialize ports */
! 205: dart_write(sc, DART_MR1A, sc->sc_sv_reg.sv_mr1[A_PORT]);
! 206: dart_write(sc, DART_MR2A, sc->sc_sv_reg.sv_mr2[A_PORT]);
! 207: dart_write(sc, DART_CSRA, sc->sc_sv_reg.sv_csr[A_PORT]);
! 208: dart_write(sc, DART_CRA, sc->sc_sv_reg.sv_cr[A_PORT]);
! 209:
! 210: dart_write(sc, DART_MR1B, sc->sc_sv_reg.sv_mr1[B_PORT]);
! 211: dart_write(sc, DART_MR2B, sc->sc_sv_reg.sv_mr2[B_PORT]);
! 212: dart_write(sc, DART_CSRB, sc->sc_sv_reg.sv_csr[B_PORT]);
! 213: dart_write(sc, DART_CRB, sc->sc_sv_reg.sv_cr[B_PORT]);
! 214:
! 215: /* initialize common register of a DUART */
! 216: dart_write(sc, DART_OPRS, OPDTRA | OPRTSA | OPDTRB | OPRTSB);
! 217:
! 218: dart_write(sc, DART_CTUR, SLCTIM >> 8);
! 219: dart_write(sc, DART_CTLR, SLCTIM & 0xff);
! 220: dart_write(sc, DART_ACR, BDSET2 | CCLK16 | IPDCDIB | IPDCDIA);
! 221: dart_write(sc, DART_IMR, sc->sc_sv_reg.sv_imr);
! 222: dart_write(sc, DART_OPCR, OPSET);
! 223: dart_write(sc, DART_IVR, SYSCON_VECT + SYSCV_SCC);
! 224:
! 225: /* enable interrupts */
! 226: sc->sc_ih.ih_fn = dartintr;
! 227: sc->sc_ih.ih_arg = sc;
! 228: sc->sc_ih.ih_wantframe = 0;
! 229: sc->sc_ih.ih_ipl = ca->ca_ipl;
! 230:
! 231: sysconintr_establish(SYSCV_SCC, &sc->sc_ih, self->dv_xname);
! 232: printf("\n");
! 233: }
! 234:
! 235: /* speed tables */
! 236: const struct dart_s {
! 237: int kspeed;
! 238: int dspeed;
! 239: } dart_speeds[] = {
! 240: { B0, 0 }, /* 0 baud, special HUP condition */
! 241: { B50, NOBAUD }, /* 50 baud, not implemented */
! 242: { B75, BD75 }, /* 75 baud */
! 243: { B110, BD110 }, /* 110 baud */
! 244: { B134, BD134 }, /* 134.5 baud */
! 245: { B150, BD150 }, /* 150 baud */
! 246: { B200, NOBAUD }, /* 200 baud, not implemented */
! 247: { B300, BD300 }, /* 300 baud */
! 248: { B600, BD600 }, /* 600 baud */
! 249: { B1200, BD1200 }, /* 1200 baud */
! 250: { B1800, BD1800 }, /* 1800 baud */
! 251: { B2400, BD2400 }, /* 2400 baud */
! 252: { B4800, BD4800 }, /* 4800 baud */
! 253: { B9600, BD9600 }, /* 9600 baud */
! 254: { B19200, BD19200 }, /* 19200 baud */
! 255: { -1, NOBAUD }, /* anything more is uncivilized */
! 256: };
! 257:
! 258: int
! 259: dart_speed(int speed)
! 260: {
! 261: const struct dart_s *ds;
! 262:
! 263: for (ds = dart_speeds; ds->kspeed != -1; ds++)
! 264: if (ds->kspeed == speed)
! 265: return ds->dspeed;
! 266:
! 267: return NOBAUD;
! 268: }
! 269:
! 270: struct tty *
! 271: darttty(dev_t dev)
! 272: {
! 273: unsigned int port;
! 274: struct dartsoftc *sc;
! 275:
! 276: port = DART_PORT(dev);
! 277: if (dart_cd.cd_ndevs == 0 || port >= NDARTPORTS)
! 278: return (NULL);
! 279:
! 280: sc = (struct dartsoftc *)dart_cd.cd_devs[0];
! 281: return sc->sc_dart[port].tty;
! 282: }
! 283:
! 284: void
! 285: dartstart(struct tty *tp)
! 286: {
! 287: struct dartsoftc *sc;
! 288: dev_t dev;
! 289: int s;
! 290: int port, tries;
! 291: int c;
! 292: bus_addr_t ptaddr;
! 293:
! 294: dev = tp->t_dev;
! 295: port = DART_PORT(dev);
! 296: if (dart_cd.cd_ndevs == 0 || port >= NDARTPORTS)
! 297: return;
! 298:
! 299: if ((tp->t_state & TS_ISOPEN) == 0)
! 300: return;
! 301:
! 302: sc = (struct dartsoftc *)dart_cd.cd_devs[0];
! 303: ptaddr = port ? DART_B_BASE : DART_A_BASE;
! 304:
! 305: s = spltty();
! 306:
! 307: if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))
! 308: goto bail;
! 309:
! 310: if (tp->t_outq.c_cc <= tp->t_lowat) {
! 311: if (tp->t_state & TS_ASLEEP) {
! 312: tp->t_state &= ~TS_ASLEEP;
! 313: wakeup((caddr_t)&tp->t_outq);
! 314: }
! 315: selwakeup(&tp->t_wsel);
! 316: if (tp->t_outq.c_cc == 0)
! 317: goto bail;
! 318: }
! 319:
! 320: tp->t_state |= TS_BUSY;
! 321: while (tp->t_outq.c_cc != 0) {
! 322:
! 323: /* load transmitter until it is full */
! 324: for (tries = 10000; tries != 0; tries --)
! 325: if (dart_read(sc, ptaddr + DART_SRA) & TXRDY)
! 326: break;
! 327:
! 328: if (tries == 0) {
! 329: timeout_add(&tp->t_rstrt_to, 1);
! 330: tp->t_state |= TS_TIMEOUT;
! 331: break;
! 332: } else {
! 333: c = getc(&tp->t_outq);
! 334:
! 335: dart_write(sc, ptaddr + DART_TBA, c & 0xff);
! 336:
! 337: if (port == A_PORT)
! 338: sc->sc_sv_reg.sv_imr |= ITXRDYA;
! 339: else
! 340: sc->sc_sv_reg.sv_imr |= ITXRDYB;
! 341: dart_write(sc, DART_IMR, sc->sc_sv_reg.sv_imr);
! 342: }
! 343: }
! 344: tp->t_state &= ~TS_BUSY;
! 345:
! 346: bail:
! 347: splx(s);
! 348: }
! 349:
! 350: int
! 351: dartstop(struct tty *tp, int flag)
! 352: {
! 353: int s;
! 354:
! 355: s = spltty();
! 356: if (tp->t_state & TS_BUSY) {
! 357: if ((tp->t_state & TS_TTSTOP) == 0)
! 358: tp->t_state |= TS_FLUSH;
! 359: }
! 360: splx(s);
! 361:
! 362: return 0;
! 363: }
! 364:
! 365: #define HANDLE_FLAG(_FLAG_, _PORT_, _AFLAG_, _BFLAG_) \
! 366: do { \
! 367: if (flags & (_FLAG_)) { \
! 368: newflags |= ((_PORT_) == A_PORT) ? (_AFLAG_) : (_BFLAG_); \
! 369: flags &= ~(_FLAG_); \
! 370: } \
! 371: } while (0)
! 372:
! 373: /*
! 374: * To be called at spltty - tty already locked.
! 375: * Returns status of carrier.
! 376: */
! 377:
! 378: int
! 379: dartmctl(dev_t dev, int flags, int how)
! 380: {
! 381: struct dartsoftc *sc;
! 382: int port;
! 383: int newflags = 0;
! 384: struct dart_info *dart;
! 385: int s;
! 386:
! 387: port = DART_PORT(dev);
! 388: if (dart_cd.cd_ndevs == 0 || port >= NDARTPORTS)
! 389: return (ENODEV);
! 390:
! 391: sc = (struct dartsoftc *)dart_cd.cd_devs[0];
! 392: dart = &sc->sc_dart[port];
! 393:
! 394: s = spltty();
! 395:
! 396: HANDLE_FLAG(TIOCM_DTR, port, OPDTRA, OPDTRB);
! 397: HANDLE_FLAG(TIOCM_RTS, port, OPRTSA, OPRTSB);
! 398:
! 399: switch (how) {
! 400: case DMSET:
! 401: dart_write(sc, DART_OPRS, newflags);
! 402: dart_write(sc, DART_OPRR, ~newflags);
! 403: break;
! 404: case DMBIS:
! 405: dart_write(sc, DART_OPRS, newflags);
! 406: break;
! 407: case DMBIC:
! 408: dart_write(sc, DART_OPRR, newflags);
! 409: break;
! 410: case DMGET:
! 411: flags = 0; /* XXX not supported */
! 412: break;
! 413: }
! 414:
! 415: splx(s);
! 416: return (flags);
! 417: }
! 418:
! 419: int
! 420: dartioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
! 421: {
! 422: int error;
! 423: int port;
! 424: struct tty *tp;
! 425: struct dart_info *dart;
! 426: struct dartsoftc *sc;
! 427:
! 428: port = DART_PORT(dev);
! 429: sc = (struct dartsoftc *)dart_cd.cd_devs[0];
! 430: dart = &sc->sc_dart[port];
! 431:
! 432: tp = dart->tty;
! 433: if (tp == NULL)
! 434: return (ENXIO);
! 435:
! 436: error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
! 437: if (error >= 0)
! 438: return(error);
! 439:
! 440: error = ttioctl(tp, cmd, data, flag, p);
! 441: if (error >= 0)
! 442: return(error);
! 443:
! 444: switch (cmd) {
! 445: case TIOCSBRK:
! 446: case TIOCCBRK:
! 447: break;
! 448: case TIOCSDTR:
! 449: (void)dartmctl(dev, TIOCM_DTR | TIOCM_RTS, DMBIS);
! 450: break;
! 451: case TIOCCDTR:
! 452: (void)dartmctl(dev, TIOCM_DTR | TIOCM_RTS, DMBIC);
! 453: break;
! 454: case TIOCMSET:
! 455: (void)dartmctl(dev, *(int *) data, DMSET);
! 456: break;
! 457: case TIOCMBIS:
! 458: (void)dartmctl(dev, *(int *) data, DMBIS);
! 459: break;
! 460: case TIOCMBIC:
! 461: (void)dartmctl(dev, *(int *) data, DMBIC);
! 462: break;
! 463: case TIOCMGET:
! 464: *(int *)data = dartmctl(dev, 0, DMGET);
! 465: break;
! 466: case TIOCGFLAGS:
! 467: if (CONS_PORT == port)
! 468: dart->dart_swflags |= TIOCFLAG_SOFTCAR;
! 469: *(int *)data = dart->dart_swflags;
! 470: break;
! 471: case TIOCSFLAGS:
! 472: error = suser(p, 0);
! 473: if (error != 0)
! 474: return (EPERM);
! 475:
! 476: dart->dart_swflags = *(int *)data;
! 477: if (CONS_PORT == port)
! 478: dart->dart_swflags |= TIOCFLAG_SOFTCAR;
! 479: dart->dart_swflags &= /* only allow valid flags */
! 480: (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL | TIOCFLAG_CRTSCTS);
! 481: break;
! 482: default:
! 483: return (ENOTTY);
! 484: }
! 485:
! 486: return (0);
! 487: }
! 488:
! 489: int
! 490: dartparam(struct tty *tp, struct termios *t)
! 491: {
! 492: int flags;
! 493: int port;
! 494: int speeds;
! 495: unsigned char mr1, mr2;
! 496: struct dart_info *dart;
! 497: struct dartsoftc *sc;
! 498: dev_t dev;
! 499: bus_addr_t ptaddr;
! 500:
! 501: dev = tp->t_dev;
! 502: sc = (struct dartsoftc *)dart_cd.cd_devs[0];
! 503: port = DART_PORT(dev);
! 504: dart = &sc->sc_dart[port];
! 505: ptaddr = port ? DART_B_BASE : DART_A_BASE;
! 506:
! 507: tp->t_ispeed = t->c_ispeed;
! 508: tp->t_ospeed = t->c_ospeed;
! 509: tp->t_cflag = t->c_cflag;
! 510:
! 511: flags = tp->t_flags;
! 512:
! 513: /* Reset to make global changes*/
! 514: /* disable Tx and Rx */
! 515:
! 516: if (CONS_PORT != port) {
! 517: if (port == A_PORT)
! 518: sc->sc_sv_reg.sv_imr &= ~(ITXRDYA | IRXRDYA);
! 519: else
! 520: sc->sc_sv_reg.sv_imr &= ~(ITXRDYB | IRXRDYB);
! 521: dart_write(sc, DART_IMR, sc->sc_sv_reg.sv_imr);
! 522:
! 523: /* hang up on zero baud rate */
! 524: if (tp->t_ispeed == 0) {
! 525: dartmctl(dev, HUPCL, DMSET);
! 526: return (0);
! 527: } else {
! 528: /* set baudrate */
! 529: speeds = dart_speed(tp->t_ispeed);
! 530: if (speeds == NOBAUD)
! 531: speeds = sc->sc_sv_reg.sv_csr[port];
! 532: dart_write(sc, ptaddr + DART_CSRA, speeds);
! 533: sc->sc_sv_reg.sv_csr[port] = speeds;
! 534: }
! 535:
! 536: /* get saved mode registers and clear set up parameters */
! 537: mr1 = sc->sc_sv_reg.sv_mr1[port];
! 538: mr1 &= ~(CLMASK | PARTYPEMASK | PARMODEMASK);
! 539:
! 540: mr2 = sc->sc_sv_reg.sv_mr2[port];
! 541: mr2 &= ~SBMASK;
! 542:
! 543: /* set up character size */
! 544: if (flags & CS8)
! 545: mr1 |= CL8;
! 546: else if (tp->t_ispeed == B134)
! 547: mr1 |= CL6;
! 548: else
! 549: mr1 |= CL7;
! 550:
! 551: /* set up stop bits */
! 552: if (tp->t_ospeed == B110)
! 553: mr2 |= SB2;
! 554: else
! 555: mr2 |= SB1;
! 556:
! 557: /* set up parity */
! 558: if (((flags & PARENB) != PARENB) &&
! 559: (flags & PARENB)) {
! 560: mr1 |= PAREN;
! 561: if (flags & PARODD)
! 562: mr1 |= ODDPAR;
! 563: else
! 564: mr1 |= EVENPAR;
! 565: } else
! 566: mr1 |= PARDIS;
! 567:
! 568: if (sc->sc_sv_reg.sv_mr1[port] != mr1 ||
! 569: sc->sc_sv_reg.sv_mr2[port] != mr2) {
! 570: /* write mode registers to duart */
! 571: dart_write(sc, ptaddr + DART_CRA, MRRESET);
! 572: dart_write(sc, ptaddr + DART_MR1A, mr1);
! 573: dart_write(sc, ptaddr + DART_MR2A, mr2);
! 574:
! 575: /* save changed mode registers */
! 576: sc->sc_sv_reg.sv_mr1[port] = mr1;
! 577: sc->sc_sv_reg.sv_mr2[port] = mr2;
! 578: }
! 579: }
! 580:
! 581: /* enable transmitter? */
! 582: if (tp->t_state & TS_BUSY) {
! 583: if (port == A_PORT)
! 584: sc->sc_sv_reg.sv_imr |= ITXRDYA;
! 585: else
! 586: sc->sc_sv_reg.sv_imr |= ITXRDYB;
! 587: dart_write(sc, DART_IMR, sc->sc_sv_reg.sv_imr);
! 588: }
! 589:
! 590: /* re-enable the receiver */
! 591: DELAY_CR;
! 592: if (port == A_PORT)
! 593: sc->sc_sv_reg.sv_imr |= IRXRDYA;
! 594: else
! 595: sc->sc_sv_reg.sv_imr |= IRXRDYB;
! 596: dart_write(sc, DART_IMR, sc->sc_sv_reg.sv_imr);
! 597:
! 598: return (0);
! 599: }
! 600:
! 601: void
! 602: dartmodemtrans(struct dartsoftc *sc, unsigned int ip, unsigned int ipcr)
! 603: {
! 604: unsigned int dcdstate;
! 605: struct tty *tp;
! 606: int port;
! 607: struct dart_info *dart;
! 608:
! 609: /* input is inverted at port!!! */
! 610: if (ipcr & IPCRDCDA) {
! 611: port = A_PORT;
! 612: dcdstate = !(ip & IPDCDA);
! 613: } else if (ipcr & IPCRDCDB) {
! 614: port = B_PORT;
! 615: dcdstate = !(ip & IPDCDB);
! 616: } else {
! 617: printf("dartmodemtrans: unknown transition ip=0x%x ipcr=0x%x\n",
! 618: ip, ipcr);
! 619: return;
! 620: }
! 621:
! 622: dart = &sc->sc_dart[port];
! 623: tp = dart->tty;
! 624: if (tp != NULL)
! 625: ttymodem(tp, dcdstate);
! 626: }
! 627:
! 628: int
! 629: dartopen(dev_t dev, int flag, int mode, struct proc *p)
! 630: {
! 631: int s, port;
! 632: struct dart_info *dart;
! 633: struct dartsoftc *sc;
! 634: struct tty *tp;
! 635:
! 636: port = DART_PORT(dev);
! 637: if (dart_cd.cd_ndevs == 0 || port >= NDARTPORTS)
! 638: return (ENODEV);
! 639: sc = (struct dartsoftc *)dart_cd.cd_devs[0]; /* the only one */
! 640: dart = &sc->sc_dart[port];
! 641:
! 642: s = spltty();
! 643: if (dart->tty != NULL)
! 644: tp = dart->tty;
! 645: else
! 646: tp = dart->tty = ttymalloc();
! 647:
! 648: tp->t_oproc = dartstart;
! 649: tp->t_param = dartparam;
! 650: tp->t_dev = dev;
! 651:
! 652: if ((tp->t_state & TS_ISOPEN) == 0) {
! 653: ttychars(tp);
! 654: tp->t_iflag = TTYDEF_IFLAG;
! 655: tp->t_oflag = TTYDEF_OFLAG;
! 656: tp->t_lflag = TTYDEF_LFLAG;
! 657: tp->t_ispeed = tp->t_ospeed = B9600;
! 658: dartparam(tp, &tp->t_termios);
! 659: if (port == CONS_PORT) {
! 660: /* console is 8N1 */
! 661: tp->t_cflag = (CREAD | CS8 | HUPCL);
! 662: } else {
! 663: tp->t_cflag = TTYDEF_CFLAG;
! 664: }
! 665: ttsetwater(tp);
! 666: (void)dartmctl(dev, TIOCM_DTR | TIOCM_RTS, DMSET);
! 667: tp->t_state |= TS_CARR_ON;
! 668: } else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) {
! 669: splx(s);
! 670: return (EBUSY);
! 671: }
! 672:
! 673: /*
! 674: * Reset the tty pointer, as there could have been a dialout
! 675: * use of the tty with a dialin open waiting.
! 676: */
! 677: tp->t_dev = dev;
! 678: splx(s);
! 679: return ((*linesw[tp->t_line].l_open)(dev, tp));
! 680: }
! 681:
! 682: int
! 683: dartclose(dev_t dev, int flag, int mode, struct proc *p)
! 684: {
! 685: struct tty *tp;
! 686: struct dart_info *dart;
! 687: struct dartsoftc *sc;
! 688: int port;
! 689:
! 690: sc = (struct dartsoftc *)dart_cd.cd_devs[0];
! 691: port = DART_PORT(dev);
! 692: dart = &sc->sc_dart[port];
! 693:
! 694: tp = dart->tty;
! 695: (*linesw[tp->t_line].l_close)(tp, flag);
! 696: ttyclose(tp);
! 697:
! 698: return (0);
! 699: }
! 700:
! 701: int
! 702: dartread(dev_t dev, struct uio *uio, int flag)
! 703: {
! 704: int port;
! 705: struct tty *tp;
! 706: struct dart_info *dart;
! 707: struct dartsoftc *sc;
! 708:
! 709: sc = (struct dartsoftc *)dart_cd.cd_devs[0];
! 710: port = DART_PORT(dev);
! 711: dart = &sc->sc_dart[port];
! 712:
! 713: tp = dart->tty;
! 714: if (tp == NULL)
! 715: return (ENXIO);
! 716: return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
! 717: }
! 718:
! 719: int
! 720: dartwrite(dev_t dev, struct uio *uio, int flag)
! 721: {
! 722: int port;
! 723: struct tty *tp;
! 724: struct dart_info *dart;
! 725: struct dartsoftc *sc;
! 726:
! 727: sc = (struct dartsoftc *)dart_cd.cd_devs[0];
! 728: port = DART_PORT(dev);
! 729: dart = &sc->sc_dart[port];
! 730:
! 731: tp = dart->tty;
! 732: if (tp == NULL)
! 733: return (ENXIO);
! 734: return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
! 735: }
! 736:
! 737: void
! 738: dartrint(struct dartsoftc *sc, int port)
! 739: {
! 740: struct tty *tp;
! 741: unsigned char data, sr;
! 742: struct dart_info *dart;
! 743: bus_addr_t ptaddr;
! 744:
! 745: dart = &sc->sc_dart[port];
! 746: ptaddr = port ? DART_B_BASE : DART_A_BASE;
! 747: tp = dart->tty;
! 748:
! 749: /* read status reg */
! 750: while ((sr = dart_read(sc, ptaddr + DART_SRA)) & RXRDY) {
! 751: /* read data and reset receiver */
! 752: data = dart_read(sc, ptaddr + DART_RBA);
! 753:
! 754: if ((tp->t_state & (TS_ISOPEN|TS_WOPEN)) == 0 &&
! 755: CONS_PORT != port) {
! 756: return;
! 757: }
! 758:
! 759: if (sr & RBRK) {
! 760: /* clear break state */
! 761: dart_write(sc, ptaddr + DART_CRA, BRKINTRESET);
! 762: DELAY_CR;
! 763: dart_write(sc, ptaddr + DART_CRA, ERRRESET);
! 764:
! 765: #if defined(DDB)
! 766: if (db_console != 0 && port == CONS_PORT)
! 767: Debugger();
! 768: #endif
! 769: } else {
! 770: if (sr & (FRERR|PERR|ROVRN)) { /* errors */
! 771: if (sr & ROVRN)
! 772: printf("%s: receiver overrun port %c\n",
! 773: sc->sc_dev.dv_xname, 'A' + port);
! 774: if (sr & FRERR)
! 775: printf("%s: framing error port %c\n",
! 776: sc->sc_dev.dv_xname, 'A' + port);
! 777: if (sr & PERR)
! 778: printf("%s: parity error port %c\n",
! 779: sc->sc_dev.dv_xname, 'A' + port);
! 780: /* clear error state */
! 781: dart_write(sc, ptaddr + DART_CRA, ERRRESET);
! 782: } else {
! 783: /* no errors */
! 784: (*linesw[tp->t_line].l_rint)(data,tp);
! 785: #if 0
! 786: {
! 787: if (tp->t_ispeed == B134) /* CS6 */
! 788: data &= 077;
! 789: else if (tp->t_flags & CS8)
! 790: ;
! 791: else
! 792: data &= 0177; /* CS7 */
! 793: ttyinput(data, tp);
! 794: }
! 795: #endif
! 796: }
! 797: }
! 798: }
! 799: }
! 800:
! 801: void
! 802: dartxint(struct dartsoftc *sc, int port)
! 803: {
! 804: struct tty *tp;
! 805: struct dart_info *dart;
! 806:
! 807: dart = &sc->sc_dart[port];
! 808: tp = dart->tty;
! 809:
! 810: if ((tp->t_state & (TS_ISOPEN|TS_WOPEN))==0)
! 811: goto out;
! 812:
! 813: if (tp->t_state & TS_FLUSH)
! 814: tp->t_state &= ~TS_FLUSH;
! 815:
! 816: if (tp->t_state & TS_BUSY) {
! 817: tp->t_state &= ~TS_BUSY;
! 818: dartstart(tp);
! 819: if (tp->t_state & TS_BUSY) {
! 820: return;
! 821: }
! 822: }
! 823: out:
! 824:
! 825: /* disable transmitter */
! 826: if (port == 0)
! 827: sc->sc_sv_reg.sv_imr &= ~ITXRDYA;
! 828: else
! 829: sc->sc_sv_reg.sv_imr &= ~ITXRDYB;
! 830:
! 831: dart_write(sc, DART_IMR, sc->sc_sv_reg.sv_imr);
! 832: }
! 833:
! 834: int
! 835: dartintr(void *arg)
! 836: {
! 837: struct dartsoftc *sc = arg;
! 838: unsigned char isr, imr;
! 839: int port;
! 840:
! 841: /* read interrupt status register and mask with imr */
! 842: isr = dart_read(sc, DART_ISR);
! 843: imr = sc->sc_sv_reg.sv_imr;
! 844:
! 845: if ((isr & imr) == 0) {
! 846: /*
! 847: * We got an interrupt on a disabled condition (such as TX
! 848: * ready change on a disabled port). This should not happen,
! 849: * but we have to claim the interrupt anyway.
! 850: */
! 851: #if defined(DIAGNOSTIC) && !defined(MULTIPROCESSOR)
! 852: printf("dartintr: spurious interrupt, isr %x imr %x\n",
! 853: isr, imr);
! 854: #endif
! 855: return (1);
! 856: }
! 857: isr &= imr;
! 858:
! 859: if (isr & IIPCHG) {
! 860: unsigned int ip, ipcr;
! 861:
! 862: ip = dart_read(sc, DART_IP);
! 863: ipcr = dart_read(sc, DART_IPCR);
! 864: dartmodemtrans(sc, ip, ipcr);
! 865: return (1);
! 866: }
! 867:
! 868: if (isr & (IRXRDYA | ITXRDYA))
! 869: port = 0;
! 870: else if (isr & (IRXRDYB | ITXRDYB))
! 871: port = 1;
! 872: else {
! 873: printf("dartintr: spurious interrupt, isr 0x%08x\n", isr);
! 874: return (1); /* claim it anyway */
! 875: }
! 876:
! 877: if (isr & (IRXRDYA | IRXRDYB)) {
! 878: dartrint(sc, port);
! 879: }
! 880: if (isr & (ITXRDYA | ITXRDYB)) {
! 881: dartxint(sc, port);
! 882: }
! 883: if ((port == A_PORT && (isr & IBRKA)) ||
! 884: (port == B_PORT && (isr & IBRKB))) {
! 885: dart_write(sc, port ? DART_CRB : DART_CRA, BRKINTRESET);
! 886: }
! 887:
! 888: return (1);
! 889: }
! 890:
! 891: /*
! 892: * Console interface routines.
! 893: * Since we select the actual console after all devices are attached,
! 894: * we can safely pick the appropriate softc and use its information.
! 895: */
! 896:
! 897: void
! 898: dartcnprobe(struct consdev *cp)
! 899: {
! 900: int maj;
! 901:
! 902: if (brdtyp != BRD_188 || badaddr(DART_BASE, 4) != 0)
! 903: return;
! 904:
! 905: /* do not attach as console if dart has been disabled */
! 906: if (dart_cd.cd_ndevs == 0 || dart_cd.cd_devs[0] == NULL)
! 907: return;
! 908:
! 909: /* locate the major number */
! 910: for (maj = 0; maj < nchrdev; maj++)
! 911: if (cdevsw[maj].d_open == dartopen)
! 912: break;
! 913: if (maj == nchrdev)
! 914: return;
! 915:
! 916: cp->cn_dev = makedev(maj, CONS_PORT);
! 917: cp->cn_pri = CN_NORMAL;
! 918: }
! 919:
! 920: void
! 921: dartcninit(cp)
! 922: struct consdev *cp;
! 923: {
! 924: }
! 925:
! 926: void
! 927: dartcnputc(dev_t dev, int c)
! 928: {
! 929: struct dartsoftc *sc;
! 930: int s;
! 931: int port;
! 932: bus_addr_t ptaddr;
! 933:
! 934: sc = (struct dartsoftc *)dart_cd.cd_devs[0];
! 935: port = DART_PORT(dev);
! 936: ptaddr = port ? DART_B_BASE : DART_A_BASE;
! 937:
! 938: s = spltty();
! 939:
! 940: /* inhibit interrupts on the chip */
! 941: dart_write(sc, DART_IMR, sc->sc_sv_reg.sv_imr & ~ITXRDYA);
! 942: /* make sure transmitter is enabled */
! 943: DELAY_CR;
! 944: dart_write(sc, ptaddr + DART_CRA, TXEN);
! 945:
! 946: while ((dart_read(sc, ptaddr + DART_SRA) & TXRDY) == 0)
! 947: ;
! 948: dart_write(sc, ptaddr + DART_TBA, c);
! 949:
! 950: /* wait for transmitter to empty */
! 951: while ((dart_read(sc, ptaddr + DART_SRA) & TXEMT) == 0)
! 952: ;
! 953:
! 954: /* restore the previous state */
! 955: dart_write(sc, DART_IMR, sc->sc_sv_reg.sv_imr);
! 956: DELAY_CR;
! 957: dart_write(sc, ptaddr + DART_CRA, sc->sc_sv_reg.sv_cr[0]);
! 958:
! 959: splx(s);
! 960: }
! 961:
! 962: int
! 963: dartcngetc(dev_t dev)
! 964: {
! 965: struct dartsoftc *sc;
! 966: unsigned char sr; /* status reg of port a/b */
! 967: u_char c; /* received character */
! 968: int s;
! 969: int port;
! 970: bus_addr_t ptaddr;
! 971:
! 972: sc = (struct dartsoftc *)dart_cd.cd_devs[0];
! 973: port = DART_PORT(dev);
! 974: ptaddr = port ? DART_B_BASE : DART_A_BASE;
! 975:
! 976: s = spltty();
! 977:
! 978: /* enable receiver */
! 979: dart_write(sc, ptaddr + DART_CRA, RXEN);
! 980:
! 981: for (;;) {
! 982: /* read status reg */
! 983: sr = dart_read(sc, ptaddr + DART_SRA);
! 984:
! 985: /* receiver interrupt handler*/
! 986: if (sr & RXRDY) {
! 987: /* read character from port */
! 988: c = dart_read(sc, ptaddr + DART_RBA);
! 989:
! 990: /* check break condition */
! 991: if (sr & RBRK) {
! 992: /* clear break state */
! 993: dart_write(sc, ptaddr + DART_CRA, BRKINTRESET);
! 994: DELAY_CR;
! 995: dart_write(sc, ptaddr + DART_CRA, ERRRESET);
! 996: break;
! 997: }
! 998:
! 999: if (sr & (FRERR | PERR | ROVRN)) {
! 1000: /* clear error state */
! 1001: dart_write(sc, ptaddr + DART_CRA, ERRRESET);
! 1002: DELAY_CR;
! 1003: dart_write(sc, ptaddr + DART_CRA, BRKINTRESET);
! 1004: } else {
! 1005: break;
! 1006: }
! 1007: }
! 1008: }
! 1009: splx(s);
! 1010:
! 1011: return ((int)c);
! 1012: }
CVSweb