The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/i386/isa/if_ep.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 1994 Herb Peyerl <hpeyerl@novatel.ca>
    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 Herb Peyerl.
   16  * 4. The name of Herb Peyerl may not be used to endorse or promote products
   17  *    derived from this software without specific prior written permission.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   29  *
   30  *      if_ep.c,v 1.19 1995/01/24 20:53:45 davidg Exp
   31  */
   32 
   33 /*
   34  *      Modified from the FreeBSD 1.1.5.1 version by:
   35  *                      Andres Vega Garcia
   36  *                      INRIA - Sophia Antipolis, France
   37  *                      avega@sophia.inria.fr
   38  */
   39 
   40 /*
   41  * $FreeBSD: src/sys/i386/isa/if_ep.c,v 1.53.2.7 1999/09/05 08:12:49 peter Exp $
   42  *
   43  *  Promiscuous mode added and interrupt logic slightly changed
   44  *  to reduce the number of adapter failures. Transceiver select
   45  *  logic changed to use value from EEPROM. Autoconfiguration
   46  *  features added.
   47  *  Done by:
   48  *          Serge Babkin
   49  *          Chelindbank (Chelyabinsk, Russia)
   50  *          babkin@hq.icb.chel.su
   51  */
   52 
   53 /*
   54  * Pccard support for 3C589 by:
   55  *              HAMADA Naoki
   56  *              nao@tom-yam.or.jp
   57  */
   58 
   59 #include "ep.h"
   60 #if NEP > 0
   61 
   62 #include "bpfilter.h"
   63 
   64 #include <sys/param.h>
   65 #if defined(__FreeBSD__)
   66 #include <sys/systm.h>
   67 #include <sys/kernel.h>
   68 #include <sys/conf.h>
   69 #endif
   70 #include <sys/mbuf.h>
   71 #include <sys/socket.h>
   72 #include <sys/ioctl.h>
   73 #include <sys/errno.h>
   74 #include <sys/syslog.h>
   75 #if defined(__NetBSD__)
   76 #include <sys/select.h>
   77 #endif
   78 
   79 #include <net/if.h>
   80 #include <net/if_dl.h>
   81 #include <net/if_types.h>
   82 
   83 #ifdef INET
   84 #include <netinet/in.h>
   85 #include <netinet/in_systm.h>
   86 #include <netinet/in_var.h>
   87 #include <netinet/ip.h>
   88 #include <netinet/if_ether.h>
   89 #endif
   90 
   91 #ifdef IPX
   92 #include <netipx/ipx.h>
   93 #include <netipx/ipx_if.h>
   94 #endif
   95 
   96 #ifdef NS
   97 #include <netns/ns.h>
   98 #include <netns/ns_if.h>
   99 #endif
  100 
  101 #if NBPFILTER > 0
  102 #include <net/bpf.h>
  103 #include <net/bpfdesc.h>
  104 #endif
  105 
  106 #ifdef BRIDGE
  107 #include <net/bridge.h>
  108 #endif
  109 
  110 #if defined(__FreeBSD__)
  111 #include <machine/clock.h>
  112 #endif
  113 
  114 #include <i386/isa/isa_device.h>
  115 #include <i386/isa/if_epreg.h>
  116 #include <i386/isa/elink.h>
  117 
  118 /* Exported variables */
  119 u_long  ep_unit;
  120 int     ep_boards;
  121 struct  ep_board ep_board[EP_MAX_BOARDS + 1];
  122 
  123 static  int eeprom_rdy __P((struct ep_softc *sc));
  124 
  125 static  int ep_isa_probe __P((struct isa_device *));
  126 static struct ep_board * ep_look_for_board_at __P((struct isa_device *is));
  127 static  int ep_isa_attach __P((struct isa_device *));
  128 static  int epioctl __P((struct ifnet * ifp, int, caddr_t));
  129 
  130 static  void epinit __P((struct ep_softc *));
  131 static  void epread __P((struct ep_softc *));
  132 void    epreset __P((int));
  133 static  void epstart __P((struct ifnet *));
  134 static  void epstop __P((struct ep_softc *));
  135 static  void epwatchdog __P((struct ifnet *));
  136 
  137 #if 0
  138 static  int send_ID_sequence __P((int));
  139 #endif
  140 static  int get_eeprom_data __P((int, int));
  141 
  142 static  struct ep_softc* ep_softc[NEP];
  143 static  int ep_current_tag = EP_LAST_TAG + 1;
  144 static  char *ep_conn_type[] = {"UTP", "AUI", "???", "BNC"};
  145 
  146 #define ep_ftst(f) (sc->stat&(f))
  147 #define ep_fset(f) (sc->stat|=(f))
  148 #define ep_frst(f) (sc->stat&=~(f))
  149 
  150 struct isa_driver epdriver = {
  151     ep_isa_probe,
  152     ep_isa_attach,
  153     "ep",
  154     0
  155 };
  156 
  157 #include "card.h"
  158 
  159 #if NCARD > 0
  160 #include "apm.h"
  161 #include <sys/select.h>
  162 #include <pccard/cardinfo.h>
  163 #include <pccard/driver.h>
  164 #include <pccard/slot.h>
  165 
  166 /*
  167  * PC-Card (PCMCIA) specific code.
  168  */
  169 static int ep_pccard_init __P((struct pccard_devinfo *));
  170 static int ep_pccard_attach  __P((struct pccard_devinfo *));
  171 static void ep_unload __P((struct pccard_devinfo *));
  172 static int card_intr __P((struct pccard_devinfo *));
  173 
  174 static struct pccard_device ep_info = {
  175     "ep",
  176     ep_pccard_init,
  177     ep_unload,
  178     card_intr,
  179     0,                      /* Attributes - presently unused */
  180     &net_imask
  181 };
  182 
  183 DATA_SET(pccarddrv_set, ep_info);
  184 
  185 /*
  186  * Initialize the device - called from Slot manager.
  187  */
  188 static int
  189 ep_pccard_init(devi)
  190     struct pccard_devinfo *devi;
  191 {
  192     struct isa_device *is = &devi->isahd;
  193     struct ep_softc *sc = ep_softc[is->id_unit];
  194     struct ep_board *epb;
  195     int i;
  196 
  197     epb = &ep_board[is->id_unit];
  198 
  199     if (sc == 0) {
  200         if ((sc = ep_alloc(is->id_unit, epb)) == 0) {
  201             return (ENXIO);
  202         }
  203         ep_unit++;
  204     }
  205 
  206     /* get_e() requires these. */
  207     sc->ep_io_addr = is->id_iobase;
  208     sc->unit = is->id_unit;
  209 
  210     epb->epb_addr = is->id_iobase;
  211     epb->epb_used = 1;
  212     epb->prod_id = get_e(sc, EEPROM_PROD_ID);
  213 
  214     /* 3C589's product id? */
  215     if (epb->prod_id != 0x9058) {
  216         printf("ep%d: failed to come ready.\n", is->id_unit);
  217         return (ENXIO);
  218     }
  219 
  220     epb->res_cfg = get_e(sc, EEPROM_RESOURCE_CFG);
  221     for (i = 0; i < 3; i++)
  222         sc->epb->eth_addr[i] = get_e(sc, EEPROM_NODE_ADDR_0 + i);
  223 
  224     if (ep_pccard_attach(devi) == 0)
  225         return (ENXIO);
  226 
  227     sc->arpcom.ac_if.if_snd.ifq_maxlen = ifqmaxlen;
  228     return (0);
  229 }
  230 
  231 static int
  232 ep_pccard_attach(devi)
  233     struct pccard_devinfo *devi;
  234 {
  235     struct isa_device *is = &devi->isahd;
  236     struct ep_softc *sc = ep_softc[is->id_unit];
  237     u_short config;
  238 
  239     sc->ep_connectors = 0;
  240     config = inw(IS_BASE + EP_W0_CONFIG_CTRL);
  241     if (config & IS_BNC) {
  242         sc->ep_connectors |= BNC;
  243     }
  244     if (config & IS_UTP) {
  245         sc->ep_connectors |= UTP;
  246     }
  247     if (!(sc->ep_connectors & 7))
  248         printf("no connectors!");
  249     sc->ep_connector = inw(BASE + EP_W0_ADDRESS_CFG) >> ACF_CONNECTOR_BITS;
  250 
  251     /* ROM size = 0, ROM base = 0 */
  252     /* For now, ignore AUTO SELECT feature of 3C589B and later. */
  253     outw(BASE + EP_W0_ADDRESS_CFG, get_e(sc, EEPROM_ADDR_CFG) & 0xc000);
  254 
  255     /* Fake IRQ must be 3 */
  256     outw(BASE + EP_W0_RESOURCE_CFG, (sc->epb->res_cfg & 0x0fff) | 0x3000);
  257 
  258     outw(BASE + EP_W0_PRODUCT_ID, sc->epb->prod_id);
  259 
  260     ep_attach(sc);
  261 
  262     return 1;
  263 }
  264 
  265 static void
  266 ep_unload(devi)
  267     struct pccard_devinfo *devi;
  268 {
  269     struct ep_softc *sc = ep_softc[devi->isahd.id_unit];
  270 
  271     if (sc->gone) {
  272         printf("ep%d: already unloaded\n", devi->isahd.id_unit);
  273         return;
  274     }
  275     sc->arpcom.ac_if.if_flags &= ~IFF_RUNNING;
  276     sc->gone = 1;
  277     printf("ep%d: unload\n", devi->isahd.id_unit);
  278 }
  279 
  280 /*
  281  * card_intr - Shared interrupt called from
  282  * front end of PC-Card handler.
  283  */
  284 static int
  285 card_intr(devi)
  286     struct pccard_devinfo *devi;
  287 {
  288     epintr(devi->isahd.id_unit);
  289     return(1);
  290 }
  291 #endif /* NCARD > 0 */
  292 
  293 static int
  294 eeprom_rdy(sc)
  295     struct ep_softc *sc;
  296 {
  297     int i;
  298 
  299     for (i = 0; is_eeprom_busy(BASE) && i < MAX_EEPROMBUSY; i++)
  300         continue;
  301     if (i >= MAX_EEPROMBUSY) {
  302         printf("ep%d: eeprom failed to come ready.\n", sc->unit);
  303         return (0);
  304     }
  305     return (1);
  306 }
  307 
  308 static struct ep_board *
  309 ep_look_for_board_at(is)
  310     struct isa_device *is;
  311 {
  312     int data, i, j, id_port = ELINK_ID_PORT;
  313     int count = 0;
  314 
  315     if (ep_current_tag == (EP_LAST_TAG + 1)) {
  316         /* Come here just one time */
  317 
  318         ep_current_tag--;
  319 
  320         /* Look for the ISA boards. Init and leave them actived */
  321         outb(id_port, 0);
  322         outb(id_port, 0);
  323 
  324         elink_idseq(0xCF);
  325 
  326         elink_reset();
  327         DELAY(10000);
  328         for (i = 0; i < EP_MAX_BOARDS; i++) {
  329             outb(id_port, 0);
  330             outb(id_port, 0);
  331             elink_idseq(0xCF);
  332 
  333             data = get_eeprom_data(id_port, EEPROM_MFG_ID);
  334             if (data != MFG_ID)
  335                 break;
  336 
  337             /* resolve contention using the Ethernet address */
  338 
  339             for (j = 0; j < 3; j++)
  340                  get_eeprom_data(id_port, j);
  341 
  342             /* and save this address for later use */
  343 
  344             for (j = 0; j < 3; j++)
  345                  ep_board[ep_boards].eth_addr[j] = get_eeprom_data(id_port, j);
  346 
  347             ep_board[ep_boards].res_cfg =
  348                 get_eeprom_data(id_port, EEPROM_RESOURCE_CFG);
  349 
  350             ep_board[ep_boards].prod_id =
  351                 get_eeprom_data(id_port, EEPROM_PROD_ID);
  352 
  353             ep_board[ep_boards].epb_used = 0;
  354 #ifdef PC98
  355             ep_board[ep_boards].epb_addr =
  356                         (get_eeprom_data(id_port, EEPROM_ADDR_CFG) & 0x1f) * 0x100 + 0x40d0;
  357 #else
  358             ep_board[ep_boards].epb_addr =
  359                         (get_eeprom_data(id_port, EEPROM_ADDR_CFG) & 0x1f) * 0x10 + 0x200;
  360 
  361             if (ep_board[ep_boards].epb_addr > 0x3E0)
  362                 /* Board in EISA configuration mode */
  363                 continue;
  364 #endif /* PC98 */
  365 
  366             outb(id_port, ep_current_tag);      /* tags board */
  367             outb(id_port, ACTIVATE_ADAPTER_TO_CONFIG);
  368             ep_boards++;
  369             count++;
  370             ep_current_tag--;
  371         }
  372 
  373         ep_board[ep_boards].epb_addr = 0;
  374         if (count) {
  375             printf("%d 3C5x9 board(s) on ISA found at", count);
  376             for (j = 0; ep_board[j].epb_addr; j++)
  377                 if (ep_board[j].epb_addr <= 0x3E0)
  378                     printf(" 0x%x", ep_board[j].epb_addr);
  379             printf("\n");
  380         }
  381     }
  382 
  383     /* we have two cases:
  384      *
  385      *  1. Device was configured with 'port ?'
  386      *      In this case we search for the first unused card in list
  387      *
  388      *  2. Device was configured with 'port xxx'
  389      *      In this case we search for the unused card with that address
  390      *
  391      */
  392 
  393     if (IS_BASE == -1) { /* port? */
  394         for (i = 0; ep_board[i].epb_addr && ep_board[i].epb_used; i++)
  395             ;
  396         if (ep_board[i].epb_addr == 0)
  397             return 0;
  398 
  399         IS_BASE = ep_board[i].epb_addr;
  400         ep_board[i].epb_used = 1;
  401 
  402         return &ep_board[i];
  403     } else {
  404         for (i = 0;
  405              ep_board[i].epb_addr && ep_board[i].epb_addr != IS_BASE;
  406              i++)
  407             ;
  408 
  409         if (ep_board[i].epb_used || ep_board[i].epb_addr != IS_BASE)
  410             return 0;
  411 
  412         if (inw(IS_BASE + EP_W0_EEPROM_COMMAND) & EEPROM_TST_MODE) {
  413             printf("ep%d: 3c5x9 at 0x%x in PnP mode. Disable PnP mode!\n",
  414                    is->id_unit, IS_BASE);
  415         }
  416         ep_board[i].epb_used = 1;
  417 
  418         return &ep_board[i];
  419     }
  420 }
  421 
  422 /*
  423  * get_e: gets a 16 bits word from the EEPROM. we must have set the window
  424  * before
  425  */
  426 u_int16_t
  427 get_e(sc, offset)
  428     struct ep_softc *sc;
  429     int offset;
  430 {
  431     if (!eeprom_rdy(sc))
  432         return (0xffff);
  433     outw(BASE + EP_W0_EEPROM_COMMAND, EEPROM_CMD_RD | offset);
  434     if (!eeprom_rdy(sc))
  435         return (0xffff);
  436     return (inw(BASE + EP_W0_EEPROM_DATA));
  437 }
  438 
  439 struct ep_softc *
  440 ep_alloc(unit, epb)
  441     int unit;
  442     struct      ep_board *epb;
  443 {
  444     struct      ep_softc *sc;
  445 
  446     if (unit >= NEP) {
  447         printf("ep: unit number (%d) too high\n", unit);
  448         return NULL;
  449     }
  450  
  451     /*
  452      * Allocate a storage area for us
  453      */
  454     if (ep_softc[unit]) {
  455         printf("ep%d: unit number already allocated to another "
  456                "adaptor\n", unit);
  457         return NULL;
  458     }
  459 
  460     sc = malloc(sizeof(struct ep_softc), M_DEVBUF, M_NOWAIT);
  461     if (!sc) {
  462         printf("ep%d: cannot malloc!\n", unit);
  463         return NULL;
  464     }
  465     bzero(sc, sizeof(struct ep_softc));
  466     ep_softc[unit] = sc;
  467     sc->unit = unit;
  468     sc->ep_io_addr = epb->epb_addr;
  469     sc->epb = epb;
  470 
  471     return(sc);
  472 }
  473 
  474 void
  475 ep_free(sc)
  476     struct ep_softc *sc;
  477 {
  478     ep_softc[sc->unit] = NULL;
  479     free(sc, M_DEVBUF);
  480     return;
  481 }
  482 
  483 int
  484 ep_isa_probe(is)
  485     struct isa_device *is;
  486 {
  487     struct ep_softc *sc;
  488     struct ep_board *epb;
  489     u_short k;
  490 
  491     if ((epb = ep_look_for_board_at(is)) == 0)
  492         return (0);
  493 
  494     /*
  495      * Allocate a storage area for us
  496      */
  497     sc = ep_alloc(ep_unit, epb); 
  498     if (!sc)
  499         return (0);
  500 
  501     is->id_unit = ep_unit++;
  502 
  503     /*
  504      * The iobase was found and MFG_ID was 0x6d50. PROD_ID should be
  505      * 0x9[0-f]50       (IBM-PC)
  506      * 0x9[0-f]5[0-f]   (PC-98)
  507      */
  508     GO_WINDOW(0);
  509     k = sc->epb->prod_id;
  510 #ifdef PC98
  511     if ((k & 0xf0f0) != (PROD_ID & 0xf0f0)) {
  512 #else
  513     if ((k & 0xf0ff) != (PROD_ID & 0xf0ff)) {
  514 #endif
  515         printf("ep_isa_probe: ignoring model %04x\n", k);
  516         ep_free(sc);
  517         return (0);
  518     }
  519 
  520     k = sc->epb->res_cfg;
  521 
  522     k >>= 12;
  523 
  524     /* Now we have two cases again:
  525      *
  526      *  1. Device was configured with 'irq?'
  527      *      In this case we use irq read from the board
  528      *
  529      *  2. Device was configured with 'irq xxx'
  530      *      In this case we set up the board to use specified interrupt
  531      *
  532      */
  533 
  534     if (is->id_irq == 0) { /* irq? */
  535         is->id_irq = 1 << ((k == 2) ? 9 : k);
  536     }
  537 
  538     sc->stat = 0;       /* 16 bit access */
  539 
  540     /* By now, the adapter is already activated */
  541 
  542     return (EP_IOSIZE);         /* 16 bytes of I/O space used. */
  543 }
  544 
  545 static int
  546 ep_isa_attach(is)
  547     struct isa_device *is;
  548 {
  549     struct ep_softc *sc = ep_softc[is->id_unit];
  550     u_short config;
  551     int irq;
  552 
  553     sc->ep_connectors = 0;
  554     config = inw(IS_BASE + EP_W0_CONFIG_CTRL);
  555     if (config & IS_AUI) {
  556         sc->ep_connectors |= AUI;
  557     }
  558     if (config & IS_BNC) {
  559         sc->ep_connectors |= BNC;
  560     }
  561     if (config & IS_UTP) {
  562         sc->ep_connectors |= UTP;
  563     }
  564     if (!(sc->ep_connectors & 7))
  565         printf("no connectors!");
  566     sc->ep_connector = inw(BASE + EP_W0_ADDRESS_CFG) >> ACF_CONNECTOR_BITS;
  567     /*
  568      * Write IRQ value to board
  569      */
  570 
  571     irq = ffs(is->id_irq) - 1;
  572     if (irq == -1) {
  573         printf(" invalid irq... cannot attach\n");
  574         return 0;
  575     }
  576 
  577     GO_WINDOW(0);
  578     SET_IRQ(BASE, irq);
  579 
  580     ep_attach(sc);
  581     return 1;
  582 }
  583 
  584 int
  585 ep_attach(sc)
  586     struct ep_softc *sc;
  587 {
  588     struct ifaddr *ifa;
  589     struct ifnet *ifp = &sc->arpcom.ac_if;
  590     struct sockaddr_dl *sdl;
  591     u_short *p;
  592     int i;
  593     int attached;
  594 
  595     sc->gone = 0;
  596     attached = (ifp->if_softc != 0);
  597 
  598     printf("ep%d: ", sc->unit);
  599     /*
  600      * Current media type
  601      */
  602     if (sc->ep_connectors & AUI) {
  603         printf("aui");
  604         if (sc->ep_connectors & ~AUI)
  605                 printf("/");
  606     }
  607     if (sc->ep_connectors & UTP) {
  608         printf("utp");
  609         if (sc->ep_connectors & BNC)
  610                 printf("/");
  611     }
  612     if (sc->ep_connectors & BNC) {
  613         printf("bnc");
  614     }
  615 
  616     printf("[*%s*]", ep_conn_type[sc->ep_connector]);
  617 
  618     /*
  619      * Setup the station address
  620      */
  621     p = (u_short *) & sc->arpcom.ac_enaddr;
  622     GO_WINDOW(2);
  623     for (i = 0; i < 3; i++) {
  624         p[i] = htons(sc->epb->eth_addr[i]);
  625         outw(BASE + EP_W2_ADDR_0 + (i * 2), ntohs(p[i]));
  626     }
  627     printf(" address %6D\n", sc->arpcom.ac_enaddr, ":");
  628 
  629     ifp->if_softc = sc;
  630     ifp->if_unit = sc->unit;
  631     ifp->if_name = "ep";
  632     ifp->if_mtu = ETHERMTU;
  633     ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
  634     ifp->if_output = ether_output;
  635     ifp->if_start = epstart;
  636     ifp->if_ioctl = epioctl;
  637     ifp->if_watchdog = epwatchdog;
  638 
  639     if (!attached) {
  640         if_attach(ifp);
  641         ether_ifattach(ifp);
  642     }
  643 
  644     /* device attach does transition from UNCONFIGURED to IDLE state */
  645 
  646     /*
  647      * Fill the hardware address into ifa_addr if we find an AF_LINK entry.
  648      * We need to do this so bpf's can get the hardware addr of this card.
  649      * netstat likes this too!
  650      */
  651     ifa = ifp->if_addrlist;
  652     while ((ifa != 0) && (ifa->ifa_addr != 0) &&
  653            (ifa->ifa_addr->sa_family != AF_LINK))
  654         ifa = ifa->ifa_next;
  655 
  656     if ((ifa != 0) && (ifa->ifa_addr != 0)) {
  657         sdl = (struct sockaddr_dl *) ifa->ifa_addr;
  658         sdl->sdl_type = IFT_ETHER;
  659         sdl->sdl_alen = ETHER_ADDR_LEN;
  660         sdl->sdl_slen = 0;
  661         bcopy(sc->arpcom.ac_enaddr, LLADDR(sdl), ETHER_ADDR_LEN);
  662     }
  663 
  664 #ifdef EP_LOCAL_STATS
  665     sc->rx_no_first = sc->rx_no_mbuf =
  666         sc->rx_bpf_disc = sc->rx_overrunf = sc->rx_overrunl =
  667         sc->tx_underrun = 0;
  668 #endif
  669     ep_fset(F_RX_FIRST);
  670     sc->top = sc->mcur = 0;
  671 
  672 #if NBPFILTER > 0
  673     if (!attached) {
  674         bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header));
  675     }
  676 #endif
  677     return 0;
  678 }
  679 
  680 
  681 /*
  682  * The order in here seems important. Otherwise we may not receive
  683  * interrupts. ?!
  684  */
  685 static void
  686 epinit(sc)
  687     struct ep_softc *sc;
  688 {
  689     register struct ifnet *ifp = &sc->arpcom.ac_if;
  690     int s, i, j;
  691 
  692     if (sc->gone)
  693         return;
  694 
  695         /*
  696     if (ifp->if_addrlist == (struct ifaddr *) 0)
  697         return;
  698         */
  699 
  700     s = splimp();
  701     while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
  702 
  703     GO_WINDOW(0);
  704     outw(BASE + EP_COMMAND, STOP_TRANSCEIVER);
  705     GO_WINDOW(4);
  706     outw(BASE + EP_W4_MEDIA_TYPE, DISABLE_UTP);
  707     GO_WINDOW(0);
  708 
  709     /* Disable the card */
  710     outw(BASE + EP_W0_CONFIG_CTRL, 0);
  711 
  712     /* Enable the card */
  713     outw(BASE + EP_W0_CONFIG_CTRL, ENABLE_DRQ_IRQ);
  714 
  715     GO_WINDOW(2);
  716 
  717     /* Reload the ether_addr. */
  718     for (i = 0; i < 6; i++)
  719         outb(BASE + EP_W2_ADDR_0 + i, sc->arpcom.ac_enaddr[i]);
  720 
  721     outw(BASE + EP_COMMAND, RX_RESET);
  722     outw(BASE + EP_COMMAND, TX_RESET);
  723     while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
  724 
  725     /* Window 1 is operating window */
  726     GO_WINDOW(1);
  727     for (i = 0; i < 31; i++)
  728         inb(BASE + EP_W1_TX_STATUS);
  729 
  730     /* get rid of stray intr's */
  731     outw(BASE + EP_COMMAND, ACK_INTR | 0xff);
  732 
  733     outw(BASE + EP_COMMAND, SET_RD_0_MASK | S_5_INTS);
  734 
  735     outw(BASE + EP_COMMAND, SET_INTR_MASK | S_5_INTS);
  736 
  737     if (ifp->if_flags & IFF_PROMISC)
  738         outw(BASE + EP_COMMAND, SET_RX_FILTER | FIL_INDIVIDUAL |
  739          FIL_GROUP | FIL_BRDCST | FIL_ALL);
  740     else
  741         outw(BASE + EP_COMMAND, SET_RX_FILTER | FIL_INDIVIDUAL |
  742          FIL_GROUP | FIL_BRDCST);
  743 
  744      /*
  745       * S.B.
  746       *
  747       * Now behavior was slightly changed:
  748       *
  749       * if any of flags link[0-2] is used and its connector is
  750       * physically present the following connectors are used:
  751       *
  752       *   link0 - AUI * highest precedence
  753       *   link1 - BNC
  754       *   link2 - UTP * lowest precedence
  755       *
  756       * If none of them is specified then
  757       * connector specified in the EEPROM is used
  758       * (if present on card or AUI if not).
  759       *
  760       */
  761 
  762     /* Set the xcvr. */
  763     if (ifp->if_flags & IFF_LINK0 && sc->ep_connectors & AUI) {
  764         i = ACF_CONNECTOR_AUI;
  765     } else if (ifp->if_flags & IFF_LINK1 && sc->ep_connectors & BNC) {
  766         i = ACF_CONNECTOR_BNC;
  767     } else if (ifp->if_flags & IFF_LINK2 && sc->ep_connectors & UTP) {
  768         i = ACF_CONNECTOR_UTP;
  769     } else {
  770         i = sc->ep_connector;
  771     }
  772     GO_WINDOW(0);
  773     j = inw(BASE + EP_W0_ADDRESS_CFG) & 0x3fff;
  774     outw(BASE + EP_W0_ADDRESS_CFG, j | (i << ACF_CONNECTOR_BITS));
  775 
  776     switch(i) {
  777       case ACF_CONNECTOR_UTP:
  778         if (sc->ep_connectors & UTP) {
  779             GO_WINDOW(4);
  780             outw(BASE + EP_W4_MEDIA_TYPE, ENABLE_UTP);
  781         }
  782         break;
  783       case ACF_CONNECTOR_BNC:
  784         if (sc->ep_connectors & BNC) {
  785             outw(BASE + EP_COMMAND, START_TRANSCEIVER);
  786             DELAY(1000);
  787         }
  788         break;
  789       case ACF_CONNECTOR_AUI:
  790         /* nothing to do */
  791         break;
  792       default:
  793         printf("ep%d: strange connector type in EEPROM: assuming AUI\n",
  794                sc->unit);
  795         break;
  796     }
  797 
  798     outw(BASE + EP_COMMAND, RX_ENABLE);
  799     outw(BASE + EP_COMMAND, TX_ENABLE);
  800 
  801     ifp->if_flags |= IFF_RUNNING;
  802     ifp->if_flags &= ~IFF_OACTIVE;      /* just in case */
  803 
  804 #ifdef EP_LOCAL_STATS
  805     sc->rx_no_first = sc->rx_no_mbuf =
  806         sc->rx_bpf_disc = sc->rx_overrunf = sc->rx_overrunl =
  807         sc->tx_underrun = 0;
  808 #endif
  809     ep_fset(F_RX_FIRST);
  810     if (sc->top) {
  811         m_freem(sc->top);
  812         sc->top = sc->mcur = 0;
  813     }
  814     outw(BASE + EP_COMMAND, SET_RX_EARLY_THRESH | RX_INIT_EARLY_THRESH);
  815     outw(BASE + EP_COMMAND, SET_TX_START_THRESH | 16);
  816 
  817     /*
  818      * Store up a bunch of mbuf's for use later. (MAX_MBS). First we free up
  819      * any that we had in case we're being called from intr or somewhere
  820      * else.
  821      */
  822 
  823     GO_WINDOW(1);
  824     epstart(ifp);
  825 
  826     splx(s);
  827 }
  828 
  829 static const char padmap[] = {0, 3, 2, 1};
  830 
  831 static void
  832 epstart(ifp)
  833     struct ifnet *ifp;
  834 {
  835     register struct ep_softc *sc = ifp->if_softc;
  836     register u_int len;
  837     register struct mbuf *m;
  838     struct mbuf *top;
  839     int s, pad;
  840 
  841     if (sc->gone) {
  842         return;
  843     }
  844 
  845     s = splimp();
  846     while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
  847     if (ifp->if_flags & IFF_OACTIVE) {
  848         splx(s);
  849         return;
  850     }
  851 startagain:
  852     /* Sneak a peek at the next packet */
  853     m = ifp->if_snd.ifq_head;
  854     if (m == 0) {
  855         splx(s);
  856         return;
  857     }
  858     for (len = 0, top = m; m; m = m->m_next)
  859         len += m->m_len;
  860 
  861     pad = padmap[len & 3];
  862 
  863     /*
  864      * The 3c509 automatically pads short packets to minimum ethernet length,
  865      * but we drop packets that are too large. Perhaps we should truncate
  866      * them instead?
  867      */
  868     if (len + pad > ETHER_MAX_LEN) {
  869         /* packet is obviously too large: toss it */
  870         ++ifp->if_oerrors;
  871         IF_DEQUEUE(&ifp->if_snd, m);
  872         m_freem(m);
  873         goto readcheck;
  874     }
  875     if (inw(BASE + EP_W1_FREE_TX) < len + pad + 4) {
  876         /* no room in FIFO */
  877         outw(BASE + EP_COMMAND, SET_TX_AVAIL_THRESH | (len + pad + 4));
  878         /* make sure */
  879         if (inw(BASE + EP_W1_FREE_TX) < len + pad + 4) {
  880             ifp->if_flags |= IFF_OACTIVE;
  881             splx(s);
  882             return;
  883         }
  884     }
  885     IF_DEQUEUE(&ifp->if_snd, m);
  886 
  887     outw(BASE + EP_W1_TX_PIO_WR_1, len); 
  888     outw(BASE + EP_W1_TX_PIO_WR_1, 0x0);        /* Second dword meaningless */
  889 
  890     for (top = m; m != 0; m = m->m_next)
  891         if (ep_ftst(F_ACCESS_32_BITS)) {
  892             outsl(BASE + EP_W1_TX_PIO_WR_1, mtod(m, caddr_t),
  893                   m->m_len / 4);
  894             if (m->m_len & 3)
  895                 outsb(BASE + EP_W1_TX_PIO_WR_1,
  896                       mtod(m, caddr_t) + (m->m_len & (~3)),
  897                       m->m_len & 3);
  898         } else {
  899             outsw(BASE + EP_W1_TX_PIO_WR_1, mtod(m, caddr_t), m->m_len / 2);
  900             if (m->m_len & 1)
  901                 outb(BASE + EP_W1_TX_PIO_WR_1,
  902                      *(mtod(m, caddr_t) + m->m_len - 1));
  903         }
  904 
  905     while (pad--)
  906         outb(BASE + EP_W1_TX_PIO_WR_1, 0);      /* Padding */
  907 
  908 #if NBPFILTER > 0
  909     if (ifp->if_bpf) {
  910         bpf_mtap(ifp, top);
  911     }
  912 #endif
  913 
  914     ifp->if_timer = 2;
  915     ifp->if_opackets++;
  916     m_freem(top);
  917 
  918     /*
  919      * Is another packet coming in? We don't want to overflow the tiny RX
  920      * fifo.
  921      */
  922 readcheck:
  923     if (inw(BASE + EP_W1_RX_STATUS) & RX_BYTES_MASK) {
  924         /*
  925          * we check if we have packets left, in that case we prepare to come
  926          * back later
  927          */
  928         if (ifp->if_snd.ifq_head) {
  929             outw(BASE + EP_COMMAND, SET_TX_AVAIL_THRESH | 8);
  930         }
  931         splx(s);
  932         return;
  933     }
  934     goto startagain;
  935 }
  936 
  937 void
  938 epintr(unit)
  939     int unit;
  940 {
  941     register struct ep_softc *sc = ep_softc[unit];
  942 
  943     if (sc->gone) {
  944         return;
  945     }
  946 
  947     ep_intr(sc);
  948 }
  949 
  950 void
  951 ep_intr(arg)
  952     void *arg;
  953 {
  954     struct ep_softc *sc;
  955     register int status;
  956     struct ifnet *ifp;
  957     int x;
  958 
  959     x = splbio();
  960 
  961     sc = (struct ep_softc *)arg;
  962 
  963     ifp = &sc->arpcom.ac_if;
  964 
  965     outw(BASE + EP_COMMAND, SET_INTR_MASK); /* disable all Ints */
  966 
  967 rescan:
  968 
  969     while ((status = inw(BASE + EP_STATUS)) & S_5_INTS) {
  970 
  971         /* first acknowledge all interrupt sources */
  972         outw(BASE + EP_COMMAND, ACK_INTR | (status & S_MASK));
  973 
  974         if (status & (S_RX_COMPLETE | S_RX_EARLY)) {
  975             epread(sc);
  976             continue;
  977         }
  978         if (status & S_TX_AVAIL) {
  979             /* we need ACK */
  980             ifp->if_timer = 0;
  981             ifp->if_flags &= ~IFF_OACTIVE;
  982             GO_WINDOW(1);
  983             inw(BASE + EP_W1_FREE_TX);
  984             epstart(ifp);
  985         }
  986         if (status & S_CARD_FAILURE) {
  987             ifp->if_timer = 0;
  988 #ifdef EP_LOCAL_STATS
  989             printf("\nep%d:\n\tStatus: %x\n", sc->unit, status);
  990             GO_WINDOW(4);
  991             printf("\tFIFO Diagnostic: %x\n", inw(BASE + EP_W4_FIFO_DIAG));
  992             printf("\tStat: %x\n", sc->stat);
  993             printf("\tIpackets=%d, Opackets=%d\n",
  994                 ifp->if_ipackets, ifp->if_opackets);
  995             printf("\tNOF=%d, NOMB=%d, BPFD=%d, RXOF=%d, RXOL=%d, TXU=%d\n",
  996                    sc->rx_no_first, sc->rx_no_mbuf, sc->rx_bpf_disc, sc->rx_overrunf,
  997                    sc->rx_overrunl, sc->tx_underrun);
  998 #else
  999 
 1000 #ifdef DIAGNOSTIC
 1001             printf("ep%d: Status: %x (input buffer overflow)\n", sc->unit, status);
 1002 #else
 1003             ++ifp->if_ierrors;
 1004 #endif
 1005 
 1006 #endif
 1007             epinit(sc);
 1008             splx(x);
 1009             return;
 1010         }
 1011         if (status & S_TX_COMPLETE) {
 1012             ifp->if_timer = 0;
 1013             /* we  need ACK. we do it at the end */
 1014             /*
 1015              * We need to read TX_STATUS until we get a 0 status in order to
 1016              * turn off the interrupt flag.
 1017              */
 1018             while ((status = inb(BASE + EP_W1_TX_STATUS)) & TXS_COMPLETE) {
 1019                 if (status & TXS_SUCCES_INTR_REQ);
 1020                 else if (status & (TXS_UNDERRUN | TXS_JABBER | TXS_MAX_COLLISION)) {
 1021                     outw(BASE + EP_COMMAND, TX_RESET);
 1022                     if (status & TXS_UNDERRUN) {
 1023 #ifdef EP_LOCAL_STATS
 1024                         sc->tx_underrun++;
 1025 #endif
 1026                     } else {
 1027                         if (status & TXS_JABBER);
 1028                         else    /* TXS_MAX_COLLISION - we shouldn't get here */
 1029                             ++ifp->if_collisions;
 1030                     }
 1031                     ++ifp->if_oerrors;
 1032                     outw(BASE + EP_COMMAND, TX_ENABLE);
 1033                     /*
 1034                      * To have a tx_avail_int but giving the chance to the
 1035                      * Reception
 1036                      */
 1037                     if (ifp->if_snd.ifq_head) {
 1038                         outw(BASE + EP_COMMAND, SET_TX_AVAIL_THRESH | 8);
 1039                     }
 1040                 }
 1041                 outb(BASE + EP_W1_TX_STATUS, 0x0);      /* pops up the next
 1042                                                          * status */
 1043             }                   /* while */
 1044             ifp->if_flags &= ~IFF_OACTIVE;
 1045             GO_WINDOW(1);
 1046             inw(BASE + EP_W1_FREE_TX);
 1047             epstart(ifp);
 1048         }                       /* end TX_COMPLETE */
 1049     }
 1050 
 1051     outw(BASE + EP_COMMAND, C_INTR_LATCH);      /* ACK int Latch */
 1052 
 1053     if ((status = inw(BASE + EP_STATUS)) & S_5_INTS)
 1054         goto rescan;
 1055 
 1056     /* re-enable Ints */
 1057     outw(BASE + EP_COMMAND, SET_INTR_MASK | S_5_INTS);
 1058 
 1059     splx(x);
 1060 }
 1061 
 1062 static void
 1063 epread(sc)
 1064     register struct ep_softc *sc;
 1065 {
 1066     struct ether_header *eh;
 1067     struct mbuf *top, *mcur, *m;
 1068     struct ifnet *ifp;
 1069     int lenthisone;
 1070 
 1071     short rx_fifo2, status;
 1072     register short delta;
 1073     register short rx_fifo;
 1074 
 1075     ifp = &sc->arpcom.ac_if;
 1076     status = inw(BASE + EP_W1_RX_STATUS);
 1077 
 1078 read_again:
 1079 
 1080     if (status & ERR_RX) {
 1081         ++ifp->if_ierrors;
 1082         if (status & ERR_RX_OVERRUN) {
 1083             /*
 1084              * we can think the rx latency is actually greather than we
 1085              * expect
 1086              */
 1087 #ifdef EP_LOCAL_STATS
 1088             if (ep_ftst(F_RX_FIRST))
 1089                 sc->rx_overrunf++;
 1090             else
 1091                 sc->rx_overrunl++;
 1092 #endif
 1093         }
 1094         goto out;
 1095     }
 1096     rx_fifo = rx_fifo2 = status & RX_BYTES_MASK;
 1097 
 1098     if (ep_ftst(F_RX_FIRST)) {
 1099         MGETHDR(m, M_DONTWAIT, MT_DATA);
 1100         if (!m)
 1101             goto out;
 1102         if (rx_fifo >= MINCLSIZE)
 1103             MCLGET(m, M_DONTWAIT);
 1104         sc->top = sc->mcur = top = m;
 1105 #define EROUND  ((sizeof(struct ether_header) + 3) & ~3)
 1106 #define EOFF    (EROUND - sizeof(struct ether_header))
 1107         top->m_data += EOFF;
 1108 
 1109         /* Read what should be the header. */
 1110         insw(BASE + EP_W1_RX_PIO_RD_1,
 1111              mtod(top, caddr_t), sizeof(struct ether_header) / 2);
 1112         top->m_len = sizeof(struct ether_header);
 1113         rx_fifo -= sizeof(struct ether_header);
 1114         sc->cur_len = rx_fifo2;
 1115     } else {
 1116         /* come here if we didn't have a complete packet last time */
 1117         top = sc->top;
 1118         m = sc->mcur;
 1119         sc->cur_len += rx_fifo2;
 1120     }
 1121 
 1122     /* Reads what is left in the RX FIFO */
 1123     while (rx_fifo > 0) {
 1124         lenthisone = min(rx_fifo, M_TRAILINGSPACE(m));
 1125         if (lenthisone == 0) {  /* no room in this one */
 1126             mcur = m;
 1127             MGET(m, M_DONTWAIT, MT_DATA);
 1128             if (!m)
 1129                 goto out;
 1130             if (rx_fifo >= MINCLSIZE)
 1131                 MCLGET(m, M_DONTWAIT);
 1132             m->m_len = 0;
 1133             mcur->m_next = m;
 1134             lenthisone = min(rx_fifo, M_TRAILINGSPACE(m));
 1135         }
 1136         if (ep_ftst(F_ACCESS_32_BITS)) { /* default for EISA configured cards*/
 1137             insl(BASE + EP_W1_RX_PIO_RD_1, mtod(m, caddr_t) + m->m_len,
 1138                  lenthisone / 4);
 1139             m->m_len += (lenthisone & ~3);
 1140             if (lenthisone & 3)
 1141                 insb(BASE + EP_W1_RX_PIO_RD_1,
 1142                      mtod(m, caddr_t) + m->m_len,
 1143                      lenthisone & 3);
 1144             m->m_len += (lenthisone & 3);
 1145         } else {
 1146             insw(BASE + EP_W1_RX_PIO_RD_1, mtod(m, caddr_t) + m->m_len,
 1147                  lenthisone / 2);
 1148             m->m_len += lenthisone;
 1149             if (lenthisone & 1)
 1150                 *(mtod(m, caddr_t) + m->m_len - 1) = inb(BASE + EP_W1_RX_PIO_RD_1);
 1151         }
 1152         rx_fifo -= lenthisone;
 1153     }
 1154 
 1155     if (status & ERR_RX_INCOMPLETE) {   /* we haven't received the complete
 1156                                          * packet */
 1157         sc->mcur = m;
 1158 #ifdef EP_LOCAL_STATS
 1159         sc->rx_no_first++;      /* to know how often we come here */
 1160 #endif
 1161         ep_frst(F_RX_FIRST);
 1162         if (!((status = inw(BASE + EP_W1_RX_STATUS)) & ERR_RX_INCOMPLETE)) {
 1163             /* we see if by now, the packet has completly arrived */
 1164             goto read_again;
 1165         }
 1166         outw(BASE + EP_COMMAND, SET_RX_EARLY_THRESH | RX_NEXT_EARLY_THRESH);
 1167         return;
 1168     }
 1169 all_pkt:
 1170     outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK);
 1171     ++ifp->if_ipackets;
 1172     ep_fset(F_RX_FIRST);
 1173     top->m_pkthdr.rcvif = &sc->arpcom.ac_if;
 1174     top->m_pkthdr.len = sc->cur_len;
 1175 
 1176 #if NBPFILTER > 0
 1177     if (ifp->if_bpf)
 1178         bpf_mtap(ifp, top);
 1179 #endif
 1180 #ifdef BRIDGE
 1181     if (do_bridge) {
 1182         struct ifnet * bdg_ifp ;
 1183 
 1184         bdg_ifp = bridge_in(top);
 1185         if (bdg_ifp == BDG_DROP)
 1186             goto dropit ;
 1187         if (bdg_ifp != BDG_LOCAL)
 1188             bdg_forward(&(sc->top), bdg_ifp);
 1189         if (bdg_ifp !=BDG_LOCAL && bdg_ifp !=BDG_BCAST && bdg_ifp !=BDG_MCAST)
 1190             goto dropit ;
 1191         /* all others accepted locally */
 1192         goto getit ;
 1193     }
 1194 #endif
 1195 
 1196     /*
 1197      * If we are in promiscuous mode, we have to
 1198      * check if this packet is really ours.
 1199      */
 1200     eh = mtod(top, struct ether_header *);
 1201     if ((ifp->if_flags & IFF_PROMISC) &&
 1202         (eh->ether_dhost[0] & 1) == 0 &&
 1203         bcmp(eh->ether_dhost, sc->arpcom.ac_enaddr,
 1204              sizeof(eh->ether_dhost)) != 0 &&
 1205         bcmp(eh->ether_dhost, etherbroadcastaddr,
 1206              sizeof(eh->ether_dhost)) != 0) {
 1207 dropit:
 1208         if (sc->top) {
 1209             m_freem(sc->top);
 1210             sc->top = 0;
 1211         }
 1212         ep_fset(F_RX_FIRST);
 1213 #ifdef EP_LOCAL_STATS
 1214         sc->rx_bpf_disc++;
 1215 #endif
 1216         while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
 1217         outw(BASE + EP_COMMAND, SET_RX_EARLY_THRESH | RX_INIT_EARLY_THRESH);
 1218         return;
 1219     }
 1220 getit:
 1221     eh = mtod(top, struct ether_header *);
 1222     m_adj(top, sizeof(struct ether_header));
 1223     ether_input(ifp, eh, top);
 1224     sc->top = 0;
 1225     while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
 1226     outw(BASE + EP_COMMAND, SET_RX_EARLY_THRESH | RX_INIT_EARLY_THRESH);
 1227     return;
 1228 
 1229 out:
 1230     outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK);
 1231     if (sc->top) {
 1232         m_freem(sc->top);
 1233         sc->top = 0;
 1234 #ifdef EP_LOCAL_STATS
 1235         sc->rx_no_mbuf++;
 1236 #endif
 1237     }
 1238     ep_fset(F_RX_FIRST);
 1239     while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
 1240     outw(BASE + EP_COMMAND, SET_RX_EARLY_THRESH | RX_INIT_EARLY_THRESH);
 1241 }
 1242 
 1243 /*
 1244  * Look familiar?
 1245  */
 1246 static int
 1247 epioctl(ifp, cmd, data)
 1248     register struct ifnet *ifp;
 1249     int cmd;
 1250     caddr_t data;
 1251 {
 1252     register struct ifaddr *ifa = (struct ifaddr *) data;
 1253     struct ep_softc *sc = ifp->if_softc;
 1254     struct ifreq *ifr = (struct ifreq *) data;
 1255     int s, error = 0;
 1256 
 1257     s = splimp();
 1258 
 1259     switch (cmd) {
 1260       case SIOCSIFADDR:
 1261         ifp->if_flags |= IFF_UP;
 1262 
 1263         /* netifs are BUSY when UP */
 1264 
 1265         switch (ifa->ifa_addr->sa_family) {
 1266 #ifdef INET
 1267           case AF_INET:
 1268             epinit(sc); /* before arpwhohas */
 1269             arp_ifinit((struct arpcom *)ifp, ifa);
 1270             break;
 1271 #endif
 1272 #ifdef IPX
 1273           case AF_IPX:
 1274             {
 1275                 register struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr);
 1276 
 1277                 if (ipx_nullhost(*ina))
 1278                     ina->x_host =
 1279                         *(union ipx_host *) (sc->arpcom.ac_enaddr);
 1280                 else {
 1281                     ifp->if_flags &= ~IFF_RUNNING;
 1282                     bcopy((caddr_t) ina->x_host.c_host,
 1283                           (caddr_t) sc->arpcom.ac_enaddr,
 1284                           sizeof(sc->arpcom.ac_enaddr));
 1285                 }
 1286                 epinit(sc);
 1287                 break;
 1288             }
 1289 #endif
 1290 #ifdef NS
 1291           case AF_NS:
 1292             {
 1293                 register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
 1294 
 1295                 if (ns_nullhost(*ina))
 1296                     ina->x_host =
 1297                         *(union ns_host *) (sc->arpcom.ac_enaddr);
 1298                 else {
 1299                     ifp->if_flags &= ~IFF_RUNNING;
 1300                     bcopy((caddr_t) ina->x_host.c_host,
 1301                           (caddr_t) sc->arpcom.ac_enaddr,
 1302                           sizeof(sc->arpcom.ac_enaddr));
 1303                 }
 1304                 epinit(sc);
 1305                 break;
 1306             }
 1307 #endif
 1308           default:
 1309             epinit(sc);
 1310             break;
 1311         }
 1312         break;
 1313       case SIOCGIFADDR:
 1314         { 
 1315           struct sockaddr *sa; 
 1316  
 1317           sa = (struct sockaddr *) & ifr->ifr_data;
 1318           bcopy((caddr_t) sc->arpcom.ac_enaddr, 
 1319                 (caddr_t) sa->sa_data, ETHER_ADDR_LEN);
 1320         }
 1321         break;
 1322       case SIOCSIFFLAGS:
 1323 
 1324         if ((ifp->if_flags & IFF_UP) == 0 && ifp->if_flags & IFF_RUNNING) {
 1325             ifp->if_flags &= ~IFF_RUNNING;
 1326             epstop(sc);
 1327             break;
 1328         } else {
 1329             /* reinitialize card on any parameter change */
 1330             epinit(sc);
 1331             break;
 1332         }
 1333 
 1334         /* NOTREACHED */
 1335         break;
 1336 #ifdef notdef
 1337       case SIOCGHWADDR:
 1338         bcopy((caddr_t) sc->sc_addr, (caddr_t) & ifr->ifr_data,
 1339               sizeof(sc->sc_addr));
 1340         break;
 1341 #endif
 1342         case SIOCSIFMTU:
 1343 
 1344                 /*
 1345                  * Set the interface MTU.
 1346                  */
 1347                 if (ifr->ifr_mtu > ETHERMTU) {
 1348                         error = EINVAL;
 1349                 } else {
 1350                         ifp->if_mtu = ifr->ifr_mtu;
 1351                 }
 1352                 break; 
 1353         case SIOCADDMULTI:
 1354         case SIOCDELMULTI:
 1355             /* Now this driver has no support for programmable
 1356              * multicast filters. If some day it will gain this
 1357              * support this part of code must be extended.
 1358              */
 1359             error = 0;
 1360             break;
 1361       default:
 1362                 error = EINVAL;
 1363     }
 1364 
 1365     splx(s);
 1366 
 1367     return (error);
 1368 }
 1369 
 1370 static void
 1371 epwatchdog(ifp)
 1372     struct ifnet *ifp;
 1373 {
 1374     struct ep_softc *sc = ifp->if_softc;
 1375 
 1376     /*
 1377     printf("ep: watchdog\n");
 1378 
 1379     log(LOG_ERR, "ep%d: watchdog\n", ifp->if_unit);
 1380     ifp->if_oerrors++;
 1381     */
 1382 
 1383     if (sc->gone) {
 1384         return;
 1385     }
 1386 
 1387     ifp->if_flags &= ~IFF_OACTIVE;
 1388     epstart(ifp);
 1389     ep_intr(ifp->if_softc);
 1390 }
 1391 
 1392 static void
 1393 epstop(sc)
 1394     struct ep_softc *sc;
 1395 {
 1396     if (sc->gone) {
 1397         return;
 1398     }
 1399 
 1400     outw(BASE + EP_COMMAND, RX_DISABLE);
 1401     outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK);
 1402     while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
 1403     outw(BASE + EP_COMMAND, TX_DISABLE);
 1404     outw(BASE + EP_COMMAND, STOP_TRANSCEIVER);
 1405     outw(BASE + EP_COMMAND, RX_RESET);
 1406     outw(BASE + EP_COMMAND, TX_RESET);
 1407     while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
 1408     outw(BASE + EP_COMMAND, C_INTR_LATCH);
 1409     outw(BASE + EP_COMMAND, SET_RD_0_MASK);
 1410     outw(BASE + EP_COMMAND, SET_INTR_MASK);
 1411     outw(BASE + EP_COMMAND, SET_RX_FILTER);
 1412 }
 1413 
 1414 
 1415 #if 0
 1416 static int
 1417 send_ID_sequence(port)
 1418     int port;
 1419 {
 1420     int cx, al;
 1421 
 1422     for (al = 0xff, cx = 0; cx < 255; cx++) {
 1423         outb(port, al);
 1424         al <<= 1;
 1425         if (al & 0x100)
 1426             al ^= 0xcf;
 1427     }
 1428     return (1);
 1429 }
 1430 #endif
 1431 
 1432 
 1433 /*
 1434  * We get eeprom data from the id_port given an offset into the eeprom.
 1435  * Basically; after the ID_sequence is sent to all of the cards; they enter
 1436  * the ID_CMD state where they will accept command requests. 0x80-0xbf loads
 1437  * the eeprom data.  We then read the port 16 times and with every read; the
 1438  * cards check for contention (ie: if one card writes a 0 bit and another
 1439  * writes a 1 bit then the host sees a 0. At the end of the cycle; each card
 1440  * compares the data on the bus; if there is a difference then that card goes
 1441  * into ID_WAIT state again). In the meantime; one bit of data is returned in
 1442  * the AX register which is conveniently returned to us by inb().  Hence; we
 1443  * read 16 times getting one bit of data with each read.
 1444  */
 1445 static int
 1446 get_eeprom_data(id_port, offset)
 1447     int id_port;
 1448     int offset;
 1449 {
 1450     int i, data = 0;
 1451     outb(id_port, 0x80 + offset);
 1452     DELAY(1000);
 1453     for (i = 0; i < 16; i++)
 1454         data = (data << 1) | (inw(id_port) & 1);
 1455     return (data);
 1456 }
 1457 
 1458 #endif                          /* NEP > 0 */

Cache object: 726813b57d7f39587c4843b6f749fb52


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.