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