免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1747 | 回复: 0
打印 上一主题 下一主题

求助 关于块设备驱动 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-05-23 13:40 |只看该作者 |倒序浏览
本科毕业设计,要做一个I2C总线的FMram的块设备驱动,自己找了一个RAMDISK的简单块设备驱动,感觉和我自己需要编写的很像,只要将里面的memcopy函数改成用I2C总线的收发函数就可以了,一个是内存之间数据的交换,一个是通过I2C总线的数据交换,而且两个设备都不是严格的块设备,都没有扇区,最小读写块之类的概念,因此觉得很像,但是总是挂载不上去,提示系统想要的超过了块设备能够提供的区块,但是原来的RAMDISK却没有这样的问题。FMram芯片比较小 才8K
希望大神么帮忙看一下。。。。粗体部分是我添加的 改的



#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/kernel.h>        /* printk() */
#include <linux/slab.h>                /* kmalloc() */
#include <linux/fs.h>                /* everything... */
#include <linux/errno.h>        /* error codes */
#include <linux/timer.h>
#include <linux/types.h>        /* size_t */
#include <linux/fcntl.h>        /* O_ACCMODE */
#include <linux/hdreg.h>        /* HDIO_GETGEO */
#include <linux/kdev_t.h>
#include <linux/vmalloc.h>
#include <linux/genhd.h>
#include <linux/blkdev.h>
#include <linux/buffer_head.h>        /* invalidate_bdev */
#include <linux/bio.h>
#include <linux/version.h>

#include <linux/string.h>
#include <linux/poll.h>
#include <linux/proc_fs.h>
#include <linux/ioport.h>
#include <asm/bitops.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <linux/i2c.h>

const char write_unlock[2]={0x0e,0x80};
//const char write_lock[2]={0x0e,0x18};

/* i2c configuration */
#define I2C_ADDR 0xd0
#define MEM_ADDR 0xa0

/*for APB 108MHz*/
#define DEFAULT_I2C_CLOCKDIV        180
extern int GM_i2c_xfer(struct i2c_msg *msgs, int num, int clockdiv);

//-------------------------------------存储器操作-------------------------------//
/* block read */
static int i2c_read_mem(u16 reg, u8 buf[], int len)
{
        struct i2c_msg msgs[1];

        if(len<0)
        {
                printk("Error:The number of reading for the memory is wrong!\n";
                return -1;
        }

        buf[0] = (reg>>&0xff;
        buf[1] = reg&0xff;
            msgs[0].addr = MEM_ADDR>>1;
            msgs[0].flags = 0;
            msgs[0].len = 2;
            msgs[0].buf = buf;   
            if (GM_i2c_xfer(msgs, 1, DEFAULT_I2C_CLOCKDIV) != 1)
                    {
                    printk("Error:unable to set read regs addr!\n";
                return -1;
                    }
            msgs[0].addr = MEM_ADDR>>1;
            msgs[0].flags = 1;
            msgs[0].len = len;              //+2;
            msgs[0].buf = buf;   
            if (GM_i2c_xfer(msgs, 1, DEFAULT_I2C_CLOCKDIV) != 1)
                    {
                    printk("Error:unable to read from the device!\n";
                return -1;
                    }
        return 0;       
}
/* block write */
static int i2c_set_mem(u16 reg, u8 const buf[], int len)
{
        u8 *i2c_buf;
        struct i2c_msg msgs[1];
       
       msgs[0].addr =I2C_ADDR>>1;              //去写保护
            msgs[0].flags = 0;
            msgs[0].len = 2;              //+2;
            msgs[0].buf = write_unlock;   
            if (GM_i2c_xfer(msgs, 1, DEFAULT_I2C_CLOCKDIV) != 1)
                    {
                    printk("Error:unable to unlock the device!\n";
                return -1;
                    }

        if(len<=0){
                printk("Error:The number of seting for the memory is wrong!\n";
                return -1;
        }
        i2c_buf=kmalloc(sizeof(u*len+2,GFP_KERNEL);                     //+2
        if(NULL==i2c_buf)
        {
                printk("Error:while kmalloc for the MEM!\n";
                return -1;
        }
        memset(i2c_buf,0,sizeof(u*len+2);
       
        i2c_buf[0] =( reg >> 8 ) & 0xff;
        i2c_buf[1] =reg & 0xff;
        memcpy(&i2c_buf[2], &buf[0], sizeof(u*len);  
            msgs[0].addr = MEM_ADDR>>1;
            msgs[0].flags =0;
            msgs[0].len = len+2;
            msgs[0].buf = i2c_buf;   
            if (GM_i2c_xfer(msgs, 1, DEFAULT_I2C_CLOCKDIV) != 1){
                if(NULL!=i2c_buf)
                        kfree(i2c_buf);
                printk("Error:unable to write the device!\n";
                return -1;
            }
        if(NULL!=i2c_buf)
                kfree(i2c_buf);
        return 0;       
}


#define SIMP_BLKDEV_DEVICEMAJOR        COMPAQ_SMART2_MAJOR
#define SIMP_BLKDEV_DISKNAME        "simp_blkdev"
#define SIMP_BLKDEV_BYTES        (8*1024)

static struct request_queue *simp_blkdev_queue;
static struct gendisk *simp_blkdev_disk;
//unsigned char simp_blkdev_data[SIMP_BLKDEV_BYTES];



static int simp_blkdev_make_request(struct request_queue *q, struct bio *bio)
{
        struct bio_vec *bvec;
        int i;
        void *dsk_mem;
        u8 *temp;

        if ((bio->bi_sector << 9) + bio->bi_size > SIMP_BLKDEV_BYTES) {
                printk(KERN_ERR SIMP_BLKDEV_DISKNAME
                        ": bad request: block=%llu, count=%u\n",
                        (unsigned long long)bio->bi_sector, bio->bi_size);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
                bio_endio(bio, 0, -EIO);
#else
                bio_endio(bio, -EIO);
#endif
                return 0;
        }

        dsk_mem = (bio->bi_sector << 9);

        bio_for_each_segment(bvec, bio, i) {
                void *iovec_mem;

                switch (bio_rw(bio)) {
                case READ:
                case READA:
                        iovec_mem = kmap(bvec->bv_page) + bvec->bv_offset;
                               
                          i2c_read_mem(dsk_mem, iovec_mem, bvec->bv_len);
                       
                        //memcpy(iovec_mem, dsk_mem, bvec->bv_len);
                        kunmap(bvec->bv_page);
                        break;
                case WRITE:
                        iovec_mem = kmap(bvec->bv_page) + bvec->bv_offset;
                                               
                          i2c_set_mem(dsk_mem, iovec_mem, bvec->len)        ;       
                                               
                      //  memcpy(dsk_mem, iovec_mem, bvec->bv_len);
                        kunmap(bvec->bv_page);
                        break;
                default:
                        printk(KERN_ERR SIMP_BLKDEV_DISKNAME
                                ": unknown value of bio_rw: %lu\n",
                                bio_rw(bio));
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
                        bio_endio(bio, 0, -EIO);
#else
                        bio_endio(bio, -EIO);
#endif
                        return 0;
                }
                dsk_mem += bvec->bv_len;
        }

#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
        bio_endio(bio, bio->bi_size, 0);
#else
        bio_endio(bio, 0);
#endif

        return 0;
}


struct block_device_operations simp_blkdev_fops = {
        .owner                = THIS_MODULE,
};

static int __init simp_blkdev_init(void)
{
        int ret;

        simp_blkdev_queue = blk_alloc_queue(GFP_KERNEL);
        if (!simp_blkdev_queue) {
                ret = -ENOMEM;
                goto err_alloc_queue;
        }
        blk_queue_make_request(simp_blkdev_queue, simp_blkdev_make_request);

        simp_blkdev_disk = alloc_disk(1);
        if (!simp_blkdev_disk) {
                ret = -ENOMEM;
                goto err_alloc_disk;
        }

        strcpy(simp_blkdev_disk->disk_name, SIMP_BLKDEV_DISKNAME);
        simp_blkdev_disk->major = SIMP_BLKDEV_DEVICEMAJOR;
        simp_blkdev_disk->first_minor = 0;
        simp_blkdev_disk->fops = &simp_blkdev_fops;
        simp_blkdev_disk->queue = simp_blkdev_queue;
        set_capacity(simp_blkdev_disk, SIMP_BLKDEV_BYTES>>9);
        add_disk(simp_blkdev_disk);

        return 0;

err_alloc_disk:
        blk_cleanup_queue(simp_blkdev_queue);
err_alloc_queue:
        return ret;
}


static void __exit simp_blkdev_exit(void)
{
        del_gendisk(simp_blkdev_disk);
        put_disk(simp_blkdev_disk);
        blk_cleanup_queue(simp_blkdev_queue);
}

module_init(simp_blkdev_init);
module_exit(simp_blkdev_exit);
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP