dasd.c

来自「linux-2.4.29操作系统的源码」· C语言 代码 · 共 2,133 行 · 第 1/5 页

C
2,133
字号
	spin_lock_irqsave (&range_lock, flags);	list_for_each (l, &dasd_range_head.list) {		temp = list_entry (l, dasd_range_t, list);                if ( devindex < temp->to - temp->from + 1) {			spin_unlock_irqrestore (&range_lock, flags);			return temp->from + devindex;		}		devindex -= temp->to - temp->from + 1;	}	spin_unlock_irqrestore (&range_lock, flags);	return -ENODEV;}/******************************************************************************** * SECTION: parsing the dasd= parameter of the parmline/insmod cmdline  ********************************************************************************//* * char *dasd[] is intended to hold the ranges supplied by the dasd= statement * it is named 'dasd' to directly be filled by insmod with the comma separated * strings when running as a module. * a maximum of 256 ranges can be supplied, as the parmline is limited to * <1024 Byte anyway. */char *dasd[256];char *dasd_disciplines[8];#ifndef MODULE/* * function: dasd_split_parm_string * splits the parmline given to the kernel into comma separated strings * which are filled into the 'dasd[]' array, to be parsed later on */static voiddasd_split_parm_string (char *str){	char *tmp = str;	int count = 0;	while (tmp != NULL && *tmp != '\0') {		char *end;		int len;		end = strchr (tmp, ',');		if (end == NULL) {			len = strlen (tmp) + 1;		} else {			len = (long) end - (long) tmp + 1;			*end = '\0';			end++;		}		dasd[count] = kmalloc (len * sizeof (char),                                        GFP_ATOMIC);		if (dasd[count] == NULL) {			MESSAGE (KERN_WARNING,                                 "can't store dasd= parameter no"                                 " %d",                                 count + 1);			break;		}		memset (dasd[count], 0, len * sizeof (char));		memcpy (dasd[count], tmp, len * sizeof (char));		count++;		tmp = end;	};}/* * dasd_parm_string holds a concatenated version of all 'dasd=' parameters * supplied in the parmline, which is later to be split by * dasd_split_parm_string * FIXME: why first concatenate then split ? */static char dasd_parm_string[1024] __initdata = { 0, };/* * function: dasd_setup * is invoked for any single 'dasd=' parameter supplied in the parmline * it merges all the arguments into dasd_parm_string */void __initdasd_setup (char *str, int *ints){	int len = strlen (dasd_parm_string);	if (len != 0) {		strcat (dasd_parm_string, ",");	}	strcat (dasd_parm_string, str);}/* * function: dasd_call_setup * is the 2.4 version of dasd_setup and * is invoked for any single 'dasd=' parameter supplied in the parmline */int __initdasd_call_setup (char *str){	int dummy;	dasd_setup (str, &dummy);	return 1;}int __initdasd_disciplines_setup (char *str){	return 1;}__setup ("dasd=", dasd_call_setup);__setup ("dasd_disciplines=", dasd_disciplines_setup);#endif				/* MODULE *//* * function: dasd_strtoul * provides a wrapper to simple_strtoul to strip leading '0x' and * interpret any argument to dasd=[range,...] as hexadecimal */static inline intdasd_strtoul (char *str, char **stra, int* features){        char *temp=str;        char *buffer;        int val,i,start;        buffer=(char*)kmalloc((strlen(str)+1)*sizeof(char),GFP_ATOMIC);        if (buffer==NULL) {                MESSAGE_LOG (KERN_WARNING,                             "can't parse dasd= parameter %s due "                             "to low memory",                             str);        }        /* remove leading '0x' */        if (*temp == '0') {                temp++;         /* strip leading zero */                if (*temp == 'x')                        temp++; /* strip leading x */        }        /* copy device no to buffer and convert to decimal */        for (i=0; temp[i]!='\0' && temp[i]!='(' &&                   temp[i]!='-'  && temp[i]!=' '; i++){                if (isxdigit(temp[i])) {                        buffer[i]=temp[i];                } else {                        return -EINVAL;                }        }        buffer[i]='\0';        val = simple_strtoul (buffer, &buffer, 16);        /* check for features - e.g. (ro) ; the '\0', ')' and '-' stops check */        *features = DASD_FEATURE_DEFAULT;        if (temp[i]=='(') {                while (temp[i]!='\0' && temp[i]!=')'&&temp[i]!='-') {                         start=++i;                                      /* move next feature to buffer */                        for (;temp[i]!='\0'&&temp[i]!=':'&&temp[i]!=')'&&temp[i]!='-';i++)                                buffer[i-start]=temp[i];                        buffer[i-start]='\0';                        if (strlen(buffer)) {                                 if (!strcmp(buffer,"ro")) { /* handle 'ro' feature */                                        (*features) |= DASD_FEATURE_READONLY;                                        break;                                }                                MESSAGE_LOG (KERN_WARNING,                                             "unsupported feature: %s, "                                             "ignoring setting",                                             buffer);                        }                }        }        *stra = temp+i;        if ((val > 0xFFFF) || (val < 0))                return -EINVAL;        return val;}/* * function: dasd_parse * examines the strings given in the string array str and * creates and adds the ranges to the apropriate lists */static intdasd_parse (char **str){	char *temp;	int from, to;        int features;        int rc = 0;	while (*str) {		temp = *str;		from = 0;		to = 0;		if (strcmp ("autodetect", *str) == 0) {			dasd_autodetect = 1;			MESSAGE (KERN_INFO, "%s",                                 "turning to autodetection mode");			break;		} else if (strcmp ("probeonly", *str) == 0) {			dasd_probeonly = 1;			MESSAGE (KERN_INFO, "%s",                                 "turning to probeonly mode");			break;		} else {			/* turn off autodetect mode, if any range is present */			dasd_autodetect = 0;			from = dasd_strtoul (temp, &temp, &features);                        to = from;			if (*temp == '-') {				temp++;				to = dasd_strtoul (temp, &temp, &features);			}                        if (from == -EINVAL ||                            to   == -EINVAL    ) {                                rc = -EINVAL;                                break;                        } else {                                dasd_add_range (from, to ,features);                        }                }		str++;	}        return rc;}/******************************************************************************** * SECTION: Dealing with devices registered to multiple major numbers  ********************************************************************************/static spinlock_t dasd_major_lock = SPIN_LOCK_UNLOCKED;static struct list_head dasd_major_info = LIST_HEAD_INIT(dasd_major_info);static major_info_t dasd_major_static = {        gendisk:{INIT_GENDISK(94, DASD_NAME, DASD_PARTN_BITS, DASD_PER_MAJOR)},        flags: DASD_MAJOR_INFO_IS_STATIC};static major_info_t *get_new_major_info (void){	major_info_t *major_info = NULL;	major_info = kmalloc (sizeof (major_info_t), GFP_KERNEL);	if (major_info) {		static major_info_t temp_major_info = {			gendisk:{				 INIT_GENDISK (0, DASD_NAME, DASD_PARTN_BITS,					       DASD_PER_MAJOR)}		};		memcpy (major_info, &temp_major_info, sizeof (major_info_t));	}	return major_info;}/* * register major number * is called with the 'static' major_info during init of the driver or 'NULL' to * allocate an additional dynamic major. */static intdasd_register_major (major_info_t * major_info){	int rc = 0;	int major;	unsigned long flags;        /* allocate dynamic major */	if (major_info == NULL) {		major_info = get_new_major_info ();		if (!major_info) {			MESSAGE (KERN_WARNING, "%s",				"Cannot get memory to allocate another "                                 "major number");			return -ENOMEM;		}	}	major = major_info->gendisk.major;        /* init devfs array */	major_info->gendisk.de_arr = (devfs_handle_t *)	    kmalloc (DASD_PER_MAJOR * sizeof (devfs_handle_t), GFP_KERNEL);	if(major_info->gendisk.de_arr == NULL)		goto out_gd_de_arr;	memset (major_info->gendisk.de_arr, 0,		DASD_PER_MAJOR * sizeof (devfs_handle_t));        /* init flags */	major_info->gendisk.flags = (char *)	    kmalloc (DASD_PER_MAJOR * sizeof (char), GFP_KERNEL);	if(major_info->gendisk.flags == NULL)		goto out_gd_flags;	memset (major_info->gendisk.flags, 0, DASD_PER_MAJOR * sizeof (char));        /* register blockdevice */	rc = devfs_register_blkdev (major, DASD_NAME, &dasd_device_operations);	if (rc < 0) {                		MESSAGE (KERN_WARNING,                         "Cannot register to major no %d, rc = %d",                         major,                          rc);		goto out_reg_blkdev; 	} else {		major_info->flags |= DASD_MAJOR_INFO_REGISTERED;	}	/* Insert the new major info into dasd_major_info if needed (dynamic major) */	if (!(major_info->flags & DASD_MAJOR_INFO_IS_STATIC)) {		spin_lock_irqsave (&dasd_major_lock, flags);		list_add_tail (&major_info->list, &dasd_major_info);		spin_unlock_irqrestore (&dasd_major_lock, flags);	}	if (major == 0) {		major = rc;		rc = 0;	}        /* init array of devices */	major_info->dasd_device =	    (dasd_device_t **) kmalloc (DASD_PER_MAJOR *					sizeof (dasd_device_t *), GFP_ATOMIC);	if (!major_info->dasd_device)		goto out_devices;	memset (major_info->dasd_device, 0,		DASD_PER_MAJOR * sizeof (dasd_device_t *));        /* init blk_size */	blk_size[major] =	    (int *) kmalloc ((1 << MINORBITS) * sizeof (int), GFP_ATOMIC);	if (!blk_size[major])		goto out_blk_size;	memset (blk_size[major], 0, (1 << MINORBITS) * sizeof (int));        /* init blksize_size */	blksize_size[major] =	    (int *) kmalloc ((1 << MINORBITS) * sizeof (int), GFP_ATOMIC);	if (!blksize_size[major])		goto out_blksize_size;	memset (blksize_size[major], 0, (1 << MINORBITS) * sizeof (int));        /* init_hardsect_size */	hardsect_size[major] =	    (int *) kmalloc ((1 << MINORBITS) * sizeof (int), GFP_ATOMIC);	if (!hardsect_size[major])		goto out_hardsect_size;	memset (hardsect_size[major], 0, (1 << MINORBITS) * sizeof (int));        /* init max_sectors */	max_sectors[major] =	    (int *) kmalloc ((1 << MINORBITS) * sizeof (int), GFP_ATOMIC);	if (!max_sectors[major])		goto out_max_sectors;	memset (max_sectors[major], 0, (1 << MINORBITS) * sizeof (int));	/* finally do the gendisk stuff */	major_info->gendisk.part = kmalloc ((1 << MINORBITS) *					    sizeof (struct hd_struct),					    GFP_ATOMIC);	if (!major_info->gendisk.part)		goto out_gendisk;	memset (major_info->gendisk.part, 0, (1 << MINORBITS) *		sizeof (struct hd_struct));	INIT_BLK_DEV (major, do_dasd_request, dasd_get_queue, NULL);	major_info->gendisk.sizes = blk_size[major];	major_info->gendisk.major = major;	add_gendisk (&major_info->gendisk);	return major;        /* error handling - free the prior allocated memory */        out_gendisk:	kfree (max_sectors[major]);	max_sectors[major] = NULL;      out_max_sectors:	kfree (hardsect_size[major]);	hardsect_size[major] = NULL;      out_hardsect_size:	kfree (blksize_size[major]);	blksize_size[major] = NULL;      out_blksize_size:	kfree (blk_size[major]);	blk_size[major] = NULL;      out_blk_size:	kfree (major_info->dasd_device);      out_devices:	/* Delete the new major info from dasd_major_info list if needed (dynamic) +*/	if (!(major_info->flags & DASD_MAJOR_INFO_IS_STATIC)) {		spin_lock_irqsave (&dasd_major_lock, flags);		list_del (&major_info->list);		spin_unlock_irqrestore (&dasd_major_lock, flags);	}        /* unregister blockdevice */	rc = devfs_unregister_blkdev (major, DASD_NAME);	if (rc < 0) {

⌨️ 快捷键说明

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