mini2440 入門塊設備驅動(用RAM緩存模擬磁盤)代碼記錄(內核用的是2.6.32.2)

#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");

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章