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 #ifdef CONFIG_APM
  43 #include <linux/apm_bios.h>
  44 #endif
  45 
  46 #include <linux/tty.h> /* needed by selection.h */
  47 #include "selection.h" /* export its symbols */
  48 #ifdef CONFIG_KERNELD
  49 #include <linux/kerneld.h>
  50 #endif
  51 
  52 /*
  53  * Head entry for the doubly linked miscdevice list
  54  */
  55 static struct miscdevice misc_list = { 0, "head", NULL, &misc_list, &misc_list };
  56 
  57 /*
  58  * Assigned numbers, used for dynamic minors
  59  */
  60 #define DYNAMIC_MINORS 64 /* like dynamic majors */
  61 static unsigned char misc_minors[DYNAMIC_MINORS / 8];
  62 
  63 #ifndef MODULE
  64 extern int bus_mouse_init(void);
  65 extern int psaux_init(void);
  66 extern int ms_bus_mouse_init(void);
  67 extern int atixl_busmouse_init(void);
  68 extern void watchdog_init(void);
  69 
  70 #ifdef CONFIG_PROC_FS
  71 static int proc_misc_read(char *buf, char **start, off_t offset, int len, int unused)
     /* [previous][next][first][last][top][bottom][index][help] */
  72 {
  73         struct miscdevice *p;
  74 
  75         len=0;
  76         for (p = misc_list.next; p != &misc_list; p = p->next)
  77                 len += sprintf(buf+len, "%3i %s\n",p->minor, p->name ?: "");
  78         return len;
  79 }
  80 
  81 #endif /* PROC_FS */
  82 #endif /* !MODULE */
  83 
  84 static int misc_open(struct inode * inode, struct file * file)
     /* [previous][next][first][last][top][bottom][index][help] */
  85 {
  86         int minor = MINOR(inode->i_rdev);
  87         struct miscdevice *c = misc_list.next;
  88         file->f_op = NULL;
  89 
  90         while ((c != &misc_list) && (c->minor != minor))
  91                 c = c->next;
  92         if (c == &misc_list) {
  93 #ifdef CONFIG_KERNELD
  94                 char modname[20];
  95                 sprintf(modname, "char-major-%d-%d", MISC_MAJOR, minor);
  96                 request_module(modname);
  97                 c = misc_list.next;
  98                 while ((c != &misc_list) && (c->minor != minor))
  99                         c = c->next;
 100                 if (c == &misc_list)
 101 #endif
 102                         return -ENODEV;
 103         }
 104 
 105         if ((file->f_op = c->fops))
 106                 return file->f_op->open(inode,file);
 107         else
 108                 return -ENODEV;
 109 }
 110 
 111 static struct file_operations misc_fops = {
 112         NULL,           /* seek */
 113         NULL,           /* read */
 114         NULL,           /* write */
 115         NULL,           /* readdir */
 116         NULL,           /* select */
 117         NULL,           /* ioctl */
 118         NULL,           /* mmap */
 119         misc_open,
 120         NULL            /* release */
 121 };
 122 
 123 int misc_register(struct miscdevice * misc)
     /* [previous][next][first][last][top][bottom][index][help] */
 124 {
 125         if (misc->next || misc->prev)
 126                 return -EBUSY;
 127         if (misc->minor == MISC_DYNAMIC_MINOR) {
 128                 int i = DYNAMIC_MINORS;
 129                 while (--i >= 0)
 130                         if ( (misc_minors[i>>3] & (1 << (i&7))) == 0)
 131                                 break;
 132                 if (i<0) return -EBUSY;
 133                 misc->minor = i;
 134         }
 135         if (misc->minor < DYNAMIC_MINORS)
 136                 misc_minors[misc->minor >> 3] |= 1 << (misc->minor & 7);
 137         MOD_INC_USE_COUNT;
 138         misc->next = &misc_list;
 139         misc->prev = misc_list.prev;
 140         misc->prev->next = misc;
 141         misc->next->prev = misc;
 142         return 0;
 143 }
 144 
 145 int misc_deregister(struct miscdevice * misc)
     /* [previous][next][first][last][top][bottom][index][help] */
 146 {
 147         int i = misc->minor;
 148         if (!misc->next || !misc->prev)
 149                 return -EINVAL;
 150         MOD_DEC_USE_COUNT;
 151         misc->prev->next = misc->next;
 152         misc->next->prev = misc->prev;
 153         misc->next = NULL;
 154         misc->prev = NULL;
 155         if (i < DYNAMIC_MINORS && i>0) {
 156                 misc_minors[i>>3] &= ~(1 << (misc->minor & 7));
 157         }
 158         return 0;
 159 }
 160 
 161 #ifdef MODULE
 162 
 163 #define misc_init init_module
 164 
 165 void cleanup_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 166 {
 167         unregister_chrdev(MISC_MAJOR, "misc");
 168 }
 169 
 170 #endif
 171 
 172 static struct symbol_table misc_syms = {
 173 /* Should this be surrounded with "#ifdef CONFIG_MODULES" ? */
 174 #include <linux/symtab_begin.h>
 175         X(misc_register),
 176         X(misc_deregister),
 177 #ifndef MODULE
 178         X(set_selection),   /* used by the kmisc module, can only */
 179         X(clear_selection), /* be exported if misc.c is in linked in */
 180 #endif
 181 #include <linux/symtab_end.h>
 182 };
 183 
 184 int misc_init(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 185 {
 186 #ifndef MODULE
 187 #ifdef CONFIG_PROC_FS
 188         proc_register_dynamic(&proc_root, &(struct proc_dir_entry) {
 189                 0, 4, "misc",
 190                 S_IRUGO, 1, 0, 0,
 191                 0, NULL /* ops -- default to array */,
 192                 &proc_misc_read /* get_info */,
 193         });     
 194 #endif /* PROC_FS */
 195 #ifdef CONFIG_BUSMOUSE
 196         bus_mouse_init();
 197 #endif
 198 #if defined CONFIG_PSMOUSE || defined CONFIG_82C710_MOUSE
 199         psaux_init();
 200 #endif
 201 #ifdef CONFIG_MS_BUSMOUSE
 202         ms_bus_mouse_init();
 203 #endif
 204 #ifdef CONFIG_ATIXL_BUSMOUSE
 205         atixl_busmouse_init();
 206 #endif
 207 #ifdef CONFIG_SOFT_WATCHDOG
 208         watchdog_init();
 209 #endif  
 210 #ifdef CONFIG_APM
 211         apm_bios_init();
 212 #endif
 213 #endif /* !MODULE */
 214         if (register_chrdev(MISC_MAJOR,"misc",&misc_fops)) {
 215           printk("unable to get major %d for misc devices\n",
 216                  MISC_MAJOR);
 217                 return -EIO;
 218         }
 219 
 220         if(register_symtab(&misc_syms)!=0)
 221         {
 222                 unregister_chrdev(MISC_MAJOR, "misc");
 223                 return -EIO;
 224         }
 225         return 0;
 226 }

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