ARM-Linux驱动--MTD驱动分析(二)
- chipsalwayspoweruplocked.Unlockthemnow*/
- if((mtd->flags&MTD_WRITEABLE)
- &&(mtd->flags&MTD_POWERUP_LOCK)&&mtd->unlock){
- if(mtd->unlock(mtd,0,mtd->size))
- printk(KERN_WARNING
- "%s:unlockfailed,writesmaynotwork\n",
- mtd->name);
- }
- /*Callershouldhavesetdev.parenttomatchthe
- *physicaldevice.
- */
- mtd->dev.type=&mtd_devtype;
- mtd->dev.class=&mtd_class;
- mtd->dev.devt=MTD_DEVT(i);
- //设置mtd设备名
- dev_set_name(&mtd->dev,"mtd%d",i);
- //设置mtd设备信息mtd_info
- dev_set_drvdata(&mtd->dev,mtd);
- //注册设备
- if(device_register(&mtd->dev)!=0)
- gotofail_added;
- //创建设备
- if(MTD_DEVT(i))
- device_create(&mtd_class,mtd->dev.parent,
- MTD_DEVT(i)+1,
- NULL,"mtd%dro",i);
- DEBUG(0,"mtd:Givingoutdevice%dto%s\n",i,mtd->name);
- /*Noneedtogetarefcountonthemodulecontaining
- thenotifier,sinceweholdthemtd_table_mutex*/
- //遍历list链表将每个mtd_notifier执行add()函数,对新加入的mtd设备操作,通知所有的MTDuser新的MTD设备的到来
- list_for_each_entry(not,&mtd_notifiers,list)
- not->add(mtd);
- //解锁信号量
- mutex_unlock(&mtd_table_mutex);
- /*We_know_wearentbeingremoved,because
- ourcallerisstillholdingushere.Sonone
- ofthistry_nonsense,andnobitchingaboutit
- either.:)*/
- __module_get(THIS_MODULE);
- return0;
- fail_added:
- idr_remove(&mtd_idr,i);
- fail_locked:
- mutex_unlock(&mtd_table_mutex);
- return1;
- }
其中用到的IDR机制如下:
(1)获得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中
- /**
- *del_mtd_device-unregisteranMTDdevice
- *@mtd:pointertoMTDdeviceinfostructure
- *
- *RemoveadevicefromthelistofMTDdevicespresentinthesystem,
- *andnotifyeachcurrentlyactiveMTDuserofitsdeparture.
- *Returnszeroonsuccessor1onfailure,whichcurrentlywillhappen
- *iftherequesteddevicedoesnotappeartobepresentinthelist.
- */
- //删除mtd设备函数。
- //从MTD设备的链表中移除该MTD设备信息,并通知系统中所有的MTDuser该MTD设备的移除。
- //返回0表示成功,返回1表示出错(该设备信息不存在设备链表中)
- intdel_mtd_device(structmtd_info*mtd)
- {
- intret;
- structmtd_notifier*not;//定义一个mtd_notifier指针
- mutex_lock(&mtd_table_mutex);
- if(idr_find(&mtd_idr,mtd->index)!=mtd){
- ret=-ENODEV;
- gotoout_error;
- }
- /*Noneedtogetarefcountonthemodulecontaining
- thenotifier,sinceweholdthemtd_table_mutex*/
- //遍历list链表,并使每个mtd_notifier执行remove函数,通知每个MTDuser该设备的移除
- list_for_each_entry(not,&mtd_notifiers,list)
- not->remove(mtd);
- if(mtd->usecount){
- printk(KERN_NOTICE"RemovingMTDdevice#%d(%s)withusecount%d\n",
- mtd->index,mtd->name,mtd->usecount);
- ret=-EBUSY;
- }else{
- device_unregister(&mtd->device_unregiste
ARM-Linux驱动MTD驱动分 相关文章:
- ARM-Linux驱动--MTD驱动分析(一)(11-20)
- ARM-Linux驱动--MTD驱动分析(三)(11-20)
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)