diff --git a/base/mk/spec-platform_rpi.mk b/base/mk/spec-platform_rpi.mk index 0bb1a0bf0..c1712b6a5 100644 --- a/base/mk/spec-platform_rpi.mk +++ b/base/mk/spec-platform_rpi.mk @@ -5,7 +5,7 @@ # # denote wich specs are also fullfilled by this spec -SPECS += arm_v6 pl011 +SPECS += arm_v6 pl011 usb # add repository relative include paths REP_INC_DIR += include/platform/rpi diff --git a/dde_linux/Makefile b/dde_linux/Makefile index 5a1c17a4a..955d4054b 100644 --- a/dde_linux/Makefile +++ b/dde_linux/Makefile @@ -92,6 +92,10 @@ CONTENT += include/linux/platform_data/usb-omap.h CONTENT += arch/arm/plat-samsung/include/plat/usb-phy.h CONTENT += include/linux/platform_data/usb-ehci-s5p.h +# Raspberry Pi +DWC_OTG_GIT_URL := https://github.com/nfeske/dwc_otg.git +DWC_OTG_GIT_BRANCH := r1 + # # # Utility to check if a tool is installed @@ -116,6 +120,12 @@ help: prepare: clean $(CONTRIB_DIR)/.prepared +prepare_rpi: prepare + $(VERBOSE)cd $(CONTRIB_DIR)/drivers/usb/host; \ + git clone $(DWC_OTG_GIT_URL) dwc_otg + $(VERBOSE)cd $(CONTRIB_DIR)/drivers/usb/host/dwc_otg; \ + git reset --hard HEAD && git checkout $(DWC_OTG_GIT_BRANCH) + $(CONTRIB_DIR)/.prepared: Makefile $(CONTRIB_DIR)/.prepared: $(DOWNLOAD_DIR)/$(LINUX_TBZ2) $(ECHO) "extracting source code to '$(CONTRIB_DIR)'" diff --git a/dde_linux/lib/mk/platform_rpi/usb.mk b/dde_linux/lib/mk/platform_rpi/usb.mk new file mode 100644 index 000000000..9a060862d --- /dev/null +++ b/dde_linux/lib/mk/platform_rpi/usb.mk @@ -0,0 +1,44 @@ + +SRC_C += \ + usb/host/dwc_otg/dwc_otg/dwc_otg_adp.c \ + usb/host/dwc_otg/dwc_otg/dwc_otg_attr.c \ + usb/host/dwc_otg/dwc_otg/dwc_otg_cfi.c \ + usb/host/dwc_otg/dwc_otg/dwc_otg_cil.c \ + usb/host/dwc_otg/dwc_otg/dwc_otg_cil_intr.c \ + usb/host/dwc_otg/dwc_otg/dwc_otg_driver.c \ + usb/host/dwc_otg/dwc_otg/dwc_otg_hcd.c \ + usb/host/dwc_otg/dwc_otg/dwc_otg_hcd_ddma.c \ + usb/host/dwc_otg/dwc_otg/dwc_otg_hcd_intr.c \ + usb/host/dwc_otg/dwc_otg/dwc_otg_hcd_linux.c \ + usb/host/dwc_otg/dwc_otg/dwc_otg_hcd_queue.c + +SRC_C += \ + usb/host/dwc_otg/dwc_common_port/dwc_cc.c \ + usb/host/dwc_otg/dwc_common_port/dwc_common_linux.c \ + usb/host/dwc_otg/dwc_common_port/dwc_crypto.c \ + usb/host/dwc_otg/dwc_common_port/dwc_dh.c \ + usb/host/dwc_otg/dwc_common_port/dwc_mem.c \ + usb/host/dwc_otg/dwc_common_port/dwc_modpow.c \ + usb/host/dwc_otg/dwc_common_port/dwc_notifier.c + +include $(REP_DIR)/lib/mk/usb.inc +include $(REP_DIR)/lib/mk/arm/usb.inc + +CC_OPT += -DDWC_LINUX -DPLATFORM_INTERFACE + +# needed for 'ehci-hcd.c', which we don't use on the rpi, but it is still +# part of the generic usb USB driver +CC_OPT += -DCONFIG_USB_EHCI_PCI=1 + +# for 'dwc_otg_hcd_linux.c' for enabling the FIQ, which we don't use anyway +CC_OPT += -DINTERRUPT_VC_USB=9 + +# for 'dwc_otg_driver.c' for preventing calls to set_irq_type +CC_OPT += -DIRQF_TRIGGER_LOW=1 + +INC_DIR += $(CONTRIB_DIR)/drivers/usb/host/dwc_otg/dwc_common_port \ + $(CONTRIB_DIR)/drivers/usb/host/dwc_otg/dwc_otg +SRC_CC += platform.cc + +vpath platform.cc $(LIB_DIR)/arm/platform_rpi +vpath %.c $(CONTRIB_DIR)/drivers/net/usb diff --git a/dde_linux/src/lib/usb/arm/platform_rpi/platform.cc b/dde_linux/src/lib/usb/arm/platform_rpi/platform.cc new file mode 100644 index 000000000..f8e466a1e --- /dev/null +++ b/dde_linux/src/lib/usb/arm/platform_rpi/platform.cc @@ -0,0 +1,210 @@ +/* + * \brief USB initialization for Raspberry Pi + * \author Norman Feske + * \date 2013-09-11 + */ + +/* + * Copyright (C) 2013 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +/* Genode */ +#include +#include + +/* emulation */ +#include +#include + +/* dwc-otg */ +#define new new_ +#include +#undef new + +using namespace Genode; + + +/************************************************ + ** Resource info passed to the dwc_otg driver ** + ************************************************/ + +enum { + DWC_BASE = 0x20980000, + DWC_SIZE = 0x20000, + + DWC_IRQ = 17, +}; + + +static resource _dwc_otg_resource[] = +{ + { DWC_BASE, DWC_BASE + DWC_SIZE - 1, "dwc_otg", IORESOURCE_MEM }, + { DWC_IRQ, DWC_IRQ, "dwc_otg-irq" /* name unused */, IORESOURCE_IRQ } +}; + + +/*************************************** + ** Supplement to lx_emul environment ** + ***************************************/ + +#if VERBOSE_LX_EMUL +#define TRACE dde_kit_printf("\033[32m%s\033[0m called, not implemented\n", __PRETTY_FUNCTION__) +#else +#define TRACE +#endif + +#define DUMMY(retval, name) \ +extern "C" long name() { \ + dde_kit_printf("\033[32m%s\033[0m called, not implemented, stop\n", #name); \ + bt(); \ + for (;;); \ + return retval; \ +} + +#define CHECKED_DUMMY(retval, name) \ +extern "C" long name() { \ + dde_kit_printf("\033[32m%s\033[0m called, not implemented, ignored\n", #name); \ + bt(); \ + return retval; \ +} + +#define SILENT_DUMMY(retval, name) \ +extern "C" long name() { return retval; } + + +/********************* + ** linux/hardirq.h ** + *********************/ + +int in_irq() +{ + TRACE; PDBG("called by %p", __builtin_return_address(0)); + return 0; +} + + +/******************* + ** linux/delay.h ** + *******************/ + +unsigned long loops_per_jiffy = 1; + + +/********************* + ** linux/jiffies.h ** + *********************/ + +unsigned int jiffies_to_msecs(const unsigned long j) +{ + PDBG("not implemented. stop"); + return 1; +} + + +/*********************************** + ** Dummies for unused PCD driver ** + ***********************************/ + +/* + * The PCD driver is used for driving the DWC-OTG device as gadget. The + * Raspberry Pi solely supports the use of the controller as host device. + * Hence, the PCD parts are not needed. + */ + +DUMMY(-1, dwc_otg_pcd_disconnect_us); +DUMMY(-1, dwc_otg_pcd_remote_wakeup); +DUMMY(-1, dwc_otg_pcd_get_rmwkup_enable); +DUMMY(-1, dwc_otg_pcd_initiate_srp); +DUMMY(-1, pcd_remove); +SILENT_DUMMY( 0, pcd_init); +DUMMY(-1, printk_once); + + +/************************************************************************ + ** Prevent use of FIQ fix, need to resolve FIQ-related symbols anyway ** + ************************************************************************/ + +int fiq_fix_enable = false; + +extern int fiq_split_enable; + +void local_fiq_disable() { } +void local_fiq_enable() { } +int claim_fiq(struct fiq_handler *f) { return 0; } +void set_fiq_regs(struct pt_regs const *regs) { } +void set_fiq_handler(void *start, unsigned int length) { } +void enable_fiq() { } + +void __FIQ_Branch(unsigned long *regs) { TRACE; } + + +/*********************** + ** linux/workqueue.h ** + ***********************/ + +struct workqueue_struct *create_singlethread_workqueue(char *) +{ + workqueue_struct *wq = (workqueue_struct *)kzalloc(sizeof(workqueue_struct), 0); + return wq; +} + +void destroy_workqueue(struct workqueue_struct *wq) { TRACE; } + + +bool queue_work(struct workqueue_struct *wq, struct work_struct *work) { TRACE; return 0; } + + +/*********************** + ** asm/dma_mapping.h ** + ***********************/ + +void *dma_to_virt(struct device *dev, dma_addr_t phys) +{ + return phys_to_virt(phys); +} + + +/******************* + ** linux/timer.h ** + *******************/ + +struct tvec_base { }; +struct tvec_base boot_tvec_bases; + + +/******************* + ** Init function ** + *******************/ + +extern "C" void module_dwc_otg_driver_init(); + +struct Services; + +void platform_hcd_init(Services *) +{ + /* disable split-enable fix, otherwise, fiq_fix will be implied */ + fiq_split_enable = false; + + bool const verbose = false; + if (verbose) + g_dbg_lvl = DBG_HCD | DBG_CIL | DBG_HCD_URB; + + module_dwc_otg_driver_init(); + + /* setup host-controller platform device */ + platform_device *pdev = (platform_device *)kzalloc(sizeof(platform_device), 0); + pdev->name = (char *)"dwc_otg"; + pdev->id = 0; + pdev->num_resources = sizeof(_dwc_otg_resource)/sizeof(resource); + pdev->resource = _dwc_otg_resource; + + /* needed for DMA buffer allocation. See 'hcd_buffer_alloc' in 'buffer.c' */ + static u64 dma_mask = ~(u64)0; + pdev->dev.dma_mask = &dma_mask; + pdev->dev.coherent_dma_mask = ~0; + + platform_device_register(pdev); +} diff --git a/dde_linux/src/lib/usb/dummies.c b/dde_linux/src/lib/usb/dummies.c index 3df2acc56..9ab528092 100644 --- a/dde_linux/src/lib/usb/dummies.c +++ b/dde_linux/src/lib/usb/dummies.c @@ -192,7 +192,6 @@ s64 ktime_us_delta(const ktime_t later, const ktime_t earlier) { TRACE; return 0 *******************/ unsigned long round_jiffies(unsigned long j) { TRACE; return 1; } -void add_timer(struct timer_list *timer) { TRACE; } void set_timer_slack(struct timer_list *time, int slack_hz) { TRACE; } /********************* @@ -422,12 +421,11 @@ void devres_free(void *res) { TRACE; } ** linux/platform_device.h ** *****************************/ -void *platform_get_drvdata(const struct platform_device *pdev) { TRACE; return NULL; } -void platform_set_drvdata(struct platform_device *pdev, void *data) { TRACE; printk("ret: %p\n", __builtin_return_address(0)); } int platform_device_del(struct platform_device *pdev) { TRACE; return 0; } int platform_device_put(struct platform_device *pdev) { TRACE; return 0; } void platform_device_unregister(struct platform_device *pdev) { TRACE; } + /******************** ** linux/dcache.h ** ********************/ diff --git a/dde_linux/src/lib/usb/include/arm/platform/lx_emul.h b/dde_linux/src/lib/usb/include/arm/platform/lx_emul.h index 36853c7b9..4178c28c9 100644 --- a/dde_linux/src/lib/usb/include/arm/platform/lx_emul.h +++ b/dde_linux/src/lib/usb/include/arm/platform/lx_emul.h @@ -29,6 +29,7 @@ struct platform_device struct device dev; u32 num_resources; struct resource *resource; + void *data; }; @@ -238,4 +239,31 @@ struct nop_usb_xceiv_platform_data { int type; }; enum samsung_usb_phy_type { USB_PHY_TYPE_HOST = 1 }; +/*********************** + ** asm/dma-mapping.h ** + ***********************/ + +/* needed by 'dwc_otg_hcd_linux.c' */ +void *dma_to_virt(struct device *dev, dma_addr_t addr); + + +/******************** + ** asm/irqflags.h ** + ********************/ + +void local_fiq_disable(); +void local_fiq_enable(); + + +/*************** + ** asm/fiq.h ** + ***************/ + +struct pt_regs; +int claim_fiq(struct fiq_handler *f); +void set_fiq_regs(struct pt_regs const *regs); +void enable_fiq(); +void set_fiq_handler(void *start, unsigned int length); + + #endif /* _ARM__PLATFORM__LX_EMUL_H_ */ diff --git a/dde_linux/src/lib/usb/include/lx_emul.h b/dde_linux/src/lib/usb/include/lx_emul.h index 20f2ca3dd..ccf449980 100644 --- a/dde_linux/src/lib/usb/include/lx_emul.h +++ b/dde_linux/src/lib/usb/include/lx_emul.h @@ -51,6 +51,19 @@ extern "C" { #define KBUILD_MODNAME "mod-noname" +static inline void bt() +{ + dde_kit_printf("BT: 0x%p\n", __builtin_return_address(0)); +} + + +/******************* + ** linux/sizes.h ** + *******************/ + +#define SZ_256K 0x40000 /* needed by 'dwc_otg_attr.c' */ + + /***************** ** linux/bcd.h ** *****************/ @@ -224,6 +237,15 @@ typedef unsigned long dma_addr_t; */ typedef unsigned short mode_t; +/* + * Needed by 'dwc_common_port/usb.h' + */ +typedef unsigned int u_int; +typedef unsigned char u_char; +typedef unsigned long u_long; +typedef uint8_t u_int8_t; +typedef uint16_t u_int16_t; +typedef uint32_t u_int32_t; #include @@ -247,6 +269,8 @@ static inline void barrier() { mb(); } #define likely #define unlikely +#define notrace /* needed by 'dwc_otg_hcd_intr.c' */ + #define __user /* needed by usb/core/devices.c */ #define __iomem /* needed by usb/hcd.h */ @@ -278,6 +302,9 @@ enum irqreturn { IRQ_HANDLED = (1 << 0), }; +/* needed by 'dwc_otg_hcd_linux.c' */ +#define IRQ_RETVAL(x) ((x) != IRQ_NONE) + typedef enum irqreturn irqreturn_t; /****************** @@ -447,6 +474,8 @@ enum { ENOLINK = 50, EADDRNOTAVAIL = 51, EPROBE_DEFER = 52, + ERESTART = 53, + ECONNABORTED = 54, }; @@ -603,6 +632,8 @@ long simple_strtoul(const char *cp, char **endp, unsigned int base); /* * Needed by 'usb.h' */ +int vsnprintf(char *buf, size_t size, const char *fmt, va_list args); +int vsprintf(char *buf, const char *fmt, va_list args); int snprintf(char *buf, size_t size, const char *fmt, ...); int sprintf(char *buf, const char *fmt, ...); int sscanf(const char *, const char *, ...); @@ -910,6 +941,7 @@ void up_write(struct rw_semaphore *sem); */ extern volatile unsigned long jiffies; unsigned long msecs_to_jiffies(const unsigned int m); +unsigned int jiffies_to_msecs(const unsigned long j); long time_after(long a, long b); long time_after_eq(long a, long b); @@ -943,11 +975,15 @@ ktime_t ktime_set(const long, const unsigned long); ** linux/timer.h ** *******************/ +struct tvec_base; +extern struct tvec_base boot_tvec_bases; /* needed by 'dwc_common_linux.c' */ + struct timer_list { void (*function)(unsigned long); unsigned long data; void *timer; unsigned long expires; + struct tvec_base *base; /* needed by 'dwc_common_linux.c' */ }; void init_timer(struct timer_list *); @@ -958,8 +994,8 @@ void setup_timer(struct timer_list *timer,void (*function)(unsigned long), int timer_pending(const struct timer_list * timer); unsigned long round_jiffies(unsigned long j); -void add_timer(struct timer_list *timer); void set_timer_slack(struct timer_list *time, int slack_hz); +static inline void add_timer(struct timer_list *timer) { mod_timer(timer, timer->expires); } static inline int del_timer_sync(struct timer_list * timer) { return del_timer(timer); } @@ -991,6 +1027,8 @@ void msleep(unsigned int msecs); void udelay(unsigned long usecs); void mdelay(unsigned long usecs); +extern unsigned long loops_per_jiffy; /* needed by 'dwc_otg_attr.c' */ + /*********************** ** linux/workquque.h ** @@ -1047,6 +1085,14 @@ struct workqueue_struct { }; bool queue_delayed_work(struct workqueue_struct *, struct delayed_work *, unsigned long); +/* needed for 'dwc_common_linux.c' */ +struct workqueue_struct *create_singlethread_workqueue(char *n); + +void destroy_workqueue(struct workqueue_struct *wq); + +bool queue_work(struct workqueue_struct *wq, struct work_struct *work); + + /****************** ** linux/wait.h ** ******************/ @@ -1622,6 +1668,10 @@ struct platform_device; void *platform_get_drvdata(const struct platform_device *pdev); void platform_set_drvdata(struct platform_device *pdev, void *data); +/* needed by 'dwc_otg_driver.c' */ +struct platform_driver; +void platform_driver_unregister(struct platform_driver *); + /********************* ** linux/dmapool.h ** @@ -1941,6 +1991,7 @@ int seq_printf(struct seq_file *, const char *, ...); enum { __GFP_DMA = 0x01u, GFP_DMA = __GFP_DMA, + GFP_DMA32 = 0x04u, /* needed by 'dwc_common_linux.c' */ __GFP_WAIT = 0x10u, GFP_ATOMIC = 0x20u, GFP_KERNEL = 0x0u, @@ -2027,6 +2078,8 @@ void *ioremap_wc(resource_size_t phys_addr, unsigned long size); #define ioremap_nocache ioremap +void *phys_to_virt(unsigned long address); + #define writel(value, addr) (*(volatile uint32_t *)(addr) = (value)) #define readl(addr) (*(volatile uint32_t *)(addr)) #define readb(addr) (*(volatile uint8_t *)(addr)) @@ -2096,6 +2149,35 @@ int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, void free_irq(unsigned int, void *); +/***************** + ** linux/irq.h ** + *****************/ + +enum { IRQ_TYPE_LEVEL_LOW = 0x00000008 }; /* needed by 'dwc_otg_driver.c' */ + + +/********************* + ** linux/hardirq.h ** + *********************/ + +/* needed by 'dwc_common_linux.c' */ +int in_irq(); + + +/*************** + ** asm/fiq.h ** + ***************/ + +/* + * Needed by 'dwc_otg_hcd_linux.c' + */ +struct fiq_handler { + char const *name; +}; + +void __FIQ_Branch(unsigned long *regs); + + /********************* ** linux/hardirq.h ** *********************/ @@ -3325,8 +3407,10 @@ struct tasklet_struct unsigned long data; }; -static inline void tasklet_schedule(struct tasklet_struct *t) { t->func(t->data); } +void tasklet_schedule(struct tasklet_struct *t); +void tasklet_hi_schedule(struct tasklet_struct *t); void tasklet_kill(struct tasklet_struct *); +void tasklet_init(struct tasklet_struct *t, void (*)(unsigned long), unsigned long); /************************* @@ -3524,6 +3608,21 @@ void genode_evdev_event(struct input_handle *handle, unsigned int type, void start_input_service(void *ep); + +/****************** + ** asm/ptrace.h ** + ******************/ + +/* + * Needed by 'dwc_otg_hcd_linux.c' + */ +struct pt_regs { unsigned long dummy; }; + +#define ARM_r8 dummy +#define ARM_r9 dummy +#define ARM_sp dummy + + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/dde_linux/src/lib/usb/include/x86/platform/lx_emul.h b/dde_linux/src/lib/usb/include/x86/platform/lx_emul.h index 981dc5a70..cbeb18228 100644 --- a/dde_linux/src/lib/usb/include/x86/platform/lx_emul.h +++ b/dde_linux/src/lib/usb/include/x86/platform/lx_emul.h @@ -14,5 +14,9 @@ #ifndef _X86_32__PLATFORM__LX_EMUL_ #define _X86_32__PLATFORM__LX_EMUL_ +struct platform_device +{ + void *data; +}; #endif /* _X86_32__PLATFORM__LX_EMUL_ */ diff --git a/dde_linux/src/lib/usb/lx_emul.cc b/dde_linux/src/lib/usb/lx_emul.cc index 3bfa115da..d71c3424a 100644 --- a/dde_linux/src/lib/usb/lx_emul.cc +++ b/dde_linux/src/lib/usb/lx_emul.cc @@ -139,6 +139,23 @@ class Genode::Slab_backend_alloc : public Genode::Allocator, return phys; } + /** + * Translate given physical address to virtual address + * + * \return virtual address, or 0 if no translation exists + */ + addr_t virt_addr(addr_t phys) + { + for (unsigned i = 0; i < ELEMENTS; i++) { + if (_ds_cap[i].valid() + && phys >= _ds_phys[i] && phys < _ds_phys[i] + BLOCK_SIZE) + return _base + i*BLOCK_SIZE + phys - _ds_phys[i]; + } + + PWRN("virt_addr(0x%lx) - no translation", phys); + return 0; + } + addr_t start() const { return _base; } addr_t end() const { return _base + VM_SIZE - 1; } }; @@ -293,6 +310,11 @@ class Malloc return _back_allocator->phys_addr((addr_t)a); } + Genode::addr_t virt_addr(Genode::addr_t phys) + { + return _back_allocator->virt_addr(phys); + } + /** * Belongs given address to this allocator */ @@ -479,6 +501,15 @@ inline void *memset(void *s, int c, size_t n) } +int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) +{ + Genode::String_console sc(buf, size); + sc.vprintf(fmt, args); + + return sc.len(); +} + + int snprintf(char *buf, size_t size, const char *fmt, ...) { va_list args; @@ -668,6 +699,12 @@ void *devm_ioremap_nocache(struct device *dev, resource_size_t offset, } +void *phys_to_virt(unsigned long address) +{ + return (void *)Malloc::dma()->virt_addr(address); +} + + /******************** ** linux/device.h ** ********************/ @@ -808,6 +845,17 @@ void *devm_kzalloc(struct device *dev, size_t size, gfp_t gfp) } +void *platform_get_drvdata(const struct platform_device *pdev) +{ + return pdev->data; +} + + +void platform_set_drvdata(struct platform_device *pdev, void *data) +{ + pdev->data = data; +} + /******************************* ** linux/byteorder/generic.h ** diff --git a/dde_linux/src/lib/usb/signal/event.cc b/dde_linux/src/lib/usb/signal/event.cc index 9e7994862..edc9dcadd 100644 --- a/dde_linux/src/lib/usb/signal/event.cc +++ b/dde_linux/src/lib/usb/signal/event.cc @@ -59,7 +59,8 @@ class Work : public Genode::List::Element private: void *_work; - bool _delayed; + + enum Type { NORMAL, DELAYED, TASKLET } _type; static Genode::List *_list() { @@ -69,12 +70,14 @@ class Work : public Genode::List::Element public: - Work(void *work, bool delayed) : _work(work), _delayed(delayed) { } + Work(delayed_work *work) : _work(work), _type(DELAYED) { } + Work(work_struct *work) : _work(work), _type(NORMAL) { } + Work(tasklet_struct *work) : _work(work), _type(TASKLET) { } - static void schedule(void *work, bool delayed) + template + static void schedule(WORK *work) { - Work *w = new (Genode::env()->heap()) Work(work, delayed); - _list()->insert(w); + _list()->insert(new (Genode::env()->heap()) Work(work)); } static void exec() @@ -83,18 +86,32 @@ class Work : public Genode::List::Element Work *w = _list()->first(); _list()->remove(w); - if (w->_delayed) { - delayed_work *work = static_cast(w->_work); - work->work.func(&(work)->work); - } - else { - work_struct *work = static_cast(w->_work); - work->func(work); + switch (w->_type) { + + case NORMAL: + { + work_struct *work = static_cast(w->_work); + work->func(work); + } + break; + + case DELAYED: + { + delayed_work *work = static_cast(w->_work); + work->work.func(&(work)->work); + } + break; + + case TASKLET: + { + tasklet_struct *tasklet = static_cast(w->_work); + tasklet->func(tasklet->data); + } + break; } destroy(Genode::env()->heap(), w); } } - }; @@ -226,15 +243,14 @@ int wake_up_process(struct task_struct *tsk) int schedule_delayed_work(struct delayed_work *work, unsigned long delay) { - Work::schedule((void *)work, true); - //work->work.func(&(work)->work); + Work::schedule(work); return 0; } int schedule_work(struct work_struct *work) { - Work::schedule((void *)work, false); + Work::schedule(work); return 1; } @@ -242,6 +258,29 @@ int schedule_work(struct work_struct *work) bool queue_delayed_work(struct workqueue_struct *wq, struct delayed_work *dwork, unsigned long delay) { - Work::schedule((void *)dwork, true); + Work::schedule(dwork); return true; } + + +/*********************** + ** linux/interrupt.h ** + ***********************/ + +void tasklet_init(struct tasklet_struct *t, void (*f)(unsigned long), unsigned long d) +{ + t->func = f; + t->data = d; +} + + +void tasklet_schedule(struct tasklet_struct *tasklet) +{ + Work::schedule(tasklet); +} + + +void tasklet_hi_schedule(struct tasklet_struct *tasklet) +{ + tasklet_schedule(tasklet); +}