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

📄 xpram.c

📁 ARM S3C2410 linux2.4 内核源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Xpram.c -- the S/390 expanded memory RAM-disk *            * significant parts of this code are based on * the sbull device driver presented in * A. Rubini: Linux Device Drivers * * Author of XPRAM specific coding: Reinhard Buendgen *                                  buendgen@de.ibm.com * * External interfaces: *   Interfaces to linux kernel *        xpram_setup: read kernel parameters   (see init/main.c) *        xpram_init:  initialize device driver (see drivers/block/ll_rw_blk.c) *   Module interfaces *        init_module *        cleanup_module *   Device specific file operations *        xpram_iotcl *        xpram_open *        xpram_release * * "ad-hoc" partitioning:          *    the expanded memory can be partitioned among several devices  *    (with different minors). The partitioning set up can be *    set by kernel or module parameters (int devs & int sizes[]) * *    module parameters: devs= and sizes= *    kernel parameters: xpram_parts= *      note: I did not succeed in parsing numbers  *            for module parameters of type string "s" ?!? * * Other kenel files/modules affected(gerp for "xpram" or "XPRAM": *    drivers/s390/Config.in *    drivers/s390/block/Makefile *    include/linux/blk.h *    include/linux/major.h *    init/main.c *    drivers/block//ll_rw_blk.c * * * Potential future improvements: *   request clustering: first coding started not yet tested or integrated *                       I doubt that it really pays off  *   generic hard disk support to replace ad-hoc partitioning * * Tested with 2.2.14 (under VM) */#ifdef MODULE#  ifndef __KERNEL__#    define __KERNEL__#  endif#  define __NO_VERSION__ /* don't define kernel_version in module.h */#endif /* MODULE */#include <linux/module.h>#include <linux/version.h>#ifdef MODULEchar kernel_version [] = UTS_RELEASE; #endif#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))#  define XPRAM_VERSION 24#else#  define XPRAM_VERSION 22#endif #if (XPRAM_VERSION == 24)#  include <linux/config.h>#  include <linux/init.h>#endif /* V24 */#include <linux/sched.h>#include <linux/kernel.h> /* printk() */#include <linux/slab.h> /* kmalloc() */#if (XPRAM_VERSION == 24)#  include <linux/devfs_fs_kernel.h>#endif /* V24 */#include <linux/fs.h>     /* everything... */#include <linux/errno.h>  /* error codes */#include <linux/timer.h>#include <linux/types.h>  /* size_t */#include <linux/ctype.h>  /* isdigit, isxdigit */#include <linux/fcntl.h>  /* O_ACCMODE */#include <linux/hdreg.h>  /* HDIO_GETGEO */#include <asm/system.h>   /* cli(), *_flags */#include <asm/uaccess.h>  /* put_user */#if (XPRAM_VERSION == 24)#define MAJOR_NR xpram_major /* force definitions on in blk.h */int xpram_major;   /* must be declared before including blk.h */devfs_handle_t xpram_devfs_handle;#define DEVICE_NR(device) MINOR(device)   /* xpram has no partition bits */#define DEVICE_NAME "xpram"               /* name for messaging */#define DEVICE_INTR xpram_intrptr         /* pointer to the bottom half */#define DEVICE_NO_RANDOM                  /* no entropy to contribute */#define DEVICE_OFF(d)                     /* do-nothing */#include <linux/blk.h>#include "xpram.h"        /* local definitions */__setup("xpram_parts=", xpram_setup);#endif /* V24 *//*   define the debug levels:   - 0 No debugging output to console or syslog   - 1 Log internal errors to syslog, ignore check conditions    - 2 Log internal errors and check conditions to syslog   - 3 Log internal errors to console, log check conditions to syslog   - 4 Log internal errors and check conditions to console   - 5 panic on internal errors, log check conditions to console   - 6 panic on both, internal errors and check conditions */#define XPRAM_DEBUG 4#define PRINTK_HEADER XPRAM_NAME#if XPRAM_DEBUG > 0#define PRINT_DEBUG(x...) printk ( KERN_DEBUG PRINTK_HEADER "debug:" x )#define PRINT_INFO(x...) printk ( KERN_INFO PRINTK_HEADER "info:" x )#define PRINT_WARN(x...) printk ( KERN_WARNING PRINTK_HEADER "warning:" x )#define PRINT_ERR(x...) printk ( KERN_ERR PRINTK_HEADER "error:" x )#define PRINT_FATAL(x...) panic ( PRINTK_HEADER "panic:"x )#else#define PRINT_DEBUG(x...) printk ( KERN_DEBUG PRINTK_HEADER "debug:"  x )#define PRINT_INFO(x...) printk ( KERN_DEBUG PRINTK_HEADER "info:" x )#define PRINT_WARN(x...) printk ( KERN_DEBUG PRINTK_HEADER "warning:" x )#define PRINT_ERR(x...) printk ( KERN_DEBUG PRINTK_HEADER "error:" x )#define PRINT_FATAL(x...) printk ( KERN_DEBUG PRINTK_HEADER "panic:" x )#endif	#if (XPRAM_VERSION == 22)#define MAJOR_NR xpram_major /* force definitions on in blk.h */int xpram_major;   /* must be declared before including blk.h */#define DEVICE_NR(device) MINOR(device)   /* xpram has no partition bits */#define DEVICE_NAME "xpram"               /* name for messaging */#define DEVICE_INTR xpram_intrptr         /* pointer to the bottom half */#define DEVICE_NO_RANDOM                  /* no entropy to contribute */#define DEVICE_OFF(d) /* do-nothing */#define DEVICE_REQUEST *xpram_dummy_device_request  /* dummy function variable 						     * to prevent warnings 						     */#include <linux/blk.h>#include "xpram.h"        /* local definitions */#endif /* V22 *//* * Non-prefixed symbols are static. They are meant to be assigned at * load time. Prefixed symbols are not static, so they can be used in * debugging. They are hidden anyways by register_symtab() unless * XPRAM_DEBUG is defined. */static int major    = XPRAM_MAJOR;static int devs     = XPRAM_DEVS;static int rahead   = XPRAM_RAHEAD;static int sizes[XPRAM_MAX_DEVS] = { 0, };static int blksize  = XPRAM_BLKSIZE;static int hardsect = XPRAM_HARDSECT;int xpram_devs, xpram_rahead;int xpram_blksize, xpram_hardsect;int xpram_mem_avail = 0;unsigned long xpram_sizes[XPRAM_MAX_DEVS];MODULE_PARM(devs,"i");MODULE_PARM(sizes,"1-" __MODULE_STRING(XPRAM_MAX_DEVS) "i"); MODULE_PARM_DESC(devs, "number of devices (\"partitions\"), " \		 "the default is " __MODULE_STRING(XPRAM_DEVS) "\n");MODULE_PARM_DESC(sizes, "list of device (partition) sizes " \		 "the defaults are 0s \n" \		 "All devices with size 0 equally partition the "		 "remaining space on the expanded strorage not "		 "claimed by explicit sizes\n");/* The following items are obtained through kmalloc() in init_module() */Xpram_Dev *xpram_devices = NULL;int *xpram_blksizes = NULL;int *xpram_hardsects = NULL;int *xpram_offsets = NULL;   /* partition offsets */#define MIN(x,y) ((x) < (y) ? (x) : (y))#define MAX(x,y) ((x) > (y) ? (x) : (y))/*  *              compute nearest multiple of 4 , argument must be non-negative *              the macros used depends on XPRAM_KB_IN_PG = 4  */#define NEXT4(x) ((x & 0x3) ? (x+4-(x &0x3)) : (x))   /* increment if needed */#define LAST4(x) ((x & 0x3) ? (x-4+(x & 0x3)) : (x))  /* decrement if needed */#if 0               /* this is probably not faster than the previous code */#define NEXT4(x)   ((((x-1)>>2)>>2)+4)             /* increment if needed */#define LAST4(x)   (((x+3)>>2)<<2)                 /* decrement if needed */#endif/* integer formats */#define XPRAM_INVALF -1    /* invalid     */#define XPRAM_HEXF    0    /* hexadecimal */#define XPRAM_DECF    1    /* decimal     *//*  *    parsing operations (needed for kernel parameter parsing) *//* ------------------------------------------------------------------------- * sets the string pointer after the next comma  * * argument:    strptr pointer to string * side effect: strptr points to endof string or to position of the next  *              comma  * ------------------------------------------------------------------------*/static voidxpram_scan_to_next_comma (char **strptr){	while ( ((**strptr) != ',') && (**strptr) )		(*strptr)++;}/* ------------------------------------------------------------------------- * interpret character as hex-digit * * argument: c charcter * result: c interpreted as hex-digit * note: can be used to read digits for any base <= 16 * ------------------------------------------------------------------------*/static intxpram_get_hexdigit (char c){	if ((c >= '0') && (c <= '9'))		return c - '0';	if ((c >= 'a') && (c <= 'f'))		return c + 10 - 'a';	if ((c >= 'A') && (c <= 'F'))		return c + 10 - 'A';	return -1;}/*-------------------------------------------------------------------------- * Check format of unsigned integer * * Argument: strptr pointer to string  * result:   -1 if strptr does not start with a digit  *                (does not start an integer) *           0  if strptr starts a positive hex-integer with "0x"  *           1  if strptr start a positive decimal integer * * side effect: if strptr start a positive hex-integer then strptr is *              set to the character after the "0x" *-------------------------------------------------------------------------*/static intxpram_int_format(char **strptr){	if ( !isdigit(**strptr) )		return XPRAM_INVALF;	if ( (**strptr == '0') 	     && ( (*((*strptr)+1) == 'x') || (*((*strptr) +1) == 'X') ) 	     && isdigit(*((*strptr)+3)) ) {		*strptr=(*strptr)+2;		return XPRAM_HEXF;	} else return XPRAM_DECF;}/*-------------------------------------------------------------------------- * Read non-negative decimal integer * * Argument: strptr pointer to string starting with a non-negative integer *           in decimal format * result:   the value of theinitial integer pointed to by strptr * * side effect: strptr is set to the first character following the integer *-------------------------------------------------------------------------*/static intxpram_read_decint (char ** strptr){	int res=0;	while ( isdigit(**strptr) ) {		res = (res*10) + xpram_get_hexdigit(**strptr);		(*strptr)++;	}	return res;}/*-------------------------------------------------------------------------- * Read non-negative hex-integer * * Argument: strptr pointer to string starting with a non-negative integer *           in hexformat (without "0x" prefix) * result:   the value of the initial integer pointed to by strptr * * side effect: strptr is set to the first character following the integer *-------------------------------------------------------------------------*/static intxpram_read_hexint (char ** strptr){	int res=0;	while ( isxdigit(**strptr) ) {		res = (res<<4) + xpram_get_hexdigit(**strptr);		(*strptr)++;	}	return res;}/*-------------------------------------------------------------------------- * Read non-negative integer * * Argument: strptr pointer to string starting with a non-negative integer             (either in decimal- or in hex-format * result:   the value of the initial integer pointed to by strptr *           in case of a parsing error the result is -EINVAL * * side effect: strptr is set to the first character following the integer *-------------------------------------------------------------------------*/static intxpram_read_int (char ** strptr){	switch (  xpram_int_format(strptr) ) {	case XPRAM_INVALF: return -EINVAL;	case XPRAM_HEXF:   return xpram_read_hexint(strptr);	case XPRAM_DECF:   return xpram_read_decint(strptr);	default: return -EINVAL;	}}/*-------------------------------------------------------------------------- * Read size * * Argument: strptr pointer to string starting with a non-negative integer *           followed optionally by a size modifier: *             k or K for kilo (default), *             m or M for mega *             g or G for giga * result:   the value of the initial integer pointed to by strptr *           multiplied by the modifier value devided by 1024 *           in case of a parsing error the result is -EINVAL * * side effect: strptr is set to the first character following the size *-------------------------------------------------------------------------*/static intxpram_read_size (char ** strptr){	int res;  	res=xpram_read_int(strptr);	if ( res < 0 )return res;	switch ( **strptr ) {	case 'g':	case 'G': res=res*1024;	case 'm':	case 'M': res=res*1024;	case 'k' :	case 'K' : (* strptr)++;	}  	return res;}/*-------------------------------------------------------------------------- * Read tail of comma separated size list  ",i1,i2,...,in" * * Arguments:strptr pointer to string. It is assumed that the string has *                  the format (","<size>)* *           maxl integer describing the maximal number of elements in the                  list pointed to by strptr, max must be > 0. *           ilist array of dimension >= maxl of integers to be modified * * result:   -EINVAL if the list is longer than maxl *           0 otherwise * * side effects: for j=1,...,n ilist[ij] is set to the value of ij if it is *               a valid non-negative integer and to -EINVAL otherwise *               if no comma is found where it is expected an entry in *               ilist is set to -EINVAL *-------------------------------------------------------------------------*/static intxpram_read_size_list_tail (char ** strptr, int maxl, int * ilist){ 	int i=0;	char *str = *strptr;	int res=0;	while ( (*str == ',') && (i < maxl) ) {		str++;      		ilist[i] = xpram_read_size(&str);		if ( ilist[i] == -EINVAL ) {			xpram_scan_to_next_comma(&str);			res = -EINVAL;		}		i++;	}	return res;#if 0  /* be lenient about trailing stuff */	if ( *str != 0 && *str != ' ' ) {		ilist[MAX(i-1,0)] = -EINVAL;		return -EINVAL;

⌨️ 快捷键说明

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