source: rtems-libbsd/freebsd/sys/powerpc/powerpc/legacy.c @ 66659ff

4.1155-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since 66659ff was 66659ff, checked in by Sebastian Huber <sebastian.huber@…>, on 11/06/13 at 15:20:21

Update to FreeBSD 9.2

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