root/drivers/char/misc.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. proc_misc_read
  2. misc_open
  3. misc_register
  4. misc_deregister
  5. cleanup_module
  6. misc_init

   1 /*
   2  * linux/drivers/char/misc.c
   3  *
   4  * Generic misc open routine by Johan Myreen
   5  *
   6  * Based on code from Linus
   7  *
   8  * Teemu Rantanen's Microsoft Busmouse support and Derrick Cole's
   9  *   changes incorporated into 0.97pl4
  10  *   by Peter Cervasio (pete%q106fm.uucp@wupost.wustl.edu) (08SEP92)
  11  *   See busmouse.c for particulars.
  12  *
  13  * Made things a lot mode modular - easy to compile in just one or two
  14  * of the misc drivers, as they are now completely independent. Linus.
  15  *
  16  * Support for loadable modules. 8-Sep-95 Philip Blundell <pjb27@cam.ac.uk>
  17  *
  18  * Fixed a failing symbol register to free the device registration
  19  *              Alan Cox <alan@lxorguk.ukuu.org.uk> 21-Jan-96
  20  *
  21  * Dynamic minors and /proc/mice by Alessandro Rubini. 26-Mar-96
  22  *
  23  * Renamed to misc and miscdevice to be more accurate. Alan Cox 26-Mar-96
  24  *
  25  * Handling of mouse minor numbers for kerneld:
  26  *  Idea by Jacques Gelinas <jack@solucorp.qc.ca>,
  27  *  adapted by Bjorn Ekwall <bj0rn@blox.se>
  28  *  corrected by Alan Cox <alan@lxorguk.ukuu.org.uk>
  29  */
  30 
  31 #include <linux/config.h>
  32 #include <linux/module.h>
  33 
  34 #include <linux/fs.h>
  35 #include <linux/errno.h>
  36 #include <linux/miscdevice.h>
  37 #include <linux/kernel.h>
  38 #include <linux/major.h>
  39 #include <linux/malloc.h>
  40 #include <linux/proc_fs.h>
  41 #include <linux/stat.h>
  42 
  43 #include <linux/tty.h> /* needed by selection.h */
  44 #include "selection.h" /* export its symbols */
  45 #ifdef CONFIG_KERNELD
  46 #include <linux/kerneld.h>
  47 #endif
  48 
  49 /*
  50  * Head entry for the doubly linked miscdevice list
  51  */
  52 static struct miscdevice misc_list = { 0, "head", NULL, &misc_list, &misc_list };
  53 
  54 /*
  55  * Assigned numbers, used for dynamic minors
  56  */
  57 #define DYNAMIC_MINORS 64 /* like dynamic majors */
  58 static unsigned char misc_minors[DYNAMIC_MINORS / 8];
  59 
  60 #ifndef MODULE
  61 extern int bus_mouse_init(void);
  62 extern int psaux_init(void);
  63 extern int ms_bus_mouse_init(void);
  64 extern int atixl_busmouse_init(void);
  65 extern void watchdog_init(void);
  66 
  67 #ifdef CONFIG_PROC_FS
  68 static int proc_misc_read(char *buf, char **start, off_t offset, int len, int unused)
     /* [previous][next][first][last][top][bottom][index][help] */
  69 {
  70         struct miscdevice *p;
  71 
  72         len=0;
  73         for (p = misc_list.next; p != &misc_list; p = p->next)
  74                 len += sprintf(buf+len, "%3i %s\n",p->minor, p->name ?: "");
  75         return len;
  76 }
  77 
  78 #endif /* PROC_FS */
  79 #endif /* !MODULE */
  80 
  81 static int misc_open(struct inode * inode, struct file * file)
     /* [previous][next][first][last][top][bottom][index][help] */
  82 {
  83         int minor = MINOR(inode->i_rdev);
  84         struct miscdevice *c = misc_list.next;
  85         file->f_op = NULL;
  86 
  87         while ((c != &misc_list) && (c->minor != minor))
  88                 c = c->next;
  89         if (c == &misc_list) {
  90 #ifdef CONFIG_KERNELD
  91                 char modname[20];
  92                 sprintf(modname, "char-major-%d-%d", MISC_MAJOR, minor);
  93                 request_module(modname);
  94                 c = misc_list.next;
  95                 while ((c != &misc_list) && (c->minor != minor))
  96                         c = c->next;
  97                 if (c == &misc_list)
  98 #endif
  99                         return -ENODEV;
 100         }
 101 
 102         if ((file->f_op = c->fops))
 103                 return file->f_op->open(inode,file);
 104         else
 105                 return -ENODEV;
 106 }
 107 
 108 static struct file_operations misc_fops = {
 109         NULL,           /* seek */
 110         NULL,           /* read */
 111         NULL,           /* write */
 112         NULL,           /* readdir */
 113         NULL,           /* select */
 114         NULL,           /* ioctl */
 115         NULL,           /* mmap */
 116         misc_open,
 117         NULL            /* release */
 118 };
 119 
 120 int misc_register(struct miscdevice * misc)
     /* [previous][next][first][last][top][bottom][index][help] */
 121 {
 122         if (misc->next || misc->prev)
 123                 return -EBUSY;
 124         if (misc->minor == MISC_DYNAMIC_MINOR) {
 125                 int i = DYNAMIC_MINORS;
 126                 while (--i >= 0)
 127                         if ( (misc_minors[i>>3] & (1 << (i&7))) == 0)
 128                                 break;
 129                 if (i<0) return -EBUSY;
 130                 misc->minor = i;
 131         }
 132         if (misc->minor < DYNAMIC_MINORS)
 133                 misc_minors[misc->minor >> 3] |= 1 << (misc->minor & 7);
 134         MOD_INC_USE_COUNT;
 135         misc->next = &misc_list;
 136         misc->prev = misc_list.prev;
 137         misc->prev->next = misc;
 138         misc->next->prev = misc;
 139         return 0;
 140 }
 141 
 142 int misc_deregister(struct miscdevice * misc)
     /* [previous][next][first][last][top][bottom][index][help] */
 143 {
 144         int i = misc->minor;
 145         if (!misc->next || !misc->prev)
 146                 return -EINVAL;
 147         MOD_DEC_USE_COUNT;
 148         misc->prev->next = misc->next;
 149         misc->next->prev = misc->prev;
 150         misc->next = NULL;
 151         misc->prev = NULL;
 152         if (i < DYNAMIC_MINORS && i>0) {
 153                 misc_minors[i>>3] &= ~(1 << (misc->minor & 7));
 154         }
 155         return 0;
 156 }
 157 
 158 #ifdef MODULE
 159 
 160 #define misc_init init_module
 161 
 162 void cleanup_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 163 {
 164         unregister_chrdev(MISC_MAJOR, "misc");
 165 }
 166 
 167 #endif
 168 
 169 static struct symbol_table misc_syms = {
 170 /* Should this be surrounded with "#ifdef CONFIG_MODULES" ? */
 171 #include <linux/symtab_begin.h>
 172         X(misc_register),
 173         X(misc_deregister),
 174 #ifndef MODULE
 175         X(set_selection),   /* used by the kmisc module, can only */
 176         X(clear_selection), /* be exported if misc.c is in linked in */
 177 #endif
 178 #include <linux/symtab_end.h>
 179 };
 180 
 181 int misc_init(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 182 {
 183 #ifndef MODULE
 184 #ifdef CONFIG_PROC_FS
 185         proc_register_dynamic(&proc_root, &(struct proc_dir_entry) {
 186                 0, 4, "misc",
 187                 S_IRUGO, 1, 0, 0,
 188                 0, NULL /* ops -- default to array */,
 189                 &proc_misc_read /* get_info */,
 190         });     
 191 #endif /* PROC_FS */
 192 #ifdef CONFIG_BUSMOUSE
 193         bus_mouse_init();
 194 #endif
 195 #if defined CONFIG_PSMOUSE || defined CONFIG_82C710_MOUSE
 196         psaux_init();
 197 #endif
 198 #ifdef CONFIG_MS_BUSMOUSE
 199         ms_bus_mouse_init();
 200 #endif
 201 #ifdef CONFIG_ATIXL_BUSMOUSE
 202         atixl_busmouse_init();
 203 #endif
 204 #ifdef CONFIG_SOFT_WATCHDOG
 205         watchdog_init();
 206 #endif  
 207 #endif /* !MODULE */
 208         if (register_chrdev(MISC_MAJOR,"misc",&misc_fops)) {
 209           printk("unable to get major %d for misc devices\n",
 210                  MISC_MAJOR);
 211                 return -EIO;
 212         }
 213 
 214         if(register_symtab(&misc_syms)!=0)
 215         {
 216                 unregister_chrdev(MISC_MAJOR, "misc");
 217                 return -EIO;
 218         }
 219         return 0;
 220 }

/* [previous][next][first][last][top][bottom][index][help] */