ecc.c (3038B)
1/* 2 * Calculate Error-correcting Codes. Used by NAND Flash controllers 3 * (not by NAND chips). 4 * 5 * Copyright (c) 2006 Openedhand Ltd. 6 * Written by Andrzej Zaborowski <balrog@zabor.org> 7 * 8 * This code is licensed under the GNU GPL v2. 9 * 10 * Contributions after 2012-01-13 are licensed under the terms of the 11 * GNU GPL, version 2 or (at your option) any later version. 12 */ 13 14#include "qemu/osdep.h" 15#include "migration/vmstate.h" 16#include "hw/block/flash.h" 17 18/* 19 * Pre-calculated 256-way 1 byte column parity. Table borrowed from Linux. 20 */ 21static const uint8_t nand_ecc_precalc_table[] = { 22 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 23 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00, 24 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 25 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65, 26 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 27 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66, 28 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 29 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03, 30 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 31 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69, 32 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 33 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c, 34 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 35 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f, 36 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 37 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a, 38 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 39 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a, 40 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 41 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f, 42 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 43 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c, 44 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 45 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69, 46 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 47 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03, 48 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 49 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66, 50 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 51 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65, 52 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 53 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00, 54}; 55 56/* Update ECC parity count. */ 57uint8_t ecc_digest(ECCState *s, uint8_t sample) 58{ 59 uint8_t idx = nand_ecc_precalc_table[sample]; 60 61 s->cp ^= idx & 0x3f; 62 if (idx & 0x40) { 63 s->lp[0] ^= ~s->count; 64 s->lp[1] ^= s->count; 65 } 66 s->count ++; 67 68 return sample; 69} 70 71/* Reinitialise the counters. */ 72void ecc_reset(ECCState *s) 73{ 74 s->lp[0] = 0x0000; 75 s->lp[1] = 0x0000; 76 s->cp = 0x00; 77 s->count = 0; 78} 79 80/* Save/restore */ 81const VMStateDescription vmstate_ecc_state = { 82 .name = "ecc-state", 83 .version_id = 0, 84 .minimum_version_id = 0, 85 .fields = (VMStateField[]) { 86 VMSTATE_UINT8(cp, ECCState), 87 VMSTATE_UINT16_ARRAY(lp, ECCState, 2), 88 VMSTATE_UINT16(count, ECCState), 89 VMSTATE_END_OF_LIST(), 90 }, 91};