Linux-FLASH驱动设计二

块设备驱动系统分析:

功能:把内存划出512k,然后利用驱动程序做成块设备进行相应的访问。

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/kernel.h> /* printk() */
#include <linux/slab.h>   /* kmalloc() */
#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/kdev_t.h>
#include <linux/vmalloc.h>
#include <linux/genhd.h>
#include <linux/blkdev.h>
#include <linux/buffer_head.h> /* invalidate_bdev */
#include <linux/bio.h>

MODULE_LICENSE("Dual BSD/GPL");

static int major = 0;
static int sect_size = 512;
static int nsectors = 1024; 
/*
* The internal representation of our device.
*/
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 *///每一个块设备都由一个struct gendisk结构体描述

};
struct blk_dev *dev;
/*
* 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);
}

/*
* The simple form of the request function.
*/
static void blk_request(struct request_queue *q)
{
	struct request *req;

	req = blk_fetch_request(q);//取出队列中要处理的请求,接下来应该根据请求里面的信息访问硬件获取数据
	while (req != NULL) 
	{
	   struct blk_dev *dev = req->rq_disk->private_data;

	   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);
	   }
	}
}
/*
* The device operations structure.
*/
static struct block_device_operations blk_ops = 
{
	.owner = THIS_MODULE,
};
/*
* Set up our internal device.
*/
static void setup_device()
{
	/*
	* Get some memory.
	*/
	dev->size = nsectors*sect_size;<span style="white-space:pre">		</span>//计算分配的设备大小
	dev->data = vmalloc(dev->size);
	if (dev->data == NULL) 
	{
	   printk (KERN_NOTICE "vmalloc failure.\n");
	   return;
	}
	dev->queue = blk_init_queue(blk_request, NULL);//块设备请求队列初始化,第一个参数为请求队列调用函数,第二个参数为信号量
	if (dev->queue == NULL)
		goto out_vfree;
	blk_queue_logical_block_size(dev->queue, sect_size);//指明设备扇区大小
	dev->queue->queuedata = dev;
	/*
	* And the gendisk structure.
	*/
	dev->gd = alloc_disk(1);//为块设备分配struct gendisk结构

	if (! dev->gd) 
	{
		printk (KERN_NOTICE "alloc_disk failure\n");
		goto out_vfree;
	}
/*初始化struct gendisk结构体
*/ 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, "simp_blk%d", 0); //块设备名set_capacity(dev->gd, nsectors*(sect_size/sect_size)); //设备块设备扇区数add_disk(dev->gd); //向内核添加(注册)块设备return;out_vfree:if (dev->data) vfree(dev->data);}static int __init blk_init(void){/** Get registered.*/major = register_blkdev(major, "blk"); //注册块设备驱动程序,如果主设备号(major)填写为0,内核会自动分配设备号,通过返回值传递给majorif (major <= 0) { printk(KERN_WARNING "blk: unable to get major number\n"); return -EBUSY;}dev = kmalloc(sizeof(struct blk_dev), GFP_KERNEL);if (dev == NULL) goto out_unregister; setup_device(); //建立块设备初始化、注册函数,自己实现 return 0;out_unregister:unregister_blkdev(major, "sbd");return -ENOMEM;}static void blk_exit(void){if (dev->gd){del_gendisk(dev->gd);put_disk(dev->gd);}if (dev->queue)blk_cleanup_queue(dev->queue);if (dev->data)vfree(dev->data);unregister_blkdev(major, "blk");kfree(dev);}module_init(blk_init);module_exit(blk_exit);

 


块设备驱动设计流程图:




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值