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/pci/if_ne_pci.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 /*      $NetBSD: if_ne_pci.c,v 1.25 2004/02/13 10:05:50 wiz Exp $       */
    2 
    3 /*-
    4  * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
    9  * NASA Ames Research Center.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  * 3. All advertising materials mentioning features or use of this software
   20  *    must display the following acknowledgement:
   21  *      This product includes software developed by the NetBSD
   22  *      Foundation, Inc. and its contributors.
   23  * 4. Neither the name of The NetBSD Foundation nor the names of its
   24  *    contributors may be used to endorse or promote products derived
   25  *    from this software without specific prior written permission.
   26  *
   27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   37  * POSSIBILITY OF SUCH DAMAGE.
   38  */
   39 
   40 #include <sys/cdefs.h>
   41 __KERNEL_RCSID(0, "$NetBSD: if_ne_pci.c,v 1.25 2004/02/13 10:05:50 wiz Exp $");
   42 
   43 #include "opt_ipkdb.h"
   44 
   45 #include <sys/param.h>
   46 #include <sys/systm.h>
   47 #include <sys/mbuf.h>
   48 #include <sys/syslog.h>
   49 #include <sys/socket.h>
   50 #include <sys/device.h>
   51 
   52 #include <net/if.h>
   53 #include <net/if_ether.h>
   54 #include <net/if_media.h>
   55 
   56 #include <machine/bus.h>
   57 #include <machine/intr.h>
   58 
   59 #ifdef IPKDB_NE_PCI
   60 #include <ipkdb/ipkdb.h>
   61 #endif
   62 
   63 #include <dev/pci/pcireg.h>
   64 #include <dev/pci/pcivar.h>
   65 #include <dev/pci/pcidevs.h>
   66 
   67 #include <dev/ic/dp8390reg.h>
   68 #include <dev/ic/dp8390var.h>
   69 
   70 #include <dev/ic/ne2000reg.h>
   71 #include <dev/ic/ne2000var.h>
   72 
   73 #include <dev/ic/rtl80x9reg.h>
   74 #include <dev/ic/rtl80x9var.h>
   75 
   76 struct ne_pci_softc {
   77         struct ne2000_softc sc_ne2000;          /* real "ne2000" softc */
   78 
   79         /* PCI-specific goo */
   80         void *sc_ih;                            /* interrupt handle */
   81 };
   82 
   83 int ne_pci_match __P((struct device *, struct cfdata *, void *));
   84 void ne_pci_attach __P((struct device *, struct device *, void *));
   85 
   86 CFATTACH_DECL(ne_pci, sizeof(struct ne_pci_softc),
   87     ne_pci_match, ne_pci_attach, NULL, NULL);
   88 
   89 #ifdef IPKDB_NE_PCI
   90 static struct ne_pci_softc ipkdb_softc;
   91 static pci_chipset_tag_t ipkdb_pc;
   92 static pcitag_t ipkdb_tag;
   93 static struct ipkdb_if *ne_kip;
   94 
   95 int ne_pci_ipkdb_attach __P((struct ipkdb_if *, bus_space_tag_t,       /* XXX */
   96                         pci_chipset_tag_t, int, int));
   97 
   98 static int ne_pci_isipkdb __P((pci_chipset_tag_t, pcitag_t));
   99 #endif
  100 
  101 const struct ne_pci_product {
  102         pci_vendor_id_t npp_vendor;
  103         pci_product_id_t npp_product;
  104         int (*npp_mediachange) __P((struct dp8390_softc *));
  105         void (*npp_mediastatus) __P((struct dp8390_softc *,
  106             struct ifmediareq *));
  107         void (*npp_init_card) __P((struct dp8390_softc *));
  108         void (*npp_media_init) __P((struct dp8390_softc *));
  109         const char *npp_name;
  110 } ne_pci_products[] = {
  111         { PCI_VENDOR_REALTEK,           PCI_PRODUCT_REALTEK_RT8029,
  112           rtl80x9_mediachange,          rtl80x9_mediastatus,
  113           rtl80x9_init_card,            rtl80x9_media_init,
  114           "Realtek 8029" },
  115 
  116         { PCI_VENDOR_WINBOND,           PCI_PRODUCT_WINBOND_W89C940F,
  117           NULL,                         NULL,
  118           NULL,                         NULL,
  119           "Winbond 89C940F" },
  120 
  121         { PCI_VENDOR_WINBOND,           PCI_PRODUCT_WINBOND_W89C940F_1,
  122           NULL,                         NULL,
  123           NULL,                         NULL,
  124           "Winbond 89C940F" },
  125 
  126         { PCI_VENDOR_VIATECH,           PCI_PRODUCT_VIATECH_VT86C926,
  127           NULL,                         NULL,
  128           NULL,                         NULL,
  129           "VIA Technologies VT86C926" },
  130 
  131         { PCI_VENDOR_SURECOM,           PCI_PRODUCT_SURECOM_NE34,
  132           NULL,                         NULL,
  133           NULL,                         NULL,
  134           "Surecom NE-34" },
  135 
  136         { PCI_VENDOR_NETVIN,            PCI_PRODUCT_NETVIN_5000,
  137           NULL,                         NULL,
  138           NULL,                         NULL,
  139           "NetVin 5000" },
  140 
  141         /* XXX The following entries need sanity checking in pcidevs */
  142         { PCI_VENDOR_COMPEX,            PCI_PRODUCT_COMPEX_NE2KETHER,
  143           NULL,                         NULL,
  144           NULL,                         NULL,
  145           "Compex" },
  146 
  147         { PCI_VENDOR_PROLAN,            PCI_PRODUCT_PROLAN_NE2KETHER,
  148           NULL,                         NULL,
  149           NULL,                         NULL,
  150           "ProLAN" },
  151 
  152         { PCI_VENDOR_KTI,               PCI_PRODUCT_KTI_NE2KETHER,
  153           NULL,                         NULL,
  154           NULL,                         NULL,
  155           "KTI" },
  156 
  157         { 0,                            0,
  158           NULL,                         NULL,
  159           NULL,                         NULL,
  160           NULL },
  161 };
  162 
  163 const struct ne_pci_product *ne_pci_lookup
  164     __P((const struct pci_attach_args *));
  165 
  166 const struct ne_pci_product *
  167 ne_pci_lookup(pa)
  168         const struct pci_attach_args *pa;
  169 {
  170         const struct ne_pci_product *npp;
  171 
  172         for (npp = ne_pci_products; npp->npp_name != NULL; npp++) {
  173                 if (PCI_VENDOR(pa->pa_id) == npp->npp_vendor &&
  174                     PCI_PRODUCT(pa->pa_id) == npp->npp_product)
  175                         return (npp);
  176         }
  177         return (NULL);
  178 }
  179 
  180 /*
  181  * PCI constants.
  182  * XXX These should be in a common file!
  183  */
  184 #define PCI_CBIO        0x10            /* Configuration Base IO Address */
  185 
  186 int
  187 ne_pci_match(parent, match, aux)
  188         struct device *parent;
  189         struct cfdata *match;
  190         void *aux;
  191 {
  192         struct pci_attach_args *pa = aux;
  193 
  194         if (ne_pci_lookup(pa) != NULL)
  195                 return (1);
  196 
  197         return (0);
  198 }
  199 
  200 void
  201 ne_pci_attach(parent, self, aux)
  202         struct device *parent, *self;
  203         void *aux;
  204 {
  205         struct ne_pci_softc *psc = (struct ne_pci_softc *)self;
  206         struct ne2000_softc *nsc = &psc->sc_ne2000;
  207         struct dp8390_softc *dsc = &nsc->sc_dp8390;
  208         struct pci_attach_args *pa = aux;
  209         pci_chipset_tag_t pc = pa->pa_pc;
  210         bus_space_tag_t nict;
  211         bus_space_handle_t nich;
  212         bus_space_tag_t asict;
  213         bus_space_handle_t asich;
  214         const char *intrstr;
  215         const struct ne_pci_product *npp;
  216         pci_intr_handle_t ih;
  217         pcireg_t csr;
  218 
  219         npp = ne_pci_lookup(pa);
  220         if (npp == NULL) {
  221                 printf("\n");
  222                 panic("ne_pci_attach: impossible");
  223         }
  224 
  225         printf(": %s Ethernet\n", npp->npp_name);
  226 
  227 #ifdef IPKDB_NE_PCI
  228         if (ne_pci_isipkdb(pc, pa->pa_tag)) {
  229                 nict = ipkdb_softc.sc_ne2000.sc_dp8390.sc_regt;
  230                 nich = ipkdb_softc.sc_ne2000.sc_dp8390.sc_regh;
  231                 ne_kip->port = nsc;
  232         } else
  233 #endif
  234         if (pci_mapreg_map(pa, PCI_CBIO, PCI_MAPREG_TYPE_IO, 0,
  235             &nict, &nich, NULL, NULL)) {
  236                 printf("%s: can't map i/o space\n", dsc->sc_dev.dv_xname);
  237                 return;
  238         }
  239 
  240         asict = nict;
  241         if (bus_space_subregion(nict, nich, NE2000_ASIC_OFFSET,
  242             NE2000_ASIC_NPORTS, &asich)) {
  243                 printf("%s: can't subregion i/o space\n", dsc->sc_dev.dv_xname);
  244                 return;
  245         }
  246 
  247         dsc->sc_regt = nict;
  248         dsc->sc_regh = nich;
  249 
  250         nsc->sc_asict = asict;
  251         nsc->sc_asich = asich;
  252 
  253         /* Enable the card. */
  254         csr = pci_conf_read(pc, pa->pa_tag,
  255             PCI_COMMAND_STATUS_REG);
  256         pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
  257             csr | PCI_COMMAND_MASTER_ENABLE);
  258 
  259         /* This interface is always enabled. */
  260         dsc->sc_enabled = 1;
  261 
  262         dsc->sc_mediachange = npp->npp_mediachange;
  263         dsc->sc_mediastatus = npp->npp_mediastatus;
  264         dsc->sc_media_init = npp->npp_media_init;
  265         dsc->init_card = npp->npp_init_card;
  266 
  267         /*
  268          * Do generic NE2000 attach.  This will read the station address
  269          * from the EEPROM.
  270          */
  271         ne2000_attach(nsc, NULL);
  272 
  273         /* Map and establish the interrupt. */
  274         if (pci_intr_map(pa, &ih)) {
  275                 printf("%s: couldn't map interrupt\n", dsc->sc_dev.dv_xname);
  276                 return;
  277         }
  278         intrstr = pci_intr_string(pc, ih);
  279         psc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, dp8390_intr, dsc);
  280         if (psc->sc_ih == NULL) {
  281                 printf("%s: couldn't establish interrupt",
  282                     dsc->sc_dev.dv_xname);
  283                 if (intrstr != NULL)
  284                         printf(" at %s", intrstr);
  285                 printf("\n");
  286                 return;
  287         }
  288         printf("%s: interrupting at %s\n", dsc->sc_dev.dv_xname, intrstr);
  289 }
  290 
  291 #ifdef IPKDB_NE_PCI
  292 static int
  293 ne_pci_isipkdb(pc, tag)
  294         pci_chipset_tag_t pc;
  295         pcitag_t tag;
  296 {
  297         return !memcmp(&pc, &ipkdb_pc, sizeof pc)
  298                 && !memcmp(&tag, &ipkdb_tag, sizeof tag);
  299 }
  300 
  301 int
  302 ne_pci_ipkdb_attach(kip, iot, pc, bus, dev)
  303         struct ipkdb_if *kip;
  304         bus_space_tag_t iot;
  305         pci_chipset_tag_t pc;
  306         int bus, dev;
  307 {
  308         struct pci_attach_args pa;
  309         bus_space_tag_t nict, asict;
  310         bus_space_handle_t nich, asich;
  311         u_int32_t csr;
  312 
  313         pa.pa_iot = iot;
  314         pa.pa_pc = pc;
  315         pa.pa_device = dev;
  316         pa.pa_function = 0;
  317         pa.pa_flags = PCI_FLAGS_IO_ENABLED;
  318         pa.pa_tag = pci_make_tag(pc, bus, dev, /*func*/0);
  319         pa.pa_id = pci_conf_read(pc, pa.pa_tag, PCI_ID_REG);
  320         pa.pa_class = pci_conf_read(pc, pa.pa_tag, PCI_CLASS_REG);
  321         if (ne_pci_lookup(&pa) == NULL)
  322                 return -1;
  323 
  324         if (pci_mapreg_map(&pa, PCI_CBIO, PCI_MAPREG_TYPE_IO, 0,
  325                         &nict, &nich, NULL, NULL))
  326                 return -1;
  327 
  328         asict = nict;
  329         if (bus_space_subregion(nict, nich, NE2000_ASIC_OFFSET,
  330                                 NE2000_ASIC_NPORTS, &asich)) {
  331                 bus_space_unmap(nict, nich, NE2000_NPORTS);
  332                 return -1;
  333         }
  334 
  335         /* Enable card */
  336         csr = pci_conf_read(pc, pa.pa_tag, PCI_COMMAND_STATUS_REG);
  337         pci_conf_write(pc, pa.pa_tag, PCI_COMMAND_STATUS_REG,
  338                         csr | PCI_COMMAND_MASTER_ENABLE);
  339 
  340         ipkdb_softc.sc_ne2000.sc_dp8390.sc_regt = nict;
  341         ipkdb_softc.sc_ne2000.sc_dp8390.sc_regh = nich;
  342         ipkdb_softc.sc_ne2000.sc_asict = asict;
  343         ipkdb_softc.sc_ne2000.sc_asich = asich;
  344 
  345         kip->port = &ipkdb_softc;
  346         ipkdb_pc = pc;
  347         ipkdb_tag = pa.pa_tag;
  348         ne_kip = kip;
  349 
  350         if (ne2000_ipkdb_attach(kip) < 0) {
  351                 bus_space_unmap(nict, nich, NE2000_NPORTS);
  352                 return -1;
  353         }
  354 
  355         return 0;
  356 }
  357 #endif

Cache object: c640aaca251e6f130555c05fb98e3989


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