diff --git a/.gitignore b/.gitignore
index 399c80651..dadb3267b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,6 +13,8 @@
/base-okl4/download
/base-pistachio/contrib
/dde_ipxe/contrib
+/dde_linux/contrib
+/dde_linux/download
/libports/contrib
/libports/download
/libports/include/EGL/egl.h
diff --git a/README b/README
index a0d913f21..c06b19b42 100644
--- a/README
+++ b/README
@@ -127,10 +127,17 @@ The Genode source tree is composed of the following subdirectories:
For instructions about how to use this mechanism, please consult the README
file at the top level of the repository.
-:'linux_drivers':
+:'dde_linux':
This source-code repository contains the device driver environment for
- executing Linux device drivers natively on Genode.
+ executing Linux device drivers natively on Genode. Currently, this
+ repository hosts the USB stack.
+
+:'linux_drivers':
+
+ Deprecated version of the Linux device driver environment featuring audio
+ drivers and the Intel GEM driver. This repository is in a transitionary
+ phase. Its functionality will be incorporated into 'dde_linux'.
:'dde_ipxe':
diff --git a/dde_linux/Makefile b/dde_linux/Makefile
new file mode 100644
index 000000000..5a5d58429
--- /dev/null
+++ b/dde_linux/Makefile
@@ -0,0 +1,98 @@
+#
+# \brief Download integrate Linux kernel sources with Genode
+# \author Norman Feske
+# \date 2012-01-28
+
+CONTRIB_DIR = contrib
+DOWNLOAD_DIR = download
+VERBOSE ?= @
+ECHO = @echo
+PATCHES = $(shell find patches -name *.patch)
+
+LINUX = linux-3.2.2
+LINUX_TBZ2 = $(LINUX).tar.bz2
+LINUX_URL = http://www.kernel.org/pub/linux/kernel/v3.x/$(LINUX_TBZ2)
+
+# Linux utilities
+CONTENT += include/linux/list.h
+CONTENT += $(addprefix include/linux/,pci_ids.h pci_regs.h usb.h hid.h hiddev.h input.h mod_devicetable.h)
+CONTENT += $(addprefix include/linux/byteorder/,generic.h little_endian.h)
+CONTENT += include/linux/swab.h
+CONTENT += $(addprefix include/asm-generic/bitops/,__ffs.h non-atomic.h)
+
+# USB core
+CONTENT += drivers/usb/core
+CONTENT += drivers/usb/usb-common.c
+CONTENT_INCLUDE_USB := ch11.h ch9.h ehci_def.h hcd.h input.h otg.h quirks.h storage.h
+CONTENT += $(addprefix include/linux/usb/,$(CONTENT_INCLUDE_USB))
+
+# needed by usb/core/devio.c
+CONTENT += include/linux/usbdevice_fs.h include/asm-generic/ioctl.h
+
+# USB host-controller driver
+CONTENT_USB_HOST := ehci.h ehci-hcd.c ehci-hub.c ehci-dbg.c ehci-mem.c \
+ ehci-q.c ehci-pci.c ehci-sched.c ehci-sysfs.c
+CONTENT_USB_HOST += ohci.h ohci-hcd.c ohci-hub.c ohci-dbg.c ohci-mem.c \
+ ohci-q.c ohci-pci.c ehci-lpm.c
+CONTENT_USB_HOST += uhci-hcd.h uhci-hcd.c uhci-debug.c uhci-q.c uhci-hub.c \
+ uhci-pci.c
+CONTENT_USB_HOST += pci-quirks.h pci-quirks.c xhci-ext-caps.h
+CONTENT += $(addprefix drivers/usb/host/,$(CONTENT_USB_HOST))
+
+# USB storage driver
+CONTENT += drivers/usb/storage/
+CONTENT += include/linux/usb_usual.h
+
+# SCSI support for storage
+CONTENT += $(addprefix drivers/scsi/,scsi.h scsi.c constants.c scsi_priv.h scsi_logging.h)
+CONTENT += $(addprefix include/scsi/,scsi.h scsi_host.h)
+
+# USB hid driver
+CONTENT += drivers/hid/hid-input.c drivers/hid/hid-core.c drivers/hid/hid-ids.h
+CONTENT += drivers/hid/usbhid
+
+# needed by USB hid
+CONTENT_INPUT := input.c evdev.c input-compat.h
+CONTENT += $(addprefix drivers/input/,$(CONTENT_INPUT))
+CONTENT += include/linux/input/mt.h
+
+
+CONTRIB_CONTENT := $(addprefix $(CONTRIB_DIR)/,$(CONTENT))
+
+#
+# Print help information by default
+#
+help:
+ $(ECHO)
+ $(ECHO) "Download integrate Linux kernel sources with Genode"
+ $(ECHO)
+ $(ECHO) "--- available commands ---"
+ $(ECHO) "prepare - download and integrate Linux source code"
+ $(ECHO) "clean - remove contib sources except downloaded archives"
+ $(ECHO) "cleanall - remove contib sources and downloaded archives"
+ $(ECHO)
+
+prepare: $(CONTRIB_DIR)/.prepared
+
+$(CONTRIB_DIR)/.prepared: Makefile
+$(CONTRIB_DIR)/.prepared: $(DOWNLOAD_DIR)/$(LINUX_TBZ2)
+ $(ECHO) "extracting source code to '$(CONTRIB_DIR)'"
+ $(VERBOSE)tar xfj $< --transform "s/$(LINUX)/$(CONTRIB_DIR)/" $(addprefix $(LINUX)/,$(CONTENT))
+ $(VERBOSE)touch $@
+ $(ECHO) "applying patches to '$(CONTRIB_DIR)/'"
+ $(VERBOSE)for i in $(PATCHES); do patch -d $(CONTRIB_DIR) -p1 < $$i; done
+
+
+$(DOWNLOAD_DIR):
+ $(VERBOSE)mkdir -p $@
+
+$(DOWNLOAD_DIR)/$(LINUX_TBZ2): $(DOWNLOAD_DIR)
+ $(ECHO) "downloading source code to '$@'"
+ $(VERBOSE)cd $(DOWNLOAD_DIR); wget -c $(LINUX_URL)
+ $(VERBOSE)touch $@
+
+clean:
+ $(VERBOSE)rm -f $(CONTRIB_DIR)
+
+cleanall: clean
+ $(VERBOSE)rm -rf $(DOWNLOAD_DIR)
diff --git a/dde_linux/README b/dde_linux/README
new file mode 100644
index 000000000..c96d02d3c
--- /dev/null
+++ b/dde_linux/README
@@ -0,0 +1,37 @@
+Device drivers ported from the Linux kernel
+
+USB
+###
+
+HID
+~~~
+
+Supports keyboard and mouse. A run script can be found under 'run/usb_hid.run'.
+
+Configuration snippet:
+
+!
+!
+!
+!
+!
+!
+!
+
+Note: It has been observed that certain 1.0 versions of Qemu do not generate
+mouse interrupts. The mouse driver should work correctly on Qemu 1.0.93 and
+above.
+
+STORAGE
+~~~~~~~
+
+Currently supports one USB storage device. Hot plugging has not been tested. A
+run script can be found under 'run/usb_storage.run'.
+
+Configuration snippet:
+
+!
+!
+!
+!
+!
diff --git a/dde_linux/patches/evdev.patch b/dde_linux/patches/evdev.patch
new file mode 100644
index 000000000..4618cb547
--- /dev/null
+++ b/dde_linux/patches/evdev.patch
@@ -0,0 +1,22 @@
+diff -r 1d04c9c5fa8a drivers/input/evdev.c
+--- a/drivers/input/evdev.c Tue Apr 17 16:14:54 2012 +0200
++++ b/drivers/input/evdev.c Wed Apr 18 11:25:37 2012 +0200
+@@ -957,6 +957,9 @@
+ if (error)
+ goto err_cleanup_evdev;
+
++ evdev_open_device(evdev);
++ dev_info(evdev, "%s\n", dev->name);
++
+ return 0;
+
+ err_cleanup_evdev:
+@@ -986,7 +989,7 @@
+ MODULE_DEVICE_TABLE(input, evdev_ids);
+
+ static struct input_handler evdev_handler = {
+- .event = evdev_event,
++ .event = genode_evdev_event,
+ .connect = evdev_connect,
+ .disconnect = evdev_disconnect,
+ .fops = &evdev_fops,
diff --git a/dde_linux/run/usb_hid.run b/dde_linux/run/usb_hid.run
new file mode 100644
index 000000000..30099e436
--- /dev/null
+++ b/dde_linux/run/usb_hid.run
@@ -0,0 +1,75 @@
+#
+# Build
+#
+
+set build_components {
+ core init
+ drivers/timer
+ drivers/pci
+ drivers/usb
+ test/input
+}
+
+build $build_components
+
+create_boot_directory
+
+#
+# Generate config
+#
+
+append config {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
+
+install_config $config
+
+#
+# Boot modules
+#
+
+# generic modules
+set boot_modules {
+ core init timer pci_drv usb_drv test-input
+}
+
+build_boot_image $boot_modules
+
+append qemu_args " -m 256 -usb -usbdevice mouse -usbdevice keyboard"
+
+
+run_genode_until forever
diff --git a/dde_linux/run/usb_storage.run b/dde_linux/run/usb_storage.run
new file mode 100644
index 000000000..adec08c04
--- /dev/null
+++ b/dde_linux/run/usb_storage.run
@@ -0,0 +1,107 @@
+#
+# \brief Test for using the Block (Storage) service of usb_drv
+# \author Christian Prochaska
+# \date 2011-06-24
+#
+
+#
+# Build
+#
+
+build {
+ core init
+ drivers/pci
+ drivers/timer
+ drivers/usb
+ test/ahci
+}
+
+create_boot_directory
+
+#
+# Generate config
+#
+
+set config {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
+install_config $config
+
+#
+# Boot modules
+#
+
+# generic modules
+set boot_modules {
+ core init timer usb_drv pci_drv test-ahci
+}
+
+
+build_boot_image $boot_modules
+
+#
+# Execute test case
+#
+set disk_image "bin/test.img"
+set cmd "dd if=/dev/zero of=$disk_image bs=1024 count=65536"
+puts "creating disk image:\n$cmd"
+catch { exec sh -c $cmd }
+
+set cmd "mkfs.vfat -F32 $disk_image"
+puts "formating disk image with vfat file system:\$cmd"
+catch { exec sh -c $cmd }
+
+#
+# Qemu opts for UHCI
+#
+#append qemu_args " -m 64 -nographic -usbdevice disk::$disk_image -boot order=d"
+
+#
+# Qemu opts for EHCI
+#
+append qemu_args "-drive if=none,id=disk,file=$disk_image"
+append qemu_args { \
+-m 64 -nographic -M pc \
+-device usb-ehci,id=ehci \
+-device usb-storage,bus=ehci.0,drive=disk \
+-boot order=d }
+
+run_genode_until {.*child exited with exit value 0.*} 40
+
+puts "\ntest succeeded\n"
+
+# vi: set ft=tcl :
diff --git a/dde_linux/src/drivers/usb/dummies.c b/dde_linux/src/drivers/usb/dummies.c
new file mode 100644
index 000000000..0642876c5
--- /dev/null
+++ b/dde_linux/src/drivers/usb/dummies.c
@@ -0,0 +1,782 @@
+/*
+ * \brief Dummy functions
+ * \author Norman Feske
+ * \author Sebastian sumpf
+ * \date 2011-01-29
+ */
+
+/*
+ * Copyright (C) 2011-2012 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.
+ */
+
+/* Linux kernel API */
+#include
+
+/* DDE-Kit includes */
+#include
+
+/* Linux includes */
+#include
+
+#define SKIP_VERBOSE 0
+
+#if VERBOSE_LX_EMUL
+#define TRACE dde_kit_printf("\033[32m%s\033[0m called, not implemented\n", __PRETTY_FUNCTION__)
+#else
+#define TRACE
+#endif
+#if SKIP_VERBOSE
+#define SKIP dde_kit_printf("\033[34m%s\033[0m: skipped\n", __PRETTY_FUNCTION__)
+#else
+#define SKIP
+#endif
+
+
+/******************
+ ** asm/atomic.h **
+ ******************/
+
+int atomic_inc_return(atomic_t *v) { TRACE; return 0; }
+
+
+/*******************************
+ ** linux/byteorder/generic.h **
+ *******************************/
+
+u16 get_unaligned_le16(const void *p) { TRACE; return 0; }
+u32 get_unaligned_le32(const void *p) { TRACE; return 0; }
+
+
+/*******************************
+ ** linux/errno.h and friends **
+ *******************************/
+
+long PTR_ERR(const void *ptr) { TRACE; return 0; }
+
+
+/********************
+ ** linux/kernel.h **
+ ********************/
+
+void might_sleep() { SKIP; }
+char *kasprintf(gfp_t gfp, const char *fmt, ...) { TRACE; return NULL; }
+int kstrtouint(const char *s, unsigned int base, unsigned int *res) { TRACE; return 0; }
+int sprintf(char *buf, const char *fmt, ...) { TRACE; return 0; }
+int sscanf(const char *b, const char *s, ...) { TRACE; return 0; }
+int scnprintf(char *buf, size_t size, const char *fmt, ...) { TRACE; return 0; }
+int strict_strtoul(const char *s, unsigned int base, unsigned long *res) { TRACE; return 0; }
+long simple_strtoul(const char *cp, char **endp, unsigned int base) { TRACE; return 0; }
+
+
+/******************
+ ** linux/log2.h **
+ ******************/
+
+int roundup_pow_of_two(u32 n) { TRACE; return 0; }
+
+
+/********************
+ ** linux/printk.h **
+ ********************/
+
+void print_hex_dump(const char *level, const char *prefix_str,
+ int prefix_type, int rowsize, int groupsize,
+ const void *buf, size_t len, bool ascii) { TRACE; }
+
+
+/**********************************
+ ** linux/bitops.h, asm/bitops.h **
+ **********************************/
+
+int ffs(int x) { TRACE; return 0; }
+
+
+/********************
+ ** linux/string.h **
+ ********************/
+
+int memcmp(const void *dst, const void *src, size_t s) { TRACE; return 0; }
+char *strcat(char *dest, const char *src) { TRACE; return 0; }
+int strcmp(const char *s1, const char *s2) { TRACE; return 0; }
+int strncmp(const char *cs, const char *ct, size_t count) { TRACE; return 0; }
+char *strncpy(char *dst, const char *src, size_t s) { TRACE; return NULL; }
+char *strchr(const char *s, int n) { TRACE; return NULL; }
+char *strrchr(const char *s, int n) { TRACE; return NULL; }
+size_t strlcpy(char *dest, const char *src, size_t size) { TRACE; return 0; }
+char *strsep(char **s,const char *d) { TRACE; return NULL; }
+char *kstrdup(const char *s, gfp_t gfp) { TRACE; return 0; }
+char *strstr(const char *h, const char *n) { TRACE; return 0; }
+
+
+/*****************
+ ** linux/nls.h **
+ *****************/
+
+int utf16s_to_utf8s(const wchar_t *pwcs, int len,
+ enum utf16_endian endian, u8 *s, int maxlen) { TRACE; return 0; }
+
+
+/*******************
+ ** linux/ctype.h **
+ *******************/
+
+int isprint(int v) { TRACE; return 0; }
+
+
+/**********************
+ ** linux/spinlock.h **
+ **********************/
+
+void spin_lock(spinlock_t *lock) { SKIP; }
+void spin_lock_nested(spinlock_t *lock, int subclass) { TRACE; }
+void spin_unlock(spinlock_t *lock) { SKIP; }
+void spin_lock_init(spinlock_t *lock) { SKIP; }
+void spin_lock_irqsave(spinlock_t *lock, unsigned long flags) { SKIP; }
+void spin_lock_irqrestore(spinlock_t *lock, unsigned long flags) { SKIP; }
+void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags) { SKIP; }
+void spin_lock_irq(spinlock_t *lock) { SKIP; }
+void spin_unlock_irq(spinlock_t *lock) { SKIP; }
+void assert_spin_locked(spinlock_t *lock) { TRACE;}
+
+
+
+/*******************
+ ** linux/mutex.h **
+ *******************/
+
+void mutex_lock_nested(struct mutex *lock, unsigned int subclass) { TRACE; }
+int mutex_lock_interruptible(struct mutex *m) { TRACE; return 0; }
+
+
+/*******************
+ ** linux/rwsem.h **
+ *******************/
+
+void down_read(struct rw_semaphore *sem) { TRACE; }
+void up_read(struct rw_semaphore *sem) { TRACE; }
+void down_write(struct rw_semaphore *sem) { TRACE; }
+void up_write(struct rw_semaphore *sem) { TRACE; }
+
+
+/*******************
+ ** linux/ktime.h **
+ *******************/
+
+ktime_t ktime_add_ns(const ktime_t kt, u64 nsec) { TRACE; ktime_t ret = { 0 }; return ret; }
+
+s64 ktime_us_delta(const ktime_t later, const ktime_t earlier) { TRACE; return 0; };
+
+
+/*******************
+ ** linux/timer.h **
+ *******************/
+
+int del_timer_sync(struct timer_list *timer) { TRACE; return 0; }
+unsigned long round_jiffies(unsigned long j) { TRACE; return 1; }
+
+
+/*********************
+ ** linux/hrtimer.h **
+ *********************/
+
+ktime_t ktime_get_real(void) { TRACE; ktime_t ret; return ret; }
+
+
+/*******************
+ ** linux/delay.h **
+ *******************/
+
+void mdelay(unsigned long msecs) { TRACE; }
+
+
+/***********************
+ ** linux/workquque.h **
+ ***********************/
+
+bool cancel_work_sync(struct work_struct *work) { TRACE; return 0; }
+int cancel_delayed_work_sync(struct delayed_work *work) { TRACE; return 0; }
+int schedule_work(struct work_struct *work) { TRACE; return 0; }
+bool flush_work_sync(struct work_struct *work) { TRACE; return 0; }
+
+
+/******************
+ ** linux/wait.h **
+ ******************/
+
+void init_waitqueue_head(wait_queue_head_t *q) { TRACE; }
+void add_wait_queue(wait_queue_head_t *q, wait_queue_t *wait) { TRACE; }
+void remove_wait_queue(wait_queue_head_t *q, wait_queue_t *wait) { TRACE; }
+
+
+/******************
+ ** linux/time.h **
+ ******************/
+
+struct timespec current_kernel_time(void)
+{
+ struct timespec t = { 0, 0 };
+ return t;
+}
+
+void do_gettimeofday(struct timeval *tv) { TRACE; }
+
+
+/*******************
+ ** linux/sched.h **
+ *******************/
+
+int kill_pid_info_as_cred(int i, struct siginfo *s, struct pid *p,
+ const struct cred *c, u32 v) { TRACE; return 0; }
+pid_t task_pid_nr(struct task_struct *tsk) { TRACE; return 0; }
+struct pid *task_pid(struct task_struct *task) { TRACE; return NULL; }
+void __set_current_state(int state) { TRACE; }
+int signal_pending(struct task_struct *p) { TRACE; return 0; }
+void schedule(void) { TRACE; }
+void yield(void) { TRACE; }
+void cpu_relax(void) { TRACE; }
+
+struct task_struct *current;
+
+
+/*********************
+ ** linux/kthread.h **
+ *********************/
+
+int kthread_should_stop(void) { SKIP; return 0; }
+int kthread_stop(struct task_struct *k) { TRACE; return 0; }
+
+
+/**********************
+ ** linux/notifier.h **
+ **********************/
+
+int blocking_notifier_chain_register(struct blocking_notifier_head *nh,
+ struct notifier_block *nb) { TRACE; return 0; }
+int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh,
+ struct notifier_block *nb) { TRACE; return 0; }
+int blocking_notifier_call_chain(struct blocking_notifier_head *nh,
+ unsigned long val, void *v) { TRACE; return 0; }
+int atomic_notifier_chain_register(struct atomic_notifier_head *nh,
+ struct notifier_block *nb) { TRACE; return 0; }
+int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh,
+ struct notifier_block *nb) { TRACE; return 0; }
+
+
+
+/*********************
+ ** linux/kobject.h **
+ *********************/
+
+int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...) { TRACE; return 0; }
+char *kobject_name(const struct kobject *kobj) { TRACE; return 0; }
+char *kobject_get_path(struct kobject *kobj, gfp_t gfp_mask) { TRACE; return 0; }
+
+
+/*******************
+ ** linux/sysfs.h **
+ *******************/
+
+int sysfs_create_group(struct kobject *kobj,
+ const struct attribute_group *grp) { TRACE; return 0; }
+void sysfs_remove_group(struct kobject *kobj,
+ const struct attribute_group *grp) { TRACE; }
+
+int fasync_helper(int fd, struct file * filp, int on, struct fasync_struct **fapp) { TRACE; return 0; }
+
+ssize_t simple_read_from_buffer(void __user *to, size_t count,
+ loff_t *ppos, const void *from, size_t available) { TRACE; return 0; }
+
+/************************
+ ** linux/pm_runtime.h **
+ ************************/
+
+int pm_runtime_set_active(struct device *dev) { TRACE; return 0; }
+void pm_suspend_ignore_children(struct device *dev, bool enable) { TRACE; }
+void pm_runtime_enable(struct device *dev) { TRACE; }
+void pm_runtime_disable(struct device *dev) { TRACE; }
+void pm_runtime_set_suspended(struct device *dev) { TRACE; }
+void pm_runtime_get_noresume(struct device *dev) { TRACE; }
+void pm_runtime_put_noidle(struct device *dev) { TRACE; }
+void pm_runtime_use_autosuspend(struct device *dev) { TRACE; }
+int pm_runtime_put_sync_autosuspend(struct device *dev) { TRACE; return 0; }
+void pm_runtime_no_callbacks(struct device *dev) { TRACE; }
+
+
+/***********************
+ ** linux/pm_wakeup.h **
+ ***********************/
+
+int device_init_wakeup(struct device *dev, bool val) { TRACE; return 0; }
+int device_wakeup_enable(struct device *dev) { TRACE; return 0; }
+bool device_may_wakeup(struct device *dev) { TRACE; return 0; }
+int device_set_wakeup_enable(struct device *dev, bool enable) { TRACE; return 0; }
+bool device_can_wakeup(struct device *dev) { TRACE; return 0; }
+
+
+/********************
+ ** linux/device.h **
+ ********************/
+
+int dev_set_name(struct device *dev, const char *name, ...) { TRACE; return 0; }
+const char *dev_name(const struct device *dev) { TRACE; return NULL; }
+int dev_to_node(struct device *dev) { TRACE; return 0; }
+void set_dev_node(struct device *dev, int node) { TRACE; }
+
+struct device *device_create(struct class *cls, struct device *parent,
+ dev_t devt, void *drvdata,
+ const char *fmt, ...) { TRACE; return NULL; }
+void device_destroy(struct class *cls, dev_t devt) { TRACE; }
+void device_unregister(struct device *dev) { TRACE; }
+void device_lock(struct device *dev) { TRACE; }
+int device_trylock(struct device *dev) { TRACE; return 0; }
+void device_unlock(struct device *dev) { TRACE; }
+void device_del(struct device *dev) { TRACE; }
+void device_initialize(struct device *dev) { TRACE; }
+int device_attach(struct device *dev) { TRACE; return 0; }
+int device_is_registered(struct device *dev) { TRACE; return 0; }
+int device_bind_driver(struct device *dev) { TRACE; return 0; }
+void device_release_driver(struct device *dev) { TRACE; }
+void device_enable_async_suspend(struct device *dev) { TRACE; }
+void device_set_wakeup_capable(struct device *dev, bool capable) { TRACE; }
+int device_create_bin_file(struct device *dev,
+ const struct bin_attribute *attr) { TRACE; return 0; }
+void device_remove_bin_file(struct device *dev,
+ const struct bin_attribute *attr) { TRACE; }
+int device_create_file(struct device *device,
+ const struct device_attribute *entry) { TRACE; return 0; }
+void device_remove_file(struct device *dev,
+ const struct device_attribute *attr) { TRACE; }
+
+void put_device(struct device *dev) { TRACE; }
+
+void driver_unregister(struct device_driver *drv) { TRACE; }
+int driver_attach(struct device_driver *drv) { TRACE; return 0; }
+int driver_create_file(struct device_driver *driver,
+ const struct driver_attribute *attr) { TRACE; return 0; }
+void driver_remove_file(struct device_driver *driver,
+ const struct driver_attribute *attr) { TRACE; }
+
+struct device_driver *get_driver(struct device_driver *drv) { TRACE; return NULL; }
+void put_driver(struct device_driver *drv) { TRACE; }
+
+struct device *bus_find_device(struct bus_type *bus, struct device *start,
+ void *data,
+ int (*match)(struct device *dev, void *data)) { TRACE; return NULL; }
+int bus_register(struct bus_type *bus) { TRACE; return 0; }
+void bus_unregister(struct bus_type *bus) { TRACE; }
+int bus_register_notifier(struct bus_type *bus,
+ struct notifier_block *nb) { TRACE; return 0; }
+int bus_unregister_notifier(struct bus_type *bus,
+ struct notifier_block *nb) { TRACE; return 0; }
+
+struct class *__class_create(struct module *owner,
+ const char *name,
+ struct lock_class_key *key) { TRACE; return NULL; }
+int class_register(struct class *cls) { TRACE; return 0; }
+void class_unregister(struct class *cls) { TRACE; }
+void class_destroy(struct class *cls) { TRACE; }
+
+
+/*****************************
+ ** linux/platform_device.h **
+ *****************************/
+
+void *platform_get_drvdata(const struct platform_device *pdev) { TRACE; return NULL; }
+
+
+/********************
+ ** linux/dcache.h **
+ ********************/
+
+void d_instantiate(struct dentry *dentry, struct inode *i) { TRACE; }
+int d_unhashed(struct dentry *dentry) { TRACE; return 0; }
+void d_delete(struct dentry *d) { TRACE; }
+struct dentry *d_alloc_root(struct inode *i) { TRACE; return NULL; }
+struct dentry *dget(struct dentry *dentry) { TRACE; return NULL; }
+void dput(struct dentry *dentry) { TRACE; }
+
+void dont_mount(struct dentry *dentry) { TRACE; }
+
+
+/******************
+ ** linux/poll.h **
+ ******************/
+
+void poll_wait(struct file *f, wait_queue_head_t *w, poll_table *p) { TRACE; }
+
+
+/********************
+ ** linux/statfs.h **
+ ********************/
+
+loff_t default_llseek(struct file *file, loff_t offset, int origin) { TRACE; return 0; }
+
+
+/****************
+ ** linux/fs.h **
+ ****************/
+
+unsigned iminor(const struct inode *inode) { TRACE; return 0; }
+unsigned imajor(const struct inode *inode) { TRACE; return 0; }
+
+int register_chrdev_region(dev_t d, unsigned v, const char *s) { TRACE; return 0; }
+void unregister_chrdev_region(dev_t d, unsigned v) { TRACE; }
+void fops_put(struct file_operations const *fops) { TRACE; }
+loff_t noop_llseek(struct file *file, loff_t offset, int origin) { TRACE; return 0; }
+int register_chrdev(unsigned int major, const char *name,
+ const struct file_operations *fops) { TRACE; return 0; }
+void unregister_chrdev(unsigned int major, const char *name) { TRACE; }
+struct inode *new_inode(struct super_block *sb) { TRACE; return NULL; }
+unsigned int get_next_ino(void) { TRACE; return 0; }
+void init_special_inode(struct inode *i, umode_t m, dev_t d) { TRACE; }
+int generic_delete_inode(struct inode *inode) { TRACE; return 0; }
+void drop_nlink(struct inode *inode) { TRACE; }
+void inc_nlink(struct inode *inode) { TRACE; }
+void dentry_unhash(struct dentry *dentry) { TRACE; }
+void iput(struct inode *i) { TRACE; }
+struct dentry *mount_single(struct file_system_type *fs_type,
+ int flags, void *data,
+ int (*fill_super)(struct super_block *,
+ void *, int)) { TRACE; return NULL; }
+int nonseekable_open(struct inode *inode, struct file *filp) { TRACE; return 0; }
+int simple_statfs(struct dentry *d, struct kstatfs *k) { TRACE; return 0; }
+int simple_pin_fs(struct file_system_type *t, struct vfsmount **mount, int *count) { TRACE; return 0; }
+void simple_release_fs(struct vfsmount **mount, int *count) { TRACE; }
+void kill_litter_super(struct super_block *sb) { TRACE; }
+int register_filesystem(struct file_system_type *t) { TRACE; return 0; }
+int unregister_filesystem(struct file_system_type *t) { TRACE; return 0; }
+
+void kill_fasync(struct fasync_struct **fp, int sig, int band) { TRACE; }
+int fasync_add_entry(int fd, struct file *filp, struct fasync_struct **fapp) { TRACE; return 0; }
+const struct file_operations simple_dir_operations;
+const struct inode_operations simple_dir_inode_operations;
+
+
+/*******************
+ ** linux/namei.h **
+ *******************/
+
+struct dentry *lookup_one_len(const char *c, struct dentry *e, int v) { TRACE; return NULL; }
+
+
+/**********************
+ ** linux/seq_file.h **
+ **********************/
+
+int seq_printf(struct seq_file *f, const char *fmt, ...) { TRACE; return 0; }
+
+
+/*****************
+ ** linux/gfp.h **
+ *****************/
+
+unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order) { TRACE; return 0; }
+void __free_pages(struct page *p, unsigned int order) { TRACE; }
+void free_pages(unsigned long addr, unsigned int order) { TRACE; }
+
+
+/*********************
+ ** linux/proc_fs.h **
+ *********************/
+
+struct proc_dir_entry *proc_mkdir(const char *s,struct proc_dir_entry *e) { TRACE; return NULL; }
+void remove_proc_entry(const char *name, struct proc_dir_entry *parent) { TRACE; }
+
+
+/********************
+ * linux/debugfs.h **
+ ********************/
+
+struct dentry *debugfs_create_dir(const char *name, struct dentry *parent) { TRACE; return (struct dentry *)1; }
+struct dentry *debugfs_create_file(const char *name, mode_t mode,
+ struct dentry *parent, void *data,
+ const struct file_operations *fops) { TRACE; return (struct dentry *)1; }
+void debugfs_remove(struct dentry *dentry) { TRACE; }
+
+
+/************************
+ ** linux/page-flags.h **
+ ************************/
+
+bool is_highmem(void *ptr) { TRACE; return 0; }
+
+
+/****************
+ ** linux/mm.h **
+ ****************/
+
+struct zone *page_zone(const struct page *page) { TRACE; return NULL; }
+
+
+/**********************
+ ** linux/highmem.h **
+ **********************/
+
+void *kmap(struct page *page) { TRACE; return 0; }
+void kunmap(struct page *page) { TRACE; }
+
+
+/**********************
+ ** asm-generic/io.h **
+ **********************/
+
+void *ioremap(resource_size_t offset, unsigned long size) { TRACE; return NULL; }
+void iounmap(volatile void *addr) { TRACE; }
+void native_io_delay(void) { TRACE; }
+
+
+/********************
+ ** linux/ioport.h **
+ ********************/
+
+void release_region(resource_size_t start, resource_size_t n) { TRACE; }
+void release_mem_region(resource_size_t start, resource_size_t n) { TRACE; }
+
+/**
+ * SKIP
+ */
+
+/* implemented in Pci_driver */
+struct resource *request_region(resource_size_t start, resource_size_t n,
+ const char *name) { SKIP; return (struct resource *)1; }
+/* implemented in Pci_driver */
+struct resource *request_mem_region(resource_size_t start, resource_size_t n,
+ const char *name) { SKIP; return (struct resource *)1; }
+
+/***********************
+ ** linux/interrupt.h **
+ ***********************/
+
+void local_irq_enable(void) { TRACE; }
+void local_irq_disable(void) { TRACE; }
+void free_irq(unsigned int i, void *p) { TRACE; }
+
+
+/*********************
+ ** linux/hardirq.h **
+ *********************/
+
+void synchronize_irq(unsigned int irq) { TRACE; }
+
+
+/*****************
+ ** linux/pci.h **
+ *****************/
+int pci_bus_read_config_dword(struct pci_bus *bus, unsigned int devfn, int where, u32 *val) { TRACE; return 0; }
+int pci_bus_write_config_dword(struct pci_bus *bus, unsigned int devfn, int where, u32 val) { TRACE; return 0; }
+
+void *pci_get_drvdata(struct pci_dev *pdev) { TRACE; return NULL; }
+void pci_dev_put(struct pci_dev *dev) { TRACE; }
+struct pci_dev *pci_get_device(unsigned int vendor, unsigned int device,
+ struct pci_dev *from) { TRACE; return NULL; }
+
+
+void pci_disable_device(struct pci_dev *dev) { TRACE; }
+int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask) { TRACE; return 0; }
+
+void pci_unregister_driver(struct pci_driver *drv) { TRACE; }
+
+bool pci_dev_run_wake(struct pci_dev *dev) { TRACE; return 0; }
+int pci_set_mwi(struct pci_dev *dev) { TRACE; return 0; }
+int pci_find_capability(struct pci_dev *dev, int cap) { TRACE; return 0; }
+struct pci_dev *pci_get_slot(struct pci_bus *bus, unsigned int devfn) { TRACE; return NULL; }
+const struct pci_device_id *pci_match_id(const struct pci_device_id *ids,
+ struct pci_dev *dev) { TRACE; return 0; }
+void *pci_ioremap_bar(struct pci_dev *pdev, int bar);
+
+/**
+ * Omitted PCI functions
+ */
+/* scans resources, this is already implemented in 'pci_driver.cc' */
+int pci_enable_device(struct pci_dev *dev) { SKIP; return 0; }
+
+/* implemented in Pci_driver::_setup_pci_device */
+void pci_set_master(struct pci_dev *dev) { SKIP; }
+
+/**********************
+ ** linux/irqflags.h **
+ **********************/
+
+unsigned long local_irq_save(unsigned long flags) { SKIP; return 0; }
+unsigned long local_irq_restore(unsigned long flags) { SKIP; return 0; }
+
+
+/*************************
+ ** linux/dma-mapping.h **
+ *************************/
+
+void dma_unmap_single_attrs(struct device *dev, dma_addr_t addr,
+ size_t size,
+ enum dma_data_direction dir,
+ struct dma_attrs *attrs) { SKIP; }
+
+void dma_unmap_sg_attrs(struct device *dev, struct scatterlist *sg,
+ int nents, enum dma_data_direction dir,
+ struct dma_attrs *attrs) { SKIP; }
+
+
+void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
+ enum dma_data_direction direction) { SKIP;; }
+
+int dma_mapping_error(struct device *dev, dma_addr_t dma_addr) { SKIP; return 0; }
+
+/*****************
+ ** linux/pid.h **
+ *****************/
+
+void put_pid(struct pid *pid) { TRACE; }
+struct pid *get_pid(struct pid *pid) { TRACE; return NULL; }
+
+
+/******************
+ ** linux/cred.h **
+ ******************/
+
+void put_cred(struct cred const *c) { TRACE; }
+const struct cred *get_cred(const struct cred *cred) { TRACE; return NULL; }
+
+
+/**********************
+ ** linux/security.h **
+ **********************/
+
+void security_task_getsecid(struct task_struct *p, u32 *secid) { TRACE; }
+
+
+/******************
+ ** linux/cdev.h **
+ ******************/
+
+void cdev_init(struct cdev *c, const struct file_operations *fops) { TRACE; }
+int cdev_add(struct cdev *c, dev_t d, unsigned v) { TRACE; return 0; }
+void cdev_del(struct cdev *c) { TRACE; }
+
+
+/*********************
+ ** linux/utsname.h **
+ *********************/
+
+struct new_utsname *init_utsname(void)
+{
+ static struct new_utsname uts = { .sysname = "Genode.UTS", .release = "1.0" };
+ return &uts;
+}
+struct new_utsname *utsname(void) { TRACE; return NULL; }
+
+
+/*********************
+ ** linux/freezer.h **
+ *********************/
+
+void set_freezable(void) { TRACE; }
+
+
+/********************
+ ** linux/parser.h **
+ ********************/
+
+int match_token(char *s, const match_table_t table, substring_t args[]) { TRACE; return 0; }
+int match_int(substring_t *s, int *result) { TRACE; return 0; }
+int match_octal(substring_t *s, int *result) { TRACE; return 0; }
+
+
+/*********************
+ ** linux/semaphore **
+ *********************/
+void sema_init(struct semaphore *sem, int val) { TRACE; }
+int down_trylock(struct semaphore *sem) { TRACE; return 0; }
+int down_interruptible(struct semaphore *sem) { TRACE; return 0; }
+void up(struct semaphore *sem) { TRACE; }
+
+
+/*******************
+ ** linux/input.h **
+ *******************/
+
+void input_ff_destroy(struct input_dev *dev) { TRACE; }
+int input_ff_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { TRACE; return 0; }
+int input_ff_upload(struct input_dev *dev, struct ff_effect *effect, struct file *file) { TRACE; return 0; }
+int input_ff_erase(struct input_dev *dev, int effect_id, struct file *file) { TRACE; return 0; }
+
+/*********************
+ ** input-compat.h" **
+ *********************/
+
+int input_event_from_user(const char __user *buffer, struct input_event *event) { TRACE; return 0; }
+int input_event_to_user(char __user *buffer, const struct input_event *event) { TRACE; return 0; }
+int input_ff_effect_from_user(const char __user *buffer, size_t size, struct ff_effect *effect) { TRACE; return 0;}
+
+/****************
+ ** linux/mt.h **
+ ****************/
+
+void input_mt_destroy_slots(struct input_dev *dev) { TRACE; }
+
+
+/*********************
+ ** linux/vmalloc.h **
+ *********************/
+
+void *vmalloc(unsigned long size) { TRACE; return 0; }
+
+
+/********************
+ ** linux/blkdev.h **
+ ********************/
+
+void blk_queue_bounce_limit(struct request_queue *q, u64 dma_mask) { TRACE; }
+void blk_queue_update_dma_alignment(struct request_queue *q, int mask) { TRACE; }
+void blk_queue_max_hw_sectors(struct request_queue *q, unsigned int max_hw_sectors) { TRACE; }
+unsigned int queue_max_hw_sectors(struct request_queue *q) { TRACE; return 0; }
+
+
+/**********************
+ ** scsi/scsi_cmnd.h **
+ **********************/
+
+void scsi_set_resid(struct scsi_cmnd *cmd, int resid) { TRACE; }
+int scsi_get_resid(struct scsi_cmnd *cmd) { TRACE; return 0; }
+
+
+/********************
+ ** scsi/scsi_eh.h **
+ *******************/
+
+void scsi_report_bus_reset(struct Scsi_Host *shost, int channel) { TRACE; }
+void scsi_report_device_reset(struct Scsi_Host *shost, int channel, int target) { TRACE; }
+
+void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd,
+ struct scsi_eh_save *ses, unsigned char *cmnd,
+ int cmnd_size, unsigned sense_bytes) { TRACE; }
+
+void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd,
+ struct scsi_eh_save *ses) { TRACE; }
+
+
+int scsi_normalize_sense(const u8 *sense_buffer, int sb_len,
+ struct scsi_sense_hdr *sshdr) { TRACE; return 0; }
+
+const u8 * scsi_sense_desc_find(const u8 * sense_buffer, int sb_len,
+ int desc_type) { TRACE; return 0; }
+
+
+/***********************
+ ** drivers/scsi/sd.h **
+ **********************/
+
+struct scsi_disk *scsi_disk(struct gendisk *disk) { TRACE; return 0; }
+
+
+/**********************
+ ** scsi/scsi_host.h **
+ **********************/
+int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev,
+ struct device *dma_dev) { TRACE; return 0; }
+void scsi_remove_host(struct Scsi_Host *shost) { TRACE; }
+void scsi_host_put(struct Scsi_Host *shost) { TRACE; }
+struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost) { TRACE; return 0; }
+
+
diff --git a/dde_linux/src/drivers/usb/input/evdev.c b/dde_linux/src/drivers/usb/input/evdev.c
new file mode 100644
index 000000000..a96cb2923
--- /dev/null
+++ b/dde_linux/src/drivers/usb/input/evdev.c
@@ -0,0 +1,136 @@
+/*
+ * \brief Input service and event handler
+ * \author Christian Helmuth
+ * \author Dirk Vogt
+ * \author Sebastian Sumpf
+ * \date 2009-04-20
+ *
+ * The original implementation was in the L4Env from the TUD:OS group
+ * (l4/pkg/input/lib/src/l4evdev.c). This file was released under the terms of
+ * the GNU General Public License version 2.
+ */
+
+/* Linux */
+#include
+
+/* Local */
+#include
+
+/* Callback function to Genode subsystem */
+static genode_input_event_cb handler;;
+
+void genode_evdev_event(struct input_handle *handle, unsigned int type,
+ unsigned int code, int value)
+{
+#if DEBUG_EVDEV
+ static unsigned long count = 0;
+#endif
+
+ /* filter sound events */
+ if (test_bit(EV_SND, handle->dev->evbit)) return;
+
+ /* filter input_repeat_key() */
+ if ((type == EV_KEY) && (value == 2)) return;
+
+ /* filter EV_SYN */
+ if (type == EV_SYN) return;
+
+ /* generate arguments and call back */
+ enum input_event_type arg_type;
+ unsigned arg_keycode = KEY_UNKNOWN;
+ int arg_ax = 0, arg_ay = 0, arg_rx = 0, arg_ry = 0;
+
+ switch (type) {
+
+ case EV_KEY:
+ arg_keycode = code;
+ switch (value) {
+
+ case 0:
+ arg_type = EVENT_TYPE_RELEASE;
+ break;
+
+ case 1:
+ arg_type = EVENT_TYPE_PRESS;
+ break;
+
+ default:
+ printk("Unknown key event value %d - not handled\n", value);
+ return;
+ }
+ break;
+
+ case EV_ABS:
+ switch (code) {
+
+ case ABS_X:
+ arg_type = EVENT_TYPE_MOTION;
+ arg_ax = value;
+ break;
+
+ case ABS_Y:
+ arg_type = EVENT_TYPE_MOTION;
+ arg_ay = value;
+ break;
+
+ case ABS_WHEEL:
+ /*
+ * XXX I do not know, how to handle this correctly. At least, this
+ * scheme works on Qemu.
+ */
+ arg_type = EVENT_TYPE_WHEEL;
+ arg_ry = value;
+ break;
+
+ default:
+ printk("Unknown absolute event code %d - not handled\n", code);
+ return;
+ }
+ break;
+
+ case EV_REL:
+ switch (code) {
+
+ case REL_X:
+ arg_type = EVENT_TYPE_MOTION;
+ arg_rx = value;
+ break;
+
+ case REL_Y:
+ arg_type = EVENT_TYPE_MOTION;
+ arg_ry = value;
+ break;
+
+ case REL_HWHEEL:
+ arg_type = EVENT_TYPE_WHEEL;
+ arg_rx = value;
+ break;
+
+ case REL_WHEEL:
+ arg_type = EVENT_TYPE_WHEEL;
+ arg_ry = value;
+ break;
+
+ default:
+ printk("Unknown relative event code %d - not handled\n", code);
+ return;
+ }
+ break;
+
+ default:
+ printk("Unknown event type %d - not handled\n", type);
+ return;
+ }
+
+ if (handler)
+ handler(arg_type, arg_keycode, arg_ax, arg_ay, arg_rx, arg_ry);
+ printk("EVENT: t: %x c: %x ax: %d ay %d rx: %d ry %d\n",
+ arg_type, arg_keycode, arg_ax, arg_ay, arg_rx, arg_ry);
+#if DEBUG_EVDEV
+ printk("event[%ld]. dev: %s, type: %d, code: %d, value: %d\n",
+ count++, handle->dev->name, type, code, value);
+#endif
+}
+
+void genode_input_register(genode_input_event_cb h) { handler = h; }
+
diff --git a/dde_linux/src/drivers/usb/input/input_component.cc b/dde_linux/src/drivers/usb/input/input_component.cc
new file mode 100644
index 000000000..2568ea1dc
--- /dev/null
+++ b/dde_linux/src/drivers/usb/input/input_component.cc
@@ -0,0 +1,77 @@
+/*
+ * \brief Linux 2.6 Input driver for USB HID
+ * \author Christian Helmuth
+ * \author Christian Prochaska
+ * \author Sebastian Sumpf
+ * \date 2011-07-15
+ */
+
+/*
+ * Copyright (C) 2011-2012 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.
+ */
+
+#include
+#include
+#include
+#include
+
+#include
+
+#undef RELEASE
+
+using namespace Genode;
+
+
+/*********************
+ ** Input component **
+ *********************/
+
+typedef Ring_buffer Input_ring_buffer;
+
+static Input_ring_buffer ev_queue;
+
+namespace Input {
+
+ void event_handling(bool enable) { }
+ bool event_pending() { return !ev_queue.empty(); }
+ Event get_event() { return ev_queue.get(); }
+}
+
+
+/**
+ * Input event call-back function
+ */
+static void input_callback(enum input_event_type type,
+ unsigned keycode,
+ int absolute_x, int absolute_y,
+ int relative_x, int relative_y)
+{
+ Input::Event::Type t = Input::Event::INVALID;
+ switch (type) {
+ case EVENT_TYPE_PRESS: t = Input::Event::PRESS; break;
+ case EVENT_TYPE_RELEASE: t = Input::Event::RELEASE; break;
+ case EVENT_TYPE_MOTION: t = Input::Event::MOTION; break;
+ case EVENT_TYPE_WHEEL: t = Input::Event::WHEEL; break;
+ }
+
+ try {
+ ev_queue.add(Input::Event(t, keycode,
+ absolute_x, absolute_y,
+ relative_x, relative_y));
+ } catch (Input_ring_buffer::Overflow) {
+ PWRN("input ring buffer overflow");
+ }
+}
+
+
+void start_input_service(void *ep)
+{
+ Rpc_entrypoint *e = static_cast(ep);
+ static Input::Root input_root(e, env()->heap());
+ env()->parent()->announce(e->manage(&input_root));
+
+ genode_input_register(input_callback);
+}
diff --git a/dde_linux/src/drivers/usb/lx_emul.cc b/dde_linux/src/drivers/usb/lx_emul.cc
new file mode 100644
index 000000000..a8d4a2755
--- /dev/null
+++ b/dde_linux/src/drivers/usb/lx_emul.cc
@@ -0,0 +1,770 @@
+/*
+ * \brief Emulation of Linux kernel interfaces
+ * \author Norman Feske
+ * \author Sebastian Sumpf
+ * \date 2012-01-29
+ */
+
+/*
+ * Copyright (C) 2012 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 includes */
+#include
+#include
+#include
+#include
+#include
+
+/* Local includes */
+#include "routine.h"
+#include "signal.h"
+#include "lx_emul.h"
+
+/* DDE kit includes */
+extern "C" {
+#include
+#include
+#include
+#include
+#include
+#include
+}
+
+
+#if VERBOSE_LX_EMUL
+#define TRACE dde_kit_printf("\033[35m%s\033[0m called\n", __PRETTY_FUNCTION__)
+#define UNSUPPORTED dde_kit_printf("\033[31m%s\033[0m unsupported arguments\n", __PRETTY_FUNCTION__)
+#else
+#define TRACE
+#define UNSUPPORTED
+#endif
+
+/***********************
+ ** Atomic operations **
+ ***********************/
+
+/*
+ * Actually not atomic, for now
+ */
+
+unsigned int atomic_read(atomic_t *p) { return *(volatile int *)p; }
+
+void atomic_inc(atomic_t *v) { (*(volatile int *)v)++; }
+void atomic_dec(atomic_t *v) { (*(volatile int *)v)--; }
+
+void atomic_add(int i, atomic_t *v) { (*(volatile int *)v) += i; }
+void atomic_sub(int i, atomic_t *v) { (*(volatile int *)v) -= i; }
+
+void atomic_set(atomic_t *p, unsigned int v) { (*(volatile int *)p) = v; }
+
+/*******************
+ ** linux/mutex.h **
+ *******************/
+
+void mutex_init (struct mutex *m) { if (m->lock) dde_kit_lock_init (&m->lock); }
+void mutex_lock (struct mutex *m) { if (m->lock) dde_kit_lock_lock ( m->lock); }
+void mutex_unlock(struct mutex *m) { if (m->lock) dde_kit_lock_unlock( m->lock); }
+
+
+/*************************************
+ ** Memory allocation, linux/slab.h **
+ *************************************/
+
+void *kmalloc(size_t size, gfp_t flags)
+{
+ return dde_kit_large_malloc(size);
+}
+
+
+void *kzalloc(size_t size, gfp_t flags)
+{
+ void *addr = dde_kit_large_malloc(size);
+ if (addr)
+ Genode::memset(addr, 0, size);
+ return addr;
+}
+
+
+void *kcalloc(size_t n, size_t size, gfp_t flags)
+{
+ if (size != 0 && n > ~0UL / size)
+ return 0;
+
+ return kzalloc(n * size, flags);
+}
+
+void kfree(const void *p)
+{
+ dde_kit_large_free((void *)p);
+}
+
+
+/*********************
+ ** linux/vmalloc.h **
+ *********************/
+
+void *vzalloc(unsigned long size)
+{
+ void *ptr = dde_kit_simple_malloc(size);
+ if (ptr)
+ Genode::memset(ptr, 0, size);
+
+ return ptr;
+}
+
+
+void vfree(void *addr) { dde_kit_simple_free(addr); }
+
+
+/******************
+ ** linux/kref.h **
+ ******************/
+
+void kref_init(struct kref *kref)
+{
+ dde_kit_log(DEBUG_KREF,"%s ref: %p", __func__, kref);
+ kref->refcount.v = 1;
+}
+
+
+void kref_get(struct kref *kref)
+{
+ kref->refcount.v++;
+ dde_kit_log(DEBUG_KREF, "%s ref: %p c: %d", __func__, kref, kref->refcount.v);
+}
+
+
+int kref_put(struct kref *kref, void (*release) (struct kref *kref))
+{
+ dde_kit_log(DEBUG_KREF, "%s: ref: %p c: %d", __func__, kref, kref->refcount.v);
+
+ if (!--kref->refcount.v) {
+ release(kref);
+ return 1;
+ }
+ return 0;
+}
+
+
+/*********************
+ ** linux/uaccess.h **
+ *********************/
+
+size_t copy_to_user(void *dst, void const *src, size_t len)
+{
+ if (dst && src && len)
+ Genode::memcpy(dst, src, len);
+ return 0;
+}
+
+
+size_t copy_from_user(void *dst, void const *src, size_t len)
+{
+ if (dst && src && len)
+ Genode::memcpy(dst, src, len);
+ return 0;
+}
+
+
+bool access_ok(int access, void *addr, size_t size) { return 1; }
+
+
+/********************
+ ** linux/string.h **
+ ********************/
+
+void *memcpy(void *dest, const void *src, size_t n) {
+ return Genode::memcpy(dest, src, n); }
+
+
+void *memset(void *s, int c, size_t n) {
+ return Genode::memset(s, c, n); }
+
+
+int snprintf(char *buf, size_t size, const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ Genode::String_console sc(buf, size);
+ sc.vprintf(fmt, args);
+ va_end(args);
+
+ return sc.len();
+}
+
+
+size_t strlen(const char *s) { return Genode::strlen(s); }
+
+
+size_t strlcat(char *dest, const char *src, size_t n)
+{
+ size_t len = strlen(dest);
+ Genode::strncpy(dest + len, src, n);
+ dest[len + n] = 0;
+ return n;
+}
+
+
+void *kmemdup(const void *src, size_t len, gfp_t gfp)
+{
+ void *ptr = kmalloc(len, 0);
+ memcpy(ptr, src, len);
+ return ptr;
+}
+
+
+void *memscan(void *addr, int c, size_t size)
+{
+ unsigned char* p = (unsigned char *)addr;
+
+ for (size_t s = 0; s < size; s++, p++)
+ if (*p == c)
+ break;
+
+ return (void *)p;
+}
+
+
+/******************
+ ** linux/log2.h **
+ ******************/
+
+int ilog2(u32 n) { return Genode::log2(n); }
+
+
+/********************
+ ** linux/slab.h **
+ ********************/
+
+struct kmem_cache
+{
+ const char *name; /* cache name */
+ unsigned size; /* object size */
+
+ struct dde_kit_slab *dde_kit_slab_cache; /* backing DDE kit cache */
+};
+
+
+struct kmem_cache *kmem_cache_create(const char *name, size_t size, size_t align,
+ unsigned long falgs, void (*ctor)(void *))
+{
+ dde_kit_log(DEBUG_SLAB, "\"%s\" obj_size=%d", name, size);
+
+ struct kmem_cache *cache;
+
+ if (!name) {
+ printk("kmem_cache name reqeuired\n");
+ return 0;
+ }
+
+ cache = (struct kmem_cache *)dde_kit_simple_malloc(sizeof(*cache));
+ if (!cache) {
+ printk("No memory for slab cache\n");
+ return 0;
+ }
+
+ /* initialize a physically contiguous cache for kmem */
+ if (!(cache->dde_kit_slab_cache = dde_kit_slab_init(size))) {
+ printk("DDE kit slab init failed\n");
+ dde_kit_simple_free(cache);
+ return 0;
+ }
+
+ cache->name = name;
+ cache->size = size;
+
+ return cache;
+}
+
+
+void kmem_cache_destroy(struct kmem_cache *cache)
+{
+ dde_kit_log(DEBUG_SLAB, "\"%s\"", cache->name);
+
+ dde_kit_slab_destroy(cache->dde_kit_slab_cache);
+ dde_kit_simple_free(cache);
+}
+
+
+void *kmem_cache_zalloc(struct kmem_cache *cache, gfp_t flags)
+{
+ void *ret;
+
+ dde_kit_log(DEBUG_SLAB, "\"%s\" flags=%x", cache->name, flags);
+
+ ret = dde_kit_slab_alloc(cache->dde_kit_slab_cache);
+
+ /* return here in case of error */
+ if (!ret) return 0;
+
+ /* zero page */
+ memset(ret, 0, cache->size);
+
+ return ret;
+}
+
+
+void kmem_cache_free(struct kmem_cache *cache, void *objp)
+{
+ dde_kit_log(DEBUG_SLAB, "\"%s\" (%p)", cache->name, objp);
+ dde_kit_slab_free(cache->dde_kit_slab_cache, objp);
+}
+
+
+/**********************
+ ** asm-generic/io.h **
+ **********************/
+
+void *ioremap_wc(resource_size_t phys_addr, unsigned long size)
+{
+ dde_kit_addr_t map_addr;
+ if (dde_kit_request_mem(phys_addr, size, 1, &map_addr)) {
+ PERR("Failed to request I/O memory: [%x,%lx)", phys_addr, phys_addr + size);
+ return 0;
+ }
+
+ return (void *)map_addr;
+}
+
+
+/********************
+ ** linux/device.h **
+ ********************/
+
+/**
+ * Simple driver management class
+ */
+class Driver : public Genode::List::Element
+{
+ private:
+
+ struct device_driver *_drv; /* Linux driver */
+
+ public:
+
+ Driver(struct device_driver *drv) : _drv(drv)
+ {
+ list()->insert(this);
+ }
+
+ /**
+ * List of all currently registered drivers
+ */
+ static Genode::List *list()
+ {
+ static Genode::List _list;
+ return &_list;
+ }
+
+ /**
+ * Match device and drivers
+ */
+ bool match(struct device *dev)
+ {
+ bool ret = _drv->bus->match ? _drv->bus->match(dev, _drv) : true;
+ dde_kit_log(DEBUG_DRIVER, "MATCH: %s ret: %u match: %p",
+ _drv->name, ret, _drv->bus->match);
+ return ret;
+ }
+
+ /**
+ * Probe device with driver
+ */
+ int probe(struct device *dev)
+ {
+ dev->driver = _drv;
+
+ if (dev->bus->probe) {
+ dde_kit_log(DEBUG_DRIVER, "Probing device bus");
+ return dev->bus->probe(dev);
+ } else if (_drv->probe) {
+ dde_kit_log(DEBUG_DRIVER, "Probing driver: %s", _drv->name);
+ return _drv->probe(dev);
+ }
+
+ return 0;
+ }
+};
+
+
+int driver_register(struct device_driver *drv)
+{
+ dde_kit_log(DEBUG_DRIVER, "%s at %p", drv->name, drv);
+ new (Genode::env()->heap()) Driver(drv);
+ return 0;
+}
+
+
+int device_add(struct device *dev)
+{
+ if (dev->driver)
+ return 0;
+
+ /* foreach driver match and probe device */
+ for (Driver *driver = Driver::list()->first(); driver; driver = driver->next())
+ if (driver->match(dev)) {
+ int ret = driver->probe(dev);
+ dde_kit_log(DEBUG_DRIVER, "Probe return %d", ret);
+ if (!ret)
+ return 0;
+ }
+
+ return 0;
+}
+
+
+int device_register(struct device *dev)
+{
+ //XXX: initialize DMA pools (see device_initialize)
+ return device_add(dev);
+}
+
+
+void *dev_get_drvdata(const struct device *dev)
+{
+ return dev->driver_data;
+}
+
+
+int dev_set_drvdata(struct device *dev, void *data)
+{
+ dev->driver_data = data; return 0;
+}
+
+
+struct device *get_device(struct device *dev) { TRACE; return dev; }
+
+
+long find_next_zero_bit_le(const void *addr,
+ unsigned long size, unsigned long offset)
+{
+ unsigned long max_size = sizeof(long) * 8;
+ if (offset >= max_size) {
+ PWRN("Offset greater max size");
+ return offset + size;
+ }
+
+ for (; offset < max_size; offset++)
+ if (!(*(unsigned long*)addr & (1 << offset)))
+ return offset;
+
+ PERR("No zero bit findable");
+ return offset + size;
+}
+
+
+/*******************************
+ ** linux/byteorder/generic.h **
+ *******************************/
+
+void put_unaligned_le32(u32 val, void *p)
+{
+ struct __una_u32 *ptr = (struct __una_u32 *)p;
+ ptr->x = val;
+}
+
+
+u64 get_unaligned_le64(const void *p)
+{
+ struct __una_u64 *ptr = (struct __una_u64 *)p;
+ return ptr->x;
+}
+
+
+void put_unaligned_le64(u64 val, void *p)
+{
+ struct __una_u64 *ptr = (struct __una_u64 *)p;
+ ptr->x = val;
+}
+
+
+/**********************************
+ ** linux/bitops.h, asm/bitops.h **
+ **********************************/
+
+int fls(int x)
+{
+ if (!x)
+ return 0;
+
+ for (int i = 31; i >= 0; i--)
+ if (x & (1 << i))
+ return i;
+
+ return 0;
+}
+
+
+/*******************
+ ** linux/delay.h **
+ *******************/
+
+static Timer::Connection _timer;
+
+
+void udelay(unsigned long usecs)
+{
+ _timer.msleep(usecs < 1000 ? 1 : usecs / 1000);
+}
+
+
+void msleep(unsigned int msecs) { _timer.msleep(msecs); }
+
+
+/*********************
+ ** linux/jiffies.h **
+ *********************/
+
+/*
+ * We use DDE kit's jiffies in 100Hz granularity.
+ */
+enum { JIFFIES_TICK_MS = 1000 / DDE_KIT_HZ };
+
+unsigned long msecs_to_jiffies(const unsigned int m) { return m / JIFFIES_TICK_MS; }
+long time_after_eq(long a, long b) { return (a - b) >= 0; }
+long time_after(long a, long b) { return (b - a) > 0; }
+
+
+/*********************
+ ** linux/dmapool.h **
+ *********************/
+
+namespace Genode {
+
+ /**
+ * Dma-pool manager
+ */
+ class Dma
+ {
+ private:
+
+ enum { SIZE = 1024 * 1024 };
+
+ addr_t _base; /* virt base of pool */
+ addr_t _base_phys; /* phys base of pool */
+ Allocator_avl _range; /* range allocator for pool */
+
+ Dma() : _range(env()->heap())
+ {
+ Ram_dataspace_capability cap = env()->ram_session()->alloc(SIZE);
+ _base_phys = Dataspace_client(cap).phys_addr();
+ _base = (addr_t)env()->rm_session()->attach(cap);
+ dde_kit_log(DEBUG_DMA, "New DMA range [%lx-%lx)", _base, _base + SIZE);
+ _range.add_range(_base, SIZE);
+ }
+
+ public:
+
+ static Dma* pool()
+ {
+ static Dma _p;
+ return &_p;
+ }
+
+ /**
+ * Alloc 'size' bytes of DMA memory
+ */
+ void *alloc(size_t size, int align = PAGE_SHIFT)
+ {
+ void *addr;
+ if (!_range.alloc_aligned(size, &addr, align)) {
+ PERR("DMA of %zu bytes allocation failed", size);
+ return 0;
+ }
+
+ return addr;
+ }
+
+ /**
+ * Free DMA memory
+ */
+ void free(void *addr) { _range.free(addr); }
+
+ /**
+ * Get phys for virt address
+ */
+ addr_t phys_addr(void *addr)
+ {
+ addr_t a = (addr_t)addr;
+ if (a < _base || a >= _base + SIZE) {
+ PERR("No DMA phys addr for %lx", a);
+ return 0;
+ }
+ return (a - _base) + _base_phys;
+ }
+ };
+}
+
+
+struct dma_pool
+{
+ size_t size;
+ int align;
+};
+
+
+struct dma_pool *dma_pool_create(const char *name, struct device *d, size_t size,
+ size_t align, size_t alloc)
+{
+ dde_kit_log(DEBUG_DMA, "size: %zx align:%zx", size, align);
+
+ if (align & (align - 1))
+ return 0;
+
+ dma_pool *pool = new(Genode::env()->heap()) dma_pool;
+ pool->align = Genode::log2((int)align);
+ pool->size = size;
+ return pool;
+}
+
+
+void dma_pool_destroy(struct dma_pool *d)
+{
+ dde_kit_log(DEBUG_DMA, "close");
+ destroy(Genode::env()->heap(), d);
+}
+
+
+static void* _alloc(size_t size, int align, dma_addr_t *dma)
+{
+ void *addr = Genode::Dma::pool()->alloc(size, align);
+ dde_kit_log(DEBUG_DMA, "addr: %p size %zx align: %d", addr, size, align);
+
+ if (!addr)
+ return 0;
+
+ *dma = (dma_addr_t)Genode::Dma::pool()->phys_addr(addr);
+ return addr;
+}
+
+
+void *dma_pool_alloc(struct dma_pool *d, gfp_t f, dma_addr_t *dma)
+{
+ return _alloc(d->size, d->align, dma);
+}
+
+
+void dma_pool_free(struct dma_pool *d, void *vaddr, dma_addr_t a)
+{
+ dde_kit_log(DEBUG_DMA, "free: addr %p, size: %zx", vaddr, d->size);
+ Genode::Dma::pool()->free(vaddr);
+}
+
+
+void *dma_alloc_coherent(struct device *, size_t size, dma_addr_t *dma, gfp_t)
+{
+ return _alloc(size, PAGE_SHIFT, dma);
+}
+
+
+void dma_free_coherent(struct device *, size_t size, void *vaddr, dma_addr_t)
+{
+ dde_kit_log(DEBUG_DMA, "free: addr %p, size: %zx", vaddr, size);
+ Genode::Dma::pool()->free(vaddr);
+}
+
+
+/*************************
+ ** linux/dma-mapping.h **
+ *************************/
+
+/**
+ * Translate virt to phys using DDE-kit
+ */
+dma_addr_t dma_map_single_attrs(struct device *dev, void *ptr,
+ size_t size,
+ enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+{
+ dma_addr_t phys = (dma_addr_t)dde_kit_pgtab_get_physaddr(ptr);
+ dde_kit_log(DEBUG_DMA, "virt: %p phys: %lx", ptr, phys);
+ return phys;
+}
+
+
+dma_addr_t dma_map_page(struct device *dev, struct page *page,
+ size_t offset, size_t size,
+ enum dma_data_direction dir)
+{
+ dde_kit_log(DEBUG_DMA, "virt: %p phys: %lx offs: %zx", page->virt, page->phys, offset);
+ return page->phys + offset;
+}
+
+
+int dma_map_sg_attrs(struct device *dev, struct scatterlist *sg,
+ int nents, enum dma_data_direction dir,
+ struct dma_attrs *attrs) { return nents; }
+
+
+/***********************
+ ** linux/workquque.h **
+ ***********************/
+
+int schedule_delayed_work(struct delayed_work *work, unsigned long delay)
+{
+ work->work.func(&(work)->work);
+ return 0;
+}
+
+
+/*********************
+ ** linux/kthread.h **
+ *********************/
+
+struct task_struct *kthread_run(int (*fn)(void *), void *arg, const char *n, ...)
+{
+ dde_kit_log(DEBUG_THREAD, "Run %s", n);
+ Routine::add(fn, arg, n);
+ return 0;
+}
+
+
+struct task_struct *kthread_create(int (*threadfn)(void *data),
+ void *data,
+ const char namefmt[], ...)
+{
+ /*
+ * This is just called for delayed device scanning (see
+ * 'drivers/usb/storage/usb.c')
+ */
+ dde_kit_log(DEBUG_THREAD, "Create %s", namefmt);
+ Routine::add(threadfn, data, namefmt);
+ return 0;
+}
+
+
+/*************************
+ ** linux/scatterlist.h **
+ *************************/
+
+struct scatterlist *sg_next(struct scatterlist *sg)
+{
+ if (sg->last)
+ return 0;
+
+ return sg++;
+}
+
+
+struct page *sg_page(struct scatterlist *sg)
+{
+ if (!sg)
+ return 0;
+
+ return (page *)sg->page_link;
+}
+
+
+void *sg_virt(struct scatterlist *sg)
+{
+ if (!sg || !sg->page_link)
+ return 0;
+
+ struct page *page = (struct page *)sg->page_link;
+ return (void *)((unsigned long)page->virt + sg->offset);
+}
diff --git a/dde_linux/src/drivers/usb/lx_emul.h b/dde_linux/src/drivers/usb/lx_emul.h
new file mode 100644
index 000000000..cecc5a4eb
--- /dev/null
+++ b/dde_linux/src/drivers/usb/lx_emul.h
@@ -0,0 +1,2647 @@
+/*
+ * \brief Emulation of the Linux kernel API
+ * \author Norman Feske
+ * \author Sebastian Sumpf
+ * \date 2012-01-28
+ *
+ * The content of this file, in particular data structures, is partially
+ * derived from Linux-internal headers.
+ */
+
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#ifndef _LX_EMUL_H_
+#define _LX_EMUL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* DDE Kit includes */
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#define VERBOSE_LX_EMUL 0
+
+
+#if VERBOSE_LX_EMUL
+#define DEBUG_COMPLETION 1
+#define DEBUG_DMA 0
+#define DEBUG_DRIVER 1
+#define DEBUG_IRQ 1
+#define DEBUG_KREF 0
+#define DEBUG_PCI 1
+#define DEBUG_SLAB 0
+#define DEBUG_TIMER 1
+#define DEBUG_THREAD 1
+#else
+#define DEBUG_COMPLETION 0
+#define DEBUG_DRIVER 0
+#define DEBUG_DMA 0
+#define DEBUG_IRQ 0
+#define DEBUG_KREF 0
+#define DEBUG_SLAB 0
+#define DEBUG_PCI 0
+#define DEBUG_TIMER 0
+#define DEBUG_THREAD 0
+#endif
+
+#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
+#define LINUX_VERSION_CODE KERNEL_VERSION(3,2,2)
+
+#define KBUILD_MODNAME "mod-noname"
+
+/***************
+ ** asm/bug.h **
+ ***************/
+
+#define WARN_ON(condition) ({ \
+ int ret = !!(condition); \
+ if (ret) dde_kit_debug("[%s] WARN_ON(" #condition ") ", __func__); \
+ ret; })
+
+#define WARN(condition, fmt, arg...) ({ \
+ int ret = !!(condition); \
+ if (ret) dde_kit_debug("[%s] *WARN* " fmt , __func__ , ##arg); \
+ ret; })
+
+#define BUG() do { \
+ dde_kit_debug("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \
+ while (1); \
+} while (0)
+
+#define WARN_ON_ONCE WARN_ON
+#define WARN_ONCE WARN
+
+#define BUG_ON(condition) do { if (condition) BUG(); } while(0)
+
+
+/*****************
+ ** asm/param.h **
+ *****************/
+
+enum { HZ = 100UL };
+
+
+/*******************
+ ** linux/magic.h **
+ *******************/
+
+enum { USBDEVICE_SUPER_MAGIC = 0x9fa2 };
+
+
+/******************
+ ** asm/atomic.h **
+ ******************/
+
+typedef struct atomic { unsigned int v; } atomic_t;
+
+void atomic_set(atomic_t *p, unsigned int v);
+unsigned int atomic_read(atomic_t *p);
+
+void atomic_inc(atomic_t *v);
+void atomic_dec(atomic_t *v);
+
+void atomic_add(int i, atomic_t *v);
+void atomic_sub(int i, atomic_t *v);
+int atomic_inc_return(atomic_t *v);
+
+#define ATOMIC_INIT(i) { (i) }
+
+
+/*******************
+ ** linux/types.h **
+ *******************/
+
+typedef dde_kit_int8_t int8_t;
+typedef dde_kit_uint8_t uint8_t;
+typedef dde_kit_int16_t int16_t;
+typedef dde_kit_uint16_t uint16_t;
+typedef dde_kit_int32_t int32_t;
+typedef dde_kit_uint32_t uint32_t;
+typedef dde_kit_size_t size_t;
+typedef dde_kit_int64_t int64_t;
+typedef dde_kit_uint64_t uint64_t;
+
+typedef uint32_t uint;
+
+typedef int8_t s8;
+typedef uint8_t u8;
+typedef int16_t s16;
+typedef uint16_t u16;
+typedef int32_t s32;
+typedef uint32_t u32;
+typedef int64_t s64;
+typedef uint64_t u64;
+
+typedef int8_t __s8;
+typedef uint8_t __u8;
+typedef int16_t __s16;
+typedef uint16_t __u16;
+typedef int32_t __s32;
+typedef uint32_t __u32;
+typedef int64_t __s64;
+typedef uint64_t __u64;
+
+typedef __u16 __le16;
+typedef __u32 __le32;
+typedef __u64 __le64;
+typedef __u16 __be16;
+typedef __u32 __be32;
+typedef __u64 __be64;
+
+typedef u64 sector_t;
+
+struct list_head {
+ struct list_head *next, *prev;
+};
+
+struct hlist_head {
+ struct hlist_node *first;
+};
+
+struct hlist_node {
+ struct hlist_node *next, **pprev;
+};
+
+#ifndef __cplusplus
+typedef int bool;
+enum { true = 1, false = 0 };
+#endif /* __cplusplus */
+
+#ifndef NULL
+#ifdef __cplusplus
+#define NULL 0
+#else
+#define NULL ((void *)0)
+#endif /* __cplusplus */
+#endif /* NULL */
+
+typedef unsigned gfp_t;
+typedef unsigned long pgoff_t;
+typedef long long loff_t;
+typedef long ssize_t;
+typedef unsigned long uintptr_t;
+typedef int dev_t;
+typedef size_t resource_size_t;
+typedef long off_t;
+typedef int pid_t;
+typedef unsigned fmode_t;
+typedef u32 uid_t;
+typedef u32 gid_t;
+typedef long __kernel_time_t;
+typedef unsigned short umode_t;
+typedef __u16 __be16;
+typedef __u32 __be32;
+
+#ifndef __cplusplus
+typedef u16 wchar_t;
+#endif
+
+/*
+ * needed by usb.h
+ */
+typedef unsigned long dma_addr_t;
+
+/*
+ * XXX 'mode_t' is 'unsigned int' on x86_64
+ */
+typedef unsigned short mode_t;
+
+
+/******************
+ ** asm/system.h **
+ ******************/
+
+#define mb() asm volatile ("": : :"memory")
+#define rmb() mb()
+#define wmb() asm volatile ("": : :"memory")
+#define smp_wmb() wmb()
+
+static inline void barrier() { mb(); }
+
+
+/**********************
+ ** linux/compiler.h **
+ **********************/
+
+#define likely
+#define unlikely
+
+#define __user /* needed by usb/core/devices.c */
+#define __iomem /* needed by usb/hcd.h */
+
+#define __releases(x) /* needed by usb/core/devio.c */
+#define __acquires(x) /* needed by usb/core/devio.c */
+#define __force
+#define __maybe_unused
+#define __bitwise
+
+#define __rcu
+#define __must_check
+
+#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x))
+
+#define __attribute_const__
+
+#undef __always_inline
+#define __always_inline
+
+#undef __unused
+
+
+/***********************
+ ** linux/irqreturn.h **
+ ***********************/
+
+enum irqreturn {
+ IRQ_NONE,
+ IRQ_HANDLED = (1 << 0),
+};
+
+typedef enum irqreturn irqreturn_t;
+
+
+/*************************************
+ ** linux/byteorder/little_endian.h **
+ *************************************/
+
+#include
+
+
+/*******************************
+ ** linux/byteorder/generic.h **
+ *******************************/
+
+#define le16_to_cpu __le16_to_cpu
+#define be16_to_cpu __be16_to_cpu
+#define le32_to_cpu __le32_to_cpu
+#define be32_to_cpu __be32_to_cpu
+#define le16_to_cpus __le16_to_cpus
+#define cpu_to_le16p __cpu_to_le16p
+#define cpu_to_be16p __cpu_to_be16p
+#define cpu_to_le16 __cpu_to_le16
+#define cpu_to_be16 __cpu_to_be16
+#define cpu_to_le32 __cpu_to_le32
+#define cpu_to_be32 __cpu_to_be32
+#define le16_to_cpup __le16_to_cpup
+#define be16_to_cpup __be16_to_cpup
+#define le32_to_cpup __le32_to_cpup
+#define be32_to_cpup __be32_to_cpup
+
+
+struct __una_u32 { u32 x; } __attribute__((packed));
+struct __una_u64 { u64 x; } __attribute__((packed));
+
+u16 get_unaligned_le16(const void *p);
+
+void put_unaligned_le32(u32 val, void *p);
+u32 get_unaligned_le32(const void *p);
+
+void put_unaligned_le64(u64 val, void *p);
+u64 get_unaligned_le64(const void *p);
+
+#define put_unaligned put_unaligned_le32
+#define get_unaligned get_unaligned_le32
+
+
+/****************
+ ** asm/page.h **
+ ****************/
+
+/*
+ * For now, hardcoded to x86_32
+ */
+enum {
+ PAGE_SIZE = 4096,
+ PAGE_SHIFT = 12,
+};
+
+struct page
+{
+ void *virt;
+ dma_addr_t phys;
+};
+
+
+/********************
+ ** linux/poison.h **
+ ********************/
+
+/*
+ * In list.h, LIST_POISON1 and LIST_POISON2 are assigned to 'struct list_head
+ * *' as well as 'struct hlist_node *' pointers. Consequently, C++ compiler
+ * produces an error "cannot convert... in assignment". To compile 'list.h'
+ * included by C++ source code, we have to define these macros to the only
+ * value universally accepted for pointer assigments.h
+ */
+
+#ifdef __cplusplus
+#define LIST_POISON1 0
+#define LIST_POISON2 0
+#else
+#define LIST_POISON1 ((void *)0x00100100)
+#define LIST_POISON2 ((void *)0x00200200)
+#endif /* __cplusplus */
+
+
+/*******************************
+ ** linux/errno.h and friends **
+ *******************************/
+
+/**
+ * Error codes
+ *
+ * Note that the codes do not correspond to those of the Linux kernel.
+ */
+enum {
+ EINVAL = 1,
+ ENODEV = 2,
+ ENOMEM = 3,
+ EFAULT = 4,
+ EBADF = 5,
+ EAGAIN = 6,
+ ERESTARTSYS = 7,
+ ENOSPC = 8,
+ EIO = 9,
+ EBUSY = 10,
+ EPERM = 11,
+ EINTR = 12,
+ ENOMSG = 13,
+ ECONNRESET = 14,
+ ENOENT = 15,
+ EHOSTUNREACH = 16,
+ ESRCH = 17,
+ EPIPE = 18,
+ ENODATA = 19,
+ EREMOTEIO = 20,
+ ENOTTY = 21,
+ ENOIOCTLCMD = 22,
+ EADDRINUSE = 23,
+ ENFILE = 23,
+ EXFULL = 24,
+ EIDRM = 25,
+ ESHUTDOWN = 26,
+ EMSGSIZE = 27,
+ E2BIG = 28,
+ EINPROGRESS = 29,
+ ESPIPE = 29,
+ ETIMEDOUT = 30,
+ ENOSYS = 31,
+ ENOTCONN = 32,
+ EPROTO = 33,
+ ENOTSUPP = 34,
+ EISDIR = 35,
+ EEXIST = 36,
+ ENOTEMPTY = 37,
+ ENXIO = 38,
+ ENOEXEC = 39,
+ EXDEV = 40,
+ EOVERFLOW = 41,
+ ENOSR = 42,
+ ECOMM = 43,
+ EFBIG = 44,
+ EILSEQ = 45,
+ ETIME = 46,
+ EALREADY = 47,
+ EOPNOTSUPP = 48,
+};
+
+static inline bool IS_ERR(void *ptr) {
+ return (unsigned long)(ptr) > (unsigned long)(-1000); }
+
+long PTR_ERR(const void *ptr);
+
+
+/*******************
+ ** linux/major.h **
+ *******************/
+
+enum {
+ INPUT_MAJOR = 13
+};
+
+/********************
+ ** linux/kernel.h **
+ ********************/
+
+/*
+ * Log tags
+ */
+#define KERN_DEBUG "DEBUG: "
+#define KERN_ERR "ERROR: "
+#define KERN_INFO "INFO: "
+#define KERN_NOTICE "NOTICE: "
+
+/*
+ * Debug macros
+ */
+#if VERBOSE_LX_EMUL
+#define printk dde_kit_printf
+#define vprintk dde_kit_vprintf
+#define panic dde_kit_panic
+#else /* VERBOSE_LX_EMUL */
+#define printk(...)
+#define vprintk(...)
+#define panic(...)
+#endif /* VERBOSE_LX_EMUL */
+
+/*
+ * Bits and types
+ */
+
+/* needed by linux/list.h */
+#define container_of(ptr, type, member) ({ \
+ const typeof( ((type *)0)->member ) *__mptr = (ptr); \
+ (type *)( (char *)__mptr - offsetof(type,member) );})
+
+/* normally provided by linux/stddef.h, needed by linux/list.h */
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+
+#define max_t(type, x, y) ({ \
+ type __max1 = (x); \
+ type __max2 = (y); \
+ __max1 > __max2 ? __max1: __max2; })
+
+/**
+ * Return minimum of two given values
+ *
+ * XXX check how this function is used (argument types)
+ */
+static inline size_t min(size_t a, size_t b) {
+ return a < b ? a : b; }
+
+/**
+ * Return maximum of two given values
+ *
+ * XXX check how this function is used (argument types)
+ */
+#define max(x, y) ({ \
+ typeof(x) _max1 = (x); \
+ typeof(y) _max2 = (y); \
+ (void) (&_max1 == &_max2); \
+ _max1 > _max2 ? _max1 : _max2; })
+
+#define min_t(type, x, y) ({ \
+ type __min1 = (x); \
+ type __min2 = (y); \
+ __min1 < __min2 ? __min1: __min2; })
+
+#define abs(x) ( { \
+ typeof (x) _x = (x); \
+ _x < 0 ? -_x : _x; })
+
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+
+void might_sleep();
+
+#define INT_MAX ((int)(~0U>>1))
+
+char *kasprintf(gfp_t gfp, const char *fmt, ...);
+int kstrtouint(const char *s, unsigned int base, unsigned int *res);
+
+#define clamp(val, min, max) ({ \
+ typeof(val) __val = (val); \
+ typeof(min) __min = (min); \
+ typeof(max) __max = (max); \
+ (void) (&__val == &__min); \
+ (void) (&__val == &__max); \
+ __val = __val < __min ? __min: __val; \
+ __val > __max ? __max: __val; })
+
+int strict_strtoul(const char *s, unsigned int base, unsigned long *res);
+long simple_strtoul(const char *cp, char **endp, unsigned int base);
+
+
+/*
+ * Needed by 'usb.h'
+ */
+int snprintf(char *buf, size_t size, const char *fmt, ...);
+int sprintf(char *buf, const char *fmt, ...);
+int sscanf(const char *, const char *, ...);
+int scnprintf(char *buf, size_t size, const char *fmt, ...);
+
+struct completion;
+void complete_and_exit(struct completion *, long);
+
+/******************
+ ** linux/log2.h **
+ ******************/
+
+int ilog2(u32 n);
+int roundup_pow_of_two(u32 n);
+
+
+/********************
+ ** linux/kdev_t.h **
+ ********************/
+
+#define MINORBITS 20
+#define MKDEV(ma,mi) (((ma) << MINORBITS) | (mi))
+
+
+/********************
+ ** linux/printk.h **
+ ********************/
+
+enum { DUMP_PREFIX_NONE };
+
+void print_hex_dump(const char *level, const char *prefix_str,
+ int prefix_type, int rowsize, int groupsize,
+ const void *buf, size_t len, bool ascii);
+
+#define KERN_WARNING "<4>"
+#define pr_info(fmt, ...) printk(KERN_INFO fmt, ##__VA_ARGS__)
+#define pr_err(fmt, ...) printk(KERN_ERR fmt, ##__VA_ARGS__)
+#define pr_debug(fmt, ...) printk(KERN_DEBUG fmt, ##__VA_ARGS__)
+#define pr_warning(fmt, ...) printk(KERN_WARNING fmt, ##__VA_ARGS__)
+#define pr_warn pr_warning
+
+#define printk_ratelimit() \
+ ({ dde_kit_debug("printk_ratelimit called - not implemented\n"); (0); })
+
+static inline bool printk_timed_ratelimit(unsigned long *caller_jiffies,
+ unsigned int interval_msec) {
+ return false; }
+
+
+/**********************************
+ ** linux/bitops.h, asm/bitops.h **
+ **********************************/
+
+#include
+
+#define BIT(nr) (1UL << (nr))
+#define BITS_PER_LONG (sizeof(long) * 8)
+
+#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
+#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
+
+#include
+
+#define test_and_clear_bit(nr, addr) \
+ __test_and_clear_bit(nr, (volatile unsigned long *)(addr))
+#define test_and_set_bit(nr, addr) \
+ __test_and_set_bit(nr, (volatile unsigned long *)(addr))
+#define set_bit(nr, addr) \
+ __set_bit(nr, (volatile unsigned long *)(addr))
+#define clear_bit(nr, addr) \
+ __clear_bit(nr, (volatile unsigned long *)(addr))
+
+/**
+ * Find first zero bit (limit to machine word size)
+ */
+long find_next_zero_bit_le(const void *addr,
+ unsigned long size, unsigned long offset);
+
+#define find_next_zero_bit find_next_zero_bit_le
+
+/* normally declared in asm-generic/bitops/ffs.h */
+int ffs(int x);
+int fls(int x);
+
+
+/********************
+ ** linux/string.h **
+ ********************/
+
+#ifndef __cplusplus
+void *memcpy(void *dest, const void *src, size_t n);
+#endif
+
+void *memset(void *s, int c, size_t n);
+int memcmp(const void *, const void *, size_t);
+void *memscan(void *addr, int c, size_t size);
+char *strcat(char *dest, const char *src);
+int strcmp(const char *s1, const char *s2);
+int strncmp(const char *cs, const char *ct, size_t count);
+char *strncpy(char *, const char *, size_t);
+char *strchr(const char *, int);
+char *strrchr(const char *,int);
+size_t strlcat(char *dest, const char *src, size_t n);
+size_t strlcpy(char *dest, const char *src, size_t size);
+size_t strlen(const char *);
+char * strsep(char **,const char *);
+char *strstr(const char *, const char *);
+char *kstrdup(const char *s, gfp_t gfp);
+void *kmemdup(const void *src, size_t len, gfp_t gfp);
+
+
+/*****************
+ ** linux/nls.h **
+ *****************/
+
+enum utf16_endian { UTF16_LITTLE_ENDIAN = 1, };
+
+int utf16s_to_utf8s(const wchar_t *pwcs, int len,
+ enum utf16_endian endian, u8 *s, int maxlen);
+
+
+/*******************
+ ** linux/ctype.h **
+ *******************/
+
+int isprint(int);
+
+
+/******************
+ ** linux/init.h **
+ ******************/
+
+#define __init
+#define __devinit
+#define __devinitconst
+#define __exit
+
+#define subsys_initcall(fn) void subsys_##fn(void) { fn(); }
+
+
+/********************
+ ** linux/module.h **
+ ********************/
+
+#define EXPORT_SYMBOL(x)
+#define EXPORT_SYMBOL_GPL(x)
+#define MODULE_AUTHOR(x)
+#define MODULE_DESCRIPTION(x)
+#define MODULE_LICENSE(x)
+#define MODULE_PARM_DESC(x, y)
+//#define MODULE_ALIAS_MISCDEV(x) /* needed by agp/backend.c */
+
+#define THIS_MODULE 0
+
+#define MODULE_DEVICE_TABLE(type, name)
+
+struct module;
+#define _MOD_CONCAT(a,b) module_##a##b
+#define MOD_CONCAT(a,b) _MOD_CONCAT(a,b)
+#define module_init(fn) void MOD_CONCAT(fn, MOD_SUFFIX)(void) { fn(); }
+#define module_exit(exit_fn) void MOD_CONCAT(exit_fn, MOD_SUFFIX)(void) { exit_fn(); }
+
+static inline void module_put(struct module *module) { }
+static inline void __module_get(struct module *module) { }
+
+/*************************
+ ** linux/moduleparam.h **
+ *************************/
+
+#define module_param(name, type, perm)
+#define module_param_named(name, value, type, perm)
+#define module_param_array_named(name, array, type, nump, perm)
+#define module_param_string(name, string, len, perm)
+#define core_param(name, var, type, perm)
+
+
+/******************
+ ** linux/slab.h **
+ ******************/
+
+enum {
+ SLAB_HWCACHE_ALIGN = 0x00002000UL,
+ SLAB_CACHE_DMA = 0x00004000UL,
+};
+
+void *kzalloc(size_t size, gfp_t flags);
+void kfree(const void *);
+void *kmalloc(size_t size, gfp_t flags);
+void *kcalloc(size_t n, size_t size, gfp_t flags);
+
+struct kmem_cache;
+
+/**
+ * Create slab cache using DDE kit
+ */
+struct kmem_cache *kmem_cache_create(const char *, size_t, size_t,
+ unsigned long, void (*)(void *));
+
+/**
+ * Destroy slab cache using DDE kit
+ */
+void kmem_cache_destroy(struct kmem_cache *);
+
+/**
+ * Allocate and zero slab
+ */
+void *kmem_cache_zalloc(struct kmem_cache *k, gfp_t flags);
+
+/**
+ * Free slab
+ */
+void kmem_cache_free(struct kmem_cache *, void *);
+
+
+/**********************
+ ** linux/spinlock.h **
+ **********************/
+
+typedef dde_kit_spin_lock spinlock_t;
+#define DEFINE_SPINLOCK(name) spinlock_t name = 0;
+
+void spin_lock(spinlock_t *lock);
+void spin_lock_nested(spinlock_t *lock, int subclass);
+void spin_unlock(spinlock_t *lock);
+void spin_lock_init(spinlock_t *lock);
+void spin_lock_irqsave(spinlock_t *lock, unsigned long flags);
+void spin_lock_irqrestore(spinlock_t *lock, unsigned long flags);
+void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags);
+void spin_lock_irq(spinlock_t *lock);
+void spin_unlock_irq(spinlock_t *lock);
+void assert_spin_locked(spinlock_t *lock);
+
+
+/*******************
+ ** linux/mutex.h **
+ *******************/
+
+struct mutex { struct dde_kit_lock *lock; };
+
+void mutex_init(struct mutex *m);
+void mutex_lock(struct mutex *m);
+void mutex_lock_nested(struct mutex *lock, unsigned int subclass);
+void mutex_unlock(struct mutex *m);
+int mutex_lock_interruptible(struct mutex *m);
+
+#define DEFINE_MUTEX(mutexname) struct mutex mutexname = { NULL };
+
+
+/*******************
+ ** linux/rwsem.h **
+ *******************/
+
+struct rw_semaphore { int dummy; };
+
+#define DECLARE_RWSEM(name) \
+ struct rw_semaphore name = { 0 };
+
+void down_read(struct rw_semaphore *sem);
+void up_read(struct rw_semaphore *sem);
+void down_write(struct rw_semaphore *sem);
+void up_write(struct rw_semaphore *sem);
+
+#define __RWSEM_INITIALIZER(name) { 0 }
+
+
+/*********************
+ ** linux/jiffies.h **
+ *********************/
+
+/*
+ * XXX check how the jiffies variable is used
+ */
+extern volatile unsigned long jiffies;
+unsigned long msecs_to_jiffies(const unsigned int m);
+long time_after(long a, long b);
+long time_after_eq(long a, long b);
+
+
+/*******************
+ ** linux/ktime.h **
+ *******************/
+
+union ktime { s64 tv64; };
+
+typedef union ktime ktime_t;
+
+ktime_t ktime_add_ns(const ktime_t kt, u64 nsec);
+
+static inline ktime_t ktime_add_us(const ktime_t kt, const u64 usec)
+{
+ return ktime_add_ns(kt, usec * 1000);
+}
+
+s64 ktime_us_delta(const ktime_t later, const ktime_t earlier);
+
+
+/*******************
+ ** linux/timer.h **
+ *******************/
+
+struct timer_list {
+ void (*function)(unsigned long);
+ unsigned long data;
+ void *timer;
+};
+
+void init_timer(struct timer_list *);
+int mod_timer(struct timer_list *timer, unsigned long expires);
+int del_timer(struct timer_list * timer);
+int del_timer_sync(struct timer_list * timer);
+void setup_timer(struct timer_list *timer,void (*function)(unsigned long),
+ unsigned long data);
+int timer_pending(const struct timer_list * timer);
+unsigned long round_jiffies(unsigned long j);
+
+
+/*********************
+ ** linux/hrtimer.h **
+ *********************/
+
+ktime_t ktime_get_real(void);
+
+
+/*******************
+ ** linux/delay.h **
+ *******************/
+
+void msleep(unsigned int msecs);
+void udelay(unsigned long usecs);
+void mdelay(unsigned long usecs);
+
+
+/***********************
+ ** linux/workquque.h **
+ ***********************/
+
+struct work_struct;
+typedef void (*work_func_t)(struct work_struct *work);
+
+struct work_struct {
+ work_func_t func;
+ struct list_head entry;
+};
+
+struct delayed_work {
+ struct timer_list timer;
+ struct work_struct work;
+};
+
+bool cancel_work_sync(struct work_struct *work);
+int cancel_delayed_work_sync(struct delayed_work *work);
+int schedule_delayed_work(struct delayed_work *work, unsigned long delay);
+int schedule_work(struct work_struct *work);
+bool flush_work_sync(struct work_struct *work);
+
+
+#define PREPARE_WORK(_work, _func) \
+ do { (_work)->func = (_func); } while (0)
+
+#define PREPARE_DELAYED_WORK(_work, _func) \
+ PREPARE_WORK(&(_work)->work, (_func))
+
+#define __INIT_WORK(_work, _func, on_stack) \
+ do { \
+ INIT_LIST_HEAD(&(_work)->entry); \
+ PREPARE_WORK((_work), (_func)); \
+ } while (0)
+
+#define INIT_WORK(_work, _func)\
+ do { __INIT_WORK((_work), (_func), 0); } while (0)
+
+#define INIT_DELAYED_WORK(_work, _func) \
+ do { \
+ INIT_WORK(&(_work)->work, (_func)); \
+ init_timer(&(_work)->timer); \
+ } while (0)
+
+
+/******************
+ ** linux/wait.h **
+ ******************/
+
+typedef struct wait_queue_head { int dummy; } wait_queue_head_t;
+
+void init_waitqueue_head(wait_queue_head_t *q);
+
+#define __WAIT_QUEUE_HEAD_INITIALIZER(name) { 0 }
+
+typedef struct wait_queue { int dummy; } wait_queue_t;
+
+#define __WAIT_QUEUE_INITIALIZER(name, tsk) { 0 }
+
+#define DECLARE_WAITQUEUE(name, tsk) \
+ wait_queue_t name = __WAIT_QUEUE_INITIALIZER(name, tsk)
+
+#define DECLARE_WAIT_QUEUE_HEAD(name) \
+ wait_queue_head_t name = __WAIT_QUEUE_HEAD_INITIALIZER(name)
+
+void __wake_up();
+void add_wait_queue(wait_queue_head_t *q, wait_queue_t *wait);
+void remove_wait_queue(wait_queue_head_t *q, wait_queue_t *wait);
+
+#define wake_up(x) __wake_up()
+#define wake_up_all(x) __wake_up()
+#define wake_up_interruptible(x) __wake_up()
+
+extern wait_queue_t wait;
+void breakpoint();
+
+/* our wait event implementation */
+void __wait_event(void);
+
+#define wait_event(wq, condition) \
+ ({ dde_kit_printf("wait_event, not yet implemented\n"); 0; })
+
+#define _wait_event(condition) \
+ while(!(condition)) { \
+ __wait_event(); \
+ if (!(condition)) \
+ msleep(1); \
+ } \
+
+#define _wait_event_timeout(condition, timeout) \
+({ \
+ unsigned long _j = jiffies + (timeout / HZ); \
+ while(1) { \
+ __wait_event(); \
+ if (condition || _j <= jiffies) \
+ break; \
+ msleep(1); \
+ } \
+})
+
+#define wait_event_interruptible(wq, condition) \
+({ \
+ _wait_event(condition); \
+ 0; \
+})
+
+#define wait_event_interruptible_timeout(wq, condition, timeout) \
+({ \
+ _wait_event_timeout(condition, timeout); \
+ 1; \
+})
+
+#define wait_event_timeout(wq, condition, timeout) \
+({ \
+ _wait_event_timeout(condition, timeout); \
+ 1; \
+})
+
+
+/******************
+ ** linux/time.h **
+ ******************/
+
+struct timespec {
+ __kernel_time_t tv_sec;
+ long tv_nsec;
+};
+
+struct timeval { };
+struct timespec current_kernel_time(void);
+void do_gettimeofday(struct timeval *tv);
+
+#define CURRENT_TIME (current_kernel_time())
+
+
+/*******************
+ ** linux/sched.h **
+ *******************/
+
+enum { TASK_RUNNING = 0, TASK_INTERRUPTIBLE = 1, TASK_NORMAL = 3 };
+
+enum { MAX_SCHEDULE_TIMEOUT = (~0U >> 1) };
+
+struct task_struct {
+ char comm[16]; /* needed by usb/core/devio.c, only for debug output */
+};
+
+struct cred;
+struct siginfo;
+struct pid;
+
+int kill_pid_info_as_cred(int, struct siginfo *, struct pid *,
+ const struct cred *, u32);
+pid_t task_pid_nr(struct task_struct *tsk);
+
+struct pid *task_pid(struct task_struct *task);
+
+void __set_current_state(int state);
+#define set_current_state(state) __set_current_state(state)
+int signal_pending(struct task_struct *p);
+void schedule(void);
+signed long schedule_timeout_uninterruptible(signed long timeout);
+void yield(void);
+int wake_up_process(struct task_struct *tsk);
+
+/* normally defined in asm/current.h, included by sched.h */
+extern struct task_struct *current;
+
+/* asm/processor.h */
+void cpu_relax(void);
+
+
+/*********************
+ ** linux/kthread.h **
+ *********************/
+
+int kthread_should_stop(void);
+int kthread_stop(struct task_struct *k);
+
+struct task_struct *kthread_run(int (*)(void *), void *, const char *, ...);
+
+struct task_struct *kthread_create(int (*threadfn)(void *data),
+ void *data,
+ const char namefmt[], ...);
+
+
+/**********************
+ ** linux/notifier.h **
+ **********************/
+
+enum {
+ NOTIFY_DONE = 0x0000,
+ NOTIFY_OK = 0x0001,
+ NOTIFY_STOP_MASK = 0x8000,
+ NOTIFY_BAD = (NOTIFY_STOP_MASK | 0x0002),
+};
+
+struct notifier_block {
+ int (*notifier_call)(struct notifier_block *, unsigned long, void *);
+};
+
+struct atomic_notifier_head {
+ spinlock_t lock;
+ struct notifier_block *head;
+};
+
+struct blocking_notifier_head {
+ struct rw_semaphore rwsem;
+ struct notifier_block *head;
+};
+
+#define BLOCKING_NOTIFIER_INIT(name) { \
+ .rwsem = __RWSEM_INITIALIZER((name).rwsem), .head = NULL }
+#define BLOCKING_NOTIFIER_HEAD(name) \
+ struct blocking_notifier_head name = BLOCKING_NOTIFIER_INIT(name)
+
+int blocking_notifier_chain_register(struct blocking_notifier_head *nh,
+ struct notifier_block *nb);
+int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh,
+ struct notifier_block *nb);
+int blocking_notifier_call_chain(struct blocking_notifier_head *nh,
+ unsigned long val, void *v);
+int atomic_notifier_chain_register(struct atomic_notifier_head *nh,
+ struct notifier_block *nb);
+int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh,
+ struct notifier_block *nb);
+
+
+/*************************
+ ** linux/scatterlist.h **
+ *************************/
+
+struct scatterlist {
+ unsigned long page_link;
+ unsigned int offset;
+ unsigned int length;
+ dma_addr_t dma_address;
+ int last;
+};
+
+struct sg_table
+{
+ struct scatterlist *sgl; /* the list */
+ unsigned int nents; /* number of mapped entries */
+};
+
+struct page *sg_page(struct scatterlist *sg);
+void *sg_virt(struct scatterlist *sg);
+struct scatterlist *sg_next(struct scatterlist *);
+
+size_t sg_copy_from_buffer(struct scatterlist *sgl, unsigned int nents,
+ void *buf, size_t buflen);
+size_t sg_copy_to_buffer(struct scatterlist *sgl, unsigned int nents,
+ void *buf, size_t buflen);
+
+#define for_each_sg(sglist, sg, nr, __i) \
+ for (__i = 0, sg = (sglist); __i < (nr); __i++, sg = sg_next(sg))
+
+#define sg_dma_address(sg) ((sg)->dma_address)
+#define sg_dma_len(sg) ((sg)->length)
+
+
+/******************
+ ** linux/kref.h **
+ ******************/
+
+struct kref { atomic_t refcount; };
+
+void kref_init(struct kref *kref);
+void kref_get(struct kref *kref);
+int kref_put(struct kref *kref, void (*release) (struct kref *kref));
+
+
+/*********************
+ ** linux/kobject.h **
+ *********************/
+
+struct kobject { int dummy; };
+struct kobj_uevent_env
+{
+ char buf[32];
+ int buflen;
+};
+
+struct kobj_uevent_env;
+
+int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...);
+char *kobject_name(const struct kobject *kobj);
+char *kobject_get_path(struct kobject *kobj, gfp_t gfp_mask);
+
+
+/*******************
+ ** linux/sysfs.h **
+ *******************/
+
+struct attribute {
+ const char *name;
+ mode_t mode;
+};
+
+struct attribute_group {
+ const char *name;
+ mode_t (*is_visible)(struct kobject *, struct attribute *, int);
+ struct attribute **attrs;
+};
+
+struct file;
+struct bin_attribute {
+ struct attribute attr;
+ size_t size;
+ ssize_t (*read)(struct file *, struct kobject *,
+ struct bin_attribute *, char *, loff_t, size_t);
+};
+
+#define __ATTR(_name,_mode,_show,_store) { \
+ .attr = {.name = #_name, .mode = _mode }, \
+ .show = _show, \
+ .store = _store, \
+}
+
+int sysfs_create_group(struct kobject *kobj,
+ const struct attribute_group *grp);
+void sysfs_remove_group(struct kobject *kobj,
+ const struct attribute_group *grp);
+
+
+/****************
+ ** linux/pm.h **
+ ****************/
+
+typedef struct pm_message { int event; } pm_message_t;
+
+struct dev_pm_info { bool is_prepared; };
+
+
+/************************
+ ** linux/pm_runtime.h **
+ ************************/
+
+struct device;
+
+int pm_runtime_set_active(struct device *dev);
+void pm_suspend_ignore_children(struct device *dev, bool enable);
+void pm_runtime_enable(struct device *dev);
+void pm_runtime_disable(struct device *dev);
+void pm_runtime_set_suspended(struct device *dev);
+void pm_runtime_get_noresume(struct device *dev);
+void pm_runtime_put_noidle(struct device *dev);
+void pm_runtime_use_autosuspend(struct device *dev);
+int pm_runtime_put_sync_autosuspend(struct device *dev);
+void pm_runtime_no_callbacks(struct device *dev);
+
+
+/***********************
+ ** linux/pm_wakeup.h **
+ ***********************/
+
+int device_init_wakeup(struct device *dev, bool val);
+int device_wakeup_enable(struct device *dev);
+bool device_may_wakeup(struct device *dev);
+int device_set_wakeup_enable(struct device *dev, bool enable);
+bool device_can_wakeup(struct device *dev);
+
+
+/********************
+ ** linux/device.h **
+ ********************/
+
+#ifdef __cplusplus
+#define class device_class
+#endif
+
+
+#define dev_info(dev, format, arg...) dde_kit_printf("dev_info: " format, ## arg)
+#define dev_warn(dev, format, arg...) dde_kit_printf("dev_warn: " format, ## arg)
+#define dev_WARN(dev, format, arg...) dde_kit_printf("dev_WARN: " format, ## arg)
+#define dev_err( dev, format, arg...) dde_kit_printf("dev_error: " format, ## arg)
+#define dev_notice(dev, format, arg...) dde_kit_printf("dev_notice: " format, ## arg)
+#define dev_dbg( dev, format, arg...)
+
+#define dev_printk(level, dev, format, arg...) \
+ dde_kit_printf("dev_printk: " format, ## arg)
+
+enum {
+ BUS_NOTIFY_ADD_DEVICE = 0x00000001,
+ BUS_NOTIFY_DEL_DEVICE = 0x00000002,
+};
+
+struct device_driver;
+
+struct bus_type {
+ const char *name;
+ int (*match)(struct device *dev, struct device_driver *drv);
+ int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
+ int (*probe)(struct device *dev);
+ int (*remove)(struct device *dev);
+};
+
+struct device_driver {
+ char const *name;
+ struct bus_type *bus;
+ struct module *owner;
+ const char *mod_name;
+ int (*probe) (struct device *dev);
+ int (*remove) (struct device *dev);
+};
+
+struct kobj_uevent_env;
+
+struct device_type {
+ const char *name;
+ const struct attribute_group **groups;
+ void (*release)(struct device *dev);
+ int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
+ char *(*devnode)(struct device *dev, mode_t *mode);
+};
+
+struct class
+{
+ const char *name;
+ char *(*devnode)(struct device *dev, mode_t *mode);
+};
+
+struct device {
+ struct device *parent;
+ struct kobject kobj;
+ const struct device_type *type;
+ struct device_driver *driver;
+ u64 *dma_mask; /* needed by usb/hcd.h */
+ struct dev_pm_info power;
+ dev_t devt;
+ const struct attribute_group **groups;
+ void (*release)(struct device *dev);
+ struct bus_type *bus;
+ struct class *class;
+ void *driver_data;
+};
+
+struct device_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct device *dev, struct device_attribute *attr,
+ char *buf);
+ ssize_t (*store)(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count);
+};
+
+struct driver_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct device_driver *driver, char *buf);
+ ssize_t (*store)(struct device_driver *driver, const char *buf,
+ size_t count);
+};
+
+struct lock_class_key { int dummy; };
+
+#define DEVICE_ATTR(_name, _mode, _show, _store) \
+struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)
+
+#define DRIVER_ATTR(_name, _mode, _show, _store) \
+struct driver_attribute driver_attr_##_name = \
+ __ATTR(_name, _mode, _show, _store)
+
+void *dev_get_drvdata(const struct device *dev);
+int dev_set_drvdata(struct device *dev, void *data);
+int dev_set_name(struct device *dev, const char *name, ...);
+const char *dev_name(const struct device *dev);
+int dev_to_node(struct device *dev);
+void set_dev_node(struct device *dev, int node);
+
+struct device *device_create(struct class *cls, struct device *parent,
+ dev_t devt, void *drvdata,
+ const char *fmt, ...);
+int device_add(struct device *dev);
+void device_destroy(struct class *cls, dev_t devt);
+int device_register(struct device *dev);
+void device_unregister(struct device *dev);
+void device_lock(struct device *dev);
+int device_trylock(struct device *dev);
+void device_unlock(struct device *dev);
+void device_del(struct device *dev);
+void device_initialize(struct device *dev);
+int device_attach(struct device *dev);
+int device_is_registered(struct device *dev);
+int device_bind_driver(struct device *dev);
+void device_release_driver(struct device *dev);
+void device_enable_async_suspend(struct device *dev);
+void device_set_wakeup_capable(struct device *dev, bool capable);
+int device_create_bin_file(struct device *dev,
+ const struct bin_attribute *attr);
+void device_remove_bin_file(struct device *dev,
+ const struct bin_attribute *attr);
+int device_create_file(struct device *device,
+ const struct device_attribute *entry);
+void device_remove_file(struct device *dev,
+ const struct device_attribute *attr);
+
+void put_device(struct device *dev);
+struct device *get_device(struct device *dev);
+
+int driver_register(struct device_driver *drv);
+void driver_unregister(struct device_driver *drv);
+int driver_attach(struct device_driver *drv);
+int driver_create_file(struct device_driver *driver,
+ const struct driver_attribute *attr);
+void driver_remove_file(struct device_driver *driver,
+ const struct driver_attribute *attr);
+
+struct device_driver *get_driver(struct device_driver *drv);
+void put_driver(struct device_driver *drv);
+
+struct device *bus_find_device(struct bus_type *bus, struct device *start,
+ void *data,
+ int (*match)(struct device *dev, void *data));
+int bus_register(struct bus_type *bus);
+void bus_unregister(struct bus_type *bus);
+int bus_register_notifier(struct bus_type *bus,
+ struct notifier_block *nb);
+int bus_unregister_notifier(struct bus_type *bus,
+ struct notifier_block *nb);
+
+struct class *__class_create(struct module *owner,
+ const char *name,
+ struct lock_class_key *key);
+#define class_create(owner, name) \
+({ \
+ static struct lock_class_key __key; \
+ __class_create(owner, name, &__key); \
+})
+int class_register(struct class *cls);
+void class_unregister(struct class *cls);
+void class_destroy(struct class *cls);
+
+#ifdef __cplusplus
+#undef class
+#endif
+
+
+/*****************************
+ ** linux/platform_device.h **
+ *****************************/
+
+struct platform_device;
+void *platform_get_drvdata(const struct platform_device *pdev);
+
+
+/*********************
+ ** linux/dmapool.h **
+ *********************/
+
+struct dma_pool;
+
+/*
+ * Needed by usb/core/buffer.c
+ */
+struct dma_pool *dma_pool_create(const char *, struct device *, size_t,
+ size_t, size_t);
+void dma_pool_destroy(struct dma_pool *);
+void *dma_pool_alloc(struct dma_pool *, gfp_t, dma_addr_t *);
+void dma_pool_free(struct dma_pool *, void *, dma_addr_t);
+
+
+/*
+ * Actually defined in asm-generic/dma-mapping-broken.h
+ */
+void *dma_alloc_coherent(struct device *, size_t, dma_addr_t *, gfp_t);
+void dma_free_coherent(struct device *, size_t, void *, dma_addr_t);
+
+
+/*************************
+ ** linux/dma-mapping.h **
+ *************************/
+
+static inline u64 DMA_BIT_MASK(unsigned n) {
+ return (n == 64) ? ~0ULL : (1ULL << n) - 1; }
+
+
+/*********************
+ ** linux/uaccess.h **
+ *********************/
+
+enum { VERIFY_READ = 0, VERIFY_WRITE = 1 };
+
+bool access_ok(int access, void *addr, size_t size);
+
+size_t copy_from_user(void *to, void const *from, size_t len);
+size_t copy_to_user(void *dst, void const *src, size_t len);
+
+#define get_user(x, ptr) ({ dde_kit_printf("get_user not implemented"); (0);})
+#define put_user(x, ptr) ({ dde_kit_printf("put_user not implemented"); (0);})
+
+
+/*****************
+ ** linux/dmi.h **
+ *****************/
+
+struct dmi_system_id;
+
+static inline int dmi_check_system(const struct dmi_system_id *list) { return 0; }
+static inline const char * dmi_get_system_info(int field) { return NULL; }
+
+
+/*****************************
+ ** linux/mod_devicetable.h **
+ *****************************/
+
+/*
+ * Deal with C++ keyword used as member name of 'pci_device_id'
+ */
+#define USB_DEVICE_ID_MATCH_VENDOR 0x0001
+#define USB_DEVICE_ID_MATCH_PRODUCT 0x0002
+#define USB_DEVICE_ID_MATCH_DEV_LO 0x0004
+#define USB_DEVICE_ID_MATCH_DEV_HI 0x0008
+#define USB_DEVICE_ID_MATCH_DEV_CLASS 0x0010
+#define USB_DEVICE_ID_MATCH_DEV_SUBCLASS 0x0020
+#define USB_DEVICE_ID_MATCH_DEV_PROTOCOL 0x0040
+#define USB_DEVICE_ID_MATCH_INT_CLASS 0x0080
+#define USB_DEVICE_ID_MATCH_INT_SUBCLASS 0x0100
+#define USB_DEVICE_ID_MATCH_INT_PROTOCOL 0x0200
+
+/********************
+ ** linux/dcache.h **
+ ********************/
+
+enum dentry_d_lock_class
+{
+ DENTRY_D_LOCK_NESTED
+};
+
+struct qstr {
+ const unsigned char *name;
+};
+
+struct dentry {
+ struct inode *d_inode;
+ struct qstr d_name;
+ struct list_head d_subdirs;
+ spinlock_t d_lock;
+ struct dentry *d_parent;
+ union { struct list_head d_child; } d_u;
+};
+
+void d_instantiate(struct dentry *, struct inode *);
+int d_unhashed(struct dentry *dentry);
+void d_delete(struct dentry *);
+struct dentry *d_alloc_root(struct inode *);
+struct dentry *dget(struct dentry *dentry);
+void dput(struct dentry *);
+
+void dont_mount(struct dentry *dentry);
+
+
+/******************
+ ** linux/poll.h **
+ ******************/
+
+/* needed by usb/core/devices.c, defined in asm-generic/poll.h */
+#define POLLIN 0x0001
+#define POLLOUT 0x0004
+#define POLLERR 0x0008
+#define POLLHUP 0x0010
+#define POLLRDNORM 0x0040
+#define POLLWRNORM 0x0100
+
+typedef struct poll_table_struct { int dummy; } poll_table;
+
+struct file;
+
+void poll_wait(struct file *, wait_queue_head_t *, poll_table *);
+
+
+/********************
+ ** linux/statfs.h **
+ ********************/
+
+struct kstatfs;
+loff_t default_llseek(struct file *file, loff_t offset, int origin);
+
+
+/*************************
+ ** asm-generic/fcntl.h **
+ *************************/
+
+enum { O_NONBLOCK = 0x4000 };
+
+
+/****************
+ ** linux/fs.h **
+ ****************/
+
+#define FMODE_WRITE 0x2
+
+enum { S_DEAD = 16 };
+
+enum inode_i_mutex_lock_class { I_MUTEX_PARENT };
+
+struct path {
+ struct dentry *dentry;
+};
+
+struct file {
+ u64 f_version;
+ loff_t f_pos;
+ struct dentry *f_dentry;
+ struct path f_path;
+ unsigned int f_flags;
+ fmode_t f_mode;
+ const struct file_operations *f_op;
+ void *private_data;
+};
+
+typedef unsigned fl_owner_t;
+
+struct file_operations {
+ struct module *owner;
+ int (*open) (struct inode *, struct file *);
+ ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
+ loff_t (*llseek) (struct file *, loff_t, int);
+ unsigned int (*poll) (struct file *, struct poll_table_struct *);
+ long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
+ int (*flush) (struct file *, fl_owner_t id);
+ int (*release) (struct inode *, struct file *);
+ ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
+ int (*fasync) (int, struct file *, int);
+};
+
+struct inode_operations { int dummy; };
+
+struct inode {
+ umode_t i_mode;
+ struct mutex i_mutex;
+ dev_t i_rdev;
+ struct timespec i_mtime;
+ struct timespec i_atime;
+ struct timespec i_ctime;
+ uid_t i_uid;
+ gid_t i_gid;
+ unsigned long i_ino;
+ const struct file_operations *i_fop;
+ const struct inode_operations *i_op;
+ struct super_block *i_sb;
+ unsigned int i_flags;
+ void *i_private;
+ loff_t i_size;
+};
+
+struct seq_file;
+struct vfsmount;
+struct super_operations {
+ int (*show_options)(struct seq_file *, struct vfsmount *);
+ int (*drop_inode) (struct inode *);
+ int (*remount_fs) (struct super_block *, int *, char *);
+ int (*statfs) (struct dentry *, struct kstatfs *);
+};
+
+struct super_block {
+ struct dentry *s_root;
+ const struct super_operations *s_op;
+ u32 s_time_gran;
+ unsigned long s_magic;
+ unsigned char s_blocksize_bits;
+ unsigned long s_blocksize;
+};
+
+struct file_system_type {
+ const char *name;
+ struct module *owner;
+ struct dentry *(*mount)(struct file_system_type *, int,
+ const char *, void *);
+ void (*kill_sb)(struct super_block *);
+};
+
+struct fasync_struct { };
+
+unsigned iminor(const struct inode *inode);
+unsigned imajor(const struct inode *inode);
+
+int register_chrdev_region(dev_t, unsigned, const char *);
+void unregister_chrdev_region(dev_t, unsigned);
+static inline struct file_operations const *
+fops_get(struct file_operations const *fops) { return fops; }
+void fops_put(struct file_operations const *);
+loff_t noop_llseek(struct file *file, loff_t offset, int origin);
+int register_chrdev(unsigned int major, const char *name,
+ const struct file_operations *fops);
+void unregister_chrdev(unsigned int major, const char *name);
+struct inode *new_inode(struct super_block *sb);
+unsigned int get_next_ino(void);
+void init_special_inode(struct inode *, umode_t, dev_t);
+int generic_delete_inode(struct inode *inode);
+void drop_nlink(struct inode *inode);
+void inc_nlink(struct inode *inode);
+void dentry_unhash(struct dentry *dentry);
+void iput(struct inode *);
+struct dentry *mount_single(struct file_system_type *fs_type,
+ int flags, void *data,
+ int (*fill_super)(struct super_block *,
+ void *, int));
+int nonseekable_open(struct inode *inode, struct file *filp);
+int simple_statfs(struct dentry *, struct kstatfs *);
+int simple_pin_fs(struct file_system_type *, struct vfsmount **mount, int *count);
+ssize_t simple_read_from_buffer(void __user *to, size_t count,
+ loff_t *ppos, const void *from, size_t available);
+void simple_release_fs(struct vfsmount **mount, int *count);
+void kill_litter_super(struct super_block *sb);
+int register_filesystem(struct file_system_type *);
+int unregister_filesystem(struct file_system_type *);
+
+void kill_fasync(struct fasync_struct **, int, int);
+int fasync_helper(int, struct file *, int, struct fasync_struct **);
+
+extern const struct file_operations simple_dir_operations;
+extern const struct inode_operations simple_dir_inode_operations;
+
+static inline loff_t no_llseek(struct file *file, loff_t offset, int origin) {
+ return -ESPIPE; }
+
+
+/*******************
+ ** linux/namei.h **
+ *******************/
+
+struct dentry *lookup_one_len(const char *, struct dentry *, int);
+
+
+/*******************
+ ** linux/mount.h **
+ *******************/
+
+struct vfsmount {
+ int dummy;
+ struct super_block *mnt_sb;
+};
+
+
+/*************************
+ ** asm-/signal.h **
+ *************************/
+
+enum { SIGIO = 29 };
+
+
+/**********************
+ ** linux/seq_file.h **
+ **********************/
+
+struct seq_file { int dummy; };
+
+int seq_printf(struct seq_file *, const char *, ...);
+
+
+/*****************
+ ** linux/gfp.h **
+ *****************/
+
+enum {
+ __GFP_DMA = 0x01u,
+ GFP_DMA = __GFP_DMA,
+ __GFP_WAIT = 0x10u,
+ GFP_ATOMIC = 0x20u,
+ GFP_KERNEL = 0x0u,
+ GFP_NOIO = __GFP_WAIT,
+};
+
+unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order);
+#define __get_free_page(gfp_mask) __get_free_pages((gfp_mask), 0)
+
+void __free_pages(struct page *p, unsigned int order);
+#define __free_page(p) __free_pages((p), 0)
+
+void free_pages(unsigned long addr, unsigned int order);
+#define free_page(addr) free_pages((addr), 0)
+
+
+/*********************
+ ** linux/proc_fs.h **
+ *********************/
+
+struct proc_dir_entry *proc_mkdir(const char *,struct proc_dir_entry *);
+void remove_proc_entry(const char *name, struct proc_dir_entry *parent);
+
+
+/********************
+ * linux/debugfs.h **
+ ********************/
+
+struct dentry *debugfs_create_dir(const char *name, struct dentry *parent);
+struct dentry *debugfs_create_file(const char *name, mode_t mode,
+ struct dentry *parent, void *data,
+ const struct file_operations *fops);
+void debugfs_remove(struct dentry *dentry);
+static inline void debugfs_remove_recursive(struct dentry *dentry) { }
+
+
+/************************
+ ** linux/page-flags.h **
+ ************************/
+
+bool is_highmem(void *);
+#define PageHighMem(__p) is_highmem(page_zone(__p))
+
+
+/****************
+ ** linux/mm.h **
+ ****************/
+
+struct zone *page_zone(const struct page *page);
+
+
+/*********************
+ ** linux/pagemap.h **
+ *********************/
+
+enum { PAGE_CACHE_SHIFT = PAGE_SHIFT };
+enum { PAGE_CACHE_SIZE = PAGE_SIZE };
+
+
+/**********************
+ ** linux/highmem.h **
+ **********************/
+
+void *kmap(struct page *page);
+void kunmap(struct page *page);
+
+
+/**********************
+ ** asm-generic/io.h **
+ **********************/
+
+void *ioremap(resource_size_t offset, unsigned long size);
+void iounmap(volatile void *addr);
+
+/**
+ * Map I/O memory write combined
+ */
+void *ioremap_wc(resource_size_t phys_addr, unsigned long size);
+
+#define ioremap_nocache ioremap_wc
+
+#define writel(value, addr) (*(volatile uint32_t *)(addr) = (value))
+#define readl(addr) (*(volatile uint32_t *)(addr))
+#define readb(addr) (*(volatile uint8_t *)(addr))
+
+static inline void outb(u8 value, u32 port) { dde_kit_outb(port, value); }
+static inline void outw(u16 value, u32 port) { dde_kit_outw(port, value); }
+static inline void outl(u32 value, u32 port) { dde_kit_outl(port, value); }
+
+static inline u8 inb(u32 port) { return dde_kit_inb(port); }
+static inline u16 inw(u32 port) { return dde_kit_inw(port); }
+static inline u32 inl(u32 port) { return dde_kit_inl(port); }
+
+void native_io_delay(void);
+
+static inline void outb_p(u8 value, u32 port) { outb(value, port); native_io_delay(); }
+static inline void outw_p(u16 value, u32 port) { outw(value, port); native_io_delay(); }
+static inline void outl_p(u32 value, u32 port) { outl(value, port); native_io_delay(); }
+
+static inline u8 inb_p(u8 port) { u8 ret = inb(port); native_io_delay(); return ret; }
+static inline u16 inw_p(u16 port) { u16 ret = inw(port); native_io_delay(); return ret; }
+static inline u32 inl_p(u32 port) { u32 ret = inl(port); native_io_delay(); return ret; }
+
+
+/********************
+ ** linux/ioport.h **
+ ********************/
+
+#define IORESOURCE_IO 0x00000100
+
+struct resource
+{
+ resource_size_t start;
+ resource_size_t end;
+ unsigned long flags;
+};
+
+struct resource *request_region(resource_size_t start, resource_size_t n,
+ const char *name);
+struct resource *request_mem_region(resource_size_t start, resource_size_t n,
+ const char *name);
+
+void release_region(resource_size_t start, resource_size_t n);
+void release_mem_region(resource_size_t start, resource_size_t n);
+
+
+/***********************
+ ** linux/interrupt.h **
+ ***********************/
+
+#define IRQF_SHARED 0x00000080
+#define IRQF_DISABLED 0x00000020
+
+void local_irq_enable(void);
+void local_irq_disable(void);
+
+typedef irqreturn_t (*irq_handler_t)(int, void *);
+
+int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
+ const char *name, void *dev);
+void free_irq(unsigned int, void *);
+
+
+/*********************
+ ** linux/hardirq.h **
+ *********************/
+
+void synchronize_irq(unsigned int irq);
+
+
+/*****************
+ ** linux/pci.h **
+ *****************/
+
+#include
+#include
+
+/*
+ * Definitions normally found in pci_regs.h
+ */
+//enum { PCI_BASE_ADDRESS_MEM_MASK = ~0x0fUL };
+//enum { PCI_CAP_ID_AGP = 0x02 };
+extern struct bus_type pci_bus_type;
+enum { PCI_ANY_ID = ~0 };
+enum { DEVICE_COUNT_RESOURCE = 6 };
+//enum { PCIBIOS_MIN_MEM = 0UL };
+
+#define PCI_DEVICE_CLASS(dev_class,dev_class_mask) \
+ .class = (dev_class), .class_mask = (dev_class_mask), \
+ .vendor = PCI_ANY_ID, .device = PCI_ANY_ID, \
+ .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID
+
+#define PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f)
+
+#define PCI_DEVICE(vend,dev) \
+ .vendor = (vend), .device = (dev), \
+ .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID
+
+typedef enum { PCI_D0 = 0 } pci_power_t;
+
+/*
+ * Deal with C++ keyword used as member name of 'pci_dev'
+ */
+#ifdef __cplusplus
+#define class device_class
+#endif /* __cplusplus */
+
+#include
+
+/*
+ * PCI types
+ */
+struct pci_bus;
+
+struct pci_dev {
+ unsigned int devfn;
+ unsigned int irq;
+ struct resource resource[DEVICE_COUNT_RESOURCE];
+ struct pci_bus *bus; /* needed for i915_dma.c */
+ unsigned short vendor; /* needed for intel-agp.c */
+ unsigned short device;
+ unsigned int class; /* needed by usb/host/pci-quirks.c */
+ u8 revision; /* needed for ehci-pci.c */
+ struct device dev; /* needed for intel-agp.c */
+ pci_power_t current_state;
+};
+
+#ifdef __cplusplus
+#undef class
+#endif /* __cplusplus */
+
+enum {
+ PCI_ROM_RESOURCE = 6
+};
+
+/*
+ * Interface functions provided by the EHCI USB HCD driver.
+ */
+struct pci_driver {
+ char *name;
+ const struct pci_device_id *id_table;
+ int (*probe) (struct pci_dev *dev,
+ const struct pci_device_id *id);
+ void (*remove) (struct pci_dev *dev);
+ void (*shutdown) (struct pci_dev *dev);
+ struct device_driver driver;
+};
+
+
+static inline uint32_t PCI_DEVFN(unsigned slot, unsigned func) {
+ return ((slot & 0x1f) << 3) | (func & 0x07); }
+
+int pci_bus_read_config_byte(struct pci_bus *bus, unsigned int devfn, int where, u8 *val);
+int pci_bus_read_config_word(struct pci_bus *bus, unsigned int devfn, int where, u16 *val);
+int pci_bus_read_config_dword(struct pci_bus *bus, unsigned int devfn, int where, u32 *val);
+int pci_bus_write_config_byte(struct pci_bus *bus, unsigned int devfn, int where, u8 val);
+int pci_bus_write_config_word(struct pci_bus *bus, unsigned int devfn, int where, u16 val);
+int pci_bus_write_config_dword(struct pci_bus *bus, unsigned int devfn, int where, u32 val);
+
+static inline
+int pci_read_config_byte(struct pci_dev *dev, int where, u8 *val) {
+ return pci_bus_read_config_byte(dev->bus, dev->devfn, where, val); }
+
+static inline
+int pci_read_config_word(struct pci_dev *dev, int where, u16 *val) {
+ return pci_bus_read_config_word(dev->bus, dev->devfn, where, val); }
+
+static inline
+int pci_read_config_dword(struct pci_dev *dev, int where, u32 *val) {
+ return pci_bus_read_config_dword(dev->bus, dev->devfn, where, val); }
+
+static inline
+int pci_write_config_byte(struct pci_dev *dev, int where, u8 val) {
+ return pci_bus_write_config_byte(dev->bus, dev->devfn, where, val); }
+
+static inline
+int pci_write_config_word(struct pci_dev *dev, int where, u16 val) {
+ return pci_bus_write_config_word(dev->bus, dev->devfn, where, val); }
+
+static inline
+int pci_write_config_dword(struct pci_dev *dev, int where, u32 val) {
+ return pci_bus_write_config_dword(dev->bus, dev->devfn, where, val); }
+
+size_t pci_resource_len(struct pci_dev *dev, unsigned bar);
+size_t pci_resource_start(struct pci_dev *dev, unsigned bar);
+void *pci_get_drvdata(struct pci_dev *pdev);
+void pci_dev_put(struct pci_dev *dev);
+struct pci_dev *pci_get_device(unsigned int vendor, unsigned int device,
+ struct pci_dev *from);
+int pci_enable_device(struct pci_dev *dev);
+void pci_disable_device(struct pci_dev *dev);
+int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask);
+int pci_register_driver(struct pci_driver *driver);
+void pci_unregister_driver(struct pci_driver *driver);
+const char *pci_name(const struct pci_dev *pdev);
+bool pci_dev_run_wake(struct pci_dev *dev);
+unsigned int pci_resource_flags(struct pci_dev *dev, unsigned bar);
+void pci_set_master(struct pci_dev *dev);
+int pci_set_mwi(struct pci_dev *dev);
+int pci_find_capability(struct pci_dev *dev, int cap);
+struct pci_dev *pci_get_slot(struct pci_bus *bus, unsigned int devfn);
+const struct pci_device_id *pci_match_id(const struct pci_device_id *ids,
+ struct pci_dev *dev);
+void *pci_ioremap_bar(struct pci_dev *pdev, int bar);
+
+#define to_pci_dev(n) container_of(n, struct pci_dev, dev)
+
+#define DECLARE_PCI_FIXUP_FINAL(vendor, device, hook)
+
+#define DEFINE_PCI_DEVICE_TABLE(_table) \
+ const struct pci_device_id _table[] __devinitconst
+
+
+/**********************
+ ** linux/irqflags.h **
+ **********************/
+
+unsigned long local_irq_save(unsigned long flags);
+unsigned long local_irq_restore(unsigned long flags);
+
+
+/*************************
+ ** linux/dma-direction **
+ *************************/
+
+enum dma_data_direction
+{
+ DMA_BIDIRECTIONAL = 0,
+ DMA_TO_DEVICE = 1,
+ DMA_FROM_DEVICE = 2
+};
+
+
+/*************************
+ ** linux/dma-mapping.h **
+ *************************/
+
+struct dma_attrs;
+
+dma_addr_t dma_map_single_attrs(struct device *dev, void *ptr,
+ size_t size,
+ enum dma_data_direction dir,
+ struct dma_attrs *attrs);
+
+void dma_unmap_single_attrs(struct device *dev, dma_addr_t addr,
+ size_t size,
+ enum dma_data_direction dir,
+ struct dma_attrs *attrs);
+
+void dma_unmap_sg_attrs(struct device *dev, struct scatterlist *sg,
+ int nents, enum dma_data_direction dir,
+ struct dma_attrs *attrs);
+
+dma_addr_t dma_map_page(struct device *dev, struct page *page,
+ size_t offset, size_t size,
+ enum dma_data_direction dir);
+
+int dma_map_sg_attrs(struct device *dev, struct scatterlist *sg,
+ int nents, enum dma_data_direction dir,
+ struct dma_attrs *attrs);
+
+#define dma_map_single(d, a, s, r) dma_map_single_attrs(d, a, s, r, NULL)
+#define dma_unmap_single(d, a, s, r) dma_unmap_single_attrs(d, a, s, r, NULL)
+#define dma_map_sg(d, s, n, r) dma_map_sg_attrs(d, s, n, r, NULL)
+#define dma_unmap_sg(d, s, n, r) dma_unmap_sg_attrs(d, s, n, r, NULL)
+
+/* linux/dma-mapping-broken.h */
+void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
+ enum dma_data_direction direction);
+int dma_mapping_error(struct device *dev, dma_addr_t dma_addr);
+
+/*****************
+ ** linux/pid.h **
+ *****************/
+
+struct pid;
+void put_pid(struct pid *pid);
+struct pid *get_pid(struct pid *pid);
+
+
+/******************
+ ** linux/cred.h **
+ ******************/
+
+struct cred;
+void put_cred(struct cred const *);
+const struct cred *get_cred(const struct cred *cred);
+
+#define get_current_cred() 0
+
+#define current_fsuid() 0
+#define current_fsgid() 0
+
+
+/***************************
+ ** asm-generic/siginfo.h **
+ ***************************/
+
+/* needed by usb/core/devio.c */
+struct siginfo {
+ int si_signo;
+ int si_errno;
+ int si_code;
+ void *si_addr;
+};
+
+enum {
+ SI_ASYNCIO = -4,
+ _P = 2 << 16,
+ POLL_IN = _P | 1,
+ POLL_HUP = _P | 6,
+};
+
+
+/**********************
+ ** linux/security.h **
+ **********************/
+
+void security_task_getsecid(struct task_struct *p, u32 *secid);
+
+
+/*************************
+ ** asm-generic/ioctl.h **
+ *************************/
+
+/*
+ * Needed by usb/core/devio.h, used to calculate ioctl opcodes
+ */
+#include
+
+
+/******************
+ ** linux/cdev.h **
+ ******************/
+
+struct cdev { int dummy; };
+void cdev_init(struct cdev *, const struct file_operations *);
+int cdev_add(struct cdev *, dev_t, unsigned);
+void cdev_del(struct cdev *);
+
+
+/******************
+ ** linux/stat.h **
+ ******************/
+
+#define S_IFMT 00170000
+#define S_IFDIR 0040000
+#define S_IFREG 0100000
+#define S_ISVTX 0001000
+#define S_IALLUGO 0007777
+
+#define S_IRUGO 00444
+#define S_IWUSR 00200
+#define S_IXUGO 00111
+#define S_IRWXUGO 00777
+
+#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+
+
+/*********************
+ ** linux/utsname.h **
+ *********************/
+
+#define __NEW_UTS_LEN 64
+
+struct new_utsname {
+ char sysname[__NEW_UTS_LEN + 1];
+ char release[__NEW_UTS_LEN + 1];
+};
+
+struct new_utsname *init_utsname(void);
+struct new_utsname *utsname(void);
+
+/*********************
+ ** linux/freezer.h **
+ *********************/
+
+void set_freezable(void);
+static inline void set_freezable_with_signal(void) {}
+
+#define wait_event_freezable(wq, cond) wait_event_interruptible(wq, cond)
+
+
+/********************
+ ** linux/parser.h **
+ ********************/
+
+/*
+ * needed for usb/core/inode.c
+ */
+
+enum { MAX_OPT_ARGS = 3 };
+
+struct match_token {
+ int token;
+ const char *pattern;
+};
+
+typedef struct substring { int dummy; } substring_t;
+
+typedef struct match_token match_table_t[];
+
+int match_token(char *, const match_table_t table, substring_t args[]);
+int match_int(substring_t *, int *result);
+int match_octal(substring_t *, int *result);
+
+
+/************************
+ ** linux/completion.h **
+ ************************/
+
+struct completion { unsigned int done; };
+void complete(struct completion *);
+void init_completion(struct completion *x);
+unsigned long wait_for_completion_timeout(struct completion *x,
+ unsigned long timeout);
+void wait_for_completion(struct completion *x);
+int wait_for_completion_interruptible(struct completion *x);
+long wait_for_completion_interruptible_timeout(struct completion *x, unsigned long timeout);
+
+
+/*******************
+ ** linux/input.h **
+ *******************/
+
+struct input_dev;
+
+#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
+#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, 8 * sizeof(long))
+
+
+/*********************
+ ** linux/semaphore **
+ *********************/
+
+struct semaphore { };
+void sema_init(struct semaphore *sem, int val);
+int down_trylock(struct semaphore *sem);
+void up(struct semaphore *sem);
+int down_interruptible(struct semaphore *sem);
+
+
+/***********************
+ ** linux/hid-debug.h **
+ ***********************/
+
+enum { HID_DEBUG_BUFSIZE=512 };
+
+#define hid_debug_init() do { } while (0)
+#define hid_dump_input(a,b,c) do { } while (0)
+#define hid_debug_event(a,b) do { } while (0)
+#define hid_debug_register(a, b) do { } while (0)
+#define hid_debug_unregister(a) do { } while (0)
+#define hid_debug_exit() do { } while (0)
+
+
+/******************
+ ** linux/list.h **
+ ******************/
+
+#define new _new
+#include
+#undef new
+
+
+/********************
+ ** linux/hidraw.h **
+ ********************/
+
+struct hidraw { u32 minor; };
+struct hid_device;
+
+static inline int hidraw_init(void) { return 0; }
+static inline void hidraw_exit(void) { }
+static inline void hidraw_report_event(struct hid_device *hid, u8 *data, int len) { }
+static inline int hidraw_connect(struct hid_device *hid) { return -1; }
+static inline void hidraw_disconnect(struct hid_device *hid) { }
+
+
+/**********************
+ ** linux/rcupdate.h **
+ **********************/
+
+static inline void rcu_read_lock(void) { }
+static inline void rcu_read_unlock(void) { }
+static inline void synchronize_rcu(void) { }
+
+#define rcu_dereference(p) p
+#define rcu_assign_pointer(p,v) p = v
+
+
+/*********************
+ ** linux/rculist.h **
+ *********************/
+
+#define list_for_each_entry_rcu(pos, head, member) \
+ list_for_each_entry(pos, head, member)
+
+static inline void list_add_rcu(struct list_head *n, struct list_head *head) {
+ list_add(n, head); }
+
+static inline void list_add_tail_rcu(struct list_head *n,
+ struct list_head *head) {
+ list_add_tail(n, head); }
+
+static inline void list_del_rcu(struct list_head *entry) {
+ list_del(entry); }
+
+
+/********************
+ ** linux/random.h **
+ ********************/
+
+static inline void add_input_randomness(unsigned int type, unsigned int code,
+ unsigned int value) { }
+
+
+/*********************
+ ** linux/vmalloc.h **
+ *********************/
+
+void *vmalloc(unsigned long size);
+void *vzalloc(unsigned long size);
+void vfree(void *addr);
+
+
+/*******************
+ ** linux/genhd.h **
+ *******************/
+
+struct gendisk
+{
+ void *private_data;
+};
+
+
+/********************
+ ** linux/blkdev.h **
+ ********************/
+
+enum { BLK_BOUNCE_HIGH = -1ULL };
+enum blk_eh_timer_return { DUMMY };
+
+#define BLK_MAX_CDB 16
+
+#define blk_bidi_rq(rq) ((rq)->next_rq != NULL)
+
+struct request_queue
+{
+ spinlock_t *queue_lock;
+};
+
+enum rq_cmd_type_bits
+{
+ REQ_TYPE_BLOCK_PC = 2,
+};
+
+struct request
+{
+ enum rq_cmd_type_bits cmd_type;
+ struct gendisk *rq_disk;
+ void *special; /* opaque pointer available for LLD use */
+ struct request *next_rq;
+};
+
+void blk_queue_bounce_limit(struct request_queue *, u64);
+void blk_queue_dma_alignment(struct request_queue *, int);
+void blk_queue_max_hw_sectors(struct request_queue *, unsigned int);
+sector_t blk_rq_pos(const struct request *rq);
+unsigned int queue_max_hw_sectors(struct request_queue *q);
+
+#include
+
+
+/********************
+ ** scsi/scsi_eh.h **
+ *******************/
+
+struct scsi_eh_save { };
+
+struct scsi_sense_hdr
+{
+ u8 response_code;
+ u8 sense_key;
+ u8 asc;
+ u8 ascq;
+ u8 additional_length; /* always 0 for fixed sense format */
+};
+
+void scsi_report_device_reset(struct Scsi_Host *, int, int);
+void scsi_report_bus_reset(struct Scsi_Host *, int);
+
+void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd,
+ struct scsi_eh_save *ses, unsigned char *cmnd,
+ int cmnd_size, unsigned sense_bytes);
+
+void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd,
+ struct scsi_eh_save *ses);
+
+int scsi_normalize_sense(const u8 *sense_buffer, int sb_len,
+ struct scsi_sense_hdr *sshdr);
+
+const u8 * scsi_sense_desc_find(const u8 * sense_buffer, int sb_len,
+ int desc_type);
+
+/*********************
+ ** scsi/scsi_tcq.h **
+ *********************/
+
+enum {
+ MSG_SIMPLE_TAG = 0x20,
+ MSG_ORDERED_TAG = 0x22,
+};
+
+
+/***********************
+ ** drivers/scsi/sd.h **
+ **********************/
+
+struct scsi_disk
+{
+ sector_t capacity; /* size in 512-byte sectors */
+};
+
+struct scsi_disk *scsi_disk(struct gendisk *disk);
+
+
+/**********************
+ ** scsi/scsi_cmnd.h **
+ **********************/
+
+enum {
+ MAX_COMMAND_SIZE = 16,
+ SCSI_SENSE_BUFFERSIZE = 96,
+};
+
+struct scsi_data_buffer
+{
+ struct sg_table table;
+ unsigned length;
+};
+
+struct scsi_cmnd
+{
+ struct scsi_device *device;
+ struct list_head list; /* scsi_cmnd participates in queue lists */
+
+ unsigned long serial_number;
+
+ /*
+ * This is set to jiffies as it was when the command was first
+ * allocated. It is used to time how long the command has
+ * been outstanding
+ */
+ unsigned long jiffies_at_alloc;
+
+ unsigned short cmd_len;
+ enum dma_data_direction sc_data_direction;
+ unsigned char *cmnd;
+
+ struct scsi_data_buffer sdb;
+ struct scsi_data_buffer *prot_sdb;
+
+ unsigned underflow; /* return error if less than
+ this amount is transferred */
+
+ struct request *request; /* the command we are working on */
+ unsigned char *sense_buffer; /* obtained by REQUEST SENSE when
+ * CHECK CONDITION is received on original
+ * command (auto-sense) */
+ /**
+ * Low-level done function
+ *
+ * This function can be used by low-level driver to point to completion
+ * function. Not used by mid/upper level code.
+ */
+ void (*scsi_done) (struct scsi_cmnd *);
+
+ int result; /* status code from lower level driver */
+ void *back; /* uur completion */
+
+ void *packet;
+ void *session;
+};
+
+
+struct scatterlist *scsi_sglist(struct scsi_cmnd *cmd);
+unsigned scsi_sg_count(struct scsi_cmnd *cmd);
+unsigned scsi_bufflen(struct scsi_cmnd *cmd);
+void scsi_set_resid(struct scsi_cmnd *cmd, int resid);
+int scsi_get_resid(struct scsi_cmnd *cmd);
+
+
+
+/************************
+ ** scsi/scsi_device.h **
+ ************************/
+
+struct scsi_target
+{
+ struct list_head devices;
+ struct device dev;
+ unsigned int channel;
+ unsigned int id;
+ unsigned int pdt_1f_for_no_lun; /* PDT = 0x1f */
+ unsigned int target_blocked;
+ char scsi_level;
+};
+
+enum scsi_device_state
+{
+ SDEV_DEL, /* device deleted
+ * no commands allowed */
+};
+
+struct scsi_device
+{
+ struct Scsi_Host *host;
+ struct request_queue *request_queue;
+
+ struct list_head siblings; /* list of all devices on this host */
+ struct list_head same_target_siblings; /* just the devices sharing same target id */
+
+ spinlock_t list_lock;
+ struct list_head cmd_list; /* queue of in use SCSI Command structures */
+
+ unsigned short queue_depth; /* How deep of a queue we want */
+
+ unsigned short last_queue_full_depth; /* These two are used by */
+ unsigned short last_queue_full_count; /* scsi_track_queue_full() */
+ unsigned long last_queue_full_time; /* last queue full time */
+
+ unsigned long id, lun, channel;
+ char type;
+ char scsi_level;
+ unsigned char inquiry_len; /* valid bytes in 'inquiry' */
+ struct scsi_target *sdev_target; /* used only for single_lun */
+
+ unsigned lockable:1; /* able to prevent media removal */
+ unsigned simple_tags:1; /* simple queue tag messages are enabled */
+ unsigned ordered_tags:1; /* ordered queue tag messages are enabled */
+ unsigned use_10_for_rw:1; /* first try 10-byte read / write */
+ unsigned use_10_for_ms:1; /* first try 10-byte mode sense/select */
+ unsigned skip_ms_page_8:1; /* do not use MODE SENSE page 0x08 */
+ unsigned skip_ms_page_3f:1; /* do not use MODE SENSE page 0x3f */
+ unsigned use_192_bytes_for_3f:1; /* ask for 192 bytes from page 0x3f */
+ unsigned allow_restart:1; /* issue START_UNIT in error handler */
+ unsigned fix_capacity:1; /* READ_CAPACITY is too high by 1 */
+ unsigned guess_capacity:1; /* READ_CAPACITY might be too high by 1 */
+ unsigned no_read_capacity_16:1; /* avoid READ_CAPACITY_16 cmds */
+ unsigned retry_hwerror:1; /* retry HARDWARE_ERROR */
+ unsigned last_sector_bug:1; /* do not use multisector accesses on
+ SD_LAST_BUGGY_SECTORS */
+ unsigned no_read_disc_info:1; /* avoid READ_DISC_INFO cmds */
+
+ unsigned int device_blocked; /* device returned QUEUE_FULL. */
+
+ atomic_t iorequest_cnt;
+ struct device sdev_gendev;
+ enum scsi_device_state sdev_state;
+};
+
+#define to_scsi_device(d) \
+ container_of(d, struct scsi_device, sdev_gendev)
+
+#define shost_for_each_device(sdev, shost) dde_kit_printf("shost_for_each_device called\n");
+#define __shost_for_each_device(sdev, shost) dde_kit_printf("__shost_for_each_device called\n");
+
+
+/************************
+ ** scsi/scsi_driver.h **
+ ************************/
+
+struct scsi_driver
+{
+ int (*done)(struct scsi_cmnd *);
+};
+
+
+/**********
+ ** misc **
+ **********/
+
+static inline void dump_stack(void) { }
+
+static inline void * __must_check ERR_PTR(long error) {
+ return (void *) error;
+}
+
+
+/**
+ * Genode's evdev event handler
+ */
+enum input_event_type {
+ EVENT_TYPE_PRESS, EVENT_TYPE_RELEASE, /* key press and release */
+ EVENT_TYPE_MOTION, /* any type of (pointer) motion */
+ EVENT_TYPE_WHEEL /* mouse scroll wheel */
+};
+
+struct input_handle;
+
+/**
+ * Input event callback
+ *
+ * \param type input event type
+ * \param keycode key code if type is EVENT_TYPE_PRESS or
+ * EVENT_TYPE_RELEASE
+ * \param absolute_x absolute horizontal coordinate if type is
+ * EVENT_TYPE_MOTION
+ * \param absolute_y absolute vertical coordinate if type is
+ * EVENT_TYPE_MOTION
+ * \param relative_x relative horizontal coordinate if type is
+ * EVENT_TYPE_MOTION or EVENT_TYPE_WHEEL
+ * \param relative_y relative vertical coordinate if type is
+ * EVENT_TYPE_MOTION or EVENT_TYPE_WHEEL
+ *
+ * Key codes conform to definitions in os/include/input/event.h, which is C++
+ * and therefore not included here.
+ *
+ * Relative coordinates are only significant if absolute_x and absolute_y are
+ * 0.
+ */
+typedef void (*genode_input_event_cb)(enum input_event_type type,
+ unsigned keycode,
+ int absolute_x, int absolute_y,
+ int relative_x, int relative_y);
+
+/**
+ * Register input handle
+ *
+ * \param handler call-back function on input events
+ *
+ * \return 0 on success; !0 otherwise
+ */
+void genode_input_register(genode_input_event_cb handler);
+
+
+void genode_evdev_event(struct input_handle *handle, unsigned int type,
+ unsigned int code, int value);
+
+void start_input_service(void *ep);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _LX_EMUL_H_ */
diff --git a/dde_linux/src/drivers/usb/main.cc b/dde_linux/src/drivers/usb/main.cc
new file mode 100644
index 000000000..b1144d55f
--- /dev/null
+++ b/dde_linux/src/drivers/usb/main.cc
@@ -0,0 +1,135 @@
+/*
+ * \brief USB driver main program
+ * \author Norman Feske
+ * \author Sebastian Sumpf
+ * \date 2012-01-29
+ */
+
+/*
+ * Copyright (C) 2012 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
+#include
+#include
+#include
+#include
+
+/* Local */
+#include "storage/component.h"
+#include "routine.h"
+#include "signal.h"
+
+extern "C" {
+#include
+}
+
+using namespace Genode;
+
+extern "C" void subsys_usb_init();
+extern "C" void subsys_input_init();
+extern "C" void module_ehci_hcd_init();
+extern "C" void module_evdev_init();
+extern "C" void module_hid_init();
+extern "C" void module_hid_init_core();
+extern "C" void module_uhci_hcd_init();
+extern "C" void module_usb_mouse_init();
+extern "C" void module_usb_kbd_init();
+extern "C" void module_usb_stor_init();
+
+extern "C" void start_input_service(void *ep);
+
+Routine *Routine::_current = 0;
+Routine *Routine::_dead = 0;
+bool Routine::_all = false;
+
+void breakpoint() { PDBG("BREAK"); }
+
+
+static void init(bool hid, bool stor)
+{
+ /* start jiffies */
+ dde_kit_timer_init(0, 0);
+
+ /* USB */
+ subsys_usb_init();
+
+ /* input + HID */
+ if (hid) {
+ subsys_input_init();
+ module_evdev_init();
+
+ /* HID */
+ module_hid_init();
+ module_usb_mouse_init();
+ module_usb_kbd_init();
+ }
+
+ /*
+ * Host controller.
+ *
+ * ehci_hcd should always be loaded before uhci_hcd and ohci_hcd, not after
+ */
+ module_ehci_hcd_init();
+ module_uhci_hcd_init();
+
+ /* storage */
+ if (stor)
+ module_usb_stor_init();
+}
+
+
+int main(int, char **)
+{
+ /*
+ * Initialize server entry point
+ */
+ enum { STACK_SIZE = 4096 };
+ static Cap_connection cap;
+ static Rpc_entrypoint ep_hid(&cap, STACK_SIZE, "usb_hid_ep");
+ static Signal_receiver recv;
+
+ bool hid = false;
+ bool stor = false;
+
+ try {
+ config()->xml_node().sub_node("hid");
+ start_input_service(&ep_hid);
+ hid = true;
+ } catch (Config::Invalid) {
+ PDBG("No node found - not starting any USB services");
+ return 0;
+ } catch (Xml_node::Nonexistent_sub_node) {
+ PDBG("No config node found - not starting the USB HID (Input) service");
+ }
+
+ try {
+ config()->xml_node().sub_node("storage");
+ stor = true;
+ } catch (Xml_node::Nonexistent_sub_node) {
+ PDBG("No config node found - not starting the USB Storage (Block) service");
+ }
+
+ Timer::init(&recv);
+ Irq::init(&recv);
+ Event::init(&recv);
+ Service_handler::s()->receiver(&recv);
+ Storage::init(&recv);
+
+ Routine::add(0, 0, "Main", true);
+ Routine::current_use_first();
+ init(hid, stor);
+
+ Routine::remove();
+
+ /* will never be reached */
+ sleep_forever();
+
+ return 0;
+}
diff --git a/dde_linux/src/drivers/usb/pci_driver.cc b/dde_linux/src/drivers/usb/pci_driver.cc
new file mode 100644
index 000000000..d0fcd1c68
--- /dev/null
+++ b/dde_linux/src/drivers/usb/pci_driver.cc
@@ -0,0 +1,320 @@
+/*
+ * \brief Emulate 'pci_dev' structure
+ * \author Sebastian Sumpf
+ * \date 2012-04-02
+ */
+
+/*
+ * Copyright (C) 2012 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 inludes */
+#include
+#include
+
+/* Linux includes */
+#include
+
+
+struct bus_type pci_bus_type;
+
+
+/**
+ * Scan PCI bus and probe for HCDs
+ */
+class Pci_driver
+{
+ private:
+
+ pci_driver *_drv; /* Linux PCI driver */
+ Pci::Device_capability _cap; /* PCI cap */
+ pci_device_id const *_id; /* matched id for this driver */
+
+ public:
+
+ pci_dev *_dev; /* Linux PCI device */
+
+ private:
+
+ /* offset used in PCI config space */
+ enum Pci_config { IRQ = 0x3c, REV = 0x8, CMD = 0x4 };
+
+ /**
+ * Match class code of device with driver id
+ */
+ bool _match(pci_device_id const *id)
+ {
+ Pci::Device_client client(_cap);
+ if (!((id->device_class ^ client.class_code()) & id->class_mask)) {
+ _id = id;
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Match supported device ID of driver to this device
+ */
+ bool _match()
+ {
+ pci_device_id const *id = _drv->id_table;
+
+ if (!id)
+ return false;
+
+ while (id->vendor || id->subvendor || id->class_mask) {
+ if (_match(id)) {
+ dde_kit_log(DEBUG_PCI, "Device matched %p", this);
+ return true;
+ }
+ id++;
+ }
+
+ return false;
+ }
+
+ /**
+ * Fill Linux device informations
+ */
+ void _setup_pci_device()
+ {
+ using namespace Pci;
+
+ _dev = new (Genode::env()->heap()) pci_dev;
+ Device_client client(_cap);
+
+ _dev->vendor = client.vendor_id();
+ _dev->device = client.device_id();
+ _dev->device_class = client.class_code();
+ _dev->revision = client.config_read(REV, Device::ACCESS_8BIT);
+ _dev->dev.driver = &_drv->driver;
+
+ /* read interrupt line */
+ _dev->irq = client.config_read(IRQ, Device::ACCESS_8BIT);
+
+ /* hide ourselfs in bus structure */
+ _dev->bus = (struct pci_bus *)this;
+
+ /* setup resources */
+ bool io = false;
+ for (int i = 0; i < Device::NUM_RESOURCES; i++) {
+ Device::Resource res = client.resource(i);
+ _dev->resource[i].start = res.base();
+ _dev->resource[i].end = res.base() + res.size() - 1;
+ _dev->resource[i].flags = res.type() == Device::Resource::IO
+ ? IORESOURCE_IO : 0;
+
+ /* request port I/O session */
+ if (res.type() == Device::Resource::IO) {
+ if (dde_kit_request_io(res.base(), res.size()))
+ PERR("Failed to request I/O: [%u,%u)",
+ res.base(), res.base() + res.size());
+ io = true;
+ dde_kit_log(DEBUG_PCI, "I/O [%u-%u)",
+ res.base(), res.base() + res.size());
+ }
+
+ /* request I/O memory (write combined) */
+ if (res.type() == Device::Resource::MEMORY)
+ dde_kit_log(DEBUG_PCI, "I/O memory [%x-%x)", res.base(),
+ res.base() + res.size());
+ }
+
+ /* enable bus master and io bits */
+ uint16_t cmd = client.config_read(CMD, Device::ACCESS_16BIT);
+ cmd |= io ? 0x1 : 0;
+
+ /* enable bus master */
+ cmd |= 0x4;
+ client.config_write(CMD, cmd, Device::ACCESS_16BIT);
+ }
+
+ /**
+ * Probe device with driver
+ */
+ bool _probe()
+ {
+ _setup_pci_device();
+
+ if (!_drv->probe(_dev, _id))
+ return true;
+
+ PERR("Probe failed\n");
+ return false;
+ }
+
+ template
+ Pci::Device::Access_size _access_size(T t)
+ {
+ switch (sizeof(T))
+ {
+ case 1:
+ return Pci::Device::ACCESS_8BIT;
+ case 2:
+ return Pci::Device::ACCESS_16BIT;
+ default:
+ return Pci::Device::ACCESS_32BIT;
+ }
+ }
+
+ public:
+
+ Pci_driver(pci_driver *drv, Pci::Device_capability cap)
+ : _drv(drv), _cap(cap), _id(0), _dev(0)
+ {
+ if (!_match())
+ throw -1;
+
+ if (!_probe())
+ throw -2;
+ }
+
+ ~Pci_driver()
+ {
+ if (!_dev)
+ return;
+
+ for (int i = 0; i < Pci::Device::NUM_RESOURCES; i++) {
+ resource *r = &_dev->resource[i];
+
+ if (r->flags & IORESOURCE_IO)
+ dde_kit_release_io(r->start, (r->end - r->start) + 1);
+ }
+
+ destroy(Genode::env()->heap(), _dev);
+ }
+
+ /**
+ * Read/write data from/to config space
+ */
+ template
+ void config_read(unsigned int devfn, T *val)
+ {
+ Pci::Device_client client(_cap);
+ *val = client.config_read(devfn, _access_size(*val));
+ }
+
+ template
+ void config_write(unsigned int devfn, T val)
+ {
+ Pci::Device_client client(_cap);
+ client.config_write(devfn, val, _access_size(val));
+ }
+};
+
+
+/*********************
+ ** Linux interface **
+ *********************/
+
+int pci_register_driver(struct pci_driver *drv)
+{
+ dde_kit_log(DEBUG_PCI, "DRIVER name: %s", drv->name);
+ drv->driver.name = drv->name;
+
+ using namespace Genode;
+ Pci::Connection pci;
+
+ Pci::Device_capability cap = pci.first_device();
+ Pci::Device_capability old;
+ while (cap.valid()) {
+
+ uint8_t bus, dev, func;
+ Pci::Device_client client(cap);
+ client.bus_address(&bus, &dev, &func);
+ dde_kit_log(DEBUG_PCI, "bus: %x dev: %x func: %x", bus, dev, func);
+
+ Pci_driver *pci_drv= 0;
+ try {
+ pci_drv = new (env()->heap()) Pci_driver(drv, cap);
+ pci.on_destruction(Pci::Connection::KEEP_OPEN);
+ return 0;
+ } catch (...) {
+ destroy(env()->heap(), pci_drv);
+ pci_drv = 0;
+ }
+
+ old = cap;
+ cap = pci.next_device(cap);
+ pci.release_device(old);
+ }
+
+ return -ENODEV;
+}
+
+
+size_t pci_resource_start(struct pci_dev *dev, unsigned bar)
+{
+ if (bar >= DEVICE_COUNT_RESOURCE)
+ return 0;
+
+ return dev->resource[bar].start;
+}
+
+
+size_t pci_resource_len(struct pci_dev *dev, unsigned bar)
+{
+ size_t start = pci_resource_start(dev, bar);
+
+ if (!start)
+ return 0;
+
+ return (dev->resource[bar].end - start) + 1;
+}
+
+
+unsigned int pci_resource_flags(struct pci_dev *dev, unsigned bar)
+{
+ if (bar >= DEVICE_COUNT_RESOURCE)
+ return 0;
+
+ return dev->resource[bar].flags;
+}
+
+
+int pci_bus_read_config_byte(struct pci_bus *bus, unsigned int devfn, int, u8 *val)
+{
+ Pci_driver *drv = (Pci_driver *)bus;
+ drv->config_read(devfn, val);
+ dde_kit_log(DEBUG_PCI, "READ %p: %x", drv, *val);
+ return 0;
+}
+
+
+int pci_bus_read_config_word(struct pci_bus *bus, unsigned int devfn, int, u16 *val)
+{
+ Pci_driver *drv = (Pci_driver *)bus;
+ drv->config_read(devfn, val);
+ dde_kit_log(DEBUG_PCI, "READ %p: %x", drv, *val);
+ return 0;
+}
+
+
+int pci_bus_write_config_word(struct pci_bus *bus, unsigned int devfn, int, u16 val)
+{
+ Pci_driver *drv = (Pci_driver *)bus;
+ dde_kit_log(DEBUG_PCI, "WRITE %p: %x", drv, val);
+ drv->config_write(devfn, val);
+ return 0;
+}
+
+
+int pci_bus_write_config_byte(struct pci_bus *bus, unsigned int devfn, int, u8 val)
+{
+ Pci_driver *drv = (Pci_driver *)bus;
+ dde_kit_log(DEBUG_PCI, "WRITE %p: %x", drv, val);
+ drv->config_write(devfn, val);
+ return 0;
+}
+
+
+const char *pci_name(const struct pci_dev *pdev)
+{
+ /* simply return driver name */
+ return "dummy";
+}
+
diff --git a/dde_linux/src/drivers/usb/routine.h b/dde_linux/src/drivers/usb/routine.h
new file mode 100644
index 000000000..fc50b3fdd
--- /dev/null
+++ b/dde_linux/src/drivers/usb/routine.h
@@ -0,0 +1,194 @@
+/*
+ * \brief Pseudo-thread implementation using setjmp/longjmp
+ * \author Sebastian Sumpf
+ * \date 2012-04-25
+ */
+
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#ifndef _ROUTINE_H_
+#define _ROUTINE_H_
+
+#include
+#include
+#include
+
+extern "C" {
+#include
+}
+
+static const bool verbose = false;
+
+
+/**
+ * Allows pseudo-parallel execution of functions
+ */
+class Routine : public Genode::List::Element
+{
+ private:
+
+ enum { STACK_SIZE = 0x2000 };
+ bool _started; /* true if already started */
+ jmp_buf _env; /* state */
+ int (*_func)(void *); /* function to call*/
+ void *_arg; /* argument for function */
+ char const *_name; /* name of this object */
+ char *_stack; /* stack pointer */
+ static Routine *_current; /* currently scheduled object */
+ static Routine *_dead; /* object to remove */
+ static bool _all; /* true when all objects must be scheduled */
+
+
+ /**
+ * List containing all registered objects
+ */
+ static Genode::List *_list()
+ {
+ static Genode::List _l;
+ return &_l;
+ }
+
+ /**
+ * Start/restore
+ */
+ void _run()
+ {
+ /* will never return */
+ if (!_started) {
+ _started = true;
+ _stack = (char *)dde_kit_simple_malloc(STACK_SIZE);
+
+ if (verbose)
+ PDBG("Start func %s (%p) sp: %p", _name, _func, (_stack + STACK_SIZE));
+
+ /* XXX move to platform code */
+
+ /* switch stack and call '_func(_arg)' */
+ asm volatile ("movl %2, 0(%0);"
+ "movl %1, -0x4(%0);"
+ "movl %0, %%esp;"
+ "call *-4(%%esp);"
+ : : "r" (_stack + STACK_SIZE), "r" (_func), "r" (_arg));
+ }
+
+ /* restore old state */
+ if (verbose)
+ PDBG("Schedule %s (%p)", _name, _func);
+
+ _longjmp(_env, 1);
+ }
+
+ /**
+ * Check for and remove dead objects
+ */
+ static void _check_dead()
+ {
+ if (!_dead)
+ return;
+
+ _list()->remove(_dead);
+ destroy(Genode::env()->heap(), _dead);
+ _dead = 0;
+ }
+
+ /**
+ * Get next object to schedule
+ */
+ static Routine *_next(bool all)
+ {
+ /* on schedule all start at first element */
+ if (all) {
+ _all = true;
+ return _list()->first();
+ }
+
+ /* disable all at last element */
+ if (_all && _current && !_current->next())
+ _all = false;
+
+ /* return next element (wrap at the end) */
+ return _current && _current->next() ? _current->next() : _list()->first();
+ }
+
+ public:
+
+ Routine(int (*func)(void*), void *arg, char const *name, bool started)
+ : _started(started), _func(func), _arg(arg), _name(name), _stack(0) { }
+
+ ~Routine()
+ {
+ if (_stack)
+ dde_kit_simple_free(_stack);
+ }
+
+ /**
+ * Schedule next object
+ *
+ * If all is true, each object will be scheduled once.
+ */
+ static void schedule(bool all = false) __attribute__((noinline))
+ {
+ if (!_list()->first())
+ return;
+
+ Routine *next = _next(all);
+
+ if (next == _current)
+ return;
+
+ /* return when restored */
+ if (_current && _setjmp(_current->_env)) {
+ _check_dead();
+ return;
+ }
+
+ _current = next;
+ _current->_run();
+ }
+
+ /**
+ * Schedule each object once
+ */
+ static void schedule_all() { schedule(true); }
+
+ /**
+ * Set current to first object
+ */
+ static void current_use_first() { _current = _list()->first(); }
+
+ /**
+ * Add an object
+ */
+ static void add(int (*func)(void *), void *arg, char const *name,
+ bool started = false)
+ {
+ _list()->insert(new (Genode::env()->heap())
+ Routine(func, arg, name, started));
+ }
+
+ /**
+ * Remove this object
+ */
+ static void remove()
+ {
+ if (!_current)
+ return;
+
+ _dead = _current;
+
+ schedule();
+ }
+
+ /**
+ * True when 'schedule_all' has been called and is still in progress
+ */
+ static bool all() { return _all; }
+};
+
+#endif /* _ROUTINE_H_ */
+
diff --git a/dde_linux/src/drivers/usb/signal.h b/dde_linux/src/drivers/usb/signal.h
new file mode 100644
index 000000000..9c766aa8e
--- /dev/null
+++ b/dde_linux/src/drivers/usb/signal.h
@@ -0,0 +1,121 @@
+/*
+ * \brief Main-signal receiver and signal-helper functions
+ * \author Sebastian Sumpf
+ * \date 2012-05-23
+ */
+
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#ifndef _SIGNAL_H_
+#define _SIGNAL_H_
+
+#include
+#include
+#include
+
+#include "routine.h"
+
+/**
+ * Context base for IRQ, Timer, etc.
+ */
+class Driver_context : public Genode::Signal_context
+{
+ public:
+
+ /**
+ * Perform context operation
+ */
+ virtual void handle() = 0;
+};
+
+
+/**
+ * This singelton currently received all signals
+ */
+class Service_handler
+{
+
+ private:
+
+ Genode::Signal_receiver *_receiver;
+
+ Service_handler() { }
+
+ public:
+
+ static Service_handler * s()
+ {
+ static Service_handler _s;
+ return &_s;
+ }
+
+ void receiver(Genode::Signal_receiver *recv) { _receiver = recv; }
+
+ /**
+ * Dispatch for wait for signal
+ */
+ void process()
+ {
+ if (Routine::all()) {
+ Routine::schedule();
+ return;
+ }
+
+ do {
+ Genode::Signal s = _receiver->wait_for_signal();
+
+ /* handle signal IRQ, timer, or event signals */
+ Driver_context *ctx = static_cast(s.context());
+ ctx->handle();
+ } while (_receiver->pending());
+ }
+};
+
+
+/**
+ * Helper that holds sender and receiver
+ */
+class Signal_helper
+{
+ private:
+
+ Genode::Signal_receiver *_receiver;
+ Genode::Signal_transmitter *_sender;
+
+ public:
+
+ Signal_helper(Genode::Signal_receiver *recv)
+ : _receiver(recv),
+ _sender(new (Genode::env()->heap()) Genode::Signal_transmitter()) { }
+
+ Genode::Signal_receiver *receiver() const { return _receiver; }
+ Genode::Signal_transmitter *sender() const { return _sender; }
+};
+
+
+namespace Timer
+{
+ void init(Genode::Signal_receiver *recv);
+}
+
+namespace Irq
+{
+ void init(Genode::Signal_receiver *recv);
+}
+
+namespace Event
+{
+ void init(Genode::Signal_receiver *recv);
+}
+
+namespace Storage
+{
+ void init(Genode::Signal_receiver *recv);
+}
+
+#endif /* _SIGNAL_H_ */
diff --git a/dde_linux/src/drivers/usb/signal/event.cc b/dde_linux/src/drivers/usb/signal/event.cc
new file mode 100644
index 000000000..960739a14
--- /dev/null
+++ b/dde_linux/src/drivers/usb/signal/event.cc
@@ -0,0 +1,167 @@
+/*
+ * \brief Signal context for completions and events
+ * \author Sebastian Sumpf
+ * \date 2012-05-23
+ */
+
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#include
+#include
+
+
+static Signal_helper *_signal = 0;
+
+/**
+ * Context for events
+ */
+class Event_context : public Driver_context
+{
+ private:
+
+ Genode::Signal_context_capability _ctx_cap;
+
+ Event_context()
+ : _ctx_cap(_signal->receiver()->manage(this)) {
+ _signal->sender()->context(_ctx_cap); }
+
+ public:
+
+ static Event_context *e()
+ {
+ static Event_context _e;
+ return &_e;
+ }
+
+ void submit() {
+ _signal->sender()->submit(); }
+
+ void handle() {
+ Routine::schedule_all(); }
+};
+
+
+void Event::init(Genode::Signal_receiver *recv) {
+ _signal = new (Genode::env()->heap()) Signal_helper(recv); }
+
+
+/************************
+ ** linux/completion.h **
+ ************************/
+
+void __wake_up() { Routine::schedule_all(); }
+
+
+void __wait_event() {
+ Service_handler::s()->process(); }
+
+
+void init_completion(struct completion *work)
+{
+ dde_kit_log(DEBUG_COMPLETION, "New completion %p", work);
+ work->done = 0;
+}
+
+
+void complete(struct completion *work)
+{
+ dde_kit_log(DEBUG_COMPLETION, "%p", work);
+ work->done = 1;
+
+ /* send signal */
+ Event_context::e()->submit();
+}
+
+
+void complete_and_exit(struct completion *work, long code)
+{
+ dde_kit_log(DEBUG_COMPLETION, "%p", work);
+ complete(work);
+ Routine::remove();
+}
+
+
+
+static void __wait_completion(struct completion *work)
+{
+ while (!work->done)
+ __wait_event();
+
+ work->done = 0;
+}
+
+
+static unsigned long
+__wait_completion_timeout(struct completion *work, unsigned long timeout)
+{
+ unsigned long _j = jiffies + (timeout / HZ);
+ while (!work->done) {
+ __wait_event();
+
+ if (_j >= jiffies)
+ return 0;
+ }
+
+ work->done = 0;
+
+ return _j - jiffies;
+}
+
+
+unsigned long wait_for_completion_timeout(struct completion *work,
+ unsigned long timeout)
+{
+ dde_kit_log(DEBUG_COMPLETION, "%p state: %u", work, work->done);
+ __wait_completion(work);
+ return 1;
+}
+
+
+int wait_for_completion_interruptible(struct completion *work)
+{
+ dde_kit_log(DEBUG_COMPLETION, "%p state: %u", work, work->done);
+
+ __wait_completion(work);
+ return 0;
+}
+
+
+long wait_for_completion_interruptible_timeout(struct completion *work,
+ unsigned long timeout)
+{
+ dde_kit_log(DEBUG_COMPLETION, "%p state: %u", work, work->done);
+ __wait_completion(work);
+ return 1;
+}
+
+
+void wait_for_completion(struct completion *work)
+{
+ dde_kit_log(DEBUG_COMPLETION, "%p state: %u", work, work->done);
+ __wait_completion(work);
+}
+
+
+/*******************
+ ** linux/timer.h **
+ *******************/
+
+signed long schedule_timeout_uninterruptible(signed long timeout)
+{
+ dde_kit_log(DEBUG_COMPLETION, "%ld\n", timeout);
+ __wait_event();
+ return 0;
+}
+
+
+int wake_up_process(struct task_struct *tsk)
+{
+ Routine::schedule_all();
+ return 0;
+}
+
diff --git a/dde_linux/src/drivers/usb/signal/irq.cc b/dde_linux/src/drivers/usb/signal/irq.cc
new file mode 100644
index 000000000..c6c69b193
--- /dev/null
+++ b/dde_linux/src/drivers/usb/signal/irq.cc
@@ -0,0 +1,140 @@
+/*
+ * \brief Signal context for IRQ's
+ * \author Sebastian Sumpf
+ * \date 2012-05-23
+ */
+
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#include
+#include
+
+extern "C" {
+#include
+}
+
+
+/* our local incarnation of sender and receiver */
+static Signal_helper *_signal = 0;
+
+
+/**
+ * This contains the Linux-driver handlers
+ */
+struct Irq_handler : Genode::List::Element
+{
+ void *dev; /* Linux device */
+ irq_handler_t handler; /* Linux handler */
+
+ Irq_handler(void *dev, irq_handler_t handler)
+ : dev(dev), handler(handler) { }
+};
+
+
+/**
+ * Signal context for IRQs
+ */
+class Irq_context : public Driver_context,
+ public Genode::List::Element
+{
+ private:
+
+ unsigned int _irq; /* IRQ number */
+ Genode::List _handler_list; /* List of registered handlers */
+ Genode::Signal_context_capability _ctx_cap; /* capability for this context */
+
+ static Genode::List *_list()
+ {
+ static Genode::List _l;
+ return &_l;
+ }
+
+ /**
+ * Find context for given IRQ number
+ */
+ static Irq_context *_find_ctx(unsigned int irq)
+ {
+ for (Irq_context *i = _list()->first(); i; i = i->next())
+ if (i->_irq == irq)
+ return i;
+
+ return 0;
+ }
+
+ /* called by the DDE kit upon IRQ */
+ static void _dde_handler(void *irq)
+ {
+ Irq_context *ctx = static_cast(irq);
+
+ /* set context & submit signal */
+ _signal->sender()->context(ctx->_ctx_cap);
+ _signal->sender()->submit();
+ }
+
+ public:
+
+ Irq_context(unsigned int irq)
+ : _irq(irq),
+ _ctx_cap(_signal->receiver()->manage(this))
+ {
+ /* register at DDE (shared) */
+ dde_kit_interrupt_attach(_irq, 1, 0, _dde_handler, this);
+ dde_kit_interrupt_enable(_irq);
+ _list()->insert(this);
+ }
+
+ void handle()
+ {
+ /* report IRQ to all clients */
+ for (Irq_handler *h = _handler_list.first(); h; h = h->next()) {
+ irqreturn_t rc;
+ do {
+ rc = h->handler(_irq, h->dev);
+ }
+ while (rc == IRQ_HANDLED);
+ dde_kit_log(DEBUG_IRQ, "IRQ: %u ret: %u", _irq, rc);
+ if (rc == IRQ_HANDLED) {
+ Routine::schedule_all();
+ return;
+ }
+ }
+ }
+
+ /**
+ * Request an IRQ
+ */
+ static void request_irq(unsigned int irq, irq_handler_t handler, void *dev)
+ {
+ Irq_handler *h = new(Genode::env()->heap()) Irq_handler(dev, handler);
+ Irq_context *ctx = _find_ctx(irq);
+
+ /* if this IRQ is not registered */
+ if (!ctx)
+ ctx = new (Genode::env()->heap()) Irq_context(irq);
+
+ /* register Linux handler */
+ ctx->_handler_list.insert(h);
+ }
+};
+
+
+void Irq::init(Genode::Signal_receiver *recv) {
+ _signal = new (Genode::env()->heap()) Signal_helper(recv); }
+
+
+/***********************
+ ** linux/interrupt.h **
+ ***********************/
+
+int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
+ const char *name, void *dev)
+{
+ dde_kit_log(DEBUG_IRQ, "Request irq %u", irq);
+ Irq_context::request_irq(irq, handler, dev);
+ return 0;
+}
diff --git a/dde_linux/src/drivers/usb/signal/timer.cc b/dde_linux/src/drivers/usb/signal/timer.cc
new file mode 100644
index 000000000..401d331fc
--- /dev/null
+++ b/dde_linux/src/drivers/usb/signal/timer.cc
@@ -0,0 +1,150 @@
+/*
+ * \brief Signal context for timer events
+ * \author Sebastian Sumpf
+ * \date 2012-05-23
+ */
+
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#include
+#include
+
+#include
+#include "signal.h"
+
+static void handler(void *timer);
+
+
+/* our local incarnation of sender and receiver */
+static Signal_helper *_signal = 0;
+
+
+/**
+ * Signal context for time-outs
+ */
+class Timer_context : public Driver_context
+{
+ private:
+
+ timer_list *_timer; /* Linux timer */
+ dde_kit_timer *_dde_timer; /* DDE kit timer */
+ Genode::Signal_context_capability _ctx_cap; /* Signal-context cap
+ for this timer */
+
+ public:
+
+ Timer_context(timer_list *timer)
+ : _timer(timer), _dde_timer(0),
+ _ctx_cap(_signal->receiver()->manage(this)) { }
+
+ ~Timer_context()
+ {
+ _signal->receiver()->dissolve(this);
+ }
+
+ /* call timer function */
+ void handle() { _timer->function(_timer->data); }
+
+ /* schedule next timeout */
+ void schedule(unsigned long expires)
+ {
+ if (!_dde_timer)
+ _dde_timer = dde_kit_timer_add(handler, this, expires);
+ else
+ dde_kit_timer_schedule_absolute(_dde_timer, expires);
+ }
+
+ /**
+ * Return true if timer is pending
+ */
+ bool pending() const
+ {
+ return _dde_timer ? dde_kit_timer_pending(_dde_timer) : false;
+ }
+
+ /**
+ * Return internal signal cap
+ */
+ Genode::Signal_context_capability cap() const { return _ctx_cap; }
+
+ /**
+ * Convert 'timer_list' to 'Timer_conext'
+ */
+ static Timer_context *to_ctx(timer_list const *timer) {
+ return static_cast(timer->timer); }
+
+ void remove()
+ {
+ if (_dde_timer)
+ dde_kit_timer_del(_dde_timer);
+
+ _dde_timer = 0;
+ }
+
+ timer_list *l() { return _timer; }
+};
+
+
+/**
+ * C handler for DDE timer interface
+ */
+static void handler(void *timer)
+{
+ Timer_context *t = static_cast(timer);
+
+ /* set context and submit */
+ _signal->sender()->context(t->cap());
+ _signal->sender()->submit();
+}
+
+
+void Timer::init(Genode::Signal_receiver *recv) {
+ _signal = new (Genode::env()->heap()) Signal_helper(recv); }
+
+
+/*******************
+ ** linux/timer.h **
+ *******************/
+
+void init_timer(struct timer_list *timer) {
+ timer->timer = (void *) new (Genode::env()->heap()) Timer_context(timer); }
+
+
+int mod_timer(struct timer_list *timer, unsigned long expires)
+{
+ dde_kit_log(DEBUG_TIMER, "Timer: %p j: %lu ex: %lu func %p",
+ timer, jiffies, expires, timer->function);
+ Timer_context::to_ctx(timer)->schedule(expires);
+ return 0;
+}
+
+
+void setup_timer(struct timer_list *timer,void (*function)(unsigned long),
+ unsigned long data)
+{
+ timer->function = function;
+ timer->data = data;
+ init_timer(timer);
+}
+
+
+int timer_pending(const struct timer_list * timer)
+{
+ bool pending = Timer_context::to_ctx(timer)->pending();
+ dde_kit_log(DEBUG_TIMER, "Pending %p %u", timer, pending);
+ return pending;
+}
+
+
+int del_timer(struct timer_list *timer)
+{
+ dde_kit_log(DEBUG_TIMER, "Delete timer %p", timer);
+ Timer_context::to_ctx(timer)->remove();
+ return 0;
+}
+
diff --git a/dde_linux/src/drivers/usb/storage/component.h b/dde_linux/src/drivers/usb/storage/component.h
new file mode 100644
index 000000000..244b54fdb
--- /dev/null
+++ b/dde_linux/src/drivers/usb/storage/component.h
@@ -0,0 +1,204 @@
+/*
+ * \brief Block-session implementation for USB storage
+ * \author Sebastian Sumpf
+ * \date 2012-05-23
+ */
+
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#ifndef _STORAGE__COMPONENT_H_
+#define _STORAGE__COMPONENT_H_
+
+#include
+#include
+
+#include "signal.h"
+
+namespace Block {
+
+ using namespace Genode;
+
+ class Session_component;
+
+ struct Device
+ {
+ /**
+ * Request block size for driver and medium
+ */
+ virtual Genode::size_t block_size() = 0;
+
+ /**
+ * Request capacity of medium in blocks
+ */
+ virtual Genode::size_t block_count() = 0;
+
+ virtual void io(Session_component *session, Packet_descriptor &packet,
+ addr_t virt, addr_t phys) = 0;
+ };
+
+
+ template
+ class Signal_dispatcher : public Driver_context,
+ public Signal_context_capability
+ {
+ private:
+
+ T &obj;
+ void (T::*member) ();
+ Signal_receiver *sig_rec;
+
+ public:
+
+ /**
+ * Constructor
+ *
+ * \param sig_rec signal receiver to associate the signal
+ * handler with
+ * \param obj,member object and member function to call when
+ * the signal occurs
+ */
+ Signal_dispatcher(Signal_receiver *sig_rec,
+ T &obj, void (T::*member)())
+ :
+ Signal_context_capability(sig_rec->manage(this)),
+ obj(obj), member(member),
+ sig_rec(sig_rec)
+ { }
+
+ ~Signal_dispatcher() { sig_rec->dissolve(this); }
+
+ void handle() { (obj.*member)(); }
+ };
+
+
+ class Session_component : public Session_rpc_object
+ {
+ private:
+
+ addr_t _rq_phys ; /* physical addr. of rq_ds */
+ Device *_device; /* device this session is using */
+
+ Signal_dispatcher _process_packet_dispatcher;
+
+ void _process_packets()
+ {
+ while (tx_sink()->packet_avail())
+ {
+ Packet_descriptor packet = tx_sink()->get_packet();
+ addr_t virt = (addr_t)tx_sink()->packet_content(packet);
+ addr_t phys = _rq_phys + packet.offset();
+
+ try {
+ _device->io(this, packet, virt, phys);
+ } catch (...) { PERR("Failed to queue packet"); }
+ }
+ }
+
+ public:
+
+ /**
+ * Constructor
+ */
+ Session_component(Dataspace_capability rq_ds,
+ Rpc_entrypoint &ep,
+ Signal_receiver *sig_rec,
+ Device *device)
+ :
+ Session_rpc_object(rq_ds, ep),
+ _rq_phys(Dataspace_client(rq_ds).phys_addr()),
+ _device(device),
+ _process_packet_dispatcher(sig_rec, *this,
+ &Session_component::_process_packets)
+ {
+ /*
+ * Register '_process_packets' dispatch function as signal
+ * handler for packet-avail and ready-to-ack signals.
+ */
+ _tx.sigh_packet_avail(_process_packet_dispatcher);
+ _tx.sigh_ready_to_ack(_process_packet_dispatcher);
+ }
+
+ void info(size_t *blk_count, size_t *blk_size,
+ Operations *ops)
+ {
+ *blk_count = _device->block_count();
+ *blk_size = _device->block_size();
+ ops->set_operation(Packet_descriptor::READ);
+ ops->set_operation(Packet_descriptor::WRITE);
+ }
+
+ void complete(Packet_descriptor &packet, bool success)
+ {
+ packet.succeeded(success);
+ tx_sink()->acknowledge_packet(packet);
+ }
+ };
+
+ /*
+ * Shortcut for single-client root component
+ */
+ typedef Root_component Root_component;
+
+ /**
+ * Root component, handling new session requests
+ */
+ class Root : public Root_component
+ {
+ private:
+
+ Rpc_entrypoint &_ep;
+ Signal_receiver *_sig_rec;
+ Device *_device;
+
+ protected:
+
+ /**
+ * Always returns the singleton block-session component
+ */
+ Session_component *_create_session(const char *args)
+ {
+ size_t ram_quota =
+ Arg_string::find_arg(args, "ram_quota" ).ulong_value(0);
+ size_t tx_buf_size =
+ Arg_string::find_arg(args, "tx_buf_size").ulong_value(0);
+
+ /* delete ram quota by the memory needed for the session */
+ size_t session_size = max((size_t)4096,
+ sizeof(Session_component)
+ + sizeof(Allocator_avl));
+ if (ram_quota < session_size)
+ throw Root::Quota_exceeded();
+
+ /*
+ * Check if donated ram quota suffices for both communication
+ * buffers. Also check both sizes separately to handle a
+ * possible overflow of the sum of both sizes.
+ */
+ if (tx_buf_size > ram_quota - session_size) {
+ PERR("insufficient 'ram_quota', got %zd, need %zd",
+ ram_quota, tx_buf_size + session_size);
+ throw Root::Quota_exceeded();
+ }
+
+ return new (md_alloc())
+ Session_component(env()->ram_session()->alloc(tx_buf_size),
+ _ep, _sig_rec, _device);
+ }
+
+ public:
+
+ Root(Rpc_entrypoint *session_ep, Allocator *md_alloc,
+ Signal_receiver *sig_rec, Device *device)
+ :
+ Root_component(session_ep, md_alloc),
+ _ep(*session_ep), _sig_rec(sig_rec), _device(device)
+ { }
+ };
+}
+
+#endif /* _STORAGE__COMPONENT_H_ */
diff --git a/dde_linux/src/drivers/usb/storage/scsi.c b/dde_linux/src/drivers/usb/storage/scsi.c
new file mode 100644
index 000000000..645545181
--- /dev/null
+++ b/dde_linux/src/drivers/usb/storage/scsi.c
@@ -0,0 +1,218 @@
+/*
+ * \brief SCSI support emulation
+ * \author Christian Helmuth
+ * \author Sebastian Sumpf
+ * \date 2009-10-29
+ *
+ * XXX NOTES XXX
+ *
+ * struct scsi_host_template
+ *
+ * struct scsi_host
+ *
+ * host_lock used by scsi_unlock, scsi_lock
+ * max_id used by usb_stor_report_device_reset
+ *
+ * struct scsi_cmnd
+ *
+ * functions
+ *
+ * scsi_add_host
+ * scsi_host_alloc
+ * scsi_host_get
+ * scsi_host_put
+ * scsi_remove_host
+ * scsi_report_bus_reset
+ * scsi_report_device_reset
+ * scsi_scan_host
+ */
+
+#include
+
+#include "scsi.h"
+
+#define DEBUG_SCSI 0
+
+/***************
+ ** SCSI host **
+ ***************/
+
+struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *t, int priv_size)
+{
+ dde_kit_log(DEBUG_SCSI, "t=%p, priv_size=%d", t, priv_size);
+
+ static int free = 1;
+
+ /* XXX we not some extra space for hostdata[] */
+ static char buffer[4096] __attribute__((aligned(4096)));
+ static struct Scsi_Host *host = (struct Scsi_Host *)buffer;
+
+ /* FIXME we support only one host for now */
+ if (!free) return 0;
+ free = 0;
+
+ host->host_lock = &host->default_lock;
+ spin_lock_init(host->host_lock);
+
+ host->host_no = 13;
+ host->max_id = 8;
+ host->hostt = t;
+
+// rval = scsi_setup_command_freelist(shost);
+// if (rval)
+// goto fail_kfree;
+
+// shost->ehandler = kthread_run(scsi_error_handler, shost,
+// "scsi_eh_%d", shost->host_no);
+// if (IS_ERR(shost->ehandler)) {
+// rval = PTR_ERR(shost->ehandler);
+// goto fail_destroy_freelist;
+// }
+
+ return host;
+}
+
+
+static struct page *_page(struct scsi_cmnd *cmnd)
+{
+ return (struct page *)cmnd->sdb.table.sgl->page_link;
+}
+
+
+void scsi_alloc_buffer(size_t size, struct scsi_cmnd *cmnd)
+{
+ scsi_setup_buffer(cmnd, size, 0, 0);
+ struct scatterlist *sgl = cmnd->sdb.table.sgl;
+ struct page *page = _page(cmnd);
+ page->virt = kmalloc(size, 0);
+ page->phys = dma_map_single_attrs(0, page->virt, 0, 0, 0);
+ sgl->dma_address = page->phys;
+}
+
+
+void scsi_setup_buffer(struct scsi_cmnd *cmnd, size_t size, void *virt, dma_addr_t addr)
+{
+ cmnd->sdb.table.nents = 1;
+ cmnd->sdb.length = size;
+
+ struct scatterlist *sgl = cmnd->sdb.table.sgl;
+
+ struct page *page = _page(cmnd);
+ page->virt = virt;
+ page->phys = addr;
+
+ sgl->page_link = (unsigned long)page;
+ sgl->offset = 0;
+ sgl->length = size;
+ sgl->dma_address = addr;
+ sgl->last = 1;
+}
+
+
+void scsi_free_buffer(struct scsi_cmnd *cmnd)
+{
+ struct page *page = _page(cmnd);
+ if (page)
+ kfree(page->virt);
+}
+
+
+void *scsi_buffer_data(struct scsi_cmnd *cmnd)
+{
+ return _page(cmnd)->virt;
+}
+
+
+struct scsi_cmnd *_scsi_alloc_command()
+{
+ struct scsi_cmnd *cmnd = (struct scsi_cmnd *)kmalloc(sizeof(struct scsi_cmnd), GFP_KERNEL);
+ cmnd->sdb.table.sgl = (struct scatterlist *)kmalloc(sizeof(struct scatterlist), GFP_KERNEL);
+ cmnd->cmnd = kzalloc(MAX_COMMAND_SIZE, 0);
+ cmnd->sdb.table.sgl->page_link = (unsigned long) kzalloc(sizeof(struct page), 0);
+ return cmnd;
+}
+
+
+void _scsi_free_command(struct scsi_cmnd *cmnd)
+{
+ kfree((void *)cmnd->sdb.table.sgl->page_link);
+ kfree(cmnd->sdb.table.sgl);
+ kfree(cmnd->cmnd);
+ kfree(cmnd);
+}
+
+
+static void inquiry_done(struct scsi_cmnd *cmnd)
+{
+ char *data = (char *)scsi_buffer_data(cmnd);
+ dde_kit_printf("Vendor id: %c%c%c%c%c%c%c%c Product id: %s\n",
+ data[8], data[9], data[10], data[11], data[12],
+ data[13], data[14], data[15], &data[16]);
+ complete(cmnd->back);
+}
+
+
+static void scsi_done(struct scsi_cmnd *cmd)
+{
+ complete(cmd->back);
+}
+
+
+void scsi_scan_host(struct Scsi_Host *host)
+{
+ struct scsi_cmnd *cmnd;
+ struct scsi_device *sdev;
+ struct scsi_target *target;
+ struct completion compl;
+ void *result;
+
+ init_completion(&compl);
+
+ sdev = (struct scsi_device *)kmalloc(sizeof(struct scsi_device), GFP_KERNEL);
+ target = (struct scsi_target *)kmalloc(sizeof(struct scsi_target), GFP_KERNEL);
+
+ cmnd = _scsi_alloc_command();
+
+ /* init device */
+ sdev->sdev_target = target;
+ sdev->host = host;
+ sdev->id = 0;
+ sdev->lun = 0;
+ host->hostt->slave_alloc(sdev);
+ host->hostt->slave_configure(sdev);
+
+ /* inquiry (36 bytes for usb) */
+ scsi_alloc_buffer(sdev->inquiry_len, cmnd);
+ cmnd->cmnd[0] = INQUIRY;
+ cmnd->cmnd[4] = sdev->inquiry_len;
+ cmnd->device = sdev;
+ cmnd->cmd_len = 6;
+ cmnd->sc_data_direction = DMA_FROM_DEVICE;
+
+ cmnd->back = &compl;
+ cmnd->scsi_done = inquiry_done;
+
+ host->hostt->queuecommand(host, cmnd);
+ wait_for_completion(&compl);
+
+ /* if PQ and PDT are zero we have a direct access block device conntected */
+ result = scsi_buffer_data(cmnd);
+ if (!((char*)result)[0])
+ scsi_add_device(sdev);
+ else {
+ kfree(sdev);
+ kfree(target);
+ }
+
+ scsi_free_buffer(cmnd);
+ _scsi_free_command(cmnd);
+}
+
+
+/**********************
+ ** scsi/scsi_cmnd.h **
+ **********************/
+
+unsigned scsi_bufflen(struct scsi_cmnd *cmnd) { return cmnd->sdb.length; }
+struct scatterlist *scsi_sglist(struct scsi_cmnd *cmnd) { return cmnd->sdb.table.sgl; }
+unsigned scsi_sg_count(struct scsi_cmnd *cmnd) { return cmnd->sdb.table.nents; }
diff --git a/dde_linux/src/drivers/usb/storage/scsi.h b/dde_linux/src/drivers/usb/storage/scsi.h
new file mode 100644
index 000000000..6b9feb6e0
--- /dev/null
+++ b/dde_linux/src/drivers/usb/storage/scsi.h
@@ -0,0 +1,88 @@
+/*
+ * \brief SCSI helpers
+ * \author Sebastian Sumpf
+ * \date 2012-05-06
+ */
+
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#ifndef _SCSI_H_
+#define _SCSI_H_
+
+struct scsi_cmnd;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Add a SCSI device
+ *
+ * \param sdev Device to add
+ */
+void scsi_add_device(struct scsi_device *sdev);
+
+
+/**
+ * Alloc data buffer for command
+ *
+ * \param size Size of buffer
+ * \param cmnd Command to assciate buffer
+ */
+void scsi_alloc_buffer(size_t size, struct scsi_cmnd *cmnd);
+
+
+/**
+ * Fill command
+ *
+ * \param cmnd Command buffer to setup
+ * \param size Data size
+ * \param virt Virtual address of buffer
+ * \param addr DMA address of buffer
+ */
+void scsi_setup_buffer(struct scsi_cmnd *cmnd, size_t size, void *virt, dma_addr_t addr);
+
+
+/**
+ * Free data buffer of command
+ *
+ * \param cmnd Command
+ */
+void scsi_free_buffer(struct scsi_cmnd *cmnd);
+
+
+/**
+ * Get buffer data for command
+ *
+ * \param cmnd Command to retrieve buffer pointer
+ *
+ * \return Buffer pointer
+ */
+void *scsi_buffer_data(struct scsi_cmnd *cmnd);
+
+
+/**
+ * Allocate a SCSI command
+ *
+ * \return Allocated command or zero on failure
+ */
+struct scsi_cmnd *_scsi_alloc_command();
+
+
+/**
+ * Free a SCSI command
+ *
+ * \param cmnd Command
+ */
+void _scsi_free_command(struct scsi_cmnd *cmnd);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SCSI_H_ */
diff --git a/dde_linux/src/drivers/usb/storage/storage.cc b/dde_linux/src/drivers/usb/storage/storage.cc
new file mode 100644
index 000000000..c47d5aadf
--- /dev/null
+++ b/dde_linux/src/drivers/usb/storage/storage.cc
@@ -0,0 +1,177 @@
+/*
+ * \brief USB storage glue
+ * \author Sebastian Sumpf
+ * \date 2012-05-06
+ */
+
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include "component.h"
+#include "signal.h"
+#include "scsi.h"
+
+static Signal_helper *_signal = 0;
+
+class Storage_device : public Genode::List::Element,
+ public Block::Device
+{
+ private:
+
+ Genode::size_t _block_size;
+ Block::sector_t _block_count;
+ struct scsi_device *_sdev;
+
+ static void _sync_done(struct scsi_cmnd *cmnd) {
+ complete((struct completion *)cmnd->back); }
+
+ static void _async_done(struct scsi_cmnd *cmnd)
+ {
+ Block::Session_component *session = static_cast(cmnd->session);
+ Block::Packet_descriptor *packet = static_cast(cmnd->packet);
+
+ if (verbose)
+ PDBG("ACK packet for block: %zu status: %d", packet->block_number(), cmnd->result);
+
+ session->complete(*packet, true);
+ _scsi_free_command(cmnd);
+ }
+
+ void _capacity()
+ {
+ struct completion comp;
+
+ struct scsi_cmnd *cmnd = _scsi_alloc_command();
+
+ /* alloc data for command */
+ scsi_alloc_buffer(8, cmnd);
+
+ cmnd->cmnd[0] = READ_CAPACITY;
+ cmnd->cmd_len = 10;
+ cmnd->device = _sdev;
+ cmnd->sc_data_direction = DMA_FROM_DEVICE;
+
+ init_completion(&comp);
+ cmnd->back = ∁
+ cmnd->scsi_done = _sync_done;
+
+ _sdev->host->hostt->queuecommand(_sdev->host, cmnd);
+ wait_for_completion(&comp);
+
+ Genode::uint32_t *data = (Genode::uint32_t *)scsi_buffer_data(cmnd);
+ _block_count = bswap(data[0]);
+ _block_size = bswap(data[1]);
+
+ /* if device returns the highest block number */
+ if (!_sdev->fix_capacity)
+ _block_count++;
+
+ if (verbose)
+ PDBG("block size: %zu block count: %llu", _block_size, _block_count);
+
+ scsi_free_buffer(cmnd);
+ _scsi_free_command(cmnd);
+ }
+
+
+ Storage_device(struct scsi_device *sdev) : _sdev(sdev)
+ {
+ /* read device capacity */
+ _capacity();
+ }
+
+ public:
+
+ static Storage_device *add(struct scsi_device *sdev) {
+ return new (Genode::env()->heap()) Storage_device(sdev); }
+
+ Genode::size_t block_size() { return _block_size; }
+ Genode::size_t block_count() { return _block_count; }
+
+ void io(Block::Session_component *session, Block::Packet_descriptor &packet,
+ Genode::addr_t virt, Genode::addr_t phys)
+ {
+ Block::sector_t block_nr = packet.block_number();
+ Genode::uint16_t block_count = packet.block_count() & 0xffff;
+ bool read = packet.operation() == Block::Packet_descriptor::WRITE ? false : true;
+
+ if (block_nr > _block_count)
+ throw -1;
+
+ if (verbose)
+ PDBG("PACKET: phys: %lx block: %llu count: %u %s",
+ phys, block_nr, block_count, read ? "read" : "write");
+
+ struct scsi_cmnd *cmnd = _scsi_alloc_command();
+
+ cmnd->cmnd[0] = read ? READ_10 : WRITE_10;
+ cmnd->cmd_len = 10;
+ cmnd->device = _sdev;
+ cmnd->sc_data_direction = read ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+ cmnd->scsi_done = _async_done;
+
+ Block::Packet_descriptor *p = new (Genode::env()->heap()) Block::Packet_descriptor();
+ *p = packet;
+ cmnd->packet = (void *)p;
+ cmnd->session = (void *)session;
+
+ Genode::uint32_t be_block_nr = bswap(block_nr);
+ Genode::memcpy(&cmnd->cmnd[2], &be_block_nr, 4);
+
+ /* transfer one block */
+ Genode::uint16_t be_block_count = bswap(block_count);
+ Genode::memcpy(&cmnd->cmnd[7], &be_block_count, 2);
+
+ /* setup command */
+ scsi_setup_buffer(cmnd, block_count * _block_size, (void *)virt, phys);
+
+ /*
+ * Required by 'last_sector_hacks' in 'drivers/usb/storage/transprot.c
+ */
+ struct request req;
+ req.rq_disk = 0;
+ cmnd->request = &req;
+
+ /* send command to host driver */
+ if (_sdev->host->hostt->queuecommand(_sdev->host, cmnd)) {
+ throw -2;
+ }
+ }
+};
+
+
+void Storage::init(Genode::Signal_receiver *recv) {
+ _signal = new (Genode::env()->heap()) Signal_helper(recv); }
+
+
+void scsi_add_device(struct scsi_device *sdev)
+{
+ using namespace Genode;
+ static bool announce = false;
+
+ Storage_device *device = Storage_device::add(sdev);
+
+ /*
+ * XXX move to 'main'
+ */
+ if (!announce) {
+ static Cap_connection cap_stor;
+ static Rpc_entrypoint ep_stor(&cap_stor, 4096, "usb_stor_ep");
+ static Block::Root root(&ep_stor, env()->heap(), _signal->receiver(), device);
+ env()->parent()->announce(ep_stor.manage(&root));
+ announce = true;
+ }
+}
+
diff --git a/dde_linux/src/drivers/usb/target.mk b/dde_linux/src/drivers/usb/target.mk
new file mode 100644
index 000000000..59642fda8
--- /dev/null
+++ b/dde_linux/src/drivers/usb/target.mk
@@ -0,0 +1,92 @@
+TARGET = usb_drv
+REQUIRES = x86 32bit
+LIBS = cxx env dde_kit server libc-setjmp signal
+SRC_CC = main.cc lx_emul.cc pci_driver.cc irq.cc timer.cc event.cc storage.cc \
+ input_component.cc
+SRC_C = dummies.c scsi.c evdev.c
+
+CONTRIB_DIR := $(REP_DIR)/contrib
+DRIVERS_DIR := $(CONTRIB_DIR)/drivers
+USB_DIR := $(DRIVERS_DIR)/usb
+
+#
+# The order of include-search directories is important, we need to look into
+# 'contrib' before falling back to our custom 'lx_emul.h' header.
+#
+INC_DIR += $(PRG_DIR)
+INC_DIR += $(CONTRIB_DIR)/include
+INC_DIR += $(shell pwd)
+
+CC_OPT += -U__linux__ -D__KERNEL__
+CC_OPT += -DCONFIG_USB_DEVICEFS -DCONFIG_HOTPLUG -DCONFIG_PCI -DDEBUG
+
+CC_WARN = -Wall -Wno-unused-variable -Wno-uninitialized \
+ -Wno-unused-function \
+
+CC_C_OPT += -Wno-implicit-function-declaration -Wno-unused-but-set-variable \
+ -Wno-pointer-sign
+
+#
+# Suffix of global 'module_init' function
+#
+MOD_SUFFIX =
+CC_OPT += -DMOD_SUFFIX=$(MOD_SUFFIX)
+
+# USB core
+SRC_C += $(addprefix usb/core/,$(notdir $(wildcard $(USB_DIR)/core/*.c)))
+SRC_C += usb/usb-common.c
+
+# USB host-controller driver
+#SRC_C += $(addprefix usb/host/,uhci-hcd.c pci-quirks.c ehci-hcd.c ohci-hcd.c)
+SRC_C += $(addprefix usb/host/,pci-quirks.c uhci-hcd.c ehci-hcd.c)
+
+# USB hid
+SRC_C += $(addprefix hid/usbhid/,hid-core.c hid-quirks.c usbmouse.c usbkbd.c)
+SRC_C += hid/hid-input.c hid/hid-core.c input/evdev.c input/input.c
+
+# USB storage
+SRC_C += $(addprefix usb/storage/,scsiglue.c protocol.c transport.c usb.c \
+ initializers.c option_ms.c sierra_ms.c usual-tables.c)
+
+# SCSI
+SRC_C += $(addprefix scsi/,scsi.c constants.c)
+
+#
+# Determine the header files included by the contrib code. For each
+# of these header files we create a symlink to 'lx_emul.h'.
+#
+GEN_INCLUDES := $(shell grep -rh "^\#include .*\/" $(CONTRIB_DIR) |\
+ sed "s/^\#include *[<\"]\(.*\)[>\"].*/\1/" | sort | uniq)
+
+#
+# Filter out some black-listed headers
+#
+NO_GEN_INCLUDES := ../../scsi/sd.h
+
+#
+# Filter out original Linux headers that exist in the contrib directory
+#
+NO_GEN_INCLUDES := $(shell cd $(CONTRIB_DIR)/include; find -name "*.h" | sed "s/.\///")
+GEN_INCLUDES := $(filter-out $(NO_GEN_INCLUDES),$(GEN_INCLUDES))
+
+#
+# Make sure to create the header symlinks prior building
+#
+$(SRC_C:.c=.o) $(SRC_CC:.cc=.o): $(GEN_INCLUDES)
+
+#
+# Add prefix, since there are two hid-core.c with the same module init function
+#
+hid/hid-core.o: MOD_SUFFIX="_core"
+
+$(GEN_INCLUDES):
+ $(VERBOSE)mkdir -p $(dir $@)
+ $(VERBOSE)ln -s $(REP_DIR)/src/drivers/usb/lx_emul.h $@
+
+vpath %.c $(DRIVERS_DIR)
+vpath %.c $(USB_DIR)/host
+vpath %.cc $(PRG_DIR)/signal
+vpath %.c $(PRG_DIR)/input
+vpath %.cc $(PRG_DIR)/input
+vpath %.cc $(PRG_DIR)/storage
+vpath %.c $(PRG_DIR)/storage
diff --git a/os/include/block_session/block_session.h b/os/include/block_session/block_session.h
index be3c1e768..df8d34b43 100644
--- a/os/include/block_session/block_session.h
+++ b/os/include/block_session/block_session.h
@@ -30,6 +30,11 @@
namespace Block {
+ /**
+ * Sector type for block session
+ */
+ typedef Genode::uint64_t sector_t;
+
/**
* Represents an operation request with respect to a block,
* the data associated with the 'Packet_descriptor' is either
diff --git a/os/include/block_session/rpc_object.h b/os/include/block_session/rpc_object.h
index accce5c1a..4412093ee 100644
--- a/os/include/block_session/rpc_object.h
+++ b/os/include/block_session/rpc_object.h
@@ -22,7 +22,7 @@ namespace Block {
class Session_rpc_object : public Genode::Rpc_object
{
- private:
+ protected:
Packet_stream_tx::Rpc_object _tx;
diff --git a/tool/builddir/etc/build.conf.drivers_x86 b/tool/builddir/etc/build.conf.drivers_x86
index 32b673a26..98bcceda0 100644
--- a/tool/builddir/etc/build.conf.drivers_x86
+++ b/tool/builddir/etc/build.conf.drivers_x86
@@ -1,9 +1,18 @@
#
-# Drivers ported from the Linux kernel
+# Drivers ported from the Linux kernel (USB)
#
# Not supported on the ARM architecture.
#
+#REPOSITORIES += $(GENODE_DIR)/dde_linux
+
+#
+# Additional drivers ported from the Linux kernel (audio, Intel GEM)
+#
+# Not supported on the ARM architecture.
+#
+# This repository is deprecated.
+#
#REPOSITORIES += $(GENODE_DIR)/linux_drivers
#