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&lt;&lt;(dev)->page_bits)
-#define NAND_SPARE_PER_PAGE(dev) ((dev)->spare_per_page)
-#define NAND_PAGES_PER_BLOCK(dev) (1&lt;&lt;(dev)->block_page_bits)
-#define NAND_BLOCKCOUNT(dev) (1&lt;&lt;(dev)->blockcount_bits)
-#define NAND_PAGECOUNT(dev) (NAND_BLOCKCOUNT(dev) * NAND_PAGES_PER_BLOCK(dev))
-#define NAND_CHIPSIZE(dev) (1&lt;&lt;(dev)->chipsize_log)
-#define NAND_APPSPARE_PER_PAGE(dev) ((dev)->oob->app_size)
+#define CYG_NAND_BYTES_PER_PAGE(dev) (1&lt;&lt;(dev)->page_bits)
+#define CYG_NAND_SPARE_PER_PAGE(dev) ((dev)->spare_per_page)
+#define CYG_NAND_PAGES_PER_BLOCK(dev) (1&lt;&lt;(dev)->block_page_bits)
+#define CYG_NAND_BLOCKCOUNT(dev) (1&lt;&lt;(dev)->blockcount_bits)
+#define CYG_NAND_PAGECOUNT(dev) (NAND_BLOCKCOUNT(dev) * NAND_PAGES_PER_BLOCK(dev))
+#define CYG_NAND_CHIPSIZE(dev) (1&lt;&lt;(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;