📄 smf_lpt.c
字号:
udword i, j, k;
udword cnt;
udword zone;
udword total_blocks;
udword p_num;
udword l_offset;
udword p_end;
udword lba;
udword parity;
ubyte acLPTBuf[8];
s_lptFlag[drv_no] = NOT_INITIALIZED;
/*
* Device Info initial
*/
s_smlErr = smpFlashReadID(drv_no, acLPTBuf, 2);
if (s_smlErr != SM_OK)
return s_smlErr;
/* search manufacture code table */
for (i = 0; i < MAX_MI_NUM; ++i)
{
if (acLPTBuf[0] == g_mCode[i])
break;
}
if (i >= MAX_MI_NUM)
return ERR_CARD_NOT_DETECTED;
s_devID[drv_no].manufacture = i;
/* search device code table */
for (j = 0; j < MAX_DI_NUM; ++j)
{
for (k = 0; k < MAX_VI_NUM; ++k)
{
if (acLPTBuf[1] == g_dCode[i][j][k])
break;
}
if (k < MAX_VI_NUM)
break;
}
if (j >= MAX_DI_NUM)
return ERR_CARD_NOT_DETECTED;
s_devID[drv_no].device = j;
total_blocks = s_devInfo[s_devID[drv_no].device].PBpV;
/*
* s_pBlock[MAX_DRIVE] table initial
*/
if (s_pBlock[drv_no] != NULL)
SM_FREE(s_pBlock[drv_no]);
s_pBlock[drv_no] = (uword*)SM_MALLOC(2 * total_blocks);
if (s_pBlock[drv_no] == NULL)
return ERR_INTERNAL;
for (i = 0; i < total_blocks; ++i)
{
s_smlErr = smpFlashReadSpare(drv_no, i * (SECTOR_SIZE * s_devInfo[s_devID[drv_no].device].SpB), acLPTBuf, 8);
if (s_smlErr != SM_OK)
{
SM_FREE(s_pBlock[drv_no]);
s_pBlock[drv_no] = NULL;
return (s_smlErr);
}
if (acLPTBuf[5] != 0xff)
{
for (j = 0, cnt = 0; j < 8; ++j)
{
if ((acLPTBuf[5] >> j) & 0x01)
++cnt;
}
if (cnt <= 6)
{
SET_PB_TBL(drv_no, i, INVALID_PBLOCK);
continue;
}
}
SET_PB_TBL(drv_no, i, ((uword)acLPTBuf[6] << 8) | acLPTBuf[7]);
}
/*
* pLBlock[MAX_DRIVE] table initial
*/
if (s_lBlock[drv_no] != NULL)
SM_FREE(s_lBlock[drv_no]);
s_lBlock[drv_no] = (uword*)SM_MALLOC(2 * total_blocks);
if (s_lBlock[drv_no] == NULL)
{
SM_FREE(s_pBlock[drv_no]);
s_pBlock[drv_no] = NULL;
return ERR_INTERNAL;
}
for (i = 0; i < total_blocks; ++i)
{
SET_LB_TBL(drv_no, i, UNUSED_LBLOCK);
}
for (zone = 0; zone < total_blocks / P_ZONE_MAX + 1; ++zone)
{
l_offset = zone * L_ZONE_MAX;
if (total_blocks < P_ZONE_MAX * (zone + 1))
p_end = total_blocks;
else
p_end = P_ZONE_MAX * (zone + 1);
for (p_num = zone * P_ZONE_MAX; p_num < p_end; ++p_num)
{
if ((GET_PB_TBL(drv_no, p_num) == INVALID_PBLOCK) || (GET_PB_TBL(drv_no, p_num) == UNUSED_PBLOCK)
|| (GET_PB_TBL(drv_no, p_num) == 0)) /* CIS Block is set to 0 */
{
continue;
}
lba = GET_PB_TBL(drv_no, p_num);
/* parity check */
parity = 0;
for (i = 1; i < 16; ++i)
{
parity ^= (lba >> i) & 0x01;
}
if ((lba & 0x01) != parity)
continue;
lba = ((lba >> 1) & 0x3ff) + l_offset;
if (lba >= total_blocks) /* invalid contents */
continue;
SET_LB_TBL(drv_no, lba, (uword)p_num);
}
}
/* start of random zone */
s_lBlockSearchStart[drv_no] = (SM_RANDOM() % s_devInfo[s_devID[drv_no].device].LBpV);
s_lBlockSearchStart[drv_no] -= (s_lBlockSearchStart[drv_no] % L_ZONE_MAX);
/* random index of random zone */
s_pBlockSearchStart[drv_no] = (SM_RANDOM() % s_devInfo[s_devID[drv_no].device].PBpV);
s_lptFlag[drv_no] = INITIALIZED;
return SM_OK;
}
/**********
* Function: sm_PreLPT
* Remarks:
* - called at the first of LPT APIs
**********/
ERR_CODE sm_PreLPT(udword drv_no)
{
if (s_lptFlag[drv_no] != INITIALIZED)
{
s_smlErr = sm_LPTInit(drv_no);
if (s_smlErr != SM_OK)
return s_smlErr;
}
return SM_OK;
}
/**********
* Function: sm_PostLPT
* Remarks:
* - called at the end of LPT APIs
**********/
ERR_CODE sm_PostLPT(udword drv_no)
{
return SM_OK;
}
#if 0 /* sm_SearchFreeLBlock is now obsolete */
/**********
* Function: sm_SearchFreeLBlock
* Remark:
* - at start, checks one more time the index retunred last
* (this is for the case that the value is not used after return)
**********/
ERR_CODE sm_SearchFreeLBlock(udword drv_no, udword* pLba)
{
udword i;
for (i = 0; i < s_devInfo[s_devID[drv_no].device].LBpV; ++i)
{
if (s_lBlockSearchStart[drv_no] >= s_devInfo[s_devID[drv_no].device].LBpV)
{
s_lBlockSearchStart[drv_no] = 0;
}
if (GET_LB_TBL(drv_no, s_lBlockSearchStart[drv_no]) == UNUSED_LBLOCK)
{
*pLba = s_lBlockSearchStart[drv_no];
return SM_OK;
}
++s_lBlockSearchStart[drv_no];
}
return ERR_NO_EMPTY_BLOCK;
}
#endif
/**********
* Function: sm_SearchFreePBlock
* Remark:
* - at start, checks one more time the index retunred last
* (this is for the case that the value is not used after return)
* - if present udPBlockSearchStart[] is in the different zone from the lba zone,
* udPBlockSearchStart[] is set to random value in the same zone as lba's
**********/
ERR_CODE sm_SearchFreePBlock(udword drv_no, udword lba, udword* pPba)
{
udword i;
udword zone;
udword count;
udword min_block, max_block;
udword start_backup;
udword pba;
if (lba >= s_devInfo[s_devID[drv_no].device].LBpV)
return ERR_INVALID_PARAM;
/* if physical block for lba already exists, return it */
pba = GET_LB_TBL(drv_no, lba);
if (pba != UNUSED_LBLOCK)
{
*pPba = pba;
return SM_OK;
}
zone = lba / L_ZONE_MAX;
/* locate MBR at first valid block for convenience */
if (lba == 0)
{
start_backup = s_pBlockSearchStart[drv_no];
s_pBlockSearchStart[drv_no] = 3;
}
/* if udPBlockSearchStart[] is not in the same zone, this value is newly randomized in the same zone */
if (s_pBlockSearchStart[drv_no] / P_ZONE_MAX != zone)
{
if (s_devInfo[s_devID[drv_no].device].PBpV < P_ZONE_MAX)
{
s_pBlockSearchStart[drv_no] = SM_RANDOM() % s_devInfo[s_devID[drv_no].device].PBpV;
}
else
{
s_pBlockSearchStart[drv_no] = SM_RANDOM() % P_ZONE_MAX;
s_pBlockSearchStart[drv_no] += (zone * P_ZONE_MAX);
}
}
if (s_devInfo[s_devID[drv_no].device].PBpV < P_ZONE_MAX)
{
count = s_devInfo[s_devID[drv_no].device].PBpV;
min_block = 0;
max_block = s_devInfo[s_devID[drv_no].device].PBpV - 1;
}
else
{
count = P_ZONE_MAX;
min_block = P_ZONE_MAX * zone;
max_block = P_ZONE_MAX * (zone + 1) - 1;
}
for (i = 0; i < count; ++i)
{
if (s_pBlockSearchStart[drv_no] > max_block)
{
s_pBlockSearchStart[drv_no] = min_block;
}
if(GET_PB_TBL(drv_no, s_pBlockSearchStart[drv_no]) == UNUSED_PBLOCK)
{
*pPba = s_pBlockSearchStart[drv_no];
break;
}
++s_pBlockSearchStart[drv_no];
}
/* restore the old search_start block when lba is MBR block */
if (lba == 0)
{
s_pBlockSearchStart[drv_no] = start_backup;
}
if (i < count)
return SM_OK;
return ERR_NO_EMPTY_BLOCK;
}
/**********
* Function: sm_ECCEncode
* Remark:
* - adopted from "ECC Algorithm for SmartMedia V3.0"
* by Memory Product & Technology, Samsung Electronics Co. (ecc30.pdf)
**********/
ERR_CODE sm_ECCEncode(const ubyte* p_buf, ubyte* p_ecc)
{
udword i, j;
ubyte paritr[256], tmp = 0, tmp2 = 0;
ubyte data_table0[16] = { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 };
ubyte data_table1[16] = { 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1 };
ubyte sum = 0, paritc = 0;
ubyte parit0c = 0, parit1c = 0, parit2c = 0, parit3c = 0;
ubyte parit4c = 0, parit5c = 0, parit6c = 0, parit7c = 0;
ubyte parit1_1, parit1_2, parit2_1, parit2_2, parit4_1, parit4_2;
ubyte parit8_1 = 0, parit8_2 = 0, parit16_1 = 0, parit16_2 = 0, parit32_1 = 0, parit32_2 = 0;
ubyte parit64_1 = 0, parit64_2 = 0, parit128_1 = 0, parit128_2 = 0, parit256_1 = 0, parit256_2 = 0;
ubyte parit512_1 = 0, parit512_2 = 0, parit1024_1 = 0, parit1024_2 = 0;
ubyte* paritr_ptr;
paritr_ptr = paritr;
for (i = 0; i < 256; ++i, ++paritr_ptr, ++p_buf)
{
paritc ^= *p_buf;
tmp = (*p_buf & 0xf0) >> 4;
tmp2 = *p_buf & 0x0f;
switch (tmp)
{
case 0:
case 3:
case 5:
case 6:
case 9:
case 10:
case 12:
case 15:
*paritr_ptr = *(data_table0 + tmp2);
break;
case 1:
case 2:
case 4:
case 7:
case 8:
case 11:
case 13:
case 14:
*paritr_ptr = *(data_table1 + tmp2);
break;
}
}
parit0c = (paritc & 0x01) ? 1 : 0;
parit1c = (paritc & 0x02) ? 1 : 0;
parit2c = (paritc & 0x04) ? 1 : 0;
parit3c = (paritc & 0x08) ? 1 : 0;
parit4c = (paritc & 0x10) ? 1 : 0;
parit5c = (paritc & 0x20) ? 1 : 0;
parit6c = (paritc & 0x40) ? 1 : 0;
parit7c = (paritc & 0x80) ? 1 : 0;
parit1_2 = parit6c ^ parit4c ^ parit2c ^ parit0c;
parit1_1 = parit7c ^ parit5c ^ parit3c ^ parit1c;
parit2_2 = parit5c ^ parit4c ^ parit1c ^ parit0c;
parit2_1 = parit7c ^ parit6c ^ parit3c ^ parit2c;
parit4_2 = parit3c ^ parit2c ^ parit1c ^ parit0c;
parit4_1 = parit7c ^ parit6c ^ parit5c ^ parit4c;
paritr_ptr = paritr;
for (i = 0; i < 256; ++i, ++paritr_ptr)
{
sum ^= *paritr_ptr;
}
paritr_ptr = paritr;
for (i = 0; i < 256; i += 2, paritr_ptr += 2)
{
parit8_2 ^= *paritr_ptr;
}
paritr_ptr = paritr;
for (i = 0; i < 256; i += 4, paritr_ptr += 4)
{
parit16_2 ^= *paritr_ptr;
parit16_2 ^= *(paritr_ptr + 1);
}
paritr_ptr = paritr;
for (i = 0; i < 256; i += 8, paritr_ptr += 8)
{
for (j = 0; j <= 3; ++j)
{
parit32_2 ^= *(paritr_ptr + j);
}
}
paritr_ptr = paritr;
for (i = 0; i < 256; i += 16, paritr_ptr += 16)
{
for (j = 0; j <= 7; ++j)
{
parit64_2 ^= *(paritr_ptr + j);
}
}
paritr_ptr = paritr;
for (i = 0; i < 256; i += 32, paritr_ptr += 32)
{
for (j = 0; j <= 15; ++j)
{
parit128_2 ^= *(paritr_ptr + j);
}
}
paritr_ptr = paritr;
for (i = 0; i < 256; i += 64, paritr_ptr += 64)
{
for (j = 0; j <= 31; ++j)
{
parit256_2 ^= *(paritr_ptr + j);
}
}
paritr_ptr = paritr;
for (i = 0; i < 256; i += 128, paritr_ptr += 128)
{
for (j = 0; j <= 63; ++j)
{
parit512_2 ^= *(paritr_ptr + j);
}
}
paritr_ptr = paritr;
for (i = 0; i < 256; i += 256, paritr_ptr += 256)
{
for (j = 0; j <= 127; ++j)
{
parit1024_2 ^= *(paritr_ptr + j);
}
}
if (sum==0)
{
parit1024_1 = parit1024_2;
parit512_1 = parit512_2;
parit256_1 = parit256_2;
parit128_1 = parit128_2;
parit64_1 = parit64_2;
parit32_1 = parit32_2;
parit16_1 = parit16_2;
parit8_1 = parit8_2;
}
else
{
parit1024_1 = parit1024_2 ? 0 : 1;
parit512_1 = parit512_2 ? 0 : 1;
parit256_1 = parit256_2 ? 0 : 1;
parit128_1 = parit128_2 ? 0 : 1;
parit64_1 = parit64_2 ? 0 : 1;
parit32_1 = parit32_2 ? 0 : 1;
parit16_1 = parit16_2 ? 0 : 1;
parit8_1 = parit8_2 ? 0 : 1;
}
parit1_2 <<= 2;
parit1_1 <<= 3;
parit2_2 <<= 4;
parit2_1 <<= 5;
parit4_2 <<= 6;
parit4_1 <<= 7;
parit128_1 <<= 1;
parit256_2 <<= 2;
parit256_1 <<= 3;
parit512_2 <<= 4;
parit512_1 <<= 5;
parit1024_2 <<= 6;
parit1024_1 <<= 7;
parit8_1 <<= 1;
parit16_2 <<= 2;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -