Here is my vb6 version, dont laugh... hehe
Public Function CalcECC(aData() As Byte, ByVal Start As Long)
Dim i As Long, p As Long
Dim v As Long, val As Long
p = Start
For i = 0 To &H1066 - 1
If (i And &H1F) = 0 Then
If i = &H1000 Then
'Force pointer to beginning of
'metadata for this page
p = Start + &H200
End If
CopyMemory v, aData(p), 4
v = Not v
p = p + 4 'Advance pointer
End If
val = val Xor (v And 1)
v = RShift(v, 1)
If (val And 1) = 1 Then
val = val Xor &H6954559
End If
val = RShift(val, 1)
Next i
val = Not val
aData(Start + &H200 + &HC) = ((aData(Start + &H200 + &HC) And &H3F) Or _
LShift(val, 6)) And &HFF
aData(Start + &H200 + &HD) = RShift(val, 2) And &HFF
aData(Start + &H200 + &HE) = RShift(val, 10) And &HFF
aData(Start + &H200 + &HF) = RShift(val, 18) And &HFF
End Function
Little Endian, Thanks DrMatrix and Seventhson
// Thanks go to DrMatrix for this function.
// I modified it slightly to preserve the block
// type field in the 6 least significant bits of
// spare[0xC]
void calcecc(unsigned long *data, unsigned char *edc)
{
int i=0, val=0;
unsigned long v;
for (i = 0; i < 0x1066; i++)
{
if (!(i & 31))
{
if (i == 0x1000)
data = (unsigned long *)edc;
v = ~*data++; /* byte order: LE */
}
val ^= v & 1;
v>>=1;
if (val & 1)
val ^= 0x6954559;
val >>= 1;
}
val = ~val;
edc[0xC] = ((val << 6) | (edc[0xC] & 0x3F)) & 0xFF;
edc[0xD] = (val >> 2) & 0xFF;
edc[0xE] = (val >> 10) & 0xFF;
edc[0xF] = (val >> 18) & 0xFF;
}
Big Endian 64bit compatible of Previous, for use in Xell for example
// ECC calc function for big endian CPU
void SfcEncodeECC(unsigned int *data, unsigned char *edc) {
int i=0, val=0;
unsigned int v=0;
for (i = 0; i < 0x1066; i++)
{
if (!(i & 31))
{
if (i == 0x1000)
data = (unsigned int *)edc;
v = ~*data++; // byte order: LE
v = bswap_32(v);
}
val ^= v & 1;
v>>=1;
if (val & 1)
val ^= 0x6954559;
val >>= 1;
}
val = ~val;
edc[0xC] = ((val << 6) | (edc[0xC] & 0x3F)) & 0xFF;
edc[0xD] = (val >> 2) & 0xFF;
edc[0xE] = (val >> 10) & 0xFF;
edc[0xF] = (val >> 18) & 0xFF;
}
Source: Microsoft Kernel, extracted for learning
Big Endian of Previous, ppc64 asm, for use in Xell for example
SfcEncodeECC
// %r3=PageData, %r4=MetaData
li %r10, 0
li %r11, 0
li %r9, 0
Location_1:
clrlwi. %r8, %r9, 27
bne Location_3
cmplwi cr6, %r9, 0x1000
bne cr6, Location_2
mr %r3, %r4
Location_2:
mr %r11, %r3
addi %r3, %r3, 4
lwbrx %r11, %r0, %r11
not %r11, %r11
Location_3:
clrlwi %r8, %r11, 31
srwi %r11, %r11, 1
xor %r10, %r8, %r10
clrlwi. %r8, %r10, 31
beq Location_4
xoris %r10, %r10, 0x695
xori %r10, %r10, 0x4559
Location_4:
addi %r9, %r9, 1
srwi %r10, %r10, 1
cmplwi cr6, %r9, 0x1066
blt cr6, Location_1
not %r11, %r10
lbz %r10, 0xC(%r4)
srwi %r9, %r11, 2
srwi %r8, %r11, 10
insrwi %r10, %r11, 26,0
srwi %r11, %r11, 18
stb %r9, 0xD(%r4)
stb %r8, 0xE(%r4)
stb %r10, 0xC(%r4)
stb %r11, 0xF(%r4)
blr