fpgafs/llmgmt.c
ben c41ddd323f fix the fucking unload issue
git-svn-id: svn+ssh://en.codiert.org/home/staff/ben/dev/misc.svn/projects/fpgafs@353 766a2236-cff9-0310-b0c0-a81a5f92509a
2007-07-09 07:19:12 +00:00

91 lines
1.9 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);
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);
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);