Example #1
0
static void set_psn(UINT32 const lba, UINT32 const psn)			//added by RED
{
	//UINT32 src = (UINT32)g_psn_write + (sizeof(UINT32) * g_psn_write_temp);
	//UINT32 dst = SMT_ADDR + (lba * sizeof(UINT32));
	
	//UINT32 size = sizeof(UINT32) * totals;
	//int i;
	//mem_copy(dst,src,size);
	UINT32 dst, bank, block, sector;
	UINT32 sectors_per_mblk = (SECTORS_PER_BANK + SMT_BANK_NUM - 1) / SMT_BANK_NUM;

	bank = lba / SECTORS_PER_BANK;
	block = ((lba % SECTORS_PER_BANK)) / (sectors_per_mblk);
	sector = ((lba % SECTORS_PER_BANK)) % (sectors_per_mblk);

	dst = smt_piece_map[bank * SMT_BANK_NUM + block];
	if(dst == (UINT32)-1)
	{
#if OPTION_FTL_TEST == 1
		num_miss++;
#endif
		load_smt_piece( bank * SMT_BANK_NUM + block);
		dst = smt_piece_map[bank * SMT_BANK_NUM + block];
		while(_BSP_FSM(g_bank_to_wait) != BANK_IDLE);
	}
	dst = SMT_ADDR + (SMT_PIECE_BYTES * dst) + (sector * sizeof(UINT32));
	smt_bit_map[bank][block / NUM_BANKS_MAX] |= ( 1 <<( block% NUM_BANKS_MAX) );

	write_dram_32( (UINT32*)dst , psn );
}
Example #2
0
static UINT32 get_psn(UINT32 const lba)		//added by RED
{   
	//UINT32 src = SMT_ADDR + (lba * sizeof(UINT32));
	//UINT32 dst = (UINT32)g_psn_read;
	//UINT32 size = sizeof(UINT32) * totals;
	//mem_copy(dst,src,size);
	UINT32 dst, bank, block, sector;
	UINT32 sectors_per_mblk = (SECTORS_PER_BANK + SMT_BANK_NUM - 1) / SMT_BANK_NUM;

	bank = lba / SECTORS_PER_BANK;
	block = (lba % SECTORS_PER_BANK)  / (sectors_per_mblk);
	sector = (lba % SECTORS_PER_BANK) % (sectors_per_mblk);

	dst = smt_piece_map[bank * SMT_BANK_NUM + block];
	if( dst == (UINT32)-1 )
	{
#if OPTION_FTL_TEST == 1
		num_miss++;
#endif
		load_smt_piece( bank * SMT_BANK_NUM + block);
		dst = smt_piece_map[bank * SMT_BANK_NUM + block];
		while(_BSP_FSM(g_bank_to_wait) != BANK_IDLE);
	}
	dst = SMT_ADDR + (SMT_PIECE_BYTES * dst) + (sector * sizeof(UINT32));
	return read_dram_32((UINT32*)dst);

}
Example #3
0
void flush_smt_piece(UINT32 idx)
{
	UINT32 bank,row,block;
	UINT32 dest;
	bank = smt_dram_map[idx] / NUM_BANKS_MAX;
	block = smt_dram_map[idx] % NUM_BANKS_MAX;
	if((smt_bit_map[bank] & (1<<block)) != 0){
		//  smt piece data
		if( g_misc_meta[bank].smt_pieces[block] >= SMT_LIMIT - 1){
			// erase 
			nand_block_erase(bank,g_bad_list[bank][block]);
		}
		//update and flash 
		g_misc_meta[bank].smt_pieces[block] = (g_misc_meta[bank].smt_pieces[block] + 1) % SMT_LIMIT;
		row = g_misc_meta[bank].smt_pieces[block] * SMT_INC_SIZE + ( PAGES_PER_VBLK * g_bad_list[bank][block]);
		// flash map data to nand
		SETREG(FCP_CMD, FC_COL_ROW_IN_PROG);
		SETREG(FCP_OPTION, FO_P | FO_E | FO_B_W_DRDY);
		SETREG(FCP_COL,0);
		SETREG(FCP_ROW_L(bank),row);
		SETREG(FCP_ROW_H(bank),row);
		dest = SMT_ADDR + (idx * SMT_PIECE_BYTES);
		SETREG(FCP_DMA_ADDR,dest);
		SETREG(FCP_DMA_CNT, SMT_PIECE_BYTES);
		while(_BSP_FSM(bank) != BANK_IDLE)
		{
			bank = bank;
		}
		flash_issue_cmd(bank,RETURN_WHEN_DONE);
	}
	smt_piece_map[smt_dram_map[idx]] = (UINT32)-1;
}
Example #4
0
void Main(void)
{
    int count = 0;
    while (1)
    {
        if (eventq_get_count()) {
            count = 0;
            CMD_T cmd;
            eventq_get(&cmd);
            if (cmd.cmd_type == READ) {
                ftl_read(cmd.lba, cmd.sector_count);
            } else {
                if (cmd.cmd_type == WRITE) {
                    if(cmd.lba == 0x3FFFFFFF) {
                        ftl_trim(0, cmd.sector_count);
                    } else {
                        ftl_write(cmd.lba, cmd.sector_count);
                    }
                } else {
                    //uart_print_level_1("-\r\n");
                }
            }
        } else {
            if (g_sata_context.slow_cmd.status == SLOW_CMD_STATUS_PENDING) {
                //uart_print_level_1("*\r\n");
                void (*ata_function)(UINT32 lba, UINT32 sector_count);
                slow_cmd_t* slow_cmd = &g_sata_context.slow_cmd;
                slow_cmd->status = SLOW_CMD_STATUS_BUSY;
                ata_function = search_ata_function(slow_cmd->code);
                ata_function(slow_cmd->lba, slow_cmd->sector_count);
                slow_cmd->status = SLOW_CMD_STATUS_NONE;
            } else {
                count ++;
                if (count == 100000000) {
                    //uart_print_level_1(".\r\n");
                    count = 0;
                    //uart_print_level_1("Warning waiting too long in SATA main loop\r\n");
                    for (int i=0; i<NUM_BANKS; i++) {
                        if (_BSP_FSM(REAL_BANK(i)) == BANK_TAKE) {
                            uart_print_level_1("Bank "); uart_print_level_1_int(i);
                            uart_print_level_1(" (real bank "); uart_print_level_1_int(REAL_BANK(i));
                            uart_print_level_1(") in state: "); uart_print_level_1_int((UINT8)_BSP_FSM(REAL_BANK(i))); uart_print_level_1("\r\n");
                            //uart_print_level_1("Try reset\r\n");
                            //flash_reset_one_bank(i);
                            //break;
                        }
                    }
                }
            }
        }
    }
}
Example #5
0
/* g_smt_target, g_smt_victim */
void load_smt_piece(UINT32 idx){
	UINT32 bank,row,block;
	UINT32 dest;
	UINT32 pblock;	// physical block which have target mapping table

	bank = idx / SMT_BANK_NUM;
	block = idx % SMT_BANK_NUM;

	pblock = block / SMT_BLOCK;
	row = smt_pos[idx] * SMT_INC_SIZE + (PAGES_PER_VBLK * g_bad_list[bank][pblock]);
	if( g_smt_full == 1){
		flush_smt_piece(g_smt_victim);
		g_smt_victim = (g_smt_victim +1 ) % SMT_DRAM;
	}
	SETREG(FCP_CMD, FC_COL_ROW_READ_OUT);	
	SETREG(FCP_DMA_CNT,SMT_PIECE_BYTES);
	SETREG(FCP_COL, 0);
	dest = SMT_ADDR + (g_smt_target * SMT_PIECE_BYTES);
	SETREG(FCP_DMA_ADDR, dest);
	SETREG(FCP_OPTION, FO_P | FO_E );		
	SETREG(FCP_ROW_L(bank), row);
	SETREG(FCP_ROW_H(bank), row);
	
	// fully guarantee 
	//flash_issue_cmd(bank, RETURN_WHEN_DONE);
	while(_BSP_FSM(g_bank_to_wait) != BANK_IDLE);
	flash_issue_cmd(bank, RETURN_ON_ISSUE);
	g_bank_to_wait = bank;

	smt_dram_map[g_smt_target] = idx;
	smt_piece_map[idx] = g_smt_target;
	smt_bit_map[bank][block/NUM_BANKS_MAX] &= ~( 1 <<(block % NUM_BANKS_MAX) );

	/* init or not */
	if(( g_misc_meta[bank].smt_init[block/NUM_BANKS_MAX] & ( 1 << (block % NUM_BANKS_MAX) ) ) == 0){
		mem_set_dram( dest, 0x00, SMT_PIECE_BYTES);
		g_misc_meta[bank].smt_init[block/NUM_BANKS_MAX] |= (1 <<(block % NUM_BANKS_MAX));
	}
	g_smt_target = (g_smt_target + 1) % SMT_DRAM;
	if( g_smt_target == 0 ){
		g_smt_full = 1;
	}
}
Example #6
0
void ftl_write_sector(UINT32 const lba)
{
	UINT32 new_bank, vsect_num, new_row;
	UINT32 new_psn;
	UINT32 temp;
	UINT32 dst,src;
	UINT32 index = lba % SECTORS_PER_PAGE;
	int i;
	//new_bank = lba % NUM_BANKS; // get bank number of sector
	new_bank = g_target_bank;
	
	temp = get_psn(lba);

	if( (temp & (UINT32)BIT31) != 0 ){
		// If data, which located in same lba, is already in dram
		// copy sata host data to same merge buffer sector
		vsect_num = (temp ^ (UINT32)BIT31); 

		dst = MERGE_BUFFER_ADDR + new_bank * BYTES_PER_PAGE + vsect_num * BYTES_PER_SECTOR;
		src = WR_BUF_PTR(g_ftl_write_buf_id) + index * BYTES_PER_SECTOR;
		mem_copy(dst,src, BYTES_PER_SECTOR);
	}
	else{
		// copy sata host data to dram memory merge buffer page 
		//vsect_num = g_misc_meta[new_bank].g_merge_buff_sect;
		vsect_num = g_target_sect;

		dst = MERGE_BUFFER_ADDR + new_bank * BYTES_PER_PAGE + vsect_num * BYTES_PER_SECTOR;
		src = WR_BUF_PTR(g_ftl_write_buf_id) + index * BYTES_PER_SECTOR;

		// Because Firmware does not know 
		// about status of previous nand flash command, 
		// wait until target bank is IDLE 
		// ( target DRAM space is fully flashed ) 
		while(_BSP_FSM(new_bank) != BANK_IDLE);
		mem_copy(dst, src, BYTES_PER_SECTOR);

		// set psn to -1 , it means that data is in dram 
		set_psn(lba, ((UINT32)BIT31 | vsect_num ));

		// for change psn 
		g_merge_buffer_lsn[vsect_num] = lba;

		vsect_num++;

		// If merge_buffer of bank is full ,
		// than flush the merge buffer page to nand flash
		// and set a psn number of all sectors.
		if( vsect_num >= SECTORS_PER_PAGE ){
			/* get free page */
			new_row = get_free_page(new_bank);
			SETREG(FCP_CMD, FC_COL_ROW_IN_PROG);
			SETREG(FCP_OPTION, FO_P | FO_E | FO_B_W_DRDY);
			SETREG(FCP_DMA_ADDR, MERGE_BUFFER_ADDR + new_bank * BYTES_PER_PAGE);
			SETREG(FCP_DMA_CNT, BYTES_PER_PAGE);
			SETREG(FCP_COL,0);
			SETREG(FCP_ROW_L(new_bank),new_row);
			SETREG(FCP_ROW_H(new_bank),new_row);

			flash_issue_cmd(new_bank,RETURN_ON_ISSUE);

			/* initialize merge buffer page's sector point */
		//	g_misc_meta[new_bank].g_merge_buff_sect = 0;
			g_target_sect = 0;
			g_target_bank = (g_target_bank + 1 ) % NUM_BANKS;
			// allocate new psn 
			//new_psn = new_row * SECTORS_PER_PAGE;

			new_psn = new_bank * SECTORS_PER_BANK + new_row * SECTORS_PER_PAGE;
			// vsn - > psn mapping  
			for(i = 0 ;i < SECTORS_PER_PAGE; i++ )
			{
				set_psn( g_merge_buffer_lsn[i],
						new_psn + i );
			}
		}
		else
		{
			//g_misc_meta[new_bank].g_merge_buff_sect++;
			g_target_sect++;
		}
	}
}