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/netif/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  * xe pccard interface driver
   27  *
   28  * $FreeBSD: src/sys/dev/xe/if_xe_pccard.c,v 1.11 2003/10/14 22:51:35 rsm Exp $
   29  */
   30 
   31 #include <sys/param.h>
   32 #include <sys/systm.h>
   33 #include <sys/kernel.h>
   34 #include <sys/socket.h>
   35 #include <sys/module.h>
   36 #include <sys/bus.h>
   37 #include <sys/rman.h>
   38  
   39 #include <net/ethernet.h>
   40 #include <net/if.h> 
   41 #include <net/if_arp.h>
   42 #include <net/if_media.h>
   43 #include <net/if_mib.h>
   44 
   45 #include <bus/pccard/pccardvar.h>
   46 
   47 #include "card_if.h"
   48 #include "pccarddevs.h"
   49 
   50 #include "if_xereg.h"
   51 #include "if_xevar.h"
   52 
   53 #define XE_DEBUG
   54 
   55 #ifdef XE_DEBUG
   56 #define DEVPRINTF(level, arg)   if (xe_debug >= (level)) device_printf arg
   57 #else
   58 #define DEVPRINTF(level, arg)
   59 #endif
   60 
   61 static const struct pccard_product xe_pccard_products[] = {
   62         PCMCIA_CARD(COMPAQ, CPQ550, 0),
   63         PCMCIA_CARD(COMPAQ2, CPQ_10_100, 0),
   64         PCMCIA_CARD(INTEL, EEPRO100, 0),
   65         PCMCIA_CARD(RACORE, ACCTON_EN2226, 0),
   66         PCMCIA_CARD(XIRCOM, CE, 0),
   67         PCMCIA_CARD(XIRCOM, CE2, 0),
   68         PCMCIA_CARD(XIRCOM, CE3, 0),
   69         PCMCIA_CARD(XIRCOM, CEM, 0),
   70         PCMCIA_CARD(XIRCOM, CEM28, 0),
   71         PCMCIA_CARD(XIRCOM, CEM33, 0),
   72         PCMCIA_CARD(XIRCOM, CEM56, 0),
   73         PCMCIA_CARD(XIRCOM, REM56, 0),
   74         PCMCIA_CARD(XIRCOM, CNW_801, 0),
   75         PCMCIA_CARD(XIRCOM, CNW_802, 0),
   76         { NULL }
   77 };
   78 
   79 struct xe_vendor {
   80         uint32_t         vendor_id;
   81         const char      *vendor_desc;
   82 } xe_vendors[] = {
   83         { PCMCIA_VENDOR_XIRCOM,         "Xircom" },
   84         { PCMCIA_VENDOR_COMPAQ,         "Compaq" },
   85         { PCMCIA_VENDOR_COMPAQ2,        "Compaq" },
   86         { PCMCIA_VENDOR_INTEL,          "Intel" },
   87         { 0,                            "Unknown" }
   88 };
   89 
   90 #define XE_CARD_TYPE_FLAGS_NO           0x0
   91 #define XE_CARD_TYPE_FLAGS_CE2          0x1
   92 #define XE_CARD_TYPE_FLAGS_MOHAWK       0x2
   93 #define XE_CARD_TYPE_FLAGS_DINGO        0x4
   94 
   95 #define XE_PROD_UMASK           0x11000f
   96 #define XE_PROD_ETHER_UMASK     0x010000
   97 #define XE_PROD_MODEM_UMASK     0x100000
   98 #define XE_PROD_SINGLE_ID1      0x010001
   99 #define XE_PROD_SINGLE_ID2      0x010002
  100 #define XE_PROD_SINGLE_ID3      0x010003
  101 #define XE_PROD_MULTI_ID1       0x110001
  102 #define XE_PROD_MULTI_ID2       0x110002
  103 #define XE_PROD_MULTI_ID3       0x110003
  104 #define XE_PROD_MULTI_ID4       0x110004
  105 #define XE_PROD_MULTI_ID5       0x110005
  106 #define XE_PROD_MULTI_ID6       0x110006 
  107 #define XE_PROD_MULTI_ID7       0x110007  
  108 
  109 struct xe_card_type {
  110         uint32_t         prod_type;
  111         const char      *card_type_desc;
  112         uint32_t         flags;
  113 } xe_card_types[] = {
  114         { XE_PROD_MULTI_ID1,    "CEM",          XE_CARD_TYPE_FLAGS_NO },
  115         { XE_PROD_MULTI_ID2,    "CEM2",         XE_CARD_TYPE_FLAGS_CE2 },
  116         { XE_PROD_MULTI_ID3,    "CEM3",         XE_CARD_TYPE_FLAGS_CE2 },
  117         { XE_PROD_MULTI_ID4,    "CEM33",        XE_CARD_TYPE_FLAGS_CE2 },
  118         { XE_PROD_MULTI_ID5,    "CEM56M",       XE_CARD_TYPE_FLAGS_MOHAWK },
  119         { XE_PROD_MULTI_ID6,    "CEM56",        XE_CARD_TYPE_FLAGS_MOHAWK |
  120                                                 XE_CARD_TYPE_FLAGS_DINGO },
  121         { XE_PROD_MULTI_ID7,    "CEM56",        XE_CARD_TYPE_FLAGS_MOHAWK |
  122                                                 XE_CARD_TYPE_FLAGS_DINGO },
  123         { XE_PROD_SINGLE_ID1,   "CE",           XE_CARD_TYPE_FLAGS_NO },
  124         { XE_PROD_SINGLE_ID2,   "CE2",          XE_CARD_TYPE_FLAGS_CE2 },
  125         { XE_PROD_SINGLE_ID3,   "CE3",          XE_CARD_TYPE_FLAGS_MOHAWK },
  126         { 0, NULL, -1 }
  127 };
  128 
  129 static struct xe_vendor         *xe_vendor_lookup       (uint32_t);
  130 static struct xe_card_type      *xe_card_type_lookup    (uint32_t);
  131 
  132 static int      xe_cemfix       (device_t);
  133 static int      xe_pccard_probe (device_t);
  134 static int      xe_pccard_match (device_t);
  135 static int      xe_pccard_attach(device_t);
  136 
  137 static device_method_t xe_pccard_methods[] = {
  138         /* Device interface */
  139         DEVMETHOD(device_probe,         pccard_compat_probe),
  140         DEVMETHOD(device_attach,        pccard_compat_attach),
  141         DEVMETHOD(device_detach,        xe_detach),
  142 
  143         /* Card interface */
  144         DEVMETHOD(card_compat_match,    xe_pccard_match),
  145         DEVMETHOD(card_compat_probe,    xe_pccard_probe),
  146         DEVMETHOD(card_compat_attach,   xe_pccard_attach),
  147 
  148         DEVMETHOD_END
  149 };
  150 
  151 static driver_t xe_pccard_driver = {
  152         "xe",
  153         xe_pccard_methods,
  154         sizeof(struct xe_softc),
  155 };
  156 
  157 devclass_t xe_devclass;
  158 DRIVER_MODULE(xe, pccard, xe_pccard_driver, xe_devclass, NULL, NULL);
  159 
  160 /*
  161  * Fixing for CEM2, CEM3 and CEM56/REM56 cards.  These need some magic to
  162  * enable the Ethernet function, which isn't mentioned anywhere in the CIS.
  163  * Despite the register names, most of this isn't Dingo-specific.
  164  */
  165 static int
  166 xe_cemfix(device_t dev)
  167 {
  168         struct xe_softc *sc = device_get_softc(dev);
  169         bus_space_tag_t bst;
  170         bus_space_handle_t bsh;
  171         struct resource *r;
  172         int rid;
  173         int ioport;
  174 
  175         device_printf(dev, "CEM I/O port 0x%0lx, size 0x%0lx\n",
  176             bus_get_resource_start(dev, SYS_RES_IOPORT, sc->port_rid),
  177             bus_get_resource_count(dev, SYS_RES_IOPORT, sc->port_rid));
  178 
  179         rid = 0;
  180         r = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0,
  181                                ~0, 4 << 10, RF_ACTIVE);
  182         if (r == NULL) {
  183                 device_printf(dev, "Can't map in attribute memory\n");
  184                 return -1;
  185         }
  186 
  187         bsh = rman_get_bushandle(r);
  188         bst = rman_get_bustag(r);
  189 
  190         CARD_SET_RES_FLAGS(device_get_parent(dev), dev, SYS_RES_MEMORY, rid,
  191                            PCCARD_A_MEM_ATTR);
  192 
  193         bus_space_write_1(bst, bsh, DINGO_ECOR, DINGO_ECOR_IRQ_LEVEL |
  194                                                 DINGO_ECOR_INT_ENABLE |
  195                                                 DINGO_ECOR_IOB_ENABLE |
  196                                                 DINGO_ECOR_ETH_ENABLE);
  197         ioport = bus_get_resource_start(dev, SYS_RES_IOPORT, sc->port_rid);
  198         bus_space_write_1(bst, bsh, DINGO_EBAR0, ioport & 0xff);
  199         bus_space_write_1(bst, bsh, DINGO_EBAR1, (ioport >> 8) & 0xff);
  200 
  201         if (sc->dingo) {
  202                 bus_space_write_1(bst, bsh, DINGO_DCOR0, DINGO_DCOR0_SF_INT);
  203                 bus_space_write_1(bst, bsh, DINGO_DCOR1,
  204                                   DINGO_DCOR1_INT_LEVEL | DINGO_DCOR1_EEDIO);
  205                 bus_space_write_1(bst, bsh, DINGO_DCOR2, 0x00);
  206                 bus_space_write_1(bst, bsh, DINGO_DCOR3, 0x00);
  207                 bus_space_write_1(bst, bsh, DINGO_DCOR4, 0x00);
  208         }
  209 
  210         bus_release_resource(dev, SYS_RES_MEMORY, rid, r);
  211 
  212         /* success! */
  213         return 0;
  214 }
  215 
  216 static struct xe_vendor *
  217 xe_vendor_lookup(uint32_t vendor_id)
  218 {
  219         struct xe_vendor *v;
  220 
  221         for (v = xe_vendors; v->vendor_id != 0; ++v) {
  222                 if(v->vendor_id == vendor_id)
  223                         break;
  224         }
  225         return v;
  226 }
  227       
  228 static struct xe_card_type *
  229 xe_card_type_lookup(uint32_t prod)
  230 {
  231         struct xe_card_type *ct;
  232 
  233         for (ct = xe_card_types; ct->card_type_desc != NULL; ++ct) {
  234                 if(ct->prod_type == (prod & XE_PROD_UMASK))
  235                         return ct;
  236         }
  237         return NULL;
  238 }
  239 
  240 /*
  241  * PCMCIA probe routine.
  242  * Identify the device.  Called from the bus driver when the card is
  243  * inserted or otherwise powers up.
  244  */
  245 static int
  246 xe_pccard_probe(device_t dev)
  247 {
  248         struct xe_softc *scp = device_get_softc(dev);
  249         uint32_t vendor, product, prod;
  250         uint16_t prodext;
  251         const uint8_t *ether_addr;
  252         const char *cis3_str=NULL;
  253         struct xe_vendor *vendor_itm;
  254         struct xe_card_type *card_itm;
  255         int i;
  256 
  257 #ifdef XE_DEBUG
  258         const char *vendor_str = NULL;
  259         const char *product_str = NULL;
  260         const char *cis4_str = NULL;
  261 
  262         vendor = pccard_get_vendor(dev);
  263         product = pccard_get_product(dev);
  264         prodext = pccard_get_prodext(dev);
  265         vendor_str = pccard_get_vendor_str(dev);
  266         product_str = pccard_get_product_str(dev);
  267         cis3_str = pccard_get_cis3_str(dev);
  268         cis4_str = pccard_get_cis4_str(dev);
  269 
  270         DEVPRINTF(1, (dev, "pccard_probe\n"));
  271         DEVPRINTF(1, (dev, "vendor = 0x%04x\n", vendor));
  272         DEVPRINTF(1, (dev, "product = 0x%04x\n", product));
  273         DEVPRINTF(1, (dev, "prodext = 0x%02x\n", prodext));
  274         DEVPRINTF(1, (dev, "vendor_str = %s\n",
  275                       vendor_str == NULL ? "NULL" : vendor_str));
  276         DEVPRINTF(1, (dev, "product_str = %s\n",
  277                       product_str == NULL ? "NULL" : product_str));
  278         DEVPRINTF(1, (dev, "cis3_str = %s\n",
  279                       cis3_str == NULL ? "NULL" : cis3_str));
  280         DEVPRINTF(1, (dev, "cis4_str = %s\n",
  281                       cis4_str == NULL ? "NULL" : cis4_str));
  282 #endif
  283 
  284         /*
  285          * PCCARD_CISTPL_MANFID = 0x20
  286          */
  287         vendor = pccard_get_vendor(dev);
  288         vendor_itm = xe_vendor_lookup(vendor);
  289         /*
  290          * We always have some vendor here, although
  291          * vendor description may be "Unknown".
  292          */
  293         scp->vendor = vendor_itm->vendor_desc;
  294 
  295         product = pccard_get_product(dev);
  296         prodext = pccard_get_prodext(dev);
  297 
  298         /*
  299          * prod(new) =  rev, media, prod(old)
  300          * prod(new) =  (don't care), (care 0x10 bit), (care 0x0f bit)
  301          */
  302         prod = (product << 8) | prodext;
  303         card_itm = xe_card_type_lookup(prod);
  304         if (card_itm == NULL)
  305                 return ENODEV;
  306 
  307         scp->card_type = card_itm->card_type_desc;
  308         if (card_itm->prod_type & XE_PROD_MODEM_UMASK)
  309                 scp->modem = 1;
  310 
  311         for (i = 1; i != XE_CARD_TYPE_FLAGS_DINGO; i = i << 1) {
  312                 switch(i & card_itm->flags) {
  313                 case XE_CARD_TYPE_FLAGS_CE2:
  314                         scp->ce2 = 1;
  315                         break;
  316                 case XE_CARD_TYPE_FLAGS_MOHAWK:
  317                         scp->mohawk = 1;
  318                         break;
  319                 case XE_CARD_TYPE_FLAGS_DINGO:
  320                         scp->dingo = 1;
  321                         break;
  322                 }
  323         }
  324 
  325         /*
  326          * PCCARD_CISTPL_VERS_1 = 0x15
  327          *
  328          * Check for certain strange CE2's that look like CE's:
  329          * match 3rd version string against "CE2"
  330          */
  331         cis3_str = pccard_get_cis3_str(dev);
  332         if (strcmp(scp->card_type, "CE") == 0)
  333                 if (cis3_str != NULL && strcmp(cis3_str, "PS-CE2-10") == 0)
  334                         scp->card_type = "CE2";
  335 
  336         /*
  337          * PCCARD_CISTPL_FUNCE = 0x22
  338          */
  339         ether_addr = pccard_get_ether(dev);
  340         bcopy(ether_addr, scp->arpcom.ac_enaddr, ETHER_ADDR_LEN);
  341 
  342         /* Reject unsupported cards */
  343         if (strcmp(scp->card_type, "CE") == 0 ||
  344             strcmp(scp->card_type, "CEM") == 0) {
  345                 device_printf(dev, "Sorry, your %s card is not supported :(\n",
  346                               scp->card_type);
  347                 return ENODEV;
  348         }
  349 
  350         /* Success */
  351         return 0;
  352 }
  353 
  354 static int
  355 xe_pccard_attach(device_t dev)
  356 {
  357         struct xe_softc *scp = device_get_softc(dev);
  358         int err;
  359 
  360         if ((err = xe_activate(dev)) != 0)
  361                 return err;
  362          
  363         /* Hack RealPorts into submission */
  364         if (scp->modem && xe_cemfix(dev) < 0) {
  365                 device_printf(dev, "Unable to fix your %s combo card\n",
  366                               scp->card_type);
  367                 xe_deactivate(dev);
  368                 return ENODEV;
  369         }
  370         return xe_attach(dev);
  371 }
  372 
  373 static int
  374 xe_pccard_match(device_t dev)
  375 {
  376         const struct pccard_product *pp;
  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 }

Cache object: 405f4f792b62bde61952c64d852c7c7f


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