mgh: fix for default HDD DMA mode, that wasn't correctly set
[open-ps2-loader.git] / modules / vmc / mcman / mcsio2.c
blob7a5d336e8989a021854d6995b49bc8f8d20727ac
1 /*
2 Copyright 2009-2010, jimmikaelkael
3 Licenced under Academic Free License version 3.0
4 Review Open PS2 Loader README & LICENSE files for further details.
5 */
7 #include "mcman.h"
9 extern int timer_ID;
11 // mcman cmd table used by sio2packet_add fnc
12 u8 mcman_cmdtable[36] = {
13 0x11, 0x04, 0x12, 0x04, 0x21, 0x09, 0x22, 0x09,
14 0x23, 0x09, 0x24, 0x86, 0x25, 0x04, 0x26, 0x0d,
15 0x27, 0x05, 0x28, 0x05, 0x42, 0x86, 0x43, 0x86,
16 0x81, 0x04, 0x82, 0x04, 0x42, 0x06, 0x43, 0x06,
17 0xbf, 0x05, 0xf3, 0x05
20 // sio2packet_add child functions
21 void (*sio2packet_add_func)(int port, int slot, int cmd, u8 *buf, int pos);
22 void sio2packet_add_wdma_u32(int port, int slot, int cmd, u8 *buf, int pos);
23 void sio2packet_add_pagedata_out(int port, int slot, int cmd, u8 *buf, int pos);
24 void sio2packet_add_pagedata_in(int port, int slot, int cmd, u8 *buf, int pos);
25 void sio2packet_add_ecc_in(int port, int slot, int cmd, u8 *buf, int pos);
26 void sio2packet_add_ecc_out(int port, int slot, int cmd, u8 *buf, int pos);
27 void sio2packet_add_wdma_5a(int port, int slot, int cmd, u8 *buf, int pos);
28 void sio2packet_add_wdma_00(int port, int slot, int cmd, u8 *buf, int pos);
29 void sio2packet_add_wdma_u8(int port, int slot, int cmd, u8 *buf, int pos);
30 void sio2packet_add_do_nothing(int port, int slot, int cmd, u8 *buf, int pos);
32 // functions pointer array to handle sio2packet_add inner functions calls
33 void *sio2packet_add_funcs_array[16] = {
34 (void *)sio2packet_add_wdma_00, // commands that needs to clear in_dma.addr[2]
35 (void *)sio2packet_add_wdma_u32, // commands that needs to copy an int to in_dma.addr[2..5] (an int* can be passed as arg into buf)
36 (void *)sio2packet_add_wdma_u32, // ...
37 (void *)sio2packet_add_wdma_u32, // ...
38 (void *)sio2packet_add_wdma_u8, // commands that needs to copy an u8 value to in_dma.addr[2]
39 (void *)sio2packet_add_do_nothing, // do nothing
40 (void *)sio2packet_add_do_nothing, // ...
41 (void *)sio2packet_add_wdma_5a, // commands that needs to set in_dma.addr[2] to value 0x5a, used to set termination code
42 (void *)sio2packet_add_do_nothing, // do nothing
43 (void *)sio2packet_add_pagedata_in, // commands that needs to copy pagedata buf into in_dma.addr
44 (void *)sio2packet_add_pagedata_out,// commands that needs to set in_dma.addr[2] to value 128 for pagedata out
45 (void *)sio2packet_add_do_nothing, // do nothing
46 (void *)sio2packet_add_do_nothing, // ...
47 (void *)sio2packet_add_ecc_in, // commands that needs to copy sparedata buf into in_dma.addr
48 (void *)sio2packet_add_ecc_out, // commands that needs to prepare regdata and in_dma.addr to receive sparedata
49 (void *)sio2packet_add_wdma_u8 // commands that needs to copy an u8 value to in_dma.addr[2]
52 //--------------------------------------------------------------
53 void sio2packet_add(int port, int slot, int cmd, u8 *buf)
54 { // Used to build the sio2packets for all mc commands
55 register u32 regdata;
56 register int pos;
57 u8 *p;
59 if (cmd == 0xffffffff) {
60 mcman_sio2packet.in_dma.count = 0;
61 return;
64 if (mcman_sio2packet.in_dma.count < 0xb) {
66 if (cmd == 0xfffffffe) {
67 mcman_sio2packet.regdata[mcman_sio2packet.in_dma.count] = 0;
68 mcman_sio2packet.out_dma.count = mcman_sio2packet.in_dma.count;
69 return;
72 regdata = (((port & 1) + 2) & 3) | 0x70;
73 regdata |= mcman_cmdtable[(cmd << 1) + 1] << 18;
74 regdata |= mcman_cmdtable[(cmd << 1) + 1] << 8;
76 mcman_sio2packet.regdata[mcman_sio2packet.in_dma.count] = regdata;
78 pos = ((mcman_sio2packet.in_dma.count + (mcman_sio2packet.in_dma.count << 3)) << 4);
80 mcman_sio2packet.in_dma.count++;
82 p = mcman_sio2packet.in_dma.addr + pos;
83 p[0] = 0x81;
84 p[1] = mcman_cmdtable[cmd << 1];
86 if (((cmd - 1) >= 16) || ((cmd - 1) < 0))
87 return;
89 sio2packet_add_func = (void*)sio2packet_add_funcs_array[(cmd - 1)];
90 (sio2packet_add_func)(port, slot, cmd, buf, pos); // call to the needed child func
94 //----
95 // sio2packet child funcs
97 void sio2packet_add_wdma_u32(int port, int slot, int cmd, u8 *buf, int pos)
99 u8 *p = mcman_sio2packet.in_dma.addr + pos;
100 p[2] = buf[0];
101 p[3] = buf[1];
102 p[4] = buf[2];
103 p[5] = buf[3];
104 p[6] = mcman_calcEDC(&p[2], 4);
107 //--
109 void sio2packet_add_pagedata_out(int port, int slot, int cmd, u8 *buf, int pos)
111 // used for sio2 command 0x81 0x43 to read page data
112 u8 *p = mcman_sio2packet.in_dma.addr + pos;
113 p[2] = 128;
116 //--
118 void sio2packet_add_pagedata_in(int port, int slot, int cmd, u8 *buf, int pos)
120 // used for sio2 command 0x81 0x42 to write page data
121 register int i;
122 u8 *p = mcman_sio2packet.in_dma.addr + pos;
123 p[2] = 128;
125 for (i=0; i<128; i++)
126 p[3 + i] = buf[i];
128 p[3 + 128] = mcman_calcEDC(&buf[0], 128);
131 //--
133 void sio2packet_add_ecc_in(int port, int slot, int cmd, u8 *buf, int pos)
135 // used for sio2 command 0x81 0x42 to write page ecc
136 register u32 regdata;
137 int i;
138 u8 *p = mcman_sio2packet.in_dma.addr + pos;
140 p[2] = mcman_sparesize(port, slot);
142 for (i=0; i<(p[2] & 0xff); i++)
143 p[3 + i] = buf[i];
145 p[3 + p[2]] = mcman_calcEDC(&buf[0], p[2]);
147 regdata = (p[2] + mcman_cmdtable[(cmd << 1) + 1]) << 18;
148 regdata |= mcman_sio2packet.regdata[mcman_sio2packet.in_dma.count-1] & 0xf803ffff;
149 regdata &= 0xfffe00ff;
150 regdata |= (p[2] + mcman_cmdtable[(cmd << 1) + 1]) << 8;
152 mcman_sio2packet.regdata[mcman_sio2packet.in_dma.count-1] = regdata;
155 //--
157 void sio2packet_add_ecc_out(int port, int slot, int cmd, u8 *buf, int pos)
159 // used for sio2 command 0x81 0x43 to read page ecc
160 register u32 regdata;
161 u8 *p = mcman_sio2packet.in_dma.addr + pos;
163 p[2] = mcman_sparesize(port, slot);
165 regdata = (p[2] + mcman_cmdtable[(cmd << 1) + 1]) << 18;
166 regdata |= mcman_sio2packet.regdata[mcman_sio2packet.in_dma.count-1] & 0xf803ffff;
167 regdata &= 0xfffe00ff;
168 regdata |= (p[2] + mcman_cmdtable[(cmd << 1) + 1]) << 8;
170 mcman_sio2packet.regdata[mcman_sio2packet.in_dma.count-1] = regdata;
173 //--
175 void sio2packet_add_wdma_5a(int port, int slot, int cmd, u8 *buf, int pos)
177 // used for sio2 command 0x81 0x27 to set a termination code
178 u8 *p = mcman_sio2packet.in_dma.addr + pos;
179 p[2] = 0x5a;
182 //--
184 void sio2packet_add_wdma_00(int port, int slot, int cmd, u8 *buf, int pos)
186 u8 *p = mcman_sio2packet.in_dma.addr + pos;
187 p[2] = 0x00;
191 //--
193 void sio2packet_add_wdma_u8(int port, int slot, int cmd, u8 *buf, int pos)
195 u8 *p = mcman_sio2packet.in_dma.addr + pos;
196 p[2] = buf[0];
199 //--
201 void sio2packet_add_do_nothing(int port, int slot, int cmd, u8 *buf, int pos)
203 // do nothing
206 //--------------------------------------------------------------
207 int mcsio2_transfer(int port, int slot, sio2_transfer_data_t *sio2data)
209 register int r;
211 #ifdef DEBUG
212 u8 *p = (u8 *)(sio2data->in_dma.addr);
213 if (p)
214 DPRINTF("mcman: mcsio2_transfer port%d slot%d cmd = %02x %02x %02x ", port, slot, p[0], p[1], p[2]);
215 else {
216 p = (u8 *)(sio2data->in);
217 DPRINTF("mcman: mcsio2_transfer for secrman port%d slot%d cmd = %02x %02x %02x ", port, slot, p[0], p[1], p[2]);
219 #endif
221 // SIO2 transfer for MCMAN
222 sio2_mc_transfer_init();
223 r = sio2_transfer(sio2data);
225 #ifdef DEBUG
226 DPRINTF("returns %d\n", r);
227 #endif
229 return r;
232 //--------------------------------------------------------------
233 int mcsio2_transfer2(int port, int slot, sio2_transfer_data_t *sio2data)
235 // SIO2 transfer for XMCMAN
236 register int r;
237 int port_ctrl[8];
239 #ifdef DEBUG
240 DPRINTF("mcman: mcsio2_transfer2 port%d slot%d\n", port, slot);
241 #endif
243 port_ctrl[0] = -1;
244 port_ctrl[1] = -1;
245 port_ctrl[2] = -1;
246 port_ctrl[3] = -1;
248 port_ctrl[(port & 1) + 2] = slot;
250 sio2_mc_transfer_init();
251 sio2_func1(&port_ctrl);
252 r = sio2_transfer(sio2data);
253 sio2_transfer_reset();
255 #ifdef DEBUG
256 DPRINTF("mcman: mcsio2_transfer2 returns %d\n", r);
257 #endif
259 return r;
262 //--------------------------------------------------------------
263 void mcman_initPS2com(void)
265 mcman_wmemset((void *)&mcman_sio2packet, sizeof (mcman_sio2packet), 0);
267 mcman_sio2packet.port_ctrl1[2] = 0xff020405;
268 mcman_sio2packet.port_ctrl1[3] = 0xff020405;
269 mcman_sio2packet.port_ctrl2[2] = 0x0005ffff & 0xfcffffff;
270 mcman_sio2packet.port_ctrl2[3] = 0x0005ffff & 0xfcffffff;
272 mcman_sio2packet.in_dma.addr = &mcman_wdmabufs;
273 mcman_sio2packet.in_dma.size = 0x24;
275 mcman_sio2packet.out_dma.addr = &mcman_rdmabufs;
276 mcman_sio2packet.out_dma.size = 0x24;
278 #ifdef DEBUG
279 DPRINTF("mcman: mcman_initPS2com registering secrman_mc_command callback\n");
280 #endif
281 SetMcCommandCallback((void *)secrman_mc_command);
283 #ifdef DEBUG
284 DPRINTF("mcman: mcman_initPS2com registering mcman_getcnum callback\n");
285 #endif
287 SetMcDevIDCallback((void *)mcman_getcnum);
290 //--------------------------------------------------------------
291 void mcman_initPS1PDAcom(void)
293 memset((void *)&mcman_sio2packet_PS1PDA, 0, sizeof (mcman_sio2packet_PS1PDA));
295 mcman_sio2packet_PS1PDA.port_ctrl1[0] = 0xffc00505;
296 mcman_sio2packet_PS1PDA.port_ctrl1[1] = 0xffc00505;
297 mcman_sio2packet_PS1PDA.port_ctrl1[2] = 0xffc00505;
298 mcman_sio2packet_PS1PDA.port_ctrl1[3] = 0xffc00505;
300 mcman_sio2packet_PS1PDA.port_ctrl2[0] = 0x000201f4 & 0xfcffffff;
301 mcman_sio2packet_PS1PDA.port_ctrl2[1] = 0x000201f4 & 0xfcffffff;
302 mcman_sio2packet_PS1PDA.port_ctrl2[2] = 0x000201f4 & 0xfcffffff;
303 mcman_sio2packet_PS1PDA.port_ctrl2[3] = 0x000201f4 & 0xfcffffff;
305 mcman_sio2packet_PS1PDA.in = (u8 *)&mcman_sio2inbufs_PS1PDA;
306 mcman_sio2packet_PS1PDA.out = (u8 *)&mcman_sio2outbufs_PS1PDA;
309 //--------------------------------------------------------------
310 int secrman_mc_command(int port, int slot, sio2_transfer_data_t *sio2data)
312 register int r;
314 #ifdef DEBUG
315 DPRINTF("mcman: secrman_mc_command port%d slot%d\n", port, slot);
316 #endif
318 r = mcman_sio2transfer(port, slot, sio2data);
320 return r;
323 //--------------------------------------------------------------
324 int mcman_cardchanged(int port, int slot)
326 register int retries;
327 u8 *p = mcman_sio2packet.out_dma.addr;
329 #ifdef DEBUG
330 DPRINTF("mcman: mcman_cardchanged sio2cmd port%d slot%d\n", port, slot);
331 #endif
333 sio2packet_add(port, slot, 0xffffffff, NULL);
334 sio2packet_add(port, slot, 0, NULL);
335 sio2packet_add(port, slot, 0xfffffffe, NULL);
337 retries = 0;
338 do {
339 mcman_sio2transfer(port, slot, &mcman_sio2packet);
341 if (((mcman_sio2packet.stat6c & 0xF000) == 0x1000) && (p[3] != 0x66))
342 break;
344 } while (++retries < 5);
346 if (retries >= 5) {
347 #ifdef DEBUG
348 DPRINTF("mcman: mcman_cardchanged sio2cmd card changed!\n");
349 #endif
350 return sceMcResChangedCard;
353 #ifdef DEBUG
354 DPRINTF("mcman: mcman_cardchanged sio2cmd succeeded\n");
355 #endif
357 return sceMcResSucceed;
360 //--------------------------------------------------------------
361 int mcman_eraseblock(int port, int slot, int block, void **pagebuf, void *eccbuf)
363 register int retries, size, ecc_offset;
364 int page;
365 u8 *p = mcman_sio2packet.out_dma.addr;
366 void *p_ecc;
367 register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
369 page = block * mcdi->blocksize;
371 sio2packet_add(port, slot, 0xffffffff, NULL);
372 sio2packet_add(port, slot, 0x02, (u8 *)&page);
373 sio2packet_add(port, slot, 0x0d, NULL);
374 sio2packet_add(port, slot, 0xfffffffe, NULL);
376 retries = 0;
377 do {
378 mcman_sio2transfer(port, slot, &mcman_sio2packet);
380 if (((mcman_sio2packet.stat6c & 0xF000) != 0x1000) || (p[8] != 0x5a))
381 continue;
383 if (p[0x93] == p[8])
384 break;
385 } while (++retries < 5);
387 if (retries >= 5)
388 return sceMcResChangedCard;
390 if (pagebuf && eccbuf) { // This part leave the first ecc byte of each block page in eccbuf
391 mcman_wmemset(eccbuf, 32, 0);
393 page = 0;
394 while (page < mcdi->blocksize) {
395 ecc_offset = page * mcdi->pagesize;
396 if (ecc_offset < 0)
397 ecc_offset += 0x1f;
398 ecc_offset = ecc_offset >> 5;
399 p_ecc = (void *)(eccbuf + ecc_offset);
400 size = 0;
401 while (size < mcdi->pagesize) {
402 if (*pagebuf)
403 McDataChecksum((void *)(*pagebuf + size), p_ecc);
404 size += 128;
405 p_ecc += 3;
407 pagebuf++;
408 page++;
412 sio2packet_add(port, slot, 0xffffffff, NULL);
413 sio2packet_add(port, slot, 0x1, NULL);
414 sio2packet_add(port, slot, 0xfffffffe, NULL);
416 retries = 0;
417 do {
418 mcman_sio2transfer(port, slot, &mcman_sio2packet);
420 if (((mcman_sio2packet.stat6c & 0xF000) != 0x1000))
421 continue;
423 if (p[3] == 0x5a)
424 return sceMcResSucceed;
425 } while (++retries < 100);
427 if (p[3] == 0x66)
428 return sceMcResFailReplace;
430 return sceMcResNoFormat;
433 //--------------------------------------------------------------
434 int McWritePage(int port, int slot, int page, void *pagebuf, void *eccbuf) // Export #19
436 register int index, count, retries;
437 u8 *p_pagebuf = (u8 *)pagebuf;
438 u8 *p = mcman_sio2packet.out_dma.addr;
440 count = (mcman_devinfos[port][slot].pagesize + 127) >> 7;
442 retries = 0;
444 do {
445 if (retries > 0)
446 mcman_cardchanged(port, slot);
448 sio2packet_add(port, slot, 0xffffffff, NULL);
449 sio2packet_add(port, slot, 0x03, (u8 *)&page);
451 index = 0;
452 while (index < count) {
453 sio2packet_add(port, slot, 0x0a, (u8 *)&p_pagebuf[index << 7]);
454 index++;
457 if (mcman_devinfos[port][slot].cardflags & CF_USE_ECC) {
458 // if memcard have ECC support
459 sio2packet_add(port, slot, 0x0e, eccbuf);
461 sio2packet_add(port, slot, 0xfffffffe, NULL);
463 mcman_sio2transfer(port, slot, &mcman_sio2packet);
465 if (((mcman_sio2packet.stat6c & 0xF000) != 0x1000) || (p[8] != 0x5a))
466 continue;
468 index = 0;
469 while (index < count) {
470 if (p[0x94 + 128 + 1 + ((index + (index << 3)) << 4)] != 0x5a)
471 break;
472 index++;
475 if (index < count)
476 continue;
478 if (mcman_devinfos[port][slot].cardflags & CF_USE_ECC) {
479 // if memcard have ECC support
480 index++;
481 if (p[5 + ((index + (index << 3)) << 4) + mcman_sparesize(port, slot)] != 0x5a)
482 continue;
485 sio2packet_add(port, slot, 0xffffffff, NULL);
486 sio2packet_add(port, slot, 0x0c, NULL);
487 sio2packet_add(port, slot, 0xfffffffe, NULL);
489 mcman_sio2transfer(port, slot, &mcman_sio2packet);
491 if (((mcman_sio2packet.stat6c & 0xF000) != 0x1000) || (p[3] != 0x5a))
492 continue;
494 return sceMcResSucceed;
496 } while (++retries < 5);
498 if (p[3] == 0x66)
499 return sceMcResFailReplace;
501 return sceMcResNoFormat;
504 //--------------------------------------------------------------
505 int mcman_readpage(int port, int slot, int page, void *buf, void *eccbuf)
507 register int index, count, retries, r, i;
508 register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
509 u8 *pbuf = (u8 *)buf;
510 u8 *pecc = (u8 *)eccbuf;
511 u8 *p = mcman_sio2packet.out_dma.addr;
513 count = (mcdi->pagesize + 127) >> 7;
515 retries = 0;
517 do {
518 if (retries > 0)
519 mcman_cardchanged(port, slot);
521 sio2packet_add(port, slot, 0xffffffff, NULL);
522 sio2packet_add(port, slot, 0x04, (u8 *)&page);
524 if (count > 0) {
525 index = 0;
526 while (index < count) {
527 sio2packet_add(port, slot, 0x0b, NULL);
528 index++;
532 if (mcdi->cardflags & CF_USE_ECC) // if memcard have ECC support
533 sio2packet_add(port, slot, 0x0f, NULL);
535 sio2packet_add(port, slot, 0x0c, NULL);
536 sio2packet_add(port, slot, 0xfffffffe, NULL);
538 mcman_sio2transfer(port, slot, &mcman_sio2packet);
540 if (((mcman_sio2packet.stat6c & 0xF000) != 0x1000)
541 || (p[8] != 0x5a)
542 || (p[0x94 + 0x2cf] != 0x5a))
543 continue;
545 if (count > 0) {
546 index = 0;
547 while (index < count) {
548 // checking EDC
549 r = mcman_calcEDC(&p[0x94 + ((index + (index << 3)) << 4)], 128) & 0xFF;
550 if (r != p[0x94 + 128 + ((index + (index << 3)) << 4)])
551 break;
552 index++;
555 if (index < count)
556 continue;
558 index = 0;
559 while (index < count) {
560 for (i=0; i<128; i++)
561 pbuf[(index << 7) + i] = p[0x94 + ((index + (index << 3)) << 4) + i];
562 index++;
566 memcpy(pecc, &p[0x94 + ((count + (count << 3)) << 4)] , mcman_sparesize(port, slot));
567 break;
569 } while (++retries < 5);
571 if (retries < 5)
572 return sceMcResSucceed;
574 return sceMcResChangedCard;
577 //--------------------------------------------------------------
578 int McGetCardSpec(int port, int slot, u16 *pagesize, u16 *blocksize, int *cardsize, u8 *flags)
580 register int retries, r;
581 u8 *p = mcman_sio2packet.out_dma.addr;
583 #ifdef DEBUG
584 DPRINTF("mcman: McGetCardSpec sio2cmd port%d slot%d\n", port, slot);
585 #endif
587 sio2packet_add(port, slot, 0xffffffff, NULL);
588 sio2packet_add(port, slot, 0x07, NULL);
589 sio2packet_add(port, slot, 0xfffffffe, NULL);
591 retries = 0;
593 do {
594 mcman_sio2transfer(port, slot, &mcman_sio2packet);
596 if (((mcman_sio2packet.stat6c & 0xF000) == 0x1000) && (p[12] == 0x5a)) {
597 // checking EDC
598 r = mcman_calcEDC(&p[3], 8) & 0xFF;
599 if (r == p[11])
600 break;
602 } while (++retries < 5);
604 if (retries >= 5)
605 return sceMcResChangedCard;
607 *pagesize = (p[4] << 8) + p[3];
608 *blocksize = (p[6] << 8) + p[5];
609 *cardsize = (p[8] << 8) + p[7] + (p[9] << 16) + (p[10] << 24);
610 *flags = p[2];
612 #ifdef DEBUG
613 DPRINTF("mcman: McGetCardSpec sio2cmd pagesize=%d blocksize=%d cardsize=%d flags%x\n", *pagesize, *blocksize, *cardsize, *flags);
614 #endif
616 return sceMcResSucceed;
619 //--------------------------------------------------------------
620 int mcman_resetauth(int port, int slot)
622 register int retries;
624 #ifdef DEBUG
625 DPRINTF("mcman: mcman_resetauth sio2cmd port%d slot%d\n", port, slot);
626 #endif
628 sio2packet_add(port, slot, 0xffffffff, NULL);
629 sio2packet_add(port, slot, 0x11, NULL);
630 sio2packet_add(port, slot, 0xfffffffe, NULL);
632 retries = 0;
634 do {
635 mcman_sio2transfer(port, slot, &mcman_sio2packet);
637 if ((mcman_sio2packet.stat6c & 0xF000) == 0x1000)
638 break;
640 } while (++retries < 5);
642 if (retries >= 5) {
643 #ifdef DEBUG
644 DPRINTF("mcman: mcman_resetauth sio2cmd card changed!\n");
645 #endif
647 return sceMcResChangedCard;
650 #ifdef DEBUG
651 DPRINTF("mcman: mcman_resetauth sio2cmd succeeded\n");
652 #endif
654 return sceMcResSucceed;
657 //--------------------------------------------------------------
658 int mcman_probePS2Card2(int port, int slot)
660 register int retries, r;
661 u8 *p = mcman_sio2packet.out_dma.addr;
663 #ifdef DEBUG
664 DPRINTF("mcman: mcman_probePS2Card2 sio2cmd port%d slot%d\n", port, slot);
665 #endif
667 retries = 0;
668 do {
669 sio2packet_add(port, slot, 0xffffffff, NULL);
670 sio2packet_add(port, slot, 0x09, NULL);
671 sio2packet_add(port, slot, 0xfffffffe, NULL);
673 mcman_sio2transfer(port, slot, &mcman_sio2packet);
675 if (((mcman_sio2packet.stat6c & 0xF000) == 0x1000) && (p[4] != 0x66))
676 break;
677 } while (++retries < 5);
679 if (retries >= 5)
680 return sceMcResFailDetect;
682 if (p[3] == 0x5a) {
683 r = McGetFormat(port, slot);
684 if (r > 0) {
685 #ifdef DEBUG
686 DPRINTF("mcman: mcman_probePS2Card2 succeeded\n");
687 #endif
689 return sceMcResSucceed;
692 r = McGetFormat(port, slot);
693 if (r < 0) {
694 #ifdef DEBUG
695 DPRINTF("mcman: mcman_probePS2Card2 sio2cmd failed (no format)\n");
696 #endif
698 return sceMcResNoFormat;
702 #ifdef DEBUG
703 DPRINTF("mcman: mcman_probePS2Card2 sio2cmd failed (mc detection failed)\n");
704 #endif
706 return sceMcResFailDetect2;
709 //--------------------------------------------------------------
710 int mcman_probePS2Card(int port, int slot) //2
712 register int retries, r;
713 register MCDevInfo *mcdi;
714 u8 *p = mcman_sio2packet.out_dma.addr;
716 #ifdef DEBUG
717 DPRINTF("mcman: mcman_probePS2Card sio2cmd port%d slot%d\n", port, slot);
718 #endif
720 r = mcman_cardchanged(port, slot);
721 if (r == sceMcResSucceed) {
722 r = McGetFormat(port, slot);
723 if (r != 0) {
724 #ifdef DEBUG
725 DPRINTF("mcman: mcman_probePS2Card sio2cmd succeeded\n");
726 #endif
728 return sceMcResSucceed;
732 if (mcman_resetauth(port, slot) != sceMcResSucceed) {
733 #ifdef DEBUG
734 DPRINTF("mcman: mcman_probePS2Card sio2cmd failed (auth reset failed)\n");
735 #endif
737 return sceMcResFailResetAuth;
740 if (SecrAuthCard(port + 2, slot, mcman_getcnum(port, slot)) == 0) {
741 #ifdef DEBUG
742 DPRINTF("mcman: mcman_probePS2Card sio2cmd failed (auth failed)\n");
743 #endif
745 return sceMcResFailAuth;
748 retries = 0;
749 do {
750 sio2packet_add(port, slot, 0xffffffff, NULL);
751 sio2packet_add(port, slot, 0x09, NULL);
752 sio2packet_add(port, slot, 0xfffffffe, NULL);
754 mcman_sio2transfer(port, slot, &mcman_sio2packet);
756 if (((mcman_sio2packet.stat6c & 0xF000) == 0x1000) && (p[4] != 0x66))
757 break;
758 } while (++retries < 5);
760 if (retries >= 5) {
761 #ifdef DEBUG
762 DPRINTF("mcman: mcman_probePS2Card sio2cmd failed (mc detection failed)\n");
763 #endif
764 return sceMcResFailDetect;
767 mcman_clearcache(port, slot);
769 sio2packet_add(port, slot, 0xffffffff, NULL);
770 sio2packet_add(port, slot, 0x08, NULL);
771 sio2packet_add(port, slot, 0xfffffffe, NULL);
773 retries = 0;
774 do {
775 mcman_sio2transfer(port, slot, &mcman_sio2packet);
777 if ((mcman_sio2packet.stat6c & 0xF000) != 0x1000)
778 continue;
780 if (p[4] == 0x5a)
781 break;
782 } while (++retries < 5);
784 if (retries >= 5) {
785 #ifdef DEBUG
786 DPRINTF("mcman: mcman_probePS2Card sio2cmd failed (mc detection failed)\n");
787 #endif
789 return sceMcResFailDetect2;
792 r = mcman_setdevinfos(port, slot);
793 if (r == 0) {
794 #ifdef DEBUG
795 DPRINTF("mcman: mcman_probePS2Card sio2cmd card changed!\n");
796 #endif
797 return sceMcResChangedCard;
799 if (r != sceMcResNoFormat) {
800 #ifdef DEBUG
801 DPRINTF("mcman: mcman_probePS2Card sio2cmd failed (mc detection failed)\n");
802 #endif
803 return sceMcResFailDetect2;
806 mcdi = &mcman_devinfos[port][slot];
807 mcdi->cardform = r;
809 #ifdef DEBUG
810 DPRINTF("mcman: mcman_probePS2Card sio2cmd succeeded\n");
811 #endif
813 return r;
816 //--------------------------------------------------------------
817 int mcman_probePS1Card2(int port, int slot)
819 register int retries;
820 register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
822 #ifdef DEBUG
823 DPRINTF("mcman: mcman_probePS1Card2 port%d slot%d\n", port, slot);
824 #endif
826 mcman_sio2packet_PS1PDA.regdata[0] = 0;
827 mcman_sio2packet_PS1PDA.regdata[0] = (((port & 1) + 2)) | 0x000c0340;
828 mcman_sio2packet_PS1PDA.in_size = 3;
829 mcman_sio2packet_PS1PDA.out_size = 3;
831 mcman_sio2packet_PS1PDA.regdata[1] = 0;
832 mcman_sio2inbufs_PS1PDA[0] = 0x81;
833 mcman_sio2inbufs_PS1PDA[1] = 0x52;
835 retries = 0;
836 do {
837 mcman_timercount = (u32)(GetTimerCounter(timer_ID) - mcman_timercount);
839 u32 hi, lo;
840 long_multiply(mcman_timercount, 0x3e0f83e1, &hi, &lo);
842 if ((u32)((hi >> 3) < mcman_timerthick))
843 DelayThread(mcman_timerthick - (hi >> 3));
845 mcman_sio2transfer(port, slot, &mcman_sio2packet_PS1PDA);
847 mcman_timercount = GetTimerCounter(timer_ID);
848 mcman_timerthick = 0;
850 if (((mcman_sio2packet_PS1PDA.stat6c & 0xf000) == 0x1000) \
851 && (mcman_sio2outbufs_PS1PDA[2] == 0x5a)) {
852 break;
854 } while (++retries < 5);
856 if (retries >= 5)
857 return -12;
859 if (mcman_sio2outbufs_PS1PDA[1] == 0) {
860 if (mcdi->cardform > 0)
861 return sceMcResSucceed;
862 if (mcdi->cardform < 0)
863 return sceMcResNoFormat;
865 else if (mcman_sio2outbufs_PS1PDA[1] != 8) {
866 return -14;
869 return -13;
872 //--------------------------------------------------------------
873 int mcman_probePS1Card(int port, int slot)
875 register int i, r, retries;
876 register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
877 u32 *p;
879 #ifdef DEBUG
880 DPRINTF("mcman: mcman_probePS1Card port%d slot%d\n", port, slot);
881 #endif
883 mcman_sio2packet_PS1PDA.regdata[0] = 0;
884 mcman_sio2packet_PS1PDA.regdata[0] = (((port & 1) + 2)) | 0x000c0340;
885 mcman_sio2packet_PS1PDA.in_size = 3;
886 mcman_sio2packet_PS1PDA.out_size = 3;
888 mcman_sio2packet_PS1PDA.regdata[1] = 0;
889 mcman_sio2inbufs_PS1PDA[0] = 0x81;
890 mcman_sio2inbufs_PS1PDA[1] = 0x52;
892 retries = 0;
893 do {
894 mcman_timercount = (u32)(GetTimerCounter(timer_ID) - mcman_timercount);
896 u32 hi, lo;
897 long_multiply(mcman_timercount, 0x3e0f83e1, &hi, &lo);
899 if ((u32)((hi >> 3) < mcman_timerthick))
900 DelayThread(mcman_timerthick - (hi >> 3));
902 mcman_sio2transfer(port, slot, &mcman_sio2packet_PS1PDA);
904 mcman_timercount = GetTimerCounter(timer_ID);
905 mcman_timerthick = 0;
907 if (((mcman_sio2packet_PS1PDA.stat6c & 0xf000) == 0x1000) \
908 && (mcman_sio2outbufs_PS1PDA[2] == 0x5a)) {
909 break;
911 } while (++retries < 5);
913 if (retries >= 5)
914 return -11;
916 if (mcman_sio2outbufs_PS1PDA[1] == 0) {
917 if (mcdi->cardform != 0)
918 return sceMcResSucceed;
920 else if (mcman_sio2outbufs_PS1PDA[1] != 8) {
921 return -12;
924 mcman_clearcache(port, slot);
926 p = (u32 *)&mcman_sio2outbufs_PS1PDA[124];
927 for (i = 31; i >= 0; i--)
928 *p-- = 0;
930 r = McWritePS1PDACard(port, slot, 63, mcman_sio2outbufs_PS1PDA);
931 if (r < 0)
932 return -13;
934 r = mcman_setPS1devinfos(port, slot);
935 if (r == 0)
936 return sceMcResChangedCard;
938 mcdi->cardform = r;
940 return r;
943 //--------------------------------------------------------------
944 int mcman_probePDACard(int port, int slot)
946 register int retries;
948 #ifdef DEBUG
949 DPRINTF("mcman: mcman_probePDACard port%d slot%d\n", port, slot);
950 #endif
952 mcman_sio2packet_PS1PDA.regdata[0] = 0;
953 mcman_sio2packet_PS1PDA.regdata[0] = (port & 3) | 0x00140540;
954 mcman_sio2packet_PS1PDA.in_size = 5;
955 mcman_sio2packet_PS1PDA.out_size = 5;
957 mcman_sio2packet_PS1PDA.regdata[1] = 0;
958 mcman_sio2inbufs_PS1PDA[0] = 0x81;
959 mcman_sio2inbufs_PS1PDA[1] = 0x58;
961 retries = 0;
962 do {
963 mcman_sio2transfer(port, slot, &mcman_sio2packet_PS1PDA);
965 if ((mcman_sio2packet_PS1PDA.stat6c & 0xf000) == 0x1000)
966 break;
968 } while (++retries < 5);
970 if (retries >= 5)
971 return -11;
973 return sceMcResSucceed;
976 //--------------------------------------------------------------
977 int McWritePS1PDACard(int port, int slot, int page, void *buf) // Export #30
979 register int i, retries;
980 register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
981 u8 *p;
983 #ifdef DEBUG
984 //DPRINTF("mcman: McWritePS1PDACard port%d slot%d page %x\n", port, slot, page);
985 #endif
987 mcman_sio2packet_PS1PDA.regdata[0] = 0;
988 mcman_sio2packet_PS1PDA.regdata[0] = (((port & 1) + 2) & 3) | 0x02288a40;
989 mcman_sio2packet_PS1PDA.in_size = 138;
990 mcman_sio2packet_PS1PDA.out_size = 138;
991 mcman_sio2packet_PS1PDA.regdata[1] = 0;
993 for (i = 0; i < 20; i++) {
994 if (mcdi->bad_block_list[i] == page)
995 page += 36;
998 mcman_sio2inbufs_PS1PDA[0] = 0x81;
999 mcman_sio2inbufs_PS1PDA[1] = 0x57;
1000 mcman_sio2inbufs_PS1PDA[4] = (u8)(page >> 8);
1001 mcman_sio2inbufs_PS1PDA[5] = (u8)page;
1003 p = (u8 *)buf;
1004 for (i = 0; i < 128; i++)
1005 mcman_sio2inbufs_PS1PDA[6 + i] = p[i];
1007 mcman_sio2inbufs_PS1PDA[4 + 130] = mcman_calcEDC(&mcman_sio2inbufs_PS1PDA[4], 130);
1009 retries = 0;
1010 do {
1011 mcman_timercount = (u32)(GetTimerCounter(timer_ID) - mcman_timercount);
1013 u32 hi, lo;
1014 long_multiply(mcman_timercount, 0x3e0f83e1, &hi, &lo);
1016 if ((u32)((hi >> 3) < mcman_timerthick))
1017 DelayThread(mcman_timerthick - (hi >> 3));
1019 mcman_sio2transfer(port, slot, &mcman_sio2packet_PS1PDA);
1021 mcman_timercount = GetTimerCounter(timer_ID);
1022 mcman_timerthick = 20000;
1024 if (((mcman_sio2packet_PS1PDA.stat6c & 0xf000) == 0x1000) \
1025 && (mcman_sio2outbufs_PS1PDA[2] == 0x5a) \
1026 && (mcman_sio2outbufs_PS1PDA[3] == 0x5d) \
1027 && (mcman_sio2outbufs_PS1PDA[137] == 0x47)) {
1028 break;
1030 } while (++retries < 5);
1032 if (retries >= 5)
1033 return sceMcResNoEntry;
1035 if ((mcman_sio2outbufs_PS1PDA[1] != 0) && (mcman_sio2outbufs_PS1PDA[1] != 8))
1036 return sceMcResFullDevice;
1038 return sceMcResSucceed;
1041 //--------------------------------------------------------------
1042 int McReadPS1PDACard(int port, int slot, int page, void *buf) // Export #29
1044 register int i, retries;
1045 register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
1046 u8 *p;
1048 #ifdef DEBUG
1049 //DPRINTF("mcman: McReadPS1PDACard port%d slot%d page %x\n", port, slot, page);
1050 #endif
1052 mcman_sio2packet_PS1PDA.regdata[0] = 0;
1053 mcman_sio2packet_PS1PDA.regdata[0] = (((port & 1) + 2) & 3) | 0x02308c40;
1054 mcman_sio2packet_PS1PDA.in_size = 140;
1055 mcman_sio2packet_PS1PDA.out_size = 140;
1056 mcman_sio2packet_PS1PDA.regdata[1] = 0;
1058 for (i = 0; i < 20; i++) {
1059 if (mcdi->bad_block_list[i] == page)
1060 page += 36;
1063 mcman_sio2inbufs_PS1PDA[0] = 0x81;
1064 mcman_sio2inbufs_PS1PDA[1] = 0x52;
1065 mcman_sio2inbufs_PS1PDA[4] = (u8)(page >> 8);
1066 mcman_sio2inbufs_PS1PDA[5] = (u8)page;
1068 retries = 0;
1069 do {
1070 mcman_timercount = (u32)(GetTimerCounter(timer_ID) - mcman_timercount);
1072 u32 hi, lo;
1073 long_multiply(mcman_timercount, 0x3e0f83e1, &hi, &lo);
1075 if ((u32)((hi >> 3) < mcman_timerthick))
1076 DelayThread(mcman_timerthick - (hi >> 3));
1078 mcman_sio2transfer(port, slot, &mcman_sio2packet_PS1PDA);
1080 mcman_timercount = GetTimerCounter(timer_ID);
1081 mcman_timerthick = 10000;
1083 if (((mcman_sio2packet_PS1PDA.stat6c & 0xf000) == 0x1000) \
1084 && (mcman_sio2outbufs_PS1PDA[2] == 0x5a) \
1085 && (mcman_sio2outbufs_PS1PDA[3] == 0x5d) \
1086 && (mcman_sio2outbufs_PS1PDA[4] == 0x00) \
1087 && (mcman_sio2outbufs_PS1PDA[6] == 0x5c) \
1088 && (mcman_sio2outbufs_PS1PDA[7] == 0x5d) \
1089 && (mcman_sio2outbufs_PS1PDA[139] == 0x47)) {
1091 if (mcman_sio2outbufs_PS1PDA[138] == (mcman_calcEDC(&mcman_sio2outbufs_PS1PDA[8], 130) & 0xff))
1092 break;
1094 } while (++retries < 5);
1096 if (retries >= 5)
1097 return sceMcResNoEntry;
1099 p = (u8 *)buf;
1100 for (i = 0; i < 128; i++)
1101 p[i] = mcman_sio2outbufs_PS1PDA[10 + i];
1103 if ((mcman_sio2outbufs_PS1PDA[1] != 0) && (mcman_sio2outbufs_PS1PDA[1] != 8))
1104 return sceMcResDeniedPermit;
1106 return sceMcResSucceed;