Esempio n. 1
0
static UINT32 assign_new_write_vpn(UINT32 const bank)
{
	UINT32 write_vpn;
	UINT32 vblock;

	write_vpn = get_cur_write_vpn(bank);
	vblock    = write_vpn / PAGES_PER_BLK;

	// NOTE: if next new write page's offset is
	// the last page offset of vblock (i.e. PAGES_PER_BLK - 1),
	if ((write_vpn % PAGES_PER_BLK) == (PAGES_PER_BLK - 2))
	{
		// then, because of the flash controller limitation
		// (prohibit accessing a spare area (i.e. OOB)),
		// thus, we persistenly write a lpn list into last page of vblock.
		mem_copy(TEMP_BUF(bank), g_misc_meta[bank].lpn_list_of_cur_vblock, sizeof(UINT32) * PAGES_PER_BLK);
		// fix minor bug
		misc_w++;
		nand_page_ptprogram(bank, vblock, PAGES_PER_BLK - 1, 0,
				((sizeof(UINT32) * PAGES_PER_BLK + BYTES_PER_SECTOR - 1 ) / BYTES_PER_SECTOR),
				TEMP_BUF(bank));

		mem_set_sram(g_misc_meta[bank].lpn_list_of_cur_vblock, 0x00000000, sizeof(UINT32) * PAGES_PER_BLK);

		inc_full_blk_cnt(bank);

		// do garbage collection if necessary
		if (is_full_all_blks(bank))
		{
			GC:
			garbage_collection(bank);
			return get_cur_write_vpn(bank);
		}
		do
		{
			vblock++;

			if(vblock == VBLKS_PER_BANK)
			{
				uart_printf(" vblock == VBLKS_PER_BANK");
				goto GC;
			}
		}while (get_vcount(bank, vblock) == VC_MAX);
	}
	// write page -> next block
	if (vblock != (write_vpn / PAGES_PER_BLK))
	{
		write_vpn = vblock * PAGES_PER_BLK;
	}
	else
	{
		write_vpn++;
	}
	set_new_write_vpn(bank, write_vpn);

	return write_vpn;
}
Esempio n. 2
0
void sata_reset(void)
{
    disable_interrupt();

    mem_set_sram(&g_sata_context, 0, sizeof(g_sata_context));

    g_sata_context.write_cache_enabled = TRUE;
    g_sata_context.read_look_ahead_enabled = TRUE;

    SETREG(PMU_ResetCon, RESET_SATA | RESET_SATADWCLK | RESET_SATAHCLK | RESET_PMCLK | RESET_PHYDOMAIN);
    delay(100);

    SETREG(PHY_DEBUG, 0x400A040E);
    int count=0;
    while ((GETREG(PHY_DEBUG) & BIT30) == 1) {
        count++;
        if (count > 100000) {
            uart_print_level_1("Warning1 in sata_reset::eventq_get\r\n");
            count=0;
        }
    }

    SETREG(SATA_BUF_PAGE_SIZE, BYTES_PER_PAGE);
    SETREG(SATA_WBUF_BASE, (WR_BUF_ADDR - DRAM_BASE));
    SETREG(SATA_RBUF_BASE, (RD_BUF_ADDR - DRAM_BASE));
    SETREG(SATA_WBUF_SIZE, NUM_WR_BUFFERS);
    SETREG(SATA_RBUF_SIZE, NUM_RD_BUFFERS);
    SETREG(SATA_WBUF_MARGIN, 16);
    SETREG(SATA_RESET_WBUF_PTR, BIT0);
    SETREG(SATA_RESET_RBUF_PTR, BIT0);

    SETREG(SATA_NCQ_BASE, g_sata_ncq.queue);

    SETREG(SATA_EQ_CFG_1, BIT0 | BIT14 | BIT9 | BIT16 | ((NUM_BANKS / 2) << 24));
    SETREG(SATA_EQ_CFG_2, (EQ_MARGIN & 0xF) << 16);

    SETREG(SATA_CFG_10, BIT0);

    SETREG(SATA_NCQ_CTRL, AUTOINC | FLUSH_NCQ);
    SETREG(SATA_NCQ_CTRL, AUTOINC);
    SETREG(SATA_CFG_5, BIT12 | BIT11*BSO_RX_SSC | (BIT9|BIT10)*BSO_TX_SSC | BIT4*0x05);
    SETREG(SATA_CFG_8, 0);
    SETREG(SATA_CFG_9, BIT20);

    SETREG(SATA_MAX_LBA, MAX_LBA);

    SETREG(APB_INT_STS, INTR_SATA);

    #if OPTION_SLOW_SATA
    SETREG(SATA_PHY_CTRL, 0x00000310);
    #else
    SETREG(SATA_PHY_CTRL, 0x00000300);
    #endif

    SETREG(SATA_ERROR, 0xFFFFFFFF);
    SETREG(SATA_INT_STAT, 0xFFFFFFFF);

    SETREG(SATA_CTRL_1, BIT31);

    count=0;
    while ((GETREG(SATA_INT_STAT) & PHY_ONLINE) == 0) {
        count++;
        if (count > 100000) {
            uart_print_level_1("Warning2 in sata_reset::eventq_get\r\n");
            count=0;
        }
    }

    SETREG(SATA_CTRL_1, BIT31 | BIT25 | BIT24);

    SETREG(SATA_INT_ENABLE, PHY_ONLINE);

    enable_interrupt();
}
Esempio n. 3
0
void init_jasmine(void)
{
	UINT32 i, bank;
	extern UINT32 Image$$ER_ZI$$ZI$$Base;
	extern UINT32 Image$$ER_ZI$$ZI$$Length;

	// PLL initialization

	SETREG(CLKSelCon, USE_BYPASS_CLK);

	SETREG(PllCon, PLL_PD); 					// power down
	delay(600);									// at least 500ns
	SETREG(PllCon, PLL_CLK_CONFIG | PLL_PD);	// change settings
	delay(600);									// at least 1us
	SETREG(PllCon, PLL_CLK_CONFIG);				// power up
	while ((GETREG(PllCon) & PLL_LD) == 0); 	// wait lock

	SETREG(CLKSelCon, USE_PLL_CLK);

	// reset hardware modules

	SETREG(PMU_ResetCon, RESET_SDRAM | RESET_BM | RESET_SATA | RESET_FLASH);

	// GPIO bits
	// There are 7 GPIO bits from 0 to 6.
	// 0: This bit is connected to J2 (Factory Mode jumper). The ROM firmware configures it as input mode.
	// While main firmware is running, it can be freely used for arbitrary purpose. Beware that a "1" output while
	// the Factory Mode jumper is set to Normal position (tied to ground) can lead to circuit damage.
	// A "0" output while the jumper is tied to Vcc will also lead to circuit damage.
	// 1: This bit is connected to J3 (Boot ROM). The controller hardware checks its status upon reset.
	// After the reset is done, you can remove the jumper and use the pin as output.
	// 2 through 5: The IO pins for these bits are shared between MAX3232C (UART chip) and J4.
	// In order to use J4, you have to turn on the switches of SW4 and turn off the switches 1 through 4 in SW2.
	// In order to use UART, you have to turn off the switches of SW4 and turn on the switches 1 through 4 in SW2.
	// 6: This bit is connected to D4 (LED) via SW2.

	#if OPTION_UART_DEBUG
	SETREG(GPIO_MOD, 0);
	SETREG(GPIO_DIR, BIT3 | BIT4 | BIT6);	// output pins: 3(UART_TXD), 4(UART_RTS), 6(LED)
	#else
	SETREG(GPIO_MOD, 7);
	SETREG(GPIO_DIR, BIT2 | BIT3 | BIT4 | BIT5 | BIT6);
	#endif

	SETREG(GPIO_REG, 0);					// initial state of LED is "off"

	// ZI region is zero-filled by hardware.
	mem_set_sram((UINT32) &Image$$ER_ZI$$ZI$$Base, 0x00000000, (UINT32) &Image$$ER_ZI$$ZI$$Length);

	SETREG(PHY_DEBUG, 0x40000139);
	while((GETREG(PHY_DEBUG) & BIT30) == 1);

	SETREG(SDRAM_INIT, SDRAM_PARAM_MAIN_FW_INIT);
	SETREG(SDRAM_REFRESH, SDRAM_PARAM_MAIN_FW_REFRESH);
	SETREG(SDRAM_TIMING, SDRAM_PARAM_MAIN_FW_TIMING);
	SETREG(SDRAM_MRS, SDRAM_PARAM_MAIN_FW_MRS);
	SETREG(SDRAM_CTRL, SDRAM_INITIALIZE);		// initialization of SDRAM begins now
	while (GETREG(SDRAM_STATUS) & 0x00000010);	// wait until the initialization completes (200us)

	for (i = 0; i < DRAM_SIZE / MU_MAX_BYTES; i++)
	{
		mem_set_dram(DRAM_BASE + i * MU_MAX_BYTES, 0x00000000, MU_MAX_BYTES);
	}

	#if OPTION_UART_DEBUG
	uart_init();
	uart_print("Welcome to OpenSSD");
	#endif

	SETREG(SDRAM_ECC_MON, 0xFFFFFFFF);

	// configure SDRAM interrupt
	SETREG(SDRAM_INTCTRL, SDRAM_INT_ENABLE);

	// clear interrupt flags in DRAM controller
	SETREG(SDRAM_INTSTATUS, 0xFFFFFFFF);

	// configure ICU
	SETREG(APB_ICU_CON, INTR_SATA);	// SATA = FIQ, other = IRQ
	SETREG(APB_INT_MSK, INTR_SATA | INTR_FLASH | INTR_SDRAM | INTR_TIMER_1 | INTR_TIMER_2 | INTR_TIMER_3);

	// clear interrupt flags in ICU
	SETREG(APB_INT_STS, 0xFFFFFFFF);

	flash_reset();

	SETREG(FCONF_PAUSE, 0);
	SETREG(INTR_MASK, 0);

	for (bank = 0; bank < NUM_BANKS; bank++)
	{
		flash_clear_irq();

		SETREG(FCP_CMD, FC_COL_ROW_READ_OUT);
		SETREG(FCP_OPTION, 0x06);				// FO_E
		SETREG(FCP_DMA_ADDR, g_temp_mem);
		SETREG(FCP_DMA_CNT, BYTES_PER_SECTOR);
		SETREG(FCP_COL, 0);
		SETREG(FCP_ROW_L(bank), STAMP_PAGE_OFFSET);
		SETREG(FCP_ROW_H(bank), STAMP_PAGE_OFFSET);

		flash_issue_cmd(bank, RETURN_WHEN_DONE);

		if ( (BSP_INTR(bank) & 0xFE)== 0 )
			break;
	}

	#if OPTION_FTL_TEST == FALSE
	sata_reset();
	#endif

    ftl_open();

	#if OPTION_FTL_TEST == TRUE
	extern void ftl_test();
	ftl_test();
    led(1);
    while (1);
    #endif
}
Esempio n. 4
0
void test_nand_blocks(void)
{
	// This function is a utility that writes random data to flash pages and verifies them.
	// This function takes a long time to complete.

	UINT32 bank, vblk_offset, page_offset, data, bad;

	#define write_buffer_base	DRAM_BASE
	#define read_buffer_base	(DRAM_BASE + BYTES_PER_VBLK)

	disable_irq();
	flash_clear_irq();

	mem_set_sram(g_test_result, 0, sizeof(g_test_result));

	// Configure the flash controller so that any FIRQ_* does not lead to pause state.
	SETREG(FCONF_PAUSE, 0);

	// STEP 1 - prepare random data

	srand(10);

	for (page_offset = 0; page_offset < PAGES_PER_VBLK; page_offset++)
	{
		data = (rand() & 0xFFFF) | (rand() << 16);
		mem_set_dram(write_buffer_base + page_offset * BYTES_PER_PAGE, data, BYTES_PER_PAGE);
	}

	for (vblk_offset = 1; vblk_offset < VBLKS_PER_BANK; vblk_offset++)
	{
		// STEP 2 - erase a block at each bank

		for (bank = 0; bank < NUM_BANKS; bank++)
		{
			UINT32 rbank = REAL_BANK(bank);

			SETREG(FCP_CMD, FC_ERASE);
			SETREG(FCP_BANK, rbank);
			SETREG(FCP_OPTION, FO_P);
			SETREG(FCP_ROW_L(bank), vblk_offset * PAGES_PER_VBLK);
			SETREG(FCP_ROW_H(bank), vblk_offset * PAGES_PER_VBLK);

			while ((GETREG(WR_STAT) & 0x00000001) != 0);
			SETREG(FCP_ISSUE, NULL);
		}

		// STEP 3 - write to every pages of the erased block

		for (page_offset = 0; page_offset < PAGES_PER_VBLK; page_offset++)
		{
			for (bank = 0; bank < NUM_BANKS; bank++)
			{
				UINT32 rbank = REAL_BANK(bank);

				SETREG(FCP_CMD, FC_COL_ROW_IN_PROG);
				SETREG(FCP_BANK, rbank);
				SETREG(FCP_OPTION, FO_P | FO_E | FO_B_W_DRDY);
				SETREG(FCP_DMA_ADDR, write_buffer_base + page_offset * BYTES_PER_PAGE);
				SETREG(FCP_DMA_CNT, BYTES_PER_PAGE);
				SETREG(FCP_COL, 0);
				SETREG(FCP_ROW_L(bank), vblk_offset * PAGES_PER_VBLK + page_offset);
				SETREG(FCP_ROW_H(bank), vblk_offset * PAGES_PER_VBLK + page_offset);

				while ((GETREG(WR_STAT) & 0x00000001) != 0);
				SETREG(FCP_ISSUE, NULL);
			}
		}

		// STEP 4 - check the FC_ERASE and FC_COL_ROW_IN_PROG results.

		bad = 0;

		while (GETREG(MON_CHABANKIDLE) != 0);

		for (bank = 0; bank < NUM_BANKS; bank++)
		{
			if (BSP_INTR(bank) & (FIRQ_BADBLK_H | FIRQ_BADBLK_L))
			{
				bad |= (1 << bank);
				CLR_BSP_INTR(bank, 0xFF);
				g_test_result[bank].erase_prog_fail++;
			}
		}

		// STEP 5 - read and verify
		// We check ECC/CRC results for verification.

		for (page_offset = 0; page_offset < PAGES_PER_VBLK; page_offset++)
		{
			for (bank = 0; bank < NUM_BANKS; bank++)
			{
				UINT32 rbank = REAL_BANK(bank);

				if (bad & (1 << bank))
					continue;

				SETREG(FCP_CMD, FC_COL_ROW_READ_OUT);
				SETREG(FCP_BANK, rbank);
				SETREG(FCP_OPTION, FO_P | FO_E);
				SETREG(FCP_DMA_ADDR, read_buffer_base + bank * BYTES_PER_PAGE);
				SETREG(FCP_DMA_CNT, BYTES_PER_PAGE);
				SETREG(FCP_COL, 0);
				SETREG(FCP_ROW_L(bank), vblk_offset * PAGES_PER_VBLK + page_offset);
				SETREG(FCP_ROW_H(bank), vblk_offset * PAGES_PER_VBLK + page_offset);

				while ((GETREG(WR_STAT) & 0x00000001) != 0);
				SETREG(FCP_ISSUE, NULL);
			}
		}

		// STEP 6 - check the FC_COL_ROW_READ_OUT results

		while (GETREG(MON_CHABANKIDLE) != 0);

		for (bank = 0; bank < NUM_BANKS; bank++)
		{
			if (BSP_INTR(bank) & FIRQ_DATA_CORRUPT)
			{
				bad |= (1 << bank);
				CLR_BSP_INTR(bank, 0xFF);
				g_test_result[bank].read_fail++;
			}
		}

		// STEP 7 - erase the blocks, but not the bad ones

		for (bank = 0; bank < NUM_BANKS; bank++)
		{
			UINT32 rbank = REAL_BANK(bank);

			if (bad & (1 << bank))
				continue;

			SETREG(FCP_CMD, FC_ERASE);
			SETREG(FCP_BANK, rbank);
			SETREG(FCP_OPTION, FO_P);
			SETREG(FCP_ROW_L(bank), vblk_offset * PAGES_PER_VBLK);
			SETREG(FCP_ROW_H(bank), vblk_offset * PAGES_PER_VBLK);

			while ((GETREG(WR_STAT) & 0x00000001) != 0);
			SETREG(FCP_ISSUE, NULL);
		}
	}

	// Now that bad blocks contain non-0xFF data, it is a good time to use install.exe to scan bad blocks.
}