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

📄 mdisk.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  drivers/s390/block/mdisk.c *    VM minidisk device driver. * *  S390 version *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation *    Author(s): Hartmut Penner (hp@de.ibm.com) */#ifndef __KERNEL__#  define __KERNEL__#endif#define __NO_VERSION__#include <linux/config.h>#include <linux/version.h>char kernel_version [] = UTS_RELEASE;#include <linux/module.h>#include <linux/sched.h>#include <linux/kernel.h>              /* printk()                         */#include <linux/malloc.h>              /* kmalloc()                        */#include <linux/vmalloc.h>             /* vmalloc()                        */#include <linux/fs.h>                  /* everything...                    */#include <linux/errno.h>               /* error codes                      */#include <linux/timer.h>#include <linux/types.h>               /* size_t                           */#include <linux/fcntl.h>               /* O_ACCMODE                        */#include <linux/hdreg.h>               /* HDIO_GETGEO                      */#include <linux/init.h>                /* initfunc                         */#include <linux/interrupt.h>#include <linux/ctype.h>#include <asm/system.h>                /* cli(), *_flags                   */#include <asm/uaccess.h>               /* access_ok                        */#include <asm/io.h>                    /* virt_to_phys                     */	 /* Added statement HSM 12/03/99 */#include <asm/irq.h>#define MAJOR_NR MDISK_MAJOR /* force definitions on in blk.h */#include <linux/blk.h>#include "mdisk.h"        /* local definitions *//* * structure for all device specific information */typedef struct mdisk_Dev {	u32 vdev;   /* vdev of mindisk */	u32 size;   /* size in blocks */	u32 status; /* status of last io operation */	u32 nr_bhs; /* number of buffer of last io operation */        u32 blksize; /* blksize from minidisk */        u32 blkmult; /* multiplier between blksize and 512 HARDSECT */        u32 blkshift; /* loe2 of multiplier above */	/*	 * each device has own iob and bio,	 * it's possible to run io in parallel	 * not used yet due to only one CURRENT per MAJOR	 */		mdisk_rw_io_t* iob;      /* each device has it own iob and bio */	mdisk_bio_t*   bio;	 /* Added statement HSM 12/03/99 */	devstat_t dev_status;    /* Here we hold the I/O status */	int usage;               /* usage counter */	struct tq_struct tqueue; /* per device task queue */} mdisk_Dev;/* * appended to global structures in mdisk_init; */static int mdisk_blksizes[MDISK_DEVS];static int mdisk_sizes[MDISK_DEVS] = { 0 };static int mdisk_hardsects[MDISK_DEVS];static int mdisk_maxsectors[MDISK_DEVS];/* *  structure hold device specific information */static mdisk_Dev mdisk_devices[MDISK_DEVS];static mdisk_rw_io_t mdisk_iob[MDISK_DEVS] __attribute__ ((aligned(8)));static mdisk_bio_t mdisk_bio[MDISK_DEVS][256]__attribute__ ((aligned(8)));/* * Parameter parsing */struct {        long vdev[MDISK_DEVS];	long size[MDISK_DEVS];	long offset[MDISK_DEVS];        long blksize[MDISK_DEVS];} mdisk_setup_data;/* * Parameter parsing function, called from init/main.c * vdev    : virtual device number * size    : size in kbyte * offset  : offset after which minidisk is available * blksize : blocksize minidisk is formated * Format is: mdisk=<vdev>:<size>:<offset>:<blksize>,<vdev>:<size>:<offset>... * <vdev>:<size>:<offset>:<blksize> can be shortened to <vdev>:<size> with offset=0,blksize=512 */int __init mdisk_setup(char *str){	char *cur = str;	int vdev, size, offset=0,blksize;	static int i = 0;	if (!i)	        memset(&mdisk_setup_data,0,sizeof(mdisk_setup_data));        while (*cur != 0) {	        blksize=MDISK_HARDSECT;		vdev = size = offset = 0;		if (!isxdigit(*cur)) goto syntax_error;		vdev = simple_strtoul(cur,&cur,16);		if (*cur != 0 && *cur != ',') { 		if (*cur++ != ':') goto syntax_error;		if (!isxdigit(*cur)) goto syntax_error;		size = simple_strtoul(cur,&cur,16);		if (*cur == ':') { /* another colon -> offset specified */			cur++;			if (!isxdigit(*cur)) goto syntax_error;			offset = simple_strtoul(cur,&cur,16);			if (*cur == ':') { /* another colon -> blksize */			  cur++;			  if (!isxdigit(*cur)) goto syntax_error;			  blksize = simple_strtoul(cur,&cur,16);			}		}		if (*cur != ',' && *cur != 0) goto syntax_error;		} 		if (*cur == ',') cur++;		if (i >= MDISK_DEVS) {			printk(KERN_WARNING "mnd: too many devices\n");			return 1;		}		mdisk_setup_data.vdev[i] = vdev;		mdisk_setup_data.size[i] = size;		mdisk_setup_data.offset[i] = offset;		mdisk_setup_data.blksize[i] = blksize;		i++;	}		return 1;syntax_error:        printk(KERN_WARNING "mnd: syntax error in parameter string: %s\n", str);	return 0;}__setup("mdisk=", mdisk_setup);/* * Open and close */static int mdisk_open (struct inode *inode, struct file *filp){	mdisk_Dev *dev; /* device information */	int num = MINOR(inode->i_rdev);		/* 	 * size 0 means device not installed	 */	if ((num >= MDISK_DEVS) || (mdisk_sizes[num] == 0))		return -ENODEV;	MOD_INC_USE_COUNT;	dev = &mdisk_devices[num];	dev->usage++;	return 0;          /* success */}static int mdisk_release (struct inode *inode, struct file *filp){	mdisk_Dev *dev = &mdisk_devices[MINOR(inode->i_rdev)];		/*	 * flush device	 */		fsync_dev(inode->i_rdev);	dev->usage--;	MOD_DEC_USE_COUNT;	return 0;}/* * The mdisk() implementation */static int mdisk_ioctl (struct inode *inode, struct file *filp,                 unsigned int cmd, unsigned long arg){	int err,rc, size=0;	struct hd_geometry *geo = (struct hd_geometry *)arg;	mdisk_Dev *dev = mdisk_devices + MINOR(inode->i_rdev);		switch(cmd) {			case BLKGETSIZE:	        rc = copy_to_user ((long *) arg, &dev->size, sizeof (long));		printk(KERN_WARNING "mnd: ioctl BLKGETSIZE %d\n",dev->size);		return rc;	case BLKFLSBUF: /* flush */		if (!suser()) return -EACCES; /* only root */		fsync_dev(inode->i_rdev);		invalidate_buffers(inode->i_rdev);		return 0;			case BLKRAGET: /* return the readahead value */		if (!arg)  return -EINVAL;		err = access_ok(VERIFY_WRITE, (long *) arg, sizeof(long));		if (err) return err;		put_user(read_ahead[MAJOR(inode->i_rdev)],(long *) arg);		return 0;			case BLKRASET: /* set the readahead value */		if (!suser()) return -EACCES;		if (arg > 0xff) return -EINVAL; /* limit it */		read_ahead[MAJOR(inode->i_rdev)] = arg;		return 0;			case BLKRRPART: /* re-read partition table: can't do it */		return -EINVAL;			case HDIO_GETGEO:		/*		 * get geometry of device -> linear		 */		size = dev->size;		if (geo==NULL) return -EINVAL;		err = access_ok(VERIFY_WRITE, geo, sizeof(*geo));		if (err) return err;		put_user(1,    &geo->cylinders);		put_user(1,    &geo->heads);		put_user(size, &geo->sectors);		put_user(0,    &geo->start);		return 0;	}		return -EINVAL; /* unknown command */}/* * The file operations */static struct block_device_operations mdisk_fops = {	ioctl:        mdisk_ioctl,	open:         mdisk_open,        release:      mdisk_release,};/* * The 'low level' IO function */static __inline__ intdia250(void* iob,int cmd){	int rc;		iob = (void*) virt_to_phys(iob);	asm volatile ("    lr    2,%1\n"		      "    lr    3,%2\n"		      "    .long 0x83230250\n"		      "    lr    %0,3"		      : "=d" (rc)		      : "d" (iob) , "d" (cmd)		      : "2", "3" );	return rc;}/* * Init of minidisk device */static __inline__ intmdisk_init_io(mdisk_Dev *dev,int blocksize,int offset,int size){	mdisk_init_io_t *iob = (mdisk_init_io_t*) dev->iob;	int rc;	memset(iob,0,sizeof(mdisk_init_io_t));		iob->dev_nr = dev->vdev;	iob->block_size = blocksize;	iob->offset     = offset;	iob->start_block= 0;	iob->end_block  = size;		rc = dia250(iob,INIT_BIO);		/*	 * clear for following io once	 */		memset(iob,0,sizeof(mdisk_rw_io_t));		return rc;}/* * release of minidisk device */static __inline__ intmdisk_term_io(mdisk_Dev *dev){	mdisk_init_io_t *iob = (mdisk_init_io_t*) dev->iob;		memset(iob,0,sizeof(mdisk_init_io_t));		iob->dev_nr = dev->vdev;		return dia250(iob,TERM_BIO);}/* * setup and start of minidisk io request */static __inline__ intmdisk_rw_io_clustered (mdisk_Dev *dev,                       mdisk_bio_t* bio_array,                       int length,                       int req,                       int sync){	int rc;	mdisk_rw_io_t *iob = dev->iob;		iob->dev_nr      = dev->vdev;	iob->key         = 0;	iob->flags       = sync;		iob->block_count = length;	iob->interrupt_params = req;	iob->bio_list     = virt_to_phys(bio_array);		rc = dia250(iob,RW_BIO);	return rc;}/* * The device characteristics function */static __inline__ intdia210(void* devchar){	int rc;	devchar = (void*) virt_to_phys(devchar);	asm volatile ("    lr    2,%1\n"		      "    .long 0x83200210\n"		      "    ipm   %0\n"		      "    srl   %0,28"		      : "=d" (rc)		      : "d" (devchar)		      : "2" );	return rc;}/* * read the label of a minidisk and extract its characteristics */static __inline__ intmdisk_read_label (mdisk_Dev *dev, int i){	static mdisk_dev_char_t devchar;	static long label[1024];	int block, b;	int rc;	mdisk_bio_t *bio;	devchar.dev_nr = dev -> vdev;

⌨️ 快捷键说明

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