root/dev/cardbus/if_rl_cardbus.c

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

DEFINITIONS

This source file includes following definitions.
  1. rl_cardbus_match
  2. rl_cardbus_attach
  3. rl_detach
  4. rl_cardbus_detach
  5. rl_cardbus_setup

    1 /*      $OpenBSD: if_rl_cardbus.c,v 1.16 2007/05/08 18:49:32 deraadt Exp $ */
    2 /*      $NetBSD: if_rl_cardbus.c,v 1.3.8.3 2001/11/14 19:14:02 nathanw Exp $    */
    3 
    4 /*
    5  * Copyright (c) 2000 Masanori Kanaoka
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. The name of the author may not be used to endorse or promote products
   17  *    derived from this software without specific prior written permission.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
   28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   29  */
   30 
   31 /*
   32  * if_rl_cardbus.c:
   33  *      Cardbus specific routines for RealTek 8139 ethernet adapter.
   34  *      Tested for 
   35  *              - elecom-Laneed LD-10/100CBA (Accton MPX5030)
   36  *              - MELCO         LPC3-TX-CB   (RealTek 8139)
   37  */
   38 
   39 #include "bpfilter.h"
   40 
   41 #include <sys/param.h>
   42 #include <sys/systm.h>
   43 #include <sys/mbuf.h>
   44 #include <sys/socket.h>
   45 #include <sys/ioctl.h>
   46 #include <sys/errno.h>
   47 #include <sys/malloc.h>
   48 #include <sys/kernel.h>
   49 #include <sys/timeout.h>
   50 #include <sys/device.h>
   51  
   52 #include <net/if.h>
   53 #include <net/if_dl.h>
   54 #include <net/if_types.h>
   55 #include <net/if_media.h>
   56 
   57 #include <machine/endian.h>
   58 
   59 #if NBPFILTER > 0
   60 #include <net/bpf.h>
   61 #endif
   62 
   63 #ifdef INET
   64 #include <netinet/in.h>
   65 #include <netinet/in_systm.h>
   66 #include <netinet/in_var.h>
   67 #include <netinet/ip.h>
   68 #include <netinet/if_ether.h>
   69 #endif
   70 
   71 #include <machine/bus.h>
   72 #include <machine/intr.h>
   73 
   74 #include <dev/mii/miivar.h>
   75 
   76 #include <dev/pci/pcivar.h>
   77 #include <dev/pci/pcireg.h>
   78 #include <dev/pci/pcidevs.h>
   79 
   80 #include <dev/cardbus/cardbusvar.h>
   81 
   82 /*
   83  * Default to using PIO access for this driver. On SMP systems,
   84  * there appear to be problems with memory mapped mode: it looks like
   85  * doing too many memory mapped access back to back in rapid succession
   86  * can hang the bus. I'm inclined to blame this on crummy design/construction
   87  * on the part of RealTek. Memory mapped mode does appear to work on
   88  * uniprocessor systems though.
   89  */
   90 #define RL_USEIOSPACE 
   91 
   92 #include <dev/ic/rtl81x9reg.h>
   93 
   94 /*
   95  * Various supported device vendors/types and their names.
   96  */
   97 const struct cardbus_matchid rl_cardbus_devices[] = {
   98         { PCI_VENDOR_ACCTON, PCI_PRODUCT_ACCTON_5030 },
   99         { PCI_VENDOR_ABOCOM, PCI_PRODUCT_ABOCOM_FE2000VX },
  100         { PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8138 },
  101         { PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8139 },
  102         { PCI_VENDOR_COREGA, PCI_PRODUCT_COREGA_CB_TXD },
  103         { PCI_VENDOR_COREGA, PCI_PRODUCT_COREGA_2CB_TXD },
  104         { PCI_VENDOR_DLINK, PCI_PRODUCT_DLINK_DFE690TXD },
  105         { PCI_VENDOR_PLANEX, PCI_PRODUCT_PLANEX_FNW_3603_TX },
  106         { PCI_VENDOR_PLANEX, PCI_PRODUCT_PLANEX_FNW_3800_TX },
  107 };
  108 
  109 struct rl_cardbus_softc {
  110         struct rl_softc sc_rl;  /* real rtk softc */ 
  111 
  112         /* CardBus-specific goo. */
  113         void *sc_ih;
  114         cardbus_devfunc_t sc_ct;
  115         cardbustag_t sc_tag;
  116         int sc_csr;
  117         int sc_cben;
  118         int sc_bar_reg;
  119         pcireg_t sc_bar_val;
  120         bus_size_t sc_mapsize;
  121         int sc_intrline;
  122 };
  123 
  124 static int rl_cardbus_match(struct device *, void *, void *);
  125 static void rl_cardbus_attach(struct device *, struct device *, void *);
  126 static int rl_cardbus_detach(struct device *, int);
  127 void rl_cardbus_setup(struct rl_cardbus_softc *);
  128 
  129 struct cfattach rl_cardbus_ca = {
  130         sizeof(struct rl_cardbus_softc), rl_cardbus_match, rl_cardbus_attach,
  131             rl_cardbus_detach
  132 };
  133 
  134 int
  135 rl_cardbus_match(parent, match, aux)
  136         struct device *parent;
  137         void *match;
  138         void *aux;
  139 {
  140         return (cardbus_matchbyid((struct cardbus_attach_args *)aux,
  141             rl_cardbus_devices,
  142             sizeof(rl_cardbus_devices)/sizeof(rl_cardbus_devices[0])));
  143 }
  144 
  145 
  146 void
  147 rl_cardbus_attach(parent, self, aux)
  148         struct device *parent, *self;
  149         void *aux;
  150 {
  151         struct rl_cardbus_softc *csc = (struct rl_cardbus_softc *)self;
  152         struct rl_softc *sc = &csc->sc_rl;
  153         struct cardbus_attach_args *ca = aux;
  154         struct cardbus_softc *psc =
  155             (struct cardbus_softc *)sc->sc_dev.dv_parent;
  156         cardbus_chipset_tag_t cc = psc->sc_cc;
  157         cardbus_function_tag_t cf = psc->sc_cf;                            
  158         cardbus_devfunc_t ct = ca->ca_ct;
  159         bus_addr_t adr;
  160 
  161         sc->sc_dmat = ca->ca_dmat;
  162         csc->sc_ct = ct;
  163         csc->sc_tag = ca->ca_tag;
  164         csc->sc_intrline = ca->ca_intrline;
  165 
  166         /*
  167          * Map control/status registers.
  168          */
  169         csc->sc_csr = CARDBUS_COMMAND_MASTER_ENABLE;
  170 #ifdef RL_USEIOSPACE
  171         if (Cardbus_mapreg_map(ct, RL_PCI_LOIO, CARDBUS_MAPREG_TYPE_IO, 0,
  172             &sc->rl_btag, &sc->rl_bhandle, &adr, &csc->sc_mapsize) == 0) {
  173                 csc->sc_cben = CARDBUS_IO_ENABLE;
  174                 csc->sc_csr |= CARDBUS_COMMAND_IO_ENABLE;
  175                 csc->sc_bar_reg = RL_PCI_LOIO;
  176                 csc->sc_bar_val = adr | CARDBUS_MAPREG_TYPE_IO;
  177         }
  178 #else
  179         if (Cardbus_mapreg_map(ct, RL_PCI_LOMEM, CARDBUS_MAPREG_TYPE_MEM, 0,
  180             &sc->rl_btag, &sc->rl_bhandle, &adr, &csc->sc_mapsize) == 0) {
  181                 csc->sc_cben = CARDBUS_MEM_ENABLE;
  182                 csc->sc_csr |= CARDBUS_COMMAND_MEM_ENABLE;
  183                 csc->sc_bar_reg = RL_PCI_LOMEM;
  184                 csc->sc_bar_val = adr | CARDBUS_MAPREG_TYPE_MEM;
  185         }
  186 #endif
  187         else {
  188                 printf("%s: unable to map deviceregisters\n",
  189                          sc->sc_dev.dv_xname);
  190                 return;
  191         }
  192 
  193         Cardbus_function_enable(ct);
  194 
  195         rl_cardbus_setup(csc);
  196 
  197         /*
  198          * Map and establish the interrupt.
  199          */
  200         csc->sc_ih = cardbus_intr_establish(cc, cf, csc->sc_intrline, IPL_NET,
  201             rl_intr, sc, sc->sc_dev.dv_xname);
  202         if (csc->sc_ih == NULL) {
  203                 printf(": couldn't establish interrupt\n");
  204                 Cardbus_function_disable(csc->sc_ct);
  205                 return;
  206         }
  207         printf(": irq %d", csc->sc_intrline);
  208 
  209         /* XXX - hardcode this, for now */
  210         sc->rl_type = RL_8139;
  211 
  212         rl_attach(sc);
  213 }
  214 
  215 extern int rl_detach(struct rl_softc *);
  216 
  217 int
  218 rl_detach(sc)
  219         struct rl_softc *sc;
  220 {
  221         struct ifnet *ifp = &sc->sc_arpcom.ac_if;
  222 
  223         /* Unhook our tick handler. */
  224         timeout_del(&sc->sc_tick_tmo);
  225 
  226         /* Detach any PHYs we might have. */
  227         if (LIST_FIRST(&sc->sc_mii.mii_phys) != NULL)
  228                 mii_detach(&sc->sc_mii, MII_PHY_ANY, MII_OFFSET_ANY);
  229 
  230         /* Delete any remaining media. */
  231         ifmedia_delete_instance(&sc->sc_mii.mii_media, IFM_INST_ANY);
  232 
  233         ether_ifdetach(ifp);
  234         if_detach(ifp);
  235 
  236         if (sc->sc_sdhook != NULL)
  237                 shutdownhook_disestablish(sc->sc_sdhook);
  238         if (sc->sc_pwrhook != NULL)
  239                 powerhook_disestablish(sc->sc_pwrhook);
  240 
  241         return (0);
  242 }
  243 
  244 int 
  245 rl_cardbus_detach(self, flags)
  246         struct device *self;
  247         int flags;
  248 {
  249         struct rl_cardbus_softc *csc = (void *) self;
  250         struct rl_softc *sc = &csc->sc_rl;
  251         struct cardbus_devfunc *ct = csc->sc_ct;
  252         int     rv;
  253 
  254 #ifdef DIAGNOSTIC
  255         if (ct == NULL)
  256                 panic("%s: data structure lacks", sc->sc_dev.dv_xname);
  257 #endif
  258         rv = rl_detach(sc);
  259         if (rv)
  260                 return (rv);
  261         /*
  262          * Unhook the interrupt handler.
  263          */
  264         if (csc->sc_ih != NULL)
  265                 cardbus_intr_disestablish(ct->ct_cc, ct->ct_cf, csc->sc_ih);
  266         
  267         /*
  268          * Release bus space and close window.
  269          */
  270         if (csc->sc_bar_reg != 0)
  271                 Cardbus_mapreg_unmap(ct, csc->sc_bar_reg,
  272                         sc->rl_btag, sc->rl_bhandle, csc->sc_mapsize);
  273 
  274         return (0);
  275 }
  276 
  277 void 
  278 rl_cardbus_setup(csc)
  279         struct rl_cardbus_softc *csc;
  280 {
  281         struct rl_softc *sc = &csc->sc_rl;
  282         cardbus_devfunc_t ct = csc->sc_ct;
  283         cardbus_chipset_tag_t cc = ct->ct_cc;
  284         cardbus_function_tag_t cf = ct->ct_cf;
  285         pcireg_t        reg, command;
  286         int             pmreg;
  287 
  288         /*
  289          * Handle power management nonsense.
  290          */
  291         if (cardbus_get_capability(cc, cf, csc->sc_tag,
  292             PCI_CAP_PWRMGMT, &pmreg, 0)) {
  293                 command = cardbus_conf_read(cc, cf, csc->sc_tag, pmreg + 4);
  294                 if (command & RL_PSTATE_MASK) {
  295                         pcireg_t                iobase, membase, irq;
  296 
  297                         /* Save important PCI config data. */
  298                         iobase = cardbus_conf_read(cc, cf, csc->sc_tag,
  299                             RL_PCI_LOIO);
  300                         membase = cardbus_conf_read(cc, cf,csc->sc_tag,
  301                             RL_PCI_LOMEM);
  302                         irq = cardbus_conf_read(cc, cf,csc->sc_tag,
  303                             PCI_PRODUCT_DELTA_8139);
  304 
  305                         /* Reset the power state. */
  306                         printf("%s: chip is in D%d power mode "
  307                             "-- setting to D0\n", sc->sc_dev.dv_xname,
  308                             command & RL_PSTATE_MASK);
  309                         command &= 0xFFFFFFFC;
  310                         cardbus_conf_write(cc, cf, csc->sc_tag,
  311                             pmreg + 4, command);
  312 
  313                         /* Restore PCI config data. */
  314                         cardbus_conf_write(cc, cf, csc->sc_tag,
  315                             RL_PCI_LOIO, iobase);
  316                         cardbus_conf_write(cc, cf, csc->sc_tag,
  317                             RL_PCI_LOMEM, membase);
  318                         cardbus_conf_write(cc, cf, csc->sc_tag,
  319                             PCI_PRODUCT_DELTA_8139, irq);
  320                 }
  321         }
  322 
  323         /* Make sure the right access type is on the CardBus bridge. */
  324         (*ct->ct_cf->cardbus_ctrl)(cc, csc->sc_cben);
  325         (*ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);
  326 
  327         /* Program the BAR */
  328         cardbus_conf_write(cc, cf, csc->sc_tag,
  329                 csc->sc_bar_reg, csc->sc_bar_val);
  330 
  331         /* Enable the appropriate bits in the CARDBUS CSR. */
  332         reg = cardbus_conf_read(cc, cf, csc->sc_tag, 
  333             CARDBUS_COMMAND_STATUS_REG);
  334         reg &= ~(CARDBUS_COMMAND_IO_ENABLE|CARDBUS_COMMAND_MEM_ENABLE);
  335         reg |= csc->sc_csr;
  336         cardbus_conf_write(cc, cf, csc->sc_tag, 
  337             CARDBUS_COMMAND_STATUS_REG, reg);
  338 
  339         /*
  340          * Make sure the latency timer is set to some reasonable
  341          * value.
  342          */
  343         reg = cardbus_conf_read(cc, cf, csc->sc_tag, CARDBUS_BHLC_REG);
  344         if (CARDBUS_LATTIMER(reg) < 0x20) {
  345                 reg &= ~(CARDBUS_LATTIMER_MASK << CARDBUS_LATTIMER_SHIFT);
  346                 reg |= (0x20 << CARDBUS_LATTIMER_SHIFT);
  347                 cardbus_conf_write(cc, cf, csc->sc_tag, CARDBUS_BHLC_REG, reg);
  348         }
  349 }
  350 

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