/* sdidentify.cpp Copyright (C) 2007 Acekard, www.acekard.com Copyright (C) 2007-2009 somebody Copyright (C) 2009 yellow wood goblin This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "iocmn.h" #if defined(_STORAGE_rpg) || defined(_STORAGE_ak2i) #include #include "timer.h" #include "sdidentify.h" #include "irqs.h" #include "inifile.h" #include "stringtool.h" #include "systemfilenames.h" #include "language.h" #include "progresswnd.h" std::string sdidGetSDName() { u8 sdinfo[8] = {}; sddGetSDInfo( sdinfo ); for( u8 i = 0; i < 5; ++i ) { if( ' ' ==sdinfo[i+1] ) sdinfo[i+1] = '_'; } return (const char *)(sdinfo + 1); } std::string sdidGetSDManufacturerID() { u8 sdinfo[8] = {}; sddGetSDInfo( sdinfo ); return formatString( "%02x", sdinfo[0] ); } std::string sdidGetSDManufacturerName() { CIniFile ini( SFN_SDCARD_LIST ); u8 sdinfo[8] = {}; sddGetSDInfo( sdinfo ); std::string manufacturerID = formatString( "%02x", sdinfo[0] ); std::string manufacturerName = ini.GetString( "SD Card Manufacturers", manufacturerID, manufacturerID ); return manufacturerName; } u32 sdidCheckSDSpeed( u32 readCount ) { CIniFile ini( SFN_SDCARD_LIST ); std::string name = sdidGetSDName(); std::string manufacturerID = sdidGetSDManufacturerID(); u32 ret = ini.GetInt( "SD Card Speed", manufacturerID + name, 0 ); if( ret != 0 ) return ret; u32 totalSectors; if(!ELM_SectorsFromDisk(ioSD(),&totalSectors)) { dbg_printf("no sd card\n"); return 0; } dbg_printf("total sectors %d, max addr %08x\n", totalSectors, (totalSectors << 9) - 0x200); // some sd card needs to be readed one time for initialization sddReadBlocks( 0, 1, NULL ); irq().vblankStop(); double maxAccessTime = 0.f; std::string tipText = LANG("progress window", "first use sd"); progressWnd().setTipText( tipText ); progressWnd().show(); progressWnd().setPercent( 0 ); vu64 tick1 = 0; vu64 tick2 = 0; for( size_t i = 0; i < readCount; ++i ) { u32 randAddr = ((rand() % totalSectors)<<(isSDHC()?0:9) ) & (~(0x200-1)); u32 sdReadSingleBlock[2] = { 0xD5030011, randAddr }; // input read address here ioRpgSendCommand( sdReadSingleBlock, 0, 80, NULL ); timer().initTimer(); tick1 = timer().getTick(); ioRpgWaitCmdBusy( true ); tick2 = timer().getTick(); u32 readSD[2] = { 0xB7000000, 0x00000000 | 0x00130000 }; // address dont care here ioRpgSendCommand( readSD, 512, 4, NULL ); if( tick2 < tick1 ) { tick2 += 65536; } tick1 = tick2 - tick1; double timeCostUs = timer().tickToUs( tick1 ); if( timeCostUs > maxAccessTime ) { maxAccessTime = timeCostUs; } u32 percent = i * 100 / readCount; if( (i & 0x1ff) == 0x1ff ) { dbg_printf( "%02d ", percent ); progressWnd().setPercent( percent ); } } progressWnd().hide(); irq().vblankStart(); maxAccessTime = ((u32)(maxAccessTime / 15 + 0.5)) * 15; ret = ((u32)(maxAccessTime * 1000 / 150)); dbg_printf("max access time: max %4.2fus\n", maxAccessTime ); ini.SetInt( "SD Card Speed", manufacturerID + name, ret ); ini.SaveIniFile( SFN_SDCARD_LIST ); return ret; } #endif