PS2SDK
PS2 Homebrew Libraries
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
15 static flash_info_t dev9_flash_info;
16 #endif
17 
18 #if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
19 static sio2_transfer_data_t mcman_sio2packet; // buffer for mcman sio2 packet
20 static u8 mcman_wdmabufs[0x0b * 0x90]; // buffer array for SIO2 DMA I/O (write)
21 static u8 mcman_rdmabufs[0x0b * 0x90]; // not sure here for size, buffer array for SIO2 DMA I/O (read)
22 
23 static sio2_transfer_data_t mcman_sio2packet_PS1PDA;
24 static u8 mcman_sio2inbufs_PS1PDA[0x90];
25 u8 mcman_sio2outbufs_PS1PDA[0x90];
26 
27 static u32 mcman_timercount;
28 static 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.
33 static 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
55 static void (*sio2packet_add_func)(int port, int slot, int cmd, u8 *buf, int pos);
56 static void sio2packet_add_wdma_u32(int port, int slot, int cmd, u8 *buf, int pos);
57 static void sio2packet_add_pagedata_out(int port, int slot, int cmd, u8 *buf, int pos);
58 static void sio2packet_add_pagedata_in(int port, int slot, int cmd, u8 *buf, int pos);
59 static void sio2packet_add_ecc_in(int port, int slot, int cmd, u8 *buf, int pos);
60 static void sio2packet_add_ecc_out(int port, int slot, int cmd, u8 *buf, int pos);
61 static void sio2packet_add_wdma_5a(int port, int slot, int cmd, u8 *buf, int pos);
62 static void sio2packet_add_wdma_00(int port, int slot, int cmd, u8 *buf, int pos);
63 static void sio2packet_add_wdma_u8(int port, int slot, int cmd, u8 *buf, int pos);
64 static 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
67 static 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 //--------------------------------------------------------------
87 void 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 
131 static 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 
147 static 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 
161 static 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 
180 static 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 
204 static 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 
224 static 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 
238 static 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 
252 static 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 
264 static 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 //--------------------------------------------------------------
276 int 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 //--------------------------------------------------------------
328 void 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 //--------------------------------------------------------------
367 void mcman_deinitPS2com(void)
368 {
369 #if !defined(BUILDING_XFROMMAN) && !defined(BUILDING_VMCMAN)
370  SecrSetMcCommandHandler(0);
371  SecrSetMcDevIDHandler(0);
372 #endif
373 }
374 
375 //--------------------------------------------------------------
376 void 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 //--------------------------------------------------------------
397 void 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 //--------------------------------------------------------------
404 int 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 //--------------------------------------------------------------
417 int 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 //--------------------------------------------------------------
457 int 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 //--------------------------------------------------------------
553 int 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 //--------------------------------------------------------------
655 int 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 //--------------------------------------------------------------
750 int 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 //--------------------------------------------------------------
807 int 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 //--------------------------------------------------------------
844 int 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 //--------------------------------------------------------------
902 int 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 //--------------------------------------------------------------
1018 int 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 //--------------------------------------------------------------
1077 int 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 //--------------------------------------------------------------
1152 int 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 //--------------------------------------------------------------
1188 int 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 //--------------------------------------------------------------
1258 int 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 
iop_sema_t
Definition: thsemap.h:38
count
u32 count
start sector of fragmented bd/file
Definition: usbhdfsd-common.h:3
flash_info_t
Definition: fls.h:20
sio2_transfer_data_t
Definition: sio2man.h:33
pbuf
Definition: tcpip.h:229
MCDevInfo
Definition: mcman-internal.h:295
mcman.h