块设备驱动---RAMDISK

来源:互联网 发布:python 期货量化交易 编辑:程序博客网 时间:2024/05/20 04:30

#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/fs.h>#include <linux/types.h>#include <linux/fcntl.h>#include <linux/vmalloc.h>#include <linux/blkdev.h>#include <linux/hdreg.h>#define RAMHD_NAME              "ramhd"#define RAMHD_MAX_DEVICE        2#define RAMHD_MAX_PARTITIONS    4#define RAMHD_SECTOR_SIZE       512#define RAMHD_SECTORS           16#define RAMHD_HEADS             4#define RAMHD_CYLINDERS         256#define RAMHD_SECTOR_TOTAL      (RAMHD_SECTORS * RAMHD_HEADS * RAMHD_CYLINDERS)#define RAMHD_SIZE              (RAMHD_SECTOR_SIZE * RAMHD_SECTOR_TOTAL) //8MBtypedef struct{    unsigned char *data;    struct request_queue *queue;    struct gendisk  *gd;}RAMHD_DEV;char *sdisk[RAMHD_MAX_DEVICE] = {NULL,};EXPORT_SYMBOL_GPL(sdisk);static RAMHD_DEV *rdev[RAMHD_MAX_DEVICE] = {NULL,};static dev_t ramhd_major;static int ramhd_space_init(void){    int i;    int err = 0;    for(i = 0; i < RAMHD_MAX_DEVICE; i++){        sdisk[i] = vmalloc(RAMHD_SIZE);        if(!sdisk[i]){            printk("vmalloc failed!");            err = -ENOMEM;            return err;        }        printk("sdisk[%d]=%p\n", i, sdisk[i]);        memset(sdisk[i], 0, RAMHD_SIZE);    }    return err;}static void ramhd_space_clean(void){    int i;    for(i = 0; i < RAMHD_MAX_DEVICE; i++){        vfree(sdisk[i]);    }}static int ramhd_open(struct block_device *bdev, fmode_t mode){    return 0;}static int ramhd_release(struct gendisk *gd, fmode_t mode){       return 0;}static int ramhd_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg){    int err;    struct hd_geometry geo;    switch(cmd)    {        case HDIO_GETGEO:            err = !access_ok(VERIFY_WRITE, arg, sizeof(geo));            if(err) return -EFAULT;            geo.cylinders = RAMHD_CYLINDERS;            geo.heads = RAMHD_HEADS;            geo.sectors = RAMHD_SECTORS;            geo.start = get_start_sect(bdev);            if(copy_to_user((void *)arg, &geo, sizeof(geo)))                return -EFAULT;            return 0;    }           return -ENOTTY;}static struct block_device_operations ramhd_fops ={   .owner = THIS_MODULE,    .open = ramhd_open,    .release = ramhd_release,    .ioctl = ramhd_ioctl,};static int ramhd_make_request(struct request_queue *q, struct bio *bio){    char *pRHdata;    char *pBuffer;    struct bio_vec *bvec;    int i;    int err = 0;        struct block_device *bdev = bio->bi_bdev;RAMHD_DEV *pdev = bdev->bd_disk->private_data;    if(((bio->bi_sector * RAMHD_SECTOR_SIZE) + bio->bi_size) > RAMHD_SIZE){        err = -EIO;        goto out;    }    pRHdata = pdev->data + (bio->bi_sector * RAMHD_SECTOR_SIZE);    bio_for_each_segment(bvec, bio, i) {        pBuffer = kmap(bvec->bv_page) + bvec->bv_offset;switch(bio_data_dir(bio))        {            case READ:                memcpy(pBuffer, pRHdata, bvec->bv_len);                flush_dcache_page(bvec->bv_page);                break;            case WRITE:                flush_dcache_page(bvec->bv_page);                memcpy(pRHdata, pBuffer, bvec->bv_len);                break;            default:                kunmap(bvec->bv_page);                goto out;        }        kunmap(bvec->bv_page);        pRHdata += bvec->bv_len;}out:bio_endio(bio, err);    return 0;      }static int alloc_ramdev(void){    int i;    for(i = 0; i < RAMHD_MAX_DEVICE; i++){        rdev[i] = kzalloc(sizeof(RAMHD_DEV), GFP_KERNEL);        if(!rdev[i])            return -ENOMEM;    }    return 0;}static void clean_ramdev(void){    int i;    for(i = 0; i < RAMHD_MAX_DEVICE; i++){        if(rdev[i])            kfree(rdev[i]);    }   }      static int __init ramhd_init(void){    int i;    int err;    err = ramhd_space_init();    if(err)        return err;    alloc_ramdev();    ramhd_major = register_blkdev(0, RAMHD_NAME);    for(i = 0; i < RAMHD_MAX_DEVICE; i++)    {          rdev[i]->data = sdisk[i];        rdev[i]->queue = blk_alloc_queue(GFP_KERNEL);        blk_queue_make_request(rdev[i]->queue, ramhd_make_request);        rdev[i]->gd = alloc_disk(RAMHD_MAX_PARTITIONS);        rdev[i]->gd->major = ramhd_major;        rdev[i]->gd->first_minor = i * RAMHD_MAX_PARTITIONS;        rdev[i]->gd->fops = &ramhd_fops;        rdev[i]->gd->queue = rdev[i]->queue;        rdev[i]->gd->private_data = rdev[i];        sprintf(rdev[i]->gd->disk_name, "ramhd%c", 'a'+i);        rdev[i]->gd->flags |= GENHD_FL_SUPPRESS_PARTITION_INFO;        set_capacity(rdev[i]->gd, RAMHD_SECTOR_TOTAL);        add_disk(rdev[i]->gd);    }    return 0;}static void __exit ramhd_exit(void){    int i;    for(i = 0; i < RAMHD_MAX_DEVICE; i++)    {        del_gendisk(rdev[i]->gd);        put_disk(rdev[i]->gd);        blk_cleanup_queue(rdev[i]->queue);      }     clean_ramdev();    ramhd_space_clean();    unregister_blkdev(ramhd_major,RAMHD_NAME);    }module_init(ramhd_init);module_exit(ramhd_exit);MODULE_AUTHOR("chen ");MODULE_DESCRIPTION("The ramdisk implementation with request function");MODULE_LICENSE("GPL");