在LDD3书中,其中的有些块设备操作函数已经在Linux-2.6.32有了很大的变动,需要自己重新根据新定义的一些函数进行适当的移植,以解决编译时报出的各种错误,
主要时在do_request请求处理函数中修改,笔者修改的结果如下:
static void ubuntu_do_ramblock_requset(struct request_queue *q)
{
static int cnt = 0;
struct request *req;
int err =0;
printk("do_ramblock_request %d\n", ++cnt);
req = blk_fetch_request(q);
while (req) {
if ((req->cmd_type != REQ_TYPE_FS)) {
printk (KERN_NOTICE "Skip non-CMD request\n");
__blk_end_request_all(req, -EIO);
continue;
}
sbull_transfer( req,blk_rq_pos(req), blk_rq_cur_sectors(req),
req->buffer, rq_data_dir(req));
done:
if (!__blk_end_request_cur(req, err))
req = blk_fetch_request(q);
}
}
其中 sbull_transfer( req,blk_rq_pos(req), blk_rq_cur_sectors(req), req->buffer, rq_data_dir(req)); 如下:
static void sbull_transfer( struct request *req,unsigned long sector,
unsigned long nsect, char *buffer, int write)
{
unsigned long offset = sector*KERNEL_SECTOR_SIZE;
unsigned long nbytes = nsect*KERNEL_SECTOR_SIZE;
if ((offset + nbytes) > get_capacity(req->rq_disk)*KERNEL_SECTOR_SIZE) {
printk (KERN_NOTICE "Beyond-end write (%ld %ld)\n", offset, nbytes);
return;
}
if (write)
memcpy(ubuntu_ramblock_buf + offset, req->buffer, nbytes);
else
memcpy(req->buffer,ubuntu_ramblock_buf + offset , nbytes);
}
以上在LDD3书的基础上修改后,就可以通过编译了。
然而,将编写好的驱动放到开发板(mini2440)上运行的时候,格式化时没有出现问题,但是,挂载块设备的时候却报出了如下错误:
# mount /dev/ramblock /mnt
yaffs: dev is 266338304 name is "ramblock"
yaffs: passed flags ""
yaffs: Attempting MTD mount on 254.0, "ramblock"
yaffs: dev is 266338304 name is "ramblock"
yaffs: passed flags ""
yaffs: Attempting MTD mount on 254.0, "ramblock"
FAT: utf8 is not a recommended IO charset for FAT filesystems, filesystem will be case sensitive!
mount: mounting /dev/ramblock on /mnt failed: Invalid argument
解决办法:
在内核源码linux - 2.6.32 中配置内核
File Systems --->
DOS/FAT/NT Filesystems --->
(utf8) Default iocharset for FAT
改为
(cp936) Default iocharset for FAT
即可完美解决该问题
现附上源代码,供大家参考
/*²Î¿¼ xd.c ºÍ z2ram.c */
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//#include
#include
#include
#include
#include /* invalidate_bdev */
#include
static struct gendisk * ubuntu_disk;
static struct request_queue * ubuntu_ramblock_queue;
static DEFINE_SPINLOCK(ubuntu_ramblock_lock);
static int major; //¿éÉ豸µÄÖ÷É豸ºÅ
static unsigned char *ubuntu_ramblock_buf; //ÉêÇëµÄÄÚ´æµØÖ·
static const struct block_device_operations ubuntu_ramblock_fops = {
.owner = THIS_MODULE,
//.getgeo = xd_getgeo, //»ñµÃÇý¶¯Æ÷µÄÓ²¼þÎûÎû
};
#define UBUNTU_RAMBLOCL_SIZE (1024*1024) // 1 M
#define KERNEL_SECTOR_SIZE 512
static void sbull_transfer( struct request *req,unsigned long sector,
unsigned long nsect, char *buffer, int write)
{
unsigned long offset = sector*KERNEL_SECTOR_SIZE;
unsigned long nbytes = nsect*KERNEL_SECTOR_SIZE;
if ((offset + nbytes) > get_capacity(req->rq_disk)*KERNEL_SECTOR_SIZE) {
printk (KERN_NOTICE "Beyond-end write (%ld %ld)\n", offset, nbytes);
return;
}
if (write)
memcpy(ubuntu_ramblock_buf + offset, req->buffer, nbytes);
else
memcpy(req->buffer,ubuntu_ramblock_buf + offset , nbytes);
}
static void ubuntu_do_ramblock_requset(struct request_queue *q)
{
static int cnt = 0;
struct request *req;
int err =0;
printk("do_ramblock_request %d\n", ++cnt);
/*while ((req = elv_next_request(q)) != NULL) {
end_request(req, 1);
}*/
req = blk_fetch_request(q); //´Ó¶ÓÁÐÖлñÈ¡Ò»¸öÇëÇó
while (req) {
if ((req->cmd_type != REQ_TYPE_FS)) {
printk (KERN_NOTICE "Skip non-CMD request\n");
__blk_end_request_all(req, -EIO);
continue;
}
/*Êý¾Ý´«ÊäÈýÒªËØ*/
/*Ô´/Ä¿µÄ*/
/*unsigned long start = blk_rq_pos(req) * 512; //ÉÈÇøÊý*512 =×Ö½ÚÊý
/*Ä¿µÄ/Ô´*/
//req->buffer
/*³¤¶È*/
/* unsigned long len = blk_rq_cur_bytes(req) * 512;*/
sbull_transfer( req,blk_rq_pos(req), blk_rq_cur_sectors(req),
req->buffer, rq_data_dir(req));
/*´«Êä*/
/* if (rq_data_dir(req) == READ)
memcpy(req->buffer,ubuntu_ramblock_buf + start , len);
else
memcpy(ubuntu_ramblock_buf + start, req->buffer, len);*/
done:
if (!__blk_end_request_cur(req, err))
req = blk_fetch_request(q);
}
}
static int ubuntu_ram_block_init(void)
{
/*print banner*/
printk("/***** ubuntu_ram_block_init driver*****/\n");
printk("/**** guoyu @ncu linux 2.6.32******* /\n");
printk("/******* 2012/5/22 ***********/\n");
/*1.·ÖÅägendisk ½á¹¹Ìå*/
ubuntu_disk= alloc_disk(16); //´ËÉ豸ºÅ¸öÊý:·ÖÇøÊý +1 ,¼´±íʾ¸ÃÉ豸ÓÐ15¸ö·ÖÇø
/*2. ÉèÖÃ*/
/*2.1 Ϊgendisk·ÖÅäºÍÉèÖÃÇëÇó¶ÓÁÐ:Ìṩ¶ÁдÄÜÁ¦*/
ubuntu_ramblock_queue = blk_init_queue(ubuntu_do_ramblock_requset, &ubuntu_ramblock_lock); //ΪÇëÇó¶ÓÁÐÉèÖÃÇëÇó´¦Àíº¯Êý
/*2.2 ÆäËûgendiskÉèÖÃ*/
major = register_blkdev(0, "ubuntu_ramblock");// Óë×Ö·ûÉ豸µÄ×¢²áº¯Êý±È
//¸Ãº¯ÊýÍË»¯ÁË£¬Ö»·µ»ØÒ»¸ö
//¿ÉʹÓõÄÖ÷É豸ºÅ
//ÔÚcat /proc/devicesÏ¿ÉÒÔ¿´µ½µÄÉ豸ÃûºÍÖ÷É豸ºÅ
ubuntu_disk->major = major;
ubuntu_disk->first_minor = 0; //µÚÒ»¸ö·ÖÇø
sprintf(ubuntu_disk->disk_name, "ubuntu_ramblock");
ubuntu_disk->fops = &ubuntu_ramblock_fops;
ubuntu_disk->queue = ubuntu_ramblock_queue;
set_capacity( ubuntu_disk, UBUNTU_RAMBLOCL_SIZE / 512); //ÒÔÉÈÇøµÄ´óС¼ÆË㣬ÿ512×Ö½ÚΪһ¸öÉÈÇø
/*ΪÉ豸·ÖÅäÄÚ´æµØÖ·*/
ubuntu_ramblock_buf = kzalloc(UBUNTU_RAMBLOCL_SIZE, GFP_KERNEL);
/*×¢²á*/
add_disk(ubuntu_disk);
return 0;
}
static void ubuntu_ram_block_exit(void)
{
unregister_blkdev(major, "ubuntu_ramblock");
del_gendisk(ubuntu_disk);
put_disk(ubuntu_disk);
blk_cleanup_queue(ubuntu_ramblock_queue);
}
#define DRIVER_VERSION "v1.0"
#define DRIVER_AUTHOR "Guoyu "
#define DRIVER_DESC "USB HID Boot Protocol mouse driver"
module_init(ubuntu_ram_block_init);
module_exit(ubuntu_ram_block_exit);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");