Linux-FLASH驱动设计三

#include <linux/module.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/blkdev.h>
#include <linux/bio.h>
static int major = 0;
static int sect_size = 512;		//指明每个扇区大小为512
static int nsectors = 1024;

struct blk_dev
{
         int size;                        /* Device size in sectors */
         u8 *data;                        /* The data array */
         struct request_queue *queue;     /* The device request queue */
         struct gendisk *gd;              /* The gendisk structure,每一个块设备都有一个gendisk向与之对应 */
};
struct blk_dev *dev;

static struct block_device_operations blk_ops = 
{
	.ower = THIS_MODULE,
};

/*
* Handle an I/O request, in sectors.
*/
static void blk_transfer(struct blk_dev *dev, unsigned long sector, 
						 unsigned long nsect, char *buffer, int write)
{
	unsigned long offset = sector*sect_size;	//计算操作起始地址
	unsigned long nbytes = nsect*sect_size;		//计算操作数据量

	if ((offset + nbytes) > dev->size) 
	{
	   printk (KERN_NOTICE "Beyond-end write (%ld %ld)\n", offset, nbytes);
	   return;
	}
	if (write)
	   memcpy(dev->data + offset, buffer, nbytes);
	else
	   memcpy(buffer, dev->data + offset, nbytes);
}

/*处理请求队列函数*/
static void blk_request(struct request_queue *q)
{
	struct request *req;
	/*取出请求队列中的一个请求*/
	req = blk_fetch_request(q);

	/*判断请求是否为空*/
	while (req != NULL) 
	{
		/*
		blk_rq_pos():取出起始扇区
		blk_rq_cur_sectors():计算操作多少个扇区
		req->buffer:磁盘数据读写缓存
		rq_data_dir():确定是写还是读
		*/
		blk_transfer(dev, blk_rq_pos(req), blk_rq_cur_sectors(req), req->buffer, rq_data_dir(req));
   
	   //判断是否为最后一个请求
	   if(!__blk_end_request_cur(req, 0)) 
	   {
			//继续取出请求队列中的请求
			req = blk_fetch_request(q);
	   }
	}

}

void setup_devce()
{
	/*初始化请求队列,第一个参数请求队列处理函数
	第二个函数自旋锁,返回值为request_queue请求队列*/
	dev->queue = blk_init_queue(blk_request, NULL);	
	
	/*设置扇区尺寸,第一个参数为请求队列,第二个参数为扇区大小*/
	blk_queue_logical_block_size(dev->queue, sect_size);

	/*分配块设备结构,参数表示支持多少个设备*/
	dev->gd = alloc_disk(1);

	/*初始化dev->gd*/
	dev->gd->major = major;
	dev->gd->first_minor = 0;
	dev->gd->fops = &blk_ops;
	dev->gd->queue = dev->queue;
	dev->gd->private_data = dev;
	sprintf (dev->gd->disk_name, "Flash_blk%d", 0);
	/*设置扇区数个数,第一个参数为需要设备的设备,第二个参数为扇区个数*/
	set_capacity(dev->gd, nsectors);
	/*向内核注册块设备*/
	add_disk(dev->gd);
}

int blk_init()
{
	register_blkdev(major, "blk");	//使用动态分配主设备号,使用静态分配可能会造成冲突
	
	if (major <= 0)
	{
		printk("register blk dev fail.\n");
		return -EBUSY;	//需要添加<linux/errno.h>
	}

	dev = kmalloc(sizeof(struct blk_dev), GFP_KERNEL);	//GFP_KERNEL常规分配

	setup_devce();

	return 0;
}

void blk_exit()
{
	del_gendisk(dev->gd);
	blk_cleanup_queue(dev->queue);
	vfree(dev->data);
	unregister_blkdev(major, "blk");
	kfree(dev);
}

module_init(blk_init);
module_exit(blk_exit);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值