Changeset 369e2c4 in rtems-libbsd


Ignore:
Timestamp:
Nov 13, 2013, 11:51:17 AM (7 years ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
4.11, b96abfd647154f10ea8f7fac68e25676636eded5, debc0aed8b9bef9996b8ec0ae7a70b0b41912e27, 68e79b6d187fe09b0a6f3f1d22c69b4121a3f76e, freebsd-9.3, 33bfaee89aa71d2252eb48d6b9a9ec17183faced
Children:
bb39e92
Parents:
b41556e
git-author:
Sebastian Huber <sebastian.huber@…> (11/13/13 11:51:17)
git-committer:
Sebastian Huber <sebastian.huber@…> (11/13/13 13:10:35)
Message:

nexus: Add table based Nexus device initialization

Files:
1 added
4 edited

Legend:

Unmodified
Added
Removed
  • Makefile

    rb41556e r369e2c4  
    9393LIB_C_FILES += rtemsbsd/sys/dev/usb/controller/ohci_lpc24xx.c
    9494LIB_C_FILES += rtemsbsd/sys/dev/usb/controller/ohci_lpc32xx.c
     95LIB_C_FILES += rtemsbsd/bsp/bsp-bsd-nexus-devices.c
    9596LIB_GEN_FILES += rtemsbsd/rtems/rtems-kvm-symbols.c
    9697LIB_C_FILES += rtemsbsd/rtems/rtems-kvm-symbols.c
  • freebsd-to-rtems.py

    rb41556e r369e2c4  
    655655                'sys/dev/usb/controller/ohci_lpc24xx.c',
    656656                'sys/dev/usb/controller/ohci_lpc32xx.c',
     657                'bsp/bsp-bsd-nexus-devices.c',
    657658        ]
    658659)
  • rtemsbsd/include/rtems/bsd/bsd.h

    rb41556e r369e2c4  
    4747#include <rtems.h>
    4848
     49typedef enum {
     50        RTEMS_BSD_RES_IRQ = 1,
     51        RTEMS_BSD_RES_MEMORY = 3
     52} rtems_bsd_device_resource_type;
     53
     54typedef struct {
     55        rtems_bsd_device_resource_type type;
     56        unsigned long start_request;
     57        unsigned long start_actual;
     58} rtems_bsd_device_resource;
     59
     60typedef struct {
     61        const char *name;
     62        int unit;
     63        size_t resource_count;
     64        const rtems_bsd_device_resource *resources;
     65} rtems_bsd_device;
     66
     67extern const rtems_bsd_device rtems_bsd_nexus_devices[];
     68
     69extern const size_t rtems_bsd_nexus_device_count;
     70
    4971rtems_status_code rtems_bsd_initialize(void);
    5072
  • rtemsbsd/rtems/rtems-bsd-nexus.c

    rb41556e r369e2c4  
    88
    99/*
    10  * Copyright (c) 2009, 2010 embedded brains GmbH.  All rights reserved.
     10 * Copyright (c) 2009-2013 embedded brains GmbH.  All rights reserved.
    1111 *
    1212 *  embedded brains GmbH
    13  *  Obere Lagerstr. 30
     13 *  Dornierstr. 4
    1414 *  82178 Puchheim
    1515 *  Germany
     
    3939
    4040#include <machine/rtems-bsd-kernel-space.h>
    41 #include <machine/rtems-bsd-sysinit.h>
    4241
    4342#include <rtems/bsd/sys/param.h>
     
    5049#include <sys/malloc.h>
    5150
    52 #include <bsp.h>
    53 #include <machine/rtems-bsd-devicet.h>
    54 #include <bsp/irq.h>
    55 #include <rtems/irq.h>
     51#include <rtems/bsd/bsd.h>
    5652#include <rtems/irq-extension.h>
    57 #include <machine/bus.h>
    58 
    59 /* XXX Note:  These defines should be moved. */
    60 #if defined(__i386__)
    61   #define       BUS_SPACE_IO    I386_BUS_SPACE_IO
    62   #define       BUS_SPACE_MEM   I386_BUS_SPACE_MEM
    63 #elif defined(__amd64__)
    64   #define       BUS_SPACE_IO    AMD64_BUS_SPACE_IO
    65   #define       BUS_SPACE_MEM   AMD64_BUS_SPACE_MEM
    66 #else
    67   #warning "Bus space information not implemented for this architecture!!"
    68   #warning "Defaulting Bus space information!!"
    69   #define       BUS_SPACE_IO    0       
    70   #define       BUS_SPACE_MEM   1
    71 #endif
    72 
    73 /* XXX - Just a guess */
    74 #define NUM_IO_INTS   30
    75 
    76 #define DEVTONX(dev)    ((struct nexus_device *)device_get_ivars(dev))
    77 
    78 static MALLOC_DEFINE(M_NEXUSDEV, "nexusdev", "Nexus device");
    79 struct rman irq_rman, drq_rman, port_rman, mem_rman;
    80 struct nexus_device {
    81         struct resource_list    nx_resources;
    82 };
    83 
    84 void
    85 nexus_init_resources(void)
    86 {
    87         int irq;
    88 
    89         /*
    90          * XXX working notes:
    91          *
    92          * - IRQ resource creation should be moved to the PIC/APIC driver.
    93          * - DRQ resource creation should be moved to the DMAC driver.
    94          * - The above should be sorted to probe earlier than any child busses.
    95          *
    96          * - Leave I/O and memory creation here, as child probes may need them.
    97          *   (especially eg. ACPI)
    98          */
    99 
    100         /*
    101          * IRQ's are on the mainboard on old systems, but on the ISA part
    102          * of PCI->ISA bridges.  There would be multiple sets of IRQs on
    103          * multi-ISA-bus systems.  PCI interrupts are routed to the ISA
    104          * component, so in a way, PCI can be a partial child of an ISA bus(!).
    105          * APIC interrupts are global though.
    106          */
    107         irq_rman.rm_start = 0;
    108         irq_rman.rm_type = RMAN_ARRAY;
    109         irq_rman.rm_descr = "Interrupt request lines";
    110         irq_rman.rm_end = NUM_IO_INTS - 1;
    111         if (rman_init(&irq_rman))
    112                 panic("nexus_init_resources irq_rman");
    113         /*
    114          * We search for regions of existing IRQs and add those to the IRQ
    115          * resource manager.
    116          */
    117         for (irq = 0; irq < NUM_IO_INTS; irq++)
    118           if (rman_manage_region(&irq_rman, irq, irq) != 0)
    119             panic("nexus_init_resources irq_rmand");
    120  
    121         /*
    122          * ISA DMA on PCI systems is implemented in the ISA part of each
    123          * PCI->ISA bridge and the channels can be duplicated if there are
    124          * multiple bridges.  (eg: laptops with docking stations)
    125          */
    126         drq_rman.rm_start = 0;
    127 #ifdef PC98
    128         drq_rman.rm_end = 3;
    129 #else
    130         drq_rman.rm_end = 7;
    131 #endif
    132         drq_rman.rm_type = RMAN_ARRAY;
    133         drq_rman.rm_descr = "DMA request lines";
    134         /* XXX drq 0 not available on some machines */
    135         if (rman_init(&drq_rman)
    136             || rman_manage_region(&drq_rman,
    137                                   drq_rman.rm_start, drq_rman.rm_end))
    138                 panic("nexus_init_resources drq_rman");
    139 
    140         /*
    141          * However, IO ports and Memory truely are global at this level,
    142          * as are APIC interrupts (however many IO APICS there turn out
    143          * to be on large systems..)
    144          */
    145         port_rman.rm_start = 0;
    146         port_rman.rm_end = 0xffff;
    147         port_rman.rm_type = RMAN_ARRAY;
    148         port_rman.rm_descr = "I/O ports";
    149         if (rman_init(&port_rman)
    150             || rman_manage_region(&port_rman, 0, 0xffff))
    151                 panic("nexus_init_resources port_rman");
     53
     54RTEMS_STATIC_ASSERT(SYS_RES_MEMORY == RTEMS_BSD_RES_MEMORY, RTEMS_BSD_RES_MEMORY);
     55
     56RTEMS_STATIC_ASSERT(SYS_RES_IRQ == RTEMS_BSD_RES_IRQ, RTEMS_BSD_RES_IRQ);
     57
     58static struct rman mem_rman;
     59
     60static struct rman irq_rman;
     61
     62static int
     63nexus_probe(device_t dev)
     64{
     65        int err;
     66        size_t i;
     67
     68        device_set_desc(dev, "RTEMS Nexus device");
    15269
    15370        mem_rman.rm_start = 0;
    154         mem_rman.rm_end = ~0u;
     71        mem_rman.rm_end = ~0UL;
    15572        mem_rman.rm_type = RMAN_ARRAY;
    15673        mem_rman.rm_descr = "I/O memory addresses";
    157         if (rman_init(&mem_rman)
    158             || rman_manage_region(&mem_rman, 0, ~0))
    159                 panic("nexus_init_resources mem_rman");
    160 }
    161 
    162 static int
    163 nexus_attach(device_t dev)
    164 {
    165 
    166         nexus_init_resources();
    167         bus_generic_probe(dev);
    168 
    169         /*
    170          * Explicitly add the legacy0 device here.  Other platform
    171          * types (such as ACPI), use their own nexus(4) subclass
    172          * driver to override this routine and add their own root bus.
    173          */
    174         if (BUS_ADD_CHILD(dev, 10, "legacy", 0) == NULL)
    175                 panic("legacy: could not attach");
    176         bus_generic_attach(dev);
    177         return 0;
    178 }
    179 
    180 static int
    181 nexus_probe(device_t dev)
    182 {
    183 #if 0
    184         /* FIXME */
    185         size_t unit = 0;
    186 
    187         for (unit = 0; _bsd_nexus_devices [unit] != NULL; ++unit) {
    188                 device_add_child(dev, _bsd_nexus_devices [unit], unit);
    189         }
    190 #endif
    191         device_set_desc(dev, "RTEMS Nexus device");
     74        err = rman_init(&mem_rman) != 0;
     75        BSD_ASSERT(err == 0);
     76        err = rman_manage_region(&mem_rman, mem_rman.rm_start, mem_rman.rm_end);
     77        BSD_ASSERT(err == 0);
     78
     79        irq_rman.rm_start = 0;
     80        irq_rman.rm_end = ~0UL;
     81        irq_rman.rm_type = RMAN_ARRAY;
     82        irq_rman.rm_descr = "Interrupt vectors";
     83        err = rman_init(&irq_rman) != 0;
     84        BSD_ASSERT(err == 0);
     85        err = rman_manage_region(&irq_rman, irq_rman.rm_start, irq_rman.rm_end);
     86        BSD_ASSERT(err == 0);
     87
     88        for (i = 0; i < rtems_bsd_nexus_device_count; ++i) {
     89                const rtems_bsd_device *nd = &rtems_bsd_nexus_devices[i];
     90
     91                device_add_child(dev, nd->name, nd->unit);
     92        }
    19293
    19394        return (0);
    19495}
    195 static device_t
    196 nexus_add_child(device_t bus, u_int order, const char *name, int unit)
    197 {
    198         device_t                child;
    199         struct nexus_device     *ndev;
    200 
    201         ndev = malloc(sizeof(struct nexus_device), M_NEXUSDEV, M_NOWAIT|M_ZERO);
    202         if (!ndev)
    203                 return(0);
    204         resource_list_init(&ndev->nx_resources);
    205 
    206         child = device_add_child_ordered(bus, order, name, unit);
    207 
    208         /* should we free this in nexus_child_detached? */
    209         device_set_ivars(child, ndev);
    210 
    211         return(child);
    212 }
    213 
    214 /*
    215  * Allocate a resource on behalf of child.  NB: child is usually going to be a
    216  * child of one of our descendants, not a direct child of nexus0.
    217  * (Exceptions include npx.)
    218  */
     96
     97static bool
     98nexus_get_start(const rtems_bsd_device *nd, int type, u_long *start)
     99{
     100        u_long sr = *start;
     101        size_t i;
     102
     103        for (i = 0; i < nd->resource_count; ++i) {
     104                const rtems_bsd_device_resource *dr = &nd->resources[i];
     105
     106                if (dr->type == type && dr->start_request == sr) {
     107                        *start = dr->start_actual;
     108
     109                        return (true);
     110                }
     111        }
     112
     113        return (false);
     114}
     115
    219116static struct resource *
    220117nexus_alloc_resource(device_t bus, device_t child, int type, int *rid,
    221                      u_long start, u_long end, u_long count, u_int flags)
    222 {
    223         struct nexus_device *ndev = DEVTONX(child);
    224         struct  resource *rv;
    225         struct resource_list_entry *rle;
    226         struct  rman *rm;
    227         int needactivate = flags & RF_ACTIVE;
    228 
    229         /*
    230          * If this is an allocation of the "default" range for a given RID, and
    231          * we know what the resources for this device are (ie. they aren't maintained
    232          * by a child bus), then work out the start/end values.
    233          */
    234         if ((start == 0UL) && (end == ~0UL) && (count == 1)) {
    235                 if (ndev == NULL)
    236                         return(NULL);
    237                 rle = resource_list_find(&ndev->nx_resources, type, *rid);
    238                 if (rle == NULL)
    239                         return(NULL);
    240                 start = rle->start;
    241                 end = rle->end;
    242                 count = rle->count;
    243         }
    244 
    245         flags &= ~RF_ACTIVE;
     118    u_long start, u_long end, u_long count, u_int flags)
     119{
     120        struct resource *rv;
     121        struct rman *rm;
     122        size_t i;
    246123
    247124        switch (type) {
     125        case SYS_RES_MEMORY:
     126                rm = &mem_rman;
     127                break;
    248128        case SYS_RES_IRQ:
    249129                rm = &irq_rman;
    250130                break;
    251 
    252         case SYS_RES_DRQ:
    253                 rm = &drq_rman;
    254                 break;
    255 
    256         case SYS_RES_IOPORT:
    257                 rm = &port_rman;
    258                 break;
    259 
    260         case SYS_RES_MEMORY:
    261                 rm = &mem_rman;
    262                 break;
    263 
    264131        default:
    265                 return 0;
     132                return (NULL);
     133        }
     134
     135        for (i = 0; i < rtems_bsd_nexus_device_count; ++i) {
     136                const rtems_bsd_device *nd = &rtems_bsd_nexus_devices[i];
     137
     138                if (strcmp(device_get_name(child), nd->name) == 0
     139                    && device_get_unit(child) == nd->unit) {
     140                        if (!nexus_get_start(nd, type, &start)) {
     141                                return (NULL);
     142                        };
     143                } else {
     144                        return (NULL);
     145                }
    266146        }
    267147
    268148        rv = rman_reserve_resource(rm, start, end, count, flags, child);
    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)) {
    275                         rman_release_resource(rv);
    276                         return 0;
    277                 }
    278         }
    279 
    280         return rv;
    281 }
    282 
    283 static int
    284 nexus_activate_resource(device_t bus, device_t child, int type, int rid,
    285                         struct resource *r)
    286 {
    287 #ifdef PC98
    288         bus_space_handle_t bh;
    289         int error;
    290 #endif
    291         void *vaddr;
    292 
    293         /*
    294          * If this is a memory resource, map it into the kernel.
    295          */
    296         switch (type) {
    297         case SYS_RES_IOPORT:
    298 #ifdef PC98
    299                 error = i386_bus_space_handle_alloc(I386_BUS_SPACE_IO,
    300                     rman_get_start(r), rman_get_size(r), &bh);
    301                 if (error)
    302                         return (error);
    303                 rman_set_bushandle(r, bh);
    304 #else
    305                 rman_set_bushandle(r, rman_get_start(r));
    306 #endif
    307                 rman_set_bustag(r, BUS_SPACE_IO);
    308                 break;
    309         case SYS_RES_MEMORY:
    310 #ifdef PC98
    311                 error = i386_bus_space_handle_alloc(I386_BUS_SPACE_MEM,
    312                     rman_get_start(r), rman_get_size(r), &bh);
    313                 if (error)
    314                         return (error);
    315 #endif
    316                 rman_set_bustag(r, BUS_SPACE_MEM);
    317 #ifdef PC98
    318                 /* PC-98: the type of bus_space_handle_t is the structure. */
    319                 bh->bsh_base = (bus_addr_t) vaddr;
    320                 rman_set_bushandle(r, bh);
    321 #else
    322                 /* IBM-PC: the type of bus_space_handle_t is u_int */
    323                 rman_set_bushandle(r, (bus_space_handle_t) vaddr);
    324 #endif
    325         }
    326         return (rman_activate_resource(r));
    327 }
    328 
    329 static int
    330 nexus_deactivate_resource(device_t bus, device_t child, int type, int rid,
    331                           struct resource *r)
    332 {
    333 
    334 #ifdef PC98
    335         if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
    336                 bus_space_handle_t bh;
    337 
    338                 bh = rman_get_bushandle(r);
    339                 i386_bus_space_handle_free(rman_get_bustag(r), bh, bh->bsh_sz);
    340         }
    341 #endif
    342         return (rman_deactivate_resource(r));
     149        if (rv != NULL) {
     150                rman_set_rid(rv, *rid);
     151                rman_set_bushandle(rv, rman_get_start(rv));
     152        }
     153
     154        return (rv);
    343155}
    344156
    345157static int
    346158nexus_release_resource(device_t bus, device_t child, int type, int rid,
    347                        struct resource *r)
    348 {
    349         if (rman_get_flags(r) & RF_ACTIVE) {
    350                 int error = bus_deactivate_resource(child, type, rid, r);
    351                 if (error)
    352                         return error;
    353         }
    354         return (rman_release_resource(r));
    355 }
    356 
    357 static int
    358 bspExtInstallSharedISR(int irqLine, void (*isr)(void *), void * uarg, int flags)
    359 {
    360   return rtems_interrupt_handler_install(
    361     irqLine,
    362     "BSD Interrupt",
    363     RTEMS_INTERRUPT_SHARED,
    364     isr,
    365     uarg
    366   );
    367 }
    368 
    369 int
    370 intr_add_handler(const char *name, int vector, driver_filter_t filter,
    371     driver_intr_t handler, void *arg, enum intr_type flags, void **cookiep)
    372 {
    373   int  rval;
    374  
    375   rval = bspExtInstallSharedISR(vector, handler, arg, 0);
    376   return rval;
    377 }
    378 
    379 static int
    380 nexus_setup_intr(device_t bus, device_t child, struct resource *irq,
    381                  int flags, driver_filter_t filter, void (*ihand)(void *),
    382                  void *arg, void **cookiep)
    383 {
    384         int             error;
    385 
    386         /* somebody tried to setup an irq that failed to allocate! */
    387         if (irq == NULL)
    388                 panic("nexus_setup_intr: NULL irq resource!");
    389 
    390         *cookiep = 0;
    391         if ((rman_get_flags(irq) & RF_SHAREABLE) == 0)
    392                 flags |= INTR_EXCL;
    393 
    394         /*
    395          * We depend here on rman_activate_resource() being idempotent.
    396          */
    397         error = rman_activate_resource(irq);
    398         if (error)
    399                 return (error);
    400 
    401         error = intr_add_handler(device_get_nameunit(child),
    402             rman_get_start(irq), filter, ihand, arg, flags, cookiep);
    403 
    404         return (error);
    405 }
    406 
    407 
    408 static device_method_t nexus_methods [] = {
     159    struct resource *res)
     160{
     161        return (rman_release_resource(res));
     162}
     163
     164struct nexus_intr {
     165        driver_filter_t *filt;
     166        driver_intr_t *intr;
     167        void *arg;
     168};
     169
     170static void
     171nexus_intr_with_filter(void *arg)
     172{
     173        struct nexus_intr *ni;
     174        int status;
     175
     176        ni = arg;
     177
     178        status = (*ni->filt)(ni->arg);
     179        if ((status & FILTER_SCHEDULE_THREAD) != 0) {
     180                (*ni->intr)(ni->arg);
     181        }
     182}
     183
     184static int
     185nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags,
     186    driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep)
     187{
     188        int err;
     189        struct nexus_intr *ni;
     190
     191        ni = malloc(sizeof(*ni), M_TEMP, M_WAITOK);
     192        if (ni != NULL) {
     193                rtems_status_code sc;
     194                rtems_interrupt_handler rh;
     195                void *ra;
     196
     197                ni->filt = filt;
     198                ni->intr = intr;
     199                ni->arg = arg;
     200
     201                *cookiep = ni;
     202
     203                if (filt == NULL) {
     204                        rh = intr;
     205                        ra = arg;
     206                } else {
     207                        rh = nexus_intr_with_filter;
     208                        ra = ni;
     209                }
     210
     211                sc = rtems_interrupt_server_handler_install(RTEMS_ID_NONE,
     212                    rman_get_start(res), device_get_nameunit(child),
     213                    RTEMS_INTERRUPT_UNIQUE, rh, ra);
     214                if (sc == RTEMS_SUCCESSFUL) {
     215                        err = 0;
     216                } else {
     217                        free(ni, M_TEMP);
     218
     219                        err = EINVAL;
     220                }
     221        } else {
     222                err = ENOMEM;
     223        }
     224
     225        return (err);
     226}
     227
     228static int
     229nexus_teardown_intr(device_t dev, device_t child, struct resource *res,
     230    void *cookie)
     231{
     232        int err;
     233        struct nexus_intr *ni;
     234        rtems_status_code sc;
     235        rtems_interrupt_handler rh;
     236        void *ra;
     237
     238        ni = cookie;
     239
     240        if (ni->filt == NULL) {
     241                rh = ni->intr;
     242                ra = ni->arg;
     243        } else {
     244                rh = nexus_intr_with_filter;
     245                ra = ni->arg;
     246        }
     247
     248        sc = rtems_interrupt_server_handler_install(RTEMS_ID_NONE,
     249            rman_get_start(res), device_get_nameunit(child),
     250            RTEMS_INTERRUPT_UNIQUE, rh, ra);
     251        err = sc == RTEMS_SUCCESSFUL ? 0 : EINVAL;
     252
     253        return (err);
     254}
     255
     256static device_method_t nexus_methods[] = {
    409257        /* Device interface */
    410258        DEVMETHOD(device_probe, nexus_probe),
    411         DEVMETHOD(device_attach, nexus_attach),
     259        DEVMETHOD(device_attach, bus_generic_attach),
    412260        DEVMETHOD(device_detach, bus_generic_detach),
    413261        DEVMETHOD(device_shutdown, bus_generic_shutdown),
     
    417265        /* Bus interface */
    418266        DEVMETHOD(bus_print_child, bus_generic_print_child),
    419         DEVMETHOD(bus_add_child,        nexus_add_child),
    420         DEVMETHOD(bus_alloc_resource,   nexus_alloc_resource),
    421         DEVMETHOD(bus_release_resource, nexus_release_resource),
    422         DEVMETHOD(bus_activate_resource, nexus_activate_resource),
    423         DEVMETHOD(bus_deactivate_resource, nexus_deactivate_resource),
    424         DEVMETHOD(bus_setup_intr,       nexus_setup_intr),
     267        DEVMETHOD(bus_add_child, bus_generic_add_child),
     268        DEVMETHOD(bus_alloc_resource, nexus_alloc_resource),
     269        DEVMETHOD(bus_release_resource, nexus_release_resource),
     270        DEVMETHOD(bus_setup_intr, nexus_setup_intr),
     271        DEVMETHOD(bus_teardown_intr, nexus_teardown_intr),
    425272
    426273        { 0, 0 }
Note: See TracChangeset for help on using the changeset viewer.