home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / vax / if / if_il.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-08  |  18.9 KB  |  690 lines

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