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

Annotation of sys/arch/sparc/dev/z8530kbd.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: z8530kbd.c,v 1.9 2007/05/25 21:27:15 krw Exp $        */
                      2: /*     $NetBSD: z8530tty.c,v 1.77 2001/05/30 15:24:24 lukem Exp $      */
                      3:
                      4: /*-
                      5:  * Copyright (c) 1993, 1994, 1995, 1996, 1997, 1998, 1999
                      6:  *     Charles M. Hannum.  All rights reserved.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
                     16:  * 3. All advertising materials mentioning features or use of this software
                     17:  *    must display the following acknowledgement:
                     18:  *     This product includes software developed by Charles M. Hannum.
                     19:  * 4. The name of the author may not be used to endorse or promote products
                     20:  *    derived from this software without specific prior written permission.
                     21:  *
                     22:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     23:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     24:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     25:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     26:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     27:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     28:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     29:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     30:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     31:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     32:  */
                     33:
                     34: /*
                     35:  * Copyright (c) 1994 Gordon W. Ross
                     36:  * Copyright (c) 1992, 1993
                     37:  *     The Regents of the University of California.  All rights reserved.
                     38:  *
                     39:  * This software was developed by the Computer Systems Engineering group
                     40:  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
                     41:  * contributed to Berkeley.
                     42:  *
                     43:  * All advertising materials mentioning features or use of this software
                     44:  * must display the following acknowledgement:
                     45:  *     This product includes software developed by the University of
                     46:  *     California, Lawrence Berkeley Laboratory.
                     47:  *
                     48:  * Redistribution and use in source and binary forms, with or without
                     49:  * modification, are permitted provided that the following conditions
                     50:  * are met:
                     51:  * 1. Redistributions of source code must retain the above copyright
                     52:  *    notice, this list of conditions and the following disclaimer.
                     53:  * 2. Redistributions in binary form must reproduce the above copyright
                     54:  *    notice, this list of conditions and the following disclaimer in the
                     55:  *    documentation and/or other materials provided with the distribution.
                     56:  * 3. Neither the name of the University nor the names of its contributors
                     57:  *    may be used to endorse or promote products derived from this software
                     58:  *    without specific prior written permission.
                     59:  *
                     60:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     61:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     62:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     63:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     64:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     65:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     66:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     67:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     68:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     69:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     70:  * SUCH DAMAGE.
                     71:  *
                     72:  *     @(#)zs.c        8.1 (Berkeley) 7/19/93
                     73:  */
                     74:
                     75: /*
                     76:  * Zilog Z8530 Dual UART driver (tty interface)
                     77:  *
                     78:  * This is the "slave" driver that will be attached to
                     79:  * the "zsc" driver for plain "tty" async. serial lines.
                     80:  *
                     81:  * Credits, history:
                     82:  *
                     83:  * The original version of this code was the sparc/dev/zs.c driver
                     84:  * as distributed with the Berkeley 4.4 Lite release.  Since then,
                     85:  * Gordon Ross reorganized the code into the current parent/child
                     86:  * driver scheme, separating the Sun keyboard and mouse support
                     87:  * into independent child drivers.
                     88:  *
                     89:  * RTS/CTS flow-control support was a collaboration of:
                     90:  *     Gordon Ross <gwr@netbsd.org>,
                     91:  *     Bill Studenmund <wrstuden@loki.stanford.edu>
                     92:  *     Ian Dall <Ian.Dall@dsto.defence.gov.au>
                     93:  *
                     94:  * The driver was massively overhauled in November 1997 by Charles Hannum,
                     95:  * fixing *many* bugs, and substantially improving performance.
                     96:  */
                     97:
                     98: #include <sys/param.h>
                     99: #include <sys/systm.h>
                    100: #include <sys/proc.h>
                    101: #include <sys/device.h>
                    102: #include <sys/conf.h>
                    103: #include <sys/file.h>
                    104: #include <sys/ioctl.h>
                    105: #include <sys/malloc.h>
                    106: #include <sys/tty.h>
                    107: #include <sys/time.h>
                    108: #include <sys/kernel.h>
                    109: #include <sys/syslog.h>
                    110:
                    111: #include <machine/autoconf.h>
                    112: #include <machine/conf.h>
                    113:
                    114: #include <dev/wscons/wsconsio.h>
                    115: #include <dev/wscons/wskbdvar.h>
                    116:
                    117: #include <dev/sun/sunkbdreg.h>
                    118: #include <dev/sun/sunkbdvar.h>
                    119:
                    120: #include <sparc/dev/z8530reg.h>
                    121: #include <machine/z8530var.h>
                    122:
                    123: #include <dev/cons.h>
                    124:
                    125: /*
                    126:  * How many input characters we can buffer.
                    127:  * The port-specific var.h may override this.
                    128:  * Note: must be a power of two!
                    129:  */
                    130: #ifndef        ZSKBD_RING_SIZE
                    131: #define        ZSKBD_RING_SIZE 2048
                    132: #endif
                    133:
                    134: struct cfdriver zskbd_cd = {
                    135:        NULL, "zskbd", DV_TTY
                    136: };
                    137:
                    138: /*
                    139:  * Make this an option variable one can patch.
                    140:  * But be warned:  this must be a power of 2!
                    141:  */
                    142: u_int zskbd_rbuf_size = ZSKBD_RING_SIZE;
                    143:
                    144: /* Stop input when 3/4 of the ring is full; restart when only 1/4 is full. */
                    145: u_int zskbd_rbuf_hiwat = (ZSKBD_RING_SIZE * 1) / 4;
                    146: u_int zskbd_rbuf_lowat = (ZSKBD_RING_SIZE * 3) / 4;
                    147:
                    148: struct zskbd_softc {
                    149:        struct sunkbd_softc     zst_base;
                    150:
                    151:        struct  zs_chanstate *zst_cs;
                    152:
                    153:        struct timeout zst_diag_ch;
                    154:
                    155:        u_int zst_overflows,
                    156:              zst_floods,
                    157:              zst_errors;
                    158:
                    159:        int zst_hwflags,        /* see z8530var.h */
                    160:            zst_swflags;        /* TIOCFLAG_SOFTCAR, ... <ttycom.h> */
                    161:
                    162:        u_int zst_r_hiwat,
                    163:              zst_r_lowat;
                    164:        u_char *volatile zst_rbget,
                    165:               *volatile zst_rbput;
                    166:        volatile u_int zst_rbavail;
                    167:        u_char *zst_rbuf,
                    168:               *zst_ebuf;
                    169:
                    170:        /*
                    171:         * The transmit byte count and address are used for pseudo-DMA
                    172:         * output in the hardware interrupt code.  PDMA can be suspended
                    173:         * to get pending changes done; heldtbc is used for this.  It can
                    174:         * also be stopped for ^S; this sets TS_TTSTOP in tp->t_state.
                    175:         */
                    176:        u_char *zst_tba;                /* transmit buffer address */
                    177:        u_int zst_tbc,                  /* transmit byte count */
                    178:              zst_heldtbc;              /* held tbc while xmission stopped */
                    179:
                    180:        u_char zst_tbuf[ZSKBD_RING_SIZE];
                    181:        u_char *zst_tbeg, *zst_tend, *zst_tbp;
                    182:
                    183:        /* Flags to communicate with zskbd_softint() */
                    184:        volatile u_char zst_rx_flags,   /* receiver blocked */
                    185: #define        RX_TTY_BLOCKED          0x01
                    186: #define        RX_TTY_OVERFLOWED       0x02
                    187: #define        RX_IBUF_BLOCKED         0x04
                    188: #define        RX_IBUF_OVERFLOWED      0x08
                    189: #define        RX_ANY_BLOCK            0x0f
                    190:                        zst_tx_busy,    /* working on an output chunk */
                    191:                        zst_tx_done,    /* done with one output chunk */
                    192:                        zst_tx_stopped, /* H/W level stop (lost CTS) */
                    193:                        zst_st_check,   /* got a status interrupt */
                    194:                        zst_rx_ready;
                    195:
                    196:        /* PPS signal on DCD, with or without inkernel clock disciplining */
                    197:        u_char  zst_ppsmask;                    /* pps signal mask */
                    198:        u_char  zst_ppsassert;                  /* pps leading edge */
                    199:        u_char  zst_ppsclear;                   /* pps trailing edge */
                    200: };
                    201:
                    202: /* Definition of the driver for autoconfig. */
                    203: static int     zskbd_match(struct device *, void *, void *);
                    204: static void    zskbd_attach(struct device *, struct device *, void *);
                    205:
                    206: struct cfattach zskbd_ca = {
                    207:        sizeof(struct zskbd_softc), zskbd_match, zskbd_attach
                    208: };
                    209:
                    210: struct zsops zsops_kbd;
                    211:
                    212: static void zs_modem(struct zskbd_softc *, int);
                    213: static void zs_hwiflow(struct zskbd_softc *);
                    214: static void zs_maskintr(struct zskbd_softc *);
                    215:
                    216: struct zskbd_softc *zskbd_device_lookup(struct cfdriver *, int);
                    217:
                    218: /* Low-level routines. */
                    219: static void zskbd_rxint(struct zs_chanstate *);
                    220: static void zskbd_stint(struct zs_chanstate *, int);
                    221: static void zskbd_txint(struct zs_chanstate *);
                    222: static void zskbd_softint(struct zs_chanstate *);
                    223: static void zskbd_diag(void *);
                    224:
                    225: int zskbd_init(struct zskbd_softc *);
                    226: void zskbd_putc(struct zskbd_softc *, u_int8_t);
                    227: void zskbd_raw(struct zskbd_softc *, u_int8_t);
                    228:
                    229: /* wskbd glue */
                    230: void zskbd_cngetc(void *, u_int *, int *);
                    231: void zskbd_cnpollc(void *, int);
                    232:
                    233: void zsstart_tx(struct zskbd_softc *);
                    234: int zsenqueue_tx(void *, u_int8_t *, u_int);
                    235:
                    236: struct wskbd_consops zskbd_consops = {
                    237:        zskbd_cngetc,
                    238:        zskbd_cnpollc
                    239: };
                    240:
                    241: #define        ZSKBDUNIT(x)    (minor(x) & 0x7ffff)
                    242:
                    243: struct zskbd_softc *
                    244: zskbd_device_lookup(cf, unit)
                    245:        struct cfdriver *cf;
                    246:        int unit;
                    247: {
                    248:        return (struct zskbd_softc *)device_lookup(cf, unit);
                    249: }
                    250:
                    251: /*
                    252:  * zskbd_match: how is this zs channel configured?
                    253:  */
                    254: int
                    255: zskbd_match(parent, vcf, aux)
                    256:        struct device *parent;
                    257:        void *vcf;
                    258:        void   *aux;
                    259: {
                    260:        struct cfdata *cf = vcf;
                    261:        struct zsc_attach_args *args = aux;
                    262:        int ret;
                    263:
                    264:        /* If we're not looking for a keyboard, just exit */
                    265:        if (strcmp(args->type, "keyboard") != 0)
                    266:                return (0);
                    267:
                    268:        ret = 10;
                    269:
                    270:        /* Exact match is better than wildcard. */
                    271:        if (cf->cf_loc[ZSCCF_CHANNEL] == args->channel)
                    272:                ret += 2;
                    273:
                    274:        /* This driver accepts wildcard. */
                    275:        if (cf->cf_loc[ZSCCF_CHANNEL] == ZSCCF_CHANNEL_DEFAULT)
                    276:                ret += 1;
                    277:
                    278:        return (ret);
                    279: }
                    280:
                    281: void
                    282: zskbd_attach(parent, self, aux)
                    283:        struct device *parent, *self;
                    284:        void   *aux;
                    285:
                    286: {
                    287:        struct zsc_softc *zsc = (void *)parent;
                    288:        struct zskbd_softc *zst = (void *)self;
                    289:        struct sunkbd_softc *ss = (void *)self;
                    290:        struct cfdata *cf = self->dv_cfdata;
                    291:        struct zsc_attach_args *args = aux;
                    292:        struct wskbddev_attach_args a;
                    293:        struct zs_chanstate *cs;
                    294:        int channel, s, tty_unit, console = 0;
                    295:        dev_t dev;
                    296:
                    297:        ss->sc_sendcmd = zsenqueue_tx;
                    298:        timeout_set(&ss->sc_bellto, sunkbd_bellstop, zst);
                    299:
                    300:        timeout_set(&zst->zst_diag_ch, zskbd_diag, zst);
                    301:
                    302:        zst->zst_tbp = zst->zst_tba = zst->zst_tbeg = zst->zst_tbuf;
                    303:        zst->zst_tend = zst->zst_tbeg + ZSKBD_RING_SIZE;
                    304:
                    305:        tty_unit = ss->sc_dev.dv_unit;
                    306:        channel = args->channel;
                    307:        cs = &zsc->zsc_cs[channel];
                    308:        cs->cs_private = zst;
                    309:        cs->cs_ops = &zsops_kbd;
                    310:
                    311:        zst->zst_cs = cs;
                    312:        zst->zst_swflags = cf->cf_flags;        /* softcar, etc. */
                    313:        zst->zst_hwflags = args->hwflags;
                    314:        dev = makedev(zs_major, tty_unit);
                    315:
                    316:        if (zst->zst_swflags)
                    317:                printf(", flags 0x%x", zst->zst_swflags);
                    318:
                    319:        /*
                    320:         * Check whether we serve as a console device.
                    321:         * XXX - split console input/output channels aren't
                    322:         *       supported yet on /dev/console
                    323:         */
                    324:        if ((zst->zst_hwflags & ZS_HWFLAG_CONSOLE_INPUT) != 0) {
                    325:                if ((args->hwflags & ZS_HWFLAG_USE_CONSDEV) != 0) {
                    326:                        args->consdev->cn_dev = dev;
                    327:                        cn_tab->cn_pollc = wskbd_cnpollc;
                    328:                        cn_tab->cn_getc = wskbd_cngetc;
                    329:                }
                    330:                cn_tab->cn_dev = dev;
                    331:                console = 1;
                    332:        }
                    333:
                    334:        zst->zst_rbuf = malloc(zskbd_rbuf_size << 1, M_DEVBUF, M_WAITOK);
                    335:        zst->zst_ebuf = zst->zst_rbuf + (zskbd_rbuf_size << 1);
                    336:        /* Disable the high water mark. */
                    337:        zst->zst_r_hiwat = 0;
                    338:        zst->zst_r_lowat = 0;
                    339:        zst->zst_rbget = zst->zst_rbput = zst->zst_rbuf;
                    340:        zst->zst_rbavail = zskbd_rbuf_size;
                    341:
                    342:        /* if there are no enable/disable functions, assume the device
                    343:           is always enabled */
                    344:        if (!cs->enable)
                    345:                cs->enabled = 1;
                    346:
                    347:        /*
                    348:         * Hardware init
                    349:         */
                    350:        if (ISSET(zst->zst_hwflags, ZS_HWFLAG_CONSOLE)) {
                    351:                /* Call zsparam similar to open. */
                    352:
                    353:                /* Wait a while for previous console output to complete */
                    354:                DELAY(10000);
                    355:        } else if (!ISSET(zst->zst_hwflags, ZS_HWFLAG_NORESET)) {
                    356:                /* Not the console; may need reset. */
                    357:                int reset;
                    358:
                    359:                reset = (channel == 0) ? ZSWR9_A_RESET : ZSWR9_B_RESET;
                    360:                s = splzs();
                    361:                zs_write_reg(cs, 9, reset);
                    362:                splx(s);
                    363:        }
                    364:
                    365:        /*
                    366:         * Probe for a keyboard.
                    367:         * If one is found, turn on receiver and status interrupts.
                    368:         * We defer the actual write of the register to zsparam(),
                    369:         * but we must make sure status interrupts are turned on by
                    370:         * the time zsparam() reads the initial rr0 state.
                    371:         */
                    372:        if (zskbd_init(zst)) {
                    373:                SET(cs->cs_preg[1], ZSWR1_RIE | ZSWR1_SIE);
                    374:                zs_write_reg(cs, 1, cs->cs_creg[1]);
                    375:
                    376:                /* Make sure DTR is on now. */
                    377:                s = splzs();
                    378:                zs_modem(zst, 1);
                    379:                splx(s);
                    380:        } else {
                    381:                /* Will raise DTR in open. */
                    382:                s = splzs();
                    383:                zs_modem(zst, 0);
                    384:                splx(s);
                    385:
                    386:                return;
                    387:        }
                    388:
                    389:        ss->sc_click = 0;
                    390: #if defined(SUN4C) || defined(SUN4M)
                    391:        if (!CPU_ISSUN4) {
                    392:                char *cp = getpropstring(optionsnode, "keyboard-click?");
                    393:
                    394:                if (cp != NULL && strcmp(cp, "true") == 0)
                    395:                        ss->sc_click = 1;
                    396:        }
                    397: #endif
                    398:        sunkbd_setclick(ss, ss->sc_click);
                    399:
                    400:        a.console = console;
                    401:        if (ISTYPE5(ss->sc_layout)) {
                    402:                printf(": keyboard, type 5, layout 0x%x", ss->sc_layout);
                    403:                a.keymap = &sunkbd5_keymapdata;
                    404: #ifndef        SUNKBD5_LAYOUT
                    405:                if (ss->sc_layout < MAXSUNLAYOUT &&
                    406:                    sunkbd_layouts[ss->sc_layout] != -1)
                    407:                        sunkbd5_keymapdata.layout =
                    408:                            sunkbd_layouts[ss->sc_layout];
                    409: #endif
                    410:        } else {
                    411:                printf(": keyboard, type %d", ss->sc_id);
                    412:                if (ss->sc_id >= KB_SUN4)
                    413:                        printf(", layout 0x%x", ss->sc_layout);
                    414:                a.keymap = &sunkbd_keymapdata;
                    415: #ifndef        SUNKBD_LAYOUT
                    416:                if (ss->sc_layout < MAXSUNLAYOUT &&
                    417:                    sunkbd_layouts[ss->sc_layout] != -1)
                    418:                        sunkbd_keymapdata.layout =
                    419:                            sunkbd_layouts[ss->sc_layout];
                    420: #endif
                    421:        }
                    422:        a.accessops = &sunkbd_accessops;
                    423:        a.accesscookie = zst;
                    424:
                    425:        printf("\n");
                    426:
                    427:        if (console)
                    428:                wskbd_cnattach(&zskbd_consops, zst, a.keymap);
                    429:
                    430:        ss->sc_wskbddev = config_found(self, &a, wskbddevprint);
                    431: }
                    432:
                    433: int
                    434: zskbd_init(zst)
                    435:        struct zskbd_softc *zst;
                    436: {
                    437:        struct sunkbd_softc *ss = (void *)zst;
                    438:        struct zs_chanstate *cs = zst->zst_cs;
                    439:        int s, tries;
                    440:        u_int8_t v3, v4, v5, rr0;
                    441:
                    442:        /* setup for 1200n81 */
                    443:        if (zs_set_speed(cs, 1200)) {                   /* set 1200bps */
                    444:                printf(": failed to set baudrate\n");
                    445:                return 0;
                    446:        }
                    447:        if (zs_set_modes(cs, CS8 | CLOCAL)) {
                    448:                printf(": failed to set modes\n");
                    449:                return 0;
                    450:        }
                    451:
                    452:        s = splzs();
                    453:
                    454:        zs_maskintr(zst);
                    455:
                    456:        v3 = cs->cs_preg[3];                            /* set 8 bit chars */
                    457:        v5 = cs->cs_preg[5];
                    458:        CLR(v3, ZSWR3_RXSIZE);
                    459:        CLR(v5, ZSWR5_TXSIZE);
                    460:        SET(v3, ZSWR3_RX_8);
                    461:        SET(v5, ZSWR5_TX_8);
                    462:        cs->cs_preg[3] = v3;
                    463:        cs->cs_preg[5] = v5;
                    464:
                    465:        v4 = cs->cs_preg[4];                            /* no parity 1 stop */
                    466:        CLR(v4, ZSWR4_SBMASK | ZSWR4_PARMASK);
                    467:        SET(v4, ZSWR4_ONESB | ZSWR4_EVENP);
                    468:        cs->cs_preg[4] = v4;
                    469:
                    470:        if (!cs->cs_heldchange) {
                    471:                if (zst->zst_tx_busy) {
                    472:                        zst->zst_heldtbc = zst->zst_tbc;
                    473:                        zst->zst_tbc = 0;
                    474:                        cs->cs_heldchange = 1;
                    475:                } else
                    476:                        zs_loadchannelregs(cs);
                    477:        }
                    478:
                    479:        /*
                    480:         * Hardware flow control is disabled, turn off the buffer water
                    481:         * marks and unblock any soft flow control state.  Otherwise, enable
                    482:         * the water marks.
                    483:         */
                    484:        zst->zst_r_hiwat = 0;
                    485:        zst->zst_r_lowat = 0;
                    486:        if (ISSET(zst->zst_rx_flags, RX_TTY_OVERFLOWED)) {
                    487:                CLR(zst->zst_rx_flags, RX_TTY_OVERFLOWED);
                    488:                zst->zst_rx_ready = 1;
                    489:                cs->cs_softreq = 1;
                    490:        }
                    491:        if (ISSET(zst->zst_rx_flags, RX_TTY_BLOCKED|RX_IBUF_BLOCKED)) {
                    492:                CLR(zst->zst_rx_flags, RX_TTY_BLOCKED|RX_IBUF_BLOCKED);
                    493:                zs_hwiflow(zst);
                    494:        }
                    495:
                    496:        /*
                    497:         * Force a recheck of the hardware carrier and flow control status,
                    498:         * since we may have changed which bits we're looking at.
                    499:         */
                    500:        zskbd_stint(cs, 1);
                    501:
                    502:        splx(s);
                    503:
                    504:        /*
                    505:         * Hardware flow control is disabled, unblock any hard flow control
                    506:         * state.
                    507:         */
                    508:        if (zst->zst_tx_stopped) {
                    509:                zst->zst_tx_stopped = 0;
                    510:                zsstart_tx(zst);
                    511:        }
                    512:
                    513:        zskbd_softint(cs);
                    514:
                    515:        /* Ok, start the reset sequence... */
                    516:
                    517:        s = splhigh();
                    518:
                    519:        for (tries = 5; tries != 0; tries--) {
                    520:                int ltries;
                    521:
                    522:                ss->sc_leds = 0;
                    523:                ss->sc_layout = -1;
                    524:
                    525:                /* Send reset request */
                    526:                zskbd_putc(zst, SKBD_CMD_RESET);
                    527:
                    528:                ltries = 1000;
                    529:                while (--ltries > 0) {
                    530:                        rr0 = *cs->cs_reg_csr;
                    531:                        if (rr0 & ZSRR0_RX_READY) {
                    532:                                sunkbd_raw(ss, *cs->cs_reg_data);
                    533:                                if (ss->sc_kbdstate == SKBD_STATE_RESET)
                    534:                                        break;
                    535:                        }
                    536:                        DELAY(1000);
                    537:                }
                    538:                if (ltries == 0)
                    539:                        continue;
                    540:
                    541:                /* Wait for reset to finish. */
                    542:                ltries = 1000;
                    543:                while (--ltries > 0) {
                    544:                        rr0 = *cs->cs_reg_csr;
                    545:                        if (rr0 & ZSRR0_RX_READY) {
                    546:                                sunkbd_raw(ss, *cs->cs_reg_data);
                    547:                                if (ss->sc_kbdstate == SKBD_STATE_GETKEY)
                    548:                                        break;
                    549:                        }
                    550:                        DELAY(1000);
                    551:                }
                    552:                if (ltries == 0)
                    553:                        continue;
                    554:
                    555:
                    556:                /* Send layout request */
                    557:                if (ss->sc_id == KB_SUN4) {
                    558:                        zskbd_putc(zst, SKBD_CMD_LAYOUT);
                    559:
                    560:                        ltries = 1000;
                    561:                        while (--ltries > 0) {
                    562:                                rr0 = *cs->cs_reg_csr;
                    563:                                if (rr0 & ZSRR0_RX_READY) {
                    564:                                        sunkbd_raw(ss, *cs->cs_reg_data);
                    565:                                        if (ss->sc_layout != -1)
                    566:                                                break;
                    567:                                }
                    568:                                DELAY(1000);
                    569:                        }
                    570:                        if (ltries == 0)
                    571:                                continue;
                    572:                        break;
                    573:                } else {
                    574:                        ss->sc_layout = 0;
                    575:                        break;
                    576:                }
                    577:        }
                    578:        if (tries == 0)
                    579:                printf(": no keyboard\n");
                    580:        splx(s);
                    581:
                    582:        return tries;
                    583: }
                    584:
                    585: void
                    586: zskbd_putc(zst, c)
                    587:        struct zskbd_softc *zst;
                    588:        u_int8_t c;
                    589: {
                    590:        u_int8_t rr0;
                    591:        int s;
                    592:
                    593:        s = splhigh();
                    594:        do {
                    595:                rr0 = *zst->zst_cs->cs_reg_csr;
                    596:        } while ((rr0 & ZSRR0_TX_READY) == 0);
                    597:        *zst->zst_cs->cs_reg_data = c;
                    598:        delay(2);
                    599:        splx(s);
                    600: }
                    601:
                    602: int
                    603: zsenqueue_tx(v, str, len)
                    604:        void *v;
                    605:        u_int8_t *str;
                    606:        u_int len;
                    607: {
                    608:        struct zskbd_softc *zst = v;
                    609:        int s;
                    610:        u_int i;
                    611:
                    612:        s = splzs();
                    613:        if (zst->zst_tbc + len > ZSKBD_RING_SIZE)
                    614:                return (-1);
                    615:        zst->zst_tbc += len;
                    616:        for (i = 0; i < len; i++) {
                    617:                *zst->zst_tbp = str[i];
                    618:                if (++zst->zst_tbp == zst->zst_tend)
                    619:                        zst->zst_tbp = zst->zst_tbeg;
                    620:        }
                    621:        splx(s);
                    622:        zsstart_tx(zst);
                    623:        return (0);
                    624: }
                    625:
                    626: void
                    627: zsstart_tx(zst)
                    628:        struct zskbd_softc *zst;
                    629: {
                    630:        struct zs_chanstate *cs = zst->zst_cs;
                    631:        int s, s1;
                    632:
                    633:        s = spltty();
                    634:
                    635:        if (zst->zst_tx_stopped)
                    636:                goto out;
                    637:        if (zst->zst_tbc == 0)
                    638:                goto out;
                    639:
                    640:        s1 = splzs();
                    641:
                    642:        zst->zst_tx_busy = 1;
                    643:
                    644:        if (!ISSET(cs->cs_preg[1], ZSWR1_TIE)) {
                    645:                SET(cs->cs_preg[1], ZSWR1_TIE);
                    646:                cs->cs_creg[1] = cs->cs_preg[1];
                    647:                zs_write_reg(cs, 1, cs->cs_creg[1]);
                    648:        }
                    649:
                    650:        zs_write_data(cs, *zst->zst_tba);
                    651:
                    652:        zst->zst_tbc--;
                    653:        if (++zst->zst_tba == zst->zst_tend)
                    654:                zst->zst_tba = zst->zst_tbeg;
                    655:
                    656:        splx(s1);
                    657:
                    658: out:
                    659:        splx(s);
                    660: }
                    661:
                    662: /*
                    663:  * Compute interrupt enable bits and set in the pending bits. Called both
                    664:  * in zsparam() and when PPS (pulse per second timing) state changes.
                    665:  * Must be called at splzs().
                    666:  */
                    667: static void
                    668: zs_maskintr(zst)
                    669:        struct zskbd_softc *zst;
                    670: {
                    671:        struct zs_chanstate *cs = zst->zst_cs;
                    672:        int tmp15;
                    673:
                    674:        cs->cs_rr0_mask = cs->cs_rr0_cts | cs->cs_rr0_dcd;
                    675:        if (zst->zst_ppsmask != 0)
                    676:                cs->cs_rr0_mask |= cs->cs_rr0_pps;
                    677:        tmp15 = cs->cs_preg[15];
                    678:        if (ISSET(cs->cs_rr0_mask, ZSRR0_DCD))
                    679:                SET(tmp15, ZSWR15_DCD_IE);
                    680:        else
                    681:                CLR(tmp15, ZSWR15_DCD_IE);
                    682:        if (ISSET(cs->cs_rr0_mask, ZSRR0_CTS))
                    683:                SET(tmp15, ZSWR15_CTS_IE);
                    684:        else
                    685:                CLR(tmp15, ZSWR15_CTS_IE);
                    686:        cs->cs_preg[15] = tmp15;
                    687: }
                    688:
                    689:
                    690: /*
                    691:  * Raise or lower modem control (DTR/RTS) signals.  If a character is
                    692:  * in transmission, the change is deferred.
                    693:  */
                    694: static void
                    695: zs_modem(zst, onoff)
                    696:        struct zskbd_softc *zst;
                    697:        int onoff;
                    698: {
                    699:        struct zs_chanstate *cs = zst->zst_cs;
                    700:
                    701:        if (cs->cs_wr5_dtr == 0)
                    702:                return;
                    703:
                    704:        if (onoff)
                    705:                SET(cs->cs_preg[5], cs->cs_wr5_dtr);
                    706:        else
                    707:                CLR(cs->cs_preg[5], cs->cs_wr5_dtr);
                    708:
                    709:        if (!cs->cs_heldchange) {
                    710:                if (zst->zst_tx_busy) {
                    711:                        zst->zst_heldtbc = zst->zst_tbc;
                    712:                        zst->zst_tbc = 0;
                    713:                        cs->cs_heldchange = 1;
                    714:                } else
                    715:                        zs_loadchannelregs(cs);
                    716:        }
                    717: }
                    718:
                    719: /*
                    720:  * Internal version of zshwiflow
                    721:  * called at splzs
                    722:  */
                    723: static void
                    724: zs_hwiflow(zst)
                    725:        struct zskbd_softc *zst;
                    726: {
                    727:        struct zs_chanstate *cs = zst->zst_cs;
                    728:
                    729:        if (cs->cs_wr5_rts == 0)
                    730:                return;
                    731:
                    732:        if (ISSET(zst->zst_rx_flags, RX_ANY_BLOCK)) {
                    733:                CLR(cs->cs_preg[5], cs->cs_wr5_rts);
                    734:                CLR(cs->cs_creg[5], cs->cs_wr5_rts);
                    735:        } else {
                    736:                SET(cs->cs_preg[5], cs->cs_wr5_rts);
                    737:                SET(cs->cs_creg[5], cs->cs_wr5_rts);
                    738:        }
                    739:        zs_write_reg(cs, 5, cs->cs_creg[5]);
                    740: }
                    741:
                    742:
                    743: /****************************************************************
                    744:  * Interface to the lower layer (zscc)
                    745:  ****************************************************************/
                    746:
                    747: #define        integrate
                    748: integrate void zskbd_rxsoft(struct zskbd_softc *);
                    749: integrate void zskbd_txsoft(struct zskbd_softc *);
                    750: integrate void zskbd_stsoft(struct zskbd_softc *);
                    751: /*
                    752:  * receiver ready interrupt.
                    753:  * called at splzs
                    754:  */
                    755: static void
                    756: zskbd_rxint(cs)
                    757:        struct zs_chanstate *cs;
                    758: {
                    759:        struct zskbd_softc *zst = cs->cs_private;
                    760:        u_char *put, *end;
                    761:        u_int cc;
                    762:        u_char rr0, rr1, c;
                    763:
                    764:        end = zst->zst_ebuf;
                    765:        put = zst->zst_rbput;
                    766:        cc = zst->zst_rbavail;
                    767:
                    768:        while (cc > 0) {
                    769:                /*
                    770:                 * First read the status, because reading the received char
                    771:                 * destroys the status of this char.
                    772:                 */
                    773:                rr1 = zs_read_reg(cs, 1);
                    774:                c = zs_read_data(cs);
                    775:
                    776:                if (ISSET(rr1, ZSRR1_FE | ZSRR1_DO | ZSRR1_PE)) {
                    777:                        /* Clear the receive error. */
                    778:                        zs_write_csr(cs, ZSWR0_RESET_ERRORS);
                    779:                }
                    780:
                    781:                put[0] = c;
                    782:                put[1] = rr1;
                    783:                put += 2;
                    784:                if (put >= end)
                    785:                        put = zst->zst_rbuf;
                    786:                cc--;
                    787:
                    788:                rr0 = zs_read_csr(cs);
                    789:                if (!ISSET(rr0, ZSRR0_RX_READY))
                    790:                        break;
                    791:        }
                    792:
                    793:        /*
                    794:         * Current string of incoming characters ended because
                    795:         * no more data was available or we ran out of space.
                    796:         * Schedule a receive event if any data was received.
                    797:         * If we're out of space, turn off receive interrupts.
                    798:         */
                    799:        zst->zst_rbput = put;
                    800:        zst->zst_rbavail = cc;
                    801:        if (!ISSET(zst->zst_rx_flags, RX_TTY_OVERFLOWED)) {
                    802:                zst->zst_rx_ready = 1;
                    803:                cs->cs_softreq = 1;
                    804:        }
                    805:
                    806:        /*
                    807:         * See if we are in danger of overflowing a buffer. If
                    808:         * so, use hardware flow control to ease the pressure.
                    809:         */
                    810:        if (!ISSET(zst->zst_rx_flags, RX_IBUF_BLOCKED) &&
                    811:            cc < zst->zst_r_hiwat) {
                    812:                SET(zst->zst_rx_flags, RX_IBUF_BLOCKED);
                    813:                zs_hwiflow(zst);
                    814:        }
                    815:
                    816:        /*
                    817:         * If we're out of space, disable receive interrupts
                    818:         * until the queue has drained a bit.
                    819:         */
                    820:        if (!cc) {
                    821:                SET(zst->zst_rx_flags, RX_IBUF_OVERFLOWED);
                    822:                CLR(cs->cs_preg[1], ZSWR1_RIE);
                    823:                cs->cs_creg[1] = cs->cs_preg[1];
                    824:                zs_write_reg(cs, 1, cs->cs_creg[1]);
                    825:        }
                    826: }
                    827:
                    828: /*
                    829:  * transmitter ready interrupt.  (splzs)
                    830:  */
                    831: static void
                    832: zskbd_txint(cs)
                    833:        struct zs_chanstate *cs;
                    834: {
                    835:        struct zskbd_softc *zst = cs->cs_private;
                    836:
                    837:        /*
                    838:         * If we've delayed a parameter change, do it now, and restart
                    839:         * output.
                    840:         */
                    841:        if (cs->cs_heldchange) {
                    842:                zs_loadchannelregs(cs);
                    843:                cs->cs_heldchange = 0;
                    844:                zst->zst_tbc = zst->zst_heldtbc;
                    845:                zst->zst_heldtbc = 0;
                    846:        }
                    847:
                    848:        /* Output the next character in the buffer, if any. */
                    849:        if (zst->zst_tbc > 0) {
                    850:                zs_write_data(cs, *zst->zst_tba);
                    851:                zst->zst_tbc--;
                    852:                if (++zst->zst_tba == zst->zst_tend)
                    853:                        zst->zst_tba = zst->zst_tbeg;
                    854:        } else {
                    855:                /* Disable transmit completion interrupts if necessary. */
                    856:                if (ISSET(cs->cs_preg[1], ZSWR1_TIE)) {
                    857:                        CLR(cs->cs_preg[1], ZSWR1_TIE);
                    858:                        cs->cs_creg[1] = cs->cs_preg[1];
                    859:                        zs_write_reg(cs, 1, cs->cs_creg[1]);
                    860:                }
                    861:                if (zst->zst_tx_busy) {
                    862:                        zst->zst_tx_busy = 0;
                    863:                        zst->zst_tx_done = 1;
                    864:                        cs->cs_softreq = 1;
                    865:                }
                    866:        }
                    867: }
                    868:
                    869: /*
                    870:  * status change interrupt.  (splzs)
                    871:  */
                    872: static void
                    873: zskbd_stint(cs, force)
                    874:        struct zs_chanstate *cs;
                    875:        int force;
                    876: {
                    877:        struct zskbd_softc *zst = cs->cs_private;
                    878:        u_char rr0, delta;
                    879:
                    880:        rr0 = zs_read_csr(cs);
                    881:        zs_write_csr(cs, ZSWR0_RESET_STATUS);
                    882:
                    883:        /*
                    884:         * Check here for console break, so that we can abort
                    885:         * even when interrupts are locking up the machine.
                    886:         */
                    887:        if (!force)
                    888:                delta = rr0 ^ cs->cs_rr0;
                    889:        else
                    890:                delta = cs->cs_rr0_mask;
                    891:        cs->cs_rr0 = rr0;
                    892:
                    893:        if (ISSET(delta, cs->cs_rr0_mask)) {
                    894:                SET(cs->cs_rr0_delta, delta);
                    895:
                    896:                /*
                    897:                 * Stop output immediately if we lose the output
                    898:                 * flow control signal or carrier detect.
                    899:                 */
                    900:                if (ISSET(~rr0, cs->cs_rr0_mask)) {
                    901:                        zst->zst_tbc = 0;
                    902:                        zst->zst_heldtbc = 0;
                    903:                }
                    904:
                    905:                zst->zst_st_check = 1;
                    906:                cs->cs_softreq = 1;
                    907:        }
                    908: }
                    909:
                    910: void
                    911: zskbd_diag(arg)
                    912:        void *arg;
                    913: {
                    914:        struct zskbd_softc *zst = arg;
                    915:        struct sunkbd_softc *ss = arg;
                    916:        int overflows, floods;
                    917:        int s;
                    918:
                    919:        s = splzs();
                    920:        overflows = zst->zst_overflows;
                    921:        zst->zst_overflows = 0;
                    922:        floods = zst->zst_floods;
                    923:        zst->zst_floods = 0;
                    924:        zst->zst_errors = 0;
                    925:        splx(s);
                    926:
                    927:        log(LOG_WARNING, "%s: %d silo overflow%s, %d ibuf flood%s\n",
                    928:            ss->sc_dev.dv_xname,
                    929:            overflows, overflows == 1 ? "" : "s",
                    930:            floods, floods == 1 ? "" : "s");
                    931: }
                    932:
                    933: integrate void
                    934: zskbd_rxsoft(zst)
                    935:        struct zskbd_softc *zst;
                    936: {
                    937:        struct sunkbd_softc *ss = (void *)zst;
                    938:        struct zs_chanstate *cs = zst->zst_cs;
                    939:        u_char *get, *end;
                    940:        u_int cc, scc, type;
                    941:        u_char rr1;
                    942:        int code, value;
                    943:        int s;
                    944:
                    945:        end = zst->zst_ebuf;
                    946:        get = zst->zst_rbget;
                    947:        scc = cc = zskbd_rbuf_size - zst->zst_rbavail;
                    948:
                    949:        if (cc == zskbd_rbuf_size) {
                    950:                zst->zst_floods++;
                    951:                if (zst->zst_errors++ == 0)
                    952:                        timeout_add(&zst->zst_diag_ch, 60 * hz);
                    953:        }
                    954:
                    955:        while (cc) {
                    956:                code = get[0];
                    957:                rr1 = get[1];
                    958:                if (ISSET(rr1, ZSRR1_DO | ZSRR1_FE | ZSRR1_PE)) {
                    959:                        if (ISSET(rr1, ZSRR1_DO)) {
                    960:                                zst->zst_overflows++;
                    961:                                if (zst->zst_errors++ == 0)
                    962:                                        timeout_add(&zst->zst_diag_ch, 60 * hz);
                    963:                        }
                    964:                        if (ISSET(rr1, ZSRR1_FE))
                    965:                                SET(code, TTY_FE);
                    966:                        if (ISSET(rr1, ZSRR1_PE))
                    967:                                SET(code, TTY_PE);
                    968:                }
                    969:
                    970:                sunkbd_decode(code, &type, &value);
                    971:                wskbd_input(ss->sc_wskbddev, type, value);
                    972:
                    973:                get += 2;
                    974:                if (get >= end)
                    975:                        get = zst->zst_rbuf;
                    976:                cc--;
                    977:        }
                    978:
                    979:        if (cc != scc) {
                    980:                zst->zst_rbget = get;
                    981:                s = splzs();
                    982:                cc = zst->zst_rbavail += scc - cc;
                    983:                /* Buffers should be ok again, release possible block. */
                    984:                if (cc >= zst->zst_r_lowat) {
                    985:                        if (ISSET(zst->zst_rx_flags, RX_IBUF_OVERFLOWED)) {
                    986:                                CLR(zst->zst_rx_flags, RX_IBUF_OVERFLOWED);
                    987:                                SET(cs->cs_preg[1], ZSWR1_RIE);
                    988:                                cs->cs_creg[1] = cs->cs_preg[1];
                    989:                                zs_write_reg(cs, 1, cs->cs_creg[1]);
                    990:                        }
                    991:                        if (ISSET(zst->zst_rx_flags, RX_IBUF_BLOCKED)) {
                    992:                                CLR(zst->zst_rx_flags, RX_IBUF_BLOCKED);
                    993:                                zs_hwiflow(zst);
                    994:                        }
                    995:                }
                    996:                splx(s);
                    997:        }
                    998: }
                    999:
                   1000: integrate void
                   1001: zskbd_txsoft(zst)
                   1002:        struct zskbd_softc *zst;
                   1003: {
                   1004: }
                   1005:
                   1006: integrate void
                   1007: zskbd_stsoft(zst)
                   1008:        struct zskbd_softc *zst;
                   1009: {
                   1010:        struct zs_chanstate *cs = zst->zst_cs;
                   1011:        u_char rr0, delta;
                   1012:        int s;
                   1013:
                   1014:        s = splzs();
                   1015:        rr0 = cs->cs_rr0;
                   1016:        delta = cs->cs_rr0_delta;
                   1017:        cs->cs_rr0_delta = 0;
                   1018:        splx(s);
                   1019:
                   1020:        if (ISSET(delta, cs->cs_rr0_cts)) {
                   1021:                /* Block or unblock output according to flow control. */
                   1022:                if (ISSET(rr0, cs->cs_rr0_cts))
                   1023:                        zst->zst_tx_stopped = 0;
                   1024:                else
                   1025:                        zst->zst_tx_stopped = 1;
                   1026:        }
                   1027: }
                   1028:
                   1029: /*
                   1030:  * Software interrupt.  Called at zssoft
                   1031:  *
                   1032:  * The main job to be done here is to empty the input ring
                   1033:  * by passing its contents up to the tty layer.  The ring is
                   1034:  * always emptied during this operation, therefore the ring
                   1035:  * must not be larger than the space after "high water" in
                   1036:  * the tty layer, or the tty layer might drop our input.
                   1037:  *
                   1038:  * Note: an "input blockage" condition is assumed to exist if
                   1039:  * EITHER the TS_TBLOCK flag or zst_rx_blocked flag is set.
                   1040:  */
                   1041: static void
                   1042: zskbd_softint(cs)
                   1043:        struct zs_chanstate *cs;
                   1044: {
                   1045:        struct zskbd_softc *zst = cs->cs_private;
                   1046:        int s;
                   1047:
                   1048:        s = spltty();
                   1049:
                   1050:        if (zst->zst_rx_ready) {
                   1051:                zst->zst_rx_ready = 0;
                   1052:                zskbd_rxsoft(zst);
                   1053:        }
                   1054:
                   1055:        if (zst->zst_st_check) {
                   1056:                zst->zst_st_check = 0;
                   1057:                zskbd_stsoft(zst);
                   1058:        }
                   1059:
                   1060:        if (zst->zst_tx_done) {
                   1061:                zst->zst_tx_done = 0;
                   1062:                zskbd_txsoft(zst);
                   1063:        }
                   1064:
                   1065:        splx(s);
                   1066: }
                   1067:
                   1068: struct zsops zsops_kbd = {
                   1069:        zskbd_rxint,    /* receive char available */
                   1070:        zskbd_stint,    /* external/status */
                   1071:        zskbd_txint,    /* xmit buffer empty */
                   1072:        zskbd_softint,  /* process software interrupt */
                   1073: };
                   1074:
                   1075: void
                   1076: zskbd_cnpollc(v, on)
                   1077:        void *v;
                   1078:        int on;
                   1079: {
                   1080:        extern int swallow_zsintrs;
                   1081:
                   1082:        if (on)
                   1083:                swallow_zsintrs++;
                   1084:        else
                   1085:                swallow_zsintrs--;
                   1086: }
                   1087:
                   1088: void
                   1089: zskbd_cngetc(v, type, data)
                   1090:        void *v;
                   1091:        u_int *type;
                   1092:        int *data;
                   1093: {
                   1094:        struct zskbd_softc *zst = v;
                   1095:        int s;
                   1096:        u_int8_t c, rr0;
                   1097:
                   1098:        s = splhigh();
                   1099:        do {
                   1100:                rr0 = *zst->zst_cs->cs_reg_csr;
                   1101:        } while ((rr0 & ZSRR0_RX_READY) == 0);
                   1102:
                   1103:        c = *zst->zst_cs->cs_reg_data;
                   1104:        splx(s);
                   1105:
                   1106:        switch (c) {
                   1107:        case SKBD_RSP_IDLE:
                   1108:                *type = WSCONS_EVENT_ALL_KEYS_UP;
                   1109:                *data = 0;
                   1110:                break;
                   1111:        default:
                   1112:                *type = (c & 0x80) ?
                   1113:                    WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN;
                   1114:                *data = c & 0x7f;
                   1115:                break;
                   1116:        }
                   1117: }

CVSweb