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
;
150 static u32 _cardunlockdata
[0x160] ATTRIBUTE_ALIGN(32) =
152 0x00000000,0x00000000,0x00000000,0x00000000,
153 0x00000000,0x00000000,0x00000021,0x02ff0021,
154 0x13061203,0x12041305,0x009200ff,0x0088ffff,
155 0x0089ffff,0x008affff,0x008bffff,0x8f0002bf,
156 0x008816fc,0xdcd116fd,0x000016fb,0x000102bf,
157 0x008e25ff,0x0380ff00,0x02940027,0x02bf008e,
158 0x1fdf24ff,0x02400fff,0x00980400,0x009a0010,
159 0x00990000,0x8e0002bf,0x009402bf,0x864402bf,
160 0x008816fc,0xdcd116fd,0x000316fb,0x00018f00,
161 0x02bf008e,0x0380cdd1,0x02940048,0x27ff0380,
162 0x00010295,0x005a0380,0x00020295,0x8000029f,
163 0x00480021,0x8e0002bf,0x008e25ff,0x02bf008e,
164 0x25ff02bf,0x008e25ff,0x02bf008e,0x00c5ffff,
165 0x03400fff,0x1c9f02bf,0x008e00c7,0xffff02bf,
166 0x008e00c6,0xffff02bf,0x008e00c0,0xffff02bf,
167 0x008e20ff,0x03400fff,0x1f5f02bf,0x008e21ff,
168 0x02bf008e,0x23ff1205,0x1206029f,0x80b50021,
169 0x27fc03c0,0x8000029d,0x008802df,0x27fe03c0,
170 0x8000029c,0x008e02df,0x2ece2ccf,0x00f8ffcd,
171 0x00f9ffc9,0x00faffcb,0x26c902c0,0x0004029d,
172 0x009c02df,0x00000000,0x00000000,0x00000000,
173 0x00000000,0x00000000,0x00000000,0x00000000
176 static u32 card_sector_size
[] =
188 static u32 card_latency
[] =
200 static u32 card_inited
= 0;
201 static u32 crand_next
= 1;
203 static u8 card_gamecode
[4] = {0xff,0xff,0xff,0xff};
204 static u8 card_company
[2] = {0xff,0xff};
205 static card_block cardmap
[2];
207 static void __card_mountcallback(s32 chn
,s32 result
);
208 static void __erase_callback(s32 chn
,s32 result
);
209 static s32
__dounlock(s32 chn
,u32
*key
);
210 static s32
__card_readsegment(s32 chn
,cardcallback callback
);
211 static s32
__card_read(s32 chn
,u32 address
,u32 block_len
,void *buffer
,cardcallback callback
);
212 static s32
__card_updatefat(s32 chn
,struct card_bat
*fatblock
,cardcallback callback
);
213 static s32
__card_updatedir(s32 chn
,cardcallback callback
);
214 static s32
__card_write(s32 chn
,u32 address
,u32 block_len
,void *buffer
,cardcallback callback
);
215 static s32
__card_writepage(s32 chn
,cardcallback callback
);
216 static s32
__card_sectorerase(s32 chn
,u32 sector
,cardcallback callback
);
217 static s32
__card_onreset(s32 final
);
219 static sys_resetinfo card_resetinfo
= {
225 extern unsigned long gettick();
226 extern long long gettime();
227 extern syssram
* __SYS_LockSram();
228 extern syssramex
* __SYS_LockSramEx();
229 extern u32
__SYS_UnlockSram(u32 write
);
230 extern u32
__SYS_UnlockSramEx(u32 write
);
232 static vu16
* const _viReg
= (u16
*)0xCC002000;
235 static s32
__card_onreset(s32 final
)
238 if(CARD_Unmount(CARD_SLOTA
)==-1) return 0;
239 if(CARD_Unmount(CARD_SLOTB
)==-1) return 0;
244 static void __card_checksum(u16
*buff
,u32 len
,u16
*cs1
,u16
*cs2
)
248 printf("__card_checksum(%p,%d,%p,%p)\n",buff
,len
,cs1
,cs2
);
253 for (i
= 0; i
< len
; ++i
) {
255 *cs2
+= (buff
[i
] ^ 0xffff);
257 if (*cs1
== 0xffff) *cs1
= 0;
258 if (*cs2
== 0xffff) *cs2
= 0;
261 static s32
__card_putcntrlblock(card_block
*card
,s32 result
)
265 _CPU_ISR_Disable(level
);
266 if(card
->attached
) card
->result
= result
;
267 else if(card
->result
==CARD_ERROR_BUSY
) card
->result
= result
;
268 _CPU_ISR_Restore(level
);
272 static s32
__card_getcntrlblock(s32 chn
,card_block
**card
)
276 card_block
*rcard
= NULL
;
278 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_FATAL_ERROR
;
280 _CPU_ISR_Disable(level
);
281 rcard
= &cardmap
[chn
];
282 if(!rcard
->attached
) {
283 _CPU_ISR_Restore(level
);
284 return CARD_ERROR_NOCARD
;
287 ret
= CARD_ERROR_BUSY
;
288 if(rcard
->result
!=CARD_ERROR_BUSY
) {
289 rcard
->result
= CARD_ERROR_BUSY
;
290 rcard
->card_api_cb
= NULL
;
292 ret
= CARD_ERROR_READY
;
294 _CPU_ISR_Restore(level
);
298 static __inline__
struct card_dat
* __card_getdirblock(card_block
*card
)
300 return card
->curr_dir
;
303 static __inline__
struct card_bat
* __card_getbatblock(card_block
*card
)
305 return card
->curr_fat
;
308 static s32
__card_sync(s32 chn
)
312 card_block
*card
= &cardmap
[chn
];
314 _CPU_ISR_Disable(level
);
315 while((ret
=CARD_GetErrorCode(chn
))==CARD_ERROR_BUSY
) {
316 LWP_ThreadSleep(card
->wait_sync_queue
);
318 _CPU_ISR_Restore(level
);
322 static void __card_synccallback(s32 chn
,s32 result
)
325 card_block
*card
= &cardmap
[chn
];
327 printf("__card_synccallback(%d,%d,%d)\n",chn
,result
,card
->result
);
329 _CPU_ISR_Disable(level
);
330 LWP_ThreadBroadcast(card
->wait_sync_queue
);
331 _CPU_ISR_Restore(level
);
334 static void __card_updateiconoffsets(struct card_direntry
*entry
,card_stat
*stats
)
338 u32 iconaddr
,iconbase
;
340 iconaddr
= entry
->iconaddr
;
342 stats
->banner_fmt
= 0;
344 stats
->icon_speed
= 0;
348 if(entry
->bannerfmt
&CARD_BANNER_MASK
) {
349 if(!(entry
->bannerfmt
&0x10)) {
350 bnrfmt
= (entry
->bannerfmt
&CARD_BANNER_MASK
);
351 if(bnrfmt
==CARD_BANNER_CI
) {
352 stats
->banner_fmt
= bnrfmt
;
353 stats
->offset_banner
= iconaddr
;
354 stats
->offset_banner_tlut
= iconaddr
+3072;
355 iconaddr
+= (3072+512);
356 } else if(bnrfmt
==CARD_BANNER_RGB
) {
357 stats
->banner_fmt
= bnrfmt
;
358 stats
->offset_banner
= iconaddr
;
359 stats
->offset_banner_tlut
= -1;
363 stats
->offset_banner
= -1;
364 stats
->offset_banner_tlut
= -1;
369 for(i
=0;i
<CARD_MAXICONS
;i
++) {
370 stats
->iconfmt
[i
] = ((entry
->iconfmt
>>(i
<<1))&CARD_ICON_MASK
);
371 stats
->iconspeed
[i
] = ((entry
->iconspeed
>>(i
<<1))&CARD_SPEED_MASK
);
372 if(stats
->iconspeed
[i
]==0) stats
->iconfmt
[i
] = 0;
373 if(stats
->iconfmt
[i
]) nicons
++;
377 for(i
=0;i
<CARD_MAXICONS
;i
++) {
378 switch(stats
->iconfmt
[i
]) {
379 case 1: //CARD_ICON_CI with shared palette
380 stats
->offset_icon
[i
] = iconaddr
;
381 stats
->offset_icon_tlut
[i
] = iconbase
+ (nicons
*1024);
384 case 2: //CARD_ICON_RGB
385 stats
->offset_icon
[i
] = iconaddr
;
386 stats
->offset_icon_tlut
[i
] = -1;
389 case 3: //CARD_ICON_CI with own palette
390 stats
->offset_icon
[i
] = iconaddr
;
391 stats
->offset_icon_tlut
[i
] = iconaddr
+ 1024;
394 default: //CARD_ICON_NONE
395 stats
->offset_icon
[i
] = -1;
396 stats
->offset_icon_tlut
[i
] = -1;
402 // stats->offset_data = iconaddr;
405 static s32
__card_getstatusex(s32 chn
,s32 fileno
,struct card_direntry
*entry
)
408 card_block
*card
= NULL
;
409 struct card_dat
*dirblock
= NULL
;
411 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
412 if(fileno
<0 || fileno
>=CARD_MAXFILES
) return CARD_ERROR_FATAL_ERROR
;
413 if((ret
=__card_getcntrlblock(chn
,&card
))<0) return ret
;
415 ret
= CARD_ERROR_BROKEN
;
416 dirblock
= __card_getdirblock(card
);
418 ret
= CARD_ERROR_READY
;
419 memcpy(entry
,&dirblock
->entries
[fileno
],sizeof(struct card_direntry
));
421 return __card_putcntrlblock(card
,ret
);
424 static s32
__card_setstatusexasync(s32 chn
,s32 fileno
,struct card_direntry
*entry
,cardcallback callback
)
427 card_block
*card
= NULL
;
428 struct card_dat
*dirblock
= NULL
;
429 struct card_direntry
*entries
= NULL
;
431 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
432 if(fileno
<0 || fileno
>=CARD_MAXFILES
) return CARD_ERROR_FATAL_ERROR
;
433 if(entry
->filename
[0]==0xff || entry
->filename
[0]==0) return CARD_ERROR_FATAL_ERROR
;
434 if((ret
=__card_getcntrlblock(chn
,&card
))<0) return ret
;
436 ret
= CARD_ERROR_BROKEN
;
437 dirblock
= __card_getdirblock(card
);
440 ret
= CARD_ERROR_READY
;
441 entries
= dirblock
->entries
;
442 while(i
<CARD_FILENAMELEN
) {
443 if(bend
|| entry
->filename
[i
]==0) {
444 entry
->filename
[i
] = 0;
450 if(memcmp(entries
[fileno
].filename
,entry
->filename
,CARD_FILENAMELEN
)
451 || memcmp(entries
[fileno
].gamecode
,entry
->gamecode
,4)
452 || memcmp(entries
[fileno
].company
,entry
->company
,2)) {
454 while(i
<CARD_MAXFILES
) {
455 if(i
!=fileno
&& entries
[i
].gamecode
[0]!=0xff
456 && memcmp(entries
[i
].gamecode
,entry
->gamecode
,4)==0
457 && memcmp(entries
[i
].company
,entry
->company
,2)==0
458 && memcmp(entries
[i
].filename
,entry
->filename
,CARD_FILENAMELEN
)==0) {
459 return __card_putcntrlblock(card
,CARD_ERROR_EXIST
);
463 memcpy(entries
[fileno
].filename
,entry
->filename
,CARD_FILENAMELEN
);
464 memcpy(entries
[fileno
].gamecode
,entry
->gamecode
,4);
465 memcpy(entries
[fileno
].company
,entry
->company
,2);
468 entries
[fileno
].lastmodified
= entry
->lastmodified
;
469 entries
[fileno
].bannerfmt
= entry
->bannerfmt
;
470 entries
[fileno
].iconaddr
= entry
->iconaddr
;
471 entries
[fileno
].iconfmt
= entry
->iconfmt
;
472 entries
[fileno
].iconspeed
= entry
->iconspeed
;
473 entries
[fileno
].commentaddr
= entry
->commentaddr
;
474 entries
[fileno
].permission
= entry
->permission
;
475 entries
[fileno
].copytimes
= entry
->copytimes
;
477 if((ret
=__card_updatedir(chn
,callback
))>=0) return ret
;
479 return __card_putcntrlblock(card
,ret
);
482 static s32
__card_setstatusex(s32 chn
,s32 fileno
,struct card_direntry
*entry
)
486 if((ret
=__card_setstatusexasync(chn
,fileno
,entry
,__card_synccallback
))>=0) {
487 ret
= __card_sync(chn
);
492 static s32
__card_getfilenum(card_block
*card
,const char *filename
,const char *gamecode
,const char *company
,s32
*fileno
)
495 struct card_direntry
*entries
= NULL
;
496 struct card_dat
*dirblock
= NULL
;
498 printf("__card_getfilenum(%p,%s,%s,%s)\n",card
,filename
,gamecode
,company
);
500 if(!card
->attached
) return CARD_ERROR_NOCARD
;
501 dirblock
= __card_getdirblock(card
);
503 entries
= dirblock
->entries
;
504 for(i
=0;i
<CARD_MAXFILES
;i
++) {
505 if(entries
[i
].gamecode
[0]!=0xff) {
506 if(strnicmp((const char*)entries
[i
].filename
,filename
,strlen(filename
))==0) {
507 if((gamecode
&& gamecode
[0]!=0xff && memcmp(entries
[i
].gamecode
,gamecode
,4)!=0)
508 || (company
&& company
[0]!=0xff && memcmp(entries
[i
].company
,company
,2)!=0)) continue;
515 if(i
>=CARD_MAXFILES
) return CARD_ERROR_NOFILE
;
516 return CARD_ERROR_READY
;
519 static s32
__card_seek(card_file
*file
,s32 len
,s32 offset
,card_block
**rcard
)
523 card_block
*card
= NULL
;
524 struct card_direntry
*entry
= NULL
;
525 struct card_dat
*dirblock
= NULL
;
526 struct card_bat
*fatblock
= NULL
;
528 printf("__card_seek(%d,%p,%d,%d)\n",file
->filenum
,file
,len
,offset
);
530 if(file
->filenum
<0 || file
->filenum
>=CARD_MAXFILES
) return CARD_ERROR_FATAL_ERROR
;
531 if((ret
=__card_getcntrlblock(file
->chn
,&card
))<0) return ret
;
533 printf("__card_seek(%d)\n",file
->iblock
);
535 if(file
->iblock
<CARD_SYSAREA
|| file
->iblock
>=card
->blocks
) {
536 __card_putcntrlblock(card
,CARD_ERROR_FATAL_ERROR
);
537 return CARD_ERROR_FATAL_ERROR
;
540 dirblock
= __card_getdirblock(card
);
541 entry
= &dirblock
->entries
[file
->filenum
];
543 printf("__card_seek(%p,%d)\n",entry
,file
->filenum
);
545 if(entry
->gamecode
[0]!=0xff) {
546 entry_len
= entry
->length
*card
->sector_size
;
547 if(entry_len
<offset
|| entry_len
<(offset
+len
)) {
548 __card_putcntrlblock(card
,CARD_ERROR_LIMIT
);
549 return CARD_ERROR_LIMIT
;
551 card
->curr_file
= file
;
554 if(offset
<file
->offset
) {
556 file
->iblock
= entry
->block
;
557 if(file
->iblock
<CARD_SYSAREA
|| file
->iblock
>=card
->blocks
) {
558 __card_putcntrlblock(card
,CARD_ERROR_BROKEN
);
559 return CARD_ERROR_BROKEN
;
563 fatblock
= __card_getbatblock(card
);
564 for(i
=file
->iblock
;i
<card
->blocks
&& file
->offset
<(offset
&~(card
->sector_size
-1));i
=file
->iblock
) {
565 file
->offset
+= card
->sector_size
;
566 file
->iblock
= fatblock
->fat
[i
-CARD_SYSAREA
];
567 if(file
->iblock
<CARD_SYSAREA
|| file
->iblock
>=card
->blocks
) {
568 __card_putcntrlblock(card
,CARD_ERROR_BROKEN
);
569 return CARD_ERROR_BROKEN
;
572 file
->offset
= offset
;
575 return CARD_ERROR_READY
;
578 static u32
__card_checkdir(card_block
*card
,u32
*currdir
)
582 struct card_dircntrl
*dircntrl
[2];
583 struct card_dat
*dirblock
[2];
585 printf("__card_checkdir(%p,%p)\n",card
,currdir
);
591 dirblock
[dir
] = card
->workarea
+((dir
+1)<<13);
592 dircntrl
[dir
] = (card
->workarea
+((dir
+1)<<13))+8128;
593 __card_checksum((u16
*)dirblock
[dir
],0x1ffc,&chksum0
,&chksum1
);
594 if(chksum0
!=dircntrl
[dir
]->chksum1
|| chksum1
!=dircntrl
[dir
]->chksum2
) {
596 printf("__card_checkdir(bad checksums: (%04x : %04x),(%04x : %04x)\n",chksum0
,dircntrl
[dir
]->chksum1
,chksum1
,dircntrl
[dir
]->chksum2
);
598 card
->curr_dir
= NULL
;
607 if(dircntrl
[0]->updated
<dircntrl
[1]->updated
) dir
= 0;
610 if(card
->curr_dir
==NULL
) {
611 card
->curr_dir
= dirblock
[dir
];
612 memcpy(dirblock
[dir
],dirblock
[dir
^1],8192);
614 else if(card
->curr_dir
==dirblock
[0]) dir
= 0;
617 if(currdir
) *currdir
= dir
;
621 static u32
__card_checkfat(card_block
*card
,u32
*currfat
)
625 struct card_bat
*fatblock
[2];
627 printf("__card_checkfat(%p,%p)\n",card
,currfat
);
633 fatblock
[fat
] = card
->workarea
+((fat
+3)<<13);
634 __card_checksum((u16
*)(((u32
)fatblock
[fat
])+4),0x1ffc,&chksum0
,&chksum1
);
635 if(chksum0
!=fatblock
[fat
]->chksum1
|| chksum1
!=fatblock
[fat
]->chksum2
) {
637 printf("__card_checkfat(bad checksums: (%04x : %04x),(%04x : %04x)\n",chksum0
,fatblock
[fat
]->chksum1
,chksum1
,fatblock
[fat
]->chksum2
);
639 card
->curr_fat
= NULL
;
643 u16 curblock
= CARD_SYSAREA
;
645 while(curblock
<card
->blocks
) {
646 if(!fatblock
[fat
]->fat
[curblock
-CARD_SYSAREA
]) freeblocks
++;
649 if(freeblocks
!=fatblock
[fat
]->freeblocks
) {
651 printf("__card_checkfat(freeblocks!=fatblock[fat]->freeblocks (%d : %d))\n",freeblocks
,fatblock
[fat
]->freeblocks
);
653 card
->curr_fat
= NULL
;
663 if(fatblock
[0]->updated
<fatblock
[1]->updated
) fat
= 0;
666 if(card
->curr_fat
==NULL
) {
667 card
->curr_fat
= fatblock
[fat
];
668 memcpy(fatblock
[fat
],fatblock
[fat
^1],8192);
670 else if(card
->curr_fat
==fatblock
[0]) fat
= 0;
673 if(currfat
) *currfat
= fat
;
677 static s32
__card_verify(card_block
*card
)
681 ret
+= __card_checkdir(card
,NULL
);
682 ret
+= __card_checkfat(card
,NULL
);
684 printf("__card_verify(%d)\n",ret
);
687 if(card
->curr_dir
&& card
->curr_fat
) return CARD_ERROR_READY
;
689 return CARD_ERROR_BROKEN
;
692 static u32
__card_iscard(u32 id
)
697 if(id
&~0xffff) return 0;
698 if(id
&0x03) return 0;
702 if(tmp
==EXI_MEMCARD59
|| tmp
==EXI_MEMCARD123
703 || tmp
==EXI_MEMCARD251
|| tmp
==EXI_MEMCARD507
704 || tmp
==EXI_MEMCARD1019
|| tmp
==EXI_MEMCARD2043
) {
705 idx
= _ROTL(id
,23)&0x1c;
706 if((secsize
=card_sector_size
[idx
>>2])==0) return 0;
707 tmp
= ((tmp
<<20)&0x1FFE0000)/secsize
;
713 static s32
__card_allocblock(s32 chn
,u32 blocksneed
,cardcallback callback
)
716 u16 block
,currblock
= 0,prevblock
= 0;
718 card_block
*card
= NULL
;
719 struct card_bat
*fatblock
= NULL
;
721 printf("__card_allocblock(%d,%d,%p)\n",chn
,blocksneed
,callback
);
723 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_FATAL_ERROR
;
724 card
= &cardmap
[chn
];
726 if(!card
->attached
) return CARD_ERROR_NOCARD
;
727 fatblock
= __card_getbatblock(card
);
729 printf("__card_allocblock(%p,%d)\n",fatblock
,fatblock
->freeblocks
);
732 if(fatblock
->freeblocks
<blocksneed
) return CARD_ERROR_INSSPACE
;
734 // Add which blocks this file will take up into the FAT
737 currblock
= fatblock
->lastalloc
;
741 // Done allocating blocks
743 printf("__card_allocblock(%d : %d)\n",block
,currblock
);
745 fatblock
->freeblocks
-= blocksneed
;
746 fatblock
->lastalloc
= currblock
;
747 card
->curr_fileblock
= block
;
748 ret
= __card_updatefat(chn
,fatblock
,callback
);
753 Since testing free space has already been done, if all the blocks
754 the file takes up cannot be entered into the FAT, something is
758 if(count
>=(card
->blocks
-CARD_SYSAREA
)) return CARD_ERROR_BROKEN
;
761 if(currblock
<CARD_SYSAREA
|| currblock
>=card
->blocks
) currblock
= CARD_SYSAREA
;
762 if(fatblock
->fat
[currblock
-CARD_SYSAREA
]==0) {
764 fatblock
->fat
[prevblock
-CARD_SYSAREA
] = currblock
;
768 fatblock
->fat
[currblock
-CARD_SYSAREA
] = 0xffff;
769 prevblock
= currblock
;
776 static s32
__card_freeblock(s32 chn
,u16 block
,cardcallback callback
)
778 u16 next
= 0xffff,prev
= 0xffff;
779 card_block
*card
= NULL
;
780 struct card_bat
*fatblock
= NULL
;
782 printf("__card_freeblock(%d,%d,%p)\n",chn
,block
,callback
);
784 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
785 card
= &cardmap
[chn
];
787 if(!card
->attached
) return CARD_ERROR_NOCARD
;
789 fatblock
= __card_getbatblock(card
);
790 next
= fatblock
->fat
[block
-CARD_SYSAREA
];
792 if(next
==0xffff) break;
793 if(next
<CARD_SYSAREA
|| next
>=card
->blocks
) return CARD_ERROR_BROKEN
;
795 // Get the file's next block and clear the previous one from the fat
797 next
= fatblock
->fat
[prev
-CARD_SYSAREA
];
798 fatblock
->fat
[prev
-CARD_SYSAREA
] = 0;
799 fatblock
->freeblocks
++;
801 return __card_updatefat(chn
,fatblock
,callback
);
804 static s32
__card_unlockedhandler(s32 chn
,s32 dev
)
807 cardcallback cb
= NULL
;
808 card_block
*card
= NULL
;
810 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
811 card
= &cardmap
[chn
];
813 ret
= CARD_ERROR_READY
;
814 cb
= card
->card_unlock_cb
;
816 card
->card_unlock_cb
= NULL
;
817 if(EXI_Probe(chn
)==0) ret
= CARD_ERROR_NOCARD
;
820 return CARD_ERROR_UNLOCKED
;
823 static s32
__card_readstatus(s32 chn
,u8
*pstatus
)
829 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
830 if(EXI_Select(chn
,EXI_DEVICE_0
,EXI_SPEED16MHZ
)==0) return CARD_ERROR_NOCARD
;
833 val
[0] = 0x83; val
[1] = 0x00;
834 if(EXI_Imm(chn
,val
,2,EXI_WRITE
,NULL
)==0) err
|= 0x01;
835 if(EXI_Sync(chn
)==0) err
|= 0x02;
836 if(EXI_Imm(chn
,pstatus
,1,EXI_READ
,NULL
)==0) err
|= 0x04;
837 if(EXI_Sync(chn
)==0) err
|= 0x08;
838 if(EXI_Deselect(chn
)==0) err
|= 0x10;
840 if(err
) ret
= CARD_ERROR_NOCARD
;
841 else ret
= CARD_ERROR_READY
;
843 printf("__card_readstatus(%d,%08x)\n",chn
,*pstatus
);
848 static s32
__card_clearstatus(s32 chn
)
854 printf("__card_clearstatus(%d)\n",chn
);
856 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
857 if(EXI_Select(chn
,EXI_DEVICE_0
,EXI_SPEED16MHZ
)==0) return CARD_ERROR_NOCARD
;
861 if(EXI_Imm(chn
,&val
,1,EXI_WRITE
,NULL
)==0) err
|= 0x01;
862 if(EXI_Sync(chn
)==0) err
|= 0x02;
863 if(EXI_Deselect(chn
)==0) err
|= 0x04;
865 if(err
) ret
= CARD_ERROR_NOCARD
;
866 else ret
= CARD_ERROR_READY
;
871 static s32
__card_sleep(s32 chn
)
877 printf("__card_sleep(%d)\n",chn
);
879 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
880 if(EXI_Select(chn
,EXI_DEVICE_0
,EXI_SPEED16MHZ
)==0) return CARD_ERROR_NOCARD
;
884 if(EXI_Imm(chn
,&val
,1,EXI_WRITE
,NULL
)==0) err
|= 0x01;
885 if(EXI_Sync(chn
)==0) err
|= 0x02;
886 if(EXI_Deselect(chn
)==0) err
|= 0x04;
888 if(err
) ret
= CARD_ERROR_NOCARD
;
889 else ret
= CARD_ERROR_READY
;
894 static s32
__card_wake(s32 chn
)
900 printf("__card_wake(%d)\n",chn
);
903 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
904 if(EXI_Select(chn
,EXI_DEVICE_0
,EXI_SPEED16MHZ
)==0) return CARD_ERROR_NOCARD
;
908 if(EXI_Imm(chn
,&val
,1,EXI_WRITE
,NULL
)==0) err
|= 0x01;
909 if(EXI_Sync(chn
)==0) err
|= 0x02;
910 if(EXI_Deselect(chn
)==0) err
|= 0x04;
912 if(err
) ret
= CARD_ERROR_NOCARD
;
913 else ret
= CARD_ERROR_READY
;
918 static s32
__card_enableinterrupt(s32 chn
,u32 enable
)
924 printf("__card_enableinterrupt(%d,%d)\n",chn
,enable
);
927 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
928 if(EXI_Select(chn
,EXI_DEVICE_0
,EXI_SPEED16MHZ
)==0) return CARD_ERROR_NOCARD
;
932 if(enable
) val
[1] = 0x01;
934 if(EXI_Imm(chn
,val
,2,EXI_WRITE
,NULL
)==0) err
|= 0x01;
935 if(EXI_Sync(chn
)==0) err
|= 0x02;
936 if(EXI_Deselect(chn
)==0) err
|= 0x04;
938 if(err
) ret
= CARD_ERROR_BUSY
;
939 else ret
= CARD_ERROR_READY
;
944 static s32
__card_txhandler(s32 chn
,s32 dev
)
947 s32 ret
= CARD_ERROR_READY
;
948 cardcallback cb
= NULL
;
949 card_block
*card
= NULL
;
951 printf("__card_txhandler(%d,%d)\n",chn
,dev
);
953 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return 0;
954 card
= &cardmap
[chn
];
957 if(EXI_Deselect(chn
)==0) ret
|= err
;
958 if(EXI_Unlock(chn
)==0) ret
|= err
;
960 cb
= card
->card_tx_cb
;
962 card
->card_tx_cb
= NULL
;
964 if(EXI_Probe(chn
)==0) ret
= CARD_ERROR_NOCARD
;
965 } else ret
= CARD_ERROR_NOCARD
;
971 static void __timeouthandler(syswd_t alarm
)
974 s32 ret
= CARD_ERROR_READY
;
976 card_block
*card
= NULL
;
978 printf("__timeouthandler(%p)\n",alarm
);
981 while(chn
<EXI_CHANNEL_2
) {
982 card
= &cardmap
[chn
];
983 if(card
->timeout_svc
==alarm
) break;
986 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return;
990 EXI_RegisterEXICallback(chn
,NULL
);
991 cb
= card
->card_exi_cb
;
993 card
->card_exi_cb
= NULL
;
994 ret
= CARD_ERROR_IOERROR
;
1000 static void __setuptimeout(card_block
*card
)
1004 printf("__setuptimeout(%p)\n",&card
->timeout_svc
);
1006 SYS_CancelAlarm(card
->timeout_svc
);
1008 if(card
->cmd
[0]==0xf1 || card
->cmd
[0]==0xf4) {
1010 printf("__setuptimeout(%02x, %dsec)\n",card
->cmd
[0],1*(card
->sector_size
/8192));
1012 tb
.tv_sec
= 1*(card
->sector_size
/8192);
1014 SYS_SetAlarm(card
->timeout_svc
,&tb
,__timeouthandler
);
1015 } else if(card
->cmd
[0]==0xf2) {
1017 printf("__setuptimeout(0xf2, 100ms)\n");
1020 tb
.tv_nsec
= 100*TB_NSPERMS
;
1021 SYS_SetAlarm(card
->timeout_svc
,&tb
,__timeouthandler
);
1025 static s32
__retry(s32 chn
)
1028 card_block
*card
= NULL
;
1030 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
1031 card
= &cardmap
[chn
];
1033 printf("__retry(%d)\n",chn
);
1035 if(EXI_Select(chn
,EXI_DEVICE_0
,EXI_SPEED16MHZ
)==0) {
1037 return CARD_ERROR_NOCARD
;
1040 __setuptimeout(card
);
1042 if(EXI_ImmEx(chn
,card
->cmd
,card
->cmd_len
,EXI_WRITE
)==0) {
1045 return CARD_ERROR_NOCARD
;
1048 if(card
->cmd
[0]==0x52) {
1049 if(EXI_ImmEx(chn
,card
->workarea
+CARD_READSIZE
,card
->latency
,EXI_WRITE
)==0) {
1052 return CARD_ERROR_NOCARD
;
1056 if(card
->cmd_mode
==-1) {
1059 return CARD_ERROR_READY
;
1063 if(card
->cmd
[0]==0x52) len
= CARD_READSIZE
;
1064 if(EXI_Dma(chn
,card
->cmd_usr_buf
,len
,card
->cmd_mode
,__card_txhandler
)==0) {
1067 return CARD_ERROR_NOCARD
;
1069 return CARD_ERROR_READY
;
1072 static void __card_defaultapicallback(s32 chn
,s32 result
)
1075 printf("__card_defaultapicallback(%d,%d)\n",chn
,result
);
1080 static s32
__card_exihandler(s32 chn
,s32 dev
)
1083 s32 ret
= CARD_ERROR_READY
;
1084 card_block
*card
= NULL
;
1087 printf("__card_exihandler(%d,%d)\n",chn
,dev
);
1089 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return 1;
1090 card
= &cardmap
[chn
];
1092 SYS_CancelAlarm(card
->timeout_svc
);
1093 if(card
->attached
) {
1094 if(EXI_Lock(chn
,EXI_DEVICE_0
,NULL
)==1) {
1095 if((ret
=__card_readstatus(chn
,&status
))>=0
1096 && (ret
=__card_clearstatus(chn
))>=0) {
1097 if(status
&0x18) ret
= CARD_ERROR_IOERROR
;
1098 else ret
= CARD_ERROR_READY
;
1100 if(ret
==CARD_ERROR_IOERROR
) {
1101 if((--card
->cmd_retries
)>0) {
1103 if(ret
<0) goto exit
;
1109 } else ret
= CARD_ERROR_FATAL_ERROR
;
1111 cb
= card
->card_exi_cb
;
1113 card
->card_exi_cb
= NULL
;
1120 static s32
__card_exthandler(s32 chn
,s32 dev
)
1123 card_block
*card
= NULL
;
1125 printf("__card_exthandler(%d,%d)\n",chn
,dev
);
1127 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return 0;
1128 card
= &cardmap
[chn
];
1130 if(card
->attached
) {
1131 if(card
->card_tx_cb
) {
1132 printf("error: card->card_tx_cb!=NULL\n");
1135 EXI_RegisterEXICallback(chn
,NULL
);
1136 SYS_CancelAlarm(card
->timeout_svc
);
1138 cb
= card
->card_exi_cb
;
1140 card
->card_exi_cb
= NULL
;
1141 cb(chn
,CARD_ERROR_NOCARD
);
1144 cb
= card
->card_ext_cb
;
1146 card
->card_ext_cb
= NULL
;
1147 cb(chn
,CARD_ERROR_NOCARD
);
1154 static void __write_callback(s32 chn
,s32 result
)
1157 cardcallback cb
= NULL
;
1158 card_file
*file
= NULL
;
1159 struct card_bat
*fatblock
= NULL
;
1160 struct card_dat
*dirblock
= NULL
;
1161 struct card_direntry
*entry
= NULL
;
1162 card_block
*card
= &cardmap
[chn
];
1164 printf("__write_callback(%d,%d)\n",chn
,result
);
1168 file
= card
->curr_file
;
1170 file
->len
= (card
->sector_size
-file
->len
);
1172 dirblock
= __card_getdirblock(card
);
1173 entry
= &dirblock
->entries
[file
->filenum
];
1174 entry
->lastmodified
= time(NULL
);
1175 cb
= card
->card_api_cb
;
1176 card
->card_api_cb
= NULL
;
1177 if((ret
=__card_updatedir(chn
,cb
))>=0) return;
1179 fatblock
= __card_getbatblock(card
);
1180 file
->offset
+= card
->sector_size
;
1181 file
->iblock
= fatblock
->fat
[file
->iblock
-CARD_SYSAREA
];
1182 if(file
->iblock
<CARD_SYSAREA
|| file
->iblock
>=card
->blocks
) {
1183 ret
= CARD_ERROR_BROKEN
;
1186 if((ret
=__card_sectorerase(chn
,(file
->iblock
*card
->sector_size
),__erase_callback
))>=0) return;
1189 ret
= CARD_ERROR_CANCELED
;
1193 cb
= card
->card_api_cb
;
1194 card
->card_api_cb
= NULL
;
1195 __card_putcntrlblock(card
,ret
);
1199 static void __erase_callback(s32 chn
,s32 result
)
1202 cardcallback cb
= NULL
;
1203 card_file
*file
= NULL
;
1204 card_block
*card
= &cardmap
[chn
];
1206 printf("__erase_callback(%d,%d)\n",chn
,result
);
1210 file
= card
->curr_file
;
1211 if((ret
=__card_write(chn
,(file
->iblock
*card
->sector_size
),card
->sector_size
,card
->cmd_usr_buf
,__write_callback
))>=0) return;
1214 cb
= card
->card_api_cb
;
1215 card
->card_api_cb
= NULL
;
1216 __card_putcntrlblock(card
,ret
);
1220 static void __read_callback(s32 chn
,s32 result
)
1224 cardcallback cb
= NULL
;
1225 card_file
*file
= NULL
;
1226 card_block
*card
= 0;
1227 struct card_bat
*fatblock
= NULL
;
1229 printf("__read_callback(%d,%d)\n",chn
,result
);
1231 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return;
1232 card
= &cardmap
[chn
];
1235 file
= card
->curr_file
;
1237 printf("__read_callback(file->len = %d,file->iblock = %d)\n",file
->len
,file
->iblock
);
1241 file
->len
= file
->len
-(((file
->offset
+card
->sector_size
)&~(card
->sector_size
-1))-file
->offset
);
1243 printf("__read_callback(file->len = %d)\n",file
->len
);
1246 fatblock
= __card_getbatblock(card
);
1247 file
->offset
+= (((file
->offset
+card
->sector_size
)&~(card
->sector_size
-1))-file
->offset
);
1248 file
->iblock
= fatblock
->fat
[file
->iblock
-CARD_SYSAREA
];
1249 if(file
->iblock
<CARD_SYSAREA
|| file
->iblock
>=card
->blocks
) {
1250 ret
= CARD_ERROR_BROKEN
;
1253 len
= file
->len
<card
->sector_size
?card
->sector_size
:file
->len
;
1254 if(__card_read(chn
,(file
->iblock
*card
->sector_size
),len
,card
->cmd_usr_buf
,__read_callback
)>=0) return;
1258 ret
= CARD_ERROR_CANCELED
;
1262 cb
= card
->card_api_cb
;
1263 card
->card_api_cb
= NULL
;
1264 __card_putcntrlblock(card
,ret
);
1268 static void __delete_callback(s32 chn
,s32 result
)
1271 cardcallback cb
= NULL
;
1272 card_block
*card
= &cardmap
[chn
];
1274 printf("__delete_callback(%d,%d)\n",chn
,result
);
1276 cb
= card
->card_api_cb
;
1277 card
->card_api_cb
= NULL
;
1280 if(ret
>=0 && (ret
=__card_freeblock(chn
,card
->curr_fileblock
,cb
))>=0) return;
1282 __card_putcntrlblock(card
,ret
);
1286 static void __format_callback(s32 chn
,s32 result
)
1289 cardcallback cb
= NULL
;
1290 card_block
*card
= &cardmap
[chn
];
1294 if((++card
->format_step
)<CARD_SYSAREA
) {
1295 if((ret
=__card_sectorerase(chn
,(card
->format_step
*card
->sector_size
),__format_callback
))>=0) return;
1298 if(card
->format_step
<10) {
1299 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;
1303 card
->curr_dir
= card
->workarea
+CARD_SYSDIR
;
1304 memcpy(card
->curr_dir
,card
->workarea
+CARD_SYSDIR_BACK
,8192);
1306 card
->curr_fat
= card
->workarea
+CARD_SYSBAT
;
1307 memcpy(card
->curr_fat
,card
->workarea
+CARD_SYSBAT_BACK
,8192);
1310 cb
= card
->card_api_cb
;
1311 card
->card_api_cb
= NULL
;
1312 __card_putcntrlblock(card
,ret
);
1316 static void __blockwritecallback(s32 chn
,s32 result
)
1318 s32 ret
= CARD_ERROR_READY
;
1319 cardcallback cb
= NULL
;
1320 card_block
*card
= &cardmap
[chn
];
1322 printf("__blockwritecallback(%d,%d)\n",chn
,result
);
1326 card
->transfer_cnt
+= 128;
1327 card
->cmd_sector_addr
+= 128;
1328 card
->cmd_usr_buf
+= 128;
1329 if((--card
->cmd_blck_cnt
)>0) {
1330 if((ret
=__card_writepage(chn
,__blockwritecallback
))>=CARD_ERROR_READY
) return;
1334 if(!card
->card_api_cb
) __card_putcntrlblock(card
,ret
);
1336 cb
= card
->card_xfer_cb
;
1338 card
->card_xfer_cb
= NULL
;
1343 static void __blockreadcallback(s32 chn
,s32 result
)
1345 s32 ret
= CARD_ERROR_READY
;
1346 cardcallback cb
= NULL
;
1347 card_block
*card
= &cardmap
[chn
];
1349 printf("__blockreadcallback(%d,%d)\n",chn
,result
);
1353 card
->transfer_cnt
+= CARD_READSIZE
;
1354 card
->cmd_sector_addr
+= CARD_READSIZE
;
1355 card
->cmd_usr_buf
+= CARD_READSIZE
;
1356 if((--card
->cmd_blck_cnt
)>0) {
1357 if((ret
=__card_readsegment(chn
,__blockreadcallback
))>=CARD_ERROR_READY
) return;
1361 if(!card
->card_api_cb
) __card_putcntrlblock(card
,ret
);
1362 cb
= card
->card_xfer_cb
;
1364 card
->card_xfer_cb
= NULL
;
1369 static void __unlocked_callback(s32 chn
,s32 result
)
1375 printf("__unlocked_callback(%d,%d)\n",chn
,result
);
1377 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return;
1378 card
= &cardmap
[chn
];
1382 card
->card_unlock_cb
= __unlocked_callback
;
1383 if(EXI_Lock(chn
,EXI_DEVICE_0
,__card_unlockedhandler
)==1) {
1384 card
->card_unlock_cb
= NULL
;
1390 if(card
->cmd
[0]==0xf3 || card
->cmd
[0]>=0xf5) return;
1391 else if(card
->cmd
[0]==0x52) {
1392 cb
= card
->card_tx_cb
;
1394 card
->card_tx_cb
= NULL
;
1397 } else if(card
->cmd
[0]>=0xf1) {
1398 cb
= card
->card_exi_cb
;
1400 card
->card_exi_cb
= NULL
;
1407 static s32
__card_start(s32 chn
,cardcallback tx_cb
,cardcallback exi_cb
)
1410 card_block
*card
= NULL
;
1412 printf("__card_start(%d,%p,%p)\n",chn
,tx_cb
,exi_cb
);
1414 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
1415 card
= &cardmap
[chn
];
1417 _CPU_ISR_Disable(level
);
1418 if(tx_cb
) card
->card_tx_cb
= tx_cb
;
1419 if(exi_cb
) card
->card_exi_cb
= exi_cb
;
1421 card
->card_unlock_cb
= __unlocked_callback
;
1422 if(EXI_Lock(chn
,EXI_DEVICE_0
,__card_unlockedhandler
)==0) {
1423 _CPU_ISR_Restore(level
);
1425 printf("__card_start(done CARD_ERROR_BUSY)\n");
1427 return CARD_ERROR_BUSY
;
1429 card
->card_unlock_cb
= NULL
;
1431 if(EXI_Select(chn
,EXI_DEVICE_0
,EXI_SPEED16MHZ
)==0) {
1433 _CPU_ISR_Restore(level
);
1435 printf("__card_start(done CARD_ERROR_NOCARD)\n");
1437 return CARD_ERROR_NOCARD
;
1440 __setuptimeout(card
);
1441 _CPU_ISR_Restore(level
);
1444 printf("__card_start(done CARD_ERROR_READY)\n");
1446 return CARD_ERROR_READY
;
1449 static s32
__card_writepage(s32 chn
,cardcallback callback
)
1452 card_block
*card
= NULL
;
1454 printf("__card_writepage(%d,%p)\n",chn
,callback
);
1456 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
1457 card
= &cardmap
[chn
];
1459 card
->cmd
[0] = 0xf2;
1460 card
->cmd
[1] = (card
->cmd_sector_addr
>>17)&0x3f;
1461 card
->cmd
[2] = (card
->cmd_sector_addr
>>9)&0xff;
1462 card
->cmd
[3] = (card
->cmd_sector_addr
>>7)&3;
1463 card
->cmd
[4] = card
->cmd_sector_addr
&0x7f;
1465 card
->cmd_mode
= EXI_WRITE
;
1466 card
->cmd_retries
= 3;
1468 ret
= __card_start(chn
,NULL
,callback
);
1469 if(ret
<0) return ret
;
1471 if(EXI_ImmEx(chn
,card
->cmd
,card
->cmd_len
,EXI_WRITE
)==1
1472 && EXI_Dma(chn
,card
->cmd_usr_buf
,128,card
->cmd_mode
,__card_txhandler
)==1) return CARD_ERROR_READY
;
1474 card
->card_exi_cb
= NULL
;
1477 return CARD_ERROR_NOCARD
;
1480 static s32
__card_readsegment(s32 chn
,cardcallback callback
)
1484 card_block
*card
= NULL
;
1486 printf("__card_readsegment(%d,%p)\n",chn
,callback
);
1488 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
1489 card
= &cardmap
[chn
];
1491 card
->cmd
[0] = 0x52;
1492 card
->cmd
[1] = (card
->cmd_sector_addr
&0xFE0000)>>17;
1493 card
->cmd
[2] = (card
->cmd_sector_addr
&0x01FE00)>>9;
1494 card
->cmd
[3] = (card
->cmd_sector_addr
&0x000180)>>7;
1495 card
->cmd
[4] = (card
->cmd_sector_addr
&0x00007F);
1497 card
->cmd_mode
= EXI_READ
;
1498 card
->cmd_retries
= 0;
1500 ret
= __card_start(chn
,callback
,NULL
);
1501 if(ret
<0) return ret
;
1504 if(EXI_ImmEx(chn
,card
->cmd
,card
->cmd_len
,EXI_WRITE
)==0) err
|= 0x01;
1505 if(EXI_ImmEx(chn
,card
->workarea
+CARD_READSIZE
,card
->latency
,EXI_WRITE
)==0) err
|= 0x02;
1506 if(EXI_Dma(chn
,card
->cmd_usr_buf
,CARD_READSIZE
,card
->cmd_mode
,__card_txhandler
)==0) err
|= 0x04;
1509 card
->card_tx_cb
= NULL
;
1512 return CARD_ERROR_NOCARD
;
1514 return CARD_ERROR_READY
;
1517 static void __card_fatwritecallback(s32 chn
,s32 result
)
1520 cardcallback cb
= NULL
;
1521 struct card_bat
*fat1
,*fat2
;
1522 card_block
*card
= &cardmap
[chn
];
1524 printf("__card_fatwritecallback(%d,%d)\n",chn
,result
);
1528 fat1
= (card
->workarea
+0x6000);
1529 fat2
= (card
->workarea
+0x8000);
1530 if(card
->curr_fat
==fat1
) {
1531 card
->curr_fat
= fat2
;
1532 memcpy(fat2
,fat1
,8192);
1534 card
->curr_fat
= fat1
;
1535 memcpy(fat1
,fat2
,8192);
1538 if(!card
->card_api_cb
) __card_putcntrlblock(card
,ret
);
1540 printf("__card_fatwritecallback(%p,%p)\n",card
->card_api_cb
,card
->card_erase_cb
);
1542 cb
= card
->card_erase_cb
;
1544 card
->card_erase_cb
= NULL
;
1549 static void __card_dirwritecallback(s32 chn
,s32 result
)
1552 cardcallback cb
= NULL
;
1553 struct card_dat
*dir1
,*dir2
;
1554 card_block
*card
= &cardmap
[chn
];
1556 printf("__card_dirwritecallback(%d,%d)\n",chn
,result
);
1560 dir1
= (card
->workarea
+0x2000);
1561 dir2
= (card
->workarea
+0x4000);
1562 if(card
->curr_dir
==dir1
) {
1563 card
->curr_dir
= dir2
;
1564 memcpy(dir2
,dir1
,8192);
1566 card
->curr_dir
= dir1
;
1567 memcpy(dir1
,dir2
,8192);
1570 if(!card
->card_api_cb
) __card_putcntrlblock(card
,ret
);
1572 printf("__card_dirwritecallback(%p,%p)\n",card
->card_api_cb
,card
->card_erase_cb
);
1574 cb
= card
->card_erase_cb
;
1576 card
->card_erase_cb
= NULL
;
1581 static s32
__card_write(s32 chn
,u32 address
,u32 block_len
,void *buffer
,cardcallback callback
)
1584 card_block
*card
= NULL
;
1586 printf("__card_write(%d,%08x,%d,%p,%p)\n",chn
,address
,block_len
,buffer
,callback
);
1588 if(chn
<EXI_CHANNEL_0
|| chn
>= EXI_CHANNEL_2
) return CARD_ERROR_FATAL_ERROR
;
1589 card
= &cardmap
[chn
];
1591 if(!card
->attached
) return CARD_ERROR_NOCARD
;
1593 card
->cmd_blck_cnt
= block_len
>>7;
1594 card
->cmd_sector_addr
= address
;
1595 card
->cmd_usr_buf
= buffer
;
1596 card
->card_xfer_cb
= callback
;
1597 ret
= __card_writepage(chn
,__blockwritecallback
);
1602 static s32
__card_read(s32 chn
,u32 address
,u32 block_len
,void *buffer
,cardcallback callback
)
1605 card_block
*card
= NULL
;
1607 printf("__card_read(%d,%08x,%d,%p,%p)\n",chn
,address
,block_len
,buffer
,callback
);
1609 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
1610 card
= &cardmap
[chn
];
1612 card
->cmd_sector_addr
= address
;
1613 card
->cmd_blck_cnt
= block_len
>>9;
1614 card
->cmd_usr_buf
= buffer
;
1615 card
->card_xfer_cb
= callback
;
1616 ret
= __card_readsegment(chn
,__blockreadcallback
);
1621 static s32
__card_formatregion(s32 chn
,u32 encode
,cardcallback callback
)
1628 void *workarea
,*memblock
;
1629 cardcallback cb
= NULL
;
1630 card_block
*card
= NULL
;
1631 struct card_header
*header
;
1632 struct card_bat
*fatblock
= NULL
;
1633 struct card_dircntrl
*dircntrl
= NULL
;
1637 printf("__card_formatregion(%d,%d,%p)\n",chn
,encode
,callback
);
1639 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
1641 if((ret
=__card_getcntrlblock(chn
,&card
))<0) return ret
;
1643 header
= workarea
= card
->workarea
;
1644 memset(header
,0xff,8192);
1647 header
->encoding
= encode
;
1649 sram
= __SYS_LockSram();
1650 header
->serial
[5] = sram
->counter_bias
;
1651 header
->serial
[6] = sram
->lang
;
1652 __SYS_UnlockSram(0);
1655 rnd_val
= time
= gettime();
1656 sramex
= __SYS_LockSramEx();
1658 rnd_val
= (((rnd_val
*(u64
)0x0000000041c64e6d)+(u64
)0x0000000000003039)>>16);
1659 ((u8
*)header
->serial
)[cnt
] = (sramex
->flash_id
[chn
][cnt
]+(u32
)rnd_val
);
1661 rnd_val
= (((rnd_val
*(u64
)0x0000000041c64e6d)+(u64
)0x0000000000003039)>>16);
1662 rnd_val
&= (u64
)0x0000000000007fff;
1666 __SYS_UnlockSramEx(0);
1668 *(u64
*)&(header
->serial
[3]) = time
;
1669 header
->serial
[7] = tmp
;
1670 header
->device_id
= 0;
1671 header
->size
= card
->card_size
;
1672 __card_checksum((u16
*)header
,508,&header
->chksum1
,&header
->chksum2
);
1676 memblock
= workarea
+((cnt
+1)<<13);
1677 dircntrl
= memblock
+8128;
1678 memset(memblock
,0xff,8192);
1679 __card_checksum(memblock
,8188,&dircntrl
->chksum1
,&dircntrl
->chksum2
);
1685 memblock
= workarea
+((cnt
+3)<<13);
1686 fatblock
= memblock
;
1687 memset(memblock
,0,8192);
1688 fatblock
->updated
= cnt
;
1689 fatblock
->freeblocks
= card
->blocks
-CARD_SYSAREA
;
1690 fatblock
->lastalloc
= 4;
1691 __card_checksum(memblock
+4,8188,&fatblock
->chksum1
,&fatblock
->chksum2
);
1696 if(!cb
) cb
= __card_defaultapicallback
;
1697 card
->card_api_cb
= cb
;
1699 DCStoreRange(card
->workarea
,0xA000);
1701 card
->format_step
= 0;
1702 if((ret
=__card_sectorerase(chn
,(card
->sector_size
*card
->format_step
),__format_callback
))>=0) return ret
;
1704 __card_putcntrlblock(card
,ret
);
1708 static s32
__card_sectorerase(s32 chn
,u32 sector
,cardcallback callback
)
1711 card_block
*card
= NULL
;
1713 printf("__card_sectorerase(%d,%08x,%p)\n",chn
,sector
,callback
);
1715 if(chn
<EXI_CHANNEL_0
|| chn
>= EXI_CHANNEL_2
) return CARD_ERROR_FATAL_ERROR
;
1716 card
= &cardmap
[chn
];
1718 if(sector
%card
->sector_size
) return CARD_ERROR_FATAL_ERROR
;
1720 card
->cmd
[0] = 0xf1;
1721 card
->cmd
[1] = (sector
>>17)&0x7f;
1722 card
->cmd
[2] = (sector
>>9)&0xff;
1724 card
->cmd_mode
= -1;
1725 card
->cmd_retries
= 3;
1727 ret
= __card_start(chn
,NULL
,callback
);
1728 if(ret
<0) return ret
;
1730 if(EXI_ImmEx(chn
,card
->cmd
,card
->cmd_len
,EXI_WRITE
)==0) {
1731 card
->card_exi_cb
= NULL
;
1732 return CARD_ERROR_NOCARD
;
1740 static void __card_faterasecallback(s32 chn
,s32 result
)
1743 cardcallback cb
= NULL
;
1744 struct card_bat
*fatblock
= NULL
;
1745 card_block
*card
= &cardmap
[chn
];
1747 printf("__card_faterasecallback(%d,%d)\n",chn
,result
);
1751 fatblock
= __card_getbatblock(card
);
1752 if((ret
=__card_write(chn
,(((u32
)fatblock
-(u32
)card
->workarea
)>>13)*card
->sector_size
,8192,fatblock
,__card_fatwritecallback
))>=0) return;
1754 if(!card
->card_api_cb
) __card_putcntrlblock(card
,ret
);
1756 cb
= card
->card_erase_cb
;
1758 card
->card_erase_cb
= NULL
;
1763 static void __card_direrasecallback(s32 chn
,s32 result
)
1766 cardcallback cb
= NULL
;
1767 struct card_dat
*dirblock
= NULL
;
1768 card_block
*card
= &cardmap
[chn
];
1770 printf("__card_direrasecallback(%d,%d)\n",chn
,result
);
1774 dirblock
= __card_getdirblock(card
);
1775 if((ret
=__card_write(chn
,(((u32
)dirblock
-(u32
)card
->workarea
)>>13)*card
->sector_size
,8192,dirblock
,__card_dirwritecallback
))>=0) return;
1777 if(!card
->card_api_cb
) __card_putcntrlblock(card
,ret
);
1779 cb
= card
->card_erase_cb
;
1781 card
->card_erase_cb
= NULL
;
1786 static void __card_createfatcallback(s32 chn
,s32 result
)
1789 cardcallback cb
= NULL
;
1790 card_file
*file
= NULL
;
1791 struct card_direntry
*entry
= NULL
;
1792 struct card_dat
*dirblock
= NULL
;
1793 card_block
*card
= &cardmap
[chn
];
1795 printf("__card_createfatcallback(%d,%d)\n",chn
,result
);
1797 cb
= card
->card_api_cb
;
1798 card
->card_api_cb
= NULL
;
1800 dirblock
= __card_getdirblock(card
);
1802 file
= card
->curr_file
;
1803 entry
= &dirblock
->entries
[file
->filenum
];
1805 memset(entry
->gamecode
,0,4);
1806 memset(entry
->company
,0,2);
1807 if(card_gamecode
[0]!=0xff) memcpy(entry
->gamecode
,card_gamecode
,4);
1808 if(card_gamecode
[0]!=0xff) memcpy(entry
->company
,card_company
,2);
1809 entry
->block
= card
->curr_fileblock
;
1810 entry
->permission
= CARD_ATTRIB_PUBLIC
;
1811 entry
->pad_00
= 0xff;
1812 entry
->copytimes
= 0;
1813 entry
->iconaddr
= -1;
1815 entry
->iconspeed
= 0;
1816 entry
->pad_01
= 0xffff;
1817 entry
->iconspeed
= (entry
->iconspeed
&~CARD_SPEED_MASK
)|CARD_SPEED_FAST
;
1818 entry
->lastmodified
= time(NULL
);
1821 file
->iblock
= card
->curr_fileblock
;
1823 if((ret
=__card_updatedir(chn
,cb
))<0) {
1824 __card_putcntrlblock(card
,ret
);
1829 static s32
__card_updatefat(s32 chn
,struct card_bat
*fatblock
,cardcallback callback
)
1831 card_block
*card
= NULL
;
1833 printf("__card_updatefat(%d,%p,%p)\n",chn
,fatblock
,callback
);
1835 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_FATAL_ERROR
;
1836 card
= &cardmap
[chn
];
1838 if(!card
->attached
) return CARD_ERROR_NOCARD
;
1840 ++fatblock
->updated
;
1841 __card_checksum((u16
*)(((u32
)fatblock
)+4),0x1ffc,&fatblock
->chksum1
,&fatblock
->chksum2
);
1842 DCStoreRange(fatblock
,8192);
1843 card
->card_erase_cb
= callback
;
1845 return __card_sectorerase(chn
,(((u32
)fatblock
-(u32
)card
->workarea
)>>13)*card
->sector_size
,__card_faterasecallback
);
1848 static s32
__card_updatedir(s32 chn
,cardcallback callback
)
1850 card_block
*card
= NULL
;
1851 void *dirblock
= NULL
;
1852 struct card_dircntrl
*dircntrl
= NULL
;
1854 printf("__card_updatedir(%d,%p)\n",chn
,callback
);
1856 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_FATAL_ERROR
;
1857 card
= &cardmap
[chn
];
1859 if(!card
->attached
) return CARD_ERROR_NOCARD
;
1861 dirblock
= __card_getdirblock(card
);
1862 dircntrl
= dirblock
+8128;
1863 ++dircntrl
->updated
;
1864 __card_checksum((u16
*)dirblock
,0x1ffc,&dircntrl
->chksum1
,&dircntrl
->chksum2
);
1865 DCStoreRange(dirblock
,0x2000);
1866 card
->card_erase_cb
= callback
;
1868 return __card_sectorerase(chn
,(((u32
)dirblock
-(u32
)card
->workarea
)>>13)*card
->sector_size
,__card_direrasecallback
);
1871 static void __card_dounmount(s32 chn
,s32 result
)
1876 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return;
1877 card
= &cardmap
[chn
];
1879 _CPU_ISR_Disable(level
);
1880 if(card
->attached
) {
1882 card
->mount_step
= 0;
1883 card
->result
= result
;
1884 EXI_RegisterEXICallback(chn
,NULL
);
1886 SYS_CancelAlarm(card
->timeout_svc
);
1888 _CPU_ISR_Restore(level
);
1891 static s32
__card_domount(s32 chn
)
1894 s32 ret
= CARD_ERROR_READY
;
1900 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
1901 card
= &cardmap
[chn
];
1903 printf("__card_domount(%d,%d)\n",chn
,card
->mount_step
);
1905 if(card
->mount_step
==0) {
1908 if(EXI_GetID(chn
,EXI_DEVICE_0
,&id
)==0) ret
= CARD_ERROR_NOCARD
;
1909 else if(!__card_iscard(id
)) ret
= CARD_ERROR_WRONGDEVICE
;
1911 if(ret
<0) goto exit
;
1913 card
->card_size
= (id
&0xfc);
1915 printf("__card_domount(card_type = %08x,%08x,%08x)\n",card
->card_size
,card
->cid
,id
);
1917 if(card
->card_size
) {
1918 idx
= _ROTL(id
,23)&0x1c;
1919 card
->sector_size
= card_sector_size
[idx
>>2];
1920 card
->blocks
= ((card
->card_size
<<20)>>3)/card
->sector_size
;
1922 if(card
->blocks
>0x0008) {
1923 idx
= _ROTL(id
,26)&0x1c;
1924 card
->latency
= card_latency
[idx
>>2];
1926 if((ret
=__card_clearstatus(chn
))<0) goto exit
;
1927 if((ret
=__card_readstatus(chn
,&status
))<0) goto exit
;
1929 if(EXI_Probe(chn
)==0) {
1930 ret
= CARD_ERROR_NOCARD
;
1933 if(!(status
&CARD_STATUS_UNLOCKED
)) {
1935 printf("__card_domount(card locked)\n");
1937 if((ret
=__dounlock(chn
,card
->key
))<0) goto exit
;
1941 sramex
= __SYS_LockSramEx();
1943 kval
= ((u8
*)card
->key
)[cnt
];
1944 sramex
->flash_id
[chn
][cnt
] = kval
;
1948 sum
= (sum
^-1)&0xff;
1949 sramex
->flashID_chksum
[chn
] = (sum
<<8)|sum
;
1950 __SYS_UnlockSramEx(1);
1953 card
->mount_step
= 1;
1957 sramex
= __SYS_LockSramEx();
1959 sum
+= sramex
->flash_id
[chn
][cnt
];
1962 cnt
= sramex
->flashID_chksum
[chn
];
1963 __SYS_UnlockSramEx(0);
1965 sum
= (sum
^-1)&0xff;
1968 ret
= CARD_ERROR_IOERROR
;
1974 if(card
->mount_step
==1) {
1975 card
->mount_step
= 2;
1976 if((ret
=__card_enableinterrupt(chn
,1))<0) goto exit
;
1977 EXI_RegisterEXICallback(chn
,__card_exihandler
);
1980 DCInvalidateRange(card
->workarea
,0xA000);
1983 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
;
1988 __card_dounmount(chn
,ret
);
1993 static void __card_mountcallback(s32 chn
,s32 result
)
1997 card_block
*card
= &cardmap
[chn
];
2000 if(ret
==CARD_ERROR_NOCARD
|| ret
==CARD_ERROR_IOERROR
) {
2001 __card_dounmount(chn
,ret
);
2002 __card_putcntrlblock(card
,ret
);
2003 }else if(ret
==CARD_ERROR_UNLOCKED
) {
2004 if((ret
=__card_domount(chn
))>=0) return;
2006 if((++card
->mount_step
)<7) {
2007 if((ret
=__card_domount(chn
))>=0) return;
2009 ret
= __card_verify(card
);
2010 __card_putcntrlblock(card
,ret
);
2014 cb
= card
->card_api_cb
;
2015 card
->card_api_cb
= NULL
;
2019 static __inline__
void __card_srand(u32 val
)
2024 static __inline__ u32
__card_rand()
2026 crand_next
= (crand_next
*0x41C64E6D)+12345;
2027 return _SHIFTR(crand_next
,16,15);
2030 static u32
__card_initval()
2032 u32 ticks
= gettick();
2034 __card_srand(ticks
);
2035 return ((0x7FEC8000|__card_rand())&~0x00000fff);
2038 static u32
__card_dummylen()
2040 u32 ticks
= gettick();
2041 u32 val
= 0,cnt
= 0,shift
= 1;
2043 __card_srand(ticks
);
2044 val
= (__card_rand()&0x1f)+1;
2050 if(shift
>16) shift
= 1;
2052 val
= (__card_rand()&0x1f)+1;
2054 }while(val
<4 && cnt
<10);
2061 static u32
exnor_1st(u32 a
,u32 b
)
2063 u32 c
,d
,e
,f
,r1
,r2
,r3
,r4
;
2072 r3
= ~(d
^r2
); //eqv(d,r2)
2074 r4
= ((r3
<<30)&0x40000000);
2081 static u32
exnor(u32 a
,u32 b
)
2083 u32 c
,d
,e
,f
,r1
,r2
,r3
,r4
;
2092 r3
= ~(d
^r2
); //eqv(d,r2)
2094 r4
= ((r3
>>30)&0x02);
2101 static u32
bitrev(u32 val
)
2103 u32 cnt
,val1
,ret
,shift
,shift1
;
2111 val1
= val
&(1<<cnt
);
2112 val1
<<= ((31-cnt
)-shift1
);
2115 } else if(cnt
==31) {
2120 val1
= val
&(1<<cnt
);
2130 static s32
__card_readarrayunlock(s32 chn
,u32 address
,void *buffer
,u32 len
,u32 flag
)
2135 card_block
*card
= &cardmap
[chn
];
2137 printf("__card_readarrayunlock(%d,%d,%p,%d,%d)\n",chn
,address
,buffer
,len
,flag
);
2139 if(EXI_Select(chn
,EXI_DEVICE_0
,EXI_SPEED16MHZ
)==0) return CARD_ERROR_NOCARD
;
2141 address
&= 0xFFFFF000;
2146 regbuf
[1] = ((address
&0x60000000)>>29)&0xff;
2147 regbuf
[2] = ((address
&0x1FE00000)>>21)&0xff;
2148 regbuf
[3] = ((address
&0x00180000)>>19)&0xff;
2149 regbuf
[4] = ((address
&0x0007F000)>>12)&0xff;
2151 regbuf
[1] = (address
>>24)&0xff;
2152 regbuf
[2] = ((address
&0x00FF0000)>>16)&0xff;
2156 if(EXI_ImmEx(chn
,regbuf
,5,EXI_WRITE
)==0) err
|= 0x01;
2157 if(EXI_ImmEx(chn
,card
->workarea
+CARD_READSIZE
,card
->latency
,EXI_WRITE
)==0) err
|= 0x02;
2158 if(EXI_ImmEx(chn
,buffer
,len
,EXI_READ
)==0) err
|= 0x04;
2159 if(EXI_Deselect(chn
)==0) err
|= 0x08;
2161 if(err
) ret
= CARD_ERROR_NOCARD
;
2162 else ret
= CARD_ERROR_READY
;
2167 static void __dsp_initcallback(dsptask_t
*task
)
2170 card_block
*card
= NULL
;
2172 printf("__dsp_initcallback(%p)\n",task
);
2175 while(chn
<EXI_CHANNEL_2
) {
2176 card
= &cardmap
[chn
];
2177 if(&card
->dsp_task
==task
) break;
2180 if(chn
>=EXI_CHANNEL_2
) return;
2182 DSP_SendMailTo(0xFF000000);
2183 while(DSP_CheckMailTo());
2184 DSP_SendMailTo((u32
)card
->workarea
);
2185 while(DSP_CheckMailTo());
2188 static u8 tmp_buffer
[64] ATTRIBUTE_ALIGN(32);
2189 static void __dsp_donecallback(dsptask_t
*task
)
2196 card_block
*card
= NULL
;
2198 printf("__dsp_donecallback(%p)\n",task
);
2201 while(chn
<EXI_CHANNEL_2
) {
2202 card
= &cardmap
[chn
];
2203 if(&card
->dsp_task
==task
) break;
2206 if(chn
>=EXI_CHANNEL_2
) return;
2208 workarea
= (u32
)card
->workarea
;
2209 workarea
= ((workarea
+47)&~0x1f);
2210 key
= ((u32
*)workarea
)[8];
2212 val
= (key
^card
->cipher
)&~0xffff;
2213 len
= __card_dummylen();
2214 if(__card_readarrayunlock(chn
,val
,tmp_buffer
,len
,1)<0) {
2216 __card_mountcallback(chn
,CARD_ERROR_NOCARD
);
2220 val
= exnor(card
->cipher
,((len
+card
->latency
+4)<<3)+1);
2228 r3
= ~(a
^r2
); //eqv(a,r2)
2229 r1
= (val
|(r3
>>31));
2233 val
= ((key
<<16)^card
->cipher
)&~0xffff;
2234 len
= __card_dummylen();
2235 if(__card_readarrayunlock(chn
,val
,tmp_buffer
,len
,1)<0) {
2237 __card_mountcallback(chn
,CARD_ERROR_NOCARD
);
2241 ret
= __card_readstatus(chn
,&status
);
2242 if(EXI_Probe(chn
)==0) {
2244 __card_mountcallback(chn
,CARD_ERROR_NOCARD
);
2247 if(!ret
&& !(status
&CARD_STATUS_UNLOCKED
)) {
2249 ret
= CARD_ERROR_IOERROR
;
2251 __card_mountcallback(chn
,ret
);
2254 static s32
__dounlock(s32 chn
,u32
*key
)
2257 u32 array_addr
,len
,val
;
2259 card_block
*card
= &cardmap
[chn
];
2260 u32
*workarea
= card
->workarea
;
2261 u32
*cipher1
= (u32
*)(((u32
)card
->workarea
+47)&~31);
2262 u32
*cipher2
= &cipher1
[8];
2264 printf("__dounlock(%d,%p)\n",chn
,key
);
2266 array_addr
= __card_initval();
2267 len
= __card_dummylen();
2269 if(__card_readarrayunlock(chn
,array_addr
,tmp_buffer
,len
,0)<0) return CARD_ERROR_NOCARD
;
2272 val
= exnor_1st(array_addr
,(len
<<3)+1);
2280 r3
= ~(a
^r2
); //eqv(a,r2)
2281 r1
= (val
|(r3
<<31));
2284 card
->cipher
= bitrev(card
->cipher
);
2287 len
= __card_dummylen();
2288 if(__card_readarrayunlock(chn
,array_addr
,tmp_buffer
,len
+20,1)<0) return CARD_ERROR_NOCARD
;
2290 a
= ((u32
*)tmp_buffer
)[0];
2291 b
= ((u32
*)tmp_buffer
)[1];
2292 c
= ((u32
*)tmp_buffer
)[2];
2293 d
= ((u32
*)tmp_buffer
)[3];
2294 e
= ((u32
*)tmp_buffer
)[4];
2297 val
= exnor(card
->cipher
,32);
2305 r3
= ~(a
^r2
); //eqv(a,r2)
2306 r1
= (val
|(r3
>>31));
2311 val
= exnor(card
->cipher
,32);
2319 r3
= ~(a
^r2
); //eqv(a,r2)
2320 r1
= (val
|(r3
>>31));
2325 val
= exnor(card
->cipher
,32);
2333 r3
= ~(a
^r2
); //eqv(a,r2)
2334 r1
= (val
|(r3
>>31));
2339 val
= exnor(card
->cipher
,32);
2347 r3
= ~(a
^r2
); //eqv(a,r2)
2348 r1
= (val
|(r3
>>31));
2353 val
= exnor(card
->cipher
,(len
<<3));
2361 r3
= ~(a
^r2
); //eqv(a,r2)
2362 r1
= (val
|(r3
>>31));
2366 val
= exnor(card
->cipher
,33);
2374 r3
= ~(a
^r2
); //eqv(a,r2)
2375 r1
= (val
|(r3
>>31));
2381 workarea
[0] = (u32
)cipher1
;
2384 workarea
[3] = (u32
)cipher2
;
2385 DCFlushRange(cipher1
,8);
2386 DCInvalidateRange(cipher2
,4);
2387 DCFlushRange(workarea
,16);
2389 card
->dsp_task
.prio
= 255;
2390 card
->dsp_task
.iram_maddr
= (u16
*)MEM_VIRTUAL_TO_PHYSICAL(_cardunlockdata
);
2391 card
->dsp_task
.iram_len
= 352;
2392 card
->dsp_task
.iram_addr
= 0x0000;
2393 card
->dsp_task
.init_vec
= 16;
2394 card
->dsp_task
.res_cb
= NULL
;
2395 card
->dsp_task
.req_cb
= NULL
;
2396 card
->dsp_task
.init_cb
= __dsp_initcallback
;
2397 card
->dsp_task
.done_cb
= __dsp_donecallback
;
2398 DSP_AddTask(&card
->dsp_task
);
2404 return CARD_ERROR_READY
;
2407 s32
CARD_Init(const char *gamecode
,const char *company
)
2411 if(card_inited
) return CARD_ERROR_READY
;
2413 printf("CARD_Init(%s,%s,%d)\n",gamecode
,company
);
2415 if(gamecode
&& strlen(gamecode
)<=4) memcpy(card_gamecode
,gamecode
,4);
2416 if(company
&& strlen(company
)<=2) memcpy(card_company
,company
,2);
2418 _CPU_ISR_Disable(level
);
2421 memset(cardmap
,0,sizeof(card_block
)*2);
2423 cardmap
[i
].result
= CARD_ERROR_NOCARD
;
2424 LWP_InitQueue(&cardmap
[i
].wait_sync_queue
);
2425 SYS_CreateAlarm(&cardmap
[i
].timeout_svc
);
2427 SYS_RegisterResetFunc(&card_resetinfo
);
2429 _CPU_ISR_Restore(level
);
2430 return CARD_ERROR_READY
;
2433 s32
CARD_Probe(s32 chn
)
2435 return EXI_Probe(chn
);
2438 s32
CARD_ProbeEx(s32 chn
,s32
*mem_size
,s32
*sect_size
)
2442 card_block
*card
= NULL
;
2444 printf("CARD_ProbeEx(%d,%p,%p)\n",chn
,mem_size
,sect_size
);
2446 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_FATAL_ERROR
;
2447 card
= &cardmap
[chn
];
2449 _CPU_ISR_Disable(level
);
2450 ret
= EXI_ProbeEx(chn
);
2452 if(!ret
) ret
= CARD_ERROR_BUSY
;
2453 else ret
= CARD_ERROR_NOCARD
;
2454 _CPU_ISR_Restore(level
);
2458 if(card
->attached
) {
2459 if(card
->mount_step
<1) {
2460 _CPU_ISR_Restore(level
);
2461 return CARD_ERROR_BUSY
;
2463 if(mem_size
) *mem_size
= card
->card_size
;
2464 if(sect_size
) *sect_size
= card
->sector_size
;
2466 _CPU_ISR_Restore(level
);
2467 return CARD_ERROR_READY
;
2470 if(EXI_GetState(chn
)&EXI_FLAG_ATTACH
) ret
= CARD_ERROR_WRONGDEVICE
;
2472 ret
= CARD_ERROR_BUSY
;
2473 if(EXI_GetID(chn
,EXI_DEVICE_0
,&card_id
)) {
2474 if(!__card_iscard(card_id
)) ret
= CARD_ERROR_WRONGDEVICE
;
2476 if(mem_size
) *mem_size
= card_id
&0xFC;
2478 u32 idx
= _ROTL(card_id
,23)&0x1c;
2479 *sect_size
= card_sector_size
[idx
>>2];
2481 ret
= CARD_ERROR_READY
;
2486 _CPU_ISR_Restore(level
);
2490 s32
CARD_MountAsync(s32 chn
,void *workarea
,cardcallback detach_cb
,cardcallback attach_cb
)
2492 s32 ret
= CARD_ERROR_READY
;
2494 cardcallback attachcb
= NULL
;
2495 card_block
*card
= NULL
;
2497 printf("CARD_MountAsync(%d,%p,%p,%p)\n",chn
,workarea
,detach_cb
,attach_cb
);
2499 if(!workarea
) return CARD_ERROR_NOCARD
;
2500 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_FATAL_ERROR
;
2501 card
= &cardmap
[chn
];
2503 _CPU_ISR_Disable(level
);
2505 printf("card->attached = %d,%08x\n",card
->attached
,EXI_GetState(chn
));
2507 if(card
->result
==CARD_ERROR_BUSY
) {
2508 _CPU_ISR_Restore(level
);
2509 return CARD_ERROR_BUSY
;
2511 if(card
->attached
|| !(EXI_GetState(chn
)&EXI_FLAG_ATTACH
)) {
2512 card
->result
= CARD_ERROR_BUSY
;
2513 card
->workarea
= workarea
;
2514 card
->card_ext_cb
= detach_cb
;
2516 attachcb
= attach_cb
;
2517 if(!attachcb
) attachcb
= __card_defaultapicallback
;
2518 card
->card_api_cb
= attachcb
;
2519 card
->card_exi_cb
= NULL
;
2521 if(!card
->attached
) {
2522 if(EXI_Attach(chn
,__card_exthandler
)==0) {
2523 card
->result
= CARD_ERROR_NOCARD
;
2525 printf("card->attached = %d,%08x,attach failed\n",card
->attached
,EXI_GetState(chn
));
2527 _CPU_ISR_Restore(level
);
2528 return CARD_ERROR_NOCARD
;
2531 card
->mount_step
= 0;
2534 printf("card->attached = %d,%08x\n",card
->attached
,EXI_GetState(chn
));
2536 EXI_RegisterEXICallback(chn
,NULL
);
2537 SYS_CancelAlarm(card
->timeout_svc
);
2538 card
->curr_dir
= NULL
;
2539 card
->curr_fat
= NULL
;
2540 _CPU_ISR_Restore(level
);
2542 card
->card_unlock_cb
= __card_mountcallback
;
2543 if(EXI_Lock(chn
,EXI_DEVICE_0
,__card_unlockedhandler
)==0) return 0;
2545 card
->card_unlock_cb
= NULL
;
2546 __card_domount(chn
);
2550 ret
= CARD_ERROR_WRONGDEVICE
;
2551 _CPU_ISR_Restore(level
);
2555 s32
CARD_Mount(s32 chn
,void *workarea
,cardcallback detach_cb
)
2559 printf("CARD_Mount(%d,%p,%p)\n",chn
,workarea
,detach_cb
);
2561 if((ret
=CARD_MountAsync(chn
,workarea
,detach_cb
,__card_synccallback
))>=0) {
2562 ret
= __card_sync(chn
);
2567 s32
CARD_Unmount(s32 chn
)
2570 card_block
*card
= NULL
;
2572 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
2574 if((ret
=__card_getcntrlblock(chn
,&card
))<0) ret
= CARD_ERROR_NOCARD
;
2576 __card_dounmount(chn
,ret
);
2577 return CARD_ERROR_READY
;
2580 s32
CARD_ReadAsync(card_file
*file
,void *buffer
,u32 len
,u32 offset
,cardcallback callback
)
2583 cardcallback cb
= NULL
;
2584 struct card_dat
*dirblock
= NULL
;
2585 card_block
*card
= NULL
;
2587 if(len
<=0 || (len
&0x1ff) || (offset
>0 && (offset
&0x1ff))) return CARD_ERROR_FATAL_ERROR
;
2588 if((ret
=__card_seek(file
,len
,offset
,&card
))<0) return ret
;
2590 dirblock
= __card_getdirblock(card
);
2591 DCInvalidateRange(buffer
,len
);
2594 if(!cb
) cb
= __card_defaultapicallback
;
2595 card
->card_api_cb
= cb
;
2597 if(len
>=(card
->sector_size
-(file
->offset
&(card
->sector_size
-1)))) len
= (card
->sector_size
-(file
->offset
&(card
->sector_size
-1)));
2599 if((ret
=__card_read(file
->chn
,(file
->iblock
*card
->sector_size
),len
,buffer
,__read_callback
))<0) {
2600 __card_putcntrlblock(card
,ret
);
2606 s32
CARD_Read(card_file
*file
,void *buffer
,u32 len
,u32 offset
)
2610 if((ret
=CARD_ReadAsync(file
,buffer
,len
,offset
,__card_synccallback
))>=0) {
2611 ret
= __card_sync(file
->chn
);
2616 s32
CARD_WriteAsync(card_file
*file
,void *buffer
,u32 len
,u32 offset
,cardcallback callback
)
2619 cardcallback cb
= NULL
;
2620 card_block
*card
= NULL
;
2622 if((ret
=__card_seek(file
,len
,offset
,&card
))<0) return ret
;
2623 if(len
<0 || (len
&(card
->sector_size
-1)) || (offset
>0 && offset
&(card
->sector_size
-1))) {
2624 __card_putcntrlblock(card
,CARD_ERROR_FATAL_ERROR
);
2625 return CARD_ERROR_FATAL_ERROR
;
2628 DCStoreRange(buffer
,len
);
2630 if(!cb
) cb
= __card_defaultapicallback
;
2631 card
->card_api_cb
= cb
;
2633 card
->cmd_usr_buf
= buffer
;
2634 if((ret
=__card_sectorerase(file
->chn
,(file
->iblock
*card
->sector_size
),__erase_callback
))>=0) return ret
;
2635 __card_putcntrlblock(card
,ret
);
2639 s32
CARD_Write(card_file
*file
,void *buffer
,u32 len
,u32 offset
)
2643 if((ret
=CARD_WriteAsync(file
,buffer
,len
,offset
,__card_synccallback
))>=0) {
2644 ret
= __card_sync(file
->chn
);
2649 s32
CARD_CreateAsync(s32 chn
,const char *filename
,u32 size
,card_file
*file
,cardcallback callback
)
2653 cardcallback cb
= NULL
;
2654 card_block
*card
= NULL
;
2655 struct card_bat
*fatblock
= NULL
;
2656 struct card_dat
*dirblock
= NULL
;
2657 struct card_direntry
*entry
= NULL
;
2659 printf("CARD_CreateAsync(%d,%s,%d,%p,%p)\n",chn
,filename
,size
,file
,callback
);
2661 len
= strlen(filename
);
2662 if(len
>CARD_FILENAMELEN
) return CARD_ERROR_NAMETOOLONG
;
2664 if((ret
=__card_getcntrlblock(chn
,&card
))<0) return ret
;
2665 if(size
<=0 || size
%card
->sector_size
) return CARD_ERROR_FATAL_ERROR
;
2667 dirblock
= __card_getdirblock(card
);
2670 entry
= dirblock
->entries
;
2671 for(i
=0;i
<CARD_MAXFILES
;i
++) {
2672 if(entry
[i
].gamecode
[0]==0xff) {
2673 if(filenum
==-1) filenum
= i
;
2674 } else if(memcmp(entry
[i
].filename
,filename
,len
)==0) {
2675 if((card_gamecode
[0]==0xff || card_company
[0]==0xff)
2676 || ((card_gamecode
[0]!=0xff && memcmp(entry
[i
].gamecode
,card_gamecode
,4)==0)
2677 && (card_company
[0]!=0xff && memcmp(entry
[i
].company
,card_company
,2)==0))) {
2678 __card_putcntrlblock(card
,CARD_ERROR_EXIST
);
2679 return CARD_ERROR_EXIST
;
2684 __card_putcntrlblock(card
,CARD_ERROR_NOENT
);
2685 return CARD_ERROR_NOENT
;
2688 fatblock
= __card_getbatblock(card
);
2689 if((fatblock
->freeblocks
*card
->sector_size
)<size
) {
2690 __card_putcntrlblock(card
,CARD_ERROR_INSSPACE
);
2691 return CARD_ERROR_INSSPACE
;
2695 if(!cb
) cb
= __card_defaultapicallback
;
2696 card
->card_api_cb
= cb
;
2698 entry
[filenum
].length
= size
/card
->sector_size
;
2699 memset(entry
[filenum
].filename
,0,CARD_FILENAMELEN
);
2700 memcpy(entry
[filenum
].filename
,filename
,len
+1);
2702 card
->curr_file
= file
;
2704 file
->filenum
= filenum
;
2705 if((ret
=__card_allocblock(chn
,(size
/card
->sector_size
),__card_createfatcallback
))<0) {
2706 __card_putcntrlblock(card
,ret
);
2713 s32
CARD_Create(s32 chn
,const char *filename
,u32 size
,card_file
*file
)
2717 if((ret
=CARD_CreateAsync(chn
,filename
,size
,file
,__card_synccallback
))>=0) {
2718 ret
= __card_sync(chn
);
2723 s32
CARD_CreateEntryAsync(s32 chn
,card_dir
*direntry
,card_file
*file
,cardcallback callback
)
2727 cardcallback cb
= NULL
;
2728 card_block
*card
= NULL
;
2729 struct card_bat
*fatblock
= NULL
;
2730 struct card_dat
*dirblock
= NULL
;
2731 struct card_direntry
*entry
= NULL
;
2733 printf("CARD_CreateEntryAsync(%d,%p,%p,%p)\n",chn
,direntry
,file
,callback
);
2735 len
= strlen((const char*)direntry
->filename
);
2736 if(len
>CARD_FILENAMELEN
) return CARD_ERROR_NAMETOOLONG
;
2738 if((ret
=__card_getcntrlblock(chn
,&card
))<0) return ret
;
2739 if(direntry
->filelen
<=0 || direntry
->filelen
%card
->sector_size
) return CARD_ERROR_FATAL_ERROR
;
2741 dirblock
= __card_getdirblock(card
);
2744 entry
= dirblock
->entries
;
2745 for(i
=0;i
<CARD_MAXFILES
;i
++) {
2746 if(entry
[i
].gamecode
[0]==0xff) {
2747 if(filenum
==-1) filenum
= i
;
2748 } else if(memcmp(entry
[i
].filename
,direntry
->filename
,len
)==0) {
2749 if((entry
->gamecode
[0]==0xff || entry
->company
[0]==0xff)
2750 || ((entry
->gamecode
[0]!=0xff && memcmp(entry
[i
].gamecode
,entry
->gamecode
,4)==0)
2751 && (entry
->company
[0]!=0xff && memcmp(entry
[i
].company
,entry
->company
,2)==0))) {
2752 __card_putcntrlblock(card
,CARD_ERROR_EXIST
);
2753 return CARD_ERROR_EXIST
;
2758 __card_putcntrlblock(card
,CARD_ERROR_NOENT
);
2759 return CARD_ERROR_NOENT
;
2762 fatblock
= __card_getbatblock(card
);
2763 if((fatblock
->freeblocks
*card
->sector_size
)<direntry
->filelen
) {
2764 __card_putcntrlblock(card
,CARD_ERROR_INSSPACE
);
2765 return CARD_ERROR_INSSPACE
;
2769 if(!cb
) cb
= __card_defaultapicallback
;
2770 card
->card_api_cb
= cb
;
2772 entry
[filenum
].length
= direntry
->filelen
/card
->sector_size
;
2773 memset(entry
[filenum
].filename
,0,CARD_FILENAMELEN
);
2774 memcpy(entry
[filenum
].filename
,direntry
->filename
,len
+1);
2776 card
->curr_file
= file
;
2778 file
->filenum
= filenum
;
2779 if((ret
=__card_allocblock(chn
,(direntry
->filelen
/card
->sector_size
),__card_createfatcallback
))<0) {
2780 __card_putcntrlblock(card
,ret
);
2787 s32
CARD_CreateEntry(s32 chn
,card_dir
*direntry
,card_file
*file
)
2791 if((ret
=CARD_CreateEntryAsync(chn
,direntry
,file
,__card_synccallback
))>=0) {
2792 ret
= __card_sync(chn
);
2797 s32
CARD_Open(s32 chn
,const char *filename
,card_file
*file
)
2800 struct card_dat
*dirblock
= NULL
;
2801 card_block
*card
= NULL
;
2803 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
2806 if((ret
=__card_getcntrlblock(chn
,&card
))<0) return ret
;
2807 if((ret
=__card_getfilenum(card
,filename
,(const char*)card_gamecode
,(const char*)card_company
,&fileno
))<0) {
2808 __card_putcntrlblock(card
,ret
);
2811 dirblock
= __card_getdirblock(card
);
2812 if(dirblock
->entries
[fileno
].block
<5 || dirblock
->entries
[fileno
].block
>=card
->blocks
) {
2813 __card_putcntrlblock(card
,CARD_ERROR_BROKEN
);
2814 return CARD_ERROR_BROKEN
;
2817 file
->filenum
= fileno
;
2819 file
->len
= dirblock
->entries
[fileno
].length
*card
->sector_size
;
2820 file
->iblock
= dirblock
->entries
[fileno
].block
;
2822 __card_putcntrlblock(card
,CARD_ERROR_READY
);
2823 return CARD_ERROR_READY
;
2826 s32
CARD_OpenEntry(s32 chn
,card_dir
*entry
,card_file
*file
)
2829 struct card_dat
*dirblock
= NULL
;
2830 card_block
*card
= NULL
;
2832 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
2835 if((ret
=__card_getcntrlblock(chn
,&card
))<0) return ret
;
2836 if((ret
=__card_getfilenum(card
,(const char*)entry
->filename
,(const char*)entry
->gamecode
,(const char*)entry
->company
,&fileno
))<0) {
2837 __card_putcntrlblock(card
,ret
);
2841 dirblock
= __card_getdirblock(card
);
2842 if(dirblock
->entries
[fileno
].block
<5 || dirblock
->entries
[fileno
].block
>=card
->blocks
) {
2843 __card_putcntrlblock(card
,CARD_ERROR_BROKEN
);
2844 return CARD_ERROR_BROKEN
;
2848 file
->filenum
= entry
->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_Close(card_file
*file
)
2860 card_block
*card
= NULL
;
2862 if(file
->chn
<EXI_CHANNEL_0
|| file
->chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
2863 if(file
->filenum
<0 || file
->filenum
>=CARD_MAXFILES
) return CARD_ERROR_NOFILE
;
2864 if((ret
=__card_getcntrlblock(file
->chn
,&card
))<0) return ret
;
2867 __card_putcntrlblock(card
,CARD_ERROR_READY
);
2868 return CARD_ERROR_READY
;
2871 s32
CARD_DeleteAsync(s32 chn
,const char *filename
,cardcallback callback
)
2874 cardcallback cb
= NULL
;
2875 card_block
*card
= NULL
;
2876 struct card_dat
*dirblock
= NULL
;
2877 struct card_direntry
*entry
= NULL
;
2879 printf("CARD_DeleteAsync(%d,%s,%p)\n",chn
,filename
,callback
);
2881 if((ret
=__card_getcntrlblock(chn
,&card
))<0) return ret
;
2882 if((ret
=__card_getfilenum(card
,filename
,(const char*)card_gamecode
,(const char*)card_company
,&fileno
))<0) {
2883 __card_putcntrlblock(card
,ret
);
2887 dirblock
= __card_getdirblock(card
);
2888 entry
= &dirblock
->entries
[fileno
];
2890 card
->curr_fileblock
= entry
->block
;
2891 memset(entry
,-1,sizeof(struct card_direntry
));
2894 if(!cb
) cb
= __card_defaultapicallback
;
2895 card
->card_api_cb
= cb
;
2897 if((ret
=__card_updatedir(chn
,__delete_callback
))>=0) return ret
;
2899 __card_putcntrlblock(card
,ret
);
2903 s32
CARD_Delete(s32 chn
,const char *filename
)
2907 printf("CARD_Delete(%d,%s)\n",chn
,filename
);
2909 if((ret
=CARD_DeleteAsync(chn
,filename
,__card_synccallback
))>=0) {
2910 ret
= __card_sync(chn
);
2915 s32
CARD_DeleteEntryAsync(s32 chn
,card_dir
*dir_entry
,cardcallback callback
)
2918 cardcallback cb
= NULL
;
2919 card_block
*card
= NULL
;
2920 struct card_dat
*dirblock
= NULL
;
2921 struct card_direntry
*entry
= NULL
;
2923 printf("CARD_DeleteEntryAsync(%p,%p)\n",dir_entry
,callback
);
2925 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
2926 if((ret
=__card_getcntrlblock(chn
,&card
))<0) return ret
;
2928 dirblock
= __card_getdirblock(card
);
2929 entry
= &dirblock
->entries
[dir_entry
->fileno
];
2931 card
->curr_fileblock
= entry
->block
;
2932 memset(entry
,-1,sizeof(struct card_direntry
));
2935 if(!cb
) cb
= __card_defaultapicallback
;
2936 card
->card_api_cb
= cb
;
2938 if((ret
=__card_updatedir(chn
,__delete_callback
))>=0) return ret
;
2940 __card_putcntrlblock(card
,ret
);
2944 s32
CARD_DeleteEntry(s32 chn
,card_dir
*dir_entry
)
2948 printf("CARD_DeleteEntry(%p)\n",dir_entry
);
2950 if((ret
=CARD_DeleteEntryAsync(chn
,dir_entry
,__card_synccallback
))>=0) {
2951 ret
= __card_sync(chn
);
2956 s32
CARD_FormatAsync(s32 chn
,cardcallback callback
)
2960 enc
= SYS_GetFontEncoding();
2961 return __card_formatregion(chn
,enc
,callback
);
2964 s32
CARD_Format(s32 chn
)
2969 enc
= SYS_GetFontEncoding();
2970 if((ret
=__card_formatregion(chn
,enc
,__card_synccallback
))>=0) {
2971 ret
= __card_sync(chn
);
2976 s32
CARD_GetErrorCode(s32 chn
)
2978 card_block
*card
= NULL
;
2980 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
2981 card
= &cardmap
[chn
];
2982 return card
->result
;
2985 s32
__card_findnext(card_dir
*dir
)
2988 struct card_dat
*dirblock
= NULL
;
2989 struct card_direntry
*entries
= NULL
;
2990 card_block
*card
= NULL
;
2992 if(dir
->chn
<EXI_CHANNEL_0
|| dir
->chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
2993 if(dir
->fileno
>=CARD_MAXFILES
) return CARD_ERROR_NOFILE
;
2994 if((ret
=__card_getcntrlblock(dir
->chn
,&card
))<0) return ret
;
2996 if(!card
->attached
) return CARD_ERROR_NOCARD
;
2997 dirblock
= __card_getdirblock(card
);
2999 entries
= dirblock
->entries
;
3001 //printf("%s\n", entries[dir->fileno].filename);
3002 if(entries
[dir
->fileno
].gamecode
[0]!=0xff) {
3003 if ((dir
->showall
|| memcmp(entries
[dir
->fileno
].gamecode
,card_gamecode
,4)==0)
3004 && (dir
->showall
|| memcmp(entries
[dir
->fileno
].company
,card_company
,2)==0)) {
3005 dir
->filelen
= entries
[dir
->fileno
].length
*card
->sector_size
;
3006 memcpy(dir
->filename
, entries
[dir
->fileno
].filename
, CARD_FILENAMELEN
);
3007 memcpy(dir
->gamecode
, entries
[dir
->fileno
].gamecode
, 4);
3008 memcpy(dir
->company
, entries
[dir
->fileno
].company
, 2);
3010 __card_putcntrlblock(card
,CARD_ERROR_READY
);
3011 return CARD_ERROR_READY
;
3015 } while (dir
->fileno
< CARD_MAXFILES
);
3016 __card_putcntrlblock(card
,CARD_ERROR_NOFILE
);
3017 return CARD_ERROR_NOFILE
;
3020 s32
CARD_FindFirst(s32 chn
, card_dir
*dir
, bool showall
)
3022 // initialise structure
3026 dir
->filename
[0] = 0;
3027 dir
->gamecode
[0] = 0;
3028 dir
->company
[0] = 0;
3029 dir
->showall
= showall
;
3030 return __card_findnext(dir
);
3033 s32
CARD_FindNext(card_dir
*dir
)
3037 return __card_findnext(dir
);
3040 s32
CARD_GetDirectory(s32 chn
,card_dir
*dir_entries
,s32
*count
,bool showall
)
3043 s32 ret
= CARD_ERROR_READY
;
3044 struct card_dat
*dirblock
= NULL
;
3045 struct card_direntry
*entries
= NULL
;
3046 card_block
*card
= NULL
;
3048 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
3049 if((ret
=__card_getcntrlblock(chn
,&card
))<0) return ret
;
3051 if(!card
->attached
) return CARD_ERROR_NOCARD
;
3052 dirblock
= __card_getdirblock(card
);
3054 entries
= dirblock
->entries
;
3055 for(i
=0,cnt
=0;i
<CARD_MAXFILES
;i
++) {
3056 if(entries
[i
].gamecode
[0]!=0xff) {
3057 if(showall
|| ((card_gamecode
[0]!=0xff && memcmp(entries
[i
].gamecode
,card_gamecode
,4)==0)
3058 && (card_company
[0]!=0xff && memcmp(entries
[i
].company
,card_company
,2)==0))) {
3059 dir_entries
[cnt
].fileno
= i
;
3060 dir_entries
[cnt
].permissions
= entries
[i
].permission
;
3061 dir_entries
[cnt
].filelen
= entries
[i
].length
*card
->sector_size
;
3062 memcpy(dir_entries
[cnt
].gamecode
,entries
[i
].gamecode
,4);
3063 memcpy(dir_entries
[cnt
].company
,entries
[i
].company
,2);
3064 memcpy(dir_entries
[cnt
].filename
,entries
[i
].filename
,CARD_FILENAMELEN
);
3069 if(count
) *count
= cnt
;
3070 if(cnt
==0) ret
= CARD_ERROR_NOFILE
;
3071 __card_putcntrlblock(card
,ret
);
3075 s32
CARD_GetSectorSize(s32 chn
,u32
*sector_size
)
3078 card_block
*card
= NULL
;
3080 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
3081 if((ret
=__card_getcntrlblock(chn
,&card
))<0) return ret
;
3083 *sector_size
= card
->sector_size
;
3084 ret
= __card_putcntrlblock(card
,CARD_ERROR_READY
);
3089 s32
CARD_GetBlockCount(s32 chn
,u32
*block_count
)
3092 card_block
*card
= NULL
;
3094 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
3095 if((ret
=__card_getcntrlblock(chn
,&card
))<0) return ret
;
3097 *block_count
= card
->blocks
;
3098 ret
= __card_putcntrlblock(card
,CARD_ERROR_READY
);
3103 s32
CARD_GetStatus(s32 chn
,s32 fileno
,card_stat
*stats
)
3106 card_block
*card
= NULL
;
3107 struct card_dat
*dirblock
= NULL
;
3108 struct card_direntry
*entry
= NULL
;
3110 if(chn
<EXI_CHANNEL_0
|| chn
>=EXI_CHANNEL_2
) return CARD_ERROR_NOCARD
;
3111 if(fileno
<0 || fileno
>=CARD_MAXFILES
) return CARD_ERROR_FATAL_ERROR
;
3113 if((ret
=__card_getcntrlblock(chn
,&card
))<0) return ret
;
3115 dirblock
= __card_getdirblock(card
);
3117 entry
= &dirblock
->entries
[fileno
];
3118 memcpy(stats
->gamecode
,entry
->gamecode
,4);
3119 memcpy(stats
->company
,entry
->company
,2);
3120 memcpy(stats
->filename
,entry
->filename
,CARD_FILENAMELEN
);
3121 stats
->len
= entry
->length
*card
->sector_size
;
3122 stats
->time
= entry
->lastmodified
;
3123 stats
->banner_fmt
= entry
->bannerfmt
;
3124 stats
->icon_addr
= entry
->iconaddr
;
3125 stats
->icon_fmt
= entry
->iconfmt
;
3126 stats
->icon_speed
= entry
->iconspeed
;
3127 stats
->comment_addr
= entry
->commentaddr
;
3128 __card_updateiconoffsets(entry
,stats
);
3131 return __card_putcntrlblock(card
,CARD_ERROR_READY
);
3134 s32
CARD_SetStatusAsync(s32 chn
,s32 fileno
,card_stat
*stats
,cardcallback callback
)
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
;
3143 if(stats
->icon_addr
!=-1 && stats
->icon_addr
>CARD_READSIZE
) return CARD_ERROR_FATAL_ERROR
;
3144 if(stats
->comment_addr
!=-1 && stats
->comment_addr
>8128) return CARD_ERROR_FATAL_ERROR
;
3145 if((ret
=__card_getcntrlblock(chn
,&card
))<0) return ret
;
3147 ret
= CARD_ERROR_BROKEN
;
3148 dirblock
= __card_getdirblock(card
);
3150 entry
= &dirblock
->entries
[fileno
];
3151 entry
->bannerfmt
= stats
->banner_fmt
;
3152 entry
->iconaddr
= stats
->icon_addr
;
3153 entry
->iconfmt
= stats
->icon_fmt
;
3154 entry
->iconspeed
= stats
->icon_speed
;
3155 entry
->commentaddr
= stats
->comment_addr
;
3156 __card_updateiconoffsets(entry
,stats
);
3158 if(entry
->iconaddr
==-1) entry
->iconfmt
= ((entry
->iconfmt
&~CARD_ICON_MASK
)|CARD_ICON_CI
);
3160 entry
->lastmodified
= time(NULL
);
3161 if((ret
=__card_updatedir(chn
,callback
))>=0) return ret
;
3164 return __card_putcntrlblock(card
,ret
);
3167 s32
CARD_SetStatus(s32 chn
,s32 fileno
,card_stat
*stats
)
3171 if((ret
=CARD_SetStatusAsync(chn
,fileno
,stats
,__card_synccallback
))>=0) {
3172 ret
= __card_sync(chn
);
3177 s32
CARD_GetAttributes(s32 chn
,s32 fileno
,u8
*attr
)
3180 struct card_direntry entry
;
3182 if((ret
=__card_getstatusex(chn
,fileno
,&entry
))==CARD_ERROR_READY
) {
3183 *attr
= entry
.permission
;
3188 s32
CARD_SetAttributesAsync(s32 chn
,s32 fileno
,u8 attr
,cardcallback callback
)
3191 struct card_direntry entry
;
3193 if((ret
=__card_getstatusex(chn
,fileno
,&entry
))>=0) {
3194 entry
.permission
= attr
;
3195 ret
= __card_setstatusexasync(chn
,fileno
,&entry
,callback
);
3200 s32
CARD_SetAttributes(s32 chn
,s32 fileno
,u8 attr
)
3204 if((ret
=CARD_SetAttributesAsync(chn
,fileno
,attr
,__card_synccallback
))>=0) {
3205 ret
= __card_sync(chn
);
3210 s32
CARD_SetCompany(const char *company
)
3214 _CPU_ISR_Disable(level
);
3215 for(i
=0;i
<2;i
++) card_company
[i
] = 0xff;
3216 if(company
&& strlen(company
)<=2) memcpy(card_company
,company
,2) ;
3217 _CPU_ISR_Restore(level
);
3219 return CARD_ERROR_READY
;
3222 s32
CARD_SetGamecode(const char *gamecode
)
3226 _CPU_ISR_Disable(level
);
3227 for(i
=0;i
<4;i
++) card_gamecode
[i
] = 0xff;
3228 if(gamecode
&& strlen(gamecode
)<=4) memcpy(card_gamecode
,gamecode
,4) ;
3229 _CPU_ISR_Restore(level
);
3231 return CARD_ERROR_READY
;