[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.10

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

CVSweb <webmaster@jp.NetBSD.org>