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/powerpc/powermac/grackle.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 2003 by Peter Grehan. All rights reserved.
    3  *
    4  * Redistribution and use in source and binary forms, with or without
    5  * modification, are permitted provided that the following conditions
    6  * are met:
    7  * 1. Redistributions of source code must retain the above copyright
    8  *    notice, this list of conditions and the following disclaimer.
    9  * 2. Redistributions in binary form must reproduce the above copyright
   10  *    notice, this list of conditions and the following disclaimer in the
   11  *    documentation and/or other materials provided with the distribution.
   12  * 3. 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,
   20  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   21  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
   22  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   23  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  */
   27 
   28 #include <sys/cdefs.h>
   29 __FBSDID("$FreeBSD$");
   30 
   31 #include <sys/param.h>
   32 #include <sys/systm.h>
   33 #include <sys/module.h>
   34 #include <sys/bus.h>
   35 #include <sys/conf.h>
   36 #include <sys/kernel.h>
   37 
   38 #include <dev/ofw/openfirm.h>
   39 #include <dev/ofw/ofw_pci.h>
   40 #include <dev/ofw/ofw_bus.h>
   41 #include <dev/ofw/ofw_bus_subr.h>
   42 
   43 #include <dev/pci/pcivar.h>
   44 #include <dev/pci/pcireg.h>
   45 
   46 #include <machine/bus.h>
   47 #include <machine/intr_machdep.h>
   48 #include <machine/md_var.h>
   49 #include <machine/pio.h>
   50 #include <machine/resource.h>
   51 
   52 #include <sys/rman.h>
   53 
   54 #include <powerpc/ofw/ofw_pci.h>
   55 #include <powerpc/powermac/gracklevar.h>
   56 
   57 #include <vm/vm.h>
   58 #include <vm/pmap.h>
   59 
   60 #include "pcib_if.h"
   61 
   62 int      badaddr(void *, size_t);  /* XXX */
   63 
   64 /*
   65  * Device interface.
   66  */
   67 static int              grackle_probe(device_t);
   68 static int              grackle_attach(device_t);
   69 
   70 /*
   71  * pcib interface.
   72  */
   73 static u_int32_t        grackle_read_config(device_t, u_int, u_int, u_int,
   74                             u_int, int);
   75 static void             grackle_write_config(device_t, u_int, u_int, u_int,
   76                             u_int, u_int32_t, int);
   77 
   78 /*
   79  * Local routines.
   80  */
   81 static int              grackle_enable_config(struct grackle_softc *, u_int,
   82                             u_int, u_int, u_int);
   83 static void             grackle_disable_config(struct grackle_softc *);
   84 
   85 /*
   86  * Driver methods.
   87  */
   88 static device_method_t  grackle_methods[] = {
   89         /* Device interface */
   90         DEVMETHOD(device_probe,         grackle_probe),
   91         DEVMETHOD(device_attach,        grackle_attach),
   92 
   93         /* pcib interface */
   94         DEVMETHOD(pcib_read_config,     grackle_read_config),
   95         DEVMETHOD(pcib_write_config,    grackle_write_config),
   96 
   97         DEVMETHOD_END
   98 };
   99 
  100 static devclass_t       grackle_devclass;
  101 DEFINE_CLASS_1(pcib, grackle_driver, grackle_methods,
  102     sizeof(struct grackle_softc), ofw_pci_driver);
  103 DRIVER_MODULE(grackle, nexus, grackle_driver, grackle_devclass, 0, 0);
  104 
  105 static int
  106 grackle_probe(device_t dev)
  107 {
  108         const char      *type, *compatible;
  109 
  110         type = ofw_bus_get_type(dev);
  111         compatible = ofw_bus_get_compat(dev);
  112 
  113         if (type == NULL || compatible == NULL)
  114                 return (ENXIO);
  115 
  116         if (strcmp(type, "pci") != 0 || strcmp(compatible, "grackle") != 0)
  117                 return (ENXIO);
  118 
  119         device_set_desc(dev, "MPC106 (Grackle) Host-PCI bridge");
  120         return (0);
  121 }
  122 
  123 static int
  124 grackle_attach(device_t dev)
  125 {
  126         struct          grackle_softc *sc;
  127 
  128         sc = device_get_softc(dev);
  129 
  130         /*
  131          * The Grackle PCI config addr/data registers are actually in
  132          * PCI space, but since they are needed to actually probe the
  133          * PCI bus, use the fact that they are also available directly
  134          * on the processor bus and map them
  135          */
  136         sc->sc_addr = (vm_offset_t)pmap_mapdev(GRACKLE_ADDR, PAGE_SIZE);
  137         sc->sc_data = (vm_offset_t)pmap_mapdev(GRACKLE_DATA, PAGE_SIZE);
  138 
  139         return (ofw_pci_attach(dev));
  140 }
  141 
  142 static u_int32_t
  143 grackle_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg,
  144     int width)
  145 {
  146         struct          grackle_softc *sc;
  147         vm_offset_t     caoff;
  148         u_int32_t       retval = 0xffffffff;
  149 
  150         sc = device_get_softc(dev);
  151         caoff = sc->sc_data + (reg & 0x03);
  152 
  153         if (grackle_enable_config(sc, bus, slot, func, reg) != 0) {
  154 
  155                 /*
  156                  * Config probes to non-existent devices on the
  157                  * secondary bus generates machine checks. Be sure
  158                  * to catch these.
  159                  */
  160                 if (bus > 0) {
  161                   if (badaddr((void *)sc->sc_data, 4)) {
  162                           return (retval);
  163                   }
  164                 }
  165 
  166                 switch (width) {
  167                 case 1:
  168                         retval = (in8rb(caoff));
  169                         break;
  170                 case 2:
  171                         retval = (in16rb(caoff));
  172                         break;
  173                 case 4:
  174                         retval = (in32rb(caoff));
  175                         break;
  176                 }
  177         }
  178         grackle_disable_config(sc);
  179 
  180         return (retval);
  181 }
  182 
  183 static void
  184 grackle_write_config(device_t dev, u_int bus, u_int slot, u_int func,
  185     u_int reg, u_int32_t val, int width)
  186 {
  187         struct          grackle_softc *sc;
  188         vm_offset_t     caoff;
  189 
  190         sc = device_get_softc(dev);
  191         caoff = sc->sc_data + (reg & 0x03);
  192 
  193         if (grackle_enable_config(sc, bus, slot, func, reg)) {
  194                 switch (width) {
  195                 case 1:
  196                         out8rb(caoff, val);
  197                         (void)in8rb(caoff);
  198                         break;
  199                 case 2:
  200                         out16rb(caoff, val);
  201                         (void)in16rb(caoff);
  202                         break;
  203                 case 4:
  204                         out32rb(caoff, val);
  205                         (void)in32rb(caoff);
  206                         break;
  207                 }
  208         }
  209         grackle_disable_config(sc);
  210 }
  211 
  212 static int
  213 grackle_enable_config(struct grackle_softc *sc, u_int bus, u_int slot,
  214     u_int func, u_int reg)
  215 {
  216         u_int32_t       cfgval;
  217 
  218         /*
  219          * Unlike UniNorth, the format of the config word is the same
  220          * for local (0) and remote busses.
  221          */
  222         cfgval = (bus << 16) | (slot << 11) | (func << 8) | (reg & 0xFC)
  223             | GRACKLE_CFG_ENABLE;
  224 
  225         out32rb(sc->sc_addr, cfgval);
  226         (void) in32rb(sc->sc_addr);
  227 
  228         return (1);
  229 }
  230 
  231 static void
  232 grackle_disable_config(struct grackle_softc *sc)
  233 {
  234         /*
  235          * Clear the GRACKLE_CFG_ENABLE bit to prevent stray
  236          * accesses from causing config cycles
  237          */
  238         out32rb(sc->sc_addr, 0);
  239 }
  240 
  241 /*
  242  * Driver to swallow Grackle host bridges from the PCI bus side.
  243  */
  244 static int
  245 grackle_hb_probe(device_t dev)
  246 {
  247 
  248         if (pci_get_devid(dev) == 0x00021057) {
  249                 device_set_desc(dev, "Grackle Host to PCI bridge");
  250                 device_quiet(dev);
  251                 return (0);
  252         }
  253 
  254         return (ENXIO);
  255 }
  256 
  257 static int
  258 grackle_hb_attach(device_t dev)
  259 {
  260 
  261         return (0);
  262 }
  263 
  264 static device_method_t grackle_hb_methods[] = {
  265         /* Device interface */
  266         DEVMETHOD(device_probe,         grackle_hb_probe),
  267         DEVMETHOD(device_attach,        grackle_hb_attach),
  268 
  269         { 0, 0 }
  270 };
  271 
  272 static driver_t grackle_hb_driver = {
  273         "grackle_hb",
  274         grackle_hb_methods,
  275         1,
  276 };
  277 static devclass_t grackle_hb_devclass;
  278 
  279 DRIVER_MODULE(grackle_hb, pci, grackle_hb_driver, grackle_hb_devclass, 0, 0);

Cache object: 095d120b5c05db165b5d79302c443188


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