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

Annotation of sys/arch/mvme88k/dev/vx.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: vx.c,v 1.38 2006/07/28 21:46:02 miod Exp $ */
        !             2: /*
        !             3:  * Copyright (c) 1999 Steve Murphree, Jr.
        !             4:  * All rights reserved.
        !             5:  *
        !             6:  * Redistribution and use in source and binary forms, with or without
        !             7:  * modification, are permitted provided that the following conditions
        !             8:  * are met:
        !             9:  * 1. Redistributions of source code must retain the above copyright
        !            10:  *    notice, this list of conditions and the following disclaimer.
        !            11:  * 2. Redistributions in binary form must reproduce the above copyright
        !            12:  *    notice, this list of conditions and the following disclaimer in the
        !            13:  *    documentation and/or other materials provided with the distribution.
        !            14:  * 3. The name of the author may not be used to endorse or promote products
        !            15:  *    derived from this software without specific prior written permission.
        !            16:  *
        !            17:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            18:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            19:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            20:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
        !            21:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            22:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        !            23:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
        !            24:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            25:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
        !            26:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            27:  */
        !            28:
        !            29: /* This card lives in D16 space */
        !            30: #define        __BUS_SPACE_RESTRICT_D16__
        !            31:
        !            32: #include <sys/param.h>
        !            33: #include <sys/ioctl.h>
        !            34: #include <sys/proc.h>
        !            35: #include <sys/tty.h>
        !            36: #include <sys/uio.h>
        !            37: #include <sys/systm.h>
        !            38: #include <sys/time.h>
        !            39: #include <sys/device.h>
        !            40: #include <sys/syslog.h>
        !            41:
        !            42: #include <machine/autoconf.h>
        !            43: #include <machine/conf.h>
        !            44: #include <machine/cpu.h>
        !            45: #include <machine/psl.h>
        !            46:
        !            47: #include <dev/cons.h>
        !            48:
        !            49: #include <mvme88k/dev/vme.h>
        !            50: #include <mvme88k/dev/vxreg.h>
        !            51:
        !            52: #define splvx()        spltty()
        !            53:
        !            54: struct vx_info {
        !            55:        struct   tty *tty;
        !            56:        u_char   vx_swflags;
        !            57:        int      vx_linestatus;
        !            58:        int      open;
        !            59:        int      waiting;
        !            60:        u_char   vx_speed;
        !            61:        u_char   read_pending;
        !            62:        struct   wring  *wringp;
        !            63:        struct   rring  *rringp;
        !            64: };
        !            65:
        !            66: struct vxsoftc {
        !            67:        struct device     sc_dev;
        !            68:        struct vx_info  sc_info[NVXPORTS];
        !            69:        struct vxreg    *vx_reg;
        !            70:        vaddr_t         board_vaddr;
        !            71:        struct channel    *channel;
        !            72:        char              channel_number;
        !            73:        struct packet     sc_bppwait_pkt;
        !            74:        void              *sc_bppwait_pktp;
        !            75:        struct intrhand   sc_ih;
        !            76:        int               sc_vec;
        !            77:        struct envelope   *elist_head, *elist_tail;
        !            78:        struct packet     *plist_head, *plist_tail;
        !            79: };
        !            80:
        !            81: int  vxmatch(struct device *, void *, void *);
        !            82: void vxattach(struct device *, struct device *, void *);
        !            83:
        !            84: struct cfattach vx_ca = {
        !            85:        sizeof(struct vxsoftc), vxmatch, vxattach
        !            86: };
        !            87:
        !            88: struct cfdriver vx_cd = {
        !            89:        NULL, "vx", DV_TTY
        !            90: };
        !            91:
        !            92: int    bpp_send(struct vxsoftc *, void *, int);
        !            93: void   ccode(struct vxsoftc *, int, char);
        !            94: int    create_channels(struct vxsoftc *);
        !            95: void   create_free_queue(struct vxsoftc *);
        !            96: short  dtr_ctl(struct vxsoftc *, int, int);
        !            97: int    env_isvalid(struct envelope *);
        !            98: struct envelope *find_status_packet(struct vxsoftc *, struct packet *);
        !            99: short  flush_ctl(struct vxsoftc *, int, int);
        !           100: struct envelope *get_cmd_tail(struct vxsoftc *);
        !           101: void   *get_free_envelope(struct vxsoftc *);
        !           102: void   *get_free_packet(struct vxsoftc *);
        !           103: struct envelope *get_next_envelope(struct vxsoftc *, struct envelope *);
        !           104: struct packet *get_packet(struct vxsoftc *, struct envelope *);
        !           105: struct envelope *get_status_head(struct vxsoftc *);
        !           106: void   put_free_envelope(struct vxsoftc *, void *);
        !           107: void   put_free_packet(struct vxsoftc *, void *);
        !           108: void   read_chars(struct vxsoftc *, int);
        !           109: void   read_wakeup(struct vxsoftc *, int);
        !           110: short  rts_ctl(struct vxsoftc *, int, int);
        !           111: void   set_status_head(struct vxsoftc *, void *);
        !           112: void   vx_break(struct vxsoftc *, int);
        !           113: int    vx_ccparam(struct vxsoftc *, struct termios *, int);
        !           114: int    vx_event(struct vxsoftc *, struct packet *);
        !           115: void   vx_frame(struct vxsoftc *, int);
        !           116: int    vx_init(struct vxsoftc *);
        !           117: int    vx_intr(void *);
        !           118: int    vx_mctl(dev_t, int, int);
        !           119: void   vx_overflow(struct vxsoftc *, int, long *, u_char *);
        !           120: int    vx_param(struct tty *, struct termios *);
        !           121: int    vx_poll(struct vxsoftc *, struct packet *);
        !           122: void   vxputc(struct vxsoftc *, int, u_char);
        !           123: int    vx_sintr(struct vxsoftc *);
        !           124: void   vxstart(struct tty *tp);
        !           125: u_short        vxtspeed(int);
        !           126: void   vx_unblock(struct tty *);
        !           127:
        !           128: /* flags for bpp_send() */
        !           129: #define        NOWAIT 0
        !           130: #define        WAIT 1
        !           131:
        !           132: #define VX_UNIT(x) (minor(x) / NVXPORTS)
        !           133: #define VX_PORT(x) (minor(x) % NVXPORTS)
        !           134:
        !           135: /*
        !           136:  * Convert dual-ported physical addresse to host virtual address, and the
        !           137:  * opposite.
        !           138:  */
        !           139: #define        VIRTUAL(addr)   (((addr) & 0xffff) + sc->board_vaddr)
        !           140: #define        PHYSICAL(addr) \
        !           141:        (((addr - sc->board_vaddr) & 0xffff) | LOCAL_DPMEM_ADDRESS)
        !           142:
        !           143: #if 0
        !           144: #define  LO(x) (u_short)((unsigned long)x & 0x0000FFFF)
        !           145: #define  HI(x) (u_short)((unsigned long)x >> 16)
        !           146: #else
        !           147: #define        LO(x)   (u_short)(x)
        !           148: #define        HI(x)   (LOCAL_DPMEM_ADDRESS >> 16)
        !           149: #endif
        !           150:
        !           151: struct tty *
        !           152: vxtty(dev_t dev)
        !           153: {
        !           154:        int unit, port;
        !           155:        struct vxsoftc *sc;
        !           156:
        !           157:        unit = VX_UNIT(dev);
        !           158:        if (unit >= vx_cd.cd_ndevs ||
        !           159:            (sc = (struct vxsoftc *)vx_cd.cd_devs[unit]) == NULL) {
        !           160:                return (NULL);
        !           161:        }
        !           162:        port = VX_PORT(dev);
        !           163:        return sc->sc_info[port].tty;
        !           164: }
        !           165:
        !           166: int
        !           167: vxmatch(struct device *parent, void *self, void *aux)
        !           168: {
        !           169:        struct vxreg *vx_reg;
        !           170:        struct confargs *ca = aux;
        !           171:        bus_space_tag_t iot = ca->ca_iot;
        !           172:        bus_space_handle_t ioh;
        !           173:        int rc;
        !           174:
        !           175:        if (bus_space_map(iot, ca->ca_paddr, 0x10000, 0, &ioh) != 0)
        !           176:                return 0;
        !           177:        vx_reg = (struct vxreg *)bus_space_vaddr(iot, ioh);
        !           178:        rc = badaddr((vaddr_t)&vx_reg->ipc_cr, 1);
        !           179:        bus_space_unmap(iot, ioh, 0x10000);
        !           180:
        !           181:        return rc == 0;
        !           182: }
        !           183:
        !           184: void
        !           185: vxattach(struct device *parent, struct device *self, void *aux)
        !           186: {
        !           187:        struct vxsoftc *sc = (struct vxsoftc *)self;
        !           188:        struct confargs *ca = aux;
        !           189:        bus_space_tag_t iot = ca->ca_iot;
        !           190:        bus_space_handle_t ioh;
        !           191:
        !           192:        if (ca->ca_vec < 0) {
        !           193:                printf(": no more interrupts!\n");
        !           194:                return;
        !           195:        }
        !           196:        if (ca->ca_ipl < 0)
        !           197:                ca->ca_ipl = IPL_TTY;
        !           198:
        !           199:        if (bus_space_map(iot, ca->ca_paddr, 0x10000, 0, &ioh) != 0) {
        !           200:                printf(": can't map registers!\n");
        !           201:                return;
        !           202:        }
        !           203:
        !           204:        /* set up dual port memory and registers and init */
        !           205:        sc->board_vaddr = (vaddr_t)bus_space_vaddr(iot, ioh);
        !           206:        sc->vx_reg = (struct vxreg *)sc->board_vaddr;
        !           207:        sc->channel = (struct channel *)(sc->board_vaddr + 0x0100);
        !           208:        sc->sc_vec = ca->ca_vec;
        !           209:
        !           210:        printf("\n");
        !           211:
        !           212:        if (create_channels(sc) != 0) {
        !           213:                printf("%s: failed to create channel %d\n",
        !           214:                    sc->sc_dev.dv_xname, sc->channel->channel_number);
        !           215:                return;
        !           216:        }
        !           217:        if (vx_init(sc) != 0) {
        !           218:                printf("%s: failed to initialize\n", sc->sc_dev.dv_xname);
        !           219:                return;
        !           220:        }
        !           221:
        !           222:        /* enable interrupts */
        !           223:        sc->sc_ih.ih_fn = vx_intr;
        !           224:        sc->sc_ih.ih_arg = sc;
        !           225:        sc->sc_ih.ih_wantframe = 0;
        !           226:        sc->sc_ih.ih_ipl = IPL_TTY;
        !           227:
        !           228:        vmeintr_establish(ca->ca_vec, &sc->sc_ih, self->dv_xname);
        !           229: }
        !           230:
        !           231: short
        !           232: dtr_ctl(struct vxsoftc *sc, int port, int on)
        !           233: {
        !           234:        struct packet pkt;
        !           235:
        !           236:        bzero(&pkt, sizeof(struct packet));
        !           237:        pkt.command = CMD_IOCTL;
        !           238:        pkt.ioctl_cmd_l = IOCTL_TCXONC;
        !           239:        pkt.command_pipe_number = sc->channel_number;
        !           240:        pkt.status_pipe_number = sc->channel_number;
        !           241:        pkt.device_number = port;
        !           242:        if (on) {
        !           243:                pkt.ioctl_arg_l = 6;  /* assert DTR */
        !           244:        } else {
        !           245:                pkt.ioctl_arg_l = 7;  /* negate DTR */
        !           246:        }
        !           247:
        !           248:        return bpp_send(sc, &pkt, WAIT);
        !           249: }
        !           250:
        !           251: short
        !           252: rts_ctl(struct vxsoftc *sc, int port, int on)
        !           253: {
        !           254:        struct packet pkt;
        !           255:
        !           256:        bzero(&pkt, sizeof(struct packet));
        !           257:        pkt.command = CMD_IOCTL;
        !           258:        pkt.ioctl_cmd_l = IOCTL_TCXONC;
        !           259:        pkt.command_pipe_number = sc->channel_number;
        !           260:        pkt.status_pipe_number = sc->channel_number;
        !           261:        pkt.device_number = port;
        !           262:        if (on) {
        !           263:                pkt.ioctl_arg_l = 4;  /* assert RTS */
        !           264:        } else {
        !           265:                pkt.ioctl_arg_l = 5;  /* negate RTS */
        !           266:        }
        !           267:
        !           268:        return bpp_send(sc, &pkt, WAIT);
        !           269: }
        !           270:
        !           271: #if 0
        !           272: short
        !           273: flush_ctl(struct vxsoftc *sc, int port, int which)
        !           274: {
        !           275:        struct packet pkt;
        !           276:
        !           277:        bzero(&pkt, sizeof(struct packet));
        !           278:        pkt.command = CMD_IOCTL;
        !           279:        pkt.ioctl_cmd_l = IOCTL_TCFLSH;
        !           280:        pkt.command_pipe_number = sc->channel_number;
        !           281:        pkt.status_pipe_number = sc->channel_number;
        !           282:        pkt.device_number = port;
        !           283:        pkt.ioctl_arg_l = which; /* 0=input, 1=output, 2=both */
        !           284:
        !           285:        return bpp_send(sc, &pkt, WAIT);
        !           286: }
        !           287: #endif
        !           288:
        !           289: int
        !           290: vx_mctl(dev_t dev, int bits, int how)
        !           291: {
        !           292:        int s, unit, port;
        !           293:        struct vxsoftc *sc;
        !           294:        struct vx_info *vxt;
        !           295:        u_char msvr;
        !           296:
        !           297:        unit = VX_UNIT(dev);
        !           298:        port = VX_PORT(dev);
        !           299:        sc = (struct vxsoftc *)vx_cd.cd_devs[unit];
        !           300:        vxt = &sc->sc_info[port];
        !           301:
        !           302:        s = splvx();
        !           303:        switch (how) {
        !           304:        case DMSET:
        !           305:                if (bits & TIOCM_RTS) {
        !           306:                        rts_ctl(sc, port, 1);
        !           307:                        vxt->vx_linestatus |= TIOCM_RTS;
        !           308:                } else {
        !           309:                        rts_ctl(sc, port, 0);
        !           310:                        vxt->vx_linestatus &= ~TIOCM_RTS;
        !           311:                }
        !           312:                if (bits & TIOCM_DTR) {
        !           313:                        dtr_ctl(sc, port, 1);
        !           314:                        vxt->vx_linestatus |= TIOCM_DTR;
        !           315:                } else {
        !           316:                        dtr_ctl(sc, port, 0);
        !           317:                        vxt->vx_linestatus &= ~TIOCM_DTR;
        !           318:                }
        !           319:                break;
        !           320:        case DMBIC:
        !           321:                if (bits & TIOCM_RTS) {
        !           322:                        rts_ctl(sc, port, 0);
        !           323:                        vxt->vx_linestatus &= ~TIOCM_RTS;
        !           324:                }
        !           325:                if (bits & TIOCM_DTR) {
        !           326:                        dtr_ctl(sc, port, 0);
        !           327:                        vxt->vx_linestatus &= ~TIOCM_DTR;
        !           328:                }
        !           329:                break;
        !           330:
        !           331:        case DMBIS:
        !           332:                if (bits & TIOCM_RTS) {
        !           333:                        rts_ctl(sc, port, 1);
        !           334:                        vxt->vx_linestatus |= TIOCM_RTS;
        !           335:                }
        !           336:                if (bits & TIOCM_DTR) {
        !           337:                        dtr_ctl(sc, port, 1);
        !           338:                        vxt->vx_linestatus |= TIOCM_DTR;
        !           339:                }
        !           340:                break;
        !           341:
        !           342:        case DMGET:
        !           343:                bits = 0;
        !           344:                msvr = vxt->vx_linestatus;
        !           345:                if (msvr & TIOCM_DSR) {
        !           346:                        bits |= TIOCM_DSR;
        !           347:                }
        !           348:                if (msvr & TIOCM_CD) {
        !           349:                        bits |= TIOCM_CD;
        !           350:                }
        !           351:                if (msvr & TIOCM_CTS) {
        !           352:                        bits |= TIOCM_CTS;
        !           353:                }
        !           354:                if (msvr & TIOCM_DTR) {
        !           355:                        bits |= TIOCM_DTR;
        !           356:                }
        !           357:                if (msvr & TIOCM_RTS) {
        !           358:                        bits |= TIOCM_RTS;
        !           359:                }
        !           360:                break;
        !           361:        }
        !           362:
        !           363:        splx(s);
        !           364:
        !           365: #if 0
        !           366:        bits = 0;
        !           367:        bits |= TIOCM_DTR;
        !           368:        bits |= TIOCM_RTS;
        !           369:        bits |= TIOCM_CTS;
        !           370:        bits |= TIOCM_CD;
        !           371:        bits |= TIOCM_DSR;
        !           372: #endif
        !           373:        return (bits);
        !           374: }
        !           375:
        !           376: int
        !           377: vxopen(dev_t dev, int flag, int mode, struct proc *p)
        !           378: {
        !           379:        int s, unit, port, error;
        !           380:        struct vx_info *vxt;
        !           381:        struct vxsoftc *sc;
        !           382:        struct tty *tp;
        !           383:        struct packet opkt;
        !           384:        u_short code;
        !           385:
        !           386:        unit = VX_UNIT(dev);
        !           387:        port = VX_PORT(dev);
        !           388:        if (unit >= vx_cd.cd_ndevs ||
        !           389:            (sc = (struct vxsoftc *) vx_cd.cd_devs[unit]) == NULL) {
        !           390:                return (ENODEV);
        !           391:        }
        !           392:        vxt = &sc->sc_info[port];
        !           393:
        !           394: #if 0
        !           395:        flush_ctl(sc, port, 2);
        !           396: #endif
        !           397:
        !           398:        bzero(&opkt, sizeof(struct packet));
        !           399:        opkt.command_pipe_number = sc->channel_number;
        !           400:        opkt.status_pipe_number = sc->channel_number;
        !           401:        opkt.command = CMD_OPEN;
        !           402:        opkt.device_number = port;
        !           403:
        !           404:        if ((error = bpp_send(sc, &opkt, WAIT)) != 0) {
        !           405: #ifdef DEBUG_VXT
        !           406:                printf("unit %d, port %d, ", unit, port);
        !           407:                printf("error = %d\n", error);
        !           408: #endif
        !           409:                return (ENXIO);
        !           410:        }
        !           411:
        !           412:        code = opkt.event_code;
        !           413:
        !           414:        s = splvx();
        !           415:        if (vxt->tty) {
        !           416:                tp = vxt->tty;
        !           417:        } else {
        !           418:                tp = vxt->tty = ttymalloc();
        !           419:        }
        !           420:
        !           421:        /* set line status */
        !           422:        tp->t_state |= TS_CARR_ON;
        !           423:        if (code & E_DCD) {
        !           424:                tp->t_state |= TS_CARR_ON;
        !           425:                vxt->vx_linestatus |= TIOCM_CD;
        !           426:        }
        !           427:        if (code & E_DSR) {
        !           428:                vxt->vx_linestatus |= TIOCM_DSR;
        !           429:        }
        !           430:        if (code & E_CTS) {
        !           431:                vxt->vx_linestatus |= TIOCM_CTS;
        !           432:        }
        !           433:
        !           434:        tp->t_oproc = vxstart;
        !           435:        tp->t_param = vx_param;
        !           436:        tp->t_dev = dev;
        !           437:
        !           438:        if ((tp->t_state & TS_ISOPEN) == 0) {
        !           439:                tp->t_state |= TS_WOPEN;
        !           440:                ttychars(tp);
        !           441:                if (tp->t_ispeed == 0) {
        !           442:                        /*
        !           443:                         * only when cleared do we reset to defaults.
        !           444:                         */
        !           445:                        tp->t_iflag = TTYDEF_IFLAG;
        !           446:                        tp->t_oflag = TTYDEF_OFLAG;
        !           447:                        tp->t_lflag = TTYDEF_LFLAG;
        !           448:                        tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
        !           449:                        tp->t_cflag = TTYDEF_CFLAG;
        !           450:                }
        !           451:                /*
        !           452:                 * do these all the time
        !           453:                 */
        !           454:                if (vxt->vx_swflags & TIOCFLAG_CLOCAL)
        !           455:                        tp->t_cflag |= CLOCAL;
        !           456:                if (vxt->vx_swflags & TIOCFLAG_CRTSCTS)
        !           457:                        tp->t_cflag |= CRTSCTS;
        !           458:                if (vxt->vx_swflags & TIOCFLAG_MDMBUF)
        !           459:                        tp->t_cflag |= MDMBUF;
        !           460:                vx_param(tp, &tp->t_termios);
        !           461:                ttsetwater(tp);
        !           462:
        !           463:                (void)vx_mctl(dev, TIOCM_DTR | TIOCM_RTS, DMSET);
        !           464:
        !           465:                tp->t_state |= TS_CARR_ON;
        !           466:        } else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) {
        !           467:                splx(s);
        !           468:                return (EBUSY);
        !           469:        }
        !           470:
        !           471:        /*
        !           472:         * Reset the tty pointer, as there could have been a dialout
        !           473:         * use of the tty with a dialin open waiting.
        !           474:         */
        !           475:        tp->t_dev = dev;
        !           476:        vxt->open = 1;
        !           477:        splx(s);
        !           478:        return (*linesw[tp->t_line].l_open)(dev, tp);
        !           479: }
        !           480:
        !           481: int
        !           482: vx_param(struct tty *tp, struct termios *t)
        !           483: {
        !           484:        int unit, port;
        !           485:        struct vxsoftc *sc;
        !           486:        dev_t dev;
        !           487:
        !           488:        dev = tp->t_dev;
        !           489:        unit = VX_UNIT(dev);
        !           490:        if (unit >= vx_cd.cd_ndevs ||
        !           491:            (sc = (struct vxsoftc *) vx_cd.cd_devs[unit]) == NULL) {
        !           492:                return (ENODEV);
        !           493:        }
        !           494:        port = VX_PORT(dev);
        !           495:        tp->t_ispeed = t->c_ispeed;
        !           496:        tp->t_ospeed = t->c_ospeed;
        !           497:        tp->t_cflag = t->c_cflag;
        !           498:        vx_ccparam(sc, t, port);
        !           499:        vx_unblock(tp);
        !           500:        return 0;
        !           501: }
        !           502:
        !           503: int
        !           504: vxclose(dev_t dev, int flag, int mode, struct proc *p)
        !           505: {
        !           506:        int unit, port;
        !           507:        struct tty *tp;
        !           508:        struct vx_info *vxt;
        !           509:        struct vxsoftc *sc;
        !           510:        int s;
        !           511:        struct packet cpkt;
        !           512:
        !           513:        unit = VX_UNIT(dev);
        !           514:        if (unit >= vx_cd.cd_ndevs ||
        !           515:            (sc = (struct vxsoftc *) vx_cd.cd_devs[unit]) == NULL) {
        !           516:                return (ENODEV);
        !           517:        }
        !           518:        port = VX_PORT(dev);
        !           519:        vxt = &sc->sc_info[port];
        !           520: #if 0
        !           521:        flush_ctl(sc, port, 2); /* flush both input and output */
        !           522: #endif
        !           523:
        !           524:        tp = vxt->tty;
        !           525:        (*linesw[tp->t_line].l_close)(tp, flag);
        !           526:
        !           527:        s = splvx();
        !           528:
        !           529:        if ((tp->t_cflag & HUPCL) != 0) {
        !           530:                rts_ctl(sc, port, 0);
        !           531:                dtr_ctl(sc, port, 0);
        !           532:        }
        !           533:
        !           534:        bzero(&cpkt, sizeof(struct packet));
        !           535:        cpkt.command_pipe_number = sc->channel_number;
        !           536:        cpkt.status_pipe_number = sc->channel_number;
        !           537:        cpkt.command = CMD_CLOSE;
        !           538:        cpkt.device_number = port;
        !           539:        bpp_send(sc, &cpkt, NOWAIT);
        !           540:
        !           541:        vxt->open = 0;
        !           542:        splx(s);
        !           543:        ttyclose(tp);
        !           544:
        !           545:        return (0);
        !           546: }
        !           547:
        !           548: void
        !           549: read_wakeup(struct vxsoftc *sc, int port)
        !           550: {
        !           551:        struct packet rwp;
        !           552:        struct vx_info *volatile vxt;
        !           553:
        !           554:        vxt = &sc->sc_info[port];
        !           555:        /*
        !           556:         * If we already have a read_wakeup paket
        !           557:         * for this port, do nothing.
        !           558:         */
        !           559:        if (vxt->read_pending != 0)
        !           560:                return;
        !           561:        else
        !           562:                vxt->read_pending = 1;
        !           563:
        !           564:        bzero(&rwp, sizeof(struct packet));
        !           565:        rwp.command_pipe_number = sc->channel_number;
        !           566:        rwp.status_pipe_number = sc->channel_number;
        !           567:        rwp.command = CMD_READW;
        !           568:        rwp.device_number = port;
        !           569:
        !           570:        /*
        !           571:         * Do not wait.  Characters will be transferred
        !           572:         * to (*linesw[tp->t_line].l_rint)(c, tp); by
        !           573:         * vx_intr()  (IPC will notify via interrupt)
        !           574:         */
        !           575:        bpp_send(sc, &rwp, NOWAIT);
        !           576: }
        !           577:
        !           578: int
        !           579: vxread(dev_t dev, struct uio *uio, int flag)
        !           580: {
        !           581:        int unit, port;
        !           582:        struct tty *tp;
        !           583:        struct vx_info *volatile vxt;
        !           584:        struct vxsoftc *volatile sc;
        !           585:
        !           586:        unit = VX_UNIT(dev);
        !           587:        if (unit >= vx_cd.cd_ndevs ||
        !           588:            (sc = (struct vxsoftc *) vx_cd.cd_devs[unit]) == NULL) {
        !           589:                return (ENODEV);
        !           590:        }
        !           591:        port = VX_PORT(dev);
        !           592:        vxt = &sc->sc_info[port];
        !           593:        tp = vxt->tty;
        !           594:        if (!tp)
        !           595:                return ENXIO;
        !           596:        return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
        !           597: }
        !           598:
        !           599: int
        !           600: vxwrite(dev_t dev, struct uio *uio, int flag)
        !           601: {
        !           602:        int unit, port;
        !           603:        struct tty *tp;
        !           604:        struct vx_info *vxt;
        !           605:        struct vxsoftc *sc;
        !           606:        struct wring *wp;
        !           607:        struct packet wwp;
        !           608:        u_short get, put;
        !           609:
        !           610:        unit = VX_UNIT(dev);
        !           611:        if (unit >= vx_cd.cd_ndevs ||
        !           612:            (sc = (struct vxsoftc *) vx_cd.cd_devs[unit]) == NULL) {
        !           613:                return (ENODEV);
        !           614:        }
        !           615:        port = VX_PORT(dev);
        !           616:        vxt = &sc->sc_info[port];
        !           617:        tp = vxt->tty;
        !           618:        if (!tp)
        !           619:                return ENXIO;
        !           620:
        !           621:        wp = sc->sc_info[port].wringp;
        !           622:        get = wp->get;
        !           623:        put = wp->put;
        !           624:        if ((put + 1) == get) {
        !           625:                bzero(&wwp, sizeof(struct packet));
        !           626:                wwp.command_pipe_number = sc->channel_number;
        !           627:                wwp.status_pipe_number = sc->channel_number;
        !           628:                wwp.command = CMD_WRITEW;
        !           629:                wwp.device_number = port;
        !           630:                if (bpp_send(sc, &wwp, WAIT))
        !           631:                        return (ENXIO);
        !           632:        }
        !           633:
        !           634:        return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
        !           635: }
        !           636:
        !           637: int
        !           638: vxioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
        !           639: {
        !           640:        int error;
        !           641:        int unit, port;
        !           642:        struct tty *tp;
        !           643:        struct vx_info *vxt;
        !           644:        struct vxsoftc *sc;
        !           645:
        !           646:        unit = VX_UNIT(dev);
        !           647:        if (unit >= vx_cd.cd_ndevs ||
        !           648:            (sc = (struct vxsoftc *) vx_cd.cd_devs[unit]) == NULL) {
        !           649:                return (ENODEV);
        !           650:        }
        !           651:        port = VX_PORT(dev);
        !           652:        vxt = &sc->sc_info[port];
        !           653:        tp = vxt->tty;
        !           654:        if (!tp)
        !           655:                return ENXIO;
        !           656:
        !           657:        error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
        !           658:        if (error >= 0)
        !           659:                return (error);
        !           660:
        !           661:        error = ttioctl(tp, cmd, data, flag, p);
        !           662:        if (error >= 0)
        !           663:                return (error);
        !           664:
        !           665:        switch (cmd) {
        !           666:        case TIOCSBRK:
        !           667:                /* */
        !           668:                break;
        !           669:
        !           670:        case TIOCCBRK:
        !           671:                /* */
        !           672:                break;
        !           673:
        !           674:        case TIOCSDTR:
        !           675:                vx_mctl(dev, TIOCM_DTR | TIOCM_RTS, DMBIS);
        !           676:                break;
        !           677:
        !           678:        case TIOCCDTR:
        !           679:                vx_mctl(dev, TIOCM_DTR | TIOCM_RTS, DMBIC);
        !           680:                break;
        !           681:
        !           682:        case TIOCMSET:
        !           683:                vx_mctl(dev, *(int *)data, DMSET);
        !           684:                break;
        !           685:
        !           686:        case TIOCMBIS:
        !           687:                vx_mctl(dev, *(int *)data, DMBIS);
        !           688:                break;
        !           689:
        !           690:        case TIOCMBIC:
        !           691:                vx_mctl(dev, *(int *)data, DMBIC);
        !           692:                break;
        !           693:
        !           694:        case TIOCMGET:
        !           695:                *(int *)data = vx_mctl(dev, 0, DMGET);
        !           696:                break;
        !           697:
        !           698:        case TIOCGFLAGS:
        !           699:                *(int *)data = vxt->vx_swflags;
        !           700:                break;
        !           701:
        !           702:        case TIOCSFLAGS:
        !           703:                error = suser(p, 0);
        !           704:                if (error != 0)
        !           705:                        return (EPERM);
        !           706:
        !           707:                vxt->vx_swflags = *(int *)data;
        !           708:                vxt->vx_swflags &= /* only allow valid flags */
        !           709:                    (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL | TIOCFLAG_CRTSCTS);
        !           710:                break;
        !           711:
        !           712:        default:
        !           713:                return (ENOTTY);
        !           714:        }
        !           715:
        !           716:        return 0;
        !           717: }
        !           718:
        !           719: int
        !           720: vxstop(struct tty *tp, int flag)
        !           721: {
        !           722:        int s;
        !           723:
        !           724:        s = splvx();
        !           725:        if (tp->t_state & TS_BUSY) {
        !           726:                if ((tp->t_state & TS_TTSTOP) == 0)
        !           727:                        tp->t_state |= TS_FLUSH;
        !           728:        }
        !           729:        splx(s);
        !           730:        return 0;
        !           731: }
        !           732:
        !           733: void
        !           734: vxputc(struct vxsoftc *sc, int port, u_char c)
        !           735: {
        !           736:        struct wring *wp;
        !           737:
        !           738:        wp = sc->sc_info[port].wringp;
        !           739:        wp->data[wp->put++ & (WRING_BUF_SIZE - 1)] = c;
        !           740:        wp->put &= (WRING_BUF_SIZE - 1);
        !           741: }
        !           742:
        !           743: u_short
        !           744: vxtspeed(int speed)
        !           745: {
        !           746:        switch (speed) {
        !           747:        case B0:
        !           748:                return VB0;
        !           749:        case B50:
        !           750:                return VB50;
        !           751:        case B75:
        !           752:                return VB75;
        !           753:        case B110:
        !           754:                return VB110;
        !           755:        case B134:
        !           756:                return VB134;
        !           757:        case B150:
        !           758:                return VB150;
        !           759:        case B200:
        !           760:                return VB200;
        !           761:        case B300:
        !           762:                return VB300;
        !           763:        case B600:
        !           764:                return VB600;
        !           765:        case B1200:
        !           766:                return VB1200;
        !           767:        case B1800:
        !           768:                return VB1800;
        !           769:        case B2400:
        !           770:                return VB2400;
        !           771:        case B4800:
        !           772:                return VB4800;
        !           773:        case B9600:
        !           774:                return VB9600;
        !           775:        case B19200:
        !           776:                return VB19200;
        !           777:        case B38400:
        !           778:                return VB38400;
        !           779:        default:
        !           780:                return VB9600;
        !           781:        }
        !           782: }
        !           783:
        !           784: int
        !           785: vx_ccparam(struct vxsoftc *sc, struct termios *par, int port)
        !           786: {
        !           787:        int imask = 0, s;
        !           788:        int cflag;
        !           789:        struct packet pkt;
        !           790:
        !           791:        if (par->c_ospeed == 0) {
        !           792:                s = splvx();
        !           793:                /* disconnect, drop RTS DTR stop receiver */
        !           794:                rts_ctl(sc, port, 0);
        !           795:                dtr_ctl(sc, port, 0);
        !           796:                splx(s);
        !           797:                return (0xff);
        !           798:        }
        !           799:
        !           800:        bzero(&pkt, sizeof(struct packet));
        !           801:        pkt.command = CMD_IOCTL;
        !           802:        pkt.ioctl_cmd_l = IOCTL_TCGETA;
        !           803:        pkt.command_pipe_number = sc->channel_number;
        !           804:        pkt.status_pipe_number = sc->channel_number;
        !           805:        pkt.device_number = port;
        !           806:        if (bpp_send(sc, &pkt, WAIT))
        !           807:                return 0xff;
        !           808:
        !           809:        cflag = pkt.pb.tio.c_cflag;
        !           810:        cflag |= vxtspeed(par->c_ospeed);
        !           811:
        !           812:        switch (par->c_cflag & CSIZE) {
        !           813:        case CS5:
        !           814:                cflag |= VCS5;
        !           815:                imask = 0x1F;
        !           816:                break;
        !           817:        case CS6:
        !           818:                cflag |= VCS6;
        !           819:                imask = 0x3F;
        !           820:                break;
        !           821:        case CS7:
        !           822:                cflag |= VCS7;
        !           823:                imask = 0x7F;
        !           824:                break;
        !           825:        default:
        !           826:                cflag |= VCS8;
        !           827:                imask = 0xFF;
        !           828:        }
        !           829:
        !           830:        if (par->c_cflag & PARENB) cflag |= VPARENB;
        !           831:        else cflag &= ~VPARENB;
        !           832:        if (par->c_cflag & PARODD) cflag |= VPARODD;
        !           833:        else cflag &= ~VPARODD;
        !           834:        if (par->c_cflag & CREAD) cflag |= VCREAD;
        !           835:        else cflag &= ~VCREAD;
        !           836:        if (par->c_cflag & CLOCAL) cflag |= VCLOCAL;
        !           837:        else cflag &= ~VCLOCAL;
        !           838:        if (par->c_cflag & HUPCL) cflag |= VHUPCL;
        !           839:        else cflag &= ~VHUPCL;
        !           840:
        !           841:        pkt.command = CMD_IOCTL;
        !           842:        pkt.ioctl_cmd_l = IOCTL_TCSETA;
        !           843:        pkt.command_pipe_number = sc->channel_number;
        !           844:        pkt.status_pipe_number = sc->channel_number;
        !           845:        pkt.device_number = port;
        !           846:        pkt.pb.tio.c_cflag = cflag;
        !           847:        if (bpp_send(sc, &pkt, WAIT))
        !           848:                return 0xff;
        !           849:
        !           850:        return imask;
        !           851: }
        !           852:
        !           853: void
        !           854: vx_unblock(struct tty *tp)
        !           855: {
        !           856:        tp->t_state &= ~TS_FLUSH;
        !           857:        if (tp->t_outq.c_cc != 0)
        !           858:                vxstart(tp);
        !           859: }
        !           860:
        !           861: void
        !           862: vxstart(struct tty *tp)
        !           863: {
        !           864:        dev_t dev;
        !           865:        struct vxsoftc *sc;
        !           866:        struct wring *wp;
        !           867:        int cc, port, unit, s, cnt, i;
        !           868:        u_short get, put;
        !           869:        char buffer[256];
        !           870:
        !           871:        dev = tp->t_dev;
        !           872:        port = VX_PORT(dev);
        !           873:        unit = VX_UNIT(dev);
        !           874:        if (unit >= vx_cd.cd_ndevs ||
        !           875:            (sc = (struct vxsoftc *) vx_cd.cd_devs[unit]) == NULL) {
        !           876:                return;
        !           877:        }
        !           878:
        !           879:        if ((tp->t_state & TS_ISOPEN) == 0)
        !           880:                return;
        !           881:
        !           882:        s = splvx();
        !           883:        if ((tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP | TS_FLUSH)) == 0) {
        !           884:                tp->t_state |= TS_BUSY;
        !           885:                wp = sc->sc_info[port].wringp;
        !           886:                get = wp->get;
        !           887:                put = wp->put;
        !           888:                cc = tp->t_outq.c_cc;
        !           889:                while (cc > 0) {
        !           890:                        cnt = min(sizeof buffer, cc);
        !           891:                        cnt = q_to_b(&tp->t_outq, buffer, cnt);
        !           892:                        buffer[cnt] = 0;
        !           893:                        for (i = 0; i < cnt; i++) {
        !           894:                                vxputc(sc, port, buffer[i]);
        !           895:                        }
        !           896:                        cc -= cnt;
        !           897:                }
        !           898:                tp->t_state &= ~TS_BUSY;
        !           899:        }
        !           900:        splx(s);
        !           901: }
        !           902:
        !           903: void
        !           904: read_chars(struct vxsoftc *sc, int port)
        !           905: {
        !           906:        /*
        !           907:         * This routine is called by vx_intr() when there are
        !           908:         * characters in the read ring.  It will process one
        !           909:         * cooked line, put the chars in the line disipline ring,
        !           910:         * and then return.  The characters may then
        !           911:         * be read by vxread.
        !           912:         */
        !           913:        struct vx_info *vxt;
        !           914:        struct rring *rp;
        !           915:        struct tty *tp;
        !           916:        u_short get, put;
        !           917:        int frame_count, i, open;
        !           918:        char c;
        !           919:
        !           920:        vxt = &sc->sc_info[port];
        !           921:        tp = vxt->tty;
        !           922:        rp = vxt->rringp;
        !           923:        open = vxt->open;
        !           924:        get = rp->get;
        !           925:        put = rp->put;
        !           926: #ifdef DEBUG_VXT
        !           927:        printf("read_chars() get=%d, put=%d ", get, put);
        !           928:        printf("open = %d ring at 0x%x\n", open, rp);
        !           929: #endif
        !           930:        while (get != put) {
        !           931:                frame_count = rp->data[rp->get++ & (RRING_BUF_SIZE - 1)];
        !           932:                rp->get &= (RRING_BUF_SIZE - 1);
        !           933:                for (i = 0; i < frame_count; i++) {
        !           934:                        c = rp->data[rp->get++ & (RRING_BUF_SIZE - 1)];
        !           935:                        rp->get &= (RRING_BUF_SIZE - 1);
        !           936:                        if (open)
        !           937:                                (*linesw[tp->t_line].l_rint)(c, tp);
        !           938:                }
        !           939:                c = rp->data[rp->get++ & (RRING_BUF_SIZE - 1)];
        !           940:                rp->get &= (RRING_BUF_SIZE - 1);
        !           941:                if (!(c & DELIMITER)) {
        !           942:                        vx_frame(sc, port);
        !           943:                        break;
        !           944:                } else {
        !           945:                        break;
        !           946:                }
        !           947:                get = rp->get;
        !           948:                put = rp->put;
        !           949:        }
        !           950:        vxt->read_pending = 0;
        !           951:        read_wakeup(sc, port);
        !           952: }
        !           953:
        !           954: void
        !           955: ccode(struct vxsoftc *sc, int port, char c)
        !           956: {
        !           957:        struct vx_info *vxt;
        !           958:        struct tty *tp;
        !           959:
        !           960:        tp = vxt->tty;
        !           961:        (*linesw[tp->t_line].l_rint)(c, tp);
        !           962: }
        !           963:
        !           964: int
        !           965: vx_intr(void *arg)
        !           966: {
        !           967:        struct vxsoftc *sc = arg;
        !           968:        struct envelope *envp, *next_envp;
        !           969:        struct packet *pktp, pkt;
        !           970:        int valid;
        !           971:        short cmd;
        !           972:        u_char port;
        !           973:
        !           974:        while (env_isvalid(get_status_head(sc))) {
        !           975:                pktp = get_packet(sc, get_status_head(sc));
        !           976:                valid = env_isvalid(get_status_head(sc));
        !           977:                cmd = pktp->command;
        !           978:                port = pktp->device_number;
        !           979:                /*
        !           980:                 * If we are waiting on this packet, store the info
        !           981:                 * so bpp_send can process the packet
        !           982:                 */
        !           983:                if (sc->sc_bppwait_pktp == pktp)
        !           984:                        d16_bcopy(pktp, &sc->sc_bppwait_pkt, sizeof(struct packet));
        !           985:
        !           986:                d16_bcopy(pktp, &pkt, sizeof(struct packet));
        !           987:                next_envp = get_next_envelope(sc, get_status_head(sc));
        !           988:                envp = get_status_head(sc);
        !           989:                /* return envelope and packet to the free queues */
        !           990:                put_free_envelope(sc, envp);
        !           991:                put_free_packet(sc, pktp);
        !           992:                /* mark new status pipe head pointer */
        !           993:                set_status_head(sc, next_envp);
        !           994:                /* if it was valid, process packet */
        !           995:                switch (cmd) {
        !           996:                case CMD_READW:
        !           997: #ifdef DEBUG_VXT
        !           998:                        printf("READW Packet\n");
        !           999: #endif
        !          1000:                        read_chars(sc, port);
        !          1001:                        break;
        !          1002:                case CMD_WRITEW:
        !          1003: #ifdef DEBUG_VXT
        !          1004:                        printf("WRITEW Packet\n");  /* Still don't know XXXsmurph */
        !          1005: #endif
        !          1006:                        break;
        !          1007:                case CMD_EVENT:
        !          1008: #ifdef DEBUG_VXT
        !          1009:                        printf("EVENT Packet\n");
        !          1010: #endif
        !          1011:                        vx_event(sc, &pkt);
        !          1012:                        break;
        !          1013:                case CMD_PROCESSED:
        !          1014: #ifdef DEBUG_VXT
        !          1015:                        printf("CMD_PROCESSED Packet\n");
        !          1016: #endif
        !          1017:                        break;
        !          1018:                default:
        !          1019: #ifdef DEBUG_VXT
        !          1020:                        printf("Other packet 0x%x\n", cmd);
        !          1021: #endif
        !          1022:                        break;
        !          1023:                }
        !          1024:        }
        !          1025:        return 1;
        !          1026: }
        !          1027:
        !          1028: int
        !          1029: vx_event(struct vxsoftc *sc, struct packet *evntp)
        !          1030: {
        !          1031:        u_short code = evntp->event_code;
        !          1032:        struct packet evnt;
        !          1033:        struct vx_info *vxt;
        !          1034:
        !          1035:        vxt = &sc->sc_info[evntp->device_number];
        !          1036:
        !          1037:        if (code & E_INTR) {
        !          1038:                ccode(sc, evntp->device_number, CINTR);
        !          1039:        }
        !          1040:        if (code & E_QUIT) {
        !          1041:                ccode(sc, evntp->device_number, CQUIT);
        !          1042:        }
        !          1043:        if (code & E_HUP) {
        !          1044:                rts_ctl(sc, evntp->device_number, 0);
        !          1045:                dtr_ctl(sc, evntp->device_number, 0);
        !          1046:        }
        !          1047:        if (code & E_DCD) {
        !          1048:                vxt->vx_linestatus |= TIOCM_CD;
        !          1049:        }
        !          1050:        if (code & E_DSR) {
        !          1051:                vxt->vx_linestatus |= TIOCM_DSR;
        !          1052:        }
        !          1053:        if (code & E_CTS) {
        !          1054:                vxt->vx_linestatus |= TIOCM_CTS;
        !          1055:        }
        !          1056:        if (code & E_LOST_DCD) {
        !          1057:                vxt->vx_linestatus &= ~TIOCM_CD;
        !          1058:        }
        !          1059:        if (code & E_LOST_DSR) {
        !          1060:                vxt->vx_linestatus &= ~TIOCM_DSR;
        !          1061:        }
        !          1062:        if (code & E_LOST_CTS) {
        !          1063:                vxt->vx_linestatus &= ~TIOCM_CTS;
        !          1064:        }
        !          1065:        if (code & E_PR_FAULT) {
        !          1066:                /* do something... */
        !          1067:        }
        !          1068:        if (code & E_PR_POUT) {
        !          1069:                /* do something... */
        !          1070:        }
        !          1071:        if (code & E_PR_SELECT) {
        !          1072:                /* do something... */
        !          1073:        }
        !          1074:        if (code & E_SWITCH) {
        !          1075:                /* do something... */
        !          1076:        }
        !          1077:        if (code & E_BREAK) {
        !          1078:                vx_break(sc, evntp->device_number);
        !          1079:        }
        !          1080:
        !          1081:        /* send an event packet back to the device */
        !          1082:        bzero(&evnt, sizeof(struct packet));
        !          1083:        evnt.command = CMD_EVENT;
        !          1084:        evnt.device_number = evntp->device_number;
        !          1085:        evnt.command_pipe_number = sc->channel_number;
        !          1086:        /* return status on same channel */
        !          1087:        evnt.status_pipe_number = sc->channel_number;
        !          1088:        /* send packet to the firmware */
        !          1089:        bpp_send(sc, &evnt, NOWAIT);
        !          1090:
        !          1091:        return 1;
        !          1092: }
        !          1093:
        !          1094: void
        !          1095: vx_overflow(struct vxsoftc *sc, int port, long *ptime, u_char *msg)
        !          1096: {
        !          1097:        log(LOG_WARNING, "%s port %d: overrun\n",
        !          1098:            sc->sc_dev.dv_xname, port);
        !          1099: }
        !          1100:
        !          1101: void
        !          1102: vx_frame(struct vxsoftc *sc, int port)
        !          1103: {
        !          1104:        log(LOG_WARNING, "%s port %d: frame error\n",
        !          1105:            sc->sc_dev.dv_xname, port);
        !          1106: }
        !          1107:
        !          1108: void
        !          1109: vx_break(struct vxsoftc *sc, int port)
        !          1110: {
        !          1111:        /*
        !          1112:         * No need to check for a ddb break, as the console can never be on
        !          1113:         * this hardware.
        !          1114:         */
        !          1115:        log(LOG_WARNING, "%s port %d: break detected\n",
        !          1116:            sc->sc_dev.dv_xname, port);
        !          1117: }
        !          1118:
        !          1119: /*
        !          1120:  *     Initialization and Buffered Pipe Protocol (BPP) code
        !          1121:  */
        !          1122:
        !          1123: void
        !          1124: create_free_queue(struct vxsoftc *sc)
        !          1125: {
        !          1126:        int i;
        !          1127:        struct envelope *envp, env;
        !          1128:        struct packet *pktp, pkt;
        !          1129:
        !          1130:        envp = (struct envelope *)VIRTUAL(ENVELOPE_AREA);
        !          1131:        sc->elist_head = envp;
        !          1132:        for (i = 1; i <= NENVELOPES; i++) {
        !          1133:                bzero(&env, sizeof(struct envelope));
        !          1134:                if (i == NENVELOPES)
        !          1135:                        env.link = NULL;
        !          1136:                else
        !          1137:                        env.link = ENVELOPE_AREA + i * sizeof(struct envelope);
        !          1138:                env.packet_ptr = NULL;
        !          1139:                env.valid_flag = 0;
        !          1140:                d16_bcopy(&env, envp, sizeof(struct envelope));
        !          1141:                envp++;
        !          1142:        }
        !          1143:        sc->elist_tail = --envp;
        !          1144:
        !          1145:        pktp = (struct packet *)VIRTUAL(PACKET_AREA);
        !          1146:        sc->plist_head = pktp;
        !          1147:        for (i = 1; i <= NPACKETS; i++) {
        !          1148:                bzero(&pkt, sizeof(struct packet));
        !          1149:                if (i == NPACKETS)
        !          1150:                        pkt.link = NULL;
        !          1151:                else
        !          1152:                        pkt.link = PACKET_AREA + i * sizeof(struct packet);
        !          1153:                d16_bcopy(&pkt, pktp, sizeof(struct packet));
        !          1154:                pktp++;
        !          1155:        }
        !          1156:        sc->plist_tail = --pktp;
        !          1157: }
        !          1158:
        !          1159: void *
        !          1160: get_free_envelope(struct vxsoftc *sc)
        !          1161: {
        !          1162:        struct envelope *envp;
        !          1163:        paddr_t link;
        !          1164:
        !          1165:        envp = sc->elist_head;
        !          1166:        /* pick envelope next pointer from the envelope itself */
        !          1167:        d16_bcopy((const void *)&envp->link, &link, sizeof link);
        !          1168:        sc->elist_head = (struct envelope *)VIRTUAL(link);
        !          1169:        d16_bzero(envp, sizeof(struct envelope));
        !          1170:
        !          1171:        return envp;
        !          1172: }
        !          1173:
        !          1174: void
        !          1175: put_free_envelope(struct vxsoftc *sc, void *ep)
        !          1176: {
        !          1177:        struct envelope *envp = (struct envelope *)ep;
        !          1178:        u_long link;
        !          1179:
        !          1180: #if 0
        !          1181:        d16_bzero(envp, sizeof(struct envelope));
        !          1182: #endif
        !          1183:        /* put envelope next pointer in the envelope itself */
        !          1184:        link = PHYSICAL((vaddr_t)envp);
        !          1185:        d16_bzero((void *)&envp->link, sizeof envp->link);
        !          1186:        d16_bcopy(&link, (void *)&sc->elist_tail->link, sizeof link);
        !          1187:
        !          1188:        sc->elist_tail = envp;
        !          1189: }
        !          1190:
        !          1191: void *
        !          1192: get_free_packet(struct vxsoftc *sc)
        !          1193: {
        !          1194:        struct packet *pktp;
        !          1195:        paddr_t link;
        !          1196:
        !          1197:        pktp = sc->plist_head;
        !          1198:        /* pick packet next pointer from the packet itself */
        !          1199:        d16_bcopy((const void *)&pktp->link, &link, sizeof link);
        !          1200:        sc->plist_head = (struct packet *)VIRTUAL(link);
        !          1201:        d16_bzero(pktp, sizeof(struct packet));
        !          1202:
        !          1203:        return pktp;
        !          1204: }
        !          1205:
        !          1206: void
        !          1207: put_free_packet(struct vxsoftc *sc, void *pp)
        !          1208: {
        !          1209:        struct packet *pktp = (struct packet *)pp;
        !          1210:        u_long link;
        !          1211:
        !          1212: #if 0
        !          1213:        d16_bzero(pktp, sizeof(struct packet));
        !          1214: #endif
        !          1215:        pktp->command = CMD_PROCESSED;
        !          1216:        /* put packet next pointer in the packet itself */
        !          1217:        link = PHYSICAL((vaddr_t)pktp);
        !          1218:        d16_bzero((void *)&pktp->link, sizeof pktp->link);
        !          1219:        d16_bcopy(&link, (void *)&sc->plist_tail->link, sizeof link);
        !          1220:
        !          1221:        sc->plist_tail = pktp;
        !          1222: }
        !          1223:
        !          1224: /*
        !          1225:  * This is the nitty gritty.  All the rest if this code
        !          1226:  * was hell to come by.  Getting this right from the
        !          1227:  * Moto manual took *time*!
        !          1228:  */
        !          1229: int
        !          1230: create_channels(struct vxsoftc *sc)
        !          1231: {
        !          1232:        u_long envp;
        !          1233:        u_short status;
        !          1234:        u_short tas;
        !          1235:        struct vxreg *ipc_csr = sc->vx_reg;
        !          1236:
        !          1237:        /* wait for busy bit to clear */
        !          1238:        while ((ipc_csr->ipc_cr & IPC_CR_BUSY))
        !          1239:                ;
        !          1240:
        !          1241:        create_free_queue(sc);
        !          1242:
        !          1243:        /* set up channel header. we only want one */
        !          1244:        tas = ipc_csr->ipc_tas;
        !          1245:        while (!(tas & IPC_TAS_VALID_STATUS)) {
        !          1246:                envp = PHYSICAL((vaddr_t)get_free_envelope(sc));
        !          1247:                sc->channel->command_pipe_head_ptr_h = HI(envp);
        !          1248:                sc->channel->command_pipe_head_ptr_l = LO(envp);
        !          1249:                sc->channel->command_pipe_tail_ptr_h =
        !          1250:                    sc->channel->command_pipe_head_ptr_h;
        !          1251:                sc->channel->command_pipe_tail_ptr_l =
        !          1252:                    sc->channel->command_pipe_head_ptr_l;
        !          1253:                envp = PHYSICAL((vaddr_t)get_free_envelope(sc));
        !          1254:                sc->channel->status_pipe_head_ptr_h = HI(envp);
        !          1255:                sc->channel->status_pipe_head_ptr_l = LO(envp);
        !          1256:                sc->channel->status_pipe_tail_ptr_h =
        !          1257:                    sc->channel->status_pipe_head_ptr_h;
        !          1258:                sc->channel->status_pipe_tail_ptr_l =
        !          1259:                    sc->channel->status_pipe_head_ptr_l;
        !          1260:                sc->channel->interrupt_level = IPL_TTY;
        !          1261:                sc->channel->interrupt_vec = sc->sc_vec;
        !          1262:                sc->channel->channel_priority = 0;
        !          1263:                sc->channel->channel_number = 0;
        !          1264:                sc->channel->valid = 1;
        !          1265:                sc->channel->address_modifier = 0x8d; /* A32/D16 supervisor data access */
        !          1266:                sc->channel->datasize = 0; /* 32 bit data mode */
        !          1267:
        !          1268:                /* loop until TAS bit is zero */
        !          1269:                while ((ipc_csr->ipc_tas & IPC_TAS_TAS))
        !          1270:                        ;
        !          1271:                ipc_csr->ipc_tas |= IPC_TAS_TAS;
        !          1272:                /* load address of channel header */
        !          1273:                ipc_csr->ipc_addrh = HI(CHANNEL_H);
        !          1274:                ipc_csr->ipc_addrl = LO(CHANNEL_H);
        !          1275:                /* load address modifier reg (supervisor data access) */
        !          1276:                ipc_csr->ipc_amr = 0x8d;
        !          1277:                /* load tas with create channel command */
        !          1278:                ipc_csr->ipc_tas |= IPC_CSR_CREATE;
        !          1279:                /* set vaild command bit */
        !          1280:                ipc_csr->ipc_tas |= IPC_TAS_VALID_CMD;
        !          1281:                /* notify IPC of the CSR command */
        !          1282:                ipc_csr->ipc_cr |= IPC_CR_ATTEN;
        !          1283:
        !          1284:                /* loop until IPC sets valid status bit */
        !          1285:                delay(5000);
        !          1286:                tas = ipc_csr->ipc_tas;
        !          1287:        }
        !          1288:
        !          1289:        /* save the status */
        !          1290:        status = ipc_csr->ipc_sr;
        !          1291:        /* set COMMAND COMPLETE bit */
        !          1292:        ipc_csr->ipc_tas |= IPC_TAS_COMPLETE;
        !          1293:        /* notify IPC that we are through */
        !          1294:        ipc_csr->ipc_cr |= IPC_CR_ATTEN;
        !          1295:        /* check and see if the channel was created */
        !          1296:        if (status == 0 && sc->channel->valid) {
        !          1297:                sc->channel_number = sc->channel->channel_number;
        !          1298: #ifdef DEBUG_VXT
        !          1299:                printf("%s: created channel %d\n", sc->sc_dev.dv_xname,
        !          1300:                       sc->channel->channel_number);
        !          1301: #endif
        !          1302:                return 0;
        !          1303:        } else {
        !          1304:                switch (status) {
        !          1305:                case 0x0000:
        !          1306:                        printf("%s: channel not valid\n",
        !          1307:                               sc->sc_dev.dv_xname);
        !          1308:                        break;
        !          1309:                case 0xFFFF:
        !          1310:                        printf("%s: invalid CSR command\n",
        !          1311:                               sc->sc_dev.dv_xname);
        !          1312:                        break;
        !          1313:                case 0xC000:
        !          1314:                        printf("%s: could not read channel structure\n",
        !          1315:                               sc->sc_dev.dv_xname);
        !          1316:                        break;
        !          1317:                case 0x8000:
        !          1318:                        printf("%s: could not write channel structure\n",
        !          1319:                               sc->sc_dev.dv_xname);
        !          1320:                        break;
        !          1321:                default:
        !          1322:                        printf("%s: unknown IPC CSR command error 0x%x\n",
        !          1323:                               sc->sc_dev.dv_xname, status);
        !          1324:                        break;
        !          1325:                }
        !          1326:                return 1;
        !          1327:        }
        !          1328: }
        !          1329:
        !          1330: struct envelope *
        !          1331: get_next_envelope(struct vxsoftc *sc, struct envelope *thisenv)
        !          1332: {
        !          1333:        paddr_t ptr;
        !          1334:
        !          1335:        d16_bcopy((const void*)&thisenv->link, &ptr, sizeof ptr);
        !          1336:
        !          1337:        return (struct envelope *)VIRTUAL(ptr);
        !          1338: }
        !          1339:
        !          1340: int
        !          1341: env_isvalid(struct envelope *thisenv)
        !          1342: {
        !          1343:        return (int)thisenv->valid_flag;
        !          1344: }
        !          1345:
        !          1346: struct envelope *
        !          1347: get_cmd_tail(struct vxsoftc *sc)
        !          1348: {
        !          1349:        paddr_t retaddr;
        !          1350:
        !          1351:        retaddr = sc->channel->command_pipe_tail_ptr_h << 16;
        !          1352:        retaddr += sc->channel->command_pipe_tail_ptr_l;
        !          1353:        return (struct envelope *)VIRTUAL(retaddr);
        !          1354: }
        !          1355:
        !          1356: struct envelope *
        !          1357: get_status_head(struct vxsoftc *sc)
        !          1358: {
        !          1359:        paddr_t retaddr;
        !          1360:
        !          1361:        retaddr = sc->channel->status_pipe_head_ptr_h << 16;
        !          1362:        retaddr += sc->channel->status_pipe_head_ptr_l;
        !          1363:        return (struct envelope *)VIRTUAL(retaddr);
        !          1364: }
        !          1365:
        !          1366: void
        !          1367: set_status_head(struct vxsoftc *sc, void *envp)
        !          1368: {
        !          1369:        paddr_t ptr;
        !          1370:
        !          1371:        ptr = PHYSICAL((vaddr_t)envp);
        !          1372:        sc->channel->status_pipe_head_ptr_h = HI(ptr);
        !          1373:        sc->channel->status_pipe_head_ptr_l = LO(ptr);
        !          1374: }
        !          1375:
        !          1376: struct packet *
        !          1377: get_packet(struct vxsoftc *sc, struct envelope *thisenv)
        !          1378: {
        !          1379:        paddr_t baseaddr;
        !          1380:
        !          1381:        if (thisenv == NULL)
        !          1382:                return NULL;
        !          1383:
        !          1384:        /*
        !          1385:         * packet ptr returned on status pipe is only last two bytes
        !          1386:         * so we must supply the full address based on the board address.
        !          1387:         * This also works for all envelopes because every address is an
        !          1388:         * offset to the board address.
        !          1389:         */
        !          1390:        d16_bcopy((const void *)&thisenv->packet_ptr, &baseaddr, sizeof baseaddr);
        !          1391:        return (struct packet *)VIRTUAL(baseaddr);
        !          1392: }
        !          1393:
        !          1394: /*
        !          1395:  *     Send a command via BPP
        !          1396:  */
        !          1397: int
        !          1398: bpp_send(struct vxsoftc *sc, void *pkt, int wait_flag)
        !          1399: {
        !          1400:        struct envelope *envp;
        !          1401:        struct packet *pktp;
        !          1402:        paddr_t ptr;
        !          1403:        int tmo;
        !          1404:
        !          1405:        /* load up packet in dual port mem */
        !          1406:        pktp = get_free_packet(sc);
        !          1407:        d16_bcopy(pkt, pktp, sizeof(struct packet));
        !          1408:
        !          1409:        envp = get_cmd_tail(sc);
        !          1410:        ptr = PHYSICAL((vaddr_t)get_free_envelope(sc)); /* put a NULL env on the tail */
        !          1411:        sc->channel->command_pipe_tail_ptr_h = HI(ptr);
        !          1412:        sc->channel->command_pipe_tail_ptr_l = LO(ptr);
        !          1413:        d16_bcopy(&ptr, (void *)&envp->link, sizeof envp->link);
        !          1414:        ptr = PHYSICAL((vaddr_t)pktp);
        !          1415:        d16_bcopy(&ptr, (void *)&envp->packet_ptr, sizeof envp->packet_ptr);
        !          1416:        envp->valid_flag = 1;
        !          1417:
        !          1418:        sc->vx_reg->ipc_cr |= IPC_CR_ATTEN;
        !          1419:
        !          1420:        /* wait for a packet to return */
        !          1421:        if (wait_flag == NOWAIT)
        !          1422:                return 0;
        !          1423:
        !          1424:        tmo = 0;
        !          1425:        while (pktp->command != CMD_PROCESSED) {
        !          1426: #ifdef DEBUG_VXT
        !          1427:                printf("Polling for packet 0x%x in envelope 0x%x...\n", pktp, envp);
        !          1428: #endif
        !          1429:                vx_intr(sc);
        !          1430:                if (++tmo > 20) {
        !          1431:                        printf("%s: bpp_send pkt %x env %x timed out %d\n",
        !          1432:                            sc->sc_dev.dv_xname, pktp, envp, pktp->command);
        !          1433:                        return ETIMEDOUT;
        !          1434:                }
        !          1435:                delay(5000);
        !          1436:        }
        !          1437:        d16_bcopy(pktp, pkt, sizeof(struct packet));
        !          1438:        return pktp->error_l;
        !          1439: }
        !          1440:
        !          1441: /*
        !          1442:  *     BPP commands
        !          1443:  */
        !          1444:
        !          1445: int
        !          1446: vx_init(struct vxsoftc *sc)
        !          1447: {
        !          1448:        int i;
        !          1449:        int error;
        !          1450:        struct init_info *infp, inf;
        !          1451:        paddr_t wringp, rringp;
        !          1452:        struct packet init;
        !          1453:        struct packet evnt;
        !          1454:
        !          1455:        /* init wait queue */
        !          1456:        d16_bzero(&sc->sc_bppwait_pkt, sizeof(struct packet));
        !          1457:        sc->sc_bppwait_pktp = NULL;
        !          1458:        /* set up init_info array */
        !          1459:        wringp = WRING_AREA;
        !          1460:        rringp = RRING_AREA;
        !          1461:        infp = (struct init_info *)VIRTUAL(INIT_INFO_AREA);
        !          1462:
        !          1463:        for (i = 0; i < NVXPORTS; i++) {
        !          1464:                bzero(&inf, sizeof(struct init_info));
        !          1465:                inf.write_ring_ptr_h = HI(wringp);
        !          1466:                inf.write_ring_ptr_l = LO(wringp);
        !          1467:                sc->sc_info[i].wringp = (struct wring *)VIRTUAL(wringp);
        !          1468:                inf.read_ring_ptr_h = HI(rringp);
        !          1469:                inf.read_ring_ptr_l = LO(rringp);
        !          1470:                sc->sc_info[i].rringp = (struct rring *)VIRTUAL(rringp);
        !          1471: #ifdef DEBUG_VXT
        !          1472:                printf("write at 0x%8x, read at 0x%8x\n", wringp, rringp);
        !          1473: #endif
        !          1474:                inf.write_ring_size = WRING_DATA_SIZE;
        !          1475:                inf.read_ring_size = RRING_DATA_SIZE;
        !          1476:                inf.def_termio.c_iflag = VBRKINT;
        !          1477:                inf.def_termio.c_oflag = 0;
        !          1478:                inf.def_termio.c_cflag = (VB9600 | VCS8);
        !          1479:
        !          1480:                inf.def_termio.c_lflag = VISIG; /* enable signal processing */
        !          1481:                inf.def_termio.c_line = 1; /* raw line discipline */
        !          1482:                inf.def_termio.c_cc[0] = CINTR;
        !          1483:                inf.def_termio.c_cc[1] = CQUIT;
        !          1484:                inf.def_termio.c_cc[2] = CERASE;
        !          1485:                inf.def_termio.c_cc[3] = CKILL;
        !          1486:                inf.def_termio.c_cc[4] = CEOF;
        !          1487:                inf.def_termio.c_cc[5] = CEOL;
        !          1488:                d16_bcopy(&inf, infp, sizeof(struct init_info));
        !          1489:                wringp += sizeof(struct wring);
        !          1490:                rringp += sizeof(struct rring);
        !          1491:                infp++;
        !          1492:        }
        !          1493:
        !          1494:        /* set up init_packet */
        !          1495:        bzero(&init, sizeof(struct packet));
        !          1496:        init.command = CMD_INIT;
        !          1497:        init.command_pipe_number = sc->channel_number;
        !          1498:        /* return status on the same channel */
        !          1499:        init.status_pipe_number = sc->channel_number;
        !          1500:        init.interrupt_level = IPL_TTY;
        !          1501:        init.interrupt_vec = sc->sc_vec;
        !          1502:        init.init_info_ptr_h = HI(INIT_INFO_AREA);
        !          1503:        init.init_info_ptr_l = LO(INIT_INFO_AREA);
        !          1504:
        !          1505:        /* send packet to the firmware and wait for completion */
        !          1506:        if ((error = bpp_send(sc, &init, WAIT)) != 0)
        !          1507:                return error;
        !          1508:
        !          1509:        /* send one event packet to each device */
        !          1510:        for (i = 0; i < NVXPORTS; i++) {
        !          1511:                bzero(&evnt, sizeof(struct packet));
        !          1512:                evnt.command = CMD_EVENT;
        !          1513:                evnt.device_number = i;
        !          1514:                evnt.command_pipe_number = sc->channel_number;
        !          1515:                /* return status on same channel */
        !          1516:                evnt.status_pipe_number = sc->channel_number;
        !          1517:                /* send packet to the firmware */
        !          1518:                bpp_send(sc, &evnt, NOWAIT);
        !          1519:        }
        !          1520:
        !          1521:        return 0;
        !          1522: }

CVSweb