aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLidza Louina <lidza.louina@gmail.com>2013-08-15 10:28:22 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-08-15 13:14:29 -0400
commit35cf90459312fc3b6bc4bbf31aa5fe47b73922d4 (patch)
tree8c6a95a56e63da5833551aa20566ce7da3850bd7
parent41506a9f83c5ef8abda07d205c52b9e35d6d229a (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/Makefile2
-rw-r--r--drivers/staging/dgnc/dgnc_driver.c10
-rw-r--r--drivers/staging/dgnc/dgnc_mgmt.c1
-rw-r--r--drivers/staging/dgnc/dgnc_proc.c1550
-rw-r--r--drivers/staging/dgnc/dgnc_proc.h147
-rw-r--r--drivers/staging/dgnc/dgnc_sysfs.c1
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
5dgnc-objs := dgnc_cls.o dgnc_driver.o\ 5dgnc-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 */
57static struct proc_dir_entry *ProcDGNC;
58
59
60/* File operation declarations */
61static int dgnc_gen_proc_open(struct inode *, struct file *);
62static int dgnc_gen_proc_close(struct inode *, struct file *);
63static ssize_t dgnc_gen_proc_read(struct file *file, char __user *buf, size_t count, loff_t *ppos);
64static ssize_t dgnc_gen_proc_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos);
65
66static int dgnc_proc_chk_perm(struct inode *, int);
67
68static 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
78static struct inode_operations dgnc_proc_inode_ops =
79{
80 .permission = dgnc_proc_chk_perm
81};
82
83
84static void dgnc_register_proc_table(struct dgnc_proc_entry *, struct proc_dir_entry *);
85static void dgnc_unregister_proc_table(struct dgnc_proc_entry *, struct proc_dir_entry *);
86static void dgnc_remove_proc_entry(struct proc_dir_entry *pde);
87
88
89/* Stuff in /proc/ */
90static int dgnc_read_info(struct dgnc_proc_entry *table, int dir, struct file *filp,
91 char __user *buffer, ssize_t *lenp, loff_t *ppos);
92static 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
95static 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
98static 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>/ */
108static 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);
110static 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);
112static 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);
114static 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);
116static 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);
118static 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
121static 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> */
139static 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);
141static int dgnc_open_channel_sniff(struct dgnc_proc_entry *table, int dir, struct file *filp,
142 void *buffer, ssize_t *lenp, loff_t *ppos);
143static int dgnc_close_channel_sniff(struct dgnc_proc_entry *table, int dir, struct file *filp,
144 void *buffer, ssize_t *lenp, loff_t *ppos);
145static 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);
147static 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);
149static 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
152static 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 */
169static 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 */
190static 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 */
204static 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 */
263static 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
299static 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
338done:
339
340 return ret;
341}
342
343
344static 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
373done:
374 return 0;
375}
376
377
378static 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
413static 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
449static 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 */
459static 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 */
528typedef 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
533static 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
546static 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
606static 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 */
736static 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 */
776static 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
847static 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 */
911static 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 */
962static 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 */
1010static 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 */
1072static 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 */
1120static 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 */
1188static 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 */
1237static 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
1281static 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
1301static 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 */
1326static 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
1421done:
1422 return rtn;
1423}
1424
1425
1426/*
1427 * Register the basic /proc/dgnc files that appear whenever
1428 * the driver is loaded.
1429 */
1430void 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 */
1444void 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
1514static 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
1525void 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 */
55enum {
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 */
73enum {
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
121struct 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
142void dgnc_proc_register_basic_prescan(void);
143void dgnc_proc_register_basic_postscan(int board_num);
144void 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