summaryrefslogtreecommitdiff
path: root/cleopatre
diff options
context:
space:
mode:
authorOlivier Dufour2013-04-26 17:06:16 +0200
committerOlivier Dufour2013-05-07 14:31:13 +0200
commit0fdbfa18a46bd832fe0b4f2a5d05c8687fd5d0dc (patch)
treedc44a50765b853018f0e7ca58459871e6606cac0 /cleopatre
parent3e414e4983fc9a25d9dc461506f5fd6ce4605953 (diff)
cleo/app/debug-utils: implement ioctl in debug-drv, refs #3956
Diffstat (limited to 'cleopatre')
-rw-r--r--cleopatre/application/debug-utils/debug-drv/inc/debugdrv.h11
-rw-r--r--cleopatre/application/debug-utils/debug-drv/src/debugdrv.c56
2 files changed, 67 insertions, 0 deletions
diff --git a/cleopatre/application/debug-utils/debug-drv/inc/debugdrv.h b/cleopatre/application/debug-utils/debug-drv/inc/debugdrv.h
index ca232cbb2f..c97eab65dc 100644
--- a/cleopatre/application/debug-utils/debug-drv/inc/debugdrv.h
+++ b/cleopatre/application/debug-utils/debug-drv/inc/debugdrv.h
@@ -1,6 +1,17 @@
#ifndef DEBUGDRV_H_
#define DEBUGDRV_H_
+
#define DEBUG_DEVICE "/dev/debugdrv"
+#define IOC_DEBUGDRV_REGISTER_READ 1
+#define IOC_DEBUGDRV_REGISTER_WRITE 2
+
+/* Memory map structure. */
+typedef struct {
+ uint32_t address;
+ uint32_t value;
+} mem_t;
+
+
#endif /* DEBUGDRV_H_ */
diff --git a/cleopatre/application/debug-utils/debug-drv/src/debugdrv.c b/cleopatre/application/debug-utils/debug-drv/src/debugdrv.c
index ca330e85b9..13f98a8e15 100644
--- a/cleopatre/application/debug-utils/debug-drv/src/debugdrv.c
+++ b/cleopatre/application/debug-utils/debug-drv/src/debugdrv.c
@@ -1,6 +1,8 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
+#include <linux/io.h>
+#include <linux/ioctl.h>
#include <asm/uaccess.h>
#include "debugdrv.h"
@@ -8,6 +10,37 @@ MODULE_AUTHOR ("MStar Semiconductor");
MODULE_DESCRIPTION ("Memory mapper for debug");
MODULE_LICENSE ("GPL");
+/* Private structure to hold a list of all memory maps. */
+typedef struct {
+ uint32_t base_address;
+ uint32_t size;
+ void *virtual_address;
+} map_t;
+
+/* Current page. */
+static map_t io_page = {
+ 0xdeadbeef,
+ 0,
+};
+
+#define REG_ADDR(addr) (addr & 0xfffff000)
+#define REG_OFFSET(addr) (addr & 0xfff)
+
+static void
+page_map (uint32_t addr)
+{
+ iounmap (io_page.virtual_address);
+ io_page.size = 0x1000;
+ io_page.virtual_address = ioremap (addr, 0x1000);
+ io_page.base_address = addr;
+}
+
+static int
+is_mapped (uint32_t addr)
+{
+ return io_page.size && (io_page.base_address == REG_ADDR(addr));
+}
+
/* Forward declaration. */
static int debugdrv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
static int debugdrv_open(struct inode *inode, struct file *file);
@@ -21,6 +54,27 @@ static struct file_operations debugdrv_fops = {
static int debugdrv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
+ mem_t req;
+ if (copy_from_user (&req, (void *)arg, sizeof (mem_t)))
+ return -1;
+
+ switch (cmd)
+ {
+ case IOC_DEBUGDRV_REGISTER_READ:
+ if (!is_mapped (req.address))
+ page_map (REG_ADDR(req.address));
+ req.value = *((uint32_t *)((unsigned char *)(io_page.virtual_address) + REG_OFFSET(req.address)));
+ if (copy_to_user ((void *)arg, &req, sizeof (mem_t)))
+ return -1;
+ break;
+ case IOC_DEBUGDRV_REGISTER_WRITE:
+ if (!is_mapped (req.address))
+ page_map (REG_ADDR(req.address));
+ *((uint32_t *)((unsigned char *)(io_page.virtual_address) + REG_OFFSET(req.address))) = req.value;
+ break;
+ default:
+ return -1;
+ }
return 0;
}
@@ -50,6 +104,8 @@ debugdrv_module_init (void)
void __exit
debugdrv_module_exit (void)
{
+ if (io_page.size)
+ iounmap (io_page.virtual_address);
unregister_chrdev(42, "debugdrv");
}