diff options
author | Lidza Louina <lidza.louina@gmail.com> | 2013-08-15 10:28:22 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-08-15 13:14:29 -0400 |
commit | 35cf90459312fc3b6bc4bbf31aa5fe47b73922d4 (patch) | |
tree | 8c6a95a56e63da5833551aa20566ce7da3850bd7 | |
parent | 41506a9f83c5ef8abda07d205c52b9e35d6d229a (diff) |
staging: dgnc: removes proc code
This patch removes the dgnc_proc.c and dgnc_proc.h files and all
references to proc functions in dgnc_driver.c. This also removes proc.h
from the include headers in driver.c, mgmt.c and sysfs.c and proc.o
from the Makefile.
Drivers now use sysfs instead of proc.
Signed-off-by: Lidza Louina <lidza.louina@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/staging/dgnc/Makefile | 2 | ||||
-rw-r--r-- | drivers/staging/dgnc/dgnc_driver.c | 10 | ||||
-rw-r--r-- | drivers/staging/dgnc/dgnc_mgmt.c | 1 | ||||
-rw-r--r-- | drivers/staging/dgnc/dgnc_proc.c | 1550 | ||||
-rw-r--r-- | drivers/staging/dgnc/dgnc_proc.h | 147 | ||||
-rw-r--r-- | drivers/staging/dgnc/dgnc_sysfs.c | 1 |
6 files changed, 1 insertions, 1710 deletions
diff --git a/drivers/staging/dgnc/Makefile b/drivers/staging/dgnc/Makefile index c4c96dc5a541..888c4334236b 100644 --- a/drivers/staging/dgnc/Makefile +++ b/drivers/staging/dgnc/Makefile | |||
@@ -4,4 +4,4 @@ obj-$(CONFIG_DGNC) += dgnc.o | |||
4 | 4 | ||
5 | dgnc-objs := dgnc_cls.o dgnc_driver.o\ | 5 | dgnc-objs := dgnc_cls.o dgnc_driver.o\ |
6 | dgnc_mgmt.o dgnc_neo.o\ | 6 | dgnc_mgmt.o dgnc_neo.o\ |
7 | dgnc_proc.o dgnc_trace.o dgnc_tty.o dgnc_sysfs.o | 7 | dgnc_trace.o dgnc_tty.o dgnc_sysfs.o |
diff --git a/drivers/staging/dgnc/dgnc_driver.c b/drivers/staging/dgnc/dgnc_driver.c index 7c88de773745..e8de7a411255 100644 --- a/drivers/staging/dgnc/dgnc_driver.c +++ b/drivers/staging/dgnc/dgnc_driver.c | |||
@@ -43,7 +43,6 @@ | |||
43 | 43 | ||
44 | #include "dgnc_driver.h" | 44 | #include "dgnc_driver.h" |
45 | #include "dgnc_pci.h" | 45 | #include "dgnc_pci.h" |
46 | #include "dgnc_proc.h" | ||
47 | #include "dpacompat.h" | 46 | #include "dpacompat.h" |
48 | #include "dgnc_mgmt.h" | 47 | #include "dgnc_mgmt.h" |
49 | #include "dgnc_tty.h" | 48 | #include "dgnc_tty.h" |
@@ -313,11 +312,6 @@ static int dgnc_start(void) | |||
313 | } | 312 | } |
314 | 313 | ||
315 | /* | 314 | /* |
316 | * Register our basic stuff in /proc/dgnc | ||
317 | */ | ||
318 | dgnc_proc_register_basic_prescan(); | ||
319 | |||
320 | /* | ||
321 | * Init any global tty stuff. | 315 | * Init any global tty stuff. |
322 | */ | 316 | */ |
323 | rc = dgnc_tty_preinit(); | 317 | rc = dgnc_tty_preinit(); |
@@ -401,8 +395,6 @@ void dgnc_cleanup_module(void) | |||
401 | /* Turn off poller right away. */ | 395 | /* Turn off poller right away. */ |
402 | del_timer_sync(&dgnc_poll_timer); | 396 | del_timer_sync(&dgnc_poll_timer); |
403 | 397 | ||
404 | dgnc_proc_unregister_all(); | ||
405 | |||
406 | dgnc_remove_driver_sysfiles(&dgnc_driver); | 398 | dgnc_remove_driver_sysfiles(&dgnc_driver); |
407 | 399 | ||
408 | if (dgnc_Major_Control_Registered) { | 400 | if (dgnc_Major_Control_Registered) { |
@@ -742,8 +734,6 @@ static int dgnc_found_board(struct pci_dev *pdev, int id) | |||
742 | */ | 734 | */ |
743 | brd->flipbuf = dgnc_driver_kzmalloc(MYFLIPLEN, GFP_KERNEL); | 735 | brd->flipbuf = dgnc_driver_kzmalloc(MYFLIPLEN, GFP_KERNEL); |
744 | 736 | ||
745 | dgnc_proc_register_basic_postscan(dgnc_NumBoards); | ||
746 | |||
747 | wake_up_interruptible(&brd->state_wait); | 737 | wake_up_interruptible(&brd->state_wait); |
748 | 738 | ||
749 | return(0); | 739 | return(0); |
diff --git a/drivers/staging/dgnc/dgnc_mgmt.c b/drivers/staging/dgnc/dgnc_mgmt.c index 96cf58b31322..bbd65db524cd 100644 --- a/drivers/staging/dgnc/dgnc_mgmt.c +++ b/drivers/staging/dgnc/dgnc_mgmt.c | |||
@@ -47,7 +47,6 @@ | |||
47 | 47 | ||
48 | #include "dgnc_driver.h" | 48 | #include "dgnc_driver.h" |
49 | #include "dgnc_pci.h" | 49 | #include "dgnc_pci.h" |
50 | #include "dgnc_proc.h" | ||
51 | #include "dgnc_kcompat.h" /* Kernel 2.4/2.6 compat includes */ | 50 | #include "dgnc_kcompat.h" /* Kernel 2.4/2.6 compat includes */ |
52 | #include "dgnc_mgmt.h" | 51 | #include "dgnc_mgmt.h" |
53 | #include "dpacompat.h" | 52 | #include "dpacompat.h" |
diff --git a/drivers/staging/dgnc/dgnc_proc.c b/drivers/staging/dgnc/dgnc_proc.c deleted file mode 100644 index c59c833f5e05..000000000000 --- a/drivers/staging/dgnc/dgnc_proc.c +++ /dev/null | |||
@@ -1,1550 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright 2003 Digi International (www.digi.com) | ||
3 | * Scott H Kilau <Scott_Kilau at digi dot com> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2, or (at your option) | ||
8 | * any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the | ||
12 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR | ||
13 | * PURPOSE. See the GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | * | ||
19 | * | ||
20 | * NOTE TO LINUX KERNEL HACKERS: DO NOT REFORMAT THIS CODE! | ||
21 | * | ||
22 | * This is shared code between Digi's CVS archive and the | ||
23 | * Linux Kernel sources. | ||
24 | * Changing the source just for reformatting needlessly breaks | ||
25 | * our CVS diff history. | ||
26 | * | ||
27 | * Send any bug fixes/changes to: Eng.Linux at digi dot com. | ||
28 | * Thank you. | ||
29 | * | ||
30 | * | ||
31 | * $Id: dgnc_proc.c,v 1.3 2011/06/22 12:16:35 markh Exp $ | ||
32 | */ | ||
33 | |||
34 | #include <linux/kernel.h> | ||
35 | #include <linux/version.h> | ||
36 | #include <linux/sched.h> /* For jiffies, task states */ | ||
37 | #include <linux/interrupt.h> /* For tasklet and interrupt structs/defines */ | ||
38 | #include <linux/module.h> | ||
39 | #include <linux/ctype.h> | ||
40 | #include <linux/proc_fs.h> | ||
41 | #include <linux/serial_reg.h> | ||
42 | #include <linux/string.h> | ||
43 | #include <asm/uaccess.h> /* For copy_from_user/copy_to_user */ | ||
44 | |||
45 | #include "dgnc_driver.h" | ||
46 | #include "dgnc_proc.h" | ||
47 | #include "dgnc_mgmt.h" | ||
48 | |||
49 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37) | ||
50 | #define init_MUTEX(sem) sema_init(sem, 1) | ||
51 | #define DECLARE_MUTEX(name) \ | ||
52 | struct semaphore name = __SEMAPHORE_INITIALIZER(name, 1) | ||
53 | #endif | ||
54 | |||
55 | |||
56 | /* The /proc/dgnc directory */ | ||
57 | static struct proc_dir_entry *ProcDGNC; | ||
58 | |||
59 | |||
60 | /* File operation declarations */ | ||
61 | static int dgnc_gen_proc_open(struct inode *, struct file *); | ||
62 | static int dgnc_gen_proc_close(struct inode *, struct file *); | ||
63 | static ssize_t dgnc_gen_proc_read(struct file *file, char __user *buf, size_t count, loff_t *ppos); | ||
64 | static ssize_t dgnc_gen_proc_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos); | ||
65 | |||
66 | static int dgnc_proc_chk_perm(struct inode *, int); | ||
67 | |||
68 | static const struct file_operations dgnc_proc_file_ops = | ||
69 | { | ||
70 | .owner = THIS_MODULE, | ||
71 | .read = dgnc_gen_proc_read, /* read */ | ||
72 | .write = dgnc_gen_proc_write, /* write */ | ||
73 | .open = dgnc_gen_proc_open, /* open */ | ||
74 | .release = dgnc_gen_proc_close, /* release */ | ||
75 | }; | ||
76 | |||
77 | |||
78 | static struct inode_operations dgnc_proc_inode_ops = | ||
79 | { | ||
80 | .permission = dgnc_proc_chk_perm | ||
81 | }; | ||
82 | |||
83 | |||
84 | static void dgnc_register_proc_table(struct dgnc_proc_entry *, struct proc_dir_entry *); | ||
85 | static void dgnc_unregister_proc_table(struct dgnc_proc_entry *, struct proc_dir_entry *); | ||
86 | static void dgnc_remove_proc_entry(struct proc_dir_entry *pde); | ||
87 | |||
88 | |||
89 | /* Stuff in /proc/ */ | ||
90 | static int dgnc_read_info(struct dgnc_proc_entry *table, int dir, struct file *filp, | ||
91 | char __user *buffer, ssize_t *lenp, loff_t *ppos); | ||
92 | static int dgnc_write_info(struct dgnc_proc_entry *table, int dir, struct file *filp, | ||
93 | const char __user *buffer, ssize_t *lenp, loff_t *ppos); | ||
94 | |||
95 | static int dgnc_read_mknod(struct dgnc_proc_entry *table, int dir, struct file *filp, | ||
96 | char __user *buffer, ssize_t *lenp, loff_t *ppos); | ||
97 | |||
98 | static struct dgnc_proc_entry dgnc_table[] = { | ||
99 | {DGNC_INFO, "info", 0600, NULL, NULL, NULL, &dgnc_read_info, &dgnc_write_info, | ||
100 | NULL, __SEMAPHORE_INITIALIZER(dgnc_table[0].excl_sem, 1), 0, NULL }, | ||
101 | {DGNC_MKNOD, "mknod", 0600, NULL, NULL, NULL, &dgnc_read_mknod, NULL, | ||
102 | NULL, __SEMAPHORE_INITIALIZER(dgnc_table[1].excl_sem, 1), 0, NULL }, | ||
103 | {0} | ||
104 | }; | ||
105 | |||
106 | |||
107 | /* Stuff in /proc/<board>/ */ | ||
108 | static int dgnc_read_board_info(struct dgnc_proc_entry *table, int dir, struct file *filp, | ||
109 | char __user *buffer, ssize_t *lenp, loff_t *ppos); | ||
110 | static int dgnc_read_board_vpd(struct dgnc_proc_entry *table, int dir, struct file *filp, | ||
111 | char __user *buffer, ssize_t *lenp, loff_t *ppos); | ||
112 | static int dgnc_read_board_mknod(struct dgnc_proc_entry *table, int dir, struct file *filp, | ||
113 | char __user *buffer, ssize_t *lenp, loff_t *ppos); | ||
114 | static int dgnc_read_board_ttystats(struct dgnc_proc_entry *table, int dir, struct file *filp, | ||
115 | char __user *buffer, ssize_t *lenp, loff_t *ppos); | ||
116 | static int dgnc_read_board_ttyintr(struct dgnc_proc_entry *table, int dir, struct file *filp, | ||
117 | char __user *buffer, ssize_t *lenp, loff_t *ppos); | ||
118 | static int dgnc_read_board_ttyflags(struct dgnc_proc_entry *table, int dir, struct file *filp, | ||
119 | char __user *buffer, ssize_t *lenp, loff_t *ppos); | ||
120 | |||
121 | static struct dgnc_proc_entry dgnc_board_table[] = { | ||
122 | {DGNC_BOARD_INFO, "info", 0600, NULL, NULL, NULL, &dgnc_read_board_info, NULL, | ||
123 | NULL, __SEMAPHORE_INITIALIZER(dgnc_board_table[0].excl_sem, 1), 0, NULL }, | ||
124 | {DGNC_BOARD_VPD, "vpd", 0600, NULL, NULL, NULL, &dgnc_read_board_vpd, NULL, | ||
125 | NULL, __SEMAPHORE_INITIALIZER(dgnc_board_table[1].excl_sem, 1), 0, NULL }, | ||
126 | {DGNC_BOARD_TTYSTATS, "stats", 0600, NULL, NULL, NULL, &dgnc_read_board_ttystats, NULL, | ||
127 | NULL, __SEMAPHORE_INITIALIZER(dgnc_board_table[2].excl_sem, 1), 0, NULL }, | ||
128 | {DGNC_BOARD_TTYINTR, "intr", 0600, NULL, NULL, NULL, &dgnc_read_board_ttyintr, NULL, | ||
129 | NULL, __SEMAPHORE_INITIALIZER(dgnc_board_table[3].excl_sem, 1), 0, NULL }, | ||
130 | {DGNC_BOARD_TTYFLAGS, "flags", 0600, NULL, NULL, NULL, &dgnc_read_board_ttyflags, NULL, | ||
131 | NULL, __SEMAPHORE_INITIALIZER(dgnc_board_table[4].excl_sem, 1), 0, NULL }, | ||
132 | {DGNC_BOARD_MKNOD, "mknod", 0600, NULL, NULL, NULL, &dgnc_read_board_mknod, NULL, | ||
133 | NULL, __SEMAPHORE_INITIALIZER(dgnc_board_table[5].excl_sem, 1), 0, NULL }, | ||
134 | {0} | ||
135 | }; | ||
136 | |||
137 | |||
138 | /* Stuff in /proc/<board>/<channel> */ | ||
139 | static int dgnc_read_channel_info(struct dgnc_proc_entry *table, int dir, struct file *filp, | ||
140 | char __user *buffer, ssize_t *lenp, loff_t *ppos); | ||
141 | static int dgnc_open_channel_sniff(struct dgnc_proc_entry *table, int dir, struct file *filp, | ||
142 | void *buffer, ssize_t *lenp, loff_t *ppos); | ||
143 | static int dgnc_close_channel_sniff(struct dgnc_proc_entry *table, int dir, struct file *filp, | ||
144 | void *buffer, ssize_t *lenp, loff_t *ppos); | ||
145 | static int dgnc_read_channel_sniff(struct dgnc_proc_entry *table, int dir, struct file *filp, | ||
146 | char __user *buffer, ssize_t *lenp, loff_t *ppos); | ||
147 | static int dgnc_read_channel_custom_ttyname(struct dgnc_proc_entry *table, int dir, struct file *filp, | ||
148 | char __user *buffer, ssize_t *lenp, loff_t *ppos); | ||
149 | static int dgnc_read_channel_custom_prname(struct dgnc_proc_entry *table, int dir, struct file *filp, | ||
150 | char __user *buffer, ssize_t *lenp, loff_t *ppos); | ||
151 | |||
152 | static struct dgnc_proc_entry dgnc_channel_table[] = { | ||
153 | {DGNC_PORT_INFO, "info", 0600, NULL, NULL, NULL, &dgnc_read_channel_info, NULL, | ||
154 | NULL, __SEMAPHORE_INITIALIZER(dgnc_channel_table[0].excl_sem, 1), 0, NULL }, | ||
155 | {DGNC_PORT_SNIFF, "sniff", 0600, NULL, &dgnc_open_channel_sniff, &dgnc_close_channel_sniff, &dgnc_read_channel_sniff, NULL, | ||
156 | NULL, __SEMAPHORE_INITIALIZER(dgnc_channel_table[1].excl_sem, 1), 0, NULL}, | ||
157 | {DGNC_PORT_CUSTOM_TTYNAME, "ttyname", 0600, NULL, NULL, NULL, &dgnc_read_channel_custom_ttyname, NULL, | ||
158 | NULL, __SEMAPHORE_INITIALIZER(dgnc_channel_table[2].excl_sem, 1), 0, NULL }, | ||
159 | {DGNC_PORT_CUSTOM_PRNAME, "prname", 0600, NULL, NULL, NULL, &dgnc_read_channel_custom_prname, NULL, | ||
160 | NULL, __SEMAPHORE_INITIALIZER(dgnc_channel_table[3].excl_sem, 1), 0, NULL }, | ||
161 | {0} | ||
162 | }; | ||
163 | |||
164 | |||
165 | /* | ||
166 | * dgnc_test_perm does NOT grant the superuser all rights automatically, because | ||
167 | * some entries are readonly even to root. | ||
168 | */ | ||
169 | static inline int dgnc_test_perm(int mode, int op) | ||
170 | { | ||
171 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) | ||
172 | if (!current->euid) | ||
173 | #else | ||
174 | if (!current_euid()) | ||
175 | #endif | ||
176 | mode >>= 6; | ||
177 | else if (in_egroup_p(0)) | ||
178 | mode >>= 3; | ||
179 | if ((mode & op & 0007) == op) | ||
180 | return 0; | ||
181 | if (capable(CAP_SYS_ADMIN)) | ||
182 | return 0; | ||
183 | return -EACCES; | ||
184 | } | ||
185 | |||
186 | |||
187 | /* | ||
188 | * /proc/sys support | ||
189 | */ | ||
190 | static inline int dgnc_proc_match(int len, const char *name, struct proc_dir_entry *de) | ||
191 | { | ||
192 | if (!de || !de->low_ino) | ||
193 | return 0; | ||
194 | if (de->namelen != len) | ||
195 | return 0; | ||
196 | return !memcmp(name, de->name, len); | ||
197 | } | ||
198 | |||
199 | |||
200 | /* | ||
201 | * Scan the entries in table and add them all to /proc at the position | ||
202 | * referred to by "root" | ||
203 | */ | ||
204 | static void dgnc_register_proc_table(struct dgnc_proc_entry *table, struct proc_dir_entry *root) | ||
205 | { | ||
206 | struct proc_dir_entry *de; | ||
207 | int len; | ||
208 | mode_t mode; | ||
209 | |||
210 | for (; table->magic; table++) { | ||
211 | /* Can't do anything without a proc name. */ | ||
212 | if (!table->name) { | ||
213 | DPR_PROC(("dgnc_register_proc_table, no name...\n")); | ||
214 | continue; | ||
215 | } | ||
216 | |||
217 | /* Maybe we can't do anything with it... */ | ||
218 | if (!table->read_handler && !table->write_handler && !table->child) { | ||
219 | DPR_PROC((KERN_WARNING "DGNC PROC: Can't register %s\n", table->name)); | ||
220 | continue; | ||
221 | } | ||
222 | |||
223 | len = strlen(table->name); | ||
224 | mode = table->mode; | ||
225 | de = NULL; | ||
226 | |||
227 | if (!table->child) { | ||
228 | mode |= S_IFREG; | ||
229 | } else { | ||
230 | mode |= S_IFDIR; | ||
231 | for (de = root->subdir; de; de = de->next) { | ||
232 | if (dgnc_proc_match(len, table->name, de)) | ||
233 | break; | ||
234 | } | ||
235 | |||
236 | /* If the subdir exists already, de is non-NULL */ | ||
237 | } | ||
238 | |||
239 | if (!de) { | ||
240 | de = create_proc_entry(table->name, mode, root); | ||
241 | if (!de) | ||
242 | continue; | ||
243 | de->data = (void *) table; | ||
244 | if (!table->child) { | ||
245 | de->proc_iops = &dgnc_proc_inode_ops; | ||
246 | de->proc_fops = &dgnc_proc_file_ops; | ||
247 | } | ||
248 | } | ||
249 | |||
250 | table->de = de; | ||
251 | |||
252 | if (de->mode & S_IFDIR) | ||
253 | dgnc_register_proc_table(table->child, de); | ||
254 | |||
255 | } | ||
256 | } | ||
257 | |||
258 | |||
259 | |||
260 | /* | ||
261 | * Unregister a /proc sysctl table and any subdirectories. | ||
262 | */ | ||
263 | static void dgnc_unregister_proc_table(struct dgnc_proc_entry *table, struct proc_dir_entry *root) | ||
264 | { | ||
265 | struct proc_dir_entry *de; | ||
266 | |||
267 | for (; table->magic; table++) { | ||
268 | if (!(de = table->de)) | ||
269 | continue; | ||
270 | |||
271 | if (de->mode & S_IFDIR) { | ||
272 | if (!table->child) { | ||
273 | DPR_PROC((KERN_ALERT "Help - malformed sysctl tree on free\n")); | ||
274 | continue; | ||
275 | } | ||
276 | |||
277 | /* recurse down into subdirectory... */ | ||
278 | DPR_PROC(("Recursing down a directory...\n")); | ||
279 | dgnc_unregister_proc_table(table->child, de); | ||
280 | |||
281 | /* Don't unregister directories which still have entries.. */ | ||
282 | if (de->subdir) | ||
283 | continue; | ||
284 | } | ||
285 | |||
286 | /* Don't unregister proc entries that are still being used.. */ | ||
287 | if ((atomic_read(&de->count)) != 1) { | ||
288 | DPR_PROC(("proc entry in use... Not removing...\n")); | ||
289 | continue; | ||
290 | } | ||
291 | |||
292 | dgnc_remove_proc_entry(de); | ||
293 | table->de = NULL; | ||
294 | } | ||
295 | } | ||
296 | |||
297 | |||
298 | |||
299 | static int dgnc_gen_proc_open(struct inode *inode, struct file *file) | ||
300 | { | ||
301 | struct proc_dir_entry *de; | ||
302 | struct dgnc_proc_entry *entry; | ||
303 | int (*handler) (struct dgnc_proc_entry *table, int dir, struct file *filp, | ||
304 | void *buffer, ssize_t *lenp, loff_t *ppos); | ||
305 | int ret = 0, error = 0; | ||
306 | |||
307 | de = (struct proc_dir_entry *) PDE(file->f_dentry->d_inode); | ||
308 | if (!de || !de->data) { | ||
309 | ret = -ENXIO; | ||
310 | goto done; | ||
311 | } | ||
312 | |||
313 | entry = (struct dgnc_proc_entry *) de->data; | ||
314 | if (!entry) { | ||
315 | ret = -ENXIO; | ||
316 | goto done; | ||
317 | } | ||
318 | |||
319 | down(&entry->excl_sem); | ||
320 | |||
321 | if (entry->excl_cnt) { | ||
322 | ret = -EBUSY; | ||
323 | } else { | ||
324 | entry->excl_cnt++; | ||
325 | |||
326 | handler = entry->open_handler; | ||
327 | if (handler) { | ||
328 | error = (*handler) (entry, OUTBOUND, file, NULL, NULL, NULL); | ||
329 | if (error) { | ||
330 | entry->excl_cnt--; | ||
331 | ret = error; | ||
332 | } | ||
333 | } | ||
334 | } | ||
335 | |||
336 | up(&entry->excl_sem); | ||
337 | |||
338 | done: | ||
339 | |||
340 | return ret; | ||
341 | } | ||
342 | |||
343 | |||
344 | static int dgnc_gen_proc_close(struct inode *inode, struct file *file) | ||
345 | { | ||
346 | struct proc_dir_entry *de; | ||
347 | int (*handler) (struct dgnc_proc_entry *table, int dir, struct file *filp, | ||
348 | void *buffer, ssize_t *lenp, loff_t *ppos); | ||
349 | struct dgnc_proc_entry *entry; | ||
350 | int error = 0; | ||
351 | |||
352 | de = (struct proc_dir_entry *) PDE(file->f_dentry->d_inode); | ||
353 | if (!de || !de->data) | ||
354 | goto done; | ||
355 | |||
356 | entry = (struct dgnc_proc_entry *) de->data; | ||
357 | if (!entry) | ||
358 | goto done; | ||
359 | |||
360 | down(&entry->excl_sem); | ||
361 | |||
362 | if (entry->excl_cnt) | ||
363 | entry->excl_cnt = 0; | ||
364 | |||
365 | |||
366 | handler = entry->close_handler; | ||
367 | if (handler) { | ||
368 | error = (*handler) (entry, OUTBOUND, file, NULL, NULL, NULL); | ||
369 | } | ||
370 | |||
371 | up(&entry->excl_sem); | ||
372 | |||
373 | done: | ||
374 | return 0; | ||
375 | } | ||
376 | |||
377 | |||
378 | static ssize_t dgnc_gen_proc_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) | ||
379 | { | ||
380 | struct proc_dir_entry *de; | ||
381 | struct dgnc_proc_entry *entry; | ||
382 | int (*handler) (struct dgnc_proc_entry *table, int dir, struct file *filp, | ||
383 | char __user *buffer, ssize_t *lenp, loff_t *ppos2); | ||
384 | ssize_t res; | ||
385 | ssize_t error; | ||
386 | |||
387 | de = (struct proc_dir_entry*) PDE(file->f_dentry->d_inode); | ||
388 | if (!de || !de->data) | ||
389 | return -ENXIO; | ||
390 | |||
391 | entry = (struct dgnc_proc_entry *) de->data; | ||
392 | if (!entry) | ||
393 | return -ENXIO; | ||
394 | |||
395 | /* Test for read permission */ | ||
396 | if (dgnc_test_perm(entry->mode, 4)) | ||
397 | return -EPERM; | ||
398 | |||
399 | res = count; | ||
400 | |||
401 | handler = entry->read_handler; | ||
402 | if (!handler) | ||
403 | return -ENXIO; | ||
404 | |||
405 | error = (*handler) (entry, OUTBOUND, file, buf, &res, ppos); | ||
406 | if (error) | ||
407 | return error; | ||
408 | |||
409 | return res; | ||
410 | } | ||
411 | |||
412 | |||
413 | static ssize_t dgnc_gen_proc_write(struct file *file, const char __user *buf, | ||
414 | size_t count, loff_t *ppos) | ||
415 | { | ||
416 | struct proc_dir_entry *de; | ||
417 | struct dgnc_proc_entry *entry; | ||
418 | int (*handler) (struct dgnc_proc_entry *table, int dir, struct file *filp, | ||
419 | const char __user *buffer, ssize_t *lenp, loff_t *ppos2); | ||
420 | ssize_t res; | ||
421 | ssize_t error; | ||
422 | |||
423 | de = (struct proc_dir_entry *) PDE(file->f_dentry->d_inode); | ||
424 | if (!de || !de->data) | ||
425 | return -ENXIO; | ||
426 | |||
427 | entry = (struct dgnc_proc_entry *) de->data; | ||
428 | if (!entry) | ||
429 | return -ENXIO; | ||
430 | |||
431 | /* Test for write permission */ | ||
432 | if (dgnc_test_perm(entry->mode, 2)) | ||
433 | return -EPERM; | ||
434 | |||
435 | res = count; | ||
436 | |||
437 | handler = entry->write_handler; | ||
438 | if (!handler) | ||
439 | return -ENXIO; | ||
440 | |||
441 | error = (*handler) (entry, INBOUND, file, buf, &res, ppos); | ||
442 | if (error) | ||
443 | return error; | ||
444 | |||
445 | return res; | ||
446 | } | ||
447 | |||
448 | |||
449 | static int dgnc_proc_chk_perm(struct inode *inode, int op) | ||
450 | { | ||
451 | return dgnc_test_perm(inode->i_mode, op); | ||
452 | } | ||
453 | |||
454 | |||
455 | /* | ||
456 | * Return what is (hopefully) useful information about the | ||
457 | * driver. | ||
458 | */ | ||
459 | static int dgnc_read_info(struct dgnc_proc_entry *table, int dir, struct file *filp, | ||
460 | char __user *buffer, ssize_t *lenp, loff_t *ppos) | ||
461 | { | ||
462 | static int done = 0; | ||
463 | static char buf[4096]; | ||
464 | char *p = buf; | ||
465 | |||
466 | DPR_PROC(("dgnc_proc_info\n")); | ||
467 | |||
468 | if (done) { | ||
469 | done = 0; | ||
470 | *lenp = 0; | ||
471 | return 0; | ||
472 | } | ||
473 | |||
474 | p += sprintf(p, "Driver:\t\t%s\n", DG_NAME); | ||
475 | p += sprintf(p, "\n"); | ||
476 | p += sprintf(p, "Debug:\t\t0x%x\n", dgnc_debug); | ||
477 | p += sprintf(p, "Sysfs Support:\t0x1\n"); | ||
478 | p += sprintf(p, "Rawreadok:\t0x%x\n", dgnc_rawreadok); | ||
479 | p += sprintf(p, "Max Boards:\t%d\n", MAXBOARDS); | ||
480 | p += sprintf(p, "Total Boards:\t%d\n", dgnc_NumBoards); | ||
481 | p += sprintf(p, "Poll rate:\t%dms\n", dgnc_poll_tick); | ||
482 | p += sprintf(p, "Poll counter:\t%ld\n", dgnc_poll_counter); | ||
483 | p += sprintf(p, "State:\t\t%s\n", dgnc_driver_state_text[dgnc_driver_state]); | ||
484 | |||
485 | if (copy_to_user(buffer, buf, (p - (char *) buf))) | ||
486 | return -EFAULT; | ||
487 | |||
488 | *lenp = p - (char *) buf; | ||
489 | *ppos += p - (char *) buf; | ||
490 | done = 1; | ||
491 | return 0; | ||
492 | } | ||
493 | |||
494 | |||
495 | /* | ||
496 | * When writing to the "info" entry point, I actually allow one | ||
497 | * to modify certain variables. This may be a sleazy overload | ||
498 | * of this /proc entry, but I don't want: | ||
499 | * | ||
500 | * a. to clutter /proc more than I have to | ||
501 | * b. to overload the "config" entry, which would be somewhat | ||
502 | * more natural | ||
503 | * c. necessarily advertise the fact this ability exists | ||
504 | * | ||
505 | * The continued support of this feature has not yet been | ||
506 | * guaranteed. | ||
507 | * | ||
508 | * Writing operates on a "state machine" principle. | ||
509 | * | ||
510 | * State 0: waiting for a symbol to start. Waiting for anything | ||
511 | * which isn't " ' = or whitespace. | ||
512 | * State 1: reading a symbol. If the character is a space, move | ||
513 | * to state 2. If =, move to state 3. If " or ', move | ||
514 | * to state 0. | ||
515 | * State 2: Waiting for =... suck whitespace. If anything other | ||
516 | * than whitespace, drop to state 0. | ||
517 | * State 3: Got =. Suck whitespace waiting for value to start. | ||
518 | * If " or ', go to state 4 (and remember which quote it | ||
519 | * was). Otherwise, go to state 5. | ||
520 | * State 4: Reading value, within quotes. Everything is added to | ||
521 | * value up until the matching quote. When you hit the | ||
522 | * matching quote, try to set the variable, then state 0. | ||
523 | * State 5: Reading value, outside quotes. Everything not " ' = | ||
524 | * or whitespace goes in value. Hitting one of the | ||
525 | * terminators tosses us back to state 0 after trying to | ||
526 | * set the variable. | ||
527 | */ | ||
528 | typedef enum { | ||
529 | INFO_NONE, INFO_INT, INFO_CHAR, INFO_SHORT, | ||
530 | INFO_LONG, INFO_PTR, INFO_STRING, INFO_END | ||
531 | } info_proc_var_val; | ||
532 | |||
533 | static struct { | ||
534 | char *name; | ||
535 | info_proc_var_val type; | ||
536 | int rw; /* 0=readonly */ | ||
537 | void *val_ptr; | ||
538 | } dgnc_info_vars[] = { | ||
539 | { "rawreadok", INFO_INT, 1, (void *) &dgnc_rawreadok }, | ||
540 | { "pollrate", INFO_INT, 1, (void *) &dgnc_poll_tick }, | ||
541 | { NULL, INFO_NONE, 0, NULL }, | ||
542 | { "debug", INFO_LONG, 1, (void *) &dgnc_debug }, | ||
543 | { NULL, INFO_END, 0, NULL } | ||
544 | }; | ||
545 | |||
546 | static void dgnc_set_info_var(char *name, char *val) | ||
547 | { | ||
548 | int i; | ||
549 | unsigned long newval; | ||
550 | unsigned char charval; | ||
551 | unsigned short shortval; | ||
552 | unsigned int intval; | ||
553 | |||
554 | for (i = 0; dgnc_info_vars[i].type != INFO_END; i++) { | ||
555 | if (dgnc_info_vars[i].name) | ||
556 | if (!strcmp(name, dgnc_info_vars[i].name)) | ||
557 | break; | ||
558 | } | ||
559 | |||
560 | if (dgnc_info_vars[i].type == INFO_END) | ||
561 | return; | ||
562 | if (dgnc_info_vars[i].rw == 0) | ||
563 | return; | ||
564 | if (dgnc_info_vars[i].val_ptr == NULL) | ||
565 | return; | ||
566 | |||
567 | newval = simple_strtoul(val, NULL, 0 ); | ||
568 | |||
569 | switch (dgnc_info_vars[i].type) { | ||
570 | case INFO_CHAR: | ||
571 | charval = newval & 0xff; | ||
572 | APR(("Modifying %s (%lx) <= 0x%02x (%d)\n", | ||
573 | name, (long)(dgnc_info_vars[i].val_ptr ), | ||
574 | charval, charval)); | ||
575 | *(uchar *)(dgnc_info_vars[i].val_ptr) = charval; | ||
576 | break; | ||
577 | case INFO_SHORT: | ||
578 | shortval = newval & 0xffff; | ||
579 | APR(("Modifying %s (%lx) <= 0x%04x (%d)\n", | ||
580 | name, (long)(dgnc_info_vars[i].val_ptr), | ||
581 | shortval, shortval)); | ||
582 | *(ushort *)(dgnc_info_vars[i].val_ptr) = shortval; | ||
583 | break; | ||
584 | case INFO_INT: | ||
585 | intval = newval & 0xffffffff; | ||
586 | APR(("Modifying %s (%lx) <= 0x%08x (%d)\n", | ||
587 | name, (long)(dgnc_info_vars[i].val_ptr), | ||
588 | intval, intval)); | ||
589 | *(uint *)(dgnc_info_vars[i].val_ptr) = intval; | ||
590 | break; | ||
591 | case INFO_LONG: | ||
592 | APR(("Modifying %s (%lx) <= 0x%lx (%ld)\n", | ||
593 | name, (long)(dgnc_info_vars[i].val_ptr), | ||
594 | newval, newval)); | ||
595 | *(ulong *)(dgnc_info_vars[i].val_ptr) = newval; | ||
596 | break; | ||
597 | case INFO_PTR: | ||
598 | case INFO_STRING: | ||
599 | case INFO_END: | ||
600 | case INFO_NONE: | ||
601 | default: | ||
602 | break; | ||
603 | } | ||
604 | } | ||
605 | |||
606 | static int dgnc_write_info(struct dgnc_proc_entry *table, int dir, struct file *filp, | ||
607 | const char __user *buffer, ssize_t *lenp, loff_t *ppos) | ||
608 | { | ||
609 | static int state = 0; | ||
610 | #define MAXSYM 255 | ||
611 | static int sympos, valpos; | ||
612 | static char sym[MAXSYM + 1]; | ||
613 | static char val[MAXSYM + 1]; | ||
614 | static int quotchar = 0; | ||
615 | |||
616 | int i; | ||
617 | |||
618 | long len; | ||
619 | #define INBUFLEN 256 | ||
620 | char inbuf[INBUFLEN]; | ||
621 | |||
622 | if (*ppos == 0) { | ||
623 | state = 0; | ||
624 | sympos = 0; sym[0] = 0; | ||
625 | valpos = 0; val[0] = 0; | ||
626 | quotchar = 0; | ||
627 | } | ||
628 | |||
629 | if ((!*lenp) || (dir != INBOUND)) { | ||
630 | *lenp = 0; | ||
631 | return 0; | ||
632 | } | ||
633 | |||
634 | len = *lenp; | ||
635 | |||
636 | if (len > INBUFLEN - 1) | ||
637 | len = INBUFLEN - 1; | ||
638 | |||
639 | if (copy_from_user(inbuf, buffer, len)) | ||
640 | return -EFAULT; | ||
641 | |||
642 | inbuf[len] = 0; | ||
643 | |||
644 | for (i = 0; i < len; i++) { | ||
645 | unsigned char c = inbuf[i]; | ||
646 | |||
647 | switch (state) { | ||
648 | case 0: | ||
649 | quotchar = sympos = valpos = sym[0] = val[0] = 0; | ||
650 | if (!isspace(c) && (c != '\"') && | ||
651 | (c != '\'') && (c != '=')) { | ||
652 | sym[sympos++] = c; | ||
653 | state = 1; | ||
654 | break; | ||
655 | } | ||
656 | break; | ||
657 | case 1: | ||
658 | if (isspace(c)) { | ||
659 | sym[sympos] = 0; | ||
660 | state = 2; | ||
661 | break; | ||
662 | } | ||
663 | if (c == '=') { | ||
664 | sym[sympos] = 0; | ||
665 | state = 3; | ||
666 | break; | ||
667 | } | ||
668 | if ((c == '\"' ) || ( c == '\'' )) { | ||
669 | state = 0; | ||
670 | break; | ||
671 | } | ||
672 | if (sympos < MAXSYM) sym[sympos++] = c; | ||
673 | break; | ||
674 | case 2: | ||
675 | if (isspace(c)) break; | ||
676 | if (c == '=') { | ||
677 | state = 3; | ||
678 | break; | ||
679 | } | ||
680 | if ((c != '\"') && (c != '\'')) { | ||
681 | quotchar = sympos = valpos = sym[0] = val[0] = 0; | ||
682 | sym[sympos++] = c; | ||
683 | state = 1; | ||
684 | break; | ||
685 | } | ||
686 | state = 0; | ||
687 | break; | ||
688 | case 3: | ||
689 | if (isspace(c)) break; | ||
690 | if (c == '=') { | ||
691 | state = 0; | ||
692 | break; | ||
693 | } | ||
694 | if ((c == '\"') || (c == '\'')) { | ||
695 | state = 4; | ||
696 | quotchar = c; | ||
697 | break; | ||
698 | } | ||
699 | val[valpos++] = c; | ||
700 | state = 5; | ||
701 | break; | ||
702 | case 4: | ||
703 | if (c == quotchar) { | ||
704 | val[valpos] = 0; | ||
705 | dgnc_set_info_var(sym, val); | ||
706 | state = 0; | ||
707 | break; | ||
708 | } | ||
709 | if (valpos < MAXSYM) val[valpos++] = c; | ||
710 | break; | ||
711 | case 5: | ||
712 | if (isspace(c) || (c == '\"') || | ||
713 | (c == '\'') || (c == '=')) { | ||
714 | val[valpos] = 0; | ||
715 | dgnc_set_info_var(sym, val); | ||
716 | state = 0; | ||
717 | break; | ||
718 | } | ||
719 | if (valpos < MAXSYM) val[valpos++] = c; | ||
720 | break; | ||
721 | default: | ||
722 | break; | ||
723 | } | ||
724 | } | ||
725 | |||
726 | *lenp = len; | ||
727 | *ppos += len; | ||
728 | |||
729 | return len; | ||
730 | } | ||
731 | |||
732 | |||
733 | /* | ||
734 | * Return mknod information for the driver's devices. | ||
735 | */ | ||
736 | static int dgnc_read_mknod(struct dgnc_proc_entry *table, int dir, struct file *filp, | ||
737 | char __user *buffer, ssize_t *lenp, loff_t *ppos) | ||
738 | { | ||
739 | static int done = 0; | ||
740 | static char buf[4096]; | ||
741 | char *p = buf; | ||
742 | int i = 0; | ||
743 | |||
744 | DPR_PROC(("dgnc_proc_info\n")); | ||
745 | |||
746 | if (done) { | ||
747 | done = 0; | ||
748 | *lenp = 0; | ||
749 | return 0; | ||
750 | } | ||
751 | |||
752 | DPR_PROC(("dgnc_proc_mknod\n")); | ||
753 | |||
754 | p += sprintf(p, "#\tCreate the management devices.\n"); | ||
755 | |||
756 | for (i = 0; i < MAXMGMTDEVICES; i++) { | ||
757 | char tmp[100]; | ||
758 | sprintf(tmp, "/dev/dg/dgnc/mgmt%d", i); | ||
759 | p += sprintf(p, "%s\t%d\t%d\t%d\n", | ||
760 | tmp, dgnc_Major, i, 1); | ||
761 | } | ||
762 | |||
763 | if (copy_to_user(buffer, buf, (p - (char *) buf))) | ||
764 | return -EFAULT; | ||
765 | |||
766 | *lenp = p - (char *) buf; | ||
767 | *ppos += p - (char *) buf; | ||
768 | done = 1; | ||
769 | return 0; | ||
770 | } | ||
771 | |||
772 | |||
773 | /* | ||
774 | * Return what is (hopefully) useful information about the specific board. | ||
775 | */ | ||
776 | static int dgnc_read_board_info(struct dgnc_proc_entry *table, int dir, struct file *filp, | ||
777 | char __user *buffer, ssize_t *lenp, loff_t *ppos) | ||
778 | { | ||
779 | struct board_t *brd; | ||
780 | static int done = 0; | ||
781 | static char buf[4096]; | ||
782 | char *p = buf; | ||
783 | char *name; | ||
784 | |||
785 | DPR_PROC(("dgnc_proc_brd_info\n")); | ||
786 | |||
787 | brd = (struct board_t *) table->data; | ||
788 | |||
789 | if (done || !brd || (brd->magic != DGNC_BOARD_MAGIC)) { | ||
790 | done = 0; | ||
791 | *lenp = 0; | ||
792 | return 0; | ||
793 | } | ||
794 | |||
795 | name = brd->name; | ||
796 | |||
797 | p += sprintf(p, "Board Name = %s\n", name); | ||
798 | if (brd->serial_num[0] == '\0') | ||
799 | p += sprintf(p, "Serial number = <UNKNOWN>\n"); | ||
800 | else | ||
801 | p += sprintf(p, "Serial number = %s\n", brd->serial_num); | ||
802 | |||
803 | p += sprintf(p, "Board Type = %d\n", brd->type); | ||
804 | p += sprintf(p, "Number of Ports = %d\n", brd->nasync); | ||
805 | |||
806 | /* | ||
807 | * report some things about the PCI bus that are important | ||
808 | * to some applications | ||
809 | */ | ||
810 | p += sprintf(p, "Vendor ID = 0x%x\n", brd->vendor); | ||
811 | p += sprintf(p, "Device ID = 0x%x\n", brd->device); | ||
812 | p += sprintf(p, "Subvendor ID = 0x%x\n", brd->subvendor); | ||
813 | p += sprintf(p, "Subdevice ID = 0x%x\n", brd->subdevice); | ||
814 | p += sprintf(p, "Bus = %d\n", brd->pci_bus); | ||
815 | p += sprintf(p, "Slot = %d\n", brd->pci_slot); | ||
816 | |||
817 | /* | ||
818 | * report the physical addresses assigned to us when we got | ||
819 | * registered | ||
820 | */ | ||
821 | p += sprintf(p, "Memory Base Address = 0x%lx\n", brd->membase); | ||
822 | p += sprintf(p, "Remapped Memory Base Address = 0x%p\n", brd->re_map_membase); | ||
823 | |||
824 | p += sprintf(p, "Current state of board = %s\n", dgnc_state_text[brd->state]); | ||
825 | p += sprintf(p, "Interrupt #: %d. Times interrupted: %ld\n", | ||
826 | brd->irq, brd->intr_count); | ||
827 | |||
828 | p += sprintf(p, "TX interrupts: %ld RX interrupts: %ld\n", | ||
829 | brd->intr_tx, brd->intr_rx); | ||
830 | p += sprintf(p, "Modem interrupts: %ld\n", brd->intr_modem); | ||
831 | |||
832 | p += sprintf(p, "Majors allocated to board = TTY: %d PR: %d\n", | ||
833 | brd->SerialDriver.major, brd->PrintDriver.major); | ||
834 | |||
835 | |||
836 | if (copy_to_user(buffer, buf, (p - (char *) buf))) | ||
837 | return -EFAULT; | ||
838 | |||
839 | *lenp = p - (char *) buf; | ||
840 | *ppos += p - (char *) buf; | ||
841 | done = 1; | ||
842 | return 0; | ||
843 | } | ||
844 | |||
845 | |||
846 | |||
847 | static int dgnc_read_board_vpd(struct dgnc_proc_entry *table, int dir, struct file *filp, | ||
848 | char __user *buffer, ssize_t *lenp, loff_t *ppos) | ||
849 | { | ||
850 | struct board_t *brd; | ||
851 | static int done = 0; | ||
852 | static char buf[4096]; | ||
853 | int i = 0, j = 0; | ||
854 | char *p = buf; | ||
855 | |||
856 | DPR_PROC(("dgnc_proc_brd_info\n")); | ||
857 | |||
858 | brd = (struct board_t *) table->data; | ||
859 | |||
860 | if (done || !brd || (brd->magic != DGNC_BOARD_MAGIC)) { | ||
861 | done = 0; | ||
862 | *lenp = 0; | ||
863 | return 0; | ||
864 | } | ||
865 | |||
866 | p += sprintf(p, "\n 0 1 2 3 4 5 6 7 8 9 A B C D E F ASCII\n"); | ||
867 | |||
868 | for (i = 0; i < 0x40 * 2; i++) { | ||
869 | j = i; | ||
870 | if (!(i % 16)) { | ||
871 | if (j > 0) { | ||
872 | p += sprintf(p, " "); | ||
873 | for (j = i - 16; j < i; j++) { | ||
874 | if (0x20 <= brd->vpd[j] && brd->vpd[j] <= 0x7e) | ||
875 | p += sprintf(p, "%c", brd->vpd[j]); | ||
876 | else | ||
877 | p += sprintf(p, "."); | ||
878 | } | ||
879 | p += sprintf(p, "\n"); | ||
880 | } | ||
881 | p += sprintf(p, "%04X ", i); | ||
882 | } | ||
883 | p += sprintf(p, "%02X ", brd->vpd[i]); | ||
884 | } | ||
885 | if (!(i % 16)) { | ||
886 | p += sprintf(p, " "); | ||
887 | for (j = i - 16; j < i; j++) { | ||
888 | if (0x20 <= brd->vpd[j] && brd->vpd[j] <= 0x7e) | ||
889 | p += sprintf(p, "%c", brd->vpd[j]); | ||
890 | else | ||
891 | p += sprintf(p, "."); | ||
892 | } | ||
893 | p += sprintf(p, "\n"); | ||
894 | } | ||
895 | |||
896 | p += sprintf(p, "\n"); | ||
897 | |||
898 | if (copy_to_user(buffer, buf, (p - (char *) buf))) | ||
899 | return -EFAULT; | ||
900 | |||
901 | *lenp = p - (char *) buf; | ||
902 | *ppos += p - (char *) buf; | ||
903 | done = 1; | ||
904 | return 0; | ||
905 | } | ||
906 | |||
907 | |||
908 | /* | ||
909 | * Return what is (hopefully) useful stats about the specific board's ttys | ||
910 | */ | ||
911 | static int dgnc_read_board_ttystats(struct dgnc_proc_entry *table, int dir, struct file *filp, | ||
912 | char __user *buffer, ssize_t *lenp, loff_t *ppos) | ||
913 | { | ||
914 | struct board_t *brd; | ||
915 | static int done = 0; | ||
916 | static char buf[4096]; | ||
917 | char *p = buf; | ||
918 | int i = 0; | ||
919 | |||
920 | DPR_PROC(("dgnc_proc_brd_info\n")); | ||
921 | |||
922 | brd = (struct board_t *) table->data; | ||
923 | |||
924 | if (done || !brd || (brd->magic != DGNC_BOARD_MAGIC)) { | ||
925 | done = 0; | ||
926 | *lenp = 0; | ||
927 | return 0; | ||
928 | } | ||
929 | |||
930 | /* Prepare the Header Labels */ | ||
931 | p += sprintf(p, "%2s %10s %23s %10s %9s\n", | ||
932 | "Ch", "Chars Rx", " Rx Par--Brk--Frm--Ovr", | ||
933 | "Chars Tx", "XON XOFF"); | ||
934 | |||
935 | for (i = 0; i < brd->nasync; i++) { | ||
936 | |||
937 | struct channel_t *ch = brd->channels[i]; | ||
938 | |||
939 | p += sprintf(p, "%2d ", i); | ||
940 | p += sprintf(p, "%10ld ", ch->ch_rxcount); | ||
941 | p += sprintf(p, " %4ld %4ld %4ld %4ld ", ch->ch_err_parity, | ||
942 | ch->ch_err_break, ch->ch_err_frame, ch->ch_err_overrun); | ||
943 | p += sprintf(p, "%10ld ", ch->ch_txcount); | ||
944 | p += sprintf(p, "%4ld %4ld ", ch->ch_xon_sends, ch->ch_xoff_sends); | ||
945 | |||
946 | p += sprintf(p, "\n"); | ||
947 | } | ||
948 | |||
949 | if (copy_to_user(buffer, buf, (p - (char *) buf))) | ||
950 | return -EFAULT; | ||
951 | |||
952 | *lenp = p - (char *) buf; | ||
953 | *ppos += p - (char *) buf; | ||
954 | done = 1; | ||
955 | return 0; | ||
956 | } | ||
957 | |||
958 | |||
959 | /* | ||
960 | * Return what is (hopefully) useful stats about the specific board's tty intrs | ||
961 | */ | ||
962 | static int dgnc_read_board_ttyintr(struct dgnc_proc_entry *table, int dir, struct file *filp, | ||
963 | char __user *buffer, ssize_t *lenp, loff_t *ppos) | ||
964 | { | ||
965 | struct board_t *brd; | ||
966 | static int done = 0; | ||
967 | static char buf[4096]; | ||
968 | char *p = buf; | ||
969 | int i = 0; | ||
970 | |||
971 | DPR_PROC(("dgnc_proc_brd_info\n")); | ||
972 | |||
973 | brd = (struct board_t *) table->data; | ||
974 | |||
975 | if (done || !brd || (brd->magic != DGNC_BOARD_MAGIC)) { | ||
976 | done = 0; | ||
977 | *lenp = 0; | ||
978 | return 0; | ||
979 | } | ||
980 | |||
981 | /* Prepare the Header Labels */ | ||
982 | p += sprintf(p, "%2s %14s %14s %14s\n", | ||
983 | "Ch", "TX interrupts", "RX interrupts", "Modem interrupts"); | ||
984 | |||
985 | for (i = 0; i < brd->nasync; i++) { | ||
986 | |||
987 | struct channel_t *ch = brd->channels[i]; | ||
988 | |||
989 | p += sprintf(p, "%2d ", i); | ||
990 | |||
991 | p += sprintf(p, " %14ld %14ld %14ld", | ||
992 | ch->ch_intr_tx, ch->ch_intr_rx, ch->ch_intr_modem); | ||
993 | |||
994 | p += sprintf(p, "\n"); | ||
995 | } | ||
996 | |||
997 | if (copy_to_user(buffer, buf, (p - (char *) buf))) | ||
998 | return -EFAULT; | ||
999 | |||
1000 | *lenp = p - (char *) buf; | ||
1001 | *ppos += p - (char *) buf; | ||
1002 | done = 1; | ||
1003 | return 0; | ||
1004 | } | ||
1005 | |||
1006 | |||
1007 | /* | ||
1008 | * Return what is (hopefully) useful flags about the specific board's ttys | ||
1009 | */ | ||
1010 | static int dgnc_read_board_ttyflags(struct dgnc_proc_entry *table, int dir, struct file *filp, | ||
1011 | char __user *buffer, ssize_t *lenp, loff_t *ppos) | ||
1012 | { | ||
1013 | struct board_t *brd; | ||
1014 | static int done = 0; | ||
1015 | static char buf[4096]; | ||
1016 | char *p = buf; | ||
1017 | int i = 0; | ||
1018 | |||
1019 | DPR_PROC(("dgnc_proc_brd_info\n")); | ||
1020 | |||
1021 | brd = (struct board_t *) table->data; | ||
1022 | |||
1023 | if (done || !brd || (brd->magic != DGNC_BOARD_MAGIC)) { | ||
1024 | done = 0; | ||
1025 | *lenp = 0; | ||
1026 | return 0; | ||
1027 | } | ||
1028 | |||
1029 | /* Prepare the Header Labels */ | ||
1030 | p += sprintf(p, "%2s %5s %5s %5s %5s %5s %10s Line Status Flags\n", | ||
1031 | "Ch", "CFlag", "IFlag", "OFlag", "LFlag", "DFlag", "Baud"); | ||
1032 | |||
1033 | for (i = 0; i < brd->nasync; i++) { | ||
1034 | |||
1035 | struct channel_t *ch = brd->channels[i]; | ||
1036 | |||
1037 | p += sprintf(p, "%2d ", i); | ||
1038 | p += sprintf(p, "%5x ", ch->ch_c_cflag); | ||
1039 | p += sprintf(p, "%5x ", ch->ch_c_iflag); | ||
1040 | p += sprintf(p, "%5x ", ch->ch_c_oflag); | ||
1041 | p += sprintf(p, "%5x ", ch->ch_c_lflag); | ||
1042 | p += sprintf(p, "%5x ", ch->ch_digi.digi_flags); | ||
1043 | p += sprintf(p, "%10d ", ch->ch_old_baud); | ||
1044 | |||
1045 | if (!ch->ch_open_count) { | ||
1046 | p += sprintf(p, " -- -- -- -- -- -- --") ; | ||
1047 | } else { | ||
1048 | p += sprintf(p, " op %s %s %s %s %s %s", | ||
1049 | (ch->ch_mostat & UART_MCR_RTS) ? "rs" : "--", | ||
1050 | (ch->ch_mistat & UART_MSR_CTS) ? "cs" : "--", | ||
1051 | (ch->ch_mostat & UART_MCR_DTR) ? "tr" : "--", | ||
1052 | (ch->ch_mistat & UART_MSR_DSR) ? "mr" : "--", | ||
1053 | (ch->ch_mistat & UART_MSR_DCD) ? "cd" : "--", | ||
1054 | (ch->ch_mistat & UART_MSR_RI) ? "ri" : "--"); | ||
1055 | } | ||
1056 | |||
1057 | p += sprintf(p, "\n"); | ||
1058 | } | ||
1059 | if (copy_to_user(buffer, buf, (p - (char *) buf))) | ||
1060 | return -EFAULT; | ||
1061 | |||
1062 | *lenp = p - (char *) buf; | ||
1063 | *ppos += p - (char *) buf; | ||
1064 | done = 1; | ||
1065 | return 0; | ||
1066 | } | ||
1067 | |||
1068 | |||
1069 | /* | ||
1070 | * Return mknod information for the board's devices. | ||
1071 | */ | ||
1072 | static int dgnc_read_board_mknod(struct dgnc_proc_entry *table, int dir, struct file *filp, | ||
1073 | char __user *buffer, ssize_t *lenp, loff_t *ppos) | ||
1074 | { | ||
1075 | struct board_t *brd; | ||
1076 | static int done = 0; | ||
1077 | static char buf[4096]; | ||
1078 | char str[MAXTTYNAMELEN]; | ||
1079 | char *p = buf; | ||
1080 | |||
1081 | DPR_PROC(("dgnc_proc_brd_info\n")); | ||
1082 | |||
1083 | brd = (struct board_t *) table->data; | ||
1084 | |||
1085 | if (done || !brd || (brd->magic != DGNC_BOARD_MAGIC)) { | ||
1086 | done = 0; | ||
1087 | *lenp = 0; | ||
1088 | return 0; | ||
1089 | } | ||
1090 | |||
1091 | /* | ||
1092 | * For each board, output the device information in | ||
1093 | * a handy table format... | ||
1094 | */ | ||
1095 | p += sprintf(p, "# Create the TTY and PR devices\n"); | ||
1096 | |||
1097 | /* TTY devices */ | ||
1098 | sprintf(str, "ttyn%d%%p", brd->boardnum + 1); | ||
1099 | p += sprintf(p, "%s\t\t\t%d\t%d\t%d\n", str, | ||
1100 | brd->dgnc_Serial_Major, 0, brd->maxports); | ||
1101 | |||
1102 | /* PR devices */ | ||
1103 | sprintf(str, "prn%d%%p", brd->boardnum + 1); | ||
1104 | p += sprintf(p, "%s\t\t\t%d\t%d\t%d\n", str, | ||
1105 | brd->dgnc_TransparentPrint_Major, 128, brd->maxports); | ||
1106 | |||
1107 | if (copy_to_user(buffer, buf, (p - (char *) buf))) | ||
1108 | return -EFAULT; | ||
1109 | |||
1110 | *lenp = p - (char *) buf; | ||
1111 | *ppos += p - (char *) buf; | ||
1112 | done = 1; | ||
1113 | return 0; | ||
1114 | } | ||
1115 | |||
1116 | |||
1117 | /* | ||
1118 | * Return what is (hopefully) useful information about the specific channel. | ||
1119 | */ | ||
1120 | static int dgnc_read_channel_info(struct dgnc_proc_entry *table, int dir, struct file *filp, | ||
1121 | char __user *buffer, ssize_t *lenp, loff_t *ppos) | ||
1122 | { | ||
1123 | struct channel_t *ch; | ||
1124 | static int done = 0; | ||
1125 | static char buf[4096]; | ||
1126 | char *p = buf; | ||
1127 | |||
1128 | DPR_PROC(("dgnc_proc_info\n")); | ||
1129 | |||
1130 | ch = (struct channel_t *) table->data; | ||
1131 | |||
1132 | if (done || !ch || (ch->magic != DGNC_CHANNEL_MAGIC)) { | ||
1133 | done = 0; | ||
1134 | *lenp = 0; | ||
1135 | return 0; | ||
1136 | } | ||
1137 | |||
1138 | p += sprintf(p, "Port number:\t\t%d\n", ch->ch_portnum); | ||
1139 | p += sprintf(p, "\n"); | ||
1140 | |||
1141 | /* Prepare the Header Labels */ | ||
1142 | p += sprintf(p, "%10s %23s %10s %9s\n", | ||
1143 | "Chars Rx", " Rx Par--Brk--Frm--Ovr", | ||
1144 | "Chars Tx", "XON XOFF"); | ||
1145 | p += sprintf(p, "%10ld ", ch->ch_rxcount); | ||
1146 | p += sprintf(p, " %4ld %4ld %4ld %4ld ", ch->ch_err_parity, | ||
1147 | ch->ch_err_break, ch->ch_err_frame, ch->ch_err_overrun); | ||
1148 | p += sprintf(p, "%10ld ", ch->ch_txcount); | ||
1149 | p += sprintf(p, "%4ld %4ld ", ch->ch_xon_sends, ch->ch_xoff_sends); | ||
1150 | p += sprintf(p, "\n\n"); | ||
1151 | |||
1152 | /* Prepare the Header Labels */ | ||
1153 | p += sprintf(p, "%5s %5s %5s %5s %5s %10s Line Status Flags\n", | ||
1154 | "CFlag", "IFlag", "OFlag", "LFlag", "DFlag", "Baud"); | ||
1155 | |||
1156 | p += sprintf(p, "%5x ", ch->ch_c_cflag); | ||
1157 | p += sprintf(p, "%5x ", ch->ch_c_iflag); | ||
1158 | p += sprintf(p, "%5x ", ch->ch_c_oflag); | ||
1159 | p += sprintf(p, "%5x ", ch->ch_c_lflag); | ||
1160 | p += sprintf(p, "%5x ", ch->ch_digi.digi_flags); | ||
1161 | p += sprintf(p, "%10d ", ch->ch_old_baud); | ||
1162 | if (!ch->ch_open_count) { | ||
1163 | p += sprintf(p, " -- -- -- -- -- -- --") ; | ||
1164 | } else { | ||
1165 | p += sprintf(p, " op %s %s %s %s %s %s", | ||
1166 | (ch->ch_mostat & UART_MCR_RTS) ? "rs" : "--", | ||
1167 | (ch->ch_mistat & UART_MSR_CTS) ? "cs" : "--", | ||
1168 | (ch->ch_mostat & UART_MCR_DTR) ? "tr" : "--", | ||
1169 | (ch->ch_mistat & UART_MSR_DSR) ? "mr" : "--", | ||
1170 | (ch->ch_mistat & UART_MSR_DCD) ? "cd" : "--", | ||
1171 | (ch->ch_mistat & UART_MSR_RI) ? "ri" : "--"); | ||
1172 | } | ||
1173 | p += sprintf(p, "\n\n"); | ||
1174 | |||
1175 | if (copy_to_user(buffer, buf, (p - (char *) buf))) | ||
1176 | return -EFAULT; | ||
1177 | |||
1178 | *lenp = p - (char *) buf; | ||
1179 | *ppos += p - (char *) buf; | ||
1180 | done = 1; | ||
1181 | return 0; | ||
1182 | } | ||
1183 | |||
1184 | |||
1185 | /* | ||
1186 | * Return mknod information for the board's devices. | ||
1187 | */ | ||
1188 | static int dgnc_read_channel_custom_ttyname(struct dgnc_proc_entry *table, int dir, struct file *filp, | ||
1189 | char __user *buffer, ssize_t *lenp, loff_t *ppos) | ||
1190 | { | ||
1191 | struct channel_t *ch; | ||
1192 | struct board_t *brd; | ||
1193 | static int done = 0; | ||
1194 | static char buf[4096]; | ||
1195 | char *p = buf; | ||
1196 | int cn; | ||
1197 | int bn; | ||
1198 | |||
1199 | DPR_PROC(("dgnc_proc_brd_info\n")); | ||
1200 | |||
1201 | ch = (struct channel_t *) table->data; | ||
1202 | |||
1203 | if (done || !ch || (ch->magic != DGNC_CHANNEL_MAGIC)) { | ||
1204 | done = 0; | ||
1205 | *lenp = 0; | ||
1206 | return 0; | ||
1207 | } | ||
1208 | |||
1209 | brd = ch->ch_bd; | ||
1210 | |||
1211 | if (done || !brd || (brd->magic != DGNC_BOARD_MAGIC)) { | ||
1212 | done = 0; | ||
1213 | *lenp = 0; | ||
1214 | return 0; | ||
1215 | } | ||
1216 | |||
1217 | bn = brd->boardnum; | ||
1218 | cn = ch->ch_portnum; | ||
1219 | |||
1220 | p += sprintf(p, "ttyn%d%c\n", bn + 1, 'a' + cn); | ||
1221 | |||
1222 | if (copy_to_user(buffer, buf, (p - (char *) buf))) | ||
1223 | return -EFAULT; | ||
1224 | |||
1225 | *lenp = p - (char *) buf; | ||
1226 | *ppos += p - (char *) buf; | ||
1227 | done = 1; | ||
1228 | return 0; | ||
1229 | } | ||
1230 | |||
1231 | |||
1232 | |||
1233 | |||
1234 | /* | ||
1235 | * Return mknod information for the board's devices. | ||
1236 | */ | ||
1237 | static int dgnc_read_channel_custom_prname(struct dgnc_proc_entry *table, int dir, struct file *filp, | ||
1238 | char __user *buffer, ssize_t *lenp, loff_t *ppos) | ||
1239 | { | ||
1240 | struct channel_t *ch; | ||
1241 | struct board_t *brd; | ||
1242 | static int done = 0; | ||
1243 | static char buf[4096]; | ||
1244 | char *p = buf; | ||
1245 | int cn; | ||
1246 | int bn; | ||
1247 | |||
1248 | DPR_PROC(("dgnc_proc_brd_info\n")); | ||
1249 | |||
1250 | ch = (struct channel_t *) table->data; | ||
1251 | |||
1252 | if (done || !ch || (ch->magic != DGNC_CHANNEL_MAGIC)) { | ||
1253 | done = 0; | ||
1254 | *lenp = 0; | ||
1255 | return 0; | ||
1256 | } | ||
1257 | |||
1258 | brd = ch->ch_bd; | ||
1259 | |||
1260 | if (done || !brd || (brd->magic != DGNC_BOARD_MAGIC)) { | ||
1261 | done = 0; | ||
1262 | *lenp = 0; | ||
1263 | return 0; | ||
1264 | } | ||
1265 | |||
1266 | bn = brd->boardnum; | ||
1267 | cn = ch->ch_portnum; | ||
1268 | |||
1269 | p += sprintf(p, "prn%d%c\n", bn + 1, 'a' + cn); | ||
1270 | |||
1271 | if (copy_to_user(buffer, buf, (p - (char *) buf))) | ||
1272 | return -EFAULT; | ||
1273 | |||
1274 | *lenp = p - (char *) buf; | ||
1275 | *ppos += p - (char *) buf; | ||
1276 | done = 1; | ||
1277 | return 0; | ||
1278 | } | ||
1279 | |||
1280 | |||
1281 | static int dgnc_open_channel_sniff(struct dgnc_proc_entry *table, int dir, struct file *filp, | ||
1282 | void *buffer, ssize_t *lenp, loff_t *ppos) | ||
1283 | { | ||
1284 | struct channel_t *ch; | ||
1285 | ulong lock_flags; | ||
1286 | |||
1287 | ch = (struct channel_t *) table->data; | ||
1288 | |||
1289 | if (!ch || (ch->magic != DGNC_CHANNEL_MAGIC)) | ||
1290 | return 0; | ||
1291 | |||
1292 | ch->ch_sniff_buf = dgnc_driver_kzmalloc(SNIFF_MAX, GFP_KERNEL); | ||
1293 | |||
1294 | DGNC_LOCK(ch->ch_lock, lock_flags); | ||
1295 | ch->ch_sniff_flags |= SNIFF_OPEN; | ||
1296 | DGNC_UNLOCK(ch->ch_lock, lock_flags); | ||
1297 | |||
1298 | return 0; | ||
1299 | } | ||
1300 | |||
1301 | static int dgnc_close_channel_sniff(struct dgnc_proc_entry *table, int dir, struct file *filp, | ||
1302 | void *buffer, ssize_t *lenp, loff_t *ppos) | ||
1303 | { | ||
1304 | struct channel_t *ch; | ||
1305 | ulong lock_flags; | ||
1306 | |||
1307 | ch = (struct channel_t *) table->data; | ||
1308 | |||
1309 | if (!ch || (ch->magic != DGNC_CHANNEL_MAGIC)) | ||
1310 | return 0; | ||
1311 | |||
1312 | DGNC_LOCK(ch->ch_lock, lock_flags); | ||
1313 | ch->ch_sniff_flags &= ~(SNIFF_OPEN); | ||
1314 | kfree(ch->ch_sniff_buf); | ||
1315 | DGNC_UNLOCK(ch->ch_lock, lock_flags); | ||
1316 | |||
1317 | return 0; | ||
1318 | } | ||
1319 | |||
1320 | |||
1321 | /* | ||
1322 | * Copy data from the monitoring buffer to the user, freeing space | ||
1323 | * in the monitoring buffer for more messages | ||
1324 | * | ||
1325 | */ | ||
1326 | static int dgnc_read_channel_sniff(struct dgnc_proc_entry *table, int dir, struct file *filp, | ||
1327 | char __user *buffer, ssize_t *lenp, loff_t *ppos) | ||
1328 | { | ||
1329 | struct channel_t *ch; | ||
1330 | int n; | ||
1331 | int r; | ||
1332 | int offset = 0; | ||
1333 | int res = 0; | ||
1334 | ssize_t rtn = 0; | ||
1335 | ulong lock_flags; | ||
1336 | |||
1337 | ch = (struct channel_t *) table->data; | ||
1338 | |||
1339 | if (!ch || (ch->magic != DGNC_CHANNEL_MAGIC)) { | ||
1340 | rtn = -ENXIO; | ||
1341 | goto done; | ||
1342 | } | ||
1343 | |||
1344 | /* | ||
1345 | * Wait for some data to appear in the buffer. | ||
1346 | */ | ||
1347 | DGNC_LOCK(ch->ch_lock, lock_flags); | ||
1348 | |||
1349 | for (;;) { | ||
1350 | n = (ch->ch_sniff_in - ch->ch_sniff_out) & SNIFF_MASK; | ||
1351 | |||
1352 | if (n != 0) | ||
1353 | break; | ||
1354 | |||
1355 | ch->ch_sniff_flags |= SNIFF_WAIT_DATA; | ||
1356 | |||
1357 | DGNC_UNLOCK(ch->ch_lock, lock_flags); | ||
1358 | |||
1359 | /* | ||
1360 | * Go to sleep waiting until the condition becomes true. | ||
1361 | */ | ||
1362 | rtn = wait_event_interruptible(ch->ch_sniff_wait, | ||
1363 | ((ch->ch_sniff_flags & SNIFF_WAIT_DATA) == 0)); | ||
1364 | |||
1365 | if (rtn) | ||
1366 | goto done; | ||
1367 | |||
1368 | DGNC_LOCK(ch->ch_lock, lock_flags); | ||
1369 | } | ||
1370 | |||
1371 | /* | ||
1372 | * Read whatever is there. | ||
1373 | */ | ||
1374 | |||
1375 | if (n > *lenp) | ||
1376 | n = *lenp; | ||
1377 | |||
1378 | res = n; | ||
1379 | |||
1380 | r = SNIFF_MAX - ch->ch_sniff_out; | ||
1381 | |||
1382 | if (r <= n) { | ||
1383 | DGNC_UNLOCK(ch->ch_lock, lock_flags); | ||
1384 | rtn = copy_to_user(buffer, ch->ch_sniff_buf + ch->ch_sniff_out, r); | ||
1385 | if (rtn) { | ||
1386 | rtn = -EFAULT; | ||
1387 | goto done; | ||
1388 | } | ||
1389 | |||
1390 | DGNC_LOCK(ch->ch_lock, lock_flags); | ||
1391 | |||
1392 | ch->ch_sniff_out = 0; | ||
1393 | n -= r; | ||
1394 | offset = r; | ||
1395 | } | ||
1396 | |||
1397 | DGNC_UNLOCK(ch->ch_lock, lock_flags); | ||
1398 | rtn = copy_to_user(buffer + offset, ch->ch_sniff_buf + ch->ch_sniff_out, n); | ||
1399 | if (rtn) { | ||
1400 | rtn = -EFAULT; | ||
1401 | goto done; | ||
1402 | } | ||
1403 | DGNC_LOCK(ch->ch_lock, lock_flags); | ||
1404 | |||
1405 | ch->ch_sniff_out += n; | ||
1406 | *ppos += res; | ||
1407 | rtn = res; | ||
1408 | // rtn = 0; | ||
1409 | |||
1410 | /* | ||
1411 | * Wakeup any thread waiting for buffer space. | ||
1412 | */ | ||
1413 | |||
1414 | if (ch->ch_sniff_flags & SNIFF_WAIT_SPACE) { | ||
1415 | ch->ch_sniff_flags &= ~SNIFF_WAIT_SPACE; | ||
1416 | wake_up_interruptible(&ch->ch_sniff_wait); | ||
1417 | } | ||
1418 | |||
1419 | DGNC_UNLOCK(ch->ch_lock, lock_flags); | ||
1420 | |||
1421 | done: | ||
1422 | return rtn; | ||
1423 | } | ||
1424 | |||
1425 | |||
1426 | /* | ||
1427 | * Register the basic /proc/dgnc files that appear whenever | ||
1428 | * the driver is loaded. | ||
1429 | */ | ||
1430 | void dgnc_proc_register_basic_prescan(void) | ||
1431 | { | ||
1432 | /* | ||
1433 | * Register /proc/dgnc | ||
1434 | */ | ||
1435 | ProcDGNC = proc_create("dgnc", (0700 | S_IFDIR), NULL, &dgnc_proc_file_ops); | ||
1436 | dgnc_register_proc_table(dgnc_table, ProcDGNC); | ||
1437 | } | ||
1438 | |||
1439 | |||
1440 | /* | ||
1441 | * Register the basic /proc/dgnc files that appear whenever | ||
1442 | * the driver is loaded. | ||
1443 | */ | ||
1444 | void dgnc_proc_register_basic_postscan(int board_num) | ||
1445 | { | ||
1446 | int i, j; | ||
1447 | char board[10]; | ||
1448 | sprintf(board, "%d", board_num); | ||
1449 | |||
1450 | /* Set proc board entry pointer */ | ||
1451 | dgnc_Board[board_num]->proc_entry_pointer = create_proc_entry(board, (0700 | S_IFDIR), ProcDGNC); | ||
1452 | |||
1453 | /* Create a new copy of the board_table... */ | ||
1454 | dgnc_Board[board_num]->dgnc_board_table = dgnc_driver_kzmalloc(sizeof(dgnc_board_table), | ||
1455 | GFP_KERNEL); | ||
1456 | |||
1457 | /* Now copy the default table into that memory */ | ||
1458 | memcpy(dgnc_Board[board_num]->dgnc_board_table, dgnc_board_table, sizeof(dgnc_board_table)); | ||
1459 | |||
1460 | /* Initialize semaphores in each table slot */ | ||
1461 | for (i = 0; i < 999; i++) { | ||
1462 | if (!dgnc_Board[board_num]->dgnc_board_table[i].magic) { | ||
1463 | break; | ||
1464 | } | ||
1465 | |||
1466 | init_MUTEX(&(dgnc_Board[board_num]->dgnc_board_table[i].excl_sem)); | ||
1467 | dgnc_Board[board_num]->dgnc_board_table[i].data = dgnc_Board[board_num]; | ||
1468 | |||
1469 | } | ||
1470 | |||
1471 | /* Register board table into proc */ | ||
1472 | dgnc_register_proc_table(dgnc_Board[board_num]->dgnc_board_table, | ||
1473 | dgnc_Board[board_num]->proc_entry_pointer); | ||
1474 | |||
1475 | /* | ||
1476 | * Add new entries for each port. | ||
1477 | */ | ||
1478 | for (i = 0; i < dgnc_Board[board_num]->nasync; i++) { | ||
1479 | |||
1480 | char channel[10]; | ||
1481 | sprintf(channel, "%d", i); | ||
1482 | |||
1483 | /* Set proc channel entry pointer */ | ||
1484 | dgnc_Board[board_num]->channels[i]->proc_entry_pointer = | ||
1485 | create_proc_entry(channel, (0700 | S_IFDIR), | ||
1486 | dgnc_Board[board_num]->proc_entry_pointer); | ||
1487 | |||
1488 | /* Create a new copy of the channel_table... */ | ||
1489 | dgnc_Board[board_num]->channels[i]->dgnc_channel_table = | ||
1490 | dgnc_driver_kzmalloc(sizeof(dgnc_channel_table), GFP_KERNEL); | ||
1491 | |||
1492 | /* Now copy the default table into that memory */ | ||
1493 | memcpy(dgnc_Board[board_num]->channels[i]->dgnc_channel_table, | ||
1494 | dgnc_channel_table, sizeof(dgnc_channel_table)); | ||
1495 | |||
1496 | /* Initialize semaphores in each table slot */ | ||
1497 | for (j = 0; j < 999; j++) { | ||
1498 | if (!dgnc_Board[board_num]->channels[i]->dgnc_channel_table[j].magic) { | ||
1499 | break; | ||
1500 | } | ||
1501 | |||
1502 | init_MUTEX(&(dgnc_Board[board_num]->channels[i]->dgnc_channel_table[j].excl_sem)); | ||
1503 | dgnc_Board[board_num]->channels[i]->dgnc_channel_table[j].data = | ||
1504 | dgnc_Board[board_num]->channels[i]; | ||
1505 | } | ||
1506 | |||
1507 | /* Register channel table into proc */ | ||
1508 | dgnc_register_proc_table(dgnc_Board[board_num]->channels[i]->dgnc_channel_table, | ||
1509 | dgnc_Board[board_num]->channels[i]->proc_entry_pointer); | ||
1510 | } | ||
1511 | } | ||
1512 | |||
1513 | |||
1514 | static void dgnc_remove_proc_entry(struct proc_dir_entry *pde) | ||
1515 | { | ||
1516 | if (!pde) { | ||
1517 | DPR_PROC(("dgnc_remove_proc_entry... NULL entry... not removing...\n")); | ||
1518 | return; | ||
1519 | } | ||
1520 | |||
1521 | remove_proc_entry(pde->name, pde->parent); | ||
1522 | } | ||
1523 | |||
1524 | |||
1525 | void dgnc_proc_unregister_all(void) | ||
1526 | { | ||
1527 | int i = 0, j = 0; | ||
1528 | |||
1529 | /* Walk each board, blowing away their proc entries... */ | ||
1530 | for (i = 0; i < dgnc_NumBoards; i++) { | ||
1531 | |||
1532 | /* Walk each channel, blowing away their proc entries... */ | ||
1533 | for (j = 0; j < dgnc_Board[i]->nasync; j++) { | ||
1534 | |||
1535 | dgnc_unregister_proc_table(dgnc_Board[i]->channels[j]->dgnc_channel_table, | ||
1536 | dgnc_Board[i]->channels[j]->proc_entry_pointer); | ||
1537 | dgnc_remove_proc_entry(dgnc_Board[i]->channels[j]->proc_entry_pointer); | ||
1538 | kfree(dgnc_Board[i]->channels[j]->dgnc_channel_table); | ||
1539 | } | ||
1540 | |||
1541 | dgnc_unregister_proc_table(dgnc_Board[i]->dgnc_board_table, | ||
1542 | dgnc_Board[i]->proc_entry_pointer); | ||
1543 | dgnc_remove_proc_entry(dgnc_Board[i]->proc_entry_pointer); | ||
1544 | kfree(dgnc_Board[i]->dgnc_board_table); | ||
1545 | } | ||
1546 | |||
1547 | /* Blow away the top proc entry */ | ||
1548 | dgnc_unregister_proc_table(dgnc_table, ProcDGNC); | ||
1549 | dgnc_remove_proc_entry(ProcDGNC); | ||
1550 | } | ||
diff --git a/drivers/staging/dgnc/dgnc_proc.h b/drivers/staging/dgnc/dgnc_proc.h deleted file mode 100644 index 19670e29d570..000000000000 --- a/drivers/staging/dgnc/dgnc_proc.h +++ /dev/null | |||
@@ -1,147 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright 2003 Digi International (www.digi.com) | ||
3 | * Scott H Kilau <Scott_Kilau at digi dot com> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2, or (at your option) | ||
8 | * any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the | ||
12 | * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR | ||
13 | * PURPOSE. See the GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | * | ||
19 | * NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!! | ||
20 | * | ||
21 | * | ||
22 | * $Id: dgnc_proc.h,v 1.1.1.1 2009/05/20 12:19:19 markh Exp $ | ||
23 | * | ||
24 | * Description: | ||
25 | * | ||
26 | * Describes the private structures used to manipulate the "special" | ||
27 | * proc constructs (not read-only) used by the Digi Neo software. | ||
28 | * The concept is borrowed heavily from the "sysctl" interface of | ||
29 | * the kernel. I decided not to use the structures and functions | ||
30 | * provided by the kernel for two reasons: | ||
31 | * | ||
32 | * 1. Due to the planned use of "/proc" in the Neo driver, many | ||
33 | * of the functions of the "sysctl" interface would go unused. | ||
34 | * A simpler interface will be easier to maintain. | ||
35 | * | ||
36 | * 2. I'd rather divorce our "added package" from the kernel internals. | ||
37 | * If the "sysctl" structures should change, I will be insulated | ||
38 | * from those changes. These "/proc" entries won't be under the | ||
39 | * "sys" tree anyway, so there is no need to maintain a strict | ||
40 | * dependence relationship. | ||
41 | * | ||
42 | * Author: | ||
43 | * | ||
44 | * Scott H Kilau | ||
45 | * | ||
46 | */ | ||
47 | |||
48 | #ifndef _DGNC_RW_PROC_H | ||
49 | #define _DGNC_RW_PROC_H | ||
50 | |||
51 | /* | ||
52 | * The list of DGNC entries with r/w capabilities. | ||
53 | * These magic numbers are used for identification purposes. | ||
54 | */ | ||
55 | enum { | ||
56 | DGNC_INFO = 1, /* Get info about the running module */ | ||
57 | DGNC_MKNOD = 2, /* Get info about driver devices */ | ||
58 | DGNC_BOARD_INFO = 3, /* Get info about the specific board */ | ||
59 | DGNC_BOARD_VPD = 4, /* Get info about the board's VPD */ | ||
60 | DGNC_BOARD_TTYSTATS = 5, /* Get info about the board's tty stats */ | ||
61 | DGNC_BOARD_TTYINTR = 6, /* Get info about the board's tty intrs */ | ||
62 | DGNC_BOARD_TTYFLAGS = 7, /* Get info about the board's tty flags */ | ||
63 | DGNC_BOARD_MKNOD = 8, /* Get info about board devices */ | ||
64 | DGNC_PORT_INFO = 9, /* Get info about the specific port */ | ||
65 | DGNC_PORT_SNIFF = 10, /* Sniff data in/out of specific port */ | ||
66 | DGNC_PORT_CUSTOM_TTYNAME = 11, /* Get info about UDEV tty name */ | ||
67 | DGNC_PORT_CUSTOM_PRNAME = 12, /* Get info about UDEV pr name */ | ||
68 | }; | ||
69 | |||
70 | /* | ||
71 | * Directions for proc handlers | ||
72 | */ | ||
73 | enum { | ||
74 | INBOUND = 1, /* Data being written to kernel */ | ||
75 | OUTBOUND = 2, /* Data being read from the kernel */ | ||
76 | }; | ||
77 | |||
78 | /* | ||
79 | * Each entry in a DGNC proc directory is described with a | ||
80 | * "dgnc_proc_entry" structure. A collection of these | ||
81 | * entries (in an array) represents the members associated | ||
82 | * with a particular "/proc" directory, and is referred to | ||
83 | * as a table. All "tables" are terminated by an entry with | ||
84 | * zeros for every member. | ||
85 | * | ||
86 | * The structure members are as follows: | ||
87 | * | ||
88 | * int magic -- ID number associated with this particular | ||
89 | * entry. Should be unique across all of | ||
90 | * DGNC. | ||
91 | * | ||
92 | * const char *name -- ASCII name associated with the /proc entry. | ||
93 | * | ||
94 | * mode_t mode -- File access permisssions for the /proc entry. | ||
95 | * | ||
96 | * dgnc_proc_entry *child -- When set, this entry refers to a directory, | ||
97 | * and points to the table which describes the | ||
98 | * entries in the subdirectory | ||
99 | * | ||
100 | * dgnc_proc_handler *open_handler -- When set, points to the fxn which | ||
101 | * does any "extra" open stuff. | ||
102 | * | ||
103 | * dgnc_proc_handler *close_handler -- When set, points to the fxn which | ||
104 | * does any "extra" close stuff. | ||
105 | * | ||
106 | * dgnc_proc_handler *read_handler -- When set, points to the fxn which | ||
107 | * handle outbound data flow | ||
108 | * | ||
109 | * dgnc_proc_handler *write_handler -- When set, points to the fxn which | ||
110 | * handles inbound data flow | ||
111 | * | ||
112 | * struct proc_dir_entry *de -- Pointer to the directory entry for this | ||
113 | * object once registered. Used to grab | ||
114 | * the handle of the object for | ||
115 | * unregistration | ||
116 | * | ||
117 | * void *data; When set, points to the parent structure | ||
118 | * | ||
119 | */ | ||
120 | |||
121 | struct dgnc_proc_entry { | ||
122 | int magic; /* Integer identifier */ | ||
123 | const char *name; /* ASCII identifier */ | ||
124 | mode_t mode; /* File access permissions */ | ||
125 | struct dgnc_proc_entry *child; /* Child pointer */ | ||
126 | |||
127 | int (*open_handler) (struct dgnc_proc_entry *table, int dir, struct file *filp, | ||
128 | void *buffer, ssize_t *lenp, loff_t *ppos); | ||
129 | int (*close_handler) (struct dgnc_proc_entry *table, int dir, struct file *filp, | ||
130 | void *buffer, ssize_t *lenp, loff_t *ppos); | ||
131 | int (*read_handler) (struct dgnc_proc_entry *table, int dir, struct file *filp, | ||
132 | char __user *buffer, ssize_t *lenp, loff_t *ppos); | ||
133 | int (*write_handler) (struct dgnc_proc_entry *table, int dir, struct file *filp, | ||
134 | const char __user *buffer, ssize_t *lenp, loff_t *ppos); | ||
135 | |||
136 | struct proc_dir_entry *de; /* proc entry pointer */ | ||
137 | struct semaphore excl_sem; /* Protects exclusive access var */ | ||
138 | int excl_cnt; /* Counts number of curr accesses */ | ||
139 | void *data; /* Allows storing a pointer to parent */ | ||
140 | }; | ||
141 | |||
142 | void dgnc_proc_register_basic_prescan(void); | ||
143 | void dgnc_proc_register_basic_postscan(int board_num); | ||
144 | void dgnc_proc_unregister_all(void); | ||
145 | |||
146 | |||
147 | #endif /* _DGNC_RW_PROC_H */ | ||
diff --git a/drivers/staging/dgnc/dgnc_sysfs.c b/drivers/staging/dgnc/dgnc_sysfs.c index 690d451e4821..f9c167e6e6e2 100644 --- a/drivers/staging/dgnc/dgnc_sysfs.c +++ b/drivers/staging/dgnc/dgnc_sysfs.c | |||
@@ -43,7 +43,6 @@ | |||
43 | #include <linux/kdev_t.h> | 43 | #include <linux/kdev_t.h> |
44 | 44 | ||
45 | #include "dgnc_driver.h" | 45 | #include "dgnc_driver.h" |
46 | #include "dgnc_proc.h" | ||
47 | #include "dgnc_mgmt.h" | 46 | #include "dgnc_mgmt.h" |
48 | 47 | ||
49 | 48 | ||