1*0e8cc8bdSWilliam Juul /* 2*0e8cc8bdSWilliam Juul * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. 3*0e8cc8bdSWilliam Juul * 4*0e8cc8bdSWilliam Juul * Copyright (C) 2002-2007 Aleph One Ltd. 5*0e8cc8bdSWilliam Juul * for Toby Churchill Ltd and Brightstar Engineering 6*0e8cc8bdSWilliam Juul * 7*0e8cc8bdSWilliam Juul * Created by Charles Manning <charles@aleph1.co.uk> 8*0e8cc8bdSWilliam Juul * 9*0e8cc8bdSWilliam Juul * This program is free software; you can redistribute it and/or modify 10*0e8cc8bdSWilliam Juul * it under the terms of the GNU General Public License version 2 as 11*0e8cc8bdSWilliam Juul * published by the Free Software Foundation. 12*0e8cc8bdSWilliam Juul */ 13*0e8cc8bdSWilliam Juul 14*0e8cc8bdSWilliam Juul /* 15*0e8cc8bdSWilliam Juul * This code implements the ECC algorithm used in SmartMedia. 16*0e8cc8bdSWilliam Juul * 17*0e8cc8bdSWilliam Juul * The ECC comprises 22 bits of parity information and is stuffed into 3 bytes. 18*0e8cc8bdSWilliam Juul * The two unused bit are set to 1. 19*0e8cc8bdSWilliam Juul * The ECC can correct single bit errors in a 256-byte page of data. Thus, two such ECC 20*0e8cc8bdSWilliam Juul * blocks are used on a 512-byte NAND page. 21*0e8cc8bdSWilliam Juul * 22*0e8cc8bdSWilliam Juul */ 23*0e8cc8bdSWilliam Juul 24*0e8cc8bdSWilliam Juul /* Table generated by gen-ecc.c 25*0e8cc8bdSWilliam Juul * Using a table means we do not have to calculate p1..p4 and p1'..p4' 26*0e8cc8bdSWilliam Juul * for each byte of data. These are instead provided in a table in bits7..2. 27*0e8cc8bdSWilliam Juul * Bit 0 of each entry indicates whether the entry has an odd or even parity, and therefore 28*0e8cc8bdSWilliam Juul * this bytes influence on the line parity. 29*0e8cc8bdSWilliam Juul */ 30*0e8cc8bdSWilliam Juul 31*0e8cc8bdSWilliam Juul const char *yaffs_ecc_c_version = 32*0e8cc8bdSWilliam Juul "$Id: yaffs_ecc.c,v 1.9 2007/02/14 01:09:06 wookey Exp $"; 33*0e8cc8bdSWilliam Juul 34*0e8cc8bdSWilliam Juul #include "yportenv.h" 35*0e8cc8bdSWilliam Juul 36*0e8cc8bdSWilliam Juul #include "yaffs_ecc.h" 37*0e8cc8bdSWilliam Juul 38*0e8cc8bdSWilliam Juul static const unsigned char column_parity_table[] = { 39*0e8cc8bdSWilliam Juul 0x00, 0x55, 0x59, 0x0c, 0x65, 0x30, 0x3c, 0x69, 40*0e8cc8bdSWilliam Juul 0x69, 0x3c, 0x30, 0x65, 0x0c, 0x59, 0x55, 0x00, 41*0e8cc8bdSWilliam Juul 0x95, 0xc0, 0xcc, 0x99, 0xf0, 0xa5, 0xa9, 0xfc, 42*0e8cc8bdSWilliam Juul 0xfc, 0xa9, 0xa5, 0xf0, 0x99, 0xcc, 0xc0, 0x95, 43*0e8cc8bdSWilliam Juul 0x99, 0xcc, 0xc0, 0x95, 0xfc, 0xa9, 0xa5, 0xf0, 44*0e8cc8bdSWilliam Juul 0xf0, 0xa5, 0xa9, 0xfc, 0x95, 0xc0, 0xcc, 0x99, 45*0e8cc8bdSWilliam Juul 0x0c, 0x59, 0x55, 0x00, 0x69, 0x3c, 0x30, 0x65, 46*0e8cc8bdSWilliam Juul 0x65, 0x30, 0x3c, 0x69, 0x00, 0x55, 0x59, 0x0c, 47*0e8cc8bdSWilliam Juul 0xa5, 0xf0, 0xfc, 0xa9, 0xc0, 0x95, 0x99, 0xcc, 48*0e8cc8bdSWilliam Juul 0xcc, 0x99, 0x95, 0xc0, 0xa9, 0xfc, 0xf0, 0xa5, 49*0e8cc8bdSWilliam Juul 0x30, 0x65, 0x69, 0x3c, 0x55, 0x00, 0x0c, 0x59, 50*0e8cc8bdSWilliam Juul 0x59, 0x0c, 0x00, 0x55, 0x3c, 0x69, 0x65, 0x30, 51*0e8cc8bdSWilliam Juul 0x3c, 0x69, 0x65, 0x30, 0x59, 0x0c, 0x00, 0x55, 52*0e8cc8bdSWilliam Juul 0x55, 0x00, 0x0c, 0x59, 0x30, 0x65, 0x69, 0x3c, 53*0e8cc8bdSWilliam Juul 0xa9, 0xfc, 0xf0, 0xa5, 0xcc, 0x99, 0x95, 0xc0, 54*0e8cc8bdSWilliam Juul 0xc0, 0x95, 0x99, 0xcc, 0xa5, 0xf0, 0xfc, 0xa9, 55*0e8cc8bdSWilliam Juul 0xa9, 0xfc, 0xf0, 0xa5, 0xcc, 0x99, 0x95, 0xc0, 56*0e8cc8bdSWilliam Juul 0xc0, 0x95, 0x99, 0xcc, 0xa5, 0xf0, 0xfc, 0xa9, 57*0e8cc8bdSWilliam Juul 0x3c, 0x69, 0x65, 0x30, 0x59, 0x0c, 0x00, 0x55, 58*0e8cc8bdSWilliam Juul 0x55, 0x00, 0x0c, 0x59, 0x30, 0x65, 0x69, 0x3c, 59*0e8cc8bdSWilliam Juul 0x30, 0x65, 0x69, 0x3c, 0x55, 0x00, 0x0c, 0x59, 60*0e8cc8bdSWilliam Juul 0x59, 0x0c, 0x00, 0x55, 0x3c, 0x69, 0x65, 0x30, 61*0e8cc8bdSWilliam Juul 0xa5, 0xf0, 0xfc, 0xa9, 0xc0, 0x95, 0x99, 0xcc, 62*0e8cc8bdSWilliam Juul 0xcc, 0x99, 0x95, 0xc0, 0xa9, 0xfc, 0xf0, 0xa5, 63*0e8cc8bdSWilliam Juul 0x0c, 0x59, 0x55, 0x00, 0x69, 0x3c, 0x30, 0x65, 64*0e8cc8bdSWilliam Juul 0x65, 0x30, 0x3c, 0x69, 0x00, 0x55, 0x59, 0x0c, 65*0e8cc8bdSWilliam Juul 0x99, 0xcc, 0xc0, 0x95, 0xfc, 0xa9, 0xa5, 0xf0, 66*0e8cc8bdSWilliam Juul 0xf0, 0xa5, 0xa9, 0xfc, 0x95, 0xc0, 0xcc, 0x99, 67*0e8cc8bdSWilliam Juul 0x95, 0xc0, 0xcc, 0x99, 0xf0, 0xa5, 0xa9, 0xfc, 68*0e8cc8bdSWilliam Juul 0xfc, 0xa9, 0xa5, 0xf0, 0x99, 0xcc, 0xc0, 0x95, 69*0e8cc8bdSWilliam Juul 0x00, 0x55, 0x59, 0x0c, 0x65, 0x30, 0x3c, 0x69, 70*0e8cc8bdSWilliam Juul 0x69, 0x3c, 0x30, 0x65, 0x0c, 0x59, 0x55, 0x00, 71*0e8cc8bdSWilliam Juul }; 72*0e8cc8bdSWilliam Juul 73*0e8cc8bdSWilliam Juul /* Count the bits in an unsigned char or a U32 */ 74*0e8cc8bdSWilliam Juul 75*0e8cc8bdSWilliam Juul static int yaffs_CountBits(unsigned char x) 76*0e8cc8bdSWilliam Juul { 77*0e8cc8bdSWilliam Juul int r = 0; 78*0e8cc8bdSWilliam Juul while (x) { 79*0e8cc8bdSWilliam Juul if (x & 1) 80*0e8cc8bdSWilliam Juul r++; 81*0e8cc8bdSWilliam Juul x >>= 1; 82*0e8cc8bdSWilliam Juul } 83*0e8cc8bdSWilliam Juul return r; 84*0e8cc8bdSWilliam Juul } 85*0e8cc8bdSWilliam Juul 86*0e8cc8bdSWilliam Juul static int yaffs_CountBits32(unsigned x) 87*0e8cc8bdSWilliam Juul { 88*0e8cc8bdSWilliam Juul int r = 0; 89*0e8cc8bdSWilliam Juul while (x) { 90*0e8cc8bdSWilliam Juul if (x & 1) 91*0e8cc8bdSWilliam Juul r++; 92*0e8cc8bdSWilliam Juul x >>= 1; 93*0e8cc8bdSWilliam Juul } 94*0e8cc8bdSWilliam Juul return r; 95*0e8cc8bdSWilliam Juul } 96*0e8cc8bdSWilliam Juul 97*0e8cc8bdSWilliam Juul /* Calculate the ECC for a 256-byte block of data */ 98*0e8cc8bdSWilliam Juul void yaffs_ECCCalculate(const unsigned char *data, unsigned char *ecc) 99*0e8cc8bdSWilliam Juul { 100*0e8cc8bdSWilliam Juul unsigned int i; 101*0e8cc8bdSWilliam Juul 102*0e8cc8bdSWilliam Juul unsigned char col_parity = 0; 103*0e8cc8bdSWilliam Juul unsigned char line_parity = 0; 104*0e8cc8bdSWilliam Juul unsigned char line_parity_prime = 0; 105*0e8cc8bdSWilliam Juul unsigned char t; 106*0e8cc8bdSWilliam Juul unsigned char b; 107*0e8cc8bdSWilliam Juul 108*0e8cc8bdSWilliam Juul for (i = 0; i < 256; i++) { 109*0e8cc8bdSWilliam Juul b = column_parity_table[*data++]; 110*0e8cc8bdSWilliam Juul col_parity ^= b; 111*0e8cc8bdSWilliam Juul 112*0e8cc8bdSWilliam Juul if (b & 0x01) // odd number of bits in the byte 113*0e8cc8bdSWilliam Juul { 114*0e8cc8bdSWilliam Juul line_parity ^= i; 115*0e8cc8bdSWilliam Juul line_parity_prime ^= ~i; 116*0e8cc8bdSWilliam Juul } 117*0e8cc8bdSWilliam Juul 118*0e8cc8bdSWilliam Juul } 119*0e8cc8bdSWilliam Juul 120*0e8cc8bdSWilliam Juul ecc[2] = (~col_parity) | 0x03; 121*0e8cc8bdSWilliam Juul 122*0e8cc8bdSWilliam Juul t = 0; 123*0e8cc8bdSWilliam Juul if (line_parity & 0x80) 124*0e8cc8bdSWilliam Juul t |= 0x80; 125*0e8cc8bdSWilliam Juul if (line_parity_prime & 0x80) 126*0e8cc8bdSWilliam Juul t |= 0x40; 127*0e8cc8bdSWilliam Juul if (line_parity & 0x40) 128*0e8cc8bdSWilliam Juul t |= 0x20; 129*0e8cc8bdSWilliam Juul if (line_parity_prime & 0x40) 130*0e8cc8bdSWilliam Juul t |= 0x10; 131*0e8cc8bdSWilliam Juul if (line_parity & 0x20) 132*0e8cc8bdSWilliam Juul t |= 0x08; 133*0e8cc8bdSWilliam Juul if (line_parity_prime & 0x20) 134*0e8cc8bdSWilliam Juul t |= 0x04; 135*0e8cc8bdSWilliam Juul if (line_parity & 0x10) 136*0e8cc8bdSWilliam Juul t |= 0x02; 137*0e8cc8bdSWilliam Juul if (line_parity_prime & 0x10) 138*0e8cc8bdSWilliam Juul t |= 0x01; 139*0e8cc8bdSWilliam Juul ecc[1] = ~t; 140*0e8cc8bdSWilliam Juul 141*0e8cc8bdSWilliam Juul t = 0; 142*0e8cc8bdSWilliam Juul if (line_parity & 0x08) 143*0e8cc8bdSWilliam Juul t |= 0x80; 144*0e8cc8bdSWilliam Juul if (line_parity_prime & 0x08) 145*0e8cc8bdSWilliam Juul t |= 0x40; 146*0e8cc8bdSWilliam Juul if (line_parity & 0x04) 147*0e8cc8bdSWilliam Juul t |= 0x20; 148*0e8cc8bdSWilliam Juul if (line_parity_prime & 0x04) 149*0e8cc8bdSWilliam Juul t |= 0x10; 150*0e8cc8bdSWilliam Juul if (line_parity & 0x02) 151*0e8cc8bdSWilliam Juul t |= 0x08; 152*0e8cc8bdSWilliam Juul if (line_parity_prime & 0x02) 153*0e8cc8bdSWilliam Juul t |= 0x04; 154*0e8cc8bdSWilliam Juul if (line_parity & 0x01) 155*0e8cc8bdSWilliam Juul t |= 0x02; 156*0e8cc8bdSWilliam Juul if (line_parity_prime & 0x01) 157*0e8cc8bdSWilliam Juul t |= 0x01; 158*0e8cc8bdSWilliam Juul ecc[0] = ~t; 159*0e8cc8bdSWilliam Juul 160*0e8cc8bdSWilliam Juul #ifdef CONFIG_YAFFS_ECC_WRONG_ORDER 161*0e8cc8bdSWilliam Juul // Swap the bytes into the wrong order 162*0e8cc8bdSWilliam Juul t = ecc[0]; 163*0e8cc8bdSWilliam Juul ecc[0] = ecc[1]; 164*0e8cc8bdSWilliam Juul ecc[1] = t; 165*0e8cc8bdSWilliam Juul #endif 166*0e8cc8bdSWilliam Juul } 167*0e8cc8bdSWilliam Juul 168*0e8cc8bdSWilliam Juul 169*0e8cc8bdSWilliam Juul /* Correct the ECC on a 256 byte block of data */ 170*0e8cc8bdSWilliam Juul 171*0e8cc8bdSWilliam Juul int yaffs_ECCCorrect(unsigned char *data, unsigned char *read_ecc, 172*0e8cc8bdSWilliam Juul const unsigned char *test_ecc) 173*0e8cc8bdSWilliam Juul { 174*0e8cc8bdSWilliam Juul unsigned char d0, d1, d2; /* deltas */ 175*0e8cc8bdSWilliam Juul 176*0e8cc8bdSWilliam Juul d0 = read_ecc[0] ^ test_ecc[0]; 177*0e8cc8bdSWilliam Juul d1 = read_ecc[1] ^ test_ecc[1]; 178*0e8cc8bdSWilliam Juul d2 = read_ecc[2] ^ test_ecc[2]; 179*0e8cc8bdSWilliam Juul 180*0e8cc8bdSWilliam Juul if ((d0 | d1 | d2) == 0) 181*0e8cc8bdSWilliam Juul return 0; /* no error */ 182*0e8cc8bdSWilliam Juul 183*0e8cc8bdSWilliam Juul if (((d0 ^ (d0 >> 1)) & 0x55) == 0x55 && 184*0e8cc8bdSWilliam Juul ((d1 ^ (d1 >> 1)) & 0x55) == 0x55 && 185*0e8cc8bdSWilliam Juul ((d2 ^ (d2 >> 1)) & 0x54) == 0x54) { 186*0e8cc8bdSWilliam Juul /* Single bit (recoverable) error in data */ 187*0e8cc8bdSWilliam Juul 188*0e8cc8bdSWilliam Juul unsigned byte; 189*0e8cc8bdSWilliam Juul unsigned bit; 190*0e8cc8bdSWilliam Juul 191*0e8cc8bdSWilliam Juul #ifdef CONFIG_YAFFS_ECC_WRONG_ORDER 192*0e8cc8bdSWilliam Juul // swap the bytes to correct for the wrong order 193*0e8cc8bdSWilliam Juul unsigned char t; 194*0e8cc8bdSWilliam Juul 195*0e8cc8bdSWilliam Juul t = d0; 196*0e8cc8bdSWilliam Juul d0 = d1; 197*0e8cc8bdSWilliam Juul d1 = t; 198*0e8cc8bdSWilliam Juul #endif 199*0e8cc8bdSWilliam Juul 200*0e8cc8bdSWilliam Juul bit = byte = 0; 201*0e8cc8bdSWilliam Juul 202*0e8cc8bdSWilliam Juul if (d1 & 0x80) 203*0e8cc8bdSWilliam Juul byte |= 0x80; 204*0e8cc8bdSWilliam Juul if (d1 & 0x20) 205*0e8cc8bdSWilliam Juul byte |= 0x40; 206*0e8cc8bdSWilliam Juul if (d1 & 0x08) 207*0e8cc8bdSWilliam Juul byte |= 0x20; 208*0e8cc8bdSWilliam Juul if (d1 & 0x02) 209*0e8cc8bdSWilliam Juul byte |= 0x10; 210*0e8cc8bdSWilliam Juul if (d0 & 0x80) 211*0e8cc8bdSWilliam Juul byte |= 0x08; 212*0e8cc8bdSWilliam Juul if (d0 & 0x20) 213*0e8cc8bdSWilliam Juul byte |= 0x04; 214*0e8cc8bdSWilliam Juul if (d0 & 0x08) 215*0e8cc8bdSWilliam Juul byte |= 0x02; 216*0e8cc8bdSWilliam Juul if (d0 & 0x02) 217*0e8cc8bdSWilliam Juul byte |= 0x01; 218*0e8cc8bdSWilliam Juul 219*0e8cc8bdSWilliam Juul if (d2 & 0x80) 220*0e8cc8bdSWilliam Juul bit |= 0x04; 221*0e8cc8bdSWilliam Juul if (d2 & 0x20) 222*0e8cc8bdSWilliam Juul bit |= 0x02; 223*0e8cc8bdSWilliam Juul if (d2 & 0x08) 224*0e8cc8bdSWilliam Juul bit |= 0x01; 225*0e8cc8bdSWilliam Juul 226*0e8cc8bdSWilliam Juul data[byte] ^= (1 << bit); 227*0e8cc8bdSWilliam Juul 228*0e8cc8bdSWilliam Juul return 1; /* Corrected the error */ 229*0e8cc8bdSWilliam Juul } 230*0e8cc8bdSWilliam Juul 231*0e8cc8bdSWilliam Juul if ((yaffs_CountBits(d0) + 232*0e8cc8bdSWilliam Juul yaffs_CountBits(d1) + 233*0e8cc8bdSWilliam Juul yaffs_CountBits(d2)) == 1) { 234*0e8cc8bdSWilliam Juul /* Reccoverable error in ecc */ 235*0e8cc8bdSWilliam Juul 236*0e8cc8bdSWilliam Juul read_ecc[0] = test_ecc[0]; 237*0e8cc8bdSWilliam Juul read_ecc[1] = test_ecc[1]; 238*0e8cc8bdSWilliam Juul read_ecc[2] = test_ecc[2]; 239*0e8cc8bdSWilliam Juul 240*0e8cc8bdSWilliam Juul return 1; /* Corrected the error */ 241*0e8cc8bdSWilliam Juul } 242*0e8cc8bdSWilliam Juul 243*0e8cc8bdSWilliam Juul /* Unrecoverable error */ 244*0e8cc8bdSWilliam Juul 245*0e8cc8bdSWilliam Juul return -1; 246*0e8cc8bdSWilliam Juul 247*0e8cc8bdSWilliam Juul } 248*0e8cc8bdSWilliam Juul 249*0e8cc8bdSWilliam Juul 250*0e8cc8bdSWilliam Juul /* 251*0e8cc8bdSWilliam Juul * ECCxxxOther does ECC calcs on arbitrary n bytes of data 252*0e8cc8bdSWilliam Juul */ 253*0e8cc8bdSWilliam Juul void yaffs_ECCCalculateOther(const unsigned char *data, unsigned nBytes, 254*0e8cc8bdSWilliam Juul yaffs_ECCOther * eccOther) 255*0e8cc8bdSWilliam Juul { 256*0e8cc8bdSWilliam Juul unsigned int i; 257*0e8cc8bdSWilliam Juul 258*0e8cc8bdSWilliam Juul unsigned char col_parity = 0; 259*0e8cc8bdSWilliam Juul unsigned line_parity = 0; 260*0e8cc8bdSWilliam Juul unsigned line_parity_prime = 0; 261*0e8cc8bdSWilliam Juul unsigned char b; 262*0e8cc8bdSWilliam Juul 263*0e8cc8bdSWilliam Juul for (i = 0; i < nBytes; i++) { 264*0e8cc8bdSWilliam Juul b = column_parity_table[*data++]; 265*0e8cc8bdSWilliam Juul col_parity ^= b; 266*0e8cc8bdSWilliam Juul 267*0e8cc8bdSWilliam Juul if (b & 0x01) { 268*0e8cc8bdSWilliam Juul /* odd number of bits in the byte */ 269*0e8cc8bdSWilliam Juul line_parity ^= i; 270*0e8cc8bdSWilliam Juul line_parity_prime ^= ~i; 271*0e8cc8bdSWilliam Juul } 272*0e8cc8bdSWilliam Juul 273*0e8cc8bdSWilliam Juul } 274*0e8cc8bdSWilliam Juul 275*0e8cc8bdSWilliam Juul eccOther->colParity = (col_parity >> 2) & 0x3f; 276*0e8cc8bdSWilliam Juul eccOther->lineParity = line_parity; 277*0e8cc8bdSWilliam Juul eccOther->lineParityPrime = line_parity_prime; 278*0e8cc8bdSWilliam Juul } 279*0e8cc8bdSWilliam Juul 280*0e8cc8bdSWilliam Juul int yaffs_ECCCorrectOther(unsigned char *data, unsigned nBytes, 281*0e8cc8bdSWilliam Juul yaffs_ECCOther * read_ecc, 282*0e8cc8bdSWilliam Juul const yaffs_ECCOther * test_ecc) 283*0e8cc8bdSWilliam Juul { 284*0e8cc8bdSWilliam Juul unsigned char cDelta; /* column parity delta */ 285*0e8cc8bdSWilliam Juul unsigned lDelta; /* line parity delta */ 286*0e8cc8bdSWilliam Juul unsigned lDeltaPrime; /* line parity delta */ 287*0e8cc8bdSWilliam Juul unsigned bit; 288*0e8cc8bdSWilliam Juul 289*0e8cc8bdSWilliam Juul cDelta = read_ecc->colParity ^ test_ecc->colParity; 290*0e8cc8bdSWilliam Juul lDelta = read_ecc->lineParity ^ test_ecc->lineParity; 291*0e8cc8bdSWilliam Juul lDeltaPrime = read_ecc->lineParityPrime ^ test_ecc->lineParityPrime; 292*0e8cc8bdSWilliam Juul 293*0e8cc8bdSWilliam Juul if ((cDelta | lDelta | lDeltaPrime) == 0) 294*0e8cc8bdSWilliam Juul return 0; /* no error */ 295*0e8cc8bdSWilliam Juul 296*0e8cc8bdSWilliam Juul if (lDelta == ~lDeltaPrime && 297*0e8cc8bdSWilliam Juul (((cDelta ^ (cDelta >> 1)) & 0x15) == 0x15)) 298*0e8cc8bdSWilliam Juul { 299*0e8cc8bdSWilliam Juul /* Single bit (recoverable) error in data */ 300*0e8cc8bdSWilliam Juul 301*0e8cc8bdSWilliam Juul bit = 0; 302*0e8cc8bdSWilliam Juul 303*0e8cc8bdSWilliam Juul if (cDelta & 0x20) 304*0e8cc8bdSWilliam Juul bit |= 0x04; 305*0e8cc8bdSWilliam Juul if (cDelta & 0x08) 306*0e8cc8bdSWilliam Juul bit |= 0x02; 307*0e8cc8bdSWilliam Juul if (cDelta & 0x02) 308*0e8cc8bdSWilliam Juul bit |= 0x01; 309*0e8cc8bdSWilliam Juul 310*0e8cc8bdSWilliam Juul if(lDelta >= nBytes) 311*0e8cc8bdSWilliam Juul return -1; 312*0e8cc8bdSWilliam Juul 313*0e8cc8bdSWilliam Juul data[lDelta] ^= (1 << bit); 314*0e8cc8bdSWilliam Juul 315*0e8cc8bdSWilliam Juul return 1; /* corrected */ 316*0e8cc8bdSWilliam Juul } 317*0e8cc8bdSWilliam Juul 318*0e8cc8bdSWilliam Juul if ((yaffs_CountBits32(lDelta) + yaffs_CountBits32(lDeltaPrime) + 319*0e8cc8bdSWilliam Juul yaffs_CountBits(cDelta)) == 1) { 320*0e8cc8bdSWilliam Juul /* Reccoverable error in ecc */ 321*0e8cc8bdSWilliam Juul 322*0e8cc8bdSWilliam Juul *read_ecc = *test_ecc; 323*0e8cc8bdSWilliam Juul return 1; /* corrected */ 324*0e8cc8bdSWilliam Juul } 325*0e8cc8bdSWilliam Juul 326*0e8cc8bdSWilliam Juul /* Unrecoverable error */ 327*0e8cc8bdSWilliam Juul 328*0e8cc8bdSWilliam Juul return -1; 329*0e8cc8bdSWilliam Juul 330*0e8cc8bdSWilliam Juul } 331*0e8cc8bdSWilliam Juul 332