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/dev/isa/if_ep_isa.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 /*      $NetBSD: if_ep_isa.c,v 1.33 2002/10/02 03:10:47 thorpej Exp $   */
    2 
    3 /*-
    4  * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
    9  * NASA Ames Research Center.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  * 3. All advertising materials mentioning features or use of this software
   20  *    must display the following acknowledgement:
   21  *      This product includes software developed by the NetBSD
   22  *      Foundation, Inc. and its contributors.
   23  * 4. Neither the name of The NetBSD Foundation nor the names of its
   24  *    contributors may be used to endorse or promote products derived
   25  *    from this software without specific prior written permission.
   26  *
   27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   37  * POSSIBILITY OF SUCH DAMAGE.
   38  */
   39 
   40 /*
   41  * Copyright (c) 1997 Jonathan Stone <jonathan@NetBSD.org>
   42  * Copyright (c) 1994 Herb Peyerl <hpeyerl@beer.org>
   43  * All rights reserved.
   44  *
   45  * Redistribution and use in source and binary forms, with or without
   46  * modification, are permitted provided that the following conditions
   47  * are met:
   48  * 1. Redistributions of source code must retain the above copyright
   49  *    notice, this list of conditions and the following disclaimer.
   50  * 2. Redistributions in binary form must reproduce the above copyright
   51  *    notice, this list of conditions and the following disclaimer in the
   52  *    documentation and/or other materials provided with the distribution.
   53  * 3. All advertising materials mentioning features or use of this software
   54  *    must display the following acknowledgement:
   55  *      This product includes software developed by Herb Peyerl.
   56  * 4. The name of Herb Peyerl may not be used to endorse or promote products
   57  *    derived from this software without specific prior written permission.
   58  *
   59  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   60  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   61  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   62  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   63  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   64  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   65  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   66  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   67  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   68  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   69  */
   70 
   71 #include <sys/cdefs.h>
   72 __KERNEL_RCSID(0, "$NetBSD: if_ep_isa.c,v 1.33 2002/10/02 03:10:47 thorpej Exp $");
   73 
   74 #include <sys/param.h>
   75 #include <sys/systm.h>
   76 #include <sys/mbuf.h>
   77 #include <sys/socket.h>
   78 #include <sys/ioctl.h>
   79 #include <sys/errno.h>
   80 #include <sys/syslog.h>
   81 #include <sys/select.h>
   82 #include <sys/device.h>
   83 #include <sys/queue.h>
   84 
   85 #include <net/if.h>
   86 #include <net/if_dl.h>
   87 #include <net/if_ether.h>
   88 #include <net/if_media.h>
   89 
   90 #include <machine/cpu.h>
   91 #include <machine/bus.h>
   92 #include <machine/intr.h>
   93 
   94 #include <dev/mii/miivar.h>
   95 
   96 #include <dev/ic/elink3var.h>
   97 #include <dev/ic/elink3reg.h>
   98 
   99 #include <dev/isa/isavar.h>
  100 #include <dev/isa/elink.h>
  101 
  102 int ep_isa_probe __P((struct device *, struct cfdata *, void *));
  103 void ep_isa_attach __P((struct device *, struct device *, void *));
  104 
  105 CFATTACH_DECL(ep_isa, sizeof(struct ep_softc),
  106     ep_isa_probe, ep_isa_attach, NULL, NULL);
  107 
  108 static  void epaddcard __P((int, int, int, int));
  109 
  110 /*
  111  * This keeps track of which ISAs have been through an ep probe sequence.
  112  * A simple static variable isn't enough, since it's conceivable that
  113  * a system might have more than one ISA bus.
  114  *
  115  * The "er_bus" member is the unit number of the parent ISA bus, e.g. ""
  116  * for "isa0".
  117  */
  118 struct ep_isa_done_probe {
  119         LIST_ENTRY(ep_isa_done_probe)   er_link;
  120         int                             er_bus;
  121 };
  122 static LIST_HEAD(, ep_isa_done_probe) ep_isa_all_probes;
  123 static int ep_isa_probes_initialized;
  124 
  125 #define MAXEPCARDS      20      /* if you have more than 20, you lose */
  126 
  127 static struct epcard {
  128         int     bus;
  129         int     iobase;
  130         int     irq;
  131         char    available;
  132         long    model;
  133 } epcards[MAXEPCARDS];
  134 static int nepcards;
  135 
  136 static void
  137 epaddcard(bus, iobase, irq, model)
  138         int bus, iobase, irq, model;
  139 {
  140 
  141         if (nepcards >= MAXEPCARDS)
  142                 return;
  143         epcards[nepcards].bus = bus;
  144         epcards[nepcards].iobase = iobase;
  145         epcards[nepcards].irq = (irq == 2) ? 9 : irq;
  146         epcards[nepcards].model = model;
  147         epcards[nepcards].available = 1;
  148         nepcards++;
  149 }
  150 
  151 /*
  152  * 3c509 cards on the ISA bus are probed in ethernet address order.
  153  * The probe sequence requires careful orchestration, and we'd like
  154  * like to allow the irq and base address to be wildcarded. So, we
  155  * probe all the cards the first time epprobe() is called. On subsequent
  156  * calls we look for matching cards.
  157  */
  158 int
  159 ep_isa_probe(parent, match, aux)
  160         struct device *parent;
  161         struct cfdata *match;
  162         void *aux;
  163 {
  164         struct isa_attach_args *ia = aux;
  165         bus_space_tag_t iot = ia->ia_iot;
  166         bus_space_handle_t ioh;
  167         int slot, iobase, irq, i;
  168         u_int16_t vendor, model;
  169         struct ep_isa_done_probe *er;
  170         int bus = parent->dv_unit;
  171 
  172         if (ISA_DIRECT_CONFIG(ia))
  173                 return (0);
  174 
  175         if (ep_isa_probes_initialized == 0) {
  176                 LIST_INIT(&ep_isa_all_probes);
  177                 ep_isa_probes_initialized = 1;
  178         }
  179 
  180         /*
  181          * Probe this bus if we haven't done so already.
  182          */
  183         for (er = ep_isa_all_probes.lh_first; er != NULL;
  184             er = er->er_link.le_next)
  185                 if (er->er_bus == parent->dv_unit)
  186                         goto bus_probed;
  187 
  188         /*
  189          * Mark this bus so we don't probe it again.
  190          */
  191         er = (struct ep_isa_done_probe *)
  192             malloc(sizeof(struct ep_isa_done_probe), M_DEVBUF, M_NOWAIT);
  193         if (er == NULL)
  194                 panic("ep_isa_probe: can't allocate state storage");
  195 
  196         er->er_bus = bus;
  197         LIST_INSERT_HEAD(&ep_isa_all_probes, er, er_link);
  198 
  199         /*
  200          * Map the Etherlink ID port for the probe sequence.
  201          */
  202         if (bus_space_map(iot, ELINK_ID_PORT, 1, 0, &ioh)) {
  203                 printf("ep_isa_probe: can't map Etherlink ID port\n");
  204                 return 0;
  205         }
  206 
  207         for (slot = 0; slot < MAXEPCARDS; slot++) {
  208                 elink_reset(iot, ioh, parent->dv_unit);
  209                 elink_idseq(iot, ioh, ELINK_509_POLY);
  210 
  211                 /* Untag all the adapters so they will talk to us. */
  212                 if (slot == 0)
  213                         bus_space_write_1(iot, ioh, 0, TAG_ADAPTER + 0);
  214 
  215                 vendor = bswap16(epreadeeprom(iot, ioh, EEPROM_MFG_ID));
  216                 if (vendor != MFG_ID)
  217                         continue;
  218 
  219                 model = bswap16(epreadeeprom(iot, ioh, EEPROM_PROD_ID));
  220                 /*
  221                  * XXX: Add a new product id to check for other cards
  222                  * (3c515?) and fix the check in ep_isa_attach.
  223                  */
  224                 if ((model & 0xfff0) != PROD_ID_3C509) {
  225 #ifndef trusted
  226                         printf(
  227                          "ep_isa_probe: ignoring model %04x\n", model);
  228 #endif
  229                         continue;
  230                         }
  231 
  232                 iobase = epreadeeprom(iot, ioh, EEPROM_ADDR_CFG);
  233                 iobase = (iobase & 0x1f) * 0x10 + 0x200;
  234 
  235                 irq = epreadeeprom(iot, ioh, EEPROM_RESOURCE_CFG);
  236                 irq >>= 12;
  237 
  238                 /* XXX Should ignore card if non-ISA(EISA) io address? -chb */
  239 
  240                 /*
  241                  * Don't attach a 3c509 in PnP mode.
  242                  * PnP mode was added with the 3C509B.
  243                  * Check some EEPROM registers to make sure this is really
  244                  * a 3C509B and test whether it is in PnP mode.
  245                  */
  246                 if ((model & 0xfff0) == PROD_ID_3C509) {
  247                         u_int16_t cksum, eepromrev, eeprom_cap, eeprom_hi;
  248 
  249 
  250                         /*
  251                          * Fetch all the info we need to ascertain whether
  252                          * the card is  PnP capable and in PnP mode.
  253                          * Skip over PnP cards.
  254                          */
  255 
  256                         /* secondary configurable data checksum */
  257                         cksum = epreadeeprom(iot, ioh, EEPROM_CHECKSUM_EL3)
  258                             & 0xFF;
  259                         for (i = EEPROM_CONFIG_HIGH;
  260                             i < EEPROM_CHECKSUM_EL3; i++) {
  261                                 cksum ^= epreadeeprom(iot, ioh, i);
  262                         }
  263                         cksum = (cksum & 0xFF) ^ ((cksum >> 8) & 0xFF);
  264 
  265                         eepromrev = epreadeeprom(iot, ioh, EEPROM_SSI);
  266                         eeprom_hi = epreadeeprom(iot, ioh, EEPROM_CONFIG_HIGH);
  267                         eeprom_cap = epreadeeprom(iot, ioh, EEPROM_CAP);
  268 
  269                         /*
  270                          * Stop card responding to contention in future.
  271                          * (NB: stops rsponse to all reads from ID port.)
  272                          */
  273                         bus_space_write_1(iot, ioh, 0, TAG_ADAPTER + 1);
  274 
  275                         if (cksum != 0) {
  276 #if 0
  277                                 printf("ep_isa_probe: cksum mismatch 0x%02x\n",
  278                                     (int)cksum);
  279 #endif
  280                         }
  281                         else if ((eepromrev & 0xF) < 1) {
  282                                 /* 3C509B is adapter revision level 1. */
  283 #if 0
  284                                 printf("ep_isa_probe revision level 0\n");
  285 #endif
  286                         }
  287                         else if (eeprom_cap != 0x2083) {
  288 #if 0
  289                                 printf("ep_isa_probe: capabilities word mismatch0x%03x\n",
  290                                     (int)epreadeeprom(iot, ioh, EEPROM_CAP));
  291 #endif
  292                         }
  293                         else
  294                           /*
  295                            * we have a 3c509B with PnP capabilities.
  296                            * Test partly documented bit which toggles when
  297                            * in  PnP mode.
  298                            */
  299                         if ((eeprom_hi & 8) != 0) {
  300                                 printf("3COM 3C509B Ethernet card in PnP mode\n");
  301                                 continue;
  302                         }
  303                 }
  304 
  305                 /*
  306                  * XXX: this should probably not be done here
  307                  * because it enables the drq/irq lines from
  308                  * the board. Perhaps it should be done after
  309                  * we have checked for irq/drq collisions?
  310                  *
  311                  * According to the 3COM docs, this does not enable
  312                  * the irq lines. -chb
  313                  */
  314                 bus_space_write_1(iot, ioh, 0, ACTIVATE_ADAPTER_TO_CONFIG);
  315 
  316                 epaddcard(bus, iobase, irq, model);
  317         }
  318         /* XXX should we sort by ethernet address? */
  319 
  320         bus_space_unmap(iot, ioh, 1);
  321 
  322 bus_probed:
  323 
  324         if (ia->ia_nio < 1)
  325                 return (0);
  326         if (ia->ia_nirq < 1)
  327                 return (0);
  328 
  329         for (i = 0; i < nepcards; i++) {
  330                 if (epcards[i].bus != bus)
  331                         continue;
  332                 if (epcards[i].available == 0)
  333                         continue;
  334 
  335                 if (ia->ia_io[0].ir_addr != ISACF_PORT_DEFAULT &&
  336                     ia->ia_io[0].ir_addr != epcards[i].iobase)
  337                         continue;
  338 
  339                 if (ia->ia_irq[0].ir_irq != ISACF_IRQ_DEFAULT &&
  340                     ia->ia_irq[0].ir_irq != epcards[i].irq)
  341                         continue;
  342 
  343                 goto good;
  344         }
  345         return 0;
  346 
  347 good:
  348         epcards[i].available = 0;
  349 
  350         ia->ia_nio = 1;
  351         ia->ia_io[0].ir_addr = epcards[i].iobase;
  352         ia->ia_io[0].ir_size = 0x10;
  353 
  354         ia->ia_nirq = 1;
  355         ia->ia_irq[0].ir_irq = epcards[i].irq;
  356 
  357         ia->ia_niomem = 0;
  358         ia->ia_ndrq = 0;
  359 
  360         ia->ia_aux = (void *)epcards[i].model;
  361         return 1;
  362 }
  363 
  364 void
  365 ep_isa_attach(parent, self, aux)
  366         struct device *parent, *self;
  367         void *aux;
  368 {
  369         struct ep_softc *sc = (void *)self;
  370         struct isa_attach_args *ia = aux;
  371         bus_space_tag_t iot = ia->ia_iot;
  372         bus_space_handle_t ioh;
  373         int chipset;
  374 
  375         /* Map i/o space. */
  376         if (bus_space_map(iot, ia->ia_io[0].ir_addr, 0x10, 0, &ioh)) {
  377                 printf(": can't map i/o space\n");
  378                 return;
  379         }
  380 
  381         sc->sc_iot = iot;
  382         sc->sc_ioh = ioh;
  383         sc->bustype = ELINK_BUS_ISA;
  384 
  385         sc->enable = NULL;
  386         sc->disable = NULL;
  387         sc->enabled = 1;
  388 
  389         chipset = (int)(long)ia->ia_aux;
  390         if ((chipset & 0xfff0) == PROD_ID_3C509) {
  391                 printf(": 3Com 3C509 Ethernet\n");
  392                 epconfig(sc, ELINK_CHIPSET_3C509, NULL);
  393         } else {
  394                 /*
  395                  * XXX: Maybe a 3c515, but the check in ep_isa_probe looks
  396                  * at the moment only for a 3c509.
  397                  */
  398                 printf(": unknown 3Com Ethernet card: %04x\n", chipset);
  399                 return;
  400         }
  401 
  402         sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq[0].ir_irq,
  403             IST_EDGE, IPL_NET, epintr, sc);
  404 }

Cache object: 531c9261d717052ce6fbdb72c849569e


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