📄 mal_2k.c
字号:
CP X, #CACHE0_FREE*2-3
JRNE shift_free0
}
temp = SMC_Lookup_pFree0[0];
}
#else
pBad = SMC_Lookup_pTable + 1023; // the last item
while (*pBad & 0x01)
pBad--;
temp = *pBad;
*pBad = SMC_Paddr | 0x0001;
#endif // USE_CACHE0
// ASSUME THIS IS A GOOD ONE
if (SMC_Cluster_Size != 64)
SMC_Paddr = temp & 0x7FFF; // re-allocate a good cluster
else
SMC_Paddr = temp & 0xffef; //different mapping bit for 2K
}
#ifndef THUMB_DRIVE
unsigned char SMC_Read_Capacity(void)
{
unsigned char CardID;
CardID = DTC_SMC_ReadID();
SMC_4MB = 0;
MAL_Capacity = 0;
SMC_Lookup_nCache0 = 0; // No zone0 cache with card < 64MB
SMC_Cluster_Size = 16;
SMC_Addr_Bytes = 3;
if (CardID == 0xE3 || CardID == 0xE5) { // 4MB
SMC_4MB = 1;
MAL_Capacity = 8000;
}
else if (CardID == 0xE6) // 8MB
MAL_Capacity = 16000;
else {
SMC_Cluster_Size <<= 1;
if (CardID == 0x73) { // 16MB
MAL_Capacity = 32000;
}
else if (CardID == 0x75) { // 32MB
MAL_Capacity = 64000;
}
else if (CardID == 0x76) { // 64MB
MAL_Capacity = 128000;
SMC_Addr_Bytes = 4;
SMC_Lookup_nCache0 = 4;
}
else if (CardID == 0x79) { // 128MB
MAL_Capacity = 256000;
SMC_Addr_Bytes = 4;
SMC_Lookup_nCache0 = 5;
}
else if (CardID == 0xF1){ // 128MB-2K
MAL_Capacity = 256000;
SMC_Addr_Bytes = 4;
SMC_Cluster_Size <<= 1;
SMC_Lookup_nCache0 = 5;
}
else if (CardID == 0xDA){ // 256MB-2K
MAL_Capacity = 512000;
SMC_Addr_Bytes = 5;
SMC_Cluster_Size <<= 1;
SMC_Lookup_nCache0 = 5;
}
else
return MAL_CARD_UNKNOWN;
}
DTC_SMC_Address_bytes = SMC_Addr_Bytes;
return MAL_GOOD;
}
#endif
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#ifndef THUMB_DRIVE
static void SMC_INC_Logical_Addr(void)
{
SMC_Laddr++;
/****for 2K Flash*****/
SubBlock = 0;
Buffer_Param[0x01] = 4;
Buffer_Param[0x25]= 0;
if (SMC_Laddr >= 1000) {
SMC_Zone++;
SMC_Laddr -= 1000;
}
}
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
void SMC_Get_Logical_Addr(void)
{
unsigned short EndBlock;
SMC_Zone = 0;
if (SMC_Cluster_Size == 32) {
asm {
LD A, MAL_Block_Address:3
LD X, MAL_Block_Address:2
LD Y, MAL_Block_Address:1
SRL Y
RRC X
RRC A ; 1st shift
SRL Y
RRC X
RRC A ; 2nd shift
SRL Y
RRC X
RRC A ; 3rd shift
SRL Y
RRC X
RRC A ; 4th shift
SRL Y
RRC X
RRC A ; 5th shift
LD SMC_Laddr:1, A
LD SMC_Laddr, X
} // The C line below costs too much
// SMC_Laddr = (unsigned int)(MAL_Block_Address >> 5);
Adjust_Laddr();
SMC_Ppage = (unsigned char)MAL_Block_Address & 0x001F;
}
else if (SMC_Cluster_Size == 64){ //for 256 MB
asm {
LD A, MAL_Block_Address:2
LD X, MAL_Block_Address:1
LD SMC_Laddr:1, A
LD SMC_Laddr, X
} // The C line below costs too much
// SMC_Laddr = (unsigned int)(MAL_Block_Address >> 8);
Adjust_Laddr();
SMC_Ppage = (unsigned char)MAL_Block_Address & 0x00FF; // No. of small pages
SubBlock = (unsigned char) (SMC_Ppage % 4); // Col. offset in a big page
SMC_Ppage = SMC_Ppage / 4;//No. of 2K page
}
else {
asm {
LD A, MAL_Block_Address:3
LD X, MAL_Block_Address:2
LD Y, MAL_Block_Address:1
SRL Y
RRC X
RRC A ; 1st shift
SRL Y
RRC X
RRC A ; 2nd shift
SRL Y
RRC X
RRC A ; 3rd shift
SRL Y
RRC X
RRC A ; 4th shift
LD SMC_Laddr:1, A
LD SMC_Laddr, X
} // The C line below costs too much
// SMC_Laddr = (unsigned int)(MAL_Block_Address >> 4);
SMC_Ppage = (unsigned char)MAL_Block_Address & 0x000F;
}
if (SMC_Lookup_nCache0 == 0) // Card < 64MB
return; // No cache management needed
if (SMC_Cluster_Size != 64){
asm {
LD A, MAL_Block_Numbers:1
LD X, MAL_Block_Numbers
ADD A, SMC_Ppage
JRNC sub_1
INC X
sub_1: SUB A, #1
JRNC shift5
DEC X
shift5:
SRL X
RRC A ; 1st shift
SRL X
RRC A ; 2nd shift
SRL X
RRC A ; 3rd shift
SRL X
RRC A ; 4th shift
SRL X
RRC A ; 5th shift
ADD A, SMC_Laddr:1
LD EndBlock:1, A
LD A, X
ADC A, SMC_Laddr
LD EndBlock, A
} // The following C line costs too much
}
else {
asm {
LD A, MAL_Block_Numbers:1
LD X, MAL_Block_Numbers
ADD A, SMC_Ppage
JRNC sub_2
INC X
sub_2: SUB A, #1
JRNC shift8
DEC X
shift8: LD A, X
ADD A, SMC_Laddr:1
LD EndBlock:1, A
CLR A
ADC A, SMC_Laddr
LD EndBlock, A
} // The following C line costs too much
}
// EndBlock = SMC_Laddr + ((SMC_Ppage + MAL_Block_Numbers - 1) >> 5);
if (EndBlock >= 1000) { // The access will cross the zone boundary
unsigned char ZoneNext;
ZoneNext = SMC_Zone + 1;
if (SMC_Zone == SMC_Lookup_Zone0) { // current zone hits table0
if (ZoneNext == SMC_Lookup_Zone1)
return;
SMC_Lookup_Update1(ZoneNext); // update lookup tabke 1 for ZoneNext
}
else if (SMC_Zone == SMC_Lookup_Zone1) {// current zone hits table1
if (ZoneNext == SMC_Lookup_Zone0)
return;
SMC_Lookup_Update0(ZoneNext); // update lookup table 0 for ZoneNext
}
else if (ZoneNext == SMC_Lookup_Zone0) // next zone hits table0
SMC_Lookup_Update1(SMC_Zone); // update lookup table 1 for SMC_Zone
else if (ZoneNext == SMC_Lookup_Zone1) // next zone hits table1
SMC_Lookup_Update0(SMC_Zone); // updata lookup table 0 for SMC_Zone
else {
SMC_Lookup_Update0(SMC_Zone); // updata lookup table 0 for SMC_Zone
SMC_Lookup_Update1(ZoneNext); // updata lookup table 1 for ZoneNext
}
}
else { // The access will not cross the zone boundary
if (SMC_Zone == SMC_Lookup_Zone0 || SMC_Zone == SMC_Lookup_Zone1)
return;
#if USE_CACHE0
if (SMC_Zone == 0 && SMC_Laddr < SMC_Lookup_nCache0) { // Hit on cache of zone0
if (EndBlock < SMC_Lookup_nCache0)
return;
}
#endif
// Going to make the lookup table for the new zone
if (SMC_Lookup_Count0 < SMC_Lookup_Count1)
SMC_Lookup_Update0(SMC_Zone);
else
SMC_Lookup_Update1(SMC_Zone);
}
}
#endif // not THUMB_DRIVE
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
Launch the DTC again for reading
-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
void SMC_Read_Interrupt()
{
_MAL_INC_Block_Param(SMC_Npage);
// MAL_Block_Numbers -= SMC_Npage;
// MAL_Block_Address += SMC_Npage;
if (DTC_Error) {
_MAL_DEC_Block_Param(malNpage);
// MAL_Block_Numbers += malNpage;
// MAL_Block_Address -= malNpage;
MAL_Error = MAL_RD_ERR;
MAL_Finish(FALSE);
DTC_Current_Func = 0;
return;
}
if (MAL_Block_Numbers == 0) {
MAL_Error = MAL_GOOD;
MAL_Finish(TRUE);
DTC_Current_Func = 0;
return;
}
// If the previous DTC was reading odd number of pages
// Clear the buffer manager flags and start from buffer0
if (SMC_Npage & 1) {
while (BUFSR & 0x06); // Wait both buffer are empty
BUFSR = 0x01; // Clear Buffer status
BUFSR = 0;
}
// Launch the next burst reading
#ifdef THUMB_DRIVE
NAND_INC_Logical_Addr();
#else
SMC_INC_Logical_Addr();
#endif
if (SMC_Cluster_Size != 64){
if (SMC_Cluster_Size > MAL_Block_Numbers)
malNpage = (unsigned char)MAL_Block_Numbers;
else
malNpage = SMC_Cluster_Size;
}
else // SMC_Cluster_Size = 64 // for 2k Flash
if (MAL_Block_Numbers < 0x100) // No. of small pages = 4 * big pages
malNpage = (unsigned char)MAL_Block_Numbers;
else
malNpage = 0x100;
_MAL_BufMgr_Upload(); // Switch to UPLOAD mode
SMC_Npage = malNpage;
DTC_Current_Func = DTC_SMC_READ;
if (SMC_Log2Phy() == 0) {
// WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING!
// When the specified location does not exist
// Have to return all 0xFF in the data block.
DTC_Read_FF();
return;
}
if (SMC_Paddr & 0x0F) { // This is a bad cluster
MAL_Error = MAL_BAD_MEDIUM; // Too many bad clusters
MAL_Finish(FALSE);
DTC_Current_Func = 0;
return;
}
// malPaddr = Map_DTC_Addr(SMC_Zone, SMC_Paddr, SMC_Npage);
// Map_To_DTC_Addr(malPaddr, SMC_Zone, SMC_Paddr, 0);
Col = 0;
SMC_Paddr_To_DTC_Addr();
DTC_SMC_Read_USB( /* malPaddr, malNpage */ );
}
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
MAL_SMC_Read
-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
unsigned char SMC_Read(void)
{
#ifdef THUMB_DRIVE
Get_Chip_Number(); // Map the MAL address within a chip
// Get the logical cluster address
NAND_Get_Logical_Addr(); // SMC_Zone:SMC_Laddr:SMC_Ppage = MAL_Block_Address
NAND_Select(NAND_Chip); // Enable the chip select of the chip
#else
DTC_SMC_Address_bytes = SMC_Addr_Bytes;
// Get the logical cluster address
SMC_Get_Logical_Addr(); // SMC_Zone:SMC_Laddr:SMC_Ppage = MAL_Block_Address
#endif
if (SMC_Cluster_Size != 64){
Buffer_Param[0x00] = 0x01; //flag to recognize 2K or 512 flash
Buffer_Param[0x25] = 0x00; //1st adr byte to be sent
}
else {
asm {
LD A, SubBlock
SWAP A
LD Buffer_Param[0x25], A
}
// if (SubBlock == 0) //1st col byte adr for 2K page
// Buffer_Param[0x25] = 0x00;
// else if (SubBlock == 1)
// Buffer_Param[0x25] = 0x10;
// else if (SubBlock == 2)
// Buffer_Param[0x25] = 0x20;
// else
// Buffer_Param[0x25] = 0x30;
Buffer_Param[0x00] = 0x00; //flag to recognize 2K or 512 flash
Buffer_Param[0x01] = (4 - SubBlock);//Number of partial pages to be read
}
MAL_Block_Finish = 0;
if (SMC_Cluster_Size != 64)
malNpage = SMC_Cluster_Size - SMC_Ppage;
else {
asm {
CLR malNpage
LD A, SMC_Ppage
SLL A
SLL A
ADD A, SubBlock
NEG A
LD malNpage:1, A
JRNE got_Npage
INC malNpage
got_Npage:
}
// malNpage = SMC_Ppage * 4 + SubBlock;
// malNpage = 0x100 - malNpage;
}
if (malNpage > MAL_Block_Numbers)
malNpage = (unsigned char)MAL_Block_Numbers;//No. of small pages to be read
SMC_Npage = malNpage;
DTC_Current_Func = DTC_SMC_READ;
_MAL_BufMgr_Upload(); // Switch to UPLOAD mode
// Get the physical cluster address
if (SMC_Log2Phy() == 0) {
// When the specified location does not exist
// Have to return all 0xFF in the data block.
DTC_Read_FF();
return MAL_GOOD;
}
if (SMC_Paddr & 0x0F) { // This is a bad cluster
MAL_Error = MAL_BAD_MEDIUM; // Too many bad clusters
MAL_Finish(FALSE);
DTC_Current_Func = 0;
return MAL_Error;
}
// Launch the DTC to copy the first data cluster
// malPaddr = Map_DTC_Addr(SMC_Zone, SMC_Paddr, SMC_Ppage);
Col = SubBlock * 2; //To get 2nd col. byte
Map_To_DTC_Addr256(malPaddr, SMC_Zone, SMC_Paddr, SMC_Ppage,Col);
// Map_To_DTC_Addr(malPaddr, SMC_Zone, SMC_Paddr, SMC_Ppage);
DTC_SMC_Read_USB( /* malPaddr, malNpage */ );
return MAL_GOOD;
}
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
MAL_Write(); MAL_Write(); MAL_Write(); MAL_Write();
-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
Launch the DTC again for writing
-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
unsigned char SMC_Write(void);
unsigned short MAL_Block_Numbers_t;
#define PAGE2K_BAD
void SMC_Write_Interrupt()
{
Label_SMC_Write_Interrupt:
// Some DTC routine is expected to finish with interrupt,
// but it returns when it finishes.
// This label is used to simulate the re-enter as interrupt.
#ifdef PAGE2K_BAD
if(SMC_Cluster_Size == 64){
if (DTC_Error) {
if((SMC_Wstate != SMC_PREMARK) && (SMC_Wstate != SMC_PRECOPY)){
malPaddr = (malPaddr & ~(0x3fff));
DTC_SMC_Mark_Bad();
SMC_Lookup_Map_Bad();
if (SMC_Wstate & SMC_OLD_CLUSTER)
SMC_Lookup_pTable[1000] = SMC_Paddr | 0x10;
else
SMC_Lookup_pTable[SMC_Laddr] = SMC_Paddr | 0x10;
MAL_Error = MAL_WR_ERR;
DTC_Error = 0;
MAL_Block_Numbers = MAL_Block_Numbers_t; //ASk for all data in case of failure
MAL_Finish(FALSE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -