[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

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