⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smf_lpt.c

📁 the test file for GP32 gameboy hack
💻 C
📖 第 1 页 / 共 4 页
字号:
 *	- 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 + -