1 /*
2 * Aironet 4500 /proc interface
3 *
4 * Elmer Joandi, Januar 1999
5 * Copyright GPL
6 *
7 *
8 * Revision 0.1 ,started 30.12.1998
9 *
10 *
11 */
12 #include <linux/module.h>
13 #include <linux/init.h>
14 #include <linux/config.h>
15 #include <linux/kernel.h>
16
17 #include <linux/version.h>
18
19 #include <linux/sched.h>
20 #include <linux/ptrace.h>
21 #include <linux/slab.h>
22 #include <linux/string.h>
23 #include <linux/timer.h>
24 #include <linux/interrupt.h>
25 #include <linux/in.h>
26 #include <asm/io.h>
27 #include <asm/system.h>
28 #include <asm/bitops.h>
29
30 #include <linux/netdevice.h>
31 #include <linux/etherdevice.h>
32 #include <linux/skbuff.h>
33 #include <linux/if_arp.h>
34 #include <linux/ioport.h>
35
36
37 #ifdef CONFIG_PROC_FS
38
39 #ifdef CONFIG_PROC_FS
40 #include <linux/sysctl.h>
41 #else
42 #error awc driver needs CONFIG_PROC_FS
43 #endif
44
45
46 #include "aironet4500.h"
47 #include "aironet4500_rid.c"
48
49
50 #define AWC_STR_SIZE 0x2ff0
51 #define DEV_AWC_INFO 1
52 #define DEV_AWC 1
53
54 struct awc_proc_private{
55 struct ctl_table_header * sysctl_header;
56 struct ctl_table * proc_table;
57 struct ctl_table proc_table_device_root[2];
58 struct ctl_table proc_table_sys_root[2];
59 char proc_name[10];
60 };
61 static char awc_drive_info[AWC_STR_SIZE]="Zcom \n\0";
62 static char awc_proc_buff[AWC_STR_SIZE];
63 static int awc_int_buff;
64 static struct awc_proc_private awc_proc_priv[MAX_AWCS];
65
66 extern int awc_proc_unset_device(int device_number);
67
awc_proc_format_array(int write,char * buff,size_t * len,struct awc_rid_dir * rid_dir,struct aironet4500_RID * rid)68 int awc_proc_format_array(int write,char * buff, size_t * len, struct awc_rid_dir * rid_dir, struct aironet4500_RID * rid){
69
70 u8 * data = rid_dir->buff + rid->offset;
71 int pos = 0;
72 int null_past = 0;
73 int hex = ((rid->mask == 0xff) && (rid->value == 0x0 ));
74 int string = ((rid->mask == 0) && (rid->value == 0 ));
75 u32 val =0;
76 int bytes = (rid->bits / 8);
77 int ch =0;
78 int i,k;
79 int array_len = rid->array;
80 int nullX = 0;
81
82
83 AWC_ENTRY_EXIT_DEBUG("awc_proc_format_array");
84
85 if (rid->bits %8 ) bytes +=1;
86
87 if (bytes > 4 && rid->array == 1){
88 array_len = bytes;
89 bytes = 1;
90 hex = 1;
91 };
92 if (bytes < 1 || bytes > 4){
93 printk(KERN_ERR " weird number of bytes %d in aironet rid \n",bytes);
94 return -1;
95 };
96 DEBUG(0x20000,"awc proc array bytes %d",bytes);
97 DEBUG(0x20000," hex %d",hex);
98 DEBUG(0x20000," string %d",string);
99
100 DEBUG(0x20000," array_len %d \n",array_len);
101 DEBUG(0x20000," offset %d \n",rid->offset);
102
103 if (!write){
104 for (i=0; i < array_len ; i++){
105
106 if (bytes <= 1 ) val = data[i*bytes];
107 else if (bytes <= 2 ) val = *((u16 *)&data[i*bytes]);
108 else if (bytes <= 4 ) val = *((u32 *)&data[i*bytes]);
109
110 if (rid->null_terminated && !val)
111 null_past =1;
112
113 if (hex && !string)
114 for (k=0; k <bytes; k++)
115 pos += sprintf(buff+pos, "%02x",(unsigned char ) data[i*bytes +k]);
116 else if (string)
117 pos += sprintf(buff+pos, "%c",val);
118 else pos += sprintf(buff+pos, "%c",val);
119
120 DEBUG(0x20000, "awcproc %x %x \n",data[i], val);
121 };
122
123 } else {
124 for (i=0; i < array_len ; i++){
125
126 DEBUG(0x20000, "awcproc %x %x \n",data[i], buff[i]);
127
128 if (hex && ! string){
129
130 val = 0;
131
132 for (k=0; k < bytes; k++){
133 val <<= 8;
134 ch = *(buff + 2*i*bytes +k + nullX);
135 if (ch >= '0' && ch <='9')
136 ch -= '0';
137 if (ch >= 'A' && ch <='F')
138 ch -= 'A'+ 0xA;
139 if (ch >= 'a' && ch <='f')
140 ch -= 'a'+ 0xA;
141 val += ch <<4;
142 k++;
143
144 ch = *(buff + 2*i*bytes +k + nullX);
145 if (val == 0 && (ch == 'X' || ch == 'x')){
146 nullX=2;
147 val = 0;
148 k = -1;
149 continue;
150 };
151 if (ch >= '0' && ch <='9')
152 ch -= '0';
153 if (ch >= 'A' && ch <='F')
154 ch -= 'A'+ 0xA;
155 if (ch >= 'a' && ch <='f')
156 ch -= 'a'+ 0xA;
157
158 val += ch;
159 if (i*bytes > *len )
160 val = 0;
161 }
162 if (rid->bits <=8 ) data[i*bytes] = val;
163 else if (rid->bits <=16 ) *((u16 *)&data[i*bytes]) = val;
164 else if (rid->bits <=32 ) *((u32 *)&data[i*bytes]) = val;
165 if (!val) null_past=1;
166
167 } else {
168 for (k=0; k < bytes; k++){
169 data[i*bytes +k] = *(buff + i*bytes +k);
170 if (i*bytes +k > *len || !data[i*bytes +k])
171 null_past = 1;;
172 }
173
174 }
175 if (null_past){
176 if (rid->bits <=8 ) data[i*bytes] = 0;
177 else if (rid->bits <=16 ) *((u16 *)&data[i*bytes]) = 0;
178 else if (rid->bits <=32 ) *((u32 *)&data[i*bytes]) = 0;
179 }
180
181 }
182
183 };
184
185
186 // *len = pos;
187
188 AWC_ENTRY_EXIT_DEBUG("awc_proc_format_array");
189 return 0;
190 };
191
192
awc_proc_format_bits(int write,u32 * buff,size_t * lenp,struct awc_rid_dir * rid_dir,struct aironet4500_RID * rid)193 int awc_proc_format_bits(int write,u32 * buff, size_t* lenp, struct awc_rid_dir * rid_dir, struct aironet4500_RID * rid){
194
195 u8 * data = rid_dir->buff + rid->offset;
196 u32 val = 0;
197 int not_bool = 0;
198
199 AWC_ENTRY_EXIT_DEBUG("awc_proc_format_bits");
200
201 if ((rid->bits == 8 && rid->mask == 0xff) ||
202 (rid->bits == 16 && rid->mask == 0xffff) ||
203 (rid->bits == 32 && rid->mask == 0xffffffff) )
204 not_bool = 1;
205
206 if (rid->bits <=8 ) val = *data;
207 else if (rid->bits <=16 ) val = *((u16 *)data);
208 else if (rid->bits <=32 ) val = *((u32 *)data);
209
210 DEBUG(0x20000,"awc proc int enter data %x \n",val);
211 DEBUG(0x20000,"awc proc int enter buff %x \n",*buff);
212 DEBUG(0x20000,"awc proc int enter intbuff %x \n",awc_int_buff);
213 DEBUG(0x20000,"awc proc int enter lenp %x \n",*lenp);
214
215
216
217 if (!write){
218 if (rid->mask)
219 val &= rid->mask;
220
221 if (!not_bool && rid->mask &&
222 ((val & rid->mask) == (rid->value & rid->mask)))
223 *buff = 1;
224 else if (!not_bool) *buff = 0;
225 else *buff = val;
226 } else {
227 if (not_bool){
228 val &= ~rid->mask;
229 val |= (*buff & rid->mask);
230 } else {
231 if (*buff){
232 val &= ~rid->mask;
233 if (rid->value)
234 val |= rid->mask & rid->value;
235 else val |= rid->mask & ~rid->value;
236 } else val &= ~rid->mask;
237 };
238 if (rid->bits == 8) *data = val & 0xff;
239 if (rid->bits == 16) *((u16*)data) = val &0xffff;
240 if (rid->bits == 32) *((u32*)data) = val &0xffffffff;
241
242 }
243 DEBUG(0x20000,"awc proc int buff %x \n",awc_int_buff);
244 if (rid->bits <=8 ) val = *data;
245 else if (rid->bits <=16 ) val = *((u16 *)data);
246 else if (rid->bits <=32 ) val = *((u32 *)data);
247
248 DEBUG(0x20000,"awc proc int data %x \n",val);
249
250 // both of them are crazy
251 // *lenp = sizeof(int);
252 // *lenp += 1;
253
254 AWC_ENTRY_EXIT_DEBUG("exit");
255 return 0;
256
257 };
258
awc_proc_fun(ctl_table * ctl,int write,struct file * filp,void * buffer,size_t * lenp)259 int awc_proc_fun(ctl_table *ctl, int write, struct file * filp,
260 void *buffer, size_t *lenp)
261 {
262 int retv =-1;
263 struct awc_private *priv = NULL;
264 unsigned long flags;
265 // int device_number = (int ) ctl->extra1;
266
267 struct awc_rid_dir * rid_dir;
268
269 struct net_device * dev= NULL;
270 struct aironet4500_RID * rid = (struct aironet4500_RID * ) ctl->extra2;
271
272
273 AWC_ENTRY_EXIT_DEBUG("awc_proc_fun");
274
275 if (!write && filp)
276 if (filp->f_pos){
277 // printk(KERN_CRIT "Oversize read\n");
278 *lenp = 0;// hack against reading til eof
279 return 0;
280 }
281
282 MOD_INC_USE_COUNT;
283
284 rid_dir = ((struct awc_rid_dir *)ctl->extra1);
285 dev = rid_dir->dev;
286
287 if (!dev){
288 printk(KERN_ERR " NO device here \n");
289 goto final;
290 }
291
292 if(ctl->procname == NULL || awc_drive_info == NULL ){
293 printk(KERN_WARNING " procname is NULL in sysctl_table or awc_mib_info is NULL \n at awc module\n ");
294 MOD_DEC_USE_COUNT;
295 return -1;
296 }
297 priv = (struct awc_private * ) dev->priv;
298
299 if ((rid->selector->read_only || rid->read_only) && write){
300 printk(KERN_ERR "This value is read-only \n");
301 goto final;
302 };
303
304 if (!write && rid->selector->may_change) {
305 save_flags(flags);
306 cli();
307 awc_readrid(dev,rid,rid_dir->buff + rid->offset);
308 restore_flags(flags);
309 };
310
311 if (rid->array > 1 || rid->bits > 32){
312 if (write){
313 retv = proc_dostring(ctl, write, filp, buffer, lenp);
314 if (retv) goto final;
315 retv = awc_proc_format_array(write, awc_proc_buff, lenp, rid_dir, rid);
316 if (retv) goto final;
317 } else {
318 retv = awc_proc_format_array(write, awc_proc_buff, lenp, rid_dir, rid);
319 if (retv) goto final;
320 retv = proc_dostring(ctl, write, filp, buffer, lenp);
321 if (retv) goto final;
322 }
323 } else {
324 if (write){
325 retv = proc_dointvec(ctl, write, filp, buffer, lenp);
326 if (retv) goto final;
327 retv = awc_proc_format_bits(write, &awc_int_buff, lenp, rid_dir, rid);
328 if (retv) goto final;
329 } else {
330 retv = awc_proc_format_bits(write, &awc_int_buff, lenp,rid_dir, rid);
331 if (retv) goto final;
332 retv = proc_dointvec(ctl, write, filp, buffer, lenp);
333 if (retv) goto final;
334 }
335 }
336 if (write) {
337 save_flags(flags);
338 cli();
339
340 if (rid->selector->MAC_Disable_at_write){
341 awc_disable_MAC(dev);
342 };
343 awc_writerid(dev,rid,rid_dir->buff + rid->offset);
344 if (rid->selector->MAC_Disable_at_write){
345 awc_enable_MAC(dev);
346 };
347 restore_flags(flags);
348
349 };
350
351 DEBUG(0x20000,"awc proc ret %x \n",retv);
352 DEBUG(0x20000,"awc proc lenp %x \n",*lenp);
353
354 MOD_DEC_USE_COUNT;
355 return retv;
356
357 final:
358
359 AWC_ENTRY_EXIT_DEBUG("exit");
360 MOD_DEC_USE_COUNT;
361 return -1 ;
362 }
363
364
365 char conf_reset_result[200];
366
367
368 ctl_table awc_exdev_table[] = {
369 {0, NULL, NULL,0, 0400, NULL},
370 {0}
371 };
372 ctl_table awc_exroot_table[] = {
373 {254, "aironet4500", NULL, 0, 0555, NULL},
374 {0}
375 };
376
377 ctl_table awc_driver_proc_table[] = {
378 {1, "debug" , &awc_debug, sizeof(awc_debug), 0600,NULL, proc_dointvec},
379 {2, "bap_sleep" , &bap_sleep, sizeof(bap_sleep), 0600,NULL, proc_dointvec},
380 {3, "bap_sleep_after_setup" , &bap_sleep_after_setup, sizeof(bap_sleep_after_setup), 0600,NULL, proc_dointvec},
381 {4, "sleep_before_command" , &sleep_before_command, sizeof(sleep_before_command), 0600,NULL, proc_dointvec},
382 {5, "bap_sleep_before_write" , &bap_sleep_before_write, sizeof(bap_sleep_before_write), 0600,NULL, proc_dointvec},
383 {6, "sleep_in_command" , &sleep_in_command , sizeof(sleep_in_command), 0600,NULL, proc_dointvec},
384 {7, "both_bap_lock" , &both_bap_lock , sizeof(both_bap_lock), 0600,NULL, proc_dointvec},
385 {8, "bap_setup_spinlock" , &bap_setup_spinlock , sizeof(bap_setup_spinlock), 0600,NULL, proc_dointvec},
386 {0}
387 };
388
389 ctl_table awc_driver_level_ctable[] = {
390 {1, "force_rts_on_shorter" , NULL, sizeof(int), 0600,NULL, proc_dointvec},
391 {2, "force_tx_rate" , NULL, sizeof(int), 0600,NULL, proc_dointvec},
392 {3, "ip_tos_reliability_rts" , NULL, sizeof(int), 0600,NULL, proc_dointvec},
393 {4, "ip_tos_troughput_no_retries", NULL, sizeof(int), 0600,NULL, proc_dointvec},
394 {5, "debug" , NULL, sizeof(int), 0600,NULL, proc_dointvec},
395 {6, "simple_bridge" , NULL, sizeof(int), 0600,NULL, proc_dointvec},
396 {7, "p802_11_send" , NULL, sizeof(int), 0600,NULL, proc_dointvec},
397 {8, "full_stats" , NULL, sizeof(int), 0600,NULL, proc_dointvec},
398 {0}
399 };
400
401 ctl_table awc_root_table[] = {
402 {254, "aironet4500", NULL, 0, 0555, awc_driver_proc_table},
403 {0}
404 };
405
406 struct ctl_table_header * awc_driver_sysctl_header;
407
408 const char awc_procname[]= "awc5";
409
410
awc_proc_set_device(int device_number)411 int awc_proc_set_device(int device_number){
412 int group =0;
413 int rid = 0;
414 struct awc_private * priv;
415 ctl_table * tmp_table_ptr;
416
417 AWC_ENTRY_EXIT_DEBUG("awc_proc_set_device");
418 if (!aironet4500_devices[device_number] || (awc_nof_rids <=0 )) return -1 ;
419 priv = (struct awc_private * )aironet4500_devices[device_number]->priv;
420
421 awc_rids_setup(aironet4500_devices[device_number]);
422
423 memcpy(&(awc_proc_priv[device_number].proc_table_sys_root[0]), awc_exroot_table,sizeof(struct ctl_table)*2);
424 awc_proc_priv[device_number].proc_table_sys_root[0].ctl_name = 254 - device_number;
425 memcpy(awc_proc_priv[device_number].proc_table_device_root, awc_exdev_table,sizeof(awc_exdev_table) );
426 awc_proc_priv[device_number].proc_table_device_root[0].ctl_name = device_number+1;
427
428 awc_proc_priv[device_number].proc_table_sys_root->child = awc_proc_priv[device_number].proc_table_device_root;
429 memcpy(awc_proc_priv[device_number].proc_name,(struct NET_DEVICE * )aironet4500_devices[device_number]->name,5);
430 awc_proc_priv[device_number].proc_name[4]=0;
431 // awc_proc_priv[device_number].proc_name[3]=48+device_number;
432 awc_proc_priv[device_number].proc_table_device_root[0].procname = &(awc_proc_priv[device_number].proc_name[0]);
433 awc_proc_priv[device_number].proc_table = kmalloc(sizeof(struct ctl_table) * (awc_nof_rids+2),GFP_KERNEL);
434 if (!awc_proc_priv[device_number].proc_table){
435 printk(KERN_CRIT "Out of memory on aironet4500_proc huge table alloc \n");
436 return -1;
437 }
438 awc_proc_priv[device_number].proc_table_device_root[0].child=awc_proc_priv[device_number].proc_table;
439
440
441 if (awc_debug) printk("device %d of %d proc interface setup ",device_number, awc_nof_rids);
442
443
444 while (awc_rids[group].selector && group < awc_nof_rids){
445 if (awc_debug & 0x20000)
446 printk(KERN_CRIT "ridgroup %s size %d \n", awc_rids[group].selector->name,awc_rids[group].size);
447
448 awc_proc_priv[device_number].proc_table[group].ctl_name = group +1;
449 awc_proc_priv[device_number].proc_table[group+1].ctl_name = 0;
450 awc_proc_priv[device_number].proc_table[group].procname = awc_rids[group].selector->name;
451 awc_proc_priv[device_number].proc_table[group].data = awc_proc_buff;
452 awc_proc_priv[device_number].proc_table[group].maxlen = sizeof(awc_proc_buff) -1;
453 awc_proc_priv[device_number].proc_table[group].mode = 0600;
454 awc_proc_priv[device_number].proc_table[group].child = kmalloc(sizeof(struct ctl_table) * (awc_rids[group].size +2), GFP_KERNEL);
455 awc_proc_priv[device_number].proc_table[group].proc_handler = NULL;
456 awc_proc_priv[device_number].proc_table[group].strategy = NULL;
457 awc_proc_priv[device_number].proc_table[group].de = NULL;
458 awc_proc_priv[device_number].proc_table[group].extra1 = NULL;
459 awc_proc_priv[device_number].proc_table[group].extra2 = NULL;
460 if (!awc_proc_priv[device_number].proc_table[group].child) {
461 awc_proc_priv[device_number].proc_table[group].ctl_name = 0;
462 printk(KERN_CRIT "Out of memory on aironet4500_proc huge table alloc \n");
463 return 0;
464 }
465 rid=0;
466 while (awc_rids[group].rids[rid].selector && (rid < awc_rids[group].size -1)){
467
468 // DEBUG(0x20000,"rid %s \n", awc_rids[group].rids[rid].name);
469
470 awc_proc_priv[device_number].proc_table[group].child[rid].ctl_name = rid +1;
471 awc_proc_priv[device_number].proc_table[group].child[rid+1].ctl_name = 0;
472 awc_proc_priv[device_number].proc_table[group].child[rid].procname = awc_rids[group].rids[rid].name;
473 if (awc_rids[group].rids[rid].array > 1 ||
474 awc_rids[group].rids[rid].bits > 32 ){
475 awc_proc_priv[device_number].proc_table[group].child[rid].data = awc_proc_buff;
476 awc_proc_priv[device_number].proc_table[group].child[rid].maxlen = sizeof(awc_proc_buff) -1;
477 } else {
478 awc_proc_priv[device_number].proc_table[group].child[rid].data = &awc_int_buff;
479 awc_proc_priv[device_number].proc_table[group].child[rid].maxlen = sizeof(awc_int_buff);
480
481 }
482 if ( awc_rids[group].rids[rid].read_only ||
483 awc_rids[group].rids[rid].selector->read_only )
484 awc_proc_priv[device_number].proc_table[group].child[rid].mode = 0400;
485 else
486 awc_proc_priv[device_number].proc_table[group].child[rid].mode = 0600;
487 awc_proc_priv[device_number].proc_table[group].child[rid].child = NULL;
488 awc_proc_priv[device_number].proc_table[group].child[rid].proc_handler = awc_proc_fun;
489 awc_proc_priv[device_number].proc_table[group].child[rid].strategy = NULL;
490 awc_proc_priv[device_number].proc_table[group].child[rid].de = NULL;
491 awc_proc_priv[device_number].proc_table[group].child[rid].extra1 = (void *) &(((struct awc_private* )aironet4500_devices[device_number]->priv)->rid_dir[group]);
492 awc_proc_priv[device_number].proc_table[group].child[rid].extra2 = (void *) &(awc_rids[group].rids[rid]);
493
494 rid++;
495 }
496
497 group++;
498
499 };
500 // here are driver-level params dir
501 awc_proc_priv[device_number].proc_table[group].ctl_name = group +1;
502 awc_proc_priv[device_number].proc_table[group+1].ctl_name = 0;
503 awc_proc_priv[device_number].proc_table[group].procname = "driver-level";
504 awc_proc_priv[device_number].proc_table[group].data = awc_proc_buff;
505 awc_proc_priv[device_number].proc_table[group].maxlen = sizeof(awc_proc_buff) -1;
506 awc_proc_priv[device_number].proc_table[group].mode = 0600;
507 awc_proc_priv[device_number].proc_table[group].child = kmalloc(sizeof(awc_driver_level_ctable) , GFP_KERNEL);
508 awc_proc_priv[device_number].proc_table[group].proc_handler = NULL;
509 awc_proc_priv[device_number].proc_table[group].strategy = NULL;
510 awc_proc_priv[device_number].proc_table[group].de = NULL;
511 awc_proc_priv[device_number].proc_table[group].extra1 = NULL;
512 awc_proc_priv[device_number].proc_table[group].extra2 = NULL;
513 if (!awc_proc_priv[device_number].proc_table[group].child) {
514 awc_proc_priv[device_number].proc_table[group].ctl_name = 0;
515 printk(KERN_CRIT "Out of memory on aironet4500_proc huge table alloc \n");
516 return 0;
517 }
518
519
520 tmp_table_ptr = awc_proc_priv[device_number].proc_table[group].child;
521 memcpy(tmp_table_ptr,awc_driver_level_ctable,sizeof(awc_driver_level_ctable));
522
523
524 tmp_table_ptr[0].data =
525 &(priv->force_rts_on_shorter);
526 tmp_table_ptr[1].data = &priv->force_tx_rate;
527 tmp_table_ptr[2].data = (void *) &priv->ip_tos_reliability_rts;
528 tmp_table_ptr[3].data = (void *) &priv->ip_tos_troughput_no_retries;
529 tmp_table_ptr[4].data = (void *) &priv->debug;
530 tmp_table_ptr[5].data = (void *) &priv->simple_bridge;
531 tmp_table_ptr[6].data = (void *) &priv->p802_11_send;
532 tmp_table_ptr[7].data = (void *) &priv->full_stats;
533
534
535 awc_proc_priv[device_number].sysctl_header =
536 register_sysctl_table(awc_proc_priv[device_number].proc_table_sys_root,0);
537
538 AWC_ENTRY_EXIT_DEBUG("exit");
539
540 if (awc_proc_priv[device_number].sysctl_header)
541 return 0;
542 return 1;
543
544 };
545
awc_proc_unset_device(int device_number)546 int awc_proc_unset_device(int device_number){
547 int k;
548
549 AWC_ENTRY_EXIT_DEBUG("awc_proc_unset_device");
550 if (awc_proc_priv[device_number].sysctl_header){
551 unregister_sysctl_table(awc_proc_priv[device_number].sysctl_header);
552 awc_proc_priv[device_number].sysctl_header = NULL;
553 }
554 if (awc_proc_priv[device_number].proc_table){
555 for (k=0; awc_proc_priv[device_number].proc_table[k].ctl_name ; k++ ){
556 if (awc_proc_priv[device_number].proc_table[k].child)
557 kfree(awc_proc_priv[device_number].proc_table[k].child);
558 }
559 kfree(awc_proc_priv[device_number].proc_table);
560 awc_proc_priv[device_number].proc_table = NULL;
561 }
562 if (awc_proc_priv[device_number].proc_table_device_root[0].ctl_name)
563 awc_proc_priv[device_number].proc_table_device_root[0].ctl_name = 0;
564 if (awc_proc_priv[device_number].proc_table_sys_root[0].ctl_name)
565 awc_proc_priv[device_number].proc_table_sys_root[0].ctl_name = 0;
566
567 AWC_ENTRY_EXIT_DEBUG("exit");
568 return 0;
569 };
570
aironet_proc_init(void)571 static int aironet_proc_init(void) {
572 int i=0;
573
574 AWC_ENTRY_EXIT_DEBUG("init_module");
575
576
577 for (i=0; i < MAX_AWCS; i++){
578 awc_proc_set_device(i);
579 }
580
581 awc_register_proc(awc_proc_set_device, awc_proc_unset_device);
582
583 awc_driver_sysctl_header = register_sysctl_table(awc_root_table,0);
584
585 AWC_ENTRY_EXIT_DEBUG("exit");
586 return 0;
587
588 };
589
aironet_proc_exit(void)590 static void aironet_proc_exit(void){
591
592 int i=0;
593 AWC_ENTRY_EXIT_DEBUG("cleanup_module");
594 awc_unregister_proc();
595 for (i=0; i < MAX_AWCS; i++){
596 awc_proc_unset_device(i);
597 }
598 if (awc_driver_sysctl_header)
599 unregister_sysctl_table(awc_driver_sysctl_header);
600 AWC_ENTRY_EXIT_DEBUG("exit");
601 };
602
603 module_init(aironet_proc_init);
604 module_exit(aironet_proc_exit);
605
606 #endif // whole proc system styff
607 MODULE_LICENSE("GPL");
608