diff --git a/trunk/bootrom/build/libraries/nand/ARM11/Makefile b/trunk/bootrom/build/libraries/nand/ARM11/Makefile new file mode 100644 index 0000000..3c5a491 --- /dev/null +++ b/trunk/bootrom/build/libraries/nand/ARM11/Makefile @@ -0,0 +1,51 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: CtrBrom - libraries - mi +# File: Makefile +# +# Copyright 2008-2009 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev$ +# $Author$ +#---------------------------------------------------------------------------- + +SUBDIRS = +SUBMAKES = + + +#---------------------------------------------------------------------------- + +# build ARM & THUMB libraries +BROM_CODEGEN_ALL ?= TRUE + +#(NE1)------------------------------------------- +ifeq ($(BROM_PLATFORM),NE1EMU) +SRCDIR = . ./src/ne1 ../common/ne1 +SRCS = \ + nandif.c \ + nand.c \ + crc.c +endif +#------------------------------------------------ + +TARGET_LIB = libnand$(BROM_LIBSUFFIX).a + +include $(CTRBROM_ROOT)/build/buildtools/commondefs + +INSTALL_TARGETS = $(TARGETS) +INSTALL_DIR = $(BROM_INSTALL_LIBDIR) + +#---------------------------------------------------------------------------- + +do-build: $(TARGETS) + +include $(CTRBROM_ROOT)/build/buildtools/modulerules + +#===== End of Makefile ===== diff --git a/trunk/bootrom/build/libraries/nand/ARM11/src/ne1/crc.c b/trunk/bootrom/build/libraries/nand/ARM11/src/ne1/crc.c new file mode 100644 index 0000000..1805a51 --- /dev/null +++ b/trunk/bootrom/build/libraries/nand/ARM11/src/ne1/crc.c @@ -0,0 +1,47 @@ + +#include +#include "crc.h" + + +/*---------------------------------------------------------------------------* + global変数 + *---------------------------------------------------------------------------*/ +static const u16 cr16_table[16] = { + 0x0000, 0xCC01, 0xD801, 0x1400, + 0xF001, 0x3C00, 0x2800, 0xE401, + 0xA001, 0x6C00, 0x7800, 0xB401, + 0x5000, 0x9C01, 0x8801, 0x4400, +}; + + +/*---------------------------------------------------------------------------* + Name: crcCalc + + Description: CRC(CRC-ANSI, 別名CRC16)を算出する + + Arguments: data : + len : + + Returns: + *---------------------------------------------------------------------------*/ +u16 crcCalc( vu8* data, vu16 len) +{ + vu16 r1, total; + + total = 0; + while( len-- > 0) { + /*下位4bit*/ + r1 = cr16_table[ total & 0xf]; + total = (total >> 4) & 0x0FFF; + total = total ^ r1 ^ cr16_table[ *data & 0xf]; + + /*上位4bit*/ + r1 = cr16_table[ total & 0xf]; + total = (total >> 4) & 0x0fff; + total = total ^ r1 ^ cr16_table[ (*data >> 4) & 0xf]; + + /*次のバイトへ*/ + data++; + } + return total; +} diff --git a/trunk/bootrom/build/libraries/nand/ARM11/src/ne1/crc.h b/trunk/bootrom/build/libraries/nand/ARM11/src/ne1/crc.h new file mode 100644 index 0000000..17e1596 --- /dev/null +++ b/trunk/bootrom/build/libraries/nand/ARM11/src/ne1/crc.h @@ -0,0 +1,26 @@ + +#ifndef __CRC_H__ +#define __CRC_H__ + + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + + +/*---------------------------------------------------------------------------* + API + *---------------------------------------------------------------------------*/ +u16 crcCalc( vu8* data, vu16 len); + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*__CRC_H__*/ diff --git a/trunk/bootrom/build/libraries/nand/ARM11/src/ne1/nand.c b/trunk/bootrom/build/libraries/nand/ARM11/src/ne1/nand.c new file mode 100644 index 0000000..e0e1b13 --- /dev/null +++ b/trunk/bootrom/build/libraries/nand/ARM11/src/ne1/nand.c @@ -0,0 +1,1611 @@ +/*---------------------------------------------------------------------------* + Project: CTR - NAND driver + File: nandif.c + + Copyright 2006 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + *---------------------------------------------------------------------------*/ + +#include +#include +#include "nand.h" + +#include "nandif_ip.h" +#include "nandif_reg.h" + +//#define PRINTDEBUG osTPrintf +//#define PRINTLEVEL2 osTPrintf +#define PRINTDEBUG( ...) ((void)0) +#define PRINTLEVEL2( ...) ((void)0) + + +/*********************************************************************** + +***********************************************************************/ +#define NAND_STACK_SIZE (8192) +#define NAND_THREAD_PRIO (10) + +//NAND_OPERATION_INITはいらない(Initでタスクを立てるため) +#define NAND_OPERATION_ENABLE (0) +#define NAND_OPERATION_FORMAT (1) +#define NAND_OPERATION_READ (2) +#define NAND_OPERATION_WRITE (3) +#define NAND_OPERATION_FLUSH (4) + +#define NAND_FLUSH_RETRY_COUNT (8) + +/*i_nandFlushPageCache関数の返り値*/ +#define I_NAND_ERR_SUCCESS (0) //成功 +#define I_NAND_ERR_VERIFY_ERR (-1) //マージで助かる +#define I_NAND_ERR_FATAL_ERR (-2) //不正番号 +#define I_NAND_ERR_IMPOSSIBLE_ERR (-3) //freeブロックが見つからない + +/**/ +#define I_NAND_FLUSH_FALSE (-1) +//#define I_NAND_FLUSH_TRUE (1) +#define I_NAND_FLUSH_CASHED (-2) + +extern u32 nand_ecc[4]; + + +/*---------------------------------------------------------------------------* + API(上位層タスク) - nandタスク間通信用構造体 + *---------------------------------------------------------------------------*/ +typedef struct { + NandPageCacheFormat* cache; + void* buf; + u32 sector; + u32 sector_count; + u32 operation; +// ID tskid; /*nandAPIを呼んだタスクのID*/ +} NandMsg; + + +/*---------------------------------------------------------------------------* + 論理ブロック-物理ブロック 変換テーブル + *---------------------------------------------------------------------------*/ +u16 nandBlkTbl[1024]; /*physical_blk = nandBlkTbl[logical_blk]*/ + +//i_nandWritePage,i_nandEraseBlockの返り値でBadBlockを認識するには、 +//スペア領域以外の場所でBadBlockを管理する必要がある +//NandSysFormat nandSys[1024]; + + +/*---------------------------------------------------------------------------* + 物理ブロックステータスのリンクリスト + *---------------------------------------------------------------------------*/ +NandBlockStatInfo NandBlockStat[1024]; +NandStatInfo NandStat; + + +/*---------------------------------------------------------------------------* + globalだがアプリケーションには非公開の関数 + *---------------------------------------------------------------------------*/ +void i_nandEnable( NandPageCacheFormat* NandPageCache); +void i_nandFormat( void); +void i_nandReset( void); +void i_nandReadSector( NandPageCacheFormat* NandPageCache, u32* dest, u32 logical_sector); +void i_nandWriteSector( NandPageCacheFormat* NandPageCache, u32* src, u32 logical_sector); +BOOL i_nandFlush( NandPageCacheFormat* NandPageCache); + +int i_nandFlushPageCache( NandPageCacheFormat* NandPageCache); +void i_nandMarkingBadBlock( u16 physical_blk, NandSpareFormat* NandSpareOrg); + + +/*---------------------------------------------------------------------------* + static関数 + *---------------------------------------------------------------------------*/ +static u8 i_nandCheckBlock( u16 physical_blk, u16* logical_adr, u32* erase_count); +static BOOL i_nandCheckFollowCluster( u16 physical_blk, u16* logical_adr, u32* erase_count); +static u8 i_nandCountBitDifferent( u8 dat1, u8 dat2); + +void i_nandInsertStatList( NandBlockStatInfo** NandBlockStatList, NandBlockStatInfo* NandBlockStat); +void i_nandRemoveStatList( NandBlockStatInfo** NandBlockStatList, NandBlockStatInfo* NandBlockStat); +static BOOL i_nandCheckECC( u32* data, u32* stored_ecc, u32 new_ecc); + +void nandFillPageCache( NandPageCacheFormat* NandPageCache, u32 physical_page); +static void nandReadPageCache( NandPageCacheFormat* NandPageCache, u32* dest, u16 cache_sect); +static void nandWritePageCache( NandPageCacheFormat* NandPageCache, u32* src, u16 cache_sect); + +BOOL i_nandMergeBlock( NandPageCacheFormat* NandPageCache); + +static void i_nandThread( void* arg); + + +/*---------------------------------------------------------------------------* + static変数 + *---------------------------------------------------------------------------*/ +static BOOL nand_tsk_created = FALSE; + +/*---------------------------------------------------------------------------* + global変数 + *---------------------------------------------------------------------------*/ +OSThread nand_tsk; +OSMessageQueue nand_dtq; +OSMessage nand_dtq_array[1]; +OSMessageQueue nand_result_dtq; +OSMessage nand_result_dtq_array[1]; + +u64 nand_stack[NAND_STACK_SIZE / sizeof(u64)]; + +NandPageCacheFormat* g_nandPageCache; + + +//u64 nand_stack[NAND_STACK_SIZE / sizeof(u64)]; + + + + + +/*---------------------------------------------------------------------------* + Name: STD_CompareString + + Description: compare strings. same to strcmp + + Arguments: str1, str2 : strings + + Returns: 0 if same + *---------------------------------------------------------------------------*/ +int stdCompareString(const char *str1, const char *str2); +int stdCompareString(const char *str1, const char *str2) +{ + while (*str1 == *str2 && *str1) + { + str1++; + str2++; + } + return (*str1 - *str2); +} + + +/*---------------------------------------------------------------------------* + Name: nandInit + + Description: + + Arguments: + + Returns: + *---------------------------------------------------------------------------*/ +void nandInit( void) +{ + NandMsg nandMsg; + u32 init_msg; + + if( nand_tsk_created == FALSE) { + /*---------- OS準備 ----------*/ + osInitMessageQueue( &nand_dtq, &nand_dtq_array[0], 1); + osInitMessageQueue( &nand_result_dtq, &nand_result_dtq_array[0], 1); + + osCreateThread( &nand_tsk, i_nandThread, NULL, (nand_stack+NAND_STACK_SIZE / sizeof(u64)), + NAND_STACK_SIZE, NAND_THREAD_PRIO); + + osWakeupThreadDirect( &nand_tsk); + /*----------------------------*/ + nand_tsk_created = TRUE; + } + + i_nandReset(); +} + + +/*---------------------------------------------------------------------------* + Name: i_nandEnable + + Description: ブロックテーブルを作成する + + Arguments: + + Returns: + *---------------------------------------------------------------------------*/ +void i_nandEnable( NandPageCacheFormat* NandPageCache) +{ + u16 i; + u16 physical_blk; + u16 logical_blk; + NandPageFormat NandPage; + u16 ctrdg_reg; + u8 block_stat; + u32 erase_count; + u16 free_blk_count = 0; + u16 busy_blk_count = 0; + u16 bad_blk_count = 0; + + miCpuFill8( nandBlkTbl, 0xFF, 2048); //全て未割り当て状態に + NandStat.busy = NULL; + NandStat.free = NULL; + + osTPrintf( "nand block checking\n"); + for( i=0; i<1024; i++) { + if( (i % 16) == 0) { + osTPrintf( "."); + } + block_stat = i_nandCheckBlock( i, &logical_blk, &erase_count); + physical_blk = i; + + /*テーブルの構築*/ + if( (logical_blk < 1024)&&(block_stat == 0xFF)) {//未割り当て(0xFFFF)をはじく + nandBlkTbl[logical_blk] = physical_blk; + if( logical_blk == 0) { + PRINTDEBUG( "nandEnable : physical:0x%x, logical:0x%x\n", physical_blk, logical_blk); + } + } + + /*ステータスのリンクリスト構築*/ + NandBlockStat[physical_blk].physical_blk = physical_blk; + NandBlockStat[physical_blk].block_stat_bad = block_stat; + NandBlockStat[physical_blk].erase_count = erase_count; + NandBlockStat[physical_blk].next = NULL; + if( (logical_blk < 1024)&&(block_stat == 0xFF)) { + i_nandInsertStatList( &(NandStat.busy), &(NandBlockStat[physical_blk])); + PRINTLEVEL2( "busy [physical_blk:0x%x, erase_count:0x%x]\n", physical_blk, NandBlockStat[physical_blk].erase_count); + busy_blk_count++; + }else{ + if( block_stat == 0xFF) { + i_nandInsertStatList( &(NandStat.free), &(NandBlockStat[physical_blk])); + PRINTLEVEL2( " free [physical_blk:0x%x, erase_count:0x%x]\n", physical_blk, NandBlockStat[physical_blk].erase_count); + free_blk_count++; + }else{ + bad_blk_count++; + PRINTLEVEL2( "%s : bad block found ... blk 0x%x(physical)\n", __FUNCTION__, physical_blk); + } + } + } + osTPrintf( "\n"); + PRINTLEVEL2( "%s : NandStat(LinkList) busy:0x%x, free:0x%x, and bad:0x%x\n", + __FUNCTION__, busy_blk_count, free_blk_count, bad_blk_count); + + /**/ + for( i=0; i<64; i++) { + NandPageCache->page_flushed[i] = I_NAND_FLUSH_FALSE; + } + NandPageCache->page_flushed_count = 0; + + + NandPageCache->valid = FALSE; + + NandPageCache->OnTheFlush = 0xFFFF; + NandPageCache->BlockDirty = FALSE; + + /*global変数に登録*/ + g_nandPageCache = NandPageCache; +} + +/*リンクリストにNandBlockStatを挿入する(消去回数順)*/ +void i_nandInsertStatList( NandBlockStatInfo** NandBlockStatList, NandBlockStatInfo* NandBlockStat) +{ + NandBlockStatInfo NandBlockStatDmy; + NandBlockStatInfo* CurrentNandBlockStat; + + /*前処理*/ + NandBlockStat->next = NULL; + + if( *NandBlockStatList == NULL) { + *NandBlockStatList = NandBlockStat; + return; + }else{ + NandBlockStatDmy.next = *NandBlockStatList; + CurrentNandBlockStat = &NandBlockStatDmy; + while( CurrentNandBlockStat->next != NULL) { + if( NandBlockStat->erase_count < CurrentNandBlockStat->next->erase_count) { + break; + } + CurrentNandBlockStat = CurrentNandBlockStat->next; + } + NandBlockStat->next = CurrentNandBlockStat->next; + CurrentNandBlockStat->next = NandBlockStat; + } + + /*先頭に挿入した場合は、リンクリストの開始位置自体を変える*/ + if( CurrentNandBlockStat == &NandBlockStatDmy) { + *NandBlockStatList = CurrentNandBlockStat->next; + } +} + +/*リンクリストからNandBlockStatを抜き出す*/ +void i_nandRemoveStatList( NandBlockStatInfo** NandBlockStatList, NandBlockStatInfo* NandBlockStat) +{ + NandBlockStatInfo NandBlockStatDmy; + NandBlockStatInfo* CurrentNandBlockStat; + + if( *NandBlockStatList == NULL) { + return; + } + NandBlockStatDmy.next = *NandBlockStatList; + CurrentNandBlockStat = &NandBlockStatDmy; + while( CurrentNandBlockStat->next != NandBlockStat) { + if( CurrentNandBlockStat->next == NULL) { + return; + }else{ + CurrentNandBlockStat = CurrentNandBlockStat->next; + } + } + CurrentNandBlockStat->next = CurrentNandBlockStat->next->next; + *NandBlockStatList = NandBlockStatDmy.next; +} + +/*---------------------------------------------------------------------------* + Name: i_nandFormat + + Description: フォーマット(スペア領域を構築)する + + Arguments: + + Returns: + *---------------------------------------------------------------------------*/ +void i_nandFormat( void) +{ + u16 i, j; + u32 physical_page_addr; + NandPageFormat NandPage; /*書き込み用作業場所*/ + u16 good_blk_count; + u8 block_stat; + u16 logical_blk; + u32 erase_count; + + miCpuFill8( &(NandPage.data.data[0][0]), 0xFF, NAND_PAGE_DATASIZE); + miCpuFill8( &(NandPage.spare), 0xFF, NAND_PAGE_SPARESIZE); + miCpuCopy8( "CTR\0", &(NandPage.spare.sig0[0]), 4); + miCpuCopy8( "CTR\0", &(NandPage.spare.sig1[0]), 4); + + good_blk_count = 0; + osTPrintf( "formatting"); + for( i=0; i<1024; i++) { + if( (i % 16) == 0) { + osTPrintf( "."); + } + /*バッドブロックかどうかチェックする*/ + block_stat = i_nandCheckBlock( i, &logical_blk, &erase_count); + if( block_stat == 0xFF) { + NandPage.spare.block_stat_bad = block_stat; + NandPage.spare.block_erase_count0 = erase_count; + NandPage.spare.block_erase_count1 = erase_count; +// if( good_blk_count > NAND_GUARANTEED_BLOCKS) { + NandPage.spare.logical_adr0 = 0xFFFF; //未割り当て + NandPage.spare.logical_adr1 = 0xFFFF; +// }else{ +// NandPage.spare.logical_adr0 = good_blk_count; +// NandPage.spare.logical_adr1 = good_blk_count; +// } + + if( i_nandEraseBlock( i) == FALSE) { + PRINTLEVEL2( "bad block generated : %s, %d\n", __FUNCTION__, __LINE__); + i_nandMarkingBadBlock( i, &(NandPage.spare)); + }else{ + good_blk_count++; + for( j=0; j<64; j++) { + physical_page_addr = ((u32)(i)<<6) + j; + //TODO:i_nandWritePageのエラーコード見る + if( i_nandWritePage( &NandPage, physical_page_addr, 1) == FALSE) { + PRINTLEVEL2( "bad block generated : %s, %d\n", __FUNCTION__, __LINE__); + i_nandMarkingBadBlock( i, &(NandPage.spare)); + good_blk_count--; + break; + } + } + } + } + } + + osTPrintf( "\n"); + osTPrintf( "%s : good_blk_count = 0x%x\n", __FUNCTION__, good_blk_count); +} + + +/*---------------------------------------------------------------------------* + Name: i_nandCheckBlock + + Description: ブロックをチェックする + + Arguments: physical_blk : チェックしたい物理ブロック番号 + + Returns: 返り値が0xFF(good block)のとき、logical_adrおよび + erase_count値が有効。返り値が0x00(bad block)のときは + どちらも無効値となります。 + *---------------------------------------------------------------------------*/ +u8 i_nandCheckBlock( u16 physical_blk, u16* logical_adr, u32* erase_count) +{ + u32 physical_page_addr; + NandPageFormat NandDevPage1; /*リードしたページ0のデータ*/ + NandSpareFormat NandDevSpare0; /*リードしたページ1のスペア領域*/ + u8 new_block_stat; + u32 new_erase_count = 0; + + /**/ + physical_page_addr = (u32)((u32)(physical_blk) << 6); + i_nandReadPage( &NandDevPage1, physical_page_addr, 1); + miCpuCopy8( &(NandDevPage1.spare), &NandDevSpare0, NAND_PAGE_SPARESIZE); + i_nandReadPage( &NandDevPage1, (physical_page_addr+1), 1); + + /*----- BBフラグが0xFFのとき -----*/ + if( (NandDevSpare0.block_stat_bad == 0xFF) && + (NandDevPage1.spare.block_stat_bad == 0xFF)) { + + new_block_stat = 0xFF; + if( (stdCompareString( NandDevSpare0.sig0, "CTR\0") == 0) || + (stdCompareString( NandDevSpare0.sig1, "CTR\0") == 0)) { + new_erase_count = NandDevSpare0.block_erase_count0; //todo:parity check + }else{/*--- pre slip write済みでpost slip writeされてないときに対応 ---*/ + if( i_nandCheckFollowCluster( physical_blk, logical_adr, + erase_count) == TRUE) { + return( new_block_stat); + } + } + }else{ + /*----- BBフラグに1bitだけ0があるとき -----*/ + if( (i_nandCountBitDifferent( NandDevSpare0.block_stat_bad, 0xFF) <= 1) && + (i_nandCountBitDifferent( NandDevPage1.spare.block_stat_bad, 0xFF) <= 1)) { + if( (stdCompareString( NandDevSpare0.sig0, "CTR\0") == 0) || + (stdCompareString( NandDevSpare0.sig1, "CTR\0") == 0)) { + new_block_stat = 0xFF; + new_erase_count = NandDevSpare0.block_erase_count0; //todo:parity check + }else{/*--- pre slip write済みでpost slip writeされてないときに対応 ---*/ + if( i_nandCheckFollowCluster( physical_blk, logical_adr, + erase_count) == TRUE) { + new_block_stat = 0xFF; + return( new_block_stat); + }else{ + //signatureがなければバッドブロック判定 + new_block_stat = 0x00; + } + } + }else{/*----- BBフラグに2bit以上0があるとき -----*/ + new_block_stat = 0x00; + } + } + + *logical_adr = NandDevSpare0.logical_adr0; //todo:parity check + *erase_count = new_erase_count; + return( new_block_stat); +} + +/*---------------------------------------------------------------------------* + Name: i_nandCheckFollowCluster + + Description: 指定ブロック内におけるクラスタ1〜7のsignatureをチェックする + + Arguments: physical_blk : チェックしたい物理ブロック番号 + + Returns: 返り値が0xFF(good block)のとき、logical_adrおよび + erase_count値が有効。返り値が0x00(bad block)のときは + どちらも無効値となります。 + *---------------------------------------------------------------------------*/ +static BOOL i_nandCheckFollowCluster( u16 physical_blk, u16* logical_adr, u32* erase_count) +{ + u16 i; + u32 physical_page_addr; + NandPageFormat NandDevPage; + + for( i=1; i<8; i++) { + physical_page_addr = (u32)(((u32)(physical_blk) << 6) + (i * 8)); + i_nandReadPage( &NandDevPage, physical_page_addr, 1); + + if( (stdCompareString( NandDevPage.spare.sig0, "CTR\0") == 0) || + (stdCompareString( NandDevPage.spare.sig1, "CTR\0") == 0)) { + *logical_adr = NandDevPage.spare.logical_adr0; //todo:parity check + *erase_count = NandDevPage.spare.block_erase_count0; //todo:parity check + return( TRUE); + } + } + + return( FALSE); +} + +/* 8bitデータを比較して、異なるビットの数を返す */ +static u8 i_nandCountBitDifferent( u8 dat1, u8 dat2) +{ + u8 dif_count; + u8 i; + + dif_count = 0; + for( i=0; i<8; i++) { + if( ((dat1>>i)&0x01) != ((dat2>>i)&0x01)) { + dif_count++; + } + } + + return( dif_count); +} + +/*---------------------------------------------------------------------------* + Name: i_nandReadSector + + Description: 論理セクタを読み出す + + Arguments: logical_sector : 論理ブロック番号 + + Returns: FALSE : 失敗 + TRUE : 成功 + *---------------------------------------------------------------------------*/ +void i_nandReadSector( NandPageCacheFormat* NandPageCache, u32* dest, u32 logical_sector) +{ + u16 logical_blk; + u16 physical_blk; + u32 logical_page; + u32 physical_page; + u16 cache_sect; /*PageCache上のセクタ番号*/ + u16 cache_offset; + u32* cache_sect_adr; + int result; + NandBlockStatInfo* AssignNandBlockStat; + + logical_blk = (u16)(logical_sector / 256); //1blk = 64*4 sectors + logical_page = (u32)(logical_sector / 4); + cache_sect = (u16)(logical_sector & 0x3); //0〜3 + + /*----- マージ制御 -----*/ + if( (NandPageCache->valid == TRUE)&&(NandPageCache->dirty == TRUE)) { + result = i_nandFlushPageCache( NandPageCache); + if( (result == I_NAND_ERR_VERIFY_ERR) || + (result == I_NAND_ERR_SUCCESS)) { + i_nandMergeBlock( NandPageCache); + }else{ + PRINTDEBUG( "%s(%d) : fatal error!\n", __FUNCTION__, __LINE__); + while( 1) {}; + } + }else{ + if( NandPageCache->BlockDirty == TRUE) { + i_nandMergeBlock( NandPageCache); + }else{ + if( NandPageCache->page_flushed[(logical_page & 0x3F)] != I_NAND_FLUSH_FALSE) { + PRINTDEBUG( "%s(%d) : fatal error!\n", __FUNCTION__, __LINE__); + while( 1) {}; + } + } + } + /*----------------------*/ + + /*マージでテーブルが更新されているかも知れないのでマージの後で計算*/ + physical_blk = nandBlkTbl[logical_blk]; + physical_page = (u32)(((u32)(physical_blk) << 6) + (logical_page & 0x3F)); + + /*----- 物理アドレスが未割り当てのとき -----*/ + //miCpuFill8( dest, 0xFF, 512);だけでも問題ないかも + if( physical_blk == 0xFFFF) { + if( (NandStat.free)&& //フリーブロックがあれば割り当て + (logical_blk < NAND_GUARANTEED_BLOCKS)) { + AssignNandBlockStat = NandStat.free; + nandBlkTbl[logical_blk] = NandStat.free->physical_blk; + + physical_blk = nandBlkTbl[logical_blk]; + physical_page = (u32)(((u32)(physical_blk) << 6) + (logical_page & 0x3F)); + + i_nandRemoveStatList( &(NandStat.free), AssignNandBlockStat); + i_nandInsertStatList( &(NandStat.busy), AssignNandBlockStat); + }else{ + return; + } + }/*-----------------------------------------*/ + + /*PageCacheが無効の場合*/ + if( NandPageCache->valid == FALSE) { + nandFillPageCache( NandPageCache, physical_page); + NandPageCache->logical_page = logical_page; //PageCacheの論理ページ番号更新 + }else{ + /*PageCacheが有効かつヒットしたとき*/ + if( (NandPageCache->valid == TRUE) && + (NandPageCache->logical_page == logical_page)) { + PRINTDEBUG( "%s : PageCache Hit! (physical:0x%x, logical:0x%x)\n", __FUNCTION__, physical_page, logical_page); + }else{ + /*PageCacheが有効だがヒットしないとき*/ + if( NandPageCache->dirty == TRUE) { + result = i_nandFlushPageCache( NandPageCache); //今までのぶんをFlush + if( (result == I_NAND_ERR_SUCCESS)||(result == I_NAND_ERR_VERIFY_ERR)) { + i_nandMergeBlock( NandPageCache); //マージ + /*マージでテーブルが更新されているかも知れないのでマージの後で計算*/ + physical_blk = nandBlkTbl[logical_blk]; + physical_page = (u32)(((u32)(physical_blk) << 6) + (logical_page & 0x3F)); + }else{ + while( 1) {}; + } + } + nandFillPageCache( NandPageCache, physical_page); + NandPageCache->logical_page = logical_page; //PageCacheの論理ページ番号更新 + } + } + + /*ECC比較 & 訂正*/ + cache_offset = cache_sect;//(u16)(cache_sect % 4); + cache_sect_adr = (u32*)((u32)&(NandPageCache->NandPage[0].data.data[cache_offset][0])); + + if( i_nandCheckECC( cache_sect_adr, + &(NandPageCache->NandPage[0].spare.ecc[cache_offset]), + NandPageCache->ecc[0][cache_offset]) == FALSE) { + PRINTLEVEL2( "ECC error : bad block generated. %s, %d\n", __FUNCTION__, __LINE__); + /*エラー発生時(訂正できたかどうかに関わらず)*/ + NandPageCache->NandSpareWriteBack.block_stat_bad = 0; /*バッドブロック・マーキング*/ + NandBlockStat[physical_blk].block_stat_bad = 0; + NandPageCache->dirty = TRUE; /*dirtyにしておかないとバッドブロック・マーキングが書き戻されない*/ + } + + /*訂正後のPageCacheデータを読み出し*/ + nandReadPageCache( NandPageCache, dest, cache_sect); + + return; +} + +/*---------------------------------------------------------------------------* + Name: i_nandCheckECC + + Description: ECCを用いてデータの誤りを訂正する + + Arguments: data : 512バイトデータのアドレス + stored_ecc : + new_ecc : + + Returns: TRUE : good ( No Error) + FALSE : bad ( ECC correction or Uncorrectable Error) + *---------------------------------------------------------------------------*/ +static BOOL i_nandCheckECC( u32* data, u32* stored_ecc, u32 new_ecc) +{ +#if 0 + return TRUE; +#else + u32 xored_ecc; + u16 i; + u16 bit_count; + u16 bit_adr; + u16 word_adr; + + /*一致しないビットの数をカウント*/ + xored_ecc = (*stored_ecc) ^ new_ecc; + if( xored_ecc == 0) { + PRINTDEBUG( "%s : no err\n", __FUNCTION__); + return TRUE; /*エラーなし*/ + } + bit_count = 0; + for( i=0; i<24; i++) { + if( xored_ecc & ( (u32)(1)<> 1) & 0x01) | /* CP9,CP8,CP7,CP6,CP5,CP4,CP3,CP2,CP1 */ + ((xored_ecc >> 2) & 0x02) | /* CP9,CP8,CP7,CP6,CP5,CP4,CP3,CP2 */ + ((xored_ecc >> 3) & 0x04) | /* CP9,CP8,CP7,CP6,CP5,CP4,CP3 */ + ((xored_ecc >> 4) & 0x08) | /* CP9,CP8,CP7,CP6,CP5,CP4 */ + ((xored_ecc >> 5) & 0x10) ); /* CP9,CP8,CP7,CP6,CP5 */ + word_adr = (u16)( + ((xored_ecc >> 11) & 0x01) | /* LP13,LP12,LP11,LP10,LP9,LP8,LP7,LP6,LP5,LP4,LP3,LP2,LP1 */ + ((xored_ecc >> 12) & 0x02) | /* LP13,LP12,LP11,LP10,LP9,LP8,LP7,LP6,LP5,LP4,LP3,LP2 */ + ((xored_ecc >> 13) & 0x04) | /* LP13,LP12,LP11,LP10,LP9,LP8,LP7,LP6,LP5,LP4,LP3 */ + ((xored_ecc >> 14) & 0x08) | /* LP13,LP12,LP11,LP10,LP9,LP8,LP7,LP6,LP5,LP4 */ + ((xored_ecc >> 15) & 0x10) | /* LP13,LP12,LP11,LP10,LP9,LP8,LP7,LP6,LP5 */ + ((xored_ecc >> 16) & 0x20) | /* LP13,LP12,LP11,LP10,LP9,LP8,LP7,LP6 */ + ((xored_ecc >> 17) & 0x40) ); /* LP13,LP12,LP11,LP10,LP9,LP8,LP7 */ + + data[word_adr] = data[word_adr] ^ (0x01 << bit_adr); + *(u32*)stored_ecc = new_ecc; + PRINTDEBUG( "%s : error corrected !!!\n", __FUNCTION__); + return FALSE; + } + /*ECCコード自体のエラー*/ + if( bit_count == 1) { + *(u32*)stored_ecc = new_ecc; + PRINTDEBUG( "%s : err of ecc own!!!\n", __FUNCTION__); + return FALSE; + } + /*訂正不可能な場合*/ + PRINTDEBUG( "%s : fatal error!!!\n", __FUNCTION__); + return FALSE; +#endif +} + +/*---------------------------------------------------------------------------* + Name: i_nandWriteSector + + Description: 論理セクタを書き込む + + Arguments: logical_sector : 論理ブロック番号 + + Returns: FALSE : 失敗 + TRUE : 成功 + *---------------------------------------------------------------------------*/ +void i_nandWriteSector( NandPageCacheFormat* NandPageCache, u32* src, u32 logical_sector) +{ + u16 logical_blk; + u16 physical_blk; + u32 logical_page; + u32 physical_page; + u16 cache_sect; + int result; + NandBlockStatInfo* AssignNandBlockStat; + + logical_blk = (u16)(logical_sector / 256); //1blk = 64*4 sectors + logical_page = (u32)(logical_sector / 4); + cache_sect = (u16)(logical_sector & 0x3); //0〜255 + + /*----- マージ制御 -----*/ + if( (NandPageCache->page_flushed[(logical_page & 0x3F)] != I_NAND_FLUSH_FALSE) || + ((NandPageCache->logical_page >> 6) != logical_blk)) { + + if( (NandPageCache->valid == TRUE)&&(NandPageCache->dirty == TRUE)) { //まずFlushする + result = i_nandFlushPageCache( NandPageCache); //今までのぶんをFlush + if( (result == I_NAND_ERR_VERIFY_ERR) || + (result == I_NAND_ERR_SUCCESS)) { + i_nandMergeBlock( NandPageCache); + }else{ + PRINTDEBUG( "%s : fatal error!\n", __FUNCTION__); + while( 1) {}; + } + }else{ + if( NandPageCache->BlockDirty == TRUE) { + i_nandMergeBlock( NandPageCache); + } + } + } + /*----------------------*/ + + /*マージでテーブルが更新されているかも知れないのでマージの後で計算*/ + physical_blk = nandBlkTbl[logical_blk]; + physical_page = (u32)(((u32)(physical_blk) << 6) + (logical_page & 0x3F)); + + /*----- 物理アドレスが未割り当てのとき -----*/ + if( physical_blk == 0xFFFF) { + if( (NandStat.free)&& //フリーブロックがあれば割り当て + (logical_blk < NAND_GUARANTEED_BLOCKS)) { + AssignNandBlockStat = NandStat.free; + nandBlkTbl[logical_blk] = NandStat.free->physical_blk; + + physical_blk = nandBlkTbl[logical_blk]; + physical_page = (u32)(((u32)(physical_blk) << 6) + (logical_page & 0x3F)); + + i_nandRemoveStatList( &(NandStat.free), AssignNandBlockStat); + i_nandInsertStatList( &(NandStat.busy), AssignNandBlockStat); + }else{ + return; + } + }/*-----------------------------------------*/ + + /*PageCacheが無効の場合*/ + if( NandPageCache->valid == FALSE) { + nandFillPageCache( NandPageCache, physical_page); + NandPageCache->logical_page = logical_page; //PageCacheの論理ブロック番号更新 + }else{ + /*PageCacheが有効かつヒットしたとき*/ + if( (NandPageCache->valid == TRUE) && + (NandPageCache->logical_page == logical_page)) { + PRINTDEBUG( "%s : PageCache Hit! (physical:0x%x, logical:0x%x)\n", __FUNCTION__, physical_page, logical_page); + }else{ + /*PageCacheが有効だがヒットしないとき*/ + if( NandPageCache->dirty == TRUE) { + result = i_nandFlushPageCache( NandPageCache); //今までのぶんをFlush + if( (result == I_NAND_ERR_FATAL_ERR)|| + (result == I_NAND_ERR_IMPOSSIBLE_ERR)) { + while( 1) {}; + } + if( result == I_NAND_ERR_VERIFY_ERR) { //Flush失敗時はすぐにマージしてリカバリ + i_nandMergeBlock( NandPageCache); + /*マージでテーブルが更新されているかも知れないのでマージの後で計算*/ + physical_blk = nandBlkTbl[logical_blk]; + physical_page = (u32)(((u32)(physical_blk) << 6) + (logical_page & 0x3F)); + } + } + nandFillPageCache( NandPageCache, physical_page); + NandPageCache->logical_page = logical_page; //PageCacheの論理ブロック番号更新 + } + } + + nandWritePageCache( NandPageCache, src, cache_sect); + + NandPageCache->dirty = TRUE; + return; +} + +/*---------------------------------------------------------------------------* + Name: nandFillPageCache + + Description: 物理ブロックをPageCacheに読み出す + + Arguments: physical_blk : 物理ブロック番号 + + Returns: FALSE : 失敗 + TRUE : 成功 + *---------------------------------------------------------------------------*/ +void nandFillPageCache( NandPageCacheFormat* NandPageCache, u32 physical_page) +{ + u16 i; + u32 physical_page_addr; + + PRINTDEBUG( "%s : Fill PageCache! (physical_page:0x%x)\n", __FUNCTION__, physical_page); + + for( i=0; iNandPage[i]), physical_page_addr, 1); + + /*自動生成されたECCを別の領域に退避しておく*/ + miCpuCopy8( &(nand_ecc[0]), &(NandPageCache->ecc[i][0]), 4); + miCpuCopy8( &(nand_ecc[1]), &(NandPageCache->ecc[i][1]), 4); + miCpuCopy8( &(nand_ecc[2]), &(NandPageCache->ecc[i][2]), 4); + miCpuCopy8( &(nand_ecc[3]), &(NandPageCache->ecc[i][3]), 4); + } + + /*oldブロックにライトバックするときのためのスペア領域をつくる*/ + miCpuCopy8( &(NandPageCache->NandPage[0].spare), &(NandPageCache->NandSpareWriteBack), + NAND_PAGE_SPARESIZE); + + NandPageCache->valid = TRUE; + NandPageCache->dirty = FALSE; + /*呼び出し元でNandPageCache->logical_blkを更新すること*/ +} + + +/*---------------------------------------------------------------------------* + Name: i_nandFlush + + Description: + + Arguments: + + Returns: + *---------------------------------------------------------------------------*/ +BOOL i_nandFlush( NandPageCacheFormat* NandPageCache) +{ + int result; + + result = 0; + /*--- ページキャッシュのフラッシュ ---*/ + if( (NandPageCache->valid == TRUE) && (NandPageCache->dirty == TRUE)) { + result = i_nandFlushPageCache( NandPageCache); + if( (result == I_NAND_ERR_FATAL_ERR)|| + (result == I_NAND_ERR_IMPOSSIBLE_ERR)) { + PRINTDEBUG( "%s : fatal error!\n", __FUNCTION__); + while( 1) {}; +// return( FALSE); + }else{ + i_nandMergeBlock( NandPageCache); + } + }/*----------------------------------*/ + + /*--- Blockのマージ ---*/ + if( NandPageCache->BlockDirty == TRUE) { + if( i_nandMergeBlock( NandPageCache) == FALSE) { + PRINTDEBUG( "%s : fatal error!\n", __FUNCTION__); + while( 1) {}; +// return( FALSE); + } + }/*--------------------*/ + + return( TRUE); +} + + +/*---------------------------------------------------------------------------* + Name: i_nandFlushPageCache + + Description: PageCacheから物理ブロックに書き出す + + Arguments: physical_blk : 物理ブロック番号 + + Returns: FALSE : 失敗 + TRUE : 成功 + *---------------------------------------------------------------------------*/ +int i_nandFlushPageCache( NandPageCacheFormat* NandPageCache) +{ + u16 i, k; + u16 new_physical_blk; + u32 new_physical_page_addr; +// u16 old_physical_blk; + u32 old_physical_page_addr; + NandPageFormat NandPage; + BOOL rslt_writepage; + + PRINTDEBUG( "%s\n", __FUNCTION__); + + /**/ +// miCpuFill8( bad_physical_blk, 0xFF, (NAND_FLUSH_RETRY_COUNT*sizeof(bad_physical_blk))); + + /*---------- 初回Flush時はNewBlockをサーチする ----------*/ + if( NandPageCache->OnTheFlush == 0xFFFF) { + if( NandStat.free) { + do { + NandPageCache->TargetNandBlockStat = NandStat.free; + new_physical_blk = NandStat.free->physical_blk; + if( new_physical_blk >= 1024) { + PRINTDEBUG( "%s : fatal error! illegal block number.\n", __FUNCTION__); + return( I_NAND_ERR_FATAL_ERR); //不正番号 + } + /*-----*/ + /*newブロックの消去回数読み出し(TODO:パリティチェック)*/ + new_physical_page_addr = (u32)(new_physical_blk << 6); + i_nandReadPage( &NandPage, new_physical_page_addr, 1); + /*消去回数をインクリメントしてWriteForwardバッファに適用,論理アドレスも適用*/ + miCpuCopy8( &(NandPage.spare), &(NandPageCache->NandSpareWriteForward), NAND_PAGE_SPARESIZE); +/* NandPageCache->NandSpareWriteForward.logical_adr0 = 0xFFFF;//(u16)(NandPageCache->logical_page >> 6); + NandPageCache->NandSpareWriteForward.logical_adr1 = 0xFFFF;//(u16)(NandPageCache->logical_page >> 6); + NandPageCache->NandSpareWriteForward.block_erase_count0 = NandPage.spare.block_erase_count0 + 1; + NandPageCache->NandSpareWriteForward.block_erase_count1 = NandPage.spare.block_erase_count1 + 1; +*/ + /*newブロック消去(TODO:eraseエラーチェック)*/ + if( i_nandEraseBlock( new_physical_blk) == FALSE) { + PRINTLEVEL2( "bad block generated : %s, %d\n", __FUNCTION__, __LINE__); + i_nandMarkingBadBlock( new_physical_blk, &(NandPageCache->NandSpareWriteForward)); + i_nandRemoveStatList( &(NandStat.free), NandPageCache->TargetNandBlockStat); + }else{ + break; + } + }while( 1); + + /*Flush用ブロックとしてnew_physical_blkを登録*/ + NandPageCache->OnTheFlush = new_physical_blk; + + for( i=0; i<64; i++) { + NandPageCache->page_flushed[i] = I_NAND_FLUSH_FALSE; + } + NandPageCache->page_flushed_count = 0; + + /*merge関数でmerge用ブロックをfreeリストから探すので、移動しておく*/ + //TODO:移動せずに、merge関数で探すときによけるべき? + i_nandRemoveStatList( &(NandStat.free), NandPageCache->TargetNandBlockStat); + i_nandInsertStatList( &(NandStat.busy), NandPageCache->TargetNandBlockStat); + + /*-----*/ + }else{ /*freeブロックがない場合は書き込み不可能なのでエラー*/ + PRINTDEBUG( "%s : fatal error! cannot found free block.\n", __FUNCTION__); + return( I_NAND_ERR_IMPOSSIBLE_ERR); + } + }else{ /* 2回目以降のFlush時 */ + new_physical_blk = NandPageCache->OnTheFlush; + if( new_physical_blk >= 1024) { + PRINTDEBUG( "%s : fatal error! illegal block number.\n", __FUNCTION__); + return( I_NAND_ERR_FATAL_ERR); //不正番号 + } + } + /*-------------------------------------------------------*/ + + PRINTDEBUG( "new_physical_blk : 0x%x, flushed_count : 0x%x\n", new_physical_blk, + NandPageCache->page_flushed_count); + + /*newブロックの該当ページにPageCacheを書き込み*/ + for( i=0; ilogical_page) & 0x3F)); + //先頭ページから順に書いていく(ランダムページ書き込み禁止のため) + new_physical_page_addr = (u32)((new_physical_blk << 6) + NandPageCache->page_flushed_count); + /*キャッシュのスペア領域にnewブロックの消去回数と論理アドレスを適用*/ + miCpuCopy8( &(NandPageCache->NandSpareWriteForward), &(NandPageCache->NandPage[i].spare), NAND_PAGE_SPARESIZE); + //TODO:i_nandWritePageのエラーコード見る + rslt_writepage = i_nandWritePage( &(NandPageCache->NandPage[i]), new_physical_page_addr, 1); + + /*Flushedフラグ*/ + if( NandPageCache->page_flushed[((NandPageCache->logical_page) & 0x3F)] != I_NAND_FLUSH_FALSE) { + PRINTDEBUG( "%s : kabutta!\n", __FUNCTION__); + while( 1) {}; + } + NandPageCache->page_flushed[((NandPageCache->logical_page) & 0x3F)] = NandPageCache->page_flushed_count; + NandPageCache->page_flushed_count++; + } + + + /*簡易ベリファイ(今回のFLUSHでバッドブロック化しなかったかチェック)*/ + for( i=0; ilogical_page) & 0x3F)); + i_nandReadPage( &NandPage, new_physical_page_addr, 1); + + for( k=0; k<4; k++) { + if( (i_nandCheckECC( (u32*)(&(NandPage.data.data[k][0])), &(NandPage.spare.ecc[k]), + *(u32*)((u32)(&(nand_ecc[0]))+(k*4))) == FALSE) || + ( rslt_writepage == FALSE)) { + //(フラッシュできなかったブロックをバッドブロック化するのはmerge関数) + //ここではマーキングのみ +// i_nandRemoveStatList( &(NandStat.busy), NandPageCache->TargetNandBlockStat); //BadBlockはfreeリストから外す + NandPageCache->NandSpareWriteForward.block_stat_bad = 0; + NandPageCache->TargetNandBlockStat->block_stat_bad = 0; +// NandPageCache->OnTheFlush = 0xFFFF; +// NandPageCache->BlockDirty = FALSE; + NandPageCache->page_flushed[((NandPageCache->logical_page) & 0x3F)] = I_NAND_FLUSH_CASHED; + PRINTLEVEL2( "%s : FLUSH failed!(bad block generated)\n", __FUNCTION__); + //Flush失敗によりnewブロックにライトが発生しないので、BlockDirtyはTRUEにしない + return( I_NAND_ERR_VERIFY_ERR); + } + } + } + + /*PageCacheを無効化*/ + NandPageCache->valid = FALSE; + NandPageCache->dirty = FALSE; + + NandPageCache->BlockDirty = TRUE; + +// PRINTDEBUG( "old : 0x%x, new : 0x%x\n", old_physical_blk, new_physical_blk); + return( I_NAND_ERR_SUCCESS); +} + + +/*---------------------------------------------------------------------------* + Name: i_nandMergeBlock + + Description: + + Arguments: + + Returns: None + *---------------------------------------------------------------------------*/ +BOOL i_nandMergeBlock( NandPageCacheFormat* NandPageCache) +{ + u16 i, k; + u16 retry_count = 0; + u16 logical_blk; + u16 old_physical_blk; + u32 old_physical_page_addr; + u16 new_physical_blk; + u32 new_physical_page_addr; + u16 merge_physical_blk; + u32 merge_physical_page_addr; + NandPageFormat NandPage; + NandBlockStatInfo* MergeNandBlockStat; + u32 bad_physical_page_addr; + u16 bad_physical_blk[NAND_FLUSH_RETRY_COUNT]; + BOOL rslt_writepage; + + /*NewBlockのECCチェックはFLUSHで逐一実行済み*/ + + PRINTDEBUG( "%s\n", __FUNCTION__); + + if( NandPageCache->OnTheFlush == 0xFFFF) { + return( FALSE); + } + + do { + /*----- Merge用にNewBlockをサーチする -----*/ + do { + MergeNandBlockStat = NandStat.free; + do { + if( MergeNandBlockStat == NULL) { /*freeブロックがない場合*/ + PRINTDEBUG( "%s : fatal error! cannot found free block.\n", __FUNCTION__); + while( 1) {}; //return( FALSE); + }else{ + break; /*見つかった*/ + } + // MergeNandBlockStat = MergeNandBlockStat->next; + }while( 1); + + merge_physical_blk = MergeNandBlockStat->physical_blk; + if( merge_physical_blk >= 1024) { + PRINTDEBUG( "%s : fatal error! illegal block number.\n", __FUNCTION__); + while( 1) {}; //return( FALSE); //不正番号 + } + /*mergeブロックの消去回数読み出し(TODO:パリティチェック)*/ + merge_physical_page_addr = (u32)(merge_physical_blk << 6); + i_nandReadPage( &NandPage, merge_physical_page_addr,1 ); + /*消去回数をインクリメントしてWriteMergeバッファに適用,論理アドレスも適用*/ + miCpuCopy8( &(NandPage.spare), &(NandPageCache->NandSpareWriteMerge), NAND_PAGE_SPARESIZE); + NandPageCache->NandSpareWriteMerge.logical_adr0 = (u16)(NandPageCache->logical_page >> 6); + NandPageCache->NandSpareWriteMerge.logical_adr1 = (u16)(NandPageCache->logical_page >> 6); + NandPageCache->NandSpareWriteMerge.block_erase_count0 = NandPage.spare.block_erase_count0 + 1; + NandPageCache->NandSpareWriteMerge.block_erase_count1 = NandPage.spare.block_erase_count1 + 1; + + /*mergeブロック消去*/ + if( i_nandEraseBlock( merge_physical_blk) == FALSE) { + PRINTLEVEL2( "bad block generated : %s, %d\n", __FUNCTION__, __LINE__); + i_nandMarkingBadBlock( merge_physical_blk, &(NandPageCache->NandSpareWriteMerge)); + i_nandRemoveStatList( &(NandStat.free), MergeNandBlockStat); + }else{ + break; + } + }while( 1); + + + /*oldブロック算出(newブロックとは必ず異なっている)*/ + logical_blk = (u16)((NandPageCache->logical_page) >> 6); + old_physical_blk = nandBlkTbl[logical_blk]; + + for( i=0; i<64; i++) { + merge_physical_page_addr = (u32)((merge_physical_blk << 6) + i); + switch( NandPageCache->page_flushed[i]) { + case I_NAND_FLUSH_FALSE:/*OldBlockからマージするデータをMergeBlockにコピーする*/ + old_physical_page_addr = (u32)((old_physical_blk<<6) + i); + i_nandReadPage( &NandPage, old_physical_page_addr, 1); + /*spare領域(消去回数,論理アドレス)変更*/ + miCpuCopy8( &(NandPageCache->NandSpareWriteMerge), &(NandPage.spare), NAND_PAGE_SPARESIZE); + //TODO:i_nandWritePageのエラーコード見る + rslt_writepage = i_nandWritePage( &NandPage, merge_physical_page_addr, 1); + break; + case I_NAND_FLUSH_CASHED:/*キャッシュからマージするデータをMergeBlockにコピーする*/ + /*spare領域(消去回数,論理アドレス)変更*/ + miCpuCopy8( &(NandPageCache->NandSpareWriteMerge), &(NandPageCache->NandPage[0].spare), + NAND_PAGE_SPARESIZE); + //TODO:i_nandWritePageのエラーコード見る + rslt_writepage = i_nandWritePage( &(NandPageCache->NandPage[0]), merge_physical_page_addr, 1); + break; + default:/*NewBlockからマージするデータをMergeBlockにコピーする*/ + if( NandPageCache->page_flushed[i] >= 0) { + new_physical_page_addr = (u32)(((NandPageCache->OnTheFlush)<<6) + + NandPageCache->page_flushed[i]); + i_nandReadPage( &NandPage, new_physical_page_addr, 1); + /*spare領域(消去回数,論理アドレス)変更*/ + miCpuCopy8( &(NandPageCache->NandSpareWriteMerge), &(NandPage.spare), NAND_PAGE_SPARESIZE); + //TODO:i_nandWritePageのエラーコード見る + rslt_writepage = i_nandWritePage( &NandPage, merge_physical_page_addr, 1); + break; + }else{ + PRINTDEBUG( "%s : fatal error! invalid status(0x%x).\n", NandPageCache->page_flushed[i]); + while( 1) {}; + } + } + if( rslt_writepage == FALSE) { + PRINTLEVEL2( "bad block generated : %s, %d\n", __FUNCTION__, __LINE__); + i_nandRemoveStatList( &(NandStat.free), MergeNandBlockStat); //BadBlockはfreeリストから外す + bad_physical_blk[retry_count] = merge_physical_blk; + goto retry; + } + } + + /* mergeをretryするとき再度freeリストから探すので、busyに移動しておく*/ + i_nandRemoveStatList( &(NandStat.free), MergeNandBlockStat); + i_nandInsertStatList( &(NandStat.busy), MergeNandBlockStat); + + /*簡易ベリファイ(今回のmergeでバッドブロック化しなかったかチェック)*/ + for( i=0; i<64; i++) { + merge_physical_page_addr = (u32)((merge_physical_blk << 6) + i); + i_nandReadPage( &NandPage, merge_physical_page_addr, 1); + for( k=0; k<4; k++) { + if( i_nandCheckECC( (u32*)(&(NandPage.data.data[k][0])), &(NandPage.spare.ecc[k]), + *(u32*)((u32)(&(nand_ecc[0]))+(k*4))) == FALSE) { + PRINTLEVEL2( "bad block generated : %s, %d\n", __FUNCTION__, __LINE__); + i_nandRemoveStatList( &(NandStat.busy), MergeNandBlockStat); //BadBlockはfreeリストから外す + bad_physical_blk[retry_count] = merge_physical_blk; + goto retry; + } + } + } + break; /* Merge成功 */ +retry: + retry_count++; + if( retry_count >= NAND_FLUSH_RETRY_COUNT) { + break; + } + PRINTDEBUG( "%s : retry merge!( blk 0x%x is bad.)\n", __FUNCTION__, + merge_physical_blk); + }while( 1); + + /*PageCacheを無効化*/ + NandPageCache->valid = FALSE; + NandPageCache->dirty = FALSE; + + //TODO:newblockを消去し、ブロック情報を書き戻す + //(TODO:テーブルをNAND上に持つようにすればこの処理は必要なし) + + /*newブロック消去*/ + new_physical_blk = NandPageCache->OnTheFlush; + if( i_nandEraseBlock( new_physical_blk) == FALSE) { + PRINTLEVEL2( "bad block generated : %s, %d\n", __FUNCTION__, __LINE__); + NandPageCache->TargetNandBlockStat->block_stat_bad = 0; + NandPageCache->NandSpareWriteForward.block_stat_bad = 0; + } + /*newブロックに書き直すスペア領域構築*/ + NandPageCache->NandSpareWriteForward.logical_adr0 = 0xFFFF; //未使用マーキング + NandPageCache->NandSpareWriteForward.logical_adr1 = 0xFFFF; + NandPageCache->NandSpareWriteForward.block_erase_count0++; + NandPageCache->NandSpareWriteForward.block_erase_count1++; + /*newブロックに書き直すデータをNandPageに作成*/ + miCpuFill8( &(NandPage.data), 0xFF, NAND_PAGE_DATASIZE); + miCpuCopy8( &(NandPageCache->NandSpareWriteForward), &(NandPage.spare), NAND_PAGE_SPARESIZE); + /*newブロックに書き込み*/ + for( i=0; i<64; i++) { + new_physical_page_addr = (u32)((new_physical_blk<<6) + i); + //TODO:i_nandWritePageのエラーコード見る + if( i_nandWritePage( &NandPage, new_physical_page_addr, 1) == FALSE) { + PRINTLEVEL2( "bad block generated : %s, %d\n", __FUNCTION__, __LINE__); + i_nandMarkingBadBlock( new_physical_blk, &(NandPage.spare)); + break; + } + } + /*-----------------------------------------------------*/ + + + /*----- OldBlockを消去し、ブロック情報を書き戻す -----*/ + //(TODO:テーブルをNAND上に持つようにすればこの処理は必要なし) + + /*oldブロック消去*/ + if( i_nandEraseBlock( old_physical_blk) == FALSE) { + PRINTLEVEL2( "bad block generated : %s, %d\n", __FUNCTION__, __LINE__); + NandBlockStat[old_physical_blk].block_stat_bad = 0; + NandPageCache->NandSpareWriteBack.block_stat_bad = 0; + } + /*oldブロックに書き直すスペア領域構築*/ + NandPageCache->NandSpareWriteBack.logical_adr0 = 0xFFFF; //未使用マーキング + NandPageCache->NandSpareWriteBack.logical_adr1 = 0xFFFF; + NandPageCache->NandSpareWriteBack.block_erase_count0++; + NandPageCache->NandSpareWriteBack.block_erase_count1++; + /*oldブロックに書き直すデータをNandPageに作成*/ + miCpuFill8( &(NandPage.data), 0xFF, NAND_PAGE_DATASIZE); + miCpuCopy8( &(NandPageCache->NandSpareWriteBack), &(NandPage.spare), NAND_PAGE_SPARESIZE); + /*oldブロックに書き込み*/ + for( i=0; i<64; i++) { + old_physical_page_addr = (u32)((old_physical_blk<<6) + i); + //TODO:i_nandWritePageのエラーコード見る + if( i_nandWritePage( &NandPage, old_physical_page_addr, 1) == FALSE) { + PRINTLEVEL2( "bad block generated : %s, %d\n", __FUNCTION__, __LINE__); + i_nandMarkingBadBlock( old_physical_page_addr, &(NandPage.spare)); + break; + } + } + /*-----------------------------------------------------*/ + + /*フラッシュできなかったmergeブロックを一気にバッドブロック化*/ + for( i=0; iOnTheFlush); + PRINTDEBUG( "merge_physical_blk:0x%x\n", merge_physical_blk); + /*---------------------------------*/ + + { + //u16 reload_logical_adr; + //u32 reload_erase_count; + + /*BlockStatリンクリスト更新*/ + /*new_physical_blkは消去回数が更新されたので、busyリストから外してfreeリストに入れ直す*/ + //memo:NandPageCache->TargetNandBlockStatはNandBlockStat[NandPageCache->OnTheFlush]でも良いはず + i_nandRemoveStatList( &(NandStat.busy), NandPageCache->TargetNandBlockStat); + NandPageCache->TargetNandBlockStat->erase_count++; + if( NandPageCache->TargetNandBlockStat->block_stat_bad == 0xFF) { //BadBlockでなければ + i_nandInsertStatList( &(NandStat.free), NandPageCache->TargetNandBlockStat); + } + + /*merge_physical_blkをbusyリストから外してbusyリストに入れ直す(ソートし直し)*/ + i_nandRemoveStatList( &(NandStat.busy), MergeNandBlockStat); + MergeNandBlockStat->erase_count++; //リンクリスト上の消去回数も更新する + i_nandInsertStatList( &(NandStat.busy), MergeNandBlockStat); + + /*old_physical_blkをbusyリストから外してfreeリストに入れる*/ + //i_nandCheckBlock( old_physical_blk, &reload_logical_adr, &reload_erase_count); + i_nandRemoveStatList( &(NandStat.busy), &(NandBlockStat[old_physical_blk])); + NandBlockStat[old_physical_blk].erase_count++; + if( NandBlockStat[old_physical_blk].block_stat_bad == 0xFF) { //BadBlockでなければ + i_nandInsertStatList( &(NandStat.free), &(NandBlockStat[old_physical_blk])); + } + } + + /**/ + for( i=0; i<64; i++) { + NandPageCache->page_flushed[i] = I_NAND_FLUSH_FALSE; + } + NandPageCache->page_flushed_count = 0; + + + NandPageCache->OnTheFlush = 0xFFFF; + NandPageCache->BlockDirty = FALSE; + + return( TRUE); +} + + +/*後発BadBlockにマーキングする(未使用、TODO:各部から呼び出す)*/ +void i_nandMarkingBadBlock( u16 physical_blk, NandSpareFormat* NandSpareOrg) +{ + u16 i; + u32 physical_page_addr; + NandPageFormat NandPage; + + miCpuFill8( &(NandPage.data.data[0][0]), 0xFF, NAND_PAGE_DATASIZE); + miCpuFill8( &(NandPage.spare), 0xFF, NAND_PAGE_SPARESIZE); + miCpuCopy8( "CTR\0", &(NandPage.spare.sig0[0]), 4); + miCpuCopy8( "CTR\0", &(NandPage.spare.sig1[0]), 4); + + NandPage.spare.block_stat_bad = 0x00; /* Bad Marking */ + NandPage.spare.block_erase_count0 = NandSpareOrg->block_erase_count0; + NandPage.spare.block_erase_count1 = NandSpareOrg->block_erase_count1; + NandPage.spare.logical_adr0 = 0xFFFF; /* 未割り当て */ + NandPage.spare.logical_adr1 = 0xFFFF; /* 未割り当て */ + + i_nandEraseBlock( physical_blk); + for( i=0; i<64; i++) { + physical_page_addr = ((u32)(physical_blk)<<6) + i; + i_nandWritePage( &NandPage, physical_page_addr, 1); + } +} + + +/*---------------------------------------------------------------------------* + Name: nandReadPageCache + + Description: PageCacheからセクタを読み出す + + Arguments: + + Returns: None + *---------------------------------------------------------------------------*/ +static void nandReadPageCache( NandPageCacheFormat* NandPageCache, u32* dest, u16 cache_sect) +{ + u16 cache_offset; + u32* cache_sect_adr; + + cache_offset = (u16)(cache_sect % 4); //PageCacheのページ内でのオフセット + + cache_sect_adr = (u32*)((u32)&(NandPageCache->NandPage[0].data.data[cache_offset][0])); + + miCpuCopy8( cache_sect_adr, dest, 512); +} + +/*---------------------------------------------------------------------------* + Name: nandWritePageCache + + Description: PageCacheにセクタを書く + + Arguments: physical_blk : 物理ブロック番号 + + Returns: None + *---------------------------------------------------------------------------*/ +static void nandWritePageCache( NandPageCacheFormat* NandPageCache, u32* src, u16 cache_sect) +{ +// u16 cache_page; + u16 cache_offset; + u32* cache_sect_adr; + +// cache_page = (u16)(cache_sect / 4); //PageCache内でのページ番号 + cache_offset = (u16)(cache_sect % 4); //PageCacheのページ内でのオフセット + + cache_sect_adr = (u32*)((u32)&(NandPageCache->NandPage[0].data.data[cache_offset][0])); + + miCpuCopy8( src, cache_sect_adr, 512); + + //ECC再計算 +} + + + + + +/*---------------------------------------------------------------------------* + Name: nandEnable + + Description: + + Arguments: + + Returns: FALSE : 失敗 + TRUE : 成功 + *---------------------------------------------------------------------------*/ +void nandEnable( NandPageCacheFormat* NandPageCache) +{ + NandMsg nandMsg; + u32 recv_dat; + + g_nandPageCache = NandPageCache; +// i_nandEnable( NandPageCache); + nandMsg.cache = NandPageCache; + nandMsg.buf = NULL; + nandMsg.sector = 0; + nandMsg.sector_count = 0; + nandMsg.operation = NAND_OPERATION_ENABLE; + +// PRINTDEBUG( "%s(%d) : snd_dtq begin\n", __FUNCTION__, __LINE__); + osSendMessage( &nand_dtq, (OSMessage*)&nandMsg, OS_MESSAGE_BLOCK); + +// PRINTDEBUG( "%s(%d) : rcv_dtq begin\n", __FUNCTION__, __LINE__); + osReceiveMessage( &nand_result_dtq, (OSMessage*)&recv_dat, OS_MESSAGE_BLOCK); + + return; +} + +/*---------------------------------------------------------------------------* + Name: nandFormat + + Description: フォーマット(スペア領域を構築)する + + Arguments: + + Returns: + *---------------------------------------------------------------------------*/ +void nandFormat( void) +{ + NandMsg nandMsg; + u32 recv_dat; + + nandMsg.cache = g_nandPageCache; + nandMsg.buf = NULL; + nandMsg.sector = 0; + nandMsg.sector_count = 0; + nandMsg.operation = NAND_OPERATION_FORMAT; + +// PRINTDEBUG( "%s(%d) : snd_dtq begin\n", __FUNCTION__, __LINE__); + osSendMessage( &nand_dtq, (OSMessage*)&nandMsg, OS_MESSAGE_BLOCK); + +// PRINTDEBUG( "%s(%d) : rcv_dtq begin\n", __FUNCTION__, __LINE__); + osReceiveMessage( &nand_result_dtq, (OSMessage*)&recv_dat, OS_MESSAGE_BLOCK); + + return; +} + +/*---------------------------------------------------------------------------* + Name: nandReadSector + + Description: 論理セクタを読み出す + + Arguments: logical_sector : 論理ブロック番号 + + Returns: FALSE : 失敗 + TRUE : 成功 + *---------------------------------------------------------------------------*/ +void nandReadSector( u32* dest, u32 logical_sector, u32 sector_count) +{ + NandMsg nandMsg; + u32 recv_dat; + + nandMsg.cache = g_nandPageCache; + nandMsg.buf = dest; + nandMsg.sector = logical_sector; + nandMsg.sector_count = sector_count; + nandMsg.operation = NAND_OPERATION_READ; + +// PRINTDEBUG( "%s(%d) : snd_dtq begin\n", __FUNCTION__, __LINE__); + osSendMessage( &nand_dtq, (OSMessage*)&nandMsg, OS_MESSAGE_BLOCK); + +// PRINTDEBUG( "%s(%d) : rcv_dtq begin\n", __FUNCTION__, __LINE__); + osReceiveMessage( &nand_result_dtq, (OSMessage*)&recv_dat, OS_MESSAGE_BLOCK); + + return; +} + +/*---------------------------------------------------------------------------* + Name: nandWriteSector + + Description: 論理セクタを書き込む + + Arguments: logical_sector : 論理ブロック番号 + + Returns: FALSE : 失敗 + TRUE : 成功 + *---------------------------------------------------------------------------*/ +void nandWriteSector( u32* src, u32 logical_sector, u32 sector_count) +{ + NandMsg nandMsg; + u32 recv_dat; +// ID tskid; + + nandMsg.cache = g_nandPageCache; + nandMsg.buf = src; + nandMsg.sector = logical_sector; + nandMsg.sector_count = sector_count; + nandMsg.operation = NAND_OPERATION_WRITE; + /* + if( get_tid( &tskid) == E_OK) { + nandMsg.tskid = tskid; + }else{ + nandMsg.tskid = 0; + }*/ + +// PRINTDEBUG( "%s(%d) : snd_dtq begin\n", __FUNCTION__, __LINE__); + osSendMessage( &nand_dtq, (OSMessage*)&nandMsg, OS_MESSAGE_BLOCK); + +// PRINTDEBUG( "%s(%d) : rcv_dtq begin\n", __FUNCTION__, __LINE__); + osReceiveMessage( &nand_result_dtq, (OSMessage*)&recv_dat, OS_MESSAGE_BLOCK); + + return; +} + +/*---------------------------------------------------------------------------* + Name: nandFlush + + Description: + + Arguments: + + Returns: FALSE : 失敗 + TRUE : 成功 + *---------------------------------------------------------------------------*/ +BOOL nandFlush( void) +{ + NandMsg nandMsg; + u32 recv_dat; + + nandMsg.cache = g_nandPageCache; + nandMsg.buf = NULL; + nandMsg.sector = 0; + nandMsg.sector_count = 0; + nandMsg.operation = NAND_OPERATION_FLUSH; + +// PRINTDEBUG( "%s(%d) : snd_dtq begin\n", __FUNCTION__, __LINE__); + osSendMessage( &nand_dtq, (OSMessage*)&nandMsg, OS_MESSAGE_BLOCK); + +// PRINTDEBUG( "%s(%d) : rcv_dtq begin\n", __FUNCTION__, __LINE__); + osReceiveMessage( &nand_result_dtq, (OSMessage*)&recv_dat, OS_MESSAGE_BLOCK); + if( recv_dat == 1) { + return( TRUE); + }else{ + return( FALSE); + } +} + +/*タスク化してないので隠し関数*/ +void nandEraseChip( void) +{ + u16 i; + for( i=0; i<1024; i++) { + i_nandEraseBlock( i); + } +} + +/*---------------------------------------------------------------------------* + Name: i_nandThread + + Description: + + Arguments: + + Returns: None + *---------------------------------------------------------------------------*/ +static void i_nandThread( void* arg) +{ + NandMsg* nandMsg; + BOOL result; + u32 current_dat; + u32 i; + u32* buf_pointer; + + result = TRUE; + while( TRUE) { + osReceiveMessage( &nand_dtq, (OSMessage*)¤t_dat, OS_MESSAGE_BLOCK); + nandMsg = (NandMsg*)current_dat; + PRINTDEBUG( "nand task : receive command : %d\n", nandMsg->operation); + + switch( nandMsg->operation) { + case NAND_OPERATION_ENABLE: + i_nandEnable( nandMsg->cache); + break; + case NAND_OPERATION_FORMAT: + i_nandFormat(); + break; + case NAND_OPERATION_READ: + PRINTDEBUG( "from:%x, sectors:%x\n", nandMsg->sector, nandMsg->sector_count); + for( i=0; isector_count; i++) { + buf_pointer = (u32*)((u32)(nandMsg->buf) + (512 * i)); + i_nandReadSector( nandMsg->cache, buf_pointer, (nandMsg->sector) + i); + } + break; + case NAND_OPERATION_WRITE: + PRINTDEBUG( "from:%x, sectors:%x\n", nandMsg->sector, nandMsg->sector_count); + /*---------- 通常の書き込み ----------*/ + for( i=0; isector_count; i++) { + buf_pointer = (u32*)((u32)(nandMsg->buf) + (512 * i)); + i_nandWriteSector( nandMsg->cache, buf_pointer, (nandMsg->sector) + i); + }/*-----------------------------------*/ + break; + case NAND_OPERATION_FLUSH: + result = i_nandFlush( nandMsg->cache); + break; + default: + break; + } + + PRINTDEBUG( "nand task : operation ends, send message begin\n"); + //メッセージ返送 + if( result) { + current_dat = 1; + }else{ + current_dat = 0; + } + osSendMessage( &nand_result_dtq, (OSMessage)current_dat, OS_MESSAGE_BLOCK); + } +} + diff --git a/trunk/bootrom/build/libraries/nand/ARM11/src/ne1/nand.h b/trunk/bootrom/build/libraries/nand/ARM11/src/ne1/nand.h new file mode 100644 index 0000000..eb91da7 --- /dev/null +++ b/trunk/bootrom/build/libraries/nand/ARM11/src/ne1/nand.h @@ -0,0 +1,121 @@ +/*---------------------------------------------------------------------------* + Project: CTR - NAND driver + File: nand.h + + Copyright 2006 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + *---------------------------------------------------------------------------*/ + +#ifndef __NAND_H__ +#define __NAND_H__ + + +#include "nandif_ip.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/*---------------------------------------------------------------------------* + 定義 + *---------------------------------------------------------------------------*/ +#define NAND_GUARANTEED_BLOCKS (999) +#define NAND_GUARANTEED_SECTORS (NAND_GUARANTEED_BLOCKS*256) //保証されたセクタ数(=使える容量) + +#define NAND_CACHE_PAGES (1) /* 1以外は設定禁止 */ +#define NAND_ANTI_READDISTURB (1) /* TODO */ + +/*---------------------------------------------------------------------------* + 構造体 + *---------------------------------------------------------------------------*/ +typedef struct NandPageCacheFormat { //ブロックキャッシュ + u16 valid; /*有効 or 無効*/ + u16 dirty; /*ダーティ or クリーン*/ + u16 OnTheFlush; /*Flush進行中のNewPhysicalBlk番号*/ + u16 reserve0; + struct NandBlockStatInfo* TargetNandBlockStat; /*Flush進行中のNewPhysicalBlk情報へのポインタ*/ + BOOL BlockDirty; /*ブロック・ダーティ or クリーン*/ +// u16 logical_blk; /*論理ブロック番号*/ + u32 logical_page; /*論理ページ番号*/ + u8 page_flushed_count; /*Flush先の物理ページオフセット(0からカウントアップ)*/ + u8 reserve1[3]; + int page_flushed[64]; /*Flushによって書き込まれた物理ページのオフセット*/ + struct NandPageFormat NandPage[NAND_CACHE_PAGES]; /*1ページ分のキャッシュメモリ*/ + u32 ecc[NAND_CACHE_PAGES][4]; /*読み出し時に自動生成されたECC*/ + struct NandSpareFormat NandSpareWriteForward; /*newブロックにライトするスペア領域*/ + struct NandSpareFormat NandSpareWriteBack; /*oldブロックにライトバックするスペア領域*/ + struct NandSpareFormat NandSpareWriteMerge; /*mergeブロックにライトするスペア領域*/ +} NandPageCacheFormat; + + +typedef struct NandBlockStatInfo { //ブロック状態リンクリスト + u16 physical_blk; + u16 block_stat_bad; + u32 erase_count; + struct NandBlockStatInfo* next; +} NandBlockStatInfo; + + +typedef struct NandStatInfo { + struct NandBlockStatInfo* busy; /*論理blk番号が割り当て済み*/ + struct NandBlockStatInfo* free; /*論理blk番号が未割り当て*/ +} NandStatInfo; + + + +/*RTFS用 FATパラメータ*/ +typedef struct { + u32 device_capacity; //デバイス全体のサイズ(512Byte単位) + u32 adjusted_device_capacity; + + u32 memory_capacity; //data areaのサイズ(512Byte単位) + u32 adjusted_memory_capacity; //memory_capacityをシリンダ(heads*secptrack)の倍数に調整したサイズ(cylinders*heads*secptrackになる) + u16 volume_cylinders; + + u16 heads; + u16 secptrack; + u16 cylinders; + u16 SC; //sectors per cluster + u16 BU; + u16 RDE; //number of root dir entries(512 fix) + u32 SS; //sector size(512 fix) + u32 RSC; //reserved sector count(1 fix) + u16 FATBITS; //16 or 32 + u16 SF; //sectors per FAT + u32 SSA; //sectors in system area + u32 NOM; //sectors in master boot record + + u32 begin_sect; +} NandSpec; + + + +/*---------------------------------------------------------------------------* + API + *---------------------------------------------------------------------------*/ +BOOL nandRtfsAttach( int driveno, int partition); + +void nandInit( void); +void nandEnable( NandPageCacheFormat* NandPageCache); +void nandFormat( void); + +void nandReadSector( u32* dest, u32 logical_sector, u32 sector_count); +void nandWriteSector( u32* src, u32 logical_sector, u32 sector_count); + +BOOL nandFlush( void); +BOOL nandCheckMedia( void); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /*__NAND_H__*/ diff --git a/trunk/bootrom/build/libraries/nand/ARM11/src/ne1/nandif.c b/trunk/bootrom/build/libraries/nand/ARM11/src/ne1/nandif.c new file mode 100644 index 0000000..41dcb1e --- /dev/null +++ b/trunk/bootrom/build/libraries/nand/ARM11/src/ne1/nandif.c @@ -0,0 +1,398 @@ +/*---------------------------------------------------------------------------* + Project: CTR - NAND driver + File: nandif.c + + Copyright 2006 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + *---------------------------------------------------------------------------*/ + +#include +#include "nandif_ip.h" +#include "nandif_reg.h" + +#if 0 +#define PRINTDEBUG osTPrintf +#else +#define PRINTDEBUG( ...) ((void)0) +#endif + + +/*---------------------------------------------------------------------------* + static関数 + *---------------------------------------------------------------------------*/ +static void i_nandWait( void); +static void i_nandStart( u16 mode); +static void i_nandSetEccDirection( u32 direction); +static void i_nandChangeBuffer( void); + +static u32 CalcECC( u32* buf); +static u32 CalcCP( u32* buf, u32 st, u32 cmp, u32 logic); +static u32 CalcLP( u32* buf, u32 st, u32 cmp, u32 logic); + +u32 nand_ecc[4]; + + +/*NAND低レベル層制御*/ +/*---------------------------------------------------------------------------* + Name: i_nandWait + + Description: オペレーションが終了するまで待つ + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +static void i_nandWait( void) +{ + u32 stat; + + while( 1) { + stat = *(vu16*)REG_NAND_COMMAND; + if( (stat & NAND_BUSY) == 0) { + return; + } + } +} + +/*---------------------------------------------------------------------------* + Name: i_nandStart + + Description: 指定したモードをスタートする + + Arguments: mode : + + Returns: None + *---------------------------------------------------------------------------*/ +static void i_nandStart( u16 mode) +{ + i_nandWait(); + *(vu32*)REG_NAND_COMMAND = (mode | NAND_START); +} + +/*---------------------------------------------------------------------------* + Name: i_nandSetEccDirection + + Description: ECCが算出される条件を指定する + + Arguments: direction : NAND_CTRL_ECC_WRITE or NAND_CTRL_ECC_READ + + Returns: None + *---------------------------------------------------------------------------*/ +static void i_nandSetEccDirection( u32 direction) +{ +} + +/*---------------------------------------------------------------------------* + Name: i_nandChangeBuffer + + Description: バッファの裏表を切り替える + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +static void i_nandChangeBuffer( void) +{ +} + +/*---------------------------------------------------------------------------* + Name: i_nandReset + + Description: HW-IPを初期状態にする + + Arguments: None + + Returns: None + *---------------------------------------------------------------------------*/ +void i_nandReset( void) +{ + /*--- HW ECC OFF ---*/ + *(vu16*)REG_NAND_ECC &= ~NAND_ENABLE_ECC; + + i_nandWait(); + *(u16*)REG_NAND_COMMAND = (NAND_RESET | NAND_START); + i_nandWait(); +} + +/*---------------------------------------------------------------------------* + Name: i_nandEraseBlock + + Description: 物理ブロックを消去する + + Arguments: physical_blk : 物理ブロック番号 + + Returns: FALSE : 失敗 + TRUE : 成功 + *---------------------------------------------------------------------------*/ +BOOL i_nandEraseBlock( u16 physical_blk) +{ +// PRINTDEBUG( ">>>@ erase physical blk : 0x%x\n", physical_blk); + + i_nandWait(); /*デバイス待ち*/ + + /*イレースするためのレジスタ設定*/ + *(u16*)REG_NAND_ADR_LO = 0; + *(u16*)REG_NAND_ADR_HI = (physical_blk << 1); + + /*書き込み開始*/ + *(u16*)REG_NAND_COMMAND = (NAND_ERASE_BLOCK | NAND_START); + +// osSleep( 1); /* 90nm(typ:2ms, max:3ms),60nm実測1.2ms */ + + i_nandWait(); /*デバイス内部消去動作中*/ +#if 0 + /*READY状態になったらPASSかFAILかを判定する*/ + while( 1) { + /*ステータスリード*/ + *(vu32*)NAND_IP_CTRL = NAND_CTRL_READSTAT | NAND_CTRL_ECC_WRITE | + (*(vu32*)NAND_IP_CTRL & NAND_CTRL_PAGE_MASK) | NAND_CTRL_SPEED_HI; + *(u32*)NAND_IP_CTRL |= NAND_CTRL_START; + /*ステータスリード*/ + i_nandWait(); + /*ステータスレジスタチェック*/ + if( *(vu16*)NAND_IP_STAT & NAND_STAT_READY) { + if( *(vu16*)NAND_IP_STAT & NAND_STAT_FAIL) { + return FALSE; + }else{ + return TRUE; + } + } + } +#else + return TRUE; +#endif +} + +/*---------------------------------------------------------------------------* + Name: i_nandReadPage + + Description: 物理ページをリードする + + Arguments: physical_page_addr : 物理ページ番号 + + Returns: + *---------------------------------------------------------------------------*/ +BOOL i_nandReadPage( NandPageFormat* dest, u32 physical_page_addr, BOOL sync) +{ + u32 byte_addr; + PRINTDEBUG( ">>>@ read physical page : 0x%x\n", physical_page_addr); + + /*IP動作中*/ + i_nandWait(); + + /*リードするためのレジスタ設定*/ + byte_addr = (physical_page_addr * NAND_PAGE_DATASIZE); + *(u16*)REG_NAND_ADR_LO = (u16)(byte_addr); + *(u16*)REG_NAND_ADR_HI = (u16)(((u32)byte_addr >> 16)); + + /*最初の1ページをリードする*/ + *(u16*)REG_NAND_COMMAND = (NAND_READ_PAGE | NAND_START); + + /*IP動作中*/ + i_nandWait(); + + if( sync) { + /*IP動作中*/ + i_nandWait(); + //ここでページバッファにデータが入った + } + + miCpuCopy16( (u16*)REG_NAND_DATA, &(dest->data.data[0][0]), NAND_PAGE_DATASIZE); + miCpuCopy16( (u16*)REG_NAND_SPARE, (u32*)&(dest->spare), NAND_PAGE_SPARESIZE); + + /*---------- ソフトウェアECC ----------*/ + { + u32 q_addr = (u32)(&(dest->data.data[0][0])); + nand_ecc[0] = CalcECC( (u32*)q_addr); + nand_ecc[1] = CalcECC( (u32*)(q_addr + 512)); + nand_ecc[2] = CalcECC( (u32*)(q_addr + 1024)); + nand_ecc[3] = CalcECC( (u32*)(q_addr + 1536)); + } + /*-------------------------------------*/ + + return TRUE; +} + + +/*---------------------------------------------------------------------------* + Name: i_nandWritePage + + Description: 物理ページに書き込む + 予め該当ページをイレースしておくこと。 + + Arguments: physical_page_addr : 物理ページ番号 + + Returns: + *---------------------------------------------------------------------------*/ +BOOL i_nandWritePage( NandPageFormat* src, u32 physical_page_addr, BOOL sync) +{ + u32 byte_addr; + PRINTDEBUG( ">>>@ write physical page : 0x%x\n", physical_page_addr); + + /*IP動作中*/ + i_nandWait(); + + /*DataとSpare*/ + miCpuCopy16( &(src->data.data[0][0]), (u16*)REG_NAND_DATA, NAND_PAGE_DATASIZE); //2KB + /*---------- ソフトウェアECC ----------*/ + { + u32 q_addr = (u32)(&(src->data.data[0][0])); + nand_ecc[0] = CalcECC( (u32*)(q_addr)); + nand_ecc[1] = CalcECC( (u32*)(q_addr + 512)); + nand_ecc[2] = CalcECC( (u32*)(q_addr + 1024)); + nand_ecc[3] = CalcECC( (u32*)(q_addr + 1536)); + } + /*-------------------------------------*/ + miCpuCopy16( &(nand_ecc[0]), &(src->spare.ecc[0]), 4); + miCpuCopy16( &(nand_ecc[1]), &(src->spare.ecc[1]), 4); + miCpuCopy16( &(nand_ecc[2]), &(src->spare.ecc[2]), 4); + miCpuCopy16( &(nand_ecc[3]), &(src->spare.ecc[3]), 4); + miCpuCopy16( &(src->spare), (u16*)REG_NAND_SPARE, NAND_PAGE_SPARESIZE); + + /*ライトするためのレジスタ設定*/ + byte_addr = (physical_page_addr * NAND_PAGE_DATASIZE); + *(u16*)REG_NAND_ADR_LO = (u16)(byte_addr); + *(u16*)REG_NAND_ADR_HI = (u16)(((u32)byte_addr >> 16)); + + *(u16*)REG_NAND_COMMAND = (NAND_PROGRAM_PAGE | NAND_START); + + if( sync) { + /*IP動作中*/ + i_nandWait(); +#if 0 + /*READY状態になったらPASSかFAILかを判定する*/ + while( 1) { + /*ステータスリード*/ + *(vu32*)NAND_IP_CTRL = NAND_CTRL_READSTAT | NAND_CTRL_ECC_WRITE | + (*(vu32*)NAND_IP_CTRL & NAND_CTRL_PAGE_MASK) | NAND_CTRL_SPEED_HI; + *(u32*)NAND_IP_CTRL |= NAND_CTRL_START; + + /*IP動作中*/ + i_nandWait(); + /*ステータスレジスタチェック*/ + if( *(vu16*)NAND_IP_STAT & NAND_STAT_READY) { + if( *(vu16*)NAND_IP_STAT & NAND_STAT_FAIL) { + return FALSE; + }else{ + return TRUE; + } + } + } +#else + return TRUE; +#endif + }else{ + return TRUE; + } +} + + +static u32 CalcECC( u32* buf) +{ + u32 cp[10]; + u32 lp[14]; + u32 cym; + + cp[0] = CalcCP( buf, 0, 0x1, 0); + cp[1] = CalcCP( buf, 1, 0x1, 1); + cp[2] = CalcCP( buf, 0, 0x2, 0); + cp[3] = CalcCP( buf, 2, 0x2, 1); + cp[4] = CalcCP( buf, 0, 0x4, 0); + cp[5] = CalcCP( buf, 4, 0x4, 1); + cp[6] = CalcCP( buf, 0, 0x8, 0); + cp[7] = CalcCP( buf, 8, 0x8, 1); + cp[8] = CalcCP( buf, 0x00, 0x10, 0); + cp[9] = CalcCP( buf, 0x10, 0x10, 1); + + lp[0] = CalcLP( buf, 0, 0x1, 0); + lp[1] = CalcLP( buf, 1, 0x1, 1); + lp[2] = CalcLP( buf, 0, 0x2, 0); + lp[3] = CalcLP( buf, 2, 0x2, 1); + lp[4] = CalcLP( buf, 0, 0x4, 0); + lp[5] = CalcLP( buf, 4, 0x4, 1); + lp[6] = CalcLP( buf, 0, 0x8, 0); + lp[7] = CalcLP( buf, 8, 0x8, 1); + lp[8] = CalcLP( buf, 0x00, 0x10, 0); + lp[9] = CalcLP( buf, 0x10, 0x10, 1); + lp[10] = CalcLP( buf, 0x00, 0x20, 0); + lp[11] = CalcLP( buf, 0x20, 0x20, 1); + lp[12] = CalcLP( buf, 0x00, 0x40, 0); + lp[13] = CalcLP( buf, 0x40, 0x40, 1); + + cym = ((lp[13] & 0x1) << 23) + + ((lp[12] & 0x1) << 22) + + ((lp[11] & 0x1) << 21) + + ((lp[10] & 0x1) << 20) + + ((lp[ 9] & 0x1) << 19) + + ((lp[ 8] & 0x1) << 18) + + ((lp[ 7] & 0x1) << 17) + + ((lp[ 6] & 0x1) << 16) + + ((lp[ 5] & 0x1) << 15) + + ((lp[ 4] & 0x1) << 14) + + ((lp[ 3] & 0x1) << 13) + + ((lp[ 2] & 0x1) << 12) + + ((lp[ 1] & 0x1) << 11) + + ((lp[ 0] & 0x1) << 10) + + ((cp[ 9] & 0x1) << 9) + + ((cp[ 8] & 0x1) << 8) + + ((cp[ 7] & 0x1) << 7) + + ((cp[ 6] & 0x1) << 6) + + ((cp[ 5] & 0x1) << 5) + + ((cp[ 4] & 0x1) << 4) + + ((cp[ 3] & 0x1) << 3) + + ((cp[ 2] & 0x1) << 2) + + ((cp[ 1] & 0x1) << 1) + + ((cp[ 0] & 0x1) << 0); +// osTPrintf( "cym:0x%x\n", cym); + return( cym); +} + +static u32 CalcCP( u32* buf, u32 st, u32 cmp, u32 logic) +{ + u32 cp; + u32 cmp0; + u32 i, j; + + cp = 0; + for( j=st; j<32; j++) { + if( (j & cmp) == 0) { + cmp0 = 0; + }else{ + cmp0 = 1; + } + if( cmp0 == logic) { + for( i=0; i<128; i++) { + cp ^= ((buf[i] >> j) & 0x1); + } + } + } + return cp; +} + +static u32 CalcLP( u32* buf, u32 st, u32 cmp, u32 logic) +{ + u32 lp; + u32 cmp0; + u32 i, j; + + lp = 0; + for( i=st; i<128; i++) { + if( (i & cmp) == 0) { + cmp0 = 0; + }else{ + cmp0 = 1; + } + if( cmp0 == logic) { + for( j=0; j<32; j++) { + lp ^= ((buf[i] >> j) & 0x1); + } + } + } + return lp; +} + diff --git a/trunk/bootrom/build/libraries/nand/ARM11/src/ne1/nandif_ip.h b/trunk/bootrom/build/libraries/nand/ARM11/src/ne1/nandif_ip.h new file mode 100644 index 0000000..eec85f4 --- /dev/null +++ b/trunk/bootrom/build/libraries/nand/ARM11/src/ne1/nandif_ip.h @@ -0,0 +1,86 @@ +/*---------------------------------------------------------------------------* + Project: CTR - NAND driver + File: nandif_ip.h + + Copyright 2006 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + *---------------------------------------------------------------------------*/ + +#ifndef __NAND_IF_IP_H__ +#define __NAND_IF_IP_H__ + + +#ifdef __cplusplus +extern "C" { +#endif + +/*---------------------------------------------------------------------------* + 定数定義 + *---------------------------------------------------------------------------*/ +#define NAND_PAGE_DATASIZE (2048) +#define NAND_PAGE_SPARESIZE (64) +#define NAND_PAGE_ALLSIZE (NAND_PAGE_DATASIZE + NAND_PAGE_SPARESIZE) + + +/*---------------------------------------------------------------------------* + 構造体 + *---------------------------------------------------------------------------*/ +typedef struct NandSpareFormat {/*スペア領域 64バイト*/ + u8 block_stat_bad; // 1 ブロックステータス(バッドブロック) + u8 block_stat_warning; // 1 ブロックステータス(注意ブロック) + u8 page_stat; // 1 ページステータス + u8 pad0; // 1 + u32 block_erase_count0; // 4 ブロック消去回数(パリティ付き) + u16 logical_adr0; // 2 論理アドレス(パリティ付き) + u16 pad1; // 2 + u32 ecc[4]; //16 ECC 0〜3 + u32 block_erase_count1; // 4 ブロック消去回数(パリティ付き)予備 + u16 logical_adr1; // 2 論理アドレス(パリティ付き)予備 + u16 pad2; // 2 + char sig0[4]; // 4 Signature"CTR\0" + char sig1[4]; // 4 Signature"CTR\0" + u8 reserve[20]; //28 予約 +} NandSpareFormat; + +typedef struct NandDataFormat { /*データ領域 2048バイト*/ + u32 data[4][512/4]; +/* u32 data0[512/4]; //データ領域1/4(512バイト) + u32 data1[512/4]; //データ領域2/4(512バイト) + u32 data2[512/4]; //データ領域3/4(512バイト) + u32 data3[512/4]; //データ領域4/4(512バイト)*/ +} NandDataFormat; + +typedef struct NandPageFormat { /*ページ全体*/ + struct NandDataFormat data; + struct NandSpareFormat spare; //スペア領域(64バイト) +} NandPageFormat; + + +/* +typedef struct NandSysFormat { + u16 logical_adr; + u16 read_count; + u32 erase_count; +} NandSysFormat;*/ + + + +/*---------------------------------------------------------------------------* + API + *---------------------------------------------------------------------------*/ +BOOL i_nandEraseBlock( u16 physical_blk); +BOOL i_nandReadPage( NandPageFormat* dest, u32 physical_page_addr, BOOL sync); +BOOL i_nandWritePage( NandPageFormat* src, u32 physical_page_addr, BOOL sync); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /*__NAND_IF_IP_H__*/ diff --git a/trunk/bootrom/build/libraries/nand/ARM11/src/ne1/nandif_reg.h b/trunk/bootrom/build/libraries/nand/ARM11/src/ne1/nandif_reg.h new file mode 100644 index 0000000..3ae363c --- /dev/null +++ b/trunk/bootrom/build/libraries/nand/ARM11/src/ne1/nandif_reg.h @@ -0,0 +1,125 @@ +/*---------------------------------------------------------------------------* + Project: CTR - NAND driver + File: nandif_reg.h + + Copyright 2006 Nintendo. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + *---------------------------------------------------------------------------*/ + +#ifndef __NAND_IP_REG_H__ +#define __NAND_IP_REG_H__ + + + + +//REG_NAND_COMMAND +#define NAND_START (0x0100) +#define NAND_BUSY NAND_START +#define NAND_RESET 6 +#define NAND_READ_STATUS 5 +#define NAND_ERASE_BLOCK 4 +#define NAND_PROGRAM_PAGE 3 +#define NAND_READ_PAGE 1 + +//REG_NAND_ECC +#define NAND_ENABLE_ECC 1 + +#define REG_NAND_ADR_LO (0x18019840) +#define REG_NAND_ADR_HI (0x18019842) +#define REG_NAND_COMMAND (0x1801984E) + +#define REG_NAND_ECC (0x18019850) + +#define REG_NAND_DATA (0x18019000) +#define REG_NAND_SPARE (0x18019800) + + +#define NAND_IP_ECC_0 (0x0100) //ダミー + +#if 0 +/********************************************* + NAND IPレジスタ + + (R/W) : readable and writable + (RO) : read only +*********************************************/ +#if (CTR_DEF_ENVIRONMENT_DSEMU == 1) +#define NAND_IP_BASE (0x08020000) +#else +#define NAND_IP_BASE (0x400D0000) // IOP実機設定 +#endif + + +#define NAND_IP_CADDR (NAND_IP_BASE + 0x0000) //16bit +#define NAND_IP_PADDR (NAND_IP_BASE + 0x0004) //24bit + dummy8bit +#define NAND_IP_COMMAND (NAND_IP_BASE + 0x0008) //0,1,2,3 +#define NAND_IP_CTRL (NAND_IP_BASE + 0x000C) //32bit +#define NAND_IP_ID (NAND_IP_BASE + 0x0010) //48bit +#define NAND_IP_ID_H (NAND_IP_BASE + 0x0014) +#define NAND_IP_STAT (NAND_IP_BASE + 0x0018) //16bit +#define NAND_IP_ECC_0 (NAND_IP_BASE + 0x0100) +#define NAND_IP_ECC_1 (NAND_IP_BASE + 0x0104) +#define NAND_IP_ECC_2 (NAND_IP_BASE + 0x0108) +#define NAND_IP_ECC_3 (NAND_IP_BASE + 0x010C) +#define NAND_IP_SPARE (NAND_IP_BASE + 0x0400) // 64BYTE +#define NAND_IP_DATA (NAND_IP_BASE + 0x0800) //2048BYTE + + + +/*コマンドレジスタに入れる値の詳細値*/ +#define NAND_COM_WRITE (0x00701080) //0x70:StatRead, 0x10:AutoProgram, 0x80:DataInput +#define NAND_COM_READ (0x00003000) //0x30:ReadStart, 0x00:ReadAdrInput +#define NAND_COM_ERASE (0x0070D060) //0x70:StatRead, 0xD0:EraseStart, 0x60:EraseSetup +#define NAND_COM_READID (0x00000090) + +/*コントロールレジスタに入れる値の詳細値*/ +#define NAND_CTRL_READSTAT (0x0010) //10000b +#define NAND_CTRL_READID (0x0011) +#define NAND_CTRL_WRITE (0x0012) +#define NAND_CTRL_ERASE (0x0013) +#define NAND_CTRL_READ_SETUP (0x0014) +#define NAND_CTRL_READ_2112 (0x000d) + +#define NAND_CTRL_RDY_MASK ((u32)0x1<<15) + +#define NAND_CTRL_ECC_WRITE (0) +#define NAND_CTRL_ECC_READ ((u32)0x1<<24) + +#define NAND_CTRL_PAGE_0 (0) +#define NAND_CTRL_PAGE_1 ((u32)1<<25) +#define NAND_CTRL_PAGE_MASK ((u32)1<<25) +#define NAND_CTRL_PAGE_SHIFT (25) + +#define NAND_CTRL_W8MHZ (0) +#define NAND_CTRL_W11MHZ ((u32)0x1<<26) +#define NAND_CTRL_W16MHZ ((u32)0x2<<26) + +#define NAND_CTRL_R8MHZ (0) +#define NAND_CTRL_R11MHZ ((u32)0x1<<28) + +#define NAND_CTRL_START ((u32)0x1<<31) +#define NAND_CTRL_START_MASK ((u32)0x1<<31) + + +/**/ +#define NAND_CTRL_SPEED_LO (NAND_CTRL_W8MHZ | NAND_CTRL_R8MHZ) +#define NAND_CTRL_SPEED_MIDDLE (NAND_CTRL_W11MHZ | NAND_CTRL_R11MHZ) +#define NAND_CTRL_SPEED_HI (NAND_CTRL_W16MHZ | NAND_CTRL_R11MHZ) + + +/*ステータスレジスタの詳細値*/ +#define NAND_STAT_FAIL (1) //NAND_STAT_READY状態で有効 +#define NAND_STAT_READY (1<<6) //60nm品対応 +#define NAND_STAT_NOPROTECT (1<<7) + + +/*ID_Hレジスタに入れる値の詳細値*/ +#define NAND_ID_H_FIFTH_MASK (0x8000) +#endif + +#endif /*__NAND_IP_REG_H__*/ diff --git a/trunk/bootrom/build/libraries/nand/ARM9/Makefile b/trunk/bootrom/build/libraries/nand/ARM9/Makefile new file mode 100644 index 0000000..be1a642 --- /dev/null +++ b/trunk/bootrom/build/libraries/nand/ARM9/Makefile @@ -0,0 +1,55 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: CtrBrom - libraries_sp - mi +# File: Makefile +# +# Copyright 2008-2009 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev$ +# $Author$ +#---------------------------------------------------------------------------- + +SUBDIRS = +#SUBMAKES = Makefile.CALLTRACE \ +# Makefile.FUNCTIONCOST + +#---------------------------------------------------------------------------- + +# build ARM & THUMB libraries +BROM_CODEGEN_ALL ?= TRUE + +# Codegen for sub processer +BROM_PROC = ARM9 + +SRCDIR = . ../common + +SRCS = \ + mi_memory.c \ + mi_exclusive.c \ + +TARGET_LIB = libmi_sp$(BROM_LIBSUFFIX).a + + +#---------------------------------------------------------------------------- + +include $(CTRBROM_ROOT)/build/buildtools/commondefs + +INSTALL_TARGETS = $(TARGETS) +INSTALL_DIR = $(BROM_INSTALL_LIBDIR) + + +#---------------------------------------------------------------------------- + +do-build: $(TARGETS) + +include $(CTRBROM_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/trunk/bootrom/build/libraries/nand/Makefile b/trunk/bootrom/build/libraries/nand/Makefile new file mode 100644 index 0000000..4c959d5 --- /dev/null +++ b/trunk/bootrom/build/libraries/nand/Makefile @@ -0,0 +1,34 @@ +#! make -f +#---------------------------------------------------------------------------- +# Project: CtrBrom - libraries - mi +# File: Makefile +# +# Copyright 2008 Nintendo. All rights reserved. +# +# These coded instructions, statements, and computer programs contain +# proprietary information of Nintendo of America Inc. and/or Nintendo +# Company Ltd., and are protected by Federal copyright law. They may +# not be disclosed to third parties or copied or duplicated in any form, +# in whole or in part, without the prior written consent of Nintendo. +# +# $Date:: $ +# $Rev$ +# $Author$ +#---------------------------------------------------------------------------- + +include $(CTRBROM_ROOT)/build/buildtools/commondefs + +#---------------------------------------------------------------------------- + +SUBDIRS = ARM11 + +#ifdef CTR_WITH_ARM9 +SUBDIRS += ARM9 +#endif + +#---------------------------------------------------------------------------- + +include $(CTRBROM_ROOT)/build/buildtools/modulerules + + +#===== End of Makefile ===== diff --git a/trunk/tools/bootrom/ne1tb/nand_deviceformat.axf b/trunk/tools/bootrom/ne1tb/nand_deviceformat.axf new file mode 100644 index 0000000..f09e52a Binary files /dev/null and b/trunk/tools/bootrom/ne1tb/nand_deviceformat.axf differ diff --git a/trunk/tools/bootrom/ne1tb/readme.txt b/trunk/tools/bootrom/ne1tb/readme.txt index 986b9f2..856f1f0 100644 --- a/trunk/tools/bootrom/ne1tb/readme.txt +++ b/trunk/tools/bootrom/ne1tb/readme.txt @@ -10,3 +10,6 @@ NE1 ・"export CTR_PLATFORM=NE1EMU" または "make CTR_PLATFORM=NE1EMU" でビルドして下さい。 ・"export CTR_DEBUGGER=KMC" または "make CTR_DEBUGGER=KMC" でビルドして下さい。 + +・PARTNERを使ってNE1ボードへnand_deviceformat.axfをロードして実行すると、 + NANDがデバイスレベルでフォーマットされます(ファイルシステムのフォーマットではなく)。