diff --git a/repos/dde_linux/intel_fb.list b/repos/dde_linux/intel_fb.list new file mode 100644 index 000000000..011cfa1f0 --- /dev/null +++ b/repos/dde_linux/intel_fb.list @@ -0,0 +1,63 @@ +linux-3.14.5/drivers/char/agp/intel-gtt.c +linux-3.14.5/drivers/char/agp/intel-agp.h +linux-3.14.5/drivers/char/agp/agp.h +linux-3.14.5/drivers/char/agp/generic.c +linux-3.14.5/drivers/char/agp/backend.c +linux-3.14.5/drivers/i2c/i2c-core.c +linux-3.14.5/drivers/i2c/i2c-core.h +linux-3.14.5/drivers/i2c/i2c-boardinfo.c +linux-3.14.5/drivers/gpu/drm/drm_mm.c +linux-3.14.5/drivers/gpu/drm/drm_crtc.c +linux-3.14.5/drivers/gpu/drm/drm_edid.c +linux-3.14.5/drivers/gpu/drm/i915/i915_dma.c +linux-3.14.5/drivers/gpu/drm/i915/i915_drv.c +linux-3.14.5/drivers/gpu/drm/i915/i915_drv.h +linux-3.14.5/drivers/gpu/drm/i915/i915_gem.c +linux-3.14.5/drivers/gpu/drm/i915/i915_gem_stolen.c +linux-3.14.5/drivers/gpu/drm/i915/i915_reg.h +linux-3.14.5/drivers/gpu/drm/i915/i915_gem_gtt.c +linux-3.14.5/drivers/gpu/drm/i915/i915_irq.c +linux-3.14.5/drivers/gpu/drm/i915/intel_bios.h +linux-3.14.5/drivers/gpu/drm/i915/intel_ddi.c +linux-3.14.5/drivers/gpu/drm/i915/intel_dp.c +linux-3.14.5/drivers/gpu/drm/i915/intel_drv.h +linux-3.14.5/drivers/gpu/drm/i915/intel_ringbuffer.h +linux-3.14.5/drivers/gpu/drm/i915/intel_display.c +linux-3.14.5/drivers/gpu/drm/i915/intel_panel.c +linux-3.14.5/drivers/gpu/drm/i915/intel_uncore.c +linux-3.14.5/drivers/gpu/drm/i915/intel_lvds.c +linux-3.14.5/drivers/gpu/drm/i915/intel_i2c.c +linux-3.14.5/include/asm-generic/atomic64.h +linux-3.14.5/include/asm-generic/ioctl.h +linux-3.14.5/include/asm-generic/getorder.h +linux-3.14.5/include/asm-generic/bitops/__ffs.h +linux-3.14.5/include/asm-generic/bitops/__fls.h +linux-3.14.5/include/asm-generic/bitops/ffs.h +linux-3.14.5/include/asm-generic/bitops/fls.h +linux-3.14.5/include/asm-generic/bitops/fls64.h +linux-3.14.5/include/asm-generic/bitops/non-atomic.h +linux-3.14.5/include/linux/agp_backend.h +linux-3.14.5/include/linux/list.h +linux-3.14.5/include/linux/log2.h +linux-3.14.5/include/linux/pci_ids.h +linux-3.14.5/include/linux/i2c-algo-bit.h +linux-3.14.5/include/linux/i2c.h +linux-3.14.5/include/drm/intel-gtt.h +linux-3.14.5/include/drm/i915_pciids.h +linux-3.14.5/include/drm/i915_drm.h +linux-3.14.5/include/drm/drm_dp_helper.h +linux-3.14.5/include/drm/drm_mm.h +linux-3.14.5/include/drm/drm_crtc.h +linux-3.14.5/include/drm/drm_crtc_helper.h +linux-3.14.5/include/drm/drm_edid.h +linux-3.14.5/include/uapi/drm/i915_drm.h +linux-3.14.5/include/uapi/drm/drm.h +linux-3.14.5/include/uapi/linux/pci_regs.h +linux-3.14.5/include/uapi/linux/i2c.h +linux-3.14.5/include/uapi/asm-generic/ioctl.h +linux-3.14.5/include/uapi/drm/drm_fourcc.h +linux-3.14.5/include/uapi/drm/drm_mode.h +linux-3.14.5/include/uapi/linux/byteorder/little_endian.h +linux-3.14.5/include/uapi/linux/swab.h +linux-3.14.5/arch/x86/include/asm/agp.h + diff --git a/repos/dde_linux/lib/import/import-intel_fb_include.mk b/repos/dde_linux/lib/import/import-intel_fb_include.mk new file mode 100644 index 000000000..ee4a43651 --- /dev/null +++ b/repos/dde_linux/lib/import/import-intel_fb_include.mk @@ -0,0 +1,27 @@ +LX_CONTRIB_DIR := $(call select_from_ports,dde_linux)/src/drivers/framebuffer/intel +SRC_DIR := $(REP_DIR)/src/drivers/framebuffer/intel + +# architecture-dependent includes +ifeq ($(filter-out $(SPECS),x86),) + ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/x86 \ + $(LX_CONTRIB_DIR)/arch/x86/include + ifeq ($(filter-out $(SPECS),32bit),) + ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/x86_32 + endif # 32bit + ifeq ($(filter-out $(SPECS),64bit),) + ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/x86_64 + endif # 64bit +endif # x86 + +INC_DIR += $(SRC_DIR)/include \ + $(REP_DIR)/src/include \ + $(ARCH_SRC_INC_DIR) \ + $(LX_CONTRIB_DIR)/drivers/gpu/drm \ + $(LX_CONTRIB_DIR)/drivers/gpu/include/drm \ + $(LX_CONTRIB_DIR)/drivers/gpu/include \ + $(LX_CONTRIB_DIR)/include \ + $(LX_CONTRIB_DIR)/include/uapi \ + $(LIB_CACHE_DIR)/intel_fb_include + +CC_OPT += -U__linux__ -D__KERNEL__ +CC_OPT += -DCONFIG_DRM_I915_KMS -DCONFIG_I2C -DCONFIG_I2C_BOARDINFO diff --git a/repos/dde_linux/lib/mk/intel_fb_drv.mk b/repos/dde_linux/lib/mk/intel_fb_drv.mk new file mode 100644 index 000000000..d5a5fd05d --- /dev/null +++ b/repos/dde_linux/lib/mk/intel_fb_drv.mk @@ -0,0 +1,25 @@ +LX_CONTRIB_DIR := $(call select_from_ports,dde_linux)/src/drivers/framebuffer/intel +SRC_DIR := $(REP_DIR)/src/drivers/framebuffer/intel + +LIBS += intel_fb_include + +SRC_C := +SRC_C += $(notdir $(wildcard $(LX_CONTRIB_DIR)/drivers/char/agp/*.c)) +SRC_C += $(notdir $(wildcard $(LX_CONTRIB_DIR)/drivers/i2c/*.c)) +SRC_C += $(notdir $(wildcard $(LX_CONTRIB_DIR)/drivers/gpu/drm/*.c)) +SRC_C += $(notdir $(wildcard $(LX_CONTRIB_DIR)/drivers/gpu/drm/i915/*.c)) + +#SRC_C := $(filter-out intel_dp.c,$(SRC_C)) +#SRC_C := intel_panel.c + +# +# Reduce build noise of compiling contrib code +# +CC_WARN = -Wall -Wno-uninitialized -Wno-unused-but-set-variable \ + -Wno-unused-variable -Wno-unused-function + +vpath %.c $(LX_CONTRIB_DIR)/drivers/char/agp +vpath %.c $(LX_CONTRIB_DIR)/drivers/i2c +vpath %.c $(LX_CONTRIB_DIR)/drivers/gpu/drm/i915 +vpath %.c $(LX_CONTRIB_DIR)/drivers/gpu/drm + diff --git a/repos/dde_linux/lib/mk/intel_fb_include.mk b/repos/dde_linux/lib/mk/intel_fb_include.mk new file mode 100644 index 000000000..7ea5de693 --- /dev/null +++ b/repos/dde_linux/lib/mk/intel_fb_include.mk @@ -0,0 +1,17 @@ +# +# Pseudo library to generate a symlink for each header file included by the +# contrib code. Each symlink points to the same 'lx_emul.h' file, which +# provides our emulation of the Linux kernel API. +# + +LX_CONTRIB_DIR := $(call select_from_ports,dde_linux)/src/drivers/framebuffer/intel +LX_EMUL_H := $(REP_DIR)/src/drivers/framebuffer/intel/include/lx_emul.h + +GEN_INCLUDES := $(shell grep -rh "^\#include .*\/" $(LX_CONTRIB_DIR) |\ + sed "s/^\#include [^<\"]*[<\"]\([^>\"]*\)[>\"].*/\1/" | sort | uniq) + +all: $(GEN_INCLUDES) + +$(GEN_INCLUDES): + $(VERBOSE)mkdir -p $(dir $@) + $(VERBOSE)ln -sf $(LX_EMUL_H) $@ diff --git a/repos/dde_linux/ports/dde_linux.port b/repos/dde_linux/ports/dde_linux.port index 0f70dd29b..4f9f0847f 100644 --- a/repos/dde_linux/ports/dde_linux.port +++ b/repos/dde_linux/ports/dde_linux.port @@ -1,9 +1,12 @@ LICENSE := GPL VERSION := 1 -DOWNLOADS := dwc_otg.git usb.archive lxip.archive wifi.archive \ +DOWNLOADS := dwc_otg.git usb.archive lxip.archive intel_fb.archive wifi.archive \ libnl.archive wpa_supplicant.archive \ fw_6000.archive fw_6205a.archive fw_6205b.archive fw_7260.archive fw_7265.archive +# XXX disable all parts except for intel_fb +DOWNLOADS := intel_fb.archive + # # Tools # @@ -37,6 +40,16 @@ URL(dwc_otg) := https://github.com/nfeske/dwc_otg.git REV(dwc_otg) := r2 DIR(dwc_otg) := $(SRC_DIR_USB)/drivers/usb/host/dwc_otg +# +# Intel framebuffer driver +# +SRC_DIR_INTEL_FB := src/drivers/framebuffer/intel +URL(intel_fb) := ${URL(usb)} +SHA(intel_fb) := ${SHA(usb)} +DIR(intel_fb) := $(SRC_DIR_INTEL_FB) +TAR_OPT(intel_fb) := --strip-components=1 --files-from $(REP_DIR)/intel_fb.list +HASH_INPUT += $(REP_DIR)/intel_fb.list + # # mac80211 stack, iwlwifi and iwslegacy sources # @@ -162,4 +175,7 @@ PATCH_OPT(patches/libnl.patch) := -p1 -d ${DIR(libnl)} # WPA supplicant PATCH_OPT(patches/wpa_supplicant.patch) := -p1 -d ${DIR(wpa_supplicant)} +# XXX disable all patches of non-intel_fb subsystems +PATCHES := + # vi: set ft=make : diff --git a/repos/dde_linux/run/intel_fb.run b/repos/dde_linux/run/intel_fb.run new file mode 100644 index 000000000..21e339bbc --- /dev/null +++ b/repos/dde_linux/run/intel_fb.run @@ -0,0 +1,79 @@ +# +# Build +# + +set build_components { + core init + drivers/timer + drivers/framebuffer/intel +} + +source ${genode_dir}/repos/base/run/platform_drv.inc +append_platform_drv_build_components + +build $build_components + +create_boot_directory + +proc platform_drv_policy {} { + return { + + + + + + } +} + +# +# Generate config +# + +append config { + + + + + + + + + + + + + + + + + } + +append_platform_drv_config + +append config { + + + + + + + + +} + +install_config $config + +# +# Boot modules +# + +# generic modules +set boot_modules { + core init timer intel_fb_drv +} + +append_platform_drv_boot_modules + +build_boot_image $boot_modules + +run_genode_until forever diff --git a/repos/dde_linux/src/drivers/framebuffer/intel/dummies.cc b/repos/dde_linux/src/drivers/framebuffer/intel/dummies.cc new file mode 100644 index 000000000..6efed3db1 --- /dev/null +++ b/repos/dde_linux/src/drivers/framebuffer/intel/dummies.cc @@ -0,0 +1,139 @@ +/* + * \brief Dummy functions + * \author Norman Feske + * \date 2015-08-18 + */ + +/* + * Copyright (C) 2015 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 "lx_emul_private.h" + +extern "C" { + +#include +#include + +/* + * Incorporate dummy implemementations semi-automaticall generated via the + * 'gen_dummy' script. + */ + +#include "gen_dummies.h" + +/* + * Manually defined dummies (because they are not covered by the heuristics + * of the 'gen_dummy' script). + */ + +struct timespec timespec_sub(struct timespec lhs, struct timespec rhs) +{ + TRACE_AND_STOP; + return { 0, 0 }; +} + +struct timespec ns_to_timespec(const s64 nsec) +{ + TRACE_AND_STOP; + return { 0, 0 }; +} + +void hex_dump_to_buffer(const void *buf, size_t len, int rowsize, int groupsize, char *linebuf, size_t linebuflen, bool ascii) +{ + TRACE_AND_STOP; +} + +bool mod_delayed_work(struct workqueue_struct *, struct delayed_work *, unsigned long) +{ + TRACE_AND_STOP; + return false; +} + +bool capable(int cap) +{ + TRACE_AND_STOP; + return false; +} + +int drm_dp_bw_code_to_link_rate(u8 link_bw) +{ + TRACE_AND_STOP; + return -1; +} + +bool intel_fbc_enabled(struct drm_device *dev) +{ + TRACE_AND_STOP; + return false; +} + +int i2c_dp_aux_add_bus(struct i2c_adapter *adapter) +{ + TRACE_AND_STOP; + return -1; +} + +int i915_gem_execbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + TRACE_AND_STOP; + return -1; +} + +int i915_gem_execbuffer2(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + TRACE_AND_STOP; + return -1; +} + +int i915_gem_set_tiling(struct drm_device *dev, void *data, struct drm_file *file) +{ + TRACE_AND_STOP; + return -1; +} + +int i915_gem_get_tiling(struct drm_device *dev, void *data, struct drm_file *file) +{ + TRACE_AND_STOP; + return -1; +} + +int intel_overlay_put_image(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + TRACE_AND_STOP; + return -1; +} + +int intel_overlay_attrs(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + TRACE_AND_STOP; + return -1; +} + +bool flush_delayed_work(struct delayed_work *dwork) +{ + TRACE_AND_STOP; + return false; +} + +void *krealloc(const void *, size_t, gfp_t) +{ + TRACE_AND_STOP; + return NULL; +} + +void down_read(struct rw_semaphore *sem) +{ + TRACE_AND_STOP; +} + +void device_unregister(struct device *dev) +{ + TRACE_AND_STOP; +} + + +} /* extern "C" */ diff --git a/repos/dde_linux/src/drivers/framebuffer/intel/gen_dummies.h b/repos/dde_linux/src/drivers/framebuffer/intel/gen_dummies.h new file mode 100644 index 000000000..3cfcdc371 --- /dev/null +++ b/repos/dde_linux/src/drivers/framebuffer/intel/gen_dummies.h @@ -0,0 +1,1682 @@ +bool access_ok(int access, void *addr, size_t size) +{ + TRACE_AND_STOP; + return -1; +} + +int acpi_video_register(void) +{ + TRACE_AND_STOP; + return -1; +} + +void acpi_video_unregister(void) +{ + TRACE_AND_STOP; +} + +void add_wait_queue(wait_queue_head_t *, wait_queue_t *) +{ + TRACE_AND_STOP; +} + +void assert_spin_locked(spinlock_t *lock) +{ + TRACE_AND_STOP; +} + +void atomic_set_mask(unsigned int mask, atomic_t *v) +{ + TRACE_AND_STOP; +} + +bool cancel_delayed_work_sync(struct delayed_work *work) +{ + TRACE_AND_STOP; + return -1; +} + +bool cancel_work_sync(struct work_struct *work) +{ + TRACE_AND_STOP; + return -1; +} + +void console_lock(void) +{ + TRACE_AND_STOP; +} + +int console_trylock(void) +{ + TRACE_AND_STOP; + return -1; +} + +void console_unlock(void) +{ + TRACE_AND_STOP; +} + +size_t copy_from_user(void *to, void const *from, size_t len) +{ + TRACE_AND_STOP; + return -1; +} + +size_t copy_to_user(void *dst, void const *src, size_t len) +{ + TRACE_AND_STOP; + return -1; +} + +void cpu_relax(void) +{ + TRACE_AND_STOP; +} + +void destroy_timer_on_stack(struct timer_list *timer) +{ + TRACE_AND_STOP; +} + +void destroy_workqueue(struct workqueue_struct *wq) +{ + TRACE_AND_STOP; +} + +int dma_map_sg_attrs(struct device *dev, struct scatterlist *sg, int nents, enum dma_data_direction dir, struct dma_attrs *attrs) +{ + TRACE_AND_STOP; + return -1; +} + +int dma_set_coherent_mask(struct device *dev, u64 mask) +{ + TRACE_AND_STOP; + return -1; +} + +void dma_unmap_sg_attrs(struct device *dev, struct scatterlist *sg, int nents, enum dma_data_direction dir, struct dma_attrs *attrs) +{ + TRACE_AND_STOP; +} + +void drm_calc_timestamping_constants(struct drm_crtc *crtc, const struct drm_display_mode *mode) +{ + TRACE_AND_STOP; +} + +int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc, int *max_error, struct timeval *vblank_time, unsigned flags, const struct drm_crtc *refcrtc, const struct drm_display_mode *mode) +{ + TRACE_AND_STOP; + return -1; +} + +void drm_clflush_pages(struct page *pages[], unsigned long num_pages) +{ + TRACE_AND_STOP; +} + +void drm_clflush_sg(struct sg_table *st) +{ + TRACE_AND_STOP; +} + +void drm_clflush_virt_range(char *addr, unsigned long length) +{ + TRACE_AND_STOP; +} + +bool drm_dp_channel_eq_ok(const u8 link_status[DP_LINK_STATUS_SIZE], int lane_count) +{ + TRACE_AND_STOP; + return -1; +} + +bool drm_dp_clock_recovery_ok(const u8 link_status[DP_LINK_STATUS_SIZE], int lane_count) +{ + TRACE_AND_STOP; + return -1; +} + +u8 drm_dp_get_adjust_request_pre_emphasis(const u8 link_status[DP_LINK_STATUS_SIZE], int lane) +{ + TRACE_AND_STOP; + return -1; +} + +u8 drm_dp_get_adjust_request_voltage(const u8 link_status[DP_LINK_STATUS_SIZE], int lane) +{ + TRACE_AND_STOP; + return -1; +} + +void drm_dp_link_train_channel_eq_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE]) +{ + TRACE_AND_STOP; +} + +void drm_dp_link_train_clock_recovery_delay(const u8 dpcd[DP_RECEIVER_CAP_SIZE]) +{ + TRACE_AND_STOP; +} + +int drm_gem_create_mmap_offset(struct drm_gem_object *obj) +{ + TRACE_AND_STOP; + return -1; +} + +int drm_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev, uint32_t handle) +{ + TRACE_AND_STOP; + return -1; +} + +void drm_gem_free_mmap_offset(struct drm_gem_object *obj) +{ + TRACE_AND_STOP; +} + +int drm_gem_handle_create(struct drm_file *file_priv, struct drm_gem_object *obj, u32 *handlep) +{ + TRACE_AND_STOP; + return -1; +} + +int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) +{ + TRACE_AND_STOP; + return -1; +} + +int drm_gem_object_init(struct drm_device *dev, struct drm_gem_object *obj, size_t size) +{ + TRACE_AND_STOP; + return -1; +} + +struct drm_gem_object *drm_gem_object_lookup(struct drm_device *dev, struct drm_file *filp, u32 handle) +{ + TRACE_AND_STOP; + return NULL; +} + +void drm_gem_object_reference(struct drm_gem_object *obj) +{ + TRACE_AND_STOP; +} + +void drm_gem_object_release(struct drm_gem_object *obj) +{ + TRACE_AND_STOP; +} + +void drm_gem_object_unreference(struct drm_gem_object *obj) +{ + TRACE_AND_STOP; +} + +void drm_gem_object_unreference_unlocked(struct drm_gem_object *obj) +{ + TRACE_AND_STOP; +} + +int drm_gem_prime_fd_to_handle(struct drm_device *dev, struct drm_file *file_priv, int prime_fd, uint32_t *handle) +{ + TRACE_AND_STOP; + return -1; +} + +int drm_gem_prime_handle_to_fd(struct drm_device *dev, struct drm_file *file_priv, uint32_t handle, uint32_t flags, int *prime_fd) +{ + TRACE_AND_STOP; + return -1; +} + +void drm_gem_vm_close(struct vm_area_struct *vma) +{ + TRACE_AND_STOP; +} + +void drm_gem_vm_open(struct vm_area_struct *vma) +{ + TRACE_AND_STOP; +} + +struct drm_local_map *drm_getsarea(struct drm_device *dev) +{ + TRACE_AND_STOP; + return NULL; +} + +bool drm_handle_vblank(struct drm_device *dev, int crtc) +{ + TRACE_AND_STOP; + return -1; +} + +bool drm_helper_hpd_irq_event(struct drm_device *dev) +{ + TRACE_AND_STOP; + return -1; +} + +int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb, struct drm_mode_fb_cmd2 *mode_cmd) +{ + TRACE_AND_STOP; + return -1; +} + +void drm_helper_move_panel_connectors_to_head(struct drm_device *) +{ + TRACE_AND_STOP; +} + +int drm_helper_probe_single_connector_modes(struct drm_connector *connector, uint32_t maxX, uint32_t maxY) +{ + TRACE_AND_STOP; + return -1; +} + +long drm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + TRACE_AND_STOP; + return -1; +} + +int drm_irq_uninstall(struct drm_device *dev) +{ + TRACE_AND_STOP; + return -1; +} + +void drm_kms_helper_hotplug_event(struct drm_device *dev) +{ + TRACE_AND_STOP; +} + +void drm_kms_helper_poll_disable(struct drm_device *dev) +{ + TRACE_AND_STOP; +} + +void drm_kms_helper_poll_enable(struct drm_device *dev) +{ + TRACE_AND_STOP; +} + +void drm_kms_helper_poll_fini(struct drm_device *dev) +{ + TRACE_AND_STOP; +} + +void drm_kms_helper_poll_init(struct drm_device *dev) +{ + TRACE_AND_STOP; +} + +void drm_mode_copy(struct drm_display_mode *dst, const struct drm_display_mode *src) +{ + TRACE_AND_STOP; +} + +void drm_mode_debug_printmodeline(const struct drm_display_mode *mode) +{ + TRACE_AND_STOP; +} + +struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev, const struct drm_display_mode *mode) +{ + TRACE_AND_STOP; + return NULL; +} + +bool drm_mode_equal(const struct drm_display_mode *mode1, const struct drm_display_mode *mode2) +{ + TRACE_AND_STOP; + return -1; +} + +void drm_mode_set_crtcinfo(struct drm_display_mode *p, int adjust_flags) +{ + TRACE_AND_STOP; +} + +int drm_noop(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + TRACE_AND_STOP; + return -1; +} + +int drm_open(struct inode *inode, struct file *filp) +{ + TRACE_AND_STOP; + return -1; +} + +drm_dma_handle_t *drm_pci_alloc(struct drm_device *dev, size_t size, size_t align) +{ + TRACE_AND_STOP; + return NULL; +} + +void drm_pci_free(struct drm_device *dev, drm_dma_handle_t * dmah) +{ + TRACE_AND_STOP; +} + +unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait) +{ + TRACE_AND_STOP; + return -1; +} + +void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg) +{ + TRACE_AND_STOP; +} + +void drm_put_dev(struct drm_device *dev) +{ + TRACE_AND_STOP; +} + +ssize_t drm_read(struct file *filp, char __user *buffer, size_t count, loff_t *offset) +{ + TRACE_AND_STOP; + return -1; +} + +int drm_release(struct inode *inode, struct file *filp) +{ + TRACE_AND_STOP; + return -1; +} + +void drm_send_vblank_event(struct drm_device *dev, int crtc, struct drm_pending_vblank_event *e) +{ + TRACE_AND_STOP; +} + +int drm_sysfs_connector_add(struct drm_connector *connector) +{ + TRACE_AND_STOP; + return -1; +} + +void drm_sysfs_connector_remove(struct drm_connector *connector) +{ + TRACE_AND_STOP; +} + +void drm_vblank_cleanup(struct drm_device *dev) +{ + TRACE_AND_STOP; +} + +int drm_vblank_get(struct drm_device *dev, int crtc) +{ + TRACE_AND_STOP; + return -1; +} + +void drm_vblank_off(struct drm_device *dev, int crtc) +{ + TRACE_AND_STOP; +} + +void drm_vblank_post_modeset(struct drm_device *dev, int crtc) +{ + TRACE_AND_STOP; +} + +void drm_vblank_pre_modeset(struct drm_device *dev, int crtc) +{ + TRACE_AND_STOP; +} + +void drm_vblank_put(struct drm_device *dev, int crtc) +{ + TRACE_AND_STOP; +} + +bool drm_vma_node_has_offset(struct drm_vma_offset_node *node) +{ + TRACE_AND_STOP; + return -1; +} + +__u64 drm_vma_node_offset_addr(struct drm_vma_offset_node *node) +{ + TRACE_AND_STOP; + return -1; +} + +void drm_vma_node_unmap(struct drm_vma_offset_node *node, struct address_space *file_mapping) +{ + TRACE_AND_STOP; +} + +struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder) +{ + TRACE_AND_STOP; + return NULL; +} + +int fault_in_multipages_readable(const char __user *uaddr, int size) +{ + TRACE_AND_STOP; + return -1; +} + +int fault_in_multipages_writeable(char __user *uaddr, int size) +{ + TRACE_AND_STOP; + return -1; +} + +struct inode *file_inode(struct file *f) +{ + TRACE_AND_STOP; + return NULL; +} + +void flush_scheduled_work(void) +{ + TRACE_AND_STOP; +} + +void flush_workqueue(struct workqueue_struct *wq) +{ + TRACE_AND_STOP; +} + +void __free_pages(struct page *page, unsigned int order) +{ + TRACE_AND_STOP; +} + +void free_pages(unsigned long addr, unsigned int order) +{ + TRACE_AND_STOP; +} + +void gen6_rps_boost(struct drm_i915_private *dev_priv) +{ + TRACE_AND_STOP; +} + +void gen6_rps_idle(struct drm_i915_private *dev_priv) +{ + TRACE_AND_STOP; +} + +void gen6_set_rps(struct drm_device *dev, u8 val) +{ + TRACE_AND_STOP; +} + +void gen6_update_ring_freq(struct drm_device *dev) +{ + TRACE_AND_STOP; +} + +unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order) +{ + TRACE_AND_STOP; + return -1; +} + +void getrawmonotonic(struct timespec *ts) +{ + TRACE_AND_STOP; +} + +unsigned long get_seconds(void) +{ + TRACE_AND_STOP; + return -1; +} + +void i915_capture_error_state(struct drm_device *dev) +{ + TRACE_AND_STOP; +} + +void i915_destroy_error_state(struct drm_device *dev) +{ + TRACE_AND_STOP; +} + +void i915_gem_context_close(struct drm_device *dev, struct drm_file *file) +{ + TRACE_AND_STOP; +} + +int i915_gem_context_create_ioctl(struct drm_device *dev, void *data, struct drm_file *file) +{ + TRACE_AND_STOP; + return -1; +} + +int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data, struct drm_file *file) +{ + TRACE_AND_STOP; + return -1; +} + +void i915_gem_context_fini(struct drm_device *dev) +{ + TRACE_AND_STOP; +} + +void i915_gem_context_free(struct kref *ctx_ref) +{ + TRACE_AND_STOP; +} + +int __must_check i915_gem_context_init(struct drm_device *dev) +{ + TRACE_AND_STOP; + return -1; +} + +int i915_gem_evict_everything(struct drm_device *dev) +{ + TRACE_AND_STOP; + return -1; +} + +int __must_check i915_gem_evict_something(struct drm_device *dev, struct i915_address_space *vm, int min_size, unsigned alignment, unsigned cache_level, bool mappable, bool nonblock) +{ + TRACE_AND_STOP; + return -1; +} + +void i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj) +{ + TRACE_AND_STOP; +} + +void i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj) +{ + TRACE_AND_STOP; +} + +struct dma_buf *i915_gem_prime_export(struct drm_device *dev, struct drm_gem_object *gem_obj, int flags) +{ + TRACE_AND_STOP; + return NULL; +} + +struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev, struct dma_buf *dma_buf) +{ + TRACE_AND_STOP; + return NULL; +} + +void i915_get_extra_instdone(struct drm_device *dev, uint32_t *instdone) +{ + TRACE_AND_STOP; +} + +int i915_restore_state(struct drm_device *dev) +{ + TRACE_AND_STOP; + return -1; +} + +int i915_save_state(struct drm_device *dev) +{ + TRACE_AND_STOP; + return -1; +} + +void i915_setup_sysfs(struct drm_device *dev_priv) +{ + TRACE_AND_STOP; +} + +int i915_switch_context(struct intel_ring_buffer *ring, struct drm_file *file, int to_id) +{ + TRACE_AND_STOP; + return -1; +} + +void i915_teardown_sysfs(struct drm_device *dev_priv) +{ + TRACE_AND_STOP; +} + +void i915_update_gfx_val(struct drm_i915_private *dev_priv) +{ + TRACE_AND_STOP; +} + +void ilk_wm_get_hw_state(struct drm_device *dev) +{ + TRACE_AND_STOP; +} + +void intel_attach_broadcast_rgb_property(struct drm_connector *connector) +{ + TRACE_AND_STOP; +} + +void intel_attach_force_audio_property(struct drm_connector *connector) +{ + TRACE_AND_STOP; +} + +void intel_aux_display_runtime_get(struct drm_i915_private *dev_priv) +{ + TRACE_AND_STOP; +} + +void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv) +{ + TRACE_AND_STOP; +} + +void intel_cleanup_overlay(struct drm_device *dev) +{ + TRACE_AND_STOP; +} + +void intel_cleanup_ring_buffer(struct intel_ring_buffer *ring) +{ + TRACE_AND_STOP; +} + +int intel_connector_update_modes(struct drm_connector *connector, struct edid *edid) +{ + TRACE_AND_STOP; + return -1; +} + +void intel_crt_init(struct drm_device *dev) +{ + TRACE_AND_STOP; +} + +int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter) +{ + TRACE_AND_STOP; + return -1; +} + +void intel_disable_fbc(struct drm_device *dev) +{ + TRACE_AND_STOP; +} + +bool intel_display_power_enabled(struct drm_device *dev, enum intel_display_power_domain domain) +{ + TRACE_AND_STOP; + return -1; +} + +void intel_display_power_get(struct drm_device *dev, enum intel_display_power_domain domain) +{ + TRACE_AND_STOP; +} + +void intel_display_power_put(struct drm_device *dev, enum intel_display_power_domain domain) +{ + TRACE_AND_STOP; +} + +bool intel_dsi_init(struct drm_device *dev) +{ + TRACE_AND_STOP; + return -1; +} + +void intel_dvo_init(struct drm_device *dev) +{ + TRACE_AND_STOP; +} + +void intel_enable_gt_powersave(struct drm_device *dev) +{ + TRACE_AND_STOP; +} + +void intel_fini_runtime_pm(struct drm_i915_private *dev_priv) +{ + TRACE_AND_STOP; +} + +void intel_gpu_ips_init(struct drm_i915_private *dev_priv) +{ + TRACE_AND_STOP; +} + +void intel_gpu_ips_teardown(void) +{ + TRACE_AND_STOP; +} + +bool intel_hdmi_compute_config(struct intel_encoder *encoder, struct intel_crtc_config *pipe_config) +{ + TRACE_AND_STOP; + return -1; +} + +void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port) +{ + TRACE_AND_STOP; +} + +void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, struct intel_connector *intel_connector) +{ + TRACE_AND_STOP; +} + +int intel_init_blt_ring_buffer(struct drm_device *dev) +{ + TRACE_AND_STOP; + return -1; +} + +int intel_init_bsd_ring_buffer(struct drm_device *dev) +{ + TRACE_AND_STOP; + return -1; +} + +void intel_init_clock_gating(struct drm_device *dev) +{ + TRACE_AND_STOP; +} + +int intel_init_render_ring_buffer(struct drm_device *dev) +{ + TRACE_AND_STOP; + return -1; +} + +void intel_init_runtime_pm(struct drm_i915_private *dev_priv) +{ + TRACE_AND_STOP; +} + +int intel_init_vebox_ring_buffer(struct drm_device *dev) +{ + TRACE_AND_STOP; + return -1; +} + +int intel_overlay_switch_off(struct intel_overlay *overlay) +{ + TRACE_AND_STOP; + return -1; +} + +void intel_plane_disable(struct drm_plane *plane) +{ + TRACE_AND_STOP; +} + +void intel_plane_restore(struct drm_plane *plane) +{ + TRACE_AND_STOP; +} + +void intel_power_domains_remove(struct drm_device *dev) +{ + TRACE_AND_STOP; +} + +int intel_render_ring_init_dri(struct drm_device *dev, u64 start, u32 size) +{ + TRACE_AND_STOP; + return -1; +} + +void __intel_ring_advance(struct intel_ring_buffer *ring) +{ + TRACE_AND_STOP; +} + +int __must_check intel_ring_begin(struct intel_ring_buffer *ring, int n) +{ + TRACE_AND_STOP; + return -1; +} + +int __must_check intel_ring_cacheline_align(struct intel_ring_buffer *ring) +{ + TRACE_AND_STOP; + return -1; +} + +int intel_ring_flush_all_caches(struct intel_ring_buffer *ring) +{ + TRACE_AND_STOP; + return -1; +} + +u32 intel_ring_get_active_head(struct intel_ring_buffer *ring) +{ + TRACE_AND_STOP; + return -1; +} + +int __must_check intel_ring_idle(struct intel_ring_buffer *ring) +{ + TRACE_AND_STOP; + return -1; +} + +void intel_ring_init_seqno(struct intel_ring_buffer *ring, u32 seqno) +{ + TRACE_AND_STOP; +} + +void intel_ring_setup_status_page(struct intel_ring_buffer *ring) +{ + TRACE_AND_STOP; +} + +void intel_runtime_pm_get(struct drm_i915_private *dev_priv) +{ + TRACE_AND_STOP; +} + +void intel_runtime_pm_put(struct drm_i915_private *dev_priv) +{ + TRACE_AND_STOP; +} + +u32 intel_sbi_read(struct drm_i915_private *dev_priv, u16 reg, enum intel_sbi_destination destination) +{ + TRACE_AND_STOP; + return -1; +} + +void intel_sbi_write(struct drm_i915_private *dev_priv, u16 reg, u32 value, enum intel_sbi_destination destination) +{ + TRACE_AND_STOP; +} + +bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob) +{ + TRACE_AND_STOP; + return -1; +} + +void intel_setup_overlay(struct drm_device *dev) +{ + TRACE_AND_STOP; +} + +int intel_sprite_get_colorkey(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + TRACE_AND_STOP; + return -1; +} + +int intel_sprite_set_colorkey(struct drm_device *dev, void *data, struct drm_file *file_priv) +{ + TRACE_AND_STOP; + return -1; +} + +void intel_suspend_hw(struct drm_device *dev) +{ + TRACE_AND_STOP; +} + +void intel_tv_init(struct drm_device *dev) +{ + TRACE_AND_STOP; +} + +void intel_update_fbc(struct drm_device *dev) +{ + TRACE_AND_STOP; +} + +void intel_update_watermarks(struct drm_crtc *crtc) +{ + TRACE_AND_STOP; +} + +void io_mapping_free(struct io_mapping *mapping) +{ + TRACE_AND_STOP; +} + +void *io_mapping_map_atomic_wc(struct io_mapping *mapping, unsigned long offset) +{ + TRACE_AND_STOP; + return NULL; +} + +void io_mapping_unmap_atomic(void *vaddr) +{ + TRACE_AND_STOP; +} + +void io_schedule(void) +{ + TRACE_AND_STOP; +} + +void iounmap(volatile void *addr) +{ + TRACE_AND_STOP; +} + +bool ironlake_set_drps(struct drm_device *dev, u8 val) +{ + TRACE_AND_STOP; + return -1; +} + +void ironlake_teardown_rc6(struct drm_device *dev) +{ + TRACE_AND_STOP; +} + +void kmem_cache_destroy(struct kmem_cache *) +{ + TRACE_AND_STOP; +} + +void *kmem_cache_zalloc(struct kmem_cache *k, gfp_t flags) +{ + TRACE_AND_STOP; + return NULL; +} + +int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, char *envp[]) +{ + TRACE_AND_STOP; + return -1; +} + +void kref_get(struct kref *kref) +{ + TRACE_AND_STOP; +} + +int kref_put(struct kref *kref, void (*release) (struct kref *kref)) +{ + TRACE_AND_STOP; + return -1; +} + +gfp_t mapping_gfp_mask(struct address_space * mapping) +{ + TRACE_AND_STOP; + return -1; +} + +void mapping_set_gfp_mask(struct address_space *m, gfp_t mask) +{ + TRACE_AND_STOP; +} + +void mark_page_accessed(struct page *) +{ + TRACE_AND_STOP; +} + +int memcmp(const void *, const void *, size_t) +{ + TRACE_AND_STOP; + return -1; +} + +void *memset_io(void *s, int c, size_t n) +{ + TRACE_AND_STOP; + return NULL; +} + +loff_t noop_llseek(struct file *file, loff_t offset, int whence) +{ + TRACE_AND_STOP; + return -1; +} + +dma_addr_t page_to_pfn(struct page *page) +{ + TRACE_AND_STOP; + return -1; +} + +resource_size_t pcibios_align_resource(void *, const struct resource *, resource_size_t, resource_size_t) +{ + TRACE_AND_STOP; + return -1; +} + +void pci_disable_device(struct pci_dev *dev) +{ + TRACE_AND_STOP; +} + +void pci_disable_msi(struct pci_dev *dev) +{ + TRACE_AND_STOP; +} + +int pci_dma_mapping_error(struct pci_dev *pdev, dma_addr_t dma_addr) +{ + TRACE_AND_STOP; + return -1; +} + +int pci_enable_device(struct pci_dev *dev) +{ + TRACE_AND_STOP; + return -1; +} + +struct pci_dev *pci_get_device(unsigned int vendor, unsigned int device, struct pci_dev *from) +{ + TRACE_AND_STOP; + return NULL; +} + +void *pci_get_drvdata(struct pci_dev *pdev) +{ + TRACE_AND_STOP; + return NULL; +} + +void pci_iounmap(struct pci_dev *dev, void __iomem *p) +{ + TRACE_AND_STOP; +} + +dma_addr_t pci_map_page(struct pci_dev *hwdev, struct page *page, unsigned long offset, size_t size, int direction) +{ + TRACE_AND_STOP; + return -1; +} + +int pci_save_state(struct pci_dev *dev) +{ + TRACE_AND_STOP; + return -1; +} + +int pci_set_power_state(struct pci_dev *dev, pci_power_t state) +{ + TRACE_AND_STOP; + return -1; +} + +void pci_unmap_page(struct pci_dev *hwdev, dma_addr_t dma_address, size_t size, int direction) +{ + TRACE_AND_STOP; +} + +void pm_qos_remove_request(struct pm_qos_request *req) +{ + TRACE_AND_STOP; +} + +void pm_qos_update_request(struct pm_qos_request *req, s32 new_value) +{ + TRACE_AND_STOP; +} + +void put_page(struct page *page) +{ + TRACE_AND_STOP; +} + +bool queue_delayed_work(struct workqueue_struct *, struct delayed_work *, unsigned long) +{ + TRACE_AND_STOP; + return -1; +} + +bool queue_work(struct workqueue_struct *wq, struct work_struct *work) +{ + TRACE_AND_STOP; + return -1; +} + +int release_resource(struct resource *r) +{ + TRACE_AND_STOP; + return -1; +} + +void remove_wait_queue(wait_queue_head_t *, wait_queue_t *) +{ + TRACE_AND_STOP; +} + +int request_resource(struct resource *root, struct resource *) +{ + TRACE_AND_STOP; + return -1; +} + +unsigned long round_jiffies_up(unsigned long j) +{ + TRACE_AND_STOP; + return -1; +} + +unsigned long round_jiffies_up_relative(unsigned long j) +{ + TRACE_AND_STOP; + return -1; +} + +int sandybridge_pcode_write(struct drm_i915_private *dev_priv, u8 mbox, u32 val) +{ + TRACE_AND_STOP; + return -1; +} + +int schedule_delayed_work(struct delayed_work *work, unsigned long delay) +{ + TRACE_AND_STOP; + return -1; +} + +int schedule_work(struct work_struct *work) +{ + TRACE_AND_STOP; + return -1; +} + +void __set_current_state(int state) +{ + TRACE_AND_STOP; +} + +void set_normalized_timespec(struct timespec *ts, time_t sec, s64 nsec) +{ + TRACE_AND_STOP; +} + +int set_page_dirty(struct page *page) +{ + TRACE_AND_STOP; + return -1; +} + +int set_pages_wb(struct page *page, int numpages) +{ + TRACE_AND_STOP; + return -1; +} + +int sg_alloc_table(struct sg_table *, unsigned int, gfp_t) +{ + TRACE_AND_STOP; + return -1; +} + +void sg_free_table(struct sg_table *) +{ + TRACE_AND_STOP; +} + +void sg_mark_end(struct scatterlist *sg) +{ + TRACE_AND_STOP; +} + +struct scatterlist *sg_next(struct scatterlist *) +{ + TRACE_AND_STOP; + return NULL; +} + +dma_addr_t sg_page_iter_dma_address(struct sg_page_iter *piter) +{ + TRACE_AND_STOP; + return -1; +} + +bool __sg_page_iter_next(struct sg_page_iter *piter) +{ + TRACE_AND_STOP; + return -1; +} + +struct page *sg_page_iter_page(struct sg_page_iter *piter) +{ + TRACE_AND_STOP; + return NULL; +} + +void __sg_page_iter_start(struct sg_page_iter *piter, struct scatterlist *sglist, unsigned int nents, unsigned long pgoffset) +{ + TRACE_AND_STOP; +} + +void sg_set_page(struct scatterlist *sg, struct page *page, unsigned int len, unsigned int offset) +{ + TRACE_AND_STOP; +} + +struct page *shmem_read_mapping_page( struct address_space *mapping, pgoff_t index) +{ + TRACE_AND_STOP; + return NULL; +} + +struct page *shmem_read_mapping_page_gfp(struct address_space *mapping, pgoff_t index, gfp_t gfp_mask) +{ + TRACE_AND_STOP; + return NULL; +} + +void shmem_truncate_range(struct inode *inode, loff_t start, loff_t end) +{ + TRACE_AND_STOP; +} + +int signal_pending(struct task_struct *p) +{ + TRACE_AND_STOP; + return -1; +} + +void spin_lock(spinlock_t *lock) +{ + TRACE_AND_STOP; +} + +void spin_lock_irq(spinlock_t *lock) +{ + TRACE_AND_STOP; +} + +void spin_unlock_irq(spinlock_t *lock) +{ + TRACE_AND_STOP; +} + +unsigned long timespec_to_jiffies(const struct timespec *value) +{ + TRACE_AND_STOP; + return -1; +} + +s64 timespec_to_ns(const struct timespec *ts) +{ + TRACE_AND_STOP; + return -1; +} + +bool timespec_valid(const struct timespec *ts) +{ + TRACE_AND_STOP; + return -1; +} + +void unregister_shrinker(struct shrinker *) +{ + TRACE_AND_STOP; +} + +void usleep_range(unsigned long min, unsigned long max) +{ + TRACE_AND_STOP; +} + +void valleyview_set_rps(struct drm_device *dev, u8 val) +{ + TRACE_AND_STOP; +} + +int vga_switcheroo_process_delayed_switch(void) +{ + TRACE_AND_STOP; + return -1; +} + +void vga_switcheroo_unregister_client(struct pci_dev *dev) +{ + TRACE_AND_STOP; +} + +phys_addr_t virt_to_phys(volatile void *address) +{ + TRACE_AND_STOP; + return -1; +} + +u32 vlv_bunit_read(struct drm_i915_private *dev_priv, u32 reg) +{ + TRACE_AND_STOP; + return -1; +} + +void vlv_bunit_write(struct drm_i915_private *dev_priv, u32 reg, u32 val) +{ + TRACE_AND_STOP; +} + +u32 vlv_cck_read(struct drm_i915_private *dev_priv, u32 reg) +{ + TRACE_AND_STOP; + return -1; +} + +void vlv_cck_write(struct drm_i915_private *dev_priv, u32 reg, u32 val) +{ + TRACE_AND_STOP; +} + +u32 vlv_dpio_read(struct drm_i915_private *dev_priv, enum pipe pipe, int reg) +{ + TRACE_AND_STOP; + return -1; +} + +void vlv_dpio_write(struct drm_i915_private *dev_priv, enum pipe pipe, int reg, u32 val) +{ + TRACE_AND_STOP; +} + +u32 vlv_punit_read(struct drm_i915_private *dev_priv, u8 addr) +{ + TRACE_AND_STOP; + return -1; +} + +void vlv_punit_write(struct drm_i915_private *dev_priv, u8 addr, u32 val) +{ + TRACE_AND_STOP; +} + +int vm_insert_pfn(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn) +{ + TRACE_AND_STOP; + return -1; +} + +unsigned long vm_mmap(struct file *, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) +{ + TRACE_AND_STOP; + return -1; +} + +int wake_up_process(struct task_struct *tsk) +{ + TRACE_AND_STOP; + return -1; +} + +void wbinvd_on_all_cpus() +{ + TRACE_AND_STOP; +} + +void ida_remove(struct ida *ida, int id) +{ + TRACE_AND_STOP; +} + +void idr_destroy(struct idr *idp) +{ + TRACE_AND_STOP; +} + +void *idr_find(struct idr *idr, int id) +{ + TRACE_AND_STOP; + return NULL; +} + +void idr_remove(struct idr *idp, int id) +{ + TRACE_AND_STOP; +} + +void kref_init(struct kref *kref) +{ + TRACE_AND_STOP; +} + +int acpi_lid_notifier_unregister(struct notifier_block *nb) +{ + TRACE_AND_STOP; + return -1; +} + +int acpi_lid_open(void) +{ + TRACE_AND_STOP; + return -1; +} + +void drm_mode_set_name(struct drm_display_mode *mode) +{ + TRACE_AND_STOP; +} + +int acpi_lid_notifier_register(struct notifier_block *nb) +{ + TRACE_AND_STOP; + return -1; +} +struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, int hdisplay, int vdisplay, int vrefresh, bool reduced, bool interlaced, bool margins) +{ + TRACE_AND_STOP; + return NULL; +} + +struct drm_display_mode *drm_gtf_mode(struct drm_device *dev, int hdisplay, int vdisplay, int vrefresh, bool interlaced, int margins) +{ + TRACE_AND_STOP; + return NULL; +} + +struct drm_display_mode *drm_gtf_mode_complex(struct drm_device *dev, int hdisplay, int vdisplay, int vrefresh, bool interlaced, int margins, int GTF_M, int GTF_2C, int GTF_K, int GTF_2J) +{ + TRACE_AND_STOP; + return NULL; +} + +bool drm_mode_equal_no_clocks_no_stereo(const struct drm_display_mode *mode1, const struct drm_display_mode *mode2) +{ + TRACE_AND_STOP; + return -1; +} + +int drm_mode_hsync(const struct drm_display_mode *mode) +{ + TRACE_AND_STOP; + return -1; +} + +int drm_mode_vrefresh(const struct drm_display_mode *mode) +{ + TRACE_AND_STOP; + return -1; +} + +void *memchr_inv(const void *s, int c, size_t n) +{ + TRACE_AND_STOP; + return NULL; +} + +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_AND_STOP; +} + +int strncmp(const char *cs, const char *ct, size_t count) +{ + TRACE_AND_STOP; + return -1; +} + +int acpi_device_uevent_modalias(struct device *, struct kobj_uevent_env *) +{ + TRACE_AND_STOP; + return -1; +} + +int acpi_dev_pm_attach(struct device *dev, bool power_on) +{ + TRACE_AND_STOP; + return -1; +} + +void acpi_dev_pm_detach(struct device *dev, bool power_off) +{ + TRACE_AND_STOP; +} + +bool acpi_driver_match_device(struct device *dev, const struct device_driver *drv) +{ + TRACE_AND_STOP; + return -1; +} + +int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...) +{ + TRACE_AND_STOP; + return -1; +} + +int bus_for_each_drv(struct bus_type *bus, struct device_driver *start, void *data, int (*fn)(struct device_driver *, void *)) +{ + TRACE_AND_STOP; + return -1; +} + +bool device_can_wakeup(struct device *dev) +{ + TRACE_AND_STOP; + return -1; +} + +int device_for_each_child(struct device *dev, void *data, int (*fn)(struct device *dev, void *data)) +{ + TRACE_AND_STOP; + return -1; +} + +int device_init_wakeup(struct device *dev, bool val) +{ + TRACE_AND_STOP; + return -1; +} + +const char *dev_name(const struct device *dev) +{ + TRACE_AND_STOP; + return NULL; +} + +void gpio_free(unsigned gpio) +{ + TRACE_AND_STOP; +} + +int gpio_get_value(unsigned int gpio) +{ + TRACE_AND_STOP; + return -1; +} + +bool gpio_is_valid(int number) +{ + TRACE_AND_STOP; + return -1; +} + +int gpio_request_one(unsigned gpio, unsigned long flags, const char *label) +{ + TRACE_AND_STOP; + return -1; +} + +void gpio_set_value(unsigned int gpio, int value) +{ + TRACE_AND_STOP; +} + +bool in_atomic() +{ + TRACE_AND_STOP; + return -1; +} + +bool irqs_disabled() +{ + TRACE_AND_STOP; + return -1; +} + +void ndelay(unsigned long) +{ + TRACE_AND_STOP; +} + +int of_alias_get_id(struct device_node *np, const char *stem) +{ + TRACE_AND_STOP; + return -1; +} + +int of_driver_match_device(struct device *dev, const struct device_driver *drv) +{ + TRACE_AND_STOP; + return -1; +} + +void rt_mutex_lock(struct rt_mutex *lock) +{ + TRACE_AND_STOP; +} + +int rt_mutex_trylock(struct rt_mutex *lock) +{ + TRACE_AND_STOP; + return -1; +} + +void rt_mutex_unlock(struct rt_mutex *lock) +{ + TRACE_AND_STOP; +} + +int strcmp(const char *s1, const char *s2) +{ + TRACE_AND_STOP; + return -1; +} + +size_t strlcpy(char *dest, const char *src, size_t size) +{ + TRACE_AND_STOP; + return -1; +} + +void up_read(struct rw_semaphore *sem) +{ + TRACE_AND_STOP; +} + +void wait_for_completion(struct completion *work) +{ + TRACE_AND_STOP; +} + +void bus_unregister(struct bus_type *bus) +{ + TRACE_AND_STOP; +} + + diff --git a/repos/dde_linux/src/drivers/framebuffer/intel/gen_dummy b/repos/dde_linux/src/drivers/framebuffer/intel/gen_dummy new file mode 100755 index 000000000..6084c730b --- /dev/null +++ b/repos/dde_linux/src/drivers/framebuffer/intel/gen_dummy @@ -0,0 +1,99 @@ +#!/usr/bin/tclsh + +# +# \brief Private utility to generate a dummy function from a symbol name +# \date 2015-08-21 +# \author Norman Feske +# +# The script must be executed in its directory and takes a symbol name as last +# argument. It searches the following places for a declaration that corresponds +# to the specified symbol: +# +# - the local include/ directory +# - the dde_linux/src/include/lx_emul/ directory +# - the contrib/dde_linux-/src/drivers/framebuffer/intel directory +# +# If a declaration could be found, the script generates a dummy implementation +# with the signature of the declarated function. +# + +set symbol $argv + +# determine contrib directory of dde_linux +set lx_drv_path [exec ../../../../../../tool/ports/current dde_linux] +append lx_drv_path "/src/drivers/framebuffer/intel" + +# grep for lines that contain the symbol and have with no leading whitespace +if {[catch { +set header [exec grep -rl "^\\w.*$symbol\\>" include ../../../include/lx_emul $lx_drv_path | grep -v "~"] +}]} { + puts stderr "failed to lookup symbol $symbol" + exit 1 +} + +if {[llength $header] != 1} { + puts stderr "cannot generate dummy for symbol $symbol" + exit 1 +} + +puts stderr "found declaration of $symbol in $header" + +set statements [split [exec cat $header] ";{}"] + +foreach statement $statements { + + # strip off comments and preprocessor commands + regsub -all {/\*.*?\*/} $statement "" statement + regsub -all {//.*?\n} $statement "" statement + regsub -all {#.*?\n} $statement "\n" statement + + # delete consecutive newlines + while {[regexp {\n\n} $statement dummy]} { + regsub -all {\n\n} $statement "\n" statement + } + + # function declarations have no leading tabs + if {[regexp {^\t} $statement dummy]} continue + + # skip statements where the symbol does not occur + if {![regexp "$symbol\\(" $statement dummy]} continue + + # strip leading whitespace (linefeed) + regsub {^\s*} $statement "" statement + + # strip leading extern keyword + regsub {^extern\s*} $statement "" statement + + # strip leading inline keyword + regsub {^inline\s*} $statement "" statement + + # merge multi-line parameter list into a single line + regsub -all {\s*\n\s*} $statement " " statement + + # strip function attributes starting with '__' + regsub -all {\)\s*__.*} $statement ")" statement + + # determine return type 'ret' of the function + regexp {^[^\(]*} $statement func_ret + regsub {\s[^\s\*]*$} $func_ret "" ret + + # output function definition + puts "$statement" + puts "{" + puts "\tTRACE_AND_STOP;" + if {[regexp {\*} $ret]} { + # function returns a pointer + puts "\treturn NULL;" + } elseif {[regexp {void} $ret dummy]} { + # void function + } else { + # function with return value + puts "\treturn -1;" + } + puts "}\n" + + # success + exit 0 +} + +puts stderr "failed to match declaration of $symbol in $header" diff --git a/repos/dde_linux/src/drivers/framebuffer/intel/i2c-algo-bit.c b/repos/dde_linux/src/drivers/framebuffer/intel/i2c-algo-bit.c new file mode 100644 index 000000000..58e373e00 --- /dev/null +++ b/repos/dde_linux/src/drivers/framebuffer/intel/i2c-algo-bit.c @@ -0,0 +1,31 @@ +/* + * \brief Definition of the global 'i2c_bit_algo' struct + * \author Norman Feske + * \date 2015-09-11 + * + * The 'i2c_bit_algo' struct must be defined in a C file because we cannot + * use C-style struct initializers in C++ code. + */ + +#include + +int i2c_algo_bit_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num) +{ + lx_printf("i2c_algo_bit_xfer called - not implemented\n"); + for (;;); + return -1; +} + + +u32 i2c_algo_bit_func(struct i2c_adapter *adap) +{ + lx_printf("i2c_algo_bit_func called - not implemented\n"); + return 0; +} + + +const struct i2c_algorithm i2c_bit_algo = { + .master_xfer = i2c_algo_bit_xfer, + .functionality = i2c_algo_bit_func, +}; + diff --git a/repos/dde_linux/src/drivers/framebuffer/intel/include/drm/drmP.h b/repos/dde_linux/src/drivers/framebuffer/intel/include/drm/drmP.h new file mode 100644 index 000000000..79086b835 --- /dev/null +++ b/repos/dde_linux/src/drivers/framebuffer/intel/include/drm/drmP.h @@ -0,0 +1,684 @@ +/* + * \brief Platform interface of DRM code + * \author Norman Feske + * \date 2015-08-19 + */ + +#ifndef _DRMP_H_ +#define _DRMP_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* local includes */ +#include + +/* + * Unfortunately, DRM headers use certain C++ keywords as variable names. + * To enable the inclusion of 'drmP.h' from C++ source codes, we have to + * rename these identifiers. + */ +#ifdef __cplusplus +#define new _new +#define virtual _virtual +#define private _private +#endif /* __cplusplus */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifdef __cplusplus +#undef virtual +#undef new +#undef private +#endif /* __cplusplus */ + +extern unsigned int drm_debug; + + +/******************* + ** DRM constants ** + *******************/ + +enum { + DRM_MINOR_CONTROL = 2, +// DRM_MINOR_RENDER = 3, +// DRM_MAGIC_HASH_ORDER = 4, +}; + +enum { + DRM_AUTH = 0x1, + DRM_MASTER = 0x2, + DRM_ROOT_ONLY = 0x4, + DRM_CONTROL_ALLOW = 0x8, + DRM_UNLOCKED = 0x10, + DRM_RENDER_ALLOW = 0x20, +}; + +enum { + DRIVER_USE_AGP = 0x1, + DRIVER_REQUIRE_AGP = 0x2, + DRIVER_HAVE_IRQ = 0x40, + DRIVER_IRQ_SHARED = 0x80, + DRIVER_GEM = 0x1000, + DRIVER_MODESET = 0x2000, + DRIVER_PRIME = 0x4000, + DRIVER_RENDER = 0x8000, +}; + +//enum { DRM_HZ = HZ }; + +enum { + DRM_SCANOUTPOS_VALID = (1 << 0), + DRM_SCANOUTPOS_INVBL = (1 << 1), + DRM_SCANOUTPOS_ACCURATE = (1 << 2), +}; + +enum { DRM_CALLED_FROM_VBLIRQ = 1 }; + +//enum { +// DRM_CONNECTOR_POLL_HPD = 1 << 0, +// DRM_CONNECTOR_POLL_CONNECT = 1 << 1, +// DRM_CONNECTOR_POLL_DISCONNECT = 1 << 2, +//}; + + +/**************** + ** DRM macros ** + ****************/ + +#define obj_to_crtc(x) container_of(x, struct drm_crtc, base) + +///* +// * Type and function mappings +// */ +//#define DRM_IRQ_ARGS void *arg +//#define DRM_ARRAY_SIZE ARRAY_SIZE +//#define DRM_WAKEUP wake_up +//#define DRM_INIT_WAITQUEUE init_waitqueue_head +//#define DRM_AGP_KERN struct agp_kern_info +//#define DRM_AGP_MEM struct agp_memory +//#define DRM_COPY_TO_USER copy_to_user +// +///* +// * Debug macros +// */ +#define DRM_VERBOSE 1 + +#if DRM_VERBOSE +#define DRM_INFO(fmt, arg...) do { \ + lx_printfln("[" DRM_NAME ":%s] *INFO* " fmt , __func__ , ##arg); } while (0) + +#define DRM_ERROR(fmt, arg...) do { \ + lx_printfln("[" DRM_NAME ":%s] *ERROR* " fmt , __func__ , ##arg); } while (0) + +#define DRM_DEBUG(fmt, arg...) do { \ + lx_printfln("[" DRM_NAME ":%s] *DEBUG* " fmt , __func__ , ##arg); } while (0) + +#define DRM_DEBUG_DRIVER(fmt, arg...) do { \ + lx_printfln("[" DRM_NAME ":%s] *DRIVER* " fmt , __func__ , ##arg); } while (0) + +#define DRM_DEBUG_KMS(fmt, arg...) do { \ + lx_printfln("[" DRM_NAME ":%s] *KMS* " fmt , __func__ , ##arg); } while (0) +#else +#define DRM_INFO(fmt, arg...) do { } while (0) +#define DRM_ERROR(fmt, arg...) do { } while (0) +#define DRM_DEBUG(fmt, arg...) do { } while (0) +#define DRM_DEBUG_DRIVER(fmt, arg...) do { } while (0) +#define DRM_DEBUG_KMS(fmt, arg...) do { } while (0) +#endif + +#define DRM_ARRAY_SIZE(x) ARRAY_SIZE(x) + +#define DRM_UT_KMS 0x04 + + +///*************** +// ** DRM types ** +// ***************/ +// +///* +// * Forward type declarations +// */ +struct drm_device; +struct drm_mm_node; +struct drm_master; +struct drm_file; +struct drm_crtc; +struct drm_plane; +struct drm_display_mode; +struct drm_connector; +struct drm_mode_create_dumb; +struct drm_mode_fb_cmd2; + + +/** + * Ioctl handler function + */ +typedef int drm_ioctl_t(struct drm_device *dev, void *data, + struct drm_file *file_priv); + +/** + * Ioctl representation + */ +struct drm_ioctl_desc { + unsigned int cmd; + int flags; + drm_ioctl_t *func; + unsigned int cmd_drv; + const char *name; +}; + +#define DRM_IOCTL_NR(n) (n & 0xff) + +#define DRM_IOCTL_DEF_DRV(ioctl, _func, _flags) \ + [DRM_IOCTL_NR(DRM_##ioctl)] = {.cmd = DRM_##ioctl, .func = _func, .flags = _flags, .cmd_drv = DRM_IOCTL_##ioctl, .name = #ioctl} + +#if 0 +#define DRM_IOCTL_DEF(ioctl, _func, _flags) \ + [ioctl & 0xff] = {.cmd = ioctl, .func = _func, .flags = _flags} +#endif + + +struct drm_gem_object; + + +struct drm_driver { + u32 driver_features; + const struct vm_operations_struct *gem_vm_ops; + const struct drm_ioctl_desc *ioctls; + int num_ioctls; + const struct file_operations *fops; + int major; + int minor; + int patchlevel; + char *name; + char *desc; + char *date; + + int (*load) (struct drm_device *, unsigned long flags); + int (*unload) (struct drm_device *); + int (*open) (struct drm_device *, struct drm_file *); + void (*lastclose) (struct drm_device *); + void (*preclose) (struct drm_device *, struct drm_file *file_priv); + void (*postclose) (struct drm_device *, struct drm_file *); + + int (*suspend) (struct drm_device *, pm_message_t state); + int (*resume) (struct drm_device *); + + int (*device_is_agp) (struct drm_device *dev); + int (*master_create)(struct drm_device *dev, struct drm_master *master); + void (*master_destroy)(struct drm_device *dev, struct drm_master *master); + void (*gem_free_object) (struct drm_gem_object *obj); + + int (*prime_handle_to_fd)(struct drm_device *dev, struct drm_file *file_priv, + uint32_t handle, uint32_t flags, int *prime_fd); + int (*prime_fd_to_handle)(struct drm_device *dev, struct drm_file *file_priv, + int prime_fd, uint32_t *handle); + struct dma_buf * (*gem_prime_export)(struct drm_device *dev, + struct drm_gem_object *obj, int flags); + struct drm_gem_object * (*gem_prime_import)(struct drm_device *dev, + struct dma_buf *dma_buf); + + int (*dumb_create)(struct drm_file *file_priv, + struct drm_device *dev, + struct drm_mode_create_dumb *args); + int (*dumb_map_offset)(struct drm_file *file_priv, + struct drm_device *dev, uint32_t handle, + uint64_t *offset); + int (*dumb_destroy)(struct drm_file *file_priv, + struct drm_device *dev, + uint32_t handle); + int (*get_vblank_timestamp) (struct drm_device *dev, int crtc, + int *max_error, + struct timeval *vblank_time, + unsigned flags); + u32 (*get_vblank_counter) (struct drm_device *dev, int crtc); + int (*get_scanout_position) (struct drm_device *dev, int crtc, + unsigned int flags, + int *vpos, int *hpos, ktime_t *stime, + ktime_t *etime); + irqreturn_t(*irq_handler) (int irq, void *arg); + void (*irq_preinstall) (struct drm_device *dev); + int (*irq_postinstall) (struct drm_device *dev); + void (*irq_uninstall) (struct drm_device *dev); + int (*enable_vblank) (struct drm_device *dev, int crtc); + void (*disable_vblank) (struct drm_device *dev, int crtc); +}; + + +///* needed by drm_agpsupport.c */ +//struct drm_agp_mem { +// unsigned long handle; +// DRM_AGP_MEM *memory; +// unsigned long bound; +// int pages; +// struct list_head head; +//}; +// +//struct drm_agp_head { +// DRM_AGP_KERN agp_info; +// unsigned long base; +// +// /* +// * Members used by drm_agpsupport.c +// */ +// int acquired; +// struct agp_bridge_data *bridge; +// int enabled; +// unsigned long mode; +// struct list_head memory; +// int cant_use_aperture; +// unsigned long page_mask; +//}; + +#define DRM_SWITCH_POWER_ON 0 +#define DRM_SWITCH_POWER_OFF 1 +#define DRM_SWITCH_POWER_CHANGING 2 + +struct drm_i915_private; + +struct drm_device { +// int pci_device; + struct pci_dev *pdev; + struct mutex struct_mutex; + struct drm_driver *driver; + struct drm_i915_private *dev_private; +// struct drm_gem_mm *mm_private; +// enum drm_stat_type types[15]; +// unsigned long counters; + struct address_space *dev_mapping; + struct drm_agp_head *agp; + int irq_enabled; /* needed for i915_dma.c */ + spinlock_t count_lock; + struct drm_mode_config mode_config; + int open_count; + int vblank_disable_allowed; + u32 max_vblank_count; + struct drm_minor *primary; /* needed by i915_dma.c */ +// atomic_t object_count; +// atomic_t object_memory; +// atomic_t pin_count; +// atomic_t pin_memory; +// atomic_t gtt_count; +// atomic_t gtt_memory; +// uint32_t gtt_total; +// uint32_t invalidate_domains; +// uint32_t flush_domains; + int switch_power_state; + spinlock_t event_lock; + struct device *dev; /* i915_gem_stolen.c */ +}; + +// +//struct drm_map_list { +// struct drm_hash_item hash; +// struct drm_local_map *map; +// struct drm_mm_node *file_offset_node; +//}; + + +/*************************** + ** drm/drm_vma_manager.h ** + ***************************/ + +struct drm_vma_offset_node { + int dummy; +}; + + +struct drm_gem_object { + +// /** Related drm device */ + struct drm_device *dev; +// +// /** File representing the shmem storage */ + struct file *filp; +// +// /** +// * Size of the object, in bytes. Immutable over the object's +// * lifetime. +// */ + size_t size; +// +// /** +// * Global name for this object, starts at 1. 0 means unnamed. +// * Access is covered by the object_name_lock in the related drm_device +// */ +// int name; +// +// /* Mapping info for this object */ +// struct drm_map_list map_list; +// +// /** +// * Memory domains. These monitor which caches contain read/write data +// * related to the object. When transitioning from one set of domains +// * to another, the driver is called to ensure that caches are suitably +// * flushed and invalidated +// */ + uint32_t read_domains; + uint32_t write_domain; +// +// /** +// * While validating an exec operation, the +// * new read/write domain values are computed here. +// * They will be transferred to the above values +// * at the point that any cache flushing occurs +// */ +// uint32_t pending_read_domains; +// uint32_t pending_write_domain; +// +// void *driver_private; + struct drm_vma_offset_node vma_node; + struct dma_buf_attachment *import_attach; +}; + +typedef struct drm_dma_handle { + void *vaddr; + size_t size; + dma_addr_t busaddr; /* needed by i915_drv.h */ +} drm_dma_handle_t; + +typedef struct drm_local_map { + size_t offset; /* Requested physical address (0 for SAREA)*/ + unsigned long size; /* Requested physical size (bytes) */ +// enum drm_map_type type; /* Type of memory to map */ +// enum drm_map_flags flags; /* Flags */ + void *handle; /* User-space: "Handle" to pass to mmap() */ + /* Kernel-space: kernel-virtual address */ + int mtrr; /* MTRR slot used */ +} drm_local_map_t; + +//struct drm_gem_mm { +// struct drm_mm offset_manager; +// struct drm_open_hash offset_hash; +//}; +// +struct drm_lock_data { + struct drm_hw_lock *hw_lock; /* for i915_dma.c */ + struct drm_file *file_priv; /* for i915_dma.c */ +}; +// +struct drm_master { + struct drm_lock_data lock; /* needed for i915_dma.c */ + void *driver_priv; /* needed for i915_dma.c */ + struct drm_minor *minor; +}; + +struct drm_file { + void *driver_priv; + struct drm_minor *minor; /* needed for drm_agpsupport.c */ + struct drm_master *master; /* needed for i915_dma.c */ + struct list_head fbs; + struct mutex fbs_lock; + unsigned stereo_allowed :1; + unsigned is_master :1; /* this file private is a master for a minor */ + int event_space; +}; +// +///* +// * needed for drm_agpsupport.c +// */ +struct drm_minor { + struct device *kdev; /* needed by i915_irq.c */ + struct drm_device *dev; + struct drm_master *master; /* needed for i915_dma.c */ + int index; /**< Minor device number */ + struct drm_mode_group mode_group; + int type; /**< Control or render */ +}; +// +///* +// * needed for drm_crtc_helper.h, included by i915_dma.c +// */ +//struct drm_encoder { void *helper_private; }; +//struct drm_mode_set { }; + + +#define DRM_MODE_OBJECT_CRTC 0xcccccccc +//#define DRM_MODE_OBJECT_CONNECTOR 0xc0c0c0c0 +//#define DRM_MODE_OBJECT_ENCODER 0xe0e0e0e0 +#define DRM_MODE_OBJECT_MODE 0xdededede +//#define DRM_MODE_OBJECT_PROPERTY 0xb0b0b0b0 +//#define DRM_MODE_OBJECT_FB 0xfbfbfbfb +//#define DRM_MODE_OBJECT_BLOB 0xbbbbbbbb +//#define DRM_MODE_OBJECT_PLANE 0xeeeeeeee +//#define DRM_MODE_OBJECT_BRIDGE 0xbdbdbdbd + +#define DRM_MODE(nm, t, c, hd, hss, hse, ht, hsk, vd, vss, vse, vt, vs, f) \ + .name = nm, .status = 0, .type = (t), .clock = (c), \ + .hdisplay = (hd), .hsync_start = (hss), .hsync_end = (hse), \ + .htotal = (ht), .hskew = (hsk), .vdisplay = (vd), \ + .vsync_start = (vss), .vsync_end = (vse), .vtotal = (vt), \ + .vscan = (vs), .flags = (f), \ + .base.type = DRM_MODE_OBJECT_MODE + +#define CRTC_STEREO_DOUBLE (1 << 1) /* adjust timings for stereo modes */ + + +struct drm_pending_vblank_event; + + +struct drm_fb_helper { int dummy; }; + + +#include + + +/*************************** + ** drm/drm_crtc_helper.h ** + ***************************/ + +struct drm_pending_event { + struct drm_event *event; +// struct list_head link; + struct drm_file *file_priv; +// pid_t pid; /* pid of requester, no guarantee it's valid by the time +// we deliver the event, for tracing only */ + void (*destroy)(struct drm_pending_event *event); +}; + +struct drm_pending_vblank_event { + int dummy; + struct drm_pending_event base; +// int pipe; + struct drm_event_vblank event; +}; + + +/****************** + ** Misc helpers ** + ******************/ + +/* normally found in drm_os_linux.h */ +#define DRM_WAIT_ON( ret, queue, timeout, condition ) \ +do { \ + DECLARE_WAITQUEUE(entry, current); \ + unsigned long end = jiffies + (timeout); \ + add_wait_queue(&(queue), &entry); \ + \ + for (;;) { \ + __set_current_state(TASK_INTERRUPTIBLE); \ + if (condition) \ + break; \ + if (time_after_eq(jiffies, end)) { \ + ret = -EBUSY; \ + break; \ + } \ + schedule_timeout((HZ/100 > 1) ? HZ/100 : 1); \ + if (signal_pending(current)) { \ + ret = -EINTR; \ + break; \ + } \ + } \ + __set_current_state(TASK_RUNNING); \ + remove_wait_queue(&(queue), &entry); \ +} while (0) + + +/* normally found in Linux drmP.h */ +#define LOCK_TEST_WITH_RETURN( dev, _file_priv ) \ +do { \ + if (!_DRM_LOCK_IS_HELD(_file_priv->master->lock.hw_lock->lock) || \ + _file_priv->master->lock.file_priv != _file_priv) { \ + DRM_ERROR( "%s called without lock held, held %d owner %p %p\n",\ + __func__, _DRM_LOCK_IS_HELD(_file_priv->master->lock.hw_lock->lock),\ + _file_priv->master->lock.file_priv, _file_priv); \ + return -EINVAL; \ + } \ +} while (0) + + +static inline int drm_core_check_feature(struct drm_device *dev, int feature) { + return ((dev->driver->driver_features & feature) ? 1 : 0); } + +#if 0 + +static inline int drm_core_has_AGP(struct drm_device *dev) { + return drm_core_check_feature(dev, DRIVER_USE_AGP); } + +/* + * Functions normally provided by drm_bufs.c + */ +static inline resource_size_t +drm_get_resource_start(struct drm_device *dev, unsigned int rsc) { + return pci_resource_start(dev->pdev, rsc); } + +static inline resource_size_t +drm_get_resource_len(struct drm_device *dev, unsigned int rsc) { + return pci_resource_len(dev->pdev, rsc); } + +#endif + +static __inline__ bool drm_can_sleep(void) { return true; } + +extern void drm_pci_free(struct drm_device *dev, drm_dma_handle_t * dmah); +extern int drm_noop(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int drm_irq_install(struct drm_device *dev); +extern int drm_irq_uninstall(struct drm_device *dev); +extern struct drm_local_map *drm_getsarea(struct drm_device *dev); +extern int drm_vblank_init(struct drm_device *dev, int num_crtcs); +extern void drm_vblank_cleanup(struct drm_device *dev); +extern void drm_kms_helper_poll_disable(struct drm_device *dev); +extern void drm_kms_helper_poll_init(struct drm_device *dev); +extern void drm_mm_takedown(struct drm_mm *mm); +extern bool drm_helper_hpd_irq_event(struct drm_device *dev); +extern void drm_modeset_lock_all(struct drm_device *dev); +extern void drm_mode_config_reset(struct drm_device *dev); +extern void drm_modeset_unlock_all(struct drm_device *dev); +extern void drm_kms_helper_poll_enable(struct drm_device *dev); +extern int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent, struct drm_driver *driver); +extern void drm_put_dev(struct drm_device *dev); +extern void drm_gem_vm_open(struct vm_area_struct *vma); +extern void drm_gem_vm_close(struct vm_area_struct *vma); +extern int drm_open(struct inode *inode, struct file *filp); +extern int drm_release(struct inode *inode, struct file *filp); +extern int drm_mmap(struct file *filp, struct vm_area_struct *vma); +extern long drm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); +extern unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait); +extern ssize_t drm_read(struct file *filp, char __user *buffer, size_t count, loff_t *offset); +extern int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma); +extern int drm_gem_prime_handle_to_fd(struct drm_device *dev, struct drm_file *file_priv, uint32_t handle, uint32_t flags, int *prime_fd); +extern int drm_gem_prime_fd_to_handle(struct drm_device *dev, struct drm_file *file_priv, int prime_fd, uint32_t *handle); +extern int drm_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev, uint32_t handle); +extern int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver); +extern void drm_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver); +extern void drm_vblank_off(struct drm_device *dev, int crtc); +extern void drm_encoder_cleanup(struct drm_encoder *encoder); +extern void drm_vblank_pre_modeset(struct drm_device *dev, int crtc); +extern void drm_vblank_post_modeset(struct drm_device *dev, int crtc); +extern struct drm_connector *drm_select_eld(struct drm_encoder *encoder, struct drm_display_mode *mode); +extern int drm_av_sync_delay(struct drm_connector *connector, struct drm_display_mode *mode); +extern struct drm_gem_object *drm_gem_object_lookup(struct drm_device *dev, struct drm_file *filp, u32 handle); +extern void drm_gem_object_unreference(struct drm_gem_object *obj); +extern void drm_gem_object_unreference_unlocked(struct drm_gem_object *obj); +extern uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth); +extern void drm_framebuffer_unregister_private(struct drm_framebuffer *fb); +extern void drm_framebuffer_unreference(struct drm_framebuffer *fb); +extern void drm_mode_set_name(struct drm_display_mode *mode); +extern void drm_crtc_cleanup(struct drm_crtc *crtc); +extern void drm_send_vblank_event(struct drm_device *dev, int crtc, struct drm_pending_vblank_event *e); +extern void drm_vblank_put(struct drm_device *dev, int crtc); +extern int drm_vblank_get(struct drm_device *dev, int crtc); +extern void drm_gem_object_reference(struct drm_gem_object *obj); +extern void drm_mode_debug_printmodeline(const struct drm_display_mode *mode); +extern void drm_mode_copy(struct drm_display_mode *dst, const struct drm_display_mode *src); +extern void drm_mode_set_crtcinfo(struct drm_display_mode *p, int adjust_flags); +extern int drm_object_property_set_value(struct drm_mode_object *obj, struct drm_property *property, uint64_t val); +extern void drm_calc_timestamping_constants(struct drm_crtc *crtc, const struct drm_display_mode *mode); +extern bool drm_mode_equal(const struct drm_display_mode *mode1, const struct drm_display_mode *mode2); +extern bool drm_encoder_crtc_ok(struct drm_encoder *encoder, struct drm_crtc *crtc); +extern int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc, int gamma_size); +extern void drm_crtc_helper_add(struct drm_crtc *crtc, const struct drm_crtc_helper_funcs *funcs); +extern struct drm_mode_object *drm_mode_object_find(struct drm_device *dev, uint32_t id, uint32_t type); +extern void drm_helper_move_panel_connectors_to_head(struct drm_device *); +extern void drm_framebuffer_cleanup(struct drm_framebuffer *fb); +extern int drm_gem_handle_create(struct drm_file *file_priv, struct drm_gem_object *obj, u32 *handlep); +extern int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb, struct drm_mode_fb_cmd2 *mode_cmd); +extern int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb, const struct drm_framebuffer_funcs *funcs); +extern void drm_mode_config_init(struct drm_device *dev); +extern void drm_kms_helper_poll_fini(struct drm_device *dev); +extern void drm_sysfs_connector_remove(struct drm_connector *connector); +extern void drm_mode_config_cleanup(struct drm_device *dev); +extern int drm_mode_connector_attach_encoder(struct drm_connector *connector, struct drm_encoder *encoder); +extern bool drm_dp_enhanced_frame_cap(const u8 dpcd[DP_RECEIVER_CAP_SIZE]); +extern int drm_encoder_init(struct drm_device *dev, struct drm_encoder *encoder, const struct drm_encoder_funcs *funcs, int encoder_type); +extern int drm_dp_bw_code_to_link_rate(u8 link_bw); +extern u8 drm_dp_max_lane_count(const u8 dpcd[DP_RECEIVER_CAP_SIZE]); +extern u8 drm_match_cea_mode(const struct drm_display_mode *to_match); +extern bool drm_probe_ddc(struct i2c_adapter *adapter); +extern struct edid *drm_edid_duplicate(const struct edid *edid); +extern struct edid *drm_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter); +extern bool drm_detect_monitor_audio(struct edid *edid); +extern struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev, const struct drm_display_mode *mode); +extern void drm_mode_probed_add(struct drm_connector *connector, struct drm_display_mode *mode); +extern void drm_connector_cleanup(struct drm_connector *connector); +extern int drm_helper_probe_single_connector_modes(struct drm_connector *connector, uint32_t maxX, uint32_t maxY); +extern int drm_mode_create_scaling_mode_property(struct drm_device *dev); +extern void drm_object_attach_property(struct drm_mode_object *obj, struct drm_property *property, uint64_t init_val); +extern int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid); +extern int drm_mode_connector_update_edid_property(struct drm_connector *connector, struct edid *edid); +extern void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid); +extern int drm_connector_init(struct drm_device *dev, struct drm_connector *connector, const struct drm_connector_funcs *funcs, int connector_type); +extern int drm_sysfs_connector_add(struct drm_connector *connector); +extern void drm_clflush_virt_range(char *addr, unsigned long length); +extern void drm_vma_node_unmap(struct drm_vma_offset_node *node, struct address_space *file_mapping); +extern bool drm_vma_node_has_offset(struct drm_vma_offset_node *node); +extern int drm_gem_create_mmap_offset(struct drm_gem_object *obj); +extern void drm_gem_free_mmap_offset(struct drm_gem_object *obj); +extern __u64 drm_vma_node_offset_addr(struct drm_vma_offset_node *node); +extern bool drm_mm_node_allocated(struct drm_mm_node *node); +extern void drm_mm_remove_node(struct drm_mm_node *node); +extern void drm_clflush_sg(struct sg_table *st); +extern int drm_gem_object_init(struct drm_device *dev, struct drm_gem_object *obj, size_t size); +extern void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg); +extern void drm_gem_object_release(struct drm_gem_object *obj); +extern drm_dma_handle_t *drm_pci_alloc(struct drm_device *dev, size_t size, size_t align); +extern void drm_clflush_pages(struct page *pages[], unsigned long num_pages); +extern void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode); +extern const char *drm_get_connector_name(const struct drm_connector *connector); +extern const char *drm_get_encoder_name(const struct drm_encoder *encoder); +extern const char *drm_get_format_name(uint32_t format); +extern void drm_mm_init(struct drm_mm *mm, unsigned long start, unsigned long size); +extern int drm_mm_reserve_node(struct drm_mm *mm, struct drm_mm_node *node); +extern int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc, int *max_error, struct timeval *vblank_time, unsigned flags, const struct drm_crtc *refcrtc, const struct drm_display_mode *mode); +extern const char *drm_get_connector_status_name(enum drm_connector_status status); +extern void drm_kms_helper_hotplug_event(struct drm_device *dev); +extern bool drm_handle_vblank(struct drm_device *dev, int crtc); +extern void drm_gem_private_object_init(struct drm_device *dev, struct drm_gem_object *obj, size_t size); + + + +#ifdef __cplusplus +} +#endif /* extern "C" */ + +#endif /* _DRMP_H_ */ diff --git a/repos/dde_linux/src/drivers/framebuffer/intel/include/i915_trace.h b/repos/dde_linux/src/drivers/framebuffer/intel/include/i915_trace.h new file mode 100644 index 000000000..8e1a48a23 --- /dev/null +++ b/repos/dde_linux/src/drivers/framebuffer/intel/include/i915_trace.h @@ -0,0 +1 @@ +#include diff --git a/repos/dde_linux/src/drivers/framebuffer/intel/include/lx_emul.h b/repos/dde_linux/src/drivers/framebuffer/intel/include/lx_emul.h new file mode 100644 index 000000000..7c6e8b79f --- /dev/null +++ b/repos/dde_linux/src/drivers/framebuffer/intel/include/lx_emul.h @@ -0,0 +1,1491 @@ +/* + * \brief Emulation of the Linux kernel API used by DRM + * \author Norman Feske + * \date 2015-08-19 + * + * The content of this file, in particular data structures, is partially + * derived from Linux-internal headers. + */ + +#ifndef _LX_EMUL_H_ +#define _LX_EMUL_H_ + +#include +#include + +#include + + +/***************** + ** asm/param.h ** + *****************/ + +enum { HZ = 100UL }; + + +#include +#include +#include +#include + +#define smp_mb__before_atomic_inc() barrier() + +void atomic_set_mask(unsigned int mask, atomic_t *v); + +#include +#include + +typedef unsigned long kernel_ulong_t; + + +/************************ + ** uapi/linux/types.h ** + ************************/ + +typedef __u16 __le16; +typedef __u16 __be16; +typedef __u32 __le32; +typedef __u32 __be32; +typedef __u64 __le64; +typedef __u64 __be64; + + +/******************** + ** linux/printk.h ** + ********************/ + +/* needed by drm_edid.c */ +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); + + +/********************* + ** uapi/linux/fb.h ** + *********************/ + +#define KHZ2PICOS(a) (1000000000UL/(a)) + + + +/******************* + ** linux/ctype.h ** + *******************/ + +#define isascii(c) (((unsigned char)(c))<=0x7f) +#define isprint(c) (isascii(c) && ((unsigned char)(c) >= 32)) + + + +/**************** + ** asm/page.h ** + ****************/ + +/* + * For now, hardcoded + */ +#define PAGE_SIZE 4096UL +#define PAGE_MASK (~(PAGE_SIZE-1)) + +dma_addr_t page_to_phys(void *page); + +enum { + PAGE_SHIFT = 12, +}; + +struct page +{ +// unsigned long flags; +// int pfmemalloc; +// int mapping; + atomic_t _count; + void *addr; + unsigned long private; +} __attribute((packed)); + +/* needed for agp/generic.c */ +struct page *virt_to_page(void *addr); + + +#include + +unsigned long find_first_zero_bit(const unsigned long *addr, unsigned long size); + +#include + + +#include + +/* needed by 'virt_to_phys', which is needed by agp/generic.c */ +typedef unsigned long phys_addr_t; + +#include + +void *memchr_inv(const void *s, int c, size_t n); + +#include +#include + +typedef __kernel_time_t time_t; + +extern int oops_in_progress; + +#define pr_debug(fmt, ...) printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__) +#define pr_info(fmt, ...) printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__) +#define pr_err(fmt, ...) printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__) +#define pr_warn(fmt, ...) printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__) +#define pr_info_once(fmt, ...) printk(KERN_INFO fmt, ##__VA_ARGS__) + +int sprintf(char *buf, const char *fmt, ...); +int snprintf(char *buf, size_t size, const char *fmt, ...); + +int sscanf(const char *, const char *, ...); + +enum { SPRINTF_STR_LEN = 64 }; + +#define kasprintf(gfp, fmt, ...) ({ \ + void *buf = kmalloc(SPRINTF_STR_LEN, 0); \ + sprintf(buf, fmt, __VA_ARGS__); \ + buf; \ +}) + +/* linux/i2c.h */ +#define __deprecated + + +/************************ + ** linux/page-flags.h ** + ************************/ + +//void SetPageDirty(struct page *page); + +/* needed by agp/generic.c */ +void SetPageReserved(struct page *page); +void ClearPageReserved(struct page *page); + + +/******************** + ** linux/printk.h ** + ********************/ + +extern void hex_dump_to_buffer(const void *buf, size_t len, + int rowsize, int groupsize, + char *linebuf, size_t linebuflen, bool ascii); + + +#include + +#define MODULE_ALIAS_MISCDEV(x) /* needed by agp/backend.c */ + +/* i2c-core.c */ +#define postcore_initcall(fn) void postcore_##fn(void) { fn(); } + + +/************************** + ** linux/preempt_mask.h ** + **************************/ + +/* needed bu i2c-core.c */ +bool in_atomic(); + + +/********************** + ** linux/irqflags.h ** + **********************/ + +/* needed bu i2c-core.c */ +bool irqs_disabled(); + + +/********************* + ** linux/jiffies.h ** + *********************/ + +#include + +#define time_before(a,b) time_after(b,a) +#define time_before_eq(a,b) time_after_eq(b,a) + +#define time_in_range(a,b,c) \ + (time_after_eq(a,b) && \ + time_before_eq(a,c)) + + + +#include +#include +#include + + +static inline int mutex_lock_interruptible(struct mutex *lock) { + mutex_lock(lock); + return 0; +} + +void mutex_lock_nest_lock(struct mutex *, struct mutex *); + + +/********************* + ** linux/rtmutex.h ** + *********************/ + +struct rt_mutex { int dummy; }; + +void rt_mutex_lock(struct rt_mutex *lock); +int rt_mutex_trylock(struct rt_mutex *lock); +void rt_mutex_unlock(struct rt_mutex *lock); + +#define rt_mutex_init(mutex) + + +/****************** + ** linux/time.h ** + ******************/ + +#include + +void getrawmonotonic(struct timespec *ts); + +struct timespec timespec_sub(struct timespec lhs, struct timespec rhs); +bool timespec_valid(const struct timespec *ts); +void set_normalized_timespec(struct timespec *ts, time_t sec, s64 nsec); +unsigned long get_seconds(void); +struct timespec ns_to_timespec(const s64 nsec); +s64 timespec_to_ns(const struct timespec *ts); + + +/******************* + ** linux/timer.h ** + *******************/ + +#include + +#define del_singleshot_timer_sync(t) del_timer_sync(t) + + +#include + +extern bool flush_delayed_work(struct delayed_work *dwork); + +extern unsigned long timespec_to_jiffies(const struct timespec *value); + +#define wait_event_interruptible_timeout wait_event_timeout + +#define setup_timer_on_stack setup_timer + +void destroy_timer_on_stack(struct timer_list *timer); + +unsigned long round_jiffies_up_relative(unsigned long j); + + +/******************* + ** linux/sched.h ** + *******************/ + +enum { TASK_RUNNING, TASK_INTERRUPTIBLE, TASK_UNINTERRUPTIBLE }; + +struct mm_struct; +struct task_struct { + struct mm_struct *mm; + char comm[16]; /* needed by agp/generic.c, only for debug output */ +}; + +signed long schedule_timeout(signed long timeout); +void __set_current_state(int state); +int signal_pending(struct task_struct *p); +void schedule(void); +int wake_up_process(struct task_struct *tsk); +void io_schedule(void); + +/* normally declared in linux/smp.h, included by sched.h */ +int on_each_cpu(void (*func) (void *info), void *info, int wait); + +/* normally defined in asm/current.h, included by sched.h */ +extern struct task_struct *current; + + +/************************ + ** linux/completion.h ** + ************************/ + +struct completion { unsigned done; }; + +void __wait_completion(struct completion *work); +void complete(struct completion *); /* i2c-core.c */ +void init_completion(struct completion *x); + + +/********************* + ** linux/raid/pq.h ** + *********************/ + +void cpu_relax(void); /* i915_dma.c */ + + +/******************* + ** linux/delay.h ** + *******************/ + +void msleep(unsigned int); +void udelay(unsigned long); +void mdelay(unsigned long); +void ndelay(unsigned long); + +void usleep_range(unsigned long min, unsigned long max); /* intel_dp.c */ + + +/***************** + ** linux/idr.h ** + *****************/ + +/* needed by intel_drv.h */ +struct idr { int dummy; }; + +void idr_init(struct idr *idp); /* i915_gem.c */ +int idr_alloc(struct idr *idp, void *ptr, int start, int end, gfp_t gfp_mask); +void idr_remove(struct idr *idp, int id); +void *idr_find(struct idr *idr, int id); +void idr_destroy(struct idr *idp); + + +struct ida { int dummy; }; + +void ida_destroy(struct ida *ida); +void ida_init(struct ida *ida); +int ida_simple_get(struct ida *ida, unsigned int start, unsigned int end, gfp_t gfp_mask); +void ida_remove(struct ida *ida, int id); + +#define IDR_INIT(name) { .dummy = 0, } +#define DEFINE_IDR(name) struct idr name = IDR_INIT(name) + + +/************************* + ** linux/scatterlist.h ** + *************************/ + +#include + +struct page *sg_page_iter_page(struct sg_page_iter *piter); + +void sg_free_table(struct sg_table *); +int sg_alloc_table(struct sg_table *, unsigned int, gfp_t); + +void sg_mark_end(struct scatterlist *sg); + +dma_addr_t sg_page_iter_dma_address(struct sg_page_iter *piter); + + + +#include + +enum kobject_action { +// KOBJ_ADD, +// KOBJ_REMOVE, + KOBJ_CHANGE, +// KOBJ_MOVE, +// KOBJ_ONLINE, +// KOBJ_OFFLINE, +// KOBJ_MAX +}; + +int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, char *envp[]); + + +/************************ + ** asm/memory_model.h ** + ************************/ + +dma_addr_t page_to_pfn(struct page *page); + + +/********************* + ** linux/pagemap.h ** + *********************/ + +int fault_in_multipages_writeable(char __user *uaddr, int size); +int fault_in_multipages_readable(const char __user *uaddr, int size); + +#define page_cache_release(page) put_page(page) + +struct address_space; + +gfp_t mapping_gfp_mask(struct address_space * mapping); +void mapping_set_gfp_mask(struct address_space *m, gfp_t mask); + + +/****************** + ** linux/swap.h ** + ******************/ + +void mark_page_accessed(struct page *); + + +/********************** + ** linux/mm_types.h ** + **********************/ + +struct vm_area_struct { + unsigned long vm_start; + void *vm_private_data; +}; + +struct mm_struct { struct rw_semaphore mmap_sem; }; + + +/********************** + ** linux/shrinker.h ** + **********************/ + +struct shrink_control { + unsigned long nr_to_scan; +}; + +struct shrinker { + int (*shrink)(int nr_to_scan, gfp_t gfp_mask); + unsigned long (*scan_objects)(struct shrinker *, struct shrink_control *sc); + unsigned long (*count_objects)(struct shrinker *, struct shrink_control *sc); /* i915_gem.c */ + int seeks; +}; + +int register_shrinker(struct shrinker *); +void unregister_shrinker(struct shrinker *); + +#define SHRINK_STOP (~0UL) + + +/**************** + ** linux/mm.h ** + ****************/ + +//extern unsigned long totalram_pages; +// +enum { + VM_FAULT_OOM = 0x001, + VM_FAULT_SIGBUS = 0x002, + VM_FAULT_NOPAGE = 0x100, +}; + +enum { FAULT_FLAG_WRITE = 0x1 }; +// +enum { DEFAULT_SEEKS = 2 }; +// +//#define PAGE_ALIGN(addr) ALIGN(addr, PAGE_SIZE) + +#define offset_in_page(p) ((unsigned long)(p) & ~PAGE_MASK) + +struct vm_fault { + void *virtual_address; + unsigned int flags; +}; +// +//struct file; +struct address_space; +// +//unsigned long do_mmap(struct file *file, unsigned long addr, +// unsigned long len, unsigned long prot, +// unsigned long flag, unsigned long offset); +// +//void unmap_mapping_range(struct address_space *mapping, +// loff_t const holebegin, loff_t const holelen, +// int even_cows); +// +int vm_insert_pfn(struct vm_area_struct *vma, unsigned long addr, + unsigned long pfn); + +int set_page_dirty(struct page *page); + +void get_page(struct page *page); +void put_page(struct page *page); +// +//int get_user_pages(void *tsk, struct mm_struct *mm, +// unsigned long start, int nr_pages, int write, int force, +// struct page **pages, struct vm_area_struct **vmas); +// +//void *page_address(struct page *page); +// +//struct shrinker { +// int (*shrink)(int nr_to_scan, gfp_t gfp_mask); +// int seeks; +//}; +// +//void register_shrinker(struct shrinker *); +//void unregister_shrinker(struct shrinker *); + +extern unsigned long totalram_pages; + + +struct vm_area_struct; +struct vm_fault; + +struct vm_operations_struct { + void (*open)(struct vm_area_struct * area); + void (*close)(struct vm_area_struct * area); + int (*fault)(struct vm_area_struct *vma, struct vm_fault *vmf); +}; + +struct file; + +extern unsigned long vm_mmap(struct file *, unsigned long, + unsigned long, unsigned long, + unsigned long, unsigned long); + +static inline void *page_address(struct page *page) { return page->addr; }; + +int is_vmalloc_addr(const void *x); + +void free_pages(unsigned long addr, unsigned int order); + + +#include + + +/*************** + ** asm/smp.h ** + ***************/ + +void wbinvd(); +void wbinvd_on_all_cpus(); + + +/********************* + ** linux/vmalloc.h ** + *********************/ + +//enum { VM_IOREMAP = 0x1 }; + +/* needed by agp/generic.c */ +void *vmalloc(unsigned long size); +void *vzalloc(unsigned long size); +void vfree(const void *addr); + +///* needed by drm_memory.c */ +//void vunmap(const void *addr); +//void *vmap(struct page **pages, unsigned int count, unsigned long flags, pgprot_t prot); + + +/************************ + ** uapi/linux/const.h ** + ************************/ + +#define _AT(T,X) ((T)(X)) + + +/************************************************* + ** asm/pgtable_64_types.h, asm/pgtable_types.h ** + *************************************************/ + +typedef unsigned long pteval_t; + + +#define _PAGE_BIT_PRESENT 0 /* is present */ +#define _PAGE_BIT_RW 1 /* writeable */ +#define _PAGE_BIT_PWT 3 /* page write through */ +#define _PAGE_BIT_PCD 4 /* page cache disabled */ +#define _PAGE_BIT_PAT 7 /* on 4KB pages */ + +#define _PAGE_PRESENT (_AT(pteval_t, 1) << _PAGE_BIT_PRESENT) +#define _PAGE_RW (_AT(pteval_t, 1) << _PAGE_BIT_RW) +#define _PAGE_PWT (_AT(pteval_t, 1) << _PAGE_BIT_PWT) +#define _PAGE_PCD (_AT(pteval_t, 1) << _PAGE_BIT_PCD) +#define _PAGE_PAT (_AT(pteval_t, 1) << _PAGE_BIT_PAT) + + +/********************** + ** asm/cacheflush.h ** + **********************/ + +int set_pages_wb(struct page *page, int numpages); +int set_pages_uc(struct page *page, int numpages); + + +/****************** + ** linux/slab.h ** + ******************/ + +enum { + SLAB_HWCACHE_ALIGN = 0x00002000ul, +// SLAB_CACHE_DMA = 0x00004000ul, +// SLAB_PANIC = 0x00040000ul, +// +// SLAB_LX_DMA = 0x80000000ul, +}; + +void *kzalloc(size_t size, gfp_t flags); +void kfree(const void *); +void *kcalloc(size_t n, size_t size, gfp_t flags); +void *kmalloc(size_t size, gfp_t flags); +void *krealloc(const void *, size_t, gfp_t); + +struct kmem_cache; +struct kmem_cache *kmem_cache_create(const char *, size_t, size_t, unsigned long, void (*)(void *)); +void kmem_cache_destroy(struct kmem_cache *); +void *kmem_cache_zalloc(struct kmem_cache *k, gfp_t flags); +void kmem_cache_free(struct kmem_cache *, void *); + + +/********************** + ** linux/byteorder/ ** + **********************/ + +#include + + +/****************** + ** linux/swab.h ** + ******************/ + +#define swab16 __swab16 + + +/********************** + ** linux/highmem.h ** + **********************/ + +static inline void *kmap(struct page *page) { return page_address(page); } +static inline void *kmap_atomic(struct page *page) { return kmap(page); } +static inline void kunmap(struct page *page) { } +static inline void kunmap_atomic(void *addr) { } + + +#include + +void __free_pages(struct page *page, unsigned int order); + +#define __free_page(page) __free_pages((page), 0) + +struct page *alloc_pages(gfp_t gfp_mask, unsigned int order); + +#define alloc_page(gfp_mask) alloc_pages(gfp_mask, 0) + +unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order); + + +/************************************** + ** asm-generic/dma-mapping-common.h ** + **************************************/ + +struct dma_attrs; +struct device; + +enum dma_data_direction { DMA_DATA_DIRECTION_DUMMY }; + +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_sg(d, s, n, r) dma_map_sg_attrs(d, s, n, r, NULL) + + +void dma_unmap_sg_attrs(struct device *dev, struct scatterlist *sg, + int nents, enum dma_data_direction dir, + struct dma_attrs *attrs); + +#define dma_unmap_sg(d, s, n, r) dma_unmap_sg_attrs(d, s, n, r, NULL) + + +/********************* + ** linux/dma-buf.h ** + *********************/ + +struct dma_buf; + + +/******************** + ** linux/pm_qos.h ** + ********************/ + +enum { PM_QOS_CPU_DMA_LATENCY, }; + +struct pm_qos_request { int dummy; }; + +void pm_qos_remove_request(struct pm_qos_request *req); +void pm_qos_update_request(struct pm_qos_request *req, s32 new_value); +void pm_qos_add_request(struct pm_qos_request *req, int pm_qos_class, s32 value); + + +#define PM_QOS_DEFAULT_VALUE -1 + + +/*********************** + ** linux/pm_wakeup.h ** + ***********************/ + +bool device_can_wakeup(struct device *dev); +int device_init_wakeup(struct device *dev, bool val); + + +/******************* + ** linux/sysfs.h ** + *******************/ + +struct attribute { int dummy; }; + +struct attribute_group { +// const char *name; +// umode_t (*is_visible)(struct kobject *, +// struct attribute *, int); + struct attribute **attrs; +// struct bin_attribute **bin_attrs; +}; + + +/**************** + ** linux/pm.h ** + ****************/ + +#include + +enum { + PM_EVENT_QUIESCE = 0x0008, + PM_EVENT_PRETHAW = PM_EVENT_QUIESCE, +}; + +#define SET_RUNTIME_PM_OPS(suspend_fn, resume_fn, idle_fn) + + +/******************** + ** linux/device.h ** + ********************/ + +struct device_driver; +struct subsys_private; + +struct bus_type +{ + const char *name; + + int (*match)(struct device *dev, struct device_driver *drv); + int (*probe)(struct device *dev); + int (*remove)(struct device *dev); + void (*shutdown)(struct device *dev); + int (*suspend)(struct device *dev, pm_message_t state); + int (*resume)(struct device *dev); + + const struct dev_pm_ops *pm; + struct subsys_private *p; +}; + +struct device_type +{ + const struct attribute_group **groups; + int (*uevent)(struct device *dev, struct kobj_uevent_env *env); + void (*release)(struct device *dev); +}; + +struct dev_archdata { int dummy; }; + +struct device { + struct device *parent; + struct kobject kobj; + u64 _dma_mask_buf; + u64 *dma_mask; + u64 coherent_dma_mask; + struct device_driver *driver; + void *drvdata; /* not in Linux */ + const struct device_type *type; + void *platform_data; + struct dev_archdata archdata; + struct bus_type *bus; + struct device_node *of_node; +}; + +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); +}; + +#define DEVICE_ATTR(_name, _mode, _show, _store) \ + struct device_attribute dev_attr_##_name = { { 0 } } + +#define DEVICE_ATTR_IGNORE_LOCKDEP(_name, _mode, _show, _store) \ + struct device_attribute dev_attr_##_name = { { 0 } } + +#define dev_info( dev, format, arg...) lx_printf("dev_info: " format , ## arg) +#define dev_warn( dev, format, arg...) lx_printf("dev_warn: " format , ## arg) +#define dev_WARN( dev, format, arg...) lx_printf("dev_WARN: " format , ## arg) +#define dev_err( dev, format, arg...) lx_printf("dev_error: " format , ## arg) +#define dev_notice(dev, format, arg...) lx_printf("dev_notice: " format , ## arg) +#define dev_crit( dev, format, arg...) lx_printf("dev_crit: " format , ## arg) + +#define dev_printk(level, dev, format, arg...) \ + lx_printf("dev_printk: " format , ## arg) +#define dev_dbg(dev, format, arg...) \ + lx_printf("dev_dbg: " format, ## arg) + +struct device_driver +{ + int dummy; + char const *name; + struct bus_type *bus; + struct module *owner; +// const char *mod_name; +// const struct of_device_id *of_match_table; +// const struct acpi_device_id *acpi_match_table; +// int (*probe) (struct device *dev); +// int (*remove) (struct device *dev); +// + const struct dev_pm_ops *pm; +}; + +int driver_register(struct device_driver *drv); +void driver_unregister(struct device_driver *drv); + +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, ...); + +int bus_register(struct bus_type *bus); +void bus_unregister(struct bus_type *bus); + +struct device *get_device(struct device *dev); +void put_device(struct device *dev); + +int device_for_each_child(struct device *dev, void *data, int (*fn)(struct device *dev, void *data)); +int device_register(struct device *dev); +void device_unregister(struct device *dev); + +const char *dev_name(const struct device *dev); + +int bus_for_each_drv(struct bus_type *bus, struct device_driver *start, + void *data, int (*fn)(struct device_driver *, void *)); + +int bus_for_each_dev(struct bus_type *bus, struct device *start, void *data, + int (*fn)(struct device *dev, void *data)); + +/* needed by linux/i2c.h */ +struct acpi_device; + +struct acpi_dev_node { struct acpi_device *companion; }; + + +/**************** + ** linux/io.h ** + ****************/ + +#define writel(value, addr) (*(volatile uint32_t *)(addr) = (value)) +#define readl(addr) (*(volatile uint32_t *)(addr)) + +#define iowrite32(v, addr) writel((v), (addr)) +#define ioread32(addr) readl(addr) + +void outb(u8 value, u32 port); +void outw(u16 value, u32 port); +void outl(u32 value, u32 port); + +u8 inb(u32 port); +u16 inw(u32 port); +u32 inl(u32 port); + +void iounmap(volatile void *addr); + +void __iomem *ioremap(phys_addr_t offset, unsigned long size); + +/** + * Map I/O memory write combined + */ +void *ioremap_wc(resource_size_t phys_addr, unsigned long size); + +#define ioremap_nocache ioremap_wc + +void *memset_io(void *s, int c, size_t n); + +int arch_phys_wc_add(unsigned long base, unsigned long size); +static inline void arch_phys_wc_del(int handle) { } + +phys_addr_t virt_to_phys(volatile void *address); + + +/********************* + ** linux/uaccess.h ** + *********************/ + +enum { VERIFY_READ = 0, VERIFY_WRITE = 1 }; + +#define get_user(x, ptr) ({ (x) = *(ptr); 0; }) +#define put_user(x, ptr) ({ *(ptr) = (x); 0; }) + +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 __copy_from_user copy_from_user +#define __copy_to_user copy_to_user +#define __copy_from_user_inatomic copy_from_user +#define __copy_to_user_inatomic copy_to_user +#define __copy_from_user_inatomic_nocache copy_from_user + + +/************************* + ** linux/dma-mapping.h ** + *************************/ + +#define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : ((1ULL<<(n))-1)) + +int dma_set_coherent_mask(struct device *dev, u64 mask); + + +/************************ + ** linux/io-mapping.h ** + ************************/ + +struct io_mapping; + +void *io_mapping_map_atomic_wc(struct io_mapping *mapping, unsigned long offset); +void io_mapping_unmap_atomic(void *vaddr); + +struct io_mapping *io_mapping_create_wc(resource_size_t base, unsigned long size); +void io_mapping_free(struct io_mapping *mapping); + +#include + + +/******************** + ** linux/ioport.h ** + ********************/ + +#include + +extern struct resource iomem_resource; + +int request_resource(struct resource *root, struct resource *); /* intel-gtt.c */ + +int release_resource(struct resource *r); /* i915_dma.c */ + + +/************************ + ** linux/pm_runtime.h ** + ************************/ + +int pm_generic_runtime_suspend(struct device *dev); +int pm_generic_runtime_resume(struct device *dev); + + +/***************** + ** linux/pci.h ** + *****************/ + +enum { DEVICE_COUNT_RESOURCE = 6 }; + +struct pci_dev { + unsigned int devfn; + unsigned int irq; + struct resource resource[DEVICE_COUNT_RESOURCE]; + struct pci_bus *bus; /* i915_dma.c */ + unsigned short vendor; /* intel-agp.c */ + unsigned short device; + u8 hdr_type; + bool msi_enabled; + struct device dev; /* intel-agp.c */ + unsigned short subsystem_vendor; /* intel_display.c */ + unsigned short subsystem_device; + u8 revision; /* i915_gem.c */ + u8 pcie_cap; + u16 pcie_flags_reg; + unsigned int class; +}; + +struct pci_device_id { + u32 vendor, device, subvendor, subdevice, class, class_mask; + unsigned long driver_data; +}; + +#include + +struct pci_dev *pci_get_bus_and_slot(unsigned int bus, unsigned int devfn); +int pci_bus_alloc_resource(struct pci_bus *bus, + struct resource *res, resource_size_t size, + resource_size_t align, resource_size_t min, + unsigned int type_mask, + resource_size_t (*alignf)(void *, + const struct resource *, + resource_size_t, + resource_size_t), + void *alignf_data); +resource_size_t pcibios_align_resource(void *, const struct resource *, + resource_size_t, + resource_size_t); +int pci_set_power_state(struct pci_dev *dev, pci_power_t state); +struct pci_dev *pci_get_class(unsigned int device_class, struct pci_dev *from); +int pci_save_state(struct pci_dev *dev); + +enum { PCIBIOS_MIN_MEM = 0UL }; + + +static inline void pci_set_drvdata(struct pci_dev *pdev, void *data) +{ + pdev->dev.drvdata = data; +} + +static inline int pci_set_dma_mask(struct pci_dev *dev, u64 mask) +{ + *dev->dev.dma_mask = mask; + return 0; +} + +static inline int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask) +{ + dev->dev.coherent_dma_mask = mask; + return 0; +} + +/* agp/generic.c */ +#define for_each_pci_dev(d) while ((d = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, d)) != NULL) + +static inline dma_addr_t pci_bus_address(struct pci_dev *pdev, int bar) +{ + lx_printf("pci_bus_address called\n"); + return (dma_addr_t)pci_resource_start(pdev, bar); +} + +struct pci_dev *pci_dev_get(struct pci_dev *dev); + + +/********************************** + ** asm-generic/pci-dma-compat.h ** + **********************************/ + +void pci_unmap_page(struct pci_dev *hwdev, dma_addr_t dma_address, size_t size, int direction); + +dma_addr_t pci_map_page(struct pci_dev *hwdev, struct page *page, unsigned long offset, size_t size, int direction); + +int pci_dma_mapping_error(struct pci_dev *pdev, dma_addr_t dma_addr); + + +/***************************** + ** asm-generic/pci_iomap.h ** + *****************************/ + +void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max); +void pci_iounmap(struct pci_dev *dev, void __iomem *p); + + +/*********************** + ** linux/irqreturn.h ** + ***********************/ + +#include + + +/************************ + ** linux/capability.h ** + ************************/ + +bool capable(int cap); + +#define CAP_SYS_ADMIN 21 + + +/****************** + ** linux/hdmi.h ** + ******************/ + +#define HDMI_IEEE_OUI 0x000c03 + +enum hdmi_infoframe_type { HDMI_INFOFRAME_TYPE_DUMMY }; + +enum hdmi_picture_aspect { + HDMI_PICTURE_ASPECT_NONE, + HDMI_PICTURE_ASPECT_4_3, + HDMI_PICTURE_ASPECT_16_9, +}; + +enum hdmi_active_aspect { + HDMI_ACTIVE_ASPECT_16_9_TOP = 2, + HDMI_ACTIVE_ASPECT_14_9_TOP = 3, + HDMI_ACTIVE_ASPECT_16_9_CENTER = 4, + HDMI_ACTIVE_ASPECT_PICTURE = 8, + HDMI_ACTIVE_ASPECT_4_3 = 9, + HDMI_ACTIVE_ASPECT_16_9 = 10, + HDMI_ACTIVE_ASPECT_14_9 = 11, + HDMI_ACTIVE_ASPECT_4_3_SP_14_9 = 13, + HDMI_ACTIVE_ASPECT_16_9_SP_14_9 = 14, + HDMI_ACTIVE_ASPECT_16_9_SP_4_3 = 15, +}; + +enum hdmi_3d_structure { + HDMI_3D_STRUCTURE_INVALID = -1, + HDMI_3D_STRUCTURE_FRAME_PACKING = 0, + HDMI_3D_STRUCTURE_FIELD_ALTERNATIVE, + HDMI_3D_STRUCTURE_LINE_ALTERNATIVE, + HDMI_3D_STRUCTURE_SIDE_BY_SIDE_FULL, + HDMI_3D_STRUCTURE_L_DEPTH, + HDMI_3D_STRUCTURE_L_DEPTH_GFX_GFX_DEPTH, + HDMI_3D_STRUCTURE_TOP_AND_BOTTOM, + HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF = 8, +}; + +struct hdmi_avi_infoframe { + int dummy; + enum hdmi_picture_aspect picture_aspect; + enum hdmi_active_aspect active_aspect; + unsigned char video_code; + unsigned char pixel_repeat; +}; + +struct hdmi_vendor_infoframe { + enum hdmi_infoframe_type type; + u8 vic; + enum hdmi_3d_structure s3d_struct; +}; + +int hdmi_avi_infoframe_init(struct hdmi_avi_infoframe *frame); +int hdmi_vendor_infoframe_init(struct hdmi_vendor_infoframe *frame); + + +/************************* + ** linux/agp_backend.h ** + *************************/ + +#include + + +/******************** + ** linux/vgaarb.h ** + ********************/ + +/* + * needed for compiling i915_dma.c + */ + +enum { + VGA_RSRC_LEGACY_IO = 0x01, + VGA_RSRC_LEGACY_MEM = 0x02, + VGA_RSRC_NORMAL_IO = 0x04, + VGA_RSRC_NORMAL_MEM = 0x08, +}; + +int vga_client_register(struct pci_dev *pdev, void *cookie, + void (*irq_set_state)(void *cookie, bool state), + unsigned int (*set_vga_decode)(void *cookie, bool state)); + +int vga_get_uninterruptible(struct pci_dev *pdev, unsigned int rsrc); + +void vga_put(struct pci_dev *pdev, unsigned int rsrc); + + +/********************** + ** linux/notifier.h ** + **********************/ + +/* needed by intel_lvds.c */ + +struct notifier_block; + +typedef int (*notifier_fn_t)(struct notifier_block *nb, unsigned long action, void *data); + +struct notifier_block { notifier_fn_t notifier_call; }; + +enum { NOTIFY_OK = 0x0001 }; + + +/******************* + ** acpi/button.h ** + *******************/ + +int acpi_lid_open(void); +int acpi_lid_notifier_register(struct notifier_block *nb); +int acpi_lid_notifier_unregister(struct notifier_block *nb); + + +/**************************** + ** linux/vga_switcheroo.h ** + ****************************/ + +/* + * needed for compiling i915_dma.c + */ + +enum vga_switcheroo_state { VGA_SWITCHEROO_OFF, VGA_SWITCHEROO_ON }; + +struct vga_switcheroo_client_ops { + void (*set_gpu_state)(struct pci_dev *dev, enum vga_switcheroo_state); + void (*reprobe)(struct pci_dev *dev); + bool (*can_switch)(struct pci_dev *dev); +}; + +int vga_switcheroo_register_client(struct pci_dev *dev, + const struct vga_switcheroo_client_ops *ops, + bool driver_power_control); + +void vga_switcheroo_unregister_client(struct pci_dev *dev); + +int vga_switcheroo_process_delayed_switch(void); + + +/****************** + ** acpi/video.h ** + ******************/ + +int acpi_video_register(void); +void acpi_video_unregister(void); + + +/***************** + ** asm/ioctl.h ** + *****************/ + +#include + + +/********************* + ** linux/console.h ** + *********************/ + +void console_lock(void); +void console_unlock(void); +int console_trylock(void); + + +/**************** + ** linux/fb.h ** + ****************/ + +enum { FBINFO_STATE_RUNNING = 0, FBINFO_STATE_SUSPENDED = 1 }; + + +/**************** + ** linux/fs.h ** + ****************/ + +struct file; +struct poll_table_struct; +struct inode; +struct inode_operations { void (*truncate) (struct inode *); }; + +struct inode { + const struct inode_operations *i_op; + struct address_space *i_mapping; +}; + +/* i915_drv.c */ +struct file_operations { + struct module *owner; + loff_t (*llseek) (struct file *, loff_t, int); + ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); + unsigned int (*poll) (struct file *, struct poll_table_struct *); + long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); + int (*mmap) (struct file *, struct vm_area_struct *); + int (*open) (struct inode *, struct file *); + int (*release) (struct inode *, struct file *); +}; + +enum { PROT_READ = 0x1, PROT_WRITE = 0x2 }; + +enum { MAP_SHARED = 0x1 }; + +loff_t noop_llseek(struct file *file, loff_t offset, int whence); + +struct inode *file_inode(struct file *f); + + +/********************** + ** linux/shmem_fs.h ** + **********************/ + +extern void shmem_truncate_range(struct inode *inode, loff_t start, loff_t end); + +extern struct page *shmem_read_mapping_page_gfp(struct address_space *mapping, + pgoff_t index, gfp_t gfp_mask); +//extern struct page *shmem_read_mapping_page_gfp(struct address_space *mapping, +// pgoff_t index, gfp_t gfp_mask); +extern struct page *shmem_read_mapping_page( struct address_space *mapping, pgoff_t index); + + +/******************** + ** linux/math64.h ** + ********************/ + +static inline u64 div_u64(u64 dividend, u32 divisor) { return dividend / divisor; } + + +/***************************** + ** linux/mod_devicetable.h ** + *****************************/ + +enum dmi_field { +// DMI_NONE, +// DMI_BIOS_VENDOR, +// DMI_BIOS_VERSION, +// DMI_BIOS_DATE, + DMI_SYS_VENDOR, + DMI_PRODUCT_NAME, + DMI_PRODUCT_VERSION, +// DMI_PRODUCT_SERIAL, +// DMI_PRODUCT_UUID, + DMI_BOARD_VENDOR, + DMI_BOARD_NAME, +// DMI_BOARD_VERSION, +// DMI_BOARD_SERIAL, +// DMI_BOARD_ASSET_TAG, +// DMI_CHASSIS_VENDOR, +// DMI_CHASSIS_TYPE, +// DMI_CHASSIS_VERSION, +// DMI_CHASSIS_SERIAL, +// DMI_CHASSIS_ASSET_TAG, +// DMI_STRING_MAX, +}; + +struct dmi_strmatch { + unsigned char slot:7; + unsigned char exact_match:1; + char substr[79]; +}; + +struct dmi_system_id { + int (*callback)(const struct dmi_system_id *); + const char *ident; + struct dmi_strmatch matches[4]; + void *driver_data; +}; + +extern int dmi_check_system(const struct dmi_system_id *list); + +#define DMI_MATCH(a, b) { .slot = a, .substr = b } +#define DMI_EXACT_MATCH(a, b) { .slot = a, .substr = b, .exact_match = 1 } + +#define I2C_MODULE_PREFIX "i2c:" +#define I2C_NAME_SIZE 20 + +struct i2c_device_id { + char name[I2C_NAME_SIZE]; + kernel_ulong_t driver_data; /* Data private to the driver */ +}; + +/********************* + ** asm/processor.h ** + *********************/ + +struct boot_cpu_data { + unsigned x86_clflush_size; +}; + +extern struct boot_cpu_data boot_cpu_data; + + +/*********************** + ** linux/backlight.h ** + ***********************/ + +/* intel_panel.c */ + +struct backlight_properties { + int brightness; +}; + +struct backlight_device { + struct backlight_properties props; +}; + + +/***************** + ** linux/i2c.h ** + *****************/ + +struct i2c_adapter; +struct i2c_msg; + +#include + + + +/**************** + ** linux/of.h ** + ****************/ + +int of_alias_get_id(struct device_node *np, const char *stem); + + +/*********************** + ** linux/of_device.h ** + ***********************/ + +int of_driver_match_device(struct device *dev, const struct device_driver *drv); + + +/****************** + ** linux/acpi.h ** + ******************/ + +struct kobject_uevent_env; + +bool acpi_driver_match_device(struct device *dev, const struct device_driver *drv); +int acpi_device_uevent_modalias(struct device *, struct kobj_uevent_env *); + +int acpi_dev_pm_attach(struct device *dev, bool power_on); +void acpi_dev_pm_detach(struct device *dev, bool power_off); + +int acpi_device_modalias(struct device *, char *, int); + +#define ACPI_COMPANION(dev) (NULL) +#define ACPI_COMPANION_SET(dev, adev) do { } while (0) + +const char *acpi_dev_name(struct acpi_device *adev); + + +/****************** + ** linux/gpio.h ** + ******************/ + +/* make these flag values available regardless of GPIO kconfig options */ +#define GPIOF_DIR_OUT (0 << 0) +#define GPIOF_DIR_IN (1 << 0) + +#define GPIOF_INIT_LOW (0 << 1) +#define GPIOF_INIT_HIGH (1 << 1) + +#define GPIOF_IN (GPIOF_DIR_IN) +#define GPIOF_OUT_INIT_HIGH (GPIOF_DIR_OUT | GPIOF_INIT_HIGH) + +#define GPIOF_OPEN_DRAIN (1 << 3) + +/* needed bu drivers/i2c/i2c-core.c */ +int gpio_get_value(unsigned int gpio); +void gpio_set_value(unsigned int gpio, int value); +int gpio_request_one(unsigned gpio, unsigned long flags, const char *label); +void gpio_free(unsigned gpio); +bool gpio_is_valid(int number); + + +/******************* + ** Configuration ** + *******************/ + +/* evaluated in i915_drv.c */ +enum { CONFIG_DRM_I915_PRELIMINARY_HW_SUPPORT = 1 }; + + +/************************** + ** Dummy trace funtions ** + **************************/ + +/* normally provided by i915_trace.h */ + +#define trace_i915_gem_object_pread(...) +#define trace_i915_gem_object_pwrite(...) +#define trace_i915_gem_request_wait_begin(...) +#define trace_i915_gem_request_wait_end(...) +#define trace_i915_gem_object_fault(...) +#define trace_i915_gem_request_add(...) +#define trace_i915_gem_request_retire(...) +#define trace_i915_gem_ring_sync_to(...) +#define trace_i915_gem_object_change_domain(...) +#define trace_i915_vma_unbind(...) +#define trace_i915_vma_bind(...) +#define trace_i915_gem_object_clflush(...) +#define trace_i915_gem_object_create(...) +#define trace_i915_gem_object_destroy(...) +#define trace_i915_flip_complete(...) +#define trace_i915_flip_request(...) +#define trace_i915_reg_rw(...) +#define trace_i915_gem_request_complete(...) + + +#include + +#endif /* _LX_EMUL_H_ */ diff --git a/repos/dde_linux/src/drivers/framebuffer/intel/lx_emul.cc b/repos/dde_linux/src/drivers/framebuffer/intel/lx_emul.cc new file mode 100644 index 000000000..81a550ae0 --- /dev/null +++ b/repos/dde_linux/src/drivers/framebuffer/intel/lx_emul.cc @@ -0,0 +1,627 @@ +/* + * \brief Emulation of Linux kernel interfaces + * \author Norman Feske + * \date 2015-08-19 + */ + +/* local includes */ +#include "lx_emul_private.h" + +/* Genode includes */ +#include + +/* DRM-specific includes */ +extern "C" { +#include +#include +#include +} + + +void lx_printf(char const *fmt, ...) +{ + va_list va; + va_start(va, fmt); + Genode::vprintf(fmt, va); + va_end(va); +} + + +void lx_vprintf(char const *fmt, va_list va) +{ + Genode::vprintf(fmt, va); +} + + +/**************************************** + ** Common Linux kernel infrastructure ** + ****************************************/ + +#include + +int oops_in_progress; + + +/******************** + ** linux/string.h ** + ********************/ + +char *strncpy(char *dst, const char* src, size_t n) +{ + return Genode::strncpy(dst, src, n); +} + + +/***************** + ** linux/dmi.h ** + *****************/ + +int dmi_check_system(const struct dmi_system_id *list) +{ + TRACE; + /* + * Is used to check for quirks of the platform. + */ + return 0; +} + + +/******************* + ** linux/delay.h ** + *******************/ + +#include + + +/********************** + ** Global variables ** + **********************/ + +struct task_struct *current; + + +struct boot_cpu_data boot_cpu_data; + + +/******************* + ** Kernel memory ** + *******************/ + +#include +#include + + +dma_addr_t page_to_phys(void *p) +{ + struct page *page = (struct page *)p; + + dma_addr_t const phys = Lx::Malloc::dma().phys_addr(page->addr); + + PDBG("virt=0x%lx -> phys=0x%lx", (long)page->addr, phys); + return phys; +} + + +/***************** + ** linux/idr.h ** + *****************/ + +void idr_init(struct idr *idp) +{ + TRACE; +} + + +int idr_alloc(struct idr *idp, void *ptr, int start, int end, gfp_t gfp_mask) +{ + TRACE; + /* + * Called from i915_gem_context.c: create_hw_context() + */ + return 0; +} + + +int ida_simple_get(struct ida *ida, unsigned int start, unsigned int end, gfp_t gfp_mask) +{ + /* + * Called by drm_crtc.c: drm_connector_init to allocate a connector_type_id + */ + TRACE; + return 0; +} + + + +/********************** + ** asm/cacheflush.h ** + **********************/ + +int set_pages_uc(struct page *page, int numpages) +{ + TRACE; + return 0; +} + + +/******************** + ** linux/ioport.h ** + ********************/ + +struct resource iomem_resource; + + +/********* + ** PCI ** + *********/ + +#include +#include + +struct pci_dev *pci_get_bus_and_slot(unsigned int bus, unsigned int devfn) +{ + if (bus != 0 || devfn != 0) + TRACE_AND_STOP; + + pci_dev *pci_dev = nullptr; + + auto lamda = [&] (Platform::Device_capability cap) { + + Platform::Device_client client(cap); + + /* request bus address of device from platform driver */ + unsigned char dev_bus = 0, dev_slot = 0, dev_fn = 0; + client.bus_address(&dev_bus, &dev_slot, &dev_fn); + + if (dev_bus == bus && PCI_SLOT(devfn) == dev_slot && PCI_FUNC(devfn) == dev_fn) { + Lx::Pci_dev *dev = new (Genode::env()->heap()) Lx::Pci_dev(cap); + Lx::pci_dev_registry()->insert(dev); + pci_dev = dev; + return true; + } + + return false; + }; + + Lx::for_each_pci_device(lamda); + + return pci_dev; +} + + +struct pci_dev *pci_get_class(unsigned int class_code, struct pci_dev *from) +{ + /* + * The function is solely called by the i915 initialization code to + * probe for the ISA bridge device in order to detect the hardware + * generation. + * + * We look up the bridge but don't need to support the iteration over + * multiple devices of the given class. + */ + if (from) + return nullptr; + + pci_dev *pci_dev = nullptr; + + auto lamda = [&] (Platform::Device_capability cap) { + + Platform::Device_client client(cap); + + if (client.class_code() == class_code) { + pci_dev = new (Genode::env()->heap()) Lx::Pci_dev(cap); + return true; + } + + return false; + }; + + Lx::for_each_pci_device(lamda); + + return pci_dev; +} + + +void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max) +{ + return pci_ioremap_bar(dev, bar); +} + + +struct pci_dev *pci_dev_get(struct pci_dev *dev) +{ + TRACE; + return dev; +}; + + +int vga_get_uninterruptible(struct pci_dev *pdev, unsigned int rsrc) +{ + /* + * This function locks the VGA device. It is normally provided by the + * VGA arbiter in the Linux kernel. We don't need this arbitration because + * the platform-driver enforces the exclusive access to the VGA resources + * by our driver. + * + * At the time when this function is called, the 'pci_dev' structure for + * the VGA card was already requested. Hence, subsequent I/O accesses + * should work. + */ + TRACE; + return 0; +} + + +void vga_put(struct pci_dev *pdev, unsigned int rsrc) +{ + TRACE; +} + + +int pci_bus_alloc_resource(struct pci_bus *, struct resource *, resource_size_t, + resource_size_t, resource_size_t, unsigned int, + resource_size_t (*)(void *, const struct resource *, resource_size_t, resource_size_t), + void *alignf_data) +{ + TRACE; + return 0; +} + + +void pci_set_master(struct pci_dev *dev) +{ + TRACE; +} + + +int pci_enable_msi(struct pci_dev *dev) +{ + TRACE; + return 0; +} + + + +struct io_mapping +{ + private: + + resource_size_t _base; + unsigned long _size; + + public: + + /** + * Constructor + */ + io_mapping(resource_size_t base, unsigned long size) : + _base(base), _size(size) { } + + resource_size_t base() const { return _base; } +}; + + +/** + * I/O mapping used by i915_dma.c to map the GTT aperture + */ +struct io_mapping *io_mapping_create_wc(resource_size_t base, unsigned long size) +{ + static int called; + TRACE; + + if (called++ != 0) { + PERR("io_mapping_create_wc unexpectedly called twice"); + return 0; + } + + io_mapping *mapping = new (Genode::env()->heap()) io_mapping(base, size); + return mapping; +} + + +/**************** + ** linux/io.h ** + ****************/ + +int arch_phys_wc_add(unsigned long base, unsigned long size) +{ + /* + * Linux tries to manipulate physical memory attributes here (e.g., + * using MTRRs). But when using PAT, this is not needed. When running + * on top of a microkernel, we cannot manipulate the attributes + * anyway. + */ + TRACE; + return 0; +} + + +/******************** + ** linux/device.h ** + ********************/ + +struct subsys_private { int dummy; }; + +int bus_register(struct bus_type *bus) +{ + /* + * called by i2c-core init + * + * The subsequent code checks for the 'p' member of the 'bus'. So + * we have to supply a valid pointer there. + */ + + static subsys_private priv = { 0 }; + bus->p = &priv; + + TRACE; + return 0; +} + + +int driver_register(struct device_driver *drv) +{ + TRACE; + return 0; +} + + +int bus_for_each_dev(struct bus_type *bus, struct device *start, void *data, + int (*fn)(struct device *dev, void *data)) +{ + /* + * Called bu the i2c-core driver after registering the driver. This + * function is called to process drivers that are present at initialization + * time. Since we initialize the i2c driver prior the others, we don't + * need to perform anything. + */ + TRACE; + return 0; +} + + +int dev_set_name(struct device *dev, const char *name, ...) +{ + PDBG("name=%s", name); + TRACE; + return 0; +} + + +int device_register(struct device *dev) +{ + TRACE; + return 0; +} + + +/*********************** + ** linux/workqueue.h ** + ***********************/ + +struct workqueue_struct *create_singlethread_workqueue(char const *) +{ + workqueue_struct *wq = (workqueue_struct *)kzalloc(sizeof(workqueue_struct), 0); + return wq; +} + +struct workqueue_struct *alloc_ordered_workqueue(char const *name , unsigned int flags, ...) +{ + return create_singlethread_workqueue(name); +} + + +/*************** + ** Execution ** + ***************/ + +#include +#include +#include +#include +#include +#include + + +void __wait_completion(struct completion *work) +{ + TRACE_AND_STOP; +} + + +void mutex_lock_nest_lock(struct mutex *lock, struct mutex *) +{ + TRACE; + /* + * Called by drm_crtc.c: drm_modeset_lock_all, drm_crtc_init to + * lock the crtc mutex. + */ + mutex_lock(lock); +} + + +/************************ + ** DRM implementation ** + ************************/ + +unsigned int drm_debug = 1; + + +extern "C" int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver) +{ + PDBG("call pci_register_driver"); + + return pci_register_driver(pdriver); +} + + +struct drm_device *drm_dev_alloc(struct drm_driver *driver, struct device *parent) +{ + struct drm_device *dev = (drm_device *)kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + return nullptr; + + dev->driver = driver; + + spin_lock_init(&dev->count_lock); + spin_lock_init(&dev->event_lock); + + mutex_init(&dev->struct_mutex); + +// ret = drm_gem_init(dev); +// if (ret) { +// PERR("drm_gem_init failed"); +// return nullptr; +// } + + return dev; +} + + +/* + * Called indirectly when 'pci_register_driver' has found a matching + * device. + */ +int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent, + struct drm_driver *driver) +{ + drm_device *dev = drm_dev_alloc(driver, &pdev->dev); + if (!dev) + return -ENOMEM; + +// ret = pci_enable_device(pdev); + + dev->pdev = pdev; + + pci_set_drvdata(pdev, dev); + +// drm_pci_agp_init(dev); + + /* + * Kick off the actual driver initialization code + * + * In the Linux DRM code, this happens indirectly via the call of + * 'drm_dev_register'. + */ + driver->load(dev, ent->driver_data); + + DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n", + driver->name, driver->major, driver->minor, driver->patchlevel, + driver->date, pci_name(pdev), dev->primary->index); + + return 0; +} + + +/** + * Called from 'i915_driver_load' + */ +int drm_vblank_init(struct drm_device *dev, int num_crtcs) +{ + TRACE; + return 0; +} + + +int drm_irq_install(struct drm_device *dev) +{ + TRACE; + return 0; +} + + +/************************************** + ** Stubs for non-ported driver code ** + **************************************/ + +void intel_pm_setup(struct drm_device *dev) +{ + TRACE; +} + +void intel_init_pm(struct drm_device *dev) +{ + TRACE; +} + +int intel_power_domains_init(struct drm_device *dev) +{ + TRACE; + return 0; +} + +void intel_power_domains_init_hw(struct drm_device *dev) +{ + TRACE; +} + +void pm_qos_add_request(struct pm_qos_request *req, int pm_qos_class, s32 value) +{ + TRACE; +} + +void intel_disable_gt_powersave(struct drm_device *dev) +{ + TRACE; +} + +void intel_setup_bios(struct drm_device *dev) +{ + TRACE; +} + +int intel_parse_bios(struct drm_device *dev) +{ + TRACE; + return -1; +} + +void i915_gem_detect_bit_6_swizzle(struct drm_device *dev) +{ + TRACE; +} + +int register_shrinker(struct shrinker *) +{ + TRACE; + return 0; +} + +int vga_client_register(struct pci_dev *pdev, void *cookie, void (*irq_set_state)(void *cookie, bool state), unsigned int (*set_vga_decode)(void *cookie, bool state)) +{ + TRACE; + return -ENODEV; +} + +int vga_switcheroo_register_client(struct pci_dev *dev, const struct vga_switcheroo_client_ops *ops, bool driver_power_control) +{ + TRACE; + return 0; +} + +int intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) +{ + TRACE; + return 0; +} + +struct i915_ctx_hang_stats * i915_gem_context_get_hang_stats(struct drm_device *dev, struct drm_file *file, u32 id) +{ + TRACE_AND_STOP; + return NULL; +} + +struct resource * devm_request_mem_region(struct device *dev, resource_size_t start, resource_size_t n, const char *name) +{ + /* + * This function solely called for keeping the stolen memory preserved + * for the driver only ('i915_stolen_to_physical'). The returned pointer is + * just checked for NULL but not used otherwise. + */ + TRACE; + static struct resource dummy; + return &dummy; +} + + +DEFINE_SPINLOCK(mchdev_lock); diff --git a/repos/dde_linux/src/drivers/framebuffer/intel/lx_emul_private.h b/repos/dde_linux/src/drivers/framebuffer/intel/lx_emul_private.h new file mode 100644 index 000000000..c47c5b028 --- /dev/null +++ b/repos/dde_linux/src/drivers/framebuffer/intel/lx_emul_private.h @@ -0,0 +1,28 @@ +/* + * \brief Local definitions of the Linux kernel API implementation + * \author Norman Feske + * \date 2015-08-24 + */ + +#ifndef _LX_EMUL_PRIVATE_H_ +#define _LX_EMUL_PRIVATE_H_ + +/* Genode includes */ +#include +#include + +/* Linux kernel API */ +#include + +#define TRACE \ + do { \ + PLOG("%s not implemented", __func__); \ + } while (0) + +#define TRACE_AND_STOP \ + do { \ + PWRN("%s not implemented", __func__); \ + Genode::sleep_forever(); \ + } while (0) + +#endif /* _LX_EMUL_PRIVATE_H_ */ diff --git a/repos/dde_linux/src/drivers/framebuffer/intel/main.cc b/repos/dde_linux/src/drivers/framebuffer/intel/main.cc new file mode 100644 index 000000000..c35960c3d --- /dev/null +++ b/repos/dde_linux/src/drivers/framebuffer/intel/main.cc @@ -0,0 +1,115 @@ +/* + * \brief Intel framebuffer driver + * \author Norman Feske + * \date 2015-08-19 + */ + +/* + * Copyright (C) 2015 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 + +/* Linux emulation environment includes */ +#include +#include +#include +#include +#include + + +namespace Server { struct Main; } + + +Lx::Scheduler & Lx::scheduler() +{ + static Lx::Scheduler inst; + return inst; +} + + +Lx::Timer & Lx::timer(Server::Entrypoint *ep, unsigned long *jiffies) +{ + return _timer_impl(ep, jiffies); +} + + +Platform::Connection *Lx::pci() +{ + static Platform::Connection _pci; + return &_pci; +} + + +Lx::Pci_dev_registry *Lx::pci_dev_registry() +{ + static Lx::Pci_dev_registry _pci_dev_registry; + return &_pci_dev_registry; +} + + +namespace Lx { + Genode::Object_pool memory_pool; +}; + + +extern "C" int postcore_i2c_init(); /* i2c-core.c */ +extern "C" int module_i915_init(); /* i915_drv.c */ + + +static void run_linux(void *) +{ + PDBG("postcore_i915_init"); + postcore_i2c_init(); + + PDBG("module_i915_init"); + module_i915_init(); + + while (1) { + Lx::scheduler().current()->block_and_schedule(); + } +} + + +unsigned long jiffies; + + +struct Server::Main +{ + Entrypoint &ep; + + /* init singleton Lx::Timer */ + Lx::Timer &timer = Lx::timer(&ep, &jiffies); + + /* Linux task that handles the initialization */ + Lx::Task linux { run_linux, nullptr, "linux", + Lx::Task::PRIORITY_0, Lx::scheduler() }; + + Main(Entrypoint &ep) : ep(ep) + { + Genode::printf("--- intel framebuffer driver ---\n"); + + /* give all task a first kick before returning */ + Lx::scheduler().schedule(); + + PDBG("returning from main"); + } +}; + + +namespace Server { + + char const *name() { return "intel_fb_ep"; } + + size_t stack_size() { return 8*1024*sizeof(long); } + + void construct(Entrypoint &ep) + { + static Main main(ep); + } +} diff --git a/repos/dde_linux/src/drivers/framebuffer/intel/target.mk b/repos/dde_linux/src/drivers/framebuffer/intel/target.mk new file mode 100644 index 000000000..a92f5c836 --- /dev/null +++ b/repos/dde_linux/src/drivers/framebuffer/intel/target.mk @@ -0,0 +1,5 @@ +TARGET = intel_fb_drv +LIBS = base intel_fb_drv intel_fb_include libc-setjmp server +SRC_CC = main.cc lx_emul.cc dummies.cc +SRC_C = i2c-algo-bit.c +INC_DIR += $(REP_DIR)/src/include diff --git a/repos/dde_linux/src/include/lx_emul/atomic.h b/repos/dde_linux/src/include/lx_emul/atomic.h new file mode 100644 index 000000000..0829b4090 --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/atomic.h @@ -0,0 +1,111 @@ +/* + * \brief Linux kernel API + * \author Norman Feske + * \author Sebastian Sumpf + * \author Josef Soentgen + * \date 2014-08-21 + * + * Based on the prototypes found in the Linux kernel's 'include/'. + */ + +/* + * Copyright (C) 2014 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. + */ + +/******************* + ** asm/cmpxchg.h ** + *******************/ + +#define cmpxchg(ptr, o, n) ({ \ + typeof(*ptr) prev = *ptr; \ + *ptr = (*ptr == o) ? n : *ptr; \ + prev;\ + }) + +#define xchg(ptr, x) ({ \ + typeof(*ptr) old = *ptr; \ + *ptr = x; \ + old; \ +}) + +#define atomic_xchg(ptr, v) (xchg(&(ptr)->counter, (v))) + + +/****************** + ** asm/atomic.h ** + ******************/ + +#include + +#define ATOMIC_INIT(i) { (i) } + +typedef struct atomic { long counter; } atomic_t; +typedef atomic_t atomic_long_t; + +static inline int atomic_read(const atomic_t *p) { return p->counter; } +static inline void atomic_set(atomic_t *p, int i) { p->counter = i; } +static inline void atomic_sub(int i, atomic_t *p) { p->counter -= i; } +static inline void atomic_add(int i, atomic_t *p) { p->counter += i; } +static inline int atomic_sub_return(int i, atomic_t *p) { p->counter -= i; return p->counter; } +static inline int atomic_add_return(int i, atomic_t *p) { p->counter += i; return p->counter; } +static inline int atomic_sub_and_test(int i, atomic_t *p) { return atomic_sub_return(i, p) == 0; } + +static inline void atomic_dec(atomic_t *p) { atomic_sub(1, p); } +static inline void atomic_inc(atomic_t *p) { atomic_add(1, p); } +static inline int atomic_dec_return(atomic_t *p) { return atomic_sub_return(1, p); } +static inline int atomic_inc_return(atomic_t *p) { return atomic_add_return(1, p); } +static inline int atomic_dec_and_test(atomic_t *p) { return atomic_sub_and_test(1, p); } +static inline int atomic_inc_not_zero(atomic_t *p) { return p->counter ? atomic_inc_return(p) : 0; } + +static inline void atomic_long_inc(atomic_long_t *p) { atomic_add(1, p); } +static inline void atomic_long_sub(int i, atomic_long_t *p) { atomic_sub(i, p); } +static inline long atomic_long_add_return(long i, atomic_long_t *p) { return atomic_add_return(i, p); } +static inline long atomic_long_read(atomic_long_t *p) { return atomic_read(p); } + +static inline int atomic_cmpxchg(atomic_t *v, int old, int n) +{ + return cmpxchg(&v->counter, old, n); +} + +static inline int atomic_inc_not_zero_hint(atomic_t *v, int hint) +{ + int val, c = hint; + + /* sanity test, should be removed by compiler if hint is a constant */ + if (!hint) + return atomic_inc_not_zero(v); + + do { + val = atomic_cmpxchg(v, c, c + 1); + if (val == c) + return 1; + c = val; + } while (c); + + return 0; +} + +static inline int atomic_add_unless(atomic_t *v, int a, int u) +{ + int ret; + unsigned long flags; + (void)flags; + + ret = v->counter; + if (ret != u) + v->counter += a; + + return ret != u; +} + +#define smp_mb__before_atomic_dec() + + +/******************************* + ** asm-generic/atomic-long.h ** + *******************************/ + +#define ATOMIC_LONG_INIT(i) ATOMIC_INIT(i) diff --git a/repos/dde_linux/src/include/lx_emul/bitops.h b/repos/dde_linux/src/include/lx_emul/bitops.h new file mode 100644 index 000000000..c87dc14a3 --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/bitops.h @@ -0,0 +1,111 @@ +/* + * \brief Linux kernel API + * \author Norman Feske + * \author Sebastian Sumpf + * \author Josef Soentgen + * \date 2014-08-21 + * + * Based on the prototypes found in the Linux kernel's 'include/'. + */ + +/* + * Copyright (C) 2014 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. + */ + +/******************************* + ** asm-generic/bitsperlong.h ** + *******************************/ + +#define BITS_PER_LONG (__SIZEOF_LONG__ * 8) + + +/********************************** + ** linux/bitops.h, asm/bitops.h ** + **********************************/ + +#define BITS_PER_BYTE 8 +#define BIT(nr) (1UL << (nr)) +#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long)) + +#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)) + +#define smp_mb__before_clear_bit() +#define smp_mb__after_clear_bit() smp_mb() + +/** + * Find first zero bit (limit to machine word size) + */ +long find_next_zero_bit_le(const void *addr, + unsigned long size, unsigned long offset); + + +#include +#include +#include +#include +#include + +static inline unsigned fls_long(unsigned long l) +{ + if (sizeof(l) == 4) + return fls(l); + return fls64(l); +} + +static inline unsigned long __ffs64(u64 word) +{ +#if BITS_PER_LONG == 32 + if (((u32)word) == 0UL) + return __ffs((u32)(word >> 32)) + 32; +#elif BITS_PER_LONG != 64 +#error BITS_PER_LONG not 32 or 64 +#endif + return __ffs((unsigned long)word); +} + +#include + +#define for_each_set_bit(bit, addr, size) \ + for ((bit) = find_first_bit((addr), (size)); \ + (bit) < (size); \ + (bit) = find_next_bit((addr), (size), (bit) + 1)) + +static inline int get_bitmask_order(unsigned int count) { + return __builtin_clz(count) ^ 0x1f; } + +static inline __s32 sign_extend32(__u32 value, int index) +{ + __u8 shift = 31 - index; + return (__s32)(value << shift) >> shift; +} + +static inline __u32 rol32(__u32 word, unsigned int shift) +{ + return (word << shift) | (word >> (32 - shift)); +} + +static inline __u32 ror32(__u32 word, unsigned int shift) +{ + return (word >> shift) | (word << (32 - shift)); +} + +static inline __u16 ror16(__u16 word, unsigned int shift) +{ + return (word >> shift) | (word << (16 - shift)); +} + diff --git a/repos/dde_linux/src/include/lx_emul/bug.h b/repos/dde_linux/src/include/lx_emul/bug.h new file mode 100644 index 000000000..48fa6e078 --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/bug.h @@ -0,0 +1,40 @@ +/* + * \brief Linux kernel API + * \author Norman Feske + * \author Sebastian Sumpf + * \author Josef Soentgen + * \date 2014-08-21 + * + * Based on the prototypes found in the Linux kernel's 'include/'. + */ + +/* + * Copyright (C) 2014 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. + */ + +/*************** + ** asm/bug.h ** + ***************/ + +#define WARN_ON(condition) ({ \ + int ret = !!(condition); \ + if (ret) lx_printf("[%s] WARN_ON(" #condition ") ", __func__); \ + ret; }) + +#define WARN(condition, fmt, arg...) ({ \ + int ret = !!(condition); \ + if (ret) lx_printf("[%s] *WARN* " fmt , __func__ , ##arg); \ + ret; }) + +#define BUG() do { \ + lx_printf("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) diff --git a/repos/dde_linux/src/include/lx_emul/byteorder.h b/repos/dde_linux/src/include/lx_emul/byteorder.h new file mode 100644 index 000000000..1ad816084 --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/byteorder.h @@ -0,0 +1,48 @@ +/* + * \brief Linux kernel API + * \author Norman Feske + * \author Sebastian Sumpf + * \author Josef Soentgen + * \date 2014-08-21 + * + * Based on the prototypes found in the Linux kernel's 'include/'. + */ + +/* + * Copyright (C) 2014 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/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_le16s __cpu_to_le16s +#define cpu_to_be16 __cpu_to_be16 +#define cpu_to_le32 __cpu_to_le32 +#define cpu_to_be32 __cpu_to_be32 +#define cpu_to_le32s __cpu_to_le32s +#define cpu_to_le64 __cpu_to_le64 +#define le16_to_cpup __le16_to_cpup +#define be16_to_cpup __be16_to_cpup +#define le32_to_cpup __le32_to_cpup +#define le32_to_cpus __le32_to_cpus +#define be32_to_cpup __be32_to_cpup +#define le64_to_cpu __le64_to_cpu diff --git a/repos/dde_linux/src/include/lx_emul/compiler.h b/repos/dde_linux/src/include/lx_emul/compiler.h new file mode 100644 index 000000000..5a9dbc3a4 --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/compiler.h @@ -0,0 +1,70 @@ +/* + * \brief Linux kernel API + * \author Norman Feske + * \author Sebastian Sumpf + * \author Josef Soentgen + * \date 2014-08-21 + * + * Based on the prototypes found in the Linux kernel's 'include/'. + */ + +/* + * Copyright (C) 2014 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/compiler.h ** + **********************/ + +#define likely +#define unlikely + +#define __user +#define __iomem +#define __rcu +#define __percpu +#define __must_check +#define __force +#define __read_mostly + +#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 __acquire(x) (void)0 +# define __release(x) (void)0 + +#define __must_check + +#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x)) + +#define __attribute_const__ +#undef __always_inline +#define __always_inline +#undef __unused + +#define noinline __attribute__((noinline)) + +#define __printf(a, b) __attribute__((format(printf, a, b))) + +#define __always_unused +#define __read_mostly + +#define __noreturn __attribute__((noreturn)) + + +/************************** + ** linux/compiler-gcc.h ** + **************************/ + +#ifndef __packed +#define __packed __attribute__((packed)) +#endif + +#define uninitialized_var(x) x = x + diff --git a/repos/dde_linux/src/include/lx_emul/errno.h b/repos/dde_linux/src/include/lx_emul/errno.h new file mode 100644 index 000000000..341242ab7 --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/errno.h @@ -0,0 +1,126 @@ +/* + * \brief Linux kernel API + * \author Norman Feske + * \author Sebastian Sumpf + * \author Josef Soentgen + * \date 2014-08-21 + * + * Based on the prototypes found in the Linux kernel's 'include/'. + */ + +/* + * Copyright (C) 2014 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/errno.h and friends ** + *******************************/ + +/** + * Error codes + * + * Note that the codes do not correspond to those of the Linux kernel. + */ +enum { + /* + * The following numbers correspond to FreeBSD + */ + EPERM = 1, + ENOENT = 2, + ESRCH = 3, + EINTR = 4, + EIO = 5, + ENXIO = 6, + E2BIG = 7, + EDEADLK = 11, + ENOMEM = 12, + EACCES = 13, + EFAULT = 14, + EBUSY = 16, + EEXIST = 17, + EXDEV = 18, + ENODEV = 19, + EINVAL = 22, + ENFILE = 23, + EFBIG = 27, + ENOSPC = 28, + ESPIPE = 29, + EPIPE = 32, + EDOM = 33, + ERANGE = 34, + EAGAIN = 35, + EINPROGRESS = 36, + EALREADY = 37, + ENOTSOCK = 38, + EDESTADDRREQ = 39, + EMSGSIZE = 40, + ENOPROTOOPT = 42, + EPROTONOSUPPORT = 43, + ESOCKTNOSUPPORT = 44, + EOPNOTSUPP = 45, + EPFNOSUPPORT = 46, + EAFNOSUPPORT = 47, + EADDRINUSE = 48, + EADDRNOTAVAIL = 49, + ENETDOWN = 50, + ENETUNREACH = 51, + ECONNABORTED = 53, + ECONNRESET = 54, + ENOBUFS = 55, + EISCONN = 56, + ENOTCONN = 57, + ETIMEDOUT = 60, + ECONNREFUSED = 61, + ENAMETOOLONG = 63, + EHOSTDOWN = 64, + EHOSTUNREACH = 65, + ENOSYS = 78, + ENOMSG = 83, + EOVERFLOW = 84, + ECANCELED = 85, + EILSEQ = 86, + EBADMSG = 89, + ENOLINK = 91, + EPROTO = 92, + + /* + * The following numbers correspond to nothing + */ + EREMOTEIO = 200, + ERESTARTSYS = 201, + ENODATA = 202, + ETOOSMALL = 203, + ENOIOCTLCMD = 204, + ENONET = 205, + ENOTSUPP = 206, + ENOTUNIQ = 207, + ERFKILL = 208, + ETIME = 209, + + MAX_ERRNO = 4095, +}; + + + /***************** + ** linux/err.h ** + *****************/ + +#define IS_ERR_VALUE(x) unlikely((x) >= (unsigned long)-MAX_ERRNO) + +static inline bool IS_ERR(void const *ptr) { + return (unsigned long)(ptr) > (unsigned long)(-1000); } + +static inline void * ERR_PTR(long error) { + return (void *) error; } + +static inline void * ERR_CAST(const void *ptr) { + return (void *) ptr; } + +static inline long IS_ERR_OR_NULL(const void *ptr) { + return !ptr || IS_ERR_VALUE((unsigned long)ptr); } + +static inline long PTR_ERR(const void *ptr) { return (long) ptr; } + diff --git a/repos/dde_linux/src/include/lx_emul/extern_c_begin.h b/repos/dde_linux/src/include/lx_emul/extern_c_begin.h new file mode 100644 index 000000000..a880be195 --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/extern_c_begin.h @@ -0,0 +1,30 @@ +/* + * \brief Include before including Linux headers in C++ + * \author Christian Helmuth + * \date 2014-08-21 + */ + +/* + * Copyright (C) 2014 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. + */ + +#ifdef __cplusplus + +#define extern_c_begin + +extern "C" { + +/* some warnings should only be switched of for Linux headers */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpointer-arith" +#pragma GCC diagnostic ignored "-Wsign-compare" + +/* deal with C++ keywords used for identifiers etc. */ +#define private private_ +#define class class_ +#define new new_ + +#endif /* __cplusplus */ diff --git a/repos/dde_linux/src/include/lx_emul/extern_c_end.h b/repos/dde_linux/src/include/lx_emul/extern_c_end.h new file mode 100644 index 000000000..f9aa11ad1 --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/extern_c_end.h @@ -0,0 +1,24 @@ +/* + * \brief Include after including Linux headers in C++ + * \author Christian Helmuth + * \date 2014-08-21 + */ + +/* + * Copyright (C) 2014 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. + */ + +#ifdef __cplusplus + +#undef new +#undef class +#undef private + +#pragma GCC diagnostic pop + +} /* extern "C" */ + +#endif /* __cplusplus */ diff --git a/repos/dde_linux/src/include/lx_emul/gfp.h b/repos/dde_linux/src/include/lx_emul/gfp.h new file mode 100644 index 000000000..6f385ef8e --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/gfp.h @@ -0,0 +1,58 @@ +/* + * \brief Linux kernel API + * \author Norman Feske + * \author Sebastian Sumpf + * \author Josef Soentgen + * \date 2014-08-21 + * + * Based on the prototypes found in the Linux kernel's 'include/'. + */ + +/* + * Copyright (C) 2014 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/gfp.h ** + *****************/ + +enum { + __GFP_DMA = 0x00000001u, + __GFP_HIGHMEM = 0x00000002u, + __GFP_DMA32 = 0x00000004u, + __GFP_MOVABLE = 0x00000008u, + __GFP_WAIT = 0x00000010u, + __GFP_HIGH = 0x00000020u, + __GFP_IO = 0x00000040u, + __GFP_FS = 0x00000080u, + __GFP_COLD = 0x00000100u, + __GFP_NOWARN = 0x00000200u, + __GFP_REPEAT = 0x00000400u, + __GFP_NOFAIL = 0x00000800u, + __GFP_NORETRY = 0x00001000u, + __GFP_MEMALLOC = 0x00002000u, + __GFP_COMP = 0x00004000u, + __GFP_ZERO = 0x00008000u, + __GFP_NOMEMALLOC = 0x00010000u, + __GFP_HARDWALL = 0x00020000u, + __GFP_THISNODE = 0x00040000u, + __GFP_RECLAIMABLE = 0x00080000u, + __GFP_KMEMCG = 0x00100000u, + __GFP_NOTRACK = 0x00200000u, + __GFP_NO_KSWAPD = 0x00400000u, + __GFP_OTHER_NODE = 0x00800000u, + __GFP_WRITE = 0x01000000u, + + GFP_LX_DMA = 0x80000000u, + + GFP_ATOMIC = __GFP_HIGH, + GFP_DMA = __GFP_DMA, + GFP_DMA32 = __GFP_DMA32, + GFP_KERNEL = __GFP_WAIT | __GFP_IO | __GFP_FS, + GFP_USER = __GFP_WAIT | __GFP_IO | __GFP_FS | __GFP_HARDWALL, + GFP_HIGHUSER = __GFP_WAIT | __GFP_IO | __GFP_FS | __GFP_HARDWALL | + __GFP_HIGHMEM, +}; diff --git a/repos/dde_linux/src/include/lx_emul/impl/completion.h b/repos/dde_linux/src/include/lx_emul/impl/completion.h new file mode 100644 index 000000000..5fdac72f6 --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/impl/completion.h @@ -0,0 +1,112 @@ +/* + * \brief Implementation of linux/completion.h + * \author Norman Feske + * \date 2015-09-09 + */ + +/* + * Copyright (C) 2015 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. + */ + +typedef Lx::Task::List_element Wait_le; +typedef Lx::Task::List Wait_list; + + +void init_waitqueue_head(wait_queue_head_t *wq) +{ + wq->list = new (Genode::env()->heap()) Wait_list; +} + + +int waitqueue_active(wait_queue_head_t *wq) +{ + Wait_list *list = static_cast(wq->list); + if (!list) + return 0; + + return list->first() ? 1 : 0; +} + + +void __wake_up(wait_queue_head_t *wq, bool all) +{ + Wait_list *list = static_cast(wq->list); + if (!list) { + PWRN("wait_queue_head_t is empty, wq: %p called from: %p", wq, __builtin_return_address(0)); + return; + } + + Wait_le *le = list->first(); + do { + if (!le) + return; + + le->object()->unblock(); + } while (all && (le = le->next())); +} + + +void wake_up_interruptible_sync_poll(wait_queue_head_t *wq, int) +{ + __wake_up(wq, false); +} + + +void __wait_event(wait_queue_head_t wq) +{ + Wait_list *list = static_cast(wq.list); + if (!list) { + PERR("__wait_event(): empty list in wq: %p", &wq); + Genode::sleep_forever(); + } + + Lx::Task *task = Lx::scheduler().current(); + + task->wait_enqueue(list); + task->block_and_schedule(); + task->wait_dequeue(list); +} + + +void init_completion(struct completion *work) +{ + work->done = 0; +} + + +void complete(struct completion *work) +{ + work->done = 1; +} + + +unsigned long wait_for_completion_timeout(struct completion *work, + unsigned long timeout) +{ + __wait_completion(work); + return 1; +} + + +int wait_for_completion_interruptible(struct completion *work) +{ + __wait_completion(work); + return 0; +} + + +long wait_for_completion_interruptible_timeout(struct completion *work, + unsigned long timeout) +{ + __wait_completion(work); + return 1; +} + + +void wait_for_completion(struct completion *work) +{ + __wait_completion(work); +} diff --git a/repos/dde_linux/src/include/lx_emul/impl/delay.h b/repos/dde_linux/src/include/lx_emul/impl/delay.h new file mode 100644 index 000000000..e5a141fc9 --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/impl/delay.h @@ -0,0 +1,30 @@ +/* + * \brief Implementation of linux/delay.h + * \author Norman Feske + * \date 2015-09-09 + */ + +/* + * Copyright (C) 2015 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 + +/* + * XXX We may consider to use the Lx::Timer instead of opening a dedicated + * timer session. + */ +static Timer::Connection _delay_timer; + + +void udelay(unsigned long usecs) { _delay_timer.usleep(usecs); } + + +void msleep(unsigned int msecs) { _delay_timer.msleep(msecs); } + + +void mdelay(unsigned long msecs) { msleep(msecs); } diff --git a/repos/dde_linux/src/include/lx_emul/impl/gfp.h b/repos/dde_linux/src/include/lx_emul/impl/gfp.h new file mode 100644 index 000000000..efd4c34ef --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/impl/gfp.h @@ -0,0 +1,43 @@ +/* + * \brief Implementation of linux/gfp.h + * \author Norman Feske + * \date 2015-09-09 + */ + +/* + * Copyright (C) 2015 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 + + +struct page *alloc_pages(gfp_t gfp_mask, unsigned int order) +{ + struct page *page = (struct page *)kzalloc(sizeof(struct page), 0); + + size_t size = PAGE_SIZE << order; + + page->addr = Lx::Malloc::dma().alloc(size, 12); + + if (!page->addr) { + PERR("alloc_pages: %zu failed", size); + kfree(page); + return 0; + } + + Lx::Addr_to_page_mapping::insert(page); + + atomic_set(&page->_count, 1); + + return page; +} + + +void get_page(struct page *page) +{ + atomic_inc(&page->_count); +} diff --git a/repos/dde_linux/src/include/lx_emul/impl/internal/addr_to_page_mapping.h b/repos/dde_linux/src/include/lx_emul/impl/internal/addr_to_page_mapping.h new file mode 100644 index 000000000..4d507eba8 --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/impl/internal/addr_to_page_mapping.h @@ -0,0 +1,78 @@ +/* + * \brief Address-to-page mapping helper + * \author Sebastian Sumpf + * \author Josef Soentgen + * \author Norman Feske + * \date 2014-10-10 + */ + +/* + * Copyright (C) 2014 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__IMPL__INTERNAL__ADDR_TO_PAGE_MAPPING_H_ +#define _LX_EMUL__IMPL__INTERNAL__ADDR_TO_PAGE_MAPPING_H_ + +/* Linux emulation environment includes */ +#include +#include + +namespace Lx { class Addr_to_page_mapping; } + +class Lx::Addr_to_page_mapping : public Lx::List::Element +{ + private: + + unsigned long _addr { 0 }; + struct page *_page { 0 }; + + static Genode::List *_list() + { + static Genode::List _l; + return &_l; + } + + public: + + Addr_to_page_mapping(unsigned long addr, struct page *page) + : _addr(addr), _page(page) { } + + static void insert(struct page *page) + { + Addr_to_page_mapping *m = (Addr_to_page_mapping*) + Lx::Malloc::mem().alloc(sizeof (Addr_to_page_mapping)); + + m->_addr = (unsigned long)page->addr; + m->_page = page; + + _list()->insert(m); + } + + static void remove(struct page *page) + { + Addr_to_page_mapping *mp = 0; + for (Addr_to_page_mapping *m = _list()->first(); m; m = m->next()) + if (m->_page == page) + mp = m; + + if (mp) { + _list()->remove(mp); + Lx::Malloc::mem().free(mp); + } + } + + static struct page* find_page(unsigned long addr) + { + for (Addr_to_page_mapping *m = _list()->first(); m; m = m->next()) + if (m->_addr == addr) + return m->_page; + + return 0; + } +}; + + +#endif /* _LX_EMUL__IMPL__INTERNAL__ADDR_TO_PAGE_MAPPING_H_ */ diff --git a/repos/dde_linux/src/include/lx_emul/impl/internal/debug.h b/repos/dde_linux/src/include/lx_emul/impl/internal/debug.h new file mode 100644 index 000000000..5248d6bea --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/impl/internal/debug.h @@ -0,0 +1,23 @@ +/* + * \brief Debug utilities + * \author Sebastian Sumpf + * \author Josef Soentgen + * \author Norman Feske + * \date 2014-10-10 + */ + +/* + * Copyright (C) 2014 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__IMPL__INTERNAL__DEBUG_H_ +#define _LX_EMUL__IMPL__INTERNAL__DEBUG_H_ + +#ifndef PDBGV +#define PDBGV(...) do { if (verbose) PDBG(__VA_ARGS__); } while (0) +#endif + +#endif /* _LX_EMUL__IMPL__INTERNAL__DEBUG_H_ */ diff --git a/repos/dde_linux/src/include/lx_emul/impl/internal/io_port.h b/repos/dde_linux/src/include/lx_emul/impl/internal/io_port.h new file mode 100644 index 000000000..2975dcd97 --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/impl/internal/io_port.h @@ -0,0 +1,83 @@ +/* + * \brief I/O port access helper + * \author Sebastian Sumpf + * \author Norman Feske + * \date 2014-10-10 + */ + +/* + * Copyright (C) 2014 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__IMPL__INTERNAL__IO_PORT_H_ +#define _LX_EMUL__IMPL__INTERNAL__IO_PORT_H_ + +/* Genode includes */ +#include +#include + +namespace Lx { class Io_port; } + +class Lx::Io_port +{ + private: + + unsigned _base = 0; + unsigned _size = 0; + Genode::Io_port_session_capability _cap; + Genode::Lazy_volatile_object _port; + + bool _valid(unsigned port) { + return _cap.valid() && port >= _base && port < _base + _size; } + + public: + + ~Io_port() + { + if (_cap.valid()) + _port.destruct(); + } + + void session(unsigned base, unsigned size, Genode::Io_port_session_capability cap) + { + _base = base; + _size = size; + _cap = cap; + _port.construct(_cap); + } + + template + bool out(unsigned port, POD val) + { + if (!_valid(port)) + return false; + + switch (sizeof(POD)) { + case 1: _port->outb(port, val); break; + case 2: _port->outw(port, val); break; + case 4: _port->outl(port, val); break; + } + + return true; + } + + template + bool in(unsigned port, POD *val) + { + if (!_valid(port)) + return false;; + + switch (sizeof(POD)) { + case 1: *val = _port->inb(port); break; + case 2: *val = _port->inw(port); break; + case 4: *val = _port->inl(port); break; + } + + return true; + } +}; + +#endif /* _LX_EMUL__IMPL__INTERNAL__IO_PORT_H_ */ diff --git a/repos/dde_linux/src/include/lx_emul/impl/internal/list.h b/repos/dde_linux/src/include/lx_emul/impl/internal/list.h new file mode 100644 index 000000000..e01913ece --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/impl/internal/list.h @@ -0,0 +1,102 @@ +/* + * \brief Slightly improved list + * \author Christian Helmuth + * \date 2014-09-25 + */ + +/* + * Copyright (C) 2014 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__IMPL__INTERNAL__LIST_H_ +#define _LX_EMUL__IMPL__INTERNAL__LIST_H_ + +#include + + +namespace Lx { + template class List; + template class List_element; +} + +template +class Lx::List : private Genode::List +{ + private: + + typedef Genode::List Base; + + public: + + using Base::Element; + + void append(LT const *le) + { + LT *at = nullptr; + + for (LT *l = first(); l; l = l->next()) + at = l; + + Base::insert(le, at); + } + + void prepend(LT const *le) + { + Base::insert(le); + } + + void insert_before(LT const *le, LT const *at) + { + if (at == first()) { + prepend(le); + return; + } else if (!at) { + append(le); + return; + } + + for (LT *l = first(); l; l = l->next()) + if (l->next() == at) + at = l; + + Base::insert(le, at); + } + + + /**************************** + ** Genode::List interface ** + ****************************/ + + LT *first() { return Base::first(); } + LT const *first() const { return Base::first(); } + + void insert(LT const *le, LT const *at = 0) + { + Base::insert(le, at); + } + + void remove(LT const *le) + { + Base::remove(le); + } +}; + + +template +class Lx::List_element : public Lx::List >::Element +{ + private: + + T *_object; + + public: + + List_element(T *object) : _object(object) { } + + T *object() const { return _object; } +}; + +#endif /* _LX_EMUL__IMPL__INTERNAL__LIST_H_ */ diff --git a/repos/dde_linux/src/include/lx_emul/impl/internal/malloc.h b/repos/dde_linux/src/include/lx_emul/impl/internal/malloc.h new file mode 100644 index 000000000..5d5bf576a --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/impl/internal/malloc.h @@ -0,0 +1,208 @@ +/* + * \brief Linux kernel memory allocator + * \author Sebastian Sumpf + * \author Josef Soentgen + * \author Norman Feske + * \date 2014-10-10 + */ + +/* + * Copyright (C) 2014 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__IMPL__INTERNAL__MALLOC_H_ +#define _LX_EMUL__IMPL__INTERNAL__MALLOC_H_ + +#include +#include + +namespace Lx { class Malloc; } + + +class Lx::Malloc +{ + private: + + enum { + SLAB_START_LOG2 = 3, /* 8 B */ + SLAB_STOP_LOG2 = 16, /* 64 KiB */ + NUM_SLABS = (SLAB_STOP_LOG2 - SLAB_START_LOG2) + 1, + }; + + typedef Genode::addr_t addr_t; + typedef Lx::Slab_alloc Slab_alloc; + typedef Lx::Slab_backend_alloc Slab_backend_alloc; + + Slab_backend_alloc &_back_allocator; + Slab_alloc *_allocator[NUM_SLABS]; + Genode::Cache_attribute _cached; /* cached or un-cached memory */ + addr_t _start; /* VM region of this allocator */ + addr_t _end; + + /** + * Set 'value' at 'addr' + */ + void _set_at(addr_t addr, addr_t value) { *((addr_t *)addr) = value; } + + /** + * Retrieve slab index belonging to given address + */ + unsigned _slab_index(Genode::addr_t **addr) + { + using namespace Genode; + /* get index */ + addr_t index = *(*addr - 1); + + /* + * If index large, we use aligned memory, retrieve beginning of slab entry + * and read index from there + */ + if (index > 32) { + *addr = (addr_t *)*(*addr - 1); + index = *(*addr - 1); + } + + return index; + } + + /** + * Get the originally requested size of the allocation + */ + size_t _get_orig_size(Genode::addr_t **addr) + { + using namespace Genode; + + addr_t index = *(*addr - 1); + if (index > 32) { + *addr = (addr_t *) * (*addr - 1); + } + + return *(*addr - 2); + } + + public: + + Malloc(Slab_backend_alloc &alloc, Genode::Cache_attribute cached) + : + _back_allocator(alloc), _cached(cached), _start(alloc.start()), + _end(alloc.end()) + { + /* init slab allocators */ + for (unsigned i = SLAB_START_LOG2; i <= SLAB_STOP_LOG2; i++) + _allocator[i - SLAB_START_LOG2] = new (Genode::env()->heap()) + Slab_alloc(1U << i, alloc); + } + + /** + * Alloc in slabs + */ + void *alloc(Genode::size_t size, int align = 0, Genode::addr_t *phys = 0) + { + using namespace Genode; + + /* save requested size */ + size_t orig_size = size; + size += sizeof(addr_t); + + /* += slab index + aligment size */ + size += sizeof(addr_t) + (align > 2 ? (1 << align) : 0); + + int msb = Genode::log2(size); + + if (size > (1U << msb)) + msb++; + + if (size < (1U << SLAB_START_LOG2)) + msb = SLAB_STOP_LOG2; + + if (msb > SLAB_STOP_LOG2) { + // PERR("Slab too large %u reqested %zu cached %d", 1U << msb, size, _cached); + return 0; + } + + addr_t addr = _allocator[msb - SLAB_START_LOG2]->alloc(); + if (!addr) { + PERR("Failed to get slab for %u", 1 << msb); + return 0; + } + + _set_at(addr, orig_size); + addr += sizeof(addr_t); + + _set_at(addr, msb - SLAB_START_LOG2); + addr += sizeof(addr_t); + + if (align > 2) { + /* save */ + addr_t ptr = addr; + addr_t align_val = (1U << align); + addr_t align_mask = align_val - 1; + /* align */ + addr = (addr + align_val) & ~align_mask; + /* write start address before aligned address */ + _set_at(addr - sizeof(addr_t), ptr); + } + + if (phys) + *phys = _back_allocator.phys_addr(addr); + return (addr_t *)addr; + } + + void free(void const *a) + { + using namespace Genode; + addr_t *addr = (addr_t *)a; + + /* XXX changes addr */ + unsigned nr = _slab_index(&addr); + /* we need to decrease addr by 2, orig_size and index come first */ + _allocator[nr]->free((void *)(addr - 2)); + } + + size_t size(void const *a) + { + using namespace Genode; + addr_t *addr = (addr_t *)a; + + /* XXX changes addr */ + return _get_orig_size(&addr); + } + + Genode::addr_t phys_addr(void *a) + { + return _back_allocator.phys_addr((addr_t)a); + } + + Genode::addr_t virt_addr(Genode::addr_t phys) + { + return _back_allocator.virt_addr(phys); + } + + /** + * Belongs given address to this allocator + */ + bool inside(addr_t const addr) const { return (addr > _start) && (addr <= _end); } + + /** + * Cached memory allocator + */ + static Malloc & mem() + { + static Malloc inst(Slab_backend_alloc::mem(), Genode::CACHED); + return inst; + } + + /** + * DMA memory allocator + */ + static Malloc & dma() + { + static Malloc inst(Slab_backend_alloc::dma(), Genode::UNCACHED); + return inst; + } +}; + +#endif /* _LX_EMUL__IMPL__INTERNAL__MALLOC_H_ */ diff --git a/repos/dde_linux/src/include/lx_emul/impl/internal/mapped_io_mem_range.h b/repos/dde_linux/src/include/lx_emul/impl/internal/mapped_io_mem_range.h new file mode 100644 index 000000000..3039d172a --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/impl/internal/mapped_io_mem_range.h @@ -0,0 +1,112 @@ +/* + * \brief Representation of a locally-mapped MMIO range + * \author Norman Feske + * \date 2015-09-09 + */ + +/* + * Copyright (C) 2015 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__IMPL__INTERNAL__MAPPED_IO_MEM_RANGE_H_ +#define _LX_EMUL__IMPL__INTERNAL__MAPPED_IO_MEM_RANGE_H_ + +/* Genode includes */ +#include +#include + +/* Linux emulation environment includes */ +#include + +namespace Lx { + + class Mapped_io_mem_range; + + void *ioremap(resource_size_t, unsigned long, Genode::Cache_attribute); +} + +/** + * Representation of a locally-mapped MMIO range + * + * This class is supposed to be a private utility to support 'ioremap'. + */ +class Lx::Mapped_io_mem_range : public Lx::List::Element +{ + private: + + Genode::Attached_dataspace _ds; + + Genode::size_t const _size; + Genode::addr_t const _phys; + Genode::addr_t const _virt; + + public: + + Mapped_io_mem_range(Genode::addr_t phys, Genode::size_t size, + Genode::Io_mem_dataspace_capability ds_cap) + : + _ds(ds_cap), + _size(size), + _phys(phys), + _virt((Genode::addr_t)_ds.local_addr() | (phys & 0xfffUL)) + { } + + Genode::addr_t phys() const { return _phys; } + Genode::addr_t virt() const { return _virt; } + + /** + * Return true if the mapped range contains the specified sub range + */ + bool contains(Genode::addr_t phys, Genode::size_t size) const + { + return (phys >= _phys) && (phys + size - 1 <= _phys + _size - 1); + } +}; + + +void *Lx::ioremap(resource_size_t phys_addr, unsigned long size, + Genode::Cache_attribute cache_attribute) +{ + using namespace Genode; + + static Lx::List ranges; + + /* search for the requested region within the already mapped ranges */ + for (Lx::Mapped_io_mem_range *r = ranges.first(); r; r = r->next()) { + + if (r->contains(phys_addr, size)) { + void * const virt = (void *)(r->virt() + phys_addr - r->phys()); + PLOG("ioremap: return sub range phys 0x%lx (size %lx) to virt 0x%lx", + (long)phys_addr, (long)size, (long)virt); + return virt; + } + } + + Io_mem_dataspace_capability ds_cap = + Lx::pci_dev_registry()->io_mem(phys_addr, cache_attribute, size); + + if (!ds_cap.valid()) { + + PERR("Failed to request I/O memory: [%zx,%lx)", phys_addr, + phys_addr + size); + return nullptr; + } + + Genode::size_t const ds_size = Genode::Dataspace_client(ds_cap).size(); + + Lx::Mapped_io_mem_range *io_mem = + new (env()->heap()) Lx::Mapped_io_mem_range(phys_addr, ds_size, ds_cap); + + ranges.insert(io_mem); + + PLOG("ioremap: mapped phys 0x%lx (size %lx) to virt 0x%lx", + (long)phys_addr, (long)size, (long)io_mem->virt()); + + addr_t const sub_page_offset = phys_addr & 0xfff; + return (void *)(io_mem->virt() + sub_page_offset); +} + +#endif /* _LX_EMUL__IMPL__INTERNAL__MAPPED_IO_MEM_RANGE_H_ */ diff --git a/repos/dde_linux/src/include/lx_emul/impl/internal/pci_backend_alloc.h b/repos/dde_linux/src/include/lx_emul/impl/internal/pci_backend_alloc.h new file mode 100644 index 000000000..df2804dad --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/impl/internal/pci_backend_alloc.h @@ -0,0 +1,110 @@ +/* + * \brief Backend allocator for DMA-capable memory + * \author Sebastian Sumpf + * \author Josef Soentgen + * \author Norman Feske + * \date 2014-10-10 + */ + +/* + * Copyright (C) 2014 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__IMPL__INTERNAL__PCI_BACKEND_ALLOC_H_ +#define _LX_EMUL__IMPL__INTERNAL__PCI_BACKEND_ALLOC_H_ + +/* Genode includes */ +#include +#include + +/* Linux emulation environment includes */ +#include + +namespace Lx { + + struct Memory_object_base; + struct Ram_object; + struct Dma_object; + + extern Genode::Object_pool memory_pool; +}; + + +struct Lx::Memory_object_base : Genode::Object_pool::Entry +{ + Memory_object_base(Genode::Ram_dataspace_capability cap) + : Genode::Object_pool::Entry(cap) {} + virtual ~Memory_object_base() {}; + + virtual void free() = 0; + + Genode::Ram_dataspace_capability ram_cap() + { + using namespace Genode; + return reinterpret_cap_cast(cap()); + } +}; + + +struct Lx::Ram_object : Memory_object_base +{ + Ram_object(Genode::Ram_dataspace_capability cap) + : Memory_object_base(cap) {} + + void free() { Genode::env()->ram_session()->free(ram_cap()); } +}; + + +struct Lx::Dma_object : Memory_object_base +{ + Dma_object(Genode::Ram_dataspace_capability cap) + : Memory_object_base(cap) {} + + void free() { Lx::pci()->free_dma_buffer(ram_cap()); } +}; + + +Genode::Ram_dataspace_capability +Lx::backend_alloc(Genode::addr_t size, Genode::Cache_attribute cached) +{ + using namespace Genode; + + Memory_object_base *o; + Genode::Ram_dataspace_capability cap; + if (cached == CACHED) { + cap = env()->ram_session()->alloc(size); + o = new (env()->heap()) Ram_object(cap); + } else { + /* transfer quota to pci driver, otherwise it will give us a exception */ + char buf[32]; + Genode::snprintf(buf, sizeof(buf), "ram_quota=%ld", size); + Genode::env()->parent()->upgrade(Lx::pci()->cap(), buf); + + cap = Lx::pci()->alloc_dma_buffer(size); + o = new (env()->heap()) Dma_object(cap); + } + + memory_pool.insert(o); + return cap; +} + + +void Lx::backend_free(Genode::Ram_dataspace_capability cap) +{ + using namespace Genode; + + Memory_object_base *o = memory_pool.lookup_and_lock(cap); + if (!o) + return; + + o->free(); + memory_pool.remove_locked(o); + destroy(env()->heap(), o); +} + + +#endif /* _LX_EMUL__IMPL__INTERNAL__PCI_BACKEND_ALLOC_H_ */ + diff --git a/repos/dde_linux/src/include/lx_emul/impl/internal/pci_dev.h b/repos/dde_linux/src/include/lx_emul/impl/internal/pci_dev.h new file mode 100644 index 000000000..8d882b6ea --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/impl/internal/pci_dev.h @@ -0,0 +1,241 @@ +/* + * \brief Emulate 'pci_dev' structure + * \author Sebastian Sumpf + * \author Josef Soentgen + * \author Norman Feske + * \date 2014-10-10 + */ + +/* + * Copyright (C) 2014 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__IMPL__INTERNAL__PCI_DEV_H_ +#define _LX_EMUL__IMPL__INTERNAL__PCI_DEV_H_ + +/* Genode includes */ +#include +#include +#include +#include +#include +#include + +/* Linux emulation environment includes */ +#include +#include +#include + +namespace Lx { + + class Pci_dev; + + /** + * Return singleton 'Platform::Connection' + * + * Implementation must be privided by the driver. + */ + Platform::Connection *pci(); + + template + static inline void for_each_pci_device(FUNC const &func); +} + + +class Lx::Pci_dev : public pci_dev, public Lx::List::Element +{ + private: + + bool const verbose = true; + + Platform::Device_client _client; + + Io_port _io_port; + + /* offset used in PCI config space */ + enum Pci_config { IRQ = 0x3c, REV = 0x8, CMD = 0x4, + STATUS = 0x4, CAP = 0x34 }; + enum Pci_cap { CAP_LIST = 0x10, CAP_EXP = 0x10, + CAP_EXP_FLAGS = 0x2, CAP_EXP_DEVCAP = 0x4 }; + + template + Platform::Device::Access_size _access_size(T t) + { + switch (sizeof(T)) + { + case 1: + return Platform::Device::ACCESS_8BIT; + case 2: + return Platform::Device::ACCESS_16BIT; + default: + return Platform::Device::ACCESS_32BIT; + } + } + + public: + + /** + * Constructor + */ + Pci_dev(Platform::Device_capability cap) + : + _client(cap) + { + using namespace Platform; + + Genode::memset(static_cast(this), 0, sizeof(pci_dev)); + + this->vendor = _client.vendor_id(); + this->device = _client.device_id(); + this->class_ = _client.class_code(); + this->revision = _client.config_read(REV, Device::ACCESS_8BIT); + + /* dummy dma mask used to mark device as DMA capable */ + this->dev._dma_mask_buf = ~(u64)0; + this->dev.dma_mask = &this->dev._dma_mask_buf; + this->dev.coherent_dma_mask = ~0; + + /* read interrupt line */ + this->irq = _client.config_read(IRQ, Device::ACCESS_8BIT); + + /* hide ourselfs in bus structure */ + this->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); + if (res.type() == Device::Resource::INVALID) + continue; + + this->resource[i].start = res.base(); + this->resource[i].end = res.base() + res.size() - 1; + + unsigned flags = 0; + if (res.type() == Device::Resource::IO) flags |= IORESOURCE_IO; + if (res.type() == Device::Resource::MEMORY) flags |= IORESOURCE_MEM; + this->resource[i].flags = flags; + + PDBGV("this=%p base: %x size: %x type: %u", + this, res.base(), res.size(), res.type()); + + /* request port I/O session */ + if (res.type() == Device::Resource::IO) { + uint8_t const virt_bar = _client.phys_bar_to_virt(i); + _io_port.session(res.base(), res.size(), _client.io_port(virt_bar)); + io = true; + PDBGV("I/O [%u-%u)", + res.base(), res.base() + res.size()); + } + + /* request I/O memory (write combined) */ + if (res.type() == Device::Resource::MEMORY) + PDBGV("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); + + /* get pci express capability */ + this->pcie_cap = 0; + uint16_t status = _client.config_read(STATUS, Device::ACCESS_32BIT) >> 16; + if (status & CAP_LIST) { + uint8_t offset = _client.config_read(CAP, Device::ACCESS_8BIT); + while (offset != 0x00) { + uint8_t value = _client.config_read(offset, Device::ACCESS_8BIT); + + if (value == CAP_EXP) + this->pcie_cap = offset; + + offset = _client.config_read(offset + 1, Device::ACCESS_8BIT); + } + } + + if (this->pcie_cap) { + uint16_t reg_val = _client.config_read(this->pcie_cap, Device::ACCESS_16BIT); + this->pcie_flags_reg = reg_val; + } + } + + /** + * Read/write data from/to config space + */ + template + void config_read(unsigned int devfn, T *val) + { + *val = _client.config_read(devfn, _access_size(*val)); + } + + template + void config_write(unsigned int devfn, T val) + { + _client.config_write(devfn, val, _access_size(val)); + } + + Platform::Device &client() { return _client; } + + Io_port &io_port() { return _io_port; } +}; + + +/** + * Call functor for each available physical PCI device + * + * The functor is called with the device capability as argument. If + * returns true if we can stop iterating. In this case, the device + * is expected to be acquired by the driver. All other devices are + * released at the platform driver. + */ +template +void Lx::for_each_pci_device(FUNC const &func) +{ + /* + * Functor that is called if the platform driver throws a + * 'Quota_exceeded' exception. + */ + auto handler = [&] () { + Genode::env()->parent()->upgrade(Lx::pci()->cap(), + "ram_quota=4096"); }; + + /* + * Obtain first device, the operation may exceed the session quota. + * So we use the 'retry' mechanism. + */ + Platform::Device_capability cap; + auto attempt = [&] () { cap = Lx::pci()->first_device(); }; + Genode::retry(attempt, handler); + + /* + * Iterate over the devices of the platform session. + */ + while (cap.valid()) { + + /* + * Call functor, stop iterating depending on its return value. + */ + if (func(cap)) + break; + + /* + * Release current device and try next one. Upgrade session + * quota on demand. + */ + auto attempt = [&] () { + Platform::Device_capability next_cap = pci()->next_device(cap); + Lx::pci()->release_device(cap); + cap = next_cap; + }; + Genode::retry(attempt, handler); + } +} + +#endif /* _LX_EMUL__IMPL__INTERNAL__PCI_DEV_H_ */ diff --git a/repos/dde_linux/src/include/lx_emul/impl/internal/pci_dev_registry.h b/repos/dde_linux/src/include/lx_emul/impl/internal/pci_dev_registry.h new file mode 100644 index 000000000..12d23fa19 --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/impl/internal/pci_dev_registry.h @@ -0,0 +1,111 @@ +/* + * \brief Registry of PCI devices + * \author Norman Feske + * \date 2015-09-09 + */ + +/* + * Copyright (C) 2015 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__IMPL__INTERNAL__PCI_DEV_REGISTRY_H_ +#define _LX_EMUL__IMPL__INTERNAL__PCI_DEV_REGISTRY_H_ + +/* Linux emulation environment includes */ +#include + +namespace Lx { + + class Pci_dev_registry; + + /** + * Return singleton 'Pci_dev_registry' object + * + * Implementation must be provided by the driver. + */ + Pci_dev_registry *pci_dev_registry(); +} + +class Lx::Pci_dev_registry +{ + private: + + List _devs; + + public: + + void insert(Pci_dev *pci_dev) + { + PDBG("insert pci_dev %p", pci_dev); + _devs.insert(pci_dev); + } + + Genode::Io_mem_dataspace_capability io_mem(resource_size_t phys, + Genode::Cache_attribute cache_attribute, + Genode::size_t size) + { + enum { PCI_ROM_RESOURCE = 6 }; + + for (Pci_dev *d = _devs.first(); d; d = d->next()) { + + unsigned bar = 0; + for (; bar < PCI_ROM_RESOURCE; bar++) { + if ((pci_resource_flags(d, bar) & IORESOURCE_MEM) && + (pci_resource_start(d, bar) == phys)) + break; + } + if (bar >= PCI_ROM_RESOURCE) + continue; + + Platform::Device &device = d->client(); + + unsigned const resource_id = + device.phys_bar_to_virt(bar); + + /* offset from the beginning of the PCI resource */ + Genode::addr_t const offset = + phys - pci_resource_start(d, bar); + + Genode::Io_mem_session_capability io_mem_cap = + device.io_mem(resource_id, cache_attribute, offset, size); + + return Genode::Io_mem_session_client(io_mem_cap).dataspace(); + } + + PERR("Device using i/o memory of address %zx is unknown", phys); + return Genode::Io_mem_dataspace_capability(); + } + + template + T io_read(unsigned port) + { + PDBG("io_read %u", port); + /* try I/O access on all PCI devices */ + for (Pci_dev *d = _devs.first(); d; d = d->next()) { + T value = 0; + if (d->io_port().in(port, &value)) + return value; + } + + PWRN("I/O port(%u) read failed", port); + return (T)~0; + } + + template + void io_write(unsigned port, T value) + { + PDBG("io_write %u", port); + + /* try I/O access on all PCI devices, return on first success */ + for (Pci_dev *d = _devs.first(); d; d = d->next()) + if (d->io_port().out(port, value)) + return; + + PWRN("I/O port(%u) write failed", port); + } +}; + +#endif /* _LX_EMUL__IMPL__INTERNAL__PCI_DEV_REGISTRY_H_ */ diff --git a/repos/dde_linux/src/include/lx_emul/impl/internal/scheduler.h b/repos/dde_linux/src/include/lx_emul/impl/internal/scheduler.h new file mode 100644 index 000000000..65358dedb --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/impl/internal/scheduler.h @@ -0,0 +1,230 @@ +/* + * \brief Scheduler for executing Lx::Task objects + * \author Sebastian Sumpf + * \author Josef Soentgen + * \author Norman Feske + * \date 2014-10-10 + */ + +/* + * Copyright (C) 2014 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__IMPL__INTERNAL__SCHEDULER_H_ +#define _LX_EMUL__IMPL__INTERNAL__SCHEDULER_H_ + +/* Genode includes */ +#include +#include +#include +#include +#include + +/* Linux emulation environment includes */ +#include +#include + +namespace Lx { + + class Scheduler; + + /** + * Return singleton instance of the scheduler + * + * Implementation must be provided by the driver. + */ + Scheduler &scheduler(); + + /** + * Called each time when a scheduling decision is taken + * + * Must be provided by the compilation unit that includes 'scheduler.h', + * e.g., by also including 'timer.h'. + */ + static inline void timer_update_jiffies(); +} + + +class Lx::Scheduler +{ + private: + + bool verbose = true; + + Lx::List _present_list; + Genode::Lock _present_list_mutex; + + Task *_current = nullptr; /* currently scheduled task */ + + bool _run_task(Task *); + + /* + * Support for logging + */ + + static inline char const *_ansi_esc_reset() { return "\033[00m"; } + static inline char const *_ansi_esc_black() { return "\033[30m"; } + static inline char const *_ansi_esc_red() { return "\033[31m"; } + static inline char const *_ansi_esc_yellow() { return "\033[33m"; } + + static inline char const *_state_color(Lx::Task::State state) + { + switch (state) { + case Lx::Task::STATE_INIT: return _ansi_esc_reset(); + case Lx::Task::STATE_RUNNING: return _ansi_esc_red(); + case Lx::Task::STATE_BLOCKED: return _ansi_esc_yellow(); + case Lx::Task::STATE_MUTEX_BLOCKED: return _ansi_esc_yellow(); + case Lx::Task::STATE_WAIT_BLOCKED: return _ansi_esc_yellow(); + } + + return _ansi_esc_black(); + } + + struct Logger : Genode::Thread<0x4000> + { + Timer::Connection _timer; + Lx::Scheduler &_scheduler; + unsigned const _interval; + + Logger(Lx::Scheduler &scheduler, unsigned interval_seconds) + : + Genode::Thread<0x4000>("logger"), + _scheduler(scheduler), _interval(interval_seconds) + { + start(); + } + + void entry() + { + PWRN("Scheduler::Logger is up"); + _timer.msleep(1000 * _interval); + while (true) { + _scheduler.log_state("LOGGER"); + _timer.msleep(2000); + } + } + }; + + public: + + Scheduler() + { + if (verbose) + new (Genode::env()->heap()) Logger(*this, 10); + } + + /** + * Return currently scheduled task + */ + Task *current() + { + if (!_current) { + PERR("BUG: _current is zero!"); + Genode::sleep_forever(); + } + + return _current; + } + + /** + * Add new task to the present list + */ + void add(Task *task) + { + Lx::Task *p = _present_list.first(); + for ( ; p; p = p->next()) { + if (p->priority() <= task->priority()) { + _present_list.insert_before(task, p); + break; + } + } + if (!p) + _present_list.append(task); + } + + /** + * Schedule all present tasks + * + * Returns if no task is runnable. + */ + void schedule() + { + bool at_least_one = false; + + /* + * Iterate over all tasks and run first runnable. + * + * (1) If one runnable tasks was run start over from beginning of + * list. + * + * (2) If no task is runnable quit scheduling (break endless + * loop). + */ + while (true) { + /* update jiffies before running task */ + Lx::timer_update_jiffies(); + + bool was_run = false; + for (Task *t = _present_list.first(); t; t = t->next()) { + /* update current before running task */ + _current = t; + + if ((was_run = t->run())) { + at_least_one = true; + break; + } + } + if (!was_run) + break; + } + + if (!at_least_one) { + PWRN("schedule() called without runnable tasks"); + log_state("SCHEDULE"); + } + + /* clear current as no task is running */ + _current = nullptr; + } + + /** + * Log current state of tasks in present list (debug) + * + * Log lines are prefixed with 'prefix'. + */ + void log_state(char const *prefix) + { + unsigned i; + Lx::Task *t; + for (i = 0, t = _present_list.first(); t; t = t->next(), ++i) { + Genode::printf("%s [%u] prio: %u state: %s%u%s %s\n", + prefix, i, t->priority(), _state_color(t->state()), + t->state(), _ansi_esc_reset(), t->name()); + } + } +}; + + +Lx::Task::Task(void (*func)(void*), void *arg, char const *name, + Priority priority, Scheduler &scheduler) +: + _priority(priority), _scheduler(scheduler), + _func(func), _arg(arg), _name(name) +{ + scheduler.add(this); + + PDBGV("name: '%s' func: %p arg: %p prio: %u t: %p", name, func, arg, priority, this); +} + + +void Lx::Task::_deinit() +{ + if (_stack) + Genode::Thread_base::myself()->free_secondary_stack(_stack); +} + + +#endif /* _LX_EMUL__IMPL__INTERNAL__SCHEDULER_H_ */ diff --git a/repos/dde_linux/src/include/lx_emul/impl/internal/slab_alloc.h b/repos/dde_linux/src/include/lx_emul/impl/internal/slab_alloc.h new file mode 100644 index 000000000..7aaa1ccc7 --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/impl/internal/slab_alloc.h @@ -0,0 +1,58 @@ +/* + * \brief Slab allocator using our back-end allocator + * \author Sebastian Sumpf + * \author Josef Soentgen + * \author Norman Feske + * \date 2014-10-10 + */ + +/* + * Copyright (C) 2014 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__IMPL__INTERNAL__SLAB_ALLOC_H_ +#define _LX_EMUL__IMPL__INTERNAL__SLAB_ALLOC_H_ + +/* Genode includes */ +#include + +/* Linux emulation environment includes */ +#include + +namespace Lx { class Slab_alloc; } + +class Lx::Slab_alloc : public Genode::Slab +{ + private: + + /* + * Each slab block in the slab contains about 8 objects (slab entries) + * as proposed in the paper by Bonwick and block sizes are multiples of + * page size. + */ + static size_t _calculate_block_size(size_t object_size) + { + size_t block_size = 8 * (object_size + sizeof(Genode::Slab_entry)) + + sizeof(Genode::Slab_block); + return Genode::align_addr(block_size, 12); + } + + public: + + Slab_alloc(size_t object_size, Slab_backend_alloc &allocator) + : Slab(object_size, _calculate_block_size(object_size), 0, &allocator) { } + + /** + * Convenience slabe-entry allocation + */ + Genode::addr_t alloc() + { + Genode::addr_t result; + return (Slab::alloc(slab_size(), (void **)&result) ? result : 0); + } +}; + +#endif /* _LX_EMUL__IMPL__INTERNAL__SLAB_ALLOC_H_ */ diff --git a/repos/dde_linux/src/include/lx_emul/impl/internal/slab_backend_alloc.h b/repos/dde_linux/src/include/lx_emul/impl/internal/slab_backend_alloc.h new file mode 100644 index 000000000..f0c5450ff --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/impl/internal/slab_backend_alloc.h @@ -0,0 +1,173 @@ + +/* + * \brief Back-end allocator for Genode's slab allocator + * \author Sebastian Sumpf + * \author Josef Soentgen + * \author Norman Feske + * \date 2014-10-10 + */ + +/* + * Copyright (C) 2014 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__IMPL__INTERNAL__SLAB_BACKEND_ALLOC_H_ +#define _LX_EMUL__IMPL__INTERNAL__SLAB_BACKEND_ALLOC_H_ + +/* Genode includes */ +#include +#include +#include +#include + +namespace Lx { + + Genode::Ram_dataspace_capability + backend_alloc(Genode::addr_t size, Genode::Cache_attribute cached); + + void backend_free(Genode::Ram_dataspace_capability cap); + class Slab_backend_alloc; +} + +class Lx::Slab_backend_alloc : public Genode::Allocator, + public Genode::Rm_connection +{ + private: + + typedef Genode::addr_t addr_t; + + enum { + VM_SIZE = 24 * 1024 * 1024, /* size of VM region to reserve */ + BLOCK_SIZE = 1024 * 1024, /* 1 MiB */ + ELEMENTS = VM_SIZE / BLOCK_SIZE, /* MAX number of dataspaces in VM */ + }; + + addr_t _base; /* virt. base address */ + Genode::Cache_attribute _cached; /* non-/cached RAM */ + Genode::Ram_dataspace_capability _ds_cap[ELEMENTS]; /* dataspaces to put in VM */ + addr_t _ds_phys[ELEMENTS]; /* physical bases of dataspaces */ + int _index; /* current index in ds_cap */ + Genode::Allocator_avl _range; /* manage allocations */ + + bool _alloc_block() + { + if (_index == ELEMENTS) { + PERR("Slab-backend exhausted!"); + return false; + } + + try { + _ds_cap[_index] = Lx::backend_alloc(BLOCK_SIZE, _cached); + /* attach at index * BLOCK_SIZE */ + Rm_connection::attach_at(_ds_cap[_index], _index * BLOCK_SIZE, BLOCK_SIZE, 0); + + /* lookup phys. address */ + _ds_phys[_index] = Genode::Dataspace_client(_ds_cap[_index]).phys_addr(); + } catch (...) { return false; } + + /* return base + offset in VM area */ + addr_t block_base = _base + (_index * BLOCK_SIZE); + ++_index; + + _range.add_range(block_base, BLOCK_SIZE); + return true; + } + + public: + + Slab_backend_alloc(Genode::Cache_attribute cached) + : + Rm_connection(0, VM_SIZE), + _cached(cached), _index(0), _range(Genode::env()->heap()) + { + /* reserver attach us, anywere */ + _base = Genode::env()->rm_session()->attach(dataspace()); + } + + /** + * Allocate + */ + bool alloc(size_t size, void **out_addr) override + { + bool done = _range.alloc(size, out_addr); + + if (done) + return done; + + done = _alloc_block(); + if (!done) { + PERR("Backend allocator exhausted\n"); + return false; + } + + return _range.alloc(size, out_addr); + } + + void free(void *addr, size_t /* size */) override { } + size_t overhead(size_t size) const override { return 0; } + bool need_size_for_free() const override { return false; } + + /** + * Return phys address for given virtual addr. + */ + addr_t phys_addr(addr_t addr) + { + if (addr < _base || addr >= (_base + VM_SIZE)) + return ~0UL; + + int index = (addr - _base) / BLOCK_SIZE; + + /* physical base of dataspace */ + addr_t phys = _ds_phys[index]; + + if (!phys) + return ~0UL; + + /* add offset */ + phys += (addr - _base - (index * BLOCK_SIZE)); + return phys; + } + + /** + * Translate given physical address to virtual address + * + * \return virtual address, or 0 if no translation exists + */ + addr_t virt_addr(addr_t phys) + { + for (unsigned i = 0; i < ELEMENTS; i++) { + if (_ds_cap[i].valid() && + phys >= _ds_phys[i] && phys < _ds_phys[i] + BLOCK_SIZE) + return _base + i*BLOCK_SIZE + phys - _ds_phys[i]; + } + + PWRN("virt_addr(0x%lx) - no translation", phys); + return 0; + } + + addr_t start() const { return _base; } + addr_t end() const { return _base + VM_SIZE - 1; } + + /** + * Cached memory backend allocator + */ + static Slab_backend_alloc & mem() + { + static Slab_backend_alloc inst(Genode::CACHED); + return inst; + } + + /** + * DMA memory backend allocator + */ + static Slab_backend_alloc & dma() + { + static Slab_backend_alloc inst(Genode::UNCACHED); + return inst; + } +}; + +#endif /* _LX_EMUL__IMPL__INTERNAL__SLAB_BACKEND_ALLOC_H_ */ diff --git a/repos/dde_linux/src/include/lx_emul/impl/internal/task.h b/repos/dde_linux/src/include/lx_emul/impl/internal/task.h new file mode 100644 index 000000000..bcac85d43 --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/impl/internal/task.h @@ -0,0 +1,255 @@ +/* + * \brief Lx::Task represents a cooperatively scheduled thread of control + * \author Sebastian Sumpf + * \author Josef Soentgen + * \author Norman Feske + * \date 2014-10-10 + */ + +/* + * Copyright (C) 2014 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__IMPL__INTERNAL__TASK_H_ +#define _LX_EMUL__IMPL__INTERNAL__TASK_H_ + +/* libc includes */ +#include + +/* Genode includes */ +#include + +/* Linux emulation environment includes */ +#include +#include + +namespace Lx { + + class Scheduler; + class Task; +} + +/** + * Allows pseudo-parallel execution of functions + */ +class Lx::Task : public Lx::List::Element +{ + public: + + /** + * TODO generalize - higher is more important + */ + enum Priority { PRIORITY_0, PRIORITY_1, PRIORITY_2, PRIORITY_3 }; + + /** + * Runtime state + * + * INIT + * | + * [run] + * v + * BLOCKED <--[block]--- RUNNING ---[mutex_block]--> MUTEX_BLOCKED + * --[unblock]-> <-[mutex_unblock]-- + * + * Transitions between BLOCKED and MUTEX_BLOCKED are not possible. + */ + enum State { STATE_INIT, STATE_RUNNING, STATE_BLOCKED, STATE_MUTEX_BLOCKED, STATE_WAIT_BLOCKED }; + + /** + * List element type + */ + typedef Lx::List_element List_element; + + /** + * List type + */ + typedef Lx::List List; + + private: + + bool verbose = true; + + State _state = STATE_INIT; + + /* sub-classes may overwrite the runnable condition */ + virtual bool _runnable() const + { + switch (_state) { + case STATE_INIT: return true; + case STATE_RUNNING: return true; + case STATE_BLOCKED: return false; + case STATE_MUTEX_BLOCKED: return false; + case STATE_WAIT_BLOCKED: return false; + } + + PERR("state %d not handled by switch", _state); + Genode::sleep_forever(); + } + + void *_stack = nullptr; /* stack pointer */ + jmp_buf _env; /* execution state */ + jmp_buf _saved_env; /* saved state of thread calling run() */ + + Priority _priority; + Scheduler &_scheduler; /* scheduler this task is attached to */ + + void (*_func)(void *); /* function to call*/ + void *_arg; /* argument for function */ + char const *_name; /* name of task */ + + List_element _mutex_le { this }; /* list element for mutex_blocked state */ + + List *_wait_list { 0 }; + List_element _wait_le { this }; + bool _wait_le_enqueued { false }; + + inline void _deinit(); + + public: + + inline Task(void (*func)(void*), void *arg, char const *name, + Priority priority, Scheduler &scheduler); + + virtual ~Task() { _deinit(); } + + State state() const { return _state; } + Priority priority() const { return _priority; } + + void wait_enqueue(List *list) + { + if (_wait_le_enqueued) { + PERR("%p already queued in %p", this, _wait_list); + Genode::sleep_forever(); + } + + _wait_le_enqueued = true; + _wait_list = list; + _wait_list->append(&_wait_le); + } + + void wait_dequeue(List *list) + { + if (!_wait_le_enqueued) { + PERR("%p not queued", this); + Genode::sleep_forever(); + } + + if (_wait_list != list) { + PERR("especially not in list %p", list); + Genode::sleep_forever(); + } + + _wait_list->remove(&_wait_le); + _wait_list = 0; + _wait_le_enqueued = false; + } + + /******************************* + ** Runtime state transitions ** + *******************************/ + + void block() + { + if (_state == STATE_RUNNING) { + _state = STATE_BLOCKED; + } + } + + void unblock() + { + if (_state == STATE_BLOCKED) { + _state = STATE_RUNNING; + } + } + + void mutex_block(List *list) + { + if (_state == STATE_RUNNING) { + _state = STATE_MUTEX_BLOCKED; + list->append(&_mutex_le); + } + } + + void mutex_unblock(List *list) + { + if (_state == STATE_MUTEX_BLOCKED) { + _state = STATE_RUNNING; + list->remove(&_mutex_le); + } + } + + /** + * Run task until next preemption point + * + * \return true if run, false if not runnable + */ + bool run() + { + if (!_runnable()) + return false; + + /* + * Save the execution environment. The scheduled task returns to this point + * after execution, i.e., at the next preemption point. + */ + if (_setjmp(_saved_env)) + return true; + + if (_state == STATE_INIT) { + /* setup execution environment and call task's function */ + _state = STATE_RUNNING; + Genode::Thread_base *th = Genode::Thread_base::myself(); + + enum { STACK_SIZE = 32 * 1024 }; /* FIXME make stack size configurable */ + _stack = th->alloc_secondary_stack(_name, STACK_SIZE); + + /* switch stack and call '_func(_arg)' */ + arch_execute(_stack, (void *)_func, _arg); + } else { + /* restore execution environment */ + _longjmp(_env, 1); + } + + /* never reached */ + PERR("Unexpected return of Task"); + Genode::sleep_forever(); + } + + /** + * Request scheduling (of other tasks) + * + * Note, this task may not be blocked when calling schedule() depending + * on the use case. + */ + void schedule() + { + /* + * Save the execution environment. The task will resume from here on next + * schedule. + */ + if (_setjmp(_env)) + return; + + /* return to thread calling run() */ + _longjmp(_saved_env, 1); + } + + /** + * Shortcut to enter blocking state and request scheduling + */ + void block_and_schedule() + { + block(); + schedule(); + } + + /** + * Return the name of the task (mainly for debugging purposes) + */ + char const *name() { return _name; } +}; + +#endif /* _LX_EMUL__IMPL__INTERNAL__TASK_H_ */ diff --git a/repos/dde_linux/src/include/lx_emul/impl/internal/timer.h b/repos/dde_linux/src/include/lx_emul/impl/internal/timer.h new file mode 100644 index 000000000..6ea712168 --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/impl/internal/timer.h @@ -0,0 +1,313 @@ +/* + * \brief Timer + * \author Sebastian Sumpf + * \author Josef Soentgen + * \author Norman Feske + * \date 2014-10-10 + */ + +/* + * Copyright (C) 2014 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__IMPL__INTERNAL__TIMER_H_ +#define _LX_EMUL__IMPL__INTERNAL__TIMER_H_ + +/* Genode includes */ +#include +#include +#include + +/* Linux emulation environment includes */ +#include + +namespace Lx { + + class Timer; + + /** + * Return singleton instance of timer + * + * \param ep entrypoint used handle timeout signals, + * to be specified at the first call of the function, + * which implicitly initializes the timer + * \param jiffies_ptr pointer to jiffies counter to be periodically + * updated + */ + Timer &timer(Server::Entrypoint *ep = nullptr, + unsigned long *jiffies_ptr = nullptr); + + /** + * Blue-print implementation of 'timer' function + */ + static inline Timer &_timer_impl(Server::Entrypoint *ep, + unsigned long *jiffies_ptr); + + static inline void timer_update_jiffies(); + + static inline void run_timer(void *); +} + + +class Lx::Timer +{ + public: + + /** + * Context encapsulates a regular linux timer_list + */ + struct Context : public Lx::List::Element + { + enum { INVALID_TIMEOUT = ~0UL }; + + struct timer_list *timer; + bool pending { false }; + unsigned long timeout { INVALID_TIMEOUT }; /* absolute in jiffies */ + bool programmed { false }; + + Context(struct timer_list *timer) : timer(timer) { } + }; + + private: + + + unsigned long &_jiffies; + ::Timer::Connection _timer_conn; + Lx::List _list; + Lx::Task _timer_task; + Genode::Signal_rpc_member _dispatcher; + Genode::Tslab _timer_alloc; + + /** + * Lookup local timer + */ + Context *_find_context(struct timer_list const *timer) + { + for (Context *c = _list.first(); c; c = c->next()) + if (c->timer == timer) + return c; + + return 0; + } + + /** + * Program the first timer in the list + * + * The first timer is programmed if the 'programmed' flag was not set + * before. The second timer is flagged as not programmed as + * 'Timer::trigger_once' invalidates former registered one-shot + * timeouts. + */ + void _program_first_timer() + { + Context *ctx = _list.first(); + if (!ctx) + return; + + if (ctx->programmed) + return; + + /* calculate relative microseconds for trigger */ + unsigned long us = ctx->timeout > _jiffies ? + jiffies_to_msecs(ctx->timeout - _jiffies) * 1000 : 0; + _timer_conn.trigger_once(us); + + ctx->programmed = true; + + /* possibly programmed successor must be reprogrammed later */ + if (Context *next = ctx->next()) + next->programmed = false; + } + + /** + * Schedule timer + * + * Add the context to the scheduling list depending on its timeout + * and reprogram the first timer. + */ + void _schedule_timer(Context *ctx, unsigned long expires) + { + _list.remove(ctx); + + ctx->timeout = expires; + ctx->pending = true; + ctx->programmed = false; + /* + * Also write the timeout value to the expires field in + * struct timer_list because the wireless stack checks + * it directly. + */ + ctx->timer->expires = expires; + + Context *c; + for (c = _list.first(); c; c = c->next()) + if (ctx->timeout <= c->timeout) + break; + _list.insert_before(ctx, c); + + _program_first_timer(); + } + + /** + * Handle trigger_once signal + */ + void _handle(unsigned) + { + _timer_task.unblock(); + + Lx::scheduler().schedule(); + } + + public: + + /** + * Constructor + */ + Timer(Server::Entrypoint &ep, unsigned long &jiffies) + : + _jiffies(jiffies), + _timer_task(run_timer, nullptr, "timer", Lx::Task::PRIORITY_2, + Lx::scheduler()), + _dispatcher(ep, *this, &Lx::Timer::_handle), + _timer_alloc(Genode::env()->heap()) + { + _timer_conn.sigh(_dispatcher); + } + + /** + * Add new linux timer + */ + void add(struct timer_list *timer) + { + Context *t = new (&_timer_alloc) Context(timer); + _list.append(t); + } + + /** + * Delete linux timer + */ + int del(struct timer_list *timer) + { + Context *ctx = _find_context(timer); + + /** + * If the timer expired it was already cleaned up after its + * execution. + */ + if (!ctx) + return 0; + + int rv = ctx->timeout != Context::INVALID_TIMEOUT ? 1 : 0; + + _list.remove(ctx); + destroy(&_timer_alloc, ctx); + + return rv; + } + + /** + * Initial scheduling of linux timer + */ + int schedule(struct timer_list *timer, unsigned long expires) + { + Context *ctx = _find_context(timer); + if (!ctx) { + PERR("schedule unknown timer %p", timer); + return -1; /* XXX better use 0 as rv? */ + } + + /* + * If timer was already active return 1, otherwise 0. The return + * value is needed by mod_timer(). + */ + int rv = ctx->timeout != Context::INVALID_TIMEOUT ? 1 : 0; + + _schedule_timer(ctx, expires); + + return rv; + } + + /** + * Schedule next linux timer + */ + void schedule_next() { _program_first_timer(); } + + /** + * Check if the timer is currently pending + */ + bool pending(struct timer_list const *timer) + { + Context *ctx = _find_context(timer); + if (!ctx) { + return false; + } + + return ctx->pending; + } + + Context *find(struct timer_list const *timer) { + return _find_context(timer); } + + /** + * Update jiffie counter + */ + void update_jiffies() + { + _jiffies = msecs_to_jiffies(_timer_conn.elapsed_ms()); + } + + /** + * Get first timer context + */ + Context* first() { return _list.first(); } + + unsigned long jiffies() const { return _jiffies; } +}; + + +void Lx::timer_update_jiffies() +{ + timer().update_jiffies(); +} + + +void Lx::run_timer(void *) +{ + Timer &t = timer(); + + while (1) { + Lx::scheduler().current()->block_and_schedule(); + + while (Lx::Timer::Context *ctx = t.first()) { + if (ctx->timeout > t.jiffies()) + break; + + ctx->timer->function(ctx->timer->data); + t.del(ctx->timer); + } + + t.schedule_next(); + } +} + + +Lx::Timer &Lx::_timer_impl(Server::Entrypoint *ep, unsigned long *jiffies_ptr) +{ + static bool initialized = false; + + if (!initialized && !ep) { + PERR("attempt to use Lx::Timer before its construction"); + class Lx_timer_not_constructed { }; + throw Lx_timer_not_constructed(); + } + + static Lx::Timer inst(*ep, *jiffies_ptr); + initialized = true; + return inst; +} + + +#endif /* _LX_EMUL__IMPL__INTERNAL__TIMER_H_ */ diff --git a/repos/dde_linux/src/include/lx_emul/impl/io.h b/repos/dde_linux/src/include/lx_emul/impl/io.h new file mode 100644 index 000000000..3ace39c8d --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/impl/io.h @@ -0,0 +1,40 @@ +/* + * \brief Implementation of linux/io.h + * \author Norman Feske + * \date 2015-09-09 + */ + +/* + * Copyright (C) 2015 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 + + +void *ioremap(resource_size_t phys_addr, unsigned long size) +{ + return Lx::ioremap(phys_addr, size, Genode::UNCACHED); +} + + +void *ioremap_wc(resource_size_t phys_addr, unsigned long size) +{ + return Lx::ioremap(phys_addr, size, Genode::WRITE_COMBINED); +} + + +/********************** + ** asm-generic/io.h ** + **********************/ + +void outb(u8 value, u32 port) { Lx::pci_dev_registry()->io_write (port, value); } +void outw(u16 value, u32 port) { Lx::pci_dev_registry()->io_write(port, value); } +void outl(u32 value, u32 port) { Lx::pci_dev_registry()->io_write(port, value); } + +u8 inb(u32 port) { return Lx::pci_dev_registry()->io_read (port); } +u16 inw(u32 port) { return Lx::pci_dev_registry()->io_read(port); } +u32 inl(u32 port) { return Lx::pci_dev_registry()->io_read(port); } diff --git a/repos/dde_linux/src/include/lx_emul/impl/kernel.h b/repos/dde_linux/src/include/lx_emul/impl/kernel.h new file mode 100644 index 000000000..3dbbe1d12 --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/impl/kernel.h @@ -0,0 +1,42 @@ +/* + * \brief Implementation of linux/kernel.h + * \author Norman Feske + * \date 2015-09-09 + */ + +/* + * Copyright (C) 2015 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 + + +int sprintf(char *str, const char *format, ...) +{ + enum { BUFFER_LEN = 128 }; + va_list list; + + va_start(list, format); + Genode::String_console sc(str, BUFFER_LEN); + sc.vprintf(format, list); + va_end(list); + + return sc.len(); +} + + +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(); +} diff --git a/repos/dde_linux/src/include/lx_emul/impl/mutex.h b/repos/dde_linux/src/include/lx_emul/impl/mutex.h new file mode 100644 index 000000000..bb188853a --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/impl/mutex.h @@ -0,0 +1,104 @@ +/* + * \brief Implementation of linux/mutex.h + * \author Norman Feske + * \date 2015-09-09 + */ + +/* + * Copyright (C) 2015 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 + + +enum { MUTEX_UNLOCKED = 1, MUTEX_LOCKED = 0, MUTEX_WAITERS = -1 }; + +void mutex_init(struct mutex *m) +{ + static unsigned id = 0; + + m->state = MUTEX_UNLOCKED; + m->holder = nullptr; + m->waiters = new (Genode::env()->heap()) Lx::Task::List; + m->id = ++id; +} + + +void mutex_destroy(struct mutex *m) +{ + /* FIXME potentially blocked tasks are not unblocked */ + + Genode::destroy(Genode::env()->heap(), static_cast(m->waiters)); + + m->holder = nullptr; + m->waiters = nullptr; + m->id = 0; +} + + +void mutex_lock(struct mutex *m) +{ + while (1) { + if (m->state == MUTEX_UNLOCKED) { + m->state = MUTEX_LOCKED; + m->holder = Lx::scheduler().current(); + + break; + } + + Lx::Task *t = reinterpret_cast(m->holder); + + if (t == Lx::scheduler().current()) { + PERR("Bug: mutex does not support recursive locking"); + Genode::sleep_forever(); + } + + /* notice that a task waits for the mutex to be released */ + m->state = MUTEX_WAITERS; + + /* block until the mutex is released (and retry then) */ + Lx::scheduler().current()->mutex_block(static_cast(m->waiters)); + Lx::scheduler().current()->schedule(); + } +} + + +void mutex_unlock(struct mutex *m) +{ + if (m->state == MUTEX_UNLOCKED) { + PERR("Bug: multiple mutex unlock detected"); + Genode::sleep_forever(); + } + if (m->holder != Lx::scheduler().current()) { + PERR("Bug: mutex unlock by task not holding the mutex"); + Genode::sleep_forever(); + } + + Lx::Task::List *waiters = static_cast(m->waiters); + + if (m->state == MUTEX_WAITERS) + while (Lx::Task::List_element *le = waiters->first()) + le->object()->mutex_unblock(waiters); + + m->state = MUTEX_UNLOCKED; + m->holder = nullptr; +} + + +int mutex_is_locked(struct mutex *m) +{ + return m->state != MUTEX_UNLOCKED; +} + + +int mutex_trylock(struct mutex *m) +{ + if (mutex_is_locked(m)) + return false; + + mutex_lock(m); + return true; +} diff --git a/repos/dde_linux/src/include/lx_emul/impl/pci.h b/repos/dde_linux/src/include/lx_emul/impl/pci.h new file mode 100644 index 000000000..8ef3d162e --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/impl/pci.h @@ -0,0 +1,194 @@ +/* + * \brief Implementation of linux/pci.h + * \author Norman Feske + * \date 2015-09-09 + */ + +/* + * Copyright (C) 2015 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 + + +extern void pci_dev_put(struct pci_dev *pci_dev) +{ + Genode::destroy(Genode::env()->heap(), pci_dev); +} + + +extern "C" int pci_register_driver(struct pci_driver *driver) +{ + driver->driver.name = driver->name; + + pci_device_id const *id_table = driver->id_table; + if (!id_table) + return -ENODEV; + + using namespace Genode; + + Lx::Pci_dev *pci_dev = nullptr; + + auto lamda = [&] (Platform::Device_capability cap) { + + Platform::Device_client client(cap); + + /* request device ID from platform driver */ + unsigned const device_id = client.device_id(); + + /* look if we find the device ID in the driver's 'id_table' */ + pci_device_id const *matching_id = nullptr; + for (pci_device_id const *id = id_table; id->class_ != (unsigned)PCI_ANY_ID; id++) + if (id->device == device_id) + matching_id = id; + + /* skip device that is not handled by driver */ + if (!matching_id) + return false; + + /* create 'pci_dev' struct for matching device */ + pci_dev = new (env()->heap()) Lx::Pci_dev(cap); + + /* enable ioremap to work */ + Lx::pci_dev_registry()->insert(pci_dev); + + /* register driver at the 'pci_dev' struct */ + pci_dev->dev.driver = &driver->driver; + + /* call probe function of the Linux driver */ + if (!driver->probe(pci_dev, matching_id)) { + + /* if the probing failed, revert the creation of 'pci_dev' */ + pci_dev_put(pci_dev); + pci_dev = nullptr; + return false; + } + + /* aquire the device, stop iterating */ + return true; + }; + + Lx::for_each_pci_device(lamda); + + return pci_dev ? 0 : -ENODEV; +} + + +extern "C" size_t pci_resource_start(struct pci_dev *dev, unsigned bar) +{ + if (bar >= DEVICE_COUNT_RESOURCE) + return 0; + + return dev->resource[bar].start; +} + + +extern "C" 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; +} + + +extern "C" void *pci_ioremap_bar(struct pci_dev *dev, int bar) +{ + using namespace Genode; + + if (bar >= DEVICE_COUNT_RESOURCE || bar < 0) + return 0; + + return Lx::ioremap(pci_resource_start(dev, bar), + pci_resource_len(dev, bar), + Genode::UNCACHED); +} + + +extern "C" unsigned int pci_resource_flags(struct pci_dev *dev, unsigned bar) +{ + if (bar >= DEVICE_COUNT_RESOURCE) + return 0; + + return dev->resource[bar].flags; +} + + +extern "C" int pci_bus_read_config_byte(struct pci_bus *bus, unsigned int, int where, u8 *val) +{ + Lx::Pci_dev *dev = (Lx::Pci_dev *)bus; + dev->config_read(where, val); + return 0; +} + + +extern "C" int pci_bus_read_config_word(struct pci_bus *bus, unsigned int, int where, u16 *val) +{ + Lx::Pci_dev *dev = (Lx::Pci_dev *)bus; + dev->config_read(where, val); + return 0; +} + + +extern "C" int pci_bus_read_config_dword(struct pci_bus *bus, unsigned int, int where, u32 *val) +{ + Lx::Pci_dev *dev = (Lx::Pci_dev *)bus; + dev->config_read(where, val); + return 0; +} + + +extern "C" int pci_bus_write_config_byte(struct pci_bus *bus, unsigned int, int where, u8 val) +{ + Lx::Pci_dev *dev = (Lx::Pci_dev *)bus; + dev->config_write(where, val); + return 0; +} + + +extern "C" int pci_bus_write_config_word(struct pci_bus *bus, unsigned int, int where, u16 val) +{ + Lx::Pci_dev *dev = (Lx::Pci_dev *)bus; + dev->config_write(where, val); + return 0; +} + + +extern "C" int pci_bus_write_config_dword(struct pci_bus *bus, unsigned int, int where, u32 val) +{ + Lx::Pci_dev *dev = (Lx::Pci_dev *)bus; + dev->config_write(where, val); + return 0; +} + + +extern "C" const char *pci_name(const struct pci_dev *pdev) +{ + /* simply return driver name */ + return "dummy"; +} + + +extern "C" int pcie_capability_read_word(struct pci_dev *pdev, int pos, u16 *val) +{ + Lx::Pci_dev *dev = (Lx::Pci_dev *)pdev->bus; + switch (pos) { + case PCI_EXP_LNKCTL: + dev->config_read(pdev->pcie_cap + PCI_EXP_LNKCTL, val); + return 0; + break; + default: + break; + } + + return 1; +} +// diff --git a/repos/dde_linux/src/include/lx_emul/impl/sched.h b/repos/dde_linux/src/include/lx_emul/impl/sched.h new file mode 100644 index 000000000..5c17033d0 --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/impl/sched.h @@ -0,0 +1,39 @@ +/* + * \brief Implementation of linux/sched.h + * \author Norman Feske + * \date 2015-09-09 + */ + +/* + * Copyright (C) 2015 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 + + +static void unblock_task(unsigned long task) +{ + Lx::Task *t = (Lx::Task *)task; + + t->unblock(); +} + + +signed long schedule_timeout(signed long timeout) +{ + struct timer_list timer; + + setup_timer(&timer, unblock_task, (unsigned long)Lx::scheduler().current()); + mod_timer(&timer, timeout); + + Lx::scheduler().current()->block_and_schedule(); + + del_timer(&timer); + + timeout = (timeout - jiffies); + + return timeout < 0 ? 0 : timeout; +} diff --git a/repos/dde_linux/src/include/lx_emul/impl/slab.h b/repos/dde_linux/src/include/lx_emul/impl/slab.h new file mode 100644 index 000000000..8d37e7fb0 --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/impl/slab.h @@ -0,0 +1,175 @@ +/* + * \brief Implementation of linux/slab.h + * \author Norman Feske + * \date 2015-09-09 + */ + +/* + * Copyright (C) 2015 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 + + +void *kmalloc(size_t size, gfp_t flags) +{ + if (flags & __GFP_DMA) + PWRN("GFP_DMA memory (below 16 MiB) requested (%p)", __builtin_return_address(0)); + if (flags & __GFP_DMA32) + PWRN("GFP_DMA32 memory (below 4 GiB) requested (%p)", __builtin_return_address(0)); + + void *addr = flags & GFP_LX_DMA ? Lx::Malloc::dma().alloc(size, 12) + : Lx::Malloc::mem().alloc(size); + + if ((Genode::addr_t)addr & 0x3) + PERR("unaligned kmalloc %lx", (Genode::addr_t)addr); + + if (flags & __GFP_ZERO) + Genode::memset(addr, 0, size); + + return addr; +} + + +void *kzalloc(size_t size, gfp_t flags) +{ + return kmalloc(size, flags | __GFP_ZERO); +} + + +void *kzalloc_node(size_t size, gfp_t flags, int node) +{ + return kzalloc(size, 0); +} + + +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(void const *p) +{ + if (!p) return; + + if (Lx::Malloc::mem().inside((Genode::addr_t)p)) + Lx::Malloc::mem().free(p); + else if (Lx::Malloc::dma().inside((Genode::addr_t)p)) + Lx::Malloc::dma().free(p); + else + PERR("%s: unknown block at %p, called from %p", __func__, + p, __builtin_return_address(0)); +} + + +static size_t _ksize(void *p) +{ + size_t size = 0; + + if (Lx::Malloc::mem().inside((Genode::addr_t)p)) + size = Lx::Malloc::mem().size(p); + else if (Lx::Malloc::dma().inside((Genode::addr_t)p)) + size = Lx::Malloc::dma().size(p); + else + PERR("%s: unknown block at %p", __func__, p); + + return size; +} + + +size_t ksize(void *p) +{ + return _ksize(p); +} + + +void kzfree(void const *p) +{ + if (!p) return; + + size_t len = ksize(const_cast(p)); + + Genode::memset((void*)p, 0, len); + + kfree(p); +} + + +void *kmalloc_node_track_caller(size_t size, gfp_t flags, int node) +{ + return kmalloc(size, flags); +} + + +void *krealloc(void *p, size_t size, gfp_t flags) +{ + /* XXX handle short-cut where size == old_size */ + void *addr = kmalloc(size, flags); + + if (addr && p) { + size_t old_size = _ksize(p); + + Genode::memcpy(addr, p, old_size); + kfree(p); + } + + return addr; +} + + +void *kmemdup(const void *src, size_t size, gfp_t flags) +{ + void *addr = kmalloc(size, flags); + + if (addr) + Genode::memcpy(addr, src, size); + + return addr; +} + + +struct kmem_cache : Lx::Slab_alloc +{ + kmem_cache(size_t object_size, bool dma) + : + Lx::Slab_alloc(object_size, dma ? Lx::Slab_backend_alloc::dma() + : Lx::Slab_backend_alloc::mem()) + { } +}; + + +struct kmem_cache *kmem_cache_create(const char *name, size_t size, size_t align, + unsigned long flags, void (*ctor)(void *)) +{ + if (ctor) { + PERR("%s: ctor not supported", __func__); + return nullptr; + } + + /* + * Copied from wifi_drv. + * + * XXX SLAB_LX_DMA is never used anywhere else, remove it? + */ + enum { SLAB_LX_DMA = 0x80000000ul, }; + return new (Genode::env()->heap()) kmem_cache(size, flags & SLAB_LX_DMA); +} + + +void * kmem_cache_alloc(struct kmem_cache *cache, gfp_t flags) +{ + return (void *)cache->alloc(); +} + + +void kmem_cache_free(struct kmem_cache *cache, void *objp) +{ + cache->free(objp); +} diff --git a/repos/dde_linux/src/include/lx_emul/impl/spinlock.h b/repos/dde_linux/src/include/lx_emul/impl/spinlock.h new file mode 100644 index 000000000..e77dd3cb5 --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/impl/spinlock.h @@ -0,0 +1,17 @@ +/* + * \brief Implementation of linux/spinlock.h + * \author Norman Feske + * \date 2015-09-09 + */ + +/* + * Copyright (C) 2015 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. + */ + +void spin_lock_init(spinlock_t *lock) { TRACE; } +void spin_lock_irqsave(spinlock_t *lock, unsigned long flags) { } +void spin_unlock(spinlock_t *lock) { TRACE; } +void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags) { } diff --git a/repos/dde_linux/src/include/lx_emul/impl/timer.h b/repos/dde_linux/src/include/lx_emul/impl/timer.h new file mode 100644 index 000000000..13a922464 --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/impl/timer.h @@ -0,0 +1,52 @@ +/* + * \brief Implementation of linux/timer.h + * \author Norman Feske + * \date 2015-09-09 + */ + +/* + * Copyright (C) 2015 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 + + +void init_timer(struct timer_list *timer) { } + + +int mod_timer(struct timer_list *timer, unsigned long expires) +{ + if (!Lx::timer().find(timer)) + Lx::timer().add(timer); + + return Lx::timer().schedule(timer, expires); +} + + +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 = Lx::timer().pending(timer); + + return pending; +} + + +int del_timer(struct timer_list *timer) +{ + int rv = Lx::timer().del(timer); + Lx::timer().schedule_next(); + + return rv; +} diff --git a/repos/dde_linux/src/include/lx_emul/impl/wait.h b/repos/dde_linux/src/include/lx_emul/impl/wait.h new file mode 100644 index 000000000..df0f74053 --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/impl/wait.h @@ -0,0 +1,47 @@ +/* + * \brief Implementation of linux/wait.h + * \author Norman Feske + * \date 2015-09-09 + */ + +/* + * Copyright (C) 2015 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. + */ + +void prepare_to_wait(wait_queue_head_t *q, wait_queue_t *w, int state) +{ + if (!q) { + PWRN("prepare_to_wait: wait_queue_head_t is 0, ignore, called from: %p", + __builtin_return_address(0)); + return; + } + + Wait_list *list = static_cast(q->list); + Lx::Task *task = Lx::scheduler().current(); + + task->wait_enqueue(list); +} + + +void prepare_to_wait_exclusive(wait_queue_head_t *q, wait_queue_t *w, int state) +{ + prepare_to_wait(q, w, state); +} + + +void finish_wait(wait_queue_head_t *q, wait_queue_t *w) +{ + if (!q) { + PWRN("finish_wait: wait_queue_head_t is 0, ignore, called from: %p", + __builtin_return_address(0)); + return; + } + + Wait_list *list = static_cast(q->list); + Lx::Task *task = Lx::scheduler().current(); + + task->wait_dequeue(list); +} diff --git a/repos/dde_linux/src/include/lx_emul/ioport.h b/repos/dde_linux/src/include/lx_emul/ioport.h new file mode 100644 index 000000000..1c94ec450 --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/ioport.h @@ -0,0 +1,47 @@ +/* + * \brief Linux kernel API + * \author Norman Feske + * \author Sebastian Sumpf + * \author Josef Soentgen + * \date 2014-08-21 + * + * Based on the prototypes found in the Linux kernel's 'include/'. + */ + +/* + * Copyright (C) 2014 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/ioport.h ** + ********************/ + +#define IORESOURCE_IO 0x00000100 +#define IORESOURCE_MEM 0x00000200 +#define IORESOURCE_IRQ 0x00000400 + +struct resource +{ + resource_size_t start; + resource_size_t end; + const char *name; + unsigned long flags; +}; + +struct device; + +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); +struct resource * devm_request_mem_region(struct device *dev, 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); + +resource_size_t resource_size(const struct resource *res); diff --git a/repos/dde_linux/src/include/lx_emul/irq.h b/repos/dde_linux/src/include/lx_emul/irq.h new file mode 100644 index 000000000..ad3e43e88 --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/irq.h @@ -0,0 +1,26 @@ +/* + * \brief Linux kernel API + * \author Norman Feske + * \author Sebastian Sumpf + * \author Josef Soentgen + * \date 2014-08-21 + * + * Based on the prototypes found in the Linux kernel's 'include/'. + */ + +/* + * Copyright (C) 2014 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/irqreturn.h ** + ***********************/ + +typedef enum irqreturn { + IRQ_NONE = 0, + IRQ_HANDLED = 1, + IRQ_WAKE_THREAD = 2, +} irqreturn_t; diff --git a/repos/dde_linux/src/include/lx_emul/jiffies.h b/repos/dde_linux/src/include/lx_emul/jiffies.h new file mode 100644 index 000000000..168936cb9 --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/jiffies.h @@ -0,0 +1,46 @@ +/* + * \brief Linux kernel API + * \author Norman Feske + * \author Sebastian Sumpf + * \author Josef Soentgen + * \date 2014-08-21 + * + * Based on the prototypes found in the Linux kernel's 'include/'. + */ + +/* + * Copyright (C) 2014 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/jiffies.h ** + *********************/ + +#define MAX_JIFFY_OFFSET ((LONG_MAX >> 1)-1) + +extern unsigned long jiffies; + +enum { + JIFFIES_TICK_MS = 1000/HZ, + JIFFIES_TICK_US = 1000*1000/HZ, +}; + +static inline unsigned long msecs_to_jiffies(const unsigned int m) { return m / JIFFIES_TICK_MS; } +static inline unsigned int jiffies_to_msecs(const unsigned long j) { return j * JIFFIES_TICK_MS; } +static inline unsigned long usecs_to_jiffies(const unsigned int u) { return u / JIFFIES_TICK_US; } + +clock_t jiffies_to_clock_t(unsigned long x); +static inline clock_t jiffies_delta_to_clock_t(long delta) +{ + return jiffies_to_clock_t(max(0L, delta)); +} + +#define time_after(a,b) ((long)((b) - (a)) < 0) +#define time_after_eq(a,b) ((long)((a) - (b)) >= 0) +#define time_before(a,b) time_after(b,a) +#define time_before_eq(a,b) time_after_eq(b,a) + +#define time_is_after_jiffies(a) time_before(jiffies, a) diff --git a/repos/dde_linux/src/include/lx_emul/kernel.h b/repos/dde_linux/src/include/lx_emul/kernel.h new file mode 100644 index 000000000..7ec001ad6 --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/kernel.h @@ -0,0 +1,172 @@ +/* + * \brief Linux kernel API + * \author Norman Feske + * \author Sebastian Sumpf + * \author Josef Soentgen + * \date 2014-08-21 + * + * Based on the prototypes found in the Linux kernel's 'include/'. + */ + +/* + * Copyright (C) 2014 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/kconfig.h ** + *********************/ + +#define IS_ENABLED(x) x + + +/******************** + ** linux/kernel.h ** + ********************/ + +/* + * Log tags + */ +#define KERN_ALERT "ALERT: " +#define KERN_CRIT "CRTITCAL: " +#define KERN_DEBUG "DEBUG: " +#define KERN_EMERG "EMERG: " +#define KERN_ERR "ERROR: " +#define KERN_INFO "INFO: " +#define KERN_NOTICE "NOTICE: " +#define KERN_WARNING "WARNING: " +#define KERN_WARN "WARNING: " + +/* + * Debug macros + */ +#if DEBUG_LINUX_PRINTK +#define printk _printk +#define vprintk lx_vprintf +#else +#define printk(...) +#define vprintk(...) +#endif + +static inline __printf(1, 2) void panic(const char *fmt, ...) __noreturn; +static inline void panic(const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + lx_vprintf(fmt, args); + va_end(args); + lx_printf("panic()"); + while (1) ; +} + +/* + * 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 lower_32_bits(n) ((u32)(n)) +#define upper_32_bits(n) ((u32)(((n) >> 16) >> 16)) + +#define roundup(x, y) ( \ +{ \ + const typeof(y) __y = y; \ + (((x) + (__y - 1)) / __y) * __y; \ +}) + +#define __round_mask(x, y) ((__typeof__(x))((y)-1)) +#define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1) +#define round_down(x, y) ((x) & ~__round_mask(x, y)) + +#define clamp_val(val, min, max) ({ \ + typeof(val) __val = (val); \ + typeof(val) __min = (min); \ + typeof(val) __max = (max); \ + __val = __val < __min ? __min: __val; \ + __val > __max ? __max: __val; }) + +#define clamp_t(type, val, min, max) ({ \ + type __val = (val); \ + type __min = (min); \ + type __max = (max); \ + __val = __val < __min ? __min: __val; \ + __val > __max ? __max: __val; }) + +#define DIV_ROUND_CLOSEST(x, divisor)( \ +{ \ + typeof(x) __x = x; \ + typeof(divisor) __d = divisor; \ + (((typeof(x))-1) > 0 || \ + ((typeof(divisor))-1) > 0 || (__x) > 0) ? \ + (((__x) + ((__d) / 2)) / (__d)) : \ + (((__x) - ((__d) / 2)) / (__d)); \ +}) + +#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) + +#define ALIGN(x, a) __ALIGN_KERNEL((x), (a)) +#define __ALIGN_KERNEL(x, a) __ALIGN_KERNEL_MASK(x, (typeof(x))(a) - 1) +#define __ALIGN_KERNEL_MASK(x, mask) (((x) + (mask)) & ~(mask)) + +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) + +#define BUILD_BUG_ON(condition) + +#define _RET_IP_ (unsigned long)__builtin_return_address(0) + +void might_sleep(); +#define might_sleep_if(cond) do { if (cond) might_sleep(); } while (0) + +#define INT_MAX ((int)(~0U>>1)) +#define UINT_MAX (~0U) +#define INT_MIN (-INT_MAX - 1) +#define USHRT_MAX ((u16)(~0U)) +#define LONG_MAX ((long)(~0UL>>1)) +#define SHRT_MAX ((s16)(USHRT_MAX>>1)) +#define SHRT_MIN ((s16)(-SHRT_MAX - 1)) +#define ULONG_MAX (~0UL) + +#define swap(a, b) \ + do { typeof(a) __tmp = (a); (a) = (b); (b) = __tmp; } while (0) + diff --git a/repos/dde_linux/src/include/lx_emul/kobject.h b/repos/dde_linux/src/include/lx_emul/kobject.h new file mode 100644 index 000000000..e01981868 --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/kobject.h @@ -0,0 +1,44 @@ +/* + * \brief Linux kernel API + * \author Norman Feske + * \author Sebastian Sumpf + * \author Josef Soentgen + * \date 2014-08-21 + * + * Based on the prototypes found in the Linux kernel's 'include/'. + */ + +/* + * Copyright (C) 2014 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/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 { struct kobject *parent; }; +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); diff --git a/repos/dde_linux/src/include/lx_emul/list.h b/repos/dde_linux/src/include/lx_emul/list.h new file mode 100644 index 000000000..86835f670 --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/list.h @@ -0,0 +1,43 @@ +/* + * \brief Linux kernel API + * \author Norman Feske + * \author Sebastian Sumpf + * \author Josef Soentgen + * \date 2014-08-21 + * + * Based on the prototypes found in the Linux kernel's 'include/'. + */ + +/* + * Copyright (C) 2014 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/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 nullptr +#define LIST_POISON2 nullptr +#else +#define LIST_POISON1 ((void *)0x00100100) +#define LIST_POISON2 ((void *)0x00200200) +#endif /* __cplusplus */ + + +/****************** + ** linux/list.h ** + ******************/ + +#include diff --git a/repos/dde_linux/src/include/lx_emul/mmio.h b/repos/dde_linux/src/include/lx_emul/mmio.h new file mode 100644 index 000000000..4e79927c2 --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/mmio.h @@ -0,0 +1,30 @@ +/* + * \brief Linux kernel API + * \author Norman Feske + * \author Sebastian Sumpf + * \author Josef Soentgen + * \date 2014-08-21 + * + * Based on the prototypes found in the Linux kernel's 'include/'. + */ + +/* + * Copyright (C) 2014 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. + */ + +/********************** + ** asm-generic/io.h ** + **********************/ + +#define writeq(value, addr) (*(volatile uint64_t *)(addr) = (value)) +#define writel(value, addr) (*(volatile uint32_t *)(addr) = (value)) +#define writew(value, addr) (*(volatile uint16_t *)(addr) = (value)) +#define writeb(value, addr) (*(volatile uint8_t *)(addr) = (value)) + +#define readq(addr) (*(volatile uint64_t *)(addr)) +#define readl(addr) (*(volatile uint32_t *)(addr)) +#define readw(addr) (*(volatile uint16_t *)(addr)) +#define readb(addr) (*(volatile uint8_t *)(addr)) diff --git a/repos/dde_linux/src/include/lx_emul/module.h b/repos/dde_linux/src/include/lx_emul/module.h new file mode 100644 index 000000000..f719929ec --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/module.h @@ -0,0 +1,70 @@ +/* + * \brief Linux kernel API + * \author Norman Feske + * \author Sebastian Sumpf + * \author Josef Soentgen + * \date 2014-08-21 + * + * Based on the prototypes found in the Linux kernel's 'include/'. + */ + +/* + * Copyright (C) 2014 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/init.h ** + ******************/ + +#define __init +#define __exit +#define __devinitconst + +#define _SETUP_CONCAT(a, b) __##a##b +#define SETUP_CONCAT(a, b) _SETUP_CONCAT(a, b) +#define __setup(str, fn) static void SETUP_CONCAT(fn, SETUP_SUFFIX)(void *addrs) { fn(addrs); } + +#define core_initcall(fn) void core_##fn(void) { fn(); } +#define subsys_initcall(fn) void subsys_##fn(void) { fn(); } +#define pure_initcall(fd) void pure_##fn(void) { printk("PURE_INITCALL"); fn(); } + + +/******************** + ** linux/module.h ** + ********************/ + +#define EXPORT_SYMBOL(x) +#define EXPORT_SYMBOL_GPL(x) +#define MODULE_LICENSE(x) +#define MODULE_NAME_LEN (64 - sizeof(long)) +#define MODULE_ALIAS(name) +#define MODULE_AUTHOR(name) +#define MODULE_DESCRIPTION(desc) +#define MODULE_VERSION(version) +#define THIS_MODULE 0 +#define MODULE_FIRMWARE(_firmware) +#define MODULE_DEVICE_TABLE(type, name) + + +struct module; +#define module_init(fn) void module_##fn(void) { fn(); } +#define module_exit(fn) void module_exit_##fn(void) { fn(); } +void module_put_and_exit(int); + +void module_put(struct module *); +void __module_get(struct module *module); +int try_module_get(struct module *); + + +/************************* + ** linux/moduleparam.h ** + *************************/ + +#define module_param(name, type, perm) +#define module_param_named(name, value, type, perm) +#define MODULE_PARM_DESC(_parm, desc) +#define kparam_block_sysfs_write(name) +#define kparam_unblock_sysfs_write(name) diff --git a/repos/dde_linux/src/include/lx_emul/mutex.h b/repos/dde_linux/src/include/lx_emul/mutex.h new file mode 100644 index 000000000..caf5686b3 --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/mutex.h @@ -0,0 +1,43 @@ +/* + * \brief Linux kernel API + * \author Norman Feske + * \author Sebastian Sumpf + * \author Josef Soentgen + * \date 2014-08-21 + * + * Based on the prototypes found in the Linux kernel's 'include/'. + */ + +/* + * Copyright (C) 2014 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/mutex.h ** + *******************/ + +struct mutex +{ + int state; + void *holder; + void *waiters; + unsigned id; /* for debugging */ +}; + +#define DEFINE_MUTEX(mutexname) \ + struct mutex mutexname; \ + static void __attribute__((constructor)) mutex_init_ ## mutexname(void) \ + { mutex_init(&mutexname); } + +void mutex_init(struct mutex *m); +void mutex_destroy(struct mutex *m); +void mutex_lock(struct mutex *m); +void mutex_unlock(struct mutex *m); +int mutex_trylock(struct mutex *m); +int mutex_is_locked(struct mutex *m); + +/* special case in net/wireless/util.c:1357 */ +#define mutex_lock_nested(lock, subclass) mutex_lock(lock) diff --git a/repos/dde_linux/src/include/lx_emul/pci.h b/repos/dde_linux/src/include/lx_emul/pci.h new file mode 100644 index 000000000..cbbd6fb29 --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/pci.h @@ -0,0 +1,149 @@ +/* + * \brief Linux kernel API + * \author Norman Feske + * \author Sebastian Sumpf + * \author Josef Soentgen + * \date 2014-08-21 + * + * Based on the prototypes found in the Linux kernel's 'include/'. + */ + +/* + * Copyright (C) 2014 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/pci.h ** + *****************/ + +#include +#include + +enum { + PCI_DMA_BIDIRECTIONAL = 0, + PCI_DMA_TODEVICE, + PCI_DMA_FROMDEVICE, + PCI_DMA_NONE +}; + + +enum { PCI_ANY_ID = ~0U }; + + +typedef enum { + PCI_D0 = 0, + PCI_D1 = 1, + PCI_D3hot = 3, + PCI_D3cold = 4, +} pci_power_t; + + +/* + * PCI types + */ +struct pci_bus; +struct pci_dev; + +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); + struct device_driver driver; +}; + + +static inline uint32_t PCI_DEVFN(unsigned slot, unsigned func) { + return ((slot & 0x1f) << 3) | (func & 0x07); } + +static inline uint32_t PCI_FUNC(unsigned devfn) { return devfn & 0x07; } +static inline uint32_t PCI_SLOT(unsigned devfn) { return ((devfn) >> 3) & 0x1f; } + +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_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_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); +bool pci_pme_capable(struct pci_dev *dev, pci_power_t state); +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); +int pci_request_regions(struct pci_dev *dev, const char *res_name); +void pci_release_regions(struct pci_dev *dev); +void *pci_ioremap_bar(struct pci_dev *pdev, int bar); +void pci_disable_link_state(struct pci_dev *pdev, int state); + +int pci_enable_msi(struct pci_dev *dev); +void pci_disable_msi(struct pci_dev *dev); + +#define DEFINE_PCI_DEVICE_TABLE(_table) \ + const struct pci_device_id _table[] __devinitconst + +#define to_pci_dev(n) container_of(n, struct pci_dev, dev) + +int pci_register_driver(struct pci_driver *driver); + +int pcie_capability_read_word(struct pci_dev *dev, int pos, u16 *val); + +void *pci_get_drvdata(struct pci_dev *pdev); + + +#define dev_is_pci(d) (1) + +int pci_num_vf(struct pci_dev *dev); + +/* XXX will this cast ever work? */ +#define dev_num_vf(d) ((dev_is_pci(d) ? pci_num_vf((struct pci_dev *)d) : 0)) + + +/********************** + ** linux/pci-aspm.h ** + **********************/ + +#define PCIE_LINK_STATE_L0S 1 +#define PCIE_LINK_STATE_L1 2 +#define PCIE_LINK_STATE_CLKPM 4 diff --git a/repos/dde_linux/src/include/lx_emul/pm.h b/repos/dde_linux/src/include/lx_emul/pm.h new file mode 100644 index 000000000..314a96cb6 --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/pm.h @@ -0,0 +1,43 @@ +/* + * \brief Linux kernel API + * \author Norman Feske + * \author Sebastian Sumpf + * \author Josef Soentgen + * \date 2014-08-21 + * + * Based on the prototypes found in the Linux kernel's 'include/'. + */ + +/* + * Copyright (C) 2014 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/pm.h ** + ****************/ + +struct device; + +typedef struct pm_message { int event; } pm_message_t; + +struct dev_pm_info { pm_message_t power_state; }; + +struct dev_pm_ops { + int (*suspend)(struct device *dev); + int (*resume)(struct device *dev); + int (*freeze)(struct device *dev); + int (*thaw)(struct device *dev); + int (*poweroff)(struct device *dev); + int (*restore)(struct device *dev); + int (*runtime_suspend)(struct device *dev); + int (*runtime_resume)(struct device *dev); +}; + +#define PMSG_IS_AUTO(msg) 0 + +enum { PM_EVENT_AUTO_SUSPEND = 0x402 }; + +#define PM_EVENT_SUSPEND 0x0002 diff --git a/repos/dde_linux/src/include/lx_emul/printf.h b/repos/dde_linux/src/include/lx_emul/printf.h new file mode 100644 index 000000000..2a9d78071 --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/printf.h @@ -0,0 +1,32 @@ +/* + * \brief Debugging utilities + * \author Norman Feske + * \author Sebastian Sumpf + * \author Josef Soentgen + * \date 2014-08-21 + */ + +/* + * Copyright (C) 2014 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. + */ + +void lx_printf(char const *, ...) __attribute__((format(printf, 1, 2))); +void lx_vprintf(char const *, va_list); + +#define lx_printfln(args...) \ + do { \ + lx_printf(args); \ + lx_printf("\n"); \ + } while (0); + +#define lx_log(doit, msg...) \ + do { \ + if (doit) { \ + lx_printf("%s(): ", __func__); \ + lx_printf(msg); \ + lx_printf("\n"); \ + } \ + } while(0) diff --git a/repos/dde_linux/src/include/lx_emul/scatterlist.h b/repos/dde_linux/src/include/lx_emul/scatterlist.h new file mode 100644 index 000000000..f9f4b657d --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/scatterlist.h @@ -0,0 +1,91 @@ +/* + * \brief Linux kernel API + * \author Norman Feske + * \author Sebastian Sumpf + * \author Josef Soentgen + * \date 2014-08-21 + * + * Based on the prototypes found in the Linux kernel's 'include/'. + */ + +/* + * Copyright (C) 2014 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/scatterlist.h ** + *************************/ + +enum { + SG_MITER_TO_SG = 2, + SG_MITER_FROM_SG = 4, +}; + +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 sg_page_iter +{ + struct scatterlist *sg; + unsigned int sg_pgoffset; /* page offset within the sg */ +}; + +struct sg_mapping_iter +{ + void *addr; + size_t length; + + struct sg_page_iter piter; +}; + +struct page; + +void sg_init_table(struct scatterlist *, unsigned int); +void sg_set_buf(struct scatterlist *sg, const void *buf, unsigned int buflen); +void sg_set_page(struct scatterlist *sg, struct page *page, + unsigned int len, unsigned int offset); + +struct page *sg_page(struct scatterlist *sg); +void *sg_virt(struct scatterlist *sg); +struct scatterlist *sg_next(struct scatterlist *); + +int sg_nents(struct scatterlist *sg); +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); + +bool __sg_page_iter_next(struct sg_page_iter *piter); +void __sg_page_iter_start(struct sg_page_iter *piter, + struct scatterlist *sglist, unsigned int nents, + unsigned long pgoffset); + +#define for_each_sg(sglist, sg, nr, __i) \ + for (__i = 0, sg = (sglist); __i < (nr); __i++, sg = sg_next(sg)) + +#define for_each_sg_page(sglist, piter, nents, pgoffset) \ + for (__sg_page_iter_start((piter), (sglist), (nents), (pgoffset)); \ + __sg_page_iter_next(piter);) + +#define sg_dma_address(sg) ((sg)->dma_address) +#define sg_dma_len(sg) ((sg)->length) + +void sg_miter_start(struct sg_mapping_iter *miter, struct scatterlist *sgl, + unsigned int nents, unsigned int flags); +bool sg_miter_skip(struct sg_mapping_iter *miter, off_t offset); +bool sg_miter_next(struct sg_mapping_iter *miter); +void sg_miter_stop(struct sg_mapping_iter *miter); diff --git a/repos/dde_linux/src/include/lx_emul/semaphore.h b/repos/dde_linux/src/include/lx_emul/semaphore.h new file mode 100644 index 000000000..030b25ab7 --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/semaphore.h @@ -0,0 +1,34 @@ +/* + * \brief Linux kernel API + * \author Norman Feske + * \author Sebastian Sumpf + * \author Josef Soentgen + * \date 2014-08-21 + * + * Based on the prototypes found in the Linux kernel's 'include/'. + */ + +/* + * Copyright (C) 2014 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/rwsem.h ** + *******************/ + +struct rw_semaphore { int dummy; }; + +#define DECLARE_RWSEM(name) \ + struct rw_semaphore name = { 0 } + +#define init_rwsem(sem) do { (void)sem; } while (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 } diff --git a/repos/dde_linux/src/include/lx_emul/spinlock.h b/repos/dde_linux/src/include/lx_emul/spinlock.h new file mode 100644 index 000000000..ee63414b1 --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/spinlock.h @@ -0,0 +1,44 @@ +/* + * \brief Linux kernel API + * \author Norman Feske + * \author Sebastian Sumpf + * \author Josef Soentgen + * \date 2014-08-21 + * + * Based on the prototypes found in the Linux kernel's 'include/'. + */ + +/* + * Copyright (C) 2014 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/spinlock.h ** + **********************/ + +typedef struct spinlock { unsigned unused; } spinlock_t; +#define DEFINE_SPINLOCK(name) spinlock_t name + +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); +void spin_lock_bh(spinlock_t *lock); +void spin_unlock_bh(spinlock_t *lock); +int spin_trylock(spinlock_t *lock); + + +/**************************** + ** linux/spinlock_types.h ** + ****************************/ + +#define __SPIN_LOCK_UNLOCKED(x) 0 diff --git a/repos/dde_linux/src/include/lx_emul/string.h b/repos/dde_linux/src/include/lx_emul/string.h new file mode 100644 index 000000000..a4f2ff4f1 --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/string.h @@ -0,0 +1,43 @@ +/* + * \brief Linux kernel API + * \author Norman Feske + * \author Sebastian Sumpf + * \author Josef Soentgen + * \date 2014-08-21 + * + * Based on the prototypes found in the Linux kernel's 'include/'. + */ + +/* + * Copyright (C) 2014 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/string.h ** + ********************/ +#undef memcpy + +void *memcpy(void *d, const void *s, size_t n); +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 *strcpy(char *to, const char *from); +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 *); +size_t strnlen(const char *, size_t); +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); +void *memmove(void *, const void *, size_t); +void * memchr(const void *, int, size_t); diff --git a/repos/dde_linux/src/include/lx_emul/time.h b/repos/dde_linux/src/include/lx_emul/time.h new file mode 100644 index 000000000..80b1bcd4f --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/time.h @@ -0,0 +1,82 @@ +/* + * \brief Linux kernel API + * \author Norman Feske + * \author Sebastian Sumpf + * \author Josef Soentgen + * \date 2014-08-21 + * + * Based on the prototypes found in the Linux kernel's 'include/'. + */ + +/* + * Copyright (C) 2014 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/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()) + + + +enum { + CLOCK_REALTIME = 0, + CLOCK_MONOTONIC = 1, + NSEC_PER_USEC = 1000L, + NSEC_PER_MSEC = 1000000L, + NSEC_PER_SEC = 1000L * NSEC_PER_MSEC, +}; + + +/******************* + ** 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); +} + +static inline ktime_t ktime_get(void) +{ + return (ktime_t){ .tv64 = (s64)jiffies * HZ * NSEC_PER_MSEC /* ns */ }; +} + +static inline ktime_t ktime_set(const long sec, const unsigned long nsec) +{ + return (ktime_t){ .tv64 = (s64)sec * NSEC_PER_SEC + (s64)nsec /* ns */ }; +} + +static inline ktime_t ktime_add(const ktime_t a, const ktime_t b) +{ + return (ktime_t){ .tv64 = a.tv64 + b.tv64 /* ns */ }; +} + + +s64 ktime_us_delta(const ktime_t later, const ktime_t earlier); + +struct timeval ktime_to_timeval(const ktime_t); + +ktime_t ktime_get_real(void); +ktime_t ktime_sub(const ktime_t, const ktime_t); +ktime_t ktime_get_monotonic_offset(void); + diff --git a/repos/dde_linux/src/include/lx_emul/timer.h b/repos/dde_linux/src/include/lx_emul/timer.h new file mode 100644 index 000000000..90990447e --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/timer.h @@ -0,0 +1,50 @@ +/* + * \brief Linux kernel API + * \author Norman Feske + * \author Sebastian Sumpf + * \author Josef Soentgen + * \date 2014-08-21 + * + * Based on the prototypes found in the Linux kernel's 'include/'. + */ + +/* + * Copyright (C) 2014 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/timer.h ** + *******************/ + +struct tvec_base; +extern struct tvec_base boot_tvec_bases; /* needed by 'dwc_common_linux.c' */ + +struct timer_list +{ + void (*function)(unsigned long); + unsigned long data; + void *timer; + unsigned long expires; + struct tvec_base *base; /* needed by 'dwc_common_linux.c' */ +}; + +void init_timer(struct timer_list *); +void init_timer_deferrable(struct timer_list *); +int mod_timer(struct timer_list *timer, unsigned long expires); +int del_timer(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); +unsigned long round_jiffies_relative(unsigned long j); +unsigned long round_jiffies_up(unsigned long j); + +void set_timer_slack(struct timer_list *time, int slack_hz); +static inline void add_timer(struct timer_list *timer) { mod_timer(timer, timer->expires); } + +static inline +int del_timer_sync(struct timer_list * timer) { return del_timer(timer); } diff --git a/repos/dde_linux/src/include/lx_emul/types.h b/repos/dde_linux/src/include/lx_emul/types.h new file mode 100644 index 000000000..d60d0310f --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/types.h @@ -0,0 +1,106 @@ +/* + * \brief Linux kernel API + * \author Norman Feske + * \author Sebastian Sumpf + * \author Josef Soentgen + * \date 2014-08-21 + * + * Based on the prototypes found in the Linux kernel's 'include/'. + */ + +/* + * Copyright (C) 2014 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/types.h ** + *******************/ + +typedef genode_int8_t int8_t; +typedef genode_uint8_t uint8_t; +typedef genode_int16_t int16_t; +typedef genode_uint16_t uint16_t; +typedef genode_int32_t int32_t; +typedef genode_uint32_t uint32_t; +typedef __SIZE_TYPE__ size_t; +typedef genode_int64_t int64_t; +typedef genode_uint64_t uint64_t; + +typedef uint32_t uint; +typedef unsigned long ulong; + +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; + +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 _Bool bool; +enum { true = 1, false = 0 }; +#endif /* __cplusplus */ + +#ifndef NULL +#ifdef __cplusplus +#define NULL nullptr +#else +#define NULL ((void *)0) +#endif /* __cplusplus */ +#endif /* NULL */ + +typedef unsigned gfp_t; +typedef unsigned long dma_addr_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 unsigned kuid_t; +typedef unsigned kgid_t; +typedef long __kernel_time_t; +typedef unsigned short umode_t; +typedef __u16 __be16; +typedef __u32 __be32; +typedef long clock_t; + +#ifndef __cplusplus +typedef u16 wchar_t; +#endif + +/* + * XXX 'mode_t' is 'unsigned int' on x86_64 + */ +typedef unsigned short mode_t; diff --git a/repos/dde_linux/src/include/lx_emul/work.h b/repos/dde_linux/src/include/lx_emul/work.h new file mode 100644 index 000000000..072d01bde --- /dev/null +++ b/repos/dde_linux/src/include/lx_emul/work.h @@ -0,0 +1,203 @@ +/* + * \brief Linux kernel API + * \author Norman Feske + * \author Sebastian Sumpf + * \author Josef Soentgen + * \date 2014-08-21 + * + * Based on the prototypes found in the Linux kernel's 'include/'. + */ + +/* + * Copyright (C) 2014 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/workqueue.h ** + ***********************/ + +enum { + WQ_MEM_RECLAIM, + WQ_CPU_INTENSIVE, +}; + +struct work_struct; +typedef void (*work_func_t)(struct work_struct *work); + +struct work_struct { + atomic_long_t data; + 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); +bool cancel_delayed_work_sync(struct delayed_work *work); +bool cancel_delayed_work(struct delayed_work *dwork); +int schedule_delayed_work(struct delayed_work *work, unsigned long delay); +int schedule_work(struct work_struct *work); +void flush_scheduled_work(void); + +bool flush_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) + + +/* dummy for queue_delayed_work call in storage/usb.c */ +#define system_freezable_wq 0 +struct workqueue_struct { unsigned unused; }; + +struct workqueue_struct *create_singlethread_workqueue(const char *name); +struct workqueue_struct *alloc_ordered_workqueue(const char *fmt, unsigned int flags, ...) __printf(1, 3); +struct workqueue_struct *alloc_workqueue(const char *fmt, unsigned int flags, + int max_active, ...) __printf(1, 4); +void destroy_workqueue(struct workqueue_struct *wq); +void flush_workqueue(struct workqueue_struct *wq); +bool queue_delayed_work(struct workqueue_struct *, struct delayed_work *, unsigned long); +bool flush_delayed_work(struct delayed_work *dwork); +bool queue_work(struct workqueue_struct *wq, struct work_struct *work); + +#define DECLARE_DELAYED_WORK(n, f) \ + struct delayed_work n + +bool mod_delayed_work(struct workqueue_struct *, struct delayed_work *, + unsigned long); + +static inline struct delayed_work *to_delayed_work(struct work_struct *work) +{ + return container_of(work, struct delayed_work, work); +} + +extern struct workqueue_struct *system_wq; + +enum { + WORK_STRUCT_STATIC = 0, + + WORK_STRUCT_COLOR_SHIFT = 4, + WORK_STRUCT_COLOR_BITS = 4, + WORK_STRUCT_FLAG_BITS = WORK_STRUCT_COLOR_SHIFT + WORK_STRUCT_COLOR_BITS, + WORK_OFFQ_FLAG_BASE = WORK_STRUCT_FLAG_BITS, + + WORK_OFFQ_FLAG_BITS = 1, + WORK_OFFQ_POOL_SHIFT = WORK_OFFQ_FLAG_BASE + WORK_OFFQ_FLAG_BITS, + WORK_OFFQ_LEFT = BITS_PER_LONG - WORK_OFFQ_POOL_SHIFT, + WORK_OFFQ_POOL_BITS = WORK_OFFQ_LEFT <= 31 ? WORK_OFFQ_LEFT : 31, + WORK_OFFQ_POOL_NONE = (1LU << WORK_OFFQ_POOL_BITS) - 1, + + WORK_STRUCT_NO_POOL = (unsigned long)WORK_OFFQ_POOL_NONE << WORK_OFFQ_POOL_SHIFT, +}; + +#define WORK_DATA_STATIC_INIT() \ + ATOMIC_LONG_INIT(WORK_STRUCT_NO_POOL | WORK_STRUCT_STATIC) + +#define __WORK_INIT_LOCKDEP_MAP(n, k) + +#define __WORK_INITIALIZER(n, f) { \ + .data = WORK_DATA_STATIC_INIT(), \ + .entry = { &(n).entry, &(n).entry }, \ + .func = (f), \ + __WORK_INIT_LOCKDEP_MAP(#n, &(n)) \ +} + +#define DECLARE_WORK(n, f) \ + struct work_struct n = __WORK_INITIALIZER(n, f) + + +/****************** + ** linux/wait.h ** + ******************/ + +typedef struct wait_queue_head { void *list; } wait_queue_head_t; +typedef struct wait_queue { unsigned unused; } wait_queue_t; + +#define DEFINE_WAIT(name) \ + wait_queue_t name; + +#define __WAIT_QUEUE_HEAD_INITIALIZER(name) { 0 } + +#define DECLARE_WAITQUEUE(name, tsk) \ + wait_queue_t name + +#define DECLARE_WAIT_QUEUE_HEAD(name) \ + wait_queue_head_t name = __WAIT_QUEUE_HEAD_INITIALIZER(name) + +#define DEFINE_WAIT_FUNC(name, function) \ + wait_queue_t name + +/* simplified signature */ +void __wake_up(wait_queue_head_t *q, bool all); + +#define wake_up(x) __wake_up(x, false) +#define wake_up_all(x) __wake_up(x, true) +#define wake_up_interruptible(x) __wake_up(x, false) +#define wake_up_interruptible_all(x) __wake_up(x, true) + +void init_waitqueue_head(wait_queue_head_t *); +int waitqueue_active(wait_queue_head_t *); + +/* void wake_up_interruptible(wait_queue_head_t *); */ +void wake_up_interruptible_sync_poll(wait_queue_head_t *, int); +void wake_up_interruptible_poll(wait_queue_head_t *, int); + +void prepare_to_wait(wait_queue_head_t *, wait_queue_t *, int); +void prepare_to_wait_exclusive(wait_queue_head_t *, wait_queue_t *, int); +void finish_wait(wait_queue_head_t *, wait_queue_t *); + +int autoremove_wake_function(wait_queue_t *, unsigned, int, void *); +void add_wait_queue(wait_queue_head_t *, wait_queue_t *); +void add_wait_queue_exclusive(wait_queue_head_t *, wait_queue_t *); +void remove_wait_queue(wait_queue_head_t *, wait_queue_t *); + +/* our wait event implementation - it's okay as value */ +void __wait_event(wait_queue_head_t); + +#define _wait_event(wq, condition) while (!(condition)) { __wait_event(wq); } +#define wait_event(wq, condition) ({ _wait_event(wq, condition); }) +#define wait_event_interruptible(wq, condition) ({ _wait_event(wq, condition); 0; }) + +#define _wait_event_timeout(wq, condition, timeout) \ + ({ int res = 1; \ + prepare_to_wait(&wq, 0, 0); \ + while (1) { \ + if ((condition) || !res) { \ + break; \ + } \ + res = schedule_timeout(jiffies + timeout); \ + } \ + finish_wait(&wq, 0); \ + res; \ + }) + +#define wait_event_timeout(wq, condition, timeout) \ + ({ \ + int ret = _wait_event_timeout(wq, (condition), timeout); \ + ret; \ + }) diff --git a/repos/dde_linux/src/include/spec/x86_32/lx_emul/impl/internal/arch_execute.h b/repos/dde_linux/src/include/spec/x86_32/lx_emul/impl/internal/arch_execute.h new file mode 100644 index 000000000..134c9f484 --- /dev/null +++ b/repos/dde_linux/src/include/spec/x86_32/lx_emul/impl/internal/arch_execute.h @@ -0,0 +1,27 @@ +/* + * \brief Architecture-specific code + * \author Sebastian Sumpf + * \date 2012-06-10 + */ + +/* + * Copyright (C) 2012-2013 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _ARCH_EXECUTE_H_ +#define _ARCH_EXECUTE_H_ + +static inline +void arch_execute(void *sp, void *func, void *arg) +{ + asm volatile ("movl %2, 0(%0);" + "movl %1, -0x4(%0);" + "movl %0, %%esp;" + "call *-4(%%esp);" + : : "r" (sp), "r" (func), "r" (arg)); +} + +#endif /* _ARCH_EXECUTE_H_ */ diff --git a/repos/dde_linux/src/include/spec/x86_64/lx_emul/impl/internal/arch_execute.h b/repos/dde_linux/src/include/spec/x86_64/lx_emul/impl/internal/arch_execute.h new file mode 100644 index 000000000..eb96ce8f6 --- /dev/null +++ b/repos/dde_linux/src/include/spec/x86_64/lx_emul/impl/internal/arch_execute.h @@ -0,0 +1,28 @@ +/* + * \brief Architecture-specific code + * \author Sebastian Sumpf + * \author Alexander Boettcher + * \date 2012-06-10 + */ + +/* + * Copyright (C) 2012-2013 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _ARCH_EXECUTE_H_ +#define _ARCH_EXECUTE_H_ + +static inline +void arch_execute(void *sp, void *func, void *arg) +{ + asm volatile ("movq %2, %%rdi;" + "movq %1, 0(%0);" + "movq %0, %%rsp;" + "call *0(%%rsp);" + : "+r" (sp), "+r" (func), "+r" (arg) : : "memory"); +} + +#endif /* _ARCH_EXECUTE_H_ */ diff --git a/repos/dde_linux/src/include/x86/lx_emul/barrier.h b/repos/dde_linux/src/include/x86/lx_emul/barrier.h new file mode 100644 index 000000000..d0575003d --- /dev/null +++ b/repos/dde_linux/src/include/x86/lx_emul/barrier.h @@ -0,0 +1,19 @@ + +/******************* + ** asm/barrier.h ** + *******************/ + +#define mb() asm volatile ("mfence": : :"memory") +#define rmb() asm volatile ("lfence": : :"memory") +#define wmb() asm volatile ("sfence": : :"memory") + +/* + * This is the "safe" implementation as needed for a configuration + * with SMP enabled. + */ + +#define smp_mb() mb() +#define smp_rmb() barrier() +#define smp_wmb() barrier() + +static inline void barrier() { asm volatile ("": : :"memory"); }