source: libbsdport/bsd_eth_drivers/libbsdport/sysbus.c @ a8bf95d

B_20100615baselibbsdport-4-10-branch
Last change on this file since a8bf95d was a8bf95d, checked in by Till Straumann <strauman@…>, on Apr 22, 2009 at 10:06:58 PM
  • importing updated version from SLAC as of 20090422
  • Property mode set to 100644
File size: 5.9 KB
Line 
1#include <rtems.h>
2#include <rtems/pci.h>
3#include <rtems/error.h>
4#include <sys/errno.h>
5#include <bsp.h>
6#include <devicet.h>
7#include <bsp/irq.h>
8#include <rtems/irq.h>
9
10#include <sys/taskqueue.h>
11
12#include <sys/bus.h>
13#include <sys/malloc.h>
14
15#include <bsp/rtems_verscheck.h>
16
17#if !RTEMS_REV_AT_LEAST(4,6,99) || !defined(BSP_SHARED_HANDLER_SUPPORT)
18
19#include <bsp/bspExt.h>
20
21#else
22
23static void noop(const rtems_irq_connect_data *unused) {};
24static int  noop1(const rtems_irq_connect_data *unused) { return 0;};
25
26/* Finally have an ISR arg but the API still sucks.. */
27static int
28bspExtInstallSharedISR(int irqLine, void (*isr)(void *), void * uarg, int flags)
29{
30rtems_irq_connect_data suck = {0};
31        suck.name   = irqLine;
32        suck.hdl    = isr;
33        suck.handle = uarg;
34        suck.on     = noop;
35        suck.off    = noop;
36        suck.isOn   = noop1;
37        return ! BSP_install_rtems_shared_irq_handler(&suck);
38}
39
40static int
41bspExtRemoveSharedISR(int irqLine, void (*isr)(void *), void *uarg)
42{
43rtems_irq_connect_data suck = {0};
44        suck.name   = irqLine;
45        suck.hdl    = isr;
46        suck.handle = uarg;
47        suck.on     = noop;
48        suck.off    = noop;
49        suck.isOn   = noop1;
50        return ! BSP_remove_rtems_irq_handler(&suck);
51}
52#endif
53
54
55struct resource *
56bus_alloc_resource_any(device_t dev, int type, int *prid, unsigned flags)
57{
58bus_addr_t ba;
59int        isio;
60        switch ( type ) {
61                default:
62                        break;
63                case SYS_RES_IOPORT:
64                case SYS_RES_MEMORY:
65                        {
66                        libbsdport_u32_t d;
67                        pci_read_config_dword(
68                                dev->bushdr.pci.bus,
69                                dev->bushdr.pci.dev,
70                                dev->bushdr.pci.fun,
71                                *prid,
72                                &d);
73                        ba = d;
74                        isio = (ba & PCI_BASE_ADDRESS_SPACE_IO) ? 1 : 0;
75                        if ( (type == SYS_RES_IOPORT) != (isio != 0) )
76                                return 0;       /* wrong type */
77
78                        return (struct resource *) ba;
79                        }
80                case SYS_RES_IRQ:
81                        {
82                        uint8_t line;
83                        pci_read_config_byte(
84                                dev->bushdr.pci.bus,
85                                dev->bushdr.pci.dev,
86                                dev->bushdr.pci.fun,
87                                PCI_INTERRUPT_LINE,
88                                &line);
89                        ba = line;
90                        /* MSI not implemented */
91                        return (struct resource*) ba;
92                        }
93        }
94        rtems_panic("bus_alloc_resource_any: unknown/unimplemented resource type %i\n", type);
95        /* never get here */
96        return (struct resource*)0;
97}
98
99struct irq_cookie {
100        device_t        dev;
101        driver_filter_t handler;
102        void                    (*work)(void*);
103        void            *arg;
104        /* cache methods */
105        int                             (*irq_check_dis)(device_t d);
106        void                    (*irq_en)       (device_t d);
107        struct task     task;
108};
109
110static int
111sysbus_isr(void *arg)
112{
113struct irq_cookie *info = arg;
114int rval;
115#ifdef DEBUG
116        printk("Sysbus IRQ\n");
117#endif
118        /* Check if we have an IRQ pending and disable further interrupts */
119        rval = info->irq_check_dis(info->dev);
120        if ( FILTER_HANDLED == rval ) {
121                /* enqueue work */
122                taskqueue_enqueue(taskqueue_fast, &info->task);
123        }
124        return rval;
125}
126
127static void
128sysbus_taskfn(void *arg, int pending)
129{
130struct irq_cookie *info = arg;
131       
132        /* do work */
133        info->work(info->arg);
134       
135        /* reenable interrupts */
136        if ( info->irq_en )
137                info->irq_en(info->dev);
138}
139
140int
141bus_setup_intr(device_t dev, struct resource *r, int flags, driver_filter_t filter, driver_intr_t handler, void *arg, void **cookiep)
142{
143int                rval;
144struct irq_cookie *info = 0;
145
146
147
148        if ( filter && handler ) {
149                rtems_panic("bus_setup_intr for both: filter & handler not implemented\n");
150        }
151
152        if ( handler ) {
153                if ( !dev->drv ) {
154                        device_printf(dev, "bus_setup_intr: device has no driver attached\n");
155                        return EINVAL;
156                } else if ( !dev->drv->methods->irq_check_dis ) {
157                        device_printf(dev, "bus_setup_intr: driver has no 'irq_dis' method\n");
158                        return EINVAL;
159                }
160        }
161
162        if ( ! (info = malloc(sizeof(*info), M_DEVBUF, M_NOWAIT)) )
163                return ENOMEM;
164
165        info->dev     = dev;
166        info->handler = filter;
167        info->work    = handler;
168        info->arg     = arg;
169
170        if ( handler ) {
171                TASK_INIT(&info->task, 0, sysbus_taskfn, info);
172                /* make sure taskqueue facility is initialized */
173                rtems_taskqueue_initialize();
174                /* install our own filter */
175                filter = sysbus_isr;
176                arg    = info;
177                info->irq_check_dis = dev->drv->methods->irq_check_dis;
178                info->irq_en        = dev->drv->methods->irq_en;
179        } else {
180                TASK_INIT(&info->task, 0, 0, 0);
181        }
182
183        rval = bspExtInstallSharedISR((int)r, (void (*)(void*))filter, arg, 0);
184
185        if ( rval ) {
186                free(info, M_DEVBUF);
187                return rval;
188        }
189
190        *cookiep = info;
191        return rval;
192}
193
194int
195bus_teardown_intr(device_t dev, struct resource *r, void *cookiep)
196{
197int rval;
198struct irq_cookie *info = cookiep;
199        rval = bspExtRemoveSharedISR((int)r, (void (*)(void*))info->handler, info->arg);
200        if ( 0 == rval ) {
201                if ( info->task.ta_fn ) {
202                        taskqueue_drain(taskqueue_fast, &info->task);
203                }
204                free(info, M_DEVBUF);
205        }
206        return rval;
207}
208
209bus_space_handle_t
210rman_get_bushandle(struct resource *r)
211{
212bus_space_handle_t h = (bus_space_handle_t)r;
213bus_space_handle_t msk = (PCI_BASE_ADDRESS_SPACE_IO & h) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK;
214        return h & msk;
215}
216
217bus_space_tag_t
218rman_get_bustag(struct resource *r)
219{
220bus_space_handle_t h = (bus_space_handle_t)r;
221        return (PCI_BASE_ADDRESS_SPACE_IO & h) ? bus_space_io : bus_space_mem;
222}
223
224int
225bus_dma_tag_create(void *parent, unsigned alignment, unsigned bounds, uint32_t lowadd, uint32_t hiaddr, void (*filter)(void*), void *filterarg, unsigned maxsize, int nsegs, unsigned maxsegsize, unsigned flags, void (*lockfunc)(void*), void *lockarg, bus_dma_tag_t *ptag)
226{
227bus_dma_tag_t tag;
228        if ( filter || lockfunc )
229                return ENOTSUP;
230        if ( ! (tag = malloc(sizeof(*tag), M_DEVBUF, M_NOWAIT)) )
231                return ENOMEM;
232        /* save some information */
233        tag->alignment = alignment;
234        tag->maxsize   = maxsize;
235        tag->maxsegs   = nsegs;
236        *ptag          = tag;
237        return 0;
238}
239
240void
241bus_dma_tag_destroy(bus_dma_tag_t tag)
242{
243        free(tag, M_DEVBUF);
244}
245
246int
247bus_dmamem_alloc(bus_dma_tag_t tag, void **p_vaddr, unsigned flags, bus_dmamap_t *p_map)
248{
249uintptr_t a;
250        if ( ! (*p_map = malloc(tag->maxsize + tag->alignment, M_DEVBUF, M_NOWAIT)) )
251                return ENOMEM;
252        a = ((uintptr_t)*p_map + tag->alignment - 1 ) & ~(tag->alignment - 1);
253        *p_vaddr = (void*)a;
254        return 0;
255}
256
257void
258bus_dmamem_free(bus_dma_tag_t tag, void *vaddr, bus_dmamap_t map)
259{
260        free(map, M_DEVBUF);
261}
Note: See TracBrowser for help on using the repository browser.