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

Annotation of sys/arch/mac68k/dev/z8530tty.c, Revision 1.1.1.1

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

CVSweb