linux驱动 分析,ARM-Linux驱动--MTD驱动分析(三)

/*

*MTDmethodswhichsimplytranslatetheeffectiveaddressandpassthrough

*tothe_real_device.

*/

//读取某个分区的指定数据

staticintpart_read(structmtd_info*mtd,loff_tfrom,size_tlen,

size_t*retlen,u_char*buf)

{

structmtd_part*part=PART(mtd);

structmtd_ecc_statsstats;

intres;

stats=part->master->ecc_stats;

if(from>=mtd->size)

len=0;

elseif(from+len>mtd->size)

len=mtd->size-from;

res=part->master->read(part->master,from+part->offset,

len,retlen,buf);

if(unlikely(res)){

if(res==-EUCLEAN)

mtd->ecc_stats.corrected+=part->master->ecc_stats.corrected-stats.corrected;

if(res==-EBADMSG)

mtd->ecc_stats.failed+=part->master->ecc_stats.failed-stats.failed;

}

returnres;

}

staticintpart_point(structmtd_info*mtd,loff_tfrom,size_tlen,

size_t*retlen,void**virt,resource_size_t*phys)

{

structmtd_part*part=PART(mtd);

if(from>=mtd->size)

len=0;

elseif(from+len>mtd->size)

len=mtd->size-from;

returnpart->master->point(part->master,from+part->offset,

len,retlen,virt,phys);

}

staticvoidpart_unpoint(structmtd_info*mtd,loff_tfrom,size_tlen)

{

structmtd_part*part=PART(mtd);

part->master->unpoint(part->master,from+part->offset,len);

}

//获取空闲的内存驱动

staticunsignedlongpart_get_unmapped_area(structmtd_info*mtd,

unsignedlonglen,

unsignedlongoffset,

unsignedlongflags)

{

structmtd_part*part=PART(mtd);

offset+=part->offset;

returnpart->master->get_unmapped_area(part->master,len,offset,

flags);

}

staticintpart_read_oob(structmtd_info*mtd,loff_tfrom,

structmtd_oob_ops*ops)

{

structmtd_part*part=PART(mtd);

intres;

if(from>=mtd->size)

return-EINVAL;

if(ops->datbuf&&from+ops->len>mtd->size)

return-EINVAL;

res=part->master->read_oob(part->master,from+part->offset,ops);

if(unlikely(res)){

if(res==-EUCLEAN)

mtd->ecc_stats.corrected++;

if(res==-EBADMSG)

mtd->ecc_stats.failed++;

}

returnres;

}

staticintpart_read_user_prot_reg(structmtd_info*mtd,loff_tfrom,

size_tlen,size_t*retlen,u_char*buf)

{

structmtd_part*part=PART(mtd);

returnpart->master->read_user_prot_reg(part->master,from,

len,retlen,buf);

}

staticintpart_get_user_prot_info(structmtd_info*mtd,

structotp_info*buf,size_tlen)

{

structmtd_part*part=PART(mtd);

returnpart->master->get_user_prot_info(part->master,buf,len);

}

staticintpart_read_fact_prot_reg(structmtd_info*mtd,loff_tfrom,

size_tlen,size_t*retlen,u_char*buf)

{

structmtd_part*part=PART(mtd);

returnpart->master->read_fact_prot_reg(part->master,from,

len,retlen,buf);

}

staticintpart_get_fact_prot_info(structmtd_info*mtd,structotp_info*buf,

size_tlen)

{

structmtd_part*part=PART(mtd);

returnpart->master->get_fact_prot_info(part->master,buf,len);

}

//分区写函数

staticintpart_write(structmtd_info*mtd,loff_tto,size_tlen,

size_t*retlen,constu_char*buf)

{

structmtd_part*part=PART(mtd);

if(!(mtd->flags&MTD_WRITEABLE))

return-EROFS;

if(to>=mtd->size)

len=0;

elseif(to+len>mtd->size)

len=mtd->size-to;

returnpart->master->write(part->master,to+part->offset,

len,retlen,buf);

}

staticintpart_panic_write(structmtd_info*mtd,loff_tto,size_tlen,

size_t*retlen,constu_char*buf)

{

structmtd_part*part=PART(mtd);

if(!(mtd->flags&MTD_WRITEABLE))

return-EROFS;

if(to>=mtd->size)

len=0;

elseif(to+len>mtd->size)

len=mtd->size-to;

returnpart->master->panic_write(part->master,to+part->offset,

len,retlen,buf);

}

staticintpart_write_oob(structmtd_info*mtd,loff_tto,

structmtd_oob_ops*ops)

{

structmtd_part*part=PART(mtd);

if(!(mtd->flags&MTD_WRITEABLE))

return-EROFS;

if(to>=mtd->size)

return-EINVAL;

if(ops->datbuf&&to+ops->len>mtd->size)

return-EINVAL;

returnpart->master->write_oob(part->master,to+part->offset,ops);

}

staticintpart_write_user_prot_reg(structmtd_info*mtd,loff_tfrom,

size_tlen,size_t*retlen,u_char*buf)

{

structmtd_part*part=PART(mtd);

returnpart->master->write_user_prot_reg(part->master,from,

len,retlen,buf);

}

staticintpart_lock_user_prot_reg(structmtd_info*mtd,loff_tfrom,

size_tlen)

{

structmtd_part*part=PART(mtd);

returnpart->master->lock_user_prot_reg(part->master,from,len);

}

staticintpart_writev(structmtd_info*mtd,conststructkvec*vecs,

unsignedlongcount,loff_tto,size_t*retlen)

{

structmtd_part*part=PART(mtd);

if(!(mtd->flags&MTD_WRITEABLE))

return-EROFS;

returnpart->master->writev(part->master,vecs,count,

to+part->offset,retlen);

}

staticintpart_erase(structmtd_info*mtd,structerase_info*instr)

{

structmtd_part*part=PART(mtd);

intret;

if(!(mtd->flags&MTD_WRITEABLE))

return-EROFS;

if(instr->addr>=mtd->size)

return-EINVAL;

instr->addr+=part->offset;

ret=part->master->erase(part->master,instr);

if(ret){

if(instr->fail_addr!=MTD_FAIL_ADDR_UNKNOWN)

instr->fail_addr-=part->offset;

instr->addr-=part->offset;

}

returnret;

}

voidmtd_erase_callback(structerase_info*instr)

{

if(instr->mtd->erase==part_erase){

structmtd_part*part=PART(instr->mtd);

if(instr->fail_addr!=MTD_FAIL_ADDR_UNKNOWN)

instr->fail_addr-=part->offset;

instr->addr-=part->offset;

}

if(instr->callback)

instr->callback(instr);

}

EXPORT_SYMBOL_GPL(mtd_erase_callback);

staticintpart_lock(structmtd_info*mtd,loff_tofs,uint64_tlen)

{

structmtd_part*part=PART(mtd);

if((len+ofs)>mtd->size)

return-EINVAL;

returnpart->master->lock(part->master,ofs+part->offset,len);

}

staticintpart_unlock(structmtd_info*mtd,loff_tofs,uint64_tlen)

{

structmtd_part*part=PART(mtd);

if((len+ofs)>mtd->size)

return-EINVAL;

returnpart->master->unlock(part->master,ofs+part->offset,len);

}

//分区同步函数

staticvoidpart_sync(structmtd_info*mtd)

{

structmtd_part*part=PART(mtd);

part->master->sync(part->master);

}

//支持电源管理的功能函数

staticintpart_suspend(structmtd_info*mtd)

{

structmtd_part*part=PART(mtd);

returnpart->master->suspend(part->master);

}

staticvoidpart_resume(structmtd_info*mtd)

{

structmtd_part*part=PART(mtd);

part->master->resume(part->master);

}

staticintpart_block_isbad(structmtd_info*mtd,loff_tofs)

{

structmtd_part*part=PART(mtd);

if(ofs>=mtd->size)

return-EINVAL;

ofs+=part->offset;

returnpart->master->block_isbad(part->master,ofs);

}

//标记设备地址坏块

staticintpart_block_markbad(structmtd_info*mtd,loff_tofs)

{

structmtd_part*part=PART(mtd);

intres;

if(!(mtd->flags&MTD_WRITEABLE))

return-EROFS;

if(ofs>=mtd->size)

return-EINVAL;

ofs+=part->offset;

res=part->master->block_markbad(part->master,ofs);

if(!res)

mtd->ecc_stats.badblocks++;

returnres;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值