Changeset 1e36900 in rtems-libbsd


Ignore:
Timestamp:
Jul 9, 2012, 3:23:19 PM (7 years ago)
Author:
Jennifer Averett <jennifer.averett@…>
Branches:
4.11, fd86c091b97759106da7355ce1dd81ebe030e285, freebsd-9.3, f020f08430150c1656a0ad0a1de13699db9b980b
Children:
4f8495e
Parents:
a0da9b6
Message:

Added nexus resource routines.

Location:
rtemsbsd/src
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • rtemsbsd/src/rtems-bsd-nexus.c

    ra0da9b6 r1e36900  
    4747#include <freebsd/sys/kernel.h>
    4848#include <freebsd/sys/module.h>
     49#include <freebsd/sys/rman.h>
     50#include <freebsd/sys/malloc.h>
     51
     52#if defined(__i386__)
     53#include <freebsd/machine/rtems-bsd-config.h>
     54#define I386_BUS_SPACE_MEM      0       /* space is mem space */
     55#endif
     56
     57/* XXX */
     58#define NUM_IO_INTS   30
     59
     60#ifdef __amd64__
     61#define BUS_SPACE_IO    AMD64_BUS_SPACE_IO
     62#define BUS_SPACE_MEM   AMD64_BUS_SPACE_MEM
     63#else
     64#define BUS_SPACE_IO    I386_BUS_SPACE_IO
     65#define BUS_SPACE_MEM   I386_BUS_SPACE_MEM
     66#endif
     67
     68
     69#define DEVTONX(dev)    ((struct nexus_device *)device_get_ivars(dev))
     70
     71static MALLOC_DEFINE(M_NEXUSDEV, "nexusdev", "Nexus device");
     72struct rman irq_rman, drq_rman, port_rman, mem_rman;
     73struct nexus_device {
     74        struct resource_list    nx_resources;
     75};
     76
     77void
     78nexus_init_resources(void)
     79{
     80        int irq;
     81
     82        /*
     83         * XXX working notes:
     84         *
     85         * - IRQ resource creation should be moved to the PIC/APIC driver.
     86         * - DRQ resource creation should be moved to the DMAC driver.
     87         * - The above should be sorted to probe earlier than any child busses.
     88         *
     89         * - Leave I/O and memory creation here, as child probes may need them.
     90         *   (especially eg. ACPI)
     91         */
     92
     93        /*
     94         * IRQ's are on the mainboard on old systems, but on the ISA part
     95         * of PCI->ISA bridges.  There would be multiple sets of IRQs on
     96         * multi-ISA-bus systems.  PCI interrupts are routed to the ISA
     97         * component, so in a way, PCI can be a partial child of an ISA bus(!).
     98         * APIC interrupts are global though.
     99         */
     100        irq_rman.rm_start = 0;
     101        irq_rman.rm_type = RMAN_ARRAY;
     102        irq_rman.rm_descr = "Interrupt request lines";
     103        irq_rman.rm_end = NUM_IO_INTS - 1;
     104        if (rman_init(&irq_rman))
     105                panic("nexus_init_resources irq_rman");
     106        /*
     107         * We search for regions of existing IRQs and add those to the IRQ
     108         * resource manager.
     109         */
     110        for (irq = 0; irq < NUM_IO_INTS; irq++)
     111#ifndef __rtems__
     112                if (intr_lookup_source(irq) != NULL)
     113#endif
     114                        if (rman_manage_region(&irq_rman, irq, irq) != 0)
     115                                panic("nexus_init_resources irq_rmand");
     116 
     117        /*
     118         * ISA DMA on PCI systems is implemented in the ISA part of each
     119         * PCI->ISA bridge and the channels can be duplicated if there are
     120         * multiple bridges.  (eg: laptops with docking stations)
     121         */
     122        drq_rman.rm_start = 0;
     123#ifdef PC98
     124        drq_rman.rm_end = 3;
     125#else
     126        drq_rman.rm_end = 7;
     127#endif
     128        drq_rman.rm_type = RMAN_ARRAY;
     129        drq_rman.rm_descr = "DMA request lines";
     130        /* XXX drq 0 not available on some machines */
     131        if (rman_init(&drq_rman)
     132            || rman_manage_region(&drq_rman,
     133                                  drq_rman.rm_start, drq_rman.rm_end))
     134                panic("nexus_init_resources drq_rman");
     135
     136        /*
     137         * However, IO ports and Memory truely are global at this level,
     138         * as are APIC interrupts (however many IO APICS there turn out
     139         * to be on large systems..)
     140         */
     141        port_rman.rm_start = 0;
     142        port_rman.rm_end = 0xffff;
     143        port_rman.rm_type = RMAN_ARRAY;
     144        port_rman.rm_descr = "I/O ports";
     145        if (rman_init(&port_rman)
     146            || rman_manage_region(&port_rman, 0, 0xffff))
     147                panic("nexus_init_resources port_rman");
     148
     149        mem_rman.rm_start = 0;
     150        mem_rman.rm_end = ~0u;
     151        mem_rman.rm_type = RMAN_ARRAY;
     152        mem_rman.rm_descr = "I/O memory addresses";
     153        if (rman_init(&mem_rman)
     154            || rman_manage_region(&mem_rman, 0, ~0))
     155                panic("nexus_init_resources mem_rman");
     156}
     157
     158static int
     159nexus_attach(device_t dev)
     160{
     161
     162        nexus_init_resources();
     163        bus_generic_probe(dev);
     164
     165        /*
     166         * Explicitly add the legacy0 device here.  Other platform
     167         * types (such as ACPI), use their own nexus(4) subclass
     168         * driver to override this routine and add their own root bus.
     169         */
     170        if (BUS_ADD_CHILD(dev, 10, "legacy", 0) == NULL)
     171                panic("legacy: could not attach");
     172        bus_generic_attach(dev);
     173        return 0;
     174}
    49175
    50176static int
     
    52178{
    53179        size_t unit = 0;
    54 
     180#if 0
    55181        /* FIXME */
    56182        for (unit = 0; _bsd_nexus_devices [unit] != NULL; ++unit) {
    57183                device_add_child(dev, _bsd_nexus_devices [unit], unit);
    58184        }
    59 
     185#endif
    60186        device_set_desc(dev, "RTEMS Nexus device");
    61187
    62188        return (0);
    63189}
     190static device_t
     191nexus_add_child(device_t bus, u_int order, const char *name, int unit)
     192{
     193        device_t                child;
     194        struct nexus_device     *ndev;
     195
     196        ndev = malloc(sizeof(struct nexus_device), M_NEXUSDEV, M_NOWAIT|M_ZERO);
     197        if (!ndev)
     198                return(0);
     199        resource_list_init(&ndev->nx_resources);
     200
     201        child = device_add_child_ordered(bus, order, name, unit);
     202
     203        /* should we free this in nexus_child_detached? */
     204        device_set_ivars(child, ndev);
     205
     206        return(child);
     207}
     208
     209/*
     210 * Allocate a resource on behalf of child.  NB: child is usually going to be a
     211 * child of one of our descendants, not a direct child of nexus0.
     212 * (Exceptions include npx.)
     213 */
     214static struct resource *
     215nexus_alloc_resource(device_t bus, device_t child, int type, int *rid,
     216                     u_long start, u_long end, u_long count, u_int flags)
     217{
     218        struct nexus_device *ndev = DEVTONX(child);
     219        struct  resource *rv;
     220        struct resource_list_entry *rle;
     221        struct  rman *rm;
     222        int needactivate = flags & RF_ACTIVE;
     223
     224        /*
     225         * If this is an allocation of the "default" range for a given RID, and
     226         * we know what the resources for this device are (ie. they aren't maintained
     227         * by a child bus), then work out the start/end values.
     228         */
     229        if ((start == 0UL) && (end == ~0UL) && (count == 1)) {
     230                if (ndev == NULL)
     231                        return(NULL);
     232                rle = resource_list_find(&ndev->nx_resources, type, *rid);
     233                if (rle == NULL)
     234                        return(NULL);
     235                start = rle->start;
     236                end = rle->end;
     237                count = rle->count;
     238        }
     239
     240        flags &= ~RF_ACTIVE;
     241
     242        switch (type) {
     243        case SYS_RES_IRQ:
     244printf( "nexus_alloc_resource: IRQ\n" );
     245                rm = &irq_rman;
     246                break;
     247
     248        case SYS_RES_DRQ:
     249printf( "nexus_alloc_resource: DRQ\n" );
     250                rm = &drq_rman;
     251                break;
     252
     253        case SYS_RES_IOPORT:
     254printf( "nexus_alloc_resource: IO\n" );
     255                rm = &port_rman;
     256                break;
     257
     258        case SYS_RES_MEMORY:
     259printf( "nexus_alloc_resource: Memory\n" );
     260                rm = &mem_rman;
     261                break;
     262
     263        default:
     264                return 0;
     265        }
     266
     267        rv = rman_reserve_resource(rm, start, end, count, flags, child);
     268printf( "nexus_alloc_resource: rman_reserve_resource ==> %d\n", rv );
     269        if (rv == 0)
     270                return 0;
     271        rman_set_rid(rv, *rid);
     272
     273        if (needactivate) {
     274                if (bus_activate_resource(child, type, *rid, rv)) {
     275printf( "nexus_alloc_resource: bus_activate_resource failed\n", rv );
     276                        rman_release_resource(rv);
     277                        return 0;
     278                }
     279        }
     280
     281        return rv;
     282}
     283
     284static int
     285nexus_activate_resource(device_t bus, device_t child, int type, int rid,
     286                        struct resource *r)
     287{
     288#ifdef PC98
     289        bus_space_handle_t bh;
     290        int error;
     291#endif
     292        void *vaddr;
     293
     294        /*
     295         * If this is a memory resource, map it into the kernel.
     296         */
     297        switch (type) {
     298        case SYS_RES_IOPORT:
     299#ifdef PC98
     300                error = i386_bus_space_handle_alloc(I386_BUS_SPACE_IO,
     301                    rman_get_start(r), rman_get_size(r), &bh);
     302                if (error)
     303                        return (error);
     304                rman_set_bushandle(r, bh);
     305#else
     306                rman_set_bushandle(r, rman_get_start(r));
     307#endif
     308                rman_set_bustag(r, BUS_SPACE_IO);
     309                break;
     310        case SYS_RES_MEMORY:
     311#ifdef PC98
     312                error = i386_bus_space_handle_alloc(I386_BUS_SPACE_MEM,
     313                    rman_get_start(r), rman_get_size(r), &bh);
     314                if (error)
     315                        return (error);
     316#endif
     317                rman_set_bustag(r, BUS_SPACE_MEM);
     318#ifdef PC98
     319                /* PC-98: the type of bus_space_handle_t is the structure. */
     320                bh->bsh_base = (bus_addr_t) vaddr;
     321                rman_set_bushandle(r, bh);
     322#else
     323                /* IBM-PC: the type of bus_space_handle_t is u_int */
     324                rman_set_bushandle(r, (bus_space_handle_t) vaddr);
     325#endif
     326        }
     327        return (rman_activate_resource(r));
     328}
     329
     330static int
     331nexus_deactivate_resource(device_t bus, device_t child, int type, int rid,
     332                          struct resource *r)
     333{
     334
     335#ifdef PC98
     336        if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
     337                bus_space_handle_t bh;
     338
     339                bh = rman_get_bushandle(r);
     340                i386_bus_space_handle_free(rman_get_bustag(r), bh, bh->bsh_sz);
     341        }
     342#endif
     343        return (rman_deactivate_resource(r));
     344}
     345
     346static int
     347nexus_release_resource(device_t bus, device_t child, int type, int rid,
     348                       struct resource *r)
     349{
     350        if (rman_get_flags(r) & RF_ACTIVE) {
     351                int error = bus_deactivate_resource(child, type, rid, r);
     352                if (error)
     353                        return error;
     354        }
     355        return (rman_release_resource(r));
     356}
     357
    64358
    65359static device_method_t nexus_methods [] = {
    66360        /* Device interface */
    67361        DEVMETHOD(device_probe, nexus_probe),
    68         DEVMETHOD(device_attach, bus_generic_attach),
     362        DEVMETHOD(device_attach, nexus_attach),
    69363        DEVMETHOD(device_detach, bus_generic_detach),
    70364        DEVMETHOD(device_shutdown, bus_generic_shutdown),
     
    74368        /* Bus interface */
    75369        DEVMETHOD(bus_print_child, bus_generic_print_child),
     370        DEVMETHOD(bus_add_child,        nexus_add_child),
     371        DEVMETHOD(bus_alloc_resource,   nexus_alloc_resource),
     372        DEVMETHOD(bus_release_resource, nexus_release_resource),
     373        DEVMETHOD(bus_activate_resource, nexus_activate_resource),
     374        DEVMETHOD(bus_deactivate_resource, nexus_deactivate_resource),
    76375
    77376        { 0, 0 }
  • rtemsbsd/src/rtems-bsd-pci_bus.c

    ra0da9b6 r1e36900  
    5353#include <freebsd/local/pcib_if.h>
    5454#include <rtems/pci.h>
     55#include <freebsd/machine/bus.h>
    5556
    5657int
Note: See TracChangeset for help on using the changeset viewer.