root/dev/cardbus/if_dc_cardbus.c

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

DEFINITIONS

This source file includes following definitions.
  1. dc_cardbus_match
  2. dc_cardbus_attach
  3. dc_detach
  4. dc_cardbus_detach
  5. dc_cardbus_setup

    1 /*      $OpenBSD: if_dc_cardbus.c,v 1.24 2007/05/08 00:04:47 deraadt Exp $      */
    2 
    3 #include <sys/param.h>
    4 #include <sys/systm.h>
    5 #include <sys/mbuf.h>
    6 #include <sys/socket.h>
    7 #include <sys/ioctl.h>
    8 #include <sys/errno.h>
    9 #include <sys/malloc.h>
   10 #include <sys/kernel.h>
   11 #include <sys/proc.h>
   12 #include <sys/device.h>
   13 
   14 #include <net/if.h>
   15 #include <net/if_dl.h>
   16 #include <net/if_types.h>
   17 #include <net/if_media.h>
   18 
   19 #include <netinet/in.h>
   20 #include <netinet/if_ether.h>
   21 
   22 #include <dev/mii/mii.h>
   23 #include <dev/mii/miivar.h>
   24 
   25 #include <machine/bus.h>
   26 
   27 #include <dev/pci/pcivar.h>
   28 #include <dev/pci/pcireg.h>
   29 #include <dev/pci/pcidevs.h>
   30 
   31 #include <dev/cardbus/cardbusvar.h>
   32 
   33 #include <dev/ic/dcreg.h>
   34 
   35 /* PCI configuration regs */
   36 #define PCI_CBIO        0x10
   37 #define PCI_CBMEM       0x14
   38 #define PCI_CFDA        0x40
   39 
   40 #define DC_CFDA_SUSPEND 0x80000000
   41 #define DC_CFDA_STANDBY 0x40000000
   42 
   43 struct dc_cardbus_softc {
   44         struct dc_softc         sc_dc;
   45         int                     sc_intrline;
   46 
   47         cardbus_devfunc_t       sc_ct;
   48         cardbustag_t            sc_tag;
   49         bus_size_t              sc_mapsize;
   50         int                     sc_actype;
   51 };
   52 
   53 int dc_cardbus_match(struct device *, void *, void *);
   54 void dc_cardbus_attach(struct device *, struct device *,void *);
   55 int dc_cardbus_detach(struct device *, int);
   56 
   57 void dc_cardbus_setup(struct dc_cardbus_softc *csc);
   58 
   59 struct cfattach dc_cardbus_ca = {
   60         sizeof(struct dc_cardbus_softc), dc_cardbus_match, dc_cardbus_attach,
   61             dc_cardbus_detach
   62 };
   63 
   64 const struct cardbus_matchid dc_cardbus_devices[] = {
   65         { PCI_VENDOR_DEC, PCI_PRODUCT_DEC_21142 },
   66         { PCI_VENDOR_XIRCOM, PCI_PRODUCT_XIRCOM_X3201_3_21143 },
   67         { PCI_VENDOR_ADMTEK, PCI_PRODUCT_ADMTEK_AN985 },
   68         { PCI_VENDOR_ACCTON, PCI_PRODUCT_ACCTON_EN2242 },
   69         { PCI_VENDOR_ABOCOM, PCI_PRODUCT_ABOCOM_FE2500 },
   70         { PCI_VENDOR_ABOCOM, PCI_PRODUCT_ABOCOM_FE2500MX },
   71         { PCI_VENDOR_ABOCOM, PCI_PRODUCT_ABOCOM_PCM200 },
   72         { PCI_VENDOR_DLINK, PCI_PRODUCT_DLINK_DRP32TXD },
   73         { PCI_VENDOR_LINKSYS, PCI_PRODUCT_LINKSYS_PCMPC200 },
   74         { PCI_VENDOR_LINKSYS, PCI_PRODUCT_LINKSYS_PCM200 },
   75         { PCI_VENDOR_HAWKING, PCI_PRODUCT_HAWKING_PN672TX },
   76         { PCI_VENDOR_MICROSOFT, PCI_PRODUCT_MICROSOFT_MN120 },
   77 };
   78 
   79 int
   80 dc_cardbus_match(parent, match, aux)
   81         struct device *parent;
   82         void *match, *aux;
   83 {
   84         return (cardbus_matchbyid((struct cardbus_attach_args *)aux,
   85             dc_cardbus_devices,
   86             sizeof(dc_cardbus_devices)/sizeof(dc_cardbus_devices[0])));
   87 }
   88 
   89 void
   90 dc_cardbus_attach(parent, self, aux)
   91         struct device *parent, *self;
   92         void *aux;
   93 {
   94         struct dc_cardbus_softc *csc = (struct dc_cardbus_softc *)self;
   95         struct dc_softc *sc = &csc->sc_dc;
   96         struct cardbus_attach_args *ca = aux;
   97         struct cardbus_devfunc *ct = ca->ca_ct;
   98         cardbus_chipset_tag_t cc = ct->ct_cc;
   99         cardbus_function_tag_t cf = ct->ct_cf;
  100         cardbusreg_t reg;
  101         bus_addr_t addr;
  102 
  103         sc->sc_dmat = ca->ca_dmat;
  104         csc->sc_ct = ct;
  105         csc->sc_tag = ca->ca_tag;
  106 
  107         Cardbus_function_enable(ct);
  108 
  109         if (Cardbus_mapreg_map(ct, PCI_CBIO,
  110             PCI_MAPREG_TYPE_IO, 0, &sc->dc_btag, &sc->dc_bhandle, &addr,
  111             &csc->sc_mapsize) == 0) {
  112 
  113                 csc->sc_actype = CARDBUS_IO_ENABLE;
  114         } else if (Cardbus_mapreg_map(ct, PCI_CBMEM,
  115             PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0,
  116             &sc->dc_btag, &sc->dc_bhandle, &addr, &csc->sc_mapsize) == 0) {
  117                 csc->sc_actype = CARDBUS_MEM_ENABLE;
  118         } else {
  119                 printf(": can\'t map device registers\n");
  120                 return;
  121         }
  122 
  123         csc->sc_intrline = ca->ca_intrline;
  124 
  125         sc->dc_cachesize = cardbus_conf_read(cc, cf, ca->ca_tag, DC_PCI_CFLT)
  126             & 0xFF;
  127 
  128         dc_cardbus_setup(csc);
  129 
  130         /* Get the eeprom width, but XIRCOM has no eeprom */
  131         if (!(PCI_VENDOR(ca->ca_id) == PCI_VENDOR_XIRCOM &&
  132               PCI_PRODUCT(ca->ca_id) == PCI_PRODUCT_XIRCOM_X3201_3_21143))
  133                 dc_eeprom_width(sc);
  134 
  135         switch (PCI_VENDOR(ca->ca_id)) {
  136         case PCI_VENDOR_DEC:
  137                 if (PCI_PRODUCT(ca->ca_id) == PCI_PRODUCT_DEC_21142) {
  138                         sc->dc_type = DC_TYPE_21143;
  139                         sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR;
  140                         sc->dc_flags |= DC_REDUCED_MII_POLL;
  141                         dc_read_srom(sc, sc->dc_romwidth);
  142                         dc_parse_21143_srom(sc);
  143                 }
  144                 break;
  145         case PCI_VENDOR_XIRCOM:
  146                 if (PCI_PRODUCT(ca->ca_id) ==
  147                     PCI_PRODUCT_XIRCOM_X3201_3_21143) {
  148                         sc->dc_type = DC_TYPE_XIRCOM;
  149                         sc->dc_flags |= DC_TX_INTR_ALWAYS|DC_TX_COALESCE |
  150                                         DC_TX_ALIGN;
  151                         sc->dc_pmode = DC_PMODE_MII;
  152 
  153                         bcopy(ca->ca_cis.funce.network.netid,
  154                             &sc->sc_arpcom.ac_enaddr,
  155                             sizeof sc->sc_arpcom.ac_enaddr);
  156                 }
  157                 break;
  158         case PCI_VENDOR_ADMTEK:
  159         case PCI_VENDOR_ACCTON:
  160         case PCI_VENDOR_ABOCOM:
  161         case PCI_VENDOR_DLINK:
  162         case PCI_VENDOR_LINKSYS:
  163         case PCI_VENDOR_HAWKING:
  164         case PCI_VENDOR_MICROSOFT:
  165                 if (PCI_PRODUCT(ca->ca_id) == PCI_PRODUCT_ADMTEK_AN985 ||
  166                     PCI_PRODUCT(ca->ca_id) == PCI_PRODUCT_ACCTON_EN2242 ||
  167                     PCI_PRODUCT(ca->ca_id) == PCI_PRODUCT_ABOCOM_FE2500 ||
  168                     PCI_PRODUCT(ca->ca_id) == PCI_PRODUCT_ABOCOM_FE2500MX ||
  169                     PCI_PRODUCT(ca->ca_id) == PCI_PRODUCT_ABOCOM_PCM200 ||
  170                     PCI_PRODUCT(ca->ca_id) == PCI_PRODUCT_DLINK_DRP32TXD ||
  171                     PCI_PRODUCT(ca->ca_id) == PCI_PRODUCT_LINKSYS_PCMPC200 ||
  172                     PCI_PRODUCT(ca->ca_id) == PCI_PRODUCT_LINKSYS_PCM200 ||
  173                     PCI_PRODUCT(ca->ca_id) == PCI_PRODUCT_HAWKING_PN672TX ||
  174                     PCI_PRODUCT(ca->ca_id) == PCI_PRODUCT_MICROSOFT_MN120) {
  175                         sc->dc_type = DC_TYPE_AN983;
  176                         sc->dc_flags |= DC_TX_USE_TX_INTR|DC_TX_ADMTEK_WAR |
  177                                         DC_64BIT_HASH;
  178                         sc->dc_pmode = DC_PMODE_MII;
  179                         /* Don't read SROM for - auto-loaded on reset */
  180                 }
  181                 break;
  182         default:
  183                 printf(": unknown device\n");
  184                 return;
  185         }
  186 
  187         /*
  188          * set latency timer, do we really need this?
  189          */
  190         reg = cardbus_conf_read(cc, cf, ca->ca_tag, PCI_BHLC_REG);
  191         if (PCI_LATTIMER(reg) < 0x20) {
  192                 reg &= ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT);
  193                 reg |= (0x20 << PCI_LATTIMER_SHIFT);
  194                 cardbus_conf_write(cc, cf, ca->ca_tag, PCI_BHLC_REG, reg);
  195         }
  196 
  197         sc->sc_ih = cardbus_intr_establish(cc, cf, ca->ca_intrline, IPL_NET,
  198             dc_intr, csc, sc->sc_dev.dv_xname);
  199         if (sc->sc_ih == NULL) {
  200                 printf(": can't establish interrupt at %d\n",
  201                     ca->ca_intrline);
  202                 return;
  203         } else
  204                 printf(" irq %d", ca->ca_intrline);
  205 
  206         dc_reset(sc);
  207 
  208         sc->dc_revision = PCI_REVISION(ca->ca_class);
  209         dc_attach(sc);
  210 }
  211 
  212 int
  213 dc_detach(sc)
  214         struct dc_softc *sc;
  215 {
  216         struct ifnet *ifp = &sc->sc_arpcom.ac_if;
  217 
  218         if (LIST_FIRST(&sc->sc_mii.mii_phys) != NULL)
  219                 mii_detach(&sc->sc_mii, MII_PHY_ANY, MII_OFFSET_ANY);
  220 
  221         if (sc->dc_srom)
  222                 free(sc->dc_srom, M_DEVBUF);
  223 
  224         timeout_del(&sc->dc_tick_tmo);
  225 
  226         ether_ifdetach(ifp);
  227         if_detach(ifp);
  228 
  229         if (sc->sc_dhook != NULL)
  230                 shutdownhook_disestablish(sc->sc_dhook);
  231         if (sc->sc_pwrhook != NULL)
  232                 powerhook_disestablish(sc->sc_pwrhook);
  233 
  234         return (0);
  235 }
  236 
  237 int
  238 dc_cardbus_detach(self, flags)
  239         struct device *self;
  240         int flags;
  241 {
  242         struct dc_cardbus_softc *csc = (struct dc_cardbus_softc *)self;
  243         struct dc_softc *sc = &csc->sc_dc;
  244         struct cardbus_devfunc *ct = csc->sc_ct;
  245         int rv = 0;
  246 
  247         rv = dc_detach(sc);
  248         if (rv)
  249                 return (rv);
  250 
  251         cardbus_intr_disestablish(ct->ct_cc, ct->ct_cf, sc->sc_ih);
  252 
  253         /* unmap cardbus resources */
  254         Cardbus_mapreg_unmap(ct,
  255             csc->sc_actype == CARDBUS_IO_ENABLE ? PCI_CBIO : PCI_CBMEM,
  256             sc->dc_btag, sc->dc_bhandle, csc->sc_mapsize);
  257 
  258         return (rv);
  259 }
  260 
  261 void
  262 dc_cardbus_setup(csc)
  263         struct dc_cardbus_softc *csc;
  264 {
  265         cardbus_devfunc_t ct = csc->sc_ct;
  266         cardbus_chipset_tag_t cc = ct->ct_cc;
  267         cardbus_function_tag_t cf = ct->ct_cf;
  268         cardbusreg_t reg;
  269         int r;
  270 
  271         /* wakeup the card if needed */
  272         reg = cardbus_conf_read(cc, cf, csc->sc_tag, PCI_CFDA);
  273         if (reg | (DC_CFDA_SUSPEND|DC_CFDA_STANDBY)) {
  274                 cardbus_conf_write(cc, cf, csc->sc_tag, PCI_CFDA,
  275                     reg & ~(DC_CFDA_SUSPEND|DC_CFDA_STANDBY));
  276         }
  277 
  278         if (cardbus_get_capability(cc, cf, csc->sc_tag, PCI_CAP_PWRMGMT, &r,
  279             0)) {
  280                 r = cardbus_conf_read(cc, cf, csc->sc_tag, r + 4) & 3;
  281                 if (r) {
  282                         printf("%s: awakening from state D%d\n",
  283                             csc->sc_dc.sc_dev.dv_xname, r);
  284                         cardbus_conf_write(cc, cf, csc->sc_tag, r + 4, 0);
  285                 }
  286         }
  287 
  288         (*ct->ct_cf->cardbus_ctrl)(cc, csc->sc_actype);
  289         (*ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);
  290 
  291         reg = cardbus_conf_read(cc, cf, csc->sc_tag, PCI_COMMAND_STATUS_REG);
  292         reg |= PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE |
  293             PCI_COMMAND_MASTER_ENABLE;
  294         cardbus_conf_write(cc, cf, csc->sc_tag, PCI_COMMAND_STATUS_REG, reg);
  295         reg = cardbus_conf_read(cc, cf, csc->sc_tag, PCI_COMMAND_STATUS_REG);
  296 }

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