nand.c (3b35d4542c8537a9269f6372df531ced6c960084) | nand.c (a9262f551eba44d4d0f9e396d7124c059a93e204) |
---|---|
1/* 2 * Flash NAND memory emulation. Based on "16M x 8 Bit NAND Flash 3 * Memory" datasheet for the KM29U128AT / K9F2808U0A chips from 4 * Samsung Electronic. 5 * 6 * Copyright (c) 2006 Openedhand Ltd. 7 * Written by Andrzej Zaborowski <balrog@zabor.org> 8 * --- 652 unchanged lines hidden (view full) --- 661 662 if (!s->blk) { 663 mem_and(s->storage + PAGE_START(s->addr) + (s->addr & PAGE_MASK) + 664 s->offset, s->io, s->iolen); 665 } else if (s->mem_oob) { 666 sector = SECTOR(s->addr); 667 off = (s->addr & PAGE_MASK) + s->offset; 668 soff = SECTOR_OFFSET(s->addr); | 1/* 2 * Flash NAND memory emulation. Based on "16M x 8 Bit NAND Flash 3 * Memory" datasheet for the KM29U128AT / K9F2808U0A chips from 4 * Samsung Electronic. 5 * 6 * Copyright (c) 2006 Openedhand Ltd. 7 * Written by Andrzej Zaborowski <balrog@zabor.org> 8 * --- 652 unchanged lines hidden (view full) --- 661 662 if (!s->blk) { 663 mem_and(s->storage + PAGE_START(s->addr) + (s->addr & PAGE_MASK) + 664 s->offset, s->io, s->iolen); 665 } else if (s->mem_oob) { 666 sector = SECTOR(s->addr); 667 off = (s->addr & PAGE_MASK) + s->offset; 668 soff = SECTOR_OFFSET(s->addr); |
669 if (blk_pread(s->blk, sector << BDRV_SECTOR_BITS, iobuf, 670 PAGE_SECTORS << BDRV_SECTOR_BITS, 0) < 0) { | 669 if (blk_pread(s->blk, sector << BDRV_SECTOR_BITS, 670 PAGE_SECTORS << BDRV_SECTOR_BITS, iobuf, 0) < 0) { |
671 printf("%s: read error in sector %" PRIu64 "\n", __func__, sector); 672 return; 673 } 674 675 mem_and(iobuf + (soff | off), s->io, MIN(s->iolen, NAND_PAGE_SIZE - off)); 676 if (off + s->iolen > NAND_PAGE_SIZE) { 677 page = PAGE(s->addr); 678 mem_and(s->storage + (page << OOB_SHIFT), s->io + NAND_PAGE_SIZE - off, 679 MIN(OOB_SIZE, off + s->iolen - NAND_PAGE_SIZE)); 680 } 681 | 671 printf("%s: read error in sector %" PRIu64 "\n", __func__, sector); 672 return; 673 } 674 675 mem_and(iobuf + (soff | off), s->io, MIN(s->iolen, NAND_PAGE_SIZE - off)); 676 if (off + s->iolen > NAND_PAGE_SIZE) { 677 page = PAGE(s->addr); 678 mem_and(s->storage + (page << OOB_SHIFT), s->io + NAND_PAGE_SIZE - off, 679 MIN(OOB_SIZE, off + s->iolen - NAND_PAGE_SIZE)); 680 } 681 |
682 if (blk_pwrite(s->blk, sector << BDRV_SECTOR_BITS, iobuf, 683 PAGE_SECTORS << BDRV_SECTOR_BITS, 0) < 0) { | 682 if (blk_pwrite(s->blk, sector << BDRV_SECTOR_BITS, 683 PAGE_SECTORS << BDRV_SECTOR_BITS, iobuf, 0) < 0) { |
684 printf("%s: write error in sector %" PRIu64 "\n", __func__, sector); 685 } 686 } else { 687 off = PAGE_START(s->addr) + (s->addr & PAGE_MASK) + s->offset; 688 sector = off >> 9; 689 soff = off & 0x1ff; | 684 printf("%s: write error in sector %" PRIu64 "\n", __func__, sector); 685 } 686 } else { 687 off = PAGE_START(s->addr) + (s->addr & PAGE_MASK) + s->offset; 688 sector = off >> 9; 689 soff = off & 0x1ff; |
690 if (blk_pread(s->blk, sector << BDRV_SECTOR_BITS, iobuf, 691 (PAGE_SECTORS + 2) << BDRV_SECTOR_BITS, 0) < 0) { | 690 if (blk_pread(s->blk, sector << BDRV_SECTOR_BITS, 691 (PAGE_SECTORS + 2) << BDRV_SECTOR_BITS, iobuf, 0) < 0) { |
692 printf("%s: read error in sector %" PRIu64 "\n", __func__, sector); 693 return; 694 } 695 696 mem_and(iobuf + soff, s->io, s->iolen); 697 | 692 printf("%s: read error in sector %" PRIu64 "\n", __func__, sector); 693 return; 694 } 695 696 mem_and(iobuf + soff, s->io, s->iolen); 697 |
698 if (blk_pwrite(s->blk, sector << BDRV_SECTOR_BITS, iobuf, 699 (PAGE_SECTORS + 2) << BDRV_SECTOR_BITS, 0) < 0) { | 698 if (blk_pwrite(s->blk, sector << BDRV_SECTOR_BITS, 699 (PAGE_SECTORS + 2) << BDRV_SECTOR_BITS, iobuf, 0) < 0) { |
700 printf("%s: write error in sector %" PRIu64 "\n", __func__, sector); 701 } 702 } 703 s->offset = 0; 704} 705 706/* Erase a single block */ 707static void glue(nand_blk_erase_, NAND_PAGE_SIZE)(NANDFlashState *s) --- 10 unchanged lines hidden (view full) --- 718 memset(s->storage + PAGE_START(addr), 719 0xff, (NAND_PAGE_SIZE + OOB_SIZE) << s->erase_shift); 720 } else if (s->mem_oob) { 721 memset(s->storage + (PAGE(addr) << OOB_SHIFT), 722 0xff, OOB_SIZE << s->erase_shift); 723 i = SECTOR(addr); 724 page = SECTOR(addr + (1 << (ADDR_SHIFT + s->erase_shift))); 725 for (; i < page; i ++) | 700 printf("%s: write error in sector %" PRIu64 "\n", __func__, sector); 701 } 702 } 703 s->offset = 0; 704} 705 706/* Erase a single block */ 707static void glue(nand_blk_erase_, NAND_PAGE_SIZE)(NANDFlashState *s) --- 10 unchanged lines hidden (view full) --- 718 memset(s->storage + PAGE_START(addr), 719 0xff, (NAND_PAGE_SIZE + OOB_SIZE) << s->erase_shift); 720 } else if (s->mem_oob) { 721 memset(s->storage + (PAGE(addr) << OOB_SHIFT), 722 0xff, OOB_SIZE << s->erase_shift); 723 i = SECTOR(addr); 724 page = SECTOR(addr + (1 << (ADDR_SHIFT + s->erase_shift))); 725 for (; i < page; i ++) |
726 if (blk_pwrite(s->blk, i << BDRV_SECTOR_BITS, iobuf, 727 BDRV_SECTOR_SIZE, 0) < 0) { | 726 if (blk_pwrite(s->blk, i << BDRV_SECTOR_BITS, 727 BDRV_SECTOR_SIZE, iobuf, 0) < 0) { |
728 printf("%s: write error in sector %" PRIu64 "\n", __func__, i); 729 } 730 } else { 731 addr = PAGE_START(addr); 732 page = addr >> 9; | 728 printf("%s: write error in sector %" PRIu64 "\n", __func__, i); 729 } 730 } else { 731 addr = PAGE_START(addr); 732 page = addr >> 9; |
733 if (blk_pread(s->blk, page << BDRV_SECTOR_BITS, iobuf, 734 BDRV_SECTOR_SIZE, 0) < 0) { | 733 if (blk_pread(s->blk, page << BDRV_SECTOR_BITS, 734 BDRV_SECTOR_SIZE, iobuf, 0) < 0) { |
735 printf("%s: read error in sector %" PRIu64 "\n", __func__, page); 736 } 737 memset(iobuf + (addr & 0x1ff), 0xff, (~addr & 0x1ff) + 1); | 735 printf("%s: read error in sector %" PRIu64 "\n", __func__, page); 736 } 737 memset(iobuf + (addr & 0x1ff), 0xff, (~addr & 0x1ff) + 1); |
738 if (blk_pwrite(s->blk, page << BDRV_SECTOR_BITS, iobuf, 739 BDRV_SECTOR_SIZE, 0) < 0) { | 738 if (blk_pwrite(s->blk, page << BDRV_SECTOR_BITS, 739 BDRV_SECTOR_SIZE, iobuf, 0) < 0) { |
740 printf("%s: write error in sector %" PRIu64 "\n", __func__, page); 741 } 742 743 memset(iobuf, 0xff, 0x200); 744 i = (addr & ~0x1ff) + 0x200; 745 for (addr += ((NAND_PAGE_SIZE + OOB_SIZE) << s->erase_shift) - 0x200; 746 i < addr; i += 0x200) { | 740 printf("%s: write error in sector %" PRIu64 "\n", __func__, page); 741 } 742 743 memset(iobuf, 0xff, 0x200); 744 i = (addr & ~0x1ff) + 0x200; 745 for (addr += ((NAND_PAGE_SIZE + OOB_SIZE) << s->erase_shift) - 0x200; 746 i < addr; i += 0x200) { |
747 if (blk_pwrite(s->blk, i, iobuf, BDRV_SECTOR_SIZE, 0) < 0) { | 747 if (blk_pwrite(s->blk, i, BDRV_SECTOR_SIZE, iobuf, 0) < 0) { |
748 printf("%s: write error in sector %" PRIu64 "\n", 749 __func__, i >> 9); 750 } 751 } 752 753 page = i >> 9; | 748 printf("%s: write error in sector %" PRIu64 "\n", 749 __func__, i >> 9); 750 } 751 } 752 753 page = i >> 9; |
754 if (blk_pread(s->blk, page << BDRV_SECTOR_BITS, iobuf, 755 BDRV_SECTOR_SIZE, 0) < 0) { | 754 if (blk_pread(s->blk, page << BDRV_SECTOR_BITS, 755 BDRV_SECTOR_SIZE, iobuf, 0) < 0) { |
756 printf("%s: read error in sector %" PRIu64 "\n", __func__, page); 757 } 758 memset(iobuf, 0xff, ((addr - 1) & 0x1ff) + 1); | 756 printf("%s: read error in sector %" PRIu64 "\n", __func__, page); 757 } 758 memset(iobuf, 0xff, ((addr - 1) & 0x1ff) + 1); |
759 if (blk_pwrite(s->blk, page << BDRV_SECTOR_BITS, iobuf, 760 BDRV_SECTOR_SIZE, 0) < 0) { | 759 if (blk_pwrite(s->blk, page << BDRV_SECTOR_BITS, 760 BDRV_SECTOR_SIZE, iobuf, 0) < 0) { |
761 printf("%s: write error in sector %" PRIu64 "\n", __func__, page); 762 } 763 } 764} 765 766static void glue(nand_blk_load_, NAND_PAGE_SIZE)(NANDFlashState *s, 767 uint64_t addr, int offset) 768{ 769 if (PAGE(addr) >= s->pages) { 770 return; 771 } 772 773 if (s->blk) { 774 if (s->mem_oob) { | 761 printf("%s: write error in sector %" PRIu64 "\n", __func__, page); 762 } 763 } 764} 765 766static void glue(nand_blk_load_, NAND_PAGE_SIZE)(NANDFlashState *s, 767 uint64_t addr, int offset) 768{ 769 if (PAGE(addr) >= s->pages) { 770 return; 771 } 772 773 if (s->blk) { 774 if (s->mem_oob) { |
775 if (blk_pread(s->blk, SECTOR(addr) << BDRV_SECTOR_BITS, s->io, 776 PAGE_SECTORS << BDRV_SECTOR_BITS, 0) < 0) { | 775 if (blk_pread(s->blk, SECTOR(addr) << BDRV_SECTOR_BITS, 776 PAGE_SECTORS << BDRV_SECTOR_BITS, s->io, 0) < 0) { |
777 printf("%s: read error in sector %" PRIu64 "\n", 778 __func__, SECTOR(addr)); 779 } 780 memcpy(s->io + SECTOR_OFFSET(s->addr) + NAND_PAGE_SIZE, 781 s->storage + (PAGE(s->addr) << OOB_SHIFT), 782 OOB_SIZE); 783 s->ioaddr = s->io + SECTOR_OFFSET(s->addr) + offset; 784 } else { | 777 printf("%s: read error in sector %" PRIu64 "\n", 778 __func__, SECTOR(addr)); 779 } 780 memcpy(s->io + SECTOR_OFFSET(s->addr) + NAND_PAGE_SIZE, 781 s->storage + (PAGE(s->addr) << OOB_SHIFT), 782 OOB_SIZE); 783 s->ioaddr = s->io + SECTOR_OFFSET(s->addr) + offset; 784 } else { |
785 if (blk_pread(s->blk, PAGE_START(addr), s->io, 786 (PAGE_SECTORS + 2) << BDRV_SECTOR_BITS, 0) < 0) { | 785 if (blk_pread(s->blk, PAGE_START(addr), 786 (PAGE_SECTORS + 2) << BDRV_SECTOR_BITS, s->io, 0) 787 < 0) { |
787 printf("%s: read error in sector %" PRIu64 "\n", 788 __func__, PAGE_START(addr) >> 9); 789 } 790 s->ioaddr = s->io + (PAGE_START(addr) & 0x1ff) + offset; 791 } 792 } else { 793 memcpy(s->io, s->storage + PAGE_START(s->addr) + 794 offset, NAND_PAGE_SIZE + OOB_SIZE - offset); --- 20 unchanged lines hidden --- | 788 printf("%s: read error in sector %" PRIu64 "\n", 789 __func__, PAGE_START(addr) >> 9); 790 } 791 s->ioaddr = s->io + (PAGE_START(addr) & 0x1ff) + offset; 792 } 793 } else { 794 memcpy(s->io, s->storage + PAGE_START(s->addr) + 795 offset, NAND_PAGE_SIZE + OOB_SIZE - offset); --- 20 unchanged lines hidden --- |