Mercurial > nand-ecoscentric
changeset 2994:3d3b0d53c2e5
NAND: application interface v2: functions take partition-relative addresses.
| author | Ross Younger <wry@ecoscentric.com> |
|---|---|
| date | Thu, 19 Nov 2009 15:50:03 +0000 |
| parents | 56ce19492892 |
| children | 59abe88f0b07 |
| files | packages/io/nand/current/ChangeLog packages/io/nand/current/cdl/nand.cdl packages/io/nand/current/doc/nand.sgml packages/io/nand/current/include/nand.h packages/io/nand/current/src/nand.c packages/io/nand/current/src/nand_bbt.c packages/io/nand/current/src/nand_bbt.h packages/io/nand/current/tests/readlimits.c packages/io/nand/current/tests/readwrite.c packages/io/nand/current/tests/rwbenchmark.c packages/io/nand/current/utils/erasenand.c |
| diffstat | 11 files changed, 195 insertions(+), 117 deletions(-) [+] |
line wrap: on
line diff
--- a/packages/io/nand/current/ChangeLog +++ b/packages/io/nand/current/ChangeLog @@ -1,3 +1,17 @@ +2009-11-19 Ross Younger <wry@eCosCentric.com> + + Significant interface change. + * nand.h: Application-facing functions now take partition-relative + addresses, not device-relative addresses. + Rename functions cyg_nand_* -> cyg_nandp_* to reflect this (change the + interface, change the name). + Create helper macros CYG_NAND_PARTITION_N{BLOCKS,PAGES}. + Rename NAND_* macros to CYG_NAND_*. + * tests, utils: Update to new semantics. + * nand.cdl: Declare CYGSEM_IO_NAND_APPINTERFACE_VERSION + - calculated, 2 - and add a tripwire to ensure YAFFS is updated. + * docs/nand.sgml: Updated to suit. + 2009-11-17 Ross Younger <wry@eCosCentric.com> * nand.c: Cosmetic messages fix
--- a/packages/io/nand/current/cdl/nand.cdl +++ b/packages/io/nand/current/cdl/nand.cdl @@ -46,6 +46,7 @@ # # ==================================================================== + cdl_package CYGPKG_IO_NAND { display "NAND Flash access library" parent CYGPKG_IO @@ -63,16 +64,32 @@ cdl_package CYGPKG_IO_NAND { requires CYGINT_ISO_STRING_MEMFUNCS requires CYGPKG_LIBC_STDLIB + # If YAFFS is loaded, ensure that is knows how to drive us. + requires ( CYGPKG_FS_YAFFS implies CYGSEM_FS_YAFFS_NAND_APPINTERFACE > 1) + compile nand.c nand_bbt.c nand_oob.c util.c compile nand_ecc_mtd.c compile nand_ecc_mtd_fast.c compile -library=libextras.a nandinit.cxx + cdl_option CYGSEM_IO_NAND_APPINTERFACE_VERSION { + display "NAND application interface version" + flavor data + calculated 2 + description "The current version of the application + interface provided by + the NAND layer. As the NAND device interface evolves, this + version number will be incremented; applications may require + that the layer provide a certain level in order + to function correctly." + } + cdl_option CYGSEM_IO_NAND_INTERFACE_VERSION { display "NAND device interface version" flavor data calculated 2 - description "The current compatibility level provided by + description "The current version of the device interface + provided by the NAND layer. As the NAND device interface evolves, this version number will be incremented; devices may require that the infrastructure provide a certain level in order
--- a/packages/io/nand/current/doc/nand.sgml +++ b/packages/io/nand/current/doc/nand.sgml @@ -332,13 +332,13 @@ size_t chipsize_log; // log2 of total ch ... }; -#define NAND_BYTES_PER_PAGE(dev) (1<<(dev)->page_bits) -#define NAND_SPARE_PER_PAGE(dev) ((dev)->spare_per_page) -#define NAND_PAGES_PER_BLOCK(dev) (1<<(dev)->block_page_bits) -#define NAND_BLOCKCOUNT(dev) (1<<(dev)->blockcount_bits) -#define NAND_PAGECOUNT(dev) (NAND_BLOCKCOUNT(dev) * NAND_PAGES_PER_BLOCK(dev)) -#define NAND_CHIPSIZE(dev) (1<<(dev)->chipsize_log) -#define NAND_APPSPARE_PER_PAGE(dev) ((dev)->oob->app_size) +#define CYG_NAND_BYTES_PER_PAGE(dev) (1<<(dev)->page_bits) +#define CYG_NAND_SPARE_PER_PAGE(dev) ((dev)->spare_per_page) +#define CYG_NAND_PAGES_PER_BLOCK(dev) (1<<(dev)->block_page_bits) +#define CYG_NAND_BLOCKCOUNT(dev) (1<<(dev)->blockcount_bits) +#define CYG_NAND_PAGECOUNT(dev) (NAND_BLOCKCOUNT(dev) * NAND_PAGES_PER_BLOCK(dev)) +#define CYG_NAND_CHIPSIZE(dev) (1<<(dev)->chipsize_log) +#define CYG_NAND_APPSPARE_PER_PAGE(dev) ((dev)->oob->app_size) </programlisting> </para> @@ -399,7 +399,7 @@ associated with it. These are used by t page's ECC; whatever is left over may be used by the application for whatever purposes may suit it.</para> -<para>Every page has <function>NAND_APPSPARE_PER_PAGE(dev)</function> +<para>Every page has <function>CYG_NAND_APPSPARE_PER_PAGE(dev)</function> bytes of spare area available to the application. (This amount is implicit from the driver configuration and cannot change during the lifetime of a device.) </para> @@ -430,10 +430,13 @@ are as follows:</para> <glossentry><glossterm><parameter>ctx</parameter></glossterm><glossdef><para>The partition that data is to be read from.</para></glossdef></glossentry> <glossentry><glossterm><parameter>page</parameter></glossterm><glossdef><para> -The page to be read, <emphasis>numbered from the start of the device, not -the partition</emphasis>. As a double-check, the library will refuse the +The page to be read, <emphasis>numbered from the start of the partition. +</emphasis>. As a double-check, the library will refuse the operation with <constant>-ENOENT</constant> if this address is not within -partition <parameter>ctx</parameter>. </para></glossdef></glossentry> +partition <parameter>ctx</parameter>. + <note><para>This was changed in application interface v2; earlier page + and block addresses were device-relative.</para></note> +</para></glossdef></glossentry> <glossentry><glossterm><parameter>dest</parameter></glossterm><glossdef><para> Where to put the data. May be NULL, in which case the page data is not read.</para></glossdef></glossentry> @@ -446,7 +449,7 @@ Where to store the application data read be NULL if spare data is not required.</para></glossdef></glossentry> <glossentry><glossterm><parameter>spare_size</parameter></glossterm><glossdef><para> The maximum number of bytes to read from the spare area. This will -not be more than <function>NAND_APPSPARE_PER_PAGE(dev)</function> +not be more than <function>CYG_NAND_APPSPARE_PER_PAGE(dev)</function> bytes.</para></glossdef></glossentry> </glosslist> @@ -474,7 +477,7 @@ and stored automatically. Parameters ar partition that data is to be written to.</para></glossdef></glossentry> <glossentry><glossterm><parameter>page</parameter></glossterm><glossdef><para> The page to be written, <emphasis>numbered from the start of -the device, not the partition</emphasis>. As a double-check, the +the partition</emphasis>. As a double-check, the library will refuse the operation with <constant>-ENOENT</constant> if this address is not within partition <parameter>ctx</parameter>. </para></glossdef></glossentry> @@ -490,7 +493,7 @@ be packed around the ECC as necessary. A data is not required.</para></glossdef></glossentry> <glossentry><glossterm><parameter>spare_size</parameter></glossterm><glossdef><para> The number of bytes to write to the spare area. This should not be -larger than <function>NAND_APPSPARE_PER_PAGE(dev)</function>; if it is, +larger than <function>CYG_NAND_APPSPARE_PER_PAGE(dev)</function>; if it is, only that many bytes will be stored.</para></glossdef></glossentry> </glosslist> @@ -511,7 +514,7 @@ it wishes to keep from the rest of the e partition that data is to be erased from.</para></glossdef></glossentry> <glossentry><glossterm><parameter>blk</parameter></glossterm><glossdef><para> The block to be erased, <emphasis>numbered from the start of -the device, not the partition</emphasis>. As a double-check, the +the partition</emphasis>. As a double-check, the library will refuse the operation with <constant>-ENOENT</constant> if this address is not within partition <parameter>ctx</parameter>. </para></glossdef></glossentry> @@ -570,7 +573,9 @@ applications.</para> as bad. This most commonly happens when a write operation fails (see <xref linkend="nand-app-writing"> above). To do this, call <function>cyg_nand_bbt_markbad</function>; the return is 0 for success, -or a negative eCos error code.</para> +or a negative eCos error code. <emphasis>As with other calls, blocks +are numbered from 0 at the start of the partition, and internally +translated for the device as appropriate.</emphasis></para> <para>Both of these calls may foreseeably return <constant>-ENOENT</constant> if the given block address was not valid, @@ -1259,9 +1264,13 @@ and they will be built and placed into <glossentry><glossterm>erasenand.c</glossterm><glossdef><para> Loops over all the blocks of a partition, erasing all the blocks which are not marked as bad. The device and partition to erase are set by #define. -<note><para>This will not erase the Bad Block Table. This is because +<note><para>This will not normally erase the Bad Block Table. This is because the BBT reports its own blocks as "Reserved" when queried via -<function>cyg_nand_bbt_query</function>. </para></note> +<function>cyg_nand_bbt_query</function>, which makes them inaccessible +to applications. However, if +<constant>CYGSEM_IO_NAND_USE_BBT</constant> is turned off, then any BBT +present will not be detected and hence will be erased. +</para></note> </para></glossdef></glossentry> <glossentry><glossterm>erase_bbt_dangerous.c</glossterm><glossdef><para> Erases the NAND blocks comprising the primary and mirror bad-block tables of a device. @@ -1269,8 +1278,10 @@ The device to erase is set by #define. (The tables are detected by the library in the usual way. If none are present, the library will scan the device for factory-bad blocks to create such a table, then this code will immediately erase it.) -<emphasis>It is particularly dangerous to run this code on a production -device, as it may not be possible to later reconstruct the list of factory-bad blocks.</emphasis> +<warning><para>It is particularly dangerous to run this utility +on a production device, as it is generally not possible to later +reconstruct the list of factory-bad blocks. It is intended only as an +aid to driver authors. </para></warning> </para></glossdef></glossentry> </glosslist> </sect1>
--- a/packages/io/nand/current/include/nand.h +++ b/packages/io/nand/current/include/nand.h @@ -96,15 +96,33 @@ __externC cyg_nand_partition* cyg_nand_get_partition(cyg_nand_device *dev, unsigned partno); -#define NAND_BYTES_PER_PAGE(dev) (1<<(dev)->page_bits) -#define NAND_SPARE_PER_PAGE(dev) ((dev)->spare_per_page) -#define NAND_PAGES_PER_BLOCK(dev) (1<<(dev)->block_page_bits) -#define NAND_BLOCKCOUNT(dev) (1<<(dev)->blockcount_bits) -#define NAND_CHIPSIZE(dev) (1<<(dev)->chipsize_log) -#define NAND_APPSPARE_PER_PAGE(dev) ((dev)->oob->app_size) +/* Device info helpers */ +#define CYG_NAND_BYTES_PER_PAGE(dev) (1<<(dev)->page_bits) +#define CYG_NAND_SPARE_PER_PAGE(dev) ((dev)->spare_per_page) +#define CYG_NAND_PAGES_PER_BLOCK(dev) (1<<(dev)->block_page_bits) +#define CYG_NAND_BLOCKCOUNT(dev) (1<<(dev)->blockcount_bits) +#define CYG_NAND_CHIPSIZE(dev) (1<<(dev)->chipsize_log) +#define CYG_NAND_APPSPARE_PER_PAGE(dev) ((dev)->oob->app_size) /* NAND access functions ============================================= */ +/* + * Pages and blocks are numbered relative to the partition containing + * them, not to the whole device. In other words, the first page + * of every partition is considered to be number 0. + * + * (Note: This was changed in application interface v2, and the + * application-facing functions renamed. + * The library uses device-relative addressing internally. + * As an aide-memoire, if a function takes a cyg_nand_partition, + * it expects a partition-relative address; if it takes a + * cyg_nand_device, it expects a device-relative address.) + */ + +/* How big is your partition? */ +#define CYG_NAND_PARTITION_NBLOCKS(_p) ((_p)->last - (_p)->first) +#define CYG_NAND_PARTITION_NPAGES(_p) (CYG_NAND_PARTITION_NBLOCKS(_p) * CYG_NAND_PAGES_PER_BLOCK((_p)->dev)) + /* Reads a single page and/or its spare area from the device. * @page@ specifies the page to be read. * If @dest@ is not NULL, it will be used to store the page contents. @@ -130,7 +148,7 @@ cyg_nand_partition* cyg_nand_get_partiti * in the current chip layout. */ __externC -int cyg_nand_read_page(cyg_nand_partition *ctx, cyg_nand_page_addr page, +int cyg_nandp_read_page(cyg_nand_partition *ctx, cyg_nand_page_addr page, void * dest, void * spare, size_t spare_size); /* Reads a partial page from the device, to @dest@. @@ -162,7 +180,7 @@ int cyg_nand_read_page(cyg_nand_partitio * past the end of the page. */ __externC -int cyg_nand_read_part_page(cyg_nand_partition *ctx, cyg_nand_page_addr page, +int cyg_nandp_read_part_page(cyg_nand_partition *ctx, cyg_nand_page_addr page, void * dest, size_t offset, size_t length, int check_ecc); /* Writes a single page and/or its spare area to the device. @@ -185,7 +203,7 @@ int cyg_nand_read_part_page(cyg_nand_par * -EINVAL : The page address is within a block that is marked bad. */ __externC -int cyg_nand_write_page(cyg_nand_partition *ctx, cyg_nand_page_addr page, +int cyg_nandp_write_page(cyg_nand_partition *ctx, cyg_nand_page_addr page, const void * src, const void * spare, size_t spare_size); /* Erases an eraseblock. @@ -198,7 +216,7 @@ int cyg_nand_write_page(cyg_nand_partiti * -ENOENT : the block address was not valid. */ __externC -int cyg_nand_erase_block(cyg_nand_partition *ctx, cyg_nand_block_addr blk); +int cyg_nandp_erase_block(cyg_nand_partition *ctx, cyg_nand_block_addr blk); /* Bad block table functions ======================================= */ @@ -215,7 +233,7 @@ typedef enum { * -EIO : something awful happened with the bad block table. */ __externC -int cyg_nand_bbt_query(cyg_nand_partition *ctx, cyg_nand_block_addr blk); +int cyg_nandp_bbt_query(cyg_nand_partition *ctx, cyg_nand_block_addr blk); /* These functions mark a block as worn-bad in the Bad Block Table. * (The only difference is in the addressing: markbad_pageaddr takes @@ -230,9 +248,9 @@ int cyg_nand_bbt_query(cyg_nand_partitio * -EIO : something awful happened with the bad block table. */ __externC -int cyg_nand_bbt_markbad(cyg_nand_partition *ctx, cyg_nand_block_addr blk); +int cyg_nandp_bbt_markbad(cyg_nand_partition *ctx, cyg_nand_block_addr blk); __externC -int cyg_nand_bbt_markbad_pageaddr(cyg_nand_partition *ctx, cyg_nand_page_addr pg); +int cyg_nandp_bbt_markbad_pageaddr(cyg_nand_partition *ctx, cyg_nand_page_addr pg); #endif
--- a/packages/io/nand/current/src/nand.c +++ b/packages/io/nand/current/src/nand.c @@ -302,6 +302,14 @@ done: #define DEV_INIT_CHECK(dev) do { if (!dev->is_inited) return -ENXIO; } while(0) #define PARTITION_CHECK(p) do { if (!p->dev) return -ENXIO; } while(0) +// Partition-to-Device and Device-to-Partition address xlation +#define BLOCK_P_TO_D(_part,_block) ((_block) + (_part)->first) +#define BLOCK_D_TO_P(_part,_block) ((_block) - (_part)->first) + +#define PAGE_P_TO_D(_part,_page) ((_page) + (_part)->first * CYG_NAND_PAGES_PER_BLOCK((_part)->dev) ) +#define PAGE_D_TO_P(_part,_page) ((_page) - (_part)->first * CYG_NAND_PAGES_PER_BLOCK((_part)->dev) ) + +/* Sanity check helpers: these take a partition and a DEVICE address */ static inline int valid_block_addr(cyg_nand_partition *part, cyg_nand_block_addr block) { return ( (block < part->first) || (block > part->last) ) ? -ENOENT : 0; @@ -319,7 +327,7 @@ static int valid_page_addr(cyg_nand_part #define EG(what) do { rv = (what); if (rv != 0) goto err_exit; } while(0) __externC -int cyg_nand_read_page(cyg_nand_partition *prt, cyg_nand_page_addr page, +int cyg_nandp_read_page(cyg_nand_partition *prt, cyg_nand_page_addr ppage, void * dest, void * spare, size_t spare_size) { int rv, locked=0; @@ -327,6 +335,7 @@ int cyg_nand_read_page(cyg_nand_partitio PARTITION_CHECK(prt); cyg_nand_device *dev = prt->dev; DEV_INIT_CHECK(dev); + cyg_nand_page_addr page = PAGE_P_TO_D(prt,ppage); if (spare_size > dev->spare_per_page) return -EFBIG; @@ -353,7 +362,7 @@ err_exit: __externC -int cyg_nand_read_part_page(cyg_nand_partition *prt, cyg_nand_page_addr page, +int cyg_nandp_read_part_page(cyg_nand_partition *prt, cyg_nand_page_addr ppage, void * dest, size_t offset, size_t length, int check_ecc) { @@ -361,10 +370,11 @@ int cyg_nand_read_part_page(cyg_nand_par PARTITION_CHECK(prt); cyg_nand_device *dev = prt->dev; DEV_INIT_CHECK(dev); + cyg_nand_page_addr page = PAGE_P_TO_D(prt,ppage); CYG_BYTE *pagebuffer; int got_pagebuf = 0, locked = 0; - if (offset + length > NAND_BYTES_PER_PAGE(dev)) return -EFBIG; + if (offset + length > CYG_NAND_BYTES_PER_PAGE(dev)) return -EFBIG; EG(valid_page_addr(prt, page)); @@ -397,6 +407,7 @@ err_exit: /* Internal, mostly-unchecked interface to read a page. + * Takes a DEVICE address. * Caller must hold the devlock! */ int nandi_read_whole_page_raw(cyg_nand_device *dev, cyg_nand_page_addr page, CYG_BYTE * dest, CYG_BYTE * spare, size_t spare_size, @@ -412,7 +423,7 @@ int nandi_read_whole_page_raw(cyg_nand_d const int do_hw_ecc = (dev->ecc->flags & NAND_ECC_FLAG_IS_HARDWARE) && check_ecc; // Stride for reading from device: - const unsigned read_data_stride = do_hw_ecc ? dev->ecc->data_size : NAND_BYTES_PER_PAGE(dev); + const unsigned read_data_stride = do_hw_ecc ? dev->ecc->data_size : CYG_NAND_BYTES_PER_PAGE(dev); // Stride for calculating/checking/repairing ECC: const unsigned ecc_data_stride = dev->ecc->data_size; // Stride within the ECC data @@ -421,14 +432,14 @@ int nandi_read_whole_page_raw(cyg_nand_d if (dest) CYG_CHECK_DATA_PTRC(dest); if (spare) CYG_CHECK_DATA_PTRC(spare); - CYG_ASSERTC(NAND_BYTES_PER_PAGE(dev) % ecc_data_stride == 0); + CYG_ASSERTC(CYG_NAND_BYTES_PER_PAGE(dev) % ecc_data_stride == 0); do { CYG_BYTE *data_dest = dest; CYG_BYTE *ecc_dest = ecc_calc; ++tries; - remain = NAND_BYTES_PER_PAGE(dev); + remain = CYG_NAND_BYTES_PER_PAGE(dev); TIMETAG(); EG(dev->fns->read_begin(dev, page)); @@ -466,7 +477,7 @@ int nandi_read_whole_page_raw(cyg_nand_d // Calculate software ECC in one go to try and take // advantage of the cache. data_dest = dest; - remain = NAND_BYTES_PER_PAGE(dev); + remain = CYG_NAND_BYTES_PER_PAGE(dev); ecc_calc_p = ecc_calc; while (remain) { @@ -482,7 +493,7 @@ int nandi_read_whole_page_raw(cyg_nand_d // Now repair ... rv = 0; int step_rv; - remain = NAND_BYTES_PER_PAGE(dev); + remain = CYG_NAND_BYTES_PER_PAGE(dev); data_dest = dest; ecc_calc_p = ecc_calc; @@ -538,9 +549,8 @@ err_exit: return rv; } -/* Internal, mostly-unchecked interface to write a page. */ __externC -int cyg_nand_write_page(cyg_nand_partition *prt, cyg_nand_page_addr page, +int cyg_nandp_write_page(cyg_nand_partition *prt, cyg_nand_page_addr ppage, const void * src, const void * spare, size_t spare_size) { int rv, locked = 0; @@ -548,6 +558,7 @@ int cyg_nand_write_page(cyg_nand_partiti PARTITION_CHECK(prt); cyg_nand_device *dev = prt->dev; DEV_INIT_CHECK(dev); + cyg_nand_page_addr page = PAGE_P_TO_D(prt,ppage); EG(valid_page_addr(prt, page)); @@ -568,6 +579,8 @@ err_exit: return rv; } +/* Internal, mostly-unchecked interface to write a page. + * Takes a DEVICE address. */ __externC int nandi_write_page_raw(cyg_nand_device *dev, cyg_nand_page_addr page, const CYG_BYTE * src, const CYG_BYTE * spare, size_t spare_size) @@ -580,7 +593,7 @@ int nandi_write_page_raw(cyg_nand_device CYG_BYTE ecc[CYG_NAND_ECCPERPAGE(dev)]; const int do_hw_ecc = (dev->ecc->flags & NAND_ECC_FLAG_IS_HARDWARE); - const unsigned write_data_stride = do_hw_ecc ? dev->ecc->data_size : NAND_BYTES_PER_PAGE(dev); + const unsigned write_data_stride = do_hw_ecc ? dev->ecc->data_size : CYG_NAND_BYTES_PER_PAGE(dev); const unsigned ecc_data_stride = dev->ecc->data_size; const unsigned ecc_stride = dev->ecc->ecc_size; size_t remain; @@ -590,13 +603,13 @@ int nandi_write_page_raw(cyg_nand_device if (src) CYG_CHECK_DATA_PTRC(src); if (spare) CYG_CHECK_DATA_PTRC(spare); - CYG_ASSERTC(NAND_BYTES_PER_PAGE(dev) % ecc_data_stride == 0); + CYG_ASSERTC(CYG_NAND_BYTES_PER_PAGE(dev) % ecc_data_stride == 0); TIMETAG(); // If we're doing software ECC, do it all in one go now. if (src && !do_hw_ecc) { const CYG_BYTE *data_src = src; - remain = NAND_BYTES_PER_PAGE(dev); + remain = CYG_NAND_BYTES_PER_PAGE(dev); while (remain) { CYG_ASSERTC(remain >= ecc_data_stride); @@ -613,7 +626,7 @@ int nandi_write_page_raw(cyg_nand_device EG(dev->fns->write_begin(dev, page)); TIMETAG(); if (src) { - remain = NAND_BYTES_PER_PAGE(dev); + remain = CYG_NAND_BYTES_PER_PAGE(dev); while (remain) { CYG_ASSERTC(remain >= write_data_stride); TIMETAG(); @@ -646,7 +659,7 @@ err_exit: } __externC -int cyg_nand_erase_block(cyg_nand_partition *prt, cyg_nand_block_addr blk) +int cyg_nandp_erase_block(cyg_nand_partition *prt, cyg_nand_block_addr pblk) { #ifdef CYGSEM_IO_NAND_READONLY return -EROFS; @@ -655,6 +668,7 @@ int cyg_nand_erase_block(cyg_nand_partit cyg_nand_device *dev = prt->dev; int rv; DEV_INIT_CHECK(dev); + cyg_nand_block_addr blk = BLOCK_P_TO_D(prt, pblk); TIMETAG(); LOCK_DEV(dev); @@ -684,13 +698,14 @@ err_exit: } __externC -int cyg_nand_bbt_query(cyg_nand_partition *prt, cyg_nand_block_addr blk) +int cyg_nandp_bbt_query(cyg_nand_partition *prt, cyg_nand_block_addr pblk) { #ifdef CYGSEM_IO_NAND_USE_BBT int rv; PARTITION_CHECK(prt); cyg_nand_device *dev = prt->dev; DEV_INIT_CHECK(dev); + cyg_nand_block_addr blk = BLOCK_P_TO_D(prt, pblk); LOCK_DEV(dev); EG(valid_block_addr(prt, blk)); rv = cyg_nand_bbti_query(dev, blk); @@ -703,13 +718,14 @@ err_exit: } __externC -int cyg_nand_bbt_markbad(cyg_nand_partition *prt, cyg_nand_block_addr blk) +int cyg_nandp_bbt_markbad(cyg_nand_partition *prt, cyg_nand_block_addr pblk) { #ifdef CYGSEM_IO_NAND_USE_BBT int rv; PARTITION_CHECK(prt); cyg_nand_device *dev = prt->dev; DEV_INIT_CHECK(dev); + cyg_nand_block_addr blk = BLOCK_P_TO_D(prt, pblk); LOCK_DEV(dev); EG(valid_block_addr(prt, blk)); EG(cyg_nand_bbti_markbad(dev, blk)); @@ -722,16 +738,17 @@ err_exit: } __externC -int cyg_nand_bbt_markbad_pageaddr(cyg_nand_partition *prt, cyg_nand_page_addr pg) +int cyg_nand_bbt_markbad_pageaddr(cyg_nand_partition *prt, cyg_nand_page_addr ppg) { #ifdef CYGSEM_IO_NAND_USE_BBT int rv; PARTITION_CHECK(prt); cyg_nand_device *dev = prt->dev; DEV_INIT_CHECK(dev); + cyg_nand_block_addr pblk = CYG_NAND_PAGE2BLOCKADDR(dev, ppg); + cyg_nand_block_addr blk = BLOCK_P_TO_D(prt, pblk); + EG(valid_block_addr(prt, blk)); LOCK_DEV(dev); - cyg_nand_block_addr blk = CYG_NAND_PAGE2BLOCKADDR(dev, pg); - EG(valid_block_addr(prt, blk)); EG(cyg_nand_bbti_markbad(dev, blk)); err_exit: UNLOCK_DEV(dev);
--- a/packages/io/nand/current/src/nand_bbt.c +++ b/packages/io/nand/current/src/nand_bbt.c @@ -151,7 +151,7 @@ static void bbti_mark_raw(cyg_nand_devic int cyg_nand_bbti_query(cyg_nand_device *dev, cyg_nand_block_addr blk) { - CYG_ASSERT(blk >= 0 && blk <= NAND_BLOCKCOUNT(dev), "valid block"); + CYG_ASSERT(blk >= 0 && blk <= CYG_NAND_BLOCKCOUNT(dev), "valid block"); unsigned offset = blk >> 2; unsigned byteshift = (blk & 3) * 2; return ( dev->bbt.data[offset] >> byteshift ) & 3; @@ -160,7 +160,7 @@ int cyg_nand_bbti_query(cyg_nand_device int cyg_nand_bbti_markany(cyg_nand_device *dev, cyg_nand_block_addr blk, cyg_nand_bbt_status_t st) { - CYG_ASSERT(blk >= 0 && blk <= NAND_BLOCKCOUNT(dev), "valid block"); + CYG_ASSERT(blk >= 0 && blk <= CYG_NAND_BLOCKCOUNT(dev), "valid block"); bbti_mark_raw(dev, blk, st); #ifdef CYGSEM_IO_NAND_READONLY NAND_CHATTER(2,dev,"ignoring mark request on read-only config\n"); @@ -175,7 +175,7 @@ int cyg_nand_bbti_markany(cyg_nand_devic int cyg_nand_bbti_markbad(cyg_nand_device *dev, cyg_nand_block_addr blk) { - CYG_ASSERT(blk >= 0 && blk <= NAND_BLOCKCOUNT(dev), "valid block"); + CYG_ASSERT(blk >= 0 && blk <= CYG_NAND_BLOCKCOUNT(dev), "valid block"); return cyg_nand_bbti_markany(dev, blk, CYG_NAND_BBT_WORNBAD); } @@ -313,8 +313,8 @@ err_exit: static int nandi_bbt_packing_test(cyg_nand_device *dev) { // Startup sanity check: Can we pack the BBT marker and version into the app spare area, do they appear in the right place, and can we extract them? - CYG_BYTE appspare[NAND_APPSPARE_PER_PAGE(dev)], - packed[NAND_SPARE_PER_PAGE(dev)], + CYG_BYTE appspare[CYG_NAND_APPSPARE_PER_PAGE(dev)], + packed[CYG_NAND_SPARE_PER_PAGE(dev)], testdata[NAND_PATTERN_SIZE > NAND_VERSION_SIZE ? NAND_PATTERN_SIZE : NAND_VERSION_SIZE], ecc[CYG_NAND_ECCPERPAGE(dev)]; int i, rv, fail = 0; @@ -400,7 +400,7 @@ static int nandi_find_bbt_locations(cyg_ cyg_nand_block_addr *mir_o, CYG_BYTE*mir_ver, int find_only) { cyg_nand_block_addr start = (1<<dev->blockcount_bits) - 1; - CYG_BYTE oobbuf[NAND_APPSPARE_PER_PAGE(dev)]; + CYG_BYTE oobbuf[CYG_NAND_APPSPARE_PER_PAGE(dev)]; CYG_BYTE patternbuf[NAND_PATTERN_SIZE]; CYG_BYTE versionbuf[NAND_VERSION_SIZE]; int i, rv=0; @@ -626,7 +626,7 @@ static int bbti_write_one_table(cyg_nand } /* Prep ECC & OOB, then send */ - CYG_BYTE appspare[NAND_APPSPARE_PER_PAGE(dev)]; + CYG_BYTE appspare[CYG_NAND_APPSPARE_PER_PAGE(dev)]; memset(appspare, 0xff, sizeof appspare); rv = nand_oob_packed_write(dev, NAND_PATTERN_OFFSET, NAND_PATTERN_SIZE, appspare, pattern);
--- a/packages/io/nand/current/src/nand_bbt.h +++ b/packages/io/nand/current/src/nand_bbt.h @@ -122,13 +122,13 @@ int cyg_nand_bbti_build_tables(cyg_nand_ /* Raw unchecked NAND access, for use by the BBT ===================== */ -/* Caller must hold the devlock! */ +/* Takes a DEVICE address. Caller must hold the devlock! */ int nandi_read_whole_page_raw(cyg_nand_device *dev, cyg_nand_page_addr page, CYG_BYTE * dest, CYG_BYTE * spare, size_t spare_size, int check_ecc); -/* Caller must hold the devlock! */ +/* Takes a DEVICE address. Caller must hold the devlock! */ int nandi_write_page_raw(cyg_nand_device *dev, cyg_nand_page_addr page, const CYG_BYTE * src, const CYG_BYTE * spare, size_t spare_size);
--- a/packages/io/nand/current/tests/readlimits.c +++ b/packages/io/nand/current/tests/readlimits.c @@ -81,7 +81,7 @@ int tryread(cyg_nand_partition *prt, cyg #if 0 printf("Trying %d...\n",pg); #endif - int rv = cyg_nand_read_page(prt, pg, buf, NULL, 0); + int rv = cyg_nandp_read_page(prt, pg, buf, NULL, 0); if (!shouldwork) ++tried_bad; if (rv==0) @@ -96,6 +96,7 @@ int cyg_user_start(void) { cyg_nand_device *dev; cyg_nand_partition *prt; + cyg_nand_page_addr pg; CYG_TEST_INIT(); CYG_TEST_INFO(msg); @@ -109,9 +110,8 @@ int cyg_user_start(void) /* Check we can read the first page of the partition, and the page * before it (which might be off the start of the device) */ - cyg_nand_page_addr pg = CYG_NAND_BLOCK2PAGEADDR(dev, prt->first); - TRYREAD(prt, pg, 1); - TRYREAD(prt, pg-1, 0); + TRYREAD(prt, 0, 1); + TRYREAD(prt, -1, 0); /* Check we can read the last page of the partition (allowing for * the BBT perhaps getting in the way) */ @@ -122,12 +122,13 @@ int cyg_user_start(void) #else CYG_TEST_INFO("Caution, CYGSEM_IO_NAND_USE_BBT disabled - this may go wrong if we hit a bad block."); #endif - pg = CYG_NAND_BLOCK2PAGEADDR(dev, blk+1) - 1; + cyg_nand_block_addr pblk = blk - prt->first; + pg = CYG_NAND_BLOCK2PAGEADDR(dev, pblk+1) - 1; TRYREAD(prt, pg, 1); /* Try and read the page after the last page (which might be off * the end of the device) */ - pg = CYG_NAND_BLOCK2PAGEADDR(dev, prt->last + 1); + pg = CYG_NAND_PARTITION_NPAGES(prt); TRYREAD(prt, pg, 0); if (!fails) {
--- a/packages/io/nand/current/tests/readwrite.c +++ b/packages/io/nand/current/tests/readwrite.c @@ -110,13 +110,13 @@ int cyg_user_start(void) prt = cyg_nand_get_partition(dev, 0); /* Now select a usable block in the partition to base ourselves around. */ - blk = prt->first+5; + blk = 0; #ifdef CYGSEM_IO_NAND_USE_BBT - while ( (cyg_nand_bbt_query(prt, blk) != CYG_NAND_BBT_OK) - && (cyg_nand_bbt_query(prt, blk+1) != CYG_NAND_BBT_OK) ) { + while ( (cyg_nandp_bbt_query(prt, blk) != CYG_NAND_BBT_OK) + && (cyg_nandp_bbt_query(prt, blk+1) != CYG_NAND_BBT_OK) ) { blk++; - if (blk+3 > prt->last) - CYG_TEST_NA("Cannot find a usable block to test"); + if (blk > CYG_NAND_PARTITION_NBLOCKS(prt)) + CYG_TEST_FAIL_FINISH("Cannot find a usable block to test"); } #else CYG_TEST_INFO("Caution, CYGSEM_IO_NAND_USE_BBT disabled - this may go wrong if we hit a bad block."); @@ -124,28 +124,28 @@ int cyg_user_start(void) pg = CYG_NAND_BLOCK2PAGEADDR(dev,blk); diag_printf("Erasing block %d\n", blk); - MUST(0==cyg_nand_erase_block(prt, blk)); + MUST(0==cyg_nandp_erase_block(prt, blk)); - CYG_ASSERTC(NAND_BYTES_PER_PAGE(dev) <= CYGNUM_NAND_PAGEBUFFER); + CYG_ASSERTC(CYG_NAND_BYTES_PER_PAGE(dev) <= CYGNUM_NAND_PAGEBUFFER); ar4prng_many(&rnd, buf, datasize); diag_printf("Read/write to page %d (block %d)\n", pg, blk); - MUST(0==cyg_nand_write_page(prt, pg, buf, 0, 0)); - MUST(0==cyg_nand_read_page (prt, pg, buf2, 0, 0)); + MUST(0==cyg_nandp_write_page(prt, pg, buf, 0, 0)); + MUST(0==cyg_nandp_read_page (prt, pg, buf2, 0, 0)); MUST(0==memcmp(buf, buf2, datasize)); diag_printf("Partial-reads of page %d (block %d)\n", pg, blk); #define TEST(_m,_n,_ecc) do { \ memset(buf2, 0, sizeof buf2); \ - MUST(0==cyg_nand_read_part_page(prt, pg, buf2, _m, _n, _ecc)); \ + MUST(0==cyg_nandp_read_part_page(prt, pg, buf2, _m, _n, _ecc)); \ MUST(0==memcmp(&buf[_m], buf2, _n)); \ } while(0) #define TESTFAIL(_m,_n,_ecc) do { \ - MUST(0!=cyg_nand_read_part_page(prt, pg, buf2, _m, _n, _ecc)); \ + MUST(0!=cyg_nandp_read_part_page(prt, pg, buf2, _m, _n, _ecc)); \ } while(0) // Ordinary whole-page reads: - TEST(0, NAND_BYTES_PER_PAGE(dev), 0); - TEST(0, NAND_BYTES_PER_PAGE(dev), 1); + TEST(0, CYG_NAND_BYTES_PER_PAGE(dev), 0); + TEST(0, CYG_NAND_BYTES_PER_PAGE(dev), 1); // Partial reads: TEST(0, 99, 0); TEST(0, 99, 1); @@ -155,30 +155,30 @@ int cyg_user_start(void) TEST(258, 99, 1); TEST(258, 99, 0); // Read right up to the end: - TEST(43, NAND_BYTES_PER_PAGE(dev)-43, 0); - TEST(43, NAND_BYTES_PER_PAGE(dev)-43, 1); - TEST(258, NAND_BYTES_PER_PAGE(dev)-258, 0); - TEST(258, NAND_BYTES_PER_PAGE(dev)-258, 1); + TEST(43, CYG_NAND_BYTES_PER_PAGE(dev)-43, 0); + TEST(43, CYG_NAND_BYTES_PER_PAGE(dev)-43, 1); + TEST(258, CYG_NAND_BYTES_PER_PAGE(dev)-258, 0); + TEST(258, CYG_NAND_BYTES_PER_PAGE(dev)-258, 1); // ... but we should not be able to read off the end of the page: - TESTFAIL(0, NAND_BYTES_PER_PAGE(dev)+1, 0); - TESTFAIL(43, NAND_BYTES_PER_PAGE(dev)-42, 1); + TESTFAIL(0, CYG_NAND_BYTES_PER_PAGE(dev)+1, 0); + TESTFAIL(43, CYG_NAND_BYTES_PER_PAGE(dev)-42, 1); // Zero-length reads should work: TEST(0, 0, 0); TEST(0, 0, 1); // Silly offsets should fail: - TESTFAIL(NAND_BYTES_PER_PAGE(dev)+1, 1, 0); - TESTFAIL(NAND_BYTES_PER_PAGE(dev)+1, 0, 1); + TESTFAIL(CYG_NAND_BYTES_PER_PAGE(dev)+1, 1, 0); + TESTFAIL(CYG_NAND_BYTES_PER_PAGE(dev)+1, 0, 1); diag_printf("Erasing adjacent block %d\n", blk+1); - MUST(0==cyg_nand_erase_block(prt, blk+1)); + MUST(0==cyg_nandp_erase_block(prt, blk+1)); diag_printf("Re-read check..\n"); - MUST(0==cyg_nand_read_page (prt, pg, buf2, 0, 0)); + MUST(0==cyg_nandp_read_page (prt, pg, buf2, 0, 0)); MUST(0==memcmp(buf, buf2, datasize)); diag_printf("Re-erase %d\n", blk); - MUST(0==cyg_nand_erase_block(prt, blk)); + MUST(0==cyg_nandp_erase_block(prt, blk)); diag_printf("Read-back page %d to confirm erase\n", pg); - MUST(0==cyg_nand_read_page (prt, pg, buf2, 0, 0)); + MUST(0==cyg_nandp_read_page (prt, pg, buf2, 0, 0)); for (i=0; i<datasize; i++) MUST(buf2[i]==0xff);
--- a/packages/io/nand/current/tests/rwbenchmark.c +++ b/packages/io/nand/current/tests/rwbenchmark.c @@ -311,14 +311,14 @@ void show_test_parameters(void) cyg_nand_block_addr find_spare_block(cyg_nand_partition *part) { - const int oobz = NAND_APPSPARE_PER_PAGE(part->dev); + const int oobz = CYG_NAND_APPSPARE_PER_PAGE(part->dev); unsigned char oob[oobz]; int i,rv; cyg_nand_block_addr b; - for (b=part->last; b>=part->first; b--) { + for (b=CYG_NAND_PARTITION_NBLOCKS(part)-1; b>=0; b--) { cyg_nand_page_addr pg = CYG_NAND_BLOCK2PAGEADDR(part->dev, b); - rv = cyg_nand_read_page(part, pg, 0, oob, oobz); + rv = cyg_nandp_read_page(part, pg, 0, oob, oobz); if (rv != 0) continue; // bad block? for (i=0; i<oobz; i++) @@ -347,19 +347,19 @@ void test_reads(cyg_nand_partition *part pgend = CYG_NAND_BLOCK2PAGEADDR(part->dev, b+1)-1, pg = pgstart; int i, rv; - const int oobz = NAND_APPSPARE_PER_PAGE(part->dev); + const int oobz = CYG_NAND_APPSPARE_PER_PAGE(part->dev); unsigned char oob[oobz]; #define ft ft_read /* First, set up the block the way we want it ... */ - cyg_nand_erase_block(part, b); + cyg_nandp_erase_block(part, b); memcpy(oob, databuf, oobz); for (i=pgstart; i <= pgend; i++) { - rv = cyg_nand_write_page(part, i, databuf, oob, oobz); + rv = cyg_nandp_write_page(part, i, databuf, oob, oobz); switch (rv) { case 0: break; case -EIO: - cyg_nand_bbt_markbad(part, b); + cyg_nandp_bbt_markbad(part, b); CYG_TEST_FAIL_FINISH("Write failed; block now marked as bad. This run can't continue but should be OK to repeat."); default: @@ -387,7 +387,7 @@ void test_reads(cyg_nand_partition *part CLEARDATA(); wait_for_tick(); get_timestamp(&ft[i].start); - cyg_nand_read_page(part, pg, testbuf, 0, 0); + cyg_nandp_read_page(part, pg, testbuf, 0, 0); get_timestamp(&ft[i].end); CHECKDATA(); ++pg; @@ -399,7 +399,7 @@ void test_reads(cyg_nand_partition *part CLEAROOB(); wait_for_tick(); get_timestamp(&ft[i].start); - cyg_nand_read_page(part, pg, 0, oob, oobz); + cyg_nandp_read_page(part, pg, 0, oob, oobz); get_timestamp(&ft[i].end); CHECKOOB(); ++pg; @@ -412,14 +412,14 @@ void test_reads(cyg_nand_partition *part CLEAROOB(); wait_for_tick(); get_timestamp(&ft[i].start); - cyg_nand_read_page(part, pg, testbuf, oob, oobz); + cyg_nandp_read_page(part, pg, testbuf, oob, oobz); get_timestamp(&ft[i].end); CHECKDATA(); CHECKOOB(); ++pg; if (pg > pgend) pg = pgstart; } - cyg_nand_erase_block(part, b); + cyg_nandp_erase_block(part, b); show_times(ft, NREADS, "NAND page reads (page + OOB)"); #undef ft } @@ -431,31 +431,31 @@ void test_writes(cyg_nand_partition *par pgend = CYG_NAND_BLOCK2PAGEADDR(part->dev, b+1)-1, pg = pgstart; int i; - const int oobz = NAND_APPSPARE_PER_PAGE(part->dev); + const int oobz = CYG_NAND_APPSPARE_PER_PAGE(part->dev); unsigned char oob[oobz]; #define ft ft_write - cyg_nand_erase_block(part, b); + cyg_nandp_erase_block(part, b); for (i=0; i < NWRITES; i++) { wait_for_tick(); get_timestamp(&ft[i].start); - cyg_nand_write_page(part, pg, databuf, databuf, oobz); + cyg_nandp_write_page(part, pg, databuf, databuf, oobz); get_timestamp(&ft[i].end); // Read it back to confirm CLEARDATA(); CLEAROOB(); - cyg_nand_read_page(part, pg, testbuf, oob, oobz); + cyg_nandp_read_page(part, pg, testbuf, oob, oobz); CHECKDATA(); CHECKOOB(); ++pg; if (pg > pgend) { - cyg_nand_erase_block(part, b); + cyg_nandp_erase_block(part, b); pg = pgstart; } } - cyg_nand_erase_block(part, b); + cyg_nandp_erase_block(part, b); show_times(ft, NWRITES, "NAND full-page writes"); #undef ft } @@ -469,19 +469,19 @@ void test_erases(cyg_nand_partition *par for (i=0; i < NERASES; i++) { wait_for_tick(); get_timestamp(&ft[i].start); - cyg_nand_erase_block(part, b); + cyg_nandp_erase_block(part, b); get_timestamp(&ft[i].end); if (i==0) { cyg_nand_page_addr pg = CYG_NAND_BLOCK2PAGEADDR(part->dev, b); - const int oobz = NAND_APPSPARE_PER_PAGE(part->dev); + const int oobz = CYG_NAND_APPSPARE_PER_PAGE(part->dev); unsigned char oob[oobz]; int j; // TODO: It only makes sense to check the one, unless we want // to try writing out more dummy data each time. CLEARDATA(); CLEAROOB(); - cyg_nand_read_page(part, pg, testbuf, oob, oobz); + cyg_nandp_read_page(part, pg, testbuf, oob, oobz); for (j=0; j < sizeof testbuf; j++) { if (testbuf[j] != 0xff) { CYG_TEST_FAIL("readback check failed");
--- a/packages/io/nand/current/utils/erasenand.c +++ b/packages/io/nand/current/utils/erasenand.c @@ -80,9 +80,9 @@ void cyg_user_start(void) int progmod = (prt->last - prt->first + 1) / 73 + 1; - for (blk=prt->first; blk <= prt->last; blk++) { + for (blk=0; blk <= CYG_NAND_PARTITION_NBLOCKS(prt); blk++) { #ifdef CYGSEM_IO_NAND_USE_BBT - int st = cyg_nand_bbt_query(prt, blk); + int st = cyg_nandp_bbt_query(prt, blk); if (st<0) { diag_printf("Block %d BBTI error %d\n", blk, -st); } @@ -92,7 +92,7 @@ void cyg_user_start(void) const char *msg = 0; switch(st) { case CYG_NAND_BBT_OK: - rv = cyg_nand_erase_block(prt, blk); + rv = cyg_nandp_erase_block(prt, blk); if (rv != 0) diag_printf("Block %d: error %d\n", blk, -rv); break;
