summaryrefslogtreecommitdiff
path: root/cleopatre/devkit
diff options
context:
space:
mode:
Diffstat (limited to 'cleopatre/devkit')
-rw-r--r--cleopatre/devkit/plcdrv/Kbuild25
-rw-r--r--cleopatre/devkit/plcdrv/Makefile59
-rw-r--r--cleopatre/devkit/plcdrv/Module3
l---------cleopatre/devkit/plcdrv/common1
-rwxr-xr-xcleopatre/devkit/plcdrv/hotplug-plcdrv27
-rw-r--r--cleopatre/devkit/plcdrv/inc/boot_params.h13
-rw-r--r--cleopatre/devkit/plcdrv/inc/common.h70
-rw-r--r--cleopatre/devkit/plcdrv/inc/debug_dump.h95
-rw-r--r--cleopatre/devkit/plcdrv/inc/firmware.h31
-rw-r--r--cleopatre/devkit/plcdrv/inc/frame.h112
-rw-r--r--cleopatre/devkit/plcdrv/inc/hal.h207
-rw-r--r--cleopatre/devkit/plcdrv/inc/ipmbox.h116
-rw-r--r--cleopatre/devkit/plcdrv/inc/linux_drv.h200
-rw-r--r--cleopatre/devkit/plcdrv/inc/mailbox.h97
-rw-r--r--cleopatre/devkit/plcdrv/inc/plcdrv.h126
-rw-r--r--cleopatre/devkit/plcdrv/inc/plcdrv_forward.h18
-rw-r--r--cleopatre/devkit/plcdrv/inc/processing.h112
-rw-r--r--cleopatre/devkit/plcdrv/inc/registers.h116
-rw-r--r--cleopatre/devkit/plcdrv/src/boot_params.c14
-rw-r--r--cleopatre/devkit/plcdrv/src/debug_dump.c197
-rw-r--r--cleopatre/devkit/plcdrv/src/firmware.c193
-rw-r--r--cleopatre/devkit/plcdrv/src/frame.c440
-rw-r--r--cleopatre/devkit/plcdrv/src/hal.c473
-rw-r--r--cleopatre/devkit/plcdrv/src/ipmbox.c470
-rw-r--r--cleopatre/devkit/plcdrv/src/linux_drv.c2042
-rw-r--r--cleopatre/devkit/plcdrv/src/mailbox.c526
-rw-r--r--cleopatre/devkit/plcdrv/src/plcdrv.c885
-rw-r--r--cleopatre/devkit/plcdrv/src/processing.c352
-rw-r--r--cleopatre/devkit/tests/plcdrv/utests/Makefile12
-rw-r--r--cleopatre/devkit/tests/plcdrv/utests/inc/hal_utests.h40
-rw-r--r--cleopatre/devkit/tests/plcdrv/utests/inc/mailbox_utests.h269
-rw-r--r--cleopatre/devkit/tests/plcdrv/utests/inc/processing_utests.h160
-rw-r--r--cleopatre/devkit/tests/plcdrv/utests/ipmbox/Makefile34
-rw-r--r--cleopatre/devkit/tests/plcdrv/utests/ipmbox/src/ipmbox_queue_test.c356
-rw-r--r--cleopatre/devkit/tests/plcdrv/utests/ipmbox/src/ipmbox_test.c373
-rw-r--r--cleopatre/devkit/tests/plcdrv/utests/ipmbox/src/stub_frame.c91
-rw-r--r--cleopatre/devkit/tests/plcdrv/utests/ipmbox/src/stub_linux.c61
-rw-r--r--cleopatre/devkit/tests/plcdrv/utests/ipmbox/stub.h44
-rw-r--r--cleopatre/devkit/tests/plcdrv/utests/src/hal_utests.c380
-rw-r--r--cleopatre/devkit/tests/plcdrv/utests/src/linux_drv_utests.c8
-rw-r--r--cleopatre/devkit/tests/plcdrv/utests/src/mailbox_utests.c252
-rw-r--r--cleopatre/devkit/tests/plcdrv/utests/src/processing_utests.c230
-rw-r--r--cleopatre/devkit/tests/plcdrv/utests/stub/linux/Module5
-rw-r--r--cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/asm/arch/hardware/regbank.h1
-rw-r--r--cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/asm/arch/ioctl.h12
-rw-r--r--cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/asm/arch/platform.h11
-rw-r--r--cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/asm.h12
-rw-r--r--cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/bitops.h5
-rw-r--r--cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/bug.h10
-rw-r--r--cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/compiler.h4
-rw-r--r--cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/device.h4
-rw-r--r--cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/dma-mapping.h1
-rw-r--r--cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/errno.h1
-rw-r--r--cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/etherdevice.h14
-rw-r--r--cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/firmware.h26
-rw-r--r--cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/if.h1
-rw-r--r--cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/if_ether.h1
-rw-r--r--cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/if_vlan.h1
-rw-r--r--cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/io.h11
-rw-r--r--cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/jiffies.h6
-rw-r--r--cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/kernel.h20
-rw-r--r--cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/module.h3
-rw-r--r--cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/moduleparam.h1
-rw-r--r--cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/netdevice.h38
-rw-r--r--cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/proc_fs.h5
-rw-r--r--cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/skbuff.h65
-rw-r--r--cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/spinlock.h6
-rw-r--r--cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/types.h4
-rw-r--r--cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/wait.h4
-rw-r--r--cleopatre/devkit/tests/plcdrv/utests/stub/linux/src/bitops.c6
-rw-r--r--cleopatre/devkit/tests/plcdrv/utests/stub/linux/src/eth.c2
-rw-r--r--cleopatre/devkit/tests/plcdrv/utests/stub/linux/src/jiffies.c1
-rw-r--r--cleopatre/devkit/tests/plcdrv/utests/stub/linux/src/net_dev.c12
-rw-r--r--cleopatre/devkit/tests/plcdrv/utests/stub/linux/src/spc300.c6
74 files changed, 4042 insertions, 5587 deletions
diff --git a/cleopatre/devkit/plcdrv/Kbuild b/cleopatre/devkit/plcdrv/Kbuild
new file mode 100644
index 0000000000..ebaf0e637f
--- /dev/null
+++ b/cleopatre/devkit/plcdrv/Kbuild
@@ -0,0 +1,25 @@
+obj-m := plcdrv.o
+plcdrv-objs := src/frame.o src/boot_params.o src/debug_dump.o src/plcdrv.o \
+ src/firmware.o src/ipmbox.o \
+ common/ipmbox/src/queue.o
+
+# Because Kernel Makefile does not clean everything in plcdrv-objs
+common-objs = $(filter-out src/%, $(plcdrv-objs))
+clean-files += $(common-objs) \
+ $(foreach f,$(common-objs),$(dir $f).$(notdir $f).cmd)
+
+# Add our debugging flag to CFLAGS
+ifeq ($(DEBUG),y)
+ DEBFLAGS = -O -g
+else
+ DEBFLAGS = -Os
+endif
+
+VERSION=$(shell git describe --always 2>/dev/null)
+
+EXTRA_CFLAGS += -I$(M)/inc -I$(M)
+EXTRA_CFLAGS += $(DEBFLAGS) -DDRV_VERSION=\"$(VERSION)\"
+
+ifeq ($(CONFIG_SEQ_CHECK),y)
+ EXTRA_CFLAGS += -DCONFIG_SEQ_CHECK
+endif
diff --git a/cleopatre/devkit/plcdrv/Makefile b/cleopatre/devkit/plcdrv/Makefile
index 60900c5bd7..cfdb92d924 100644
--- a/cleopatre/devkit/plcdrv/Makefile
+++ b/cleopatre/devkit/plcdrv/Makefile
@@ -1,54 +1,13 @@
-BASEPATH=../..
-PLCSUBPATH=devkit/plcdrv/
-PLCPATH=$(BASEPATH)/$(PLCSUBPATH)
-KRNPATH=$(BASEPATH)/linux-2.6.25.10-spc300
+KERNELDIR := ../../linux-2.6.25.10-spc300
DEBUG = n
-VERSION=$(shell git describe --always 2>/dev/null)
-# Add our debugging flag to CFLAGS
-ifeq ($(DEBUG),y)
- DEBFLAGS = -O -g
-else
- DEBFLAGS = -Os
-endif
+# all rules is buggy for external modules, default to modules rule
+all:
+ $(MAKE) -C $(KERNELDIR) M=`pwd` Q= ARCH=arm CROSS_COMPILE=arm-linux- modules
-#We cannot modify CFLAGS but we have to methods to add CFLAGS
-#1st for all files
-EXTRA_CFLAGS += $(DEBFLAGS) -D__LINUX__ -DDRV_VERSION=\"$(VERSION)\"
-EXTRA_CFLAGS += -I../$(PLCSUBPATH)/inc
+%::
+ $(MAKE) -C $(KERNELDIR) M=`pwd` ARCH=arm CROSS_COMPILE=arm-linux- $@
-ifeq ($(CONFIG_SEQ_CHECK),y)
- EXTRA_CFLAGS += -DCONFIG_SEQ_CHECK
-endif
-
-#2nd for each file
-#CFLAGS_linux_drv.o := $(DEBFLAGS) -D__LINUX__ -I../$(PLCSUBPATH)/inc
-
-ifneq ($(KERNELRELEASE),)
-# call from kernel build system
-
-plcdrv-objs := src/linux_drv.o src/processing.o src/mailbox.o src/hal.o \
- src/boot_params.o
-obj-m := plcdrv.o
-
-else
-
-KERNELDIR ?= $(KRNPATH)
-PWD := $(CURDIR)
-
-modules:
- $(MAKE) -C $(KERNELDIR) ARCH=arm CROSS_COMPILE=arm-linux- M=$(PWD) modules
-endif
-
-
-clean:
- rm -f $(PLCPATH)/src/*.o
- rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c *.mod.o .tmp_versions modules.order Module.symvers
-
-depend .depend dep:
- $(CC) $(CFLAGS) -M *.c > .depend
-
-
-ifeq (.depend,$(wildcard .depend))
-include .depend
-endif
+clean::
+ $(MAKE) -C $(KERNELDIR) M=`pwd` ARCH=arm CROSS_COMPILE=arm-linux- $@
+ rm -f $(CURDIR)/modules.order
diff --git a/cleopatre/devkit/plcdrv/Module b/cleopatre/devkit/plcdrv/Module
index d644569e21..fdaa4c9072 100644
--- a/cleopatre/devkit/plcdrv/Module
+++ b/cleopatre/devkit/plcdrv/Module
@@ -1 +1,2 @@
-SOURCES = hal.c linux_drv.c mailbox.c processing.c
+SOURCES = boot_params.c debug_dump.c firmware.c frame.c ipmbox.c \
+ plcdrv.c
diff --git a/cleopatre/devkit/plcdrv/common b/cleopatre/devkit/plcdrv/common
new file mode 120000
index 0000000000..f74dff0e4d
--- /dev/null
+++ b/cleopatre/devkit/plcdrv/common
@@ -0,0 +1 @@
+../../../common \ No newline at end of file
diff --git a/cleopatre/devkit/plcdrv/hotplug-plcdrv b/cleopatre/devkit/plcdrv/hotplug-plcdrv
new file mode 100755
index 0000000000..4fd46366e8
--- /dev/null
+++ b/cleopatre/devkit/plcdrv/hotplug-plcdrv
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+case "$ACTION:$SUBSYSTEM:$DEVPATH" in
+ add:module:/module/plcdrv)
+ mknod /dev/plcdrv c 254 0
+ chmod 666 /dev/plcdrv
+ mknod /dev/trace c 254 1
+ ;;
+ add:firmware:/class/firmware/plc0)
+ echo 1 > /sys/$DEVPATH/loading
+ plcfw=/lib/modules/$FIRMWARE.rom
+ if [ -e /etc/plcdrv.conf ]; then
+ source /etc/plcdrv.conf
+ fi
+ if [ -e /usr/local/$plcfw ]; then
+ plcfw=/usr/local/$plcfw
+ fi
+ if cat $plcfw > /sys/$DEVPATH/data; then
+ echo 0 > /sys/$DEVPATH/loading
+ else
+ echo -1 > /sys/$DEVPATH/loading
+ fi
+ ;;
+ remove:module:/module/plcdrv)
+ rm /dev/plcdrv /dev/trace
+ ;;
+esac
diff --git a/cleopatre/devkit/plcdrv/inc/boot_params.h b/cleopatre/devkit/plcdrv/inc/boot_params.h
index 2d264550d2..108c7cb1e3 100644
--- a/cleopatre/devkit/plcdrv/inc/boot_params.h
+++ b/cleopatre/devkit/plcdrv/inc/boot_params.h
@@ -1,6 +1,5 @@
-#ifndef boot_params_h
-#define boot_params_h
-
+#ifndef inc_boot_params_h
+#define inc_boot_params_h
/* Cleopatre project {{{
*
* Copyright (C) 2011 Spidcom
@@ -9,9 +8,9 @@
*
* }}} */
/**
- * \file boot_params.h
- * \brief support for passing boot parameters to Cesar.
- * \ingroup Cleopatre - PlcDrv
+ * \file inc/boot_params.h
+ * \brief Support for passing boot parameters to Cesar.
+ * \ingroup plcdrv
*
*/
@@ -32,4 +31,4 @@ extern char custom_boot_params[BOOT_PARAMS_STR_SIZE];
*/
int plcdrv_pass_boot_params(uint8_t *boot_params_area);
-#endif /* boot_params_h */
+#endif /* inc_boot_params_h */
diff --git a/cleopatre/devkit/plcdrv/inc/common.h b/cleopatre/devkit/plcdrv/inc/common.h
deleted file mode 100644
index 1737a6cc83..0000000000
--- a/cleopatre/devkit/plcdrv/inc/common.h
+++ /dev/null
@@ -1,70 +0,0 @@
-#ifndef common_h
-#define common_h
-/* Cleopatre project {{{
- *
- * Copyright (C) 2008 Spidcom
- *
- * <<<Licence>>>
- *
- * }}} */
-/**
- * \file common.h
- * \brief general definitions
- * \ingroup Cleopatre - PlcDrv
- *
- * This file content all definitions needed by all different layers
- */
-
-#ifndef __UTESTS__
-#include <linux/types.h> //for uint32_t....
-#include <linux/kernel.h> //for printk...
-#include <linux/string.h> //for memcpy, memset...
-#include <linux/if_ether.h>//for ETH_ALEN
-#else
-#include <linux/types.h>
-#include <linux/if_ether.h>
-#endif
-
-/** Define different trace levels */
-#define TRACE_HAL 0
-#define TRACE_MAIL 1
-#define TRACE_PROCESS 2
-#define TRACE_LINUX 3
-#define TRACE_PACKET 4
-extern uint32_t trace;
-
-/** Max size of an Ethernet frame (size for all buffers) must be align on 4 bytes */
-#define PKT_BUF_SZ 1524
-
-/** Define the budget for RX part */
-#define PLCDRV_RX_BUDGET 32
-
-/** Arm to Leon mailbox ring size */
-#define A2L_RING_SIZE 0x1000
-
-/** Leon to Arm mailbox ring size */
-#define L2A_RING_SIZE 0x1000
-
-/** Define queue status */
-#define NOT_FULL 0
-#define FULL 1
-#define NEARLY_FULL 2
-
-/** Type of buffer */
-typedef enum buffer_type {
- DATA = 0,
- MME = 1,
- INTERFACE = 2,
-} buffer_type_t;
-
-/** Initialization structure */
-struct init_info {
- unsigned int ring_base_addr;
- unsigned int phys_ring_base_addr;
- unsigned int mbx_reg_base_addr;
- int (*launch_leon)(void);
- int debug_mode;
- uint8_t mac_addr[ETH_ALEN];
-};
-
-#endif /* common_h */
diff --git a/cleopatre/devkit/plcdrv/inc/debug_dump.h b/cleopatre/devkit/plcdrv/inc/debug_dump.h
new file mode 100644
index 0000000000..dd92dcf0c0
--- /dev/null
+++ b/cleopatre/devkit/plcdrv/inc/debug_dump.h
@@ -0,0 +1,95 @@
+#ifndef inc_debug_dump_h
+#define inc_debug_dump_h
+/* Cleopatre project {{{
+ *
+ * Copyright (C) 2012 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file inc/debug_dump.h
+ * \brief Debug dump interface.
+ * \ingroup plcdrv
+ *
+ * Debug dump buffers are exchanged between Cleopatre and firmware and contains
+ * the traces.
+ */
+
+#include <linux/types.h>
+#include <linux/wait.h>
+#include <linux/fs.h>
+#include <linux/compiler.h>
+
+#include "plcdrv_forward.h"
+
+/**
+ * Debug dump buffer length allocated by Cleopatra.
+ */
+#define DEBUG_DUMP_BUFFER_LENGTH 2048
+
+/**
+ * Debug dump context structure.
+ */
+typedef struct debug_dump_t
+{
+ /**
+ * Length of the debug dump buffer received from firmware by the mailbox.
+ * Set to -1 at initialization and to 0 when there is nothing more to read
+ * from firmware.
+ */
+ int buffer_length_received;
+ /**
+ * Debug dump buffer location.
+ * When debug dump buffer has been sent to firmware, this variable is set
+ * to true, otherwise, this is set to false.
+ */
+ bool waiting_for_buffer;
+ /**
+ * Debug dump wait queue shared between the mailbox received and the read
+ * proc from the kernel.
+ */
+ wait_queue_head_t wait_queue;
+ /**
+ * Open function has been called?
+ */
+ bool opened;
+} debug_dump_t;
+
+/**
+ * Debug dump read primitive.
+ * \param priv PLC device private context
+ * \param buf where to copy read data
+ * \param count size of buf
+ * \param f_pos position in buf
+ * \return negative value for error code, otherwise amount of data copied in
+ * buf
+ */
+int
+debug_dump_read (plcdrv_t *priv, char __user *buf, size_t count,
+ loff_t *f_pos);
+
+/**
+ * Debug dump open primitive.
+ * \param priv PLC device private context
+ * \return 0 if no error, negative value otherwise
+ */
+int
+debug_dump_open (plcdrv_t *priv);
+
+/**
+ * Debug dump release primitive.
+ * \param priv PLC device private context
+ * \return 0 if no error, negative value otherwise
+ */
+void
+debug_dump_release (plcdrv_t *priv);
+
+/**
+ * Initialize debug dump context.
+ * \param priv PLC device private context
+ */
+void
+debug_dump_init (plcdrv_t *priv);
+
+#endif /* inc_debug_dump_h */
diff --git a/cleopatre/devkit/plcdrv/inc/firmware.h b/cleopatre/devkit/plcdrv/inc/firmware.h
new file mode 100644
index 0000000000..e80ce46c40
--- /dev/null
+++ b/cleopatre/devkit/plcdrv/inc/firmware.h
@@ -0,0 +1,31 @@
+#ifndef inc_firmware_h
+#define inc_firmware_h
+/* Cleopatre project {{{
+ *
+ * Copyright (C) 2012 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file inc/firmware.h
+ * \brief Firmware loading support.
+ * \ingroup plcdrv
+ *
+ * This module is responsible to load the firmware from userspace, by calling
+ * a program/script (hotplug) which will have to cat the content of firmware
+ * to a proc/sys file.
+ */
+
+#include <linux/types.h>
+#include <linux/netdevice.h>
+
+/**
+ * Load firmware from userspace.
+ * \param dev net device structure
+ * \return error code
+ */
+int
+firmware_load (struct net_device *dev);
+
+#endif /* inc_firmware_h */
diff --git a/cleopatre/devkit/plcdrv/inc/frame.h b/cleopatre/devkit/plcdrv/inc/frame.h
new file mode 100644
index 0000000000..191bf4f965
--- /dev/null
+++ b/cleopatre/devkit/plcdrv/inc/frame.h
@@ -0,0 +1,112 @@
+#ifndef inc_frame_h
+#define inc_frame_h
+/* Cleopatre project {{{
+ *
+ * Copyright (C) 2012 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file inc/frame.h
+ * \brief Interfaces to send/receive/alloc/free frames for firmware.
+ * \ingroup plcdrv
+ */
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+
+#include "plcdrv.h"
+
+/**
+ * Max size of an Ethernet frame (size for all buffers).
+ * It must be align on 4 bytes.
+ */
+#define PKT_BUF_SZ 1524
+
+/**
+ * Allocate buffers and give them to firmware.
+ * \param priv PLC device private context
+ * \return true if all buffers have been allocated, false otherwise
+ */
+bool
+frame_buffer_alloc (plcdrv_t *priv);
+
+/**
+ * Free a buffer after being used by firmware.
+ * \param priv PLC device private context
+ * \param buffer buffer to release (physical address)
+ */
+void
+frame_buffer_free (plcdrv_t *priv, uint32_t buffer);
+
+/**
+ * Resume device queue if possible.
+ * \param priv PLC device private context
+ */
+static inline void
+frame_wake_queue (plcdrv_t *priv)
+{
+ if (skb_queue_len (&priv->tx_pool_data) < PLCDRV_TX_POOL_DATA)
+ netif_wake_queue (priv->dev);
+}
+
+/**
+ * Handle a data buffer from firmware.
+ * \param priv PLC device private context
+ * \param data_addr data physical address
+ * \param data_length data length in byte
+ */
+void
+frame_rx_data (plcdrv_t *priv, uint32_t data_addr,
+ uint32_t data_length);
+
+/**
+ * Handle a private MME buffer from firmware.
+ * \param priv PLC device private context
+ * \param data_addr data physical address
+ * \param data_length data length in byte
+ */
+void
+frame_rx_mme_priv (plcdrv_t *priv, uint32_t data_addr,
+ uint32_t data_length);
+
+/**
+ * Handle a debug dump buffer from firmware.
+ * \param priv PLC device private context
+ * \param data_addr data physical address
+ * \param data_length data length in byte
+ */
+void
+frame_rx_debug_dump (plcdrv_t *priv, uint32_t data_addr,
+ uint32_t data_length);
+
+/**
+ * Transmit a data frame to firmware.
+ * \param skb frame structure
+ * \param dev device structure
+ * \return error code
+ */
+int
+frame_tx_data (struct sk_buff *skb, struct net_device *dev);
+
+/**
+ * Transmit a private MME frame to firmware.
+ * \param priv PLC device private context
+ * \param skb frame structure
+ */
+void
+frame_tx_mbx_mme_priv (plcdrv_t *priv, struct sk_buff *skb);
+
+/**
+ * Transmit a debug dump buffer to firmware.
+ * \param priv PLC device private context
+ * \param buffer debug dump virtual address
+ * \param length debug dump buffer length
+ */
+void
+frame_tx_mbx_debug_dump (plcdrv_t *priv, uint32_t *buffer,
+ unsigned int length);
+
+#endif /* inc_frame_h */
diff --git a/cleopatre/devkit/plcdrv/inc/hal.h b/cleopatre/devkit/plcdrv/inc/hal.h
deleted file mode 100644
index db99ef1479..0000000000
--- a/cleopatre/devkit/plcdrv/inc/hal.h
+++ /dev/null
@@ -1,207 +0,0 @@
-#ifndef hal_h
-#define hal_h
-/* Cleopatre project {{{
- *
- * Copyright (C) 2008 Spidcom
- *
- * <<<Licence>>>
- *
- * }}} */
-/**
- * \file hal.h
- * \brief interfaces for mailbox layer
- * \ingroup Cleopatre - PlcDrv
- *
- * this file content interfaces and exported macros, variables... For the
- * Hardware Abstraction Layer
- */
-
-#ifdef __UTESTS__
-# include "common.h"
-# include <linux/spinlock.h>
-#else
-# include <linux/spinlock.h>
-#endif
-
-#define A2L_RING_MASK (A2L_RING_SIZE-1)
-#define L2A_RING_MASK (L2A_RING_SIZE-1)
-
-#define MAX_MSG_SIZE (2 * 4) //2 words : one for header and one for data
-
-/** hal layer context structure */
-struct halctx {
- volatile uint32_t *A2L_ptr;
- volatile uint32_t *L2A_ptr;
- volatile uint32_t *L2A_head;
-#ifdef __UTESTS__
- volatile uint32_t *A2L_head;
- volatile uint32_t *L2A_tail;
-#else
- const volatile uint32_t *A2L_head;
- const volatile uint32_t *L2A_tail;
-#endif
- volatile uint32_t *A2L_tail;
- volatile uint32_t *A2L_it;
- volatile uint32_t *L2A_it;
- volatile uint32_t *L2A_it_mask;
- uint32_t L2A_max_length; // current L2A queue length for stats
- uint32_t A2L_max_length; // current A2L queue length for stats
- //Spin lock to protect concurrent access to the HAL mailbox.
- spinlock_t lock;
-};
-
-/**
- * Initialize the hal layer.
- *
- * \param init user information.
- * \return hal context.
- */
-struct halctx* halmbx_init(struct init_info *info);
-
-/**
- * UnInitialize the hal layer.
- *
- * \param ctx hal context.
- * \return error code.
- */
-int halmbx_uninit(struct halctx *ctx);
-
-/**
- * Check if Leon to Arm mailbox queue is empty.
- *
- * \param ctx hal context.
- * \return 0 if the queue is empty.
- */
-int halmbx_L2Amail_not_empty_queue(struct halctx *ctx);
-
-/**
- * Check Arm to Leon mailbox queue status.
- *
- * \param ctx hal context.
- * \return queue state.
- */
-int halmbx_A2Lmail_status_queue(struct halctx *ctx);
-
-/**
- * Check Leon to Arm mailbox queue status.
- *
- * \param ctx hal context.
- * \return queue state.
- */
-int halmbx_L2Amail_status_queue(struct halctx *ctx);
-
-/**
- * Copy message to the ring buffer.
- *
- * \param ctx hal context.
- * \param message pointer to the message align on 32bits.
- * \param size message size in bytes and align on 32bits.
- * \return error code.
- */
-int halmbx_copy_to_ring(struct halctx *ctx, uint32_t *message, int size);
-
-/**
- * Copy message from the ring buffer.
- *
- * \param ctx hal context.
- * \param message pointer to the message align on 32bits.
- * \param size max message size in bytes and align on 32bits.
- * \return error code.
- */
-int halmbx_copy_from_ring(struct halctx *ctx, uint32_t *message, int size);
-
-/**
- * Update the ring management for Leon to Arm mailbox (TX).
- *
- * \param ctx hal context.
- * \param size real size of the last proceed message.
- * \return error code.
- */
-int halmbx_A2Lmail_update(struct halctx *ctx, int size);
-
-/**
- * Update the ring management for Arm to Leon mailbox (RX).
- *
- * \param ctx hal context.
- * \param size real size of the last proceed message.
- * \return error code.
- */
-int halmbx_L2Amail_update(struct halctx *ctx, int size);
-
-/**
- * Enable the Arm to Leon Acknowledge Interrupt.
- *
- * \param ctx hal context.
- */
-void A2La_it_enable(struct halctx *ctx);
-
-/**
- * Enable the Leon to Arm Trigger Interrupt.
- *
- * \param ctx hal context.
- */
-void L2At_it_enable(struct halctx *ctx);
-
-/**
- * Enable the Leon to Arm Watchdog Interrupt.
- *
- * \param ctx hal context.
- */
-void L2Awd_it_enable(struct halctx *ctx);
-
-/**
- * Disable the Arm to Leon Acknowledge Interrupt.
- *
- * \param ctx hal context.
- */
-void A2La_it_disable(struct halctx *ctx);
-
-/**
- * Disable the Leon to Arm Trigger Interrupt.
- *
- * \param ctx hal context.
- */
-void L2At_it_disable(struct halctx *ctx);
-
-/**
- * Set the Arm to Leon Interrupt.
- *
- * \param ctx hal context.
- */
-void set_A2Lt_interrupt(struct halctx *ctx);
-
-/**
- * Disable the Leon to Arm Watchdog Interrupt.
- *
- * \param ctx hal context.
- */
-void L2Awd_it_disable(struct halctx *ctx);
-
-/**
- * Set the Arm to Leon acknowledge Interrupt.
- *
- * \param ctx hal context.
- */
-void set_L2Aa_interrupt(struct halctx *ctx);
-
-/**
- * Clear the Leon to Arm Interrupt.
- *
- * \param ctx hal context.
- */
-void clr_L2At_interrupt(struct halctx *ctx);
-
-/**
- * Clear the Leon to Arm acknowledge Interrupt.
- *
- * \param ctx hal context.
- */
-void clr_A2La_interrupt(struct halctx *ctx);
-
-/**
- * Clear the Leon to Arm watchdog Interrupt.
- *
- * \param ctx hal context.
- */
-void clr_L2Awd_interrupt(struct halctx *ctx);
-#endif /* hal_h */
diff --git a/cleopatre/devkit/plcdrv/inc/ipmbox.h b/cleopatre/devkit/plcdrv/inc/ipmbox.h
new file mode 100644
index 0000000000..3128e495ef
--- /dev/null
+++ b/cleopatre/devkit/plcdrv/inc/ipmbox.h
@@ -0,0 +1,116 @@
+#ifndef inc_ipmbox_h
+#define inc_ipmbox_h
+/* Cleopatre project {{{
+ *
+ * Copyright (C) 2011 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file inc/ipmbox.h
+ * \brief Interfaces for IPMBox layer.
+ * \ingroup plcdrv
+ *
+ * This file contains interfaces used to access the different queues defined
+ * for IPMBox: DATA, EMPTY_BUF and MBX (all existing in TX and RX).
+ */
+
+#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+
+#include "common/ipmbox/queue.h"
+#include "common/ipmbox/registers.h"
+
+/**
+ * Budget for RX part.
+ */
+#define IPMBOX_RX_BUDGET 64
+
+/**
+ * IPMBox context.
+ */
+typedef struct ipmbox_ctx_t
+{
+ /** Queues, by types & directions. */
+ ipmbox_queue_t queue[IPMBOX_QUEUE_TYPE_NB][IPMBOX_QUEUE_DIRECTION_NB];
+ /** IPMBox hardware registers. */
+ volatile ipmbox_registers_t *regs;
+ /** Shared memory virtual start pointer. */
+ uint32_t *shared_mem_virt_base_ptr;
+ /** Shared memory physical start address. */
+ dma_addr_t shared_mem_phy_base_addr;
+ /** Shared memory size. */
+ size_t shared_mem_size;
+ /** Only needed lock for A2L mbx queue. */
+ spinlock_t a2l_mbx_queue_lock;
+} ipmbox_ctx_t;
+
+/**
+ * Initialize the IPMBox layer.
+ * \param ctx IPMBox context
+ * \param dev netdevice structure
+ * \param it_mbx_handler handler for mailbox interrupt
+ * \param it_wd_handler handler for watchdog interrupt
+ * \return error code
+ */
+int
+ipmbox_init (ipmbox_ctx_t *ctx, struct net_device *dev,
+ irq_handler_t it_mbx_handler, irq_handler_t it_wd_handler);
+
+/**
+ * Un-initialize the IPMBox layer.
+ * \param ctx IPMBox context
+ * \param dev netdevice structure
+ */
+void
+ipmbox_uninit (ipmbox_ctx_t *ctx, struct net_device *dev);
+
+/**
+ * Check if IPMBox has been synchronized by firmware.
+ * \param ctx IPMBox context
+ * \return true if synchronized, false otherwise
+ */
+bool
+ipmbox_is_synchronized (ipmbox_ctx_t *ctx);
+
+/**
+ * Receive messages from IPMBox queues.
+ * \param napi NAPI context
+ * \param budget RX budget in messages (only for data & mbx)
+ * \return total number of messages treated
+ */
+int
+ipmbox_receive (struct napi_struct *napi, int budget);
+
+/**
+ * Send empty buffer(s) to firmware.
+ * \param ctx IPMBox context
+ * \param buffer_addr buffers' addresses to send
+ * \param buffer_nb number of buffer to send
+ */
+void
+ipmbox_send_empty_buf (ipmbox_ctx_t *ctx, uint32_t buffer_addr[],
+ unsigned int buffer_nb);
+
+/**
+ * Send a data frame to firmware.
+ * \param ctx IPMBox context
+ * \param buffer_addr buffer address to send
+ * \param header corresponding data header
+ */
+void
+ipmbox_send_data (ipmbox_ctx_t *ctx, uint32_t buffer_addr, uint32_t header);
+
+/**
+ * Send a mailbox message to firmware.
+ * \param ctx IPMBox context
+ * \param buffer_addr buffer address to send
+ * \param header corresponding mailbox header
+ */
+void
+ipmbox_send_mbx (ipmbox_ctx_t *ctx, uint32_t buffer_addr, uint32_t header);
+
+#endif /* inc_ipmbox_h */
diff --git a/cleopatre/devkit/plcdrv/inc/linux_drv.h b/cleopatre/devkit/plcdrv/inc/linux_drv.h
deleted file mode 100644
index 71f541a0ad..0000000000
--- a/cleopatre/devkit/plcdrv/inc/linux_drv.h
+++ /dev/null
@@ -1,200 +0,0 @@
-#ifndef linux_drv_h
-#define linux_drv_h
-/* Cleopatre project {{{
- *
- * Copyright (C) 2008 Spidcom
- *
- * <<<Licence>>>
- *
- * }}} */
-/**
- * \file linux_drv.h
- * \brief interfaces for linux_drv layer
- * \ingroup Cleopatre - PlcDrv
- *
- * this file content interfaces and exported macros, variables... For the
- * linux_drv layer
- */
-
-#ifndef __UTESTS__
-#include <linux/netdevice.h>
-#include <net/seq_check.h>
-#else
-#include <linux/types.h>
-#include <linux/wait.h>
-#include <linux/interrupt.h>
-#include <linux/dma-mapping.h>
-#include <linux/netdevice.h>
-#endif
-
-#include "common.h"
-#include "hal.h"
-
-/** */
-enum pkt_dest {
- OTHER = 0,
- NETLINK_DRV = 1,
- NETLINK_MME = 2,
-};
-
-/** why do you want to free the buffer */
-enum free_reason {
- RX_DROP = 0,
- TX_DROP = 1,
- TX_COMPLETE = 2,
-};
-
-/** Data direction. */
-enum data_direction {
- DATA_TO_FW = DMA_TO_DEVICE,
- DATA_FROM_FW = DMA_FROM_DEVICE,
- DATA_BIDIR = DMA_BIDIRECTIONAL,
-};
-
-/** Define plc.rom informations */
-#define ROM_INFO_DELIMITER '\n'
-#define ROM_INFO_KEY_DELIMITER ':'
-#define ROM_INFO_MAX_SIZE 1024
-#define ROM_VERSION_SIZE 64
-#define ROM_VERSION_KEY "version"
-
-/** PLC private stats */
-struct plc_stats {
- uint32_t tx_pool; // number of allocated skbuff for Tx
- uint32_t rx_pool; // number of allocated skbuff for Rx
-};
-
-/** Select function private data */
-struct plc_select
-{
- atomic_t plc_error;
- wait_queue_head_t wq;
-};
-
-/** Driver private data */
-struct net_priv
-{
- struct plc_select plc_select;
- uint32_t num_mbx_it;
- uint32_t num_mbx_it_ack;
- uint32_t num_mbx_it_wd;
- uint32_t phys_ring_base_addr;
- uint32_t virt_ring_base_addr;
- spinlock_t lock;
- struct list_head list_head_skbs;
- struct net_device_stats stats;
- struct plc_stats plc_stats;
- struct tasklet_struct tasklet_it_rx;
- struct halctx *halctx;
- struct sock *nl_drv_sock;
- struct sock *nl_mme_sock;
- uint32_t nl_drv_pid;
- uint32_t nl_mme_pid;
- uint8_t firmware_written;
- uint8_t version[ROM_VERSION_SIZE];
-
-#ifdef CONFIG_SEQ_CHECK
- struct seq_check_ctx seq_check_ctx;
-#endif
-};
-
-/**
- * Debug dump buffer length of the buffer received from Cesar by the mailbox.
- * Set to -1 at initialization and to 0 when there is nothing more to read
- * from Cesar.
- */
-extern int debug_dump_buffer_length_received;
-/**
- * Debug dump buffer location.
- * When debug dump buffer has been sent to Cesar, this variable is set to
- * true, otherwise, this is set to false.
- */
-extern bool debug_dump_waiting_for_buffer;
-/**
- * Debug dump buffer length allocated by Cleopatra.
- */
-extern const uint debug_dump_buffer_length;
-/**
- * Debug dump wait queue shared between the mailbox received and the read
- * proc from the kernel.
- */
-extern wait_queue_head_t debug_dump_wait_queue;
-
-/**
- * Receive a packet.
- *
- * \param packet packet pointer.
- * \param length packet length.
- * \param dest packet destination.
- * \return error code.
- */
-int plcdrv_rx(void *packet, int length, enum pkt_dest dst);
-
-/**
- * Release a buffer.
- *
- * \param packet packet pointer.
- * \param reason freeing reason.
- * \return error code.
- */
-int free_buffer(void *packet, enum free_reason reason);
-
-/**
- * Allocate a buffer to the pool
- * and send to the communication layer.
- *
- * \param type type of buffer to allocate.
- * \return error code.
- */
-int alloc_buffer(enum buffer_type type);
-
-/**
- * Allocate a debug dump buffer for CESAR and return its.
- *
- * \param debug_dump_buffer the debug dump buffer to allocate
- * \param debug_dump_buffer_length the length of the debug dump buffer
- * \return error code
- *
- * \note the address returned is a virtual one, not a physical one: you need
- * to convert it before using it.
- */
-int alloc_debug_dump_buffer(void **debug_dump_buffer,
- int debug_dump_buffer_length);
-
-/**
- * Free a debug dump buffer.
- *
- * \param debug_dump_buffer the debug dump buffer to free
- * \param debug_dump_buffer_length the length of the debug dump buffer
- *
- * \note the address of debug_dump_buffer should be a virtual one.
- */
-void free_debug_dump_buffer(void *debug_dump_buffer,
- int debug_dump_buffer_length);
-
-/**
- * Changed a virtual address to its corresponding physical address
- * and manage the cache.
- *
- * \param addr buffer virtual address.
- * \param len buffer length.
- * \param data_dir data direction.
- * \return buffer physical address.
- */
-uint32_t prepare_buffer_to_hw(uint32_t addr, unsigned int len,
- enum data_direction data_dir);
-
-/**
- * Changed a physical address to its corresponding virtual address
- * and manage the cache.
- *
- * \param addr buffer physical address.
- * \param len buffer length.
- * \param data_dir data direction.
- * \return buffer virtual address.
- */
-uint32_t prepare_buffer_from_hw(uint32_t addr, unsigned int len,
- enum data_direction data_dir);
-
-#endif /* linux_drv_h */
-
diff --git a/cleopatre/devkit/plcdrv/inc/mailbox.h b/cleopatre/devkit/plcdrv/inc/mailbox.h
deleted file mode 100644
index f176eab9a4..0000000000
--- a/cleopatre/devkit/plcdrv/inc/mailbox.h
+++ /dev/null
@@ -1,97 +0,0 @@
-#ifndef mailbox_h
-#define mailbox_h
-/* Cleopatre project {{{
- *
- * Copyright (C) 2008 Spidcom
- *
- * <<<Licence>>>
- *
- * }}} */
-/**
- * \file mailbox.h
- * \brief interfaces for mailbox layer
- * \ingroup Cleopatre - PlcDrv
- *
- * this file content interfaces and exported macros, variables... For the
- * mailbox layer
- */
-
-#include "common.h"
-
-#ifdef __UTESTS__
-#include <linux/netdevice.h>
-#endif
-
-/**
- * Initialize the mailbox layer.
- *
- * \param info initialisation structure.
- * \param dev network device structure
- * \return error code.
- */
-int mailbox_init(struct init_info *info, struct net_device *dev);
-
-/**
- * UnInitialize the mailbox layer.
- */
-int mailbox_uninit(void);
-
-/**
- * Prepare the mailbox message
- * corresponding to a sending frame
- * and send it to CESAR.
- *
- * \param pointer the data message pointer.
- * \param length the length of the data message.
- * \param prio message priority.
- * \param type type of message.
- * \return error code.
- */
-int mailbox_send(void *pointer, uint32_t length, uint32_t prio, enum buffer_type type);
-
-/**
- * Prepare the mailbox message
- * corresponding to a new buffer
- * and send it to CESAR.
- *
- * \param pointer the buffer pointer.
- * \param type type of message.
- * \return error code.
- */
-int mailbox_buffer_add(void *pointer, enum buffer_type type);
-
-/**
- * Send a DEBUG_DUMP to CESAR (using the mailbox).
- *
- * \param buffer pointer to the buffer to send to CESAR
- * \param length length of the buffer to send to CESAR
- * \return error code
- *
- * \note this function is quite similar to mailbox_buffer_add or mailbox_send
- * (its actually does the same thing as the last one), but only support
- * mailbox message type DEBUG_DUMP.
- */
-int mailbox_send_debug_dump(void *buffer, uint length);
-
-/**
- * Manage the Hardware after knowing
- * that a txdone arrived.
- *
- * \return error code.
- */
-int mailbox_txdone(void);
-
-/**
- * Receive everything from the HLE layer.
- *
- * \param budget budget before giving hand to caller
- * \return error code.
- */
-int mailbox_receive(unsigned int *budget);
-
-/**
- * Receive part for interrupt context.
- */
-void mailbox_receive_isr(void);
-
-#endif /* mailbox_h */
diff --git a/cleopatre/devkit/plcdrv/inc/plcdrv.h b/cleopatre/devkit/plcdrv/inc/plcdrv.h
new file mode 100644
index 0000000000..a72fe455d2
--- /dev/null
+++ b/cleopatre/devkit/plcdrv/inc/plcdrv.h
@@ -0,0 +1,126 @@
+#ifndef inc_plcdrv_h
+#define inc_plcdrv_h
+/* Cleopatre project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file inc/plcdrv.h
+ * \brief Interfaces for plcdrv layer.
+ * \ingroup plcdrv
+ *
+ * Main structure of the PLC driver module and some small modules.
+ */
+
+#include <linux/types.h>
+#include <linux/netdevice.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/skbuff.h>
+#include <linux/wait.h>
+#include <linux/cdev.h>
+#include <linux/proc_fs.h>
+#include <net/sock.h>
+#include <net/seq_check.h>
+
+#include "debug_dump.h"
+#include "ipmbox.h"
+
+#include "common/ipmbox/protocol.h"
+#include "common/ipmbox/msg.h"
+
+/** Define plc.rom informations. */
+#define ROM_VERSION_SIZE 64
+
+/**
+ * TX pool size for data.
+ */
+#define PLCDRV_TX_POOL_DATA (IPMBOX_PROTOCOL_QUEUE_SIZE_A2L_DATA / \
+ IPMBOX_MSG_DATA_WORDS - 1)
+
+/**
+ * RX pool size.
+ */
+#define PLCDRV_RX_POOL (IPMBOX_PROTOCOL_QUEUE_SIZE_A2L_EMPTY_BUF \
+ / IPMBOX_MSG_EMPTY_BUF_WORDS - 1)
+
+/**
+ * Watchdog private context.
+ */
+typedef struct wd_t
+{
+ /** Set to 1 when WD IT triggered. */
+ atomic_t expired;
+ /** User space process sleeping on wait queue for WD IT triggering. */
+ wait_queue_head_t wq;
+} wd_t;
+
+/**
+ * PLC private stats.
+ */
+typedef struct plcdrv_stats_t
+{
+ /** No headroom in skb to FW, need to re-allocate it. */
+ atomic_t skb_to_fw_no_headroom;
+} plcdrv_stats_t;
+
+/**
+ * Netlink context.
+ */
+typedef struct netlink_t
+{
+ /** Socket. */
+ struct sock *sock;
+ /** PID. */
+ uint32_t pid;
+} netlink_t;
+
+/**
+ * PLC driver private data.
+ */
+struct plcdrv_t
+{
+ /** PLC driver net device. */
+ struct net_device *dev;
+ /** PLC driver net device stats. */
+ struct net_device_stats stats;
+ /** IPMbox context. */
+ ipmbox_ctx_t ipmbox;
+ /** NAPI context. */
+ struct napi_struct napi;
+ /** Data TX pool (buffers given to firmware for transmission to PLC). */
+ struct sk_buff_head tx_pool_data;
+ /** MME TX pool (buffers given to firmware for transmission to PLC). */
+ struct sk_buff_head tx_pool_mme;
+ /** RX pool (buffers waiting to be filled by firmware). */
+ struct sk_buff_head rx_pool;
+ /** Watchdog context. */
+ wd_t wd;
+ /** PLC driver stats. */
+ plcdrv_stats_t plcdrv_stats;
+ /** Netlink for PLCd. */
+ netlink_t nl_plcd;
+ /** Netlink for Managerd. */
+ netlink_t nl_managerd;
+ /** PLC driver character device. */
+ struct cdev cdev;
+ /** PLC driver trace character device. */
+ struct cdev cdev_trace;
+ /** PLC driver global device number. */
+ dev_t dev_number;
+ /** PLC driver directory in ProcFS. */
+ struct proc_dir_entry *proc_dir_plc;
+ /** Debug dump context. */
+ debug_dump_t debug_dump;
+ /** Version of PLC firmware. */
+ uint8_t version[ROM_VERSION_SIZE];
+#ifdef CONFIG_SEQ_CHECK
+ /** Sequence check context. */
+ struct seq_check_ctx seq_check_ctx;
+#endif
+};
+
+#endif /* inc_plcdrv_h */
diff --git a/cleopatre/devkit/plcdrv/inc/plcdrv_forward.h b/cleopatre/devkit/plcdrv/inc/plcdrv_forward.h
new file mode 100644
index 0000000000..70e768d773
--- /dev/null
+++ b/cleopatre/devkit/plcdrv/inc/plcdrv_forward.h
@@ -0,0 +1,18 @@
+#ifndef inc_plcdrv_forward_h
+#define inc_plcdrv_forward_h
+/* Cleopatre project {{{
+ *
+ * Copyright (C) 2012 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file inc/plcdrv_forward.h
+ * \brief PLC driver private context forward declaration.
+ * \ingroup plcdrv
+ */
+
+typedef struct plcdrv_t plcdrv_t;
+
+#endif /* inc_plcdrv_forward_h */
diff --git a/cleopatre/devkit/plcdrv/inc/processing.h b/cleopatre/devkit/plcdrv/inc/processing.h
deleted file mode 100644
index 64f607d46e..0000000000
--- a/cleopatre/devkit/plcdrv/inc/processing.h
+++ /dev/null
@@ -1,112 +0,0 @@
-#ifndef processing_h
-#define processing_h
-/* Cleopatre project {{{
- *
- * Copyright (C) 2008 Spidcom
- *
- * <<<Licence>>>
- *
- * }}} */
-/**
- * \file processing.h
- * \brief interfaces for processing layer
- * \ingroup Cleopatre - PlcDrv
- *
- * this file content interfaces and exported macros, variables... For the
- * processing layer
- */
-
-#include "common.h"
-
-/** Define HPAV Ethernet type */
-#define ETH_P_HPAV 0x88E1
-/** Define MME fcall type */
-#define HPAV_MME_P_FCALL 0xA006
-/** Define MME sniffer type */
-#define HPAV_MME_P_SNIFFER 0xA02C
-#define HPAV_MME_P_VS_BASE 0xA000
-#define HPAV_MME_P_DRV_BASE 0xB000
-#define HPAV_MME_P_MS_BASE 0x8000
-
-/** processing layer context structure */
-struct processctx {
- uint8_t board_addr[ETH_ALEN];
- uint8_t broadcast_addr[ETH_ALEN];
-};
-
-/**
- * Find the Ethernet MME type.
- *
- * \param eth_frame Ethernet frame pointer.
- * \return HPAV MME type.
- */
-uint16_t get_eth_mme_type(uint8_t* eth_frame);
-
-/**
- * Initialize the processing layer.
- *
- * \param info initialisation structure.
- * \param dev network device structure
- * \return error code.
- */
-int processing_init(struct init_info *info, struct net_device *dev);
-
-/**
- * UnInitialize the processing layer.
- *
- * \return error code.
- */
-int processing_uninit(void);
-
-/**
- * Processing procedure to add a buffer to CESAR.
- *
- * \param pointer buffer pointer.
- * \param type type of the message pointed.
- * \return error code.
- */
-int processing_buffer_add(void *pointer, enum buffer_type type);
-
-/**
- * Processing procedure to release a buffer from CESAR.
- *
- * \param pointer buffer pointer.
- * \return error code.
- */
-int processing_buffer_free(void *pointer);
-
-/**
- * Processing procedure for a A->L message.
- *
- * \param pointer buffer pointer.
- * \param length length of the message pointed.
- * \return status queue.
- */
-int processing_send(void *pointer, int length, buffer_type_t type);
-
-/**
- * Processing procedure for a L->A message.
- *
- * \param pointer buffer pointer.
- * \param length length of the message pointed.
- * \param type type of message.
- * \return error code.
- */
-int processing_receive(void *pointer, int length, enum buffer_type type);
-
-/**
- * Send a debug dump buffer to be filled by leon.
- *
- * \param buffer debug dump buffer to be filled.
- * \return error code.
- */
-int processing_debug_dump_buffer_send(void *buffer);
-
-/**
- * Process a debug dump buffer for a leon to arm message.
- * \param buffer debug dump buffer received
- * \param length length of debug dump buffer received
- */
-int processing_debug_dump_buffer_receive(void *buffer, int length);
-
-#endif /* processing_h */
diff --git a/cleopatre/devkit/plcdrv/inc/registers.h b/cleopatre/devkit/plcdrv/inc/registers.h
index eff1d95c9c..75e1f865ee 100644
--- a/cleopatre/devkit/plcdrv/inc/registers.h
+++ b/cleopatre/devkit/plcdrv/inc/registers.h
@@ -1,5 +1,5 @@
-#ifndef registers_h
-#define registers_h
+#ifndef inc_registers_h
+#define inc_registers_h
/* Cleopatre project {{{
*
* Copyright (C) 2008 Spidcom
@@ -8,79 +8,59 @@
*
* }}} */
/**
- * \file registers.h
- * \brief all hardware definitions
- * \ingroup Cleopatre - PlcDrv
+ * \file inc/registers.h
+ * \brief All hardware definitions.
+ * \ingroup plcdrv
*
- * this file contents registers definitions for mailboxes.
+ * This file contains hardware registers definitions.
*/
-/** Physical Base Address for Mailboxes */
-#define MBX_BASE_ADDR 0xC8030000
+/** Physical base address for mailboxes. */
+#define IPMBOX_BASE_ADDR 0xC8030000
-/** Number of registers present for mailboxes */
-#define NB_MBX_REGISTERS 8
+/** Physical base address for firmware watchdog. */
+#define LEON_WD_BASE_ADDR 0x8000004C
-/** Registers Offsets for Mailboxes */
-#define MBX_A2L_IT_OFFSET 0x00
-#define MBX_A2L_IT_MASK_OFFSET 0x04
-#define MBX_L2A_IT_OFFSET 0x08
-#define MBX_L2A_IT_MASK_OFFSET 0x0C
-#define MBX_A2L_HEAD_OFFSET 0x14
-#define MBX_A2L_TAIL_OFFSET 0x10
-#define MBX_L2A_HEAD_OFFSET 0x1C
-#define MBX_L2A_TAIL_OFFSET 0x18
-
-/** Bit fields for A2L_IT register */
-#define A2L_IT (1<<0)
-#define A2L_IT_ACK (1<<1)
-
-/** Bit fields for L2A_IT register */
-#define L2A_IT (1<<0)
-#define L2A_IT_ACK (1<<1)
-#define L2A_IT_WKP (1<<2)
-#define L2A_IT_WD (1<<3)
-
-
-/** Physical Base Address for Leon Watchdog */
-#define LEON_WD_BASE_ADDR 0x8000004C
-
-/** Set leon watchdog timeout in seconds */
-#define LEON_WD_REFRESH(val) ((val*1000000)>0xFFFFFF ? val*1000000 : 0xFFFFFF) //WD freq=1MHz
+/**
+ * Set firmware watchdog timeout in seconds.
+ * Watchdog frequency is 1Mhz.
+ */
+#define LEON_WD_REFRESH(val) (((val) * 1000000) > 0xFFFFFF ? \
+ (val) * 1000000 : 0xFFFFFF)
-/** Physical Base Address for Leon DSU controller */
-#define LEON_DSU_CTRL_BASE_ADDR 0x90000000
+/** Physical base address for firmware DSU controller. */
+#define LEON_DSU_CTRL_BASE_ADDR 0x90000000
-/** Bit fields for Leon DSU */
-#define LEON_DSU_TE (1<<0)
-#define LEON_DSU_DCM (1<<1)
-#define LEON_DSU_BT (1<<2)
-#define LEON_DSU_FT (1<<3)
-#define LEON_DSU_BE (1<<4)
-#define LEON_DSU_BW (1<<5)
-#define LEON_DSU_BS (1<<6)
-#define LEON_DSU_BN (1<<7)
-#define LEON_DSU_BD (1<<8)
-#define LEON_DSU_BX (1<<9)
-#define LEON_DSU_BZ (1<<10)
-#define LEON_DSU_DE (1<<11)
-#define LEON_DSU_DM (1<<12)
-#define LEON_DSU_EB (1<<13)
-#define LEON_DSU_EE (1<<14)
-#define LEON_DSU_PE (1<<15)
-#define LEON_DSU_SS (1<<16)
-#define LEON_DSU_LR (1<<17)
-#define LEON_DSU_DR (1<<18)
-#define LEON_DSU_RE (1<<19)
-#define LEON_DSU_DCNT(val) ((val&0xFFF)<<20)
+/** Bit fields for firmware DSU. */
+#define LEON_DSU_TE (1<<0)
+#define LEON_DSU_DCM (1<<1)
+#define LEON_DSU_BT (1<<2)
+#define LEON_DSU_FT (1<<3)
+#define LEON_DSU_BE (1<<4)
+#define LEON_DSU_BW (1<<5)
+#define LEON_DSU_BS (1<<6)
+#define LEON_DSU_BN (1<<7)
+#define LEON_DSU_BD (1<<8)
+#define LEON_DSU_BX (1<<9)
+#define LEON_DSU_BZ (1<<10)
+#define LEON_DSU_DE (1<<11)
+#define LEON_DSU_DM (1<<12)
+#define LEON_DSU_EB (1<<13)
+#define LEON_DSU_EE (1<<14)
+#define LEON_DSU_PE (1<<15)
+#define LEON_DSU_SS (1<<16)
+#define LEON_DSU_LR (1<<17)
+#define LEON_DSU_DR (1<<18)
+#define LEON_DSU_RE (1<<19)
+#define LEON_DSU_DCNT(val) (((val) & 0xFFF) << 20)
-/** Physical Base Address for Leon TRACE controller */
-#define LEON_TRACE_CTRL_BASE_ADDR 0x90000004
+/** Physical base address for firmware TRACE controller. */
+#define LEON_TRACE_CTRL_BASE_ADDR 0x90000004
-/** Bit fields for Leon TRACE */
-#define LEON_TRACE_PROC_IDX(val) ((val&0xFFF)<<0)
-#define LEON_TRACE_AHB_IDX(val) ((val&0xFFF)<<12)
-#define LEON_TRACE_PROC_EN (1<<24)
-#define LEON_TRACE_AHB_EN (1<<25)
+/** Bit fields for firmware TRACE. */
+#define LEON_TRACE_PROC_IDX(val) (((val) & 0xFFF) << 0)
+#define LEON_TRACE_AHB_IDX(val) (((val) & 0xFFF) << 12)
+#define LEON_TRACE_PROC_EN (1 << 24)
+#define LEON_TRACE_AHB_EN (1 << 25)
-#endif /* registers_h */
+#endif /* inc_registers_h */
diff --git a/cleopatre/devkit/plcdrv/src/boot_params.c b/cleopatre/devkit/plcdrv/src/boot_params.c
index d33b0e7e87..484e8c2b73 100644
--- a/cleopatre/devkit/plcdrv/src/boot_params.c
+++ b/cleopatre/devkit/plcdrv/src/boot_params.c
@@ -6,9 +6,9 @@
*
* }}} */
/**
- * \file boot_params.c
- * \brief support for passing boot parameters to Cesar.
- * \ingroup Cleopatre - PlcDrv
+ * \file src/boot_params.c
+ * \brief Support for passing boot parameters to Cesar.
+ * \ingroup plcdrv
*
*/
@@ -77,12 +77,12 @@ static int plcdrv_add_boot_param(char *params_str, const char *param_name,
strcat(params_str, param_value);
}
- return 0;
+ return 0;
overflow:
- printk (KERN_ERR
- "Boot parameters string too long (while adding default parameter)\n");
- return -1;
+ printk (KERN_ERR
+ "Boot parameters string too long (while adding default parameter)\n");
+ return -1;
}
/**
diff --git a/cleopatre/devkit/plcdrv/src/debug_dump.c b/cleopatre/devkit/plcdrv/src/debug_dump.c
new file mode 100644
index 0000000000..8e9f42e313
--- /dev/null
+++ b/cleopatre/devkit/plcdrv/src/debug_dump.c
@@ -0,0 +1,197 @@
+/* Cleopatre project {{{
+ *
+ * Copyright (C) 2012 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/debug_dump.c
+ * \brief Debug dump.
+ * \ingroup plcdrv
+ */
+#include <linux/kernel.h>
+#include <linux/compiler.h>
+#include <linux/bug.h>
+#include <linux/errno.h>
+#include <linux/gfp.h>
+
+#include "frame.h"
+#include "plcdrv.h"
+
+#include "debug_dump.h"
+
+/**
+ * Allocate a debug dump buffer for firmware.
+ * \param debug_dump_buffer the debug dump buffer to allocate
+ * \param debug_dump_buffer_length the length of the debug dump buffer
+ * \return error code
+ */
+static inline int
+debug_dump_buffer_alloc (void **debug_dump_buffer,
+ int debug_dump_buffer_length)
+{
+ /* Check parameters. */
+ BUG_ON (!debug_dump_buffer || *debug_dump_buffer);
+
+ /* Allocate debug dump buffer. */
+ *debug_dump_buffer = kmalloc (debug_dump_buffer_length,
+ GFP_ATOMIC | GFP_DMA);
+
+ /* If allocation failed. */
+ if (!(*debug_dump_buffer))
+ return -ENOMEM;
+
+ return 0;
+}
+
+/**
+ * Free a debug dump buffer.
+ * \param debug_dump_buffer the debug dump buffer to free
+ */
+static inline void
+debug_dump_buffer_free (void *debug_dump_buffer)
+{
+ /* Check parameters. */
+ BUG_ON (!debug_dump_buffer);
+
+ /* Free. */
+ kfree (debug_dump_buffer);
+}
+
+int
+debug_dump_read (plcdrv_t *priv, char __user *buf, size_t count,
+ loff_t *f_pos)
+{
+ static void *debug_dump_buffer = NULL;
+ static uint debug_dump_buffer_remaining_length = 0;
+ uint copied_data;
+ int error;
+
+ /* Check used parameter. */
+ BUG_ON (!f_pos);
+ BUG_ON (!priv);
+ /* Sanity check. */
+ BUG_ON (!priv->debug_dump.opened);
+
+ /* Allocate debug dump buffer if needed. */
+ if (!debug_dump_buffer)
+ {
+ /* Allocate. */
+ error = debug_dump_buffer_alloc (&debug_dump_buffer,
+ DEBUG_DUMP_BUFFER_LENGTH);
+ if (error != 0)
+ return error;
+ }
+
+ /* If we have nothing to copy to user. */
+ if (debug_dump_buffer_remaining_length == 0)
+ {
+ /* We need to handle the case where the buffer has been received while
+ * this code is not executed anymore (ctrl+c for example). There can
+ * be three cases:
+ * - we need to send a new buffer to Cesar because we do not have
+ * one to deal with,
+ * - the buffer has already been sent (debug_dump_waiting_for_buffer
+ * is set to true) but still not received
+ * (debug_dump_buffer_length_received set to -1): we need to wait.
+ * - the buffer has been received (debug_dump_buffer_length_received
+ * is not -1) but not processed by this code
+ * (debug_dump_waiting_for_buffer is set to false).
+ *
+ * Give debug dump buffer to firmware if this not already done. */
+ if (priv->debug_dump.waiting_for_buffer == false)
+ {
+ /* Debug dump buffer has been given to firmware. */
+ priv->debug_dump.buffer_length_received = -1;
+ priv->debug_dump.waiting_for_buffer = true;
+ frame_tx_mbx_debug_dump (priv, debug_dump_buffer,
+ DEBUG_DUMP_BUFFER_LENGTH);
+ }
+
+ /* Go to sleep until debug dump buffer has returned. */
+ error = wait_event_interruptible
+ (priv->debug_dump.wait_queue,
+ priv->debug_dump.buffer_length_received != -1);
+ if (error != 0)
+ return error;
+
+ /* Debug dump buffer received from firmware. */
+ priv->debug_dump.waiting_for_buffer = false;
+ debug_dump_buffer_remaining_length
+ = priv->debug_dump.buffer_length_received;
+ }
+
+ /* If this is not the last debug dump buffer. */
+ if (debug_dump_buffer_remaining_length)
+ {
+ BUG_ON ((int) debug_dump_buffer_remaining_length
+ > priv->debug_dump.buffer_length_received);
+ /* How much can we copy? */
+ copied_data = min (count, debug_dump_buffer_remaining_length);
+ /* Copy debug dump buffer to buffer for reading. */
+ if (copy_to_user (buf, debug_dump_buffer
+ + (priv->debug_dump.buffer_length_received
+ - debug_dump_buffer_remaining_length),
+ copied_data))
+ {
+ return -EFAULT;
+ }
+ debug_dump_buffer_remaining_length -= copied_data;
+
+ }
+ else
+ {
+ /* Finish, let's clean. */
+ debug_dump_buffer_free (debug_dump_buffer);
+ debug_dump_buffer = NULL;
+ debug_dump_buffer_remaining_length = 0;
+
+ copied_data = 0;
+ }
+
+ /* Update what have been done. */
+ *f_pos += copied_data;
+ return copied_data;
+}
+
+int
+debug_dump_open (plcdrv_t *priv)
+{
+ /* Check parameter. */
+ BUG_ON (!priv);
+
+ /* Open only one time. */
+ if (!priv->debug_dump.opened)
+ {
+ priv->debug_dump.opened = true;
+ return 0;
+ }
+ else
+ return -EBUSY;
+}
+
+void
+debug_dump_release (plcdrv_t *priv)
+{
+ /* Check parameter. */
+ BUG_ON (!priv);
+
+ BUG_ON (priv->debug_dump.opened == false);
+
+ /* Device now closed. */
+ priv->debug_dump.opened = false;
+}
+
+void
+debug_dump_init (plcdrv_t *priv)
+{
+ /* Check parameter. */
+ BUG_ON (!priv);
+
+ /* Initialise context. */
+ priv->debug_dump.buffer_length_received = -1;
+ priv->debug_dump.waiting_for_buffer = false;
+ init_waitqueue_head (&priv->debug_dump.wait_queue);
+ priv->debug_dump.opened = false;
+}
diff --git a/cleopatre/devkit/plcdrv/src/firmware.c b/cleopatre/devkit/plcdrv/src/firmware.c
new file mode 100644
index 0000000000..be7934163e
--- /dev/null
+++ b/cleopatre/devkit/plcdrv/src/firmware.c
@@ -0,0 +1,193 @@
+/* Cleopatre project {{{
+ *
+ * Copyright (C) 2012 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/firmware.c
+ * \brief Firmware loading support.
+ * \ingroup plcdrv
+ */
+#include <asm/arch/platform.h>
+#include <linux/bug.h>
+#include <linux/firmware.h>
+
+#include "firmware.h"
+#include "plcdrv.h"
+#include "boot_params.h"
+
+/** Define plc.rom informations */
+#define ROM_INFO_DELIMITER '\n'
+#define ROM_INFO_KEY_DELIMITER ':'
+#define ROM_INFO_MAX_SIZE 1024
+#define ROM_VERSION_KEY "version"
+
+/**
+ * Find the start and size of the ROM info area.
+ * \param file_end end of the file
+ * \param[out] rom_info_start start of the ROM info area
+ * \param[out] rom_info_size size of the ROM info area
+ */
+static inline void
+firmware_find_rom_info (uint8_t *file_end, uint8_t **rom_info_start,
+ size_t *rom_info_size)
+{
+ uint8_t *infos;
+ uint32_t infos_limit;
+ int infos_size;
+
+ /* Check parameters. */
+ BUG_ON (!file_end);
+ BUG_ON (!rom_info_start);
+ BUG_ON (!rom_info_size);
+
+ infos = file_end;
+ infos_limit = (uint32_t) infos - ROM_INFO_MAX_SIZE;
+ infos_size = 0;
+
+ /* No informations area. */
+ if (*infos != ROM_INFO_DELIMITER)
+ goto not_found;
+
+ /* Find start of informations area
+ * We are at the end. We go back until we find a delimiter of the
+ * beginning of the area. */
+ while (((uint32_t) infos > (infos_limit - 1))
+ && ((*infos != ROM_INFO_DELIMITER)
+ || (*(infos - 1) != ROM_INFO_DELIMITER)))
+ {
+ infos--;
+ infos_size++;
+ }
+
+ /* Informations not found. */
+ if ((uint32_t) infos <= infos_limit)
+ goto not_found;
+
+ /* There may be more than one delimiter at the beginning of the area.
+ * As we need to kwow the exact start of the area, we go up until we see
+ * all the delimiters. */
+ BUG_ON (*infos != ROM_INFO_DELIMITER);
+ while (((uint32_t) infos > infos_limit - 1)
+ && (*infos == ROM_INFO_DELIMITER))
+ {
+ infos--;
+ infos_size++;
+ }
+
+ *rom_info_start = infos + 1;
+ *rom_info_size = infos_size;
+
+ return;
+
+not_found:
+ *rom_info_start = NULL;
+ *rom_info_size = 0;
+
+ return;
+}
+
+/**
+ * Get plc.rom version number.
+ * \param rom_info_start start of the ROM info area.
+ * \param rom_info_size size of the ROM info area.
+ * \param[out] version version result buffer.
+ */
+static inline void
+firmware_get_rom_version (uint8_t *rom_info_start, size_t rom_info_size,
+ uint8_t *version)
+{
+ uint8_t *infos, *p;
+
+ /* Check parameters. */
+ BUG_ON (version == NULL);
+ if (!rom_info_start || !rom_info_size)
+ goto unknown;
+
+ infos = rom_info_start;
+
+ /* Skip delimiters at the beginning of the info area. */
+ while ((infos < (rom_info_start + rom_info_size)
+ && (*infos == ROM_INFO_DELIMITER)))
+ {
+ infos++;
+ }
+
+ if (infos >= (rom_info_start + rom_info_size))
+ goto unknown;
+
+ /* Split informations, format is "key: value\n". */
+ for (p = infos; p < (rom_info_start + rom_info_size); p++)
+ {
+ if ((*p == ROM_INFO_DELIMITER) || (*p == ROM_INFO_KEY_DELIMITER))
+ *p = '\0';
+ }
+
+ /* Find version key. */
+ while (strcasecmp (infos, ROM_VERSION_KEY))
+ {
+ /* Skip the key. */
+ infos += strlen (infos) + 1;
+ /* Skip the associated value. */
+ infos += strlen (infos) + 1;
+ }
+
+ /* Skip version key. */
+ infos += strlen (infos) + 1;
+
+ /* Copy version value without first space. */
+ strncpy (version, infos + 1, ROM_VERSION_SIZE);
+
+ return;
+
+unknown:
+ strcpy (version, "Unknown");
+
+ return;
+}
+
+int
+firmware_load (struct net_device *dev)
+{
+ plcdrv_t *priv = netdev_priv (dev);
+ int ret;
+ const struct firmware *fw;
+ uint8_t *plc_fw_base = (uint8_t *) VIRT_PLCCODE_BASE;
+ uint8_t *rom_info_start;
+ size_t rom_info_size;
+
+ ret = request_firmware (&fw, "plc", &dev->dev);
+ if (ret != 0)
+ return ret;
+
+ /* Copy firmware. */
+ memcpy (plc_fw_base, fw->data, fw->size);
+
+ /* Get boundaries of firmware info region. */
+ firmware_find_rom_info (plc_fw_base + fw->size - 1,
+ &rom_info_start, &rom_info_size);
+
+ /* Get firmware version number. */
+ firmware_get_rom_version (rom_info_start, rom_info_size,
+ priv->version);
+
+ if (rom_info_start)
+ {
+ /* End of the .bin file that became the .rom file. */
+ uint8_t *bin_eof = rom_info_start;
+
+ /* Pass boot parameters.
+ * As a consequence, the rom info that was written to Cesar memory
+ * will be overwritten. But that is not a problem because the rom
+ * info is not used on Cesar side. */
+ plcdrv_pass_boot_params (bin_eof);
+ }
+
+ /* Release firmware memory. */
+ release_firmware (fw);
+
+ return 0;
+}
+
diff --git a/cleopatre/devkit/plcdrv/src/frame.c b/cleopatre/devkit/plcdrv/src/frame.c
new file mode 100644
index 0000000000..5f19eaaaa9
--- /dev/null
+++ b/cleopatre/devkit/plcdrv/src/frame.c
@@ -0,0 +1,440 @@
+/* Cleopatre project {{{
+ *
+ * Copyright (C) 2012 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/frame.c
+ * \brief Interfaces to send/receive/alloc/free frames for firmware.
+ * \ingroup plcdrv
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/wait.h>
+#include <linux/if_vlan.h>
+#include <linux/if_ether.h>
+#include <linux/dma-mapping.h>
+#include <linux/netlink.h>
+#include <linux/jiffies.h>
+#include <linux/bug.h>
+#include <net/seq_check.h>
+
+#include "plcdrv.h"
+#include "debug_dump.h"
+
+#include "frame.h"
+
+#include "common/ipmbox/msg.h"
+#include "common/ipmbox/protocol.h"
+
+/** Define HPAV MME format */
+#define ETH_MME_VERSION_OFFSET (sizeof (struct ethhdr))
+#define ETH_MME_VERSION_SIZE (1)
+#define ETH_MME_TYPE_OFFSET (ETH_MME_VERSION_OFFSET + ETH_MME_VERSION_SIZE)
+
+#define HPAV_MME_P_DRV_BASE 0xB000
+
+/** Define VLAN format */
+#define VLAN_CFI_MASK 0x1000
+#define VLAN_PRIO_MASK 0xe000
+#define VLAN_VID_SHIFT 0
+#define VLAN_CFI_SHIFT 12
+#define VLAN_PRIO_SHIFT 13
+
+#define VLAN_PRIO(tci) ((tci & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT)
+#define VLAN_MAX_PRIO 7
+#define VLAN_MME_PRIO 6 /** VLAN priorities 6 and 7 correspond to CAP 3. */
+
+/** Frame info magic word. */
+#define FRAME_INFO_MAGIC 0xc742a74e
+
+/**
+ * Frame information stored before data (in headroom of the skb).
+ * This way, we are able to get the corresponding skb from the data buffer.
+ */
+typedef struct frame_info_t
+{
+ /** Magic word. */
+ uint32_t magic;
+ /** Corresponding skb. */
+ struct sk_buff *skb;
+ /** \warning must be smaller than NET_SKB_PAD. */
+} frame_info_t;
+
+/** Compute an aligned pointer address before data in skb headroom. */
+#define FRAME_INFO_PTR_ALIGN(data) \
+ ((frame_info_t *) \
+ (((uint32_t) (data) - sizeof (frame_info_t)) & ~(sizeof (uint32_t) - 1)))
+
+/**
+ * Find the Ethernet MME type.
+ * \param eth_frame Ethernet frame pointer
+ * \return HPAV MME type
+ */
+static inline uint16_t
+frame_get_eth_mme_type (uint8_t *eth_frame)
+{
+ /* Warning: mme type is stored in little endian. */
+ return *(uint16_t *) (eth_frame + ETH_MME_TYPE_OFFSET);
+}
+
+/**
+ * Find the Ethernet type.
+ * \param eth_frame Ethernet frame pointer.
+ * \return Ethernet type.
+ */
+static inline uint16_t
+frame_get_eth_type (uint8_t *eth_frame)
+{
+ struct ethhdr *eth = (struct ethhdr *) eth_frame;
+ return ntohs (eth->h_proto);
+}
+
+/**
+ * Prepare a sk buff for sending to firmware.
+ * \param priv PLC device private context
+ * \param skb sk buff to send to firmware
+ * \param data_dir DMA_TO_DEVICE if skb is filled with data to send,
+ * DMA_FROM_DEVICE if skb is empty and to be filled by firmware
+ * \return physical address to send to firmware
+ */
+static uint32_t
+frame_skb_to_fw (plcdrv_t *priv, struct sk_buff *skb,
+ enum dma_data_direction data_dir)
+{
+ frame_info_t *frame_info;
+ size_t len;
+ int delta = 0;
+
+ /* Reserve some space to store the skb pointer. */
+ if (skb_headroom (skb) < NET_SKB_PAD)
+ delta = NET_SKB_PAD;
+ if (delta || skb_header_cloned (skb))
+ {
+ atomic_inc (&priv->plcdrv_stats.skb_to_fw_no_headroom);
+ BUG_ON (pskb_expand_head (skb, delta, 0, GFP_ATOMIC));
+ }
+ /* Store frame information. */
+ frame_info = FRAME_INFO_PTR_ALIGN (skb->data);
+ frame_info->magic = FRAME_INFO_MAGIC;
+ frame_info->skb = skb;
+
+ /* Get length. */
+ if (data_dir == DMA_TO_DEVICE)
+ len = skb->len;
+ else
+ len = PKT_BUF_SZ;
+
+ /* Map in DMA zone, dma_map_single is always happy on our architecture. */
+ return dma_map_single (NULL, skb->data, len, data_dir);
+}
+
+/**
+ * Retrieve sk buff from a buffer received from firmware.
+ * \param buffer physical buffer address received from firmware
+ * \param data_dir DMA_TO_DEVICE if buffer is empty, DMA_FROM_DEVICE if a
+ * filled buffer is received with data
+ * \return associated sk buff or NULL on invalid magic word
+ */
+static struct sk_buff *
+frame_skb_from_fw (uint32_t buffer, enum dma_data_direction data_dir)
+{
+ struct sk_buff *skb;
+ frame_info_t *frame_info;
+ size_t len;
+
+ /* Retrieve frame information. */
+ frame_info = FRAME_INFO_PTR_ALIGN (dma_to_virt (NULL, buffer));
+ if (frame_info->magic != FRAME_INFO_MAGIC)
+ return NULL;
+ skb = frame_info->skb;
+ /* Clear magic. */
+ frame_info->magic = 0;
+
+ /* Get length. */
+ if (data_dir == DMA_TO_DEVICE)
+ len = skb->len;
+ else
+ len = PKT_BUF_SZ;
+
+ /* Unmap from DMA zone. */
+ dma_unmap_single (NULL, buffer, len, data_dir);
+
+ return skb;
+}
+
+bool
+frame_buffer_alloc (plcdrv_t *priv)
+{
+ struct sk_buff *skb;
+ uint32_t skb_data_addr[PLCDRV_RX_POOL];
+ unsigned int i;
+ unsigned int new_skb_nb = PLCDRV_RX_POOL - skb_queue_len (&priv->rx_pool);
+
+ for (i = 0; i < new_skb_nb; i++)
+ {
+ /* Allocate an sk_buff. */
+ skb = dev_alloc_skb (PKT_BUF_SZ);
+ if (!skb)
+ break;
+
+ /* Add it to the RX pool. */
+ __skb_queue_head (&priv->rx_pool, skb);
+
+ /* Store sk buff physical data address to send it to firmware. */
+ skb_data_addr[i] = frame_skb_to_fw (priv, skb, DMA_FROM_DEVICE);
+ }
+
+ /* Send it to firmware. */
+ if (i)
+ ipmbox_send_empty_buf (&priv->ipmbox, skb_data_addr, i);
+
+ if (skb_queue_len (&priv->rx_pool) != PLCDRV_RX_POOL)
+ return false;
+ return true;
+}
+
+void
+frame_buffer_free (plcdrv_t *priv, uint32_t buffer)
+{
+ struct sk_buff *skb;
+ struct sk_buff_head *pool;
+
+ /* Get skb. */
+ skb = frame_skb_from_fw (buffer, DMA_TO_DEVICE);
+
+ if (!skb)
+ {
+ printk (KERN_CRIT "bad buffer in frame_buffer_free\n");
+ return;
+ }
+
+ /* Remove it from the right TX pool. */
+ pool = *(struct sk_buff_head **) skb->cb;
+ __skb_unlink (skb, pool);
+
+ /* Free it. */
+ kfree_skb (skb);
+}
+
+void
+frame_rx_data (plcdrv_t *priv, uint32_t data_addr,
+ uint32_t data_length)
+{
+ struct sk_buff *skb;
+
+ /* Retrieve skb. */
+ skb = frame_skb_from_fw (data_addr, DMA_FROM_DEVICE);
+
+ if (!skb)
+ {
+ printk (KERN_CRIT "bad buffer in frame_rx_data\n");
+ return;
+ }
+
+ /* Remove it from the RX pool, this is not our buffer anymore. */
+ __skb_unlink (skb, &priv->rx_pool);
+
+ /* Prepare skb for linux receive level. */
+ skb->dev = priv->dev;
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ skb_put (skb, data_length);
+ skb->protocol = eth_type_trans (skb, priv->dev);
+
+ /* Check sequence number on receive. */
+ seq_check_rx (&priv->seq_check_ctx, skb);
+
+ /* Pass data to the Linux internal receive level. */
+ netif_receive_skb (skb);
+}
+
+void
+frame_rx_mme_priv (plcdrv_t *priv, uint32_t data_addr,
+ uint32_t data_length)
+{
+ struct sk_buff *skb, *nlskb;
+ struct nlmsghdr *nlh;
+ netlink_t *nl;
+
+ /* Retrieve skb. */
+ skb = frame_skb_from_fw (data_addr, DMA_FROM_DEVICE);
+
+ if (!skb)
+ {
+ printk (KERN_CRIT "bad buffer in frame_rx_mme_priv\n");
+ return;
+ }
+
+ /* Remove it from the RX pool, this is not our buffer anymore. */
+ __skb_unlink (skb, &priv->rx_pool);
+
+ /* Prepare sk buff for linux receive level. */
+ skb->dev = priv->dev;
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ skb_put (skb, data_length);
+
+ /* Allocate a new sk_buff to add netlink header. */
+ nlskb = alloc_skb (NLMSG_LENGTH (skb->len), GFP_ATOMIC);
+ if (!nlskb)
+ goto msg_failure;
+
+ /* Fill netlink header. */
+ nlh = NLMSG_PUT (nlskb, 0, 0, NLMSG_DONE,
+ NLMSG_LENGTH (skb->len) - sizeof(*nlh));
+ NETLINK_CB (nlskb).pid = 0; /* From kernel. */
+ NETLINK_CB (nlskb).dst_group = 0; /* Unicast. */
+
+ /* Fill this new sk_buff with the old one after netlink header. */
+ memcpy (NLMSG_DATA (nlh), skb->data, skb->len);
+
+ /* Suppress old sk_buff. */
+ kfree_skb (skb);
+
+ /* Get destination netlink. */
+ BUG_ON (data_length <= ETH_MME_TYPE_OFFSET);
+ if (frame_get_eth_mme_type (skb->data) >= HPAV_MME_P_DRV_BASE)
+ nl = &priv->nl_plcd;
+ else
+ nl = &priv->nl_managerd;
+
+ /* Send to netlink. */
+ if (netlink_unicast (nl->sock, nlskb, nl->pid, MSG_DONTWAIT) < 0)
+ goto nlmsg_failure;
+
+ return;
+
+ /* nlmsg_failure is used by NLMSG_PUT (yeark!). */
+nlmsg_failure:
+ kfree_skb (nlskb);
+msg_failure:
+ kfree_skb (skb);
+}
+
+void
+frame_rx_debug_dump (plcdrv_t *priv, uint32_t data_addr,
+ uint32_t data_length)
+{
+ /* Check parameter. */
+ BUG_ON (data_length > DEBUG_DUMP_BUFFER_LENGTH);
+
+ /* Sanity check. */
+ BUG_ON (priv->debug_dump.waiting_for_buffer == false);
+
+ /* We do not use data_length here because we have allocated a fixed size,
+ * without regards of the actual size of the data. */
+ dma_unmap_single (NULL, data_addr, DEBUG_DUMP_BUFFER_LENGTH,
+ DMA_FROM_DEVICE);
+
+ /* Copy received length. */
+ priv->debug_dump.buffer_length_received = data_length;
+
+ /* Wake up our process. */
+ wake_up_interruptible (&priv->debug_dump.wait_queue);
+}
+
+int
+frame_tx_data (struct sk_buff *skb, struct net_device *dev)
+{
+ uint16_t eth_type;
+ unsigned int vlan_prio = 0;
+ uint32_t phy_addr;
+ plcdrv_t *priv = netdev_priv (dev);
+
+ /* Check there is an Ethernet header. */
+ if (skb->len < sizeof (struct ethhdr))
+ {
+ /* Packet is too small to be transmitted. Free skb because we have
+ * handled it (ret is ok). */
+ kfree_skb (skb);
+ priv->stats.tx_errors++;
+ priv->stats.tx_fifo_errors++;
+ return NETDEV_TX_OK;
+ }
+
+ /* Sequence check. */
+ seq_check_tx (&priv->seq_check_ctx, skb);
+
+ /* Get VLAN priority. */
+ eth_type = frame_get_eth_type ((uint8_t *) skb->data);
+ if (eth_type == ETH_P_8021Q)
+ vlan_prio
+ = (unsigned int) VLAN_PRIO (ntohs (((struct vlan_ethhdr *)
+ skb->data)->h_vlan_TCI));
+ else if (eth_type == ETH_P_HPAV)
+ vlan_prio = VLAN_MME_PRIO;
+
+ /* TX pool full? This can not happen because netif queue would have been
+ * stopped before data queue is full. */
+ BUG_ON (skb_queue_len (&priv->tx_pool_data) == PLCDRV_TX_POOL_DATA);
+
+ /* Update TX pool. */
+ __skb_queue_head (&priv->tx_pool_data, skb);
+ *(struct sk_buff_head **) skb->cb = &priv->tx_pool_data;
+
+ /* Map it to DMA. */
+ phy_addr = frame_skb_to_fw (priv, skb, DMA_TO_DEVICE);
+
+ /* Send it to firmware. */
+ ipmbox_send_data (&priv->ipmbox, phy_addr,
+ ipmbox_msg_create_header_data (skb->len, vlan_prio));
+
+ /* Update trans start to jiffies. */
+ dev->trans_start = jiffies;
+
+ /* Queue is now full? */
+ if (skb_queue_len (&priv->tx_pool_data) == PLCDRV_TX_POOL_DATA)
+ {
+ /* Stop queue. */
+ netif_stop_queue (dev);
+ }
+ return NETDEV_TX_OK;
+}
+
+void
+frame_tx_mbx_mme_priv (plcdrv_t *priv, struct sk_buff *skb)
+{
+ uint32_t phy_addr, header;
+
+ /* Check parameters. */
+ BUG_ON (!priv);
+ BUG_ON (!skb);
+
+ /* Update TX pool, with lock. */
+ skb_queue_head (&priv->tx_pool_mme, skb);
+ *(struct sk_buff_head **) skb->cb = &priv->tx_pool_mme;
+
+ /* Get physical address. */
+ phy_addr = frame_skb_to_fw (priv, skb, DMA_TO_DEVICE);
+
+ /* Build message header. */
+ header = ipmbox_msg_create_header_mme_priv (skb->len);
+
+ /* Send to firmware. */
+ ipmbox_send_mbx (&priv->ipmbox, phy_addr, header);
+}
+
+void
+frame_tx_mbx_debug_dump (plcdrv_t *priv, uint32_t *buffer,
+ unsigned int length)
+{
+ uint32_t phy_addr, header;
+
+ /* Check parameters. */
+ BUG_ON (!priv);
+ BUG_ON (!buffer);
+ BUG_ON (!length);
+
+ /* Get physical address. */
+ phy_addr = dma_map_single (NULL, buffer, length, DMA_FROM_DEVICE);
+
+ /* Build message header. */
+ header = ipmbox_msg_create_header_debug_dump (length);
+
+ /* Send to firmware. */
+ ipmbox_send_mbx (&priv->ipmbox, phy_addr, header);
+}
diff --git a/cleopatre/devkit/plcdrv/src/hal.c b/cleopatre/devkit/plcdrv/src/hal.c
deleted file mode 100644
index c95818c7a3..0000000000
--- a/cleopatre/devkit/plcdrv/src/hal.c
+++ /dev/null
@@ -1,473 +0,0 @@
-/* Cleopatre project {{{
- *
- * Copyright (C) 2008 Spidcom
- *
- * <<<Licence>>>
- *
- * }}} */
-/**
- * \file hal.c
- * \brief HAL Layer.
- * \ingroup Cleopatre - PlcDrv
- *
- * this layer provide all Hardware Abstraction:
- * registers, interrupts.
- */
-
-#ifndef __UTESTS__
-# include <linux/delay.h>
-#else
-# include <linux/delay.h>
-# include <linux/bitops.h>
-# include <linux/kernel.h>
-#endif
-#include "mailbox.h"
-#include "hal.h"
-#include "registers.h"
-#include "common.h"
-
-/** Define Debug/Trace Level */
-#define TRACE(...) if(test_bit(TRACE_HAL, (const volatile unsigned long*)&trace)) printk(KERN_INFO "SPC300: HAL : " __VA_ARGS__)
-
-/** Time Out for leon start */
-#define TOUT_LEON_START 2000 //in ms
-/** Step Time Out for leon start */
-#define TOUT_LEON_START_STEP 20 //in ms
-
-/** Our global context */
-static struct halctx glbctx;
-
-/**
- * Initialize the hal layer.
- *
- * \param init user information.
- * \return hal context.
- */
-struct halctx* halmbx_init(struct init_info *info)
-{
- uint32_t timeout=0;
-
- //Check arguments
- if(info == NULL)
- return NULL;
-
- //Initialise context structure
- memset (&glbctx, '\0', sizeof(glbctx));
- glbctx.A2L_ptr = (volatile uint32_t*)info->ring_base_addr;
- glbctx.L2A_ptr = (volatile uint32_t*)(info->ring_base_addr+A2L_RING_SIZE);
- glbctx.A2L_head = (volatile uint32_t*)(info->mbx_reg_base_addr+MBX_A2L_HEAD_OFFSET);
- glbctx.A2L_tail = (volatile uint32_t*)(info->mbx_reg_base_addr+MBX_A2L_TAIL_OFFSET);
- glbctx.L2A_head = (volatile uint32_t*)(info->mbx_reg_base_addr+MBX_L2A_HEAD_OFFSET);
- glbctx.L2A_tail = (volatile uint32_t*)(info->mbx_reg_base_addr+MBX_L2A_TAIL_OFFSET);
- glbctx.A2L_it = (volatile uint32_t*)(info->mbx_reg_base_addr+MBX_A2L_IT_OFFSET);
- glbctx.L2A_it = (volatile uint32_t*)(info->mbx_reg_base_addr+MBX_L2A_IT_OFFSET);
- glbctx.L2A_it_mask = (volatile uint32_t*)(info->mbx_reg_base_addr+MBX_L2A_IT_MASK_OFFSET);
-
- //Initialise head and tail offset pointers for arm access
- *glbctx.A2L_tail = info->phys_ring_base_addr;
- *glbctx.L2A_head = (info->phys_ring_base_addr + A2L_RING_SIZE);
-
- //If we are here Leon code was already downloaded so,
- //we need to start the Leon processor.
- //it must be done after ARM head and tail pointers initialization
- //because LEON use it to set the rings base addresses
- if(!info->debug_mode && (info->launch_leon != NULL))
- (*info->launch_leon)();
-
- //Now the Leon is started we have to wait leon mailbox initialization
- //before continuing
- while((*glbctx.A2L_head != *glbctx.A2L_tail) &&
- (*glbctx.L2A_head != *glbctx.L2A_tail))
- {
- msleep_interruptible(TOUT_LEON_START_STEP);
- if(!info->debug_mode)
- {
- timeout += TOUT_LEON_START_STEP;
- if(timeout >= TOUT_LEON_START)
- return NULL;
- }
- }
-
- return &glbctx;
-}// halmbx_init
-
-/**
- * UnInitialize the hal layer.
- *
- * \param ctx hal context.
- * \return error code.
- */
-int halmbx_uninit(struct halctx *ctx)
-{
- //Check arguments
- if(ctx == NULL)
- return -1;
- else
- return 0;
- //TODO:Stop Leon
-}// hal_uninit
-
-/**
- * Set the Arm to Leon Interrupt.
- *
- * \param ctx hal context.
- */
-void set_A2Lt_interrupt(struct halctx *ctx)
-{
- if(ctx == NULL)
- return;
- else
- *ctx->A2L_it |= A2L_IT;
-}// set_A2Lt_interrupt
-
-/**
- * Set the Arm to Leon acknowledge Interrupt.
- *
- * \param ctx hal context.
- */
-void set_L2Aa_interrupt(struct halctx *ctx)
-{
- if(ctx == NULL)
- return;
- else
- *ctx->A2L_it |= A2L_IT_ACK;
-}// set_L2Aa_interrupt
-
-/**
- * Clear the Leon to Arm Interrupt.
- *
- * \param ctx hal context.
- */
- void clr_L2At_interrupt(struct halctx *ctx)
-{
- if(ctx == NULL)
- return;
- else
- *ctx->L2A_it = L2A_IT;
-}// clr_L2At_interrupt
-
-/**
- * Clear the Leon to Arm acknowledge Interrupt.
- *
- * \param ctx hal context.
- */
-void clr_A2La_interrupt(struct halctx *ctx)
-{
- if(ctx == NULL)
- return;
- else
- *ctx->L2A_it = L2A_IT_ACK;
-}//clr_A2La_interrupt
-
-/**
- * Clear the Leon to Arm watchdog Interrupt.
- *
- * \param ctx hal context.
- */
-void clr_L2Awd_interrupt(struct halctx *ctx)
-{
- if(ctx == NULL)
- return;
- else
- *ctx->L2A_it = L2A_IT_WD;
-}//clr_L2Awd_interrupt
-
-/**
- * Enable the Arm to Leon Acknowledge Interrupt.
- *
- * \param ctx hal context.
- */
-void A2La_it_enable(struct halctx *ctx)
-{
- if(ctx == NULL)
- return;
- else
- *ctx->L2A_it_mask &= ~L2A_IT_ACK;
-}// A2La_it_enable
-
-/**
- * Enable the Leon to Arm Trigger Interrupt.
- *
- * \param ctx hal context.
- */
-void L2At_it_enable(struct halctx *ctx)
-{
- if(ctx == NULL)
- return;
- else
- *ctx->L2A_it_mask &= ~L2A_IT;
-}// L2At_it_enable
-
-/**
- * Enable the Leon to Arm Watchdog Interrupt.
- *
- * \param ctx hal context.
- */
-void L2Awd_it_enable(struct halctx *ctx)
-{
- if(ctx == NULL)
- return;
- else
- *ctx->L2A_it_mask &= ~L2A_IT_WD;
-}// L2Awd_it_enable
-
-/**
- * Disable the Arm to Leon Acknowledge Interrupt.
- *
- * \param ctx hal context.
- */
-void A2La_it_disable(struct halctx *ctx)
-{
- if(ctx == NULL)
- return;
- else
- *ctx->L2A_it_mask |= L2A_IT_ACK;
-}// A2La_it_disable
-
-/**
- * Disable the Leon to Arm Trigger Interrupt.
- *
- * \param ctx hal context.
- */
-void L2At_it_disable(struct halctx *ctx)
-{
- if(ctx == NULL)
- return;
- else
- *ctx->L2A_it_mask |= L2A_IT;
-}// L2At_it_disable
-
-/**
- * Disable the Leon to Arm Watchdog Interrupt.
- *
- * \param ctx hal context.
- */
-void L2Awd_it_disable(struct halctx *ctx)
-{
- if(ctx == NULL)
- return;
- else
- *ctx->L2A_it_mask |= L2A_IT_WD;
-}// L2Awd_it_disable
-
-/**
- * Check if Leon to Arm mailbox queue is empty.
- *
- * \param ctx hal context.
- * \return 0 if the queue is empty.
- */
-int halmbx_L2Amail_not_empty_queue(struct halctx *ctx)
-{
- int result;
-
- //Check arguments
- if(ctx == NULL)
- return -1;
-
- result = (int)((*ctx->L2A_head - *ctx->L2A_tail) & L2A_RING_MASK);
- if(result > ctx->L2A_max_length)
- ctx->L2A_max_length = result;
- TRACE("Q empty:%x ; L2A_head=%x ; L2A_tail=%x\n", result, *ctx->L2A_head, *ctx->L2A_tail);
- return result;
-}// halmbx_L2Amail_not_empty_queue
-
-/**
- * Check Arm to Leon mailbox queue status.
- *
- * \param ctx hal context.
- * \return queue state.
- */
-int halmbx_A2Lmail_status_queue(struct halctx *ctx)
-{
- uint32_t space;
-
- //Check arguments
- if(ctx == NULL)
- return -1;
-
- space = ((*ctx->A2L_head - *ctx->A2L_tail) & A2L_RING_MASK);
-
- TRACE("A2L_status=%x\n",space);
-
- if((space != 0) && (space <= MAX_MSG_SIZE))
- return FULL;
- else if ((space != 0) && (space <= (MAX_MSG_SIZE*2)))
- return NEARLY_FULL;
- else
- return NOT_FULL;
-}// halmbx_A2Lmail_status_queue
-
-/**
- * Check Leon to Arm mailbox queue status.
- *
- * \param ctx hal context.
- * \return queue state.
- */
-int halmbx_L2Amail_status_queue(struct halctx *ctx)
-{
- uint32_t space;
-
- //Check arguments
- if(ctx == NULL)
- return -1;
-
- space = ((*ctx->L2A_head - *ctx->L2A_tail) & L2A_RING_MASK);
-
- TRACE("L2A_status=%x\n",space);
-
- if((space != 0) && (space <= MAX_MSG_SIZE))
- return FULL;
- else if ((space != 0) && (space <= (MAX_MSG_SIZE*2)))
- return NEARLY_FULL;
- else
- return NOT_FULL;
-}// halmbx_L2Amail_status_queue
-
-/**
- * Copy message to the ring buffer.
- *
- * \param ctx hal context.
- * \param message pointer to the message align on 32bits.
- * \param size message size in bytes and align on 32bits.
- * \return error code.
- */
-int halmbx_copy_to_ring(struct halctx *ctx, uint32_t *message, int size)
-{
- int i;
- uint32_t tail;
- uint32_t *our_msg;
-
- //Check arguments
- if(ctx == NULL)
- return -1;
-
- //Check size range and alignment on 32bits
- if(size > MAX_MSG_SIZE || size == 0 || size & 0x3)
- return -1;
- //Check pointer and alignment on 32bits
- if(message == NULL || ((uint32_t)message & 0x3))
- return -1;
- else
- our_msg = message;
-
- //Check space in ring just to be sure
- if(halmbx_A2Lmail_status_queue(ctx) == FULL)
- return FULL;
-
- //Convert size for 32bits
- size = (size / sizeof(uint32_t));
-
- //Calculate offset and convert for 32bits
- tail = (*ctx->A2L_tail & A2L_RING_MASK);
- tail = (tail / sizeof(uint32_t));
-
- //Copy the message into the mailbox ring
- for(i=0 ; i<size ; i++)
- {
- *(ctx->A2L_ptr + tail) = *our_msg++;
- tail = ((tail+1) & (A2L_RING_MASK / sizeof(uint32_t)));
- }
- TRACE("Copy to ring= %x, %x\n",*(ctx->A2L_ptr+tail-2), *(ctx->A2L_ptr+tail-1));
- return 0;
-}// halmbx_copy_to_ring
-
-/**
- * Copy message from the ring buffer.
- *
- * \param ctx hal context.
- * \param message pointer to the message align on 32bits.
- * \param size max message size in bytes and align on 32bits.
- * \return error code.
- */
-int halmbx_copy_from_ring(struct halctx *ctx, uint32_t *message, int size)
-{
- int i;
- uint32_t head;
- uint32_t *our_msg;
-
- //Check arguments
- if(ctx == NULL)
- return -1;
-
- //Check size range and alignment on 32bits
- if(size > MAX_MSG_SIZE || size == 0 || size & 0x3)
- return -1;
- //Check pointer and alignment on 32bits
- if(message == NULL || ((uint32_t)message & 0x3))
- return -1;
- else
- our_msg = message;
-
- //Align and convert size for 32bits
- size = (size / sizeof(uint32_t));
-
- //Calculate offset and convert for 32bits
- head = (*ctx->L2A_head & L2A_RING_MASK);
- head = (head / sizeof(uint32_t));
-
- //Copy the message into the mailbox ring
- for(i=0 ; i<size ; i++)
- {
- *our_msg++ = *(ctx->L2A_ptr + head);
- head = ((head+1) & (L2A_RING_MASK / sizeof(uint32_t)));
- }
- TRACE("Copy from ring= %x, %x\n",*(ctx->L2A_ptr+head-2), *(ctx->L2A_ptr+head-1));
- return 0;
-}// halmbx_copy_from_ring
-
-/**
- * Update the ring management for Arm to Leon mailbox (TX).
- *
- * \param ctx hal context.
- * \param size real size in bytes of the last proceed message.
- * \return error code.
- */
-int halmbx_A2Lmail_update(struct halctx *ctx, int size)
-{
- TRACE("halmbx_A2L_update\n");
-
- //Check arguments
- if(ctx == NULL)
- return -1;
-
- //Check size
- if(size == 0)
- return -1;
-
- //Update the TAIL pointer
- *ctx->A2L_tail = ((*ctx->A2L_tail + size) & A2L_RING_MASK) + (*ctx->A2L_tail & ~A2L_RING_MASK);
-
- //Start interrupt
- set_A2Lt_interrupt(ctx);
-
- return 0;
-}// halmbx_A2Lmail_update
-
-/**
- * Update the ring management for Leon to Arm mailbox (RX).
- *
- * \param ctx hal context.
- * \param size real size in bytes of the last proceed message.
- * \return error code.
- */
-int halmbx_L2Amail_update(struct halctx *ctx, int size)
-{
- TRACE("halmbx_L2A_update\n");
-
- //Check arguments
- if(ctx == NULL)
- return -1;
-
- //Check size
- if(size == 0)
- return -1;
-
- //Update the TAIL pointer
- *ctx->L2A_head = ((*ctx->L2A_head + size) & L2A_RING_MASK) + (*ctx->L2A_head & ~L2A_RING_MASK);
-
- //Acknowledge the interrupt
- set_L2Aa_interrupt(ctx);
-
- return 0;
-}// halmbx_L2Amail_update
-
diff --git a/cleopatre/devkit/plcdrv/src/ipmbox.c b/cleopatre/devkit/plcdrv/src/ipmbox.c
new file mode 100644
index 0000000000..567ce3e4a8
--- /dev/null
+++ b/cleopatre/devkit/plcdrv/src/ipmbox.c
@@ -0,0 +1,470 @@
+/* Cleopatre project {{{
+ *
+ * Copyright (C) 2011 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/ipmbox.c
+ * \brief Interfaces for IPMBox layer.
+ * \ingroup plcdrv
+ */
+
+#include <linux/bug.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+
+#include "registers.h"
+#include "plcdrv.h"
+#include "ipmbox.h"
+#include "frame.h"
+#include "common/ipmbox/queue.h"
+#include "common/ipmbox/protocol.h"
+#include "common/ipmbox/msg.h"
+
+/**
+ * Size in words for each queue.
+ */
+static const unsigned int
+ipmbox_queue_size[IPMBOX_QUEUE_TYPE_NB][IPMBOX_QUEUE_DIRECTION_NB] =
+{
+ { IPMBOX_PROTOCOL_QUEUE_SIZE_A2L_MBX,
+ IPMBOX_PROTOCOL_QUEUE_SIZE_L2A_MBX },
+ { IPMBOX_PROTOCOL_QUEUE_SIZE_A2L_EMPTY_BUF,
+ IPMBOX_PROTOCOL_QUEUE_SIZE_L2A_EMPTY_BUF },
+ { IPMBOX_PROTOCOL_QUEUE_SIZE_A2L_DATA,
+ IPMBOX_PROTOCOL_QUEUE_SIZE_L2A_DATA },
+};
+
+/**
+ * Prototype for function to receive message from a queue.
+ * \param priv PLC device private context
+ * \param queue queue to treat
+ * \param budget available budget for this queue
+ * \return consumed budget
+ */
+typedef unsigned int (*ipmbox_queue_receive_t) (plcdrv_t *priv,
+ ipmbox_queue_t *queue,
+ unsigned int budget);
+
+/**
+ * Treat EMPTY_BUF RX queue.
+ * \see ipmbox_queue_receive_t
+ */
+static inline unsigned int
+ipmbox_receive_empty_buf (plcdrv_t *priv, ipmbox_queue_t *queue,
+ unsigned int budget);
+
+/**
+ * Treat DATA RX queue.
+ * \see ipmbox_queue_receive_t
+ */
+static inline unsigned int
+ipmbox_receive_data (plcdrv_t *priv, ipmbox_queue_t *queue,
+ unsigned int budget);
+
+/**
+ * Treat MBX RX queue.
+ * \see ipmbox_queue_receive_t
+ */
+static inline unsigned int
+ipmbox_receive_mbx (plcdrv_t *priv, ipmbox_queue_t *queue,
+ unsigned int budget);
+
+static inline unsigned int
+ipmbox_receive_empty_buf (plcdrv_t *priv, ipmbox_queue_t *queue,
+ unsigned int budget)
+{
+ ipmbox_msg_empty_buf_t msg[IPMBOX_PROTOCOL_QUEUE_SIZE_L2A_EMPTY_BUF
+ / IPMBOX_MSG_EMPTY_BUF_WORDS - 1];
+ unsigned int i, msg_nb;
+
+ msg_nb = ipmbox_queue_get_used_space (queue) / IPMBOX_MSG_EMPTY_BUF_WORDS;
+
+ /* Empty queue. */
+ if (!msg_nb)
+ return 0;
+
+ /* Get message from queue. */
+ ipmbox_queue_copy_from (queue, (uint32_t *) msg,
+ msg_nb * IPMBOX_MSG_EMPTY_BUF_WORDS);
+
+ for (i = 0; i < msg_nb; i++)
+ {
+ /* Call Linux driver layer to free received buffer. */
+ frame_buffer_free (priv, msg[i].buffer_addr);
+ }
+
+ /* As buffers has been freed, it may resume the queue. */
+ frame_wake_queue (priv);
+
+ /* We do not consume any budget. */
+ return 0;
+}
+
+static inline unsigned int
+ipmbox_receive_data (plcdrv_t *priv, ipmbox_queue_t *queue,
+ unsigned int budget)
+{
+ ipmbox_msg_data_t msg[IPMBOX_RX_BUDGET];
+ unsigned int i, msg_nb;
+ uint32_t length;
+
+ msg_nb = ipmbox_queue_get_used_space (queue) / IPMBOX_MSG_DATA_WORDS;
+
+ /* Empty queue. */
+ if (!msg_nb)
+ return 0;
+
+ msg_nb = min (msg_nb, budget);
+
+ ipmbox_queue_copy_from (queue, (uint32_t *) msg,
+ msg_nb * IPMBOX_MSG_DATA_WORDS);
+
+ for (i = 0; i < msg_nb; i++)
+ {
+ /* Get length and send to upper layer. */
+ length = ipmbox_msg_get_data_length (msg[i].header);
+ frame_rx_data (priv, msg[i].buffer_addr, length);
+ }
+
+ /* Reallocate as many buffers as we just received. */
+ frame_buffer_alloc (priv);
+
+ return msg_nb;
+}
+
+static inline unsigned int
+ipmbox_receive_mbx (plcdrv_t *priv, ipmbox_queue_t *queue,
+ unsigned int budget)
+{
+ ipmbox_msg_mbx_t msg[IPMBOX_RX_BUDGET];
+ unsigned int i, msg_nb;
+ uint32_t msg_type, length;
+
+ msg_nb = ipmbox_queue_get_used_space (queue) / IPMBOX_MSG_MBX_WORDS;
+
+ /* Empty queue. */
+ if (!msg_nb)
+ return 0;
+
+ msg_nb = min (msg_nb, budget);
+
+ ipmbox_queue_copy_from (queue, (uint32_t *) msg,
+ msg_nb * IPMBOX_MSG_MBX_WORDS);
+
+ for (i = 0; i < msg_nb; i++)
+ {
+ /* Get message type. */
+ msg_type = ipmbox_msg_get_mbx_type (msg[i].header);
+ if (msg_type == IPMBOX_MSG_MBX_TYPE_MME_PRIV)
+ {
+ /* Get data length. */
+ length = ipmbox_msg_get_mme_priv_length (msg[i].header);
+ frame_rx_mme_priv (priv, msg[i].buffer_addr, length);
+ }
+ else if (msg_type == IPMBOX_MSG_MBX_TYPE_DEBUG_DUMP)
+ {
+ /* Get data length. */
+ length = ipmbox_msg_get_debug_dump_length (msg[i].header);
+ frame_rx_debug_dump (priv, msg[i].buffer_addr, length);
+ }
+ else
+ /* Unsupported message type. */
+ BUG ();
+ }
+
+ /* Reallocate as many buffers as we just received (private MME only). */
+ frame_buffer_alloc (priv);
+
+ return msg_nb;
+}
+
+int
+ipmbox_init (ipmbox_ctx_t *ctx, struct net_device *dev,
+ irq_handler_t it_mbx_handler, irq_handler_t it_wd_handler)
+{
+ uint32_t *shared_mem_base_ptr;
+ uint32_t virt_to_phys_offset;
+ volatile ipmbox_protocol_init_t *init_struct;
+ int i, j, ret;
+
+ /* Check parameters. */
+ BUG_ON (!ctx);
+ BUG_ON (!dev);
+
+ /* Map registers. */
+ dev->base_addr = (unsigned long) ioremap (IPMBOX_BASE_ADDR,
+ sizeof (ipmbox_registers_t));
+ BUG_ON (!dev->base_addr);
+
+ /* Map registers. */
+ ctx->regs = (ipmbox_registers_t *) dev->base_addr;
+ ctx->queue[IPMBOX_QUEUE_DATA][IPMBOX_A2L].ptr
+ = (ipmbox_queue_ptr_t *) &ctx->regs->a2l_tail;
+ ctx->queue[IPMBOX_QUEUE_DATA][IPMBOX_L2A].ptr
+ = (ipmbox_queue_ptr_t *) &ctx->regs->l2a_tail;
+
+ /* Mask all interrupts. */
+ ctx->regs->l2a_it_mask = IPMBOX_L2A_IT | IPMBOX_L2A_IT_ACK
+ | IPMBOX_L2A_IT_WKP | IPMBOX_L2A_IT_WD;
+ /* Clear all interrupts. */
+ ctx->regs->l2a_it = IPMBOX_L2A_IT | IPMBOX_L2A_IT_WD;
+
+ /* Initialise queue sizes. */
+ for (i = 0; i < IPMBOX_QUEUE_TYPE_NB; i++)
+ for (j = 0; j < IPMBOX_QUEUE_DIRECTION_NB; j++)
+ ctx->queue[i][j].size = ipmbox_queue_size[i][j];
+
+ /* Compute shared memory size for queues and queues management pointers
+ * (except for data queue which is managed using registers). */
+ ctx->shared_mem_size = 0;
+ for (i = 0; i < IPMBOX_QUEUE_TYPE_NB; i++)
+ for (j = 0; j < IPMBOX_QUEUE_DIRECTION_NB; j++)
+ ctx->shared_mem_size += ctx->queue[i][j].size * sizeof (uint32_t);
+ ctx->shared_mem_size += sizeof (ipmbox_queue_ptr_t)
+ * (IPMBOX_QUEUE_TYPE_NB - 1) * IPMBOX_QUEUE_DIRECTION_NB;
+
+ /* Allocate shared memory. */
+ ctx->shared_mem_virt_base_ptr = dma_alloc_coherent
+ (NULL, ctx->shared_mem_size, &ctx->shared_mem_phy_base_addr,
+ (GFP_ATOMIC | GFP_DMA));
+ if (!ctx->shared_mem_virt_base_ptr)
+ {
+ ret = -ENOMEM;
+ goto cl_iounmap;
+ }
+ virt_to_phys_offset = ctx->shared_mem_phy_base_addr
+ - (uint32_t) ctx->shared_mem_virt_base_ptr;
+
+ /* Map queues pointers (but not for data, already done in register). */
+ shared_mem_base_ptr = ctx->shared_mem_virt_base_ptr;
+ for (i = 0; i < IPMBOX_QUEUE_DATA; i++)
+ {
+ for (j = 0; j < IPMBOX_QUEUE_DIRECTION_NB; j++)
+ {
+ ctx->queue[i][j].ptr = (ipmbox_queue_ptr_t *) shared_mem_base_ptr;
+ shared_mem_base_ptr += sizeof (ipmbox_queue_ptr_t)
+ / sizeof (uint32_t);
+ }
+ }
+
+ /* Map queues buffers and initialise queues pointers at the same time.*/
+ for (i = 0; i < IPMBOX_QUEUE_TYPE_NB; i++)
+ {
+ for (j = 0; j < IPMBOX_QUEUE_DIRECTION_NB; j++)
+ {
+ ipmbox_queue_t *q = &ctx->queue[i][j];
+ q->base_ptr = shared_mem_base_ptr;
+ q->virt_to_phys_offset = virt_to_phys_offset;
+ BUG_ON (
+ ipmbox_queue_virt_to_phys (q, ctx->shared_mem_virt_base_ptr)
+ != ctx->shared_mem_phy_base_addr);
+ BUG_ON (
+ ipmbox_queue_phys_to_virt (q, ctx->shared_mem_phy_base_addr)
+ != ctx->shared_mem_virt_base_ptr);
+ q->ptr->head = ipmbox_queue_virt_to_phys (q, shared_mem_base_ptr);
+ shared_mem_base_ptr += q->size;
+ q->end_ptr = shared_mem_base_ptr;
+ q->ptr->tail
+ = ipmbox_queue_virt_to_phys (q, shared_mem_base_ptr - 1);
+ }
+ }
+
+ /* Fill initialisation structure. */
+ init_struct = ipmbox_queue_phys_to_virt (
+ &ctx->queue[IPMBOX_QUEUE_DATA][IPMBOX_L2A],
+ ctx->queue[IPMBOX_QUEUE_DATA][IPMBOX_L2A].ptr->head);
+ init_struct->version = IPMBOX_PROTOCOL_VERSION;
+ init_struct->shared_mem = (void *) ctx->shared_mem_phy_base_addr;
+ for (i = 0; i < IPMBOX_QUEUE_TYPE_NB; i++)
+ for (j = 0; j < IPMBOX_QUEUE_DIRECTION_NB; j++)
+ init_struct->queue_size[i][j] = ctx->queue[i][j].size;
+
+ /* Initialise lock. */
+ spin_lock_init (&ctx->a2l_mbx_queue_lock);
+
+ /* Register each interrupt. */
+ ret = request_irq (INT_MBX, it_mbx_handler, 0, dev->name, dev);
+ BUG_ON (ret);
+ ret = request_irq (INT_MBX_WD, it_wd_handler, 0, dev->name, dev);
+ BUG_ON (ret);
+
+ /* Unmask used interrupts. */
+ ctx->regs->l2a_it_mask &= ~(IPMBOX_L2A_IT | IPMBOX_L2A_IT_WD);
+
+ return 0;
+
+cl_iounmap:
+ iounmap ((void *) dev->base_addr);
+ return ret;
+}
+
+void
+ipmbox_uninit (ipmbox_ctx_t *ctx, struct net_device *dev)
+{
+ /* Check arguments. */
+ BUG_ON (!ctx);
+ BUG_ON (!dev);
+
+ /* Mask all interrupts. */
+ ctx->regs->l2a_it_mask = IPMBOX_L2A_IT | IPMBOX_L2A_IT_ACK
+ | IPMBOX_L2A_IT_WKP | IPMBOX_L2A_IT_WD;
+
+ /* Unregister interrupts. */
+ free_irq (INT_MBX, dev);
+ free_irq (INT_MBX_WD, dev);
+
+ /* Free shared memory. */
+ dma_free_coherent (NULL, ctx->shared_mem_size,
+ ctx->shared_mem_virt_base_ptr,
+ ctx->shared_mem_phy_base_addr);
+
+ /* Unmap registers. */
+ iounmap ((void *) dev->base_addr);
+}
+
+bool
+ipmbox_is_synchronized (ipmbox_ctx_t *ctx)
+{
+ int i, j;
+
+ BUG_ON (!ctx);
+
+ for (i = 0; i < IPMBOX_QUEUE_TYPE_NB; i++)
+ {
+ for (j = 0; j < IPMBOX_QUEUE_DIRECTION_NB; j++)
+ {
+ if (ipmbox_queue_get_used_space (
+ &ctx->queue[IPMBOX_QUEUE_DATA][IPMBOX_A2L]))
+ return false;
+ }
+ }
+ return true;
+}
+
+int
+ipmbox_receive (struct napi_struct *napi, int budget)
+{
+ static const ipmbox_queue_receive_t rcv_func_ptr[IPMBOX_QUEUE_TYPE_NB]
+ = { ipmbox_receive_mbx, ipmbox_receive_empty_buf,
+ ipmbox_receive_data };
+ plcdrv_t *priv;
+ struct net_device *dev;
+ ipmbox_ctx_t *ctx;
+ ipmbox_queue_t *queue;
+ int i;
+ int budget_orig = budget;
+
+ BUG_ON (budget > IPMBOX_RX_BUDGET);
+
+ /* Initialise local variables. */
+ priv = container_of (napi, plcdrv_t, napi);
+ ctx = &priv->ipmbox;
+ dev = priv->dev;
+
+ do
+ {
+ /* Clear interrupt before getting message count from any queues in
+ * case an interrupt is triggered after message count is read. */
+ ctx->regs->l2a_it = IPMBOX_L2A_IT;
+
+ for (i = 0; (i < IPMBOX_QUEUE_TYPE_NB) && budget; i++)
+ {
+ /* Get queue. */
+ queue = &ctx->queue[i][IPMBOX_L2A];
+
+ /* Call the function to handle message from the mailbox. */
+ budget -= rcv_func_ptr[i] (priv, queue, budget);
+ }
+ /* If there is still some budgets and interrupt have been triggered,
+ * we can still do some work. */
+ } while (budget && (ctx->regs->l2a_it & IPMBOX_L2A_IT));
+
+ /* If we still have some budget, this mean there is no more work in
+ * queues, let's rest. */
+ if (budget)
+ {
+ /* Exit polling mode. */
+ netif_rx_complete (dev, napi);
+ /* Unmask interrupt for future reception. */
+ ctx->regs->l2a_it_mask &= ~IPMBOX_L2A_IT;
+ }
+
+ /* Return how much work has been done. */
+ return budget_orig - budget;
+}
+
+void
+ipmbox_send_empty_buf (ipmbox_ctx_t *ctx, uint32_t buffer_addr[],
+ unsigned int buffer_nb)
+{
+ ipmbox_queue_t *queue;
+
+ queue = &ctx->queue[IPMBOX_QUEUE_EMPTY_BUF][IPMBOX_A2L];
+ buffer_nb *= IPMBOX_MSG_EMPTY_BUF_WORDS;
+
+ /* Check free space in queue. */
+ BUG_ON (ipmbox_queue_get_free_space (queue) < buffer_nb);
+
+ /* Copy data to queue. */
+ ipmbox_queue_copy_to (queue, buffer_addr, buffer_nb);
+
+ /* Trigger an IT to wake up LEON. */
+ ctx->regs->a2l_it = IPMBOX_A2L_IT_ACK;
+}
+
+void
+ipmbox_send_data (ipmbox_ctx_t *ctx, uint32_t buffer_addr, uint32_t header)
+{
+ ipmbox_msg_data_t msg;
+ ipmbox_queue_t *queue;
+
+ queue = &ctx->queue[IPMBOX_QUEUE_DATA][IPMBOX_A2L];
+
+ /* Build message. */
+ msg.header = header;
+ msg.buffer_addr = buffer_addr;
+
+ /* Check free space in queue. */
+ BUG_ON (ipmbox_queue_get_free_space (queue) < IPMBOX_MSG_DATA_WORDS);
+
+ /* Copy data to queue. */
+ ipmbox_queue_copy_to (queue, (uint32_t *) &msg, IPMBOX_MSG_DATA_WORDS);
+
+ /* Trigger an IT to wake up LEON. */
+ ctx->regs->a2l_it = IPMBOX_A2L_IT;
+}
+
+void
+ipmbox_send_mbx (ipmbox_ctx_t *ctx, uint32_t buffer_addr, uint32_t header)
+{
+ ipmbox_queue_t *queue;
+ ipmbox_msg_mbx_t msg;
+
+ queue = &ctx->queue[IPMBOX_QUEUE_MBX][IPMBOX_A2L];
+
+ /* Build message. */
+ msg.header = header;
+ msg.buffer_addr = buffer_addr;
+
+ /* This can be called for netlink debug dump in task context, lock is
+ * needed. */
+ spin_lock_bh (&ctx->a2l_mbx_queue_lock);
+
+ /* Check free space in queue. */
+ BUG_ON (ipmbox_queue_get_free_space (queue) < IPMBOX_MSG_MBX_WORDS);
+
+ /* Copy data to queue. */
+ ipmbox_queue_copy_to (queue, (uint32_t *) &msg, IPMBOX_MSG_MBX_WORDS);
+
+ spin_unlock_bh (&ctx->a2l_mbx_queue_lock);
+
+ /* Trigger an IT to wake up LEON. */
+ ctx->regs->a2l_it = IPMBOX_A2L_IT;
+}
diff --git a/cleopatre/devkit/plcdrv/src/linux_drv.c b/cleopatre/devkit/plcdrv/src/linux_drv.c
deleted file mode 100644
index d76fa729f0..0000000000
--- a/cleopatre/devkit/plcdrv/src/linux_drv.c
+++ /dev/null
@@ -1,2042 +0,0 @@
-/* Cleopatre project {{{
- *
- * Copyright (C) 2008 Spidcom
- *
- * <<<Licence>>>
- *
- * }}} */
-/**
- * \file linux_drv.c
- * \brief Linux Driver layer
- * \ingroup Cleopatre - PlcDrv
- *
- * This file content the Linux Driver layer, this layer correspond to the
- * interface between the driver and Linux (it's a network Linux driver).
- */
-
-#define DRV_NAME "SPC300"
-#define DRV_LAYER "PLC "
-#define DRV_RELDATE __DATE__ " " __TIME__
-
-
-#ifndef __UTESTS__
-# include <linux/types.h>
-# include <linux/kernel.h>
-# include <linux/module.h>
-# include <linux/afe.h>
-# include <linux/init.h>
-# include <linux/errno.h>
-# include <linux/netdevice.h>
-# include <linux/etherdevice.h>
-# include <asm/semaphore.h>
-# include <linux/kdev_t.h>
-# include <linux/cdev.h>
-# include <linux/fs.h>
-# include <linux/proc_fs.h>
-# include <asm/uaccess.h>
-# include <linux/list.h>
-# include <linux/netlink.h>
-# include <linux/poll.h>
-# include <linux/wait.h>
-# include "net/seq_check.h"
-
-# include <asm/arch/nvram.h>
-# include <asm/arch/hardware/spi.h>
-# include <asm/arch/hardware/regbank.h>
-# include <asm-arm/arch-spc300/ioctl.h>
-#else
-# include <linux/types.h>
-# include <linux/kernel.h>
-# include <linux/init.h>
-# include <linux/mutex.h>
-# include <linux/list.h>
-# include <linux/wait.h>
-# include <linux/afe.h>
-# include <linux/fs.h>
-# include <linux/poll.h>
-# include <linux/bitops.h> /* non present au-dessus, inclus par qqn ? */
-# include <linux/gfp.h> /* non present au-dessus, inclus par qqn ? */
-# include <linux/skbuff.h>
-# include <linux/netlink.h>
-# include <linux/interrupt.h>
-# include <linux/irqreturn.h>
-# include <linux/module.h>
-# include <linux/moduleparam.h>
-# include <linux/kdev_t.h>
-# include <linux/cdev.h>
-# include <linux/if_ether.h>
-# include <linux/errno.h>
-# include <linux/sched.h>
-# include <linux/dma-mapping.h>
-# include <net/net_namespace.h>
-# include <net/seq_check.h>
-
-# include <asm/arch/nvram.h>
-# include <asm/arch/hardware/regbank.h>
-
-/* TODO : move this ! */
-unsigned char plccode[124];
-#define VIRT_PLCCODE_BASE (&plccode[0])
-#define jiffies 1234
-struct net init_net;
-spc300_nvram_t spc300_nvram;
-
-#endif
-
-#include "boot_params.h"
-#include "common.h"
-#include "linux_drv.h"
-#include "processing.h"
-#include "mailbox.h"
-#include "hal.h"
-#include "registers.h"
-
-MODULE_AUTHOR("SPiDCOM Technologies");
-MODULE_DESCRIPTION("SPC300 PLC driver");
-MODULE_LICENSE("SPiDCOM Technologies 2009");
-
-/** Define Debug/Trace Level */
-#define TRACE(...) if(test_bit(TRACE_LINUX, (const volatile unsigned long*)&trace)) printk(KERN_INFO DRV_NAME": "DRV_LAYER": " __VA_ARGS__)
-#define PRINTPKT(a,b,c) if(test_bit(TRACE_PACKET, (const volatile unsigned long*)&trace)) print_packet(a,b,c)
-
-/** Define DSU trace modes */
-#define DSU_TRACE_NONE 0
-#define DSU_TRACE_PROC 1
-#define DSU_TRACE_AHB 2
-#define DSU_TRACE_ALL 3
-
-#define MSEC_PER_JIFFY (1000/HZ) //aligned on HZ, which corresponds to 10ms
-
-/** Define default numbers of buffers */
-#define DEFAULT_NB_DATA_BUFFERS 97
-#define DEFAULT_NB_MME_BUFFERS 1
-#define DEFAULT_NB_INTERFACE_BUFFERS 2
-
-/** Fake address used to detect that a leon_start_addr was provided as a
- * module param. */
-#define INVALID_LEON_START_ADDR 1
-
-/** Max allowed TX message in the same time */
-#define MBX_TX_POOL (L2A_RING_SIZE / MAX_MSG_SIZE / 2)
-
-/** These identify the driver base version */
-static char version[] __devinitdata = DRV_NAME " PLC driver v" DRV_VERSION " (" DRV_RELDATE ")\n";
-
-/** Structure used with Linux list to manage the sk_buff in used */
-struct skb_addr_list {
- struct list_head list;
- uint32_t *pkt_addr;
- struct sk_buff *skb;
-};
-
-/** Our global netlink mutex */
-static DEFINE_MUTEX(plcdrv_nl_mutex);
-
-/** Our global net device */
-static struct net_device *plcdrv_device;
-
-/** Our global Major number */
-static dev_t number;
-/** Our global character device */
-static struct cdev plcdrv_char_dev;
-/** Our trace character device. */
-static struct cdev trace_cdev;
-
-/** Our plc directory in procfs. */
-static struct proc_dir_entry *proc_plc_dir;
-
-/** Our mutex between firmware download and network driver start-up */
-static uint8_t write_called = 0;
-
-/** Parameters for the module */
-static int nb_rx_data_buffers = DEFAULT_NB_DATA_BUFFERS;
-static int nb_rx_mme_buffers = DEFAULT_NB_MME_BUFFERS;
-static int nb_rx_interface_buffers = DEFAULT_NB_INTERFACE_BUFFERS;
-static uint32_t leon_start_addr = INVALID_LEON_START_ADDR;
-static uint32_t dsu_ctrl = (LEON_DSU_BZ | LEON_DSU_BD | LEON_DSU_BW | LEON_DSU_BE | LEON_DSU_TE);
-static uint32_t dsu_trace = DSU_TRACE_PROC;
-static int debug = 0;
-uint32_t trace = 0;
-
-/** For debug dump buffer. */
-int debug_dump_buffer_length_received = -1;
-bool debug_dump_waiting_for_buffer = false;
-const uint debug_dump_buffer_length = 2048;
-DECLARE_WAIT_QUEUE_HEAD(debug_dump_wait_queue);
-bool debug_dump_opened = false;
-
-module_param(nb_rx_data_buffers, int, 0644);
-MODULE_PARM_DESC(nb_rx_data_buffers, "Number of Data Ethernet buffers for PLC -> ARM exchanges");
-module_param(nb_rx_mme_buffers, int, 0644);
-MODULE_PARM_DESC(nb_rx_mme_buffers, "Number of MME Ethernet buffers for PLC -> ARM exchanges");
-module_param(nb_rx_interface_buffers, int, 0644);
-MODULE_PARM_DESC(nb_rx_interface_buffers, "Number of Interface Ethernet buffers for PLC -> ARM exchanges");
-module_param(leon_start_addr, uint, 0644);
-MODULE_PARM_DESC(leon_start_addr, "PLC code start address");
-module_param_string(boot_params, custom_boot_params,
- sizeof(custom_boot_params), 0644);
-MODULE_PARM_DESC(custom_boot_params, "PLC Boot Parameters");
-module_param(dsu_ctrl, uint, 0644);
-MODULE_PARM_DESC(dsu_ctrl, "Configure the PLC Processor debugger");
-module_param(dsu_trace, uint, 0644);
-MODULE_PARM_DESC(dsu_trace, "Configure the PLC Processor trace (0=no ; 1=proc ; 2=AHB ; 3=all)");
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Let's the user start PLC Processor by debugger");
-module_param(trace, uint, 0644);
-
-void plcdrv_uninit(struct net_device *dev);
-
-
-static const unsigned char __hexdigits[] = "0123456789ABCDEF";
-static void sprintf_hex(unsigned char * str, const unsigned char * ptr, int len, unsigned char delim)
-{
- int i, j=0;
- for(i=0; i<len; i++){
- if(i)str[j++]=delim;
- str[j++]=__hexdigits[ptr[i]>>4];
- str[j++]=__hexdigits[ptr[i]&0x0F];
- }
- str[j] = 0;
-}
-static void print_packet(const char * prefix, struct sk_buff * skb, int len)
-{
- struct ethhdr * h;
- unsigned char src[20], dst[20], body[50];
- int l;
-
- h = (struct ethhdr *)skb->data;
- l = len - 14 > 16 ? 16 : len - 14;
- sprintf_hex(src, &h->h_source[0], 6, ':');
- sprintf_hex(dst, &h->h_dest[0], 6, ':');
- sprintf_hex(body, ((unsigned char *)skb->data)+14, l, ' ');
-
- printk(KERN_INFO "%s: len=%-4d proto=0x%04X src=%s dst=%s\n", prefix, len, be16_to_cpu(h->h_proto), src, dst);
- printk(KERN_INFO " body=%s\n", body);
-}
-
-/**
- * Read Version number by /proc.
- *
- * \param file file structure.
- * \param buffer string pointer given by user.
- * \param start string pointer begin.
- * \param offset offset value.
- * \param count count parameter.
- * \param eof end of file.
- * \param data network device structure.
- * \return new pointer position.
- */
-static int plcdrv_readproc_version(char *buf, char **start, off_t offset, int count, int *eof, void *data)
-{
- struct net_device *dev = (struct net_device*)data;
- struct net_priv *priv;
- char *p;
-
- if(dev == NULL)
- return -1;
- priv = (struct net_priv *)dev->priv;
- if(priv == NULL)
- return -1;
-
- p = buf;
- p += sprintf(p, "%s: %s\n", "PLC Driver", DRV_VERSION);
- p += sprintf(p, "%s: %s\n", "PLC Firmware", priv->version);
- *eof = 1;
- return p-buf+1;
-}
-
-/**
- * Configure AFE with the default configuration.
- */
-static int init_afe(void)
-{
- int ret;
-
-#ifdef CONFIG_MACH_ARIZONA
- ret = afe_write_reg(0x03, 0x04)
- || afe_write_reg(0x04, 0x35)
- || afe_write_reg(0x06, 0x44)
- || afe_write_reg(0x0A, 0x7F)
- || afe_write_reg(0x0C, 0x43)
- || afe_write_reg(0x0D, 0x01)
- || afe_write_reg(0x0E, 0x80);
-#else
- ret = afe_write_reg(0x04, 0x16)
- || afe_write_reg(0x05, 0x80)
- || afe_write_reg(0x07, 0x20)
- || afe_write_reg(0x0A, 0x7F) // TODO: check diff values 9865 / 9867
- || afe_write_reg(0x0B, 0x20)
- || afe_write_reg(0x0C, 0x51) // TODO: check diff values 9865 / 9867
- || afe_write_reg(0x0D, 0x01)
- || afe_write_reg(0x0E, 0x08)
- || afe_write_reg(0x03, 0xF8);
-#endif
-
- if (ret)
- return -EFAULT;
-
- return 0;
-}
-
-/**
- * Read plc stats
- *
- * \param file file structure.
- * \param buffer string pointer given by user.
- * \param start string pointer begin.
- * \param offset offset value.
- * \param count count parameter.
- * \param eof end of file.
- * \param data network device structure.
- * \return new pointer position.
- */
-static int plcdrv_readproc_plc_stats(char *buf, char **start, off_t offset, int count, int *eof, void *data)
-{
- struct net_device *dev = (struct net_device*)data;
- struct net_priv *priv;
- char *p;
-
- if(dev == NULL)
- return -1;
- priv = (struct net_priv *)dev->priv;
- if(priv == NULL)
- return -1;
-
- p = buf;
- p += sprintf (p, "Tx pool: %u\n", priv->plc_stats.tx_pool);
- p += sprintf (p, "Rx pool: %u\n", priv->plc_stats.rx_pool);
- p += sprintf (p, "L2A max length: %u\n", priv->halctx->L2A_max_length);
- *eof = 1;
- return p-buf+1;
-}
-
-/**
- * Set/Unset Reset the Leon processor.
- *
- * \param activate 1 to activate reset.
- * \return error code.
- */
-int plcdrv_reset_leon(int activate)
-{
- if(activate)
- {
- RB_RST_GROUP_VA |= RST_LEONSS;
- if(!(RB_RST_GROUP_VA & RST_LEONSS))
- return -1;
-
- RB_RST_MODULE_VA |= RST_LCPU;
- if(!(RB_RST_MODULE_VA & RST_LCPU))
- return -1;
- }
- else
- {
- RB_RST_GROUP_VA &= ~RST_LEONSS;
- if(RB_RST_GROUP_VA & RST_LEONSS)
- return -1;
-
- RB_RST_MODULE_VA &= ~RST_LCPU;
- if(RB_RST_MODULE_VA & RST_LCPU)
- return -1;
- }
-
- return 0;
-}
-
-/**
- * Set/Unset Reset the DSP.
- *
- * \param activate 1 to activate reset.
- * \return error code.
- */
-int plcdrv_reset_dsp(int activate)
-{
- if(activate)
- {
- RB_RST_GROUP_VA |= RST_DSP;
- if(!(RB_RST_GROUP_VA & RST_DSP))
- return -1;
- }
- else
- {
- RB_RST_GROUP_VA &= ~RST_DSP;
- if(RB_RST_GROUP_VA & RST_DSP)
- return -1;
- }
-
- return 0;
-}
-
-/**
- * Launch the Leon processor.
- *
- * \return error code.
- */
-int plcdrv_launch_leon(void)
-{
- uint32_t *leon_dsu_ptr;
- uint32_t *leon_wd_ptr;
- uint32_t *leon_trace_ptr;
- int result=0;
-
- //Prepare Leon registers accesses
- leon_dsu_ptr = (uint32_t*)ioremap(LEON_DSU_CTRL_BASE_ADDR, 1);
- leon_trace_ptr = (uint32_t*)ioremap(LEON_TRACE_CTRL_BASE_ADDR, 1);
- leon_wd_ptr = (uint32_t*)ioremap(LEON_WD_BASE_ADDR, 1);
-
- //Set trace mode for leon
- switch(dsu_trace)
- {
- case DSU_TRACE_NONE:
- dsu_ctrl &= ~LEON_DSU_TE;
- *leon_trace_ptr &= ~(LEON_TRACE_PROC_EN | LEON_TRACE_AHB_EN);
- break;
- case DSU_TRACE_ALL:
- dsu_ctrl |= LEON_DSU_TE;
- *leon_trace_ptr |= (LEON_TRACE_PROC_EN | LEON_TRACE_AHB_EN);
- break;
- case DSU_TRACE_AHB:
- dsu_ctrl |= LEON_DSU_TE;
- *leon_trace_ptr &= ~(LEON_TRACE_PROC_EN);
- *leon_trace_ptr |= (LEON_TRACE_AHB_EN);
- break;
- case DSU_TRACE_PROC:
- default:
- dsu_ctrl |= LEON_DSU_TE;
- *leon_trace_ptr &= ~(LEON_TRACE_AHB_EN);
- *leon_trace_ptr |= (LEON_TRACE_PROC_EN);
- }
-
- //Refresh watchdog before running (for 10 seconds)
- *leon_wd_ptr = LEON_WD_REFRESH(10);
-
- //Configure DSU + Resume Leon processor execution
- *leon_dsu_ptr = (dsu_ctrl & ~(LEON_DSU_BN | LEON_DSU_FT));
-
- //Check if processor is running
- if((*leon_dsu_ptr) & LEON_DSU_BN)
- {
- result = -1;
- }
-
- //Release reset Leon register
- iounmap((void*)leon_dsu_ptr);
- iounmap((void*)leon_wd_ptr);
- iounmap((void*)leon_trace_ptr);
-
- return result;
-}
-
-/**
- * Find the start and size of the ROM info area.
- *
- * \param file_end end of the file.
- * \param[out] rom_info_start start of the ROM info area.
- * \param[out] rom_info_size size of the ROM info area.
- */
-void plcdrv_find_rom_info(uint8_t *file_end, uint8_t **rom_info_start,
- size_t *rom_info_size)
-{
- uint8_t *infos;
- uint32_t infos_limit;
- int infos_size;
-
- BUG_ON(file_end == NULL);
- BUG_ON(rom_info_start == NULL);
- BUG_ON(rom_info_size == NULL);
-
- infos = file_end;
- infos_limit = (uint32_t)infos - ROM_INFO_MAX_SIZE;
- infos_size = 0;
-
- //No informations area
- if(*infos != ROM_INFO_DELIMITER)
- {
- goto not_found;
- }
-
- //Find start of informations area
- //We are at the end. We go back until we find a delimiter of the beginning
- //of the area.
- while(((uint32_t)infos > infos_limit-1)
- && ((*infos != ROM_INFO_DELIMITER)
- || (*(infos-1) != ROM_INFO_DELIMITER)))
- {
- infos--;
- infos_size++;
- }
-
- //Informations not found
- if((uint32_t)infos <= infos_limit)
- {
- goto not_found;
- }
-
- //There may be more than one delimiter at the beginning of the area.
- //As we need to kwow the exact start of the area,
- //we go up until we see all the delimiters.
- BUG_ON (*infos != ROM_INFO_DELIMITER);
- while(((uint32_t)infos > infos_limit-1) && (*infos == ROM_INFO_DELIMITER))
- {
- infos--;
- infos_size++;
- }
-
- *rom_info_start = infos + 1;
- *rom_info_size = infos_size;
-
- return;
-
-not_found:
- *rom_info_start = NULL;
- *rom_info_size = 0;
-
- return;
-}
-
-/**
- * Get plc.rom version number.
- *
- * \param rom_info_start start of the ROM info area.
- * \param rom_info_size size of the ROM info area.
- * \param[out] version version result buffer.
- */
-void plcdrv_get_rom_version(uint8_t *rom_info_start, size_t rom_info_size,
- uint8_t *version)
-{
- uint8_t *infos, *p;
-
- BUG_ON(version == NULL);
-
- if ((rom_info_start == NULL) || (rom_info_size == 0))
- goto unknown;
-
- infos = rom_info_start;
-
- //Skip delimiters at the beginning of the info area
- while ((infos < (rom_info_start + rom_info_size)
- && (*infos == ROM_INFO_DELIMITER)))
- {
- infos++;
- }
-
- if (infos >= (rom_info_start + rom_info_size))
- {
- goto unknown;
- }
-
- //Split informations, format is "key: value\n"
- for (p = infos ; p < (rom_info_start + rom_info_size) ; p++)
- {
- if((*p == ROM_INFO_DELIMITER) || (*p == ROM_INFO_KEY_DELIMITER))
- *p = '\0';
- }
-
- //Find version key
- while (strcasecmp(infos, ROM_VERSION_KEY))
- {
- infos += strlen(infos)+1; //to skip the key
- infos += strlen(infos)+1; //to skip the associated value
- }
-
- //Skip version key
- infos += strlen(infos)+1;
-
- //Copy version value without first space
- strncpy(version, infos+1, ROM_VERSION_SIZE);
-
- return;
-
-unknown:
- strcpy(version, "Unknown");
-
- return;
-}
-
-/**
- * Open the character device.
- *
- * \param inp inode structure.
- * \param filp file structure.
- * \return error code.
- */
-int plcdrv_char_open(struct inode *inp, struct file *filp)
-{
- filp->private_data = plcdrv_device;
- write_called = 0;
- return 0;
-}
-
-/**
- * Close the character device.
- *
- * \param inp inode structure.
- * \param filp file structure.
- * \return error code.
- */
-int plcdrv_char_close(struct inode *inp, struct file *filp)
-{
- struct net_device *dev = filp->private_data;
- struct net_priv *priv;
-
- if(dev == NULL)
- return -1;
- priv = (struct net_priv *)dev->priv;
- if(priv == NULL)
- return -1;
-
- if(write_called)
- {
- uint8_t *file_end = (uint8_t *)VIRT_PLCCODE_BASE + filp->f_pos - 1;
- uint8_t *rom_info_start;
- size_t rom_info_size;
-
- plcdrv_find_rom_info(file_end, &rom_info_start, &rom_info_size);
-
- //Get firmware version number
- plcdrv_get_rom_version(rom_info_start, rom_info_size, priv->version);
-
- if (rom_info_start != NULL)
- {
- /* End of the .bin file that became the .rom file. */
- uint8_t *bin_eof = rom_info_start;
-
- //Pass boot parameters.
- //As a consequence, the rom info that was written to Cesar memory
- //will be overwritten. But that is not a problem because the rom
- //info is not used on Cesar side.
- plcdrv_pass_boot_params(bin_eof);
- }
-
- //LEON code downloaded let's start network device
- priv->firmware_written = 1;
- }
-
- return 0;
-}
-
-/**
- * Write on the character device,
- * to download LEON binary.
- *
- * \param filp file structure.
- * \param buf user data pointer.
- * \param pos position.
- * \return error code.
- */
-int plcdrv_char_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
-{
- uint8_t *ptr;
-
- //Offset calculation
- ptr = (uint8_t*)VIRT_PLCCODE_BASE + *f_pos;
-
- //Download binary into Leon base address
- if(copy_from_user(ptr, buf, count))
- {
- return -EFAULT;
- }
- *f_pos += count;
-
- //Write at least one packet, prepare on start network device
- write_called = 1;
- return count;
-}
-
-/**
- * Read on the character device,
- * normally not used.
- *
- * \param filp file structure.
- * \param buf user data pointer.
- * \param pos position.
- * \return error code.
- */
-int plcdrv_char_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
-{
- uint32_t *ptr;
-
- //Offset calculation
- ptr = (uint32_t*)VIRT_PLCCODE_BASE + *f_pos;
-
- //Load binary from Leon base address
- if(copy_to_user(buf, ptr, count))
- {
- return -EFAULT;
- }
- *f_pos += count;
- return count;
-}
-
-/**
- * Poll the character device.
- *
- * \param filp file structure
- * \param wait poll table structure
- * \return error code
- */
-unsigned int plcdrv_char_poll(struct file *filp, poll_table * wait)
-{
- struct net_device *dev = NULL;
- struct net_priv *priv = NULL;
-
- if (NULL == filp)
- return POLLERR;
-
- dev = filp->private_data;
- if (NULL == dev)
- return POLLERR;
-
- priv = (struct net_priv *) dev->priv;
- if (NULL == priv)
- return POLLERR;
-
- poll_wait (filp, &priv->plc_select.wq, wait);
-
- if (1 == atomic_read (&priv->plc_select.plc_error))
- return POLLPRI;
-
- return 0;
-}
-
-int trace_cfops_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
-{
- static void *debug_dump_buffer = NULL;
- static uint debug_dump_buffer_remaining_length = 0;
- uint copied_data;
- int error;
-
- //Check used parameter.
- BUG_ON(f_pos == NULL);
- //Sanity check.
- BUG_ON(debug_dump_opened == false);
-
- //Allocate debug dump buffer if needed.
- if(!debug_dump_buffer)
- {
- //Allocate.
- error = alloc_debug_dump_buffer(&debug_dump_buffer,
- debug_dump_buffer_length);
- if(error != 0)
- return error;
- }
-
- //If we have nothing to copy to user.
- if(debug_dump_buffer_remaining_length == 0)
- {
- //We need to handle the case where the buffer has been received while
- //this code is not executed anymore (ctrl+c for example). There can be
- //three cases:
- // - we need to send a new buffer to Cesar because we do not have one
- // to deal with,
- // - the buffer has already been sent (debug_dump_waiting_for_buffer
- // is set to true) but still not received
- // (debug_dump_buffer_length_received set to -1): we need to wait.
- // - the buffer has been received (debug_dump_buffer_length_received
- // is not -1) but not processed by this code
- // (debug_dump_waiting_for_buffer is set to false).
-
- //Give debug dump buffer to CESAR if this not already done.
- if(debug_dump_waiting_for_buffer == false)
- {
- //Debug dump buffer has been given to Cesar.
- debug_dump_buffer_length_received = -1;
- debug_dump_waiting_for_buffer = true;
- error = processing_debug_dump_buffer_send(debug_dump_buffer);
- if (error != 0)
- {
- free_debug_dump_buffer(debug_dump_buffer,
- debug_dump_buffer_length);
- debug_dump_buffer = NULL;
- debug_dump_waiting_for_buffer = false;
- return error;
- }
- }
-
- //Go to sleep until debug dump buffer has returned.
- error = wait_event_interruptible
- (debug_dump_wait_queue,
- debug_dump_buffer_length_received != -1);
- if (error != 0)
- return error;
-
- //Debug dump buffer received from Cesar.
- debug_dump_waiting_for_buffer = false;
- debug_dump_buffer_remaining_length = debug_dump_buffer_length_received;
- }
-
- //If this is not the last debug dump buffer.
- if(debug_dump_buffer_remaining_length)
- {
- BUG_ON(debug_dump_buffer_remaining_length
- > debug_dump_buffer_length_received);
- //How much can we copy?
- copied_data = min(count, debug_dump_buffer_remaining_length);
- //Copy debug dump buffer to buffer for reading.
- if(copy_to_user
- (buf,
- debug_dump_buffer
- + (debug_dump_buffer_length_received
- - debug_dump_buffer_remaining_length),
- copied_data))
- {
- return -EFAULT;
- }
- debug_dump_buffer_remaining_length -= copied_data;
-
- }
- else
- {
- //Finish, let's clean.
- free_debug_dump_buffer(debug_dump_buffer,
- debug_dump_buffer_length);
- debug_dump_buffer = NULL;
- debug_dump_buffer_remaining_length = 0;
-
- copied_data = 0;
- }
-
- //Update what have been done.
- *f_pos += copied_data;
- return copied_data;
-}
-
-int trace_cfops_open(struct inode *inp, struct file *filp)
-{
- //Open only one time.
- if(!debug_dump_opened)
- {
- debug_dump_opened = true;
- return 0;
- }
- else
- return -EBUSY;
-}
-
-int trace_cfops_release(struct inode *inp, struct file *filp)
-{
- BUG_ON(debug_dump_opened == false);
-
- //Device now closed.
- debug_dump_opened = false;
- return 0;
-}
-
-/**
- * Find with data packet address the sk_buff structure address,
- * this address was stored in a Linux list.
- *
- * \param data_addr the packet data address.
- * \return sk_buff address.
- */
-static struct sk_buff* get_skb_addr(uint32_t data_addr)
-{
- struct skb_addr_list *entry;
- struct sk_buff *skb = NULL;
- struct net_priv *priv = plcdrv_device->priv;
- unsigned long flags;
-
- spin_lock_irqsave(&priv->lock, flags);
- //Check in the list to find the sk_buff corresponding to our data_addr
- //No need to use the _safe version as we stop as soon we have deleted the
- //element.
- list_for_each_entry(entry, &priv->list_head_skbs, list)
- {
- if(((uint32_t)entry->pkt_addr) == data_addr)
- {
- //Get the content.
- skb = entry->skb;
- //We should never have a match without any sk_buff.
- BUG_ON(skb == NULL);
- //Remove the element first.
- list_del(&entry->list);
- //Delete the entry.
- kfree(entry);
- //Go out of the loop.
- break;
- }
- }
- spin_unlock_irqrestore(&priv->lock, flags);
- return skb;
-}// get_skb_addr
-
-/**
- * Store the sk_buff->data address in a Linux list
- * this address is associated with sk_buff address.
- *
- * \param skb the sk_buff address.
- * \return error code.
- */
-static uint32_t put_skb_addr(struct sk_buff *skb)
-{
- struct skb_addr_list *entry;
- struct net_priv *priv = plcdrv_device->priv;
- unsigned long flags;
-
- spin_lock_irqsave(&priv->lock, flags);
- //Create a new entry for the list of sk_buffs in used
- entry = (struct skb_addr_list*)kmalloc(sizeof(struct skb_addr_list), GFP_ATOMIC);
- if(entry == NULL)
- {
- spin_unlock_irqrestore(&priv->lock, flags);
- return -ENOMEM;
- }
-
- entry->skb = skb;
- entry->pkt_addr = (uint32_t*)skb->data;
-
- //Add the new entry in the list
- list_add_tail(&entry->list, &priv->list_head_skbs);
-
- spin_unlock_irqrestore(&priv->lock, flags);
- return 0;
-}// put_skb_addr
-
-uint32_t prepare_buffer_to_hw(uint32_t addr, unsigned int len,
- enum data_direction data_dir)
-{
- return dma_map_single(NULL, (void *) addr, len, data_dir);
-}// prepare_buffer_to_hw
-
-uint32_t prepare_buffer_from_hw(uint32_t addr, unsigned int len,
- enum data_direction data_dir)
-{
- dma_unmap_single(NULL, addr, len, data_dir);
-
- //Return the corresponding virtual addr
- return (uint32_t)(dma_to_virt(NULL, addr));
-}// prepare_buffer_from_hw
-
-/**
- * Allocate a buffer to the pool
- * and send to the communication layer.
- *
- * \param type type of buffer to allocate.
- * \return error code.
- */
-int alloc_buffer(enum buffer_type type)
-{
- struct sk_buff *skb;
- int result;
-
- //Allocate an sk_buff
- skb = alloc_skb(PKT_BUF_SZ, GFP_ATOMIC | GFP_DMA);
- if(!skb)
- {
- printk(KERN_ERR DRV_NAME": Error allocating RX buffer for %s\n",plcdrv_device->name);
- return -ENOMEM;
- }
-
- TRACE("AddBuffer: virt@skb=%x ; virt@skb->data=%x\n",(uint32_t)skb, (uint32_t)skb->data);
-
- //Store the sk_buff in sk_buff list in used
- if((result = put_skb_addr(skb)))
- {
- kfree_skb(skb);
- return result;
- }
-
- //Send this allocated pointer to lower layer
- if((result = processing_buffer_add((void*)skb->data, type)))
- {
- kfree_skb(skb);
- }
-
- return result;
-}// alloc_buffer
-
-int alloc_debug_dump_buffer(void **debug_dump_buffer,
- int debug_dump_buffer_length)
-{
- //Check parameters.
- BUG_ON(debug_dump_buffer == NULL || *debug_dump_buffer != NULL);
-
- //Allocate debug dump buffer.
- *debug_dump_buffer = kmalloc(debug_dump_buffer_length, GFP_ATOMIC | GFP_DMA);
-
- if(!*debug_dump_buffer)
- return -ENOMEM;
-
- return 0;
-}
-
-/**
- * Release a buffer from the pool.
- *
- * \param packet packet pointer.
- * \param reason freeing reason.
- * \return error code.
- */
-int free_buffer(void *packet, enum free_reason reason)
-{
- struct net_priv *priv = NULL;
- struct sk_buff *skb;
-
- //Check pointers
- priv = (struct net_priv *)plcdrv_device->priv;
- if(priv == NULL)
- return -1;
-
- if(packet)
- {
- //Find the sk_buff associated to this packet
- skb = get_skb_addr((uint32_t)packet);
- TRACE("FreeBuffer: virt@skb=%x ; virt@skb->data=%x ; @packet=%x\n",(uint32_t)skb, (uint32_t)skb->data,(uint32_t)packet);
- if(!skb)
- {
- printk(KERN_ERR DRV_NAME": %s: error getting sb_buff from received pointer\n", plcdrv_device->name);
- return -1;
- }
-
- //Check the free reason for stats
- switch(reason)
- {
- case RX_DROP: priv->stats.rx_dropped++;
- break;
- case TX_DROP: priv->stats.tx_dropped++;
- priv->plc_stats.tx_pool--;
- if(netif_queue_stopped(plcdrv_device))
- netif_wake_queue(plcdrv_device);
- break;
- case TX_COMPLETE: priv->stats.tx_packets++;
- priv->stats.tx_bytes += skb->len;
- priv->plc_stats.tx_pool--;
- if(netif_queue_stopped(plcdrv_device))
- netif_wake_queue(plcdrv_device);
- break;
- default:
- break;
- }
-
- //Free sk_buff
- kfree_skb(skb);
-
- return 0;
- }
- else
- {
- printk(KERN_ERR DRV_NAME": %s: error freeing a NULL buffer\n", plcdrv_device->name);
- return -1;
- }
-}// free_buffer
-
-void free_debug_dump_buffer(void *debug_dump_buffer,
- int debug_dump_buffer_length)
-{
- //Check parameters.
- BUG_ON(debug_dump_buffer == NULL || debug_dump_buffer_length == 0);
-
- //Free.
- kfree(debug_dump_buffer);
-}
-
-/**
- * Receive a packet that need to transit through NETLINK.
- *
- * \param skb frame structure.
- * \param dev device structure config
- * \param sock netlink socket where to transmit
- * \param pid netlink message pid
- */
-void plcdrv_netlink_rx(struct sk_buff *skb, struct net_device *dev, struct sock *sock, uint32_t pid)
-{
- struct net_priv *priv;
- struct sk_buff *nlskb;
- struct nlmsghdr *nlh;
-
- //Check pointers
- if(skb == NULL)
- return;
- if(dev == NULL)
- return;
- priv = (struct net_priv *)dev->priv;
- if(priv == NULL)
- return;
-
- //Allocate a new sk_buff to add netlink header
- nlskb = alloc_skb(NLMSG_LENGTH(skb->len), GFP_ATOMIC);
- if(!nlskb)
- {
- printk(KERN_ERR DRV_NAME": %s: Error allocating a netlink sk_buff\n", dev->name);
- return;
- }
-
- //Fill netlink header
- nlh = NLMSG_PUT(nlskb, 0, 0, NLMSG_DONE, NLMSG_LENGTH(skb->len) - sizeof(*nlh));
- NETLINK_CB(nlskb).pid = 0; //from kernel
- NETLINK_CB(nlskb).dst_group = 0; //unicast
-
- //Fill this new sk_buff with the old one after netlink header
- memcpy(NLMSG_DATA(nlh), skb->data, skb->len);
-
- //Suppress old sk_buff
- kfree_skb(skb);
-
- //Send netlink to plcd
- netlink_unicast(sock, nlskb, pid, MSG_DONTWAIT);
-
- return;
-
-nlmsg_failure:
- kfree_skb(skb);
- kfree_skb(nlskb);
-}// plcdrv_netlink_rx
-
-/**
- * Receive a packet.
- *
- * \param packet packet pointer.
- * \param length packet length.
- * \return error code.
- */
-int plcdrv_rx(void *packet, int length, enum pkt_dest dst)
-{
- struct net_priv *priv = NULL;
- struct sk_buff *skb;
- int result;
-
- priv = (struct net_priv *)plcdrv_device->priv;
- if(priv == NULL)
- return -1;
-
- //Check packet length size
- if((length <= 0) || (length > PKT_BUF_SZ))
- return -1;
-
- if(packet)
- {
-
- //Find the sk_buff address
- skb = get_skb_addr((uint32_t)packet);
-
- //Pass data to the Linux internal receive level
- skb->dev = plcdrv_device;
- skb_put(skb, length);
- TRACE("\nRX: virt@skb=%x ; virt@skb->data=%x ; @packet=%x\n",(uint32_t)skb, (uint32_t)skb->data,(uint32_t)packet);
- PRINTPKT("RX",skb, length);
- skb->ip_summed = CHECKSUM_UNNECESSARY;
- priv->stats.rx_packets++;
- priv->stats.rx_bytes += length;
- if(dst == NETLINK_DRV)
- {
- plcdrv_netlink_rx(skb, plcdrv_device, priv->nl_drv_sock, priv->nl_drv_pid);
- }
- else if(dst == NETLINK_MME)
- {
- plcdrv_netlink_rx(skb, plcdrv_device, priv->nl_mme_sock, priv->nl_mme_pid);
- }
- else
- {
- skb->protocol = eth_type_trans(skb, plcdrv_device);
-
- seq_check_rx(&priv->seq_check_ctx, skb);
-
- netif_rx(skb);
- }
- result = 0;
- }
- else
- {
- printk(KERN_ERR DRV_NAME": %s: Error Receiving a NULL buffer\n", plcdrv_device->name);
- result = -1;
- }
- return result;
-}// plcdrv_rx
-
-static void plcdrv_post_tx (struct sk_buff *skb, struct net_device *dev, int status)
-{
- struct net_priv *priv = NULL;
- priv = (struct net_priv *)dev->priv;
-
- //Tx queue is nearly full we must stop it
- if(status == NEARLY_FULL ||
- priv->plc_stats.tx_pool == MBX_TX_POOL - 1)
- {
- netif_stop_queue(dev);
- priv->plc_stats.tx_pool++; // update plc stats
- TRACE("TX queue nearly Full\n");
- }
- //Tx queue is full drop the frame
- else if(status == FULL)
- {
- netif_stop_queue(dev);
- priv->stats.tx_errors++;
- priv->stats.tx_fifo_errors++;
- kfree_skb(skb);
- printk(KERN_WARNING DRV_NAME ": %s: TX queue is Full\n", dev->name);
- }
- // Transmit success
- else
- {
- priv->plc_stats.tx_pool++; // update plc stats
- }
-
- //Handle transmit
- dev->trans_start = jiffies;
-
- return;
-}
-
-/**
- * Transmit frame procedure.
- *
- * \param skb frame structure.
- * \param dev device structure.
- * \return error code.
- */
-int plcdrv_data_tx(struct sk_buff *skb, struct net_device *dev)
-{
- struct net_priv *priv = NULL;
- int status;
-
- //Check pointers
- if(skb == NULL)
- return -1;
- if(dev == NULL)
- return -1;
- priv = (struct net_priv *)dev->priv;
- if(priv == NULL)
- return -1;
-
- TRACE("\nTX: virt@skb=%x ; virt@skb->data=%x ; skb->len=%d\n",(uint32_t)skb, (uint32_t)skb->data, skb->len);
- PRINTPKT("TX",skb, skb->len);
-
- seq_check_tx(&priv->seq_check_ctx, skb);
-
- //Store the sk_buff in sk_buff list in used
- if((status = put_skb_addr(skb)))
- {
- return status;
- }
-
- //Send buffer to lower layers
- status = processing_send((void *)skb->data, skb->len, DATA);
-
- /* check result and update stats */
- plcdrv_post_tx (skb, dev, status);
-
- return 0;
-}// plcdrv_data_tx
-
-/**
- * Transmit a frame received from NETLINK.
- *
- * \param skb frame structure.
- * \param dev net device structure
- * \param sock netlink socket structure
- */
-int plcdrv_netlink_tx(struct sk_buff *nlskb, struct net_device *dev, struct sock *sock)
-{
- struct sk_buff *skb;
- struct net_priv *priv;
- buffer_type_t type;
- int status;
-
- //Check pointers
- if(nlskb == NULL)
- return -1;
- if(dev == NULL)
- return -1;
- priv = (struct net_priv *)dev->priv;
- if(priv == NULL)
- return -1;
-
- mutex_lock(&plcdrv_nl_mutex);
-
- //Prepare a sk_buff without netlink header
- skb_pull(nlskb, NLMSG_HDRLEN);
-
- //Allocate a new sk_buff because nlskb will be suppress at this end of this function
- skb = alloc_skb(nlskb->len, GFP_ATOMIC | GFP_DMA);
- if(!skb)
- {
- printk(KERN_ERR DRV_NAME": %s: Error allocating a netlink sk_buff\n", dev->name);
- return -1;
- }
-
- //Fill this new sk_buff with the old one
- memcpy(skb->data, nlskb->data, nlskb->len);
-
- //Prepare this new sk_buff
- skb_put(skb, nlskb->len);
-
- TRACE("\nTX: virt@skb=%x ; virt@skb->data=%x ; skb->len=%d\n",(uint32_t)skb, (uint32_t)skb->data, skb->len);
- PRINTPKT("TX",skb, skb->len);
-
- //Store the sk_buff in sk_buff list in used
- if((status = put_skb_addr(skb)))
- {
- return status;
- }
-
- if((get_eth_mme_type(skb->data) == HPAV_MME_P_FCALL) ||
- (get_eth_mme_type(skb->data) == HPAV_MME_P_SNIFFER))
- {
- type = INTERFACE;
- }
- else
- {
- type = MME;
- }
- //send buffer to lower layer
- status = processing_send((void *)skb->data, skb->len, type);
-
- /* check result and update stats */
- plcdrv_post_tx (skb, dev, status);
-
- mutex_unlock(&plcdrv_nl_mutex);
-
- return 0;
-}// plcdrv_netlink_tx
-
-/**
- * Transmit a frame received from DRV NETLINK.
- *
- * \param skb frame structure.
- */
-void plcdrv_netlink_drv_tx (struct sk_buff *nlskb)
-{
- struct net_priv *priv = (struct net_priv *)plcdrv_device->priv;
- struct nlmsghdr *nlh;
- if(NULL == nlskb)
- return;
- nlh = nlmsg_hdr(nlskb);
- plcdrv_netlink_tx(nlskb, plcdrv_device, priv->nl_drv_sock);
-}
-
-/**
- * Transmit a frame received from MME NETLINK.
- *
- * \param skb frame structure.
- */
-void plcdrv_netlink_mme_tx (struct sk_buff *nlskb)
-{
- struct net_priv *priv = (struct net_priv *)plcdrv_device->priv;
- struct nlmsghdr *nlh;
- if(NULL == nlskb)
- return;
- nlh = nlmsg_hdr(nlskb);
- plcdrv_netlink_tx(nlskb, plcdrv_device, priv->nl_mme_sock);
-}
-
-/**
- * Interrupt Handler Watchdog procedure.
- *
- * \param irq interrupt number
- * \param dev_id device structure
- * \return error code
- */
-irqreturn_t
-plcdrv_it_wd (int irq, void * dev_id)
-{
- struct net_device *dev = NULL;
- struct net_priv *priv = NULL;
-
- if (NULL == dev_id)
- return IRQ_NONE;
-
- dev = (struct net_device *) dev_id;
- priv = netdev_priv(dev);
- if (NULL == priv)
- return IRQ_NONE;
-
- /* Is some process waiting on a select() ? */
- if (!waitqueue_active (&priv->plc_select.wq))
- {
- /* Reset */
- /* Can't use one of the kernel reboot functions (like kernel_restart())
- * because of the EXPORT_SYMBOL_GPL. */
- RB_RST_GLOBAL_VA = 1;
- }
- else
- {
- /* Wake up the process waiting on the select(), and let it handle the
- * situation. */
- atomic_set (&priv->plc_select.plc_error, 1);
- wake_up (&priv->plc_select.wq);
- L2Awd_it_disable (priv->halctx);
- }
-
- return IRQ_HANDLED;
-} // plcdrv_it_wd
-
-/**
- * Interrupt Handler Receive procedure.
- *
- * \param irq interrupt number.
- * \param dev_id device structure.
- * \return error code.
- */
-irqreturn_t plcdrv_it_rx(int irq, void * dev_id)
-{
- struct net_device *dev = NULL;
- struct net_priv *priv = NULL;
-
- //Check pointer
- dev = (struct net_device*)dev_id;
- if(dev == NULL)
- return IRQ_NONE;
-
- priv = (struct net_priv *)dev->priv;
- if(priv == NULL)
- return IRQ_NONE;
-
- //Call mailbox receive for interrupt part
- mailbox_receive_isr();
-
- //Call the tasklet for real mailbox reception part
- tasklet_schedule(&priv->tasklet_it_rx);
-
- return IRQ_HANDLED;
-}// plcdrv_it_rx
-
-/**
- * Bottom Half Receive procedure.
- *
- * \param dev_id device structure.
- */
-void plcdrv_bh_rx(unsigned long dev_id)
-{
- struct net_device *dev = NULL;
- struct net_priv *priv = NULL;
- unsigned int budget;
-
- //Check pointer
- dev = (struct net_device*)dev_id;
- if(dev == NULL)
- return;
-
- priv = (struct net_priv *)dev->priv;
- if(priv == NULL)
- return;
-
- budget = PLCDRV_RX_BUDGET;
-
- //Call mailbox receive
- mailbox_receive(&budget);
-
- //Re-call us if budget is exhausted
- if(!budget)
- tasklet_schedule(&priv->tasklet_it_rx);
-
-}// plcdrv_bh_rx
-
-/**
- * Finish the transmit frame procedure.
- *
- * \param irq interrupt number.
- * \param dev device structure.
- */
-irqreturn_t plcdrv_it_txdone(int irq, void * dev_id)
-{
- struct net_device *dev;
-
- //Check pointer
- if(dev_id == NULL)
- return IRQ_NONE;
-
- dev = (struct net_device*)dev_id;
- TRACE("Transmit Done IT\n");
-
- //A packet was just freeing by the hardware,
- //we can restart the tx queue
- if(netif_queue_stopped(dev))
- netif_wake_queue(dev);
-
- //call lowest layer that a tx_done is arrived
- mailbox_txdone();
- TRACE("Transmit Done IT end\n");
-
- return IRQ_HANDLED;
-}// plcdrv_it_txdone
-
-/**
- * Read packet status from the device.
- *
- * \param dev device structure.
- * \return the device stats.
- */
-struct net_device_stats *plcdrv_stats(struct net_device *dev)
-{
- struct net_priv *priv = NULL;
-
- //Check pointers
- if(dev == NULL)
- return NULL;
-
- priv = (struct net_priv *)dev->priv;
- if(priv == NULL)
- return NULL;
-
- //Give statistics
- return &priv->stats;
-}// plcdrv_stats
-
-/**
- * Change the MTU.
- *
- * \param dev device structure.
- * \param new_mtu the new mtu value.
- * \return error code.
- */
-int plcdrv_change_mtu(struct net_device *dev, int new_mtu)
-{
- //Check pointers
- if(dev == NULL)
- return -1;
-
- TRACE("change_mtu\n");
-
- //Check arguments
- if(new_mtu < 64 || new_mtu > 1508)
- return -EINVAL;
- else
- {
- //Change the MTU
- dev->mtu = new_mtu;
- TRACE("change_mtu end\n");
- return 0;
- }
-}// plcdrv_change_mtu
-
-/**
- * Change the MAC address.
- *
- * \param dev device structure.
- * \param p mac addr source.
- * \return error code.
- */
-int plcdrv_set_mac_address(struct net_device *dev, void *p)
-{
- struct sockaddr *addr = p;
-
- //Check pointers
- if(dev == NULL)
- return -1;
- if(p == NULL)
- return -1;
-
- TRACE("set_mac_address\n");
-
- //Store the new address for Linux
- memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
-
- TRACE("set_mac_address end\n");
-
- return 0;
-}// plcdrv_set_mac_address
-
-/**
- * User control device interface.
- *
- * \param dev device structure.
- * \param ifr user exchange structure.
- * \param cmd command to execute.
- * \return error code.
- */
-int plcdrv_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
- struct net_priv *priv = NULL;
- struct plcdrv_setpid user_data = {0};
-
- //Check pointers
- if(ifr == NULL)
- return -1;
- if(dev == NULL)
- return -1;
-
- TRACE("ioctl\n");
-
- //Find the command
- switch(cmd)
- {
- case PLCDRV_IOCTL_SETPID:
-
- /* Check validity of driver private data */
- if (NULL == (priv = (struct net_priv *) dev->priv))
- return -EFAULT;
-
- /* Get user data */
- if (copy_from_user (&user_data, ifr->ifr_data, sizeof (user_data)))
- return -EFAULT;
-
- /* During initialization, plcd & managerd register their pid
- * for reception on drv & mme netlink */
- if (NETLINK_PLC_DRV == user_data.nl)
- {
- priv->nl_drv_pid = user_data.pid;
- printk (KERN_INFO "%s: plcd registered with pid %d\n", __FUNCTION__,
- priv->nl_drv_pid);
- }
- if (NETLINK_PLC_MME == user_data.nl)
- {
- priv->nl_mme_pid = user_data.pid;
- printk (KERN_INFO "%s: managerd registered with pid %d\n", __FUNCTION__,
- priv->nl_mme_pid);
- }
-
- /* In case of another netlink, do nothing */
- break;
-
- default:
- return -EOPNOTSUPP;
- }
-
- TRACE("ioctl end\n");
-
- return 0;
-}// plcdrv_ioctl
-
-/**
- * Initialize the device.
- *
- * \param dev device structure.
- * \return error code.
- */
-int plcdrv_open(struct net_device *dev)
-{
- struct net_priv *priv = NULL;
- struct init_info info;
- int i;
- int result;
-
- //Check pointers
- if(dev == NULL)
- return -1;
- priv = (struct net_priv *)dev->priv;
- if(priv == NULL)
- return -1;
-
- //Wait Downloading Leon binary into RAM to really open the driver
- if(!priv->firmware_written)
- {
- printk(KERN_ERR DRV_NAME": %s You need to download SPiDCOM PLC binary before\n",dev->name);
- return -EPERM;
- }
-
- //Prepare mutex
- spin_lock_init(&priv->lock);
-
- //Prepare sk_buff in used list
- INIT_LIST_HEAD(&priv->list_head_skbs);
-
- //Configure AFE with the default configuration
- if (init_afe())
- return -EFAULT;
-
- //Allocate rings for each mailbox
- if((priv->virt_ring_base_addr =
- (uint32_t)dma_alloc_coherent(NULL,
- A2L_RING_SIZE+L2A_RING_SIZE,
- &priv->phys_ring_base_addr,
- GFP_ATOMIC|GFP_DMA)
- ) == 0)
- {
- printk(KERN_ERR DRV_NAME": Error allocating mailboxes rings for %s\n", dev->name);
- return -ENOMEM;
- }
- TRACE("OPEN: virt@rings=%x ; phys@rings=%x\n",priv->virt_ring_base_addr, priv->phys_ring_base_addr);
-
- //Flush rings for each mailbox
- memset((void*)priv->virt_ring_base_addr, 0, A2L_RING_SIZE+L2A_RING_SIZE);
-
- //Request Receive IRQ
- if(request_irq(priv->num_mbx_it, plcdrv_it_rx, 0, dev->name, dev) != 0)
- {
- printk(KERN_ERR DRV_NAME ": %s - interrupt %d request fail\n", dev->name, dev->irq);
- result = -ENODEV;
- goto err_open;
- }
-
- //Request Transmit Acknowledge IRQ
- if(request_irq(priv->num_mbx_it_ack, plcdrv_it_txdone, 0, dev->name, dev) != 0)
- {
- printk(KERN_ERR DRV_NAME ": %s - interrupt %d request fail\n", dev->name, dev->irq);
- result = -ENODEV;
- goto err_rq_ack;
- }
-
- //Request Leon Watchdog IRQ
- if(request_irq(priv->num_mbx_it_wd, plcdrv_it_wd, 0, dev->name, dev) != 0)
- {
- printk(KERN_ERR DRV_NAME ": %s - interrupt %d request fail\n", dev->name, dev->irq);
- result = -ENODEV;
- goto err_rq_wd;
- }
-
- //Unreset Leon Processor
- if(plcdrv_reset_leon(0))
- {
- result = -1;
- goto err_rq_wd;
- }
-
- //Start lower Layers
- info.ring_base_addr = priv->virt_ring_base_addr;
- info.phys_ring_base_addr = priv->phys_ring_base_addr;
- info.mbx_reg_base_addr = dev->base_addr;
- info.debug_mode = debug;
- info.launch_leon = &plcdrv_launch_leon;
- memcpy(info.mac_addr, dev->dev_addr, sizeof(info.mac_addr));
- if(processing_init(&info, dev))
- {
- printk(KERN_ERR DRV_NAME ": %s: Error initializing hardware (firmware)\n", dev->name);
- result = -1;
- goto err_rq_wd;
- }
-
- //Allocate RX buffer pool to give to CESAR
- for(i=0 ; i<nb_rx_data_buffers ; i++)
- {
- if(alloc_buffer(DATA))
- {
- printk(KERN_ERR DRV_NAME ": %s: Error creating DATA buffer pool\n", dev->name);
- result = -1;
- goto err_rq_wd;
- }
- // update plc stats
- priv->plc_stats.rx_pool++;
- }
- for(i=0 ; i<nb_rx_mme_buffers ; i++)
- {
- if(alloc_buffer(MME))
- {
- printk(KERN_ERR DRV_NAME ": %s: Error creating MME buffer pool\n", dev->name);
- result = -1;
- goto err_rq_wd;
- }
- }
- for(i=0 ; i<nb_rx_interface_buffers ; i++)
- {
- if(alloc_buffer(INTERFACE))
- {
- printk(KERN_ERR DRV_NAME ": %s: Error creating INTERFACE buffer pool\n", dev->name);
- result = -1;
- goto err_rq_wd;
- }
- // update plc stats
- priv->plc_stats.rx_pool++;
- }
-
- //Enable tasklet for reception
- tasklet_enable(&priv->tasklet_it_rx);
-
- //Initialize netlink functions
- priv->nl_drv_sock = netlink_kernel_create(&init_net, NETLINK_PLC_DRV, 0, plcdrv_netlink_drv_tx, NULL, THIS_MODULE);
- priv->nl_mme_sock = netlink_kernel_create(&init_net, NETLINK_PLC_MME, 0, plcdrv_netlink_mme_tx, NULL, THIS_MODULE);
-
- //Prepare Linux as link up
- netif_carrier_on(dev);
- netif_start_queue(dev);
-
- return 0;
-
-err_rq_wd:
- free_irq(priv->num_mbx_it_ack, dev);
-err_rq_ack:
- free_irq(priv->num_mbx_it, dev);
-err_open:
- dma_free_coherent(NULL,
- A2L_RING_SIZE+L2A_RING_SIZE,
- (void*)priv->virt_ring_base_addr,
- priv->phys_ring_base_addr);
- return result;
-}// plcdrv_open
-
-/**
- * Uninitialize the device.
- *
- * \param dev device structure.
- * \return error code.
- */
-int plcdrv_stop(struct net_device *dev)
-{
- struct net_priv *priv = NULL;
- struct skb_addr_list *entry, *n;
-
- //Check pointers
- if(dev == NULL)
- return -1;
- priv = (struct net_priv *)dev->priv;
- if(priv == NULL)
- return -1;
-
- TRACE("stop\n");
-
- //Disable transmitter
- netif_stop_queue(dev);
- netif_carrier_off(dev);
-
- //Stop netlink interface
- netlink_kernel_release(priv->nl_drv_sock);
- netlink_kernel_release(priv->nl_mme_sock);
-
- //Stop tasklet for reception
- tasklet_disable(&priv->tasklet_it_rx);
-
- //Stop lower layers
- processing_uninit();
-
- //Reset LEON and DSP
- plcdrv_reset_leon(1);
- plcdrv_reset_dsp(1);
- plcdrv_reset_dsp(0);
-
- //Disconnect from IRQ
- free_irq(priv->num_mbx_it, dev);
- free_irq(priv->num_mbx_it_ack, dev);
- free_irq(priv->num_mbx_it_wd, dev);
-
- //Free mailboxes ring
- dma_free_coherent(NULL,
- A2L_RING_SIZE+L2A_RING_SIZE,
- (void*)priv->virt_ring_base_addr,
- priv->phys_ring_base_addr);
-
- //TODO:Freeing all buffers
- //TODO: send a message to processing layer or communication layer
- //that we want to shutdown le plc driver
- //Wait all allocated sk_buff become free
- //(a sk_buff become free when we receive a send_done procedure)
- //
- //Currently, we only suppress all sk_buff in used
- list_for_each_entry_safe (entry, n, &priv->list_head_skbs, list)
- {
- //Remove the element first.
- list_del(&entry->list);
- //Delete the content of the element.
- kfree_skb(entry->skb);
- //Delete the element itself.
- kfree(entry);
- }
-
- TRACE("stop end\n");
-
- return 0;
-}// plcdrv_stop
-
-/**
- * Initialise the network device.
- *
- * \param dev device structure.
- * \return error code.
- */
-int plcdrv_init(struct net_device *dev)
-{
- struct net_priv *priv = NULL;
- uint32_t *leon_start_addr_ptr;
-
- //Check pointers
- if(dev == NULL)
- return -1;
- priv = (struct net_priv *)dev->priv;
- if(priv == NULL)
- return -1;
-
- //Set IP base address
- dev->base_addr = (unsigned int)ioremap(MBX_BASE_ADDR, NB_MBX_REGISTERS);
- TRACE("INIT: virt@mbx_reg=%x ; phys@mbx_reg=%x\n",(uint32_t)dev->base_addr,MBX_BASE_ADDR);
-
- //Set Interrupts numbers
- dev->irq = INT_MBX; //do not use dev->irq because there is more than one IT given by the hardware
- priv->num_mbx_it = INT_MBX;
- priv->num_mbx_it_ack = INT_MBX_ACK;
- priv->num_mbx_it_wd = INT_MBX_WD;
-
- //Set Leon code base address (translation)
- leon_start_addr_ptr = (uint32_t*)ioremap(RB_LEON_ADD_START, 1);
- //If a custom value was passed as a module parameter, use it.
- //Otherwise, use the default one.
- *leon_start_addr_ptr = (leon_start_addr != INVALID_LEON_START_ADDR) ?
- leon_start_addr : spc300_plc_mem_start;
- iounmap(leon_start_addr_ptr);
-
- //Force waiting download Leon binary
- priv->firmware_written = 0;
-
- //Initialise device functions
- ether_setup(dev);
- dev->uninit = plcdrv_uninit;
- dev->open = plcdrv_open;
- dev->stop = plcdrv_stop;
- dev->do_ioctl = plcdrv_ioctl;
- dev->set_mac_address = plcdrv_set_mac_address;
- dev->hard_start_xmit = plcdrv_data_tx;
- dev->get_stats = plcdrv_stats;
-/* dev->tx_timeout = plcdrv_tx_timeout; */
-/* dev->watchdog_timeo = TX_TIMEOUT; */
- dev->change_mtu = plcdrv_change_mtu;
-
- //Declare tasklet for reception
- tasklet_init(&priv->tasklet_it_rx, &plcdrv_bh_rx, (unsigned long)dev);
- tasklet_disable(&priv->tasklet_it_rx);
-
- //Setup MAC address for Linux (stored in NVRAM)
- dev->dev_addr[0] = spc300_nvram.plc_address[0];
- dev->dev_addr[1] = spc300_nvram.plc_address[1];
- dev->dev_addr[2] = spc300_nvram.plc_address[2];
- dev->dev_addr[3] = spc300_nvram.plc_address[3];
- dev->dev_addr[4] = spc300_nvram.plc_address[4];
- dev->dev_addr[5] = spc300_nvram.plc_address[5];
-
- // Initialize structure for poll/select management
- atomic_set (&priv->plc_select.plc_error, 0);
- init_waitqueue_head (&priv->plc_select.wq);
-
- seq_check_init(&priv->seq_check_ctx, "plc_drv");
-
- return 0;
-}// plcdrv_init
-
-/**
- * Uninitialise the network device.
- *
- * \param dev device structure.
- */
-void plcdrv_uninit(struct net_device *dev)
-{
- struct net_priv *priv;
- BUG_ON(!dev);
- priv = (struct net_priv *)dev->priv;
- BUG_ON(!priv);
-
- //Kill tasklet for reception
- tasklet_kill(&priv->tasklet_it_rx);
-
- //Unmap IP address
- BUG_ON(!dev->base_addr);
- iounmap((void*)dev->base_addr);
-}// plcdrv_uninit
-
-/** Character device functions */
-static struct file_operations plcdrv_char_fops = {
- .owner = THIS_MODULE,
- .open = plcdrv_char_open,
- .read = plcdrv_char_read,
- .write = plcdrv_char_write,
- .release = plcdrv_char_close,
- .poll = plcdrv_char_poll,
-};
-
-static struct file_operations trace_cfops = {
- .owner = THIS_MODULE,
- .read = trace_cfops_read,
- .open = trace_cfops_open,
- .release = trace_cfops_release,
-};
-
-/**
- * Initialise the module.
- *
- * \return error code.
- */
-int __init plcdrv_module_init(void)
-{
- int result;
- struct net_device *dev = NULL;
- struct proc_dir_entry *entry;
-
- printk("%s", version);
-
- //Register a character device to manage Cesar Binary download
- //Allocate character device Major number
- result = alloc_chrdev_region(&number, 0, 2, "plcdrv");
- if(result < 0)
- {
- printk(KERN_ERR "plcdrv: can't get major %d\n",MAJOR(number));
- return result;
- }
- //Register character device
- cdev_init(&plcdrv_char_dev,&plcdrv_char_fops);
- plcdrv_char_dev.owner = THIS_MODULE;
- plcdrv_char_dev.ops = &plcdrv_char_fops;
- result = cdev_add(&plcdrv_char_dev, number, 1);
- if(result <0)
- {
- printk(KERN_ERR "plcdrv: Error registering\n");
- unregister_chrdev_region(number, 2);
- return result;
- }
-
- // Register trace character device.
- cdev_init(&trace_cdev, &trace_cfops);
- trace_cdev.owner = THIS_MODULE;
- result = cdev_add(&trace_cdev, MKDEV(MAJOR(number), MINOR(number) + 1), 1);
- if(result<0)
- {
- printk (KERN_ERR "plcdrv: error registering trace device\n");
- cdev_del(&plcdrv_char_dev);
- unregister_chrdev_region(number, 2);
- }
-
- //Register the network device
- //Allocate device memory
- dev = alloc_netdev(sizeof(struct net_priv), "plc%d", ether_setup);
- if((dev == NULL) || (dev->priv == NULL))
- {
- cdev_del(&plcdrv_char_dev);
- cdev_del(&trace_cdev);
- unregister_chrdev_region(number, 2);
- return -ENOMEM;
- }
- //Initialize private structure
- memset(dev->priv, 0, sizeof(struct net_priv));
-
- //Proceed the init driver
- dev->init = plcdrv_init;
-
- //Register network device
- result = register_netdev(dev);
- if(result < 0)
- {
- printk(KERN_ERR DRV_NAME": Error %i registering %s\n", result, dev->name);
- cdev_del(&plcdrv_char_dev);
- cdev_del(&trace_cdev);
- unregister_chrdev_region(number, 2);
- kfree(dev->priv);
- free_netdev(dev);
- return result;
- }
- else
- {
- plcdrv_device = dev;
- }
-
- //Create a proc entry for version
- proc_plc_dir = proc_mkdir("plc", init_net.proc_net);
- entry = create_proc_entry("version", 0, proc_plc_dir);
- entry->read_proc = plcdrv_readproc_version;
- entry->data = (int*)plcdrv_device;
-
- // Create stats entries
- entry = create_proc_entry ("stats", 0, proc_plc_dir);
- entry->read_proc = plcdrv_readproc_plc_stats;
- entry->data = (int*)plcdrv_device;
-
- return result;
-}// plcdrv_module_init
-
-/**
- * Uninitialise the module.
- */
-void __exit plcdrv_module_exit(void)
-{
- BUG_ON(!plcdrv_device);
-
- //Unregister character device
- cdev_del(&plcdrv_char_dev);
- cdev_del(&trace_cdev);
- unregister_chrdev_region(number, 2);
-
- //Unregister network device
- unregister_netdev(plcdrv_device);
- free_netdev(plcdrv_device);
-
- //Remove proc
- remove_proc_entry("stats", proc_plc_dir);
- remove_proc_entry("version", proc_plc_dir);
- remove_proc_entry("plc", init_net.proc_net);
-}// plcdrv_module_exit
-
-module_init(plcdrv_module_init);
-module_exit(plcdrv_module_exit);
-
diff --git a/cleopatre/devkit/plcdrv/src/mailbox.c b/cleopatre/devkit/plcdrv/src/mailbox.c
deleted file mode 100644
index 0574d64557..0000000000
--- a/cleopatre/devkit/plcdrv/src/mailbox.c
+++ /dev/null
@@ -1,526 +0,0 @@
-/* Cleopatre project {{{
- *
- * Copyright (C) 2008 Spidcom
- *
- * <<<Licence>>>
- *
- * }}} */
-/**
- * \file mailbox.c
- * \brief Mailbox Layer
- * \ingroup Cleopatre - PlcDrv
- *
- * This file content the mailbox layer, this layer will
- * provide all mechanisms to manage mailboxes.
- */
-
-#include "common.h"
-#include "linux_drv.h"
-#include "processing.h"
-#include "mailbox.h"
-#include "hal.h"
-
-#include <linux/bitops.h>
-#include <linux/kernel.h>
-
-#ifdef __UTESTS__
-/* TODO : move this ! */
-uint32_t mbx_send_result[2];
-uint32_t mbx_buffer_add_result[2];
-uint32_t mbx_rx_ptr_result;
-#endif
-
-/** Define Debug/Trace Level */
-#define TRACE(...) if(test_bit(TRACE_MAIL, (const volatile unsigned long*)&trace)) printk(KERN_INFO "SPC300: MAIL: " __VA_ARGS__)
-
-/** Data parameters */
-#define MBX_MSG_DATA_TYPE_DATA 0
-#define MBX_MSG_DATA_TYPE_MME 1
-typedef struct {
- uint32_t type :8;
- uint32_t length :4;
- uint32_t param_type :1;
- uint32_t param_length :11;
- uint32_t param_prio :3;
- uint32_t reserved :5;
-} __attribute__ ((__packed__)) mbx_data_hdr_t;
-
-/** Buffer add parameters */
-#define MBX_MSG_BUFF_ADD_TYPE_DATA 0
-#define MBX_MSG_BUFF_ADD_TYPE_MME 1
-#define MBX_MSG_BUFF_ADD_TYPE_INTERFACE 2
-typedef struct {
- uint32_t type :8;
- uint32_t length :4;
- uint32_t param_type :2;
- uint32_t reserved :18;
-} __attribute__ ((__packed__)) mbx_buffer_add_hdr_t;
-
-/** Send done parameters */
-typedef struct {
- uint32_t type :8;
- uint32_t length :4;
- uint32_t reserved :20;
-} __attribute__ ((__packed__)) mbx_send_done_hdr_t;
-
-/** Interface parameters */
-#define MBX_MSG_INTERFACE_TYPE_INTERFACE 0
-#define MBX_MSG_INTERFACE_TYPE_SNIFFER 1
-#define MBX_MSG_INTERFACE_TYPE_FCALL 2
-typedef struct {
- uint32_t type :8;
- uint32_t length :4;
- uint32_t param_type :8;
- uint32_t param_length :11;
- uint32_t reserved :1;
-} __attribute__ ((__packed__)) mbx_interface_hdr_t;
-
-/** Debug dump parameters. */
-typedef struct {
- uint32_t type :8;
- uint32_t length :4;
- uint32_t param_length :16;
- uint32_t reserved :4;
-} __attribute__ ((__packed__)) mbx_debug_dump_hdr_t;
-
-/** Generic parameters */
-typedef struct {
- uint32_t type :8;
- uint32_t length :4;
- uint32_t raw :20;
-} __attribute__ ((__packed__)) mbx_generic_hdr_t;
-
-/** Mailbox type */
-#define MBX_MSG_TYPE_DATA 0
-#define MBX_MSG_TYPE_BUFFER_ADD 1
-#define MBX_MSG_TYPE_SEND_DONE 2
-#define MBX_MSG_TYPE_INTERFACE 3
-#define MBX_MSG_TYPE_DEBUG_DUMP 0x40
-
-/** Mailbox Header Structure */
-typedef union {
- mbx_data_hdr_t data;
- mbx_buffer_add_hdr_t buffer_add;
- mbx_send_done_hdr_t send_done;
- mbx_interface_hdr_t interface;
- mbx_debug_dump_hdr_t debug_dump;
- mbx_generic_hdr_t generic;
-} mbx_hdr_t;
-
-/** Mailbox Data Structure */
-typedef union {
- uint32_t buffer_ptr;
- uint32_t further_use;
-} __attribute__ ((__packed__)) mbx_data_t;
-
-/** Mailbox Structure */
-typedef struct {
- mbx_hdr_t header;
- mbx_data_t data;
-} __attribute__ ((__packed__)) mbx_t;
-
-
-/** Our global HAL context pointer */
-struct halctx *ctx;
-
-/**
- * Initialize the mailbox layer.
- *
- * \param info initialisation structure.
- * \return error code.
- */
-int mailbox_init(struct init_info *info, struct net_device *dev)
-{
- struct net_priv *priv;
- //Check arguments
- if(info == NULL)
- return -1;
-
- if(dev == NULL)
- return -1;
- priv = (struct net_priv *)dev->priv;
- if(priv == NULL)
- return -1;
-
- //Initialize registers
- if((ctx = halmbx_init(info))==NULL)
- return -1;
-
- priv->halctx = ctx;
-
- //Initialize spin lock.
- spin_lock_init (&ctx->lock);
-
- //Stop all interrupts
- A2La_it_disable(ctx);
- L2At_it_disable(ctx);
- L2Awd_it_disable(ctx);
-
- //Clear interrupts
- clr_A2La_interrupt(ctx);
- clr_L2At_interrupt(ctx);
- clr_L2Awd_interrupt(ctx);
-
- //Unmask sending interrupts
- L2At_it_enable(ctx);
-
- L2Awd_it_enable (ctx);
- return 0;
-}// mailbox_init
-
-/**
- * UnInitialize the mailbox layer.
- *
- * \return error code.
- */
-int mailbox_uninit(void)
-{
- //Mask all interrupts
- A2La_it_disable(ctx);
- L2At_it_disable(ctx);
- L2Awd_it_disable(ctx);
-
- //Uninit lower layer
- return halmbx_uninit(ctx);
-}// mailbox_uninit
-
-/**
- * Give the message to hardware.
- *
- * \param msg message pointer.
- * \param size size of message.
- * \return error code or status queue.
- */
-int internal_mailbox_send(uint32_t *msg, int size)
-{
- int status;
- unsigned long flags;
-
- //Lock access to the mailbox.
- spin_lock_irqsave(&ctx->lock, flags);
-
- //Check pointer
- if(msg == NULL)
- {
- status = -1;
- goto internal_mailbox_send_out;
- }
-
- //Check room
- status = halmbx_A2Lmail_status_queue(ctx);
- if(status == NEARLY_FULL || status == FULL)
- {
- //The mailbox is nearly full stop upper layers
- //and activate tx_ack interrupt
- clr_A2La_interrupt(ctx);
- A2La_it_enable(ctx);
- if(status == FULL)
- goto internal_mailbox_send_out;
- }
- else
- {
- A2La_it_disable(ctx);
- }
-
- //Copy to ring buffer
- if(halmbx_copy_to_ring(ctx, msg, size))
- {
- status = -1;
- goto internal_mailbox_send_out;
- }
-
- //Update the ring management
- if(halmbx_A2Lmail_update(ctx, size))
- {
- status = -1;
- goto internal_mailbox_send_out;
- }
-
-internal_mailbox_send_out:
- //Unlock spin lock and irq.
- spin_unlock_irqrestore(&ctx->lock, flags);
- return status;
-}// internal_mailbox_send
-
-/**
- * Prepare the mailbox message
- * corresponding to a sending frame
- * and send it to CESAR.
- *
- * \param pointer the data message pointer.
- * \param length the length of the data message.
- * \param prio message priority.
- * \param type type of message.
- * \return error code.
- */
-int mailbox_send(void *pointer, uint32_t length, uint32_t prio, enum buffer_type type)
-{
- mbx_t msg;
-
- //Check pointer and length
- if(pointer == NULL || length == 0)
- return -1;
-
- //Check prio range
- if(prio > 7)
- return -1;
-
- //Reset message variable
- memset(&msg, 0, sizeof(msg));
-
- //Header construction
- switch(type)
- {
- case DATA:
- msg.header.data.type = MBX_MSG_TYPE_DATA;
- msg.header.data.length = 1;
- TRACE("SEND data data\n");
- msg.header.data.param_type = MBX_MSG_DATA_TYPE_DATA;
- msg.header.data.param_length = length;
- msg.header.data.param_prio = prio;
- break;
- case MME:
- msg.header.data.type = MBX_MSG_TYPE_DATA;
- msg.header.data.length = 1;
- TRACE("SEND data mme\n");
- msg.header.data.param_type = MBX_MSG_DATA_TYPE_MME;
- msg.header.data.param_length = length;
- msg.header.data.param_prio = prio;
- break;
- case INTERFACE:
- msg.header.interface.type = MBX_MSG_TYPE_INTERFACE;
- msg.header.interface.length = 1;
- TRACE("SEND interface\n");
- msg.header.interface.param_type = MBX_MSG_INTERFACE_TYPE_FCALL;
- msg.header.interface.param_length = length;
- break;
- default:
- return -1;
- }
-
- //Data construction
- msg.data.buffer_ptr = (uint32_t)pointer;
-
-#ifdef __UTESTS__
- //For Utests we need to return the msg to check it
- memcpy(mbx_send_result, &msg, sizeof(mbx_send_result));
-#endif
-
- //Send the message
- //we consider that all sending
- //messages(data or interface)
- //have field length at the same position
- return internal_mailbox_send((uint32_t*)&msg, sizeof(mbx_hdr_t) + (msg.header.generic.length * sizeof(uint32_t)));
-}// mailbox_send
-
-/**
- * Prepare the mailbox message
- * corresponding to a new buffer
- * and send it to CESAR.
- *
- * \param pointer the buffer pointer.
- * \param type type of message.
- * \return error code.
- */
-int mailbox_buffer_add(void *pointer, enum buffer_type type)
-{
- mbx_t msg;
-
- //Check pointer
- if(pointer == NULL)
- return -1;
-
- //Reset message variable
- memset(&msg, 0, sizeof(msg));
-
- //Header construction
- msg.header.buffer_add.type = MBX_MSG_TYPE_BUFFER_ADD;
- msg.header.buffer_add.length = 1;
- switch(type)
- {
- case DATA:
- TRACE("SEND BUFF ADD type data\n");
- msg.header.buffer_add.param_type = MBX_MSG_BUFF_ADD_TYPE_DATA;
- break;
- case MME:
- TRACE("SEND BUFF ADD type mme\n");
- msg.header.buffer_add.param_type = MBX_MSG_BUFF_ADD_TYPE_MME;
- break;
- case INTERFACE:
- TRACE("SEND BUFF ADD type interface\n");
- msg.header.buffer_add.param_type = MBX_MSG_BUFF_ADD_TYPE_INTERFACE;
- break;
- default:
- return -1;
- }
-
- //Data construction
- msg.data.buffer_ptr = (uint32_t)pointer;
-
-#ifdef __UTESTS__
- //For Utests we need to return the msg to check it
- memcpy(mbx_buffer_add_result, &msg, sizeof(mbx_buffer_add_result));
-#endif
-
- //Send the message
- return internal_mailbox_send((uint32_t*)&msg, sizeof(mbx_hdr_t) + (msg.header.buffer_add.length * sizeof(uint32_t)));
-}// mailbox_buffer_add
-
-int mailbox_send_debug_dump(void *buffer, uint length)
-{
- mbx_t msg;
-
- //Check parameters.
- BUG_ON(buffer == NULL || length == 0 || length > (u16)(-1));
-
- //Ensure message is clean.
- memset(&msg, 0, sizeof(msg));
-
- //Fill header of message.
- msg.header.debug_dump.type = MBX_MSG_TYPE_DEBUG_DUMP;
- msg.header.debug_dump.length = 1;
- msg.header.debug_dump.param_length = length;
-
- //Fill data.
- msg.data.buffer_ptr = (uint32_t)buffer;
-
- //Send the message.
- return internal_mailbox_send
- ((uint32_t*)&msg,
- sizeof(mbx_hdr_t) + (msg.header.generic.length * sizeof(uint32_t)));
-}
-
-/**
- * Manage the Hardware after knowing
- * that a txdone arrived.
- *
- * \return error code.
- */
-int mailbox_txdone(void)
-{
- //Just clear the interrupt
- clr_A2La_interrupt(ctx);
- return 0;
-}
-
-/**
- * Receive everything from the HLE layer.
- *
- * \param budget budget before giving hand to caller
- * \return error code.
- */
-int mailbox_receive(unsigned int *budget)
-{
- mbx_t msg;
- int result=0;
-
- while(halmbx_L2Amail_not_empty_queue(ctx) && *budget)
- {
- (*budget)--;
-
- //Copy the new message from the ring buffer
- //we copy the max size of a message even it's to big
- if(halmbx_copy_from_ring(ctx, (uint32_t*)&msg, sizeof(msg)))
- {
- return -2;
- }
-
- //Update the ring management
- //we consider that all received
- //messages(data, send_done or interface)
- //have field length at the same position
- if(halmbx_L2Amail_update(ctx, sizeof(mbx_hdr_t) + (msg.header.generic.length * sizeof(uint32_t))))
- {
- return -3;
- }
-
- //Ring correctly updated
- //say to Leon that the msg is correctly sent
- set_L2Aa_interrupt(ctx);
-
- //Proceed the message
- //we consider that all received
- //messages(data, send_done or interface)
- //have field type at the same position
- switch(msg.header.generic.type)
- {
- case MBX_MSG_TYPE_SEND_DONE:
- TRACE("RECEIVE a send_done\n");
- if(processing_buffer_free((void*)msg.data.buffer_ptr))
- {
- printk (KERN_WARNING "plc mailbox: Rx SEND_DONE failed\n");
- result = -4;
- }
- else
- {
- result = 0;
- }
- break;
-
- case MBX_MSG_TYPE_INTERFACE:
- TRACE("RECEIVE an interface\n");
- //Transmit to the upper layers
- if(processing_receive((void*)msg.data.buffer_ptr, msg.header.interface.param_length, INTERFACE))
- {
- result = -5;
- break;
- }
- result = 0;
- break;
-
- case MBX_MSG_TYPE_DATA:
- //Transmit to the upper layers
- if(msg.header.data.param_type == MBX_MSG_DATA_TYPE_MME)
- {
- TRACE("RECEIVE a data mme\n");
- if(processing_receive((void*)msg.data.buffer_ptr, msg.header.data.param_length, MME))
- {
- printk (KERN_WARNING "plc mailbox: Rx DATA failed\n");
- result = -6;
- break;
- }
- }
- else
- {
- TRACE("RECEIVE a data data\n");
- if(processing_receive((void*)msg.data.buffer_ptr, msg.header.data.param_length, DATA))
- {
- result = -7;
- break;
- }
- }
- result = 0;
- break;
- case MBX_MSG_TYPE_DEBUG_DUMP:
- if(processing_debug_dump_buffer_receive((void*)msg.data.buffer_ptr,
- msg.header.debug_dump.param_length))
- {
- result = -8;
- break;
- }
- result = 0;
- break;
- default:
- result = -1;
- break;
- }
- if(result)
- break;
- }
-
- return result;
-}// mailbox_receive
-
-/**
- * Receive part for interrupt context.
- */
-void mailbox_receive_isr(void)
-{
- //Only clear interrupt.
- clr_L2At_interrupt(ctx);
-
- //Receive work is done under mailbox_receive function
- //mailbox_receive will be called in a non IRQ context
-
-}// mailbox_receive_isr
-
diff --git a/cleopatre/devkit/plcdrv/src/plcdrv.c b/cleopatre/devkit/plcdrv/src/plcdrv.c
new file mode 100644
index 0000000000..a78386ea46
--- /dev/null
+++ b/cleopatre/devkit/plcdrv/src/plcdrv.c
@@ -0,0 +1,885 @@
+/* Cleopatre project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/plcdrv.c
+ * \brief PLC driver management functions.
+ * \ingroup plcdrv
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/afe.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/kdev_t.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+#include <linux/list.h>
+#include <linux/netlink.h>
+#include <linux/poll.h>
+#include <linux/wait.h>
+#include <net/seq_check.h>
+
+#include <asm/arch/nvram.h>
+#include <asm/arch/hardware/regbank.h>
+#include <asm/arch/ioctl.h>
+
+#include "plcdrv.h"
+#include "frame.h"
+#include "firmware.h"
+#include "boot_params.h"
+#include "registers.h"
+
+#define DRV_NAME "SPC300"
+#define DRV_LAYER "PLC "
+#define DRV_RELDATE __DATE__ " " __TIME__
+
+MODULE_AUTHOR ("SPiDCOM Technologies");
+MODULE_DESCRIPTION ("SPC300 PLC driver");
+MODULE_LICENSE ("SPiDCOM Technologies 2009");
+
+/**
+ * Define DSU trace modes
+ */
+#define DSU_TRACE_NONE 0
+#define DSU_TRACE_PROC 1
+#define DSU_TRACE_AHB 2
+#define DSU_TRACE_ALL 3
+
+/**
+ * Fake address used to detect that a leon_start_addr was provided as a
+ * module param.
+ */
+#define INVALID_LEON_START_ADDR 1
+
+/** Time Out for Leon start (in ms). */
+#define TOUT_LEON_START 2000
+/** Step Time Out for Leon start (in ms). */
+#define TOUT_LEON_START_STEP 20
+
+/** Parameters for the module. */
+static uint32_t leon_start_addr = INVALID_LEON_START_ADDR;
+static uint32_t dsu_ctrl = (LEON_DSU_BZ | LEON_DSU_BD | LEON_DSU_BW
+ | LEON_DSU_BE | LEON_DSU_TE);
+static uint32_t dsu_trace = DSU_TRACE_PROC;
+static int debug = 0;
+
+module_param (leon_start_addr, uint, 0644);
+MODULE_PARM_DESC (leon_start_addr, "PLC code start address");
+module_param_string (boot_params, custom_boot_params,
+ sizeof (custom_boot_params), 0644);
+MODULE_PARM_DESC (custom_boot_params, "PLC Boot Parameters");
+module_param (dsu_ctrl, uint, 0644);
+MODULE_PARM_DESC (dsu_ctrl, "Configure the PLC Processor debugger");
+module_param (dsu_trace, uint, 0644);
+MODULE_PARM_DESC (dsu_trace, "Configure the PLC Processor trace "
+ "(0=no; 1=proc; 2=AHB; 3=all)");
+module_param (debug, int, 0644);
+MODULE_PARM_DESC (debug, "Let's the user start PLC Processor by debugger");
+
+/** These identify the driver base version. */
+static char version[] __devinitdata = DRV_NAME " PLC driver v" DRV_VERSION
+ " (" DRV_RELDATE ")\n";
+
+/** Our global net device. */
+static struct net_device *plcdrv_device;
+
+/**
+ * Configure AFE with the default configuration.
+ * \return negative value if error, 0 if no error
+ */
+static int
+init_afe (void)
+{
+ int ret;
+
+#ifdef CONFIG_MACH_ARIZONA
+ ret = afe_write_reg (0x03, 0x04)
+ || afe_write_reg (0x04, 0x35)
+ || afe_write_reg (0x06, 0x44)
+ || afe_write_reg (0x0A, 0x7F)
+ || afe_write_reg (0x0C, 0x43)
+ || afe_write_reg (0x0D, 0x01)
+ || afe_write_reg (0x0E, 0x80);
+#else
+ ret = afe_write_reg (0x04, 0x16)
+ || afe_write_reg (0x05, 0x80)
+ || afe_write_reg (0x07, 0x20)
+ || afe_write_reg (0x0A, 0x7F) // TODO: check diff values 9865 / 9867
+ || afe_write_reg (0x0B, 0x20)
+ || afe_write_reg (0x0C, 0x51) // TODO: check diff values 9865 / 9867
+ || afe_write_reg (0x0D, 0x01)
+ || afe_write_reg (0x0E, 0x08)
+ || afe_write_reg (0x03, 0xF8);
+#endif
+ return ret;
+}
+
+/**
+ * Read Version number by /proc.
+ * \param page buffer to write data to
+ * \param start unused
+ * \param offset unused
+ * \param count unused
+ * \param eof to be set if end of file reached
+ * \param data priv structure
+ * \return number of read bytes
+ */
+static int
+plcdrv_readproc_version (char *page, char **start, off_t offset, int count,
+ int *eof, void *data)
+{
+ plcdrv_t *priv = data;
+ char *p;
+
+ p = page;
+ p += sprintf (p, "%s: %s\n", "PLC Driver", DRV_VERSION);
+ p += sprintf (p, "%s: %s\n", "PLC Firmware", priv->version);
+ *eof = 1;
+
+ return p - page;
+}
+
+/**
+ * Read plc stats.
+ * \param page buffer to write data to
+ * \param start unused
+ * \param offset unused
+ * \param count unused
+ * \param eof to be set if end of file reached
+ * \param data priv structure
+ * \return number of read bytes
+ */
+static int
+plcdrv_readproc_plc_stats (char *page, char **start, off_t offset, int count,
+ int *eof, void *data)
+{
+ char *p;
+ plcdrv_t *priv = data;
+ plcdrv_stats_t *stats = &priv->plcdrv_stats;
+
+ p = page;
+ p += sprintf (p, "skb_to_fw_no_headroom: %d\n",
+ atomic_read (&stats->skb_to_fw_no_headroom));
+ *eof = 1;
+
+ return p - page;
+}
+
+/**
+ * Set/Unset Reset the Leon processor.
+ * \param activate true to activate reset
+ * \return error code
+ */
+static int
+plcdrv_reset_leon (bool activate)
+{
+ if (activate)
+ {
+ RB_RST_GROUP_VA |= RST_LEONSS;
+ if (!(RB_RST_GROUP_VA & RST_LEONSS))
+ return -1;
+
+ RB_RST_MODULE_VA |= RST_LCPU;
+ if (!(RB_RST_MODULE_VA & RST_LCPU))
+ return -1;
+ }
+ else
+ {
+ RB_RST_GROUP_VA &= ~RST_LEONSS;
+ if (RB_RST_GROUP_VA & RST_LEONSS)
+ return -1;
+
+ RB_RST_MODULE_VA &= ~RST_LCPU;
+ if (RB_RST_MODULE_VA & RST_LCPU)
+ return -1;
+ }
+
+ return 0;
+}
+
+/**
+ * Set/Unset Reset the DSP.
+ * \param activate true to activate reset
+ * \return error code
+ */
+static int
+plcdrv_reset_dsp (bool activate)
+{
+ if (activate)
+ {
+ RB_RST_GROUP_VA |= RST_DSP;
+ if (!(RB_RST_GROUP_VA & RST_DSP))
+ return -1;
+ }
+ else
+ {
+ RB_RST_GROUP_VA &= ~RST_DSP;
+ if (RB_RST_GROUP_VA & RST_DSP)
+ return -1;
+ }
+
+ return 0;
+}
+
+/**
+ * Launch the Leon processor.
+ * \param priv PLC device private context
+ * \param dsu_trace LEON trace mode
+ * \param debug_mode 1 for debug mode, 0 otherwise
+ * \return error code
+ */
+static int
+plcdrv_launch_leon (plcdrv_t *priv, uint32_t dsu_trace, int debug_mode)
+{
+ uint32_t *leon_dsu_ptr;
+ uint32_t *leon_wd_ptr;
+ uint32_t *leon_trace_ptr;
+ unsigned int timeout = 0;
+
+ /* Prepare Leon registers accesses. */
+ leon_dsu_ptr = (uint32_t *) ioremap (LEON_DSU_CTRL_BASE_ADDR, 1);
+ leon_trace_ptr = (uint32_t *) ioremap (LEON_TRACE_CTRL_BASE_ADDR, 1);
+ leon_wd_ptr = (uint32_t *) ioremap (LEON_WD_BASE_ADDR, 1);
+
+ /* Set trace mode for leon. */
+ switch (dsu_trace)
+ {
+ case DSU_TRACE_NONE:
+ dsu_ctrl &= ~LEON_DSU_TE;
+ *leon_trace_ptr &= ~(LEON_TRACE_PROC_EN | LEON_TRACE_AHB_EN);
+ break;
+
+ case DSU_TRACE_ALL:
+ dsu_ctrl |= LEON_DSU_TE;
+ *leon_trace_ptr |= (LEON_TRACE_PROC_EN | LEON_TRACE_AHB_EN);
+ break;
+
+ case DSU_TRACE_AHB:
+ dsu_ctrl |= LEON_DSU_TE;
+ *leon_trace_ptr &= ~(LEON_TRACE_PROC_EN);
+ *leon_trace_ptr |= (LEON_TRACE_AHB_EN);
+ break;
+
+ case DSU_TRACE_PROC:
+ default:
+ dsu_ctrl |= LEON_DSU_TE;
+ *leon_trace_ptr &= ~(LEON_TRACE_AHB_EN);
+ *leon_trace_ptr |= (LEON_TRACE_PROC_EN);
+ }
+
+ /* Refresh watchdog before running (for 10 seconds). */
+ *leon_wd_ptr = LEON_WD_REFRESH (10);
+
+ /* Configure DSU + Resume Leon processor execution. */
+ *leon_dsu_ptr = (dsu_ctrl & ~(LEON_DSU_BN | LEON_DSU_FT));
+
+ /* Check if processor is running. */
+ if ((*leon_dsu_ptr) & LEON_DSU_BN)
+ return -1;
+
+ /* Release reset Leon register. */
+ iounmap ((void *) leon_dsu_ptr);
+ iounmap ((void *) leon_wd_ptr);
+ iounmap ((void *) leon_trace_ptr);
+
+ /* Now the Leon is started we have to wait leon mailbox initialization
+ * before continuing. */
+ while (!ipmbox_is_synchronized (&priv->ipmbox))
+ {
+ msleep_interruptible (TOUT_LEON_START_STEP);
+ if (!debug_mode)
+ {
+ timeout += TOUT_LEON_START_STEP;
+ if (timeout >= TOUT_LEON_START)
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Open the character device.
+ * \param inp inode structure
+ * \param filp file structure
+ * \return error code
+ */
+static int
+plcdrv_char_open (struct inode *inp, struct file *filp)
+{
+ plcdrv_t *priv = netdev_priv (plcdrv_device);
+
+ /* Store private data. */
+ filp->private_data = priv;
+
+ return 0;
+}
+
+/**
+ * Poll the character device.
+ * \param filp file structure
+ * \param wait poll table structure
+ * \return error code
+ */
+static unsigned int
+plcdrv_char_poll (struct file *filp, poll_table *wait)
+{
+ plcdrv_t *priv = filp->private_data;
+
+ poll_wait (filp, &priv->wd.wq, wait);
+
+ if (atomic_read (&priv->wd.expired) == 1)
+ return POLLPRI;
+
+ return 0;
+}
+
+/** Character device functions */
+static struct file_operations plcdrv_fops =
+{
+ .owner = THIS_MODULE,
+ .open = plcdrv_char_open,
+ .poll = plcdrv_char_poll,
+};
+
+/**
+ * Read from trace character device.
+ * \param filp file structure
+ * \param buf user data pointer
+ * \param f_pos position
+ * \return error code
+ */
+static int
+plcdrv_trace_read (struct file *filp, char __user *buf, size_t count,
+ loff_t *f_pos)
+{
+ return debug_dump_read (filp->private_data, buf, count, f_pos);
+}
+
+/**
+ * Open trace character device.
+ * \param inp inode structure
+ * \param filp file structure
+ * \return error code
+ */
+static int
+plcdrv_trace_open (struct inode *inp, struct file *filp)
+{
+ plcdrv_t *priv = netdev_priv (plcdrv_device);
+
+ /* Store private data. */
+ filp->private_data = priv;
+
+ /* Call open function. */
+ return debug_dump_open (priv);
+}
+
+/**
+ * Release the trace character device.
+ * \param inp inode structure
+ * \param filp file structure
+ * \return error code
+ */
+static int
+plcdrv_trace_release (struct inode *inp, struct file *filp)
+{
+ debug_dump_release (filp->private_data);
+
+ return 0;
+}
+
+/** File operations for trace char device. */
+static struct file_operations plcdrv_fops_trace =
+{
+ .owner = THIS_MODULE,
+ .read = plcdrv_trace_read,
+ .open = plcdrv_trace_open,
+ .release = plcdrv_trace_release,
+};
+
+/**
+ * Transmit a frame received from DRV NETLINK.
+ * \param skb frame structure
+ */
+static void
+plcdrv_netlink_tx (struct sk_buff *skb)
+{
+ struct sk_buff *our_skb;
+ plcdrv_t *priv = netdev_priv (plcdrv_device);
+
+ /* Copy skb - will be freed by empty buffer later. */
+ our_skb = skb_copy (skb, GFP_ATOMIC);
+
+ /* If allocation failed, nothing to do. */
+ if (!our_skb)
+ return;
+
+ /* Remove netlink header. */
+ skb_pull (our_skb, NLMSG_HDRLEN);
+
+ /* Send it to MBX queue. */
+ frame_tx_mbx_mme_priv (priv, our_skb);
+}
+
+/**
+ * Interrupt Handler Watchdog procedure.
+ * \param irq interrupt number
+ * \param dev_id device structure
+ * \return error code
+ */
+static irqreturn_t
+plcdrv_it_wd (int irq, void *dev_id)
+{
+ plcdrv_t *priv = netdev_priv (dev_id);
+
+ /* Is some process waiting on a select()? */
+ if (!waitqueue_active (&priv->wd.wq))
+ {
+ /* Reset */
+ /* Can't use one of the kernel reboot functions (like
+ * kernel_restart()) because of the EXPORT_SYMBOL_GPL. */
+ RB_RST_GLOBAL_VA = 1;
+ }
+ else
+ {
+ /* Wake up the process waiting on the select(), and let it handle the
+ * situation. */
+ atomic_set (&priv->wd.expired, 1);
+ wake_up (&priv->wd.wq);
+ priv->ipmbox.regs->l2a_it_mask |= IPMBOX_L2A_IT_WD;
+ }
+
+ return IRQ_HANDLED;
+}
+
+/**
+ * Interrupt Handler Receive procedure.
+ * \param irq interrupt number
+ * \param dev_id device structure
+ * \return error code
+ */
+static irqreturn_t
+plcdrv_it_rx (int irq, void *dev_id)
+{
+ struct net_device *dev = dev_id;
+ plcdrv_t *priv = netdev_priv (dev);
+
+ /* Mask interrupt. */
+ priv->ipmbox.regs->l2a_it_mask |= IPMBOX_L2A_IT;
+
+ /* Schedule NAPI poll function. */
+ netif_rx_schedule (dev, &priv->napi);
+
+ return IRQ_HANDLED;
+}
+
+/**
+ * Read packet status from the device.
+ * \param dev device structure
+ * \return the device stats
+ */
+static struct net_device_stats *
+plcdrv_stats (struct net_device *dev)
+{
+ plcdrv_t *priv = netdev_priv (dev);
+
+ return &priv->stats;
+}
+
+/**
+ * Change the MTU.
+ * \param dev device structure
+ * \param new_mtu the new mtu value
+ * \return error code
+ */
+int
+plcdrv_change_mtu (struct net_device *dev, int new_mtu)
+{
+ /* Check parameters. */
+ if (new_mtu < 64 || new_mtu > 1508)
+ return -EINVAL;
+ else
+ {
+ dev->mtu = new_mtu;
+ return 0;
+ }
+}
+
+/**
+ * Change the MAC address.
+ * \param dev device structure
+ * \param p mac addr source
+ * \return error code
+ */
+int
+plcdrv_set_mac_address (struct net_device *dev, void *p)
+{
+ struct sockaddr *addr = p;
+
+ memcpy (dev->dev_addr, addr->sa_data, dev->addr_len);
+
+ return 0;
+}
+
+/**
+ * User control device interface.
+ * \param dev device structure
+ * \param ifr user exchange structure
+ * \param cmd command to execute
+ * \return error code
+ */
+static int
+plcdrv_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+ plcdrv_t *priv = netdev_priv (dev);
+ struct plcdrv_setpid user_data;
+
+ /* Find the command. */
+ switch (cmd)
+ {
+ case PLCDRV_IOCTL_SETPID:
+ /* Get user data */
+ if (copy_from_user (&user_data, ifr->ifr_data, sizeof (user_data)))
+ return -EFAULT;
+
+ /* During initialization, plcd & managerd register their PID
+ * for reception on DRV & MME netlink. */
+ if (NETLINK_PLC_DRV == user_data.nl)
+ {
+ priv->nl_plcd.pid = user_data.pid;
+ printk (KERN_INFO "%s: plcd registered with PID %d\n", dev->name,
+ priv->nl_plcd.pid);
+ }
+ if (NETLINK_PLC_MME == user_data.nl)
+ {
+ priv->nl_managerd.pid = user_data.pid;
+ printk (KERN_INFO "%s: managerd registered with PID %d\n",
+ dev->name, priv->nl_managerd.pid);
+ }
+
+ /* In case of another netlink, do nothing */
+ break;
+
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+/**
+ * Initialize the device.
+ * \param dev net device structure
+ * \return error code
+ */
+static int
+plcdrv_open (struct net_device *dev)
+{
+ plcdrv_t *priv = netdev_priv (dev);
+ int ret;
+
+ /* Request firmware. */
+ ret = firmware_load (dev);
+ if (ret != 0)
+ {
+ printk (KERN_ERR "%s: error while loading firmware\n", dev->name);
+ return ret;
+ }
+
+ /* Configure AFE with the default configuration. */
+ if (init_afe ())
+ return -EFAULT;
+
+ /* Unreset Leon Processor. */
+ if (plcdrv_reset_leon (false))
+ return -1;
+
+ /* Clear watchdog expiration flag. */
+ atomic_set (&priv->wd.expired, 0);
+
+ /* Init IPMbox */
+ ret = ipmbox_init (&priv->ipmbox, dev, plcdrv_it_rx, plcdrv_it_wd);
+ if (ret < 0)
+ return ret;
+
+ /* If we are here Leon code was already downloaded so,
+ * we need to start the Leon processor.
+ * It must be done after ARM head and tail pointers initialization because
+ * firmware use it to set the rings base addresses. */
+ if (!debug)
+ {
+ ret = plcdrv_launch_leon (priv, dsu_trace, debug);
+ if (ret < 0)
+ goto clean_ipmbox;
+ }
+
+ /* Allocate RX buffer pool to give to CESAR. */
+ skb_queue_head_init (&priv->rx_pool);
+ if (!frame_buffer_alloc (priv))
+ {
+ ret = -ENOMEM;
+ goto clean_pool;
+ }
+
+ /* Initialize TX pool lists. */
+ skb_queue_head_init (&priv->tx_pool_data);
+ skb_queue_head_init (&priv->tx_pool_mme);
+
+ /* Initialize netlink functions. */
+ priv->nl_plcd.sock
+ = netlink_kernel_create (&init_net, NETLINK_PLC_DRV, 0,
+ plcdrv_netlink_tx, NULL, THIS_MODULE);
+ if (!priv->nl_plcd.sock)
+ {
+ ret = -1;
+ goto clean_pool;
+ }
+
+ priv->nl_managerd.sock
+ = netlink_kernel_create (&init_net, NETLINK_PLC_MME, 0,
+ plcdrv_netlink_tx, NULL, THIS_MODULE);
+ if (!priv->nl_managerd.sock)
+ {
+ ret = -1;
+ goto clean_nl_plcd;
+ }
+
+ /* Enable NAPI poll. */
+ napi_enable (&priv->napi);
+
+ /* Prepare Linux as link up. */
+ netif_carrier_on (dev);
+ netif_start_queue (dev);
+
+ return 0;
+
+clean_nl_plcd:
+ netlink_kernel_release (priv->nl_plcd.sock);
+clean_pool:
+ __skb_queue_purge (&priv->rx_pool);
+clean_ipmbox:
+ ipmbox_uninit (&priv->ipmbox, dev);
+ return ret;
+}
+
+/**
+ * Uninitialize the device.
+ * \param dev device structure
+ * \return error code
+ */
+static int
+plcdrv_stop (struct net_device *dev)
+{
+ plcdrv_t *priv = netdev_priv (dev);
+
+ /* Disable transmitter. */
+ netif_stop_queue (dev);
+ netif_carrier_off (dev);
+
+ /* Disable NAPI poll. */
+ napi_disable (&priv->napi);
+
+ /* Stop netlink interface. */
+ netlink_kernel_release (priv->nl_plcd.sock);
+ netlink_kernel_release (priv->nl_managerd.sock);
+
+ /* Reset LEON and DSP. */
+ plcdrv_reset_leon (true);
+ plcdrv_reset_dsp (true);
+ plcdrv_reset_dsp (false);
+
+ ipmbox_uninit (&priv->ipmbox, dev);
+
+ /* Clean our queue, we can not rely on ipmbox content. */
+ __skb_queue_purge (&priv->rx_pool);
+ __skb_queue_purge (&priv->tx_pool_data);
+ __skb_queue_purge (&priv->tx_pool_mme);
+
+ return 0;
+}
+
+/**
+ * Uninitialise the network device.
+ * \param dev device structure
+ */
+static void
+plcdrv_uninit (struct net_device *dev)
+{
+ plcdrv_t *priv = netdev_priv (dev);
+
+ /* Unregister character device. */
+ cdev_del (&priv->cdev);
+ cdev_del (&priv->cdev_trace);
+ unregister_chrdev_region (priv->dev_number, 2);
+
+ /* Remove proc. */
+ remove_proc_entry ("stats", priv->proc_dir_plc);
+ remove_proc_entry ("version", priv->proc_dir_plc);
+ remove_proc_entry ("plc", init_net.proc_net);
+}
+
+/**
+ * Initialise the network device.
+ * \param dev device structure
+ * \return error code
+ */
+static int
+plcdrv_init (struct net_device *dev)
+{
+ plcdrv_t *priv = netdev_priv (dev);
+ uint32_t *leon_start_addr_ptr;
+ int result;
+
+ /* Initialise debug dump. */
+ debug_dump_init (priv);
+
+ /* Register a character device to manage firmware binary download. */
+ /* Allocate character device Major number. */
+ result = alloc_chrdev_region (&priv->dev_number, 0, 2, "plcdrv");
+ if (result < 0)
+ {
+ printk (KERN_ERR DRV_NAME ": can't get major %d\n",
+ MAJOR (priv->dev_number));
+ goto error_cdev_region_alloc;
+ }
+ /* Register PLC driver character device. */
+ cdev_init (&priv->cdev, &plcdrv_fops);
+ priv->cdev.owner = THIS_MODULE;
+ result = cdev_add (&priv->cdev,
+ MKDEV (MAJOR (priv->dev_number),
+ MINOR (priv->dev_number)),
+ 1);
+ if (result < 0)
+ {
+ printk (KERN_ERR DRV_NAME ": error registering plcdrv device\n");
+ goto error_cdev_add_plcdrv;
+ }
+
+ /* Register trace character device. */
+ cdev_init (&priv->cdev_trace, &plcdrv_fops_trace);
+ priv->cdev_trace.owner = THIS_MODULE;
+ result = cdev_add (&priv->cdev_trace,
+ MKDEV (MAJOR (priv->dev_number),
+ MINOR (priv->dev_number) + 1),
+ 1);
+ if (result < 0)
+ {
+ printk (KERN_ERR DRV_NAME ": error registering trace device\n");
+ goto error_cdev_add_trace;
+ }
+
+ /* Create proc entries. */
+ priv->proc_dir_plc = proc_mkdir ("plc", init_net.proc_net);
+ create_proc_read_entry ("version", 0, priv->proc_dir_plc,
+ plcdrv_readproc_version, priv);
+ create_proc_read_entry ("stats", 0, priv->proc_dir_plc,
+ plcdrv_readproc_plc_stats, priv);
+
+ /* Set Leon code base address (translation). */
+ leon_start_addr_ptr = (uint32_t *) ioremap (RB_LEON_ADD_START, 1);
+ /* If a custom value was passed as a module parameter, use it.
+ * Otherwise, use the default one. */
+ *leon_start_addr_ptr = (leon_start_addr != INVALID_LEON_START_ADDR) ?
+ leon_start_addr : spc300_plc_mem_start;
+ iounmap (leon_start_addr_ptr);
+
+ /* Initialise device functions. */
+ ether_setup (dev);
+ dev->uninit = plcdrv_uninit;
+ dev->open = plcdrv_open;
+ dev->stop = plcdrv_stop;
+ dev->do_ioctl = plcdrv_ioctl;
+ dev->set_mac_address = plcdrv_set_mac_address;
+ dev->hard_start_xmit = frame_tx_data;
+ dev->get_stats = plcdrv_stats;
+ dev->change_mtu = plcdrv_change_mtu;
+
+ /* Init NAPI structure. */
+ netif_napi_add (dev, &priv->napi, ipmbox_receive, IPMBOX_RX_BUDGET);
+
+ /* Setup MAC address for Linux (stored in NVRAM). */
+ memcpy (dev->dev_addr, spc300_nvram.plc_address,
+ ARRAY_SIZE (spc300_nvram.plc_address));
+
+ /* Initialize structure for poll/select management. */
+ init_waitqueue_head (&priv->wd.wq);
+
+ seq_check_init (&priv->seq_check_ctx, "plc_drv");
+
+ return 0;
+
+error_cdev_add_trace:
+ cdev_del (&priv->cdev);
+error_cdev_add_plcdrv:
+ unregister_chrdev_region (priv->dev_number, 2);
+error_cdev_region_alloc:
+ return result;
+}
+
+/**
+ * Initialise the module.
+ * \return error code
+ */
+int __init
+plcdrv_module_init (void)
+{
+ int result;
+ struct net_device *dev = NULL;
+ struct plcdrv_t *priv;
+
+ /* Print version. */
+ printk ("%s", version);
+
+ /* Register the network device. */
+ /* Allocate device memory. */
+ dev = alloc_netdev (sizeof (plcdrv_t), "plc%d", ether_setup);
+ if (!dev)
+ return -ENOMEM;
+ BUG_ON (!dev->priv);
+
+ /* Initialize private structure. */
+ memset (dev->priv, 0, sizeof (plcdrv_t));
+
+ /* Proceed the init driver. */
+ dev->init = plcdrv_init;
+
+ /* Store global plcdrv context. */
+ plcdrv_device = dev;
+ priv = netdev_priv (dev);
+ priv->dev = dev;
+
+ /* Register network device. */
+ result = register_netdev (dev);
+ if (result < 0)
+ {
+ /* Clean. */
+ free_netdev (dev);
+ return result;
+ }
+
+ return 0;
+}
+
+/**
+ * Uninitialise the module.
+ */
+void __exit
+plcdrv_module_exit (void)
+{
+ /* Unregister network device. */
+ unregister_netdev (plcdrv_device);
+ /* Free it. */
+ free_netdev (plcdrv_device);
+ plcdrv_device = NULL;
+}
+
+module_init (plcdrv_module_init);
+module_exit (plcdrv_module_exit);
diff --git a/cleopatre/devkit/plcdrv/src/processing.c b/cleopatre/devkit/plcdrv/src/processing.c
deleted file mode 100644
index fa998fd0b3..0000000000
--- a/cleopatre/devkit/plcdrv/src/processing.c
+++ /dev/null
@@ -1,352 +0,0 @@
-/* Cleopatre project {{{
- *
- * Copyright (C) 2008 Spidcom
- *
- * <<<Licence>>>
- *
- * }}} */
-/**
- * \file processing.c
- * \brief Processing Layer
- * \ingroup Cleopatre - PlcDrv
- *
- * This file content the processing layer, this layer will analyse all frames
- * (TX ans RX) and decided to pass and drop it.
- */
-
-#include "common.h"
-#include "linux_drv.h"
-#include "processing.h"
-#include "mailbox.h"
-
-#ifndef __UTESTS__
-#include <linux/if_ether.h>
-#include <linux/if_vlan.h>
-#include <asm/byteorder.h>
-#else //__UTESTS__
-#include <linux/types.h>
-#include <linux/bitops.h>
-#include <linux/kernel.h>
-#include <linux/if_ether.h>
-#include <linux/if_vlan.h>
-#endif // __UTESTS__
-
-/** Define Debug/Trace Level */
-#define TRACE(...) if(test_bit(TRACE_PROCESS, (const volatile unsigned long*)&trace)) printk(KERN_INFO "SPC300: PROC: " __VA_ARGS__)
-
-/** Define HPAV MME format */
-#define ETH_MME_VERSION_OFFSET (sizeof(struct ethhdr))
-#define ETH_MME_VERSION_SIZE (1)
-#define ETH_MME_TYPE_OFFSET (ETH_MME_VERSION_OFFSET + ETH_MME_VERSION_SIZE)
-#define ETH_MME_TYPE_SIZE (2)
-#define ETH_MME_FMI_OFFSET (ETH_MME_TYPE_OFFSET + ETH_MME_TYPE_SIZE)
-#define ETH_MME_FMI_SIZE (2)
-
-/** Define VLAN format */
-#define VLAN_CFI_MASK 0x1000
-#define VLAN_PRIO_MASK 0xe000
-#define VLAN_VID_SHIFT 0
-#define VLAN_CFI_SHIFT 12
-#define VLAN_PRIO_SHIFT 13
-
-#define VLAN_PRIO(tci) ((tci & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT)
-#define VLAN_MAX_PRIO 7
-#define VLAN_MME_PRIO 6 /** VLAN priorities 6 and 7 correspond to CAP 3. */
-
-/**
- * Find the Ethernet source Address.
- *
- * \param eth_frame Ethernet frame pointer.
- * \param source final source address copy.
- * \return source address pointer.
- */
-uint8_t* get_eth_src_addr(uint8_t* eth_frame, uint8_t source[ETH_ALEN])
-{
- struct ethhdr *eth = (struct ethhdr *) eth_frame;
- if(source != NULL)
- memcpy(source, eth->h_source, ETH_ALEN);
- return (uint8_t*)eth->h_source;
-}// get_eth_src_addr
-
-/**
- * Find the Ethernet source Address.
- *
- * \param eth_frame Ethernet frame pointer.
- * \param dest final destination address copy.
- * \return destination address pointer.
- */
-uint8_t* get_eth_dst_addr(uint8_t* eth_frame, uint8_t dest[ETH_ALEN])
-{
- struct ethhdr *eth = (struct ethhdr *) eth_frame;
- if(dest != NULL)
- memcpy(dest, eth->h_dest, ETH_ALEN);
- return (uint8_t*)eth->h_dest;
-}// get_eth_dst_addr
-
-/**
- * Find the Ethernet type.
- *
- * \param eth_frame Ethernet frame pointer.
- * \return Ethernet type.
- */
-uint16_t get_eth_type(uint8_t* eth_frame)
-{
- struct ethhdr *eth = (struct ethhdr *) eth_frame;
- uint16_t result;
- result = ntohs(eth->h_proto);
- return result;
-}// get_eth_type
-
-/**
- * Find the Ethernet MME version.
- *
- * \param eth_frame Ethernet frame pointer.
- * \return HPAV MME version.
- */
-uint8_t get_eth_mme_version(uint8_t* eth_frame)
-{
- return *(eth_frame + ETH_MME_VERSION_OFFSET);
-}// get_eth_mme_version
-
-/**
- * Find the Ethernet MME type.
- *
- * \param eth_frame Ethernet frame pointer.
- * \return HPAV MME type.
- */
-uint16_t get_eth_mme_type(uint8_t* eth_frame)
-{
- //Warning: mme type is stored in little endian
- return *(uint16_t*)(eth_frame + ETH_MME_TYPE_OFFSET);
-}// get_eth_mme_type
-
-/**
- * Find the Ethernet MME type.
- *
- * \param eth_frame Ethernet frame pointer.
- * \return HPAV MME fmi.
- */
-uint16_t get_eth_mme_fmi(uint8_t* eth_frame)
-{
- //Warning: mme fmi is stored in little endian
- return *(uint16_t*)(eth_frame + ETH_MME_FMI_OFFSET);
-}// get_eth_mme_fmi
-
-
-/** Our global context */
-static struct processctx glbctx;
-
-/**
- * Initialize the processing layer.
- *
- * \param info initialisation structure.
- * \return error code.
- */
-int processing_init(struct init_info *info, struct net_device *dev)
-{
- //Check arguments
- if(info == NULL)
- return -1;
-
- if(NULL == dev)
- return -1;
-
- //Store Board and broadcast MAC addresses
- memcpy(glbctx.board_addr, info->mac_addr, ETH_ALEN);
- memset(glbctx.broadcast_addr, 0xFF, ETH_ALEN);
-
- //Init lower layers
- return mailbox_init(info, dev);
-}// processing_init
-
-/**
- * UnInitialize the processing layer.
- *
- * \return error code.
- */
-int processing_uninit(void)
-{
- //Uninit lower layers
- return mailbox_uninit();
-}// processing_uninit
-
-/**
- * Processing procedure to add a buffer to CESAR.
- *
- * \param pointer buffer pointer.
- * \param type type of the message pointed.
- * \return error code.
- */
-int processing_buffer_add(void *pointer, enum buffer_type type)
-{
- uint32_t phys_addr;
-
- if(!(phys_addr = prepare_buffer_to_hw((uint32_t)pointer, PKT_BUF_SZ,
- DATA_FROM_FW)))
- {
- return -1;
- }
- else
- {
- TRACE("virt@pointer=%x ; phys@pointer=%x\n",(unsigned int)pointer,phys_addr);
- return mailbox_buffer_add((void*)phys_addr, type);
- }
-}
-
-/**
- * Processing procedure to release a buffer from CESAR.
- *
- * \param pointer buffer pointer.
- * \return error code.
- */
-int processing_buffer_free(void *pointer)
-{
- uint32_t virt_addr;
-
- //Length should be the same as the one used by prepare_buffer_to_hw, but
- //we do not have it anymore (and it is not used in our architecture).
- //Should be corrected by PLC redesign.
- if(!(virt_addr = prepare_buffer_from_hw((uint32_t)pointer, PKT_BUF_SZ,
- DATA_TO_FW)))
- return -1;
- else
- {
- TRACE("virt@pointer=%x ; phys@pointer=%x\n",virt_addr,(unsigned int)pointer);
- return free_buffer((void*)virt_addr, TX_COMPLETE);
- }
-}
-
-/**
- * Processing procedure for a A->L message.
- *
- * \param pointer buffer pointer.
- * \param length length of the message pointed.
- * \return status queue.
- */
-int processing_send(void *pointer, int length, buffer_type_t type)
-{
- uint32_t phys_ptr;
- uint32_t vlan_prio = 0;
- int result;
-
- //Check pointer
- if(!pointer)
- return -1;
- //Check length
- if((length <= 0) || (length > PKT_BUF_SZ))
- return -1;
-
- //Check VLAN priority of VLAN frames
- if(get_eth_type((uint8_t*)pointer) == ETH_P_8021Q)
- vlan_prio = (uint32_t)VLAN_PRIO(ntohs(((struct vlan_ethhdr*)pointer)->h_vlan_TCI));
-
- /** Set VLAN priority to 6 or 7 for all Tx MME-s. */
- if (ETH_P_HPAV == get_eth_type ((uint8_t *) pointer))
- {
- vlan_prio = (uint32_t) VLAN_MME_PRIO;
- }
-
- //Find phys address and invalide cache
- if(!(phys_ptr = prepare_buffer_to_hw((uint32_t)pointer, length,
- DATA_TO_FW)))
- return -1;
-
- TRACE("virt@pointer=%x ; phys@pointer=%x\n",(unsigned int)pointer,phys_ptr);
-
- //Send to lower layer
- result = mailbox_send((void*)phys_ptr, length, vlan_prio, type);
-
- return result;
-}// processing_send
-
-/**
- * Processing procedure for a L->A message.
- *
- * \param pointer buffer pointer.
- * \param length length of the message pointed.
- * \param type type of message.
- * \return error code.
- */
-int processing_receive(void *pointer, int length, enum buffer_type type)
-{
- uint32_t virt_ptr;
- enum pkt_dest dst_type = OTHER;
-
- //Check pointer
- if(!pointer)
- return -1;
- //Check length
- if((length <= 0) || (length > PKT_BUF_SZ))
- return -1;
-
- //Find virtual address
- if(!(virt_ptr = prepare_buffer_from_hw((uint32_t)pointer, PKT_BUF_SZ,
- DATA_FROM_FW)))
- return -1;
-
- TRACE("virt@pointer=%x ; phys@pointer=%x\n",virt_ptr,(unsigned int)pointer);
-
- //TODO:Check which type of frame is it
- if((type == MME)
- || (type == INTERFACE))
- {
- TRACE("In the processing_receive : MME or INTERFACE\n");
- if(get_eth_mme_type ((uint8_t*)virt_ptr) >= HPAV_MME_P_DRV_BASE)
- {
- dst_type = NETLINK_DRV;
- }
- else
- {
- dst_type = NETLINK_MME;
- }
- }
- else if(type == DATA)
- {
- TRACE("In the processing_receive : DATA\n");
- }
-
- //Alloc a new corresponding buffer
- if(alloc_buffer(type))
- return -1;
-
- //TODO:if frame not ok drop it with free_buffer(pointer, RX_DROP)
-
- //TODO:Send the packet to the TX part with processing_send(pointer, length)
- //Or Send packet to the upper layers
- return plcdrv_rx((void*)virt_ptr, length, dst_type);
-}// processing_receive
-
-int processing_debug_dump_buffer_send(void *buffer)
-{
- uint32_t phys_addr;
-
- //Check parameters.
- BUG_ON(!buffer);
-
- //Cache synchronisation.
- phys_addr = prepare_buffer_to_hw((uint32_t)buffer, debug_dump_buffer_length, DATA_FROM_FW);
-
- //Send message to firmware.
- return mailbox_send_debug_dump((void *)phys_addr, debug_dump_buffer_length);
-}
-
-int processing_debug_dump_buffer_receive(void *buffer, int length)
-{
- //Check parameters.
- BUG_ON(!buffer);
- BUG_ON(length > debug_dump_buffer_length);
-
- //Sanity check.
- BUG_ON(debug_dump_waiting_for_buffer == false);
-
- //Cache synchronisation.
- BUG_ON(!prepare_buffer_from_hw((uint32_t)buffer, debug_dump_buffer_length, DATA_FROM_FW));
-
- //Copy received length.
- debug_dump_buffer_length_received = length;
-
- //Wake up our process.
- wake_up_interruptible(&debug_dump_wait_queue);
-
- return 0;
-}
diff --git a/cleopatre/devkit/tests/plcdrv/utests/Makefile b/cleopatre/devkit/tests/plcdrv/utests/Makefile
index 38ea0edb68..213f7d2d94 100644
--- a/cleopatre/devkit/tests/plcdrv/utests/Makefile
+++ b/cleopatre/devkit/tests/plcdrv/utests/Makefile
@@ -6,16 +6,18 @@ PROJECT_DIR = $(CLEO_BASE)/devkit/plcdrv
LINUX_STUB_BASE = $(CLEO_BASE)/devkit/tests/plcdrv/utests/stub/linux
-INCLUDES = $(PROJECT_DIR)/inc $(LINUX_STUB_BASE)/inc
+INCLUDES = $(PROJECT_DIR)/inc $(LINUX_STUB_BASE)/inc $(PROJECT_DIR)
EXTRA_HOST_LDLIBS = -lcheck
DEFS = -D__UTESTS__ -DDRV_VERSION=\"test\"
-#Do not compile linux_drv_utests, mailbox_utests and processing_utests
-HOST_PROGRAMS = hal_utests
+EXTRA_HOST_CFLAGS = -fno-strict-aliasing
-hal_utests_SOURCES = hal_utests.c
-hal_utests_MODULES = $(PROJECT_DIR) $(LINUX_STUB_BASE)
+HOST_PROGRAMS = linux_drv_utests
+
+linux_drv_utests_SOURCES = linux_drv_utests.c
+linux_drv_utests_MODULES = $(PROJECT_DIR) $(LINUX_STUB_BASE) \
+ $(PROJECT_DIR)/common/ipmbox
include $(BASE)/common/make/top.mk
diff --git a/cleopatre/devkit/tests/plcdrv/utests/inc/hal_utests.h b/cleopatre/devkit/tests/plcdrv/utests/inc/hal_utests.h
deleted file mode 100644
index 4677169dc2..0000000000
--- a/cleopatre/devkit/tests/plcdrv/utests/inc/hal_utests.h
+++ /dev/null
@@ -1,40 +0,0 @@
-#ifndef hal_utests_h
-#define hal_utests_h
-/* Cleopatre project {{{
- *
- * Copyright (C) 2008 Spidcom
- *
- * <<<Licence>>>
- *
- * }}} */
-/**
- * \file hal_utests.h
- * \brief interfaces for unitary tests of hal layer
- * \ingroup Cleopatre - PlcDrv
- *
- * this file content interfaces and exported macros, variables... For the
- * unitary tests of hal layer
- */
-
-#include <stdlib.h>
-#include <stdint.h>
-#include <string.h>
-#include "common.h"
-#include "registers.h"
-
-/****************************************************/
-/***** HARDWARE STUB *****/
-/****************************************************/
-static uint32_t MBX_ring[(A2L_RING_SIZE+L2A_RING_SIZE)/4] __attribute__ ((aligned (A2L_RING_SIZE))); //4 for sizeof(int)
-static uint32_t MBX_registers[NB_MBX_REGISTERS] __attribute__ ((aligned (A2L_RING_SIZE)));
-
-/****************************************************/
-/***** LINUX STUB *****/
-/****************************************************/
-#define printk(...)
-
-/****************************************************/
-/***** SPECIFICS VARIABLES *****/
-/****************************************************/
-
-#endif /* hal_utests_h */
diff --git a/cleopatre/devkit/tests/plcdrv/utests/inc/mailbox_utests.h b/cleopatre/devkit/tests/plcdrv/utests/inc/mailbox_utests.h
deleted file mode 100644
index 4d161d65fb..0000000000
--- a/cleopatre/devkit/tests/plcdrv/utests/inc/mailbox_utests.h
+++ /dev/null
@@ -1,269 +0,0 @@
-#ifndef mailbox_utests_h
-#define mailbox_utests_h
-/* Cleopatre project {{{
- *
- * Copyright (C) 2008 Spidcom
- *
- * <<<Licence>>>
- *
- * }}} */
-/**
- * \file mailbox_utests.h
- * \brief interfaces for unitary tests of mailbox layer
- * \ingroup Cleopatre - PlcDrv
- *
- * this file content interfaces and exported macros, variables... For the
- * unitary tests of mailbox layer
- */
-
-#include <stdlib.h>
-#include <stdint.h>
-#include <string.h>
-#include "common.h"
-
-/****************************************************/
-/***** SPECIFICS DEFINES *****/
-/****************************************************/
-#define SEND_DONE_ADDRESS 0x12345678
-#define INTERFACE_ADDRESS 0x87654321
-#define DATADATA_ADDRESS 0x73895622
-#define DATAMME_ADDRESS 0x57826189
-
-/****************************************************/
-/***** SPECIFICS VARIABLES *****/
-/****************************************************/
-
-/****************************************************/
-/***** LOWER STUB *****/
-/****************************************************/
-struct halctx {
- uint32_t num_tst;
-};
-struct halctx glbctx;
-static inline void A2La_it_disable(struct halctx *ctx){}
-static inline void L2At_it_disable(struct halctx *ctx){}
-static inline void A2La_it_enable(struct halctx *ctx){}
-static inline void L2At_it_enable(struct halctx *ctx){}
-static inline void set_L2Aa_interrupt(struct halctx *ctx){}
-static inline void clr_L2At_interrupt(struct halctx *ctx){}
-static inline void clr_A2La_interrupt(struct halctx *ctx){}
-static inline struct halctx * halmbx_init(struct init_info *info)
-{
- if((!info) || ((uint32_t)info == (uint32_t)0x55555555))
- return NULL;
- else
- {
- glbctx.num_tst=0;
- return &glbctx;
- }
-}
-static inline int halmbx_uninit(struct halctx *ctx){return 0;}
-static inline int halmbx_L2Amail_not_empty_queue(struct halctx *ctx)
-{
- if(ctx->num_tst == 0)
- { //return empty
- return 0;
- }
- else if(ctx->num_tst == 5)
- { //return empty to break RX loop for SEND_DONE
- return 0;
- }
- else if(ctx->num_tst == 8)
- { //return empty to break RX loop for INTERFACE
- return 0;
- }
- else if(ctx->num_tst == 11)
- { //return empty to break RX loop for DATA
- return 0;
- }
- else if(ctx->num_tst == 14)
- { //return empty to break RX loop for MME
- return 0;
- }
- else
- {
- //return not_empty
- return 1;
- }
-}
-static inline int halmbx_A2Lmail_status_queue(struct halctx *ctx)
-{
- //The first time you use this function it will return NEARLY_FULL
- //The second time you use this function it will return FULL
- //The other times you use this function it will return NOT_FULL
- nbtests_A2L_status_queue++;
- switch(nbtests_A2L_status_queue)
- {
- case 1:
- return NEARLY_FULL;
- case 2:
- return FULL;
- default:
- return NOT_FULL;
- }
-}
-static inline int halmbx_L2Amail_status_queue(struct halctx *ctx)
-{
- //The first time you use this function it will return NEARLY_FULL
- //The second time you use this function it will return FULL
- //The other times you use this function it will return NOT_FULL
- nbtests_L2A_status_queue++;
- switch(nbtests_L2A_status_queue)
- {
- case 1:
- return NEARLY_FULL;
- case 2:
- return FULL;
- default:
- return NOT_FULL;
- }
-}
-static inline int halmbx_copy_to_ring(struct halctx *ctx, uint32_t *message, int size)
-{
- if((uint32_t)message == (uint32_t)0x55555555)
- return -1;
- else
- return 0;
-}
-static inline int halmbx_copy_from_ring(struct halctx *ctx, uint32_t *message, int size)
-{
- if(ctx->num_tst == 1)
- { //return error
- return -1;
- }
- else if((ctx->num_tst == 3)||(ctx->num_tst == 4))
- {
- //SEND DONE test
- //return a send_done message
- *message = 0x00000102;
- *(message+1) = SEND_DONE_ADDRESS;
- //return OK
- return 0;
- }
- else if((ctx->num_tst == 6)||(ctx->num_tst == 7))
- {
- //INTERFACE test
- //return a interface message
- *message = 0x00070203;
- *(message+1) = INTERFACE_ADDRESS;
- //return OK
- return 0;
- }
- else if((ctx->num_tst == 9)||(ctx->num_tst == 10))
- {
- //MME test
- //return a mme message
- *message = 0x00009100;
- *(message+1) = DATAMME_ADDRESS;
- //return OK
- return 0;
- }
- else if((ctx->num_tst == 12)||(ctx->num_tst == 13))
- {
- //DATA test
- //return a data message
- *message = 0x00008100;
- *(message+1) = DATADATA_ADDRESS;
- //return OK
- return 0;
- }
- else
- {
- //return OK
- return 0;
- }
-}
-static inline int halmbx_A2Lmail_update(struct halctx *ctx, int size)
-{
- if(size)
- return 0;
- else
- return -1;
-}
-static inline int halmbx_L2Amail_update(struct halctx *ctx, int size)
-{
- if(ctx->num_tst == 2)
- { //return error
- return -1;
- }
- else
- {
- //return OK
- return 0;
- }
-}
-
-/****************************************************/
-/***** UPPER STUB *****/
-/****************************************************/
-static inline int processing_buffer_free(void *pointer)
-{
- if(glbctx.num_tst == 3)
- { //return error
- return -1;
- }
- else if(glbctx.num_tst == 4)
- { //return ok
- //we are in OK SEND_DONE process and we need to break RX loop
- glbctx.num_tst++;
- mbx_rx_ptr_result = (uint32_t)pointer;
- return 0;
- }
- else
- {
- //return OK
- return 0;
- }
-}
-static inline int processing_receive(void *pointer, int length, enum buffer_type type)
-{
- if((glbctx.num_tst == 6) || (glbctx.num_tst == 9) || (glbctx.num_tst == 12))
- { //return error
- return -1;
- }
- else if(glbctx.num_tst == 7)
- { //return ok
- //we are in OK INTERFACE process and we need to break RX loop
- glbctx.num_tst++;
- mbx_rx_ptr_result = (uint32_t)pointer;
- return 0;
- }
- else if(glbctx.num_tst == 10)
- { //return ok
- //we are in OK DATA process and we need to break RX loop
- glbctx.num_tst++;
- mbx_rx_ptr_result = (uint32_t)pointer;
- return 0;
- }
- else if(glbctx.num_tst == 13)
- { //return ok
- //we are in OK MME process and we need to break RX loop
- glbctx.num_tst++;
- mbx_rx_ptr_result = (uint32_t)pointer;
- return 0;
- }
- else
- {
- //return OK
- return 0;
- }
-}
-
-/****************************************************/
-/***** LINUX STUB *****/
-/****************************************************/
-#define printk(...)
-
-/****************************************************/
-/***** STATIC FUNCTION PROTOTYPES *****/
-/****************************************************/
-/**
- * Give the message to hardware
- *
- * \param msg message pointer.
- * \param size size of message.
- * \return error code or status queue.
- */
-int internal_mailbox_send(uint32_t *msg, int size);
-
-#endif /* mailbox_utests_h */
diff --git a/cleopatre/devkit/tests/plcdrv/utests/inc/processing_utests.h b/cleopatre/devkit/tests/plcdrv/utests/inc/processing_utests.h
deleted file mode 100644
index f4f1f73b57..0000000000
--- a/cleopatre/devkit/tests/plcdrv/utests/inc/processing_utests.h
+++ /dev/null
@@ -1,160 +0,0 @@
-#ifndef processing_utests_h
-#define processing_utests_h
-/* Cleopatre project {{{
- *
- * Copyright (C) 2008 Spidcom
- *
- * <<<Licence>>>
- *
- * }}} */
-/**
- * \file processing_utests.h
- * \brief interfaces for unitary tests of processing layer
- * \ingroup Cleopatre - PlcDrv
- *
- * this file content interfaces and exported macros, variables... For the
- * unitary tests of processing layer
- */
-
-#include <stdlib.h>
-#include <stdint.h>
-#include <string.h>
-#include "common.h"
-
-/****************************************************/
-/***** UPPER STUB *****/
-/****************************************************/
-enum free_reason {
- RX_DROP = 0,
- TX_DROP = 1,
- TX_COMPLETE = 2,
-};
-
-enum data_direction {
- DATA_TO_FW,
- DATA_FROM_FW,
- DATA_BIDIR,
-};
-
-static inline int alloc_buffer(enum buffer_type type)
-{
- if((type != INTERFACE) &&
- (type != MME) &&
- (type != DATA))
- return -1;
- else
- return 0;
-}
-static inline int free_buffer(void *packet, enum free_reason reason)
-{
- if((uint32_t)packet == (uint32_t)0x55555555)
- return -1;
- else
- return 0;
-}
-static inline int plcdrv_rx(void *packet, int length)
-{
- if((uint32_t)packet == (uint32_t)0x55555555)
- return -1;
- else
- return 0;
-}
-static inline uint32_t prepare_buffer_to_hw(uint32_t addr, unsigned int len,
- enum data_direction data_dir)
-{
- if(len==100)
- return 0;
- else
- return addr;
-}
-
-static inline uint32_t prepare_buffer_from_hw(uint32_t addr, unsigned int len,
- enum data_direction data_dir)
-{
- if(len==100)
- return 0;
- else
- return addr;
-}
-
-/****************************************************/
-/***** LOWER STUB *****/
-/****************************************************/
-static inline int mailbox_init(struct init_info *info)
-{
- if((unsigned int)info == 0x55555555)
- return -1;
- else
- return 0;
-}
-static inline int mailbox_uninit(void){return 0;}
-static inline int mailbox_buffer_add(void *pointer, enum buffer_type type)
-{
- if((type != INTERFACE) &&
- (type != MME) &&
- (type != DATA))
- return -1;
- else
- return 0;
-}
-static inline int mailbox_send(void *pointer, int length, enum buffer_type type)
-{
- if(type == INTERFACE)
- return 3;
- else if(type == MME)
- return 2;
- else
- return 1;
-}
-
-/****************************************************/
-/***** LINUX STUB *****/
-/****************************************************/
-#define printk(...)
-
-/****************************************************/
-/***** STATIC FUNCTION PROTOTYPES *****/
-/****************************************************/
-/**
- * Find the Ethernet source Address.
- * \param eth_frame Ethernet frame pointer.
- * \param source final source address pointer.
- */
-void get_eth_src_addr(uint8_t* eth_frame, uint8_t source[6]);
-
-/**
- * Find the Ethernet source Address.
- * \param eth_frame Ethernet frame pointer.
- * \param dest final source address pointer.
- */
-void get_eth_dst_addr(uint8_t* eth_frame, uint8_t dest[6]);
-
-/**
- * Find the Ethernet type.
- * \param eth_frame Ethernet frame pointer.
- * \return Ethernet type.
- */
-uint16_t get_eth_type(uint8_t* eth_frame);
-
-/**
- * Find the Ethernet MME version.
- * \param eth_frame Ethernet frame pointer.
- * \return HPAV MME version.
- */
-uint8_t get_eth_mme_version(uint8_t* eth_frame);
-
-/**
- * Find the Ethernet MME type.
- * \param eth_frame Ethernet frame pointer.
- * \return HPAV MME type.
- */
-uint16_t get_eth_mme_type(uint8_t* eth_frame);
-
-/**
- * Find the Ethernet MME type.
- * \param eth_frame Ethernet frame pointer.
- * \return HPAV MME fmi.
- */
-uint16_t get_eth_mme_fmi(uint8_t* eth_frame);
-
-#endif /* processing_utests_h */
diff --git a/cleopatre/devkit/tests/plcdrv/utests/ipmbox/Makefile b/cleopatre/devkit/tests/plcdrv/utests/ipmbox/Makefile
new file mode 100644
index 0000000000..48da7d1b7d
--- /dev/null
+++ b/cleopatre/devkit/tests/plcdrv/utests/ipmbox/Makefile
@@ -0,0 +1,34 @@
+BASE = ../../../../../../cesar
+CLEO_BASE = ../cleopatre
+
+# We test PLCDrv.
+PROJECT_DIR = $(CLEO_BASE)/devkit/plcdrv
+
+LINUX_STUB_BASE = $(CLEO_BASE)/devkit/tests/plcdrv/utests/stub/linux
+
+common_MODULES = $(PROJECT_DIR) $(LINUX_STUB_BASE) \
+ $(PROJECT_DIR)/common/ipmbox
+
+INCLUDES = $(PROJECT_DIR)/inc $(LINUX_STUB_BASE)/inc $(PROJECT_DIR)
+
+EXTRA_HOST_LDLIBS = -lcheck
+
+DEFS = -DDRV_VERSION=\"test\"
+
+HOST_OPTIMIZE = -O0
+
+HOST_PROGRAMS = ipmbox_queue_test ipmbox_test
+
+ipmbox_queue_test_SOURCES = ipmbox_queue_test.c stub_linux.c stub_frame.c
+ipmbox_queue_test_MODULES = $(common_MODULES)
+
+ipmbox_test_SOURCES = ipmbox_test.c stub_linux.c stub_frame.c
+ipmbox_test_MODULES = $(common_MODULES)
+
+.._cleopatre_devkit_plcdrv_MODULE_SOURCES = ipmbox.c
+
+.._cleopatre_devkit_tests_plcdrv_utests_stub_linux_MODULE_SOURCES = \
+ af_netlink.c afe.c char_dev.c delay.c eth.c \
+ mutex.c net_dev.c softirq.c spc300.c uaccess.c wait.c
+
+include $(BASE)/common/make/top.mk
diff --git a/cleopatre/devkit/tests/plcdrv/utests/ipmbox/src/ipmbox_queue_test.c b/cleopatre/devkit/tests/plcdrv/utests/ipmbox/src/ipmbox_queue_test.c
new file mode 100644
index 0000000000..63b763dbec
--- /dev/null
+++ b/cleopatre/devkit/tests/plcdrv/utests/ipmbox/src/ipmbox_queue_test.c
@@ -0,0 +1,356 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2011 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/ipmbox_queue_test.c
+ * \brief IPMbox queue unitary tests
+ * \ingroup devkit_tests
+ */
+
+#include <check.h>
+#include <linux/types.h>
+#include <linux/netdevice.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "frame.h"
+#include "ipmbox.h"
+#include "common/ipmbox/queue.h"
+#include "registers.h"
+
+#include "stub.h"
+
+/**
+ * Size in 32 bits words for each queue.
+ * This table is the same as the one in ipmbox.c but we do not want it
+ * to be public. That is why there is a local copy here.
+ */
+static unsigned int
+ipmbox_test_queue_size[IPMBOX_QUEUE_TYPE_NB][IPMBOX_QUEUE_DIRECTION_NB] =
+{
+ { IPMBOX_PROTOCOL_QUEUE_SIZE_A2L_MBX,
+ IPMBOX_PROTOCOL_QUEUE_SIZE_L2A_MBX },
+ { IPMBOX_PROTOCOL_QUEUE_SIZE_A2L_EMPTY_BUF,
+ IPMBOX_PROTOCOL_QUEUE_SIZE_L2A_EMPTY_BUF },
+ { IPMBOX_PROTOCOL_QUEUE_SIZE_A2L_DATA,
+ IPMBOX_PROTOCOL_QUEUE_SIZE_L2A_DATA },
+};
+
+irqreturn_t it_mbx_handler (int param_1, void * param_2)
+{
+ return 0;
+}
+
+irqreturn_t it_wd_handler (int param_1, void * param_2)
+{
+ return 0;
+}
+
+START_TEST (ipmbox_test_init)
+{
+ uint32_t reg_mask_l2a = IPMBOX_L2A_IT_WKP | IPMBOX_L2A_IT_ACK;
+ ipmbox_ctx_t ipmbox;
+ unsigned int total_shared_mem_size = 0;
+ unsigned int shared_mem_ptr_zone_size;
+ struct net_device netdev;
+ uint i, j, k;
+
+ memset (&reg, 0x42, sizeof (reg));
+
+ /* Call init. */
+ ipmbox_init (&ipmbox, &netdev, it_mbx_handler, it_wd_handler);
+
+ /* Check registers mapping. */
+ fail_if (netdev.base_addr != (uint32_t) &reg);
+ i = 0;
+ fail_if (ipmbox.regs != &reg);
+ fail_if (ipmbox.queue[IPMBOX_QUEUE_DATA][IPMBOX_A2L].ptr->tail
+ != ipmbox.regs->a2l_tail);
+ fail_if (ipmbox.queue[IPMBOX_QUEUE_DATA][IPMBOX_A2L].ptr->head
+ != ipmbox.regs->a2l_head);
+ fail_if (ipmbox.queue[IPMBOX_QUEUE_DATA][IPMBOX_L2A].ptr->tail
+ != ipmbox.regs->l2a_tail);
+ fail_if (ipmbox.queue[IPMBOX_QUEUE_DATA][IPMBOX_L2A].ptr->head
+ != ipmbox.regs->l2a_head);
+ /* Check registers initialisation. */
+ fail_if (ipmbox.regs->l2a_it_mask != reg_mask_l2a);
+ fail_if (ipmbox.regs->l2a_it != (IPMBOX_L2A_IT | IPMBOX_L2A_IT_WD));
+
+ /* Check queues sizes. */
+ for (j = 0; j < IPMBOX_QUEUE_TYPE_NB; j++)
+ {
+ for (k = 0; k < IPMBOX_QUEUE_DIRECTION_NB; k++)
+ {
+ fail_if (ipmbox.queue[j][k].size != ipmbox_test_queue_size[j][k]);
+ total_shared_mem_size += ipmbox_test_queue_size[j][k];
+ }
+ }
+ total_shared_mem_size *= sizeof (uint32_t);
+ total_shared_mem_size += sizeof (ipmbox_queue_ptr_t)
+ * (IPMBOX_QUEUE_TYPE_NB - 1) * IPMBOX_QUEUE_DIRECTION_NB;
+ fail_if (ipmbox.shared_mem_size != total_shared_mem_size);
+
+ /* Check shared memory mapping and initialisation. */
+ fail_if (ipmbox.shared_mem_virt_base_ptr != shared_mem);
+ i = 0;
+ shared_mem_ptr_zone_size = sizeof (ipmbox_queue_ptr_t) / sizeof (uint32_t)
+ * (IPMBOX_QUEUE_TYPE_NB - 1) * IPMBOX_QUEUE_DIRECTION_NB;
+ for (j = 0; j < IPMBOX_QUEUE_DATA; j++)
+ {
+ for (k = 0; k < IPMBOX_QUEUE_DIRECTION_NB; k++)
+ {
+ fail_if (ipmbox.queue[j][k].ptr
+ != (ipmbox_queue_ptr_t *) &shared_mem[i]);
+ i += sizeof (ipmbox_queue_ptr_t) / sizeof (uint32_t);
+ fail_if (test_phys_to_virt (ipmbox.queue[j][k].ptr->head)
+ != shared_mem + shared_mem_ptr_zone_size);
+ shared_mem_ptr_zone_size += ipmbox_test_queue_size[j][k];
+ fail_if (test_phys_to_virt (ipmbox.queue[j][k].ptr->tail)
+ != shared_mem + shared_mem_ptr_zone_size - 1);
+ }
+ }
+
+ /* Check base pointers initialisation. */
+ i = sizeof (ipmbox_queue_ptr_t) * (IPMBOX_QUEUE_TYPE_NB - 1)
+ * IPMBOX_QUEUE_DIRECTION_NB / sizeof (uint32_t);
+ for (j = 0; j < IPMBOX_QUEUE_TYPE_NB; j++)
+ {
+ for (k = 0; k < IPMBOX_QUEUE_DIRECTION_NB; k++)
+ {
+ fail_if (ipmbox.queue[j][k].base_ptr != shared_mem + i);
+ i += ipmbox_test_queue_size[j][k];
+ fail_if (ipmbox.queue[j][k].end_ptr != shared_mem + i);
+ }
+ }
+
+ /* TODO: irq check. Make a scenario? */
+}
+END_TEST
+
+START_TEST (ipmbox_test_space)
+{
+ ipmbox_ctx_t ipmbox;
+ struct net_device netdev;
+ int i, j;
+
+ /* Call init. */
+ ipmbox_init (&ipmbox, &netdev, it_mbx_handler, it_wd_handler);
+
+ for (i = 0; i < IPMBOX_QUEUE_TYPE_NB; i++)
+ {
+ for (j = 0; j < IPMBOX_QUEUE_DIRECTION_NB; j++)
+ {
+ /* Init emulates that all queues are full. */
+ fail_if (ipmbox_queue_get_free_space (&ipmbox.queue[i][j]) != 0);
+ fail_if (ipmbox_queue_get_used_space (&ipmbox.queue[i][j])
+ != ipmbox_test_queue_size[i][j] - 1);
+
+ /* Test empty queues. */
+ ipmbox.queue[i][j].ptr->tail = ipmbox.queue[i][j].ptr->head;
+ fail_if (ipmbox_queue_get_free_space (&ipmbox.queue[i][j])
+ != ipmbox_test_queue_size[i][j] - 1);
+ fail_if (ipmbox_queue_get_used_space (&ipmbox.queue[i][j]) != 0);
+ ipmbox.queue[i][j].ptr->head = ipmbox.queue[i][j].ptr->tail
+ = test_virt_to_phys (ipmbox.queue[i][j].base_ptr
+ + ipmbox.queue[i][j].size - 1);
+ fail_if (ipmbox_queue_get_free_space (&ipmbox.queue[i][j])
+ != ipmbox_test_queue_size[i][j] - 1);
+ fail_if (ipmbox_queue_get_used_space (&ipmbox.queue[i][j]) != 0);
+
+ /* Test random queues. */
+ ipmbox.queue[i][j].ptr->head
+ = test_virt_to_phys (ipmbox.queue[i][j].base_ptr + 42);
+ fail_if (ipmbox_queue_get_free_space (&ipmbox.queue[i][j])
+ != 42);
+ fail_if (ipmbox_queue_get_used_space (&ipmbox.queue[i][j])
+ != ipmbox_test_queue_size[i][j] - 1 - 42);
+ ipmbox.queue[i][j].ptr->tail
+ = test_virt_to_phys (ipmbox.queue[i][j].base_ptr + 45);
+ fail_if (ipmbox_queue_get_free_space (&ipmbox.queue[i][j])
+ != ipmbox_test_queue_size[i][j] - (45 - 42) - 1);
+ fail_if (ipmbox_queue_get_used_space (&ipmbox.queue[i][j])
+ != 45 - 42);
+ ipmbox.queue[i][j].ptr->tail
+ = test_virt_to_phys (ipmbox.queue[i][j].base_ptr + 25);
+ fail_if (ipmbox_queue_get_free_space (&ipmbox.queue[i][j])
+ != 42 - 25 - 1);
+ fail_if (ipmbox_queue_get_used_space (&ipmbox.queue[i][j])
+ != ipmbox_test_queue_size[i][j] - (42 - 25));
+ }
+ }
+}
+END_TEST
+
+START_TEST (ipmbox_test_copy_to)
+{
+ ipmbox_ctx_t ipmbox;
+ struct net_device netdev;
+ int i, j;
+ const int buffer_size = 510;
+ uint32_t data_buffer[buffer_size];
+ uint32_t *head, *tail;
+
+ /* Call init. */
+ ipmbox_init (&ipmbox, &netdev, it_mbx_handler, it_wd_handler);
+
+ for (i = 0; i < buffer_size; i++)
+ data_buffer[i] = i;
+
+ for (i = 0; i < IPMBOX_QUEUE_TYPE_NB; i++)
+ {
+ for (j = 0; j < IPMBOX_QUEUE_DIRECTION_NB; j++)
+ {
+ /* Fake queues are empty. */
+ ipmbox.queue[i][j].ptr->tail = ipmbox.queue[i][j].ptr->head;
+ /* Keep a copy of pointer. */
+ head = test_phys_to_virt (ipmbox.queue[i][j].ptr->head);
+ tail = test_phys_to_virt (ipmbox.queue[i][j].ptr->tail);
+ /* Copy all data possible (queue size - 1). */
+ ipmbox_queue_copy_to (&ipmbox.queue[i][j], data_buffer,
+ ipmbox_test_queue_size[i][j] - 1);
+ fail_if (ipmbox_queue_get_free_space (&ipmbox.queue[i][j]) != 0);
+ /* Check all data are correctly copied inside queue. */
+ fail_if (memcmp (data_buffer, ipmbox.queue[i][j].base_ptr,
+ ipmbox_test_queue_size[i][j] - 1) != 0);
+ /* Check position of head & tail. */
+ fail_if (ipmbox.queue[i][j].ptr->head
+ != test_virt_to_phys (head));
+ fail_if (ipmbox.queue[i][j].ptr->tail
+ != test_virt_to_phys (
+ tail + ipmbox_test_queue_size[i][j] - 1));
+ /* Fake removal of some data. */
+ ipmbox.queue[i][j].ptr->head
+ = test_virt_to_phys (ipmbox.queue[i][j].base_ptr
+ + ipmbox_test_queue_size[i][j] / 2);
+ /* Keep a copy of pointer. */
+ head = test_phys_to_virt (ipmbox.queue[i][j].ptr->head);
+ tail = test_phys_to_virt (ipmbox.queue[i][j].ptr->tail);
+ /* Copy what we have removed. */
+ ipmbox_queue_copy_to (&ipmbox.queue[i][j], data_buffer,
+ ipmbox_test_queue_size[i][j] / 2);
+ /* Check data. */
+ fail_if (memcmp (data_buffer + 1, ipmbox.queue[i][j].base_ptr,
+ ipmbox_test_queue_size[i][j] / 2 - 1) != 0);
+ fail_if (*(ipmbox.queue[i][j].base_ptr
+ + ipmbox_test_queue_size[i][j] - 1) != data_buffer[0]);
+ /* Check position of head & tail. */
+ fail_if (ipmbox.queue[i][j].ptr->head
+ != test_virt_to_phys (head));
+ fail_if (ipmbox.queue[i][j].ptr->tail
+ != test_virt_to_phys (
+ ipmbox.queue[i][j].base_ptr
+ + ipmbox_test_queue_size[i][j] / 2 - 1));
+ }
+ }
+}
+END_TEST
+
+START_TEST (ipmbox_test_copy_from)
+{
+ ipmbox_ctx_t ipmbox;
+ struct net_device netdev;
+ int i, j;
+ uint k;
+ const int buffer_size = 510;
+ uint32_t data_buffer[buffer_size];
+ uint32_t *head, *tail;
+
+ /* Call init. */
+ ipmbox_init (&ipmbox, &netdev, it_mbx_handler, it_wd_handler);
+
+ for (i = 0; i < IPMBOX_QUEUE_TYPE_NB; i++)
+ {
+ for (j = 0; j < IPMBOX_QUEUE_DIRECTION_NB; j++)
+ {
+ /* Initialize all data of queue. */
+ for (k = 0; k < ipmbox.queue[i][j].size; k++)
+ ipmbox.queue[i][j].base_ptr[k] = k;
+
+ /* Keep a copy of pointer. */
+ head = test_phys_to_virt (ipmbox.queue[i][j].ptr->head);
+ tail = test_phys_to_virt (ipmbox.queue[i][j].ptr->tail);
+ /* Copy all data possible (queue size - 1). */
+ ipmbox_queue_copy_from (&ipmbox.queue[i][j], data_buffer,
+ ipmbox_test_queue_size[i][j] - 1);
+ /* Check data. */
+ fail_if (memcmp (ipmbox.queue[i][j].base_ptr, data_buffer,
+ ipmbox_test_queue_size[i][j] - 1) != 0);
+ /* Check position of head & tail. */
+ fail_if (ipmbox.queue[i][j].ptr->tail
+ != test_virt_to_phys (tail));
+ fail_if (ipmbox.queue[i][j].ptr->head
+ != test_virt_to_phys (
+ head + ipmbox_test_queue_size[i][j] - 1));
+ /* Fake add of some data. */
+ ipmbox.queue[i][j].ptr->tail
+ = test_virt_to_phys (ipmbox.queue[i][j].base_ptr
+ + ipmbox_test_queue_size[i][j] / 2);
+ /* Keep a copy of pointer. */
+ head = test_phys_to_virt (ipmbox.queue[i][j].ptr->head);
+ tail = test_phys_to_virt (ipmbox.queue[i][j].ptr->tail);
+ /* Copy. */
+ ipmbox_queue_copy_from (&ipmbox.queue[i][j], data_buffer,
+ ipmbox_test_queue_size[i][j] / 2);
+ /* Check data. */
+ fail_if (*(ipmbox.queue[i][j].base_ptr
+ + ipmbox_test_queue_size[i][j] - 1) != data_buffer[0]);
+ fail_if (memcmp (data_buffer + 1, ipmbox.queue[i][j].base_ptr,
+ ipmbox_test_queue_size[i][j] / 2 - 1) != 0);
+ /* Check position of head & tail. */
+ fail_if (ipmbox.queue[i][j].ptr->tail
+ != test_virt_to_phys (tail));
+ fail_if (ipmbox.queue[i][j].ptr->head
+ != test_virt_to_phys (ipmbox.queue[i][j].base_ptr
+ + ipmbox_test_queue_size[i][j]
+ / 2 - 1));
+ }
+ }
+}
+END_TEST
+
+extern Suite* ipmbox_suite (void)
+{
+ Suite *s = suite_create ("IPMBox queue");
+
+ TCase *tc_init = tcase_create ("init");
+ tcase_add_test (tc_init, ipmbox_test_init);
+ suite_add_tcase (s, tc_init);
+
+ TCase *tc_space = tcase_create ("free & used space");
+ tcase_add_test (tc_space, ipmbox_test_space);
+ suite_add_tcase (s, tc_space);
+
+ TCase *tc_copy_to = tcase_create ("copy to");
+ tcase_add_test (tc_copy_to, ipmbox_test_copy_to);
+ suite_add_tcase (s, tc_copy_to);
+
+ TCase *tc_copy_from = tcase_create ("copy from");
+ tcase_add_test (tc_copy_from, ipmbox_test_copy_from);
+ suite_add_tcase (s, tc_copy_from);
+
+ return s;
+}
+
+int
+main (int argc, char **argv)
+{
+ int number_failed = 0;
+ Suite *s;
+
+ /* Run IPMbox test. */
+ s = ipmbox_suite ();
+
+ SRunner *sr = srunner_create (s);
+ srunner_set_fork_status (sr, CK_NOFORK);
+ srunner_run_all (sr, CK_NORMAL);
+ number_failed = srunner_ntests_failed (sr);
+ srunner_free (sr);
+
+ return (number_failed == 0) ? 0 : -1;
+}
diff --git a/cleopatre/devkit/tests/plcdrv/utests/ipmbox/src/ipmbox_test.c b/cleopatre/devkit/tests/plcdrv/utests/ipmbox/src/ipmbox_test.c
new file mode 100644
index 0000000000..5de637e5a8
--- /dev/null
+++ b/cleopatre/devkit/tests/plcdrv/utests/ipmbox/src/ipmbox_test.c
@@ -0,0 +1,373 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2011 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/ipmbox_test.c
+ * \brief IPMbox RX/TX unitary tests
+ * \ingroup devkit_tests
+ */
+
+#include <check.h>
+#include <linux/types.h>
+#include <linux/netdevice.h>
+#include <linux/errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "ipmbox.h"
+#include "frame.h"
+#include "plcdrv.h"
+
+#include "common/ipmbox/msg.h"
+#include "common/ipmbox/protocol.h"
+
+#include "stub.h"
+
+#define test_phys_to_virt_u32(x) ((uint32_t *) test_phys_to_virt (x))
+
+irqreturn_t
+it_mbx_handler (int param_1, void * param_2)
+{
+ return 0;
+}
+
+irqreturn_t
+it_wd_handler (int param_1, void * param_2)
+{
+ return 0;
+}
+
+START_TEST (ipmbox_test_hdr_data)
+{
+ uint32_t generated_header = 0;
+ unsigned int length = 42;
+ unsigned int prio_tag = 2;
+
+ generated_header = ipmbox_msg_create_header_data (length, prio_tag);
+ fail_if (ipmbox_msg_get_data_length (generated_header) != length);
+ fail_if (ipmbox_msg_get_data_prio_tag (generated_header) != prio_tag);
+}
+END_TEST
+
+START_TEST (ipmbox_test_hdr_mme_priv)
+{
+ uint32_t generated_header = 0;
+ unsigned int length = 42;
+
+ generated_header = ipmbox_msg_create_header_mme_priv (length);
+ fail_if (ipmbox_msg_get_mbx_type (generated_header)
+ != IPMBOX_MSG_MBX_TYPE_MME_PRIV);
+ fail_if (ipmbox_msg_get_mme_priv_length (generated_header) != length);
+
+ length = 0x7FF;
+
+ generated_header = ipmbox_msg_create_header_mme_priv (length);
+ fail_if (ipmbox_msg_get_mbx_type (generated_header)
+ != IPMBOX_MSG_MBX_TYPE_MME_PRIV);
+ fail_if (ipmbox_msg_get_mme_priv_length (generated_header) != length);
+}
+END_TEST
+
+START_TEST (ipmbox_test_hdr_debug_dump)
+{
+ uint32_t generated_header = 0;
+ unsigned int length = 42;
+
+ generated_header = ipmbox_msg_create_header_debug_dump (length);
+ fail_if (ipmbox_msg_get_mbx_type (generated_header)
+ != IPMBOX_MSG_MBX_TYPE_DEBUG_DUMP);
+ fail_if (ipmbox_msg_get_debug_dump_length (generated_header) != length);
+
+ length = (1 << 16) - 1;
+
+ generated_header = ipmbox_msg_create_header_debug_dump (length);
+ fail_if (ipmbox_msg_get_mbx_type (generated_header)
+ != IPMBOX_MSG_MBX_TYPE_DEBUG_DUMP);
+ fail_if (ipmbox_msg_get_debug_dump_length (generated_header) != length);
+}
+END_TEST
+
+START_TEST (ipmbox_test_send_mbx)
+{
+ ipmbox_ctx_t ctx;
+ struct net_device netdev;
+ ipmbox_queue_t *queue;
+ uint32_t header, buffer_addr;
+ unsigned int data_length;
+ unsigned int i, j;
+
+ queue = &ctx.queue[IPMBOX_QUEUE_MBX][IPMBOX_A2L];
+
+ /* Call init. */
+ ipmbox_init (&ctx, &netdev, it_mbx_handler, it_wd_handler);
+
+ /* Empty all queues. */
+ memset (shared_mem + 8, 0, (SHARED_MEM_SIZE - 8) * sizeof (uint32_t));
+ for (i = 0; i < IPMBOX_QUEUE_TYPE_NB; i++)
+ for (j = 0; j < IPMBOX_QUEUE_DIRECTION_NB; j++)
+ ctx.queue[i][j].ptr->tail = ctx.queue[i][j].ptr->head;
+
+ ctx.regs->a2l_it = 0;
+ for (i = 0; i < 10; i++)
+ {
+ /* Create a message. */
+ data_length = 0x12 + i;
+ header = ipmbox_msg_create_header_mme_priv (data_length);
+ buffer_addr = 0x34 + i;
+
+ /* "Send" the message. */
+ ipmbox_send_mbx (&ctx, buffer_addr, header);
+
+ /* Message should be added. */
+ fail_if (ipmbox_queue_get_used_space (queue) != (i + 1) * 2);
+ /* Check content: header. */
+ fail_if (*(test_phys_to_virt_u32 (queue->ptr->head) + i * 2 + 0)
+ != header);
+ /* Check content: buffer address. */
+ fail_if (*(test_phys_to_virt_u32 (queue->ptr->head) + i * 2 + 1)
+ != buffer_addr);
+ /* It should have been triggered. */
+ fail_if (ctx.regs->a2l_it != IPMBOX_A2L_IT);
+ /* Fake it with some others it. */
+ ctx.regs->a2l_it = (1 << i);
+ }
+}
+END_TEST
+
+START_TEST (ipmbox_test_send_empty_buf)
+{
+ ipmbox_ctx_t ctx;
+ struct net_device netdev;
+ ipmbox_queue_t *queue;
+ static const uint32_t count = 5;
+ uint32_t buffer_addr[count];
+ unsigned int i, j, z;
+
+ queue = &ctx.queue[IPMBOX_QUEUE_EMPTY_BUF][IPMBOX_A2L];
+
+ /* Call init. */
+ ipmbox_init (&ctx, &netdev, it_mbx_handler, it_wd_handler);
+
+ /* Empty all queues. */
+ memset (shared_mem + 8, 0, (SHARED_MEM_SIZE - 8) * sizeof (uint32_t));
+ for (i = 0; i < IPMBOX_QUEUE_TYPE_NB; i++)
+ for (j = 0; j < IPMBOX_QUEUE_DIRECTION_NB; j++)
+ ctx.queue[i][j].ptr->tail = ctx.queue[i][j].ptr->head;
+
+ /* Create some buffer addresses. */
+ for (i = 0; i < count; i++)
+ buffer_addr[i] = 0x34 + i;
+
+ ctx.regs->a2l_it = 0;
+ for (i = 1, j = 1; i < count; i++, j += i)
+ {
+ /* "Send" the message. */
+ ipmbox_send_empty_buf (&ctx, buffer_addr, i);
+ /* Message should be added. */
+ fail_if (ipmbox_queue_get_used_space (queue) != j);
+ /* Check content: buffer address. */
+ for (z = 0; z < i; z++)
+ fail_if (*(test_phys_to_virt_u32 (queue->ptr->head) + j - i + z)
+ != buffer_addr[z]);
+ /* It should have been triggered. */
+ fail_if (ctx.regs->a2l_it != IPMBOX_A2L_IT_ACK);
+ /* Fake it with some others it. */
+ ctx.regs->a2l_it = (1 << i);
+ }
+
+ /* Check the whole content. */
+ for (i = 1, j = 1; i < count; i++, j += i)
+ {
+ for (z = 0; z < i; z++)
+ fail_if (*(test_phys_to_virt_u32 (queue->ptr->head) + j - i + z)
+ != buffer_addr[z]);
+ }
+}
+END_TEST
+
+START_TEST (ipmbox_test_send_data)
+{
+ ipmbox_ctx_t ctx;
+ struct net_device netdev;
+ ipmbox_queue_t *queue;
+ static const uint32_t count = 10;
+ unsigned int i, j;
+ uint32_t header;
+
+ queue = &ctx.queue[IPMBOX_QUEUE_DATA][IPMBOX_A2L];
+
+ /* Call init. */
+ ipmbox_init (&ctx, &netdev, it_mbx_handler, it_wd_handler);
+
+ /* Empty all queues. */
+ memset (shared_mem + 8, 0, (SHARED_MEM_SIZE - 8) * sizeof (uint32_t));
+ for (i = 0; i < IPMBOX_QUEUE_TYPE_NB; i++)
+ for (j = 0; j < IPMBOX_QUEUE_DIRECTION_NB; j++)
+ ctx.queue[i][j].ptr->tail = ctx.queue[i][j].ptr->head;
+
+ ctx.regs->a2l_it = 0;
+ for (i = 0; i < count; i++)
+ {
+ /* "Send" the message. */
+ ipmbox_send_data (&ctx, 0x42 + i, ipmbox_msg_create_header_data (
+ i + 1, i % 3));
+
+ /* Message should be added. */
+ fail_if (ipmbox_queue_get_used_space (queue) != (i + 1) * 2);
+ /* Check content: header. */
+ header = (i + 1);
+ header |= (i % 3) << 11;
+ fail_if (*(test_phys_to_virt_u32 (queue->ptr->head) + i * 2 + 0)
+ != header);
+ /* Check content: buffer address. */
+ fail_if (*(test_phys_to_virt_u32 (queue->ptr->head) + i * 2 + 1)
+ != 0x42 + i);
+ /* It should have been triggered. */
+ fail_if (ctx.regs->a2l_it != IPMBOX_A2L_IT);
+ /* Fake it with some others it. */
+ ctx.regs->a2l_it = (1 << i);
+ }
+}
+END_TEST
+
+START_TEST (ipmbox_test_receive)
+{
+ struct net_device netdev;
+ plcdrv_t netpriv = { .dev = &netdev };
+ struct ipmbox_ctx_t *ipmbox = &netpriv.ipmbox;
+ unsigned int i, j;
+
+ /* Init reference buffers. */
+ for (i = 0; i < IPMBOX_PROTOCOL_QUEUE_SIZE_L2A_MBX; i += 2)
+ {
+ if (i % 4)
+ mbx_ref_queue[i] = ipmbox_msg_create_header_mme_priv (i + 1);
+ else
+ mbx_ref_queue[i] = ipmbox_msg_create_header_debug_dump (i + 1);
+ mbx_ref_queue[i + 1] = i;
+ }
+
+ for (i = 0; i < IPMBOX_PROTOCOL_QUEUE_SIZE_L2A_EMPTY_BUF; i++)
+ empty_buf_ref_queue[i] = i;
+
+ for (i = 0; i < IPMBOX_PROTOCOL_QUEUE_SIZE_L2A_DATA; i += 2)
+ {
+ data_ref_queue[i] = ipmbox_msg_create_header_data (
+ i + 1, i % 3);
+ data_ref_queue[i + 1] = i;
+ }
+
+ /* Call init. */
+ ipmbox_init (ipmbox, &netdev, it_mbx_handler, it_wd_handler);
+
+ /* Empty all queues. */
+ memset (shared_mem + 8, 0, (SHARED_MEM_SIZE - 8) * sizeof (uint32_t));
+ for (i = 0; i < IPMBOX_QUEUE_TYPE_NB; i++)
+ for (j = 0; j < IPMBOX_QUEUE_DIRECTION_NB; j++)
+ ipmbox->queue[i][j].ptr->tail = ipmbox->queue[i][j].ptr->head;
+
+ /* Add some messages. */
+ ipmbox_queue_copy_to (&ipmbox->queue[IPMBOX_QUEUE_MBX][IPMBOX_L2A],
+ mbx_ref_queue, 5 * 2);
+ ipmbox_queue_copy_to (&ipmbox->queue[IPMBOX_QUEUE_EMPTY_BUF][IPMBOX_L2A],
+ empty_buf_ref_queue, 5);
+ ipmbox_queue_copy_to (&ipmbox->queue[IPMBOX_QUEUE_DATA][IPMBOX_L2A],
+ data_ref_queue, 30 * 2);
+
+ /* Init masks. */
+ ipmbox->regs->l2a_it_mask = 0x42FF;
+
+ /* Check work done. */
+ fail_if (ipmbox_receive (&netpriv.napi, 64) != 35);
+ fail_if (ipmbox->regs->l2a_it_mask != (0x42FF & ~IPMBOX_L2A_IT));
+ for (i = 0; i < IPMBOX_QUEUE_TYPE_NB; i++)
+ fail_if (ipmbox_queue_get_used_space (&ipmbox->queue[i][IPMBOX_L2A])
+ != 0);
+
+ /* Add some messages. */
+ ipmbox_queue_copy_to (&ipmbox->queue[IPMBOX_QUEUE_MBX][IPMBOX_L2A],
+ mbx_ref_queue + 5 * 2, 5 * 2);
+ ipmbox_queue_copy_to (&ipmbox->queue[IPMBOX_QUEUE_EMPTY_BUF][IPMBOX_L2A],
+ empty_buf_ref_queue + 5, 5);
+ ipmbox_queue_copy_to (&ipmbox->queue[IPMBOX_QUEUE_DATA][IPMBOX_L2A],
+ data_ref_queue + 30 * 2, 90 * 2);
+
+ /* Init masks. */
+ ipmbox->regs->l2a_it_mask = 0x42FF;
+
+ /* Check work done. */
+ fail_if (ipmbox_receive (&netpriv.napi, 64) != 64);
+ fail_if (ipmbox->regs->l2a_it_mask != 0x42FF);
+ fail_if (ipmbox_queue_get_used_space
+ (&ipmbox->queue[IPMBOX_QUEUE_MBX][IPMBOX_L2A]) != 0);
+ fail_if (ipmbox_queue_get_used_space
+ (&ipmbox->queue[IPMBOX_QUEUE_EMPTY_BUF][IPMBOX_L2A]) != 0);
+ fail_if (ipmbox_queue_get_used_space
+ (&ipmbox->queue[IPMBOX_QUEUE_DATA][IPMBOX_L2A]) != 31 * 2);
+
+ /* Check work done. */
+ fail_if (ipmbox_receive (&netpriv.napi, 64) != 31);
+ fail_if (ipmbox->regs->l2a_it_mask != (0x42FF & ~IPMBOX_L2A_IT));
+ for (i = 0; i < IPMBOX_QUEUE_TYPE_NB; i++)
+ fail_if (ipmbox_queue_get_used_space (&ipmbox->queue[i][IPMBOX_L2A])
+ != 0);
+}
+END_TEST
+
+Suite *
+ipmbox_suite (void)
+{
+ Suite *s = suite_create ("IPMBox RX/TX");
+
+ TCase *tc_hdr_data = tcase_create ("header data");
+ tcase_add_test (tc_hdr_data, ipmbox_test_hdr_data);
+ suite_add_tcase (s, tc_hdr_data);
+
+ TCase *tc_hdr_mme_priv = tcase_create ("header private MME");
+ tcase_add_test (tc_hdr_mme_priv, ipmbox_test_hdr_mme_priv);
+ suite_add_tcase (s, tc_hdr_mme_priv);
+
+ TCase *tc_hdr_debug_dump = tcase_create ("header debug dump");
+ tcase_add_test (tc_hdr_debug_dump, ipmbox_test_hdr_debug_dump);
+ suite_add_tcase (s, tc_hdr_debug_dump);
+
+ TCase *tc_send_mbx = tcase_create ("Send MBX");
+ tcase_add_test (tc_send_mbx, ipmbox_test_send_mbx);
+ suite_add_tcase (s, tc_send_mbx);
+
+ TCase *tc_send_empty_buf = tcase_create ("Send empty buffers");
+ tcase_add_test (tc_send_empty_buf, ipmbox_test_send_empty_buf);
+ suite_add_tcase (s, tc_send_empty_buf);
+
+ TCase *tc_send_data = tcase_create ("Send data");
+ tcase_add_test (tc_send_data, ipmbox_test_send_data);
+ suite_add_tcase (s, tc_send_data);
+
+ TCase *tc_send_receive = tcase_create ("Receive");
+ tcase_add_test (tc_send_receive, ipmbox_test_receive);
+ suite_add_tcase (s, tc_send_receive);
+
+ return s;
+}
+
+int
+main (int argc, char **argv)
+{
+ int number_failed = 0;
+ Suite *s;
+
+ /* Run IPMbox test. */
+ s = ipmbox_suite ();
+
+ SRunner *sr = srunner_create (s);
+ srunner_set_fork_status (sr, CK_NOFORK);
+ srunner_run_all (sr, CK_NORMAL);
+ number_failed = srunner_ntests_failed (sr);
+ srunner_free (sr);
+
+ return (number_failed == 0) ? 0 : -1;
+}
diff --git a/cleopatre/devkit/tests/plcdrv/utests/ipmbox/src/stub_frame.c b/cleopatre/devkit/tests/plcdrv/utests/ipmbox/src/stub_frame.c
new file mode 100644
index 0000000000..5dbd500011
--- /dev/null
+++ b/cleopatre/devkit/tests/plcdrv/utests/ipmbox/src/stub_frame.c
@@ -0,0 +1,91 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2012 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/stub_frame.c
+ * \brief stub frame layer
+ */
+
+#include <check.h>
+
+#include "frame.h"
+#include "plcdrv.h"
+#include "stub.h"
+
+/* Queues' reference buffers. */
+uint32_t mbx_ref_queue[IPMBOX_PROTOCOL_QUEUE_SIZE_L2A_MBX];
+uint32_t empty_buf_ref_queue[IPMBOX_PROTOCOL_QUEUE_SIZE_L2A_EMPTY_BUF];
+uint32_t data_ref_queue[IPMBOX_PROTOCOL_QUEUE_SIZE_L2A_DATA];
+
+void
+frame_buffer_free (plcdrv_t *priv, uint32_t buffer)
+{
+ static unsigned int empty_buf_word_counter = 0;
+
+ fail_if (buffer != empty_buf_ref_queue[empty_buf_word_counter++]);
+}
+
+bool
+frame_buffer_alloc (plcdrv_t *priv)
+{
+ return true;
+}
+
+void
+frame_rx_data (plcdrv_t *priv, uint32_t data_addr,
+ uint32_t data_length)
+{
+ /* Clear IT register for stub. */
+ priv->ipmbox.regs->l2a_it &= ~IPMBOX_L2A_IT;
+
+ static unsigned int data_word_counter = 0;
+
+ fail_if (data_length != (data_ref_queue[data_word_counter++]
+ & ((1 << 11) - 1)));
+ fail_if (data_addr != data_ref_queue[data_word_counter++]);
+}
+
+static unsigned int mbx_word_counter = 0;
+
+void
+frame_rx_mme_priv (plcdrv_t *priv, uint32_t data_addr,
+ uint32_t data_length)
+{
+ /* Clear IT register for stub. */
+ priv->ipmbox.regs->l2a_it &= ~IPMBOX_L2A_IT;
+
+ fail_if (data_length != mbx_ref_queue[mbx_word_counter++] >> 8);
+ fail_if (data_addr != mbx_ref_queue[mbx_word_counter++]);
+}
+
+void
+frame_rx_debug_dump (plcdrv_t *priv, uint32_t data_addr,
+ uint32_t data_length)
+{
+ /* Clear IT register for stub. */
+ priv->ipmbox.regs->l2a_it &= ~IPMBOX_L2A_IT;
+
+ fail_if (data_length != mbx_ref_queue[mbx_word_counter++] >> 8);
+ fail_if (data_addr != mbx_ref_queue[mbx_word_counter++]);
+}
+
+int
+frame_tx_data (struct sk_buff *skb, struct net_device *dev)
+{
+ return 0;
+}
+
+void
+frame_tx_mbx_mme_priv (plcdrv_t *priv, struct sk_buff *skb)
+{
+}
+
+void
+frame_tx_mbx_debug_dump (plcdrv_t *priv, uint32_t *buffer,
+ unsigned int length)
+{
+}
diff --git a/cleopatre/devkit/tests/plcdrv/utests/ipmbox/src/stub_linux.c b/cleopatre/devkit/tests/plcdrv/utests/ipmbox/src/stub_linux.c
new file mode 100644
index 0000000000..7778bf57b1
--- /dev/null
+++ b/cleopatre/devkit/tests/plcdrv/utests/ipmbox/src/stub_linux.c
@@ -0,0 +1,61 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2011 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file src/stub_linux.c
+ */
+
+#include <linux/types.h>
+#include <linux/io.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+
+#include "stub.h"
+
+/* Fake hardware registers. */
+ipmbox_registers_t reg;
+
+/* Fake shared memory between LEON and ARM. */
+uint32_t shared_mem[SHARED_MEM_SIZE];
+
+void *
+__arm_ioremap (unsigned long phys_addr, size_t size, unsigned int mtype)
+{
+ return &reg;
+}
+
+void
+__iounmap (volatile void *addr)
+{
+}
+
+void *
+dma_alloc_coherent (struct device *dev, size_t size, dma_addr_t *handle,
+ gfp_t gfp)
+{
+ *handle = test_virt_to_phys (shared_mem);
+ return (void *) shared_mem;
+}
+
+void
+dma_free_coherent (struct device *dev, size_t size, void *cpu_addr,
+ dma_addr_t handle)
+{
+}
+
+int
+request_irq (unsigned int irq, irq_handler_t handler,
+ unsigned long irqflags, const char *devname, void *dev_id)
+{
+ return 0;
+}
+
+void
+free_irq (unsigned int irq, void *dev_id)
+{
+}
diff --git a/cleopatre/devkit/tests/plcdrv/utests/ipmbox/stub.h b/cleopatre/devkit/tests/plcdrv/utests/ipmbox/stub.h
new file mode 100644
index 0000000000..104796821e
--- /dev/null
+++ b/cleopatre/devkit/tests/plcdrv/utests/ipmbox/stub.h
@@ -0,0 +1,44 @@
+#ifndef stub_h
+#define stub_h
+/* Cesar project {{{
+ *
+ * Copyright (C) 2011 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file stub.h
+ */
+
+#include "common/ipmbox/registers.h"
+#include "common/ipmbox/protocol.h"
+
+/* Shared memory size (in 32 bits words). */
+#define SHARED_MEM_SIZE (IPMBOX_PROTOCOL_QUEUE_SIZE_A2L_MBX \
+ + IPMBOX_PROTOCOL_QUEUE_SIZE_A2L_DATA \
+ + IPMBOX_PROTOCOL_QUEUE_SIZE_L2A_EMPTY_BUF \
+ + IPMBOX_PROTOCOL_QUEUE_SIZE_L2A_MBX \
+ + IPMBOX_PROTOCOL_QUEUE_SIZE_L2A_DATA \
+ + IPMBOX_PROTOCOL_QUEUE_SIZE_A2L_EMPTY_BUF \
+ + 8)
+
+
+extern ipmbox_registers_t reg;
+extern uint32_t shared_mem[SHARED_MEM_SIZE];
+extern uint32_t mbx_ref_queue[IPMBOX_PROTOCOL_QUEUE_SIZE_L2A_MBX];
+extern uint32_t empty_buf_ref_queue[IPMBOX_PROTOCOL_QUEUE_SIZE_L2A_EMPTY_BUF];
+extern uint32_t data_ref_queue[IPMBOX_PROTOCOL_QUEUE_SIZE_L2A_DATA];
+
+static inline unsigned long test_virt_to_phys (void *x)
+{
+ return (unsigned long) x + 0x10000000;
+}
+
+static inline void *test_phys_to_virt (unsigned long x)
+{
+ return (void *) (x - 0x10000000);
+}
+
+
+#endif /* stub_h */
diff --git a/cleopatre/devkit/tests/plcdrv/utests/src/hal_utests.c b/cleopatre/devkit/tests/plcdrv/utests/src/hal_utests.c
deleted file mode 100644
index 57cd7db0b1..0000000000
--- a/cleopatre/devkit/tests/plcdrv/utests/src/hal_utests.c
+++ /dev/null
@@ -1,380 +0,0 @@
-/* Cleopatre project {{{
- *
- * Copyright (C) 2008 Spidcom
- *
- * <<<Licence>>>
- *
- * }}} */
-/**
- * \file hal_utests.c
- * \brief Unitary tests for HAL layer
- * \ingroup Cleopatre - PlcDrv
- *
- * This file content all the unitary tests for the hal layer,
- * this layer will provide all mechanisms to manage hardware.
- */
-
-#include <check.h>
-#include <stdio.h>
-#include <string.h>
-#include "hal.h"
-#include "common.h"
-
-#include "inc/hal_utests.h"
-
-/** local defines */
-#define L2A_RING_BASE_ADDR ((uint32_t)&MBX_ring[A2L_RING_SIZE/4])
-#define A2L_RING_BASE_ADDR ((uint32_t)&MBX_ring[0])
-
-/** local variables */
-struct halctx *tstctx;
-
-struct init_info info = {
- .ring_base_addr = (uint32_t)&MBX_ring[0],
- .phys_ring_base_addr = (uint32_t)&MBX_ring[0],
- .mbx_reg_base_addr = (uint32_t)&MBX_registers[0]
-};
-
-/** init test procedure */
-START_TEST (test_halmbx_init)
-{
- //Check arguments
- fail_if(halmbx_init(NULL) != NULL, "halmbx_init arguments error");
-
- tstctx = halmbx_init(&info);
-
- //Check mailbox pointer initialization
- fail_if(tstctx->A2L_ptr != &MBX_ring[0], "A2L ring pointer not initialize");
- fail_if(tstctx->L2A_ptr != &MBX_ring[A2L_RING_SIZE/4], "L2A ring pointer not initialize");
- fail_if(tstctx->A2L_head != &MBX_registers[5], "A2L_tail pointer not initialize");
- fail_if(tstctx->A2L_tail != &MBX_registers[4], "A2L_tail pointer not initialize");
- fail_if(tstctx->L2A_head != &MBX_registers[7], "L2A_head pointer not initialize");
- fail_if(tstctx->L2A_tail != &MBX_registers[6], "L2A_tail pointer not initialize");
- fail_if(tstctx->A2L_it != &MBX_registers[0], "A2L it pointer not initialize");
- fail_if(tstctx->L2A_it != &MBX_registers[2], "L2A it pointer not initialize");
- fail_if(tstctx->L2A_it_mask != &MBX_registers[3], "L2A it mask pointer not initialize");
-
- //Check mailbox head and tail pointers values
- fail_if(*tstctx->A2L_tail != (uint32_t)&MBX_ring[0], "A2L tail not initialize");
- fail_if(*tstctx->L2A_head != (uint32_t)&MBX_ring[A2L_RING_SIZE/4], "L2A head not initialize");
-}
-END_TEST
-
-START_TEST (test_set_A2Lt_interrupt)
-{
- *tstctx->A2L_it = 0;
- set_A2Lt_interrupt(tstctx);
- fail_if(*tstctx->A2L_it != 0x01, "A2L trigger not set");
- *tstctx->A2L_it = 3;
- set_A2Lt_interrupt(tstctx);
- fail_if(*tstctx->A2L_it != 0x03, "A2L trigger not set");
-}
-END_TEST
-
-START_TEST (test_set_L2Aa_interrupt)
-{
- *tstctx->A2L_it = 0;
- set_L2Aa_interrupt(tstctx);
- fail_if(*tstctx->A2L_it != 0x02, "L2A acknowledge not set");
- *tstctx->A2L_it = 3;
- set_L2Aa_interrupt(tstctx);
- fail_if(*tstctx->A2L_it != 0x03, "L2A acknowledge not set");
-}
-END_TEST
-
-START_TEST (test_clr_L2At_interrupt)
-{
- *tstctx->L2A_it = 1;
- clr_L2At_interrupt(tstctx);
- fail_if(*tstctx->L2A_it != 0x01, "L2A trigger not clr");
- *tstctx->L2A_it = 2;
- clr_L2At_interrupt(tstctx);
- fail_if(*tstctx->L2A_it != 0x01, "L2A trigger not clr");
-}
-END_TEST
-
-START_TEST (test_clr_A2La_interrupt)
-{
- *tstctx->L2A_it = 2;
- clr_A2La_interrupt(tstctx);
- fail_if(*tstctx->L2A_it != 0x02, "A2L acknowledge not clr");
- *tstctx->L2A_it = 1;
- clr_A2La_interrupt(tstctx);
- fail_if(*tstctx->L2A_it != 0x02, "A2L acknowledge not clr");
-}
-END_TEST
-
-START_TEST (test_A2La_it_enable)
-{
- *tstctx->L2A_it_mask = 2;
- A2La_it_enable(tstctx);
- fail_if(*tstctx->L2A_it_mask != 0x00, "A2L acknowledge not enable");
- *tstctx->L2A_it_mask = 1;
- A2La_it_enable(tstctx);
- fail_if(*tstctx->L2A_it_mask != 0x01, "A2L acknowledge not enable");
-}
-END_TEST
-
-START_TEST (test_L2At_it_enable)
-{
- *tstctx->L2A_it_mask = 1;
- L2At_it_enable(tstctx);
- fail_if(*tstctx->L2A_it_mask != 0x00, "L2A trigger not enable");
- *tstctx->L2A_it_mask = 2;
- L2At_it_enable(tstctx);
- fail_if(*tstctx->L2A_it_mask != 0x02, "L2A trigger not enable");
-}
-END_TEST
-
-START_TEST (test_A2La_it_disable)
-{
- *tstctx->L2A_it_mask = 0;
- A2La_it_disable(tstctx);
- fail_if(*tstctx->L2A_it_mask != 0x02, "A2L acknowledge not disable");
- *tstctx->L2A_it_mask = 3;
- A2La_it_disable(tstctx);
- fail_if(*tstctx->L2A_it_mask != 0x03, "A2L acknowledge not disable");
-}
-END_TEST
-
-START_TEST (test_L2At_it_disable)
-{
- *tstctx->L2A_it_mask = 0;
- L2At_it_disable(tstctx);
- fail_if(*tstctx->L2A_it_mask != 0x01, "L2A trigger not disable");
- *tstctx->L2A_it_mask = 3;
- L2At_it_disable(tstctx);
- fail_if(*tstctx->L2A_it_mask != 0x03, "L2A trigger not disable");
-}
-END_TEST
-
-START_TEST (test_halmbx_L2Amail_not_empty_queue)
-{
- //The ring size for the test is 0x100
- *tstctx->L2A_tail = 0x5;
- *tstctx->L2A_head = 0x5;
- fail_if(halmbx_L2Amail_not_empty_queue(tstctx) != 0, "Error checking L2A not empty queue");
- *tstctx->L2A_tail = 0xA;
- *tstctx->L2A_head = 0x7;
- fail_if(halmbx_L2Amail_not_empty_queue(tstctx) == 0, "Error checking L2A not empty queue");
- *tstctx->L2A_tail = 0x0;
- *tstctx->L2A_head = 0xFE;
- fail_if(halmbx_L2Amail_not_empty_queue(tstctx) == 0, "Error checking L2A not empty queue");
-}
-END_TEST
-
-START_TEST (test_halmbx_A2Lmail_status_queue)
-{
- //The ring size for the test is 0x100
- *tstctx->A2L_tail = A2L_RING_BASE_ADDR + 0x05;
- *tstctx->A2L_head = A2L_RING_BASE_ADDR + 0x05;
- fail_if(halmbx_A2Lmail_status_queue(tstctx) != NOT_FULL, "Error checking A2L status queue");
- *tstctx->A2L_tail = A2L_RING_BASE_ADDR + 0x54;
- *tstctx->A2L_head = A2L_RING_BASE_ADDR + 0x04;
- fail_if(halmbx_A2Lmail_status_queue(tstctx) != NOT_FULL, "Error checking A2L status queue");
- *tstctx->A2L_tail = A2L_RING_BASE_ADDR + 0x20;
- *tstctx->A2L_head = A2L_RING_BASE_ADDR + 0xF0;
- fail_if(halmbx_A2Lmail_status_queue(tstctx) != NOT_FULL, "Error checking A2L status queue");
- *tstctx->A2L_tail = A2L_RING_BASE_ADDR + 0x18;
- *tstctx->A2L_head = A2L_RING_BASE_ADDR + 0x1C;
- fail_if(halmbx_A2Lmail_status_queue(tstctx) != FULL, "Error checking A2L status queue");
- *tstctx->A2L_tail = A2L_RING_BASE_ADDR + 0xFC;
- *tstctx->A2L_head = A2L_RING_BASE_ADDR + 0x04;
- fail_if(halmbx_A2Lmail_status_queue(tstctx) != FULL, "Error checking A2L status queue");
- *tstctx->A2L_tail = A2L_RING_BASE_ADDR + 0x08;
- *tstctx->A2L_head = A2L_RING_BASE_ADDR + 0x14;
- fail_if(halmbx_A2Lmail_status_queue(tstctx) != NEARLY_FULL, "Error checking A2L status queue");
-}
-END_TEST
-
-START_TEST (test_halmbx_L2Amail_status_queue)
-{
- //The ring size for the test is 0x100
- *tstctx->L2A_tail = L2A_RING_BASE_ADDR + 0x05;
- *tstctx->L2A_head = L2A_RING_BASE_ADDR + 0x05;
- fail_if(halmbx_L2Amail_status_queue(tstctx) != NOT_FULL, "Error checking L2A status queue");
- *tstctx->L2A_tail = L2A_RING_BASE_ADDR + 0x54;
- *tstctx->L2A_head = L2A_RING_BASE_ADDR + 0x04;
- fail_if(halmbx_L2Amail_status_queue(tstctx) != NOT_FULL, "Error checking L2A status queue");
- *tstctx->L2A_tail = L2A_RING_BASE_ADDR + 0x20;
- *tstctx->L2A_head = L2A_RING_BASE_ADDR + 0xF0;
- fail_if(halmbx_L2Amail_status_queue(tstctx) != NOT_FULL, "Error checking L2A status queue");
- *tstctx->L2A_tail = L2A_RING_BASE_ADDR + 0x18;
- *tstctx->L2A_head = L2A_RING_BASE_ADDR + 0x1C;
- fail_if(halmbx_L2Amail_status_queue(tstctx) != FULL, "Error checking L2A status queue");
- *tstctx->L2A_tail = L2A_RING_BASE_ADDR + 0xFC;
- *tstctx->L2A_head = L2A_RING_BASE_ADDR + 0x04;
- fail_if(halmbx_L2Amail_status_queue(tstctx) != FULL, "Error checking L2A status queue");
- *tstctx->L2A_tail = L2A_RING_BASE_ADDR + 0x08;
- *tstctx->L2A_head = L2A_RING_BASE_ADDR + 0x14;
- fail_if(halmbx_L2Amail_status_queue(tstctx) != NEARLY_FULL, "Error checking L2A status queue");
-}
-END_TEST
-
-START_TEST (test_halmbx_copy_to_ring)
-{
- uint32_t msg[] = {0x12345678, 0xFEDCBA98};
- uint32_t *res;
-
- //Check arguments
- fail_if(halmbx_copy_to_ring(NULL,NULL,5) == 0, "Error with no context");
- fail_if(halmbx_copy_to_ring(tstctx,NULL,MAX_MSG_SIZE+5) == 0, "Error with a too big size");
- fail_if(halmbx_copy_to_ring(tstctx,NULL,0) == 0, "Error without size");
- fail_if(halmbx_copy_to_ring(tstctx,NULL,3) == 0, "Error with size not align");
- fail_if(halmbx_copy_to_ring(tstctx,NULL,4) == 0, "Error without pointer");
- fail_if(halmbx_copy_to_ring(tstctx,(uint32_t*)0x67546421,4) == 0, "Error with pointer not align");
-
- //Check function
- *tstctx->A2L_tail = A2L_RING_BASE_ADDR + 0x4;
- *tstctx->A2L_head = A2L_RING_BASE_ADDR + 0x4;
- fail_if(halmbx_copy_to_ring(tstctx,(uint32_t*)msg, sizeof(msg)) != 0, "Error during copy");
- res = (uint32_t*)(*tstctx->A2L_tail);
- fail_if(*res++ != msg[0], "Error with copy");
- fail_if(*res != msg[1], "Error with copy");
-
- *tstctx->A2L_tail = A2L_RING_BASE_ADDR + 0xFC;
- *tstctx->A2L_head = A2L_RING_BASE_ADDR + 0xFC;
- fail_if(halmbx_copy_to_ring(tstctx,(uint32_t*)msg, sizeof(msg)) != 0, "Error before copy");
- res = (uint32_t*)(*tstctx->A2L_tail);
- fail_if(*res != msg[0], "Error with rollover copy"); //offset=FC to FF
- res = (uint32_t*)A2L_RING_BASE_ADDR;
- fail_if(*res != msg[1], "Error with rollover copy"); //offset=0 to 3
-}
-END_TEST
-
-START_TEST (test_halmbx_copy_from_ring)
-{
- uint32_t msg_origin[] = {0x87654321, 0x89ABCDEF};
- uint32_t msg[2];
- uint32_t *res;
-
- //Check arguments
- fail_if(halmbx_copy_to_ring(NULL,NULL,5) == 0, "Error with no context");
- fail_if(halmbx_copy_from_ring(tstctx,NULL,MAX_MSG_SIZE+5) == 0, "Error with a too big size");
- fail_if(halmbx_copy_from_ring(tstctx,NULL,0) == 0, "Error without size");
- fail_if(halmbx_copy_from_ring(tstctx,NULL,3) == 0, "Error with size not align");
- fail_if(halmbx_copy_from_ring(tstctx,NULL,4) == 0, "Error without pointer");
- fail_if(halmbx_copy_from_ring(tstctx,(uint32_t*)0x67546421,4) == 0, "Error with pointer not align");
-
- //Check function
- *tstctx->L2A_tail = L2A_RING_BASE_ADDR + 0x4;
- *tstctx->L2A_head = L2A_RING_BASE_ADDR + 0x4;
- res = (uint32_t*)(*tstctx->L2A_head);
- *res = msg_origin[0];
- *(res+1) = msg_origin[1];
- fail_if(halmbx_copy_from_ring(tstctx,(uint32_t*)msg, sizeof(msg_origin)) != 0, "Error before copy");
- fail_if(msg[0] != msg[0], "Error with copy");
- fail_if(msg[1] != msg[1], "Error with copy");
-
- memset((char*)tstctx->L2A_head, 0, 4);
- *tstctx->L2A_tail = L2A_RING_BASE_ADDR + 0xFC;
- *tstctx->L2A_head = L2A_RING_BASE_ADDR + 0xFC;
- res = (uint32_t*)(*tstctx->L2A_head); //offset=FC to FF
- *res = msg_origin[0];
- res = (uint32_t*)L2A_RING_BASE_ADDR; //offset=0 to 3
- *(res+1) = msg_origin[1];
- fail_if(halmbx_copy_from_ring(tstctx,(uint32_t*)msg, sizeof(msg_origin)) != 0, "Error before copy");
- fail_if(msg[0] != msg[0], "Error with rollover copy");
- fail_if(msg[1] != msg[1], "Error with rollover copy");
-}
-END_TEST
-
-START_TEST (test_halmbx_A2Lmail_update)
-{
- //Check arguments
- fail_if(halmbx_A2Lmail_update(NULL,5) == 0, "Error with no context");
- fail_if(halmbx_A2Lmail_update(tstctx,0) == 0, "Error without size");
-
- //Check function
- *tstctx->A2L_tail = A2L_RING_BASE_ADDR + 0x4;
- *tstctx->A2L_head = A2L_RING_BASE_ADDR + 0x4;
- fail_if(halmbx_A2Lmail_update(tstctx,8) != 0, "Error before update");
- fail_if(*tstctx->A2L_tail != (A2L_RING_BASE_ADDR + 0xC), "Error with update");
- *tstctx->A2L_tail = A2L_RING_BASE_ADDR + 0xFC;
- *tstctx->A2L_head = A2L_RING_BASE_ADDR + 0xFC;
- fail_if(halmbx_A2Lmail_update(tstctx,8) != 0, "Error before update");
- fail_if(*tstctx->A2L_tail != (A2L_RING_BASE_ADDR + 0x4), "Error with rollover update");
-}
-END_TEST
-
-START_TEST (test_halmbx_L2Amail_update)
-{
- //Check arguments
- fail_if(halmbx_A2Lmail_update(NULL,5) == 0, "Error with no context");
- fail_if(halmbx_L2Amail_update(tstctx,0) == 0, "Error without size");
-
- //Check function
- *tstctx->L2A_tail = L2A_RING_BASE_ADDR + 0x4;
- *tstctx->L2A_head = L2A_RING_BASE_ADDR + 0x4;
- fail_if(halmbx_L2Amail_update(tstctx,4) != 0, "Error before update");
- fail_if(*tstctx->L2A_head != (L2A_RING_BASE_ADDR + 0x8), "Error with update");
- *tstctx->L2A_tail = L2A_RING_BASE_ADDR + 0xFC;
- *tstctx->L2A_head = L2A_RING_BASE_ADDR + 0xFC;
- fail_if(halmbx_L2Amail_update(tstctx,0xC) != 0, "Error before update");
- fail_if(*tstctx->L2A_head != (L2A_RING_BASE_ADDR + 0x8), "Error with rollover update");
-}
-END_TEST
-
-extern Suite* processing_suite(void)
-{
- Suite *s = suite_create("HAL");
- TCase *tc_core = tcase_create("Core");
-
- //Test halmbx_init
- tcase_add_test(tc_core, test_halmbx_init);
-
- //Test set_A2Lt_interrupt
- tcase_add_test(tc_core, test_set_A2Lt_interrupt);
- //Test set_L2Aa_interrupt
- tcase_add_test(tc_core, test_set_L2Aa_interrupt);
- //Test clr_L2At_interrupt
- tcase_add_test(tc_core, test_clr_L2At_interrupt);
- //Test clr_A2La_interrupt
- tcase_add_test(tc_core, test_clr_A2La_interrupt);
-
- //Test en_A2La_interrupt
- tcase_add_test(tc_core, test_A2La_it_enable);
- //Test en_L2At_interrupt
- tcase_add_test(tc_core, test_L2At_it_enable);
- //Test dis_A2La_interrupt
- tcase_add_test(tc_core, test_A2La_it_disable);
- //Test dis_L2At_interrupt
- tcase_add_test(tc_core, test_L2At_it_disable);
-
- //Test halmbx_L2Amail_not_empty_queue
- tcase_add_test(tc_core, test_halmbx_L2Amail_not_empty_queue);
- //Test halmbx_A2Lmail_status_queue
- tcase_add_test(tc_core, test_halmbx_A2Lmail_status_queue);
- //Test halmbx_L2Amail_status_queue
- tcase_add_test(tc_core, test_halmbx_L2Amail_status_queue);
-
- //Test halmbx_copy_to_ring
- tcase_add_test(tc_core, test_halmbx_copy_to_ring);
- //Test halmbx_copy_from_ring
- tcase_add_test(tc_core, test_halmbx_copy_from_ring);
- //Test halmbx_A2Lmail_update
- tcase_add_test(tc_core, test_halmbx_A2Lmail_update);
- //Test halmbx_L2Amail_update
- tcase_add_test(tc_core, test_halmbx_L2Amail_update);
-
- suite_add_tcase(s, tc_core);
- return s;
-}
-
-int main(void)
-{
- int number_failed = 0;
- Suite *s;
-
- //Run Processing tests
- s = processing_suite();
-
- SRunner *sr = srunner_create(s);
- srunner_set_fork_status (sr, CK_NOFORK);
- srunner_run_all(sr, CK_NORMAL);
- number_failed = srunner_ntests_failed(sr);
- srunner_free(sr);
-
- return (number_failed == 0) ? 0 : -1;
-}
-
diff --git a/cleopatre/devkit/tests/plcdrv/utests/src/linux_drv_utests.c b/cleopatre/devkit/tests/plcdrv/utests/src/linux_drv_utests.c
index ec341b9d35..9f881603f7 100644
--- a/cleopatre/devkit/tests/plcdrv/utests/src/linux_drv_utests.c
+++ b/cleopatre/devkit/tests/plcdrv/utests/src/linux_drv_utests.c
@@ -18,7 +18,9 @@
#include <check.h>
#include <stdio.h>
#include <string.h>
-#include "linux_drv.h"
+#include <linux/socket.h>
+
+#include "plcdrv.h"
/** local variables */
static struct net_device dev;
@@ -26,7 +28,6 @@ static struct net_device dev;
/** change mtu procedure */
START_TEST (test_plc_drv_change_mtu)
{
- fail_if(plcdrv_change_mtu(NULL, 1234) != -1, "Error with arguments checking");
fail_if(plcdrv_change_mtu(&dev, 63) >= 0, "Error with too small mtu");
fail_if(plcdrv_change_mtu(&dev, 1510) >= 0, "Error with too big mtu");
fail_if(plcdrv_change_mtu(&dev, 1400) < 0, "Error with a correct mtu");
@@ -39,9 +40,6 @@ START_TEST (test_plc_drv_set_mac_address)
struct sockaddr addr;
int i;
- fail_if(plcdrv_set_mac_address(NULL, NULL) != -1, "Error with first arguments checking");
- fail_if(plcdrv_set_mac_address(&dev, NULL) != -1, "Error with second arguments checking");
-
for(i=0 ; i<sizeof(addr.sa_data) ; i++)
{
addr.sa_data[i] = i*11;
diff --git a/cleopatre/devkit/tests/plcdrv/utests/src/mailbox_utests.c b/cleopatre/devkit/tests/plcdrv/utests/src/mailbox_utests.c
deleted file mode 100644
index b9cc7299a0..0000000000
--- a/cleopatre/devkit/tests/plcdrv/utests/src/mailbox_utests.c
+++ /dev/null
@@ -1,252 +0,0 @@
-/* Cleopatre project {{{
- *
- * Copyright (C) 2008 Spidcom
- *
- * <<<Licence>>>
- *
- * }}} */
-/**
- * \file mailbox_utests.c
- * \brief Unitary tests for Mailbox layer
- * \ingroup Cleopatre - PlcDrv
- *
- * This file content all the unitary tests for the mailbox layer,
- * this layer will provide all mechanisms to manage mailboxes.
- */
-
-#include <check.h>
-#include <stdio.h>
-#include <string.h>
-#include "mailbox.h"
-
-/** local defines */
-
-/** local variables */
-struct init_info info;
-
-/** Test init */
-START_TEST (test_mailbox_init)
-{
- fail_if(mailbox_init(NULL) != -1, "Error with argument checking");
- fail_if(mailbox_init((struct init_info*)0x55555555) != -1, "Error with halmbx error");
- fail_if(mailbox_init(&info) != 0, "Error with normal case");
-}
-END_TEST
-
-/** Test uninit */
-START_TEST (test_mailbox_uninit)
-{
-}
-END_TEST
-
-/** Test internal_send */
-START_TEST (test_internal_mailbox_send)
-{
- mailbox_init(&info);
- fail_if(internal_mailbox_send(NULL,4) != -1, "Error with argument checking");
- fail_if(internal_mailbox_send((uint32_t*)0x12345678, 4) != NEARLY_FULL, "Error with status queue");
- fail_if(internal_mailbox_send((uint32_t*)0x12345678, 4) != FULL, "Error with status queue");
- fail_if(internal_mailbox_send((uint32_t*)0x55555555, 4) != -1, "Error with copy to ring process");
- fail_if(internal_mailbox_send((uint32_t*)0x12345678, 0) != -1, "Error with A2Lmail_update");
- fail_if(internal_mailbox_send((uint32_t*)0x12345678, 8) != NOT_FULL, "Error with normal process");
-}
-END_TEST
-
-/** Test buffer_add */
-START_TEST (test_mailbox_buffer_add)
-{
- uint32_t eth_std[] = {0x11223344, 0x55667788, 0x99AABBCC};
-
- mailbox_init(&info);
-
- fail_if(mailbox_buffer_add(NULL,DATA) != -1, "Error with argument checking");
- fail_if(mailbox_buffer_add((uint32_t*)0x12345678,(enum buffer_type)10) != -1, "Error with argument checking");
-
- //WITH SEND TYPE DATA
- //Clear the previous msg for a new test
- mbx_buffer_add_result[0] = 0;
- mbx_buffer_add_result[1] = 0;
- //Add a data msg with eth_std pointer
- fail_if(mailbox_buffer_add((uint32_t*)eth_std, DATA) != 0, "Error with buffer add data");
- //Check msg header for buffer add type data
- fail_if(mbx_buffer_add_result[0] != 0x00000101,"Error with buffer add data msg header construction");
- //Check the if buffer_ptr is good
- fail_if(mbx_buffer_add_result[1] != (uint32_t)&eth_std[0] ,"Error with buffer add msg construction");
-
- //WITH SEND TYPE MME
- //Clear the previous msg for a new test
- mbx_buffer_add_result[0] = 0;
- mbx_buffer_add_result[1] = 0;
- //Add a mme msg with eth_std pointer
- fail_if(mailbox_buffer_add((uint32_t*)eth_std, MME) != 0, "Error with buffer add mme");
- //Check msg header for buffer add type mme
- fail_if(mbx_buffer_add_result[0] != 0x00001101,"Error with buffer add mme msg header construction");
- //Check the if buffer_ptr is good
- fail_if(mbx_buffer_add_result[1] != (uint32_t)&eth_std[0] ,"Error with buffer add msg construction");
-
- //WITH SEND TYPE INTERFACE
- //Clear the previous msg for a new test
- mbx_buffer_add_result[0] = 0;
- mbx_buffer_add_result[1] = 0;
- //Add a interface msg with eth_std pointer
- fail_if(mailbox_buffer_add((uint32_t*)eth_std, INTERFACE) != 0, "Error with buffer add interface");
- //Check msg header for buffer add type interface
- fail_if(mbx_buffer_add_result[0] != 0x00002101,"Error with buffer add interface msg header construction");
- //Check the if buffer_ptr is good
- fail_if(mbx_buffer_add_result[1] != (uint32_t)&eth_std[0] ,"Error with buffer add msg construction");
-}
-END_TEST
-
-/** Test send */
-START_TEST (test_mailbox_send)
-{
- uint32_t eth_std[] = {0x11223344, 0x55667788, 0x99AABBCC};
-
- mailbox_init(&info);
-
- fail_if(mailbox_send(NULL,4,DATA) != -1, "Error with argument checking");
- fail_if(mailbox_send((uint32_t*)0x12345678,0,DATA) != -1, "Error with argument checking");
- fail_if(mailbox_send((uint32_t*)0x12345678,4,(enum buffer_type)10) != -1, "Error with argument checking");
-
- //WITH SEND TYPE DATA
- //Clear the previous msg for a new test
- mbx_send_result[0] = 0;
- mbx_send_result[1] = 0;
- //Send a data msg with eth_std pointer
- fail_if(mailbox_send((uint32_t*)eth_std, sizeof(eth_std), DATA) != 0, "Error with send data");
- //Check msg header for send type data
- fail_if(mbx_send_result[0] != 0x00018100,"Error with send data msg header construction");
- //Check the if buffer_ptr is good
- fail_if(mbx_send_result[1] != (uint32_t)&eth_std[0] ,"Error with send msg construction");
-
- //WITH SEND TYPE MME
- //Clear the previous msg for a new test
- mbx_send_result[0] = 0;
- mbx_send_result[1] = 0;
- //Send a mme msg with eth_std pointer
- fail_if(mailbox_send((uint32_t*)eth_std, sizeof(eth_std), MME) != 0, "Error with send mme");
- //Check msg header for send type mme
- fail_if(mbx_send_result[0] != 0x00019100,"Error with send data msg header construction");
- //Check the if buffer_ptr is good
- fail_if(mbx_send_result[1] != (uint32_t)&eth_std[0] ,"Error with send msg construction");
-
- //WITH SEND TYPE INTERFACE
- //Clear the previous msg for a new test
- mbx_send_result[0] = 0;
- mbx_send_result[1] = 0;
- //Send a interface msg with eth_std pointer
- fail_if(mailbox_send((uint32_t*)eth_std, sizeof(eth_std), INTERFACE) != 0, "Error with send interface");
- //Check msg header for send type mme
- fail_if(mbx_send_result[0] != 0x00C02103,"Error with send data msg header construction");
- //Check the if buffer_ptr is good
- fail_if(mbx_send_result[1] != (uint32_t)&eth_std[0] ,"Error with send msg construction");
-}
-END_TEST
-
-/** Test receive */
-START_TEST (test_mailbox_receive)
-{
- mailbox_init(&info);
- //Check code the L2Amail_not_empty_queue
- glbctx.num_tst=0; //num_tst=0 L2Amail_not_empty_queue returns empty
- fail_if(mailbox_receive() != 0, "Error with not empty queue");
- //Check code with copy_from_ring error
- glbctx.num_tst=1; //num_tst=1 copy_from_ring returns an error
- fail_if(mailbox_receive() != -2, "Error with copy from ring");
- //Check code with update_ring_pointer error
- glbctx.num_tst=2; //num_tst=2 update_ring_pointer returns an error
- fail_if(mailbox_receive() != -3, "Error with update ring pointer");
-
- //CHECK THE REAL FUNCTIONNALITY OF THE FUNCTION
- //WITH SEND_DONE
- //Check code with processing_buffer_free error
- glbctx.num_tst=3; //num_tst=3 processing_buffer_free returns an error
- fail_if(mailbox_receive() != -4, "Error with send done false");
- //Check the real functionality of send_done
- glbctx.num_tst=4; //num_tst=4 processing_buffer_free returns OK
- fail_if(mailbox_receive() != 0, "Error with send done true");
- //num_tst=5 by processing_buffer_free to break the RX loop
- //Now check send_done message content (the addr pointer)
- fail_if(mbx_rx_ptr_result != SEND_DONE_ADDRESS, "Error with RX send done");
-
-
- //WITH INTERFACE
- //Check code with processing_receive error
- glbctx.num_tst=6; //num_tst=6 processing_receive returns an error
- fail_if(mailbox_receive() != -5, "Error with interface false");
- //Check the real functionality of interface
- glbctx.num_tst=7; //num_tst=7 processing_receive returns OK
- fail_if(mailbox_receive() != 0, "Error with interface true");
- //num_tst=8 by processing_receive to break the RX loop
- //Now check interface message content (the addr pointer)
- fail_if(mbx_rx_ptr_result != INTERFACE_ADDRESS, "Error with RX interface");
-
-
- //WITH MME
- //Check code with processing_receive error
- glbctx.num_tst=9; //num_tst=9 processing_receive returns an error
- fail_if(mailbox_receive() != -6, "Error with mme false");
- //Check the real functionality of mme
- glbctx.num_tst=10; //num_tst=10 processing_receive returns OK
- fail_if(mailbox_receive() != 0, "Error with mme true");
- //num_tst=11 by processing_receive to break the RX loop
- //Now check mme message content (the addr pointer)
- fail_if(mbx_rx_ptr_result != DATAMME_ADDRESS, "Error with RX mme");
-
- //WITH DATA
- //Check code with processing_receive error
- glbctx.num_tst=12; //num_tst=12 processing_receive returns an error
- fail_if(mailbox_receive() != -7, "Error with data false");
- //Check the real functionality of data
- glbctx.num_tst=13; //num_tst=13 processing_receive returns OK
- fail_if(mailbox_receive() != 0, "Error with data true");
- //num_tst=14 by processing_receive to break the RX loop
- //Now check data message content (the addr pointer)
- fail_if(mbx_rx_ptr_result != DATADATA_ADDRESS, "Error with RX data");
-
-
- //WITH ERROR TYPE
-// fail_if(mailbox_receive() != -1, "Error with message type");
-}
-END_TEST
-
-
-extern Suite* processing_suite(void)
-{
- Suite *s = suite_create("MAILBOX");
- TCase *tc_core = tcase_create("Core");
-
- //Test init
- tcase_add_test(tc_core, test_mailbox_init);
- //Test uninit
- tcase_add_test(tc_core, test_mailbox_uninit);
- //Test internal_send
- tcase_add_test(tc_core, test_internal_mailbox_send);
- //Test buffer_add
- tcase_add_test(tc_core, test_mailbox_buffer_add);
- //Test send
- tcase_add_test(tc_core, test_mailbox_send);
- //Test receive
- tcase_add_test(tc_core, test_mailbox_receive);
-
- suite_add_tcase(s, tc_core);
- return s;
-}
-
-int main(void)
-{
- int number_failed = 0;
- Suite *s;
-
- //Run Processing tests
- s = processing_suite();
-
- SRunner *sr = srunner_create(s);
- srunner_set_fork_status (sr, CK_NOFORK);
- srunner_run_all(sr, CK_NORMAL);
- number_failed = srunner_ntests_failed(sr);
- srunner_free(sr);
-
- return (number_failed == 0) ? 0 : -1;
-}
-
diff --git a/cleopatre/devkit/tests/plcdrv/utests/src/processing_utests.c b/cleopatre/devkit/tests/plcdrv/utests/src/processing_utests.c
deleted file mode 100644
index 9035df1969..0000000000
--- a/cleopatre/devkit/tests/plcdrv/utests/src/processing_utests.c
+++ /dev/null
@@ -1,230 +0,0 @@
-/* Cleopatre project {{{
- *
- * Copyright (C) 2008 Spidcom
- *
- * <<<Licence>>>
- *
- * }}} */
-/**
- * \file processing_utests.c
- * \brief Unitary tests for Porcessing layer
- * \ingroup Cleopatre - PlcDrv
- *
- * This file content all the unitary tests for the processing layer,
- * this layer will analyse all frames(TX ans RX) and decided to pass and drop it.
- */
-
-#include <check.h>
-#include <stdio.h>
-#include <string.h>
-#include "processing.h"
-
-/** local defines */
-#define ETH_P_HPAV 0x88E1
-#define HPAV_MME_VERSION 0x01
-#define HPAV_MME_TYPE_FCALL 0xABCD
-#define HPAV_MME_FMI 0x2664
-
-/** local variables */
-static uint8_t eth_std[] = {
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, //src addr
- 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, //dst addr
- 0x34, 0x12, //eth type
- 0x01, //eth raw
- 0x88, 0x99,
- 0x55, 0x66,
- 0x99
-};
-static uint8_t eth_hpav[] = {
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, //src addr
- 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, //dst addr
- 0x88, 0xE1, //eth type=HPAV
- 0x01, //mme version
- 0x88, 0x99, //mme type=unknown
- 0x55, 0x66, //mme fmi
- 0x99
-};
-static uint8_t eth_hpav_fcall[] = {
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, //src addr
- 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, //dst addr
- 0x88, 0xE1, //eth type=HPAV
- 0x01, //mme version
- 0xAB, 0xCD, //mme type=fcall
- 0x26, 0x64, //mme fmi
- 0x99
-};
-
-/** Test init */
-START_TEST (test_processing_init)
-{
- struct init_info info;
- fail_if(processing_init(NULL) == 0, "Error checking arguments");
- fail_if(processing_init((struct init_info*)0x55555555) == 0, "Error with mailbox layer error");
- fail_if(processing_init(&info) != 0, "Error checking normal case");
-}
-END_TEST
-
-/** Test uninit */
-START_TEST (test_processing_uninit)
-{
-}
-END_TEST
-
-/** Test get_eth_src_addr */
-START_TEST (test_processing_get_eth_src_addr)
-{
- uint8_t source[6];
- int i;
- get_eth_src_addr(eth_std, source);
- for(i=0; i<6; i++)
- {
- fail_if(source[i] != eth_std[i+6], "Error with Eth src addr copy");
- }
-}
-END_TEST
-
-/** Test get_eth_dst_addr */
-START_TEST (test_processing_get_eth_dst_addr)
-{
- uint8_t dst[6];
- int i;
- get_eth_dst_addr(eth_std, dst);
- for(i=0; i<6; i++)
- {
- fail_if(dst[i] != eth_std[i], "Error with Eth dst addr copy");
- }
-}
-END_TEST
-
-/** Test get_eth_type */
-START_TEST (test_processing_get_eth_type)
-{
- fail_if(get_eth_type(eth_hpav) != ETH_P_HPAV, "Error with Eth type search");
-}
-END_TEST
-
-/** Test get_eth_mme_version */
-START_TEST (test_processing_get_eth_mme_version)
-{
- fail_if(get_eth_mme_version(eth_hpav) != HPAV_MME_VERSION, "Error with HPAV MME version search");
-}
-END_TEST
-
-/** Test get_eth_mme_type */
-START_TEST (test_processing_get_eth_mme_type)
-{
- fail_if(get_eth_mme_type(eth_hpav_fcall) != HPAV_MME_TYPE_FCALL, "Error with HPAV MME type search");
-}
-END_TEST
-
-/** Test get_eth_mme_fmi */
-START_TEST (test_processing_get_eth_mme_fmi)
-{
- fail_if(get_eth_mme_fmi(eth_hpav_fcall) != HPAV_MME_FMI, "Error with HPAV MME fmi search");
-}
-END_TEST
-
-/** Test processing_buffer_add */
-START_TEST (test_processing_buffer_add)
-{
- fail_if(processing_buffer_add((void*)NULL, DATA) != -1, "Error with prepare_hw procedure");
-
- fail_if(processing_buffer_add(eth_hpav_fcall, MME) != 0, "Error with sending a known frame");
- fail_if(processing_buffer_add(eth_std, (enum buffer_type)10) != -1, "Error with sending an unknown type frame");
-}
-END_TEST
-
-/** Test processing_buffer_free */
-START_TEST (test_processing_buffer_free)
-{
- fail_if(processing_buffer_free((void*)NULL) != -1, "Error with prepare_hw procedure");
-
- fail_if(processing_buffer_free((void*)0x12345678) != 0, "Error with freeing a known frame");
- fail_if(processing_buffer_free((void*)0x55555555) != -1, "Error with freeing an unknown type frame");
-}
-END_TEST
-
-/** Test processing_send */
-START_TEST (test_processing_send)
-{
- fail_if(processing_send(NULL, 124) != -1, "Error with arguments checking");
- fail_if(processing_send((void*)0x12345678, 0) != -1, "Error with arguments checking");
- fail_if(processing_send((void*)0x12345678, 2000) != -1, "Error with arguments checking");
-
- fail_if(processing_send((void*)eth_std, 100) != -1, "Error with prepare_hw procedure");
-
- fail_if(processing_send(eth_hpav_fcall, 70) != 3, "Error with sending an Interface frame");
- fail_if(processing_send(eth_hpav, 70) != 2, "Error with sending a Mme frame");
- fail_if(processing_send(eth_std, 70) != 1, "Error with sending a Data frame");
-}
-END_TEST
-
-/** Test processing_receive */
-START_TEST (test_processing_receive)
-{
- fail_if(processing_receive(NULL, 124, DATA) != -1, "Error with arguments checking");
- fail_if(processing_receive((void*)0x12345678, 0, DATA) != -1, "Error with arguments checking");
- fail_if(processing_receive((void*)0x12345678, 2000, DATA) != -1, "Error with arguments checking");
-
- fail_if(processing_receive((void*)0x12345678, 100, DATA) != -1, "Error with prepare_hw procedure");
-
- fail_if(processing_receive(eth_hpav_fcall, 70, INTERFACE) != 0, "Error with receiving an Interface frame");
- fail_if(processing_receive(eth_hpav, 70, MME) != 0, "Error with receiving a Mme frame");
- fail_if(processing_receive(eth_hpav, 70, DATA) != 0, "Error with receiving a Data frame");
- fail_if(processing_receive(eth_hpav, 70, (enum buffer_type)10) != -1, "Error with receiving a unknown frame");
-
- fail_if(processing_receive((void*)0x55555555, 70, DATA) != -1, "Error with plcdrv_rx procedure");
-}
-END_TEST
-
-
-extern Suite* processing_suite(void)
-{
- Suite *s = suite_create("PROCESSING");
- TCase *tc_core = tcase_create("Core");
-
- //Test init
- tcase_add_test(tc_core, test_processing_init);
- //Test uninit
- tcase_add_test(tc_core, test_processing_uninit);
- //Test get_eth_src_addr
- tcase_add_test(tc_core, test_processing_get_eth_src_addr);
- //Test get_eth_dst_addr
- tcase_add_test(tc_core, test_processing_get_eth_dst_addr);
- //Test get_eth_type
- tcase_add_test(tc_core, test_processing_get_eth_type);
- //Test get_eth_mme_version
- tcase_add_test(tc_core, test_processing_get_eth_mme_version);
- //Test get_eth_mme_type
- tcase_add_test(tc_core, test_processing_get_eth_mme_type);
- //Test get_eth_mme_fmi
- tcase_add_test(tc_core, test_processing_get_eth_mme_fmi);
- //Test processing_buffer_add
- tcase_add_test(tc_core, test_processing_buffer_add);
- //Test processing_buffer_add
- tcase_add_test(tc_core, test_processing_buffer_free);
- //Test processing_send
- tcase_add_test(tc_core, test_processing_send);
- //Test processing_receive
- tcase_add_test(tc_core, test_processing_receive);
-
- suite_add_tcase(s, tc_core);
- return s;
-}
-
-int main(void)
-{
- int number_failed = 0;
- Suite *s;
-
- //Run Processing tests
- s = processing_suite();
-
- SRunner *sr = srunner_create(s);
- srunner_run_all(sr, CK_NORMAL);
- number_failed = srunner_ntests_failed(sr);
- srunner_free(sr);
-
- return (number_failed == 0) ? 0 : -1;
-}
-
diff --git a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/Module b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/Module
index c0143da23f..40db90b452 100644
--- a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/Module
+++ b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/Module
@@ -1,2 +1,3 @@
-SOURCES := af_netlink.c afe.c bitops.c char_dev.c delay.c dma.c eth.c \
- ioremap.c irq_manage.c mutex.c net_dev.c softirq.c uaccess.c wait.c
+SOURCES := af_netlink.c afe.c char_dev.c delay.c dma.c eth.c ioremap.c \
+ irq_manage.c mutex.c net_dev.c softirq.c spc300.c uaccess.c \
+ wait.c jiffies.c
diff --git a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/asm/arch/hardware/regbank.h b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/asm/arch/hardware/regbank.h
index bbcc8e4de8..21406fb8ad 100644
--- a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/asm/arch/hardware/regbank.h
+++ b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/asm/arch/hardware/regbank.h
@@ -9,5 +9,6 @@
#define RB_RST_GLOBAL_VA (*(volatile uint32_t *)0x55555555)
#define RST_LEONSS (0x8)
#define RST_LCPU (0x800)
+#define RST_DSP (0x4)
#endif /* stub_linux_inc_linux_asm_arch_hardware_regbank_h */
diff --git a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/asm/arch/ioctl.h b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/asm/arch/ioctl.h
new file mode 100644
index 0000000000..2fd6399425
--- /dev/null
+++ b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/asm/arch/ioctl.h
@@ -0,0 +1,12 @@
+#ifndef stub_linux_inc_linux_asm_arch_ioctl_h
+#define stub_linux_inc_linux_asm_arch_ioctl_h
+
+#define PLCDRV_IOCTL_SETPID (0)
+
+struct plcdrv_setpid
+{
+ int nl; /* Netlink to consider for pid registration */
+ int pid; /* Identifier of the process to register for reception */
+};
+
+#endif /* stub_linux_inc_linux_asm_arch_ioctl_h */
diff --git a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/asm/arch/platform.h b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/asm/arch/platform.h
new file mode 100644
index 0000000000..1da66d4c8d
--- /dev/null
+++ b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/asm/arch/platform.h
@@ -0,0 +1,11 @@
+#ifndef stub_linux_inc_linux_asm_arch_platform_h
+#define stub_linux_inc_linux_asm_arch_platform_h
+
+#include <linux/types.h>
+
+#define VIRT_PLCCODE_BASE (0xEF000000)
+
+extern uint32_t spc300_plc_mem_start;
+extern uint32_t spc300_plc_mem_size;
+
+#endif /* stub_linux_inc_linux_asm_arch_platform_h */
diff --git a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/asm.h b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/asm.h
index 20254883f1..9c569a0a0f 100644
--- a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/asm.h
+++ b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/asm.h
@@ -4,6 +4,7 @@
/** All stubs from linux/asm directory. */
#include <linux/compiler.h>
+#include <linux/bug.h>
/* types.h */
typedef unsigned char __u8;
@@ -17,6 +18,7 @@ typedef struct { volatile int counter; } atomic_t;
#define ATOMIC_INIT(i) { (i) }
#define atomic_read(v) ((v)->counter)
#define atomic_set(v,i) (((v)->counter) = (i))
+#define atomic_inc(v) ((v)->counter++)
/* rwsem.h */
struct rw_semaphore {};
@@ -25,9 +27,6 @@ struct rw_semaphore {};
#define POLLPRI 0x0002
#define POLLERR 0x0008
-/* bug.h */
-#define BUG_ON(condition) do { if (condition) {} } while(0)
-
/* processor.h */
static inline void prefetch(const void *ptr)
{
@@ -52,12 +51,7 @@ static inline void kfree(void * ptr)
/* arch/param.h */
#define HZ 100
-/* io.h */
-#define MT_DEVICE 0
-extern void * __arm_ioremap(unsigned long phys_addr, size_t size, unsigned int mtype);
-#define ioremap(cookie,size) __arm_ioremap(cookie, size, MT_DEVICE)
-extern void __iounmap(volatile void *addr);
-#define iounmap(cookie) __iounmap(cookie)
+#include <linux/io.h>
/* memory.h */
#define virt_to_dma(dev, addr) ((int) addr)
diff --git a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/bitops.h b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/bitops.h
index 83a16882b6..1d22755ea4 100644
--- a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/bitops.h
+++ b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/bitops.h
@@ -1,6 +1,9 @@
#ifndef inc_linux_asm_bitops_h
#define inc_linux_asm_bitops_h
-extern inline int test_bit(int nr, const volatile unsigned long *addr);
+extern inline int test_bit(int nr, const volatile unsigned long *addr)
+{
+ return 0;
+}
#endif /* inc_linux_asm_bitops_h */
diff --git a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/bug.h b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/bug.h
new file mode 100644
index 0000000000..2ee2e8b9cc
--- /dev/null
+++ b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/bug.h
@@ -0,0 +1,10 @@
+#ifndef stub_linux_inc_bug_h
+#define stub_linux_inc_bug_h
+
+#include <assert.h>
+
+#define BUG_ON(condition) do { assert (!(condition)); } while(0)
+
+#define BUG() do { BUG_ON(1); } while (0)
+
+#endif /* stub_linux_inc_bug_h */
diff --git a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/compiler.h b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/compiler.h
index bbe302a179..831647edfa 100644
--- a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/compiler.h
+++ b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/compiler.h
@@ -1,8 +1,12 @@
#ifndef stub_linux_inc_linux_compiler_h
#define stub_linux_inc_linux_compiler_h
+#define inline inline __attribute__((always_inline))
+
#define unlikely(x) x
#define __user
+#define barrier()
+
#endif /* stub_linux_inc_linux_compiler_h */
diff --git a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/device.h b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/device.h
index 309238757a..9ba2a32786 100644
--- a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/device.h
+++ b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/device.h
@@ -1,6 +1,8 @@
#ifndef stub_linux_inc_linux_device_h
#define stub_linux_inc_linux_device_h
-struct device;
+struct device
+{
+};
#endif /* stub_linux_inc_linux_device_h */
diff --git a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/dma-mapping.h b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/dma-mapping.h
index 327c7d0773..1f4d32e899 100644
--- a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/dma-mapping.h
+++ b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/dma-mapping.h
@@ -3,6 +3,7 @@
#include <linux/types.h>
#include <linux/device.h>
+#include <linux/gfp.h>
enum dma_data_direction {
DMA_BIDIRECTIONAL = 0,
diff --git a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/errno.h b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/errno.h
index 7e8a432ba4..d8a480081d 100644
--- a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/errno.h
+++ b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/errno.h
@@ -8,5 +8,6 @@
#define EFAULT 1
#define EPERM 1
#define EBUSY 1
+#define ENOSPC 1
#endif /* stub_linux_inc_linux_errno_h */
diff --git a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/etherdevice.h b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/etherdevice.h
new file mode 100644
index 0000000000..8ddfeaf704
--- /dev/null
+++ b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/etherdevice.h
@@ -0,0 +1,14 @@
+#ifndef stub_linux_inc_linux_etherdevice_h
+#define stub_linux_inc_linux_etherdevice_h
+
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+
+extern void
+ether_setup (struct net_device *dev);
+
+extern __be16
+eth_type_trans (struct sk_buff *skb, struct net_device *dev);
+
+#endif /* stub_linux_inc_linux_etherdevice_h */
diff --git a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/firmware.h b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/firmware.h
new file mode 100644
index 0000000000..d99c5af1d3
--- /dev/null
+++ b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/firmware.h
@@ -0,0 +1,26 @@
+#ifndef stub_linux_inc_linux_firmware_h
+#define stub_linux_inc_linux_firmware_h
+
+#include <linux/device.h>
+
+struct firmware
+{
+ void *data;
+ size_t size;
+};
+
+int
+request_firmware (const struct firmware **firmware_p, const char *name,
+ struct device *device)
+{
+ BUG ();
+}
+
+void
+release_firmware(const struct firmware *fw)
+{
+ BUG ();
+}
+
+
+#endif /* stub_linux_inc_linux_firmware_h */
diff --git a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/if.h b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/if.h
index 0641cbde81..508e4e522a 100644
--- a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/if.h
+++ b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/if.h
@@ -3,6 +3,7 @@
struct ifreq {
char dummy;
+ void *ifr_data;
};
#endif /* stub_linux_inc_linux_if_h */
diff --git a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/if_ether.h b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/if_ether.h
index ae973e4d35..25fcd5d963 100644
--- a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/if_ether.h
+++ b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/if_ether.h
@@ -3,6 +3,7 @@
#include <linux/types.h>
+#define ETH_P_HPAV 0x88E1 /* HomePlug AV packet */
#define ETH_P_8021Q 0x8100
#define ETH_ALEN 6 /* Octets in one ethernet addr */
diff --git a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/if_vlan.h b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/if_vlan.h
index 3c4db05de9..a0705404eb 100644
--- a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/if_vlan.h
+++ b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/if_vlan.h
@@ -2,6 +2,7 @@
#define stub_linux_inc_linux_if_vlan_h
#include <linux/types.h>
+#include <linux/if_ether.h>
#define VLAN_ETH_ALEN 6
#define VLAN_ETH_HLEN 18
diff --git a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/io.h b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/io.h
new file mode 100644
index 0000000000..d551f86c3e
--- /dev/null
+++ b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/io.h
@@ -0,0 +1,11 @@
+#ifndef io_h
+#define io_h
+
+/* io.h */
+#define MT_DEVICE 0
+extern void * __arm_ioremap(unsigned long phys_addr, size_t size, unsigned int mtype);
+#define ioremap(cookie,size) __arm_ioremap(cookie, size, MT_DEVICE)
+extern void __iounmap(volatile void *addr);
+#define iounmap(cookie) __iounmap(cookie)
+
+#endif /* io_h */
diff --git a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/jiffies.h b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/jiffies.h
new file mode 100644
index 0000000000..4b81451aa7
--- /dev/null
+++ b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/jiffies.h
@@ -0,0 +1,6 @@
+#ifndef stub_linux_inc_linux_jiffies_h
+#define stub_linux_inc_linux_jiffies_h
+
+extern unsigned long volatile jiffies;
+
+#endif /* stub_linux_inc_linux_jiffies_h */
diff --git a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/kernel.h b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/kernel.h
index 022d68bad7..4694427a5b 100644
--- a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/kernel.h
+++ b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/kernel.h
@@ -1,6 +1,9 @@
#ifndef stub_linux_inc_linux_kernel_h
#define stub_linux_inc_linux_kernel_h
+#include <linux/bitops.h>
+#include <asm/arch/platform.h>
+
/* from stddef.h */
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
@@ -14,8 +17,10 @@
(void) (&_x == &_y); \
_x < _y ? _x : _y; })
+#define KERN_CRIT "<2>"
#define KERN_ERR "<3>"
#define KERN_WARNING "<4>"
+#define KERN_NOTICE "<5>"
#define KERN_INFO "<6>"
static inline int printk(const char *s, ...)
@@ -23,6 +28,20 @@ static inline int printk(const char *s, ...)
return 0;
}
+static inline int printk_ratelimit(void)
+{
+ return 0;
+}
+
+static inline void dump_stack(void)
+{
+}
+
+#define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask))
+#define ALIGN(x,a) __ALIGN_MASK(x,(typeof(x))(a)-1)
+
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+
/* from byteorder/generic.h */
static inline unsigned short int ntohs(unsigned short int x)
{
@@ -30,5 +49,6 @@ static inline unsigned short int ntohs(unsigned short int x)
}
#define be16_to_cpu(x) ((__u16)(__be16)(x))
+#define cpu_to_be32p(x) (*x)
#endif /* stub_linux_inc_linux_kernel_h */
diff --git a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/module.h b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/module.h
index 1cb1188291..8b042ed936 100644
--- a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/module.h
+++ b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/module.h
@@ -1,6 +1,9 @@
#ifndef stub_linux_inc_linux_module_h
#define stub_linux_inc_linux_module_h
+#include <linux/gfp.h>
+#include <linux/moduleparam.h>
+
struct module;
#define THIS_MODULE ((struct module *)0)
diff --git a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/moduleparam.h b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/moduleparam.h
index d932f30e88..c4d2f9ca65 100644
--- a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/moduleparam.h
+++ b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/moduleparam.h
@@ -2,5 +2,6 @@
#define stub_linux_inc_linux_moduleparam_h
#define module_param(a,b,c)
+#define module_param_string(name, string, len, perm)
#endif /* stub_linux_inc_linux_moduleparam_h */
diff --git a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/netdevice.h b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/netdevice.h
index 2b9ab7ceb6..2cc22086f6 100644
--- a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/netdevice.h
+++ b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/netdevice.h
@@ -4,6 +4,13 @@
#include <linux/types.h>
#include <linux/skbuff.h>
#include <linux/if.h>
+#include <linux/list.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/etherdevice.h>
+
+#define NETDEV_TX_OK 0 /* driver took care of packet */
+#define NETDEV_TX_BUSY 1 /* driver tx path was busy*/
struct net_device_stats {
unsigned long rx_packets; /* total packets received */
@@ -37,6 +44,13 @@ struct net_device_stats {
unsigned long tx_compressed;
};
+struct napi_struct {
+ struct list_head poll_list;
+ unsigned long state;
+ int weight;
+ int (*poll)(struct napi_struct *, int);
+};
+
/* linux_drv_utests.h stub */
struct net_device {
char name[16];
@@ -47,7 +61,9 @@ struct net_device {
unsigned int irq;
unsigned int mtu;
unsigned long trans_start;
+ struct device dev;
int (*init)(struct net_device *dev);
+ void (*uninit)(struct net_device *dev);
int (*hard_start_xmit)(struct sk_buff *skb, struct net_device *dev);
int (*open)(struct net_device *dev);
int (*stop)(struct net_device *dev);
@@ -84,9 +100,23 @@ static inline int netif_queue_stopped(const struct net_device *dev)
{
return 0;
}
-
-extern void ether_setup(struct net_device *dev);
-/* from etherdevice.h */
-extern __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev);
+void netif_rx_complete(struct net_device *dev, struct napi_struct *napi);
+extern int netif_receive_skb(struct sk_buff *skb);
+static inline void netif_rx_schedule(struct net_device *dev,
+ struct napi_struct *napi)
+{
+}
+static inline void napi_enable(struct napi_struct *n)
+{
+}
+static inline void napi_disable(struct napi_struct *n)
+{
+}
+static inline void netif_napi_add(struct net_device *dev,
+ struct napi_struct *napi,
+ int (*poll)(struct napi_struct *, int),
+ int weight)
+{
+}
#endif /* stub_linux_inc_linux_netdevice_h */
diff --git a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/proc_fs.h b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/proc_fs.h
index dc3ac29603..ece0f03def 100644
--- a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/proc_fs.h
+++ b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/proc_fs.h
@@ -18,8 +18,9 @@ static inline struct proc_dir_entry *proc_mkdir(const char *name,
return NULL;
}
-static inline struct proc_dir_entry *create_proc_entry(const char *name,
- mode_t mode, struct proc_dir_entry *parent)
+static inline struct proc_dir_entry *create_proc_read_entry(
+ const char *name, mode_t mode, struct proc_dir_entry *base,
+ read_proc_t *read_proc, void *data)
{
return NULL;
}
diff --git a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/skbuff.h b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/skbuff.h
index 523824e453..256b5c62ae 100644
--- a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/skbuff.h
+++ b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/skbuff.h
@@ -4,6 +4,7 @@
#include <linux/types.h>
#define CHECKSUM_UNNECESSARY 1
+#define NET_SKB_PAD 16
/* linux_drv_utests.h stub */
struct sk_buff {
@@ -15,12 +16,21 @@ struct sk_buff {
char cb[48];
};
+struct sk_buff_head {
+};
+
static inline struct sk_buff *alloc_skb(unsigned int size, int priority)
{
struct sk_buff* skb;
skb = (struct sk_buff*)malloc((unsigned int)(sizeof(struct sk_buff)));
return skb;
}
+
+static inline struct sk_buff *dev_alloc_skb(unsigned int length)
+{
+ return alloc_skb (length, 0);
+}
+
static inline void kfree_skb(struct sk_buff *skb)
{
if(skb)
@@ -37,9 +47,64 @@ static inline int skb_tailroom(const struct sk_buff *skb)
return 0;
}
+static inline int skb_headroom(const struct sk_buff *skb)
+{
+ return NET_SKB_PAD;
+}
+
static inline unsigned char *skb_pull(struct sk_buff *skb, unsigned int len)
{
return NULL;
}
+static inline struct sk_buff *skb_copy(const struct sk_buff *skb,
+ gfp_t priority)
+{
+ return NULL;
+}
+
+static inline int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail,
+ gfp_t gfp_mask)
+{
+ return 0;
+}
+
+static inline int skb_header_cloned(const struct sk_buff *skb)
+{
+ return 0;
+}
+
+static inline void __skb_unlink(struct sk_buff *skb,
+ struct sk_buff_head *list)
+{
+ BUG ();
+}
+
+static inline __u32 skb_queue_len(const struct sk_buff_head *list_)
+{
+ return 0;
+}
+
+static inline void __skb_queue_head(struct sk_buff_head *list,
+ struct sk_buff *newsk)
+{
+ BUG ();
+}
+
+static inline void skb_queue_head(struct sk_buff_head *list,
+ struct sk_buff *newsk)
+{
+ BUG ();
+}
+
+static inline void __skb_queue_purge(struct sk_buff_head *list)
+{
+ BUG ();
+}
+
+static inline void skb_queue_head_init(struct sk_buff_head *list)
+{
+ BUG ();
+}
+
#endif /* stub_linux_inc_linux_skbuff_h */
diff --git a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/spinlock.h b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/spinlock.h
index 76bb624db0..f3f6702389 100644
--- a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/spinlock.h
+++ b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/spinlock.h
@@ -27,9 +27,7 @@ typedef struct {
# define spin_lock_init(lock) \
do { *(lock) = SPIN_LOCK_UNLOCKED; } while (0)
-#define spin_lock_irqsave(lock, flags) ((int) 0)
-#define spin_lock_irqrestore(lock, flags) ((int) 0)
-
-#define spin_unlock_irqrestore(lock, flags) ((int) 0)
+#define spin_lock_bh(lock) ((void) 0)
+#define spin_unlock_bh(lock) ((void) 0)
#endif /* stub_linux_inc_linux_spinlock_h */
diff --git a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/types.h b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/types.h
index 0643cc52b9..ade261f942 100644
--- a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/types.h
+++ b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/types.h
@@ -3,6 +3,8 @@
#include <linux/asm.h>
+#include <linux/compiler.h>
+
#include <stdint.h>
#include <sys/types.h>
@@ -12,7 +14,7 @@ typedef _Bool bool;
typedef unsigned char u8;
typedef unsigned short u16;
-typedef unsigned long u32;
+typedef unsigned int u32;
typedef unsigned long long u64;
typedef __u16 __be16;
diff --git a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/wait.h b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/wait.h
index c2b2fdd940..112399a9a5 100644
--- a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/wait.h
+++ b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/inc/linux/wait.h
@@ -19,8 +19,8 @@ typedef struct __wait_queue_head wait_queue_head_t;
wait_queue_head_t name = __WAIT_QUEUE_HEAD_INITIALIZER(name)
#define wait_event_interruptible(wq, condition) ((int) 0)
-#define wake_up(x) ((int) 0)
-#define wake_up_interruptible(x) ((int) 0)
+#define wake_up(x) ((void) 0)
+#define wake_up_interruptible(x) ((void) 0)
static inline int waitqueue_active(wait_queue_head_t *q)
{
diff --git a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/src/bitops.c b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/src/bitops.c
deleted file mode 100644
index 824bdeeba1..0000000000
--- a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/src/bitops.c
+++ /dev/null
@@ -1,6 +0,0 @@
-#include <linux/bitops.h>
-
-inline int test_bit(int nr, const volatile unsigned long *addr)
-{
- return 0;
-}
diff --git a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/src/eth.c b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/src/eth.c
index 37eac916a7..a9eeb16a3a 100644
--- a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/src/eth.c
+++ b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/src/eth.c
@@ -8,5 +8,5 @@ void ether_setup(struct net_device *dev)
__be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev)
{
- return 5;
+ return 0;
}
diff --git a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/src/jiffies.c b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/src/jiffies.c
new file mode 100644
index 0000000000..8dbed25470
--- /dev/null
+++ b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/src/jiffies.c
@@ -0,0 +1 @@
+unsigned long volatile jiffies;
diff --git a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/src/net_dev.c b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/src/net_dev.c
index 31f63a46ba..68f18b5f82 100644
--- a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/src/net_dev.c
+++ b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/src/net_dev.c
@@ -1,6 +1,8 @@
+#include <stdlib.h>
#include <linux/netdevice.h>
+#include <net/net_namespace.h>
-#include <stdlib.h>
+struct net init_net;
int register_netdev(struct net_device *dev)
{
@@ -40,3 +42,11 @@ void netif_carrier_off(struct net_device *dev)
{
}
+void netif_rx_complete(struct net_device *dev, struct napi_struct *napi)
+{
+}
+
+int netif_receive_skb(struct sk_buff *skb)
+{
+ return 0;
+}
diff --git a/cleopatre/devkit/tests/plcdrv/utests/stub/linux/src/spc300.c b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/src/spc300.c
new file mode 100644
index 0000000000..eb3420b098
--- /dev/null
+++ b/cleopatre/devkit/tests/plcdrv/utests/stub/linux/src/spc300.c
@@ -0,0 +1,6 @@
+#include <linux/types.h>
+#include <asm/arch/nvram.h>
+
+spc300_nvram_t spc300_nvram;
+uint32_t spc300_plc_mem_start;
+uint32_t spc300_plc_mem_size;