OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [char/] [misc.c] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
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
 * Changes for kmod (from kerneld):
31
 *      Cyrus Durgin <cider@speakeasy.org>
32
 *
33
 * Added devfs support. Richard Gooch <rgooch@atnf.csiro.au>  10-Jan-1998
34
 */
35
 
36
#include <linux/module.h>
37
#include <linux/config.h>
38
 
39
#include <linux/fs.h>
40
#include <linux/errno.h>
41
#include <linux/miscdevice.h>
42
#include <linux/kernel.h>
43
#include <linux/major.h>
44
#include <linux/slab.h>
45
#include <linux/proc_fs.h>
46
#include <linux/devfs_fs_kernel.h>
47
#include <linux/stat.h>
48
#include <linux/init.h>
49
 
50
#include <linux/tty.h>
51
#include <linux/selection.h>
52
#include <linux/kmod.h>
53
 
54
#include "busmouse.h"
55
 
56
/*
57
 * Head entry for the doubly linked miscdevice list
58
 */
59
static struct miscdevice misc_list = { 0, "head", NULL, &misc_list, &misc_list };
60
static DECLARE_MUTEX(misc_sem);
61
 
62
/*
63
 * Assigned numbers, used for dynamic minors
64
 */
65
#define DYNAMIC_MINORS 64 /* like dynamic majors */
66
static unsigned char misc_minors[DYNAMIC_MINORS / 8];
67
 
68
extern int psaux_init(void);
69
extern int rtc_DP8570A_init(void);
70
extern int rtc_MK48T08_init(void);
71
extern int ds1286_init(void);
72
extern int pmu_device_init(void);
73
extern int tosh_init(void);
74
extern int i8k_init(void);
75
extern int lcd_init(void);
76
 
77
static int misc_read_proc(char *buf, char **start, off_t offset,
78
                          int len, int *eof, void *private)
79
{
80
        struct miscdevice *p;
81
        int written;
82
 
83
        written=0;
84
        for (p = misc_list.next; p != &misc_list && written < len; p = p->next) {
85
                written += sprintf(buf+written, "%3i %s\n",p->minor, p->name ?: "");
86
                if (written < offset) {
87
                        offset -= written;
88
                        written = 0;
89
                }
90
        }
91
        *start = buf + offset;
92
        written -= offset;
93
        if(written > len) {
94
                *eof = 0;
95
                return len;
96
        }
97
        *eof = 1;
98
        return (written<0) ? 0 : written;
99
}
100
 
101
 
102
static int misc_open(struct inode * inode, struct file * file)
103
{
104
        int minor = MINOR(inode->i_rdev);
105
        struct miscdevice *c;
106
        int err = -ENODEV;
107
        struct file_operations *old_fops, *new_fops = NULL;
108
 
109
        down(&misc_sem);
110
 
111
        c = misc_list.next;
112
 
113
        while ((c != &misc_list) && (c->minor != minor))
114
                c = c->next;
115
        if (c != &misc_list)
116
                new_fops = fops_get(c->fops);
117
        if (!new_fops) {
118
                char modname[20];
119
                up(&misc_sem);
120
                sprintf(modname, "char-major-%d-%d", MISC_MAJOR, minor);
121
                request_module(modname);
122
                down(&misc_sem);
123
                c = misc_list.next;
124
                while ((c != &misc_list) && (c->minor != minor))
125
                        c = c->next;
126
                if (c == &misc_list || (new_fops = fops_get(c->fops)) == NULL)
127
                        goto fail;
128
        }
129
 
130
        err = 0;
131
        old_fops = file->f_op;
132
        file->f_op = new_fops;
133
        if (file->f_op->open) {
134
                err=file->f_op->open(inode,file);
135
                if (err) {
136
                        fops_put(file->f_op);
137
                        file->f_op = fops_get(old_fops);
138
                }
139
        }
140
        fops_put(old_fops);
141
fail:
142
        up(&misc_sem);
143
        return err;
144
}
145
 
146
static struct file_operations misc_fops = {
147
        owner:          THIS_MODULE,
148
        open:           misc_open,
149
};
150
 
151
 
152
/**
153
 *      misc_register   -       register a miscellaneous device
154
 *      @misc: device structure
155
 *
156
 *      Register a miscellaneous device with the kernel. If the minor
157
 *      number is set to %MISC_DYNAMIC_MINOR a minor number is assigned
158
 *      and placed in the minor field of the structure. For other cases
159
 *      the minor number requested is used.
160
 *
161
 *      The structure passed is linked into the kernel and may not be
162
 *      destroyed until it has been unregistered.
163
 *
164
 *      A zero is returned on success and a negative errno code for
165
 *      failure.
166
 */
167
 
168
int misc_register(struct miscdevice * misc)
169
{
170
        static devfs_handle_t devfs_handle, dir;
171
        struct miscdevice *c;
172
 
173
        if (misc->next || misc->prev)
174
                return -EBUSY;
175
        down(&misc_sem);
176
        c = misc_list.next;
177
 
178
        while ((c != &misc_list) && (c->minor != misc->minor))
179
                c = c->next;
180
        if (c != &misc_list) {
181
                up(&misc_sem);
182
                return -EBUSY;
183
        }
184
 
185
        if (misc->minor == MISC_DYNAMIC_MINOR) {
186
                int i = DYNAMIC_MINORS;
187
                while (--i >= 0)
188
                        if ( (misc_minors[i>>3] & (1 << (i&7))) == 0)
189
                                break;
190
                if (i<0)
191
                {
192
                        up(&misc_sem);
193
                        return -EBUSY;
194
                }
195
                misc->minor = i;
196
        }
197
        if (misc->minor < DYNAMIC_MINORS)
198
                misc_minors[misc->minor >> 3] |= 1 << (misc->minor & 7);
199
        if (!devfs_handle)
200
                devfs_handle = devfs_mk_dir (NULL, "misc", NULL);
201
        dir = strchr (misc->name, '/') ? NULL : devfs_handle;
202
        misc->devfs_handle =
203
                devfs_register (dir, misc->name, DEVFS_FL_NONE,
204
                                MISC_MAJOR, misc->minor,
205
                                S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,
206
                                misc->fops, NULL);
207
 
208
        /*
209
         * Add it to the front, so that later devices can "override"
210
         * earlier defaults
211
         */
212
        misc->prev = &misc_list;
213
        misc->next = misc_list.next;
214
        misc->prev->next = misc;
215
        misc->next->prev = misc;
216
        up(&misc_sem);
217
        return 0;
218
}
219
 
220
/**
221
 *      misc_deregister - unregister a miscellaneous device
222
 *      @misc: device to unregister
223
 *
224
 *      Unregister a miscellaneous device that was previously
225
 *      successfully registered with misc_register(). Success
226
 *      is indicated by a zero return, a negative errno code
227
 *      indicates an error.
228
 */
229
 
230
int misc_deregister(struct miscdevice * misc)
231
{
232
        int i = misc->minor;
233
        if (!misc->next || !misc->prev)
234
                return -EINVAL;
235
        down(&misc_sem);
236
        misc->prev->next = misc->next;
237
        misc->next->prev = misc->prev;
238
        misc->next = NULL;
239
        misc->prev = NULL;
240
        devfs_unregister (misc->devfs_handle);
241
        if (i < DYNAMIC_MINORS && i>0) {
242
                misc_minors[i>>3] &= ~(1 << (misc->minor & 7));
243
        }
244
        up(&misc_sem);
245
        return 0;
246
}
247
 
248
EXPORT_SYMBOL(misc_register);
249
EXPORT_SYMBOL(misc_deregister);
250
 
251
int __init misc_init(void)
252
{
253
        create_proc_read_entry("misc", 0, 0, misc_read_proc, NULL);
254
#ifdef CONFIG_MVME16x
255
        rtc_MK48T08_init();
256
#endif
257
#ifdef CONFIG_BVME6000
258
        rtc_DP8570A_init();
259
#endif
260
#ifdef CONFIG_SGI_DS1286
261
        ds1286_init();
262
#endif
263
#ifdef CONFIG_PMAC_PBOOK
264
        pmu_device_init();
265
#endif
266
#ifdef CONFIG_TOSHIBA
267
        tosh_init();
268
#endif
269
#ifdef CONFIG_COBALT_LCD
270
        lcd_init();
271
#endif
272
#ifdef CONFIG_I8K
273
        i8k_init();
274
#endif
275
        if (devfs_register_chrdev(MISC_MAJOR,"misc",&misc_fops)) {
276
                printk("unable to get major %d for misc devices\n",
277
                       MISC_MAJOR);
278
                return -EIO;
279
        }
280
        return 0;
281
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.