From 2882bd48e6fe6d0cc285f2ba2b148bf5b718dd1e Mon Sep 17 00:00:00 2001 From: Stefan Kalkowski Date: Wed, 22 Aug 2018 13:52:41 +0200 Subject: [PATCH] dde_linux: USB client driver for NIC version 4.16 --- .../lib/import/import-usb_net_include.mk | 33 + repos/dde_linux/lib/mk/usb_net_include.mk | 37 + .../patches/usb_net_skbuff_cast.patch | 13 + repos/dde_linux/ports/dde_linux.hash | 2 +- repos/dde_linux/ports/dde_linux.port | 15 +- repos/dde_linux/run/usb_hid.run | 5 +- repos/dde_linux/run/usb_net.run | 94 +- repos/dde_linux/src/drivers/usb_net/README | 20 + .../src/drivers/usb_net/component.cc | 182 +++ .../dde_linux/src/drivers/usb_net/component.h | 126 ++ repos/dde_linux/src/drivers/usb_net/driver.h | 105 ++ repos/dde_linux/src/drivers/usb_net/dummies.c | 518 +++++++ .../dde_linux/src/drivers/usb_net/lx_emul.cc | 539 +++++++ repos/dde_linux/src/drivers/usb_net/lx_emul.h | 1296 +++++++++++++++++ repos/dde_linux/src/drivers/usb_net/lxc.c | 65 + repos/dde_linux/src/drivers/usb_net/lxc.h | 40 + repos/dde_linux/src/drivers/usb_net/main.cc | 216 +++ repos/dde_linux/src/drivers/usb_net/target.mk | 32 + repos/dde_linux/usb_net.list | 71 + 19 files changed, 3370 insertions(+), 39 deletions(-) create mode 100644 repos/dde_linux/lib/import/import-usb_net_include.mk create mode 100644 repos/dde_linux/lib/mk/usb_net_include.mk create mode 100644 repos/dde_linux/patches/usb_net_skbuff_cast.patch create mode 100644 repos/dde_linux/src/drivers/usb_net/README create mode 100644 repos/dde_linux/src/drivers/usb_net/component.cc create mode 100644 repos/dde_linux/src/drivers/usb_net/component.h create mode 100644 repos/dde_linux/src/drivers/usb_net/driver.h create mode 100644 repos/dde_linux/src/drivers/usb_net/dummies.c create mode 100644 repos/dde_linux/src/drivers/usb_net/lx_emul.cc create mode 100644 repos/dde_linux/src/drivers/usb_net/lx_emul.h create mode 100644 repos/dde_linux/src/drivers/usb_net/lxc.c create mode 100644 repos/dde_linux/src/drivers/usb_net/lxc.h create mode 100644 repos/dde_linux/src/drivers/usb_net/main.cc create mode 100644 repos/dde_linux/src/drivers/usb_net/target.mk create mode 100644 repos/dde_linux/usb_net.list diff --git a/repos/dde_linux/lib/import/import-usb_net_include.mk b/repos/dde_linux/lib/import/import-usb_net_include.mk new file mode 100644 index 000000000..79e6fb4c9 --- /dev/null +++ b/repos/dde_linux/lib/import/import-usb_net_include.mk @@ -0,0 +1,33 @@ +USB_NET_CONTRIB_DIR := $(call select_from_ports,dde_linux)/src/drivers/usb_net + +# architecture-dependent includes +ifeq ($(filter-out $(SPECS),x86),) + ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/x86 + 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 + +ifeq ($(filter-out $(SPECS),arm),) + ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/arm + ifeq ($(filter-out $(SPECS),arm_v6),) + ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/arm_v6 + endif # arm_v6 + ifeq ($(filter-out $(SPECS),arm_v7),) + ARCH_SRC_INC_DIR += $(REP_DIR)/src/include/spec/arm_v7 + endif # arm_v7 +endif # arm + + +# +# The order of include-search directories is important, we need to look into +# 'contrib' before falling back to our custom 'lx_emul.h' header. +# +INC_DIR += $(ARCH_SRC_INC_DIR) +INC_DIR += $(USB_NET_CONTRIB_DIR)/include +#INC_DIR += $(USB_NET_CONTRIB_DIR)/drivers/hid +#INC_DIR += $(USB_NET_CONTRIB_DIR)/drivers/input +INC_DIR += $(LIB_CACHE_DIR)/usb_net_include/include/include/include diff --git a/repos/dde_linux/lib/mk/usb_net_include.mk b/repos/dde_linux/lib/mk/usb_net_include.mk new file mode 100644 index 000000000..662957851 --- /dev/null +++ b/repos/dde_linux/lib/mk/usb_net_include.mk @@ -0,0 +1,37 @@ +ifeq ($(called_from_lib_mk),yes) + +USB_NET_CONTRIB_DIR := $(call select_from_ports,dde_linux)/src/drivers/usb_net +LX_EMUL_H := $(REP_DIR)/src/drivers/usb_net/lx_emul.h + +# +# Determine the header files included by the contrib code. For each +# of these header files we create a symlink to 'lx_emul.h'. +# +SCAN_DIRS := $(addprefix $(USB_NET_CONTRIB_DIR)/include/, asm-generic linux uapi net) \ + $(addprefix $(USB_NET_CONTRIB_DIR)/, drivers net) +GEN_INCLUDES := $(shell grep -rIh "^\#include .*\/" $(SCAN_DIRS) |\ + sed "s/^\#include [^<\"]*[<\"]\([^>\"]*\)[>\"].*/\1/" |\ + sort | uniq) +# +# Filter out original Linux headers that exist in the contrib directory +# +NO_GEN_INCLUDES := $(shell cd $(USB_NET_CONTRIB_DIR)/; find include -name "*.h" |\ + sed "s/.\///" | sed "s/.*include\///") +GEN_INCLUDES := $(filter-out $(NO_GEN_INCLUDES),$(GEN_INCLUDES)) + +# +# Put Linux headers in 'GEN_INC' dir, since some include use "../../" paths use +# three level include hierarchy +# +GEN_INC := $(shell pwd)/include/include/include +GEN_INCLUDES := $(addprefix $(GEN_INC)/,$(GEN_INCLUDES)) + +all: $(GEN_INCLUDES) + +$(GEN_INCLUDES): + $(VERBOSE)mkdir -p $(dir $@) + $(VERBOSE)ln -s $(LX_EMUL_H) $@ + +endif + +CC_CXX_WARN_STRICT = diff --git a/repos/dde_linux/patches/usb_net_skbuff_cast.patch b/repos/dde_linux/patches/usb_net_skbuff_cast.patch new file mode 100644 index 000000000..5e63596db --- /dev/null +++ b/repos/dde_linux/patches/usb_net_skbuff_cast.patch @@ -0,0 +1,13 @@ +diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h +index 9147f9f..c63ee5c 100644 +--- a/include/linux/skbuff.h ++++ b/include/linux/skbuff.h +@@ -3281,7 +3281,7 @@ static inline void skb_remcsum_process(struct sk_buff *skb, void *ptr, + + if (unlikely(skb->ip_summed != CHECKSUM_COMPLETE)) { + __skb_checksum_complete(skb); +- skb_postpull_rcsum(skb, skb->data, ptr - (void *)skb->data); ++ skb_postpull_rcsum(skb, skb->data, (unsigned char*)ptr - skb->data); + } + + delta = remcsum_adjust(ptr, skb->csum, start, offset); diff --git a/repos/dde_linux/ports/dde_linux.hash b/repos/dde_linux/ports/dde_linux.hash index 5fdcbd6ec..f9b0ee45f 100644 --- a/repos/dde_linux/ports/dde_linux.hash +++ b/repos/dde_linux/ports/dde_linux.hash @@ -1 +1 @@ -66e54dcbcd22c597db5794f080d92df114b88985 +987b3081e335b0063655441c929a86a4627af72f diff --git a/repos/dde_linux/ports/dde_linux.port b/repos/dde_linux/ports/dde_linux.port index 34a56501f..5f144e1a2 100644 --- a/repos/dde_linux/ports/dde_linux.port +++ b/repos/dde_linux/ports/dde_linux.port @@ -2,7 +2,8 @@ LICENSE := GPLv2 VERSION := 2 DOWNLOADS := dwc_otg.git usb.archive intel_fb.archive lxip.archive \ wifi.archive fec.archive libnl.archive wpa_supplicant.git \ - fw.archive usb_host.archive dwc_otg_host.git usb_hid.archive + fw.archive usb_host.archive dwc_otg_host.git usb_hid.archive \ + usb_net.archive # # Tools @@ -51,6 +52,14 @@ DIR(usb_hid) := $(SRC_DIR_USB_HID) TAR_OPT(usb_hid) := --strip-components=1 --files-from - < <(sed 's/-x.x.x/-$(VERSION_USB_HID)/g' $(REP_DIR)/usb_hid.list) HASH_INPUT += $(REP_DIR)/usb_hid.list +SRC_DIR_USB_NET := src/drivers/usb_net +VERSION_USB_NET := 4.16.3 +URL(usb_net) := https://www.kernel.org/pub/linux/kernel/v4.x/linux-$(VERSION_USB_NET).tar.xz +SHA(usb_net) := 0d6971a81da97e38b974c5eba31a74803bfe41aabc46d406c3acda56306c81a3 +DIR(usb_net) := $(SRC_DIR_USB_NET) +TAR_OPT(usb_net) := --strip-components=1 --files-from - < <(sed 's/-x.x.x/-$(VERSION_USB_NET)/g' $(REP_DIR)/usb_net.list) +HASH_INPUT += $(REP_DIR)/usb_net.list + # # Raspberry Pi USB controller # @@ -187,6 +196,10 @@ PATCH_OPT(patches/usb_hid_usbhid.patch) := $(USB_HID_OPT) PATCH_OPT(patches/usb_hid_wacom_sys.patch) := $(USB_HID_OPT) PATCH_OPT(patches/usb_hid_evdev.patch) := $(USB_HID_OPT) +# USB NET +USB_NET_OPT = -p1 -d$(SRC_DIR_USB_NET) +PATCH_OPT(patches/usb_net_skbuff_cast.patch) := $(USB_NET_OPT) + # INTEL FB PATCH_OPT(patches/intel_fb_backlight.patch) := -p1 -d$(SRC_DIR_INTEL_FB) PATCH_OPT(patches/intel_fb_drm.patch) := -p1 -d$(SRC_DIR_INTEL_FB) diff --git a/repos/dde_linux/run/usb_hid.run b/repos/dde_linux/run/usb_hid.run index e4076aa25..fea02ab98 100644 --- a/repos/dde_linux/run/usb_hid.run +++ b/repos/dde_linux/run/usb_hid.run @@ -127,7 +127,7 @@ append config { } append config "" append config { - + @@ -140,7 +140,7 @@ append config { - + @@ -207,7 +207,6 @@ append_platform_drv_boot_modules build_boot_image $boot_modules -append qemu_args " -nographic" append qemu_args " -usb -usbdevice mouse -usbdevice keyboard" append qemu_args " -device usb-ehci,id=ehci" append xen_args { usbdevice=\["mouse","keyboard"\] } diff --git a/repos/dde_linux/run/usb_net.run b/repos/dde_linux/run/usb_net.run index 4806e5f9f..6d07c8dd6 100644 --- a/repos/dde_linux/run/usb_net.run +++ b/repos/dde_linux/run/usb_net.run @@ -13,29 +13,32 @@ set build_components { core init - drivers/timer drivers/usb + drivers/timer + drivers/usb_host + drivers/usb_net test/lwip/http_srv + lib/vfs/lwip } -proc gpio_drv { } { if {[have_spec rpi] && [have_spec hw]} { return hw_gpio_drv } - if {[have_spec rpi] && [have_spec foc]} { return foc_gpio_drv } - return gpio_drv } +lappend_if [have_spec gpio] build_components drivers/gpio source ${genode_dir}/repos/base/run/platform_drv.inc append_platform_drv_build_components -lappend_if [have_spec gpio] build_components drivers/gpio - build $build_components +proc gpio_drv { } { if {[have_spec rpi] && [have_spec hw]} { return hw_gpio_drv } + if {[have_spec rpi] && [have_spec foc]} { return foc_gpio_drv } + return gpio_drv } + create_boot_directory # # Generate config # -set config { - +append config { + @@ -49,29 +52,7 @@ set config { - - - - - - - - - - - - - - - - - - - - - } - -append_platform_drv_config + } append_if [have_spec gpio] config " @@ -80,7 +61,50 @@ append_if [have_spec gpio] config " " +append_platform_drv_config + append config { + + + + + + } +append config "" +append config { + + + } +append_if [have_spec arndale] config { + } +append_if [expr [have_spec panda] || [have_spec rpi] ] config { + } +append_if [have_spec x86] config { + } +append config { + + + + + + + + + + + + + + + + + + + + + + + } @@ -92,13 +116,15 @@ install_config $config # generic modules set boot_modules { - core ld.lib.so init timer usb_drv - libc.lib.so vfs.lib.so libm.lib.so lwip_legacy.lib.so posix.lib.so test-lwip_httpsrv + core init timer usb_net_drv + ld.lib.so libc.lib.so vfs.lib.so vfs_lwip.lib.so test-lwip_httpsrv } -append_platform_drv_boot_modules +append boot_modules [usb_host_drv_binary] lappend_if [have_spec gpio] boot_modules [gpio_drv] +append_platform_drv_boot_modules + build_boot_image $boot_modules append qemu_args " -nographic" diff --git a/repos/dde_linux/src/drivers/usb_net/README b/repos/dde_linux/src/drivers/usb_net/README new file mode 100644 index 000000000..7e3aee439 --- /dev/null +++ b/repos/dde_linux/src/drivers/usb_net/README @@ -0,0 +1,20 @@ +USB NIC driver +############## + +Driver for network interface cards connected via USB. + +Configuration snippet: + +! +! +! +! +! + +There is the 'mac' attribute where one can specify the hardware address of +the network interface. This is necessary in case the EEPROM of the network card +cannot be accessed via the host controller making it impossible to retrieve the +devices hardware address. If this is the case and no 'mac' attribute is given a +fallback address will be assigned to the network device. Note that the fallback +address will always be the same. + diff --git a/repos/dde_linux/src/drivers/usb_net/component.cc b/repos/dde_linux/src/drivers/usb_net/component.cc new file mode 100644 index 000000000..fdac2710e --- /dev/null +++ b/repos/dde_linux/src/drivers/usb_net/component.cc @@ -0,0 +1,182 @@ +/* + * \brief Freescale ethernet driver component + * \author Stefan Kalkowski + * \date 2017-11-01 + */ + +/* + * Copyright (C) 2017 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#include +#include + +extern "C" { +#include +}; + +void Session_component::_run_rx_task(void * args) +{ + Rx_data *data = static_cast(args); + + while (1) { + Lx::scheduler().current()->block_and_schedule(); + + int ret = 0; + struct napi_struct * n = data->napi; + + for (;;) { + + /* This NAPI_STATE_SCHED test is for avoiding a race + * with netpoll's poll_napi(). Only the entity which + * obtains the lock and sees NAPI_STATE_SCHED set will + * actually make the ->poll() call. Therefore we avoid + * accidentally calling ->poll() when NAPI is not scheduled. + */ + if (!test_bit(NAPI_STATE_SCHED, &n->state)) break; + + int weight = n->weight; + int work = n->poll(n, weight); + ret += work; + + if (work < weight) break; + + Genode::warning("Too much incoming traffic, we should schedule RX more intelligent"); + } + } +} + + +void Session_component::_run_tx_task(void * args) +{ + Tx_data *data = static_cast(args); + + while (1) { + Lx::scheduler().current()->block_and_schedule(); + + net_device * ndev = data->ndev; + struct sk_buff * skb = data->skb; + + ndev->netdev_ops->ndo_start_xmit(skb, ndev); + } +} + + +bool Session_component::_send() +{ + using namespace Genode; + + /* + * We must not be called from another task, just from the + * packet stream dispatcher. + */ + if (Lx::scheduler().active()) { + warning("scheduler active"); + return false; + } + + if (!_tx.sink()->ready_to_ack()) { return false; } + if (!_tx.sink()->packet_avail()) { return false; } + + Packet_descriptor packet = _tx.sink()->get_packet(); + if (!packet.size()) { + warning("invalid tx packet"); + return true; + } + + enum { HEAD_ROOM = 8 }; + + struct sk_buff *skb = lxc_alloc_skb(packet.size() + HEAD_ROOM, HEAD_ROOM); + + unsigned char *data = lxc_skb_put(skb, packet.size()); + Genode::memcpy(data, _tx.sink()->packet_content(packet), packet.size()); + + _tx_data.ndev = _ndev; + _tx_data.skb = skb; + + _tx_task.unblock(); + Lx::scheduler().schedule(); + + _tx.sink()->acknowledge_packet(packet); + + return true; +} + + +void Session_component::_handle_rx() +{ + while (_rx.source()->ack_avail()) + _rx.source()->release_packet(_rx.source()->get_acked_packet()); +} + + +void Session_component::_handle_packet_stream() +{ + _handle_rx(); + + while (_send()) continue; +} + + +void Session_component::unblock_rx_task(napi_struct * n) +{ + _rx_data.napi = n; + _rx_task.unblock(); +} + + +Nic::Mac_address Session_component::mac_address() +{ + return _ndev ? Nic::Mac_address(_ndev->dev_addr) : Nic::Mac_address(); +} + + +void Session_component::receive(struct sk_buff *skb) +{ + _handle_rx(); + + if (!_rx.source()->ready_to_submit()) { + Genode::warning("not ready to receive packet"); + return; + } + + Skb s = skb_helper(skb); + + try { + Nic::Packet_descriptor p = _rx.source()->alloc_packet(s.packet_size + s.frag_size); + void *buffer = _rx.source()->packet_content(p); + memcpy(buffer, s.packet, s.packet_size); + + if (s.frag_size) + memcpy((char *)buffer + s.packet_size, s.frag, s.frag_size); + + _rx.source()->submit_packet(p); + } catch (...) { + Genode::warning("failed to process received packet"); + } +} + + +void Session_component::link_state(bool link) +{ + if (link == _has_link) return; + + _has_link = link; + _link_state_changed(); +} + + +Session_component::Session_component(Genode::size_t const tx_buf_size, + Genode::size_t const rx_buf_size, + Genode::Allocator & rx_block_md_alloc, + Genode::Env & env, + Genode::Session_label label) +: Nic::Session_component(tx_buf_size, rx_buf_size, rx_block_md_alloc, env), + _ndev(_register_session_component(*this, label)), + _has_link(_ndev ? !(_ndev->state & (1UL << __LINK_STATE_NOCARRIER)) : false) +{ + if (!_ndev) throw Genode::Service_denied(); +} diff --git a/repos/dde_linux/src/drivers/usb_net/component.h b/repos/dde_linux/src/drivers/usb_net/component.h new file mode 100644 index 000000000..c9867692c --- /dev/null +++ b/repos/dde_linux/src/drivers/usb_net/component.h @@ -0,0 +1,126 @@ +/* + * \brief Freescale ethernet driver component + * \author Stefan Kalkowski + * \date 2017-11-01 + */ + +/* + * Copyright (C) 2017 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#ifndef _SRC__DRIVERS__NIC__FEC__COMPONENT_H_ +#define _SRC__DRIVERS__NIC__FEC__COMPONENT_H_ + +/* Genode includes */ +#include +#include + +#include + +extern "C" { + struct net_device; + struct napi_struct; + struct sk_buff; +} + +class Session_component : public Nic::Session_component +{ + private: + + struct Tx_data + { + net_device * ndev; + sk_buff * skb; + }; + + struct Rx_data + { + struct napi_struct * napi; + }; + + net_device * _ndev = nullptr; + bool _has_link = false; + Tx_data _tx_data; + Rx_data _rx_data; + + static void _run_tx_task(void * args); + static void _run_rx_task(void * args); + static net_device * _register_session_component(Session_component &, + Genode::Session_label); + + Lx::Task _tx_task { _run_tx_task, &_tx_data, "tx_task", + Lx::Task::PRIORITY_1, Lx::scheduler() }; + Lx::Task _rx_task { _run_rx_task, &_rx_data, "rx_task", + Lx::Task::PRIORITY_1, Lx::scheduler() }; + + bool _send(); + void _handle_rx(); + void _handle_packet_stream() override; + + public: + + Session_component(Genode::size_t const tx_buf_size, + Genode::size_t const rx_buf_size, + Genode::Allocator & rx_block_md_alloc, + Genode::Env & env, + Genode::Session_label label); + + Nic::Mac_address mac_address() override; + bool link_state() override { return _has_link; } + void link_state(bool link); + void receive(struct sk_buff *skb); + void unblock_rx_task(napi_struct * n); +}; + + +class Root : public Genode::Root_component +{ + private: + + Genode::Env &_env; + Genode::Allocator &_md_alloc; + + protected: + + Session_component *_create_session(const char *args) + { + using namespace Genode; + + Session_label const label = label_from_args(args); + + size_t ram_quota = Arg_string::find_arg(args, "ram_quota" ).ulong_value(0); + size_t tx_buf_size = Arg_string::find_arg(args, "tx_buf_size").ulong_value(0); + size_t rx_buf_size = Arg_string::find_arg(args, "rx_buf_size").ulong_value(0); + + /* deplete ram quota by the memory needed for the session structure */ + size_t session_size = max(4096UL, (unsigned long)sizeof(Session_component)); + + /* + * Check if donated ram quota suffices for both communication + * buffers and check for overflow + */ + if ((ram_quota < session_size) || + (tx_buf_size + rx_buf_size < tx_buf_size || + tx_buf_size + rx_buf_size > ram_quota - session_size)) { + Genode::error("insufficient 'ram_quota', got ", ram_quota, ", " + "need ", tx_buf_size + rx_buf_size + session_size); + throw Genode::Insufficient_ram_quota(); + } + + return new (Root::md_alloc()) + Session_component(tx_buf_size, rx_buf_size, + _md_alloc, _env, label); + } + + public: + + Root(Genode::Env &env, Genode::Allocator &md_alloc) + : Genode::Root_component(&env.ep().rpc_ep(), &md_alloc), + _env(env), _md_alloc(md_alloc) + { } +}; + +#endif /* _SRC__DRIVERS__NIC__FEC__COMPONENT_H_ */ diff --git a/repos/dde_linux/src/drivers/usb_net/driver.h b/repos/dde_linux/src/drivers/usb_net/driver.h new file mode 100644 index 000000000..d0af2b0ad --- /dev/null +++ b/repos/dde_linux/src/drivers/usb_net/driver.h @@ -0,0 +1,105 @@ +/* + * \brief USB net driver + * \author Stefan Kalkowski + * \date 2018-06-27 + */ + +/* + * Copyright (C) 2018 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#ifndef _SRC__DRIVERS__USB_NET__DRIVER_H_ +#define _SRC__DRIVERS__USB_NET__DRIVER_H_ + +#include +#include +#include +#include +#include + +#include + +struct usb_device_id; +struct usb_interface; +struct usb_device; + +struct Driver +{ + using Label = Genode::String<64>; + + struct Task + { + Lx::Task task; + Genode::Signal_handler handler; + + void handle_signal() + { + task.unblock(); + Lx::scheduler().schedule(); + } + + template + Task(Genode::Entrypoint & ep, ARGS &&... args) + : task(args...), handler(ep, *this, &Task::handle_signal) {} + }; + + struct Device + { + using Le = Genode::List_element; + + Le le { this }; + Label label; + Driver &driver; + Genode::Env &env; + Genode::Allocator_avl &alloc; + Task state_task; + Task urb_task; + Usb::Connection usb { env, &alloc, label.string(), + 512 * 1024, state_task.handler }; + usb_device * udev = nullptr; + bool updated = true; + + Device(Driver & drv, Label label); + ~Device(); + + static void state_task_entry(void *); + static void urb_task_entry(void *); + void register_device(); + void unregister_device(); + void scan_interfaces(unsigned iface_idx); + void scan_altsettings(usb_interface * iface, + unsigned iface_idx, unsigned alt_idx); + void probe_interface(usb_interface *, usb_device_id *); + void remove_interface(usb_interface *); + }; + + struct Devices : Genode::List + { + template + void for_each(FN const & fn) + { + Device::Le * cur = first(); + for (Device::Le * next = cur ? cur->next() : nullptr; cur; + cur = next, next = cur ? cur->next() : nullptr) + fn(*cur->object()); + } + }; + + Devices devices; + Genode::Env &env; + Genode::Entrypoint &ep { env.ep() }; + Genode::Heap heap { env.ram(), env.rm() }; + Genode::Allocator_avl alloc { &heap }; + Root root { env, heap }; + Genode::Constructible main_task; + Genode::Constructible report_rom; + + Driver(Genode::Env &env); + + static void main_task_entry(void *); +}; + +#endif /* _SRC__DRIVERS__USB_HID__DRIVER_H_ */ diff --git a/repos/dde_linux/src/drivers/usb_net/dummies.c b/repos/dde_linux/src/drivers/usb_net/dummies.c new file mode 100644 index 000000000..0aec439ef --- /dev/null +++ b/repos/dde_linux/src/drivers/usb_net/dummies.c @@ -0,0 +1,518 @@ +#include + +#if 0 +#define TRACE \ + do { \ + lx_printf("%s not implemented\n", __func__); \ + } while (0) +#else +#define TRACE do { ; } while (0) +#endif + +#define TRACE_AND_STOP \ + do { \ + lx_printf("%s not implemented\n", __func__); \ + BUG(); \ + } while (0) + +struct page *alloc_pages(gfp_t gfp_mask, unsigned int order) +{ + TRACE_AND_STOP; + return NULL; +} + +u16 bitrev16(u16 in) +{ + TRACE_AND_STOP; + return -1; +} + +struct usb_cdc_parsed_header; +struct usb_interface; +int cdc_parse_cdc_header(struct usb_cdc_parsed_header *hdr, struct usb_interface *intf, u8 *buffer, int buflen) +{ + TRACE_AND_STOP; + return -1; +} + +u16 crc16(u16 crc, const u8 *buffer, size_t len) +{ + TRACE_AND_STOP; + return -1; +} + +__sum16 csum_fold(__wsum csum) +{ + TRACE_AND_STOP; + return -1; +} + +__wsum csum_partial(const void *buff, int len, __wsum sum) +{ + TRACE_AND_STOP; + return -1; +} + +void * dev_get_drvdata(const struct device *dev) +{ + TRACE_AND_STOP; + return NULL; +} + +int device_set_wakeup_enable(struct device *dev, bool enable) +{ + TRACE_AND_STOP; + return -1; +} + +struct sk_buff; +void dev_kfree_skb_any(struct sk_buff *skb) +{ + TRACE_AND_STOP; +} + +void dst_release(struct dst_entry *dst) +{ + TRACE_AND_STOP; +} + +struct net_device; +u32 ethtool_op_get_link(struct net_device *dev) +{ + TRACE_AND_STOP; + return -1; +} + +int ethtool_op_get_ts_info(struct net_device *dev, struct ethtool_ts_info *eti) +{ + TRACE_AND_STOP; + return -1; +} + +bool file_ns_capable(const struct file *file, struct user_namespace *ns, int cap) +{ + TRACE_AND_STOP; + return -1; +} + +void free_netdev(struct net_device * ndev) +{ + TRACE_AND_STOP; +} + +void free_uid(struct user_struct * user) +{ + TRACE_AND_STOP; +} + +struct mii_if_info; +int generic_mii_ioctl(struct mii_if_info *mii_if, struct mii_ioctl_data *mii_data, int cmd, unsigned int *duplex_changed) +{ + TRACE_AND_STOP; + return -1; +} + +void get_page(struct page *page) +{ + TRACE_AND_STOP; +} + +bool gfpflags_allow_blocking(const gfp_t gfp_flags) +{ + TRACE_AND_STOP; + return -1; +} + +bool gfp_pfmemalloc_allowed(gfp_t gfp_flags) +{ + TRACE_AND_STOP; + return -1; +} + +int hex2bin(u8 *dst, const char *src, size_t count) +{ + TRACE_AND_STOP; + return -1; +} + +int in_irq() +{ + TRACE_AND_STOP; + return -1; +} + +void *kmap_atomic(struct page *page) +{ + TRACE_AND_STOP; + return NULL; +} + +int memcmp(const void *s1, const void *s2, size_t size) +{ + TRACE_AND_STOP; + return -1; +} + +void mii_ethtool_get_link_ksettings( struct mii_if_info *mii, struct ethtool_link_ksettings *cmd) +{ + TRACE_AND_STOP; +} + +int mii_ethtool_set_link_ksettings( struct mii_if_info *mii, const struct ethtool_link_ksettings *cmd) +{ + TRACE_AND_STOP; + return -1; +} + +unsigned netdev_mc_count(struct net_device * dev) +{ + TRACE; + return 1; +} + +int netdev_mc_empty(struct net_device * ndev) +{ + TRACE; + return 1; +} + +void netdev_stats_to_stats64(struct rtnl_link_stats64 *stats64, const struct net_device_stats *netdev_stats) +{ + TRACE_AND_STOP; +} + +bool netdev_uses_dsa(struct net_device *dev) +{ + TRACE; + return false; +} + +void netif_device_attach(struct net_device *dev) +{ + TRACE; +} + +void netif_device_detach(struct net_device *dev) +{ + TRACE_AND_STOP; +} + +int netif_device_present(struct net_device * d) +{ + TRACE; + return 1; +} + +u32 netif_msg_init(int arg0, int arg1) +{ + TRACE; + return 0; +} + +void netif_start_queue(struct net_device *dev) +{ + TRACE; +} + +void netif_stop_queue(struct net_device *dev) +{ + TRACE_AND_STOP; +} + +void netif_trans_update(struct net_device *dev) +{ + TRACE; +} + +void netif_tx_wake_all_queues(struct net_device *dev) +{ + TRACE_AND_STOP; +} + +void netif_wake_queue(struct net_device * d) +{ + TRACE; +} + +const void *of_get_mac_address(struct device_node *np) +{ + TRACE; + return NULL; +} + +void pm_runtime_enable(struct device *dev) +{ + TRACE; +} + +void read_lock_bh(rwlock_t * l) +{ + TRACE_AND_STOP; +} + +void read_unlock_bh(rwlock_t * l) +{ + TRACE_AND_STOP; +} + +void unregister_netdev(struct net_device * dev) +{ + TRACE_AND_STOP; +} + +void secpath_reset(struct sk_buff * skb) +{ + TRACE; +} + +void __set_current_state(int state) +{ + TRACE_AND_STOP; +} + +void sg_init_table(struct scatterlist *sg, unsigned int arg) +{ + TRACE_AND_STOP; +} + +void sg_set_buf(struct scatterlist *sg, const void *buf, unsigned int buflen) +{ + TRACE_AND_STOP; +} + +void sg_set_page(struct scatterlist *sg, struct page *page, unsigned int len, unsigned int offset) +{ + TRACE_AND_STOP; +} + +void sk_free(struct sock *sk) +{ + TRACE_AND_STOP; +} + +void sock_efree(struct sk_buff *skb) +{ + TRACE_AND_STOP; +} + +void spin_lock_irq(spinlock_t *lock) +{ + TRACE_AND_STOP; +} + +void spin_lock_nested(spinlock_t *lock, int subclass) +{ + TRACE; +} + +void spin_unlock_irq(spinlock_t *lock) +{ + TRACE_AND_STOP; +} + +size_t strlcpy(char *dest, const char *src, size_t size) +{ + TRACE_AND_STOP; + return -1; +} + +void tasklet_kill(struct tasklet_struct *t) +{ + TRACE_AND_STOP; +} + +void trace_consume_skb(struct sk_buff *skb) +{ + TRACE; +} + +void trace_kfree_skb(struct sk_buff *skb, void *arg) +{ + TRACE; +} + +unsigned int u64_stats_fetch_begin_irq(const struct u64_stats_sync *p) +{ + TRACE_AND_STOP; + return -1; +} + +bool u64_stats_fetch_retry_irq(const struct u64_stats_sync *p, unsigned int s) +{ + TRACE_AND_STOP; + return -1; +} + +struct usb_device; +int usb_clear_halt(struct usb_device *dev, int pipe) +{ + TRACE_AND_STOP; + return -1; +} + +struct usb_driver; +int usb_driver_claim_interface(struct usb_driver *driver, struct usb_interface *iface, void *priv) +{ + TRACE_AND_STOP; + return -1; +} + +void usb_driver_release_interface(struct usb_driver *driver, struct usb_interface *iface) +{ + TRACE_AND_STOP; +} + +struct usb_anchor; +struct urb *usb_get_from_anchor(struct usb_anchor *anchor) +{ + TRACE_AND_STOP; + return NULL; +} + +struct urb *usb_get_urb(struct urb *urb) +{ + TRACE_AND_STOP; + return NULL; +} + +int usb_interrupt_msg(struct usb_device *usb_dev, unsigned int pipe, void *data, int len, int *actual_length, int timeout) +{ + TRACE_AND_STOP; + return -1; +} + +void usb_scuttle_anchored_urbs(struct usb_anchor *anchor) +{ + TRACE_AND_STOP; +} + +int usb_string(struct usb_device *dev, int index, char *buf, size_t size) +{ + TRACE_AND_STOP; + return -1; +} + +ktime_t ktime_get_real(void) +{ + TRACE_AND_STOP; + return -1; +} + +void kunmap_atomic(void *addr) +{ + TRACE_AND_STOP; +} + +void might_sleep() +{ + TRACE_AND_STOP; +} + +bool page_is_pfmemalloc(struct page *page) +{ + TRACE_AND_STOP; + return -1; +} + +void put_page(struct page *page) +{ + TRACE_AND_STOP; +} + +struct usb_interface *usb_ifnum_to_if(const struct usb_device *dev, unsigned ifnum) +{ + TRACE_AND_STOP; + return NULL; +} + +void usb_kill_urb(struct urb *urb) +{ + TRACE_AND_STOP; +} + +int usb_set_interface(struct usb_device *dev, int ifnum, int alternate) +{ + TRACE; + return 0; +} + +int usb_unlink_urb(struct urb *urb) +{ + TRACE_AND_STOP; + return -1; +} + +void usleep_range(unsigned long min, unsigned long max) +{ + TRACE; +} + +void phy_stop(struct phy_device *phydev) +{ + TRACE; +} + +void phy_disconnect(struct phy_device *phydev) +{ + TRACE; +} + +void phy_print_status(struct phy_device *phydev) +{ + TRACE; +} + +int phy_mii_ioctl(struct phy_device *phydev, struct ifreq *ifr, int cmd) +{ + TRACE; + return 0; +} + +typedef int phy_interface_t; +struct phy_device * phy_connect(struct net_device *dev, const char *bus_id, void (*handler)(struct net_device *), phy_interface_t interface) +{ + TRACE; + return 0; +} + +int genphy_resume(struct phy_device *phydev) { TRACE; return 0; } + +void phy_start(struct phy_device *phydev) { TRACE; } + +struct mii_bus; +void mdiobus_free(struct mii_bus *bus) { TRACE; } + +void mdiobus_unregister(struct mii_bus *bus) { TRACE; } + +struct mii_bus *mdiobus_alloc_size(size_t size) +{ + TRACE_AND_STOP; + return NULL; +} + +int __mdiobus_register(struct mii_bus *bus, struct module *owner) +{ + TRACE_AND_STOP; + return -1; +} + +int phy_ethtool_get_link_ksettings(struct net_device *ndev, struct ethtool_link_ksettings *cmd) +{ + TRACE_AND_STOP; + return -1; +} + +int phy_ethtool_set_link_ksettings(struct net_device *ndev, const struct ethtool_link_ksettings *cmd) +{ + TRACE_AND_STOP; + return -1; +} + +int phy_ethtool_nway_reset(struct net_device *ndev) +{ + TRACE_AND_STOP; + return -1; +} + +int sysctl_tstamp_allow_data; +struct user_namespace init_user_ns; diff --git a/repos/dde_linux/src/drivers/usb_net/lx_emul.cc b/repos/dde_linux/src/drivers/usb_net/lx_emul.cc new file mode 100644 index 000000000..e6fa4b335 --- /dev/null +++ b/repos/dde_linux/src/drivers/usb_net/lx_emul.cc @@ -0,0 +1,539 @@ +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#define TRACE do { ; } while (0) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include + +static int usb_match_device(struct usb_device *dev, + const struct usb_device_id *id) +{ + if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) && + id->idVendor != le16_to_cpu(dev->descriptor.idVendor)) + return 0; + + if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) && + id->idProduct != le16_to_cpu(dev->descriptor.idProduct)) + return 0; + + if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) && + (id->bcdDevice_lo > le16_to_cpu(dev->descriptor.bcdDevice))) + return 0; + + if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) && + (id->bcdDevice_hi < le16_to_cpu(dev->descriptor.bcdDevice))) + return 0; + + if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) && + (id->bDeviceClass != dev->descriptor.bDeviceClass)) + return 0; + + if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) && + (id->bDeviceSubClass != dev->descriptor.bDeviceSubClass)) + return 0; + + if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) && + (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol)) + return 0; + + return 1; +} + + +static int usb_match_one_id_intf(struct usb_device *dev, + struct usb_host_interface *intf, + const struct usb_device_id *id) +{ + if (dev->descriptor.bDeviceClass == USB_CLASS_VENDOR_SPEC && + !(id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) && + (id->match_flags & (USB_DEVICE_ID_MATCH_INT_CLASS | + USB_DEVICE_ID_MATCH_INT_SUBCLASS | + USB_DEVICE_ID_MATCH_INT_PROTOCOL | + USB_DEVICE_ID_MATCH_INT_NUMBER))) + return 0; + + if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) && + (id->bInterfaceClass != intf->desc.bInterfaceClass)) + return 0; + + if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS) && + (id->bInterfaceSubClass != intf->desc.bInterfaceSubClass)) + return 0; + + if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL) && + (id->bInterfaceProtocol != intf->desc.bInterfaceProtocol)) + return 0; + + if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_NUMBER) && + (id->bInterfaceNumber != intf->desc.bInterfaceNumber)) + return 0; + + return 1; +} + + +int usb_match_one_id(struct usb_interface *interface, + const struct usb_device_id *id) +{ + struct usb_host_interface *intf; + struct usb_device *dev; + + if (id == NULL) + return 0; + + intf = interface->cur_altsetting; + dev = interface_to_usbdev(interface); + + if (!usb_match_device(dev, id)) + return 0; + + return usb_match_one_id_intf(dev, intf, id); +} + +#include + + +class Addr_to_page_mapping : public Genode::List::Element +{ + private: + + struct page *_page { nullptr }; + + static Genode::List & _list() + { + static Genode::List _l; + return _l; + } + + public: + + Addr_to_page_mapping(struct page *page) + : _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->_page = page; + _list().insert(m); + } + + static struct page * remove(unsigned long addr) + { + for (Addr_to_page_mapping *m = _list().first(); m; m = m->next()) + if ((unsigned long)m->_page->addr == addr) { + struct page * ret = m->_page; + _list().remove(m); + Lx::Malloc::mem().free(m); + return ret; + } + + return nullptr; + } +}; + +struct Lx_driver +{ + using Element = Genode::List_element; + using List = Genode::List; + + usb_driver & drv; + Element le { this }; + + Lx_driver(usb_driver & drv) : drv(drv) { list().insert(&le); } + + usb_device_id * match(usb_interface * iface) + { + struct usb_device_id * id = const_cast(drv.id_table); + for (; id->idVendor || id->idProduct || id->bDeviceClass || + id->bInterfaceClass || id->driver_info; id++) + if (usb_match_one_id(iface, id)) return id; + return nullptr; + } + + int probe(usb_interface * iface, usb_device_id * id) + { + iface->dev.driver = &drv.drvwrap.driver; + if (drv.probe) return drv.probe(iface, id); + return 0; + } + + static List & list() + { + static List _list; + return _list; + } +}; + +struct task_struct *current; +struct workqueue_struct *system_wq; +unsigned long jiffies; + +Genode::Ram_dataspace_capability Lx::backend_alloc(Genode::addr_t size, Genode::Cache_attribute cached) { + return Lx_kit::env().env().ram().alloc(size, cached); } + + + +int usb_register_driver(struct usb_driver * driver, struct module *, const char *) +{ + INIT_LIST_HEAD(&driver->dynids.list); + if (driver) new (Lx::Malloc::mem()) Lx_driver(*driver); + return 0; +} + + +void Driver::Device::probe_interface(usb_interface * iface, usb_device_id * id) +{ + using Le = Genode::List_element; + for (Le *le = Lx_driver::list().first(); le; le = le->next()) { + usb_device_id * id = le->object()->match(iface); + if (id && le->object()->probe(iface, id)) return; + } +} + + +void Driver::Device::remove_interface(usb_interface * iface) +{ + to_usb_driver(iface->dev.driver)->disconnect(iface); + for (unsigned i = 0; i < iface->num_altsetting; i++) { + if (iface->altsetting[i].extra) + kfree(iface->altsetting[i].extra); + kfree(iface->altsetting[i].endpoint); + kfree(iface->altsetting); + } + kfree(iface); +} + + +long __wait_completion(struct completion *work, unsigned long timeout) +{ + Lx::timer_update_jiffies(); + struct process_timer timer { *Lx::scheduler().current() }; + unsigned long expire = timeout + jiffies; + + if (timeout) { + timer_setup(&timer.timer, process_timeout, 0); + mod_timer(&timer.timer, expire); + } + + while (!work->done) { + + if (timeout && expire <= jiffies) return 0; + + Lx::Task * task = Lx::scheduler().current(); + work->task = (void *)task; + task->block_and_schedule(); + } + + if (timeout) del_timer(&timer.timer); + + work->done = 0; + return (expire > jiffies) ? (expire - jiffies) : 1; +} + + +u16 get_unaligned_le16(const void *p) +{ + const struct __una_u16 *ptr = (const struct __una_u16 *)p; + return ptr->x; +} + + +u32 get_unaligned_le32(const void *p) +{ + const struct __una_u32 *ptr = (const struct __una_u32 *)p; + return ptr->x; +} + + +enum { MAC_LEN = 17 }; + + +static void snprint_mac(u8 *buf, u8 *mac) +{ + for (int i = 0; i < ETH_ALEN; i++) { + Genode::snprintf((char *)&buf[i * 3], 3, "%02x", mac[i]); + if ((i * 3) < MAC_LEN) + buf[(i * 3) + 2] = ':'; + } + + buf[MAC_LEN] = 0; +} + + +static void random_ether_addr(u8 *addr) +{ + using namespace Genode; + + u8 str[MAC_LEN + 1]; + u8 fallback[] = { 0x2e, 0x60, 0x90, 0x0c, 0x4e, 0x01 }; + Nic::Mac_address mac; + + Xml_node config_node = Lx_kit::env().config_rom().xml(); + + /* try using configured mac */ + try { + Xml_node::Attribute mac_node = config_node.attribute("mac"); + mac_node.value(&mac); + } catch (...) { + /* use fallback mac */ + snprint_mac(str, fallback); + Genode::warning("No mac address or wrong format attribute in - using fallback (", str, ")"); + + Genode::memcpy(addr, fallback, ETH_ALEN); + return; + } + + /* use configured mac*/ + Genode::memcpy(addr, mac.addr, ETH_ALEN); + snprint_mac(str, (u8 *)mac.addr); + Genode::log("Using configured mac: ", str); +} + + +void eth_hw_addr_random(struct net_device *dev) +{ + random_ether_addr(dev->dev_addr); +} + + +void eth_random_addr(u8 *addr) +{ + random_ether_addr(addr); +} + + +struct net_device *alloc_etherdev(int sizeof_priv) +{ + net_device *dev = (net_device*) kzalloc(sizeof(net_device), 0); + dev->mtu = 1500; + dev->hard_header_len = 0; + dev->priv = kzalloc(sizeof_priv, 0); + dev->dev_addr = (unsigned char*) kzalloc(ETH_ALEN, 0); + //memset(dev->_dev_addr, 0, sizeof(dev->_dev_addr)); + return dev; +} + + +void *__alloc_percpu(size_t size, size_t align) +{ + return kmalloc(size, 0); +} + + +int mii_nway_restart(struct mii_if_info *mii) +{ + /* if autoneg is off, it's an error */ + int bmcr = mii->mdio_read(mii->dev, mii->phy_id, MII_BMCR); + + if (bmcr & BMCR_ANENABLE) { + printk("Reenable\n"); + bmcr |= BMCR_ANRESTART; + mii->mdio_write(mii->dev, mii->phy_id, MII_BMCR, bmcr); + return 0; + } + + return -EINVAL; +} + + +static net_device * single_net_device = nullptr; + +int register_netdev(struct net_device *dev) +{ + dev->state |= 1 << __LINK_STATE_START; + + int err = dev->netdev_ops->ndo_open(dev); + if (err) return err; + + if (dev->netdev_ops->ndo_set_rx_mode) + dev->netdev_ops->ndo_set_rx_mode(dev); + + single_net_device = dev; + return 0; +}; + + +net_device * Session_component::_register_session_component(Session_component & s, + Genode::Session_label policy) +{ + if (single_net_device) single_net_device->session_component = (void*) &s; + return single_net_device; +} + + +void tasklet_schedule(struct tasklet_struct *t) +{ + Lx::Work *lx_work = (Lx::Work *)tasklet_wq->task; + lx_work->schedule_tasklet(t); + lx_work->unblock(); +} + + +struct workqueue_struct *create_singlethread_workqueue(char const *name) +{ + workqueue_struct *wq = (workqueue_struct *)kzalloc(sizeof(workqueue_struct), 0); + Lx::Work *work = Lx::Work::alloc_work_queue(&Lx::Malloc::mem(), name); + wq->task = (void *)work; + + return wq; +} + + +struct workqueue_struct *alloc_workqueue(const char *fmt, unsigned int flags, + int max_active, ...) +{ + return create_singlethread_workqueue(fmt); +} + + +int dev_set_drvdata(struct device *dev, void *data) +{ + dev->driver_data = data; + return 0; +} + + +int netif_running(const struct net_device *dev) +{ + return dev->state & (1 << __LINK_STATE_START); +} + + +void netif_carrier_off(struct net_device *dev) +{ + dev->state |= 1 << __LINK_STATE_NOCARRIER; + if (dev->session_component) + reinterpret_cast(dev->session_component)->link_state(false); +} + + +int netif_carrier_ok(const struct net_device *dev) +{ + return !(dev->state & (1 << __LINK_STATE_NOCARRIER)); +} + + +void *kmem_cache_alloc_node(struct kmem_cache *cache, gfp_t gfp_flags, int arg) +{ + return (void*)cache->alloc(); +} + + +int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd) +{ + ecmd->duplex = DUPLEX_FULL; + return 0; +} + + +void netif_carrier_on(struct net_device *dev) +{ + dev->state &= ~(1 << __LINK_STATE_NOCARRIER); + if (dev->session_component) + reinterpret_cast(dev->session_component)->link_state(true); +} + + +int netif_rx(struct sk_buff * skb) +{ + if (skb->dev->session_component) + reinterpret_cast(skb->dev->session_component)->receive(skb); + + dev_kfree_skb(skb); + return NET_RX_SUCCESS; +} + + +int is_valid_ether_addr(const u8 * a) +{ + for (unsigned i = 0; i < ETH_ALEN; i++) + if (a[i] != 0 && a[i] != 255) return 1; + return 0; +} + + +unsigned int mii_check_media (struct mii_if_info *mii, unsigned int ok_to_print, unsigned int init_media) +{ + if (mii_link_ok(mii)) netif_carrier_on(mii->dev); + else netif_carrier_off(mii->dev); + return 0; +} + + +int mii_link_ok (struct mii_if_info *mii) +{ + /* first, a dummy read, needed to latch some MII phys */ + mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR); + if (mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR) & BMSR_LSTATUS) + return 1; + return 0; +} + + +static struct page *allocate_pages(gfp_t gfp_mask, unsigned int size) +{ + struct page *page = (struct page *)kzalloc(sizeof(struct page), 0); + + page->addr = Lx::Malloc::dma().alloc_large(size); + page->size = size; + + if (!page->addr) { + Genode::error("alloc_pages: ", size, " failed"); + kfree(page); + return 0; + } + + Addr_to_page_mapping::insert(page); + + atomic_set(&page->_count, 1); + + return page; +} + + +void *page_frag_alloc(struct page_frag_cache *nc, unsigned int fragsz, gfp_t gfp_mask) +{ + struct page *page = allocate_pages(gfp_mask, fragsz); + if (!page) return nullptr; + + return page->addr; +} + + +void page_frag_free(void *addr) +{ + struct page *page = Addr_to_page_mapping::remove((unsigned long)addr); + + if (!atomic_dec_and_test(&page->_count)) + Genode::error("page reference count != 0"); + + Lx::Malloc::dma().free_large(page->addr); + kfree(page); +} diff --git a/repos/dde_linux/src/drivers/usb_net/lx_emul.h b/repos/dde_linux/src/drivers/usb_net/lx_emul.h new file mode 100644 index 000000000..a56cf02b9 --- /dev/null +++ b/repos/dde_linux/src/drivers/usb_net/lx_emul.h @@ -0,0 +1,1296 @@ +/* + * \brief USB net driver Linux emulation environment + * \author Stefan Kalkowski + * \date 2018-06-13 + */ + +/* + * Copyright (C) 2018 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#ifndef _SRC__DRIVERS__USB_NET__LX_EMUL_H_ +#define _SRC__DRIVERS__USB_NET__LX_EMUL_H_ + +#include +#include + +#include + +#define __KERNEL__ 1 + +#include +#include +#include +#include + +#define __KERNEL_DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) + +enum { HZ = 100UL }; + +#include +#include +#include + +typedef int clockid_t; + +#include +#include +#include + +typedef __u16 __le16; +typedef __u32 __le32; +typedef __u64 __le64; +typedef __u64 __be64; + +#define __aligned_u64 __u64 __attribute__((aligned(8))) + +#include +#include +#include +#include +#include +#include +//#define __init +//#define __exit +//#define THIS_MODULE 0 +//struct module; +//#define module_init(fn) int module_##fn(void) { return fn(); } +//#define module_exit(fn) void module_exit_##fn(void) { fn(); } +//#define EXPORT_SYMBOL_GPL(x) +//#define MODULE_AUTHOR(name) +//#define MODULE_DESCRIPTION(desc) +//#define MODULE_LICENSE(x) +//#define MODULE_VERSION(x) +//#define MODULE_PARM_DESC(_parm, desc) +//#define module_param(name, type, perm) +#include +#include + +#define READ_ONCE(x) x + +#include +#include +#include +#include +#include +#include + +struct user_namespace {}; + +struct cred { + struct user_namespace * user_ns; +}; + +struct file +{ + unsigned int f_flags; + void * private_data; + const struct cred * f_cred; +}; + +struct device; +struct device_driver; + +typedef struct { __u8 b[16]; } uuid_le; +void * dev_get_drvdata(const struct device *dev); +int dev_set_drvdata(struct device *dev, void *data); + +#define netdev_dbg(dev, fmt, args...) +#define netdev_warn(dev, fmt, args...) lx_printf("netdev_warn: " fmt, ##args) +#define netdev_err(dev, fmt, args...) lx_printf("netdev_err: " fmt, ##args) +#define netdev_info(dev, fmt, args...) lx_printf("netdev_info: " fmt, ##args) + +#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_err( dev, format, arg...) lx_printf("dev_err: " format , ## arg) +#define dev_dbg( dev, format, arg...) + +#define netif_info(priv, type, dev, fmt, args...) lx_printf("netif_info: " fmt, ## args); +#define netif_dbg(priv, type, dev, fmt, args...) +#define netif_err(priv, type, dev, fmt, args...) lx_printf("netif_err: " fmt, ## args); + +#define pr_debug(fmt, ...) +#define pr_info(fmt, ...) printk(KERN_INFO fmt, ##__VA_ARGS__) +#define pr_err(fmt, ...) printk(KERN_ERR fmt, ##__VA_ARGS__) +#define pr_warn(fmt, ...) printk(KERN_ERR fmt, ##__VA_ARGS__) +#define pr_info_once(fmt, ...) printk(KERN_INFO fmt, ##__VA_ARGS__) +#define pr_notice(fmt, ...) printk(KERN_NOTICE fmt, ##__VA_ARGS__) +#define pr_emerg(fmt, ...) printk(KERN_INFO fmt, ##__VA_ARGS__) + +struct bus_type +{ + int (*match)(struct device *dev, struct device_driver *drv); + int (*probe)(struct device *dev); +}; + +struct device_driver +{ + char const *name; + struct bus_type *bus; + struct module *owner; + const char *mod_name; +}; + +typedef int devt; + + struct device_type { + const char *name; +}; + +struct class +{ + const char *name; + char *(*devnode)(struct device *dev, mode_t *mode); +}; + +struct device_node; + +struct device +{ + char const * name; + struct device * parent; + struct kobject * kobj; + struct device_driver * driver; + struct bus_type * bus; + dev_t devt; + struct class * class; + const struct device_type * type; + void (*release)(struct device *dev); + void * driver_data; + struct device_node * of_node; +}; + +#define module_driver(__driver, __register, __unregister, ...) \ + static int __init __driver##_init(void) \ + { \ + return __register(&(__driver) , ##__VA_ARGS__); \ + } \ + module_init(__driver##_init); \ + static void __exit __driver##_exit(void) \ + { \ + __unregister(&(__driver) , ##__VA_ARGS__); \ + } \ + module_exit(__driver##_exit); + +#define KBUILD_MODNAME "" + +void kfree(const void *); + +#define from_timer(var, callback_timer, timer_fieldname) \ + container_of(callback_timer, typeof(*var), timer_fieldname) + +void *kmalloc(size_t size, gfp_t flags); +void *kzalloc(size_t size, gfp_t flags); +int snprintf(char *buf, size_t size, const char *fmt, ...); +const char *dev_name(const struct device *dev); + +struct __una_u16 { u16 x; } __attribute__((packed)); +struct __una_u32 { u32 x; } __attribute__((packed)); + +u16 get_unaligned_le16(const void *p); +u32 get_unaligned_le32(const void *p); + +#define clamp(val, lo, hi) min((typeof(val))max(val, lo), hi) + +struct completion +{ + unsigned int done; + void * task; +}; + +struct notifier_block; + +enum { + ESHUTDOWN = 58, +}; + +void msleep(unsigned int); + +#define PAGE_SIZE 4096 + +#define rcu_assign_pointer(p,v) p = v + +signed long schedule_timeout(signed long timeout); + +int device_set_wakeup_enable(struct device *dev, bool enable); + +struct tasklet_struct +{ + void (*func)(unsigned long); + unsigned long data; +}; + +struct net_device; +struct ifreq; +struct sk_buff; +struct rtnl_link_stats64; + +enum netdev_tx { + NETDEV_TX_OK = 0x00, + NETDEV_TX_BUSY = 0x10, + NETDEV_TX_LOCKED = 0x20, +}; +typedef enum netdev_tx netdev_tx_t; + +#include + +struct net_device_ops { + int (*ndo_open) (struct net_device *dev); + int (*ndo_stop) (struct net_device *dev); + netdev_tx_t (*ndo_start_xmit) (struct sk_buff *skb, struct net_device *dev); + void (*ndo_set_rx_mode) (struct net_device *dev); + int (*ndo_change_mtu) (struct net_device *dev, int new_mtu); + int (*ndo_validate_addr) (struct net_device *dev); + void (*ndo_tx_timeout) (struct net_device *dev); + int (*ndo_set_mac_address)(struct net_device *dev, void *addr); + int (*ndo_do_ioctl)(struct net_device *dev, struct ifreq *ifr, int cmd); + int (*ndo_set_features)(struct net_device *dev, netdev_features_t features); + void (*ndo_get_stats64)(struct net_device *dev, struct rtnl_link_stats64 *storage); +}; + +struct net_device_stats +{ + unsigned long rx_packets; + unsigned long tx_packets; + unsigned long rx_bytes; + unsigned long tx_bytes; + unsigned long rx_errors; + unsigned long tx_errors; + unsigned long rx_dropped; + unsigned long tx_dropped; + unsigned long rx_length_errors; + unsigned long rx_over_errors; + unsigned long rx_crc_errors; + unsigned long rx_frame_errors; +}; + +enum netdev_state_t { + __LINK_STATE_START, + __LINK_STATE_PRESENT, + __LINK_STATE_NOCARRIER, + __LINK_STATE_LINKWATCH_PENDING, + __LINK_STATE_DORMANT, +}; + +enum { MAX_ADDR_LEN = 32, IFNAMESZ = 16 }; + +struct net_device +{ + char name[IFNAMESZ]; + unsigned long state; + netdev_features_t features; + struct net_device_stats stats; + netdev_features_t hw_features; + const struct net_device_ops *netdev_ops; + const struct ethtool_ops *ethtool_ops; + const struct header_ops *header_ops; + unsigned int flags; + unsigned int priv_flags; + unsigned short hard_header_len; + unsigned char min_header_len; + unsigned long mtu; + unsigned long min_mtu; + unsigned long max_mtu; + unsigned short type; + unsigned char addr_len; + unsigned char *dev_addr; + unsigned char broadcast[MAX_ADDR_LEN]; + unsigned long tx_queue_len; + int watchdog_timeo; + struct timer_list watchdog_timer; + struct device dev; + u16 gso_max_segs; + struct phy_device *phydev; + unsigned short needed_headroom; + unsigned short needed_tailroom; + void *priv; + unsigned char perm_addr[MAX_ADDR_LEN]; + unsigned char addr_assign_type; + int ifindex; + void *session_component; +}; + +struct usbnet; + +struct ethtool_eeprom; +struct ethtool_drvinfo; + +struct sock; + +struct kvec +{ + void *iov_base; + size_t iov_len; +}; + +struct iov_iter {}; +size_t iov_iter_count(struct iov_iter *i); + +typedef int raw_hdlc_proto; +typedef int cisco_proto; +typedef int fr_proto; +typedef int fr_proto_pvc; +typedef int fr_proto_pvc_info; +typedef int sync_serial_settings; +typedef int te1_settings; + +struct rndis_indicate; + +enum { ETH_ALEN = 6 }; + +int netif_running(const struct net_device *dev); +int phy_mii_ioctl(struct phy_device *phydev, struct ifreq *ifr, int cmd); +static inline void *netdev_priv(const struct net_device *dev) { return dev->priv; } + +int usbnet_read_cmd(struct usbnet *dev, u8 cmd, u8 reqtype, u16 value, u16 index, void *data, u16 size); +int usbnet_read_cmd_nopm(struct usbnet *dev, u8 cmd, u8 reqtype, u16 value, u16 index, void *data, u16 size); + +typedef __u32 __wsum; + +static inline int rcu_read_lock_held(void) { return 1; } +static inline int rcu_read_lock_bh_held(void) { return 1; } + +enum { NUMA_NO_NODE = -1 }; + +struct ts_state +{ + char cb[40]; +}; + +struct ts_config +{ + unsigned int (*get_next_block)(unsigned int consumed, + const u8 **dst, + struct ts_config *conf, + struct ts_state *state); + void (*finish)(struct ts_config *conf, + struct ts_state *state); +}; + +struct flow_dissector_key_control +{ + u16 thoff; + u16 addr_type; + u32 flags; +}; + +struct flow_keys +{ + struct flow_dissector_key_control control; +}; + +struct flow_dissector_key {}; + +struct flow_dissector {}; + +extern struct flow_dissector flow_keys_dissector; +extern struct flow_dissector flow_keys_buf_dissector; + +struct flowi4 {}; +struct flowi6 {}; + +__u32 __get_hash_from_flowi6(const struct flowi6 *fl6, struct flow_keys *keys); + +bool flow_keys_have_l4(struct flow_keys *keys); + +__u32 __get_hash_from_flowi4(const struct flowi4 *fl4, struct flow_keys *keys); + +bool gfpflags_allow_blocking(const gfp_t gfp_flags); + +struct lock_class_key { }; + +#define lockdep_set_class(lock, key) + +struct page +{ + atomic_t _count; + void *addr; + dma_addr_t paddr; + unsigned long private; + unsigned long size; +} __attribute((packed)); + +static inline struct page *compound_head(struct page *page) { return page; } + +bool page_is_pfmemalloc(struct page *page); + +void __free_page_frag(void *addr); + +struct page *alloc_pages_node(int nid, gfp_t gfp_mask, unsigned int order); + +void get_page(struct page *page); +void put_page(struct page *page); + +static inline void *page_address(struct page *page) { return page->addr; }; + +struct page_frag +{ + struct page *page; + __u16 offset; + __u16 size; +}; + +enum dma_data_direction { DMA_FROM_DEVICE = 2 }; + +dma_addr_t dma_map_page(struct device *dev, struct page *page, size_t offset, size_t size, enum dma_data_direction dir); + +void dma_sync_single_for_cpu(struct device *dev, dma_addr_t addr, size_t size, enum dma_data_direction dir); + +#define L1_CACHE_BYTES 32 + +size_t csum_and_copy_from_iter(void *addr, size_t bytes, __wsum *csum, struct iov_iter *i); + +__wsum csum_block_add(__wsum csum, __wsum csum2, int offset); +__wsum csum_sub(__wsum csum, __wsum addend); +__wsum csum_partial(const void *buff, int len, __wsum sum); + +bool csum_and_copy_from_iter_full(void *addr, size_t bytes, __wsum *csum, struct iov_iter *i); +bool copy_from_iter_full(void *addr, size_t bytes, struct iov_iter *i); +__wsum csum_block_sub(__wsum, __wsum, int); +typedef unsigned __poll_t; + +typedef struct poll_table_struct { } poll_table; +size_t copy_to_iter(void *addr, size_t bytes, struct iov_iter *i); +struct timespec ktime_to_timespec(const ktime_t kt); + +struct socket; +typedef u64 netdev_features_t; +typedef __u16 __sum16; + +__sum16 csum_fold(__wsum csum); +__wsum csum_unfold(__sum16 n); +__wsum csum_add(__wsum csum, __wsum addend); +__wsum remcsum_adjust(void *ptr, __wsum csum, int start, int offset); + +struct sk_buff; + +void dev_kfree_skb_any(struct sk_buff *); + + +extern void page_frag_free(void *addr); + +#define DECLARE_BITMAP(name,bits) unsigned long name[BITS_TO_LONGS(bits)] + +struct rtnl_link_stats64; +struct ethtool_link_ksettings; +int netif_carrier_ok(const struct net_device *dev); + +int is_valid_ether_addr(const u8 *); + +void phy_print_status(struct phy_device *phydev); + +enum { + MII_BMCR = 0x0, + MII_BMSR = 0x1, + MII_PHYSID1 = 0x2, + MII_PHYSID2 = 0x3, + MII_ADVERTISE = 0x4, + MII_LPA = 0x5, + MII_CTRL1000 = 0x9, + MII_MMD_CTRL = 0xd, + MII_MMD_DATA = 0xe, + MII_PHYADDR = 0x19, + MII_MMD_CTRL_NOINCR = 0x4000, +}; + +enum { VLAN_HLEN = 4 }; + +void udelay(unsigned long usecs); + +int eth_validate_addr(struct net_device *); + +int netdev_mc_empty(struct net_device *); +unsigned netdev_mc_count(struct net_device * dev); + +#define netdev_for_each_mc_addr(a, b) if (0) + +void usleep_range(unsigned long min, unsigned long max); + +void eth_hw_addr_random(struct net_device *dev); + +static inline void ether_addr_copy(u8 *dst, const u8 *src) +{ + *(u32 *)dst = *(const u32 *)src; + *(u16 *)(dst+ 4) = *(const u16 *)(src + 4); +} + +u32 ether_crc(int, unsigned char *); + +struct netdev_hw_addr +{ + unsigned char addr[MAX_ADDR_LEN]; +}; + +void mdelay(unsigned long usecs); + +int eth_mac_addr(struct net_device *, void *); + +void netif_carrier_on(struct net_device *dev); +void netif_carrier_off(struct net_device *dev); + +const void *of_get_mac_address(struct device_node *np); + +u16 bitrev16(u16 in); +u16 crc16(u16 crc, const u8 *buffer, size_t len); +int hex2bin(u8 *dst, const char *src, size_t count); + +#define this_cpu_ptr(ptr) ptr + +__be16 eth_type_trans(struct sk_buff *, struct net_device *); + +struct u64_stats_sync {}; + +static inline unsigned long u64_stats_update_begin_irqsave(struct u64_stats_sync *syncp) { + return 0; } + +static inline void u64_stats_update_end_irqrestore(struct u64_stats_sync *syncp, unsigned long flags) { } + +struct pcpu_sw_netstats +{ + u64 rx_packets; + u64 rx_bytes; + u64 tx_packets; + u64 tx_bytes; + struct u64_stats_sync syncp; +}; + +int netif_rx(struct sk_buff *); + +enum { NET_RX_SUCCESS = 0 }; +enum { SINGLE_DEPTH_NESTING = 1 }; + +void tasklet_schedule(struct tasklet_struct *t); +void tasklet_kill(struct tasklet_struct *t); + +int netif_device_present(struct net_device * d); +void netif_device_detach(struct net_device *dev); +void netif_stop_queue(struct net_device *); +void netif_start_queue(struct net_device *); +void netif_wake_queue(struct net_device * d); + +void netdev_stats_to_stats64(struct rtnl_link_stats64 *stats64, const struct net_device_stats *netdev_stats); + +enum { TASK_RUNNING = 0, TASK_INTERRUPTIBLE = 1, TASK_UNINTERRUPTIBLE = 2, TASK_NORMAL = 3 }; + +void __set_current_state(int state); +#define set_current_state(state) __set_current_state(state) + +extern const struct cpumask *const cpu_possible_mask; + +#define for_each_cpu(cpu, mask) \ + for ((cpu) = 0; (cpu) < 1; (cpu)++, (void)mask) + +#define for_each_possible_cpu(cpu) for_each_cpu((cpu), cpu_possible_mask) + +#define per_cpu_ptr(ptr, cpu) ({ (void)(cpu);(typeof(*(ptr)) *)(ptr); }) + +u32 netif_msg_init(int, int); +#define netif_msg_tx_err(p) ({ printk("netif_msg_tx_err called not implemented\n"); 0; }) +#define netif_msg_rx_err(p) ({ printk("netif_msg_rx_err called not implemented\n"); 0; }) + +unsigned int u64_stats_fetch_begin_irq(const struct u64_stats_sync *p); +bool u64_stats_fetch_retry_irq(const struct u64_stats_sync *p, unsigned int s); + +void unregister_netdev(struct net_device *); + +#define free_percpu(pdata) kfree(pdata) + +void free_netdev(struct net_device *); + +void netif_trans_update(struct net_device *dev); + +void pm_runtime_enable(struct device *dev); + +struct net_device *alloc_etherdev(int); + +#define SET_NETDEV_DEV(net, pdev) ((net)->dev.parent = (pdev)) + +void *__alloc_percpu(size_t size, size_t align); + +#define alloc_percpu(type) \ + (typeof(type) __percpu *)__alloc_percpu(sizeof(type), __alignof__(type)) + + +#define netdev_alloc_pcpu_stats(type) alloc_percpu(type) + +enum { + NETIF_MSG_DRV = 0x1, + NETIF_MSG_PROBE = 0x2, + NETIF_MSG_LINK = 0x4, +}; + +static inline bool ether_addr_equal(const u8 *addr1, const u8 *addr2) +{ + const u16 *a = (const u16 *)addr1; + const u16 *b = (const u16 *)addr2; + + return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2])) == 0; +} + +enum { NET_ADDR_RANDOM = 1 }; + +#define SET_NETDEV_DEVTYPE(net, devtype) ((net)->dev.type = (devtype)) + +int register_netdev(struct net_device *); + +void netif_device_attach(struct net_device *dev); + +enum { GFP_NOIO = GFP_LX_DMA }; + +void netif_tx_wake_all_queues(struct net_device *dev); + +void eth_random_addr(u8 *addr); + +long __wait_completion(struct completion *work, unsigned long timeout); + +struct mii_ioctl_data; + +typedef int possible_net_t; + +void *kmalloc_node_track_caller(size_t size, gfp_t flags, int node); +bool gfp_pfmemalloc_allowed(gfp_t); + +struct callback_head { + struct callback_head *next; + void (*func)(struct callback_head *head); +}; +#define rcu_head callback_head + +typedef int rwlock_t; + +struct task_struct; + +typedef struct { } read_descriptor_t; + +#define SMP_CACHE_BYTES L1_CACHE_BYTES +#define ____cacheline_aligned __attribute__((aligned(SMP_CACHE_BYTES))) +#define ____cacheline_aligned_in_smp __attribute__((aligned(SMP_CACHE_BYTES))) + +struct percpu_counter { + s64 count; +}; + +static inline int percpu_counter_init(struct percpu_counter *fbc, s64 amount, gfp_t gfp) +{ + fbc->count = amount; + return 0; +} + +static inline s64 percpu_counter_read(struct percpu_counter *fbc) +{ + return fbc->count; +} + +static inline +void percpu_counter_add(struct percpu_counter *fbc, s64 amount) +{ + fbc->count += amount; +} + +static inline +void __percpu_counter_add(struct percpu_counter *fbc, s64 amount, s32 batch) +{ + percpu_counter_add(fbc, amount); +} + +s64 percpu_counter_sum_positive(struct percpu_counter *fbc); + +static inline void percpu_counter_inc(struct percpu_counter *fbc) +{ + percpu_counter_add(fbc, 1); +} + +static inline void percpu_counter_dec(struct percpu_counter *fbc) +{ + percpu_counter_add(fbc, -1); +} + +static inline +s64 percpu_counter_read_positive(struct percpu_counter *fbc) +{ + return fbc->count; +} + +void percpu_counter_destroy(struct percpu_counter *fbc); + +s64 percpu_counter_sum(struct percpu_counter *fbc); + +void bitmap_fill(unsigned long *dst, int nbits); +void bitmap_zero(unsigned long *dst, int nbits); + +typedef unsigned seqlock_t; + +enum { LL_MAX_HEADER = 96 }; + +struct hh_cache +{ + u16 hh_len; + u16 __pad; + seqlock_t hh_lock; + +#define HH_DATA_MOD 16 +#define HH_DATA_OFF(__len) \ + (HH_DATA_MOD - (((__len - 1) & (HH_DATA_MOD - 1)) + 1)) +#define HH_DATA_ALIGN(__len) \ + (((__len)+(HH_DATA_MOD-1))&~(HH_DATA_MOD - 1)) + unsigned long hh_data[HH_DATA_ALIGN(LL_MAX_HEADER) / sizeof(long)]; +}; + +struct seq_net_private { + struct net *net; +}; + +struct seq_file; +struct ctl_table; + +typedef int proc_handler (struct ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos); + +unsigned read_seqbegin(const seqlock_t *sl); +unsigned read_seqretry(const seqlock_t *sl, unsigned start); + +int dev_queue_xmit(struct sk_buff *skb); + +#define raw_smp_processor_id() 0 + +#define rcu_dereference_bh(p) p +#define rcu_dereference_raw(p) p +#define rcu_dereference_check(p, c) p +#define rcu_dereference(p) p + +#define read_pnet(pnet) (&init_net) + +static inline int net_eq(const struct net *net1, const struct net *net2) { + return net1 == net2; } + +extern struct net init_net; + +struct net *dev_net(const struct net_device *dev); + +#define __randomize_layout + +struct cgroup; + +#define mem_cgroup_sockets_enabled 0 + +struct mem_cgroup; + +static inline bool mem_cgroup_under_socket_pressure(struct mem_cgroup *memcg) { + return false; } + +struct inode +{ +//umode_t i_mode; + kuid_t i_uid; +//unsigned long i_ino; +}; + +#define mutex_release(l, n, i) + +int spin_is_locked(spinlock_t *lock); + +void write_lock_bh(rwlock_t *); +void write_unlock_bh(rwlock_t *); + +void security_sock_graft(struct sock *, struct socket *); + +typedef unsigned kgid_t; +kuid_t make_kuid(struct user_namespace *from, uid_t uid); + +struct net +{ + struct user_namespace * user_ns; +}; + +u32 prandom_u32(void); +void rcu_read_lock(void); +void rcu_read_unlock(void); +#define rcu_dereference_protected(p, c) p +bool net_gso_ok(netdev_features_t features, int gso_type); +bool copy_from_iter_full_nocache(void *addr, size_t bytes, struct iov_iter *i); +bool lockdep_is_held(void *l); + +extern int debug_locks; +bool wq_has_sleeper(struct wait_queue_head *wq_head); +bool poll_does_not_wait(const poll_table *p); +void poll_wait(struct file *f, wait_queue_head_t *w, poll_table *p); + +struct task_struct +{ + unsigned int flags; + struct page_frag task_frag; +}; + +extern struct task_struct *current; +int in_softirq(void); + +enum { MAX_SCHEDULE_TIMEOUT = 1000 }; + +#define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f)) + +#define write_pnet(pnet, net) do { (void)(net);} while (0) + +int l3mdev_master_ifindex_by_index(struct net *net, int ifindex); + +struct kmem_cache; +void *kmem_cache_alloc_node(struct kmem_cache *cache, gfp_t, int); +void kmem_cache_free(struct kmem_cache *, void *); +void *kmem_cache_alloc(struct kmem_cache *, gfp_t); +struct page *virt_to_head_page(const void *x); + +struct page_frag_cache +{ + bool pfmemalloc; +}; + +#define prefetchw(x) __builtin_prefetch(x,1) + +size_t ksize(void *); + +#define DEFINE_PER_CPU(type, name) \ + typeof(type) name + +static inline unsigned long local_irq_save(unsigned long flags) { return flags; } +static inline void local_irq_restore(unsigned long f) { } + +void *page_frag_alloc(struct page_frag_cache *nc, unsigned int fragsz, gfp_t gfp_mask); + +enum { + NAPI_STATE_SCHED, + NAPI_STATE_DISABLE, + NAPI_STATE_NPSVC, + NAPI_STATE_HASHED, +}; + +struct napi_struct +{ + struct net_device * dev; + int (*poll)(struct napi_struct *, int); + unsigned long state; + int weight; +}; + +void secpath_reset(struct sk_buff *); +int in_irq(); + +void trace_kfree_skb(struct sk_buff *, void *); +void trace_consume_skb(struct sk_buff *); + +void kmem_cache_free_bulk(struct kmem_cache *, size_t, void **); + +void dev_consume_skb_any(struct sk_buff *skb); + +bool capable(int); + +enum { PAGE_SHIFT = 12 }; + +unsigned long rlimit(unsigned int limit); + +enum { RLIMIT_MEMLOCK = 8 }; + +struct user_struct +{ + atomic_long_t locked_vm; +}; + +struct user_struct *current_user(); + +static inline int atomic_long_cmpxchg(atomic_long_t *v, long old, long n) { + return cmpxchg(&v->counter, old, n); } + +struct user_struct *get_uid(struct user_struct *u); +void free_uid(struct user_struct *); + +#define in_task() (1) + +struct inet_skb_parm +{ + int iif; +}; + +struct page *alloc_pages(gfp_t gfp_mask, unsigned int order); +#define alloc_page(gfp_mask) alloc_pages(gfp_mask, 0) + +#define page_private(page) ((page)->private) +#define set_page_private(page, v) ((page)->private = (v)) + +void *kmap_atomic(struct page *page); +void kunmap_atomic(void *addr); + +#define CONFIG_LOCKDEP 1 + +struct partial_page +{ + unsigned int offset; + unsigned int len; +}; + +struct splice_pipe_desc +{ + struct page **pages; + struct partial_page *partial; + int nr_pages; + unsigned int nr_pages_max; + //unsigned int flags; + const struct pipe_buf_operations *ops; + void (*spd_release)(struct splice_pipe_desc *, unsigned int); +}; + +struct page *virt_to_page(const void *x); + +extern const struct pipe_buf_operations nosteal_pipe_buf_ops; + +struct pipe_inode_info; +ssize_t splice_to_pipe(struct pipe_inode_info *, struct splice_pipe_desc *); + +bool check_copy_size(const void *addr, size_t bytes, bool is_source); + +__wsum csum_partial_ext(const void *buff, int len, __wsum sum); +__wsum csum_block_add_ext(__wsum csum, __wsum csum2, int offset, int len); +__wsum csum_partial_copy(const void *src, void *dst, int len, __wsum sum); +#define csum_partial_copy_nocheck(src, dst, len, sum) \ + csum_partial_copy((src), (dst), (len), (sum)) + +unsigned int textsearch_find(struct ts_config *, struct ts_state *); + +__be16 skb_network_protocol(struct sk_buff *skb, int *depth); + +bool can_checksum_protocol(netdev_features_t features, __be16 protocol); + +unsigned int skb_gro_offset(const struct sk_buff *skb); + +unsigned int skb_gro_len(const struct sk_buff *skb); + +#define NAPI_GRO_CB(skb) ((struct napi_gro_cb *)(skb)->cb) + +enum { NAPI_GRO_FREE = 1, NAPI_GRO_FREE_STOLEN_HEAD = 2, }; + +struct napi_gro_cb +{ + u16 flush; + u16 count; + u8 same_flow; + u8 free; + struct sk_buff *last; +}; + +enum { + SLAB_HWCACHE_ALIGN = 0x00002000ul, + SLAB_CACHE_DMA = 0x00004000ul, + SLAB_PANIC = 0x00040000ul, + SLAB_LX_DMA = 0x80000000ul, +}; + +#define sizeof_field(TYPE, MEMBER) sizeof((((TYPE *)0)->MEMBER)) + +struct kmem_cache *kmem_cache_create_usercopy(const char *name, size_t size, size_t align, slab_flags_t flags, size_t useroffset, size_t usersize, void (*ctor)(void *)); +struct kmem_cache *kmem_cache_create(const char *, size_t, size_t, unsigned long, void (*)(void *)); + +#define sg_is_last(sg) ((sg)->page_link & 0x02) +void sg_mark_end(struct scatterlist *sg); +//void sg_set_buf(struct scatterlist *, const void *, unsigned int); +//void sg_set_page(struct scatterlist *, struct page *, unsigned int, unsigned int); + +enum { + IPPROTO_IP = 0, + IPPROTO_TCP = 6, + IPPROTO_UDP = 17, + IPPROTO_AH = 51, +}; + +enum { + IPPROTO_HOPOPTS = 0, + IPPROTO_ROUTING = 43, + IPPROTO_FRAGMENT = 44, + IPPROTO_DSTOPTS = 60, +}; + +void read_lock_bh(rwlock_t *); +void read_unlock_bh(rwlock_t *); + +bool file_ns_capable(const struct file *file, struct user_namespace *ns, int cap); + +extern struct user_namespace init_user_ns; + +struct tcphdr +{ + __be16 source; + __be16 dest; + __be32 seq; + __be32 ack_seq; + __u16 res1:4, + doff:4, + fin:1, + syn:1, + rst:1, + psh:1, + ack:1, + urg:1, + ece:1, + cwr:1; + __be16 window; + __sum16 check; +}; + +struct tcphdr *tcp_hdr(const struct sk_buff *skb); + +unsigned int tcp_hdrlen(const struct sk_buff *skb); + +struct udphdr +{ + __sum16 check; +}; + +struct udphdr *udp_hdr(const struct sk_buff *skb); + +struct iphdr { + __u8 ihl:4; + __u8 version:4; + __u8 tos; + __be16 tot_len; + __be16 frag_off; + __u8 ttl; + __u8 protocol; + __sum16 check; + __be32 saddr; + __be32 daddr; +}; + +struct iphdr *ip_hdr(const struct sk_buff *skb); + +struct in6_addr {}; + +struct ipv6hdr +{ + __be16 payload_len; + __u8 nexthdr; + struct in6_addr saddr; + struct in6_addr daddr; +}; + +struct ipv6hdr *ipv6_hdr(const struct sk_buff *skb); + +struct ipv6_opt_hdr +{ + __u8 nexthdr; + __u8 hdrlen; +} __attribute__((packed)); + +struct ip_auth_hdr +{ + __u8 nexthdr; + __u8 hdrlen; +}; + +struct frag_hdr +{ + __u8 nexthdr; + __be16 frag_off; +}; + +#define ipv6_optlen(p) (((p)->hdrlen+1) << 3) +#define ipv6_authlen(p) (((p)->hdrlen+2) << 2) + +enum { IP_OFFSET = 0x1FFF, IP_MF = 0x2000 }; + +enum { IP6_MF = 0x0001, IP6_OFFSET = 0xfff8 }; + +unsigned int ip_hdrlen(const struct sk_buff *skb); + +__sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr, unsigned short len, unsigned short proto, __wsum sum); + +__sum16 csum_ipv6_magic(const struct in6_addr *saddr, const struct in6_addr *daddr, __u32 len, unsigned short proto, __wsum csum); + +void secpath_reset(struct sk_buff *); + +struct tcphdr *inner_tcp_hdr(const struct sk_buff *skb); +unsigned int inner_tcp_hdrlen(const struct sk_buff *skb); + +#define htons(x) __cpu_to_be16(x) +#define ntohs(x) __be16_to_cpu(x) + +struct sctphdr +{ + unsigned unused; +}; + +enum { + VLAN_CFI_MASK = 0x1000, + VLAN_TAG_PRESENT = VLAN_CFI_MASK +}; + +struct vlan_hdr +{ + __be16 h_vlan_TCI; +}; + +#define skb_vlan_tag_present(__skb) ((__skb)->vlan_tci & VLAN_TAG_PRESENT) + +void __vlan_hwaccel_put_tag(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci); + +void vlan_set_encap_proto(struct sk_buff *skb, struct vlan_hdr *vhdr); + +enum { VLAN_ETH_HLEN = 18 }; + +static inline bool eth_type_vlan(__be16 ethertype) { return false; } + +static inline int __vlan_insert_tag(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci) { + return 1; } + +#define skb_vlan_tag_get(__skb) ((__skb)->vlan_tci & ~VLAN_TAG_PRESENT) + +extern struct workqueue_struct *tasklet_wq; + +int __init netdev_boot_setup(char *str); + +static inline void eth_zero_addr(u8 *addr) { + memset(addr, 0x00, ETH_ALEN); } + +#define FLOW_DISSECTOR_F_PARSE_1ST_FRAG BIT(0) + +static inline void eth_broadcast_addr(u8 *addr) { + memset(addr, 0xff, ETH_ALEN); } + +static inline bool is_multicast_ether_addr(const u8 *addr) +{ + return 0x01 & addr[0]; +} + +static inline bool is_multicast_ether_addr_64bits(const u8 addr[6+2]) +{ + return is_multicast_ether_addr(addr); +} + +static inline bool ether_addr_equal_64bits(const u8 addr1[6+2], const u8 addr2[6+2]) +{ + const u16 *a = (const u16 *)addr1; + const u16 *b = (const u16 *)addr2; + + return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2])) == 0; +} + +bool netdev_uses_dsa(struct net_device *dev); + +#include + +static inline bool eth_proto_is_802_3(__be16 proto) +{ + proto &= htons(0xFF00); + return (u16)proto >= (u16)htons(ETH_P_802_3_MIN); +} + +enum { + IFF_LIVE_ADDR_CHANGE = 0x100000, + IFF_TX_SKB_SHARING = 0x10000, +}; + +enum { ARPHRD_ETHER = 1, }; + +struct neighbour; + +struct header_ops +{ + int (*create) (struct sk_buff *skb, struct net_device *dev, + unsigned short type, const void *daddr, + const void *saddr, unsigned int len); + int (*parse)(const struct sk_buff *skb, unsigned char *haddr); + int (*rebuild)(struct sk_buff *skb); + int (*cache)(const struct neighbour *neigh, struct hh_cache *hh, __be16 type); + void (*cache_update)(struct hh_cache *hh, + const struct net_device *dev, + const unsigned char *haddr); +}; + +#define DEFAULT_TX_QUEUE_LEN 1000 + +struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name, unsigned char name_assign_type, void (*setup)(struct net_device *), unsigned int txqs, unsigned int rxqs); + +enum { NET_NAME_UNKNOWN = 0 }; + +typedef void (*dr_release_t)(struct device *dev, void *res); +void *devres_alloc(dr_release_t release, size_t size, gfp_t gfp); +void devres_free(void *res); +void devres_add(struct device *dev, void *res); + +int scnprintf(char *buf, size_t size, const char *fmt, ...); + +void *skb_gro_header_fast(struct sk_buff *skb, unsigned int offset); +void *skb_gro_header_hard(struct sk_buff *skb, unsigned int hlen); +void *skb_gro_header_slow(struct sk_buff *skb, unsigned int hlen, unsigned int offset); + +static inline unsigned long compare_ether_header(const void *a, const void *b) +{ + u32 *a32 = (u32 *)((u8 *)a + 2); + u32 *b32 = (u32 *)((u8 *)b + 2); + + return (*(u16 *)a ^ *(u16 *)b) | (a32[0] ^ b32[0]) | + (a32[1] ^ b32[1]) | (a32[2] ^ b32[2]); + +} + +typedef struct sk_buff **(*gro_receive_t)(struct sk_buff **, struct sk_buff *); + +struct offload_callbacks +{ + struct sk_buff **(*gro_receive)(struct sk_buff **head, struct sk_buff *skb); + int (*gro_complete)(struct sk_buff *skb, int nhoff); +}; + +struct packet_offload +{ + __be16 type; + u16 priority; + struct offload_callbacks callbacks; +}; + +struct packet_offload *gro_find_receive_by_type(__be16 type); + +void skb_gro_pull(struct sk_buff *skb, unsigned int len); +void skb_gro_postpull_rcsum(struct sk_buff *skb, const void *start, unsigned int len); + +struct sk_buff **call_gro_receive(gro_receive_t cb, struct sk_buff **head, struct sk_buff *skb); + +void skb_gro_flush_final(struct sk_buff *skb, struct sk_buff **pp, int flush); + +struct packet_offload *gro_find_complete_by_type(__be16 type); + +void dev_add_offload(struct packet_offload *po); + +#define fs_initcall(x) + +#define __weak __attribute__((weak)) + +unsigned char *arch_get_platform_mac_address(void); + +#define to_pci_dev(n) NULL +struct pci_dev; +struct device_node * pci_device_to_OF_node(const struct pci_dev *pdev); + +int dev_is_pci(struct device *dev); + +void skb_init(); +int module_usbnet_init(); +int module_smsc95xx_driver_init(); +int module_asix_driver_init(); +int module_ax88179_178a_driver_init(); +int module_cdc_driver_init(); +int module_rndis_driver_init(); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#endif /* _SRC__DRIVERS__USB_HID__LX_EMUL_H_ */ diff --git a/repos/dde_linux/src/drivers/usb_net/lxc.c b/repos/dde_linux/src/drivers/usb_net/lxc.c new file mode 100644 index 000000000..d264b8224 --- /dev/null +++ b/repos/dde_linux/src/drivers/usb_net/lxc.c @@ -0,0 +1,65 @@ +/* + * \brief Linux emulation code + * \author Josef Soentgen + * \date 2014-03-07 + */ + +/* + * Copyright (C) 2014-2017 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +/* linux includes */ +#include +#include + +/* local includes */ +#include + + +struct Skb skb_helper(struct sk_buff *skb) +{ + struct Skb helper; + + skb_push(skb, ETH_HLEN); + + helper.packet = skb->data; + helper.packet_size = ETH_HLEN; + helper.frag = 0; + helper.frag_size = 0; + + /** + * If received packets are too large (as of now 128 bytes) the actually + * payload is put into a fragment. Otherwise the payload is stored directly + * in the sk_buff. + */ + if (skb_shinfo(skb)->nr_frags) { + if (skb_shinfo(skb)->nr_frags > 1) + printk("more than 1 fragment in skb: %p nr_frags: %d", skb, + skb_shinfo(skb)->nr_frags); + + skb_frag_t *f = &skb_shinfo(skb)->frags[0]; + helper.frag = skb_frag_address(f); + helper.frag_size = skb_frag_size(f); + } + else + helper.packet_size += skb->len; + + return helper; +} + + +struct sk_buff *lxc_alloc_skb(size_t len, size_t headroom) +{ + struct sk_buff *skb = alloc_skb(len + headroom, GFP_KERNEL | GFP_LX_DMA); + skb_reserve(skb, headroom); + return skb; +} + + +unsigned char *lxc_skb_put(struct sk_buff *skb, size_t len) +{ + return skb_put(skb, len); +} diff --git a/repos/dde_linux/src/drivers/usb_net/lxc.h b/repos/dde_linux/src/drivers/usb_net/lxc.h new file mode 100644 index 000000000..0bdad76ab --- /dev/null +++ b/repos/dde_linux/src/drivers/usb_net/lxc.h @@ -0,0 +1,40 @@ +/* + * \brief Lx C env + * \author Josef Soentgen + * \date 2016-03-04 + */ + +/* + * Copyright (C) 2016-2017 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#ifndef _LXC_H_ +#define _LXC_H_ + +/* + * The sk_buff struct contains empty array members whose + * size differs between C and C++. Since we want to access + * certain members of the sk_buff from C++ we have to use + * a uniform format useable from both languages.W + * + * Note: we pull struct skb_buff as well as size_t from + * headers included before this one. + */ +struct Skb +{ + void *packet; + size_t packet_size; + void *frag; + size_t frag_size; +}; + +struct Skb skb_helper(struct sk_buff *skb); +bool is_eapol(struct sk_buff *skb); + +struct sk_buff *lxc_alloc_skb(size_t len, size_t headroom); +unsigned char *lxc_skb_put(struct sk_buff *skb, size_t len); + +#endif /* _LXC_H_ */ diff --git a/repos/dde_linux/src/drivers/usb_net/main.cc b/repos/dde_linux/src/drivers/usb_net/main.cc new file mode 100644 index 000000000..5e4d28808 --- /dev/null +++ b/repos/dde_linux/src/drivers/usb_net/main.cc @@ -0,0 +1,216 @@ +/* + * \brief USB net driver + * \author Stefan Kalkowski + * \date 2018-06-07 + */ + +/* + * Copyright (C) 2018 Genode Labs GmbH + * + * This file is distributed under the terms of the GNU General Public License + * version 2. + */ + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +struct workqueue_struct *tasklet_wq; + + +void Driver::Device::scan_altsettings(usb_interface * iface, + unsigned iface_idx, unsigned alt_idx) +{ + Usb::Interface_descriptor iface_desc; + usb.interface_descriptor(iface_idx, alt_idx, &iface_desc); + Genode::memcpy(&iface->altsetting[alt_idx].desc, &iface_desc, + sizeof(usb_interface_descriptor)); + if (iface_desc.active) + iface->cur_altsetting = &iface->altsetting[alt_idx]; + + + iface->altsetting[alt_idx].endpoint = (usb_host_endpoint*) + kzalloc(sizeof(usb_host_endpoint)*iface->altsetting[alt_idx].desc.bNumEndpoints, GFP_KERNEL); + + for (unsigned i = 0; i < iface->altsetting[alt_idx].desc.bNumEndpoints; i++) { + Usb::Endpoint_descriptor ep_desc; + usb.endpoint_descriptor(iface_idx, alt_idx, i, &ep_desc); + Genode::memcpy(&iface->altsetting[alt_idx].endpoint[i].desc, + &ep_desc, sizeof(usb_endpoint_descriptor)); + int epnum = usb_endpoint_num(&iface->altsetting[alt_idx].endpoint[i].desc); + if (usb_endpoint_dir_out(&iface->altsetting[alt_idx].endpoint[i].desc)) + udev->ep_out[epnum] = &iface->altsetting[alt_idx].endpoint[i]; + else + udev->ep_in[epnum] = &iface->altsetting[alt_idx].endpoint[i]; + } +} + + +void Driver::Device::scan_interfaces(unsigned iface_idx) +{ + struct usb_interface * iface = + (usb_interface*) kzalloc(sizeof(usb_interface), GFP_KERNEL); + iface->num_altsetting = usb.alt_settings(iface_idx); + iface->altsetting = (usb_host_interface*) + kzalloc(sizeof(usb_host_interface)*iface->num_altsetting, GFP_KERNEL); + iface->dev.parent = &udev->dev; + iface->dev.bus = (bus_type*) 0xdeadbeef; + + for (unsigned i = 0; i < iface->num_altsetting; i++) + scan_altsettings(iface, iface_idx, i); + + struct usb_device_id id; + probe_interface(iface, &id); + udev->config->interface[iface_idx] = iface; + + driver.env.parent().announce(driver.ep.manage(driver.root)); +}; + + +void Driver::Device::register_device() +{ + if (udev) { + Genode::error("device already registered!"); + return; + } + + Usb::Device_descriptor dev_desc; + Usb::Config_descriptor config_desc; + usb.config_descriptor(&dev_desc, &config_desc); + + udev = (usb_device*) kzalloc(sizeof(usb_device), GFP_KERNEL); + udev->bus = (usb_bus*) kzalloc(sizeof(usb_bus), GFP_KERNEL); + udev->config = (usb_host_config*) kzalloc(sizeof(usb_host_config), GFP_KERNEL); + udev->bus->bus_name = "usbbus"; + udev->bus->controller = (device*) (&usb); + + udev->descriptor.idVendor = dev_desc.vendor_id; + udev->descriptor.idProduct = dev_desc.product_id; + udev->descriptor.bcdDevice = dev_desc.device_release; + + for (unsigned i = 0; i < config_desc.num_interfaces; i++) + scan_interfaces(i); +} + + +void Driver::Device::unregister_device() +{ + for (unsigned i = 0; i < USB_MAXINTERFACES; i++) { + if (!udev->config->interface[i]) break; + else remove_interface(udev->config->interface[i]); + } + kfree(udev->bus); + kfree(udev->config); + kfree(udev); + udev = nullptr; +} + + +void Driver::Device::state_task_entry(void * arg) +{ + Device & dev = *reinterpret_cast(arg); + + for (;;) { + if (dev.usb.plugged() && !dev.udev) + dev.register_device(); + + if (!dev.usb.plugged() && dev.udev) + dev.unregister_device(); + + Lx::scheduler().current()->block_and_schedule(); + } +} + + +void Driver::Device::urb_task_entry(void * arg) +{ + Device & dev = *reinterpret_cast(arg); + + for (;;) { + while (dev.udev && dev.usb.source()->ack_avail()) { + Usb::Packet_descriptor p = dev.usb.source()->get_acked_packet(); + if (p.completion) p.completion->complete(p); + dev.usb.source()->release_packet(p); + } + + Lx::scheduler().current()->block_and_schedule(); + } +} + + +Driver::Device::Device(Driver & driver, Label label) +: label(label), + driver(driver), + env(driver.env), + alloc(driver.alloc), + state_task(env.ep(), state_task_entry, reinterpret_cast(this), + "usb_state", Lx::Task::PRIORITY_0, Lx::scheduler()), + urb_task(env.ep(), urb_task_entry, reinterpret_cast(this), + "usb_urb", Lx::Task::PRIORITY_0, Lx::scheduler()) +{ + usb.tx_channel()->sigh_ack_avail(urb_task.handler); + driver.devices.insert(&le); +} + + +Driver::Device::~Device() +{ + driver.devices.remove(&le); + if (udev) unregister_device(); +} + + +void Driver::main_task_entry(void * arg) +{ + Driver * driver = reinterpret_cast(arg); + + tasklet_wq = alloc_workqueue("tasklet_wq", 0, 0); + + skb_init(); + module_usbnet_init(); + module_smsc95xx_driver_init(); + module_asix_driver_init(); + module_ax88179_178a_driver_init(); + module_cdc_driver_init(); + module_rndis_driver_init(); + + static Device dev(*driver, Label("")); + + for (;;) Lx::scheduler().current()->block_and_schedule(); +} + + +Driver::Driver(Genode::Env &env) : env(env) +{ + Genode::log("--- USB net driver ---"); + + Lx_kit::construct_env(env); + Lx::scheduler(&env); + Lx::malloc_init(env, heap); + Lx::timer(&env, &ep, &heap, &jiffies); + Lx::Work::work_queue(&heap); + + main_task.construct(env.ep(), main_task_entry, reinterpret_cast(this), + "main", Lx::Task::PRIORITY_0, Lx::scheduler()); + + /* give all task a first kick before returning */ + Lx::scheduler().schedule(); +} + + +void Component::construct(Genode::Env &env) +{ + env.exec_static_constructors(); + static Driver driver(env); +} diff --git a/repos/dde_linux/src/drivers/usb_net/target.mk b/repos/dde_linux/src/drivers/usb_net/target.mk new file mode 100644 index 000000000..bbe981aae --- /dev/null +++ b/repos/dde_linux/src/drivers/usb_net/target.mk @@ -0,0 +1,32 @@ +TARGET := usb_net_drv +SRC_C := dummies.c lxc.c +SRC_CC := main.cc lx_emul.cc component.cc +SRC_CC += printf.cc timer.cc scheduler.cc malloc.cc env.cc work.cc + +LIBS := base usb_net_include lx_kit_setjmp + +USB_CONTRIB_DIR := $(call select_from_ports,dde_linux)/src/drivers/usb_net + +INC_DIR += $(PRG_DIR) +INC_DIR += $(REP_DIR)/src/include + +SRC_C += drivers/net/usb/asix_common.c +SRC_C += drivers/net/usb/asix_devices.c +SRC_C += drivers/net/usb/ax88172a.c +SRC_C += drivers/net/usb/ax88179_178a.c +SRC_C += drivers/net/usb/cdc_ether.c +SRC_C += drivers/net/usb/rndis_host.c +SRC_C += drivers/net/usb/smsc95xx.c +SRC_C += drivers/net/usb/usbnet.c +SRC_C += net/core/skbuff.c +SRC_C += net/ethernet/eth.c + +CC_C_OPT += -Wno-comment -Wno-int-conversion -Wno-incompatible-pointer-types \ + -Wno-unused-variable -Wno-pointer-sign -Wno-uninitialized \ + -Wno-maybe-uninitialized -Wno-format -Wno-discarded-qualifiers \ + -Wno-unused-function -Wno-unused-but-set-variable + +CC_CXX_WARN_STRICT = + +vpath %.c $(USB_CONTRIB_DIR) +vpath %.cc $(REP_DIR)/src/lx_kit diff --git a/repos/dde_linux/usb_net.list b/repos/dde_linux/usb_net.list new file mode 100644 index 000000000..5f4123b80 --- /dev/null +++ b/repos/dde_linux/usb_net.list @@ -0,0 +1,71 @@ +linux-x.x.x/drivers/net/usb/asix_common.c +linux-x.x.x/drivers/net/usb/asix_devices.c +linux-x.x.x/drivers/net/usb/asix.h +linux-x.x.x/drivers/net/usb/ax88172a.c +linux-x.x.x/drivers/net/usb/ax88179_178a.c +linux-x.x.x/drivers/net/usb/cdc_ether.c +linux-x.x.x/drivers/net/usb/rndis_host.c +linux-x.x.x/drivers/net/usb/smsc95xx.h +linux-x.x.x/drivers/net/usb/smsc95xx.c +linux-x.x.x/drivers/net/usb/usbnet.c +linux-x.x.x/net/core/skbuff.c +linux-x.x.x/net/ethernet/eth.c +linux-x.x.x/include/asm-generic/atomic64.h +linux-x.x.x/include/asm-generic/bitops/__ffs.h +linux-x.x.x/include/asm-generic/bitops/__fls.h +linux-x.x.x/include/asm-generic/bitops/ffs.h +linux-x.x.x/include/asm-generic/bitops/fls.h +linux-x.x.x/include/asm-generic/bitops/fls64.h +linux-x.x.x/include/asm-generic/bitops/non-atomic.h +linux-x.x.x/include/linux/cgroup-defs.h +linux-x.x.x/include/linux/errqueue.h +linux-x.x.x/include/linux/ethtool.h +linux-x.x.x/include/linux/if_ether.h +linux-x.x.x/include/linux/kfifo.h +linux-x.x.x/include/linux/list.h +linux-x.x.x/include/linux/list_nulls.h +linux-x.x.x/include/linux/log2.h +linux-x.x.x/include/linux/mii.h +linux-x.x.x/include/linux/mdio.h +linux-x.x.x/include/linux/mod_devicetable.h +linux-x.x.x/include/linux/netdev_features.h +linux-x.x.x/include/linux/net.h +linux-x.x.x/include/linux/phy.h +linux-x.x.x/include/linux/rbtree.h +linux-x.x.x/include/linux/rculist.h +linux-x.x.x/include/linux/rculist_nulls.h +linux-x.x.x/include/linux/refcount.h +linux-x.x.x/include/linux/rndis.h +linux-x.x.x/include/linux/skbuff.h +linux-x.x.x/include/linux/socket.h +linux-x.x.x/include/linux/swab.h +linux-x.x.x/include/linux/usb.h +linux-x.x.x/include/linux/usb/ch9.h +linux-x.x.x/include/linux/usb/cdc.h +linux-x.x.x/include/linux/usb/rndis_host.h +linux-x.x.x/include/linux/usb/usbnet.h +linux-x.x.x/include/net/dst.h +linux-x.x.x/include/net/dst_ops.h +linux-x.x.x/include/net/neighbour.h +linux-x.x.x/include/net/sock.h +linux-x.x.x/include/net/tcp_states.h +linux-x.x.x/include/net/tso.h +linux-x.x.x/include/uapi/linux/byteorder/little_endian.h +linux-x.x.x/include/uapi/linux/capability.h +linux-x.x.x/include/uapi/linux/errqueue.h +linux-x.x.x/include/uapi/linux/ethtool.h +linux-x.x.x/include/uapi/linux/if.h +linux-x.x.x/include/uapi/linux/if_ether.h +linux-x.x.x/include/uapi/linux/if_link.h +linux-x.x.x/include/uapi/linux/if_packet.h +linux-x.x.x/include/uapi/linux/libc-compat.h +linux-x.x.x/include/uapi/linux/mdio.h +linux-x.x.x/include/uapi/linux/mii.h +linux-x.x.x/include/uapi/linux/neighbour.h +linux-x.x.x/include/uapi/linux/net.h +linux-x.x.x/include/uapi/linux/rtnetlink.h +linux-x.x.x/include/uapi/linux/socket.h +linux-x.x.x/include/uapi/linux/swab.h +linux-x.x.x/include/uapi/linux/net_tstamp.h +linux-x.x.x/include/uapi/linux/usb/cdc.h +linux-x.x.x/include/uapi/linux/usb/ch9.h