[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

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