[BACK]Return to zs.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / arch / macppc / dev

Annotation of src/sys/arch/macppc/dev/zs.c, Revision 1.45.14.1

1.45.14.1! mjf         1: /*     $NetBSD$        */
1.1       tsubai      2:
                      3: /*
1.7       wrstuden    4:  * Copyright (c) 1996, 1998 Bill Studenmund
1.1       tsubai      5:  * Copyright (c) 1995 Gordon W. Ross
                      6:  * 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. The name of the author may not be used to endorse or promote products
                     17:  *    derived from this software without specific prior written permission.
                     18:  * 4. All advertising materials mentioning features or use of this software
                     19:  *    must display the following acknowledgement:
                     20:  *      This product includes software developed by Gordon Ross
                     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:  * Zilog Z8530 Dual UART driver (machine-dependent part)
                     36:  *
                     37:  * Runs two serial lines per chip using slave drivers.
                     38:  * Plain tty/async lines use the zs_async slave.
                     39:  * Sun keyboard/mouse uses the zs_kbd/zs_ms slaves.
                     40:  * Other ports use their own mice & keyboard slaves.
                     41:  *
                     42:  * Credits & history:
                     43:  *
                     44:  * With NetBSD 1.1, port-mac68k started using a port of the port-sparc
                     45:  * (port-sun3?) zs.c driver (which was in turn based on code in the
                     46:  * Berkeley 4.4 Lite release). Bill Studenmund did the port, with
1.28      keihan     47:  * help from Allen Briggs and Gordon Ross <gwr@NetBSD.org>. Noud de
1.1       tsubai     48:  * Brouwer field-tested the driver at a local ISP.
                     49:  *
1.41      wiz        50:  * Bill Studenmund and Gordon Ross then ported the machine-independent
1.1       tsubai     51:  * z8530 driver to work with port-mac68k. NetBSD 1.2 contained an
                     52:  * intermediate version (mac68k using a local, patched version of
                     53:  * the m.i. drivers), with NetBSD 1.3 containing a full version.
                     54:  */
1.27      lukem      55:
                     56: #include <sys/cdefs.h>
1.45.14.1! mjf        57: __KERNEL_RCSID(0, "$NetBSD$");
1.3       jonathan   58:
                     59: #include "opt_ddb.h"
1.19      dbj        60: #include "opt_kgdb.h"
1.1       tsubai     61:
                     62: #include <sys/param.h>
                     63: #include <sys/systm.h>
                     64: #include <sys/proc.h>
                     65: #include <sys/device.h>
                     66: #include <sys/conf.h>
                     67: #include <sys/file.h>
                     68: #include <sys/ioctl.h>
                     69: #include <sys/tty.h>
                     70: #include <sys/time.h>
                     71: #include <sys/kernel.h>
                     72: #include <sys/syslog.h>
1.45      ad         73: #include <sys/intr.h>
                     74: #include <sys/cpu.h>
1.19      dbj        75: #ifdef KGDB
                     76: #include <sys/kgdb.h>
                     77: #endif
1.1       tsubai     78:
                     79: #include <dev/cons.h>
                     80: #include <dev/ofw/openfirm.h>
                     81: #include <dev/ic/z8530reg.h>
                     82:
                     83: #include <machine/z8530var.h>
                     84: #include <machine/autoconf.h>
                     85: #include <machine/pio.h>
                     86:
                     87: /* Are these in a header file anywhere? */
                     88: /* Booter flags interface */
                     89: #define ZSMAC_RAW      0x01
                     90: #define ZSMAC_LOCALTALK        0x02
1.11      mycroft    91:
1.1       tsubai     92: /*
                     93:  * Some warts needed by z8530tty.c -
                     94:  */
                     95: int zs_def_cflag = (CREAD | CS8 | HUPCL);
                     96:
                     97: /*
                     98:  * abort detection on console will now timeout after iterating on a loop
                     99:  * the following # of times. Cheep hack. Also, abort detection is turned
                    100:  * off after a timeout (i.e. maybe there's not a terminal hooked up).
                    101:  */
                    102: #define ZSABORT_DELAY 3000000
                    103:
                    104: struct zsdevice {
                    105:        /* Yes, they are backwards. */
                    106:        struct  zschan zs_chan_b;
                    107:        struct  zschan zs_chan_a;
                    108: };
                    109:
1.31      chs       110: static int zs_defspeed[2] = {
                    111:        38400,          /* ttyZ0 */
                    112:        38400,          /* ttyZ1 */
1.1       tsubai    113: };
1.15      tsubai    114:
1.1       tsubai    115: /* console stuff */
                    116: void   *zs_conschan = 0;
1.32      matt      117: int    zs_conschannel = -1;
1.1       tsubai    118: #ifdef ZS_CONSOLE_ABORT
                    119: int    zs_cons_canabort = 1;
                    120: #else
                    121: int    zs_cons_canabort = 0;
                    122: #endif /* ZS_CONSOLE_ABORT*/
                    123:
                    124: /* device to which the console is attached--if serial. */
                    125: /* Mac stuff */
                    126:
1.30      chs       127: static int zs_get_speed(struct zs_chanstate *);
1.1       tsubai    128:
                    129: /*
                    130:  * Even though zsparam will set up the clock multiples, etc., we
                    131:  * still set them here as: 1) mice & keyboards don't use zsparam,
                    132:  * and 2) the console stuff uses these defaults before device
                    133:  * attach.
                    134:  */
                    135:
1.45.14.1! mjf       136: static uint8_t zs_init_reg[16] = {
1.1       tsubai    137:        0,      /* 0: CMD (reset, etc.) */
                    138:        0,      /* 1: No interrupts yet. */
                    139:        0,      /* IVECT */
                    140:        ZSWR3_RX_8 | ZSWR3_RX_ENABLE,
                    141:        ZSWR4_CLK_X16 | ZSWR4_ONESB | ZSWR4_EVENP,
                    142:        ZSWR5_TX_8 | ZSWR5_TX_ENABLE,
                    143:        0,      /* 6: TXSYNC/SYNCLO */
                    144:        0,      /* 7: RXSYNC/SYNCHI */
                    145:        0,      /* 8: alias for data port */
                    146:        ZSWR9_MASTER_IE,
                    147:        0,      /*10: Misc. TX/RX control bits */
                    148:        ZSWR11_TXCLK_BAUD | ZSWR11_RXCLK_BAUD,
1.11      mycroft   149:        ((PCLK/32)/38400)-2,    /*12: BAUDLO (default=38400) */
                    150:        0,                      /*13: BAUDHI (default=38400) */
1.12      wrstuden  151:        ZSWR14_BAUD_ENA,
1.10      mycroft   152:        ZSWR15_BREAK_IE,
1.1       tsubai    153: };
                    154:
                    155: /****************************************************************
                    156:  * Autoconfig
                    157:  ****************************************************************/
                    158:
                    159: /* Definition of the driver for autoconfig. */
1.45.14.1! mjf       160: static int     zsc_match(device_t, cfdata_t, void *);
        !           161: static void    zsc_attach(device_t, device_t, void *);
1.30      chs       162: static int     zsc_print(void *, const char *);
1.1       tsubai    163:
1.45.14.1! mjf       164: CFATTACH_DECL_NEW(zsc, sizeof(struct zsc_softc),
1.23      thorpej   165:     zsc_match, zsc_attach, NULL, NULL);
1.1       tsubai    166:
                    167: extern struct cfdriver zsc_cd;
                    168:
1.31      chs       169: int zsc_attached;
                    170:
1.30      chs       171: int zshard(void *);
1.1       tsubai    172: #ifdef ZS_TXDMA
1.30      chs       173: static int zs_txdma_int(void *);
1.1       tsubai    174: #endif
                    175:
1.30      chs       176: void zscnprobe(struct consdev *);
                    177: void zscninit(struct consdev *);
                    178: int  zscngetc(dev_t);
                    179: void zscnputc(dev_t, int);
                    180: void zscnpollc(dev_t, int);
1.1       tsubai    181:
                    182: /*
                    183:  * Is the zs chip present?
                    184:  */
                    185: static int
1.45.14.1! mjf       186: zsc_match(device_t parent, cfdata_t cf, void *aux)
1.1       tsubai    187: {
                    188:        struct confargs *ca = aux;
                    189:
                    190:        if (strcmp(ca->ca_name, "escc") != 0)
                    191:                return 0;
                    192:
1.31      chs       193:        if (zsc_attached)
1.1       tsubai    194:                return 0;
                    195:
                    196:        return 1;
                    197: }
                    198:
                    199: /*
                    200:  * Attach a found zs.
                    201:  *
                    202:  * Match slave number to zs unit number, so that misconfiguration will
                    203:  * not set up the keyboard as ttya, etc.
                    204:  */
                    205: static void
1.45.14.1! mjf       206: zsc_attach(device_t parent, device_t self, void *aux)
1.1       tsubai    207: {
1.45.14.1! mjf       208:        struct zsc_softc *zsc = device_private(self);
1.1       tsubai    209:        struct confargs *ca = aux;
                    210:        struct zsc_attach_args zsc_args;
                    211:        volatile struct zschan *zc;
                    212:        struct xzs_chanstate *xcs;
                    213:        struct zs_chanstate *cs;
1.15      tsubai    214:        struct zsdevice *zsd;
1.31      chs       215:        int channel;
1.1       tsubai    216:        int s, chip, theflags;
                    217:        int node, intr[2][3];
                    218:        u_int regs[6];
                    219:
1.31      chs       220:        zsc_attached = 1;
                    221:
1.45.14.1! mjf       222:        zsc->zsc_dev = self;
        !           223:
1.15      tsubai    224:        chip = 0;
1.8       tsubai    225:        ca->ca_reg[0] += ca->ca_baseaddr;
1.15      tsubai    226:        zsd = mapiodev(ca->ca_reg[0], ca->ca_reg[1]);
1.8       tsubai    227:
                    228:        node = OF_child(ca->ca_node);   /* ch-a */
1.1       tsubai    229:
                    230:        for (channel = 0; channel < 2; channel++) {
1.8       tsubai    231:                if (OF_getprop(node, "AAPL,interrupts",
1.9       tsubai    232:                               intr[channel], sizeof(intr[0])) == -1 &&
1.8       tsubai    233:                    OF_getprop(node, "interrupts",
1.9       tsubai    234:                               intr[channel], sizeof(intr[0])) == -1) {
1.45.14.1! mjf       235:                        aprint_error(": cannot find interrupt property\n");
1.8       tsubai    236:                        return;
                    237:                }
                    238:
                    239:                if (OF_getprop(node, "reg", regs, sizeof(regs)) < 24) {
1.45.14.1! mjf       240:                        aprint_error(": cannot find reg property\n");
1.8       tsubai    241:                        return;
                    242:                }
1.1       tsubai    243:                regs[2] += ca->ca_baseaddr;
                    244:                regs[4] += ca->ca_baseaddr;
                    245: #ifdef ZS_TXDMA
                    246:                zsc->zsc_txdmareg[channel] = mapiodev(regs[2], regs[3]);
                    247:                zsc->zsc_txdmacmd[channel] =
                    248:                        dbdma_alloc(sizeof(dbdma_command_t) * 3);
1.18      wiz       249:                memset(zsc->zsc_txdmacmd[channel], 0,
                    250:                        sizeof(dbdma_command_t) * 3);
1.1       tsubai    251:                dbdma_reset(zsc->zsc_txdmareg[channel]);
                    252: #endif
                    253:                node = OF_peer(node);   /* ch-b */
                    254:        }
                    255:
1.45.14.1! mjf       256:        aprint_normal(": irq %d,%d\n", intr[0][0], intr[1][0]);
1.1       tsubai    257:
                    258:        /*
                    259:         * Initialize software state for each channel.
                    260:         */
                    261:        for (channel = 0; channel < 2; channel++) {
                    262:                zsc_args.channel = channel;
1.31      chs       263:                zsc_args.hwflags = (channel == zs_conschannel ?
                    264:                                    ZS_HWFLAG_CONSOLE : 0);
1.1       tsubai    265:                xcs = &zsc->xzsc_xcs_store[channel];
                    266:                cs  = &xcs->xzs_cs;
                    267:                zsc->zsc_cs[channel] = cs;
                    268:
1.44      ad        269:                zs_lock_init(cs);
1.1       tsubai    270:                cs->cs_channel = channel;
                    271:                cs->cs_private = NULL;
                    272:                cs->cs_ops = &zsops_null;
                    273:
1.15      tsubai    274:                zc = (channel == 0) ? &zsd->zs_chan_a : &zsd->zs_chan_b;
                    275:
1.1       tsubai    276:                cs->cs_reg_csr  = &zc->zc_csr;
                    277:                cs->cs_reg_data = &zc->zc_data;
                    278:
1.18      wiz       279:                memcpy(cs->cs_creg, zs_init_reg, 16);
                    280:                memcpy(cs->cs_preg, zs_init_reg, 16);
1.1       tsubai    281:
                    282:                /* Current BAUD rate generator clock. */
1.11      mycroft   283:                cs->cs_brg_clk = PCLK / 16;     /* RTxC is 230400*16, so use 230400 */
1.13      tsubai    284:                if (zsc_args.hwflags & ZS_HWFLAG_CONSOLE)
                    285:                        cs->cs_defspeed = zs_get_speed(cs);
                    286:                else
1.31      chs       287:                        cs->cs_defspeed = zs_defspeed[channel];
1.1       tsubai    288:                cs->cs_defcflag = zs_def_cflag;
                    289:
                    290:                /* Make these correspond to cs_defcflag (-crtscts) */
                    291:                cs->cs_rr0_dcd = ZSRR0_DCD;
                    292:                cs->cs_rr0_cts = 0;
                    293:                cs->cs_wr5_dtr = ZSWR5_DTR;
                    294:                cs->cs_wr5_rts = 0;
                    295:
                    296: #ifdef __notyet__
                    297:                cs->cs_slave_type = ZS_SLAVE_NONE;
                    298: #endif
                    299:
                    300:                /* Define BAUD rate stuff. */
1.11      mycroft   301:                xcs->cs_clocks[0].clk = PCLK;
1.7       wrstuden  302:                xcs->cs_clocks[0].flags = ZSC_RTXBRG | ZSC_RTXDIV;
1.1       tsubai    303:                xcs->cs_clocks[1].flags =
                    304:                        ZSC_RTXBRG | ZSC_RTXDIV | ZSC_VARIABLE | ZSC_EXTERN;
                    305:                xcs->cs_clocks[2].flags = ZSC_TRXDIV | ZSC_VARIABLE;
                    306:                xcs->cs_clock_count = 3;
                    307:                if (channel == 0) {
                    308:                        theflags = 0; /*mac68k_machine.modem_flags;*/
1.6       tsubai    309:                        /*xcs->cs_clocks[1].clk = mac68k_machine.modem_dcd_clk;*/
                    310:                        /*xcs->cs_clocks[2].clk = mac68k_machine.modem_cts_clk;*/
                    311:                        xcs->cs_clocks[1].clk = 0;
1.1       tsubai    312:                        xcs->cs_clocks[2].clk = 0;
                    313:                } else {
                    314:                        theflags = 0; /*mac68k_machine.print_flags;*/
                    315:                        xcs->cs_clocks[1].flags = ZSC_VARIABLE;
                    316:                        /*
                    317:                         * Yes, we aren't defining ANY clock source enables for the
                    318:                         * printer's DCD clock in. The hardware won't let us
                    319:                         * use it. But a clock will freak out the chip, so we
                    320:                         * let you set it, telling us to bar interrupts on the line.
                    321:                         */
1.6       tsubai    322:                        /*xcs->cs_clocks[1].clk = mac68k_machine.print_dcd_clk;*/
                    323:                        /*xcs->cs_clocks[2].clk = mac68k_machine.print_cts_clk;*/
                    324:                        xcs->cs_clocks[1].clk = 0;
1.1       tsubai    325:                        xcs->cs_clocks[2].clk = 0;
                    326:                }
                    327:                if (xcs->cs_clocks[1].clk)
                    328:                        zsc_args.hwflags |= ZS_HWFLAG_NO_DCD;
                    329:                if (xcs->cs_clocks[2].clk)
                    330:                        zsc_args.hwflags |= ZS_HWFLAG_NO_CTS;
                    331:
                    332:                /* Set defaults in our "extended" chanstate. */
                    333:                xcs->cs_csource = 0;
                    334:                xcs->cs_psource = 0;
                    335:                xcs->cs_cclk_flag = 0;  /* Nothing fancy by default */
                    336:                xcs->cs_pclk_flag = 0;
                    337:
                    338:                if (theflags & ZSMAC_RAW) {
                    339:                        zsc_args.hwflags |= ZS_HWFLAG_RAW;
                    340:                        printf(" (raw defaults)");
                    341:                }
                    342:
                    343:                /*
                    344:                 * XXX - This might be better done with a "stub" driver
                    345:                 * (to replace zstty) that ignores LocalTalk for now.
                    346:                 */
                    347:                if (theflags & ZSMAC_LOCALTALK) {
                    348:                        printf(" shielding from LocalTalk");
                    349:                        cs->cs_defspeed = 1;
                    350:                        cs->cs_creg[ZSRR_BAUDLO] = cs->cs_preg[ZSRR_BAUDLO] = 0xff;
                    351:                        cs->cs_creg[ZSRR_BAUDHI] = cs->cs_preg[ZSRR_BAUDHI] = 0xff;
                    352:                        zs_write_reg(cs, ZSRR_BAUDLO, 0xff);
                    353:                        zs_write_reg(cs, ZSRR_BAUDHI, 0xff);
                    354:                        /*
                    355:                         * If we might have LocalTalk, then make sure we have the
                    356:                         * Baud rate low-enough to not do any damage.
                    357:                         */
                    358:                }
                    359:
                    360:                /*
                    361:                 * We used to disable chip interrupts here, but we now
                    362:                 * do that in zscnprobe, just in case MacOS left the chip on.
                    363:                 */
                    364:
                    365:                xcs->cs_chip = chip;
                    366:
                    367:                /* Stash away a copy of the final H/W flags. */
                    368:                xcs->cs_hwflags = zsc_args.hwflags;
                    369:
                    370:                /*
                    371:                 * Look for a child driver for this channel.
                    372:                 * The child attach will setup the hardware.
                    373:                 */
                    374:                if (!config_found(self, (void *)&zsc_args, zsc_print)) {
                    375:                        /* No sub-driver.  Just reset it. */
1.45.14.1! mjf       376:                        uint8_t reset = (channel == 0) ?
1.1       tsubai    377:                                ZSWR9_A_RESET : ZSWR9_B_RESET;
                    378:                        s = splzs();
                    379:                        zs_write_reg(cs, 9, reset);
                    380:                        splx(s);
                    381:                }
                    382:        }
                    383:
                    384:        /* XXX - Now safe to install interrupt handlers. */
1.43      garbled   385:        intr_establish(intr[0][0], IST_EDGE, IPL_TTY, zshard, zsc);
                    386:        intr_establish(intr[1][0], IST_EDGE, IPL_TTY, zshard, zsc);
1.1       tsubai    387: #ifdef ZS_TXDMA
1.43      garbled   388:        intr_establish(intr[0][1], IST_EDGE, IPL_TTY, zs_txdma_int, (void *)0);
                    389:        intr_establish(intr[1][1], IST_EDGE, IPL_TTY, zs_txdma_int, (void *)1);
1.1       tsubai    390: #endif
                    391:
1.45      ad        392:        zsc->zsc_si = softint_establish(SOFTINT_SERIAL,
1.29      matt      393:                (void (*)(void *)) zsc_intr_soft, zsc);
                    394:
1.1       tsubai    395:        /*
                    396:         * Set the master interrupt enable and interrupt vector.
                    397:         * (common to both channels, do it on A)
                    398:         */
                    399:        cs = zsc->zsc_cs[0];
                    400:        s = splzs();
                    401:        /* interrupt vector */
                    402:        zs_write_reg(cs, 2, zs_init_reg[2]);
                    403:        /* master interrupt control (enable) */
                    404:        zs_write_reg(cs, 9, zs_init_reg[9]);
                    405:        splx(s);
                    406: }
                    407:
                    408: static int
1.30      chs       409: zsc_print(void *aux, const char *name)
1.1       tsubai    410: {
                    411:        struct zsc_attach_args *args = aux;
                    412:
                    413:        if (name != NULL)
1.24      thorpej   414:                aprint_normal("%s: ", name);
1.1       tsubai    415:
                    416:        if (args->channel != -1)
1.24      thorpej   417:                aprint_normal(" channel %d", args->channel);
1.1       tsubai    418:
                    419:        return UNCONF;
1.6       tsubai    420: }
                    421:
                    422: int
1.42      christos  423: zsmdioctl(struct zs_chanstate *cs, u_long cmd, void *data)
1.6       tsubai    424: {
                    425:        switch (cmd) {
                    426:        default:
1.20      atatat    427:                return (EPASSTHROUGH);
1.6       tsubai    428:        }
                    429:        return (0);
                    430: }
                    431:
                    432: void
1.30      chs       433: zsmd_setclock(struct zs_chanstate *cs)
1.6       tsubai    434: {
1.16      matt      435: #ifdef NOTYET
1.6       tsubai    436:        struct xzs_chanstate *xcs = (void *)cs;
                    437:
                    438:        if (cs->cs_channel != 0)
                    439:                return;
                    440:
                    441:        /*
                    442:         * If the new clock has the external bit set, then select the
                    443:         * external source.
                    444:         */
1.16      matt      445:        via_set_modem((xcs->cs_pclk_flag & ZSC_EXTERN) ? 1 : 0);
                    446: #endif
1.1       tsubai    447: }
                    448:
                    449: int
1.30      chs       450: zshard(void *arg)
1.1       tsubai    451: {
1.30      chs       452:        struct zsc_softc *zsc;
1.39      tsutsui   453:        int rval;
1.1       tsubai    454:
1.39      tsutsui   455:        zsc = arg;
                    456:        rval = zsc_intr_hard(zsc);
                    457:        if ((zsc->zsc_cs[0]->cs_softreq) || (zsc->zsc_cs[1]->cs_softreq))
1.45      ad        458:                softint_schedule(zsc->zsc_si);
1.39      tsutsui   459:
                    460:        return rval;
1.1       tsubai    461: }
                    462:
                    463: #ifdef ZS_TXDMA
                    464: int
1.30      chs       465: zs_txdma_int(void *arg)
1.1       tsubai    466: {
                    467:        int ch = (int)arg;
                    468:        struct zsc_softc *zsc;
                    469:        struct zs_chanstate *cs;
                    470:        int unit = 0;                   /* XXX */
                    471:
1.45.14.1! mjf       472:        zsc = device_priavet(zsc_cd.cd_devs[unit]);
1.1       tsubai    473:        if (zsc == NULL)
                    474:                panic("zs_txdma_int");
                    475:
                    476:        cs = zsc->zsc_cs[ch];
                    477:        zstty_txdma_int(cs);
                    478:
1.38      tsutsui   479:        if (cs->cs_softreq)
1.45      ad        480:                softint_schedule(zsc->zsc_si);
1.38      tsutsui   481:
1.1       tsubai    482:        return 1;
                    483: }
                    484:
                    485: void
1.42      christos  486: zs_dma_setup(struct zs_chanstate *cs, void *pa, int len)
1.1       tsubai    487: {
                    488:        struct zsc_softc *zsc;
                    489:        dbdma_command_t *cmdp;
                    490:        int ch = cs->cs_channel;
                    491:
1.45.14.1! mjf       492:        zsc = device_private(zsc_cd.cd_devs[ch]);
1.1       tsubai    493:        cmdp = zsc->zsc_txdmacmd[ch];
                    494:
                    495:        DBDMA_BUILD(cmdp, DBDMA_CMD_OUT_LAST, 0, len, kvtop(pa),
                    496:                DBDMA_INT_ALWAYS, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
                    497:        cmdp++;
                    498:        DBDMA_BUILD(cmdp, DBDMA_CMD_STOP, 0, 0, 0,
                    499:                DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
                    500:
1.35      perry     501:        __asm volatile("eieio");
1.1       tsubai    502:
                    503:        dbdma_start(zsc->zsc_txdmareg[ch], zsc->zsc_txdmacmd[ch]);
                    504: }
                    505: #endif
                    506:
                    507: /*
1.13      tsubai    508:  * Compute the current baud rate given a ZS channel.
                    509:  * XXX Assume internal BRG.
1.1       tsubai    510:  */
                    511: int
1.30      chs       512: zs_get_speed(struct zs_chanstate *cs)
1.1       tsubai    513: {
1.13      tsubai    514:        int tconst;
1.1       tsubai    515:
1.13      tsubai    516:        tconst = zs_read_reg(cs, 12);
                    517:        tconst |= zs_read_reg(cs, 13) << 8;
                    518:        return TCONST_TO_BPS(cs->cs_brg_clk, tconst);
1.1       tsubai    519: }
1.13      tsubai    520:
                    521: #ifndef ZS_TOLERANCE
                    522: #define ZS_TOLERANCE 51
                    523: /* 5% in tenths of a %, plus 1 so that exactly 5% will be ok. */
                    524: #endif
1.1       tsubai    525:
                    526: /*
                    527:  * Search through the signal sources in the channel, and
                    528:  * pick the best one for the baud rate requested. Return
                    529:  * a -1 if not achievable in tolerance. Otherwise return 0
                    530:  * and fill in the values.
                    531:  *
                    532:  * This routine draws inspiration from the Atari port's zs.c
                    533:  * driver in NetBSD 1.1 which did the same type of source switching.
                    534:  * Tolerance code inspired by comspeed routine in isa/com.c.
                    535:  *
                    536:  * By Bill Studenmund, 1996-05-12
                    537:  */
                    538: int
1.30      chs       539: zs_set_speed(struct zs_chanstate *cs, int bps)
1.1       tsubai    540: {
                    541:        struct xzs_chanstate *xcs = (void *) cs;
                    542:        int i, tc, tc0 = 0, tc1, s, sf = 0;
                    543:        int src, rate0, rate1, err, tol;
                    544:
                    545:        if (bps == 0)
                    546:                return (0);
                    547:
                    548:        src = -1;               /* no valid source yet */
                    549:        tol = ZS_TOLERANCE;
                    550:
                    551:        /*
                    552:         * Step through all the sources and see which one matches
                    553:         * the best. A source has to match BETTER than tol to be chosen.
                    554:         * Thus if two sources give the same error, the first one will be
                    555:         * chosen. Also, allow for the possability that one source might run
                    556:         * both the BRG and the direct divider (i.e. RTxC).
                    557:         */
                    558:        for (i = 0; i < xcs->cs_clock_count; i++) {
                    559:                if (xcs->cs_clocks[i].clk <= 0)
1.17      wiz       560:                        continue;       /* skip non-existent or bad clocks */
1.1       tsubai    561:                if (xcs->cs_clocks[i].flags & ZSC_BRG) {
                    562:                        /* check out BRG at /16 */
                    563:                        tc1 = BPS_TO_TCONST(xcs->cs_clocks[i].clk >> 4, bps);
                    564:                        if (tc1 >= 0) {
                    565:                                rate1 = TCONST_TO_BPS(xcs->cs_clocks[i].clk >> 4, tc1);
                    566:                                err = abs(((rate1 - bps)*1000)/bps);
                    567:                                if (err < tol) {
                    568:                                        tol = err;
                    569:                                        src = i;
                    570:                                        sf = xcs->cs_clocks[i].flags & ~ZSC_DIV;
                    571:                                        tc0 = tc1;
                    572:                                        rate0 = rate1;
                    573:                                }
                    574:                        }
                    575:                }
                    576:                if (xcs->cs_clocks[i].flags & ZSC_DIV) {
                    577:                        /*
                    578:                         * Check out either /1, /16, /32, or /64
                    579:                         * Note: for /1, you'd better be using a synchronized
                    580:                         * clock!
                    581:                         */
                    582:                        int b0 = xcs->cs_clocks[i].clk, e0 = abs(b0-bps);
                    583:                        int b1 = b0 >> 4, e1 = abs(b1-bps);
                    584:                        int b2 = b1 >> 1, e2 = abs(b2-bps);
                    585:                        int b3 = b2 >> 1, e3 = abs(b3-bps);
                    586:
                    587:                        if (e0 < e1 && e0 < e2 && e0 < e3) {
                    588:                                err = e0;
                    589:                                rate1 = b0;
                    590:                                tc1 = ZSWR4_CLK_X1;
                    591:                        } else if (e0 > e1 && e1 < e2  && e1 < e3) {
                    592:                                err = e1;
                    593:                                rate1 = b1;
                    594:                                tc1 = ZSWR4_CLK_X16;
                    595:                        } else if (e0 > e2 && e1 > e2 && e2 < e3) {
                    596:                                err = e2;
                    597:                                rate1 = b2;
                    598:                                tc1 = ZSWR4_CLK_X32;
                    599:                        } else {
                    600:                                err = e3;
                    601:                                rate1 = b3;
                    602:                                tc1 = ZSWR4_CLK_X64;
                    603:                        }
                    604:
                    605:                        err = (err * 1000)/bps;
                    606:                        if (err < tol) {
                    607:                                tol = err;
                    608:                                src = i;
                    609:                                sf = xcs->cs_clocks[i].flags & ~ZSC_BRG;
                    610:                                tc0 = tc1;
                    611:                                rate0 = rate1;
                    612:                        }
                    613:                }
                    614:        }
                    615: #ifdef ZSMACDEBUG
                    616:        zsprintf("Checking for rate %d. Found source #%d.\n",bps, src);
                    617: #endif
                    618:        if (src == -1)
                    619:                return (EINVAL); /* no can do */
                    620:
                    621:        /*
                    622:         * The M.I. layer likes to keep cs_brg_clk current, even though
                    623:         * we are the only ones who should be touching the BRG's rate.
                    624:         *
                    625:         * Note: we are assuming that any ZSC_EXTERN signal source comes in
                    626:         * on the RTxC pin. Correct for the mac68k obio zsc.
                    627:         */
                    628:        if (sf & ZSC_EXTERN)
                    629:                cs->cs_brg_clk = xcs->cs_clocks[i].clk >> 4;
                    630:        else
1.11      mycroft   631:                cs->cs_brg_clk = PCLK / 16;
1.1       tsubai    632:
                    633:        /*
                    634:         * Now we have a source, so set it up.
                    635:         */
                    636:        s = splzs();
                    637:        xcs->cs_psource = src;
                    638:        xcs->cs_pclk_flag = sf;
                    639:        bps = rate0;
                    640:        if (sf & ZSC_BRG) {
                    641:                cs->cs_preg[4] = ZSWR4_CLK_X16;
                    642:                cs->cs_preg[11]= ZSWR11_RXCLK_BAUD | ZSWR11_TXCLK_BAUD;
                    643:                if (sf & ZSC_PCLK) {
                    644:                        cs->cs_preg[14] = ZSWR14_BAUD_ENA | ZSWR14_BAUD_FROM_PCLK;
                    645:                } else {
                    646:                        cs->cs_preg[14] = ZSWR14_BAUD_ENA;
                    647:                }
                    648:                tc = tc0;
                    649:        } else {
                    650:                cs->cs_preg[4] = tc0;
                    651:                if (sf & ZSC_RTXDIV) {
                    652:                        cs->cs_preg[11] = ZSWR11_RXCLK_RTXC | ZSWR11_TXCLK_RTXC;
                    653:                } else {
                    654:                        cs->cs_preg[11] = ZSWR11_RXCLK_TRXC | ZSWR11_TXCLK_TRXC;
                    655:                }
                    656:                cs->cs_preg[14]= 0;
                    657:                tc = 0xffff;
                    658:        }
                    659:        /* Set the BAUD rate divisor. */
                    660:        cs->cs_preg[12] = tc;
                    661:        cs->cs_preg[13] = tc >> 8;
                    662:        splx(s);
                    663:
                    664: #ifdef ZSMACDEBUG
                    665:        zsprintf("Rate is %7d, tc is %7d, source no. %2d, flags %4x\n", \
                    666:            bps, tc, src, sf);
                    667:        zsprintf("Registers are: 4 %x, 11 %x, 14 %x\n\n",
                    668:                cs->cs_preg[4], cs->cs_preg[11], cs->cs_preg[14]);
                    669: #endif
                    670:
                    671:        cs->cs_preg[5] |= ZSWR5_RTS;    /* Make sure the drivers are on! */
                    672:
                    673:        /* Caller will stuff the pending registers. */
                    674:        return (0);
                    675: }
                    676:
                    677: int
1.30      chs       678: zs_set_modes(struct zs_chanstate *cs, int cflag)
1.1       tsubai    679: {
                    680:        struct xzs_chanstate *xcs = (void*)cs;
                    681:        int s;
                    682:
                    683:        /*
                    684:         * Make sure we don't enable hfc on a signal line we're ignoring.
                    685:         * As we enable CTS interrupts only if we have CRTSCTS or CDTRCTS,
                    686:         * this code also effectivly turns off ZSWR15_CTS_IE.
                    687:         *
                    688:         * Also, disable DCD interrupts if we've been told to ignore
                    689:         * the DCD pin. Happens on mac68k because the input line for
                    690:         * DCD can also be used as a clock input.  (Just set CLOCAL.)
                    691:         *
                    692:         * If someone tries to turn an invalid flow mode on, Just Say No
                    693:         * (Suggested by gwr)
                    694:         */
                    695:        if ((cflag & CDTRCTS) && (cflag & (CRTSCTS | MDMBUF)))
                    696:                return (EINVAL);
                    697:        if (xcs->cs_hwflags & ZS_HWFLAG_NO_DCD) {
                    698:                if (cflag & MDMBUF)
                    699:                        return (EINVAL);
                    700:                cflag |= CLOCAL;
                    701:        }
                    702:        if ((xcs->cs_hwflags & ZS_HWFLAG_NO_CTS) && (cflag & (CRTSCTS | CDTRCTS)))
                    703:                return (EINVAL);
                    704:
                    705:        /*
                    706:         * Output hardware flow control on the chip is horrendous:
                    707:         * if carrier detect drops, the receiver is disabled, and if
                    708:         * CTS drops, the transmitter is stoped IN MID CHARACTER!
                    709:         * Therefore, NEVER set the HFC bit, and instead use the
                    710:         * status interrupt to detect CTS changes.
                    711:         */
                    712:        s = splzs();
                    713:        if ((cflag & (CLOCAL | MDMBUF)) != 0)
                    714:                cs->cs_rr0_dcd = 0;
                    715:        else
                    716:                cs->cs_rr0_dcd = ZSRR0_DCD;
                    717:        /*
                    718:         * The mac hardware only has one output, DTR (HSKo in Mac
                    719:         * parlance). In HFC mode, we use it for the functions
                    720:         * typically served by RTS and DTR on other ports, so we
                    721:         * have to fake the upper layer out some.
                    722:         *
                    723:         * CRTSCTS we use CTS as an input which tells us when to shut up.
                    724:         * We make no effort to shut up the other side of the connection.
                    725:         * DTR is used to hang up the modem.
                    726:         *
                    727:         * In CDTRCTS, we use CTS to tell us to stop, but we use DTR to
                    728:         * shut up the other side.
                    729:         */
                    730:        if ((cflag & CRTSCTS) != 0) {
                    731:                cs->cs_wr5_dtr = ZSWR5_DTR;
                    732:                cs->cs_wr5_rts = 0;
                    733:                cs->cs_rr0_cts = ZSRR0_CTS;
                    734:        } else if ((cflag & CDTRCTS) != 0) {
                    735:                cs->cs_wr5_dtr = 0;
                    736:                cs->cs_wr5_rts = ZSWR5_DTR;
                    737:                cs->cs_rr0_cts = ZSRR0_CTS;
                    738:        } else if ((cflag & MDMBUF) != 0) {
                    739:                cs->cs_wr5_dtr = 0;
                    740:                cs->cs_wr5_rts = ZSWR5_DTR;
                    741:                cs->cs_rr0_cts = ZSRR0_DCD;
                    742:        } else {
                    743:                cs->cs_wr5_dtr = ZSWR5_DTR;
                    744:                cs->cs_wr5_rts = 0;
                    745:                cs->cs_rr0_cts = 0;
                    746:        }
                    747:        splx(s);
                    748:
                    749:        /* Caller will stuff the pending registers. */
                    750:        return (0);
                    751: }
                    752:
                    753:
                    754: /*
                    755:  * Read or write the chip with suitable delays.
                    756:  * MacII hardware has the delay built in.
                    757:  * No need for extra delay. :-) However, some clock-chirped
                    758:  * macs, or zsc's on serial add-on boards might need it.
                    759:  */
                    760: #define        ZS_DELAY()
                    761:
1.45.14.1! mjf       762: uint8_t
        !           763: zs_read_reg(struct zs_chanstate *cs, uint8_t reg)
1.1       tsubai    764: {
1.45.14.1! mjf       765:        uint8_t val;
1.1       tsubai    766:
                    767:        out8(cs->cs_reg_csr, reg);
                    768:        ZS_DELAY();
                    769:        val = in8(cs->cs_reg_csr);
                    770:        ZS_DELAY();
                    771:        return val;
                    772: }
                    773:
                    774: void
1.45.14.1! mjf       775: zs_write_reg(struct zs_chanstate *cs, uint8_t reg, uint8_t val)
1.1       tsubai    776: {
                    777:        out8(cs->cs_reg_csr, reg);
                    778:        ZS_DELAY();
                    779:        out8(cs->cs_reg_csr, val);
                    780:        ZS_DELAY();
                    781: }
                    782:
1.45.14.1! mjf       783: uint8_t
1.30      chs       784: zs_read_csr(struct zs_chanstate *cs)
1.1       tsubai    785: {
1.45.14.1! mjf       786:        uint8_t val;
1.1       tsubai    787:
                    788:        val = in8(cs->cs_reg_csr);
                    789:        ZS_DELAY();
                    790:        /* make up for the fact CTS is wired backwards */
                    791:        val ^= ZSRR0_CTS;
                    792:        return val;
                    793: }
                    794:
1.30      chs       795: void
1.45.14.1! mjf       796: zs_write_csr(struct zs_chanstate *cs, uint8_t val)
1.1       tsubai    797: {
                    798:        /* Note, the csr does not write CTS... */
                    799:        out8(cs->cs_reg_csr, val);
                    800:        ZS_DELAY();
                    801: }
                    802:
1.45.14.1! mjf       803: uint8_t
1.30      chs       804: zs_read_data(struct zs_chanstate *cs)
1.1       tsubai    805: {
1.45.14.1! mjf       806:        uint8_t val;
1.1       tsubai    807:
                    808:        val = in8(cs->cs_reg_data);
                    809:        ZS_DELAY();
                    810:        return val;
                    811: }
                    812:
1.30      chs       813: void
1.45.14.1! mjf       814: zs_write_data(struct zs_chanstate *cs, uint8_t val)
1.1       tsubai    815: {
                    816:        out8(cs->cs_reg_data, val);
                    817:        ZS_DELAY();
                    818: }
                    819:
                    820: /****************************************************************
                    821:  * Console support functions (powermac specific!)
                    822:  * Note: this code is allowed to know about the layout of
                    823:  * the chip registers, and uses that to keep things simple.
                    824:  * XXX - I think I like the mvme167 code better. -gwr
                    825:  * XXX - Well :-P  :-)  -wrs
                    826:  ****************************************************************/
                    827:
                    828: #define zscnpollc      nullcnpollc
                    829: cons_decl(zs);
                    830:
1.4       tsubai    831: static int stdin, stdout;
                    832:
1.1       tsubai    833: /*
                    834:  * Console functions.
                    835:  */
                    836:
                    837: /*
                    838:  * zscnprobe is the routine which gets called as the kernel is trying to
                    839:  * figure out where the console should be. Each io driver which might
                    840:  * be the console (as defined in mac68k/conf.c) gets probed. The probe
                    841:  * fills in the consdev structure. Important parts are the device #,
                    842:  * and the console priority. Values are CN_DEAD (don't touch me),
                    843:  * CN_NORMAL (I'm here, but elsewhere might be better), CN_INTERNAL
                    844:  * (the video, better than CN_NORMAL), and CN_REMOTE (pick me!)
                    845:  *
                    846:  * As the mac's a bit different, we do extra work here. We mainly check
                    847:  * to see if we have serial echo going on. Also chould check for default
                    848:  * speeds.
                    849:  */
                    850:
                    851: /*
                    852:  * Polled input char.
                    853:  */
                    854: int
1.30      chs       855: zs_getc(void *v)
1.1       tsubai    856: {
1.30      chs       857:        volatile struct zschan *zc = v;
                    858:        int s, c, rr0;
1.1       tsubai    859:
                    860:        s = splhigh();
                    861:        /* Wait for a character to arrive. */
                    862:        do {
                    863:                rr0 = in8(&zc->zc_csr);
                    864:                ZS_DELAY();
                    865:        } while ((rr0 & ZSRR0_RX_READY) == 0);
                    866:
                    867:        c = in8(&zc->zc_data);
                    868:        ZS_DELAY();
                    869:        splx(s);
                    870:
                    871:        /*
                    872:         * This is used by the kd driver to read scan codes,
                    873:         * so don't translate '\r' ==> '\n' here...
                    874:         */
                    875:        return (c);
                    876: }
                    877:
                    878: /*
                    879:  * Polled output char.
                    880:  */
                    881: void
1.30      chs       882: zs_putc(void *v, int c)
1.1       tsubai    883: {
1.30      chs       884:        volatile struct zschan *zc = v;
                    885:        int s, rr0;
                    886:        long wait = 0;
1.1       tsubai    887:
                    888:        s = splhigh();
                    889:        /* Wait for transmitter to become ready. */
                    890:        do {
                    891:                rr0 = in8(&zc->zc_csr);
                    892:                ZS_DELAY();
                    893:        } while (((rr0 & ZSRR0_TX_READY) == 0) && (wait++ < 1000000));
                    894:
                    895:        if ((rr0 & ZSRR0_TX_READY) != 0) {
                    896:                out8(&zc->zc_data, c);
                    897:                ZS_DELAY();
                    898:        }
                    899:        splx(s);
                    900: }
                    901:
                    902:
                    903: /*
                    904:  * Polled console input putchar.
                    905:  */
                    906: int
1.30      chs       907: zscngetc(dev_t dev)
1.1       tsubai    908: {
1.30      chs       909:        volatile struct zschan *zc = zs_conschan;
                    910:        int c;
1.1       tsubai    911:
1.4       tsubai    912:        if (zc) {
1.33      matt      913:                c = zs_getc(__UNVOLATILE(zc));
1.4       tsubai    914:        } else {
                    915:                char ch = 0;
                    916:                OF_read(stdin, &ch, 1);
                    917:                c = ch;
                    918:        }
                    919:        return c;
1.1       tsubai    920: }
                    921:
                    922: /*
                    923:  * Polled console output putchar.
                    924:  */
                    925: void
1.30      chs       926: zscnputc(dev_t dev, int c)
1.1       tsubai    927: {
1.30      chs       928:        volatile struct zschan *zc = zs_conschan;
1.1       tsubai    929:
1.4       tsubai    930:        if (zc) {
1.33      matt      931:                zs_putc(__UNVOLATILE(zc), c);
1.4       tsubai    932:        } else {
                    933:                char ch = c;
                    934:                OF_write(stdout, &ch, 1);
                    935:        }
1.1       tsubai    936: }
                    937:
                    938: /*
                    939:  * Handle user request to enter kernel debugger.
                    940:  */
                    941: void
1.30      chs       942: zs_abort(struct zs_chanstate *cs)
1.1       tsubai    943: {
                    944:        volatile struct zschan *zc = zs_conschan;
                    945:        int rr0;
1.30      chs       946:        long wait = 0;
1.1       tsubai    947:
                    948:        if (zs_cons_canabort == 0)
                    949:                return;
                    950:
                    951:        /* Wait for end of break to avoid PROM abort. */
                    952:        do {
                    953:                rr0 = in8(&zc->zc_csr);
                    954:                ZS_DELAY();
                    955:        } while ((rr0 & ZSRR0_BREAK) && (wait++ < ZSABORT_DELAY));
                    956:
                    957:        if (wait > ZSABORT_DELAY) {
                    958:                zs_cons_canabort = 0;
                    959:        /* If we time out, turn off the abort ability! */
                    960:        }
                    961:
1.19      dbj       962: #if defined(KGDB)
                    963:        kgdb_connect(1);
                    964: #elif defined(DDB)
1.1       tsubai    965:        Debugger();
                    966: #endif
                    967: }
                    968:
1.30      chs       969: extern int ofccngetc(dev_t);
                    970: extern void ofccnputc(dev_t, int);
1.1       tsubai    971:
                    972: struct consdev consdev_zs = {
                    973:        zscnprobe,
                    974:        zscninit,
1.4       tsubai    975:        zscngetc,
                    976:        zscnputc,
1.1       tsubai    977:        zscnpollc,
                    978: };
                    979:
                    980: void
1.30      chs       981: zscnprobe(struct consdev *cp)
1.1       tsubai    982: {
1.4       tsubai    983:        int chosen, pkg;
                    984:        char name[16];
                    985:
                    986:        if ((chosen = OF_finddevice("/chosen")) == -1)
                    987:                return;
                    988:
                    989:        if (OF_getprop(chosen, "stdin", &stdin, sizeof(stdin)) == -1)
                    990:                return;
                    991:        if (OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)) == -1)
                    992:                return;
                    993:
                    994:        if ((pkg = OF_instance_to_package(stdin)) == -1)
                    995:                return;
1.1       tsubai    996:
1.18      wiz       997:        memset(name, 0, sizeof(name));
1.4       tsubai    998:        if (OF_getprop(pkg, "device_type", name, sizeof(name)) == -1)
1.1       tsubai    999:                return;
                   1000:
1.4       tsubai   1001:        if (strcmp(name, "serial") != 0)
                   1002:                return;
                   1003:
1.18      wiz      1004:        memset(name, 0, sizeof(name));
1.4       tsubai   1005:        if (OF_getprop(pkg, "name", name, sizeof(name)) == -1)
1.1       tsubai   1006:                return;
                   1007:
1.4       tsubai   1008:        cp->cn_pri = CN_REMOTE;
1.1       tsubai   1009: }
                   1010:
                   1011: void
1.30      chs      1012: zscninit(struct consdev *cp)
1.1       tsubai   1013: {
1.15      tsubai   1014:        int escc, escc_ch, obio, zs_offset;
                   1015:        u_int32_t reg[5];
1.4       tsubai   1016:        char name[16];
1.1       tsubai   1017:
1.15      tsubai   1018:        if ((escc_ch = OF_instance_to_package(stdin)) == -1)
1.1       tsubai   1019:                return;
                   1020:
1.18      wiz      1021:        memset(name, 0, sizeof(name));
1.15      tsubai   1022:        if (OF_getprop(escc_ch, "name", name, sizeof(name)) == -1)
1.1       tsubai   1023:                return;
                   1024:
1.37      macallan 1025:        zs_conschannel = strcmp(name, "ch-b") == 0;
1.15      tsubai   1026:
                   1027:        if (OF_getprop(escc_ch, "reg", reg, sizeof(reg)) < 4)
                   1028:                return;
                   1029:        zs_offset = reg[0];
                   1030:
                   1031:        escc = OF_parent(escc_ch);
                   1032:        obio = OF_parent(escc);
                   1033:
                   1034:        if (OF_getprop(obio, "assigned-addresses", reg, sizeof(reg)) < 12)
                   1035:                return;
                   1036:        zs_conschan = (void *)(reg[2] + zs_offset);
1.1       tsubai   1037: }

CVSweb <webmaster@jp.NetBSD.org>