Beispiel #1
0
static BOOL32 check_format_mark(void)
{
	// This function reads a flash page from (bank #0, block #0) in order to check whether the SSD is formatted or not.

#ifdef __GNUC__
	extern UINT32 size_of_firmware_image;
	UINT32 firmware_image_pages = (((UINT32) (&size_of_firmware_image)) + BYTES_PER_FW_PAGE - 1) / BYTES_PER_FW_PAGE;
#else
	extern UINT32 Image$$ER_CODE$$RO$$Length;
	extern UINT32 Image$$ER_RW$$RW$$Length;
	UINT32 firmware_image_bytes = ((UINT32) &Image$$ER_CODE$$RO$$Length) + ((UINT32) &Image$$ER_RW$$RW$$Length);
	UINT32 firmware_image_pages = (firmware_image_bytes + BYTES_PER_FW_PAGE - 1) / BYTES_PER_FW_PAGE;
#endif

	UINT32 format_mark_page_offset = FW_PAGE_OFFSET + firmware_image_pages;
	UINT32 temp;

	flash_clear_irq();	// clear any flash interrupt flags that might have been set

	SETREG(FCP_CMD, FC_COL_ROW_READ_OUT);
	SETREG(FCP_BANK, REAL_BANK(0));
	SETREG(FCP_OPTION, FO_E);
	SETREG(FCP_DMA_ADDR, FTL_BUF_ADDR); 	// flash -> DRAM
	SETREG(FCP_DMA_CNT, BYTES_PER_SECTOR);
	SETREG(FCP_COL, 0);
	SETREG(FCP_ROW_L(0), format_mark_page_offset);
	SETREG(FCP_ROW_H(0), format_mark_page_offset);

	// At this point, we do not have to check Waiting Room status before issuing a command,
	// because scan list loading has been completed just before this function is called.
	SETREG(FCP_ISSUE, NULL);

	// wait for the FC_COL_ROW_READ_OUT command to be accepted by bank #0
	while ((GETREG(WR_STAT) & 0x00000001) != 0);

	// wait until bank #0 finishes the read operation
	while (BSP_FSM(0) != BANK_IDLE);

	// Now that the read operation is complete, we can check interrupt flags.
	temp = BSP_INTR(0) & FIRQ_ALL_FF;

	// clear interrupt flags
	CLR_BSP_INTR(0, 0xFF);

	if (temp != 0)
	{
		return FALSE;	// the page contains all-0xFF (the format mark does not exist.)
	}
	else
	{
		return TRUE;	// the page contains something other than 0xFF (it must be the format mark)
	}
}
Beispiel #2
0
void ftl_isr(void)
{
	// interrupt service routine for flash interrupts

	UINT32 bank;
	UINT32 bsp_intr_flag;

	for (bank = 0; bank < NUM_BANKS; bank++)
	{
		while (BSP_FSM(bank) != BANK_IDLE);

		bsp_intr_flag = BSP_INTR(bank);

		if (bsp_intr_flag == 0)
		{
			continue;
		}

		UINT32 fc = GETREG(BSP_CMD(bank));

		CLR_BSP_INTR(bank, bsp_intr_flag);

		if (bsp_intr_flag & FIRQ_DATA_CORRUPT)
		{
			g_read_fail_count++;
		}

		if (bsp_intr_flag & (FIRQ_BADBLK_H | FIRQ_BADBLK_L))
		{
			if (fc == FC_COL_ROW_IN_PROG || fc == FC_IN_PROG || fc == FC_PROG)
			{
				g_program_fail_count++;
			}
			else
			{
				ASSERT(fc == FC_ERASE);
				g_erase_fail_count++;
			}
		}
	}

	// clear the flash interrupt flag at the interrupt controller
	SETREG(APB_INT_STS, INTR_FLASH);
}
Beispiel #3
0
// BSP interrupt service routine
void ftl_isr(void)
{
    UINT32 bank;
    UINT32 bsp_intr_flag;

    uart_print("BSP interrupt occured...");
    // interrupt pending clear (ICU)
    SETREG(APB_INT_STS, INTR_FLASH);

    for (bank = 0; bank < NUM_BANKS; bank++) {
        while (BSP_FSM(bank) != BANK_IDLE);
        // get interrupt flag from BSP
        bsp_intr_flag = BSP_INTR(bank);

        if (bsp_intr_flag == 0) {
            continue;
        }
        UINT32 fc = GETREG(BSP_CMD(bank));
        // BSP clear
        CLR_BSP_INTR(bank, bsp_intr_flag);

        // interrupt handling
		if (bsp_intr_flag & FIRQ_DATA_CORRUPT) {
            uart_printf("BSP interrupt at bank: 0x%x", bank);
            uart_print("FIRQ_DATA_CORRUPT occured...");
		}
		if (bsp_intr_flag & (FIRQ_BADBLK_H | FIRQ_BADBLK_L)) {
            uart_printf("BSP interrupt at bank: 0x%x", bank);
			if (fc == FC_COL_ROW_IN_PROG || fc == FC_IN_PROG || fc == FC_PROG) {
                uart_print("find runtime bad block when block program...");
			}
			else {
                uart_printf("find runtime bad block when block erase...vblock #: %d", GETREG(BSP_ROW_H(bank)) / PAGES_PER_BLK);
				ASSERT(fc == FC_ERASE);
			}
		}
    }
}
Beispiel #4
0
static void write_format_mark(void)
{
	// This function writes a format mark to a page at (bank #0, block #0).

#ifdef __GNUC__
	extern UINT32 size_of_firmware_image;
	UINT32 firmware_image_pages = (((UINT32) (&size_of_firmware_image)) + BYTES_PER_FW_PAGE - 1) / BYTES_PER_FW_PAGE;
#else
	extern UINT32 Image$$ER_CODE$$RO$$Length;
	extern UINT32 Image$$ER_RW$$RW$$Length;
	UINT32 firmware_image_bytes = ((UINT32) &Image$$ER_CODE$$RO$$Length) + ((UINT32) &Image$$ER_RW$$RW$$Length);
	UINT32 firmware_image_pages = (firmware_image_bytes + BYTES_PER_FW_PAGE - 1) / BYTES_PER_FW_PAGE;
#endif

	UINT32 format_mark_page_offset = FW_PAGE_OFFSET + firmware_image_pages;

	mem_set_dram(FTL_BUF_ADDR, 0, BYTES_PER_SECTOR);

	SETREG(FCP_CMD, FC_COL_ROW_IN_PROG);
	SETREG(FCP_BANK, REAL_BANK(0));
	SETREG(FCP_OPTION, FO_E | FO_B_W_DRDY);
	SETREG(FCP_DMA_ADDR, FTL_BUF_ADDR); 	// DRAM -> flash
	SETREG(FCP_DMA_CNT, BYTES_PER_SECTOR);
	SETREG(FCP_COL, 0);
	SETREG(FCP_ROW_L(0), format_mark_page_offset);
	SETREG(FCP_ROW_H(0), format_mark_page_offset);

	// At this point, we do not have to check Waiting Room status before issuing a command,
	// because we have waited for all the banks to become idle before returning from format().
	SETREG(FCP_ISSUE, NULL);

	// wait for the FC_COL_ROW_IN_PROG command to be accepted by bank #0
	while ((GETREG(WR_STAT) & 0x00000001) != 0);

	// wait until bank #0 finishes the write operation
	while (BSP_FSM(0) != BANK_IDLE);
}
Beispiel #5
0
static void build_bad_blk_list(void)
{
	UINT32 bank, num_entries, result, vblk_offset;
	scan_list_t* scan_list = (scan_list_t*) TEMP_BUF_ADDR;

	mem_set_dram(BAD_BLK_BMP_ADDR, NULL, BAD_BLK_BMP_BYTES);

	disable_irq();

	flash_clear_irq();

	for (bank = 0; bank < NUM_BANKS; bank++)
	{
		SETREG(FCP_CMD, FC_COL_ROW_READ_OUT);
		SETREG(FCP_BANK, REAL_BANK(bank));
		SETREG(FCP_OPTION, FO_E);
		SETREG(FCP_DMA_ADDR, (UINT32) scan_list);
		SETREG(FCP_DMA_CNT, SCAN_LIST_SIZE);
		SETREG(FCP_COL, 0);
		SETREG(FCP_ROW_L(bank), SCAN_LIST_PAGE_OFFSET);
		SETREG(FCP_ROW_H(bank), SCAN_LIST_PAGE_OFFSET);

		SETREG(FCP_ISSUE, NULL);
		while ((GETREG(WR_STAT) & 0x00000001) != 0);
		while (BSP_FSM(bank) != BANK_IDLE);

		num_entries = NULL;
		result = OK;

		if (BSP_INTR(bank) & FIRQ_DATA_CORRUPT)
		{
			result = FAIL;
		}
		else
		{
			UINT32 i;

			num_entries = read_dram_16(&(scan_list->num_entries));

			if (num_entries > SCAN_LIST_ITEMS)
			{
				result = FAIL;
			}
			else
			{
				for (i = 0; i < num_entries; i++)
				{
					UINT16 entry = read_dram_16(scan_list->list + i);
					UINT16 pblk_offset = entry & 0x7FFF;

					if (pblk_offset == 0 || pblk_offset >= PBLKS_PER_BANK)
					{
						#if OPTION_REDUCED_CAPACITY == FALSE
						result = FAIL;
						#endif
					}
					else
					{
						write_dram_16(scan_list->list + i, pblk_offset);
					}
				}
			}
		}

		if (result == FAIL)
		{
			num_entries = 0;  // We cannot trust this scan list. Perhaps a software bug.
		}
		else
		{
			write_dram_16(&(scan_list->num_entries), 0);
		}

		g_bad_blk_count[bank] = 0;

		for (vblk_offset = 1; vblk_offset < VBLKS_PER_BANK; vblk_offset++)
		{
			BOOL32 bad = FALSE;

			#if OPTION_2_PLANE
			{
				UINT32 pblk_offset;

				pblk_offset = vblk_offset * NUM_PLANES;

                // fix bug@jasmine v.1.1.0
				if (mem_search_equ_dram(scan_list, sizeof(UINT16), num_entries + 1, pblk_offset) < num_entries + 1)
				{
					bad = TRUE;
				}

				pblk_offset = vblk_offset * NUM_PLANES + 1;

                // fix bug@jasmine v.1.1.0
				if (mem_search_equ_dram(scan_list, sizeof(UINT16), num_entries + 1, pblk_offset) < num_entries + 1)
				{
					bad = TRUE;
				}
			}
			#else
			{
                // fix bug@jasmine v.1.1.0
				if (mem_search_equ_dram(scan_list, sizeof(UINT16), num_entries + 1, vblk_offset) < num_entries + 1)
				{
					bad = TRUE;
				}
			}
			#endif

			if (bad)
			{
				g_bad_blk_count[bank]++;
				set_bit_dram(BAD_BLK_BMP_ADDR + bank*(VBLKS_PER_BANK/8 + 1), vblk_offset);
			}
		}
	}
}
void NANDController::outputLogicBankFSM(int bank)
{
	uint32_t r_data = 0;
	uint32_t *index = &(curIdx[bank]);
	signal_t signals;
	uint8_t w_data_l;
	uint8_t w_data_h;

	//Default outputs
	tmp_flash_sout[bank] = 34; //CEn = disable
	tmp_flash_dout[bank] = 0;

	switch(getRegister(BSP_FSM(bank)))
	{
		case BS_IDLE:
			//do nothing.
			break;


			//////////////////////////////Read Status//////////////////////////////
		case BS_RS_CMD:
			signals.CLE = ENABLE;
			signals.CEn = ENABLEn;
			signals.WEn = ENABLEn;
			signals.ALE = DISABLE;
			signals.REn = DISABLEn;
			signals.WPn = DISABLEn; //fix

			tmp_flash_sout[bank] = encodingSignals(signals);
			tmp_flash_dout[bank] = FCMD_READ_STATE;
			break;

		case BS_RS_DATA:
			r_data = flash_din_SSlave[bank];
			printf( "Read data: 0x%x\n", r_data);
			break;


			//////////////////////////////Read//////////////////////////////
		case BS_READ_CMD_1:
			signals.CLE = ENABLE;
			signals.CEn = ENABLEn;
			signals.WEn = ENABLEn;
			signals.ALE = DISABLE;
			signals.REn = DISABLEn;
			signals.WPn = DISABLEn; //fix

			tmp_flash_sout[bank] = encodingSignals(signals);
			tmp_flash_dout[bank] = FCMD_READ_1;
			break;

		case BS_READ_COL_1: //two column addresses are zero.
		case BS_READ_COL_2:
			signals.CLE = DISABLE;
			signals.CEn = ENABLEn;
			signals.WEn = ENABLEn;
			signals.ALE = ENABLE;
			signals.REn = DISABLEn;
			signals.WPn = DISABLEn; //fix

			tmp_flash_sout[bank] = encodingSignals(signals);
			tmp_flash_dout[bank] = 0; //fix
			break;

		case BS_READ_ROW_1:
			signals.CLE = DISABLE;
			signals.CEn = ENABLEn;
			signals.WEn = ENABLEn;
			signals.ALE = ENABLE;
			signals.REn = DISABLEn;
			signals.WPn = DISABLEn; //fix

			tmp_flash_sout[bank] = encodingSignals(signals);
			tmp_flash_dout[bank] = getRegister(BSP_ROW_L(bank));
			break;

		case BS_READ_ROW_2:
			signals.CLE = DISABLE;
			signals.CEn = ENABLEn;
			signals.WEn = ENABLEn;
			signals.ALE = ENABLE;
			signals.REn = DISABLEn;
			signals.WPn = DISABLEn; //fix

			tmp_flash_sout[bank] = encodingSignals(signals);
			tmp_flash_dout[bank] = getRegister(BSP_ROW_H(bank));
			break;

		case BS_READ_CMD_2:
			signals.CLE = ENABLE;
			signals.CEn = ENABLEn;
			signals.WEn = ENABLEn;
			signals.ALE = DISABLE;
			signals.REn = DISABLEn;
			signals.WPn = DISABLEn; //fix

			tmp_flash_sout[bank] = encodingSignals(signals);
			tmp_flash_dout[bank] = FCMD_READ_2;
			break;

		case BS_READ_WAIT:
			signals.CLE = DISABLE;
			signals.CEn = ENABLEn;
			signals.WEn = DISABLEn;
			signals.ALE = DISABLE;
			signals.REn = DISABLEn;
			signals.WPn = DISABLEn; //fix

			tmp_flash_sout[bank] = encodingSignals(signals);
			break;

		case BS_READ_DATA: //1024 iteration: using curReadIdx
			signals.CLE = DISABLE;
			signals.CEn = ENABLEn;
			signals.WEn = DISABLEn;
			signals.ALE = DISABLE;
			signals.REn = ENABLEn;
			signals.WPn = DISABLEn; //fix

			if(flash_inputSignal_active[bank]) {
				//read data
				r_data = flash_din_SSlave[bank]; //16bit i/o
				buffers[bank][(*index)] = (uint8_t)(r_data & 0x00FF);
				buffers[bank][(*index)+1] = (uint8_t)((r_data & 0xFF00) >> 8);

				//if(p_enableDbgMsg)
				printf( "[Bank#%d] Read data: 0x%X, index: %d\n", bank, r_data, *index);

				(*index) += 2;
			}
			else {
				flash_inputSignal_active[bank] = true;
			}

			tmp_flash_sout[bank] = encodingSignals(signals);
			//printf( "[Drive to bank#%d] sout(%d)", bank, encoded_signal);
			break;

		case BS_READ_DMA:
			if(runDMA(bank, 1)) {
				dma_done[bank] = true;
			}
			break;

		case BS_READ_INC_BM:
			bm_read_inc = 1;
			break;


			//////////////////////////////Write//////////////////////////////
		case BS_WRITE_DMA:
			if(runDMA(bank, 0)) {
				dma_done[bank] = true;
			}
			break;

		case BS_WRITE_CMD_1:
			signals.CLE = ENABLE;
			signals.CEn = ENABLEn;
			signals.WEn = ENABLEn;
			signals.ALE = DISABLE;
			signals.REn = DISABLEn;
			signals.WPn = DISABLEn; //fix

			tmp_flash_sout[bank] = encodingSignals(signals);
			tmp_flash_dout[bank] = FCMD_WRITE_1;
			break;

		case BS_WRITE_COL_1:
		case BS_WRITE_COL_2:
			signals.CLE = DISABLE;
			signals.CEn = ENABLEn;
			signals.WEn = ENABLEn;
			signals.ALE = ENABLE;
			signals.REn = DISABLEn;
			signals.WPn = DISABLEn; //fix

			tmp_flash_sout[bank] = encodingSignals(signals);
			tmp_flash_dout[bank] = getRegister(BSP_COL(bank)); //fix
			break;

		case BS_WRITE_ROW_1:
			signals.CLE = DISABLE;
			signals.CEn = ENABLEn;
			signals.WEn = ENABLEn;
			signals.ALE = ENABLE;
			signals.REn = DISABLEn;
			signals.WPn = DISABLEn; //fix

			tmp_flash_sout[bank] = encodingSignals(signals);
			tmp_flash_dout[bank] = getRegister(BSP_ROW_L(bank));
			break;

		case BS_WRITE_ROW_2:
			signals.CLE = DISABLE;
			signals.CEn = ENABLEn;
			signals.WEn = ENABLEn;
			signals.ALE = ENABLE;
			signals.REn = DISABLEn;
			signals.WPn = DISABLEn; //fix

			tmp_flash_sout[bank] = encodingSignals(signals);
			tmp_flash_dout[bank] = getRegister(BSP_ROW_H(bank));
			break;

		case BS_WRITE_DATA: //1024 iteration: using curWriteIdx
			signals.CLE = DISABLE;
			signals.CEn = ENABLEn;
			signals.WEn = ENABLEn;
			signals.ALE = DISABLE;
			signals.REn = DISABLEn;
			signals.WPn = DISABLEn; //fix

			w_data_l = buffers[bank][(*index)]; //need implement
			w_data_h = (buffers[bank][(*index)+1]);

			//if(p_enableDbgMsg)
			printf( "[Bank#%d] Write data: 0x%X, index: %d\n", bank, ((w_data_h << 8)|w_data_l), *index);

			(*index)+=2;
			tmp_flash_sout[bank] = encodingSignals(signals);
			tmp_flash_dout[bank] = ((w_data_h << 8)|w_data_l);
			break;

		case BS_WRITE_CMD_2:
			signals.CLE = ENABLE;
			signals.CEn = ENABLEn;
			signals.WEn = ENABLEn;
			signals.ALE = DISABLE;
			signals.REn = DISABLEn;
			signals.WPn = DISABLEn; //fix

			tmp_flash_sout[bank] = encodingSignals(signals);
			tmp_flash_dout[bank] = FCMD_WRITE_2;
			break;

		case BS_WRITE_WAIT:
			signals.CLE = DISABLE;
			signals.CEn = ENABLEn;
			signals.WEn = DISABLEn;
			signals.ALE = DISABLE;
			signals.REn = DISABLEn;
			signals.WPn = DISABLEn; //fix

			tmp_flash_sout[bank] = encodingSignals(signals);
			break;

		case BS_WRITE_INC_BM:
			bm_write_inc = 1;
			break;


			//////////////////////////////Copy-Back//////////////////////////////
		case BS_CB_CMD_1:
			signals.CLE = ENABLE;
			signals.CEn = ENABLEn;
			signals.WEn = ENABLEn;
			signals.ALE = DISABLE;
			signals.REn = DISABLEn;
			signals.WPn = DISABLEn; //fix

			tmp_flash_sout[bank] = encodingSignals(signals);
			tmp_flash_dout[bank] = FCMD_CP_1;
			break;

		case BS_CB_COL_1:
		case BS_CB_COL_2:
			signals.CLE = DISABLE;
			signals.CEn = ENABLEn;
			signals.WEn = ENABLEn;
			signals.ALE = ENABLE;
			signals.REn = DISABLEn;
			signals.WPn = DISABLEn; //fix

			tmp_flash_sout[bank] = encodingSignals(signals);
			tmp_flash_dout[bank] = getRegister(BSP_COL(bank));
			break;

		case BS_CB_ROW_1:
			signals.CLE = DISABLE;
			signals.CEn = ENABLEn;
			signals.WEn = ENABLEn;
			signals.ALE = ENABLE;
			signals.REn = DISABLEn;
			signals.WPn = DISABLEn; //fix

			tmp_flash_sout[bank] = encodingSignals(signals);
			tmp_flash_dout[bank] = getRegister(BSP_ROW_L(bank));
			break;

		case BS_CB_ROW_2:
			signals.CLE = DISABLE;
			signals.CEn = ENABLEn;
			signals.WEn = ENABLEn;
			signals.ALE = ENABLE;
			signals.REn = DISABLEn;
			signals.WPn = DISABLEn; //fix

			tmp_flash_sout[bank] = encodingSignals(signals);
			tmp_flash_dout[bank] = getRegister(BSP_ROW_H(bank));
			break;

		case BS_CB_CMD_2:
			signals.CLE = ENABLE;
			signals.CEn = ENABLEn;
			signals.WEn = ENABLEn;
			signals.ALE = DISABLE;
			signals.REn = DISABLEn;
			signals.WPn = DISABLEn; //fix

			tmp_flash_sout[bank] = encodingSignals(signals);
			tmp_flash_dout[bank] = FCMD_CP_2;
			break;

		case BS_CB_WAIT_1:
			signals.CLE = DISABLE;
			signals.CEn = ENABLEn;
			signals.WEn = DISABLEn;
			signals.ALE = DISABLE;
			signals.REn = DISABLEn;
			signals.WPn = DISABLEn; //fix

			tmp_flash_sout[bank] = encodingSignals(signals);
			break;

		case BS_CB_CMD_3:
			signals.CLE = ENABLE;
			signals.CEn = ENABLEn;
			signals.WEn = ENABLEn;
			signals.ALE = DISABLE;
			signals.REn = DISABLEn;
			signals.WPn = DISABLEn; //fix

			tmp_flash_sout[bank] = encodingSignals(signals);
			tmp_flash_dout[bank] = FCMD_CP_3;
			break;

		case BS_CB_COL_3:
		case BS_CB_COL_4:
			signals.CLE = DISABLE;
			signals.CEn = ENABLEn;
			signals.WEn = ENABLEn;
			signals.ALE = ENABLE;
			signals.REn = DISABLEn;
			signals.WPn = DISABLEn; //fix

			tmp_flash_sout[bank] = encodingSignals(signals);
			tmp_flash_dout[bank] = getRegister(BSP_DST_COL(bank));
			break;

		case BS_CB_ROW_3:
			signals.CLE = DISABLE;
			signals.CEn = ENABLEn;
			signals.WEn = ENABLEn;
			signals.ALE = ENABLE;
			signals.REn = DISABLEn;
			signals.WPn = DISABLEn; //fix

			tmp_flash_sout[bank] = encodingSignals(signals);
			tmp_flash_dout[bank] = getRegister(BSP_DST_ROW_L(bank));
			break;

		case BS_CB_ROW_4:
			signals.CLE = DISABLE;
			signals.CEn = ENABLEn;
			signals.WEn = ENABLEn;
			signals.ALE = ENABLE;
			signals.REn = DISABLEn;
			signals.WPn = DISABLEn; //fix

			tmp_flash_sout[bank] = encodingSignals(signals);
			tmp_flash_dout[bank] = getRegister(BSP_DST_ROW_H(bank));
			break;

		case BS_CB_CMD_4:
			signals.CLE = ENABLE;
			signals.CEn = ENABLEn;
			signals.WEn = ENABLEn;
			signals.ALE = DISABLE;
			signals.REn = DISABLEn;
			signals.WPn = DISABLEn; //fix

			tmp_flash_sout[bank] = encodingSignals(signals);
			tmp_flash_dout[bank] = FCMD_CP_4;
			break;

		case BS_CB_WAIT_2:
			signals.CLE = DISABLE;
			signals.CEn = ENABLEn;
			signals.WEn = DISABLEn;
			signals.ALE = DISABLE;
			signals.REn = DISABLEn;
			signals.WPn = DISABLEn; //fix

			tmp_flash_sout[bank] = encodingSignals(signals);
			break;


			//////////////////////////////Erase//////////////////////////////
		case BS_ERASE_CMD_1:
			signals.CLE = ENABLE;
			signals.CEn = ENABLEn;
			signals.WEn = ENABLEn;
			signals.ALE = DISABLE;
			signals.REn = DISABLEn;
			signals.WPn = DISABLEn; //fix

			tmp_flash_sout[bank] = encodingSignals(signals);
			tmp_flash_dout[bank] = FCMD_ERASE_1;
			break;

		case BS_ERASE_ROW_1:
			signals.CLE = DISABLE;
			signals.CEn = ENABLEn;
			signals.WEn = ENABLEn;
			signals.ALE = ENABLE;
			signals.REn = DISABLEn;
			signals.WPn = DISABLEn; //fix

			tmp_flash_sout[bank] = encodingSignals(signals);
			tmp_flash_dout[bank] = getRegister(BSP_ROW_L(bank));
			break;

		case BS_ERASE_ROW_2:
			signals.CLE = DISABLE;
			signals.CEn = ENABLEn;
			signals.WEn = ENABLEn;
			signals.ALE = ENABLE;
			signals.REn = DISABLEn;
			signals.WPn = DISABLEn; //fix

			tmp_flash_sout[bank] = encodingSignals(signals);
			tmp_flash_dout[bank] = getRegister(BSP_ROW_H(bank));
			break;

		case BS_ERASE_CMD_2:
			signals.CLE = ENABLE;
			signals.CEn = ENABLEn;
			signals.WEn = ENABLEn;
			signals.ALE = DISABLE;
			signals.REn = DISABLEn;
			signals.WPn = DISABLEn; //fix

			tmp_flash_sout[bank] = encodingSignals(signals);
			tmp_flash_dout[bank] = FCMD_ERASE_2;
			break;

		case BS_ERASE_WAIT:
			signals.CLE = DISABLE;
			signals.CEn = ENABLEn;
			signals.WEn = DISABLEn;
			signals.ALE = DISABLE;
			signals.REn = DISABLEn;
			signals.WPn = DISABLEn; //fix

			tmp_flash_sout[bank] = encodingSignals(signals);
			break;


			//////////////////////////////Error//////////////////////////////
		default:
			;
	}
void NANDController::communicate()
{
	/**************************************************************************************
	 * Read Signals
	 **************************************************************************************/
	for(int i=0; i<NUM_BANKS; i++) {
		RBn[i] = flash_RBn_SSlave[i];
	}



	/* When all banks are idle, set MON_CHABANKIDLE. */
	bool allIdle = true;

	for(int i=0; ( i<NUM_BANKS ) && allIdle; i++) {
		allIdle = getRegister(BSP_FSM(i)) == BS_IDLE;
	}

	if(allIdle && getRegister(WR_STAT) == WR_STAT_IDLE) {
		setRegister(MON_CHABANKIDLE, 0);
	}




	/**************************************************************************************
	 * If Issue flag is on, Execute command
	 **************************************************************************************/
	if(getRegister(FCP_ISSUE) == ISSUE_ENABLE)
	{
		printf( "Command ISSUED\n");

		if(getRegister(WR_STAT) == WR_STAT_BUSY) {
			printf( "Waiting Room is Busy, ignore this command\n");
		}
		else
		{
			getCommandInfo();


			//The Banks FSM is already running.
			if(getRegister(BSP_FSM(curFCPCommand.bank)) != BS_IDLE)
			{
				printf( "%d Bank is busy, put this command into WR\n", curFCPCommand.bank);

				//Active Wating Room.
				setRegister(WR_BANK, curFCPCommand.bank);
				setRegister(WR_STAT, WR_STAT_BUSY);
			}
			else {
				issueCommandToBank(curFCPCommand.bank);
				bIssued[curFCPCommand.bank] = true;
			}

			//set some banks are non-idle.
			setRegister(MON_CHABANKIDLE, 1);
		}

		//Clear ISSUE register
		setRegister(FCP_ISSUE, ISSUE_DISABLE);
	}



	/**************************************************************************************
	 * The bank that has next command in WR will be IDLE state, Issue the command.
	 **************************************************************************************/
	int wrBank = getRegister(WR_BANK);

	if(		getRegister(WR_STAT) == WR_STAT_BUSY		&&
			NextStateOfBanks[wrBank] == BS_IDLE)
	{
		printf( "%d Bank become IDLE, issue CMD to %d Bank from WR\n", wrBank, wrBank);

		issueCommandToBank(wrBank);
		bIssued[wrBank] = true;

		setRegister(WR_STAT, WR_STAT_IDLE);
	}




	/**************************************************************************************
	 * Banks FSM
	 **************************************************************************************/
	for(int i=0; i<NUM_BANKS; i++)
	{
		if(bIssued[i]) {
			runCommand(i);
			bIssued[i] = false;
		}


		combinationalLogicBankFSM(i);
	}




	/**************************************************************************************
	 * Send Drive
	 **************************************************************************************/
	// Send(drive) all the signals set in previous update()
	//ahb_m0_mpms->sendDrive();
	// Send(drive) all the signals set in previous update()
	//ahb_m1_mpms->sendDrive();
	// Send(drive) all the signals set in previous update()
	//ahb_s0_spss->sendDrive();
}
void NANDController::combinationalLogicBankFSM(int bank)
{
	/*****************************************************************************
	 * Get pointers that indicating specific bank.
	 *****************************************************************************/
	uint8_t *pStateFSMBanks = ((uint8_t*)m_regs)+BSP_FSM(bank);
	uint8_t *nextState = &(NextStateOfBanks[bank]);
	uint32_t *index = &(curIdx[bank]);




	/*****************************************************************************
	 * Move to Next state
	 *****************************************************************************/
	*pStateFSMBanks = *nextState;



	/*****************************************************************************
	 * Define Next state
	 *****************************************************************************/
	switch(*pStateFSMBanks)
	{
		case BS_IDLE:
			break;


			//////////////////////////////Read Status//////////////////////////////
		case BS_RS_CMD:
			printf( "[Bank#%d] State: BS_RS_CMD\n", bank);
			*nextState = (uint8_t)BS_RS_DATA;
			break;

		case BS_RS_DATA:
			printf( "[Bank#%d] State: BS_RS_DATA\n", bank);
			*nextState = (uint8_t)BS_IDLE; //finish
			break;


			//////////////////////////////Read//////////////////////////////
		case BS_READ_CMD_1:
			printf( "[Bank#%d] State: BS_READ_CMD_1\n", bank);
			*nextState = (uint8_t)BS_READ_COL_1;
			break;

		case BS_READ_COL_1:
			printf( "[Bank#%d] State: BS_READ_COL_1\n", bank);
			*nextState = (uint8_t)BS_READ_COL_2;
			break;

		case BS_READ_COL_2:
			printf( "[Bank#%d] State: BS_READ_COL_2\n", bank);
			*nextState = (uint8_t)BS_READ_ROW_1;
			break;

		case BS_READ_ROW_1:
			printf( "[Bank#%d] State: BS_READ_ROW_1\n", bank);
			*nextState = (uint8_t)BS_READ_ROW_2;
			break;

		case BS_READ_ROW_2:
			printf( "[Bank#%d] State: BS_READ_ROW_2\n", bank);
			*nextState = (uint8_t)BS_READ_CMD_2;
			break;

		case BS_READ_CMD_2:
			printf( "[Bank#%d] State: BS_READ_CMD_2\n", bank);
			*nextState = (uint8_t)BS_READ_WAIT;
			flash_inputSignal_active[bank] = false;

			printf( "[Bank#%d] Move to BS_READ_WAIT\n", bank);
			break;

		case BS_READ_WAIT:
			if(flash_inputSignal_active[bank])
			{
				//printf( "[Bank#%d] BS_READ_WAIT Active \n", bank);
				if(RBn[bank] == READY) {
					printf( "[Bank#%d] READY! BS_READ_WAIT \n", bank);
					*nextState = *pStateFSMBanks = (uint8_t)BS_READ_DATA;
					*index = 0;
					flash_inputSignal_active[bank] = false;
				}
			}
			else {
				//printf( "[Bank#%d] BS_READ_WAIT No Active \n", bank);
				flash_inputSignal_active[bank] = true;
			}
			break;

		case BS_READ_DATA: //1024 iteration: using curReadIdx
			if(*index == 0) {
				printf( "[Bank#%d] State: BS_READ_DATA\n", bank);
			}


			if(*index >= BYTE_PER_PAGE-4) {
				if(getRegister(BSP_DMA_ADDR(bank)) != 0) {
					dma_done[bank] = false;
					*nextState = (uint8_t)BS_READ_DMA; //dma
				}
				else {
					*nextState = (uint8_t)BS_IDLE; //finish
				}
			}
			break;

		case BS_READ_DMA:
			if(dma_done[bank]) //Write read data into external memory.
			{
				dma_running_bank = DMA_IDLE;

				if(getRegister(BSP_OPTION(bank)) & FO_B_SATA_R)
				{
					printf( "[Bank#%d] Move to BS_READ_INC_BM\n", bank);
					*pStateFSMBanks = (uint8_t)BS_READ_INC_BM;
					*nextState = (uint8_t)BS_IDLE; //Move to state for BufferManasger
				}
				else {
					*nextState = *pStateFSMBanks = (uint8_t)BS_IDLE; //finish
				}
			}
			break;

		case BS_READ_INC_BM:
			*nextState = (uint8_t)BS_IDLE;
			break;



			//////////////////////////////Write//////////////////////////////
		case BS_WRITE_DMA:
			if(dma_done[bank]) { //Read data that will be wrote into nand flash from external memory.
				dma_running_bank = DMA_IDLE;

				printf( "[Bank#%d] Move to BS_WRITE_CMD_1\n", bank);
				*pStateFSMBanks = (uint8_t)BS_WRITE_CMD_1;
				*nextState = (uint8_t)BS_WRITE_COL_1;
			}
			break;

		case BS_WRITE_CMD_1:
			printf( "[Bank#%d] State: BS_WRITE_CMD_1\n", bank);
			*nextState = (uint8_t)BS_WRITE_COL_1;
			break;

		case BS_WRITE_COL_1:
			printf( "[Bank#%d] State: BS_WRITE_COL_1\n", bank);
			*nextState = (uint8_t)BS_WRITE_COL_2;
			break;

		case BS_WRITE_COL_2:
			printf( "[Bank#%d] State: BS_WRITE_COL_2\n", bank);
			*nextState = (uint8_t)BS_WRITE_ROW_1;
			break;

		case BS_WRITE_ROW_1:
			printf( "[Bank#%d] State: BS_WRITE_ROW_1\n", bank);
			*nextState = (uint8_t)BS_WRITE_ROW_2;
			break;

		case BS_WRITE_ROW_2:
			printf( "[Bank#%d] State: BS_WRITE_ROW_2\n", bank);
			*nextState = (uint8_t)BS_WRITE_DATA;
			*index = 0;
			break;

		case BS_WRITE_DATA: //1024 iteration: using curWriteIdx
			if(*index == 0) {
				printf( "[Bank#%d] State: BS_WRITE_DATA, writeIdx: %d\n", bank, *index);
			}

			if(*index >= BYTE_PER_PAGE-2) {
				*nextState = (uint8_t)BS_WRITE_CMD_2;
			}
			break;

		case BS_WRITE_CMD_2:
			printf( "[Bank#%d] State: BS_WRITE_CMD_2\n", bank);
			*nextState = (uint8_t)BS_WRITE_WAIT;
			flash_inputSignal_active[bank] = false;

			printf( "[Bank#%d] Move to BS_WRITE_WAIT\n", bank);
			break;

		case BS_WRITE_WAIT:
			if(flash_inputSignal_active[bank])
			{
				if(RBn[bank] == READY)
				{
					if(getRegister(BSP_OPTION(bank)) & FO_B_SATA_W) {
						printf( "[Bank#%d] Move to BS_WRITE_INC_BM\n", bank);
						*pStateFSMBanks = (uint8_t)BS_WRITE_INC_BM; //Move to the state for Buffer manager
						*nextState = (uint8_t)BS_RS_CMD;
					}
					else {
						//*pStateFSMBanks = (uint8_t)BS_RS_CMD; //finish
						//*nextState = (uint8_t)BS_RS_DATA;
						*nextState = (uint8_t)BS_RS_CMD;
					}

					flash_inputSignal_active[bank] = false;
				}
			}
			else {
				flash_inputSignal_active[bank] = true;
			}
			break;

		case BS_WRITE_INC_BM:
			*nextState = (uint8_t)BS_RS_CMD;
			break;


			//////////////////////////////Copy-Back//////////////////////////////
		case BS_CB_CMD_1:
			printf( "[Bank#%d] State: BS_CB_CMD_1\n", bank);
			*nextState = (uint8_t)BS_CB_COL_1;
			break;

		case BS_CB_COL_1:
			printf( "[Bank#%d] State: BS_CB_COL_1\n", bank);
			*nextState = (uint8_t)BS_CB_COL_2;
			break;

		case BS_CB_COL_2:
			printf( "[Bank#%d] State: BS_CB_COL_2\n", bank);
			*nextState = (uint8_t)BS_CB_ROW_1;
			break;

		case BS_CB_ROW_1:
			printf( "[Bank#%d] State: BS_CB_ROW_1\n", bank);
			*nextState = (uint8_t)BS_CB_ROW_2;
			break;

		case BS_CB_ROW_2:
			printf( "[Bank#%d] State: BS_CB_ROW_2\n", bank);
			*nextState = (uint8_t)BS_CB_CMD_2;
			break;

		case BS_CB_CMD_2:
			printf( "[Bank#%d] State: BS_CB_CMD_2\n", bank);
			*nextState = (uint8_t)BS_CB_WAIT_1;
			flash_inputSignal_active[bank] = false;

			printf( "[Bank#%d] Move to BS_CB_WAIT_1\n", bank);
			break;

		case BS_CB_WAIT_1:
			if(flash_inputSignal_active[bank])
			{
				if(RBn[bank] == READY)
				{
					*pStateFSMBanks = (uint8_t)BS_CB_CMD_3;
					*nextState = (uint8_t)BS_CB_COL_3;

					flash_inputSignal_active[bank] = false;
				}
			}
			else {
				flash_inputSignal_active[bank] = true;
			}
			break;

		case BS_CB_CMD_3:
			printf( "[Bank#%d] State: BS_CB_CMD_3\n", bank);
			*nextState = (uint8_t)BS_CB_COL_3;
			break;

		case BS_CB_COL_3:
			printf( "[Bank#%d] State: BS_CB_COL_3\n", bank);
			*nextState = (uint8_t)BS_CB_COL_4;
			break;

		case BS_CB_COL_4:
			printf( "[Bank#%d] State: BS_CB_COL_4\n", bank);
			*nextState = (uint8_t)BS_CB_ROW_3;
			break;

		case BS_CB_ROW_3:
			printf( "[Bank#%d] State: BS_CB_ROW_3\n", bank);
			*nextState = (uint8_t)BS_CB_ROW_4;
			break;

		case BS_CB_ROW_4:
			printf( "[Bank#%d] State: BS_CB_ROW_4\n", bank);
			*nextState = (uint8_t)BS_CB_CMD_4;
			break;

		case BS_CB_CMD_4:
			printf( "[Bank#%d] State: BS_CB_CMD_4\n", bank);
			*nextState = (uint8_t)BS_CB_WAIT_2;
			flash_inputSignal_active[bank] = false;

			printf( "[Bank#%d] Move to BS_CB_WAIT_2\n", bank);
			break;

		case BS_CB_WAIT_2:
			if(flash_inputSignal_active[bank])
			{
				if(RBn[bank] == READY)
				{
					//*pStateFSMBanks = (uint8_t)BS_RS_CMD; //finish
					//*nextState = (uint8_t)BS_RS_DATA;
					*nextState = (uint8_t)BS_RS_CMD;

					flash_inputSignal_active[bank] = false;
				}
			}
			else {
				flash_inputSignal_active[bank] = true;
			}
			break;


			//////////////////////////////Erase//////////////////////////////
		case BS_ERASE_CMD_1:
			printf( "[Bank#%d] State: BS_ERASE_CMD_1\n", bank);
			*nextState = (uint8_t)BS_ERASE_ROW_1;
			break;

		case BS_ERASE_ROW_1:
			printf( "[Bank#%d] State: BS_ERASE_ROW_1\n", bank);
			*nextState = (uint8_t)BS_ERASE_ROW_2;
			break;

		case BS_ERASE_ROW_2:
			printf( "[Bank#%d] State: BS_ERASE_ROW_2\n", bank);
			*nextState = (uint8_t)BS_ERASE_CMD_2;
			break;

		case BS_ERASE_CMD_2:
			printf( "[Bank#%d] State: BS_ERASE_CMD_2\n", bank);
			*nextState = (uint8_t)BS_ERASE_WAIT;
			flash_inputSignal_active[bank] = false;

			printf( "[Bank#%d] Move to BS_ERASE_WAIT\n", bank);
			break;

		case BS_ERASE_WAIT:

			if(flash_inputSignal_active[bank])
			{
				if(RBn[bank] == READY)
				{
					//*pStateFSMBanks = (uint8_t)BS_RS_CMD; //finish
					//*nextState = (uint8_t)BS_RS_DATA;
					*nextState = (uint8_t)BS_RS_CMD;

					flash_inputSignal_active[bank] = false;
				}
			}
			else {
				flash_inputSignal_active[bank] = true;
			}
			break;


			//////////////////////////////Error//////////////////////////////
		default:
			*nextState = (uint8_t)BS_IDLE;
	}
}