📄 sd.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.
____________________________________________________________________________
____________________________________________________________________________
sd.c - secure digital mass storage class implementation file
____________________________________________________________________________
comments tbd
____________________________________________________________________________
Revision History
Date Who Comment
________ ___ _____________________________________________________________
11/##/01 cds initial version - stubs for a few overrides.
04/28/02 tbh xdata is not initialized to zero on power up so set fmc_options to
zero at start of every transfer.
05/06/02 ds It has been noted that the power-cycling of the card is not sufficient to reset the card.
So,we roll back the change and issue the reset command along with power-cycle.
05/06/02 ds If the media is write-protected we should pass the Verify command, to ensure proper operation
in Win2k
05/09/02 ds Enabled "Emergency Exit" with setjmp when waiting for tx and rx interrupts during FS xfers
05/28/02 ds In an attempt to speed up SD, I have made the code to poll for the tx and rx bits instead of
taking an interrupt. Note that the changes are reflected in the irq_timeout fn. Also, implemented
pre-erase which speeds-up 'certain SD cards'.
06/17/02 ds The pre-erase is applicable only to SD and not MMC cards.
06/18/02 DS More error detection code added to the Read/Write parts. On a media removal made sure we are
reporting the right sense code
06/18/02 ds Added comments to explain the timeout value. Also added a margin to the timeout. This reflects
the current 1.1 xfer speed of 200 KBPS
06/19/02 ds Fixed win2k 1.1 surprise removal bug. _sd_data_loaded is reinitialized on a surprise removal
06/19/02 ds Changed the fmc_set_callback to use fmc_dflt_callback instead of NULL, BOT optimization.
06/20/02 ds Set the minimum timeout to 50 ms in g_fmc_timeout, to care of the device overhead
06/20/02 ds Since the Upper layer sets the sense code for no-media, it has been removed from SD layer.
06/25/02 ds Now that we receive a sync_abort on sd_blk_ovrrun error and crc_error, they are handled accordingly
in the SD layer.
06/25/02 ds Based on measurements set the "card programming " timeout to 1sec
06/27/02 ds USB97c210 exibited the latency issue ( a la 201). This appeared as a format issue in Mac OS 10.1.5
Thus added NOPs to bur some time after we set the bits in ep2_ctl register.
07/01/02 ds In sync with the optimization of reads and writes, the read and write dfas are now functions.
So, they shall use __thread_return_dfa a new macro which simply returns to the caller.
Also, took out the check for wr_protection on writes. This should be done in the generic lun layer.
07/11/02 ds Changed the device ID name to be consistent with recent change (by Trenton), to the drive names.
07/16/02 tbh added k_pfm_led code to de/activate led on card discovery/absence so led
operates correctly with old-n-busted OSs that don't send periodic TURs.
07/30/02 ds On a high speed read we now wait for an innak before issuing the read command. This is
to take care of slow hosts ( some wait for about 2ms after the read command to send the first IN token).
Due to lack of flow control in the SDC hardware, the sd_blk_ovrrun error occurs, forcing us to send
a read_error and fail the transfer. It has been noted that the Wincomp software does not retry a read.
This causes it to fail. This does not happen in Full speed as we take a lot of time to hand-fill the buffers.
09/11/02 ds The firing of the timer1 interrupt in the middle of 2.0 data xfer (FMDU), causes data loss and
makes it appear to the host like there is data corruption, even though the file itself is not corrupted.
So, turned off the timer for now, if we know it is an SD 2.0 read. So, the light will not blink to the desired interval on SD.
09/12/02 ds To be safe turn of timer1 even on 2.0 writes.
09/12/02 ds Manage the state of the gpio0 led, during the xfer.
09/12/02 tbh replaced strncpy() with memcpy() to save data space.
09/12/02 tbh/ds timer1 disabled during sd transfers to avoid data corruption issue. bug report #343
added comments (including this one)
09/17/02 tbh fixed improperly coded accesses to x_fmc_clk_ctl.
09/18/02 tbh bug report 343, sd data corruption. initial workaround was to
disable timer1 interrupts during sd transfers. later examination
revealed that issuing the read to the sd card *before* enabling
the block transfer is problematic due to a window of vulnerability
during which the following can occur:
if the transfer is off for too long bu the sd is reading data then
the sd card will dump its data into the bit bucket. once the
block transfer is enabled the sd card provides the desired quantity
of data, but starting from the incorrect offset. thus the data
appears corrupt. today's modification was to postpone issuing
the read command until after the block transfer is enabled.
09/19/02 tbh typo - disable was diable
10/02/02 ds Set the timeout value for data transfers to 10 seconds, following the other luns.
This value is safer than then the empirical value we had before.
10/17/02 cds updated lun_data macros to use the new vtbl and lun_data formats.
10/24/02 ds Implemented Retry of 2.0 reads, when an sd_blk_ovrrun error occurs. The new address is
computed and a multiple-block-read is issued.
============================================================================*/
#define __sd_dot_c__
#include "project.h"
#include "dev.h"
// provide vtable definition '_vtbl_cf'
code _vtbl_defn(sd);
#define sd_1point1_included
//#define Debug_On //A local directive to turn on certain debug features
//#define sd_fast_1point1
#define FS_pktsz 64
uint8 xdata _sd_card_active = k_true; //This is a flag to know if the card is not responding
uint8 xdata _sd_data_loaded = k_false; //Tells me if the buffers are already loaded
//------------------------------------------------------------------------------
// sd/mmc controller (sdc) interface registers
unsigned char volatile xdata sdc_data at_sd(F6); // rw SDC Data Register
unsigned char volatile xdata sdc_mode_ctl at_sd(F8); // rw SDC Model Control Register
unsigned char volatile xdata sdc_ctl at_sd(F9); // rw SDC Control Register
unsigned char volatile xdata sdc_cmd_rsp_buf[17] _at_ 0x3640;
//RCA bytes
uint8 xdata g_sdc_rca_h = 0x00;
uint8 xdata g_sdc_rca_l = 0x00;
uint8 xdata _sd_state = 0x00; //Tells us the current _sd_state of the card
uint8 xdata _sd_data_xfer_cmd; //Instead of passing a parameter this tells what cmd to issue
uint8 xdata _sd_write_protected = k_false; //The media could be Write Protected both in Soft and Hard way
jmp_buf xdata _sd_context; // This the context to which timeout fns will jump to on error
xdata t_udw32 xdata _sd_start_addr_this_xfer; //The device takes byte address instead of block address. This variable stores that.
//+-----------------------------------------------------------------------------
// Name:
// TBD
//
// Declaration:
// TBD
//
// Purpose:
// TBD
//
// Arguments:
// TBD
//
// Return:
// TBD
//
// Notes:
// This is a FUNCTION, not a DFA.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
void sdc_read_rsp(uint8 length) reentrant
{
uint8 i,temp;
for(i=0;i<=length;i++)
{
temp = XBYTE[(0X3640+i)];
}
}
//+-----------------------------------------------------------------------------
// Name:
// sdc_wait_status_with_timeout
//
// Declaration:
// t_result sdc_wait_status_with_timeout(uint8 mask,uint16 ticks);
//
// Purpose:
// Poll the sdc status register to watch for specific bits being set.
//
// Arguments:
// mask - a uint8 with 1's in the bits to be compared
// ticks - a uint16 representing the timeout limit
//
// Return:
// A t_result indicating:
// k_success - the sdc status register logically anded with the mask
// k_usbreset - 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.
// Why does this not return a result? and Why does this set a global instead? This is because this fn is
// is called several levels down from the main caller, and requires a lot of code to transmit the result up
// the hierarchy. So, now we just check for the flag and return, so the highest caller may take appropriate
// action.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
void sdc_wait_status_with_timeout(uint8 mask, uint16 ticks) reentrant
{
uint8 status;
t_sync sync = 0;
t_sync sync1 = 0;
_stack_check();
//_stack_dump();
//TRACE2(295, sd, 1, "sdc_wait_status_with_timeout(mask:%02X ticks:%d)", mask, ticks);
// do this to get kbm_sync_abort delivered of there is traffic on the control pipe
_isr_bind_dma_owner(g_tid, kbm_sync_none);
// wait until the device is no longer busy
thread_set_timer(ticks);
_mcu_begin_critical_section();
sync = _thread_got_sync(kbm_sync_abort |kbm_sync_usbrst |kbm_sync_timer);
_mcu_end_critical_section();
status = x_sdc_stat;
//TRACE1(296, sd, 1, "The value of status %02x ",status);
while((status & mask) != mask)
{
_mcu_begin_critical_section();
sync = _thread_got_sync(kbm_sync_abort |kbm_sync_usbrst |kbm_sync_timer);
_mcu_end_critical_section();
_stack_check();
if(sync & kbm_sync_usbrst)
{
trace0(0, sd, 1, "sdc_wait_status_with_timeout() - error: kbm_sync_usbrst");
break;
}
if(sync & kbm_sync_abort)
{
trace0(0, sd, 1, "sdc_wait_status_with_timeout() - error: kbm_sync_abort");
break;
}
if(sync & kbm_sync_timer)
{
trace0(0, sd, 1, "sdc_wait_status_with_timeout() - error: hung busy");
//when a command fails init stage it could be because of a mmc card
_sd_card_active = k_false;
break;
}
status = x_sdc_stat;
// trace1(0, sd, 1, "The value of status %02x ",status);
}
if(sync) //did we get out on a failure?
{
//Reset the media here
trace0(0, sd, 1, "Resetting the SDC Block");
sdc_ctl = 0x20;
thread_set_timer(10);
while(!(sync1 & kbm_sync_timer))
{
_mcu_begin_critical_section();
sync1 = _thread_got_sync(kbm_sync_timer);
_mcu_end_critical_section();
}
_thread_clr_sync(kbm_sync_timer);
}
_thread_clr_sync(sync); //clear the synchronizers
if(sync & (kbm_sync_usbrst |kbm_sync_abort))
longjmp(_sd_context, 1); //Go to the caller dfa and return failed
//_stack_dump();
//TRACE1(301, sd, 1, "The value of status %02x ",status);
_stack_check();
//_stack_dump();
return;
}
//+-----------------------------------------------------------------------------
// Name:
// sdc_wait_irq_with_timeout
//
// Declaration:
// t_result sdc_wait_irq_with_timeout(uint16 ticks);
//
// Purpose:
// Poll for any synchronizer .
//
// Arguments:
// ticks - a uint16 representing the timeout limit
//
// Return:
// A t_result indicating:
// k_success - the sync was spotted.
// k_usbreset - 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.
//
// Since:
// fmc-1.0
//------------------------------------------------------------------------------
#ifndef sd_fast_1point1
t_result sdc_wait_irq_with_timeout(uint8 irq_name, uint16 ticks) reentrant
{
t_sync sync;
//TRACE2(302, sd, 1, "sd_wait_irq_with_timeout(ticks:%d) for %02x", ticks, irq_name);
// do this to get kbm_sync_abort delivered of there is traffic on the control pipe
_isr_bind_dma_owner(g_tid, kbm_sync_none);
thread_set_timer(ticks);
sync = kbm_sync_none;
//while(!(sync & irq_name))
while(!(_mcu_register_rd(x_isr0) & irq_name))
{
sync = thread_got_sync(kbm_sync_abort |kbm_sync_usbrst |kbm_sync_timer);
_thread_clr_sync(sync);
if(sync & kbm_sync_usbrst)
{
trace0(0, sd, 1, "sd_wait_irq_with_timeout() - error: kbm_sync_usbrst");
}
if(sync & kbm_sync_abort)
{
trace0(0, sd, 1, "sd_wait_irq_with_timeout() - error: kbm_sync_abort");
}
if(sync & kbm_sync_timer)
{
trace0(0, sd, 1, "sd_wait_irq_with_timeout() - error: timeout awaiting irq");
return k_timeout;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -