#define DEV_TO_MOUSE(dev) MINOR_TO_MOUSE(MINOR(dev))
#define MINOR_TO_MOUSE(minor) ((minor) - FIRST_MOUSE)
+/*
+ * List of mice and guarding semaphore. You must take the semaphore
+ * before you take the misc device semaphore if you need both
+ */
+
static struct busmouse_data *busmouse_data[NR_MICE];
+static DECLARE_MUTEX(mouse_sem);
/* a mouse driver just has to interface with these functions
* These are !!!OLD!!! Do not use!!!
/* New interface. !!! Use this one !!!
* These routines will most probably be called from interrupt.
*/
-void
-busmouse_add_movementbuttons(int mousedev, int dx, int dy, int buttons)
+void busmouse_add_movementbuttons(int mousedev, int dx, int dy, int buttons)
{
struct busmouse_data *mse = busmouse_data[mousedev];
int changed;
}
}
-void
-busmouse_add_movement(int mousedev, int dx, int dy)
+void busmouse_add_movement(int mousedev, int dx, int dy)
{
struct busmouse_data *mse = busmouse_data[mousedev];
busmouse_add_movementbuttons(mousedev, dx, dy, mse->buttons);
}
-void
-busmouse_add_buttons(int mousedev, int clear, int eor)
+void busmouse_add_buttons(int mousedev, int clear, int eor)
{
struct busmouse_data *mse = busmouse_data[mousedev];
busmouse_add_movementbuttons(mousedev, 0, 0, (mse->buttons & ~clear) ^ eor);
}
-static int
-busmouse_fasync(int fd, struct file *filp, int on)
+static int busmouse_fasync(int fd, struct file *filp, int on)
{
struct busmouse_data *mse = (struct busmouse_data *)filp->private_data;
int retval;
return 0;
}
-static int
-busmouse_release(struct inode *inode, struct file *file)
+static int busmouse_release(struct inode *inode, struct file *file)
{
struct busmouse_data *mse = (struct busmouse_data *)file->private_data;
int ret = 0;
return ret;
}
-static int
-busmouse_open(struct inode *inode, struct file *file)
+static int busmouse_open(struct inode *inode, struct file *file)
{
struct busmouse_data *mse;
unsigned long flags;
unsigned int mousedev;
- int ret = 0;
+ int ret = -ENODEV;
mousedev = DEV_TO_MOUSE(inode->i_rdev);
if (mousedev >= NR_MICE)
return -EINVAL;
+
+ down(&mouse_sem);
mse = busmouse_data[mousedev];
if (!mse)
/* shouldn't happen, but... */
- return -ENODEV;
-
+ goto end;
+
if (mse->ops &&
mse->ops->open)
ret = mse->ops->open(inode, file);
if (ret)
- return ret;
+ goto end;
file->private_data = mse;
if (mse->active++)
- return 0;
+ goto end;
MOD_INC_USE_COUNT;
mse->buttons = 7;
spin_unlock_irqrestore(&mse->lock, flags);
-
- return 0;
+end:
+ up(&mouse_sem);
+ return ret;
}
-static ssize_t
-busmouse_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
+static ssize_t busmouse_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
{
return -EINVAL;
}
-static ssize_t
-busmouse_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
+static ssize_t busmouse_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
{
struct busmouse_data *mse = (struct busmouse_data *)file->private_data;
DECLARE_WAITQUEUE(wait, current);
return count;
}
-static unsigned int
-busmouse_poll(struct file *file, poll_table *wait)
+static unsigned int busmouse_poll(struct file *file, poll_table *wait)
{
struct busmouse_data *mse = (struct busmouse_data *)file->private_data;
fasync: busmouse_fasync,
};
-int
-register_busmouse(struct busmouse *ops)
+/**
+ * register_busmouse - register a bus mouse interface
+ * @ops: busmouse structure for the mouse
+ *
+ * Registers a mouse with the driver. The return is mouse number on
+ * success and a negative errno code on an error. The passed ops
+ * structure most not be freed until the mouser is unregistered
+ */
+
+int register_busmouse(struct busmouse *ops)
{
unsigned int msedev = MINOR_TO_MOUSE(ops->minor);
struct busmouse_data *mse;
return -EINVAL;
}
- if (busmouse_data[msedev])
- return -EBUSY;
-
mse = kmalloc(sizeof(*mse), GFP_KERNEL);
if (!mse)
return -ENOMEM;
+ down(&mouse_sem);
+ if (busmouse_data[msedev])
+ {
+ up(&mouse_sem);
+ kfree(mse);
+ return -EBUSY;
+ }
+
memset(mse, 0, sizeof(*mse));
mse->miscdev.minor = ops->minor;
ret = misc_register(&mse->miscdev);
if (!ret)
ret = msedev;
-
+ up(&mouse_sem);
+
return ret;
}
-int
-unregister_busmouse(int mousedev)
+/**
+ * unregister_busmouse - unregister a bus mouse interface
+ * @mousedev: Mouse number to release
+ *
+ * Unregister a previously installed mouse handler. The mousedev
+ * passed is the return code from a previous call to register_busmouse
+ */
+
+
+int unregister_busmouse(int mousedev)
{
+ int err = -EINVAL;
if (mousedev < 0)
return 0;
if (mousedev >= NR_MICE) {
return -EINVAL;
}
+ down(&mouse_sem);
+
if (!busmouse_data[mousedev]) {
printk(KERN_WARNING "busmouse: trying to free free mouse"
" on mousedev %d\n", mousedev);
- return -EINVAL;
+ goto fail;
}
if (busmouse_data[mousedev]->active) {
printk(KERN_ERR "busmouse: trying to free active mouse"
" on mousedev %d\n", mousedev);
- return -EINVAL;
+ goto fail;
}
- misc_deregister(&busmouse_data[mousedev]->miscdev);
+ err=misc_deregister(&busmouse_data[mousedev]->miscdev);
kfree(busmouse_data[mousedev]);
busmouse_data[mousedev] = NULL;
- return 0;
+fail:
+ up(&mouse_sem);
+ return err;
}
-int __init
-bus_mouse_init(void)
+int __init bus_mouse_init(void)
{
#ifdef CONFIG_SUN_MOUSE
sun_mouse_init();
EXPORT_SYMBOL(unregister_busmouse);
#ifdef MODULE
-int
-init_module(void)
+int init_module(void)
{
return bus_mouse_init();
}
-void
-cleanup_module(void)
+void cleanup_module(void)
{
}
#endif
* Head entry for the doubly linked miscdevice list
*/
static struct miscdevice misc_list = { 0, "head", NULL, &misc_list, &misc_list };
+static DECLARE_MUTEX(misc_sem);
/*
* Assigned numbers, used for dynamic minors
static int misc_open(struct inode * inode, struct file * file)
{
int minor = MINOR(inode->i_rdev);
- struct miscdevice *c = misc_list.next;
+ struct miscdevice *c;
+ int err = -ENODEV;
+
file->f_op = NULL;
+
+ down(&misc_sem);
+
+ c = misc_list.next;
while ((c != &misc_list) && (c->minor != minor))
c = c->next;
if (c == &misc_list) {
char modname[20];
+ up(&misc_sem);
sprintf(modname, "char-major-%d-%d", MISC_MAJOR, minor);
request_module(modname);
+ down(&misc_sem);
c = misc_list.next;
while ((c != &misc_list) && (c->minor != minor))
c = c->next;
if (c == &misc_list)
- return -ENODEV;
+ goto fail;
}
if ((file->f_op = c->fops) && file->f_op->open)
- return file->f_op->open(inode,file);
- else
- return -ENODEV;
+ err=file->f_op->open(inode,file);
+fail:
+ up(&misc_sem);
+ return err;
}
static struct file_operations misc_fops = {
open: misc_open,
};
+
/**
* misc_register - register a miscellaneous device
* @misc: device structure
if (misc->next || misc->prev)
return -EBUSY;
+ down(&misc_sem);
if (misc->minor == MISC_DYNAMIC_MINOR) {
int i = DYNAMIC_MINORS;
while (--i >= 0)
if ( (misc_minors[i>>3] & (1 << (i&7))) == 0)
break;
- if (i<0) return -EBUSY;
+ if (i<0)
+ {
+ up(&misc_sem);
+ return -EBUSY;
+ }
misc->minor = i;
}
if (misc->minor < DYNAMIC_MINORS)
misc->next = misc_list.next;
misc->prev->next = misc;
misc->next->prev = misc;
+ up(&misc_sem);
return 0;
}
int i = misc->minor;
if (!misc->next || !misc->prev)
return -EINVAL;
+ down(&misc_sem);
misc->prev->next = misc->next;
misc->next->prev = misc->prev;
misc->next = NULL;
if (i < DYNAMIC_MINORS && i>0) {
misc_minors[i>>3] &= ~(1 << (misc->minor & 7));
}
+ up(&misc_sem);
return 0;
}
EXPORT_SYMBOL(locks_mandatory_area);
EXPORT_SYMBOL(dput);
EXPORT_SYMBOL(is_root_busy);
+EXPORT_SYMBOL(have_submounts);
EXPORT_SYMBOL(prune_dcache);
EXPORT_SYMBOL(shrink_dcache_sb);
EXPORT_SYMBOL(shrink_dcache_parent);
EXPORT_SYMBOL(proc_doulongvec_minmax);
/* interrupt handling */
+EXPORT_SYMBOL(add_timer);
+EXPORT_SYMBOL(del_timer);
EXPORT_SYMBOL(request_irq);
EXPORT_SYMBOL(free_irq);
+
+/* The notion of irq probe/assignment is foreign to S/390 */
+
+#if !defined(CONFIG_ARCH_S390)
EXPORT_SYMBOL(probe_irq_on);
EXPORT_SYMBOL(probe_irq_off);
-EXPORT_SYMBOL(add_timer);
-EXPORT_SYMBOL(del_timer);
+EXPORT_SYMBOL(autoirq_setup);
+EXPORT_SYMBOL(autoirq_report);
+#endif
+
#ifdef __SMP__
EXPORT_SYMBOL(del_timer_sync);
#endif
EXPORT_SYMBOL(unlock_kiovec);
EXPORT_SYMBOL(brw_kiovec);
-/* autoirq from drivers/net/auto_irq.c */
-EXPORT_SYMBOL(autoirq_setup);
-EXPORT_SYMBOL(autoirq_report);
-
/* dma handling */
EXPORT_SYMBOL(request_dma);
EXPORT_SYMBOL(free_dma);