📄 aironet4500_proc.c
字号:
/* * Aironet 4500 Pcmcia driver * * 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/malloc.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 1struct 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\0";static char awc_proc_buff[AWC_STR_SIZE]="\0";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 read\n"); *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 module\n "); 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) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -