[BACK]Return to scc.c CVS log [TXT][DIR] Up to [local] / sys / arch / alpha / tc

Annotation of sys/arch/alpha/tc/scc.c, Revision 1.1

1.1     ! nbrk        1: /* $OpenBSD: scc.c,v 1.20 2004/09/19 21:34:42 mickey Exp $ */
        !             2: /* $NetBSD: scc.c,v 1.58 2002/03/17 19:40:27 atatat Exp $ */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 1991,1990,1989,1994,1995,1996 Carnegie Mellon University
        !             6:  * All Rights Reserved.
        !             7:  *
        !             8:  * Permission to use, copy, modify and distribute this software and its
        !             9:  * documentation is hereby granted, provided that both the copyright
        !            10:  * notice and this permission notice appear in all copies of the
        !            11:  * software, derivative works or modified versions, and any portions
        !            12:  * thereof, and that both notices appear in supporting documentation.
        !            13:  *
        !            14:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
        !            15:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
        !            16:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
        !            17:  *
        !            18:  * Carnegie Mellon requests users of this software to return to
        !            19:  *
        !            20:  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
        !            21:  *  School of Computer Science
        !            22:  *  Carnegie Mellon University
        !            23:  *  Pittsburgh PA 15213-3890
        !            24:  *
        !            25:  * any improvements or extensions that they make and grant Carnegie the
        !            26:  * rights to redistribute these changes.
        !            27:  */
        !            28:
        !            29: /*-
        !            30:  * Copyright (c) 1992, 1993
        !            31:  *     The Regents of the University of California.  All rights reserved.
        !            32:  *
        !            33:  * This code is derived from software contributed to Berkeley by
        !            34:  * Ralph Campbell and Rick Macklem.
        !            35:  *
        !            36:  * Redistribution and use in source and binary forms, with or without
        !            37:  * modification, are permitted provided that the following conditions
        !            38:  * are met:
        !            39:  * 1. Redistributions of source code must retain the above copyright
        !            40:  *    notice, this list of conditions and the following disclaimer.
        !            41:  * 2. Redistributions in binary form must reproduce the above copyright
        !            42:  *    notice, this list of conditions and the following disclaimer in the
        !            43:  *    documentation and/or other materials provided with the distribution.
        !            44:  * 3. Neither the name of the University nor the names of its contributors
        !            45:  *    may be used to endorse or promote products derived from this software
        !            46:  *    without specific prior written permission.
        !            47:  *
        !            48:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            49:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            50:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            51:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            52:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            53:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            54:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            55:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            56:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            57:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            58:  * SUCH DAMAGE.
        !            59:  *
        !            60:  *     @(#)scc.c       8.2 (Berkeley) 11/30/93
        !            61:  */
        !            62:
        !            63: /*
        !            64:  * Intel 82530 dual usart chip driver. Supports the serial port(s) on the
        !            65:  * Personal DECstation 5000/xx and DECstation 5000/1xx, plus the keyboard
        !            66:  * and mouse on the 5000/1xx. (Don't ask me where the A channel signals
        !            67:  * are on the 5000/xx.)
        !            68:  *
        !            69:  * See: Intel MicroCommunications Handbook, Section 2, pg. 155-173, 1992.
        !            70:  */
        !            71: #include <sys/param.h>
        !            72: #include <sys/systm.h>
        !            73: #include <sys/ioctl.h>
        !            74: #include <sys/tty.h>
        !            75: #include <sys/proc.h>
        !            76: #include <sys/buf.h>
        !            77: #include <sys/file.h>
        !            78: #include <sys/uio.h>
        !            79: #include <sys/kernel.h>
        !            80: #include <sys/syslog.h>
        !            81: #include <sys/device.h>
        !            82:
        !            83: #include <dev/cons.h>
        !            84:
        !            85: #include <dev/ic/z8530reg.h>
        !            86: #include <alpha/tc/sccreg.h>
        !            87: #include <alpha/tc/sccvar.h>
        !            88:
        !            89: #include <machine/rpb.h>
        !            90: #include <machine/conf.h>
        !            91:
        !            92: #include <dev/tc/tcvar.h>
        !            93: #include <dev/tc/ioasicreg.h>
        !            94: #include <dev/tc/ioasicvar.h>
        !            95:
        !            96: #undef SCCDEV
        !            97: #define        SCCDEV          15                      /* XXX */
        !            98:
        !            99: #define raster_console() 1     /* Treat test for cn_screen as true */
        !           100: #define CONSOLE_ON_UNIT(unit) 0        /* No raster console on Alphas */
        !           101:
        !           102: #define        NSCCLINE        (NSCC*2)
        !           103: #define        SCCUNIT(dev)    (minor(dev) >> 1)
        !           104: #define        SCCLINE(dev)    (minor(dev) & 0x1)
        !           105:
        !           106: #ifdef DEBUG
        !           107: int    debugChar;
        !           108: #endif
        !           109:
        !           110: struct scc_softc {
        !           111:        struct device sc_dv;
        !           112:        struct pdma scc_pdma[2];
        !           113:        struct {
        !           114:                u_char  wr1;
        !           115:                u_char  wr3;
        !           116:                u_char  wr4;
        !           117:                u_char  wr5;
        !           118:                u_char  wr14;
        !           119:        } scc_wreg[2];
        !           120:        struct tty *scc_tty[2];
        !           121:        int     scc_softCAR;
        !           122:
        !           123:        int scc_flags[2];
        !           124: #define SCC_CHAN_NEEDSDELAY    0x01    /* sw must delay 1.6us between output*/
        !           125: #define SCC_CHAN_NOMODEM       0x02    /* don't touch modem ctl lines (may
        !           126:                                           be left floating or x-wired */
        !           127: #define SCC_CHAN_MODEM_CROSSED 0x04    /* modem lines wired to other channel*/
        !           128: #define SCC_CHAN_KBDLINE       0x08    /* XXX special-case keyboard lines */
        !           129: };
        !           130:
        !           131: /*
        !           132:  * BRG formula is:
        !           133:  *                             ClockFrequency
        !           134:  *     BRGconstant =   ---------------------------  -  2
        !           135:  *                     2 * BaudRate * ClockDivider
        !           136:  *
        !           137:  * Speed selections with Pclk=7.3728MHz, clock x16
        !           138:  */
        !           139: const struct speedtab sccspeedtab[] = {
        !           140:        { 0,            0,      },
        !           141:        { 50,           4606,   },
        !           142:        { 75,           3070,   },
        !           143:        { 110,          2093,   },
        !           144:        { 134.5,        1711,   },
        !           145:        { 150,          1534,   },
        !           146:        { 200,          1150,   },
        !           147:        { 300,          766,    },
        !           148:        { 600,          382,    },
        !           149:        { 1200,         190,    },
        !           150:        { 1800,         126,    },
        !           151:        { 2400,         94,     },
        !           152:        { 4800,         46,     },
        !           153:        { 7200,         30,     },      /* non-POSIX */
        !           154:        { 9600,         22,     },
        !           155:        { 14400,        14,     },      /* non-POSIX */
        !           156:        { 19200,        10,     },
        !           157:        { 28800,        6,      },      /* non-POSIX */
        !           158:        { 38400,        4,      },      /* non-POSIX */
        !           159:        { 57600,        2,      },      /* non-POSIX */
        !           160:        { -1,           -1,     },
        !           161: };
        !           162:
        !           163: #ifndef        PORTSELECTOR
        !           164: #define        ISPEED  TTYDEF_SPEED
        !           165: #define        LFLAG   TTYDEF_LFLAG
        !           166: #else
        !           167: #define        ISPEED  B4800
        !           168: #define        LFLAG   (TTYDEF_LFLAG & ~ECHO)
        !           169: #endif
        !           170:
        !           171: /* Definition of the driver for autoconfig. */
        !           172: int    sccmatch(struct device *, void *, void *);
        !           173: void   sccattach(struct device *, struct device *, void *);
        !           174:
        !           175: struct cfattach scc_ca = {
        !           176:        sizeof (struct scc_softc), sccmatch, sccattach,
        !           177: };
        !           178:
        !           179: struct cfdriver scc_cd = {
        !           180:        NULL, "scc", DV_TTY,
        !           181: };
        !           182:
        !           183: cdev_decl(scc);
        !           184:
        !           185: int            sccGetc(dev_t);
        !           186: void           sccPutc(dev_t, int);
        !           187: void           sccPollc(dev_t, int);
        !           188: int            sccparam(struct tty *, struct termios *);
        !           189: void           sccstart(struct tty *);
        !           190:
        !           191: int    sccmctl(struct scc_softc *, int, int, int);
        !           192: int    cold_sccparam(struct tty *, struct termios *,
        !           193:                    struct scc_softc *sc, int line);
        !           194:
        !           195: #ifdef SCC_DEBUG
        !           196: void   rr(char *, scc_regmap_t *);
        !           197: #endif
        !           198: void   scc_modem_intr(dev_t);
        !           199: void   sccreset(struct scc_softc *);
        !           200:
        !           201: int    sccintr(void *);
        !           202: void   scc_alphaintr(int);
        !           203:
        !           204: /*
        !           205:  * console variables, for using serial console while still cold and
        !           206:  * autoconfig has not attached the scc device.
        !           207:  */
        !           208: scc_regmap_t *scc_cons_addr = 0;
        !           209: struct consdev scccons = {
        !           210:        NULL, NULL, sccGetc, sccPutc, sccPollc, NULL, NODEV, 0
        !           211: };
        !           212:
        !           213: /*
        !           214:  * Test to see if device is present.
        !           215:  * Return true if found.
        !           216:  */
        !           217: int
        !           218: sccmatch(parent, vcf, aux)
        !           219:        struct device *parent;
        !           220:        void *vcf, *aux;
        !           221: {
        !           222:        extern struct cfdriver ioasic_cd;               /* XXX */
        !           223:        struct ioasicdev_attach_args *d = aux;
        !           224:        struct cfdata *cf = vcf;
        !           225:        void *sccaddr;
        !           226:
        !           227:        if (parent->dv_cfdata->cf_driver != &ioasic_cd) {
        !           228: #ifdef DIAGNOSTIC
        !           229:                printf("Cannot attach scc on %s\n", parent->dv_xname);
        !           230: #endif
        !           231:                return (0);
        !           232:        }
        !           233:
        !           234:        /* Make sure that we're looking for this type of device. */
        !           235:        if ((strncmp(d->iada_modname, "z8530   ", TC_ROM_LLEN) != 0) &&
        !           236:            (strncmp(d->iada_modname, "scc", TC_ROM_LLEN)!= 0))
        !           237:                return (0);
        !           238:
        !           239:        /*
        !           240:         * Check user-specified offset against the ioasic offset.
        !           241:         * Allow it to be wildcarded.
        !           242:         */
        !           243:        if (cf->cf_loc[0] != -1 &&
        !           244:            cf->cf_loc[0] != d->iada_offset)
        !           245:                return (0);
        !           246:
        !           247:        /* Get the address, and check it for validity. */
        !           248:        sccaddr = (void *)d->iada_addr;
        !           249: #ifdef SPARSE
        !           250:        sccaddr = (void *)TC_DENSE_TO_SPARSE((tc_addr_t)sccaddr);
        !           251: #endif
        !           252:        if (badaddr(sccaddr, 2))
        !           253:                return (0);
        !           254:
        !           255:        return (1);
        !           256: }
        !           257:
        !           258: /*
        !           259:  * Enable ioasic SCC interrupts and scc DMA engine interrupts.
        !           260:  * XXX does not really belong here.
        !           261:  */
        !           262: void
        !           263: scc_alphaintr(onoff)
        !           264:        int onoff;
        !           265: {
        !           266:        if (onoff) {
        !           267:                *(volatile u_int *)(ioasic_base + IOASIC_IMSK) |=
        !           268:                    IOASIC_INTR_SCC_1 | IOASIC_INTR_SCC_0;
        !           269: #if !defined(DEC_3000_300) && defined(SCC_DMA)
        !           270:                *(volatile u_int *)(ioasic_base + IOASIC_CSR) |=
        !           271:                    IOASIC_CSR_DMAEN_T1 | IOASIC_CSR_DMAEN_R1 |
        !           272:                    IOASIC_CSR_DMAEN_T2 | IOASIC_CSR_DMAEN_R2;
        !           273: #endif
        !           274:        } else {
        !           275:                *(volatile u_int *)(ioasic_base + IOASIC_IMSK) &=
        !           276:                    ~(IOASIC_INTR_SCC_1 | IOASIC_INTR_SCC_0);
        !           277: #if !defined(DEC_3000_300) && defined(SCC_DMA)
        !           278:                *(volatile u_int *)(ioasic_base + IOASIC_CSR) &=
        !           279:                    ~(IOASIC_CSR_DMAEN_T1 | IOASIC_CSR_DMAEN_R1 |
        !           280:                    IOASIC_CSR_DMAEN_T2 | IOASIC_CSR_DMAEN_R2);
        !           281: #endif
        !           282:        }
        !           283:        tc_mb();
        !           284: }
        !           285:
        !           286: void
        !           287: sccattach(parent, self, aux)
        !           288:        struct device *parent;
        !           289:        struct device *self;
        !           290:        void *aux;
        !           291: {
        !           292:        struct scc_softc *sc = (struct scc_softc *)self;
        !           293:        struct ioasicdev_attach_args *d = aux;
        !           294:        struct pdma *pdp;
        !           295:        struct tty *tp;
        !           296:        void *sccaddr;
        !           297:        int cntr;
        !           298:        struct termios cterm;
        !           299:        struct tty ctty;
        !           300:        int s;
        !           301:        int unit;
        !           302:
        !           303:        unit = sc->sc_dv.dv_unit;
        !           304:
        !           305:        /* Get the address, and check it for validity. */
        !           306:        sccaddr = (void *)d->iada_addr;
        !           307: #ifdef SPARSE
        !           308:        sccaddr = (void *)TC_DENSE_TO_SPARSE((tc_addr_t)sccaddr);
        !           309: #endif
        !           310:
        !           311:        /* Register the interrupt handler. */
        !           312:        ioasic_intr_establish(parent, d->iada_cookie, TC_IPL_TTY,
        !           313:            sccintr, (void *)sc);
        !           314:
        !           315:        /*
        !           316:         * For a remote console, wait a while for previous output to
        !           317:         * complete.
        !           318:         */
        !           319:        if ((cputype == ST_DEC_3000_500 && sc->sc_dv.dv_unit == 1) ||
        !           320:            (cputype == ST_DEC_3000_300 && sc->sc_dv.dv_unit == 0))
        !           321:                DELAY(10000);
        !           322:        pdp = &sc->scc_pdma[0];
        !           323:
        !           324:        /* init pseudo DMA structures */
        !           325:        for (cntr = 0; cntr < 2; cntr++) {
        !           326:                pdp->p_addr = (void *)sccaddr;
        !           327:                tp = sc->scc_tty[cntr] = ttymalloc();
        !           328:                pdp->p_arg = (long)tp;
        !           329:                pdp->p_fcn = (void (*)(struct tty*))0;
        !           330:                tp->t_dev = (dev_t)((sc->sc_dv.dv_unit << 1) | cntr);
        !           331:                pdp++;
        !           332:        }
        !           333:        /* What's the warning here? Defaulting to softCAR on line 2? */
        !           334:        sc->scc_softCAR = sc->sc_dv.dv_cfdata->cf_flags | 0x2;  /* XXX */
        !           335:
        !           336:        /* reset chip, initialize  register-copies in softc */
        !           337:        sccreset(sc);
        !           338:
        !           339:        /*
        !           340:         * Special handling for consoles.
        !           341:         */
        !           342:        if (1 /* SCCUNIT(cn_tab.cn_dev) == sc->sc_dv.dv_unit */) {
        !           343:                s = spltty();
        !           344:                cterm.c_cflag = (TTYDEF_CFLAG & ~(CSIZE | PARENB)) | CS8;
        !           345:                cterm.c_ospeed = cterm.c_ispeed = 9600;
        !           346:                (void) cold_sccparam(&ctty, &cterm, sc,
        !           347:                    SCCLINE((sc->sc_dv.dv_unit == 0) ?
        !           348:                            SCCCOMM2_PORT : SCCCOMM3_PORT));
        !           349:                DELAY(1000);
        !           350:                splx(s);
        !           351:        }
        !           352:
        !           353:        /*
        !           354:         * XXX
        !           355:         * Unit 1 is the remote console, wire it up now.
        !           356:         */
        !           357:        if ((cputype == ST_DEC_3000_500 && sc->sc_dv.dv_unit == 1) ||
        !           358:            (cputype == ST_DEC_3000_300 && sc->sc_dv.dv_unit == 0)) {
        !           359:                if (alpha_donot_kludge_scc)
        !           360:                        printf("\nSWITCHING TO SERIAL CONSOLE!\n");
        !           361:                cn_tab = &scccons;
        !           362:                cn_tab->cn_dev = makedev(SCCDEV, sc->sc_dv.dv_unit * 2);
        !           363:
        !           364:                printf("%s console\n", alpha_donot_kludge_scc ? "\n***" : ":");
        !           365:
        !           366:                /* wire carrier for console. */
        !           367:                sc->scc_softCAR |= SCCLINE(cn_tab->cn_dev);
        !           368:        } else
        !           369:                printf("\n");
        !           370: }
        !           371:
        !           372: /*
        !           373:  * Reset the chip.
        !           374:  */
        !           375: void
        !           376: sccreset(sc)
        !           377:        register struct scc_softc *sc;
        !           378: {
        !           379:        register scc_regmap_t *regs;
        !           380:        register u_char val;
        !           381:
        !           382:        regs = (scc_regmap_t *)sc->scc_pdma[0].p_addr;
        !           383:        /*
        !           384:         * Chip once-only initialization
        !           385:         *
        !           386:         * NOTE: The wiring we assume is the one on the 3min:
        !           387:         *
        !           388:         *      out     A-TxD   -->     TxD     keybd or mouse
        !           389:         *      in      A-RxD   -->     RxD     keybd or mouse
        !           390:         *      out     A-DTR~  -->     DTR     comm
        !           391:         *      out     A-RTS~  -->     RTS     comm
        !           392:         *      in      A-CTS~  -->     SI      comm
        !           393:         *      in      A-DCD~  -->     RI      comm
        !           394:         *      in      A-SYNCH~-->     DSR     comm
        !           395:         *      out     B-TxD   -->     TxD     comm
        !           396:         *      in      B-RxD   -->     RxD     comm
        !           397:         *      in      B-RxC   -->     TRxCB   comm
        !           398:         *      in      B-TxC   -->     RTxCB   comm
        !           399:         *      out     B-RTS~  -->     SS      comm
        !           400:         *      in      B-CTS~  -->     CTS     comm
        !           401:         *      in      B-DCD~  -->     CD      comm
        !           402:         */
        !           403:        SCC_INIT_REG(regs, SCC_CHANNEL_A);
        !           404:        SCC_INIT_REG(regs, SCC_CHANNEL_B);
        !           405:
        !           406:        SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR9, ZSWR9_HARD_RESET);
        !           407:        DELAY(50000);   /*enough ? */
        !           408:        SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR9, 0);
        !           409:
        !           410:        /* program the interrupt vector */
        !           411:        SCC_WRITE_REG(regs, SCC_CHANNEL_A, ZSWR_IVEC, 0xf0);
        !           412:        SCC_WRITE_REG(regs, SCC_CHANNEL_B, ZSWR_IVEC, 0xf0);
        !           413:        SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR9, ZSWR9_VECTOR_INCL_STAT);
        !           414:
        !           415:        /* receive parameters and control */
        !           416:        sc->scc_wreg[SCC_CHANNEL_A].wr3 = 0;
        !           417:        sc->scc_wreg[SCC_CHANNEL_B].wr3 = 0;
        !           418:
        !           419:        /* timing base defaults */
        !           420:        sc->scc_wreg[SCC_CHANNEL_A].wr4 = ZSWR4_CLK_X16;
        !           421:        sc->scc_wreg[SCC_CHANNEL_B].wr4 = ZSWR4_CLK_X16;
        !           422:
        !           423:        /* enable DTR, RTS and SS */
        !           424:        sc->scc_wreg[SCC_CHANNEL_B].wr5 = 0;
        !           425:        sc->scc_wreg[SCC_CHANNEL_A].wr5 = ZSWR5_RTS | ZSWR5_DTR;
        !           426:
        !           427:        /* baud rates */
        !           428:        val = ZSWR14_BAUD_ENA | ZSWR14_BAUD_FROM_PCLK;
        !           429:        sc->scc_wreg[SCC_CHANNEL_B].wr14 = val;
        !           430:        sc->scc_wreg[SCC_CHANNEL_A].wr14 = val;
        !           431:
        !           432:        /* interrupt conditions */
        !           433:        val =   ZSWR1_RIE | ZSWR1_PE_SC | ZSWR1_SIE | ZSWR1_TIE;
        !           434:        sc->scc_wreg[SCC_CHANNEL_A].wr1 = val;
        !           435:        sc->scc_wreg[SCC_CHANNEL_B].wr1 = val;
        !           436: }
        !           437:
        !           438: int
        !           439: sccopen(dev, flag, mode, p)
        !           440:        dev_t dev;
        !           441:        int flag, mode;
        !           442:        struct proc *p;
        !           443: {
        !           444:        register struct scc_softc *sc;
        !           445:        register struct tty *tp;
        !           446:        register int unit, line;
        !           447:        int s, error = 0;
        !           448:        int firstopen = 0;
        !           449:
        !           450:        unit = SCCUNIT(dev);
        !           451:        if (unit >= scc_cd.cd_ndevs)
        !           452:                return (ENXIO);
        !           453:        sc = scc_cd.cd_devs[unit];
        !           454:        if (!sc)
        !           455:                return (ENXIO);
        !           456:
        !           457:        line = SCCLINE(dev);
        !           458:        if (sc->scc_pdma[line].p_addr == NULL)
        !           459:                return (ENXIO);
        !           460:        tp = sc->scc_tty[line];
        !           461:        if (tp == NULL) {
        !           462:                tp = sc->scc_tty[line] = ttymalloc();
        !           463:        }
        !           464:        tp->t_oproc = sccstart;
        !           465:        tp->t_param = sccparam;
        !           466:        tp->t_dev = dev;
        !           467:        if ((tp->t_state & TS_ISOPEN) == 0) {
        !           468:                ttychars(tp);
        !           469:                firstopen = 1;
        !           470: #ifndef PORTSELECTOR
        !           471:                if (tp->t_ispeed == 0) {
        !           472: #endif
        !           473:                        tp->t_iflag = TTYDEF_IFLAG;
        !           474:                        tp->t_oflag = TTYDEF_OFLAG;
        !           475:                        tp->t_cflag = TTYDEF_CFLAG;
        !           476:                        tp->t_lflag = LFLAG;
        !           477:                        tp->t_ispeed = tp->t_ospeed = ISPEED;
        !           478: #ifdef PORTSELECTOR
        !           479:                        tp->t_cflag |= HUPCL;
        !           480: #else
        !           481:                }
        !           482: #endif
        !           483:                (void) sccparam(tp, &tp->t_termios);
        !           484:                ttsetwater(tp);
        !           485:        } else if ((tp->t_state & TS_XCLUDE) && curproc->p_ucred->cr_uid != 0)
        !           486:                return (EBUSY);
        !           487:        (void) sccmctl(sc, SCCLINE(dev), DML_DTR, DMSET);
        !           488:        s = spltty();
        !           489:        while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) &&
        !           490:            !(tp->t_state & TS_CARR_ON)) {
        !           491:                tp->t_state |= TS_WOPEN;
        !           492:                error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
        !           493:                    ttopen, 0);
        !           494:                tp->t_state &= ~TS_WOPEN;
        !           495:                if (error != 0)
        !           496:                        break;
        !           497:        }
        !           498:        splx(s);
        !           499:        if (error)
        !           500:                return (error);
        !           501:        error = (*linesw[tp->t_line].l_open)(dev, tp);
        !           502:
        !           503:        return (error);
        !           504: }
        !           505:
        !           506: /*ARGSUSED*/
        !           507: int
        !           508: sccclose(dev, flag, mode, p)
        !           509:        dev_t dev;
        !           510:        int flag, mode;
        !           511:        struct proc *p;
        !           512: {
        !           513:        register struct scc_softc *sc = scc_cd.cd_devs[SCCUNIT(dev)];
        !           514:        register struct tty *tp;
        !           515:        register int line;
        !           516:
        !           517:        line = SCCLINE(dev);
        !           518:        tp = sc->scc_tty[line];
        !           519:        if (sc->scc_wreg[line].wr5 & ZSWR5_BREAK) {
        !           520:                sc->scc_wreg[line].wr5 &= ~ZSWR5_BREAK;
        !           521:                ttyoutput(0, tp);
        !           522:        }
        !           523:        (*linesw[tp->t_line].l_close)(tp, flag);
        !           524:        if ((tp->t_cflag & HUPCL) || (tp->t_state & TS_WOPEN) ||
        !           525:            !(tp->t_state & TS_ISOPEN))
        !           526:                (void) sccmctl(sc, line, 0, DMSET);
        !           527:        return (ttyclose(tp));
        !           528: }
        !           529:
        !           530: int
        !           531: sccread(dev, uio, flag)
        !           532:        dev_t dev;
        !           533:        struct uio *uio;
        !           534:        int flag;
        !           535: {
        !           536:        register struct scc_softc *sc;
        !           537:        register struct tty *tp;
        !           538:
        !           539:        sc = scc_cd.cd_devs[SCCUNIT(dev)];              /* XXX*/
        !           540:        tp = sc->scc_tty[SCCLINE(dev)];
        !           541:        return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
        !           542: }
        !           543:
        !           544: int
        !           545: sccwrite(dev, uio, flag)
        !           546:        dev_t dev;
        !           547:        struct uio *uio;
        !           548:        int flag;
        !           549: {
        !           550:        register struct scc_softc *sc;
        !           551:        register struct tty *tp;
        !           552:
        !           553:        sc = scc_cd.cd_devs[SCCUNIT(dev)];      /* XXX*/
        !           554:        tp = sc->scc_tty[SCCLINE(dev)];
        !           555:        return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
        !           556: }
        !           557:
        !           558: struct tty *
        !           559: scctty(dev)
        !           560:        dev_t dev;
        !           561: {
        !           562:        register struct scc_softc *sc;
        !           563:        register struct tty *tp;
        !           564:        register int unit = SCCUNIT(dev);
        !           565:
        !           566:        if ((unit >= scc_cd.cd_ndevs) || (sc = scc_cd.cd_devs[unit]) == 0)
        !           567:                return (0);
        !           568:        tp = sc->scc_tty[SCCLINE(dev)];
        !           569:        return (tp);
        !           570: }
        !           571:
        !           572: /*ARGSUSED*/
        !           573: int
        !           574: sccioctl(dev, cmd, data, flag, p)
        !           575:        dev_t dev;
        !           576:        u_long cmd;
        !           577:        caddr_t data;
        !           578:        int flag;
        !           579:        struct proc *p;
        !           580: {
        !           581:        register struct scc_softc *sc;
        !           582:        register struct tty *tp;
        !           583:        int error, line;
        !           584:
        !           585:        line = SCCLINE(dev);
        !           586:        sc = scc_cd.cd_devs[SCCUNIT(dev)];
        !           587:        tp = sc->scc_tty[line];
        !           588:        error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
        !           589:        if (error >= 0)
        !           590:                return (error);
        !           591:        error = ttioctl(tp, cmd, data, flag, p);
        !           592:        if (error >= 0)
        !           593:                return (error);
        !           594:
        !           595:        switch (cmd) {
        !           596:
        !           597:        case TIOCSBRK:
        !           598:                sc->scc_wreg[line].wr5 |= ZSWR5_BREAK;
        !           599:                ttyoutput(0, tp);
        !           600:                break;
        !           601:
        !           602:        case TIOCCBRK:
        !           603:                sc->scc_wreg[line].wr5 &= ~ZSWR5_BREAK;
        !           604:                ttyoutput(0, tp);
        !           605:                break;
        !           606:
        !           607:        case TIOCSDTR:
        !           608:                (void) sccmctl(sc, line, DML_DTR|DML_RTS, DMBIS);
        !           609:                break;
        !           610:
        !           611:        case TIOCCDTR:
        !           612:                (void) sccmctl(sc, line, DML_DTR|DML_RTS, DMBIC);
        !           613:                break;
        !           614:
        !           615:        case TIOCMSET:
        !           616:                (void) sccmctl(sc, line, *(int *)data, DMSET);
        !           617:                break;
        !           618:
        !           619:        case TIOCMBIS:
        !           620:                (void) sccmctl(sc, line, *(int *)data, DMBIS);
        !           621:                break;
        !           622:
        !           623:        case TIOCMBIC:
        !           624:                (void) sccmctl(sc, line, *(int *)data, DMBIC);
        !           625:                break;
        !           626:
        !           627:        case TIOCMGET:
        !           628:                *(int *)data = sccmctl(sc, line, 0, DMGET);
        !           629:                break;
        !           630:
        !           631:        default:
        !           632:                return (ENOTTY);
        !           633:        }
        !           634:        return (0);
        !           635: }
        !           636:
        !           637:
        !           638:
        !           639: /*
        !           640:  * Set line parameters --  tty t_param entry point.
        !           641:  */
        !           642: int
        !           643: sccparam(tp, t)
        !           644:        register struct tty *tp;
        !           645:        register struct termios *t;
        !           646: {
        !           647:        register struct scc_softc *sc;
        !           648:
        !           649:        /* Extract the softc and call cold_sccparam to do all the work. */
        !           650:        sc = scc_cd.cd_devs[SCCUNIT(tp->t_dev)];
        !           651:        return cold_sccparam(tp, t, sc, SCCLINE(tp->t_dev));
        !           652: }
        !           653:
        !           654:
        !           655: /*
        !           656:  * Do what sccparam() (t_param entry point) does, but callable when cold.
        !           657:  */
        !           658: int
        !           659: cold_sccparam(tp, t, sc, line)
        !           660:        register struct tty *tp;
        !           661:        register struct termios *t;
        !           662:        register struct scc_softc *sc;
        !           663:        register int line;
        !           664: {
        !           665:        register scc_regmap_t *regs;
        !           666:        register u_char value, wvalue;
        !           667:        register int cflag = t->c_cflag;
        !           668:        int ospeed;
        !           669:
        !           670:        /* Check arguments */
        !           671:        if (t->c_ispeed && t->c_ispeed != t->c_ospeed)
        !           672:                return (EINVAL);
        !           673:        ospeed = ttspeedtab(t->c_ospeed, sccspeedtab);
        !           674:        if (ospeed < 0)
        !           675:                return (EINVAL);
        !           676:        /* and copy to tty */
        !           677:        tp->t_ispeed = t->c_ispeed;
        !           678:        tp->t_ospeed = t->c_ospeed;
        !           679:        tp->t_cflag = cflag;
        !           680:
        !           681:        /*
        !           682:         * Handle console specially.
        !           683:         */
        !           684:        {
        !           685:                cflag = CS8;
        !           686:                ospeed = ttspeedtab(9600, sccspeedtab);
        !           687:        }
        !           688:        if (ospeed == 0) {
        !           689:                (void) sccmctl(sc, line, 0, DMSET);     /* hang up line */
        !           690:                return (0);
        !           691:        }
        !           692:
        !           693:        regs = (scc_regmap_t *)sc->scc_pdma[line].p_addr;
        !           694:
        !           695:        /*
        !           696:         * pmax driver used to reset the SCC here. That reset causes the
        !           697:         * other channel on the SCC to drop outpur chars: at least that's
        !           698:         * what CGD reports for the Alpha.  It's a bug.
        !           699:         */
        !           700: #if 0
        !           701:        /* reset line */
        !           702:        if (line == SCC_CHANNEL_A)
        !           703:                value = ZSWR9_A_RESET;
        !           704:        else
        !           705:                value = ZSWR9_B_RESET;
        !           706:        SCC_WRITE_REG(regs, line, SCC_WR9, value);
        !           707:        DELAY(25);
        !           708: #endif
        !           709:
        !           710:        /* stop bits, normally 1 */
        !           711:        value = sc->scc_wreg[line].wr4 & 0xf0;
        !           712:        if (cflag & CSTOPB)
        !           713:                value |= ZSWR4_TWOSB;
        !           714:        else
        !           715:                value |= ZSWR4_ONESB;
        !           716:        if ((cflag & PARODD) == 0)
        !           717:                value |= ZSWR4_EVENP;
        !           718:        if (cflag & PARENB)
        !           719:                value |= ZSWR4_PARENB;
        !           720:
        !           721:        /* set it now, remember it must be first after reset */
        !           722:        sc->scc_wreg[line].wr4 = value;
        !           723:        SCC_WRITE_REG(regs, line, SCC_WR4, value);
        !           724:
        !           725:        /* vector again */
        !           726:        SCC_WRITE_REG(regs, line, ZSWR_IVEC, 0xf0);
        !           727:
        !           728:        /* clear break, keep rts dtr */
        !           729:        wvalue = sc->scc_wreg[line].wr5 & (ZSWR5_DTR|ZSWR5_RTS);
        !           730:        switch (cflag & CSIZE) {
        !           731:        case CS5:
        !           732:                value = ZSWR3_RX_5;
        !           733:                wvalue |= ZSWR5_TX_5;
        !           734:                break;
        !           735:        case CS6:
        !           736:                value = ZSWR3_RX_6;
        !           737:                wvalue |= ZSWR5_TX_6;
        !           738:                break;
        !           739:        case CS7:
        !           740:                value = ZSWR3_RX_7;
        !           741:                wvalue |= ZSWR5_TX_7;
        !           742:                break;
        !           743:        case CS8:
        !           744:        default:
        !           745:                value = ZSWR3_RX_8;
        !           746:                wvalue |= ZSWR5_TX_8;
        !           747:        };
        !           748:        sc->scc_wreg[line].wr3 = value;
        !           749:        SCC_WRITE_REG(regs, line, SCC_WR3, value);
        !           750:
        !           751:        sc->scc_wreg[line].wr5 = wvalue;
        !           752:        SCC_WRITE_REG(regs, line, SCC_WR5, wvalue);
        !           753:
        !           754:        /*
        !           755:         * XXX Does the SCC chip require us to refresh the WR5 register
        !           756:         * for the other channel after writing the other, or not?
        !           757:         */
        !           758: #ifdef notdef
        !           759:        /* XXX */
        !           760:        {
        !           761:        int otherline = (line + 1) & 1;
        !           762:        SCC_WRITE_REG(regs, otherline, SCC_WR5, sc->scc_wreg[otherline].wr5);
        !           763:        }
        !           764: #endif
        !           765:
        !           766:        SCC_WRITE_REG(regs, line, ZSWR_SYNCLO, 0);
        !           767:        SCC_WRITE_REG(regs, line, ZSWR_SYNCHI, 0);
        !           768:        SCC_WRITE_REG(regs, line, SCC_WR9, ZSWR9_VECTOR_INCL_STAT);
        !           769:        SCC_WRITE_REG(regs, line, SCC_WR10, 0);
        !           770:        value = ZSWR11_RXCLK_BAUD | ZSWR11_TXCLK_BAUD |
        !           771:                ZSWR11_TRXC_OUT_ENA | ZSWR11_TRXC_BAUD;
        !           772:        SCC_WRITE_REG(regs, line, SCC_WR11, value);
        !           773:        SCC_SET_TIMING_BASE(regs, line, ospeed);
        !           774:        value = sc->scc_wreg[line].wr14;
        !           775:        SCC_WRITE_REG(regs, line, SCC_WR14, value);
        !           776:
        !           777:        if (sc->sc_dv.dv_unit == 1) {
        !           778:                /* On unit one, on the flamingo, modem control is floating! */
        !           779:                value = ZSWR15_BREAK_IE;
        !           780:        } else
        !           781:        {
        !           782:                value = ZSWR15_BREAK_IE | ZSWR15_CTS_IE | ZSWR15_DCD_IE;
        !           783:        }
        !           784:        SCC_WRITE_REG(regs, line, SCC_WR15, value);
        !           785:
        !           786:        /* and now the enables */
        !           787:        value = sc->scc_wreg[line].wr3 | ZSWR3_RX_ENABLE;
        !           788:        SCC_WRITE_REG(regs, line, SCC_WR3, value);
        !           789:        value = sc->scc_wreg[line].wr5 | ZSWR5_TX_ENABLE;
        !           790:        sc->scc_wreg[line].wr5 = value;
        !           791:        SCC_WRITE_REG(regs, line, SCC_WR5, value);
        !           792:
        !           793:        /* master inter enable */
        !           794:        value = ZSWR9_MASTER_IE | ZSWR9_VECTOR_INCL_STAT;
        !           795:        SCC_WRITE_REG(regs, line, SCC_WR9, value);
        !           796:        SCC_WRITE_REG(regs, line, SCC_WR1, sc->scc_wreg[line].wr1);
        !           797:        tc_mb();
        !           798:
        !           799:        scc_alphaintr(1);                       /* XXX XXX XXX */
        !           800:
        !           801:        return (0);
        !           802: }
        !           803:
        !           804:
        !           805: /*
        !           806:  * Check for interrupts from all devices.
        !           807:  */
        !           808: int
        !           809: sccintr(xxxsc)
        !           810:        void *xxxsc;
        !           811: {
        !           812:        register struct scc_softc *sc = (struct scc_softc *)xxxsc;
        !           813:        register int unit = (long)sc->sc_dv.dv_unit;
        !           814:        register scc_regmap_t *regs;
        !           815:        register struct tty *tp;
        !           816:        register struct pdma *dp;
        !           817:        register int cc, chan, rr1, rr2, rr3;
        !           818:        int overrun = 0;
        !           819:
        !           820:        rr1 = 0;                /* shut up gcc -Wall */
        !           821:        regs = (scc_regmap_t *)sc->scc_pdma[0].p_addr;
        !           822:        unit <<= 1;
        !           823:        for (;;) {
        !           824:            SCC_READ_REG(regs, SCC_CHANNEL_B, ZSRR_IVEC, rr2);
        !           825:            rr2 = SCC_RR2_STATUS(rr2);
        !           826:            /* are we done yet ? */
        !           827:            if (rr2 == 6) {     /* strange, distinguished value */
        !           828:                SCC_READ_REG(regs, SCC_CHANNEL_A, ZSRR_IPEND, rr3);
        !           829:                if (rr3 == 0)
        !           830:                        return 1;
        !           831:            }
        !           832:
        !           833:            SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_RR0, ZSWR0_CLR_INTR);
        !           834:            if ((rr2 == SCC_RR2_A_XMIT_DONE) || (rr2 == SCC_RR2_B_XMIT_DONE)) {
        !           835:                chan = (rr2 == SCC_RR2_A_XMIT_DONE) ?
        !           836:                        SCC_CHANNEL_A : SCC_CHANNEL_B;
        !           837:                tp = sc->scc_tty[chan];
        !           838:                dp = &sc->scc_pdma[chan];
        !           839:                if (dp->p_mem < dp->p_end) {
        !           840:                        SCC_WRITE_DATA(regs, chan, *dp->p_mem++);
        !           841:                        tc_mb();
        !           842:                } else {
        !           843:                        tp->t_state &= ~TS_BUSY;
        !           844:                        if (tp->t_state & TS_FLUSH)
        !           845:                                tp->t_state &= ~TS_FLUSH;
        !           846:                        else {
        !           847:                                ndflush(&tp->t_outq, dp->p_mem -
        !           848:                                        (caddr_t) tp->t_outq.c_cf);
        !           849:                                dp->p_end = dp->p_mem = tp->t_outq.c_cf;
        !           850:                        }
        !           851:                        (*linesw[tp->t_line].l_start)(tp);
        !           852:                        if (tp->t_outq.c_cc == 0 || !(tp->t_state & TS_BUSY)) {
        !           853:                                SCC_READ_REG(regs, chan, SCC_RR15, cc);
        !           854:                                cc &= ~ZSWR15_TXUEOM_IE;
        !           855:                                SCC_WRITE_REG(regs, chan, SCC_WR15, cc);
        !           856:                                cc = sc->scc_wreg[chan].wr1 & ~ZSWR1_TIE;
        !           857:                                SCC_WRITE_REG(regs, chan, SCC_WR1, cc);
        !           858:                                sc->scc_wreg[chan].wr1 = cc;
        !           859:                                tc_mb();
        !           860:                        }
        !           861:                }
        !           862:            } else if (rr2 == SCC_RR2_A_RECV_DONE ||
        !           863:                rr2 == SCC_RR2_B_RECV_DONE || rr2 == SCC_RR2_A_RECV_SPECIAL ||
        !           864:                rr2 == SCC_RR2_B_RECV_SPECIAL) {
        !           865:                if (rr2 == SCC_RR2_A_RECV_DONE || rr2 == SCC_RR2_A_RECV_SPECIAL)
        !           866:                        chan = SCC_CHANNEL_A;
        !           867:                else
        !           868:                        chan = SCC_CHANNEL_B;
        !           869:                tp = sc->scc_tty[chan];
        !           870:                SCC_READ_DATA(regs, chan, cc);
        !           871:                if (rr2 == SCC_RR2_A_RECV_SPECIAL ||
        !           872:                        rr2 == SCC_RR2_B_RECV_SPECIAL) {
        !           873:                        SCC_READ_REG(regs, chan, SCC_RR1, rr1);
        !           874:                        SCC_WRITE_REG(regs, chan, SCC_RR0, ZSWR0_RESET_ERRORS);
        !           875:                        if ((rr1 & ZSRR1_DO) && overrun == 0) {
        !           876:                                log(LOG_WARNING, "scc%d,%d: silo overflow\n",
        !           877:                                        unit >> 1, chan);
        !           878:                                overrun = 1;
        !           879:                        }
        !           880:                }
        !           881:
        !           882:                if (!(tp->t_state & TS_ISOPEN)) {
        !           883:                        wakeup((caddr_t)&tp->t_rawq);
        !           884: #ifdef PORTSELECTOR
        !           885:                        if (!(tp->t_state & TS_WOPEN))
        !           886: #endif
        !           887:                                continue;
        !           888:                }
        !           889:                if (rr2 == SCC_RR2_A_RECV_SPECIAL ||
        !           890:                        rr2 == SCC_RR2_B_RECV_SPECIAL) {
        !           891:                        if (rr1 & ZSRR1_PE)
        !           892:                                cc |= TTY_PE;
        !           893:                        if (rr1 & ZSRR1_FE)
        !           894:                                cc |= TTY_FE;
        !           895:                }
        !           896:                (*linesw[tp->t_line].l_rint)(cc, tp);
        !           897:            } else if ((rr2 == SCC_RR2_A_EXT_STATUS) || (rr2 == SCC_RR2_B_EXT_STATUS)) {
        !           898:                chan = (rr2 == SCC_RR2_A_EXT_STATUS) ?
        !           899:                    SCC_CHANNEL_A : SCC_CHANNEL_B;
        !           900:                SCC_WRITE_REG(regs, chan, SCC_RR0, ZSWR0_RESET_STATUS);
        !           901:                scc_modem_intr(unit | chan);
        !           902:            }
        !           903:        }
        !           904:        return 0;       /* XXX */
        !           905: }
        !           906:
        !           907: void
        !           908: sccstart(tp)
        !           909:        register struct tty *tp;
        !           910: {
        !           911:        register struct pdma *dp;
        !           912:        register scc_regmap_t *regs;
        !           913:        register struct scc_softc *sc;
        !           914:        register int cc, chan;
        !           915:        u_char temp;
        !           916:        int s, sendone;
        !           917:
        !           918:        sc = scc_cd.cd_devs[SCCUNIT(tp->t_dev)];
        !           919:        dp = &sc->scc_pdma[SCCLINE(tp->t_dev)];
        !           920:        regs = (scc_regmap_t *)dp->p_addr;
        !           921:        s = spltty();
        !           922:        if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
        !           923:                goto out;
        !           924:        if (tp->t_outq.c_cc <= tp->t_lowat) {
        !           925:                if (tp->t_state & TS_ASLEEP) {
        !           926:                        tp->t_state &= ~TS_ASLEEP;
        !           927:                        wakeup((caddr_t)&tp->t_outq);
        !           928:                }
        !           929:                selwakeup(&tp->t_wsel);
        !           930:        }
        !           931:        if (tp->t_outq.c_cc == 0)
        !           932:                goto out;
        !           933:        /* handle console specially */
        !           934:        if (tp == scctty(makedev(SCCDEV,SCCKBD_PORT)) && raster_console()) {
        !           935:                while (tp->t_outq.c_cc > 0) {
        !           936:                        cc = getc(&tp->t_outq) & 0x7f;
        !           937:                        cnputc(cc);
        !           938:                }
        !           939:                /*
        !           940:                 * After we flush the output queue we may need to wake
        !           941:                 * up the process that made the output.
        !           942:                 */
        !           943:                if (tp->t_outq.c_cc <= tp->t_lowat) {
        !           944:                        if (tp->t_state & TS_ASLEEP) {
        !           945:                                tp->t_state &= ~TS_ASLEEP;
        !           946:                                wakeup((caddr_t)&tp->t_outq);
        !           947:                        }
        !           948:                        selwakeup(&tp->t_wsel);
        !           949:                }
        !           950:                goto out;
        !           951:        }
        !           952:        cc = ndqb(&tp->t_outq, 0);
        !           953:
        !           954:        tp->t_state |= TS_BUSY;
        !           955:        dp->p_end = dp->p_mem = tp->t_outq.c_cf;
        !           956:        dp->p_end += cc;
        !           957:
        !           958:        /*
        !           959:         * Enable transmission and send the first char, as required.
        !           960:         */
        !           961:        chan = SCCLINE(tp->t_dev);
        !           962:        SCC_READ_REG(regs, chan, SCC_RR0, temp);
        !           963:        sendone = (temp & ZSRR0_TX_READY);
        !           964:        SCC_READ_REG(regs, chan, SCC_RR15, temp);
        !           965:        temp |= ZSWR15_TXUEOM_IE;
        !           966:        SCC_WRITE_REG(regs, chan, SCC_WR15, temp);
        !           967:        temp = sc->scc_wreg[chan].wr1 | ZSWR1_TIE;
        !           968:        SCC_WRITE_REG(regs, chan, SCC_WR1, temp);
        !           969:        sc->scc_wreg[chan].wr1 = temp;
        !           970:        if (sendone) {
        !           971: #ifdef DIAGNOSTIC
        !           972:                if (cc == 0)
        !           973:                        panic("sccstart: No chars");
        !           974: #endif
        !           975:                SCC_WRITE_DATA(regs, chan, *dp->p_mem++);
        !           976:        }
        !           977:        tc_mb();
        !           978: out:
        !           979:        splx(s);
        !           980: }
        !           981:
        !           982: /*
        !           983:  * Stop output on a line.
        !           984:  */
        !           985: /*ARGSUSED*/
        !           986: int
        !           987: sccstop(tp, flag)
        !           988:        register struct tty *tp;
        !           989:        int flag;
        !           990: {
        !           991:        register struct pdma *dp;
        !           992:        register struct scc_softc *sc;
        !           993:        register int s;
        !           994:
        !           995:        sc = scc_cd.cd_devs[SCCUNIT(tp->t_dev)];
        !           996:        dp = &sc->scc_pdma[SCCLINE(tp->t_dev)];
        !           997:        s = spltty();
        !           998:        if (tp->t_state & TS_BUSY) {
        !           999:                dp->p_end = dp->p_mem;
        !          1000:                if (!(tp->t_state & TS_TTSTOP))
        !          1001:                        tp->t_state |= TS_FLUSH;
        !          1002:        }
        !          1003:        splx(s);
        !          1004:        return 0;
        !          1005: }
        !          1006:
        !          1007: int
        !          1008: sccmctl(sc, line, bits, how)
        !          1009:        struct scc_softc *sc;
        !          1010:        int line, bits, how;
        !          1011: {
        !          1012:        register scc_regmap_t *regs;
        !          1013:        register int mbits;
        !          1014:        register u_char value;
        !          1015:        int s;
        !          1016:
        !          1017:        regs = (scc_regmap_t *)sc->scc_pdma[line].p_addr;
        !          1018:        s = spltty();
        !          1019:        /*
        !          1020:         * only channel B has modem control, however the DTR and RTS
        !          1021:         * pins on the comm port are wired to the DTR and RTS A channel
        !          1022:         * signals.
        !          1023:         */
        !          1024:        mbits = DML_DTR | DML_DSR | DML_CAR;
        !          1025:        if (line == SCC_CHANNEL_B) {
        !          1026:                if (sc->scc_wreg[SCC_CHANNEL_A].wr5 & ZSWR5_DTR)
        !          1027:                        mbits = DML_DTR | DML_DSR;
        !          1028:                else
        !          1029:                        mbits = 0;
        !          1030:                SCC_READ_REG_ZERO(regs, SCC_CHANNEL_B, value);
        !          1031:                if (value & ZSRR0_DCD)
        !          1032:                        mbits |= DML_CAR;
        !          1033:        }
        !          1034:        switch (how) {
        !          1035:        case DMSET:
        !          1036:                mbits = bits;
        !          1037:                break;
        !          1038:
        !          1039:        case DMBIS:
        !          1040:                mbits |= bits;
        !          1041:                break;
        !          1042:
        !          1043:        case DMBIC:
        !          1044:                mbits &= ~bits;
        !          1045:                break;
        !          1046:
        !          1047:        case DMGET:
        !          1048:                (void) splx(s);
        !          1049:                return (mbits);
        !          1050:        }
        !          1051:        if (line == SCC_CHANNEL_B) {
        !          1052:                if (mbits & DML_DTR)
        !          1053:                        sc->scc_wreg[SCC_CHANNEL_A].wr5 |= ZSWR5_DTR;
        !          1054:                else
        !          1055:                        sc->scc_wreg[SCC_CHANNEL_A].wr5 &= ~ZSWR5_DTR;
        !          1056:                SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR5,
        !          1057:                        sc->scc_wreg[SCC_CHANNEL_A].wr5);
        !          1058:        }
        !          1059:        if ((mbits & DML_DTR) || (sc->scc_softCAR & (1 << line)))
        !          1060:                sc->scc_tty[line]->t_state |= TS_CARR_ON;
        !          1061:        (void) splx(s);
        !          1062:        return (mbits);
        !          1063: }
        !          1064:
        !          1065: /*
        !          1066:  * Check for carrier transition.
        !          1067:  */
        !          1068: void
        !          1069: scc_modem_intr(dev)
        !          1070:        dev_t dev;
        !          1071: {
        !          1072:        register scc_regmap_t *regs;
        !          1073:        register struct scc_softc *sc;
        !          1074:        register struct tty *tp;
        !          1075:        register int car, chan;
        !          1076:        register u_char value;
        !          1077:        int s;
        !          1078:
        !          1079:        chan = SCCLINE(dev);
        !          1080:        sc = scc_cd.cd_devs[SCCUNIT(dev)];
        !          1081:        tp = sc->scc_tty[chan];
        !          1082:        regs = (scc_regmap_t *)sc->scc_pdma[chan].p_addr;
        !          1083:        if (chan == SCC_CHANNEL_A)
        !          1084:                return;
        !          1085:        s = spltty();
        !          1086:        if (sc->scc_softCAR & (1 << chan))
        !          1087:                car = 1;
        !          1088:        else {
        !          1089:                SCC_READ_REG_ZERO(regs, chan, value);
        !          1090:                car = value & ZSRR0_DCD;
        !          1091:        }
        !          1092:
        !          1093:        /* Break on serial console drops into the debugger */
        !          1094:        if ((value & ZSRR0_BREAK) && CONSOLE_ON_UNIT(sc->sc_dv.dv_unit)) {
        !          1095: #ifdef DDB
        !          1096:                splx(s);                /* spl0()? */
        !          1097:                Debugger();
        !          1098:                return;
        !          1099: #else
        !          1100:                /* XXX maybe fall back to PROM? */
        !          1101: #endif
        !          1102:        }
        !          1103:
        !          1104:        splx(s);
        !          1105: }
        !          1106:
        !          1107: /*
        !          1108:  * Get a char off the appropriate line via. a busy wait loop.
        !          1109:  */
        !          1110: int
        !          1111: sccGetc(dev)
        !          1112:        dev_t dev;
        !          1113: {
        !          1114:        register scc_regmap_t *regs;
        !          1115:        register int c, line;
        !          1116:        register u_char value;
        !          1117:        int s;
        !          1118:
        !          1119:        line = SCCLINE(dev);
        !          1120:        if (cold && scc_cons_addr) {
        !          1121:                regs = scc_cons_addr;
        !          1122:        } else {
        !          1123:                register struct scc_softc *sc;
        !          1124:                sc = scc_cd.cd_devs[SCCUNIT(dev)];
        !          1125:                regs = (scc_regmap_t *)sc->scc_pdma[line].p_addr;
        !          1126:        }
        !          1127:
        !          1128:        if (!regs)
        !          1129:                return (0);
        !          1130:        s = splhigh();
        !          1131:        for (;;) {
        !          1132:                SCC_READ_REG(regs, line, SCC_RR0, value);
        !          1133:                if (value & ZSRR0_RX_READY) {
        !          1134:                        SCC_READ_REG(regs, line, SCC_RR1, value);
        !          1135:                        SCC_READ_DATA(regs, line, c);
        !          1136:                        if (value & (ZSRR1_PE | ZSRR1_DO | ZSRR1_FE)) {
        !          1137:                                SCC_WRITE_REG(regs, line, SCC_WR0,
        !          1138:                                    ZSWR0_RESET_ERRORS);
        !          1139:                                SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR0,
        !          1140:                                    ZSWR0_CLR_INTR);
        !          1141:                        } else {
        !          1142:                                SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR0,
        !          1143:                                    ZSWR0_CLR_INTR);
        !          1144:                                splx(s);
        !          1145:                                return (c & 0xff);
        !          1146:                        }
        !          1147:                } else
        !          1148:                        DELAY(10);
        !          1149:        }
        !          1150: }
        !          1151:
        !          1152: /*
        !          1153:  * Send a char on a port, via a busy wait loop.
        !          1154:  */
        !          1155: void
        !          1156: sccPutc(dev, c)
        !          1157:        dev_t dev;
        !          1158:        int c;
        !          1159: {
        !          1160:        register scc_regmap_t *regs;
        !          1161:        register int line;
        !          1162:        register u_char value;
        !          1163:        int s;
        !          1164:
        !          1165:        s = splhigh();
        !          1166:        line = SCCLINE(dev);
        !          1167:        if (cold && scc_cons_addr) {
        !          1168:                regs = scc_cons_addr;
        !          1169:        } else {
        !          1170:                register struct scc_softc *sc;
        !          1171:                sc = scc_cd.cd_devs[SCCUNIT(dev)];
        !          1172:                regs = (scc_regmap_t *)sc->scc_pdma[line].p_addr;
        !          1173:        }
        !          1174:
        !          1175:        /*
        !          1176:         * Wait for transmitter to be not busy.
        !          1177:         */
        !          1178:        do {
        !          1179:                SCC_READ_REG(regs, line, SCC_RR0, value);
        !          1180:                if (value & ZSRR0_TX_READY)
        !          1181:                        break;
        !          1182:                DELAY(100);
        !          1183:        } while (1);
        !          1184:
        !          1185:        /*
        !          1186:         * Send the char.
        !          1187:         */
        !          1188:        SCC_WRITE_DATA(regs, line, c);
        !          1189:        tc_mb();
        !          1190:        splx(s);
        !          1191:
        !          1192:        return;
        !          1193: }
        !          1194:
        !          1195: /*
        !          1196:  * Enable/disable polling mode
        !          1197:  */
        !          1198: void
        !          1199: sccPollc(dev, on)
        !          1200:        dev_t dev;
        !          1201:        int on;
        !          1202: {
        !          1203: }
        !          1204:
        !          1205: #ifdef SCC_DEBUG
        !          1206: void
        !          1207: rr(msg, regs)
        !          1208:        char *msg;
        !          1209:        scc_regmap_t *regs;
        !          1210: {
        !          1211:        u_char value;
        !          1212:        int r0, r1, r2, r3, r10, r15;
        !          1213:
        !          1214:        printf("%s: register: %lx\n", msg, regs);
        !          1215: #define        L(reg, r) {                                                     \
        !          1216:        SCC_READ_REG(regs, SCC_CHANNEL_A, reg, value);                  \
        !          1217:        r = value;                                                      \
        !          1218: }
        !          1219:        L(SCC_RR0, r0);
        !          1220:        L(SCC_RR1, r1);
        !          1221:        L(ZSRR_IVEC, r2);
        !          1222:        L(ZSRR_IPEND, r3);
        !          1223:        L(SCC_RR10, r10);
        !          1224:        L(SCC_RR15, r15);
        !          1225:        printf("A: 0: %x  1: %x    2(vec): %x  3: %x  10: %x  15: %x\n",
        !          1226:            r0, r1, r2, r3, r10, r15);
        !          1227: #undef L
        !          1228: #define        L(reg, r) {                                                     \
        !          1229:        SCC_READ_REG(regs, SCC_CHANNEL_B, reg, value);                  \
        !          1230:        r = value;                                                      \
        !          1231: }
        !          1232:        L(SCC_RR0, r0);
        !          1233:        L(SCC_RR1, r1);
        !          1234:        L(ZSRR_IVEC, r2);
        !          1235:        L(SCC_RR10, r10);
        !          1236:        L(SCC_RR15, r15);
        !          1237:        printf("B: 0: %x  1: %x  2(state): %x        10: %x  15: %x\n",
        !          1238:            r0, r1, r2, r10, r15);
        !          1239: }
        !          1240: #endif /* SCC_DEBUG */

CVSweb