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

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

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

CVSweb