-/* $Id: divamnt.c,v 1.32 2004/01/15 09:48:13 armin Exp $
+/* $Id: divamnt.c,v 1.32.6.10 2005/02/11 19:40:25 armin Exp $
*
* Driver for Eicon DIVA Server ISDN cards.
* Maint module
* of the GNU General Public License, incorporated herein by reference.
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/smp_lock.h>
#include <linux/poll.h>
-#include <linux/proc_fs.h>
-#include <linux/skbuff.h>
-#include <linux/devfs_fs_kernel.h>
+#include <asm/uaccess.h>
#include "platform.h"
#include "di_defs.h"
#include "divasync.h"
#include "debug_if.h"
-static char *main_revision = "$Revision: 1.32 $";
+static char *main_revision = "$Revision: 1.32.6.10 $";
static int major;
MODULE_SUPPORTED_DEVICE("DIVA card driver");
MODULE_LICENSE("GPL");
-int buffer_length = 128;
-MODULE_PARM(buffer_length, "i");
-unsigned long diva_dbg_mem = 0;
-MODULE_PARM(diva_dbg_mem, "l");
+static int buffer_length = 128;
+module_param(buffer_length, int, 0);
+static unsigned long diva_dbg_mem = 0;
+module_param(diva_dbg_mem, ulong, 0);
static char *DRIVERNAME =
"Eicon DIVA - MAINT module (http://www.melware.net)";
char *DRIVERRELEASE_MNT = "2.0";
static wait_queue_head_t msgwaitq;
-static DECLARE_MUTEX(opened_sem);
-static int opened;
+static unsigned long opened;
static struct timeval start_time;
extern int mntfunc_init(int *, void **, unsigned long);
return rev;
}
-/*
- * buffer alloc
- */
-void *diva_os_malloc_tbuffer(unsigned long flags, unsigned long size)
-{
- return (kmalloc(size, GFP_KERNEL));
-}
-void diva_os_free_tbuffer(unsigned long flags, void *ptr)
-{
- if (ptr) {
- kfree(ptr);
- }
-}
-
/*
* kernel/user space copy functions
*/
}
/*
- * /proc entries
+ * device node operations
*/
-
-extern struct proc_dir_entry *proc_net_eicon;
-static struct proc_dir_entry *maint_proc_entry = NULL;
-
-/*
- Read function is provided for compatibility reason - this allows
- to read unstructured traces, formated as ascii string only
- */
-static ssize_t
-maint_read(struct file *file, char __user *buf, size_t count, loff_t * off)
-{
- diva_dbg_entry_head_t *pmsg = NULL;
- diva_os_spin_lock_magic_t old_irql;
- word size;
- char *pstr, *dli_label = "UNK";
- int str_length;
- int *str_msg;
-
- if (off != &file->f_pos)
- return -ESPIPE;
-
- if (!file->private_data) {
- for (;;) {
- while (
- (pmsg =
- diva_maint_get_message(&size,
- &old_irql))) {
- if (!(pmsg->facility == MSG_TYPE_STRING)) {
- diva_maint_ack_message(1,
- &old_irql);
- } else {
- break;
- }
- }
-
- if (!pmsg) {
- if (file->f_flags & O_NONBLOCK) {
- return (-EAGAIN);
- }
- interruptible_sleep_on(&msgwaitq);
- if (signal_pending(current)) {
- return (-ERESTARTSYS);
- }
- } else {
- break;
- }
- }
- /*
- The length of message that shoule be read is:
- pmsg->data_length + label(25) + DrvID(2) + byte CR + trailing zero
- */
- if (!
- (str_msg =
- (int *) diva_os_malloc_tbuffer(0,
- pmsg->data_length +
- 29 + 2 * sizeof(int)))) {
- diva_maint_ack_message(0, &old_irql);
- return (-ENOMEM);
- }
- pstr = (char *) &str_msg[2];
-
- switch (pmsg->dli) {
- case DLI_LOG:
- dli_label = "LOG";
- break;
- case DLI_FTL:
- dli_label = "FTL";
- break;
- case DLI_ERR:
- dli_label = "ERR";
- break;
- case DLI_TRC:
- dli_label = "TRC";
- break;
- case DLI_REG:
- dli_label = "REG";
- break;
- case DLI_MEM:
- dli_label = "MEM";
- break;
- case DLI_SPL:
- dli_label = "SPL";
- break;
- case DLI_IRP:
- dli_label = "IRP";
- break;
- case DLI_TIM:
- dli_label = "TIM";
- break;
- case DLI_TAPI:
- dli_label = "TAPI";
- break;
- case DLI_NDIS:
- dli_label = "NDIS";
- break;
- case DLI_CONN:
- dli_label = "CONN";
- break;
- case DLI_STAT:
- dli_label = "STAT";
- break;
- case DLI_PRV0:
- dli_label = "PRV0";
- break;
- case DLI_PRV1:
- dli_label = "PRV1";
- break;
- case DLI_PRV2:
- dli_label = "PRV2";
- break;
- case DLI_PRV3:
- dli_label = "PRV3";
- break;
- }
- str_length = sprintf(pstr, "%s %02x %s\n",
- dli_label, (byte) pmsg->drv_id,
- (char *) &pmsg[1]);
- str_msg[0] = str_length;
- str_msg[1] = 0;
- file->private_data = str_msg;
- diva_maint_ack_message(1, &old_irql);
- } else {
- str_msg = (int *) file->private_data;
- pstr = (char *) &str_msg[2];
- pstr += str_msg[1]; /* head + offset */
- str_length = str_msg[0] - str_msg[1]; /* length - offset */
- }
- str_length = MIN(str_length, count);
-
- if (diva_os_copy_to_user(NULL, buf, pstr, str_length)) {
- diva_os_free_tbuffer(0, str_msg);
- file->private_data = NULL;
- return (-EFAULT);
- }
- str_msg[1] += str_length;
- if ((str_msg[0] - str_msg[1]) <= 0) {
- diva_os_free_tbuffer(0, str_msg);
- file->private_data = NULL;
- }
-
- return (str_length);
-}
-
-static ssize_t
-maint_write(struct file *file, const char __user *buf, size_t count, loff_t * off)
-{
- return (-ENODEV);
-}
-
static unsigned int maint_poll(struct file *file, poll_table * wait)
{
unsigned int mask = 0;
static int maint_open(struct inode *ino, struct file *filep)
{
- down(&opened_sem);
- if (opened) {
- up(&opened_sem);
+ /* only one open is allowed, so we test
+ it atomically */
+ if (test_and_set_bit(0, &opened))
return (-EBUSY);
- }
- opened++;
- up(&opened_sem);
filep->private_data = NULL;
- return (0);
+ return nonseekable_open(ino, filep);
}
static int maint_close(struct inode *ino, struct file *filep)
{
if (filep->private_data) {
- diva_os_free_tbuffer(0, filep->private_data);
+ diva_os_free(0, filep->private_data);
filep->private_data = NULL;
}
- down(&opened_sem);
- opened--;
- up(&opened_sem);
+ /* clear 'used' flag */
+ clear_bit(0, &opened);
+
return (0);
}
-/*
- * fops
- */
-static struct file_operations maint_fops = {
- .owner = THIS_MODULE,
- .llseek = no_llseek,
- .read = maint_read,
- .write = maint_write,
- .poll = maint_poll,
- .open = maint_open,
- .release = maint_close
-};
-
-static int DIVA_INIT_FUNCTION create_maint_proc(void)
-{
- maint_proc_entry =
- create_proc_entry("maint", S_IFREG | S_IRUGO | S_IWUSR,
- proc_net_eicon);
- if (!maint_proc_entry)
- return (0);
-
- maint_proc_entry->proc_fops = &maint_fops;
- maint_proc_entry->owner = THIS_MODULE;
-
- return (1);
-}
-
-static void remove_maint_proc(void)
-{
- if (maint_proc_entry) {
- remove_proc_entry("maint", proc_net_eicon);
- maint_proc_entry = NULL;
- }
-}
-
-/*
- * device node operations
- */
static ssize_t divas_maint_write(struct file *file, const char __user *buf,
size_t count, loff_t * ppos)
{
static void divas_maint_unregister_chrdev(void)
{
- devfs_remove(DEVNAME);
unregister_chrdev(major, DEVNAME);
}
DRIVERLNAME);
return (0);
}
- devfs_mk_cdev(MKDEV(major, 0), S_IFCHR|S_IRUSR|S_IWUSR, DEVNAME);
return (1);
}
ret = -EIO;
goto out;
}
- if (!create_maint_proc()) {
- printk(KERN_ERR "%s: failed to create proc entry.\n",
- DRIVERLNAME);
- divas_maint_unregister_chrdev();
- ret = -EIO;
- goto out;
- }
if (!(mntfunc_init(&buffer_length, &buffer, diva_dbg_mem))) {
printk(KERN_ERR "%s: failed to connect to DIDD.\n",
DRIVERLNAME);
- remove_maint_proc();
divas_maint_unregister_chrdev();
ret = -EIO;
goto out;
*/
static void DIVA_EXIT_FUNCTION maint_exit(void)
{
- remove_maint_proc();
divas_maint_unregister_chrdev();
mntfunc_finit();
module_init(maint_init);
module_exit(maint_exit);
+