[BACK]Return to dl.c CVS log [TXT][DIR] Up to [local] / sys / arch / vax / qbus

Annotation of sys/arch/vax/qbus/dl.c, Revision 1.1.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