📄 2k_mass.c
字号:
/****************** (c) 1999 STMicroelectronics *****************************
PROJECT : USB - ST7
VERSION : SMC_Mass.c 1.0 Beta2
CREATION DATE :
AUTHOR : CMG / ST Rousset
-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
REM:
-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
MODIFICATIONS :
******************************************************************************/
#include "Map_7265.h"
#include "MAL_Map.h"
#include "MAL_2K.h"
#include "DTC_Func.h"
#include "2K_DTC.h"
#include "2K_Mass.h"
#include "MAL.h"
#include "Mconfig.h"
#pragma DATA_SEG SHORT MAL_RAM0
extern unsigned char DTC_Code_Number;
#ifdef debug
static unsigned char counter; //for debug
#endif
//#define Bytes2K_PAGE
#pragma DATA_SEG DEFAULT_RAM
#ifdef debug
static unsigned int Error_Laddr[40]; //for debug of corruption
static unsigned char Error_Page[40];
static unsigned char Error_offset[40];
#endif
#pragma CODE_SEG SMC_CODE
#define ID_CYCLES 5
//#define Copy_malPaddr() { *((unsigned long*)&Buffer_Param[SMC_RespFrame_AddrBeg]) = malPaddr; }
void Copy_malPaddr()
{
*((unsigned long*)&Buffer_Param[SMC_RespFrame_AddrBeg]) = malPaddr;
}
/*-*-*-*-*-*-*-* Calculate the parity bit of the address -*-*-*-*-*-*-*-*-*-*/
#pragma NO_ENTRY
static unsigned int DTC_SMC_Addr_Parity(unsigned int Addr)
{
#if 0
unsigned int tAddr;
// Calculate the parity bit
tAddr = (Addr << 1) | 0x1000 | 0x01;
do {
if (Addr & 0x01)
tAddr ^= 1;
Addr >>= 1;
} while (Addr);
return tAddr;
#endif
// Calculate the parity bit
asm {
LD Y, A
SCF // OR 0x01
RLC A
RLC X
LD Addr, A // Lobyte of tAddr
LD A, X
OR A, #0x10
PUSH A // Hibyte of tAddr
RRC X // Shift back the hi-byte of Addr
}
asm {
LD A, Addr // Lobyte of tAddr
Parity_Loop:
SRL X // Hibyte of Addr
RRC Y // Lobyte of Addr
JRNC Parity_Next
XOR A, #0x01
Parity_Next:
TNZ Y
JRNE Parity_Loop
TNZ X
JRNE Parity_Loop
POP X // Hibyte of result
}
}
/*-----------------------------------------------------------------------------
ROUTINE NAME : DTC_SMC_Send_Cmd
INPUT/OUTPUT : Buffer_Param[0x20] contains the command to be sent
DESCRIPTION : Send the specified command to the SMC
-----------------------------------------------------------------------------*/
void DTC_SMC_Send_Cmd(void)
{
if (DTC_Code_Number != CODE_DTC_PLAY) {
// DTC_Load_Code(SMC_DTC_Play);
DTC_Load_Code(SMC_DTC_Play256);//for 256 MB
DTC_Code_Number = CODE_DTC_PLAY;
}
No_DTC_Int();
DTC_Process(SMC_DTC_Play_Send_Cmd);
DTC_Wait_Stop();
}
/*-----------------------------------------------------------------------------
ROUTINE NAME : SMC_USB
INPUT/OUTPUT :
DESCRIPTION : None
-----------------------------------------------------------------------------*/
void DTC_SMC_Init()
{
if (DTC_Code_Number != CODE_DTC_CODE0) {
DTC_Load_Code(SMC_DTC_Code0);
DTC_Code_Number = CODE_DTC_CODE0;
}
No_DTC_Int();
DTC_Process(SMC_DTC_Code_Init_SMC_Mode);
DTC_Wait_Stop();
Buffer_Param[0x20] = Reset;
DTC_SMC_Send_Cmd();
}
/*-----------------------------------------------------------------------------
ROUTINE NAME : SMC_Send_Addr
INPUT/OUTPUT : Buffer_Param[0x22-0x25] contains the address to be sent
Buffer_Param[0x26] a byte indicates number of address bytes
DESCRIPTION : Send the specified address to the SMC
-----------------------------------------------------------------------------*/
void SMC_Send_Addr(void)
{
No_DTC_Int();
DTC_Process(SMC_DTC_Play_Send_Addr);
DTC_Wait_Stop();
}
/*-----------------------------------------------------------------------------
ROUTINE NAME : SMC_Read_Status
INPUT/OUTPUT :
DESCRIPTION : Read the status byte and return it
-----------------------------------------------------------------------------*/
unsigned char SMC_Read_Status(void)
{
Buffer_Param[0x20] = Read_Status;
DTC_SMC_Send_Cmd();
DTC_Process(SMC_DTC_Play_Read_Status);
DTC_Wait_Stop();
return Buffer_Param[0x3E];
}
/*-----------------------------------------------------------------------------
ROUTINE NAME : Read_SMC_ID
INPUT/OUTPUT : None
DESCRIPTION : None
-----------------------------------------------------------------------------*/
unsigned char DTC_SMC_ReadID(void)
{
Buffer_Param[0x3C] = ID_CYCLES;
Buffer_Param[0x20] = ID_Read;
DTC_SMC_Send_Cmd();
No_DTC_Int();
DTC_Process(SMC_DTC_Play_Read_ID);
DTC_Wait_Stop();
return Buffer_Param[0x31];
}
/*--------------------------------------------------------------------------------------------------------------------
Routine : DTC_SMC_Map_Zone
Input : malPaddr = the first page of the zone
malNpage = pages of one cluster
malRaddr = number of clusters in the zone
Output : void
Description
---------------------------------------------------------------------------------------------------------------------*/
#define CONVERT_ASM 1
//#define CONVERT_ASM 0
#pragma NO_ENTRY
void DTC_SMC_Map_Zone(unsigned short *SMC_Lookup_Table)
{
unsigned short *pScan, *pLookup, *pBad, item;
#if CONVERT_ASM
unsigned char loop;
#else
unsigned short value;
#endif
/******For 256MB**********/
asm { // Since this function is almost assembly code, the compiler optimized this code
// This is the entry code, I have to make it myself
LD SMC_Lookup_Table:1, A
LD SMC_Lookup_Table, X
}
if (DTC_Code_Number != CODE_MAP_ZONE) {
// DTC_Load_Code(SMC_DTC_Map_Zone);
DTC_Load_Code(SMC_DTC_Map_Zone256); //For 256MB
DTC_Code_Number = CODE_MAP_ZONE;
}
Buffer_Param[0x3F] = malNpage;
Buffer_Param[0x25]= 0x00;//First Add byte
Copy_malPaddr();
No_DTC_Int();
DTC_Process(0); // Collect mapping information for the 1st half of the zone
#if CONVERT_ASM
asm {
CLR X
LD Y, #8
mark_as_free:
LD A, #0x40
LD ([SMC_Lookup_Table.W],X), A
INC X
CLR A
LD ([SMC_Lookup_Table.W],X), A
INC X
JRNE mark_as_free
INC SMC_Lookup_Table
DEC Y
JRNE mark_as_free
LD A, SMC_Lookup_Table
SUB A, #8
LD SMC_Lookup_Table, A
}
#else
for (item = 1023; item >= 0; item--)
SMC_Lookup_Table[item] = 0x4000; // mark all as free
#endif
DTC_Wait_Stop();
#if CONVERT_ASM
asm {
CLR item:1
CLR item
LD A, SMC_Lookup_Table:1
LD pLookup:1, A
ADD A, #0xFE // point to end of the word array
LD pBad:1, A
LD A, SMC_Lookup_Table
LD pLookup, A
ADC A, #0x07 // point to end of the word array
LD pBad, A
LD A, #Buffer_0
LD pScan:1, A
LD A, #HIGH(Buffer_0)
LD pScan, A
CALLR convert_table
}
#else
item = 0;
pBad = SMC_Lookup_Table + 1023;
pScan = (unsigned short *)Buffer_0;
pLookup = SMC_Lookup_Table;
for (item = 0; item < 512; item++) {
value = *pScan >> 1;
if (value != 0x7FFF) {
*pLookup &= ~0x4000; // mark as not free
if (value == 0x0800)
*pBad-- |= item | 0xA000; // mark as bad
else {
// debug if (SMC_Lookup_Table[value] != 0x4000)
// debug asm nop;
SMC_Lookup_Table[value] |= item | 0x8000; // mapping
// item_good++;
}
}
// else
// item_free++;
pScan++;
pLookup++;
}
#endif
// Second half of the table
if ((unsigned short)malRaddr == 512)
goto scan_free_clusters;
DTC_Process(0);
DTC_Wait_Stop(); // Collect mapping informat for the 2nd half of the zone
#if CONVERT_ASM
asm {
LD A, #Buffer_0
LD pScan:1, A
LD A, #HIGH(Buffer_0)
LD pScan, A
CALLR convert_table
JRA map_free_cluster
convert_table:
CLR X
LD A, #4
LD loop, A
convert_table0:
LD A, ([pScan.w],X) // load high byte of the Scan
LD Y, A // save it in Y
INC X
LD A, ([pScan.w],X) // load low byte of the Scan
CP Y, #0xFF
JRNE check_bad
CP A, #0xFE
JREQ next_cluster // this is a free cluster
check_bad:
CP Y, #0x10
JRNE map_cluster
TNZ A
JREQ bad_cluster
map_cluster:
PUSH X
PUSH A // low byte of value
LD X, SMC_Lookup_Table // save it
LD A, Y
ADD A, SMC_Lookup_Table
LD SMC_Lookup_Table, A
POP Y
LD A, ([SMC_Lookup_Table.W],Y) // SMC_Lookup_Table[value] |= item | 0x8000
OR A, item
OR A, #0x80
LD ([SMC_Lookup_Table.W],Y), A // high byte of above result
INC Y
LD A, item:1
LD ([SMC_Lookup_Table.W],Y), A // low byte of above result
LD SMC_Lookup_Table, X // restore the variable of SMC_Lookup_Table
POP X
JRA not_free_cluster
bad_cluster:
LD Y, #1
LD A, item:1
LD ([pBad.W],Y), A // low byte
LD A, [pBad.W]
OR A, item
OR A, #0xA0
LD [pBad.W], A // high byte
LD A, pBad:1
SUB A, #0x02
LD pBad:1, A
LD A, pBad
SBC A, #0
LD pBad, A
not_free_cluster:
DEC X
LD A, ([pLookup.W],X)
AND A, #0xBF
LD ([pLookup.W],X), A
INC X
next_cluster:
INC item:1
JRNE next_cluster0
INC item
next_cluster0:
INC X
JRNE convert_table0
INC pScan
INC pLookup
DEC loop
JRNE convert_table0
convert_end:
RET
map_free_cluster:
NOP
}
#else
pScan = (unsigned short *)Buffer_0;
for (item = 512; item < 1024; item++) {
value = *pScan >> 1;
if (value != 0x7FFF) {
*pLookup &= ~0x4000; // mark as not free
if (value == 0x0800)
*pBad-- |= item | 0xA000; // mark as bad
else {
// debug if (SMC_Lookup_Table[value] != 0x4000)
// debug asm nop;
SMC_Lookup_Table[value] |= item | 0x8000; // mapping
// item_good++;
}
}
// else
// item_free++;
pScan++;
pLookup++;
}
#endif
scan_free_clusters:
#if CONVERT_ASM
asm {
LD A, SMC_Lookup_Table:1
LD pScan:1, A
LD pLookup:1, A
LD pBad:1, A
LD A, SMC_Lookup_Table
LD pScan, A
LD pLookup, A
ADD A, #0x08 // point to end of the word array
LD pBad, A
}
// loop = ((unsigned short)malRaddr == 512) ? 4 : 8;
asm {
LD X, #8
LD A, malRaddr
CP A, #2
JRNE loop_8
LD A, malRaddr:1
JRNE loop_8
// For 4MB card only
LD A, pLookup
ADD A, #4
LD pBad, A
LD X, #4
loop_8:
LD loop, X
}
asm {
CLR X
CLR Y
scan_free_cluster:
LD A, ([pScan.W], X)
BCP A, #0x80
JRNE scan_next_free0
search_free:
LD A, ([pLookup.W], Y)
BCP A, #0x40
JRNE found_free
INC Y
INC Y
JRNE search_free
INC pLookup
LD A, pLookup
CP A, pBad
JRNE search_free
RET // no more free cluster
// some logical cluster got 2 or more physical location
found_free:
AND A, #0xBF
LD ([pLookup.W], Y), A // map it, clear the free flag
LD A, pLookup
SUB A, SMC_Lookup_Table
SRL A
OR A, #0x0C // 0x0c is the mark of free cluster
OR A, ([pScan.W], X) // keep the free marking if there is one
LD ([pScan.W], X), A
LD A, Y
RRC A
INC X
LD ([pScan.W], X), A // *pScan = 0xC00 | (pLookup - SMC_Lookup_Table);
JRA scan_next_free
scan_next_free0:
INC X
scan_next_free:
INC X
JRNE scan_free_cluster
INC pScan
DEC loop
JRNE scan_free_cluster
}
#else
pScan = SMC_Lookup_Table;
pLookup = SMC_Lookup_Table;
pBad = SMC_Lookup_Table + 1024; // guard the pLookup
for (item = 0; item < (unsigned short)malRaddr; item++, pScan++) {
if (*pScan & 0x8000)
continue; // a mapped cluster
while ((*pLookup & 0x4000) == 0) {
pLookup++;
if (pLookup >= pBad)
goto Map_Zone_END;
}
*pScan = 0xC00 | (pLookup - SMC_Lookup_Table);
*pLookup &= ~0x4000;
}
Map_Zone_END: ;
#endif
/*
if (DTC_Code_Number != CODE_DTC_PLAY) {
DTC_Load_Code(SMC_DTC_Play);
DTC_Code_Number = CODE_DTC_PLAY;
}
DTC_SMC_Command = 0x01; // read spare area
for (Sectors = malRaddr; Sectors; Sectors--) {
// CopyStartAddr(malPaddr);
Copy_malPaddr();
No_DTC_Int();
DTC_Process(SMC_DTC_Read_Data_4Addr);
DTC_Wait_Stop();
if ( (Spare_Area.Block_Status_Byte == 0xFF) && (Spare_Area.Data_Status_Byte == 0xFF)
&& (Spare_Area.Block_Address_Field_1 == Spare_Area.Block_Address_Field_2)) {
if (Spare_Area.Block_Address_Field_1 == 0xFFFF)
*SMC_Lookup_Table = 0x73FF;
else {
if ((Spare_Area.Block_Address_Field_1 & 0x1000) == 0x0000)
*SMC_Lookup_Table = 0x800;
else {
#define Logical_Block ((Spare_Area.Block_Address_Field_1 >> 1) & 0x03FF)
*SMC_Lookup_Table = Logical_Block | 0x4000;
}
}
}
else
*SMC_Lookup_Table = 0x800;
SMC_Lookup_Table++;
malPaddr += (unsigned long)malNpage;
}
*/
}
/*----------------------------------------------------------------------------------------------------------------
Routine : DTC_Read_FF
Input :
Output : void
Description
-----------------------------------------------------------------------------------------------------------------*/
unsigned char DTC_Read_FF(void)
{
if (DTC_Code_Number != CODE_READ_USB) {
DTC_Load_Code(SMC_DTC_USB_Mass_Upld);
DTC_Code_Number = CODE_READ_USB;
}
Buffer_Param[0x3F] = malNpage; // Nb of Sectors processed
Enable_DTC_Int();
DTC_Process(SMC_DTC_USB_Upload_FF);
return 0x00;
}
/*---------------------------------------------------------------------------
Routine : DTC_SMC_Read_USB
Input :
Output : void
Description
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -