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

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

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

CVSweb