usb: remove monolithic usb driver

+ adjust README files

Fixes #4173
This commit is contained in:
Alexander Boettcher 2021-06-04 11:51:05 +02:00 committed by Christian Helmuth
parent b09e69a444
commit 27004e1fd5
65 changed files with 90 additions and 12451 deletions

View File

@ -162,10 +162,6 @@ capture-session and event-session interfaces respectively.
:_dde_linux/src/drivers/usb_hid/_:
USB Human Interface Device driver using the USB session interface.
:_os/src/drivers/usb_block/_:
USB storage driver that uses the USB session interface and provides
a block-session interface.
Timer drivers
=============
@ -220,11 +216,6 @@ _os/include/block_session/_.
:_os/src/drivers/sd_card/spec/rpi/_:
Driver for SD-cards connected to the Raspberry Pi.
:_dde_linux/src/drivers/usb/_:
USB driver that makes USB storage devices available as block sessions.
For an example of using this driver, refer to the run script at
_dde_linux/run/usb_storage.run_.
:_os/src/drivers/ahci/_:
Driver for SATA disks and CD-ROMs on x86 PCs.
@ -232,7 +223,8 @@ _os/include/block_session/_.
Driver for NVMe block devices on x86 PCs.
:_os/src/drivers/usb_block/_:
USB Mass Storage Bulk-Only driver using the USB session interface.
USB Mass Storage Bulk-Only driver using the USB session interface and provides
a block-session interface.
Network interface drivers
@ -257,8 +249,8 @@ defined at _os/include/nic_session/_.
The wifi_drv component is a port of the Linux mac802.11 stack, including the
iwlwifi driver. It enables the use of Intel Wireless 6xxx and 7xxx cards.
:_dde_linux/src/drivers/usb/_:
For the OMAP4 platform, the USB driver contains the networking driver.
:_dde_linux/src/drivers/usb_net/_:
USB network driver using the USB session interface.
:_dde_linux/src/drivers/nic/fec/_:
Driver for ethernet NICs of the i.MX SoC family.

View File

@ -3,174 +3,27 @@ Device drivers ported from the Linux kernel
USB
###
Controller configuration
~~~~~~~~~~~~~~~~~~~~~~~~
Host controller
~~~~~~~~~~~~~~~
The driver can be started using different or all USB controller types a platform
offers (USB 1.0/2.0/3.0). Note that not all controllers are supported by all
platforms. Controllers can be enabled as attribute in the config node of the
driver. Supported attributes are: 'uhci', 'ohci', 'ehci', and 'xhci'.
The driver will start all USB controller types a platform offers.
Configuration snippet to enable UHCI and EHCI
! <config uhci="yes" ehci="yes">
BIOS Handoff
~~~~~~~~~~~~
Per default the USB driver performs a hand off of the USB controller from the
BIOS, since it still may access the controller when booting, for example, from
a USB device. The BIOS hand off induces the execution of BIOS/SMM USB driver
code and potentially DMA operations. Unfortunately, some ACPI tables report
wrong RMRR information, which implicates IOMMU faults on illegal DMA
operations and consequently the hand off may fail after noticeably long
timeouts. Therefore, the hand off can be disabled in the USB driver
configuration like follows.
! <config bios_handoff="no"/>
Please consult repos/dde_linux/drivers/usb_host/README for a description.
HID
~~~
Supports keyboard and mouse. A run script can be found under 'run/usb_hid.run'.
Configuration snippet:
!<start name="usb_drv">
! <resource name="RAM" quantum="12M"/>
! <config uhci="yes" ohci="yes" ehci="yes" xhci="yes">
! <hid/>
! </config>
!</start>
With '<hid>' config node in place, the USB driver requests an "Event" session
for reporting input events.
Note: It has been observed that certain 1.0 versions of Qemu do not generate
mouse interrupts. The mouse driver should work correctly on Qemu 1.0.93 and
above.
HID - Touchscreen support
~~~~~~~~~~~~~~~~~~~~~~~~~
Touchscreen absolute coordinates must be calibrated (e.g. re-calculated) to
screen absolute coordinates. The screen resolution is not determined
automatically by the USB driver, but can be configured as sub node of the
hid xml tag:
!...
!<hid>
! <touchscreen width="1024" height="768" multitouch="no"/>
!</hid>
!...
If a touchscreen is multi-touch-capable than the multitouch attribute gears
which type of Genode input events are generated. If set to 'no' (default)
than absolute events are generated and no multitouch events. If set to 'yes'
solely multitouch events are generated.
Please consult repos/dde_linux/drivers/usb_hid/README for a description.
Storage
~~~~~~~
Currently supports one USB storage device. Hot plugging has not been tested. A
run script can be found under 'run/usb_storage.run'.
Configuration snippet:
!<start name="usb_drv">
! <resource name="RAM" quantum="12M"/>
! <provides> <service name="Block"/> </provides>
! <config><storage /></config>
!</start>
Please consult repos/os/src/drivers/usb_block/README for a description.
Network (Nic)
~~~~~~~~~~~~~
Configuration snippet:
!<start name="usb_drv">
! <resource name="RAM" quantum="12M"/>
! <provides>
! <service name="Nic"/>
! </provides>
! <config ehci="yes" xhci="yes">
! <nic mac="2e:60:90:0c:4e:01" />
! <hid/>
! </config>
!</start>
Please observe that this setup starts the HID and Nic service at the same time.
Also 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.
RAW
~~~
Allows raw access to USB devices via the 'Usb' session interface.
Configuration snippet:
!<start name="usb_drv">
! <resource name="RAM" quantum="12M"/>
! <provides><service name="Usb"/></provides>
! <config uhci="yes" ohci="yes" ehci="yes" xhci="yes">
! <raw>
! <report devices="yes"/>
! </raw>
! </config>
!</start>
The optional 'devices' report lists the connected devices and gets updated
when devices are added or removed.
Example report:
!<devices>
! <device label="usb-1-7" vendor_id="0x1f75" product_id="0x0917" bus="0x0001" dev="0x0007"/>
! <device label="usb-1-6" vendor_id="0x13fe" product_id="0x5200" bus="0x0001" dev="0x0006"/>
! <device label="usb-1-4" vendor_id="0x17ef" product_id="0x4816" bus="0x0001" dev="0x0004"/>
! <device label="usb-1-3" vendor_id="0x0a5c" product_id="0x217f" bus="0x0001" dev="0x0003"/>
! <device label="usb-2-2" vendor_id="0x8087" product_id="0x0020" bus="0x0002" dev="0x0002"/>
! <device label="usb-1-2" vendor_id="0x8087" product_id="0x0020" bus="0x0001" dev="0x0002"/>
! <device label="usb-2-1" vendor_id="0x1d6b" product_id="0x0002" bus="0x0002" dev="0x0001"/>
! <device label="usb-1-1" vendor_id="0x1d6b" product_id="0x0002" bus="0x0001" dev="0x0001"/>
!</devices>
For every device a unique identifier is generated that is used to access the
USB device. Only devices that have a valid policy configured at the USB driver
can be accessed by a client. The following configuration allows 'comp1' to
access the device 'usb-1-6':
!<start name="usb_drv">
! <resource name="RAM" quantum="12M"/>
! <provides><service name="Usb"/></provides>
! <config uhci="yes" ohci="yes" ehci="yes" xhci="yes">
! <raw>
! <report devices="yes"/>
! <policy label="comp1 -> usb-1-6" vendor_id="0x13fe" product_id="0x5200" bus="0x0001" dev="0x0006"/>
! </raw>
! </config>
!</start>
In addition to the mandatory 'label' attribute the policy node also
contains optional attribute tuples of which at least one has to be present.
The 'vendor_id' and 'product_id' tuple selects a device regardless of its
location on the USB bus and is mostly used in static configurations. The
'bus' and 'dev' tuple selects a specific device via its bus locations and
device address. It is mostly used in dynamic configurations because the device
address is not fixed and may change every time the same device is plugged in.
The configuration of the USB driver can be changed at runtime to satisfy
dynamic configurations or rather policies when using the 'Usb' session
interface.
Please consolut repos/dde_linux/src/drivers/usb_net/README for a description.
LXIP
####

View File

@ -1,16 +0,0 @@
USB_CONTRIB_DIR := $(call select_from_ports,dde_linux)/src/lib/usb
LIB_DIR := $(REP_DIR)/src/drivers/usb
LIB_INC_DIR := $(LIB_DIR)/include
include $(call select_from_repositories,lib/import/import-usb_arch_include.mk)
#
# 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 += $(LIB_INC_DIR)
INC_DIR += $(ARCH_SRC_INC_DIR)
INC_DIR += $(USB_CONTRIB_DIR)/include
INC_DIR += $(USB_CONTRIB_DIR)/drivers/usb/core
INC_DIR += $(LIB_CACHE_DIR)/usb_include/include/include/include

View File

@ -1,39 +0,0 @@
ifeq ($(called_from_lib_mk),yes)
USB_CONTRIB_DIR := $(call select_from_ports,dde_linux)/src/lib/usb
LX_EMUL_H := $(REP_DIR)/src/drivers/usb/include/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_CONTRIB_DIR)/include/, asm-generic linux scsi uapi) \
$(addprefix $(USB_CONTRIB_DIR)/, drivers lib)
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_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
# vi: set ft=make :
CC_CXX_WARN_STRICT =

View File

@ -1,12 +0,0 @@
diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c
index e6338c1..b768fc8 100644
--- a/drivers/net/usb/ax88179_178a.c
+++ b/drivers/net/usb/ax88179_178a.c
@@ -1266,6 +1266,7 @@ static int ax88179_bind(struct usbnet *dev, struct usb_interface *intf)
dev->net->netdev_ops = &ax88179_netdev_ops;
dev->net->ethtool_ops = &ax88179_ethtool_ops;
dev->net->needed_headroom = 8;
+ dev->net->net_ip_align = 1;
/* Initialize MII structure */
dev->mii.dev = dev->net;

View File

@ -1,19 +0,0 @@
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
index 66b3ab9..a17f054 100644
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -1730,7 +1730,13 @@ static int smsc95xx_reset_resume(struct usb_interface *intf)
static void smsc95xx_rx_csum_offload(struct sk_buff *skb)
{
- skb->csum = *(u16 *)(skb_tail_pointer(skb) - 2);
+ /*
+ * Use bytewise access to avoid alignment issues on packets that have none
+ * aligned sizes
+ */
+ char *tail = skb_tail_pointer(skb);
+ skb->csum = (*(tail - 2) << 8) | *(tail - 1);
+
skb->ip_summed = CHECKSUM_COMPLETE;
skb_trim(skb, skb->len - 2);
}

View File

@ -1,24 +0,0 @@
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index e9ae3d5..edd0b4f 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -1425,6 +1425,9 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
if (error)
goto err_cleanup_evdev;
+ evdev_open_device(evdev);
+ dev_info(evdev, "%s\n", dev->name);
+
return 0;
err_cleanup_evdev:
@@ -1457,8 +1460,7 @@ static const struct input_device_id evdev_ids[] = {
MODULE_DEVICE_TABLE(input, evdev_ids);
static struct input_handler evdev_handler = {
- .event = evdev_event,
- .events = evdev_events,
+ .event = genode_evdev_event,
.connect = evdev_connect,
.disconnect = evdev_disconnect,
.legacy_minors = true,

View File

@ -1,24 +0,0 @@
--- a/drivers/input/input-mt.c
+++ b/drivers/input/input-mt.c
@@ -217,10 +217,6 @@
count++;
}
- input_event(dev, EV_KEY, BTN_TOUCH, count > 0);
- if (use_count)
- input_mt_report_finger_count(dev, count);
-
if (oldest) {
int x = input_mt_get_value(oldest, ABS_MT_POSITION_X);
int y = input_mt_get_value(oldest, ABS_MT_POSITION_Y);
@@ -236,6 +232,10 @@
if (test_bit(ABS_MT_PRESSURE, dev->absbit))
input_event(dev, EV_ABS, ABS_PRESSURE, 0);
}
+
+ input_event(dev, EV_KEY, BTN_TOUCH, count > 0);
+ if (use_count)
+ input_mt_report_finger_count(dev, count);
}
EXPORT_SYMBOL(input_mt_report_pointer_emulation);

View File

@ -1,327 +0,0 @@
commit 91eb4a3e68978feca81f6a5bc31cfcd7c683d628
Author: Sebastian Sumpf <sebastian.sumpf@genode-labs.com>
Date: Tue Mar 15 09:59:11 2016 +0100
mem
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 5dd426f..6b4294a 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -841,7 +841,7 @@ static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid)
&usbhid->inbuf_dma);
usbhid->outbuf = usb_alloc_coherent(dev, usbhid->bufsize, GFP_KERNEL,
&usbhid->outbuf_dma);
- usbhid->cr = kmalloc(sizeof(*usbhid->cr), GFP_KERNEL);
+ usbhid->cr = kmalloc(sizeof(*usbhid->cr), GFP_LX_DMA);
usbhid->ctrlbuf = usb_alloc_coherent(dev, usbhid->bufsize, GFP_KERNEL,
&usbhid->ctrlbuf_dma);
if (!usbhid->inbuf || !usbhid->outbuf || !usbhid->cr ||
@@ -1013,7 +1013,7 @@ static int usbhid_parse(struct hid_device *hid)
return -EINVAL;
}
- if (!(rdesc = kmalloc(rsize, GFP_KERNEL))) {
+ if (!(rdesc = kmalloc(rsize, GFP_LX_DMA))) {
dbg_hid("couldn't allocate rdesc memory\n");
return -ENOMEM;
}
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 0744bf2..6237370 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -229,7 +229,7 @@ static int init_status (struct usbnet *dev, struct usb_interface *intf)
period = max ((int) dev->status->desc.bInterval,
(dev->udev->speed == USB_SPEED_HIGH) ? 7 : 3);
- buf = kmalloc (maxp, GFP_KERNEL);
+ buf = kmalloc (maxp, GFP_LX_DMA);
if (buf) {
dev->interrupt = usb_alloc_urb (0, GFP_KERNEL);
if (!dev->interrupt) {
@@ -1916,7 +1916,7 @@ static int __usbnet_read_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
cmd, reqtype, value, index, size);
if (data) {
- buf = kmalloc(size, GFP_KERNEL);
+ buf = kmalloc(size, GFP_LX_DMA);
if (!buf)
goto out;
}
@@ -1943,7 +1943,7 @@ static int __usbnet_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
cmd, reqtype, value, index, size);
if (data) {
- buf = kmemdup(data, size, GFP_KERNEL);
+ buf = kmemdup(data, size, GFP_LX_DMA);
if (!buf)
goto out;
}
@@ -2192,7 +2192,7 @@ int usbnet_write_cmd_async(struct usbnet *dev, u8 cmd, u8 reqtype,
}
if (data) {
- buf = kmemdup(data, size, GFP_ATOMIC);
+ buf = kmemdup(data, size, GFP_LX_DMA);
if (!buf) {
netdev_err(dev->net, "Error allocating buffer"
" in %s!\n", __func__);
@@ -2200,7 +2200,7 @@ int usbnet_write_cmd_async(struct usbnet *dev, u8 cmd, u8 reqtype,
}
}
- req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC);
+ req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_LX_DMA);
if (!req)
goto fail_free_buf;
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
index 5050760..9ac55f9 100644
--- a/drivers/usb/core/config.c
+++ b/drivers/usb/core/config.c
@@ -695,7 +695,7 @@ int usb_get_configuration(struct usb_device *dev)
if (!dev->rawdescriptors)
goto err2;
- desc = kmalloc(USB_DT_CONFIG_SIZE, GFP_KERNEL);
+ desc = kmalloc(USB_DT_CONFIG_SIZE, GFP_LX_DMA);
if (!desc)
goto err2;
@@ -724,7 +724,7 @@ int usb_get_configuration(struct usb_device *dev)
USB_DT_CONFIG_SIZE);
/* Now that we know the length, get the whole thing */
- bigbuffer = kmalloc(length, GFP_KERNEL);
+ bigbuffer = kmalloc(length, GFP_LX_DMA);
if (!bigbuffer) {
result = -ENOMEM;
goto err;
@@ -786,7 +786,7 @@ int usb_get_bos_descriptor(struct usb_device *dev)
int length, total_len, num, i;
int ret;
- bos = kzalloc(sizeof(struct usb_bos_descriptor), GFP_KERNEL);
+ bos = kzalloc(sizeof(struct usb_bos_descriptor), GFP_LX_DMA);
if (!bos)
return -ENOMEM;
@@ -812,7 +812,7 @@ int usb_get_bos_descriptor(struct usb_device *dev)
return -ENOMEM;
/* Now let's get the whole BOS descriptor set */
- buffer = kzalloc(total_len, GFP_KERNEL);
+ buffer = kzalloc(total_len, GFP_LX_DMA);
if (!buffer) {
ret = -ENOMEM;
goto err;
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 1560f3f..54e99b5 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1365,20 +1365,20 @@ static int hub_configure(struct usb_hub *hub,
unsigned full_load;
unsigned maxchild;
- hub->buffer = kmalloc(sizeof(*hub->buffer), GFP_KERNEL);
+ hub->buffer = kmalloc(sizeof(*hub->buffer), GFP_LX_DMA);
if (!hub->buffer) {
ret = -ENOMEM;
goto fail;
}
- hub->status = kmalloc(sizeof(*hub->status), GFP_KERNEL);
+ hub->status = kmalloc(sizeof(*hub->status), GFP_LX_DMA);
if (!hub->status) {
ret = -ENOMEM;
goto fail;
}
mutex_init(&hub->status_mutex);
- hub->descriptor = kmalloc(sizeof(*hub->descriptor), GFP_KERNEL);
+ hub->descriptor = kmalloc(sizeof(*hub->descriptor), GFP_LX_DMA);
if (!hub->descriptor) {
ret = -ENOMEM;
goto fail;
@@ -4586,7 +4586,7 @@ check_highspeed(struct usb_hub *hub, struct usb_device *udev, int port1)
if (udev->quirks & USB_QUIRK_DEVICE_QUALIFIER)
return;
- qual = kmalloc(sizeof *qual, GFP_KERNEL);
+ qual = kmalloc(sizeof *qual, GFP_LX_DMA);
if (qual == NULL)
return;
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 8e641b5..5807f68 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -942,7 +942,7 @@ int usb_get_device_descriptor(struct usb_device *dev, unsigned int size)
int usb_get_status(struct usb_device *dev, int type, int target, void *data)
{
int ret;
- __le16 *status = kmalloc(sizeof(*status), GFP_KERNEL);
+ __le16 *status = kmalloc(sizeof(*status), GFP_LX_DMA);
if (!status)
return -ENOMEM;
diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c
index b6205fa..99cae0f 100644
--- a/drivers/usb/host/ehci-mem.c
+++ b/drivers/usb/host/ehci-mem.c
@@ -82,7 +82,7 @@ static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, gfp_t flags)
struct ehci_qh *qh;
dma_addr_t dma;
- qh = kzalloc(sizeof *qh, GFP_ATOMIC);
+ qh = kzalloc(sizeof *qh, GFP_LX_DMA);
if (!qh)
goto done;
qh->hw = (struct ehci_qh_hw *)
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 776d59c..e32db7b 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -1354,7 +1354,7 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags)
size = 1;
urb_priv = kzalloc(sizeof(struct urb_priv) +
- size * sizeof(struct xhci_td *), mem_flags);
+ size * sizeof(struct xhci_td *), GFP_LX_DMA);
if (!urb_priv)
return -ENOMEM;
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 43576ed..2b13b4e 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -450,7 +450,7 @@ static int associate_dev(struct us_data *us, struct usb_interface *intf)
usb_set_intfdata(intf, us);
/* Allocate the control/setup and DMA-mapped buffers */
- us->cr = kmalloc(sizeof(*us->cr), GFP_KERNEL);
+ us->cr = kmalloc(sizeof(*us->cr), GFP_LX_DMA);
if (!us->cr)
return -ENOMEM;
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -325,7 +325,7 @@
if (td->mtclass.name != MT_CLS_WIN_8)
return;
- buf = hid_alloc_report_buf(report, GFP_KERNEL);
+ buf = hid_alloc_report_buf(report, GFP_LX_DMA);
if (!buf)
return;
@@ -912,7 +912,7 @@
if (r) {
if (cls->quirks & MT_QUIRK_FORCE_GET_FEATURE) {
report_len = hid_report_len(r);
- buf = hid_alloc_report_buf(r, GFP_KERNEL);
+ buf = hid_alloc_report_buf(r, GFP_LX_DMA);
if (!buf) {
hid_err(hdev, "failed to allocate buffer for report\n");
return;
@@ -1043,7 +1043,7 @@
if (suffix) {
name = devm_kzalloc(&hi->input->dev,
strlen(hdev->name) + strlen(suffix) + 2,
- GFP_KERNEL);
+ GFP_LX_DMA);
if (name) {
sprintf(name, "%s %s", hdev->name, suffix);
hi->input->name = name;
@@ -1096,7 +1096,7 @@
*/
hdev->quirks |= HID_QUIRK_NO_INIT_REPORTS;
- td = devm_kzalloc(&hdev->dev, sizeof(struct mt_device), GFP_KERNEL);
+ td = devm_kzalloc(&hdev->dev, sizeof(struct mt_device), GFP_LX_DMA);
if (!td) {
dev_err(&hdev->dev, "cannot allocate multitouch data\n");
return -ENOMEM;
@@ -1110,7 +1110,7 @@
hid_set_drvdata(hdev, td);
td->fields = devm_kzalloc(&hdev->dev, sizeof(struct mt_fields),
- GFP_KERNEL);
+ GFP_LX_DMA);
if (!td->fields) {
dev_err(&hdev->dev, "cannot allocate multitouch fields data\n");
return -ENOMEM;
--- a/drivers/hid/wacom_sys.c
+++ b/drivers/hid/wacom_sys.c
@@ -124,7 +124,7 @@
/* leave touch_max as is if predefined */
if (!features->touch_max) {
/* read manually */
- data = kzalloc(2, GFP_KERNEL);
+ data = kzalloc(2, GFP_LX_DMA);
if (!data)
break;
data[0] = field->report->id;
@@ -328,7 +328,7 @@
unsigned char *rep_data;
int error = -ENOMEM, limit = 0;
- rep_data = kzalloc(length, GFP_KERNEL);
+ rep_data = kzalloc(length, GFP_LX_DMA);
if (!rep_data)
return error;
@@ -530,7 +530,7 @@
data = wacom_get_hdev_data(hdev);
if (!data) {
- data = kzalloc(sizeof(struct wacom_hdev_data), GFP_KERNEL);
+ data = kzalloc(sizeof(struct wacom_hdev_data), GFP_LX_DMA);
if (!data) {
retval = -ENOMEM;
goto out;
@@ -595,7 +595,7 @@
report_id = WAC_CMD_WL_LED_CONTROL;
buf_size = 13;
}
- buf = kzalloc(buf_size, GFP_KERNEL);
+ buf = kzalloc(buf_size, GFP_LX_DMA);
if (!buf)
return -ENOMEM;
@@ -648,7 +648,7 @@
int i, retval;
const unsigned chunk_len = len / 4; /* 4 chunks are needed to be sent */
- buf = kzalloc(chunk_len + 3 , GFP_KERNEL);
+ buf = kzalloc(chunk_len + 3 , GFP_LX_DMA);
if (!buf)
return -ENOMEM;
@@ -1176,7 +1176,7 @@
wacom_wac->serial[index] = serial;
- buf = kzalloc(WAC_REMOTE_SERIAL_MAX_STRLEN, GFP_KERNEL);
+ buf = kzalloc(WAC_REMOTE_SERIAL_MAX_STRLEN, GFP_LX_DMA);
if (!buf)
return -ENOMEM;
snprintf(buf, WAC_REMOTE_SERIAL_MAX_STRLEN, "%d", serial);
@@ -1222,7 +1222,7 @@
unsigned char *buf;
int retval;
- buf = kzalloc(buf_size, GFP_KERNEL);
+ buf = kzalloc(buf_size, GFP_LX_DMA);
if (!buf)
return -ENOMEM;
@@ -1705,7 +1705,7 @@
/* hid-core sets this quirk for the boot interface */
hdev->quirks &= ~HID_QUIRK_NOGET;
- wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL);
+ wacom = kzalloc(sizeof(struct wacom), GFP_LX_DMA);
if (!wacom)
return -ENOMEM;

View File

@ -1,30 +0,0 @@
diff -Nur a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c
--- a/drivers/net/usb/rndis_host.c
+++ b/drivers/net/usb/rndis_host.c
@@ -318,7 +318,7 @@
unsigned char *bp;
/* we can't rely on i/o from stack working, or stack allocation */
- u.buf = kmalloc(CONTROL_BUFFER_SIZE, GFP_KERNEL);
+ u.buf = kzalloc(CONTROL_BUFFER_SIZE, GFP_KERNEL | GFP_LX_DMA);
if (!u.buf)
return -ENOMEM;
retval = usbnet_generic_cdc_bind(dev, intf);
@@ -475,7 +475,7 @@
struct rndis_halt *halt;
/* try to clear any rndis state/activity (no i/o from stack!) */
- halt = kzalloc(CONTROL_BUFFER_SIZE, GFP_KERNEL);
+ halt = kzalloc(CONTROL_BUFFER_SIZE, GFP_KERNEL | GFP_LX_DMA);
if (halt) {
halt->msg_type = cpu_to_le32(RNDIS_MSG_HALT);
halt->msg_len = cpu_to_le32(sizeof *halt);
@@ -573,7 +573,7 @@
* packets; Linux minimizes wasted bandwidth through tx queues.
*/
fill:
- hdr = (void *) __skb_push(skb, sizeof *hdr);
+ hdr = (void *) skb_push(skb, sizeof *hdr);
memset(hdr, 0, sizeof *hdr);
hdr->msg_type = cpu_to_le32(RNDIS_MSG_PACKET);
hdr->msg_len = cpu_to_le32(skb->len);

View File

@ -1,13 +0,0 @@
diff --git a/drivers/usb/host/ehci-timer.c b/drivers/usb/host/ehci-timer.c
index 424ac5d..a2afc34 100644
--- a/drivers/usb/host/ehci-timer.c
+++ b/drivers/usb/host/ehci-timer.c
@@ -422,7 +422,7 @@ static enum hrtimer_restart ehci_hrtimer_func(struct hrtimer *t)
*/
now = ktime_get();
for_each_set_bit(e, &events, EHCI_HRTIMER_NUM_EVENTS) {
- if (now.tv64 >= ehci->hr_timeouts[e].tv64)
+ if (now >= ehci->hr_timeouts[e])
event_handlers[e](ehci);
else
ehci_enable_event(ehci, e, false);

View File

@ -1,37 +0,0 @@
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 6237370..8339402 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -64,8 +64,30 @@
* the equation.
*/
#define MAX_QUEUE_MEMORY (60 * 1518)
-#define RX_QLEN(dev) ((dev)->rx_qlen)
-#define TX_QLEN(dev) ((dev)->tx_qlen)
+
+inline unsigned RX_QLEN(struct usbnet *dev)
+{
+ switch(dev->udev->speed) {
+ case USB_SPEED_HIGH:
+ return MAX_QUEUE_MEMORY/dev->rx_urb_size;
+ case USB_SPEED_SUPER:
+ return 16;
+ default:
+ return 4;
+ }
+}
+
+inline unsigned TX_QLEN(struct usbnet *dev)
+{
+ switch(dev->udev->speed) {
+ case USB_SPEED_HIGH:
+ return MAX_QUEUE_MEMORY/dev->hard_mtu;
+ case USB_SPEED_SUPER:
+ return 16;
+ default:
+ return 4;
+ }
+}
// reawaken network queue this soon after stopping; else watchdog barks
#define TX_TIMEOUT_JIFFIES (5*HZ)

View File

@ -1 +1 @@
6f2e873679a79e8c85bdf62c2f81910b357f8abe
c2dc5da56111d6a1734458679176722832b10207

View File

@ -1,6 +1,6 @@
LICENSE := GPLv2
VERSION := 2
DOWNLOADS := dwc_otg.git usb.archive intel_fb.archive lxip.archive \
DOWNLOADS := 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 \
usb_modem.archive usb_net.archive imx8_fb.archive
@ -18,21 +18,9 @@ YACC = bison
# The git checkout checks for the existence of SRC_DIR, which is created by the
# Linux extraction, therefore make sure to checkout the GIT sources first.
#
usb.archive: dwc_otg.git
usb_host.archive: dwc_otg_host.git
#
# USB
#
SRC_DIR_USB := src/lib/usb
VERSION_USB := 4.4.3
URL(usb) := https://www.kernel.org/pub/linux/kernel/v4.x/linux-$(VERSION_USB).tar.xz
SHA(usb) := 0b379cb19bbd7e38fc5a9a000ea927db55cce519a7400ec7fa705c581a6491dd
DIR(usb) := $(SRC_DIR_USB)
TAR_OPT(usb) := --strip-components=1 --files-from - < <(sed 's/-x.x.x/-$(VERSION_USB)/g' $(REP_DIR)/usb.list)
HASH_INPUT += $(REP_DIR)/usb.list
#
# USB host controller
#
@ -71,10 +59,6 @@ HASH_INPUT += $(REP_DIR)/usb_modem.list
#
# Raspberry Pi USB controller
#
URL(dwc_otg) := https://github.com/ssumpf/dwc_otg.git
REV(dwc_otg) := r3
DIR(dwc_otg) := $(SRC_DIR_USB)/drivers/usb/host/dwc_otg
URL(dwc_otg_host) := https://github.com/cproc/dwc_otg.git
REV(dwc_otg_host) := r5
DIR(dwc_otg_host) := $(SRC_DIR_USB_HOST)/drivers/usb/host
@ -194,17 +178,6 @@ PATCH_OPT(patches/libnl.patch) := -p1 -d ${DIR(libnl)}
# WPA supplicant
PATCH_OPT(patches/wpa_supplicant.patch) := -p1 -d ${DIR(wpa_supplicant)}
# USB
USB_OPT = -p1 -d$(SRC_DIR_USB)
PATCH_OPT(patches/usb_ax88179.patch) := $(USB_OPT)
PATCH_OPT(patches/usb_csum.patch) := $(USB_OPT)
PATCH_OPT(patches/usb_evdev.patch) := $(USB_OPT)
PATCH_OPT(patches/usb_input_mt.patch) := $(USB_OPT)
PATCH_OPT(patches/usb_mem.patch) := $(USB_OPT)
PATCH_OPT(patches/usb_usbnet.patch) := $(USB_OPT)
PATCH_OPT(patches/usb_rndis.patch) := $(USB_OPT)
PATCH_OPT(patches/usb_tv64.patch) := $(USB_OPT)
# USB HOST
USB_HOST_OPT = -p1 -d$(SRC_DIR_USB_HOST)
PATCH_OPT(patches/usb_host_mem.patch) := $(USB_HOST_OPT)

View File

@ -1,26 +0,0 @@
LIB_MK := lib/import/import-usb_include.mk lib/mk/usb_include.mk \
lib/import/import-usb_arch_include.mk \
$(foreach SPEC,x86_32 x86_64 arm,lib/mk/spec/$(SPEC)/lx_kit_setjmp.mk)
PORT_DIR := $(call port_dir,$(REP_DIR)/ports/dde_linux)
MIRROR_FROM_REP_DIR := $(LIB_MK) \
src/drivers/usb \
src/include src/lx_kit
MIRROR_FROM_PORT_DIR := $(shell cd $(PORT_DIR); find src/lib/usb -type f | grep -v ".git")
MIRROR_FROM_PORT_DIR := $(filter-out $(MIRROR_FROM_REP_DIR),$(MIRROR_FROM_PORT_DIR))
content: $(MIRROR_FROM_REP_DIR) $(MIRROR_FROM_PORT_DIR)
$(MIRROR_FROM_REP_DIR):
$(mirror_from_rep_dir)
$(MIRROR_FROM_PORT_DIR):
mkdir -p $(dir $@)
cp $(PORT_DIR)/$@ $@
content: LICENSE
LICENSE:
( echo "GNU General Public License version 2, see:"; \
echo "https://www.kernel.org/pub/linux/kernel/COPYING" ) > $@

View File

@ -1 +0,0 @@
2021-05-27 ca37c2f2c35387633aff258015e3bee29ff6109a

View File

@ -1,12 +0,0 @@
base
os
nic_session
uplink_session
nic_driver
usb_session
gpio_session
event_session
block_session
platform_session
timer_session
report_session

View File

@ -1,235 +0,0 @@
#
# USB HID test
#
# By default, the run script runs interactively and reports any received USB
# input events to the console.
#
# When run with the '--autopilot' run option, the run script tests the USB
# input events generated by a 'Pro Micro' microcontroller.
#
# Pro Micro setup instructions
# ----------------------------
#
# Install prerequisites (example for Xubuntu 16.04):
#
# $ sudo apt-get install gcc-avr avr-libc avrdude
#
# Checkout and build the microcontroller software:
#
# $ git clone https://github.com/cproc/lufa.git
# $ cd lufa
# $ git checkout genode_usb_tests
# $ cd Demos/Device/ClassDriver/KeyboardMouseGenode
# $ make
#
# Connect the 'RST' pin with the 'GND' pin to hold the Pro Micro in the reset
# state.
#
# Connect the Pro Micro to the host PC
#
# Check the device file name with 'dmesg'. If it is not 'ttyACM0', change
# 'AVRDUDE_PORT' in 'makefile' accordingly.
#
# Release the RST/GND pin connection and within the next 8 seconds run:
#
# $ make avrdude
#
# Disconnect the Pro Micro or put it into reset state again to avoid unexpected
# input events on the host PC.
#
if { [get_cmd_switch --autopilot] && [have_include "power_on/qemu"] } {
puts "Run script does not support autopilot mode on Qemu"
exit 0
}
if {![have_board rpi] && ![have_board pc]} {
puts "Run script does not support autopilot mode on this platform"
exit 0
}
proc usb_drv_binary { } {
if {[have_board rpi]} { return rpi_usb_drv }
if {[have_board pc]} { return usb_drv }
return no_usb_drv_available
}
#
# Build
#
set build_components {
core init timer
drivers/usb
server/event_dump
server/dynamic_rom
}
source ${genode_dir}/repos/base/run/platform_drv.inc
append_platform_drv_build_components
build $build_components
create_boot_directory
#
# Generate config
#
append config {
<config prio_levels="2">
<parent-provides>
<service name="ROM"/>
<service name="IRQ"/>
<service name="IO_MEM"/>
<service name="IO_PORT"/>
<service name="PD"/>
<service name="RM"/>
<service name="CPU"/>
<service name="LOG"/>
</parent-provides>
<default-route>
<any-service> <parent/> <any-child/> </any-service>
</default-route>
<default caps="100"/>}
append_platform_drv_config
append config {
<start name="timer" priority="0">
<resource name="CPU" quantum="10"/>
<resource name="RAM" quantum="1M"/>
<provides><service name="Timer"/></provides>
</start>
<start name="usb_drv" caps="150" priority="0">
<binary name="} [usb_drv_binary] {"/>
<resource name="RAM" quantum="12M"/>
<resource name="CPU" quantum="80"/>
<config uhci="yes" ohci="yes" ehci="yes" xhci="yes"
capslock_led="rom" numlock_led="rom" scrlock_led="rom"
bios_handoff="yes">
<hid/>
</config>
<route>
<service name="ROM" label="capslock"> <child name="dynamic_rom"/> </service>
<service name="ROM" label="numlock"> <child name="dynamic_rom"/> </service>
<service name="ROM" label="scrlock"> <child name="dynamic_rom"/> </service>
<service name="ROM"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="PD"> <parent/> </service>
<service name="IO_PORT"> <parent/> </service>
<service name="IO_MEM"> <parent/> </service>
<service name="IRQ"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="RM"> <parent/> </service>
<service name="Platform"> <any-child/> </service>
<service name="Regulator"> <child name="platform_drv"/> </service>
<service name="Timer"> <child name="timer"/> </service>
<service name="Event"> <child name="event_dump"/> </service>
</route>
</start>
<start name="dynamic_rom" priority="-1">
<resource name="RAM" quantum="4M"/>
<provides> <service name="ROM"/> </provides>
<config verbose="no">
<rom name="capslock">
<inline> <capslock enabled="no"/> </inline>
<sleep milliseconds="250" />
<inline> <capslock enabled="yes"/> </inline>
<sleep milliseconds="250" />
</rom>
<rom name="numlock">
<inline> <numlock enabled="no"/> </inline>
<sleep milliseconds="500" />
<inline> <numlock enabled="yes"/> </inline>
<sleep milliseconds="500" />
</rom>
<rom name="scrlock">
<inline> <scrlock enabled="no"/> </inline>
<sleep milliseconds="1000" />
<inline> <scrlock enabled="yes"/> </inline>
<sleep milliseconds="1000" />
</rom>
</config>
<route>
<service name="ROM"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="PD"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="Timer"> <child name="timer"/> </service>
</route>
</start>
<start name="event_dump" priority="-1">
<resource name="RAM" quantum="1M"/>
<provides> <service name="Event"/> </provides>
<config/>
</start>
</config>}
install_config $config
#
# Boot modules
#
# generic modules
set boot_modules {
core ld.lib.so init timer event_dump dynamic_rom
}
append boot_modules [usb_drv_binary]
append_platform_drv_boot_modules
build_boot_image $boot_modules
append qemu_args " -usb -usbdevice mouse -usbdevice keyboard"
append qemu_args " -device usb-ehci,id=ehci"
append xen_args { usbdevice=\["mouse","keyboard"\] }
if { [have_include "power_on/qemu"] || ![get_cmd_switch --autopilot] } { run_genode_until forever }
# autopilot test
run_genode_until {\[init -\> event_dump\] Input event #0\t} 60
# remove everything before the first interesting line
regexp {(\[init -\> event_dump\] Input event #0\t.*)} $output all output
run_genode_until {\[init -\> event_dump\] Input event #11.*\n} 40 [output_spawn_id]
# pay only attention to the output of init and its children
grep_output {^\[init }
unify_output { number [0-9]+} ""
unify_output {(?n)on usb-.*$} ""
unify_output {(?n)using .*$} ""
unify_output {(?n)^.*__wait_event.*$} ""
unify_output {(?n)^.*Failed to submit URB.*$} ""
unify_output {(?n)^.*dev_warn.*$} ""
filter_out_color_escape_sequences
trim_lines
compare_output_to {
[init -> event_dump] Input event #0 PRESS KEY_X 65534 key count: 1
[init -> event_dump] Input event #1 RELEASE KEY_X key count: 0
[init -> event_dump] Input event #2 PRESS BTN_LEFT 65534 key count: 1
[init -> event_dump] Input event #3 REL_MOTION -1+0 key count: 1
[init -> event_dump] Input event #4 REL_MOTION +0+1 key count: 1
[init -> event_dump] Input event #5 RELEASE BTN_LEFT key count: 0
[init -> usb_drv] dev_info: USB disconnect, device
[init -> usb_drv] dev_info: new full-speed USB device
[init -> usb_drv] dev_info: D L
[init -> usb_drv] dev_info: input: USB HID v1.11 Keyboard [D L]
[init -> usb_drv] dev_info: D L
[init -> usb_drv] dev_info: input: USB HID v1.11 Mouse [D L]
[init -> event_dump] Input event #6 PRESS KEY_X 65534 key count: 1
[init -> event_dump] Input event #7 RELEASE KEY_X key count: 0
[init -> event_dump] Input event #8 PRESS BTN_LEFT 65534 key count: 1
[init -> event_dump] Input event #9 REL_MOTION -1+0 key count: 1
[init -> event_dump] Input event #10 REL_MOTION +0+1 key count: 1
[init -> event_dump] Input event #11 RELEASE BTN_LEFT key count: 0
}

View File

@ -201,9 +201,8 @@ append config {
</config>
</start>
<start name="usb_drv" caps="150"> }
append config "<binary name=\"[usb_host_drv_binary]\"/>"
append config {
<start name="usb_drv" caps="150">
<binary name="} [usb_host_drv_binary] {"/>
<resource name="RAM" quantum="12M"/>
<provides> <service name="Usb"/> </provides>
<config bios_handoff="yes">

View File

@ -26,7 +26,8 @@ if {[get_cmd_switch --autopilot] && ![have_spec x86_64]} {
set build_components {
core init timer
drivers/usb
drivers/usb_host
drivers/usb_hid
server/event_dump
server/dynamic_rom
}
@ -67,17 +68,23 @@ append config {
<provides><service name="Timer"/></provides>
</start>
<start name="usb_drv" caps="120">
<start name="report_rom">
<resource name="RAM" quantum="1M"/>
<provides> <service name="Report"/> <service name="ROM"/> </provides>
<config verbose="no">
<default-policy report="usb_drv -> devices"/>
</config>
</start>
<start name="usb_drv" caps="150">
<binary name="} [usb_host_drv_binary] {"/>
<resource name="RAM" quantum="12M"/>
<config uhci="no" ohci="no" ehci="no" xhci="yes"
capslock_led="rom" numlock_led="rom" scrlock_led="rom"
bios_handoff="yes">
<hid/>
<provides> <service name="Usb"/> </provides>
<config uhci="no" ohci="no" ehci="no" xhci="yes" bios_handoff="yes">
<report devices="yes"/>
<policy label_prefix="usb_hid_drv" class="0x3"/>
</config>
<route>
<service name="ROM" label="capslock"> <child name="dynamic_rom"/> </service>
<service name="ROM" label="numlock"> <child name="dynamic_rom"/> </service>
<service name="ROM" label="scrlock"> <child name="dynamic_rom"/> </service>
<service name="ROM"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="PD"> <parent/> </service>
@ -87,7 +94,20 @@ append config {
<service name="RM"> <parent/> </service>
<service name="Platform"> <any-child/> </service>
<service name="Timer"> <child name="timer"/> </service>
<service name="Event"> <child name="event_dump"/> </service>
<service name="Report"> <child name="report_rom"/> </service>
</route>
</start>
<start name="usb_hid_drv" caps="140">
<resource name="RAM" quantum="11M"/>
<config use_report="yes" capslock_led="rom" numlock_led="rom" scrlock_led="rom"/>
<route>
<service name="ROM" label="capslock"> <child name="dynamic_rom"/> </service>
<service name="ROM" label="numlock"> <child name="dynamic_rom"/> </service>
<service name="ROM" label="scrlock"> <child name="dynamic_rom"/> </service>
<service name="ROM" label="report"> <child name="report_rom"/> </service>
<service name="Event"> <child name="event_dump"/> </service>
<any-service> <parent/> <any-child/> </any-service>
</route>
</start>
@ -138,8 +158,10 @@ install_config $config
# generic modules
set boot_modules {
core ld.lib.so init timer usb_drv event_dump dynamic_rom
core ld.lib.so init timer event_dump dynamic_rom
usb_hid_drv
}
append boot_modules [usb_host_drv_binary]
append_platform_drv_boot_modules

View File

@ -12,10 +12,12 @@ assert_spec x86
set build_components {
core init timer
drivers/usb
drivers/usb_host
drivers/usb_net
server/tcp_terminal
test/terminal_echo
lib/vfs/lwip
lib/vfs/pipe
server/nic_router
}
@ -30,7 +32,8 @@ create_boot_directory
# Generate config
#
set config {
set config ""
append config {
<config verbose="yes">
<parent-provides>
<service name="ROM"/>
@ -52,13 +55,24 @@ set config {
<provides> <service name="Timer"/> </provides>
</start>
<start name="usb_drv">
<start name="usb_drv" caps="120">
<binary name="} [usb_host_drv_binary] {"/>
<resource name="RAM" quantum="24M"/>
<config mode="uplink_client" uhci="no" ohci="no" ehci="yes" xhci="yes">
<nic mac="02:00:00:00:01:01" />
<provides><service name="Usb"/></provides>
<config>
<policy label_prefix="usb_net_drv" vendor_id="0x0b95" product_id="0x1790"/>
</config>
</start>
<start name="usb_net_drv">
<resource name="RAM" quantum="20M"/>
<config mode="uplink_client" mac="02:00:00:00:01:01" />
<route>
<service name="Uplink"><child name="nic_router"/></service>
<any-service> <parent/> <any-child/> </any-service>
</route>
</start>
<start name="nic_router" caps="200">
<resource name="RAM" quantum="10M"/>
<provides>
@ -68,7 +82,7 @@ set config {
<config verbose_domain_state="yes">
<policy label_prefix="tcp_terminal" domain="downlink"/>
<policy label_prefix="usb_drv" domain="uplink"/>
<policy label_prefix="usb_net_drv" domain="uplink"/>
<domain name="uplink">
@ -87,7 +101,7 @@ set config {
</start>
<start name="tcp_terminal" caps="200">
<resource name="RAM" quantum="2560K"/>
<resource name="RAM" quantum="3M"/>
<provides> <service name="Terminal"/> </provides>
<config>
<policy label_prefix="test-terminal_echo" port="8888"/>
@ -105,8 +119,7 @@ set config {
</start>
<start name="test-terminal_echo">
<resource name="RAM" quantum="2M"/>
</start>
}
</start>}
append_platform_drv_config
@ -122,13 +135,15 @@ install_config $config
# generic modules
set boot_modules {
core ld.lib.so init timer usb_drv
libc.lib.so vfs.lib.so lwip_legacy.lib.so
core ld.lib.so init timer
libc.lib.so vfs.lib.so vfs_pipe.lib.so
tcp_terminal
test-terminal_echo
vfs_lwip.lib.so
usb_net_drv
nic_router
}
append boot_modules [usb_host_drv_binary]
append_platform_drv_boot_modules

View File

@ -1,121 +0,0 @@
#
# \brief Test for using the Block (Storage) service of usb_drv
# \author Christian Prochaska
# \date 2011-06-24
#
assert_spec x86
#
# Build
#
set build_components {
core init timer
drivers/usb
test/block/client
}
source ${genode_dir}/repos/base/run/platform_drv.inc
append_platform_drv_build_components
build $build_components
create_boot_directory
#
# Generate config
#
set config {
<config verbose="yes">
<parent-provides>
<service name="ROM"/>
<service name="IRQ"/>
<service name="IO_MEM"/>
<service name="IO_PORT"/>
<service name="PD"/>
<service name="RM"/>
<service name="CPU"/>
<service name="LOG"/>
</parent-provides>
<default-route>
<any-service> <parent/> <any-child/> </any-service>
</default-route>
<default caps="100"/>}
append_platform_drv_config
append config {
<start name="timer">
<resource name="RAM" quantum="1M"/>
<provides> <service name="Timer"/> </provides>
</start>
<start name="usb_drv">
<resource name="RAM" quantum="12M"/>
<provides> <service name="Block"/> </provides>
<config uhci="yes" ohci="yes" ehci="yes" xhci="yes"><storage /></config>
</start>
<start name="test-usb">
<resource name="RAM" quantum="2M" />
<binary name="test-block-client" />
<config test_size="1M" />
</start>
</config>
}
install_config $config
#
# Boot modules
#
# generic modules
set boot_modules {
core ld.lib.so init timer usb_drv test-block-client
}
append_platform_drv_boot_modules
build_boot_image $boot_modules
#
# Execute test case
#
set disk_image "bin/test.img"
set cmd "dd if=/dev/zero of=$disk_image bs=1024 count=65536"
puts "creating disk image:\n$cmd"
catch { exec sh -c $cmd }
set cmd "mkfs.vfat -F32 $disk_image"
puts "formating disk image with vfat file system:\$cmd"
catch { exec sh -c $cmd }
#
# Qemu opts for UHCI
#
#append qemu_args " -nographic -usbdevice disk::$disk_image -boot order=d"
#
# Qemu opts for EHCI
#
append qemu_args "-drive if=none,id=disk,file=$disk_image"
append qemu_args { \
-nographic -M pc \
-device usb-ehci,id=ehci \
-device usb-storage,bus=ehci.0,drive=disk \
-boot order=d }
#
# Qemu opts for XHCI
#
#append qemu_args { \
# -nographic -M pc \
#-device nec-usb-xhci,id=xhci \
#-device usb-storage,bus=xhci.0,drive=disk \
#-boot order=d }
run_genode_until {.*child "test-usb" exited with exit value 0.*} 100
puts "\nTest succeeded\n"
# vi: set ft=tcl :

View File

@ -17,7 +17,7 @@ if {[have_include power_on/qemu]} {
#
set build_components {
core init timer
drivers/usb
drivers/usb_host
server/usb_terminal
test/terminal_echo
}
@ -57,13 +57,12 @@ append config {
<resource name="RAM" quantum="2M"/>
<provides><service name="Timer"/></provides>
</start>
<start name="usb_drv">
<start name="usb_drv" caps="120">
<binary name="} [usb_host_drv_binary] {"/>
<resource name="RAM" quantum="32M"/>
<provides><service name="Usb"/></provides>
<config uhci="yes" ohci="yes" ehci="yes" xhci="yes">
<raw>
<policy label="usb_terminal -> usb_serial" vendor_id="0x67b" product_id="0x2303"/>
</raw>
<config>
<policy label="usb_terminal -> usb_serial" vendor_id="0x67b" product_id="0x2303"/>
</config>
</start>
<start name="usb_terminal">
@ -83,9 +82,10 @@ install_config $config
# generic modules
set boot_modules {
core ld.lib.so init timer usb_drv test-terminal_echo
core ld.lib.so init timer test-terminal_echo
usb_terminal
}
append boot_modules [usb_host_drv_binary]
append_platform_drv_boot_modules

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,135 +0,0 @@
/*
* \brief Platform specific definitions
* \author Sebastian Sumpf
* \date 2012-07-06
*
* These functions have to be implemented on all supported platforms.
*/
/*
* Copyright (C) 2012-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _PLATFORM_H_
#define _PLATFORM_H_
#include <base/log.h>
#include <util/xml_node.h>
#include <irq_session/capability.h>
#include <lx_kit/env.h>
struct Services
{
Genode::Env &env;
/* USB profiles */
bool hid = false;
bool stor = false;
bool nic = false;
bool raw = false;
/* Controller types */
bool uhci = false; /* 1.0 */
bool ohci = false;
bool ehci = false; /* 2.0 */
bool xhci = false; /* 3.0 */
/*
* Screen resolution used by touch devices to convert touchscreen
* absolute coordinates to screen absolute coordinates
*/
bool multitouch = false;
unsigned long screen_width = 0;
unsigned long screen_height = 0;
/* report generation */
bool raw_report_device_list = false;
Services(Genode::Env &env) : env(env)
{
using namespace Genode;
Genode::Xml_node config_node = Lx_kit::env().config_rom().xml();
try {
Genode::Xml_node node_hid = config_node.sub_node("hid");
hid = true;
try {
Genode::Xml_node node_screen = node_hid.sub_node("touchscreen");
node_screen.attribute("width").value(screen_width);
node_screen.attribute("height").value(screen_height);
multitouch = node_screen.attribute_value("multitouch", false);
} catch (...) {
screen_width = screen_height = 0;
log("Could not read screen resolution in config node");
}
log("Configured HID screen with ", screen_width, "x", screen_height,
" (multitouch=", multitouch ? "true" : "false", ")");
} catch (Xml_node::Nonexistent_sub_node) {
log("No <hid> config node found - not starting the USB HID (Input) service");
}
try {
config_node.sub_node("storage");
stor = true;
} catch (Xml_node::Nonexistent_sub_node) {
log("No <storage> config node found - not starting the USB Storage (Block) service");
}
try {
config_node.sub_node("nic");
nic = true;
} catch (Xml_node::Nonexistent_sub_node) {
log("No <nic> config node found - not starting the USB Nic (Network) service");
}
try {
Genode::Xml_node node_raw = config_node.sub_node("raw");
raw = true;
try {
Genode::Xml_node node_report = node_raw.sub_node("report");
raw_report_device_list = node_report.attribute_value("devices", false);
} catch (...) { }
} catch (Xml_node::Nonexistent_sub_node) {
log("No <raw> config node found - not starting external USB service");
}
if (config_node.attribute_value("uhci", false)) {
uhci = true;
log("Enabled UHCI (USB 1.0/1.1) support");
}
if (config_node.attribute_value("ohci", false)) {
ohci = true;
log("Enabled OHCI (USB 1.0/1.1) support");
}
if (config_node.attribute_value("ehci", false)) {
ehci = true;
log("Enabled EHCI (USB 2.0) support");
}
if (config_node.attribute_value("xhci", false)) {
xhci = true;
log("Enabled XHCI (USB 3.0) support");
}
if (!(uhci | ohci | ehci | xhci))
warning("Warning: No USB controllers enabled.\n"
"Use <config (u/o/e/x)hci=\"yes\"> in your 'usb_drv' configuration");
}
};
void backend_alloc_init(Genode::Env &env, Genode::Ram_allocator &ram, Genode::Allocator &alloc);
void platform_hcd_init(Genode::Env &, Services *services);
Genode::Irq_session_capability platform_irq_activate(int irq);
#endif /* _PLATFORM_H_ */

View File

@ -1,62 +0,0 @@
/*
* \brief Main-signal receiver and signal-helper functions
* \author Sebastian Sumpf <sebastian.sumpf@genode-labs.com>
* \date 2012-05-23
*/
/*
* Copyright (C) 2012-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _SIGNAL_H_
#define _SIGNAL_H_
#include <platform.h>
#include <base/signal.h>
static bool const verbose = false;
/**
* Helper that holds sender and entrypoint
*/
class Signal_helper
{
private:
Genode::Env &_env;
Genode::Signal_transmitter _sender;
public:
Signal_helper(Genode::Env &env) : _env(env) { }
Genode::Entrypoint &ep() { return _env.ep(); }
Genode::Signal_transmitter &sender() { return _sender; }
Genode::Parent &parent() { return _env.parent(); }
Genode::Env &env() { return _env; }
Genode::Ram_allocator &ram() { return _env.ram(); }
Genode::Region_map &rm() { return _env.rm(); }
};
namespace Storage
{
void init(Genode::Env &env);
}
namespace Nic
{
void init(Genode::Env &env);
}
namespace Raw
{
void init(Genode::Env &env, bool report_device_list);
}
#endif /* _SIGNAL_H_ */

View File

@ -1,357 +0,0 @@
/*
* \brief Platform specific part of the Linux API emulation
* \author Sebastian Sumpf
* \date 2012-06-18
*/
/*
* Copyright (C) 2012-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _ARM__PLATFORM__LX_EMUL_H_
#define _ARM__PLATFORM__LX_EMUL_H_
#include <platform/lx_emul_barrier.h>
/*************************
** asm-generic/sizes.h **
*************************/
enum {
SZ_1K = 0x00000400,
SZ_4K = 0x00001000,
};
struct platform_device
{
char *name;
int id;
struct device dev;
u32 num_resources;
struct resource *resource;
};
/**********************
** linux/usb/ulpi.h **
**********************/
enum {
ULPI_FUNC_CTRL_RESET = (1 << 5),
ULPI_FUNC_CTRL = (1 << 2),
};
/*
* Macros for Set and Clear
* See ULPI 1.1 specification to find the registers with Set and Clear offsets
*/
#define ULPI_SET(a) (a + 1)
/*****************************
** linux/platform_device.h **
*****************************/
#define module_platform_driver(__platform_driver) \
module_driver(__platform_driver, platform_driver_register, \
platform_driver_unregister)
enum { PLATFORM_DEVID_AUTO = -2 };
struct platform_driver {
int (*probe)(struct platform_device *);
int (*remove)(struct platform_device *);
void (*shutdown)(struct platform_device *);
int (*suspend)(struct platform_device *, pm_message_t state);
int (*resume)(struct platform_device *);
struct device_driver driver;
const struct platform_device_id *id_table;
};
struct resource *platform_get_resource(struct platform_device *, unsigned, unsigned);
struct resource *platform_get_resource_byname(struct platform_device *, unsigned int, const char *);
int platform_get_irq(struct platform_device *, unsigned int);
int platform_get_irq_byname(struct platform_device *, const char *);
int platform_driver_register(struct platform_driver *);
int platform_device_register(struct platform_device *);
void platform_device_unregister(struct platform_device *);
struct platform_device *platform_device_alloc(const char *name, int id);
int platform_device_add_data(struct platform_device *pdev, const void *data,
size_t size);
int platform_device_add_resources(struct platform_device *pdev,
const struct resource *res, unsigned int num);
int platform_device_add(struct platform_device *pdev);
int platform_device_del(struct platform_device *pdev);
int platform_device_put(struct platform_device *pdev);
#define to_platform_device(x) container_of((x), struct platform_device, dev)
/**********************
** asm/generic/io.h **
**********************/
static inline u32 __raw_readl(const volatile void __iomem *addr)
{
return *(const volatile u32 __force *) addr;
}
static inline void __raw_writel(u32 b, volatile void __iomem *addr)
{
*(volatile u32 __force *) addr = b;
}
static inline u8 __raw_readb(const volatile void __iomem *addr)
{
return *(const volatile u8 __force *) addr;
}
static inline void __raw_writeb(u8 b, volatile void __iomem *addr)
{
*(volatile u8 __force *) addr = b;
}
/********************************
** linux/regulator/consumer.h **
********************************/
struct regulator { };
int regulator_enable(struct regulator *);
int regulator_disable(struct regulator *);
void regulator_put(struct regulator *regulator);
struct regulator *regulator_get(struct device *dev, const char *id);
struct regulator *__must_check devm_regulator_get(struct device *dev,
const char *id);
/*******************************************
** arch/arm/plat-omap/include/plat/usb.h **
*******************************************/
int omap_usbhs_enable(struct device *dev);
void omap_usbhs_disable(struct device *dev);
/*****************
** linux/clk.h **
*****************/
struct clk *clk_get(struct device *, const char *);
int clk_enable(struct clk *);
void clk_disable(struct clk *);
void clk_put(struct clk *);
struct clk *devm_clk_get(struct device *dev, const char *id);
int clk_prepare_enable(struct clk *);
void clk_disable_unprepare(struct clk *);
/******************
** linux/gpio.h **
******************/
enum { GPIOF_OUT_INIT_HIGH = 0x2 };
bool gpio_is_valid(int);
void gpio_set_value_cansleep(unsigned, int);
int gpio_request_one(unsigned, unsigned long, const char *);
int devm_gpio_request_one(struct device *dev, unsigned gpio,
unsigned long flags, const char *label);
/****************
** linux/of.h **
****************/
#define of_match_ptr(ptr) NULL
#define for_each_available_child_of_node(parent, child) while (0)
unsigned of_usb_get_maximum_speed(struct device_node *np);
unsigned of_usb_get_dr_mode(struct device_node *np);
int of_device_is_compatible(const struct device_node *device, const char *);
void of_node_put(struct device_node *node);
int of_property_read_u32(const struct device_node *np, const char *propname,
u32 *out_value);
/*************************
** linux/of_platform.h **
*************************/
struct of_dev_auxdata;
int of_platform_populate(struct device_node *, const struct of_device_id *,
const struct of_dev_auxdata *, struct device *);
/*********************
** linux/of_gpio.h **
*********************/
int of_get_named_gpio(struct device_node *, const char *, int);
/******************
** linux/phy.h **
******************/
enum {
MII_BUS_ID_SIZE = 17,
PHY_MAX_ADDR = 32,
PHY_POLL = -1,
};
#define PHY_ID_FMT "%s:%02x"
struct mii_bus
{
const char *name;
char id[MII_BUS_ID_SIZE];
int (*read)(struct mii_bus *bus, int phy_id, int regnum);
int (*write)(struct mii_bus *bus, int phy_id, int regnum, u16 val);
void *priv;
int *irq;
};
struct phy_device
{
int speed;
int duplex;
int link;
};
struct mii_bus *mdiobus_alloc(void);
int mdiobus_register(struct mii_bus *bus);
void mdiobus_unregister(struct mii_bus *bus);
void mdiobus_free(struct mii_bus *bus);
int phy_mii_ioctl(struct phy_device *phydev, struct ifreq *ifr, int cmd);
void phy_print_status(struct phy_device *phydev);
int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd);
int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd);
void phy_start(struct phy_device *phydev);
int phy_start_aneg(struct phy_device *phydev);
void phy_stop(struct phy_device *phydev);
int phy_create_lookup(struct phy *phy, const char *con_id, const char *dev_id);
void phy_remove_lookup(struct phy *phy, const char *con_id, const char *dev_id);
int genphy_resume(struct phy_device *phydev);
struct phy_device * phy_connect(struct net_device *dev, const char *bus_id,
void (*handler)(struct net_device *),
phy_interface_t interface);
void phy_disconnect(struct phy_device *phydev);
struct phy *devm_phy_get(struct device *dev, const char *string);
struct phy *devm_of_phy_get(struct device *dev, struct device_node *np,
const char *con_id);
/*********************************
** linux/usb/usb_phy_generic.h **
*********************************/
#include <linux/usb/ch9.h>
#include <linux/usb/phy.h>
struct usb_phy_generic_platform_data
{
enum usb_phy_type type;
int gpio_reset;
};
/*******************************
** linux/usb/nop-usb-xceiv.h **
*******************************/
struct nop_usb_xceiv_platform_data { int type; };
/*******************************
** linux/usb/samsung_usb_phy **
*******************************/
enum samsung_usb_phy_type { USB_PHY_TYPE_HOST = 1 };
/***********************
** asm/dma-mapping.h **
***********************/
/* needed by 'dwc_otg_hcd_linux.c' */
void *dma_to_virt(struct device *dev, dma_addr_t addr);
/********************
** asm/irqflags.h **
********************/
void local_fiq_disable();
void local_fiq_enable();
unsigned smp_processor_id(void);
/***************
** asm/fiq.h **
***************/
struct pt_regs;
int claim_fiq(struct fiq_handler *f);
void set_fiq_regs(struct pt_regs const *regs);
void enable_fiq();
void set_fiq_handler(void *start, unsigned int length);
/************************************
** /linux/usb/usb_phy_gen_xceiv.h **
************************************/
struct usb_phy_gen_xceiv_platform_data
{
unsigned type;
int gpio_reset;
};
/******************************
** linux/usb/xhci_pdriver.h **
******************************/
struct usb_xhci_pdata {
unsigned usb3_lpm_capable:1;
};
/******************
** asm/memory.h **
******************/
#define __bus_to_virt phys_to_virt
/********************************************************
** drivers/usb/host/dwc_otg/dwc_otg/dwc_otg_fiq_fsm.h **
********************************************************/
extern bool fiq_enable, fiq_fsm_enable;
#endif /* _ARM__PLATFORM__LX_EMUL_H_ */

View File

@ -1,24 +0,0 @@
/*
* \brief ARMv6-specific part of the Linux API emulation
* \author Christian Prochaska
* \date 2014-05-28
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _ARMV6__PLATFORM__LX_EMUL_BARRIER_H_
#define _ARMV6__PLATFORM__LX_EMUL_BARRIER_H_
/*******************
** asm/barrier.h **
*******************/
#include <lx_emul/barrier.h>
#endif /* _ARMV6__PLATFORM__LX_EMUL_BARRIER_H_ */

View File

@ -1,24 +0,0 @@
/*
* \brief ARMv7-specific part of the Linux API emulation
* \author Christian Prochaska
* \date 2014-05-28
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _ARMV7__PLATFORM__LX_EMUL_BARRIER_H_
#define _ARMV7__PLATFORM__LX_EMUL_BARRIER_H_
/*******************
** asm/barrier.h **
*******************/
#include <lx_emul/barrier.h>
#endif /* _ARMV7__PLATFORM__LX_EMUL_BARRIER_H_ */

View File

@ -1,14 +0,0 @@
/*
* \brief USB: DWC-OTG RaspberryPI Interrupt (base-foc)
* \author Reinier Millo Sánchez <rmillo@uclv.cu>
* \date 2015-06-21
*/
#ifndef _INCLUDE_USB_IRQ_H_
#define _INCLUDE_USB_IRQ_H_
enum{
DWC_IRQ = 9,
};
#endif /* _INCLUDE_USB_IRQ_H_ */

View File

@ -1,33 +0,0 @@
/*
* \brief Platform specific part of the Linux API emulation
* \author Sebastian Sumpf
* \date 2012-06-18
*/
/*
* Copyright (C) 2012-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _X86_32__PLATFORM__LX_EMUL_
#define _X86_32__PLATFORM__LX_EMUL_
/*******************
** asm/barrier.h **
*******************/
#include <lx_emul/barrier.h>
struct platform_device
{
void *data;
};
#define dev_is_pci(d) (1)
#endif /* _X86_32__PLATFORM__LX_EMUL_ */

View File

@ -1,88 +0,0 @@
/*
* \brief SCSI helpers
* \author Sebastian Sumpf
* \date 2012-05-06
*/
/*
* Copyright (C) 2012-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _SCSI_H_
#define _SCSI_H_
struct scsi_cmnd;
#ifdef __cplusplus
extern "C" {
#endif
/**
* Add a SCSI device
*
* \param sdev Device to add
*/
void scsi_add_device(struct scsi_device *sdev);
/**
* Alloc data buffer for command
*
* \param size Size of buffer
* \param cmnd Command to assciate buffer
*/
void scsi_alloc_buffer(size_t size, struct scsi_cmnd *cmnd);
/**
* Fill command
*
* \param cmnd Command buffer to setup
* \param size Data size
* \param virt Virtual address of buffer
* \param addr DMA address of buffer
*/
void scsi_setup_buffer(struct scsi_cmnd *cmnd, size_t size, void *virt, dma_addr_t addr);
/**
* Free data buffer of command
*
* \param cmnd Command
*/
void scsi_free_buffer(struct scsi_cmnd *cmnd);
/**
* Get buffer data for command
*
* \param cmnd Command to retrieve buffer pointer
*
* \return Buffer pointer
*/
void *scsi_buffer_data(struct scsi_cmnd *cmnd);
/**
* Allocate a SCSI command
*
* \return Allocated command or zero on failure
*/
struct scsi_cmnd *_scsi_alloc_command();
/**
* Free a SCSI command
*
* \param cmnd Command
*/
void _scsi_free_command(struct scsi_cmnd *cmnd);
#ifdef __cplusplus
}
#endif
#endif /* _SCSI_H_ */

View File

@ -1,441 +0,0 @@
/*
* \brief Block-session implementation for network devices
* \author Sebastian Sumpf
* \date 2012-07-05
*/
/*
* Copyright (C) 2012-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _USB_NIC_COMPONENT_H_
#define _USB_NIC_COMPONENT_H_
/* Genode includes */
#include <base/log.h>
#include <nic/component.h>
#include <root/component.h>
/* Linux emulation environment includes */
#include <lx_emul.h>
#include <lx_emul/extern_c_begin.h>
#include <linux/usb.h>
#include <linux/usb/usbnet.h>
#include <lx_emul/extern_c_end.h>
/* NIC driver includes */
#include <drivers/nic/uplink_client_base.h>
namespace Usb_nic {
using namespace Genode;
using Genode::size_t;
class Session_component;
struct Device;
};
class Usb_network_session
{
protected:
Usb_nic::Device &_device;
public:
Usb_network_session(Usb_nic::Device &device)
:
_device { device }
{ }
virtual void link_state_changed() = 0;
virtual void rx(Genode::addr_t virt,
Genode::size_t size) = 0;
};
struct Usb_nic::Device
{
Usb_network_session *_session;
/**
* Transmit data to driver
*/
virtual bool tx(addr_t virt, size_t size) = 0;
/**
* Return mac address of device
*/
virtual Nic::Mac_address mac_address() = 0;
/**
* Return current link-state (true if link detected)
*/
virtual bool link_state() = 0;
/**
* Set session belonging to this driver
*/
void session(Usb_network_session *s) { _session = s; }
/**
* Check for session
*/
bool session() { return _session != 0; }
/**
* Alloc an SKB
*/
virtual sk_buff *alloc_skb() = 0;
/**
* Submit SKB to device
*/
virtual void tx_skb(sk_buff *skb) = 0;
/**
* Setup SKB with 'data' of 'size', return 'false' if SKB is longer than
* 'end'.
*/
virtual bool skb_fill(struct sk_buff *skb, unsigned char *data, Genode::size_t size, unsigned char *end) = 0;
/**
* Call driver fixup function on SKB
*/
virtual void tx_fixup(struct sk_buff *skb) = 0;
/**
* Return true if device supports burst operations
*/
virtual bool burst() = 0;
Device() : _session(0) { }
};
class Usb_nic::Session_component : public Usb_network_session,
public Nic::Session_component
{
protected:
void _send_burst()
{
static sk_buff work_skb; /* dummy skb for fixup calls */
static Packet_descriptor save;
sk_buff *skb = nullptr;
unsigned char *ptr = nullptr;
/* submit received packets to lower layer */
while (((_tx.sink()->packet_avail() || save.size()) && _tx.sink()->ready_to_ack()))
{
/* alloc skb */
if (!skb) {
if (!(skb = _device.alloc_skb()))
return;
ptr = skb->data;
work_skb.data = nullptr;
}
Packet_descriptor packet = save.size() ? save : _tx.sink()->get_packet();
save = Packet_descriptor();
if (!_device.skb_fill(&work_skb, ptr, packet.size(), skb->end)) {
/* submit batch */
_device.tx_skb(skb);
skb = nullptr;
save = packet;
continue;
}
/* copy packet to current data pos */
try { Genode::memcpy(work_skb.data, _tx.sink()->packet_content(packet), packet.size()); }
catch (Genode::Packet_descriptor::Invalid_packet) { }
/* call fixup on dummy SKB */
_device.tx_fixup(&work_skb);
/* advance to next slot */
ptr = work_skb.end;
skb->len += work_skb.truesize;
/* acknowledge to client */
_tx.sink()->acknowledge_packet(packet);
}
/* submit last skb */
if (skb)
_device.tx_skb(skb);
}
bool _send()
{
if (!_tx.sink()->ready_to_ack())
return false;
if (!_tx.sink()->packet_avail())
return false;
Genode::Packet_descriptor packet = _tx.sink()->get_packet();
if (!packet.size() || !_tx.sink()->packet_valid(packet)) {
Genode::warning("Invalid tx packet");
return true;
}
bool ret = _device.tx((addr_t)_tx.sink()->packet_content(packet), packet.size());
_tx.sink()->acknowledge_packet(packet);
return ret;
}
void _handle_packet_stream() override
{
while (_rx.source()->ack_avail())
_rx.source()->release_packet(_rx.source()->get_acked_packet());
if (_device.burst())
_send_burst();
else
while (_send());
}
public:
/**
* Constructor
*/
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,
Device &device)
:
Usb_network_session { device },
Nic::Session_component { tx_buf_size, rx_buf_size, Genode::CACHED,
rx_block_md_alloc, env }
{
_device.session(this);
}
/****************************
** Nic::Session_component **
****************************/
Nic::Mac_address mac_address() override { return _device.mac_address(); }
bool link_state() override { return _device.link_state(); }
/*************************
** Usb_network_session **
*************************/
void link_state_changed() override { _link_state_changed(); }
/**
* Send packet to client (called from driver)
*/
void rx(addr_t virt, size_t size) override
{
_handle_packet_stream();
if (!_rx.source()->ready_to_submit())
return;
try {
Packet_descriptor p =_rx.source()->alloc_packet(size);
Genode::memcpy(_rx.source()->packet_content(p), (void*)virt, size);
_rx.source()->submit_packet(p);
} catch (...) {
/* drop */
return;
}
}
};
/*
* Shortcut for single-client root component
*/
typedef Genode::Root_component<Usb_nic::Session_component, Genode::Single_client> Root_component;
/**
* Root component, handling new session requests
*/
class Root : public Root_component
{
private:
Genode::Env &_env;
Usb_nic::Device &_device;
protected:
Usb_nic::Session_component *_create_session(const char *args)
{
using namespace Genode;
using Genode::size_t;
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(Usb_nic::Session_component));
if (ram_quota < session_size)
throw Genode::Insufficient_ram_quota();
/*
* Check if donated ram quota suffices for both communication
* buffers and check for overflow
*/
if (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 %ld",
tx_buf_size + rx_buf_size + session_size);
throw Genode::Insufficient_ram_quota();
}
return new (Root::md_alloc())
Usb_nic::Session_component(tx_buf_size, rx_buf_size,
Lx::Malloc::mem(), _env,
_device);
}
public:
Root(Genode::Env &env,
Genode::Allocator &md_alloc,
Usb_nic::Device &device)
:
Root_component { &env.ep().rpc_ep(), &md_alloc },
_env { env },
_device { device }
{ }
};
namespace Genode {
class Uplink_client;
}
class Genode::Uplink_client : public Usb_network_session,
public Uplink_client_base
{
private:
sk_buff _burst_work_skb { };
sk_buff *_burst_skb { nullptr };
unsigned char *_burst_ptr { nullptr };
/************************
** Uplink_client_base **
************************/
Transmit_result
_drv_transmit_pkt(const char *conn_rx_pkt_base,
size_t conn_rx_pkt_size) override
{
if (_device.tx((addr_t)conn_rx_pkt_base, conn_rx_pkt_size) == 0) {
return Transmit_result::ACCEPTED;
}
return Transmit_result::REJECTED;
}
void _drv_transmit_pkt_burst_prepare() override
{
_burst_skb = nullptr;
_burst_ptr = nullptr;
}
Burst_result
_drv_transmit_pkt_burst_step(Packet_descriptor const &packet,
char const *packet_base,
Packet_descriptor &save) override
{
/* alloc _burst_skb */
if (!_burst_skb) {
if (!(_burst_skb = _device.alloc_skb()))
return Burst_result::BURST_FAILED;
_burst_ptr = _burst_skb->data;
_burst_work_skb.data = nullptr;
}
if (!_device.skb_fill(&_burst_work_skb, _burst_ptr, packet.size(), _burst_skb->end)) {
/* submit batch */
_device.tx_skb(_burst_skb);
_burst_skb = nullptr;
save = packet;
return Burst_result::BURST_CONTINUE;
}
/* copy packet to current data pos */
Genode::memcpy(_burst_work_skb.data, packet_base, packet.size());
/* call fixup on dummy SKB */
_device.tx_fixup(&_burst_work_skb);
/* advance to next slot */
_burst_ptr = _burst_work_skb.end;
_burst_skb->len += _burst_work_skb.truesize;
return Burst_result::BURST_SUCCEEDED;
}
void _drv_transmit_pkt_burst_finish() override
{
/* submit last _burst_skb */
if (_burst_skb)
_device.tx_skb(_burst_skb);
}
bool _drv_supports_transmit_pkt_burst() override
{
return _device.burst();
}
public:
Uplink_client(Env &env,
Allocator &alloc,
Usb_nic::Device &device)
:
Usb_network_session { device },
Uplink_client_base { env, alloc, _device.mac_address() }
{
_device.session(this);
_drv_handle_link_state(_device.link_state());
}
/*************************
** Usb_network_session **
*************************/
void link_state_changed() override
{
_drv_handle_link_state(_device.link_state());
}
void rx(Genode::addr_t virt,
Genode::size_t size) override
{
_drv_rx_handle_pkt(
size,
[&] (void *conn_tx_pkt_base,
size_t &)
{
memcpy(conn_tx_pkt_base, (void *)virt, size);
return Write_result::WRITE_SUCCEEDED;
});
}
};
#endif /* _USB_NIC_COMPONENT_H_ */

View File

@ -1,525 +0,0 @@
/*
* \brief Input service and event handler
* \author Christian Helmuth
* \author Dirk Vogt
* \author Sebastian Sumpf
* \author Christian Menard
* \author Alexander Boettcher
* \date 2009-04-20
*
* TODO make this a complete replacement for evdev.c from Linux
* TODO per-device slot handling
*
* The original implementation was in the L4Env from the TUD:OS group
* (l4/pkg/input/lib/src/l4evdev.c). This file was released under the terms of
* the GNU General Public License version 2.
*/
/*
* Copyright (C) 2009-2017 Genode Labs GmbH
* Copyright (C) 2014 Ksys Labs LLC
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* Genode includes */
#include <base/log.h>
#include <base/registry.h>
#include <util/reconstructible.h>
/* LX kit */
#include <lx_kit/env.h>
#include <lx_kit/scheduler.h>
/* local */
#include "led_state.h"
/* Linux includes */
#include <lx_emul.h>
#include <lx_emul/extern_c_begin.h>
#include <linux/hid.h>
#include <linux/input.h>
#include <linux/input/mt.h>
#include <linux/usb.h>
#include <lx_emul/extern_c_end.h>
/* Callback function to Genode subsystem */
static genode_input_event_cb handler;
static unsigned long screen_x;
static unsigned long screen_y;
/*
* We only send multi-touch events if enabled. Otherwise emulated pointer events
* are generated.
*/
static bool multi_touch;
static struct slot
{
int id; /* current tracking id */
int x; /* last reported x axis */
int y; /* last reported y axis */
int event; /* last reported ABS_MT_ event */
} slots[16];
static int slot = 0; /* store current input slot */
static bool transform(input_dev *dev, int &x, int &y)
{
if (!screen_x || !screen_y) return true;
int const min_x_dev = input_abs_get_min(dev, ABS_X);
int const min_y_dev = input_abs_get_min(dev, ABS_Y);
int const max_x_dev = input_abs_get_max(dev, ABS_X);
int const max_y_dev = input_abs_get_max(dev, ABS_Y);
int const max_y_norm = max_y_dev - min_y_dev;
int const max_x_norm = max_x_dev - min_x_dev;
if (!max_x_norm || !max_y_norm ||
x < min_x_dev || y < min_y_dev || x > max_x_dev || y > max_y_dev) {
Genode::warning("ignore input source with coordinates out of range");
return false;
}
x = screen_x * (x - min_x_dev) / (max_x_norm);
y = screen_y * (y - min_y_dev) / (max_y_norm);
return true;
}
static void handle_mt_tracking_id(input_dev *dev, int value)
{
if (value != -1) {
if (slots[slot].id != -1)
Genode::warning("old tracking id in use and got new one");
slots[slot].id = value;
return;
}
/* send end of slot usage event for clients */
int x = slots[slot].x < 0 ? 0 : slots[slot].x;
int y = slots[slot].y < 0 ? 0 : slots[slot].y;
if (!transform(dev, x, y)) return;
if (handler)
handler(EVENT_TYPE_TOUCH, slot, x, y, -1, -1);
slots[slot].event = slots[slot].x = slots[slot].y = -1;
slots[slot].id = value;
}
static void handle_mt_slot(int value)
{
if ((unsigned)value >= sizeof(slots) / sizeof(slots[0])) {
Genode::warning("drop multi-touch slot id ", value);
return;
}
slot = value;
}
enum Axis { AXIS_X, AXIS_Y };
static void handle_absolute_axis(input_dev *dev, unsigned code, int value, Axis axis)
{
slots[slot].event = code;
input_event_type type = EVENT_TYPE_MOTION;
switch (axis) {
case AXIS_X:
type = code == ABS_X ? EVENT_TYPE_MOTION : EVENT_TYPE_TOUCH;
slots[slot].x = value;
break;
case AXIS_Y:
type = code == ABS_Y ? EVENT_TYPE_MOTION : EVENT_TYPE_TOUCH;
slots[slot].y = value;
break;
}
int x = slots[slot].x;
int y = slots[slot].y;
if (x == -1 || y == -1) return;
if (!transform(dev, x, y)) return;
if (handler)
handler(type, slot, x, y, 0, 0);
}
static void handle_absolute(input_dev *dev, unsigned code, int value)
{
switch (code) {
case ABS_WHEEL:
if (handler)
handler(EVENT_TYPE_WHEEL, 0, 0, 0, 0, value);
return;
case ABS_X:
if (dev->mt && multi_touch) return;
handle_absolute_axis(dev, code, value, AXIS_X);
return;
case ABS_MT_POSITION_X:
if (!multi_touch) return;
handle_absolute_axis(dev, code, value, AXIS_X);
return;
case ABS_Y:
if (dev->mt && multi_touch) return;
handle_absolute_axis(dev, code, value, AXIS_Y);
return;
case ABS_MT_POSITION_Y:
if (!multi_touch) return;
handle_absolute_axis(dev, code, value, AXIS_Y);
return;
case ABS_MT_TRACKING_ID:
if (!multi_touch) return;
handle_mt_tracking_id(dev, value);
return;
case ABS_MT_SLOT:
if (!multi_touch) return;
handle_mt_slot(value);
return;
case ABS_MT_TOUCH_MAJOR:
case ABS_MT_TOUCH_MINOR:
case ABS_MT_ORIENTATION:
case ABS_MT_TOOL_TYPE:
case ABS_MT_BLOB_ID:
case ABS_MT_PRESSURE:
case ABS_MT_DISTANCE:
case ABS_MT_TOOL_X:
case ABS_MT_TOOL_Y:
/* ignore unused multi-touch events */
return;
default:
Genode::warning("unknown absolute event code ", code, " not handled");
return;
}
}
static void handle_relative(unsigned code, int value)
{
input_event_type type;
int x = 0, y = 0;
switch (code) {
case REL_X:
type = EVENT_TYPE_MOTION;
x = value;
break;
case REL_Y:
type = EVENT_TYPE_MOTION;
y = value;
break;
case REL_HWHEEL:
type = EVENT_TYPE_WHEEL;
x = value;
break;
case REL_WHEEL:
type = EVENT_TYPE_WHEEL;
y = value;
break;
default:
Genode::warning("unknown relative event code ", code, " not handled");
return;
}
if (handler)
handler(type, 0, 0, 0, x, y);
}
static void handle_key(input_dev *dev, unsigned code, int value)
{
/* no press/release events for multi-touch devices in multi-touch mode */
if (dev->mt && multi_touch) return;
/* map BTN_TOUCH to BTN_LEFT */
if (code == BTN_TOUCH) code = BTN_LEFT;
input_event_type type;
switch (value) {
case 0: type = EVENT_TYPE_RELEASE; break;
case 1: type = EVENT_TYPE_PRESS; break;
default:
Genode::warning("unknown key event value ", value, " not handled");
return;
}
if (handler)
handler(type, code, 0, 0, 0, 0);
}
extern "C" void genode_evdev_event(input_handle *handle, unsigned int type,
unsigned int code, int value)
{
input_dev *dev = handle->dev;
/* filter sound events */
if (test_bit(EV_SND, handle->dev->evbit)) return;
/* filter input_repeat_key() */
if ((type == EV_KEY) && (value == 2)) return;
/* filter EV_SYN and EV_MSC */
if (type == EV_SYN || type == EV_MSC) return;
switch (type) {
case EV_KEY: handle_key(dev, code, value); return;
case EV_REL: handle_relative(code, value); return;
case EV_ABS: handle_absolute(dev, code, value); return;
default:
Genode::warning("unknown event type ", type, " not handled");
return;
}
}
void genode_input_register(genode_input_event_cb h, unsigned long res_x,
unsigned long res_y, bool multitouch)
{
for (unsigned i = 0; i < sizeof(slots)/sizeof(*slots); ++i)
slots[i].id = slots[i].event = slots[i].x = slots[i].y = -1;
handler = h;
screen_x = res_x;
screen_y = res_y;
multi_touch = multitouch;
}
/***************************
** Keyboard LED handling **
***************************/
class Keyboard_led
{
private:
Genode::Registry<Keyboard_led>::Element _reg_elem;
input_dev * const _input_dev;
usb_interface *_interface() {
return container_of(_input_dev->dev.parent->parent, usb_interface, dev); }
usb_device *_usb_device() {
return interface_to_usbdev(_interface()); }
public:
Keyboard_led(Genode::Registry<Keyboard_led> &registry, input_dev *dev)
: _reg_elem(registry, *this), _input_dev(dev) { }
bool match(input_dev const *other) const { return _input_dev == other; }
void update(unsigned leds)
{
unsigned *buf = (unsigned *)kmalloc(4, GFP_LX_DMA);
*buf = leds;
usb_control_msg(_usb_device(), usb_sndctrlpipe(_usb_device(), 0),
0x9, USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0x200,
_interface()->cur_altsetting->desc.bInterfaceNumber,
buf, 1, 500);
kfree(buf);
}
};
static Genode::Registry<Keyboard_led> _registry;
namespace Usb { class Led; }
class Usb::Led
{
private:
Lx::Task _task { _run, this, "led_worker", Lx::Task::PRIORITY_2,
Lx::scheduler() };
completion _config_update;
completion _led_update;
enum Update_state { NONE, UPDATE, BLOCKED };
Update_state _update_state { NONE };
Led_state _capslock { Lx_kit::env().env(), "capslock" },
_numlock { Lx_kit::env().env(), "numlock" },
_scrlock { Lx_kit::env().env(), "scrlock" };
Genode::Signal_handler<Led> _config_handler {
Lx_kit::env().env().ep(), *this, &Led::_handle_config };
void _handle_config()
{
Lx_kit::env().config_rom().update();
Genode::Xml_node config = Lx_kit::env().config_rom().xml();
_capslock.update(config, _config_handler);
_numlock .update(config, _config_handler);
_scrlock .update(config, _config_handler);
complete(&_config_update);
Lx::scheduler().schedule();
}
static void _run(void *l)
{
Led *led = (Led *)l;
while (true) {
/* config update from EP */
wait_for_completion(&led->_config_update);
led->_update_state = UPDATE;
_registry.for_each([&] (Keyboard_led &keyboard) {
led->update(keyboard); });
/* wake up other task that waits for regestry access */
if (led->_update_state == BLOCKED)
complete(&led->_led_update);
led->_update_state = NONE;
}
}
public:
Led()
{
init_completion(&_config_update);
init_completion(&_led_update);
Genode::Signal_transmitter(_config_handler).submit();
}
void update(Keyboard_led &keyboard)
{
unsigned leds = 0;
leds |= _capslock.enabled() ? 1u << LED_CAPSL : 0;
leds |= _numlock.enabled() ? 1u << LED_NUML : 0;
leds |= _scrlock.enabled() ? 1u << LED_SCROLLL : 0;
keyboard.update(leds);
}
/*
* wait for completion of registry and led state updates
*/
void wait_for_registry()
{
/* task in _run function might receive multiple updates */
while ((_update_state == UPDATE)) {
_update_state = BLOCKED;
wait_for_completion(&_led_update);
}
}
};
static Genode::Constructible<Usb::Led> _led;
static int led_connect(struct input_handler *handler, struct input_dev *dev,
const struct input_device_id *id)
{
_led->wait_for_registry();
Keyboard_led *keyboard = new (Lx_kit::env().heap()) Keyboard_led(_registry, dev);
_led->update(*keyboard);
input_handle *handle = (input_handle *)kzalloc(sizeof(input_handle), 0);
handle->dev = input_get_device(dev);
handle->handler = handler;
input_register_handle(handle);
return 0;
}
static void led_disconnect(struct input_handle *handle)
{
input_dev *dev = handle->dev;
_led->wait_for_registry();
_registry.for_each([&] (Keyboard_led &keyboard) {
if (keyboard.match(dev))
destroy(Lx_kit::env().heap(), &keyboard);
});
input_unregister_handle(handle);
input_put_device(dev);
kfree(handle);
}
static bool led_match(struct input_handler *handler, struct input_dev *dev)
{
hid_device *hid = (hid_device *)input_get_drvdata(dev);
hid_report *report;
/* search report for keyboard entries */
list_for_each_entry(report, &hid->report_enum[0].report_list, list) {
for (unsigned i = 0; i < report->maxfield; i++)
for (unsigned j = 0; j < report->field[i]->maxusage; j++) {
hid_usage *usage = report->field[i]->usage + j;
if ((usage->hid & HID_USAGE_PAGE) == HID_UP_KEYBOARD) {
return true;
}
}
}
return false;
}
static struct input_handler led_handler;
static struct input_device_id led_ids[2];
static int led_init(void)
{
led_ids[0].driver_info = 1; /* match all */
led_ids[1] = {};
led_handler.name = "led";
led_handler.connect = led_connect;
led_handler.disconnect = led_disconnect;
led_handler.id_table = led_ids;
led_handler.match = led_match;
_led.construct();
return input_register_handler(&led_handler);
}
extern "C" { module_init(led_init); }

View File

@ -1,80 +0,0 @@
/*
* \brief Linux 2.6 Input driver for USB HID
* \author Christian Helmuth
* \author Christian Prochaska
* \author Sebastian Sumpf
* \date 2011-07-15
*/
/*
* Copyright (C) 2011-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#include <base/rpc_server.h>
#include <event_session/connection.h>
#include <os/ring_buffer.h>
#include <lx_emul.h>
#include "platform.h"
#undef RELEASE
using namespace Genode;
/**
* Singleton instance of input-session component
*/
static Genode::Constructible<Event::Connection> _event_session;
/**
* Input event call-back function
*/
static void input_callback(enum input_event_type type,
unsigned code, int ax, int ay, int rx, int ry)
{
auto submit = [&] (Input::Event const &ev) {
_event_session->with_batch([&] (Event::Session_client::Batch &batch) {
batch.submit(ev); });
};
using namespace Input;
switch (type) {
case EVENT_TYPE_PRESS: submit(Press{Keycode(code)}); break;
case EVENT_TYPE_RELEASE: submit(Release{Keycode(code)}); break;
case EVENT_TYPE_MOTION:
if (rx == 0 && ry == 0)
submit(Absolute_motion{ax, ay});
else
submit(Relative_motion{rx, ry});
break;
case EVENT_TYPE_WHEEL: submit(Wheel{rx, ry}); break;
case EVENT_TYPE_TOUCH:
{
Touch_id const id { (int)code };
if (rx == -1 && ry == -1)
submit(Touch_release{id});
else
submit(Touch{id, (float)ax, (float)ay});
break;
}
}
}
void start_input_service(void *service_ptr)
{
Services *service = static_cast<Services *>(service_ptr);
Env &env = service->env;
_event_session.construct(env);
genode_input_register(input_callback, service->screen_width,
service->screen_height, service->multitouch);
}

View File

@ -1,66 +0,0 @@
/*
* \brief Configuration of keyboard mode indicators
* \author Norman Feske
* \date 2017-10-25
*/
/*
* Copyright (C) 2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _INPUT__LED_STATE_H_
#define _INPUT__LED_STATE_H_
#include <util/xml_node.h>
#include <util/reconstructible.h>
#include <base/component.h>
namespace Usb { struct Led_state; }
struct Usb::Led_state
{
Genode::Env &_env;
typedef Genode::String<32> Name;
Name const _name;
Genode::Constructible<Genode::Attached_rom_dataspace> _rom;
bool _enabled = false;
Led_state(Genode::Env &env, Name const &name) : _env(env), _name(name) { }
void update(Genode::Xml_node config, Genode::Signal_context_capability sigh)
{
typedef Genode::String<32> Attr;
typedef Genode::String<16> Value;
Attr const attr(_name, "_led");
Value const value = config.attribute_value(attr.string(), Value());
bool const rom_configured = (value == "rom");
if (rom_configured && !_rom.constructed()) {
_rom.construct(_env, _name.string());
_rom->sigh(sigh);
}
if (!rom_configured && _rom.constructed())
_rom.destruct();
if (_rom.constructed())
_rom->update();
_enabled = _rom.constructed() ? _rom->xml().attribute_value("enabled", false)
: config.attribute_value(attr.string(), false);
}
bool enabled() const { return _enabled; }
};
#endif /* _INPUT__LED_STATE_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -1,221 +0,0 @@
/*
* \brief Startup USB driver library
* \author Sebastian Sumpf
* \date 2013-02-20
*/
/*
* Copyright (C) 2013-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#include <base/component.h>
#include <base/attached_rom_dataspace.h>
#include <base/sleep.h>
#include <nic_session/nic_session.h>
/* Local */
#include <signal.h>
#include <lx_emul.h>
#include <lx_kit/env.h>
#include <lx_kit/pci.h>
#include <lx_kit/irq.h>
#include <lx_kit/malloc.h>
#include <lx_kit/scheduler.h>
#include <lx_kit/timer.h>
#include <lx_kit/work.h>
using namespace Genode;
extern "C" int subsys_usb_init();
extern "C" void subsys_input_init();
extern "C" void module_evdev_init();
extern "C" void module_hid_init();
extern "C" void module_hid_init_core();
extern "C" void module_hid_generic_init();
extern "C" void module_usb_storage_driver_init();
extern "C" void module_wacom_driver_init();
extern "C" void module_ch_driver_init();
extern "C" void module_ms_driver_init();
extern "C" void module_mt_driver_init();
extern "C" void module_raw_driver_init();
extern "C" void module_led_init();
struct workqueue_struct *system_power_efficient_wq;
struct workqueue_struct *system_wq;
struct workqueue_struct *tasklet_wq;
void breakpoint() { Genode::log("BREAK"); }
static void run_linux(void *s)
{
Services *services = (Services *)s;
system_power_efficient_wq = alloc_workqueue("system_power_efficient_wq", 0, 0);
system_wq = alloc_workqueue("system_wq", 0, 0);
tasklet_wq = alloc_workqueue("tasklet_wq", 0, 0);
/*
* The RAW driver is initialized first to make sure that it doesn't miss
* notifications about added devices.
*/
if (services->raw)
/* low level interface */
module_raw_driver_init();
/* USB */
subsys_usb_init();
/* input + HID */
if (services->hid) {
subsys_input_init();
module_evdev_init();
module_led_init();
/* HID */
module_hid_init_core();
module_hid_init();
module_hid_generic_init();
module_ch_driver_init();
module_ms_driver_init();
module_mt_driver_init();
module_wacom_driver_init();
}
/* storage */
if (services->stor)
module_usb_storage_driver_init();
/* host controller */
platform_hcd_init(Lx_kit::env().env(), services);
while (true)
Lx::scheduler().current()->block_and_schedule();
}
void start_usb_driver(Genode::Env &env)
{
/* initialize USB env */
Lx_kit::construct_env(env);
LX_MUTEX_INIT(hid_open_mut);
LX_MUTEX_INIT(host_cmd_pool_mutex);
LX_MUTEX_INIT(input_mutex);
LX_MUTEX_INIT(usb_bus_list_lock);
LX_MUTEX_INIT(usb_port_peer_mutex);
LX_MUTEX_INIT(usbfs_mutex);
LX_MUTEX_INIT(wacom_udev_list_lock);
/* sets up backend alloc needed by malloc */
backend_alloc_init(env, env.ram(), Lx_kit::env().heap());
Lx::malloc_init(env, Lx_kit::env().heap());
static Services services(env);
if (services.hid)
start_input_service(&services);
Storage::init(env);
Nic::init(env);
if (services.raw)
Raw::init(env, services.raw_report_device_list);
Lx::Scheduler &sched = Lx::scheduler(&env);
Lx::Timer &timer = Lx::timer(&env, &env.ep(), &Lx_kit::env().heap(), &jiffies);
Lx::Irq::irq(&env.ep(), &Lx_kit::env().heap());
Lx::Work::work_queue(&Lx_kit::env().heap());
static Lx::Task linux(run_linux, &services, "linux", Lx::Task::PRIORITY_0,
Lx::scheduler());
Lx::scheduler().schedule();
}
namespace Usb_driver {
using namespace Genode;
struct Driver_starter { virtual void start_driver() = 0; };
struct Main;
}
struct Usb_driver::Main : Driver_starter
{
Env &_env;
/*
* Defer the startup of the USB driver until the first configuration
* becomes available. This is needed in scenarios where the configuration
* is dynamically generated and supplied to the USB driver via the
* report-ROM service.
*/
struct Initial_config_handler
{
Driver_starter &_driver_starter;
Attached_rom_dataspace _config;
Signal_handler<Initial_config_handler> _config_handler;
void _handle_config()
{
_config.update();
if (_config.xml().type() == "config")
_driver_starter.start_driver();
}
Initial_config_handler(Env &env, Driver_starter &driver_starter)
:
_driver_starter(driver_starter),
_config(env, "config"),
_config_handler(env.ep(), *this, &Initial_config_handler::_handle_config)
{
_config.sigh(_config_handler);
_handle_config();
}
};
void _handle_start()
{
if (_initial_config_handler.constructed()) {
_initial_config_handler.destruct();
start_usb_driver(_env);
}
}
Signal_handler<Main> _start_handler {
_env.ep(), *this, &Main::_handle_start };
Reconstructible<Initial_config_handler> _initial_config_handler { _env, *this };
/*
* Called from 'Initial_config_handler'
*/
void start_driver() override
{
Signal_transmitter(_start_handler).submit();
}
Main(Env &env) : _env(env) { }
};
void Component::construct(Genode::Env &env)
{
/* XXX execute constructors of global statics */
env.exec_static_constructors();
static Usb_driver::Main main(env);
}

View File

@ -1,763 +0,0 @@
/*
* \brief Glue code for Linux network drivers
* \author Sebastian Sumpf
* \date 2012-07-05
*/
/*
* Copyright (C) 2012-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* Genode includes */
#include <base/rpc_server.h>
#include <base/snprintf.h>
#include <nic_session/nic_session.h>
#include <util/xml_node.h>
/* Linux emulation environment includes */
#include <lx_kit/env.h>
#include <lx_kit/malloc.h>
/* NIC driver includes */
#include <drivers/nic/mode.h>
/* local includes */
#include <usb_nic_component.h>
#include "signal.h"
static Signal_helper *_signal = 0;
enum {
HEAD_ROOM = 8, /* head room in skb in bytes */
MAC_LEN = 17, /* 12 number and 6 colons */
};
/**
* Internal alloc function
*/
struct sk_buff *_alloc_skb(unsigned int size, bool tx = true);
/**
* Skb-bitmap allocator
*/
class Skb
{
private:
unsigned const _entries;
sk_buff *_buf;
unsigned *_free;
unsigned _idx;
enum { ENTRY_ELEMENT_SIZE = sizeof(unsigned) * 8 };
public:
Skb(unsigned const entries, unsigned const buffer_size)
:
_entries(entries), _idx(0)
{
unsigned const size = _entries / sizeof(unsigned);
_buf = (sk_buff *)kmalloc(sizeof(sk_buff) * _entries, GFP_KERNEL);
_free = (unsigned *)kmalloc(sizeof(unsigned) * size, GFP_KERNEL);
Genode::memset(_free, 0xff, size * sizeof(unsigned));
for (unsigned i = 0; i < _entries; i++)
_buf[i].start = (unsigned char *)kmalloc(buffer_size + NET_IP_ALIGN, GFP_NOIO);
}
sk_buff *alloc()
{
unsigned const IDX = _entries / ENTRY_ELEMENT_SIZE;
for (unsigned i = 0; i < IDX; i++) {
if (_free[_idx] != 0) {
unsigned msb = Genode::log2(_free[_idx]);
_free[_idx] ^= (1 << msb);
sk_buff *r = &_buf[(_idx * ENTRY_ELEMENT_SIZE) + msb];
r->data = r->start;
r->head = r->data;
r->phys = 0;
r->cloned = 0;
r->clone = 0;
r->len = 0;
return r;
}
_idx = (_idx + 1) % IDX;
}
return 0;
}
void free(sk_buff *buf)
{
unsigned entry = buf - &_buf[0];
if (&_buf[0] > buf || entry > _entries)
return;
_idx = entry / ENTRY_ELEMENT_SIZE;
_free[_idx] |= (1 << (entry % ENTRY_ELEMENT_SIZE));
}
};
/* send/receive skb allocators */
static Skb *skb_tx(unsigned const elements = 0, unsigned const buffer_size = 0)
{
static Skb _skb(elements, buffer_size);
return &_skb;
}
static Skb *skb_rx(unsigned const elements = 0, unsigned const buffer_size = 0)
{
static Skb _skb(elements, buffer_size);
return &_skb;
}
/**
* Prototype of fixup function
*/
extern "C" {
typedef struct sk_buff* (*fixup_t)(struct usbnet *, struct sk_buff *, gfp_t);
}
/**
* Net_device to session glue code
*/
class Nic_device : public Usb_nic::Device
{
public:
struct net_device *_ndev; /* Linux-net device */
fixup_t _tx_fixup;
bool const _burst;
bool _has_link { false };
public:
Nic_device(struct net_device *ndev)
:
_ndev(ndev),
/* XXX should be configurable instead of guessing burst mode */
_burst(((usbnet *)netdev_priv(ndev))->rx_urb_size > 2048)
{
struct usbnet *dev = (usbnet *)netdev_priv(_ndev);
/* initialize skb allocators */
unsigned urb_cnt = dev->rx_urb_size <= 2048 ? 128 : 64;
skb_rx(urb_cnt, dev->rx_urb_size);
skb_tx(urb_cnt, dev->rx_urb_size);
if (!burst()) return;
/*
* Retrieve 'tx_fixup' function from driver and set it to zero,
* so it cannot be called by the actual driver. Required for
* burst mode.
*/
_tx_fixup = dev->driver_info->tx_fixup;
dev->driver_info->tx_fixup = 0;
}
/**
* Add device
*/
static Nic_device *add(struct net_device *ndev) {
return new (Lx::Malloc::mem()) Nic_device(ndev); }
/**
* Report link state
*/
void link_state(bool link)
{
/* only report changes of the link state */
if (link == _has_link)
return;
_has_link = link;
if (_session)
_session->link_state_changed();
}
/**********************
** Device interface **
**********************/
bool link_state() override { return _has_link; }
/**
* Submit packet to driver
*/
bool tx(Genode::addr_t virt, Genode::size_t size)
{
sk_buff *skb;
if (!(skb = _alloc_skb(size + HEAD_ROOM)))
return false;
skb->len = size;
skb->data += HEAD_ROOM;
Genode::memcpy(skb->data, (void *)virt, skb->len);
tx_skb(skb);
return true;
}
/**
* Alloc an SKB
*/
sk_buff *alloc_skb()
{
struct usbnet *dev = (usbnet *)netdev_priv(_ndev);
sk_buff *skb;
if (!(skb = _alloc_skb(dev->rx_urb_size)))
return 0;
skb->len = 0;
return skb;
}
/**
* Submit SKB to the driver
*/
void tx_skb(sk_buff *skb)
{
struct usbnet *dev = (usbnet *)netdev_priv(_ndev);
unsigned long dropped = dev->net->stats.tx_dropped;
_ndev->netdev_ops->ndo_start_xmit(skb, _ndev);
if (dropped < dev->net->stats.tx_dropped)
Genode::warning("Dropped SKB");
}
/**
* Call tx_fixup function of driver
*/
void tx_fixup(struct sk_buff *skb)
{
struct usbnet *dev = (usbnet *)netdev_priv(_ndev);
if(!_tx_fixup || !_tx_fixup(dev, skb, 0))
Genode::error("Tx fixup error");
}
/**
* Fill an SKB with 'data' if 'size', return false if SKB is greater than
* 'end'
*/
bool skb_fill(struct sk_buff *skb, unsigned char *data, Genode::size_t size, unsigned char *end)
{
Genode::addr_t align = ((Genode::addr_t)(data + 3) & ~3);
skb->truesize = skb->data == 0 ? 0 : (unsigned char*)align - data;
data = skb->data == 0 ? data : (unsigned char*)align;
skb->start = data;
data += HEAD_ROOM;
skb->len = size;
skb->data = data;
skb->end = skb->tail = data + size;
skb->truesize += (skb->end - skb->start);
return skb->end >= end ? false : true;
}
/**
* Submit packet for session
*/
inline void rx(sk_buff *skb) { _session->rx((Genode::addr_t)skb->data, skb->len); }
/**
* Return mac address
*/
Nic::Mac_address mac_address()
{
Nic::Mac_address m;
Genode::memcpy(&m, _ndev->_dev_addr, ETH_ALEN);
return m;
}
bool burst() { return _burst; }
};
/* XXX support multiple devices */
static Nic_device *_nic = 0;
void Nic::init(Genode::Env &env) {
_signal = new (Lx::Malloc::mem()) Signal_helper(env); }
/***********************
** linux/netdevice.h **
***********************/
int register_netdev(struct net_device *ndev)
{
using namespace Genode;
static bool registered = false;
int err = -ENODEV;
Nic_device *nic = Nic_device::add(ndev);
if (nic == nullptr) {
class Invalid_nic_device { };
throw Invalid_nic_device { };
}
/* XXX: move to 'main' */
if (!registered) {
registered = true;
Nic_driver_mode const mode {
read_nic_driver_mode(Lx_kit::env().config_rom().xml()) };
switch (mode) {
case Genode::Nic_driver_mode::NIC_SERVER:
static ::Root root(_signal->env(), Lx::Malloc::mem(), *nic);
ndev->state |= 1 << __LINK_STATE_START;
if ((err = ndev->netdev_ops->ndo_open(ndev)))
return err;
if (ndev->netdev_ops->ndo_set_rx_mode)
ndev->netdev_ops->ndo_set_rx_mode(ndev);
_nic = nic;
_signal->parent().announce(_signal->ep().rpc_ep().manage(&root));
log("Acting as Nic server");
break;
case Genode::Nic_driver_mode::UPLINK_CLIENT:
ndev->state |= 1 << __LINK_STATE_START;
if ((err = ndev->netdev_ops->ndo_open(ndev)))
return err;
_nic = nic;
static Uplink_client uplink_client {
_signal->env(), Lx::Malloc::mem(), *nic };
log("Acting as Uplink client");
break;
}
}
return err;
}
int netif_running(const struct net_device *dev)
{
return dev->state & (1 << __LINK_STATE_START);
}
int netif_device_present(struct net_device *dev) { return 1; }
int netif_carrier_ok(const struct net_device *dev)
{
return !(dev->state & (1 << __LINK_STATE_NOCARRIER));
}
void netif_carrier_on(struct net_device *dev)
{
dev->state &= ~(1 << __LINK_STATE_NOCARRIER);
if (_nic)
_nic->link_state(true);
}
void netif_carrier_off(struct net_device *dev)
{
dev->state |= 1 << __LINK_STATE_NOCARRIER;
if (_nic)
_nic->link_state(false);
}
#ifdef GENODE_NET_STAT
#include <nic/stat.h>
static Timer::Connection _timer;
static Nic::Measurement _stat(_timer);
#endif
int netif_rx(struct sk_buff *skb)
{
if (_nic && _nic->session()) {
_nic->rx(skb);
}
#ifdef GENODE_NET_STAT
else if (_nic) {
try {
_stat.data(new (skb->data) Net::Ethernet_frame(skb->len), skb->len);
} catch(Net::Ethernet_frame::No_ethernet_frame) {
Genode::warning("No ether frame");
}
}
#endif
dev_kfree_skb(skb);
return NET_RX_SUCCESS;
}
/********************
** linux/skbuff.h **
********************/
struct sk_buff *_alloc_skb(unsigned int size, bool tx)
{
sk_buff *skb = tx ? skb_tx()->alloc() : skb_rx()->alloc();
if (!skb)
return 0;
size = (size + 3) & ~(0x3);
skb->end = skb->start + size;
skb->tail = skb->start;
skb->truesize = size;
return skb;
}
struct sk_buff *alloc_skb(unsigned int size, gfp_t priority)
{
/*
* Note: This is only called for RX skb's by the driver
*/
struct sk_buff *skb = _alloc_skb(size, false);
return skb;
}
struct sk_buff *netdev_alloc_skb_ip_align(struct net_device *dev, unsigned int length)
{
struct sk_buff *s = _alloc_skb(length + NET_IP_ALIGN, false);
if (s && dev->net_ip_align) {
s->data += NET_IP_ALIGN;
s->tail += NET_IP_ALIGN;
}
return s;
}
void dev_kfree_skb(struct sk_buff *skb)
{
lx_log(DEBUG_SKB, "free skb: %p start: %p cloned: %d",
skb, skb->start, skb->cloned);
if (skb->cloned) {
skb->start = skb->clone;
skb->cloned = false;
skb_rx()->free(skb);
return;
}
skb_tx()->free(skb);
skb_rx()->free(skb);
}
void dev_kfree_skb_any(struct sk_buff *skb) { dev_kfree_skb(skb); }
void kfree_skb(struct sk_buff *skb) { dev_kfree_skb(skb); }
/**
* Reserve 'len'
*/
void skb_reserve(struct sk_buff *skb, int len)
{
if ((skb->data + len) > skb->end) {
Genode::error("Error resevring SKB data: skb: ", skb, " data: ", skb->data,
" end: ", skb->end, "len: ", skb->len);
return;
}
skb->data += len;
lx_log(DEBUG_SKB, "skb: %p slen: %u len: %d", skb, skb->len, len);
}
/**
* Prepend 'len'
*/
unsigned char *skb_push(struct sk_buff *skb, unsigned int len)
{
if((skb->data - len) < skb->start) {
Genode::error("Error SKB head room too small: ", skb, " data: ", skb->data,
" start: ", skb->start, " len: ", len);
return 0;
}
skb->len += len;
skb->data -= len;
lx_log(DEBUG_SKB, "skb: %p slen: %u len: %u", skb, skb->len, len);
return skb->data;
}
/**
* Append 'len'
*/
unsigned char *skb_put(struct sk_buff *skb, unsigned int len)
{
if ((skb->data + len > skb->end)) {
Genode::error("Error increasing SKB length: skb: ", skb, " data: ", skb->data,
" end: ", skb->end, " len: ", len);
return 0;
}
unsigned char *old = skb_tail_pointer(skb);
skb->len += len;
skb->tail += len;
lx_log(DEBUG_SKB, "skb: %p slen: %u len: %u", skb, skb->len, len);
return old;
}
/**
* Return current head room
*/
unsigned int skb_headroom(const struct sk_buff *skb)
{
return skb->data - skb->start;
}
int skb_tailroom(const struct sk_buff *skb)
{
return skb->end - skb->tail;
}
/**
* Take 'len' from front
*/
unsigned char *skb_pull(struct sk_buff *skb, unsigned int len)
{
if (len > skb->len) {
Genode::error("Error try to pull too much: skb: ", skb, " len: ", skb->len,
" pull len: ", len);
return 0;
}
skb->len -= len;
lx_log(DEBUG_SKB, "skb: %p slen: %u len: %u", skb, skb->len, len);
return skb->data += len;
}
/**
* Set 'len' and 'tail'
*/
void skb_trim(struct sk_buff *skb, unsigned int len)
{
if (skb->len < len) {
Genode::error("Error trimming to ", len, " bytes skb: ", skb, " data: ",
skb->data, " start: ", skb->start, " len ", skb->len);
return;
}
skb->len = len;
skb_set_tail_pointer(skb, len);
lx_log(DEBUG_SKB, "skb: %p slen: %u len: %u", skb, skb->len, len);
}
/**
* Clone skb
*/
struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask)
{
sk_buff *c;
if (!(c = alloc_skb(0,0)))
return 0;
unsigned char *start = c->start;
*c = *skb;
/* save old start pointer */
c->cloned = 1;
c->clone = start;
return c;
}
int skb_header_cloned(const struct sk_buff *skb)
{
return skb->cloned;
}
void skb_set_tail_pointer(struct sk_buff *skb, const int offset)
{
skb->tail = skb->data + offset;
}
unsigned char *skb_tail_pointer(const struct sk_buff *skb)
{
return skb->tail;
}
/**
* Dummy for shared info
*/
struct skb_shared_info *skb_shinfo(struct sk_buff const * /* skb */)
{
static skb_shared_info _s = { 0 };
return &_s;
}
/**
* Init list head
*/
void skb_queue_head_init(struct sk_buff_head *list)
{
static int count_x = 0;
list->prev = list->next = (sk_buff *)list;
list->qlen = 0;
}
/**
* Add to tail of queue
*/
void __skb_queue_tail(struct sk_buff_head *list, struct sk_buff *newsk)
{
newsk->next = (sk_buff *)list;
newsk->prev = list->prev;
list->prev->next = newsk;
list->prev = newsk;
list->qlen++;
}
void skb_queue_tail(struct sk_buff_head *list, struct sk_buff *newsk) {
__skb_queue_tail(list, newsk); }
/**
* Remove skb from queue
*/
void __skb_unlink(struct sk_buff *skb, struct sk_buff_head *list)
{
if (!list->qlen)
return;
skb->prev->next = skb->next;
skb->next->prev = skb->prev;
skb->next = skb->prev = 0;
list->qlen--;
}
/**
* Remove from head of queue
*/
struct sk_buff *skb_dequeue(struct sk_buff_head *list)
{
if (list->qlen == 0)
return 0;
sk_buff *skb = list->next;
__skb_unlink(skb, list);
return skb;
}
/**********************
** linux/inerrupt.h **
**********************/
static void snprint_mac(char *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;
}
/*************************
** linux/etherdevice.h **
*************************/
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);
}
void random_ether_addr(u8 *addr)
{
using namespace Genode;
char 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 nic_config = config_node.sub_node("nic");
Xml_node::Attribute mac_node = nic_config.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 (", Genode::Cstring(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: ", Genode::Cstring(str));
#ifdef GENODE_NET_STAT
_stat.set_mac(mac.addr);
#endif
}

File diff suppressed because it is too large Load Diff

View File

@ -1,12 +0,0 @@
#ifndef _RAW_H_
#define _RAW_H_
struct usb_device;
struct usb_driver;
extern struct usb_device_driver raw_driver;
extern struct usb_driver raw_intf_driver;
int raw_notify(struct notifier_block *nb, unsigned long action, void *data);
#endif /* _RAW_H_ */

View File

@ -1,94 +0,0 @@
/*
* \brief Low level USB access driver
* \author Sebastian Sumpf
* \date 2014-11-11
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#include <linux/usb.h>
#include "raw.h"
static int raw_probe(struct usb_device *udev)
{
printk("RAW: vendor: %x product: %x dev %p\n",
udev->descriptor.idVendor, udev->descriptor.idProduct, udev);
return -ENODEV;
}
static void raw_disconnect(struct usb_device *udev)
{
printk("driver disconnect called\n");
}
struct usb_device_driver raw_driver =
{
.name = "raw",
.probe = raw_probe,
.disconnect = raw_disconnect,
.supports_autosuspend = 0,
};
static int raw_intf_probe(struct usb_interface *intf,
struct usb_device_id const *id)
{
struct usb_device *udev = interface_to_usbdev(intf);
printk("RAW_INTF: vendor: %04x product: %04x\n", udev->descriptor.idVendor,
udev->descriptor.idProduct);
return -ENODEV;
}
void raw_intf_disconnect(struct usb_interface *intf) { }
static const struct usb_device_id raw_intf_id_table[] = {
{ .driver_info = 1 }
};
struct usb_driver raw_intf_driver =
{
.name = "rawintf",
.probe = raw_intf_probe,
.disconnect = raw_intf_disconnect,
.supports_autosuspend = 0,
};
struct notifier_block usb_nb =
{
.notifier_call = raw_notify
};
static int raw_driver_init(void)
{
int err;
if ((err = usb_register_device_driver(&raw_driver, THIS_MODULE)))
return err;
printk("RAW: driver registered\n");
if ((err = usb_register(&raw_intf_driver)))
return err;
printk("RAW: interface driver registered\n");
usb_register_notify(&usb_nb);
printk("RAW: notify function registered\n");
return 0;
}
module_init(raw_driver_init);

View File

@ -1,235 +0,0 @@
/*
* \brief Linux platform_device emulation
* \author Sebastian Sumpf
* \date 2012-06-18
*/
/*
* Copyright (C) 2012-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#include <base/attached_io_mem_dataspace.h>
#include <lx_emul.h>
#include <lx_kit/malloc.h>
#include <lx_kit/env.h>
#define to_platform_driver(drv) (container_of((drv), struct platform_driver, \
driver))
static int platform_match(struct device *dev, struct device_driver *drv)
{
if (!dev->name)
return 0;
printk("MATCH %s %s\n", dev->name, drv->name);
return (strcmp(dev->name, drv->name) == 0);
}
static int platform_drv_probe(struct device *_dev)
{
struct platform_driver *drv = to_platform_driver(_dev->driver);
struct platform_device *dev = to_platform_device(_dev);
return drv->probe(dev);
}
struct bus_type platform_bus_type = {
.name = "platform",
};
int platform_driver_register(struct platform_driver *drv)
{
/* init plarform_bus_type */
platform_bus_type.match = platform_match;
platform_bus_type.probe = platform_drv_probe;
drv->driver.bus = &platform_bus_type;
if (drv->probe)
drv->driver.probe = platform_drv_probe;
printk("Register: %s\n", drv->driver.name);
return driver_register(&drv->driver);
}
struct resource *platform_get_resource(struct platform_device *dev,
unsigned int type, unsigned int num)
{
unsigned i;
for (i = 0; i < dev->num_resources; i++) {
struct resource *r = &dev->resource[i];
if ((type & r->flags) && num-- == 0)
return r;
}
return NULL;
}
struct resource *platform_get_resource_byname(struct platform_device *dev,
unsigned int type,
const char *name)
{
unsigned i;
for (i = 0; i < dev->num_resources; i++) {
struct resource *r = &dev->resource[i];
if (type == r->flags && !strcmp(r->name, name))
return r;
}
return NULL;
}
int platform_get_irq_byname(struct platform_device *dev, const char *name)
{
struct resource *r = platform_get_resource_byname(dev, IORESOURCE_IRQ, name);
return r ? r->start : -1;
}
int platform_get_irq(struct platform_device *dev, unsigned int num)
{
struct resource *r = platform_get_resource(dev, IORESOURCE_IRQ, 0);
return r ? r->start : -1;
}
int platform_device_register(struct platform_device *pdev)
{
pdev->dev.bus = &platform_bus_type;
pdev->dev.name = pdev->name;
/*Set parent to ourselfs */
if (!pdev->dev.parent)
pdev->dev.parent = &pdev->dev;
device_add(&pdev->dev);
return 0;
}
struct platform_device *platform_device_alloc(const char *name, int id)
{
platform_device *pdev = (platform_device *)kzalloc(sizeof(struct platform_device), GFP_KERNEL);
if (!pdev)
return 0;
int len = strlen(name);
pdev->name = (char *)kzalloc(len + 1, GFP_KERNEL);
if (!pdev->name) {
kfree(pdev);
return 0;
}
memcpy(pdev->name, name, len);
pdev->name[len] = 0;
pdev->id = id;
return pdev;
}
int platform_device_add_data(struct platform_device *pdev, const void *data,
size_t size)
{
void *d = NULL;
if (data && !(d = kmemdup(data, size, GFP_KERNEL)))
return -ENOMEM;
kfree(pdev->dev.platform_data);
pdev->dev.platform_data = d;
return 0;
}
int platform_device_add(struct platform_device *pdev)
{
return platform_device_register(pdev);
}
int platform_device_add_resources(struct platform_device *pdev,
const struct resource *res, unsigned int num)
{
struct resource *r = NULL;
if (res) {
r = (resource *)kmemdup(res, sizeof(struct resource) * num, GFP_KERNEL);
if (!r)
return -ENOMEM;
}
kfree(pdev->resource);
pdev->resource = r;
pdev->num_resources = num;
return 0;
}
void *platform_get_drvdata(const struct platform_device *pdev)
{
return dev_get_drvdata(&pdev->dev);
}
void platform_set_drvdata(struct platform_device *pdev, void *data)
{
dev_set_drvdata(&pdev->dev, data);
}
/**********************
** asm-generic/io.h **
**********************/
void *_ioremap(phys_addr_t phys_addr, unsigned long size, int wc)
{
try {
Genode::Attached_io_mem_dataspace *ds = new(Lx::Malloc::mem())
Genode::Attached_io_mem_dataspace(Lx_kit::env().env(), phys_addr, size, !!wc);
return ds->local_addr<void>();
} catch (...) {
panic("Failed to request I/O memory: [%lx,%lx)", phys_addr, phys_addr + size);
return 0;
}
}
void *ioremap(phys_addr_t offset, unsigned long size)
{
return _ioremap(offset, size, 0);
}
void *devm_ioremap(struct device *dev, resource_size_t offset,
unsigned long size)
{
return _ioremap(offset, size, 0);
}
void *devm_ioremap_nocache(struct device *dev, resource_size_t offset,
unsigned long size)
{
return _ioremap(offset, size, 0);
}
void *devm_ioremap_resource(struct device *dev, struct resource *res)
{
return _ioremap(res->start, res->end - res->start, 0);
}

View File

@ -1,66 +0,0 @@
/*
* \brief ARM specific implemenations used on all SOCs
* \author Sebastian Sumpf
* \date 2016-04-25
*/
/*
* Copyright (C) 2016-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#include <base/env.h>
#include <irq_session/connection.h>
#include <lx_emul/irq.h>
#include <lx_kit/backend_alloc.h>
#include <lx_kit/env.h>
#include <lx_kit/irq.h>
/****************************
** lx_kit/backend_alloc.h **
****************************/
void backend_alloc_init(Genode::Env&, Genode::Ram_allocator&,
Genode::Allocator&)
{
/* intentionally left blank */
}
Genode::Ram_dataspace_capability
Lx::backend_alloc(Genode::addr_t size, Genode::Cache cache) {
return Lx_kit::env().env().ram().alloc(size, cache); }
void Lx::backend_free(Genode::Ram_dataspace_capability cap) {
return Lx_kit::env().env().ram().free(cap); }
/***********************
** linux/interrupt.h **
***********************/
extern "C" int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
const char *name, void *dev)
{
struct Irq : Genode::List<Irq>::Element {
unsigned const nr;
Genode::Irq_connection irq_con { Lx_kit::env().env(), nr };
Irq(unsigned const irq, Genode::List<Irq> & list)
: nr(irq) { list.insert(this); }
};
static Genode::List<Irq> irq_list;
Irq * i = irq_list.first();
for (; i; i = i->next()) { if (i->nr == irq) break; }
if (!i) i = new (Lx_kit::env().heap()) Irq(irq, irq_list);
Lx::Irq::irq().request_irq(i->irq_con.cap(), irq, handler, dev);
return 0;
}

View File

@ -1,11 +0,0 @@
include $(REP_DIR)/src/drivers/usb/target.inc
SRC_CC += platform_device.cc platform_generic.cc
INC_DIR += $(LIB_INC_DIR)/spec/arm
INC_DIR += $(REP_DIR)/src/include/spec/arm
vpath platform_device.cc $(LIB_DIR)/spec/arm
vpath platform_generic.cc $(LIB_DIR)/spec/arm
# vi:set ft=make :

View File

@ -1,3 +0,0 @@
include $(REP_DIR)/src/drivers/usb/spec/arm/target.inc
INC_DIR += $(LIB_INC_DIR)/spec/arm_v6

View File

@ -1,3 +0,0 @@
include $(REP_DIR)/src/drivers/usb/spec/arm/target.inc
INC_DIR += $(LIB_INC_DIR)/spec/arm_v7

View File

@ -1,196 +0,0 @@
/*
* \brief USB initialization for Raspberry Pi
* \author Norman Feske
* \date 2013-09-11
*/
/*
* Copyright (C) 2013-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* Genode includes */
#include <io_mem_session/connection.h>
#include <util/mmio.h>
#include <platform_session/connection.h>
/* emulation */
#include <platform.h>
#include <lx_emul.h>
/* dwc-otg */
#define new new_
#include <dwc_otg_dbg.h>
#undef new
using namespace Genode;
/************************************************
** Resource info passed to the dwc_otg driver **
************************************************/
enum {
DWC_BASE = 0x20980000,
DWC_SIZE = 0x20000,
DWC_IRQ = 9,
};
/***************************************
** Supplement to lx_emul environment **
***************************************/
#if VERBOSE_LX_EMUL
#define TRACE lx_printf("\033[32m%s\033[0m called, not implemented\n", __PRETTY_FUNCTION__)
#else
#define TRACE
#endif
#define DUMMY(retval, name) \
extern "C" long name() { \
lx_printf("\033[32m%s\033[0m called, not implemented, stop\n", #name); \
bt(); \
for (;;); \
return retval; \
}
#define CHECKED_DUMMY(retval, name) \
extern "C" long name() { \
lx_printf("\033[32m%s\033[0m called, not implemented, ignored\n", #name); \
bt(); \
return retval; \
}
#define SILENT_DUMMY(retval, name) \
extern "C" long name() { return retval; }
/*********************
** linux/hardirq.h **
*********************/
int in_irq()
{
TRACE;
return 0;
}
/*******************
** linux/delay.h **
*******************/
unsigned long loops_per_jiffy = 1;
/***********************************
** Dummies for unused PCD driver **
***********************************/
/*
* The PCD driver is used for driving the DWC-OTG device as gadget. The
* Raspberry Pi solely supports the use of the controller as host device.
* Hence, the PCD parts are not needed.
*/
DUMMY(-1, dwc_otg_pcd_disconnect_us);
DUMMY(-1, dwc_otg_pcd_remote_wakeup);
DUMMY(-1, dwc_otg_pcd_get_rmwkup_enable);
DUMMY(-1, dwc_otg_pcd_initiate_srp);
DUMMY(-1, pcd_remove);
SILENT_DUMMY( 0, pcd_init);
/************************************************************************
** Prevent use of FIQ fix, need to resolve FIQ-related symbols anyway **
************************************************************************/
void local_fiq_disable() { }
void local_fiq_enable() { }
extern "C" void fiq_fsm_spin_lock(void *lock) { }
extern "C" void fiq_fsm_spin_unlock(void *lock) { }
int claim_fiq(struct fiq_handler *f) { return 0; }
void set_fiq_regs(struct pt_regs const *regs) { }
void set_fiq_handler(void *start, unsigned int length) { }
void enable_fiq() { }
void __FIQ_Branch(unsigned long *regs) { TRACE; }
extern "C" int fiq_fsm_too_late(struct fiq_state *st, int n) { TRACE; return 0; }
extern "C" void dwc_otg_fiq_nop(struct fiq_state *state) { TRACE; }
extern "C" void dwc_otg_fiq_fsm(struct fiq_state *state, int num_channels) { TRACE; }
unsigned char _dwc_otg_fiq_stub, _dwc_otg_fiq_stub_end;
/***********************
** asm/dma_mapping.h **
***********************/
void *dma_to_virt(struct device *dev, dma_addr_t phys)
{
return phys_to_virt(phys);
}
/*******************
** linux/timer.h **
*******************/
struct tvec_base { };
struct tvec_base boot_tvec_bases;
/*******************
** Init function **
*******************/
extern "C" void module_dwc_otg_driver_init();
extern "C" int module_usbnet_init();
extern "C" int module_smsc95xx_driver_init();
void platform_hcd_init(Env &env, Services *services)
{
static resource _dwc_otg_resource[] =
{
{ DWC_BASE, DWC_BASE + DWC_SIZE - 1, "dwc_otg", IORESOURCE_MEM },
{ DWC_IRQ, DWC_IRQ, "dwc_otg-irq" /* name unused */, IORESOURCE_IRQ }
};
/* enable USB power */
Platform::Connection platform(env);
platform.power_state(Platform::Session::POWER_USB_HCD, true);
/* register network */
if (services->nic) {
module_usbnet_init();
module_smsc95xx_driver_init();
}
/* disable fiq optimization */
fiq_enable = false;
fiq_fsm_enable = false;
bool const verbose = false;
if (verbose)
g_dbg_lvl = DBG_HCD | DBG_CIL | DBG_HCD_URB;
module_dwc_otg_driver_init();
/* setup host-controller platform device */
platform_device *pdev = (platform_device *)kzalloc(sizeof(platform_device), 0);
pdev->name = (char *)"dwc_otg";
pdev->id = 0;
pdev->num_resources = sizeof(_dwc_otg_resource)/sizeof(resource);
pdev->resource = _dwc_otg_resource;
/* needed for DMA buffer allocation. See 'hcd_buffer_alloc' in 'buffer.c' */
static u64 dma_mask = ~(u64)0;
pdev->dev.dma_mask = &dma_mask;
pdev->dev.coherent_dma_mask = ~0;
platform_device_register(pdev);
}

View File

@ -1 +0,0 @@
#include <spec/rpi/platform_session/client.h>

View File

@ -1 +0,0 @@
#include <spec/rpi/platform_session/platform_session.h>

View File

@ -1,49 +0,0 @@
TARGET = rpi_usb_drv
REQUIRES = arm_v6
SRC_C += \
usb/host/dwc_otg/dwc_otg/dwc_otg_adp.c \
usb/host/dwc_otg/dwc_otg/dwc_otg_attr.c \
usb/host/dwc_otg/dwc_otg/dwc_otg_cfi.c \
usb/host/dwc_otg/dwc_otg/dwc_otg_cil.c \
usb/host/dwc_otg/dwc_otg/dwc_otg_cil_intr.c \
usb/host/dwc_otg/dwc_otg/dwc_otg_driver.c \
usb/host/dwc_otg/dwc_otg/dwc_otg_hcd.c \
usb/host/dwc_otg/dwc_otg/dwc_otg_hcd_ddma.c \
usb/host/dwc_otg/dwc_otg/dwc_otg_hcd_intr.c \
usb/host/dwc_otg/dwc_otg/dwc_otg_hcd_linux.c \
usb/host/dwc_otg/dwc_otg/dwc_otg_hcd_queue.c \
usb/host/dwc_otg/dwc_common_port/dwc_cc.c \
usb/host/dwc_otg/dwc_common_port/dwc_common_linux.c \
usb/host/dwc_otg/dwc_common_port/dwc_crypto.c \
usb/host/dwc_otg/dwc_common_port/dwc_dh.c \
usb/host/dwc_otg/dwc_common_port/dwc_mem.c \
usb/host/dwc_otg/dwc_common_port/dwc_modpow.c \
usb/host/dwc_otg/dwc_common_port/dwc_notifier.c
SRC_C += net/usb/usbnet.c net/usb/smsc95xx.c
include $(REP_DIR)/src/drivers/usb/spec/arm_v6/target.inc
CC_OPT += -DDWC_LINUX -DPLATFORM_INTERFACE
# needed for 'ehci-hcd.c', which we don't use on the rpi, but it is still
# part of the generic usb USB driver
CC_OPT += -DCONFIG_USB_EHCI_PCI=1
# for 'dwc_otg_hcd_linux.c' for enabling the FIQ, which we don't use anyway
CC_OPT += -DINTERRUPT_VC_USB=9
# for 'dwc_otg_driver.c' for preventing calls to set_irq_type
CC_OPT += -DIRQF_TRIGGER_LOW=1
INC_DIR += $(LX_CONTRIB_DIR)/drivers/usb/host/dwc_otg/dwc_common_port \
$(LX_CONTRIB_DIR)/drivers/usb/host/dwc_otg/dwc_otg \
$(call select_from_repositories,include/spec/rpi)
SRC_CC += platform.cc
vpath platform.cc $(LIB_DIR)/spec/rpi
vpath %.c $(LX_CONTRIB_DIR)/drivers/net/usb
# enable C++11 support
CC_CXX_OPT += -std=gnu++11

View File

@ -1,205 +0,0 @@
/*
* \brief PCI device handling
* \author Sebastian Sumpf
* \date 2016-04-25
*/
/*
* Copyright (C) 2016-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* Genode includes */
#include <base/allocator.h>
#include <base/entrypoint.h>
#include <base/signal.h>
#include <util/misc_math.h>
#include <lx_emul.h>
#include <lx_kit/env.h>
#include <lx_kit/irq.h>
#include <lx_kit/pci_dev_registry.h>
#include <lx_kit/malloc.h>
#include <lx_kit/mapped_io_mem_range.h>
#include <lx_emul/impl/io.h>
#include <lx_emul/impl/pci_resource.h>
/**
* Quirks
*/
extern "C" void __pci_fixup_quirk_usb_early_handoff(void *data);
/**
* List of pci devices from platform driver
*/
class Pci_dev_list
{
private:
struct Element : public Lx_kit::List<Element>::Element
{
Platform::Device_capability cap;
Element(Platform::Device_capability cap) : cap(cap) { }
};
Lx_kit::List<Element> _pci_caps;
public:
Pci_dev_list()
{
/*
* Obtain first device, the operation may exceed the session quota.
* So we use the 'with_upgrade' mechanism.
*/
Platform::Device_capability cap =
Lx::pci()->with_upgrade([&] () {
return Lx::pci()->first_device(); });
/*
* Iterate over the devices of the platform session.
*/
while (cap.valid()) {
/*
* Keep PCI devices in natural bus order. Otherwise on a Lenovo
* ThinkCentre M57p, the system locks up when the UHCI
* controller BIOS handoff (disabling bit 4 in the LEGSUP
* register) for the controller with PCI BDF 00:1d:2 is
* attempted before the handoff for the controller with BDF
* 00:1a:0.
*/
_pci_caps.append(new (Lx::Malloc::mem()) Element(cap));
/* try next one. Upgrade session quota on demand.*/
Lx::pci()->with_upgrade([&] () {
cap = Lx::pci()->next_device(cap); });
}
}
template <typename FUNC>
void for_each_pci_device(FUNC const &func)
{
for (Element *e = _pci_caps.first(); e; e = e->next())
func(e->cap);
}
};
Pci_dev_list *pci_dev_list()
{
static Pci_dev_list _list;
return &_list;
}
extern "C" int pci_register_driver(struct pci_driver *driver)
{
driver->driver.name = driver->name;
pci_device_id const *id_table = driver->id_table;
if (!id_table)
return -ENODEV;
using namespace Genode;
bool found = false;
auto lambda = [&] (Platform::Device_capability cap) {
Platform::Device_client client(cap);
/* request device ID from platform driver */
unsigned const class_code = client.class_code();
/* look if we find the device ID in the driver's 'id_table' */
pci_device_id const *matching_id = nullptr;
for (pci_device_id const *id = id_table; id->device; id++) {
lx_log(DEBUG_PCI,"idclass: %x idclassm: %x devclass %x", id->class_,
id->class_mask, class_code);
/* check for drivers that support any device for a given class */
if (id->device != (unsigned)PCI_ANY_ID || !id->class_mask)
continue;
if ((id->class_ & id->class_mask) == (class_code & id->class_mask)) {
matching_id = id;
break;
}
}
/* skip device that is not handled by driver */
if (!matching_id)
return false;
/* create 'pci_dev' struct for matching device */
Lx::Pci_dev *pci_dev = new (Lx::Malloc::mem()) Lx::Pci_dev(cap);
/* enable ioremap to work */
Lx::pci_dev_registry()->insert(pci_dev);
/* register driver at the 'pci_dev' struct */
pci_dev->dev.driver = &driver->driver;
/*
* This quirk handles device handoff from BIOS, since the BIOS may still
* access the USB controller after bootup. For this the ext cap register of
* the PCI config space is checked
*/
if (Lx_kit::env().config_rom().xml().attribute_value("bios_handoff", true))
__pci_fixup_quirk_usb_early_handoff(pci_dev);
/* call probe function of the Linux driver */
if (driver->probe(pci_dev, matching_id)) {
/* if the probing failed, revert the creation of 'pci_dev' */
pci_dev_put(pci_dev);
return false;
}
found = true;
/* multiple device support continue */
return true;
};
pci_dev_list()->for_each_pci_device(lambda);
return found ? 0 : -ENODEV;
}
/***********************
** linux/interrupt.h **
***********************/
int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
const char *name, void *dev)
{
for (Lx::Pci_dev *pci_dev = Lx::pci_dev_registry()->first(); pci_dev; pci_dev = pci_dev->next())
if (pci_dev->irq == irq) {
Lx::Irq::irq().request_irq(pci_dev->client().irq(0), irq, handler, dev);
return 0;
}
return -ENODEV;
}
/*********************************
** Platform backend alloc init **
*********************************/
void backend_alloc_init(Genode::Env &env, Genode::Ram_allocator &ram,
Genode::Allocator &alloc)
{
Lx::pci_init(env, ram, alloc);
}

View File

@ -1,57 +0,0 @@
/*
* \brief X86 platform initialization
* \author Sebastian Sumpf
* \date 2013-05-17
*/
/*
* Copyright (C) 2013-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#include <platform.h>
extern "C" void module_ax88179_178a_driver_init();
extern "C" void module_cdc_driver_init();
extern "C" void module_rndis_driver_init();
extern "C" void module_usbnet_init();
extern "C" void module_ehci_hcd_init();
extern "C" void module_ehci_pci_init();
extern "C" void module_ohci_hcd_mod_init();
extern "C" void module_ohci_pci_init();
extern "C" void module_uhci_hcd_init();
extern "C" void module_xhci_hcd_init();
extern "C" void module_xhci_pci_init();
void platform_hcd_init(Genode::Env &, Services *s)
{
if (s->nic) {
module_usbnet_init();
module_ax88179_178a_driver_init();
module_cdc_driver_init();
module_rndis_driver_init();
}
if (s->xhci) {
module_xhci_hcd_init();
module_xhci_pci_init();
}
/* ehci_hcd should always be loaded before uhci_hcd and ohci_hcd, not after */
if (s->ehci) {
module_ehci_hcd_init();
module_ehci_pci_init();
}
if (s->ohci) {
module_ohci_hcd_mod_init();
module_ohci_pci_init();
}
if (s->uhci) {
module_uhci_hcd_init();
}
}

View File

@ -1,27 +0,0 @@
SRC_C += $(addprefix usb/host/,pci-quirks.c uhci-hcd.c ehci-pci.c ohci-hcd.c ohci-pci.c)
SRC_C += usb/core/hcd-pci.c
#
# USB netwpork support
#
SRC_C += $(addprefix net/usb/, usbnet.c ax88179_178a.c cdc_ether.c rndis_host.c)
# XHCI
SRC_C += usb/host/xhci-pci.c
# PCI
SRC_CC += pci_driver.cc platform.cc
# lx_kit
SRC_CC += pci.cc mapped_io_mem_range.cc
include $(REP_DIR)/src/drivers/usb/xhci.inc
include $(REP_DIR)/src/drivers/usb/target.inc
CC_OPT += -DCONFIG_PCI -DCONFIG_USB_EHCI_PCI=1 -DCONFIG_USB_XHCI_HCD=1
vpath platform.cc $(LIB_DIR)/spec/x86
vpath pci_driver.cc $(LIB_DIR)/spec/x86
# vi:set ft=make :

View File

@ -1,7 +0,0 @@
TARGET = usb_drv
REQUIRES = x86_32
INC_DIR += $(LIB_INC_DIR)/spec/x86_32 $(LIB_INC_DIR)/spec/x86
INC_DIR += $(REP_DIR)/src/include/spec/x86_32
include $(REP_DIR)/src/drivers/usb/spec/x86/target.inc

View File

@ -1,7 +0,0 @@
TARGET = usb_drv
REQUIRES = x86_64
INC_DIR += $(LIB_INC_DIR)/spec/x86_64 $(LIB_INC_DIR)/spec/x86
INC_DIR += $(REP_DIR)/src/include/spec/x86_64
include $(REP_DIR)/src/drivers/usb/spec/x86/target.inc

View File

@ -1,235 +0,0 @@
/*
* \brief SCSI support emulation
* \author Christian Helmuth
* \author Sebastian Sumpf
* \date 2009-10-29
*
* XXX NOTES XXX
*
* struct scsi_host_template
*
* struct scsi_host
*
* host_lock used by scsi_unlock, scsi_lock
* max_id used by usb_stor_report_device_reset
*
* struct scsi_cmnd
*
* functions
*
* scsi_add_host
* scsi_host_alloc
* scsi_host_get
* scsi_host_put
* scsi_remove_host
* scsi_report_bus_reset
* scsi_report_device_reset
* scsi_scan_host
*/
/*
* Copyright (C) 2009-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#include <lx_emul.h>
#include <storage/scsi.h>
#define DEBUG_SCSI 0
/***************
** SCSI host **
***************/
struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *t, int priv_size)
{
lx_log(DEBUG_SCSI, "t=%p, priv_size=%d", t, priv_size);
static int free = 1;
/* XXX we not some extra space for hostdata[] */
static char buffer[4096] __attribute__((aligned(4096)));
static struct Scsi_Host *host = (struct Scsi_Host *)buffer;
/* FIXME we support only one host for now */
if (!free) return 0;
free = 0;
host->host_lock = &host->default_lock;
spin_lock_init(host->host_lock);
host->host_no = 13;
host->max_id = 8;
host->hostt = t;
return host;
}
static struct page *_page(struct scsi_cmnd *cmnd)
{
return (struct page *)cmnd->sdb.table.sgl->page_link;
}
void scsi_alloc_buffer(size_t size, struct scsi_cmnd *cmnd)
{
scsi_setup_buffer(cmnd, size, 0, 0);
struct scatterlist *sgl = cmnd->sdb.table.sgl;
struct page *page = _page(cmnd);
page->virt = kmalloc(size, GFP_NOIO);
page->phys = dma_map_single_attrs(0, page->virt, 0, 0, 0);
sgl->dma_address = page->phys;
}
void scsi_setup_buffer(struct scsi_cmnd *cmnd, size_t size, void *virt, dma_addr_t addr)
{
cmnd->sdb.table.nents = 1;
cmnd->sdb.length = size;
struct scatterlist *sgl = cmnd->sdb.table.sgl;
struct page *page = _page(cmnd);
page->virt = virt;
page->phys = addr;
sgl->page_link = (unsigned long)page;
sgl->offset = 0;
sgl->length = size;
sgl->dma_address = addr;
sgl->last = 1;
}
void scsi_free_buffer(struct scsi_cmnd *cmnd)
{
struct page *page = _page(cmnd);
if (page)
kfree(page->virt);
}
void *scsi_buffer_data(struct scsi_cmnd *cmnd)
{
return _page(cmnd)->virt;
}
struct scsi_cmnd *_scsi_alloc_command()
{
struct scsi_cmnd *cmnd = (struct scsi_cmnd *)kmalloc(sizeof(struct scsi_cmnd), GFP_KERNEL);
cmnd->sdb.table.sgl = (struct scatterlist *)kmalloc(sizeof(struct scatterlist), GFP_KERNEL);
cmnd->cmnd = kzalloc(MAX_COMMAND_SIZE, 0);
cmnd->sdb.table.sgl->page_link = (unsigned long) kzalloc(sizeof(struct page), 0);
cmnd->sense_buffer = kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL);
return cmnd;
}
void _scsi_free_command(struct scsi_cmnd *cmnd)
{
kfree((void *)cmnd->sdb.table.sgl->page_link);
kfree(cmnd->sdb.table.sgl);
kfree(cmnd->sense_buffer);
kfree(cmnd->cmnd);
kfree(cmnd);
}
static void inquiry_done(struct scsi_cmnd *cmnd)
{
char *data = (char *)scsi_buffer_data(cmnd);
lx_printf("Vendor id: %c%c%c%c%c%c%c%c Product id: %s\n",
data[8], data[9], data[10], data[11], data[12],
data[13], data[14], data[15], &data[16]);
complete(cmnd->back);
}
static void scsi_done(struct scsi_cmnd *cmd)
{
complete(cmd->back);
}
void scsi_scan_host(struct Scsi_Host *host)
{
struct scsi_cmnd *cmnd;
struct scsi_device *sdev;
struct scsi_target *target;
struct completion compl;
void *result;
init_completion(&compl);
sdev = (struct scsi_device *)kmalloc(sizeof(struct scsi_device), GFP_KERNEL);
target = (struct scsi_target *)kmalloc(sizeof(struct scsi_target), GFP_KERNEL);
cmnd = _scsi_alloc_command();
/* init device */
sdev->sdev_target = target;
sdev->host = host;
sdev->id = 0;
sdev->lun = 0;
host->hostt->slave_alloc(sdev);
host->hostt->slave_configure(sdev);
/* inquiry (36 bytes for usb) */
scsi_alloc_buffer(sdev->inquiry_len, cmnd);
cmnd->cmnd[0] = INQUIRY;
cmnd->cmnd[4] = sdev->inquiry_len;
cmnd->device = sdev;
cmnd->cmd_len = 6;
cmnd->sc_data_direction = DMA_FROM_DEVICE;
cmnd->back = &compl;
cmnd->scsi_done = inquiry_done;
host->hostt->queuecommand(host, cmnd);
wait_for_completion(&compl);
/* if PQ and PDT are zero we have a direct access block device conntected */
result = scsi_buffer_data(cmnd);
if (!((char*)result)[0])
scsi_add_device(sdev);
else {
kfree(sdev);
kfree(target);
}
scsi_free_buffer(cmnd);
_scsi_free_command(cmnd);
}
/**********************
** scsi/scsi_cmnd.h **
**********************/
unsigned scsi_bufflen(struct scsi_cmnd *cmnd) { return cmnd->sdb.length; }
struct scatterlist *scsi_sglist(struct scsi_cmnd *cmnd) { return cmnd->sdb.table.sgl; }
unsigned scsi_sg_count(struct scsi_cmnd *cmnd) { return cmnd->sdb.table.nents; }
/********************
** scsi/scsi_eh.h **
*******************/
void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd,
struct scsi_eh_save *ses, unsigned char *cmnd,
int cmnd_size, unsigned sense_bytes)
{
ses->cmd_len = scmd->cmd_len;
}
void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd,
struct scsi_eh_save *ses)
{
scmd->cmd_len = ses->cmd_len;
}

View File

@ -1,246 +0,0 @@
/*
* \brief USB storage glue
* \author Sebastian Sumpf <sebastian.sumpf@genode-labs.com>
* \date 2012-05-06
*/
/*
* Copyright (C) 2012-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#include <base/log.h>
#include <base/rpc_server.h>
#include <block/component.h>
#include <util/endian.h>
#include <util/list.h>
#include <lx_emul.h>
#include <lx_kit/malloc.h>
#include <lx_kit/backend_alloc.h>
#include <lx_kit/scheduler.h>
#include <lx_emul/extern_c_begin.h>
#include <storage/scsi.h>
#include <drivers/usb/storage/usb.h>
#include <lx_emul/extern_c_end.h>
#include "signal.h"
static Signal_helper *_signal = 0;
class Storage_device : public Genode::List<Storage_device>::Element,
public Block::Driver
{
private:
Genode::size_t _block_size;
Block::sector_t _block_count;
struct scsi_device *_sdev;
static void _sync_done(struct scsi_cmnd *cmnd) {
complete((struct completion *)cmnd->back); }
static void _async_done(struct scsi_cmnd *cmnd);
void _capacity()
{
struct completion comp;
struct scsi_cmnd *cmnd = _scsi_alloc_command();
/* alloc data for command */
scsi_alloc_buffer(8, cmnd);
cmnd->cmnd[0] = READ_CAPACITY;
cmnd->cmd_len = 10;
cmnd->device = _sdev;
cmnd->sc_data_direction = DMA_FROM_DEVICE;
init_completion(&comp);
cmnd->back = &comp;
cmnd->scsi_done = _sync_done;
_sdev->host->hostt->queuecommand(_sdev->host, cmnd);
wait_for_completion(&comp);
Genode::uint32_t *data = (Genode::uint32_t *)scsi_buffer_data(cmnd);
_block_count = host_to_big_endian(data[0]);
_block_size = host_to_big_endian(data[1]);
/* if device returns the highest block number */
if (!_sdev->fix_capacity)
_block_count++;
if (verbose)
Genode::log("block size: ", _block_size, " block count", _block_count);
scsi_free_buffer(cmnd);
_scsi_free_command(cmnd);
}
void _io(Block::sector_t block_nr, Genode::size_t block_count,
Block::Packet_descriptor packet,
Genode::addr_t phys, bool read)
{
if (block_nr > _block_count)
throw Io_error();
if (verbose)
log("PACKET: phys: ", Genode::Hex(phys), " block: ", block_nr, "count: ", block_count,
read ? " read" : " write");
/* check if we can call queuecommand */
struct us_data *us = (struct us_data *) _sdev->host->hostdata;
if (us->srb != NULL)
throw Request_congestion();
struct scsi_cmnd *cmnd = _scsi_alloc_command();
cmnd->cmnd[0] = read ? READ_10 : WRITE_10;
cmnd->cmd_len = 10;
cmnd->device = _sdev;
cmnd->sc_data_direction = read ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
cmnd->scsi_done = _async_done;
Block::Packet_descriptor *p = new (Lx::Malloc::mem()) Block::Packet_descriptor();
*p = packet;
cmnd->packet = (void *)p;
Genode::uint32_t be_block_nr = host_to_big_endian<Genode::uint32_t>(block_nr);
memcpy(&cmnd->cmnd[2], &be_block_nr, 4);
/* transfer one block */
Genode::uint16_t be_block_count = host_to_big_endian<Genode::uint16_t>(block_count);
memcpy(&cmnd->cmnd[7], &be_block_count, 2);
/* setup command */
scsi_setup_buffer(cmnd, block_count * _block_size, (void *)0, phys);
/*
* Required by 'last_sector_hacks' in 'drivers/usb/storage/transprot.c
*/
struct request req;
req.rq_disk = 0;
cmnd->request = &req;
/* send command to host driver */
_sdev->host->hostt->queuecommand(_sdev->host, cmnd);
/* schedule next task if we come from EP */
if (Lx::scheduler().active() == false)
Lx::scheduler().schedule();
}
public:
Storage_device(Genode::Ram_allocator &ram, struct scsi_device *sdev)
: Block::Driver(ram), _sdev(sdev)
{
/* read device capacity */
_capacity();
}
Block::Session::Info info() const override
{
return { .block_size = _block_size,
.block_count = _block_count,
.align_log2 = Genode::log2(_block_size),
.writeable = true };
}
void read_dma(Block::sector_t block_number,
Genode::size_t block_count,
Genode::addr_t phys,
Block::Packet_descriptor &packet) {
_io(block_number, block_count, packet, phys, true); }
void write_dma(Block::sector_t block_number,
Genode::size_t block_count,
Genode::addr_t phys,
Block::Packet_descriptor &packet) {
_io(block_number, block_count, packet, phys, false); }
bool dma_enabled() { return true; }
Genode::Ram_dataspace_capability alloc_dma_buffer(Genode::size_t size) {
return Lx::backend_alloc(size, Genode::UNCACHED); }
void free_dma_buffer(Genode::Ram_dataspace_capability cap) {
return Lx::backend_free(cap); }
};
void Storage::init(Genode::Env &env) {
_signal = new (Lx::Malloc::mem()) Signal_helper(env); }
struct Factory : Block::Driver_factory
{
Storage_device device;
Factory(Genode::Ram_allocator &ram, struct scsi_device *sdev)
: device(ram, sdev) {}
Block::Driver *create() { return &device; }
void destroy(Block::Driver *driver) { }
};
static Storage_device *device = nullptr;
static work_struct delayed;
extern "C" void ack_packet(work_struct *work)
{
Block::Packet_descriptor *packet =
(Block::Packet_descriptor *)(work->data);
if (verbose)
Genode::log("ACK packet for block: ", packet->block_number());
device->ack_packet(*packet);
Genode::destroy(Lx::Malloc::mem(), packet);
}
void scsi_add_device(struct scsi_device *sdev)
{
using namespace Genode;
static bool announce = false;
static struct Factory factory(_signal->ram(), sdev);
device = &factory.device;
/*
* XXX move to 'main'
*/
if (!announce) {
enum { WRITEABLE = true };
PREPARE_WORK(&delayed, ack_packet);
static Block::Root root(_signal->ep(), Lx::Malloc::mem(),
_signal->rm(), factory, WRITEABLE);
_signal->parent().announce(_signal->ep().rpc_ep().manage(&root));
announce = true;
}
}
void Storage_device::_async_done(struct scsi_cmnd *cmnd)
{
/*
* Schedule packet ack, because we are called here in USB storage thread
* context, the from code that will clear the command queue later, so we
* cannot send the next packet from here
*/
delayed.data = cmnd->packet;
schedule_work(&delayed);
scsi_free_buffer(cmnd);
_scsi_free_command(cmnd);
}

View File

@ -1,100 +0,0 @@
SRC_CC += main.cc
LIBS = base nic_driver
CC_CXX_WARN_STRICT =
LIB_DIR = $(REP_DIR)/src/drivers/usb
LIB_INC_DIR = $(LIB_DIR)/include
LIBS += usb_include lx_kit_setjmp
SRC_CC += lx_emul.cc storage.cc \
input_component.cc evdev.cc nic.cc raw.cc
SRC_C += dummies.c scsi.c raw_driver.c
LX_CONTRIB_DIR := $(call select_from_ports,dde_linux)/src/lib/usb
DRIVERS_DIR := $(LX_CONTRIB_DIR)/drivers
USB_DIR := $(DRIVERS_DIR)/usb
#
# The order of include-search directories is important, we need to look into
# 'contrib' before falling back to our custom 'lx_emul.h' header.
#
INC_DIR += $(PRG_DIR)
INC_DIR += $(LIB_INC_DIR) $(REP_DIR)/src/include
INC_DIR += $(LX_CONTRIB_DIR)/include $(LX_CONTRIB_DIR)/include/uapi $(LX_CONTRIB_DIR)
CC_OPT += -U__linux__ -D__KERNEL__
CC_OPT += -DCONFIG_USB_DEVICEFS -DCONFIG_HOTPLUG -DDEBUG -DCONFIG_USB_PHY=1 \
-DCONFIG_GENERIC_PHY=0 -DCONFIG_USB_OTG_WHITELIST=0 \
-DCONFIG_USB_OTG=0 -DCONFIG_USB_NET_RNDIS_HOST=1
CC_WARN = -Wall -Wno-unused-variable -Wno-uninitialized \
-Wno-unused-function -Wno-overflow
CC_C_OPT += -std=gnu89 -Wno-unused-but-set-variable -Wno-pointer-sign -Wno-unused-label
CC_C_OPT += -include $(LIB_INC_DIR)/lx_emul.h
CC_CXX_OPT += -fpermissive
#
# Suffix of global 'module_init' function
#
MOD_SUFFIX =
CC_OPT += -DMOD_SUFFIX=$(MOD_SUFFIX)
# lx_kit
SRC_CC += printf.cc bug.cc work.cc timer.cc scheduler.cc irq.cc malloc.cc env.cc
# common lib
SRC_C += lib/ctype.c
SRC_C += lib/int_sqrt.c
# USB core
SRC_C += $(addprefix usb/core/, buffer.c config.c devices.c driver.c endpoint.c file.c \
generic.c hcd.c hub.c message.c notify.c port.c quirks.c\
urb.c usb.c)
# USB host-controller driver
SRC_C += $(addprefix usb/host/, ehci-hcd.c)
# common
SRC_C += usb/common/common.c
# USB hid
SRC_C += $(addprefix hid/usbhid/, hid-core.c hid-quirks.c)
SRC_C += $(addprefix hid/, hid-core.c hid-generic.c hid-input.c \
hid-cherry.c hid-microsoft.c hid-multitouch.c \
wacom_sys.c wacom_wac.c)
SRC_C += $(addprefix input/, evdev.c input.c input-mt.c)
# USB storage
SRC_C += $(addprefix usb/storage/,scsiglue.c protocol.c transport.c usb.c \
initializers.c option_ms.c sierra_ms.c usual-tables.c)
# SCSI
SRC_C += $(addprefix scsi/,scsi.c constants.c)
#SRC_CC = storage.cc
#SRC_C =
#
# Add suffix, since there are two hid-core.c with the same module init function
#
hid/hid-core.o: MOD_SUFFIX="_core"
vpath %.c $(DRIVERS_DIR)
vpath %.c $(LIB_DIR)
vpath %.cc $(LIB_DIR)
vpath %.cc $(LIB_DIR)/signal
vpath %.c $(LIB_DIR)/input
vpath %.cc $(LIB_DIR)/input
vpath %.cc $(LIB_DIR)/storage
vpath %.c $(LIB_DIR)/storage
vpath %.cc $(LIB_DIR)/nic
vpath %.cc $(LIB_DIR)/raw
vpath %.c $(LIB_DIR)/raw
vpath lib/int_sqrt.c $(LX_CONTRIB_DIR)
vpath lib/ctype.c $(LX_CONTRIB_DIR)
vpath %.cc $(REP_DIR)/src/lx_kit
# vi: set ft=make :

View File

@ -1,44 +0,0 @@
/*
* \brief Test functions
* \author Sebastian Sumpf
* \date 2012-08-02
*/
/*
* Copyright (C) 2012-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#if 0
void tx_test() {
char *data = (char *)skb->data;
if (data[0x2a] == (char)0xaa && data[0x2b] == (char)0xbb) {
Genode::log("Got server signal");
static char data[1066];
static char header[] = {
0x00, 0x1c, 0x25, 0x9e, 0x92, 0x4a, 0x2e, 0x60, 0x90, 0x0c, 0x4e, 0x01, 0x08, 0x00, 0x45, 0x00,
0x04, 0x1c, 0x00, 0x00, 0x40, 0x00, 0x40, 0x11, 0x22, 0x88, 0x0a, 0x00, 0x00, 0x3b, 0x0a, 0x00,
0x00, 0x0f, 0x89, 0xc5, 0x04, 0xd2, 0x04, 0x08, 0x54, 0xfd};
Genode::memset(data, 0, 1065);
memcpy(data, header, sizeof(header));
while (1) {
sk_buff *skb = alloc_skb(1066 + HEAD_ROOM, 0);
if (!skb) {
Service_handler::s()->check_signal();
continue;
}
skb->len = 1066;
skb->data += HEAD_ROOM;
memcpy(skb->data, data, 1066);
_nic->_ndev->netdev_ops->ndo_start_xmit(skb, _nic->_ndev);
dev_kfree_skb(skb);
}
}
}
#endif

View File

@ -1,6 +0,0 @@
#
# Generic XHCI files
#
SRC_C += $(addprefix usb/host/, xhci-dbg.c xhci-hub.c xhci-mem.c xhci-ring.c xhci.c)
# vi:set ft=make :

View File

@ -1,14 +1,15 @@
USB host controller driver
##########################
Allows access to USB devices via the 'Usb' session interface.
Configuration snippet:
The driver will start all USB controller types a platform offers
(USB 1.0/2.0/3.0). Controllers can be disabled as attribute in the config node
of the driver. Supported attributes are: 'uhci', 'ohci', 'ehci', and 'xhci'.
!<start name="usb_host_drv">
! <binary name="platform_specific_usb_host_drv_name"/>
! <resource name="RAM" quantum="10M"/>
! <provides><service name="Usb"/></provides>
! <config>
! <config uhci="yes" ohci="yes" ehci="yes" xhci="yes">
! <report devices="yes"/>
! </config>
!</start>
@ -28,14 +29,12 @@ USB device. Only devices that have a valid policy configured at the USB driver
can be accessed by a client. The following configuration allows 'comp1' to
access the device 'usb-1-6':
!<start name="usb_drv">
!<start name="usb_host_drv">
! <resource name="RAM" quantum="12M"/>
! <provides><service name="Usb"/></provides>
! <config uhci="yes" ohci="yes" ehci="yes" xhci="yes">
! <raw>
! <report devices="yes"/>
! <policy label="comp1 -> usb-1-6" vendor_id="0x13fe" product_id="0x5200" bus="0x0001" dev="0x0006"/>
! </raw>
! <config>
! <report devices="yes"/>
! <policy label="comp1 -> usb-1-6" vendor_id="0x13fe" product_id="0x5200" bus="0x0001" dev="0x0006"/>
! </config>
!</start>

View File

@ -68,7 +68,6 @@ timeout
timeout_smp
timer_accuracy
tz_vmm
usb_hid
usb_hid_raw
vbox5_genode_usb_hid_raw
vbox5_ubuntu_16_04_32