⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nvram.txt

📁 为Linux环境开发的NVRAM驱动源码
💻 TXT
字号:
#define MODULE
#include <linux/ioport.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <linux/init.h>
#include <asm/io.h>
#include <linux/ioport.h>
#include <linux/module.h>
#include <linux/errno.h> /* error codes */
#include <linux/timer.h>
#include <linux/types.h> /* size_t */
#include <linux/hdreg.h> /* HDIO_GETGEO */
#include <linux/kdev_t.h>
#include <linux/vmalloc.h>
#include <linux/genhd.h>
#include <linux/blkdev.h>
#define MAJOR_NR rd_major /* force definitions on in blk.h */
static int rd_major; /* must be declared before including blk.h */

MODULE_LICENSE("Dual BSD/GPL");
static unsigned long port_addr=0x148;   /*ioport address*/
static unsigned int ctlmask=0xc0;   /*a part of control signal of nvram stand for 0x1100000*/
static unsigned long mem_addr=0xD0000;   /*io memory address*/
static unsigned long mem_len=0x10000;   /*io memory lenth*/
static char *ptr;      /*the point for the ioremap*/ 
static int major=0;     
static int hardsect=512;


static int rd_make_request(request_queue_t *queue, int rw, struct buffer_head *bh)
{
    char *rdptr,*result;
    unsigned long offset;    /*the offset in one 64K window*/
    unsigned long index;    /*the number of the window in all 64 windows in this request*/
    int time;      /*how many times the ioremap will do */
    int i;
    unsigned long r_size;    /*the size of data in one request*/
    unsigned long t_size;    /*the size of data in one tansfer*/
    
    /*check if the request out of the disk size or not*/
    if (bh->b_rsector * hardsect+bh->b_size > 0x400000) {
        static int count = 0;
        if (count++ < 5)
            printk("ram: request past end of device\n");
        bh->b_end_io(bh, 0);
        return 0;
    }

    offset=(bh->b_rsector * hardsect) & (mem_len-1);  /*get the offset in this request*/
    index=(bh->b_rsector * hardsect)>>16;  /*get the index in this request*/
    rdptr = ptr + offset;    /*get the actual address in the memory*/
    r_size=bh->b_size;     /*record the size of data for translation in r_size*/     
    if(r_size>(mem_len-offset)){   /*calculate the variable time*/
     time=(r_size-(mem_len-offset))>>16 + 2;  
    }else time=1;
    
    /* Do the transfer */
    switch(rw) {
        /*read progess*/
        case READ:
        case READA:  /* Readahead */
            while(time){
             outb(index|ctlmask,port_addr);
             if(time==1) t_size=r_size;
             else t_size=mem_len-offset;
             result=memcpy_fromio(bh->b_data,rdptr,t_size);
             r_size-=t_size;
             time--;
             index++;
             offset=0;
            }
            bh->b_end_io(bh, 1);
            break;/*read end*/
        /*write progess*/
        case WRITE: 
            refile_buffer(bh);
            while(time){
             outb(index|ctlmask,port_addr);
             if(time==1)t_size=r_size;
             else  t_size=mem_len-offset;
             result=memcpy_toio(rdptr,bh->b_data,t_size);
             r_size-=t_size;
             time--;
             index++;
             offset=0;
            } 
            mark_buffer_uptodate(bh, 1);
            bh->b_end_io(bh, 1);
            break;/*write end*/
        default:
            /* can't happen */
            bh->b_end_io(bh, 0);
            break;
    }

    return 0;
}

int rd_open(struct inode *inode, struct file *filp) 
{ 
 MOD_INC_USE_COUNT; 
 return 0; 
}

int rd_release(struct inode *inode, struct file *filp) 
{ 
 MOD_DEC_USE_COUNT; 
 return 0;
}

int rd_ioctl (struct inode *inode, struct file *filp,
                 unsigned int cmd, unsigned long arg)
{
    int err;
    long size;   /*amount of hardsects*/
    struct hd_geometry geo;
    printk("ioctl 0x%x 0x%lx\n", cmd, arg);
    switch(cmd) {

      case BLKGETSIZE:
        /* Return the device size, expressed in sectors */
        if (!arg) return -EINVAL; /* NULL pointer: not valid */
        err = ! access_ok (VERIFY_WRITE, arg, sizeof(long));
        if (err) return -EFAULT;
        size = 0x400000/512;
 if (copy_to_user((long *) arg, &size, sizeof (long)))
     return -EFAULT;
        return 0;

      case BLKRRPART: /* re-read partition table: can't do it */
        return -ENOTTY;

      case HDIO_GETGEO:
        /*
  * Get geometry: since we are a virtual device, we have to make
  * up something plausible.  So we claim 16 sectors, four heads,
  * and calculate the corresponding number of cylinders.  We set the
  * start of data at sector four.
         */
        err = ! access_ok(VERIFY_WRITE, arg, sizeof(geo));
        if (err) return -EFAULT;
        size = 0x400000/512;
        geo.cylinders = (size & ~0x3f) >> 6;
 geo.heads = 4;
 geo.sectors = 16;
 geo.start = 4;
 if (copy_to_user((void *) arg, &geo, sizeof(geo)))
     return -EFAULT;
        return 0;

      default:
        /*
         * For ioctls we don't understand, let the block layer handle them.
         */
        return blk_ioctl(inode->i_rdev, cmd, arg);
    }

    return -ENOTTY; /* unknown command */
}

struct block_device_operations rd_bdops ={ 
 open: rd_open, 
 release: rd_release, 
 ioctl: rd_ioctl, 
 check_media_change: NULL, 
 revalidate: NULL, 
};  





static int rd_init(void){
 int result; 
 int rd_major=major;
 /*check the io memory*/
 if(check_mem_region(mem_addr,mem_len)){ 
  printk("memory busy\n");
  return -1;
 }
 /*request the io memory*/
 request_mem_region(mem_addr,mem_len,"NVRAM DRIVER");
 
 /*mapping*/
 outb(ctlmask,port_addr);
 ptr=ioremap(mem_addr,mem_len);
 printk("Virtual Memory Address: 0x%x\n",ptr);
 
 /*register the device*/
 result = register_blkdev(rd_major, "nvram", &rd_bdops);
 if (result < 0) {
         printk("Nvram: can't get major %d\n",rd_major);
         return result;
     }
     if (rd_major == 0) rd_major = result; /* dynamic */
     major = rd_major;  
 printk("Devie Major Number: %d\n",major);
 
 /*register the request*/
 blk_queue_make_request(BLK_DEFAULT_QUEUE(major), rd_make_request);
 
 /*register the disk*/
 register_disk(NULL, MKDEV(rd_major, 0),1, &rd_bdops, 0x400000);
 
 printk("Nvram is Initialized\n");
 return 0;
}

static void rd_exit(void){ 
 fsync_dev(MKDEV(major, 0));      /*reflash the device*/
 unregister_blkdev(major,"nvram");   /*unregister the device*/
 iounmap(ptr);      /**/
 release_mem_region(mem_addr,mem_len);   /*release the io memory*/
 printk("Devie release...OK!\n");
}

module_init(rd_init);
module_exit(rd_exit);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -