1: /*
   2:  * Copyright (c) 1982, 1986 Regents of the University of California.
   3:  * All rights reserved.  The Berkeley software License Agreement
   4:  * specifies the terms and conditions for redistribution.
   5:  *
   6:  *	@(#)if_il.c	7.1 (Berkeley) 6/5/86
   7:  */
   8: 
   9: #include "il.h"
  10: #if NIL > 0
  11: 
  12: /*
  13:  * Interlan Ethernet Communications Controller interface
  14:  */
  15: #include "../machine/pte.h"
  16: 
  17: #include "param.h"
  18: #include "systm.h"
  19: #include "mbuf.h"
  20: #include "buf.h"
  21: #include "protosw.h"
  22: #include "socket.h"
  23: #include "vmmac.h"
  24: #include "ioctl.h"
  25: #include "errno.h"
  26: 
  27: #include "../net/if.h"
  28: #include "../net/netisr.h"
  29: #include "../net/route.h"
  30: 
  31: #ifdef INET
  32: #include "../netinet/in.h"
  33: #include "../netinet/in_systm.h"
  34: #include "../netinet/in_var.h"
  35: #include "../netinet/ip.h"
  36: #include "../netinet/if_ether.h"
  37: #endif
  38: 
  39: #ifdef NS
  40: #include "../netns/ns.h"
  41: #include "../netns/ns_if.h"
  42: #endif
  43: 
  44: #include "../vax/cpu.h"
  45: #include "../vax/mtpr.h"
  46: #include "if_il.h"
  47: #include "if_ilreg.h"
  48: #include "if_uba.h"
  49: #include "../vaxuba/ubareg.h"
  50: #include "../vaxuba/ubavar.h"
  51: 
  52: int ilprobe(), ilattach(), ilrint(), ilcint();
  53: struct  uba_device *ilinfo[NIL];
  54: u_short ilstd[] = { 0 };
  55: struct  uba_driver ildriver =
  56:     { ilprobe, 0, ilattach, 0, ilstd, "il", ilinfo };
  57: #define ILUNIT(x)   minor(x)
  58: int ilinit(),iloutput(),ilioctl(),ilreset(),ilwatch();
  59: int ildebug = 0;
  60: 
  61: /*
  62:  * Ethernet software status per interface.
  63:  *
  64:  * Each interface is referenced by a network interface structure,
  65:  * is_if, which the routing code uses to locate the interface.
  66:  * This structure contains the output queue for the interface, its address, ...
  67:  * We also have, for each interface, a UBA interface structure, which
  68:  * contains information about the UNIBUS resources held by the interface:
  69:  * map registers, buffered data paths, etc.  Information is cached in this
  70:  * structure for use by the if_uba.c routines in running the interface
  71:  * efficiently.
  72:  */
  73: struct  il_softc {
  74:     struct  arpcom is_ac;       /* Ethernet common part */
  75: #define is_if   is_ac.ac_if     /* network-visible interface */
  76: #define is_addr is_ac.ac_enaddr     /* hardware Ethernet address */
  77:     struct  ifuba is_ifuba;     /* UNIBUS resources */
  78:     int is_flags;
  79: #define ILF_OACTIVE 0x1     /* output is active */
  80: #define ILF_RCVPENDING  0x2     /* start rcv in ilcint */
  81: #define ILF_STATPENDING 0x4     /* stat cmd pending */
  82: #define ILF_RUNNING 0x8     /* board is running */
  83: #define ILF_SETADDR 0x10        /* physical address is changed */
  84:     short   is_lastcmd;     /* can't read csr, so must save it */
  85:     short   is_scaninterval;    /* interval of stat collection */
  86: #define ILWATCHINTERVAL 60      /* once every 60 seconds */
  87:     struct  il_stats is_stats;  /* holds on-board statistics */
  88:     struct  il_stats is_sum;    /* summation over time */
  89:     int is_ubaddr;      /* mapping registers of is_stats */
  90: } il_softc[NIL];
  91: 
  92: ilprobe(reg)
  93:     caddr_t reg;
  94: {
  95:     register int br, cvec;      /* r11, r10 value-result */
  96:     register struct ildevice *addr = (struct ildevice *)reg;
  97:     register i;
  98: 
  99: #ifdef lint
 100:     br = 0; cvec = br; br = cvec;
 101:     i = 0; ilrint(i); ilcint(i); ilwatch(i);
 102: #endif
 103: 
 104:     addr->il_csr = ILC_OFFLINE|IL_CIE;
 105:     DELAY(100000);
 106:     i = addr->il_csr;       /* clear CDONE */
 107:     if (cvec > 0 && cvec != 0x200)
 108:         cvec -= 4;
 109:     return (1);
 110: }
 111: 
 112: /*
 113:  * Interface exists: make available by filling in network interface
 114:  * record.  System will initialize the interface when it is ready
 115:  * to accept packets.  A STATUS command is done to get the ethernet
 116:  * address and other interesting data.
 117:  */
 118: ilattach(ui)
 119:     struct uba_device *ui;
 120: {
 121:     register struct il_softc *is = &il_softc[ui->ui_unit];
 122:     register struct ifnet *ifp = &is->is_if;
 123:     register struct ildevice *addr = (struct ildevice *)ui->ui_addr;
 124: 
 125:     ifp->if_unit = ui->ui_unit;
 126:     ifp->if_name = "il";
 127:     ifp->if_mtu = ETHERMTU;
 128:     ifp->if_flags = IFF_BROADCAST;
 129: 
 130:     /*
 131: 	 * Reset the board and map the statistics
 132: 	 * buffer onto the Unibus.
 133: 	 */
 134:     addr->il_csr = ILC_RESET;
 135:     (void)ilwait(ui, "reset");
 136: 
 137:     is->is_ubaddr = uballoc(ui->ui_ubanum, (caddr_t)&is->is_stats,
 138:         sizeof (struct il_stats), 0);
 139:     addr->il_bar = is->is_ubaddr & 0xffff;
 140:     addr->il_bcr = sizeof (struct il_stats);
 141:     addr->il_csr = ((is->is_ubaddr >> 2) & IL_EUA)|ILC_STAT;
 142:     (void)ilwait(ui, "status");
 143:     ubarelse(ui->ui_ubanum, &is->is_ubaddr);
 144:     if (ildebug)
 145:         printf("il%d: module=%s firmware=%s\n", ui->ui_unit,
 146:             is->is_stats.ils_module, is->is_stats.ils_firmware);
 147:     bcopy((caddr_t)is->is_stats.ils_addr, (caddr_t)is->is_addr,
 148:         sizeof (is->is_addr));
 149:     printf("il%d: hardware address %s\n", ui->ui_unit,
 150:         ether_sprintf(is->is_addr));
 151:     ifp->if_init = ilinit;
 152:     ifp->if_output = iloutput;
 153:     ifp->if_ioctl = ilioctl;
 154:     ifp->if_reset = ilreset;
 155:     is->is_ifuba.ifu_flags = UBA_CANTWAIT;
 156:     if_attach(ifp);
 157: }
 158: 
 159: ilwait(ui, op)
 160:     struct uba_device *ui;
 161:     char *op;
 162: {
 163:     register struct ildevice *addr = (struct ildevice *)ui->ui_addr;
 164: 
 165:     while ((addr->il_csr&IL_CDONE) == 0)
 166:         ;
 167:     if (addr->il_csr&IL_STATUS) {
 168:         printf("il%d: %s failed, csr=%b\n", ui->ui_unit, op,
 169:             addr->il_csr, IL_BITS);
 170:         return (-1);
 171:     }
 172:     return (0);
 173: }
 174: 
 175: /*
 176:  * Reset of interface after UNIBUS reset.
 177:  * If interface is on specified uba, reset its state.
 178:  */
 179: ilreset(unit, uban)
 180:     int unit, uban;
 181: {
 182:     register struct uba_device *ui;
 183: 
 184:     if (unit >= NIL || (ui = ilinfo[unit]) == 0 || ui->ui_alive == 0 ||
 185:         ui->ui_ubanum != uban)
 186:         return;
 187:     printf(" il%d", unit);
 188:     il_softc[unit].is_if.if_flags &= ~IFF_RUNNING;
 189:     il_softc[unit].is_flags &= ~ILF_RUNNING;
 190:     ilinit(unit);
 191: }
 192: 
 193: /*
 194:  * Initialization of interface; clear recorded pending
 195:  * operations, and reinitialize UNIBUS usage.
 196:  */
 197: ilinit(unit)
 198:     int unit;
 199: {
 200:     register struct il_softc *is = &il_softc[unit];
 201:     register struct uba_device *ui = ilinfo[unit];
 202:     register struct ildevice *addr;
 203:     register struct ifnet *ifp = &is->is_if;
 204:     int s;
 205: 
 206:     /* not yet, if address still unknown */
 207:     if (ifp->if_addrlist == (struct ifaddr *)0)
 208:         return;
 209:     if (is->is_flags & ILF_RUNNING)
 210:         return;
 211: 
 212:     if ((ifp->if_flags & IFF_RUNNING) == 0) {
 213:         if (if_ubainit(&is->is_ifuba, ui->ui_ubanum,
 214:             sizeof (struct il_rheader), (int)btoc(ETHERMTU)) == 0) {
 215:             printf("il%d: can't initialize\n", unit);
 216:             is->is_if.if_flags &= ~IFF_UP;
 217:             return;
 218:         }
 219:         is->is_ubaddr = uballoc(ui->ui_ubanum, (caddr_t)&is->is_stats,
 220:             sizeof (struct il_stats), 0);
 221:     }
 222:     ifp->if_watchdog = ilwatch;
 223:     is->is_scaninterval = ILWATCHINTERVAL;
 224:     ifp->if_timer = is->is_scaninterval;
 225:     addr = (struct ildevice *)ui->ui_addr;
 226: 
 227:     /*
 228: 	 * Turn off source address insertion (it's faster this way),
 229: 	 * and set board online.  Former doesn't work if board is
 230: 	 * already online (happens on ubareset), so we put it offline
 231: 	 * first.
 232: 	 */
 233:     s = splimp();
 234:     addr->il_csr = ILC_RESET;
 235:     if (ilwait(ui, "hardware diag")) {
 236:         is->is_if.if_flags &= ~IFF_UP;
 237:         splx(s);
 238:         return;
 239:     }
 240:     addr->il_csr = ILC_CISA;
 241:     while ((addr->il_csr & IL_CDONE) == 0)
 242:         ;
 243:     /*
 244: 	 * If we must reprogram this board's physical ethernet
 245: 	 * address (as for secondary XNS interfaces), we do so
 246: 	 * before putting it on line, and starting receive requests.
 247: 	 * If you try this on an older 1010 board, it will total
 248: 	 * wedge the board.
 249: 	 */
 250:     if (is->is_flags & ILF_SETADDR) {
 251:         bcopy((caddr_t)is->is_addr, (caddr_t)&is->is_stats,
 252:                             sizeof is->is_addr);
 253:         addr->il_bar = is->is_ubaddr & 0xffff;
 254:         addr->il_bcr = sizeof is->is_addr;
 255:         addr->il_csr = ((is->is_ubaddr >> 2) & IL_EUA)|ILC_LDPA;
 256:         if (ilwait(ui, "setaddr"))
 257:             return;
 258:         addr->il_bar = is->is_ubaddr & 0xffff;
 259:         addr->il_bcr = sizeof (struct il_stats);
 260:         addr->il_csr = ((is->is_ubaddr >> 2) & IL_EUA)|ILC_STAT;
 261:         if (ilwait(ui, "verifying setaddr"))
 262:             return;
 263:         if (bcmp((caddr_t)is->is_stats.ils_addr, (caddr_t)is->is_addr,
 264:                         sizeof (is->is_addr)) != 0) {
 265:             printf("il%d: setaddr didn't work\n", ui->ui_unit);
 266:             return;
 267:         }
 268:     }
 269:     /*
 270: 	 * Set board online.
 271: 	 * Hang receive buffer and start any pending
 272: 	 * writes by faking a transmit complete.
 273: 	 * Receive bcr is not a multiple of 8 so buffer
 274: 	 * chaining can't happen.
 275: 	 */
 276:     addr->il_csr = ILC_ONLINE;
 277:     while ((addr->il_csr & IL_CDONE) == 0)
 278:         ;
 279:     addr->il_bar = is->is_ifuba.ifu_r.ifrw_info & 0xffff;
 280:     addr->il_bcr = sizeof(struct il_rheader) + ETHERMTU + 6;
 281:     addr->il_csr =
 282:         ((is->is_ifuba.ifu_r.ifrw_info >> 2) & IL_EUA)|ILC_RCV|IL_RIE;
 283:     while ((addr->il_csr & IL_CDONE) == 0)
 284:         ;
 285:     is->is_flags = ILF_OACTIVE;
 286:     is->is_if.if_flags |= IFF_RUNNING;
 287:     is->is_flags |= ILF_RUNNING;
 288:     is->is_lastcmd = 0;
 289:     ilcint(unit);
 290:     splx(s);
 291: }
 292: 
 293: /*
 294:  * Start output on interface.
 295:  * Get another datagram to send off of the interface queue,
 296:  * and map it to the interface before starting the output.
 297:  */
 298: ilstart(dev)
 299:     dev_t dev;
 300: {
 301:         int unit = ILUNIT(dev), len;
 302:     struct uba_device *ui = ilinfo[unit];
 303:     register struct il_softc *is = &il_softc[unit];
 304:     register struct ildevice *addr;
 305:     struct mbuf *m;
 306:     short csr;
 307: 
 308:     IF_DEQUEUE(&is->is_if.if_snd, m);
 309:     addr = (struct ildevice *)ui->ui_addr;
 310:     if (m == 0) {
 311:         if ((is->is_flags & ILF_STATPENDING) == 0)
 312:             return;
 313:         addr->il_bar = is->is_ubaddr & 0xffff;
 314:         addr->il_bcr = sizeof (struct il_stats);
 315:         csr = ((is->is_ubaddr >> 2) & IL_EUA)|ILC_STAT|IL_RIE|IL_CIE;
 316:         is->is_flags &= ~ILF_STATPENDING;
 317:         goto startcmd;
 318:     }
 319:     len = if_wubaput(&is->is_ifuba, m);
 320:     /*
 321: 	 * Ensure minimum packet length.
 322: 	 * This makes the safe assumtion that there are no virtual holes
 323: 	 * after the data.
 324: 	 * For security, it might be wise to zero out the added bytes,
 325: 	 * but we're mainly interested in speed at the moment.
 326: 	 */
 327:     if (len - sizeof(struct ether_header) < ETHERMIN)
 328:         len = ETHERMIN + sizeof(struct ether_header);
 329:     if (is->is_ifuba.ifu_flags & UBA_NEEDBDP)
 330:         UBAPURGE(is->is_ifuba.ifu_uba, is->is_ifuba.ifu_w.ifrw_bdp);
 331:     addr->il_bar = is->is_ifuba.ifu_w.ifrw_info & 0xffff;
 332:     addr->il_bcr = len;
 333:     csr =
 334:       ((is->is_ifuba.ifu_w.ifrw_info >> 2) & IL_EUA)|ILC_XMIT|IL_CIE|IL_RIE;
 335: 
 336: startcmd:
 337:     is->is_lastcmd = csr & IL_CMD;
 338:     addr->il_csr = csr;
 339:     is->is_flags |= ILF_OACTIVE;
 340: }
 341: 
 342: /*
 343:  * Command done interrupt.
 344:  */
 345: ilcint(unit)
 346:     int unit;
 347: {
 348:     register struct il_softc *is = &il_softc[unit];
 349:     struct uba_device *ui = ilinfo[unit];
 350:     register struct ildevice *addr = (struct ildevice *)ui->ui_addr;
 351:     short csr;
 352: 
 353:     if ((is->is_flags & ILF_OACTIVE) == 0) {
 354:         printf("il%d: stray xmit interrupt, csr=%b\n", unit,
 355:             addr->il_csr, IL_BITS);
 356:         return;
 357:     }
 358: 
 359:     csr = addr->il_csr;
 360:     /*
 361: 	 * Hang receive buffer if it couldn't
 362: 	 * be done earlier (in ilrint).
 363: 	 */
 364:     if (is->is_flags & ILF_RCVPENDING) {
 365:         int s;
 366: 
 367:         addr->il_bar = is->is_ifuba.ifu_r.ifrw_info & 0xffff;
 368:         addr->il_bcr = sizeof(struct il_rheader) + ETHERMTU + 6;
 369:         addr->il_csr =
 370:           ((is->is_ifuba.ifu_r.ifrw_info >> 2) & IL_EUA)|ILC_RCV|IL_RIE;
 371:         s = splhigh();
 372:         while ((addr->il_csr & IL_CDONE) == 0)
 373:             ;
 374:         splx(s);
 375:         is->is_flags &= ~ILF_RCVPENDING;
 376:     }
 377:     is->is_flags &= ~ILF_OACTIVE;
 378:     csr &= IL_STATUS;
 379:     switch (is->is_lastcmd) {
 380: 
 381:     case ILC_XMIT:
 382:         is->is_if.if_opackets++;
 383:         if (csr > ILERR_RETRIES)
 384:             is->is_if.if_oerrors++;
 385:         break;
 386: 
 387:     case ILC_STAT:
 388:         if (csr == ILERR_SUCCESS)
 389:             iltotal(is);
 390:         break;
 391:     }
 392:     if (is->is_ifuba.ifu_xtofree) {
 393:         m_freem(is->is_ifuba.ifu_xtofree);
 394:         is->is_ifuba.ifu_xtofree = 0;
 395:     }
 396:     ilstart(unit);
 397: }
 398: 
 399: /*
 400:  * Ethernet interface receiver interrupt.
 401:  * If input error just drop packet.
 402:  * Otherwise purge input buffered data path and examine
 403:  * packet to determine type.  If can't determine length
 404:  * from type, then have to drop packet.  Othewise decapsulate
 405:  * packet based on type and pass to type specific higher-level
 406:  * input routine.
 407:  */
 408: ilrint(unit)
 409:     int unit;
 410: {
 411:     register struct il_softc *is = &il_softc[unit];
 412:     struct ildevice *addr = (struct ildevice *)ilinfo[unit]->ui_addr;
 413:     register struct il_rheader *il;
 414:         struct mbuf *m;
 415:     int len, off, resid, s;
 416:     register struct ifqueue *inq;
 417: 
 418:     is->is_if.if_ipackets++;
 419:     if (is->is_ifuba.ifu_flags & UBA_NEEDBDP)
 420:         UBAPURGE(is->is_ifuba.ifu_uba, is->is_ifuba.ifu_r.ifrw_bdp);
 421:     il = (struct il_rheader *)(is->is_ifuba.ifu_r.ifrw_addr);
 422:     len = il->ilr_length - sizeof(struct il_rheader);
 423:     if ((il->ilr_status&(ILFSTAT_A|ILFSTAT_C)) || len < 46 ||
 424:         len > ETHERMTU) {
 425:         is->is_if.if_ierrors++;
 426: #ifdef notdef
 427:         if (is->is_if.if_ierrors % 100 == 0)
 428:             printf("il%d: += 100 input errors\n", unit);
 429: #endif
 430:         goto setup;
 431:     }
 432: 
 433:     /*
 434: 	 * Deal with trailer protocol: if type is trailer type
 435: 	 * get true type from first 16-bit word past data.
 436: 	 * Remember that type was trailer by setting off.
 437: 	 */
 438:     il->ilr_type = ntohs((u_short)il->ilr_type);
 439: #define ildataaddr(il, off, type)   ((type)(((caddr_t)((il)+1)+(off))))
 440:     if (il->ilr_type >= ETHERTYPE_TRAIL &&
 441:         il->ilr_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
 442:         off = (il->ilr_type - ETHERTYPE_TRAIL) * 512;
 443:         if (off >= ETHERMTU)
 444:             goto setup;     /* sanity */
 445:         il->ilr_type = ntohs(*ildataaddr(il, off, u_short *));
 446:         resid = ntohs(*(ildataaddr(il, off+2, u_short *)));
 447:         if (off + resid > len)
 448:             goto setup;     /* sanity */
 449:         len = off + resid;
 450:     } else
 451:         off = 0;
 452:     if (len == 0)
 453:         goto setup;
 454: 
 455:     /*
 456: 	 * Pull packet off interface.  Off is nonzero if packet
 457: 	 * has trailing header; ilget will then force this header
 458: 	 * information to be at the front, but we still have to drop
 459: 	 * the type and length which are at the front of any trailer data.
 460: 	 */
 461:     m = if_rubaget(&is->is_ifuba, len, off, &is->is_if);
 462:     if (m == 0)
 463:         goto setup;
 464:     if (off) {
 465:         struct ifnet *ifp;
 466: 
 467:         ifp = *(mtod(m, struct ifnet **));
 468:         m->m_off += 2 * sizeof (u_short);
 469:         m->m_len -= 2 * sizeof (u_short);
 470:         *(mtod(m, struct ifnet **)) = ifp;
 471:     }
 472:     switch (il->ilr_type) {
 473: 
 474: #ifdef INET
 475:     case ETHERTYPE_IP:
 476:         schednetisr(NETISR_IP);
 477:         inq = &ipintrq;
 478:         break;
 479: 
 480:     case ETHERTYPE_ARP:
 481:         arpinput(&is->is_ac, m);
 482:         goto setup;
 483: #endif
 484: #ifdef NS
 485:     case ETHERTYPE_NS:
 486:         schednetisr(NETISR_NS);
 487:         inq = &nsintrq;
 488:         break;
 489: 
 490: #endif
 491:     default:
 492:         m_freem(m);
 493:         goto setup;
 494:     }
 495: 
 496:     s = splimp();
 497:     if (IF_QFULL(inq)) {
 498:         IF_DROP(inq);
 499:         m_freem(m);
 500:     } else
 501:         IF_ENQUEUE(inq, m);
 502:     splx(s);
 503: 
 504: setup:
 505:     /*
 506: 	 * Reset for next packet if possible.
 507: 	 * If waiting for transmit command completion, set flag
 508: 	 * and wait until command completes.
 509: 	 */
 510:     if (is->is_flags & ILF_OACTIVE) {
 511:         is->is_flags |= ILF_RCVPENDING;
 512:         return;
 513:     }
 514:     addr->il_bar = is->is_ifuba.ifu_r.ifrw_info & 0xffff;
 515:     addr->il_bcr = sizeof(struct il_rheader) + ETHERMTU + 6;
 516:     addr->il_csr =
 517:         ((is->is_ifuba.ifu_r.ifrw_info >> 2) & IL_EUA)|ILC_RCV|IL_RIE;
 518:     s = splhigh();
 519:     while ((addr->il_csr & IL_CDONE) == 0)
 520:         ;
 521:     splx(s);
 522: }
 523: 
 524: /*
 525:  * Ethernet output routine.
 526:  * Encapsulate a packet of type family for the local net.
 527:  * Use trailer local net encapsulation if enough data in first
 528:  * packet leaves a multiple of 512 bytes of data in remainder.
 529:  */
 530: iloutput(ifp, m0, dst)
 531:     struct ifnet *ifp;
 532:     struct mbuf *m0;
 533:     struct sockaddr *dst;
 534: {
 535:     int type, s, error;
 536:     u_char edst[6];
 537:     struct in_addr idst;
 538:     register struct il_softc *is = &il_softc[ifp->if_unit];
 539:     register struct mbuf *m = m0;
 540:     register struct ether_header *il;
 541:     register int off;
 542:     int usetrailers;
 543: 
 544:     if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
 545:         error = ENETDOWN;
 546:         goto bad;
 547:     }
 548:     switch (dst->sa_family) {
 549: 
 550: #ifdef INET
 551:     case AF_INET:
 552:         idst = ((struct sockaddr_in *)dst)->sin_addr;
 553:         if (!arpresolve(&is->is_ac, m, &idst, edst, &usetrailers))
 554:             return (0); /* if not yet resolved */
 555:         off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
 556:         if (usetrailers && off > 0 && (off & 0x1ff) == 0 &&
 557:             m->m_off >= MMINOFF + 2 * sizeof (u_short)) {
 558:             type = ETHERTYPE_TRAIL + (off>>9);
 559:             m->m_off -= 2 * sizeof (u_short);
 560:             m->m_len += 2 * sizeof (u_short);
 561:             *mtod(m, u_short *) = htons((u_short)ETHERTYPE_IP);
 562:             *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len);
 563:             goto gottrailertype;
 564:         }
 565:         type = ETHERTYPE_IP;
 566:         off = 0;
 567:         goto gottype;
 568: #endif
 569: #ifdef NS
 570:     case AF_NS:
 571:         type = ETHERTYPE_NS;
 572:         bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
 573:         (caddr_t)edst, sizeof (edst));
 574:         off = 0;
 575:         goto gottype;
 576: #endif
 577: 
 578:     case AF_UNSPEC:
 579:         il = (struct ether_header *)dst->sa_data;
 580:         bcopy((caddr_t)il->ether_dhost, (caddr_t)edst, sizeof (edst));
 581:         type = il->ether_type;
 582:         goto gottype;
 583: 
 584:     default:
 585:         printf("il%d: can't handle af%d\n", ifp->if_unit,
 586:             dst->sa_family);
 587:         error = EAFNOSUPPORT;
 588:         goto bad;
 589:     }
 590: 
 591: gottrailertype:
 592:     /*
 593: 	 * Packet to be sent as trailer: move first packet
 594: 	 * (control information) to end of chain.
 595: 	 */
 596:     while (m->m_next)
 597:         m = m->m_next;
 598:     m->m_next = m0;
 599:     m = m0->m_next;
 600:     m0->m_next = 0;
 601:     m0 = m;
 602: 
 603: gottype:
 604:     /*
 605: 	 * Add local net header.  If no space in first mbuf,
 606: 	 * allocate another.
 607: 	 */
 608:     if (m->m_off > MMAXOFF ||
 609:         MMINOFF + sizeof (struct ether_header) > m->m_off) {
 610:         m = m_get(M_DONTWAIT, MT_HEADER);
 611:         if (m == 0) {
 612:             error = ENOBUFS;
 613:             goto bad;
 614:         }
 615:         m->m_next = m0;
 616:         m->m_off = MMINOFF;
 617:         m->m_len = sizeof (struct ether_header);
 618:     } else {
 619:         m->m_off -= sizeof (struct ether_header);
 620:         m->m_len += sizeof (struct ether_header);
 621:     }
 622:     il = mtod(m, struct ether_header *);
 623:     il->ether_type = htons((u_short)type);
 624:     bcopy((caddr_t)edst, (caddr_t)il->ether_dhost, sizeof (edst));
 625:     bcopy((caddr_t)is->is_addr, (caddr_t)il->ether_shost,
 626:         sizeof(il->ether_shost));
 627: 
 628:     /*
 629: 	 * Queue message on interface, and start output if interface
 630: 	 * not yet active.
 631: 	 */
 632:     s = splimp();
 633:     if (IF_QFULL(&ifp->if_snd)) {
 634:         IF_DROP(&ifp->if_snd);
 635:         splx(s);
 636:         m_freem(m);
 637:         return (ENOBUFS);
 638:     }
 639:     IF_ENQUEUE(&ifp->if_snd, m);
 640:     if ((is->is_flags & ILF_OACTIVE) == 0)
 641:         ilstart(ifp->if_unit);
 642:     splx(s);
 643:     return (0);
 644: 
 645: bad:
 646:     m_freem(m0);
 647:     return (error);
 648: }
 649: 
 650: /*
 651:  * Watchdog routine, request statistics from board.
 652:  */
 653: ilwatch(unit)
 654:     int unit;
 655: {
 656:     register struct il_softc *is = &il_softc[unit];
 657:     register struct ifnet *ifp = &is->is_if;
 658:     int s;
 659: 
 660:     if (is->is_flags & ILF_STATPENDING) {
 661:         ifp->if_timer = is->is_scaninterval;
 662:         return;
 663:     }
 664:     s = splimp();
 665:     is->is_flags |= ILF_STATPENDING;
 666:     if ((is->is_flags & ILF_OACTIVE) == 0)
 667:         ilstart(ifp->if_unit);
 668:     splx(s);
 669:     ifp->if_timer = is->is_scaninterval;
 670: }
 671: 
 672: /*
 673:  * Total up the on-board statistics.
 674:  */
 675: iltotal(is)
 676:     register struct il_softc *is;
 677: {
 678:     register u_short *interval, *sum, *end;
 679: 
 680:     interval = &is->is_stats.ils_frames;
 681:     sum = &is->is_sum.ils_frames;
 682:     end = is->is_sum.ils_fill2;
 683:     while (sum < end)
 684:         *sum++ += *interval++;
 685:     is->is_if.if_collisions = is->is_sum.ils_collis;
 686: }
 687: 
 688: /*
 689:  * Process an ioctl request.
 690:  */
 691: ilioctl(ifp, cmd, data)
 692:     register struct ifnet *ifp;
 693:     int cmd;
 694:     caddr_t data;
 695: {
 696:     register struct ifaddr *ifa = (struct ifaddr *)data;
 697:     register struct il_softc *is = &il_softc[ifp->if_unit];
 698:     int s = splimp(), error = 0;
 699: 
 700:     switch (cmd) {
 701: 
 702:     case SIOCSIFADDR:
 703:         ifp->if_flags |= IFF_UP;
 704:         ilinit(ifp->if_unit);
 705: 
 706:         switch (ifa->ifa_addr.sa_family) {
 707: #ifdef INET
 708:         case AF_INET:
 709:             ((struct arpcom *)ifp)->ac_ipaddr =
 710:                 IA_SIN(ifa)->sin_addr;
 711:             arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
 712:             break;
 713: #endif
 714: #ifdef NS
 715:         case AF_NS:
 716:             {
 717:             register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
 718: 
 719:             if (ns_nullhost(*ina)) {
 720:                 ina->x_host = * (union ns_host *)
 721:                      (il_softc[ifp->if_unit].is_addr);
 722:             } else {
 723:                 il_setaddr(ina->x_host.c_host, ifp->if_unit);
 724:                 return (0);
 725:             }
 726:             break;
 727:             }
 728: #endif
 729:         }
 730:         break;
 731: 
 732:     case SIOCSIFFLAGS:
 733:         if ((ifp->if_flags & IFF_UP) == 0 &&
 734:             is->is_flags & ILF_RUNNING) {
 735:             ((struct ildevice *)
 736:                (ilinfo[ifp->if_unit]->ui_addr))->il_csr = ILC_RESET;
 737:             is->is_flags &= ~ILF_RUNNING;
 738:         } else if (ifp->if_flags & IFF_UP &&
 739:             (is->is_flags & ILF_RUNNING) == 0)
 740:             ilinit(ifp->if_unit);
 741:         break;
 742: 
 743:     default:
 744:         error = EINVAL;
 745:     }
 746:     splx(s);
 747:     return (error);
 748: }
 749: 
 750: /*
 751:  * set ethernet address for unit
 752:  */
 753: il_setaddr(physaddr, unit)
 754: u_char *physaddr;
 755: int unit;
 756: {
 757:     register struct il_softc *is = &il_softc[unit];
 758: 
 759:     if (! (is->is_flags & ILF_RUNNING))
 760:         return;
 761: 
 762:     bcopy((caddr_t)physaddr, (caddr_t)is->is_addr, sizeof is->is_addr);
 763:     is->is_flags &= ~ILF_RUNNING;
 764:     is->is_flags |= ILF_SETADDR;
 765:     ilinit(unit);
 766: }
 767: #endif

Defined functions

il_setaddr defined in line 753; used 1 times
ilattach defined in line 118; used 2 times
ilcint defined in line 345; used 4 times
ilinit defined in line 197; used 6 times
ilioctl defined in line 691; used 2 times
iloutput defined in line 530; used 2 times
ilprobe defined in line 92; used 2 times
ilreset defined in line 179; used 2 times
ilrint defined in line 408; used 3 times
ilstart defined in line 298; used 3 times
iltotal defined in line 675; used 1 times
ilwait defined in line 159; used 5 times
ilwatch defined in line 653; used 3 times

Defined variables

il_softc defined in line 90; used 12 times
ildebug defined in line 59; used 1 times
ildriver defined in line 55; used 1 times
ilinfo defined in line 53; used 7 times
ilstd defined in line 54; used 1 times
  • in line 56

Defined struct's

il_softc defined in line 73; used 20 times

Defined macros

ILF_OACTIVE defined in line 79; used 7 times
ILF_RCVPENDING defined in line 80; used 3 times
ILF_RUNNING defined in line 82; used 8 times
ILF_SETADDR defined in line 83; used 2 times
ILF_STATPENDING defined in line 81; used 4 times
ILUNIT defined in line 57; used 1 times
ILWATCHINTERVAL defined in line 86; used 1 times
ildataaddr defined in line 439; used 2 times
is_addr defined in line 76; used 12 times
is_if defined in line 75; used 15 times
Last modified: 1986-06-06
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2693
Valid CSS Valid XHTML 1.0 Strict