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

Annotation of sys/arch/sparc/dev/zs.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: zs.c,v 1.43 2006/01/09 20:57:00 miod Exp $    */
        !             2: /*     $NetBSD: zs.c,v 1.50 1997/10/18 00:00:40 gwr Exp $      */
        !             3:
        !             4: /*-
        !             5:  * Copyright (c) 1996 The NetBSD Foundation, Inc.
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * This code is derived from software contributed to The NetBSD Foundation
        !             9:  * by Gordon W. Ross.
        !            10:  *
        !            11:  * Redistribution and use in source and binary forms, with or without
        !            12:  * modification, are permitted provided that the following conditions
        !            13:  * are met:
        !            14:  * 1. Redistributions of source code must retain the above copyright
        !            15:  *    notice, this list of conditions and the following disclaimer.
        !            16:  * 2. Redistributions in binary form must reproduce the above copyright
        !            17:  *    notice, this list of conditions and the following disclaimer in the
        !            18:  *    documentation and/or other materials provided with the distribution.
        !            19:  * 3. All advertising materials mentioning features or use of this software
        !            20:  *    must display the following acknowledgement:
        !            21:  *        This product includes software developed by the NetBSD
        !            22:  *        Foundation, Inc. and its contributors.
        !            23:  * 4. Neither the name of The NetBSD Foundation nor the names of its
        !            24:  *    contributors may be used to endorse or promote products derived
        !            25:  *    from this software without specific prior written permission.
        !            26:  *
        !            27:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
        !            28:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
        !            29:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
        !            30:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
        !            31:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
        !            32:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        !            33:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        !            34:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        !            35:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            36:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            37:  * POSSIBILITY OF SUCH DAMAGE.
        !            38:  */
        !            39:
        !            40: /*
        !            41:  * Zilog Z8530 Dual UART driver (machine-dependent part)
        !            42:  *
        !            43:  * Runs two serial lines per chip using slave drivers.
        !            44:  * Plain tty/async lines use the zs_async slave.
        !            45:  * Sun keyboard/mouse uses the zs_kbd/zs_ms slaves.
        !            46:  */
        !            47:
        !            48: #include <sys/param.h>
        !            49: #include <sys/systm.h>
        !            50: #include <sys/conf.h>
        !            51: #include <sys/device.h>
        !            52: #include <sys/file.h>
        !            53: #include <sys/ioctl.h>
        !            54: #include <sys/kernel.h>
        !            55: #include <sys/proc.h>
        !            56: #include <sys/tty.h>
        !            57: #include <sys/time.h>
        !            58: #include <sys/syslog.h>
        !            59:
        !            60: #include <machine/autoconf.h>
        !            61: #include <machine/bsd_openprom.h>
        !            62: #include <machine/conf.h>
        !            63: #include <machine/cpu.h>
        !            64: #include <machine/eeprom.h>
        !            65: #if defined(SUN4)
        !            66: #include <machine/oldmon.h>
        !            67: #endif
        !            68: #include <machine/psl.h>
        !            69: #include <machine/z8530var.h>
        !            70:
        !            71: #include <dev/cons.h>
        !            72: #include <sparc/dev/z8530reg.h>
        !            73:
        !            74: #include <sparc/sparc/vaddrs.h>
        !            75: #include <sparc/sparc/auxioreg.h>
        !            76: #include <sparc/dev/cons.h>
        !            77:
        !            78: #ifdef solbourne
        !            79: #include <machine/prom.h>
        !            80: #endif
        !            81:
        !            82: #include <uvm/uvm_extern.h>
        !            83:
        !            84: #include "zskbd.h"
        !            85: #include "zs.h"
        !            86:
        !            87: /* Make life easier for the initialized arrays here. */
        !            88: #if NZS < 3
        !            89: #undef  NZS
        !            90: #define NZS 3
        !            91: #endif
        !            92:
        !            93: /*
        !            94:  * Some warts needed by z8530tty.c -
        !            95:  * The default parity REALLY needs to be the same as the PROM uses,
        !            96:  * or you can not see messages done with printf during boot-up...
        !            97:  */
        !            98: int zs_def_cflag = (CREAD | CS8 | HUPCL);
        !            99: int zs_major = 12;
        !           100:
        !           101: /*
        !           102:  * The Sun provides a 4.9152 MHz clock to the ZS chips.
        !           103:  */
        !           104: #define PCLK   (9600 * 512)    /* PCLK pin input clock rate */
        !           105:
        !           106: /*
        !           107:  * Select software interrupt bit based on TTY ipl.
        !           108:  */
        !           109: #if IPL_TTY == 1
        !           110: # define IE_ZSSOFT IE_L1
        !           111: #elif IPL_TTY == 4
        !           112: # define IE_ZSSOFT IE_L4
        !           113: #elif IPL_TTY == 6
        !           114: # define IE_ZSSOFT IE_L6
        !           115: #else
        !           116: # error "no suitable software interrupt bit"
        !           117: #endif
        !           118:
        !           119: #define        ZS_DELAY()              (CPU_ISSUN4C ? (0) : delay(2))
        !           120:
        !           121: /* The layout of this is hardware-dependent (padding, order). */
        !           122: struct zschan {
        !           123: #if defined(SUN4) || defined(SUN4C) || defined(SUN4M)
        !           124:        volatile u_char zc_csr;         /* ctrl,status, and indirect access */
        !           125:        u_char          zc_xxx0;
        !           126:        volatile u_char zc_data;        /* data */
        !           127:        u_char          zc_xxx1;
        !           128: #endif
        !           129: #if defined(solbourne)
        !           130:        volatile u_char zc_csr;         /* ctrl,status, and indirect access */
        !           131:        u_char          zc_xxx0[7];
        !           132:        volatile u_char zc_data;        /* data */
        !           133:        u_char          zc_xxx1[7];
        !           134: #endif
        !           135: };
        !           136: struct zsdevice {
        !           137:        /* Yes, they are backwards. */
        !           138:        struct  zschan zs_chan_b;
        !           139:        struct  zschan zs_chan_a;
        !           140: };
        !           141:
        !           142: /* Saved PROM mappings */
        !           143: struct zsdevice *zsaddr[NZS];
        !           144:
        !           145: /* Flags from cninit() */
        !           146: int zs_hwflags[NZS][2];
        !           147:
        !           148: /* Default speed for each channel */
        !           149: int zs_defspeed[NZS][2] = {
        !           150:        { 9600,         /* ttya */
        !           151:          9600 },       /* ttyb */
        !           152:        { 1200,         /* keyboard */
        !           153:          1200 },       /* mouse */
        !           154:        { 9600,         /* ttyc */
        !           155:          9600 },       /* ttyd */
        !           156: };
        !           157:
        !           158: u_char zs_init_reg[16] = {
        !           159:        0,      /* 0: CMD (reset, etc.) */
        !           160:        0,      /* 1: No interrupts yet. */
        !           161:        0,      /* 2: IVECT */
        !           162:        ZSWR3_RX_8 | ZSWR3_RX_ENABLE,
        !           163:        ZSWR4_CLK_X16 | ZSWR4_ONESB | ZSWR4_EVENP,
        !           164:        ZSWR5_TX_8 | ZSWR5_TX_ENABLE,
        !           165:        0,      /* 6: TXSYNC/SYNCLO */
        !           166:        0,      /* 7: RXSYNC/SYNCHI */
        !           167:        0,      /* 8: alias for data port */
        !           168:        ZSWR9_MASTER_IE | ZSWR9_NO_VECTOR,
        !           169:        0,      /*10: Misc. TX/RX control bits */
        !           170:        ZSWR11_TXCLK_BAUD | ZSWR11_RXCLK_BAUD,
        !           171:        ((PCLK/32)/9600)-2,     /*12: BAUDLO (default=9600) */
        !           172:        0,                      /*13: BAUDHI (default=9600) */
        !           173:        ZSWR14_BAUD_ENA | ZSWR14_BAUD_FROM_PCLK,
        !           174:        ZSWR15_BREAK_IE /* | ZSWR15_DCD_IE */,
        !           175: };
        !           176:
        !           177: struct zschan *
        !           178: zs_get_chan_addr(zs_unit, channel)
        !           179:        int zs_unit, channel;
        !           180: {
        !           181:        struct zsdevice *addr;
        !           182:        struct zschan *zc;
        !           183:
        !           184:        if (zs_unit >= NZS)
        !           185:                return NULL;
        !           186:        addr = zsaddr[zs_unit];
        !           187:        if (addr == NULL)
        !           188:                addr = zsaddr[zs_unit] = findzs(zs_unit);
        !           189:        if (addr == NULL)
        !           190:                return NULL;
        !           191:        if (channel == 0) {
        !           192:                zc = &addr->zs_chan_a;
        !           193:        } else {
        !           194:                zc = &addr->zs_chan_b;
        !           195:        }
        !           196:        return (zc);
        !           197: }
        !           198:
        !           199:
        !           200: /****************************************************************
        !           201:  * Autoconfig
        !           202:  ****************************************************************/
        !           203:
        !           204: /* Definition of the driver for autoconfig. */
        !           205: int    zs_match(struct device *, void *, void *);
        !           206: void   zs_attach(struct device *, struct device *, void *);
        !           207: int    zs_print(void *, const char *nam);
        !           208:
        !           209: /* Power management hooks (for Tadpole SPARCbooks) */
        !           210: void   zs_disable(struct zs_chanstate *);
        !           211: int    zs_enable(struct zs_chanstate *);
        !           212:
        !           213: struct cfattach zs_ca = {
        !           214:        sizeof(struct zsc_softc), zs_match, zs_attach
        !           215: };
        !           216:
        !           217: struct cfdriver zs_cd = {
        !           218:        NULL, "zs", DV_DULL
        !           219: };
        !           220:
        !           221: /* Interrupt handlers. */
        !           222: int zshard(void *);
        !           223: int zssoft(void *);
        !           224: struct intrhand levelhard = { zshard };
        !           225: struct intrhand levelsoft = { zssoft };
        !           226:
        !           227: int zs_get_speed(struct zs_chanstate *);
        !           228:
        !           229:
        !           230: /*
        !           231:  * Is the zs chip present?
        !           232:  */
        !           233: int
        !           234: zs_match(parent, vcf, aux)
        !           235:        struct device *parent;
        !           236:        void *vcf, *aux;
        !           237: {
        !           238:        struct cfdata *cf = (struct cfdata *)vcf;
        !           239:        struct confargs *ca = (struct confargs *)aux;
        !           240:        struct romaux *ra = &ca->ca_ra;
        !           241:
        !           242:        if (strcmp(cf->cf_driver->cd_name, ra->ra_name))
        !           243:                return (0);
        !           244:
        !           245: #ifdef solbourne
        !           246:        if (CPU_ISKAP)
        !           247:                return (ca->ca_bustype == BUS_OBIO);
        !           248: #endif
        !           249:
        !           250:        if ((ca->ca_bustype == BUS_MAIN && !CPU_ISSUN4) ||
        !           251:            (ca->ca_bustype == BUS_OBIO && CPU_ISSUN4M))
        !           252:                return (getpropint(ra->ra_node, "slave", -2) == cf->cf_unit);
        !           253:        ra->ra_len = NBPG;
        !           254:        return (probeget(ra->ra_vaddr, 1) != -1);
        !           255: }
        !           256:
        !           257: /*
        !           258:  * Attach a found zs.
        !           259:  *
        !           260:  * USE ROM PROPERTIES port-a-ignore-cd AND port-b-ignore-cd FOR
        !           261:  * SOFT CARRIER, AND keyboard PROPERTY FOR KEYBOARD/MOUSE?
        !           262:  */
        !           263: void
        !           264: zs_attach(parent, self, aux)
        !           265:        struct device *parent;
        !           266:        struct device *self;
        !           267:        void *aux;
        !           268: {
        !           269:        struct zsc_softc *zsc = (void *) self;
        !           270:        struct confargs *ca = aux;
        !           271:        struct romaux *ra = &ca->ca_ra;
        !           272:        struct zsc_attach_args zsc_args;
        !           273:        volatile struct zschan *zc;
        !           274:        struct zs_chanstate *cs;
        !           275:        int pri, s, zs_unit, channel;
        !           276:        static int didintr, prevpri;
        !           277:
        !           278:        zs_unit = zsc->zsc_dev.dv_unit;
        !           279:
        !           280:        /* Use the mapping setup by the Sun PROM. */
        !           281:        if (zsaddr[zs_unit] == NULL)
        !           282:                zsaddr[zs_unit] = findzs(zs_unit);
        !           283:
        !           284:        if (ca->ca_bustype==BUS_MAIN)
        !           285:                if ((void*)zsaddr[zs_unit] != ra->ra_vaddr)
        !           286:                        panic("zsattach");
        !           287:        if (ra->ra_nintr != 1) {
        !           288:                printf(": expected 1 interrupt, got %d\n", ra->ra_nintr);
        !           289:                return;
        !           290:        }
        !           291:        pri = ra->ra_intr[0].int_pri;
        !           292:        printf(" pri %d, softpri %d\n", pri, IPL_TTY);
        !           293:
        !           294:        /*
        !           295:         * Initialize software state for each channel.
        !           296:         */
        !           297:        for (channel = 0; channel < 2; channel++) {
        !           298:                zsc_args.type = "serial";
        !           299:                /* XXX hardcoded */
        !           300:                if (zs_unit == 1) {
        !           301:                        if (channel == 0)
        !           302:                                zsc_args.type = "keyboard";
        !           303:                        if (channel == 1)
        !           304:                                zsc_args.type = "mouse";
        !           305:                }
        !           306:
        !           307:                zsc_args.channel = channel;
        !           308:                zsc_args.hwflags = zs_hwflags[zs_unit][channel];
        !           309:                cs = &zsc->zsc_cs[channel];
        !           310:
        !           311:                cs->cs_channel = channel;
        !           312:                cs->cs_private = NULL;
        !           313:                cs->cs_ops = &zsops_null;
        !           314:                cs->cs_brg_clk = PCLK / 16;
        !           315:
        !           316:                zc = zs_get_chan_addr(zs_unit, channel);
        !           317:
        !           318:                cs->cs_reg_csr  = &zc->zc_csr;
        !           319:                cs->cs_reg_data = &zc->zc_data;
        !           320:
        !           321:                bcopy(zs_init_reg, cs->cs_creg, 16);
        !           322:                bcopy(zs_init_reg, cs->cs_preg, 16);
        !           323:
        !           324:                /* XXX: Get these from the PROM properties! */
        !           325:                /* XXX: See the mvme167 code.  Better. */
        !           326:                if (zsc_args.hwflags & ZS_HWFLAG_CONSOLE)
        !           327:                        cs->cs_defspeed = zs_get_speed(cs);
        !           328:                else
        !           329:                        cs->cs_defspeed = zs_defspeed[zs_unit][channel];
        !           330:                cs->cs_defcflag = zs_def_cflag;
        !           331:
        !           332:                /* Make these correspond to cs_defcflag (-crtscts) */
        !           333:                cs->cs_rr0_dcd = ZSRR0_DCD;
        !           334:                cs->cs_rr0_cts = 0;
        !           335:                cs->cs_wr5_dtr = ZSWR5_DTR | ZSWR5_RTS;
        !           336:                cs->cs_wr5_rts = 0;
        !           337:
        !           338:                /*
        !           339:                 * Clear the master interrupt enable.
        !           340:                 * The INTENA is common to both channels,
        !           341:                 * so just do it on the A channel.
        !           342:                 */
        !           343:                if (channel == 0) {
        !           344:                        zs_write_reg(cs, 9, 0);
        !           345:                }
        !           346:
        !           347:                /*
        !           348:                 * Look for a child driver for this channel.
        !           349:                 * The child attach will setup the hardware.
        !           350:                 */
        !           351:                if (!config_found(self, (void *)&zsc_args, zs_print)) {
        !           352:                        /* No sub-driver.  Just reset it. */
        !           353:                        u_char reset = (channel == 0) ?
        !           354:                                ZSWR9_A_RESET : ZSWR9_B_RESET;
        !           355:                        s = splzs();
        !           356:                        zs_write_reg(cs,  9, reset);
        !           357:                        splx(s);
        !           358:                }
        !           359:        }
        !           360:
        !           361:        /*
        !           362:         * Now safe to install interrupt handlers.  Note the arguments
        !           363:         * to the interrupt handlers aren't used.  Note, we only do this
        !           364:         * once since both SCCs interrupt at the same level and vector.
        !           365:         */
        !           366:        if (!didintr) {
        !           367:                didintr = 1;
        !           368:                prevpri = pri;
        !           369:                intr_establish(pri, &levelhard, IPL_ZS, self->dv_xname);
        !           370:                intr_establish(IPL_TTY, &levelsoft, IPL_TTY, self->dv_xname);
        !           371:        } else if (pri != prevpri)
        !           372:                panic("broken zs interrupt scheme");
        !           373:
        !           374:        /*
        !           375:         * Set the master interrupt enable and interrupt vector.
        !           376:         * (common to both channels, do it on A)
        !           377:         */
        !           378:        cs = &zsc->zsc_cs[0];
        !           379:        s = splhigh();
        !           380:        /* interrupt vector */
        !           381:        zs_write_reg(cs, 2, zs_init_reg[2]);
        !           382:        /* master interrupt control (enable) */
        !           383:        zs_write_reg(cs, 9, zs_init_reg[9]);
        !           384:        splx(s);
        !           385:
        !           386: #ifdef SUN4M
        !           387:        /* register power management routines if necessary */
        !           388:        if (CPU_ISSUN4M) {
        !           389:                if (getpropint(ra->ra_node, "pwr-on-auxio2", 0))
        !           390:                        for (channel = 0; channel < 2; channel++) {
        !           391:                                cs = &zsc->zsc_cs[channel];
        !           392:                                cs->disable = zs_disable;
        !           393:                                cs->enable = zs_enable;
        !           394:                                cs->enabled = 0;
        !           395:                        }
        !           396:        }
        !           397: #endif
        !           398:
        !           399: #if 0
        !           400:        /*
        !           401:         * XXX: L1A hack - We would like to be able to break into
        !           402:         * the debugger during the rest of autoconfiguration, so
        !           403:         * lower interrupts just enough to let zs interrupts in.
        !           404:         * This is done after both zs devices are attached.
        !           405:         */
        !           406:        if (zs_unit == 1) {
        !           407:                printf("zs1: enabling zs interrupts\n");
        !           408:                (void)splfd(); /* XXX: splzs - 1 */
        !           409:        }
        !           410: #endif
        !           411: }
        !           412:
        !           413: int
        !           414: zs_print(aux, name)
        !           415:        void *aux;
        !           416:        const char *name;
        !           417: {
        !           418:        struct zsc_attach_args *args = aux;
        !           419:
        !           420:        if (name != NULL)
        !           421:                printf("%s:", name);
        !           422:
        !           423:        if (args->channel != -1)
        !           424:                printf(" channel %d", args->channel);
        !           425:
        !           426:        return UNCONF;
        !           427: }
        !           428:
        !           429: volatile int zssoftpending;
        !           430:
        !           431: /*
        !           432:  * Our ZS chips all share a common, autovectored interrupt,
        !           433:  * so we have to look at all of them on each interrupt.
        !           434:  */
        !           435: int
        !           436: zshard(arg)
        !           437:        void *arg;
        !           438: {
        !           439:        struct zsc_softc *zsc;
        !           440:        int unit, rr3, rval, softreq;
        !           441:
        !           442:        rval = softreq = 0;
        !           443:        for (unit = 0; unit < zs_cd.cd_ndevs; unit++) {
        !           444:                zsc = zs_cd.cd_devs[unit];
        !           445:                if (zsc == NULL)
        !           446:                        continue;
        !           447:                rr3 = zsc_intr_hard(zsc);
        !           448:                /* Count up the interrupts. */
        !           449:                if (rr3) {
        !           450:                        rval |= rr3;
        !           451:                }
        !           452:                softreq |= zsc->zsc_cs[0].cs_softreq;
        !           453:                softreq |= zsc->zsc_cs[1].cs_softreq;
        !           454:        }
        !           455:
        !           456:        /* We are at splzs here, so no need to lock. */
        !           457:        if (softreq && (zssoftpending == 0)) {
        !           458:                zssoftpending = IE_ZSSOFT;
        !           459: #if defined(SUN4M)
        !           460:                if (CPU_ISSUN4M)
        !           461:                        raise(0, IPL_TTY);
        !           462:                else
        !           463: #endif
        !           464:                ienab_bis(IE_ZSSOFT);
        !           465:        }
        !           466:        return (rval);
        !           467: }
        !           468:
        !           469: /*
        !           470:  * Similar scheme as for zshard (look at all of them)
        !           471:  */
        !           472: int
        !           473: zssoft(arg)
        !           474:        void *arg;
        !           475: {
        !           476:        struct zsc_softc *zsc;
        !           477:        int s, unit;
        !           478:
        !           479:        /* This is not the only ISR on this IPL. */
        !           480:        if (zssoftpending == 0)
        !           481:                return (0);
        !           482:
        !           483:        /*
        !           484:         * The soft intr. bit will be set by zshard only if
        !           485:         * the variable zssoftpending is zero.  The order of
        !           486:         * these next two statements prevents our clearing
        !           487:         * the soft intr bit just after zshard has set it.
        !           488:         */
        !           489:        /* ienab_bic(IE_ZSSOFT); */
        !           490:        zssoftpending = 0;
        !           491:
        !           492:        /* Make sure we call the tty layer at spltty. */
        !           493:        s = spltty();
        !           494:        for (unit = 0; unit < zs_cd.cd_ndevs; unit++) {
        !           495:                zsc = zs_cd.cd_devs[unit];
        !           496:                if (zsc == NULL)
        !           497:                        continue;
        !           498:                (void)zsc_intr_soft(zsc);
        !           499:        }
        !           500:        splx(s);
        !           501:        return (1);
        !           502: }
        !           503:
        !           504:
        !           505: /*
        !           506:  * Compute the current baud rate given a ZS channel.
        !           507:  */
        !           508: int
        !           509: zs_get_speed(cs)
        !           510:        struct zs_chanstate *cs;
        !           511: {
        !           512:        int tconst;
        !           513:
        !           514:        tconst = zs_read_reg(cs, 12);
        !           515:        tconst |= zs_read_reg(cs, 13) << 8;
        !           516:        return (TCONST_TO_BPS(cs->cs_brg_clk, tconst));
        !           517: }
        !           518:
        !           519: /*
        !           520:  * MD functions for setting the baud rate and control modes.
        !           521:  */
        !           522: int
        !           523: zs_set_speed(cs, bps)
        !           524:        struct zs_chanstate *cs;
        !           525:        int bps;        /* bits per second */
        !           526: {
        !           527:        int tconst, real_bps;
        !           528:
        !           529:        if (bps == 0)
        !           530:                return (0);
        !           531:
        !           532: #ifdef DIAGNOSTIC
        !           533:        if (cs->cs_brg_clk == 0)
        !           534:                panic("zs_set_speed");
        !           535: #endif
        !           536:
        !           537:        tconst = BPS_TO_TCONST(cs->cs_brg_clk, bps);
        !           538:        if (tconst < 0)
        !           539:                return (EINVAL);
        !           540:
        !           541:        /* Convert back to make sure we can do it. */
        !           542:        real_bps = TCONST_TO_BPS(cs->cs_brg_clk, tconst);
        !           543:
        !           544:        /* XXX - Allow some tolerance here? */
        !           545:        if (real_bps != bps)
        !           546:                return (EINVAL);
        !           547:
        !           548:        cs->cs_preg[12] = tconst;
        !           549:        cs->cs_preg[13] = tconst >> 8;
        !           550:
        !           551:        /* Caller will stuff the pending registers. */
        !           552:        return (0);
        !           553: }
        !           554:
        !           555: int
        !           556: zs_set_modes(cs, cflag)
        !           557:        struct zs_chanstate *cs;
        !           558:        int cflag;      /* bits per second */
        !           559: {
        !           560:        int s;
        !           561:
        !           562:        /*
        !           563:         * Output hardware flow control on the chip is horrendous:
        !           564:         * if carrier detect drops, the receiver is disabled, and if
        !           565:         * CTS drops, the transmitter is stoped IN MID CHARACTER!
        !           566:         * Therefore, NEVER set the HFC bit, and instead use the
        !           567:         * status interrupt to detect CTS changes.
        !           568:         */
        !           569:        s = splzs();
        !           570:        cs->cs_rr0_pps = 0;
        !           571:        if ((cflag & (CLOCAL | MDMBUF)) != 0) {
        !           572:                cs->cs_rr0_dcd = 0;
        !           573:                if ((cflag & MDMBUF) == 0)
        !           574:                        cs->cs_rr0_pps = ZSRR0_DCD;
        !           575:        } else
        !           576:                cs->cs_rr0_dcd = ZSRR0_DCD;
        !           577:        if ((cflag & CRTSCTS) != 0) {
        !           578:                cs->cs_wr5_dtr = ZSWR5_DTR;
        !           579:                cs->cs_wr5_rts = ZSWR5_RTS;
        !           580:                cs->cs_rr0_cts = ZSRR0_CTS;
        !           581: #if 0 /* JLW */
        !           582:        } else if ((cflag & CDTRCTS) != 0) {
        !           583:                cs->cs_wr5_dtr = 0;
        !           584:                cs->cs_wr5_rts = ZSWR5_DTR;
        !           585:                cs->cs_rr0_cts = ZSRR0_CTS;
        !           586: #endif
        !           587:        } else if ((cflag & MDMBUF) != 0) {
        !           588:                cs->cs_wr5_dtr = 0;
        !           589:                cs->cs_wr5_rts = ZSWR5_DTR;
        !           590:                cs->cs_rr0_cts = ZSRR0_DCD;
        !           591:        } else {
        !           592:                cs->cs_wr5_dtr = ZSWR5_DTR | ZSWR5_RTS;
        !           593:                cs->cs_wr5_rts = 0;
        !           594:                cs->cs_rr0_cts = 0;
        !           595:        }
        !           596:        splx(s);
        !           597:
        !           598:        /* Caller will stuff the pending registers. */
        !           599:        return (0);
        !           600: }
        !           601:
        !           602:
        !           603: /*
        !           604:  * Read or write the chip with suitable delays.
        !           605:  */
        !           606:
        !           607: u_char
        !           608: zs_read_reg(cs, reg)
        !           609:        struct zs_chanstate *cs;
        !           610:        u_char reg;
        !           611: {
        !           612:        u_char val;
        !           613:
        !           614:        *cs->cs_reg_csr = reg;
        !           615:        ZS_DELAY();
        !           616:        val = *cs->cs_reg_csr;
        !           617:        ZS_DELAY();
        !           618:        return val;
        !           619: }
        !           620:
        !           621: void
        !           622: zs_write_reg(cs, reg, val)
        !           623:        struct zs_chanstate *cs;
        !           624:        u_char reg, val;
        !           625: {
        !           626:        *cs->cs_reg_csr = reg;
        !           627:        ZS_DELAY();
        !           628:        *cs->cs_reg_csr = val;
        !           629:        ZS_DELAY();
        !           630: }
        !           631:
        !           632: u_char zs_read_csr(cs)
        !           633:        struct zs_chanstate *cs;
        !           634: {
        !           635:        register u_char val;
        !           636:
        !           637:        val = *cs->cs_reg_csr;
        !           638:        ZS_DELAY();
        !           639:        return val;
        !           640: }
        !           641:
        !           642: void  zs_write_csr(cs, val)
        !           643:        struct zs_chanstate *cs;
        !           644:        u_char val;
        !           645: {
        !           646:        *cs->cs_reg_csr = val;
        !           647:        ZS_DELAY();
        !           648: }
        !           649:
        !           650: u_char zs_read_data(cs)
        !           651:        struct zs_chanstate *cs;
        !           652: {
        !           653:        register u_char val;
        !           654:
        !           655:        val = *cs->cs_reg_data;
        !           656:        ZS_DELAY();
        !           657:        return val;
        !           658: }
        !           659:
        !           660: void  zs_write_data(cs, val)
        !           661:        struct zs_chanstate *cs;
        !           662:        u_char val;
        !           663: {
        !           664:        *cs->cs_reg_data = val;
        !           665:        ZS_DELAY();
        !           666: }
        !           667:
        !           668: #ifdef SUN4M
        !           669: /*
        !           670:  * Power management hooks for zsopen() and zsclose().
        !           671:  * We use them to power on/off the ports on the Tadpole SPARCbook machines
        !           672:  * (on other sun4m machines, this is a no-op).
        !           673:  */
        !           674:
        !           675: /*
        !           676:  * Since the serial power control is global, we need to remember which channels
        !           677:  * have their ports open, so as not to power off when closing one channel if
        !           678:  * both were open. Simply xor'ing the zs_chanstate pointers is enough to let us
        !           679:  * know if the serial lines are used or not.
        !           680:  */
        !           681: static vaddr_t zs_sb_enable = 0;
        !           682:
        !           683: int
        !           684: zs_enable(struct zs_chanstate *cs)
        !           685: {
        !           686:        if (cs->enabled == 0) {
        !           687:                if (zs_sb_enable == 0)
        !           688:                        sb_auxregbisc(1, AUXIO2_SERIAL, 0);
        !           689:                zs_sb_enable ^= (vaddr_t)cs;
        !           690:                cs->enabled = 1;
        !           691:        }
        !           692:        return (0);
        !           693: }
        !           694:
        !           695: void
        !           696: zs_disable(struct zs_chanstate *cs)
        !           697: {
        !           698:        if (cs->enabled != 0) {
        !           699:                cs->enabled = 0;
        !           700:                zs_sb_enable ^= (vaddr_t)cs;
        !           701:                if (zs_sb_enable == 0)
        !           702:                        sb_auxregbisc(1, 0, AUXIO2_SERIAL);
        !           703:        }
        !           704: }
        !           705:
        !           706: #endif /* SUN4M */
        !           707:
        !           708: /****************************************************************
        !           709:  * Console support functions (Sun specific!)
        !           710:  * Note: this code is allowed to know about the layout of
        !           711:  * the chip registers, and uses that to keep things simple.
        !           712:  * XXX - I think I like the mvme167 code better. -gwr
        !           713:  ****************************************************************/
        !           714:
        !           715: extern void Debugger(void);
        !           716: void *zs_conschan;
        !           717:
        !           718: /*
        !           719:  * Handle user request to enter kernel debugger.
        !           720:  */
        !           721: void
        !           722: zs_abort(cs)
        !           723:        struct zs_chanstate *cs;
        !           724: {
        !           725:        volatile struct zschan *zc = zs_conschan;
        !           726:        int rr0;
        !           727:
        !           728:        /* Wait for end of break to avoid PROM abort. */
        !           729:        /* XXX - Limit the wait? */
        !           730:        do {
        !           731:                rr0 = zc->zc_csr;
        !           732:                ZS_DELAY();
        !           733:        } while (rr0 & ZSRR0_BREAK);
        !           734:
        !           735: #if defined(KGDB)
        !           736:        zskgdb(cs);
        !           737: #elif defined(DDB)
        !           738:        {
        !           739:                extern int db_active;
        !           740:
        !           741:                if (!db_active)
        !           742:                        Debugger();
        !           743:                else
        !           744:                        /* Debugger is probably hosed */
        !           745:                        callrom();
        !           746:        }
        !           747: #else
        !           748:        printf("stopping on keyboard abort\n");
        !           749:        callrom();
        !           750: #endif
        !           751: }
        !           752:
        !           753: /*
        !           754:  * Polled input char.
        !           755:  */
        !           756: int
        !           757: zs_getc(arg)
        !           758:        void *arg;
        !           759: {
        !           760:        volatile struct zschan *zc = arg;
        !           761:        int s, c, rr0;
        !           762:
        !           763:        s = splhigh();
        !           764:        /* Wait for a character to arrive. */
        !           765:        do {
        !           766:                rr0 = zc->zc_csr;
        !           767:                ZS_DELAY();
        !           768:        } while ((rr0 & ZSRR0_RX_READY) == 0);
        !           769:
        !           770:        c = zc->zc_data;
        !           771:        ZS_DELAY();
        !           772:        splx(s);
        !           773:
        !           774:        return (c);
        !           775: }
        !           776:
        !           777: /*
        !           778:  * Polled output char.
        !           779:  */
        !           780: void
        !           781: zs_putc(arg, c)
        !           782:        void *arg;
        !           783:        int c;
        !           784: {
        !           785:        volatile struct zschan *zc = arg;
        !           786:        int s, rr0;
        !           787:
        !           788:        s = splhigh();
        !           789:        /* Wait for transmitter to become ready. */
        !           790:        do {
        !           791:                rr0 = zc->zc_csr;
        !           792:                ZS_DELAY();
        !           793:        } while ((rr0 & ZSRR0_TX_READY) == 0);
        !           794:
        !           795:        /*
        !           796:         * Send the next character.
        !           797:         * Now you'd think that this could be followed by a ZS_DELAY()
        !           798:         * just like all the other chip accesses, but it turns out that
        !           799:         * the `transmit-ready' interrupt isn't de-asserted until
        !           800:         * some period of time after the register write completes
        !           801:         * (more than a couple instructions).  So to avoid stray
        !           802:         * interrupts we put in the 2us delay regardless of cpu model.
        !           803:         */
        !           804:         zc->zc_data = c;
        !           805:         delay(2);
        !           806:
        !           807:        splx(s);
        !           808: }
        !           809:
        !           810: /*****************************************************************/
        !           811:
        !           812: cons_decl(zs);
        !           813:
        !           814: /*
        !           815:  * Console table shared by ttya, ttyb
        !           816:  */
        !           817: struct consdev consdev_tty = {
        !           818:        zscnprobe,
        !           819:        zscninit,
        !           820:        zscngetc,
        !           821:        zscnputc,
        !           822:        zscnpollc,
        !           823: };
        !           824:
        !           825: int zstty_unit;        /* set in consinit() */
        !           826:
        !           827: void
        !           828: zscnprobe(cn)
        !           829:        struct consdev *cn;
        !           830: {
        !           831:        cn->cn_dev = makedev(zs_major, zstty_unit);
        !           832:        cn->cn_pri = CN_REMOTE;
        !           833: }
        !           834:
        !           835: void
        !           836: zscninit(cn)
        !           837:        struct consdev *cn;
        !           838: {
        !           839: }
        !           840:
        !           841: /*
        !           842:  * Polled console input putchar.
        !           843:  */
        !           844: int
        !           845: zscngetc(dev)
        !           846:        dev_t dev;
        !           847: {
        !           848:        return (zs_getc(zs_conschan));
        !           849: }
        !           850:
        !           851: /*
        !           852:  * Polled console output putchar.
        !           853:  */
        !           854: void
        !           855: zscnputc(dev, c)
        !           856:        dev_t dev;
        !           857:        int c;
        !           858: {
        !           859:        zs_putc(zs_conschan, c);
        !           860: }
        !           861:
        !           862: int swallow_zsintrs;
        !           863:
        !           864: void
        !           865: zscnpollc(dev, on)
        !           866:        dev_t dev;
        !           867:        int on;
        !           868: {
        !           869:        /*
        !           870:         * Need to tell zs driver to acknowledge all interrupts or we get
        !           871:         * annoying spurious interrupt messages.  This is because mucking
        !           872:         * with spl() levels during polling does not prevent interrupts from
        !           873:         * being generated.
        !           874:         */
        !           875:
        !           876:        if (on) swallow_zsintrs++;
        !           877:        else swallow_zsintrs--;
        !           878: }
        !           879:
        !           880: /*****************************************************************/
        !           881:
        !           882: #if defined(SUN4) || defined(SUN4C) || defined(SUN4M)
        !           883:
        !           884: cons_decl(prom);
        !           885:
        !           886: /*
        !           887:  * The console is set to this one initially,
        !           888:  * which lets us use the PROM until consinit()
        !           889:  * is called to select a real console.
        !           890:  */
        !           891: struct consdev consdev_prom = {
        !           892:        promcnprobe,
        !           893:        promcninit,
        !           894:        promcngetc,
        !           895:        promcnputc,
        !           896:        nullcnpollc,
        !           897: };
        !           898:
        !           899: /*
        !           900:  * The console table pointer is statically initialized
        !           901:  * to point to the PROM (output only) table, so that
        !           902:  * early calls to printf will work.
        !           903:  */
        !           904: struct consdev *cn_tab = &consdev_prom;
        !           905:
        !           906: void
        !           907: promcnprobe(cn)
        !           908:        struct consdev *cn;
        !           909: {
        !           910:        cn->cn_dev = makedev(0, 0);
        !           911:        cn->cn_pri = CN_INTERNAL;
        !           912: }
        !           913:
        !           914: void
        !           915: promcninit(cn)
        !           916:        struct consdev *cn;
        !           917: {
        !           918: }
        !           919:
        !           920: /*
        !           921:  * PROM console input putchar.
        !           922:  */
        !           923: int
        !           924: promcngetc(dev)
        !           925:        dev_t dev;
        !           926: {
        !           927:        int s, c;
        !           928:
        !           929:        if (promvec->pv_romvec_vers > 2) {
        !           930:                int n = 0;
        !           931:                unsigned char c0;
        !           932:
        !           933:                s = splhigh();
        !           934:                while (n <= 0) {
        !           935:                        n = (*promvec->pv_v2devops.v2_read)
        !           936:                                (*promvec->pv_v2bootargs.v2_fd0, &c0, 1);
        !           937:                }
        !           938:                splx(s);
        !           939:
        !           940:                c = c0;
        !           941:        } else {
        !           942: #if defined(SUN4)
        !           943:                /* SUN4 PROM: must turn off local echo */
        !           944:                extern struct om_vector *oldpvec;
        !           945:                int saveecho = 0;
        !           946: #endif
        !           947:                s = splhigh();
        !           948: #if defined(SUN4)
        !           949:                if (CPU_ISSUN4) {
        !           950:                        saveecho = *(oldpvec->echo);
        !           951:                        *(oldpvec->echo) = 0;
        !           952:                }
        !           953: #endif
        !           954:                c = (*promvec->pv_getchar)();
        !           955: #if defined(SUN4)
        !           956:                if (CPU_ISSUN4)
        !           957:                        *(oldpvec->echo) = saveecho;
        !           958: #endif
        !           959:                splx(s);
        !           960:        }
        !           961:
        !           962:        if (c == '\r')
        !           963:                c = '\n';
        !           964:
        !           965:        return (c);
        !           966: }
        !           967:
        !           968: /*
        !           969:  * PROM console output putchar.
        !           970:  */
        !           971: void
        !           972: promcnputc(dev, c)
        !           973:        dev_t dev;
        !           974:        int c;
        !           975: {
        !           976:        int s;
        !           977:        char c0 = (c & 0x7f);
        !           978:
        !           979:        s = splhigh();
        !           980:        if (promvec->pv_romvec_vers > 2)
        !           981:                (*promvec->pv_v2devops.v2_write)
        !           982:                        (*promvec->pv_v2bootargs.v2_fd1, &c0, 1);
        !           983:        else
        !           984:                (*promvec->pv_putchar)(c);
        !           985:        splx(s);
        !           986: }
        !           987:
        !           988: #endif /* SUN4 || SUN4C || SUN4M */
        !           989:
        !           990: /*****************************************************************/
        !           991:
        !           992: #if 0
        !           993: extern struct consdev consdev_kd;
        !           994: #endif
        !           995:
        !           996: char *prom_inSrc_name[] = {
        !           997:        "keyboard/display",
        !           998:        "ttya", "ttyb",
        !           999:        "ttyc", "ttyd" };
        !          1000:
        !          1001: /*
        !          1002:  * This function replaces sys/dev/cninit.c
        !          1003:  * Determine which device is the console using
        !          1004:  * the PROM "input source" and "output sink".
        !          1005:  */
        !          1006: void
        !          1007: consinit()
        !          1008: {
        !          1009:        struct zschan *zc;
        !          1010:        struct consdev *console = cn_tab;
        !          1011:        int channel, zs_unit;
        !          1012:        int inSource, outSink;
        !          1013:
        !          1014: #if defined(SUN4) || defined(SUN4C) || defined(SUN4M)
        !          1015:        if (promvec->pv_romvec_vers > 2) {
        !          1016:                /* We need to probe the PROM device tree */
        !          1017:                int node,fd;
        !          1018:                char buffer[128];
        !          1019:                struct nodeops *no;
        !          1020:                struct v2devops *op;
        !          1021:                char *cp;
        !          1022:                extern int fbnode;
        !          1023:
        !          1024:                inSource = outSink = -1;
        !          1025:                no = promvec->pv_nodeops;
        !          1026:                op = &promvec->pv_v2devops;
        !          1027:
        !          1028:                node = findroot();
        !          1029:                if (no->no_proplen(node, "stdin-path") >= sizeof(buffer)) {
        !          1030:                        printf("consinit: increase buffer size and recompile\n");
        !          1031:                        goto setup_output;
        !          1032:                }
        !          1033:                /* XXX: fix above */
        !          1034:
        !          1035:                no->no_getprop(node, "stdin-path",buffer);
        !          1036:
        !          1037:                /*
        !          1038:                 * Open an "instance" of this device.
        !          1039:                 * You'd think it would be appropriate to call v2_close()
        !          1040:                 * on the handle when we're done with it. But that seems
        !          1041:                 * to cause the device to shut down somehow; for the moment,
        !          1042:                 * we simply leave it open...
        !          1043:                 */
        !          1044:                if ((fd = op->v2_open(buffer)) == 0 ||
        !          1045:                     (node = op->v2_fd_phandle(fd)) == 0) {
        !          1046:                        printf("consinit: bogus stdin path %s.\n",buffer);
        !          1047:                        goto setup_output;
        !          1048:                }
        !          1049:                if (no->no_proplen(node,"keyboard") >= 0) {
        !          1050:                        inSource = PROMDEV_KBD;
        !          1051:                        goto setup_output;
        !          1052:                }
        !          1053:                if (strcmp(getpropstring(node,"device_type"),"serial") != 0) {
        !          1054:                        /* not a serial, not keyboard. what is it?!? */
        !          1055:                        inSource = -1;
        !          1056:                        goto setup_output;
        !          1057:                }
        !          1058:                /*
        !          1059:                 * At this point we assume the device path is in the form
        !          1060:                 *   ....device@x,y:a for ttya and ...device@x,y:b for ttyb.
        !          1061:                 * If it isn't, we defer to the ROM
        !          1062:                 */
        !          1063:                cp = buffer;
        !          1064:                while (*cp)
        !          1065:                    cp++;
        !          1066:                cp -= 2;
        !          1067: #ifdef DEBUG
        !          1068:                if (cp < buffer)
        !          1069:                    panic("consinit: bad stdin path %s",buffer);
        !          1070: #endif
        !          1071:                /* XXX: only allows tty's a->z, assumes PROMDEV_TTYx contig */
        !          1072:                if (cp[0]==':' && cp[1] >= 'a' && cp[1] <= 'z')
        !          1073:                    inSource = PROMDEV_TTYA + (cp[1] - 'a');
        !          1074:                /* else use rom */
        !          1075: setup_output:
        !          1076:                node = findroot();
        !          1077:                if (no->no_proplen(node, "stdout-path") >= sizeof(buffer)) {
        !          1078:                        printf("consinit: increase buffer size and recompile\n");
        !          1079:                        goto setup_console;
        !          1080:                }
        !          1081:                /* XXX: fix above */
        !          1082:
        !          1083:                no->no_getprop(node, "stdout-path", buffer);
        !          1084:
        !          1085:                if ((fd = op->v2_open(buffer)) == 0 ||
        !          1086:                     (node = op->v2_fd_phandle(fd)) == 0) {
        !          1087:                        printf("consinit: bogus stdout path %s.\n",buffer);
        !          1088:                        goto setup_output;
        !          1089:                }
        !          1090:                if (strcmp(getpropstring(node,"device_type"),"display") == 0) {
        !          1091:                        /* frame buffer output */
        !          1092:                        outSink = PROMDEV_SCREEN;
        !          1093:                        fbnode = node;
        !          1094:                } else if (strcmp(getpropstring(node,"device_type"), "serial")
        !          1095:                           != 0) {
        !          1096:                        /* not screen, not serial. Whatzit? */
        !          1097:                        outSink = -1;
        !          1098:                } else { /* serial console. which? */
        !          1099:                        /*
        !          1100:                         * At this point we assume the device path is in the
        !          1101:                         * form:
        !          1102:                         * ....device@x,y:a for ttya, etc.
        !          1103:                         * If it isn't, we defer to the ROM
        !          1104:                         */
        !          1105:                        cp = buffer;
        !          1106:                        while (*cp)
        !          1107:                            cp++;
        !          1108:                        cp -= 2;
        !          1109: #ifdef DEBUG
        !          1110:                        if (cp < buffer)
        !          1111:                                panic("consinit: bad stdout path %s",buffer);
        !          1112: #endif
        !          1113:                        /* XXX: only allows tty's a->z, assumes PROMDEV_TTYx contig */
        !          1114:                        if (cp[0]==':' && cp[1] >= 'a' && cp[1] <= 'z')
        !          1115:                            outSink = PROMDEV_TTYA + (cp[1] - 'a');
        !          1116:                        else outSink = -1;
        !          1117:                }
        !          1118:        } else {
        !          1119:                inSource = *promvec->pv_stdin;
        !          1120:                outSink  = *promvec->pv_stdout;
        !          1121:        }
        !          1122: #endif /* SUN4 || SUN4C || SUN4M */
        !          1123: #ifdef solbourne
        !          1124:        if (CPU_ISKAP) {
        !          1125:                const char *dev;
        !          1126:
        !          1127:                inSource = PROMDEV_TTYA;        /* default */
        !          1128:                dev = prom_getenv(ENV_INPUTDEVICE);
        !          1129:                if (dev != NULL) {
        !          1130:                        if (strcmp(dev, "ttyb") == 0)
        !          1131:                                inSource = PROMDEV_TTYB;
        !          1132:                        if (strcmp(dev, "keyboard") == 0)
        !          1133:                                inSource = PROMDEV_KBD;
        !          1134:                }
        !          1135:
        !          1136:                outSink = PROMDEV_TTYA; /* default */
        !          1137:                dev = prom_getenv(ENV_OUTPUTDEVICE);
        !          1138:                if (dev != NULL) {
        !          1139:                        if (strcmp(dev, "ttyb") == 0)
        !          1140:                                outSink = PROMDEV_TTYB;
        !          1141:                        if (strcmp(dev, "screen") == 0)
        !          1142:                                outSink = PROMDEV_SCREEN;
        !          1143:                }
        !          1144:        }
        !          1145: #endif
        !          1146:
        !          1147: #if defined(SUN4) || defined(SUN4C) || defined(SUN4M)
        !          1148: setup_console:
        !          1149: #endif
        !          1150:
        !          1151:        if (inSource != outSink) {
        !          1152:                printf("cninit: mismatched PROM output selector\n");
        !          1153:        }
        !          1154:
        !          1155:        switch (inSource) {
        !          1156:        default:
        !          1157:                printf("cninit: invalid inSource=%d\n", inSource);
        !          1158:                callrom();
        !          1159:                inSource = PROMDEV_KBD;
        !          1160:                /* FALLTHROUGH */
        !          1161:
        !          1162:        case PROMDEV_KBD: /* keyboard/display */
        !          1163: #if NZSKBD > 0
        !          1164:                zs_unit = 1;
        !          1165:                channel = 0;
        !          1166:                break;
        !          1167: #else  /* NZSKBD */
        !          1168:                printf("cninit: kdb/display not configured\n");
        !          1169:                callrom();
        !          1170:                inSource = PROMDEV_TTYA;
        !          1171:                /* FALLTHROUGH */
        !          1172: #endif /* NZSKBD */
        !          1173:
        !          1174:        case PROMDEV_TTYA:
        !          1175:        case PROMDEV_TTYB:
        !          1176:                zstty_unit = inSource - PROMDEV_TTYA;
        !          1177:                zs_unit = 0;
        !          1178:                channel = zstty_unit & 1;
        !          1179:                console = &consdev_tty;
        !          1180:                break;
        !          1181:
        !          1182:        }
        !          1183:        /* Now that inSource has been validated, print it. */
        !          1184:        printf("console is %s\n", prom_inSrc_name[inSource]);
        !          1185:
        !          1186:        zc = zs_get_chan_addr(zs_unit, channel);
        !          1187:        if (zc == NULL) {
        !          1188:                printf("cninit: zs not mapped.\n");
        !          1189:                return;
        !          1190:        }
        !          1191:        zs_conschan = zc;
        !          1192:        zs_hwflags[zs_unit][channel] = ZS_HWFLAG_CONSOLE;
        !          1193:        /* switch to selected console */
        !          1194:        cn_tab = console;
        !          1195:        (*cn_tab->cn_probe)(cn_tab);
        !          1196:        (*cn_tab->cn_init)(cn_tab);
        !          1197: #ifdef KGDB
        !          1198:        zs_kgdb_init();
        !          1199: #endif
        !          1200: }

CVSweb