yaffs2: Yaffs endian support
[yaffs2.git] / yaffs_tagscompat.c
index 23e694781361516f25236142bc78a88fb49545ea..e57c2d33f15f77e5ab1f001d64203cfdf3e8d21b 100644 (file)
@@ -9,6 +9,9 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
+ *
+ * This file handles yaffs1-style tags to allow compatibility with Yaffs1 style
+ * flash layouts.
  */
 
 #include "yaffs_guts.h"
 #include "yaffs_ecc.h"
 #include "yaffs_getblockinfo.h"
 #include "yaffs_trace.h"
+#include "yaffs_endian.h"
 
 static void yaffs_handle_rd_data_error(struct yaffs_dev *dev, int nand_chunk);
 
 
 /********** Tags ECC calculations  *********/
 
-
 void yaffs_calc_tags_ecc(struct yaffs_tags *tags)
 {
        /* Calculate an ecc */
@@ -73,21 +76,30 @@ int yaffs_check_tags_ecc(struct yaffs_tags *tags)
 
 /********** Tags **********/
 
-static void yaffs_load_tags_to_spare(struct yaffs_spare *spare_ptr,
+/*
+ * During tags storing/retireval we use a copy of the tags so that
+ * we can modify the endian etc without damaging the previous structure.
+ */
+static void yaffs_load_tags_to_spare(struct yaffs_dev *dev,
+                                    struct yaffs_spare *spare_ptr,
                                     struct yaffs_tags *tags_ptr)
 {
-       union yaffs_tags_union *tu = (union yaffs_tags_union *)tags_ptr;
-
-       yaffs_calc_tags_ecc(tags_ptr);
-
-       spare_ptr->tb0 = tu->as_bytes[0];
-       spare_ptr->tb1 = tu->as_bytes[1];
-       spare_ptr->tb2 = tu->as_bytes[2];
-       spare_ptr->tb3 = tu->as_bytes[3];
-       spare_ptr->tb4 = tu->as_bytes[4];
-       spare_ptr->tb5 = tu->as_bytes[5];
-       spare_ptr->tb6 = tu->as_bytes[6];
-       spare_ptr->tb7 = tu->as_bytes[7];
+       union yaffs_tags_union *tu_ptr = (union yaffs_tags_union *)tags_ptr;
+       union yaffs_tags_union tags_stored = *tu_ptr;
+
+       yaffs_calc_tags_ecc(&tags_stored.as_tags);
+
+       yaffs_do_endian_u32(dev, &tags_stored.as_u32[0]);
+       yaffs_do_endian_u32(dev, &tags_stored.as_u32[1]);
+
+       spare_ptr->tb0 = tags_stored.as_bytes[0];
+       spare_ptr->tb1 = tags_stored.as_bytes[1];
+       spare_ptr->tb2 = tags_stored.as_bytes[2];
+       spare_ptr->tb3 = tags_stored.as_bytes[3];
+       spare_ptr->tb4 = tags_stored.as_bytes[4];
+       spare_ptr->tb5 = tags_stored.as_bytes[5];
+       spare_ptr->tb6 = tags_stored.as_bytes[6];
+       spare_ptr->tb7 = tags_stored.as_bytes[7];
 }
 
 static void yaffs_get_tags_from_spare(struct yaffs_dev *dev,
@@ -95,16 +107,22 @@ static void yaffs_get_tags_from_spare(struct yaffs_dev *dev,
                                      struct yaffs_tags *tags_ptr)
 {
        union yaffs_tags_union *tu = (union yaffs_tags_union *)tags_ptr;
+       union yaffs_tags_union tags_stored;
        int result;
 
-       tu->as_bytes[0] = spare_ptr->tb0;
-       tu->as_bytes[1] = spare_ptr->tb1;
-       tu->as_bytes[2] = spare_ptr->tb2;
-       tu->as_bytes[3] = spare_ptr->tb3;
-       tu->as_bytes[4] = spare_ptr->tb4;
-       tu->as_bytes[5] = spare_ptr->tb5;
-       tu->as_bytes[6] = spare_ptr->tb6;
-       tu->as_bytes[7] = spare_ptr->tb7;
+       tags_stored.as_bytes[0] = spare_ptr->tb0;
+       tags_stored.as_bytes[1] = spare_ptr->tb1;
+       tags_stored.as_bytes[2] = spare_ptr->tb2;
+       tags_stored.as_bytes[3] = spare_ptr->tb3;
+       tags_stored.as_bytes[4] = spare_ptr->tb4;
+       tags_stored.as_bytes[5] = spare_ptr->tb5;
+       tags_stored.as_bytes[6] = spare_ptr->tb6;
+       tags_stored.as_bytes[7] = spare_ptr->tb7;
+
+       yaffs_do_endian_u32(dev, &tags_stored.as_u32[0]);
+       yaffs_do_endian_u32(dev, &tags_stored.as_u32[1]);
+
+       *tu = tags_stored;
 
        result = yaffs_check_tags_ecc(tags_ptr);
        if (result > 0)
@@ -124,7 +142,7 @@ static int yaffs_wr_nand(struct yaffs_dev *dev,
 {
        int data_size = dev->data_bytes_per_chunk;
 
-       return dev->param.drv_write_chunk_fn(dev, nand_chunk,
+       return dev->drv.drv_write_chunk_fn(dev, nand_chunk,
                                data, data_size,
                                (u8 *) spare, sizeof(*spare));
 }
@@ -152,7 +170,7 @@ static int yaffs_rd_chunk_nand(struct yaffs_dev *dev,
        spare_size = sizeof(struct yaffs_spare);
 
        if (dev->param.use_nand_ecc)
-               return dev->param.drv_read_chunk_fn(dev, nand_chunk,
+               return dev->drv.drv_read_chunk_fn(dev, nand_chunk,
                                                data, data_size,
                                                (u8 *) spare, spare_size,
                                                ecc_result);
@@ -160,7 +178,7 @@ static int yaffs_rd_chunk_nand(struct yaffs_dev *dev,
 
        /* Handle the ECC at this level. */
 
-       ret_val = dev->param.drv_read_chunk_fn(dev, nand_chunk,
+       ret_val = dev->drv.drv_read_chunk_fn(dev, nand_chunk,
                                                 data, data_size,
                                                 (u8 *)spare, spare_size,
                                                NULL);
@@ -263,7 +281,7 @@ static int yaffs_tags_compat_wr(struct yaffs_dev *dev,
                        yaffs_ecc_calc(&data[256], spare.ecc2);
                }
 
-               yaffs_load_tags_to_spare(&spare, &tags);
+               yaffs_load_tags_to_spare(dev, &spare, &tags);
        }
        return yaffs_wr_nand(dev, nand_chunk, data, &spare);
 }
@@ -303,6 +321,7 @@ static int yaffs_tags_compat_rd(struct yaffs_dev *dev,
 
        if (ext_tags->chunk_used) {
                yaffs_get_tags_from_spare(dev, &spare, &tags);
+
                ext_tags->obj_id = tags.obj_id;
                ext_tags->chunk_id = tags.chunk_id;
                ext_tags->n_bytes = tags.n_bytes_lsb;
@@ -350,6 +369,7 @@ static int yaffs_tags_compat_query_block(struct yaffs_dev *dev,
 
        *seq_number = 0;
 
+       /* Look for bad block markers in the first two chunks */
        yaffs_rd_chunk_nand(dev, block_no * dev->param.chunks_per_block,
                            NULL, &spare0, &dummy, 0);
        yaffs_rd_chunk_nand(dev, block_no * dev->param.chunks_per_block + 1,
@@ -369,12 +389,12 @@ void yaffs_tags_compat_install(struct yaffs_dev *dev)
 {
        if(dev->param.is_yaffs2)
                return;
-       if(!dev->param.write_chunk_tags_fn)
-               dev->param.write_chunk_tags_fn = yaffs_tags_compat_wr;
-       if(!dev->param.read_chunk_tags_fn)
-               dev->param.read_chunk_tags_fn = yaffs_tags_compat_rd;
-       if(!dev->param.query_block_fn)
-               dev->param.query_block_fn = yaffs_tags_compat_query_block;
-       if(!dev->param.mark_bad_fn)
-               dev->param.mark_bad_fn = yaffs_tags_compat_mark_bad;
+       if(!dev->tagger.write_chunk_tags_fn)
+               dev->tagger.write_chunk_tags_fn = yaffs_tags_compat_wr;
+       if(!dev->tagger.read_chunk_tags_fn)
+               dev->tagger.read_chunk_tags_fn = yaffs_tags_compat_rd;
+       if(!dev->tagger.query_block_fn)
+               dev->tagger.query_block_fn = yaffs_tags_compat_query_block;
+       if(!dev->tagger.mark_bad_fn)
+               dev->tagger.mark_bad_fn = yaffs_tags_compat_mark_bad;
 }