source: rtems-libbsd/rtemsbsd/rtems/rtems-bsd-nexus.c @ e51bc97

4.1155-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since e51bc97 was e51bc97, checked in by Sebastian Huber <sebastian.huber@…>, on Dec 20, 2013 at 12:26:03 PM

Delete rtems_bsd_initialize_with_interrupt_server

Move interrupt server initialization to nexus_probe().

  • Property mode set to 100644
File size: 6.9 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup rtems_bsd_rtems
5 *
6 * @brief TODO.
7 */
8
9/*
10 * Copyright (c) 2009-2013 embedded brains GmbH.  All rights reserved.
11 *
12 *  embedded brains GmbH
13 *  Dornierstr. 4
14 *  82178 Puchheim
15 *  Germany
16 *  <rtems@embedded-brains.de>
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions
20 * are met:
21 * 1. Redistributions of source code must retain the above copyright
22 *    notice, this list of conditions and the following disclaimer.
23 * 2. Redistributions in binary form must reproduce the above copyright
24 *    notice, this list of conditions and the following disclaimer in the
25 *    documentation and/or other materials provided with the distribution.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE.
38 */
39
40#include <machine/rtems-bsd-kernel-space.h>
41#include <machine/rtems-bsd-thread.h>
42
43#include <rtems/bsd/sys/param.h>
44#include <rtems/bsd/sys/types.h>
45#include <sys/systm.h>
46#include <sys/bus.h>
47#include <sys/kernel.h>
48#include <sys/module.h>
49#include <sys/rman.h>
50#include <sys/malloc.h>
51
52#include <rtems/bsd/bsd.h>
53#include <rtems/irq-extension.h>
54
55RTEMS_STATIC_ASSERT(SYS_RES_MEMORY == RTEMS_BSD_RES_MEMORY, RTEMS_BSD_RES_MEMORY);
56
57RTEMS_STATIC_ASSERT(SYS_RES_IRQ == RTEMS_BSD_RES_IRQ, RTEMS_BSD_RES_IRQ);
58
59static struct rman mem_rman;
60
61static struct rman irq_rman;
62
63static int
64nexus_probe(device_t dev)
65{
66        rtems_status_code status;
67        int err;
68        size_t i;
69
70        device_set_desc(dev, "RTEMS Nexus device");
71
72        status = rtems_interrupt_server_initialize(
73                BSD_TASK_PRIORITY_INTERRUPT,
74                BSD_MINIMUM_TASK_STACK_SIZE,
75                RTEMS_DEFAULT_MODES,
76                RTEMS_DEFAULT_ATTRIBUTES,
77                NULL
78        );
79        BSD_ASSERT(status == RTEMS_SUCCESSFUL);
80
81        mem_rman.rm_start = 0;
82        mem_rman.rm_end = ~0UL;
83        mem_rman.rm_type = RMAN_ARRAY;
84        mem_rman.rm_descr = "I/O memory addresses";
85        err = rman_init(&mem_rman) != 0;
86        BSD_ASSERT(err == 0);
87        err = rman_manage_region(&mem_rman, mem_rman.rm_start, mem_rman.rm_end);
88        BSD_ASSERT(err == 0);
89
90        irq_rman.rm_start = 0;
91        irq_rman.rm_end = ~0UL;
92        irq_rman.rm_type = RMAN_ARRAY;
93        irq_rman.rm_descr = "Interrupt vectors";
94        err = rman_init(&irq_rman) != 0;
95        BSD_ASSERT(err == 0);
96        err = rman_manage_region(&irq_rman, irq_rman.rm_start, irq_rman.rm_end);
97        BSD_ASSERT(err == 0);
98
99        for (i = 0; i < rtems_bsd_nexus_device_count; ++i) {
100                const rtems_bsd_device *nd = &rtems_bsd_nexus_devices[i];
101
102                device_add_child(dev, nd->name, nd->unit);
103        }
104
105        return (0);
106}
107
108static bool
109nexus_get_start(const rtems_bsd_device *nd, int type, u_long *start)
110{
111        u_long sr = *start;
112        size_t i;
113
114        for (i = 0; i < nd->resource_count; ++i) {
115                const rtems_bsd_device_resource *dr = &nd->resources[i];
116
117                if (dr->type == type && dr->start_request == sr) {
118                        *start = dr->start_actual;
119
120                        return (true);
121                }
122        }
123
124        return (false);
125}
126
127static struct resource *
128nexus_alloc_resource(device_t bus, device_t child, int type, int *rid,
129    u_long start, u_long end, u_long count, u_int flags)
130{
131        struct resource *rv;
132        struct rman *rm;
133        size_t i;
134
135        switch (type) {
136        case SYS_RES_MEMORY:
137                rm = &mem_rman;
138                break;
139        case SYS_RES_IRQ:
140                rm = &irq_rman;
141                break;
142        default:
143                return (NULL);
144        }
145
146        for (i = 0; i < rtems_bsd_nexus_device_count; ++i) {
147                const rtems_bsd_device *nd = &rtems_bsd_nexus_devices[i];
148
149                if (strcmp(device_get_name(child), nd->name) == 0
150                    && device_get_unit(child) == nd->unit) {
151                        if (!nexus_get_start(nd, type, &start)) {
152                                return (NULL);
153                        };
154                } else {
155                        return (NULL);
156                }
157        }
158
159        rv = rman_reserve_resource(rm, start, end, count, flags, child);
160        if (rv != NULL) {
161                rman_set_rid(rv, *rid);
162                rman_set_bushandle(rv, rman_get_start(rv));
163        }
164
165        return (rv);
166}
167
168static int
169nexus_release_resource(device_t bus, device_t child, int type, int rid,
170    struct resource *res)
171{
172        return (rman_release_resource(res));
173}
174
175struct nexus_intr {
176        driver_filter_t *filt;
177        driver_intr_t *intr;
178        void *arg;
179};
180
181static void
182nexus_intr_with_filter(void *arg)
183{
184        struct nexus_intr *ni;
185        int status;
186
187        ni = arg;
188
189        status = (*ni->filt)(ni->arg);
190        if ((status & FILTER_SCHEDULE_THREAD) != 0) {
191                (*ni->intr)(ni->arg);
192        }
193}
194
195static int
196nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags,
197    driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep)
198{
199        int err;
200        struct nexus_intr *ni;
201
202        ni = malloc(sizeof(*ni), M_TEMP, M_WAITOK);
203        if (ni != NULL) {
204                rtems_status_code sc;
205                rtems_interrupt_handler rh;
206                void *ra;
207
208                ni->filt = filt;
209                ni->intr = intr;
210                ni->arg = arg;
211
212                *cookiep = ni;
213
214                if (filt == NULL) {
215                        rh = intr;
216                        ra = arg;
217                } else {
218                        rh = nexus_intr_with_filter;
219                        ra = ni;
220                }
221
222                sc = rtems_interrupt_server_handler_install(RTEMS_ID_NONE,
223                    rman_get_start(res), device_get_nameunit(child),
224                    RTEMS_INTERRUPT_UNIQUE, rh, ra);
225                if (sc == RTEMS_SUCCESSFUL) {
226                        err = 0;
227                } else {
228                        free(ni, M_TEMP);
229
230                        err = EINVAL;
231                }
232        } else {
233                err = ENOMEM;
234        }
235
236        return (err);
237}
238
239static int
240nexus_teardown_intr(device_t dev, device_t child, struct resource *res,
241    void *cookie)
242{
243        int err;
244        struct nexus_intr *ni;
245        rtems_status_code sc;
246        rtems_interrupt_handler rh;
247        void *ra;
248
249        ni = cookie;
250
251        if (ni->filt == NULL) {
252                rh = ni->intr;
253                ra = ni->arg;
254        } else {
255                rh = nexus_intr_with_filter;
256                ra = ni->arg;
257        }
258
259        sc = rtems_interrupt_server_handler_install(RTEMS_ID_NONE,
260            rman_get_start(res), device_get_nameunit(child),
261            RTEMS_INTERRUPT_UNIQUE, rh, ra);
262        err = sc == RTEMS_SUCCESSFUL ? 0 : EINVAL;
263
264        return (err);
265}
266
267static device_method_t nexus_methods[] = {
268        /* Device interface */
269        DEVMETHOD(device_probe, nexus_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_print_child, bus_generic_print_child),
278        DEVMETHOD(bus_add_child, bus_generic_add_child),
279        DEVMETHOD(bus_alloc_resource, nexus_alloc_resource),
280        DEVMETHOD(bus_release_resource, nexus_release_resource),
281        DEVMETHOD(bus_setup_intr, nexus_setup_intr),
282        DEVMETHOD(bus_teardown_intr, nexus_teardown_intr),
283
284        { 0, 0 }
285};
286
287static driver_t nexus_driver = {
288        .name = "nexus",
289        .methods = nexus_methods,
290        .size = 0
291};
292
293static devclass_t nexus_devclass;
294
295DRIVER_MODULE(nexus, root, nexus_driver, nexus_devclass, 0, 0);
Note: See TracBrowser for help on using the repository browser.