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  * xe pccard interface driver
   28  * $FreeBSD: releng/5.1/sys/dev/xe/if_xe_pccard.c 113315 2003-04-10 04:36:02Z imp $
   29  */
   30 
   31 #include <sys/param.h>
   32 #include <sys/systm.h>
   33 #include <sys/kernel.h>
   34 #include <sys/socket.h>
   35 
   36 #include <sys/module.h>
   37 #include <sys/bus.h>
   38 
   39 #include <machine/bus.h>
   40 #include <machine/resource.h>
   41 #include <sys/rman.h>
   42  
   43 #include <net/ethernet.h>
   44 #include <net/if.h> 
   45 #include <net/if_arp.h>
   46 #include <net/if_media.h>
   47 #include <net/if_mib.h>
   48 
   49 
   50 #include <dev/xe/if_xereg.h>
   51 #include <dev/xe/if_xevar.h>
   52 
   53 #include <dev/pccard/pccardvar.h>
   54 #include <dev/pccard/pccarddevs.h>
   55 #include "card_if.h"
   56 
   57 #define XE_VENDOR_ID_XIRCOM 0x0105
   58 #define XE_VENDOR_ID_COMPAQ_1 0x0138
   59 #define XE_VENDOR_ID_COMPAQ_2 0x0183
   60 #define XE_VENDOR_ID_INTEL 0x0089
   61 #define XE_VENDOR_ID_UNKNOWN 0
   62 
   63 struct xe_vendor_table {
   64         u_int32_t vendor_id;
   65         char *vendor_desc;
   66 } xe_vendor_devs[] = {
   67         { XE_VENDOR_ID_XIRCOM, "Xircom" },
   68         { XE_VENDOR_ID_COMPAQ_1, "Compaq" },
   69         { XE_VENDOR_ID_COMPAQ_2, "Compaq" },
   70         { XE_VENDOR_ID_INTEL, "Intel" },
   71         { XE_VENDOR_ID_UNKNOWN, "Unknown" }
   72 };
   73 
   74 #define XE_CARD_TYPE_FLAGS_NO 0x0
   75 #define XE_CARD_TYPE_FLAGS_CE2 0x1
   76 #define XE_CARD_TYPE_FLAGS_MOHAWK 0x2
   77 #define XE_CARD_TYPE_FLAGS_DINGO 0x4
   78 #define XE_PROD_UMASK 0x100f
   79 #define XE_PROD_MODEM_UMASK 0x1000
   80 #define XE_PROD_SINGLE_ID1 0x1
   81 #define XE_PROD_SINGLE_ID2 0x2
   82 #define XE_PROD_SINGLE_ID3 0x3
   83 #define XE_PROD_MULTI_ID1 0x1001
   84 #define XE_PROD_MULTI_ID2 0x1002
   85 #define XE_PROD_MULTI_ID3 0x1003
   86 #define XE_PROD_MULTI_ID4 0x1004
   87 #define XE_PROD_MULTI_ID5 0x1005
   88 #define XE_PROD_MULTI_ID6 0x1006 
   89 #define XE_PROD_MULTI_ID7 0x1007  
   90 
   91 struct xe_card_type_table {
   92         u_int32_t prod_type;
   93         char *card_type_desc;
   94         u_int32_t flags;
   95 } xe_card_type_devs[] = {
   96         { XE_PROD_MULTI_ID1, "CEM", XE_CARD_TYPE_FLAGS_NO },
   97         { XE_PROD_MULTI_ID2, "CEM2", XE_CARD_TYPE_FLAGS_CE2 },
   98         { XE_PROD_MULTI_ID3, "CEM3", XE_CARD_TYPE_FLAGS_CE2 },
   99         { XE_PROD_MULTI_ID4, "CEM33", XE_CARD_TYPE_FLAGS_CE2 },
  100         { XE_PROD_MULTI_ID5, "CEM56M", XE_CARD_TYPE_FLAGS_MOHAWK },
  101         { XE_PROD_MULTI_ID6, "CEM56", XE_CARD_TYPE_FLAGS_MOHAWK |
  102                                         XE_CARD_TYPE_FLAGS_DINGO },
  103         { XE_PROD_MULTI_ID7, "CEM56", XE_CARD_TYPE_FLAGS_MOHAWK |
  104                                         XE_CARD_TYPE_FLAGS_DINGO },
  105         { XE_PROD_SINGLE_ID1, "CE", XE_CARD_TYPE_FLAGS_NO },
  106         { XE_PROD_SINGLE_ID2, "CE2", XE_CARD_TYPE_FLAGS_CE2 },
  107         { XE_PROD_SINGLE_ID3, "CE3", XE_CARD_TYPE_FLAGS_MOHAWK },
  108         { 0, NULL,  -1 }
  109 };
  110 
  111 /*
  112  * Prototypes
  113  */
  114 static int xe_cem56fix(device_t dev);
  115 static struct xe_vendor_table *xe_vendor_lookup(u_int32_t devid,
  116                                         struct xe_vendor_table *tbl);
  117 static struct xe_card_type_table *xe_card_type_lookup(u_int32_t devid,
  118                                         struct xe_card_type_table *tbl);
  119 
  120 /*
  121  * Fixing for RealPort cards - they need a little furtling to get the
  122  * ethernet working. But this codes don't work well in NEWCARD.
  123  */
  124 static int
  125 xe_cem56fix(device_t dev)
  126 {
  127         struct xe_softc *sc = (struct xe_softc *) device_get_softc(dev);
  128         bus_space_tag_t bst;
  129         bus_space_handle_t bsh;
  130         struct resource *r;
  131         int rid;
  132         int ioport;
  133 
  134         device_printf(dev, "Realport port 0x%0lx, size 0x%0lx\n",
  135                 bus_get_resource_start(dev, SYS_RES_IOPORT, sc->port_rid),
  136                 bus_get_resource_count(dev, SYS_RES_IOPORT, sc->port_rid));
  137 
  138         rid = 0;
  139         r = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0,
  140                                ~0, 4 << 10, RF_ACTIVE);
  141         if (!r) {
  142                 device_printf(dev, "Can't map in attribute memory\n");
  143                 return (-1);
  144         }
  145 
  146         bsh = rman_get_bushandle(r);
  147         bst = rman_get_bustag(r);
  148 
  149         CARD_SET_RES_FLAGS(device_get_parent(dev), dev, SYS_RES_MEMORY, rid,
  150                            PCCARD_A_MEM_ATTR);
  151 
  152         bus_space_write_1(bst, bsh, DINGO_ECOR, DINGO_ECOR_IRQ_LEVEL |
  153                                                 DINGO_ECOR_INT_ENABLE |
  154                                                 DINGO_ECOR_IOB_ENABLE |
  155                                                 DINGO_ECOR_ETH_ENABLE);
  156         ioport = bus_get_resource_start(dev, SYS_RES_IOPORT, sc->port_rid);
  157         bus_space_write_1(bst, bsh, DINGO_EBAR0, ioport & 0xff);
  158         bus_space_write_1(bst, bsh, DINGO_EBAR1, (ioport >> 8) & 0xff);
  159 
  160         bus_space_write_1(bst, bsh, DINGO_DCOR0, DINGO_DCOR0_SF_INT);
  161         bus_space_write_1(bst, bsh, DINGO_DCOR1, DINGO_DCOR1_INT_LEVEL |
  162                                                  DINGO_DCOR1_EEDIO);
  163         bus_space_write_1(bst, bsh, DINGO_DCOR2, 0x00);
  164         bus_space_write_1(bst, bsh, DINGO_DCOR3, 0x00);
  165         bus_space_write_1(bst, bsh, DINGO_DCOR4, 0x00);
  166 
  167         bus_release_resource(dev, SYS_RES_MEMORY, rid, r);
  168 
  169         /* success! */
  170         return (0);
  171 }
  172 
  173 static struct xe_vendor_table *
  174 xe_vendor_lookup(u_int32_t devid, struct xe_vendor_table *tbl)
  175 {
  176         while(tbl->vendor_id) {
  177                 if(tbl->vendor_id == devid)
  178                         return (tbl);
  179                 tbl++;
  180         }       
  181         return (tbl); /* return Unknown */
  182 }
  183       
  184 static struct xe_card_type_table *
  185 xe_card_type_lookup(u_int32_t devid, struct xe_card_type_table *tbl)
  186 {
  187         while(tbl->prod_type) {
  188                 if(tbl->prod_type == (devid & XE_PROD_UMASK))
  189                         return (tbl);
  190                 tbl++;
  191         }
  192         return (NULL);
  193 }
  194 
  195 /*
  196  * PCMCIA probe routine.
  197  * Identify the device.  Called from the bus driver when the card is
  198  * inserted or otherwise powers up.
  199  */
  200 static int
  201 xe_pccard_probe(device_t dev)
  202 {
  203         struct xe_softc *scp = (struct xe_softc *) device_get_softc(dev);
  204         u_int32_t vendor,prodid,prod;
  205         u_int16_t prodext;
  206         char *cis3_str=NULL;
  207         struct xe_vendor_table *vendor_itm;
  208         struct xe_card_type_table *card_itm;
  209         int i;
  210 
  211         /*
  212          * PCCARD_CISTPL_MANFID = 0x20
  213          */
  214         pccard_get_vendor(dev, &vendor);
  215         vendor_itm = xe_vendor_lookup(vendor, &xe_vendor_devs[0]);
  216         if (vendor_itm == NULL)
  217                 return (ENODEV);
  218         scp->vendor = vendor_itm->vendor_desc;
  219         pccard_get_product(dev, &prodid);
  220         pccard_get_prodext(dev, &prodext);
  221         /*
  222          * prod(new) =  rev, media, prod(old)
  223          * prod(new) =  (don't care), (care 0x10 bit), (care 0x0f bit)
  224          */
  225         prod = (prodid << 8) | prodext;
  226         card_itm = xe_card_type_lookup(prod, &xe_card_type_devs[0]);
  227         if (card_itm == NULL)
  228                 return (ENODEV);
  229         scp->card_type = card_itm->card_type_desc;
  230         if (card_itm->prod_type & XE_PROD_MODEM_UMASK)
  231                 scp->modem = 1;
  232         for(i=1; i!=XE_CARD_TYPE_FLAGS_DINGO; i=i<<1) {
  233                 switch(i & card_itm->flags) {
  234                 case XE_CARD_TYPE_FLAGS_CE2:
  235                         scp->ce2 = 1; break;
  236                 case XE_CARD_TYPE_FLAGS_MOHAWK:
  237                         scp->mohawk = 1; break;
  238                 case XE_CARD_TYPE_FLAGS_DINGO:
  239                         scp->dingo = 1; break;
  240                 }
  241         }
  242         /*
  243          * PCCARD_CISTPL_VERS_1 = 0x15
  244          */
  245         pccard_get_cis3_str(dev, &cis3_str);
  246         if (strcmp(scp->card_type, "CE") == 0)
  247                 if (strcmp(cis3_str, "CE2") ==0)
  248                         scp->card_type = "CE2"; /* Look for "CE2" string */
  249 
  250         /*
  251          * PCCARD_CISTPL_FUNCE = 0x22
  252          */
  253         pccard_get_ether(dev, scp->arpcom.ac_enaddr);
  254 
  255         /* Reject unsupported cards */
  256         if(strcmp(scp->card_type, "CE") == 0
  257         || strcmp(scp->card_type, "CEM") == 0) {
  258                 device_printf(dev, "Sorry, your %s card is not supported :(\n",
  259                                 scp->card_type);
  260                 return (ENODEV);
  261         }
  262 
  263         /* Success */
  264         return (0);
  265 }
  266 
  267 /*
  268  * Attach a device.
  269  */
  270 static int
  271 xe_pccard_attach(device_t dev)
  272 {
  273         struct xe_softc *scp = device_get_softc(dev);
  274         int err;
  275 
  276         if ((err = xe_activate(dev)) != 0)
  277                 return (err);
  278          
  279         /* Hack RealPorts into submission */
  280         if (scp->dingo && xe_cem56fix(dev) < 0) {
  281                 device_printf(dev, "Unable to fix your RealPort\n");
  282                 xe_deactivate(dev);
  283                 return (ENODEV);
  284         }
  285         if ((err = xe_attach(dev))) {
  286                 device_printf(dev, "xe_attach() failed! (%d)\n", err);
  287                 return (err);
  288         }
  289         return (0);
  290 }
  291 
  292 /*
  293  * The device entry is being removed, probably because someone ejected the
  294  * card.  The interface should have been brought down manually before calling
  295  * this function; if not you may well lose packets.  In any case, I shut down
  296  * the card and the interface, and hope for the best.
  297  */
  298 static int
  299 xe_pccard_detach(device_t dev)
  300 {
  301         struct xe_softc *sc = device_get_softc(dev);
  302 
  303         sc->arpcom.ac_if.if_flags &= ~IFF_RUNNING;
  304         ether_ifdetach(&sc->arpcom.ac_if);
  305         xe_deactivate(dev);
  306         return (0);
  307 }
  308 
  309 static const struct pccard_product xe_pccard_products[] = {
  310         PCMCIA_CARD(ACCTON, EN2226, 0),
  311         PCMCIA_CARD(COMPAQ2, CPQ_10_100, 0),
  312         PCMCIA_CARD(INTEL, EEPRO100, 0),
  313         PCMCIA_CARD(XIRCOM, CE, 0),
  314         PCMCIA_CARD(XIRCOM, CE2, 0),
  315         PCMCIA_CARD(XIRCOM, CE3, 0),
  316         PCMCIA_CARD(XIRCOM, CEM, 0),
  317         PCMCIA_CARD(XIRCOM, CEM28, 0),
  318         PCMCIA_CARD(XIRCOM, CEM33, 0),
  319         PCMCIA_CARD(XIRCOM, CEM56, 0),
  320         PCMCIA_CARD(XIRCOM, REM56, 0),
  321         { NULL }
  322 };
  323 
  324 static int
  325 xe_pccard_match(device_t dev)
  326 {
  327         const struct pccard_product *pp;
  328 
  329         if ((pp = pccard_product_lookup(dev, xe_pccard_products,
  330              sizeof(xe_pccard_products[0]), NULL)) != NULL) {
  331                 if (pp->pp_name != NULL)
  332                         device_set_desc(dev, pp->pp_name);
  333                 return (0);
  334         }
  335         return (EIO);
  336 }
  337 
  338 static device_method_t xe_pccard_methods[] = {
  339         /* Device interface */
  340         DEVMETHOD(device_probe,         pccard_compat_probe),
  341         DEVMETHOD(device_attach,        pccard_compat_attach),
  342         DEVMETHOD(device_detach,        xe_pccard_detach),
  343 
  344         /* Card interface */
  345         DEVMETHOD(card_compat_match,    xe_pccard_match),
  346         DEVMETHOD(card_compat_probe,    xe_pccard_probe),
  347         DEVMETHOD(card_compat_attach,   xe_pccard_attach),
  348 
  349         { 0, 0 }
  350 };
  351 
  352 static driver_t xe_pccard_driver = {
  353         "xe",
  354         xe_pccard_methods,
  355         sizeof(struct xe_softc),
  356 };
  357 
  358 devclass_t xe_devclass;
  359 
  360 DRIVER_MODULE(xe, pccard, xe_pccard_driver, xe_devclass, 0, 0);

Cache object: 55ddabc7f3c3f460d7b95ba81216964a


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