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