Merge branch 'for-linus' of git://git390.osdl.marist.edu/pub/scm/linux-2.6
[linux-2.6] / net / wanrouter / wanproc.c
1 /*****************************************************************************
2 * wanproc.c     WAN Router Module. /proc filesystem interface.
3 *
4 *               This module is completely hardware-independent and provides
5 *               access to the router using Linux /proc filesystem.
6 *
7 * Author:       Gideon Hack
8 *
9 * Copyright:    (c) 1995-1999 Sangoma Technologies Inc.
10 *
11 *               This program is free software; you can redistribute it and/or
12 *               modify it under the terms of the GNU General Public License
13 *               as published by the Free Software Foundation; either version
14 *               2 of the License, or (at your option) any later version.
15 * ============================================================================
16 * Jun 02, 1999  Gideon Hack     Updates for Linux 2.2.X kernels.
17 * Jun 29, 1997  Alan Cox        Merged with 1.0.3 vendor code
18 * Jan 29, 1997  Gene Kozin      v1.0.1. Implemented /proc read routines
19 * Jan 30, 1997  Alan Cox        Hacked around for 2.1
20 * Dec 13, 1996  Gene Kozin      Initial version (based on Sangoma's WANPIPE)
21 *****************************************************************************/
22
23 #include <linux/init.h>         /* __initfunc et al. */
24 #include <linux/stddef.h>       /* offsetof(), etc. */
25 #include <linux/errno.h>        /* return codes */
26 #include <linux/kernel.h>
27 #include <linux/module.h>
28 #include <linux/wanrouter.h>    /* WAN router API definitions */
29 #include <linux/seq_file.h>
30 #include <linux/smp_lock.h>
31
32 #include <asm/io.h>
33
34 #define PROC_STATS_FORMAT "%30s: %12lu\n"
35
36 /****** Defines and Macros **************************************************/
37
38 #define PROT_DECODE(prot) ((prot == WANCONFIG_FR) ? " FR" :\
39                               (prot == WANCONFIG_X25) ? " X25" : \
40                                  (prot == WANCONFIG_PPP) ? " PPP" : \
41                                     (prot == WANCONFIG_CHDLC) ? " CHDLC": \
42                                        (prot == WANCONFIG_MPPP) ? " MPPP" : \
43                                            " Unknown" )
44
45 /****** Function Prototypes *************************************************/
46
47 #ifdef CONFIG_PROC_FS
48
49 /* Miscellaneous */
50
51 /*
52  *      Structures for interfacing with the /proc filesystem.
53  *      Router creates its own directory /proc/net/router with the folowing
54  *      entries:
55  *      config          device configuration
56  *      status          global device statistics
57  *      <device>        entry for each WAN device
58  */
59
60 /*
61  *      Generic /proc/net/router/<file> file and inode operations
62  */
63
64 /*
65  *      /proc/net/router
66  */
67
68 static struct proc_dir_entry *proc_router;
69
70 /* Strings */
71
72 /*
73  *      Interface functions
74  */
75
76 /****** Proc filesystem entry points ****************************************/
77
78 /*
79  *      Iterator
80  */
81 static void *r_start(struct seq_file *m, loff_t *pos)
82 {
83         struct wan_device *wandev;
84         loff_t l = *pos;
85
86         lock_kernel();
87         if (!l--)
88                 return SEQ_START_TOKEN;
89         for (wandev = wanrouter_router_devlist; l-- && wandev;
90              wandev = wandev->next)
91                 ;
92         return wandev;
93 }
94
95 static void *r_next(struct seq_file *m, void *v, loff_t *pos)
96 {
97         struct wan_device *wandev = v;
98         (*pos)++;
99         return (v == SEQ_START_TOKEN) ? wanrouter_router_devlist : wandev->next;
100 }
101
102 static void r_stop(struct seq_file *m, void *v)
103 {
104         unlock_kernel();
105 }
106
107 static int config_show(struct seq_file *m, void *v)
108 {
109         struct wan_device *p = v;
110         if (v == SEQ_START_TOKEN) {
111                 seq_puts(m, "Device name    | port |IRQ|DMA|  mem.addr  |"
112                             "mem.size|option1|option2|option3|option4\n");
113                 return 0;
114         }
115         if (!p->state)
116                 return 0;
117         seq_printf(m, "%-15s|0x%-4X|%3u|%3u| 0x%-8lX |0x%-6X|%7u|%7u|%7u|%7u\n",
118                         p->name, p->ioport, p->irq, p->dma, p->maddr, p->msize,
119                         p->hw_opt[0], p->hw_opt[1], p->hw_opt[2], p->hw_opt[3]);
120         return 0;
121 }
122
123 static int status_show(struct seq_file *m, void *v)
124 {
125         struct wan_device *p = v;
126         if (v == SEQ_START_TOKEN) {
127                 seq_puts(m, "Device name    |protocol|station|interface|"
128                             "clocking|baud rate| MTU |ndev|link state\n");
129                 return 0;
130         }
131         if (!p->state)
132                 return 0;
133         seq_printf(m, "%-15s|%-8s| %-7s| %-9s|%-8s|%9u|%5u|%3u |",
134                 p->name,
135                 PROT_DECODE(p->config_id),
136                 p->config_id == WANCONFIG_FR ?
137                         (p->station ? "Node" : "CPE") :
138                         (p->config_id == WANCONFIG_X25 ?
139                         (p->station ? "DCE" : "DTE") :
140                         ("N/A")),
141                 p->interface ? "V.35" : "RS-232",
142                 p->clocking ? "internal" : "external",
143                 p->bps,
144                 p->mtu,
145                 p->ndev);
146
147         switch (p->state) {
148         case WAN_UNCONFIGURED:
149                 seq_printf(m, "%-12s\n", "unconfigured");
150                 break;
151         case WAN_DISCONNECTED:
152                 seq_printf(m, "%-12s\n", "disconnected");
153                 break;
154         case WAN_CONNECTING:
155                 seq_printf(m, "%-12s\n", "connecting");
156                 break;
157         case WAN_CONNECTED:
158                 seq_printf(m, "%-12s\n", "connected");
159                 break;
160         default:
161                 seq_printf(m, "%-12s\n", "invalid");
162                 break;
163         }
164         return 0;
165 }
166
167 static struct seq_operations config_op = {
168         .start  = r_start,
169         .next   = r_next,
170         .stop   = r_stop,
171         .show   = config_show,
172 };
173
174 static struct seq_operations status_op = {
175         .start  = r_start,
176         .next   = r_next,
177         .stop   = r_stop,
178         .show   = status_show,
179 };
180
181 static int config_open(struct inode *inode, struct file *file)
182 {
183         return seq_open(file, &config_op);
184 }
185
186 static int status_open(struct inode *inode, struct file *file)
187 {
188         return seq_open(file, &status_op);
189 }
190
191 static const struct file_operations config_fops = {
192         .owner   = THIS_MODULE,
193         .open    = config_open,
194         .read    = seq_read,
195         .llseek  = seq_lseek,
196         .release = seq_release,
197 };
198
199 static const struct file_operations status_fops = {
200         .owner   = THIS_MODULE,
201         .open    = status_open,
202         .read    = seq_read,
203         .llseek  = seq_lseek,
204         .release = seq_release,
205 };
206
207 static int wandev_show(struct seq_file *m, void *v)
208 {
209         struct wan_device *wandev = m->private;
210
211         if (wandev->magic != ROUTER_MAGIC)
212                 return 0;
213
214         if (!wandev->state) {
215                 seq_puts(m, "device is not configured!\n");
216                 return 0;
217         }
218
219         /* Update device statistics */
220         if (wandev->update) {
221                 int err = wandev->update(wandev);
222                 if (err == -EAGAIN) {
223                         seq_puts(m, "Device is busy!\n");
224                         return 0;
225                 }
226                 if (err) {
227                         seq_puts(m, "Device is not configured!\n");
228                         return 0;
229                 }
230         }
231
232         seq_printf(m, PROC_STATS_FORMAT,
233                 "total packets received", wandev->stats.rx_packets);
234         seq_printf(m, PROC_STATS_FORMAT,
235                 "total packets transmitted", wandev->stats.tx_packets);
236         seq_printf(m, PROC_STATS_FORMAT,
237                 "total bytes received", wandev->stats.rx_bytes);
238         seq_printf(m, PROC_STATS_FORMAT,
239                 "total bytes transmitted", wandev->stats.tx_bytes);
240         seq_printf(m, PROC_STATS_FORMAT,
241                 "bad packets received", wandev->stats.rx_errors);
242         seq_printf(m, PROC_STATS_FORMAT,
243                 "packet transmit problems", wandev->stats.tx_errors);
244         seq_printf(m, PROC_STATS_FORMAT,
245                 "received frames dropped", wandev->stats.rx_dropped);
246         seq_printf(m, PROC_STATS_FORMAT,
247                 "transmit frames dropped", wandev->stats.tx_dropped);
248         seq_printf(m, PROC_STATS_FORMAT,
249                 "multicast packets received", wandev->stats.multicast);
250         seq_printf(m, PROC_STATS_FORMAT,
251                 "transmit collisions", wandev->stats.collisions);
252         seq_printf(m, PROC_STATS_FORMAT,
253                 "receive length errors", wandev->stats.rx_length_errors);
254         seq_printf(m, PROC_STATS_FORMAT,
255                 "receiver overrun errors", wandev->stats.rx_over_errors);
256         seq_printf(m, PROC_STATS_FORMAT,
257                 "CRC errors", wandev->stats.rx_crc_errors);
258         seq_printf(m, PROC_STATS_FORMAT,
259                 "frame format errors (aborts)", wandev->stats.rx_frame_errors);
260         seq_printf(m, PROC_STATS_FORMAT,
261                 "receiver fifo overrun", wandev->stats.rx_fifo_errors);
262         seq_printf(m, PROC_STATS_FORMAT,
263                 "receiver missed packet", wandev->stats.rx_missed_errors);
264         seq_printf(m, PROC_STATS_FORMAT,
265                 "aborted frames transmitted", wandev->stats.tx_aborted_errors);
266         return 0;
267 }
268
269 static int wandev_open(struct inode *inode, struct file *file)
270 {
271         return single_open(file, wandev_show, PDE(inode)->data);
272 }
273
274 static const struct file_operations wandev_fops = {
275         .owner   = THIS_MODULE,
276         .open    = wandev_open,
277         .read    = seq_read,
278         .llseek  = seq_lseek,
279         .release = single_release,
280         .ioctl   = wanrouter_ioctl,
281 };
282
283 /*
284  *      Initialize router proc interface.
285  */
286
287 int __init wanrouter_proc_init(void)
288 {
289         struct proc_dir_entry *p;
290         proc_router = proc_mkdir(ROUTER_NAME, proc_net);
291         if (!proc_router)
292                 goto fail;
293
294         p = create_proc_entry("config", S_IRUGO, proc_router);
295         if (!p)
296                 goto fail_config;
297         p->proc_fops = &config_fops;
298         p = create_proc_entry("status", S_IRUGO, proc_router);
299         if (!p)
300                 goto fail_stat;
301         p->proc_fops = &status_fops;
302         return 0;
303 fail_stat:
304         remove_proc_entry("config", proc_router);
305 fail_config:
306         remove_proc_entry(ROUTER_NAME, proc_net);
307 fail:
308         return -ENOMEM;
309 }
310
311 /*
312  *      Clean up router proc interface.
313  */
314
315 void wanrouter_proc_cleanup(void)
316 {
317         remove_proc_entry("config", proc_router);
318         remove_proc_entry("status", proc_router);
319         remove_proc_entry(ROUTER_NAME, proc_net);
320 }
321
322 /*
323  *      Add directory entry for WAN device.
324  */
325
326 int wanrouter_proc_add(struct wan_device* wandev)
327 {
328         if (wandev->magic != ROUTER_MAGIC)
329                 return -EINVAL;
330
331         wandev->dent = create_proc_entry(wandev->name, S_IRUGO, proc_router);
332         if (!wandev->dent)
333                 return -ENOMEM;
334         wandev->dent->proc_fops = &wandev_fops;
335         wandev->dent->data      = wandev;
336         return 0;
337 }
338
339 /*
340  *      Delete directory entry for WAN device.
341  */
342 int wanrouter_proc_delete(struct wan_device* wandev)
343 {
344         if (wandev->magic != ROUTER_MAGIC)
345                 return -EINVAL;
346         remove_proc_entry(wandev->name, proc_router);
347         return 0;
348 }
349
350 #else
351
352 /*
353  *      No /proc - output stubs
354  */
355
356 int __init wanrouter_proc_init(void)
357 {
358         return 0;
359 }
360
361 void wanrouter_proc_cleanup(void)
362 {
363 }
364
365 int wanrouter_proc_add(struct wan_device *wandev)
366 {
367         return 0;
368 }
369
370 int wanrouter_proc_delete(struct wan_device *wandev)
371 {
372         return 0;
373 }
374
375 #endif
376
377 /*
378  *      End
379  */
380