root/dev/pci/if_re_pci.c

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

DEFINITIONS

This source file includes following definitions.
  1. re_pci_probe
  2. re_pci_attach

    1 /*      $OpenBSD: if_re_pci.c,v 1.19 2006/11/28 20:04:02 brad Exp $     */
    2 
    3 /*
    4  * Copyright (c) 2005 Peter Valchev <pvalchev@openbsd.org>
    5  *
    6  * Permission to use, copy, modify, and distribute this software for any
    7  * purpose with or without fee is hereby granted, provided that the above
    8  * copyright notice and this permission notice appear in all copies.
    9  *
   10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   17  */
   18 
   19 /*
   20  * PCI front-end for the Realtek 8169
   21  */
   22 
   23 #include <sys/param.h>
   24 #include <sys/endian.h>
   25 #include <sys/systm.h>
   26 #include <sys/sockio.h>
   27 #include <sys/mbuf.h>
   28 #include <sys/malloc.h>
   29 #include <sys/kernel.h>
   30 #include <sys/device.h>
   31 #include <sys/timeout.h>
   32 #include <sys/socket.h>
   33 
   34 #include <net/if.h>
   35 #include <net/if_dl.h>
   36 #include <net/if_media.h>
   37 
   38 #ifdef INET
   39 #include <netinet/in.h>
   40 #include <netinet/in_systm.h>
   41 #include <netinet/in_var.h>
   42 #include <netinet/ip.h>
   43 #include <netinet/if_ether.h>
   44 #endif
   45 
   46 #include <dev/mii/mii.h>
   47 #include <dev/mii/miivar.h>
   48 
   49 #include <dev/pci/pcireg.h>
   50 #include <dev/pci/pcivar.h>
   51 #include <dev/pci/pcidevs.h>
   52 
   53 #include <dev/ic/rtl81x9reg.h>
   54 #include <dev/ic/revar.h>
   55 
   56 struct re_pci_softc {
   57         /* General */
   58         struct rl_softc sc_rl;
   59 
   60         /* PCI-specific data */
   61         void *sc_ih;
   62         pci_chipset_tag_t sc_pc;
   63         pcitag_t sc_pcitag;
   64 };
   65 
   66 const struct pci_matchid re_pci_devices[] = {
   67         { PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8101E },
   68         { PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8168 },
   69         { PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8169 },
   70         { PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8169SC },
   71         { PCI_VENDOR_COREGA, PCI_PRODUCT_COREGA_CGLAPCIGT },
   72         { PCI_VENDOR_DLINK, PCI_PRODUCT_DLINK_DGE528T },
   73         { PCI_VENDOR_USR2, PCI_PRODUCT_USR2_USR997902 },
   74         { PCI_VENDOR_TTTECH, PCI_PRODUCT_TTTECH_MC322 }
   75 };
   76 
   77 #define RE_LINKSYS_EG1032_SUBID 0x00241737
   78 
   79 int     re_pci_probe(struct device *, void *, void *);
   80 void    re_pci_attach(struct device *, struct device *, void *);
   81 
   82 /*
   83  * PCI autoconfig definitions
   84  */
   85 struct cfattach re_pci_ca = {
   86         sizeof(struct re_pci_softc),
   87         re_pci_probe,
   88         re_pci_attach
   89 };
   90 
   91 /*
   92  * Probe for a Realtek 8169/8110 chip. Check the PCI vendor and device
   93  * IDs against our list and return a device name if we find a match.
   94  */
   95 int
   96 re_pci_probe(struct device *parent, void *match, void *aux)
   97 {
   98         struct pci_attach_args *pa = aux;
   99         pci_chipset_tag_t pc = pa->pa_pc;
  100         pcireg_t subid;
  101 
  102         subid = pci_conf_read(pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
  103 
  104         /* C+ mode 8139's */
  105         if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_REALTEK &&
  106             PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_REALTEK_RT8139 &&
  107             PCI_REVISION(pa->pa_class) == 0x20)
  108                 return (1);
  109 
  110         if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_LINKSYS &&
  111             PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_LINKSYS_EG1032 &&
  112             subid == RE_LINKSYS_EG1032_SUBID)
  113                 return (1);
  114 
  115         return (pci_matchbyid((struct pci_attach_args *)aux, re_pci_devices,
  116             sizeof(re_pci_devices)/sizeof(re_pci_devices[0])));
  117 }
  118 
  119 /*
  120  * PCI-specific attach routine
  121  */
  122 void
  123 re_pci_attach(struct device *parent, struct device *self, void *aux)
  124 {
  125         struct re_pci_softc     *psc = (struct re_pci_softc *)self;
  126         struct rl_softc         *sc = &psc->sc_rl;
  127         struct pci_attach_args  *pa = aux;
  128         pci_chipset_tag_t       pc = pa->pa_pc;
  129         pci_intr_handle_t       ih;
  130         const char              *intrstr = NULL;
  131         bus_size_t              iosize;
  132         pcireg_t                command;
  133 
  134         /*
  135          * Handle power management nonsense.
  136          */
  137 
  138         command = pci_conf_read(pc, pa->pa_tag, RL_PCI_CAPID) & 0x000000FF;
  139 
  140         if (command == 0x01) {
  141                 u_int32_t               iobase, membase, irq;
  142 
  143                 /* Save important PCI config data. */
  144                 iobase = pci_conf_read(pc, pa->pa_tag,  RL_PCI_LOIO);
  145                 membase = pci_conf_read(pc, pa->pa_tag, RL_PCI_LOMEM);
  146                 irq = pci_conf_read(pc, pa->pa_tag, RL_PCI_INTLINE);
  147 
  148 #if 0
  149                 /* Reset the power state. */
  150                 printf(": chip is in D%d power mode "
  151                     "-- setting to D0", command & RL_PSTATE_MASK);
  152 #endif
  153                 command &= 0xFFFFFFFC;
  154 
  155                 /* Restore PCI config data. */
  156                 pci_conf_write(pc, pa->pa_tag, RL_PCI_LOIO, iobase);
  157                 pci_conf_write(pc, pa->pa_tag, RL_PCI_LOMEM, membase);
  158                 pci_conf_write(pc, pa->pa_tag, RL_PCI_INTLINE, irq);
  159         }
  160 
  161         /*
  162          * Map control/status registers.
  163          */
  164         if (pci_mapreg_map(pa, RL_PCI_LOMEM, PCI_MAPREG_TYPE_MEM, 0,
  165             &sc->rl_btag, &sc->rl_bhandle, NULL, &iosize, 0)) {
  166                 if (pci_mapreg_map(pa, RL_PCI_LOIO, PCI_MAPREG_TYPE_IO, 0,
  167                     &sc->rl_btag, &sc->rl_bhandle, NULL, &iosize, 0)) {
  168                         printf(": can't map mem or i/o space\n");
  169                         return;
  170                 }
  171         }
  172 
  173         /* Allocate interrupt */
  174         if (pci_intr_map(pa, &ih)) {
  175                 printf(": couldn't map interrupt\n");
  176                 return;
  177         }
  178         intrstr = pci_intr_string(pc, ih);
  179         psc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, re_intr, sc,
  180             sc->sc_dev.dv_xname);
  181         if (psc->sc_ih == NULL) {
  182                 printf(": couldn't establish interrupt");
  183                 if (intrstr != NULL)
  184                         printf(" at %s", intrstr);
  185                 return;
  186         }
  187 
  188         sc->sc_dmat = pa->pa_dmat;
  189         sc->sc_flags |= RL_ENABLED;
  190 
  191         if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_REALTEK) {
  192                 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_REALTEK_RT8139)
  193                         sc->rl_type = RL_8139CPLUS;
  194                 else
  195                         sc->rl_type = RL_8169;
  196         } else if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_TTTECH &&
  197                    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_TTTECH_MC322)
  198                 sc->rl_type = RL_8139CPLUS;
  199         else
  200                 sc->rl_type = RL_8169;
  201 
  202         /* Call bus-independent attach routine */
  203         re_attach(sc, intrstr);
  204 }

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