- Visual C++源码
- Visual Basic源码
- C++ Builder源码
- Java源码
- Delphi源码
- C/C++源码
- PHP源码
- Perl源码
- Python源码
- Asm源码
- Pascal源码
- Borland C++源码
- Others源码
- SQL源码
- VBScript源码
- JavaScript源码
- ASP/ASPX源码
- C#源码
- Flash/ActionScript源码
- matlab源码
- PowerBuilder源码
- LabView源码
- Flex源码
- MathCAD源码
- VBA源码
- IDL源码
- Lisp/Scheme源码
- VHDL源码
- Objective-C源码
- Fortran源码
- tcl/tk源码
- QT源码
aironet4500_proc.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:19k
源码类别:
Linux/Unix编程
开发平台:
Unix_Linux
- /*
- * Aironet 4500 /proc interface
- *
- * Elmer Joandi, Januar 1999
- * Copyright GPL
- *
- *
- * Revision 0.1 ,started 30.12.1998
- *
- *
- */
- #include <linux/module.h>
- #include <linux/init.h>
- #include <linux/config.h>
- #include <linux/kernel.h>
- #include <linux/version.h>
- #include <linux/sched.h>
- #include <linux/ptrace.h>
- #include <linux/slab.h>
- #include <linux/string.h>
- #include <linux/timer.h>
- #include <linux/interrupt.h>
- #include <linux/in.h>
- #include <asm/io.h>
- #include <asm/system.h>
- #include <asm/bitops.h>
- #include <linux/netdevice.h>
- #include <linux/etherdevice.h>
- #include <linux/skbuff.h>
- #include <linux/if_arp.h>
- #include <linux/ioport.h>
- #ifdef CONFIG_PROC_FS
- #ifdef CONFIG_PROC_FS
- #include <linux/sysctl.h>
- #else
- #error awc driver needs CONFIG_PROC_FS
- #endif
- #include "aironet4500.h"
- #include "aironet4500_rid.c"
- #define AWC_STR_SIZE 0x2ff0
- #define DEV_AWC_INFO 1
- #define DEV_AWC 1
- struct awc_proc_private{
- struct ctl_table_header * sysctl_header;
- struct ctl_table * proc_table;
- struct ctl_table proc_table_device_root[2];
- struct ctl_table proc_table_sys_root[2];
- char proc_name[10];
- };
- static char awc_drive_info[AWC_STR_SIZE]="Zcom n";
- static char awc_proc_buff[AWC_STR_SIZE];
- static int awc_int_buff;
- static struct awc_proc_private awc_proc_priv[MAX_AWCS];
- extern int awc_proc_unset_device(int device_number);
- int awc_proc_format_array(int write,char * buff, size_t * len, struct awc_rid_dir * rid_dir, struct aironet4500_RID * rid){
- u8 * data = rid_dir->buff + rid->offset;
- int pos = 0;
- int null_past = 0;
- int hex = ((rid->mask == 0xff) && (rid->value == 0x0 ));
- int string = ((rid->mask == 0) && (rid->value == 0 ));
- u32 val =0;
- int bytes = (rid->bits / 8);
- int ch =0;
- int i,k;
- int array_len = rid->array;
- int nullX = 0;
- AWC_ENTRY_EXIT_DEBUG("awc_proc_format_array");
- if (rid->bits %8 ) bytes +=1;
- if (bytes > 4 && rid->array == 1){
- array_len = bytes;
- bytes = 1;
- hex = 1;
- };
- if (bytes < 1 || bytes > 4){
- printk(KERN_ERR " weird number of bytes %d in aironet rid n",bytes);
- return -1;
- };
- DEBUG(0x20000,"awc proc array bytes %d",bytes);
- DEBUG(0x20000," hex %d",hex);
- DEBUG(0x20000," string %d",string);
- DEBUG(0x20000," array_len %d n",array_len);
- DEBUG(0x20000," offset %d n",rid->offset);
- if (!write){
- for (i=0; i < array_len ; i++){
- if (bytes <= 1 ) val = data[i*bytes];
- else if (bytes <= 2 ) val = *((u16 *)&data[i*bytes]);
- else if (bytes <= 4 ) val = *((u32 *)&data[i*bytes]);
- if (rid->null_terminated && !val)
- null_past =1;
- if (hex && !string)
- for (k=0; k <bytes; k++)
- pos += sprintf(buff+pos, "%02x",(unsigned char ) data[i*bytes +k]);
- else if (string)
- pos += sprintf(buff+pos, "%c",val);
- else pos += sprintf(buff+pos, "%c",val);
- DEBUG(0x20000, "awcproc %x %x n",data[i], val);
- };
- } else {
- for (i=0; i < array_len ; i++){
- DEBUG(0x20000, "awcproc %x %x n",data[i], buff[i]);
- if (hex && ! string){
- val = 0;
- for (k=0; k < bytes; k++){
- val <<= 8;
- ch = *(buff + 2*i*bytes +k + nullX);
- if (ch >= '0' && ch <='9')
- ch -= '0';
- if (ch >= 'A' && ch <='F')
- ch -= 'A'+ 0xA;
- if (ch >= 'a' && ch <='f')
- ch -= 'a'+ 0xA;
- val += ch <<4;
- k++;
- ch = *(buff + 2*i*bytes +k + nullX);
- if (val == 0 && (ch == 'X' || ch == 'x')){
- nullX=2;
- val = 0;
- k = -1;
- continue;
- };
- if (ch >= '0' && ch <='9')
- ch -= '0';
- if (ch >= 'A' && ch <='F')
- ch -= 'A'+ 0xA;
- if (ch >= 'a' && ch <='f')
- ch -= 'a'+ 0xA;
- val += ch;
- if (i*bytes > *len )
- val = 0;
- }
- if (rid->bits <=8 ) data[i*bytes] = val;
- else if (rid->bits <=16 ) *((u16 *)&data[i*bytes]) = val;
- else if (rid->bits <=32 ) *((u32 *)&data[i*bytes]) = val;
- if (!val) null_past=1;
- } else {
- for (k=0; k < bytes; k++){
- data[i*bytes +k] = *(buff + i*bytes +k);
- if (i*bytes +k > *len || !data[i*bytes +k])
- null_past = 1;;
- }
- }
- if (null_past){
- if (rid->bits <=8 ) data[i*bytes] = 0;
- else if (rid->bits <=16 ) *((u16 *)&data[i*bytes]) = 0;
- else if (rid->bits <=32 ) *((u32 *)&data[i*bytes]) = 0;
- }
- }
- };
- // *len = pos;
- AWC_ENTRY_EXIT_DEBUG("awc_proc_format_array");
- return 0;
- };
- int awc_proc_format_bits(int write,u32 * buff, size_t* lenp, struct awc_rid_dir * rid_dir, struct aironet4500_RID * rid){
- u8 * data = rid_dir->buff + rid->offset;
- u32 val = 0;
- int not_bool = 0;
- AWC_ENTRY_EXIT_DEBUG("awc_proc_format_bits");
- if ((rid->bits == 8 && rid->mask == 0xff) ||
- (rid->bits == 16 && rid->mask == 0xffff) ||
- (rid->bits == 32 && rid->mask == 0xffffffff) )
- not_bool = 1;
- if (rid->bits <=8 ) val = *data;
- else if (rid->bits <=16 ) val = *((u16 *)data);
- else if (rid->bits <=32 ) val = *((u32 *)data);
- DEBUG(0x20000,"awc proc int enter data %x n",val);
- DEBUG(0x20000,"awc proc int enter buff %x n",*buff);
- DEBUG(0x20000,"awc proc int enter intbuff %x n",awc_int_buff);
- DEBUG(0x20000,"awc proc int enter lenp %x n",*lenp);
- if (!write){
- if (rid->mask)
- val &= rid->mask;
- if (!not_bool && rid->mask &&
- ((val & rid->mask) == (rid->value & rid->mask)))
- *buff = 1;
- else if (!not_bool) *buff = 0;
- else *buff = val;
- } else {
- if (not_bool){
- val &= ~rid->mask;
- val |= (*buff & rid->mask);
- } else {
- if (*buff){
- val &= ~rid->mask;
- if (rid->value)
- val |= rid->mask & rid->value;
- else val |= rid->mask & ~rid->value;
- } else val &= ~rid->mask;
- };
- if (rid->bits == 8) *data = val & 0xff;
- if (rid->bits == 16) *((u16*)data) = val &0xffff;
- if (rid->bits == 32) *((u32*)data) = val &0xffffffff;
- }
- DEBUG(0x20000,"awc proc int buff %x n",awc_int_buff);
- if (rid->bits <=8 ) val = *data;
- else if (rid->bits <=16 ) val = *((u16 *)data);
- else if (rid->bits <=32 ) val = *((u32 *)data);
- DEBUG(0x20000,"awc proc int data %x n",val);
- // both of them are crazy
- // *lenp = sizeof(int);
- // *lenp += 1;
- AWC_ENTRY_EXIT_DEBUG("exit");
- return 0;
- };
- int awc_proc_fun(ctl_table *ctl, int write, struct file * filp,
- void *buffer, size_t *lenp)
- {
- int retv =-1;
- struct awc_private *priv = NULL;
- unsigned long flags;
- // int device_number = (int ) ctl->extra1;
- struct awc_rid_dir * rid_dir;
- struct net_device * dev= NULL;
- struct aironet4500_RID * rid = (struct aironet4500_RID * ) ctl->extra2;
- AWC_ENTRY_EXIT_DEBUG("awc_proc_fun");
- if (!write && filp)
- if (filp->f_pos){
- // printk(KERN_CRIT "Oversize readn");
- *lenp = 0;// hack against reading til eof
- return 0;
- }
- MOD_INC_USE_COUNT;
- rid_dir = ((struct awc_rid_dir *)ctl->extra1);
- dev = rid_dir->dev;
- if (!dev){
- printk(KERN_ERR " NO device here n");
- goto final;
- }
- if(ctl->procname == NULL || awc_drive_info == NULL ){
- printk(KERN_WARNING " procname is NULL in sysctl_table or awc_mib_info is NULL n at awc modulen ");
- MOD_DEC_USE_COUNT;
- return -1;
- }
- priv = (struct awc_private * ) dev->priv;
- if ((rid->selector->read_only || rid->read_only) && write){
- printk(KERN_ERR "This value is read-only n");
- goto final;
- };
- if (!write && rid->selector->may_change) {
- save_flags(flags);
- cli();
- awc_readrid(dev,rid,rid_dir->buff + rid->offset);
- restore_flags(flags);
- };
- if (rid->array > 1 || rid->bits > 32){
- if (write){
- retv = proc_dostring(ctl, write, filp, buffer, lenp);
- if (retv) goto final;
- retv = awc_proc_format_array(write, awc_proc_buff, lenp, rid_dir, rid);
- if (retv) goto final;
- } else {
- retv = awc_proc_format_array(write, awc_proc_buff, lenp, rid_dir, rid);
- if (retv) goto final;
- retv = proc_dostring(ctl, write, filp, buffer, lenp);
- if (retv) goto final;
- }
- } else {
- if (write){
- retv = proc_dointvec(ctl, write, filp, buffer, lenp);
- if (retv) goto final;
- retv = awc_proc_format_bits(write, &awc_int_buff, lenp, rid_dir, rid);
- if (retv) goto final;
- } else {
- retv = awc_proc_format_bits(write, &awc_int_buff, lenp,rid_dir, rid);
- if (retv) goto final;
- retv = proc_dointvec(ctl, write, filp, buffer, lenp);
- if (retv) goto final;
- }
- }
- if (write) {
- save_flags(flags);
- cli();
- if (rid->selector->MAC_Disable_at_write){
- awc_disable_MAC(dev);
- };
- awc_writerid(dev,rid,rid_dir->buff + rid->offset);
- if (rid->selector->MAC_Disable_at_write){
- awc_enable_MAC(dev);
- };
- restore_flags(flags);
- };
- DEBUG(0x20000,"awc proc ret %x n",retv);
- DEBUG(0x20000,"awc proc lenp %x n",*lenp);
- MOD_DEC_USE_COUNT;
- return retv;
- final:
- AWC_ENTRY_EXIT_DEBUG("exit");
- MOD_DEC_USE_COUNT;
- return -1 ;
- }
- char conf_reset_result[200];
- ctl_table awc_exdev_table[] = {
- {0, NULL, NULL,0, 0400, NULL},
- {0}
- };
- ctl_table awc_exroot_table[] = {
- {254, "aironet4500", NULL, 0, 0555, NULL},
- {0}
- };
- ctl_table awc_driver_proc_table[] = {
- {1, "debug" , &awc_debug, sizeof(awc_debug), 0600,NULL, proc_dointvec},
- {2, "bap_sleep" , &bap_sleep, sizeof(bap_sleep), 0600,NULL, proc_dointvec},
- {3, "bap_sleep_after_setup" , &bap_sleep_after_setup, sizeof(bap_sleep_after_setup), 0600,NULL, proc_dointvec},
- {4, "sleep_before_command" , &sleep_before_command, sizeof(sleep_before_command), 0600,NULL, proc_dointvec},
- {5, "bap_sleep_before_write" , &bap_sleep_before_write, sizeof(bap_sleep_before_write), 0600,NULL, proc_dointvec},
- {6, "sleep_in_command" , &sleep_in_command , sizeof(sleep_in_command), 0600,NULL, proc_dointvec},
- {7, "both_bap_lock" , &both_bap_lock , sizeof(both_bap_lock), 0600,NULL, proc_dointvec},
- {8, "bap_setup_spinlock" , &bap_setup_spinlock , sizeof(bap_setup_spinlock), 0600,NULL, proc_dointvec},
- {0}
- };
- ctl_table awc_driver_level_ctable[] = {
- {1, "force_rts_on_shorter" , NULL, sizeof(int), 0600,NULL, proc_dointvec},
- {2, "force_tx_rate" , NULL, sizeof(int), 0600,NULL, proc_dointvec},
- {3, "ip_tos_reliability_rts" , NULL, sizeof(int), 0600,NULL, proc_dointvec},
- {4, "ip_tos_troughput_no_retries", NULL, sizeof(int), 0600,NULL, proc_dointvec},
- {5, "debug" , NULL, sizeof(int), 0600,NULL, proc_dointvec},
- {6, "simple_bridge" , NULL, sizeof(int), 0600,NULL, proc_dointvec},
- {7, "p802_11_send" , NULL, sizeof(int), 0600,NULL, proc_dointvec},
- {8, "full_stats" , NULL, sizeof(int), 0600,NULL, proc_dointvec},
- {0}
- };
- ctl_table awc_root_table[] = {
- {254, "aironet4500", NULL, 0, 0555, awc_driver_proc_table},
- {0}
- };
- struct ctl_table_header * awc_driver_sysctl_header;
- const char awc_procname[]= "awc5";
- int awc_proc_set_device(int device_number){
- int group =0;
- int rid = 0;
- struct awc_private * priv;
- ctl_table * tmp_table_ptr;
- AWC_ENTRY_EXIT_DEBUG("awc_proc_set_device");
- if (!aironet4500_devices[device_number] || (awc_nof_rids <=0 )) return -1 ;
- priv = (struct awc_private * )aironet4500_devices[device_number]->priv;
- awc_rids_setup(aironet4500_devices[device_number]);
- memcpy(&(awc_proc_priv[device_number].proc_table_sys_root[0]), awc_exroot_table,sizeof(struct ctl_table)*2);
- awc_proc_priv[device_number].proc_table_sys_root[0].ctl_name = 254 - device_number;
- memcpy(awc_proc_priv[device_number].proc_table_device_root, awc_exdev_table,sizeof(awc_exdev_table) );
- awc_proc_priv[device_number].proc_table_device_root[0].ctl_name = device_number+1;
- awc_proc_priv[device_number].proc_table_sys_root->child = awc_proc_priv[device_number].proc_table_device_root;
- memcpy(awc_proc_priv[device_number].proc_name,(struct NET_DEVICE * )aironet4500_devices[device_number]->name,5);
- awc_proc_priv[device_number].proc_name[4]=0;
- // awc_proc_priv[device_number].proc_name[3]=48+device_number;
- awc_proc_priv[device_number].proc_table_device_root[0].procname = &(awc_proc_priv[device_number].proc_name[0]);
- awc_proc_priv[device_number].proc_table = kmalloc(sizeof(struct ctl_table) * (awc_nof_rids+2),GFP_KERNEL);
- if (!awc_proc_priv[device_number].proc_table){
- printk(KERN_CRIT "Out of memory on aironet4500_proc huge table alloc n");
- return -1;
- }
- awc_proc_priv[device_number].proc_table_device_root[0].child=awc_proc_priv[device_number].proc_table;
- if (awc_debug) printk("device %d of %d proc interface setup ",device_number, awc_nof_rids);
- while (awc_rids[group].selector && group < awc_nof_rids){
- if (awc_debug & 0x20000)
- printk(KERN_CRIT "ridgroup %s size %d n", awc_rids[group].selector->name,awc_rids[group].size);
- awc_proc_priv[device_number].proc_table[group].ctl_name = group +1;
- awc_proc_priv[device_number].proc_table[group+1].ctl_name = 0;
- awc_proc_priv[device_number].proc_table[group].procname = awc_rids[group].selector->name;
- awc_proc_priv[device_number].proc_table[group].data = awc_proc_buff;
- awc_proc_priv[device_number].proc_table[group].maxlen = sizeof(awc_proc_buff) -1;
- awc_proc_priv[device_number].proc_table[group].mode = 0600;
- awc_proc_priv[device_number].proc_table[group].child = kmalloc(sizeof(struct ctl_table) * (awc_rids[group].size +2), GFP_KERNEL);
- awc_proc_priv[device_number].proc_table[group].proc_handler = NULL;
- awc_proc_priv[device_number].proc_table[group].strategy = NULL;
- awc_proc_priv[device_number].proc_table[group].de = NULL;
- awc_proc_priv[device_number].proc_table[group].extra1 = NULL;
- awc_proc_priv[device_number].proc_table[group].extra2 = NULL;
- if (!awc_proc_priv[device_number].proc_table[group].child) {
- awc_proc_priv[device_number].proc_table[group].ctl_name = 0;
- printk(KERN_CRIT "Out of memory on aironet4500_proc huge table alloc n");
- return 0;
- }
- rid=0;
- while (awc_rids[group].rids[rid].selector && (rid < awc_rids[group].size -1)){
- // DEBUG(0x20000,"rid %s n", awc_rids[group].rids[rid].name);
- awc_proc_priv[device_number].proc_table[group].child[rid].ctl_name = rid +1;
- awc_proc_priv[device_number].proc_table[group].child[rid+1].ctl_name = 0;
- awc_proc_priv[device_number].proc_table[group].child[rid].procname = awc_rids[group].rids[rid].name;
- if (awc_rids[group].rids[rid].array > 1 ||
- awc_rids[group].rids[rid].bits > 32 ){
- awc_proc_priv[device_number].proc_table[group].child[rid].data = awc_proc_buff;
- awc_proc_priv[device_number].proc_table[group].child[rid].maxlen = sizeof(awc_proc_buff) -1;
- } else {
- awc_proc_priv[device_number].proc_table[group].child[rid].data = &awc_int_buff;
- awc_proc_priv[device_number].proc_table[group].child[rid].maxlen = sizeof(awc_int_buff);
- }
- if ( awc_rids[group].rids[rid].read_only ||
- awc_rids[group].rids[rid].selector->read_only )
- awc_proc_priv[device_number].proc_table[group].child[rid].mode = 0400;
- else
- awc_proc_priv[device_number].proc_table[group].child[rid].mode = 0600;
- awc_proc_priv[device_number].proc_table[group].child[rid].child = NULL;
- awc_proc_priv[device_number].proc_table[group].child[rid].proc_handler = awc_proc_fun;
- awc_proc_priv[device_number].proc_table[group].child[rid].strategy = NULL;
- awc_proc_priv[device_number].proc_table[group].child[rid].de = NULL;
- awc_proc_priv[device_number].proc_table[group].child[rid].extra1 = (void *) &(((struct awc_private* )aironet4500_devices[device_number]->priv)->rid_dir[group]);
- awc_proc_priv[device_number].proc_table[group].child[rid].extra2 = (void *) &(awc_rids[group].rids[rid]);
- rid++;
- }
- group++;
- };
- // here are driver-level params dir
- awc_proc_priv[device_number].proc_table[group].ctl_name = group +1;
- awc_proc_priv[device_number].proc_table[group+1].ctl_name = 0;
- awc_proc_priv[device_number].proc_table[group].procname = "driver-level";
- awc_proc_priv[device_number].proc_table[group].data = awc_proc_buff;
- awc_proc_priv[device_number].proc_table[group].maxlen = sizeof(awc_proc_buff) -1;
- awc_proc_priv[device_number].proc_table[group].mode = 0600;
- awc_proc_priv[device_number].proc_table[group].child = kmalloc(sizeof(awc_driver_level_ctable) , GFP_KERNEL);
- awc_proc_priv[device_number].proc_table[group].proc_handler = NULL;
- awc_proc_priv[device_number].proc_table[group].strategy = NULL;
- awc_proc_priv[device_number].proc_table[group].de = NULL;
- awc_proc_priv[device_number].proc_table[group].extra1 = NULL;
- awc_proc_priv[device_number].proc_table[group].extra2 = NULL;
- if (!awc_proc_priv[device_number].proc_table[group].child) {
- awc_proc_priv[device_number].proc_table[group].ctl_name = 0;
- printk(KERN_CRIT "Out of memory on aironet4500_proc huge table alloc n");
- return 0;
- }
- tmp_table_ptr = awc_proc_priv[device_number].proc_table[group].child;
- memcpy(tmp_table_ptr,awc_driver_level_ctable,sizeof(awc_driver_level_ctable));
- tmp_table_ptr[0].data =
- &(priv->force_rts_on_shorter);
- tmp_table_ptr[1].data = &priv->force_tx_rate;
- tmp_table_ptr[2].data = (void *) &priv->ip_tos_reliability_rts;
- tmp_table_ptr[3].data = (void *) &priv->ip_tos_troughput_no_retries;
- tmp_table_ptr[4].data = (void *) &priv->debug;
- tmp_table_ptr[5].data = (void *) &priv->simple_bridge;
- tmp_table_ptr[6].data = (void *) &priv->p802_11_send;
- tmp_table_ptr[7].data = (void *) &priv->full_stats;
- awc_proc_priv[device_number].sysctl_header =
- register_sysctl_table(awc_proc_priv[device_number].proc_table_sys_root,0);
- AWC_ENTRY_EXIT_DEBUG("exit");
- if (awc_proc_priv[device_number].sysctl_header)
- return 0;
- return 1;
- };
- int awc_proc_unset_device(int device_number){
- int k;
- AWC_ENTRY_EXIT_DEBUG("awc_proc_unset_device");
- if (awc_proc_priv[device_number].sysctl_header){
- unregister_sysctl_table(awc_proc_priv[device_number].sysctl_header);
- awc_proc_priv[device_number].sysctl_header = NULL;
- }
- if (awc_proc_priv[device_number].proc_table){
- for (k=0; awc_proc_priv[device_number].proc_table[k].ctl_name ; k++ ){
- if (awc_proc_priv[device_number].proc_table[k].child)
- kfree(awc_proc_priv[device_number].proc_table[k].child);
- }
- kfree(awc_proc_priv[device_number].proc_table);
- awc_proc_priv[device_number].proc_table = NULL;
- }
- if (awc_proc_priv[device_number].proc_table_device_root[0].ctl_name)
- awc_proc_priv[device_number].proc_table_device_root[0].ctl_name = 0;
- if (awc_proc_priv[device_number].proc_table_sys_root[0].ctl_name)
- awc_proc_priv[device_number].proc_table_sys_root[0].ctl_name = 0;
- AWC_ENTRY_EXIT_DEBUG("exit");
- return 0;
- };
- static int aironet_proc_init(void) {
- int i=0;
- AWC_ENTRY_EXIT_DEBUG("init_module");
- for (i=0; i < MAX_AWCS; i++){
- awc_proc_set_device(i);
- }
- awc_register_proc(awc_proc_set_device, awc_proc_unset_device);
- awc_driver_sysctl_header = register_sysctl_table(awc_root_table,0);
- AWC_ENTRY_EXIT_DEBUG("exit");
- return 0;
- };
- static void aironet_proc_exit(void){
- int i=0;
- AWC_ENTRY_EXIT_DEBUG("cleanup_module");
- awc_unregister_proc();
- for (i=0; i < MAX_AWCS; i++){
- awc_proc_unset_device(i);
- }
- if (awc_driver_sysctl_header)
- unregister_sysctl_table(awc_driver_sysctl_header);
- AWC_ENTRY_EXIT_DEBUG("exit");
- };
- module_init(aironet_proc_init);
- module_exit(aironet_proc_exit);
- #endif // whole proc system styff
- MODULE_LICENSE("GPL");