[BACK]Return to scc.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / arch / pmax / tc

Annotation of src/sys/arch/pmax/tc/scc.c, Revision 1.15

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

CVSweb <webmaster@jp.NetBSD.org>