PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
mcsio2.c
1/*
2# _____ ___ ____ ___ ____
3# ____| | ____| | | |____|
4# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5#-----------------------------------------------------------------------
6# Copyright (c) 2009 jimmikaelkael
7# Licenced under Academic Free License version 2.0
8# Review ps2sdk README & LICENSE files for further details.
9*/
10
11#include <mcman.h>
12#include "mcman-internal.h"
13
14#ifdef BUILDING_XFROMMAN
15static flash_info_t dev9_flash_info;
16#endif
17
18#if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
19static sio2_transfer_data_t mcman_sio2packet; // buffer for mcman sio2 packet
20static u8 mcman_wdmabufs[0x0b * 0x90]; // buffer array for SIO2 DMA I/O (write)
21static u8 mcman_rdmabufs[0x0b * 0x90]; // not sure here for size, buffer array for SIO2 DMA I/O (read)
22
23static sio2_transfer_data_t mcman_sio2packet_PS1PDA;
24static u8 mcman_sio2inbufs_PS1PDA[0x90];
25u8 mcman_sio2outbufs_PS1PDA[0x90];
26
27static u32 mcman_timercount;
28static int mcman_timerthick;
29
30// mcman cmd table used by sio2packet_add fnc
31// This is not an exaustive list of all commands being used. Some commands are generated by SECRMAN
32// See usages of functions beginning with card_auth in SECRMAN.
33static const u8 mcman_cmdtable[36] = {
34 0x11, 0x04, // 00, Probe, mcman/mcman_cardchanged
35 0x12, 0x04, // 01, ???, mcman/mcman_eraseblock
36 0x21, 0x09, // 02, Start Erase, mcman/mcman_eraseblock
37 0x22, 0x09, // 03, Start Write, mcman/McWritePage
38 0x23, 0x09, // 04, Start Read, mcman/mcman_readpage
39 0x24, 0x86, // 05, ???, ???
40 0x25, 0x04, // 06, ???, ???
41 0x26, 0x0d, // 07, Get Specs, mcman/McGetCardSpec
42 0x27, 0x05, // 08, Set Terminator, mcman/mcman_probePS2Card
43 0x28, 0x05, // 09, Get Terminator, mcman/mcman_probePS2Card2;mcman/mcman_probePS2Card
44 0x42, 0x86, // 0A, Write Data, mcman/McWritePage
45 0x43, 0x86, // 0B, Read Data, mcman/mcman_readpage
46 0x81, 0x04, // 0C, Read/Write End, mcman/McWritePage;mcman/mcman_readpage
47 0x82, 0x04, // 0D, Erase Block, mcman/mcman_eraseblock
48 0x42, 0x06, // 0E, Write Data, mcman/McWritePage
49 0x43, 0x06, // 0F, Read Data, mcman/mcman_readpage
50 0xbf, 0x05, // 10, ???, ???
51 0xf3, 0x05, // 11, ???, mcman/mcman_resetauth
52};
53
54// sio2packet_add child functions
55static void (*sio2packet_add_func)(int port, int slot, int cmd, u8 *buf, int pos);
56static void sio2packet_add_wdma_u32(int port, int slot, int cmd, u8 *buf, int pos);
57static void sio2packet_add_pagedata_out(int port, int slot, int cmd, u8 *buf, int pos);
58static void sio2packet_add_pagedata_in(int port, int slot, int cmd, u8 *buf, int pos);
59static void sio2packet_add_ecc_in(int port, int slot, int cmd, u8 *buf, int pos);
60static void sio2packet_add_ecc_out(int port, int slot, int cmd, u8 *buf, int pos);
61static void sio2packet_add_wdma_5a(int port, int slot, int cmd, u8 *buf, int pos);
62static void sio2packet_add_wdma_00(int port, int slot, int cmd, u8 *buf, int pos);
63static void sio2packet_add_wdma_u8(int port, int slot, int cmd, u8 *buf, int pos);
64static void sio2packet_add_do_nothing(int port, int slot, int cmd, u8 *buf, int pos);
65
66// functions pointer array to handle sio2packet_add inner functions calls
67static void *sio2packet_add_funcs_array[16] = {
68 (void *)sio2packet_add_wdma_00, // commands that needs to clear in_dma.addr[2]
69 (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)
70 (void *)sio2packet_add_wdma_u32, // ...
71 (void *)sio2packet_add_wdma_u32, // ...
72 (void *)sio2packet_add_wdma_u8, // commands that needs to copy an u8 value to in_dma.addr[2]
73 (void *)sio2packet_add_do_nothing, // do nothing
74 (void *)sio2packet_add_do_nothing, // ...
75 (void *)sio2packet_add_wdma_5a, // commands that needs to set in_dma.addr[2] to value 0x5a, used to set termination code
76 (void *)sio2packet_add_do_nothing, // do nothing
77 (void *)sio2packet_add_pagedata_in, // commands that needs to copy pagedata buf into in_dma.addr
78 (void *)sio2packet_add_pagedata_out,// commands that needs to set in_dma.addr[2] to value 128 for pagedata out
79 (void *)sio2packet_add_do_nothing, // do nothing
80 (void *)sio2packet_add_do_nothing, // ...
81 (void *)sio2packet_add_ecc_in, // commands that needs to copy sparedata buf into in_dma.addr
82 (void *)sio2packet_add_ecc_out, // commands that needs to prepare regdata and in_dma.addr to receive sparedata
83 (void *)sio2packet_add_wdma_u8 // commands that needs to copy an u8 value to in_dma.addr[2]
84};
85
86//--------------------------------------------------------------
87void sio2packet_add(int port, int slot, int cmd, u8 *buf)
88{ // Used to build the sio2packets for all mc commands
89 register u32 regdata;
90
91 if ((unsigned int)cmd == 0xffffffff) {
92 mcman_sio2packet.in_dma.count = 0;
93 return;
94 }
95
96 if (mcman_sio2packet.in_dma.count < 0xb) {
97 register int pos;
98 u8 *p;
99
100 if ((unsigned int)cmd == 0xfffffffe) {
101 mcman_sio2packet.regdata[mcman_sio2packet.in_dma.count] = 0;
102 mcman_sio2packet.out_dma.count = mcman_sio2packet.in_dma.count;
103 return;
104 }
105
106 regdata = (((port & 1) + 2) & 3) | 0x70;
107 regdata |= mcman_cmdtable[(cmd << 1) + 1] << 18;
108 regdata |= mcman_cmdtable[(cmd << 1) + 1] << 8;
109
110 mcman_sio2packet.regdata[mcman_sio2packet.in_dma.count] = regdata;
111
112 pos = ((mcman_sio2packet.in_dma.count + (mcman_sio2packet.in_dma.count << 3)) << 4);
113
114 mcman_sio2packet.in_dma.count++;
115
116 p = mcman_sio2packet.in_dma.addr + pos;
117 p[0] = 0x81;
118 p[1] = mcman_cmdtable[cmd << 1];
119
120 if (((cmd - 1) >= 16) || ((cmd - 1) < 0))
121 return;
122
123 sio2packet_add_func = (void*)sio2packet_add_funcs_array[(cmd - 1)];
124 (sio2packet_add_func)(port, slot, cmd, buf, pos); // call to the needed child func
125 }
126}
127
128//----
129// sio2packet child funcs
130
131static void sio2packet_add_wdma_u32(int port, int slot, int cmd, u8 *buf, int pos)
132{
133 (void)port;
134 (void)slot;
135 (void)cmd;
136
137 u8 *p = mcman_sio2packet.in_dma.addr + pos;
138 p[2] = buf[0];
139 p[3] = buf[1];
140 p[4] = buf[2];
141 p[5] = buf[3];
142 p[6] = mcman_calcEDC(&p[2], 4);
143}
144
145//--
146
147static void sio2packet_add_pagedata_out(int port, int slot, int cmd, u8 *buf, int pos)
148{
149 (void)port;
150 (void)slot;
151 (void)cmd;
152 (void)buf;
153
154 // used for sio2 command 0x81 0x43 to read page data
155 u8 *p = mcman_sio2packet.in_dma.addr + pos;
156 p[2] = 128;
157}
158
159//--
160
161static void sio2packet_add_pagedata_in(int port, int slot, int cmd, u8 *buf, int pos)
162{
163 (void)port;
164 (void)slot;
165 (void)cmd;
166
167 // used for sio2 command 0x81 0x42 to write page data
168 register int i;
169 u8 *p = mcman_sio2packet.in_dma.addr + pos;
170 p[2] = 128;
171
172 for (i=0; i<128; i++)
173 p[3 + i] = buf[i];
174
175 p[3 + 128] = mcman_calcEDC(&buf[0], 128);
176}
177
178//--
179
180static void sio2packet_add_ecc_in(int port, int slot, int cmd, u8 *buf, int pos)
181{
182 // used for sio2 command 0x81 0x42 to write page ecc
183 register u32 regdata;
184 int i;
185 u8 *p = mcman_sio2packet.in_dma.addr + pos;
186
187 p[2] = mcman_sparesize(port, slot);
188
189 for (i=0; i<(p[2] & 0xff); i++)
190 p[3 + i] = buf[i];
191
192 p[3 + p[2]] = mcman_calcEDC(&buf[0], p[2]);
193
194 regdata = (p[2] + mcman_cmdtable[(cmd << 1) + 1]) << 18;
195 regdata |= mcman_sio2packet.regdata[mcman_sio2packet.in_dma.count-1] & ~0x07fc0000;
196 regdata &= ~0x0001ff00;
197 regdata |= (p[2] + mcman_cmdtable[(cmd << 1) + 1]) << 8;
198
199 mcman_sio2packet.regdata[mcman_sio2packet.in_dma.count-1] = regdata;
200}
201
202//--
203
204static void sio2packet_add_ecc_out(int port, int slot, int cmd, u8 *buf, int pos)
205{
206 (void)buf;
207
208 // used for sio2 command 0x81 0x43 to read page ecc
209 register u32 regdata;
210 u8 *p = mcman_sio2packet.in_dma.addr + pos;
211
212 p[2] = mcman_sparesize(port, slot);
213
214 regdata = (p[2] + mcman_cmdtable[(cmd << 1) + 1]) << 18;
215 regdata |= mcman_sio2packet.regdata[mcman_sio2packet.in_dma.count-1] & ~0x07fc0000;
216 regdata &= ~0x0001ff00;
217 regdata |= (p[2] + mcman_cmdtable[(cmd << 1) + 1]) << 8;
218
219 mcman_sio2packet.regdata[mcman_sio2packet.in_dma.count-1] = regdata;
220}
221
222//--
223
224static void sio2packet_add_wdma_5a(int port, int slot, int cmd, u8 *buf, int pos)
225{
226 (void)port;
227 (void)slot;
228 (void)cmd;
229 (void)buf;
230
231 // used for sio2 command 0x81 0x27 to set a termination code
232 u8 *p = mcman_sio2packet.in_dma.addr + pos;
233 p[2] = 0x5a;
234}
235
236//--
237
238static void sio2packet_add_wdma_00(int port, int slot, int cmd, u8 *buf, int pos)
239{
240 (void)port;
241 (void)slot;
242 (void)cmd;
243 (void)buf;
244
245 u8 *p = mcman_sio2packet.in_dma.addr + pos;
246 p[2] = 0x00;
247
248}
249
250//--
251
252static void sio2packet_add_wdma_u8(int port, int slot, int cmd, u8 *buf, int pos)
253{
254 (void)port;
255 (void)slot;
256 (void)cmd;
257
258 u8 *p = mcman_sio2packet.in_dma.addr + pos;
259 p[2] = buf[0];
260}
261
262//--
263
264static void sio2packet_add_do_nothing(int port, int slot, int cmd, u8 *buf, int pos)
265{
266 (void)port;
267 (void)slot;
268 (void)cmd;
269 (void)buf;
270 (void)pos;
271
272 // do nothing
273}
274
275//--------------------------------------------------------------
276int mcsio2_transfer(int port, int slot, sio2_transfer_data_t *sio2data)
277{
278#ifdef BUILDING_XMCMAN
279 // SIO2 transfer for XMCMAN
280 register int r;
281 s32 port_ctrl[8];
282
283 DPRINTF("mcsio2_transfer port%d slot%d\n", port, slot);
284
285 port_ctrl[0] = -1;
286 port_ctrl[1] = -1;
287 port_ctrl[2] = -1;
288 port_ctrl[3] = -1;
289
290 port_ctrl[(port & 1) + 2] = slot;
291
292 sio2_mc_transfer_init();
293 sio2_mtap_change_slot(port_ctrl);
294 r = sio2_transfer(sio2data);
295 sio2_transfer_reset();
296
297 DPRINTF("mcsio2_transfer returns %d\n", r);
298
299 return r;
300#else
301 register int r;
302
303 (void)port;
304 (void)slot;
305
306#ifdef DEBUG
307 u8 *p = (u8 *)(sio2data->in_dma.addr);
308 if (p)
309 DPRINTF("mcsio2_transfer port%d slot%d cmd = %02x %02x %02x ", port, slot, p[0], p[1], p[2]);
310 else {
311 p = (u8 *)(sio2data->in);
312 DPRINTF("mcsio2_transfer for secrman port%d slot%d cmd = %02x %02x %02x ", port, slot, p[0], p[1], p[2]);
313 }
314#endif
315
316 // SIO2 transfer for MCMAN
317 sio2_mc_transfer_init();
318 r = sio2_transfer(sio2data);
319
320 DPRINTF("returns %d\n", r);
321
322 return r;
323#endif
324}
325#endif
326
327//--------------------------------------------------------------
328void mcman_initPS2com(void)
329{
330#if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
331 mcman_wmemset((void *)&mcman_sio2packet, sizeof (mcman_sio2packet), 0);
332
333 mcman_sio2packet.port_ctrl1[2] = 0xff020405;
334 mcman_sio2packet.port_ctrl1[3] = 0xff020405;
335 mcman_sio2packet.port_ctrl2[2] = 0x0005ffff & ~0x03000000;
336 mcman_sio2packet.port_ctrl2[3] = 0x0005ffff & ~0x03000000;
337
338 mcman_sio2packet.in_dma.addr = &mcman_wdmabufs;
339 mcman_sio2packet.in_dma.size = 0x24;
340
341 mcman_sio2packet.out_dma.addr = &mcman_rdmabufs;
342 mcman_sio2packet.out_dma.size = 0x24;
343
344 DPRINTF("mcman_initPS2com registering secrman_mc_command callback\n");
345 SecrSetMcCommandHandler((void *)secrman_mc_command);
346
347 DPRINTF("mcman_initPS2com registering mcman_getcnum callback\n");
348
349 SecrSetMcDevIDHandler((void *)mcman_getcnum);
350
351#ifdef BUILDING_DONGLEMAN
352 iop_sema_t sema_hakama;
353 sema_hakama.attr = 1;
354 sema_hakama.initial = 1;
355 sema_hakama.max = 1;
356 sema_hakama.option = 0;
357 sema_hakama_id = CreateSema(&sema_hakama);
358#endif
359
360#elif defined(BUILDING_XFROMMAN)
361 flash_detect();
362 flash_get_info(&dev9_flash_info);
363#endif
364}
365
366//--------------------------------------------------------------
367void mcman_deinitPS2com(void)
368{
369#if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
370 SecrSetMcCommandHandler(0);
371 SecrSetMcDevIDHandler(0);
372#endif
373}
374
375//--------------------------------------------------------------
376void mcman_initPS1PDAcom(void)
377{
378#if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
379 memset((void *)&mcman_sio2packet_PS1PDA, 0, sizeof (mcman_sio2packet_PS1PDA));
380
381 mcman_sio2packet_PS1PDA.port_ctrl1[0] = 0xffc00505;
382 mcman_sio2packet_PS1PDA.port_ctrl1[1] = 0xffc00505;
383 mcman_sio2packet_PS1PDA.port_ctrl1[2] = 0xffc00505;
384 mcman_sio2packet_PS1PDA.port_ctrl1[3] = 0xffc00505;
385
386 mcman_sio2packet_PS1PDA.port_ctrl2[0] = 0x000201f4 & ~0x03000000;
387 mcman_sio2packet_PS1PDA.port_ctrl2[1] = 0x000201f4 & ~0x03000000;
388 mcman_sio2packet_PS1PDA.port_ctrl2[2] = 0x000201f4 & ~0x03000000;
389 mcman_sio2packet_PS1PDA.port_ctrl2[3] = 0x000201f4 & ~0x03000000;
390
391 mcman_sio2packet_PS1PDA.in = (u8 *)&mcman_sio2inbufs_PS1PDA;
392 mcman_sio2packet_PS1PDA.out = (u8 *)&mcman_sio2outbufs_PS1PDA;
393#endif
394}
395
396//--------------------------------------------------------------
397void mcman_deinitPS1PDAcom(void)
398{
399 // For now, stubbed. Semaphore was created somewhere between 1.6.0 (exclusive) and 3.1.0 (inclusive)
400}
401
402#if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
403//--------------------------------------------------------------
404int secrman_mc_command(int port, int slot, sio2_transfer_data_t *sio2data)
405{
406 register int r;
407
408 DPRINTF("secrman_mc_command port%d slot%d\n", port, slot);
409
410 r = mcsio2_transfer(port, slot, sio2data);
411
412 return r;
413}
414#endif
415
416//--------------------------------------------------------------
417int mcman_cardchanged(int port, int slot)
418{
419#if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
420 register int retries;
421 u8 *p = mcman_sio2packet.out_dma.addr;
422
423 DPRINTF("mcman_cardchanged sio2cmd port%d slot%d\n", port, slot);
424
425 sio2packet_add(port, slot, 0xffffffff, NULL);
426 sio2packet_add(port, slot, 0x00, NULL);
427 sio2packet_add(port, slot, 0xfffffffe, NULL);
428
429 retries = 0;
430 do {
431 mcsio2_transfer(port, slot, &mcman_sio2packet);
432
433 if (((mcman_sio2packet.stat6c & 0xF000) == 0x1000) && (p[3] != 0x66))
434 break;
435
436 } while (++retries < 5);
437
438 if (retries >= 5) {
439 DPRINTF("mcman_cardchanged sio2cmd card changed!\n");
440 return sceMcResChangedCard;
441 }
442
443 DPRINTF("mcman_cardchanged sio2cmd succeeded\n");
444#else
445 (void)port;
446 (void)slot;
447#endif
448
449#if defined(BUILDING_VMCMAN)
450 return sceMcResChangedCard;
451#else
452 return sceMcResSucceed;
453#endif
454}
455
456//--------------------------------------------------------------
457int mcman_eraseblock(int port, int slot, int block, void **pagebuf, void *eccbuf)
458{
459 register int retries, size, ecc_offset;
460 int page;
461 HAKAMA_WAITSEMA();
462#if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
463 u8 *p = mcman_sio2packet.out_dma.addr;
464#endif
465 void *p_ecc;
466 register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
467
468 page = block * mcdi->blocksize;
469
470#if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
471 sio2packet_add(port, slot, 0xffffffff, NULL);
472 sio2packet_add(port, slot, 0x02, (u8 *)&page);
473 sio2packet_add(port, slot, 0x0d, NULL);
474 sio2packet_add(port, slot, 0xfffffffe, NULL);
475#endif
476
477 retries = 0;
478 do {
479#if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
480 mcsio2_transfer(port, slot, &mcman_sio2packet);
481
482 if (((mcman_sio2packet.stat6c & 0xF000) != 0x1000) || (p[8] != 0x5a))
483 continue;
484
485 if (p[0x93] == p[8])
486 break;
487#elif defined(BUILDING_VMCMAN)
488 if (!mcman_iomanx_backing_erase(port, slot, page))
489 break;
490#elif defined(BUILDING_XFROMMAN)
491 if (!flash_page_erase(&dev9_flash_info, page))
492 break;
493#endif
494 } while (++retries < 5);
495
496 if (retries >= 5)
497 return sceMcResChangedCard;
498
499 if (pagebuf && eccbuf) { // This part leave the first ecc byte of each block page in eccbuf
500 mcman_wmemset(eccbuf, 32, 0);
501
502 page = 0;
503 while (page < mcdi->blocksize) {
504 ecc_offset = page * mcdi->pagesize;
505 if (ecc_offset < 0)
506 ecc_offset += 0x1f;
507 ecc_offset = ecc_offset >> 5;
508 p_ecc = (void *)((u8 *)eccbuf + ecc_offset);
509 size = 0;
510 while (size < mcdi->pagesize) {
511 if (*pagebuf)
512 McDataChecksum((void *)((u8 *)(*pagebuf) + size), p_ecc);
513 size += 128;
514 p_ecc = (void *)((u8 *)p_ecc + 3);
515 }
516 pagebuf++;
517 page++;
518 }
519 }
520
521#if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
522 sio2packet_add(port, slot, 0xffffffff, NULL);
523 sio2packet_add(port, slot, 0x01, NULL);
524 sio2packet_add(port, slot, 0xfffffffe, NULL);
525
526 retries = 0;
527 do {
528 mcsio2_transfer(port, slot, &mcman_sio2packet);
529
530 if (((mcman_sio2packet.stat6c & 0xF000) != 0x1000))
531 continue;
532
533 if (p[3] == 0x5a) {
534 HAKAMA_SIGNALSEMA();
535 return sceMcResSucceed;
536 }
537 } while (++retries < 100);
538
539 HAKAMA_SIGNALSEMA(); //El_isra: Original impl has two semas (still commented there) replaced with one for simplicity
540 if (p[3] == 0x66) {
541 //HAKAMA_SIGNALSEMA();
542 return sceMcResFailReplace;
543 }
544#endif
545 //HAKAMA_SIGNALSEMA();
546 return sceMcResNoFormat;
547}
548
549//--------------------------------------------------------------
550int McWritePage(int port, int slot, int page, void *pagebuf, void *eccbuf) // Export #19
551{
552 register int retries;
553#if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
554 register int index, count;
555 u8 *p_pagebuf = (u8 *)pagebuf;
556 u8 *p = mcman_sio2packet.out_dma.addr;
557#endif
558
559 HAKAMA_WAITSEMA();
560
561#ifdef BUILDING_XFROMMAN
562 (void)port;
563 (void)slot;
564 char page_buf[528];
565 memcpy(page_buf, pagebuf, 512);
566 memcpy(page_buf + 512, eccbuf, 16);
567#endif
568
569#if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
570 count = (mcman_devinfos[port][slot].pagesize + 127) >> 7;
571#endif
572
573 retries = 0;
574
575 do {
576#if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
577 if (retries > 0)
578 mcman_cardchanged(port, slot);
579
580 sio2packet_add(port, slot, 0xffffffff, NULL);
581 sio2packet_add(port, slot, 0x03, (u8 *)&page);
582
583 index = 0;
584 while (index < count) {
585 sio2packet_add(port, slot, 0x0a, (u8 *)&p_pagebuf[index << 7]);
586 index++;
587 }
588
589 if (mcman_devinfos[port][slot].cardflags & CF_USE_ECC) {
590 // if memcard have ECC support
591 sio2packet_add(port, slot, 0x0e, eccbuf);
592 }
593 sio2packet_add(port, slot, 0xfffffffe, NULL);
594
595 mcsio2_transfer(port, slot, &mcman_sio2packet);
596
597 if (((mcman_sio2packet.stat6c & 0xF000) != 0x1000) || (p[8] != 0x5a))
598 continue;
599
600 index = 0;
601 while (index < count) {
602 if (p[0x94 + 128 + 1 + ((index + (index << 3)) << 4)] != 0x5a)
603 break;
604 index++;
605 }
606
607 if (index < count)
608 continue;
609
610 if (mcman_devinfos[port][slot].cardflags & CF_USE_ECC) {
611 // if memcard have ECC support
612 index++;
613 if (p[5 + ((index + (index << 3)) << 4) + mcman_sparesize(port, slot)] != 0x5a)
614 continue;
615 }
616
617 sio2packet_add(port, slot, 0xffffffff, NULL);
618 sio2packet_add(port, slot, 0x0c, NULL);
619 sio2packet_add(port, slot, 0xfffffffe, NULL);
620
621 mcsio2_transfer(port, slot, &mcman_sio2packet);
622
623 if (((mcman_sio2packet.stat6c & 0xF000) != 0x1000) || (p[3] != 0x5a))
624 continue;
625#elif defined(BUILDING_VMCMAN)
626 if (mcman_iomanx_backing_write(port, slot, page, pagebuf, eccbuf))
627 continue;
628#elif defined(BUILDING_XFROMMAN)
629 if (flash_page_write(&dev9_flash_info, page, page_buf))
630 continue;
631#endif
632 HAKAMA_SIGNALSEMA();
633 return sceMcResSucceed;
634
635 } while (++retries < 5);
636
637#if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
638 HAKAMA_SIGNALSEMA(); // El_isra: simplify original impl
639 if (p[3] == 0x66) {
640 //HAKAMA_SIGNALSEMA();
641 return sceMcResFailReplace;
642 }
643
644 //HAKAMA_SIGNALSEMA();
645 return sceMcResNoFormat;
646#else
647 return sceMcResFailReplace;
648#endif
649}
650
651//--------------------------------------------------------------
652int mcman_readpage(int port, int slot, int page, void *buf, void *eccbuf)
653{
654#if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
655 register int index, count, retries, r, i;
656 register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
657 u8 *pbuf = (u8 *)buf;
658 u8 *pecc = (u8 *)eccbuf;
659 u8 *p = mcman_sio2packet.out_dma.addr;
660
661 count = (mcdi->pagesize + 127) >> 7;
662
663 retries = 0;
664
665 do {
666 if (retries > 0)
667 mcman_cardchanged(port, slot);
668
669 sio2packet_add(port, slot, 0xffffffff, NULL);
670 sio2packet_add(port, slot, 0x04, (u8 *)&page);
671
672 if (count > 0) {
673 index = 0;
674 while (index < count) {
675 sio2packet_add(port, slot, 0x0b, NULL);
676 index++;
677 }
678 }
679
680 if (mcdi->cardflags & CF_USE_ECC) // if memcard have ECC support
681 sio2packet_add(port, slot, 0x0f, NULL);
682
683 sio2packet_add(port, slot, 0x0c, NULL);
684 sio2packet_add(port, slot, 0xfffffffe, NULL);
685
686 mcsio2_transfer(port, slot, &mcman_sio2packet);
687
688 if (((mcman_sio2packet.stat6c & 0xF000) != 0x1000)
689 || (p[8] != 0x5a)
690 || (p[0x94 + 0x2cf] != 0x5a))
691 continue;
692
693 if (count > 0) {
694 index = 0;
695 while (index < count) {
696 // checking EDC
697 r = mcman_calcEDC(&p[0x94 + ((index + (index << 3)) << 4)], 128) & 0xFF;
698 if (r != p[0x94 + 128 + ((index + (index << 3)) << 4)])
699 break;
700 index++;
701 }
702
703 if (index < count)
704 continue;
705
706 index = 0;
707 while (index < count) {
708 for (i=0; i<128; i++)
709 pbuf[(index << 7) + i] = p[0x94 + ((index + (index << 3)) << 4) + i];
710 index++;
711 }
712 }
713
714 memcpy(pecc, &p[0x94 + ((count + (count << 3)) << 4)] , mcman_sparesize(port, slot));
715 break;
716
717 } while (++retries < 5);
718
719 if (retries < 5)
720 return sceMcResSucceed;
721#elif defined(BUILDING_VMCMAN)
722 if (!mcman_iomanx_backing_read(port, slot, page, buf, eccbuf)) {
723 return sceMcResSucceed;
724 }
725#elif defined(BUILDING_XFROMMAN)
726 (void)port;
727 (void)slot;
728 // No retry logic here.
729 char page_buf[528];
730 if (!flash_page_read(&dev9_flash_info, page, 1, page_buf))
731 {
732 if (buf)
733 {
734 memcpy(buf, page_buf, 512);
735 }
736 if (eccbuf)
737 {
738 memcpy(eccbuf, page_buf + 512, 16);
739 }
740 return sceMcResSucceed;
741 }
742#endif
743 return sceMcResChangedCard;
744}
745
746//--------------------------------------------------------------
747int McGetCardSpec(int port, int slot, s16 *pagesize, u16 *blocksize, int *cardsize, u8 *flags)
748{
749#if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
750 register int retries, r;
751 u8 *p = mcman_sio2packet.out_dma.addr;
752
753 DPRINTF("McGetCardSpec sio2cmd port%d slot%d\n", port, slot);
754
755 HAKAMA_WAITSEMA();
756
757 sio2packet_add(port, slot, 0xffffffff, NULL);
758 sio2packet_add(port, slot, 0x07, NULL);
759 sio2packet_add(port, slot, 0xfffffffe, NULL);
760
761 retries = 0;
762
763 do {
764 mcsio2_transfer(port, slot, &mcman_sio2packet);
765
766 if (((mcman_sio2packet.stat6c & 0xF000) == 0x1000) && (p[12] == 0x5a)) {
767 // checking EDC
768 r = mcman_calcEDC(&p[3], 8) & 0xFF;
769 if (r == p[11])
770 break;
771 }
772 } while (++retries < 5);
773
774 if (retries >= 5) {
775 HAKAMA_SIGNALSEMA();
776 return sceMcResChangedCard;
777 }
778
779 *pagesize = (p[4] << 8) + p[3];
780 *blocksize = (p[6] << 8) + p[5];
781 *cardsize = (p[8] << 8) + p[7] + (p[9] << 16) + (p[10] << 24);
782 *flags = p[2];
783#elif defined(BUILDING_VMCMAN)
784 if (mcman_iomanx_backing_getcardspec(port, slot, pagesize, blocksize, cardsize, flags))
785 return sceMcResFailDetect2;
786#elif defined(BUILDING_XFROMMAN)
787 (void)port;
788 (void)slot;
789 flash_get_info(&dev9_flash_info);
790 *pagesize = 512; /* Yes, this is hardcoded to 512 bytes */
791 *blocksize = dev9_flash_info.block_pages;
792 *cardsize = dev9_flash_info.blocks * dev9_flash_info.block_pages;
793 *flags = 0x22 | CF_BAD_BLOCK;
794 if (dev9_flash_info.page_bytes != 512)
795 *flags |= CF_USE_ECC;
796#endif
797 DPRINTF("McGetCardSpec sio2cmd pagesize=%d blocksize=%u cardsize=%d flags%x\n", *pagesize, *blocksize, *cardsize, *flags);
798 HAKAMA_SIGNALSEMA();
799
800 return sceMcResSucceed;
801}
802
803//--------------------------------------------------------------
804int mcman_resetauth(int port, int slot)
805{
806#if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
807 register int retries;
808
809 DPRINTF("mcman_resetauth sio2cmd port%d slot%d\n", port, slot);
810
811 sio2packet_add(port, slot, 0xffffffff, NULL);
812 sio2packet_add(port, slot, 0x11, NULL);
813 sio2packet_add(port, slot, 0xfffffffe, NULL);
814
815 retries = 0;
816
817 do {
818 mcsio2_transfer(port, slot, &mcman_sio2packet);
819
820 if ((mcman_sio2packet.stat6c & 0xF000) == 0x1000)
821 break;
822
823 } while (++retries < 5);
824
825 if (retries >= 5) {
826 DPRINTF("mcman_resetauth sio2cmd card changed!\n");
827
828 return sceMcResChangedCard;
829 }
830
831 DPRINTF("mcman_resetauth sio2cmd succeeded\n");
832#else
833 (void)port;
834 (void)slot;
835#endif
836
837 return sceMcResSucceed;
838}
839
840//--------------------------------------------------------------
841int mcman_probePS2Card2(int port, int slot)
842{
843#if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
844 register int retries, r;
845 u8 *p = mcman_sio2packet.out_dma.addr;
846
847 DPRINTF("mcman_probePS2Card2 sio2cmd port%d slot%d\n", port, slot);
848 HAKAMA_WAITSEMA();
849 retries = 0;
850 do {
851 sio2packet_add(port, slot, 0xffffffff, NULL);
852 sio2packet_add(port, slot, 0x09, NULL);
853 sio2packet_add(port, slot, 0xfffffffe, NULL);
854
855 mcsio2_transfer(port, slot, &mcman_sio2packet);
856
857 if (((mcman_sio2packet.stat6c & 0xF000) == 0x1000) && (p[4] != 0x66))
858 break;
859 } while (++retries < 5);
860
861 if (retries >= 5) {
862 HAKAMA_SIGNALSEMA();
863 return sceMcResFailDetect;
864 }
865
866 if (p[3] == 0x5a) {
867 r = McGetFormat(port, slot);
868 if (r > 0)
869 {
870 DPRINTF("mcman_probePS2Card2 succeeded\n");
871 HAKAMA_SIGNALSEMA();
872 return sceMcResSucceed;
873 }
874 else if (r < 0)
875 {
876 DPRINTF("mcman_probePS2Card2 sio2cmd failed (no format)\n");
877 HAKAMA_SIGNALSEMA();
878 return sceMcResNoFormat;
879 }
880 }
881
882 DPRINTF("mcman_probePS2Card2 sio2cmd failed (mc detection failed)\n");
883#else
884 if (!McGetFormat(port, slot))
885 {
886 mcman_probePS2Card(port, slot);
887 }
888 if (McGetFormat(port, slot) > 0)
889 return sceMcResSucceed;
890 if (McGetFormat(port, slot) < 0)
891 return sceMcResNoFormat;
892#endif
893
894 HAKAMA_SIGNALSEMA();
895 return sceMcResFailDetect2;
896}
897
898//--------------------------------------------------------------
899int mcman_probePS2Card(int port, int slot) //2
900{
901 register int r;
902#if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
903 register int retries;
904 u8 *p = mcman_sio2packet.out_dma.addr;
905#endif
906
907 HAKAMA_WAITSEMA();
908
909 DPRINTF("mcman_probePS2Card sio2cmd port%d slot%d\n", port, slot);
910
911 r = mcman_cardchanged(port, slot);
912 if (r == sceMcResSucceed) {
913 r = McGetFormat(port, slot);
914#ifdef BUILDING_DONGLEMAN
915 if (r != 0 && port == 0) {
916 DPRINTF("mcman_probePS2Card:[McGetFormat() != 0]: calling authdongle(2, %d, %d)\n", slot, mcman_getcnum(port, slot));
917 SecrAuthDongle(2, slot, mcman_getcnum(port, slot));
918 }
919#endif
920 if (r > 0)
921 {
922 DPRINTF("mcman_probePS2Card sio2cmd succeeded\n");
923 HAKAMA_SIGNALSEMA();
924 return sceMcResSucceed;
925 }
926 else if (r < 0)
927 {
928 DPRINTF("mcman_probePS2Card sio2cmd failed (no format)\n");
929 HAKAMA_SIGNALSEMA();
930 return sceMcResNoFormat;
931 }
932 }
933
934#if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
935 if (mcman_resetauth(port, slot) != sceMcResSucceed) {
936 DPRINTF("mcman_probePS2Card sio2cmd failed (auth reset failed)\n");
937 HAKAMA_SIGNALSEMA();
938 return sceMcResFailResetAuth;
939 }
940
941#ifdef BUILDING_DONGLEMAN
942 if (port == 0) {
943 DPRINTF("mcman_probePS2Card: SecrAuthDongle(2, %d, %d)\n", slot, mcman_getcnum(port, slot));
944 if (SecrAuthDongle(2, slot, mcman_getcnum(port, slot)) == 0) {
945 DPRINTF("mcman_probePS2Card SecrAuthDongle Failed\n");
946
947 return sceMcResFailAuth;
948 }
949 }
950 else if (SecrAuthCard(port + 2, slot, mcman_getcnum(port, slot)) == 0) {
951 DPRINTF("mcman_probePS2Card sio2cmd failed (auth failed)\n");
952
953 return sceMcResFailAuth;
954 }
955#else
956 if (SecrAuthCard(port + 2, slot, mcman_getcnum(port, slot)) == 0) {
957 DPRINTF("mcman_probePS2Card sio2cmd failed (auth failed)\n");
958
959 return sceMcResFailAuth;
960 }
961#endif
962
963 retries = 0;
964 do {
965 sio2packet_add(port, slot, 0xffffffff, NULL);
966 sio2packet_add(port, slot, 0x09, NULL);
967 sio2packet_add(port, slot, 0xfffffffe, NULL);
968
969 mcsio2_transfer(port, slot, &mcman_sio2packet);
970
971 if (((mcman_sio2packet.stat6c & 0xF000) == 0x1000) && (p[4] != 0x66))
972 break;
973 } while (++retries < 5);
974
975 if (retries >= 5) {
976 DPRINTF("mcman_probePS2Card sio2cmd failed (mc detection failed)\n");
977 return sceMcResFailDetect;
978 }
979#endif
980
981 mcman_clearcache(port, slot);
982
983#if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
984 sio2packet_add(port, slot, 0xffffffff, NULL);
985 sio2packet_add(port, slot, 0x08, NULL);
986 sio2packet_add(port, slot, 0xfffffffe, NULL);
987
988 retries = 0;
989 do {
990 mcsio2_transfer(port, slot, &mcman_sio2packet);
991
992 if ((mcman_sio2packet.stat6c & 0xF000) != 0x1000)
993 continue;
994
995 if (p[4] == 0x5a)
996 break;
997 } while (++retries < 5);
998
999 if (retries >= 5) {
1000 DPRINTF("mcman_probePS2Card sio2cmd failed (mc detection failed)\n");
1001
1002 return sceMcResFailDetect2;
1003 }
1004#endif
1005
1006 r = mcman_setdevinfos(port, slot);
1007 if (r == 0) {
1008 DPRINTF("mcman_probePS2Card sio2cmd card changed!\n");
1009 return sceMcResChangedCard;
1010 }
1011 if (r != sceMcResNoFormat) {
1012 DPRINTF("mcman_probePS2Card sio2cmd failed (mc detection failed)\n");
1013 return sceMcResFailDetect2;
1014 }
1015
1016 DPRINTF("mcman_probePS2Card sio2cmd succeeded\n");
1017
1018 return r;
1019}
1020
1021//--------------------------------------------------------------
1022int mcman_probePS1Card2(int port, int slot)
1023{
1024#if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
1025 register int retries;
1026 register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
1027
1028 DPRINTF("mcman_probePS1Card2 port%d slot%d\n", port, slot);
1029
1030 mcman_sio2packet_PS1PDA.regdata[0] = 0;
1031 mcman_sio2packet_PS1PDA.regdata[0] = (((port & 1) + 2)) | 0x000c0340;
1032 mcman_sio2packet_PS1PDA.in_size = 3;
1033 mcman_sio2packet_PS1PDA.out_size = 3;
1034
1035 mcman_sio2packet_PS1PDA.regdata[1] = 0;
1036 mcman_sio2inbufs_PS1PDA[0] = 0x81;
1037 mcman_sio2inbufs_PS1PDA[1] = 0x52;
1038
1039 retries = 0;
1040 do {
1041 mcman_timercount = (u32)(GetTimerCounter(timer_ID) - mcman_timercount);
1042
1043 u32 hi, lo;
1044 long_multiply(mcman_timercount, 0x3e0f83e1, &hi, &lo);
1045
1046 if (((u32)(hi >> 3) < (u32)mcman_timerthick))
1047 DelayThread(mcman_timerthick - (hi >> 3));
1048
1049 mcsio2_transfer(port, slot, &mcman_sio2packet_PS1PDA);
1050
1051 mcman_timercount = GetTimerCounter(timer_ID);
1052 mcman_timerthick = 0;
1053
1054 if (((mcman_sio2packet_PS1PDA.stat6c & 0xf000) == 0x1000) \
1055 && (mcman_sio2outbufs_PS1PDA[2] == 0x5a)) {
1056 break;
1057 }
1058 } while (++retries < 5);
1059
1060 if (retries >= 5)
1061 return -12;
1062
1063 if (mcman_sio2outbufs_PS1PDA[1] == 0) {
1064 if (mcdi->cardform > 0)
1065 return sceMcResSucceed;
1066 else if (mcdi->cardform < 0)
1067 return sceMcResNoFormat;
1068 }
1069 else if (mcman_sio2outbufs_PS1PDA[1] != 8) {
1070 return -14;
1071 }
1072#else
1073 (void)port;
1074 (void)slot;
1075#endif
1076
1077 return -13;
1078}
1079
1080//--------------------------------------------------------------
1081int mcman_probePS1Card(int port, int slot)
1082{
1083#if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
1084 register int i, r, retries;
1085 register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
1086 u32 *p;
1087
1088 DPRINTF("mcman_probePS1Card port%d slot%d\n", port, slot);
1089
1090 mcman_sio2packet_PS1PDA.regdata[0] = 0;
1091 mcman_sio2packet_PS1PDA.regdata[0] = (((port & 1) + 2)) | 0x000c0340;
1092 mcman_sio2packet_PS1PDA.in_size = 3;
1093 mcman_sio2packet_PS1PDA.out_size = 3;
1094
1095 mcman_sio2packet_PS1PDA.regdata[1] = 0;
1096 mcman_sio2inbufs_PS1PDA[0] = 0x81;
1097 mcman_sio2inbufs_PS1PDA[1] = 0x52;
1098
1099 retries = 0;
1100 do {
1101 mcman_timercount = (u32)(GetTimerCounter(timer_ID) - mcman_timercount);
1102
1103 u32 hi, lo;
1104 long_multiply(mcman_timercount, 0x3e0f83e1, &hi, &lo);
1105
1106 if (((u32)(hi >> 3) < (u32)mcman_timerthick))
1107 DelayThread(mcman_timerthick - (hi >> 3));
1108
1109 mcsio2_transfer(port, slot, &mcman_sio2packet_PS1PDA);
1110
1111 mcman_timercount = GetTimerCounter(timer_ID);
1112 mcman_timerthick = 0;
1113
1114 if (((mcman_sio2packet_PS1PDA.stat6c & 0xf000) == 0x1000) \
1115 && (mcman_sio2outbufs_PS1PDA[2] == 0x5a)) {
1116 break;
1117 }
1118 } while (++retries < 5);
1119
1120 if (retries >= 5)
1121 return -11;
1122
1123 if (mcman_sio2outbufs_PS1PDA[1] == 0) {
1124 if (mcdi->cardform != 0)
1125 return sceMcResSucceed;
1126 else
1127 return sceMcResNoFormat;
1128 }
1129 else if (mcman_sio2outbufs_PS1PDA[1] != 8) {
1130 return -12;
1131 }
1132
1133 mcman_clearcache(port, slot);
1134
1135 p = (u32 *)&mcman_sio2outbufs_PS1PDA[124];
1136 for (i = 31; i >= 0; i--)
1137 *p-- = 0;
1138
1139 r = McWritePS1PDACard(port, slot, 63, mcman_sio2outbufs_PS1PDA);
1140 if (r < 0)
1141 return -13;
1142
1143 r = mcman_setPS1devinfos(port, slot);
1144 if (r == 0)
1145 return sceMcResChangedCard;
1146
1147 return r;
1148#else
1149 (void)port;
1150 (void)slot;
1151 return sceMcResSucceed;
1152#endif
1153}
1154
1155//--------------------------------------------------------------
1156int mcman_probePDACard(int port, int slot)
1157{
1158#if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
1159 register int retries;
1160
1161 DPRINTF("mcman_probePDACard port%d slot%d\n", port, slot);
1162
1163 mcman_sio2packet_PS1PDA.regdata[0] = 0;
1164 mcman_sio2packet_PS1PDA.regdata[0] = (port & 3) | 0x00140540;
1165 mcman_sio2packet_PS1PDA.in_size = 5;
1166 mcman_sio2packet_PS1PDA.out_size = 5;
1167
1168 mcman_sio2packet_PS1PDA.regdata[1] = 0;
1169 mcman_sio2inbufs_PS1PDA[0] = 0x81;
1170 mcman_sio2inbufs_PS1PDA[1] = 0x58;
1171
1172 retries = 0;
1173 do {
1174 mcsio2_transfer(port, slot, &mcman_sio2packet_PS1PDA);
1175
1176 if ((mcman_sio2packet_PS1PDA.stat6c & 0xf000) == 0x1000)
1177 break;
1178
1179 } while (++retries < 5);
1180
1181 if (retries >= 5)
1182 return -11;
1183#else
1184 (void)port;
1185 (void)slot;
1186#endif
1187
1188 return sceMcResSucceed;
1189}
1190
1191//--------------------------------------------------------------
1192int McWritePS1PDACard(int port, int slot, int page, void *buf) // Export #30
1193{
1194#if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
1195 register int i, retries;
1196 register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
1197 u8 *p;
1198
1199 //DPRINTF("McWritePS1PDACard port%d slot%d page %x\n", port, slot, page);
1200
1201 mcman_sio2packet_PS1PDA.regdata[0] = 0;
1202 mcman_sio2packet_PS1PDA.regdata[0] = (((port & 1) + 2) & 3) | 0x02288a40;
1203 mcman_sio2packet_PS1PDA.in_size = 138;
1204 mcman_sio2packet_PS1PDA.out_size = 138;
1205 mcman_sio2packet_PS1PDA.regdata[1] = 0;
1206
1207 for (i = 0; i < 20; i++) {
1208 if (mcdi->bad_block_list[i] == page)
1209 page += 36;
1210 }
1211
1212 mcman_sio2inbufs_PS1PDA[0] = 0x81;
1213 mcman_sio2inbufs_PS1PDA[1] = 0x57;
1214 mcman_sio2inbufs_PS1PDA[4] = (u8)(page >> 8);
1215 mcman_sio2inbufs_PS1PDA[5] = (u8)page;
1216
1217 p = (u8 *)buf;
1218 for (i = 0; i < 128; i++)
1219 mcman_sio2inbufs_PS1PDA[6 + i] = p[i];
1220
1221 mcman_sio2inbufs_PS1PDA[4 + 130] = mcman_calcEDC(&mcman_sio2inbufs_PS1PDA[4], 130);
1222
1223 retries = 0;
1224 do {
1225 mcman_timercount = (u32)(GetTimerCounter(timer_ID) - mcman_timercount);
1226
1227 u32 hi, lo;
1228 long_multiply(mcman_timercount, 0x3e0f83e1, &hi, &lo);
1229
1230 if (((u32)(hi >> 3) < (u32)mcman_timerthick))
1231 DelayThread(mcman_timerthick - (hi >> 3));
1232
1233 mcsio2_transfer(port, slot, &mcman_sio2packet_PS1PDA);
1234
1235 mcman_timercount = GetTimerCounter(timer_ID);
1236 mcman_timerthick = 20000;
1237
1238 if (((mcman_sio2packet_PS1PDA.stat6c & 0xf000) == 0x1000) \
1239 && (mcman_sio2outbufs_PS1PDA[2] == 0x5a) \
1240 && (mcman_sio2outbufs_PS1PDA[3] == 0x5d) \
1241 && (mcman_sio2outbufs_PS1PDA[137] == 0x47)) {
1242 break;
1243 }
1244 } while (++retries < 5);
1245
1246 if (retries >= 5)
1247 return sceMcResNoEntry;
1248
1249 if ((mcman_sio2outbufs_PS1PDA[1] != 0) && (mcman_sio2outbufs_PS1PDA[1] != 8))
1250 return sceMcResFullDevice;
1251#else
1252 (void)port;
1253 (void)slot;
1254 (void)page;
1255 (void)buf;
1256#endif
1257
1258 return sceMcResSucceed;
1259}
1260
1261//--------------------------------------------------------------
1262int McReadPS1PDACard(int port, int slot, int page, void *buf) // Export #29
1263{
1264#if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
1265 register int i, retries;
1266 register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
1267 u8 *p;
1268
1269 //DPRINTF("McReadPS1PDACard port%d slot%d page %x\n", port, slot, page);
1270
1271 mcman_sio2packet_PS1PDA.regdata[0] = 0;
1272 mcman_sio2packet_PS1PDA.regdata[0] = (((port & 1) + 2) & 3) | 0x02308c40;
1273 mcman_sio2packet_PS1PDA.in_size = 140;
1274 mcman_sio2packet_PS1PDA.out_size = 140;
1275 mcman_sio2packet_PS1PDA.regdata[1] = 0;
1276
1277 for (i = 0; i < 20; i++) {
1278 if (mcdi->bad_block_list[i] == page)
1279 page += 36;
1280 }
1281
1282 mcman_sio2inbufs_PS1PDA[0] = 0x81;
1283 mcman_sio2inbufs_PS1PDA[1] = 0x52;
1284 mcman_sio2inbufs_PS1PDA[4] = (u8)(page >> 8);
1285 mcman_sio2inbufs_PS1PDA[5] = (u8)page;
1286
1287 retries = 0;
1288 do {
1289 mcman_timercount = (u32)(GetTimerCounter(timer_ID) - mcman_timercount);
1290
1291 u32 hi, lo;
1292 long_multiply(mcman_timercount, 0x3e0f83e1, &hi, &lo);
1293
1294 if (((u32)(hi >> 3) < (u32)mcman_timerthick))
1295 DelayThread(mcman_timerthick - (hi >> 3));
1296
1297 mcsio2_transfer(port, slot, &mcman_sio2packet_PS1PDA);
1298
1299 mcman_timercount = GetTimerCounter(timer_ID);
1300 mcman_timerthick = 10000;
1301
1302 if (((mcman_sio2packet_PS1PDA.stat6c & 0xf000) == 0x1000) \
1303 && (mcman_sio2outbufs_PS1PDA[2] == 0x5a) \
1304 && (mcman_sio2outbufs_PS1PDA[3] == 0x5d) \
1305 && (mcman_sio2outbufs_PS1PDA[4] == 0x00) \
1306 && (mcman_sio2outbufs_PS1PDA[6] == 0x5c) \
1307 && (mcman_sio2outbufs_PS1PDA[7] == 0x5d) \
1308 && (mcman_sio2outbufs_PS1PDA[139] == 0x47)) {
1309
1310 if (mcman_sio2outbufs_PS1PDA[138] == (mcman_calcEDC(&mcman_sio2outbufs_PS1PDA[8], 130) & 0xff))
1311 break;
1312 }
1313 } while (++retries < 5);
1314
1315 if (retries >= 5)
1316 return sceMcResNoEntry;
1317
1318 p = (u8 *)buf;
1319 for (i = 0; i < 128; i++)
1320 p[i] = mcman_sio2outbufs_PS1PDA[10 + i];
1321
1322 if ((mcman_sio2outbufs_PS1PDA[1] != 0) && (mcman_sio2outbufs_PS1PDA[1] != 8))
1323 return sceMcResDeniedPermit;
1324#else
1325 (void)port;
1326 (void)slot;
1327 (void)page;
1328 (void)buf;
1329#endif
1330
1331 return sceMcResSucceed;
1332}
1333
1334
Definition tcpip.h:200
u32 count
start sector of fragmented bd/file