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/fe/if_fe_pccard.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  * All Rights Reserved, Copyright (C) Fujitsu Limited 1995
    3  *
    4  * This software may be used, modified, copied, distributed, and sold, in
    5  * both source and binary form provided that the above copyright, these
    6  * terms and the following disclaimer are retained.  The name of the author
    7  * and/or the contributor may not be used to endorse or promote products
    8  * derived from this software without specific prior written permission.
    9  *
   10  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND THE CONTRIBUTOR ``AS IS'' AND
   11  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   12  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   13  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR THE CONTRIBUTOR BE LIABLE
   14  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   15  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   16  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION.
   17  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   18  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   19  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   20  * SUCH DAMAGE.
   21  *
   22  */
   23 
   24 #include <sys/cdefs.h>
   25 __FBSDID("$FreeBSD: releng/9.0/sys/dev/fe/if_fe_pccard.c 199798 2009-11-25 13:31:17Z rwatson $");
   26 
   27 #include <sys/param.h>
   28 #include <sys/kernel.h>
   29 #include <sys/socket.h>
   30 #include <sys/systm.h>
   31 #include <sys/module.h>
   32 
   33 #include <sys/bus.h>
   34 #include <machine/bus.h>
   35 #include <sys/rman.h>
   36 
   37 #include <net/ethernet.h>
   38 #include <net/if.h>
   39 #include <net/if_mib.h>
   40 #include <net/if_media.h>
   41 
   42 #include <netinet/in.h>
   43 #include <netinet/if_ether.h>
   44 
   45 #include <dev/fe/mb86960.h>
   46 #include <dev/fe/if_fereg.h>
   47 #include <dev/fe/if_fevar.h>
   48 
   49 #include <dev/pccard/pccardvar.h>
   50 #include <dev/pccard/pccard_cis.h>
   51 
   52 #include "card_if.h"
   53 #include "pccarddevs.h"
   54 
   55 /*
   56  *      PC Card (PCMCIA) specific code.
   57  */
   58 static int fe_pccard_probe(device_t);
   59 static int fe_pccard_attach(device_t);
   60 static int fe_pccard_detach(device_t);
   61 
   62 static const struct fe_pccard_product {
   63         struct pccard_product mpp_product;
   64         int mpp_flags;
   65         int mpp_cfe;
   66 #define MPP_MBH10302 1
   67 #define MPP_ANYFUNC 2
   68 #define MPP_SKIP_TO_CFE 4
   69 } fe_pccard_products[] = {
   70         /* These need to be first */
   71         { PCMCIA_CARD(FUJITSU2, FMV_J181), MPP_MBH10302 },
   72         { PCMCIA_CARD(FUJITSU2, FMV_J182), 0 },
   73         { PCMCIA_CARD(FUJITSU2, FMV_J182A), 0 },
   74         { PCMCIA_CARD(FUJITSU2, ITCFJ182A), 0 },
   75         /* These need to be second */
   76         { PCMCIA_CARD(TDK, LAK_CD011), 0 }, 
   77         { PCMCIA_CARD(TDK, LAK_CD021BX), 0 }, 
   78         { PCMCIA_CARD(TDK, LAK_CF010), 0 }, 
   79 #if 0 /* XXX 86960-based? */
   80         { PCMCIA_CARD(TDK, LAK_DFL9610), 0 }, 
   81 #endif
   82         { PCMCIA_CARD(CONTEC, CNETPC), MPP_SKIP_TO_CFE, 2 },
   83         { PCMCIA_CARD(FUJITSU, LA501), 0 },
   84         { PCMCIA_CARD(FUJITSU, LA10S), 0 },
   85         { PCMCIA_CARD(FUJITSU, NE200T), MPP_MBH10302 },/* Sold by Eagle */
   86         { PCMCIA_CARD(HITACHI, HT_4840), MPP_MBH10302 | MPP_SKIP_TO_CFE, 10 },
   87         { PCMCIA_CARD(RATOC, REX_R280), 0 },
   88         { PCMCIA_CARD(XIRCOM, CE), MPP_ANYFUNC },
   89         { { NULL } }
   90 };
   91 
   92 static int
   93 fe_pccard_probe(device_t dev)
   94 {
   95         int             error;
   96         uint32_t        fcn = PCCARD_FUNCTION_UNSPEC;
   97         const struct fe_pccard_product *pp;
   98         int i;
   99 
  100         if ((pp = (const struct fe_pccard_product *)pccard_product_lookup(dev,
  101                  (const struct pccard_product *)fe_pccard_products,
  102                  sizeof(fe_pccard_products[0]), NULL)) != NULL) {
  103                 if (pp->mpp_product.pp_name != NULL)
  104                         device_set_desc(dev, pp->mpp_product.pp_name);
  105                 if (pp->mpp_flags & MPP_ANYFUNC)
  106                         return (0);
  107                 /* Make sure we're a network function */
  108                 error = pccard_get_function(dev, &fcn);
  109                 if (error != 0)
  110                         return (error);
  111                 if (fcn != PCCARD_FUNCTION_NETWORK)
  112                         return (ENXIO);
  113                 if (pp->mpp_flags & MPP_SKIP_TO_CFE) {
  114                         for (i = pp->mpp_cfe; i < 32; i++) {
  115                                 if (pccard_select_cfe(dev, i) == 0)
  116                                         goto good;
  117                         }
  118                         device_printf(dev,
  119                             "Failed to map CFE %d or higher\n", pp->mpp_cfe);
  120                         return ENXIO;
  121                 }
  122         good:;
  123                 return (0);
  124         }
  125         return (ENXIO);
  126 }
  127 
  128 static device_method_t fe_pccard_methods[] = {
  129         /* Device interface */
  130         DEVMETHOD(device_probe,         fe_pccard_probe),
  131         DEVMETHOD(device_attach,        fe_pccard_attach),
  132         DEVMETHOD(device_detach,        fe_pccard_detach),
  133 
  134         { 0, 0 }
  135 };
  136 
  137 static driver_t fe_pccard_driver = {
  138         "fe",
  139         fe_pccard_methods,
  140         sizeof (struct fe_softc)
  141 };
  142 
  143 DRIVER_MODULE(fe, pccard, fe_pccard_driver, fe_devclass, 0, 0);
  144 MODULE_DEPEND(fe, pccard, 1, 1, 1);
  145 
  146 static int fe_probe_mbh(device_t, const struct fe_pccard_product *);
  147 static int fe_probe_tdk(device_t, const struct fe_pccard_product *);
  148 
  149 static int
  150 fe_pccard_attach(device_t dev)
  151 {
  152         struct fe_softc *sc;
  153         const struct fe_pccard_product *pp;
  154         int error;
  155 
  156         /* Prepare for the device probe process.  */
  157         sc = device_get_softc(dev);
  158         sc->sc_unit = device_get_unit(dev);
  159 
  160         pp = (const struct fe_pccard_product *) pccard_product_lookup(dev,
  161             (const struct pccard_product *)fe_pccard_products,
  162             sizeof(fe_pccard_products[0]), NULL);
  163         if (pp == NULL)
  164                 return (ENXIO);
  165 
  166         if (pp->mpp_flags & MPP_MBH10302)
  167                 error = fe_probe_mbh(dev, pp);
  168         else
  169                 error = fe_probe_tdk(dev, pp);
  170         if (error != 0) {
  171                 fe_release_resource(dev);
  172                 return (error);
  173         }
  174         error = fe_alloc_irq(dev, 0);
  175         if (error != 0) {
  176                 fe_release_resource(dev);
  177                 return (error);
  178         }
  179         return (fe_attach(dev));
  180 }
  181 
  182 /*
  183  *      feunload - unload the driver and clear the table.
  184  */
  185 static int
  186 fe_pccard_detach(device_t dev)
  187 {
  188         struct fe_softc *sc = device_get_softc(dev);
  189         struct ifnet *ifp = sc->ifp;
  190 
  191         FE_LOCK(sc);
  192         fe_stop(sc);
  193         FE_UNLOCK(sc);
  194         callout_drain(&sc->timer);
  195         ether_ifdetach(ifp);
  196         bus_teardown_intr(dev, sc->irq_res, sc->irq_handle);
  197         if_free(ifp);
  198         fe_release_resource(dev);
  199         mtx_destroy(&sc->lock);
  200 
  201         return 0;
  202 }
  203 
  204 
  205 /*
  206  * Probe and initialization for Fujitsu MBH10302 PCMCIA Ethernet interface.
  207  * Note that this is for 10302 only; MBH10304 is handled by fe_probe_tdk().
  208  */
  209 static void
  210 fe_init_mbh(struct fe_softc *sc)
  211 {
  212         /* Minimal initialization of 86960.  */
  213         DELAY(200);
  214         fe_outb(sc, FE_DLCR6, sc->proto_dlcr6 | FE_D6_DLC_DISABLE);
  215         DELAY(200);
  216 
  217         /* Disable all interrupts.  */
  218         fe_outb(sc, FE_DLCR2, 0);
  219         fe_outb(sc, FE_DLCR3, 0);
  220 
  221         /* Enable master interrupt flag.  */
  222         fe_outb(sc, FE_MBH0, FE_MBH0_MAGIC | FE_MBH0_INTR_ENABLE);
  223 }
  224 
  225 static int
  226 fe_probe_mbh(device_t dev, const struct fe_pccard_product *pp)
  227 {
  228         struct fe_softc *sc = device_get_softc(dev);
  229 
  230         static struct fe_simple_probe_struct probe_table [] = {
  231                 { FE_DLCR2, 0x58, 0x00 },
  232                 { FE_DLCR4, 0x08, 0x00 },
  233                 { FE_DLCR6, 0xFF, 0xB6 },
  234                 { 0 }
  235         };
  236 
  237         /* MBH10302 occupies 32 I/O addresses. */
  238         if (fe_alloc_port(dev, 32))
  239                 return ENXIO;
  240 
  241         /* Fill the softc struct with default values.  */
  242         fe_softc_defaults(sc);
  243 
  244         /*
  245          * See if MBH10302 is on its address.
  246          * I'm not sure the following probe code works.  FIXME.
  247          */
  248         if (!fe_simple_probe(sc, probe_table))
  249                 return ENXIO;
  250 
  251         /* Get our station address from EEPROM.  */
  252         fe_inblk(sc, FE_MBH10, sc->enaddr, ETHER_ADDR_LEN);
  253 
  254         /* Make sure we got a valid station address.  */
  255         if (!fe_valid_Ether_p(sc->enaddr, 0))
  256                 return ENXIO;
  257 
  258         /* Determine the card type.  */
  259         sc->type = FE_TYPE_MBH;
  260         sc->typestr = "MBH10302 (PCMCIA)";
  261 
  262         /* We seems to need our own IDENT bits...  FIXME.  */
  263         sc->proto_dlcr7 = FE_D7_BYTSWP_LH | FE_D7_IDENT_NICE;
  264 
  265         /* Setup hooks.  We need a special initialization procedure.  */
  266         sc->init = fe_init_mbh;
  267 
  268         return 0;
  269 }
  270 
  271 static int
  272 fe_pccard_xircom_mac(const struct pccard_tuple *tuple, void *argp)
  273 {
  274         uint8_t *enaddr = argp;
  275         int i;
  276 
  277 #if 1
  278         /*
  279          * We fail to map the CIS twice, for reasons unknown.  We
  280          * may fix this in the future by loading the CIS with a sane
  281          * CIS from userland.
  282          */
  283         static uint8_t defaultmac[ETHER_ADDR_LEN] = {
  284                 0x00, 0x80, 0xc7, 0xed, 0x16, 0x7b};
  285 
  286         /* Copy the MAC ADDR and return success */
  287         for (i = 0; i < ETHER_ADDR_LEN; i++)
  288                 enaddr[i] = defaultmac[i];
  289 #else
  290         /* FUNCE is not after FUNCID, so we gotta go find it */
  291         if (tuple->code != 0x22)
  292                 return (0);
  293 
  294         /* Make sure this is a sane node */
  295         if (tuple->length < ETHER_ADDR_LEN + 3)
  296                 return (0);
  297 
  298         /* Copy the MAC ADDR and return success */
  299         for (i = 0; i < ETHER_ADDR_LEN; i++)
  300                 enaddr[i] = pccard_tuple_read_1(tuple, i + 3);
  301 #endif
  302         return (1);
  303 }
  304 
  305 /*
  306  * Probe and initialization for TDK/CONTEC PCMCIA Ethernet interface.
  307  * by MASUI Kenji <masui@cs.titech.ac.jp>
  308  *
  309  * (Contec uses TDK Ethernet chip -- hosokawa)
  310  *
  311  * This version of fe_probe_tdk has been rewrote to handle
  312  * *generic* PC Card implementation of Fujitsu MB8696x family.  The
  313  * name _tdk is just for a historical reason. :-)
  314  */
  315 static int
  316 fe_probe_tdk (device_t dev, const struct fe_pccard_product *pp)
  317 {
  318         struct fe_softc *sc = device_get_softc(dev);
  319 
  320         static struct fe_simple_probe_struct probe_table [] = {
  321                 { FE_DLCR2, 0x10, 0x00 },
  322                 { FE_DLCR4, 0x08, 0x00 },
  323 /*              { FE_DLCR5, 0x80, 0x00 },       Does not work well.  */
  324                 { 0 }
  325         };
  326 
  327 
  328         /* C-NET(PC)C occupies 16 I/O addresses. */
  329         if (fe_alloc_port(dev, 16))
  330                 return ENXIO;
  331 
  332         /* Fill the softc struct with default values.  */
  333         fe_softc_defaults(sc);
  334 
  335         /*
  336          * See if C-NET(PC)C is on its address.
  337          */
  338         if (!fe_simple_probe(sc, probe_table))
  339                 return ENXIO;
  340 
  341         /* Determine the card type.  */
  342         sc->type = FE_TYPE_TDK;
  343         sc->typestr = "Generic MB8696x/78Q837x Ethernet (PCMCIA)";
  344 
  345         pccard_get_ether(dev, sc->enaddr);
  346 
  347         /* Make sure we got a valid station address.  */
  348         if (!fe_valid_Ether_p(sc->enaddr, 0)) {
  349                 pccard_cis_scan(dev, fe_pccard_xircom_mac, sc->enaddr);
  350         }
  351 
  352         /* Make sure we got a valid station address.  */
  353         if (!fe_valid_Ether_p(sc->enaddr, 0))
  354                 return ENXIO;
  355 
  356         return 0;
  357 }

Cache object: dbf91a690e9989a87889c87ab8abd732


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