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

📄 chandev.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 5 页
字号:
				curr_chandev=chandev_get_by_irq(curr_irqinfo->sch.irq);				if(curr_chandev)				{					auto_msck_recovery=curr_chandev->model_info->						auto_msck_recovery;				}				else					goto remove;				for_each(curr_msck_range,chandev_msck_range_head)				{					if(curr_msck_range->lo_devno<=					   curr_irqinfo->sch.devno&&					   curr_msck_range->hi_devno>=					   curr_irqinfo->sch.devno)					{						auto_msck_recovery=							curr_msck_range->							auto_msck_recovery;						break;					}				}				if((1<<(curr_irqinfo->msck_status-1))&auto_msck_recovery)				{					if(curr_irqinfo->msck_status==chandev_status_revalidate)					{						if((get_dev_info_by_irq(curr_irqinfo->sch.irq,&curr_devinfo)==0))						{							curr_irqinfo->sch.devno=curr_devinfo.devno;							curr_irqinfo->msck_status=chandev_status_good;						}					}					else					{						if(curr_chandev)						{							/* Has the device reappeared */							if(chandev_compare_subchannel_info(								&curr_chandev->sch,								&curr_device->read_irqinfo->sch)||							   chandev_compare_subchannel_info(								&curr_chandev->sch,								&curr_device->write_irqinfo->sch)||							   (curr_device->data_irqinfo&&							    chandev_compare_subchannel_info(								    &curr_chandev->sch,								    &curr_device->data_irqinfo->sch)))							{								if((err=chandev_request_irq_from_irqinfo(curr_irqinfo,curr_chandev))==0)									curr_irqinfo->msck_status=chandev_status_good;								else									chandev_irqallocerr(curr_irqinfo,err);							}											}					}				}			}			chandev_call_notification_func(curr_device,curr_irqinfo,prevstatus);		}		/* This is required because the device can go & come back */                /* even before we realize it is gone owing to the waits in our kernel threads */		/* & the device will be marked as not owned but its status will be good */                /* & an attempt to accidently reprobe it may be done. */ 		remove:		chandev_remove(chandev_get_by_irq(curr_irqinfo->sch.irq));			}	/* extra sanity */	for_each_allow_delete(curr_chandev,next_chandev,(chandev *)chandev_head.head)		if(curr_chandev->owned)			chandev_remove(curr_chandev);	for_each(curr_force,chandev_force_head)	{		if(curr_force->devif_num==-2)		{			for_each_allow_delete2(curr_chandev,next_chandev,(chandev *)chandev_head.head)			{				if(chandev_find_eligible_channels(curr_chandev,&read_chandev,								  &write_chandev,&data_chandev,								  &next_chandev,								  curr_force->chan_type));				{					if((curr_force->read_lo_devno>=read_chandev->sch.devno)&&					   (curr_force->write_hi_devno<=read_chandev->sch.devno)&&					   (curr_force->read_lo_devno>=write_chandev->sch.devno)&&					   (curr_force->write_hi_devno<=write_chandev->sch.devno)&&					   (!data_chandev||(data_chandev&&					   (curr_force->read_lo_devno>=data_chandev->sch.devno)&&					   (curr_force->write_hi_devno<=data_chandev->sch.devno))))						chandev_doprobe(curr_force,read_chandev,write_chandev,								data_chandev);				}			}		}		else		{			read_chandev=chandev_get_free_chandev_by_devno(curr_force->read_lo_devno);			if(read_chandev)			{				write_chandev=chandev_get_free_chandev_by_devno(curr_force->write_hi_devno);				if(write_chandev)				{					if(curr_force->chan_type==chandev_type_qeth)					{						data_chandev=chandev_get_free_chandev_by_devno(curr_force->data_devno);						if(data_chandev==NULL)							printk("chandev_probe unable to force gigabit_ethernet driver invalid device  no 0x%04x given\n",curr_force->data_devno);					}					else						data_chandev=NULL;					chandev_doprobe(curr_force,read_chandev,write_chandev,							data_chandev);				}			}		}	}	for_each_allow_delete(curr_chandev,next_chandev,(chandev *)chandev_head.head)	{		for_each(curr_noauto,chandev_noauto_head)		{			if(curr_chandev->sch.devno>=curr_noauto->lo_devno&&			   curr_chandev->sch.devno<=curr_noauto->hi_devno)			{				chandev_remove(curr_chandev);				break;			}		}	}	for_each_allow_delete2(curr_chandev,next_chandev,(chandev *)chandev_head.head)	{		if(chandev_find_eligible_channels(curr_chandev,&read_chandev,						  &write_chandev,&data_chandev,						  &next_chandev,						  chandev_type_none))			chandev_doprobe(NULL,read_chandev,write_chandev,					data_chandev);	}	chandev_remove_all();	chandev_unlock();}static void chandev_not_oper_func(int irq,int status){	chandev_irqinfo *curr_irqinfo;	chandev_activelist *curr_device;		chandev_lock();	for_each(curr_irqinfo,chandev_irqinfo_head)		if(curr_irqinfo->sch.irq==irq)		{			chandev_msck_status prevstatus=curr_irqinfo->msck_status;			switch(status)			{				/* Currently defined but not used in kernel */				/* Despite being in specs */			case DEVSTAT_NOT_OPER:				curr_irqinfo->msck_status=chandev_status_not_oper;				break;#ifdef DEVSTAT_NO_PATH				/* Kernel hasn't this defined currently. */				/* Despite being in specs */			case DEVSTAT_NO_PATH:				curr_irqinfo->msck_status=chandev_status_no_path;				break;#endif			case DEVSTAT_REVALIDATE:				curr_irqinfo->msck_status=chandev_status_revalidate;				break;			case DEVSTAT_DEVICE_GONE:				curr_irqinfo->msck_status=chandev_status_gone;				break;                        }                        if((curr_device=chandev_get_activelist_by_irq(irq)))					chandev_call_notification_func(curr_device,curr_irqinfo,prevstatus); 			else				printk("chandev_not_oper_func received channel check for unowned irq %d",irq);		}	chandev_unlock();}static int chandev_msck_thread(void *unused){	int loopcnt,not_oper_probe_required=FALSE;	wait_queue_head_t    wait;	chandev_not_oper_struct *new_not_oper;	/* This loop exists because machine checks tend to come in groups & we have           to wait for the other devnos to appear also */	init_waitqueue_head(&wait);	for(loopcnt=0;loopcnt<10||(jiffies-chandev_last_machine_check)<HZ;loopcnt++)	{		sleep_on_timeout(&wait,HZ);	}	atomic_set(&chandev_msck_thread_lock,1);	while(!atomic_compare_and_swap(TRUE,FALSE,&chandev_new_msck));	{		chandev_probe();	}	while(TRUE)	{				unsigned long        flags; 		spin_lock_irqsave(&chandev_not_oper_spinlock,flags);		new_not_oper=(chandev_not_oper_struct *)dequeue_head(&chandev_not_oper_head);		spin_unlock_irqrestore(&chandev_not_oper_spinlock,flags);		if(new_not_oper)		{			chandev_not_oper_func(new_not_oper->irq,new_not_oper->status);			not_oper_probe_required=TRUE;			kfree(new_not_oper);		}		else			break;	}	if(not_oper_probe_required)		chandev_probe();	return(0);}static void chandev_msck_task(void *unused){	if(kernel_thread(chandev_msck_thread,NULL,SIGCHLD)<0)	{		atomic_set(&chandev_msck_thread_lock,1);		printk("error making chandev_msck_thread kernel thread\n");	}}static char *argstrs[]={	"noauto",	"del_noauto",	"ctc",	"escon",	"lcs",	"osad",	"qeth",	"claw",	"add_parms",	"del_parms",	"del_force",#if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)	"use_devno_names",	"dont_use_devno_names",#endif	"cautious_auto_detect",	"non_cautious_auto_detect",	"add_model",	"del_model",	"auto_msck",	"del_auto_msck",	"del_all_models",	"reset_conf_clean",	"reset_conf",	"shutdown",	"reprobe",	"unregister_probe",	"unregister_probe_by_chan_type",	"read_conf",	"dont_read_conf",	"persist"};typedef enum{	stridx_mult=256,	first_stridx=0,	noauto_stridx=first_stridx,	del_noauto_stridx,	ctc_stridx,	escon_stridx,	lcs_stridx,	osad_stridx,        qeth_stridx,	claw_stridx,	add_parms_stridx,	del_parms_stridx,	del_force_stridx,#if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)	use_devno_names_stridx,	dont_use_devno_names_stridx,#endif	cautious_auto_detect_stridx,	non_cautious_auto_detect_stridx,	add_model_stridx,	del_model_stridx,	auto_msck_stridx,	del_auto_msck_stridx,	del_all_models_stridx,	reset_conf_clean_stridx,	reset_conf_stridx,	shutdown_stridx,	reprobe_stridx,	unregister_probe_stridx,	unregister_probe_by_chan_type_stridx,	read_conf_stridx,	dont_read_conf_stridx,	persist_stridx,	last_stridx,} chandev_str_enum;void chandev_add_noauto(u16 lo_devno,u16 hi_devno){	chandev_noauto_range *new_range;	if((new_range=chandev_alloc(sizeof(chandev_noauto_range))))	{		new_range->lo_devno=lo_devno;		new_range->hi_devno=hi_devno;		chandev_add_to_list((list **)&chandev_noauto_head,new_range);	}}void chandev_add_msck_range(u16 lo_devno,u16 hi_devno,int auto_msck_recovery){	chandev_msck_range *new_range;	if((new_range=chandev_alloc(sizeof(chandev_msck_range))))	{		new_range->lo_devno=lo_devno;		new_range->hi_devno=hi_devno;		new_range->auto_msck_recovery=auto_msck_recovery;		chandev_add_to_list((list **)&chandev_msck_range_head,new_range);	}}static char chandev_keydescript[]="\nchan_type key bitfield ctc=0x1,escon=0x2,lcs=0x4,osad=0x8,qeth=0x10,claw=0x20\n";#if  CONFIG_ARCH_S390X/* We need this as we sometimes use this to evaluate pointers */typedef long chandev_int; #elsetypedef int chandev_int;#endif#if (LINUX_VERSION_CODE<KERNEL_VERSION(2,3,0)) || (CONFIG_ARCH_S390X)/* * Read an int from an option string; if available accept a subsequent * comma as well. * * Return values: * 0 : no int in string * 1 : int found, no subsequent comma * 2 : int found including a subsequent comma */static chandev_int chandev_get_option(char **str,chandev_int *pint){    char *cur = *str;    if (!cur || !(*cur)) return 0;    *pint = simple_strtol(cur,str,0);    if (cur==*str) return 0;    if (**str==',') {        (*str)++;        return 2;    }    return 1;}static char *chandev_get_options(char *str, int nints, chandev_int *ints){	int res,i=1;	while (i<nints) 	{		res = chandev_get_option(&str, ints+i);		if (res==0) break;		i++;		if (res==1) break;	}	ints[0] = i-1;	return(str);}#else#define chandev_get_option get_option#define chandev_get_options get_options#endif/* * Read an string from an option string; if available accept a subsequent * comma as well & set this comma to a null character when returning the string. * * Return values: * 0 : no string found * 1 : string found, no subsequent comma * 2 : string found including a subsequent comma */static int chandev_get_string(char **instr,char **outstr){	char *cur = *instr;	if (!cur ||*cur==0)	{		*outstr=NULL;		return 0;	}	*outstr=*instr;	for(;;)	{		if(*(++cur)==',')		{			*cur=0;			*instr=cur+1;			return 2;		}		else if(*cur==0)		{			*instr=cur+1;			return 1;		}	}}static int chandev_setup(int in_read_conf,char *instr,char *errstr,int lineno){	chandev_strval   val=isnull;	chandev_str_enum stridx;	long             endlong;	chandev_type     chan_type;	char             *str,*currstr,*interpretstr=NULL;	int              cnt,strcnt;	int              retval=0;#define CHANDEV_MAX_EXTRA_INTS 12	chandev_int ints[CHANDEV_MAX_EXTRA_INTS+1];	currstr=alloca(strlen(instr)+1);	strcpy(currstr,instr);	strcnt=chandev_pack_args(currstr);	for(cnt=1;cnt<=strcnt;cnt++)	{		interpretstr=currstr;		memset(ints,0,sizeof(ints));		for(stridx=first_stridx;stridx<last_stridx;stridx++)		{			str=currstr;			if((val=chandev_strcmp(argstrs[stridx],&str,&endlong)))				break;		}		currstr=str;		if(val)		{			val=(((chandev_strval)stridx)*stridx_mult)+(val&~isstr);			switch(val)			{			case (add_parms_stridx*stridx_mult)|iscomma:				currstr=chandev_get_options(currstr,4,ints);				if(*currstr&&ints[0]>=1)				{					if(ints[0]==1)					{						ints[2]=0;						ints[3]=0xffff;					}					else if(ints[0]==2)						ints[3]=ints[2];					chandev_add_parms(ints[1],ints[2],ints[3],currstr);					goto NextOption;				}				else					goto BadArgs;				break;			case (claw_stridx*stridx_mult)|isnum|iscomma:			case (claw_stridx*stridx_mult)|iscomma:				currstr=chandev_get_options(str,6,ints);				break;			default:				if(val&iscomma)					currstr=chandev_get_options(str,CHANDEV_MAX_EXTRA_INTS,ints);				break;			}			switch(val)			{			case noauto_stridx*stridx_mult:			case (noauto_stridx*stridx_mult)

⌨️ 快捷键说明

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