diff --git a/Makefile b/Makefile index 4e7c189..9876de1 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,11 @@ KERNEL_BUILDROOT ?= /lib/modules/$(KERNEL_RELEASE)/build BUILDROOT = $(shell pwd) obj-m := fpgafs.o -fpgafs-objs := files.o inode.o +fpgafs-objs := files.o inode.o llmgmt.o + +# low level driver +obj-m += fpgafs_lldrv_dbg.o +obj-m += fpgafs_lldrv_cham.o all : $(MAKE) -C $(KERNEL_BUILDROOT) SUBDIRS=$(BUILDROOT) modules diff --git a/files.c b/files.c index beaa651..8867a7a 100644 --- a/files.c +++ b/files.c @@ -42,6 +42,7 @@ static ssize_t fpgafs_stat_read(struct file *file, char __user *buf, if (copy_to_user(buf, &data, sizeof(data))) return -EFAULT; + fpgafs_recv_data(NULL, 1); return 4; } @@ -66,6 +67,7 @@ static ssize_t fpgafs_cmd_write(struct file *file, const char __user *buf, return -EFAULT; do_cmd(BLA,data); + fpgafs_send_data(NULL, 1); return 4; } diff --git a/fpgafs.h b/fpgafs.h index 20d1480..8b39e8c 100644 --- a/fpgafs.h +++ b/fpgafs.h @@ -1,3 +1,6 @@ +/********************************************* + * Benjamin Krill + *********************************************/ #ifndef FPGAFS_H #define FPGAFS_H @@ -26,6 +29,25 @@ extern struct tree_descr fpgafs_dir_contents[]; #define FPGAFS_I(inode) \ container_of(inode, struct fpgafs_inode_info, vfs_inode) + +/* command definitions */ #define BLA 0 +/* low level driver */ +struct fpgafs_lldrv { + char name[5]; + + int (*init) (void); + int (*exit) (void); + + int (*send) (unsigned char *buf, int len); + int (*recv) (unsigned char *buf, int len); +}; + +int fpgafs_register_lldrv(struct fpgafs_lldrv *drv); +int fpgafs_unregister_lldrv(struct fpgafs_lldrv *drv); + +int fpgafs_send_data(char *buf, int len); +int fpgafs_recv_data(char *buf, int len); + #endif /* FPGAFS_H */ diff --git a/fpgafs_lldrv_cham.c b/fpgafs_lldrv_cham.c new file mode 100644 index 0000000..19e87c2 --- /dev/null +++ b/fpgafs_lldrv_cham.c @@ -0,0 +1,44 @@ +/********************************************* + * Benjamin Krill + *********************************************/ +#include +#include +#include +#include "fpgafs.h" + +static int fpgafs_send_data_cham(unsigned char *buf, int len) +{ + printk("fpgafs: send data CHAM\n"); + return 0; +} + +static int fpgafs_recv_data_cham(unsigned char *buf, int len) +{ + printk("fpgafs: receive data CHAM\n"); + return 4; +} + +static struct fpgafs_lldrv fpgafs_lldrv_cham = { + .name = "cham", + .init = NULL, + .exit = NULL, + .send = &fpgafs_send_data_cham, + .recv = &fpgafs_recv_data_cham +}; + +/* init exit functions ... */ +int __init fpgafs_lldrv_cham_init(void) +{ + return fpgafs_register_lldrv(&fpgafs_lldrv_cham); +} + +void __exit fpgafs_lldrv_cham_exit(void) +{ + fpgafs_unregister_lldrv(&fpgafs_lldrv_cham); +} + +module_init(fpgafs_lldrv_cham_init); +module_exit(fpgafs_lldrv_cham_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Benjamin Krill "); diff --git a/fpgafs_lldrv_dbg.c b/fpgafs_lldrv_dbg.c new file mode 100644 index 0000000..8d437cc --- /dev/null +++ b/fpgafs_lldrv_dbg.c @@ -0,0 +1,44 @@ +/********************************************* + * Benjamin Krill + *********************************************/ +#include +#include +#include +#include "fpgafs.h" + +static int fpgafs_send_data_dbg(unsigned char *buf, int len) +{ + printk("fpgafs: send data CHAM\n"); + return 0; +} + +static int fpgafs_recv_data_dbg(unsigned char *buf, int len) +{ + printk("fpgafs: receive data CHAM\n"); + return 4; +} + +static struct fpgafs_lldrv fpgafs_lldrv_dbg = { + .name = "dbg", + .init = NULL, + .exit = NULL, + .send = &fpgafs_send_data_dbg, + .recv = &fpgafs_recv_data_dbg +}; + +/* init exit functions ... */ +int __init fpgafs_lldrv_dbg_init(void) +{ + return fpgafs_register_lldrv(&fpgafs_lldrv_dbg); +} + +void __exit fpgafs_lldrv_dbg_exit(void) +{ + fpgafs_unregister_lldrv(&fpgafs_lldrv_dbg); +} + +module_init(fpgafs_lldrv_dbg_init); +module_exit(fpgafs_lldrv_dbg_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Benjamin Krill "); diff --git a/llmgmt.c b/llmgmt.c new file mode 100644 index 0000000..2369721 --- /dev/null +++ b/llmgmt.c @@ -0,0 +1,86 @@ +/********************************************* + * Benjamin Krill + *********************************************/ +#include +#include +#include +#include "fpgafs.h" + +#define FPGAFS_MAX_LLDRV 3 + +static struct fpgafs_lldrv *lldrv[FPGAFS_MAX_LLDRV]; +static struct fpgafs_lldrv *lldrv_cur; +static int lldrv_count = 0x0; +static DEFINE_SPINLOCK(fpgafs_lldrv_lock); + +int fpgafs_send_data(char *buf, int len) +{ + return (lldrv_cur)?lldrv_cur->send(buf, len) : -EBUSY; +} +EXPORT_SYMBOL_GPL(fpgafs_send_data); + +int fpgafs_recv_data(char *buf, int len) +{ + return (lldrv_cur) ? lldrv_cur->recv(buf, len) : -EBUSY; +} +EXPORT_SYMBOL_GPL(fpgafs_recv_data); + +int fpgafs_register_lldrv(struct fpgafs_lldrv *drv) +{ + unsigned long flags; + int i; + + spin_lock_irqsave(&fpgafs_lldrv_lock, flags); + if (lldrv_count == FPGAFS_MAX_LLDRV) + return -EBUSY; + + /* find free space */ + for(i=0; i < FPGAFS_MAX_LLDRV; i++) + if (lldrv[lldrv_count] == NULL) { + lldrv[lldrv_count] = drv; + break; + } + + if (lldrv[lldrv_count]->init) + lldrv[lldrv_count]->init(); + + lldrv_cur = lldrv[lldrv_count]; + + lldrv_count++; + + spin_unlock_irqrestore(&fpgafs_lldrv_lock, flags); + return 0; +} +EXPORT_SYMBOL_GPL(fpgafs_register_lldrv); + +int fpgafs_unregister_lldrv(struct fpgafs_lldrv *drv) +{ + unsigned long flags; + int i,k; + + spin_lock_irqsave(&fpgafs_lldrv_lock, flags); + + if (lldrv[lldrv_count]->exit) + lldrv[lldrv_count]->exit(); + + for(i=0; i < FPGAFS_MAX_LLDRV; i++) { + if (lldrv[i] == drv) { + lldrv[i] = NULL; + /* if current, search another low level driver */ + if (lldrv_cur == drv) { + for(k=0; k < FPGAFS_MAX_LLDRV; k++) + if (lldrv[k]) { + lldrv_cur = lldrv[k]; + break; + } + } + break; + } + } + + lldrv_count--; + + spin_unlock_irqrestore(&fpgafs_lldrv_lock, flags); + return 0; +} +EXPORT_SYMBOL_GPL(fpgafs_unregister_lldrv);