root/dev/cardbus/if_xl_cardbus.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. xl_cardbus_lookup
  2. xl_cardbus_match
  3. xl_cardbus_attach
  4. xl_detach
  5. xl_cardbus_detach
  6. xl_cardbus_intr_ack

    1 /*      $OpenBSD: if_xl_cardbus.c,v 1.19 2007/05/05 13:24:03 deraadt Exp $ */
    2 /*      $NetBSD: if_xl_cardbus.c,v 1.13 2000/03/07 00:32:52 mycroft Exp $       */
    3 
    4 /*
    5  * CardBus specific routines for 3Com 3C575-family CardBus ethernet adapter
    6  *
    7  * Copyright (c) 1998 and 1999
    8  *       HAYAKAWA Koichi.  All rights reserved.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *      This product includes software developed by the author.
   21  * 4. Neither the name of the author nor the names of any co-contributors
   22  *    may be used to endorse or promote products derived from this software
   23  *    without specific prior written permission.
   24  *
   25  * THIS SOFTWARE IS PROVIDED BY HAYAKAWA KOICHI ``AS IS'' AND
   26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   28  * ARE DISCLAIMED.  IN NO EVENT SHALL TAKESHI OHASHI OR CONTRIBUTORS BE LIABLE
   29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   35  * SUCH DAMAGE.
   36  *
   37  *
   38  */
   39 
   40 #include "bpfilter.h"
   41 
   42 #include <sys/param.h>
   43 #include <sys/systm.h>
   44 #include <sys/mbuf.h>
   45 #include <sys/socket.h>
   46 #include <sys/ioctl.h>
   47 #include <sys/errno.h>
   48 #include <sys/malloc.h>
   49 #include <sys/kernel.h>
   50 #include <sys/proc.h>
   51 #include <sys/device.h>
   52 
   53 #include <net/if.h>
   54 #include <net/if_dl.h>
   55 #include <net/if_types.h>
   56 #include <net/if_media.h>
   57 
   58 #ifdef INET
   59 #include <netinet/in.h>
   60 #include <netinet/in_systm.h>
   61 #include <netinet/in_var.h>
   62 #include <netinet/ip.h>
   63 #include <netinet/if_ether.h>
   64 #endif
   65 
   66 #include <machine/cpu.h>
   67 #include <machine/bus.h>
   68 
   69 #include <dev/cardbus/cardbusvar.h>
   70 #include <dev/pci/pcidevs.h>
   71 
   72 #include <dev/mii/mii.h>
   73 #include <dev/mii/miivar.h>
   74 
   75 #include <dev/ic/xlreg.h>
   76 
   77 #if defined XL_DEBUG
   78 #define DPRINTF(a) printf a
   79 #else
   80 #define DPRINTF(a)
   81 #endif
   82 
   83 #define CARDBUS_3C575BTX_FUNCSTAT_PCIREG  CARDBUS_BASE2_REG  /* means 0x18 */
   84 
   85 int xl_cardbus_match(struct device *, void *, void *);
   86 void xl_cardbus_attach(struct device *, struct device *,void *);
   87 int xl_cardbus_detach(struct device *, int);
   88 void xl_cardbus_intr_ack(struct xl_softc *);
   89 
   90 #define XL_CARDBUS_BOOMERANG    0x0001
   91 #define XL_CARDBUS_CYCLONE      0x0002
   92 
   93 #define XL_CARDBUS_INTR         0x0004
   94 #define XL_CARDBUS_INTR_ACK     0x8000
   95 
   96 struct xl_cardbus_softc {
   97         struct xl_softc sc_softc;
   98 
   99         cardbus_devfunc_t sc_ct;
  100         int sc_intrline;
  101         u_int8_t sc_cardbus_flags;
  102         u_int8_t sc_cardtype;
  103 
  104         /* CardBus function status space.  575B requests it. */
  105         bus_space_tag_t sc_funct;
  106         bus_space_handle_t sc_funch;
  107         bus_size_t sc_funcsize;
  108 
  109         bus_size_t sc_mapsize;          /* size of mapped bus space region */
  110 };
  111 
  112 struct cfattach xl_cardbus_ca = {
  113         sizeof(struct xl_cardbus_softc), xl_cardbus_match,
  114             xl_cardbus_attach, xl_cardbus_detach
  115 };
  116 
  117 const struct xl_cardbus_product {
  118         u_int32_t       ecp_prodid;     /* CardBus product ID */
  119         int             ecp_flags;      /* initial softc flags */
  120         pcireg_t        ecp_csr;        /* PCI CSR flags */
  121         int             ecp_cardtype;   /* card type */
  122         const char      *ecp_name;      /* device name */
  123 } xl_cardbus_products[] = {
  124         { PCI_PRODUCT_3COM_3C575,
  125           XL_FLAG_PHYOK | XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_8BITROM,
  126           CARDBUS_COMMAND_IO_ENABLE | CARDBUS_COMMAND_MASTER_ENABLE,
  127           XL_CARDBUS_BOOMERANG,
  128           "3c575-TX Ethernet" },
  129 
  130         { PCI_PRODUCT_3COM_3CCFE575BT,
  131           XL_FLAG_PHYOK | XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_8BITROM |
  132               XL_FLAG_INVERT_LED_PWR,
  133           CARDBUS_COMMAND_IO_ENABLE | CARDBUS_COMMAND_MEM_ENABLE |
  134               CARDBUS_COMMAND_MASTER_ENABLE,
  135           XL_CARDBUS_CYCLONE,
  136           "3c575B-TX Ethernet" },
  137 
  138         { PCI_PRODUCT_3COM_3CCFE575CT,
  139           XL_FLAG_PHYOK | XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_8BITROM |
  140               XL_FLAG_INVERT_MII_PWR,
  141           CARDBUS_COMMAND_IO_ENABLE | CARDBUS_COMMAND_MEM_ENABLE |
  142               CARDBUS_COMMAND_MASTER_ENABLE,
  143           XL_CARDBUS_CYCLONE,
  144           "3c575C-TX Ethernet" },
  145 
  146         { PCI_PRODUCT_3COM_3CCFEM656,
  147           XL_FLAG_PHYOK | XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_8BITROM |
  148               XL_FLAG_INVERT_LED_PWR | XL_FLAG_INVERT_MII_PWR,
  149           CARDBUS_COMMAND_IO_ENABLE | CARDBUS_COMMAND_MEM_ENABLE |
  150               CARDBUS_COMMAND_MASTER_ENABLE,
  151           XL_CARDBUS_CYCLONE,
  152           "3c656-TX Ethernet" },
  153 
  154         { PCI_PRODUCT_3COM_3CCFEM656B,
  155           XL_FLAG_PHYOK | XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_8BITROM |
  156               XL_FLAG_INVERT_LED_PWR | XL_FLAG_INVERT_MII_PWR,
  157           CARDBUS_COMMAND_IO_ENABLE | CARDBUS_COMMAND_MEM_ENABLE |
  158               CARDBUS_COMMAND_MASTER_ENABLE,
  159           XL_CARDBUS_CYCLONE,
  160           "3c656B-TX Ethernet" },
  161 
  162         { PCI_PRODUCT_3COM_3CCFEM656C,
  163           XL_FLAG_PHYOK | XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_8BITROM |
  164               XL_FLAG_INVERT_MII_PWR,
  165           CARDBUS_COMMAND_IO_ENABLE | CARDBUS_COMMAND_MEM_ENABLE |
  166               CARDBUS_COMMAND_MASTER_ENABLE,
  167           XL_CARDBUS_CYCLONE,
  168           "3c656C-TX Ethernet" },
  169 
  170         { 0,
  171           0,
  172           0,
  173           0,
  174           NULL },
  175 };
  176 
  177 const struct xl_cardbus_product *xl_cardbus_lookup(const struct cardbus_attach_args *);
  178 
  179 const struct xl_cardbus_product *
  180 xl_cardbus_lookup(const struct cardbus_attach_args *ca)
  181 {
  182         const struct xl_cardbus_product *ecp;
  183 
  184         if (CARDBUS_VENDOR(ca->ca_id) != PCI_VENDOR_3COM)
  185                 return (NULL);
  186 
  187         for (ecp = xl_cardbus_products; ecp->ecp_name != NULL; ecp++)
  188                 if (CARDBUS_PRODUCT(ca->ca_id) == ecp->ecp_prodid)
  189                         return (ecp);
  190         return (NULL);
  191 }
  192 
  193 int
  194 xl_cardbus_match(struct device *parent, void *match, void *aux)
  195 {
  196         struct cardbus_attach_args *ca = aux;
  197 
  198         if (xl_cardbus_lookup(ca) != NULL)
  199                 return (1);
  200 
  201         return (0);
  202 }
  203 
  204 void
  205 xl_cardbus_attach(struct device *parent, struct device *self, void *aux)
  206 {
  207         struct xl_cardbus_softc *csc = (void *)self;
  208         struct xl_softc *sc = &csc->sc_softc;
  209         struct cardbus_attach_args *ca = aux;
  210         cardbus_devfunc_t ct = ca->ca_ct;
  211         cardbus_chipset_tag_t cc = ct->ct_cc;
  212         cardbus_function_tag_t cf = ct->ct_cf;
  213         cardbusreg_t iob, command, bhlc;
  214         const struct xl_cardbus_product *ecp;
  215         bus_space_handle_t ioh;
  216         bus_addr_t adr;
  217 
  218         if (Cardbus_mapreg_map(ct, CARDBUS_BASE0_REG, CARDBUS_MAPREG_TYPE_IO, 0,
  219             &sc->xl_btag, &ioh, &adr, &csc->sc_mapsize)) {
  220                 printf(": can't map i/o space\n");
  221                 return;
  222         }
  223 
  224         ecp = xl_cardbus_lookup(ca);
  225         if (ecp == NULL) {
  226                 printf("\n");
  227                 panic("xl_cardbus_attach: impossible");
  228         }
  229 
  230         printf(": 3Com %s", ecp->ecp_name);
  231 
  232         sc->xl_flags = ecp->ecp_flags;
  233         sc->sc_dmat = ca->ca_dmat;
  234 
  235         iob = adr;
  236         sc->xl_bhandle = ioh;
  237 
  238         (ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_IO_ENABLE);
  239 
  240         command = cardbus_conf_read(cc, cf, ca->ca_tag,
  241             CARDBUS_COMMAND_STATUS_REG);
  242         command |= ecp->ecp_csr;
  243         csc->sc_cardtype = ecp->ecp_cardtype;
  244 
  245         if (csc->sc_cardtype == XL_CARDBUS_CYCLONE) {
  246                 /* map CardBus function status window */
  247                 if (Cardbus_mapreg_map(ct, CARDBUS_BASE2_REG,
  248                     CARDBUS_MAPREG_TYPE_MEM, 0, &csc->sc_funct,
  249                     &csc->sc_funch, 0, &csc->sc_funcsize)) {
  250                         printf("%s: unable to map function status window\n",
  251                             self->dv_xname);
  252                         return;
  253                 }
  254 
  255                 /*
  256                  * Make sure CardBus bridge can access memory space.  Usually
  257                  * memory access is enabled by BIOS, but some BIOSes do not
  258                  * enable it.
  259                  */
  260                 (ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_MEM_ENABLE);
  261         }
  262 
  263         (ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);
  264         cardbus_conf_write(cc, cf, ca->ca_tag, CARDBUS_COMMAND_STATUS_REG,
  265             command);
  266   
  267         /*
  268          * set latency timer
  269          */
  270         bhlc = cardbus_conf_read(cc, cf, ca->ca_tag, CARDBUS_BHLC_REG);
  271         if (CARDBUS_LATTIMER(bhlc) < 0x20) {
  272                 /* at least the value of latency timer should 0x20. */
  273                 DPRINTF(("if_xl_cardbus: lattimer 0x%x -> 0x20\n",
  274                     CARDBUS_LATTIMER(bhlc)));
  275                 bhlc &= ~(CARDBUS_LATTIMER_MASK << CARDBUS_LATTIMER_SHIFT);
  276                 bhlc |= (0x20 << CARDBUS_LATTIMER_SHIFT);
  277                 cardbus_conf_write(cc, cf, ca->ca_tag, CARDBUS_BHLC_REG, bhlc);
  278         }
  279 
  280         csc->sc_ct = ca->ca_ct;
  281         csc->sc_intrline = ca->ca_intrline;
  282 
  283         /* Map and establish the interrupt. */
  284 
  285         sc->xl_intrhand = cardbus_intr_establish(cc, cf, ca->ca_intrline,
  286             IPL_NET, xl_intr, csc, self->dv_xname);
  287 
  288         if (sc->xl_intrhand == NULL) {
  289                 printf(": couldn't establish interrupt");
  290                 printf(" at %d", ca->ca_intrline);
  291                 printf("\n");
  292                 return;
  293         }
  294         printf(": irq %d", ca->ca_intrline);
  295 
  296         sc->intr_ack = xl_cardbus_intr_ack;
  297 
  298         xl_attach(sc);
  299 
  300         if (csc->sc_cardtype == XL_CARDBUS_CYCLONE)
  301                 bus_space_write_4(csc->sc_funct, csc->sc_funch,
  302                     XL_CARDBUS_INTR, XL_CARDBUS_INTR_ACK);
  303 
  304 }
  305 
  306 int
  307 xl_detach(struct xl_softc *sc)
  308 {
  309         struct ifnet *ifp = &sc->sc_arpcom.ac_if;
  310         extern void xl_freetxrx(struct xl_softc *);
  311 
  312         /* Unhook our tick handler. */
  313         timeout_del(&sc->xl_stsup_tmo);
  314 
  315         xl_freetxrx(sc);
  316 
  317         /* Detach all PHYs */
  318         if (sc->xl_hasmii)
  319                 mii_detach(&sc->sc_mii, MII_PHY_ANY, MII_OFFSET_ANY);
  320 
  321         /* Delete all remaining media. */
  322         ifmedia_delete_instance(&sc->sc_mii.mii_media, IFM_INST_ANY);
  323 
  324         ether_ifdetach(ifp);
  325         if_detach(ifp);
  326 
  327         if (sc->sc_sdhook != NULL)
  328                 shutdownhook_disestablish(sc->sc_sdhook);
  329         if (sc->sc_pwrhook != NULL)
  330                 powerhook_disestablish(sc->sc_pwrhook);
  331 
  332         return (0);
  333 }
  334 
  335 int
  336 xl_cardbus_detach(struct device *self, int arg)
  337 {
  338         struct xl_cardbus_softc *csc = (void *)self;
  339         struct xl_softc *sc = &csc->sc_softc;
  340         struct cardbus_devfunc *ct = csc->sc_ct;
  341         int rv = 0;
  342 
  343 #if defined(DIAGNOSTIC)
  344         if (ct == NULL) {
  345                 panic("%s: data structure lacks", sc->sc_dev.dv_xname);
  346         }
  347 #endif
  348 
  349         rv = xl_detach(sc);
  350         if (rv == 0) {
  351                 /*
  352                  * Unhook the interrupt handler.
  353                  */
  354                 cardbus_intr_disestablish(ct->ct_cc, ct->ct_cf,
  355                     sc->xl_intrhand);
  356 
  357                 if (csc->sc_cardtype == XL_CARDBUS_CYCLONE) {
  358                         Cardbus_mapreg_unmap(ct, CARDBUS_BASE2_REG,
  359                             csc->sc_funct, csc->sc_funch, csc->sc_funcsize);
  360                 }
  361 
  362                 Cardbus_mapreg_unmap(ct, CARDBUS_BASE0_REG, sc->xl_btag,
  363                     sc->xl_bhandle, csc->sc_mapsize);
  364         }
  365         return (rv);
  366 }
  367 
  368 void
  369 xl_cardbus_intr_ack(struct xl_softc *sc)
  370 {
  371         struct xl_cardbus_softc *csc = (struct xl_cardbus_softc *)sc;
  372 
  373         bus_space_write_4(csc->sc_funct, csc->sc_funch, XL_CARDBUS_INTR,
  374             XL_CARDBUS_INTR_ACK);
  375 }

/* [<][>][^][v][top][bottom][index][help] */