#include <linux/module.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/timer.h>
#include <linux/genhd.h>
#include <linux/hdreg.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/wait.h>
#include <linux/blkdev.h>
#include <linux/blkpg.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/dma.h>
#define RAMBLOCK_SIZE (1024*1024)
static struct gendisk *grh_gendisk;
static struct request_queue *grh_queue;
static DEFINE_SPINLOCK(grh_spin_lock);
static int major;
static unsigned char *ramblock_buf;
//對隊列中的請求進行處理的函數
static void grh_do_ramblock_req(struct request_queue *q){
struct request *req;
static int read_count=0, write_count=0;
unsigned long offset, count;
req = blk_fetch_request(q);
while (req) {
//真正的數據操作
offset = blk_rq_pos(req); //req對應的扇區的偏移量
count = blk_rq_cur_sectors(req); //req對應的數據傳輸量,以扇區爲單位
offset <<= 9;
count <<= 9;
if(rq_data_dir(req) == READ){ //讀操作
printk(KERN_EMERG"read count=%d\n", ++read_count);
memcpy(req->buffer, ramblock_buf+offset, count); /*從ramdisk把需要搬移的扇區數據移動到req的buffer裏面*/
}
else{ //寫操作
printk(KERN_EMERG"write count=%d\n", ++write_count);
memcpy(ramblock_buf+offset, req->buffer, count);
}
if (!__blk_end_request_cur(req, 0))
req = blk_fetch_request(q);
}
}
//獲取柱面和扇區信息的函數,用於向分區工具提供參數
static int grh_getgeo(struct block_device *bdev, struct hd_geometry *geo){
geo->heads = 2; //假設2個面
geo->cylinders = 32; //假設32個柱面
geo->sectors = RAMBLOCK_SIZE/512/2/32; //算出扇區個數
return 0;
}
static struct block_device_operations grh_bdops = {
.owner = THIS_MODULE,
.getgeo = grh_getgeo,
};
static int ram_block_init(void){
//分配gendisk
grh_gendisk = alloc_disk(16); //分區個數爲16
//設置gendisk
grh_queue = blk_init_queue(grh_do_ramblock_req, &grh_spin_lock); //創建操作隊列
grh_gendisk->queue = grh_queue;
major = register_blkdev(0, "grh_ramblock");
grh_gendisk->major = major;
grh_gendisk->first_minor = 0;
sprintf(grh_gendisk->disk_name, "ramblock");
grh_gendisk->fops = &grh_bdops;
set_capacity(grh_gendisk, RAMBLOCK_SIZE/512); //設置塊設備大小爲1M
ramblock_buf = kzalloc(RAMBLOCK_SIZE, GFP_KERNEL);
if(NULL == ramblock_buf){
printk(KERN_EMERG"allocate buffer error!\n");
}
//註冊gendisk
add_disk(grh_gendisk);
return 0;
}
static void ram_block_exit(void){
unregister_blkdev(major, "grh_ramblock");
del_gendisk(grh_gendisk);
put_disk(grh_gendisk);
blk_cleanup_queue(grh_queue);
kfree(ramblock_buf);
return;
}
module_init(ram_block_init);
module_exit(ram_block_exit);
MODULE_AUTHOR("GRH");
MODULE_VERSION("1.0");
MODULE_DESCRIPTION("RAM BLOCK DRIVER");
MODULE_LICENSE("GPL");
mini2440 入門塊設備驅動(用RAM緩存模擬磁盤)代碼記錄(內核用的是2.6.32.2)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.