/*
*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;
}