5 * Copyright (C) 2004 ZyDAS Inc. All Rights Reserved.
6 * --------------------------------------------------------------------
10 * The contents of this file are subject to the Mozilla Public
11 * License Version 1.1 (the "License"); you may not use this file
12 * except in compliance with the License. You may obtain a copy of
13 * the License at http://www.mozilla.org/MPL/
15 * Software distributed under the License is distributed on an "AS
16 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
17 * implied. See the License for the specific language governing
18 * rights and limitations under the License.
20 * Alternatively, the contents of this file may be used under the
21 * terms of the GNU Public License version 2 (the "GPL"), in which
22 * case the provisions of the GPL are applicable instead of the
23 * above. If you wish to allow the use of your version of this file
24 * only under the terms of the GPL and not to allow others to use
25 * your version of this file under the MPL, indicate your decision
26 * by deleting the provisions above and replace them with the notice
27 * and other provisions required by the GPL. If you do not delete
28 * the provisions above, a recipient may use your version of this
29 * file under either the MPL or the GPL.
31 * -------------------------------------------------------------------- */
33 #include <linux/config.h>
38 /***************************************************************************/
39 /* /proc File System Interaface Support Functions */
40 /***************************************************************************/
42 static struct proc_dir_entry
*adapters_proc_dir
= 0;
44 /* externs from zd1205.c */
45 extern char zd1205_short_driver_name
[];
46 extern char zd1205_driver_version
[];
47 extern struct net_device_stats
*zd1205_get_stats(struct net_device
*dev
);
50 static void zd1205_proc_cleanup(void);
51 static unsigned char zd1205_init_proc_dir(void);
53 #define ADAPTERS_PROC_DIR "zd1205"
54 #define WRITE_BUF_MAX_LEN 20
55 #define READ_BUF_MAX_LEN 256
56 #define ZD1205_PE_LEN 25
58 #define bdp_drv_off(off) (unsigned long)(offsetof(struct zd1205_private, drv_stats.off))
59 #define bdp_prm_off(off) (unsigned long)(offsetof(struct zd1205_private, params.off))
61 typedef struct _zd1205_proc_entry
{
63 read_proc_t
*read_proc
;
64 write_proc_t
*write_proc
;
66 unsigned long offset
; /* offset into bdp. ~0 means no value, pass NULL. */
71 generic_read(char *page
, char **start
, off_t off
, int count
, int *eof
, int len
)
73 if (len
<= off
+ count
)
89 read_ulong(char *page
, char **start
, off_t off
,
90 int count
, int *eof
, unsigned long l
)
94 len
= sprintf(page
, "%lu\n", l
);
96 return generic_read(page
, start
, off
, count
, eof
, len
);
100 read_gen_ulong(char *page
, char **start
, off_t off
,
102 int count
, int *eof
, void *data
)
104 unsigned long val
= 0;
107 val
= *((unsigned long *) data
);
109 return read_ulong(page
, start
, off
, count
, eof
, val
);
114 read_hwaddr(char *page
, char **start
, off_t off
,
115 int count
, int *eof
, unsigned char *hwaddr
)
119 len
= sprintf(page
, "%02X:%02X:%02X:%02X:%02X:%02X\n",
120 hwaddr
[0], hwaddr
[1], hwaddr
[2],
121 hwaddr
[3], hwaddr
[4], hwaddr
[5]);
123 return generic_read(page
, start
, off
, count
, eof
, len
);
128 read_permanent_hwaddr(char *page
, char **start
, off_t off
,
129 int count
, int *eof
, void *data
)
131 struct zd1205_private
*macp
= data
;
132 unsigned char *hwaddr
= macp
->macAdr
;
134 return read_hwaddr(page
, start
, off
, count
, eof
, hwaddr
);
138 static zd1205_proc_entry zd1205_proc_list
[] = {
139 {"Permanent_HWaddr", read_permanent_hwaddr
, 0, 0},
146 read_info(char *page
, char **start
, off_t off
, int count
, int *eof
, void *data
)
149 struct zd1205_private
*macp
= data
;
150 zd1205_proc_entry
*pe
;
155 for (pe
= zd1205_proc_list
; pe
->name
[0]; pe
++) {
156 if (pe
->name
[0] == '\n') {
157 len
+= sprintf(page
+ len
, "\n");
162 if ((len
+ READ_BUF_MAX_LEN
+ ZD1205_PE_LEN
+ 1) >=
166 if (pe
->offset
!= ~0)
167 val
= ((char *) macp
) + pe
->offset
;
171 len
+= sprintf(page
+ len
, "%-"
172 __MODULE_STRING(ZD1205_PE_LEN
)
174 len
+= pe
->read_proc(page
+ len
, start
, 0,
175 READ_BUF_MAX_LEN
+ 1, &tmp
, val
);
179 return generic_read(page
, start
, off
, count
, eof
, len
);
183 static struct proc_dir_entry
*
184 create_proc_rw(char *name
, void *data
, struct proc_dir_entry
*parent
,
185 read_proc_t
* read_proc
, write_proc_t
* write_proc
)
187 struct proc_dir_entry
*pdep
;
188 mode_t mode
= S_IFREG
;
196 } else if (read_proc
) {
200 if (!(pdep
= create_proc_entry(name
, mode
, parent
)))
203 pdep
->read_proc
= read_proc
;
204 pdep
->write_proc
= write_proc
;
211 zd1205_remove_proc_subdir(struct zd1205_private
*macp
, char *name
)
213 zd1205_proc_entry
*pe
;
217 /* If our root /proc dir was not created, there is nothing to remove */
218 if (adapters_proc_dir
== NULL
) {
222 len
= strlen(macp
->ifname
);
223 strncpy(info
, macp
->ifname
, sizeof (info
));
224 strncat(info
+ len
, ".info", sizeof (info
) - len
);
226 if (macp
->proc_parent
) {
227 for (pe
= zd1205_proc_list
; pe
->name
[0]; pe
++) {
228 if (pe
->name
[0] == '\n')
231 remove_proc_entry(pe
->name
, macp
->proc_parent
);
234 remove_proc_entry(macp
->ifname
, adapters_proc_dir
);
235 macp
->proc_parent
= NULL
;
238 remove_proc_entry(info
, adapters_proc_dir
);
240 /* try to remove the main /proc dir, if it's empty */
241 zd1205_proc_cleanup();
246 zd1205_create_proc_subdir(struct zd1205_private
*macp
)
248 struct proc_dir_entry
*dev_dir
;
249 zd1205_proc_entry
*pe
;
254 /* create the main /proc dir if needed */
255 if (!adapters_proc_dir
) {
256 if (!zd1205_init_proc_dir())
260 strncpy(info
, macp
->ifname
, sizeof (info
));
262 strncat(info
+ len
, ".info", sizeof (info
) - len
);
265 if (!(create_proc_rw(info
, macp
, adapters_proc_dir
, read_info
, 0))) {
266 zd1205_proc_cleanup();
270 dev_dir
= create_proc_entry(macp
->ifname
, S_IFDIR
,
272 macp
->proc_parent
= dev_dir
;
275 zd1205_remove_proc_subdir(macp
, macp
->ifname
);
279 for (pe
= zd1205_proc_list
; pe
->name
[0]; pe
++) {
280 if (pe
->name
[0] == '\n')
283 if (pe
->offset
!= ~0)
284 data
= ((char *) macp
) + pe
->offset
;
288 if (!(create_proc_rw(pe
->name
, data
, dev_dir
,
289 pe
->read_proc
, pe
->write_proc
))) {
290 zd1205_remove_proc_subdir(macp
, macp
->ifname
);
298 /****************************************************************************
299 * Name: zd1205_init_proc_dir
301 * Description: This routine creates the top-level /proc directory for the
302 * driver in /proc/net
306 * Returns: true on success, false on fail
308 ***************************************************************************/
310 zd1205_init_proc_dir(void)
314 /* first check if adapters_proc_dir already exists */
315 len
= strlen(ADAPTERS_PROC_DIR
);
316 for (adapters_proc_dir
= proc_net
->subdir
;
317 adapters_proc_dir
; adapters_proc_dir
= adapters_proc_dir
->next
) {
319 if ((adapters_proc_dir
->namelen
== len
) &&
320 (!memcmp(adapters_proc_dir
->name
, ADAPTERS_PROC_DIR
, len
)))
324 if (!adapters_proc_dir
)
326 create_proc_entry(ADAPTERS_PROC_DIR
, S_IFDIR
, proc_net
);
328 if (!adapters_proc_dir
)
335 /****************************************************************************
336 * Name: zd1205_proc_cleanup
338 * Description: This routine clears the top-level /proc directory, if empty.
344 ***************************************************************************/
346 zd1205_proc_cleanup(void)
348 struct proc_dir_entry
*de
;
350 if (adapters_proc_dir
== NULL
) {
354 /* check if subdir list is empty before removing adapters_proc_dir */
355 for (de
= adapters_proc_dir
->subdir
; de
; de
= de
->next
) {
356 /* ignore . and .. */
357 if (*(de
->name
) != '.')
364 remove_proc_entry(ADAPTERS_PROC_DIR
, proc_net
);
365 adapters_proc_dir
= NULL
;
368 #endif /* CONFIG_PROC_FS */