PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
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
33IRX_ID("hdsk", APA_MODVER_MAJOR, APA_MODVER_MINOR);
34#endif
35
36static apa_device_t HddInfo[2] = {
37 {0, 0, 0, 3},
38 {0, 0, 0, 3},
39};
40
41static int hdskEventFlagID; // 0x000276c8
42static int hdskThreadID; // 0x000276cc
43static int hdskStopFlag;
44static int hdskStatus;
45static u32 hdskProgress;
46
47u8 IOBuffer[IOBUFFER_SIZE_SECTORS * 512];
48
49#define HDSK_MIN_PART_SIZE 0x00040000
50
51static 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
103static 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
128static 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
145static 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
161static 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
209static 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
249static 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
287static 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
332static 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
423static 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
452static 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.
483static 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
519static 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
583hdsk_thread_end:
584 hdskRemoveTmp(device);
585 SetEventFlag(hdskEventFlagID, 1);
586}
587
588static int HdskInit(iomanX_iop_device_t *device)
589{
590 (void)device;
591
592 return 0;
593}
594
595int BitmapUsed;
596u32 TotalCopied;
597struct hdskBitmap hdskBitmap[HDSK_BITMAP_SIZE];
598
599static 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
627static 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
676static 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
726IOMANX_RETURN_VALUE_IMPL(0);
727IOMANX_RETURN_VALUE_IMPL(EPERM);
728
729static 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
759static iomanX_iop_device_t HdskDevice = {
760 "hdsk",
761 IOP_DT_FSEXT | IOP_DT_FS,
762 1,
763 "HDSK",
764 &HdskDeviceOps};
765
766int 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}
s32 exists
Definition atad.h:29
u32 total_sectors
Definition atad.h:33
s32 has_packet
Definition atad.h:31
#define ENXIO
Definition errno.h:31
#define EINVAL
Definition errno.h:63
#define EIO
Definition errno.h:29
#define EPERM
Definition errno.h:21
#define APA_FLAG_SUB
Definition hdd-ioctl.h:51
#define IOP_DT_FSEXT
Definition iomanX.h:66
Definition hdck.c:76