diff options
Diffstat (limited to 'drivers/mtd/nftlmount.c')
-rw-r--r-- | drivers/mtd/nftlmount.c | 91 |
1 files changed, 57 insertions, 34 deletions
diff --git a/drivers/mtd/nftlmount.c b/drivers/mtd/nftlmount.c index 3b104ebb219a..067262ee8df0 100644 --- a/drivers/mtd/nftlmount.c +++ b/drivers/mtd/nftlmount.c | |||
@@ -33,6 +33,11 @@ | |||
33 | 33 | ||
34 | char nftlmountrev[]="$Revision: 1.41 $"; | 34 | char nftlmountrev[]="$Revision: 1.41 $"; |
35 | 35 | ||
36 | extern int nftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len, | ||
37 | size_t *retlen, uint8_t *buf); | ||
38 | extern int nftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len, | ||
39 | size_t *retlen, uint8_t *buf); | ||
40 | |||
36 | /* find_boot_record: Find the NFTL Media Header and its Spare copy which contains the | 41 | /* find_boot_record: Find the NFTL Media Header and its Spare copy which contains the |
37 | * various device information of the NFTL partition and Bad Unit Table. Update | 42 | * various device information of the NFTL partition and Bad Unit Table. Update |
38 | * the ReplUnitTable[] table accroding to the Bad Unit Table. ReplUnitTable[] | 43 | * the ReplUnitTable[] table accroding to the Bad Unit Table. ReplUnitTable[] |
@@ -45,6 +50,7 @@ static int find_boot_record(struct NFTLrecord *nftl) | |||
45 | size_t retlen; | 50 | size_t retlen; |
46 | u8 buf[SECTORSIZE]; | 51 | u8 buf[SECTORSIZE]; |
47 | struct NFTLMediaHeader *mh = &nftl->MediaHdr; | 52 | struct NFTLMediaHeader *mh = &nftl->MediaHdr; |
53 | struct mtd_info *mtd = nftl->mbd.mtd; | ||
48 | unsigned int i; | 54 | unsigned int i; |
49 | 55 | ||
50 | /* Assume logical EraseSize == physical erasesize for starting the scan. | 56 | /* Assume logical EraseSize == physical erasesize for starting the scan. |
@@ -65,7 +71,8 @@ static int find_boot_record(struct NFTLrecord *nftl) | |||
65 | 71 | ||
66 | /* Check for ANAND header first. Then can whinge if it's found but later | 72 | /* Check for ANAND header first. Then can whinge if it's found but later |
67 | checks fail */ | 73 | checks fail */ |
68 | ret = MTD_READ(nftl->mbd.mtd, block * nftl->EraseSize, SECTORSIZE, &retlen, buf); | 74 | ret = mtd->read(mtd, block * nftl->EraseSize, SECTORSIZE, |
75 | &retlen, buf); | ||
69 | /* We ignore ret in case the ECC of the MediaHeader is invalid | 76 | /* We ignore ret in case the ECC of the MediaHeader is invalid |
70 | (which is apparently acceptable) */ | 77 | (which is apparently acceptable) */ |
71 | if (retlen != SECTORSIZE) { | 78 | if (retlen != SECTORSIZE) { |
@@ -90,8 +97,9 @@ static int find_boot_record(struct NFTLrecord *nftl) | |||
90 | } | 97 | } |
91 | 98 | ||
92 | /* To be safer with BIOS, also use erase mark as discriminant */ | 99 | /* To be safer with BIOS, also use erase mark as discriminant */ |
93 | if ((ret = MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, | 100 | if ((ret = nftl_read_oob(mtd, block * nftl->EraseSize + |
94 | 8, &retlen, (char *)&h1) < 0)) { | 101 | SECTORSIZE + 8, 8, &retlen, |
102 | (char *)&h1) < 0)) { | ||
95 | printk(KERN_WARNING "ANAND header found at 0x%x in mtd%d, but OOB data read failed (err %d)\n", | 103 | printk(KERN_WARNING "ANAND header found at 0x%x in mtd%d, but OOB data read failed (err %d)\n", |
96 | block * nftl->EraseSize, nftl->mbd.mtd->index, ret); | 104 | block * nftl->EraseSize, nftl->mbd.mtd->index, ret); |
97 | continue; | 105 | continue; |
@@ -109,8 +117,8 @@ static int find_boot_record(struct NFTLrecord *nftl) | |||
109 | } | 117 | } |
110 | 118 | ||
111 | /* Finally reread to check ECC */ | 119 | /* Finally reread to check ECC */ |
112 | if ((ret = MTD_READECC(nftl->mbd.mtd, block * nftl->EraseSize, SECTORSIZE, | 120 | if ((ret = mtd->read(mtd, block * nftl->EraseSize, SECTORSIZE, |
113 | &retlen, buf, (char *)&oob, NULL) < 0)) { | 121 | &retlen, buf) < 0)) { |
114 | printk(KERN_NOTICE "ANAND header found at 0x%x in mtd%d, but ECC read failed (err %d)\n", | 122 | printk(KERN_NOTICE "ANAND header found at 0x%x in mtd%d, but ECC read failed (err %d)\n", |
115 | block * nftl->EraseSize, nftl->mbd.mtd->index, ret); | 123 | block * nftl->EraseSize, nftl->mbd.mtd->index, ret); |
116 | continue; | 124 | continue; |
@@ -228,9 +236,9 @@ device is already correct. | |||
228 | The new DiskOnChip driver already scanned the bad block table. Just query it. | 236 | The new DiskOnChip driver already scanned the bad block table. Just query it. |
229 | if ((i & (SECTORSIZE - 1)) == 0) { | 237 | if ((i & (SECTORSIZE - 1)) == 0) { |
230 | /* read one sector for every SECTORSIZE of blocks */ | 238 | /* read one sector for every SECTORSIZE of blocks */ |
231 | if ((ret = MTD_READECC(nftl->mbd.mtd, block * nftl->EraseSize + | 239 | if ((ret = mtd->read(nftl->mbd.mtd, block * nftl->EraseSize + |
232 | i + SECTORSIZE, SECTORSIZE, &retlen, buf, | 240 | i + SECTORSIZE, SECTORSIZE, &retlen, |
233 | (char *)&oob, NULL)) < 0) { | 241 | buf)) < 0) { |
234 | printk(KERN_NOTICE "Read of bad sector table failed (err %d)\n", | 242 | printk(KERN_NOTICE "Read of bad sector table failed (err %d)\n", |
235 | ret); | 243 | ret); |
236 | kfree(nftl->ReplUnitTable); | 244 | kfree(nftl->ReplUnitTable); |
@@ -268,18 +276,22 @@ static int memcmpb(void *a, int c, int n) | |||
268 | static int check_free_sectors(struct NFTLrecord *nftl, unsigned int address, int len, | 276 | static int check_free_sectors(struct NFTLrecord *nftl, unsigned int address, int len, |
269 | int check_oob) | 277 | int check_oob) |
270 | { | 278 | { |
271 | int i; | ||
272 | size_t retlen; | ||
273 | u8 buf[SECTORSIZE + nftl->mbd.mtd->oobsize]; | 279 | u8 buf[SECTORSIZE + nftl->mbd.mtd->oobsize]; |
280 | struct mtd_info *mtd = nftl->mbd.mtd; | ||
281 | size_t retlen; | ||
282 | int i; | ||
274 | 283 | ||
275 | for (i = 0; i < len; i += SECTORSIZE) { | 284 | for (i = 0; i < len; i += SECTORSIZE) { |
276 | if (MTD_READECC(nftl->mbd.mtd, address, SECTORSIZE, &retlen, buf, &buf[SECTORSIZE], &nftl->oobinfo) < 0) | 285 | if (mtd->read(mtd, address, SECTORSIZE, &retlen, buf)) |
277 | return -1; | 286 | return -1; |
278 | if (memcmpb(buf, 0xff, SECTORSIZE) != 0) | 287 | if (memcmpb(buf, 0xff, SECTORSIZE) != 0) |
279 | return -1; | 288 | return -1; |
280 | 289 | ||
281 | if (check_oob) { | 290 | if (check_oob) { |
282 | if (memcmpb(buf + SECTORSIZE, 0xff, nftl->mbd.mtd->oobsize) != 0) | 291 | if(nftl_read_oob(mtd, address, mtd->oobsize, |
292 | &retlen, &buf[SECTORSIZE]) < 0) | ||
293 | return -1; | ||
294 | if (memcmpb(buf + SECTORSIZE, 0xff, mtd->oobsize) != 0) | ||
283 | return -1; | 295 | return -1; |
284 | } | 296 | } |
285 | address += SECTORSIZE; | 297 | address += SECTORSIZE; |
@@ -301,10 +313,11 @@ int NFTL_formatblock(struct NFTLrecord *nftl, int block) | |||
301 | unsigned int nb_erases, erase_mark; | 313 | unsigned int nb_erases, erase_mark; |
302 | struct nftl_uci1 uci; | 314 | struct nftl_uci1 uci; |
303 | struct erase_info *instr = &nftl->instr; | 315 | struct erase_info *instr = &nftl->instr; |
316 | struct mtd_info *mtd = nftl->mbd.mtd; | ||
304 | 317 | ||
305 | /* Read the Unit Control Information #1 for Wear-Leveling */ | 318 | /* Read the Unit Control Information #1 for Wear-Leveling */ |
306 | if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, | 319 | if (nftl_read_oob(mtd, block * nftl->EraseSize + SECTORSIZE + 8, |
307 | 8, &retlen, (char *)&uci) < 0) | 320 | 8, &retlen, (char *)&uci) < 0) |
308 | goto default_uci1; | 321 | goto default_uci1; |
309 | 322 | ||
310 | erase_mark = le16_to_cpu ((uci.EraseMark | uci.EraseMark1)); | 323 | erase_mark = le16_to_cpu ((uci.EraseMark | uci.EraseMark1)); |
@@ -321,7 +334,7 @@ int NFTL_formatblock(struct NFTLrecord *nftl, int block) | |||
321 | instr->mtd = nftl->mbd.mtd; | 334 | instr->mtd = nftl->mbd.mtd; |
322 | instr->addr = block * nftl->EraseSize; | 335 | instr->addr = block * nftl->EraseSize; |
323 | instr->len = nftl->EraseSize; | 336 | instr->len = nftl->EraseSize; |
324 | MTD_ERASE(nftl->mbd.mtd, instr); | 337 | mtd->erase(mtd, instr); |
325 | 338 | ||
326 | if (instr->state == MTD_ERASE_FAILED) { | 339 | if (instr->state == MTD_ERASE_FAILED) { |
327 | printk("Error while formatting block %d\n", block); | 340 | printk("Error while formatting block %d\n", block); |
@@ -343,8 +356,8 @@ int NFTL_formatblock(struct NFTLrecord *nftl, int block) | |||
343 | goto fail; | 356 | goto fail; |
344 | 357 | ||
345 | uci.WearInfo = le32_to_cpu(nb_erases); | 358 | uci.WearInfo = le32_to_cpu(nb_erases); |
346 | if (MTD_WRITEOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8, | 359 | if (nftl_write_oob(mtd, block * nftl->EraseSize + SECTORSIZE + |
347 | &retlen, (char *)&uci) < 0) | 360 | 8, 8, &retlen, (char *)&uci) < 0) |
348 | goto fail; | 361 | goto fail; |
349 | return 0; | 362 | return 0; |
350 | fail: | 363 | fail: |
@@ -365,6 +378,7 @@ fail: | |||
365 | * case. */ | 378 | * case. */ |
366 | static void check_sectors_in_chain(struct NFTLrecord *nftl, unsigned int first_block) | 379 | static void check_sectors_in_chain(struct NFTLrecord *nftl, unsigned int first_block) |
367 | { | 380 | { |
381 | struct mtd_info *mtd = nftl->mbd.mtd; | ||
368 | unsigned int block, i, status; | 382 | unsigned int block, i, status; |
369 | struct nftl_bci bci; | 383 | struct nftl_bci bci; |
370 | int sectors_per_block; | 384 | int sectors_per_block; |
@@ -374,8 +388,9 @@ static void check_sectors_in_chain(struct NFTLrecord *nftl, unsigned int first_b | |||
374 | block = first_block; | 388 | block = first_block; |
375 | for (;;) { | 389 | for (;;) { |
376 | for (i = 0; i < sectors_per_block; i++) { | 390 | for (i = 0; i < sectors_per_block; i++) { |
377 | if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + i * SECTORSIZE, | 391 | if (nftl_read_oob(mtd, |
378 | 8, &retlen, (char *)&bci) < 0) | 392 | block * nftl->EraseSize + i * SECTORSIZE, |
393 | 8, &retlen, (char *)&bci) < 0) | ||
379 | status = SECTOR_IGNORE; | 394 | status = SECTOR_IGNORE; |
380 | else | 395 | else |
381 | status = bci.Status | bci.Status1; | 396 | status = bci.Status | bci.Status1; |
@@ -394,9 +409,10 @@ static void check_sectors_in_chain(struct NFTLrecord *nftl, unsigned int first_b | |||
394 | /* sector not free actually : mark it as SECTOR_IGNORE */ | 409 | /* sector not free actually : mark it as SECTOR_IGNORE */ |
395 | bci.Status = SECTOR_IGNORE; | 410 | bci.Status = SECTOR_IGNORE; |
396 | bci.Status1 = SECTOR_IGNORE; | 411 | bci.Status1 = SECTOR_IGNORE; |
397 | MTD_WRITEOOB(nftl->mbd.mtd, | 412 | nftl_write_oob(mtd, block * |
398 | block * nftl->EraseSize + i * SECTORSIZE, | 413 | nftl->EraseSize + |
399 | 8, &retlen, (char *)&bci); | 414 | i * SECTORSIZE, 8, |
415 | &retlen, (char *)&bci); | ||
400 | } | 416 | } |
401 | break; | 417 | break; |
402 | default: | 418 | default: |
@@ -481,13 +497,14 @@ static void format_chain(struct NFTLrecord *nftl, unsigned int first_block) | |||
481 | * 1. */ | 497 | * 1. */ |
482 | static int check_and_mark_free_block(struct NFTLrecord *nftl, int block) | 498 | static int check_and_mark_free_block(struct NFTLrecord *nftl, int block) |
483 | { | 499 | { |
500 | struct mtd_info *mtd = nftl->mbd.mtd; | ||
484 | struct nftl_uci1 h1; | 501 | struct nftl_uci1 h1; |
485 | unsigned int erase_mark; | 502 | unsigned int erase_mark; |
486 | size_t retlen; | 503 | size_t retlen; |
487 | 504 | ||
488 | /* check erase mark. */ | 505 | /* check erase mark. */ |
489 | if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8, | 506 | if (nftl_read_oob(mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8, |
490 | &retlen, (char *)&h1) < 0) | 507 | &retlen, (char *)&h1) < 0) |
491 | return -1; | 508 | return -1; |
492 | 509 | ||
493 | erase_mark = le16_to_cpu ((h1.EraseMark | h1.EraseMark1)); | 510 | erase_mark = le16_to_cpu ((h1.EraseMark | h1.EraseMark1)); |
@@ -501,8 +518,9 @@ static int check_and_mark_free_block(struct NFTLrecord *nftl, int block) | |||
501 | h1.EraseMark = cpu_to_le16(ERASE_MARK); | 518 | h1.EraseMark = cpu_to_le16(ERASE_MARK); |
502 | h1.EraseMark1 = cpu_to_le16(ERASE_MARK); | 519 | h1.EraseMark1 = cpu_to_le16(ERASE_MARK); |
503 | h1.WearInfo = cpu_to_le32(0); | 520 | h1.WearInfo = cpu_to_le32(0); |
504 | if (MTD_WRITEOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8, | 521 | if (nftl_write_oob(mtd, |
505 | &retlen, (char *)&h1) < 0) | 522 | block * nftl->EraseSize + SECTORSIZE + 8, 8, |
523 | &retlen, (char *)&h1) < 0) | ||
506 | return -1; | 524 | return -1; |
507 | } else { | 525 | } else { |
508 | #if 0 | 526 | #if 0 |
@@ -513,8 +531,8 @@ static int check_and_mark_free_block(struct NFTLrecord *nftl, int block) | |||
513 | SECTORSIZE, 0) != 0) | 531 | SECTORSIZE, 0) != 0) |
514 | return -1; | 532 | return -1; |
515 | 533 | ||
516 | if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + i, | 534 | if (nftl_read_oob(mtd, block * nftl->EraseSize + i, |
517 | 16, &retlen, buf) < 0) | 535 | 16, &retlen, buf) < 0) |
518 | return -1; | 536 | return -1; |
519 | if (i == SECTORSIZE) { | 537 | if (i == SECTORSIZE) { |
520 | /* skip erase mark */ | 538 | /* skip erase mark */ |
@@ -540,11 +558,12 @@ static int check_and_mark_free_block(struct NFTLrecord *nftl, int block) | |||
540 | */ | 558 | */ |
541 | static int get_fold_mark(struct NFTLrecord *nftl, unsigned int block) | 559 | static int get_fold_mark(struct NFTLrecord *nftl, unsigned int block) |
542 | { | 560 | { |
561 | struct mtd_info *mtd = nftl->mbd.mtd; | ||
543 | struct nftl_uci2 uci; | 562 | struct nftl_uci2 uci; |
544 | size_t retlen; | 563 | size_t retlen; |
545 | 564 | ||
546 | if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + 2 * SECTORSIZE + 8, | 565 | if (nftl_read_oob(mtd, block * nftl->EraseSize + 2 * SECTORSIZE + 8, |
547 | 8, &retlen, (char *)&uci) < 0) | 566 | 8, &retlen, (char *)&uci) < 0) |
548 | return 0; | 567 | return 0; |
549 | 568 | ||
550 | return le16_to_cpu((uci.FoldMark | uci.FoldMark1)); | 569 | return le16_to_cpu((uci.FoldMark | uci.FoldMark1)); |
@@ -558,6 +577,7 @@ int NFTL_mount(struct NFTLrecord *s) | |||
558 | int chain_length, do_format_chain; | 577 | int chain_length, do_format_chain; |
559 | struct nftl_uci0 h0; | 578 | struct nftl_uci0 h0; |
560 | struct nftl_uci1 h1; | 579 | struct nftl_uci1 h1; |
580 | struct mtd_info *mtd = s->mbd.mtd; | ||
561 | size_t retlen; | 581 | size_t retlen; |
562 | 582 | ||
563 | /* search for NFTL MediaHeader and Spare NFTL Media Header */ | 583 | /* search for NFTL MediaHeader and Spare NFTL Media Header */ |
@@ -582,10 +602,13 @@ int NFTL_mount(struct NFTLrecord *s) | |||
582 | 602 | ||
583 | for (;;) { | 603 | for (;;) { |
584 | /* read the block header. If error, we format the chain */ | 604 | /* read the block header. If error, we format the chain */ |
585 | if (MTD_READOOB(s->mbd.mtd, block * s->EraseSize + 8, 8, | 605 | if (nftl_read_oob(mtd, |
586 | &retlen, (char *)&h0) < 0 || | 606 | block * s->EraseSize + 8, 8, |
587 | MTD_READOOB(s->mbd.mtd, block * s->EraseSize + SECTORSIZE + 8, 8, | 607 | &retlen, (char *)&h0) < 0 || |
588 | &retlen, (char *)&h1) < 0) { | 608 | nftl_read_oob(mtd, |
609 | block * s->EraseSize + | ||
610 | SECTORSIZE + 8, 8, | ||
611 | &retlen, (char *)&h1) < 0) { | ||
589 | s->ReplUnitTable[block] = BLOCK_NIL; | 612 | s->ReplUnitTable[block] = BLOCK_NIL; |
590 | do_format_chain = 1; | 613 | do_format_chain = 1; |
591 | break; | 614 | break; |