📄 chandev.c
字号:
" this is nothing to worry about chan_type/chan_model/dev_type/dev_model %s\n",buff); drinfo->oper_func=NULL; } chandev_add_to_list((list **)&chandev_models_head,newmodel); }}void chandev_remove(chandev *member){ chandev_free_queuemember(&chandev_head,(queue *)member);}void chandev_remove_all(void){ chandev_free_all_queue(&chandev_head);}void chandev_remove_model(chandev_model_info *model){ chandev *curr_chandev,*next_chandev; chandev_lock(); for_each_allow_delete(curr_chandev,next_chandev,(chandev *)chandev_head.head) if(curr_chandev->model_info==model) chandev_remove(curr_chandev); if(model->drinfo.oper_func) s390_device_unregister(&model->drinfo); chandev_free_listmember((list **)&chandev_models_head,(list *)model); chandev_unlock();}void chandev_remove_all_models(void){ chandev_lock(); while(chandev_models_head) chandev_remove_model(chandev_models_head); chandev_unlock();}void chandev_del_model(s32 cu_type,s16 cu_model,s32 dev_type,s16 dev_model){ chandev_model_info *curr_model,*next_model; chandev_lock(); for_each_allow_delete(curr_model,next_model,chandev_models_head) if((curr_model->cu_type==cu_type||cu_type==-1)&& (curr_model->cu_model==cu_model||cu_model==-1)&& (curr_model->dev_type==dev_type||dev_type==-1)&& (curr_model->dev_model==dev_model||dev_model==-1)) chandev_remove_model(curr_model); chandev_unlock();}static void chandev_init_default_models(void){ /* Usually P390/Planter 3172 emulation assume maximum 16 to be safe. */ chandev_add_model(chandev_type_lcs,0x3088,0x1,-1,-1,15,default_msck_bits,FALSE,FALSE); /* 3172/2216 Paralell the 2216 allows 16 ports per card the */ /* the original 3172 only allows 4 we will assume the max of 16 */ chandev_add_model(chandev_type_lcs|chandev_type_ctc,0x3088,0x8,-1,-1,15,default_msck_bits,FALSE,FALSE); /* 3172/2216 Escon serial the 2216 allows 16 ports per card the */ /* the original 3172 only allows 4 we will assume the max of 16 */ chandev_add_model(chandev_type_lcs|chandev_type_escon,0x3088,0x1F,-1,-1,15,default_msck_bits,FALSE,FALSE); /* Only 2 ports allowed on OSA2 cards model 0x60 */ chandev_add_model(chandev_type_lcs,0x3088,0x60,-1,-1,1,default_msck_bits,FALSE,FALSE); /* qeth gigabit ethernet */ chandev_add_model(chandev_type_qeth,0x1731,0x1,0x1732,0x1,0,default_msck_bits,FALSE,FALSE); chandev_add_model(chandev_type_qeth,0x1731,0x5,0x1732,0x5,0,default_msck_bits,FALSE,FALSE); /* Osa-D we currently aren't too emotionally involved with this */ chandev_add_model(chandev_type_osad,0x3088,0x62,-1,-1,0,default_msck_bits,FALSE,FALSE); /* claw */ chandev_add_model(chandev_type_claw,0x3088,0x61,-1,-1,0,default_msck_bits,FALSE,FALSE); /* ficon attached ctc */ chandev_add_model(chandev_type_escon,0x3088,0x1E,-1,-1,0,default_msck_bits,FALSE,FALSE);}void chandev_del_noauto(u16 devno){ chandev_noauto_range *curr_noauto,*next_noauto; chandev_lock(); for_each_allow_delete(curr_noauto,next_noauto,chandev_noauto_head) if(curr_noauto->lo_devno<=devno&&curr_noauto->hi_devno>=devno) chandev_free_listmember((list **)&chandev_noauto_head,(list *)curr_noauto); chandev_unlock();}void chandev_del_msck(u16 devno){ chandev_msck_range *curr_msck_range,*next_msck_range; chandev_lock(); for_each_allow_delete(curr_msck_range,next_msck_range,chandev_msck_range_head) if(curr_msck_range->lo_devno<=devno&&curr_msck_range->hi_devno>=devno) chandev_free_listmember((list **)&chandev_msck_range_head,(list *)curr_msck_range); chandev_unlock();}void chandev_add(s390_dev_info_t *newdevinfo,chandev_model_info *newmodelinfo){ chandev *new_chandev=NULL; if((new_chandev=chandev_alloc(sizeof(chandev)))) { new_chandev->model_info=newmodelinfo; new_chandev->sch.devno=newdevinfo->devno; new_chandev->sch.irq=newdevinfo->irq; new_chandev->sch.cu_type=newdevinfo->sid_data.cu_type; /* control unit type */ new_chandev->sch.cu_model=newdevinfo->sid_data.cu_model; /* control unit model */ new_chandev->sch.dev_type=newdevinfo->sid_data.dev_type; /* device type */ new_chandev->sch.dev_model=newdevinfo->sid_data.dev_model; /* device model */ chandev_add_schib_info(newdevinfo->irq,&new_chandev->sch); new_chandev->owned=(newdevinfo->status&DEVSTAT_DEVICE_OWNED ? TRUE:FALSE); chandev_queuemember(&chandev_head,new_chandev); }}void chandev_unregister_probe(chandev_probefunc probefunc){ chandev_probelist *curr_probe,*next_probe; chandev_lock(); for_each_allow_delete(curr_probe,next_probe,chandev_probelist_head) if(curr_probe->probefunc==probefunc) chandev_free_listmember((list **)&chandev_probelist_head, (list *)curr_probe); chandev_unlock();}void chandev_unregister_probe_by_chan_type(chandev_type chan_type){ chandev_probelist *curr_probe,*next_probe; chandev_lock(); for_each_allow_delete(curr_probe,next_probe,chandev_probelist_head) if(curr_probe->chan_type==chan_type) chandev_free_listmember((list **)&chandev_probelist_head, (list *)curr_probe); chandev_unlock();}void chandev_reset(void){ chandev_lock(); chandev_remove_all_models(); chandev_free_all_list((list **)&chandev_noauto_head); chandev_free_all_list((list **)&chandev_msck_range_head); chandev_free_all_list((list **)&chandev_force_head); chandev_remove_parms(-1,FALSE,-1);#if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0) chandev_use_devno_names=FALSE;#endif chandev_persistent=0; chandev_unlock();}int chandev_is_chandev(int irq,s390_dev_info_t *devinfo,chandev_force **forceinfo,chandev_model_info **ret_model){ chandev_force *curr_force; chandev_model_info *curr_model=NULL; int err; int retval=FALSE; if(forceinfo) *forceinfo=NULL; if(ret_model) *ret_model=NULL; if((err=get_dev_info_by_irq(irq,devinfo))) { printk("chandev_is_chandev get_dev_info_by_irq reported err=%X on irq %d\n" "should not happen\n",err,irq); return FALSE; } chandev_lock(); for_each(curr_model,chandev_models_head) { if(((curr_model->cu_type==devinfo->sid_data.cu_type)||(curr_model->cu_type==-1))&& ((curr_model->cu_model==devinfo->sid_data.cu_model)||(curr_model->cu_model==-1))&& ((curr_model->dev_type==devinfo->sid_data.dev_type)||(curr_model->dev_type==-1))&& ((curr_model->dev_model==devinfo->sid_data.dev_model)||(curr_model->dev_model==-1))) { retval=TRUE; if(ret_model) *ret_model=curr_model; break; } } for_each(curr_force,chandev_force_head) { if(((curr_force->read_lo_devno==devinfo->devno)&& (curr_force->write_hi_devno==devinfo->devno)&& (curr_force->devif_num!=-2))|| ((curr_force->read_lo_devno>=devinfo->devno)&& (curr_force->write_hi_devno<=devinfo->devno)&& (curr_force->devif_num==-2))) { if(forceinfo) *forceinfo=curr_force; break; } } chandev_unlock(); return(retval);}void chandev_collect_devices(void){ int curr_irq,loopcnt=0; s390_dev_info_t curr_devinfo; chandev_model_info *curr_model; for(curr_irq=get_irq_first();curr_irq>=0; curr_irq=get_irq_next(curr_irq)) { /* check read chandev * we had to do the cu_model check also because ctc devices * have the same cutype & after asking some people * the model numbers are given out pseudo randomly so * we can't just take a range of them also the dev_type & models are 0 */ loopcnt++; if(loopcnt>0x10000) { printk(KERN_ERR"chandev_collect_devices detected infinite loop bug in get_irq_next\n"); break; } chandev_lock(); if(chandev_is_chandev(curr_irq,&curr_devinfo,NULL,&curr_model)) chandev_add(&curr_devinfo,curr_model); chandev_unlock(); }}int chandev_add_force(chandev_type chan_type,s32 devif_num,u16 read_lo_devno,u16 write_hi_devno,u16 data_devno,s32 memory_usage_in_k,s16 port_protocol_no,u8 checksum_received_ip_pkts,u8 use_hw_stats,char *host_name,char *adapter_name,char *api_type){ chandev_force *new_chandev_force; if(devif_num==-2&&read_lo_devno>write_hi_devno) { printk("chandev_add_force detected bad device range lo_devno=0x%04x hi_devno=0x%04x\n,", (int)read_lo_devno,(int)write_hi_devno); return(-1); } if(memory_usage_in_k<0) { printk("chandev_add_force memory_usage_in_k is bad\n"); return(-1); } if(chan_type==chandev_type_claw) { int host_name_len=strlen(host_name), adapter_name_len=strlen(adapter_name), api_type_len=strlen(api_type); if(host_name_len>=CLAW_NAMELEN||host_name_len==0|| adapter_name_len>=CLAW_NAMELEN||adapter_name_len==0|| api_type_len>=CLAW_NAMELEN||api_type_len==0) return(-1); } if((new_chandev_force=chandev_alloc(sizeof(chandev_force)))) { new_chandev_force->chan_type=chan_type; new_chandev_force->devif_num=devif_num; new_chandev_force->read_lo_devno=read_lo_devno; new_chandev_force->write_hi_devno=write_hi_devno; new_chandev_force->data_devno=data_devno; new_chandev_force->memory_usage_in_k=memory_usage_in_k; new_chandev_force->port_protocol_no=port_protocol_no; new_chandev_force->checksum_received_ip_pkts=checksum_received_ip_pkts; new_chandev_force->use_hw_stats=use_hw_stats; if(chan_type==chandev_type_claw) { strcpy(new_chandev_force->claw.host_name,host_name); strcpy(new_chandev_force->claw.adapter_name,adapter_name); strcpy(new_chandev_force->claw.api_type,api_type); } chandev_add_to_list((list **)&chandev_force_head,new_chandev_force); } return(0);}void chandev_del_force(int read_lo_devno){ chandev_force *curr_force,*next_force; chandev_lock(); for_each_allow_delete(curr_force,next_force,chandev_force_head) { if(curr_force->read_lo_devno==read_lo_devno||read_lo_devno==-1) chandev_free_listmember((list **)&chandev_force_head, (list *)curr_force); } chandev_unlock();}void chandev_shutdown(chandev_activelist *curr_device){ int err=0; chandev_lock(); /* unregister_netdev calls the dev->close so we shouldn't do this */ /* this otherwise we crash */ if(curr_device->unreg_dev) { curr_device->unreg_dev(curr_device->dev_ptr); curr_device->unreg_dev=NULL; } if(curr_device->shutdownfunc) { err=curr_device->shutdownfunc(curr_device->dev_ptr); } if(err) printk("chandev_shutdown unable to fully shutdown & unload %s err=%d\n" "probably some upper layer still requires the device to exist\n", curr_device->devname,err); else { chandev_free_irq_by_irqinfo(curr_device->read_irqinfo); chandev_free_irq_by_irqinfo(curr_device->write_irqinfo); if(curr_device->data_irqinfo) chandev_free_irq_by_irqinfo(curr_device->data_irqinfo); chandev_free_listmember((list **)&chandev_activelist_head, (list *)curr_device); } chandev_unlock();}void chandev_shutdown_all(void){ while(chandev_activelist_head) chandev_shutdown(chandev_activelist_head);}void chandev_shutdown_by_name(char *devname){ chandev_activelist *curr_device; chandev_lock(); for_each(curr_device,chandev_activelist_head) if(strcmp(devname,curr_device->devname)==0) { chandev_shutdown(curr_device); break; } chandev_unlock();}static chandev_activelist *chandev_active(u16 devno){ chandev_activelist *curr_device; for_each(curr_device,chandev_activelist_head) if(curr_device->read_irqinfo->sch.devno==devno|| curr_device->write_irqinfo->sch.devno==devno|| (curr_device->data_irqinfo&&curr_device->data_irqinfo->sch.devno==devno)) { return(curr_device); } return(NULL);}void chandev_shutdown_by_devno(u16 devno){ chandev_activelist *curr_device; chandev_lock(); curr_device=chandev_active(devno); if(curr_device) chandev_shutdown(curr_device); chandev_unlock();}int chandev_pack_args(char *str){ char *newstr=str,*next; int strcnt=1; while(*str) { next=str+1; /*remove dead spaces */ if(isspace(*str)&&isspace(*next)) { str++; continue; } if(isspace(*str)) { *str=','; goto pack_dn; } if(((*str)==';')&&(*next)) { strcnt++; *str=0; } pack_dn: *newstr++=*str++; } *newstr=0; return(strcnt);}typedef enum{ isnull=0, isstr=1, isnum=2, iscomma=4,} chandev_strval;chandev_strval chandev_strcmp(char *teststr,char **str,long *endlong){ char *cur; chandev_strval retval=isnull; int len=strlen(teststr); if(strncmp(teststr,*str,len)==0) { *str+=len; retval=isstr; cur=*str; *endlong=simple_strtol(cur,str,0); if(cur!=*str) retval|=isnum; if(**str==',') { retval|=iscomma; *str+=1; } else if(**str!=0) retval=isnull; } return(retval);}int chandev_initdevice(chandev_probeinfo *probeinfo,void *dev_ptr,u8 port_no,char *devname,chandev_category category,chandev_unregfunc unreg_dev){ chandev_activelist *newdevice,*curr_device; chandev_interrupt_check(); if(probeinfo->newdevice!=NULL) { printk("probeinfo->newdevice!=NULL in chandev_initdevice for %s",devname); return(-EPERM); } chandev_lock(); for_each(curr_device,chandev_activelist_head) { if(strcmp(curr_device->devname,devname)==0) { printk("chandev_initdevice detected duplicate devicename %s\n",devname); chandev_unlock(); return(-EPERM); } } if((newdevice=chandev_allocstr(devname,offsetof(chandev_activelist,devname)))) { newdevice->read_irqinfo=chandev_get_irqinfo_by_irq(probeinfo->read.irq); newdevice->write_irqinfo=chandev_get_irqinfo_by_irq(probeinfo->write.irq); if(probeinfo->data_exists) newdevice->data_irqinfo=chandev_get_irqinfo_by_irq(probeinfo->data.irq); chandev_unlock(); if(newdevice->read_irqinfo==NULL||newdevice->write_irqinfo==NULL|| (probeinfo->data_exists&&newdevice->data_irqinfo==NULL)) { printk("chandev_initdevice, it appears that chandev_request_irq was not " "called for devname=%s read_irq=%d write_irq=%d data_irq=%d\n", devname,probeinfo->read.irq,probeinfo->write.irq,probeinfo->data.irq); kfree(newdevice); return(-EPERM); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -