📄 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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -