static ssize_t mtd_read_oob(struct cdev *cdev, void *buf, size_t count, loff_t _offset, ulong flags) { struct mtd_info *mtd = to_mtd(cdev); struct mtd_oob_ops ops; int ret; unsigned long offset = _offset; if (count < mtd->oobsize) return -EINVAL; ops.mode = MTD_OOB_RAW; ops.ooboffs = 0; ops.ooblen = mtd->oobsize; ops.oobbuf = buf; ops.datbuf = NULL; ops.len = mtd->oobsize; offset /= mtd->oobsize; ret = mtd->read_oob(mtd, offset * mtd->writesize, &ops); if (ret) return ret; return mtd->oobsize; }
static ssize_t mtdraw_read(struct cdev *cdev, void *buf, size_t count, loff_t _offset, ulong flags) { struct mtd_info *mtd = to_mtd(cdev); ssize_t retlen = 0, ret = 1, toread; ulong numpage; int skip; unsigned long offset = _offset; numpage = offset / (mtd->writesize + mtd->oobsize); skip = offset % (mtd->writesize + mtd->oobsize); while (ret > 0 && count > 0) { toread = min_t(int, count, mtd->writesize + mtd->oobsize - skip); ret = mtdraw_read_unaligned(mtd, buf, toread, skip, numpage++ * mtd->writesize); buf += ret; skip = 0; count -= ret; retlen += ret; } if (ret < 0) printf("err %zd\n", ret); else ret = retlen; return ret; }
static int mtdraw_erase(struct cdev *cdev, size_t count, loff_t _offset) { struct mtd_info *mtd = to_mtd(cdev); struct erase_info erase; unsigned long offset = _offset; int ret; offset = offset / (mtd->writesize + mtd->oobsize) * mtd->writesize; count = count / (mtd->writesize + mtd->oobsize) * mtd->writesize; memset(&erase, 0, sizeof(erase)); erase.mtd = mtd; erase.addr = offset; erase.len = mtd->erasesize; while (count > 0) { debug("erase %d %d\n", erase.addr, erase.len); ret = mtd_block_isbad(mtd, erase.addr); if (ret > 0) { printf("Skipping bad block at 0x%08x\n", erase.addr); } else { ret = mtd->erase(mtd, &erase); if (ret) return ret; } erase.addr += mtd->erasesize; count -= count > mtd->erasesize ? mtd->erasesize : count; } return 0; }
static ssize_t mtdraw_write(struct cdev *cdev, const void *buf, size_t count, loff_t _offset, ulong flags) { struct mtdraw *mtdraw = to_mtdraw(cdev); struct mtd_info *mtd = to_mtd(cdev); int bsz = mtd->writesize + mtd->oobsize; ulong numpage; size_t retlen = 0, tofill; unsigned long offset = _offset; int ret = 0; if (mtdraw->write_fill && mtdraw->write_ofs + mtdraw->write_fill != offset) return -EINVAL; if (mtdraw->write_fill == 0 && offset % bsz) return -EINVAL; if (mtdraw->write_fill) { tofill = min_t(size_t, count, bsz - mtdraw->write_fill); mtdraw_fillbuf(mtdraw, buf, tofill); offset += tofill; count -= tofill; retlen += tofill; } if (mtdraw->write_fill == bsz) { numpage = mtdraw->write_ofs / (mtd->writesize + mtd->oobsize); ret = mtdraw_blkwrite(mtd, mtdraw->writebuf, mtd->writesize * numpage); mtdraw->write_fill = 0; } numpage = offset / (mtd->writesize + mtd->oobsize); while (ret >= 0 && count >= bsz) { ret = mtdraw_blkwrite(mtd, buf + retlen, mtd->writesize * numpage++); count -= ret; retlen += ret; offset += ret; } if (ret >= 0 && count) { mtdraw->write_ofs = offset - mtdraw->write_fill; mtdraw_fillbuf(mtdraw, buf + retlen, count); retlen += count; } if (ret < 0) { printf("err %d\n", ret); return ret; } else { return retlen; } }