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/xe/if_xe_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  * Copyright (c) 2002 Takeshi Shibagaki
    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  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  */
   26 
   27 #include <sys/cdefs.h>
   28 __FBSDID("$FreeBSD: releng/5.2/sys/dev/xe/if_xe_pccard.c 122081 2003-11-04 21:09:37Z rsm $");
   29 
   30 /* xe pccard interface driver */
   31 
   32 #include <sys/param.h>
   33 #include <sys/systm.h>
   34 #include <sys/kernel.h>
   35 #include <sys/socket.h>
   36 
   37 #include <sys/module.h>
   38 #include <sys/bus.h>
   39 
   40 #include <machine/bus.h>
   41 #include <machine/resource.h>
   42 #include <sys/rman.h>
   43  
   44 #include <net/ethernet.h>
   45 #include <net/if.h> 
   46 #include <net/if_arp.h>
   47 #include <net/if_media.h>
   48 #include <net/if_mib.h>
   49 
   50 
   51 #include <dev/xe/if_xereg.h>
   52 #include <dev/xe/if_xevar.h>
   53 
   54 #include <dev/pccard/pccardvar.h>
   55 #include <dev/pccard/pccarddevs.h>
   56 #include "card_if.h"
   57 
   58 /*
   59  * Debug logging levels - set with hw.xe.debug sysctl
   60  * 0 = None
   61  * 1 = More hardware details, probe/attach progress
   62  * 2 = Most function calls, ioctls and media selection progress
   63  * 3 = Everything - interrupts, packets in/out and multicast address setup
   64  */
   65 #define XE_DEBUG
   66 #ifdef XE_DEBUG
   67 
   68 extern int xe_debug;
   69 
   70 #define DEVPRINTF(level, arg) if (xe_debug >= (level)) device_printf arg
   71 #define DPRINTF(level, arg) if (xe_debug >= (level)) printf arg
   72 #else
   73 #define DEVPRINTF(level, arg)
   74 #define DPRINTF(level, arg)
   75 #endif
   76 
   77 
   78 struct xe_vendor_table {
   79         u_int32_t vendor_id;
   80         char *vendor_desc;
   81 } xe_vendor_devs[] = {
   82         { PCMCIA_VENDOR_XIRCOM, "Xircom" },
   83         { PCMCIA_VENDOR_COMPAQ, "Compaq" },
   84         { PCMCIA_VENDOR_COMPAQ2, "Compaq" },   /* Maybe Paralon Techologies, Inc */
   85         { PCMCIA_VENDOR_INTEL, "Intel" },
   86         { 0, "Unknown" }
   87 };
   88 
   89 #define XE_CARD_TYPE_FLAGS_NO 0x0
   90 #define XE_CARD_TYPE_FLAGS_CE2 0x1
   91 #define XE_CARD_TYPE_FLAGS_MOHAWK 0x2
   92 #define XE_CARD_TYPE_FLAGS_DINGO 0x4
   93 #define XE_PROD_UMASK 0x11000f
   94 #define XE_PROD_ETHER_UMASK 0x010000
   95 #define XE_PROD_MODEM_UMASK 0x100000
   96 #define XE_PROD_SINGLE_ID1 0x010001
   97 #define XE_PROD_SINGLE_ID2 0x010002
   98 #define XE_PROD_SINGLE_ID3 0x010003
   99 #define XE_PROD_MULTI_ID1 0x110001
  100 #define XE_PROD_MULTI_ID2 0x110002
  101 #define XE_PROD_MULTI_ID3 0x110003
  102 #define XE_PROD_MULTI_ID4 0x110004
  103 #define XE_PROD_MULTI_ID5 0x110005
  104 #define XE_PROD_MULTI_ID6 0x110006 
  105 #define XE_PROD_MULTI_ID7 0x110007  
  106 
  107 struct xe_card_type_table {
  108         u_int32_t prod_type;
  109         char *card_type_desc;
  110         u_int32_t flags;
  111 } xe_card_type_devs[] = {
  112         { XE_PROD_MULTI_ID1, "CEM", XE_CARD_TYPE_FLAGS_NO },
  113         { XE_PROD_MULTI_ID2, "CEM2", XE_CARD_TYPE_FLAGS_CE2 },
  114         { XE_PROD_MULTI_ID3, "CEM3", XE_CARD_TYPE_FLAGS_CE2 },
  115         { XE_PROD_MULTI_ID4, "CEM33", XE_CARD_TYPE_FLAGS_CE2 },
  116         { XE_PROD_MULTI_ID5, "CEM56M", XE_CARD_TYPE_FLAGS_MOHAWK },
  117         { XE_PROD_MULTI_ID6, "CEM56", XE_CARD_TYPE_FLAGS_MOHAWK |
  118                                         XE_CARD_TYPE_FLAGS_DINGO },
  119         { XE_PROD_MULTI_ID7, "CEM56", XE_CARD_TYPE_FLAGS_MOHAWK |
  120                                         XE_CARD_TYPE_FLAGS_DINGO },
  121         { XE_PROD_SINGLE_ID1, "CE", XE_CARD_TYPE_FLAGS_NO },
  122         { XE_PROD_SINGLE_ID2, "CE2", XE_CARD_TYPE_FLAGS_CE2 },
  123         { XE_PROD_SINGLE_ID3, "CE3", XE_CARD_TYPE_FLAGS_MOHAWK },
  124         { 0, NULL,  -1 }
  125 };
  126 
  127 /*
  128  * Prototypes
  129  */
  130 static int xe_cemfix(device_t dev);
  131 static struct xe_vendor_table *xe_vendor_lookup(u_int32_t devid,
  132                                         struct xe_vendor_table *tbl);
  133 static struct xe_card_type_table *xe_card_type_lookup(u_int32_t devid,
  134                                         struct xe_card_type_table *tbl);
  135 
  136 /*
  137  * Fixing for CEM2, CEM3 and CEM56/REM56 cards.  These need some magic to
  138  * enable the Ethernet function, which isn't mentioned anywhere in the CIS.
  139  * Despite the register names, most of this isn't Dingo-specific.
  140  */
  141 static int
  142 xe_cemfix(device_t dev)
  143 {
  144         struct xe_softc *sc = (struct xe_softc *) device_get_softc(dev);
  145         bus_space_tag_t bst;
  146         bus_space_handle_t bsh;
  147         struct resource *r;
  148         int rid;
  149         int ioport;
  150 
  151         DEVPRINTF(2, (dev, "cemfix\n"));
  152 
  153         DEVPRINTF(1, (dev, "CEM I/O port 0x%0lx, size 0x%0lx\n",
  154                 bus_get_resource_start(dev, SYS_RES_IOPORT, sc->port_rid),
  155                 bus_get_resource_count(dev, SYS_RES_IOPORT, sc->port_rid)));
  156 
  157         rid = 0;
  158         r = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0,
  159                                ~0, 4 << 10, RF_ACTIVE);
  160         if (!r) {
  161                 device_printf(dev, "cemfix: Can't map in attribute memory\n");
  162                 return (-1);
  163         }
  164 
  165         bsh = rman_get_bushandle(r);
  166         bst = rman_get_bustag(r);
  167 
  168         CARD_SET_RES_FLAGS(device_get_parent(dev), dev, SYS_RES_MEMORY, rid,
  169                            PCCARD_A_MEM_ATTR);
  170 
  171         bus_space_write_1(bst, bsh, DINGO_ECOR, DINGO_ECOR_IRQ_LEVEL |
  172                                                 DINGO_ECOR_INT_ENABLE |
  173                                                 DINGO_ECOR_IOB_ENABLE |
  174                                                 DINGO_ECOR_ETH_ENABLE);
  175         ioport = bus_get_resource_start(dev, SYS_RES_IOPORT, sc->port_rid);
  176         bus_space_write_1(bst, bsh, DINGO_EBAR0, ioport & 0xff);
  177         bus_space_write_1(bst, bsh, DINGO_EBAR1, (ioport >> 8) & 0xff);
  178 
  179         if (sc->dingo) {
  180                 bus_space_write_1(bst, bsh, DINGO_DCOR0, DINGO_DCOR0_SF_INT);
  181                 bus_space_write_1(bst, bsh, DINGO_DCOR1, DINGO_DCOR1_INT_LEVEL |
  182                                                   DINGO_DCOR1_EEDIO);
  183                 bus_space_write_1(bst, bsh, DINGO_DCOR2, 0x00);
  184                 bus_space_write_1(bst, bsh, DINGO_DCOR3, 0x00);
  185                 bus_space_write_1(bst, bsh, DINGO_DCOR4, 0x00);
  186         }
  187 
  188         bus_release_resource(dev, SYS_RES_MEMORY, rid, r);
  189 
  190         /* success! */
  191         return (0);
  192 }
  193 
  194 static struct xe_vendor_table *
  195 xe_vendor_lookup(u_int32_t devid, struct xe_vendor_table *tbl)
  196 {
  197         while(tbl->vendor_id) {
  198                 if(tbl->vendor_id == devid)
  199                         return (tbl);
  200                 tbl++;
  201         }       
  202         return (tbl); /* return Unknown */
  203 }
  204       
  205 static struct xe_card_type_table *
  206 xe_card_type_lookup(u_int32_t devid, struct xe_card_type_table *tbl)
  207 {
  208         while(tbl->prod_type) {
  209                 if(tbl->prod_type == (devid & XE_PROD_UMASK))
  210                         return (tbl);
  211                 tbl++;
  212         }
  213         return (NULL);
  214 }
  215 
  216 /*
  217  * PCMCIA probe routine.
  218  * Identify the device.  Called from the bus driver when the card is
  219  * inserted or otherwise powers up.
  220  */
  221 static int
  222 xe_pccard_probe(device_t dev)
  223 {
  224         struct xe_softc *scp = (struct xe_softc *) device_get_softc(dev);
  225         u_int32_t vendor,prodid,prod;
  226         u_int16_t prodext;
  227         const char* vendor_str = NULL;
  228         const char* product_str = NULL;
  229         const char* cis4_str = NULL;
  230         const char *cis3_str=NULL;
  231         struct xe_vendor_table *vendor_itm;
  232         struct xe_card_type_table *card_itm;
  233         int i;
  234 
  235         DEVPRINTF(2, (dev, "pccard_probe\n"));
  236 
  237         pccard_get_vendor(dev, &vendor);
  238         pccard_get_product(dev, &prodid);
  239         pccard_get_prodext(dev, &prodext);
  240         pccard_get_vendor_str(dev, &vendor_str);
  241         pccard_get_product_str(dev, &product_str);
  242         pccard_get_cis3_str(dev, &cis3_str);
  243         pccard_get_cis4_str(dev, &cis4_str);
  244 
  245         DEVPRINTF(1, (dev, "vendor = 0x%04x\n", vendor));
  246         DEVPRINTF(1, (dev, "product = 0x%04x\n", prodid));
  247         DEVPRINTF(1, (dev, "prodext = 0x%02x\n", prodext));
  248         DEVPRINTF(1, (dev, "vendor_str = %s\n", vendor_str));
  249         DEVPRINTF(1, (dev, "product_str = %s\n", product_str));
  250         DEVPRINTF(1, (dev, "cis3_str = %s\n", cis3_str));
  251         DEVPRINTF(1, (dev, "cis4_str = %s\n", cis4_str));
  252 
  253         /*
  254          * PCCARD_CISTPL_MANFID = 0x20
  255          */
  256         pccard_get_vendor(dev, &vendor);
  257         vendor_itm = xe_vendor_lookup(vendor, &xe_vendor_devs[0]);
  258         if (vendor_itm == NULL)
  259                 return (ENODEV);
  260         scp->vendor = vendor_itm->vendor_desc;
  261         pccard_get_product(dev, &prodid);
  262         pccard_get_prodext(dev, &prodext);
  263         /*
  264          * prod(new) =  rev, media, prod(old)
  265          * prod(new) =  (don't care), (care 0x10 bit), (care 0x0f bit)
  266          */
  267         prod = (prodid << 8) | prodext;
  268         card_itm = xe_card_type_lookup(prod, &xe_card_type_devs[0]);
  269         if (card_itm == NULL)
  270                 return (ENODEV);
  271         scp->card_type = card_itm->card_type_desc;
  272         if (card_itm->prod_type & XE_PROD_MODEM_UMASK)
  273                 scp->modem = 1;
  274         for(i=1; i!=XE_CARD_TYPE_FLAGS_DINGO; i=i<<1) {
  275                 switch(i & card_itm->flags) {
  276                 case XE_CARD_TYPE_FLAGS_CE2:
  277                         scp->ce2 = 1; break;
  278                 case XE_CARD_TYPE_FLAGS_MOHAWK:
  279                         scp->mohawk = 1; break;
  280                 case XE_CARD_TYPE_FLAGS_DINGO:
  281                         scp->dingo = 1; break;
  282                 }
  283         }
  284         /*
  285          * PCCARD_CISTPL_VERS_1 = 0x15
  286          */
  287         pccard_get_cis3_str(dev, &cis3_str);
  288         if (strcmp(scp->card_type, "CE") == 0)
  289                 if (cis3_str != NULL && strcmp(cis3_str, "PS-CE2-10") == 0)
  290                         scp->card_type = "CE2"; /* Look for "CE2" string */
  291 
  292         /*
  293          * PCCARD_CISTPL_FUNCE = 0x22
  294          */
  295         pccard_get_ether(dev, scp->arpcom.ac_enaddr);
  296 
  297         /* Reject unsupported cards */
  298         if(strcmp(scp->card_type, "CE") == 0
  299         || strcmp(scp->card_type, "CEM") == 0) {
  300                 device_printf(dev, "Sorry, your %s card is not supported :(\n",
  301                                 scp->card_type);
  302                 return (ENODEV);
  303         }
  304 
  305         /* Success */
  306         return (0);
  307 }
  308 
  309 /*
  310  * Attach a device.
  311  */
  312 static int
  313 xe_pccard_attach(device_t dev)
  314 {
  315         struct xe_softc *scp = device_get_softc(dev);
  316         int err;
  317 
  318         DEVPRINTF(2, (dev, "pccard_attach\n"));
  319 
  320         if ((err = xe_activate(dev)) != 0)
  321                 return (err);
  322          
  323         /* Hack RealPorts into submission */
  324         if (scp->modem && xe_cemfix(dev) < 0) {
  325                 device_printf(dev, "Unable to fix your %s combo card\n",
  326                                           scp->card_type);
  327                 xe_deactivate(dev);
  328                 return (ENODEV);
  329         }
  330         if ((err = xe_attach(dev))) {
  331                 device_printf(dev, "xe_attach() failed! (%d)\n", err);
  332                 return (err);
  333         }
  334         return (0);
  335 }
  336 
  337 /*
  338  * The device entry is being removed, probably because someone ejected the
  339  * card.  The interface should have been brought down manually before calling
  340  * this function; if not you may well lose packets.  In any case, I shut down
  341  * the card and the interface, and hope for the best.
  342  */
  343 static int
  344 xe_pccard_detach(device_t dev)
  345 {
  346         struct xe_softc *sc = device_get_softc(dev);
  347 
  348         DEVPRINTF(2, (dev, "pccard_detach\n"));
  349 
  350         sc->arpcom.ac_if.if_flags &= ~IFF_RUNNING;
  351         ether_ifdetach(&sc->arpcom.ac_if);
  352         xe_deactivate(dev);
  353         return (0);
  354 }
  355 
  356 static const struct pccard_product xe_pccard_products[] = {
  357         PCMCIA_CARD(ACCTON, EN2226, 0),
  358         PCMCIA_CARD(COMPAQ2, CPQ_10_100, 0),
  359         PCMCIA_CARD(INTEL, EEPRO100, 0),
  360         PCMCIA_CARD(XIRCOM, CE, 0),
  361         PCMCIA_CARD(XIRCOM, CE2, 0),
  362         PCMCIA_CARD(XIRCOM, CE3, 0),
  363         PCMCIA_CARD(XIRCOM, CEM, 0),
  364         PCMCIA_CARD(XIRCOM, CEM28, 0),
  365         PCMCIA_CARD(XIRCOM, CEM33, 0),
  366         PCMCIA_CARD(XIRCOM, CEM56, 0),
  367         PCMCIA_CARD(XIRCOM, REM56, 0),
  368         { NULL }
  369 };
  370 
  371 static int
  372 xe_pccard_match(device_t dev)
  373 {
  374         const struct pccard_product *pp;
  375 
  376         DEVPRINTF(2, (dev, "pccard_match\n"));
  377 
  378         if ((pp = pccard_product_lookup(dev, xe_pccard_products,
  379                 sizeof(xe_pccard_products[0]), NULL)) != NULL) {
  380             if (pp->pp_name != NULL)
  381                                         device_set_desc(dev, pp->pp_name);
  382                         return (0);
  383         }
  384         return (EIO);
  385 }
  386 
  387 static device_method_t xe_pccard_methods[] = {
  388         /* Device interface */
  389         DEVMETHOD(device_probe,         pccard_compat_probe),
  390         DEVMETHOD(device_attach,        pccard_compat_attach),
  391         DEVMETHOD(device_detach,        xe_pccard_detach),
  392 
  393         /* Card interface */
  394         DEVMETHOD(card_compat_match,    xe_pccard_match),
  395         DEVMETHOD(card_compat_probe,    xe_pccard_probe),
  396         DEVMETHOD(card_compat_attach,   xe_pccard_attach),
  397 
  398         { 0, 0 }
  399 };
  400 
  401 static driver_t xe_pccard_driver = {
  402         "xe",
  403         xe_pccard_methods,
  404         sizeof(struct xe_softc),
  405 };
  406 
  407 devclass_t xe_devclass;
  408 
  409 DRIVER_MODULE(xe, pccard, xe_pccard_driver, xe_devclass, 0, 0);

Cache object: 2c68ec5c345a2d848da60b806e16246e


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