#include
#include
#include
#include
#include /* printk() */
#include /* kmalloc() */
#include /* everything... */
#include /* error codes */
#include
#include /* size_t */
#include /* O_ACCMODE */
#include /* HDIO_GETGEO */
#include
#include
#include
#include
#include /* invalidate_bdev */
#include
//块设备文件主设备号 72
#define BLOCK_DEVICEMAJOR COMPAQ_SMART2_MAJOR
// 块设备名字
#define BLOCK_DISKNAME "queue_block"
//块设备容量
#define BLOCK_DEV_BYTES (1*1024*1024) // 1M
//请求队列指针
static struct request_queue *block_request_queue;
// gendisk结构体指针变量
static struct gendisk *block_dev_disk;
//模拟磁盘空间
unsigned char block_dev_data[BLOCK_DEV_BYTES];//该函数不能由驱动自己调用 由系统调用 系统认为是时候调用的时候调用static void block_dev_do_request(struct request_queue *q)
{ //获取请求队列第一个IO请求
struct request *req =blk_fetch_request(q);
while ( req != NULL) {
sector_t sector = blk_rq_pos(req); //获取扇区第一个位置
unsigned long nsector = blk_rq_cur_sectors(req);//获取扇区数目
//判断是否大于总容量
if ((sector + nsector)<<9 > BLOCK_DEV_BYTES)
{
printk(KERN_ERR BLOCK_DISKNAME
": bad request: block=%llu, count=%llu\n",
(unsigned long long)sector,
(unsigned long long)nsector);
__blk_end_request_all(req, -EIO);
continue;
}
//判断数据传输方向
switch (rq_data_dir(req)) {
case READ:
memcpy(req->buffer,
block_dev_data + (sector<<9),
nsector<<9);
break;
case WRITE:
memcpy(block_dev_data + (sector<<9),
req->buffer, nsector<<9);
break;
default:
break;
}
//通知请求队列当前IO已经处理完毕
if ( ! __blk_end_request_cur(req, 0) ) {req = blk_fetch_request(q); //继续读取下一个IO请求}
}
}
static int block_dev_open (struct block_device *device, fmode_t mode)
{
printk("open %s\n", device->bd_disk->disk_name);
return 0;
}
// 释放块设备
static int block_dev_release(struct gendisk *gendisk, fmode_t mode)
{
printk("release %s\n", gendisk->disk_name);
return 0;
}
//类似字符设备
struct block_device_operations block_dev_fops = {
.owner = THIS_MODULE,.open=block_dev_open, .release=block_dev_release
};
static int __init block_dev_init(void)
{
int ret;
//初始化请求队列
block_request_queue = blk_init_queue(block_dev_do_request, NULL);
if (!block_request_queue) {
ret = -ENOMEM;
goto err_init_queue;
}
//分配磁盘
block_dev_disk = alloc_disk(1);
if (!block_dev_disk) {
ret = -ENOMEM;
goto err_alloc_disk;
}
strcpy(block_dev_disk->disk_name, BLOCK_DISKNAME);//设备文件名
block_dev_disk->major = BLOCK_DEVICEMAJOR;
block_dev_disk->first_minor = 0;
block_dev_disk->fops = &block_dev_fops;
block_dev_disk->queue = block_request_queue;//指定请求队列
set_capacity(block_dev_disk, BLOCK_DEV_BYTES>>9);//设置磁盘容量
add_disk(block_dev_disk);//添加磁盘
return 0;
err_alloc_disk:
blk_cleanup_queue(block_request_queue);
err_init_queue:
return ret;
}
static void __exit block_dev_exit(void)
{
del_gendisk(block_dev_disk);//删除磁盘
put_disk(block_dev_disk);//gendisk引用次数减一
blk_cleanup_queue(block_request_queue);//清除请求队列
}
module_init(block_dev_init);
module_exit(block_dev_exit);