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

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