| Profil von 郁芊依稀BlogListenNetzwerk | Hilfe |
|
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); } 依稀 |
||||
|
|