home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / vax / if / if_ec.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-08  |  21.3 KB  |  829 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_ec.c    7.8 (Berkeley) 12/16/90
  34.  */
  35.  
  36. #include "ec.h"
  37. #if NEC > 0
  38.  
  39. /*
  40.  * 3Com Ethernet 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/syslog.h"
  51. #include "sys/vmmac.h"
  52. #include "sys/ioctl.h"
  53. #include "sys/errno.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_ecreg.h"
  75. #include "if_uba.h"
  76. #include "../uba/ubareg.h"
  77. #include "../uba/ubavar.h"
  78.  
  79. #if CLSIZE == 2
  80. #define ECBUFSIZE    32        /* on-board memory, clusters */
  81. #endif
  82.  
  83. int    ecubamem(), ecprobe(), ecattach(), ecrint(), ecxint(), eccollide();
  84. struct    uba_device *ecinfo[NEC];
  85. u_short ecstd[] = { 0 };
  86. struct    uba_driver ecdriver =
  87.     { ecprobe, 0, ecattach, 0, ecstd, "ec", ecinfo, 0, 0, 0, 0, ecubamem };
  88.  
  89. int    ecinit(),ecioctl(),ecstart(),ecreset(),ether_output();
  90. struct    mbuf *ecget();
  91.  
  92. extern struct ifnet loif;
  93.  
  94. /*
  95.  * Ethernet software status per interface.
  96.  *
  97.  * Each interface is referenced by a network interface structure,
  98.  * es_if, which the routing code uses to locate the interface.
  99.  * This structure contains the output queue for the interface, its address, ...
  100.  * We also have, for each interface, a UBA interface structure, which
  101.  * contains information about the UNIBUS resources held by the interface:
  102.  * map registers, buffered data paths, etc.  Information is cached in this
  103.  * structure for use by the if_uba.c routines in running the interface
  104.  * efficiently.
  105.  */
  106. struct    ec_softc {
  107.     struct    arpcom es_ac;        /* common Ethernet structures */
  108. #define    es_if    es_ac.ac_if        /* network-visible interface */
  109. #define    es_addr    es_ac.ac_enaddr        /* hardware Ethernet address */
  110.     struct    ifuba es_ifuba;        /* UNIBUS resources */
  111.     short    es_mask;        /* mask for current output delay */
  112.     u_char    *es_buf[16];        /* virtual addresses of buffers */
  113. } ec_softc[NEC];
  114.  
  115. /*
  116.  * Configure on-board memory for an interface.
  117.  * Called from autoconfig and after a uba reset.
  118.  * The address of the memory on the uba is supplied in the device flags.
  119.  */
  120. ecubamem(ui, uban)
  121.     register struct uba_device *ui;
  122. {
  123.     register caddr_t ecbuf = (caddr_t) &umem[uban][ui->ui_flags];
  124.     register struct ecdevice *addr = (struct ecdevice *)ui->ui_addr;
  125.  
  126.     /*
  127.      * Make sure csr is there (we run before ecprobe).
  128.      */
  129.     if (badaddr((caddr_t)addr, 2))
  130.         return (-1);
  131. #if VAX780
  132.     if (cpu == VAX_780 && uba_hd[uban].uh_uba->uba_sr) {
  133.         uba_hd[uban].uh_uba->uba_sr = uba_hd[uban].uh_uba->uba_sr;
  134.         return (-1);
  135.     }
  136. #endif
  137.     /*
  138.      * Make sure memory is turned on
  139.      */
  140.     addr->ec_rcr = EC_AROM;
  141.     /*
  142.      * Tell the system that the board has memory here, so it won't
  143.      * attempt to allocate the addresses later.
  144.      */
  145.     if (ubamem(uban, ui->ui_flags, ECBUFSIZE*CLSIZE, 1) == 0) {
  146.         printf("ec%d: cannot reserve uba addresses\n", ui->ui_unit);
  147.         addr->ec_rcr = EC_MDISAB;    /* disable memory */
  148.         return (-1);
  149.     }
  150.     /*
  151.      * Check for existence of buffers on Unibus.
  152.      */
  153.     if (badaddr((caddr_t)ecbuf, 2)) {
  154. bad:
  155.         printf("ec%d: buffer mem not found\n", ui->ui_unit);
  156.         (void) ubamem(uban, ui->ui_flags, ECBUFSIZE*2, 0);
  157.         addr->ec_rcr = EC_MDISAB;    /* disable memory */
  158.         return (-1);
  159.     }
  160. #if VAX780
  161.     if (cpu == VAX_780 && uba_hd[uban].uh_uba->uba_sr) {
  162.         uba_hd[uban].uh_uba->uba_sr = uba_hd[uban].uh_uba->uba_sr;
  163.         goto bad;
  164.     }
  165. #endif
  166.     if (ui->ui_alive == 0)        /* Only printf from autoconfig */
  167.         printf("ec%d: mem %x-%x\n", ui->ui_unit,
  168.             ui->ui_flags, ui->ui_flags + ECBUFSIZE*CLBYTES - 1);
  169.     ui->ui_type = 1;        /* Memory on, allocated */
  170.     return (0);
  171. }
  172.  
  173. /*
  174.  * Do output DMA to determine interface presence and
  175.  * interrupt vector.  DMA is too short to disturb other hosts.
  176.  */
  177. ecprobe(reg, ui)
  178.     caddr_t reg;
  179.     struct uba_device *ui;
  180. {
  181.     register int br, cvec;        /* r11, r10 value-result */
  182.     register struct ecdevice *addr = (struct ecdevice *)reg;
  183.     register caddr_t ecbuf = (caddr_t) &umem[ui->ui_ubanum][ui->ui_flags];
  184.  
  185. #ifdef lint
  186.     br = 0; cvec = br; br = cvec;
  187.     ecrint(0); ecxint(0); eccollide(0);
  188. #endif
  189.  
  190.     /*
  191.      * Check that buffer memory was found and enabled.
  192.      */
  193.     if (ui->ui_type == 0)
  194.         return(0);
  195.     /*
  196.      * Make a one byte packet in what should be buffer #0.
  197.      * Submit it for sending.  This should cause an xmit interrupt.
  198.      * The xmit interrupt vector is 8 bytes after the receive vector,
  199.      * so adjust for this before returning.
  200.      */
  201.     *(u_short *)ecbuf = (u_short) 03777;
  202.     ecbuf[03777] = '\0';
  203.     addr->ec_xcr = EC_XINTEN|EC_XWBN;
  204.     DELAY(100000);
  205.     addr->ec_xcr = EC_XCLR;
  206.     if (cvec > 0 && cvec != 0x200) {
  207.         if (cvec & 04) {    /* collision interrupt */
  208.             cvec -= 04;
  209.             br += 1;        /* rcv is collision + 1 */
  210.         } else {        /* xmit interrupt */
  211.             cvec -= 010;
  212.             br += 2;        /* rcv is xmit + 2 */
  213.         }
  214.     }
  215.     return (1);
  216. }
  217.  
  218. /*
  219.  * Interface exists: make available by filling in network interface
  220.  * record.  System will initialize the interface when it is ready
  221.  * to accept packets.
  222.  */
  223. ecattach(ui)
  224.     struct uba_device *ui;
  225. {
  226.     struct ec_softc *es = &ec_softc[ui->ui_unit];
  227.     register struct ifnet *ifp = &es->es_if;
  228.     register struct ecdevice *addr = (struct ecdevice *)ui->ui_addr;
  229.     int i, j;
  230.     u_char *cp;
  231.  
  232.     ifp->if_unit = ui->ui_unit;
  233.     ifp->if_name = "ec";
  234.     ifp->if_mtu = ETHERMTU;
  235.  
  236.     /*
  237.      * Read the ethernet address off the board, one nibble at a time.
  238.      */
  239.     addr->ec_xcr = EC_UECLR; /* zero address pointer */
  240.     addr->ec_rcr = EC_AROM;
  241.     cp = es->es_addr;
  242. #define    NEXTBIT    addr->ec_rcr = EC_AROM|EC_ASTEP; addr->ec_rcr = EC_AROM
  243.     for (i=0; i < sizeof (es->es_addr); i++) {
  244.         *cp = 0;
  245.         for (j=0; j<=4; j+=4) {
  246.             *cp |= ((addr->ec_rcr >> 8) & 0xf) << j;
  247.             NEXTBIT; NEXTBIT; NEXTBIT; NEXTBIT;
  248.         }
  249.         cp++;
  250.     }
  251.     printf("ec%d: hardware address %s\n", ui->ui_unit,
  252.         ether_sprintf(es->es_addr));
  253.     ifp->if_init = ecinit;
  254.     ifp->if_ioctl = ecioctl;
  255.     ifp->if_output = ether_output;
  256.     ifp->if_start = ecstart;
  257.     ifp->if_reset = ecreset;
  258.     ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
  259.     for (i=0; i<16; i++)
  260.         es->es_buf[i] 
  261.             = (u_char *)&umem[ui->ui_ubanum][ui->ui_flags + 2048*i];
  262.     if_attach(ifp);
  263. }
  264.  
  265. /*
  266.  * Reset of interface after UNIBUS reset.
  267.  * If interface is on specified uba, reset its state.
  268.  */
  269. ecreset(unit, uban)
  270.     int unit, uban;
  271. {
  272.     register struct uba_device *ui;
  273.  
  274.     if (unit >= NEC || (ui = ecinfo[unit]) == 0 || ui->ui_alive == 0 ||
  275.         ui->ui_ubanum != uban)
  276.         return;
  277.     printf(" ec%d", unit);
  278.     ec_softc[unit].es_if.if_flags &= ~IFF_RUNNING;
  279.     ecinit(unit);
  280. }
  281.  
  282. /*
  283.  * Initialization of interface; clear recorded pending
  284.  * operations, and reinitialize UNIBUS usage.
  285.  */
  286. ecinit(unit)
  287.     int unit;
  288. {
  289.     struct ec_softc *es = &ec_softc[unit];
  290.     struct ecdevice *addr;
  291.     register struct ifnet *ifp = &es->es_if;
  292.     int i, s;
  293.  
  294.     /* not yet, if address still unknown */
  295.     if (ifp->if_addrlist == (struct ifaddr *)0)
  296.         return;
  297.  
  298.     /*
  299.      * Hang receive buffers and start any pending writes.
  300.      * Writing into the rcr also makes sure the memory
  301.      * is turned on.
  302.      */
  303.     if ((ifp->if_flags & IFF_RUNNING) == 0) {
  304.         u_short start_read;
  305.         addr = (struct ecdevice *)ecinfo[unit]->ui_addr;
  306.         s = splimp();
  307.         /*
  308.          * write our ethernet address into the address recognition ROM 
  309.          * so we can always use the same EC_READ bits (referencing ROM),
  310.          * in case we change the address sometime.
  311.          * Note that this is safe here as the receiver is NOT armed.
  312.          */
  313.         ec_setaddr(es->es_addr, unit);
  314.         /*
  315.          * Arm the receiver
  316. #ifdef MULTI
  317.         if (es->es_if.if_flags & IFF_PROMISC)
  318.             start_read = EC_PROMISC;
  319.         else if (es->es_if.if_flags & IFF_MULTI)
  320.             start_read = EC_MULTI;
  321.         else
  322. #endif MULTI
  323.             start_read = EC_READ;
  324.          */
  325.         for (i = ECRHBF; i >= ECRLBF; i--)
  326.             addr->ec_rcr = EC_READ | i;
  327.         es->es_if.if_flags &= ~IFF_OACTIVE;
  328.         es->es_mask = ~0;
  329.         es->es_if.if_flags |= IFF_RUNNING;
  330.         if (es->es_if.if_snd.ifq_head)
  331.             (void) ecstart(&es->es_if);
  332.         splx(s);
  333.     }
  334. }
  335.  
  336. /*
  337.  * Start output on interface.  Get another datagram to send
  338.  * off of the interface queue, and copy it to the interface
  339.  * before starting the output.
  340.  */
  341. ecstart(ifp)
  342. struct ifnet *ifp;
  343. {
  344.     int unit = ifp->if_unit;
  345.     register struct ec_softc *es = &ec_softc[unit];
  346.     struct ecdevice *addr;
  347.     struct mbuf *m;
  348.  
  349.     if ((es->es_if.if_flags & IFF_RUNNING) == 0)
  350.         return (0);
  351.     IF_DEQUEUE(&es->es_if.if_snd, m);
  352.     if (m == 0)
  353.         return (0);
  354.     ecput(es->es_buf[ECTBF], m);
  355.     addr = (struct ecdevice *)ecinfo[unit]->ui_addr;
  356.     addr->ec_xcr = EC_WRITE|ECTBF;
  357.     es->es_if.if_flags |= IFF_OACTIVE;
  358.     return (0);
  359. }
  360.  
  361. /*
  362.  * Ethernet interface transmitter interrupt.
  363.  * Start another output if more data to send.
  364.  */
  365. ecxint(unit)
  366.     int unit;
  367. {
  368.     register struct ec_softc *es = &ec_softc[unit];
  369.     register struct ecdevice *addr =
  370.         (struct ecdevice *)ecinfo[unit]->ui_addr;
  371.  
  372.     if ((es->es_if.if_flags & IFF_OACTIVE) == 0)
  373.         return;
  374.     if ((addr->ec_xcr&EC_XDONE) == 0 || (addr->ec_xcr&EC_XBN) != ECTBF) {
  375.         printf("ec%d: stray xmit interrupt, xcr=%b\n", unit,
  376.             addr->ec_xcr, EC_XBITS);
  377.         es->es_if.if_flags &= ~IFF_OACTIVE;
  378.         addr->ec_xcr = EC_XCLR;
  379.         return;
  380.     }
  381.     es->es_if.if_opackets++;
  382.     es->es_if.if_flags &= ~IFF_OACTIVE;
  383.     es->es_mask = ~0;
  384.     addr->ec_xcr = EC_XCLR;
  385.     if (es->es_if.if_snd.ifq_head)
  386.         (void) ecstart(&es->es_if);
  387. }
  388.  
  389. /*
  390.  * Collision on ethernet interface.  Do exponential
  391.  * backoff, and retransmit.  If have backed off all
  392.  * the way print warning diagnostic, and drop packet.
  393.  */
  394. eccollide(unit)
  395.     int unit;
  396. {
  397.     register struct ec_softc *es = &ec_softc[unit];
  398.     register struct ecdevice *addr =
  399.         (struct ecdevice *)ecinfo[unit]->ui_addr;
  400.     register i;
  401.     int delay;
  402.  
  403.     es->es_if.if_collisions++;
  404.     if ((es->es_if.if_flags & IFF_OACTIVE) == 0)
  405.         return;
  406.  
  407.     /*
  408.      * Es_mask is a 16 bit number with n low zero bits, with
  409.      * n the number of backoffs.  When es_mask is 0 we have
  410.      * backed off 16 times, and give up.
  411.      */
  412.     if (es->es_mask == 0) {
  413.         u_short start_read;
  414.         es->es_if.if_oerrors++;
  415.         log(LOG_ERR, "ec%d: send error\n", unit);
  416.         /*
  417.          * Reset interface, then requeue rcv buffers.
  418.          * Some incoming packets may be lost, but that
  419.          * can't be helped.
  420.          */
  421.         addr->ec_xcr = EC_UECLR;
  422. #ifdef MULTI
  423.         if (es->es_if.if_flags & IFF_PROMISC)
  424.             start_read = EC_PROMISC;
  425.         else if (es->es_if.if_flags & IFF_MULTI)
  426.             start_read = EC_MULTI;
  427.         else
  428. #endif MULTI
  429.             start_read = EC_READ;
  430.         for (i=ECRHBF; i>=ECRLBF; i--)
  431.             addr->ec_rcr = start_read|i;
  432.         /*
  433.          * Reset and transmit next packet (if any).
  434.          */
  435.         es->es_if.if_flags &= ~IFF_OACTIVE;
  436.         es->es_mask = ~0;
  437.         if (es->es_if.if_snd.ifq_head)
  438.             (void) ecstart(&es->es_if);
  439.         return;
  440.     }
  441.     /*
  442.      * Do exponential backoff.  Compute delay based on low bits
  443.      * of the interval timer (1 bit for each transmission attempt,
  444.      * but at most 5 bits).  Then delay for that number of
  445.      * slot times.  A slot time is 51.2 microseconds (rounded to 51).
  446.      * This does not take into account the time already used to
  447.      * process the interrupt.
  448.      */
  449.     es->es_mask <<= 1;
  450.     delay = mfpr(ICR) & 0x1f &~ es->es_mask;
  451.     DELAY(delay * 51);
  452.     /*
  453.      * Clear the controller's collision flag, thus enabling retransmit.
  454.      */
  455.     addr->ec_xcr = EC_CLEAR;
  456. }
  457.  
  458. /*
  459.  * Ethernet interface receiver interrupt.
  460.  * If input error just drop packet.
  461.  * Otherwise examine 
  462.  * packet to determine type.  If can't determine length
  463.  * from type, then have to drop packet.  Othewise decapsulate
  464.  * packet based on type and pass to type specific higher-level
  465.  * input routine.
  466.  */
  467. ecrint(unit)
  468.     int unit;
  469. {
  470.     struct ecdevice *addr = (struct ecdevice *)ecinfo[unit]->ui_addr;
  471.  
  472.     while (addr->ec_rcr & EC_RDONE)
  473.         ecread(unit);
  474. }
  475.  
  476. ecread(unit)
  477.     int unit;
  478. {
  479.     register struct ec_softc *es = &ec_softc[unit];
  480.     struct ecdevice *addr = (struct ecdevice *)ecinfo[unit]->ui_addr;
  481.     register struct ether_header *ec;
  482.         struct mbuf *m;
  483.     int len, off, resid, ecoff, rbuf;
  484.     register struct ifqueue *inq;
  485.     u_short start_read;
  486.     u_char *ecbuf;
  487.  
  488.     es->es_if.if_ipackets++;
  489.     rbuf = addr->ec_rcr & EC_RBN;
  490.     if (rbuf < ECRLBF || rbuf > ECRHBF)
  491.         panic("ecrint");
  492.     ecbuf = es->es_buf[rbuf];
  493.     ecoff = *(short *)ecbuf;
  494.     if (ecoff <= ECRDOFF || ecoff > 2046) {
  495.         es->es_if.if_ierrors++;
  496. #ifdef notdef
  497.         if (es->es_if.if_ierrors % 100 == 0)
  498.             printf("ec%d: += 100 input errors\n", unit);
  499. #endif
  500.         goto setup;
  501.     }
  502.  
  503.     /*
  504.      * Get input data length.
  505.      * Get pointer to ethernet header (in input buffer).
  506.      * Deal with trailer protocol: if type is trailer type
  507.      * get true type from first 16-bit word past data.
  508.      * Remember that type was trailer by setting off.
  509.      */
  510.     len = ecoff - ECRDOFF - sizeof (struct ether_header);
  511.     ec = (struct ether_header *)(ecbuf + ECRDOFF);
  512.     ec->ether_type = ntohs((u_short)ec->ether_type);
  513. #define    ecdataaddr(ec, off, type)    ((type)(((caddr_t)((ec)+1)+(off))))
  514.     if (ec->ether_type >= ETHERTYPE_TRAIL &&
  515.         ec->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
  516.         off = (ec->ether_type - ETHERTYPE_TRAIL) * 512;
  517.         if (off >= ETHERMTU)
  518.             goto setup;        /* sanity */
  519.         ec->ether_type = ntohs(*ecdataaddr(ec, off, u_short *));
  520.         resid = ntohs(*(ecdataaddr(ec, off+2, u_short *)));
  521.         if (off + resid > len)
  522.             goto setup;        /* sanity */
  523.         len = off + resid;
  524.     } else
  525.         off = 0;
  526.     if (len == 0)
  527.         goto setup;
  528.  
  529.     /*
  530.      * Pull packet off interface.  Off is nonzero if packet
  531.      * has trailing header; ecget will then force this header
  532.      * information to be at the front, but we still have to drop
  533.      * the type and length which are at the front of any trailer data.
  534.      */
  535.     m = ecget(ecbuf, len, off, &es->es_if);
  536.     if (m)
  537.         ether_input(&es->es_if, ec, m);
  538.     /*
  539.      * Reset for next packet.
  540.      */
  541. setup:
  542. #ifdef MULTI
  543.         if (es->es_if.if_flags & IFF_PROMISC)
  544.             start_read = EC_PROMISC;
  545.         else if (es->es_if.if_flags & IFF_MULTI)
  546.             start_read = EC_MULTI;
  547.         else
  548. #endif MULTI
  549.             start_read = EC_READ;
  550.     addr->ec_rcr = start_read|EC_RCLR|rbuf;
  551. }
  552.  
  553. /*
  554.  * Routine to copy from mbuf chain to transmit
  555.  * buffer in UNIBUS memory.
  556.  * If packet size is less than the minimum legal size,
  557.  * the buffer is expanded.  We probably should zero out the extra
  558.  * bytes for security, but that would slow things down.
  559.  */
  560. ecput(ecbuf, m)
  561.     u_char *ecbuf;
  562.     struct mbuf *m;
  563. {
  564.     register struct mbuf *mp;
  565.     register int off;
  566.     u_char *bp;
  567.  
  568.     for (off = 2048, mp = m; mp; mp = mp->m_next)
  569.         off -= mp->m_len;
  570.     if (2048 - off < ETHERMIN + sizeof (struct ether_header))
  571.         off = 2048 - ETHERMIN - sizeof (struct ether_header);
  572.     *(u_short *)ecbuf = off;
  573.     bp = (u_char *)(ecbuf + off);
  574.     for (mp = m; mp; mp = mp->m_next) {
  575.         register unsigned len = mp->m_len;
  576.         u_char *mcp;
  577.  
  578.         if (len == 0)
  579.             continue;
  580.         mcp = mtod(mp, u_char *);
  581.         if ((unsigned)bp & 01) {
  582.             *bp++ = *mcp++;
  583.             len--;
  584.         }
  585.         if (off = (len >> 1)) {
  586.             register u_short *to, *from;
  587.  
  588.             to = (u_short *)bp;
  589.             from = (u_short *)mcp;
  590.             do
  591.                 *to++ = *from++;
  592.             while (--off > 0);
  593.             bp = (u_char *)to,
  594.             mcp = (u_char *)from;
  595.         }
  596.         if (len & 01)
  597.             *bp++ = *mcp++;
  598.     }
  599.     m_freem(m);
  600. }
  601.  
  602. /*
  603.  * Routine to copy from UNIBUS memory into mbufs.
  604.  * Similar in spirit to if_rubaget.
  605.  *
  606.  * Warning: This makes the fairly safe assumption that
  607.  * mbufs have even lengths.
  608.  */
  609. struct mbuf *
  610. ecget(ecbuf, totlen, off0, ifp)
  611.     u_char *ecbuf;
  612.     int totlen, off0;
  613.     struct ifnet *ifp;
  614. {
  615.     register struct mbuf *m;
  616.     struct mbuf *top = 0, **mp = ⊤
  617.     register int off = off0, len;
  618.     u_char *cp = (ecbuf += ECRDOFF + sizeof (struct ether_header));
  619.     u_char *packet_end = cp + totlen;
  620.  
  621.     if (off) {
  622.         off += 2 * sizeof(u_short);
  623.         totlen -= 2 *sizeof(u_short);
  624.         cp += off;
  625.     }
  626.  
  627.     MGETHDR(m, M_DONTWAIT, MT_DATA);
  628.     if (m == 0)
  629.         return (0);
  630.     m->m_pkthdr.rcvif = ifp;
  631.     m->m_pkthdr.len = totlen;
  632.     m->m_len = MHLEN;
  633.  
  634.     while (totlen > 0) {
  635.         register int words;
  636.         u_char *mcp;
  637.  
  638.         if (top) {
  639.             MGET(m, M_DONTWAIT, MT_DATA);
  640.             if (m == 0) {
  641.                 m_freem(top);
  642.                 return (0);
  643.             }
  644.             m->m_len = MLEN;
  645.         }
  646.         len = min(totlen, (packet_end - cp));
  647.         if (len >= MINCLSIZE) {
  648.             MCLGET(m, M_DONTWAIT);
  649.             if (m->m_flags & M_EXT)
  650.                 m->m_len = len = min(len, MCLBYTES);
  651.             else
  652.                 len = m->m_len;
  653.         } else {
  654.             /*
  655.              * Place initial small packet/header at end of mbuf.
  656.              */
  657.             if (len < m->m_len) {
  658.                 if (top == 0 && len + max_linkhdr <= m->m_len)
  659.                     m->m_data += max_linkhdr;
  660.                 m->m_len = len;
  661.             } else
  662.                 len = m->m_len;
  663.         }
  664.         mcp = mtod(m, u_char *);
  665.         if (words = (len >> 1)) {
  666.             register u_short *to, *from;
  667.  
  668.             to = (u_short *)mcp;
  669.             from = (u_short *)cp;
  670.             do
  671.                 *to++ = *from++;
  672.             while (--words > 0);
  673.             mcp = (u_char *)to;
  674.             cp = (u_char *)from;
  675.         }
  676.         if (len & 01)
  677.             *mcp++ = *cp++;
  678.         *mp = m;
  679.         mp = &m->m_next;
  680.         totlen -= len;
  681.         if (cp == packet_end)
  682.             cp = ecbuf;
  683.     }
  684.     return (top);
  685. bad:
  686.     m_freem(top);
  687.     return (0);
  688. }
  689.  
  690. /*
  691.  * Process an ioctl request.
  692.  */
  693. ecioctl(ifp, cmd, data)
  694.     register struct ifnet *ifp;
  695.     int cmd;
  696.     caddr_t data;
  697. {
  698.     register struct ifaddr *ifa = (struct ifaddr *)data;
  699.     struct ec_softc *es = &ec_softc[ifp->if_unit];
  700.     struct ecdevice *addr;
  701.     int s = splimp(), error = 0;
  702.  
  703.     addr = (struct ecdevice *)(ecinfo[ifp->if_unit]->ui_addr);
  704.  
  705.     switch (cmd) {
  706.  
  707.     case SIOCSIFADDR:
  708.         ifp->if_flags |= IFF_UP;
  709.  
  710.         switch (ifa->ifa_addr->sa_family) {
  711. #ifdef INET
  712.         case AF_INET:
  713.             ecinit(ifp->if_unit);    /* before arpwhohas */
  714.             ((struct arpcom *)ifp)->ac_ipaddr =
  715.                 IA_SIN(ifa)->sin_addr;
  716.             arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
  717.             break;
  718. #endif
  719. #ifdef NS
  720.         case AF_NS:
  721.             {
  722.             register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
  723.  
  724.             if (ns_nullhost(*ina))
  725.                 ina->x_host = *(union ns_host *)(es->es_addr);
  726.             else {
  727.                 /* 
  728.                  * The manual says we can't change the address 
  729.                  * while the receiver is armed,
  730.                  * so reset everything
  731.                  */
  732.                 ifp->if_flags &= ~IFF_RUNNING; 
  733.                 bcopy((caddr_t)ina->x_host.c_host,
  734.                     (caddr_t)es->es_addr, sizeof(es->es_addr));
  735.             }
  736.             ecinit(ifp->if_unit); /* does ec_setaddr() */
  737.             break;
  738.             }
  739. #endif
  740.         default:
  741.             ecinit(ifp->if_unit);
  742.             break;
  743.         }
  744.         break;
  745.  
  746.     case SIOCSIFFLAGS:
  747.         if ((ifp->if_flags & IFF_UP) == 0 &&
  748.             ifp->if_flags & IFF_RUNNING) {
  749.             addr->ec_xcr = EC_UECLR;
  750.             ifp->if_flags &= ~IFF_RUNNING;
  751.         } else if (ifp->if_flags & IFF_UP &&
  752.             (ifp->if_flags & IFF_RUNNING) == 0)
  753.             ecinit(ifp->if_unit);
  754.         break;
  755.  
  756.     default:
  757.         error = EINVAL;
  758.     }
  759.     splx(s);
  760.     return (error);
  761. }
  762.  
  763. ec_setaddr(physaddr,unit)
  764.     u_char *physaddr;
  765.     int unit;
  766. {
  767.     struct ec_softc *es = &ec_softc[unit];
  768.     struct uba_device *ui = ecinfo[unit];
  769.     register struct ecdevice *addr = (struct ecdevice *)ui->ui_addr;
  770.     register char nibble;
  771.     register int i, j;
  772.  
  773.     /*
  774.      * Use the ethernet address supplied
  775.      * Note that we do a UECLR here, so the receive buffers
  776.      * must be requeued.
  777.      */
  778.     
  779. #ifdef DEBUG
  780.     printf("ec_setaddr: setting address for unit %d = %s",
  781.         unit, ether_sprintf(physaddr));
  782. #endif
  783.     addr->ec_xcr = EC_UECLR;
  784.     addr->ec_rcr = 0;
  785.     /* load requested address */
  786.     for (i = 0; i < 6; i++) { /* 6 bytes of address */
  787.         es->es_addr[i] = physaddr[i];
  788.         nibble = physaddr[i] & 0xf; /* lower nibble */
  789.         addr->ec_rcr = (nibble << 8);
  790.         addr->ec_rcr = (nibble << 8) + EC_AWCLK; /* latch nibble */
  791.         addr->ec_rcr = (nibble << 8);
  792.         for (j=0; j < 4; j++) {
  793.         addr->ec_rcr = 0;
  794.         addr->ec_rcr = EC_ASTEP; /* step counter */
  795.         addr->ec_rcr = 0;
  796.         }
  797.         nibble = (physaddr[i] >> 4) & 0xf; /* upper nibble */
  798.         addr->ec_rcr = (nibble << 8);
  799.         addr->ec_rcr = (nibble << 8) + EC_AWCLK; /* latch nibble */
  800.         addr->ec_rcr = (nibble << 8);
  801.         for (j=0; j < 4; j++) {
  802.         addr->ec_rcr = 0;
  803.         addr->ec_rcr = EC_ASTEP; /* step counter */
  804.         addr->ec_rcr = 0;
  805.         }
  806.     }
  807. #ifdef DEBUG
  808.     /*
  809.      * Read the ethernet address off the board, one nibble at a time.
  810.      */
  811.     addr->ec_xcr = EC_UECLR;
  812.     addr->ec_rcr = 0; /* read RAM */
  813.     cp = es->es_addr;
  814. #undef NEXTBIT
  815. #define    NEXTBIT    addr->ec_rcr = EC_ASTEP; addr->ec_rcr = 0
  816.     for (i=0; i < sizeof (es->es_addr); i++) {
  817.         *cp = 0;
  818.         for (j=0; j<=4; j+=4) {
  819.             *cp |= ((addr->ec_rcr >> 8) & 0xf) << j;
  820.             NEXTBIT; NEXTBIT; NEXTBIT; NEXTBIT;
  821.         }
  822.         cp++;
  823.     }
  824.     printf("ec_setaddr: RAM address for unit %d = %s",
  825.         unit, ether_sprintf(physaddr));
  826. #endif
  827. }
  828. #endif
  829.