[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     ! 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