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

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