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

📄 raw.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
字号:
/* * linux/drivers/char/raw.c * * Front-end raw character devices.  These can be bound to any block * devices to provide genuine Unix raw character device semantics. * * We reserve minor number 0 for a control interface.  ioctl()s on this * device are used to bind the other minor numbers to block devices. */#include <linux/fs.h>#include <linux/iobuf.h>#include <linux/major.h>#include <linux/blkdev.h>#include <linux/raw.h>#include <linux/capability.h>#include <linux/smp_lock.h>#include <asm/uaccess.h>#define dprintk(x...) typedef struct raw_device_data_s {	struct block_device *binding;	int inuse, sector_size, sector_bits;	struct semaphore mutex;} raw_device_data_t;static raw_device_data_t raw_devices[256];static ssize_t rw_raw_dev(int rw, struct file *, char *, size_t, loff_t *);ssize_t	raw_read(struct file *, char *, size_t, loff_t *);ssize_t	raw_write(struct file *, const char *, size_t, loff_t *);int	raw_open(struct inode *, struct file *);int	raw_release(struct inode *, struct file *);int	raw_ctl_ioctl(struct inode *, struct file *, unsigned int, unsigned long);static struct file_operations raw_fops = {	read:		raw_read,	write:		raw_write,	open:		raw_open,	release:	raw_release,};static struct file_operations raw_ctl_fops = {	ioctl:		raw_ctl_ioctl,	open:		raw_open,};static int __init raw_init(void){	int i;	register_chrdev(RAW_MAJOR, "raw", &raw_fops);	for (i = 0; i < 256; i++)		init_MUTEX(&raw_devices[i].mutex);	return 0;}__initcall(raw_init);/*  * Open/close code for raw IO. */int raw_open(struct inode *inode, struct file *filp){	int minor;	struct block_device * bdev;	kdev_t rdev;	/* it should eventually go away */	int err;	int sector_size;	int sector_bits;	minor = MINOR(inode->i_rdev);		/* 	 * Is it the control device? 	 */		if (minor == 0) {		filp->f_op = &raw_ctl_fops;		return 0;	}		if (!filp->f_iobuf) {		err = alloc_kiovec(1, &filp->f_iobuf);		if (err)			return err;	}	down(&raw_devices[minor].mutex);	/*	 * No, it is a normal raw device.  All we need to do on open is	 * to check that the device is bound, and force the underlying	 * block device to a sector-size blocksize. 	 */	bdev = raw_devices[minor].binding;	err = -ENODEV;	if (!bdev)		goto out;	atomic_inc(&bdev->bd_count);	rdev = to_kdev_t(bdev->bd_dev);	err = blkdev_get(bdev, filp->f_mode, 0, BDEV_RAW);	if (err)		goto out;		/*	 * Don't change the blocksize if we already have users using	 * this device 	 */	if (raw_devices[minor].inuse++)		goto out;	/* 	 * Don't interfere with mounted devices: we cannot safely set	 * the blocksize on a device which is already mounted.  	 */		sector_size = 512;	if (is_mounted(rdev)) {		if (blksize_size[MAJOR(rdev)])			sector_size = blksize_size[MAJOR(rdev)][MINOR(rdev)];	} else {		if (hardsect_size[MAJOR(rdev)])			sector_size = hardsect_size[MAJOR(rdev)][MINOR(rdev)];	}	set_blocksize(rdev, sector_size);	raw_devices[minor].sector_size = sector_size;	for (sector_bits = 0; !(sector_size & 1); )		sector_size>>=1, sector_bits++;	raw_devices[minor].sector_bits = sector_bits; out:	up(&raw_devices[minor].mutex);		return err;}int raw_release(struct inode *inode, struct file *filp){	int minor;	struct block_device *bdev;		minor = MINOR(inode->i_rdev);	down(&raw_devices[minor].mutex);	bdev = raw_devices[minor].binding;	raw_devices[minor].inuse--;	up(&raw_devices[minor].mutex);	blkdev_put(bdev, BDEV_RAW);	return 0;}/* * Deal with ioctls against the raw-device control interface, to bind * and unbind other raw devices.   */int raw_ctl_ioctl(struct inode *inode, 		  struct file *flip,		  unsigned int command, 		  unsigned long arg){	struct raw_config_request rq;	int err = 0;	int minor;		switch (command) {	case RAW_SETBIND:	case RAW_GETBIND:		/* First, find out which raw minor we want */		err = copy_from_user(&rq, (void *) arg, sizeof(rq));		if (err)			break;				minor = rq.raw_minor;		if (minor <= 0 || minor > MINORMASK) {			err = -EINVAL;			break;		}		if (command == RAW_SETBIND) {			/*			 * This is like making block devices, so demand the			 * same capability			 */			if (!capable(CAP_SYS_ADMIN)) {				err = -EPERM;				break;			}			/* 			 * For now, we don't need to check that the underlying			 * block device is present or not: we can do that when			 * the raw device is opened.  Just check that the			 * major/minor numbers make sense. 			 */			if ((rq.block_major == NODEV && 			     rq.block_minor != NODEV) ||			    rq.block_major > MAX_BLKDEV ||			    rq.block_minor > MINORMASK) {				err = -EINVAL;				break;			}						down(&raw_devices[minor].mutex);			if (raw_devices[minor].inuse) {				up(&raw_devices[minor].mutex);				err = -EBUSY;				break;			}			if (raw_devices[minor].binding)				bdput(raw_devices[minor].binding);			raw_devices[minor].binding = 				bdget(kdev_t_to_nr(MKDEV(rq.block_major, rq.block_minor)));			up(&raw_devices[minor].mutex);		} else {			struct block_device *bdev;			kdev_t dev;			bdev = raw_devices[minor].binding;			if (bdev) {				dev = to_kdev_t(bdev->bd_dev);				rq.block_major = MAJOR(dev);				rq.block_minor = MINOR(dev);			} else {				rq.block_major = rq.block_minor = 0;			}			err = copy_to_user((void *) arg, &rq, sizeof(rq));		}		break;			default:		err = -EINVAL;	}		return err;}ssize_t	raw_read(struct file *filp, char * buf, 		 size_t size, loff_t *offp){	return rw_raw_dev(READ, filp, buf, size, offp);}ssize_t	raw_write(struct file *filp, const char *buf, 		  size_t size, loff_t *offp){	return rw_raw_dev(WRITE, filp, (char *) buf, size, offp);}#define SECTOR_BITS 9#define SECTOR_SIZE (1U << SECTOR_BITS)#define SECTOR_MASK (SECTOR_SIZE - 1)ssize_t	rw_raw_dev(int rw, struct file *filp, char *buf, 		   size_t size, loff_t *offp){	struct kiobuf * iobuf;	int		new_iobuf;	int		err = 0;	unsigned long	blocknr, blocks;	size_t		transferred;	int		iosize;	int		i;	int		minor;	kdev_t		dev;	unsigned long	limit;	int		sector_size, sector_bits, sector_mask;	int		max_sectors;		/*	 * First, a few checks on device size limits 	 */	minor = MINOR(filp->f_dentry->d_inode->i_rdev);	new_iobuf = 0;	iobuf = filp->f_iobuf;	if (test_and_set_bit(0, &filp->f_iobuf_lock)) {		/*		 * A parallel read/write is using the preallocated iobuf		 * so just run slow and allocate a new one.		 */		err = alloc_kiovec(1, &iobuf);		if (err)			goto out;		new_iobuf = 1;	}	dev = to_kdev_t(raw_devices[minor].binding->bd_dev);	sector_size = raw_devices[minor].sector_size;	sector_bits = raw_devices[minor].sector_bits;	sector_mask = sector_size- 1;	max_sectors = KIO_MAX_SECTORS >> (sector_bits - 9);		if (blk_size[MAJOR(dev)])		limit = (((loff_t) blk_size[MAJOR(dev)][MINOR(dev)]) << BLOCK_SIZE_BITS) >> sector_bits;	else		limit = INT_MAX;	dprintk ("rw_raw_dev: dev %d:%d (+%d)\n",		 MAJOR(dev), MINOR(dev), limit);		err = -EINVAL;	if ((*offp & sector_mask) || (size & sector_mask))		goto out_free;	err = 0;	if (size)		err = -ENXIO;	if ((*offp >> sector_bits) >= limit)		goto out_free;	/*	 * Split the IO into KIO_MAX_SECTORS chunks, mapping and	 * unmapping the single kiobuf as we go to perform each chunk of	 * IO.  	 */	transferred = 0;	blocknr = *offp >> sector_bits;	while (size > 0) {		blocks = size >> sector_bits;		if (blocks > max_sectors)			blocks = max_sectors;		if (blocks > limit - blocknr)			blocks = limit - blocknr;		if (!blocks)			break;		iosize = blocks << sector_bits;		err = map_user_kiobuf(rw, iobuf, (unsigned long) buf, iosize);		if (err)			break;		for (i=0; i < blocks; i++) 			iobuf->blocks[i] = blocknr++;				err = brw_kiovec(rw, 1, &iobuf, dev, iobuf->blocks, sector_size);		if (rw == READ && err > 0)			mark_dirty_kiobuf(iobuf, err);				if (err >= 0) {			transferred += err;			size -= err;			buf += err;		}		unmap_kiobuf(iobuf);		if (err != iosize)			break;	}		if (transferred) {		*offp += transferred;		err = transferred;	} out_free:	if (!new_iobuf)		clear_bit(0, &filp->f_iobuf_lock);	else		free_kiovec(1, &iobuf); out:		return err;}

⌨️ 快捷键说明

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