diff --git a/drivers/mtd/nand/nand-bb.c b/drivers/mtd/nand/nand-bb.c index f387ef6..06b5824 100644 --- a/drivers/mtd/nand/nand-bb.c +++ b/drivers/mtd/nand/nand-bb.c @@ -25,22 +25,18 @@ #include #include #include -#include +#include #include #include #include struct nand_bb { - char cdevname[MAX_DRIVER_NAME]; - struct cdev *cdev_parent; char *name; int open; int needs_write; - struct mtd_info_user info; + struct mtd_info *mtd; - loff_t raw_size; - loff_t size; loff_t offset; unsigned long flags; void *writebuf; @@ -54,31 +50,28 @@ loff_t offset, ulong flags) { struct nand_bb *bb = cdev->priv; - struct cdev *parent = bb->cdev_parent; + size_t retlen; int ret, bytes = 0, now; debug("%s 0x%08llx %d\n", __func__, offset, count); - while(count) { - ret = cdev_ioctl(parent, MEMGETBADBLOCK, &bb->offset); - if (ret < 0) - return ret; - - if (ret) { + while (count) { + if (mtd_block_isbad(bb->mtd, offset)) { printf("skipping bad block at 0x%08llx\n", bb->offset); - bb->offset += bb->info.erasesize; + bb->offset += bb->mtd->erasesize; continue; } - now = min(count, (size_t)(bb->info.erasesize - - ((size_t)bb->offset % bb->info.erasesize))); - ret = cdev_read(parent, buf, now, bb->offset, 0); + now = min(count, (size_t)(bb->mtd->erasesize - + ((size_t)bb->offset % bb->mtd->erasesize))); + + ret = mtd_read(bb->mtd, bb->offset, now, &retlen, buf); if (ret < 0) return ret; - buf += now; - count -= now; - bb->offset += now; - bytes += now; + buf += retlen; + count -= retlen; + bb->offset += retlen; + bytes += retlen; }; return bytes; @@ -91,29 +84,25 @@ static int nand_bb_write_buf(struct nand_bb *bb, size_t count) { int ret, now; - struct cdev *parent = bb->cdev_parent; + size_t retlen; void *buf = bb->writebuf; loff_t cur_ofs = bb->offset & ~(BB_WRITEBUF_SIZE - 1); while (count) { - ret = cdev_ioctl(parent, MEMGETBADBLOCK, &cur_ofs); - if (ret < 0) - return ret; - - if (ret) { + if (mtd_block_isbad(bb->mtd, cur_ofs)) { debug("skipping bad block at 0x%08llx\n", cur_ofs); - bb->offset += bb->info.erasesize; - cur_ofs += bb->info.erasesize; + bb->offset += bb->mtd->erasesize; + cur_ofs += bb->mtd->erasesize; continue; } - now = min(count, (size_t)(bb->info.erasesize)); - ret = cdev_write(parent, buf, now, cur_ofs, 0); + now = min(count, (size_t)(bb->mtd->erasesize)); + ret = mtd_write(bb->mtd, cur_ofs, now, &retlen, buf); if (ret < 0) return ret; - buf += now; - count -= now; - cur_ofs += now; + buf += retlen; + count -= retlen; + cur_ofs += retlen; }; return 0; @@ -152,13 +141,17 @@ static int nand_bb_erase(struct cdev *cdev, size_t count, loff_t offset) { struct nand_bb *bb = cdev->priv; + struct erase_info erase = {}; if (offset != 0) { printf("can only erase from beginning of device\n"); return -EINVAL; } - return cdev_erase(bb->cdev_parent, bb->raw_size, 0); + erase.addr = 0; + erase.len = bb->mtd->size; + + return mtd_erase(bb->mtd, &erase); } #endif @@ -195,16 +188,12 @@ static int nand_bb_calc_size(struct nand_bb *bb) { loff_t pos = 0; - int ret; - while (pos < bb->raw_size) { - ret = cdev_ioctl(bb->cdev_parent, MEMGETBADBLOCK, &pos); - if (ret < 0) - return ret; - if (!ret) - bb->cdev.size += bb->info.erasesize; + while (pos < bb->mtd->size) { + if (!mtd_block_isbad(bb->mtd, pos)) + bb->cdev.size += bb->mtd->erasesize; - pos += bb->info.erasesize; + pos += bb->mtd->erasesize; } return 0; @@ -215,22 +204,18 @@ struct nand_bb *bb = cdev->priv; loff_t raw_pos = 0; uint32_t offset = __offset; - int ret; /* lseek only in readonly mode */ if (bb->flags & O_ACCMODE) return -ENOSYS; - while (raw_pos < bb->raw_size) { - off_t now = min(offset, bb->info.erasesize); + while (raw_pos < bb->mtd->size) { + off_t now = min(offset, bb->mtd->erasesize); - ret = cdev_ioctl(bb->cdev_parent, MEMGETBADBLOCK, &raw_pos); - if (ret < 0) - return ret; - if (!ret) { + if (mtd_block_isbad(bb->mtd, raw_pos)) { + raw_pos += bb->mtd->erasesize; + } else { offset -= now; raw_pos += now; - } else { - raw_pos += bb->info.erasesize; } if (!offset) { @@ -264,28 +249,23 @@ int dev_add_bb_dev(const char *path, const char *name) { struct nand_bb *bb; + struct cdev *parent; int ret = -ENOMEM; + parent = cdev_by_name(path); + if (!parent) + return -ENODEV; + + if (!parent->mtd) + return -EINVAL; + bb = xzalloc(sizeof(*bb)); + bb->mtd = parent->mtd; - bb->cdev_parent = cdev_open(path, O_RDWR); - if (!bb->cdev_parent) - goto out1; - - if (name) { - strcpy(bb->cdevname, name); - } else { - strcpy(bb->cdevname, path); - strcat(bb->cdevname, ".bb"); - } - - bb->cdev.name = bb->cdevname; - - bb->raw_size = bb->cdev_parent->size; - - ret = cdev_ioctl(bb->cdev_parent, MEMGETINFO, &bb->info); - if (ret) - goto out4; + if (name) + bb->cdev.name = xstrdup(name); + else + bb->cdev.name = asprintf("%s.bb", path);; nand_bb_calc_size(bb); bb->cdev.ops = &nand_bb_ops; @@ -300,8 +280,6 @@ return 0; out4: - cdev_close(bb->cdev_parent); -out1: free(bb); return ret; } @@ -313,8 +291,8 @@ list_for_each_entry(bb, &bb_list, list) { if (!strcmp(bb->cdev.name, name)) { devfs_remove(&bb->cdev); - cdev_close(bb->cdev_parent); list_del_init(&bb->list); + free(bb->name); free(bb); return 0; }