Profil von 郁芊依稀BlogListenNetzwerk Extras Hilfe
Listen
26 Dezember

摘录

#include <linux/fs.h>
int register_blkdev(unsigned int major,const char *name,struct block_device_operations *bdops);
int unregister_blkdev(unsigned int major, const char *name);
//注册设备
struct block_device_operations{
 int(*open)(struct inode *inode,struct file *filp);
 int(*release)(struct inode *inode,struct file *filp);
 int(*ioctl)(struct inode *inode,struct file *filp,unsigned command,unsigned long argument);
 int(*check_media_change)(kdev_t dev);
 int(*revalidate)(kdev_t dev);
}
#include <linxu/blkdev.h>
blk_init_queue(request_queue_t *queue, request_fn_proc *request/*关联*/);
blk_cleanup_queue(request_queue_t *queue);
BLK_DEFAULT_QUEUE(major) //获得默认队列

struct blk_dev_struct{
 request_queue_t request_queue;
 queue_proc  *queue;
 void *data;

struct blk_dev_struct blk_dev[MAX_BLKDEV];
int blk_size[][] //设备大小
int read_ahead[]; //预先读取扇区数 顺序
int max_readahead[][]; //预先读取扇区数 离散
int max_selectors[][]; //
int blksize_size[][];  //块大小
int hardsect_size[][]; //扇区大小
fsync_dev(dev_t);//刷新设备
MAJOR_NR
DEVICE_NAME
DEVICE_NR(kdev_t device)
DEVICE_INTR
#include <linux/blk.h>
spinlock_t io_request_lock;
struct request *CURRENT
INIT _REQUEST;
end_request(int status);
struct request *blkdev_entry_next_request(struct list_head *head);//请求队列下一项
struct request *blkdev_next_request(struct request *req); //获取前后项
struct request *blkdev_prev_request(struct request *req); 
blkdev_dequeue_request(struct request *req);   //删除请求
blkdev_release_request(struct request *req);   //释放
io_request_lock(

blk_queue_headactive(request_queue_t *queue, int active); //0=活动头,可修改
void blk_queue_make_request(request_queue_t *queue, make_request_fn *func);
end_that_request_first(struct request *req, int status, char *name);
end_that_request_last(struct request *req);
bh->b_end_io(struct buffer_head *bh, int status);
#include<linux/blkpg.h>
int blk_ioctl(kdev_t dev, unsigned int cmd, unsigned long arg);
#include<linux/fs.h>
BLKGETSIZE  //检索大小 扇区为单位
BLKFLSBUF //刷新缓冲区
BLKRRPART //重读分区表
BLKRAGET
BLKRASET //块级预读值
BLKFRAGET
BLKFRASET //文件系统级预读值
BLKROGET
BLKROSET //只读位
HDIO_GETGEO //检索磁盘的几何参数
int check_disk_change(kdev_t dev);
#include<linux/gendisk.h>
struct gendisk;
struct gendisk *gendisk_head;
void register_disk(struct gendisk *gd, int driver, unsigned minors, struct block_device_operations *ops, long size);
 
typedef struct page {
 struct list_head list;  /* ->mapping has some page lists. */
 struct address_space *mapping; /* The inode (or ...) we belong to. */
 unsigned long index;  /* Our offset within mapping. */
 struct page *next_hash;  /* Next page sharing our hash bucket in
        the pagecache hash table. */
 atomic_t count;   /* Usage count, see below. */
 unsigned long flags;  /* atomic flags, some possibly
        updated asynchronously */
 struct list_head lru;  /* Pageout list, eg. active_list;
        protected by pagemap_lru_lock !! */
 struct page **pprev_hash; /* Complement to *next_hash. */
 struct buffer_head * buffers; /* Buffer maps us to a disk block. */
 
 
struct list_head {
 struct list_head *next, *prev;
};
#define Page_Uptodate(page) test_bit(PG_uptodate, &(page)->flags)
      3
struct buffer_head {
 /* First cache line: */
 struct buffer_head *b_next; /* Hash queue list */
 unsigned long b_blocknr; /* block number */
 unsigned short b_size;  /* block size */
 unsigned short b_list;  /* List that this buffer appears */
 kdev_t b_dev;   /* device (B_FREE = free) */
 atomic_t b_count;  /* users using this block */
 kdev_t b_rdev;   /* Real device */
 unsigned long b_state;  /* buffer state bitmap (see above) */
 unsigned long b_flushtime; /* Time when (dirty) buffer should be written */
 struct buffer_head *b_next_free;/* lru/free list linkage */
 struct buffer_head *b_prev_free;/* doubly linked list of buffers */
 struct buffer_head *b_this_page;/* circular list of buffers in one page */
 struct buffer_head *b_reqnext; /* request queue */
 struct buffer_head **b_pprev; /* doubly linked list of hash-queue */
 char * b_data;   /* pointer to data block */
 struct page *b_page;  /* the page this bh is mapped to */
 void (*b_end_io)(struct buffer_head *bh, int uptodate); /* I/O completion */
  void *b_private;  /* reserved for b_end_io */
 unsigned long b_rsector; /* Real buffer location on disk */
 wait_queue_head_t b_wait;
 struct inode *      b_inode;
 struct list_head     b_inode_buffers; /* doubly linked list of inode dirty buffers */
};
static inline void (struct buffer_head * bh, int on)
{
 if (on)
  set_bit(BH_Uptodate, &bh->b_state);
 else
  clear_bit(BH_Uptodate, &bh->b_state);
}
static inline void *kmap(struct page *page)
{
 if (in_interrupt())
  out_of_line_bug();
 if (page < highmem_start_page)
  return page_address(page);
 return kmap_high(page);
}
#define in_interrupt() ({ int __cpu = smp_processor_id(); (local_irq_count(__cpu) + local_bh_count(__cpu) != 0); })
struct address_space {
 struct list_head clean_pages; /* list of clean pages */
 struct list_head dirty_pages; /* list of dirty pages */
 struct list_head locked_pages; /* list of locked pages */
 unsigned long  nrpages; /* number of total pages */
 struct address_space_operations *a_ops; /* methods */
 struct inode  *host;  /* owner: inode, block_device */
 struct vm_area_struct *i_mmap; /* list of private mappings */
 struct vm_area_struct *i_mmap_shared; /* list of shared mappings */
 spinlock_t  i_shared_lock;  /* and spinlock protecting it */
 int   gfp_mask; /* how to allocate the pages */
};

NVRAM driver

#include <linux/config.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/ioport.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/config.h>
#include <linux/module.h>
#include <asm/system.h>   /* cli(), *_flags */
MODULE_LICENSE("Dual BSD/GPL");
static int a=1;
#define MEM_ADDR 0xD0000
#define MEM_LEN (a<<16)
#define PORT_ADDR 0x148
#define CTRLSHIFT 192
typedef struct Rd_Dev {
int usage;
int removable;
spinlock_t lock;
} Rd_Dev;
struct Rd_Dev *rd_dev = NULL;
static unsigned long *ptr;
static int major=0;
static int rahead=2;
static int hardsect=512;
int rd_open(struct inode *inode, struct file *filp)
{
 printk("enter rd_open\n");
 spin_lock(&rd_dev->lock);
 rd_dev->usage++;
 MOD_INC_USE_COUNT;
 if(rd_dev->removable && rd_dev->usage == 1)
  check_disk_change(inode->i_rdev);
 spin_unlock(&srd_dev->lock);
 return 0;
}
void rd_release(struct inode *inode, struct file *filp)
{
 rd_dev->usage--;
 if(rd_dev->removable && !rd_dev->usage)
  invalidate_buffers(inode->i_rdev);
 MOD_DEC_USE_COUNT;
}

struct block_device_operations rd_bdops ={
 open: rd_open,
 release: rd_release,
 ioctl: NULL,
 check_media_change: NULL,
 revalidate: NULL,
};
static int rd_make_request(request_queue_t *queue, int rw, struct buffer_head *bh)
{
    unsigned long *rdptr;
    unsigned long offset,index;
    int time;//传输次数
    int i;
    unsigned long r_size;//需要传输大小
    unsigned long t_size;//每次传输大小
   
    /*if (bh->b_rsector * hardsect+bh->b_size > rd_blksize*rd_size) {
        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);  //页内偏移
    index=(bh->b_rsector * hardsect)>>16;  //页数
   
    rdptr = ptr + offset;    //获取映射地址
    r_size=bh->b_size;     //
    if(r_size>(MEM_LEN-offset)){
     time=(r_size-(MEM_LEN-offset))>>16 + 2;
    }else time=1;
   
#if CONFIG_HIGHMEM
    bh = create_bounce(rw, bh);
#endif
    /* Do the transfer */
    switch(rw) {
        case READ:
        case READA:  /* Readahead */
            while(time){
             outb(index|CTRLSHIFT,PORT_ADDR);
             if(time==1) t_size=r_size;
             else {t_size=MEM_LEN-offset;offset=0;}
             for(i=0;i<t_size;i++){
              bh->b_data=readb(ptr);
              ptr++;
              bh->b_data++;
             }
             r_size-=t_size;
             time--;
             index++;
            }
            bh->b_end_io(bh, 1);
            break;
        case WRITE:
            refile_buffer(bh);
            while(time){
             outb(index|CTRLSHIFT,PORT_ADDR);
             if(time==1)t_size=r_size;
             else  {t_size=MEM_LEN-offset;offset=0;}
             for(i=0;i<t_size;i++){
              writeb(ptr,bh->b_data);
              ptr++;
              bh->b_data++;
             }
             r_size-=t_size;
             time--;
             index++;
            } /* from buffer to sbull */
            mark_buffer_uptodate(bh, 1);
            bh->b_end_io(bh, 1);
            break;
        default:
            /* can't happen */
            bh->b_end_io(bh, 0);
            break;
    }
    /* Nonzero return means we're done */
    return 0;
}
int init_module()
{
 int result;
 int rd_major=major;
 if(check_mem_region(MEM_ADDR,MEM_LEN)){
  printk("the memory is already in use/n");
  return -EBUSY;
 }
 request_mem_region(MEM_ADDR,MEM_LEN,"rd");
 ptr=ioremap(MEM_ADDR,MEM_LEN);
 result = register_blkdev(rd_major, "ramdisk", &rd_bdops);
 if (result < 0) {
         printk("rd: can't get major %d\n",rd_major);
         return result;
     }
     if (rd_major == 0) rd_major = result; /* dynamic */
     major = rd_major; 
 rd_dev = kmalloc(sizeof(Rd_Dev));
 if(!rd_dev)
  goto fail;
 memset(rd_dev, sizeof(Rd_Dev), 0);
 rd_dev->removable = 0;
 spin_lock_init(&rd_dev->lock);
 read_ahead=rahead;
 blk_queue_make_request(BLK_DEFAULT_QUEUE(major), rd_make_request);
 register_disk(NULL, MKDEV(rd_major, 0),1, rd_bdops, a<<22);
 return 0;
 
 fail:
 kfree(rd_dev);
 unregister_blkdev(rd_major, "rd");
}
void cleanup_module()
{
 spin_lock(&rd_dev->lock);
 rd_dev->usage++;
 spin_unlock(&rd_dev->lock);
 printk("before fsync_dev\n");
 fsync_dev(MKDEV(major, 0)); /* flush the devices */
 printk("after fsync_dev\n");
 unregister_blkdev(major, "rd");
 release_mem_region(MEM_ADDR,MEM_LEN);
 printk("after unregister_blkdev\n");
 printk("after blk_cleanup_queue\n");
 printk("after vfree\n");
 kfree(rd_dev);
}
 

依稀