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_fpa.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_fpa.c,v 1.43 2003/01/31 00:07:42 thorpej Exp $      */
    2 
    3 /*-
    4  * Copyright (c) 1995, 1996 Matt Thomas <matt@3am-software.com>
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. The name of the author may not be used to endorse or promote products
   13  *    derived from this software without specific prior written permission
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   25  *
   26  * Id: if_fpa.c,v 1.11 1997/06/05 01:56:35 thomas Exp
   27  *
   28  */
   29 
   30 /*
   31  * DEC PDQ FDDI Controller; code for BSD derived operating systems
   32  *
   33  *   This module supports the DEC DEFPA PCI FDDI Controller
   34  */
   35 
   36 #include <sys/cdefs.h>
   37 __KERNEL_RCSID(0, "$NetBSD: if_fpa.c,v 1.43 2003/01/31 00:07:42 thorpej Exp $");
   38 
   39 #ifdef __NetBSD__
   40 #include "opt_inet.h"
   41 #endif
   42 
   43 #include <sys/param.h>
   44 #include <sys/kernel.h>
   45 #include <sys/mbuf.h>
   46 #include <sys/protosw.h>
   47 #include <sys/socket.h>
   48 #include <sys/ioctl.h>
   49 #include <sys/errno.h>
   50 #include <sys/malloc.h>
   51 #if defined(__FreeBSD__) && BSD < 199401
   52 #include <sys/devconf.h>
   53 #elif defined(__bsdi__) || defined(__NetBSD__)
   54 #include <sys/device.h>
   55 #endif
   56 
   57 #include <net/if.h>
   58 #include <net/if_types.h>
   59 #include <net/if_dl.h>
   60 #include <net/route.h>
   61 
   62 #include "bpfilter.h"
   63 #if NBPFILTER > 0
   64 #include <net/bpf.h>
   65 #include <net/bpfdesc.h>
   66 #endif
   67 
   68 #if defined(__FreeBSD__)
   69 #include <netinet/if_fddi.h>
   70 #else
   71 #include <net/if_fddi.h>
   72 #endif
   73 
   74 #if defined(__FreeBSD__)
   75 #include <vm/vm.h>
   76 #include "fpa.h"
   77 #include <netinet/if_ether.h>
   78 #include <pci/pcivar.h>
   79 #include <i386/isa/icu.h>
   80 #include <dev/pdq/pdqvar.h>
   81 #include <dev/pdq/pdqreg.h>
   82 #elif defined(__bsdi__)
   83 #include <netinet/if_ether.h>
   84 #include <i386/isa/isavar.h>
   85 #include <i386/isa/icu.h>
   86 #ifndef DRQNONE
   87 #define DRQNONE         0
   88 #endif
   89 #if _BSDI_VERSION < 199401
   90 #define IRQSHARE        0
   91 #endif
   92 #include <i386/pci/pci.h>
   93 #include <dev/pdq/pdqvar.h>
   94 #include <dev/pdq/pdqreg.h>
   95 #elif defined(__NetBSD__)
   96 #include <dev/pci/pcidevs.h>
   97 #include <dev/pci/pcivar.h>
   98 #include <dev/ic/pdqvar.h>
   99 #include <dev/ic/pdqreg.h>
  100 #endif /* __NetBSD__ */
  101 
  102 
  103 #define DEC_VENDORID            0x1011
  104 #define DEFPA_CHIPID            0x000F
  105 #define PCI_VENDORID(x)         ((x) & 0xFFFF)
  106 #define PCI_CHIPID(x)           (((x) >> 16) & 0xFFFF)
  107 
  108 #define DEFPA_LATENCY   0x88
  109 
  110 #define PCI_CFLT        0x0C    /* Configuration Latency */
  111 #define PCI_CBMA        0x10    /* Configuration Base Memory Address */
  112 #define PCI_CBIO        0x14    /* Configuration Base I/O Address */
  113 
  114 #if defined(__FreeBSD__)
  115 #if NFPA < 4
  116 #undef NFPA
  117 #define NFPA    4
  118 #endif
  119 static pdq_softc_t *pdqs_pci[NFPA];
  120 #define PDQ_PCI_UNIT_TO_SOFTC(unit)     (pdqs_pci[unit])
  121 #if BSD >= 199506
  122 #define pdq_pci_ifwatchdog              NULL
  123 static void pdq_pci_shutdown(int howto, void *sc);
  124 #endif
  125 
  126 #elif defined(__bsdi__)
  127 extern struct cfdriver fpacd;
  128 #define PDQ_PCI_UNIT_TO_SOFTC(unit)     ((pdq_softc_t *)fpacd.cd_devs[unit])
  129 
  130 #elif defined(__NetBSD__)
  131 extern struct cfdriver fpa_cd;
  132 #define PDQ_PCI_UNIT_TO_SOFTC(unit)     ((pdq_softc_t *)fpa_cd.cd_devs[unit])
  133 #define pdq_pci_ifwatchdog              NULL
  134 #endif
  135 
  136 #ifndef pdq_pci_ifwatchdog
  137 static ifnet_ret_t
  138 pdq_pci_ifwatchdog(
  139     int unit)
  140 {
  141     pdq_ifwatchdog(&PDQ_PCI_UNIT_TO_SOFTC(unit)->sc_if);
  142 }
  143 #endif
  144 
  145 #if defined(__FreeBSD__) && BSD >= 199506
  146 static void
  147 pdq_pci_ifintr(
  148     void *arg)
  149 {
  150     (void) pdq_interrupt(((pdq_softc_t *) arg)->sc_pdq);
  151 }
  152 #else
  153 static int
  154 pdq_pci_ifintr(
  155     void *arg)
  156 {
  157     pdq_softc_t * const sc = (pdq_softc_t *) arg;
  158 #ifdef __FreeBSD__
  159     return pdq_interrupt(sc->sc_pdq);
  160 #elif defined(__bsdi__) || defined(__NetBSD__)
  161     (void) pdq_interrupt(sc->sc_pdq);
  162     return 1;
  163 #endif
  164 }
  165 #endif /* __FreeBSD && BSD */
  166 
  167 #if defined(__FreeBSD__)
  168 /*
  169  * This is the PCI configuration support.  Since the PDQ is available
  170  * on both EISA and PCI boards, one must be careful in how defines the
  171  * PDQ in the config file.
  172  */
  173 static char *
  174 pdq_pci_probe(
  175     pcici_t config_id,
  176     pcidi_t device_id)
  177 {
  178     if (PCI_VENDORID(device_id) == DEC_VENDORID &&
  179             PCI_CHIPID(device_id) == DEFPA_CHIPID)
  180         return "Digital DEFPA PCI FDDI Controller";
  181     return NULL;
  182 }
  183 
  184 static void
  185 pdq_pci_attach(
  186     pcici_t config_id,
  187     int unit)
  188 {
  189     pdq_softc_t *sc;
  190     vaddr_t va_csrs;
  191     paddr_t pa_csrs;
  192     pdq_uint32_t data;
  193 
  194     if (unit == NFPA) {
  195         printf("fpa%d: not configured; kernel is built for only %d device%s.\n",
  196                unit, NFPA, NFPA == 1 ? "" : "s");
  197         return;
  198     }
  199 
  200     data = pci_conf_read(config_id, PCI_CFLT);
  201     if ((data & 0xFF00) < (DEFPA_LATENCY << 8)) {
  202         data &= ~0xFF00;
  203         data |= DEFPA_LATENCY << 8;
  204         pci_conf_write(config_id, PCI_CFLT, data);
  205     }
  206 
  207     sc = (pdq_softc_t *) malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT|M_ZERO);
  208     if (sc == NULL)
  209         return;
  210 
  211     if (!pci_map_mem(config_id, PCI_CBMA, &va_csrs, &pa_csrs)) {
  212         free((void *) sc, M_DEVBUF);
  213         return;
  214     }
  215 
  216     sc->sc_if.if_name = "fpa";
  217     sc->sc_if.if_unit = unit;
  218     sc->sc_membase = (pdq_bus_memaddr_t) va_csrs;
  219     sc->sc_pdq = pdq_initialize(PDQ_BUS_PCI, sc->sc_membase,
  220                                 sc->sc_if.if_name, sc->sc_if.if_unit,
  221                                 (void *) sc, PDQ_DEFPA);
  222     if (sc->sc_pdq == NULL) {
  223         free((void *) sc, M_DEVBUF);
  224         return;
  225     }
  226     bcopy((caddr_t) sc->sc_pdq->pdq_hwaddr.lanaddr_bytes, sc->sc_ac.ac_enaddr, 6);
  227     pdqs_pci[unit] = sc;
  228     pdq_ifattach(sc, pdq_pci_ifwatchdog);
  229     pci_map_int(config_id, pdq_pci_ifintr, (void*) sc, &net_imask);
  230 #if BSD >= 199506
  231     at_shutdown(pdq_pci_shutdown, (void *) sc, SHUTDOWN_POST_SYNC);
  232 #endif
  233 }
  234 
  235 #if BSD < 199401
  236 static int
  237 pdq_pci_shutdown(
  238     struct kern_devconf *kdc,
  239     int force)
  240 {
  241     if (kdc->kdc_unit < NFPA)
  242         pdq_hwreset(PDQ_PCI_UNIT_TO_SOFTC(kdc->kdc_unit)->sc_pdq);
  243     (void) dev_detach(kdc);
  244     return 0;
  245 }
  246 #else
  247 static void
  248 pdq_pci_shutdown(
  249     int howto,
  250     void *sc)
  251 {
  252     pdq_hwreset(((pdq_softc_t *)sc)->sc_pdq);
  253 }   
  254 #endif
  255 
  256 static u_long pdq_pci_count;
  257 
  258 struct pci_device fpadevice = {
  259     "fpa",
  260     pdq_pci_probe,
  261     pdq_pci_attach,
  262     &pdq_pci_count,
  263 #if BSD < 199401
  264     pdq_pci_shutdown,
  265 #endif
  266 };
  267 
  268 #ifdef DATA_SET
  269 DATA_SET (pcidevice_set, fpadevice);
  270 #endif
  271 #elif defined(__bsdi__)
  272 
  273 static int
  274 pdq_pci_match(
  275     pci_devaddr_t *pa)
  276 {
  277     int irq;
  278     int id;
  279 
  280     id = pci_inl(pa, PCI_VENDOR_ID);
  281     if (PCI_VENDORID(id) != DEC_VENDORID || PCI_CHIPID(id) != DEFPA_CHIPID)
  282         return 0;
  283 
  284     irq = pci_inl(pa, PCI_I_LINE) & 0xFF;
  285     if (irq == 0 || irq >= 16)
  286         return 0;
  287 
  288     return 1;
  289 }
  290 
  291 int
  292 pdq_pci_probe(
  293     struct device *parent,
  294     struct cfdata *cf,
  295     void *aux)
  296 {
  297     struct isa_attach_args *ia = (struct isa_attach_args *) aux;
  298     pdq_uint32_t irq, data;
  299     pci_devaddr_t *pa;
  300 
  301     pa = pci_scan(pdq_pci_match);
  302     if (pa == NULL)
  303         return 0;
  304 
  305     irq = (1 << (pci_inl(pa, PCI_I_LINE) & 0xFF));
  306 
  307     if (ia->ia_irq != IRQUNK && irq != ia->ia_irq) {
  308         printf("fpa%d: error: desired IRQ of %d does not match device's actual IRQ of %d\n",
  309                cf->cf_unit,
  310                ffs(ia->ia_irq) - 1, ffs(irq) - 1);
  311         return 0;
  312     }
  313     if (ia->ia_irq == IRQUNK) {
  314         (void) isa_irqalloc(irq);
  315         ia->ia_irq = irq;
  316     }
  317 
  318     /* PCI bus masters don't use host DMA channels */
  319     ia->ia_drq = DRQNONE;
  320 
  321     /* Get the memory base address; assume the BIOS set it up correctly */
  322     ia->ia_maddr = (caddr_t) (pci_inl(pa, PCI_CBMA) & ~7);
  323     pci_outl(pa, PCI_CBMA, 0xFFFFFFFF);
  324     ia->ia_msize = ((~pci_inl(pa, PCI_CBMA)) | 7) + 1;
  325     pci_outl(pa, PCI_CBMA, (int) ia->ia_maddr);
  326 
  327     /* Disable I/O space access */
  328     pci_outl(pa, PCI_COMMAND, pci_inl(pa, PCI_COMMAND) & ~1);
  329     ia->ia_iobase = 0;
  330     ia->ia_iosize = 0;
  331 
  332     /* Make sure the latency timer is what the DEFPA likes */
  333     data = pci_inl(pa, PCI_CFLT);
  334     if ((data & 0xFF00) < (DEFPA_LATENCY << 8)) {
  335         data &= ~0xFF00;
  336         data |= DEFPA_LATENCY << 8;
  337         pci_outl(pa, PCI_CFLT, data);
  338     }
  339     ia->ia_irq |= IRQSHARE;
  340 
  341     return 1;
  342 }
  343 
  344 void
  345 pdq_pci_attach(
  346     struct device *parent,
  347     struct device *self,
  348     void *aux)
  349 {
  350     pdq_softc_t *sc = (pdq_softc_t *) self;
  351     struct isa_attach_args *ia = (struct isa_attach_args *) aux;
  352     struct ifnet *ifp = &sc->sc_if;
  353     int i;
  354 
  355     sc->sc_if.if_unit = sc->sc_dev.dv_unit;
  356     sc->sc_if.if_name = "fpa";
  357     sc->sc_if.if_flags = 0;
  358     sc->sc_membase = (pdq_bus_memaddr_t) mapphys((vaddr_t)ia->ia_maddr, ia->ia_msize);
  359 
  360     sc->sc_pdq = pdq_initialize(PDQ_BUS_PCI, sc->sc_membase,
  361                                 sc->sc_if.if_name, sc->sc_if.if_unit,
  362                                 (void *) sc, PDQ_DEFPA);
  363     if (sc->sc_pdq == NULL) {
  364         printf("fpa%d: initialization failed\n", sc->sc_if.if_unit);
  365         return;
  366     }
  367 
  368     bcopy((caddr_t) sc->sc_pdq->pdq_hwaddr.lanaddr_bytes, sc->sc_ac.ac_enaddr, 6);
  369 
  370     pdq_ifattach(sc, pdq_pci_ifwatchdog);
  371 
  372     isa_establish(&sc->sc_id, &sc->sc_dev);
  373 
  374     sc->sc_ih.ih_fun = pdq_pci_ifintr;
  375     sc->sc_ih.ih_arg = (void *)sc;
  376     intr_establish(ia->ia_irq, &sc->sc_ih, DV_NET);
  377 
  378     sc->sc_ats.func = (void (*)(void *)) pdq_hwreset;
  379     sc->sc_ats.arg = (void *) sc->sc_pdq;
  380     atshutdown(&sc->sc_ats, ATSH_ADD);
  381 }
  382 
  383 struct cfdriver fpacd = {
  384     0, "fpa", pdq_pci_probe, pdq_pci_attach,
  385 #if _BSDI_VERSION >= 199401
  386     DV_IFNET,
  387 #endif
  388     sizeof(pdq_softc_t)
  389 };
  390 
  391 #elif defined(__NetBSD__)
  392 
  393 static int
  394 pdq_pci_match(
  395     struct device *parent,
  396     struct cfdata *match,
  397     void *aux)
  398 {
  399     struct pci_attach_args *pa = (struct pci_attach_args *) aux;
  400 
  401     if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_DEC)
  402         return 0;
  403     if (PCI_PRODUCT(pa->pa_id) != PCI_PRODUCT_DEC_DEFPA)
  404         return 0;
  405 
  406     return 1;
  407 }
  408 
  409 static void
  410 pdq_pci_attach(
  411     struct device * const parent,
  412     struct device * const self,
  413     void * const aux)
  414 {
  415     pdq_softc_t * const sc = (pdq_softc_t *)self;
  416     struct pci_attach_args * const pa = (struct pci_attach_args *) aux;
  417     pdq_uint32_t data;
  418     pci_intr_handle_t intrhandle;
  419     const char *intrstr;
  420     bus_space_tag_t iot, memt;
  421     bus_space_handle_t ioh, memh;
  422     int ioh_valid, memh_valid;
  423 
  424     aprint_naive(": FDDI controller\n");
  425 
  426     data = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CFLT);
  427     if ((data & 0xFF00) < (DEFPA_LATENCY << 8)) {
  428         data &= ~0xFF00;
  429         data |= DEFPA_LATENCY << 8;
  430         pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_CFLT, data);
  431     }
  432 
  433     strcpy(sc->sc_if.if_xname, sc->sc_dev.dv_xname);
  434     sc->sc_if.if_flags = 0;
  435     sc->sc_if.if_softc = sc;
  436 
  437     ioh_valid = (pci_mapreg_map(pa, PCI_CBIO, PCI_MAPREG_TYPE_IO, 0,
  438                  &iot, &ioh, NULL, NULL) == 0);
  439     memh_valid = (pci_mapreg_map(pa, PCI_CBMA,
  440                   PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0,
  441                   &memt, &memh, NULL, NULL) == 0);
  442 
  443 #if defined(DEFPA_IOMAPED)
  444     if (ioh_valid) {
  445         sc->sc_csrtag = iot;
  446         sc->sc_membase = ioh;
  447     } else if (memh_valid) {
  448         sc->sc_csrtag = memt;
  449         sc->sc_membase = memh;
  450     }
  451 #else /* defined(DEFPA_IOMAPPED) */
  452     if (memh_valid) {
  453         sc->sc_csrtag = memt;
  454         sc->sc_membase = memh;
  455     } else if (ioh_valid) {
  456         sc->sc_csrtag = iot;
  457         sc->sc_membase = ioh;
  458     }
  459 #endif /* DEFPA_IOMAPPED */
  460     else {
  461         aprint_error(": unable to map device registers\n");
  462         return;
  463     }
  464 
  465     sc->sc_dmatag = pa->pa_dmat;
  466 
  467     /* Make sure bus mastering is enabled. */
  468     pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
  469                    pci_conf_read(pa->pa_pc, pa->pa_tag,
  470                                  PCI_COMMAND_STATUS_REG) |
  471                    PCI_COMMAND_MASTER_ENABLE);
  472 
  473     sc->sc_pdq = pdq_initialize(sc->sc_csrtag, sc->sc_membase,
  474                                 sc->sc_if.if_xname, 0,
  475                                 (void *) sc, PDQ_DEFPA);
  476     if (sc->sc_pdq == NULL) {
  477         aprint_error("%s: initialization failed\n", sc->sc_dev.dv_xname);
  478         return;
  479     }
  480 
  481     pdq_ifattach(sc, pdq_pci_ifwatchdog);
  482 
  483     if (pci_intr_map(pa, &intrhandle)) {
  484         aprint_error("%s: couldn't map interrupt\n", self->dv_xname);
  485         return;
  486     }
  487     intrstr = pci_intr_string(pa->pa_pc, intrhandle);
  488     sc->sc_ih = pci_intr_establish(pa->pa_pc, intrhandle, IPL_NET, pdq_pci_ifintr, sc);
  489     if (sc->sc_ih == NULL) {
  490         aprint_error("%s: couldn't establish interrupt", self->dv_xname);
  491         if (intrstr != NULL)
  492             aprint_normal(" at %s", intrstr);
  493         aprint_normal("\n");
  494         return;
  495     }
  496 
  497     sc->sc_ats = shutdownhook_establish((void (*)(void *)) pdq_hwreset, sc->sc_pdq);
  498     if (sc->sc_ats == NULL)
  499         aprint_error("%s: warning: couldn't establish shutdown hook\n", self->dv_xname);
  500     if (intrstr != NULL)
  501         aprint_normal("%s: interrupting at %s\n", self->dv_xname, intrstr);
  502 }
  503 
  504 CFATTACH_DECL(fpa, sizeof(pdq_softc_t),
  505     pdq_pci_match, pdq_pci_attach, NULL, NULL);
  506 
  507 #endif /* __NetBSD__ */

Cache object: 25ba97c99f6d2cc0cef27815f0162a64


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