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

Defined functions

il_setaddr defined in line 816; used 1 times
ilattach defined in line 125; used 2 times
ilcint defined in line 368; used 3 times
ilinit defined in line 220; used 6 times
ilioctl defined in line 754; used 2 times
iloutput defined in line 585; used 2 times
ilprobe defined in line 99; used 2 times
ilreset defined in line 202; used 2 times
ilrint defined in line 431; used 2 times
ilstart defined in line 321; used 3 times
iltotal defined in line 738; used 1 times
ilwait defined in line 182; used 5 times
ilwatch defined in line 716; used 3 times

Defined variables

il_softc defined in line 97; used 12 times
ildebug defined in line 63; used 1 times
ildriver defined in line 59; never used
ilinfo defined in line 57; used 7 times

Defined struct's

il_softc defined in line 77; used 20 times

Defined macros

ILF_OACTIVE defined in line 83; used 7 times
ILF_RCVPENDING defined in line 84; used 3 times
ILF_RUNNING defined in line 86; used 8 times
ILF_SETADDR defined in line 87; used 2 times
ILF_STATPENDING defined in line 85; used 4 times
ILUNIT defined in line 61; used 1 times
ILWATCHINTERVAL defined in line 90; used 1 times
ildataaddr defined in line 462; used 2 times
is_addr defined in line 80; used 16 times
is_if defined in line 79; used 16 times
Last modified: 1986-06-06
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2323
Valid CSS Valid XHTML 1.0 Strict