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

Cache object: dd04429f61bb15a492af456cb1477ba6


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