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

📄 chandev.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  drivers/s390/misc/chandev.c *    common channel device layer * *  S390 version *    Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) */#define __KERNEL_SYSCALLS__#include <linux/config.h>#include <linux/types.h>#include <linux/ctype.h>#include <asm/queue.h>#include <asm/uaccess.h>#include <linux/slab.h>#include <asm/irq.h>#include <linux/init.h>#include <linux/unistd.h>#include <asm/chandev.h>#include <linux/proc_fs.h>#include <linux/vmalloc.h>static chandev_model_info *chandev_models_head=NULL;static chandev *chandev_head=NULL;static chandev_noauto_range *chandev_noauto_head=NULL;static chandev_force *chandev_force_head=NULL;static chandev_probelist *chandev_probelist_head=NULL;static int use_devno_names=FALSE;static int chandev_conf_read=FALSE;static void *chandev_alloc_listmember(list **listhead,size_t size){	void *newmember=kmalloc(size, GFP_KERNEL);	if(newmember)		add_to_list(listhead,newmember);	return(newmember);}void chandev_free_listmember(list **listhead,list *member){	if(remove_from_list(listhead,member))		kfree(member);	else		printk(KERN_CRIT"chandev_free_listmember detected nonexistant"		       "listmember listhead=%p member %p\n",listhead,member);}void chandev_free_all(list **listhead){	while(*listhead)		chandev_free_listmember(listhead,*listhead);}void chandev_add_model(chandev_type chan_type,u16 cu_type,u8 cu_model,u8 max_port_no){	chandev_model_info *newmodel;	if((newmodel=chandev_alloc_listmember(		(list **)&chandev_models_head,sizeof(chandev_model_info))))	{		newmodel->chan_type=chan_type;		newmodel->cu_type=cu_type;		newmodel->cu_model=cu_model;		newmodel->max_port_no=max_port_no;	}}void chandev_remove(chandev *member){	chandev_free_listmember((list **)&chandev_head,(list *)member);}void chandev_remove_all(void){	chandev_free_all((list **)&chandev_head);}void chandev_remove_model(chandev_model_info *model){	chandev *curr_chandev;	for(curr_chandev=chandev_head;curr_chandev!=NULL;		    curr_chandev=curr_chandev->next)		if(curr_chandev->model_info==model)			chandev_remove(curr_chandev);	chandev_free_listmember((list **)&chandev_models_head,(list *)model);}void chandev_remove_all_models(void){	while(chandev_models_head)		chandev_remove_model(chandev_models_head);}void chandev_del_model(u16 cu_type,u8 cu_model){	chandev_model_info *curr_model;	for(curr_model=chandev_models_head;curr_model!=NULL;		    curr_model=curr_model->next)		if(curr_model->cu_type==cu_type&&curr_model->cu_model==cu_model)			chandev_remove_model(curr_model);			}static void chandev_init_default_models(void){	/* P390/Planter 3172 emulation assume maximum 16 to be safe. */	chandev_add_model(lcs,0x3088,0x1,15);		/* 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(lcs|ctc,0x3088,0x8,15);	/* 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(lcs|escon,0x3088,0x1F,15);	/* Only 2 ports allowed on OSA2 cards model 0x60 */	chandev_add_model(lcs,0x3088,0x60,1);	/* Osa-D we currently aren't too emotionally involved with this */	chandev_add_model(osad,0x3088,0x62,0);}void chandev_add(dev_info_t  *newdevinfo,chandev_model_info *newmodelinfo){	chandev *new_chandev;	if((new_chandev=chandev_alloc_listmember(		(list **)&chandev_head,sizeof(chandev))))	{		new_chandev->model_info=newmodelinfo;		new_chandev->devno=newdevinfo->devno;		new_chandev->irq=newdevinfo->irq;	}}void chandev_collect_devices(void){	int curr_irq,loopcnt=0,err;	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;		}		if((err=get_dev_info_by_irq(curr_irq,&curr_devinfo)))		{			printk("chandev_collect_devices get_dev_info_by_irq reported err=%X on irq %d\n"			       "should not happen\n",err,curr_irq);			continue;		}		for(curr_model=chandev_models_head;curr_model!=NULL;		    curr_model=curr_model->next)		{			if((curr_model->cu_type==curr_devinfo.sid_data.cu_type)&&			   (curr_model->cu_model==curr_devinfo.sid_data.cu_model)			   &&((curr_devinfo.status&DEVSTAT_DEVICE_OWNED)==0))				chandev_add(&curr_devinfo,curr_model);		}	}}void chandev_add_force(chandev_type chan_type,s32 devif_num,u16 read_devno,u16 write_devno,s16 port_no,u8 do_ip_checksumming,u8 use_hw_stats){	chandev_force *new_chandev_force;	if((new_chandev_force=chandev_alloc_listmember(		(list **)&chandev_force_head,sizeof(chandev_force))))	{		new_chandev_force->chan_type=chan_type;		new_chandev_force->devif_num=devif_num;		new_chandev_force->read_devno=read_devno;		new_chandev_force->write_devno=write_devno;		new_chandev_force->port_no=port_no;		new_chandev_force->do_ip_checksumming=do_ip_checksumming;		new_chandev_force->use_hw_stats=use_hw_stats;	}}void chandev_del_force(u16 read_devno){	chandev_force *curr_force;	for(curr_force=chandev_force_head;curr_force!=NULL;		    curr_force=curr_force->next)	{		if(curr_force->read_devno==read_devno)			chandev_free_listmember((list **)&chandev_force_head,						(list *)curr_force);	}}void chandev_pack_args(char *str){	char *newstr=str;	while(*str)	{		if(isspace(*str))			str++;		else			*newstr++=*str++;	}	*newstr=0;}typedef enum{ 	isnull=0,	isstr=1,	isnum=2,	iscomma=4,} chandev_strval;chandev_strval chandev_strcmp(char *teststr,char **str,long *endlong){	char *cur=*str;	chandev_strval  retval=isnull;	int len=strlen(teststr);	if(strncmp(teststr,*str,len)==0)	{		*str+=len;		retval=isstr;		*endlong=simple_strtol(cur,str,0);		if(cur!=*str)			retval|=isnum;		if(**str==',')			retval|=iscomma;	}	return(retval);}static char *argstrs[]={	"noauto",	"lcs",	"ctc",	"escon",	"del_force",	"use_devno_names"	"dont_use_devno_names",	"add_model"	"del_model"	"del_all_models"};typedef enum{	stridx_mult=16,	first_stridx=0,	noauto_stridx=first_stridx,	lcs_stridx,	ctc_stridx,	escon_stridx,	del_force_stridx,	use_devno_names_stridx,	dont_use_devno_names_stridx,	add_model_stridx,	del_model_stridx,	del_all_models_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_listmember(		(list **)&chandev_noauto_head,sizeof(chandev_noauto_range))))	{		new_range->lo_devno=lo_devno;		new_range->hi_devno=hi_devno;	}}static char chandev_keydescript[]="chan_type key bitfield\nctc=0x1,escon=0x2,lcs=0x4,lcs=0x4,osad=0x8,claw=0x16\n";static void chandev_print_args(void){	printk("valid chandev arguments are"                 "<> indicate optional parameters | indicate a choice.\n");	printk("noauto,<lo_devno>,<hi_devno>\n"               "don't probe a range of device numbers for channel devices\n");	printk("lcs|ctc|escon<devif_num>,read_devno,write_devno,<port_no>,"	       "<do_ip_checksumming>,<use_hw_stats>\n");	printk("e.g. ctc0,0x7c00,0x7c01,-1,0,0\n");	printk("     tells the channel layer to force ctc0 if detected to use\n"	       "     cuu's 7c00 & 7c01 port ( rel adapter no ) is invalid for\n"	       "     ctc's so use -1 don't do checksumming on received ip\n"               "     packets & as ctc doesn't have hardware stats ignore this\n"               "     parameter\n\n");	printk("del_force read_devno\n"       "delete a forced channel device from force list.\n");	printk("use_devno_names, tells the channel layer to assign device\n"               "names based on the read channel cuu number\n"	       "e.g. a token ring read channel 0x7c00 would have an interface"	       "called tr0x7c00 this avoids name collisions on devices.");	printk("add_model chan_type cu_model max_port no\n"	       "tells the channel layer to probe for the device described\n");	printk("%s use max_port_no of 0 for devices where this field "       "is invalid.\n",chandev_keydescript);	printk("del_model cu_type cu_model\n");	printk("del_all_models\n");}static int chandev_setup(char *str){	chandev_strval   val=isnull;	chandev_str_enum stridx;	long             endlong;	chandev_type     chan_type;#define CHANDEV_MAX_EXTRA_INTS 5	int ints[CHANDEV_MAX_EXTRA_INTS+1];	memset(ints,0,sizeof(ints));	chandev_pack_args(str);	for(stridx=first_stridx;stridx<last_stridx;stridx++)		if((val=chandev_strcmp(argstrs[stridx],&str,&endlong)))			break;	if(val)	{		if(val&iscomma)			get_options(str,CHANDEV_MAX_EXTRA_INTS,ints);		else			ints[0]=0;		val=(((chandev_strval)stridx)*stridx_mult)+(val&~isstr);		switch(val)		{		case noauto_stridx*stridx_mult:		case (noauto_stridx*stridx_mult)|iscomma:			switch(ints[0])			{			case 0: 				chandev_free_all((list **)&chandev_noauto_head);				chandev_add_noauto(0,0xffff);				break;			case 1:				ints[2]=ints[1];			case 2:				chandev_add_noauto(ints[1],ints[2]);						}			break;		case (ctc_stridx*stridx_mult)|isnum|iscomma:		case (escon_stridx*stridx_mult)|isnum|iscomma:		case (lcs_stridx*stridx_mult)|isnum|iscomma:			switch(val)			{			case (ctc_stridx*stridx_mult)|isnum|iscomma:				chan_type=ctc;				break;			case (escon_stridx*stridx_mult)|isnum|iscomma:				chan_type=escon;				break;			case (lcs_stridx*stridx_mult)|isnum|iscomma:				chan_type=lcs;				break;			default:				goto BadArgs;			}			chandev_add_force(chan_type,endlong,ints[1],ints[2],					  ints[3],ints[4],ints[5]);			break;

⌨️ 快捷键说明

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