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

Annotation of sys/arch/sparc/dev/spif.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: spif.c,v 1.20 2006/06/02 20:00:54 miod Exp $  */
                      2:
                      3: /*
                      4:  * Copyright (c) 1999 Jason L. Wright (jason@thought.net)
                      5:  * 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:  *
                     16:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     17:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
                     18:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
                     19:  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
                     20:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
                     21:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                     22:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     23:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
                     24:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
                     25:  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     26:  * POSSIBILITY OF SUCH DAMAGE.
                     27:  */
                     28:
                     29: /*
                     30:  * Driver for the SUNW,spif: 8 serial, 1 parallel sbus board
                     31:  * based heavily on Iain Hibbert's driver for the MAGMA cards
                     32:  */
                     33:
                     34: #include <sys/param.h>
                     35: #include <sys/systm.h>
                     36: #include <sys/proc.h>
                     37: #include <sys/device.h>
                     38: #include <sys/kernel.h>
                     39: #include <sys/file.h>
                     40: #include <sys/errno.h>
                     41: #include <sys/ioctl.h>
                     42: #include <sys/mbuf.h>
                     43: #include <sys/socket.h>
                     44: #include <sys/syslog.h>
                     45: #include <sys/malloc.h>
                     46: #include <sys/tty.h>
                     47: #include <sys/conf.h>
                     48:
                     49: #include <machine/autoconf.h>
                     50: #include <sparc/cpu.h>
                     51: #include <sparc/sparc/cpuvar.h>
                     52: #include <sparc/dev/sbusvar.h>
                     53: #include <sparc/dev/spifreg.h>
                     54: #include <sparc/dev/spifvar.h>
                     55:
                     56: #if IPL_TTY == 1
                     57: # define IE_MSOFT IE_L1
                     58: #elif IPL_TTY == 4
                     59: # define IE_MSOFT IE_L4
                     60: #elif IPL_TTY == 6
                     61: # define IE_MSOFT IE_L6
                     62: #else
                     63: # error "no suitable software interrupt bit"
                     64: #endif
                     65:
                     66: int    spifmatch(struct device *, void *, void *);
                     67: void   spifattach(struct device *, struct device *, void *);
                     68:
                     69: int    sttymatch(struct device *, void *, void *);
                     70: void   sttyattach(struct device *, struct device *, void *);
                     71: int    sttyopen(dev_t, int, int, struct proc *);
                     72: int    sttyclose(dev_t, int, int, struct proc *);
                     73: int    sttyread(dev_t, struct uio *, int);
                     74: int    sttywrite(dev_t, struct uio *, int);
                     75: int    sttyioctl(dev_t, u_long, caddr_t, int, struct proc *);
                     76: int    sttystop(struct tty *, int);
                     77:
                     78: int    spifstcintr(void *);
                     79: int    spifstcintr_mx(struct spif_softc *, int *);
                     80: int    spifstcintr_tx(struct spif_softc *, int *);
                     81: int    spifstcintr_rx(struct spif_softc *, int *);
                     82: int    spifstcintr_rxexception(struct spif_softc *, int *);
                     83: int    spifsoftintr(void *);
                     84:
                     85: int    stty_param(struct tty *, struct termios *);
                     86: struct tty *sttytty(dev_t);
                     87: int    stty_modem_control(struct stty_port *, int, int);
                     88: static __inline        void    stty_write_ccr(struct stcregs *, u_int8_t);
                     89: int    stty_compute_baud(speed_t, int, u_int8_t *, u_int8_t *);
                     90: void   stty_start(struct tty *);
                     91:
                     92: int    sbppmatch(struct device *, void *, void *);
                     93: void   sbppattach(struct device *, struct device *, void *);
                     94: int    sbppopen(dev_t, int, int, struct proc *);
                     95: int    sbppclose(dev_t, int, int, struct proc *);
                     96: int    sbppread(dev_t, struct uio *, int);
                     97: int    sbppwrite(dev_t, struct uio *, int);
                     98: int    sbpp_rw(dev_t, struct uio *);
                     99: int    spifppcintr(void *);
                    100: int    sbpppoll(dev_t, int, struct proc *);
                    101: int    sbppioctl(dev_t, u_long, caddr_t, int, struct proc *);
                    102:
                    103: struct cfattach spif_ca = {
                    104:        sizeof (struct spif_softc), spifmatch, spifattach
                    105: };
                    106:
                    107: struct cfdriver spif_cd = {
                    108:        NULL, "spif", DV_DULL
                    109: };
                    110:
                    111: struct cfattach stty_ca = {
                    112:        sizeof(struct stty_softc), sttymatch, sttyattach
                    113: };
                    114:
                    115: struct cfdriver stty_cd = {
                    116:        NULL, "stty", DV_TTY
                    117: };
                    118:
                    119: struct cfattach sbpp_ca = {
                    120:        sizeof(struct sbpp_softc), sbppmatch, sbppattach
                    121: };
                    122:
                    123: struct cfdriver sbpp_cd = {
                    124:        NULL, "sbpp", DV_DULL
                    125: };
                    126:
                    127: int
                    128: spifmatch(parent, vcf, aux)
                    129:        struct device *parent;
                    130:        void *vcf, *aux;
                    131: {
                    132:        struct cfdata *cf = vcf;
                    133:        struct confargs *ca = aux;
                    134:        register struct romaux *ra = &ca->ca_ra;
                    135:
                    136:        if (strcmp(cf->cf_driver->cd_name, ra->ra_name) &&
                    137:            strcmp("SUNW,spif", ra->ra_name))
                    138:                return (0);
                    139:        return (1);
                    140: }
                    141:
                    142: void
                    143: spifattach(parent, self, aux)
                    144:        struct device *parent, *self;
                    145:        void *aux;
                    146: {
                    147:        struct spif_softc *sc = (struct spif_softc *)self;
                    148:        struct confargs *ca = aux;
                    149:        int stcpri, ppcpri;
                    150:
                    151:        if (ca->ca_ra.ra_nintr != 2) {
                    152:                printf(": expected 2 interrupts, got %d\n",
                    153:                    ca->ca_ra.ra_nintr);
                    154:                return;
                    155:        }
                    156:        stcpri = ca->ca_ra.ra_intr[SERIAL_INTR].int_pri;
                    157:        ppcpri = ca->ca_ra.ra_intr[PARALLEL_INTR].int_pri;
                    158:
                    159:        if (ca->ca_ra.ra_nreg != 1) {
                    160:                printf(": expected %d registers, got %d\n",
                    161:                    1, ca->ca_ra.ra_nreg);
                    162:                return;
                    163:        }
                    164:        sc->sc_regs = mapiodev(ca->ca_ra.ra_reg, 0, ca->ca_ra.ra_len);
                    165:
                    166:        sc->sc_node = ca->ca_ra.ra_node;
                    167:
                    168:        sc->sc_rev = getpropint(sc->sc_node, "revlev", 0);
                    169:
                    170:        sc->sc_osc = getpropint(sc->sc_node, "verosc", 0);
                    171:        switch (sc->sc_osc) {
                    172:        case SPIF_OSC10:
                    173:                sc->sc_osc = 10000000;
                    174:                break;
                    175:        case SPIF_OSC9:
                    176:        default:
                    177:                sc->sc_osc = 9830400;
                    178:                break;
                    179:        }
                    180:
                    181:        sc->sc_nser = 8;
                    182:        sc->sc_npar = 1;
                    183:
                    184:        sc->sc_rev2 = sc->sc_regs->stc.gfrcr;
                    185:        sc->sc_regs->stc.gsvr = 0;
                    186:
                    187:        stty_write_ccr(&sc->sc_regs->stc,
                    188:            CD180_CCR_CMD_RESET | CD180_CCR_RESETALL);
                    189:        while (sc->sc_regs->stc.gsvr != 0xff);
                    190:        while (sc->sc_regs->stc.gfrcr != sc->sc_rev2);
                    191:
                    192:        sc->sc_regs->stc.pprh = CD180_PPRH;
                    193:        sc->sc_regs->stc.pprl = CD180_PPRL;
                    194:        sc->sc_regs->stc.msmr = SPIF_MSMR;
                    195:        sc->sc_regs->stc.tsmr = SPIF_TSMR;
                    196:        sc->sc_regs->stc.rsmr = SPIF_RSMR;
                    197:        sc->sc_regs->stc.gsvr = 0;
                    198:        sc->sc_regs->stc.gscr1 = 0;
                    199:        sc->sc_regs->stc.gscr2 = 0;
                    200:        sc->sc_regs->stc.gscr3 = 0;
                    201:        printf(": rev %x chiprev %x osc %sMHz stcpri %d ppcpri %d softpri %d\n",
                    202:            sc->sc_rev, sc->sc_rev2, clockfreq(sc->sc_osc),
                    203:            stcpri, ppcpri, IPL_TTY);
                    204:
                    205:        (void)config_found(self, sttymatch, NULL);
                    206:        (void)config_found(self, sbppmatch, NULL);
                    207:
                    208:        sc->sc_ppcih.ih_fun = spifppcintr;
                    209:        sc->sc_ppcih.ih_arg = sc;
                    210:        intr_establish(ppcpri, &sc->sc_ppcih, -1, self->dv_xname);
                    211:
                    212:        sc->sc_stcih.ih_fun = spifstcintr;
                    213:        sc->sc_stcih.ih_arg = sc;
                    214:        intr_establish(stcpri, &sc->sc_stcih, -1, self->dv_xname);
                    215:
                    216:        sc->sc_softih.ih_fun = spifsoftintr;
                    217:        sc->sc_softih.ih_arg = sc;
                    218:        intr_establish(IPL_TTY, &sc->sc_softih, IPL_TTY, self->dv_xname);
                    219: }
                    220:
                    221: int
                    222: sttymatch(parent, vcf, aux)
                    223:        struct device *parent;
                    224:        void *vcf, *aux;
                    225: {
                    226:        struct spif_softc *sc = (struct spif_softc *)parent;
                    227:
                    228:        return (aux == sttymatch && sc->sc_ttys == NULL);
                    229: }
                    230:
                    231: void
                    232: sttyattach(parent, dev, aux)
                    233:        struct device *parent, *dev;
                    234:        void *aux;
                    235: {
                    236:        struct spif_softc *sc = (struct spif_softc *)parent;
                    237:        struct stty_softc *ssc = (struct stty_softc *)dev;
                    238:        int port;
                    239:
                    240:        sc->sc_ttys = ssc;
                    241:
                    242:        for (port = 0; port < sc->sc_nser; port++) {
                    243:                struct stty_port *sp = &ssc->sc_port[port];
                    244:                struct tty *tp;
                    245:
                    246:                sp->sp_dtr = 0;
                    247:                sc->sc_regs->dtrlatch[port] = 1;
                    248:
                    249:                tp = ttymalloc();
                    250:
                    251:                tp->t_oproc = stty_start;
                    252:                tp->t_param = stty_param;
                    253:
                    254:                sp->sp_tty = tp;
                    255:                sp->sp_sc = sc;
                    256:                sp->sp_channel = port;
                    257:
                    258:                sp->sp_rbuf = malloc(STTY_RBUF_SIZE, M_DEVBUF, M_NOWAIT);
                    259:                if(sp->sp_rbuf == NULL)
                    260:                        break;
                    261:
                    262:                sp->sp_rend = sp->sp_rbuf + STTY_RBUF_SIZE;
                    263:        }
                    264:
                    265:        ssc->sc_nports = port;
                    266:
                    267:        printf(": %d tty%s\n", port, port == 1 ? "" : "s");
                    268: }
                    269:
                    270: int
                    271: sttyopen(dev, flags, mode, p)
                    272:        dev_t dev;
                    273:        int flags;
                    274:        int mode;
                    275:        struct proc *p;
                    276: {
                    277:        struct spif_softc *csc;
                    278:        struct stty_softc *sc;
                    279:        struct stty_port *sp;
                    280:        struct tty *tp;
                    281:        int card = SPIF_CARD(dev);
                    282:        int port = SPIF_PORT(dev);
                    283:        int s;
                    284:
                    285:        if (card >= stty_cd.cd_ndevs || card >= spif_cd.cd_ndevs)
                    286:                return (ENXIO);
                    287:
                    288:        sc = stty_cd.cd_devs[card];
                    289:        csc = spif_cd.cd_devs[card];
                    290:        if (sc == NULL)
                    291:                return (ENXIO);
                    292:
                    293:        if (port >= sc->sc_nports)
                    294:                return (ENXIO);
                    295:
                    296:        sp = &sc->sc_port[port];
                    297:        tp = sp->sp_tty;
                    298:        tp->t_dev = dev;
                    299:
                    300:        if (!ISSET(tp->t_state, TS_ISOPEN)) {
                    301:                SET(tp->t_state, TS_WOPEN);
                    302:
                    303:                ttychars(tp);
                    304:                tp->t_iflag = TTYDEF_IFLAG;
                    305:                tp->t_oflag = TTYDEF_OFLAG;
                    306:                tp->t_cflag = TTYDEF_CFLAG;
                    307:                if (ISSET(sp->sp_openflags, TIOCFLAG_CLOCAL))
                    308:                        SET(tp->t_cflag, CLOCAL);
                    309:                if (ISSET(sp->sp_openflags, TIOCFLAG_CRTSCTS))
                    310:                        SET(tp->t_cflag, CRTSCTS);
                    311:                if (ISSET(sp->sp_openflags, TIOCFLAG_MDMBUF))
                    312:                        SET(tp->t_cflag, MDMBUF);
                    313:                tp->t_lflag = TTYDEF_LFLAG;
                    314:                tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
                    315:
                    316:                sp->sp_rput = sp->sp_rget = sp->sp_rbuf;
                    317:
                    318:                s = spltty();
                    319:
                    320:                csc->sc_regs->stc.car = sp->sp_channel;
                    321:                stty_write_ccr(&csc->sc_regs->stc,
                    322:                    CD180_CCR_CMD_RESET | CD180_CCR_RESETCHAN);
                    323:                csc->sc_regs->stc.car = sp->sp_channel;
                    324:
                    325:                stty_param(tp, &tp->t_termios);
                    326:
                    327:                ttsetwater(tp);
                    328:
                    329:                csc->sc_regs->stc.srer = CD180_SRER_CD | CD180_SRER_RXD;
                    330:
                    331:                if (ISSET(sp->sp_openflags, TIOCFLAG_SOFTCAR) || sp->sp_carrier)
                    332:                        SET(tp->t_state, TS_CARR_ON);
                    333:                else
                    334:                        CLR(tp->t_state, TS_CARR_ON);
                    335:        }
                    336:        else if (ISSET(tp->t_state, TS_XCLUDE) && p->p_ucred->cr_uid != 0) {
                    337:                return (EBUSY);
                    338:        } else {
                    339:                s = spltty();
                    340:        }
                    341:
                    342:        if (!ISSET(flags, O_NONBLOCK)) {
                    343:                while (!ISSET(tp->t_cflag, CLOCAL) &&
                    344:                    !ISSET(tp->t_state, TS_CARR_ON)) {
                    345:                        int error;
                    346:
                    347:                        SET(tp->t_state, TS_WOPEN);
                    348:                        error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH,
                    349:                            "sttycd", 0);
                    350:                        if (error != 0) {
                    351:                                splx(s);
                    352:                                CLR(tp->t_state, TS_WOPEN);
                    353:                                return (error);
                    354:                        }
                    355:                }
                    356:        }
                    357:
                    358:        splx(s);
                    359:
                    360:        return ((*linesw[tp->t_line].l_open)(dev, tp));
                    361: }
                    362:
                    363: int
                    364: sttyclose(dev, flags, mode, p)
                    365:        dev_t dev;
                    366:        int flags;
                    367:        int mode;
                    368:        struct proc *p;
                    369: {
                    370:        struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(dev)];
                    371:        struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)];
                    372:        struct spif_softc *csc = sp->sp_sc;
                    373:        struct tty *tp = sp->sp_tty;
                    374:        int port = SPIF_PORT(dev);
                    375:        int s;
                    376:
                    377:        (*linesw[tp->t_line].l_close)(tp, flags);
                    378:        s = spltty();
                    379:
                    380:        if (ISSET(tp->t_cflag, HUPCL) || !ISSET(tp->t_state, TS_ISOPEN)) {
                    381:                stty_modem_control(sp, 0, DMSET);
                    382:                csc->sc_regs->stc.car = port;
                    383:                csc->sc_regs->stc.ccr =
                    384:                    CD180_CCR_CMD_RESET | CD180_CCR_RESETCHAN;
                    385:        }
                    386:
                    387:        splx(s);
                    388:        ttyclose(tp);
                    389:        return (0);
                    390: }
                    391:
                    392: int
                    393: sttyioctl(dev, cmd, data, flags, p)
                    394:        dev_t dev;
                    395:        u_long cmd;
                    396:        caddr_t data;
                    397:        int flags;
                    398:        struct proc *p;
                    399: {
                    400:        struct stty_softc *stc = stty_cd.cd_devs[SPIF_CARD(dev)];
                    401:        struct stty_port *sp = &stc->sc_port[SPIF_PORT(dev)];
                    402:        struct spif_softc *sc = sp->sp_sc;
                    403:        struct tty *tp = sp->sp_tty;
                    404:        int error;
                    405:
                    406:        error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flags, p);
                    407:        if (error >= 0)
                    408:                return (error);
                    409:
                    410:        error = ttioctl(tp, cmd, data, flags, p);
                    411:        if (error >= 0)
                    412:                return (error);
                    413:
                    414:        error = 0;
                    415:
                    416:        switch (cmd) {
                    417:        case TIOCSBRK:
                    418:                SET(sp->sp_flags, STTYF_SET_BREAK);
                    419:                sc->sc_regs->stc.car = sp->sp_channel;
                    420:                sc->sc_regs->stc.srer |= CD180_SRER_TXD;
                    421:                break;
                    422:        case TIOCCBRK:
                    423:                SET(sp->sp_flags, STTYF_CLR_BREAK);
                    424:                sc->sc_regs->stc.car = sp->sp_channel;
                    425:                sc->sc_regs->stc.srer |= CD180_SRER_TXD;
                    426:                break;
                    427:        case TIOCSDTR:
                    428:                stty_modem_control(sp, TIOCM_DTR, DMBIS);
                    429:                break;
                    430:        case TIOCCDTR:
                    431:                stty_modem_control(sp, TIOCM_DTR, DMBIC);
                    432:                break;
                    433:        case TIOCMBIS:
                    434:                stty_modem_control(sp, *((int *)data), DMBIS);
                    435:                break;
                    436:        case TIOCMBIC:
                    437:                stty_modem_control(sp, *((int *)data), DMBIC);
                    438:                break;
                    439:        case TIOCMGET:
                    440:                *((int *)data) = stty_modem_control(sp, 0, DMGET);
                    441:                break;
                    442:        case TIOCMSET:
                    443:                stty_modem_control(sp, *((int *)data), DMSET);
                    444:                break;
                    445:        case TIOCGFLAGS:
                    446:                *((int *)data) = sp->sp_openflags;
                    447:                break;
                    448:        case TIOCSFLAGS:
                    449:                if (suser(p, 0))
                    450:                        error = EPERM;
                    451:                else
                    452:                        sp->sp_openflags = *((int *)data) &
                    453:                            (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL |
                    454:                             TIOCFLAG_CRTSCTS | TIOCFLAG_MDMBUF);
                    455:                break;
                    456:        default:
                    457:                error = ENOTTY;
                    458:        }
                    459:
                    460:        return (error);
                    461: }
                    462:
                    463: int
                    464: stty_modem_control(sp, bits, how)
                    465:        struct stty_port *sp;
                    466:        int bits, how;
                    467: {
                    468:        struct spif_softc *csc = sp->sp_sc;
                    469:        struct tty *tp = sp->sp_tty;
                    470:        int s, msvr;
                    471:
                    472:        s = spltty();
                    473:        csc->sc_regs->stc.car = sp->sp_channel;
                    474:
                    475:        switch (how) {
                    476:        case DMGET:
                    477:                bits = TIOCM_LE;
                    478:                if (sp->sp_dtr)
                    479:                        bits |= TIOCM_DTR;
                    480:                msvr = csc->sc_regs->stc.msvr;
                    481:                if (ISSET(msvr, CD180_MSVR_DSR))
                    482:                        bits |= TIOCM_DSR;
                    483:                if (ISSET(msvr, CD180_MSVR_CD))
                    484:                        bits |= TIOCM_CD;
                    485:                if (ISSET(msvr, CD180_MSVR_CTS))
                    486:                        bits |= TIOCM_CTS;
                    487:                if (ISSET(msvr, CD180_MSVR_RTS))
                    488:                        bits |= TIOCM_RTS;
                    489:                break;
                    490:        case DMSET:
                    491:                if (ISSET(bits, TIOCM_DTR)) {
                    492:                        sp->sp_dtr = 1;
                    493:                        csc->sc_regs->dtrlatch[sp->sp_channel] = 0;
                    494:                }
                    495:                else {
                    496:                        sp->sp_dtr = 0;
                    497:                        csc->sc_regs->dtrlatch[sp->sp_channel] = 1;
                    498:                }
                    499:                if (ISSET(bits, TIOCM_RTS))
                    500:                        csc->sc_regs->stc.msvr &= ~CD180_MSVR_RTS;
                    501:                else
                    502:                        csc->sc_regs->stc.msvr |= CD180_MSVR_RTS;
                    503:                break;
                    504:        case DMBIS:
                    505:                if (ISSET(bits, TIOCM_DTR)) {
                    506:                        sp->sp_dtr = 1;
                    507:                        csc->sc_regs->dtrlatch[sp->sp_channel] = 0;
                    508:                }
                    509:                if (ISSET(bits, TIOCM_RTS) && !ISSET(tp->t_cflag, CRTSCTS))
                    510:                        csc->sc_regs->stc.msvr &= ~CD180_MSVR_RTS;
                    511:                break;
                    512:        case DMBIC:
                    513:                if (ISSET(bits, TIOCM_DTR)) {
                    514:                        sp->sp_dtr = 0;
                    515:                        csc->sc_regs->dtrlatch[sp->sp_channel] = 1;
                    516:                }
                    517:                if (ISSET(bits, TIOCM_RTS))
                    518:                        csc->sc_regs->stc.msvr |= CD180_MSVR_RTS;
                    519:                break;
                    520:        }
                    521:
                    522:        splx(s);
                    523:        return (bits);
                    524: }
                    525:
                    526: int
                    527: stty_param(tp, t)
                    528:        struct tty *tp;
                    529:        struct termios *t;
                    530: {
                    531:        struct stty_softc *st = stty_cd.cd_devs[SPIF_CARD(tp->t_dev)];
                    532:        struct stty_port *sp = &st->sc_port[SPIF_PORT(tp->t_dev)];
                    533:        struct spif_softc *sc = sp->sp_sc;
                    534:        u_int8_t rbprl, rbprh, tbprl, tbprh;
                    535:        int s, opt;
                    536:
                    537:        if (t->c_ospeed &&
                    538:            stty_compute_baud(t->c_ospeed, sc->sc_osc, &tbprl, &tbprh))
                    539:                return (EINVAL);
                    540:
                    541:        if (t->c_ispeed &&
                    542:            stty_compute_baud(t->c_ispeed, sc->sc_osc, &rbprl, &rbprh))
                    543:                return (EINVAL);
                    544:
                    545:        s = spltty();
                    546:
                    547:        /* hang up line if ospeed is zero, otherwise raise DTR */
                    548:        stty_modem_control(sp, TIOCM_DTR,
                    549:            (t->c_ospeed == 0 ? DMBIC : DMBIS));
                    550:
                    551:        sc->sc_regs->stc.car = sp->sp_channel;
                    552:
                    553:        opt = 0;
                    554:        if (ISSET(t->c_cflag, PARENB)) {
                    555:                opt |= CD180_COR1_PARMODE_NORMAL;
                    556:                opt |= (ISSET(t->c_cflag, PARODD) ?
                    557:                                CD180_COR1_ODDPAR :
                    558:                                CD180_COR1_EVENPAR);
                    559:        }
                    560:        else
                    561:                opt |= CD180_COR1_PARMODE_NO;
                    562:
                    563:        if (!ISSET(t->c_iflag, INPCK))
                    564:                opt |= CD180_COR1_IGNPAR;
                    565:
                    566:        if (ISSET(t->c_cflag, CSTOPB))
                    567:                opt |= CD180_COR1_STOP2;
                    568:
                    569:        switch (t->c_cflag & CSIZE) {
                    570:        case CS5:
                    571:                opt |= CD180_COR1_CS5;
                    572:                break;
                    573:        case CS6:
                    574:                opt |= CD180_COR1_CS6;
                    575:                break;
                    576:        case CS7:
                    577:                opt |= CD180_COR1_CS7;
                    578:                break;
                    579:        default:
                    580:                opt |= CD180_COR1_CS8;
                    581:                break;
                    582:        }
                    583:        sc->sc_regs->stc.cor1 = opt;
                    584:        stty_write_ccr(&sc->sc_regs->stc, CD180_CCR_CMD_COR|CD180_CCR_CORCHG1);
                    585:
                    586:        opt = CD180_COR2_ETC;
                    587:        if (ISSET(t->c_cflag, CRTSCTS))
                    588:                opt |= CD180_COR2_CTSAE;
                    589:        sc->sc_regs->stc.cor2 = opt;
                    590:        stty_write_ccr(&sc->sc_regs->stc, CD180_CCR_CMD_COR|CD180_CCR_CORCHG2);
                    591:
                    592:        sc->sc_regs->stc.cor3 = STTY_RX_FIFO_THRESHOLD;
                    593:        stty_write_ccr(&sc->sc_regs->stc, CD180_CCR_CMD_COR|CD180_CCR_CORCHG3);
                    594:
                    595:        sc->sc_regs->stc.schr1 = 0x11;
                    596:        sc->sc_regs->stc.schr2 = 0x13;
                    597:        sc->sc_regs->stc.schr3 = 0x11;
                    598:        sc->sc_regs->stc.schr4 = 0x13;
                    599:        sc->sc_regs->stc.rtpr = 0x12;
                    600:
                    601:        sc->sc_regs->stc.mcor1 = CD180_MCOR1_CDZD | STTY_RX_DTR_THRESHOLD;
                    602:        sc->sc_regs->stc.mcor2 = CD180_MCOR2_CDOD;
                    603:        sc->sc_regs->stc.mcr = 0;
                    604:
                    605:        if (t->c_ospeed) {
                    606:                sc->sc_regs->stc.tbprh = tbprh;
                    607:                sc->sc_regs->stc.tbprl = tbprl;
                    608:        }
                    609:
                    610:        if (t->c_ispeed) {
                    611:                sc->sc_regs->stc.rbprh = rbprh;
                    612:                sc->sc_regs->stc.rbprl = rbprl;
                    613:        }
                    614:
                    615:        stty_write_ccr(&sc->sc_regs->stc, CD180_CCR_CMD_CHAN |
                    616:            CD180_CCR_CHAN_TXEN | CD180_CCR_CHAN_RXEN);
                    617:
                    618:        sp->sp_carrier = sc->sc_regs->stc.msvr & CD180_MSVR_CD;
                    619:
                    620:        splx(s);
                    621:        return (0);
                    622: }
                    623:
                    624: int
                    625: sttyread(dev, uio, flags)
                    626:        dev_t dev;
                    627:        struct uio *uio;
                    628:        int flags;
                    629: {
                    630:        struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(dev)];
                    631:        struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)];
                    632:        struct tty *tp = sp->sp_tty;
                    633:
                    634:        return ((*linesw[tp->t_line].l_read)(tp, uio, flags));
                    635: }
                    636:
                    637: int
                    638: sttywrite(dev, uio, flags)
                    639:        dev_t dev;
                    640:        struct uio *uio;
                    641:        int flags;
                    642: {
                    643:        struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(dev)];
                    644:        struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)];
                    645:        struct tty *tp = sp->sp_tty;
                    646:
                    647:        return ((*linesw[tp->t_line].l_write)(tp, uio, flags));
                    648: }
                    649:
                    650: struct tty *
                    651: sttytty(dev)
                    652:        dev_t dev;
                    653: {
                    654:        struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(dev)];
                    655:        struct stty_port *sp = &sc->sc_port[SPIF_PORT(dev)];
                    656:
                    657:        return (sp->sp_tty);
                    658: }
                    659:
                    660: int
                    661: sttystop(tp, flags)
                    662:        struct tty *tp;
                    663:        int flags;
                    664: {
                    665:        struct stty_softc *sc = stty_cd.cd_devs[SPIF_CARD(tp->t_dev)];
                    666:        struct stty_port *sp = &sc->sc_port[SPIF_PORT(tp->t_dev)];
                    667:        int s;
                    668:
                    669:        s = spltty();
                    670:        if (ISSET(tp->t_state, TS_BUSY)) {
                    671:                if (!ISSET(tp->t_state, TS_TTSTOP))
                    672:                        SET(tp->t_state, TS_FLUSH);
                    673:                SET(sp->sp_flags, STTYF_STOP);
                    674:        }
                    675:        splx(s);
                    676:        return (0);
                    677: }
                    678:
                    679: void
                    680: stty_start(tp)
                    681:        struct tty *tp;
                    682: {
                    683:        struct stty_softc *stc = stty_cd.cd_devs[SPIF_CARD(tp->t_dev)];
                    684:        struct stty_port *sp = &stc->sc_port[SPIF_PORT(tp->t_dev)];
                    685:        struct spif_softc *sc = sp->sp_sc;
                    686:        int s;
                    687:
                    688:        s = spltty();
                    689:
                    690:        if (!ISSET(tp->t_state, TS_TTSTOP | TS_TIMEOUT | TS_BUSY)) {
                    691:                if (tp->t_outq.c_cc <= tp->t_lowat) {
                    692:                        if (ISSET(tp->t_state, TS_ASLEEP)) {
                    693:                                CLR(tp->t_state, TS_ASLEEP);
                    694:                                wakeup(&tp->t_outq);
                    695:                        }
                    696:                        selwakeup(&tp->t_wsel);
                    697:                }
                    698:                if (tp->t_outq.c_cc) {
                    699:                        sp->sp_txc = ndqb(&tp->t_outq, 0);
                    700:                        sp->sp_txp = tp->t_outq.c_cf;
                    701:                        SET(tp->t_state, TS_BUSY);
                    702:                        sc->sc_regs->stc.car = sp->sp_channel;
                    703:                        sc->sc_regs->stc.srer |= CD180_SRER_TXD;
                    704:                }
                    705:        }
                    706:
                    707:        splx(s);
                    708: }
                    709:
                    710: int
                    711: spifstcintr_rxexception(sc, needsoftp)
                    712:        struct spif_softc *sc;
                    713:        int *needsoftp;
                    714: {
                    715:        struct stty_port *sp;
                    716:        u_int8_t channel, *ptr;
                    717:
                    718:        channel = CD180_GSCR_CHANNEL(sc->sc_regs->stc.gscr1);
                    719:        sp = &sc->sc_ttys->sc_port[channel];
                    720:        ptr = sp->sp_rput;
                    721:        *ptr++ = sc->sc_regs->stc.rcsr;
                    722:        *ptr++ = sc->sc_regs->stc.rdr;
                    723:        if (ptr == sp->sp_rend)
                    724:                ptr = sp->sp_rbuf;
                    725:        if (ptr == sp->sp_rget) {
                    726:                if (ptr == sp->sp_rbuf)
                    727:                        ptr = sp->sp_rend;
                    728:                ptr -= 2;
                    729:                SET(sp->sp_flags, STTYF_RING_OVERFLOW);
                    730:        }
                    731:        sc->sc_regs->stc.eosrr = 0;
                    732:        *needsoftp = 1;
                    733:        sp->sp_rput = ptr;
                    734:        return (1);
                    735: }
                    736:
                    737: int
                    738: spifstcintr_rx(sc, needsoftp)
                    739:        struct spif_softc *sc;
                    740:        int *needsoftp;
                    741: {
                    742:        struct stty_port *sp;
                    743:        u_int8_t channel, *ptr, cnt, rcsr;
                    744:        int i;
                    745:
                    746:        channel = CD180_GSCR_CHANNEL(sc->sc_regs->stc.gscr1);
                    747:        sp = &sc->sc_ttys->sc_port[channel];
                    748:        ptr = sp->sp_rput;
                    749:        cnt = sc->sc_regs->stc.rdcr;
                    750:        for (i = 0; i < cnt; i++) {
                    751:                *ptr++ = 0;
                    752:                rcsr = sc->sc_regs->stc.rcsr;
                    753:                *ptr++ = sc->sc_regs->stc.rdr;
                    754:                if (ptr == sp->sp_rend)
                    755:                        ptr = sp->sp_rbuf;
                    756:                if (ptr == sp->sp_rget) {
                    757:                        if (ptr == sp->sp_rbuf)
                    758:                                ptr = sp->sp_rend;
                    759:                        ptr -= 2;
                    760:                        SET(sp->sp_flags, STTYF_RING_OVERFLOW);
                    761:                        break;
                    762:                }
                    763:        }
                    764:        sc->sc_regs->stc.eosrr = 0;
                    765:        if (cnt) {
                    766:                *needsoftp = 1;
                    767:                sp->sp_rput = ptr;
                    768:        }
                    769:        return (1);
                    770: }
                    771:
                    772: int
                    773: spifstcintr_tx(sc, needsoftp)
                    774:        struct spif_softc *sc;
                    775:        int *needsoftp;
                    776: {
                    777:        struct stty_port *sp;
                    778:        u_int8_t channel, ch;
                    779:        int cnt = 0;
                    780:
                    781:        channel = CD180_GSCR_CHANNEL(sc->sc_regs->stc.gscr1);
                    782:        sp = &sc->sc_ttys->sc_port[channel];
                    783:        if (!ISSET(sp->sp_flags, STTYF_STOP)) {
                    784:                if (ISSET(sp->sp_flags, STTYF_SET_BREAK)) {
                    785:                        sc->sc_regs->stc.tdr = 0;
                    786:                        sc->sc_regs->stc.tdr = 0x81;
                    787:                        CLR(sp->sp_flags, STTYF_SET_BREAK);
                    788:                        cnt += 2;
                    789:                }
                    790:                if (ISSET(sp->sp_flags, STTYF_CLR_BREAK)) {
                    791:                        sc->sc_regs->stc.tdr = 0;
                    792:                        sc->sc_regs->stc.tdr = 0x83;
                    793:                        CLR(sp->sp_flags, STTYF_CLR_BREAK);
                    794:                        cnt += 2;
                    795:                }
                    796:
                    797:                while (sp->sp_txc > 0 && cnt < (CD180_TX_FIFO_SIZE-1)) {
                    798:                        ch = *sp->sp_txp;
                    799:                        sp->sp_txc--;
                    800:                        sp->sp_txp++;
                    801:
                    802:                        if (ch == 0) {
                    803:                                sc->sc_regs->stc.tdr = ch;
                    804:                                cnt++;
                    805:                        }
                    806:                        sc->sc_regs->stc.tdr = ch;
                    807:                        cnt++;
                    808:                }
                    809:        }
                    810:
                    811:        if (sp->sp_txc == 0 ||
                    812:            ISSET(sp->sp_flags, STTYF_STOP)) {
                    813:                sc->sc_regs->stc.srer &= ~CD180_SRER_TXD;
                    814:                CLR(sp->sp_flags, STTYF_STOP);
                    815:                SET(sp->sp_flags, STTYF_DONE);
                    816:                *needsoftp = 1;
                    817:        }
                    818:
                    819:        sc->sc_regs->stc.eosrr = 0;
                    820:
                    821:        return (1);
                    822: }
                    823:
                    824: int
                    825: spifstcintr_mx(sc, needsoftp)
                    826:        struct spif_softc *sc;
                    827:        int *needsoftp;
                    828: {
                    829:        struct stty_port *sp;
                    830:        u_int8_t channel, mcr;
                    831:
                    832:        channel = CD180_GSCR_CHANNEL(sc->sc_regs->stc.gscr1);
                    833:        sp = &sc->sc_ttys->sc_port[channel];
                    834:        mcr = sc->sc_regs->stc.mcr;
                    835:        if (mcr & CD180_MCR_CD) {
                    836:                SET(sp->sp_flags, STTYF_CDCHG);
                    837:                *needsoftp = 1;
                    838:        }
                    839:        sc->sc_regs->stc.mcr = 0;
                    840:        sc->sc_regs->stc.eosrr = 0;
                    841:        return (1);
                    842: }
                    843:
                    844: int
                    845: spifstcintr(vsc)
                    846:        void *vsc;
                    847: {
                    848:        struct spif_softc *sc = (struct spif_softc *)vsc;
                    849:        int needsoft = 0, r = 0, i;
                    850:        u_int8_t ar;
                    851:
                    852:        for (i = 0; i < 8; i++) {
                    853:                ar = sc->sc_regs->istc.rrar & CD180_GSVR_IMASK;
                    854:                if (ar == CD180_GSVR_RXGOOD)
                    855:                        r |= spifstcintr_rx(sc, &needsoft);
                    856:                else if (ar == CD180_GSVR_RXEXCEPTION)
                    857:                        r |= spifstcintr_rxexception(sc, &needsoft);
                    858:        }
                    859:
                    860:        for (i = 0; i < 8; i++) {
                    861:                ar = sc->sc_regs->istc.trar & CD180_GSVR_IMASK;
                    862:                if (ar == CD180_GSVR_TXDATA)
                    863:                        r |= spifstcintr_tx(sc, &needsoft);
                    864:        }
                    865:
                    866:        for (i = 0; i < 8; i++) {
                    867:                ar = sc->sc_regs->istc.mrar & CD180_GSVR_IMASK;
                    868:                if (ar == CD180_GSVR_STATCHG)
                    869:                        r |= spifstcintr_mx(sc, &needsoft);
                    870:        }
                    871:
                    872:        if (needsoft) {
                    873: #if defined(SUN4M)
                    874:                if (CPU_ISSUN4M)
                    875:                        raise(0, IPL_TTY);
                    876:                else
                    877: #endif
                    878:                        ienab_bis(IE_MSOFT);
                    879:        }
                    880:        return (r);
                    881: }
                    882:
                    883: int
                    884: spifsoftintr(vsc)
                    885:        void *vsc;
                    886: {
                    887:        struct spif_softc *sc = (struct spif_softc *)vsc;
                    888:        struct stty_softc *stc = sc->sc_ttys;
                    889:        int r = 0, i, data, s, flags;
                    890:        u_int8_t stat, msvr;
                    891:        struct stty_port *sp;
                    892:        struct tty *tp;
                    893:
                    894:        if (stc != NULL) {
                    895:                for (i = 0; i < stc->sc_nports; i++) {
                    896:                        sp = &stc->sc_port[i];
                    897:                        tp = sp->sp_tty;
                    898:
                    899:                        if (!ISSET(tp->t_state, TS_ISOPEN))
                    900:                                continue;
                    901:
                    902:                        while (sp->sp_rget != sp->sp_rput) {
                    903:                                stat = sp->sp_rget[0];
                    904:                                data = sp->sp_rget[1];
                    905:                                sp->sp_rget += 2;
                    906:                                if (sp->sp_rget == sp->sp_rend)
                    907:                                        sp->sp_rget = sp->sp_rbuf;
                    908:
                    909:                                if (stat & (CD180_RCSR_BE | CD180_RCSR_FE))
                    910:                                        data |= TTY_FE;
                    911:
                    912:                                if (stat & CD180_RCSR_PE)
                    913:                                        data |= TTY_PE;
                    914:
                    915:                                (*linesw[tp->t_line].l_rint)(data, tp);
                    916:                                r = 1;
                    917:                        }
                    918:
                    919:                        s = splhigh();
                    920:                        flags = sp->sp_flags;
                    921:                        CLR(sp->sp_flags, STTYF_DONE | STTYF_CDCHG |
                    922:                            STTYF_RING_OVERFLOW);
                    923:                        splx(s);
                    924:
                    925:                        if (ISSET(flags, STTYF_CDCHG)) {
                    926:                                s = spltty();
                    927:                                sc->sc_regs->stc.car = i;
                    928:                                msvr = sc->sc_regs->stc.msvr;
                    929:                                splx(s);
                    930:
                    931:                                sp->sp_carrier = msvr & CD180_MSVR_CD;
                    932:                                (*linesw[tp->t_line].l_modem)(tp,
                    933:                                    sp->sp_carrier);
                    934:                                r = 1;
                    935:                        }
                    936:
                    937:                        if (ISSET(flags, STTYF_RING_OVERFLOW)) {
                    938:                                log(LOG_WARNING, "%s-%x: ring overflow\n",
                    939:                                        stc->sc_dev.dv_xname, i);
                    940:                                r = 1;
                    941:                        }
                    942:
                    943:                        if (ISSET(flags, STTYF_DONE)) {
                    944:                                ndflush(&tp->t_outq,
                    945:                                    sp->sp_txp - tp->t_outq.c_cf);
                    946:                                CLR(tp->t_state, TS_BUSY);
                    947:                                (*linesw[tp->t_line].l_start)(tp);
                    948:                                r = 1;
                    949:                        }
                    950:                }
                    951:        }
                    952:
                    953:        return (r);
                    954: }
                    955:
                    956: static __inline        void
                    957: stty_write_ccr(stc, val)
                    958:        struct stcregs *stc;
                    959:        u_int8_t val;
                    960: {
                    961:        int tries = 100000;
                    962:
                    963:        while (stc->ccr && tries--);
                    964:        if (tries == 0)
                    965:                printf("CCR: timeout\n");
                    966:        stc->ccr = val;
                    967: }
                    968:
                    969: int
                    970: stty_compute_baud(speed, clock, bprlp, bprhp)
                    971:        speed_t speed;
                    972:        int clock;
                    973:        u_int8_t *bprlp, *bprhp;
                    974: {
                    975:        u_int32_t rate;
                    976:
                    977:        rate = (2 * clock) / (16 * speed);
                    978:        if (rate & 1)
                    979:                rate = (rate >> 1) + 1;
                    980:        else
                    981:                rate = rate >> 1;
                    982:
                    983:        if (rate > 0xffff || rate == 0)
                    984:                return (1);
                    985:
                    986:        *bprlp = rate & 0xff;
                    987:        *bprhp = (rate >> 8) & 0xff;
                    988:        return (0);
                    989: }
                    990:
                    991: int
                    992: sbppmatch(parent, vcf, aux)
                    993:        struct device *parent;
                    994:        void *vcf, *aux;
                    995: {
                    996:        struct spif_softc *sc = (struct spif_softc *)parent;
                    997:
                    998:        return (aux == sbppmatch && sc->sc_bpps == NULL);
                    999: }
                   1000:
                   1001: void
                   1002: sbppattach(parent, dev, aux)
                   1003:        struct device *parent, *dev;
                   1004:        void *aux;
                   1005: {
                   1006:        struct spif_softc *sc = (struct spif_softc *)parent;
                   1007:        struct sbpp_softc *psc = (struct sbpp_softc *)dev;
                   1008:        int port;
                   1009:
                   1010:        sc->sc_bpps = psc;
                   1011:
                   1012:        for (port = 0; port < sc->sc_npar; port++) {
                   1013:        }
                   1014:
                   1015:        psc->sc_nports = port;
                   1016:        printf(": %d port%s\n", port, port == 1 ? "" : "s");
                   1017: }
                   1018:
                   1019: int
                   1020: sbppopen(dev, flags, mode, p)
                   1021:        dev_t dev;
                   1022:        int flags;
                   1023:        int mode;
                   1024:        struct proc *p;
                   1025: {
                   1026:        return (ENXIO);
                   1027: }
                   1028:
                   1029: int
                   1030: sbppclose(dev, flags, mode, p)
                   1031:        dev_t dev;
                   1032:        int flags;
                   1033:        int mode;
                   1034:        struct proc *p;
                   1035: {
                   1036:        return (ENXIO);
                   1037: }
                   1038:
                   1039: int
                   1040: spifppcintr(v)
                   1041:        void *v;
                   1042: {
                   1043:        return (0);
                   1044: }
                   1045:
                   1046: int
                   1047: sbppread(dev, uio, flags)
                   1048:        dev_t dev;
                   1049:        struct uio *uio;
                   1050:        int flags;
                   1051: {
                   1052:        return (sbpp_rw(dev, uio));
                   1053: }
                   1054:
                   1055: int
                   1056: sbppwrite(dev, uio, flags)
                   1057:        dev_t dev;
                   1058:        struct uio *uio;
                   1059:        int flags;
                   1060: {
                   1061:        return (sbpp_rw(dev, uio));
                   1062: }
                   1063:
                   1064: int
                   1065: sbpp_rw(dev, uio)
                   1066:        dev_t dev;
                   1067:        struct uio *uio;
                   1068: {
                   1069:        return (ENXIO);
                   1070: }
                   1071:
                   1072: int
                   1073: sbpppoll(dev, events, p)
                   1074:        dev_t dev;
                   1075:        int events;
                   1076:        struct proc *p;
                   1077: {
                   1078:        return (seltrue(dev, events, p));
                   1079: }
                   1080:
                   1081: int
                   1082: sbppioctl(dev, cmd, data, flags, p)
                   1083:        dev_t dev;
                   1084:        u_long cmd;
                   1085:        caddr_t data;
                   1086:        int flags;
                   1087:        struct proc *p;
                   1088: {
                   1089:        int error;
                   1090:
                   1091:        error = ENOTTY;
                   1092:
                   1093:        return (error);
                   1094: }

CVSweb