⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chandev.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 5 页
字号:
		newdevice->chan_type=probeinfo->chan_type;				newdevice->dev_ptr=dev_ptr;		newdevice->port_no=port_no;		newdevice->memory_usage_in_k=probeinfo->memory_usage_in_k;		newdevice->category=category;		newdevice->unreg_dev=unreg_dev;		probeinfo->newdevice=newdevice;		return(0);	}	chandev_unlock();	return(-ENOMEM);}char *chandev_build_device_name(chandev_probeinfo *probeinfo,char *destnamebuff,char *basename,int buildfullname){	if (chandev_use_devno_names&&(!probeinfo->device_forced||probeinfo->devif_num==-1)) 		sprintf(destnamebuff,"%s%04x",basename,(int)probeinfo->read.devno);	else	{		if(probeinfo->devif_num==-1)		{			if(buildfullname)			{				int idx,len=strlen(basename);								chandev_activelist *curr_device;				for(idx=0;idx<0xffff;idx++)				{					for_each(curr_device,chandev_activelist_head)					{						if(strncmp(curr_device->devname,basename,len)==0)						{							char numbuff[10];							sprintf(numbuff,"%d",idx);							if(strcmp(&curr_device->devname[len],numbuff)==0)								goto next_idx;						}					}					sprintf(destnamebuff,"%s%d",basename,idx);					return(destnamebuff);				next_idx:				}				printk("chandev_build_device_name was usable to build a unique name for %s\n",basename);				return(NULL);			}			else				sprintf(destnamebuff,"%s%%d",basename);		}		else		{			sprintf(destnamebuff,"%s%d",basename,(int)probeinfo->devif_num);		}	}	return(destnamebuff);}#if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)struct net_device *chandev_init_netdev(chandev_probeinfo *probeinfo,char *basename,struct net_device *dev, int sizeof_priv,struct net_device *(*init_netdevfunc)(struct net_device *dev, int sizeof_priv))#elsestruct device *chandev_init_netdev(chandev_probeinfo *probeinfo,char *basename,struct device *dev, int sizeof_priv,struct device *(*init_netdevfunc)(struct device *dev, int sizeof_priv))#endif{#if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)	struct net_device *retdevice=NULL;	int new_device = FALSE;#else	struct device *retdevice=NULL;#endif		chandev_interrupt_check();	if (!init_netdevfunc) 	{		printk("init_netdevfunc=NULL in chandev_init_netdev, it should not be valid.\n");		return NULL;	}#if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)	/* Allocate a device if one is not provided. */        if (dev == NULL) 	{		/* ensure 32-byte alignment of the private area */		int alloc_size = sizeof (*dev) + sizeof_priv + 31;		dev = (struct net_device *) kmalloc (alloc_size, GFP_KERNEL);		if (dev == NULL) 		{			printk(KERN_ERR "chandev_initnetdevice: Unable to allocate device memory.\n");			return NULL;		}		memset(dev, 0, alloc_size);		if (sizeof_priv)			dev->priv = (void *) (((long)(dev + 1) + 31) & ~31);		new_device=TRUE;	}	chandev_build_device_name(probeinfo,dev->name,basename,FALSE);#endif	retdevice=init_netdevfunc(dev,sizeof_priv);#if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)	/* Register device if necessary */	/* we need to do this as init_netdev doesn't call register_netdevice */	/* for already allocated devices */	if (retdevice && new_device)		register_netdev(retdevice);#endif#if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)	/* We allocated it, so we should free it on error */	if (!retdevice && new_device) 		kfree(dev);#endif	return retdevice;}#if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)struct net_device *chandev_initnetdevice(chandev_probeinfo *probeinfo,u8 port_no,struct net_device *dev, int sizeof_priv, char *basename, struct net_device *(*init_netdevfunc)(struct net_device *dev, int sizeof_priv),void (*unreg_netdevfunc)(struct net_device *dev))#elsestruct device *chandev_initnetdevice(chandev_probeinfo *probeinfo,u8 port_no,struct device *dev, int sizeof_priv, char *basename,struct device *(*init_netdevfunc)(struct device *dev, int sizeof_priv),void (*unreg_netdevfunc)(struct device *dev))#endif{#if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)	struct net_device *retdevice=NULL;	int new_device=(dev==NULL);#else	struct device *retdevice=NULL;#endif	if (!unreg_netdevfunc) 	{		printk("unreg_netdevfunc=NULL in chandev_initnetdevice, it should not be valid.\n");		return NULL;	}	chandev_interrupt_check();	retdevice=chandev_init_netdev(probeinfo,basename,dev,sizeof_priv,init_netdevfunc);	if (retdevice) 	{		if (chandev_initdevice(probeinfo,retdevice,port_no,retdevice->name,				      chandev_category_network_device,(chandev_unregfunc)unreg_netdevfunc)) 		{			unreg_netdevfunc(retdevice);#if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)			/* We allocated it, so we should free it on error */			if(new_device)				kfree(dev);#endif			retdevice = NULL;		}	}	return retdevice;}int chandev_compare_chpid_info(chandev_subchannel_info *chan1,chandev_subchannel_info *chan2){	return (chan1->pim!=chan2->pim || *chan1->chpid!=*chan2->chpid);}int chandev_compare_cu_dev_info(chandev_subchannel_info *chan1,chandev_subchannel_info *chan2){	return ((chan1->cu_type != chan2->cu_type)||		(chan1->cu_model != chan2->cu_model)||		(chan1->dev_type != chan2->dev_type)||		(chan1->dev_model != chan2->dev_model));}int chandev_compare_subchannel_info(chandev_subchannel_info *chan1,chandev_subchannel_info *chan2){	return((chan1->devno == chan2->devno) &&	       (chan1->cu_type == chan2->cu_type) &&	       (chan1->cu_model == chan2->cu_model) &&	       (chan1->dev_type == chan2->dev_type) &&	       (chan1->dev_model == chan2->dev_model) &&	       (chan1->pim == chan2->pim) &&	       (*chan1->chpid == *chan2->chpid));}int chandev_doprobe(chandev_force *force,chandev *read,chandev *write,chandev *data){	chandev_probelist *probe;	chandev_model_info *model_info;	chandev_probeinfo probeinfo;	int               rc=-1,hint=-1;	chandev_activelist *newdevice;	chandev_probefunc  probefunc;	chandev_parms      *curr_parms;	chandev_model_info dummy_model_info;	memset(&probeinfo,0,sizeof(probeinfo));	memset(&dummy_model_info,0,sizeof(dummy_model_info));	probeinfo.device_forced=(force!=NULL);	probeinfo.chpid_info_inconsistent=chandev_compare_chpid_info(&read->sch,&write->sch)||		 (data&&chandev_compare_chpid_info(&read->sch,&data->sch));	probeinfo.cu_dev_info_inconsistent=chandev_compare_cu_dev_info(&read->sch,&write->sch)||		 (data&&chandev_compare_cu_dev_info(&read->sch,&data->sch));	if(read->model_info)		model_info=read->model_info;	else	{		dummy_model_info.chan_type=chandev_type_none;		dummy_model_info.max_port_no=16;		model_info=&dummy_model_info;	}	for_each(probe,chandev_probelist_head)	{		if(force)			probeinfo.chan_type = ( probe->chan_type & force->chan_type );		else		{			if(chandev_cautious_auto_detect)				probeinfo.chan_type = ( probe->chan_type == model_info->chan_type ? 						       probe->chan_type : chandev_type_none );			else				probeinfo.chan_type = ( probe->chan_type & model_info->chan_type );		}		if(probeinfo.chan_type && (force || ( !probeinfo.cu_dev_info_inconsistent &&		  ((probe->chan_type&(chandev_type_ctc|chandev_type_escon)) ||		   !probeinfo.chpid_info_inconsistent))))		{#if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)			if(chandev_use_devno_names)				probeinfo.devif_num=read->sch.devno;			else#endif				probeinfo.devif_num=-1;			probeinfo.read=read->sch;			probeinfo.write=write->sch;			if(data)			{				probeinfo.data=data->sch;				probeinfo.data_exists=TRUE;			}			probeinfo.max_port_no=(force&&(force->port_protocol_no!=-1) ? 			      force->port_protocol_no : model_info->max_port_no);			for_each(curr_parms,chandev_parms_head)			{				if(probe->chan_type==curr_parms->chan_type&&				   read->sch.devno>=curr_parms->lo_devno&&					read->sch.devno<=curr_parms->hi_devno)				{					probeinfo.parmstr=curr_parms->parmstr;					break;				}			}			if(force)			{				if(force->chan_type==chandev_type_claw)					memcpy(&probeinfo.claw,&force->claw,sizeof(chandev_claw_info));				probeinfo.port_protocol_no=force->port_protocol_no;				if(force->devif_num==-1&&force->devif_num==-2)					probeinfo.devif_num=-1;				else					probeinfo.devif_num=force->devif_num;				probeinfo.memory_usage_in_k=force->memory_usage_in_k;				probeinfo.checksum_received_ip_pkts=force->checksum_received_ip_pkts;				probeinfo.use_hw_stats=force->use_hw_stats;			}			else			{				probeinfo.port_protocol_no=0;				probeinfo.checksum_received_ip_pkts=model_info->default_checksum_received_ip_pkts;				probeinfo.use_hw_stats=model_info->default_use_hw_stats;				probeinfo.memory_usage_in_k=0;				if(probe->chan_type&chandev_type_lcs)				{					hint=(read->sch.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;			probefunc=probe->probefunc;			rc=probefunc(&probeinfo);			if(rc==0)			{				newdevice=probeinfo.newdevice;				if(newdevice)				{					newdevice->probefunc=probe->probefunc;					newdevice->shutdownfunc=probe->shutdownfunc;					newdevice->msck_notfunc=probe->msck_notfunc;					probe->devices_found++;					chandev_add_to_list((list **)&chandev_activelist_head,							    newdevice);					chandev_add_to_userland_notify_list(chandev_start,								      newdevice->devname,chandev_status_good,chandev_status_good);				}				else				{					printk("chandev_initdevice either failed or wasn't called for device read_irq=0x%04x\n",probeinfo.read.irq);				}				break;							}		}	}	chandev_remove(read);	chandev_remove(write);	if(data)		chandev_remove(data);	return(rc);}int chandev_request_irq_from_irqinfo(chandev_irqinfo *irqinfo,chandev *this_chandev){	int retval=s390_request_irq_special(irqinfo->sch.irq,				   irqinfo->handler,				   chandev_not_oper_handler,				   irqinfo->irqflags,				   irqinfo->devname,				   irqinfo->dev_id);	if(retval==0)	{		irqinfo->msck_status=chandev_status_good;		this_chandev->owned=TRUE;	}	return(retval);}void chandev_irqallocerr(chandev_irqinfo *irqinfo,int err){	printk("chandev_probe failed to realloc irq=%d for %s err=%d\n",irqinfo->sch.irq,irqinfo->devname,err);}void chandev_call_notification_func(chandev_activelist *curr_device,chandev_irqinfo *curr_irqinfo,chandev_msck_status prevstatus){	if(curr_irqinfo->msck_status!=prevstatus)	{		chandev_msck_status new_msck_status=curr_irqinfo->msck_status;		if(curr_irqinfo->msck_status==chandev_status_good)		{			if(curr_device->read_irqinfo->msck_status==chandev_status_good&&			   curr_device->write_irqinfo->msck_status==chandev_status_good)			{				if(curr_device->data_irqinfo)				{					if(curr_device->data_irqinfo->msck_status==chandev_status_good)						new_msck_status=chandev_status_all_chans_good;				}				else					new_msck_status=chandev_status_all_chans_good;			}		}		if(curr_device->msck_notfunc)		{			curr_device->msck_notfunc(curr_device->dev_ptr,					      curr_irqinfo->sch.irq,					      prevstatus,new_msck_status);		}		if(new_msck_status!=chandev_status_good)		{			/* No point in sending a machine check if only one channel is good */			chandev_add_to_userland_notify_list(chandev_msck,curr_device->devname,						      prevstatus,curr_irqinfo->msck_status);		}	}}int chandev_find_eligible_channels(chandev *first_chandev_to_check,			       chandev **read,chandev **write,chandev **data,chandev **next,				   chandev_type chan_type){	chandev *curr_chandev;	int eligible_found=FALSE,changed;		*next=first_chandev_to_check->next;	*read=*write=*data=NULL;	for_each(curr_chandev,first_chandev_to_check)		if((curr_chandev->sch.devno&1)==0&&curr_chandev->model_info->chan_type!=chandev_type_claw)		{			*read=curr_chandev;			if(chan_type==chandev_type_none)				chan_type=(*read)->model_info->chan_type;			break;		}	if(*read)	{		for_each(curr_chandev,(chandev *)chandev_head.head)			if((((*read)->sch.devno|1)==curr_chandev->sch.devno)&&			   (chandev_compare_cu_dev_info(&(*read)->sch,&curr_chandev->sch)==0)&&			   ((chan_type&(chandev_type_ctc|chandev_type_escon))||			    chandev_compare_chpid_info(&(*read)->sch,&curr_chandev->sch)==0))			{				*write=curr_chandev;				break;			}	}	if((chan_type&chandev_type_qeth))	{		if(*write)		{			for_each(curr_chandev,(chandev *)chandev_head.head)				if((curr_chandev!=*read&&curr_chandev!=*write)&&				   (chandev_compare_cu_dev_info(&(*read)->sch,&curr_chandev->sch)==0)&&				   (chandev_compare_chpid_info(&(*read)->sch,&curr_chandev->sch)==0))				{					*data=curr_chandev;					break;				}			if(*data)				eligible_found=TRUE;		}			}	else		if(*write)			eligible_found=TRUE;	if(eligible_found)	{		do		{			changed=FALSE;			if(*next&&			   ((*read&&(*read==*next))||			   (*write&&(*write==*next))||			   (*data&&(*data==*next))))			{				*next=(*next)->next;				changed=TRUE;			}		}while(changed==TRUE);	}	return(eligible_found);}chandev *chandev_get_free_chandev_by_devno(int devno){	chandev *curr_chandev;	if(devno==-1)		return(NULL);	for_each(curr_chandev,(chandev *)chandev_head.head)		if(curr_chandev->sch.devno==devno)		{			if(chandev_active(devno))				return(NULL);			else				return(curr_chandev);		}	return(NULL);}void chandev_probe(void){	chandev *read_chandev,*write_chandev,*data_chandev,*curr_chandev,*next_chandev;	chandev_force *curr_force;	chandev_noauto_range *curr_noauto;	chandev_activelist *curr_device;	chandev_irqinfo *curr_irqinfo;	s390_dev_info_t curr_devinfo;	int  err;	int auto_msck_recovery;	chandev_msck_status prevstatus;	chandev_msck_range *curr_msck_range;	chandev_interrupt_check();	chandev_read_conf_if_necessary();	chandev_collect_devices();	chandev_lock();	for_each(curr_irqinfo,chandev_irqinfo_head)	{		if((curr_device=chandev_get_activelist_by_irq(curr_irqinfo->sch.irq)))		{			prevstatus=curr_irqinfo->msck_status;			if(curr_irqinfo->msck_status!=chandev_status_good)			{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -