📄 smf_lpt.c
字号:
* - calculate (lblock_no, offset) from (lsector_no, offset), and do the same as smlReadBlock
* - cannot read beyond the sector boundary
**********/
SML_EXPORT ERR_CODE smlReadSector(udword drv_no, udword lsector_no, udword offset, void* p_buf, udword read_size)
{
udword new_lblock;
udword new_lsector;
udword new_offset;
s_smlErr = sm_PreLPT(drv_no);
if (s_smlErr != SM_OK)
LPT_RETURN(drv_no, s_smlErr);
new_lblock = lsector_no / s_devInfo[s_devID[drv_no].device].SpB;
new_lsector = lsector_no % s_devInfo[s_devID[drv_no].device].SpB;
new_offset = new_lsector * SECTOR_SIZE + offset;
s_smlErr = sm_ReadBlock(drv_no, new_lblock, new_offset, p_buf, read_size);
LPT_RETURN(drv_no, s_smlErr);
}
/**********
* Function: smlGetDeviceInfo
* Remarks:
* - returns SmartMedia information
* - used when formatting in FAT layer
**********/
SML_EXPORT ERR_CODE smlGetDeviceInfo(udword drv_no, const sDEV_INFO** dev_info)
{
s_smlErr = sm_PreLPT(drv_no);
if (s_smlErr != SM_OK)
LPT_RETURN(drv_no, s_smlErr);
*dev_info = &s_devInfo[s_devID[drv_no].device];
LPT_RETURN(drv_no, SM_OK);
}
/**********
* Function: smlFormatVol
* Remarks:
* - formats the SmartMedia according to the device ID
* - This API must be called prior to the FAT API for format (smFormatVol())
* Parameters
* . format_id: LPT_FORMAT_NORMAL, LPT_FORMAT_RESCUE
* . p_bad_count (result): number of bad blocks
**********/
SML_EXPORT ERR_CODE smlFormatVol(udword drv_no, udword format_id, udword* p_bad_count)
{
udword i, j, n;
udword total_blocks;
udword addr;
ubyte spare[20];
udword cnt;
udword block_size;
udword page_size;
ubyte* write_buf;
ubyte spare_buf[16];
bool b_error;
udword err_count=0;
s_smlErr = sm_PreLPT(drv_no);
if (s_smlErr != SM_OK)
LPT_RETURN(drv_no, s_smlErr);
total_blocks = s_devInfo[s_devID[drv_no].device].PBpV;
page_size = s_devInfo[s_devID[drv_no].device].szP;
block_size = s_devInfo[s_devID[drv_no].device].SpB * SECTOR_SIZE;
if (format_id == LPT_FORMAT_NORMAL)
{
for (i = 0; i < total_blocks; ++i)
{
addr = i * SECTOR_SIZE * s_devInfo[s_devID[drv_no].device].SpB;
s_smlErr = smpFlashReadSpare(drv_no, addr, spare, 8);
if (s_smlErr != SM_OK)
LPT_RETURN(drv_no, s_smlErr);
if (spare[5] != 0xff)
{
for (j = 0, cnt = 0; j < 8; ++j)
{
if ((spare[5] >> j) & 0x01)
{
++cnt;
}
}
/* skip invalid block */
if(cnt <= 6)
{
++err_count;
continue;
}
}
smpFlashEraseBlock(drv_no, addr);
}
}
else if (format_id == LPT_FORMAT_RESCUE)
{
write_buf = SMB_ALLOC_BUF();
if (!write_buf)
LPT_RETURN(drv_no, ERR_OUT_OF_MEMORY);
for (i = 0; i < total_blocks; ++i)
{
addr = i * SECTOR_SIZE * s_devInfo[s_devID[drv_no].device].SpB;
s_smlErr = smpFlashReadSpare(drv_no, addr, spare, 8);
if (s_smlErr != SM_OK)
{
SMB_FREE_BUF(write_buf);
LPT_RETURN(drv_no, s_smlErr);
}
if (spare[5] != 0xff)
{
for (j = 0, cnt = 0; j < 8; ++j)
{
if ((spare[5] >> j) & 0x01)
{
++cnt;
}
}
/* skip invalid block marked by factory */
if (cnt <= 1)
{
++err_count;
continue;
}
}
b_error = FALSE;
s_smlErr = smpFlashEraseBlock(drv_no, addr);
if (s_smlErr != SM_OK)
{
if (s_smlErr == ERR_FLASH_STATUS)
{
b_error = TRUE;
}
else
{
SMB_FREE_BUF(write_buf);
LPT_RETURN(drv_no, s_smlErr);
}
}
SM_MEMSET(write_buf, 0x5a, 512);
SM_MEMSET(spare_buf, 0x5a, 16);
if (b_error == FALSE)
{
for (j = 0; j < block_size; j += SECTOR_SIZE)
{
s_smlErr = smpFlashWriteSector(drv_no, (addr + j) / SECTOR_SIZE, write_buf, spare_buf);
if (s_smlErr != SM_OK)
{
if (s_smlErr == ERR_FLASH_STATUS)
{
b_error = TRUE;
break;
}
else
{
SMB_FREE_BUF(write_buf);
LPT_RETURN(drv_no, s_smlErr);
}
}
s_smlErr = smpFlashReadSector(drv_no, (addr + j) / SECTOR_SIZE, write_buf);
if (s_smlErr != SM_OK)
{
SMB_FREE_BUF(write_buf);
LPT_RETURN(drv_no, s_smlErr);
}
for (n = 0; n < 512; ++n)
{
if (write_buf[n] != 0x5a)
{
break;
}
}
if (n < 512)
{
b_error = TRUE;
break;
}
s_smlErr = smpFlashReadSectorSpare(drv_no, (addr + j) / SECTOR_SIZE, spare_buf);
if (s_smlErr != SM_OK)
{
SMB_FREE_BUF(write_buf);
LPT_RETURN(drv_no, s_smlErr);
}
for (n = 0; n < 16; ++n)
{
if (spare_buf[n] != 0x5a)
{
break;
}
}
if (n < 16)
{
b_error = TRUE;
break;
}
}
}
if (b_error)
{
++err_count;
SM_MEMSET(write_buf, 0xff, 512);
SM_MEMSET(spare_buf, 0xff, 16);
/*
* set block_status_area to 0 => invalid block marking
*/
spare_buf[5] = SM_INVALID_BLOCK_MARK;
for (j = 0; j < block_size; j += SECTOR_SIZE)
{
smpFlashWriteSector(drv_no, (addr + j) / SECTOR_SIZE, write_buf, spare_buf);
}
}
else
{
smpFlashEraseBlock(drv_no, addr);
}
}
SMB_FREE_BUF(write_buf);
}
write_buf = SMB_ALLOC_BUF();
if (!write_buf)
LPT_RETURN(drv_no, ERR_OUT_OF_MEMORY);
/* bad block marking at block_0 */
SM_MEMSET(write_buf, 0xff, 512);
SM_MEMSET(spare_buf, 0xff, 16);
spare_buf[5] = SM_INVALID_BLOCK_MARK;
for (j = 0; j < block_size; j += SECTOR_SIZE)
{
smpFlashWriteSector(drv_no, j / SECTOR_SIZE, write_buf, spare_buf);
}
SMB_FREE_BUF(write_buf);
/* write CIS block in the first valid block from block_1 */
for (i = 1; i < total_blocks; ++i)
{
addr = i * SECTOR_SIZE * s_devInfo[s_devID[drv_no].device].SpB;
s_smlErr = smpFlashReadSpare(drv_no, addr, spare, 8);
if (s_smlErr != SM_OK)
LPT_RETURN(drv_no, s_smlErr);
if (spare[5] != 0xff)
{
for (j = 0, cnt = 0; j < 8; ++j)
{
if ((spare[5] >> j) & 0x01)
{
++cnt;
}
}
/* skip invalid block */
if (cnt <= 6)
continue;
}
s_smlErr = sm_WriteCISBlock(drv_no, i);
if (s_smlErr != SM_OK)
LPT_RETURN(drv_no, s_smlErr);
break;
}
sm_LPTInit(drv_no);
*p_bad_count = err_count;
LPT_RETURN(drv_no, SM_OK);
}
SML_EXPORT bool smlIsSpaceAvailable(udword drv_no, udword block, udword offset, udword count)
{
udword pba;
udword startSector;
udword endSector;
udword sectorsPerBlock;
udword i;
s_smlErr = sm_PreLPT(drv_no);
if (s_smlErr != SM_OK)
LPT_RETURN(drv_no, FALSE);
pba = GET_LB_TBL(drv_no, block);
if (pba == UNUSED_LBLOCK)
LPT_RETURN(drv_no, FALSE);
sectorsPerBlock = s_devInfo[s_devID[drv_no].device].SpB;
startSector = pba * sectorsPerBlock + offset / SECTOR_SIZE;
endSector = pba * sectorsPerBlock
+ (offset + count - 1) / SECTOR_SIZE;
for (i = startSector; i <= endSector; ++i)
{
ubyte spareBuf[16];
int j;
s_smlErr = smpFlashReadSectorSpare(drv_no, i, spareBuf);
if (s_smlErr != SM_OK)
LPT_RETURN(drv_no, FALSE);
for (j = 0; j < sizeof(spareBuf); ++j)
{
if (spareBuf[j] != 0xff)
LPT_RETURN(drv_no, FALSE);
}
}
LPT_RETURN(drv_no, TRUE);
}
SML_EXPORT bool smlIsPhysSectorErased(udword drv_no, udword pba, udword sectorOffset)
{
udword sector;
ubyte spareBuf[16];
int i;
bool rv; /* if not use this variable, ARM system misbehaves */
s_smlErr = sm_PreLPT(drv_no);
if (s_smlErr != SM_OK)
{
rv = FALSE;
LPT_RETURN(drv_no, rv);
}
sector = pba * s_devInfo[s_devID[drv_no].device].SpB + sectorOffset;
s_smlErr = smpFlashReadSectorSpare(drv_no, sector, spareBuf);
if (s_smlErr != SM_OK)
{
rv = FALSE;
LPT_RETURN(drv_no, rv);
}
for (i = 0; i < sizeof(spareBuf); ++i)
{
if (spareBuf[i] != 0xff)
{
rv = FALSE;
LPT_RETURN(drv_no, rv);
}
}
rv = TRUE;
LPT_RETURN(drv_no, rv);
}
SML_EXPORT ERR_CODE smlTouchBlock(udword drv_no, udword lblock)
{
udword pba;
ubyte* buf;
udword i;
const udword sectorsPerBlock = s_devInfo[s_devID[drv_no].device].SpB;
s_smlErr = sm_PreLPT(drv_no);
if (s_smlErr != SM_OK)
LPT_RETURN(drv_no, s_smlErr);
pba = GET_LB_TBL(drv_no, lblock);
if (pba == UNUSED_LBLOCK)
LPT_RETURN(drv_no, ERR_INVALID_BLOCK);
buf = SMB_ALLOC_BUF();
if (!buf)
LPT_RETURN(drv_no, ERR_OUT_OF_MEMORY);
SM_MEMSET(buf, 0xff, SECTOR_SIZE);
/* if sector's spare area is erased, fill it appropriately */
for (i = 0; i < sectorsPerBlock; ++i)
{
if (smlIsPhysSectorErased(drv_no, pba, i))
{
s_smlErr = smlWriteBlock(drv_no, lblock, i * SECTOR_SIZE, buf, SECTOR_SIZE);
if (s_smlErr != SM_OK)
{
SMB_FREE_BUF(buf);
LPT_RETURN(drv_no, s_smlErr);
}
}
}
SMB_FREE_BUF(buf);
LPT_RETURN(drv_no, SM_OK);
}
/*????????????????????????????????????????????????????????????????????*/
/**********
* Function: smlOptimizeVol
* Remarks:
* - implements LPT level optimization
**********/
SML_EXPORT ERR_CODE smlOptimizeVol(udword drv_no, udword opt_mode)
{
s_smlErr = sm_PreLPT(drv_no);
if (s_smlErr != SM_OK)
LPT_RETURN(drv_no, s_smlErr);
LPT_RETURN(drv_no, SM_OK);
}
/**********
* Function: SMLCBCardInserted
* Remarks:
* - callback function that is called when the card is inserted
* - must call the callback function of higher layer
**********/
SML_EXPORT void SMLCBCardInserted(udword drv_no)
{
SMCBCardInserted(drv_no);
}
/**********
* Function: SMLCBCardEjected
* Remarks:
* - callback function that is called when the card is ejected
* - must call the callback function of higher layer
**********/
SML_EXPORT void SMLCBCardEjected(udword drv_no)
{
s_lptFlag[drv_no] = NOT_INITIALIZED;
SMCBCardEjected(drv_no);
}
/**********
* Local Function definitions
**********/
/**********
* Function: sm_LPTInitDefaultValue
* Remarks:
* - called when the file system is initialized
**********/
void sm_LPTInitDefaultValue(void)
{
udword i;
for (i = 0; i < MAX_DRIVE; ++i)
{
s_lptFlag[i] = NOT_INITIALIZED;
if (s_lBlock[i] != NULL)
{
SM_FREE(s_lBlock[i]);
s_lBlock[i] = NULL;
}
if (s_pBlock[i] != NULL)
{
SM_FREE(s_pBlock[i]);
s_pBlock[i] = NULL;
}
}
}
/**********
* Function: sm_LPTInit
* Remarks:
* - called when the udLPTFlag is not initialized and LPT API is called
**********/
ERR_CODE sm_LPTInit(udword drv_no)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -