/********************************************* * 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); struct fpga_context* alloc_fpga_context(void) { struct fpga_context *ctx; ctx = kzalloc(sizeof *ctx, GFP_KERNEL); if (!ctx) goto out; /* do some stuff */ out: return ctx; } void free_fpga_context(struct fpga_context *ctx) { if (ctx->load_buf) kfree(ctx->load_buf); kfree(ctx); return; } 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) : -EBUSY; } 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) : -EBUSY; } 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) : -EBUSY; } 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) : -EBUSY; } EXPORT_SYMBOL_GPL(fpgafs_read_load); /* low level un-/register functions */ 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); for(i=0; i < FPGAFS_MAX_LLDRV; i++) { if (lldrv[i] == drv) { /* call the exit function */ if (lldrv[i]->exit) lldrv[i]->exit(); lldrv[i] = NULL; /* if current, search another low level driver */ if (lldrv_cur == drv) { lldrv_cur = NULL; 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);