fpgafs/llmgmt.c

138 lines
3.0 KiB
C
Raw Normal View History

/*********************************************
* Benjamin Krill <ben@codiert.org>
*********************************************/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#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);