home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / vax / if / if_en.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-08  |  18.3 KB  |  746 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_en.c    7.7 (Berkeley) 12/16/90
  34.  */
  35.  
  36. #include "en.h"
  37. #if NEN > 0
  38.  
  39. /*
  40.  * Xerox prototype (3 Mb) Ethernet interface driver.
  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/errno.h"
  52. #include "sys/ioctl.h"
  53.  
  54. #include "net/if.h"
  55. #include "net/netisr.h"
  56. #include "net/route.h"
  57.  
  58. #ifdef    INET
  59. #include "netinet/in.h"
  60. #include "netinet/in_systm.h"
  61. #include "netinet/in_var.h"
  62. #include "netinet/ip.h"
  63. #endif
  64.  
  65. #ifdef PUP
  66. #include "netpup/pup.h"
  67. #include "netpup/ether.h"
  68. #endif
  69.  
  70. #ifdef NS
  71. #include "netns/ns.h"
  72. #include "netns/ns_if.h"
  73. #endif
  74.  
  75. #include "../include/cpu.h"
  76. #include "../include/mtpr.h"
  77. #include "if_en.h"
  78. #include "if_enreg.h"
  79. #include "if_uba.h"
  80. #include "../uba/ubareg.h"
  81. #include "../uba/ubavar.h"
  82.  
  83. #define    ENMTU    (1024+512)
  84. #define    ENMRU    (1024+512+16)        /* 16 is enough to receive trailer */
  85.  
  86. int    enprobe(), enattach(), enrint(), enxint(), encollide();
  87. struct    uba_device *eninfo[NEN];
  88. u_short enstd[] = { 0 };
  89. struct    uba_driver endriver =
  90.     { enprobe, 0, enattach, 0, enstd, "en", eninfo };
  91. #define    ENUNIT(x)    minor(x)
  92.  
  93. int    eninit(),oldenoutput(),enreset(),enioctl(), enstart();
  94.  
  95. #ifdef notdef
  96. /*
  97.  * If you need to byte swap IP's in the system, define
  98.  * this and do a SIOCSIFFLAGS at boot time.
  99.  */
  100. #define    ENF_SWABIPS    0x1000
  101. #endif
  102.  
  103. /*
  104.  * Ethernet software status per interface.
  105.  *
  106.  * Each interface is referenced by a network interface structure,
  107.  * es_if, which the routing code uses to locate the interface.
  108.  * This structure contains the output queue for the interface, its address, ...
  109.  * We also have, for each interface, a UBA interface structure, which
  110.  * contains information about the UNIBUS resources held by the interface:
  111.  * map registers, buffered data paths, etc.  Information is cached in this
  112.  * structure for use by the if_uba.c routines in running the interface
  113.  * efficiently.
  114.  */
  115. struct    en_softc {
  116.     struct    ifnet es_if;        /* network-visible interface */
  117.     struct    ifuba es_ifuba;        /* UNIBUS resources */
  118.     short    es_host;        /* hardware host number */
  119.     short    es_delay;        /* current output delay */
  120.     short    es_mask;        /* mask for current output delay */
  121.     short    es_lastx;        /* host last transmitted to */
  122.     short    es_oactive;        /* is output active? */
  123.     short    es_olen;        /* length of last output */
  124.     short    es_nsactive;        /* is interface enabled for ns? */
  125. } en_softc[NEN];
  126.  
  127. /*
  128.  * Do output DMA to determine interface presence and
  129.  * interrupt vector.  DMA is too short to disturb other hosts.
  130.  */
  131. enprobe(reg)
  132.     caddr_t reg;
  133. {
  134.     register int br, cvec;        /* r11, r10 value-result */
  135.     register struct endevice *addr = (struct endevice *)reg;
  136.  
  137. #ifdef lint
  138.     br = 0; cvec = br; br = cvec;
  139.     enrint(0); enxint(0); encollide(0);
  140. #endif
  141.     addr->en_istat = 0;
  142.     addr->en_owc = -1;
  143.     addr->en_oba = 0;
  144.     addr->en_ostat = EN_IEN|EN_GO;
  145.     DELAY(100000);
  146.     addr->en_ostat = 0;
  147.     return (1);
  148. }
  149.  
  150. /*
  151.  * Interface exists: make available by filling in network interface
  152.  * record.  System will initialize the interface when it is ready
  153.  * to accept packets.
  154.  */
  155. enattach(ui)
  156.     struct uba_device *ui;
  157. {
  158.     register struct en_softc *es = &en_softc[ui->ui_unit];
  159.  
  160.     es->es_if.if_unit = ui->ui_unit;
  161.     es->es_if.if_name = "en";
  162.     es->es_if.if_mtu = ENMTU;
  163.     es->es_if.if_flags = IFF_BROADCAST;
  164.     es->es_if.if_init = eninit;
  165.     es->es_if.if_output = oldenoutput;
  166.     es->es_if.if_start = enstart;
  167.     es->es_if.if_ioctl = enioctl;
  168.     es->es_if.if_reset = enreset;
  169.     es->es_ifuba.ifu_flags = UBA_NEEDBDP | UBA_NEED16 | UBA_CANTWAIT;
  170. #if defined(VAX750)
  171.     /* don't chew up 750 bdp's */
  172.     if (cpu == VAX_750 && ui->ui_unit > 0)
  173.         es->es_ifuba.ifu_flags &= ~UBA_NEEDBDP;
  174. #endif
  175.     if_attach(&es->es_if);
  176. }
  177.  
  178. /*
  179.  * Reset of interface after UNIBUS reset.
  180.  * If interface is on specified uba, reset its state.
  181.  */
  182. enreset(unit, uban)
  183.     int unit, uban;
  184. {
  185.     register struct uba_device *ui;
  186.  
  187.     if (unit >= NEN || (ui = eninfo[unit]) == 0 || ui->ui_alive == 0 ||
  188.         ui->ui_ubanum != uban)
  189.         return;
  190.     printf(" en%d", unit);
  191.     eninit(unit);
  192. }
  193.  
  194. /*
  195.  * Initialization of interface; clear recorded pending
  196.  * operations, and reinitialize UNIBUS usage.
  197.  */
  198. eninit(unit)
  199.     int unit;
  200. {
  201.     register struct en_softc *es = &en_softc[unit];
  202.     register struct uba_device *ui = eninfo[unit];
  203.     register struct endevice *addr;
  204.     int s;
  205.  
  206.     if (es->es_if.if_addrlist == (struct ifaddr *)0)
  207.         return;
  208.     if (if_ubainit(&es->es_ifuba, ui->ui_ubanum,
  209.         sizeof (struct en_header), (int)btoc(ENMRU)) == 0) { 
  210.         printf("en%d: can't initialize\n", unit);
  211.         es->es_if.if_flags &= ~IFF_UP;
  212.         return;
  213.     }
  214.     addr = (struct endevice *)ui->ui_addr;
  215.     addr->en_istat = addr->en_ostat = 0;
  216.  
  217.     /*
  218.      * Hang a receive and start any
  219.      * pending writes by faking a transmit complete.
  220.      */
  221.     s = splimp();
  222.     addr->en_iba = es->es_ifuba.ifu_r.ifrw_info;
  223.     addr->en_iwc = -(sizeof (struct en_header) + ENMRU) >> 1;
  224.     addr->en_istat = EN_IEN|EN_GO;
  225.     es->es_oactive = 1;
  226.     es->es_if.if_flags |= IFF_RUNNING;
  227.     enxint(unit);
  228.     splx(s);
  229. }
  230.  
  231. int    enalldelay = 0;
  232. int    enlastdel = 50;
  233. int    enlastmask = (~0) << 5;
  234.  
  235. /*
  236.  * Start or restart output on interface.
  237.  * If interface is already active, then this is a retransmit
  238.  * after a collision, and just restuff registers and delay.
  239.  * If interface is not already active, get another datagram
  240.  * to send off of the interface queue, and map it to the interface
  241.  * before starting the output.
  242.  */
  243. enstart(dev)
  244.     dev_t dev;
  245. {
  246.         int unit = ENUNIT(dev);
  247.     struct uba_device *ui = eninfo[unit];
  248.     register struct en_softc *es = &en_softc[unit];
  249.     register struct endevice *addr;
  250.     register struct en_header *en;
  251.     struct mbuf *m;
  252.     int dest;
  253.  
  254.     if (es->es_oactive)
  255.         goto restart;
  256.  
  257.     /*
  258.      * Not already active: dequeue another request
  259.      * and map it to the UNIBUS.  If no more requests,
  260.      * just return.
  261.      */
  262.     IF_DEQUEUE(&es->es_if.if_snd, m);
  263.     if (m == 0) {
  264.         es->es_oactive = 0;
  265.         return;
  266.     }
  267.     en = mtod(m, struct en_header *);
  268.     dest = en->en_dhost;
  269.     en->en_shost = es->es_host;
  270.     es->es_olen = if_wubaput(&es->es_ifuba, m);
  271. #ifdef ENF_SWABIPS
  272.     /*
  273.      * The Xerox interface does word at a time DMA, so
  274.      * someone must do byte swapping of user data if high
  275.      * and low ender machines are to communicate.  It doesn't
  276.      * belong here, but certain people depend on it, so...
  277.      *
  278.      * Should swab everybody, but this is a kludge anyway.
  279.      */
  280.     if (es->es_if.if_flags & ENF_SWABIPS) {
  281.         en = (struct en_header *)es->es_ifuba.ifu_w.ifrw_addr;
  282.         if (en->en_type == ENTYPE_IP)
  283.             enswab((caddr_t)(en + 1), (caddr_t)(en + 1),
  284.                 es->es_olen - sizeof (struct en_header) + 1);
  285.     }
  286. #endif
  287.  
  288.     /*
  289.      * Ethernet cannot take back-to-back packets (no
  290.      * buffering in interface.  To help avoid overrunning
  291.      * receivers, enforce a small delay (about 1ms) in interface:
  292.      *    * between all packets when enalldelay
  293.      *    * whenever last packet was broadcast
  294.      *    * whenever this packet is to same host as last packet
  295.      */
  296.     if (enalldelay || es->es_lastx == 0 || es->es_lastx == dest) {
  297.         es->es_delay = enlastdel;
  298.         es->es_mask = enlastmask;
  299.     }
  300.     es->es_lastx = dest;
  301.  
  302. restart:
  303.     /*
  304.      * Have request mapped to UNIBUS for transmission.
  305.      * Purge any stale data from this BDP, and start the otput.
  306.      */
  307.     if (es->es_ifuba.ifu_flags & UBA_NEEDBDP)
  308.         UBAPURGE(es->es_ifuba.ifu_uba, es->es_ifuba.ifu_w.ifrw_bdp);
  309.     addr = (struct endevice *)ui->ui_addr;
  310.     addr->en_oba = (int)es->es_ifuba.ifu_w.ifrw_info;
  311.     addr->en_odelay = es->es_delay;
  312.     addr->en_owc = -((es->es_olen + 1) >> 1);
  313.     addr->en_ostat = EN_IEN|EN_GO;
  314.     es->es_oactive = 1;
  315. }
  316.  
  317. /*
  318.  * Ethernet interface transmitter interrupt.
  319.  * Start another output if more data to send.
  320.  */
  321. enxint(unit)
  322.     int unit;
  323. {
  324.     register struct uba_device *ui = eninfo[unit];
  325.     register struct en_softc *es = &en_softc[unit];
  326.     register struct endevice *addr = (struct endevice *)ui->ui_addr;
  327.  
  328.     if (es->es_oactive == 0)
  329.         return;
  330.     if (es->es_mask && (addr->en_ostat&EN_OERROR)) {
  331.         es->es_if.if_oerrors++;
  332.         endocoll(unit);
  333.         return;
  334.     }
  335.     es->es_if.if_opackets++;
  336.     es->es_oactive = 0;
  337.     es->es_delay = 0;
  338.     es->es_mask = ~0;
  339.     if (es->es_ifuba.ifu_xtofree) {
  340.         m_freem(es->es_ifuba.ifu_xtofree);
  341.         es->es_ifuba.ifu_xtofree = 0;
  342.     }
  343.     if (es->es_if.if_snd.ifq_head == 0) {
  344.         es->es_lastx = 256;        /* putatively illegal */
  345.         return;
  346.     }
  347.     enstart(unit);
  348. }
  349.  
  350. /*
  351.  * Collision on ethernet interface.  Do exponential
  352.  * backoff, and retransmit.  If have backed off all
  353.  * the way print warning diagnostic, and drop packet.
  354.  */
  355. encollide(unit)
  356.     int unit;
  357. {
  358.     struct en_softc *es = &en_softc[unit];
  359.  
  360.     es->es_if.if_collisions++;
  361.     if (es->es_oactive == 0)
  362.         return;
  363.     endocoll(unit);
  364. }
  365.  
  366. endocoll(unit)
  367.     int unit;
  368. {
  369.     register struct en_softc *es = &en_softc[unit];
  370.  
  371.     /*
  372.      * Es_mask is a 16 bit number with n low zero bits, with
  373.      * n the number of backoffs.  When es_mask is 0 we have
  374.      * backed off 16 times, and give up.
  375.      */
  376.     if (es->es_mask == 0) {
  377.         printf("en%d: send error\n", unit);
  378.         enxint(unit);
  379.         return;
  380.     }
  381.     /*
  382.      * Another backoff.  Restart with delay based on n low bits
  383.      * of the interval timer.
  384.      */
  385.     es->es_mask <<= 1;
  386.     es->es_delay = mfpr(ICR) &~ es->es_mask;
  387.     enstart(unit);
  388. }
  389.  
  390. #ifdef notdef
  391. struct    sockproto enproto = { AF_ETHERLINK };
  392. struct    sockaddr_en endst = { sizeof(endst), AF_ETHERLINK };
  393. struct    sockaddr_en ensrc = { sizeof(ensrc), AF_ETHERLINK };
  394. #endif
  395. /*
  396.  * Ethernet interface receiver interrupt.
  397.  * If input error just drop packet.
  398.  * Otherwise purge input buffered data path and examine 
  399.  * packet to determine type.  If can't determine length
  400.  * from type, then have to drop packet.  Othewise decapsulate
  401.  * packet based on type and pass to type specific higher-level
  402.  * input routine.
  403.  */
  404. enrint(unit)
  405.     int unit;
  406. {
  407.     register struct en_softc *es = &en_softc[unit];
  408.     struct endevice *addr = (struct endevice *)eninfo[unit]->ui_addr;
  409.     register struct en_header *en;
  410.         struct mbuf *m;
  411.     int len; short resid;
  412.     register struct ifqueue *inq;
  413.     int off, s;
  414.  
  415.     es->es_if.if_ipackets++;
  416.  
  417.     /*
  418.      * Purge BDP; drop if input error indicated.
  419.      */
  420.     if (es->es_ifuba.ifu_flags & UBA_NEEDBDP)
  421.         UBAPURGE(es->es_ifuba.ifu_uba, es->es_ifuba.ifu_r.ifrw_bdp);
  422.     if (addr->en_istat&EN_IERROR) {
  423.         es->es_if.if_ierrors++;
  424.         goto setup;
  425.     }
  426.  
  427.     /*
  428.      * Calculate input data length.
  429.      * Get pointer to ethernet header (in input buffer).
  430.      * Deal with trailer protocol: if type is PUP trailer
  431.      * get true type from first 16-bit word past data.
  432.      * Remember that type was trailer by setting off.
  433.      */
  434.     resid = addr->en_iwc;
  435.     if (resid)
  436.         resid |= 0176000;
  437.     len = (((sizeof (struct en_header) + ENMRU) >> 1) + resid) << 1;
  438.     len -= sizeof (struct en_header);
  439.     if (len > ENMRU)
  440.         goto setup;            /* sanity */
  441.     en = (struct en_header *)(es->es_ifuba.ifu_r.ifrw_addr);
  442.     en->en_type = ntohs(en->en_type);
  443. #define    endataaddr(en, off, type)    ((type)(((caddr_t)((en)+1)+(off))))
  444.     if (en->en_type >= ENTYPE_TRAIL &&
  445.         en->en_type < ENTYPE_TRAIL+ENTYPE_NTRAILER) {
  446.         off = (en->en_type - ENTYPE_TRAIL) * 512;
  447.         if (off > ENMTU)
  448.             goto setup;        /* sanity */
  449.         en->en_type = ntohs(*endataaddr(en, off, u_short *));
  450.         resid = ntohs(*(endataaddr(en, off+2, u_short *)));
  451.         if (off + resid > len)
  452.             goto setup;        /* sanity */
  453.         len = off + resid;
  454.     } else
  455.         off = 0;
  456.     if (len == 0)
  457.         goto setup;
  458. #ifdef ENF_SWABIPS
  459.     if (es->es_if.if_flags & ENF_SWABIPS && en->en_type == ENTYPE_IP)
  460.         enswab((caddr_t)(en + 1), (caddr_t)(en + 1), len);
  461. #endif
  462.     /*
  463.      * Pull packet off interface.  Off is nonzero if packet
  464.      * has trailing header; if_rubaget will then force this header
  465.      * information to be at the front, but we still have to drop
  466.      * the type and length which are at the front of any trailer data.
  467.      */
  468.     m = if_rubaget(&es->es_ifuba, len, off, &es->es_if);
  469.     if (m == 0)
  470.         goto setup;
  471.     switch (en->en_type) {
  472.  
  473. #ifdef INET
  474.     case ENTYPE_IP:
  475.         schednetisr(NETISR_IP);
  476.         inq = &ipintrq;
  477.         break;
  478. #endif
  479. #ifdef PUP
  480.     case ENTYPE_PUP:
  481.         rpup_input(m);
  482.         goto setup;
  483. #endif
  484. #ifdef NS
  485.     case ETHERTYPE_NS:
  486.         if (es->es_nsactive) {
  487.             schednetisr(NETISR_NS);
  488.             inq = &nsintrq;
  489.         } else {
  490.             m_freem(m);
  491.             goto setup;
  492.         }
  493.         break;
  494. #endif
  495.  
  496.     default:
  497. #ifdef notdef
  498.         enproto.sp_protocol = en->en_type;
  499.         endst.sen_host = en->en_dhost;
  500.         endst.sen_net = ensrc.sen_net = es->es_if.if_net;
  501.         ensrc.sen_host = en->en_shost;
  502.         raw_input(m, &enproto,
  503.             (struct sockaddr *)&ensrc, (struct sockaddr *)&endst);
  504. #else
  505.         m_freem(m);
  506. #endif
  507.         goto setup;
  508.     }
  509.  
  510.     s = splimp();
  511.     if (IF_QFULL(inq)) {
  512.         IF_DROP(inq);
  513.         m_freem(m);
  514.     } else
  515.         IF_ENQUEUE(inq, m);
  516.     splx(s);
  517.  
  518. setup:
  519.     /*
  520.      * Reset for next packet.
  521.      */
  522.     addr->en_iba = es->es_ifuba.ifu_r.ifrw_info;
  523.     addr->en_iwc = -(sizeof (struct en_header) + ENMRU) >> 1;
  524.     addr->en_istat = EN_IEN|EN_GO;
  525. }
  526.  
  527. /*
  528.  * Ethernet output routine.
  529.  * Encapsulate a packet of type family for the local net.
  530.  * Use trailer local net encapsulation if enough data in first
  531.  * packet leaves a multiple of 512 bytes of data in remainder.
  532.  */
  533. oldenoutput(ifp, m0, dst)
  534.     struct ifnet *ifp;
  535.     struct mbuf *m0;
  536.     struct sockaddr *dst;
  537. {
  538.     int type, dest, s, error;
  539.     register struct mbuf *m = m0;
  540.     register struct en_header *en;
  541.     register int off;
  542.  
  543.     if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
  544.         error = ENETDOWN;
  545.         goto bad;
  546.     }
  547.     switch (dst->sa_family) {
  548.  
  549. #ifdef INET
  550.     case AF_INET:
  551.         {
  552.         struct in_addr in;
  553.  
  554.         in = ((struct sockaddr_in *)dst)->sin_addr;
  555.         if (in_broadcast(in))
  556.             dest = EN_BROADCAST;
  557.         else
  558.             dest = in_lnaof(in);
  559.         }
  560.         if (dest >= 0x100) {
  561.             error = EPERM;        /* ??? */
  562.             goto bad;
  563.         }
  564.         off = m->m_pkthdr.len - m->m_len;
  565.         /* need per host negotiation */
  566.         if ((ifp->if_flags & IFF_NOTRAILERS) == 0)
  567.         if (off > 0 && (off & 0x1ff) == 0 &&
  568.             (m->m_flags & M_EXT) == 0 &&
  569.             m->m_data >= m->m_pktdat + 2 * sizeof (u_short)) {
  570.             type = ENTYPE_TRAIL + (off>>9);
  571.             m->m_data -= 2 * sizeof (u_short);
  572.             m->m_len += 2 * sizeof (u_short);
  573.             *mtod(m, u_short *) = htons((u_short)ENTYPE_IP);
  574.             *(mtod(m, u_short *) + 1) = ntohs((u_short)m->m_len);
  575.             goto gottrailertype;
  576.         }
  577.         type = ENTYPE_IP;
  578.         off = 0;
  579.         goto gottype;
  580. #endif
  581. #ifdef NS
  582.     case AF_NS:
  583.     {
  584.         u_char *up;
  585.  
  586.         type = ETHERTYPE_NS;
  587.         up = ((struct sockaddr_ns *)dst)->sns_addr.x_host.c_host;
  588.         if (*up & 1)
  589.             dest = EN_BROADCAST;
  590.         else
  591.             dest = up[5];
  592.  
  593.         off = 0;
  594.         goto gottype;
  595.     }
  596. #endif
  597. #ifdef PUP
  598.     case AF_PUP:
  599.         dest = ((struct sockaddr_pup *)dst)->spup_host;
  600.         type = ENTYPE_PUP;
  601.         off = 0;
  602.         goto gottype;
  603. #endif
  604.  
  605. #ifdef notdef
  606.     case AF_ETHERLINK:
  607.         goto gotheader;
  608. #endif
  609.  
  610.     default:
  611.         printf("en%d: can't handle af%d\n", ifp->if_unit,
  612.             dst->sa_family);
  613.         error = EAFNOSUPPORT;
  614.         goto bad;
  615.     }
  616.  
  617. gottrailertype:
  618.     /*
  619.      * Packet to be sent as trailer: move first packet
  620.      * (control information) to end of chain.
  621.      */
  622.     while (m->m_next)
  623.         m = m->m_next;
  624.     m->m_next = m0;
  625.     m = m0->m_next;
  626.     m0->m_next = 0;
  627.     m0 = m;
  628.  
  629. gottype:
  630.     /*
  631.      * Add local net header.  If no space in first mbuf,
  632.      * allocate another.
  633.      */
  634.     M_PREPEND(m, sizeof (struct en_header), M_DONTWAIT);
  635.     if (m == NULL)
  636.         return (ENOBUFS);
  637.     en = mtod(m, struct en_header *);
  638.     /* add en_shost later */
  639.     en->en_dhost = dest;
  640.     en->en_type = htons((u_short)type);
  641.  
  642. #ifdef notdef
  643. gotheader:
  644. #endif
  645.     /*
  646.      * Queue message on interface, and start output if interface
  647.      * not yet active.
  648.      */
  649.     s = splimp();
  650.     if (IF_QFULL(&ifp->if_snd)) {
  651.         IF_DROP(&ifp->if_snd);
  652.         error = ENOBUFS;
  653.         goto qfull;
  654.     }
  655.     IF_ENQUEUE(&ifp->if_snd, m);
  656.     if (en_softc[ifp->if_unit].es_oactive == 0)
  657.         enstart(ifp->if_unit);
  658.     splx(s);
  659.     return (0);
  660. qfull:
  661.     m0 = m;
  662.     splx(s);
  663. bad:
  664.     m_freem(m0);
  665.     return (error);
  666. }
  667.  
  668. /*
  669.  * Process an ioctl request.
  670.  */
  671. enioctl(ifp, cmd, data)
  672.     register struct ifnet *ifp;
  673.     int cmd;
  674.     caddr_t data;
  675. {
  676.     register struct en_softc *es = ((struct en_softc *)ifp);
  677.     struct ifaddr *ifa = (struct ifaddr *) data;
  678.     int s = splimp(), error = 0;
  679.     struct endevice *enaddr;
  680.  
  681.     switch (cmd) {
  682.  
  683.     case SIOCSIFADDR:
  684.         enaddr = (struct endevice *)eninfo[ifp->if_unit]->ui_addr;
  685.         es->es_host = (~enaddr->en_addr) & 0xff;
  686.         /*
  687.          * Attempt to check agreement of protocol address
  688.          * and board address.
  689.          */
  690.         switch (ifa->ifa_addr->sa_family) {
  691.         case AF_INET:
  692.             if (in_lnaof(IA_SIN(ifa)->sin_addr) != es->es_host)
  693.                 return (EADDRNOTAVAIL);
  694.             break;
  695. #ifdef NS
  696.         case AF_NS:
  697.             if (IA_SNS(ifa)->sns_addr.x_host.c_host[5]
  698.                             != es->es_host)
  699.                 return (EADDRNOTAVAIL);
  700.             es->es_nsactive = 1;
  701.             break;
  702. #endif
  703.         }
  704.         ifp->if_flags |= IFF_UP;
  705.         if ((ifp->if_flags & IFF_RUNNING) == 0)
  706.             eninit(ifp->if_unit);
  707.         break;
  708.  
  709.     default:
  710.         error = EINVAL;
  711.         break;
  712.     }
  713.     splx(s);
  714.     return (error);
  715. }
  716.  
  717. #ifdef ENF_SWABIPS
  718. /*
  719.  * Swab bytes
  720.  * Jeffrey Mogul, Stanford
  721.  */
  722. enswab(from, to, n)
  723.     register unsigned char *from, *to;
  724.     register int n;
  725. {
  726.     register unsigned long temp;
  727.  
  728.     if ((n <= 0) || (n > 0xFFFF)) {
  729.         printf("enswab: bad len %d\n", n);
  730.         return;
  731.     }
  732.     
  733.     n >>= 1; n++;
  734. #define    STEP    {temp = *from++;*to++ = *from++;*to++ = temp;}
  735.     /* round to multiple of 8 */
  736.     while ((--n) & 07)
  737.         STEP;
  738.     n >>= 3;
  739.     while (--n >= 0) {
  740.         STEP; STEP; STEP; STEP;
  741.         STEP; STEP; STEP; STEP;
  742.     }
  743. }
  744. #endif
  745. #endif
  746.