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/ed/if_ed_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) 1995, David Greenman
    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 unmodified, this list of conditions, and the following
   10  *    disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  *
   27  * $FreeBSD: src/sys/dev/ed/if_ed_pccard.c,v 1.55 2003/12/31 04:25:00 kato Exp $
   28  */
   29 
   30 #include "opt_ed.h"
   31 
   32 #include <sys/param.h>
   33 #include <sys/systm.h>
   34 #include <sys/socket.h>
   35 #include <sys/kernel.h>
   36 #include <sys/conf.h>
   37 #include <sys/uio.h>
   38 #include <sys/module.h>
   39 #include <sys/interrupt.h>
   40 #include <sys/bus.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_mib.h>
   47 #include <net/if_media.h>
   48 #include <net/ifq_var.h>
   49 
   50 #include "if_edreg.h"
   51 #include "if_edvar.h"
   52 #include <bus/pccard/pccard_cis.h>
   53 #include <bus/pccard/pccardvar.h>
   54 #ifndef ED_NO_MIIBUS
   55 #include <dev/netif/mii_layer/mii.h>
   56 #include <dev/netif/mii_layer/miivar.h>
   57 #endif
   58 
   59 #include "card_if.h"
   60 #include "pccarddevs.h"
   61 #ifndef ED_NO_MIIBUS
   62 /* "device miibus" required.  See GENERIC if you get errors here. */
   63 #include "miibus_if.h"
   64 
   65 MODULE_DEPEND(ed, miibus, 1, 1, 1);
   66 #endif
   67 MODULE_DEPEND(ed, pccard, 1, 1, 1);
   68 
   69 /*
   70  *      PC-Card (PCMCIA) specific code.
   71  */
   72 static int      ed_pccard_match(device_t);
   73 static int      ed_pccard_probe(device_t);
   74 static int      ed_pccard_attach(device_t);
   75 static int      ed_pccard_detach(device_t);
   76 
   77 static int      ed_pccard_Linksys(device_t dev);
   78 static int      ed_pccard_ax88190(device_t dev);
   79 
   80 static void     ax88190_geteprom(struct ed_softc *);
   81 static int      ed_pccard_memwrite(device_t dev, off_t offset, u_char byte);
   82 #ifndef ED_NO_MIIBUS
   83 static void     ed_pccard_dlink_mii_reset(struct ed_softc *sc);
   84 static u_int    ed_pccard_dlink_mii_readbits(struct ed_softc *sc, int nbits);
   85 static void     ed_pccard_dlink_mii_writebits(struct ed_softc *sc, u_int val,
   86     int nbits);
   87 #endif
   88 
   89 /*
   90  *      ed_pccard_detach - unload the driver and clear the table.
   91  *      XXX TODO:
   92  *      This is usually called when the card is ejected, but
   93  *      can be caused by a modunload of a controller driver.
   94  *      The idea is to reset the driver's view of the device
   95  *      and ensure that any driver entry points such as
   96  *      read and write do not hang.
   97  */
   98 static int
   99 ed_pccard_detach(device_t dev)
  100 {
  101         struct ed_softc *sc = device_get_softc(dev);
  102         struct ifnet *ifp = &sc->arpcom.ac_if;
  103 
  104         lwkt_serialize_enter(ifp->if_serializer);
  105 
  106         if (sc->gone) {
  107                 device_printf(dev, "already unloaded\n");
  108                 lwkt_serialize_exit(ifp->if_serializer);
  109                 return (0);
  110         }
  111         ed_stop(sc);
  112         ifp->if_flags &= ~IFF_RUNNING;
  113         sc->gone = 1;
  114         bus_teardown_intr(dev, sc->irq_res, sc->irq_handle);
  115 
  116         lwkt_serialize_exit(ifp->if_serializer);
  117 
  118         ether_ifdetach(ifp);
  119         ed_release_resources(dev);
  120         return (0);
  121 }
  122 
  123 static const struct ed_product {
  124         struct pccard_product   prod;
  125         int flags;
  126 #define NE2000DVF_DL10019       0x0001          /* chip is D-Link DL10019 */
  127 #define NE2000DVF_AX88190       0x0002          /* chip is ASIX AX88190 */
  128 } ed_pccard_products[] = {
  129         { PCMCIA_CARD(ACCTON, EN2212, 0), 0},
  130         { PCMCIA_CARD(ALLIEDTELESIS, LA_PCM, 0), 0},
  131         { PCMCIA_CARD(AMBICOM, AMB8002T, 0), 0},
  132         { PCMCIA_CARD(BILLIONTON, LNT10TN, 0), 0},
  133         { PCMCIA_CARD(BILLIONTON, CFLT10N, 0), 0},
  134         { PCMCIA_CARD(BUFFALO, LPC3_CLT,  0), 0},
  135         { PCMCIA_CARD(BUFFALO, LPC3_CLX,  0), NE2000DVF_AX88190},
  136         { PCMCIA_CARD(BUFFALO, LPC_CF_CLT,  0), 0},
  137         { PCMCIA_CARD(CNET, NE2000, 0), 0},
  138         { PCMCIA_CARD(COMPEX, LINKPORT_ENET_B, 0), 0},
  139         { PCMCIA_CARD(COREGA, ETHER_II_PCC_T, 0), 0},
  140         { PCMCIA_CARD(COREGA, ETHER_II_PCC_TD, 0), 0},
  141         { PCMCIA_CARD(COREGA, ETHER_PCC_T, 0), 0},
  142         { PCMCIA_CARD(COREGA, ETHER_PCC_TD, 0), 0},
  143         { PCMCIA_CARD(COREGA, FAST_ETHER_PCC_TX, 0), NE2000DVF_DL10019 },
  144         { PCMCIA_CARD(COREGA, FETHER_PCC_TXD, 0), NE2000DVF_AX88190 },
  145         { PCMCIA_CARD(COREGA, FETHER_PCC_TXF, 0), NE2000DVF_DL10019 },
  146         { PCMCIA_CARD(DAYNA, COMMUNICARD_E_1, 0), 0},
  147         { PCMCIA_CARD(DAYNA, COMMUNICARD_E_2, 0), 0},
  148         { PCMCIA_CARD(DLINK, DE650, 0), 0},
  149         { PCMCIA_CARD(DLINK, DE660, 0), 0 },
  150         { PCMCIA_CARD(DLINK, DE660PLUS, 0), 0},
  151         { PCMCIA_CARD(DLINK, DFE670TXD, 0), NE2000DVF_DL10019},
  152         { PCMCIA_CARD(DYNALINK, L10C, 0), 0},
  153         { PCMCIA_CARD(EDIMAX, EP4000A, 0), 0},
  154         { PCMCIA_CARD(EPSON, EEN10B, 0), 0},
  155         { PCMCIA_CARD(EXP, THINLANCOMBO, 0), 0},
  156         { PCMCIA_CARD(IBM, INFOMOVER, 0), 0},
  157         { PCMCIA_CARD(IODATA3, PCLAT, 0), 0},
  158         { PCMCIA_CARD(KINGSTON, KNE2, 0), 0},
  159         { PCMCIA_CARD(LANTECH, FASTNETTX, 0),NE2000DVF_AX88190 },
  160         { PCMCIA_CARD(LINKSYS, COMBO_ECARD, 0), NE2000DVF_DL10019 },
  161         { PCMCIA_CARD(LINKSYS, ECARD_1, 0), 0},
  162         { PCMCIA_CARD(LINKSYS, ECARD_2, 0), 0},
  163         { PCMCIA_CARD(LINKSYS, ETHERFAST, 0), NE2000DVF_DL10019 },
  164         { PCMCIA_CARD(LINKSYS, TRUST_COMBO_ECARD, 0), 0},
  165         { PCMCIA_CARD(MACNICA, ME1_JEIDA, 0), 0},
  166         { PCMCIA_CARD(MELCO, LPC3_CLX,  0), NE2000DVF_AX88190},
  167         { PCMCIA_CARD(MELCO, LPC3_TX, 0), NE2000DVF_AX88190 },
  168         { PCMCIA_CARD(NDC, ND5100_E, 0), 0},
  169         { PCMCIA_CARD(NETGEAR, FA410TXC, 0), NE2000DVF_DL10019},
  170         { PCMCIA_CARD(NETGEAR, FA411, 0), NE2000DVF_AX88190},
  171         { PCMCIA_CARD(NEXTCOM, NEXTHAWK, 0), 0},
  172         { PCMCIA_CARD(OEM2, ETHERNET, 0), 0},
  173         { PCMCIA_CARD(PLANET, SMARTCOM2000, 0), 0 },
  174         { PCMCIA_CARD(PREMAX, PE200, 0), 0},
  175         { PCMCIA_CARD(RACORE, ETHERNET, 0), 0},
  176         { PCMCIA_CARD(RPTI, EP400, 0), 0},
  177         { PCMCIA_CARD(RPTI, EP401, 0), 0},
  178         { PCMCIA_CARD(SMC, EZCARD, 0), 0},
  179         { PCMCIA_CARD(SOCKET, EA_ETHER, 0), 0},
  180         { PCMCIA_CARD(SOCKET, LP_ETHER, 0), 0},
  181         { PCMCIA_CARD(SOCKET, LP_ETHER_CF, 0), 0},
  182         { PCMCIA_CARD(SOCKET, LP_ETH_10_100_CF, 0), NE2000DVF_DL10019},
  183         { PCMCIA_CARD(SVEC, COMBOCARD, 0), 0},
  184         { PCMCIA_CARD(SVEC, LANCARD, 0), 0},
  185         { PCMCIA_CARD(TAMARACK, ETHERNET, 0), 0},
  186         { PCMCIA_CARD(TDK, LAK_CD031, 0), 0},
  187         { PCMCIA_CARD(TELECOMDEVICE, TCD_HPC100, 0), NE2000DVF_AX88190 },
  188         { PCMCIA_CARD(XIRCOM, CFE_10, 0), 0},
  189         { PCMCIA_CARD(ZONET, ZEN, 0), 0},
  190         { { NULL } }
  191 };
  192 
  193 static int
  194 ed_pccard_match(device_t dev)
  195 {
  196         const struct ed_product *pp;
  197 
  198         if ((pp = (const struct ed_product *) pccard_product_lookup(dev, 
  199             (const struct pccard_product *) ed_pccard_products,
  200             sizeof(ed_pccard_products[0]), NULL)) != NULL) {
  201                 if (pp->prod.pp_name != NULL)
  202                         device_set_desc(dev, pp->prod.pp_name);
  203                 if (pp->flags & NE2000DVF_DL10019)
  204                         device_set_flags(dev, ED_FLAGS_LINKSYS);
  205                 else if (pp->flags & NE2000DVF_AX88190)
  206                         device_set_flags(dev, ED_FLAGS_AX88190);
  207                 return (0);
  208         }
  209         return (EIO);
  210 }
  211 
  212 /* 
  213  * Probe framework for pccards.  Replicates the standard framework,
  214  * minus the pccard driver registration and ignores the ether address
  215  * supplied (from the CIS), relying on the probe to find it instead.
  216  */
  217 static int
  218 ed_pccard_probe(device_t dev)
  219 {
  220         int     error;
  221         int     flags = device_get_flags(dev);
  222 
  223         if (ED_FLAGS_GETTYPE(flags) == ED_FLAGS_AX88190) {
  224                 error = ed_pccard_ax88190(dev);
  225                 goto end2;
  226         }
  227 
  228         error = ed_probe_Novell(dev, 0, flags);
  229         if (error == 0)
  230                 goto end;
  231         ed_release_resources(dev);
  232 
  233         error = ed_probe_WD80x3(dev, 0, flags);
  234         if (error == 0)
  235                 goto end;
  236         ed_release_resources(dev);
  237         goto end2;
  238 
  239 end:
  240         if (ED_FLAGS_GETTYPE(flags) & ED_FLAGS_LINKSYS)
  241                 ed_pccard_Linksys(dev);
  242 end2:
  243         if (error == 0)
  244                 error = ed_alloc_irq(dev, 0, 0);
  245 
  246         ed_release_resources(dev);
  247         return (error);
  248 }
  249 
  250 static int
  251 ed_pccard_attach(device_t dev)
  252 {
  253         struct ed_softc *sc = device_get_softc(dev);
  254         struct ifnet *ifp = &sc->arpcom.ac_if;
  255         int error;
  256         int i;
  257         uint8_t sum;
  258         const uint8_t *ether_addr;
  259         
  260         if (sc->port_used > 0)
  261                 ed_alloc_port(dev, sc->port_rid, sc->port_used);
  262         if (sc->mem_used)
  263                 ed_alloc_memory(dev, sc->mem_rid, sc->mem_used);
  264         ed_alloc_irq(dev, sc->irq_rid, 0);
  265                 
  266         if (sc->vendor != ED_VENDOR_LINKSYS) {
  267                 ether_addr = pccard_get_ether(dev);
  268                 for (i = 0, sum = 0; i < ETHER_ADDR_LEN; i++)
  269                         sum |= ether_addr[i];
  270                 if (sum)
  271                         bcopy(ether_addr, sc->arpcom.ac_enaddr, ETHER_ADDR_LEN);
  272         }
  273 
  274         error = ed_attach(dev);
  275 #ifndef ED_NO_MIIBUS
  276         if (error == 0 && sc->vendor == ED_VENDOR_LINKSYS) {
  277                 /* Probe for an MII bus, but ignore errors. */
  278                 ed_pccard_dlink_mii_reset(sc);
  279                 sc->mii_readbits = ed_pccard_dlink_mii_readbits;
  280                 sc->mii_writebits = ed_pccard_dlink_mii_writebits;
  281                 mii_phy_probe(dev, &sc->miibus, ed_ifmedia_upd,
  282                     ed_ifmedia_sts);
  283         }
  284 #endif
  285 
  286         ifq_set_cpuid(&ifp->if_snd, rman_get_cpuid(sc->irq_res));
  287 
  288         error = bus_setup_intr(dev, sc->irq_res, INTR_MPSAFE,
  289                                edintr, sc, &sc->irq_handle,
  290                                ifp->if_serializer);
  291         if (error) {
  292                 kprintf("setup intr failed %d \n", error);
  293                 ed_release_resources(dev);
  294                 return (error);
  295         }
  296 
  297         return (error);
  298 }
  299 
  300 static void
  301 ax88190_geteprom(struct ed_softc *sc)
  302 {
  303         int prom[16],i;
  304         u_char tmp;
  305         struct {
  306                 u_char offset, value;
  307         } pg_seq[] = {
  308                 {ED_P0_CR, ED_CR_RD2|ED_CR_STP},        /* Select Page0 */
  309                 {ED_P0_DCR, 0x01},
  310                 {ED_P0_RBCR0, 0x00},                    /* Clear the count regs. */
  311                 {ED_P0_RBCR1, 0x00},
  312                 {ED_P0_IMR, 0x00},                      /* Mask completion irq. */
  313                 {ED_P0_ISR, 0xff},
  314                 {ED_P0_RCR, ED_RCR_MON | ED_RCR_INTT},  /* Set To Monitor */
  315                 {ED_P0_TCR, ED_TCR_LB0},                /* loopback mode. */
  316                 {ED_P0_RBCR0, 32},
  317                 {ED_P0_RBCR1, 0x00},
  318                 {ED_P0_RSAR0, 0x00},
  319                 {ED_P0_RSAR1, 0x04},
  320                 {ED_P0_CR ,ED_CR_RD0 | ED_CR_STA},
  321         };
  322 
  323         /* Reset Card */
  324         tmp = ed_asic_inb(sc, ED_NOVELL_RESET);
  325         ed_asic_outb(sc, ED_NOVELL_RESET, tmp);
  326         DELAY(5000);
  327         ed_asic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STP);
  328         DELAY(5000);
  329 
  330         /* Card Settings */
  331         for (i = 0; i < NELEM(pg_seq); i++)
  332                 ed_nic_outb(sc, pg_seq[i].offset, pg_seq[i].value);
  333 
  334         /* Get Data */
  335         for (i = 0; i < 16; i++)
  336                 prom[i] = ed_asic_inb(sc, 0);
  337         sc->arpcom.ac_enaddr[0] = prom[0] & 0xff;
  338         sc->arpcom.ac_enaddr[1] = prom[0] >> 8;
  339         sc->arpcom.ac_enaddr[2] = prom[1] & 0xff;
  340         sc->arpcom.ac_enaddr[3] = prom[1] >> 8;
  341         sc->arpcom.ac_enaddr[4] = prom[2] & 0xff;
  342         sc->arpcom.ac_enaddr[5] = prom[2] >> 8;
  343 }
  344 
  345 static int
  346 ed_pccard_memwrite(device_t dev, off_t offset, u_char byte)
  347 {
  348         int cis_rid;
  349         struct resource *cis;
  350         
  351         cis_rid = 0;
  352         cis = bus_alloc_resource(dev, SYS_RES_MEMORY, &cis_rid, 0, ~0,
  353                                  4 << 10, RF_ACTIVE | RF_SHAREABLE);
  354         if (cis == NULL)
  355                 return (ENXIO);
  356         CARD_SET_RES_FLAGS(device_get_parent(dev), dev, SYS_RES_MEMORY,
  357                            cis_rid, PCCARD_A_MEM_ATTR);
  358 
  359         bus_space_write_1(rman_get_bustag(cis), rman_get_bushandle(cis),
  360                           offset, byte);
  361 
  362         bus_deactivate_resource(dev, SYS_RES_MEMORY, cis_rid, cis);
  363         bus_release_resource(dev, SYS_RES_MEMORY, cis_rid, cis);
  364 
  365         return (0);
  366 }
  367 
  368 /*
  369  * Probe the Ethernet MAC addrees for PCMCIA Linksys EtherFast 10/100 
  370  * and compatible cards (DL10019C Ethernet controller).
  371  *
  372  * Note: The PAO patches try to use more memory for the card, but that
  373  * seems to fail for my card.  A future optimization would add this back
  374  * conditionally.
  375  */
  376 static int
  377 ed_pccard_Linksys(device_t dev)
  378 {
  379         struct ed_softc *sc = device_get_softc(dev);
  380         u_char sum;
  381         int i;
  382 
  383         /*
  384          * Linksys registers(offset from ASIC base)
  385          *
  386          * 0x04-0x09 : Physical Address Register 0-5 (PAR0-PAR5)
  387          * 0x0A      : Card ID Register (CIR)
  388          * 0x0B      : Check Sum Register (SR)
  389          */
  390         for (sum = 0, i = 0x04; i < 0x0c; i++)
  391                 sum += ed_asic_inb(sc, i);
  392         if (sum != 0xff)
  393                 return (0);             /* invalid DL10019C */
  394         for (i = 0; i < ETHER_ADDR_LEN; i++) {
  395                 sc->arpcom.ac_enaddr[i] = ed_asic_inb(sc, 0x04 + i);
  396         }
  397 
  398         ed_nic_outb(sc, ED_P0_DCR, ED_DCR_WTS | ED_DCR_FT1 | ED_DCR_LS);
  399         sc->isa16bit = 1;
  400         sc->vendor = ED_VENDOR_LINKSYS;
  401         sc->type = ED_TYPE_NE2000;
  402         sc->type_str = "Linksys";
  403 
  404         return (1);
  405 }
  406 
  407 /*
  408  * Special setup for AX88190
  409  */
  410 static int
  411 ed_pccard_ax88190(device_t dev)
  412 {
  413         int     error;
  414         int     flags = device_get_flags(dev);
  415         int     iobase;
  416         struct  ed_softc *sc = device_get_softc(dev);
  417 
  418         /* Allocate the port resource during setup. */
  419         error = ed_alloc_port(dev, 0, ED_NOVELL_IO_PORTS);
  420         if (error)
  421                 return (error);
  422 
  423         sc->asic_offset = ED_NOVELL_ASIC_OFFSET;
  424         sc->nic_offset  = ED_NOVELL_NIC_OFFSET;
  425         sc->chip_type = ED_CHIP_TYPE_AX88190;
  426 
  427         /*
  428          * Set Attribute Memory IOBASE Register.  Is this a deficiency in
  429          * the PC Card layer, or an ax88190 specific issue? xxx
  430          */
  431         iobase = rman_get_start(sc->port_res);
  432         ed_pccard_memwrite(dev, ED_AX88190_IOBASE0, iobase & 0xff);
  433         ed_pccard_memwrite(dev, ED_AX88190_IOBASE1, (iobase >> 8) & 0xff);
  434         ax88190_geteprom(sc);
  435         ed_release_resources(dev);
  436         error = ed_probe_Novell(dev, 0, flags);
  437         if (error == 0) {
  438                 sc->vendor = ED_VENDOR_PCCARD;
  439                 sc->type = ED_TYPE_NE2000;
  440                 sc->type_str = "AX88190";
  441         }
  442         return (error);
  443 }
  444 
  445 #ifndef ED_NO_MIIBUS
  446 /* MII bit-twiddling routines for cards using Dlink chipset */
  447 #define DLINK_MIISET(sc, x) ed_asic_outb(sc, ED_DLINK_MIIBUS, \
  448     ed_asic_inb(sc, ED_DLINK_MIIBUS) | (x))
  449 #define DLINK_MIICLR(sc, x) ed_asic_outb(sc, ED_DLINK_MIIBUS, \
  450     ed_asic_inb(sc, ED_DLINK_MIIBUS) & ~(x))
  451 
  452 static void
  453 ed_pccard_dlink_mii_reset(struct ed_softc *sc)
  454 {
  455         ed_asic_outb(sc, ED_DLINK_MIIBUS, 0);
  456         DELAY(10);
  457         DLINK_MIISET(sc, ED_DLINK_MII_RESET2);
  458         DELAY(10);
  459         DLINK_MIISET(sc, ED_DLINK_MII_RESET1);
  460         DELAY(10);
  461         DLINK_MIICLR(sc, ED_DLINK_MII_RESET1);
  462         DELAY(10);
  463         DLINK_MIICLR(sc, ED_DLINK_MII_RESET2);
  464         DELAY(10);
  465 }
  466 
  467 static void
  468 ed_pccard_dlink_mii_writebits(struct ed_softc *sc, u_int val, int nbits)
  469 {
  470         int i;
  471 
  472         DLINK_MIISET(sc, ED_DLINK_MII_DIROUT);
  473 
  474         for (i = nbits - 1; i >= 0; i--) {
  475                 if ((val >> i) & 1)
  476                         DLINK_MIISET(sc, ED_DLINK_MII_DATAOUT);
  477                 else
  478                         DLINK_MIICLR(sc, ED_DLINK_MII_DATAOUT);
  479                 DELAY(10);
  480                 DLINK_MIISET(sc, ED_DLINK_MII_CLK);
  481                 DELAY(10);
  482                 DLINK_MIICLR(sc, ED_DLINK_MII_CLK);
  483                 DELAY(10);
  484         }
  485 }
  486 
  487 static u_int
  488 ed_pccard_dlink_mii_readbits(struct ed_softc *sc, int nbits)
  489 {
  490         int i;
  491         u_int val = 0;
  492 
  493         DLINK_MIICLR(sc, ED_DLINK_MII_DIROUT);
  494 
  495         for (i = nbits - 1; i >= 0; i--) {
  496                 DLINK_MIISET(sc, ED_DLINK_MII_CLK);
  497                 DELAY(10);
  498                 val <<= 1;
  499                 if (ed_asic_inb(sc, ED_DLINK_MIIBUS) & ED_DLINK_MII_DATATIN)
  500                         val++;
  501                 DLINK_MIICLR(sc, ED_DLINK_MII_CLK);
  502                 DELAY(10);
  503         }
  504 
  505         return val;
  506 }
  507 #endif
  508 
  509 static device_method_t ed_pccard_methods[] = {
  510         /* Device interface */
  511         DEVMETHOD(device_probe,         pccard_compat_probe),
  512         DEVMETHOD(device_attach,        pccard_compat_attach),
  513         DEVMETHOD(device_detach,        ed_pccard_detach),
  514 
  515 #ifndef ED_NO_MIIBUS
  516         /* Bus interface */
  517         DEVMETHOD(bus_child_detached,   ed_child_detached),
  518 
  519         /* MII interface */
  520         DEVMETHOD(miibus_readreg,       ed_miibus_readreg),
  521         DEVMETHOD(miibus_writereg,      ed_miibus_writereg),
  522 #endif
  523 
  524         /* Card interface */
  525         DEVMETHOD(card_compat_match,    ed_pccard_match),
  526         DEVMETHOD(card_compat_probe,    ed_pccard_probe),
  527         DEVMETHOD(card_compat_attach,   ed_pccard_attach),
  528         DEVMETHOD_END
  529 };
  530 
  531 static driver_t ed_pccard_driver = {
  532         "ed",
  533         ed_pccard_methods,
  534         sizeof(struct ed_softc)
  535 };
  536 
  537 DRIVER_MODULE(if_ed, pccard, ed_pccard_driver, ed_devclass, NULL, NULL);
  538 #ifndef ED_NO_MIIBUS
  539 MODULE_DEPEND(if_ed, miibus, 1, 1, 1);
  540 DRIVER_MODULE(miibus, ed, miibus_driver, miibus_devclass, NULL, NULL);
  541 #endif

Cache object: 3e3c42b5a164558988d63175ec8cbea3


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