www.pudn.com > SMSC USB2.0.zip > ms_media.c
/*============================================================================
____________________________________________________________________________
______________________________________________
SSSS M M CCCC Standard Microsystems Corporation
S MM MM SSSS C Austin Design Center
SSS M M M S C 11000 N. Mopac Expressway
S M M SSS C Stonelake Bldg. 6, Suite 500
SSSS M M S CCCC Austin, Texas 78759
SSSS ______________________________________________
____________________________________________________________________________
Copyright(C) 1999, Standard Microsystems Corporation
All Rights Reserved.
This program code listing is proprietary to SMSC and may not be copied,
distributed, or used without a license to do so. Such license may have
Limited or Restricted Rights. Please refer to the license for further
clarification.
____________________________________________________________________________
Notice: The program contained in this listing is a proprietary trade
secret of SMSC, Hauppauge, New York, and is copyrighted
under the United States Copyright Act of 1976 as an unpublished work,
pursuant to Section 104 and Section 408 of Title XVII of the United
States code. Unauthorized copying, adaption, distribution, use, or
display is prohibited by this law.
____________________________________________________________________________
Use, duplication, or disclosure by the Government is subject to
restrictions as set forth in subparagraph(c)(1)(ii) of the Rights
in Technical Data and Computer Software clause at DFARS 52.227-7013.
Contractor/Manufacturer is Standard Microsystems Corporation,
80 Arkay Drive, Hauppauge, New York, 1178-8847.
____________________________________________________________________________
____________________________________________________________________________
media.c - common media sector-mapping, sector copying code, used as a base
class for sm_media & ms_media specific classes
____________________________________________________________________________
comments tbd
____________________________________________________________________________
Revision History
Date Who Comment
________ ___ _____________________________________________________________
03/01/02 cds initial version
03/13/02 tbh started filling in the stubs
04/01/02 tbh ms_media_erase_block protects boot blocks now
04/02/02 tbh added ms_media_copy_sector
04/19/02 tbh added ms_media_resolve_conflict
06/03/02 cds implemented ms_media_copy_sector
08/06/02 tbh modified ms_media_copy_sector to use single-page copy commands
to work around the SanDisk 64MB issue with cards whose date
codes are < J (they assert breq after block-end on writes) [br308]
08/13/02 tbh additional comments, minor tweaks to ms_media_copy_sector()
08/28/02 tbh changed interpretation of uncorrectable error bits from
"all relevant bits set -> uncorrectable error" to
"any relevant bit set -> uncorrectable error" to resolve the
data corruption issue on sony cards (sorry, no bug reporter number
was entered yet)
09/04/02 cds address name & usage change-over
g_addr_sector => g_addr_page,
g_addr_page => g_addr_segment,
_media_data(sectors_per_block) => _media_data(pages_per_block)
_media_data(cis_phy_block) => _media_data(boot_block)
_media_data(cis_sector) => _media_data(boot_sector)
(new item) => _media_data(segments_per_page)
11/01/02 tbh ms_media_is_phyblock_ok() now references the bad block table
from the boot sector of the ms card.
do not erase any blocks in ms_media_erase_block() if write protected.
added ms_media_is_phyblock_wp(), but didn't use it. instead
ms_media_erase_block performs the test (for the information block).
11/03/02 cds added new function to report boot area blocks as "reserved" so that they
can neither be read nor written.
============================================================================*/
#define __ms_media_dot_c__
#include "project.h"
// provide vtable definition
code _vtbl_defn(ms_media);
// some shared code between this and ms.c files
extern t_result ms_write_parm_reg(uint8 sys_parm, uint8 cmd_parm) reentrant;
extern t_result ms_set_cmd(uint8 cmd) reentrant;
extern t_result ms_get_int(uint8 ticks) reentrant;
extern t_result ms_read_extra_data_reg(void) reentrant;
extern t_result ms_set_tpc(uint8 tpc, uint8 count) reentrant;
extern t_result ms_wait_fifo_with_timeout(uint8 msk, uint8 val, uint8 ticks) reentrant;
extern t_result ms_write_all_reg(uint8 sys_parm, uint8 cmd_parm) reentrant;
// hacks into ms.c to enable ms_media_copy_sector to access relevant data.
// perhaps would be better to move that function in to ms.c?
extern xdata uint8 _factor; // interrupt factor from get_int()
extern xdata uint8 _status1; // hack to get SanDisk64MB working
//------------------------------------------------------------------------------
static xdata t_udw32 _phyblk;
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void set_rd_phyblk()
{
_phyblk.u32 = g_addr_zone * _media_data(physical_blocks_per_zone) + g_addr_rd_phy_blk;
g_ms_blk_addr_msb = _phyblk.u8.lh;
g_ms_blk_addr_mid = _phyblk.u8.hl;
g_ms_blk_addr_lsb = _phyblk.u8.lo;
// g_ms_page = g_addr_sector;
g_ms_page = g_addr_page;
//TRACE3(286, ms, 0, " addr:0x00%02X%02X%02X", g_ms_blk_addr_msb, g_ms_blk_addr_mid, g_ms_blk_addr_lsb);
//TRACE1(287, ms, 0, " page:0x%02X", g_ms_page);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void set_wr_phyblk()
{
_phyblk.u32 = g_addr_zone * _media_data(physical_blocks_per_zone) + g_addr_wr_phy_blk;
g_ms_blk_addr_msb = _phyblk.u8.lh;
g_ms_blk_addr_mid = _phyblk.u8.hl;
g_ms_blk_addr_lsb = _phyblk.u8.lo;
// g_ms_page = g_addr_sector;
g_ms_page = g_addr_page;
//TRACE3(286, ms, 0, " addr:0x00%02X%02X%02X", g_ms_blk_addr_msb, g_ms_blk_addr_mid, g_ms_blk_addr_lsb);
//TRACE1(287, ms, 0, " page:0x%02X", g_ms_page);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
t_result ms_media_erase_block() reentrant
{
uint16 old_page;
trace2(0, ms_media, 110, "ms_media_erase_block() - zone:%d blk:%d", g_addr_zone, g_addr_wr_phy_blk);
old_page = g_addr_page;
g_addr_page = 0;
set_wr_phyblk();
g_addr_page = old_page;
// don't erase the boot blocks
if (_phyblk.u32 <= _media_data(boot_block))
{
trace0(0, err, 0, "error: attempt to erase a boot block");
return k_error;
}
if (_lun_data(media) & kbm_lun_media_wrprot)
{
trace0(0, err, 0, "error: the disk is write protected");
return k_media_error_wp;
}
if (ms_is_this_blk_the_information_block(g_addr_zone * _media_data(physical_blocks_per_zone) + g_addr_wr_phy_blk))
{
trace0(0, err, 0, "error: attempt to erase information block");
return k_media_error_wp;
}
return ms_erase_block();
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//t_result ms_media_read_sector() reentrant
//{
// trace0(0, ms_media, 0, "ms_media_read_sector()");
// set_rd_phyblk();
// return ms_pio_read_page(k_max_pnr);
//}
#if 0
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
t_result ms_media_copy_sector() reentrant
{
trace0(0, ms_media, 0, "ms_media_copy_sector()");
set_rd_phyblk();
return ms_copy_page();
}
#else
//+-----------------------------------------------------------------------------
// Name:
// ms_media_copy_sector()
//
// Declaration:
// t_result ms_media_copy_sector(void);
//
// Purpose:
// Copy a single 512 byte sector/page from one block to another block.
// Used during copy-head/copy-tail operations.
//
// Arguments:
// None.
//
// Return:
//
// Notes:
// This implements pattern-2 for writes.
// Could probably be a little faster changing to implement patters-1 for writes,
// avoiding an extra get_int call.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
t_result ms_media_copy_sector() reentrant
{
trace4(0, ms_media, 0, "+ms_media_copy_sector() zone:%d SRC_BLK:%d DEST_BLK:%d page:%d", g_addr_zone, g_addr_rd_phy_blk, g_addr_wr_phy_blk, g_addr_page) ;
if( (g_addr_wr_phy_blk == k_block_free) )
{
trace0(0, ms_media, 0, " error. invalid wr_phy_block: 0xffff") ;
return k_media_err_illegal_lba ;
}
if( (g_addr_zone==0) && (g_addr_wr_phy_blk<=_media_data(boot_block)))
{
trace1(0, ms_media, 0, " error. wr_phy_block has lower address than cis_phy_block. Invalid address: 0x%04X", g_addr_wr_phy_blk) ;
return k_media_err_illegal_lba ;
}
// set direction - device->sram
_mcu_register_set_bits( x_ep2_ctl, kbm_ep2_ctl_dir) ;
// enable buffer a to receive (wrtog_valid=1, ramwr_tog=0) ;
_mcu_register_set_bits( x_ep2_ctl, kbm_ep2_ctl_wrtog_valid) ;
// issue command to read sector at g_addr_rd_phy_blk
set_rd_phyblk();
if (k_success != ms_write_parm_reg(0x80, 0x20))
return k_error;
if (k_success != ms_set_cmd(k_ms_block_read))
return k_error;
// wait for memory stick to be ready
if (k_success != ms_get_int(10))
return k_error;
if (_factor & kbm_ms_reg_int_cmdnk)
{
trace0(0, ms, 10, "error: cmdnk");
return k_error;
}
if (!(_factor & kbm_ms_reg_int_ced))
{
trace0(0, ms, 10, "error: ced not set");
return k_error;
}
trace0(0, ms, 0, "ced");
if (!(_factor & kbm_ms_reg_int_breq))
{
trace0(0, ms, 0, "error: breq not set");
return k_error;
}
trace0(0, ms, 0, "breq");
if (_factor & kbm_ms_reg_int_err)
{
trace0(0, ms, 0, "error: err");
if (k_success != ms_read_status())
return k_error;
// if (_status1 & (kbm_ms_reg_status1_ucdt |kbm_ms_reg_status1_ucex |kbm_ms_reg_status1_ucfg) ==
// (kbm_ms_reg_status1_ucdt |kbm_ms_reg_status1_ucex |kbm_ms_reg_status1_ucfg))
if (_status1 & (kbm_ms_reg_status1_ucdt |kbm_ms_reg_status1_ucex |kbm_ms_reg_status1_ucfg))
{
trace0(0, ms, 0, "error: ucdt&ucex&ucfg - uncorrectable flash read error");
ms_media_set_phyblock_failed();
return k_error;
}
}
// daken must be set during dma transfers.
// only wr-page-data and rd-page-data can be issued with daken set.
_ms_register_set_bits(ms_mode_ctl, kbm_ms_mode_ctl_daken);
if (k_success != ms_set_tpc(k_ms_tpc_rd_page_data |0x02, 0))
{
_ms_register_clr_bits(ms_mode_ctl, kbm_ms_mode_ctl_daken);
return k_error;
}
// $$$ IMPORTANT! This begin_critical_section() is ended in the 'end_burst' function
// $$$ to prevent xdata access while blk_xfer bit is enabled
_mcu_begin_critical_section();
// set fmc ctl reg - 1 sector
_mcu_register_wr(x_fmc_cnt3, 0x00) ;
_mcu_register_wr(x_fmc_cnt2, 0x00) ;
_mcu_register_wr(x_fmc_cnt1, 0x02) ;
_mcu_register_wr(x_fmc_cnt0, 0x00) ;
// enable blk xfer, use 512 bytes per burst
_mcu_register_wr(x_fmc_ctl, (kbm_fmc_ctl_512_byte_pkt|kbm_fmc_ctl_blk_xfer_en)) ;
_mcu_register_wr(x_isr0, kbm_isr0_blk_xfer_complete);
_mcu_register_clr_bits(x_imr0, kbm_isr0_blk_xfer_complete);
// $$$$$$ warning!
// $$ must do a while loop because we cannot yield
// also, cannot have a timer, because of the memory stick bug... the timer
// is in XDATA space, and touching it during ms fmdu xfers ist verboten
while( !(_mcu_register_rd(x_isr0)&kbm_isr0_blk_xfer_complete)) ;
_mcu_end_critical_section() ;
if (!_ms_rx_data_fifo_is_empty())
{
trace0(0, ms, 10, "alert - entered read_end_burst before rx fifo emptied - wait before stopping dma");
if (k_success != ms_wait_fifo_with_timeout(ms_fifo_stat_r_buf_e, ms_fifo_stat_r_buf_e, 3)) //rcc test for MS bug tbh!!!
return k_error;
}
// clear daken before issuing command other than wr-page-data and rd-page-data
_ms_register_clr_bits(ms_mode_ctl, kbm_ms_mode_ctl_daken);
trace0(0, ms_media, 0, "ms_copy_sector() read complete") ;
// bind current logical block to new physical block
ms_media_bind_log2phy() ;
// reverse data flow direction: sram->device
_mcu_register_clr_bits( x_ep2_ctl, kbm_ep2_ctl_dir) ;
// program the card to write 1 sector at g_addr_wr_phy_blk
set_wr_phyblk();
//return ms_write_issue_command();
if (k_success != ms_write_all_reg(0x80, 0x20))
return k_error;
if (k_success != ms_set_cmd(k_ms_block_write))
return k_error;
if (k_success != ms_get_int(10))
return k_error;
if (_factor & kbm_ms_reg_int_cmdnk)
{
trace0(0, ms, 10, "error: cmdnk");
return k_error;
}
if (!(_factor & kbm_ms_reg_int_breq))
{
trace0(0, ms, 10, "error: breq not set");
return k_error;
}
// daken must be set during dma transfers.
// only wr-page-data and rd-page-data can be issued with daken set.
_ms_register_set_bits(ms_mode_ctl, kbm_ms_mode_ctl_daken);
if (k_success != ms_set_tpc(k_ms_tpc_wr_page_data |0x02, 0))
{
_ms_register_clr_bits(ms_mode_ctl, kbm_ms_mode_ctl_daken);
return k_error;
}
// IMPORTANT! This begin_critical_section() is ended in the 'rw_intra_burst' function
// to prevent xdata access while blk_xfer bit is enabled
_mcu_begin_critical_section();
// set fmc ctl reg - 1 sector
_mcu_register_wr(x_fmc_cnt3, 0x00) ;
_mcu_register_wr(x_fmc_cnt2, 0x00) ;
_mcu_register_wr(x_fmc_cnt1, 0x02) ;
_mcu_register_wr(x_fmc_cnt0, 0x00) ;
// enable blk xfer, use 512 bytes per burst
_mcu_register_wr(x_isr0, kbm_isr0_blk_xfer_complete);
_mcu_register_clr_bits(x_imr0, kbm_isr0_blk_xfer_complete);
_mcu_register_wr(x_fmc_ctl, (kbm_fmc_ctl_512_byte_pkt|kbm_fmc_ctl_blk_xfer_en)) ;
// point the byte count & source buffer for fmdu to buffer a
_mcu_register_wr( x_ramrdbc_a1, 0x02) ;
_mcu_register_wr( x_ramrdbc_a2, 0x00) ;
// (rdtog_valid:1 ramrd_tog:0)
_mcu_register_set_bits( x_ep2_ctl, kbm_ep2_ctl_rdtog_valid) ;
// warning!
// must do a while loop because we cannot yield
// also, cannot have a timer, because of the memory stick bug... the timer
// is in XDATA space, and touching it during ms fmdu xfers ist verboten
while( !(_mcu_register_rd( x_isr0)&kbm_isr0_blk_xfer_complete)) ;
_mcu_end_critical_section() ;
if (!_ms_tx_data_fifo_is_empty())
{
trace0(0, ms, 10, "alert - entered write_end_burst before tx fifo emptied - wait before stopping dma");
if (k_success != ms_wait_fifo_with_timeout(ms_fifo_stat_t_buf_e, ms_fifo_stat_t_buf_e, 3)) //rcc test for MS bug tbh!!!
return k_error;
}
// clear daken before issuing command other than wr-page-data and rd-page-data
_ms_register_clr_bits(ms_mode_ctl, kbm_ms_mode_ctl_daken);
// get status
if (k_success != ms_get_int(10))
return k_error;
if (_factor & kbm_ms_reg_int_cmdnk)
{
trace0(0, ms, 10, "error: cmdnk");
return k_error;
}
if (_factor & kbm_ms_reg_int_breq)
{
trace0(0, ms, 0, "error: breq set after block-end (presumably) delivered");
return k_error;
//TRACE0(448, ms, 0, "alert: breq set");
}
if (!(_factor & kbm_ms_reg_int_ced))
{
trace0(0, ms, 0, "error: ced not set");
return k_error;
}
if (_factor & kbm_ms_reg_int_err)
{
trace0(0, ms, 10, "error: ced&err unrecoverable flash write error");
ms_media_set_phyblock_failed();
return k_error;
}
// write complete
return k_success;
}
#endif
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//t_result ms_media_write_sector() reentrant
//{
// trace0(0, ms_media, 0, "ms_media_write_sector()");
// set_wr_phyblk();
// return ms_pio_write_page(k_max_pnr);
//}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
t_result ms_media_phy2log() reentrant
{
uint16 absolute;
uint16 relative;
trace0(0, ms_media, 10, "ms_media_phy2log()");
absolute = g_ms_extra[k_log_addr_msb_flg_offset] * 256 + g_ms_extra[k_log_addr_lsb_flg_offset];
switch (g_addr_zone)
{
case 0:
relative = absolute;
break;
case 1:
relative = absolute - _media_data(logical_blocks_per_boot_zone);
break;
default:
relative = absolute - _media_data(logical_blocks_per_boot_zone);
relative %= _media_data(logical_blocks_per_zone);
break;
}
g_addr_log_blk = relative;
trace3(0, ms, 110, "...zone:%02d absolute:0x%04X relative:0x%04X", g_addr_zone, absolute, g_addr_log_blk);
return k_success;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
t_result ms_media_bind_log2phy() reentrant
{
uint16 absolute;
trace1(0, ms_media, 10, "ms_media_bind_log2phy() log:%04X", g_addr_log_blk);
switch (g_addr_zone)
{
case 0:
absolute = g_addr_log_blk;
break;
case 1:
absolute = g_addr_log_blk + _media_data(logical_blocks_per_boot_zone);
break;
default:
absolute = g_addr_log_blk + _media_data(logical_blocks_per_boot_zone);
absolute += (g_addr_zone - 1) * _media_data(logical_blocks_per_zone);
break;
}
trace3(0, ms, 10, "...zone:%02d absolute:0x%04X relative:0x%04X", g_addr_zone, absolute, g_addr_log_blk);
g_ms_extra[k_log_addr_msb_flg_offset] = _h(absolute);
g_ms_extra[k_log_addr_lsb_flg_offset] = _l(absolute);
return k_success;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
t_result ms_media_set_phyblock_failed() reentrant
{
trace0(0, ms_media, 0, "ms_media_set_phyblock_failed()");
g_ms_extra[k_ovwr_flg_offset] &= ~ kbm_ms_ext_ovwr_bkst;
return k_error;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
#define k_reference_bad_block_table
t_bool ms_media_is_phyblock_ok() reentrant
{
t_bool rslt;
trace0(0, ms_media, 110, "ms_media_is_phyblock_ok()");
// start out hopeful
rslt = k_yes;
// is this a user area block?
if(!g_addr_zone && g_addr_rd_phy_blk < g_ms_user_area_start_blk)
{
trace0(0, ms_media, 110, "alert: ms_media_is_phyblock_ok() - block is not in user area");
rslt = k_no;
}
// block status of 0 is bad
if (!(g_ms_extra[k_ovwr_flg_offset] & kbm_ms_ext_ovwr_bkst))
{
trace0(0, ms_media, 110, "alert: ms_media_is_phyblock_ok() - bad page by bkst");
rslt = k_no;
}
// page status of 1 is bad
if (g_ms_extra[k_ovwr_flg_offset] & (kbm_ms_ext_ovwr_pgst0 | kbm_ms_ext_ovwr_pgst1) == 1)
{
trace0(0, ms_media, 110, "alert: ms_media_is_phyblock_ok() - bad page by pgst01");
rslt = k_no;
}
// is it the log2phy map table block? if yes it should get whacked.
if (!g_ms_extra[k_mgmt_flg_offset] & kbm_ms_ext_mgmt_atflg)
{
trace0(0, ms_media, 110, "alert: ms_media_is_phyblock_ok() - table block found");
trace1(0, ms, 80, "atflg:%02X", g_ms_extra[k_mgmt_flg_offset] & kbm_ms_ext_mgmt_atflg);
}
#ifdef k_reference_bad_block_table
// read the bad block list
if (rslt == k_yes)
{
t_uw16 blk_to_check;
trace0(0, ms_media, 110, "reference the bad block table");
// look to see if this phy block is in it
trace2(0, ms_media, 110, "g_addr_zone:%d g_addr_rd_phy_blk:%d", g_addr_zone, g_addr_rd_phy_blk);
blk_to_check.u16 = g_addr_zone * _media_data(physical_blocks_per_zone) + g_addr_rd_phy_blk;
trace1(0, ms_media, 110, "blk_to_check:%d", blk_to_check.u16);
if (ms_is_this_blk_in_bad_blk_tbl(blk_to_check.u16))
{
// this physical block appears in the bad block list
rslt = k_no;
trace1(0, ms_media, 110, "alert: block:%d is in the bad block table!", blk_to_check.u16);
}
}
//exit:
#endif //k_reference_bad_block_table
trace1(0, ms_media, 110, "ms_media_is_phyblock_ok(): %c", rslt ? 'Y' : 'N');
return rslt;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
t_result ms_media_is_phyblock_blank() reentrant
{
t_bool is_blank;
is_blank = (0xFF == g_ms_extra[k_log_addr_msb_flg_offset]) && (0xFF == g_ms_extra[k_log_addr_lsb_flg_offset]);
trace1(0, ms_media, 0, "ms_media_is_phyblock_blank(): %c", is_blank ? 'Y' : 'N');
return is_blank;
}
#if 0
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
t_result ms_media_is_phyblock_wp() reentrant
{
t_bool is_wp;
uint16 blk_to_check;
blk_to_check = g_addr_zone * _media_data(physical_blocks_per_zone) + g_addr_rd_phy_blk;
trace1(0, ms_media, 110, "blk_to_check:%d", blk_to_check);
is_wp = ms_is_this_blk_the_information_block(blk_to_check);
trace1(0, ms_media, 0, "ms_media_is_phyblock_wp(): %c", is_wp ? 'Y' : 'N');
return is_wp;
}
#endif
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
t_result ms_media_read_extra_data() reentrant
{
trace0(0, ms_media, 0, "ms_media_read_extra_data()------------------------------------");
set_rd_phyblk();
return ms_read_extra_data();
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
t_result ms_media_write_extra_data() reentrant
{
trace0(0, ms_media, 0, "ms_media_write_extra_data()");
set_wr_phyblk();
return ms_write_extra_data();
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
t_result ms_media_clear_extra_data(void) reentrant
{
trace0(0, ms_media, 0, "ms_media_clear_extra_data()");
memset(g_ms_extra, 0xFF, 4);
return k_success;
}
//+-----------------------------------------------------------------------------
// Name:
// ms_media_resolve_conflict()
//
// Declaration:
// t_result ms_media_resolve_conflict(void) reentrant
//
// Purpose:
// resolve a log2phy binding in a media-specific algorithm
//
// Arguments:
// - see Notes
//
// Return:
// k_success always
//
// Notes:
// when called,
// g_addr_rd_phy_blk contains one of the bindings,
// g_addr_wr_phy_blk contains the original mapping
//
// before returning, ensure:
// g_addr_rd_phy_blk should contain the correct mapping
// g_addr_wr_phy_blk should contain the block to be erased (or not used)
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
t_result ms_media_resolve_conflict() reentrant
{
uint16 tmp;
uint8 udst0;
uint8 udst1;
trace0(0, ms_media, 110, "ms_media_resolve_conflict()");
trace2(0, ms_media, 110, "->g_addr_rd_phy_blk:0x%04X, g_addr_wr_phy_blk:0x%04X", g_addr_rd_phy_blk, g_addr_wr_phy_blk);
// determine the update status of the block at g_addr_rd_phy_blk
set_rd_phyblk();
ms_read_extra_data();
udst0 = g_ms_extra[k_ovwr_flg_offset] & kbm_ms_ext_ovwr_udst;
// determine the update status of the block at g_addr_wr_phy_blk
set_wr_phyblk();
ms_read_extra_data();
udst1 = g_ms_extra[k_ovwr_flg_offset] & kbm_ms_ext_ovwr_udst;
// udst0 udst1 choose
// ----- ----- ------
// 0 0 largest phy addr
// 0 1 g_addr_rd_phy_blk
// 1 0 g_addr_wr_phy_blk
// 1 1 largest phy addr
if (udst0 == udst1)
{
// cannot tell by update status; choose the larger physical block number
tmp = _max(g_addr_rd_phy_blk, g_addr_wr_phy_blk);
g_addr_wr_phy_blk = _min(g_addr_rd_phy_blk, g_addr_wr_phy_blk);
g_addr_rd_phy_blk = tmp;
trace1(0, ms_media, 110, "-->chose larger:0x%04X", g_addr_rd_phy_blk);
}
else
if (!udst1)
{
// ye olde triangle swap
tmp = g_addr_wr_phy_blk;
g_addr_wr_phy_blk = g_addr_rd_phy_blk;
g_addr_rd_phy_blk = tmp;
trace1(0, ms_media, 110, "-->chose: wr by update status 0x%04X", g_addr_rd_phy_blk);
}
else
{
trace1(0, ms_media, 110, "-->chose: rd by update status 0x%04X", g_addr_rd_phy_blk);
}
// and reverse the order because this works, and doing it the way the spec says doesnt.
//tmp = g_addr_wr_phy_blk;
//g_addr_wr_phy_blk = g_addr_rd_phy_blk;
//g_addr_rd_phy_blk = tmp;
// otherwise udst0 must be zero, so no variable swapping needs to occur
return k_success;
}
//+-----------------------------------------------------------------------------
// Name:
// media_erase_card()
//
// Declaration:
// t_result media_erase_card() reentrant
//
// Purpose:
// TBD
//
// Arguments:
// TBD
//
// Return:
// k_success always
//
// Notes:
// TBD
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
#if 0
t_result ms_media_erase_card() reentrant
{
uint16 max_lb ;
trace0(0, sm, 0, "ms_media_erase_card() - Erasing Memory Stick Card.") ;
for(g_addr_zone=0 ; g_addr_zone < _media_data(num_zones) ; g_addr_zone++)
{
max_lb = g_addr_zone? (_media_data(logical_blocks_per_zone)) : (_media_data(logical_blocks_per_boot_zone)) ;
g_addr_log_blk = 0 ;
for(g_addr_wr_phy_blk = g_addr_zone?0:_media_data(cis_phy_block)+1;
g_addr_wr_phy_blk < _media_data(physical_blocks_per_zone) ;
g_addr_wr_phy_blk++)
{
_media_erase_block() ;
if( g_addr_log_blk < max_lb )
{
// bind the log2phy addrs... memory stick gets upset if all blocks are bound to log_blk 0xffff
_media_clear_extra_data() ;
_media_bind_log2phy() ;
_media_write_extra_data() ;
g_addr_log_blk++ ;
}
}
}
return k_success ;
}
#endif
//+-----------------------------------------------------------------------------
// Name:
// ms_media_is_phyblock_reserved()
//
// Declaration:
// t_result ms_media_is_phyblock_reserved() reentrant
//
// Purpose:
// tells mapper whether or not a block is reserved (i.e. boot area) or
// usable by mapper & user.
//
// Arguments:
//
// Return:
// k_true if physical zone/block can be a user-accessible block
// k_false if physical block should be ignored by the mapper for everything
//
// Notes:
// a reserved block is NOT a factory or user-marked bad block. it is a block reserved
// for storing private data or boot information. (i.e. boot blocks, boot area, etc.)
// blocks marked bad by the factory will be detected in a subsequent call
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
t_result ms_media_is_phyblock_reserved(void) reentrant
{
trace0(0, ms_media, 110, "ms_media_is_phyblock_reserved()");
if ((!g_addr_zone) && (g_addr_rd_phy_blk < g_ms_user_area_start_blk))
{
trace2(0, sm_media, 0, "block %d:%d is part of the boot area. tell mapper it is reserved", g_addr_zone, g_addr_rd_phy_blk);
return k_true;
}
return k_false;
}
//---eof------------------------------------------------------------------------