📄 chandev.c
字号:
case (del_force_stridx*stridx_mult)|iscomma: if(ints[0]!=1) goto BadArgs; chandev_del_force(ints[1]); break; case (use_devno_names_stridx*stridx_mult): use_devno_names=1; break; case (dont_use_devno_names_stridx*stridx_mult): use_devno_names=0; case (add_model_stridx*stridx_mult)|iscomma: if(ints[0]<3) goto BadArgs; if(ints[0]==3) { ints[0]=4; ints[4]=-1; } chandev_add_model(ints[1],ints[2],ints[3],ints[4]); break; case (del_model_stridx*stridx_mult)|iscomma: if(ints[0]!=2) goto BadArgs; chandev_del_model(ints[1],ints[2]); break; case del_all_models_stridx*stridx_mult: chandev_remove_all_models(); break; default: goto BadArgs; } } return(1); BadArgs: chandev_print_args(); return(0);}__setup("chandev=",chandev_setup);int chandev_doprobe(chandev_force *force,chandev *read_chandev,chandev *write_chandev){ chandev_probelist *probe; chandev_model_info *model_info; chandev_probeinfo probeinfo; int retval=-1,hint=-1; model_info=read_chandev->model_info; if(read_chandev->model_info!=write_chandev->model_info|| (force&&((force->chan_type&model_info->chan_type)==0))) return(-1); /* inconsistent */ for(probe=chandev_probelist_head; probe!=NULL; probe=probe->next) { if(probe->chan_type&model_info->chan_type) { if(use_devno_names) probeinfo.devif_num=read_chandev->devno; else probeinfo.devif_num=-1; probeinfo.read_irq=read_chandev->irq; probeinfo.write_irq=write_chandev->irq; probeinfo.max_port_no=model_info->max_port_no; if(force) { probeinfo.forced_port_no=force->port_no; if(force->devif_num!=-1) probeinfo.devif_num=force->devif_num; probeinfo.do_ip_checksumming=force->do_ip_checksumming; probeinfo.use_hw_stats=force->use_hw_stats; } else { probeinfo.forced_port_no=-1; probeinfo.do_ip_checksumming=FALSE; probeinfo.use_hw_stats=FALSE; if(probe->chan_type&lcs) { hint=(read_chandev->devno&0xFF)>>1; if(hint>model_info->max_port_no) { /* The card is possibly emulated e.g P/390 */ /* or possibly configured to use a shared */ /* port configured by osa-sf. */ hint=0; } } } probeinfo.hint_port_no=hint; retval=probe->probefunc(&probeinfo); if(retval==0) break; } } return(retval);}void chandev_probe(void){ chandev *read_chandev,*write_chandev,*curr_chandev; chandev_force *curr_force; chandev_noauto_range *curr_noauto; chandev_collect_devices(); for(curr_force=chandev_force_head;curr_force!=NULL; curr_force=curr_force->next) { for(read_chandev=chandev_head; read_chandev!=NULL; read_chandev=read_chandev->next) if(read_chandev->devno==curr_force->read_devno) { for(write_chandev=chandev_head; write_chandev!=NULL; write_chandev=write_chandev->next) if(write_chandev->devno== curr_force->write_devno) { if(chandev_doprobe(curr_force, read_chandev, write_chandev)==0) { chandev_remove(read_chandev); chandev_remove(write_chandev); goto chandev_probe_skip; } } } chandev_probe_skip: } for(curr_chandev=chandev_head; curr_chandev!=NULL; curr_chandev=curr_chandev->next) { for(curr_noauto=chandev_noauto_head;curr_noauto!=NULL; curr_noauto=curr_noauto->next) { if(curr_chandev->devno>=curr_noauto->lo_devno&& curr_chandev->devno<=curr_noauto->hi_devno) { chandev_remove(curr_chandev); break; } } } for(curr_chandev=chandev_head;curr_chandev!=NULL; curr_chandev=curr_chandev->next) { if(curr_chandev->next&&curr_chandev->model_info== curr_chandev->next->model_info) { chandev_doprobe(NULL,curr_chandev,curr_chandev->next); curr_chandev=curr_chandev->next; } } chandev_remove_all();}int chandev_do_setup(char *buff,int size){ int curr,startline=0,comment=FALSE,newline=FALSE,oldnewline=TRUE; int rc=1; buff[size]=0; for(curr=0;curr<=size;curr++) { if(buff[curr]=='#') { comment=TRUE; newline=FALSE; } else if(buff[curr]==10||buff[curr]==13||buff[curr]==0) { buff[curr]=0; comment=FALSE; newline=TRUE; } if(comment==FALSE&&curr>startline &&((oldnewline==TRUE&&newline==FALSE)||curr==size)) { if((rc=chandev_setup(&buff[startline]))==0) break; startline=curr+1; } oldnewline=newline; } return(rc);}void chandev_read_conf(void){#define CHANDEV_FILE "/etc/chandev.conf" struct stat statbuf; char *buff; int curr,left,len,fd; chandev_conf_read=TRUE; set_fs(KERNEL_DS); if(stat(CHANDEV_FILE,&statbuf)==0) { set_fs(USER_DS); buff=vmalloc(statbuf.st_size+1); if(buff) { set_fs(KERNEL_DS); if((fd=open(CHANDEV_FILE,O_RDONLY,0))!=-1) { curr=0; left=statbuf.st_size; while((len=read(fd,&buff[curr],left))>0) { curr+=len; left-=len; } close(fd); } set_fs(USER_DS); chandev_do_setup(buff,statbuf.st_size); vfree(buff); } } set_fs(USER_DS);}void chandev_register_and_probe(chandev_probefunc probefunc,chandev_type chan_type){ chandev_probelist *new_probe; if(!chandev_conf_read) chandev_read_conf(); if((new_probe=chandev_alloc_listmember((list **)& chandev_probelist_head,sizeof(chandev_probelist)))) { new_probe->probefunc=probefunc; new_probe->chan_type=chan_type; chandev_probe(); }}void chandev_unregister(chandev_probefunc probefunc){ chandev_probelist *curr_probe=NULL; for(curr_probe=chandev_probelist_head;curr_probe!=NULL; curr_probe=curr_probe->next) { if(curr_probe->probefunc==probefunc) chandev_free_listmember((list **)&chandev_probelist_head, (list *)curr_probe); }}#ifdef CONFIG_PROC_FS#define chandev_printf(exitchan,args...) \splen=sprintf(spbuff,##args); \spoffset+=splen; \if(spoffset>offset) { \ spbuff+=splen; \ currlen+=splen; \} \if(currlen>=length) \ goto exitchan;static int chandev_read_proc(char *page, char **start, off_t offset, int length, int *eof, void *data){ char *spbuff=*start=page; int currlen=0,splen; off_t spoffset=0; chandev_model_info *curr_model; chandev_noauto_range *curr_noauto; chandev_force *curr_force; chandev_printf(chan_exit,"Channels enabled for detection\n"); chandev_printf(chan_exit,"chan_type cu_type cu_model max_port_no\n"); chandev_printf(chan_exit,"=================================================\n"); for(curr_model=chandev_models_head;curr_model!=NULL; curr_model=curr_model->next) { chandev_printf(chan_exit,"0x%02x 0x%04x 0x%02x %d\n", curr_model->chan_type,(int)curr_model->cu_type, (int)curr_model->cu_model,(int)curr_model->max_port_no); } chandev_printf(chan_exit,"%s",chandev_keydescript); chandev_printf(chan_exit,"No auto devno ranges\n"); chandev_printf(chan_exit," From To \n"); chandev_printf(chan_exit,"====================\n"); for(curr_noauto=chandev_noauto_head;curr_noauto!=NULL; curr_noauto=curr_noauto->next) { chandev_printf(chan_exit,"0x%4x 0x%4x\n", curr_noauto->lo_devno, curr_noauto->hi_devno); } chandev_printf(chan_exit,"\nForced devices\n"); chandev_printf(chan_exit,"chan_type defif_num read_devno write_devno port_no ip_cksum hw_stats\n"); chandev_printf(chan_exit,"====================================================================\n"); for(curr_force=chandev_force_head;curr_force!=NULL; curr_force=curr_force->next) { chandev_printf(chan_exit,"0x%2x %d 0x%4x 0x%4x %4d %1d %1d\n", curr_force->chan_type,curr_force->devif_num, curr_force->read_devno,curr_force->write_devno, curr_force->port_no,curr_force->do_ip_checksumming, curr_force->use_hw_stats); } *eof=TRUE; chan_exit: if(currlen>length) { /* rewind to previous printf so that we are correctly * aligned if we get called to print another page. */ currlen-=splen; } return(currlen);}static int chandev_write_proc(struct file *file, const char *buffer, unsigned long count, void *data){ int rc; char *buff; buff=vmalloc(count+1); if(buff) { rc = copy_from_user(buff,buffer,count); if (rc) goto chandev_write_exit; chandev_do_setup(buff,count); rc=count; chandev_write_exit: vfree(buff); return rc; } else return -ENOMEM; return(0);}static void __init chandev_create_proc(void){ struct proc_dir_entry *dir_entry= create_proc_entry("chandev",0644, &proc_root); if(dir_entry) { dir_entry->read_proc=&chandev_read_proc; dir_entry->write_proc=&chandev_write_proc; }}#endifstatic int __init chandev_init(void){ chandev_init_default_models();#if CONFIG_PROC_FS chandev_create_proc();#endif return(0);}__initcall(chandev_init);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -