# 2.11BSD#431 - /usr/src/sys/net/if_sl.c

##### Functions

    sl_btom           X
    slattach          X
    slclose           X
    slinit            X
    slinput           X
    slioctl           X
    slopen            X
    sloutput          X
    slstart           X
    sltioctl          X

##### Variables

    sl_softc          X

##### Macros

    CLISTRESERVE      X
    FRAME_END         X
    FRAME_ESCAPE      X
    SC_ESCAPED        X
    SLIP_HIWAT        X
    SLMTU             X
    TRANS_FRAME_END   X
    TRANS_FRAME_ESCAPEX
    t_sc              X

##### struct's

    sl_softc          X

       1: /*
       2:  * Copyright (c) 1987 Regents of the University of California.
       3:  * All rights reserved.
       4:  *
       5:  * Redistribution and use in source and binary forms are permitted
       6:  * provided that this notice is preserved and that due credit is given
       7:  * to the University of California at Berkeley. The name of the University
       8:  * may not be used to endorse or promote products derived from this
       9:  * software without specific prior written permission. This software
      10:  * is provided ``as is'' without express or implied warranty.
      11:  *
      12:  *	@(#)if_sl.c	7.6.1.1 (Berkeley) 3/15/88
      13:  */
      14:
      15: /*
      16:  * Serial Line interface
      17:  *
      18:  * Rick Adams
      19:  * Center for Seismic Studies
      20:  * 1300 N 17th Street, Suite 1450
      21:  * Arlington, Virginia 22209
      22:  * (703)276-7900
      23:  * rick@seismo.ARPA
      24:  * seismo!rick
      25:  *
      26:  * Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris).
      27:  * N.B.: this belongs in netinet, not net, the way it stands now.
      28:  * Should have a link-layer type designation, but wouldn't be
      29:  * backwards-compatible.
      30:  *
      31:  * Converted to 4.3BSD Beta by Chris Torek.
      32:  * Other changes made at Berkeley, based in part on code by Kirk Smith.
      33:  */
      34:
      35: /* $Header: /usr/src/sys/net/RCS/if_sl.c,v 1.1 88/08/18 00:28:00 bin Exp Locker: bin $ */
      36: /* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
      37:
      38: #include "sl.h"
      39: #if NSL > 0
      40:
      41: #include "param.h"
      42: #include "mbuf.h"
      43: #include "buf.h"
      44: #include "dk.h"
      45: #include "domain.h"
      46: #include "protosw.h"
      47: #include "socket.h"
      48: #include "ioctl.h"
      49: #include "file.h"
      50: #include "tty.h"
      51: #include "errno.h"
      52:
      53: #include "if.h"
      54: #include "netisr.h"
      55: #include "route.h"
      56: #if INET
      57: #include "../netinet/in.h"
      58: #include "../netinet/in_systm.h"
      59: #include "../netinet/in_var.h"
      60: #include "../netinet/ip.h"
      61: #endif
      62:
      63: /*
      64:  * N.B.: SLMTU is now a hard limit on input packet size.
      65:  * SLMTU must be <= CLBYTES - sizeof(struct ifnet *).
      66:  */
      67: #define SLMTU   1006
      68: #define SLIP_HIWAT  500 /* don't start a new packet if HIWAT on queue */
      69: #define CLISTRESERVE    200 /* Can't let clists get too low */
      70:
      71: struct sl_softc {
      72:     struct  ifnet sc_if;    /* network-visible interface */
      73:     short   sc_flags;   /* see below */
      74:     short   sc_ilen;    /* length of input-packet-so-far */
      75:     struct  tty *sc_ttyp;   /* pointer to tty structure */
      76:     char    *sc_mp;     /* pointer to next available buf char */
      77:     char    *sc_buf;    /* input buffer */
      78: } sl_softc[NSL];
      79:
      80: /* flags */
      81: #define SC_ESCAPED  0x0001  /* saw a FRAME_ESCAPE */
      82:
      83: #define FRAME_END       0300        /* Frame End */
      84: #define FRAME_ESCAPE        0333        /* Frame Esc */
      85: #define TRANS_FRAME_END     0334        /* transposed frame end */
      86: #define TRANS_FRAME_ESCAPE  0335        /* transposed frame esc */
      87:
      88: #define t_sc T_LINEP
      89:
      90: int sloutput(), slioctl(), slopen(), sltioctl();
      91:
      92: /*
      93:  * Called from boot code to establish sl interfaces.
      94:  */
      95: slattach()
      96: {
      97:     register struct sl_softc *sc;
      98:     register int i = 0;
      99:
     100:     for (sc = sl_softc; i < NSL; sc++) {
     101:         sc->sc_if.if_name = "sl";
     102:         sc->sc_if.if_unit = i++;
     103:         sc->sc_if.if_mtu = SLMTU;
     104:         sc->sc_if.if_flags = IFF_POINTOPOINT;
     105:         sc->sc_if.if_ioctl = slioctl;
     106:         sc->sc_if.if_output = sloutput;
     107:         sc->sc_if.if_snd.ifq_maxlen = IFQ_MAXLEN;
     108:         if_attach(&sc->sc_if);
     109:     }
     110: }
     111:
     112: /*
     113:  * Line specific open routine.
     114:  * Attach the given tty to the first available sl unit.
     115:  */
     116: /* ARGSUSED */
     117: slopen(dev, tp)
     118:     dev_t dev;
     119:     register struct tty *tp;
     120: {
     121:     struct sl_softc *sc;
     122:     register int nsl;
     123:
     124: #ifdef DONE_IN_KERNEL_STUB
     125:     if (!suser())
     126:         return (EPERM);
     127:     if (tp->t_line == SLIPDISC)
     128:         return (EBUSY);
     129: #endif
     130:
     131:     for (nsl = 0, sc = sl_softc; nsl < NSL; nsl++, sc++)
     132:         if (sc->sc_ttyp == NULL) {
     133:             sc->sc_flags = 0;
     134:             sc->sc_ilen = 0;
     135:             if (slinit(sc) == 0)
     136:                 return (ENOBUFS);
     137:             mtkd(&tp->t_sc, sc);
     138:             sc->sc_ttyp = tp;
     139: #ifdef DONE_IN_KERNEL_STUB
     140:             ttyflush(tp, FREAD | FWRITE);
     141: #endif
     142:             return (0);
     143:         }
     144:
     145:     return (ENXIO);
     146: }
     147:
     148: /*
     149:  * Line specific close routine.
     150:  * Detach the tty from the sl unit.
     151:  * Mimics part of ttyclose().
     152:  */
     153: slclose(tp)
     154:     struct tty *tp;
     155: {
     156:     register struct sl_softc *sc;
     157:     int s;
     158:
     159: #ifdef DONE_IN_KERNEL_STUB
     160:     ttywflush(tp);
     161:     tp->t_line = 0;
     162: #endif
     163:     s = splimp();       /* paranoid; splnet probably ok */
     164:     sc = (struct sl_softc *)mfkd(&tp->t_sc);
     165:     if (sc != NULL) {
     166:         if_down(&sc->sc_if);
     167:         sc->sc_ttyp = NULL;
     168:         mtkd(&tp->t_sc, 0);
     169:         MCLFREE((struct mbuf *)sc->sc_buf);
     170:         sc->sc_buf = 0;
     171:     }
     172:     splx(s);
     173: }
     174:
     175: /*
     176:  * Line specific (tty) ioctl routine.
     177:  * Provide a way to get the sl unit number.
     178:  */
     179: /* ARGSUSED */
     180: sltioctl(tp, cmd, data, flag)
     181:     struct tty *tp;
     182:     caddr_t data;
     183: {
     184:
     185:     if (cmd == TIOCGETD) {
     186:         mtkd(data,
     187:             ((struct sl_softc *)mfkd(&tp->t_sc))->sc_if.if_unit);
     188:         return (0);
     189:     }
     190:     return (-1);
     191: }
     192:
     193: /*
     194:  * Queue a packet.  Start transmission if not active.
     195:  */
     196: sloutput(ifp, m, dst)
     197:     register struct ifnet *ifp;
     198:     register struct mbuf *m;
     199:     struct sockaddr *dst;
     200: {
     201:     register struct sl_softc *sc;
     202:     long lval;
     203:     int s;
     204:
     205:     /*
     206: 	 * `Cannot happen' (see slioctl).  Someday we will extend
     207: 	 * the line protocol to support other address families.
     208: 	 */
     209:     if (dst->sa_family != AF_INET) {
     210:         printf("sl%d: af%d not supported\n", ifp->if_unit,
     211:             dst->sa_family);
     212:         m_freem(m);
     213:         return (EAFNOSUPPORT);
     214:     }
     215:
     216:     sc = &sl_softc[ifp->if_unit];
     217:     if (sc->sc_ttyp == NULL) {
     218:         m_freem(m);
     219:         return (ENETDOWN);  /* sort of */
     220:     }
     221:     cpfromkern(&sc->sc_ttyp->t_state, &lval, 4);
     222:     if ((lval & TS_CARR_ON) == 0) {
     223:         m_freem(m);
     224:         return (EHOSTUNREACH);
     225:     }
     226:     s = splimp();
     227:     if (IF_QFULL(&ifp->if_snd)) {
     228:         IF_DROP(&ifp->if_snd);
     229:         splx(s);
     230:         m_freem(m);
     231:         sc->sc_if.if_oerrors++;
     232:         return (ENOBUFS);
     233:     }
     234:     IF_ENQUEUE(&ifp->if_snd, m);
     235:     if (mfkd(&sc->sc_ttyp->t_outq.c_cc) == 0) {
     236:         splx(s);
     237:         slstart(sc->sc_ttyp);
     238:     } else
     239:         splx(s);
     240:     return (0);
     241: }
     242:
     243: /*
     244:  * Start output on interface.  Get another datagram
     245:  * to send from the interface queue and map it to
     246:  * the interface before starting output.
     247:  */
     248: slstart(tp)
     249:     register struct tty *tp;
     250: {
     251:     register struct sl_softc *sc;
     252:     register struct mbuf *m;
     253:     register int len;
     254:     register u_char *cp;
     255:     int nd, np, n, s, t, c_cc;
     256:     char sup_clist[MLEN];
     257:     struct mbuf *m2;
     258:     extern int cfreecount;
     259:
     260:     sc = (struct sl_softc *)mfkd(&tp->t_sc);
     261:     for (;;) {
     262:         /*
     263: 		 * If there is more in the output queue, just send it now.
     264: 		 * We are being called in lieu of ttstart and must do what
     265: 		 * it would.
     266: 		 */
     267:         if ((c_cc = mfkd(&tp->t_outq.c_cc)) > 0)
     268:             TTSTART(tp);
     269:         if (c_cc > SLIP_HIWAT)
     270:             return;
     271:
     272:         /*
     273: 		 * This happens briefly when the line shuts down.
     274: 		 */
     275:         if (sc == NULL)
     276:             return;
     277:
     278:         /*
     279: 		 * If system is getting low on clists
     280: 		 * and we have something running already, stop here.
     281: 		 */
     282:         if (mfkd(&cfreecount) < CLISTRESERVE + SLMTU && c_cc)
     283:             return;
     284:
     285:         /*
     286: 		 * Get a packet and send it to the interface.
     287: 		 */
     288:         s = splimp();
     289:         IF_DEQUEUE(&sc->sc_if.if_snd, m);
     290:         splx(s);
     291:         if (m == NULL)
     292:             return;
     293:
     294:         /*
     295: 		 * The extra FRAME_END will start up a new packet, and thus
     296: 		 * will flush any accumulated garbage.  We do this whenever
     297: 		 * the line may have been idle for some time.
     298: 		 */
     299:         if (c_cc == 0)
     300:             (void) PUTC(FRAME_END, &tp->t_outq);
     301:
     302:         while (m) {
     303:             cp = mtod(m, u_char *);
     304:             len = m->m_len;
     305:             while (len > 0) {
     306:                 /*
     307: 				 * Find out how many bytes in the string we can
     308: 				 * handle without doing something special.
     309: 				 */
     310:                 nd = locc(FRAME_ESCAPE, len, cp);
     311:                 np = locc(FRAME_END, len, cp);
     312:                 n = len - MAX(nd, np);
     313:                 /*
     314: 				 * Put n characters into the tty output
     315: 				 * queue.  We do it in chunks of MLEN, using
     316: 				 * the supervisor stack to copy into kernel
     317: 				 * space.
     318: 				 */
     319:                 while (n) {
     320:                     t = n > MLEN ? MLEN : n;
     321:                     bcopy((char *)cp, sup_clist, t);
     322:                     if (B_TO_Q(sup_clist, t, &tp->t_outq))
     323:                         break;
     324:                     len -= t;
     325:                     cp += t;
     326:                     n -= t;
     327:                 }
     328:                 if (n)
     329:                     break;
     330:                 /*
     331: 				 * If there are characters left in the mbuf,
     332: 				 * the first one must be special..
     333: 				 * Put it out in a different form.
     334: 				 */
     335:                 if (len) {
     336:                     if (PUTC(FRAME_ESCAPE, &tp->t_outq))
     337:                         break;
     338:                     if (PUTC(*cp == FRAME_ESCAPE ?
     339:                        TRANS_FRAME_ESCAPE : TRANS_FRAME_END,
     340:                        &tp->t_outq)) {
     341:                         (void) UNPUTC(&tp->t_outq);
     342:                         break;
     343:                     }
     344:                     cp++;
     345:                     len--;
     346:                 }
     347:             }
     348:             MFREE(m, m2);
     349:             m = m2;
     350:         }
     351:
     352:         if (PUTC(FRAME_END, &tp->t_outq)) {
     353:             /*
     354: 			 * Not enough room.  Remove a char to make room
     355: 			 * and end the packet normally.
     356: 			 * If you get many collisions (more than one or two
     357: 			 * a day) you probably do not have enough clists
     358: 			 * and you should increase "nclist" in param.c.
     359: 			 */
     360:             (void) UNPUTC(&tp->t_outq);
     361:             (void) PUTC(FRAME_END, &tp->t_outq);
     362:             sc->sc_if.if_collisions++;
     363:         } else
     364:             sc->sc_if.if_opackets++;
     365:     }
     366: }
     367:
     368: slinit(sc)
     369:     register struct sl_softc *sc;
     370: {
     371:     struct mbuf *p;
     372:
     373:     if (sc->sc_buf == (char *) 0) {
     374:         MCLALLOC(p, 1);
     375:         if (p) {
     376:             sc->sc_buf = (char *)p;
     377:             sc->sc_mp = sc->sc_buf + sizeof(struct ifnet *);
     378:         } else {
     379:             printf("sl%d: can't allocate buffer\n", sc - sl_softc);
     380:             sc->sc_if.if_flags &= ~IFF_UP;
     381:             return (0);
     382:         }
     383:     }
     384:     return (1);
     385: }
     386:
     387: /*
     388:  * Copy data buffer to mbuf chain; add ifnet pointer ifp.
     389:  */
     390: struct mbuf *
     391: sl_btom(sc, len, ifp)
     392:     struct sl_softc *sc;
     393:     register int len;
     394:     struct ifnet *ifp;
     395: {
     396:     register caddr_t cp;
     397:     register struct mbuf *m, **mp;
     398:     register unsigned count;
     399:     struct mbuf *top = NULL;
     400:
     401:     cp = sc->sc_buf + sizeof(struct ifnet *);
     402:     mp = &top;
     403:     while (len > 0) {
     404:         MGET(m, M_DONTWAIT, MT_DATA);
     405:         if ((*mp = m) == NULL) {
     406:             m_freem(top);
     407:             return (NULL);
     408:         }
     409:         if (ifp)
     410:             m->m_off += sizeof(ifp);
     411:         /*
     412: 		 * If we have at least NBPG bytes,
     413: 		 * allocate a new page.  Swap the current buffer page
     414: 		 * with the new one.  We depend on having a space
     415: 		 * left at the beginning of the buffer
     416: 		 * for the interface pointer.
     417: 		 */
     418:         if (len >= NBPG) {
     419:             MCLGET(m);
     420:             if (m->m_len == CLBYTES) {
     421:                 cp = mtod(m, char *);
     422:                 m->m_off = (int)sc->sc_buf - (int)m;
     423:                 sc->sc_buf = cp;
     424:                 if (ifp) {
     425:                     m->m_off += sizeof(ifp);
     426:                     count = MIN(len,
     427:                         CLBYTES - sizeof(struct ifnet *));
     428:                 } else
     429:                     count = MIN(len, CLBYTES);
     430:                 goto nocopy;
     431:             }
     432:         }
     433:         if (ifp)
     434:             count = MIN(len, MLEN - sizeof(ifp));
     435:         else
     436:             count = MIN(len, MLEN);
     437:         bcopy(cp, mtod(m, caddr_t), count);
     438: nocopy:
     439:         m->m_len = count;
     440:         if (ifp) {
     441:             m->m_off -= sizeof(ifp);
     442:             m->m_len += sizeof(ifp);
     443:             *mtod(m, struct ifnet **) = ifp;
     444:             ifp = NULL;
     445:         }
     446:         cp += count;
     447:         len -= count;
     448:         mp = &m->m_next;
     449:     }
     450:     return (top);
     451: }
     452:
     453: /*
     454:  * tty interface receiver interrupt.
     455:  */
     456: slinput(c, tp)
     457:     register int c;
     458:     register struct tty *tp;
     459: {
     460:     register struct sl_softc *sc;
     461:     register struct mbuf *m;
     462:     int s;
     463:
     464: #ifdef notdef
     465:     tk_nin++;
     466: #endif
     467:     sc = (struct sl_softc *)mfkd(&tp->t_sc);
     468:     if (sc == NULL)
     469:         return;
     470:
     471:     c &= 0xff;
     472:     if (sc->sc_flags & SC_ESCAPED) {
     473:         sc->sc_flags &= ~SC_ESCAPED;
     474:         switch (c) {
     475:
     476:         case TRANS_FRAME_ESCAPE:
     477:             c = FRAME_ESCAPE;
     478:             break;
     479:
     480:         case TRANS_FRAME_END:
     481:             c = FRAME_END;
     482:             break;
     483:
     484:         default:
     485:             sc->sc_if.if_ierrors++;
     486:             sc->sc_mp = sc->sc_buf + sizeof(struct ifnet *);
     487:             sc->sc_ilen = 0;
     488:             return;
     489:         }
     490:     } else {
     491:         switch (c) {
     492:
     493:         case FRAME_END:
     494:             if (sc->sc_ilen == 0)   /* ignore */
     495:                 return;
     496:             m = sl_btom(sc, sc->sc_ilen, &sc->sc_if);
     497:             if (m == NULL) {
     498:                 sc->sc_if.if_ierrors++;
     499:                 return;
     500:             }
     501:             sc->sc_mp = sc->sc_buf + sizeof(struct ifnet *);
     502:             sc->sc_ilen = 0;
     503:             sc->sc_if.if_ipackets++;
     504:             s = splimp();
     505:             if (IF_QFULL(&ipintrq)) {
     506:                 IF_DROP(&ipintrq);
     507:                 sc->sc_if.if_ierrors++;
     508:                 m_freem(m);
     509:             } else {
     510:                 IF_ENQUEUE(&ipintrq, m);
     511:                 schednetisr(NETISR_IP);
     512:             }
     513:             splx(s);
     514:             return;
     515:
     516:         case FRAME_ESCAPE:
     517:             sc->sc_flags |= SC_ESCAPED;
     518:             return;
     519:         }
     520:     }
     521:     if (++sc->sc_ilen > SLMTU) {
     522:         sc->sc_if.if_ierrors++;
     523:         sc->sc_mp = sc->sc_buf + sizeof(struct ifnet *);
     524:         sc->sc_ilen = 0;
     525:         return;
     526:     }
     527:     *sc->sc_mp++ = c;
     528: }
     529:
     530: /*
     531:  * Process an ioctl request.
     532:  */
     533: slioctl(ifp, cmd, data)
     534:     register struct ifnet *ifp;
     535:     int cmd;
     536:     caddr_t data;
     537: {
     538:     register struct ifaddr *ifa = (struct ifaddr *)data;
     539:     int s = splimp(), error = 0;
     540:
     541:     switch (cmd) {
     542:
     543:     case SIOCSIFADDR:
     544:         if (ifa->ifa_addr.sa_family == AF_INET)
     545:             ifp->if_flags |= IFF_UP;
     546:         else
     547:             error = EAFNOSUPPORT;
     548:         break;
     549:
     550:     case SIOCSIFDSTADDR:
     551:         if (ifa->ifa_addr.sa_family != AF_INET)
     552:             error = EAFNOSUPPORT;
     553:         break;
     554:
     555:     default:
     556:         error = EINVAL;
     557:     }
     558:     splx(s);
     559:     return (error);
     560: }
     561: #endif

#### Defined functions

sl_btom defined in line 390; used 1 times

- in line 496

slattach defined in line 95; never used
slclose defined in line 153; never used
slinit defined in line 368; used 1 times

- in line 135

slinput defined in line 456; never used
slioctl defined in line 533; used 2 times

- in line 90, 105

slopen defined in line 117; used 1 times

- in line 90

sloutput defined in line 196; used 2 times

- in line 90, 106

slstart defined in line 248; used 1 times

- in line 237

sltioctl defined in line 180; used 1 times

- in line 90

#### Defined variables

sl_softc defined in line 78; used 4 times

- in line 100, 131, 216, 379

#### Defined struct's

sl_softc defined in line 71; used 24 times

- in line 97(2), 121(2), 156(2), 164(2), 187(2), 201(2), 251(2), 260(2), 369(2), 392(2), 460(2), 467(2)

#### Defined macros

CLISTRESERVE defined in line 69; used 1 times

- in line 282

FRAME_END defined in line 83; used 5 times

- in line 300, 311, 352, 361, 481

FRAME_ESCAPE defined in line 84; used 4 times

- in line 310, 336-338(2), 477

SC_ESCAPED defined in line 81; used 3 times

- in line 472-473(2), 517

SLIP_HIWAT defined in line 68; used 1 times

- in line 269

SLMTU defined in line 67; used 3 times

- in line 103, 282, 521

TRANS_FRAME_END defined in line 85; used 1 times

- in line 339

TRANS_FRAME_ESCAPE defined in line 86; used 1 times

- in line 339

t_sc defined in line 88; used 6 times

- in line 137, 164-168(2), 187, 260, 467

Last modified: 1988-09-27 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 2006 |