微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > ARM-Linux驱动--MTD驱动分析(二)

ARM-Linux驱动--MTD驱动分析(二)

时间:11-20 来源:互联网 点击:
主机:Gentoo Linux 11.2 with linux kernel 3.0.6

硬件平台:FL2440(S3C2440)with linux kernel 2.6.35

1、mtd_notifier结构体

  1. //MTD设备通知结构体
  2. structmtd_notifier{
  3. void(*add)(structmtd_info*mtd);//加入MTD原始/字符/块设备时执行
  4. void(*remove)(structmtd_info*mtd);//移除MTD原始/字符/块设备时执行
  5. structlist_headlist;//list是双向链表,定义在include/linux/list.h
  6. };

而struct list_head定义在/include/linux/list.h中,内核中其宏定义和函数如下

INIT_LIST_HEAD(ptr) 初始化ptr节点为表头,将前趋与后继都指向自己。
LIST_HEAD(name) 声明并初始化双向循环链表name。

static inline void __list_add(struct list_head *new, struct list_head *prev, struct list_head *next)
向链表中在prev与next之间插入元素new
static inline void list_add(struct list_head *new, struct list_head *head)
在链表中头节点后插入元素new,调用__list_add()实现。
static inline void list_add_tail(struct list_head *new, struct list_head *head)
在链表末尾插入元素new,调用__list_add()实现。

static inline void __list_del(struct list_head * prev, struct list_head * next)
删除链表中prev与next之间的元素。
static inline void list_del(struct list_head *entry)
删除链表中的元素entry。

static inline void list_del_init(struct list_head *entry)
从链表中删除元素entry,并将其初始化为新的链表。
static inline void list_move(struct list_head *list, struct list_head *head)
从链表中删除list元素,并将其加入head链表。
static inline void list_move_tail(struct list_head *list, struct list_head *head)
把list移动到链表末尾。

static inline int list_empty(const struct list_head *head)
测试链表是否为空。

static inline void __list_splice(struct list_head *list, struct list_head *head)
将链表list与head合并。
static inline void list_splice(struct list_head *list, struct list_head *head)
在list不为空的情况下,调用__list_splice()实现list与head的合并。
static inline void list_splice_init(struct list_head *list, struct list_head *head)
将两链表合并,并将list初始化。

list_entry(ptr, type, member)
list_entry的定义是怎么回事?
a. list_entry的定义在内核源文件include/linux/list.h中:
#define list_entry(ptr, type, member)
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
b. 其功能是根据list_head型指针ptr换算成其宿主结构的起始地址,该宿主结构是type型的,而ptr在其宿主结构中定义为member成员。

2、add_mtd_device函数

  1. /**
  2. *add_mtd_device-registeranMTDdevice
  3. *@mtd:pointertonewMTDdeviceinfostructure
  4. *
  5. *AddadevicetothelistofMTDdevicespresentinthesystem,and
  6. *notifyeachcurrentlyactiveMTDuserofitsarrival.Returns
  7. *zeroonsuccessor1onfailure,whichcurrentlywillonlyhappen
  8. *ifthereisinsufficientmemoryorasysfserror.
  9. */
  10. //添加MTD设备函数,将MTD设备加入MTD设备链表,并通知所有的MTDuser该MTD设备。返回0表示成功,返回1表示出错(内存不足或文件系统错误)
  11. intadd_mtd_device(structmtd_info*mtd)
  12. {
  13. structmtd_notifier*not;//定义一个MTD设备通知器
  14. inti,error;
  15. //下面是设置mtd_info结构体信息
  16. if(!mtd->backing_dev_info){
  17. switch(mtd->type){
  18. caseMTD_RAM://MTD_RAM定义在include/mtd/mtd-abi.h
  19. mtd->backing_dev_info=&mtd_bdi_rw_mappable;
  20. break;
  21. caseMTD_ROM:
  22. mtd->backing_dev_info=&mtd_bdi_ro_mappable;
  23. break;
  24. default:
  25. mtd->backing_dev_info=&mtd_bdi_unmappable;
  26. break;
  27. }
  28. }
  29. BUG_ON(mtd->writesize==0);
  30. mutex_lock(&mtd_table_mutex);//给操作mtd_table加锁
  31. do{
  32. if(!idr_pre_get(&mtd_idr,GFP_KERNEL))//为mtd_idr分配内存
  33. gotofail_locked;
  34. error=idr_get_new(&mtd_idr,mtd,&i);//将id号和mtd_idr关联
  35. }while(error==-EAGAIN);
  36. if(error)
  37. gotofail_locked;
  38. mtd->index=i;
  39. mtd->usecount=0;
  40. if(is_power_of_2(mtd->erasesize))
  41. mtd->erasesize_shift=ffs(mtd->erasesize)-1;
  42. else
  43. mtd->erasesize_shift=0;
  44. if(is_power_of_2(mtd->writesize))
  45. mtd->writesize_shift=ffs(mtd->writesize)-1;
  46. else
  47. mtd->writesize_shift=0;
  48. mtd->erasesize_mask=(1erasesize_shift)-1;
  49. mtd->writesize_mask=(1writesize_shift)-1;
  50. /*Some

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top