[BACK]Return to scn.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / arch / pc532 / dev

Annotation of src/sys/arch/pc532/dev/scn.c, Revision 1.66

1.66    ! chs         1: /*     $NetBSD: scn.c,v 1.65 2005/09/06 21:40:38 kleink Exp $ */
1.62      agc         2:
                      3: /*
                      4:  * Copyright (c) 1991, 1992, 1993
                      5:  *     The Regents of the University of California.  All rights reserved.
                      6:  *
                      7:  * Portions of this software were developed by the Computer Systems
                      8:  * Engineering group at Lawrence Berkeley Laboratory under DARPA
                      9:  * contract BG 91-66 and contributed to Berkeley.
                     10:  *
                     11:  * All advertising materials mentioning features or use of this software
                     12:  * must display the following acknowledgement:
                     13:  *     This product includes software developed by the University of
                     14:  *     California, Lawrence Berkeley Laboratory.
                     15:  *
                     16:  * Redistribution and use in source and binary forms, with or without
                     17:  * modification, are permitted provided that the following conditions
                     18:  * are met:
                     19:  * 1. Redistributions of source code must retain the above copyright
                     20:  *    notice, this list of conditions and the following disclaimer.
                     21:  * 2. Redistributions in binary form must reproduce the above copyright
                     22:  *    notice, this list of conditions and the following disclaimer in the
                     23:  *    documentation and/or other materials provided with the distribution.
                     24:  * 3. Neither the name of the University nor the names of its contributors
                     25:  *    may be used to endorse or promote products derived from this software
                     26:  *    without specific prior written permission.
                     27:  *
                     28:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     29:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     30:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     31:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     32:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     33:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     34:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     35:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     36:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     37:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     38:  * SUCH DAMAGE.
                     39:  *
                     40:  *     from: @(#)com.c 7.5 (Berkeley) 5/16/91
                     41:  */
1.12      cgd        42:
1.19      phil       43: /*
1.36      matthias   44:  * Copyright (c) 1996, 1997 Philip L. Budne.
1.30      matthias   45:  * Copyright (c) 1993 Philip A. Nelson.
                     46:  *
                     47:  * Portions of this software were developed by the Computer Systems
                     48:  * Engineering group at Lawrence Berkeley Laboratory under DARPA
                     49:  * contract BG 91-66 and contributed to Berkeley.
                     50:  *
                     51:  * All advertising materials mentioning features or use of this software
                     52:  * must display the following acknowledgement:
                     53:  *     This product includes software developed by the University of
                     54:  *     California, Lawrence Berkeley Laboratory.
1.1       phil       55:  *
                     56:  * Redistribution and use in source and binary forms, with or without
                     57:  * modification, are permitted provided that the following conditions
                     58:  * are met:
                     59:  * 1. Redistributions of source code must retain the above copyright
                     60:  *    notice, this list of conditions and the following disclaimer.
                     61:  * 2. Redistributions in binary form must reproduce the above copyright
                     62:  *    notice, this list of conditions and the following disclaimer in the
                     63:  *    documentation and/or other materials provided with the distribution.
                     64:  * 3. All advertising materials mentioning features or use of this software
                     65:  *    must display the following acknowledgement:
                     66:  *     This product includes software developed by the University of
                     67:  *     California, Berkeley and its contributors.
                     68:  * 4. Neither the name of the University nor the names of its contributors
                     69:  *    may be used to endorse or promote products derived from this software
                     70:  *    without specific prior written permission.
                     71:  *
                     72:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     73:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     74:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     75:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     76:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     77:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     78:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     79:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     80:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     81:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     82:  * SUCH DAMAGE.
                     83:  *
1.30      matthias   84:  *     from: @(#)com.c 7.5 (Berkeley) 5/16/91
1.1       phil       85:  */
1.61      lukem      86:
                     87: #include <sys/cdefs.h>
1.66    ! chs        88: __KERNEL_RCSID(0, "$NetBSD: scn.c,v 1.65 2005/09/06 21:40:38 kleink Exp $");
1.1       phil       89:
1.43      jonathan   90: #include "opt_ddb.h"
1.48      lukem      91: #include "opt_kgdb.h"
1.60      thorpej    92: #include "opt_cpu30mhz.h"
1.1       phil       93: #include "scn.h"
                     94:
1.11      phil       95: #include <sys/param.h>
                     96: #include <sys/systm.h>
                     97: #include <sys/ioctl.h>
                     98: #include <sys/select.h>
                     99: #include <sys/tty.h>
                    100: #include <sys/proc.h>
                    101: #include <sys/user.h>
                    102: #include <sys/file.h>
                    103: #include <sys/uio.h>
                    104: #include <sys/kernel.h>
                    105: #include <sys/syslog.h>
                    106: #include <sys/types.h>
1.13      phil      107: #include <sys/device.h>
1.31      matthias  108: #include <sys/malloc.h>
1.54      gehenna   109: #include <sys/conf.h>
1.37      matthias  110: #ifdef KGDB
                    111: #include <sys/kgdb.h>
                    112: #endif
1.11      phil      113:
                    114: #include <dev/cons.h>
                    115:
1.33      matthias  116: #include <machine/autoconf.h>
1.1       phil      117:
                    118: #include "scnreg.h"
1.30      matthias  119: #include "scnvar.h"
                    120:
1.33      matthias  121: static const char scnints[4] = {IR_TTY0, IR_TTY1, IR_TTY2, IR_TTY3};
                    122: static const char rxints[4] = {IR_TTY0RDY, IR_TTY1RDY, IR_TTY2RDY, IR_TTY3RDY};
1.32      matthias  123:
                    124: int     scnprobe __P((struct device *, struct cfdata *, void *));
1.30      matthias  125: void    scnattach __P((struct device *, struct device *, void *));
                    126: int     scnparam __P((struct tty *, struct termios *));
                    127: void    scnstart __P((struct tty *));
1.44      matthias  128: void   scncnprobe __P((struct consdev *));
1.30      matthias  129: void   scncninit __P((struct consdev *));
1.64      chs       130: int     scncngetc __P((void *));
                    131: void    scncnputc __P((void *, int));
1.30      matthias  132: void   scncnpollc __P((dev_t, int));
                    133: int    scninit __P((dev_t, int));
                    134: void   scncnreinit __P((void *));
1.32      matthias  135: int     scnhwiflow __P((struct tty *, int));
1.30      matthias  136:
1.56      thorpej   137: CFATTACH_DECL(scn, sizeof(struct scn_softc),
                    138:     scnprobe, scnattach, NULL, NULL);
1.58      simonb    139:
                    140: extern struct cfdriver scn_cd;
1.41      thorpej   141:
1.54      gehenna   142: dev_type_open(scnopen);
                    143: dev_type_close(scnclose);
                    144: dev_type_read(scnread);
                    145: dev_type_write(scnwrite);
                    146: dev_type_ioctl(scnioctl);
                    147: dev_type_stop(scnstop);
                    148: dev_type_tty(scntty);
                    149: dev_type_poll(scnpoll);
                    150:
                    151: const struct cdevsw scn_cdevsw = {
                    152:        scnopen, scnclose, scnread, scnwrite, scnioctl,
1.57      jdolecek  153:        scnstop, scntty, scnpoll, nommap, ttykqfilter, D_TTY
1.54      gehenna   154: };
                    155:
1.30      matthias  156: #ifndef CONSOLE_SPEED
                    157: #define CONSOLE_SPEED TTYDEF_SPEED
                    158: #endif
                    159:
                    160: #ifndef SCNDEF_CFLAG
                    161: #define SCNDEF_CFLAG TTYDEF_CFLAG
                    162: #endif
                    163:
1.31      matthias  164: #ifdef CPU30MHZ
1.34      matthias  165: #define RECOVER()      __asm __volatile("bispsrw 0x800" : : : "cc")
1.31      matthias  166: #else
                    167: #define RECOVER()
                    168: #endif
                    169:
1.30      matthias  170: int     scndefaultrate = TTYDEF_SPEED;
                    171: int     scnconsrate = CONSOLE_SPEED;
                    172:
                    173: #define SOFTC(UNIT) scn_cd.cd_devs[(UNIT)]
1.64      chs       174: #define SCN_ADDR2DUART(addr)   (((addr) >> 4) & 3)
                    175: #define SCN_ADDR2CHAN(addr)    (((addr) >> 3) & 1)
                    176: #define SCN_ISCONSOLE(addr) \
                    177:        (SCN_ADDR2DUART(addr) == SCN_CONSDUART && (SCN_ADDR2CHAN(addr) == SCN_CONSCHAN))
1.30      matthias  178:
1.31      matthias  179: static void scnintr __P((void *));
1.32      matthias  180: static void scnrxintr __P((void *));
1.64      chs       181: static int scn_rxintr __P((struct scn_softc *));
1.30      matthias  182: static void scnsoft __P((void *));
1.36      matthias  183: static void scn_setchip __P((struct scn_softc *sc));
                    184: static int scniter __P((int *, int, int*, int*, struct chan *, int));
1.64      chs       185: static int scn_config __P((int, int, int, int, u_char, u_char));
1.37      matthias  186: static void scn_rxenable __P((struct scn_softc *));
                    187: static void scn_rxdisable __P((struct scn_softc *));
                    188: static void dcd_int __P((struct scn_softc *, struct tty *, u_char));
1.66    ! chs       189: static void scnoverrun __P((int, long *, const char *));
1.37      matthias  190: static unsigned char opbits __P((struct scn_softc *, int));
1.30      matthias  191:
1.35      matthias  192: static int scnsir = -1;                /* s/w intr number */
                    193: #define setsoftscn()   softintr(scnsir)
                    194:
                    195: #ifdef SCN_TIMING
1.30      matthias  196: /*
                    197:  * Keep timing info on latency of software interrupt used by
1.31      matthias  198:  * the ringbuf code to empty ring buffer.
1.30      matthias  199:  * "getinfo" program reads data from /dev/kemm.
                    200:  */
                    201: static struct timeval tstart;
                    202: #define NJITTER 100
                    203: int     scn_njitter = NJITTER;
                    204: int     scn_jitter[NJITTER];
                    205: #endif
1.16      phil      206:
1.35      matthias  207: #define SCN_CLOCK      3686400         /* input clock */
1.1       phil      208:
1.36      matthias  209: /* speed table groups ACR[7] */
                    210: #define GRP_A  0
                    211: #define GRP_B  ACR_BRG
                    212:
                    213: /* combo of MR0[2:0] and ACR[7] */
                    214: #define MODE0A MR0_MODE_0
                    215: #define MODE0B (MR0_MODE_0|ACR_BRG)
                    216: #define MODE1A MR0_MODE_1
                    217: #define MODE1B (MR0_MODE_1|ACR_BRG)
                    218: #define MODE2A MR0_MODE_2
                    219: #define MODE2B (MR0_MODE_2|ACR_BRG)
                    220:
                    221: #define ANYMODE        -1
                    222: #define DEFMODE(C92) MODE0A            /* use MODE4A if 26c92? */
                    223:
                    224: /* speed code for Counter/Timer (all modes, groups) */
                    225: #define USE_CT 0xd
                    226:
1.30      matthias  227: /*
1.36      matthias  228:  * Rate table, ordered by speed, then mode.
                    229:  * NOTE: ordering of modes must be done carefully!
1.30      matthias  230:  */
1.36      matthias  231: struct tabent {
                    232:        int32_t speed;
                    233:        int16_t code;
                    234:        int16_t mode;
                    235: } table[] = {
                    236:        {     50, 0x0, MODE0A },
                    237:        {     75, 0x0, MODE0B },
                    238:        {    110, 0x1, MODE0A },
                    239:        {    110, 0x1, MODE0B },
                    240:        {    110, 0x1, MODE1A },
                    241:        {    110, 0x1, MODE1B },
                    242:        {    134, 0x2, MODE0A },        /* 134.5 */
                    243:        {    134, 0x2, MODE0B },        /* 134.5 */
                    244:        {    134, 0x2, MODE1A },        /* 134.5 */
                    245:        {    134, 0x2, MODE1B },        /* 134.5 */
                    246:        {    150, 0x3, MODE0A },
                    247:        {    150, 0x3, MODE0A },
                    248:        {    200, 0x3, MODE0A },
                    249:        {    300, 0x4, MODE0A },
                    250:        {    300, 0x4, MODE0B },
                    251:        {    300, 0x0, MODE1A },
                    252:        {    450, 0x0, MODE1B },
                    253:        {    600, 0x5, MODE0A },
                    254:        {    600, 0x5, MODE0B },
                    255:        {    880, 0x1, MODE2A },
                    256:        {    880, 0x1, MODE2B },
                    257:        {    900, 0x3, MODE1B },
                    258:        {   1050, 0x7, MODE0A },
                    259:        {   1050, 0x7, MODE1A },
                    260:        {   1076, 0x2, MODE2A },
                    261:        {   1076, 0x2, MODE2B },
                    262:        {   1200, 0x6, MODE0A },
                    263:        {   1200, 0x6, MODE0B },
                    264:        {   1200, 0x3, MODE1A },
                    265:        {   1800, 0xa, MODE0B },
                    266:        {   1800, 0x4, MODE1A },
                    267:        {   1800, 0x4, MODE1B },
                    268:        {   2000, 0x7, MODE0B },
                    269:        {   2000, 0x7, MODE1B },
                    270:        {   2400, 0x8, MODE0A },
                    271:        {   2400, 0x8, MODE0B },
                    272:        {   3600, 0x5, MODE1A },
                    273:        {   3600, 0x5, MODE1B },
                    274:        {   4800, 0x9, MODE2A },
                    275:        {   4800, 0x9, MODE2B },
                    276:        {   4800, 0x9, MODE0A },
                    277:        {   4800, 0x9, MODE0B },
                    278:        {   7200, 0xa, MODE0A },
                    279:        {   7200, 0x0, MODE2B },
                    280:        {   7200, 0x6, MODE1A },
                    281:        {   7200, 0x6, MODE1B },
                    282:        {   9600, 0xb, MODE2A },
                    283:        {   9600, 0xb, MODE2B },
                    284:        {   9600, 0xb, MODE0A },
                    285:        {   9600, 0xb, MODE0B },
                    286:        {   9600, 0xd, MODE1A },        /* use C/T as entre' to mode1 */
                    287:        {   9600, 0xd, MODE1B },        /* use C/T as entre' to mode1 */
                    288:        {  14400, 0x3, MODE2B },
                    289:        {  14400, 0x8, MODE1A },
                    290:        {  14400, 0x8, MODE1B },
                    291:        {  19200, 0x3, MODE2A },
                    292:        {  19200, 0xc, MODE2B },
                    293:        {  19200, 0xc, MODE0B },
                    294:        {  19200, 0xd, MODE1A },        /* use C/T as entre' to mode1 */
                    295:        {  19200, 0xd, MODE1B },        /* use C/T as entre' to mode1 */
                    296:        {  28800, 0x4, MODE2A },
                    297:        {  28800, 0x4, MODE2B },
                    298:        {  28800, 0x9, MODE1A },
                    299:        {  28800, 0x9, MODE1B },
                    300:        {  38400, 0xc, MODE2A },
                    301:        {  38400, 0xc, MODE0A },
                    302:        {  57600, 0x5, MODE2A },
                    303:        {  57600, 0x5, MODE2B },
                    304:        {  57600, 0xb, MODE1A },
                    305:        {  57600, 0xb, MODE1B },
                    306:        { 115200, 0x6, MODE2A },
                    307:        { 115200, 0x6, MODE2B },
                    308:        { 115200, 0xc, MODE1B },
                    309:        { 230400, 0xc, MODE1A }
                    310: };
                    311: #define TABENTRIES (sizeof(table)/sizeof(table[0]))
1.26      thorpej   312:
1.30      matthias  313: /*
1.36      matthias  314:  * boolean for speed codes which are identical in both A/B BRG groups
                    315:  * in all modes
1.30      matthias  316:  */
1.36      matthias  317: static u_char bothgroups[16] = {
                    318:        0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1
                    319: };
1.1       phil      320:
1.30      matthias  321: /*
1.36      matthias  322:  * Manually constructed divisors table
                    323:  * for minimum error (from some of Dave Rand's code)
1.30      matthias  324:  */
1.36      matthias  325: const struct {
                    326:        u_int16_t speed;
                    327:        u_int16_t div;
                    328: } divs[] = {
                    329:        {    50, 2303 },        /* 2304 is exact?? */
                    330:        {   110, 1047 },        /* Should be 1047.27 */
                    331:        {   134, 857 },         /* Should be 856.505576 */
                    332:        {  1050, 110 },         /* Should be 109.7142857 */
                    333:        {  2000, 57 }           /* Should be 57.6 */
1.30      matthias  334: };
1.36      matthias  335: #define DIVS (sizeof(divs)/sizeof(divs[0]))
1.32      matthias  336:
1.30      matthias  337: /*
                    338:  * minor unit bit decode:
                    339:  * CxxxUUU
                    340:  *
                    341:  * C - carrier
                    342:  *     0 - delay open until carrier high
                    343:  *     1 - allow open with carrier low
                    344:  * UUU - unit 0-7
                    345:  */
1.1       phil      346:
1.30      matthias  347: #define DEV_UNIT(x)    (minor(x) & 0x7)
                    348: #define DEV_DIALOUT(x) (minor(x) & 0x80)
1.1       phil      349:
1.30      matthias  350: extern struct tty *constty;
1.40      phil      351:
1.64      chs       352: #define SCN_MAXDUART 4
                    353: static struct duart scn_duart[SCN_MAXDUART];
1.1       phil      354:
                    355: #ifdef KGDB
                    356: extern int kgdb_dev;
                    357: extern int kgdb_rate;
                    358: extern int kgdb_debug_init;
                    359: #endif
1.64      chs       360:
                    361: #define SCN_MAP_ADDR(addr) \
                    362:        ((addr) - SCN_FIRST_ADR + SCN_FIRST_MAP_ADR)
                    363:
1.36      matthias  364: /* RS-232 configuration routines */
                    365:
                    366: /*
                    367:  * set chip parameters, or mark for delayed change.
                    368:  * called at spltty() or on TxEMPTY interrupt.
                    369:  *
                    370:  * Reads current values to avoid glitches from redundant sets.
                    371:  * Perhaps should save last value set to avoid read/write?  NOTE:
                    372:  * Would still need to do read if write not needed to advance MR
                    373:  * pointer.
                    374:  *
                    375:  * new 2/97 -plb
                    376:  */
                    377:
                    378: static void
                    379: scn_setchip(sc)
                    380:        struct scn_softc *sc;
                    381: {
                    382:        struct duart *dp;
                    383:        u_char acr, csr, mr1, mr2;
                    384:        int chan;
                    385:
                    386:        if (sc->sc_tty && (sc->sc_tty->t_state & TS_BUSY)) {
                    387:                sc->sc_heldchanges = 1;
                    388:                return;
                    389:        }
                    390:
1.64      chs       391:        chan = sc->sc_channel;
1.36      matthias  392:        dp = sc->sc_duart;
                    393:        if (dp->type == SC26C92) {
                    394:                u_char nmr0a, mr0a;
1.1       phil      395:
1.39      matthias  396:                /* input rate high enough so 64 bit time watchdog not
                    397:                 * onerous? */
1.36      matthias  398:                if (dp->chan[chan].ispeed >= 1200) {
1.39      matthias  399:                        /* set FIFO threshold at 6 for other
                    400:                         * thresholds we could have to set MR1_FFULL
                    401:                         */
1.36      matthias  402:                        dp->chan[chan].mr0 |= MR0_RXWD | MR0_RXINT;
                    403:                } else {
                    404:                        dp->chan[chan].mr0 &= ~(MR0_RXWD | MR0_RXINT);
                    405:                }
                    406:
                    407:                /* select BRG mode (MR0A only) */
                    408:                nmr0a = dp->chan[0].mr0 | (dp->mode & MR0_MODE);
                    409:
                    410:                dp->base[CH_CR] = CR_CMD_MR0;
                    411:                RECOVER();
                    412:
                    413:                mr0a = dp->base[CH_MR];
                    414:                if (mr0a != nmr0a) {
                    415:                        dp->base[CH_CR] = CR_CMD_MR0;
                    416:                        RECOVER();
                    417:                        dp->base[CH_MR] = nmr0a;
                    418:                }
                    419:
                    420:                if (chan) {      /* channel B? */
                    421:                        u_char mr0b;
                    422:
                    423:                        sc->sc_chbase[CH_CR] = CR_CMD_MR0;
                    424:                        RECOVER();
                    425:                        mr0b = dp->base[CH_MR];
                    426:
                    427:                        if (dp->chan[chan].mr0 != mr0b) {
                    428:                                sc->sc_chbase[CH_CR] = CR_CMD_MR0;
                    429:                                RECOVER();
                    430:                                sc->sc_chbase[CH_MR] = dp->chan[chan].mr0;
                    431:                        }
                    432:                }
                    433:        } else {
                    434:                sc->sc_chbase[CH_CR] = CR_CMD_MR1;
                    435:                RECOVER();
                    436:        }
                    437:
                    438:        mr1 = sc->sc_chbase[CH_MR];
                    439:        mr2 = sc->sc_chbase[CH_MR];
                    440:        if (mr1 != dp->chan[chan].new_mr1 ||
                    441:            mr2 != dp->chan[chan].new_mr2) {
                    442:                sc->sc_chbase[CH_CR] = CR_CMD_MR1;
                    443:                RECOVER();
                    444:                sc->sc_chbase[CH_MR] = dp->chan[chan].new_mr1;
                    445:                sc->sc_chbase[CH_MR] = dp->chan[chan].new_mr2;
                    446:        }
                    447:
                    448:        acr = dp->acr | (dp->mode & ACR_BRG);
                    449:        dp->base[DU_ACR] = acr;         /* write-only reg! */
                    450:
                    451:        /* set speed codes */
                    452:        csr = (dp->chan[chan].icode<<4) | dp->chan[chan].ocode;
                    453:        if (sc->sc_chbase[CH_CSR] != csr) {
                    454:                sc->sc_chbase[CH_CSR] = csr;
                    455:        }
                    456:
                    457:        /* see if counter/timer in use */
                    458:        if (dp->counter &&
                    459:            (dp->chan[0].icode == USE_CT || dp->chan[0].ocode == USE_CT ||
                    460:             dp->chan[1].icode == USE_CT || dp->chan[1].ocode == USE_CT)) {
                    461:
                    462:                /* program counter/timer only if necessary */
                    463:                if (dp->counter != dp->ocounter) {
                    464:                        u_int16_t div;
                    465: #ifdef DIVS
                    466:                        int i;
                    467:
                    468:                        /* look for precalculated rate, for minimum error */
                    469:                        for (i = 0; i < DIVS && divs[i].speed <= dp->counter; i++) {
                    470:                                if (divs[i].speed == dp->counter) {
                    471:                                        div = divs[i].div;
                    472:                                        goto found;
                    473:                                }
                    474:                        }
1.30      matthias  475: #endif
1.1       phil      476:
1.36      matthias  477:                        /* not found in table; calculate a value (rounding up) */
                    478:                        div = ((long)SCN_CLOCK/16/2 + dp->counter/2) / dp->counter;
                    479:
                    480:                found:
                    481:                        /* halt before loading? may ALWAYS glitch?
                    482:                         * reload race may only sometimes glitch??
                    483:                         */
                    484:                        dp->base[DU_CTUR] = div >> 8;
                    485:                        dp->base[DU_CTLR] = div & 255;
                    486:                        if (dp->ocounter == 0) {
                    487:                                /* not previously used? */
                    488:                                u_char temp;
                    489:                                /* start C/T running */
                    490:                                temp = dp->base[DU_CSTRT];
                    491:                        }
                    492:                        dp->ocounter = dp->counter;
                    493:                }
                    494:        } else {
                    495:                /* counter not in use; mark as free */
                    496:                dp->counter = 0;
                    497:        }
                    498:        sc->sc_heldchanges = 0;
1.30      matthias  499:
                    500:        /*
1.36      matthias  501:         * delay a tiny bit to try and avoid tx glitching.
                    502:         * I know we're at spltty(), but this is much better than the
                    503:         * old version used DELAY((96000 / out_speed) * 10000)
                    504:         * -plb
1.30      matthias  505:         */
1.36      matthias  506:        DELAY(10);
                    507: }
                    508:
                    509: /*
                    510:  * iterator function for speeds.
                    511:  * (could be called "findnextcode")
                    512:  * Returns sequence of possible speed codes for a given rate.
                    513:  * should set index to zero before first call.
                    514:  *
                    515:  * Could be implemented as a "checkspeed()" function called
                    516:  * to evaluate table entries, BUT this allows more variety in
                    517:  * use of C/T with fewer table entries.
                    518:  */
                    519:
                    520: static int
                    521: scniter(index, wanted, counter, mode, other, c92)
                    522:        int *index;             /* IN/OUT: index */
                    523:        int wanted;             /* IN: speed wanted */
                    524:        int *counter;           /* IN/OUT: counter/timer rate */
                    525:        int *mode;              /* IN/OUT: mode */
                    526:        struct chan *other;     /* IN: other channel, or NULL */
                    527:        int c92;                /* IN: true for 26C92 */
                    528: {
                    529:        while (*index < TABENTRIES) {
                    530:                struct tabent *tp;
                    531:
                    532:                tp = table + (*index)++;
                    533:                if (tp->speed != wanted)
                    534:                        continue;
                    535:
                    536:                /* if not a 26C92 only look at MODE0 entries */
                    537:                if (!c92 && (tp->mode & MR0_MODE) != MR0_MODE_0)
                    538:                        continue;
                    539:
                    540:                /*
                    541:                 * check mode;
                    542:                 * OK if this table entry for current mode, or mode not
                    543:                 * yet set, or other channel's rates are available in both
                    544:                 * A and B groups.
                    545:                 */
                    546:
                    547:                if (tp->mode == *mode || *mode == ANYMODE ||
                    548:                    (other != NULL && (tp->mode & MR0_MODE) == (*mode & MR0_MODE) &&
                    549:                     bothgroups[other->icode] && bothgroups[other->ocode])) {
                    550:                        /*
                    551:                         * for future table entries specifying
                    552:                         * use of counter/timer
                    553:                         */
                    554:                        if (tp->code == USE_CT) {
                    555:                                if (*counter != wanted && *counter != 0)
                    556:                                        continue;       /* counter busy */
                    557:                                *counter = wanted;
                    558:                        }
                    559:                        *mode = tp->mode;
                    560:                        return tp->code;
                    561:                }
                    562:        }
1.1       phil      563:
1.36      matthias  564:        /* here after returning all applicable table entries */
                    565:        /* XXX return sequence of USE_CT with all possible modes?? */
                    566:        if ((*index)++ == TABENTRIES) {
                    567:                /* Max C/T rate (even on 26C92?) is 57600 */
                    568:                if (wanted <= 57600 && (*counter == wanted || *counter == 0)) {
                    569:                        *counter = wanted;
                    570:                        return USE_CT;
                    571:                }
                    572:        }
                    573:
                    574:        return -1;                      /* FAIL */
1.30      matthias  575: }
1.36      matthias  576:
                    577: /*
                    578:  * calculate configuration
                    579:  * rewritten 2/97 -plb
                    580:  */
1.30      matthias  581: static int
1.64      chs       582: scn_config(unit, chan, ispeed, ospeed, mr1, mr2)
1.36      matthias  583:        int unit;
1.64      chs       584:        int chan;
1.36      matthias  585:        int ispeed;     /* input speed in bps */
                    586:        int ospeed;     /* output speed in bps */
                    587:        u_char mr1;     /* new bits for MR1 */
                    588:        u_char mr2;     /* new bits for MR2 */
1.30      matthias  589: {
1.64      chs       590:        struct scn_softc *sc;
1.36      matthias  591:        struct duart *dp;
1.64      chs       592:        int other;              /* opposite of chan */
1.36      matthias  593:        int mode;
                    594:        int counter;
                    595:        int i, o;               /* input, output iterator indexes */
                    596:        int ic, oc;             /* input, output codes */
                    597:        struct chan *ocp;       /* other duart channel */
                    598:        struct tty *otp;        /* other channel tty struct */
                    599:        int c92;                /* true if duart is sc26c92 */
1.32      matthias  600:        int s;
1.30      matthias  601:
                    602:        /* Set up softc pointer. */
                    603:        if (unit >= scn_cd.cd_ndevs)
                    604:                return ENXIO;
                    605:        sc = SOFTC(unit);
1.64      chs       606:        chan = sc->sc_channel;
1.36      matthias  607:        other = chan ^ 1;
                    608:        dp = sc->sc_duart;
                    609:        ocp = &dp->chan[other];
1.64      chs       610:        otp = ocp->tty;
1.36      matthias  611:        c92 = (dp->type == SC26C92);
                    612:
1.30      matthias  613:        /*
1.36      matthias  614:         * Right now the first combination that works is used.
                    615:         * Perhaps it should search entire solution space for "best"
                    616:         * combination. For example, use heuristic weighting of mode
                    617:         * preferences, and use of counter timer?
                    618:         *
                    619:         * For example right now with 2681/2692 when default rate is
                    620:         * 9600 and other channel is closed setting 19200 will pick
                    621:         * mode 0a and use counter/timer.  Better solution might be
                    622:         * mode 0b, leaving counter/timer free!
                    623:         *
                    624:         * When other channel is open might want to prefer
                    625:         * leaving counter timer free, or not flipping A/B group?
                    626:         */
                    627:        if (otp && (otp->t_state & TS_ISOPEN)) {
1.64      chs       628:
1.36      matthias  629:                /*
                    630:                 * Other channel open;
                    631:                 * Find speed codes compatible with current mode/counter.
                    632:                 */
                    633:
                    634:                i = 0;
                    635:                for (;;) {
                    636:                        mode = dp->mode;
                    637:                        counter = dp->counter;
1.30      matthias  638:
1.36      matthias  639:                        /* NOTE: pass other chan pointer to allow group flipping */
                    640:                        ic = scniter(&i, ispeed, &counter, &mode, ocp, c92);
                    641:                        if (ic == -1)
                    642:                                break;
                    643:
                    644:                        o = 0;
                    645:                        if ((oc = scniter(&o, ospeed, &counter,
                    646:                                          &mode, NULL, c92)) != -1) {
1.30      matthias  647:                                /*
1.36      matthias  648:                                 * take first match
                    649:                                 *
                    650:                                 * Perhaps calculate heuristic "score",
                    651:                                 * save score,codes,mode,counter if score
                    652:                                 * better than previous best?
1.30      matthias  653:                                 */
1.36      matthias  654:                                goto gotit;
                    655:                        }
                    656:                }
                    657:                /* XXX try looping for ospeed? */
                    658:        } else {
                    659:                /* other channel closed */
                    660:                int oo, oi;     /* other input, output iterators */
                    661:                int oic, ooc;   /* other input, output codes */
                    662:
                    663:                /*
                    664:                 * Here when other channel closed.  Finds first
                    665:                 * combination that will allow other channel to be opened
                    666:                 * (with defaults) and fits our needs.
                    667:                 */
                    668:                oi = 0;
                    669:                for (;;) {
                    670:                        mode = ANYMODE;
                    671:                        counter = 0;
                    672:
                    673:                        oic = scniter(&oi, ocp->ispeed, &counter, &mode, NULL, c92);
                    674:                        if (oic == -1)
                    675:                                break;
                    676:
                    677:                        oo = 0;
                    678:                        while ((ooc = scniter(&oo, ocp->ospeed, &counter,
                    679:                                           &mode, NULL, c92)) != -1) {
                    680:                                i = 0;
                    681:                                while ((ic = scniter(&i, ispeed, &counter,
                    682:                                                  &mode, NULL, c92)) != -1) {
                    683:                                        o = 0;
                    684:                                        if ((oc = scniter(&o, ospeed, &counter,
                    685:                                                       &mode, NULL, c92)) != -1) {
                    686:                                                /*
                    687:                                                 * take first match
                    688:                                                 *
                    689:                                                 * Perhaps calculate heuristic
                    690:                                                 * "score", save
                    691:                                                 *     score,codes,mode,counter
                    692:                                                 * if score better than
                    693:                                                 * previous best?
                    694:                                                 */
                    695:                                                s = spltty();
                    696:                                                dp->chan[other].icode = oic;
                    697:                                                dp->chan[other].ocode = ooc;
                    698:                                                goto gotit2;
                    699:                                        }
                    700:                                }
1.30      matthias  701:                        }
                    702:                }
                    703:        }
1.46      matthias  704:        return EINVAL;
1.36      matthias  705:
                    706:     gotit:
1.30      matthias  707:        s = spltty();
1.36      matthias  708:     gotit2:
                    709:        dp->chan[chan].new_mr1 = mr1;
                    710:        dp->chan[chan].new_mr2 = mr2;
                    711:        dp->chan[chan].ispeed = ispeed;
                    712:        dp->chan[chan].ospeed = ospeed;
                    713:        dp->chan[chan].icode = ic;
                    714:        dp->chan[chan].ocode = oc;
                    715:        if (mode == ANYMODE)            /* no mode selected?? */
                    716:                mode = DEFMODE(c92);
                    717:        dp->mode = mode;
                    718:        dp->counter = counter;
                    719:
                    720:        scn_setchip(sc);                /* set chip now, if possible */
1.30      matthias  721:        splx(s);
                    722:        return (0);
1.1       phil      723: }
1.64      chs       724:
1.30      matthias  725: int
                    726: scnprobe(parent, cf, aux)
                    727:        struct device *parent;
1.32      matthias  728:        struct cfdata *cf;
                    729:        void *aux;
1.33      matthias  730: {
                    731:        struct confargs *ca = aux;
1.64      chs       732:        volatile u_char *ch_base;
1.32      matthias  733:        int mr1;
1.31      matthias  734:
                    735:        /* Now some black magic that should detect a scc26x2 channel. */
1.64      chs       736:        ca->ca_addr = SCN_MAP_ADDR(cf->cf_loc[MAINBUSCF_ADDR]);
                    737:        ch_base = (volatile u_char *)ca->ca_addr;
1.31      matthias  738:        ch_base[CH_CR] = CR_CMD_RESET_ERR;
                    739:        RECOVER();
                    740:        ch_base[CH_CR] = CR_CMD_RESET_BRK;
                    741:        RECOVER();
                    742:        ch_base[CH_CR] = CR_CMD_MR1;
                    743:        RECOVER();
                    744:        mr1 = ch_base[CH_MR] ^ 0x80;
                    745:        ch_base[CH_CR] = CR_CMD_MR1;
                    746:        RECOVER();
                    747:        ch_base[CH_MR] = mr1;
                    748:        ch_base[CH_CR] = CR_CMD_MR1;
                    749:        RECOVER();
                    750:        if (ch_base[CH_MR] != mr1)
                    751:                return(0);
                    752:        if (ch_base[CH_MR] == mr1)
                    753:                return(0);
1.33      matthias  754:
1.64      chs       755:        ca->ca_irq = cf->cf_loc[MAINBUSCF_IRQ];
1.33      matthias  756:
1.31      matthias  757:        return(1);
1.30      matthias  758: }
                    759:
                    760: /*
                    761:  * No need to make scn_rx{en,dis}able too efficient,
                    762:  * they're only called on setup, open & close!
                    763:  */
                    764: static __inline void
                    765: scn_rxenable(sc)
                    766:        struct scn_softc *sc;
                    767: {
1.36      matthias  768:        struct duart *dp;
1.32      matthias  769:        int channel;
1.30      matthias  770:
1.36      matthias  771:        dp = sc->sc_duart;
1.64      chs       772:        channel = sc->sc_channel;
1.30      matthias  773:
                    774:        /* Outputs wire-ored and connected to ICU input for fast rx interrupt. */
                    775:        if (channel == 0)
1.36      matthias  776:                dp->opcr |= OPCR_OP4_RXRDYA;
1.30      matthias  777:        else
1.36      matthias  778:                dp->opcr |= OPCR_OP5_RXRDYB;
                    779:        dp->base[DU_OPCR] = dp->opcr;
1.30      matthias  780: }
1.1       phil      781:
1.30      matthias  782: static __inline void
                    783: scn_rxdisable(sc)
                    784:        struct scn_softc *sc;
                    785: {
1.36      matthias  786:        struct duart *dp;
1.32      matthias  787:        int channel;
1.30      matthias  788:
1.36      matthias  789:        dp = sc->sc_duart;
1.64      chs       790:        channel = sc->sc_channel;
1.30      matthias  791:
                    792:        /* Outputs wire-ored and connected to ICU input for fast rx interrupt. */
                    793:        if (channel == 0)
1.36      matthias  794:                dp->opcr &= ~OPCR_OP4_RXRDYA;
1.30      matthias  795:        else
1.36      matthias  796:                dp->opcr &= ~OPCR_OP5_RXRDYB;
                    797:        dp->base[DU_OPCR] = dp->opcr;
1.1       phil      798: }
                    799:
1.13      phil      800: void
1.16      phil      801: scnattach(parent, self, aux)
1.30      matthias  802:        struct device *parent;
                    803:        struct device *self;
                    804:        void   *aux;
                    805: {
1.33      matthias  806:        struct confargs *ca = aux;
1.64      chs       807:        struct scn_softc *sc;
                    808:        struct duart *duart;
                    809:        volatile u_char *ch_base;
                    810:        volatile u_char *duart_base;
1.32      matthias  811:        int channel;
                    812:        int speed;
1.33      matthias  813:        int s;
1.64      chs       814:        int maj;
1.33      matthias  815:        u_char unit;
1.64      chs       816:        u_char duartno;
1.33      matthias  817:        u_char delim = ':';
1.64      chs       818:        u_char mr1, mr2;
1.37      matthias  819:        enum scntype scntype = SCNUNK;
1.66    ! chs       820:        const char *duart_type = "Unknown";
1.59      simonb    821:        char *intrname;
1.64      chs       822:        boolean_t console, first;
1.30      matthias  823:
                    824:        sc = (void *) self;
1.64      chs       825:        unit = self->dv_unit;
1.30      matthias  826:
1.64      chs       827:        duartno = SCN_ADDR2DUART(ca->ca_addr);  /* get chip number */
                    828:        channel = SCN_ADDR2CHAN(ca->ca_addr);   /* get channel on chip */
                    829:
                    830:        duart = sc->sc_duart = &scn_duart[duartno];
                    831:        duart->chan[channel].sc = sc;
                    832:        first = (duart->base == NULL);
1.30      matthias  833:
                    834:        /* pick up "flags" (SCN_xxx) from config file */
                    835:        if (self->dv_cfdata)    /* paranoia */
1.36      matthias  836:                sc->sc_swflags = ca->ca_flags;
1.30      matthias  837:        else
1.36      matthias  838:                sc->sc_swflags = 0;
1.30      matthias  839:
1.64      chs       840:        console = SCN_ISCONSOLE(ca->ca_addr);
                    841:        if (console) {
                    842:                sc->sc_isconsole = 1;
1.36      matthias  843:                sc->sc_swflags |= SCN_SW_SOFTCAR;       /* ignore carrier */
1.64      chs       844:        }
1.30      matthias  845:
1.64      chs       846:        ch_base = (volatile u_char *)ca->ca_addr;
                    847:        duart_base = (volatile u_char *)(ca->ca_addr & ~0xf);
1.30      matthias  848:
1.64      chs       849:        if (first) {
1.32      matthias  850:                /* Probe DUART type */
                    851:                s = spltty();
1.64      chs       852:                if (console) {
1.32      matthias  853:                        ch_base[CH_CR] = CR_DIS_TX;
                    854:                        delay(5 * 10000);
                    855:                }
                    856:                ch_base[CH_CR] = CR_CMD_MR1;
                    857:                RECOVER();
                    858:                mr1 = ch_base[CH_MR];
                    859:                mr2 = ch_base[CH_MR];
                    860:                ch_base[CH_CR] = CR_CMD_MR1;
                    861:                RECOVER();
                    862:                ch_base[CH_MR] = 1;
                    863:                ch_base[CH_MR] = 0;
                    864:                ch_base[CH_CR] = CR_CMD_MR1;
                    865:                RECOVER();
                    866:                if (ch_base[CH_MR] == 1) {
                    867:                        /* MR 2 selected */
                    868:                        ch_base[CH_CR] = CR_CMD_MR0;
                    869:                        RECOVER();
                    870:                        /* if 2681, MR2 still selected */
                    871:                        ch_base[CH_MR] = 1;
                    872:                        ch_base[CH_CR] = CR_CMD_MR1;
                    873:                        RECOVER();
                    874:                        ch_base[CH_MR] = 0; /* MR1 */
                    875:                        ch_base[CH_MR] = 0; /* MR2 */
                    876:                        ch_base[CH_CR] = CR_CMD_MR0;
                    877:                        RECOVER();
                    878:                        /* if 2681, MR2 still selected */
                    879:                        if((ch_base[CH_MR] & 1) == 1) {
1.33      matthias  880:                                duart_type = "sc26c92";
1.36      matthias  881:                                scntype = SC26C92;
1.32      matthias  882:                        } else {
1.36      matthias  883:                                /* 2681 treats as MR1 Select */
                    884:                                ch_base[CH_CR] = CR_CMD_RTS_OFF;
1.32      matthias  885:                                RECOVER();
                    886:                                ch_base[CH_MR] = 1;
                    887:                                ch_base[CH_MR] = 0;
                    888:                                ch_base[CH_CR] = CR_CMD_RTS_OFF;
                    889:                                RECOVER();
                    890:                                if (ch_base[CH_MR] == 1) {
1.33      matthias  891:                                        duart_type = "scn2681";
1.36      matthias  892:                                        scntype = SCN2681;
1.32      matthias  893:                                } else {
1.36      matthias  894:                                        duart_type = "scn2692";
                    895:                                        scntype = SCN2692;
1.32      matthias  896:                                }
                    897:                        }
                    898:                }
                    899:
                    900:                /* If a 2681, the CR_CMD_MR0 is interpreted as a TX_RESET */
1.64      chs       901:                if (console) {
1.32      matthias  902:                        ch_base[CH_CR] = CR_ENA_TX;
                    903:                        RECOVER();
                    904:                }
                    905:                ch_base[CH_CR] = CR_CMD_MR1;
                    906:                RECOVER();
                    907:                ch_base[CH_MR] = mr1;
                    908:                ch_base[CH_MR] = mr2;
                    909:                splx(s);
1.36      matthias  910:
1.30      matthias  911:                /* Arg 0 is special, so we must pass "unit + 1" */
1.59      simonb    912:                intrname = malloc(sizeof("scnXX"), M_DEVBUF, M_NOWAIT);
                    913:                snprintf(intrname, sizeof("scnXX"), "scn%d", unit);
1.64      chs       914:                intr_establish(scnints[duartno], scnintr, duart, intrname, IPL_TTY,
                    915:                               IPL_ZERO, LOW_LEVEL);
1.32      matthias  916:
1.33      matthias  917:                printf("%c %s", delim, duart_type);
                    918:                delim = ',';
1.30      matthias  919:
                    920:                /*
                    921:                 * IPL_ZERO is the right priority for the rx interrupt.
                    922:                 * Only splhigh() should disable rxints.
                    923:                 */
1.59      simonb    924:                intrname = malloc(sizeof("scnXXrx"), M_DEVBUF, M_NOWAIT);
                    925:                snprintf(intrname, 8, "scn%drx", unit);
1.64      chs       926:                intr_establish(ca->ca_irq >> 4, scnrxintr, duart, intrname, IPL_ZERO,
                    927:                               IPL_RTTY, LOW_LEVEL);
                    928:
                    929:                duart->base = duart_base;
                    930:                duart->type = scntype;
1.30      matthias  931:        }
1.64      chs       932:        /* Record channel, uart */
                    933:        sc->sc_channel = channel;
1.36      matthias  934:        sc->sc_chbase = ch_base;
1.30      matthias  935:
                    936:        /* Initialize modem/interrupt bit masks */
                    937:        if (channel == 0) {
                    938:                sc->sc_op_rts = OP_RTSA;
                    939:                sc->sc_op_dtr = OP_DTRA;
                    940:                sc->sc_ip_cts = IP_CTSA;
                    941:                sc->sc_ip_dcd = IP_DCDA;
                    942:
                    943:                sc->sc_tx_int = INT_TXA;
                    944:        } else {
                    945:                sc->sc_op_rts = OP_RTSB;
                    946:                sc->sc_op_dtr = OP_DTRB;
                    947:                sc->sc_ip_cts = IP_CTSB;
                    948:                sc->sc_ip_dcd = IP_DCDB;
                    949:
                    950:                sc->sc_tx_int = INT_TXB;
                    951:        }
                    952:
1.36      matthias  953:        /* Initialize counters */
                    954:        sc->sc_framing_errors = 0;
                    955:        sc->sc_fifo_overruns = 0;
                    956:        sc->sc_parity_errors = 0;
                    957:        sc->sc_breaks = 0;
1.30      matthias  958:
1.64      chs       959:        if (console) {
1.30      matthias  960:                DELAY(5 * 10000);       /* Let the output go out.... */
                    961:        }
1.64      chs       962:
1.30      matthias  963:        /*
                    964:          * Set up the hardware to a base state, in particular:
                    965:          * o reset transmitter and receiver
                    966:          * o set speeds and configurations
                    967:          * o receiver interrupts only (RxRDY and BREAK)
                    968:          */
                    969:
                    970:        s = spltty();
                    971:        /* RTS off... */
                    972:        SCN_OP_BIC(sc, sc->sc_op_rts);  /* "istop" */
                    973:
                    974:        ch_base[CH_CR] = CR_DIS_RX | CR_DIS_TX;
1.31      matthias  975:        RECOVER();
1.30      matthias  976:        ch_base[CH_CR] = CR_CMD_RESET_RX;
1.31      matthias  977:        RECOVER();
1.30      matthias  978:        ch_base[CH_CR] = CR_CMD_RESET_TX;
1.31      matthias  979:        RECOVER();
1.30      matthias  980:        ch_base[CH_CR] = CR_CMD_RESET_ERR;
1.31      matthias  981:        RECOVER();
1.30      matthias  982:        ch_base[CH_CR] = CR_CMD_RESET_BRK;
1.31      matthias  983:        RECOVER();
1.30      matthias  984:        ch_base[CH_CR] = CR_CMD_MR1;
1.31      matthias  985:        RECOVER();
1.30      matthias  986:
                    987:        /* No receiver control of RTS. */
                    988:        ch_base[CH_MR] = 0;
                    989:        ch_base[CH_MR] = 0;
                    990:
                    991:        /* Initialize the uart structure if this is channel A. */
1.64      chs       992:        if (first) {
1.30      matthias  993:                /* Disable all interrupts. */
1.64      chs       994:                duart_base[DU_IMR] = duart->imr = 0;
1.30      matthias  995:
                    996:                /* Output port config */
1.64      chs       997:                duart_base[DU_OPCR] = duart->opcr = 0;
1.30      matthias  998:
                    999:                /* Speeds... */
1.64      chs      1000:                duart->mode = 0;
                   1001:
1.36      matthias 1002:                /*
                   1003:                 * Set initial speed to an illegal code that can be changed to
                   1004:                 * any other baud.
                   1005:                 */
1.64      chs      1006:                duart->chan[0].icode = duart->chan[0].ocode = 0x2f;
                   1007:                duart->chan[1].icode = duart->chan[1].ocode = 0x2f;
                   1008:                duart->chan[0].ispeed = duart->chan[0].ospeed = 0;
                   1009:                duart->chan[1].ispeed = duart->chan[1].ospeed = 0;
                   1010:
                   1011:                duart->acr = 0;
                   1012:                duart->acr |= ACR_CT_TCLK1;     /* timer mode 1x clk */
                   1013:        }
                   1014:
                   1015:        if (channel == 0) {
                   1016:                duart->acr |= ACR_DELTA_DCDA;   /* Set CD int */
1.30      matthias 1017:        } else {
1.64      chs      1018:                duart->acr |= ACR_DELTA_DCDB;   /* Set CD int */
1.30      matthias 1019:        }
1.1       phil     1020:
1.30      matthias 1021:        if (scnsir == -1) {
                   1022:                /* software intr: calls tty code, hence IPL_TTY */
1.32      matthias 1023:                scnsir = intr_establish(SOFTINT, scnsoft, NULL,
                   1024:                                "softscn", IPL_TTY, IPL_TTY, 0);
1.30      matthias 1025:        }
1.1       phil     1026:
1.64      chs      1027:        duart_base[DU_ACR] = (duart->mode & ACR_BRG) | duart->acr;
1.1       phil     1028:
1.64      chs      1029:        if (console)
1.30      matthias 1030:                speed = scnconsrate;
                   1031:        else
                   1032:                speed = scndefaultrate;
                   1033:
1.64      chs      1034:        scn_config(unit, channel, speed, speed, MR1_PNONE | MR1_CS8, MR2_STOP1);
                   1035:        if (console) {
1.54      gehenna  1036:                maj = cdevsw_lookup_major(&scn_cdevsw);
                   1037:                shutdownhook_establish(scncnreinit, (void *)makedev(maj, unit));
1.37      matthias 1038:                /* Make sure console can do scncngetc */
1.64      chs      1039:                duart_base[DU_OPSET] = channel ? (OP_RTSB | OP_DTRB) :
                   1040:                        (OP_RTSA | OP_DTRA);
1.37      matthias 1041:        }
1.30      matthias 1042:
                   1043:        /* Turn on the receiver and transmitters */
                   1044:        ch_base[CH_CR] = CR_ENA_RX | CR_ENA_TX;
                   1045:
                   1046:        /* Set up the interrupts. */
1.64      chs      1047:        duart->imr |= INT_IP;
1.30      matthias 1048:        scn_rxdisable(sc);
                   1049:        splx(s);
                   1050:
1.36      matthias 1051:        if (sc->sc_swflags) {
                   1052:                printf("%c flags %d", delim, sc->sc_swflags);
1.33      matthias 1053:                delim = ',';
                   1054:        }
1.46      matthias 1055:
1.1       phil     1056: #ifdef KGDB
1.54      gehenna  1057:        if (kgdb_dev == makedev(cdevsw_lookup_major(&scn_cdevsw), unit)) {
1.64      chs      1058:                if (console)
1.36      matthias 1059:                        kgdb_dev = NODEV; /* can't debug over console port */
1.1       phil     1060:                else {
1.30      matthias 1061:                        scninit(kgdb_dev, kgdb_rate);
                   1062:                        scn_rxenable(sc);
1.64      chs      1063:                        scn->sc_iskgdb = 1;
                   1064:                        kgdb_attach(scncngetc, scncnputc, kgdb_dev);
1.1       phil     1065:                        if (kgdb_debug_init) {
1.33      matthias 1066:                                printf("%c ", delim);
1.1       phil     1067:                                kgdb_connect(1);
                   1068:                        } else
1.33      matthias 1069:                                printf("%c kgdb enabled", delim);
                   1070:                        delim = ',';
1.1       phil     1071:                }
                   1072:        }
                   1073: #endif
1.30      matthias 1074:        printf("\n");
1.1       phil     1075: }
                   1076:
                   1077: /* ARGSUSED */
1.30      matthias 1078: int
                   1079: scnopen(dev, flag, mode, p)
1.32      matthias 1080:        dev_t dev;
                   1081:        int flag;
                   1082:        int mode;
1.30      matthias 1083:        struct proc *p;
1.1       phil     1084: {
1.64      chs      1085:        struct tty *tp;
                   1086:        int unit = DEV_UNIT(dev);
                   1087:        struct scn_softc *sc;
1.32      matthias 1088:        int error = 0;
                   1089:        int hwset = 0;
                   1090:        int s;
1.7       phil     1091:
1.26      thorpej  1092:        if (unit >= scn_cd.cd_ndevs)
1.16      phil     1093:                return ENXIO;
1.30      matthias 1094:        sc = SOFTC(unit);
1.16      phil     1095:        if (!sc)
                   1096:                return ENXIO;
1.7       phil     1097:
1.30      matthias 1098:        s = spltty();
1.64      chs      1099:        tp = sc->sc_tty;
                   1100:        if (!tp) {
                   1101:                tp = ttymalloc();
                   1102:                sc->sc_tty = sc->sc_duart->chan[sc->sc_channel].tty = tp;
1.30      matthias 1103:                tty_attach(tp);
1.64      chs      1104:        }
1.16      phil     1105:
1.1       phil     1106:        tp->t_oproc = scnstart;
                   1107:        tp->t_param = scnparam;
1.32      matthias 1108:        tp->t_hwiflow = scnhwiflow;
1.1       phil     1109:        tp->t_dev = dev;
1.32      matthias 1110:
1.42      matthias 1111:        if ((tp->t_state & TS_ISOPEN) == 0 && tp->t_wopen == 0) {
1.1       phil     1112:                ttychars(tp);
1.7       phil     1113:                tp->t_iflag = TTYDEF_IFLAG;
                   1114:                tp->t_oflag = TTYDEF_OFLAG;
1.30      matthias 1115:                tp->t_cflag = SCNDEF_CFLAG;
1.32      matthias 1116:
                   1117:                sc->sc_rx_blocked = 0;
                   1118:
1.36      matthias 1119:                if (sc->sc_swflags & SCN_SW_CLOCAL)
1.7       phil     1120:                        tp->t_cflag |= CLOCAL;
1.36      matthias 1121:                if (sc->sc_swflags & SCN_SW_CRTSCTS)
1.30      matthias 1122:                        tp->t_cflag |= CCTS_OFLOW | CRTS_IFLOW;
1.7       phil     1123:                tp->t_lflag = TTYDEF_LFLAG;
1.64      chs      1124:                if (sc->sc_isconsole)
1.30      matthias 1125:                        tp->t_ispeed = tp->t_ospeed = scnconsrate;
                   1126:                else
                   1127:                        tp->t_ispeed = tp->t_ospeed = scndefaultrate;
1.1       phil     1128:                scnparam(tp, &tp->t_termios);
                   1129:                ttsetwater(tp);
                   1130:
                   1131:                /* Turn on DTR and RTS. */
1.30      matthias 1132:                SCN_OP_BIS(sc, sc->sc_op_rts | sc->sc_op_dtr);
                   1133:
1.49      wiz      1134:                /* enable receiver interrupts */
1.30      matthias 1135:                scn_rxenable(sc);
1.32      matthias 1136:                hwset = 1;
1.7       phil     1137:
1.30      matthias 1138:                /* set carrier state; */
1.36      matthias 1139:                if ((sc->sc_swflags & SCN_SW_SOFTCAR) || /* check ttyflags */
                   1140:                    SCN_DCD(sc) ||                       /* check h/w */
1.30      matthias 1141:                    DEV_DIALOUT(dev))
                   1142:                        tp->t_state |= TS_CARR_ON;
                   1143:                else
                   1144:                        tp->t_state &= ~TS_CARR_ON;
1.36      matthias 1145:        } else {
1.65      kleink   1146:                if (tp->t_state & TS_XCLUDE &&
                   1147:                    suser(p->p_ucred, &p->p_acflag) != 0) {
1.30      matthias 1148:                        splx(s);
                   1149:                        return (EBUSY);
1.36      matthias 1150:                } else {
1.30      matthias 1151:                        if (DEV_DIALOUT(dev) && !SCN_DIALOUT(sc)) {
                   1152:                                /* dialout attempt while someone dialed in */
                   1153:                                splx(s);
                   1154:                                return (EBUSY);
                   1155:                        }
1.36      matthias 1156:                }
                   1157:        }
1.30      matthias 1158:        if (DEV_DIALOUT(dev)) {
                   1159:                /* dialout open and no one dialed in (see above) */
                   1160:                SCN_SETDIALOUT(sc);     /* mark line as dialed out */
1.1       phil     1161:        }
1.30      matthias 1162:        if (flag & O_NONBLOCK) {
                   1163:                /* Non-blocking open
                   1164:                 *
                   1165:                 * If non-dialout open, and currenly opened for dialout you
                   1166:                 * lose.
                   1167:                 */
                   1168:                if (!DEV_DIALOUT(dev) && SCN_DIALOUT(sc)) {
                   1169:                        splx(s);
                   1170:                        return EBUSY;
                   1171:                }
                   1172:        } else {
                   1173:                /* Blocking open
                   1174:                 *
                   1175:                 * This used to be more compact (while loop with lots of nots)
                   1176:                 * but it was incomprehensible.
1.46      matthias 1177:                 *
1.30      matthias 1178:                 * "getty" is the classic case of a program that waits here...
                   1179:                 */
                   1180:                for (;;) {
                   1181:                        if (SCN_DIALOUT(sc)) {
                   1182:                                /* Currently opened for dialout. */
                   1183:                                if (DEV_DIALOUT(dev))
                   1184:                                        /* No need to wait if dialout open */
                   1185:                                        break;
                   1186:                                /*
                   1187:                                 * "getty" falls thru and waits while line
                   1188:                                 * dialed out.
                   1189:                                 */
                   1190:                        } else {
                   1191:                                /* Not currently opened for dialout. */
                   1192:                                if ((tp->t_cflag & CLOCAL) ||   /* "local" line? */
                   1193:                                    (tp->t_state & TS_CARR_ON)) /* or carrier up */
                   1194:                                        break;  /* no (more) waiting */
1.36      matthias 1195:                                /*
                   1196:                                 *"getty" on modem falls thru and waits for
                   1197:                                 * carrier up
                   1198:                                 */
1.30      matthias 1199:                        }
                   1200:                        error = ttysleep(tp, (caddr_t) & tp->t_rawq,
1.7       phil     1201:                            TTIPRI | PCATCH, ttopen, 0);
                   1202:                        if (error) {
1.30      matthias 1203:                                /* XXX should turn off chip if we're the only
                   1204:                                 * waiter */
                   1205:
                   1206: /* XXX drop RTS too? -plb */
                   1207: /* XXX dialout state??? -plb */
                   1208:                                SCN_OP_BIC(sc, sc->sc_op_dtr);
                   1209:                                splx(s);
1.7       phil     1210:                                return error;
                   1211:                        }
                   1212:                }
1.30      matthias 1213:        }
                   1214:        splx(s);
                   1215:
1.45      eeh      1216:        error = (*tp->t_linesw->l_open) (dev, tp);
1.32      matthias 1217:        if (error && hwset) {
                   1218:                scn_rxdisable(sc);
1.30      matthias 1219:                SCN_OP_BIC(sc, sc->sc_op_rts | sc->sc_op_dtr);
                   1220:        }
                   1221:        return (error);
1.1       phil     1222: }
1.30      matthias 1223:
                   1224:
1.1       phil     1225: /*ARGSUSED*/
1.30      matthias 1226: int
1.1       phil     1227: scnclose(dev, flag, mode, p)
1.32      matthias 1228:        dev_t dev;
                   1229:        int flag;
                   1230:        int mode;
1.1       phil     1231:        struct proc *p;
                   1232: {
1.64      chs      1233:        int unit = DEV_UNIT(dev);
                   1234:        struct scn_softc *sc = SOFTC(unit);
                   1235:        struct tty *tp = sc->sc_tty;
1.1       phil     1236:
1.32      matthias 1237:        if ((tp->t_state & TS_ISOPEN) == 0)
1.36      matthias 1238:                return 0;
1.32      matthias 1239:
1.45      eeh      1240:        (*tp->t_linesw->l_close) (tp, flag);
1.30      matthias 1241:
1.1       phil     1242: #ifdef KGDB
                   1243:        /* do not disable interrupts if debugging */
1.54      gehenna  1244:        if (kgdb_dev != makedev(cdevsw_lookup_major(&scn_cdevsw), unit))
1.1       phil     1245: #endif
1.30      matthias 1246:                if ((tp->t_state & TS_ISOPEN) == 0) {
                   1247:                        scn_rxdisable(sc);
                   1248:                }
1.36      matthias 1249:        if ((tp->t_cflag & HUPCL) && (sc->sc_swflags & SCN_SW_SOFTCAR) == 0) {
1.30      matthias 1250:                SCN_OP_BIC(sc, sc->sc_op_dtr);
                   1251:                /* hold low for 1 second */
                   1252:                (void) tsleep((caddr_t)sc, TTIPRI, ttclos, hz);
1.1       phil     1253:        }
1.30      matthias 1254:        SCN_CLRDIALOUT(sc);
1.5       phil     1255:        ttyclose(tp);
1.30      matthias 1256:
1.6       phil     1257: #if 0
1.30      matthias 1258:        if ((tp->t_state & TS_ISOPEN) == 0) {
1.6       phil     1259:                ttyfree(tp);
1.36      matthias 1260:                sc->sc_tty = (struct tty *) NULL;
1.6       phil     1261:        }
1.5       phil     1262: #endif
1.30      matthias 1263:
                   1264:        return (0);
1.1       phil     1265: }
1.30      matthias 1266:
                   1267: int
1.1       phil     1268: scnread(dev, uio, flag)
1.32      matthias 1269:        dev_t dev;
1.1       phil     1270:        struct uio *uio;
1.32      matthias 1271:        int flag;
1.1       phil     1272: {
1.64      chs      1273:        struct scn_softc *sc = SOFTC(DEV_UNIT(dev));
                   1274:        struct tty *tp = sc->sc_tty;
1.1       phil     1275:
1.45      eeh      1276:        return ((*tp->t_linesw->l_read) (tp, uio, flag));
1.1       phil     1277: }
1.30      matthias 1278:
                   1279: int
1.1       phil     1280: scnwrite(dev, uio, flag)
1.32      matthias 1281:        dev_t dev;
1.1       phil     1282:        struct uio *uio;
1.32      matthias 1283:        int flag;
1.1       phil     1284: {
1.64      chs      1285:        struct scn_softc *sc = SOFTC(DEV_UNIT(dev));
                   1286:        struct tty *tp = sc->sc_tty;
1.1       phil     1287:
1.45      eeh      1288:        return ((*tp->t_linesw->l_write) (tp, uio, flag));
1.47      scw      1289: }
                   1290:
                   1291: int
                   1292: scnpoll(dev, events, p)
                   1293:        dev_t dev;
                   1294:        int events;
                   1295:        struct proc *p;
                   1296: {
1.64      chs      1297:        struct scn_softc *sc = SOFTC(DEV_UNIT(dev));
                   1298:        struct tty *tp = sc->sc_tty;
1.63      simonb   1299:
1.47      scw      1300:        return ((*tp->t_linesw->l_poll)(tp, events, p));
1.1       phil     1301: }
                   1302:
1.16      phil     1303: struct tty *
                   1304: scntty(dev)
1.32      matthias 1305:        dev_t dev;
1.16      phil     1306: {
1.64      chs      1307:        struct scn_softc *sc = SOFTC(DEV_UNIT(dev));
1.16      phil     1308:
1.36      matthias 1309:        return sc->sc_tty;
1.16      phil     1310: }
                   1311:
1.30      matthias 1312: /* Worker routines for interrupt processing */
                   1313: static __inline void
                   1314: dcd_int(sc, tp, new)
                   1315:        struct scn_softc *sc;
                   1316:        struct tty *tp;
1.32      matthias 1317:        u_char new;
1.8       phil     1318: {
1.36      matthias 1319:        if (sc->sc_swflags & SCN_SW_SOFTCAR)
1.30      matthias 1320:                return;
                   1321:
                   1322: #if 0
                   1323:        printf("scn%d: dcd_int ip %x SCN_DCD %x new %x ipcr %x\n",
                   1324:            sc->unit,
1.36      matthias 1325:            sc->sc_duart->base[DU_IP],
1.30      matthias 1326:            SCN_DCD(sc),
                   1327:            new,
1.36      matthias 1328:            sc->sc_duart->base[DU_IPCR]
1.30      matthias 1329:            );
                   1330: #endif
                   1331:
                   1332: /* XXX set some flag to have some lower (soft) int call line discipline? */
1.46      matthias 1333:        if (!(*tp->t_linesw->l_modem) (tp, new == 0? 1: 0)) {
1.36      matthias 1334:                SCN_OP_BIC(sc, sc->sc_op_rts | sc->sc_op_dtr);
1.32      matthias 1335:        }
1.30      matthias 1336: }
                   1337:
                   1338: /*
                   1339:  * Print out a ring or fifo overrun error message.
                   1340:  */
                   1341: static void
                   1342: scnoverrun(unit, ptime, what)
1.32      matthias 1343:        int unit;
                   1344:        long *ptime;
1.66    ! chs      1345:        const char *what;
1.30      matthias 1346: {
                   1347:        if (*ptime != time.tv_sec) {
                   1348:                *ptime = time.tv_sec;
                   1349:                log(LOG_WARNING, "scn%d: %s overrun\n", unit, what);
                   1350:        }
1.8       phil     1351: }
                   1352:
1.32      matthias 1353: /*
                   1354:  * Try to block or unblock input using hardware flow-control.
                   1355:  * This is called by kern/tty.c if MDMBUF|CRTSCTS is set, and
                   1356:  * if this function returns non-zero, the TS_TBLOCK flag will
                   1357:  * be set or cleared according to the "stop" arg passed.
                   1358:  */
                   1359: int
                   1360: scnhwiflow(tp, stop)
                   1361:        struct tty *tp;
                   1362:        int stop;
                   1363: {
                   1364:        int unit = DEV_UNIT(tp->t_dev);
                   1365:        struct scn_softc *sc = SOFTC(unit);
1.64      chs      1366:        int s;
1.32      matthias 1367:
1.64      chs      1368:        s = splrtty();
1.32      matthias 1369:        if (!stop) {
                   1370:                if (sc->sc_rbput - sc->sc_rbget - 1) {
                   1371:                        setsoftscn();
                   1372:                }
                   1373:        }
                   1374:        splx(s);
                   1375:        return 1;
                   1376: }
                   1377:
1.30      matthias 1378: static void
1.31      matthias 1379: scnintr(arg)
                   1380:        void *arg;
                   1381: {
1.64      chs      1382:        struct duart *duart = arg;
                   1383:        struct scn_softc *sc0 = duart->chan[0].sc;
                   1384:        struct scn_softc *sc1 = duart->chan[1].sc;
1.30      matthias 1385:
1.64      chs      1386:        struct tty *tp0 = sc0->sc_tty;
                   1387:        struct tty *tp1 = sc1->sc_tty;
1.30      matthias 1388:
1.32      matthias 1389:        char rs_work;
                   1390:        u_char rs_stat;
                   1391:        u_char rs_ipcr;
1.30      matthias 1392:
                   1393:        do {
                   1394:                /* Loop to pick up ALL pending interrupts for device. */
                   1395:                rs_work = FALSE;
                   1396:                rs_stat = duart->base[DU_ISR];
                   1397:
                   1398: /* channel a */
                   1399:                if (tp0 != NULL) {
                   1400:                        if ((rs_stat & INT_TXA) && (tp0->t_state & TS_BUSY)) {
                   1401:                                /* output char done. */
                   1402:                                tp0->t_state &= ~(TS_BUSY | TS_FLUSH);
                   1403:
                   1404:                                /* disable tx ints */
1.64      chs      1405:                                duart->imr &= ~sc0->sc_tx_int;
                   1406:                                duart->base[DU_IMR] = duart->imr;
1.1       phil     1407:
1.36      matthias 1408:                                if (sc0->sc_heldchanges) {
                   1409:                                        scn_setchip(sc0);
                   1410:                                }
1.16      phil     1411:
1.46      matthias 1412:                                (*tp0->t_linesw->l_start) (tp0);
1.30      matthias 1413:                                rs_work = TRUE;
                   1414:                        }
                   1415:                }
                   1416:                /* channel b */
                   1417:                if (tp1 != NULL) {
                   1418:                        if ((rs_stat & INT_TXB) && (tp1->t_state & TS_BUSY)) {
                   1419:                                /* output char done. */
                   1420:                                tp1->t_state &= ~(TS_BUSY | TS_FLUSH);
                   1421:
                   1422:                                /* disable tx ints */
1.64      chs      1423:                                duart->imr &= ~sc1->sc_tx_int;
                   1424:                                duart->base[DU_IMR] = duart->imr;
1.16      phil     1425:
1.36      matthias 1426:                                if (sc1->sc_heldchanges) {
                   1427:                                        scn_setchip(sc1);
                   1428:                                }
1.1       phil     1429:
1.46      matthias 1430:                                (*tp1->t_linesw->l_start) (tp1);
1.30      matthias 1431:                                rs_work = TRUE;
                   1432:                        }
                   1433:                }
                   1434:                if (rs_stat & INT_IP) {
                   1435:                        rs_work = TRUE;
                   1436:                        rs_ipcr = duart->base[DU_IPCR];
1.1       phil     1437:
1.31      matthias 1438:                        if (rs_ipcr & IPCR_DELTA_DCDA && tp0 != NULL) {
1.30      matthias 1439:                                dcd_int(sc0, tp0, rs_ipcr & IPCR_DCDA);
                   1440:                        }
1.31      matthias 1441:                        if (rs_ipcr & IPCR_DELTA_DCDB && tp1 != NULL) {
1.30      matthias 1442:                                dcd_int(sc1, tp1, rs_ipcr & IPCR_DCDB);
                   1443:                        }
                   1444:                }
                   1445:        } while (rs_work);
                   1446: }
1.1       phil     1447:
1.30      matthias 1448: /*
                   1449:  * Handle rxrdy/ffull interrupt: QUICKLY poll both channels (checking
                   1450:  * status first) and stash data in a ring buffer.  Ring buffer scheme
                   1451:  * borowed from sparc/zs.c requires NO interlock on data!
                   1452:  *
                   1453:  * This interrupt should NOT be included in spltty() mask since it
                   1454:  * invokes NO tty code!  The whole point is to allow tty input as much
                   1455:  * of the time as possible, while deferring "heavy" character
                   1456:  * processing until later.
                   1457:  *
                   1458:  * see scn.hw.README and scnsoft() for more info.
                   1459:  *
                   1460:  * THIS ROUTINE SHOULD BE KEPT AS CLEAN AS POSSIBLE!!
                   1461:  * IT'S A CANDIDATE FOR RECODING IN ASSEMBLER!!
                   1462:  */
1.36      matthias 1463: static __inline int
1.64      chs      1464: scn_rxintr(struct scn_softc *sc)
1.32      matthias 1465: {
1.64      chs      1466:        char sr;
                   1467:        int i, n;
1.32      matthias 1468:        int work;
1.1       phil     1469:
1.32      matthias 1470:        work = 0;
                   1471:        i = sc->sc_rbput;
                   1472:        while (work <= 10) {
                   1473: #define SCN_GETCH(SC) \
1.36      matthias 1474:                sr = (SC)->sc_chbase[CH_SR]; \
1.32      matthias 1475:                if ((sr & SR_RX_RDY) == 0) \
                   1476:                        break; \
                   1477:                if (sr & (SR_PARITY | SR_FRAME | SR_BREAK | SR_OVERRUN)) \
                   1478:                        goto exception; \
                   1479:                work++; \
1.36      matthias 1480:                (SC)->sc_rbuf[i++ & SCN_RING_MASK] = (SC)->sc_chbase[CH_DAT]
1.32      matthias 1481:
                   1482:                SCN_GETCH(sc); SCN_GETCH(sc); SCN_GETCH(sc);
1.36      matthias 1483:                /* XXX more here if 26C92? -plb */
1.32      matthias 1484:                continue;
                   1485:        exception:
1.30      matthias 1486: #if defined(DDB)
1.64      chs      1487:                if (sc->sc_isconsole && (sr & SR_BREAK)) {
1.32      matthias 1488:                        Debugger();
1.36      matthias 1489:                        sr = sc->sc_chbase[CH_SR];
1.32      matthias 1490:                }
1.30      matthias 1491: #endif
                   1492: #if defined(KGDB)
1.64      chs      1493:                if (sc->sc_iskgdb && (sr & SR_RX_RDY)) {
1.32      matthias 1494:                        kgdb_connect(1);
1.36      matthias 1495:                        sr = sc->sc_chbase[CH_SR];
1.32      matthias 1496:                }
1.30      matthias 1497: #endif
                   1498:                work++;
1.36      matthias 1499:                sc->sc_rbuf[i++ & SCN_RING_MASK] = (sr << 8) | sc->sc_chbase[CH_DAT];
                   1500:                sc->sc_chbase[CH_CR] = CR_CMD_RESET_ERR;        /* resets break? */
1.31      matthias 1501:                RECOVER();
1.30      matthias 1502:        }
1.32      matthias 1503:        /*
                   1504:         * If ring is getting too full, try to block input.
                   1505:         */
                   1506:        n = i - sc->sc_rbget;
                   1507:        if (sc->sc_rbhiwat && (n > sc->sc_rbhiwat)) {
                   1508:                /* If not CRTSCTS sc_rbhiwat is such that this
1.39      matthias 1509:                 *  never happens.
                   1510:                 * Clear RTS
1.32      matthias 1511:                 */
1.39      matthias 1512:                SCN_OP_BIC(sc, sc->sc_op_rts);
1.32      matthias 1513:                sc->sc_rx_blocked = 1;
                   1514:        }
                   1515:        sc->sc_rbput = i;
                   1516:
                   1517:        return work;
                   1518: }
                   1519:
                   1520: static void
                   1521: scnrxintr(arg)
                   1522:        void *arg;
                   1523: {
1.64      chs      1524:        struct duart *duart = arg;
1.32      matthias 1525:        int work = 0;
1.1       phil     1526:
1.64      chs      1527:        work += scn_rxintr(duart->chan[0].sc);
                   1528:        work += scn_rxintr(duart->chan[1].sc);
1.30      matthias 1529:        if (work > 0) {
                   1530:                setsoftscn();   /* trigger s/w intr */
                   1531: #ifdef SCN_TIMING
                   1532:                microtime(&tstart);
                   1533: #endif
1.1       phil     1534:        }
                   1535: }
                   1536:
1.30      matthias 1537: /*
                   1538:  * Here on soft interrupt (at spltty) to empty ring buffers.
                   1539:  *
1.49      wiz      1540:  * Dave's original scheme was to use the DUART receiver timeout
1.30      matthias 1541:  * interrupt. This requires 2692's (which my board doesn't have), and
                   1542:  * I also liked the idea of using the C/T to generate alternate and/or
                   1543:  * arbitrary bauds. -plb
                   1544:  *
                   1545:  * The ringbuffer code comes from Chris Torek's SPARC 44bsd zs driver
                   1546:  * (hence the LBL notice on top of this file), DOES NOT require
                   1547:  * interlocking with interrupt levels!
                   1548:  *
1.50      wiz      1549:  * The 44bsd sparc/zs driver reads the ring buffer from a separate
1.30      matthias 1550:  * zssoftint, while the SunOS 4.x zs driver appears to use
                   1551:  * timeout()'s.  timeouts seem to be too slow to deal with high data
                   1552:  * rates.  I know, I tried them.
                   1553:  * -plb.
                   1554:  */
                   1555: static void
                   1556: scnsoft(arg)
1.32      matthias 1557:        void *arg;
1.30      matthias 1558: {
1.64      chs      1559:        int s, unit;
1.30      matthias 1560: #ifdef SCN_TIMING
                   1561:        struct timeval tend;
                   1562:        u_long  t;
                   1563:
                   1564:        microtime(&tend);
                   1565:        t = (tend.tv_sec - tstart.tv_sec) * 1000000 + (tend.tv_usec - tstart.tv_usec);
                   1566:        t = (t + tick / 20) / (tick / 10);
                   1567:        if (t >= NJITTER - 1) {
                   1568:                t = NJITTER - 1;
                   1569:        }
                   1570:        scn_jitter[t]++;
1.1       phil     1571: #endif
1.16      phil     1572:
1.30      matthias 1573:        for (unit = 0; unit < scn_cd.cd_ndevs; unit++) {
1.64      chs      1574:                struct scn_softc *sc;
                   1575:                struct tty *tp;
                   1576:                int n, get;
1.16      phil     1577:
1.30      matthias 1578:                sc = SOFTC(unit);
1.36      matthias 1579:                if (sc == NULL) {
1.34      matthias 1580:                        continue;
1.36      matthias 1581:                }
                   1582:                tp = sc->sc_tty;
1.30      matthias 1583: #ifdef KGDB
                   1584:                if (tp == NULL) {
                   1585:                        sc->sc_rbget = sc->sc_rbput;
                   1586:                        continue;
                   1587:                }
                   1588: #endif
1.32      matthias 1589:                if (tp == NULL || tp->t_state & TS_TBLOCK) {
                   1590:                        continue;
                   1591:                }
                   1592:
                   1593:
1.30      matthias 1594:                get = sc->sc_rbget;
1.1       phil     1595:
1.30      matthias 1596:                /* NOTE: fetch from rbput is atomic */
                   1597:                while (get != (n = sc->sc_rbput)) {
                   1598:                        /*
1.36      matthias 1599:                         * Compute the number of interrupts in the receive ring.
                   1600:                         * If the count is overlarge, we lost some events, and
                   1601:                         * must advance to the first valid one.  It may get
                   1602:                         * overwritten if more data are arriving, but this is
                   1603:                         * too expensive to check and gains nothing (we already
                   1604:                         * lost out; all we can do at this point is trade one
                   1605:                         * kind of loss for another).
                   1606:                         */
1.30      matthias 1607:                        n -= get;
                   1608:                        if (n > SCN_RING_SIZE) {
                   1609:                                scnoverrun(unit, &sc->sc_rotime, "ring");
                   1610:                                get += n - SCN_RING_SIZE;
                   1611:                                n = SCN_RING_SIZE;
1.36      matthias 1612:                                sc->sc_ring_overruns++;
1.30      matthias 1613:                        }
                   1614:                        while (--n >= 0) {
1.64      chs      1615:                                int c, sr;
1.1       phil     1616:
1.32      matthias 1617:                                if (tp->t_state & TS_TBLOCK) {
                   1618:                                        sc->sc_rbget = get;
                   1619:                                        goto done;
                   1620:                                }
1.30      matthias 1621:                                /* Race to keep ahead of incoming interrupts. */
                   1622:                                c = sc->sc_rbuf[get++ & SCN_RING_MASK];
1.1       phil     1623:
1.30      matthias 1624:                                sr = c >> 8;    /* extract status */
                   1625:                                c &= 0xff;      /* leave just character */
1.19      phil     1626:
1.30      matthias 1627:                                if (sr & SR_OVERRUN) {
                   1628:                                        scnoverrun(unit, &sc->sc_fotime, "fifo");
1.36      matthias 1629:                                        sc->sc_fifo_overruns++;
1.30      matthias 1630:                                }
1.36      matthias 1631:                                if (sr & SR_PARITY) {
1.30      matthias 1632:                                        c |= TTY_PE;
1.36      matthias 1633:                                        sc->sc_parity_errors++;
                   1634:                                }
                   1635:                                if (sr & SR_FRAME) {
1.30      matthias 1636:                                        c |= TTY_FE;
1.36      matthias 1637:                                        sc->sc_framing_errors++;
                   1638:                                }
1.30      matthias 1639:                                if (sr & SR_BREAK) {
                   1640: #if 0
                   1641:                                        /*
                   1642:                                         * See DDB_CHECK() comments in
                   1643:                                         * scnrxintr()
                   1644:                                         */
1.64      chs      1645:                                        if (sc->sc_isconsole)
1.30      matthias 1646:                                                Debugger();
1.21      phil     1647: #endif
1.30      matthias 1648:                                        c = TTY_FE | 0;
1.36      matthias 1649:                                        sc->sc_breaks++;
1.21      phil     1650:                                }
1.45      eeh      1651:                                (*tp->t_linesw->l_rint) (c, tp);
1.32      matthias 1652:
                   1653:                                if (sc->sc_rx_blocked && n < SCN_RING_THRESH) {
1.64      chs      1654:                                        s = splrtty();
1.32      matthias 1655:                                        sc->sc_rx_blocked = 0;
1.39      matthias 1656:                                        SCN_OP_BIS(sc, sc->sc_op_rts);
1.32      matthias 1657:                                        splx(s);
                   1658:                                }
1.46      matthias 1659:
1.19      phil     1660:                        }
1.30      matthias 1661:                        sc->sc_rbget = get;
1.19      phil     1662:                }
1.53      simonb   1663:        done: ;
1.1       phil     1664:        }
                   1665: }
                   1666:
1.30      matthias 1667: /* Convert TIOCM_xxx bits to output port bits. */
                   1668: static unsigned char
                   1669: opbits(sc, tioc_bits)
                   1670:        struct scn_softc *sc;
1.32      matthias 1671:        int tioc_bits;
1.30      matthias 1672: {
                   1673:        return ((((tioc_bits) & TIOCM_DTR) ? sc->sc_op_dtr : 0) |
                   1674:            (((tioc_bits) & TIOCM_RTS) ? sc->sc_op_rts : 0));
                   1675: }
1.1       phil     1676:
1.30      matthias 1677: int
1.3       phil     1678: scnioctl(dev, cmd, data, flag, p)
1.32      matthias 1679:        dev_t dev;
1.37      matthias 1680:        u_long cmd;
1.30      matthias 1681:        caddr_t data;
1.32      matthias 1682:        int flag;
1.3       phil     1683:        struct proc *p;
1.1       phil     1684: {
1.64      chs      1685:        int unit = DEV_UNIT(dev);
                   1686:        struct scn_softc *sc = SOFTC(unit);
                   1687:        struct tty *tp = sc->sc_tty;
                   1688:        int error;
1.5       phil     1689:
1.45      eeh      1690:        error = (*tp->t_linesw->l_ioctl) (tp, cmd, data, flag, p);
1.52      atatat   1691:        if (error != EPASSTHROUGH)
1.1       phil     1692:                return (error);
1.52      atatat   1693:
1.3       phil     1694:        error = ttioctl(tp, cmd, data, flag, p);
1.52      atatat   1695:        if (error != EPASSTHROUGH)
1.1       phil     1696:                return (error);
                   1697:
                   1698:        switch (cmd) {
                   1699:        case TIOCSBRK:
1.36      matthias 1700:                sc->sc_chbase[CH_CR] = CR_CMD_START_BRK;
1.1       phil     1701:                break;
                   1702:
                   1703:        case TIOCCBRK:
1.36      matthias 1704:                sc->sc_chbase[CH_CR] = CR_CMD_STOP_BRK;
1.1       phil     1705:                break;
                   1706:
                   1707:        case TIOCSDTR:
1.30      matthias 1708:                SCN_OP_BIS(sc, sc->sc_op_dtr | sc->sc_op_rts);
1.1       phil     1709:                break;
                   1710:
                   1711:        case TIOCCDTR:
1.30      matthias 1712:                SCN_OP_BIC(sc, sc->sc_op_dtr | sc->sc_op_rts);
1.1       phil     1713:                break;
                   1714:
1.30      matthias 1715:        case TIOCMSET: {
                   1716:                        int     s;
                   1717:                        unsigned char sbits, cbits;
                   1718:
                   1719:                        /* set bits */
                   1720:                        sbits = opbits(sc, *(int *) data);
                   1721:
                   1722:                        /* get bits to clear */
                   1723:                        cbits = ~sbits & (sc->sc_op_dtr | sc->sc_op_rts);
                   1724:
                   1725:                        s = spltty();
                   1726:                        if (sbits) {
                   1727:                                SCN_OP_BIS(sc, sbits);
                   1728:                        }
                   1729:                        if (cbits) {
                   1730:                                SCN_OP_BIC(sc, cbits);
                   1731:                        }
                   1732:                        splx(s);
                   1733:                        break;
                   1734:                }
1.1       phil     1735:
                   1736:        case TIOCMBIS:
1.30      matthias 1737:                SCN_OP_BIS(sc, opbits(sc, *(int *) data));
1.1       phil     1738:                break;
                   1739:
                   1740:        case TIOCMBIC:
1.30      matthias 1741:                SCN_OP_BIC(sc, opbits(sc, *(int *) data));
1.1       phil     1742:                break;
                   1743:
1.30      matthias 1744:        case TIOCMGET: {
                   1745:                        int     bits;
                   1746:                        unsigned char ip, op;
                   1747:
                   1748:                        /* s = spltty(); */
1.36      matthias 1749:                        ip = sc->sc_duart->base[DU_IP];
1.30      matthias 1750:                        /*
                   1751:                         * XXX sigh; cannot get op current state!! even if
                   1752:                         * maintained in private, RTS is done in h/w!!
                   1753:                         */
                   1754:                        op = 0;
                   1755:                        /* splx(s); */
                   1756:
                   1757:                        bits = 0;
                   1758:                        if (ip & sc->sc_ip_dcd)
                   1759:                                bits |= TIOCM_CD;
                   1760:                        if (ip & sc->sc_ip_cts)
                   1761:                                bits |= TIOCM_CTS;
                   1762:
                   1763: #if 0
                   1764:                        if (op & sc->sc_op_dtr)
                   1765:                                bits |= TIOCM_DTR;
                   1766:                        if (op & sc->sc_op_rts)
                   1767:                                bits |= TIOCM_RTS;
                   1768: #endif
                   1769:
                   1770:                        *(int *) data = bits;
                   1771:                        break;
                   1772:                }
                   1773:
                   1774:        case TIOCGFLAGS:{
                   1775:                        int     bits = 0;
1.1       phil     1776:
1.36      matthias 1777:                        if (sc->sc_swflags & SCN_SW_SOFTCAR)
1.30      matthias 1778:                                bits |= TIOCFLAG_SOFTCAR;
1.36      matthias 1779:                        if (sc->sc_swflags & SCN_SW_CLOCAL)
1.30      matthias 1780:                                bits |= TIOCFLAG_CLOCAL;
1.36      matthias 1781:                        if (sc->sc_swflags & SCN_SW_CRTSCTS)
1.30      matthias 1782:                                bits |= TIOCFLAG_CRTSCTS;
1.36      matthias 1783:                        if (sc->sc_swflags & SCN_SW_MDMBUF)
1.30      matthias 1784:                                bits |= TIOCFLAG_MDMBUF;
1.8       phil     1785:
1.30      matthias 1786:                        *(int *) data = bits;
                   1787:                        break;
                   1788:                }
                   1789:        case TIOCSFLAGS:{
                   1790:                        int     userbits, driverbits = 0;
1.8       phil     1791:
1.30      matthias 1792:                        error = suser(p->p_ucred, &p->p_acflag);
                   1793:                        if (error != 0)
                   1794:                                return (EPERM);
                   1795:
                   1796:                        userbits = *(int *) data;
                   1797:                        if (userbits & TIOCFLAG_SOFTCAR)
                   1798:                                driverbits |= SCN_SW_SOFTCAR;
                   1799:                        if (userbits & TIOCFLAG_CLOCAL)
                   1800:                                driverbits |= SCN_SW_CLOCAL;
                   1801:                        if (userbits & TIOCFLAG_CRTSCTS)
                   1802:                                driverbits |= SCN_SW_CRTSCTS;
                   1803:                        if (userbits & TIOCFLAG_MDMBUF)
                   1804:                                driverbits |= SCN_SW_MDMBUF;
                   1805:
1.36      matthias 1806:                        sc->sc_swflags = driverbits;
1.8       phil     1807:
1.30      matthias 1808:                        break;
                   1809:                }
1.8       phil     1810:
1.1       phil     1811:        default:
1.52      atatat   1812:                return (EPASSTHROUGH);
1.1       phil     1813:        }
                   1814:        return (0);
                   1815: }
                   1816:
1.30      matthias 1817: int
1.1       phil     1818: scnparam(tp, t)
1.30      matthias 1819:        struct tty *tp;
                   1820:        struct termios *t;
1.1       phil     1821: {
1.32      matthias 1822:        int cflag = t->c_cflag;
                   1823:        int unit = DEV_UNIT(tp->t_dev);
                   1824:        char mr1, mr2;
                   1825:        int error;
1.30      matthias 1826:        struct scn_softc *sc = SOFTC(unit);
                   1827:
                   1828:        /* Is this a hang up? */
                   1829:        if (t->c_ospeed == B0) {
                   1830:                SCN_OP_BIC(sc, sc->sc_op_dtr);
                   1831:                /* leave DTR down. see comment in scnclose() -plb */
                   1832:                return (0);
                   1833:        }
                   1834:        mr1 = mr2 = 0;
                   1835:
                   1836:        /* Parity? */
                   1837:        if (cflag & PARENB) {
                   1838:                if ((cflag & PARODD) == 0)
                   1839:                        mr1 |= MR1_PEVEN;
                   1840:                else
                   1841:                        mr1 |= MR1_PODD;
                   1842:        } else
                   1843:                mr1 |= MR1_PNONE;
                   1844:
                   1845:        /* Stop bits. */
                   1846:        if (cflag & CSTOPB)
                   1847:                mr2 |= MR2_STOP2;
1.1       phil     1848:        else
1.30      matthias 1849:                mr2 |= MR2_STOP1;
                   1850:
                   1851:        /* Data bits. */
                   1852:        switch (cflag & CSIZE) {
                   1853:        case CS5:
1.36      matthias 1854:                mr1 |= MR1_CS5;
1.30      matthias 1855:                break;
                   1856:        case CS6:
1.36      matthias 1857:                mr1 |= MR1_CS6;
1.30      matthias 1858:                break;
                   1859:        case CS7:
1.36      matthias 1860:                mr1 |= MR1_CS7;
1.30      matthias 1861:                break;
                   1862:        case CS8:
                   1863:        default:
1.36      matthias 1864:                mr1 |= MR1_CS8;
1.30      matthias 1865:                break;
                   1866:        }
1.1       phil     1867:
1.30      matthias 1868:        if (cflag & CCTS_OFLOW)
                   1869:                mr2 |= MR2_TXCTS;
1.1       phil     1870:
1.32      matthias 1871:        if (cflag & CRTS_IFLOW) {
1.39      matthias 1872:                mr1 |= MR1_RXRTS;
1.32      matthias 1873:                sc->sc_rbhiwat = SCN_RING_HIWAT;
                   1874:        } else {
                   1875:                sc->sc_rbhiwat = 0;
                   1876:        }
1.30      matthias 1877:
1.64      chs      1878:        error = scn_config(unit, sc->sc_channel, t->c_ispeed, t->c_ospeed, mr1, mr2);
1.30      matthias 1879:
                   1880:        /* If successful, copy to tty */
                   1881:        if (!error) {
                   1882:                tp->t_ispeed = t->c_ispeed;
                   1883:                tp->t_ospeed = t->c_ospeed;
                   1884:                tp->t_cflag = cflag;
                   1885:        }
                   1886:        return (error);
1.1       phil     1887: }
1.3       phil     1888:
1.30      matthias 1889: void
1.1       phil     1890: scnstart(tp)
1.30      matthias 1891:        struct tty *tp;
1.1       phil     1892: {
1.32      matthias 1893:        int s, c;
                   1894:        int unit = DEV_UNIT(tp->t_dev);
1.30      matthias 1895:        struct scn_softc *sc = SOFTC(unit);
                   1896:
1.1       phil     1897:        s = spltty();
1.30      matthias 1898:        if (tp->t_state & (TS_BUSY | TS_TTSTOP))
1.1       phil     1899:                goto out;
1.30      matthias 1900:        if (tp->t_outq.c_cc <= tp->t_lowat) {
                   1901:                if (tp->t_state & TS_ASLEEP) {
                   1902:                        tp->t_state &= ~TS_ASLEEP;
                   1903:                        wakeup((caddr_t) & tp->t_outq);
                   1904:                }
                   1905:                if (tp->t_outq.c_cc == 0)       /* plb 11/8/95 - from
                   1906:                                                 * isa/com.c */
                   1907:                        goto out;
                   1908:                selwakeup(&tp->t_wsel);
                   1909:        }
1.7       phil     1910:        tp->t_state |= TS_BUSY;
1.39      matthias 1911:
                   1912:        while (sc->sc_chbase[CH_SR] & SR_TX_RDY) {
                   1913:                if ((c = getc(&tp->t_outq)) == -1)
                   1914:                        break;
1.36      matthias 1915:                sc->sc_chbase[CH_DAT] = c;
1.39      matthias 1916:        }
                   1917:        sc->sc_duart->base[DU_IMR] = (sc->sc_duart->imr |= sc->sc_tx_int);
1.30      matthias 1918:
1.1       phil     1919: out:
                   1920:        splx(s);
                   1921: }
1.30      matthias 1922:
1.1       phil     1923: /*
                   1924:  * Stop output on a line.
                   1925:  */
                   1926: /*ARGSUSED*/
1.27      mycroft  1927: void
1.1       phil     1928: scnstop(tp, flag)
1.30      matthias 1929:        struct tty *tp;
1.32      matthias 1930:        int flag;
1.1       phil     1931: {
1.64      chs      1932:        int s;
1.1       phil     1933:
1.64      chs      1934:        s = spltty();
1.1       phil     1935:        if (tp->t_state & TS_BUSY) {
1.30      matthias 1936:                if ((tp->t_state & TS_TTSTOP) == 0)
1.1       phil     1937:                        tp->t_state |= TS_FLUSH;
                   1938:        }
                   1939:        splx(s);
                   1940: }
1.30      matthias 1941:
1.1       phil     1942: /*
1.30      matthias 1943:  * Following are all routines needed for SCN to act as console.
1.1       phil     1944:  */
1.30      matthias 1945: #ifdef VERYLOWDEBUG
                   1946: /* So the kernel can write in unmapped mode! */
                   1947: extern int _mapped;
                   1948: #define SCN_BASE       (_mapped ? SCN_FIRST_MAP_ADR : SCN_FIRST_ADR)
                   1949: #else
                   1950: #define SCN_BASE       (SCN_FIRST_MAP_ADR)
                   1951: #endif
                   1952:
1.64      chs      1953: #define        DUADDR()        (u_char *)(SCN_BASE + SCN_CONSDUART * DUART_SZ)
                   1954: #define        CHADDR()        (u_char *)(SCN_BASE + \
                   1955:                                   (SCN_CONSDUART * 2 + SCN_CONSCHAN) * CH_SZ)
1.1       phil     1956:
1.44      matthias 1957: void
1.1       phil     1958: scncnprobe(cp)
                   1959:        struct consdev *cp;
                   1960: {
                   1961:        /* initialize required fields */
1.54      gehenna  1962:        cp->cn_dev = makedev(cdevsw_lookup_major(&scn_cdevsw), SCN_CONSOLE);
1.1       phil     1963:        cp->cn_pri = CN_NORMAL;
                   1964: }
                   1965:
1.30      matthias 1966: void
                   1967: scncnreinit(v)
1.32      matthias 1968:        void *v;
1.1       phil     1969: {
1.64      chs      1970:        volatile u_char *du_base = DUADDR();
1.1       phil     1971:
1.64      chs      1972:        du_base[DU_OPSET] = SCN_CONSCHAN ? (OP_RTSB | OP_DTRB) : (OP_RTSA | OP_DTRA);
1.1       phil     1973: }
                   1974:
1.30      matthias 1975: void
                   1976: scncninit(cp)
                   1977:        struct consdev *cp;
1.1       phil     1978: {
1.30      matthias 1979:        scninit(cp->cn_dev, scnconsrate);
1.1       phil     1980: }
                   1981:
1.30      matthias 1982: /* Used by scncninit and kgdb startup. */
1.1       phil     1983: int
1.30      matthias 1984: scninit(dev, rate)
1.32      matthias 1985:        dev_t dev;
                   1986:        int rate;
1.30      matthias 1987: {
1.64      chs      1988:        volatile u_char *du_base = DUADDR();
1.32      matthias 1989:        int unit = DEV_UNIT(dev);
1.30      matthias 1990:
1.64      chs      1991:        du_base[DU_OPSET] = SCN_CONSCHAN ? (OP_RTSB | OP_DTRB) : (OP_RTSA | OP_DTRA);
                   1992:        scn_config(unit, SCN_CONSCHAN, rate, rate, MR1_PNONE | MR1_CS8, MR2_STOP1);
1.30      matthias 1993:        return (0);
1.1       phil     1994: }
1.5       phil     1995:
                   1996: /*
                   1997:  * Console kernel input character routine.
                   1998:  */
1.30      matthias 1999: int
1.64      chs      2000: scncngetc(void *arg)
1.30      matthias 2001: {
1.64      chs      2002:        volatile u_char *ch_base = CHADDR();
1.32      matthias 2003:        char c;
1.64      chs      2004:        int s;
1.30      matthias 2005:
1.64      chs      2006:        s = spltty();
                   2007:
                   2008:        while ((ch_base[CH_SR] & SR_RX_RDY) == 0)
                   2009:                ;
1.30      matthias 2010:        c = ch_base[CH_DAT];
                   2011:
                   2012:        splx(s);
                   2013:        return c;
                   2014: }
1.5       phil     2015:
1.30      matthias 2016: /* The pc532 does not turn off console polling. */
                   2017: void
                   2018: scncnpollc(dev, on)
1.32      matthias 2019:        dev_t dev;
                   2020:        int on;
1.5       phil     2021: {
1.15      phil     2022: }
                   2023:
1.5       phil     2024: /*
                   2025:  * Console kernel output character routine.
                   2026:  */
1.30      matthias 2027: void
1.64      chs      2028: scncnputc(void *arg, int c)
1.30      matthias 2029: {
1.64      chs      2030:        volatile u_char *ch_base = CHADDR();
                   2031:        volatile u_char *du_base = DUADDR();
                   2032:        int s;
                   2033:
                   2034:        s = spltty();
1.30      matthias 2035:
                   2036:        if (c == '\n')
1.64      chs      2037:                scncnputc(arg, '\r');
1.30      matthias 2038:
1.64      chs      2039:        while ((ch_base[CH_SR] & SR_TX_RDY) == 0)
                   2040:                ;
1.30      matthias 2041:        ch_base[CH_DAT] = c;
1.64      chs      2042:        while ((ch_base[CH_SR] & SR_TX_RDY) == 0)
                   2043:                ;
1.30      matthias 2044:        du_base[DU_ISR];
1.5       phil     2045:
1.30      matthias 2046:        splx(s);
1.5       phil     2047: }

CVSweb <webmaster@jp.NetBSD.org>