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

Annotation of sys/arch/vax/qbus/dz.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: dz.c,v 1.14 2006/08/05 16:58:47 miod Exp $    */
                      2: /*     $NetBSD: dz.c,v 1.23 2000/06/04 02:14:12 matt Exp $     */
                      3: /*
                      4:  * Copyright (c) 1996  Ken C. Wellsch.  All rights reserved.
                      5:  * Copyright (c) 1992, 1993
                      6:  *     The Regents of the University of California.  All rights reserved.
                      7:  *
                      8:  * This code is derived from software contributed to Berkeley by
                      9:  * Ralph Campbell and Rick Macklem.
                     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. Neither the name of the University nor the names of its contributors
                     20:  *    may be used to endorse or promote products derived from this software
                     21:  *    without specific prior written permission.
                     22:  *
                     23:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     24:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     25:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     26:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     27:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     28:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     29:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     31:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     32:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     33:  * SUCH DAMAGE.
                     34:  */
                     35:
                     36: #include <sys/param.h>
                     37: #include <sys/systm.h>
                     38: #include <sys/ioctl.h>
                     39: #include <sys/tty.h>
                     40: #include <sys/proc.h>
                     41: #include <sys/buf.h>
                     42: #include <sys/conf.h>
                     43: #include <sys/file.h>
                     44: #include <sys/uio.h>
                     45: #include <sys/kernel.h>
                     46: #include <sys/syslog.h>
                     47: #include <sys/device.h>
                     48: #include <sys/timeout.h>
                     49:
                     50: #ifdef DDB
                     51: #include <dev/cons.h>
                     52: #endif
                     53:
                     54: #include <machine/bus.h>
                     55: #include <machine/pte.h>
                     56: #include <machine/trap.h>
                     57: #include <machine/cpu.h>
                     58:
                     59: #include <arch/vax/qbus/dzreg.h>
                     60: #include <arch/vax/qbus/dzvar.h>
                     61:
                     62: #define        DZ_READ_BYTE(adr) \
                     63:        bus_space_read_1(sc->sc_iot, sc->sc_ioh, sc->sc_dr.adr)
                     64: #define        DZ_READ_WORD(adr) \
                     65:        bus_space_read_2(sc->sc_iot, sc->sc_ioh, sc->sc_dr.adr)
                     66: #define        DZ_WRITE_BYTE(adr, val) \
                     67:        bus_space_write_1(sc->sc_iot, sc->sc_ioh, sc->sc_dr.adr, val)
                     68: #define        DZ_WRITE_WORD(adr, val) \
                     69:        bus_space_write_2(sc->sc_iot, sc->sc_ioh, sc->sc_dr.adr, val)
                     70:
                     71:
                     72: /* Flags used to monitor modem bits, make them understood outside driver */
                     73:
                     74: #define DML_DTR                TIOCM_DTR
                     75: #define DML_DCD                TIOCM_CD
                     76: #define DML_RI         TIOCM_RI
                     77: #define DML_BRK                0100000         /* no equivalent, we will mask */
                     78:
                     79: static const struct speedtab dzspeedtab[] =
                     80: {
                     81:   {       0,   0               },
                     82:   {      50,   DZ_LPR_B50      },
                     83:   {      75,   DZ_LPR_B75      },
                     84:   {     110,   DZ_LPR_B110     },
                     85:   {     134,   DZ_LPR_B134     },
                     86:   {     150,   DZ_LPR_B150     },
                     87:   {     300,   DZ_LPR_B300     },
                     88:   {     600,   DZ_LPR_B600     },
                     89:   {    1200,   DZ_LPR_B1200    },
                     90:   {    1800,   DZ_LPR_B1800    },
                     91:   {    2000,   DZ_LPR_B2000    },
                     92:   {    2400,   DZ_LPR_B2400    },
                     93:   {    3600,   DZ_LPR_B3600    },
                     94:   {    4800,   DZ_LPR_B4800    },
                     95:   {    7200,   DZ_LPR_B7200    },
                     96:   {    9600,   DZ_LPR_B9600    },
                     97:   {   19200,   DZ_LPR_B19200   },
                     98:   {      -1,   -1              }
                     99: };
                    100:
                    101: static void    dzstart(struct tty *);
                    102: static int     dzparam(struct tty *, struct termios *);
                    103: static unsigned        dzmctl(struct dz_softc *, int, int, int);
                    104: static void    dzscan(void *);
                    105: static void    dzdrain(struct dz_softc *);
                    106:
                    107: struct cfdriver dz_cd = {
                    108:        NULL, "dz", DV_TTY
                    109: };
                    110:
                    111: cdev_decl(dz);
                    112:
                    113: /*
                    114:  * The DZ series doesn't interrupt on carrier transitions,
                    115:  * so we have to use a timer to watch it.
                    116:  */
                    117: int    dz_timer = 0;   /* true if timer started */
                    118:
                    119: struct timeout dz_timeout;
                    120:
                    121: void
                    122: dzattach(struct dz_softc *sc)
                    123: {
                    124:        int n;
                    125:
                    126:        sc->sc_rxint = sc->sc_brk = 0;
                    127:
                    128:        sc->sc_dr.dr_tcrw = sc->sc_dr.dr_tcr;
                    129:        DZ_WRITE_WORD(dr_csr, DZ_CSR_MSE | DZ_CSR_RXIE | DZ_CSR_TXIE);
                    130:        dzdrain(sc);
                    131:        DZ_WRITE_BYTE(dr_dtr, 0);
                    132:        DZ_WRITE_BYTE(dr_break, 0);
                    133:
                    134:        /* Initialize our softc structure. Should be done in open? */
                    135:
                    136:        for (n = 0; n < sc->sc_type; n++) {
                    137:                sc->sc_dz[n].dz_sc = sc;
                    138:                sc->sc_dz[n].dz_line = n;
                    139:                sc->sc_dz[n].dz_tty = ttymalloc();
                    140:        }
                    141:
                    142:        /* Alas no interrupt on modem bit changes, so we manually scan */
                    143:
                    144:        if (dz_timer == 0) {
                    145:                dz_timer = 1;
                    146:                timeout_set(&dz_timeout, dzscan, NULL);
                    147:                timeout_add(&dz_timeout, hz);
                    148:        }
                    149:        printf("\n");
                    150: }
                    151:
                    152: /* Receiver Interrupt */
                    153:
                    154: void
                    155: dzrint(void *arg)
                    156: {
                    157:        struct dz_softc *sc = arg;
                    158:        struct tty *tp;
                    159:        int cc, line;
                    160:        unsigned c;
                    161:        int overrun = 0;
                    162:
                    163:        sc->sc_rxint++;
                    164:
                    165:        while ((c = DZ_READ_WORD(dr_rbuf)) & DZ_RBUF_DATA_VALID) {
                    166:                cc = c & 0xFF;
                    167:                line = DZ_PORT(c>>8);
                    168:                tp = sc->sc_dz[line].dz_tty;
                    169:
                    170:                /* Must be caught early */
                    171:                if (sc->sc_dz[line].dz_catch &&
                    172:                    (*sc->sc_dz[line].dz_catch)(sc->sc_dz[line].dz_private, cc))
                    173:                        continue;
                    174:
                    175:                if (!(tp->t_state & TS_ISOPEN)) {
                    176:                        wakeup((caddr_t)&tp->t_rawq);
                    177:                        continue;
                    178:                }
                    179:
                    180:                if ((c & DZ_RBUF_OVERRUN_ERR) && overrun == 0) {
                    181:                        log(LOG_WARNING, "%s: silo overflow, line %d\n",
                    182:                            sc->sc_dev.dv_xname, line);
                    183:                        overrun = 1;
                    184:                }
                    185:
                    186:                /* A BREAK key will appear as a NULL with a framing error */
                    187:                if (c & DZ_RBUF_FRAMING_ERR)
                    188:                        cc |= TTY_FE;
                    189:                if (c & DZ_RBUF_PARITY_ERR)
                    190:                        cc |= TTY_PE;
                    191:
                    192: #if defined(DDB) && (defined(VAX410) || defined(VAX43) || defined(VAX46) || defined(VAX48) || defined(VAX49) || defined(VAX53))
                    193:                if (tp->t_dev == cn_tab->cn_dev) {
                    194:                        int j = kdbrint(cc);
                    195:
                    196:                        if (j == 1)     /* Escape received, just return */
                    197:                                continue;
                    198:
                    199:                        if (j == 2)     /* Second char wasn't 'D' */
                    200:                                (*linesw[tp->t_line].l_rint)(27, tp);
                    201:                }
                    202: #endif
                    203:                (*linesw[tp->t_line].l_rint)(cc, tp);
                    204:        }
                    205: }
                    206:
                    207: /* Transmitter Interrupt */
                    208:
                    209: void
                    210: dzxint(void *arg)
                    211: {
                    212:        struct dz_softc *sc = arg;
                    213:        struct tty *tp;
                    214:        struct clist *cl;
                    215:        int line, ch, csr;
                    216:        u_char tcr;
                    217:
                    218:        /*
                    219:         * Switch to POLLED mode.
                    220:         *   Some simple measurements indicated that even on
                    221:         *  one port, by freeing the scanner in the controller
                    222:         *  by either providing a character or turning off
                    223:         *  the port when output is complete, the transmitter
                    224:         *  was ready to accept more output when polled again.
                    225:         *   With just two ports running the game "worms,"
                    226:         *  almost every interrupt serviced both transmitters!
                    227:         *   Each UART is double buffered, so if the scanner
                    228:         *  is quick enough and timing works out, we can even
                    229:         *  feed the same port twice.
                    230:         *
                    231:         * Ragge 980517:
                    232:         * Do not need to turn off interrupts, already at interrupt level.
                    233:         * Remove the pdma stuff; no great need of it right now.
                    234:         */
                    235:
                    236:        while (((csr = DZ_READ_WORD(dr_csr)) & DZ_CSR_TX_READY) != 0) {
                    237:
                    238:                line = DZ_PORT(csr>>8);
                    239:
                    240:                tp = sc->sc_dz[line].dz_tty;
                    241:                cl = &tp->t_outq;
                    242:                tp->t_state &= ~TS_BUSY;
                    243:
                    244:                /* Just send out a char if we have one */
                    245:                /* As long as we can fill the chip buffer, we just loop here */
                    246:                if (cl->c_cc) {
                    247:                        tp->t_state |= TS_BUSY;
                    248:                        ch = getc(cl);
                    249:                        DZ_WRITE_BYTE(dr_tbuf, ch);
                    250:                        continue;
                    251:                }
                    252:                /* Nothing to send; clear the scan bit */
                    253:                /* Clear xmit scanner bit; dzstart may set it again */
                    254:                tcr = DZ_READ_WORD(dr_tcrw);
                    255:                tcr &= 255;
                    256:                tcr &= ~(1 << line);
                    257:                DZ_WRITE_BYTE(dr_tcr, tcr);
                    258:                if (sc->sc_dz[line].dz_catch)
                    259:                        continue;
                    260:
                    261:                if (tp->t_state & TS_FLUSH)
                    262:                        tp->t_state &= ~TS_FLUSH;
                    263:                else
                    264:                        ndflush (&tp->t_outq, cl->c_cc);
                    265:
                    266:                if (tp->t_line)
                    267:                        (*linesw[tp->t_line].l_start)(tp);
                    268:                else
                    269:                        dzstart(tp);
                    270:        }
                    271: }
                    272:
                    273: int
                    274: dzopen(dev_t dev, int flag, int mode, struct proc *p)
                    275: {
                    276:        struct tty *tp;
                    277:        int unit, line;
                    278:        struct  dz_softc *sc;
                    279:        int s, error = 0;
                    280:
                    281:        unit = DZ_I2C(minor(dev));
                    282:        line = DZ_PORT(minor(dev));
                    283:        if (unit >= dz_cd.cd_ndevs ||  dz_cd.cd_devs[unit] == NULL)
                    284:                return (ENXIO);
                    285:
                    286:        sc = dz_cd.cd_devs[unit];
                    287:
                    288:        if (line >= sc->sc_type)
                    289:                return ENXIO;
                    290:
                    291:        /* if some other device is using the line, it's not available */
                    292:        if (sc->sc_dz[line].dz_catch)
                    293:                return ENXIO;
                    294:
                    295:        if (sc->sc_openings++ == 0)
                    296:                dzdrain(sc);
                    297:
                    298:        tp = sc->sc_dz[line].dz_tty;
                    299:        if (tp == NULL)
                    300:                return (ENODEV);
                    301:        tp->t_oproc   = dzstart;
                    302:        tp->t_param   = dzparam;
                    303:        tp->t_dev = dev;
                    304:        if ((tp->t_state & TS_ISOPEN) == 0) {
                    305:                ttychars(tp);
                    306:                if (tp->t_ispeed == 0) {
                    307:                        tp->t_iflag = TTYDEF_IFLAG;
                    308:                        tp->t_oflag = TTYDEF_OFLAG;
                    309:                        tp->t_cflag = TTYDEF_CFLAG;
                    310:                        tp->t_lflag = TTYDEF_LFLAG;
                    311:                        tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
                    312:                }
                    313:                (void) dzparam(tp, &tp->t_termios);
                    314:                ttsetwater(tp);
                    315:        } else if ((tp->t_state & TS_XCLUDE) && p->p_ucred->cr_uid != 0)
                    316:                return (EBUSY);
                    317:        /* Use DMBIS and *not* DMSET or else we clobber incoming bits */
                    318:        if (dzmctl(sc, line, DML_DTR, DMBIS) & DML_DCD)
                    319:                tp->t_state |= TS_CARR_ON;
                    320:        s = spltty();
                    321:        while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) &&
                    322:               !(tp->t_state & TS_CARR_ON)) {
                    323:                error = ttysleep(tp, (caddr_t)&tp->t_rawq,
                    324:                                TTIPRI | PCATCH, ttopen, 0);
                    325:                if (error)
                    326:                        break;
                    327:        }
                    328:        splx(s);
                    329:        if (error)
                    330:                return (error);
                    331:        return ((*linesw[tp->t_line].l_open)(dev, tp));
                    332: }
                    333:
                    334: /*ARGSUSED*/
                    335: int
                    336: dzclose(dev_t dev, int flag, int mode, struct proc *p)
                    337: {
                    338:        struct  dz_softc *sc;
                    339:        struct tty *tp;
                    340:        int unit, line;
                    341:
                    342:
                    343:        unit = DZ_I2C(minor(dev));
                    344:        line = DZ_PORT(minor(dev));
                    345:        sc = dz_cd.cd_devs[unit];
                    346:
                    347:        tp = sc->sc_dz[line].dz_tty;
                    348:
                    349:        (*linesw[tp->t_line].l_close)(tp, flag);
                    350:
                    351:        /* Make sure a BREAK state is not left enabled. */
                    352:        (void) dzmctl(sc, line, DML_BRK, DMBIC);
                    353:
                    354:        /* Do a hangup if so required. */
                    355:        if ((tp->t_cflag & HUPCL) || !(tp->t_state & TS_ISOPEN))
                    356:                (void) dzmctl(sc, line, 0, DMSET);
                    357:
                    358:        sc->sc_openings--;
                    359:        return (ttyclose(tp));
                    360: }
                    361:
                    362: int
                    363: dzread(dev_t dev, struct uio *uio, int flag)
                    364: {
                    365:        struct tty *tp;
                    366:        struct  dz_softc *sc;
                    367:
                    368:        sc = dz_cd.cd_devs[DZ_I2C(minor(dev))];
                    369:
                    370:        tp = sc->sc_dz[DZ_PORT(minor(dev))].dz_tty;
                    371:        return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
                    372: }
                    373:
                    374: int
                    375: dzwrite(dev_t dev, struct uio *uio, int flag)
                    376: {
                    377:        struct tty *tp;
                    378:        struct  dz_softc *sc;
                    379:
                    380:        sc = dz_cd.cd_devs[DZ_I2C(minor(dev))];
                    381:
                    382:        tp = sc->sc_dz[DZ_PORT(minor(dev))].dz_tty;
                    383:        return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
                    384: }
                    385:
                    386: /*ARGSUSED*/
                    387: int
                    388: dzioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
                    389: {
                    390:        struct  dz_softc *sc;
                    391:        struct tty *tp;
                    392:        int unit, line;
                    393:        int error;
                    394:
                    395:        unit = DZ_I2C(minor(dev));
                    396:        line = DZ_PORT(minor(dev));
                    397:        sc = dz_cd.cd_devs[unit];
                    398:        tp = sc->sc_dz[line].dz_tty;
                    399:
                    400:        error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
                    401:        if (error >= 0)
                    402:                return (error);
                    403:
                    404:        error = ttioctl(tp, cmd, data, flag, p);
                    405:        if (error >= 0)
                    406:                return (error);
                    407:
                    408:        switch (cmd) {
                    409:
                    410:        case TIOCSBRK:
                    411:                (void) dzmctl(sc, line, DML_BRK, DMBIS);
                    412:                break;
                    413:
                    414:        case TIOCCBRK:
                    415:                (void) dzmctl(sc, line, DML_BRK, DMBIC);
                    416:                break;
                    417:
                    418:        case TIOCSDTR:
                    419:                (void) dzmctl(sc, line, DML_DTR, DMBIS);
                    420:                break;
                    421:
                    422:        case TIOCCDTR:
                    423:                (void) dzmctl(sc, line, DML_DTR, DMBIC);
                    424:                break;
                    425:
                    426:        case TIOCMSET:
                    427:                (void) dzmctl(sc, line, *(int *)data, DMSET);
                    428:                break;
                    429:
                    430:        case TIOCMBIS:
                    431:                (void) dzmctl(sc, line, *(int *)data, DMBIS);
                    432:                break;
                    433:
                    434:        case TIOCMBIC:
                    435:                (void) dzmctl(sc, line, *(int *)data, DMBIC);
                    436:                break;
                    437:
                    438:        case TIOCMGET:
                    439:                *(int *)data = (dzmctl(sc, line, 0, DMGET) & ~DML_BRK);
                    440:                break;
                    441:
                    442:        default:
                    443:                return (ENOTTY);
                    444:        }
                    445:        return (0);
                    446: }
                    447:
                    448: struct tty *
                    449: dztty(dev_t dev)
                    450: {
                    451:        struct  dz_softc *sc = dz_cd.cd_devs[DZ_I2C(minor(dev))];
                    452:         struct tty *tp = sc->sc_dz[DZ_PORT(minor(dev))].dz_tty;
                    453:
                    454:         return (tp);
                    455: }
                    456:
                    457: /*ARGSUSED*/
                    458: int
                    459: dzstop(struct tty *tp, int flag)
                    460: {
                    461:        if (tp->t_state & TS_BUSY)
                    462:                if (!(tp->t_state & TS_TTSTOP))
                    463:                        tp->t_state |= TS_FLUSH;
                    464:        return(0);
                    465: }
                    466:
                    467: void
                    468: dzstart(struct tty *tp)
                    469: {
                    470:        struct dz_softc *sc;
                    471:        struct clist *cl;
                    472:        int unit, line, s;
                    473:        char state;
                    474:
                    475:        unit = DZ_I2C(minor(tp->t_dev));
                    476:        line = DZ_PORT(minor(tp->t_dev));
                    477:        sc = dz_cd.cd_devs[unit];
                    478:
                    479:        s = spltty();
                    480:        if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) {
                    481:                splx(s);
                    482:                return;
                    483:        }
                    484:        cl = &tp->t_outq;
                    485:        if (cl->c_cc <= tp->t_lowat) {
                    486:                if (tp->t_state & TS_ASLEEP) {
                    487:                        tp->t_state &= ~TS_ASLEEP;
                    488:                        wakeup((caddr_t)cl);
                    489:                }
                    490:                selwakeup(&tp->t_wsel);
                    491:        }
                    492:        if (cl->c_cc == 0) {
                    493:                splx(s);
                    494:                return;
                    495:        }
                    496:
                    497:        tp->t_state |= TS_BUSY;
                    498:
                    499:        state = DZ_READ_WORD(dr_tcrw) & 255;
                    500:        if ((state & (1 << line)) == 0) {
                    501:                DZ_WRITE_BYTE(dr_tcr, state | (1 << line));
                    502:        }
                    503:        dzxint(sc);
                    504:        splx(s);
                    505: }
                    506:
                    507: static int
                    508: dzparam(struct tty *tp, struct termios *t)
                    509: {
                    510:        struct  dz_softc *sc;
                    511:        int cflag = t->c_cflag;
                    512:        int unit, line;
                    513:        int ispeed = ttspeedtab(t->c_ispeed, dzspeedtab);
                    514:        int ospeed = ttspeedtab(t->c_ospeed, dzspeedtab);
                    515:        unsigned lpr;
                    516:        int s;
                    517:
                    518:        unit = DZ_I2C(minor(tp->t_dev));
                    519:        line = DZ_PORT(minor(tp->t_dev));
                    520:        sc = dz_cd.cd_devs[unit];
                    521:
                    522:        /* check requested parameters */
                    523:         if (ospeed < 0 || ispeed < 0 || ispeed != ospeed)
                    524:                 return (EINVAL);
                    525:
                    526:         tp->t_ispeed = t->c_ispeed;
                    527:         tp->t_ospeed = t->c_ospeed;
                    528:         tp->t_cflag = cflag;
                    529:
                    530:        if (ospeed == 0) {
                    531:                (void) dzmctl(sc, line, 0, DMSET);      /* hang up line */
                    532:                return (0);
                    533:        }
                    534:
                    535:        s = spltty();
                    536:
                    537:        lpr = DZ_LPR_RX_ENABLE | ((ispeed&0xF)<<8) | line;
                    538:
                    539:        switch (cflag & CSIZE)
                    540:        {
                    541:          case CS5:
                    542:                lpr |= DZ_LPR_5_BIT_CHAR;
                    543:                break;
                    544:          case CS6:
                    545:                lpr |= DZ_LPR_6_BIT_CHAR;
                    546:                break;
                    547:          case CS7:
                    548:                lpr |= DZ_LPR_7_BIT_CHAR;
                    549:                break;
                    550:          default:
                    551:                lpr |= DZ_LPR_8_BIT_CHAR;
                    552:                break;
                    553:        }
                    554:        if (cflag & PARENB)
                    555:                lpr |= DZ_LPR_PARENB;
                    556:        if (cflag & PARODD)
                    557:                lpr |= DZ_LPR_OPAR;
                    558:        if (cflag & CSTOPB)
                    559:                lpr |= DZ_LPR_2_STOP;
                    560:
                    561:        DZ_WRITE_WORD(dr_lpr, lpr);
                    562:
                    563:        splx(s);
                    564:        return (0);
                    565: }
                    566:
                    567: static unsigned
                    568: dzmctl(struct dz_softc *sc, int line, int bits, int how)
                    569: {
                    570:        unsigned status;
                    571:        unsigned mbits;
                    572:        unsigned bit;
                    573:        int s;
                    574:
                    575:        s = spltty();
                    576:
                    577:        mbits = 0;
                    578:
                    579:        bit = (1 << line);
                    580:
                    581:        /* external signals as seen from the port */
                    582:
                    583:        status = DZ_READ_BYTE(dr_dcd) | sc->sc_dsr;
                    584:
                    585:        if (status & bit)
                    586:                mbits |= DML_DCD;
                    587:
                    588:        status = DZ_READ_BYTE(dr_ring);
                    589:
                    590:        if (status & bit)
                    591:                mbits |= DML_RI;
                    592:
                    593:        /* internal signals/state delivered to port */
                    594:
                    595:        status = DZ_READ_BYTE(dr_dtr);
                    596:
                    597:        if (status & bit)
                    598:                mbits |= DML_DTR;
                    599:
                    600:        if (sc->sc_brk & bit)
                    601:                mbits |= DML_BRK;
                    602:
                    603:        switch (how)
                    604:        {
                    605:          case DMSET:
                    606:                mbits = bits;
                    607:                break;
                    608:
                    609:          case DMBIS:
                    610:                mbits |= bits;
                    611:                break;
                    612:
                    613:          case DMBIC:
                    614:                mbits &= ~bits;
                    615:                break;
                    616:
                    617:          case DMGET:
                    618:                splx(s);
                    619:                return (mbits);
                    620:        }
                    621:
                    622:        if (mbits & DML_DTR) {
                    623:                DZ_WRITE_BYTE(dr_dtr, DZ_READ_BYTE(dr_dtr) | bit);
                    624:        } else {
                    625:                DZ_WRITE_BYTE(dr_dtr, DZ_READ_BYTE(dr_dtr) & ~bit);
                    626:        }
                    627:
                    628:        if (mbits & DML_BRK) {
                    629:                sc->sc_brk |= bit;
                    630:                DZ_WRITE_BYTE(dr_break, sc->sc_brk);
                    631:        } else {
                    632:                sc->sc_brk &= ~bit;
                    633:                DZ_WRITE_BYTE(dr_break, sc->sc_brk);
                    634:        }
                    635:
                    636:        splx(s);
                    637:        return (mbits);
                    638: }
                    639:
                    640: /*
                    641:  * This is called by timeout() periodically.
                    642:  * Check to see if modem status bits have changed.
                    643:  */
                    644: static void
                    645: dzscan(void *arg)
                    646: {
                    647:        struct dz_softc *sc;
                    648:        struct tty *tp;
                    649:        int n, bit, port;
                    650:        unsigned csr;
                    651:        int s;
                    652:
                    653:        s = spltty();
                    654:
                    655:        for (n = 0; n < dz_cd.cd_ndevs; n++) {
                    656:
                    657:                if (dz_cd.cd_devs[n] == NULL)
                    658:                        continue;
                    659:
                    660:                sc = dz_cd.cd_devs[n];
                    661:
                    662:                for (port = 0; port < sc->sc_type; port++) {
                    663:
                    664:                        tp = sc->sc_dz[port].dz_tty;
                    665:                        bit = (1 << port);
                    666:
                    667:                        if ((DZ_READ_BYTE(dr_dcd) | sc->sc_dsr) & bit) {
                    668:                                if (!(tp->t_state & TS_CARR_ON))
                    669:                                        (*linesw[tp->t_line].l_modem) (tp, 1);
                    670:                        } else if ((tp->t_state & TS_CARR_ON) &&
                    671:                            (*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
                    672:                                DZ_WRITE_BYTE(dr_tcr,
                    673:                                    (DZ_READ_WORD(dr_tcrw) & 255) & ~bit);
                    674:                        }
                    675:                }
                    676:
                    677:                /*
                    678:                 *  If the RX interrupt rate is this high, switch
                    679:                 *  the controller to Silo Alarm - which means don't
                    680:                 *  interrupt until the RX silo has 16 characters in
                    681:                 *  it (the silo is 64 characters in all).
                    682:                 *  Avoid oscillating SA on and off by not turning
                    683:                 *  if off unless the rate is appropriately low.
                    684:                 */
                    685:
                    686:                csr = DZ_READ_WORD(dr_csr);
                    687:
                    688:                if (sc->sc_rxint > (16*10)) {
                    689:                        if ((csr & DZ_CSR_SAE) == 0)
                    690:                                DZ_WRITE_WORD(dr_csr, csr | DZ_CSR_SAE);
                    691:                } else if ((csr & DZ_CSR_SAE) != 0)
                    692:                        if (sc->sc_rxint < 10)
                    693:                                DZ_WRITE_WORD(dr_csr, csr & ~(DZ_CSR_SAE));
                    694:
                    695:                sc->sc_rxint = 0;
                    696:        }
                    697:        splx(s);
                    698:        timeout_add(&dz_timeout, hz);
                    699: }
                    700:
                    701: /*
                    702:  * Called after an ubareset. The DZ card is reset, but the only thing
                    703:  * that must be done is to start the receiver and transmitter again.
                    704:  * No DMA setup to care about.
                    705:  */
                    706: void
                    707: dzreset(struct device *dev)
                    708: {
                    709:        struct dz_softc *sc = (void *)dev;
                    710:        struct tty *tp;
                    711:        int i;
                    712:
                    713:        for (i = 0; i < sc->sc_type; i++) {
                    714:                tp = sc->sc_dz[i].dz_tty;
                    715:
                    716:                if ((tp->t_state & TS_ISOPEN) == 0)
                    717:                        continue;
                    718:
                    719:                dzparam(tp, &tp->t_termios);
                    720:                dzmctl(sc, i, DML_DTR, DMSET);
                    721:                tp->t_state &= ~TS_BUSY;
                    722:                dzstart(tp);    /* Kick off transmitter again */
                    723:        }
                    724: }
                    725:
                    726: /*
                    727:  * Drain RX fifo.
                    728:  */
                    729: static void
                    730: dzdrain(struct dz_softc *sc)
                    731: {
                    732:        while (DZ_READ_WORD(dr_rbuf) & DZ_RBUF_DATA_VALID)
                    733:                /*EMPTY*/;
                    734: }

CVSweb