Annotation of cci/sys/tahoeif/tty_if_sl.c, revision 1.1

1.1     ! root        1: /*
        !             2:  *     Serial Line interface
        !             3:  *     Modified for Power 6/32. 10/05/84
        !             4:  *
        !             5:  *     Rick Adams
        !             6:  *     Center for Seismic Studies
        !             7:  *     1300 N 17th Street, Suite 1450
        !             8:  *     Arlington, Virginia 22209
        !             9:  *     (703)276-7900
        !            10:  *     [email protected]
        !            11:  *     seismo!rick
        !            12:  *
        !            13:  *     Some things done here could obviously be done in a better way,
        !            14:  *     but they were done this way to minimize the number of files
        !            15:  *     that had to be changed to accomodate this device.
        !            16:  *     A lot of this code belongs in the tty driver.
        !            17:  */
        !            18: 
        !            19: #include "vx.h"
        !            20: #if NVX > 0
        !            21: long vxstart();
        !            22: long vxparam();
        !            23: #endif NVX
        !            24: 
        !            25: #include "sl.h"
        !            26: #if NSL > 0
        !            27: 
        !            28: #include "../h/param.h"
        !            29: #include "../h/systm.h"
        !            30: #include "../h/mbuf.h"
        !            31: #include "../h/buf.h"
        !            32: #include "../h/protosw.h"
        !            33: /*#include "../h/socket.h"*/
        !            34: #include "../h/vmmac.h"
        !            35: #include "../h/errno.h"
        !            36: #include "../h/ioctl.h"
        !            37: #include "../h/tty.h"
        !            38: 
        !            39: #include "../net/netisr.h"
        !            40: #include "../net/route.h"
        !            41: #include "../netinet/in.h"
        !            42: #include "../netinet/in_systm.h"
        !            43: #include "../netinet/ip.h"
        !            44: #include "../netinet/ip_var.h"
        !            45: 
        !            46: #include "../tahoe/mtpr.h"
        !            47: 
        !            48: #define        SLINES  (NSL*8)
        !            49: struct sl_softc sl_softc[SLINES];
        !            50: 
        !            51: #define FRAME_END      0300            /* Frame End */
        !            52: #define FRAME_ESCAPE   0333            /* Frame Esc */
        !            53: #define TRANS_FRAME_END        0334            /* transposed frame end */
        !            54: #define TRANS_FRAME_ESCAPE 0335                /* transposed frame esc */
        !            55: 
        !            56: #define SLTU   1500
        !            57: 
        !            58: int sloutput(), slioctl();
        !            59: 
        !            60: /*------------- debugging tools -------------*/
        !            61: #ifdef SL_DEBUG
        !            62: int    slprintfs;
        !            63: #define        SLOPEN          1
        !            64: #define        SLOUTPUT        2
        !            65: #define        SLINPUT         4
        !            66: #define        SLSTART         8
        !            67: #define        SLALL           (SLOPEN | SLOUTPUT | SLINPUT | SLSTART)
        !            68: #define SL_TRACE(X,Y)  {if (slprintfs & X) Y}
        !            69: #else SL_DEBUG
        !            70: #define SL_TRACE(X,Y)
        !            71: #endif SL_DEBUG
        !            72: /*
        !            73:  * Changes:
        !            74:  *     .       reset sc_m when enqueueing messages to IP input queue.
        !            75:  *     .       reset sc_m when deallocating sc_m if cannot allocate
        !            76:  *             more mbufs.
        !            77:  *     .       restore ipl() before returning from slstart() when 
        !            78:  *             sc_ttyp is NULL.
        !            79:  *     .       fix the window in slstart() by changing sc_oactive
        !            80:  *             with high ipl() so that slstart() would not be re-entered
        !            81:  *             when tcp time-out occurs.
        !            82:  *     .       slstart() transmits another packet when done with one.
        !            83:  *
        !            84:  *     .       when putc() fails, slstart() "backspaces" in such
        !            85:  *             a way that the FRAME_END is never preceeded by 
        !            86:  *             FRAME_ESCAPE. Otherwise, FRAME_ESCAPE could preceed
        !            87:  *             FRAME_END and causes the receiver to concatenate two
        !            88:  *             packets when packetizing input stream.
        !            89:  */
        !            90: /*
        !            91:  * Routine called when the serial line IP line discipline is entered.
        !            92:  * In effect, this also acts as "slattach", except it's not called at
        !            93:  * autoconfigure time but when the serial line is enabled for networking.
        !            94:  */
        !            95: slopen(dev, tp)
        !            96:        dev_t dev;
        !            97:        register struct tty *tp;
        !            98: {
        !            99:        register struct sl_softc *sc = sl_softc;
        !           100:        register struct sockaddr_in *sin;
        !           101:        register int nsl;
        !           102:        extern int ifqmaxlen;
        !           103:        int addloop = 0;
        !           104: 
        !           105:        if (tp->t_slsoftc)
        !           106:                return EBUSY;
        !           107: 
        !           108:        for (nsl = 0; sc->sc_ttyp;) {
        !           109:                if (++nsl >= SLINES)
        !           110:                        return(ENOSPC);
        !           111:                sc++;
        !           112:        }
        !           113: 
        !           114:        /* This is a real kludge. Since we do the attach in the rc file,
        !           115:           the loopback driver gets configured first. Now Berkeley, in its
        !           116:           infinite wisdom, when connecting to a machine through a gateway,
        !           117:           chooses the FIRST interface on its list. Guess what that is when you
        !           118:           don't have an ethernet? That's right! It's the loopback driver!
        !           119:           The following crock is an attempt to get around that.
        !           120:         */
        !           121: 
        !           122:        if ( ifnet && ifnet->if_name[0] == 'l' && ifnet->if_name[1] == 'o'
        !           123:                && ifnet->if_name[2] == '\0') {
        !           124:                /* the loopback device is configured in first */
        !           125:                ifnet = ifnet->if_next;
        !           126:                addloop++;
        !           127:        }
        !           128:        SL_TRACE(SLOPEN,
        !           129:                printf("sl%lx open:tty(%lx):softc(%lx)\n",
        !           130:                                        nsl,(long)tp,(long)sc);)
        !           131:        tp->t_slsoftc = (struct sl_softc *)sc;
        !           132:        sc->sc_ttyp = tp;
        !           133:        sc->sc_if.if_unit = nsl;
        !           134:        sc->sc_if.if_name = "sl";
        !           135:        sc->sc_if.if_mtu = SLTU;
        !           136:        sc->sc_if.if_output = sloutput;
        !           137:        sc->sc_if.if_ioctl = slioctl;
        !           138:        sc->sc_if.if_flags = IFF_POINTOPOINT;
        !           139:        sc->sc_if.if_oerrors = sc->sc_if.if_ierrors = 0;
        !           140:        sc->sc_if.if_opackets = sc->sc_if.if_ipackets = 0;
        !           141:        sc->sc_if.if_snd.ifq_maxlen = ifqmaxlen;
        !           142:        if_attach(&sc->sc_if);
        !           143: 
        !           144:        if (addloop)
        !           145:                loattach();
        !           146: 
        !           147:        return 0;
        !           148: }
        !           149: 
        !           150: /*ARGSUSED*/
        !           151: sltioctl(tp, cmd, data, flag)
        !           152:        struct tty *tp;
        !           153:        caddr_t data;
        !           154: {
        !           155:        register struct sl_softc *sc = (struct sl_softc *)tp->t_slsoftc;
        !           156: 
        !           157:        /*
        !           158:         * This is done this way, because we want these attributes to
        !           159:         * be present AFTER the user program closes the line.
        !           160:         */
        !           161:        if (cmd == TIOCGETD) {
        !           162:                *(int *)data = (int)sc->sc_if.if_unit;
        !           163:                tp->t_state &= ~TS_HUPCLS;
        !           164:                tp->t_flags |= NOHANG;
        !           165:                sc->sc_ttyspeed = tp->t_ispeed;
        !           166:                return 0;
        !           167:        }
        !           168:        return EINVAL;
        !           169: }
        !           170: 
        !           171: sloutput(ifp, m, dst)
        !           172:        register struct ifnet *ifp;
        !           173:        register struct mbuf *m;
        !           174:        struct sockaddr *dst;
        !           175: {
        !           176:        int s;
        !           177: 
        !           178:        SL_TRACE(SLOUTPUT, printf("sl%lx: output\n",ifp->if_unit);)
        !           179:        if (dst->sa_family != AF_INET) {
        !           180:                printf("sl%d: af%d not supported\n", ifp->if_unit,
        !           181:                        dst->sa_family);
        !           182:                m_freem(m);
        !           183:                return (EAFNOSUPPORT);
        !           184:        }
        !           185:        s = splimp();
        !           186:        if (IF_QFULL(&ifp->if_snd)) {
        !           187:                IF_DROP(&ifp->if_snd);
        !           188:                m_freem(m);
        !           189:                splx(s);
        !           190:                sl_softc[ifp->if_unit].sc_if.if_collisions++;
        !           191:                return (ENOBUFS);
        !           192:        }
        !           193:        IF_ENQUEUE(&ifp->if_snd, m);
        !           194:        if (sl_softc[ifp->if_unit].sc_oactive == 0)
        !           195:                slstart(ifp->if_unit, s);       /* slstart does an splx(s) */
        !           196:        else
        !           197:                splx(s);
        !           198:        return (0);
        !           199: }
        !           200: 
        !           201: /*
        !           202:  * Start output on interface.  Get another datagram
        !           203:  * to send from the interface queue and map it to
        !           204:  * the interface before starting output.
        !           205:  */
        !           206: slstart(n, s)
        !           207:        int n, s;
        !           208: {
        !           209:        register struct sl_softc *sc = &sl_softc[n];
        !           210:        register struct tty *tp;
        !           211:        struct mbuf *m, *mp;
        !           212: 
        !           213:        tp = sc->sc_ttyp;
        !           214:        if (tp == NULL) {
        !           215:                printf("sl%d: sc_ttyp is NULL\n", n);
        !           216:                splx(s);
        !           217:                return;
        !           218:        }
        !           219: next:
        !           220:        sc->sc_oactive = 1;
        !           221:        IF_DEQUEUE(&sc->sc_if.if_snd, m);
        !           222:        if (m == 0) {
        !           223:                sc->sc_oactive = 0;
        !           224:                splx(s);
        !           225:                return;
        !           226:        }
        !           227:        splx(s);
        !           228: 
        !           229:        SL_TRACE(SLSTART,printf("slstart %lx\n", tp);)
        !           230:        for (mp = m; mp; mp = mp->m_next) {
        !           231:                register unsigned len = mp->m_len;
        !           232:                register u_char *mcp;
        !           233:                u_char c;
        !           234: 
        !           235:                mcp = mtod(mp, u_char *);
        !           236:                while (len--) {
        !           237:                        c = *mcp++;
        !           238:                        if (c == FRAME_ESCAPE || c == FRAME_END) {
        !           239:                                if (putc(FRAME_ESCAPE, &tp->t_outq))
        !           240:                                        goto full;
        !           241:                                c = c == FRAME_ESCAPE ?
        !           242:                                        TRANS_FRAME_ESCAPE : TRANS_FRAME_END;
        !           243:                        }
        !           244:                        if (putc(c, &tp->t_outq))
        !           245:                                goto full;
        !           246:                }
        !           247:        }
        !           248:        if (putc(FRAME_END, &tp->t_outq)) {
        !           249: full:
        !           250:                SL_TRACE(SLSTART,printf("slstart: line is full\n");)
        !           251:                /*
        !           252:                 * If you get many oerrors (more than 1 or two a day),
        !           253:                 * you probably do not have enough clists and you should 
        !           254:                 * increase the number of them.
        !           255:                 */
        !           256:                m_freem(m);
        !           257:                (void) unputc(&tp->t_outq);     /* make some space */
        !           258:                (void) unputc(&tp->t_outq);     /* make some space */
        !           259:                putc('\0', &tp->t_outq);        /* end the packet */
        !           260:                putc(FRAME_END, &tp->t_outq);   /* end the packet */
        !           261:                sc->sc_if.if_oerrors++;
        !           262:                sc->sc_oactive = 0;
        !           263:                ttstart(tp);
        !           264:                return EIO;
        !           265:        }
        !           266:        m_freem(m);
        !           267:        ttstart(tp);
        !           268:        sc->sc_if.if_opackets++;
        !           269: 
        !           270:        s = splimp();
        !           271:        sc->sc_oactive = 0;
        !           272:        splx(s);
        !           273: 
        !           274: /*     s = splimp();
        !           275: /*     goto next;
        !           276: /**/
        !           277: }
        !           278: 
        !           279: /*
        !           280:  * tty interface receiver interrupt.
        !           281:  */
        !           282: slinput(c, tp)
        !           283: register c;
        !           284: register struct tty *tp;
        !           285: {
        !           286:        register struct sl_softc *sc;
        !           287:        register struct mbuf *m;
        !           288:        register struct ifqueue *inq;
        !           289:        register int s;
        !           290: 
        !           291:        SL_TRACE(SLINPUT, printf("slinput %x,", c & 0xff);)
        !           292:        sc = (struct sl_softc *)tp->t_slsoftc;
        !           293:        if (sc == NULL) {
        !           294:                printf("sl: t_slsoftc is NULL,tty %lx\n",(long)tp);
        !           295:                return;
        !           296:        }
        !           297:        c &= 0xff;
        !           298:        if (sc->sc_escaped) {
        !           299:                sc->sc_escaped = 0;
        !           300:                switch(c) {
        !           301:                case TRANS_FRAME_ESCAPE:
        !           302:                        c = FRAME_ESCAPE;
        !           303:                        break;
        !           304:                case TRANS_FRAME_END:
        !           305:                        c = FRAME_END;
        !           306:                        break;
        !           307:                default:
        !           308:                        sc->sc_if.if_ierrors++;
        !           309:                        return;
        !           310:                }
        !           311:        } else {
        !           312:                switch(c) {
        !           313:                case FRAME_END:
        !           314:                        if (sc->sc_mt == 0) {
        !           315:                                sc->sc_if.if_ierrors++;
        !           316:                                return;
        !           317:                        }
        !           318:                        sc->sc_if.if_ipackets++;
        !           319:                        sc->sc_mt->m_len -= sc->sc_len;
        !           320:                        schednetisr(NETISR_IP);
        !           321:                        inq = &ipintrq;
        !           322: 
        !           323:                        s = splimp();
        !           324:                        if (IF_QFULL(inq)) {
        !           325:                                IF_DROP(inq);
        !           326:                                sc->sc_if.if_ierrors++;
        !           327:                                m_freem(sc->sc_m);
        !           328:                        } else
        !           329:                                IF_ENQUEUE(inq, sc->sc_m);
        !           330:                        splx(s);
        !           331:                        sc->sc_m = sc->sc_mt = 0;
        !           332:                        sc->sc_len = 0;
        !           333:                        return;
        !           334:                case FRAME_ESCAPE:
        !           335:                        sc->sc_escaped = 1;
        !           336:                        return;
        !           337:                }
        !           338:        }
        !           339:        if (sc->sc_len <= 0) {  /* have to get more buffer space */
        !           340:                struct mbuf *mm;
        !           341:                MGET(mm, M_DONTWAIT, MT_DATA);
        !           342:                MBUFNULL(34, mm);       /* for debugging */
        !           343:                if (mm == 0) {
        !           344:                        m_freem(sc->sc_m);
        !           345:                        sc->sc_m = sc->sc_mt = 0;
        !           346:                        sc->sc_len = 0;
        !           347:                        sc->sc_if.if_collisions++;
        !           348:                        return;
        !           349:                }
        !           350:                if (sc->sc_mt == 0) {
        !           351:                        sc->sc_mt = sc->sc_m = mm;
        !           352:                } else {
        !           353:                        sc->sc_mt->m_next = mm;
        !           354:                        sc->sc_mt = mm;
        !           355:                }
        !           356:                sc->sc_len = mm->m_len = MLEN;
        !           357:                sc->sc_mp = mtod(mm, u_char *);
        !           358:        }
        !           359: 
        !           360:        *sc->sc_mp++ = c;
        !           361:        sc->sc_len--;
        !           362: }
        !           363: 
        !           364: /*
        !           365:  * Process an ioctl request.
        !           366:  */
        !           367: slioctl(ifp, cmd, data)
        !           368:        register struct ifnet *ifp;
        !           369:        int cmd;
        !           370:        caddr_t data;
        !           371: {
        !           372:        struct tty *tp;
        !           373:        struct sockaddr_in *sin;
        !           374:        struct sl_softc *sc;
        !           375:        struct rtentry route;
        !           376:        int s = splimp(), error = 0;
        !           377:        register struct ifreq *ifr = (struct ifreq *)data;
        !           378: 
        !           379: 
        !           380: 
        !           381:        switch (cmd) {
        !           382: 
        !           383:        case SIOCSIFADDR:
        !           384:                if (ifp->if_flags & IFF_RUNNING)
        !           385:                        if_rtinit(ifp, -1);     /* delete previous route */
        !           386:                sin = (struct sockaddr_in *)&ifr->ifr_addr;
        !           387:                ifp->if_addr = *(struct sockaddr *)sin;
        !           388:                sin = (struct sockaddr_in *)&ifp->if_dstaddr;
        !           389:                ifp->if_net = in_netof(sin->sin_addr);
        !           390:                ifp->if_flags |= IFF_UP | IFF_RUNNING;
        !           391:                /* set up routing table entry */
        !           392:                if ((ifp->if_flags & IFF_ROUTE) == 0) {
        !           393:                        rtinit(&ifp->if_dstaddr, &ifp->if_addr, RTF_HOST|RTF_UP);
        !           394:                        ifp->if_flags |= IFF_ROUTE;
        !           395:                }
        !           396:                /*
        !           397:                 * Since the way a tty line is attached as a network interface
        !           398:                 * is to open it, do an "ioctl" to attach it, and close it,
        !           399:                 * and since the close will reset the line discipline, we
        !           400:                 * must set the line discipline here.
        !           401:                 */
        !           402:                sc = &sl_softc[ifp->if_unit];
        !           403:                tp = sc->sc_ttyp;
        !           404:                tp->t_line = SLIPDISC;
        !           405:                tp->t_flags = RAW|EVENP|ODDP;
        !           406:                tp->t_ispeed = tp->t_ospeed = sc->sc_ttyspeed;
        !           407: 
        !           408:                /* Unfortunately, the tty driver does not have any
        !           409:                 * way of jumping directly to the correct param routine
        !           410:                 * so, to get the line set to the correct baudrate
        !           411:                 * we are forced to use the following kludge
        !           412:                 * (Fortunately, it is only called once per line)
        !           413:                 * THIS CAN BE FIXED WITH THE SYSTEM V RELEASE 2
        !           414:                 * TTY DRIVER, WHICH DOES HAVE A t_proc ARGUMENT FOR
        !           415:                 * DO A "param".
        !           416:                 */
        !           417: #if NVX > 0
        !           418:                if (tp->t_oproc == vxstart)
        !           419:                        vxparam(tp->t_dev);
        !           420:                else
        !           421: #endif NVX
        !           422:                {
        !           423:                        printf("Serial line attach: Unknown device\n");
        !           424:                        error = ENODEV;
        !           425:                }
        !           426:                break;
        !           427: 
        !           428:        case SIOCSIFDSTADDR:
        !           429:                sin = (struct sockaddr_in *)&ifr->ifr_dstaddr;
        !           430:                ifp->if_dstaddr = *(struct sockaddr *)sin;
        !           431:                break;
        !           432: 
        !           433:        case SIOCIFDETACH:
        !           434:                bzero((caddr_t)&route, sizeof (route));
        !           435:                route.rt_dst = ifp->if_dstaddr;
        !           436:                route.rt_gateway = ifp->if_addr;
        !           437:                route.rt_flags = RTF_HOST | RTF_UP;
        !           438:                (void) rtrequest(SIOCDELRT, &route);
        !           439:                if_detach(ifp);
        !           440:                sc = &sl_softc[ifp->if_unit];
        !           441:                tp = sc->sc_ttyp;
        !           442:                tp->t_slsoftc = 0;
        !           443:                sc->sc_ttyp = 0;
        !           444:                ttyclose(tp);
        !           445:                break;
        !           446: 
        !           447:        default:
        !           448:                error = EINVAL;
        !           449:        }
        !           450:        splx(s);
        !           451:        return (error);
        !           452: }
        !           453: #endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.