1 /***************************************************************************
2  * Copyright (c) 2024 Microsoft Corporation
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the MIT License which is available at
6  * https://opensource.org/licenses/MIT.
7  *
8  * SPDX-License-Identifier: MIT
9  **************************************************************************/
10 
11 
12 /**************************************************************************/
13 /**************************************************************************/
14 /**                                                                       */
15 /** LevelX Component                                                      */
16 /**                                                                       */
17 /**   NAND Flash                                                          */
18 /**                                                                       */
19 /**************************************************************************/
20 /**************************************************************************/
21 
22 #define LX_SOURCE_CODE
23 
24 
25 /* Disable ThreadX error checking.  */
26 
27 #ifndef LX_DISABLE_ERROR_CHECKING
28 #define LX_DISABLE_ERROR_CHECKING
29 #endif
30 
31 
32 /* Include necessary system files.  */
33 
34 #include "lx_api.h"
35 
36 
37 /**************************************************************************/
38 /*                                                                        */
39 /*  FUNCTION                                               RELEASE        */
40 /*                                                                        */
41 /*    _lx_nand_flash_256byte_ecc_compute                  PORTABLE C      */
42 /*                                                           6.2.1       */
43 /*  AUTHOR                                                                */
44 /*                                                                        */
45 /*    William E. Lamie, Microsoft Corporation                             */
46 /*                                                                        */
47 /*  DESCRIPTION                                                           */
48 /*                                                                        */
49 /*    This function computes the ECC for 256 bytes of a NAND flash page.  */
50 /*    The resulting ECC code is returned in 3 bytes.                      */
51 /*                                                                        */
52 /*  INPUT                                                                 */
53 /*                                                                        */
54 /*    page_buffer                           Page buffer                   */
55 /*    ecc_buffer                            Returned ECC buffer           */
56 /*                                                                        */
57 /*  OUTPUT                                                                */
58 /*                                                                        */
59 /*    return status                                                       */
60 /*                                                                        */
61 /*  CALLS                                                                 */
62 /*                                                                        */
63 /*    None                                                                */
64 /*                                                                        */
65 /*  CALLED BY                                                             */
66 /*                                                                        */
67 /*    _lx_nand_flash_page_ecc_compute       NAND page ECC compute         */
68 /*    _lx_nand_flash_256byte_ecc_check      Check 256 bytes and ECC       */
69 /*                                                                        */
70 /*  RELEASE HISTORY                                                       */
71 /*                                                                        */
72 /*    DATE              NAME                      DESCRIPTION             */
73 /*                                                                        */
74 /*  05-19-2020     William E. Lamie         Initial Version 6.0           */
75 /*  09-30-2020     William E. Lamie         Modified comment(s),          */
76 /*                                            resulting in version 6.1    */
77 /*  06-02-2021     Bhupendra Naphade        Modified comment(s),          */
78 /*                                            resulting in version 6.1.7  */
79 /*  03-08-2023     Xiuwen Cai               Modified comment(s),          */
80 /*                                            inverted output,            */
81 /*                                            resulting in version 6.2.1 */
82 /*                                                                        */
83 /**************************************************************************/
_lx_nand_flash_256byte_ecc_compute(UCHAR * page_buffer,UCHAR * ecc_buffer)84 UINT  _lx_nand_flash_256byte_ecc_compute(UCHAR *page_buffer, UCHAR *ecc_buffer)
85 {
86 
87 USHORT      i, j;
88 USHORT      *data;
89 USHORT      bits, mask;
90 USHORT      bit_parity;
91 USHORT      even_bit_parity;
92 USHORT      odd_bit_parity;
93 USHORT      even_byte_parity;
94 USHORT      odd_byte_parity;
95 
96 
97     /* Initialize local variables.  */
98     bit_parity =       0;
99     even_bit_parity =  0;
100     odd_bit_parity =   0;
101     even_byte_parity = 0;
102     odd_byte_parity =  0;
103 
104     /* Initialize the return ECC code area.  */
105     ecc_buffer[0]=  0;
106     ecc_buffer[1]=  0;
107     ecc_buffer[2]=  0;
108 
109     /* Setup a 16-bit pointer to the buffer area.  */
110     data =  (USHORT *) page_buffer;
111 
112     /* Loop through the 256 byte buffer, 16 bits at a time.  */
113     for (i = 0; i < 128; i++)
114     {
115 
116         /* Compute the ECC value.  */
117         bit_parity = bit_parity ^ data[i];
118 
119         /* Now count the bits in the current data word.  */
120         bits =  0;
121         mask =  1;
122         for (j = 0; j < 16; j++)
123         {
124 
125             /* Is the bit set?  */
126             if (data[i] & mask)
127             {
128 
129                 /* Yes, increment the bit count.  */
130                 bits++;
131             }
132 
133             /* Move the mask to the next bit.  */
134             mask = (USHORT) ((mask << 1) & 0xFFFF);
135         }
136 
137         /* Determine if the number of bits is odd.  */
138         if ((bits & 1) == 1)
139         {
140 
141             /* Odd number of bits.  Adjust the odd/even byte parity.  */
142             even_byte_parity = (USHORT) ((even_byte_parity ^ (0xffff - i)) & 0xFFFF);
143             odd_byte_parity = odd_byte_parity ^ i;
144         }
145     }
146 
147     /* Now look for bits set in the bit parity.  */
148     for (i = 0; i < 16; i++)
149     {
150 
151         /* Is the bit set?  */
152         if (bit_parity & 1)
153         {
154 
155             /* Yes, adjust the odd even byte parity.  */
156             even_bit_parity = (USHORT) ((even_bit_parity ^ (15 - i)) & 0xFFFF);
157             odd_bit_parity =   odd_bit_parity ^ i;
158         }
159 
160         /* Look at next bit position.  */
161         bit_parity =  bit_parity >> 1;
162     }
163 
164     /* At this point, we need to pack the 22 ECC bits into the 3 byte return area.  */
165 
166     /* Pack bit 21.  */
167     ecc_buffer[(21+2)/8] = ((UCHAR)(ecc_buffer[(21+2)/8] | ((odd_byte_parity >> 6) & 1) << (21+2)%8) & 0xFF);
168 
169     /* Pack bit 20.  */
170     ecc_buffer[(20+2)/8] = ((UCHAR)(ecc_buffer[(20+2)/8] | ((even_byte_parity >> 6) & 1) << (20+2)%8) & 0xFF);
171 
172     /* Pack bit 19.  */
173     ecc_buffer[(19+2)/8] = ((UCHAR)(ecc_buffer[(19+2)/8] | ((odd_byte_parity >> 5) & 1) << (19+2)%8) & 0xFF);
174 
175     /* Pack bit 18.  */
176     ecc_buffer[(18+2)/8] = ((UCHAR)(ecc_buffer[(18+2)/8] | ((even_byte_parity >> 5) & 1) << (18+2)%8) & 0xFF);
177 
178     /* Pack bit 17.  */
179     ecc_buffer[(17+2)/8] = ((UCHAR)(ecc_buffer[(17+2)/8] | ((odd_byte_parity >> 4) & 1) << (17+2)%8) & 0xFF);
180 
181     /* Pack bit 16.  */
182     ecc_buffer[(16+2)/8] = ((UCHAR)(ecc_buffer[(16+2)/8] | ((even_byte_parity >> 4) & 1) << (16+2)%8) & 0xFF);
183 
184     /* Pack bit 15.  */
185     ecc_buffer[(15+2)/8] = ((UCHAR)(ecc_buffer[(15+2)/8] | ((odd_byte_parity >> 3) & 1) << (15+2)%8) & 0xFF);
186 
187     /* Pack bit 14.  */
188     ecc_buffer[(14+2)/8] = ((UCHAR)(ecc_buffer[(14+2)/8] | ((even_byte_parity >> 3) & 1) << (14+2)%8) & 0xFF);
189 
190     /* Pack bit 13.  */
191     ecc_buffer[(13+2)/8] = ((UCHAR)(ecc_buffer[(13+2)/8] | ((odd_byte_parity >> 2) & 1) << (13+2)%8) & 0xFF);
192 
193     /* Pack bit 12.  */
194     ecc_buffer[(12+2)/8] = ((UCHAR)(ecc_buffer[(12+2)/8] | ((even_byte_parity >> 2) & 1) << (12+2)%8) & 0xFF);
195 
196     /* Pack bit 11.  */
197     ecc_buffer[(11+2)/8] = ((UCHAR)(ecc_buffer[(11+2)/8] | ((odd_byte_parity >> 1) & 1) << (11+2)%8) & 0xFF);
198 
199     /* Pack bit 10.  */
200     ecc_buffer[(10+2)/8] = ((UCHAR)(ecc_buffer[(10+2)/8] | ((even_byte_parity >> 1) & 1) << (10+2)%8) & 0xFF);
201 
202     /* Pack bit 9.  */
203     ecc_buffer[(9+2)/8] = ((UCHAR)(ecc_buffer[(9+2)/8] | ((odd_byte_parity >> 0) & 1) << (9+2)%8) & 0xFF);
204 
205     /* Pack bit 8.  */
206     ecc_buffer[(8+2)/8] = ((UCHAR)(ecc_buffer[(8+2)/8] | ((even_byte_parity >> 0) & 1) << (8+2)%8) & 0xFF);
207 
208     /* Pack bit 7.  */
209     ecc_buffer[(7+2)/8] = ((UCHAR)(ecc_buffer[(7+2)/8] | ((odd_bit_parity >> 3) & 1) << (7+2)%8) & 0xFF);
210 
211     /* Pack bit 6.  */
212     ecc_buffer[(6+2)/8] = ((UCHAR)(ecc_buffer[(6+2)/8] | ((even_bit_parity >> 3) & 1) << (6+2)%8) & 0xFF);
213 
214     /* Pack bit 5.  */
215     ecc_buffer[(5+2)/8] = ((UCHAR)(ecc_buffer[(5+2)/8] | ((odd_bit_parity >> 2) & 1) << (5+2)%8) & 0xFF);
216 
217     /* Pack bit 4.  */
218     ecc_buffer[(4+2)/8] = ((UCHAR)(ecc_buffer[(4+2)/8] | ((even_bit_parity >> 2) & 1) << (4+2)%8) & 0xFF);
219 
220     /* Pack bit 3.  */
221     ecc_buffer[(3+2)/8] = ((UCHAR)(ecc_buffer[(3+2)/8] | ((odd_bit_parity >> 1) & 1) << (3+2)%8) & 0xFF);
222 
223     /* Pack bit 2.  */
224     ecc_buffer[(2+2)/8] = ((UCHAR)(ecc_buffer[(2+2)/8] | ((even_bit_parity >> 1) & 1) << (2+2)%8) & 0xFF);
225 
226     /* Pack bit 1.  */
227     ecc_buffer[(1+2)/8] = ((UCHAR)(ecc_buffer[(1+2)/8] | ((odd_bit_parity >> 0) & 1) << (1+2)%8) & 0xFF);
228 
229     /* Pack bit 0.  */
230     ecc_buffer[(0+2)/8] = ((UCHAR)(ecc_buffer[(0+2)/8] | ((even_bit_parity >> 0) & 1) << (0+2)%8) & 0xFF);
231 
232     ecc_buffer[0] = (UCHAR)~ecc_buffer[0];
233     ecc_buffer[1] = (UCHAR)~ecc_buffer[1];
234     ecc_buffer[2] = (UCHAR)~ecc_buffer[2];
235 
236     /* Return success!  */
237     return(LX_SUCCESS);
238 }
239 
240