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

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: 
1.1.1.2 ! root       48: #define        SLINES  (NSL*16)
1.1       root       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) {
1.1.1.2 ! root      393:                        rtinit(&ifp->if_dstaddr, &ifp->if_addr,
        !           394:                                ifp, RTF_HOST|RTF_UP);
1.1       root      395:                        ifp->if_flags |= IFF_ROUTE;
                    396:                }
                    397:                /*
                    398:                 * Since the way a tty line is attached as a network interface
                    399:                 * is to open it, do an "ioctl" to attach it, and close it,
                    400:                 * and since the close will reset the line discipline, we
                    401:                 * must set the line discipline here.
                    402:                 */
                    403:                sc = &sl_softc[ifp->if_unit];
                    404:                tp = sc->sc_ttyp;
                    405:                tp->t_line = SLIPDISC;
                    406:                tp->t_flags = RAW|EVENP|ODDP;
                    407:                tp->t_ispeed = tp->t_ospeed = sc->sc_ttyspeed;
                    408: 
                    409:                /* Unfortunately, the tty driver does not have any
                    410:                 * way of jumping directly to the correct param routine
                    411:                 * so, to get the line set to the correct baudrate
                    412:                 * we are forced to use the following kludge
                    413:                 * (Fortunately, it is only called once per line)
                    414:                 * THIS CAN BE FIXED WITH THE SYSTEM V RELEASE 2
                    415:                 * TTY DRIVER, WHICH DOES HAVE A t_proc ARGUMENT FOR
                    416:                 * DO A "param".
                    417:                 */
                    418: #if NVX > 0
                    419:                if (tp->t_oproc == vxstart)
                    420:                        vxparam(tp->t_dev);
                    421:                else
                    422: #endif NVX
                    423:                {
                    424:                        printf("Serial line attach: Unknown device\n");
                    425:                        error = ENODEV;
                    426:                }
                    427:                break;
                    428: 
                    429:        case SIOCSIFDSTADDR:
                    430:                sin = (struct sockaddr_in *)&ifr->ifr_dstaddr;
                    431:                ifp->if_dstaddr = *(struct sockaddr *)sin;
                    432:                break;
                    433: 
                    434:        case SIOCIFDETACH:
                    435:                bzero((caddr_t)&route, sizeof (route));
                    436:                route.rt_dst = ifp->if_dstaddr;
                    437:                route.rt_gateway = ifp->if_addr;
                    438:                route.rt_flags = RTF_HOST | RTF_UP;
                    439:                (void) rtrequest(SIOCDELRT, &route);
                    440:                if_detach(ifp);
                    441:                sc = &sl_softc[ifp->if_unit];
                    442:                tp = sc->sc_ttyp;
                    443:                tp->t_slsoftc = 0;
                    444:                sc->sc_ttyp = 0;
                    445:                ttyclose(tp);
                    446:                break;
                    447: 
                    448:        default:
                    449:                error = EINVAL;
                    450:        }
                    451:        splx(s);
                    452:        return (error);
                    453: }
                    454: #endif

unix.superglobalmegacorp.com

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