📄 ms.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.
____________________________________________________________________________
____________________________________________________________________________
sm.c - memory stick mass storage class implementation file
____________________________________________________________________________
comments tbd
____________________________________________________________________________
Revision History
Date Who Comment
________ ___ _____________________________________________________________
11/##/01 tbh initial version
02/26/02 tbh changed strcpy to strncpy for safety
04/01/02 tbh read_boot now finds 2 boot blocks on cards that have them
04/02/02 tbh added ms_copy_page
04/17/02 tbh override dfa_lun_mode_sense
04/18/02 tbh removed that override. superclass method handles it now.
05/07/02 cds added a rw_intra_burst callback to actually perform the blk_xfer inner loop
to get around xdata-access bug in the chip
05/09/02 cds added call to _dev_soft_reset() when a usbreset occurs during rw_intra_bursts
06/03/02 cds updated ms_write_end_xfer() to turn off auto-xfer so that
the sector copy can use the fmdu.
06/19/02 tbh converted to read boot into xdata buf instead of packet buf
since bot layer is can now run concurrently with discovery
06/20/02 tbh tweaked the intra-burst callback to stop clearing the isr bit
to be compatible with the perf opto done in fmc_transfer
06/26/02 tbh added nops in ms_wait_msc_stat_sif_with_timeout.
two back to back reads of the alt_stat register causes failure.
there is some latency issue causing intermittant failure...
inserting nops fixes it.
07/01/02 tbh write-protect check is now performed in the lun layer
07/09/02 cds renamed WorkBuf to g_sector_buffer
07/12/02 tbh lun string name change caused by mandate from on high
07/17/02 tbh ms_write_end_xfer sets g_fmc_rslt if map_write_flush returns an error
because fmc_transfer doesn't check the return code of the callback.
I feared breaking all of the other luns by changing fmc...
07/18/02 tbh fixed long standing (but until recently dormant) bug in
ms_rw_intra_burst_callback where && was erroneously used
in place of &.
07/23/02 tbh the ms_wait_msc_stat_sif_with_timeout nop injection was insufficient,
it seems. i increased the number of ops and moved them into the do
loop to delay betwean -every- read of the ms_alt_stat register.
this appears to resolve the issue of the cards formatted by DoTop
becoming unreadable in the 210.
07/31/02 cds called media_set_active(...) instead of setting g_active_media
to select a new media object.
08/06/02 tbh added _force_one_burst_per_split to solve the SanDisk 64MB cards
w/ date codes < J [bug report br308]
08/13/02 tbh added status check after read error in read-begin-burst to
distinguish uncorrectabel error from correctable error on last block.
08/28/02 tbh added extra get-int after block-end command for read and write
to ensure that no error happened issuing that command (shawn's suggestions).
also 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)
=> _media_data(segments_per_page)
09/12/02 tbh replaced strncpy() with memcpy() to save data space.
09/18/02 cds initialized _media_data(options) field to kbm_media_data_opts_none
10/17/02 cds updated for new lun vtbl and lun_data macros
11/01/02 tbh made xbuf_rd() visible so ms_media.c can call it.
ms_read_boot_block was using the wrong boot block when more than one
exists. changed to use the lowest-numbered one, per the spec.
move write-protection test to occur before map_build_sector_map
to avoid erroneous block erase on write protected disks.
11/02/02 tbh added ms_is_this_blk_in_bad_blk_tbl().
added ms_find_map_block() to see if any exists, and compare contents.
11/03/02 cds - updated ms_is_this_blk_in_bad_blk_tbl() to include info block
- added new global g_ms_user_area_start_blk to help mapper know which blocks
are to be used for mapping
- updated bad-block table code to read data in big endian format
============================================================================*/
#define __ms_dot_c__
#include "project.h"
#include "dev.h"
code _vtbl_defn(ms);
void fmc_dbg_dump_sector(uint8* sector) reentrant;
//#define k_memory_stick_eraser
//------------------------------------------------------------------------------
// module globals
// status
xdata uint8 _factor;
xdata uint8 _status0;
xdata uint8 _status1;
// extra data registers buffer
xdata uint8 g_ms_extra[4];
// shadow registers
xdata uint8 g_ms_blk_addr_msb;
xdata uint8 g_ms_blk_addr_mid;
xdata uint8 g_ms_blk_addr_lsb;
xdata uint8 g_ms_page;
// logical to physical sector mapping table
//xdata uint16 _ms_map_table[512];
#define k_map_boot_blk 0x8000
#define k_map_initial_err 0xfffd
#define k_map_fatal_err 0xfffe
// total number of blocks on the card
xdata t_uw16 _ms_block_per_card;
// block size - 8k or 16k bytes
xdata t_uw16 _ms_byte_per_block;
// segment size - number of card blocks in a card segment
#define k_phy_block_per_segment 512L
#define k_log_block_per_segment 496L
#define k_log_block_per_boot_segment 494L
// pages per block - a page is analogous to a mass storage class logical block, or disk sector
xdata uint16 _ms_page_per_block;
// tables used by the mapper/pager
#define k_ms_max_zones_per_table 2
xdata uint16 _ms_log2phy[k_ms_max_zones_per_table][k_phy_block_per_segment];
xdata uint8 _ms_assign_map[k_ms_max_zones_per_table][k_phy_block_per_segment/8];
xdata uint16 _ms_bad_blk_tbl[256];
xdata uint16 g_ms_user_area_start_blk;
// br308
// set to false when the boot blocks are read.
// set to true if a block write fails with breq after block-end (i.e., exibits the bug).
// provides the solution for the SanDisk 64MB cards w/ date codes < J
static bit _force_one_burst_per_split;
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
t_bool ms_is_this_blk_in_bad_blk_tbl(uint16 blk) reentrant
{
uint8 i;
for (i=0; i<255; i++)
{
// the zeroth entry in this table is the "information block"
// any non-FFFF blocks in the table that are off the end of the card
// are to be ignored.
if (_ms_bad_blk_tbl[i] == 0xFFFF)
return k_no;
if (_ms_bad_blk_tbl[i] == blk)
{
// this physical block appears in the bad block list
trace1(0, ms_media, 110, "alert: block:%d is in the bad block table!", _ms_bad_blk_tbl[i]);
if (!i)
{
trace0(0, ms_media, 110, " and its the information block!");
}
return k_yes;
}
}
return k_no;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
t_bool ms_is_this_blk_the_information_block(uint16 blk) reentrant
{
// the zeroth entry in this table is the "information block"
if (_ms_bad_blk_tbl[0] == blk)
{
// this physical block appears in the bad block list
trace1(0, ms_media, 110, "alert: block:%d is in the information block!", blk);
return k_yes;
}
return k_no;
}
//+-----------------------------------------------------------------------------
// Name:
// ms_wait_msc_stat_rdy_with_timeout
//
// Declaration:
// t_result ms_wait_msc_stat_rdy_with_timeout(uint8 ticks);
//
// Purpose:
// Wait for the ready bit in the msc status register to go hi indicating that
// the MS card can accept a TPC.
//
// Arguments:
// ticks - a uint8 representing the timeout period in milliseconds.
//
// Return:
// A t_result indicating:
// k_success - the bit was set, and this routine has cleared it.
// k_usbrst - usb reset signalling was detected while waiting.
// k_aborted - traffic occurred on the control pipe while waiting (probably a mass storage reset).
// k_timeout - timeout limit exceeded.
//
// Notes:
// This is a FUNCTION, not a DFA.
// Clears the ready bit after seeing it get set (to rearm for the next one).
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
xdata uint8 status; //!!! NEED PROPER NAMES IF STICK TO THIS SCHEME (AVOID STKOVF)
xdata t_sync sync;
t_result ms_wait_msc_stat_rdy_with_timeout(uint8 ticks) reentrant;
t_result ms_wait_msc_stat_rdy_with_timeout(uint8 ticks) reentrant
{
//uint8 status;
//t_sync sync;
trace1(0, ms, 1, "ms_wait_msc_stat_rdy_with_timeout(ticks:%d)", ticks);
//_stack_dump();
//_stack_check();
thread_set_timer(ticks+1);
do
{
// clear the interrupt generator in the sony block
//status = _ms_register_rd(ms_alt_stat);
status = _mcu_register_rd(x_msc_stat);
sync = thread_got_sync(kbm_sync_usbrst |kbm_sync_abort |kbm_sync_timer);
_thread_clr_sync(sync);
if (sync & kbm_sync_abort)
{
trace0(0, err, 110, "ms_wait_msc_stat_rdy_with_timeout() - error: kbm_sync_abort");
return k_aborted;
}
if (sync & kbm_sync_usbrst)
{
trace0(0, err, 110, "ms_wait_msc_stat_rdy_with_timeout() - error: kbm_sync_usbrst");
return k_usbreset;
}
if (sync & kbm_sync_timer)
{
trace0(0, err, 110, "ms_wait_msc_stat_rdy_with_timeout() - error: kbm_sync_timer");
return k_timeout;
}
} while ((status & kbm_msc_stat_rdy) != kbm_msc_stat_rdy);
_mcu_register_wr(x_msc_stat, kbm_msc_stat_rdy);
return k_success;
}
//+-----------------------------------------------------------------------------
// Name:
// ms_wait_msc_stat_sif_with_timeout
//
// Declaration:
// t_result ms_wait_msc_stat_sif_with_timeout(uint8 ticks);
//
// Purpose:
// Wait for the sif bit in the msc alternate status register to go hi indicating
// that the getint command can be issued.
//
// Arguments:
// ticks - a uint8 representing the timeout period in milliseconds.
//
// Return:
// A t_result indicating:
// k_success - the bit was set, and this routine has cleared it.
// k_usbrst - usb reset signalling was detected while waiting.
// k_aborted - traffic occurred on the control pipe while waiting (probably a mass storage reset).
// k_timeout - timeout limit exceeded.
//
// Notes:
// This is a FUNCTION, not a DFA.
// Clears the sif bit after seeing it get set (to rearm for the next one)
// by writing the msc staus register (causing alternate status register to clear also.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
t_result ms_wait_msc_stat_sif_with_timeout(uint8 ticks) reentrant;
t_result ms_wait_msc_stat_sif_with_timeout(uint8 ticks) reentrant
{
//uint8 status;
//t_sync sync;
trace1(0, ms, 0, "ms_wait_msc_stat_sif_with_timeout(ticks:%d)", ticks);
//_stack_check();
thread_set_timer(ticks+1);
do
{
// two back to back reads of the alt_stat register appears to cause failure.
// apparently there is some latency issue causing intermittant failure...
// note well that i have not yet invested the time to determine if this
// is really cause by a synchronization issue or not. i merely opted
// for the 'bit ricochet' gambit and inserted a delay between every read of the
// ms_alt_status register. emperical evidence suggests that this fixs the problem...
// but i am not willing to assert that as a proof...
// the actual cause of death could not be determined from the forensic evidence.
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
// clear the interrupt generator in the sony block
status = _ms_register_rd(ms_alt_stat);
//status = _mcu_register_rd(x_msc_stat);
trace1(0, ms, 0, "status:0x%02X", status);
sync = thread_got_sync(kbm_sync_usbrst |kbm_sync_abort |kbm_sync_timer);
_thread_clr_sync(sync);
if (sync & kbm_sync_abort)
{
trace0(0, err, 110, "ms_wait_msc_stat_sif_with_timeout() - error: kbm_sync_abort");
return k_aborted;
}
if (sync & kbm_sync_usbrst)
{
trace0(0, err, 110, "ms_wait_msc_stat_sif_with_timeout() - error: kbm_sync_usbrst");
return k_usbreset;
}
if (sync & kbm_sync_timer)
{
trace0(0, err, 110, "ms_wait_msc_stat_sif_with_timeout() - error: kbm_sync_timer");
return k_timeout;
}
} while ((status & kbm_msc_stat_sif) != kbm_msc_stat_sif);
_mcu_register_wr(x_msc_stat, kbm_msc_stat_sif);
return k_success;
}
//+-----------------------------------------------------------------------------
// Name:
// ms_wait_fifo_with_timeout
//
// Declaration:
// t_result ms_wait_fifo_with_timeout(uint8 msk, uint8 val, uint8 ticks);
//
// Purpose:
// Wait for the a bit patern in the msc fifo status register to go hi indicating
// that the fifo has emptied, filled, etc. (Waiting for status & mask == value.)
//
// Arguments:
// msk - a uint8 bitmask to be logically and-ed with the msc fifo status register.
// val - a uint8 indicating the desired bit pattern.
// ticks - a uint8 representing the timeout period in milliseconds.
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -