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/amd64/amd64/legacy.c

Version: -  FREEBSD  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright 1998 Massachusetts Institute of Technology
    3  *
    4  * Permission to use, copy, modify, and distribute this software and
    5  * its documentation for any purpose and without fee is hereby
    6  * granted, provided that both the above copyright notice and this
    7  * permission notice appear in all copies, that both the above
    8  * copyright notice and this permission notice appear in all
    9  * supporting documentation, and that the name of M.I.T. not be used
   10  * in advertising or publicity pertaining to distribution of the
   11  * software without specific, written prior permission.  M.I.T. makes
   12  * no representations about the suitability of this software for any
   13  * purpose.  It is provided "as is" without express or implied
   14  * warranty.
   15  * 
   16  * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''.  M.I.T. DISCLAIMS
   17  * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
   18  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
   19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
   20  * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   21  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   23  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   25  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   26  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  */
   29 
   30 #include <sys/cdefs.h>
   31 __FBSDID("$FreeBSD: releng/9.0/sys/amd64/amd64/legacy.c 222929 2011-06-10 12:30:16Z jhb $");
   32 
   33 /*
   34  * This code implements a system driver for legacy systems that do not
   35  * support ACPI or when ACPI support is not present in the kernel.
   36  */
   37 
   38 #include <sys/param.h>
   39 #include <sys/systm.h>
   40 #include <sys/bus.h>
   41 #include <sys/cpu.h>
   42 #include <sys/kernel.h>
   43 #include <sys/malloc.h>
   44 #include <sys/module.h>
   45 #include <machine/bus.h>
   46 #include <sys/pcpu.h>
   47 #include <sys/rman.h>
   48 #include <sys/smp.h>
   49 
   50 #include <machine/clock.h>
   51 #include <machine/legacyvar.h>
   52 #include <machine/resource.h>
   53 
   54 static MALLOC_DEFINE(M_LEGACYDEV, "legacydrv", "legacy system device");
   55 struct legacy_device {
   56         int                     lg_pcibus;
   57 };
   58 
   59 #define DEVTOAT(dev)    ((struct legacy_device *)device_get_ivars(dev))
   60 
   61 static  int legacy_probe(device_t);
   62 static  int legacy_attach(device_t);
   63 static  int legacy_print_child(device_t, device_t);
   64 static device_t legacy_add_child(device_t bus, u_int order, const char *name,
   65                                 int unit);
   66 static  int legacy_read_ivar(device_t, device_t, int, uintptr_t *);
   67 static  int legacy_write_ivar(device_t, device_t, int, uintptr_t);
   68 
   69 static device_method_t legacy_methods[] = {
   70         /* Device interface */
   71         DEVMETHOD(device_probe,         legacy_probe),
   72         DEVMETHOD(device_attach,        legacy_attach),
   73         DEVMETHOD(device_detach,        bus_generic_detach),
   74         DEVMETHOD(device_shutdown,      bus_generic_shutdown),
   75         DEVMETHOD(device_suspend,       bus_generic_suspend),
   76         DEVMETHOD(device_resume,        bus_generic_resume),
   77 
   78         /* Bus interface */
   79         DEVMETHOD(bus_print_child,      legacy_print_child),
   80         DEVMETHOD(bus_add_child,        legacy_add_child),
   81         DEVMETHOD(bus_read_ivar,        legacy_read_ivar),
   82         DEVMETHOD(bus_write_ivar,       legacy_write_ivar),
   83         DEVMETHOD(bus_alloc_resource,   bus_generic_alloc_resource),
   84         DEVMETHOD(bus_adjust_resource,  bus_generic_adjust_resource),
   85         DEVMETHOD(bus_release_resource, bus_generic_release_resource),
   86         DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
   87         DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
   88         DEVMETHOD(bus_setup_intr,       bus_generic_setup_intr),
   89         DEVMETHOD(bus_teardown_intr,    bus_generic_teardown_intr),
   90 
   91         { 0, 0 }
   92 };
   93 
   94 static driver_t legacy_driver = {
   95         "legacy",
   96         legacy_methods,
   97         1,                      /* no softc */
   98 };
   99 static devclass_t legacy_devclass;
  100 
  101 DRIVER_MODULE(legacy, nexus, legacy_driver, legacy_devclass, 0, 0);
  102 
  103 static int
  104 legacy_probe(device_t dev)
  105 {
  106 
  107         device_set_desc(dev, "legacy system");
  108         device_quiet(dev);
  109         return (0);
  110 }
  111 
  112 static int
  113 legacy_attach(device_t dev)
  114 {
  115         device_t child;
  116 
  117         /*
  118          * Let our child drivers identify any child devices that they
  119          * can find.  Once that is done attach any devices that we
  120          * found.
  121          */
  122         bus_generic_probe(dev);
  123         bus_generic_attach(dev);
  124 
  125         /*
  126          * If we didn't see ISA on a pci bridge, create some
  127          * connection points now so it shows up "on motherboard".
  128          */
  129         if (!devclass_get_device(devclass_find("isa"), 0)) {
  130                 child = BUS_ADD_CHILD(dev, 0, "isa", 0);
  131                 if (child == NULL)
  132                         panic("legacy_attach isa");
  133                 device_probe_and_attach(child);
  134         }
  135 
  136         return 0;
  137 }
  138 
  139 static int
  140 legacy_print_child(device_t bus, device_t child)
  141 {
  142         struct legacy_device *atdev = DEVTOAT(child);
  143         int retval = 0;
  144 
  145         retval += bus_print_child_header(bus, child);
  146         if (atdev->lg_pcibus != -1)
  147                 retval += printf(" pcibus %d", atdev->lg_pcibus);
  148         retval += printf(" on motherboard\n");  /* XXX "motherboard", ick */
  149 
  150         return (retval);
  151 }
  152 
  153 static device_t
  154 legacy_add_child(device_t bus, u_int order, const char *name, int unit)
  155 {
  156         device_t child;
  157         struct legacy_device *atdev;
  158 
  159         atdev = malloc(sizeof(struct legacy_device), M_LEGACYDEV,
  160             M_NOWAIT | M_ZERO);
  161         if (atdev == NULL)
  162                 return(NULL);
  163         atdev->lg_pcibus = -1;
  164 
  165         child = device_add_child_ordered(bus, order, name, unit);
  166         if (child == NULL)
  167                 free(atdev, M_LEGACYDEV);
  168         else
  169                 /* should we free this in legacy_child_detached? */
  170                 device_set_ivars(child, atdev);
  171 
  172         return (child);
  173 }
  174 
  175 static int
  176 legacy_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
  177 {
  178         struct legacy_device *atdev = DEVTOAT(child);
  179 
  180         switch (which) {
  181         case LEGACY_IVAR_PCIDOMAIN:
  182                 *result = 0;
  183                 break;
  184         case LEGACY_IVAR_PCIBUS:
  185                 *result = atdev->lg_pcibus;
  186                 break;
  187         default:
  188                 return ENOENT;
  189         }
  190         return 0;
  191 }
  192         
  193 
  194 static int
  195 legacy_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
  196 {
  197         struct legacy_device *atdev = DEVTOAT(child);
  198 
  199         switch (which) {
  200         case LEGACY_IVAR_PCIDOMAIN:
  201                 return EINVAL;
  202         case LEGACY_IVAR_PCIBUS:
  203                 atdev->lg_pcibus = value;
  204                 break;
  205         default:
  206                 return ENOENT;
  207         }
  208         return 0;
  209 }
  210 
  211 /*
  212  * Legacy CPU attachment when ACPI is not available.  Drivers like
  213  * cpufreq(4) hang off this.
  214  */
  215 static void     cpu_identify(driver_t *driver, device_t parent);
  216 static int      cpu_read_ivar(device_t dev, device_t child, int index,
  217                     uintptr_t *result);
  218 static device_t cpu_add_child(device_t bus, u_int order, const char *name,
  219                     int unit);
  220 static struct resource_list *cpu_get_rlist(device_t dev, device_t child);
  221 
  222 struct cpu_device {
  223         struct resource_list cd_rl;
  224         struct pcpu *cd_pcpu;
  225 };
  226 
  227 static device_method_t cpu_methods[] = {
  228         /* Device interface */
  229         DEVMETHOD(device_identify,      cpu_identify),
  230         DEVMETHOD(device_probe,         bus_generic_probe),
  231         DEVMETHOD(device_attach,        bus_generic_attach),
  232         DEVMETHOD(device_detach,        bus_generic_detach),
  233         DEVMETHOD(device_shutdown,      bus_generic_shutdown),
  234         DEVMETHOD(device_suspend,       bus_generic_suspend),
  235         DEVMETHOD(device_resume,        bus_generic_resume),
  236 
  237         /* Bus interface */
  238         DEVMETHOD(bus_add_child,        cpu_add_child),
  239         DEVMETHOD(bus_read_ivar,        cpu_read_ivar),
  240         DEVMETHOD(bus_print_child,      bus_generic_print_child),
  241         DEVMETHOD(bus_get_resource_list, cpu_get_rlist),
  242         DEVMETHOD(bus_get_resource,     bus_generic_rl_get_resource),
  243         DEVMETHOD(bus_set_resource,     bus_generic_rl_set_resource),
  244         DEVMETHOD(bus_alloc_resource,   bus_generic_rl_alloc_resource),
  245         DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource),
  246         DEVMETHOD(bus_driver_added,     bus_generic_driver_added),
  247         DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
  248         DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
  249         DEVMETHOD(bus_setup_intr,       bus_generic_setup_intr),
  250         DEVMETHOD(bus_teardown_intr,    bus_generic_teardown_intr),
  251 
  252         { 0, 0 }
  253 };
  254 
  255 static driver_t cpu_driver = {
  256         "cpu",
  257         cpu_methods,
  258         1,              /* no softc */
  259 };
  260 static devclass_t cpu_devclass;
  261 DRIVER_MODULE(cpu, legacy, cpu_driver, cpu_devclass, 0, 0);
  262 
  263 static void
  264 cpu_identify(driver_t *driver, device_t parent)
  265 {
  266         device_t child;
  267         int i;
  268 
  269         /*
  270          * Attach a cpuX device for each CPU.  We use an order of 150
  271          * so that these devices are attached after the Host-PCI
  272          * bridges (which are added at order 100).
  273          */
  274         CPU_FOREACH(i) {
  275                 child = BUS_ADD_CHILD(parent, 150, "cpu", i);
  276                 if (child == NULL)
  277                         panic("legacy_attach cpu");
  278         }
  279 }
  280 
  281 static device_t
  282 cpu_add_child(device_t bus, u_int order, const char *name, int unit)
  283 {
  284         struct cpu_device *cd;
  285         device_t child;
  286         struct pcpu *pc;
  287 
  288         if ((cd = malloc(sizeof(*cd), M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL)
  289                 return (NULL);
  290 
  291         resource_list_init(&cd->cd_rl);
  292         pc = pcpu_find(device_get_unit(bus));
  293         cd->cd_pcpu = pc;
  294 
  295         child = device_add_child_ordered(bus, order, name, unit);
  296         if (child != NULL) {
  297                 pc->pc_device = child;
  298                 device_set_ivars(child, cd);
  299         } else
  300                 free(cd, M_DEVBUF);
  301         return (child);
  302 }
  303 
  304 static struct resource_list *
  305 cpu_get_rlist(device_t dev, device_t child)
  306 {
  307         struct cpu_device *cpdev;
  308 
  309         cpdev = device_get_ivars(child);
  310         return (&cpdev->cd_rl);
  311 }
  312 
  313 static int
  314 cpu_read_ivar(device_t dev, device_t child, int index, uintptr_t *result)
  315 {
  316         struct cpu_device *cpdev;
  317 
  318         switch (index) {
  319         case CPU_IVAR_PCPU:
  320                 cpdev = device_get_ivars(child);
  321                 *result = (uintptr_t)cpdev->cd_pcpu;
  322                 break;
  323         case CPU_IVAR_NOMINAL_MHZ:
  324                 if (tsc_is_invariant) {
  325                         *result = (uintptr_t)(atomic_load_acq_64(&tsc_freq) /
  326                             1000000);
  327                         break;
  328                 }
  329                 /* FALLTHROUGH */
  330         default:
  331                 return (ENOENT);
  332         }
  333         return (0);
  334 }

Cache object: a401df569c28ae3904ac5d62bd362c8a


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