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

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

时间:11-20 来源:互联网 点击:

  1. chipsalwayspoweruplocked.Unlockthemnow*/
  2. if((mtd->flags&MTD_WRITEABLE)
  3. &&(mtd->flags&MTD_POWERUP_LOCK)&&mtd->unlock){
  4. if(mtd->unlock(mtd,0,mtd->size))
  5. printk(KERN_WARNING
  6. "%s:unlockfailed,writesmaynotwork\n",
  7. mtd->name);
  8. }
  9. /*Callershouldhavesetdev.parenttomatchthe
  10. *physicaldevice.
  11. */
  12. mtd->dev.type=&mtd_devtype;
  13. mtd->dev.class=&mtd_class;
  14. mtd->dev.devt=MTD_DEVT(i);
  15. //设置mtd设备名
  16. dev_set_name(&mtd->dev,"mtd%d",i);
  17. //设置mtd设备信息mtd_info
  18. dev_set_drvdata(&mtd->dev,mtd);
  19. //注册设备
  20. if(device_register(&mtd->dev)!=0)
  21. gotofail_added;
  22. //创建设备
  23. if(MTD_DEVT(i))
  24. device_create(&mtd_class,mtd->dev.parent,
  25. MTD_DEVT(i)+1,
  26. NULL,"mtd%dro",i);
  27. DEBUG(0,"mtd:Givingoutdevice%dto%s\n",i,mtd->name);
  28. /*Noneedtogetarefcountonthemodulecontaining
  29. thenotifier,sinceweholdthemtd_table_mutex*/
  30. //遍历list链表将每个mtd_notifier执行add()函数,对新加入的mtd设备操作,通知所有的MTDuser新的MTD设备的到来
  31. list_for_each_entry(not,&mtd_notifiers,list)
  32. not->add(mtd);
  33. //解锁信号量
  34. mutex_unlock(&mtd_table_mutex);
  35. /*We_know_wearentbeingremoved,because
  36. ourcallerisstillholdingushere.Sonone
  37. ofthistry_nonsense,andnobitchingaboutit
  38. either.:)*/
  39. __module_get(THIS_MODULE);
  40. return0;
  41. fail_added:
  42. idr_remove(&mtd_idr,i);
  43. fail_locked:
  44. mutex_unlock(&mtd_table_mutex);
  45. return1;
  46. }

其中用到的IDR机制如下:

(1)获得idr
要在代码中使用idr,首先要包括。接下来,我们要在代码中分配idr结构体,并初始化:
void idr_init(struct idr *idp);
其中idr定义如下:
struct idr {
struct idr_layer *top;
struct idr_layer *id_free;
int layers;
int id_free_cnt;
spinlock_t lock;
};
/* idr是idr机制的核心结构体 */
(2)为idr分配内存
int idr_pre_get(struct idr *idp, unsigned int gfp_mask);
每次通过idr获得ID号之前,需要先分配内存。
返回0表示错误,非零值代表正常
(3)分配ID号并将ID号和指针关联
int idr_get_new(struct idr *idp, void *ptr, int *id);
int idr_get_new_above(struct idr *idp, void *ptr, int start_id, int *id);
idp: 之前通过idr_init初始化的idr指针
id: 由内核自动分配的ID号
ptr: 和ID号相关联的指针
start_id: 起始ID号。内核在分配ID号时,会从start_id开始。如果为I2C节点分配ID号,可以将设备地址作为start_id
函数调用正常返回0,如果没有ID可以分配,则返回-ENOSPC
在实际中,上述函数常常采用如下方式使用:
again:
if (idr_pre_get(&my_idr, GFP_KERNEL) == 0) {
/* No memory, give up entirely */
}
spin_lock(&my_lock);
result = idr_get_new(&my_idr, &target, &id);
if (result == -EAGAIN) {
sigh();
spin_unlock(&my_lock);
goto again;
}
(4)通过ID号搜索对应的指针
void *idr_find(struct idr *idp, int id);
返回值是和给定id相关联的指针,如果没有,则返回NULL
(5)删除ID
要删除一个ID,使用:
void idr_remove(struct idr *idp, int id);
通过上面这些方法,内核代码可以为子设备,inode生成对应的ID号。这些函数都定义在lib/idr.c中

3、del_mtd_device函数

  1. /**
  2. *del_mtd_device-unregisteranMTDdevice
  3. *@mtd:pointertoMTDdeviceinfostructure
  4. *
  5. *RemoveadevicefromthelistofMTDdevicespresentinthesystem,
  6. *andnotifyeachcurrentlyactiveMTDuserofitsdeparture.
  7. *Returnszeroonsuccessor1onfailure,whichcurrentlywillhappen
  8. *iftherequesteddevicedoesnotappeartobepresentinthelist.
  9. */
  10. //删除mtd设备函数。
  11. //从MTD设备的链表中移除该MTD设备信息,并通知系统中所有的MTDuser该MTD设备的移除。
  12. //返回0表示成功,返回1表示出错(该设备信息不存在设备链表中)
  13. intdel_mtd_device(structmtd_info*mtd)
  14. {
  15. intret;
  16. structmtd_notifier*not;//定义一个mtd_notifier指针
  17. mutex_lock(&mtd_table_mutex);
  18. if(idr_find(&mtd_idr,mtd->index)!=mtd){
  19. ret=-ENODEV;
  20. gotoout_error;
  21. }
  22. /*Noneedtogetarefcountonthemodulecontaining
  23. thenotifier,sinceweholdthemtd_table_mutex*/
  24. //遍历list链表,并使每个mtd_notifier执行remove函数,通知每个MTDuser该设备的移除
  25. list_for_each_entry(not,&mtd_notifiers,list)
  26. not->remove(mtd);
  27. if(mtd->usecount){
  28. printk(KERN_NOTICE"RemovingMTDdevice#%d(%s)withusecount%d\n",
  29. mtd->index,mtd->name,mtd->usecount);
  30. ret=-EBUSY;
  31. }else{
  32. device_unregister(&mtd->device_unregiste

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

网站地图

Top