mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-07 11:27:29 +00:00
dde_linux: USB client driver for NIC version 4.16
This commit is contained in:
parent
b32a3cd4d9
commit
2882bd48e6
33
repos/dde_linux/lib/import/import-usb_net_include.mk
Normal file
33
repos/dde_linux/lib/import/import-usb_net_include.mk
Normal file
@ -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
|
37
repos/dde_linux/lib/mk/usb_net_include.mk
Normal file
37
repos/dde_linux/lib/mk/usb_net_include.mk
Normal file
@ -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 =
|
13
repos/dde_linux/patches/usb_net_skbuff_cast.patch
Normal file
13
repos/dde_linux/patches/usb_net_skbuff_cast.patch
Normal file
@ -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);
|
@ -1 +1 @@
|
||||
66e54dcbcd22c597db5794f080d92df114b88985
|
||||
987b3081e335b0063655441c929a86a4627af72f
|
||||
|
@ -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)
|
||||
|
@ -127,7 +127,7 @@ append config {
|
||||
<start name="usb_drv" caps="120"> }
|
||||
append config "<binary name=\"[usb_host_drv_binary]\"/>"
|
||||
append config {
|
||||
<resource name="RAM" quantum="10M"/>
|
||||
<resource name="RAM" quantum="11M"/>
|
||||
<provides> <service name="Usb"/> </provides>
|
||||
<config bios_handoff="no">
|
||||
<report devices="yes"/>
|
||||
@ -140,7 +140,7 @@ append config {
|
||||
</start>
|
||||
|
||||
<start name="usb_hid_drv" caps="120">
|
||||
<resource name="RAM" quantum="10M"/>
|
||||
<resource name="RAM" quantum="11M"/>
|
||||
<provides><service name="Input"/></provides>
|
||||
<config use_report="yes" capslock_led="rom" numlock_led="rom" scrlock_led="rom"/>
|
||||
<route>
|
||||
@ -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"\] }
|
||||
|
@ -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 {
|
||||
<config verbose="yes">
|
||||
append config {
|
||||
<config>
|
||||
<parent-provides>
|
||||
<service name="ROM"/>
|
||||
<service name="IRQ"/>
|
||||
@ -49,29 +52,7 @@ set config {
|
||||
<default-route>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</default-route>
|
||||
<default caps="100"/>
|
||||
<start name="timer">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides> <service name="Timer"/> </provides>
|
||||
</start>
|
||||
<start name="usb_drv">
|
||||
<resource name="RAM" quantum="24M"/>
|
||||
<provides>
|
||||
<service name="Nic"/>
|
||||
</provides>
|
||||
<config uhci="no" ohci="no" ehci="yes" xhci="yes">
|
||||
<nic mac="02:00:00:00:01:01" />
|
||||
</config>
|
||||
</start>
|
||||
<start name="test-lwip_httpsrv">
|
||||
<resource name="RAM" quantum="4M"/>
|
||||
<config>
|
||||
<vfs> <dir name="dev"> <log/> </dir> </vfs>
|
||||
<libc stdout="/dev/log" stderr="/dev/log"/>
|
||||
</config>
|
||||
</start>}
|
||||
|
||||
append_platform_drv_config
|
||||
<default caps="200"/>}
|
||||
|
||||
append_if [have_spec gpio] config "
|
||||
<start name=\"[gpio_drv]\">
|
||||
@ -80,7 +61,50 @@ append_if [have_spec gpio] config "
|
||||
<config/>
|
||||
</start>"
|
||||
|
||||
append_platform_drv_config
|
||||
|
||||
append config {
|
||||
<start name="timer">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides><service name="Timer"/></provides>
|
||||
</start>
|
||||
|
||||
<start name="usb_drv" caps="120"> }
|
||||
append config "<binary name=\"[usb_host_drv_binary]\"/>"
|
||||
append config {
|
||||
<resource name="RAM" quantum="10M"/>
|
||||
<provides> <service name="Usb"/> </provides>
|
||||
<config bios_handoff="no">}
|
||||
append_if [have_spec arndale] config {
|
||||
<policy label_prefix="usb_net_drv" vendor_id="0x0b95" product_id="0x772a"/> }
|
||||
append_if [expr [have_spec panda] || [have_spec rpi] ] config {
|
||||
<policy label_prefix="usb_net_drv" vendor_id="0x0424" product_id="0xec00"/> }
|
||||
append_if [have_spec x86] config {
|
||||
<policy label_prefix="usb_net_drv" vendor_id="0x0b95" product_id="0x1790"/> }
|
||||
append config {
|
||||
</config>
|
||||
<route>
|
||||
<service name="Report"> <child name="report_rom"/> </service>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</route>
|
||||
</start>
|
||||
|
||||
<start name="usb_net_drv">
|
||||
<resource name="RAM" quantum="10M"/>
|
||||
<provides> <service name="Nic"/> </provides>
|
||||
<config mac="02:00:00:00:01:01" />
|
||||
</start>
|
||||
|
||||
<start name="test-lwip_httpsrv" caps="120">
|
||||
<resource name="RAM" quantum="4M"/>
|
||||
<config>
|
||||
<vfs>
|
||||
<dir name="dev"> <log/> </dir>
|
||||
<dir name="socket"> <lwip dhcp="yes"/> </dir>
|
||||
</vfs>
|
||||
<libc stdout="/dev/log" stderr="/dev/log" socket="/socket"/>
|
||||
</config>
|
||||
</start>
|
||||
</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"
|
||||
|
20
repos/dde_linux/src/drivers/usb_net/README
Normal file
20
repos/dde_linux/src/drivers/usb_net/README
Normal file
@ -0,0 +1,20 @@
|
||||
USB NIC driver
|
||||
##############
|
||||
|
||||
Driver for network interface cards connected via USB.
|
||||
|
||||
Configuration snippet:
|
||||
|
||||
!<start name="usb_net_drv">
|
||||
! <resource name="RAM" quantum="10M"/>
|
||||
! <provides> <service name="Nic"/> </provides>
|
||||
! <config mac="2e:60:90:0c:4e:01" />
|
||||
!</start>
|
||||
|
||||
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.
|
||||
|
182
repos/dde_linux/src/drivers/usb_net/component.cc
Normal file
182
repos/dde_linux/src/drivers/usb_net/component.cc
Normal file
@ -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 <component.h>
|
||||
#include <lx_emul.h>
|
||||
|
||||
extern "C" {
|
||||
#include <lxc.h>
|
||||
};
|
||||
|
||||
void Session_component::_run_rx_task(void * args)
|
||||
{
|
||||
Rx_data *data = static_cast<Rx_data*>(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<Tx_data*>(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();
|
||||
}
|
126
repos/dde_linux/src/drivers/usb_net/component.h
Normal file
126
repos/dde_linux/src/drivers/usb_net/component.h
Normal file
@ -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 <nic/component.h>
|
||||
#include <root/component.h>
|
||||
|
||||
#include <lx_kit/scheduler.h>
|
||||
|
||||
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<Session_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<Session_component>(&env.ep().rpc_ep(), &md_alloc),
|
||||
_env(env), _md_alloc(md_alloc)
|
||||
{ }
|
||||
};
|
||||
|
||||
#endif /* _SRC__DRIVERS__NIC__FEC__COMPONENT_H_ */
|
105
repos/dde_linux/src/drivers/usb_net/driver.h
Normal file
105
repos/dde_linux/src/drivers/usb_net/driver.h
Normal file
@ -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 <base/allocator_avl.h>
|
||||
#include <base/attached_rom_dataspace.h>
|
||||
#include <base/heap.h>
|
||||
#include <usb_session/connection.h>
|
||||
#include <lx_kit/scheduler.h>
|
||||
|
||||
#include <component.h>
|
||||
|
||||
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<Task> handler;
|
||||
|
||||
void handle_signal()
|
||||
{
|
||||
task.unblock();
|
||||
Lx::scheduler().schedule();
|
||||
}
|
||||
|
||||
template <typename... ARGS>
|
||||
Task(Genode::Entrypoint & ep, ARGS &&... args)
|
||||
: task(args...), handler(ep, *this, &Task::handle_signal) {}
|
||||
};
|
||||
|
||||
struct Device
|
||||
{
|
||||
using Le = Genode::List_element<Device>;
|
||||
|
||||
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<Device::Le>
|
||||
{
|
||||
template <typename FN>
|
||||
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<Task> main_task;
|
||||
Genode::Constructible<Genode::Attached_rom_dataspace> report_rom;
|
||||
|
||||
Driver(Genode::Env &env);
|
||||
|
||||
static void main_task_entry(void *);
|
||||
};
|
||||
|
||||
#endif /* _SRC__DRIVERS__USB_HID__DRIVER_H_ */
|
518
repos/dde_linux/src/drivers/usb_net/dummies.c
Normal file
518
repos/dde_linux/src/drivers/usb_net/dummies.c
Normal file
@ -0,0 +1,518 @@
|
||||
#include <lx_emul.h>
|
||||
|
||||
#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;
|
539
repos/dde_linux/src/drivers/usb_net/lx_emul.cc
Normal file
539
repos/dde_linux/src/drivers/usb_net/lx_emul.cc
Normal file
@ -0,0 +1,539 @@
|
||||
#include <base/env.h>
|
||||
#include <usb_session/client.h>
|
||||
#include <base/snprintf.h>
|
||||
#include <nic_session/nic_session.h>
|
||||
#include <util/xml_node.h>
|
||||
|
||||
#include <driver.h>
|
||||
#include <lx_emul.h>
|
||||
|
||||
#include <lx_emul/extern_c_begin.h>
|
||||
#include <linux/usb.h>
|
||||
#include <lx_emul/extern_c_end.h>
|
||||
|
||||
#define TRACE do { ; } while (0)
|
||||
|
||||
#include <lx_emul/impl/kernel.h>
|
||||
#include <lx_emul/impl/delay.h>
|
||||
#include <lx_emul/impl/slab.h>
|
||||
#include <lx_emul/impl/work.h>
|
||||
#include <lx_emul/impl/spinlock.h>
|
||||
#include <lx_emul/impl/mutex.h>
|
||||
#include <lx_emul/impl/sched.h>
|
||||
#include <lx_emul/impl/timer.h>
|
||||
#include <lx_emul/impl/completion.h>
|
||||
#include <lx_emul/impl/wait.h>
|
||||
#include <lx_emul/impl/usb.h>
|
||||
|
||||
#include <lx_kit/backend_alloc.h>
|
||||
|
||||
#include <lx_emul/extern_c_begin.h>
|
||||
|
||||
#include <linux/mii.h>
|
||||
|
||||
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 <lx_emul/extern_c_end.h>
|
||||
|
||||
|
||||
class Addr_to_page_mapping : public Genode::List<Addr_to_page_mapping>::Element
|
||||
{
|
||||
private:
|
||||
|
||||
struct page *_page { nullptr };
|
||||
|
||||
static Genode::List<Addr_to_page_mapping> & _list()
|
||||
{
|
||||
static Genode::List<Addr_to_page_mapping> _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<Lx_driver>;
|
||||
using List = Genode::List<Element>;
|
||||
|
||||
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<usb_device_id*>(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<Lx_driver>;
|
||||
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 <nic> - 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<Session_component*>(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<Session_component*>(dev->session_component)->link_state(true);
|
||||
}
|
||||
|
||||
|
||||
int netif_rx(struct sk_buff * skb)
|
||||
{
|
||||
if (skb->dev->session_component)
|
||||
reinterpret_cast<Session_component*>(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);
|
||||
}
|
1296
repos/dde_linux/src/drivers/usb_net/lx_emul.h
Normal file
1296
repos/dde_linux/src/drivers/usb_net/lx_emul.h
Normal file
File diff suppressed because it is too large
Load Diff
65
repos/dde_linux/src/drivers/usb_net/lxc.c
Normal file
65
repos/dde_linux/src/drivers/usb_net/lxc.c
Normal file
@ -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 <lx_emul.h>
|
||||
#include <linux/skbuff.h>
|
||||
|
||||
/* local includes */
|
||||
#include <lxc.h>
|
||||
|
||||
|
||||
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);
|
||||
}
|
40
repos/dde_linux/src/drivers/usb_net/lxc.h
Normal file
40
repos/dde_linux/src/drivers/usb_net/lxc.h
Normal file
@ -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_ */
|
216
repos/dde_linux/src/drivers/usb_net/main.cc
Normal file
216
repos/dde_linux/src/drivers/usb_net/main.cc
Normal file
@ -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 <base/component.h>
|
||||
|
||||
#include <driver.h>
|
||||
#include <lx_emul.h>
|
||||
|
||||
#include <lx_kit/env.h>
|
||||
#include <lx_kit/malloc.h>
|
||||
#include <lx_kit/scheduler.h>
|
||||
#include <lx_kit/timer.h>
|
||||
#include <lx_kit/work.h>
|
||||
|
||||
#include <lx_emul/extern_c_begin.h>
|
||||
#include <linux/usb.h>
|
||||
#include <lx_emul/extern_c_end.h>
|
||||
|
||||
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<Device*>(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<Device*>(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<void*>(this),
|
||||
"usb_state", Lx::Task::PRIORITY_0, Lx::scheduler()),
|
||||
urb_task(env.ep(), urb_task_entry, reinterpret_cast<void*>(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<Driver*>(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<void*>(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);
|
||||
}
|
32
repos/dde_linux/src/drivers/usb_net/target.mk
Normal file
32
repos/dde_linux/src/drivers/usb_net/target.mk
Normal file
@ -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
|
71
repos/dde_linux/usb_net.list
Normal file
71
repos/dde_linux/usb_net.list
Normal file
@ -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
|
Loading…
x
Reference in New Issue
Block a user