blob: b60027e8a213db2ab6ec4d18389e7a30bdbd0c75 [file] [log] [blame]
/*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.12
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#define __NO_VERSION__
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/poll.h>
#include <linux/fs.h>
#include <linux/slab.h>
#undef N_DATA
#include "adapter.h"
#include "divas.h"
#include "divalog.h"
extern int DivasCardNext;
void UxPause(long ms);
int DivasGetMem(mem_block_t *);
#define DIA_IOCTL_UNLOCK 12
void UnlockDivas(void);
int do_ioctl(struct inode *pDivasInode, struct file *pDivasFile,
unsigned int command, unsigned long arg)
{
byte *pUserCards, card_i;
word wCardNum;
switch (command)
{
case DIA_IOCTL_CONFIG:
{
dia_config_t DivaConfig;
if (copy_from_user(&DivaConfig, (void *)arg, sizeof(dia_config_t)))
return -EFAULT;
DivasCardConfig(&DivaConfig);
return 0;
}
case DIA_IOCTL_DETECT:
pUserCards = (byte *) arg;
if (!verify_area(VERIFY_WRITE, pUserCards, 20))
{
if(__put_user(DivasCardNext, pUserCards++))
return -EFAULT;
for (card_i=1; card_i < 20; card_i++)
{
if(__put_user((byte) DivasCards[card_i - 1].cfg.card_type, pUserCards++))
return -EFAULT;
}
}
else return -EFAULT;
return 0;
case DIA_IOCTL_START:
{
dia_start_t DivaStart;
if (copy_from_user(&DivaStart, (void *)arg, sizeof(dia_start_t)))
return -EFAULT;
return DivasCardStart(DivaStart.card_id);
}
case DIA_IOCTL_FLAVOUR:
return 0;
case DIA_IOCTL_LOAD:
{
dia_load_t DivaLoad;
if(copy_from_user(&DivaLoad, (void *)arg, sizeof(dia_load_t)))
return -EFAULT;
if (!verify_area(VERIFY_READ, DivaLoad.code,DivaLoad.length))
{
if (DivasCardLoad(&DivaLoad))
{
printk(KERN_WARNING "Divas: Error loading DIVA Server adapter\n");
return -EINVAL;
}
return 0;
}
return -EFAULT;
}
case DIA_IOCTL_LOG:
{
dia_log_t DivaLog;
if (copy_from_user(&DivaLog, (void *) arg, sizeof(dia_log_t)))
return -EFAULT;
DivasLog(&DivaLog);
return 0;
}
case DIA_IOCTL_XLOG_REQ:
if(get_user(wCardNum, (word *) arg))
return -EFAULT;
DivasXlogReq(wCardNum);
return 0;
case DIA_IOCTL_GET_NUM:
if(put_user(DivasCardNext, (int *)arg))
return -EFAULT;
return 0;
case DIA_IOCTL_GET_LIST:
{
dia_card_list_t cards;
DPRINTF(("divas: DIA_IOCTL_GET_LIST"));
DivasGetList(&cards);
if(copy_to_user((void *)arg, &cards, sizeof(cards)))
return -EFAULT;
return 0;
}
case DIA_IOCTL_GET_MEM:
{
mem_block_t mem_block;
if (copy_from_user(&mem_block, (void *)arg, sizeof(mem_block_t)))
return -EFAULT;
DivasGetMem(&mem_block);
return 0;
}
case DIA_IOCTL_UNLOCK:
UnlockDivas();
return 0;
default:
return -EINVAL;
}
return -EINVAL;
}
unsigned int do_poll(struct file *pFile, struct poll_table_struct *pPollTable)
{
word wMask = 0;
if (!DivasLogFifoEmpty())
wMask |= POLLIN | POLLRDNORM;
return wMask;
}
ssize_t do_read(struct file *pFile, char *pUserBuffer, size_t BufferSize, loff_t *pOffset)
{
klog_t *pClientLogBuffer = (klog_t *) pUserBuffer;
klog_t *pHeadItem;
if (BufferSize < sizeof(klog_t))
return -EIO;
pHeadItem = (klog_t *) DivasLogFifoRead();
if (pHeadItem)
{
if(copy_to_user(pClientLogBuffer, pHeadItem, sizeof(klog_t)))
{
kfree(pHeadItem);
return -EFAULT;
}
kfree(pHeadItem);
return sizeof(klog_t);
}
return 0;
}
static int private_usage_count;
int do_open(struct inode *pInode, struct file *pFile)
{
MOD_INC_USE_COUNT;
#ifdef MODULE
private_usage_count++;
#endif
return 0;
}
int do_release(struct inode *pInode, struct file *pFile)
{
MOD_DEC_USE_COUNT;
#ifdef MODULE
private_usage_count--;
#endif
return 0;
}
void UnlockDivas(void)
{
while (private_usage_count > 0)
{
private_usage_count--;
MOD_DEC_USE_COUNT;
}
}