|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.