sdk-core v2026.11.05
PS2 SDK - core tier (build-critical EE/IOP modules)
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 //HAKAMA_SIGNALSEMA();
545 return sceMcResNoFormat;
546#else
547 //HAKAMA_SIGNALSEMA();
548 return sceMcResSucceed;
549#endif
550}
551
552//--------------------------------------------------------------
553int McWritePage(int port, int slot, int page, void *pagebuf, void *eccbuf) // Export #19
554{
555 register int retries;
556#if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
557 register int index, count;
558 u8 *p_pagebuf = (u8 *)pagebuf;
559 u8 *p = mcman_sio2packet.out_dma.addr;
560#endif
561
562 HAKAMA_WAITSEMA();
563
564#ifdef BUILDING_XFROMMAN
565 (void)port;
566 (void)slot;
567 char page_buf[528];
568 memcpy(page_buf, pagebuf, 512);
569 memcpy(page_buf + 512, eccbuf, 16);
570#endif
571
572#if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
573 count = (mcman_devinfos[port][slot].pagesize + 127) >> 7;
574#endif
575
576 retries = 0;
577
578 do {
579#if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
580 if (retries > 0)
581 mcman_cardchanged(port, slot);
582
583 sio2packet_add(port, slot, 0xffffffff, NULL);
584 sio2packet_add(port, slot, 0x03, (u8 *)&page);
585
586 index = 0;
587 while (index < count) {
588 sio2packet_add(port, slot, 0x0a, (u8 *)&p_pagebuf[index << 7]);
589 index++;
590 }
591
592 if (mcman_devinfos[port][slot].cardflags & CF_USE_ECC) {
593 // if memcard have ECC support
594 sio2packet_add(port, slot, 0x0e, eccbuf);
595 }
596 sio2packet_add(port, slot, 0xfffffffe, NULL);
597
598 mcsio2_transfer(port, slot, &mcman_sio2packet);
599
600 if (((mcman_sio2packet.stat6c & 0xF000) != 0x1000) || (p[8] != 0x5a))
601 continue;
602
603 index = 0;
604 while (index < count) {
605 if (p[0x94 + 128 + 1 + ((index + (index << 3)) << 4)] != 0x5a)
606 break;
607 index++;
608 }
609
610 if (index < count)
611 continue;
612
613 if (mcman_devinfos[port][slot].cardflags & CF_USE_ECC) {
614 // if memcard have ECC support
615 index++;
616 if (p[5 + ((index + (index << 3)) << 4) + mcman_sparesize(port, slot)] != 0x5a)
617 continue;
618 }
619
620 sio2packet_add(port, slot, 0xffffffff, NULL);
621 sio2packet_add(port, slot, 0x0c, NULL);
622 sio2packet_add(port, slot, 0xfffffffe, NULL);
623
624 mcsio2_transfer(port, slot, &mcman_sio2packet);
625
626 if (((mcman_sio2packet.stat6c & 0xF000) != 0x1000) || (p[3] != 0x5a))
627 continue;
628#elif defined(BUILDING_VMCMAN)
629 if (mcman_iomanx_backing_write(port, slot, page, pagebuf, eccbuf))
630 continue;
631#elif defined(BUILDING_XFROMMAN)
632 if (flash_page_write(&dev9_flash_info, page, page_buf))
633 continue;
634#endif
635 HAKAMA_SIGNALSEMA();
636 return sceMcResSucceed;
637
638 } while (++retries < 5);
639
640#if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
641 HAKAMA_SIGNALSEMA(); // El_isra: simplify original impl
642 if (p[3] == 0x66) {
643 //HAKAMA_SIGNALSEMA();
644 return sceMcResFailReplace;
645 }
646
647 //HAKAMA_SIGNALSEMA();
648 return sceMcResNoFormat;
649#else
650 return sceMcResFailReplace;
651#endif
652}
653
654//--------------------------------------------------------------
655int mcman_readpage(int port, int slot, int page, void *buf, void *eccbuf)
656{
657#if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
658 register int index, count, retries, r, i;
659 register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
660 u8 *pbuf = (u8 *)buf;
661 u8 *pecc = (u8 *)eccbuf;
662 u8 *p = mcman_sio2packet.out_dma.addr;
663
664 count = (mcdi->pagesize + 127) >> 7;
665
666 retries = 0;
667
668 do {
669 if (retries > 0)
670 mcman_cardchanged(port, slot);
671
672 sio2packet_add(port, slot, 0xffffffff, NULL);
673 sio2packet_add(port, slot, 0x04, (u8 *)&page);
674
675 if (count > 0) {
676 index = 0;
677 while (index < count) {
678 sio2packet_add(port, slot, 0x0b, NULL);
679 index++;
680 }
681 }
682
683 if (mcdi->cardflags & CF_USE_ECC) // if memcard have ECC support
684 sio2packet_add(port, slot, 0x0f, NULL);
685
686 sio2packet_add(port, slot, 0x0c, NULL);
687 sio2packet_add(port, slot, 0xfffffffe, NULL);
688
689 mcsio2_transfer(port, slot, &mcman_sio2packet);
690
691 if (((mcman_sio2packet.stat6c & 0xF000) != 0x1000)
692 || (p[8] != 0x5a)
693 || (p[0x94 + 0x2cf] != 0x5a))
694 continue;
695
696 if (count > 0) {
697 index = 0;
698 while (index < count) {
699 // checking EDC
700 r = mcman_calcEDC(&p[0x94 + ((index + (index << 3)) << 4)], 128) & 0xFF;
701 if (r != p[0x94 + 128 + ((index + (index << 3)) << 4)])
702 break;
703 index++;
704 }
705
706 if (index < count)
707 continue;
708
709 index = 0;
710 while (index < count) {
711 for (i=0; i<128; i++)
712 pbuf[(index << 7) + i] = p[0x94 + ((index + (index << 3)) << 4) + i];
713 index++;
714 }
715 }
716
717 memcpy(pecc, &p[0x94 + ((count + (count << 3)) << 4)] , mcman_sparesize(port, slot));
718 break;
719
720 } while (++retries < 5);
721
722 if (retries < 5)
723 return sceMcResSucceed;
724#elif defined(BUILDING_VMCMAN)
725 if (!mcman_iomanx_backing_read(port, slot, page, buf, eccbuf)) {
726 return sceMcResSucceed;
727 }
728#elif defined(BUILDING_XFROMMAN)
729 (void)port;
730 (void)slot;
731 // No retry logic here.
732 char page_buf[528];
733 if (!flash_page_read(&dev9_flash_info, page, 1, page_buf))
734 {
735 if (buf)
736 {
737 memcpy(buf, page_buf, 512);
738 }
739 if (eccbuf)
740 {
741 memcpy(eccbuf, page_buf + 512, 16);
742 }
743 return sceMcResSucceed;
744 }
745#endif
746 return sceMcResChangedCard;
747}
748
749//--------------------------------------------------------------
750int McGetCardSpec(int port, int slot, s16 *pagesize, u16 *blocksize, int *cardsize, u8 *flags)
751{
752#if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
753 register int retries, r;
754 u8 *p = mcman_sio2packet.out_dma.addr;
755
756 DPRINTF("McGetCardSpec sio2cmd port%d slot%d\n", port, slot);
757
758 HAKAMA_WAITSEMA();
759
760 sio2packet_add(port, slot, 0xffffffff, NULL);
761 sio2packet_add(port, slot, 0x07, NULL);
762 sio2packet_add(port, slot, 0xfffffffe, NULL);
763
764 retries = 0;
765
766 do {
767 mcsio2_transfer(port, slot, &mcman_sio2packet);
768
769 if (((mcman_sio2packet.stat6c & 0xF000) == 0x1000) && (p[12] == 0x5a)) {
770 // checking EDC
771 r = mcman_calcEDC(&p[3], 8) & 0xFF;
772 if (r == p[11])
773 break;
774 }
775 } while (++retries < 5);
776
777 if (retries >= 5) {
778 HAKAMA_SIGNALSEMA();
779 return sceMcResChangedCard;
780 }
781
782 *pagesize = (p[4] << 8) + p[3];
783 *blocksize = (p[6] << 8) + p[5];
784 *cardsize = (p[8] << 8) + p[7] + (p[9] << 16) + (p[10] << 24);
785 *flags = p[2];
786#elif defined(BUILDING_VMCMAN)
787 if (mcman_iomanx_backing_getcardspec(port, slot, pagesize, blocksize, cardsize, flags))
788 return sceMcResFailDetect2;
789#elif defined(BUILDING_XFROMMAN)
790 (void)port;
791 (void)slot;
792 flash_get_info(&dev9_flash_info);
793 *pagesize = 512; /* Yes, this is hardcoded to 512 bytes */
794 *blocksize = dev9_flash_info.block_pages;
795 *cardsize = dev9_flash_info.blocks * dev9_flash_info.block_pages;
796 *flags = 0x22 | CF_BAD_BLOCK;
797 if (dev9_flash_info.page_bytes != 512)
798 *flags |= CF_USE_ECC;
799#endif
800 DPRINTF("McGetCardSpec sio2cmd pagesize=%d blocksize=%u cardsize=%d flags%x\n", *pagesize, *blocksize, *cardsize, *flags);
801 HAKAMA_SIGNALSEMA();
802
803 return sceMcResSucceed;
804}
805
806//--------------------------------------------------------------
807int mcman_resetauth(int port, int slot)
808{
809#if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
810 register int retries;
811
812 DPRINTF("mcman_resetauth sio2cmd port%d slot%d\n", port, slot);
813
814 sio2packet_add(port, slot, 0xffffffff, NULL);
815 sio2packet_add(port, slot, 0x11, NULL);
816 sio2packet_add(port, slot, 0xfffffffe, NULL);
817
818 retries = 0;
819
820 do {
821 mcsio2_transfer(port, slot, &mcman_sio2packet);
822
823 if ((mcman_sio2packet.stat6c & 0xF000) == 0x1000)
824 break;
825
826 } while (++retries < 5);
827
828 if (retries >= 5) {
829 DPRINTF("mcman_resetauth sio2cmd card changed!\n");
830
831 return sceMcResChangedCard;
832 }
833
834 DPRINTF("mcman_resetauth sio2cmd succeeded\n");
835#else
836 (void)port;
837 (void)slot;
838#endif
839
840 return sceMcResSucceed;
841}
842
843//--------------------------------------------------------------
844int mcman_probePS2Card2(int port, int slot)
845{
846#if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
847 register int retries, r;
848 u8 *p = mcman_sio2packet.out_dma.addr;
849
850 DPRINTF("mcman_probePS2Card2 sio2cmd port%d slot%d\n", port, slot);
851 HAKAMA_WAITSEMA();
852 retries = 0;
853 do {
854 sio2packet_add(port, slot, 0xffffffff, NULL);
855 sio2packet_add(port, slot, 0x09, NULL);
856 sio2packet_add(port, slot, 0xfffffffe, NULL);
857
858 mcsio2_transfer(port, slot, &mcman_sio2packet);
859
860 if (((mcman_sio2packet.stat6c & 0xF000) == 0x1000) && (p[4] != 0x66))
861 break;
862 } while (++retries < 5);
863
864 if (retries >= 5) {
865 HAKAMA_SIGNALSEMA();
866 return sceMcResFailDetect;
867 }
868
869 if (p[3] == 0x5a) {
870 r = McGetFormat(port, slot);
871 if (r > 0)
872 {
873 DPRINTF("mcman_probePS2Card2 succeeded\n");
874 HAKAMA_SIGNALSEMA();
875 return sceMcResSucceed;
876 }
877 else if (r < 0)
878 {
879 DPRINTF("mcman_probePS2Card2 sio2cmd failed (no format)\n");
880 HAKAMA_SIGNALSEMA();
881 return sceMcResNoFormat;
882 }
883 }
884
885 DPRINTF("mcman_probePS2Card2 sio2cmd failed (mc detection failed)\n");
886#else
887 if (!McGetFormat(port, slot))
888 {
889 mcman_probePS2Card(port, slot);
890 }
891 if (McGetFormat(port, slot) > 0)
892 return sceMcResSucceed;
893 if (McGetFormat(port, slot) < 0)
894 return sceMcResNoFormat;
895#endif
896
897 HAKAMA_SIGNALSEMA();
898 return sceMcResFailDetect2;
899}
900
901//--------------------------------------------------------------
902int mcman_probePS2Card(int port, int slot) //2
903{
904 register int r;
905#if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
906 register int retries;
907 u8 *p = mcman_sio2packet.out_dma.addr;
908#endif
909
910 HAKAMA_WAITSEMA();
911
912 DPRINTF("mcman_probePS2Card sio2cmd port%d slot%d\n", port, slot);
913
914 r = mcman_cardchanged(port, slot);
915 if (r == sceMcResSucceed) {
916 r = McGetFormat(port, slot);
917#ifdef BUILDING_DONGLEMAN
918 if (r != 0 && port == 0) {
919 DPRINTF("mcman_probePS2Card:[McGetFormat() != 0]: calling authdongle(2, %d, %d)\n", slot, mcman_getcnum(port, slot));
920 SecrAuthDongle(2, slot, mcman_getcnum(port, slot));
921 }
922#endif
923 if (r != 0) {
924 HAKAMA_SIGNALSEMA();
925 DPRINTF("mcman_probePS2Card sio2cmd succeeded\n");
926 return sceMcResSucceed;
927 }
928 }
929
930#if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
931 if (mcman_resetauth(port, slot) != sceMcResSucceed) {
932 DPRINTF("mcman_probePS2Card sio2cmd failed (auth reset failed)\n");
933 HAKAMA_SIGNALSEMA();
934 return sceMcResFailResetAuth;
935 }
936
937#ifdef BUILDING_DONGLEMAN
938 if (port == 0) {
939 DPRINTF("mcman_probePS2Card: SecrAuthDongle(2, %d, %d)\n", slot, mcman_getcnum(port, slot));
940 if (SecrAuthDongle(2, slot, mcman_getcnum(port, slot)) == 0) {
941 DPRINTF("mcman_probePS2Card SecrAuthDongle Failed\n");
942
943 return sceMcResFailAuth;
944 }
945 }
946 else if (SecrAuthCard(port + 2, slot, mcman_getcnum(port, slot)) == 0) {
947 DPRINTF("mcman_probePS2Card sio2cmd failed (auth failed)\n");
948
949 return sceMcResFailAuth;
950 }
951#else
952 if (SecrAuthCard(port + 2, slot, mcman_getcnum(port, slot)) == 0) {
953 DPRINTF("mcman_probePS2Card sio2cmd failed (auth failed)\n");
954
955 return sceMcResFailAuth;
956 }
957#endif
958
959 retries = 0;
960 do {
961 sio2packet_add(port, slot, 0xffffffff, NULL);
962 sio2packet_add(port, slot, 0x09, NULL);
963 sio2packet_add(port, slot, 0xfffffffe, NULL);
964
965 mcsio2_transfer(port, slot, &mcman_sio2packet);
966
967 if (((mcman_sio2packet.stat6c & 0xF000) == 0x1000) && (p[4] != 0x66))
968 break;
969 } while (++retries < 5);
970
971 if (retries >= 5) {
972 DPRINTF("mcman_probePS2Card sio2cmd failed (mc detection failed)\n");
973 return sceMcResFailDetect;
974 }
975#endif
976
977 mcman_clearcache(port, slot);
978
979#if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
980 sio2packet_add(port, slot, 0xffffffff, NULL);
981 sio2packet_add(port, slot, 0x08, NULL);
982 sio2packet_add(port, slot, 0xfffffffe, NULL);
983
984 retries = 0;
985 do {
986 mcsio2_transfer(port, slot, &mcman_sio2packet);
987
988 if ((mcman_sio2packet.stat6c & 0xF000) != 0x1000)
989 continue;
990
991 if (p[4] == 0x5a)
992 break;
993 } while (++retries < 5);
994
995 if (retries >= 5) {
996 DPRINTF("mcman_probePS2Card sio2cmd failed (mc detection failed)\n");
997
998 return sceMcResFailDetect2;
999 }
1000#endif
1001
1002 r = mcman_setdevinfos(port, slot);
1003 if (r == 0) {
1004 DPRINTF("mcman_probePS2Card sio2cmd card changed!\n");
1005 return sceMcResChangedCard;
1006 }
1007 if (r != sceMcResNoFormat) {
1008 DPRINTF("mcman_probePS2Card sio2cmd failed (mc detection failed)\n");
1009 return sceMcResFailDetect2;
1010 }
1011
1012 DPRINTF("mcman_probePS2Card sio2cmd succeeded\n");
1013
1014 return r;
1015}
1016
1017//--------------------------------------------------------------
1018int mcman_probePS1Card2(int port, int slot)
1019{
1020#if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
1021 register int retries;
1022 register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
1023
1024 DPRINTF("mcman_probePS1Card2 port%d slot%d\n", port, slot);
1025
1026 mcman_sio2packet_PS1PDA.regdata[0] = 0;
1027 mcman_sio2packet_PS1PDA.regdata[0] = (((port & 1) + 2)) | 0x000c0340;
1028 mcman_sio2packet_PS1PDA.in_size = 3;
1029 mcman_sio2packet_PS1PDA.out_size = 3;
1030
1031 mcman_sio2packet_PS1PDA.regdata[1] = 0;
1032 mcman_sio2inbufs_PS1PDA[0] = 0x81;
1033 mcman_sio2inbufs_PS1PDA[1] = 0x52;
1034
1035 retries = 0;
1036 do {
1037 mcman_timercount = (u32)(GetTimerCounter(timer_ID) - mcman_timercount);
1038
1039 u32 hi, lo;
1040 long_multiply(mcman_timercount, 0x3e0f83e1, &hi, &lo);
1041
1042 if (((u32)(hi >> 3) < (u32)mcman_timerthick))
1043 DelayThread(mcman_timerthick - (hi >> 3));
1044
1045 mcsio2_transfer(port, slot, &mcman_sio2packet_PS1PDA);
1046
1047 mcman_timercount = GetTimerCounter(timer_ID);
1048 mcman_timerthick = 0;
1049
1050 if (((mcman_sio2packet_PS1PDA.stat6c & 0xf000) == 0x1000) \
1051 && (mcman_sio2outbufs_PS1PDA[2] == 0x5a)) {
1052 break;
1053 }
1054 } while (++retries < 5);
1055
1056 if (retries >= 5)
1057 return -12;
1058
1059 if (mcman_sio2outbufs_PS1PDA[1] == 0) {
1060 if (mcdi->cardform > 0)
1061 return sceMcResSucceed;
1062 else if (mcdi->cardform < 0)
1063 return sceMcResNoFormat;
1064 }
1065 else if (mcman_sio2outbufs_PS1PDA[1] != 8) {
1066 return -14;
1067 }
1068#else
1069 (void)port;
1070 (void)slot;
1071#endif
1072
1073 return -13;
1074}
1075
1076//--------------------------------------------------------------
1077int mcman_probePS1Card(int port, int slot)
1078{
1079#if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
1080 register int i, r, retries;
1081 register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
1082 u32 *p;
1083
1084 DPRINTF("mcman_probePS1Card port%d slot%d\n", port, slot);
1085
1086 mcman_sio2packet_PS1PDA.regdata[0] = 0;
1087 mcman_sio2packet_PS1PDA.regdata[0] = (((port & 1) + 2)) | 0x000c0340;
1088 mcman_sio2packet_PS1PDA.in_size = 3;
1089 mcman_sio2packet_PS1PDA.out_size = 3;
1090
1091 mcman_sio2packet_PS1PDA.regdata[1] = 0;
1092 mcman_sio2inbufs_PS1PDA[0] = 0x81;
1093 mcman_sio2inbufs_PS1PDA[1] = 0x52;
1094
1095 retries = 0;
1096 do {
1097 mcman_timercount = (u32)(GetTimerCounter(timer_ID) - mcman_timercount);
1098
1099 u32 hi, lo;
1100 long_multiply(mcman_timercount, 0x3e0f83e1, &hi, &lo);
1101
1102 if (((u32)(hi >> 3) < (u32)mcman_timerthick))
1103 DelayThread(mcman_timerthick - (hi >> 3));
1104
1105 mcsio2_transfer(port, slot, &mcman_sio2packet_PS1PDA);
1106
1107 mcman_timercount = GetTimerCounter(timer_ID);
1108 mcman_timerthick = 0;
1109
1110 if (((mcman_sio2packet_PS1PDA.stat6c & 0xf000) == 0x1000) \
1111 && (mcman_sio2outbufs_PS1PDA[2] == 0x5a)) {
1112 break;
1113 }
1114 } while (++retries < 5);
1115
1116 if (retries >= 5)
1117 return -11;
1118
1119 if (mcman_sio2outbufs_PS1PDA[1] == 0) {
1120 if (mcdi->cardform != 0)
1121 return sceMcResSucceed;
1122 else
1123 return sceMcResNoFormat;
1124 }
1125 else if (mcman_sio2outbufs_PS1PDA[1] != 8) {
1126 return -12;
1127 }
1128
1129 mcman_clearcache(port, slot);
1130
1131 p = (u32 *)&mcman_sio2outbufs_PS1PDA[124];
1132 for (i = 31; i >= 0; i--)
1133 *p-- = 0;
1134
1135 r = McWritePS1PDACard(port, slot, 63, mcman_sio2outbufs_PS1PDA);
1136 if (r < 0)
1137 return -13;
1138
1139 r = mcman_setPS1devinfos(port, slot);
1140 if (r == 0)
1141 return sceMcResChangedCard;
1142
1143 return r;
1144#else
1145 (void)port;
1146 (void)slot;
1147 return sceMcResSucceed;
1148#endif
1149}
1150
1151//--------------------------------------------------------------
1152int mcman_probePDACard(int port, int slot)
1153{
1154#if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
1155 register int retries;
1156
1157 DPRINTF("mcman_probePDACard port%d slot%d\n", port, slot);
1158
1159 mcman_sio2packet_PS1PDA.regdata[0] = 0;
1160 mcman_sio2packet_PS1PDA.regdata[0] = (port & 3) | 0x00140540;
1161 mcman_sio2packet_PS1PDA.in_size = 5;
1162 mcman_sio2packet_PS1PDA.out_size = 5;
1163
1164 mcman_sio2packet_PS1PDA.regdata[1] = 0;
1165 mcman_sio2inbufs_PS1PDA[0] = 0x81;
1166 mcman_sio2inbufs_PS1PDA[1] = 0x58;
1167
1168 retries = 0;
1169 do {
1170 mcsio2_transfer(port, slot, &mcman_sio2packet_PS1PDA);
1171
1172 if ((mcman_sio2packet_PS1PDA.stat6c & 0xf000) == 0x1000)
1173 break;
1174
1175 } while (++retries < 5);
1176
1177 if (retries >= 5)
1178 return -11;
1179#else
1180 (void)port;
1181 (void)slot;
1182#endif
1183
1184 return sceMcResSucceed;
1185}
1186
1187//--------------------------------------------------------------
1188int McWritePS1PDACard(int port, int slot, int page, void *buf) // Export #30
1189{
1190#if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
1191 register int i, retries;
1192 register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
1193 u8 *p;
1194
1195 //DPRINTF("McWritePS1PDACard port%d slot%d page %x\n", port, slot, page);
1196
1197 mcman_sio2packet_PS1PDA.regdata[0] = 0;
1198 mcman_sio2packet_PS1PDA.regdata[0] = (((port & 1) + 2) & 3) | 0x02288a40;
1199 mcman_sio2packet_PS1PDA.in_size = 138;
1200 mcman_sio2packet_PS1PDA.out_size = 138;
1201 mcman_sio2packet_PS1PDA.regdata[1] = 0;
1202
1203 for (i = 0; i < 20; i++) {
1204 if (mcdi->bad_block_list[i] == page)
1205 page += 36;
1206 }
1207
1208 mcman_sio2inbufs_PS1PDA[0] = 0x81;
1209 mcman_sio2inbufs_PS1PDA[1] = 0x57;
1210 mcman_sio2inbufs_PS1PDA[4] = (u8)(page >> 8);
1211 mcman_sio2inbufs_PS1PDA[5] = (u8)page;
1212
1213 p = (u8 *)buf;
1214 for (i = 0; i < 128; i++)
1215 mcman_sio2inbufs_PS1PDA[6 + i] = p[i];
1216
1217 mcman_sio2inbufs_PS1PDA[4 + 130] = mcman_calcEDC(&mcman_sio2inbufs_PS1PDA[4], 130);
1218
1219 retries = 0;
1220 do {
1221 mcman_timercount = (u32)(GetTimerCounter(timer_ID) - mcman_timercount);
1222
1223 u32 hi, lo;
1224 long_multiply(mcman_timercount, 0x3e0f83e1, &hi, &lo);
1225
1226 if (((u32)(hi >> 3) < (u32)mcman_timerthick))
1227 DelayThread(mcman_timerthick - (hi >> 3));
1228
1229 mcsio2_transfer(port, slot, &mcman_sio2packet_PS1PDA);
1230
1231 mcman_timercount = GetTimerCounter(timer_ID);
1232 mcman_timerthick = 20000;
1233
1234 if (((mcman_sio2packet_PS1PDA.stat6c & 0xf000) == 0x1000) \
1235 && (mcman_sio2outbufs_PS1PDA[2] == 0x5a) \
1236 && (mcman_sio2outbufs_PS1PDA[3] == 0x5d) \
1237 && (mcman_sio2outbufs_PS1PDA[137] == 0x47)) {
1238 break;
1239 }
1240 } while (++retries < 5);
1241
1242 if (retries >= 5)
1243 return sceMcResNoEntry;
1244
1245 if ((mcman_sio2outbufs_PS1PDA[1] != 0) && (mcman_sio2outbufs_PS1PDA[1] != 8))
1246 return sceMcResFullDevice;
1247#else
1248 (void)port;
1249 (void)slot;
1250 (void)page;
1251 (void)buf;
1252#endif
1253
1254 return sceMcResSucceed;
1255}
1256
1257//--------------------------------------------------------------
1258int McReadPS1PDACard(int port, int slot, int page, void *buf) // Export #29
1259{
1260#if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
1261 register int i, retries;
1262 register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
1263 u8 *p;
1264
1265 //DPRINTF("McReadPS1PDACard port%d slot%d page %x\n", port, slot, page);
1266
1267 mcman_sio2packet_PS1PDA.regdata[0] = 0;
1268 mcman_sio2packet_PS1PDA.regdata[0] = (((port & 1) + 2) & 3) | 0x02308c40;
1269 mcman_sio2packet_PS1PDA.in_size = 140;
1270 mcman_sio2packet_PS1PDA.out_size = 140;
1271 mcman_sio2packet_PS1PDA.regdata[1] = 0;
1272
1273 for (i = 0; i < 20; i++) {
1274 if (mcdi->bad_block_list[i] == page)
1275 page += 36;
1276 }
1277
1278 mcman_sio2inbufs_PS1PDA[0] = 0x81;
1279 mcman_sio2inbufs_PS1PDA[1] = 0x52;
1280 mcman_sio2inbufs_PS1PDA[4] = (u8)(page >> 8);
1281 mcman_sio2inbufs_PS1PDA[5] = (u8)page;
1282
1283 retries = 0;
1284 do {
1285 mcman_timercount = (u32)(GetTimerCounter(timer_ID) - mcman_timercount);
1286
1287 u32 hi, lo;
1288 long_multiply(mcman_timercount, 0x3e0f83e1, &hi, &lo);
1289
1290 if (((u32)(hi >> 3) < (u32)mcman_timerthick))
1291 DelayThread(mcman_timerthick - (hi >> 3));
1292
1293 mcsio2_transfer(port, slot, &mcman_sio2packet_PS1PDA);
1294
1295 mcman_timercount = GetTimerCounter(timer_ID);
1296 mcman_timerthick = 10000;
1297
1298 if (((mcman_sio2packet_PS1PDA.stat6c & 0xf000) == 0x1000) \
1299 && (mcman_sio2outbufs_PS1PDA[2] == 0x5a) \
1300 && (mcman_sio2outbufs_PS1PDA[3] == 0x5d) \
1301 && (mcman_sio2outbufs_PS1PDA[4] == 0x00) \
1302 && (mcman_sio2outbufs_PS1PDA[6] == 0x5c) \
1303 && (mcman_sio2outbufs_PS1PDA[7] == 0x5d) \
1304 && (mcman_sio2outbufs_PS1PDA[139] == 0x47)) {
1305
1306 if (mcman_sio2outbufs_PS1PDA[138] == (mcman_calcEDC(&mcman_sio2outbufs_PS1PDA[8], 130) & 0xff))
1307 break;
1308 }
1309 } while (++retries < 5);
1310
1311 if (retries >= 5)
1312 return sceMcResNoEntry;
1313
1314 p = (u8 *)buf;
1315 for (i = 0; i < 128; i++)
1316 p[i] = mcman_sio2outbufs_PS1PDA[10 + i];
1317
1318 if ((mcman_sio2outbufs_PS1PDA[1] != 0) && (mcman_sio2outbufs_PS1PDA[1] != 8))
1319 return sceMcResDeniedPermit;
1320#else
1321 (void)port;
1322 (void)slot;
1323 (void)page;
1324 (void)buf;
1325#endif
1326
1327 return sceMcResSucceed;
1328}
1329
1330
Definition tcpip.h:234
u32 count
start sector of fragmented bd/file