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

📄 chandev.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 5 页
字号:
static void chandev_wait_for_root_fs(void){	wait_queue_head_t      wait;	init_waitqueue_head(&wait);	/* We need to wait till there is a root filesystem */	while(init_task.fs->root==NULL)	{		sleep_on_timeout(&wait,HZ);	}}/* We are now hotplug compliant i.e. *//* we typically get called in /sbin/hotplug chandev our parameters */static int chandev_exec_start_script(void *unused){		char **argv,*tempname;	int retval=-ENOMEM;	int argc,loopcnt;	size_t allocsize;	chandev_userland_notify_list *member;	wait_queue_head_t      wait;	int                    have_tag[chandev_num_notify_tags]={FALSE,};	chandev_userland_notify_tag tagidx;	static char * envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };		init_waitqueue_head(&wait);	strcpy(current->comm,"chandev_script");	for(loopcnt=0;loopcnt<10&&(jiffies-chandev_last_startmsck_list_update)<HZ;loopcnt++)	{		sleep_on_timeout(&wait,HZ);	}	if(!chandev_userland_notify_head)		return(0);	chandev_lock();	argc=2;	for(tagidx=chandev_first_tag;tagidx<chandev_num_notify_tags;tagidx++)	{		for_each(member,chandev_userland_notify_head)		{			if(member->tag==tagidx)			{				switch(tagidx)				{				case chandev_start:					argc++;					break;				case chandev_msck:					argc+=3;					break;				default:				}				if(have_tag[tagidx]==FALSE)					argc++;				have_tag[tagidx]=TRUE;			}		}	}	allocsize=(argc+1)*sizeof(char *);        /* Warning possible stack overflow */	/* We can't kmalloc the parameters here as execve will */	/* not return if successful */	argv=alloca(allocsize);	if(argv)	{		memset(argv,0,allocsize);		argv[0]=hotplug_path;		argv[1]="chandev";		argc=2;		for(tagidx=chandev_first_tag;tagidx<chandev_num_notify_tags;tagidx++)		{			if(have_tag[tagidx])			{				argv[argc++]=userland_notify_strs[tagidx];				for_each(member,chandev_userland_notify_head)				{					if(member->tag==tagidx)					{						tempname=alloca(strlen(member->devname)+1);						if(tempname)						{							strcpy(tempname,member->devname);							argv[argc++]=tempname;						}						else							goto Fail;						if(member->tag==chandev_msck)						{							argv[argc++]=msck_status_strs[member->prev_status];							argv[argc++]=msck_status_strs[member->curr_status];						}					}				}			}		}		chandev_free_all_list((list **)&chandev_userland_notify_head);		chandev_unlock();		chandev_wait_for_root_fs();		/* We are basically execve'ing here there normally is no */		/* return */		retval=exec_usermodehelper(hotplug_path, argv, envp);		goto Fail2;	} Fail:		chandev_unlock(); Fail2:	return(retval);}void *chandev_allocstr(const char *str,size_t offset){	char *member;	if((member=chandev_alloc(offset+strlen(str)+1)))	{		strcpy(&member[offset],str);	}	return((void *)member);}static int chandev_add_to_userland_notify_list(chandev_userland_notify_tag tag,char *devname, chandev_msck_status prev_status,chandev_msck_status curr_status){	chandev_userland_notify_list *member,*nextmember;	int pid;		chandev_lock();	/* remove operations still outstanding for this device */	for_each_allow_delete(member,nextmember,chandev_userland_notify_head)		if(strcmp(member->devname,devname)==0)			chandev_free_listmember((list **)&chandev_userland_notify_head,(list *)member);		if((member=chandev_allocstr(devname,offsetof(chandev_userland_notify_list,devname))))	{		member->tag=tag;		member->prev_status=prev_status;		member->curr_status=curr_status;		add_to_list((list **)&chandev_userland_notify_head,(list *)member);		chandev_last_startmsck_list_update=jiffies;		chandev_unlock();		pid = kernel_thread(chandev_exec_start_script,NULL,SIGCHLD);		if(pid<0)		{			printk("error making kernel thread for chandev_exec_start_script\n");			return(pid);		}		else			return(0);	}	else	{		chandev_unlock();		printk("chandev_add_to_startmscklist memory allocation failed devname=%s\n",devname);		return(-ENOMEM);	}}int chandev_oper_func(int irq,devreg_t *dreg){	chandev_last_machine_check=jiffies;	if(atomic_dec_and_test(&chandev_msck_thread_lock))	{		schedule_task(&chandev_msck_task_tq);	}	atomic_set(&chandev_new_msck,TRUE);	return(0);}static void chandev_not_oper_handler(int irq,int status ){	chandev_not_oper_struct *new_not_oper;	chandev_last_machine_check=jiffies;	if((new_not_oper=kmalloc(sizeof(chandev_not_oper_struct),GFP_ATOMIC)))	{		new_not_oper->irq=irq;		new_not_oper->status=status;		spin_lock(&chandev_not_oper_spinlock);		enqueue_tail(&chandev_not_oper_head,(queue *)new_not_oper);		spin_unlock(&chandev_not_oper_spinlock);		if(atomic_dec_and_test(&chandev_msck_thread_lock))		{			schedule_task(&chandev_msck_task_tq);		}	}	else		printk("chandev_not_oper_handler failed to allocate memory & "		       "lost a not operational interrupt %d %x",		       irq,status);}chandev_irqinfo *chandev_get_irqinfo_by_irq(int irq){	chandev_irqinfo *curr_irqinfo;	for_each(curr_irqinfo,chandev_irqinfo_head)		if(irq==curr_irqinfo->sch.irq)			return(curr_irqinfo);	return(NULL);}chandev *chandev_get_by_irq(int irq){	chandev *curr_chandev;	for_each(curr_chandev,(chandev *)chandev_head.head)		if(curr_chandev->sch.irq==irq)		{			return(curr_chandev);		}	return(NULL);}chandev_activelist *chandev_get_activelist_by_irq(int irq){	chandev_activelist *curr_device;	for_each(curr_device,chandev_activelist_head)	{			if(curr_device->read_irqinfo->sch.irq==irq||			   curr_device->write_irqinfo->sch.irq==irq||			   (curr_device->data_irqinfo&&curr_device->data_irqinfo->sch.irq==irq))				return(curr_device);	}	return(NULL);}void chandev_remove_irqinfo_by_irq(unsigned int irq){	chandev_irqinfo *remove_irqinfo;	chandev_activelist *curr_device;	chandev_lock();	/* remove any orphan irqinfo left lying around. */        if((remove_irqinfo=chandev_get_irqinfo_by_irq(irq)))	{		for_each(curr_device,chandev_activelist_head)		{			if(curr_device->read_irqinfo==remove_irqinfo)			{				curr_device->read_irqinfo=NULL;				break;			}			if(curr_device->write_irqinfo==remove_irqinfo)			{				curr_device->write_irqinfo=NULL;				break;			}			if(curr_device->data_irqinfo&&curr_device->data_irqinfo==remove_irqinfo)			{				curr_device->data_irqinfo=NULL;				break;			}		}		chandev_free_listmember((list **)&chandev_irqinfo_head,					 (list *)remove_irqinfo);	}	chandev_unlock();	}int chandev_add_schib_info(int irq,chandev_subchannel_info *sch){	schib_t *new_schib;		if((new_schib=s390_get_schib(irq)))	{		sch->pim=new_schib->pmcw.pim;		memcpy(&sch->chpid,&new_schib->pmcw.chpid,sizeof(sch->chpid));		return(0);	}	return(-ENODEV);}int chandev_request_irq(unsigned int   irq,                      void           (*handler)(int, void *, struct pt_regs *),                      unsigned long  irqflags,                      const char    *devname,                      void          *dev_id){	chandev_irqinfo *new_irqinfo;	chandev_activelist *curr_device;	s390_dev_info_t         devinfo;	int          retval;		chandev_lock();	if((curr_device=chandev_get_activelist_by_irq(irq)))	{		printk("chandev_request_irq failed devname=%s irq=%d "		       "it already belongs to %s shutdown this device first.\n",		       devname,irq,curr_device->devname);		chandev_unlock();		return(-EPERM);	}	/* remove any orphan irqinfo left lying around. */	chandev_remove_irqinfo_by_irq(irq);	chandev_unlock();	if((new_irqinfo=chandev_allocstr(devname,offsetof(chandev_irqinfo,devname))))	{				if((retval=get_dev_info_by_irq(irq,&devinfo))||		   (retval=s390_request_irq_special(irq,handler,						chandev_not_oper_handler,						irqflags,devname,dev_id)))			kfree(new_irqinfo);		else		{			new_irqinfo->msck_status=chandev_status_good;			new_irqinfo->sch.devno=devinfo.devno;			new_irqinfo->sch.irq=irq;			new_irqinfo->sch.cu_type=devinfo.sid_data.cu_type; /* control unit type */			new_irqinfo->sch.cu_model=devinfo.sid_data.cu_model; /* control unit model */			new_irqinfo->sch.dev_type=devinfo.sid_data.dev_type; /* device type */			new_irqinfo->sch.dev_model=devinfo.sid_data.dev_model; /* device model */			chandev_add_schib_info(irq,&new_irqinfo->sch);			new_irqinfo->handler=handler;			new_irqinfo->dev_id=dev_id;			chandev_add_to_list((list **)&chandev_irqinfo_head,new_irqinfo);		}	}	else	{		printk("chandev_request_irq memory allocation failed devname=%s irq=%d\n",devname,irq);		retval=-ENOMEM;	}	return(retval);}/* This should be safe to call even multiple times. */void chandev_free_irq(unsigned int irq, void *dev_id){	s390_dev_info_t devinfo;	int err;		/* remove any orphan irqinfo left lying around. */	chandev_remove_irqinfo_by_irq(irq);	if((err=get_dev_info_by_irq(irq,&devinfo)))	{		printk("chandev_free_irq get_dev_info_by_irq reported err=%X on irq %d\n"		       "should not happen\n",err,irq);		return;	 }	if(devinfo.status&DEVSTAT_DEVICE_OWNED)	   free_irq(irq,dev_id);}/* This should be safe even if chandev_free_irq is already called by the device */void chandev_free_irq_by_irqinfo(chandev_irqinfo *irqinfo){	if(irqinfo)		chandev_free_irq(irqinfo->sch.irq,irqinfo->dev_id);}void chandev_sprint_type_model(char *buff,s32 type,s16 model){	if(type==-1)		strcpy(buff,"    *    ");	else		sprintf(buff," 0x%04x  ",(int)type);	buff+=strlen(buff);	if(model==-1)		strcpy(buff,"    *   ");	else		sprintf(buff," 0x%02x  ",(int)model);}void chandev_sprint_devinfo(char *buff,s32 cu_type,s16 cu_model,s32 dev_type,s16 dev_model){	chandev_sprint_type_model(buff,cu_type,cu_model);	chandev_sprint_type_model(&buff[strlen(buff)],dev_type,dev_model);}void chandev_remove_parms(chandev_type chan_type,int exact_match,int lo_devno){	chandev_parms      *curr_parms,*next_parms;	chandev_lock();	for_each_allow_delete(curr_parms,next_parms,chandev_parms_head)	{		if(((chan_type&(curr_parms->chan_type)&&!exact_match)||		   (chan_type==(curr_parms->chan_type)&&exact_match))&&		   (lo_devno==-1||lo_devno==curr_parms->lo_devno))			chandev_free_listmember((list **)&chandev_parms_head,(list *)curr_parms);	}	chandev_unlock();}void chandev_add_parms(chandev_type chan_type,u16 lo_devno,u16 hi_devno,char *parmstr){	chandev_parms      *parms;	if(lo_devno>hi_devno)	{		printk("chandev_add_parms detected bad device range lo_devno=0x%04x  hi_devno=0x%04x\n,",		       (int)lo_devno,(int)hi_devno);		return;	}	chandev_lock();	for_each(parms,chandev_parms_head)	{		if(chan_type&(parms->chan_type))		{			u16 lomax=MAX(parms->lo_devno,lo_devno),				himin=MIN(parms->hi_devno,lo_devno);			if(lomax<=himin)			{				chandev_unlock();				printk("chandev_add_parms detected overlapping "				       "parameter definitions for chan_type=0x%02x"				       " lo_devno=0x%04x  hi_devno=0x%04x\n,"				       " do a del_parms.",chan_type,(int)lo_devno,(int)hi_devno);				return;			}		}	}	chandev_unlock();	if((parms=chandev_allocstr(parmstr,offsetof(chandev_parms,parmstr))))	{		parms->chan_type=chan_type;		parms->lo_devno=lo_devno;		parms->hi_devno=hi_devno;		chandev_add_to_list((list **)&chandev_parms_head,(void *)parms);	}	else		printk("chandev_add_parms memory request failed\n");}void chandev_add_model(chandev_type chan_type,s32 cu_type,s16 cu_model,		       s32 dev_type,s16 dev_model,u8 max_port_no,int auto_msck_recovery,		       u8 default_checksum_received_ip_pkts,u8 default_use_hw_stats){	chandev_model_info *newmodel;	int                err;	char buff[40];	if((newmodel=chandev_alloc(sizeof(chandev_model_info))))	{		devreg_t *drinfo=&newmodel->drinfo;		newmodel->chan_type=chan_type;		newmodel->cu_type=cu_type;		newmodel->cu_model=cu_model;		newmodel->dev_type=dev_type;		newmodel->dev_model=dev_model;		newmodel->max_port_no=max_port_no;		newmodel->auto_msck_recovery=auto_msck_recovery;		newmodel->default_checksum_received_ip_pkts=default_checksum_received_ip_pkts;		newmodel->default_use_hw_stats=default_use_hw_stats; /* where available e.g. lcs */		if(cu_type==-1&&dev_type==-1)		{			chandev_sprint_devinfo(buff,newmodel->cu_type,newmodel->cu_model,					       newmodel->dev_type,newmodel->dev_model);			printk(KERN_INFO"can't call s390_device_register for this device chan_type/chan_model/dev_type/dev_model %s\n",buff);			kfree(newmodel);			return;		}		drinfo->flag=DEVREG_TYPE_DEVCHARS;		if(cu_type!=-1)			drinfo->flag|=DEVREG_MATCH_CU_TYPE;		if(cu_model!=-1)			drinfo->flag|=DEVREG_MATCH_CU_MODEL;		if(dev_type!=-1)			drinfo->flag|=DEVREG_MATCH_DEV_TYPE;		if(dev_model!=-1)			drinfo->flag|=DEVREG_MATCH_DEV_MODEL;		drinfo->ci.hc.ctype=cu_type;		drinfo->ci.hc.cmode=cu_model;		drinfo->ci.hc.dtype=dev_type;		drinfo->ci.hc.dmode=dev_model;		drinfo->oper_func=chandev_oper_func;		if((err=s390_device_register(&newmodel->drinfo)))		{			chandev_sprint_devinfo(buff,newmodel->cu_type,newmodel->cu_model,					       newmodel->dev_type,newmodel->dev_model);			printk("s390_device_register failed in chandev_add_model"

⌨️ 快捷键说明

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