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

Cache object: a9c0daf2fe2f186e50e5b897ff945d08


[ 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.