fpgafs/llmgmt.c

106 lines
2.3 KiB
C

/*********************************************
* 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);
ssize_t fpgafs_send_data(struct file *file, char __user *buf,
size_t len, loff_t *pos)
{
return (lldrv_cur) ? lldrv_cur->send(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(buf, len) : -EBUSY;
}
EXPORT_SYMBOL_GPL(fpgafs_recv_data);
int fpgafs_write_load(char *buf, int len)
{
return (lldrv_cur) ? lldrv_cur->write_load(buf, len) : -EBUSY;
}
EXPORT_SYMBOL_GPL(fpgafs_write_load);
int fpgafs_read_load(char *buf, int len)
{
return (lldrv_cur) ? lldrv_cur->read_load(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);