1 /*-------------------------------------------------------------
3 card.c -- Memory card subsystem
6 Michael Wiedenbauer (shagkur)
7 Dave Murphy (WinterMute)
9 This software is provided 'as-is', without any express or implied
10 warranty. In no event will the authors be held liable for any
11 damages arising from the use of this software.
13 Permission is granted to anyone to use this software for any
14 purpose, including commercial applications, and to alter it and
15 redistribute it freely, subject to the following restrictions:
17 1. The origin of this software must not be misrepresented; you
18 must not claim that you wrote the original software. If you use
19 this software in a product, an acknowledgment in the product
20 documentation would be appreciated but is not required.
22 2. Altered source versions must be plainly marked as such, and
23 must not be misrepresented as being the original software.
25 3. This notice may not be removed or altered from any source
28 -------------------------------------------------------------*/
38 #include "processor.h"
49 #define CARD_SYSAREA 5
50 #define CARD_SYSDIR 0x2000
51 #define CARD_SYSDIR_BACK 0x4000
52 #define CARD_SYSBAT 0x6000
53 #define CARD_SYSBAT_BACK 0x8000
55 #define _SHIFTL(v, s, w) \
56 ((u32) (((u32)(v) & ((0x01 << (w)) - 1)) << (s)))
57 #define _SHIFTR(v, s, w) \
58 ((u32)(((u32)(v) >> (s)) & ((0x01 << (w)) - 1)))
60 (((u32)v<<s)|((u32)v>>(0x20-s)))
62 #define CARD_STATUS_UNLOCKED 0x40
74 struct card_direntry
{
79 u8 filename
[CARD_FILENAMELEN
];
92 struct card_dat
{ // dir allocation table
93 struct card_direntry entries
[CARD_MAXFILES
];
96 struct card_dircntrl
{
112 typedef struct _card_block
{
132 card_file
*curr_file
;
133 struct card_dat
*curr_dir
;
134 struct card_bat
*curr_fat
;
137 lwpq_t wait_sync_queue
;
141 cardcallback card_ext_cb
;
142 cardcallback card_tx_cb
;
143 cardcallback card_exi_cb
;
144 cardcallback card_api_cb
;
145 cardcallback card_xfer_cb
;
146 cardcallback card_erase_cb
;
147 cardcallback card_unlock_cb
;
152 static u32 _cardunlockdata
[0x160] ATTRIBUTE_ALIGN(32) =
154 0x00000000,0x00000000,0x00000000,0x00000000,
155 0x00000000,0x00000000,0x00000021,0x02ff0021,
156 0x13061203,0x12041305,0x009200ff,0x0088ffff,
157 0x0089ffff,0x008affff,0x008bffff,0x8f0002bf,
158 0x008816fc,0xdcd116fd,0x000016fb,0x000102bf,
159 0x008e25ff,0x0380ff00,0x02940027,0x02bf008e,
160 0x1fdf24ff,0x02403fff,0x00980400,0x009a0010,
161 0x00990000,0x8e0002bf,0x009402bf,0x864402bf,
162 0x008816fc,0xdcd116fd,0x000316fb,0x00018f00,
163 0x02bf008e,0x0380cdd1,0x02940048,0x27ff0380,
164 0x00010295,0x005a0380,0x00020295,0x8000029f,
165 0x00480021,0x8e0002bf,0x008e25ff,0x02bf008e,
166 0x25ff02bf,0x008e25ff,0x02bf008e,0x00c5ffff,
167 0x03403fff,0x1c9f02bf,0x008e00c7,0xffff02bf,
168 0x008e00c6,0xffff02bf,0x008e00c0,0xffff02bf,
169 0x008e20ff,0x03403fff,0x1f5f02bf,0x008e21ff,
170 0x02bf008e,0x23ff1205,0x1206029f,0x80b50021,
171 0x27fc03c0,0x8000029d,0x008802df,0x27fe03c0,
172 0x8000029c,0x008e02df,0x2ece2ccf,0x00f8ffcd,
173 0x00f9ffc9,0x00faffcb,0x26c902c0,0x0004029d,
174 0x009c02df,0x00000000,0x00000000,0x00000000,
175 0x00000000,0x00000000,0x00000000,0x00000000
178 #elif defined(HW_DOL)
180 static u32 _cardunlockdata
[0x160] ATTRIBUTE_ALIGN(32) =
182 0x00000000,0x00000000,0x00000000,0x00000000,
183 0x00000000,0x00000000,0x00000021,0x02ff0021,
184 0x13061203,0x12041305,0x009200ff,0x0088ffff,
185 0x0089ffff,0x008affff,0x008bffff,0x8f0002bf,
186 0x008816fc,0xdcd116fd,0x000016fb,0x000102bf,
187 0x008e25ff,0x0380ff00,0x02940027,0x02bf008e,
188 0x1fdf24ff,0x02400fff,0x00980400,0x009a0010,
189 0x00990000,0x8e0002bf,0x009402bf,0x864402bf,
190 0x008816fc,0xdcd116fd,0x000316fb,0x00018f00,
191 0x02bf008e,0x0380cdd1,0x02940048,0x27ff0380,
192 0x00010295,0x005a0380,0x00020295,0x8000029f,
193 0x00480021,0x8e0002bf,0x008e25ff,0x02bf008e,
194 0x25ff02bf,0x008e25ff,0x02bf008e,0x00c5ffff,
195 0x03400fff,0x1c9f02bf,0x008e00c7,0xffff02bf,
196 0x008e00c6,0xffff02bf,0x008e00c0,0xffff02bf,
197 0x008e20ff,0x03400fff,0x1f5f02bf,0x008e21ff,
198 0x02bf008e,0x23ff1205,0x1206029f,0x80b50021,
199 0x27fc03c0,0x8000029d,0x008802df,0x27fe03c0,
200 0x8000029c,0x008e02df,0x2ece2ccf,0x00f8ffcd,
201 0x00f9ffc9,0x00faffcb,0x26c902c0,0x0004029d,
202 0x009c02df,0x00000000,0x00000000,0x00000000,
203 0x00000000,0x00000000,0x00000000,0x00000000
207 static u32 card_sector_size
[] =
219 static u32 card_latency
[] =
231 static u32 card_inited
= 0;
232 static u32 crand_next
= 1;
234 static u8 card_gamecode
[4] = {0xff,0xff,0xff,0xff};
235 static u8 card_company
[2] = {0xff,0xff};
236 static card_block cardmap
[2];
238 static void __card_mountcallback(s32 chn
,s32 result
);
239 static void __erase_callback(s32 chn
,s32 result
);
240 static s32
__dounlock(s32 chn
,u32
*key
);
241 static s32
__card_readsegment(s32 chn
,cardcallback callback
);
242 static s32
__card_read(s32 chn
,u32 address
,u32 block_len
,void *buffer
,cardcallback callback
);
243 static s32
__card_updatefat(s32 chn
,struct card_bat
*fatblock
,cardcallback callback
);
244 static s32
__card_updatedir(s32 chn
,cardcallback callback
);
245 static s32
__card_write(s32 chn
,u32 address
,u32 block_len
,void *buffer
,cardcallback callback
);
246 static s32
__card_writepage(s32 chn
,cardcallback callback
);
247 static s32
__card_sectorerase(s32 chn
,u32 sector
,cardcallback callback
);
248 static s32
__card_onreset(s32 final
);
250 static sys_resetinfo card_resetinfo
= {
256 extern unsigned long gettick();
257 extern long long gettime();
258 extern syssram
* __SYS_LockSram();
259 extern syssramex
* __SYS_LockSramEx();
260 extern u32
__SYS_UnlockSram(u32 write
);
261 extern u32
__SYS_UnlockSramEx(u32 write
);
263 static vu16
* const _viReg
= (u16
*)0xCC002000;
266 static s32
__card_onreset(s32 final
)
269 if(CARD_Unmount(CARD_SLOTA
)==-1) return 0;
270 if(CARD_Unmount(CARD_SLOTB
)==-1) return 0;
275 static void __card_checksum(u16
*buff
,u32 len
,u16
*cs1
,u16
*cs2
)
279 printf("__card_checksum(%p,%d,%p,%p)\n",buff
,len
,cs1
,cs2
);
284 for (i
= 0; i
< len
; ++i
) {
286 *cs2
+= (buff
[i
] ^ 0xffff);
288 if (*cs1
== 0xffff) *cs1
= 0;
289 if (*cs2
== 0xffff) *cs2
= 0;
292 static s32
__card_putcntrlblock(card_block
*card
,s32 result
)
296 _CPU_ISR_Disable(level
);
297 if(card
->attached
) card
->result
= result
;
298 else if(card
->result
==CARD_ERROR_BUSY
) card
->result
= result
;
299 _CPU_ISR_Restore(level
);
303 static s32
__card_getcntrlblock(s32 chn
,card_block
**card
)
307 card_block
*rcard
= NULL
;
309 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_FATAL_ERROR
;
311 _CPU_ISR_Disable(level
);
312 rcard
= &cardmap
[chn
];
313 if(!rcard
->attached
) {
314 _CPU_ISR_Restore(level
);
315 return CARD_ERROR_NOCARD
;
318 ret
= CARD_ERROR_BUSY
;
319 if(rcard
->result
!=CARD_ERROR_BUSY
) {
320 rcard
->result
= CARD_ERROR_BUSY
;
321 rcard
->card_api_cb
= NULL
;
323 ret
= CARD_ERROR_READY
;
325 _CPU_ISR_Restore(level
);
329 static __inline__
struct card_dat
* __card_getdirblock(card_block
*card
)
331 return card
->curr_dir
;
334 static __inline__
struct card_bat
* __card_getbatblock(card_block
*card
)
336 return card
->curr_fat
;
339 static s32
__card_sync(s32 chn
)
343 card_block
*card
= &cardmap
[chn
];
345 _CPU_ISR_Disable(level
);
346 while((ret
=CARD_GetErrorCode(chn
))==CARD_ERROR_BUSY
) {
347 LWP_ThreadSleep(card
->wait_sync_queue
);
349 _CPU_ISR_Restore(level
);
353 static void __card_synccallback(s32 chn
,s32 result
)
356 card_block
*card
= &cardmap
[chn
];
358 printf("__card_synccallback(%d,%d,%d)\n",chn
,result
,card
->result
);
360 _CPU_ISR_Disable(level
);
361 LWP_ThreadBroadcast(card
->wait_sync_queue
);
362 _CPU_ISR_Restore(level
);
365 static void __card_updateiconoffsets(struct card_direntry
*entry
,card_stat
*stats
)
369 u32 iconaddr
,iconbase
;
371 iconaddr
= entry
->iconaddr
;
373 stats
->banner_fmt
= 0;
375 stats
->icon_speed
= 0;
379 if(entry
->bannerfmt
&CARD_BANNER_MASK
) {
380 if(!(entry
->bannerfmt
&0x10)) {
381 bnrfmt
= (entry
->bannerfmt
&CARD_BANNER_MASK
);
382 if(bnrfmt
==CARD_BANNER_CI
) {
383 stats
->banner_fmt
= bnrfmt
;
384 stats
->offset_banner
= iconaddr
;
385 stats
->offset_banner_tlut
= iconaddr
+3072;
386 iconaddr
+= (3072+512);
387 } else if(bnrfmt
==CARD_BANNER_RGB
) {
388 stats
->banner_fmt
= bnrfmt
;
389 stats
->offset_banner
= iconaddr
;
390 stats
->offset_banner_tlut
= -1;
394 stats
->offset_banner
= -1;
395 stats
->offset_banner_tlut
= -1;
400 for(i
=0;i
<CARD_MAXICONS
;i
++) {
401 stats
->iconfmt
[i
] = ((entry
->iconfmt
>>(i
<<1))&CARD_ICON_MASK
);
402 stats
->iconspeed
[i
] = ((entry
->iconspeed
>>(i
<<1))&CARD_SPEED_MASK
);
403 if(stats
->iconspeed
[i
]==0) stats
->iconfmt
[i
] = 0;
404 if(stats
->iconfmt
[i
]) nicons
++;
408 for(i
=0;i
<CARD_MAXICONS
;i
++) {
409 switch(stats
->iconfmt
[i
]) {
410 case 1: //CARD_ICON_CI with shared palette
411 stats
->offset_icon
[i
] = iconaddr
;
412 stats
->offset_icon_tlut
[i
] = iconbase
+ (nicons
*1024);
415 case 2: //CARD_ICON_RGB
416 stats
->offset_icon
[i
] = iconaddr
;
417 stats
->offset_icon_tlut
[i
] = -1;
420 case 3: //CARD_ICON_CI with own palette
421 stats
->offset_icon
[i
] = iconaddr
;
422 stats
->offset_icon_tlut
[i
] = iconaddr
+ 1024;
425 default: //CARD_ICON_NONE
426 stats
->offset_icon
[i
] = -1;
427 stats
->offset_icon_tlut
[i
] = -1;
433 // stats->offset_data = iconaddr;
436 static s32
__card_getstatusex(s32 chn
,s32 fileno
,struct card_direntry
*entry
)
439 card_block
*card
= NULL
;
440 struct card_dat
*dirblock
= NULL
;
442 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
443 if(fileno
<0 || fileno
>=CARD_MAXFILES
) return CARD_ERROR_FATAL_ERROR
;
444 if((ret
=__card_getcntrlblock(chn
,&card
))<0) return ret
;
446 ret
= CARD_ERROR_BROKEN
;
447 dirblock
= __card_getdirblock(card
);
449 ret
= CARD_ERROR_READY
;
450 memcpy(entry
,&dirblock
->entries
[fileno
],sizeof(struct card_direntry
));
452 return __card_putcntrlblock(card
,ret
);
455 static s32
__card_setstatusexasync(s32 chn
,s32 fileno
,struct card_direntry
*entry
,cardcallback callback
)
458 card_block
*card
= NULL
;
459 struct card_dat
*dirblock
= NULL
;
460 struct card_direntry
*entries
= NULL
;
462 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
463 if(fileno
<0 || fileno
>=CARD_MAXFILES
) return CARD_ERROR_FATAL_ERROR
;
464 if(entry
->filename
[0]==0xff || entry
->filename
[0]==0) return CARD_ERROR_FATAL_ERROR
;
465 if((ret
=__card_getcntrlblock(chn
,&card
))<0) return ret
;
467 ret
= CARD_ERROR_BROKEN
;
468 dirblock
= __card_getdirblock(card
);
471 ret
= CARD_ERROR_READY
;
472 entries
= dirblock
->entries
;
473 while(i
<CARD_FILENAMELEN
) {
474 if(bend
|| entry
->filename
[i
]==0) {
475 entry
->filename
[i
] = 0;
481 if(memcmp(entries
[fileno
].filename
,entry
->filename
,CARD_FILENAMELEN
)
482 || memcmp(entries
[fileno
].gamecode
,entry
->gamecode
,4)
483 || memcmp(entries
[fileno
].company
,entry
->company
,2)) {
485 while(i
<CARD_MAXFILES
) {
486 if(i
!=fileno
&& entries
[i
].gamecode
[0]!=0xff
487 && memcmp(entries
[i
].gamecode
,entry
->gamecode
,4)==0
488 && memcmp(entries
[i
].company
,entry
->company
,2)==0
489 && memcmp(entries
[i
].filename
,entry
->filename
,CARD_FILENAMELEN
)==0) {
490 return __card_putcntrlblock(card
,CARD_ERROR_EXIST
);
494 memcpy(entries
[fileno
].filename
,entry
->filename
,CARD_FILENAMELEN
);
495 memcpy(entries
[fileno
].gamecode
,entry
->gamecode
,4);
496 memcpy(entries
[fileno
].company
,entry
->company
,2);
499 entries
[fileno
].lastmodified
= entry
->lastmodified
;
500 entries
[fileno
].bannerfmt
= entry
->bannerfmt
;
501 entries
[fileno
].iconaddr
= entry
->iconaddr
;
502 entries
[fileno
].iconfmt
= entry
->iconfmt
;
503 entries
[fileno
].iconspeed
= entry
->iconspeed
;
504 entries
[fileno
].commentaddr
= entry
->commentaddr
;
505 entries
[fileno
].permission
= entry
->permission
;
506 entries
[fileno
].copytimes
= entry
->copytimes
;
508 if((ret
=__card_updatedir(chn
,callback
))>=0) return ret
;
510 return __card_putcntrlblock(card
,ret
);
513 static s32
__card_setstatusex(s32 chn
,s32 fileno
,struct card_direntry
*entry
)
517 if((ret
=__card_setstatusexasync(chn
,fileno
,entry
,__card_synccallback
))>=0) {
518 ret
= __card_sync(chn
);
523 static s32
__card_getfilenum(card_block
*card
,const char *filename
,const char *gamecode
,const char *company
,s32
*fileno
)
526 struct card_direntry
*entries
= NULL
;
527 struct card_dat
*dirblock
= NULL
;
529 printf("__card_getfilenum(%p,%s,%s,%s)\n",card
,filename
,gamecode
,company
);
531 if(!card
->attached
) return CARD_ERROR_NOCARD
;
532 dirblock
= __card_getdirblock(card
);
534 entries
= dirblock
->entries
;
535 for(i
=0;i
<CARD_MAXFILES
;i
++) {
536 if(entries
[i
].gamecode
[0]!=0xff) {
537 if(strnicmp((const char*)entries
[i
].filename
,filename
,strlen(filename
))==0) {
538 if((gamecode
&& gamecode
[0]!=0xff && memcmp(entries
[i
].gamecode
,gamecode
,4)!=0)
539 || (company
&& company
[0]!=0xff && memcmp(entries
[i
].company
,company
,2)!=0)) continue;
546 if(i
>=CARD_MAXFILES
) return CARD_ERROR_NOFILE
;
547 return CARD_ERROR_READY
;
550 static s32
__card_seek(card_file
*file
,s32 len
,s32 offset
,card_block
**rcard
)
554 card_block
*card
= NULL
;
555 struct card_direntry
*entry
= NULL
;
556 struct card_dat
*dirblock
= NULL
;
557 struct card_bat
*fatblock
= NULL
;
559 printf("__card_seek(%d,%p,%d,%d)\n",file
->filenum
,file
,len
,offset
);
561 if(file
->filenum
<0 || file
->filenum
>=CARD_MAXFILES
) return CARD_ERROR_FATAL_ERROR
;
562 if((ret
=__card_getcntrlblock(file
->chn
,&card
))<0) return ret
;
564 printf("__card_seek(%d)\n",file
->iblock
);
566 if(file
->iblock
<CARD_SYSAREA
|| file
->iblock
>=card
->blocks
) {
567 __card_putcntrlblock(card
,CARD_ERROR_FATAL_ERROR
);
568 return CARD_ERROR_FATAL_ERROR
;
571 dirblock
= __card_getdirblock(card
);
572 entry
= &dirblock
->entries
[file
->filenum
];
574 printf("__card_seek(%p,%d)\n",entry
,file
->filenum
);
576 if(entry
->gamecode
[0]!=0xff) {
577 entry_len
= entry
->length
*card
->sector_size
;
578 if(entry_len
<offset
|| entry_len
<(offset
+len
)) {
579 __card_putcntrlblock(card
,CARD_ERROR_LIMIT
);
580 return CARD_ERROR_LIMIT
;
582 card
->curr_file
= file
;
585 if(offset
<file
->offset
) {
587 file
->iblock
= entry
->block
;
588 if(file
->iblock
<CARD_SYSAREA
|| file
->iblock
>=card
->blocks
) {
589 __card_putcntrlblock(card
,CARD_ERROR_BROKEN
);
590 return CARD_ERROR_BROKEN
;
594 fatblock
= __card_getbatblock(card
);
595 for(i
=file
->iblock
;i
<card
->blocks
&& file
->offset
<(offset
&~(card
->sector_size
-1));i
=file
->iblock
) {
596 file
->offset
+= card
->sector_size
;
597 file
->iblock
= fatblock
->fat
[i
-CARD_SYSAREA
];
598 if(file
->iblock
<CARD_SYSAREA
|| file
->iblock
>=card
->blocks
) {
599 __card_putcntrlblock(card
,CARD_ERROR_BROKEN
);
600 return CARD_ERROR_BROKEN
;
603 file
->offset
= offset
;
606 return CARD_ERROR_READY
;
609 static u32
__card_checkdir(card_block
*card
,u32
*currdir
)
613 struct card_dircntrl
*dircntrl
[2];
614 struct card_dat
*dirblock
[2];
616 printf("__card_checkdir(%p,%p)\n",card
,currdir
);
622 dirblock
[dir
] = card
->workarea
+((dir
+1)<<13);
623 dircntrl
[dir
] = (card
->workarea
+((dir
+1)<<13))+8128;
624 __card_checksum((u16
*)dirblock
[dir
],0x1ffc,&chksum0
,&chksum1
);
625 if(chksum0
!=dircntrl
[dir
]->chksum1
|| chksum1
!=dircntrl
[dir
]->chksum2
) {
627 printf("__card_checkdir(bad checksums: (%04x : %04x),(%04x : %04x)\n",chksum0
,dircntrl
[dir
]->chksum1
,chksum1
,dircntrl
[dir
]->chksum2
);
629 card
->curr_dir
= NULL
;
638 if(dircntrl
[0]->updated
<dircntrl
[1]->updated
) dir
= 0;
641 if(card
->curr_dir
==NULL
) {
642 card
->curr_dir
= dirblock
[dir
];
643 memcpy(dirblock
[dir
],dirblock
[dir
^1],8192);
645 else if(card
->curr_dir
==dirblock
[0]) dir
= 0;
648 if(currdir
) *currdir
= dir
;
652 static u32
__card_checkfat(card_block
*card
,u32
*currfat
)
656 struct card_bat
*fatblock
[2];
658 printf("__card_checkfat(%p,%p)\n",card
,currfat
);
664 fatblock
[fat
] = card
->workarea
+((fat
+3)<<13);
665 __card_checksum((u16
*)(((u32
)fatblock
[fat
])+4),0x1ffc,&chksum0
,&chksum1
);
666 if(chksum0
!=fatblock
[fat
]->chksum1
|| chksum1
!=fatblock
[fat
]->chksum2
) {
668 printf("__card_checkfat(bad checksums: (%04x : %04x),(%04x : %04x)\n",chksum0
,fatblock
[fat
]->chksum1
,chksum1
,fatblock
[fat
]->chksum2
);
670 card
->curr_fat
= NULL
;
674 u16 curblock
= CARD_SYSAREA
;
676 while(curblock
<card
->blocks
) {
677 if(!fatblock
[fat
]->fat
[curblock
-CARD_SYSAREA
]) freeblocks
++;
680 if(freeblocks
!=fatblock
[fat
]->freeblocks
) {
682 printf("__card_checkfat(freeblocks!=fatblock[fat]->freeblocks (%d : %d))\n",freeblocks
,fatblock
[fat
]->freeblocks
);
684 card
->curr_fat
= NULL
;
694 if(fatblock
[0]->updated
<fatblock
[1]->updated
) fat
= 0;
697 if(card
->curr_fat
==NULL
) {
698 card
->curr_fat
= fatblock
[fat
];
699 memcpy(fatblock
[fat
],fatblock
[fat
^1],8192);
701 else if(card
->curr_fat
==fatblock
[0]) fat
= 0;
704 if(currfat
) *currfat
= fat
;
708 static s32
__card_verify(card_block
*card
)
712 ret
+= __card_checkdir(card
,NULL
);
713 ret
+= __card_checkfat(card
,NULL
);
715 printf("__card_verify(%d)\n",ret
);
718 if(card
->curr_dir
&& card
->curr_fat
) return CARD_ERROR_READY
;
720 return CARD_ERROR_BROKEN
;
723 static u32
__card_iscard(u32 id
)
728 if(id
&~0xffff) return 0;
729 if(id
&0x03) return 0;
733 if(tmp
==EXI_MEMCARD59
|| tmp
==EXI_MEMCARD123
734 || tmp
==EXI_MEMCARD251
|| tmp
==EXI_MEMCARD507
735 || tmp
==EXI_MEMCARD1019
|| tmp
==EXI_MEMCARD2043
) {
736 idx
= _ROTL(id
,23)&0x1c;
737 if((secsize
=card_sector_size
[idx
>>2])==0) return 0;
738 tmp
= ((tmp
<<20)&0x1FFE0000)/secsize
;
744 static s32
__card_allocblock(s32 chn
,u32 blocksneed
,cardcallback callback
)
747 u16 block
,currblock
= 0,prevblock
= 0;
749 card_block
*card
= NULL
;
750 struct card_bat
*fatblock
= NULL
;
752 printf("__card_allocblock(%d,%d,%p)\n",chn
,blocksneed
,callback
);
754 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_FATAL_ERROR
;
755 card
= &cardmap
[chn
];
757 if(!card
->attached
) return CARD_ERROR_NOCARD
;
758 fatblock
= __card_getbatblock(card
);
760 printf("__card_allocblock(%p,%d)\n",fatblock
,fatblock
->freeblocks
);
763 if(fatblock
->freeblocks
<blocksneed
) return CARD_ERROR_INSSPACE
;
765 // Add which blocks this file will take up into the FAT
768 currblock
= fatblock
->lastalloc
;
772 // Done allocating blocks
774 printf("__card_allocblock(%d : %d)\n",block
,currblock
);
776 fatblock
->freeblocks
-= blocksneed
;
777 fatblock
->lastalloc
= currblock
;
778 card
->curr_fileblock
= block
;
779 ret
= __card_updatefat(chn
,fatblock
,callback
);
784 Since testing free space has already been done, if all the blocks
785 the file takes up cannot be entered into the FAT, something is
789 if(count
>=(card
->blocks
-CARD_SYSAREA
)) return CARD_ERROR_BROKEN
;
792 if(currblock
<CARD_SYSAREA
|| currblock
>=card
->blocks
) currblock
= CARD_SYSAREA
;
793 if(fatblock
->fat
[currblock
-CARD_SYSAREA
]==0) {
795 fatblock
->fat
[prevblock
-CARD_SYSAREA
] = currblock
;
799 fatblock
->fat
[currblock
-CARD_SYSAREA
] = 0xffff;
800 prevblock
= currblock
;
807 static s32
__card_freeblock(s32 chn
,u16 block
,cardcallback callback
)
809 u16 next
= 0xffff,prev
= 0xffff;
810 card_block
*card
= NULL
;
811 struct card_bat
*fatblock
= NULL
;
813 printf("__card_freeblock(%d,%d,%p)\n",chn
,block
,callback
);
815 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
816 card
= &cardmap
[chn
];
818 if(!card
->attached
) return CARD_ERROR_NOCARD
;
820 fatblock
= __card_getbatblock(card
);
821 next
= fatblock
->fat
[block
-CARD_SYSAREA
];
823 if(next
==0xffff) break;
824 if(next
<CARD_SYSAREA
|| next
>=card
->blocks
) return CARD_ERROR_BROKEN
;
826 // Get the file's next block and clear the previous one from the fat
828 next
= fatblock
->fat
[prev
-CARD_SYSAREA
];
829 fatblock
->fat
[prev
-CARD_SYSAREA
] = 0;
830 fatblock
->freeblocks
++;
832 return __card_updatefat(chn
,fatblock
,callback
);
835 static s32
__card_unlockedhandler(s32 chn
,s32 dev
)
838 cardcallback cb
= NULL
;
839 card_block
*card
= NULL
;
841 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
842 card
= &cardmap
[chn
];
844 ret
= CARD_ERROR_READY
;
845 cb
= card
->card_unlock_cb
;
847 card
->card_unlock_cb
= NULL
;
848 if(EXI_Probe(chn
)==0) ret
= CARD_ERROR_NOCARD
;
851 return CARD_ERROR_UNLOCKED
;
854 static s32
__card_readstatus(s32 chn
,u8
*pstatus
)
860 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
861 if(EXI_Select(chn
,EXI_DEVICE_0
,EXI_SPEED16MHZ
)==0) return CARD_ERROR_NOCARD
;
864 val
[0] = 0x83; val
[1] = 0x00;
865 if(EXI_Imm(chn
,val
,2,EXI_WRITE
,NULL
)==0) err
|= 0x01;
866 if(EXI_Sync(chn
)==0) err
|= 0x02;
867 if(EXI_Imm(chn
,pstatus
,1,EXI_READ
,NULL
)==0) err
|= 0x04;
868 if(EXI_Sync(chn
)==0) err
|= 0x08;
869 if(EXI_Deselect(chn
)==0) err
|= 0x10;
871 if(err
) ret
= CARD_ERROR_NOCARD
;
872 else ret
= CARD_ERROR_READY
;
874 printf("__card_readstatus(%d,%08x)\n",chn
,*pstatus
);
879 static s32
__card_clearstatus(s32 chn
)
885 printf("__card_clearstatus(%d)\n",chn
);
887 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
888 if(EXI_Select(chn
,EXI_DEVICE_0
,EXI_SPEED16MHZ
)==0) return CARD_ERROR_NOCARD
;
892 if(EXI_Imm(chn
,&val
,1,EXI_WRITE
,NULL
)==0) err
|= 0x01;
893 if(EXI_Sync(chn
)==0) err
|= 0x02;
894 if(EXI_Deselect(chn
)==0) err
|= 0x04;
896 if(err
) ret
= CARD_ERROR_NOCARD
;
897 else ret
= CARD_ERROR_READY
;
902 static s32
__card_sleep(s32 chn
)
908 printf("__card_sleep(%d)\n",chn
);
910 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
911 if(EXI_Select(chn
,EXI_DEVICE_0
,EXI_SPEED16MHZ
)==0) return CARD_ERROR_NOCARD
;
915 if(EXI_Imm(chn
,&val
,1,EXI_WRITE
,NULL
)==0) err
|= 0x01;
916 if(EXI_Sync(chn
)==0) err
|= 0x02;
917 if(EXI_Deselect(chn
)==0) err
|= 0x04;
919 if(err
) ret
= CARD_ERROR_NOCARD
;
920 else ret
= CARD_ERROR_READY
;
925 static s32
__card_wake(s32 chn
)
931 printf("__card_wake(%d)\n",chn
);
934 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
935 if(EXI_Select(chn
,EXI_DEVICE_0
,EXI_SPEED16MHZ
)==0) return CARD_ERROR_NOCARD
;
939 if(EXI_Imm(chn
,&val
,1,EXI_WRITE
,NULL
)==0) err
|= 0x01;
940 if(EXI_Sync(chn
)==0) err
|= 0x02;
941 if(EXI_Deselect(chn
)==0) err
|= 0x04;
943 if(err
) ret
= CARD_ERROR_NOCARD
;
944 else ret
= CARD_ERROR_READY
;
949 static s32
__card_enableinterrupt(s32 chn
,u32 enable
)
955 printf("__card_enableinterrupt(%d,%d)\n",chn
,enable
);
958 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
959 if(EXI_Select(chn
,EXI_DEVICE_0
,EXI_SPEED16MHZ
)==0) return CARD_ERROR_NOCARD
;
963 if(enable
) val
[1] = 0x01;
965 if(EXI_Imm(chn
,val
,2,EXI_WRITE
,NULL
)==0) err
|= 0x01;
966 if(EXI_Sync(chn
)==0) err
|= 0x02;
967 if(EXI_Deselect(chn
)==0) err
|= 0x04;
969 if(err
) ret
= CARD_ERROR_BUSY
;
970 else ret
= CARD_ERROR_READY
;
975 static s32
__card_txhandler(s32 chn
,s32 dev
)
978 s32 ret
= CARD_ERROR_READY
;
979 cardcallback cb
= NULL
;
980 card_block
*card
= NULL
;
982 printf("__card_txhandler(%d,%d)\n",chn
,dev
);
984 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return 0;
985 card
= &cardmap
[chn
];
988 if(EXI_Deselect(chn
)==0) ret
|= err
;
989 if(EXI_Unlock(chn
)==0) ret
|= err
;
991 cb
= card
->card_tx_cb
;
993 card
->card_tx_cb
= NULL
;
995 if(EXI_Probe(chn
)==0) ret
= CARD_ERROR_NOCARD
;
996 } else ret
= CARD_ERROR_NOCARD
;
1002 static void __timeouthandler(syswd_t alarm
,void *cbarg
)
1005 s32 ret
= CARD_ERROR_READY
;
1007 card_block
*card
= NULL
;
1009 printf("__timeouthandler(%p)\n",alarm
);
1012 while(chn
<EXI_CHANNEL_2
) {
1013 card
= &cardmap
[chn
];
1014 if(card
->timeout_svc
==alarm
) break;
1017 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return;
1020 if(card
->attached
) {
1021 EXI_RegisterEXICallback(chn
,NULL
);
1022 cb
= card
->card_exi_cb
;
1024 card
->card_exi_cb
= NULL
;
1025 ret
= CARD_ERROR_IOERROR
;
1031 static void __setuptimeout(card_block
*card
)
1035 printf("__setuptimeout(%p)\n",&card
->timeout_svc
);
1037 SYS_CancelAlarm(card
->timeout_svc
);
1039 if(card
->cmd
[0]==0xf1 || card
->cmd
[0]==0xf4) {
1041 printf("__setuptimeout(%02x, %dsec)\n",card
->cmd
[0],1*(card
->sector_size
/8192));
1043 tb
.tv_sec
= 1*(card
->sector_size
/8192);
1045 SYS_SetAlarm(card
->timeout_svc
,&tb
,__timeouthandler
,NULL
);
1046 } else if(card
->cmd
[0]==0xf2) {
1048 printf("__setuptimeout(0xf2, 100ms)\n");
1051 tb
.tv_nsec
= 100*TB_NSPERMS
;
1052 SYS_SetAlarm(card
->timeout_svc
,&tb
,__timeouthandler
,NULL
);
1056 static s32
__retry(s32 chn
)
1059 card_block
*card
= NULL
;
1061 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
1062 card
= &cardmap
[chn
];
1064 printf("__retry(%d)\n",chn
);
1066 if(EXI_Select(chn
,EXI_DEVICE_0
,EXI_SPEED16MHZ
)==0) {
1068 return CARD_ERROR_NOCARD
;
1071 __setuptimeout(card
);
1073 if(EXI_ImmEx(chn
,card
->cmd
,card
->cmd_len
,EXI_WRITE
)==0) {
1076 return CARD_ERROR_NOCARD
;
1079 if(card
->cmd
[0]==0x52) {
1080 if(EXI_ImmEx(chn
,card
->workarea
+CARD_READSIZE
,card
->latency
,EXI_WRITE
)==0) {
1083 return CARD_ERROR_NOCARD
;
1087 if(card
->cmd_mode
==-1) {
1090 return CARD_ERROR_READY
;
1094 if(card
->cmd
[0]==0x52) len
= CARD_READSIZE
;
1095 if(EXI_Dma(chn
,card
->cmd_usr_buf
,len
,card
->cmd_mode
,__card_txhandler
)==0) {
1098 return CARD_ERROR_NOCARD
;
1100 return CARD_ERROR_READY
;
1103 static void __card_defaultapicallback(s32 chn
,s32 result
)
1106 printf("__card_defaultapicallback(%d,%d)\n",chn
,result
);
1111 static s32
__card_exihandler(s32 chn
,s32 dev
)
1114 s32 ret
= CARD_ERROR_READY
;
1115 card_block
*card
= NULL
;
1118 printf("__card_exihandler(%d,%d)\n",chn
,dev
);
1120 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return 1;
1121 card
= &cardmap
[chn
];
1123 SYS_CancelAlarm(card
->timeout_svc
);
1124 if(card
->attached
) {
1125 if(EXI_Lock(chn
,EXI_DEVICE_0
,NULL
)==1) {
1126 if((ret
=__card_readstatus(chn
,&status
))>=0
1127 && (ret
=__card_clearstatus(chn
))>=0) {
1128 if(status
&0x18) ret
= CARD_ERROR_IOERROR
;
1129 else ret
= CARD_ERROR_READY
;
1131 if(ret
==CARD_ERROR_IOERROR
) {
1132 if((--card
->cmd_retries
)>0) {
1134 if(ret
<0) goto exit
;
1140 } else ret
= CARD_ERROR_FATAL_ERROR
;
1142 cb
= card
->card_exi_cb
;
1144 card
->card_exi_cb
= NULL
;
1151 static s32
__card_exthandler(s32 chn
,s32 dev
)
1154 card_block
*card
= NULL
;
1156 printf("__card_exthandler(%d,%d)\n",chn
,dev
);
1158 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return 0;
1159 card
= &cardmap
[chn
];
1161 if(card
->attached
) {
1162 if(card
->card_tx_cb
) {
1163 printf("error: card->card_tx_cb!=NULL\n");
1166 EXI_RegisterEXICallback(chn
,NULL
);
1167 SYS_CancelAlarm(card
->timeout_svc
);
1169 cb
= card
->card_exi_cb
;
1171 card
->card_exi_cb
= NULL
;
1172 cb(chn
,CARD_ERROR_NOCARD
);
1175 cb
= card
->card_ext_cb
;
1177 card
->card_ext_cb
= NULL
;
1178 cb(chn
,CARD_ERROR_NOCARD
);
1185 static void __write_callback(s32 chn
,s32 result
)
1188 cardcallback cb
= NULL
;
1189 card_file
*file
= NULL
;
1190 struct card_bat
*fatblock
= NULL
;
1191 struct card_dat
*dirblock
= NULL
;
1192 struct card_direntry
*entry
= NULL
;
1193 card_block
*card
= &cardmap
[chn
];
1195 printf("__write_callback(%d,%d)\n",chn
,result
);
1199 file
= card
->curr_file
;
1201 file
->len
= (card
->sector_size
-file
->len
);
1203 dirblock
= __card_getdirblock(card
);
1204 entry
= &dirblock
->entries
[file
->filenum
];
1205 entry
->lastmodified
= time(NULL
);
1206 cb
= card
->card_api_cb
;
1207 card
->card_api_cb
= NULL
;
1208 if((ret
=__card_updatedir(chn
,cb
))>=0) return;
1210 fatblock
= __card_getbatblock(card
);
1211 file
->offset
+= card
->sector_size
;
1212 file
->iblock
= fatblock
->fat
[file
->iblock
-CARD_SYSAREA
];
1213 if(file
->iblock
<CARD_SYSAREA
|| file
->iblock
>=card
->blocks
) {
1214 ret
= CARD_ERROR_BROKEN
;
1217 if((ret
=__card_sectorerase(chn
,(file
->iblock
*card
->sector_size
),__erase_callback
))>=0) return;
1220 ret
= CARD_ERROR_CANCELED
;
1224 cb
= card
->card_api_cb
;
1225 card
->card_api_cb
= NULL
;
1226 __card_putcntrlblock(card
,ret
);
1230 static void __erase_callback(s32 chn
,s32 result
)
1233 cardcallback cb
= NULL
;
1234 card_file
*file
= NULL
;
1235 card_block
*card
= &cardmap
[chn
];
1237 printf("__erase_callback(%d,%d)\n",chn
,result
);
1241 file
= card
->curr_file
;
1242 if((ret
=__card_write(chn
,(file
->iblock
*card
->sector_size
),card
->sector_size
,card
->cmd_usr_buf
,__write_callback
))>=0) return;
1245 cb
= card
->card_api_cb
;
1246 card
->card_api_cb
= NULL
;
1247 __card_putcntrlblock(card
,ret
);
1251 static void __read_callback(s32 chn
,s32 result
)
1255 cardcallback cb
= NULL
;
1256 card_file
*file
= NULL
;
1257 card_block
*card
= 0;
1258 struct card_bat
*fatblock
= NULL
;
1260 printf("__read_callback(%d,%d)\n",chn
,result
);
1262 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return;
1263 card
= &cardmap
[chn
];
1266 file
= card
->curr_file
;
1268 printf("__read_callback(file->len = %d,file->iblock = %d)\n",file
->len
,file
->iblock
);
1272 file
->len
= file
->len
-(((file
->offset
+card
->sector_size
)&~(card
->sector_size
-1))-file
->offset
);
1274 printf("__read_callback(file->len = %d)\n",file
->len
);
1277 fatblock
= __card_getbatblock(card
);
1278 file
->offset
+= (((file
->offset
+card
->sector_size
)&~(card
->sector_size
-1))-file
->offset
);
1279 file
->iblock
= fatblock
->fat
[file
->iblock
-CARD_SYSAREA
];
1280 if(file
->iblock
<CARD_SYSAREA
|| file
->iblock
>=card
->blocks
) {
1281 ret
= CARD_ERROR_BROKEN
;
1284 len
= file
->len
<card
->sector_size
?card
->sector_size
:file
->len
;
1285 if(__card_read(chn
,(file
->iblock
*card
->sector_size
),len
,card
->cmd_usr_buf
,__read_callback
)>=0) return;
1289 ret
= CARD_ERROR_CANCELED
;
1293 cb
= card
->card_api_cb
;
1294 card
->card_api_cb
= NULL
;
1295 __card_putcntrlblock(card
,ret
);
1299 static void __delete_callback(s32 chn
,s32 result
)
1302 cardcallback cb
= NULL
;
1303 card_block
*card
= &cardmap
[chn
];
1305 printf("__delete_callback(%d,%d)\n",chn
,result
);
1307 cb
= card
->card_api_cb
;
1308 card
->card_api_cb
= NULL
;
1311 if(ret
>=0 && (ret
=__card_freeblock(chn
,card
->curr_fileblock
,cb
))>=0) return;
1313 __card_putcntrlblock(card
,ret
);
1317 static void __format_callback(s32 chn
,s32 result
)
1320 cardcallback cb
= NULL
;
1321 card_block
*card
= &cardmap
[chn
];
1325 if((++card
->format_step
)<CARD_SYSAREA
) {
1326 if((ret
=__card_sectorerase(chn
,(card
->format_step
*card
->sector_size
),__format_callback
))>=0) return;
1329 if(card
->format_step
<10) {
1330 if((ret
=__card_write(chn
,((card
->format_step
-CARD_SYSAREA
)*card
->sector_size
),8192,card
->workarea
+((card
->format_step
-CARD_SYSAREA
)<<13),__format_callback
))>=0) return;
1334 card
->curr_dir
= card
->workarea
+CARD_SYSDIR
;
1335 memcpy(card
->curr_dir
,card
->workarea
+CARD_SYSDIR_BACK
,8192);
1337 card
->curr_fat
= card
->workarea
+CARD_SYSBAT
;
1338 memcpy(card
->curr_fat
,card
->workarea
+CARD_SYSBAT_BACK
,8192);
1341 cb
= card
->card_api_cb
;
1342 card
->card_api_cb
= NULL
;
1343 __card_putcntrlblock(card
,ret
);
1347 static void __blockwritecallback(s32 chn
,s32 result
)
1349 s32 ret
= CARD_ERROR_READY
;
1350 cardcallback cb
= NULL
;
1351 card_block
*card
= &cardmap
[chn
];
1353 printf("__blockwritecallback(%d,%d)\n",chn
,result
);
1357 card
->transfer_cnt
+= 128;
1358 card
->cmd_sector_addr
+= 128;
1359 card
->cmd_usr_buf
+= 128;
1360 if((--card
->cmd_blck_cnt
)>0) {
1361 if((ret
=__card_writepage(chn
,__blockwritecallback
))>=CARD_ERROR_READY
) return;
1365 if(!card
->card_api_cb
) __card_putcntrlblock(card
,ret
);
1367 cb
= card
->card_xfer_cb
;
1369 card
->card_xfer_cb
= NULL
;
1374 static void __blockreadcallback(s32 chn
,s32 result
)
1376 s32 ret
= CARD_ERROR_READY
;
1377 cardcallback cb
= NULL
;
1378 card_block
*card
= &cardmap
[chn
];
1380 printf("__blockreadcallback(%d,%d)\n",chn
,result
);
1384 card
->transfer_cnt
+= CARD_READSIZE
;
1385 card
->cmd_sector_addr
+= CARD_READSIZE
;
1386 card
->cmd_usr_buf
+= CARD_READSIZE
;
1387 if((--card
->cmd_blck_cnt
)>0) {
1388 if((ret
=__card_readsegment(chn
,__blockreadcallback
))>=CARD_ERROR_READY
) return;
1392 if(!card
->card_api_cb
) __card_putcntrlblock(card
,ret
);
1393 cb
= card
->card_xfer_cb
;
1395 card
->card_xfer_cb
= NULL
;
1400 static void __unlocked_callback(s32 chn
,s32 result
)
1406 printf("__unlocked_callback(%d,%d)\n",chn
,result
);
1408 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return;
1409 card
= &cardmap
[chn
];
1413 card
->card_unlock_cb
= __unlocked_callback
;
1414 if(EXI_Lock(chn
,EXI_DEVICE_0
,__card_unlockedhandler
)==1) {
1415 card
->card_unlock_cb
= NULL
;
1421 if(card
->cmd
[0]==0xf3 || card
->cmd
[0]>=0xf5) return;
1422 else if(card
->cmd
[0]==0x52) {
1423 cb
= card
->card_tx_cb
;
1425 card
->card_tx_cb
= NULL
;
1428 } else if(card
->cmd
[0]>=0xf1) {
1429 cb
= card
->card_exi_cb
;
1431 card
->card_exi_cb
= NULL
;
1438 static s32
__card_start(s32 chn
,cardcallback tx_cb
,cardcallback exi_cb
)
1441 card_block
*card
= NULL
;
1443 printf("__card_start(%d,%p,%p)\n",chn
,tx_cb
,exi_cb
);
1445 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
1446 card
= &cardmap
[chn
];
1448 _CPU_ISR_Disable(level
);
1449 if(tx_cb
) card
->card_tx_cb
= tx_cb
;
1450 if(exi_cb
) card
->card_exi_cb
= exi_cb
;
1452 card
->card_unlock_cb
= __unlocked_callback
;
1453 if(EXI_Lock(chn
,EXI_DEVICE_0
,__card_unlockedhandler
)==0) {
1454 _CPU_ISR_Restore(level
);
1456 printf("__card_start(done CARD_ERROR_BUSY)\n");
1458 return CARD_ERROR_BUSY
;
1460 card
->card_unlock_cb
= NULL
;
1462 if(EXI_Select(chn
,EXI_DEVICE_0
,EXI_SPEED16MHZ
)==0) {
1464 _CPU_ISR_Restore(level
);
1466 printf("__card_start(done CARD_ERROR_NOCARD)\n");
1468 return CARD_ERROR_NOCARD
;
1471 __setuptimeout(card
);
1472 _CPU_ISR_Restore(level
);
1475 printf("__card_start(done CARD_ERROR_READY)\n");
1477 return CARD_ERROR_READY
;
1480 static s32
__card_writepage(s32 chn
,cardcallback callback
)
1483 card_block
*card
= NULL
;
1485 printf("__card_writepage(%d,%p)\n",chn
,callback
);
1487 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
1488 card
= &cardmap
[chn
];
1490 card
->cmd
[0] = 0xf2;
1491 card
->cmd
[1] = (card
->cmd_sector_addr
>>17)&0x3f;
1492 card
->cmd
[2] = (card
->cmd_sector_addr
>>9)&0xff;
1493 card
->cmd
[3] = (card
->cmd_sector_addr
>>7)&3;
1494 card
->cmd
[4] = card
->cmd_sector_addr
&0x7f;
1496 card
->cmd_mode
= EXI_WRITE
;
1497 card
->cmd_retries
= 3;
1499 ret
= __card_start(chn
,NULL
,callback
);
1500 if(ret
<0) return ret
;
1502 if(EXI_ImmEx(chn
,card
->cmd
,card
->cmd_len
,EXI_WRITE
)==1
1503 && EXI_Dma(chn
,card
->cmd_usr_buf
,128,card
->cmd_mode
,__card_txhandler
)==1) return CARD_ERROR_READY
;
1505 card
->card_exi_cb
= NULL
;
1508 return CARD_ERROR_NOCARD
;
1511 static s32
__card_readsegment(s32 chn
,cardcallback callback
)
1515 card_block
*card
= NULL
;
1517 printf("__card_readsegment(%d,%p)\n",chn
,callback
);
1519 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
1520 card
= &cardmap
[chn
];
1522 card
->cmd
[0] = 0x52;
1523 card
->cmd
[1] = (card
->cmd_sector_addr
&0xFE0000)>>17;
1524 card
->cmd
[2] = (card
->cmd_sector_addr
&0x01FE00)>>9;
1525 card
->cmd
[3] = (card
->cmd_sector_addr
&0x000180)>>7;
1526 card
->cmd
[4] = (card
->cmd_sector_addr
&0x00007F);
1528 card
->cmd_mode
= EXI_READ
;
1529 card
->cmd_retries
= 0;
1531 ret
= __card_start(chn
,callback
,NULL
);
1532 if(ret
<0) return ret
;
1535 if(EXI_ImmEx(chn
,card
->cmd
,card
->cmd_len
,EXI_WRITE
)==0) err
|= 0x01;
1536 if(EXI_ImmEx(chn
,card
->workarea
+CARD_READSIZE
,card
->latency
,EXI_WRITE
)==0) err
|= 0x02;
1537 if(EXI_Dma(chn
,card
->cmd_usr_buf
,CARD_READSIZE
,card
->cmd_mode
,__card_txhandler
)==0) err
|= 0x04;
1540 card
->card_tx_cb
= NULL
;
1543 return CARD_ERROR_NOCARD
;
1545 return CARD_ERROR_READY
;
1548 static void __card_fatwritecallback(s32 chn
,s32 result
)
1551 cardcallback cb
= NULL
;
1552 struct card_bat
*fat1
,*fat2
;
1553 card_block
*card
= &cardmap
[chn
];
1555 printf("__card_fatwritecallback(%d,%d)\n",chn
,result
);
1559 fat1
= (card
->workarea
+0x6000);
1560 fat2
= (card
->workarea
+0x8000);
1561 if(card
->curr_fat
==fat1
) {
1562 card
->curr_fat
= fat2
;
1563 memcpy(fat2
,fat1
,8192);
1565 card
->curr_fat
= fat1
;
1566 memcpy(fat1
,fat2
,8192);
1569 if(!card
->card_api_cb
) __card_putcntrlblock(card
,ret
);
1571 printf("__card_fatwritecallback(%p,%p)\n",card
->card_api_cb
,card
->card_erase_cb
);
1573 cb
= card
->card_erase_cb
;
1575 card
->card_erase_cb
= NULL
;
1580 static void __card_dirwritecallback(s32 chn
,s32 result
)
1583 cardcallback cb
= NULL
;
1584 struct card_dat
*dir1
,*dir2
;
1585 card_block
*card
= &cardmap
[chn
];
1587 printf("__card_dirwritecallback(%d,%d)\n",chn
,result
);
1591 dir1
= (card
->workarea
+0x2000);
1592 dir2
= (card
->workarea
+0x4000);
1593 if(card
->curr_dir
==dir1
) {
1594 card
->curr_dir
= dir2
;
1595 memcpy(dir2
,dir1
,8192);
1597 card
->curr_dir
= dir1
;
1598 memcpy(dir1
,dir2
,8192);
1601 if(!card
->card_api_cb
) __card_putcntrlblock(card
,ret
);
1603 printf("__card_dirwritecallback(%p,%p)\n",card
->card_api_cb
,card
->card_erase_cb
);
1605 cb
= card
->card_erase_cb
;
1607 card
->card_erase_cb
= NULL
;
1612 static s32
__card_write(s32 chn
,u32 address
,u32 block_len
,void *buffer
,cardcallback callback
)
1615 card_block
*card
= NULL
;
1617 printf("__card_write(%d,%08x,%d,%p,%p)\n",chn
,address
,block_len
,buffer
,callback
);
1619 if(chn
<EXI_CHANNEL_0
|| chn
>= EXI_CHANNEL_2
) return CARD_ERROR_FATAL_ERROR
;
1620 card
= &cardmap
[chn
];
1622 if(!card
->attached
) return CARD_ERROR_NOCARD
;
1624 card
->cmd_blck_cnt
= block_len
>>7;
1625 card
->cmd_sector_addr
= address
;
1626 card
->cmd_usr_buf
= buffer
;
1627 card
->card_xfer_cb
= callback
;
1628 ret
= __card_writepage(chn
,__blockwritecallback
);
1633 static s32
__card_read(s32 chn
,u32 address
,u32 block_len
,void *buffer
,cardcallback callback
)
1636 card_block
*card
= NULL
;
1638 printf("__card_read(%d,%08x,%d,%p,%p)\n",chn
,address
,block_len
,buffer
,callback
);
1640 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
1641 card
= &cardmap
[chn
];
1643 card
->cmd_sector_addr
= address
;
1644 card
->cmd_blck_cnt
= block_len
>>9;
1645 card
->cmd_usr_buf
= buffer
;
1646 card
->card_xfer_cb
= callback
;
1647 ret
= __card_readsegment(chn
,__blockreadcallback
);
1652 static s32
__card_formatregion(s32 chn
,u32 encode
,cardcallback callback
)
1659 void *workarea
,*memblock
;
1660 cardcallback cb
= NULL
;
1661 card_block
*card
= NULL
;
1662 struct card_header
*header
;
1663 struct card_bat
*fatblock
= NULL
;
1664 struct card_dircntrl
*dircntrl
= NULL
;
1668 printf("__card_formatregion(%d,%d,%p)\n",chn
,encode
,callback
);
1670 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
1672 if((ret
=__card_getcntrlblock(chn
,&card
))<0) return ret
;
1674 header
= workarea
= card
->workarea
;
1675 memset(header
,0xff,8192);
1678 header
->encoding
= encode
;
1680 sram
= __SYS_LockSram();
1681 header
->serial
[5] = sram
->counter_bias
;
1682 header
->serial
[6] = sram
->lang
;
1683 __SYS_UnlockSram(0);
1686 rnd_val
= time
= gettime();
1687 sramex
= __SYS_LockSramEx();
1689 rnd_val
= (((rnd_val
*(u64
)0x0000000041c64e6d)+(u64
)0x0000000000003039)>>16);
1690 ((u8
*)header
->serial
)[cnt
] = (sramex
->flash_id
[chn
][cnt
]+(u32
)rnd_val
);
1692 rnd_val
= (((rnd_val
*(u64
)0x0000000041c64e6d)+(u64
)0x0000000000003039)>>16);
1693 rnd_val
&= (u64
)0x0000000000007fff;
1697 __SYS_UnlockSramEx(0);
1699 *(u64
*)&(header
->serial
[3]) = time
;
1700 header
->serial
[7] = tmp
;
1701 header
->device_id
= 0;
1702 header
->size
= card
->card_size
;
1703 __card_checksum((u16
*)header
,508,&header
->chksum1
,&header
->chksum2
);
1707 memblock
= workarea
+((cnt
+1)<<13);
1708 dircntrl
= memblock
+8128;
1709 memset(memblock
,0xff,8192);
1710 __card_checksum(memblock
,8188,&dircntrl
->chksum1
,&dircntrl
->chksum2
);
1716 memblock
= workarea
+((cnt
+3)<<13);
1717 fatblock
= memblock
;
1718 memset(memblock
,0,8192);
1719 fatblock
->updated
= cnt
;
1720 fatblock
->freeblocks
= card
->blocks
-CARD_SYSAREA
;
1721 fatblock
->lastalloc
= 4;
1722 __card_checksum(memblock
+4,8188,&fatblock
->chksum1
,&fatblock
->chksum2
);
1727 if(!cb
) cb
= __card_defaultapicallback
;
1728 card
->card_api_cb
= cb
;
1730 DCStoreRange(card
->workarea
,0xA000);
1732 card
->format_step
= 0;
1733 if((ret
=__card_sectorerase(chn
,(card
->sector_size
*card
->format_step
),__format_callback
))>=0) return ret
;
1735 __card_putcntrlblock(card
,ret
);
1739 static s32
__card_sectorerase(s32 chn
,u32 sector
,cardcallback callback
)
1742 card_block
*card
= NULL
;
1744 printf("__card_sectorerase(%d,%08x,%p)\n",chn
,sector
,callback
);
1746 if(chn
<EXI_CHANNEL_0
|| chn
>= EXI_CHANNEL_2
) return CARD_ERROR_FATAL_ERROR
;
1747 card
= &cardmap
[chn
];
1749 if(sector
%card
->sector_size
) return CARD_ERROR_FATAL_ERROR
;
1751 card
->cmd
[0] = 0xf1;
1752 card
->cmd
[1] = (sector
>>17)&0x7f;
1753 card
->cmd
[2] = (sector
>>9)&0xff;
1755 card
->cmd_mode
= -1;
1756 card
->cmd_retries
= 3;
1758 ret
= __card_start(chn
,NULL
,callback
);
1759 if(ret
<0) return ret
;
1761 if(EXI_ImmEx(chn
,card
->cmd
,card
->cmd_len
,EXI_WRITE
)==0) {
1762 card
->card_exi_cb
= NULL
;
1763 return CARD_ERROR_NOCARD
;
1771 static void __card_faterasecallback(s32 chn
,s32 result
)
1774 cardcallback cb
= NULL
;
1775 struct card_bat
*fatblock
= NULL
;
1776 card_block
*card
= &cardmap
[chn
];
1778 printf("__card_faterasecallback(%d,%d)\n",chn
,result
);
1782 fatblock
= __card_getbatblock(card
);
1783 if((ret
=__card_write(chn
,(((u32
)fatblock
-(u32
)card
->workarea
)>>13)*card
->sector_size
,8192,fatblock
,__card_fatwritecallback
))>=0) return;
1785 if(!card
->card_api_cb
) __card_putcntrlblock(card
,ret
);
1787 cb
= card
->card_erase_cb
;
1789 card
->card_erase_cb
= NULL
;
1794 static void __card_direrasecallback(s32 chn
,s32 result
)
1797 cardcallback cb
= NULL
;
1798 struct card_dat
*dirblock
= NULL
;
1799 card_block
*card
= &cardmap
[chn
];
1801 printf("__card_direrasecallback(%d,%d)\n",chn
,result
);
1805 dirblock
= __card_getdirblock(card
);
1806 if((ret
=__card_write(chn
,(((u32
)dirblock
-(u32
)card
->workarea
)>>13)*card
->sector_size
,8192,dirblock
,__card_dirwritecallback
))>=0) return;
1808 if(!card
->card_api_cb
) __card_putcntrlblock(card
,ret
);
1810 cb
= card
->card_erase_cb
;
1812 card
->card_erase_cb
= NULL
;
1817 static void __card_createfatcallback(s32 chn
,s32 result
)
1820 cardcallback cb
= NULL
;
1821 card_file
*file
= NULL
;
1822 struct card_direntry
*entry
= NULL
;
1823 struct card_dat
*dirblock
= NULL
;
1824 card_block
*card
= &cardmap
[chn
];
1826 printf("__card_createfatcallback(%d,%d)\n",chn
,result
);
1828 cb
= card
->card_api_cb
;
1829 card
->card_api_cb
= NULL
;
1831 dirblock
= __card_getdirblock(card
);
1833 file
= card
->curr_file
;
1834 entry
= &dirblock
->entries
[file
->filenum
];
1836 memset(entry
->gamecode
,0,4);
1837 memset(entry
->company
,0,2);
1838 if(card_gamecode
[0]!=0xff) memcpy(entry
->gamecode
,card_gamecode
,4);
1839 if(card_gamecode
[0]!=0xff) memcpy(entry
->company
,card_company
,2);
1840 entry
->block
= card
->curr_fileblock
;
1841 entry
->permission
= CARD_ATTRIB_PUBLIC
;
1842 entry
->pad_00
= 0xff;
1843 entry
->copytimes
= 0;
1844 entry
->iconaddr
= -1;
1846 entry
->iconspeed
= 0;
1847 entry
->pad_01
= 0xffff;
1848 entry
->iconspeed
= (entry
->iconspeed
&~CARD_SPEED_MASK
)|CARD_SPEED_FAST
;
1849 entry
->lastmodified
= time(NULL
);
1852 file
->iblock
= card
->curr_fileblock
;
1854 if((ret
=__card_updatedir(chn
,cb
))<0) {
1855 __card_putcntrlblock(card
,ret
);
1860 static s32
__card_updatefat(s32 chn
,struct card_bat
*fatblock
,cardcallback callback
)
1862 card_block
*card
= NULL
;
1864 printf("__card_updatefat(%d,%p,%p)\n",chn
,fatblock
,callback
);
1866 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_FATAL_ERROR
;
1867 card
= &cardmap
[chn
];
1869 if(!card
->attached
) return CARD_ERROR_NOCARD
;
1871 ++fatblock
->updated
;
1872 __card_checksum((u16
*)(((u32
)fatblock
)+4),0x1ffc,&fatblock
->chksum1
,&fatblock
->chksum2
);
1873 DCStoreRange(fatblock
,8192);
1874 card
->card_erase_cb
= callback
;
1876 return __card_sectorerase(chn
,(((u32
)fatblock
-(u32
)card
->workarea
)>>13)*card
->sector_size
,__card_faterasecallback
);
1879 static s32
__card_updatedir(s32 chn
,cardcallback callback
)
1881 card_block
*card
= NULL
;
1882 void *dirblock
= NULL
;
1883 struct card_dircntrl
*dircntrl
= NULL
;
1885 printf("__card_updatedir(%d,%p)\n",chn
,callback
);
1887 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_FATAL_ERROR
;
1888 card
= &cardmap
[chn
];
1890 if(!card
->attached
) return CARD_ERROR_NOCARD
;
1892 dirblock
= __card_getdirblock(card
);
1893 dircntrl
= dirblock
+8128;
1894 ++dircntrl
->updated
;
1895 __card_checksum((u16
*)dirblock
,0x1ffc,&dircntrl
->chksum1
,&dircntrl
->chksum2
);
1896 DCStoreRange(dirblock
,0x2000);
1897 card
->card_erase_cb
= callback
;
1899 return __card_sectorerase(chn
,(((u32
)dirblock
-(u32
)card
->workarea
)>>13)*card
->sector_size
,__card_direrasecallback
);
1902 static void __card_dounmount(s32 chn
,s32 result
)
1907 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return;
1908 card
= &cardmap
[chn
];
1910 _CPU_ISR_Disable(level
);
1911 if(card
->attached
) {
1913 card
->mount_step
= 0;
1914 card
->result
= result
;
1915 EXI_RegisterEXICallback(chn
,NULL
);
1917 SYS_CancelAlarm(card
->timeout_svc
);
1919 _CPU_ISR_Restore(level
);
1922 static s32
__card_domount(s32 chn
)
1925 s32 ret
= CARD_ERROR_READY
;
1931 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
1932 card
= &cardmap
[chn
];
1934 printf("__card_domount(%d,%d)\n",chn
,card
->mount_step
);
1936 if(card
->mount_step
==0) {
1939 if(EXI_GetID(chn
,EXI_DEVICE_0
,&id
)==0) ret
= CARD_ERROR_NOCARD
;
1940 else if(!__card_iscard(id
)) ret
= CARD_ERROR_WRONGDEVICE
;
1942 if(ret
<0) goto exit
;
1944 card
->card_size
= (id
&0xfc);
1946 printf("__card_domount(card_type = %08x,%08x,%08x)\n",card
->card_size
,card
->cid
,id
);
1948 if(card
->card_size
) {
1949 idx
= _ROTL(id
,23)&0x1c;
1950 card
->sector_size
= card_sector_size
[idx
>>2];
1951 card
->blocks
= ((card
->card_size
<<20)>>3)/card
->sector_size
;
1953 if(card
->blocks
>0x0008) {
1954 idx
= _ROTL(id
,26)&0x1c;
1955 card
->latency
= card_latency
[idx
>>2];
1957 if((ret
=__card_clearstatus(chn
))<0) goto exit
;
1958 if((ret
=__card_readstatus(chn
,&status
))<0) goto exit
;
1960 if(EXI_Probe(chn
)==0) {
1961 ret
= CARD_ERROR_NOCARD
;
1964 if(!(status
&CARD_STATUS_UNLOCKED
)) {
1966 printf("__card_domount(card locked)\n");
1968 if((ret
=__dounlock(chn
,card
->key
))<0) goto exit
;
1972 sramex
= __SYS_LockSramEx();
1974 kval
= ((u8
*)card
->key
)[cnt
];
1975 sramex
->flash_id
[chn
][cnt
] = kval
;
1979 sum
= (sum
^-1)&0xff;
1980 sramex
->flashID_chksum
[chn
] = (sum
<<8)|sum
;
1981 __SYS_UnlockSramEx(1);
1984 card
->mount_step
= 1;
1988 sramex
= __SYS_LockSramEx();
1990 sum
+= sramex
->flash_id
[chn
][cnt
];
1993 cnt
= sramex
->flashID_chksum
[chn
];
1994 __SYS_UnlockSramEx(0);
1996 sum
= (sum
^-1)&0xff;
1999 ret
= CARD_ERROR_IOERROR
;
2005 if(card
->mount_step
==1) {
2006 card
->mount_step
= 2;
2007 if((ret
=__card_enableinterrupt(chn
,1))<0) goto exit
;
2008 EXI_RegisterEXICallback(chn
,__card_exihandler
);
2011 DCInvalidateRange(card
->workarea
,0xA000);
2014 if((ret
=__card_read(chn
,(card
->sector_size
*(card
->mount_step
-2)),card
->sector_size
,card
->workarea
+((card
->mount_step
-2)<<13),__card_mountcallback
))<0) goto exit
;
2019 __card_dounmount(chn
,ret
);
2024 static void __card_mountcallback(s32 chn
,s32 result
)
2028 card_block
*card
= &cardmap
[chn
];
2031 if(ret
==CARD_ERROR_NOCARD
|| ret
==CARD_ERROR_IOERROR
) {
2032 __card_dounmount(chn
,ret
);
2033 __card_putcntrlblock(card
,ret
);
2034 }else if(ret
==CARD_ERROR_UNLOCKED
) {
2035 if((ret
=__card_domount(chn
))>=0) return;
2037 if((++card
->mount_step
)<7) {
2038 if((ret
=__card_domount(chn
))>=0) return;
2040 ret
= __card_verify(card
);
2041 __card_putcntrlblock(card
,ret
);
2045 cb
= card
->card_api_cb
;
2046 card
->card_api_cb
= NULL
;
2050 static __inline__
void __card_srand(u32 val
)
2055 static __inline__ u32
__card_rand()
2057 crand_next
= (crand_next
*0x41C64E6D)+12345;
2058 return _SHIFTR(crand_next
,16,15);
2061 static u32
__card_initval()
2063 u32 ticks
= gettick();
2065 __card_srand(ticks
);
2066 return ((0x7FEC8000|__card_rand())&~0x00000fff);
2069 static u32
__card_dummylen()
2071 u32 ticks
= gettick();
2072 u32 val
= 0,cnt
= 0,shift
= 1;
2074 __card_srand(ticks
);
2075 val
= (__card_rand()&0x1f)+1;
2081 if(shift
>16) shift
= 1;
2083 val
= (__card_rand()&0x1f)+1;
2085 }while(val
<4 && cnt
<10);
2092 static u32
exnor_1st(u32 a
,u32 b
)
2094 u32 c
,d
,e
,f
,r1
,r2
,r3
,r4
;
2103 r3
= ~(d
^r2
); //eqv(d,r2)
2105 r4
= ((r3
<<30)&0x40000000);
2112 static u32
exnor(u32 a
,u32 b
)
2114 u32 c
,d
,e
,f
,r1
,r2
,r3
,r4
;
2123 r3
= ~(d
^r2
); //eqv(d,r2)
2125 r4
= ((r3
>>30)&0x02);
2132 static u32
bitrev(u32 val
)
2134 u32 cnt
,val1
,ret
,shift
,shift1
;
2142 val1
= val
&(1<<cnt
);
2143 val1
<<= ((31-cnt
)-shift1
);
2146 } else if(cnt
==31) {
2151 val1
= val
&(1<<cnt
);
2161 static s32
__card_readarrayunlock(s32 chn
,u32 address
,void *buffer
,u32 len
,u32 flag
)
2166 card_block
*card
= &cardmap
[chn
];
2168 printf("__card_readarrayunlock(%d,%d,%p,%d,%d)\n",chn
,address
,buffer
,len
,flag
);
2170 if(EXI_Select(chn
,EXI_DEVICE_0
,EXI_SPEED16MHZ
)==0) return CARD_ERROR_NOCARD
;
2172 address
&= 0xFFFFF000;
2177 regbuf
[1] = ((address
&0x60000000)>>29)&0xff;
2178 regbuf
[2] = ((address
&0x1FE00000)>>21)&0xff;
2179 regbuf
[3] = ((address
&0x00180000)>>19)&0xff;
2180 regbuf
[4] = ((address
&0x0007F000)>>12)&0xff;
2182 regbuf
[1] = (address
>>24)&0xff;
2183 regbuf
[2] = ((address
&0x00FF0000)>>16)&0xff;
2187 if(EXI_ImmEx(chn
,regbuf
,5,EXI_WRITE
)==0) err
|= 0x01;
2188 if(EXI_ImmEx(chn
,card
->workarea
+CARD_READSIZE
,card
->latency
,EXI_WRITE
)==0) err
|= 0x02;
2189 if(EXI_ImmEx(chn
,buffer
,len
,EXI_READ
)==0) err
|= 0x04;
2190 if(EXI_Deselect(chn
)==0) err
|= 0x08;
2192 if(err
) ret
= CARD_ERROR_NOCARD
;
2193 else ret
= CARD_ERROR_READY
;
2198 static void __dsp_initcallback(dsptask_t
*task
)
2201 card_block
*card
= NULL
;
2203 printf("__dsp_initcallback(%p)\n",task
);
2206 while(chn
<EXI_CHANNEL_2
) {
2207 card
= &cardmap
[chn
];
2208 if(&card
->dsp_task
==task
) break;
2211 if(chn
>=EXI_CHANNEL_2
) return;
2213 DSP_SendMailTo(0xFF000000);
2214 while(DSP_CheckMailTo());
2215 DSP_SendMailTo((u32
)card
->workarea
);
2216 while(DSP_CheckMailTo());
2219 static u8 tmp_buffer
[64] ATTRIBUTE_ALIGN(32);
2220 static void __dsp_donecallback(dsptask_t
*task
)
2227 card_block
*card
= NULL
;
2229 printf("__dsp_donecallback(%p)\n",task
);
2232 while(chn
<EXI_CHANNEL_2
) {
2233 card
= &cardmap
[chn
];
2234 if(&card
->dsp_task
==task
) break;
2237 if(chn
>=EXI_CHANNEL_2
) return;
2239 workarea
= (u32
)card
->workarea
;
2240 workarea
= ((workarea
+47)&~0x1f);
2241 key
= ((u32
*)workarea
)[8];
2243 val
= (key
^card
->cipher
)&~0xffff;
2244 len
= __card_dummylen();
2245 if(__card_readarrayunlock(chn
,val
,tmp_buffer
,len
,1)<0) {
2247 __card_mountcallback(chn
,CARD_ERROR_NOCARD
);
2251 val
= exnor(card
->cipher
,((len
+card
->latency
+4)<<3)+1);
2259 r3
= ~(a
^r2
); //eqv(a,r2)
2260 r1
= (val
|(r3
>>31));
2264 val
= ((key
<<16)^card
->cipher
)&~0xffff;
2265 len
= __card_dummylen();
2266 if(__card_readarrayunlock(chn
,val
,tmp_buffer
,len
,1)<0) {
2268 __card_mountcallback(chn
,CARD_ERROR_NOCARD
);
2272 ret
= __card_readstatus(chn
,&status
);
2273 if(EXI_Probe(chn
)==0) {
2275 __card_mountcallback(chn
,CARD_ERROR_NOCARD
);
2278 if(!ret
&& !(status
&CARD_STATUS_UNLOCKED
)) {
2280 ret
= CARD_ERROR_IOERROR
;
2282 __card_mountcallback(chn
,ret
);
2285 static s32
__dounlock(s32 chn
,u32
*key
)
2288 u32 array_addr
,len
,val
;
2290 card_block
*card
= &cardmap
[chn
];
2291 u32
*workarea
= card
->workarea
;
2292 u32
*cipher1
= (u32
*)(((u32
)card
->workarea
+47)&~31);
2293 u32
*cipher2
= &cipher1
[8];
2295 printf("__dounlock(%d,%p)\n",chn
,key
);
2297 array_addr
= __card_initval();
2298 len
= __card_dummylen();
2300 if(__card_readarrayunlock(chn
,array_addr
,tmp_buffer
,len
,0)<0) return CARD_ERROR_NOCARD
;
2303 val
= exnor_1st(array_addr
,(len
<<3)+1);
2311 r3
= ~(a
^r2
); //eqv(a,r2)
2312 r1
= (val
|(r3
<<31));
2315 card
->cipher
= bitrev(card
->cipher
);
2318 len
= __card_dummylen();
2319 if(__card_readarrayunlock(chn
,array_addr
,tmp_buffer
,len
+20,1)<0) return CARD_ERROR_NOCARD
;
2321 a
= ((u32
*)tmp_buffer
)[0];
2322 b
= ((u32
*)tmp_buffer
)[1];
2323 c
= ((u32
*)tmp_buffer
)[2];
2324 d
= ((u32
*)tmp_buffer
)[3];
2325 e
= ((u32
*)tmp_buffer
)[4];
2328 val
= exnor(card
->cipher
,32);
2336 r3
= ~(a
^r2
); //eqv(a,r2)
2337 r1
= (val
|(r3
>>31));
2342 val
= exnor(card
->cipher
,32);
2350 r3
= ~(a
^r2
); //eqv(a,r2)
2351 r1
= (val
|(r3
>>31));
2356 val
= exnor(card
->cipher
,32);
2364 r3
= ~(a
^r2
); //eqv(a,r2)
2365 r1
= (val
|(r3
>>31));
2370 val
= exnor(card
->cipher
,32);
2378 r3
= ~(a
^r2
); //eqv(a,r2)
2379 r1
= (val
|(r3
>>31));
2384 val
= exnor(card
->cipher
,(len
<<3));
2392 r3
= ~(a
^r2
); //eqv(a,r2)
2393 r1
= (val
|(r3
>>31));
2397 val
= exnor(card
->cipher
,33);
2405 r3
= ~(a
^r2
); //eqv(a,r2)
2406 r1
= (val
|(r3
>>31));
2412 workarea
[0] = (u32
)cipher1
;
2415 workarea
[3] = (u32
)cipher2
;
2416 DCFlushRange(cipher1
,8);
2417 DCInvalidateRange(cipher2
,4);
2418 DCFlushRange(workarea
,16);
2420 card
->dsp_task
.prio
= 255;
2421 card
->dsp_task
.iram_maddr
= (u16
*)MEM_VIRTUAL_TO_PHYSICAL(_cardunlockdata
);
2422 card
->dsp_task
.iram_len
= 352;
2423 card
->dsp_task
.iram_addr
= 0x0000;
2424 card
->dsp_task
.init_vec
= 16;
2425 card
->dsp_task
.res_cb
= NULL
;
2426 card
->dsp_task
.req_cb
= NULL
;
2427 card
->dsp_task
.init_cb
= __dsp_initcallback
;
2428 card
->dsp_task
.done_cb
= __dsp_donecallback
;
2429 DSP_AddTask(&card
->dsp_task
);
2435 return CARD_ERROR_READY
;
2438 s32
CARD_Init(const char *gamecode
,const char *company
)
2442 if(card_inited
) return CARD_ERROR_READY
;
2444 printf("CARD_Init(%s,%s,%d)\n",gamecode
,company
);
2446 if(gamecode
&& strlen(gamecode
)<=4) memcpy(card_gamecode
,gamecode
,4);
2447 if(company
&& strlen(company
)<=2) memcpy(card_company
,company
,2);
2449 _CPU_ISR_Disable(level
);
2452 memset(cardmap
,0,sizeof(card_block
)*2);
2454 cardmap
[i
].result
= CARD_ERROR_NOCARD
;
2455 LWP_InitQueue(&cardmap
[i
].wait_sync_queue
);
2456 SYS_CreateAlarm(&cardmap
[i
].timeout_svc
);
2458 SYS_RegisterResetFunc(&card_resetinfo
);
2460 _CPU_ISR_Restore(level
);
2461 return CARD_ERROR_READY
;
2464 s32
CARD_Probe(s32 chn
)
2466 return EXI_Probe(chn
);
2469 s32
CARD_ProbeEx(s32 chn
,s32
*mem_size
,s32
*sect_size
)
2473 card_block
*card
= NULL
;
2475 printf("CARD_ProbeEx(%d,%p,%p)\n",chn
,mem_size
,sect_size
);
2477 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_FATAL_ERROR
;
2478 card
= &cardmap
[chn
];
2480 _CPU_ISR_Disable(level
);
2481 ret
= EXI_ProbeEx(chn
);
2483 if(!ret
) ret
= CARD_ERROR_BUSY
;
2484 else ret
= CARD_ERROR_NOCARD
;
2485 _CPU_ISR_Restore(level
);
2489 if(card
->attached
) {
2490 if(card
->mount_step
<1) {
2491 _CPU_ISR_Restore(level
);
2492 return CARD_ERROR_BUSY
;
2494 if(mem_size
) *mem_size
= card
->card_size
;
2495 if(sect_size
) *sect_size
= card
->sector_size
;
2497 _CPU_ISR_Restore(level
);
2498 return CARD_ERROR_READY
;
2501 if(EXI_GetState(chn
)&EXI_FLAG_ATTACH
) ret
= CARD_ERROR_WRONGDEVICE
;
2503 ret
= CARD_ERROR_BUSY
;
2504 if(EXI_GetID(chn
,EXI_DEVICE_0
,&card_id
)) {
2505 if(!__card_iscard(card_id
)) ret
= CARD_ERROR_WRONGDEVICE
;
2507 if(mem_size
) *mem_size
= card_id
&0xFC;
2509 u32 idx
= _ROTL(card_id
,23)&0x1c;
2510 *sect_size
= card_sector_size
[idx
>>2];
2512 ret
= CARD_ERROR_READY
;
2517 _CPU_ISR_Restore(level
);
2521 s32
CARD_MountAsync(s32 chn
,void *workarea
,cardcallback detach_cb
,cardcallback attach_cb
)
2523 s32 ret
= CARD_ERROR_READY
;
2525 cardcallback attachcb
= NULL
;
2526 card_block
*card
= NULL
;
2528 printf("CARD_MountAsync(%d,%p,%p,%p)\n",chn
,workarea
,detach_cb
,attach_cb
);
2530 if(!workarea
) return CARD_ERROR_NOCARD
;
2531 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_FATAL_ERROR
;
2532 card
= &cardmap
[chn
];
2534 _CPU_ISR_Disable(level
);
2536 printf("card->attached = %d,%08x\n",card
->attached
,EXI_GetState(chn
));
2538 if(card
->result
==CARD_ERROR_BUSY
) {
2539 _CPU_ISR_Restore(level
);
2540 return CARD_ERROR_BUSY
;
2542 if(card
->attached
|| !(EXI_GetState(chn
)&EXI_FLAG_ATTACH
)) {
2543 card
->result
= CARD_ERROR_BUSY
;
2544 card
->workarea
= workarea
;
2545 card
->card_ext_cb
= detach_cb
;
2547 attachcb
= attach_cb
;
2548 if(!attachcb
) attachcb
= __card_defaultapicallback
;
2549 card
->card_api_cb
= attachcb
;
2550 card
->card_exi_cb
= NULL
;
2552 if(!card
->attached
) {
2553 if(EXI_Attach(chn
,__card_exthandler
)==0) {
2554 card
->result
= CARD_ERROR_NOCARD
;
2556 printf("card->attached = %d,%08x,attach failed\n",card
->attached
,EXI_GetState(chn
));
2558 _CPU_ISR_Restore(level
);
2559 return CARD_ERROR_NOCARD
;
2562 card
->mount_step
= 0;
2565 printf("card->attached = %d,%08x\n",card
->attached
,EXI_GetState(chn
));
2567 EXI_RegisterEXICallback(chn
,NULL
);
2568 SYS_CancelAlarm(card
->timeout_svc
);
2569 card
->curr_dir
= NULL
;
2570 card
->curr_fat
= NULL
;
2571 _CPU_ISR_Restore(level
);
2573 card
->card_unlock_cb
= __card_mountcallback
;
2574 if(EXI_Lock(chn
,EXI_DEVICE_0
,__card_unlockedhandler
)==0) return 0;
2576 card
->card_unlock_cb
= NULL
;
2577 __card_domount(chn
);
2581 ret
= CARD_ERROR_WRONGDEVICE
;
2582 _CPU_ISR_Restore(level
);
2586 s32
CARD_Mount(s32 chn
,void *workarea
,cardcallback detach_cb
)
2590 printf("CARD_Mount(%d,%p,%p)\n",chn
,workarea
,detach_cb
);
2592 if((ret
=CARD_MountAsync(chn
,workarea
,detach_cb
,__card_synccallback
))>=0) {
2593 ret
= __card_sync(chn
);
2598 s32
CARD_Unmount(s32 chn
)
2601 card_block
*card
= NULL
;
2603 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
2605 if((ret
=__card_getcntrlblock(chn
,&card
))<0) ret
= CARD_ERROR_NOCARD
;
2607 __card_dounmount(chn
,ret
);
2608 return CARD_ERROR_READY
;
2611 s32
CARD_ReadAsync(card_file
*file
,void *buffer
,u32 len
,u32 offset
,cardcallback callback
)
2614 cardcallback cb
= NULL
;
2615 struct card_dat
*dirblock
= NULL
;
2616 card_block
*card
= NULL
;
2618 if(len
<=0 || (len
&0x1ff) || (offset
>0 && (offset
&0x1ff))) return CARD_ERROR_FATAL_ERROR
;
2619 if((ret
=__card_seek(file
,len
,offset
,&card
))<0) return ret
;
2621 dirblock
= __card_getdirblock(card
);
2622 DCInvalidateRange(buffer
,len
);
2625 if(!cb
) cb
= __card_defaultapicallback
;
2626 card
->card_api_cb
= cb
;
2628 if(len
>=(card
->sector_size
-(file
->offset
&(card
->sector_size
-1)))) len
= (card
->sector_size
-(file
->offset
&(card
->sector_size
-1)));
2630 if((ret
=__card_read(file
->chn
,(file
->iblock
*card
->sector_size
),len
,buffer
,__read_callback
))<0) {
2631 __card_putcntrlblock(card
,ret
);
2637 s32
CARD_Read(card_file
*file
,void *buffer
,u32 len
,u32 offset
)
2641 if((ret
=CARD_ReadAsync(file
,buffer
,len
,offset
,__card_synccallback
))>=0) {
2642 ret
= __card_sync(file
->chn
);
2647 s32
CARD_WriteAsync(card_file
*file
,void *buffer
,u32 len
,u32 offset
,cardcallback callback
)
2650 cardcallback cb
= NULL
;
2651 card_block
*card
= NULL
;
2653 if((ret
=__card_seek(file
,len
,offset
,&card
))<0) return ret
;
2654 if(len
<0 || (len
&(card
->sector_size
-1)) || (offset
>0 && offset
&(card
->sector_size
-1))) {
2655 __card_putcntrlblock(card
,CARD_ERROR_FATAL_ERROR
);
2656 return CARD_ERROR_FATAL_ERROR
;
2659 DCStoreRange(buffer
,len
);
2661 if(!cb
) cb
= __card_defaultapicallback
;
2662 card
->card_api_cb
= cb
;
2664 card
->cmd_usr_buf
= buffer
;
2665 if((ret
=__card_sectorerase(file
->chn
,(file
->iblock
*card
->sector_size
),__erase_callback
))>=0) return ret
;
2666 __card_putcntrlblock(card
,ret
);
2670 s32
CARD_Write(card_file
*file
,void *buffer
,u32 len
,u32 offset
)
2674 if((ret
=CARD_WriteAsync(file
,buffer
,len
,offset
,__card_synccallback
))>=0) {
2675 ret
= __card_sync(file
->chn
);
2680 s32
CARD_CreateAsync(s32 chn
,const char *filename
,u32 size
,card_file
*file
,cardcallback callback
)
2684 cardcallback cb
= NULL
;
2685 card_block
*card
= NULL
;
2686 struct card_bat
*fatblock
= NULL
;
2687 struct card_dat
*dirblock
= NULL
;
2688 struct card_direntry
*entry
= NULL
;
2690 printf("CARD_CreateAsync(%d,%s,%d,%p,%p)\n",chn
,filename
,size
,file
,callback
);
2692 len
= strlen(filename
);
2693 if(len
>CARD_FILENAMELEN
) return CARD_ERROR_NAMETOOLONG
;
2695 if((ret
=__card_getcntrlblock(chn
,&card
))<0) return ret
;
2696 if(size
<=0 || size
%card
->sector_size
) return CARD_ERROR_FATAL_ERROR
;
2698 dirblock
= __card_getdirblock(card
);
2701 entry
= dirblock
->entries
;
2702 for(i
=0;i
<CARD_MAXFILES
;i
++) {
2703 if(entry
[i
].gamecode
[0]==0xff) {
2704 if(filenum
==-1) filenum
= i
;
2705 } else if(memcmp(entry
[i
].filename
,filename
,len
)==0) {
2706 if((card_gamecode
[0]==0xff || card_company
[0]==0xff)
2707 || ((card_gamecode
[0]!=0xff && memcmp(entry
[i
].gamecode
,card_gamecode
,4)==0)
2708 && (card_company
[0]!=0xff && memcmp(entry
[i
].company
,card_company
,2)==0))) {
2709 __card_putcntrlblock(card
,CARD_ERROR_EXIST
);
2710 return CARD_ERROR_EXIST
;
2715 __card_putcntrlblock(card
,CARD_ERROR_NOENT
);
2716 return CARD_ERROR_NOENT
;
2719 fatblock
= __card_getbatblock(card
);
2720 if((fatblock
->freeblocks
*card
->sector_size
)<size
) {
2721 __card_putcntrlblock(card
,CARD_ERROR_INSSPACE
);
2722 return CARD_ERROR_INSSPACE
;
2726 if(!cb
) cb
= __card_defaultapicallback
;
2727 card
->card_api_cb
= cb
;
2729 entry
[filenum
].length
= size
/card
->sector_size
;
2730 memset(entry
[filenum
].filename
,0,CARD_FILENAMELEN
);
2731 memcpy(entry
[filenum
].filename
,filename
,len
+1);
2733 card
->curr_file
= file
;
2735 file
->filenum
= filenum
;
2736 if((ret
=__card_allocblock(chn
,(size
/card
->sector_size
),__card_createfatcallback
))<0) {
2737 __card_putcntrlblock(card
,ret
);
2744 s32
CARD_Create(s32 chn
,const char *filename
,u32 size
,card_file
*file
)
2748 if((ret
=CARD_CreateAsync(chn
,filename
,size
,file
,__card_synccallback
))>=0) {
2749 ret
= __card_sync(chn
);
2754 s32
CARD_CreateEntryAsync(s32 chn
,card_dir
*direntry
,card_file
*file
,cardcallback callback
)
2758 cardcallback cb
= NULL
;
2759 card_block
*card
= NULL
;
2760 struct card_bat
*fatblock
= NULL
;
2761 struct card_dat
*dirblock
= NULL
;
2762 struct card_direntry
*entry
= NULL
;
2764 printf("CARD_CreateEntryAsync(%d,%p,%p,%p)\n",chn
,direntry
,file
,callback
);
2766 len
= strlen((const char*)direntry
->filename
);
2767 if(len
>CARD_FILENAMELEN
) return CARD_ERROR_NAMETOOLONG
;
2769 if((ret
=__card_getcntrlblock(chn
,&card
))<0) return ret
;
2770 if(direntry
->filelen
<=0 || direntry
->filelen
%card
->sector_size
) return CARD_ERROR_FATAL_ERROR
;
2772 dirblock
= __card_getdirblock(card
);
2775 entry
= dirblock
->entries
;
2776 for(i
=0;i
<CARD_MAXFILES
;i
++) {
2777 if(entry
[i
].gamecode
[0]==0xff) {
2778 if(filenum
==-1) filenum
= i
;
2779 } else if(memcmp(entry
[i
].filename
,direntry
->filename
,len
)==0) {
2780 if((entry
->gamecode
[0]==0xff || entry
->company
[0]==0xff)
2781 || ((entry
->gamecode
[0]!=0xff && memcmp(entry
[i
].gamecode
,entry
->gamecode
,4)==0)
2782 && (entry
->company
[0]!=0xff && memcmp(entry
[i
].company
,entry
->company
,2)==0))) {
2783 __card_putcntrlblock(card
,CARD_ERROR_EXIST
);
2784 return CARD_ERROR_EXIST
;
2789 __card_putcntrlblock(card
,CARD_ERROR_NOENT
);
2790 return CARD_ERROR_NOENT
;
2793 fatblock
= __card_getbatblock(card
);
2794 if((fatblock
->freeblocks
*card
->sector_size
)<direntry
->filelen
) {
2795 __card_putcntrlblock(card
,CARD_ERROR_INSSPACE
);
2796 return CARD_ERROR_INSSPACE
;
2800 if(!cb
) cb
= __card_defaultapicallback
;
2801 card
->card_api_cb
= cb
;
2803 entry
[filenum
].length
= direntry
->filelen
/card
->sector_size
;
2804 memset(entry
[filenum
].filename
,0,CARD_FILENAMELEN
);
2805 memcpy(entry
[filenum
].filename
,direntry
->filename
,len
+1);
2807 card
->curr_file
= file
;
2809 file
->filenum
= filenum
;
2810 if((ret
=__card_allocblock(chn
,(direntry
->filelen
/card
->sector_size
),__card_createfatcallback
))<0) {
2811 __card_putcntrlblock(card
,ret
);
2818 s32
CARD_CreateEntry(s32 chn
,card_dir
*direntry
,card_file
*file
)
2822 if((ret
=CARD_CreateEntryAsync(chn
,direntry
,file
,__card_synccallback
))>=0) {
2823 ret
= __card_sync(chn
);
2828 s32
CARD_Open(s32 chn
,const char *filename
,card_file
*file
)
2831 struct card_dat
*dirblock
= NULL
;
2832 card_block
*card
= NULL
;
2834 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
2837 if((ret
=__card_getcntrlblock(chn
,&card
))<0) return ret
;
2838 if((ret
=__card_getfilenum(card
,filename
,(const char*)card_gamecode
,(const char*)card_company
,&fileno
))<0) {
2839 __card_putcntrlblock(card
,ret
);
2842 dirblock
= __card_getdirblock(card
);
2843 if(dirblock
->entries
[fileno
].block
<5 || dirblock
->entries
[fileno
].block
>=card
->blocks
) {
2844 __card_putcntrlblock(card
,CARD_ERROR_BROKEN
);
2845 return CARD_ERROR_BROKEN
;
2848 file
->filenum
= fileno
;
2850 file
->len
= dirblock
->entries
[fileno
].length
*card
->sector_size
;
2851 file
->iblock
= dirblock
->entries
[fileno
].block
;
2853 __card_putcntrlblock(card
,CARD_ERROR_READY
);
2854 return CARD_ERROR_READY
;
2857 s32
CARD_OpenEntry(s32 chn
,card_dir
*entry
,card_file
*file
)
2860 struct card_dat
*dirblock
= NULL
;
2861 card_block
*card
= NULL
;
2863 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
2866 if((ret
=__card_getcntrlblock(chn
,&card
))<0) return ret
;
2867 if((ret
=__card_getfilenum(card
,(const char*)entry
->filename
,(const char*)entry
->gamecode
,(const char*)entry
->company
,&fileno
))<0) {
2868 __card_putcntrlblock(card
,ret
);
2872 dirblock
= __card_getdirblock(card
);
2873 if(dirblock
->entries
[fileno
].block
<5 || dirblock
->entries
[fileno
].block
>=card
->blocks
) {
2874 __card_putcntrlblock(card
,CARD_ERROR_BROKEN
);
2875 return CARD_ERROR_BROKEN
;
2879 file
->filenum
= entry
->fileno
;
2881 file
->len
= dirblock
->entries
[fileno
].length
*card
->sector_size
;
2882 file
->iblock
= dirblock
->entries
[fileno
].block
;
2884 __card_putcntrlblock(card
,CARD_ERROR_READY
);
2885 return CARD_ERROR_READY
;
2888 s32
CARD_Close(card_file
*file
)
2891 card_block
*card
= NULL
;
2893 if(file
->chn
<EXI_CHANNEL_0
|| file
->chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
2894 if(file
->filenum
<0 || file
->filenum
>=CARD_MAXFILES
) return CARD_ERROR_NOFILE
;
2895 if((ret
=__card_getcntrlblock(file
->chn
,&card
))<0) return ret
;
2898 __card_putcntrlblock(card
,CARD_ERROR_READY
);
2899 return CARD_ERROR_READY
;
2902 s32
CARD_DeleteAsync(s32 chn
,const char *filename
,cardcallback callback
)
2905 cardcallback cb
= NULL
;
2906 card_block
*card
= NULL
;
2907 struct card_dat
*dirblock
= NULL
;
2908 struct card_direntry
*entry
= NULL
;
2910 printf("CARD_DeleteAsync(%d,%s,%p)\n",chn
,filename
,callback
);
2912 if((ret
=__card_getcntrlblock(chn
,&card
))<0) return ret
;
2913 if((ret
=__card_getfilenum(card
,filename
,(const char*)card_gamecode
,(const char*)card_company
,&fileno
))<0) {
2914 __card_putcntrlblock(card
,ret
);
2918 dirblock
= __card_getdirblock(card
);
2919 entry
= &dirblock
->entries
[fileno
];
2921 card
->curr_fileblock
= entry
->block
;
2922 memset(entry
,-1,sizeof(struct card_direntry
));
2925 if(!cb
) cb
= __card_defaultapicallback
;
2926 card
->card_api_cb
= cb
;
2928 if((ret
=__card_updatedir(chn
,__delete_callback
))>=0) return ret
;
2930 __card_putcntrlblock(card
,ret
);
2934 s32
CARD_Delete(s32 chn
,const char *filename
)
2938 printf("CARD_Delete(%d,%s)\n",chn
,filename
);
2940 if((ret
=CARD_DeleteAsync(chn
,filename
,__card_synccallback
))>=0) {
2941 ret
= __card_sync(chn
);
2946 s32
CARD_DeleteEntryAsync(s32 chn
,card_dir
*dir_entry
,cardcallback callback
)
2949 cardcallback cb
= NULL
;
2950 card_block
*card
= NULL
;
2951 struct card_dat
*dirblock
= NULL
;
2952 struct card_direntry
*entry
= NULL
;
2954 printf("CARD_DeleteEntryAsync(%p,%p)\n",dir_entry
,callback
);
2956 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
2957 if((ret
=__card_getcntrlblock(chn
,&card
))<0) return ret
;
2959 dirblock
= __card_getdirblock(card
);
2960 entry
= &dirblock
->entries
[dir_entry
->fileno
];
2962 card
->curr_fileblock
= entry
->block
;
2963 memset(entry
,-1,sizeof(struct card_direntry
));
2966 if(!cb
) cb
= __card_defaultapicallback
;
2967 card
->card_api_cb
= cb
;
2969 if((ret
=__card_updatedir(chn
,__delete_callback
))>=0) return ret
;
2971 __card_putcntrlblock(card
,ret
);
2975 s32
CARD_DeleteEntry(s32 chn
,card_dir
*dir_entry
)
2979 printf("CARD_DeleteEntry(%p)\n",dir_entry
);
2981 if((ret
=CARD_DeleteEntryAsync(chn
,dir_entry
,__card_synccallback
))>=0) {
2982 ret
= __card_sync(chn
);
2987 s32
CARD_FormatAsync(s32 chn
,cardcallback callback
)
2991 enc
= SYS_GetFontEncoding();
2992 return __card_formatregion(chn
,enc
,callback
);
2995 s32
CARD_Format(s32 chn
)
3000 enc
= SYS_GetFontEncoding();
3001 if((ret
=__card_formatregion(chn
,enc
,__card_synccallback
))>=0) {
3002 ret
= __card_sync(chn
);
3007 s32
CARD_GetErrorCode(s32 chn
)
3009 card_block
*card
= NULL
;
3011 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
3012 card
= &cardmap
[chn
];
3013 return card
->result
;
3016 s32
__card_findnext(card_dir
*dir
)
3019 struct card_dat
*dirblock
= NULL
;
3020 struct card_direntry
*entries
= NULL
;
3021 card_block
*card
= NULL
;
3023 if(dir
->chn
<EXI_CHANNEL_0
|| dir
->chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
3024 if(dir
->fileno
>=CARD_MAXFILES
) return CARD_ERROR_NOFILE
;
3025 if((ret
=__card_getcntrlblock(dir
->chn
,&card
))<0) return ret
;
3027 if(!card
->attached
) return CARD_ERROR_NOCARD
;
3028 dirblock
= __card_getdirblock(card
);
3030 entries
= dirblock
->entries
;
3032 //printf("%s\n", entries[dir->fileno].filename);
3033 if(entries
[dir
->fileno
].gamecode
[0]!=0xff) {
3034 if ((dir
->showall
|| memcmp(entries
[dir
->fileno
].gamecode
,card_gamecode
,4)==0)
3035 && (dir
->showall
|| memcmp(entries
[dir
->fileno
].company
,card_company
,2)==0)) {
3036 dir
->filelen
= entries
[dir
->fileno
].length
*card
->sector_size
;
3037 memcpy(dir
->filename
, entries
[dir
->fileno
].filename
, CARD_FILENAMELEN
);
3038 memcpy(dir
->gamecode
, entries
[dir
->fileno
].gamecode
, 4);
3039 memcpy(dir
->company
, entries
[dir
->fileno
].company
, 2);
3041 __card_putcntrlblock(card
,CARD_ERROR_READY
);
3042 return CARD_ERROR_READY
;
3046 } while (dir
->fileno
< CARD_MAXFILES
);
3047 __card_putcntrlblock(card
,CARD_ERROR_NOFILE
);
3048 return CARD_ERROR_NOFILE
;
3051 s32
CARD_FindFirst(s32 chn
, card_dir
*dir
, bool showall
)
3053 // initialise structure
3057 dir
->filename
[0] = 0;
3058 dir
->gamecode
[0] = 0;
3059 dir
->company
[0] = 0;
3060 dir
->showall
= showall
;
3061 return __card_findnext(dir
);
3064 s32
CARD_FindNext(card_dir
*dir
)
3068 return __card_findnext(dir
);
3071 s32
CARD_GetDirectory(s32 chn
,card_dir
*dir_entries
,s32
*count
,bool showall
)
3074 s32 ret
= CARD_ERROR_READY
;
3075 struct card_dat
*dirblock
= NULL
;
3076 struct card_direntry
*entries
= NULL
;
3077 card_block
*card
= NULL
;
3079 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
3080 if((ret
=__card_getcntrlblock(chn
,&card
))<0) return ret
;
3082 if(!card
->attached
) return CARD_ERROR_NOCARD
;
3083 dirblock
= __card_getdirblock(card
);
3085 entries
= dirblock
->entries
;
3086 for(i
=0,cnt
=0;i
<CARD_MAXFILES
;i
++) {
3087 if(entries
[i
].gamecode
[0]!=0xff) {
3088 if(showall
|| ((card_gamecode
[0]!=0xff && memcmp(entries
[i
].gamecode
,card_gamecode
,4)==0)
3089 && (card_company
[0]!=0xff && memcmp(entries
[i
].company
,card_company
,2)==0))) {
3090 dir_entries
[cnt
].fileno
= i
;
3091 dir_entries
[cnt
].permissions
= entries
[i
].permission
;
3092 dir_entries
[cnt
].filelen
= entries
[i
].length
*card
->sector_size
;
3093 memcpy(dir_entries
[cnt
].gamecode
,entries
[i
].gamecode
,4);
3094 memcpy(dir_entries
[cnt
].company
,entries
[i
].company
,2);
3095 memcpy(dir_entries
[cnt
].filename
,entries
[i
].filename
,CARD_FILENAMELEN
);
3100 if(count
) *count
= cnt
;
3101 if(cnt
==0) ret
= CARD_ERROR_NOFILE
;
3102 __card_putcntrlblock(card
,ret
);
3106 s32
CARD_GetSectorSize(s32 chn
,u32
*sector_size
)
3109 card_block
*card
= NULL
;
3111 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
3112 if((ret
=__card_getcntrlblock(chn
,&card
))<0) return ret
;
3114 *sector_size
= card
->sector_size
;
3115 ret
= __card_putcntrlblock(card
,CARD_ERROR_READY
);
3120 s32
CARD_GetBlockCount(s32 chn
,u32
*block_count
)
3123 card_block
*card
= NULL
;
3125 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
3126 if((ret
=__card_getcntrlblock(chn
,&card
))<0) return ret
;
3128 *block_count
= card
->blocks
;
3129 ret
= __card_putcntrlblock(card
,CARD_ERROR_READY
);
3134 s32
CARD_GetStatus(s32 chn
,s32 fileno
,card_stat
*stats
)
3137 card_block
*card
= NULL
;
3138 struct card_dat
*dirblock
= NULL
;
3139 struct card_direntry
*entry
= NULL
;
3141 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
3142 if(fileno
<0 || fileno
>=CARD_MAXFILES
) return CARD_ERROR_FATAL_ERROR
;
3144 if((ret
=__card_getcntrlblock(chn
,&card
))<0) return ret
;
3146 dirblock
= __card_getdirblock(card
);
3148 entry
= &dirblock
->entries
[fileno
];
3149 memcpy(stats
->gamecode
,entry
->gamecode
,4);
3150 memcpy(stats
->company
,entry
->company
,2);
3151 memcpy(stats
->filename
,entry
->filename
,CARD_FILENAMELEN
);
3152 stats
->len
= entry
->length
*card
->sector_size
;
3153 stats
->time
= entry
->lastmodified
;
3154 stats
->banner_fmt
= entry
->bannerfmt
;
3155 stats
->icon_addr
= entry
->iconaddr
;
3156 stats
->icon_fmt
= entry
->iconfmt
;
3157 stats
->icon_speed
= entry
->iconspeed
;
3158 stats
->comment_addr
= entry
->commentaddr
;
3159 __card_updateiconoffsets(entry
,stats
);
3162 return __card_putcntrlblock(card
,CARD_ERROR_READY
);
3165 s32
CARD_SetStatusAsync(s32 chn
,s32 fileno
,card_stat
*stats
,cardcallback callback
)
3168 card_block
*card
= NULL
;
3169 struct card_dat
*dirblock
= NULL
;
3170 struct card_direntry
*entry
= NULL
;
3172 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
3173 if(fileno
<0 || fileno
>=CARD_MAXFILES
) return CARD_ERROR_FATAL_ERROR
;
3174 if(stats
->icon_addr
!=-1 && stats
->icon_addr
>CARD_READSIZE
) return CARD_ERROR_FATAL_ERROR
;
3175 if(stats
->comment_addr
!=-1 && stats
->comment_addr
>8128) return CARD_ERROR_FATAL_ERROR
;
3176 if((ret
=__card_getcntrlblock(chn
,&card
))<0) return ret
;
3178 ret
= CARD_ERROR_BROKEN
;
3179 dirblock
= __card_getdirblock(card
);
3181 entry
= &dirblock
->entries
[fileno
];
3182 entry
->bannerfmt
= stats
->banner_fmt
;
3183 entry
->iconaddr
= stats
->icon_addr
;
3184 entry
->iconfmt
= stats
->icon_fmt
;
3185 entry
->iconspeed
= stats
->icon_speed
;
3186 entry
->commentaddr
= stats
->comment_addr
;
3187 __card_updateiconoffsets(entry
,stats
);
3189 if(entry
->iconaddr
==-1) entry
->iconfmt
= ((entry
->iconfmt
&~CARD_ICON_MASK
)|CARD_ICON_CI
);
3191 entry
->lastmodified
= time(NULL
);
3192 if((ret
=__card_updatedir(chn
,callback
))>=0) return ret
;
3195 return __card_putcntrlblock(card
,ret
);
3198 s32
CARD_SetStatus(s32 chn
,s32 fileno
,card_stat
*stats
)
3202 if((ret
=CARD_SetStatusAsync(chn
,fileno
,stats
,__card_synccallback
))>=0) {
3203 ret
= __card_sync(chn
);
3208 s32
CARD_GetAttributes(s32 chn
,s32 fileno
,u8
*attr
)
3211 struct card_direntry entry
;
3213 if((ret
=__card_getstatusex(chn
,fileno
,&entry
))==CARD_ERROR_READY
) {
3214 *attr
= entry
.permission
;
3219 s32
CARD_SetAttributesAsync(s32 chn
,s32 fileno
,u8 attr
,cardcallback callback
)
3222 struct card_direntry entry
;
3224 if((ret
=__card_getstatusex(chn
,fileno
,&entry
))>=0) {
3225 entry
.permission
= attr
;
3226 ret
= __card_setstatusexasync(chn
,fileno
,&entry
,callback
);
3231 s32
CARD_SetAttributes(s32 chn
,s32 fileno
,u8 attr
)
3235 if((ret
=CARD_SetAttributesAsync(chn
,fileno
,attr
,__card_synccallback
))>=0) {
3236 ret
= __card_sync(chn
);
3241 s32
CARD_SetCompany(const char *company
)
3245 _CPU_ISR_Disable(level
);
3246 for(i
=0;i
<2;i
++) card_company
[i
] = 0xff;
3247 if(company
&& strlen(company
)<=2) memcpy(card_company
,company
,2) ;
3248 _CPU_ISR_Restore(level
);
3250 return CARD_ERROR_READY
;
3253 s32
CARD_SetGamecode(const char *gamecode
)
3257 _CPU_ISR_Disable(level
);
3258 for(i
=0;i
<4;i
++) card_gamecode
[i
] = 0xff;
3259 if(gamecode
&& strlen(gamecode
)<=4) memcpy(card_gamecode
,gamecode
,4) ;
3260 _CPU_ISR_Restore(level
);
3262 return CARD_ERROR_READY
;