|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1990 Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms, with or without ! 6: * modification, are permitted provided that the following conditions ! 7: * are met: ! 8: * 1. Redistributions of source code must retain the above copyright ! 9: * notice, this list of conditions and the following disclaimer. ! 10: * 2. Redistributions in binary form must reproduce the above copyright ! 11: * notice, this list of conditions and the following disclaimer in the ! 12: * documentation and/or other materials provided with the distribution. ! 13: * 3. All advertising materials mentioning features or use of this software ! 14: * must display the following acknowledgement: ! 15: * This product includes software developed by the University of ! 16: * California, Berkeley and its contributors. ! 17: * 4. Neither the name of the University nor the names of its contributors ! 18: * may be used to endorse or promote products derived from this software ! 19: * without specific prior written permission. ! 20: * ! 21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 31: * SUCH DAMAGE. ! 32: * ! 33: * @(#)if_dp.c 7.9 (Berkeley) 6/27/91 ! 34: */ ! 35: ! 36: #include "dp.h" ! 37: #if NDP > 0 ! 38: ! 39: /* ! 40: * DPV-11 device driver, X.25 version ! 41: * ! 42: * Derived from dmc-11 driver: ! 43: * ! 44: * Bill Nesheim ! 45: * Cornell University ! 46: * ! 47: * Lou Salkind ! 48: * New York University ! 49: */ ! 50: ! 51: /* #define DEBUG /* for base table dump on fatal error */ ! 52: ! 53: #include "../include/pte.h" ! 54: ! 55: #include "sys/param.h" ! 56: #include "sys/systm.h" ! 57: #include "sys/mbuf.h" ! 58: #include "sys/buf.h" ! 59: #include "sys/ioctl.h" /* must precede tty.h */ ! 60: #include "sys/protosw.h" ! 61: #include "sys/socket.h" ! 62: #include "sys/socketvar.h" ! 63: #include "sys/syslog.h" ! 64: #include "sys/vmmac.h" ! 65: #include "sys/errno.h" ! 66: #include "sys/time.h" ! 67: #include "sys/kernel.h" ! 68: ! 69: #include "net/if.h" ! 70: #include "net/if_types.h" ! 71: #include "net/netisr.h" ! 72: #include "net/route.h" ! 73: ! 74: #include "../include/cpu.h" ! 75: #include "../include/mtpr.h" ! 76: ! 77: #define dzdevice dpdevice ! 78: #include "../uba/pdma.h" ! 79: #include "../uba/ubavar.h" ! 80: ! 81: #include "netccitt/x25.h" ! 82: #include "netccitt/pk.h" ! 83: #include "netccitt/pk_var.h" ! 84: ! 85: #include "if_dpreg.h" ! 86: ! 87: /* ! 88: * Driver information for auto-configuration stuff. ! 89: */ ! 90: int dpprobe(), dpattach(), dpinit(), dpioctl(), dprint(), dpxint(); ! 91: int dpoutput(), dpreset(), dptimeout(), dpstart(), dptestoutput(); ! 92: int x25_ifoutput(), x25_rtrequest(); ! 93: ! 94: struct uba_device *dpinfo[NDP]; ! 95: ! 96: u_short dpstd[] = { 0 }; ! 97: struct uba_driver dpdriver = ! 98: { dpprobe, 0, dpattach, 0, dpstd, "dp", dpinfo }; ! 99: ! 100: /* ! 101: * Pdma structures for fast interrupts. ! 102: */ ! 103: struct pdma dppdma[2*NDP]; ! 104: ! 105: /* ! 106: * DP software status per interface. ! 107: * ! 108: * Each interface is referenced by a network interface structure, ! 109: * dp_if, which the routing code uses to locate the interface. ! 110: * This structure contains the output queue for the interface, its address, ... ! 111: */ ! 112: struct dp_softc { ! 113: struct ifnet dp_if; /* network-visible interface */ ! 114: int dp_ipl; ! 115: struct dpdevice *dp_addr; /* dpcsr address */ ! 116: short dp_iused; /* input buffers given to DP */ ! 117: short dp_flags; /* flags */ ! 118: #define DPF_RUNNING 0x01 /* device initialized */ ! 119: #define DPF_ONLINE 0x02 /* device running (had a RDYO) */ ! 120: #define DPF_RESTART 0x04 /* software restart in progress */ ! 121: #define DPF_FLUSH 0x08 /* had a ROVR, flush ipkt when done */ ! 122: #define DPF_X25UP 0x10 /* XXX -- someday we'll do PPP also */ ! 123: short dp_ostate; /* restarting, etc. */ ! 124: short dp_istate; /* not sure this is necessary */ ! 125: #define DPS_IDLE 0 ! 126: #define DPS_RESTART 1 ! 127: #define DPS_ACTIVE 2 ! 128: #define DPS_XEM 3 /* transmitting CRC, etc. */ ! 129: short dp_olen; /* length of last packet sent */ ! 130: short dp_ilen; /* length of last packet recvd */ ! 131: char dp_obuf[DP_MTU+8]; ! 132: char dp_ibuf[DP_MTU+8]; ! 133: } dp_softc[NDP]; ! 134: ! 135: /* ! 136: * Debug info ! 137: */ ! 138: struct dpstat { ! 139: long start; ! 140: long nohdr; ! 141: long init; ! 142: long rint; ! 143: long xint; ! 144: long reset; ! 145: long ioctl; ! 146: long down; ! 147: long mchange; ! 148: long timeout; ! 149: long rsm; ! 150: long rem; ! 151: long remchr; ! 152: long rga; ! 153: long xem; ! 154: long rovr; ! 155: } dpstat; ! 156: ! 157: short dp_ilb = 0; ! 158: short dp_log = 0; ! 159: ! 160: #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m)) ! 161: int dp_sizes[] = { ! 162: sizeof(dp_softc[0]), sizeof(struct ifnet), ! 163: _offsetof(struct dp_softc, dp_obuf[0]), ! 164: _offsetof(struct dp_softc, dp_ibuf[0]), ! 165: }; ! 166: ! 167: dpprobe(reg, ui) ! 168: caddr_t reg; ! 169: struct uba_device *ui; ! 170: { ! 171: register int br, cvec; ! 172: register struct dpdevice *addr = (struct dpdevice *)reg; ! 173: register int unit = ui->ui_unit; ! 174: ! 175: #ifdef lint ! 176: br = 0; cvec = br; br = cvec; ! 177: dprint(0); dpxint(0); ! 178: #endif ! 179: (void) spl6(); ! 180: addr->dpclr = DP_CLR; ! 181: addr->dpclr = DP_XIE|DP_XE; ! 182: DELAY(100000); ! 183: dp_softc[unit].dp_ipl = br = qbgetpri(); ! 184: dp_softc[unit].dp_addr = addr; ! 185: addr->dpclr = 0; ! 186: if (cvec && cvec != 0x200){ ! 187: cvec -= 4; ! 188: } ! 189: return (1); ! 190: } ! 191: ! 192: /* ! 193: * Interface exists: make available by filling in network interface ! 194: * record. System will initialize the interface when it is ready ! 195: * to accept packets. ! 196: */ ! 197: dpattach(ui) ! 198: register struct uba_device *ui; ! 199: { ! 200: register struct dp_softc *dp = &dp_softc[ui->ui_unit]; ! 201: ! 202: dp->dp_if.if_unit = ui->ui_unit; ! 203: dp->dp_if.if_name = "dp"; ! 204: dp->dp_if.if_mtu = DP_MTU; ! 205: dp->dp_if.if_init = dpinit; ! 206: dp->dp_if.if_output = x25_ifoutput; ! 207: dp->dp_if.if_type = IFT_X25; ! 208: dp->dp_if.if_hdrlen = 5; ! 209: dp->dp_if.if_addrlen = 8; ! 210: dp->dp_if.if_start = dpstart; ! 211: dp->dp_if.if_ioctl = dpioctl; ! 212: dp->dp_if.if_reset = dpreset; ! 213: dp->dp_if.if_watchdog = dptimeout; ! 214: dp->dp_if.if_flags = 0; ! 215: if_attach(&dp->dp_if); ! 216: } ! 217: ! 218: /* ! 219: * Reset of interface after UNIBUS reset. ! 220: * If interface is on specified UBA, reset its state. ! 221: */ ! 222: dpreset(unit, uban) ! 223: int unit, uban; ! 224: { ! 225: register struct uba_device *ui; ! 226: register struct dp_softc *dp = &dp_softc[unit]; ! 227: register struct dpdevice *addr; ! 228: ! 229: dpstat.reset++; ! 230: if (unit >= NDP || (ui = dpinfo[unit]) == 0 || ui->ui_alive == 0 || ! 231: ui->ui_ubanum != uban) ! 232: return; ! 233: dpdown(unit); ! 234: dpinit(unit); ! 235: printf(" dp%d", unit); ! 236: } ! 237: ! 238: /* ! 239: * Initialization of interface. ! 240: */ ! 241: dpinit(unit) ! 242: int unit; ! 243: { ! 244: register struct dp_softc *dp = &dp_softc[unit]; ! 245: register struct dpdevice *addr; ! 246: register struct ifaddr *ifa; ! 247: register struct pdma *pdp = &dppdma[unit*2]; ! 248: int base, s; ! 249: ! 250: dpstat.init++; ! 251: /* ! 252: * Check to see that an address has been set. ! 253: */ ! 254: for (ifa = dp->dp_if.if_addrlist; ifa; ifa = ifa->ifa_next) ! 255: if (ifa->ifa_addr->sa_family != AF_LINK) ! 256: break; ! 257: if (ifa == (struct ifaddr *) 0) ! 258: return; ! 259: ! 260: addr = dp->dp_addr; ! 261: s = splimp(); ! 262: dp->dp_iused = 0; ! 263: dp->dp_istate = dp->dp_ostate = DPS_IDLE; ! 264: dp->dp_if.if_flags |= IFF_RUNNING; ! 265: dp->dp_if.if_flags &= ~IFF_OACTIVE; ! 266: ! 267: pdp->p_addr = addr; ! 268: pdp->p_fcn = dpxint; ! 269: pdp->p_mem = pdp->p_end = dp->dp_obuf; ! 270: pdp++; ! 271: pdp->p_addr = addr; ! 272: pdp->p_fcn = dprint; ! 273: /* force initial interrupt to come to dprint */ ! 274: pdp->p_mem = pdp->p_end = dp->dp_ibuf + DP_MTU + 8; ! 275: ! 276: addr->dpclr = DP_CLR; ! 277: DELAY(5000); ! 278: /* DP_ATA = 0, DP_CHRM = 0, DP_SSLM = 1, (enable aborts), ! 279: CRC = CCIIT, initially all ones, 2nd addr = 0 */ ! 280: addr->dpsar = DP_SSLM | DP_IDLE; ! 281: addr->dpclr = DP_XE | dp_ilb; ! 282: addr->dptdsr = DP_XSM; ! 283: /* enable receiver, receive interrupt, DTR, RTS */ ! 284: addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR | DP_RTS; ! 285: dpstart(&dp->dp_if); ! 286: splx(s); ! 287: } ! 288: ! 289: /* ! 290: * Start output on interface. Get another datagram ! 291: * to send from the interface queue and map it to ! 292: * the interface before starting output. ! 293: * ! 294: */ ! 295: dpstart(ifp) ! 296: struct ifnet *ifp; ! 297: { ! 298: int s, unit = ifp->if_unit, error = 0, len; ! 299: register struct dp_softc *dp = &dp_softc[unit]; ! 300: register struct dpdevice *addr = dp->dp_addr; ! 301: register struct mbuf *m; ! 302: register char *cp; ! 303: char *cplim; ! 304: ! 305: /* ! 306: * If already doing output, go away and depend on transmit ! 307: * complete or error. ! 308: */ ! 309: dpstat.start++; ! 310: if ((dp->dp_if.if_flags & IFF_OACTIVE) || ! 311: (dp->dp_if.if_flags & IFF_RUNNING) == 0) ! 312: goto out; ! 313: IF_DEQUEUE(&dp->dp_if.if_snd, m); ! 314: if (m == 0) ! 315: goto out; ! 316: dp->dp_if.if_collisions++; ! 317: if (m->m_flags & M_PKTHDR) ! 318: len = m->m_pkthdr.len; ! 319: else { ! 320: struct mbuf *m0 = m; ! 321: for (len = 0; m; m = m->m_next) ! 322: len += m->m_len; ! 323: m = m0; ! 324: dpstat.nohdr++; ! 325: } ! 326: if (len < 2) ! 327: goto out; ! 328: if (len > DP_MTU) { ! 329: error = EINVAL; ! 330: goto out; ! 331: } ! 332: dppdma[2*unit].p_mem = cp = dp->dp_obuf; ! 333: while (m) { ! 334: struct mbuf *n; ! 335: bcopy(mtod(m, caddr_t), (caddr_t)cp, m->m_len); ! 336: cp += m->m_len; ! 337: MFREE(m, n); m = n; ! 338: } ! 339: dppdma[2*unit].p_end = cp - 1; ! 340: dp->dp_if.if_flags |= IFF_OACTIVE; ! 341: dp->dp_ostate = DPS_ACTIVE; ! 342: dp->dp_if.if_collisions--; ! 343: dp->dp_olen = len; ! 344: if (dp_log) { ! 345: register u_char *p = (u_char *)dp->dp_obuf; ! 346: log(LOG_DEBUG, "dpoutput(%d):%x %x %x %x %x\n", ! 347: len, p[0], p[1], p[2], p[3], p[4]); ! 348: } ! 349: addr->dpsar = DP_SSLM | DP_IDLE; ! 350: addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR | DP_RTS; ! 351: addr->dpclr = DP_XIE | DP_XE | dp_ilb; ! 352: addr->dptdsr = DP_XSM; ! 353: out: ! 354: return (error); ! 355: } ! 356: /* ! 357: * Receive done or error interrupt ! 358: */ ! 359: dprint(unit, pdma, addr) ! 360: register struct pdma *pdma; ! 361: register struct dpdevice *addr; ! 362: { ! 363: register struct dp_softc *dp = &dp_softc[unit]; ! 364: short rdsr = addr->dprdsr, rcsr = pdma->p_arg; ! 365: ! 366: dpstat.rint++; ! 367: splx(dp->dp_ipl); ! 368: if (rdsr & DP_RGA) { ! 369: /* DP_ATA = 0, DP_CHRM = 0, DP_SSLM = 1, (enable aborts), ! 370: CRC = CCIIT, initially all ones, 2nd addr = 0 */ ! 371: addr->dpsar = DP_SSLM | DP_IDLE; ! 372: addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR | DP_RTS; ! 373: dpstat.rga++; ! 374: return; ! 375: } ! 376: if (rdsr & DP_RSM) { /* Received Start of Message */ ! 377: dpstat.rsm++; ! 378: pdma->p_mem = dp->dp_ibuf; ! 379: if (rcsr & DP_RDR) { ! 380: dp->dp_ibuf[0] = rdsr & DP_RBUF; ! 381: pdma->p_mem++; ! 382: } ! 383: dp->dp_flags &= ~DPF_FLUSH; ! 384: return; ! 385: } ! 386: if (rdsr & DP_REM) { /* Received End of Message */ ! 387: dpstat.rem++; ! 388: if (rcsr & DP_RDR) { ! 389: *(pdma->p_mem++) = rdsr; ! 390: dpstat.remchr++; ! 391: } ! 392: dp->dp_ilen = pdma->p_mem - dp->dp_ibuf; ! 393: if (rdsr & DP_REC || dp->dp_flags & DPF_FLUSH) { ! 394: dp->dp_if.if_ierrors++; ! 395: } else ! 396: dpinput(&dp->dp_if, dp->dp_ilen, dp->dp_ibuf); ! 397: pdma->p_mem = pdma->p_end; ! 398: dp->dp_flags &= ~ DPF_FLUSH; ! 399: return; ! 400: } ! 401: if (rdsr & DP_ROVR) { ! 402: dpstat.rovr++; ! 403: dp->dp_flags |= DPF_FLUSH; ! 404: return; ! 405: } ! 406: if (rcsr & DP_MSC) { ! 407: dpstat.mchange++; ! 408: if (0 == (rcsr & DP_DSR)) { ! 409: log(LOG_DEBUG, "dp%d: lost modem\n", unit); ! 410: /*dpdown(unit);*/ ! 411: } ! 412: return; ! 413: } ! 414: dp->dp_flags |= DPF_FLUSH; ! 415: if (pdma->p_mem != pdma->p_end) ! 416: log(LOG_DEBUG, "dp%d: unexplained receiver interrupt\n", unit); ! 417: } ! 418: /* ! 419: * Transmit complete or error interrupt ! 420: */ ! 421: dpxint(unit, pdma, addr) ! 422: register struct pdma *pdma; ! 423: register struct dpdevice *addr; ! 424: { ! 425: register struct dp_softc *dp = &dp_softc[unit]; ! 426: int s; ! 427: ! 428: splx(dp->dp_ipl); ! 429: dpstat.xint++; ! 430: if (addr->dptdsr & DP_XERR) { ! 431: log(LOG_DEBUG, "if_dp%d: data late\n", unit); ! 432: restart: ! 433: pdma->p_mem = dp->dp_obuf; ! 434: addr->dptdsr = DP_XSM; ! 435: dp->dp_if.if_oerrors++; ! 436: return; ! 437: } ! 438: switch (dp->dp_ostate) { ! 439: ! 440: case DPS_ACTIVE: ! 441: if (pdma->p_mem != pdma->p_end) { ! 442: log(LOG_DEBUG, "if_dp%d: misc error in dpxint\n", unit); ! 443: goto restart; ! 444: } ! 445: addr->dpsar = DP_IDLE|DP_SSLM; ! 446: addr->dpclr = DP_XE | DP_XIE | dp_ilb; ! 447: addr->dptdsr = DP_XEM | (0xff & pdma->p_mem[0]); ! 448: addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR | DP_RTS; ! 449: dp->dp_ostate = DPS_XEM; ! 450: break; ! 451: ! 452: case DPS_XEM: ! 453: dpstat.xem++; ! 454: dp->dp_if.if_opackets++; ! 455: dp->dp_ostate = DPS_IDLE; ! 456: dp->dp_if.if_flags &= ~IFF_OACTIVE; ! 457: if (dp->dp_if.if_snd.ifq_len) ! 458: dpstart(&dp->dp_if); ! 459: else { ! 460: addr->dpsar = DP_IDLE|DP_SSLM; ! 461: addr->dpclr = DP_XE | dp_ilb; ! 462: addr->dptdsr = DP_XSM; ! 463: addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR|DP_RTS; ! 464: } ! 465: break; ! 466: ! 467: default: ! 468: log(LOG_DEBUG, "if_dp%d: impossible state in dpxint\n"); ! 469: } ! 470: } ! 471: /* ! 472: * Routine to copy from device buffer into mbufs. ! 473: * ! 474: * Warning: This makes the fairly safe assumption that ! 475: * mbufs have even lengths. ! 476: */ ! 477: struct mbuf * ! 478: dpget(rxbuf, totlen, off, ifp) ! 479: caddr_t rxbuf; ! 480: int totlen, off; ! 481: struct ifnet *ifp; ! 482: { ! 483: register caddr_t cp; ! 484: register struct mbuf *m; ! 485: struct mbuf *top = 0, **mp = ⊤ ! 486: int len; ! 487: caddr_t packet_end; ! 488: ! 489: cp = rxbuf; ! 490: packet_end = cp + totlen; ! 491: if (off) { ! 492: off += 2 * sizeof(u_short); ! 493: totlen -= 2 *sizeof(u_short); ! 494: cp = rxbuf + off; ! 495: } ! 496: ! 497: MGETHDR(m, M_DONTWAIT, MT_DATA); ! 498: if (m == 0) ! 499: return (0); ! 500: m->m_pkthdr.rcvif = ifp; ! 501: m->m_pkthdr.len = totlen; ! 502: m->m_len = MHLEN; ! 503: ! 504: while (totlen > 0) { ! 505: if (top) { ! 506: MGET(m, M_DONTWAIT, MT_DATA); ! 507: if (m == 0) { ! 508: m_freem(top); ! 509: return (0); ! 510: } ! 511: m->m_len = MLEN; ! 512: } ! 513: len = min(totlen, (packet_end - cp)); ! 514: if (len >= MINCLSIZE) { ! 515: MCLGET(m, M_DONTWAIT); ! 516: if (m->m_flags & M_EXT) ! 517: m->m_len = len = min(len, MCLBYTES); ! 518: else ! 519: len = m->m_len; ! 520: } else { ! 521: /* ! 522: * Place initial small packet/header at end of mbuf. ! 523: */ ! 524: if (len < m->m_len) { ! 525: if (top == 0 && len + max_linkhdr <= m->m_len) ! 526: m->m_data += max_linkhdr; ! 527: m->m_len = len; ! 528: } else ! 529: len = m->m_len; ! 530: } ! 531: bcopy(cp, mtod(m, caddr_t), (u_int)len); ! 532: *mp = m; ! 533: mp = &m->m_next; ! 534: totlen -= len; ! 535: cp += len; ! 536: if (cp == packet_end) ! 537: cp = rxbuf; ! 538: } ! 539: return (top); ! 540: } ! 541: ! 542: dpinput(ifp, len, buffer) ! 543: register struct ifnet *ifp; ! 544: caddr_t buffer; ! 545: { ! 546: register struct ifqueue *inq; ! 547: register struct mbuf *m; ! 548: extern struct ifqueue hdintrq, ipintrq; ! 549: int isr; ! 550: ! 551: ifp->if_ipackets++; ! 552: if (dp_log) { ! 553: register u_char *p = (u_char *)buffer; ! 554: log(LOG_DEBUG, "dpinput(%d):%x %x %x %x %x\n", ! 555: len, p[0], p[1], p[2], p[3], p[4]); ! 556: } ! 557: ! 558: { ! 559: register struct ifaddr *ifa = ifp->if_addrlist; ! 560: register u_char *cp = (u_char *)buffer; ! 561: ! 562: for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) ! 563: if (ifa->ifa_addr->sa_family != AF_LINK) ! 564: break; ! 565: if (cp[0] == 0xff && cp[1] == 0x3) { ! 566: /* This is a UI HDLC Packet, so we'll assume PPP ! 567: protocol. for now, IP only. */ ! 568: buffer += 4; ! 569: len -= 4; ! 570: inq = &ipintrq; ! 571: isr = NETISR_IP; ! 572: } else { ! 573: inq = &hdintrq; ! 574: isr = NETISR_CCITT; ! 575: } ! 576: } ! 577: if (len <= 0) ! 578: return; ! 579: ! 580: m = dpget(buffer, len , 0, ifp); ! 581: if (m == 0) ! 582: return; ! 583: ! 584: if(IF_QFULL(inq)) { ! 585: IF_DROP(inq); ! 586: m_freem(m); ! 587: } else { ! 588: IF_ENQUEUE(inq, m); ! 589: schednetisr(isr); ! 590: } ! 591: } ! 592: ! 593: /* ! 594: * Process an ioctl request. ! 595: */ ! 596: dpioctl(ifp, cmd, data) ! 597: register struct ifnet *ifp; ! 598: int cmd; ! 599: caddr_t data; ! 600: { ! 601: register struct ifaddr *ifa = (struct ifaddr *)data; ! 602: int s = splimp(), error = 0; ! 603: struct dp_softc *dp = &dp_softc[ifp->if_unit]; ! 604: ! 605: dpstat.ioctl++; ! 606: switch (cmd) { ! 607: case SIOCSIFCONF_X25: ! 608: ifp->if_flags |= IFF_UP; ! 609: error = hd_ctlinput(PRC_IFUP, ifa->ifa_addr); ! 610: if (error == 0) ! 611: dpinit(ifp->if_unit); ! 612: break; ! 613: ! 614: case SIOCSIFADDR: ! 615: ifa->ifa_rtrequest = x25_rtrequest; ! 616: break; ! 617: ! 618: case SIOCSIFFLAGS: ! 619: if ((ifp->if_flags & IFF_UP) == 0 && ! 620: (ifp->if_flags & IFF_RUNNING)) ! 621: dpdown(ifp->if_unit); ! 622: else if (ifp->if_flags & IFF_UP && ! 623: (ifp->if_flags & IFF_RUNNING) == 0) ! 624: dpinit(ifp->if_unit); ! 625: break; ! 626: ! 627: ! 628: default: ! 629: error = EINVAL; ! 630: } ! 631: splx(s); ! 632: return (error); ! 633: } ! 634: /* ! 635: * Reset a device and mark down. ! 636: * Flush output queue and drop queue limit. ! 637: */ ! 638: dpdown(unit) ! 639: int unit; ! 640: { ! 641: ! 642: register struct dp_softc *dp = &dp_softc[unit]; ! 643: register struct dpdevice *addr = dp->dp_addr; ! 644: ! 645: dpstat.down++; ! 646: if_qflush(&dp->dp_if.if_snd); ! 647: dp->dp_flags = 0; ! 648: dp->dp_if.if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); ! 649: ! 650: addr->dpclr = DP_CLR; ! 651: DELAY(1000); ! 652: addr->dpsar = 0; ! 653: addr->dprcsr = 0; ! 654: } ! 655: ! 656: /* ! 657: * Watchdog timeout to see that transmitted packets don't ! 658: * lose interrupts. The device has to be online (the first ! 659: * transmission may block until the other side comes up). ! 660: */ ! 661: dptimeout(unit) ! 662: int unit; ! 663: { ! 664: register struct dp_softc *dp; ! 665: ! 666: /* currently not armed */ ! 667: dpstat.timeout++; ! 668: dp = &dp_softc[unit]; ! 669: if (dp->dp_if.if_flags & IFF_OACTIVE) { ! 670: dpstart(&dp->dp_if); ! 671: } ! 672: } ! 673: /* ! 674: * For debugging loopback activity. ! 675: */ ! 676: static char pppheader[4] = { -1, 3, 0, 0x21 }; ! 677: int dp_louts; ! 678: ! 679: dptestoutput(ifp, m, dst, rt) ! 680: register struct ifnet *ifp; ! 681: register struct mbuf *m; ! 682: struct sockaddr *dst; ! 683: struct rtentry *rt; ! 684: { ! 685: /* ! 686: * Queue message on interface, and start output if interface ! 687: * not yet active. ! 688: */ ! 689: int s = splimp(), error = 0; ! 690: dp_louts++; ! 691: M_PREPEND(m, sizeof pppheader, M_DONTWAIT); ! 692: if (m == 0) { ! 693: splx(s); ! 694: return ENOBUFS; ! 695: } ! 696: bcopy(pppheader, mtod(m, caddr_t), sizeof pppheader); ! 697: if (IF_QFULL(&ifp->if_snd)) { ! 698: IF_DROP(&ifp->if_snd); ! 699: /* printf("%s%d: HDLC says OK to send but queue full, may hang\n", ! 700: ifp->if_name, ifp->if_unit);*/ ! 701: m_freem(m); ! 702: error = ENOBUFS; ! 703: } else { ! 704: IF_ENQUEUE(&ifp->if_snd, m); ! 705: if ((ifp->if_flags & IFF_OACTIVE) == 0) ! 706: (*ifp->if_start)(ifp); ! 707: } ! 708: splx(s); ! 709: return (error); ! 710: } ! 711: ! 712: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.