Linux-2.6.32 下 块设备驱动的编写 与 相关问题解决

在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 <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>
#include <linux/genhd.h>
#include <linux/blkdev.h>
#include <linux/buffer_head.h>	/* invalidate_bdev */
#include <linux/bio.h>

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 <cgsz1992@163.com>"
#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");


 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值