[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

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