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/cardbus/if_tlp_cardbus.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_tlp_cardbus.c,v 1.39 2003/10/24 17:04:35 mycroft Exp $      */
    2 
    3 /*-
    4  * Copyright (c) 1999, 2000 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  * CardBus bus front-end for the Digital Semiconductor ``Tulip'' (21x4x)
   42  * Ethernet controller family driver.
   43  */
   44 
   45 #include <sys/cdefs.h>
   46 __KERNEL_RCSID(0, "$NetBSD: if_tlp_cardbus.c,v 1.39 2003/10/24 17:04:35 mycroft Exp $");
   47 
   48 #include "opt_inet.h"
   49 #include "opt_ns.h"
   50 #include "bpfilter.h"
   51 
   52 #include <sys/param.h>
   53 #include <sys/systm.h> 
   54 #include <sys/mbuf.h>   
   55 #include <sys/malloc.h>
   56 #include <sys/kernel.h>
   57 #include <sys/socket.h>
   58 #include <sys/ioctl.h>
   59 #include <sys/errno.h>
   60 #include <sys/device.h>
   61 
   62 #include <machine/endian.h>
   63  
   64 #include <net/if.h>
   65 #include <net/if_dl.h>
   66 #include <net/if_media.h>
   67 #include <net/if_ether.h>
   68 
   69 #if NBPFILTER > 0 
   70 #include <net/bpf.h>
   71 #endif 
   72 
   73 #ifdef INET
   74 #include <netinet/in.h> 
   75 #include <netinet/if_inarp.h>
   76 #endif
   77 
   78 #ifdef NS
   79 #include <netns/ns.h>
   80 #include <netns/ns_if.h>
   81 #endif
   82 
   83 #include <machine/bus.h>
   84 #include <machine/intr.h>
   85 
   86 #include <dev/mii/miivar.h>
   87 #include <dev/mii/mii_bitbang.h>
   88 
   89 #include <dev/ic/tulipreg.h>
   90 #include <dev/ic/tulipvar.h>
   91 
   92 #include <dev/pci/pcivar.h>
   93 #include <dev/pci/pcireg.h>
   94 #include <dev/pci/pcidevs.h>
   95 
   96 #include <dev/cardbus/cardbusvar.h>
   97 #include <dev/cardbus/cardbusdevs.h>
   98 
   99 /*
  100  * PCI configuration space registers used by the Tulip.
  101  */
  102 #define TULIP_PCI_IOBA          0x10    /* i/o mapped base */
  103 #define TULIP_PCI_MMBA          0x14    /* memory mapped base */
  104 #define TULIP_PCI_CFDA          0x40    /* configuration driver area */
  105 
  106 #define CFDA_SLEEP              0x80000000      /* sleep mode */
  107 #define CFDA_SNOOZE             0x40000000      /* snooze mode */
  108 
  109 struct tulip_cardbus_softc {
  110         struct tulip_softc sc_tulip;    /* real Tulip softc */
  111 
  112         /* CardBus-specific goo. */
  113         void    *sc_ih;                 /* interrupt handle */
  114         cardbus_devfunc_t sc_ct;        /* our CardBus devfuncs */
  115         cardbustag_t sc_tag;            /* our CardBus tag */
  116         int     sc_csr;                 /* CSR bits */
  117         bus_size_t sc_mapsize;          /* the size of mapped bus space
  118                                            region */
  119 
  120         int     sc_cben;                /* CardBus enables */
  121         int     sc_bar_reg;             /* which BAR to use */
  122         pcireg_t sc_bar_val;            /* value of the BAR */
  123 
  124         int     sc_intrline;            /* interrupt line */
  125 };
  126 
  127 int     tlp_cardbus_match __P((struct device *, struct cfdata *, void *));
  128 void    tlp_cardbus_attach __P((struct device *, struct device *, void *));
  129 int     tlp_cardbus_detach __P((struct device *, int));
  130 
  131 CFATTACH_DECL(tlp_cardbus, sizeof(struct tulip_cardbus_softc),
  132     tlp_cardbus_match, tlp_cardbus_attach, tlp_cardbus_detach, tlp_activate);
  133 
  134 const struct tulip_cardbus_product {
  135         u_int32_t       tcp_vendor;     /* PCI vendor ID */
  136         u_int32_t       tcp_product;    /* PCI product ID */
  137         tulip_chip_t    tcp_chip;       /* base Tulip chip type */
  138 } tlp_cardbus_products[] = {
  139         { PCI_VENDOR_DEC,               PCI_PRODUCT_DEC_21142,
  140           TULIP_CHIP_21142 },
  141 
  142         { PCI_VENDOR_XIRCOM,            PCI_PRODUCT_XIRCOM_X3201_3_21143,
  143           TULIP_CHIP_X3201_3 },
  144 
  145         { PCI_VENDOR_ADMTEK,            PCI_PRODUCT_ADMTEK_AN985,
  146           TULIP_CHIP_AN985 },
  147 
  148         { CARDBUS_VENDOR_ACCTON,        CARDBUS_PRODUCT_ACCTON_EN2242,
  149           TULIP_CHIP_AN985 },
  150 
  151         { CARDBUS_VENDOR_ABOCOM,        CARDBUS_PRODUCT_ABOCOM_FE2500,
  152           TULIP_CHIP_AN985 },
  153 
  154         { CARDBUS_VENDOR_ABOCOM,        CARDBUS_PRODUCT_ABOCOM_PCM200,
  155           TULIP_CHIP_AN985 },
  156 
  157         { CARDBUS_VENDOR_ABOCOM,        CARDBUS_PRODUCT_ABOCOM_FE2500MX,
  158           TULIP_CHIP_AN985 },
  159 
  160         { CARDBUS_VENDOR_HAWKING,       CARDBUS_PRODUCT_HAWKING_PN672TX,
  161           TULIP_CHIP_AN985 },
  162 
  163         { CARDBUS_VENDOR_NETGEAR,       CARDBUS_PRODUCT_NETGEAR_FA511,
  164           TULIP_CHIP_AN985 },
  165 
  166         { 0,                            0,
  167           TULIP_CHIP_INVALID },
  168 };
  169 
  170 struct tlp_cardbus_quirks {
  171         void            (*tpq_func) __P((struct tulip_cardbus_softc *,
  172                             const u_int8_t *));
  173         u_int8_t        tpq_oui[3];
  174 };
  175 
  176 void    tlp_cardbus_lxt_quirks __P((struct tulip_cardbus_softc *,
  177             const u_int8_t *));
  178 
  179 const struct tlp_cardbus_quirks tlp_cardbus_21142_quirks[] = {
  180         { tlp_cardbus_lxt_quirks,       { 0x00, 0x40, 0x05 } },
  181         { NULL,                         { 0, 0, 0 } }
  182 };
  183 
  184 void    tlp_cardbus_setup __P((struct tulip_cardbus_softc *));
  185 
  186 int     tlp_cardbus_enable __P((struct tulip_softc *));
  187 void    tlp_cardbus_disable __P((struct tulip_softc *));
  188 void    tlp_cardbus_power __P((struct tulip_softc *, int));
  189 
  190 void    tlp_cardbus_x3201_reset __P((struct tulip_softc *));
  191 
  192 const struct tulip_cardbus_product *tlp_cardbus_lookup
  193     __P((const struct cardbus_attach_args *));
  194 void tlp_cardbus_get_quirks __P((struct tulip_cardbus_softc *,
  195     const u_int8_t *, const struct tlp_cardbus_quirks *));
  196 
  197 const struct tulip_cardbus_product *
  198 tlp_cardbus_lookup(ca)
  199         const struct cardbus_attach_args *ca;
  200 {
  201         const struct tulip_cardbus_product *tcp;
  202 
  203         for (tcp = tlp_cardbus_products;
  204              tlp_chip_names[tcp->tcp_chip] != NULL;
  205              tcp++) {
  206                 if (PCI_VENDOR(ca->ca_id) == tcp->tcp_vendor &&
  207                     PCI_PRODUCT(ca->ca_id) == tcp->tcp_product)
  208                         return (tcp);
  209         }
  210         return (NULL);
  211 }
  212 
  213 void
  214 tlp_cardbus_get_quirks(csc, enaddr, tpq)
  215         struct tulip_cardbus_softc *csc;
  216         const u_int8_t *enaddr;
  217         const struct tlp_cardbus_quirks *tpq;
  218 {
  219 
  220         for (; tpq->tpq_func != NULL; tpq++) {
  221                 if (tpq->tpq_oui[0] == enaddr[0] &&
  222                     tpq->tpq_oui[1] == enaddr[1] &&
  223                     tpq->tpq_oui[2] == enaddr[2]) {
  224                         (*tpq->tpq_func)(csc, enaddr);
  225                         return;
  226                 }
  227         }
  228 }
  229 
  230 int
  231 tlp_cardbus_match(parent, match, aux)
  232         struct device *parent;
  233         struct cfdata *match;
  234         void *aux;
  235 {
  236         struct cardbus_attach_args *ca = aux;
  237 
  238         if (tlp_cardbus_lookup(ca) != NULL)
  239                 return (1);
  240 
  241         return (0);
  242 }
  243 
  244 void
  245 tlp_cardbus_attach(parent, self, aux)
  246         struct device *parent, *self;
  247         void *aux;
  248 {
  249         struct tulip_cardbus_softc *csc = (void *)self;
  250         struct tulip_softc *sc = &csc->sc_tulip;
  251         struct cardbus_attach_args *ca = aux;
  252         cardbus_devfunc_t ct = ca->ca_ct;
  253         const struct tulip_cardbus_product *tcp;
  254         u_int8_t enaddr[ETHER_ADDR_LEN];
  255         bus_addr_t adr;
  256         pcireg_t reg;
  257 
  258         sc->sc_devno = ca->ca_device;
  259         sc->sc_dmat = ca->ca_dmat;
  260         csc->sc_ct = ct;
  261         csc->sc_tag = ca->ca_tag;
  262 
  263         tcp = tlp_cardbus_lookup(ca);
  264         if (tcp == NULL) {
  265                 printf("\n");
  266                 panic("tlp_cardbus_attach: impossible");
  267         }
  268         sc->sc_chip = tcp->tcp_chip;
  269 
  270         /*
  271          * By default, Tulip registers are 8 bytes long (4 bytes
  272          * followed by a 4 byte pad).
  273          */
  274         sc->sc_regshift = 3;
  275 
  276         /*
  277          * Power management hooks.
  278          */
  279         sc->sc_enable = tlp_cardbus_enable;
  280         sc->sc_disable = tlp_cardbus_disable;
  281         sc->sc_power = tlp_cardbus_power;
  282 
  283         /*
  284          * Get revision info, and set some chip-specific variables.
  285          */
  286         sc->sc_rev = PCI_REVISION(ca->ca_class);
  287         switch (sc->sc_chip) {
  288         case TULIP_CHIP_21142:
  289                 if (sc->sc_rev >= 0x20)
  290                         sc->sc_chip = TULIP_CHIP_21143;
  291                 break;
  292 
  293         case TULIP_CHIP_AN985:
  294                 /*
  295                  * The AN983 and AN985 are very similar, and are
  296                  * differentiated by a "signature" register that
  297                  * is like, but not identical, to a PCI ID register.
  298                  */
  299                 reg = cardbus_conf_read(ct->ct_cc, ct->ct_cf, csc->sc_tag,
  300                     0x80);
  301                 switch (reg) {
  302                 case 0x09811317:
  303                         sc->sc_chip = TULIP_CHIP_AN985;
  304                         break;
  305 
  306                 case 0x09851317:
  307                         sc->sc_chip = TULIP_CHIP_AN983;
  308                         break;
  309 
  310                 }
  311                 break;
  312 
  313         default:
  314                 /* Nothing. -- to make gcc happy */
  315                 break;
  316         }
  317 
  318         printf(": %s Ethernet, pass %d.%d\n",
  319             tlp_chip_names[sc->sc_chip],
  320             (sc->sc_rev >> 4) & 0xf, sc->sc_rev & 0xf);
  321 
  322         /*
  323          * Map the device.
  324          */
  325         csc->sc_csr = CARDBUS_COMMAND_MASTER_ENABLE;
  326         if (Cardbus_mapreg_map(ct, TULIP_PCI_MMBA,
  327             CARDBUS_MAPREG_TYPE_MEM, 0, &sc->sc_st, &sc->sc_sh, &adr,
  328             &csc->sc_mapsize) == 0) {
  329 #if rbus
  330 #else
  331                 (*ct->ct_cf->cardbus_mem_open)(cc, 0, adr, adr+csc->sc_mapsize);
  332 #endif
  333                 csc->sc_cben = CARDBUS_MEM_ENABLE;
  334                 csc->sc_csr |= CARDBUS_COMMAND_MEM_ENABLE;
  335                 csc->sc_bar_reg = TULIP_PCI_MMBA;
  336                 csc->sc_bar_val = adr | CARDBUS_MAPREG_TYPE_MEM;
  337         } else if (Cardbus_mapreg_map(ct, TULIP_PCI_IOBA,
  338             CARDBUS_MAPREG_TYPE_IO, 0, &sc->sc_st, &sc->sc_sh, &adr,
  339             &csc->sc_mapsize) == 0) {
  340 #if rbus
  341 #else
  342                 (*ct->ct_cf->cardbus_io_open)(cc, 0, adr, adr+csc->sc_mapsize);
  343 #endif
  344                 csc->sc_cben = CARDBUS_IO_ENABLE;
  345                 csc->sc_csr |= CARDBUS_COMMAND_IO_ENABLE;
  346                 csc->sc_bar_reg = TULIP_PCI_IOBA;
  347                 csc->sc_bar_val = adr | CARDBUS_MAPREG_TYPE_IO;
  348         } else {
  349                 printf("%s: unable to map device registers\n",
  350                     sc->sc_dev.dv_xname);
  351                 return;
  352         }
  353 
  354         /*
  355          * Bring the chip out of powersave mode and initialize the
  356          * configuration registers.
  357          */
  358         tlp_cardbus_setup(csc);
  359 
  360         /*
  361          * Read the contents of the Ethernet Address ROM/SROM.
  362          */
  363         switch (sc->sc_chip) {
  364         case TULIP_CHIP_X3201_3:
  365                 /*
  366                  * No SROM on this chip.
  367                  */
  368                 break;
  369 
  370         default:
  371                 if (tlp_read_srom(sc) == 0)
  372                         goto cant_cope;
  373                 break;
  374         }
  375 
  376         /*
  377          * Deal with chip/board quirks.  This includes setting up
  378          * the mediasw, and extracting the Ethernet address from
  379          * the rombuf.
  380          */
  381         switch (sc->sc_chip) {
  382         case TULIP_CHIP_21142:
  383         case TULIP_CHIP_21143:
  384                 /* Check for new format SROM. */
  385                 if (tlp_isv_srom_enaddr(sc, enaddr) != 0) {
  386                         /*
  387                          * We start out with the 2114x ISV media switch.
  388                          * When we search for quirks, we may change to
  389                          * a different switch.
  390                          */
  391                         sc->sc_mediasw = &tlp_2114x_isv_mediasw;
  392                 } else if (tlp_parse_old_srom(sc, enaddr) == 0) {
  393                         /*
  394                          * Not an ISV SROM, and not in old DEC Address
  395                          * ROM format.  Try to snarf it out of the CIS.
  396                          */
  397                         if (ca->ca_cis.funce.network.netid_present == 0)
  398                                 goto cant_cope;
  399 
  400                         /* Grab the MAC address from the CIS. */
  401                         memcpy(enaddr, ca->ca_cis.funce.network.netid,
  402                             sizeof(enaddr));
  403                 }
  404 
  405                 /*
  406                  * Deal with any quirks this board might have.
  407                  */
  408                 tlp_cardbus_get_quirks(csc, enaddr, tlp_cardbus_21142_quirks);
  409 
  410                 /*
  411                  * If we don't already have a media switch, default to
  412                  * MII-over-SIO, with no special reset routine.
  413                  */
  414                 if (sc->sc_mediasw == NULL) {
  415                         printf("%s: defaulting to MII-over-SIO; no bets...\n",
  416                             sc->sc_dev.dv_xname);
  417                         sc->sc_mediasw = &tlp_sio_mii_mediasw;
  418                 }
  419                 break;
  420 
  421         case TULIP_CHIP_AN983:
  422         case TULIP_CHIP_AN985:
  423                 /*
  424                  * The ADMtek AN985's Ethernet address is located
  425                  * at offset 8 of its EEPROM.
  426                  */
  427                 memcpy(enaddr, &sc->sc_srom[8], ETHER_ADDR_LEN);
  428 
  429                 /*
  430                  * The ADMtek AN985 can be configured in Single-Chip
  431                  * mode or MAC-only mode.  Single-Chip uses the built-in
  432                  * PHY, MAC-only has an external PHY (usually HomePNA).
  433                  * The selection is based on an EEPROM setting, and both
  434                  * PHYs are access via MII attached to SIO.
  435                  *
  436                  * The AN985 "ghosts" the internal PHY onto all
  437                  * MII addresses, so we have to use a media init
  438                  * routine that limits the search.
  439                  * XXX How does this work with MAC-only mode?
  440                  */
  441                 sc->sc_mediasw = &tlp_an985_mediasw;
  442                 break;
  443 
  444         case TULIP_CHIP_X3201_3:
  445                 /*
  446                  * The X3201 doesn't have an SROM.  Lift the MAC address
  447                  * from the CIS.  Also, we have a special media switch:
  448                  * MII-on-SIO, plus some special GPIO setup.
  449                  */
  450                 memcpy(enaddr, ca->ca_cis.funce.network.netid, sizeof(enaddr));
  451                 sc->sc_reset = tlp_cardbus_x3201_reset;
  452                 sc->sc_mediasw = &tlp_sio_mii_mediasw;
  453                 break;
  454 
  455         default:
  456  cant_cope:
  457                 printf("%s: sorry, unable to handle your board\n",
  458                     sc->sc_dev.dv_xname);
  459                 return;
  460         }
  461 
  462         /* Remember which interrupt line. */
  463         csc->sc_intrline = ca->ca_intrline;
  464 
  465         /*
  466          * The CardBus cards will make it to store-and-forward mode as
  467          * soon as you put them under any kind of load, so just start
  468          * out there.
  469          */
  470         sc->sc_txthresh = TXTH_SF;
  471 
  472         /*
  473          * Finish off the attach.
  474          */
  475         tlp_attach(sc, enaddr);
  476 
  477         /*
  478          * Power down the socket.
  479          */
  480         Cardbus_function_disable(csc->sc_ct);
  481 }
  482 
  483 int
  484 tlp_cardbus_detach(self, flags)
  485         struct device *self;
  486         int flags;
  487 {
  488         struct tulip_cardbus_softc *csc = (void *)self;
  489         struct tulip_softc *sc = &csc->sc_tulip;
  490         struct cardbus_devfunc *ct = csc->sc_ct;
  491         int rv;
  492 
  493 #if defined(DIAGNOSTIC)
  494         if (ct == NULL)
  495                 panic("%s: data structure lacks", sc->sc_dev.dv_xname);
  496 #endif
  497 
  498         rv = tlp_detach(sc);
  499         if (rv)
  500                 return (rv);
  501 
  502         /*
  503          * Unhook the interrupt handler.
  504          */
  505         if (csc->sc_ih != NULL)
  506                 cardbus_intr_disestablish(ct->ct_cc, ct->ct_cf, csc->sc_ih);
  507 
  508         /*
  509          * Release bus space and close window.
  510          */
  511         if (csc->sc_bar_reg != 0)
  512                 Cardbus_mapreg_unmap(ct, csc->sc_bar_reg,
  513                     sc->sc_st, sc->sc_sh, csc->sc_mapsize);
  514 
  515         return (0);
  516 }
  517 
  518 int
  519 tlp_cardbus_enable(sc)
  520         struct tulip_softc *sc;
  521 {
  522         struct tulip_cardbus_softc *csc = (void *) sc;
  523         cardbus_devfunc_t ct = csc->sc_ct;
  524         cardbus_chipset_tag_t cc = ct->ct_cc;
  525         cardbus_function_tag_t cf = ct->ct_cf;
  526 
  527         /*
  528          * Power on the socket.
  529          */
  530         Cardbus_function_enable(ct);
  531 
  532         /*
  533          * Set up the PCI configuration registers.
  534          */
  535         tlp_cardbus_setup(csc);
  536 
  537         /*
  538          * Map and establish the interrupt.
  539          */
  540         csc->sc_ih = cardbus_intr_establish(cc, cf, csc->sc_intrline, IPL_NET,
  541             tlp_intr, sc);
  542         if (csc->sc_ih == NULL) {
  543                 printf("%s: unable to establish interrupt at %d\n",
  544                     sc->sc_dev.dv_xname, csc->sc_intrline);
  545                 Cardbus_function_disable(csc->sc_ct);
  546                 return (1);
  547         }
  548         printf("%s: interrupting at %d\n", sc->sc_dev.dv_xname,
  549             csc->sc_intrline);
  550 
  551         return (0);
  552 }
  553 
  554 void
  555 tlp_cardbus_disable(sc)
  556         struct tulip_softc *sc;
  557 {
  558         struct tulip_cardbus_softc *csc = (void *) sc;
  559         cardbus_devfunc_t ct = csc->sc_ct;
  560         cardbus_chipset_tag_t cc = ct->ct_cc;
  561         cardbus_function_tag_t cf = ct->ct_cf;
  562 
  563         /* Unhook the interrupt handler. */
  564         cardbus_intr_disestablish(cc, cf, csc->sc_ih);
  565         csc->sc_ih = NULL;
  566 
  567         /* Power down the socket. */
  568         Cardbus_function_disable(ct);
  569 }
  570 
  571 void
  572 tlp_cardbus_power(sc, why)
  573         struct tulip_softc *sc;
  574         int why;
  575 {
  576         struct tulip_cardbus_softc *csc = (void *) sc;
  577 
  578         if (why == PWR_RESUME) {
  579                 /*
  580                  * Give the PCI configuration registers a kick
  581                  * in the head.
  582                  */
  583 #ifdef DIAGNOSTIC
  584                 if (TULIP_IS_ENABLED(sc) == 0)
  585                         panic("tlp_cardbus_power");
  586 #endif
  587                 tlp_cardbus_setup(csc);
  588         }
  589 }
  590 
  591 void
  592 tlp_cardbus_setup(csc)
  593         struct tulip_cardbus_softc *csc;
  594 {
  595         struct tulip_softc *sc = &csc->sc_tulip;
  596         cardbus_devfunc_t ct = csc->sc_ct;
  597         cardbus_chipset_tag_t cc = ct->ct_cc;
  598         cardbus_function_tag_t cf = ct->ct_cf;
  599         pcireg_t reg;
  600         int pmreg;
  601 
  602         /*
  603          * Check to see if the device is in power-save mode, and
  604          * bring it out if necessary.
  605          */
  606         switch (sc->sc_chip) {
  607         case TULIP_CHIP_21142:
  608         case TULIP_CHIP_21143:
  609         case TULIP_CHIP_X3201_3:
  610                 /*
  611                  * Clear the "sleep mode" bit in the CFDA register.
  612                  */
  613                 reg = cardbus_conf_read(cc, cf, csc->sc_tag, TULIP_PCI_CFDA);
  614                 if (reg & (CFDA_SLEEP|CFDA_SNOOZE))
  615                         cardbus_conf_write(cc, cf, csc->sc_tag, TULIP_PCI_CFDA,
  616                             reg & ~(CFDA_SLEEP|CFDA_SNOOZE));
  617                 break;
  618 
  619         default:
  620                 /* Nothing. -- to make gcc happy */
  621                 break;
  622         }
  623 
  624         if (cardbus_get_capability(cc, cf, csc->sc_tag,
  625             PCI_CAP_PWRMGMT, &pmreg, 0)) {
  626                 reg = cardbus_conf_read(cc, cf, csc->sc_tag, pmreg + 4) & 0x03;
  627 #if 1 /* XXX Probably not right for CardBus. */
  628                 if (reg == 3) {
  629                         /*
  630                          * The card has lost all configuration data in
  631                          * this state, so punt.
  632                          */
  633                         printf("%s: unable to wake up from power state D3\n",
  634                             sc->sc_dev.dv_xname);
  635                         return;
  636                 }
  637 #endif
  638                 if (reg != 0) {
  639                         printf("%s: waking up from power state D%d\n",
  640                             sc->sc_dev.dv_xname, reg);
  641                         cardbus_conf_write(cc, cf, csc->sc_tag,
  642                             pmreg + 4, 0);
  643                 }
  644         }
  645 
  646         /* Make sure the right access type is on the CardBus bridge. */
  647         (*ct->ct_cf->cardbus_ctrl)(cc, csc->sc_cben);
  648         (*ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);
  649 
  650         /* Program the BAR. */
  651         cardbus_conf_write(cc, cf, csc->sc_tag, csc->sc_bar_reg,
  652             csc->sc_bar_val);
  653 
  654         /* Enable the appropriate bits in the PCI CSR. */
  655         reg = cardbus_conf_read(cc, cf, csc->sc_tag, PCI_COMMAND_STATUS_REG);
  656         reg &= ~(PCI_COMMAND_IO_ENABLE|PCI_COMMAND_MEM_ENABLE);
  657         reg |= csc->sc_csr;
  658         cardbus_conf_write(cc, cf, csc->sc_tag, PCI_COMMAND_STATUS_REG, reg);
  659 
  660         /*
  661          * Make sure the latency timer is set to some reasonable
  662          * value.
  663          */
  664         reg = cardbus_conf_read(cc, cf, csc->sc_tag, PCI_BHLC_REG);
  665         if (PCI_LATTIMER(reg) < 0x20) {
  666                 reg &= ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT);
  667                 reg |= (0x20 << PCI_LATTIMER_SHIFT);
  668                 cardbus_conf_write(cc, cf, csc->sc_tag, PCI_BHLC_REG, reg);
  669         }
  670 }
  671 
  672 void
  673 tlp_cardbus_x3201_reset(sc)
  674         struct tulip_softc *sc;
  675 {
  676         u_int32_t reg;
  677 
  678         reg = TULIP_READ(sc, CSR_SIAGEN);
  679 
  680         /* make GP[2,0] outputs */
  681         TULIP_WRITE(sc, CSR_SIAGEN, (reg & ~SIAGEN_MD) | SIAGEN_CWE |
  682             0x00050000);
  683         TULIP_WRITE(sc, CSR_SIAGEN, (reg & ~SIAGEN_CWE) | SIAGEN_MD);
  684 }
  685 
  686 void
  687 tlp_cardbus_lxt_quirks(csc, enaddr)
  688         struct tulip_cardbus_softc *csc;
  689         const u_int8_t *enaddr;
  690 {
  691         struct tulip_softc *sc = &csc->sc_tulip;
  692 
  693         sc->sc_mediasw = &tlp_sio_mii_mediasw;
  694 }

Cache object: 3961eedccdcf56c7a81d3392d93c63e1


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