设为首页 加入收藏

TOP

Linux驱动开发之块设备初入门(三)
2016-12-12 08:15:24 】 浏览:633
Tags:Linux 驱动 开发 设备 入门
void blk_start_queue(request_queue_t* queue);

//参数设置
void blk_queue_max_sectors(request_queue_t* q, unsigned short max);
/*请求可包含的最大扇区数.默认255*/

void blk_queue_max_phys_segments(request_queue_t* q, unsigned short max);
void blk_queue_max_hw_segments(request_queue_t* q, unsigned short max);
/*这两个函数设置一个请求可包含的最大物理段数(系统内存中不相邻的区),缺省是128*/


void blk_queue_max_segment_size(request_queue_t* q, unsigned int max);
/*告知内核请求短的最大字节数,默认2^16 = 65536*/

//通告内核
void blk_queue_bounce_limit(request_queue_t* queue, u64 dma_addr);
/*
* 此函数告知内核设备执行DMA时,可使用的最高物理地址dma_addr,常用的宏如下:
* BLK_BOUNCE_HIGH:对高端内存页使用反弹缓冲(缺省)
* BLK_BOUNCE_ISA:驱动只可以在MB的ISA区执行DMA
* BLK_BOUNCE_ANY:驱动可在任何地方执行DMA
*/

blk_queue_segment_boundary(request_queue_t* queue, unsigned long mask);
/*这个函数在设备无法处理跨越一个特殊大小内存边界的请求时,告知内核这个边界.*/

void blk_queue_dma_alignment(request_queue_t* q, int mask);
/*告知内核设备加于DMA传送的内存对齐限制*/

viod blk_queue_hardsect_size(request_queue_t* q, unsigned short max);
/*此函数告知内核块设备硬件扇区大小*/


块IO(bio)结构体:
通常一个bio对应一个IO请求,IO调度算法可以将连续的bio合并成一个请求,所以一个请求包含多个bio

struct bio {
sector_t bi_sector; /* device address in 512 byte sectors */
struct bio *bi_next; /* request queue link */
struct block_device *bi_bdev;

/*如果是一个写请求,最低有效位被置位,可使用bio_data_dir(bio)宏来获取读写方向*/
unsigned long bi_flags; /* status, command, etc */
unsigned long bi_rw; /* 低位代表:READ/WRITE,高位代表:优先级 */


unsigned short bi_vcnt; /* how many bio_vec's (bio_vec的数量)*/
unsigned short bi_idx; /* current index into bvl_vec(当前bio_vec的索引) */


/*不相邻的物理段的数目*/
unsigned short bi_phys_segments;

/*物理合并和DMA remap合并后不相邻的物理扇区*/
unsigned short bi_hw_segments;


/*被传送的数据大小(byte),用bio_sector(bio)获取扇区为单位的大小*/
unsigned int bi_size; /* residual I/O count */


/*被传送的数据大小(byte),用bio_sector(bio)获取扇区为单位的大小*/
/*为了明了最大的hw尺寸,考虑bio中第一个和最后一个虚拟的可合并的段的尺寸*/
unsigned int bi_hw_front_size;
unsigned int bi_hw_back_size;


unsigned int bi_max_vecs; /*能持有的最大bvl_vecs数*/


struct bio_vec *bi_io_vec; /*能持有的最大bvl_vecs数*/
...................
}


struct bio_vec {
struct page *bv_page; /*要操作的页指针*/
unsigned int bv_len; /*要传输的字节数*/
unsigned int bv_offset;/*偏移位置*/
};

/*一般不直接访问bio的bio_vec成员,而使用bio_for_each_segment()宏进行操作.
*该宏循环遍历整个bio中的每个段.
*/
#define __bio_for_each_segment(bvl, bio, i, start_idx)\
for(
bvl = bio_iovec_idx((bio),(start_idx)),i = (start_idx);\
i <(bio)->bi_vcnt;\
bvl++, i++\
)
#define bio_for_each_segment(bvl, bio, i)\
__bio_for_each_segment(bvl, bio, i, (bio)->bi_idx)

在内核中,提供了一组函数(宏)用于操作bio:
int bio_data_dir(struct bio* bio);

该函数用于获得数据传送方向.
struct page* bio_page(struct bio* bio);

该函数用于获得目前的页指针.
int bio_offset(struct bio* bio);

该函数返回操作对应的当前页的页内偏移,通常块IO操作本身就是页对齐的.
int bio_cur_sectors(struct bio* bio);

该函数返回当前bio_vec要传输的扇区数.
char* bio_data(struct bio* bio);

该函数返回数据缓冲区的内核虚拟地址.
char* bvec_kmap_irq(struct bio_vec* bvec, unsigned long* offset);
该函数也返回一个内核虚拟地址此地址可用于存取被给定的bio_vec入口指向的数据缓冲区.同时会屏蔽中断并返回一个原子kmap,因此,在此函数调用之前,驱动不应该是睡眠状态.
void bvec_kunmap_irq(char* buffer, unsigned long flags

首页 上一页 1 2 3 4 5 6 下一页 尾页 3/6/6
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Nand Flash驱动程序编写 下一篇在Linux下的中断方式读取按键驱动..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目