diff --git a/files.c b/files.c index 52eaac1..be6306e 100644 --- a/files.c +++ b/files.c @@ -45,11 +45,6 @@ static ssize_t fpgafs_stat_read(struct file *file, char __user *buf, return 4; } -static const struct file_operations fpgafs_stat_fops = { - .open = fpgafs_open, - .read = fpgafs_stat_read, -}; - static ssize_t fpgafs_cmd_write(struct file *file, const char __user *buf, size_t len, loff_t *pos) { @@ -69,6 +64,11 @@ static ssize_t fpgafs_cmd_write(struct file *file, const char __user *buf, return 4; } +static const struct file_operations fpgafs_stat_fops = { + .open = fpgafs_open, + .read = fpgafs_stat_read, +}; + static const struct file_operations fpgafs_cmd_fops = { .open = fpgafs_open, .write = fpgafs_cmd_write, @@ -90,11 +90,18 @@ static const struct file_operations fpgafs_dout_fops = { .write = fpgafs_send_data, }; +static const struct file_operations fpgafs_lldrv_fops = { + .open = fpgafs_open, + .write = fpgafs_write_lldrv, + .read = fpgafs_read_lldrv, +}; + struct tree_descr fpgafs_dir_contents[] = { { "din", &fpgafs_din_fops, 0222, }, { "dout", &fpgafs_dout_fops, 0444, }, { "load", &fpgafs_load_fops, 0666, }, { "cmd", &fpgafs_cmd_fops, 0222, }, { "stat", &fpgafs_stat_fops, 0444, }, + { "lldrv", &fpgafs_lldrv_fops, 0444, }, {}, }; diff --git a/fpgafs.h b/fpgafs.h index 9768e9a..f42a924 100644 --- a/fpgafs.h +++ b/fpgafs.h @@ -16,7 +16,7 @@ enum { struct fpga_context { char *load_buf; - unsigned intlldrv; + unsigned int lldrv; int bla; }; @@ -61,6 +61,11 @@ ssize_t fpgafs_write_load(struct file *file, const char __user *buf, ssize_t fpgafs_read_load(struct file *file, char __user *buf, size_t len, loff_t *pos); +ssize_t fpgafs_write_lldrv(struct file *file, const char __user *buf, + size_t len, loff_t *pos); +ssize_t fpgafs_read_lldrv(struct file *file, char __user *buf, + size_t len, loff_t *pos); + struct fpga_context* alloc_fpga_context(void); void free_fpga_context(struct fpga_context *ctx); #endif /* FPGAFS_H */ diff --git a/fpgafs_lldrv_rag.c b/fpgafs_lldrv_rag.c index ae281f5..a2339e7 100644 --- a/fpgafs_lldrv_rag.c +++ b/fpgafs_lldrv_rag.c @@ -1,10 +1,12 @@ /********************************************* * Benjamin Krill *********************************************/ +#include #include #include #include #include +#include #include "fpgafs.h" #define VENDOR_ID_ALTERA 0x1172 @@ -14,24 +16,49 @@ static void *vaddr = 0; static unsigned long memstart = 0, memlen = 0; -/* len must 2 or higher ... */ static int fpgafs_send_data_rag(struct fpga_context *ctx, const char __user *buf, int len) { int i; - for(i=0; i < len; i+=2) - writew((buf[i+1] << 8)|buf[i], vaddr); + u8 __user *usr; + unsigned char dat[2]; + + if (len < 2) + return -EINVAL; + + if (!access_ok(VERIFY_READ, buf, len)) + return -EFAULT; + + for(i=0; i < len; i+=2) { + usr = (u8*)&buf[i]; + if (__get_user(dat[0], usr)) + return -EFAULT; + + usr = (u8*)&buf[i+1]; + if (__get_user(dat[1], usr)) + return -EFAULT; + + writew((dat[1] << 8)|dat[0], vaddr); + } + return i; } -/* len must 2 or higher ... */ static int fpgafs_recv_data_rag(struct fpga_context *ctx, unsigned char *buf, int len) { int i; unsigned short d; + unsigned char b[2]; + + if ((len < 2) || ((len % 2) != 0)) + return -EINVAL; + for(i=0; i < len; i+=2) { d=readw((void *)((unsigned int)vaddr | 0x20)); - buf[i] = d & 0xff; - buf[i+1] = d >> 8; + b[i] = d & 0xff; + b[i+1] = d >> 8; + if (copy_to_user(b, ctx->load_buf, 2)) + return -EFAULT; } + return i; } diff --git a/llmgmt.c b/llmgmt.c index 7cd191b..a47a66f 100644 --- a/llmgmt.c +++ b/llmgmt.c @@ -1,9 +1,11 @@ /********************************************* * Benjamin Krill *********************************************/ +#include #include #include #include +#include #include "fpgafs.h" #define FPGAFS_MAX_LLDRV 3 @@ -20,7 +22,8 @@ struct fpga_context* alloc_fpga_context(void) if (!ctx) goto out; - /* do some stuff */ + /* initialize the struct*/ + ctx->lldrv = -1; out: return ctx; @@ -38,8 +41,9 @@ void free_fpga_context(struct fpga_context *ctx) ssize_t fpgafs_send_data(struct file *file, const char __user *buf, size_t len, loff_t *pos) { - return (lldrv_cur) ? - lldrv_cur->send((struct fpga_context*)file->private_data, buf, len) + struct fpga_context *fcur = (struct fpga_context*)file->private_data; + return (fcur->lldrv > -1) ? + lldrv[fcur->lldrv]->send(fcur, buf, len) : -EBUSY; } EXPORT_SYMBOL_GPL(fpgafs_send_data); @@ -47,8 +51,9 @@ EXPORT_SYMBOL_GPL(fpgafs_send_data); ssize_t fpgafs_recv_data(struct file *file, char __user *buf, size_t len, loff_t *pos) { - return (lldrv_cur) ? - lldrv_cur->recv((struct fpga_context*)file->private_data, buf, len) + struct fpga_context *fcur = (struct fpga_context*)file->private_data; + return (fcur->lldrv > -1) ? + lldrv[fcur->lldrv]->recv(fcur, buf, len) : -EBUSY; } EXPORT_SYMBOL_GPL(fpgafs_recv_data); @@ -56,8 +61,9 @@ EXPORT_SYMBOL_GPL(fpgafs_recv_data); ssize_t fpgafs_write_load(struct file *file, const char __user *buf, size_t len, loff_t *pos) { - return (lldrv_cur) ? - lldrv_cur->write_load((struct fpga_context*)file->private_data, buf, len) + struct fpga_context *fcur = (struct fpga_context*)file->private_data; + return (fcur->lldrv > -1) ? + lldrv[fcur->lldrv]->write_load(fcur, buf, len) : -EBUSY; } EXPORT_SYMBOL_GPL(fpgafs_write_load); @@ -65,12 +71,63 @@ EXPORT_SYMBOL_GPL(fpgafs_write_load); ssize_t fpgafs_read_load(struct file *file, char __user *buf, size_t len, loff_t *pos) { - return (lldrv_cur) ? - lldrv_cur->read_load((struct fpga_context*)file->private_data, buf, len) + struct fpga_context *fcur = (struct fpga_context*)file->private_data; + return (fcur->lldrv > -1) ? + lldrv[fcur->lldrv]->read_load(fcur, buf, len) : -EBUSY; } EXPORT_SYMBOL_GPL(fpgafs_read_load); +/* set/get current low level driver */ +ssize_t fpgafs_read_lldrv(struct file *file, char __user *buf, + size_t len, loff_t *pos) +{ + struct fpga_context *fcur = (struct fpga_context*)file->private_data; + size_t l = (len > 5)?5:len; + if (fcur->lldrv > -1) { + if (copy_to_user(buf, lldrv[fcur->lldrv]->name, l)) + return -EFAULT; + } else { + return -EBUSY; + } + return l; +} +EXPORT_SYMBOL_GPL(fpgafs_read_lldrv); + +ssize_t fpgafs_write_lldrv(struct file *file, const char __user *buf, + size_t len, loff_t *pos) +{ + struct fpga_context *fcur = (struct fpga_context*)file->private_data; + u32 cp = 0, i; + u8 __user *usr; + unsigned char tmp[5]; + size_t l = (len > 5)?5:len; + + /* get name */ + while (cp < l) { + usr = (u8*)&buf[cp]; + if (__get_user(tmp[cp], usr)) + return -EFAULT; + cp++; + } + + for(i=0; i < FPGAFS_MAX_LLDRV; i++) + if (lldrv[i] != NULL) { + for (cp = 0; cp < l; cp++) { + if (lldrv[i]->name[cp] != tmp[cp]) + break; + } + if (cp == l) { + fcur->lldrv = i; + return l; + } + } + + fcur->lldrv = -1; + return -1; +} +EXPORT_SYMBOL_GPL(fpgafs_write_lldrv); + /* low level un-/register functions */ int fpgafs_register_lldrv(struct fpgafs_lldrv *drv) { @@ -83,15 +140,15 @@ int fpgafs_register_lldrv(struct fpgafs_lldrv *drv) /* find free space */ for(i=0; i < FPGAFS_MAX_LLDRV; i++) - if (lldrv[lldrv_count] == NULL) { - lldrv[lldrv_count] = drv; + if (lldrv[i] == NULL) { + lldrv[i] = drv; break; } - if (lldrv[lldrv_count]->init) - lldrv[lldrv_count]->init(); + if (lldrv[i]->init) + lldrv[i]->init(); - lldrv_cur = lldrv[lldrv_count]; + lldrv_cur = lldrv[i]; lldrv_count++;