Annotation of sys/arch/vax/qbus/dl.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: dl.c,v 1.5 2003/10/03 16:44:50 miod Exp $ */
! 2: /* $NetBSD: dl.c,v 1.11 2000/01/24 02:40:29 matt Exp $ */
! 3:
! 4: /*-
! 5: * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
! 6: * All rights reserved.
! 7: *
! 8: * This code is derived from software contributed to The NetBSD Foundation
! 9: * by Jason R. Thorpe.
! 10: *
! 11: * Redistribution and use in source and binary forms, with or without
! 12: * modification, are permitted provided that the following conditions
! 13: * are met:
! 14: * 1. Redistributions of source code must retain the above copyright
! 15: * notice, this list of conditions and the following disclaimer.
! 16: * 2. Redistributions in binary form must reproduce the above copyright
! 17: * notice, this list of conditions and the following disclaimer in the
! 18: * documentation and/or other materials provided with the distribution.
! 19: * 3. All advertising materials mentioning features or use of this software
! 20: * must display the following acknowledgement:
! 21: * This product includes software developed by the NetBSD
! 22: * Foundation, Inc. and its contributors.
! 23: * 4. Neither the name of The NetBSD Foundation nor the names of its
! 24: * contributors may be used to endorse or promote products derived
! 25: * from this software without specific prior written permission.
! 26: *
! 27: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
! 28: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
! 29: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
! 30: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
! 31: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
! 32: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
! 33: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
! 34: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
! 35: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
! 36: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
! 37: * POSSIBILITY OF SUCH DAMAGE.
! 38: */
! 39:
! 40: /*
! 41: * Copyright (c) 1997 Ben Harris. All rights reserved.
! 42: * Copyright (c) 1996 Ken C. Wellsch. All rights reserved.
! 43: * Copyright (c) 1982, 1986, 1990, 1992, 1993
! 44: * The Regents of the University of California. All rights reserved.
! 45: *
! 46: * This code is derived from software contributed to Berkeley by
! 47: * Ralph Campbell and Rick Macklem.
! 48: *
! 49: * Redistribution and use in source and binary forms, with or without
! 50: * modification, are permitted provided that the following conditions
! 51: * are met:
! 52: * 1. Redistributions of source code must retain the above copyright
! 53: * notice, this list of conditions and the following disclaimer.
! 54: * 2. Redistributions in binary form must reproduce the above copyright
! 55: * notice, this list of conditions and the following disclaimer in the
! 56: * documentation and/or other materials provided with the distribution.
! 57: * 3. Neither the name of the University nor the names of its contributors
! 58: * may be used to endorse or promote products derived from this software
! 59: * without specific prior written permission.
! 60: *
! 61: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 62: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 63: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 64: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 65: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 66: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 67: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 68: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 69: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 70: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 71: * SUCH DAMAGE.
! 72: */
! 73:
! 74: /*
! 75: * dl.c -- Device driver for the DL11 and DLV11 serial cards.
! 76: *
! 77: * OS-interface code derived from the dz and dca (hp300) drivers.
! 78: */
! 79:
! 80: #include <sys/param.h>
! 81: #include <sys/systm.h>
! 82: #include <sys/ioctl.h>
! 83: #include <sys/tty.h>
! 84: #include <sys/proc.h>
! 85: #include <sys/buf.h>
! 86: #include <sys/conf.h>
! 87: #include <sys/file.h>
! 88: #include <sys/uio.h>
! 89: #include <sys/kernel.h>
! 90: #include <sys/syslog.h>
! 91: #include <sys/device.h>
! 92:
! 93: #include <machine/bus.h>
! 94: #include <machine/scb.h>
! 95:
! 96: #include <arch/vax/qbus/ubavar.h>
! 97: #include <arch/vax/qbus/dlreg.h>
! 98:
! 99: struct dl_softc {
! 100: struct device sc_dev;
! 101: bus_space_tag_t sc_iot;
! 102: bus_space_handle_t sc_ioh;
! 103: struct tty *sc_tty;
! 104: };
! 105:
! 106: static int dl_match(struct device *, struct cfdata *, void *);
! 107: static void dl_attach(struct device *, struct device *, void *);
! 108: static void dlrint(void *);
! 109: static void dlxint(void *);
! 110: static void dlstart(struct tty *);
! 111: static int dlparam(struct tty *, struct termios *);
! 112: static void dlbrk(struct dl_softc *, int);
! 113: struct tty * dltty(dev_t);
! 114: int dlopen(dev_t, int, int, struct proc *);
! 115: int dlclose(dev_t, int, int, struct proc *);
! 116: int dlread(dev_t, struct uio *, int);
! 117: int dlwrite(dev_t, struct uio *, int);
! 118: int dlioctl(dev_t, int, caddr_t, int, struct proc *);
! 119: void dlstop(struct tty *, int);
! 120:
! 121: struct cfattach dl_ca = {
! 122: sizeof(struct dl_softc), (cfmatch_t)dl_match, dl_attach
! 123: };
! 124:
! 125: struct cfdriver dl_cd = {
! 126: NULL, "dl", DV_TTY
! 127: };
! 128:
! 129: #define DL_READ_WORD(reg) \
! 130: bus_space_read_2(sc->sc_iot, sc->sc_ioh, reg)
! 131: #define DL_WRITE_WORD(reg, val) \
! 132: bus_space_write_2(sc->sc_iot, sc->sc_ioh, reg, val)
! 133: #define DL_WRITE_BYTE(reg, val) \
! 134: bus_space_write_1(sc->sc_iot, sc->sc_ioh, reg, val)
! 135:
! 136: /* Autoconfig handles: setup the controller to interrupt, */
! 137: /* then complete the housecleaning for full operation */
! 138:
! 139: static int
! 140: dl_match (parent, cf, aux)
! 141: struct device * parent;
! 142: struct cfdata *cf;
! 143: void *aux;
! 144: {
! 145: struct uba_attach_args *ua = aux;
! 146:
! 147: #ifdef DL_DEBUG
! 148: printf("Probing for dl at %lo ... ", (long)ua->ua_iaddr);
! 149: #endif
! 150:
! 151: bus_space_write_2(ua->ua_iot, ua->ua_ioh, DL_UBA_XCSR, DL_XCSR_TXIE);
! 152: if (bus_space_read_2(ua->ua_iot, ua->ua_ioh, DL_UBA_XCSR) !=
! 153: (DL_XCSR_TXIE | DL_XCSR_TX_READY)) {
! 154: #ifdef DL_DEBUG
! 155: printf("failed (step 1; XCSR = %.4b)\n",
! 156: bus_space_read_2(ua->ua_iot, ua->ua_ioh, DL_UBA_XCSR),
! 157: DL_XCSR_BITS);
! 158: #endif
! 159: return 0;
! 160: }
! 161:
! 162: /*
! 163: * We have to force an interrupt so the uba driver can work
! 164: * out where we are. Unfortunately, the only way to make a
! 165: * DL11 interrupt is to get it to send or receive a
! 166: * character. We'll send a NUL and hope it doesn't hurt
! 167: * anything.
! 168: */
! 169:
! 170: bus_space_write_1(ua->ua_iot, ua->ua_ioh, DL_UBA_XBUFL, '\0');
! 171: #if 0 /* This test seems to fail 2/3 of the time :-( */
! 172: if (dladdr->dl_xcsr != (DL_XCSR_TXIE)) {
! 173: #ifdef DL_DEBUG
! 174: printf("failed (step 2; XCSR = %.4b)\n", dladdr->dl_xcsr,
! 175: DL_XCSR_BITS);
! 176: #endif
! 177: return 0;
! 178: }
! 179: #endif
! 180: DELAY(100000); /* delay 1/10 s for character to transmit */
! 181: if (bus_space_read_2(ua->ua_iot, ua->ua_ioh, DL_UBA_XCSR) !=
! 182: (DL_XCSR_TXIE | DL_XCSR_TX_READY)) {
! 183: #ifdef DL_DEBUG
! 184: printf("failed (step 3; XCSR = %.4b)\n",
! 185: bus_space_read_2(ua->ua_iot, ua->ua_ioh, DL_UBA_XCSR),
! 186: DL_XCSR_BITS);
! 187: #endif
! 188: return 0;
! 189: }
! 190:
! 191:
! 192: /* What else do I need to do? */
! 193:
! 194: return 1;
! 195:
! 196: }
! 197:
! 198: static void
! 199: dl_attach (parent, self, aux)
! 200: struct device *parent, *self;
! 201: void *aux;
! 202: {
! 203: struct dl_softc *sc = (void *)self;
! 204: register struct uba_attach_args *ua = aux;
! 205:
! 206: sc->sc_iot = ua->ua_iot;
! 207: sc->sc_ioh = ua->ua_ioh;
! 208:
! 209: /* Tidy up the device */
! 210:
! 211: DL_WRITE_WORD(DL_UBA_RCSR, DL_RCSR_RXIE);
! 212: DL_WRITE_WORD(DL_UBA_XCSR, DL_XCSR_TXIE);
! 213:
! 214: /* Initialize our softc structure. Should be done in open? */
! 215:
! 216: sc->sc_tty = ttymalloc();
! 217:
! 218: /* Now register the TX & RX interrupt handlers */
! 219: uba_intr_establish(ua->ua_icookie, ua->ua_cvec , dlxint, sc);
! 220: uba_intr_establish(ua->ua_icookie, ua->ua_cvec - 4, dlrint, sc);
! 221:
! 222: printf("\n");
! 223: }
! 224:
! 225: /* Receiver Interrupt Handler */
! 226:
! 227: static void
! 228: dlrint(arg)
! 229: void *arg;
! 230: {
! 231: struct dl_softc *sc = arg;
! 232: register struct tty *tp;
! 233: register int cc;
! 234: register unsigned c;
! 235:
! 236: if (DL_READ_WORD(DL_UBA_RCSR) & DL_RCSR_RX_DONE) {
! 237: c = DL_READ_WORD(DL_UBA_RBUF);
! 238: cc = c & 0xFF;
! 239: tp = sc->sc_tty;
! 240:
! 241: if (!(tp->t_state & TS_ISOPEN)) {
! 242: wakeup((caddr_t)&tp->t_rawq);
! 243: return;
! 244: }
! 245:
! 246: if (c & DL_RBUF_OVERRUN_ERR)
! 247: /*
! 248: * XXX: This should really be logged somwhere
! 249: * else where we can afford the time.
! 250: */
! 251: log(LOG_WARNING, "%s: rx overrun\n",
! 252: sc->sc_dev.dv_xname);
! 253: if (c & DL_RBUF_FRAMING_ERR)
! 254: cc |= TTY_FE;
! 255: if (c & DL_RBUF_PARITY_ERR)
! 256: cc |= TTY_PE;
! 257:
! 258: (*linesw[tp->t_line].l_rint)(cc, tp);
! 259: } else
! 260: log(LOG_WARNING, "%s: stray rx interrupt\n",
! 261: sc->sc_dev.dv_xname);
! 262: return;
! 263: }
! 264:
! 265: /* Transmitter Interrupt Handler */
! 266:
! 267: static void
! 268: dlxint(arg)
! 269: void *arg;
! 270: {
! 271: struct dl_softc *sc = arg;
! 272: register struct tty *tp;
! 273:
! 274: tp = sc->sc_tty;
! 275: tp->t_state &= ~(TS_BUSY | TS_FLUSH);
! 276: if (tp->t_line)
! 277: (*linesw[tp->t_line].l_start)(tp);
! 278: else
! 279: dlstart(tp);
! 280:
! 281: return;
! 282: }
! 283:
! 284: int
! 285: dlopen(dev, flag, mode, p)
! 286: dev_t dev;
! 287: int flag, mode;
! 288: struct proc *p;
! 289: {
! 290: register struct tty *tp;
! 291: register int unit;
! 292: struct dl_softc *sc;
! 293:
! 294: unit = minor(dev);
! 295:
! 296: if (unit >= dl_cd.cd_ndevs || dl_cd.cd_devs[unit] == NULL)
! 297: return ENXIO;
! 298: sc = dl_cd.cd_devs[unit];
! 299:
! 300: tp = sc->sc_tty;
! 301: if (tp == NULL)
! 302: return ENODEV;
! 303: tp->t_oproc = dlstart;
! 304: tp->t_param = dlparam;
! 305: tp->t_dev = dev;
! 306:
! 307: if (!(tp->t_state & TS_ISOPEN)) {
! 308: ttychars(tp);
! 309: tp->t_iflag = TTYDEF_IFLAG;
! 310: tp->t_oflag = TTYDEF_OFLAG;
! 311: /* No modem control, so set CLOCAL. */
! 312: tp->t_cflag = TTYDEF_CFLAG | CLOCAL;
! 313: tp->t_lflag = TTYDEF_LFLAG;
! 314: tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
! 315:
! 316: dlparam(tp, &tp->t_termios);
! 317: ttsetwater(tp);
! 318:
! 319: } else if ((tp->t_state & TS_XCLUDE) && p->p_ucred->cr_uid != 0)
! 320: return EBUSY;
! 321:
! 322: return ((*linesw[tp->t_line].l_open)(dev, tp));
! 323: }
! 324:
! 325: /*ARGSUSED*/
! 326: int
! 327: dlclose(dev, flag, mode, p)
! 328: dev_t dev;
! 329: int flag, mode;
! 330: struct proc *p;
! 331: {
! 332: struct dl_softc *sc;
! 333: register struct tty *tp;
! 334: register int unit;
! 335:
! 336: unit = minor(dev);
! 337: sc = dl_cd.cd_devs[unit];
! 338: tp = sc->sc_tty;
! 339:
! 340: (*linesw[tp->t_line].l_close)(tp, flag);
! 341:
! 342: /* Make sure a BREAK state is not left enabled. */
! 343: dlbrk(sc, 0);
! 344:
! 345: return (ttyclose(tp));
! 346: }
! 347:
! 348: int
! 349: dlread(dev, uio, flag)
! 350: dev_t dev;
! 351: struct uio *uio;
! 352: int flag;
! 353: {
! 354: register struct tty *tp;
! 355: struct dl_softc *sc;
! 356: register int unit;
! 357:
! 358: unit = minor(dev);
! 359: sc = dl_cd.cd_devs[unit];
! 360: tp = sc->sc_tty;
! 361: return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
! 362: }
! 363:
! 364: int
! 365: dlwrite(dev, uio, flag)
! 366: dev_t dev;
! 367: struct uio *uio;
! 368: int flag;
! 369: {
! 370: register struct tty *tp;
! 371: struct dl_softc *sc;
! 372: register int unit;
! 373:
! 374: unit = minor(dev);
! 375: sc = dl_cd.cd_devs[unit];
! 376: tp = sc->sc_tty;
! 377: return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
! 378: }
! 379:
! 380: int
! 381: dlioctl(dev, cmd, data, flag, p)
! 382: dev_t dev;
! 383: int cmd;
! 384: caddr_t data;
! 385: int flag;
! 386: struct proc *p;
! 387: {
! 388: struct dl_softc *sc;
! 389: register struct tty *tp;
! 390: register int unit;
! 391: int error;
! 392:
! 393: unit = minor(dev);
! 394: sc = dl_cd.cd_devs[unit];
! 395: tp = sc->sc_tty;
! 396:
! 397: error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
! 398: if (error >= 0)
! 399: return (error);
! 400: error = ttioctl(tp, cmd, data, flag, p);
! 401: if (error >= 0)
! 402: return (error);
! 403:
! 404: switch (cmd) {
! 405:
! 406: case TIOCSBRK:
! 407: dlbrk(sc, 1);
! 408: break;
! 409:
! 410: case TIOCCBRK:
! 411: dlbrk(sc, 0);
! 412: break;
! 413:
! 414: case TIOCMGET:
! 415: /* No modem control, assume they're all low. */
! 416: *(int *)data = 0;
! 417: break;
! 418:
! 419: default:
! 420: return (ENOTTY);
! 421: }
! 422: return (0);
! 423: }
! 424:
! 425: struct tty *
! 426: dltty(dev)
! 427: dev_t dev;
! 428: {
! 429: register struct dl_softc* sc;
! 430:
! 431: sc = dl_cd.cd_devs[minor(dev)];
! 432: return sc->sc_tty;
! 433: }
! 434:
! 435: void
! 436: dlstop(tp, flag)
! 437: register struct tty *tp;
! 438: int flag;
! 439: {
! 440: register struct dl_softc *sc;
! 441: int unit, s;
! 442:
! 443: unit = minor(tp->t_dev);
! 444: sc = dl_cd.cd_devs[unit];
! 445:
! 446: s = spltty();
! 447:
! 448: if (tp->t_state & TS_BUSY)
! 449: if (!(tp->t_state & TS_TTSTOP))
! 450: tp->t_state |= TS_FLUSH;
! 451: splx(s);
! 452: }
! 453:
! 454: static void
! 455: dlstart(tp)
! 456: register struct tty *tp;
! 457: {
! 458: register struct dl_softc *sc;
! 459: register int unit;
! 460: int s;
! 461:
! 462: unit = minor(tp->t_dev);
! 463: sc = dl_cd.cd_devs[unit];
! 464:
! 465: s = spltty();
! 466: if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
! 467: goto out;
! 468: if (tp->t_outq.c_cc <= tp->t_lowat) {
! 469: if (tp->t_state & TS_ASLEEP) {
! 470: tp->t_state &= ~TS_ASLEEP;
! 471: wakeup((caddr_t)&tp->t_outq);
! 472: }
! 473: selwakeup(&tp->t_wsel);
! 474: }
! 475: if (tp->t_outq.c_cc == 0)
! 476: goto out;
! 477:
! 478:
! 479: if (DL_READ_WORD(DL_UBA_XCSR) & DL_XCSR_TX_READY) {
! 480: tp->t_state |= TS_BUSY;
! 481: DL_WRITE_BYTE(DL_UBA_XBUFL, getc(&tp->t_outq));
! 482: }
! 483: out:
! 484: splx(s);
! 485: return;
! 486: }
! 487:
! 488: /*ARGSUSED*/
! 489: static int
! 490: dlparam(tp, t)
! 491: register struct tty *tp;
! 492: register struct termios *t;
! 493: {
! 494: /*
! 495: * All this kind of stuff (speed, character format, whatever)
! 496: * is set by jumpers on the card. Changing it is thus rather
! 497: * tricky for a mere device driver.
! 498: */
! 499: return 0;
! 500: }
! 501:
! 502: static void
! 503: dlbrk(sc, state)
! 504: register struct dl_softc *sc;
! 505: int state;
! 506: {
! 507: int s = spltty();
! 508:
! 509: if (state) {
! 510: DL_WRITE_WORD(DL_UBA_XCSR, DL_READ_WORD(DL_UBA_XCSR) |
! 511: DL_XCSR_TX_BREAK);
! 512: } else {
! 513: DL_WRITE_WORD(DL_UBA_XCSR, DL_READ_WORD(DL_UBA_XCSR) &
! 514: ~DL_XCSR_TX_BREAK);
! 515: }
! 516: splx(s);
! 517: }
CVSweb