home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / i386 / isa / if_we.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-21  |  21.1 KB  |  845 lines

  1. /*-
  2.  * Copyright (c) 1990 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * This code is derived from software contributed to Berkeley by
  6.  * Tim L. Tucker.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. All advertising materials mentioning features or use of this software
  17.  *    must display the following acknowledgement:
  18.  *    This product includes software developed by the University of
  19.  *    California, Berkeley and its contributors.
  20.  * 4. Neither the name of the University nor the names of its contributors
  21.  *    may be used to endorse or promote products derived from this software
  22.  *    without specific prior written permission.
  23.  *
  24.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  *
  36.  *    @(#)if_we.c    7.3 (Berkeley) 5/21/91
  37.  */
  38.  
  39. /*
  40.  * Modification history
  41.  *
  42.  * 8/28/89 - Initial version(if_wd.c), Tim L Tucker
  43.  */
  44.  
  45. #include "we.h"
  46. #if    NWE > 0
  47. /*
  48.  * Western Digital 8003 ethernet/starlan adapter
  49.  *
  50.  * Supports the following interface cards:
  51.  * WD8003E, WD8003EBT, WD8003S, WD8003SBT, WD8013EBT
  52.  *
  53.  * The Western Digital card is one of many AT/MCA ethernet interfaces
  54.  * based on the National DS8390 Network Interface chip set.
  55.  */
  56. #include "param.h"
  57. #include "mbuf.h"
  58. #include "socket.h"
  59. #include "ioctl.h"
  60. #include "errno.h"
  61. #include "syslog.h"
  62.  
  63. #include "net/if.h"
  64. #include "net/netisr.h"
  65.  
  66. #ifdef INET
  67. #include "netinet/in.h"
  68. #include "netinet/in_systm.h"
  69. #include "netinet/in_var.h"
  70. #include "netinet/ip.h"
  71. #include "netinet/if_ether.h"
  72. #endif
  73.  
  74. #ifdef NS
  75. #include "netns/ns.h"
  76. #include "netns/ns_if.h"
  77. #endif
  78.  
  79. #include "i386/isa/if_wereg.h"
  80. #include "i386/isa/isa_device.h"
  81.  
  82. /*
  83.  * This constant should really be 60 because the we adds 4 bytes of crc.
  84.  * However when set to 60 our packets are ignored by deuna's , 3coms are
  85.  * okay ??????????????????????????????????????????
  86.  */
  87. #define ETHER_MIN_LEN 64
  88. #define    ETHER_ADDR_LEN 6
  89. #define ETHER_HDR_SIZE 14
  90.  
  91. /*
  92.  * Ethernet software status per interface.
  93.  *
  94.  * Each interface is referenced by a network interface structure,
  95.  * qe_if, which the routing code uses to locate the interface.
  96.  * This structure contains the output queue for the interface, its address, ...
  97.  */
  98. struct    we_softc {
  99.     struct    arpcom we_ac;        /* Ethernet common part     */
  100. #define    we_if    we_ac.ac_if        /* network-visible interface     */
  101. #define    we_addr    we_ac.ac_enaddr        /* hardware Ethernet address     */
  102.  
  103.     u_char    we_flags;        /* software state        */
  104. #define    WDF_RUNNING    0x01
  105. #define WDF_TXBUSY    0x02
  106.  
  107.     u_char    we_type;        /* interface type code        */
  108.     u_short    we_vector;        /* interrupt vector         */
  109.     short    we_io_ctl_addr;        /* i/o bus address, control    */
  110.     short    we_io_nic_addr;        /* i/o bus address, DS8390    */
  111.  
  112.     caddr_t    we_vmem_addr;        /* card RAM virtual memory base */
  113.     u_long    we_vmem_size;        /* card RAM bytes        */
  114.     caddr_t    we_vmem_ring;        /* receive ring RAM vaddress    */
  115.     caddr_t    we_vmem_end;        /* receive ring RAM end    */
  116. } we_softc[NWE];
  117.  
  118. int    weprobe(), weattach(), weintr(), westart();
  119. int    weinit(), ether_output(), weioctl(), wereset(), wewatchdog();
  120.  
  121. struct    isa_driver wedriver = {
  122.     weprobe, weattach, "we",
  123. };
  124.  
  125. /*
  126.  * Probe the WD8003 to see if it's there
  127.  */
  128. weprobe(is)
  129.     struct isa_device *is;
  130. {
  131.     register int i;
  132.     register struct we_softc *sc = &we_softc[is->id_unit];
  133.     union we_mem_sel wem;
  134.     u_char sum;
  135.  
  136.     /*
  137.      * Here we check the card ROM, if the checksum passes, and the
  138.      * type code and ethernet address check out, then we know we have
  139.      * a wd8003 card.
  140.      *
  141.      * Autoconfiguration: No warning message is printed on error.
  142.      */
  143.     for (sum = 0, i = 0; i < 8; ++i)
  144.         sum += inb(is->id_iobase + WD_ROM_OFFSET + i);
  145.     if (sum != WD_CHECKSUM)
  146.             return (0);
  147.     sc->we_type = inb(is->id_iobase + WD_ROM_OFFSET + 6);
  148.     if ((sc->we_type != WD_ETHER) && (sc->we_type != WD_STARLAN)
  149.     && (sc->we_type != WD_ETHER2))
  150.             return (0);
  151.  
  152.     /*
  153.      * Setup card RAM area and i/o addresses
  154.      * Kernel Virtual to segment C0000-DFFFF?????
  155.      */
  156.     sc->we_io_ctl_addr = is->id_iobase;
  157.     sc->we_io_nic_addr = sc->we_io_ctl_addr + WD_NIC_OFFSET;
  158.     sc->we_vector = is->id_irq;
  159.     sc->we_vmem_addr = (caddr_t)is->id_maddr;
  160.     sc->we_vmem_size = is->id_msize;
  161.     sc->we_vmem_ring = sc->we_vmem_addr + (WD_PAGE_SIZE * WD_TXBUF_SIZE);
  162.     sc->we_vmem_end = sc->we_vmem_addr + is->id_msize;
  163.  
  164.     /*
  165.      * Save board ROM station address
  166.      */
  167.     for (i = 0; i < ETHER_ADDR_LEN; ++i)
  168.         sc->we_addr[i] = inb(sc->we_io_ctl_addr + WD_ROM_OFFSET + i);
  169.  
  170.     /*
  171.      * Mapin interface memory, setup memory select register
  172.      */
  173.     /* wem.ms_addr = (u_long)sc->we_vmem_addr >> 13; */
  174.     wem.ms_addr = (u_long)(0xd0000)>> 13;
  175.     wem.ms_enable = 1;
  176.     wem.ms_reset = 0;
  177.     outb(sc->we_io_ctl_addr, wem.ms_byte);
  178.  
  179.     /*
  180.      * clear interface memory, then sum to make sure its valid
  181.      */
  182.     for (i = 0; i < sc->we_vmem_size; ++i)
  183.         sc->we_vmem_addr[i] = 0x0;
  184.     for (sum = 0, i = 0; i < sc->we_vmem_size; ++i)
  185.         sum += sc->we_vmem_addr[i];
  186.     if (sum != 0x0) {
  187.             printf("we%d: wd8003 dual port RAM address error\n", is->id_unit);
  188.         return (0);
  189.     }
  190.  
  191.     return (WD_IO_PORTS);
  192. }
  193.  
  194. /*
  195.  * Interface exists: make available by filling in network interface
  196.  * record.  System will initialize the interface when it is ready
  197.  * to accept packets.
  198.  */
  199. weattach(is)
  200.     struct isa_device *is;
  201. {
  202.     register struct we_softc *sc = &we_softc[is->id_unit];
  203.     register struct ifnet *ifp = &sc->we_if;
  204.     union we_command wecmd;
  205.  
  206.     wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND);
  207.     wecmd.cs_stp = 1;
  208.     wecmd.cs_sta = 0;
  209.     wecmd.cs_ps = 0;
  210.     outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);
  211.     /*
  212.      * Initialize ifnet structure
  213.      */
  214.     ifp->if_unit = is->id_unit;
  215.     ifp->if_name = "we" ;
  216.     ifp->if_mtu = ETHERMTU;
  217.     ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS ;
  218.     ifp->if_init = weinit;
  219.     ifp->if_output = ether_output;
  220.     ifp->if_start = westart;
  221.     ifp->if_ioctl = weioctl;
  222.     ifp->if_reset = wereset;
  223.     ifp->if_watchdog = wewatchdog;
  224.     if_attach(ifp);
  225.  
  226.     /*
  227.      * Banner...
  228.      */
  229.     printf(" %s address %s",
  230.         ((sc->we_type != WD_STARLAN) ? "ethernet" : "starlan"),
  231.         ether_sprintf(sc->we_addr));
  232. }
  233.  
  234. /*
  235.  * Reset of interface.
  236.  */
  237. wereset(unit, uban)
  238.     int unit, uban;
  239. {
  240.     if (unit >= NWE)
  241.         return;
  242.     printf("we%d: reset\n", unit);
  243. /*    we_softc[unit].we_flags &= ~WDF_RUNNING; */
  244.     weinit(unit);
  245. }
  246.  
  247. /*
  248.  * Take interface offline.
  249.  */
  250. westop(unit)
  251.     int unit;
  252. {
  253.     register struct we_softc *sc = &we_softc[unit];
  254.     union we_command wecmd;
  255.     int s;
  256.  
  257.     /*
  258.      * Shutdown DS8390
  259.      */
  260.     s = splimp();
  261.     wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND);
  262.     wecmd.cs_stp = 1;
  263.     wecmd.cs_sta = 0;
  264.     wecmd.cs_ps = 0;
  265.     outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);
  266.     (void) splx(s);
  267. }
  268.  
  269. wewatchdog(unit) {
  270.  
  271.     log(LOG_WARNING,"we%d: soft reset\n", unit);
  272.     westop(unit);
  273.     weinit(unit);
  274. }
  275.  
  276. static Bdry;
  277. /*
  278.  * Initialization of interface (really just DS8390). 
  279.  */
  280. weinit(unit)
  281.     int unit;
  282. {
  283.     register struct we_softc *sc = &we_softc[unit];
  284.     register struct ifnet *ifp = &sc->we_if;
  285.     union we_command wecmd;
  286.     int i, s;
  287.  
  288.     /* address not known */
  289.     if (ifp->if_addrlist == (struct ifaddr *)0)
  290.         return;
  291.  
  292.     /* already running */
  293.     /*if (ifp->if_flags & IFF_RUNNING) return; */
  294.  
  295.     /*
  296.      * Initialize DS8390 in order given in NSC NIC manual.
  297.      * this is stock code...please see the National manual for details.
  298.      */
  299.     s = splhigh();
  300. Bdry = 0;
  301.     wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND);
  302.     wecmd.cs_stp = 1;
  303.     wecmd.cs_sta = 0;
  304.     wecmd.cs_ps = 0;
  305.     outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);
  306.     outb(sc->we_io_nic_addr + WD_P0_DCR, WD_D_CONFIG);
  307.     outb(sc->we_io_nic_addr + WD_P0_RBCR0, 0);
  308.     outb(sc->we_io_nic_addr + WD_P0_RBCR1, 0);
  309.     outb(sc->we_io_nic_addr + WD_P0_RCR, WD_R_MON);
  310.     outb(sc->we_io_nic_addr + WD_P0_TCR, WD_T_CONFIG);
  311.     outb(sc->we_io_nic_addr + WD_P0_TPSR, 0);
  312.     outb(sc->we_io_nic_addr + WD_P0_PSTART, WD_TXBUF_SIZE);
  313.     outb(sc->we_io_nic_addr + WD_P0_PSTOP,
  314.         sc->we_vmem_size / WD_PAGE_SIZE);
  315.     outb(sc->we_io_nic_addr + WD_P0_BNRY, WD_TXBUF_SIZE);
  316.     outb(sc->we_io_nic_addr + WD_P0_ISR, 0xff);
  317.     outb(sc->we_io_nic_addr + WD_P0_IMR, WD_I_CONFIG);
  318.     wecmd.cs_ps = 1;
  319.     outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);
  320.     for (i = 0; i < ETHER_ADDR_LEN; ++i)
  321.         outb(sc->we_io_nic_addr + WD_P1_PAR0 + i, sc->we_addr[i]);
  322.     for (i = 0; i < ETHER_ADDR_LEN; ++i)    /* == broadcast addr */
  323.         outb(sc->we_io_nic_addr + WD_P1_MAR0 + i, 0xff);
  324.     outb(sc->we_io_nic_addr + WD_P1_CURR, WD_TXBUF_SIZE);
  325.     wecmd.cs_ps = 0;
  326.     wecmd.cs_stp = 0;
  327.     wecmd.cs_sta = 1;
  328.     wecmd.cs_rd = 0x4;
  329.     outb(sc->we_io_nic_addr + WD_P1_COMMAND, wecmd.cs_byte);
  330.     outb(sc->we_io_nic_addr + WD_P0_RCR, WD_R_CONFIG);
  331.  
  332.     /*
  333.      * Take the interface out of reset, program the vector, 
  334.      * enable interrupts, and tell the world we are up.
  335.      */
  336.     ifp->if_flags |= IFF_RUNNING;
  337.     sc->we_flags &= ~WDF_TXBUSY;
  338.     (void) splx(s);
  339.     westart(ifp);
  340. }
  341.  
  342. /*
  343.  * Start output on interface.
  344.  */
  345. westart(ifp)
  346.     struct ifnet *ifp;
  347. {
  348.     register struct we_softc *sc = &we_softc[ifp->if_unit];
  349.     struct mbuf *m0, *m;
  350.     register caddr_t buffer;
  351.     int len, s;
  352.     union we_command wecmd;
  353.  
  354.     /*
  355.      * The DS8390 has only one transmit buffer, if it is busy we
  356.      * must wait until the transmit interrupt completes.
  357.      */
  358.     s = splhigh();
  359.     if (sc->we_flags & WDF_TXBUSY) {
  360.         (void) splx(s);
  361.         return;
  362.     }
  363.     IF_DEQUEUE(&sc->we_if.if_snd, m);
  364.     if (m == 0) {
  365.         (void) splx(s);
  366.         return;
  367.     }
  368.     sc->we_flags |= WDF_TXBUSY; 
  369.     (void) splx(s);
  370.  
  371.     /*
  372.      * Copy the mbuf chain into the transmit buffer
  373.      */
  374.     buffer = sc->we_vmem_addr;
  375.     len = 0;
  376.     for (m0 = m; m != 0; m = m->m_next) {
  377.         bcopy(mtod(m, caddr_t), buffer, m->m_len);
  378.         buffer += m->m_len;
  379.             len += m->m_len;
  380.     }
  381.  
  382.     m_freem(m0);
  383.  
  384.     /*
  385.      * Init transmit length registers, and set transmit start flag.
  386.      */
  387.     s = splhigh();
  388.     len = MAX(len, ETHER_MIN_LEN);
  389.     wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND);
  390.     wecmd.cs_ps = 0;
  391.     outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);
  392.     outb(sc->we_io_nic_addr + WD_P0_TBCR0, len & 0xff);
  393.     outb(sc->we_io_nic_addr + WD_P0_TBCR1, len >> 8);
  394.     wecmd.cs_txp = 1;
  395.     outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);
  396.     (void) splx(s);
  397. }
  398.  
  399. /*
  400.  * Ethernet interface interrupt processor
  401.  */
  402. weintr(unit)
  403.     int unit;
  404. {
  405.     register struct we_softc *sc = &we_softc[unit];
  406.     union we_command wecmd;
  407.     union we_interrupt weisr;
  408.  
  409.     unit =0;
  410.  
  411.     /* disable onboard interrupts, then get interrupt status */
  412.     wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND);
  413.     wecmd.cs_ps = 0;
  414.     outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);
  415.     weisr.is_byte = inb(sc->we_io_nic_addr + WD_P0_ISR);
  416. loop:
  417.     outb(sc->we_io_nic_addr + WD_P0_ISR, weisr.is_byte);
  418.  
  419.     /* transmit error */
  420.     if (weisr.is_txe) {
  421.         /* need to read these registers to clear status */
  422.         sc->we_if.if_collisions +=
  423.             inb(sc->we_io_nic_addr + WD_P0_TBCR0);
  424.         ++sc->we_if.if_oerrors;
  425.     }
  426.  
  427.     /* receiver error */
  428.     if (weisr.is_rxe) {
  429.         /* need to read these registers to clear status */
  430.         (void) inb(sc->we_io_nic_addr + 0xD);
  431.         (void) inb(sc->we_io_nic_addr + 0xE);
  432.         (void) inb(sc->we_io_nic_addr + 0xF);
  433.         ++sc->we_if.if_ierrors;
  434.     }
  435.  
  436.     /* normal transmit complete */
  437.     if (weisr.is_ptx || weisr.is_txe)
  438.         wetint (unit);
  439.  
  440.     /* normal receive notification */
  441.     if (weisr.is_prx || weisr.is_rxe)
  442.         werint (unit);
  443.  
  444.     /* try to start transmit */
  445.     westart(&sc->we_if);
  446.  
  447.     /* re-enable onboard interrupts */
  448.     wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND);
  449.     wecmd.cs_ps = 0;
  450.     outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);
  451.     outb(sc->we_io_nic_addr + WD_P0_IMR, 0xff/*WD_I_CONFIG*/);
  452.     weisr.is_byte = inb(sc->we_io_nic_addr + WD_P0_ISR);
  453.     if (weisr.is_byte) goto loop;
  454. }
  455.  
  456. /*
  457.  * Ethernet interface transmit interrupt.
  458.  */
  459. wetint(unit)
  460.     int unit;
  461. {
  462.     register struct we_softc *sc = &we_softc[unit];
  463.  
  464.     /*
  465.      * Do some statistics (assume page zero of NIC mapped in)
  466.      */
  467.     sc->we_flags &= ~WDF_TXBUSY; 
  468.     sc->we_if.if_timer = 0;
  469.     ++sc->we_if.if_opackets;
  470.     sc->we_if.if_collisions += inb(sc->we_io_nic_addr + WD_P0_TBCR0);
  471. }
  472.  
  473. /*
  474.  * Ethernet interface receiver interrupt.
  475.  */
  476. werint(unit)
  477.     int unit;
  478. {
  479.     register struct we_softc *sc = &we_softc[unit];
  480.     u_char bnry, curr;
  481.     long len;
  482.     union we_command wecmd;
  483.     struct we_ring *wer;
  484.  
  485.     /*
  486.      * Traverse the receive ring looking for packets to pass back.
  487.      * The search is complete when we find a descriptor not in use.
  488.      */
  489.     wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND);
  490.     wecmd.cs_ps = 0;
  491.     outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);
  492.     bnry = inb(sc->we_io_nic_addr + WD_P0_BNRY);
  493.     wecmd.cs_ps = 1;
  494.     outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);
  495.     curr = inb(sc->we_io_nic_addr + WD_P1_CURR);
  496. if(Bdry)
  497.     bnry =Bdry;
  498.  
  499.     while (bnry != curr)
  500.     {
  501.         /* get pointer to this buffer header structure */
  502.         wer = (struct we_ring *)(sc->we_vmem_addr + (bnry << 8));
  503.  
  504.         /* count includes CRC */
  505.         len = wer->we_count - 4;
  506.         if (len > 30 && len <= ETHERMTU+100
  507.             /*&& (*(char *)wer  == 1 || *(char *) wer == 0x21)*/)
  508.             weread(sc, (caddr_t)(wer + 1), len);
  509.         else printf("reject %d", len);
  510.  
  511. outofbufs:
  512.         wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND);
  513.         wecmd.cs_ps = 0;
  514.         outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);
  515.  
  516.         /* advance on chip Boundry register */
  517.         if((caddr_t) wer + WD_PAGE_SIZE - 1 > sc->we_vmem_end) {
  518.             bnry = WD_TXBUF_SIZE;
  519.             outb(sc->we_io_nic_addr + WD_P0_BNRY,
  520.                     sc->we_vmem_size / WD_PAGE_SIZE-1);
  521.     
  522.         } else {
  523.             if (len > 30 && len <= ETHERMTU+100)
  524.                 bnry = wer->we_next_packet;
  525.             else bnry = curr;
  526.  
  527.             /* watch out for NIC overflow, reset Boundry if invalid */
  528.             if ((bnry - 1) < WD_TXBUF_SIZE) {
  529.                     outb(sc->we_io_nic_addr + WD_P0_BNRY,
  530.                     (sc->we_vmem_size / WD_PAGE_SIZE) - 1);
  531.                 bnry = WD_TXBUF_SIZE;
  532.             } else
  533.                 outb(sc->we_io_nic_addr + WD_P0_BNRY, bnry-1);
  534.         }
  535.  
  536.         /* refresh our copy of CURR */
  537.         wecmd.cs_ps = 1;
  538.         outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);
  539.         curr = inb(sc->we_io_nic_addr + WD_P1_CURR);
  540.     }
  541. Bdry = bnry;
  542. }
  543.  
  544. #ifdef shit
  545. /*
  546.  * Process an ioctl request.
  547.  */
  548. weioctl(ifp, cmd, data)
  549.     register struct ifnet *ifp;
  550.     int cmd;
  551.     caddr_t data;
  552. {
  553.     struct we_softc *sc = &we_softc[ifp->if_unit];
  554.     struct ifaddr *ifa = (struct ifaddr *)data;
  555.     int s = splimp(), error = 0;
  556.  
  557.     switch (cmd) {
  558.  
  559.     case SIOCSIFADDR:
  560.         ifp->if_flags |= IFF_UP;
  561.         weinit(ifp->if_unit);
  562.         switch(ifa->ifa_addr->sa_family) {
  563. #ifdef INET
  564.         case AF_INET:
  565.             ((struct arpcom *)ifp)->ac_ipaddr =
  566.                 IA_SIN(ifa)->sin_addr;
  567.             arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
  568.             break;
  569. #endif
  570. #ifdef NS
  571.         case AF_NS:
  572.             {
  573.             register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
  574.             
  575.             if (ns_nullhost(*ina))
  576.                 ina->x_host = *(union ns_host *)(sc->we_addr);
  577.             else
  578.                 wesetaddr(ina->x_host.c_host, ifp->if_unit);
  579.             break;
  580.             }
  581. #endif
  582.         }
  583.         break;
  584.  
  585.     case SIOCSIFFLAGS:
  586.         if (((ifp->if_flags & IFF_UP) == 0) &&
  587.            (sc->we_flags & WDF_RUNNING)) {
  588.             westop(ifp->if_unit);
  589.         } else if (((ifp->if_flags & IFF_UP) == IFF_UP) &&
  590.            ((sc->we_flags & WDF_RUNNING) == 0))
  591.             weinit(ifp->if_unit);
  592.         break;
  593.  
  594.     default:
  595.         error = EINVAL;
  596.  
  597.     }
  598.     (void) splx(s);
  599.     return (error);
  600. }
  601. #endif
  602.  
  603. /*
  604.  * Process an ioctl request.
  605.  */
  606. weioctl(ifp, cmd, data)
  607.     register struct ifnet *ifp;
  608.     int cmd;
  609.     caddr_t data;
  610. {
  611.     register struct ifaddr *ifa = (struct ifaddr *)data;
  612.     struct we_softc *sc = &we_softc[ifp->if_unit];
  613.     struct ifreq *ifr = (struct ifreq *)data;
  614.     int s = splimp(), error = 0;
  615.  
  616.  
  617.     switch (cmd) {
  618.  
  619.     case SIOCSIFADDR:
  620.         ifp->if_flags |= IFF_UP;
  621.  
  622.         switch (ifa->ifa_addr->sa_family) {
  623. #ifdef INET
  624.         case AF_INET:
  625.             weinit(ifp->if_unit);    /* before arpwhohas */
  626.             ((struct arpcom *)ifp)->ac_ipaddr =
  627.                 IA_SIN(ifa)->sin_addr;
  628.             arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
  629.             break;
  630. #endif
  631. #ifdef NS
  632.         case AF_NS:
  633.             {
  634.             register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
  635.  
  636.             if (ns_nullhost(*ina))
  637.                 ina->x_host = *(union ns_host *)(sc->ns_addr);
  638.             else {
  639.                 /* 
  640.                  * The manual says we can't change the address 
  641.                  * while the receiver is armed,
  642.                  * so reset everything
  643.                  */
  644.                 ifp->if_flags &= ~IFF_RUNNING; 
  645.                 bcopy((caddr_t)ina->x_host.c_host,
  646.                     (caddr_t)sc->ns_addr, sizeof(sc->ns_addr));
  647.             }
  648.             weinit(ifp->if_unit); /* does ne_setaddr() */
  649.             break;
  650.             }
  651. #endif
  652.         default:
  653.             weinit(ifp->if_unit);
  654.             break;
  655.         }
  656.         break;
  657.  
  658.     case SIOCSIFFLAGS:
  659.         if ((ifp->if_flags & IFF_UP) == 0 &&
  660.             ifp->if_flags & IFF_RUNNING) {
  661.             ifp->if_flags &= ~IFF_RUNNING;
  662.             westop(ifp->if_unit);
  663.         } else if (ifp->if_flags & IFF_UP &&
  664.             (ifp->if_flags & IFF_RUNNING) == 0)
  665.             weinit(ifp->if_unit);
  666.         break;
  667.  
  668. #ifdef notdef
  669.     case SIOCGHWADDR:
  670.         bcopy((caddr_t)sc->sc_addr, (caddr_t) &ifr->ifr_data,
  671.             sizeof(sc->sc_addr));
  672.         break;
  673. #endif
  674.  
  675.     default:
  676.         error = EINVAL;
  677.     }
  678.     splx(s);
  679.     return (error);
  680. }
  681. /*
  682.  * set ethernet address for unit
  683.  */
  684. wesetaddr(physaddr, unit)
  685.     u_char *physaddr;
  686.     int unit;
  687. {
  688.     register struct we_softc *sc = &we_softc[unit];
  689.     register int i;
  690.  
  691.     /*
  692.      * Rewrite ethernet address, and then force restart of NIC
  693.      */
  694.     for (i = 0; i < ETHER_ADDR_LEN; i++)
  695.         sc->we_addr[i] = physaddr[i];
  696.     sc->we_flags &= ~WDF_RUNNING;
  697.     weinit(unit);
  698. }
  699.  
  700. #define    wedataaddr(sc, eh, off, type) \
  701.     ((type) ((caddr_t)((eh)+1)+(off) >= (sc)->we_vmem_end) ? \
  702.         (((caddr_t)((eh)+1)+(off))) - (sc)->we_vmem_end \
  703.         + (sc)->we_vmem_ring: \
  704.         ((caddr_t)((eh)+1)+(off)))
  705. /*
  706.  * Pass a packet to the higher levels.
  707.  * We deal with the trailer protocol here.
  708.  */
  709. weread(sc, buf, len)
  710.     register struct we_softc *sc;
  711.     char *buf;
  712.     int len;
  713. {
  714.     register struct ether_header *eh;
  715.         struct mbuf *m, *weget();
  716.     int off, resid;
  717.  
  718.     /*
  719.      * Deal with trailer protocol: if type is trailer type
  720.      * get true type from first 16-bit word past data.
  721.      * Remember that type was trailer by setting off.
  722.      */
  723.     eh = (struct ether_header *)buf;
  724.     eh->ether_type = ntohs((u_short)eh->ether_type);
  725.     if (eh->ether_type >= ETHERTYPE_TRAIL &&
  726.         eh->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
  727.         off = (eh->ether_type - ETHERTYPE_TRAIL) * 512;
  728.         if (off >= ETHERMTU) return;        /* sanity */
  729.         eh->ether_type = ntohs(*wedataaddr(sc, eh, off, u_short *));
  730.         resid = ntohs(*(wedataaddr(sc, eh, off+2, u_short *)));
  731.         if (off + resid > len) return;        /* sanity */
  732.         len = off + resid;
  733.     } else    off = 0;
  734.  
  735.     len -= sizeof(struct ether_header);
  736.     if (len <= 0) return;
  737.  
  738.     /*
  739.      * Pull packet off interface.  Off is nonzero if packet
  740.      * has trailing header; neget will then force this header
  741.      * information to be at the front, but we still have to drop
  742.      * the type and length which are at the front of any trailer data.
  743.      */
  744.     m = weget(buf, len, off, &sc->we_if, sc);
  745.     if (m == 0) return;
  746.     ether_input(&sc->we_if, eh, m);
  747. }
  748.  
  749. /*
  750.  * Supporting routines
  751.  */
  752.  
  753. /*
  754.  * Pull read data off a interface.
  755.  * Len is length of data, with local net header stripped.
  756.  * Off is non-zero if a trailer protocol was used, and
  757.  * gives the offset of the trailer information.
  758.  * We copy the trailer information and then all the normal
  759.  * data into mbufs.  When full cluster sized units are present
  760.  * we copy into clusters.
  761.  */
  762. struct mbuf *
  763. weget(buf, totlen, off0, ifp, sc)
  764.     caddr_t buf;
  765.     int totlen, off0;
  766.     struct ifnet *ifp;
  767.     struct we_softc *sc;
  768. {
  769.     struct mbuf *top, **mp, *m, *p;
  770.     int off = off0, len;
  771.     register caddr_t cp = buf;
  772.     char *epkt;
  773.     int tc =totlen;
  774.  
  775.     buf += sizeof(struct ether_header);
  776.     cp = buf;
  777.     epkt = cp + totlen;
  778.  
  779.     if (off) {
  780.         cp += off + 2 * sizeof(u_short);
  781.         totlen -= 2 * sizeof(u_short);
  782.     }
  783.  
  784.     MGETHDR(m, M_DONTWAIT, MT_DATA);
  785.     if (m == 0)
  786.         return (0);
  787.     m->m_pkthdr.rcvif = ifp;
  788.     m->m_pkthdr.len = totlen;
  789.     m->m_len = MHLEN;
  790.  
  791.     top = 0;
  792.     mp = ⊤
  793.     while (totlen > 0) {
  794.         if (top) {
  795.             MGET(m, M_DONTWAIT, MT_DATA);
  796.             if (m == 0) {
  797.                 m_freem(top);
  798.                 return (0);
  799.             }
  800.             m->m_len = MLEN;
  801.         }
  802.         len = min(totlen, epkt - cp);
  803.         if (len >= MINCLSIZE) {
  804.             MCLGET(m, M_DONTWAIT);
  805.             if (m->m_flags & M_EXT)
  806.                 m->m_len = len = min(len, MCLBYTES);
  807.             else
  808.                 len = m->m_len;
  809.         } else {
  810.             /*
  811.              * Place initial small packet/header at end of mbuf.
  812.              */
  813.             if (len < m->m_len) {
  814.                 if (top == 0 && len + max_linkhdr <= m->m_len)
  815.                     m->m_data += max_linkhdr;
  816.                 m->m_len = len;
  817.             } else
  818.                 len = m->m_len;
  819.         }
  820.  
  821.         totlen -= len;
  822.         /* only do up to end of buffer */
  823.         if (cp+len > sc->we_vmem_end) {
  824.             unsigned toend = sc->we_vmem_end - cp;
  825.  
  826.             bcopy(cp, mtod(m, caddr_t), toend);
  827.             cp = sc->we_vmem_ring;
  828.             bcopy(cp, mtod(m, caddr_t)+toend, len - toend);
  829.             cp += len - toend;
  830.             epkt = cp + totlen;
  831.         } else {
  832.             bcopy(cp, mtod(m, caddr_t), (unsigned)len);
  833.             cp += len;
  834.         }
  835.         *mp = m;
  836.         mp = &m->m_next;
  837.         if (cp == epkt) {
  838.             cp = buf;
  839.             epkt = cp + tc;
  840.         }
  841.     }
  842.     return (top);
  843. }
  844. #endif
  845.