summaryrefslogtreecommitdiff
path: root/cleopatre
diff options
context:
space:
mode:
authorJérémy Dufour2010-12-21 11:46:35 +0100
committerJérémy Dufour2011-01-04 11:19:04 +0100
commitbb48d6d13c6122e42be0b17f35cbf28229f04fad (patch)
tree2269434cefde5345d67c335a72f9d2bcd664bbd4 /cleopatre
parent340046df05abf386b2cac0c1f9b66f9aef538443 (diff)
cleo/devkit/plcdrv: add device to read debug dump from cesar, refs #2071
Diffstat (limited to 'cleopatre')
-rwxr-xr-xcleopatre/buildroot/target/device/Spidcom/scr310/target_skeleton/etc/init.d/S30plc1
-rwxr-xr-xcleopatre/buildroot/target/device/Spidcom/spk300/target_skeleton/etc/init.d/S30plc1
-rwxr-xr-xcleopatre/buildroot/target/device/Spidcom/spk300g/target_skeleton/etc/init.d/S30plc1
-rwxr-xr-xcleopatre/buildroot/target/device/Spidcom/spk310/target_skeleton/etc/init.d/S30plc1
-rwxr-xr-xcleopatre/buildroot/target/device/Spidcom/spr300/target_skeleton/etc/init.d/S30plc1
-rw-r--r--cleopatre/devkit/plcdrv/arm/inc/linux_drv.h26
-rw-r--r--cleopatre/devkit/plcdrv/arm/src/linux_drv.c182
7 files changed, 208 insertions, 5 deletions
diff --git a/cleopatre/buildroot/target/device/Spidcom/scr310/target_skeleton/etc/init.d/S30plc b/cleopatre/buildroot/target/device/Spidcom/scr310/target_skeleton/etc/init.d/S30plc
index d805d8dfc4..9c42349720 100755
--- a/cleopatre/buildroot/target/device/Spidcom/scr310/target_skeleton/etc/init.d/S30plc
+++ b/cleopatre/buildroot/target/device/Spidcom/scr310/target_skeleton/etc/init.d/S30plc
@@ -18,6 +18,7 @@ start() {
fi
/bin/mknod /dev/plcdrv c 254 0
/bin/chmod 666 /dev/plcdrv
+ /bin/mknod /dev/trace c 254 1
echo "Loading PLC firmware..."
if [ -e /usr/local$plcfw ] ; then
dd if=/usr/local/$plcfw of=/dev/plcdrv
diff --git a/cleopatre/buildroot/target/device/Spidcom/spk300/target_skeleton/etc/init.d/S30plc b/cleopatre/buildroot/target/device/Spidcom/spk300/target_skeleton/etc/init.d/S30plc
index d805d8dfc4..9c42349720 100755
--- a/cleopatre/buildroot/target/device/Spidcom/spk300/target_skeleton/etc/init.d/S30plc
+++ b/cleopatre/buildroot/target/device/Spidcom/spk300/target_skeleton/etc/init.d/S30plc
@@ -18,6 +18,7 @@ start() {
fi
/bin/mknod /dev/plcdrv c 254 0
/bin/chmod 666 /dev/plcdrv
+ /bin/mknod /dev/trace c 254 1
echo "Loading PLC firmware..."
if [ -e /usr/local$plcfw ] ; then
dd if=/usr/local/$plcfw of=/dev/plcdrv
diff --git a/cleopatre/buildroot/target/device/Spidcom/spk300g/target_skeleton/etc/init.d/S30plc b/cleopatre/buildroot/target/device/Spidcom/spk300g/target_skeleton/etc/init.d/S30plc
index d805d8dfc4..9c42349720 100755
--- a/cleopatre/buildroot/target/device/Spidcom/spk300g/target_skeleton/etc/init.d/S30plc
+++ b/cleopatre/buildroot/target/device/Spidcom/spk300g/target_skeleton/etc/init.d/S30plc
@@ -18,6 +18,7 @@ start() {
fi
/bin/mknod /dev/plcdrv c 254 0
/bin/chmod 666 /dev/plcdrv
+ /bin/mknod /dev/trace c 254 1
echo "Loading PLC firmware..."
if [ -e /usr/local$plcfw ] ; then
dd if=/usr/local/$plcfw of=/dev/plcdrv
diff --git a/cleopatre/buildroot/target/device/Spidcom/spk310/target_skeleton/etc/init.d/S30plc b/cleopatre/buildroot/target/device/Spidcom/spk310/target_skeleton/etc/init.d/S30plc
index d805d8dfc4..9c42349720 100755
--- a/cleopatre/buildroot/target/device/Spidcom/spk310/target_skeleton/etc/init.d/S30plc
+++ b/cleopatre/buildroot/target/device/Spidcom/spk310/target_skeleton/etc/init.d/S30plc
@@ -18,6 +18,7 @@ start() {
fi
/bin/mknod /dev/plcdrv c 254 0
/bin/chmod 666 /dev/plcdrv
+ /bin/mknod /dev/trace c 254 1
echo "Loading PLC firmware..."
if [ -e /usr/local$plcfw ] ; then
dd if=/usr/local/$plcfw of=/dev/plcdrv
diff --git a/cleopatre/buildroot/target/device/Spidcom/spr300/target_skeleton/etc/init.d/S30plc b/cleopatre/buildroot/target/device/Spidcom/spr300/target_skeleton/etc/init.d/S30plc
index d805d8dfc4..9c42349720 100755
--- a/cleopatre/buildroot/target/device/Spidcom/spr300/target_skeleton/etc/init.d/S30plc
+++ b/cleopatre/buildroot/target/device/Spidcom/spr300/target_skeleton/etc/init.d/S30plc
@@ -18,6 +18,7 @@ start() {
fi
/bin/mknod /dev/plcdrv c 254 0
/bin/chmod 666 /dev/plcdrv
+ /bin/mknod /dev/trace c 254 1
echo "Loading PLC firmware..."
if [ -e /usr/local$plcfw ] ; then
dd if=/usr/local/$plcfw of=/dev/plcdrv
diff --git a/cleopatre/devkit/plcdrv/arm/inc/linux_drv.h b/cleopatre/devkit/plcdrv/arm/inc/linux_drv.h
index e1a74a6425..cfaaaa4f3b 100644
--- a/cleopatre/devkit/plcdrv/arm/inc/linux_drv.h
+++ b/cleopatre/devkit/plcdrv/arm/inc/linux_drv.h
@@ -82,6 +82,32 @@ struct net_priv
};
/**
+ * Debug dump buffer physical address.
+ */
+extern uint32_t debug_dump_buffer_physical;
+/**
+ * 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.
diff --git a/cleopatre/devkit/plcdrv/arm/src/linux_drv.c b/cleopatre/devkit/plcdrv/arm/src/linux_drv.c
index 7018786c44..38dcc361fa 100644
--- a/cleopatre/devkit/plcdrv/arm/src/linux_drv.c
+++ b/cleopatre/devkit/plcdrv/arm/src/linux_drv.c
@@ -37,6 +37,7 @@
#include <linux/list.h>
#include <linux/netlink.h>
#include <linux/poll.h>
+#include <linux/wait.h>
#include <asm/arch/nvram.h>
#include <asm/arch/hardware/spi.h>
@@ -97,6 +98,8 @@ static struct net_device *plcdrv_device;
static dev_t number;
/** Our global character device */
static struct cdev plcdrv_char_dev;
+/** Our trace character device. */
+static struct cdev trace_cdev;
/** Our mutex between firmware download and network driver start-up */
static uint8_t write_called = 0;
@@ -113,6 +116,15 @@ static uint32_t dsu_trace = DSU_TRACE_PROC;
static int debug = 0;
static int nowd = 0;
uint32_t trace = 0;
+
+/** For debug dump buffer. */
+uint32_t debug_dump_buffer_physical = 0;
+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);
@@ -661,6 +673,145 @@ unsigned int plcdrv_char_poll(struct file *filp, poll_table * wait)
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);
+
+ //Cesar has already given us all the traces.
+ if (debug_dump_buffer_length_received == 0)
+ return 0;
+
+ //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;
+ //Get physical address.
+ debug_dump_buffer_physical = prepare_buffer_to_hw
+ ((uint32_t)debug_dump_buffer, sizeof (uint32_t));
+ if(debug_dump_buffer_physical == 0)
+ {
+ free_debug_dump_buffer(debug_dump_buffer,
+ debug_dump_buffer_length);
+ debug_dump_buffer = NULL;
+ return -ENOMEM;
+ }
+ }
+
+ //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)
+ {
+ error = mailbox_send_debug_dump((void *)debug_dump_buffer_physical,
+ debug_dump_buffer_length);
+ if (error != 0)
+ {
+ free_debug_dump_buffer(debug_dump_buffer,
+ debug_dump_buffer_length);
+ debug_dump_buffer = NULL;
+ debug_dump_buffer_physical = 0;
+ return error;
+ }
+ //Debug dump buffer has been given to Cesar.
+ debug_dump_waiting_for_buffer = true;
+ debug_dump_buffer_length_received = -1;
+ }
+
+ //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_physical = 0;
+ 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.
@@ -1759,6 +1910,13 @@ static struct file_operations plcdrv_char_fops = {
.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.
*
@@ -1775,7 +1933,7 @@ int __init plcdrv_module_init(void)
//Register a character device to manage Cesar Binary download
//Allocate character device Major number
- result = alloc_chrdev_region(&number, 0, 1, "plcdrv");
+ result = alloc_chrdev_region(&number, 0, 2, "plcdrv");
if(result < 0)
{
printk(KERN_ERR "plcdrv: can't get major %d\n",MAJOR(number));
@@ -1789,17 +1947,29 @@ int __init plcdrv_module_init(void)
if(result <0)
{
printk(KERN_ERR "plcdrv: Error registering\n");
- unregister_chrdev_region(number, 1);
+ 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);
- unregister_chrdev_region(number, 1);
+ cdev_del(&trace_cdev);
+ unregister_chrdev_region(number, 2);
return -ENOMEM;
}
//Initialize private structure
@@ -1814,7 +1984,8 @@ int __init plcdrv_module_init(void)
{
printk(KERN_ERR DRV_NAME": Error %i registering %s\n", result, dev->name);
cdev_del(&plcdrv_char_dev);
- unregister_chrdev_region(number, 1);
+ cdev_del(&trace_cdev);
+ unregister_chrdev_region(number, 2);
kfree(dev->priv);
free_netdev(dev);
return result;
@@ -1854,7 +2025,8 @@ void __exit plcdrv_module_exit(void)
//Unregister character device
cdev_del(&plcdrv_char_dev);
- unregister_chrdev_region(number, 1);
+ cdev_del(&trace_cdev);
+ unregister_chrdev_region(number, 2);
//Unregister network device
if(plcdrv_device)