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

Defined functions

il_setaddr defined in line 762; used 1 times
ilattach defined in line 134; used 2 times
ilcint defined in line 387; used 3 times
ilinit defined in line 207; used 5 times
ilioctl defined in line 698; used 2 times
iloutput defined in line 563; used 2 times
ilprobe defined in line 106; used 2 times
ilrint defined in line 456; used 2 times
ilstart defined in line 329; used 3 times
iltotal defined in line 682; used 1 times
ilwait defined in line 187; used 5 times
ilwatch defined in line 660; used 3 times

Defined variables

il_softc defined in line 104; used 10 times
ildebug defined in line 71; used 1 times
ildriver defined in line 67; never used
ilinfo defined in line 65; used 6 times
ilstd defined in line 66; used 1 times
  • in line 68
ilub defined in line 72; used 9 times

Defined struct's

il_softc defined in line 87; used 20 times

Defined macros

ILF_OACTIVE defined in line 93; used 7 times
ILF_RCVPENDING defined in line 94; used 3 times
ILF_RUNNING defined in line 96; used 7 times
ILF_SETADDR defined in line 97; used 2 times
ILF_STATPENDING defined in line 95; used 4 times
ILUNIT defined in line 69; used 1 times
ILWATCHINTERVAL defined in line 100; used 1 times
MAPBUFDESC defined in line 469; used 1 times
is_addr defined in line 90; used 12 times
is_if defined in line 89; used 13 times
Last modified: 1995-01-07
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 5731
Valid CSS Valid XHTML 1.0 Strict