[BACK]Return to z8530tty.c CVS log [TXT][DIR] Up to [local] / sys / dev / ic

Annotation of sys/dev/ic/z8530tty.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: z8530tty.c,v 1.16 2006/04/27 19:31:44 deraadt Exp $ */
        !             2: /*     $NetBSD: z8530tty.c,v 1.13 1996/10/16 20:42:14 gwr Exp $        */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 1994 Gordon W. Ross
        !             6:  * Copyright (c) 1992, 1993
        !             7:  *     The Regents of the University of California.  All rights reserved.
        !             8:  *
        !             9:  * This software was developed by the Computer Systems Engineering group
        !            10:  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
        !            11:  * contributed to Berkeley.
        !            12:  *
        !            13:  * All advertising materials mentioning features or use of this software
        !            14:  * must display the following acknowledgement:
        !            15:  *     This product includes software developed by the University of
        !            16:  *     California, Lawrence Berkeley Laboratory.
        !            17:  *
        !            18:  * Redistribution and use in source and binary forms, with or without
        !            19:  * modification, are permitted provided that the following conditions
        !            20:  * are met:
        !            21:  * 1. Redistributions of source code must retain the above copyright
        !            22:  *    notice, this list of conditions and the following disclaimer.
        !            23:  * 2. Redistributions in binary form must reproduce the above copyright
        !            24:  *    notice, this list of conditions and the following disclaimer in the
        !            25:  *    documentation and/or other materials provided with the distribution.
        !            26:  * 3. Neither the name of the University nor the names of its contributors
        !            27:  *    may be used to endorse or promote products derived from this software
        !            28:  *    without specific prior written permission.
        !            29:  *
        !            30:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            31:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            32:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            33:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            34:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            35:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            36:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            37:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            38:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            39:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            40:  * SUCH DAMAGE.
        !            41:  *
        !            42:  *     @(#)zs.c        8.1 (Berkeley) 7/19/93
        !            43:  */
        !            44:
        !            45: /*
        !            46:  * Zilog Z8530 Dual UART driver (tty interface)
        !            47:  *
        !            48:  * This is the "slave" driver that will be attached to
        !            49:  * the "zsc" driver for plain "tty" async. serial lines.
        !            50:  *
        !            51:  * Credits, history:
        !            52:  *
        !            53:  * The original version of this code was the sparc/dev/zs.c driver
        !            54:  * as distributed with the Berkeley 4.4 Lite release.  Since then,
        !            55:  * Gordon Ross reorganized the code into the current parent/child
        !            56:  * driver scheme, separating the Sun keyboard and mouse support
        !            57:  * into independent child drivers.
        !            58:  *
        !            59:  * RTS/CTS flow-control support was a collaboration of:
        !            60:  *     Gordon Ross <gwr@netbsd.org>,
        !            61:  *     Bill Studenmund <wrstuden@loki.stanford.edu>
        !            62:  *     Ian Dall <Ian.Dall@dsto.defence.gov.au>
        !            63:  */
        !            64:
        !            65: #include <sys/param.h>
        !            66: #include <sys/systm.h>
        !            67: #include <sys/proc.h>
        !            68: #include <sys/device.h>
        !            69: #include <sys/conf.h>
        !            70: #include <sys/file.h>
        !            71: #include <sys/ioctl.h>
        !            72: #include <sys/malloc.h>
        !            73: #include <sys/tty.h>
        !            74: #include <sys/time.h>
        !            75: #include <sys/kernel.h>
        !            76: #include <sys/syslog.h>
        !            77:
        !            78: #include <dev/ic/z8530reg.h>
        !            79: #include <machine/z8530var.h>
        !            80:
        !            81: #ifdef KGDB
        !            82: extern int zs_check_kgdb();
        !            83: #endif
        !            84:
        !            85: /*
        !            86:  * Allow the MD var.h to override the default CFLAG so that
        !            87:  * console messages during boot come out with correct parity.
        !            88:  */
        !            89: #ifndef        ZSTTY_DEF_CFLAG
        !            90: #define        ZSTTY_DEF_CFLAG TTYDEF_CFLAG
        !            91: #endif
        !            92:
        !            93: /*
        !            94:  * How many input characters we can buffer.
        !            95:  * The port-specific var.h may override this.
        !            96:  * Note: must be a power of two!
        !            97:  */
        !            98: #ifndef        ZSTTY_RING_SIZE
        !            99: #define        ZSTTY_RING_SIZE 2048
        !           100: #endif
        !           101:
        !           102: /*
        !           103:  * Make this an option variable one can patch.
        !           104:  * But be warned:  this must be a power of 2!
        !           105:  */
        !           106: int zstty_rbuf_size = ZSTTY_RING_SIZE;
        !           107:
        !           108: /* This should usually be 3/4 of ZSTTY_RING_SIZE */
        !           109: int zstty_rbuf_hiwat = (ZSTTY_RING_SIZE - (ZSTTY_RING_SIZE >> 2));
        !           110:
        !           111: struct zstty_softc {
        !           112:        struct  device zst_dev;         /* required first: base device */
        !           113:        struct  tty *zst_tty;
        !           114:        struct  zs_chanstate *zst_cs;
        !           115:
        !           116:        int zst_hwflags;        /* see z8530var.h */
        !           117:        int zst_swflags;        /* TIOCFLAG_SOFTCAR, ... <ttycom.h> */
        !           118:
        !           119:        /*
        !           120:         * Printing an overrun error message often takes long enough to
        !           121:         * cause another overrun, so we only print one per second.
        !           122:         */
        !           123:        long    zst_rotime;             /* time of last ring overrun */
        !           124:        long    zst_fotime;             /* time of last fifo overrun */
        !           125:
        !           126:        /*
        !           127:         * The receive ring buffer.
        !           128:         */
        !           129:        int     zst_rbget;      /* ring buffer `get' index */
        !           130:        volatile int    zst_rbput;      /* ring buffer `put' index */
        !           131:        int     zst_ringmask;
        !           132:        int     zst_rbhiwat;
        !           133:
        !           134:        u_short *zst_rbuf; /* rr1, data pairs */
        !           135:
        !           136:        /*
        !           137:         * The transmit byte count and address are used for pseudo-DMA
        !           138:         * output in the hardware interrupt code.  PDMA can be suspended
        !           139:         * to get pending changes done; heldtbc is used for this.  It can
        !           140:         * also be stopped for ^S; this sets TS_TTSTOP in tp->t_state.
        !           141:         */
        !           142:        int     zst_tbc;                        /* transmit byte count */
        !           143:        caddr_t zst_tba;                        /* transmit buffer address */
        !           144:        int     zst_heldtbc;            /* held tbc while xmission stopped */
        !           145:
        !           146:        /* Flags to communicate with zstty_softint() */
        !           147:        volatile char zst_rx_blocked;   /* input block at ring */
        !           148:        volatile char zst_rx_overrun;   /* ring overrun */
        !           149:        volatile char zst_tx_busy;      /* working on an output chunk */
        !           150:        volatile char zst_tx_done;      /* done with one output chunk */
        !           151:        volatile char zst_tx_stopped;   /* H/W level stop (lost CTS) */
        !           152:        volatile char zst_st_check;     /* got a status interrupt */
        !           153:        char pad[2];
        !           154: };
        !           155:
        !           156:
        !           157: /* Definition of the driver for autoconfig. */
        !           158: static int     zstty_match(struct device *, void *, void *);
        !           159: static void    zstty_attach(struct device *, struct device *, void *);
        !           160:
        !           161: struct cfattach zstty_ca = {
        !           162:        sizeof(struct zstty_softc), zstty_match, zstty_attach
        !           163: };
        !           164:
        !           165: struct cfdriver zstty_cd = {
        !           166:        NULL, "zstty", DV_TTY
        !           167: };
        !           168:
        !           169: struct zsops zsops_tty;
        !           170:
        !           171: /* Routines called from other code. */
        !           172: cdev_decl(zs); /* open, close, read, write, ioctl, stop, ... */
        !           173:
        !           174: static void    zsstart(struct tty *);
        !           175: static int     zsparam(struct tty *, struct termios *);
        !           176: static void    zs_modem(struct zstty_softc *zst, int onoff);
        !           177: static int     zshwiflow(struct tty *, int);
        !           178: static void    zs_hwiflow(struct zstty_softc *, int);
        !           179: static void    zstty_rxint(register struct zs_chanstate *);
        !           180: static void    zstty_txint(register struct zs_chanstate *);
        !           181: static void    zstty_stint(register struct zs_chanstate *);
        !           182: static void    zstty_softint(struct zs_chanstate *);
        !           183: static void    zsoverrun(struct zstty_softc *, long *, char *);
        !           184: /*
        !           185:  * zstty_match: how is this zs channel configured?
        !           186:  */
        !           187: int
        !           188: zstty_match(parent, match, aux)
        !           189:        struct device *parent;
        !           190:        void   *match, *aux;
        !           191: {
        !           192:        struct cfdata *cf = match;
        !           193:        struct zsc_attach_args *args = aux;
        !           194:
        !           195:        /* Exact match is better than wildcard. */
        !           196:        if (cf->cf_loc[0] == args->channel)
        !           197:                return 2;
        !           198:
        !           199:        /* This driver accepts wildcard. */
        !           200:        if (cf->cf_loc[0] == -1)
        !           201:                return 1;
        !           202:
        !           203:        return 0;
        !           204: }
        !           205:
        !           206: void
        !           207: zstty_attach(parent, self, aux)
        !           208:        struct device *parent, *self;
        !           209:        void   *aux;
        !           210:
        !           211: {
        !           212:        struct zsc_softc *zsc = (void *) parent;
        !           213:        struct zstty_softc *zst = (void *) self;
        !           214:        struct zsc_attach_args *args = aux;
        !           215:        struct zs_chanstate *cs;
        !           216:        struct cfdata *cf;
        !           217:        struct tty *tp;
        !           218:        int channel, tty_unit;
        !           219:        dev_t dev;
        !           220:
        !           221:        cf = zst->zst_dev.dv_cfdata;
        !           222:        tty_unit = zst->zst_dev.dv_unit;
        !           223:        channel = args->channel;
        !           224:        cs = &zsc->zsc_cs[channel];
        !           225:        cs->cs_private = zst;
        !           226:        cs->cs_ops = &zsops_tty;
        !           227:
        !           228:        zst->zst_cs = cs;
        !           229:        zst->zst_swflags = cf->cf_flags;        /* softcar, etc. */
        !           230:        zst->zst_hwflags = args->hwflags;
        !           231:        dev = makedev(ZSTTY_MAJOR, tty_unit);
        !           232:
        !           233:        if (zst->zst_swflags)
        !           234:                printf(" flags 0x%x", zst->zst_swflags);
        !           235:
        !           236:        if (zst->zst_hwflags & ZS_HWFLAG_CONSOLE)
        !           237:                printf(" (console)");
        !           238:        else {
        !           239: #ifdef KGDB
        !           240:                /*
        !           241:                 * Allow kgdb to "take over" this port.  If this port is
        !           242:                 * NOT the kgdb port, zs_check_kgdb() will return zero.
        !           243:                 * If it IS the kgdb port, it will print "kgdb,...\n"
        !           244:                 * and then return non-zero.
        !           245:                 */
        !           246:                if (zs_check_kgdb(cs, dev)) {
        !           247:                        /*
        !           248:                         * This is the kgdb port (exclusive use)
        !           249:                         * so skip the normal attach code.
        !           250:                         */
        !           251:                        return;
        !           252:                }
        !           253: #endif
        !           254:        }
        !           255:        printf("\n");
        !           256:
        !           257:        tp = ttymalloc();
        !           258:        tp->t_dev = dev;
        !           259:        tp->t_oproc = zsstart;
        !           260:        tp->t_param = zsparam;
        !           261:        tp->t_hwiflow = zshwiflow;
        !           262:
        !           263:        zst->zst_tty = tp;
        !           264:        zst->zst_rbhiwat =  zstty_rbuf_size;    /* impossible value */
        !           265:        zst->zst_ringmask = zstty_rbuf_size - 1;
        !           266:        zst->zst_rbuf = malloc(zstty_rbuf_size * sizeof(zst->zst_rbuf[0]),
        !           267:                              M_DEVBUF, M_WAITOK);
        !           268:
        !           269:        /*
        !           270:         * Hardware init
        !           271:         */
        !           272:        if (zst->zst_hwflags & ZS_HWFLAG_CONSOLE) {
        !           273:                /* This unit is the console. */
        !           274:                zst->zst_swflags |= TIOCFLAG_SOFTCAR;
        !           275:                /* Call _param so interrupts get enabled. */
        !           276:                cs->cs_defspeed = zs_getspeed(cs);
        !           277:                tp->t_ispeed = cs->cs_defspeed;
        !           278:                tp->t_ospeed = cs->cs_defspeed;
        !           279:                tp->t_cflag = ZSTTY_DEF_CFLAG;
        !           280:                (void) zsparam(tp, &tp->t_termios);
        !           281:        } else {
        !           282:                /* Not the console; may need reset. */
        !           283:                int reset, s;
        !           284:                reset = (channel == 0) ?
        !           285:                        ZSWR9_A_RESET : ZSWR9_B_RESET;
        !           286:                s = splzs();
        !           287:                zs_write_reg(cs, 9, reset);
        !           288:                splx(s);
        !           289:        }
        !           290:
        !           291:        /*
        !           292:         * Initialize state of modem control lines (DTR).
        !           293:         * If softcar is set, turn on DTR now and leave it.
        !           294:         * otherwise, turn off DTR now, and raise in open.
        !           295:         * (Keeps modem from answering too early.)
        !           296:         */
        !           297:        zs_modem(zst, (zst->zst_swflags & TIOCFLAG_SOFTCAR) ? 1 : 0);
        !           298: }
        !           299:
        !           300:
        !           301: /*
        !           302:  * Return pointer to our tty.
        !           303:  */
        !           304: struct tty *
        !           305: zstty(dev)
        !           306:        dev_t dev;
        !           307: {
        !           308:        struct zstty_softc *zst;
        !           309:        int unit = minor(dev);
        !           310:
        !           311: #ifdef DIAGNOSTIC
        !           312:        if (unit >= zstty_cd.cd_ndevs)
        !           313:                panic("zstty");
        !           314: #endif
        !           315:        zst = zstty_cd.cd_devs[unit];
        !           316:        return (zst->zst_tty);
        !           317: }
        !           318:
        !           319:
        !           320: /*
        !           321:  * Open a zs serial (tty) port.
        !           322:  */
        !           323: int
        !           324: zsopen(dev, flags, mode, p)
        !           325:        dev_t dev;
        !           326:        int flags;
        !           327:        int mode;
        !           328:        struct proc *p;
        !           329: {
        !           330:        register struct tty *tp;
        !           331:        register struct zs_chanstate *cs;
        !           332:        struct zstty_softc *zst;
        !           333:        int error, s, unit;
        !           334:
        !           335:        unit = minor(dev);
        !           336:        if (unit >= zstty_cd.cd_ndevs)
        !           337:                return (ENXIO);
        !           338:        zst = zstty_cd.cd_devs[unit];
        !           339:        if (zst == NULL)
        !           340:                return (ENXIO);
        !           341:        tp = zst->zst_tty;
        !           342:        cs = zst->zst_cs;
        !           343:
        !           344:        /* If KGDB took the line, then tp==NULL */
        !           345:        if (tp == NULL)
        !           346:                return (EBUSY);
        !           347:
        !           348:        /* It's simpler to do this up here. */
        !           349:        if (((tp->t_state & (TS_ISOPEN | TS_XCLUDE))
        !           350:             ==             (TS_ISOPEN | TS_XCLUDE))
        !           351:            && (p->p_ucred->cr_uid != 0) )
        !           352:        {
        !           353:                return (EBUSY);
        !           354:        }
        !           355:
        !           356:        s = spltty();
        !           357:
        !           358:        if ((tp->t_state & TS_ISOPEN) == 0) {
        !           359:                /* First open. */
        !           360:                ttychars(tp);
        !           361:                tp->t_iflag = TTYDEF_IFLAG;
        !           362:                tp->t_oflag = TTYDEF_OFLAG;
        !           363:                tp->t_cflag = ZSTTY_DEF_CFLAG;
        !           364:                if (zst->zst_swflags & TIOCFLAG_CLOCAL)
        !           365:                        tp->t_cflag |= CLOCAL;
        !           366:                if (zst->zst_swflags & TIOCFLAG_CRTSCTS)
        !           367:                        tp->t_cflag |= CRTSCTS;
        !           368:                if (zst->zst_swflags & TIOCFLAG_MDMBUF)
        !           369:                        tp->t_cflag |= MDMBUF;
        !           370:                tp->t_lflag = TTYDEF_LFLAG;
        !           371:                tp->t_ispeed = tp->t_ospeed = cs->cs_defspeed;
        !           372:                (void) zsparam(tp, &tp->t_termios);
        !           373:                ttsetwater(tp);
        !           374:                /* Flush any pending input. */
        !           375:                zst->zst_rbget = zst->zst_rbput;
        !           376:                zs_iflush(cs);  /* XXX */
        !           377:                /* Turn on DTR */
        !           378:                zs_modem(zst, 1);
        !           379:                if (zst->zst_swflags & TIOCFLAG_SOFTCAR) {
        !           380:                        tp->t_state |= TS_CARR_ON;
        !           381:                }
        !           382:        }
        !           383:        error = 0;
        !           384:
        !           385:        /* Wait for carrier. */
        !           386:        for (;;) {
        !           387:
        !           388:                /* Might never get status intr if carrier already on. */
        !           389:                cs->cs_rr0 = zs_read_csr(cs);
        !           390:                if (cs->cs_rr0 & ZSRR0_DCD) {
        !           391:                        tp->t_state |= TS_CARR_ON;
        !           392:                        break;
        !           393:                }
        !           394:
        !           395:                if ((tp->t_state & TS_CARR_ON) ||
        !           396:                    (tp->t_cflag & CLOCAL) ||
        !           397:                    (flags & O_NONBLOCK) )
        !           398:                {
        !           399:                        break;
        !           400:                }
        !           401:
        !           402:                tp->t_state |= TS_WOPEN;
        !           403:                error = ttysleep(tp, (caddr_t)&tp->t_rawq,
        !           404:                        TTIPRI | PCATCH, ttopen, 0);
        !           405:                if (error) {
        !           406:                        if ((tp->t_state & TS_ISOPEN) == 0) {
        !           407:                                /* Never get here with softcar */
        !           408:                                zs_modem(zst, 0);
        !           409:                                tp->t_state &= ~TS_WOPEN;
        !           410:                                ttwakeup(tp);
        !           411:                        }
        !           412:                        break;
        !           413:                }
        !           414:        }
        !           415:
        !           416:        splx(s);
        !           417:
        !           418:        if (error == 0)
        !           419:                error = linesw[tp->t_line].l_open(dev, tp);
        !           420:
        !           421:        return (error);
        !           422: }
        !           423:
        !           424: /*
        !           425:  * Close a zs serial port.
        !           426:  */
        !           427: int
        !           428: zsclose(dev, flags, mode, p)
        !           429:        dev_t dev;
        !           430:        int flags;
        !           431:        int mode;
        !           432:        struct proc *p;
        !           433: {
        !           434:        struct zstty_softc *zst;
        !           435:        register struct zs_chanstate *cs;
        !           436:        register struct tty *tp;
        !           437:        int hup;
        !           438:
        !           439:        zst = zstty_cd.cd_devs[minor(dev)];
        !           440:        cs = zst->zst_cs;
        !           441:        tp = zst->zst_tty;
        !           442:
        !           443:        /* XXX This is for cons.c. */
        !           444:        if ((tp->t_state & TS_ISOPEN) == 0)
        !           445:                return 0;
        !           446:
        !           447:        (*linesw[tp->t_line].l_close)(tp, flags);
        !           448:        hup = tp->t_cflag & HUPCL;
        !           449:        if (zst->zst_swflags & TIOCFLAG_SOFTCAR)
        !           450:                hup = 0;
        !           451:        if (hup) {
        !           452:                zs_modem(zst, 0);
        !           453:                /* hold low for 1 second */
        !           454:                (void) tsleep((caddr_t)cs, TTIPRI, ttclos, hz);
        !           455:        }
        !           456:        if (cs->cs_creg[5] & ZSWR5_BREAK) {
        !           457:                zs_break(cs, 0);
        !           458:        }
        !           459:        /* XXX - turn off interrupts? */
        !           460:
        !           461:        ttyclose(tp);
        !           462:        return (0);
        !           463: }
        !           464:
        !           465: /*
        !           466:  * Read/write zs serial port.
        !           467:  */
        !           468: int
        !           469: zsread(dev, uio, flags)
        !           470:        dev_t dev;
        !           471:        struct uio *uio;
        !           472:        int flags;
        !           473: {
        !           474:        register struct zstty_softc *zst;
        !           475:        register struct tty *tp;
        !           476:
        !           477:        zst = zstty_cd.cd_devs[minor(dev)];
        !           478:        tp = zst->zst_tty;
        !           479:        return (linesw[tp->t_line].l_read(tp, uio, flags));
        !           480: }
        !           481:
        !           482: int
        !           483: zswrite(dev, uio, flags)
        !           484:        dev_t dev;
        !           485:        struct uio *uio;
        !           486:        int flags;
        !           487: {
        !           488:        register struct zstty_softc *zst;
        !           489:        register struct tty *tp;
        !           490:
        !           491:        zst = zstty_cd.cd_devs[minor(dev)];
        !           492:        tp = zst->zst_tty;
        !           493:        return (linesw[tp->t_line].l_write(tp, uio, flags));
        !           494: }
        !           495:
        !           496: #define TIOCFLAG_ALL (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL | \
        !           497:                       TIOCFLAG_CRTSCTS | TIOCFLAG_MDMBUF )
        !           498:
        !           499: int
        !           500: zsioctl(dev, cmd, data, flag, p)
        !           501:        dev_t dev;
        !           502:        u_long cmd;
        !           503:        caddr_t data;
        !           504:        int flag;
        !           505:        struct proc *p;
        !           506: {
        !           507:        register struct zstty_softc *zst;
        !           508:        register struct zs_chanstate *cs;
        !           509:        register struct tty *tp;
        !           510:        register int error, tmp;
        !           511:
        !           512:        zst = zstty_cd.cd_devs[minor(dev)];
        !           513:        cs = zst->zst_cs;
        !           514:        tp = zst->zst_tty;
        !           515:
        !           516:        error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
        !           517:        if (error >= 0)
        !           518:                return (error);
        !           519:        error = ttioctl(tp, cmd, data, flag, p);
        !           520:        if (error >= 0)
        !           521:                return (error);
        !           522:
        !           523:        switch (cmd) {
        !           524:
        !           525:        case TIOCSBRK:
        !           526:                zs_break(cs, 1);
        !           527:                break;
        !           528:
        !           529:        case TIOCCBRK:
        !           530:                zs_break(cs, 0);
        !           531:                break;
        !           532:
        !           533:        case TIOCGFLAGS:
        !           534:                *(int *)data = zst->zst_swflags;
        !           535:                break;
        !           536:
        !           537:        case TIOCSFLAGS:
        !           538:                error = suser(p, 0);
        !           539:                if (error != 0)
        !           540:                        return (EPERM);
        !           541:                tmp = *(int *)data;
        !           542:                /* Check for random bits... */
        !           543:                if (tmp & ~TIOCFLAG_ALL)
        !           544:                        return(EINVAL);
        !           545:                /* Silently enforce softcar on the console. */
        !           546:                if (zst->zst_hwflags & ZS_HWFLAG_CONSOLE)
        !           547:                        tmp |= TIOCFLAG_SOFTCAR;
        !           548:                /* These flags take effect during open. */
        !           549:                zst->zst_swflags = tmp;
        !           550:                break;
        !           551:
        !           552:        case TIOCSDTR:
        !           553:                zs_modem(zst, 1);
        !           554:                break;
        !           555:
        !           556:        case TIOCCDTR:
        !           557:                zs_modem(zst, 0);
        !           558:                break;
        !           559:
        !           560:        case TIOCMSET:
        !           561:        case TIOCMBIS:
        !           562:        case TIOCMBIC:
        !           563:        case TIOCMGET:
        !           564:        default:
        !           565:                return (ENOTTY);
        !           566:        }
        !           567:        return (0);
        !           568: }
        !           569:
        !           570: /*
        !           571:  * Start or restart transmission.
        !           572:  */
        !           573: static void
        !           574: zsstart(tp)
        !           575:        register struct tty *tp;
        !           576: {
        !           577:        register struct zstty_softc *zst;
        !           578:        register struct zs_chanstate *cs;
        !           579:        register int s, nch;
        !           580:
        !           581:        zst = zstty_cd.cd_devs[minor(tp->t_dev)];
        !           582:        cs = zst->zst_cs;
        !           583:
        !           584:        s = spltty();
        !           585:
        !           586:        /*
        !           587:         * If currently active or delaying, no need to do anything.
        !           588:         */
        !           589:        if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))
        !           590:                goto out;
        !           591:
        !           592:        /*
        !           593:         * If under CRTSCTS hfc and halted, do nothing
        !           594:         */
        !           595:        if (tp->t_cflag & CRTSCTS)
        !           596:                if (zst->zst_tx_stopped)
        !           597:                        goto out;
        !           598:
        !           599:        /*
        !           600:         * If there are sleepers, and output has drained below low
        !           601:         * water mark, awaken.
        !           602:         */
        !           603:        if (tp->t_outq.c_cc <= tp->t_lowat) {
        !           604:                if (tp->t_state & TS_ASLEEP) {
        !           605:                        tp->t_state &= ~TS_ASLEEP;
        !           606:                        wakeup((caddr_t)&tp->t_outq);
        !           607:                }
        !           608:                selwakeup(&tp->t_wsel);
        !           609:        }
        !           610:
        !           611:        nch = ndqb(&tp->t_outq, 0);     /* XXX */
        !           612:        (void) splzs();
        !           613:
        !           614:        if (nch) {
        !           615:                register char *p = tp->t_outq.c_cf;
        !           616:
        !           617:                /* mark busy, enable tx done interrupts, & send first byte */
        !           618:                tp->t_state |= TS_BUSY;
        !           619:                zst->zst_tx_busy = 1;
        !           620:                cs->cs_preg[1] |= ZSWR1_TIE;
        !           621:                cs->cs_creg[1] = cs->cs_preg[1];
        !           622:                zs_write_reg(cs, 1, cs->cs_creg[1]);
        !           623:                zs_write_data(cs, *p);
        !           624:                zst->zst_tba = p + 1;
        !           625:                zst->zst_tbc = nch - 1;
        !           626:        } else {
        !           627:                /*
        !           628:                 * Nothing to send, turn off transmit done interrupts.
        !           629:                 * This is useful if something is doing polled output.
        !           630:                 */
        !           631:                cs->cs_preg[1] &= ~ZSWR1_TIE;
        !           632:                cs->cs_creg[1] = cs->cs_preg[1];
        !           633:                zs_write_reg(cs, 1, cs->cs_creg[1]);
        !           634:        }
        !           635: out:
        !           636:        splx(s);
        !           637: }
        !           638:
        !           639: /*
        !           640:  * Stop output, e.g., for ^S or output flush.
        !           641:  */
        !           642: int
        !           643: zsstop(tp, flag)
        !           644:        struct tty *tp;
        !           645:        int flag;
        !           646: {
        !           647:        register struct zstty_softc *zst;
        !           648:        register struct zs_chanstate *cs;
        !           649:        register int s;
        !           650:
        !           651:        zst = zstty_cd.cd_devs[minor(tp->t_dev)];
        !           652:        cs = zst->zst_cs;
        !           653:
        !           654:        s = splzs();
        !           655:        if (tp->t_state & TS_BUSY) {
        !           656:                /*
        !           657:                 * Device is transmitting; must stop it.
        !           658:                 * Also clear _heldtbc to prevent any
        !           659:                 * flow-control event from resuming.
        !           660:                 */
        !           661:                zst->zst_tbc = 0;
        !           662:                zst->zst_heldtbc = 0;
        !           663:                if ((tp->t_state & TS_TTSTOP) == 0)
        !           664:                        tp->t_state |= TS_FLUSH;
        !           665:        }
        !           666:        splx(s);
        !           667:        return (0);
        !           668: }
        !           669:
        !           670: /*
        !           671:  * Set ZS tty parameters from termios.
        !           672:  * XXX - Should just copy the whole termios after
        !           673:  * making sure all the changes could be done.
        !           674:  * XXX - Only whack the UART when params change...
        !           675:  */
        !           676: static int
        !           677: zsparam(tp, t)
        !           678:        register struct tty *tp;
        !           679:        register struct termios *t;
        !           680: {
        !           681:        register struct zstty_softc *zst;
        !           682:        register struct zs_chanstate *cs;
        !           683:        register int s, bps, cflag, tconst;
        !           684:        u_char tmp3, tmp4, tmp5;
        !           685:
        !           686:        zst = zstty_cd.cd_devs[minor(tp->t_dev)];
        !           687:        cs = zst->zst_cs;
        !           688:
        !           689:        /* XXX: Need to use an MD function for this. */
        !           690:        bps = t->c_ospeed;
        !           691:        if (bps < 0 || (t->c_ispeed && t->c_ispeed != bps))
        !           692:                return (EINVAL);
        !           693:        if (bps == 0) {
        !           694:                /* stty 0 => drop DTR and RTS */
        !           695:                zs_modem(zst, 0);
        !           696:                return (0);
        !           697:        }
        !           698:        tconst = BPS_TO_TCONST(cs->cs_brg_clk, bps);
        !           699:        if (tconst < 0)
        !           700:                return (EINVAL);
        !           701:
        !           702:        /* Convert back to make sure we can do it. */
        !           703:        bps = TCONST_TO_BPS(cs->cs_brg_clk, tconst);
        !           704:        if (bps != t->c_ospeed)
        !           705:                return (EINVAL);
        !           706:        tp->t_ispeed = tp->t_ospeed = bps;
        !           707:
        !           708:        cflag = t->c_cflag;
        !           709:        tp->t_cflag = cflag;
        !           710:
        !           711:        /*
        !           712:         * Block interrupts so that state will not
        !           713:         * be altered until we are done setting it up.
        !           714:         */
        !           715:        s = splzs();
        !           716:
        !           717:        /*
        !           718:         * Initial values in cs_preg are set before
        !           719:         * our attach routine is called.  The master
        !           720:         * interrupt enable is handled by zsc.c
        !           721:         */
        !           722:
        !           723:        cs->cs_preg[12] = tconst;
        !           724:        cs->cs_preg[13] = tconst >> 8;
        !           725:
        !           726:        switch (cflag & CSIZE) {
        !           727:        case CS5:
        !           728:                tmp3 = ZSWR3_RX_5;
        !           729:                tmp5 = ZSWR5_TX_5;
        !           730:                break;
        !           731:        case CS6:
        !           732:                tmp3 = ZSWR3_RX_6;
        !           733:                tmp5 = ZSWR5_TX_6;
        !           734:                break;
        !           735:        case CS7:
        !           736:                tmp3 = ZSWR3_RX_7;
        !           737:                tmp5 = ZSWR5_TX_7;
        !           738:                break;
        !           739:        case CS8:
        !           740:        default:
        !           741:                tmp3 = ZSWR3_RX_8;
        !           742:                tmp5 = ZSWR5_TX_8;
        !           743:                break;
        !           744:        }
        !           745:
        !           746:        cs->cs_preg[3] = tmp3 | ZSWR3_RX_ENABLE;
        !           747:        cs->cs_preg[5] = tmp5 | ZSWR5_TX_ENABLE | ZSWR5_DTR | ZSWR5_RTS;
        !           748:
        !           749:        tmp4 = ZSWR4_CLK_X16 | (cflag & CSTOPB ? ZSWR4_TWOSB : ZSWR4_ONESB);
        !           750:        if ((cflag & PARODD) == 0)
        !           751:                tmp4 |= ZSWR4_EVENP;
        !           752:        if (cflag & PARENB)
        !           753:                tmp4 |= ZSWR4_PARENB;
        !           754:        cs->cs_preg[4] = tmp4;
        !           755:
        !           756:        /*
        !           757:         * Output hardware flow control on the chip is horrendous:
        !           758:         * if carrier detect drops, the receiver is disabled.
        !           759:         * Therefore, NEVER set the HFC bit, and instead use
        !           760:         * the status interrupts to detect CTS changes.
        !           761:         */
        !           762:        if (cflag & CRTSCTS) {
        !           763:                zst->zst_rbhiwat = zstty_rbuf_hiwat;
        !           764:                cs->cs_preg[15] |= ZSWR15_CTS_IE;
        !           765:        } else {
        !           766:                zst->zst_rbhiwat = zstty_rbuf_size; /* impossible value */
        !           767:                cs->cs_preg[15] &= ~ZSWR15_CTS_IE;
        !           768:        }
        !           769:
        !           770:        /*
        !           771:         * If nothing is being transmitted, set up new current values,
        !           772:         * else mark them as pending.
        !           773:         */
        !           774:        if (cs->cs_heldchange == 0) {
        !           775:                if (zst->zst_tx_busy) {
        !           776:                        zst->zst_heldtbc = zst->zst_tbc;
        !           777:                        zst->zst_tbc = 0;
        !           778:                        cs->cs_heldchange = 0xFF; /* XXX */
        !           779:                } else {
        !           780:                        zs_loadchannelregs(cs);
        !           781:                }
        !           782:        }
        !           783:        splx(s);
        !           784:        return (0);
        !           785: }
        !           786:
        !           787: /*
        !           788:  * Raise or lower modem control (DTR/RTS) signals.  If a character is
        !           789:  * in transmission, the change is deferred.
        !           790:  */
        !           791: static void
        !           792: zs_modem(zst, onoff)
        !           793:        struct zstty_softc *zst;
        !           794:        int onoff;
        !           795: {
        !           796:        struct zs_chanstate *cs;
        !           797:        struct tty *tp;
        !           798:        int s, bis, and;
        !           799:
        !           800:        cs = zst->zst_cs;
        !           801:        tp = zst->zst_tty;
        !           802:
        !           803:        if (onoff) {
        !           804:                bis = ZSWR5_DTR | ZSWR5_RTS;
        !           805:                and = ~0;
        !           806:        } else {
        !           807:                bis = 0;
        !           808:                and = ~(ZSWR5_DTR | ZSWR5_RTS);
        !           809:        }
        !           810:        s = splzs();
        !           811:        cs->cs_preg[5] = (cs->cs_preg[5] | bis) & and;
        !           812:        if (cs->cs_heldchange == 0) {
        !           813:                if (zst->zst_tx_busy) {
        !           814:                        zst->zst_heldtbc = zst->zst_tbc;
        !           815:                        zst->zst_tbc = 0;
        !           816:                        cs->cs_heldchange = (1<<5);
        !           817:                } else {
        !           818:                        cs->cs_creg[5] = cs->cs_preg[5];
        !           819:                        zs_write_reg(cs, 5, cs->cs_creg[5]);
        !           820:                }
        !           821:        }
        !           822:        splx(s);
        !           823: }
        !           824:
        !           825: /*
        !           826:  * Try to block or unblock input using hardware flow-control.
        !           827:  * This is called by kern/tty.c if MDMBUF|CRTSCTS is set, and
        !           828:  * if this function returns non-zero, the TS_TBLOCK flag will
        !           829:  * be set or cleared according to the "stop" arg passed.
        !           830:  */
        !           831: int
        !           832: zshwiflow(tp, stop)
        !           833:        struct tty *tp;
        !           834:        int stop;
        !           835: {
        !           836:        register struct zstty_softc *zst;
        !           837:        int s;
        !           838:
        !           839:        zst = zstty_cd.cd_devs[minor(tp->t_dev)];
        !           840:
        !           841:        s = splzs();
        !           842:        if (stop) {
        !           843:                /*
        !           844:                 * The tty layer is asking us to block input.
        !           845:                 * If we already did it, just return TRUE.
        !           846:                 */
        !           847:                if (zst->zst_rx_blocked)
        !           848:                        goto out;
        !           849:                zst->zst_rx_blocked = 1;
        !           850:        } else {
        !           851:                /*
        !           852:                 * The tty layer is asking us to resume input.
        !           853:                 * The input ring is always empty by now.
        !           854:                 */
        !           855:                zst->zst_rx_blocked = 0;
        !           856:        }
        !           857:        zs_hwiflow(zst, stop);
        !           858:  out:
        !           859:        splx(s);
        !           860:        return 1;
        !           861: }
        !           862:
        !           863: /*
        !           864:  * Internal version of zshwiflow
        !           865:  * called at splzs
        !           866:  */
        !           867: static void
        !           868: zs_hwiflow(zst, stop)
        !           869:        register struct zstty_softc *zst;
        !           870:        int stop;
        !           871: {
        !           872:        register struct zs_chanstate *cs;
        !           873:        register struct tty *tp;
        !           874:        register int bis, and;
        !           875:
        !           876:        cs = zst->zst_cs;
        !           877:        tp = zst->zst_tty;
        !           878:
        !           879:        if (stop) {
        !           880:                /* Block input (Lower RTS) */
        !           881:                bis = 0;
        !           882:                and = ~ZSWR5_RTS;
        !           883:        } else {
        !           884:                /* Unblock input (Raise RTS) */
        !           885:                bis = ZSWR5_RTS;
        !           886:                and = ~0;
        !           887:        }
        !           888:
        !           889:        cs->cs_preg[5] = (cs->cs_preg[5] | bis) & and;
        !           890:        if (cs->cs_heldchange == 0) {
        !           891:                if (zst->zst_tx_busy) {
        !           892:                        zst->zst_heldtbc = zst->zst_tbc;
        !           893:                        zst->zst_tbc = 0;
        !           894:                        cs->cs_heldchange = (1<<5);
        !           895:                } else {
        !           896:                        cs->cs_creg[5] = cs->cs_preg[5];
        !           897:                        zs_write_reg(cs, 5, cs->cs_creg[5]);
        !           898:                }
        !           899:        }
        !           900: }
        !           901:
        !           902:
        !           903: /****************************************************************
        !           904:  * Interface to the lower layer (zscc)
        !           905:  ****************************************************************/
        !           906:
        !           907:
        !           908: /*
        !           909:  * receiver ready interrupt.
        !           910:  * called at splzs
        !           911:  */
        !           912: static void
        !           913: zstty_rxint(cs)
        !           914:        register struct zs_chanstate *cs;
        !           915: {
        !           916:        register struct zstty_softc *zst;
        !           917:        register int cc, put, put_next, ringmask;
        !           918:        register u_char c, rr0, rr1;
        !           919:        register u_short ch_rr1;
        !           920:
        !           921:        zst = cs->cs_private;
        !           922:        put = zst->zst_rbput;
        !           923:        ringmask = zst->zst_ringmask;
        !           924:
        !           925: nextchar:
        !           926:
        !           927:        /*
        !           928:         * First read the status, because reading the received char
        !           929:         * destroys the status of this char.
        !           930:         */
        !           931:        rr1 = zs_read_reg(cs, 1);
        !           932:        c = zs_read_data(cs);
        !           933:        ch_rr1 = (c << 8) | rr1;
        !           934:
        !           935:        if (ch_rr1 & (ZSRR1_FE | ZSRR1_DO | ZSRR1_PE)) {
        !           936:                /* Clear the receive error. */
        !           937:                zs_write_csr(cs, ZSWR0_RESET_ERRORS);
        !           938:        }
        !           939:
        !           940:        /* XXX: Check for the stop character? */
        !           941:
        !           942:        zst->zst_rbuf[put] = ch_rr1;
        !           943:        put_next = (put + 1) & ringmask;
        !           944:
        !           945:        /* Would overrun if increment makes (put==get). */
        !           946:        if (put_next == zst->zst_rbget) {
        !           947:                zst->zst_rx_overrun = 1;
        !           948:        } else {
        !           949:                /* OK, really increment. */
        !           950:                put = put_next;
        !           951:        }
        !           952:
        !           953:        /* Keep reading until the FIFO is empty. */
        !           954:        rr0 = zs_read_csr(cs);
        !           955:        if (rr0 & ZSRR0_RX_READY)
        !           956:                goto nextchar;
        !           957:
        !           958:        /* Done reading. */
        !           959:        zst->zst_rbput = put;
        !           960:
        !           961:        /*
        !           962:         * If ring is getting too full, try to block input.
        !           963:         */
        !           964:        cc = put - zst->zst_rbget;
        !           965:        if (cc < 0)
        !           966:                cc += zstty_rbuf_size;
        !           967:        if ((cc > zst->zst_rbhiwat) && (zst->zst_rx_blocked == 0)) {
        !           968:                zst->zst_rx_blocked = 1;
        !           969:                zs_hwiflow(zst, 1);
        !           970:        }
        !           971:
        !           972:        /* Ask for softint() call. */
        !           973:        cs->cs_softreq = 1;
        !           974: }
        !           975:
        !           976: /*
        !           977:  * transmitter ready interrupt.  (splzs)
        !           978:  */
        !           979: static void
        !           980: zstty_txint(cs)
        !           981:        register struct zs_chanstate *cs;
        !           982: {
        !           983:        register struct zstty_softc *zst;
        !           984:        register int count;
        !           985:
        !           986:        zst = cs->cs_private;
        !           987:
        !           988:        /*
        !           989:         * If we suspended output for a "held" change,
        !           990:         * then handle that now and resume.
        !           991:         * Do flow-control changes ASAP.
        !           992:         * When the only change is for flow control,
        !           993:         * avoid hitting other registers, because that
        !           994:         * often makes the stupid zs drop input...
        !           995:         */
        !           996:        if (cs->cs_heldchange) {
        !           997:                if (cs->cs_heldchange == (1<<5)) {
        !           998:                        /* Avoid whacking the chip... */
        !           999:                        cs->cs_creg[5] = cs->cs_preg[5];
        !          1000:                        zs_write_reg(cs, 5, cs->cs_creg[5]);
        !          1001:                } else
        !          1002:                        zs_loadchannelregs(cs);
        !          1003:                cs->cs_heldchange = 0;
        !          1004:                count = zst->zst_heldtbc;
        !          1005:        } else
        !          1006:                count = zst->zst_tbc;
        !          1007:
        !          1008:        /*
        !          1009:         * If our transmit buffer still has data,
        !          1010:         * just send the next character.
        !          1011:         */
        !          1012:        if (count > 0) {
        !          1013:                /* Send the next char. */
        !          1014:                zst->zst_tbc = --count;
        !          1015:                zs_write_data(cs, *zst->zst_tba);
        !          1016:                zst->zst_tba++;
        !          1017:                return;
        !          1018:        }
        !          1019:
        !          1020:        zs_write_csr(cs, ZSWR0_RESET_TXINT);
        !          1021:
        !          1022:        /* Ask the softint routine for more output. */
        !          1023:        zst->zst_tx_busy = 0;
        !          1024:        zst->zst_tx_done = 1;
        !          1025:        cs->cs_softreq = 1;
        !          1026: }
        !          1027:
        !          1028: /*
        !          1029:  * status change interrupt.  (splzs)
        !          1030:  */
        !          1031: static void
        !          1032: zstty_stint(cs)
        !          1033:        register struct zs_chanstate *cs;
        !          1034: {
        !          1035:        register struct zstty_softc *zst;
        !          1036:        register struct tty *tp;
        !          1037:        register u_char rr0;
        !          1038:
        !          1039:        zst = cs->cs_private;
        !          1040:        tp  = zst->zst_tty;
        !          1041:
        !          1042:        rr0 = zs_read_csr(cs);
        !          1043:        zs_write_csr(cs, ZSWR0_RESET_STATUS);
        !          1044:
        !          1045:        /*
        !          1046:         * Check here for console break, so that we can abort
        !          1047:         * even when interrupts are locking up the machine.
        !          1048:         */
        !          1049:        if ((rr0 & ZSRR0_BREAK) &&
        !          1050:                (zst->zst_hwflags & ZS_HWFLAG_CONSOLE))
        !          1051:        {
        !          1052:                zs_abort();
        !          1053:                return;
        !          1054:        }
        !          1055:
        !          1056:        /*
        !          1057:         * Need to handle CTS output flow control here.
        !          1058:         * Output remains stopped as long as either the
        !          1059:         * zst_tx_stopped or TS_TTSTOP flag is set.
        !          1060:         * Never restart here; the softint routine will
        !          1061:         * do that after things are ready to move.
        !          1062:         */
        !          1063:        if (((rr0 & ZSRR0_CTS) == 0) && (tp->t_cflag & CRTSCTS)) {
        !          1064:                zst->zst_tbc = 0;
        !          1065:                zst->zst_heldtbc = 0;
        !          1066:                zst->zst_tx_stopped = 1;
        !          1067:        }
        !          1068:
        !          1069:        /*
        !          1070:         * We have to accumulate status line changes here.
        !          1071:         * Otherwise, if we get multiple status interrupts
        !          1072:         * before the softint runs, we could fail to notice
        !          1073:         * some status line changes in the softint routine.
        !          1074:         * Fix from Bill Studenmund, October 1996.
        !          1075:         */
        !          1076:        cs->cs_rr0_delta |= (cs->cs_rr0 ^ rr0);
        !          1077:
        !          1078:        ttytstamp(tp, cs->cs_rr0 & ZSRR0_CTS, rr0 & ZSRR0_CTS,
        !          1079:            cs->cs_rr0 & ZSRR0_DCD, rr0 & ZSRR0_DCD);
        !          1080:
        !          1081:        cs->cs_rr0 = rr0;
        !          1082:        zst->zst_st_check = 1;
        !          1083:
        !          1084:        /* Ask for softint() call. */
        !          1085:        cs->cs_softreq = 1;
        !          1086: }
        !          1087:
        !          1088: /*
        !          1089:  * Print out a ring or fifo overrun error message.
        !          1090:  */
        !          1091: static void
        !          1092: zsoverrun(zst, ptime, what)
        !          1093:        struct zstty_softc *zst;
        !          1094:        long *ptime;
        !          1095:        char *what;
        !          1096: {
        !          1097:
        !          1098:        if (*ptime != time_second) {
        !          1099:                *ptime = time_second;
        !          1100:                log(LOG_WARNING, "%s: %s overrun\n",
        !          1101:                        zst->zst_dev.dv_xname, what);
        !          1102:        }
        !          1103: }
        !          1104:
        !          1105: /*
        !          1106:  * Software interrupt.  Called at zssoft
        !          1107:  *
        !          1108:  * The main job to be done here is to empty the input ring
        !          1109:  * by passing its contents up to the tty layer.  The ring is
        !          1110:  * always emptied during this operation, therefore the ring
        !          1111:  * must not be larger than the space after "high water" in
        !          1112:  * the tty layer, or the tty layer might drop our input.
        !          1113:  *
        !          1114:  * Note: an "input blockage" condition is assumed to exist if
        !          1115:  * EITHER the TS_TBLOCK flag or zst_rx_blocked flag is set.
        !          1116:  */
        !          1117: static void
        !          1118: zstty_softint(cs)
        !          1119:        struct zs_chanstate *cs;
        !          1120: {
        !          1121:        register struct zstty_softc *zst;
        !          1122:        register struct linesw *line;
        !          1123:        register struct tty *tp;
        !          1124:        register int get, c, s;
        !          1125:        int ringmask, overrun;
        !          1126:        register u_short ring_data;
        !          1127:        register u_char rr0, delta;
        !          1128:
        !          1129:        zst  = cs->cs_private;
        !          1130:        tp   = zst->zst_tty;
        !          1131:        line = &linesw[tp->t_line];
        !          1132:        ringmask = zst->zst_ringmask;
        !          1133:        overrun = 0;
        !          1134:
        !          1135:        /*
        !          1136:         * Raise to tty priority while servicing the ring.
        !          1137:         */
        !          1138:        s = spltty();
        !          1139:
        !          1140:        if (zst->zst_rx_overrun) {
        !          1141:                zst->zst_rx_overrun = 0;
        !          1142:                zsoverrun(zst, &zst->zst_rotime, "ring");
        !          1143:        }
        !          1144:
        !          1145:        /*
        !          1146:         * Copy data from the receive ring into the tty layer.
        !          1147:         */
        !          1148:        get = zst->zst_rbget;
        !          1149:        while (get != zst->zst_rbput) {
        !          1150:                ring_data = zst->zst_rbuf[get];
        !          1151:                get = (get + 1) & ringmask;
        !          1152:
        !          1153:                if (ring_data & ZSRR1_DO)
        !          1154:                        overrun++;
        !          1155:                /* low byte of ring_data is rr1 */
        !          1156:                c = (ring_data >> 8) & 0xff;
        !          1157:                if (ring_data & ZSRR1_FE)
        !          1158:                        c |= TTY_FE;
        !          1159:                if (ring_data & ZSRR1_PE)
        !          1160:                        c |= TTY_PE;
        !          1161:
        !          1162:                line->l_rint(c, tp);
        !          1163:        }
        !          1164:        zst->zst_rbget = get;
        !          1165:
        !          1166:        /*
        !          1167:         * If the overrun flag is set now, it was set while
        !          1168:         * copying char/status pairs from the ring, which
        !          1169:         * means this was a hardware (fifo) overrun.
        !          1170:         */
        !          1171:        if (overrun) {
        !          1172:                zsoverrun(zst, &zst->zst_fotime, "fifo");
        !          1173:        }
        !          1174:
        !          1175:        /*
        !          1176:         * We have emptied the input ring.  Maybe unblock input.
        !          1177:         * Note: an "input blockage" condition is assumed to exist
        !          1178:         * when EITHER zst_rx_blocked or the TS_TBLOCK flag is set,
        !          1179:         * so unblock here ONLY if TS_TBLOCK has not been set.
        !          1180:         */
        !          1181:        if (zst->zst_rx_blocked && ((tp->t_state & TS_TBLOCK) == 0)) {
        !          1182:                (void) splzs();
        !          1183:                zst->zst_rx_blocked = 0;
        !          1184:                zs_hwiflow(zst, 0);     /* unblock input */
        !          1185:                (void) spltty();
        !          1186:        }
        !          1187:
        !          1188:        /*
        !          1189:         * Do any deferred work for status interrupts.
        !          1190:         * The rr0 was saved in the h/w interrupt to
        !          1191:         * avoid another splzs in here.
        !          1192:         */
        !          1193:        if (zst->zst_st_check) {
        !          1194:                zst->zst_st_check = 0;
        !          1195:
        !          1196:                rr0 = cs->cs_rr0;
        !          1197:                delta = cs->cs_rr0_delta;
        !          1198:                cs->cs_rr0_delta = 0;
        !          1199:                if (delta & ZSRR0_DCD) {
        !          1200:                        c = ((rr0 & ZSRR0_DCD) != 0);
        !          1201:                        if (line->l_modem(tp, c) == 0)
        !          1202:                                zs_modem(zst, c);
        !          1203:                }
        !          1204:                if ((delta & ZSRR0_CTS) && (tp->t_cflag & CRTSCTS)) {
        !          1205:                        /*
        !          1206:                         * Only do restart here.  Stop is handled
        !          1207:                         * at the h/w interrupt level.
        !          1208:                         */
        !          1209:                        if (rr0 & ZSRR0_CTS) {
        !          1210:                                zst->zst_tx_stopped = 0;
        !          1211:                                tp->t_state &= ~TS_TTSTOP;
        !          1212:                                (*line->l_start)(tp);
        !          1213:                        }
        !          1214:                }
        !          1215:        }
        !          1216:
        !          1217:        if (zst->zst_tx_done) {
        !          1218:                zst->zst_tx_done = 0;
        !          1219:                tp->t_state &= ~TS_BUSY;
        !          1220:                if (tp->t_state & TS_FLUSH)
        !          1221:                        tp->t_state &= ~TS_FLUSH;
        !          1222:                else
        !          1223:                        ndflush(&tp->t_outq, zst->zst_tba -
        !          1224:                                (caddr_t) tp->t_outq.c_cf);
        !          1225:                line->l_start(tp);
        !          1226:        }
        !          1227:
        !          1228:        splx(s);
        !          1229: }
        !          1230:
        !          1231: struct zsops zsops_tty = {
        !          1232:        zstty_rxint,    /* receive char available */
        !          1233:        zstty_stint,    /* external/status */
        !          1234:        zstty_txint,    /* xmit buffer empty */
        !          1235:        zstty_softint,  /* process software interrupt */
        !          1236: };
        !          1237:

CVSweb