[BACK]Return to scif.c CVS log [TXT][DIR] Up to [local] / sys / arch / sh / dev

Annotation of sys/arch/sh/dev/scif.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: scif.c,v 1.4 2006/11/20 17:53:16 drahn Exp $  */
                      2: /*     $NetBSD: scif.c,v 1.47 2006/07/23 22:06:06 ad Exp $ */
                      3:
                      4: /*-
                      5:  * Copyright (C) 1999 T.Horiuchi and SAITOH Masanobu.  All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  * 3. The name of the author may not be used to endorse or promote products
                     16:  *    derived from this software without specific prior written permission.
                     17:  *
                     18:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     19:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     20:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     21:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     22:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     23:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     24:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     25:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     26:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
                     27:  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     28:  */
                     29:
                     30: /*-
                     31:  * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
                     32:  * All rights reserved.
                     33:  *
                     34:  * This code is derived from software contributed to The NetBSD Foundation
                     35:  * by Charles M. Hannum.
                     36:  *
                     37:  * Redistribution and use in source and binary forms, with or without
                     38:  * modification, are permitted provided that the following conditions
                     39:  * are met:
                     40:  * 1. Redistributions of source code must retain the above copyright
                     41:  *    notice, this list of conditions and the following disclaimer.
                     42:  * 2. Redistributions in binary form must reproduce the above copyright
                     43:  *    notice, this list of conditions and the following disclaimer in the
                     44:  *    documentation and/or other materials provided with the distribution.
                     45:  * 3. All advertising materials mentioning features or use of this software
                     46:  *    must display the following acknowledgement:
                     47:  *        This product includes software developed by the NetBSD
                     48:  *        Foundation, Inc. and its contributors.
                     49:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     50:  *    contributors may be used to endorse or promote products derived
                     51:  *    from this software without specific prior written permission.
                     52:  *
                     53:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     54:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     55:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     56:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     57:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     58:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     59:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     60:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     61:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     62:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     63:  * POSSIBILITY OF SUCH DAMAGE.
                     64:  */
                     65:
                     66: /*
                     67:  * Copyright (c) 1991 The Regents of the University of California.
                     68:  * All rights reserved.
                     69:  *
                     70:  * Redistribution and use in source and binary forms, with or without
                     71:  * modification, are permitted provided that the following conditions
                     72:  * are met:
                     73:  * 1. Redistributions of source code must retain the above copyright
                     74:  *    notice, this list of conditions and the following disclaimer.
                     75:  * 2. Redistributions in binary form must reproduce the above copyright
                     76:  *    notice, this list of conditions and the following disclaimer in the
                     77:  *    documentation and/or other materials provided with the distribution.
                     78:  * 3. Neither the name of the University nor the names of its contributors
                     79:  *    may be used to endorse or promote products derived from this software
                     80:  *    without specific prior written permission.
                     81:  *
                     82:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     83:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     84:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     85:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     86:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     87:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     88:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     89:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     90:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     91:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     92:  * SUCH DAMAGE.
                     93:  *
                     94:  *     @(#)com.c       7.5 (Berkeley) 5/16/91
                     95:  */
                     96:
                     97: /*
                     98:  * SH internal serial driver
                     99:  *
                    100:  * This code is derived from both z8530tty.c and com.c
                    101:  */
                    102:
                    103: #include <sys/param.h>
                    104: #include <sys/systm.h>
                    105: #include <sys/tty.h>
                    106: #include <sys/proc.h>
                    107: #include <sys/conf.h>
                    108: #include <sys/file.h>
                    109: #include <sys/syslog.h>
                    110: #include <sys/kernel.h>
                    111: #include <sys/device.h>
                    112: #include <sys/malloc.h>
                    113: #include <sys/timeout.h>
                    114:
                    115: #include <dev/cons.h>
                    116:
                    117: #include <sh/clock.h>
                    118: #include <sh/trap.h>
                    119: #include <machine/intr.h>
                    120: #include <machine/conf.h>
                    121:
                    122: #include <sh/dev/scifreg.h>
                    123:
                    124: #ifdef DDB
                    125: #include <ddb/db_var.h>
                    126: #endif
                    127:
                    128: void   scifstart(struct tty *);
                    129: int    scifparam(struct tty *, struct termios *);
                    130:
                    131: void scifcnprobe(struct consdev *);
                    132: void scifcninit(struct consdev *);
                    133: void scifcnputc(dev_t, int);
                    134: int scifcngetc(dev_t);
                    135: void scifcnpoolc(dev_t, int);
                    136: void scif_intr_init(void);
                    137: int scifintr(void *);
                    138:
                    139: struct scif_softc {
                    140:        struct device sc_dev;           /* boilerplate */
                    141:        struct tty *sc_tty;
                    142:        void *sc_si;
                    143:
                    144:        struct timeout sc_diag_tmo;
                    145:
                    146: #if 0
                    147:        bus_space_tag_t sc_iot;         /* ISA i/o space identifier */
                    148:        bus_space_handle_t   sc_ioh;    /* ISA io handle */
                    149:
                    150:        int sc_drq;
                    151:
                    152:        int sc_frequency;
                    153: #endif
                    154:
                    155:        u_int sc_overflows,
                    156:              sc_floods,
                    157:              sc_errors;                /* number of retries so far */
                    158:        u_char sc_status[7];            /* copy of registers */
                    159:
                    160:        int sc_hwflags;
                    161:        int sc_swflags;
                    162:        u_int sc_fifolen;
                    163:
                    164:        u_int sc_r_hiwat,
                    165:              sc_r_lowat;
                    166:        u_char *volatile sc_rbget,
                    167:               *volatile sc_rbput;
                    168:        volatile u_int sc_rbavail;
                    169:        u_char *sc_rbuf,
                    170:               *sc_ebuf;
                    171:
                    172:        u_char *sc_tba;                 /* transmit buffer address */
                    173:        u_int sc_tbc,                   /* transmit byte count */
                    174:              sc_heldtbc;
                    175:
                    176:        volatile u_char sc_rx_flags,
                    177: #define        RX_TTY_BLOCKED          0x01
                    178: #define        RX_TTY_OVERFLOWED       0x02
                    179: #define        RX_IBUF_BLOCKED         0x04
                    180: #define        RX_IBUF_OVERFLOWED      0x08
                    181: #define        RX_ANY_BLOCK            0x0f
                    182:                        sc_tx_busy,     /* working on an output chunk */
                    183:                        sc_tx_done,     /* done with one output chunk */
                    184:                        sc_tx_stopped,  /* H/W level stop (lost CTS) */
                    185:                        sc_st_check,    /* got a status interrupt */
                    186:                        sc_rx_ready;
                    187:
                    188:        volatile u_char sc_heldchange;
                    189: };
                    190:
                    191: /* controller driver configuration */
                    192: int scif_match(struct device *, void *, void *);
                    193: void scif_attach(struct device *, struct device *, void *);
                    194:
                    195: void   scif_break(struct scif_softc *, int);
                    196: void   scif_iflush(struct scif_softc *);
                    197:
                    198: void   scifsoft(void *);
                    199: void scif_rxsoft(struct scif_softc *, struct tty *);
                    200: void scif_txsoft(struct scif_softc *, struct tty *);
                    201: void scif_stsoft(struct scif_softc *, struct tty *);
                    202: void scif_schedrx(struct scif_softc *);
                    203: void   scifdiag(void *);
                    204:
                    205:
                    206: #define        SCIFUNIT_MASK           0x7ffff
                    207: #define        SCIFDIALOUT_MASK        0x80000
                    208:
                    209: #define        SCIFUNIT(x)     (minor(x) & SCIFUNIT_MASK)
                    210: #define        SCIFDIALOUT(x)  (minor(x) & SCIFDIALOUT_MASK)
                    211:
                    212: /* Hardware flag masks */
                    213: #define        SCIF_HW_NOIEN   0x01
                    214: #define        SCIF_HW_FIFO    0x02
                    215: #define        SCIF_HW_FLOW    0x08
                    216: #define        SCIF_HW_DEV_OK  0x20
                    217: #define        SCIF_HW_CONSOLE 0x40
                    218:
                    219: /* Buffer size for character buffer */
                    220: #define        SCIF_RING_SIZE  2048
                    221:
                    222: /* Stop input when 3/4 of the ring is full; restart when only 1/4 is full. */
                    223: u_int scif_rbuf_hiwat = (SCIF_RING_SIZE * 1) / 4;
                    224: u_int scif_rbuf_lowat = (SCIF_RING_SIZE * 3) / 4;
                    225:
                    226: #define        CONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */
                    227: int scifconscflag = CONMODE;
                    228: int scifisconsole = 0;
                    229:
                    230: #ifdef SCIFCN_SPEED
                    231: unsigned int scifcn_speed = SCIFCN_SPEED;
                    232: #else
                    233: unsigned int scifcn_speed = 9600;
                    234: #endif
                    235:
                    236: #define        divrnd(n, q)    (((n)*2/(q)+1)/2)       /* divide and round off */
                    237:
                    238: u_int scif_rbuf_size = SCIF_RING_SIZE;
                    239:
                    240: struct cfattach scif_ca = {
                    241:        sizeof(struct scif_softc), scif_match, scif_attach
                    242: };
                    243:
                    244: struct cfdriver scif_cd = {
                    245:        0, "scif", DV_DULL
                    246: };
                    247:
                    248: static int scif_attached;
                    249:
                    250: void InitializeScif(unsigned int);
                    251:
                    252: /*
                    253:  * following functions are debugging prupose only
                    254:  */
                    255: #define        CR      0x0D
                    256: #define        USART_ON (unsigned int)~0x08
                    257:
                    258: void scif_putc(unsigned char);
                    259: unsigned char scif_getc(void);
                    260: int ScifErrCheck(void);
                    261:
                    262:
                    263: /* XXX: uwe
                    264:  * Prepare for bus_spacification.  The difference in access widths is
                    265:  * still handled by the magic definitions in scifreg.h
                    266:  */
                    267: #define scif_smr_read()                SHREG_SCSMR2
                    268: #define scif_smr_write(v)      (SHREG_SCSMR2 = (v))
                    269:
                    270: #define scif_brr_read()                SHREG_SCBRR2
                    271: #define scif_brr_write(v)      (SHREG_SCBRR2 = (v))
                    272:
                    273: #define scif_scr_read()                SHREG_SCSCR2
                    274: #define scif_scr_write(v)      (SHREG_SCSCR2 = (v))
                    275:
                    276: #define scif_ftdr_write(v)     (SHREG_SCFTDR2 = (v))
                    277:
                    278: #define scif_ssr_read()                SHREG_SCSSR2
                    279: #define scif_ssr_write(v)      (SHREG_SCSSR2 = (v))
                    280:
                    281: #define scif_frdr_read()       SHREG_SCFRDR2
                    282:
                    283: #define scif_fcr_read()                SHREG_SCFCR2
                    284: #define scif_fcr_write(v)      (SHREG_SCFCR2 = (v))
                    285:
                    286: #define scif_fdr_read()                SHREG_SCFDR2
                    287:
                    288: #ifdef SH4 /* additional registers in sh4 */
                    289:
                    290: #define scif_sptr_read()       SHREG_SCSPTR2
                    291: #define scif_sptr_write(v)     (SHREG_SCSPTR2 = (v))
                    292:
                    293: #define scif_lsr_read()                SHREG_SCLSR2
                    294: #define scif_lsr_write(v)      (SHREG_SCLSR2 = (v))
                    295:
                    296: #endif /* SH4 */
                    297:
                    298:
                    299: /*
                    300:  * InitializeScif
                    301:  * : unsigned int bps;
                    302:  * : SCIF(Serial Communication Interface)
                    303:  */
                    304:
                    305: void
                    306: InitializeScif(unsigned int bps)
                    307: {
                    308:        /* Initialize SCR */
                    309:        scif_scr_write(0x00);
                    310:
                    311: #if 0
                    312:        scif_fcr_write(SCFCR2_TFRST | SCFCR2_RFRST | SCFCR2_MCE);
                    313: #else
                    314:        scif_fcr_write(SCFCR2_TFRST | SCFCR2_RFRST);
                    315: #endif
                    316:        /* Serial Mode Register */
                    317:        scif_smr_write(0x00);   /* 8bit,NonParity,Even,1Stop */
                    318:
                    319:        /* Bit Rate Register */
                    320:        scif_brr_write(divrnd(sh_clock_get_pclock(), 32 * bps) - 1);
                    321:
                    322:        /*
                    323:         * wait 2m Sec, because Send/Recv must begin 1 bit period after
                    324:         * BRR is set.
                    325:         */
                    326:        delay(2000);
                    327:
                    328: #if 0
                    329:        scif_fcr_write(FIFO_RCV_TRIGGER_14 | FIFO_XMT_TRIGGER_1 | SCFCR2_MCE);
                    330: #else
                    331:        scif_fcr_write(FIFO_RCV_TRIGGER_14 | FIFO_XMT_TRIGGER_1);
                    332: #endif
                    333:
                    334:        /* Send permission, Receive permission ON */
                    335:        scif_scr_write(SCSCR2_TE | SCSCR2_RE);
                    336:
                    337:        /* Serial Status Register */
                    338:        scif_ssr_write(scif_ssr_read() & SCSSR2_TDFE); /* Clear Status */
                    339: }
                    340:
                    341:
                    342: /*
                    343:  * scif_putc
                    344:  *  : unsigned char c;
                    345:  */
                    346:
                    347: void
                    348: scif_putc(unsigned char c)
                    349: {
                    350:        /* wait for ready */
                    351:        while ((scif_fdr_read() & SCFDR2_TXCNT) == SCFDR2_TXF_FULL)
                    352:                continue;
                    353:
                    354:        /* write send data to send register */
                    355:        scif_ftdr_write(c);
                    356:
                    357:        /* clear ready flag */
                    358:        scif_ssr_write(scif_ssr_read() & ~(SCSSR2_TDFE | SCSSR2_TEND));
                    359: }
                    360:
                    361: /*
                    362:  * : ScifErrCheck
                    363:  *     0x80 = error
                    364:  *     0x08 = frame error
                    365:  *     0x04 = parity error
                    366:  */
                    367: int
                    368: ScifErrCheck(void)
                    369: {
                    370:        return (scif_ssr_read() & (SCSSR2_ER | SCSSR2_FER | SCSSR2_PER));
                    371: }
                    372:
                    373: /*
                    374:  * scif_getc
                    375:  */
                    376: unsigned char
                    377: scif_getc(void)
                    378: {
                    379:        unsigned char c, err_c;
                    380: #ifdef SH4
                    381:        unsigned short err_c2 = 0; /* XXXGCC: -Wuninitialized */
                    382: #endif
                    383:
                    384:        for (;;) {
                    385:                /* wait for ready */
                    386:                while ((scif_fdr_read() & SCFDR2_RECVCNT) == 0)
                    387:                        continue;
                    388:
                    389:                c = scif_frdr_read();
                    390:                err_c = scif_ssr_read();
                    391:                scif_ssr_write(scif_ssr_read()
                    392:                        & ~(SCSSR2_ER | SCSSR2_BRK | SCSSR2_RDF | SCSSR2_DR));
                    393: #ifdef SH4
                    394:                if (CPU_IS_SH4) {
                    395:                        err_c2 = scif_lsr_read();
                    396:                        scif_lsr_write(scif_lsr_read() & ~SCLSR2_ORER);
                    397:                }
                    398: #endif
                    399:                if ((err_c & (SCSSR2_ER | SCSSR2_BRK | SCSSR2_FER
                    400:                    | SCSSR2_PER)) == 0) {
                    401: #ifdef SH4
                    402:                        if (CPU_IS_SH4 && ((err_c2 & SCLSR2_ORER) == 0))
                    403: #endif
                    404:                        return(c);
                    405:                }
                    406:        }
                    407:
                    408: }
                    409:
                    410: int
                    411: scif_match(struct device *parent, void *vcf, void *aux)
                    412: {
                    413:        if (scif_attached != 0)
                    414:                return 0;
                    415:
                    416:        return 1;
                    417: }
                    418:
                    419: void
                    420: scif_attach(struct device *parent, struct device *self, void *aux)
                    421: {
                    422:        struct scif_softc *sc = (struct scif_softc *)self;
                    423:        struct tty *tp;
                    424:
                    425:        scif_attached = 1;
                    426:
                    427:        sc->sc_hwflags = 0;     /* XXX */
                    428:        sc->sc_swflags = 0;     /* XXX */
                    429:        sc->sc_fifolen = 16;
                    430:
                    431:        if (scifisconsole) {
                    432:                /* InitializeScif(scifcn_speed); */
                    433:                SET(sc->sc_hwflags, SCIF_HW_CONSOLE);
                    434:                SET(sc->sc_swflags, TIOCFLAG_SOFTCAR);
                    435:                printf("\n%s: console\n", sc->sc_dev.dv_xname);
                    436:        } else {
                    437:                InitializeScif(9600);
                    438:                printf("\n");
                    439:        }
                    440:
                    441:        timeout_set(&sc->sc_diag_tmo, scifdiag, sc);
                    442: #ifdef SH4
                    443:        intc_intr_establish(SH4_INTEVT_SCIF_ERI, IST_LEVEL, IPL_TTY,
                    444:            scifintr, sc, self->dv_xname);
                    445:        intc_intr_establish(SH4_INTEVT_SCIF_RXI, IST_LEVEL, IPL_TTY,
                    446:            scifintr, sc, self->dv_xname);
                    447:        intc_intr_establish(SH4_INTEVT_SCIF_BRI, IST_LEVEL, IPL_TTY,
                    448:            scifintr, sc, self->dv_xname);
                    449:        intc_intr_establish(SH4_INTEVT_SCIF_TXI, IST_LEVEL, IPL_TTY,
                    450:            scifintr, sc, self->dv_xname);
                    451: #else
                    452:        intc_intr_establish(SH7709_INTEVT2_SCIF_ERI, IST_LEVEL, IPL_TTY,
                    453:            scifintr, sc, self->dv_xname);
                    454:        intc_intr_establish(SH7709_INTEVT2_SCIF_RXI, IST_LEVEL, IPL_TTY,
                    455:            scifintr, sc, self->dv_xname);
                    456:        intc_intr_establish(SH7709_INTEVT2_SCIF_BRI, IST_LEVEL, IPL_TTY,
                    457:            scifintr, sc, self->dv_xname);
                    458:        intc_intr_establish(SH7709_INTEVT2_SCIF_TXI, IST_LEVEL, IPL_TTY,
                    459:            scifintr, sc, self->dv_xname);
                    460: #endif
                    461:
                    462:        sc->sc_si = softintr_establish(IPL_SOFTSERIAL, scifsoft, sc);
                    463:        SET(sc->sc_hwflags, SCIF_HW_DEV_OK);
                    464:
                    465:        tp = ttymalloc();
                    466:        tp->t_oproc = scifstart;
                    467:        tp->t_param = scifparam;
                    468:        tp->t_hwiflow = NULL;
                    469:
                    470:        sc->sc_tty = tp;
                    471:        sc->sc_rbuf = malloc(scif_rbuf_size << 1, M_DEVBUF, M_NOWAIT);
                    472:        if (sc->sc_rbuf == NULL) {
                    473:                printf("%s: unable to allocate ring buffer\n",
                    474:                    sc->sc_dev.dv_xname);
                    475:                return;
                    476:        }
                    477:        sc->sc_ebuf = sc->sc_rbuf + (scif_rbuf_size << 1);
                    478: }
                    479:
                    480: /*
                    481:  * Start or restart transmission.
                    482:  */
                    483: void
                    484: scifstart(struct tty *tp)
                    485: {
                    486:        struct scif_softc *sc = scif_cd.cd_devs[SCIFUNIT(tp->t_dev)];
                    487:        int s;
                    488:
                    489:        s = spltty();
                    490:        if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP))
                    491:                goto out;
                    492:        if (sc->sc_tx_stopped)
                    493:                goto out;
                    494:
                    495:        if (tp->t_outq.c_cc <= tp->t_lowat) {
                    496:                if (ISSET(tp->t_state, TS_ASLEEP)) {
                    497:                        CLR(tp->t_state, TS_ASLEEP);
                    498:                        wakeup(&tp->t_outq);
                    499:                }
                    500:                selwakeup(&tp->t_wsel);
                    501:                if (tp->t_outq.c_cc == 0)
                    502:                        goto out;
                    503:        }
                    504:
                    505:        /* Grab the first contiguous region of buffer space. */
                    506:        {
                    507:                u_char *tba;
                    508:                int tbc;
                    509:
                    510:                tba = tp->t_outq.c_cf;
                    511:                tbc = ndqb(&tp->t_outq, 0);
                    512:
                    513:
                    514:                sc->sc_tba = tba;
                    515:                sc->sc_tbc = tbc;
                    516:        }
                    517:
                    518:        SET(tp->t_state, TS_BUSY);
                    519:        sc->sc_tx_busy = 1;
                    520:
                    521:        /* Enable transmit completion interrupts if necessary. */
                    522:        scif_scr_write(scif_scr_read() | SCSCR2_TIE | SCSCR2_RIE);
                    523:
                    524:        /* Output the first chunk of the contiguous buffer. */
                    525:        {
                    526:                int n;
                    527:                int maxchars;
                    528:                int i;
                    529:
                    530:                n = sc->sc_tbc;
                    531:                maxchars = sc->sc_fifolen
                    532:                        - ((scif_fdr_read() & SCFDR2_TXCNT) >> 8);
                    533:                if (n > maxchars)
                    534:                        n = maxchars;
                    535:
                    536:                for (i = 0; i < n; i++) {
                    537:                        scif_putc(*(sc->sc_tba));
                    538:                        sc->sc_tba++;
                    539:                }
                    540:                sc->sc_tbc -= n;
                    541:        }
                    542: out:
                    543:        splx(s);
                    544:        return;
                    545: }
                    546:
                    547: /*
                    548:  * Set SCIF tty parameters from termios.
                    549:  * XXX - Should just copy the whole termios after
                    550:  * making sure all the changes could be done.
                    551:  */
                    552: int
                    553: scifparam(struct tty *tp, struct termios *t)
                    554: {
                    555:        struct scif_softc *sc = scif_cd.cd_devs[SCIFUNIT(tp->t_dev)];
                    556:        int ospeed = t->c_ospeed;
                    557:        int s;
                    558:
                    559:        /* Check requested parameters. */
                    560:        if (ospeed < 0)
                    561:                return (EINVAL);
                    562:        if (t->c_ispeed && t->c_ispeed != t->c_ospeed)
                    563:                return (EINVAL);
                    564:
                    565:        /*
                    566:         * For the console, always force CLOCAL and !HUPCL, so that the port
                    567:         * is always active.
                    568:         */
                    569:        if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR) ||
                    570:            ISSET(sc->sc_hwflags, SCIF_HW_CONSOLE)) {
                    571:                SET(t->c_cflag, CLOCAL);
                    572:                CLR(t->c_cflag, HUPCL);
                    573:        }
                    574:
                    575:        /*
                    576:         * If there were no changes, don't do anything.  This avoids dropping
                    577:         * input and improves performance when all we did was frob things like
                    578:         * VMIN and VTIME.
                    579:         */
                    580:        if (tp->t_ospeed == t->c_ospeed &&
                    581:            tp->t_cflag == t->c_cflag)
                    582:                return (0);
                    583:
                    584: #if 0
                    585: /* XXX (msaitoh) */
                    586:        lcr = ISSET(sc->sc_lcr, LCR_SBREAK) | cflag2lcr(t->c_cflag);
                    587: #endif
                    588:
                    589:        s = spltty();
                    590:
                    591:        /*
                    592:         * Set the flow control pins depending on the current flow control
                    593:         * mode.
                    594:         */
                    595:        if (ISSET(t->c_cflag, CRTSCTS)) {
                    596:                scif_fcr_write(scif_fcr_read() | SCFCR2_MCE);
                    597:        } else {
                    598:                scif_fcr_write(scif_fcr_read() & ~SCFCR2_MCE);
                    599:        }
                    600:
                    601:        scif_brr_write(divrnd(sh_clock_get_pclock(), 32 * ospeed) -1);
                    602:
                    603:        /*
                    604:         * Set the FIFO threshold based on the receive speed.
                    605:         *
                    606:         *  * If it's a low speed, it's probably a mouse or some other
                    607:         *    interactive device, so set the threshold low.
                    608:         *  * If it's a high speed, trim the trigger level down to prevent
                    609:         *    overflows.
                    610:         *  * Otherwise set it a bit higher.
                    611:         */
                    612: #if 0
                    613: /* XXX (msaitoh) */
                    614:        if (ISSET(sc->sc_hwflags, SCIF_HW_HAYESP))
                    615:                sc->sc_fifo = FIFO_DMA_MODE | FIFO_ENABLE | FIFO_TRIGGER_8;
                    616:        else if (ISSET(sc->sc_hwflags, SCIF_HW_FIFO))
                    617:                sc->sc_fifo = FIFO_ENABLE |
                    618:                    (t->c_ospeed <= 1200 ? FIFO_TRIGGER_1 :
                    619:                     t->c_ospeed <= 38400 ? FIFO_TRIGGER_8 : FIFO_TRIGGER_4);
                    620:        else
                    621:                sc->sc_fifo = 0;
                    622: #endif
                    623:
                    624:        /* And copy to tty. */
                    625:        tp->t_ispeed = 0;
                    626:        tp->t_ospeed = t->c_ospeed;
                    627:        tp->t_cflag = t->c_cflag;
                    628:
                    629:        if (!sc->sc_heldchange) {
                    630:                if (sc->sc_tx_busy) {
                    631:                        sc->sc_heldtbc = sc->sc_tbc;
                    632:                        sc->sc_tbc = 0;
                    633:                        sc->sc_heldchange = 1;
                    634:                }
                    635: #if 0
                    636: /* XXX (msaitoh) */
                    637:                else
                    638:                        scif_loadchannelregs(sc);
                    639: #endif
                    640:        }
                    641:
                    642:        if (!ISSET(t->c_cflag, CHWFLOW)) {
                    643:                /* Disable the high water mark. */
                    644:                sc->sc_r_hiwat = 0;
                    645:                sc->sc_r_lowat = 0;
                    646:                if (ISSET(sc->sc_rx_flags, RX_TTY_OVERFLOWED)) {
                    647:                        CLR(sc->sc_rx_flags, RX_TTY_OVERFLOWED);
                    648:                        scif_schedrx(sc);
                    649:                }
                    650:        } else {
                    651:                sc->sc_r_hiwat = scif_rbuf_hiwat;
                    652:                sc->sc_r_lowat = scif_rbuf_lowat;
                    653:        }
                    654:
                    655:        splx(s);
                    656:
                    657: #ifdef SCIF_DEBUG
                    658:        if (scif_debug)
                    659:                scifstatus(sc, "scifparam ");
                    660: #endif
                    661:
                    662:        if (!ISSET(t->c_cflag, CHWFLOW)) {
                    663:                if (sc->sc_tx_stopped) {
                    664:                        sc->sc_tx_stopped = 0;
                    665:                        scifstart(tp);
                    666:                }
                    667:        }
                    668:
                    669:        return (0);
                    670: }
                    671:
                    672: void
                    673: scif_iflush(struct scif_softc *sc)
                    674: {
                    675:        int i;
                    676:        unsigned char c;
                    677:
                    678:        i = scif_fdr_read() & SCFDR2_RECVCNT;
                    679:
                    680:        while (i > 0) {
                    681:                c = scif_frdr_read();
                    682:                scif_ssr_write(scif_ssr_read() & ~(SCSSR2_RDF | SCSSR2_DR));
                    683:                i--;
                    684:        }
                    685: }
                    686:
                    687: int
                    688: scifopen(dev_t dev, int flag, int mode, struct proc *p)
                    689: {
                    690:        int unit = SCIFUNIT(dev);
                    691:        struct scif_softc *sc;
                    692:        struct tty *tp;
                    693:        int s;
                    694:        int error;
                    695:
                    696:        if (unit >= scif_cd.cd_ndevs)
                    697:                return (ENXIO);
                    698:        sc = scif_cd.cd_devs[unit];
                    699:        if (sc == 0 || !ISSET(sc->sc_hwflags, SCIF_HW_DEV_OK) ||
                    700:            sc->sc_rbuf == NULL)
                    701:                return (ENXIO);
                    702:
                    703:        tp = sc->sc_tty;
                    704:
                    705:        if (ISSET(tp->t_state, TS_ISOPEN) &&
                    706:            ISSET(tp->t_state, TS_XCLUDE) &&
                    707:            p->p_ucred->cr_uid != 0)
                    708:                return (EBUSY);
                    709:
                    710:        s = spltty();
                    711:
                    712:        /*
                    713:         * Do the following iff this is a first open.
                    714:         */
                    715:        if (!ISSET(tp->t_state, TS_ISOPEN)) {
                    716:                struct termios t;
                    717:
                    718:                tp->t_dev = dev;
                    719:
                    720:
                    721:                /* Turn on interrupts. */
                    722:                scif_scr_write(scif_scr_read() | SCSCR2_TIE | SCSCR2_RIE);
                    723:
                    724:                /*
                    725:                 * Initialize the termios status to the defaults.  Add in the
                    726:                 * sticky bits from TIOCSFLAGS.
                    727:                 */
                    728:                t.c_ispeed = 0;
                    729:                if (ISSET(sc->sc_hwflags, SCIF_HW_CONSOLE)) {
                    730:                        t.c_ospeed = scifcn_speed;      /* XXX (msaitoh) */
                    731:                        t.c_cflag = scifconscflag;
                    732:                } else {
                    733:                        t.c_ospeed = TTYDEF_SPEED;
                    734:                        t.c_cflag = TTYDEF_CFLAG;
                    735:                }
                    736:                if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL))
                    737:                        SET(t.c_cflag, CLOCAL);
                    738:                if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS))
                    739:                        SET(t.c_cflag, CRTSCTS);
                    740:                if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF))
                    741:                        SET(t.c_cflag, MDMBUF);
                    742:                /* Make sure scifparam() will do something. */
                    743:                tp->t_ospeed = 0;
                    744:                (void) scifparam(tp, &t);
                    745:
                    746:                /*
                    747:                 * XXX landisk has no hardware flow control!
                    748:                 * When porting to another platform, fix this somehow
                    749:                 */
                    750:                SET(tp->t_state, TS_CARR_ON);
                    751:
                    752:                tp->t_iflag = TTYDEF_IFLAG;
                    753:                tp->t_oflag = TTYDEF_OFLAG;
                    754:                tp->t_lflag = TTYDEF_LFLAG;
                    755:                ttychars(tp);
                    756:                ttsetwater(tp);
                    757:
                    758:                /* Clear the input ring, and unblock. */
                    759:                sc->sc_rbput = sc->sc_rbget = sc->sc_rbuf;
                    760:                sc->sc_rbavail = scif_rbuf_size;
                    761:                scif_iflush(sc);
                    762:                CLR(sc->sc_rx_flags, RX_ANY_BLOCK);
                    763: #if 0
                    764: /* XXX (msaitoh) */
                    765:                scif_hwiflow(sc);
                    766: #endif
                    767:
                    768: #ifdef SCIF_DEBUG
                    769:                if (scif_debug)
                    770:                        scifstatus(sc, "scifopen  ");
                    771: #endif
                    772:
                    773:        }
                    774:
                    775:        splx(s);
                    776:
                    777:        error = ttyopen(dev, tp);
                    778:        if (error)
                    779:                goto bad;
                    780:
                    781:        error = (*linesw[tp->t_line].l_open)(dev, tp);
                    782:        if (error)
                    783:                goto bad;
                    784:
                    785:        return (0);
                    786:
                    787: bad:
                    788:
                    789:        return (error);
                    790: }
                    791:
                    792: int
                    793: scifclose(dev_t dev, int flag, int mode, struct proc *p)
                    794: {
                    795:        struct scif_softc *sc = scif_cd.cd_devs[SCIFUNIT(dev)];
                    796:        struct tty *tp = sc->sc_tty;
                    797:
                    798:        /* XXX This is for cons.c. */
                    799:        if (!ISSET(tp->t_state, TS_ISOPEN))
                    800:                return (0);
                    801:
                    802:        (*linesw[tp->t_line].l_close)(tp, flag);
                    803:        ttyclose(tp);
                    804:
                    805:        return (0);
                    806: }
                    807:
                    808: int
                    809: scifread(dev_t dev, struct uio *uio, int flag)
                    810: {
                    811:        struct scif_softc *sc = scif_cd.cd_devs[SCIFUNIT(dev)];
                    812:        struct tty *tp = sc->sc_tty;
                    813:
                    814:        return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
                    815: }
                    816:
                    817: int
                    818: scifwrite(dev_t dev, struct uio *uio, int flag)
                    819: {
                    820:        struct scif_softc *sc = scif_cd.cd_devs[SCIFUNIT(dev)];
                    821:        struct tty *tp = sc->sc_tty;
                    822:
                    823:        return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
                    824: }
                    825:
                    826: #if 0
                    827: int
                    828: scifpoll(dev_t dev, int events, struct proc *p)
                    829: {
                    830:        struct scif_softc *sc = scif_cd.cd_devs[SCIFUNIT(dev)];
                    831:        struct tty *tp = sc->sc_tty;
                    832:
                    833:        return ((*linesw[tp->t_line].l_poll)(tp, events, p));
                    834: }
                    835: #endif
                    836:
                    837: struct tty *
                    838: sciftty(dev_t dev)
                    839: {
                    840:        struct scif_softc *sc = scif_cd.cd_devs[SCIFUNIT(dev)];
                    841:        struct tty *tp = sc->sc_tty;
                    842:
                    843:        return (tp);
                    844: }
                    845:
                    846: int
                    847: scifioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
                    848: {
                    849:        struct scif_softc *sc = scif_cd.cd_devs[SCIFUNIT(dev)];
                    850:        struct tty *tp = sc->sc_tty;
                    851:        int error;
                    852:        int s;
                    853:
                    854:        error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
                    855:        if (error != -1)
                    856:                return (error);
                    857:
                    858:        error = ttioctl(tp, cmd, data, flag, p);
                    859:        if (error != -1)
                    860:                return (error);
                    861:
                    862:        error = 0;
                    863:
                    864:        s = spltty();
                    865:
                    866:        switch (cmd) {
                    867:        case TIOCSBRK:
                    868:                scif_break(sc, 1);
                    869:                break;
                    870:
                    871:        case TIOCCBRK:
                    872:                scif_break(sc, 0);
                    873:                break;
                    874:
                    875:        case TIOCGFLAGS:
                    876:                *(int *)data = sc->sc_swflags;
                    877:                break;
                    878:
                    879:        case TIOCSFLAGS:
                    880:                error = suser(p, 0);
                    881:                if (error)
                    882:                        break;
                    883:                sc->sc_swflags = *(int *)data;
                    884:                break;
                    885:
                    886:        default:
                    887:                error = -1;
                    888:                break;
                    889:        }
                    890:
                    891:        splx(s);
                    892:
                    893:        return (error);
                    894: }
                    895:
                    896: void
                    897: scif_schedrx(struct scif_softc *sc)
                    898: {
                    899:        sc->sc_rx_ready = 1;
                    900:
                    901:        /* Wake up the poller. */
                    902:        softintr_schedule(sc->sc_si);
                    903: }
                    904:
                    905: void
                    906: scif_break(struct scif_softc *sc, int onoff)
                    907: {
                    908:        if (onoff)
                    909:                scif_ssr_write(scif_ssr_read() & ~SCSSR2_TDFE);
                    910:        else
                    911:                scif_ssr_write(scif_ssr_read() | SCSSR2_TDFE);
                    912:
                    913: #if 0  /* XXX */
                    914:        if (!sc->sc_heldchange) {
                    915:                if (sc->sc_tx_busy) {
                    916:                        sc->sc_heldtbc = sc->sc_tbc;
                    917:                        sc->sc_tbc = 0;
                    918:                        sc->sc_heldchange = 1;
                    919:                } else
                    920:                        scif_loadchannelregs(sc);
                    921:        }
                    922: #endif
                    923: }
                    924:
                    925: /*
                    926:  * Stop output, e.g., for ^S or output flush.
                    927:  */
                    928: int
                    929: scifstop(struct tty *tp, int flag)
                    930: {
                    931:        struct scif_softc *sc = scif_cd.cd_devs[SCIFUNIT(tp->t_dev)];
                    932:        int s;
                    933:
                    934:        s = spltty();
                    935:        if (ISSET(tp->t_state, TS_BUSY)) {
                    936:                /* Stop transmitting at the next chunk. */
                    937:                sc->sc_tbc = 0;
                    938:                sc->sc_heldtbc = 0;
                    939:                if (!ISSET(tp->t_state, TS_TTSTOP))
                    940:                        SET(tp->t_state, TS_FLUSH);
                    941:        }
                    942:        splx(s);
                    943:        return (0);
                    944: }
                    945:
                    946: void
                    947: scif_intr_init()
                    948: {
                    949:        /* XXX */
                    950: }
                    951:
                    952: void
                    953: scifdiag(void *arg)
                    954: {
                    955:        struct scif_softc *sc = arg;
                    956:        int overflows, floods;
                    957:        int s;
                    958:
                    959:        s = spltty();
                    960:        overflows = sc->sc_overflows;
                    961:        sc->sc_overflows = 0;
                    962:        floods = sc->sc_floods;
                    963:        sc->sc_floods = 0;
                    964:        sc->sc_errors = 0;
                    965:        splx(s);
                    966:
                    967:        log(LOG_WARNING, "%s: %d silo overflow%s, %d ibuf flood%s\n",
                    968:            sc->sc_dev.dv_xname,
                    969:            overflows, overflows == 1 ? "" : "s",
                    970:            floods, floods == 1 ? "" : "s");
                    971: }
                    972:
                    973: void
                    974: scif_rxsoft(struct scif_softc *sc, struct tty *tp)
                    975: {
                    976:        int (*rint)(int, struct tty *) = *linesw[tp->t_line].l_rint;
                    977:        u_char *get, *end;
                    978:        u_int cc, scc;
                    979:        u_char ssr2;
                    980:        int code;
                    981:        int s;
                    982:
                    983:        end = sc->sc_ebuf;
                    984:        get = sc->sc_rbget;
                    985:        scc = cc = scif_rbuf_size - sc->sc_rbavail;
                    986:
                    987:        if (cc == scif_rbuf_size) {
                    988:                sc->sc_floods++;
                    989:                if (sc->sc_errors++ == 0)
                    990:                        timeout_add(&sc->sc_diag_tmo, 60 * hz);
                    991:        }
                    992:
                    993:        while (cc) {
                    994:                code = get[0];
                    995:                ssr2 = get[1];
                    996:                if (ISSET(ssr2, SCSSR2_BRK | SCSSR2_FER | SCSSR2_PER)) {
                    997:                        if (ISSET(ssr2, SCSSR2_BRK | SCSSR2_FER))
                    998:                                SET(code, TTY_FE);
                    999:                        if (ISSET(ssr2, SCSSR2_PER))
                   1000:                                SET(code, TTY_PE);
                   1001:                }
                   1002:                if ((*rint)(code, tp) == -1) {
                   1003:                        /*
                   1004:                         * The line discipline's buffer is out of space.
                   1005:                         */
                   1006:                        if (!ISSET(sc->sc_rx_flags, RX_TTY_BLOCKED)) {
                   1007:                                /*
                   1008:                                 * We're either not using flow control, or the
                   1009:                                 * line discipline didn't tell us to block for
                   1010:                                 * some reason.  Either way, we have no way to
                   1011:                                 * know when there's more space available, so
                   1012:                                 * just drop the rest of the data.
                   1013:                                 */
                   1014:                                get += cc << 1;
                   1015:                                if (get >= end)
                   1016:                                        get -= scif_rbuf_size << 1;
                   1017:                                cc = 0;
                   1018:                        } else {
                   1019:                                /*
                   1020:                                 * Don't schedule any more receive processing
                   1021:                                 * until the line discipline tells us there's
                   1022:                                 * space available (through scifhwiflow()).
                   1023:                                 * Leave the rest of the data in the input
                   1024:                                 * buffer.
                   1025:                                 */
                   1026:                                SET(sc->sc_rx_flags, RX_TTY_OVERFLOWED);
                   1027:                        }
                   1028:                        break;
                   1029:                }
                   1030:                get += 2;
                   1031:                if (get >= end)
                   1032:                        get = sc->sc_rbuf;
                   1033:                cc--;
                   1034:        }
                   1035:
                   1036:        if (cc != scc) {
                   1037:                sc->sc_rbget = get;
                   1038:                s = spltty();
                   1039:                cc = sc->sc_rbavail += scc - cc;
                   1040:                /* Buffers should be ok again, release possible block. */
                   1041:                if (cc >= sc->sc_r_lowat) {
                   1042:                        if (ISSET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED)) {
                   1043:                                CLR(sc->sc_rx_flags, RX_IBUF_OVERFLOWED);
                   1044:                                scif_scr_write(scif_scr_read() | SCSCR2_RIE);
                   1045:                        }
                   1046: #if 0
                   1047:                        if (ISSET(sc->sc_rx_flags, RX_IBUF_BLOCKED)) {
                   1048:                                CLR(sc->sc_rx_flags, RX_IBUF_BLOCKED);
                   1049:                                scif_hwiflow(sc);
                   1050:                        }
                   1051: #endif
                   1052:                }
                   1053:                splx(s);
                   1054:        }
                   1055: }
                   1056:
                   1057: void
                   1058: scif_txsoft(struct scif_softc *sc, struct tty *tp)
                   1059: {
                   1060:        CLR(tp->t_state, TS_BUSY);
                   1061:        if (ISSET(tp->t_state, TS_FLUSH))
                   1062:                CLR(tp->t_state, TS_FLUSH);
                   1063:        else
                   1064:                ndflush(&tp->t_outq, (int)(sc->sc_tba - tp->t_outq.c_cf));
                   1065:        (*linesw[tp->t_line].l_start)(tp);
                   1066: }
                   1067:
                   1068: void
                   1069: scif_stsoft(struct scif_softc *sc, struct tty *tp)
                   1070: {
                   1071: #if 0
                   1072: /* XXX (msaitoh) */
                   1073:        u_char msr, delta;
                   1074:        int s;
                   1075:
                   1076:        s = spltty();
                   1077:        msr = sc->sc_msr;
                   1078:        delta = sc->sc_msr_delta;
                   1079:        sc->sc_msr_delta = 0;
                   1080:        splx(s);
                   1081:
                   1082:        if (ISSET(delta, sc->sc_msr_dcd)) {
                   1083:                /*
                   1084:                 * Inform the tty layer that carrier detect changed.
                   1085:                 */
                   1086:                (void) (*linesw[tp->t_line].l_modem)(tp, ISSET(msr, MSR_DCD));
                   1087:        }
                   1088:
                   1089:        if (ISSET(delta, sc->sc_msr_cts)) {
                   1090:                /* Block or unblock output according to flow control. */
                   1091:                if (ISSET(msr, sc->sc_msr_cts)) {
                   1092:                        sc->sc_tx_stopped = 0;
                   1093:                        (*linesw[tp->t_line].l_start)(tp);
                   1094:                } else {
                   1095:                        sc->sc_tx_stopped = 1;
                   1096:                }
                   1097:        }
                   1098:
                   1099: #ifdef SCIF_DEBUG
                   1100:        if (scif_debug)
                   1101:                scifstatus(sc, "scif_stsoft");
                   1102: #endif
                   1103: #endif
                   1104: }
                   1105:
                   1106: void
                   1107: scifsoft(void *arg)
                   1108: {
                   1109:        struct scif_softc *sc = arg;
                   1110:        struct tty *tp;
                   1111:
                   1112:        tp = sc->sc_tty;
                   1113:
                   1114:        if (sc->sc_rx_ready) {
                   1115:                sc->sc_rx_ready = 0;
                   1116:                scif_rxsoft(sc, tp);
                   1117:        }
                   1118:
                   1119: #if 0
                   1120:        if (sc->sc_st_check) {
                   1121:                sc->sc_st_check = 0;
                   1122:                scif_stsoft(sc, tp);
                   1123:        }
                   1124: #endif
                   1125:
                   1126:        if (sc->sc_tx_done) {
                   1127:                sc->sc_tx_done = 0;
                   1128:                scif_txsoft(sc, tp);
                   1129:        }
                   1130: }
                   1131:
                   1132: int
                   1133: scifintr(void *arg)
                   1134: {
                   1135:        struct scif_softc *sc = arg;
                   1136:        u_char *put, *end;
                   1137:        u_int cc;
                   1138:        u_short ssr2;
                   1139:        int count;
                   1140:
                   1141:        end = sc->sc_ebuf;
                   1142:        put = sc->sc_rbput;
                   1143:        cc = sc->sc_rbavail;
                   1144:
                   1145:        do {
                   1146:                ssr2 = scif_ssr_read();
                   1147:                if (ISSET(ssr2, SCSSR2_BRK)) {
                   1148:                        scif_ssr_write(scif_ssr_read()
                   1149:                                & ~(SCSSR2_ER | SCSSR2_BRK | SCSSR2_DR));
                   1150: #ifdef DDB
                   1151:                        if (ISSET(sc->sc_hwflags, SCIF_HW_CONSOLE) &&
                   1152:                            db_console != 0) {
                   1153:                                Debugger();
                   1154:                        }
                   1155: #endif /* DDB */
                   1156:                }
                   1157:                count = scif_fdr_read() & SCFDR2_RECVCNT;
                   1158:                if (count != 0) {
                   1159:                        for (;;) {
                   1160:                                u_char c = scif_frdr_read();
                   1161:                                u_char err = (u_char)(scif_ssr_read() & 0x00ff);
                   1162:
                   1163:                                scif_ssr_write(scif_ssr_read()
                   1164:                                    & ~(SCSSR2_ER | SCSSR2_RDF | SCSSR2_DR));
                   1165: #ifdef SH4
                   1166:                                if (CPU_IS_SH4)
                   1167:                                        scif_lsr_write(scif_lsr_read()
                   1168:                                                       & ~SCLSR2_ORER);
                   1169: #endif
                   1170:                                if ((cc > 0) && (count > 0)) {
                   1171:                                        put[0] = c;
                   1172:                                        put[1] = err;
                   1173:                                        put += 2;
                   1174:                                        if (put >= end)
                   1175:                                                put = sc->sc_rbuf;
                   1176:                                        cc--;
                   1177:                                        count--;
                   1178:                                } else
                   1179:                                        break;
                   1180:                        }
                   1181:
                   1182:                        /*
                   1183:                         * Current string of incoming characters ended because
                   1184:                         * no more data was available or we ran out of space.
                   1185:                         * Schedule a receive event if any data was received.
                   1186:                         * If we're out of space, turn off receive interrupts.
                   1187:                         */
                   1188:                        sc->sc_rbput = put;
                   1189:                        sc->sc_rbavail = cc;
                   1190:                        if (!ISSET(sc->sc_rx_flags, RX_TTY_OVERFLOWED))
                   1191:                                sc->sc_rx_ready = 1;
                   1192:
                   1193:                        /*
                   1194:                         * See if we are in danger of overflowing a buffer. If
                   1195:                         * so, use hardware flow control to ease the pressure.
                   1196:                         */
                   1197:                        if (!ISSET(sc->sc_rx_flags, RX_IBUF_BLOCKED) &&
                   1198:                            cc < sc->sc_r_hiwat) {
                   1199:                                SET(sc->sc_rx_flags, RX_IBUF_BLOCKED);
                   1200: #if 0
                   1201:                                scif_hwiflow(sc);
                   1202: #endif
                   1203:                        }
                   1204:
                   1205:                        /*
                   1206:                         * If we're out of space, disable receive interrupts
                   1207:                         * until the queue has drained a bit.
                   1208:                         */
                   1209:                        if (!cc) {
                   1210:                                SET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED);
                   1211:                                scif_scr_write(scif_scr_read() & ~SCSCR2_RIE);
                   1212:                        }
                   1213:                } else {
                   1214:                        if (scif_ssr_read() & (SCSSR2_RDF | SCSSR2_DR)) {
                   1215:                                scif_scr_write(scif_scr_read()
                   1216:                                               & ~(SCSCR2_TIE | SCSCR2_RIE));
                   1217:                                delay(10);
                   1218:                                scif_scr_write(scif_scr_read()
                   1219:                                               | SCSCR2_TIE | SCSCR2_RIE);
                   1220:                                continue;
                   1221:                        }
                   1222:                }
                   1223:        } while (scif_ssr_read() & (SCSSR2_RDF | SCSSR2_DR));
                   1224:
                   1225: #if 0
                   1226:        msr = bus_space_read_1(iot, ioh, scif_msr);
                   1227:        delta = msr ^ sc->sc_msr;
                   1228:        sc->sc_msr = msr;
                   1229:        if (ISSET(delta, sc->sc_msr_mask)) {
                   1230:                SET(sc->sc_msr_delta, delta);
                   1231:
                   1232:                /*
                   1233:                 * Pulse-per-second clock signal on edge of DCD?
                   1234:                 */
                   1235:                if (ISSET(delta, sc->sc_ppsmask)) {
                   1236:                        struct timeval tv;
                   1237:                        if (ISSET(msr, sc->sc_ppsmask) ==
                   1238:                            sc->sc_ppsassert) {
                   1239:                                /* XXX nanotime() */
                   1240:                                microtime(&tv);
                   1241:                                TIMEVAL_TO_TIMESPEC(&tv,
                   1242:                                                    &sc->ppsinfo.assert_timestamp);
                   1243:                                if (sc->ppsparam.mode & PPS_OFFSETASSERT) {
                   1244:                                        timespecadd(&sc->ppsinfo.assert_timestamp,
                   1245:                                                    &sc->ppsparam.assert_offset,
                   1246:                                                    &sc->ppsinfo.assert_timestamp);
                   1247:                                        TIMESPEC_TO_TIMEVAL(&tv, &sc->ppsinfo.assert_timestamp);
                   1248:                                }
                   1249:
                   1250: #ifdef PPS_SYNC
                   1251:                                if (sc->ppsparam.mode & PPS_HARDPPSONASSERT)
                   1252:                                        hardpps(&tv, tv.tv_usec);
                   1253: #endif
                   1254:                                sc->ppsinfo.assert_sequence++;
                   1255:                                sc->ppsinfo.current_mode =
                   1256:                                        sc->ppsparam.mode;
                   1257:
                   1258:                        } else if (ISSET(msr, sc->sc_ppsmask) ==
                   1259:                                   sc->sc_ppsclear) {
                   1260:                                /* XXX nanotime() */
                   1261:                                microtime(&tv);
                   1262:                                TIMEVAL_TO_TIMESPEC(&tv,
                   1263:                                                    &sc->ppsinfo.clear_timestamp);
                   1264:                                if (sc->ppsparam.mode & PPS_OFFSETCLEAR) {
                   1265:                                        timespecadd(&sc->ppsinfo.clear_timestamp,
                   1266:                                                    &sc->ppsparam.clear_offset,
                   1267:                                                    &sc->ppsinfo.clear_timestamp);
                   1268:                                        TIMESPEC_TO_TIMEVAL(&tv, &sc->ppsinfo.clear_timestamp);
                   1269:                                }
                   1270:
                   1271: #ifdef PPS_SYNC
                   1272:                                if (sc->ppsparam.mode & PPS_HARDPPSONCLEAR)
                   1273:                                        hardpps(&tv, tv.tv_usec);
                   1274: #endif
                   1275:                                sc->ppsinfo.clear_sequence++;
                   1276:                                sc->ppsinfo.current_mode =
                   1277:                                        sc->ppsparam.mode;
                   1278:                        }
                   1279:                }
                   1280:
                   1281:                /*
                   1282:                 * Stop output immediately if we lose the output
                   1283:                 * flow control signal or carrier detect.
                   1284:                 */
                   1285:                if (ISSET(~msr, sc->sc_msr_mask)) {
                   1286:                        sc->sc_tbc = 0;
                   1287:                        sc->sc_heldtbc = 0;
                   1288: #ifdef SCIF_DEBUG
                   1289:                        if (scif_debug)
                   1290:                                scifstatus(sc, "scifintr  ");
                   1291: #endif
                   1292:                }
                   1293:
                   1294:                sc->sc_st_check = 1;
                   1295:        }
                   1296: #endif
                   1297:
                   1298:        /*
                   1299:         * Done handling any receive interrupts. See if data can be
                   1300:         * transmitted as well. Schedule tx done event if no data left
                   1301:         * and tty was marked busy.
                   1302:         */
                   1303:        if (((scif_fdr_read() & SCFDR2_TXCNT) >> 8) != 16) { /* XXX (msaitoh) */
                   1304:                /*
                   1305:                 * If we've delayed a parameter change, do it now, and restart
                   1306:                 * output.
                   1307:                 */
                   1308:                if (sc->sc_heldchange) {
                   1309:                        sc->sc_heldchange = 0;
                   1310:                        sc->sc_tbc = sc->sc_heldtbc;
                   1311:                        sc->sc_heldtbc = 0;
                   1312:                }
                   1313:
                   1314:                /* Output the next chunk of the contiguous buffer, if any. */
                   1315:                if (sc->sc_tbc > 0) {
                   1316:                        int n;
                   1317:                        int maxchars;
                   1318:                        int i;
                   1319:
                   1320:                        n = sc->sc_tbc;
                   1321:                        maxchars = sc->sc_fifolen -
                   1322:                                ((scif_fdr_read() & SCFDR2_TXCNT) >> 8);
                   1323:                        if (n > maxchars)
                   1324:                                n = maxchars;
                   1325:
                   1326:                        for (i = 0; i < n; i++) {
                   1327:                                scif_putc(*(sc->sc_tba));
                   1328:                                sc->sc_tba++;
                   1329:                        }
                   1330:                        sc->sc_tbc -= n;
                   1331:                } else {
                   1332:                        /* Disable transmit completion interrupts if necessary. */
                   1333: #if 0
                   1334:                        if (ISSET(sc->sc_ier, IER_ETXRDY))
                   1335: #endif
                   1336:                                scif_scr_write(scif_scr_read() & ~SCSCR2_TIE);
                   1337:
                   1338:                        if (sc->sc_tx_busy) {
                   1339:                                sc->sc_tx_busy = 0;
                   1340:                                sc->sc_tx_done = 1;
                   1341:                        }
                   1342:                }
                   1343:        }
                   1344:
                   1345:        /* Wake up the poller. */
                   1346:        softintr_schedule(sc->sc_si);
                   1347:
                   1348:        return (1);
                   1349: }
                   1350:
                   1351: void
                   1352: scifcnprobe(struct consdev *cp)
                   1353: {
                   1354:        int maj;
                   1355:
                   1356:        /* locate the major number */
                   1357:        for (maj = 0; maj < nchrdev; maj++)
                   1358:                if (cdevsw[maj].d_open == scifopen)
                   1359:                        break;
                   1360:
                   1361:        cp->cn_dev = makedev(maj, 0);
                   1362: #ifdef SCIFCONSOLE
                   1363:        cp->cn_pri = CN_REMOTE;
                   1364: #else
                   1365:        cp->cn_pri = CN_NORMAL;
                   1366: #endif
                   1367: }
                   1368:
                   1369: void
                   1370: scifcninit(struct consdev *cp)
                   1371: {
                   1372:        InitializeScif(scifcn_speed);
                   1373:        scifisconsole = 1;
                   1374: }
                   1375:
                   1376: int
                   1377: scifcngetc(dev_t dev)
                   1378: {
                   1379:        int c;
                   1380:        int s;
                   1381:
                   1382:        s = spltty();
                   1383:        c = scif_getc();
                   1384:        splx(s);
                   1385:
                   1386:        return (c);
                   1387: }
                   1388:
                   1389: void
                   1390: scifcnputc(dev_t dev, int c)
                   1391: {
                   1392:        int s;
                   1393:
                   1394:        s = spltty();
                   1395:        scif_putc((u_char)c);
                   1396:        splx(s);
                   1397: }

CVSweb