USB: Support usbnet and smsc95xx for omap4
This commit is contained in:
parent
b2a62b4b2d
commit
70b8fc2832
|
@ -56,13 +56,11 @@ CONTENT_INPUT := input.c evdev.c input-compat.h
|
||||||
CONTENT += $(addprefix drivers/input/,$(CONTENT_INPUT))
|
CONTENT += $(addprefix drivers/input/,$(CONTENT_INPUT))
|
||||||
CONTENT += include/linux/input/mt.h
|
CONTENT += include/linux/input/mt.h
|
||||||
|
|
||||||
|
# Panda board usb network driver
|
||||||
|
CONTENT_NET = usbnet.c smsc95xx.c smsc95xx.h
|
||||||
|
CONTENT += $(addprefix drivers/net/usb/,$(CONTENT_NET))
|
||||||
|
CONTENT += include/linux/usb/usbnet.h
|
||||||
|
|
||||||
# Panda board
|
|
||||||
#CONTENT += drivers/mfd/omap-usb-host.c
|
|
||||||
#CONTENT += arch/arm/plat-omap/include/plat/usb.h
|
|
||||||
#CONTENT_ARCH = usb-host.c mux.h mux2420.h mux2430.h mux34xx.h mux44xx.h
|
|
||||||
#CONTENT += $(addprefix arch/arm/mach-omap2/,$(CONTENT_ARCH))
|
|
||||||
#CONTRIB_CONTENT := $(addprefix $(CONTRIB_DIR)/,$(CONTENT))
|
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# Utility to check if a tool is installed
|
# Utility to check if a tool is installed
|
||||||
|
|
|
@ -22,7 +22,7 @@ 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
|
mouse interrupts. The mouse driver should work correctly on Qemu 1.0.93 and
|
||||||
above.
|
above.
|
||||||
|
|
||||||
STORAGE
|
Storage
|
||||||
~~~~~~~
|
~~~~~~~
|
||||||
|
|
||||||
Currently supports one USB storage device. Hot plugging has not been tested. A
|
Currently supports one USB storage device. Hot plugging has not been tested. A
|
||||||
|
@ -35,3 +35,31 @@ Configuration snippet:
|
||||||
! <provides> <service name="Block"/> </provides>
|
! <provides> <service name="Block"/> </provides>
|
||||||
! <config><storage /></config>
|
! <config><storage /></config>
|
||||||
!</start>
|
!</start>
|
||||||
|
|
||||||
|
|
||||||
|
Network (Nic)
|
||||||
|
~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Supported on PandaBoard only using the 'smsc95xx' driver.
|
||||||
|
|
||||||
|
Configuration snippet:
|
||||||
|
|
||||||
|
!<start name="usb_drv">
|
||||||
|
! <resource name="RAM" quantum="3M"/>
|
||||||
|
! <provides>
|
||||||
|
! <service name="Nic"/>
|
||||||
|
! <service name="Input"/>
|
||||||
|
! </provides>
|
||||||
|
! <config>
|
||||||
|
! <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.
|
||||||
|
|
17
dde_linux/patches/csum.patch
Normal file
17
dde_linux/patches/csum.patch
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
diff -r 4d66ab105ff0 drivers/net/usb/smsc95xx.c
|
||||||
|
--- a/drivers/net/usb/smsc95xx.c Fri Jul 06 17:50:36 2012 +0200
|
||||||
|
+++ b/drivers/net/usb/smsc95xx.c Fri Jul 06 17:55:13 2012 +0200
|
||||||
|
@@ -1032,7 +1032,12 @@
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
80
dde_linux/run/usb_net.run
Normal file
80
dde_linux/run/usb_net.run
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
#
|
||||||
|
# \brief Test for using the lwIP TCP/IP stack over USB
|
||||||
|
# \author Sebastian Sumpf
|
||||||
|
# \date 2012-07-06
|
||||||
|
#
|
||||||
|
# This test case executes a small HTTP server, it has been used on PandaBoard
|
||||||
|
# hardware only, though it should execute but not do anything on other hardware
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# Build
|
||||||
|
#
|
||||||
|
|
||||||
|
build {
|
||||||
|
core init
|
||||||
|
drivers/pci drivers/timer drivers/usb
|
||||||
|
test/lwip/http_srv
|
||||||
|
}
|
||||||
|
|
||||||
|
create_boot_directory
|
||||||
|
|
||||||
|
#
|
||||||
|
# Generate config
|
||||||
|
#
|
||||||
|
|
||||||
|
set config {
|
||||||
|
<config verbose="yes">
|
||||||
|
<parent-provides>
|
||||||
|
<service name="ROM"/>
|
||||||
|
<service name="RAM"/>
|
||||||
|
<service name="IRQ"/>
|
||||||
|
<service name="IO_MEM"/>
|
||||||
|
<service name="IO_PORT"/>
|
||||||
|
<service name="CAP"/>
|
||||||
|
<service name="PD"/>
|
||||||
|
<service name="RM"/>
|
||||||
|
<service name="CPU"/>
|
||||||
|
<service name="LOG"/>
|
||||||
|
<service name="SIGNAL"/>
|
||||||
|
</parent-provides>
|
||||||
|
<default-route>
|
||||||
|
<any-service> <parent/> <any-child/> </any-service>
|
||||||
|
</default-route>
|
||||||
|
<start name="timer">
|
||||||
|
<resource name="RAM" quantum="512K"/>
|
||||||
|
<provides> <service name="Timer"/> </provides>
|
||||||
|
</start>
|
||||||
|
<start name="usb_drv">
|
||||||
|
<resource name="RAM" quantum="3M"/>
|
||||||
|
<provides>
|
||||||
|
<service name="Nic"/>
|
||||||
|
<service name="Input"/>
|
||||||
|
</provides>
|
||||||
|
<config>
|
||||||
|
<nic mac="2e:60:90:0c:4e:01" />
|
||||||
|
<hid/>
|
||||||
|
</config>
|
||||||
|
</start>
|
||||||
|
<start name="test-lwip_httpsrv">
|
||||||
|
<resource name="RAM" quantum="2M"/>
|
||||||
|
</start>
|
||||||
|
</config>
|
||||||
|
}
|
||||||
|
|
||||||
|
install_config $config
|
||||||
|
|
||||||
|
#
|
||||||
|
# Boot modules
|
||||||
|
#
|
||||||
|
|
||||||
|
# generic modules
|
||||||
|
set boot_modules {
|
||||||
|
core init timer
|
||||||
|
usb_drv
|
||||||
|
ld.lib.so libc.lib.so libc_log.lib.so lwip.lib.so test-lwip_httpsrv
|
||||||
|
}
|
||||||
|
|
||||||
|
build_boot_image $boot_modules
|
||||||
|
|
||||||
|
# vi: set ft=tcl :
|
|
@ -61,7 +61,6 @@ static struct ehci_hcd_omap_platform_data _ehci_data
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
extern "C" void module_ehci_hcd_init();
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -370,9 +369,22 @@ static void omap_ehci_init()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void platform_hcd_init(void)
|
extern "C" void module_ehci_hcd_init();
|
||||||
|
extern "C" int module_usbnet_init();
|
||||||
|
extern "C" int module_smsc95xx_init();
|
||||||
|
|
||||||
|
void platform_hcd_init(Services *services)
|
||||||
{
|
{
|
||||||
|
/* register netowrk */
|
||||||
|
if (services->nic) {
|
||||||
|
module_usbnet_init();
|
||||||
|
module_smsc95xx_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* register EHCI controller */
|
||||||
module_ehci_hcd_init();
|
module_ehci_hcd_init();
|
||||||
|
|
||||||
|
/* initialize EHCI */
|
||||||
omap_ehci_init();
|
omap_ehci_init();
|
||||||
|
|
||||||
/* setup EHCI-controller platform device */
|
/* setup EHCI-controller platform device */
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <platform.h>
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
void platform_execute(void *sp, void *func, void *arg)
|
void platform_execute(void *sp, void *func, void *arg)
|
||||||
{
|
{
|
||||||
|
@ -28,9 +30,6 @@ void platform_execute(void *sp, void *func, void *arg)
|
||||||
: : "r"(sp), "r"(func), "r"(arg) : "r0");
|
: : "r"(sp), "r"(func), "r"(arg) : "r0");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void platform_hcd_init(void);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -197,7 +197,6 @@ void mdelay(unsigned long msecs) { TRACE; }
|
||||||
|
|
||||||
bool cancel_work_sync(struct work_struct *work) { TRACE; return 0; }
|
bool cancel_work_sync(struct work_struct *work) { TRACE; return 0; }
|
||||||
int cancel_delayed_work_sync(struct delayed_work *work) { TRACE; return 0; }
|
int cancel_delayed_work_sync(struct delayed_work *work) { TRACE; return 0; }
|
||||||
int schedule_work(struct work_struct *work) { TRACE; return 0; }
|
|
||||||
bool flush_work_sync(struct work_struct *work) { TRACE; return 0; }
|
bool flush_work_sync(struct work_struct *work) { TRACE; return 0; }
|
||||||
|
|
||||||
|
|
||||||
|
@ -236,6 +235,7 @@ int signal_pending(struct task_struct *p) { TRACE; return 0; }
|
||||||
void schedule(void) { TRACE; }
|
void schedule(void) { TRACE; }
|
||||||
void yield(void) { TRACE; }
|
void yield(void) { TRACE; }
|
||||||
void cpu_relax(void) { TRACE; udelay(1); }
|
void cpu_relax(void) { TRACE; udelay(1); }
|
||||||
|
signed long schedule_timeout(signed long timeout) { TRACE; return 0; }
|
||||||
|
|
||||||
struct task_struct *current;
|
struct task_struct *current;
|
||||||
|
|
||||||
|
@ -793,3 +793,90 @@ struct regulator *regulator_get(struct device *dev, const char *id) { TRACE; ret
|
||||||
|
|
||||||
int omap_usbhs_enable(struct device *dev) { TRACE; return 0; }
|
int omap_usbhs_enable(struct device *dev) { TRACE; return 0; }
|
||||||
void omap_usbhs_disable(struct device *dev) { TRACE; }
|
void omap_usbhs_disable(struct device *dev) { TRACE; }
|
||||||
|
|
||||||
|
|
||||||
|
/********************
|
||||||
|
** linux/skbuff.h **
|
||||||
|
********************/
|
||||||
|
|
||||||
|
unsigned char *__skb_put(struct sk_buff *skb, unsigned int len) { TRACE; return 0; }
|
||||||
|
int skb_checksum_start_offset(const struct sk_buff *skb) { TRACE; return 0; }
|
||||||
|
struct sk_buff *skb_copy_expand(const struct sk_buff *skb,
|
||||||
|
int newheadroom, int newtailroom,
|
||||||
|
gfp_t gfp_mask) { TRACE; return 0; }
|
||||||
|
int skb_tailroom(const struct sk_buff *skb) { TRACE; return 0; }
|
||||||
|
|
||||||
|
int skb_queue_empty(const struct sk_buff_head *list) { TRACE; return 1; }
|
||||||
|
void skb_queue_purge(struct sk_buff_head *list) { TRACE; }
|
||||||
|
|
||||||
|
void skb_tx_timestamp(struct sk_buff *skb) { TRACE; }
|
||||||
|
bool skb_defer_rx_timestamp(struct sk_buff *skb) { TRACE; return 0; }
|
||||||
|
|
||||||
|
void dev_kfree_skb_any(struct sk_buff *skb) { TRACE; }
|
||||||
|
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
** linux/ethtool.h **
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
__u32 ethtool_cmd_speed(const struct ethtool_cmd *ep) { TRACE; return 0; }
|
||||||
|
u32 ethtool_op_get_link(struct net_device *dev) { TRACE; return 0; }
|
||||||
|
|
||||||
|
|
||||||
|
/***********************
|
||||||
|
** linux/netdevice.h **
|
||||||
|
***********************/
|
||||||
|
|
||||||
|
u32 netif_msg_init(int debug_value, int default_msg_enable_bits) { TRACE; return 0; }
|
||||||
|
|
||||||
|
void netif_start_queue(struct net_device *dev) { TRACE; }
|
||||||
|
void netif_device_detach(struct net_device *dev) { TRACE; }
|
||||||
|
void netif_stop_queue(struct net_device *dev) { TRACE; }
|
||||||
|
void netif_wake_queue(struct net_device *dev) { TRACE; }
|
||||||
|
void netif_device_attach(struct net_device *dev) { TRACE; }
|
||||||
|
void unregister_netdev(struct net_device *dev) { TRACE; }
|
||||||
|
void free_netdev(struct net_device *dev) { TRACE; }
|
||||||
|
void netif_carrier_off(struct net_device *dev) { TRACE; }
|
||||||
|
|
||||||
|
int netdev_mc_empty(struct net_device *dev) { TRACE; return 1; }
|
||||||
|
|
||||||
|
/*****************
|
||||||
|
** linux/mii.h **
|
||||||
|
*****************/
|
||||||
|
|
||||||
|
unsigned int mii_check_media (struct mii_if_info *mii,
|
||||||
|
unsigned int ok_to_print,
|
||||||
|
unsigned int init_media) { TRACE; return 0; }
|
||||||
|
int mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd) { TRACE; return 0; }
|
||||||
|
int mii_link_ok (struct mii_if_info *mii) { TRACE; return 0; }
|
||||||
|
|
||||||
|
int generic_mii_ioctl(struct mii_if_info *mii_if,
|
||||||
|
struct mii_ioctl_data *mii_data, int cmd,
|
||||||
|
unsigned int *duplex_changed) { TRACE; return 0; }
|
||||||
|
struct mii_ioctl_data *if_mii(struct ifreq *rq) { TRACE; return 0; }
|
||||||
|
|
||||||
|
|
||||||
|
/*************************
|
||||||
|
** linux/etherdevice.h **
|
||||||
|
*************************/
|
||||||
|
|
||||||
|
__be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev) { TRACE; return 0; }
|
||||||
|
int eth_mac_addr(struct net_device *dev, void *p) { TRACE; return 0; }
|
||||||
|
int eth_validate_addr(struct net_device *dev) { TRACE; return 0; }
|
||||||
|
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
** linux/inerrupt.h **
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
void tasklet_kill(struct tasklet_struct *t) { TRACE; }
|
||||||
|
|
||||||
|
|
||||||
|
/********************
|
||||||
|
** asm/checksum.h **
|
||||||
|
********************/
|
||||||
|
|
||||||
|
__wsum csum_partial(const void *buff, int len, __wsum wsum) { TRACE; return 0; }
|
||||||
|
__sum16 csum_fold(__wsum sum) { TRACE; return 0; }
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -77,13 +77,15 @@ void mutex_unlock(struct mutex *m) { if (m->lock) dde_kit_lock_unlock( m->lock);
|
||||||
|
|
||||||
void *kmalloc(size_t size, gfp_t flags)
|
void *kmalloc(size_t size, gfp_t flags)
|
||||||
{
|
{
|
||||||
return dde_kit_large_malloc(size);
|
/* align at least four byte alignment */
|
||||||
|
void *addr = Genode::Dma::pool()->alloc(size, 2);
|
||||||
|
return addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void *kzalloc(size_t size, gfp_t flags)
|
void *kzalloc(size_t size, gfp_t flags)
|
||||||
{
|
{
|
||||||
void *addr = dde_kit_large_malloc(size);
|
void *addr = kmalloc(size, flags);
|
||||||
if (addr)
|
if (addr)
|
||||||
Genode::memset(addr, 0, size);
|
Genode::memset(addr, 0, size);
|
||||||
return addr;
|
return addr;
|
||||||
|
@ -100,7 +102,8 @@ void *kcalloc(size_t n, size_t size, gfp_t flags)
|
||||||
|
|
||||||
void kfree(const void *p)
|
void kfree(const void *p)
|
||||||
{
|
{
|
||||||
dde_kit_large_free((void *)p);
|
//dde_kit_large_free((void *)p);
|
||||||
|
Genode::Dma::pool()->free((void *)p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -396,6 +399,13 @@ class Driver : public Genode::List<Driver>::Element
|
||||||
*/
|
*/
|
||||||
bool match(struct device *dev)
|
bool match(struct device *dev)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* Don't try if buses don't match, since drivers often use 'container_of'
|
||||||
|
* which might cast the device to non-matching type
|
||||||
|
*/
|
||||||
|
if (_drv->bus != dev->bus)
|
||||||
|
return false;
|
||||||
|
|
||||||
bool ret = _drv->bus->match ? _drv->bus->match(dev, _drv) : true;
|
bool ret = _drv->bus->match ? _drv->bus->match(dev, _drv) : true;
|
||||||
dde_kit_log(DEBUG_DRIVER, "MATCH: %s ret: %u match: %p",
|
dde_kit_log(DEBUG_DRIVER, "MATCH: %s ret: %u match: %p",
|
||||||
_drv->name, ret, _drv->bus->match);
|
_drv->name, ret, _drv->bus->match);
|
||||||
|
@ -594,7 +604,7 @@ void dma_pool_destroy(struct dma_pool *d)
|
||||||
|
|
||||||
static void* _alloc(size_t size, int align, dma_addr_t *dma)
|
static void* _alloc(size_t size, int align, dma_addr_t *dma)
|
||||||
{
|
{
|
||||||
void *addr = Genode::Dma::pool()->alloc(size, align);
|
void *addr = Genode::Dma::pool()->alloc(size, align < 2 ? 2 : align);
|
||||||
|
|
||||||
if (!addr)
|
if (!addr)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -609,8 +619,6 @@ static void* _alloc(size_t size, int align, dma_addr_t *dma)
|
||||||
void *dma_pool_alloc(struct dma_pool *d, gfp_t f, dma_addr_t *dma)
|
void *dma_pool_alloc(struct dma_pool *d, gfp_t f, dma_addr_t *dma)
|
||||||
{
|
{
|
||||||
return _alloc(d->size, d->align, dma);
|
return _alloc(d->size, d->align, dma);
|
||||||
// return _alloc(0x1000, 12, dma);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -646,7 +654,7 @@ dma_addr_t dma_map_single_attrs(struct device *dev, void *ptr,
|
||||||
enum dma_data_direction dir,
|
enum dma_data_direction dir,
|
||||||
struct dma_attrs *attrs)
|
struct dma_attrs *attrs)
|
||||||
{
|
{
|
||||||
dma_addr_t phys = (dma_addr_t)dde_kit_pgtab_get_physaddr(ptr);
|
dma_addr_t phys = (dma_addr_t)Genode::Dma::pool()->phys_addr(ptr);
|
||||||
dde_kit_log(DEBUG_DMA, "virt: %p phys: %lx", ptr, phys);
|
dde_kit_log(DEBUG_DMA, "virt: %p phys: %lx", ptr, phys);
|
||||||
return phys;
|
return phys;
|
||||||
}
|
}
|
||||||
|
@ -666,17 +674,6 @@ int dma_map_sg_attrs(struct device *dev, struct scatterlist *sg,
|
||||||
struct dma_attrs *attrs) { return nents; }
|
struct dma_attrs *attrs) { return nents; }
|
||||||
|
|
||||||
|
|
||||||
/***********************
|
|
||||||
** linux/workquque.h **
|
|
||||||
***********************/
|
|
||||||
|
|
||||||
int schedule_delayed_work(struct delayed_work *work, unsigned long delay)
|
|
||||||
{
|
|
||||||
work->work.func(&(work)->work);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*********************
|
/*********************
|
||||||
** linux/kthread.h **
|
** linux/kthread.h **
|
||||||
*********************/
|
*********************/
|
||||||
|
@ -743,3 +740,115 @@ resource_size_t resource_size(const struct resource *res)
|
||||||
{
|
{
|
||||||
return res->end - res->start + 1;
|
return res->end - res->start + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/****************
|
||||||
|
** Networking **
|
||||||
|
****************/
|
||||||
|
|
||||||
|
|
||||||
|
/*************************
|
||||||
|
** linux/etherdevice.h **
|
||||||
|
*************************/
|
||||||
|
|
||||||
|
struct net_device *alloc_etherdev(int sizeof_priv)
|
||||||
|
{
|
||||||
|
net_device *dev = (net_device *)kzalloc(sizeof(net_device), 0);
|
||||||
|
|
||||||
|
dev->mtu = 1500;
|
||||||
|
dev->hard_header_len = 0;
|
||||||
|
dev->priv = kzalloc(sizeof_priv, 0);
|
||||||
|
dev->dev_addr = dev->_dev_addr;
|
||||||
|
memset(dev->_dev_addr, 0, sizeof(dev->_dev_addr));
|
||||||
|
|
||||||
|
return dev;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int is_valid_ether_addr(const u8 *addr)
|
||||||
|
{
|
||||||
|
/* is multicast */
|
||||||
|
if (!(addr[0] & 0x1))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* zero */
|
||||||
|
if (!(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5]))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*****************
|
||||||
|
** linux/mii.h **
|
||||||
|
*****************/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restart NWay (autonegotiation) for this interface
|
||||||
|
*/
|
||||||
|
int mii_nway_restart (struct mii_if_info *mii)
|
||||||
|
{
|
||||||
|
int bmcr;
|
||||||
|
int r = -EINVAL;
|
||||||
|
enum {
|
||||||
|
BMCR_ANENABLE = 0x1000, /* enable auto negotiation */
|
||||||
|
BMCR_ANRESTART = 0x200, /* auto negotation restart */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* if autoneg is off, it's an error */
|
||||||
|
bmcr = mii->mdio_read(mii->dev, mii->phy_id, MII_BMCR);
|
||||||
|
|
||||||
|
if (bmcr & BMCR_ANENABLE) {
|
||||||
|
printk("Reanable\n");
|
||||||
|
bmcr |= BMCR_ANRESTART;
|
||||||
|
mii->mdio_write(mii->dev, mii->phy_id, MII_BMCR, bmcr);
|
||||||
|
r = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd)
|
||||||
|
{
|
||||||
|
ecmd->duplex = DUPLEX_FULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
u8 mii_resolve_flowctrl_fdx(u16 lcladv, u16 rmtadv)
|
||||||
|
{
|
||||||
|
u8 cap = 0;
|
||||||
|
|
||||||
|
if (lcladv & rmtadv & ADVERTISE_PAUSE_CAP) {
|
||||||
|
cap = FLOW_CTRL_TX | FLOW_CTRL_RX;
|
||||||
|
} else if (lcladv & rmtadv & ADVERTISE_PAUSE_ASYM) {
|
||||||
|
if (lcladv & ADVERTISE_PAUSE_CAP)
|
||||||
|
cap = FLOW_CTRL_RX;
|
||||||
|
else if (rmtadv & ADVERTISE_PAUSE_CAP)
|
||||||
|
cap = FLOW_CTRL_TX;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cap;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************
|
||||||
|
** linux/netdevice.h **
|
||||||
|
***********************/
|
||||||
|
|
||||||
|
void *netdev_priv(const struct net_device *dev)
|
||||||
|
{
|
||||||
|
return dev->priv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
** linux/inerrupt.h **
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
void tasklet_schedule(struct tasklet_struct *t)
|
||||||
|
{
|
||||||
|
t->func(t->data);
|
||||||
|
}
|
||||||
|
|
|
@ -39,10 +39,11 @@ extern "C" {
|
||||||
#if VERBOSE_LX_EMUL
|
#if VERBOSE_LX_EMUL
|
||||||
#define DEBUG_COMPLETION 0
|
#define DEBUG_COMPLETION 0
|
||||||
#define DEBUG_DMA 0
|
#define DEBUG_DMA 0
|
||||||
#define DEBUG_DRIVER 0
|
#define DEBUG_DRIVER 1
|
||||||
#define DEBUG_IRQ 0
|
#define DEBUG_IRQ 0
|
||||||
#define DEBUG_KREF 0
|
#define DEBUG_KREF 0
|
||||||
#define DEBUG_PCI 0
|
#define DEBUG_PCI 0
|
||||||
|
#define DEBUG_SKB 0
|
||||||
#define DEBUG_SLAB 0
|
#define DEBUG_SLAB 0
|
||||||
#define DEBUG_TIMER 0
|
#define DEBUG_TIMER 0
|
||||||
#define DEBUG_THREAD 0
|
#define DEBUG_THREAD 0
|
||||||
|
@ -52,8 +53,9 @@ extern "C" {
|
||||||
#define DEBUG_DMA 0
|
#define DEBUG_DMA 0
|
||||||
#define DEBUG_IRQ 0
|
#define DEBUG_IRQ 0
|
||||||
#define DEBUG_KREF 0
|
#define DEBUG_KREF 0
|
||||||
#define DEBUG_SLAB 0
|
|
||||||
#define DEBUG_PCI 0
|
#define DEBUG_PCI 0
|
||||||
|
#define DEBUG_SKB 0
|
||||||
|
#define DEBUG_SLAB 0
|
||||||
#define DEBUG_TIMER 0
|
#define DEBUG_TIMER 0
|
||||||
#define DEBUG_THREAD 0
|
#define DEBUG_THREAD 0
|
||||||
#endif
|
#endif
|
||||||
|
@ -136,6 +138,7 @@ typedef dde_kit_int64_t int64_t;
|
||||||
typedef dde_kit_uint64_t uint64_t;
|
typedef dde_kit_uint64_t uint64_t;
|
||||||
|
|
||||||
typedef uint32_t uint;
|
typedef uint32_t uint;
|
||||||
|
typedef unsigned long ulong;
|
||||||
|
|
||||||
typedef int8_t s8;
|
typedef int8_t s8;
|
||||||
typedef uint8_t u8;
|
typedef uint8_t u8;
|
||||||
|
@ -162,6 +165,9 @@ typedef __u16 __be16;
|
||||||
typedef __u32 __be32;
|
typedef __u32 __be32;
|
||||||
typedef __u64 __be64;
|
typedef __u64 __be64;
|
||||||
|
|
||||||
|
typedef __u16 __sum16;
|
||||||
|
typedef __u32 __wsum;
|
||||||
|
|
||||||
typedef u64 sector_t;
|
typedef u64 sector_t;
|
||||||
|
|
||||||
struct list_head {
|
struct list_head {
|
||||||
|
@ -229,6 +235,7 @@ typedef unsigned short mode_t;
|
||||||
#define rmb() mb()
|
#define rmb() mb()
|
||||||
#define wmb() asm volatile ("": : :"memory")
|
#define wmb() asm volatile ("": : :"memory")
|
||||||
#define smp_wmb() wmb()
|
#define smp_wmb() wmb()
|
||||||
|
#define smp_mb() mb()
|
||||||
|
|
||||||
static inline void barrier() { mb(); }
|
static inline void barrier() { mb(); }
|
||||||
|
|
||||||
|
@ -417,6 +424,8 @@ enum {
|
||||||
ETIME = 46,
|
ETIME = 46,
|
||||||
EALREADY = 47,
|
EALREADY = 47,
|
||||||
EOPNOTSUPP = 48,
|
EOPNOTSUPP = 48,
|
||||||
|
EDOM = 49,
|
||||||
|
ENOLINK = 50,
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline bool IS_ERR(void *ptr) {
|
static inline bool IS_ERR(void *ptr) {
|
||||||
|
@ -505,6 +514,8 @@ static inline size_t min(size_t a, size_t b) {
|
||||||
|
|
||||||
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
|
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
|
||||||
|
|
||||||
|
#define BUILD_BUG_ON(condition)
|
||||||
|
|
||||||
void might_sleep();
|
void might_sleep();
|
||||||
|
|
||||||
#define INT_MAX ((int)(~0U>>1))
|
#define INT_MAX ((int)(~0U>>1))
|
||||||
|
@ -627,6 +638,7 @@ void *memscan(void *addr, int c, size_t size);
|
||||||
char *strcat(char *dest, const char *src);
|
char *strcat(char *dest, const char *src);
|
||||||
int strcmp(const char *s1, const char *s2);
|
int strcmp(const char *s1, const char *s2);
|
||||||
int strncmp(const char *cs, const char *ct, size_t count);
|
int strncmp(const char *cs, const char *ct, size_t count);
|
||||||
|
char *strcpy(char *to, const char *from);
|
||||||
char *strncpy(char *, const char *, size_t);
|
char *strncpy(char *, const char *, size_t);
|
||||||
char *strchr(const char *, int);
|
char *strchr(const char *, int);
|
||||||
char *strrchr(const char *,int);
|
char *strrchr(const char *,int);
|
||||||
|
@ -931,6 +943,8 @@ typedef struct wait_queue { int dummy; } wait_queue_t;
|
||||||
#define DECLARE_WAIT_QUEUE_HEAD(name) \
|
#define DECLARE_WAIT_QUEUE_HEAD(name) \
|
||||||
wait_queue_head_t name = __WAIT_QUEUE_HEAD_INITIALIZER(name)
|
wait_queue_head_t name = __WAIT_QUEUE_HEAD_INITIALIZER(name)
|
||||||
|
|
||||||
|
#define DECLARE_WAIT_QUEUE_HEAD_ONSTACK(name) DECLARE_WAIT_QUEUE_HEAD(name)
|
||||||
|
|
||||||
void __wake_up();
|
void __wake_up();
|
||||||
void add_wait_queue(wait_queue_head_t *q, wait_queue_t *wait);
|
void add_wait_queue(wait_queue_head_t *q, wait_queue_t *wait);
|
||||||
void remove_wait_queue(wait_queue_head_t *q, wait_queue_t *wait);
|
void remove_wait_queue(wait_queue_head_t *q, wait_queue_t *wait);
|
||||||
|
@ -1005,7 +1019,7 @@ void do_gettimeofday(struct timeval *tv);
|
||||||
** linux/sched.h **
|
** linux/sched.h **
|
||||||
*******************/
|
*******************/
|
||||||
|
|
||||||
enum { TASK_RUNNING = 0, TASK_INTERRUPTIBLE = 1, TASK_NORMAL = 3 };
|
enum { TASK_RUNNING = 0, TASK_INTERRUPTIBLE = 1, TASK_UNINTERRUPTIBLE = 2, TASK_NORMAL = 3 };
|
||||||
|
|
||||||
enum { MAX_SCHEDULE_TIMEOUT = (~0U >> 1) };
|
enum { MAX_SCHEDULE_TIMEOUT = (~0U >> 1) };
|
||||||
|
|
||||||
|
@ -1027,6 +1041,7 @@ void __set_current_state(int state);
|
||||||
#define set_current_state(state) __set_current_state(state)
|
#define set_current_state(state) __set_current_state(state)
|
||||||
int signal_pending(struct task_struct *p);
|
int signal_pending(struct task_struct *p);
|
||||||
void schedule(void);
|
void schedule(void);
|
||||||
|
signed long schedule_timeout(signed long);
|
||||||
signed long schedule_timeout_uninterruptible(signed long timeout);
|
signed long schedule_timeout_uninterruptible(signed long timeout);
|
||||||
void yield(void);
|
void yield(void);
|
||||||
int wake_up_process(struct task_struct *tsk);
|
int wake_up_process(struct task_struct *tsk);
|
||||||
|
@ -1200,6 +1215,7 @@ typedef struct pm_message { int event; } pm_message_t;
|
||||||
|
|
||||||
struct dev_pm_info { bool is_prepared; };
|
struct dev_pm_info { bool is_prepared; };
|
||||||
|
|
||||||
|
#define PMSG_IS_AUTO(msg) 0
|
||||||
|
|
||||||
/************************
|
/************************
|
||||||
** linux/pm_runtime.h **
|
** linux/pm_runtime.h **
|
||||||
|
@ -2595,6 +2611,396 @@ struct scsi_driver
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/************************
|
||||||
|
** Networking support **
|
||||||
|
************************/
|
||||||
|
|
||||||
|
|
||||||
|
/********************
|
||||||
|
** linux/skbuff.h **
|
||||||
|
********************/
|
||||||
|
|
||||||
|
enum {
|
||||||
|
NET_IP_ALIGN = 2,
|
||||||
|
CHECKSUM_COMPLETE = 2,
|
||||||
|
CHECKSUM_PARTIAL = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct skb_shared_info
|
||||||
|
{
|
||||||
|
unsigned short nr_frags;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sk_buff
|
||||||
|
{
|
||||||
|
struct sk_buff *next;
|
||||||
|
struct sk_buff *prev;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is the control buffer. It is free to use for every
|
||||||
|
* layer. Please put your private variables there. If you
|
||||||
|
* want to keep them across layers you have to do a skb_clone()
|
||||||
|
* first. This is owned by whoever has the skb queued ATM.
|
||||||
|
*/
|
||||||
|
char cb[48] __attribute__((aligned(8)));
|
||||||
|
|
||||||
|
unsigned int len;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
__wsum csum;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
u16 csum_start;
|
||||||
|
u16 csum_offset;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
u8 local_df:1,
|
||||||
|
cloned:1,
|
||||||
|
ip_summed:2,
|
||||||
|
nohdr:1,
|
||||||
|
nfctinfo:3;
|
||||||
|
__be16 protocol;
|
||||||
|
unsigned char *start;
|
||||||
|
unsigned char *end;
|
||||||
|
unsigned char *data;
|
||||||
|
unsigned char *tail;
|
||||||
|
unsigned int truesize;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sk_buff_head
|
||||||
|
{
|
||||||
|
struct sk_buff *next;
|
||||||
|
struct sk_buff *prev;
|
||||||
|
u32 qlen;
|
||||||
|
spinlock_t lock;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#define skb_queue_walk_safe(queue, skb, tmp) \
|
||||||
|
for (skb = (queue)->next, tmp = skb->next; \
|
||||||
|
skb != (struct sk_buff *)(queue); \
|
||||||
|
skb = tmp, tmp = skb->next)
|
||||||
|
|
||||||
|
struct skb_shared_info *skb_shinfo(struct sk_buff *);
|
||||||
|
|
||||||
|
struct sk_buff *alloc_skb(unsigned int, gfp_t);
|
||||||
|
unsigned char *skb_push(struct sk_buff *, unsigned int);
|
||||||
|
unsigned char *skb_pull(struct sk_buff *, unsigned int);
|
||||||
|
unsigned char *skb_put(struct sk_buff *, unsigned int);
|
||||||
|
unsigned char *__skb_put(struct sk_buff *, unsigned int);
|
||||||
|
void skb_trim(struct sk_buff *, unsigned int);
|
||||||
|
unsigned int skb_headroom(const struct sk_buff *);
|
||||||
|
int skb_checksum_start_offset(const struct sk_buff *);
|
||||||
|
struct sk_buff *skb_copy_expand(const struct sk_buff *, int, int, gfp_t);
|
||||||
|
unsigned char *skb_tail_pointer(const struct sk_buff *);
|
||||||
|
int skb_tailroom(const struct sk_buff *);
|
||||||
|
void skb_set_tail_pointer(struct sk_buff *, const int);
|
||||||
|
struct sk_buff *skb_clone(struct sk_buff *, gfp_t);
|
||||||
|
void skb_reserve(struct sk_buff *, int);
|
||||||
|
|
||||||
|
struct sk_buff *skb_dequeue(struct sk_buff_head *);
|
||||||
|
void skb_queue_head_init(struct sk_buff_head *);
|
||||||
|
void skb_queue_tail(struct sk_buff_head *, struct sk_buff *);
|
||||||
|
void __skb_queue_tail(struct sk_buff_head *, struct sk_buff *);
|
||||||
|
int skb_queue_empty(const struct sk_buff_head *);
|
||||||
|
void skb_queue_purge(struct sk_buff_head *);
|
||||||
|
void __skb_unlink(struct sk_buff *, struct sk_buff_head *);
|
||||||
|
|
||||||
|
void skb_tx_timestamp(struct sk_buff *);
|
||||||
|
bool skb_defer_rx_timestamp(struct sk_buff *);
|
||||||
|
|
||||||
|
void dev_kfree_skb(struct sk_buff *);
|
||||||
|
void dev_kfree_skb_any(struct sk_buff *);
|
||||||
|
|
||||||
|
|
||||||
|
/****************
|
||||||
|
** linux/if.h **
|
||||||
|
****************/
|
||||||
|
|
||||||
|
enum {
|
||||||
|
IFF_PROMISC = 0x100, /* receive all packets */
|
||||||
|
IFF_ALLMULTI = 0x200, /* receive all multicast packets */
|
||||||
|
IFF_MULTICAST = 0x1000, /* supports multicast */
|
||||||
|
IFNAMSIZ = 16,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ifreq { };
|
||||||
|
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
** linux/if_ether.h **
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
enum {
|
||||||
|
ETH_ALEN = 6, /* octets in one ethernet addr */
|
||||||
|
ETH_P_8021Q = 0x8100, /* 802.1Q VLAN Extended Header */
|
||||||
|
|
||||||
|
ETH_FRAME_LEN = 1514,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
** linux/ethtool.h **
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
enum {
|
||||||
|
DUPLEX_FULL = 0x1,
|
||||||
|
ETHTOOL_GSET = 0x1,
|
||||||
|
ETHTOOL_FWVERS_LEN = 32,
|
||||||
|
ETHTOOL_BUSINFO_LEN = 32,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct ethtool_cmd
|
||||||
|
{
|
||||||
|
u32 cmd;
|
||||||
|
u8 duplex;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ethtool_eeprom
|
||||||
|
{
|
||||||
|
u32 magic;
|
||||||
|
u32 offset;
|
||||||
|
u32 len;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ethtool_drvinfo
|
||||||
|
{
|
||||||
|
char driver[32]; /* driver short name, "tulip", "eepro100" */
|
||||||
|
char version[32]; /* driver version string */
|
||||||
|
char fw_version[ETHTOOL_FWVERS_LEN]; /* firmware version string */
|
||||||
|
char bus_info[ETHTOOL_BUSINFO_LEN]; /* Bus info for this IF. */
|
||||||
|
/* For PCI devices, use pci_name(pci_dev). */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ethhdr { };
|
||||||
|
|
||||||
|
struct net_device;
|
||||||
|
|
||||||
|
struct ethtool_ops
|
||||||
|
{
|
||||||
|
int (*get_settings)(struct net_device *, struct ethtool_cmd *);
|
||||||
|
int (*set_settings)(struct net_device *, struct ethtool_cmd *);
|
||||||
|
void (*get_drvinfo)(struct net_device *, struct ethtool_drvinfo *);
|
||||||
|
int (*nway_reset)(struct net_device *);
|
||||||
|
u32 (*get_link)(struct net_device *);
|
||||||
|
int (*get_eeprom_len)(struct net_device *);
|
||||||
|
int (*get_eeprom)(struct net_device *, struct ethtool_eeprom *, u8 *);
|
||||||
|
int (*set_eeprom)(struct net_device *, struct ethtool_eeprom *, u8 *);
|
||||||
|
u32 (*get_msglevel)(struct net_device *);
|
||||||
|
void (*set_msglevel)(struct net_device *, u32);
|
||||||
|
};
|
||||||
|
|
||||||
|
__u32 ethtool_cmd_speed(const struct ethtool_cmd *ep);
|
||||||
|
u32 ethtool_op_get_link(struct net_device *);
|
||||||
|
|
||||||
|
|
||||||
|
/***********************
|
||||||
|
** linux/netdevice.h **
|
||||||
|
***********************/
|
||||||
|
|
||||||
|
#define netif_err(priv, type, dev, fmt, args...) dde_kit_printf("netif_err: " fmt, ## args);
|
||||||
|
#define netif_info(priv, type, dev, fmt, args...) dde_kit_printf("netif_info: " fmt, ## args);
|
||||||
|
|
||||||
|
#define netdev_err(dev, fmt, args...) dde_kit_printf("nedev_err: " fmt, ##args)
|
||||||
|
#define netdev_warn(dev, fmt, args...) dde_kit_printf("nedev_warn: " fmt, ##args)
|
||||||
|
#define netdev_info(dev, fmt, args...) dde_kit_printf("nedev_info: " fmt, ##args)
|
||||||
|
|
||||||
|
#define netdev_for_each_mc_addr(a, b) if (0)
|
||||||
|
|
||||||
|
#if VERBOSE_LX_EMUL
|
||||||
|
#define netif_dbg(priv, type, dev, fmt, args...) dde_kit_printf("netif_dbg: " fmt, ## args)
|
||||||
|
#define netdev_dbg(dev, fmt, args...) dde_kit_printf("nedev_dbg: " fmt, ##args)
|
||||||
|
#else
|
||||||
|
#define netif_dbg(priv, type, dev, fmt, args...)
|
||||||
|
#define netdev_dbg(dev, fmt, args...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SET_NETDEV_DEV(net, pdev) ((net)->dev.parent = (pdev))
|
||||||
|
#define SET_NETDEV_DEVTYPE(net, devtype) ((net)->dev.type = (devtype))
|
||||||
|
|
||||||
|
enum netdev_tx { NETDEV_TX_OK = 0 };
|
||||||
|
typedef enum netdev_tx netdev_tx_t;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
MAX_ADDR_LEN = 32,
|
||||||
|
|
||||||
|
NETIF_F_HW_CSUM = 8,
|
||||||
|
NETIF_F_RXCSUM = (1 << 29),
|
||||||
|
|
||||||
|
NET_RX_SUCCESS = 0,
|
||||||
|
|
||||||
|
NETIF_MSG_DRV = 0x1,
|
||||||
|
NETIF_MSG_PROBE = 0x2,
|
||||||
|
NETIF_MSG_LINK = 0x4,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct net_device_ops
|
||||||
|
{
|
||||||
|
int (*ndo_open)(struct net_device *dev);
|
||||||
|
int (*ndo_stop)(struct net_device *dev);
|
||||||
|
netdev_tx_t (*ndo_start_xmit) (struct sk_buff *skb, struct net_device *dev);
|
||||||
|
void (*ndo_set_rx_mode)(struct net_device *dev);
|
||||||
|
int (*ndo_set_mac_address)(struct net_device *dev, void *addr);
|
||||||
|
int (*ndo_validate_addr)(struct net_device *dev);
|
||||||
|
int (*ndo_do_ioctl)(struct net_device *dev, struct ifreq *ifr, int cmd);
|
||||||
|
void (*ndo_tx_timeout) (struct net_device *dev);
|
||||||
|
int (*ndo_change_mtu)(struct net_device *dev, int new_mtu);
|
||||||
|
int (*ndo_set_features)(struct net_device *dev, u32 features);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct net_device_stats
|
||||||
|
{
|
||||||
|
unsigned long rx_packets;
|
||||||
|
unsigned long tx_packets;
|
||||||
|
unsigned long rx_bytes;
|
||||||
|
unsigned long tx_bytes;
|
||||||
|
unsigned long rx_errors;
|
||||||
|
unsigned long tx_errors;
|
||||||
|
unsigned long rx_dropped;
|
||||||
|
unsigned long tx_dropped;
|
||||||
|
unsigned long rx_length_errors;
|
||||||
|
unsigned long rx_over_errors;
|
||||||
|
unsigned long rx_crc_errors;
|
||||||
|
unsigned long rx_frame_errors;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* NET_DEVICE */
|
||||||
|
struct net_device
|
||||||
|
{
|
||||||
|
char name[IFNAMSIZ];
|
||||||
|
u32 features;
|
||||||
|
u32 hw_features;
|
||||||
|
|
||||||
|
struct net_device_stats stats;
|
||||||
|
const struct net_device_ops *netdev_ops;
|
||||||
|
const struct ethtool_ops *ethtool_ops;
|
||||||
|
|
||||||
|
unsigned long state;
|
||||||
|
|
||||||
|
unsigned int flags;
|
||||||
|
unsigned short hard_header_len; /* hardware hdr length */
|
||||||
|
unsigned int mtu;
|
||||||
|
unsigned char *dev_addr;
|
||||||
|
unsigned char _dev_addr[ETH_ALEN];
|
||||||
|
unsigned long trans_start; /* Time (in jiffies) of last Tx */
|
||||||
|
int watchdog_timeo; /* used by dev_watchdog() */
|
||||||
|
struct device dev;
|
||||||
|
void *priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct netdev_hw_addr
|
||||||
|
{
|
||||||
|
unsigned char addr[MAX_ADDR_LEN];
|
||||||
|
};
|
||||||
|
|
||||||
|
#define netif_msg_tx_err(p) ({ printk("netif_msg_tx_err called not implemented\n"); 0; })
|
||||||
|
#define netif_msg_rx_err(p) ({ printk("netif_msg_rx_err called not implemented\n"); 0; })
|
||||||
|
#define netif_msg_tx_queued(p) ({ printk("netif_msg_tx_queued called not implemented\n"); 0; })
|
||||||
|
|
||||||
|
u32 netif_msg_init(int, int);
|
||||||
|
|
||||||
|
void *netdev_priv(const struct net_device *);
|
||||||
|
int netif_running(const struct net_device *);
|
||||||
|
int netif_device_present(struct net_device *);
|
||||||
|
void netif_device_detach(struct net_device *);
|
||||||
|
void netif_start_queue(struct net_device *);
|
||||||
|
void netif_stop_queue(struct net_device *);
|
||||||
|
void netif_wake_queue(struct net_device *);
|
||||||
|
void netif_device_attach(struct net_device *);
|
||||||
|
void unregister_netdev(struct net_device *);
|
||||||
|
void free_netdev(struct net_device *);
|
||||||
|
int netif_rx(struct sk_buff *);
|
||||||
|
void netif_carrier_off(struct net_device *);
|
||||||
|
|
||||||
|
int netdev_mc_empty(struct net_device *);
|
||||||
|
int register_netdev(struct net_device *);
|
||||||
|
|
||||||
|
/*****************
|
||||||
|
** linux/mii.h **
|
||||||
|
*****************/
|
||||||
|
|
||||||
|
enum {
|
||||||
|
FLOW_CTRL_TX = 0x1,
|
||||||
|
FLOW_CTRL_RX = 0x2,
|
||||||
|
|
||||||
|
MII_BMCR = 0x0,
|
||||||
|
MII_ADVERTISE = 0x4,
|
||||||
|
MII_LPA = 0x5,
|
||||||
|
|
||||||
|
BMCR_RESET = 0x8000, /* reset to default state */
|
||||||
|
|
||||||
|
ADVERTISE_PAUSE_CAP = 0x0400, /* try for pause */
|
||||||
|
ADVERTISE_CSMA = 0x0001, /* only selector supported */
|
||||||
|
ADVERTISE_PAUSE_ASYM = 0x0800, /* try for asymetric pause */
|
||||||
|
ADVERTISE_10HALF = 0x0020,
|
||||||
|
ADVERTISE_10FULL = 0x0040,
|
||||||
|
ADVERTISE_100HALF = 0x0080,
|
||||||
|
ADVERTISE_100FULL = 0x0100,
|
||||||
|
ADVERTISE_ALL = ADVERTISE_10HALF | ADVERTISE_10FULL |
|
||||||
|
ADVERTISE_100HALF | ADVERTISE_100FULL
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mii_if_info
|
||||||
|
{
|
||||||
|
int phy_id;
|
||||||
|
int phy_id_mask;
|
||||||
|
int reg_num_mask;
|
||||||
|
struct net_device *dev;
|
||||||
|
int (*mdio_read) (struct net_device *dev, int phy_id, int location);
|
||||||
|
void (*mdio_write) (struct net_device *dev, int phy_id, int location, int val);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
unsigned int mii_check_media (struct mii_if_info *, unsigned int,
|
||||||
|
unsigned int);
|
||||||
|
int mii_ethtool_gset(struct mii_if_info *, struct ethtool_cmd *);
|
||||||
|
int mii_ethtool_sset(struct mii_if_info *, struct ethtool_cmd *);
|
||||||
|
u8 mii_resolve_flowctrl_fdx(u16, u16);
|
||||||
|
int mii_nway_restart (struct mii_if_info *);
|
||||||
|
int mii_link_ok (struct mii_if_info *);
|
||||||
|
|
||||||
|
struct mii_ioctl_data { };
|
||||||
|
int generic_mii_ioctl(struct mii_if_info *,
|
||||||
|
struct mii_ioctl_data *, int,
|
||||||
|
unsigned int *);
|
||||||
|
struct mii_ioctl_data *if_mii(struct ifreq *);
|
||||||
|
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
** linux/inerrupt.h **
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
struct tasklet_struct
|
||||||
|
{
|
||||||
|
void (*func)(unsigned long);
|
||||||
|
unsigned long data;
|
||||||
|
};
|
||||||
|
|
||||||
|
void tasklet_schedule(struct tasklet_struct *);
|
||||||
|
void tasklet_kill(struct tasklet_struct *);
|
||||||
|
|
||||||
|
/*************************
|
||||||
|
** linux/etherdevice.h **
|
||||||
|
*************************/
|
||||||
|
|
||||||
|
int eth_mac_addr(struct net_device *, void *);
|
||||||
|
int eth_validate_addr(struct net_device *);
|
||||||
|
__be16 eth_type_trans(struct sk_buff *, struct net_device *);
|
||||||
|
int is_valid_ether_addr(const u8 *);
|
||||||
|
|
||||||
|
void random_ether_addr(u8 *addr);
|
||||||
|
|
||||||
|
struct net_device *alloc_etherdev(int);
|
||||||
|
|
||||||
|
/********************
|
||||||
|
** asm/checksum.h **
|
||||||
|
********************/
|
||||||
|
|
||||||
|
__wsum csum_partial(const void *, int, __wsum);
|
||||||
|
__sum16 csum_fold(__wsum);
|
||||||
|
|
||||||
/**********************************
|
/**********************************
|
||||||
** Platform specific defintions **
|
** Platform specific defintions **
|
||||||
*********************************/
|
*********************************/
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include <os/config.h>
|
#include <os/config.h>
|
||||||
#include <util/xml_node.h>
|
#include <util/xml_node.h>
|
||||||
|
|
||||||
|
#include <nic_session/nic_session.h>
|
||||||
/* Local */
|
/* Local */
|
||||||
#include "storage/component.h"
|
#include "storage/component.h"
|
||||||
#include "routine.h"
|
#include "routine.h"
|
||||||
|
@ -50,7 +51,7 @@ bool Routine::_all = false;
|
||||||
void breakpoint() { PDBG("BREAK"); }
|
void breakpoint() { PDBG("BREAK"); }
|
||||||
|
|
||||||
|
|
||||||
static void init(bool hid, bool stor)
|
static void init(Services *services)
|
||||||
{
|
{
|
||||||
/* start jiffies */
|
/* start jiffies */
|
||||||
dde_kit_timer_init(0, 0);
|
dde_kit_timer_init(0, 0);
|
||||||
|
@ -59,7 +60,7 @@ static void init(bool hid, bool stor)
|
||||||
subsys_usb_init();
|
subsys_usb_init();
|
||||||
|
|
||||||
/* input + HID */
|
/* input + HID */
|
||||||
if (hid) {
|
if (services->hid) {
|
||||||
subsys_input_init();
|
subsys_input_init();
|
||||||
module_evdev_init();
|
module_evdev_init();
|
||||||
|
|
||||||
|
@ -73,10 +74,10 @@ static void init(bool hid, bool stor)
|
||||||
* Host controller.
|
* Host controller.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
platform_hcd_init();
|
platform_hcd_init(services);
|
||||||
|
|
||||||
/* storage */
|
/* storage */
|
||||||
if (stor)
|
if (services->stor)
|
||||||
module_usb_stor_init();
|
module_usb_stor_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,13 +92,12 @@ int main(int, char **)
|
||||||
static Rpc_entrypoint ep_hid(&cap, STACK_SIZE, "usb_hid_ep");
|
static Rpc_entrypoint ep_hid(&cap, STACK_SIZE, "usb_hid_ep");
|
||||||
static Signal_receiver recv;
|
static Signal_receiver recv;
|
||||||
|
|
||||||
bool hid = false;
|
Services services;
|
||||||
bool stor = false;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
config()->xml_node().sub_node("hid");
|
config()->xml_node().sub_node("hid");
|
||||||
start_input_service(&ep_hid);
|
start_input_service(&ep_hid);
|
||||||
hid = true;
|
services.hid = true;
|
||||||
} catch (Config::Invalid) {
|
} catch (Config::Invalid) {
|
||||||
PDBG("No <config> node found - not starting any USB services");
|
PDBG("No <config> node found - not starting any USB services");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -107,20 +107,28 @@ int main(int, char **)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
config()->xml_node().sub_node("storage");
|
config()->xml_node().sub_node("storage");
|
||||||
stor = true;
|
services.stor = true;
|
||||||
} catch (Xml_node::Nonexistent_sub_node) {
|
} catch (Xml_node::Nonexistent_sub_node) {
|
||||||
PDBG("No <storage> config node found - not starting the USB Storage (Block) service");
|
PDBG("No <storage> config node found - not starting the USB Storage (Block) service");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
config()->xml_node().sub_node("nic");
|
||||||
|
services.nic = true;
|
||||||
|
} catch (Xml_node::Nonexistent_sub_node) {
|
||||||
|
PDBG("No <nic> config node found - not starting the USB Nic (Network) service");
|
||||||
|
}
|
||||||
|
|
||||||
Timer::init(&recv);
|
Timer::init(&recv);
|
||||||
Irq::init(&recv);
|
Irq::init(&recv);
|
||||||
Event::init(&recv);
|
Event::init(&recv);
|
||||||
Service_handler::s()->receiver(&recv);
|
Service_handler::s()->receiver(&recv);
|
||||||
Storage::init(&recv);
|
Storage::init(&recv);
|
||||||
|
Nic::init(&recv);
|
||||||
|
|
||||||
Routine::add(0, 0, "Main", true);
|
Routine::add(0, 0, "Main", true);
|
||||||
Routine::current_use_first();
|
Routine::current_use_first();
|
||||||
init(hid, stor);
|
init(&services);
|
||||||
|
|
||||||
Routine::remove();
|
Routine::remove();
|
||||||
|
|
||||||
|
|
136
dde_linux/src/drivers/usb/nic/component.h
Normal file
136
dde_linux/src/drivers/usb/nic/component.h
Normal file
|
@ -0,0 +1,136 @@
|
||||||
|
/*
|
||||||
|
* \brief Block-session implementation for network devices
|
||||||
|
* \author Sebastian Sumpf
|
||||||
|
* \date 2012-07-05
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2012 Genode Labs GmbH
|
||||||
|
*
|
||||||
|
* This file is part of the Genode OS framework, which is distributed
|
||||||
|
* under the terms of the GNU General Public License version 2.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _NIC__COMPONENT_H_
|
||||||
|
#define _NIC__COMPONENT_H_
|
||||||
|
|
||||||
|
#include <root/component.h>
|
||||||
|
#include <nic_session/rpc_object.h>
|
||||||
|
|
||||||
|
#include <signal/dispatch.h>
|
||||||
|
|
||||||
|
namespace Nic {
|
||||||
|
|
||||||
|
using namespace Genode;
|
||||||
|
|
||||||
|
|
||||||
|
class Session_component;
|
||||||
|
|
||||||
|
struct Device : ::Device
|
||||||
|
{
|
||||||
|
Session_component *_session;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transmit data to driver
|
||||||
|
*/
|
||||||
|
virtual void tx(addr_t virt, size_t size) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return mac address of device
|
||||||
|
*/
|
||||||
|
virtual Mac_address mac_address() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set session belonging to this driver
|
||||||
|
*/
|
||||||
|
void session(Session_component *s) { _session = s; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class Session_component : public Genode::Allocator_avl,
|
||||||
|
public Packet_session_component<Session_rpc_object>
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
Device *_device; /* device this session is using */
|
||||||
|
Tx::Sink *_tx_sink; /* client packet sink */
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
void _process_packets()
|
||||||
|
{
|
||||||
|
/* submit received packets to lower layer */
|
||||||
|
while (_tx_sink->packet_avail())
|
||||||
|
{
|
||||||
|
Packet_descriptor packet = _tx_sink->get_packet();
|
||||||
|
addr_t virt = (addr_t)_tx_sink->packet_content(packet);
|
||||||
|
/* send to driver */
|
||||||
|
_device->tx(virt, packet.size());
|
||||||
|
|
||||||
|
if (!_tx_sink->ready_to_ack())
|
||||||
|
PWRN("Wait for TX packet ack");
|
||||||
|
|
||||||
|
/* acknowledge to client */
|
||||||
|
_tx_sink->acknowledge_packet(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* release acknowledged packets */
|
||||||
|
while (_rx.source()->ack_avail())
|
||||||
|
{
|
||||||
|
|
||||||
|
Packet_descriptor packet = _rx.source()->get_acked_packet();
|
||||||
|
|
||||||
|
/* free packet buffer */
|
||||||
|
_rx.source()->release_packet(packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
Session_component(Dataspace_capability tx_ds,
|
||||||
|
Dataspace_capability rx_ds,
|
||||||
|
Rpc_entrypoint &ep,
|
||||||
|
Signal_receiver *sig_rec,
|
||||||
|
::Device *device)
|
||||||
|
:
|
||||||
|
Genode::Allocator_avl(Genode::env()->heap()),
|
||||||
|
Packet_session_component(tx_ds, rx_ds, this, ep, sig_rec),
|
||||||
|
_device(static_cast<Device *>(device)),
|
||||||
|
_tx_sink(Session_rpc_object::_tx.sink()) { _device->session(this); }
|
||||||
|
|
||||||
|
Mac_address mac_address() { return _device->mac_address(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send packet to client (called form driver)
|
||||||
|
*/
|
||||||
|
void rx(addr_t virt, size_t size)
|
||||||
|
{
|
||||||
|
Packet_descriptor p =_rx.source()->alloc_packet(size);
|
||||||
|
memcpy(_rx.source()->packet_content(p), (void*)virt, size);
|
||||||
|
_rx.source()->submit_packet(p);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Shortcut for single-client root component
|
||||||
|
*/
|
||||||
|
typedef Root_component<Session_component, Single_client> Root_component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Root component, handling new session requests
|
||||||
|
*/
|
||||||
|
class Root : public Packet_root<Root_component, Session_component>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
Root(Rpc_entrypoint *session_ep, Allocator *md_alloc,
|
||||||
|
Signal_receiver *sig_rec, Device *device)
|
||||||
|
:
|
||||||
|
Packet_root(session_ep, md_alloc, sig_rec, device) { }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _NIC__COMPONENT_H_ */
|
441
dde_linux/src/drivers/usb/nic/nic.cc
Normal file
441
dde_linux/src/drivers/usb/nic/nic.cc
Normal file
|
@ -0,0 +1,441 @@
|
||||||
|
/*
|
||||||
|
* \brief Glue code for Linux network drivers
|
||||||
|
* \author Sebastian Sumpf
|
||||||
|
* \date 2012-07-05
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2012 Genode Labs GmbH
|
||||||
|
*
|
||||||
|
* This file is part of the Genode OS framework, which is distributed
|
||||||
|
* under the terms of the GNU General Public License version 2.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <base/rpc_server.h>
|
||||||
|
#include <base/snprintf.h>
|
||||||
|
#include <nic_session/nic_session.h>
|
||||||
|
#include <cap_session/connection.h>
|
||||||
|
#include <os/config.h>
|
||||||
|
#include <util/xml_node.h>
|
||||||
|
|
||||||
|
#include <lx_emul.h>
|
||||||
|
#include <dma.h>
|
||||||
|
|
||||||
|
#include <nic/component.h>
|
||||||
|
#include "signal.h"
|
||||||
|
|
||||||
|
static Signal_helper *_signal = 0;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
START = 0x1, /* device flag */
|
||||||
|
HEAD_ROOM = 32, /* head room in skb in bytes */
|
||||||
|
MAC_LEN = 17, /* 12 number and 6 colons */
|
||||||
|
};
|
||||||
|
|
||||||
|
class Nic_device : public Nic::Device
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
struct net_device *_ndev; /* Linux-net device */
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Nic_device(struct net_device *ndev) : _ndev(ndev) { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add device
|
||||||
|
*/
|
||||||
|
static Nic_device *add(struct net_device *ndev) {
|
||||||
|
return new (Genode::env()->heap()) Nic_device(ndev); }
|
||||||
|
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
** Device interface **
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Submit packet to driver
|
||||||
|
*/
|
||||||
|
void tx(Genode::addr_t virt, Genode::size_t size)
|
||||||
|
{
|
||||||
|
sk_buff *skb = alloc_skb(size + HEAD_ROOM, 0);
|
||||||
|
skb->len = size;
|
||||||
|
skb->data += HEAD_ROOM;
|
||||||
|
|
||||||
|
Genode::memcpy(skb->data, (void *)virt, skb->len);
|
||||||
|
|
||||||
|
_ndev->netdev_ops->ndo_start_xmit(skb, _ndev);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Submit packet for session
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* XXX support multiple devices */
|
||||||
|
static Nic_device *_nic = 0;
|
||||||
|
|
||||||
|
void Nic::init(Genode::Signal_receiver *recv) {
|
||||||
|
_signal = new (Genode::env()->heap()) Signal_helper(recv); }
|
||||||
|
|
||||||
|
|
||||||
|
/***********************
|
||||||
|
** linux/netdevice.h **
|
||||||
|
***********************/
|
||||||
|
|
||||||
|
int register_netdev(struct net_device *ndev)
|
||||||
|
{
|
||||||
|
using namespace Genode;
|
||||||
|
static bool announce = false;
|
||||||
|
|
||||||
|
Nic_device *nic = Nic_device::add(ndev);
|
||||||
|
|
||||||
|
/* XXX: move to 'main' */
|
||||||
|
if (!announce) {
|
||||||
|
static Cap_connection cap_nic;
|
||||||
|
static Rpc_entrypoint ep_nic(&cap_nic, 4096, "usb_nic_ep");
|
||||||
|
static Nic::Root root(&ep_nic, env()->heap(), _signal->receiver(), nic);
|
||||||
|
|
||||||
|
announce = true;
|
||||||
|
|
||||||
|
ndev->state |= START;
|
||||||
|
int err = ndev->netdev_ops->ndo_open(ndev);
|
||||||
|
_nic = nic;
|
||||||
|
env()->parent()->announce(ep_nic.manage(&root));
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int netif_running(const struct net_device *dev) { return dev->state & START; }
|
||||||
|
int netif_device_present(struct net_device *dev) { return 1; }
|
||||||
|
|
||||||
|
|
||||||
|
int netif_rx(struct sk_buff *skb)
|
||||||
|
{
|
||||||
|
if (_nic)
|
||||||
|
_nic->rx(skb);
|
||||||
|
dev_kfree_skb(skb);
|
||||||
|
return NET_RX_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/********************
|
||||||
|
** linux/skbuff.h **
|
||||||
|
********************/
|
||||||
|
|
||||||
|
struct sk_buff *alloc_skb(unsigned int size, gfp_t priority)
|
||||||
|
{
|
||||||
|
sk_buff *skb = new (Genode::env()->heap()) sk_buff;
|
||||||
|
Genode::memset(skb, 0, sizeof(sk_buff));
|
||||||
|
|
||||||
|
size = (size + 3) & ~(0x3);
|
||||||
|
|
||||||
|
skb->start = skb->data = size ? (unsigned char*)kzalloc(size, 0) : 0;
|
||||||
|
skb->tail = skb->end = skb->start + size;
|
||||||
|
skb->truesize = size;
|
||||||
|
|
||||||
|
dde_kit_log(DEBUG_SKB, "alloc sbk: %p start: %p size: %u", skb, skb->start, size);
|
||||||
|
return skb;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void dev_kfree_skb(struct sk_buff *skb)
|
||||||
|
{
|
||||||
|
dde_kit_log(DEBUG_SKB, "free skb: %p start: %p cloned: %d",
|
||||||
|
skb, skb->start, skb->cloned);
|
||||||
|
|
||||||
|
if (!skb->cloned)
|
||||||
|
kfree(skb->start);
|
||||||
|
|
||||||
|
destroy(Genode::env()->heap(), skb);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reserve 'len'
|
||||||
|
*/
|
||||||
|
void skb_reserve(struct sk_buff *skb, int len)
|
||||||
|
{
|
||||||
|
if ((skb->data + len) > skb->end) {
|
||||||
|
PERR("Error resevring SKB data: skb: %p data: %p end: %p len: %d",
|
||||||
|
skb, skb->data, skb->end, skb->len);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
skb->data += len;
|
||||||
|
dde_kit_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) {
|
||||||
|
PERR("Error SKB head room too small: %p data: %p start: %p len: %u",
|
||||||
|
skb, skb->data, skb->start, len);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
skb->len += len;
|
||||||
|
skb->data -= len;
|
||||||
|
|
||||||
|
dde_kit_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)) {
|
||||||
|
PERR("Error increasing SKB length: skb: %p data: %p end: %p len: %u",
|
||||||
|
skb, skb->data, skb->end, len);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char *old = skb_tail_pointer(skb);
|
||||||
|
skb->len += len;
|
||||||
|
skb->tail += len;
|
||||||
|
dde_kit_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Take 'len' from front
|
||||||
|
*/
|
||||||
|
unsigned char *skb_pull(struct sk_buff *skb, unsigned int len)
|
||||||
|
{
|
||||||
|
if (len > skb->len) {
|
||||||
|
PERR("Error try to pull too much: skb: %p len: %u pull len: %u",
|
||||||
|
skb, skb->len, len);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
skb->len -= len;
|
||||||
|
dde_kit_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) {
|
||||||
|
PERR("Error trimming skb: %p data: %p start: %p len %u ret: %p",
|
||||||
|
skb, skb->data, skb->start, len, __builtin_return_address((0)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
skb->len = len;
|
||||||
|
skb_set_tail_pointer(skb, len);
|
||||||
|
|
||||||
|
dde_kit_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 = alloc_skb(0, 0);
|
||||||
|
Genode::memcpy(c, skb, sizeof(sk_buff));
|
||||||
|
c->cloned = 1;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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 * /* skb */)
|
||||||
|
{
|
||||||
|
static skb_shared_info _s = { 0 };
|
||||||
|
return &_s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Init list head
|
||||||
|
*/
|
||||||
|
void skb_queue_head_init(struct sk_buff_head *list)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
sk_buff *l = (sk_buff *)list;
|
||||||
|
while (l->next != l) {
|
||||||
|
l = l->next;
|
||||||
|
|
||||||
|
if (l == skb) {
|
||||||
|
l->prev->next = l->next;
|
||||||
|
l->next->prev = l->prev;
|
||||||
|
list->qlen--;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PERR("SKB not found in __skb_unlink");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove from head of queue
|
||||||
|
*/
|
||||||
|
struct sk_buff *skb_dequeue(struct sk_buff_head *list)
|
||||||
|
{
|
||||||
|
if (list->next == (sk_buff *)list)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
sk_buff *skb = list->next;
|
||||||
|
list->next = skb->next;
|
||||||
|
list->next->prev = (sk_buff *)list;
|
||||||
|
list->qlen--;
|
||||||
|
|
||||||
|
return skb;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**********************
|
||||||
|
** linux/inerrupt.h **
|
||||||
|
**********************/
|
||||||
|
|
||||||
|
namespace Genode {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert ASCII string to mac address
|
||||||
|
*/
|
||||||
|
template <>
|
||||||
|
inline size_t ascii_to<Nic::Mac_address>(char const *s, Nic::Mac_address* mac, unsigned)
|
||||||
|
{
|
||||||
|
enum {
|
||||||
|
HEX = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
if(strlen(s) < MAC_LEN)
|
||||||
|
throw -1;
|
||||||
|
|
||||||
|
char mac_str[6];
|
||||||
|
for (int i = 0; i < ETH_ALEN; i++) {
|
||||||
|
int hi = i * 3;
|
||||||
|
int lo = hi + 1;
|
||||||
|
|
||||||
|
if (!is_digit(s[hi], HEX) || !is_digit(s[lo], HEX))
|
||||||
|
throw -1;
|
||||||
|
|
||||||
|
mac_str[i] = (digit(s[hi], HEX) << 4) | digit(s[lo], HEX);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(mac->addr, mac_str, ETH_ALEN);
|
||||||
|
|
||||||
|
return MAC_LEN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void snprint_mac(char *buf, char *mac)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < ETH_ALEN; i++)
|
||||||
|
{
|
||||||
|
Genode::snprintf(&buf[i * 3], 3, "%02x", mac[i]);
|
||||||
|
if ((i * 3) < MAC_LEN)
|
||||||
|
buf[(i * 3) + 2] = ':';
|
||||||
|
}
|
||||||
|
|
||||||
|
buf[MAC_LEN] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void random_ether_addr(u8 *addr)
|
||||||
|
{
|
||||||
|
using namespace Genode;
|
||||||
|
char str[MAC_LEN + 1];
|
||||||
|
char fallback[] = { 0x2e, 0x60, 0x90, 0x0c, 0x4e, 0x01 };
|
||||||
|
Nic::Mac_address mac;
|
||||||
|
|
||||||
|
/* try using configured mac */
|
||||||
|
try {
|
||||||
|
Xml_node nic_config = config()->xml_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);
|
||||||
|
PWRN("No mac address or wrong format attribute in <nic> - using fallback (%s)",
|
||||||
|
str);
|
||||||
|
|
||||||
|
Genode::memcpy(addr, fallback, ETH_ALEN);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* use configured mac*/
|
||||||
|
Genode::memcpy(addr, mac.addr, ETH_ALEN);
|
||||||
|
snprint_mac(str, mac.addr);
|
||||||
|
PINF("Using configured mac: %s", str);
|
||||||
|
}
|
30
dde_linux/src/drivers/usb/platform.h
Normal file
30
dde_linux/src/drivers/usb/platform.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
/**
|
||||||
|
* \brief Platform specific definitions
|
||||||
|
* \author Sebastian Sumpf
|
||||||
|
* \date 2012-07-06
|
||||||
|
*
|
||||||
|
* These functions have to be implemented on all supported platforms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2012 Genode Labs GmbH
|
||||||
|
*
|
||||||
|
* This file is part of the Genode OS framework, which is distributed
|
||||||
|
* under the terms of the GNU General Public License version 2.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _PLATFORM_H_
|
||||||
|
#define _PLATFORM_H_
|
||||||
|
|
||||||
|
struct Services
|
||||||
|
{
|
||||||
|
bool hid;
|
||||||
|
bool stor;
|
||||||
|
bool nic;
|
||||||
|
|
||||||
|
Services() : hid(false), stor(false), nic(false) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
void platform_hcd_init(Services *services);
|
||||||
|
|
||||||
|
#endif /* _PLATFORM_H_ */
|
|
@ -136,8 +136,10 @@ class Routine : public Genode::List<Routine>::Element
|
||||||
|
|
||||||
Routine *next = _next(all);
|
Routine *next = _next(all);
|
||||||
|
|
||||||
if (next == _current)
|
if (next == _current) {
|
||||||
|
_check_dead();
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* return when restored */
|
/* return when restored */
|
||||||
if (_current && _setjmp(_current->_env)) {
|
if (_current && _setjmp(_current->_env)) {
|
||||||
|
|
|
@ -120,4 +120,9 @@ namespace Storage
|
||||||
void init(Genode::Signal_receiver *recv);
|
void init(Genode::Signal_receiver *recv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Nic
|
||||||
|
{
|
||||||
|
void init(Genode::Signal_receiver *recv);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* _SIGNAL_H_ */
|
#endif /* _SIGNAL_H_ */
|
||||||
|
|
174
dde_linux/src/drivers/usb/signal/dispatch.h
Normal file
174
dde_linux/src/drivers/usb/signal/dispatch.h
Normal file
|
@ -0,0 +1,174 @@
|
||||||
|
/**
|
||||||
|
* \brief Packet-stream-session components
|
||||||
|
* \author Sebastian Sumpf
|
||||||
|
* \author Norman Feske
|
||||||
|
* \date 2012-07-06
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2012 Genode Labs GmbH
|
||||||
|
*
|
||||||
|
* This file is part of the Genode OS framework, which is distributed
|
||||||
|
* under the terms of the GNU General Public License version 2.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SIGNAL__DISPATCHER_H_
|
||||||
|
#define _SIGNAL__DISPATCHER_H_
|
||||||
|
|
||||||
|
#include "signal.h"
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class Signal_dispatcher : public Driver_context,
|
||||||
|
public Genode::Signal_context_capability
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
T &obj;
|
||||||
|
void (T::*member) ();
|
||||||
|
Genode::Signal_receiver *sig_rec;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* \param sig_rec signal receiver to associate the signal
|
||||||
|
* handler with
|
||||||
|
* \param obj,member object and member function to call when
|
||||||
|
* the signal occurs
|
||||||
|
*/
|
||||||
|
Signal_dispatcher(Genode::Signal_receiver *sig_rec,
|
||||||
|
T &obj, void (T::*member)())
|
||||||
|
:
|
||||||
|
Genode::Signal_context_capability(sig_rec->manage(this)),
|
||||||
|
obj(obj), member(member),
|
||||||
|
sig_rec(sig_rec)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
~Signal_dispatcher() { sig_rec->dissolve(this); }
|
||||||
|
|
||||||
|
void handle() { (obj.*member)(); }
|
||||||
|
char const *debug() { return "Signal_dispatcher"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Session components that overrides signal handlers
|
||||||
|
*/
|
||||||
|
template <typename RPC>
|
||||||
|
class Packet_session_component : public RPC
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
Signal_dispatcher<Packet_session_component> _process_packet_dispatcher;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual void _process_packets() = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Packet_session_component(Genode::Dataspace_capability tx_ds,
|
||||||
|
Genode::Rpc_entrypoint &ep,
|
||||||
|
Genode::Signal_receiver *sig_rec)
|
||||||
|
:
|
||||||
|
RPC(tx_ds, ep),
|
||||||
|
_process_packet_dispatcher(sig_rec, *this,
|
||||||
|
&Packet_session_component::_process_packets)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Register '_process_packets' dispatch function as signal
|
||||||
|
* handler for packet-avail and ready-to-ack signals.
|
||||||
|
*/
|
||||||
|
RPC::_tx.sigh_packet_avail(_process_packet_dispatcher);
|
||||||
|
RPC::_tx.sigh_ready_to_ack(_process_packet_dispatcher);
|
||||||
|
}
|
||||||
|
|
||||||
|
Packet_session_component(Genode::Dataspace_capability tx_ds,
|
||||||
|
Genode::Dataspace_capability rx_ds,
|
||||||
|
Genode::Range_allocator *rx_buffer_alloc,
|
||||||
|
Genode::Rpc_entrypoint &ep,
|
||||||
|
Genode::Signal_receiver *sig_rec)
|
||||||
|
:
|
||||||
|
RPC(tx_ds, rx_ds, rx_buffer_alloc, ep),
|
||||||
|
_process_packet_dispatcher(sig_rec, *this,
|
||||||
|
&Packet_session_component::_process_packets)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Register '_process_packets' dispatch function as signal
|
||||||
|
* handler for packet-avail and ready-to-ack signals.
|
||||||
|
*/
|
||||||
|
RPC::_tx.sigh_packet_avail(_process_packet_dispatcher);
|
||||||
|
RPC::_tx.sigh_ready_to_ack(_process_packet_dispatcher);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract device
|
||||||
|
*/
|
||||||
|
struct Device { };
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Root component, handling new session requests
|
||||||
|
*/
|
||||||
|
template <typename ROOT_COMPONENT, typename SESSION_COMPONENT>
|
||||||
|
class Packet_root : public ROOT_COMPONENT
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
Genode::Rpc_entrypoint &_ep;
|
||||||
|
Genode::Signal_receiver *_sig_rec;
|
||||||
|
Device *_device;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Always returns the singleton block-session component
|
||||||
|
*/
|
||||||
|
SESSION_COMPONENT *_create_session(const char *args)
|
||||||
|
{
|
||||||
|
using namespace Genode;
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* delete ram quota by the memory needed for the session */
|
||||||
|
size_t session_size = max((size_t)4096,
|
||||||
|
sizeof(SESSION_COMPONENT)
|
||||||
|
+ sizeof(Allocator_avl));
|
||||||
|
if (ram_quota < session_size)
|
||||||
|
throw Root::Quota_exceeded();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if donated ram quota suffices for both communication
|
||||||
|
* buffers. Also check both sizes separately to handle a
|
||||||
|
* possible overflow of the sum of both sizes.
|
||||||
|
*/
|
||||||
|
if (tx_buf_size > ram_quota - session_size) {
|
||||||
|
PERR("insufficient 'ram_quota', got %zd, need %zd",
|
||||||
|
ram_quota, tx_buf_size + session_size);
|
||||||
|
throw Root::Quota_exceeded();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new (ROOT_COMPONENT::md_alloc())
|
||||||
|
SESSION_COMPONENT(env()->ram_session()->alloc(tx_buf_size),
|
||||||
|
env()->ram_session()->alloc(rx_buf_size),
|
||||||
|
_ep, _sig_rec, _device);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Packet_root(Genode::Rpc_entrypoint *session_ep, Genode::Allocator *md_alloc,
|
||||||
|
Genode::Signal_receiver *sig_rec, Device *device)
|
||||||
|
:
|
||||||
|
ROOT_COMPONENT(session_ep, md_alloc),
|
||||||
|
_ep(*session_ep), _sig_rec(sig_rec), _device(device)
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _SIGNAL__DISPATCHER_H_ */
|
|
@ -52,6 +52,53 @@ void Event::init(Genode::Signal_receiver *recv) {
|
||||||
_signal = new (Genode::env()->heap()) Signal_helper(recv); }
|
_signal = new (Genode::env()->heap()) Signal_helper(recv); }
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delayed work
|
||||||
|
*/
|
||||||
|
class Work : public Genode::List<Work>::Element
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
void *_work;
|
||||||
|
bool _delayed;
|
||||||
|
|
||||||
|
static Genode::List<Work> *_list()
|
||||||
|
{
|
||||||
|
static Genode::List<Work> _l;
|
||||||
|
return &_l;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Work(void *work, bool delayed) : _work(work), _delayed(delayed) { }
|
||||||
|
|
||||||
|
static void schedule(void *work, bool delayed)
|
||||||
|
{
|
||||||
|
Work *w = new (Genode::env()->heap()) Work(work, delayed);
|
||||||
|
_list()->insert(w);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void exec()
|
||||||
|
{
|
||||||
|
while (_list()->first()) {
|
||||||
|
Work *w = _list()->first();
|
||||||
|
_list()->remove(w);
|
||||||
|
|
||||||
|
if (w->_delayed) {
|
||||||
|
delayed_work *work = static_cast<delayed_work *>(w->_work);
|
||||||
|
work->work.func(&(work)->work);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
work_struct *work = static_cast<work_struct *>(w->_work);
|
||||||
|
work->func(work);
|
||||||
|
}
|
||||||
|
destroy(Genode::env()->heap(), w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/************************
|
/************************
|
||||||
** linux/completion.h **
|
** linux/completion.h **
|
||||||
************************/
|
************************/
|
||||||
|
@ -59,8 +106,14 @@ void Event::init(Genode::Signal_receiver *recv) {
|
||||||
void __wake_up() { Routine::schedule_all(); }
|
void __wake_up() { Routine::schedule_all(); }
|
||||||
|
|
||||||
|
|
||||||
void __wait_event() {
|
void __wait_event()
|
||||||
Service_handler::s()->process(); }
|
{
|
||||||
|
/* schedule work first */
|
||||||
|
Work::exec();
|
||||||
|
|
||||||
|
/* schedule other routines or wait for signals */
|
||||||
|
Service_handler::s()->process();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void init_completion(struct completion *work)
|
void init_completion(struct completion *work)
|
||||||
|
@ -167,3 +220,21 @@ int wake_up_process(struct task_struct *tsk)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************
|
||||||
|
** linux/workquque.h **
|
||||||
|
***********************/
|
||||||
|
|
||||||
|
int schedule_delayed_work(struct delayed_work *work, unsigned long delay)
|
||||||
|
{
|
||||||
|
Work::schedule((void *)work, true);
|
||||||
|
//work->work.func(&(work)->work);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int schedule_work(struct work_struct *work)
|
||||||
|
{
|
||||||
|
Work::schedule((void *)work, false);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
|
@ -93,9 +93,13 @@ class Irq_context : public Driver_context,
|
||||||
/* report IRQ to all clients */
|
/* report IRQ to all clients */
|
||||||
for (Irq_handler *h = _handler_list.first(); h; h = h->next()) {
|
for (Irq_handler *h = _handler_list.first(); h; h = h->next()) {
|
||||||
irqreturn_t rc;
|
irqreturn_t rc;
|
||||||
if ((rc = h->handler(_irq, h->dev)) == IRQ_HANDLED)
|
|
||||||
|
rc = h->handler(_irq, h->dev);
|
||||||
|
dde_kit_log(DEBUG_IRQ, "IRQ: %u ret: %u %p", _irq, rc, h->handler);
|
||||||
|
if (rc == IRQ_HANDLED) {
|
||||||
Routine::schedule_all();
|
Routine::schedule_all();
|
||||||
dde_kit_log(DEBUG_IRQ, "IRQ: %u ret: %u", _irq, rc);
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
#include <root/component.h>
|
#include <root/component.h>
|
||||||
#include <block_session/rpc_object.h>
|
#include <block_session/rpc_object.h>
|
||||||
|
|
||||||
#include "signal.h"
|
#include <signal/dispatch.h>
|
||||||
|
|
||||||
namespace Block {
|
namespace Block {
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ namespace Block {
|
||||||
|
|
||||||
class Session_component;
|
class Session_component;
|
||||||
|
|
||||||
struct Device
|
struct Device : ::Device
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Request block size for driver and medium
|
* Request block size for driver and medium
|
||||||
|
@ -42,49 +42,14 @@ namespace Block {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
class Session_component : public Packet_session_component<Session_rpc_object>
|
||||||
class Signal_dispatcher : public Driver_context,
|
|
||||||
public Signal_context_capability
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
|
|
||||||
T &obj;
|
|
||||||
void (T::*member) ();
|
|
||||||
Signal_receiver *sig_rec;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*
|
|
||||||
* \param sig_rec signal receiver to associate the signal
|
|
||||||
* handler with
|
|
||||||
* \param obj,member object and member function to call when
|
|
||||||
* the signal occurs
|
|
||||||
*/
|
|
||||||
Signal_dispatcher(Signal_receiver *sig_rec,
|
|
||||||
T &obj, void (T::*member)())
|
|
||||||
:
|
|
||||||
Signal_context_capability(sig_rec->manage(this)),
|
|
||||||
obj(obj), member(member),
|
|
||||||
sig_rec(sig_rec)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
~Signal_dispatcher() { sig_rec->dissolve(this); }
|
|
||||||
|
|
||||||
void handle() { (obj.*member)(); }
|
|
||||||
char const *debug() { return "Block_context"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class Session_component : public Session_rpc_object
|
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
addr_t _rq_phys ; /* physical addr. of rq_ds */
|
addr_t _rq_phys ; /* physical addr. of rq_ds */
|
||||||
Device *_device; /* device this session is using */
|
Device *_device; /* device this session is using */
|
||||||
|
|
||||||
Signal_dispatcher<Session_component> _process_packet_dispatcher;
|
protected:
|
||||||
|
|
||||||
void _process_packets()
|
void _process_packets()
|
||||||
{
|
{
|
||||||
|
@ -105,23 +70,17 @@ namespace Block {
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*/
|
*/
|
||||||
Session_component(Dataspace_capability rq_ds,
|
Session_component(Dataspace_capability tx_ds,
|
||||||
|
Ram_dataspace_capability rx_ds,
|
||||||
Rpc_entrypoint &ep,
|
Rpc_entrypoint &ep,
|
||||||
Signal_receiver *sig_rec,
|
Signal_receiver *sig_rec,
|
||||||
Device *device)
|
::Device *device)
|
||||||
:
|
:
|
||||||
Session_rpc_object(rq_ds, ep),
|
Packet_session_component(tx_ds, ep, sig_rec),
|
||||||
_rq_phys(Dataspace_client(rq_ds).phys_addr()),
|
_rq_phys(Dataspace_client(tx_ds).phys_addr()),
|
||||||
_device(device),
|
_device(static_cast<Device *>(device))
|
||||||
_process_packet_dispatcher(sig_rec, *this,
|
|
||||||
&Session_component::_process_packets)
|
|
||||||
{
|
{
|
||||||
/*
|
env()->ram_session()->free(rx_ds);
|
||||||
* Register '_process_packets' dispatch function as signal
|
|
||||||
* handler for packet-avail and ready-to-ack signals.
|
|
||||||
*/
|
|
||||||
_tx.sigh_packet_avail(_process_packet_dispatcher);
|
|
||||||
_tx.sigh_ready_to_ack(_process_packet_dispatcher);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void info(size_t *blk_count, size_t *blk_size,
|
void info(size_t *blk_count, size_t *blk_size,
|
||||||
|
@ -148,58 +107,15 @@ namespace Block {
|
||||||
/**
|
/**
|
||||||
* Root component, handling new session requests
|
* Root component, handling new session requests
|
||||||
*/
|
*/
|
||||||
class Root : public Root_component
|
class Root : public Packet_root<Root_component, Session_component>
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
|
|
||||||
Rpc_entrypoint &_ep;
|
|
||||||
Signal_receiver *_sig_rec;
|
|
||||||
Device *_device;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Always returns the singleton block-session component
|
|
||||||
*/
|
|
||||||
Session_component *_create_session(const char *args)
|
|
||||||
{
|
|
||||||
size_t ram_quota =
|
|
||||||
Arg_string::find_arg(args, "ram_quota" ).ulong_value(0);
|
|
||||||
size_t tx_buf_size =
|
|
||||||
Arg_string::find_arg(args, "tx_buf_size").ulong_value(0);
|
|
||||||
|
|
||||||
/* delete ram quota by the memory needed for the session */
|
|
||||||
size_t session_size = max((size_t)4096,
|
|
||||||
sizeof(Session_component)
|
|
||||||
+ sizeof(Allocator_avl));
|
|
||||||
if (ram_quota < session_size)
|
|
||||||
throw Root::Quota_exceeded();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check if donated ram quota suffices for both communication
|
|
||||||
* buffers. Also check both sizes separately to handle a
|
|
||||||
* possible overflow of the sum of both sizes.
|
|
||||||
*/
|
|
||||||
if (tx_buf_size > ram_quota - session_size) {
|
|
||||||
PERR("insufficient 'ram_quota', got %zd, need %zd",
|
|
||||||
ram_quota, tx_buf_size + session_size);
|
|
||||||
throw Root::Quota_exceeded();
|
|
||||||
}
|
|
||||||
|
|
||||||
return new (md_alloc())
|
|
||||||
Session_component(env()->ram_session()->alloc(tx_buf_size),
|
|
||||||
_ep, _sig_rec, _device);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Root(Rpc_entrypoint *session_ep, Allocator *md_alloc,
|
Root(Rpc_entrypoint *session_ep, Allocator *md_alloc,
|
||||||
Signal_receiver *sig_rec, Device *device)
|
Signal_receiver *sig_rec, Device *device)
|
||||||
:
|
:
|
||||||
Root_component(session_ep, md_alloc),
|
Packet_root(session_ep, md_alloc, sig_rec, device) { }
|
||||||
_ep(*session_ep), _sig_rec(sig_rec), _device(device)
|
|
||||||
{ }
|
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
|
}
|
||||||
#endif /* _STORAGE__COMPONENT_H_ */
|
#endif /* _STORAGE__COMPONENT_H_ */
|
||||||
|
|
|
@ -19,9 +19,9 @@
|
||||||
|
|
||||||
#include <lx_emul.h>
|
#include <lx_emul.h>
|
||||||
|
|
||||||
#include "component.h"
|
#include <storage/component.h>
|
||||||
|
#include <storage/scsi.h>
|
||||||
#include "signal.h"
|
#include "signal.h"
|
||||||
#include "scsi.h"
|
|
||||||
|
|
||||||
static Signal_helper *_signal = 0;
|
static Signal_helper *_signal = 0;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
TARGET = usb_drv
|
TARGET = usb_drv
|
||||||
LIBS = cxx env dde_kit server libc-setjmp signal
|
LIBS = cxx env dde_kit server libc-setjmp signal
|
||||||
SRC_CC = main.cc lx_emul.cc irq.cc timer.cc event.cc storage.cc \
|
SRC_CC = main.cc lx_emul.cc irq.cc timer.cc event.cc storage.cc \
|
||||||
input_component.cc
|
input_component.cc nic.cc
|
||||||
SRC_C = dummies.c scsi.c evdev.c
|
SRC_C = dummies.c scsi.c evdev.c
|
||||||
|
|
||||||
CONTRIB_DIR := $(REP_DIR)/contrib
|
CONTRIB_DIR := $(REP_DIR)/contrib
|
||||||
|
@ -82,12 +82,11 @@ else ifeq ($(filter-out $(SPECS),platform_panda),)
|
||||||
CC_OPT += -DCONFIG_USB_EHCI_HCD_OMAP -DCONFIG_USB_EHCI_TT_NEWSCHED -DVERBOSE_DEBUG
|
CC_OPT += -DCONFIG_USB_EHCI_HCD_OMAP -DCONFIG_USB_EHCI_TT_NEWSCHED -DVERBOSE_DEBUG
|
||||||
INC_DIR += $(PRG_DIR)/arm
|
INC_DIR += $(PRG_DIR)/arm
|
||||||
INC_DIR += $(CONTRIB_DIR)/arch/arm/plat-omap/include
|
INC_DIR += $(CONTRIB_DIR)/arch/arm/plat-omap/include
|
||||||
SRC_C += platform_device.c
|
SRC_C += platform_device.c usbnet.c smsc95xx.c
|
||||||
SRC_CC += platform.cc
|
SRC_CC += platform.cc
|
||||||
#SRC_C += $(CONTRIB_DIR)/arch/arm/mach-omap2/usb-host.c
|
|
||||||
#SRC_C += $(DRIVERS_DIR)/mfd/omap-usb-host.c
|
|
||||||
vpath %.c $(PRG_DIR)/arm/platform
|
vpath %.c $(PRG_DIR)/arm/platform
|
||||||
vpath %.cc $(PRG_DIR)/arm/platform
|
vpath %.cc $(PRG_DIR)/arm/platform
|
||||||
|
vpath %.c $(CONTRIB_DIR)/drivers/net/usb
|
||||||
|
|
||||||
#
|
#
|
||||||
# Unsupported
|
# Unsupported
|
||||||
|
@ -135,6 +134,7 @@ vpath %.c $(PRG_DIR)/input
|
||||||
vpath %.cc $(PRG_DIR)/input
|
vpath %.cc $(PRG_DIR)/input
|
||||||
vpath %.cc $(PRG_DIR)/storage
|
vpath %.cc $(PRG_DIR)/storage
|
||||||
vpath %.c $(PRG_DIR)/storage
|
vpath %.c $(PRG_DIR)/storage
|
||||||
|
vpath %.cc $(PRG_DIR)/nic
|
||||||
|
|
||||||
clean cleanall:
|
clean cleanall:
|
||||||
$(VERBOSE) rm -r include
|
$(VERBOSE) rm -r include
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
#ifndef _X86_32__PLATFORM_H_
|
#ifndef _X86_32__PLATFORM_H_
|
||||||
#define _X86_32__PLATFORM_H_
|
#define _X86_32__PLATFORM_H_
|
||||||
|
|
||||||
|
#include <platform.h>
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
void platform_execute(void *sp, void *func, void *arg)
|
void platform_execute(void *sp, void *func, void *arg)
|
||||||
{
|
{
|
||||||
|
@ -27,7 +29,7 @@ void platform_execute(void *sp, void *func, void *arg)
|
||||||
extern "C" void module_ehci_hcd_init();
|
extern "C" void module_ehci_hcd_init();
|
||||||
extern "C" void module_uhci_hcd_init();
|
extern "C" void module_uhci_hcd_init();
|
||||||
|
|
||||||
static inline void platform_hcd_init(void)
|
inline void platform_hcd_init(Services *s)
|
||||||
{
|
{
|
||||||
|
|
||||||
/* ehci_hcd should always be loaded before uhci_hcd and ohci_hcd, not after */
|
/* ehci_hcd should always be loaded before uhci_hcd and ohci_hcd, not after */
|
||||||
|
|
Loading…
Reference in New Issue
Block a user