PS2SDK
PS2 Homebrew Libraries
hdsk.c
1 /*
2 # _____ ___ ____ ___ ____
3 # ____| | ____| | | |____|
4 # | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5 #-----------------------------------------------------------------------
6 # Copyright 2001-2004, ps2dev - http://www.ps2dev.org
7 # Licenced under Academic Free License version 2.0
8 # Review ps2sdk README & LICENSE files for further details.
9 */
10 
11 #include <atad.h>
12 #include <errno.h>
13 #include <iomanX.h>
14 #include <loadcore.h>
15 #include <kerr.h>
16 #include <stdio.h>
17 #include <sysclib.h>
18 #include <thbase.h>
19 #include <thevent.h>
20 #include <irx.h>
21 #include <hdd-ioctl.h>
22 
23 #include "libapa.h"
24 #include "hdsk-devctl.h"
25 #include "hdsk.h"
26 #include "sim.h"
27 #include "misc_hdsk.h"
28 #ifdef HDSK_SUPPORT_HDLFS
29 #include "hdl.h"
30 #endif
31 
32 #ifdef _IOP
33 IRX_ID("hdsk", APA_MODVER_MAJOR, APA_MODVER_MINOR);
34 #endif
35 
36 static apa_device_t HddInfo[2] = {
37  {0, 0, 0, 3},
38  {0, 0, 0, 3},
39 };
40 
41 static int hdskEventFlagID; // 0x000276c8
42 static int hdskThreadID; // 0x000276cc
43 static int hdskStopFlag;
44 static int hdskStatus;
45 static u32 hdskProgress;
46 
47 u8 IOBuffer[IOBUFFER_SIZE_SECTORS * 512];
48 
49 #define HDSK_MIN_PART_SIZE 0x00040000
50 
51 static int hdskRemoveTmp(int device)
52 {
53  apa_cache_t *clink;
54  char partition[APA_IDMAX];
55  u32 start;
56  int result;
57 
58  clink = apaCacheGetHeader(device, 0, APA_IO_MODE_READ, &result);
59  memset(partition, 0, sizeof(partition));
60  strcpy(partition, "_tmp");
61 
62  while (clink != NULL) {
63  if (!(clink->header->flags & APA_FLAG_SUB)) {
64  if (!memcmp(clink->header->id, partition, sizeof(clink->header->id))) {
65  break;
66  }
67  }
68 
69  clink = apaGetNextHeader(clink, &result);
70  }
71 
72  if (result == 0 && clink != NULL) {
73  int sub;
74 
75  APA_PRINTF("remove _tmp\n");
76  sub = clink->header->nsub;
77  clink->header->nsub = 0;
78 
79  clink->flags |= APA_CACHE_FLAG_DIRTY;
80  start = clink->header->start + 0x2000;
81  apaCacheFlushAllDirty(device);
82 
83  for (--sub; sub != -1; sub--) {
84  apa_cache_t *clinkSub;
85 
86  if ((clinkSub = apaCacheGetHeader(device, clink->header->subs[sub].start, APA_IO_MODE_READ, &result)) != NULL) {
87  if ((result = apaDelete(clinkSub)) != 0) {
88  break;
89  }
90  }
91  }
92 
93  apaDelete(clink);
94  clink = apaCacheAlloc();
95  memset(clink->header, 0, sizeof(apa_header_t));
96  sceAtaDmaTransfer(device, clink->header, start, 2, ATA_DIR_WRITE);
97  apaCacheFree(clink);
98  }
99 
100  return result;
101 }
102 
103 static apa_cache_t *hdskFindEmptyPartition(int device, u32 size)
104 {
105  int result;
106  apa_cache_t *clink;
107 
108  clink = apaCacheGetHeader(device, 0, APA_IO_MODE_READ, &result);
109  while (clink != NULL) {
110  if (clink->header->length != size || clink->header->type != APA_TYPE_FREE) {
111  clink = apaGetNextHeader(clink, &result);
112  if (hdskStopFlag) {
113  apaCacheFree(clink);
114  return NULL;
115  }
116  } else {
117  break;
118  }
119  }
120 
121  if (clink != NULL) {
122  APA_PRINTF("found empty partition at %08lx, size %08lx.\n", clink->header->start, clink->header->length);
123  }
124 
125  return clink;
126 }
127 
128 static int hdskIsPartitionOfSize(int device, u32 sector, u32 size)
129 {
130  apa_cache_t *clink;
131  int result, returnValue;
132 
133  returnValue = 1;
134  if ((clink = apaCacheGetHeader(device, sector, APA_IO_MODE_READ, &result)) != NULL) {
135  if (clink->header->type == APA_TYPE_FREE) {
136  returnValue = 0 < (clink->header->length ^ size);
137  }
138 
139  apaCacheFree(clink);
140  }
141 
142  return returnValue;
143 }
144 
145 static u32 hdskGetPartitionPrev(int device, u32 size, u32 start)
146 {
147  int result;
148  apa_cache_t *clink;
149 
150  (void)size;
151  (void)start;
152 
153  if ((clink = apaCacheGetHeader(device, 0, APA_IO_MODE_READ, &result)) != NULL) {
154  apaCacheFree(clink);
155  return (clink->header->prev);
156  }
157 
158  return 0;
159 }
160 
161 static apa_cache_t *hdskFindLastUsedPartition(int device, u32 size, u32 start, int mode)
162 {
163  int result;
164  apa_cache_t *clink;
165  u32 previous, DoubleSize, partition;
166 
167  clink = NULL;
168  previous = hdskGetPartitionPrev(device, size, start);
169  DoubleSize = size * 2;
170  while (start < previous) {
171  if ((clink = apaCacheGetHeader(device, previous, APA_IO_MODE_READ, &result)) != NULL) {
172  if (clink->header->length == size && clink->header->type != APA_TYPE_FREE) {
173  if (mode) {
174  if (clink->header->start % DoubleSize == 0) {
175  if ((partition = clink->header->next) == 0) {
176  break;
177  }
178  } else {
179  partition = clink->header->prev;
180  }
181 
182  if (!hdskIsPartitionOfSize(device, partition, size)) {
183  break;
184  }
185  } else {
186  break;
187  }
188  }
189  } else {
190  break;
191  }
192 
193  previous = clink->header->prev;
194  apaCacheFree(clink);
195 
196  if (hdskStopFlag) {
197  break;
198  }
199  clink = NULL;
200  }
201 
202  if (clink != NULL) {
203  APA_PRINTF("found last used partition at %08lx, size %08lx.\n", clink->header->start, clink->header->length);
204  }
205 
206  return clink;
207 }
208 
209 static int hdskFindPartitionOfSize(int device, apa_header_t *start, u32 MinSize, int mode)
210 {
211  u32 next;
212  u32 BlockSize;
213  int result;
214  apa_cache_t *clink;
215 
216  next = start->next;
217  BlockSize = start->length;
218  while (BlockSize < MinSize && next != 0) {
219  if ((clink = apaCacheGetHeader(device, next, APA_IO_MODE_READ, &result)) != NULL) {
220  if (clink->header->type == APA_TYPE_FREE) {
221  break;
222  }
223 
224  next = clink->header->next;
225  BlockSize += clink->header->length;
226  apaCacheFree(clink);
227  } else {
228  break;
229  }
230  }
231 
232  if (BlockSize == MinSize) {
233  if (mode != 0) {
234  if (start->start % (MinSize * 2) != 0) {
235  return ((hdskIsPartitionOfSize(device, start->prev, MinSize) != 0) ? 0 : 1);
236  } else {
237  if (next != 0) {
238  return ((hdskIsPartitionOfSize(device, next, MinSize) != 0) ? 0 : 1);
239  }
240  }
241  } else {
242  return 1;
243  }
244  }
245 
246  return 0;
247 }
248 
249 static apa_cache_t *hdskFindLastUsedBlock(int device, u32 MinSize, u32 start, int mode)
250 {
251  int result;
252  apa_cache_t *last;
253  u32 NextStart, sector;
254 
255  last = NULL;
256  sector = start;
257  if ((NextStart = hdskGetPartitionPrev(device, MinSize, start)) != 0) {
258  while (sector < NextStart) {
259  if ((last = apaCacheGetHeader(device, NextStart, 0, &result)) != NULL) {
260  if (last->header->start % MinSize != 0) {
261  if (last->header->length < MinSize && last->header->type != APA_TYPE_FREE) {
262  if (hdskFindPartitionOfSize(device, last->header, MinSize, mode) != 0) {
263  break;
264  }
265  }
266  }
267 
268  // 0x000006bc
269  NextStart = last->header->prev;
270  apaCacheFree(last);
271  if (hdskStopFlag) {
272  break;
273  }
274  last = NULL;
275  } else {
276  return last;
277  }
278  }
279  }
280  if (last != NULL) {
281  APA_PRINTF("found last used block of partitions at %08lx, size %08lx.\n", last->header->start, last->header->length);
282  }
283 
284  return last;
285 }
286 
287 static int CopyPartition(int device, apa_header_t *dest, apa_header_t *start)
288 {
289  u32 blocks, i;
290  int result;
291 
292  blocks = dest->length / IOBUFFER_SIZE_SECTORS;
293  APA_PRINTF("copy start...");
294 
295  // Copy data, but skip the APA header.
296  result = sceAtaDmaTransfer(device, IOBuffer, start->start + 2, IOBUFFER_SIZE_SECTORS - 2, ATA_DIR_READ) == 0 ? 0 : -EIO;
297 
298  if (result == 0) {
299  result = sceAtaDmaTransfer(device, IOBuffer, dest->start + 2, IOBUFFER_SIZE_SECTORS - 2, ATA_DIR_WRITE) == 0 ? 0 : -EIO;
300 
301  if (result == 0) {
302  hdskProgress += IOBUFFER_SIZE_SECTORS;
303 
304  for (i = 1; i < blocks; i++) {
305  result = sceAtaDmaTransfer(device, IOBuffer, start->start + i * IOBUFFER_SIZE_SECTORS, IOBUFFER_SIZE_SECTORS, ATA_DIR_READ) == 0 ? 0 : -EIO;
306 
307  if (result == 0) {
308  result = sceAtaDmaTransfer(device, IOBuffer, dest->start + i * IOBUFFER_SIZE_SECTORS, IOBUFFER_SIZE_SECTORS, ATA_DIR_WRITE) == 0 ? 0 : -EIO;
309 
310  if (result == 0) {
311  hdskProgress += IOBUFFER_SIZE_SECTORS;
312  if (hdskStopFlag) {
313  break;
314  }
315  } else {
316  APA_PRINTF("error: write failed at %08lx.\n", dest->start + i * IOBUFFER_SIZE_SECTORS);
317  break;
318  }
319  } else {
320  APA_PRINTF("error: read failed at %08lx.\n", start->start + i * IOBUFFER_SIZE_SECTORS);
321  break;
322  }
323  }
324 
325  printf("done\n");
326  }
327  }
328 
329  return result;
330 }
331 
332 static int SwapPartition(int device, apa_cache_t *dest, apa_cache_t *start)
333 {
334  apa_cache_t *clink[64];
335  int result, i;
336  u32 StartSector, next, prev;
337 
338  StartSector = dest->header->start;
339  next = dest->header->next;
340  prev = dest->header->prev;
341 
342  APA_PRINTF("swap %s partition start...", (start->header->flags & APA_FLAG_SUB) ? "sub" : "main");
343 
344  memcpy(dest->header, start->header, sizeof(apa_header_t));
345  dest->header->start = StartSector;
346  dest->header->next = next;
347  dest->header->prev = prev;
348  StartSector = start->header->start;
349  next = start->header->next;
350  prev = start->header->prev;
351  memset(start->header, 0, sizeof(apa_header_t));
352 
353  start->header->magic = APA_MAGIC;
354  start->header->start = StartSector;
355  start->header->next = next;
356  start->header->prev = prev;
357  start->header->length = dest->header->length;
358  start->header->modver = APA_MODVER;
359  start->header->type = dest->header->type;
360  strcpy(start->header->id, "_tmp");
361 
362  memset(clink, 0, sizeof(clink));
363  if (dest->header->flags & APA_FLAG_SUB) {
364  if ((clink[0] = apaCacheGetHeader(device, dest->header->main, APA_IO_MODE_READ, &result)) != NULL) {
365  for (i = 0; (u32)i < clink[0]->header->nsub; i++) {
366  if (start->header->start == clink[0]->header->subs[i].start) {
367  clink[0]->header->subs[i].start = dest->header->start;
368  clink[0]->flags |= APA_CACHE_FLAG_DIRTY;
369 #ifdef HDSK_SUPPORT_HDLFS
370  if (dest->header->type == APA_TYPE_HDLFS) {
371  hdlUpdateGameSliceInfo(device, dest->header->main, i, start->header->start, dest->header->start);
372  }
373 #endif
374  break;
375  }
376  }
377 
378  if ((u32)i == clink[0]->header->nsub) {
379  apaCacheFree(clink[0]);
380  return -1;
381  }
382  } else {
383  return result;
384  }
385  } else {
386  // 0x00000944
387  for (i = 0; (u32)i < dest->header->nsub; i++) {
388  if ((clink[i] = apaCacheGetHeader(device, dest->header->subs[i].start, APA_IO_MODE_READ, &result)) == NULL) {
389  for (--i; i >= 0; i--) {
390  apaCacheFree(clink[i]);
391  }
392 
393  return result;
394  }
395  }
396 
397  for (i = 0; (u32)i < dest->header->nsub; i++) {
398  clink[i]->header->main = dest->header->start;
399  clink[i]->flags |= APA_CACHE_FLAG_DIRTY;
400  }
401 
402 #ifdef HDSK_SUPPORT_HDLFS
403  if (dest->header->type == APA_TYPE_HDLFS) {
404  hdlUpdateGameSliceInfo(device, dest->header->start, 0, start->header->start, dest->header->start);
405  }
406 #endif
407  }
408 
409  dest->flags |= APA_CACHE_FLAG_DIRTY;
410  start->flags |= APA_CACHE_FLAG_DIRTY;
411  apaCacheFlushAllDirty(device);
412  for (i = 0; i < 64; i++) {
413  if (clink[i] != NULL) {
414  apaCacheFree(clink[i]);
415  }
416  }
417 
418  printf("done\n");
419 
420  return result;
421 }
422 
423 static int MovePartition(int device, apa_cache_t *dest, apa_cache_t *start)
424 {
425  int result;
426 
427  APA_PRINTF("MovePartition: %08lx to %08lx. sector count = %08lx.\n", start->header->start, dest->header->start, start->header->length);
428 
429  if (dest->header->type != APA_TYPE_FREE) {
430  APA_PRINTF("error: destination is not empty.\n");
431  return -1;
432  }
433 
434  if (dest->header->length != start->header->length) {
435  APA_PRINTF("error: source and destination size are not same.\n");
436  return -1;
437  }
438 
439  if ((result = hdskRemoveTmp(device)) == 0) {
440  if ((result = CopyPartition(device, dest->header, start->header)) == 0) {
441  if (hdskStopFlag == 0) {
442  SwapPartition(device, dest, start);
443  }
444  }
445  }
446 
447  APA_PRINTF("MovePartition: done\n");
448 
449  return result;
450 }
451 
452 static int SplitEmptyPartition(int device, apa_cache_t *partition, u32 length)
453 {
454  apa_cache_t *clink;
455  int result;
456 
457  result = 0;
458 
459  APA_PRINTF("split empty partition.\n");
460 
461  while (partition->header->length != length) {
462  apa_cache_t *empty;
463 
464  if ((empty = apaCacheGetHeader(device, partition->header->next, APA_IO_MODE_READ, &result)) != NULL) {
465  partition->header->length /= 2;
466  clink = apaRemovePartition(device, partition->header->start + partition->header->length, partition->header->next, partition->header->start, partition->header->length);
467 
468  partition->header->next = clink->header->start;
469  partition->flags |= APA_CACHE_FLAG_DIRTY;
470 
471  empty->header->prev = clink->header->start;
472  empty->flags |= APA_CACHE_FLAG_DIRTY;
473  apaCacheFlushAllDirty(device);
474  apaCacheFree(clink);
475  apaCacheFree(empty);
476  }
477  }
478 
479  return result;
480 }
481 
482 // Move a group of partitions.
483 static int MovePartitionsBlock(int device, apa_cache_t *dest, apa_cache_t *start)
484 {
485  u32 remaining;
486  int result, stat;
487 
488  remaining = dest->header->length;
489  APA_PRINTF("MovePartitionsBlock: %08lx to %08lx. sector count = %08lx.\n", start->header->start, dest->header->start, dest->header->length);
490 
491  while (1) {
492  if ((result = SplitEmptyPartition(device, dest, start->header->length)) == 0) {
493  if ((result = MovePartition(device, dest, start)) == 0) {
494  remaining -= dest->header->length;
495  if (hdskStopFlag == 0 && remaining != 0) {
496  // Stop if there are no more partitions to copy (either to or from).
497  if ((dest = apaGetNextHeader(dest, &stat)) == NULL || (start = apaGetNextHeader(start, &stat)) == NULL) {
498  break;
499  }
500  } else {
501  break;
502  }
503  } else {
504  break;
505  }
506  } else {
507  break;
508  }
509  }
510 
511  apaCacheFree(dest);
512  apaCacheFree(start);
513 
514  APA_PRINTF("MovePartitionsBlock: done\n");
515 
516  return result;
517 }
518 
519 static void HdskThread(int device)
520 {
521  u32 PartSize;
522  apa_cache_t *clink, *clink2;
523 
524  hdskProgress = 0;
525  hdskStatus = 0;
526  hdskStopFlag = 0;
527 
528  if ((hdskStatus = hdskRemoveTmp(device)) >= 0) {
529  for (PartSize = HDSK_MIN_PART_SIZE; PartSize < HddInfo[device].partitionMaxSize; PartSize *= 2) {
530  while ((hdskStatus = hdskRemoveTmp(device)) >= 0) {
531  if ((clink = hdskFindEmptyPartition(device, PartSize)) != NULL) {
532  if ((clink2 = hdskFindLastUsedPartition(device, PartSize, clink->header->start, 1)) == NULL) {
533  if ((HDSK_MIN_PART_SIZE < PartSize) && (clink2 = hdskFindLastUsedBlock(device, PartSize, clink->header->start, 1)) != NULL) {
534  goto move_partition_block;
535  }
536 
537  // 0x0000110c
538  if ((clink2 = hdskFindLastUsedPartition(device, PartSize, clink->header->start, 0)) == NULL) {
539  // 0x00001160
540  if (HDSK_MIN_PART_SIZE < PartSize) {
541  if ((clink2 = hdskFindLastUsedBlock(device, PartSize, clink->header->start, 0)) != NULL) {
542  goto move_partition_block;
543  }
544  }
545 
546  APA_PRINTF("there is no copyable partition/partitions block.\n");
547  apaCacheFree(clink);
548  break;
549  } else {
550  goto move_partition;
551  }
552 
553  move_partition_block:
554  // 0x00001190
555  if ((hdskStatus = MovePartitionsBlock(device, clink, clink2)) != 0) {
556  goto hdsk_thread_end;
557  }
558  } else {
559  move_partition:
560  // 0x00001120
561  hdskStatus = MovePartition(device, clink, clink2);
562  // apaCacheFree(clink); // BUGBUG: SONY original frees clink here, and again below ("unused cache returned"). However, clink must be freed here before the user terminates the defrag operation.
563  apaCacheFree(clink2);
564  if (hdskStatus != 0) {
565  apaCacheFree(clink); // Move this here. See comment above.
566  goto hdsk_thread_end;
567  }
568  }
569 
570  // 0x000011d4
571  apaCacheFree(clink);
572  } else
573  break;
574  }
575 
576  // 0x000011f4
577  if (hdskStatus != 0 || hdskStopFlag != 0) {
578  break;
579  }
580  }
581  }
582 
583 hdsk_thread_end:
584  hdskRemoveTmp(device);
585  SetEventFlag(hdskEventFlagID, 1);
586 }
587 
588 static int HdskInit(iomanX_iop_device_t *device)
589 {
590  (void)device;
591 
592  return 0;
593 }
594 
595 int BitmapUsed;
596 u32 TotalCopied;
597 struct hdskBitmap hdskBitmap[HDSK_BITMAP_SIZE];
598 
599 static int hdskBitmapInit(int device)
600 {
601  apa_cache_t *clink;
602  int result;
603 
604  clink = apaCacheGetHeader(device, 0, APA_IO_MODE_READ, &result);
605  memset(hdskBitmap, 0, sizeof(hdskBitmap));
606 
607  hdskBitmap[0].next = hdskBitmap;
608  hdskBitmap[0].prev = hdskBitmap;
609 
610  for (BitmapUsed = 0; clink != NULL;) {
611  struct hdskBitmap *pBitmap;
612 
613  pBitmap = &hdskBitmap[BitmapUsed + 1];
614  pBitmap->start = clink->header->start;
615  pBitmap->length = clink->header->length;
616  pBitmap->type = clink->header->type;
617 
618  apaCacheLink((apa_cache_t *)hdskBitmap[0].prev, (apa_cache_t *)pBitmap);
619 
620  BitmapUsed++;
621  clink = apaGetNextHeader(clink, &result);
622  }
623 
624  return result;
625 }
626 
627 static int hdskGetStat(int device, struct hdskStat *buf, apa_device_t *deviceInfo)
628 {
629  int result;
630 
631  u32 PartSize;
632 
633  TotalCopied = 0;
634 
635  PartSize = HDSK_MIN_PART_SIZE;
636  if ((result = hdskBitmapInit(device)) == 0) {
637  apa_device_t *pDeviceInfo;
638 
639  hdskSimGetFreeSectors(device, buf, deviceInfo);
640 
641  for (pDeviceInfo = &deviceInfo[device]; PartSize < pDeviceInfo->partitionMaxSize; PartSize *= 2) {
642  int IsValidPartSize;
643  struct hdskBitmap *pPartBitmap;
644 
645  IsValidPartSize = HDSK_MIN_PART_SIZE < PartSize;
646 
647  while ((pPartBitmap = hdskSimFindEmptyPartition(PartSize)) != NULL) {
648  struct hdskBitmap *pSelEmptyPartBM;
649 
650  if (((pSelEmptyPartBM = hdskSimFindLastUsedPartition(PartSize, pPartBitmap->start, 1)) == NULL) &&
651  (!IsValidPartSize || (pSelEmptyPartBM = hdskSimFindLastUsedBlock(PartSize, pPartBitmap->start, 1)) == NULL) &&
652  ((pSelEmptyPartBM = hdskSimFindLastUsedPartition(PartSize, pPartBitmap->start, 0)) == NULL)) {
653  if (IsValidPartSize && (pSelEmptyPartBM = hdskSimFindLastUsedBlock(PartSize, pPartBitmap->start, 0)) != NULL) {
654  APA_PRINTF("found last used block of partitions at %08lx, size %08lx.\n", pSelEmptyPartBM->start, pSelEmptyPartBM->length);
655  hdskSimMovePartitionsBlock(pPartBitmap, pSelEmptyPartBM);
656  } else {
657  APA_PRINTF("there is no copyable partition/partitions block.\n");
658  break;
659  }
660  } else {
661  APA_PRINTF("found last used partition at %08lx, size %08lx.\n", pSelEmptyPartBM->start, pSelEmptyPartBM->length);
662  hdskSimMovePartition(pPartBitmap, pSelEmptyPartBM);
663  }
664  }
665  }
666 
667  // 0x00004368
668  hdskSimGetFreeSectors(device, buf, deviceInfo);
669  printf("copy total %08lx sectors\n", TotalCopied);
670  buf->total = TotalCopied;
671  }
672 
673  return result;
674 }
675 
676 static int HdskDevctl(iomanX_iop_file_t *fd, const char *name, int cmd, void *arg, unsigned int arglen, void *buf, unsigned int buflen)
677 {
678  u32 bits;
679  int result;
680 
681  (void)name;
682  (void)arg;
683  (void)arglen;
684  (void)buflen;
685 
686  if (HddInfo[fd->unit].status != 0) {
687  return -ENXIO;
688  }
689 
690  switch (cmd) {
691  case HDSK_DEVCTL_GET_FREE:
692  result = apaGetFreeSectors(fd->unit, buf, HddInfo);
693  break;
694  case HDSK_DEVCTL_GET_HDD_STAT:
695  if ((result = hdskRemoveTmp(fd->unit)) == 0)
696  result = hdskGetStat(fd->unit, buf, HddInfo);
697  break;
698  case HDSK_DEVCTL_START:
699  result = StartThread(hdskThreadID, (void *)(uiptr)fd->unit);
700  break;
701  case HDSK_DEVCTL_WAIT:
702  result = WaitEventFlag(hdskEventFlagID, 1, WEF_CLEAR | WEF_OR, &bits);
703  break;
704  case HDSK_DEVCTL_POLL:
705  result = PollEventFlag(hdskEventFlagID, 1, WEF_CLEAR | WEF_OR, &bits);
706  if (result == KE_EVF_COND)
707  result = 1;
708  break;
709  case HDSK_DEVCTL_GET_STATUS:
710  result = hdskStatus;
711  break;
712  case HDSK_DEVCTL_STOP:
713  hdskStopFlag = 1;
714  result = -EINVAL;
715  break;
716  case HDSK_DEVCTL_GET_PROGRESS:
717  result = (int)hdskProgress;
718  break;
719  default:
720  result = -EINVAL;
721  }
722 
723  return result;
724 }
725 
726 IOMANX_RETURN_VALUE_IMPL(0);
727 IOMANX_RETURN_VALUE_IMPL(EPERM);
728 
729 static iomanX_iop_device_ops_t HdskDeviceOps = {
730  &HdskInit, // init
731  IOMANX_RETURN_VALUE(0), // deinit
732  IOMANX_RETURN_VALUE(EPERM), // format
733  IOMANX_RETURN_VALUE(EPERM), // open
734  IOMANX_RETURN_VALUE(EPERM), // close
735  IOMANX_RETURN_VALUE(EPERM), // read
736  IOMANX_RETURN_VALUE(EPERM), // write
737  IOMANX_RETURN_VALUE(EPERM), // lseek
738  IOMANX_RETURN_VALUE(EPERM), // ioctl
739  IOMANX_RETURN_VALUE(EPERM), // remove
740  IOMANX_RETURN_VALUE(EPERM), // mkdir
741  IOMANX_RETURN_VALUE(EPERM), // rmdir
742  IOMANX_RETURN_VALUE(EPERM), // dopen
743  IOMANX_RETURN_VALUE(EPERM), // dclose
744  IOMANX_RETURN_VALUE(EPERM), // dread
745  IOMANX_RETURN_VALUE(EPERM), // getstat
746  IOMANX_RETURN_VALUE(EPERM), // chstat
747  IOMANX_RETURN_VALUE(EPERM), // rename
748  IOMANX_RETURN_VALUE(EPERM), // chdir
749  IOMANX_RETURN_VALUE(EPERM), // sync
750  IOMANX_RETURN_VALUE(EPERM), // mount
751  IOMANX_RETURN_VALUE(EPERM), // umount
752  IOMANX_RETURN_VALUE_S64(EPERM), // lseek64
753  &HdskDevctl, // devctl
754  IOMANX_RETURN_VALUE(EPERM), // symlink
755  IOMANX_RETURN_VALUE(EPERM), // readlink
756  IOMANX_RETURN_VALUE(EPERM), // ioctl2
757 };
758 
759 static iomanX_iop_device_t HdskDevice = {
760  "hdsk",
761  IOP_DT_FSEXT | IOP_DT_FS,
762  1,
763  "HDSK",
764  &HdskDeviceOps};
765 
766 int APA_ENTRYPOINT(int argc, char **argv)
767 {
768  apa_ps2time_t time;
769  ata_devinfo_t *pDevInfo;
770  int i;
771 
772  (void)argc;
773  (void)argv;
774 
775  if (apaGetTime(&time) != 0) {
776  APA_PRINTF("error: could not get date\n");
777  return MODULE_NO_RESIDENT_END;
778  }
779 
780  APA_PRINTF("%02d:%02d:%02d %02d/%02d/%d\n", time.hour, time.min, time.sec, time.month, time.day, time.year);
781 
782  for (i = 0; i < 2; i++) {
783  if ((pDevInfo = sceAtaInit(i)) == NULL) {
784  APA_PRINTF("error: ata initialization failed.\n");
785  return MODULE_NO_RESIDENT_END;
786  }
787 
788  if (pDevInfo->exists && !pDevInfo->has_packet) {
789  HddInfo[i].status--;
790  HddInfo[i].totalLBA = pDevInfo->total_sectors;
791 
792  HddInfo[i].partitionMaxSize = apaGetPartitionMax(pDevInfo->total_sectors);
793  if (HdskUnlockHdd(i) == 0) {
794  HddInfo[i].status--;
795  }
796 
797  APA_PRINTF("disk%d: 0x%08lx sectors, max 0x%08lx\n", i, HddInfo[i].totalLBA, HddInfo[i].partitionMaxSize);
798  }
799  }
800 
801  // 0x00001440
802  apaCacheInit(128);
803  for (i = 0; i < 2; i++) {
804  if (HddInfo[i].status < 2) {
805  if (apaJournalRestore(i) != 0) {
806  return MODULE_NO_RESIDENT_END;
807  }
808 
809  if (apaGetFormat(i, &HddInfo[i].format)) {
810  HddInfo[i].status--;
811  }
812  }
813  }
814 
815  if ((hdskEventFlagID = HdskCreateEventFlag()) < 0) {
816  return MODULE_NO_RESIDENT_END;
817  }
818 
819  if ((hdskThreadID = HdskCreateThread((void *)&HdskThread, 0x2080)) < 0) {
820  return MODULE_NO_RESIDENT_END;
821  }
822 
823  iomanX_DelDrv(HdskDevice.name);
824  if (iomanX_AddDrv(&HdskDevice) == 0) {
825  APA_PRINTF("driver start.\n");
826  return MODULE_RESIDENT_END;
827  }
828 
829  return MODULE_NO_RESIDENT_END;
830 }
iomanX.h
apa_header_t
Definition: libapa.h:62
IOP_DT_FSEXT
#define IOP_DT_FSEXT
Definition: iomanX.h:66
thbase.h
_ata_devinfo::has_packet
s32 has_packet
Definition: xatapi.c:43
_ata_devinfo
Definition: xatapi.c:40
_iomanX_iop_file
Definition: iomanX.h:70
sysclib.h
EPERM
#define EPERM
Definition: errno.h:21
atad.h
ENXIO
#define ENXIO
Definition: errno.h:31
sapa_cache
Definition: libapa.h:120
EIO
#define EIO
Definition: errno.h:29
loadcore.h
apa_ps2time_t
Definition: libapa.h:42
partition
Definition: part_driver.h:20
hdd-ioctl.h
APA_FLAG_SUB
#define APA_FLAG_SUB
Definition: hdd-ioctl.h:51
_ata_devinfo::exists
s32 exists
Definition: xatapi.c:42
irx.h
_iomanX_iop_device_ops
Definition: iomanX.h:95
hdskStat
Definition: hdsk-devctl.h:25
_iomanX_iop_device
Definition: iomanX.h:81
stdio.h
hdskBitmap
Definition: fssk.h:22
HddInfo
Definition: hdck.c:75
_ata_devinfo::total_sectors
u32 total_sectors
Definition: xatapi.c:44
apa_device_t
Definition: libapa.h:209
EINVAL
#define EINVAL
Definition: errno.h:63
thevent.h
errno.h
kerr.h