mgh: fix for default HDD DMA mode, that wasn't correctly set
[open-ps2-loader.git] / modules / vmc / mcman / ps1mc_io.c
blobad57addd472fb1d0412baea6a094a6b54377850c
1 /*
2 Copyright 2009-2010, jimmikaelkael
3 Licenced under Academic Free License version 3.0
4 Review Open PS2 Loader README & LICENSE files for further details.
5 */
7 #include "mcman.h"
9 extern int sio2man_type;
11 //--------------------------------------------------------------
12 int mcman_format1(int port, int slot)
14 register int r, i;
15 register MCDevInfo *mcdi = &mcman_devinfos[port][slot];
17 #ifdef DEBUG
18 DPRINTF("mcman: mcman_format1 port%d slot%d\n", port, slot);
19 #endif
21 mcman_invhandles(port, slot);
23 for (i = 0; i < 56; i++) {
24 r = mcman_PS1pagetest(port, slot, i);
25 if (r == 0)
26 return sceMcResNoFormat;
27 if (r != 1)
28 return -41;
31 memset(mcman_PS1PDApagebuf, 0, 128);
33 *((u32 *)&mcman_PS1PDApagebuf) = 0xa0;
34 *((u16 *)&mcman_PS1PDApagebuf+4) = 0xffff;
36 mcman_PS1PDApagebuf[127] = mcman_calcEDC(mcman_PS1PDApagebuf, 127);
38 for (i = 1; i < 15; i++) {
39 r = McWritePS1PDACard(port, slot, i, mcman_PS1PDApagebuf);
40 if (r != sceMcResSucceed)
41 return -42;
44 memset(mcman_PS1PDApagebuf, 0, 128);
46 *((u32 *)&mcman_PS1PDApagebuf) = 0xffffffff;
48 for (i = 0; i < 20; i++) {
49 *((u32 *)&mcman_PS1PDApagebuf) = mcdi->bad_block_list[i];
50 mcman_PS1PDApagebuf[127] = mcman_calcEDC(mcman_PS1PDApagebuf, 127);
52 r = McWritePS1PDACard(port, slot, i + 16, mcman_PS1PDApagebuf);
53 if (r != sceMcResSucceed)
54 return -43;
57 mcman_wmemset(mcman_PS1PDApagebuf, 128, 0);
59 mcman_PS1PDApagebuf[0] = 0x4d;
60 mcman_PS1PDApagebuf[1] = 0x43;
61 mcman_PS1PDApagebuf[127] = 0x0e;
63 r = McWritePS1PDACard(port, slot, 0, mcman_PS1PDApagebuf);
64 if (r != sceMcResSucceed)
65 return -44;
67 mcdi->cardform = 1;
69 return sceMcResSucceed;
72 //--------------------------------------------------------------
73 int mcman_open1(int port, int slot, char *filename, int flags)
75 register int r, i, fd, cluster, temp;
76 register MC_FHANDLE *fh = (MC_FHANDLE *)&mcman_fdhandles[fd];
77 McFsEntryPS1 *fse; //sp18
78 McCacheEntry *mce;
79 char *p = (char *)filename;
81 #ifdef DEBUG
82 DPRINTF("mcman: mcman_open1 port%d slot%d filename %s flags %x\n", port, slot, filename, flags);
83 #endif
85 if ((flags & sceMcFileCreateFile) != 0)
86 flags |= sceMcFileAttrWriteable;
88 for (fd = 0; fd < MAX_FDHANDLES; fd++) {
89 fh = (MC_FHANDLE *)&mcman_fdhandles[fd];
90 if (fh->status == 0)
91 break;
94 if (fd == MAX_FDHANDLES)
95 return -7;
97 mcman_wmemset((void *)fh, sizeof (MC_FHANDLE), 0);
99 fh->port = port;
100 fh->slot = slot;
102 if (*p == '/')
103 p++;
105 if ((*p == 0) || ((*p == '.') && (p[1] == 0))) {
106 fh->filesize = 15;
107 fh->drdflag = 1;
108 fh->status = 1;
109 return fd;
112 r = mcman_getPS1direntry(port, slot, p, &fse, 1);
113 if ((fse->mode & 0xf0) == 0xa0)
114 r = -4;
116 fh->freeclink = r;
118 if (r >= 0) {
119 if (fse->field_7d == 1)
120 fh->filesize = fse->field_38;
121 else
122 fh->filesize = fse->length;
124 else
125 fh->filesize = 0;
127 fh->rdflag = flags & sceMcFileAttrReadable;
128 fh->wrflag = flags & sceMcFileAttrWriteable;
129 fh->unknown1 = 0;
131 if ((flags & sceMcFileCreateFile) == 0) {
132 if (r < 0)
133 return sceMcResNoEntry;
135 fh->status = 1;
136 return fd;
139 for (i = 0; i < MAX_FDHANDLES; i++) {
140 if ((mcman_fdhandles[i].status != 0) && \
141 (mcman_fdhandles[i].port == port) && (mcman_fdhandles[i].slot == slot) && \
142 (mcman_fdhandles[i].freeclink == r) && (fh->wrflag != 0))
143 return sceMcResDeniedPermit;
146 if (r >= 0) {
147 r = mcman_clearPS1direntry(port, slot, r, 0);
148 if (r != sceMcResSucceed)
149 return r;
152 cluster = -1;
153 for (i = 0; i < 15; i++) {
154 r = mcman_readdirentryPS1(port, slot, i, &fse);
155 if (r != sceMcResSucceed)
156 return r;
158 if ((fse->mode & 0xf0) == 0xa0) {
159 if (cluster < 0)
160 cluster = i;
162 if (fse->mode != 0xa0) {
164 mcman_wmemset((void *)fse, sizeof(McFsEntryPS1), 0);
165 fse->mode = 0xa0;
166 fse->linked_block = -1;
167 fse->edc = mcman_calcEDC((void *)fse, 127);
169 mce = mcman_get1stcacheEntp();
171 if ((i + 1) < 0)
172 temp = i + 8;
173 else
174 temp = i + 1;
176 mce->wr_flag |= 1 << ((i + 1) - ((temp >> 3) << 3));
181 r = mcman_flushmccache(port, slot);
182 if (r != sceMcResSucceed)
183 return r;
185 if (cluster < 0)
186 return sceMcResFullDevice;
188 r = mcman_readdirentryPS1(port, slot, cluster, &fse);
189 if (r != sceMcResSucceed)
190 return r;
192 mcman_wmemset((void *)fse, sizeof(McFsEntryPS1), 0);
194 fse->mode = 0x51;
195 fse->length = 0;
196 fse->linked_block = -1;
198 strncpy(fse->name, p, 20);
200 if ((flags & sceMcFileAttrPDAExec) != 0)
201 fse->field_7e = 1;
203 fse->edc = mcman_calcEDC((void *)fse, 127);
204 fh->freeclink = cluster;
206 mce = mcman_get1stcacheEntp();
208 if ((cluster + 1) < 0)
209 temp = cluster + 8;
210 else
211 temp = cluster + 1;
213 mce->wr_flag |= 1 << ((cluster + 1) - ((temp >> 3) << 3));
215 r = mcman_flushmccache(port, slot);
216 if (r != sceMcResSucceed)
217 return r;
219 fh->unknown2 = 1;
220 fh->status = 1;
222 return fd;
225 //--------------------------------------------------------------
226 int mcman_read1(int fd, void *buffer, int nbyte)
228 register int r, size, temp, rpos, offset, maxsize;
229 register MC_FHANDLE *fh = (MC_FHANDLE *)&mcman_fdhandles[fd];
230 McCacheEntry *mce;
231 u8 *p = (u8 *)buffer;
233 if (fh->position >= fh->filesize)
234 return 0;
236 if (nbyte >= (fh->filesize - fh->position))
237 nbyte = fh->filesize - fh->position;
239 rpos = 0;
240 if (nbyte) {
241 do {
242 if (fh->position < 0)
243 temp = fh->position + 0x3ff;
244 else
245 temp = fh->position;
247 offset = (fh->position - ((temp >> 10) << 10));
248 maxsize = MCMAN_CLUSTERSIZE - offset;
249 if (maxsize < nbyte)
250 size = maxsize;
251 else
252 size = nbyte;
254 r = mcman_fatRseekPS1(fd);
255 if (r < 0)
256 return r;
258 r = mcman_readclusterPS1(fh->port, fh->slot, r, &mce);
259 if (r != sceMcResSucceed)
260 return r;
262 memcpy(&p[rpos], (void *)(mce->cl_data + offset), size);
264 rpos += size;
265 nbyte -= size;
266 fh->position += size;
268 } while (nbyte);
271 return rpos;
274 //--------------------------------------------------------------
275 int mcman_write1(int fd, void *buffer, int nbyte)
277 register int r, size, temp, wpos, offset, maxsize;
278 register MC_FHANDLE *fh = (MC_FHANDLE *)&mcman_fdhandles[fd];
279 McCacheEntry *mce;
280 u8 *p = (u8 *)buffer;
282 if (nbyte) {
283 if (fh->unknown2 == 0) {
284 fh->unknown2 = 1;
285 r = mcman_close1(fd);
286 if (r != sceMcResSucceed)
287 return r;
288 r = mcman_flushmccache(fh->port, fh->slot);
289 if (r != sceMcResSucceed)
290 return r;
294 wpos = 0;
295 if (nbyte) {
297 do {
298 r = mcman_fatRseekPS1(fd);
300 if (r == sceMcResFullDevice) {
301 r = mcman_fatWseekPS1(fd);
302 if (r == sceMcResFullDevice)
303 return r;
304 if (r!= sceMcResSucceed)
305 return r;
307 r = mcman_fatRseekPS1(fd);
309 else {
310 if (r < 0)
311 return r;
314 r = mcman_readclusterPS1(fh->port, fh->slot, r, &mce);
315 if (r != sceMcResSucceed)
316 return r;
318 if (fh->position < 0)
319 temp = fh->position + 0x3ff;
320 else
321 temp = fh->position;
323 offset = fh->position - ((temp >> 10) << 10);
324 maxsize = MCMAN_CLUSTERSIZE - offset;
325 if (maxsize < nbyte)
326 size = maxsize;
327 else
328 size = nbyte;
330 memcpy((void *)(mce->cl_data + offset), &p[wpos], size);
332 mce->wr_flag = -1;
333 fh->position += size;
334 if (fh->position >= fh->filesize)
335 fh->filesize = fh->position;
337 nbyte -= size;
338 wpos += size;
340 } while (nbyte);
344 mcman_close1(fd);
346 return wpos;
349 //--------------------------------------------------------------
350 int mcman_dread1(int fd, fio_dirent_t *dirent)
352 register int r;
353 register MC_FHANDLE *fh = (MC_FHANDLE *)&mcman_fdhandles[fd];
354 McFsEntryPS1 *fse;
356 if (fh->position < fh->filesize) {
357 do {
358 r = mcman_readdirentryPS1(fh->port, fh->slot, fh->position, &fse);
359 if (r != sceMcResSucceed)
360 return r;
362 if (fse->mode == 0x51)
363 break;
365 } while (++fh->position < fh->filesize);
368 if (fh->position >= fh->filesize)
369 return 0;
371 fh->position++;
372 mcman_wmemset((void *)dirent, sizeof(fio_dirent_t), 0);
374 strncpy(dirent->name, fse->name, 20);
375 dirent->name[20] = 0;
377 dirent->stat.mode = 0x101f;
379 if (fse->field_7e == 1)
380 dirent->stat.mode = 0x181f;
382 if (fse->field_7d == 1) {
383 *((u32 *)&dirent->stat.ctime) = *((u32 *)&fse->created);
384 *((u32 *)&dirent->stat.ctime + 1) = *((u32 *)&fse->created + 1);
385 *((u32 *)&dirent->stat.mtime) = *((u32 *)&fse->modified);
386 *((u32 *)&dirent->stat.mtime + 1) = *((u32 *)&fse->modified + 1);
387 dirent->stat.size = fse->field_38;
388 dirent->stat.attr = fse->field_28;
390 else {
391 dirent->stat.size = fse->length;
394 return 1;
397 //--------------------------------------------------------------
398 int mcman_getstat1(int port, int slot, char *filename, fio_stat_t *stat)
400 register int r;
401 McFsEntryPS1 *fse;
403 #ifdef DEBUG
404 DPRINTF("mcman: mcman_getstat1 port%d slot%d filename %s\n", port, slot, filename);
405 #endif
407 r = mcman_getPS1direntry(port, slot, filename, &fse, 1);
409 if ((fse->mode & 0xf0) == 0xa0)
410 r = -4;
412 if (r < 0)
413 return sceMcResNoEntry;
415 mcman_wmemset(stat, sizeof(fio_stat_t), 0);
417 stat->mode = 0x1f;
419 if (fse->field_7d == 1) {
421 if ((fse->field_2c & sceMcFileAttrClosed) != 0)
422 stat->mode = 0x9f;
424 *((u32 *)&stat->ctime) = *((u32 *)&fse->created);
425 *((u32 *)&stat->ctime+1) = *((u32 *)&fse->created+1);
426 *((u32 *)&stat->mtime) = *((u32 *)&fse->modified);
427 *((u32 *)&stat->mtime+1) = *((u32 *)&fse->modified+1);
429 stat->size = fse->field_38;
430 stat->attr = fse->field_28;
432 return sceMcResSucceed;
435 stat->size = fse->length;
437 return sceMcResSucceed;
440 //--------------------------------------------------------------
441 int mcman_setinfo1(int port, int slot, char *filename, sceMcTblGetDir *info, int flags)
443 register int r, temp, ret;
444 McFsEntryPS1 *fse1, *fse2;
445 McCacheEntry *mce;
447 #ifdef DEBUG
448 DPRINTF("mcman: mcman_setinfo1 port%d slot%d filename %s flags %x\n", port, slot, filename, flags);
449 #endif
451 ret = 0;
452 if (sio2man_type == XSIO2MAN) {
453 if ((flags & sceMcFileAttrFile) != 0) {
454 r = mcman_getPS1direntry(port, slot, info->EntryName, &fse1, 1);
455 if (r < 0) {
456 if (r != sceMcResNoEntry) {
457 ret = r;
459 else {
460 if ((!strcmp(".", info->EntryName)) || (!strcmp("..", info->EntryName)) || (info->EntryName[0] == 0))
461 ret = sceMcResNoEntry;
467 r = mcman_getPS1direntry(port, slot, filename, &fse2, 1);
469 if ((fse2->mode & 0xf0) == 0)
470 r = sceMcResNoEntry;
472 if (r < 0)
473 return r;
475 if (sio2man_type == XSIO2MAN) {
476 if (ret != sceMcResSucceed)
477 return sceMcResNoEntry;
480 mce = mcman_get1stcacheEntp();
482 temp = r + 1;
483 if ((r + 1) < 0)
484 temp = r + 8;
486 mce->wr_flag |= 1 << ((r + 1) - ((temp >> 3) << 3));
488 if (sio2man_type == XSIO2MAN) {
489 fse2->field_7d = 0;
490 fse2->field_2c = 0;
491 flags &= -12;
493 else {
494 if(fse2->field_7d != 1) {
495 fse2->field_7d = 1;
496 fse2->field_38 = fse2->length;
500 if ((flags & sceMcFileAttrExecutable) != 0) {
501 if ((info->AttrFile & sceMcFileAttrPDAExec) != 0)
502 fse2->field_7e = 1;
503 else
504 fse2->field_7e = 0;
507 //Special fix clause for file managers (like uLaunchELF)
508 //This allows writing most entries that can be read by mcGetDir
509 //and without usual restrictions. This flags value should cause no conflict
510 //as Sony code never uses it, and the value is changed after its use here.
511 //This is primarily needed for PS2 MC backups, but must be implemented here
512 //too since the 'flags' argument may be used indiscriminately for both
513 if(flags == 0xFEED){
514 flags = sceMcFileAttrReadable|sceMcFileAttrWriteable;
515 //The changed flags value allows more entries to be copied below
518 if ((flags & sceMcFileAttrDupProhibit) != 0)
519 fse2->field_28 = info->Reserve2;
521 if ((flags & sceMcFileAttrReadable) != 0)
522 fse2->created = info->_Create;
524 if ((flags & sceMcFileAttrWriteable) != 0)
525 fse2->modified = info->_Modify;
527 if ((flags & sceMcFileAttrFile) != 0)
528 strncpy(fse2->name, info->EntryName, 20);
530 fse2->field_1e = 0;
532 r = mcman_flushmccache(port, slot);
534 return r;
537 //--------------------------------------------------------------
538 int mcman_getdir1(int port, int slot, char *dirname, int flags, int maxent, sceMcTblGetDir *info)
540 register int r, i;
541 char *p;
542 McFsEntryPS1 *fse;
544 #ifdef DEBUG
545 DPRINTF("mcman: mcman_getdir1 port%d slot%d dirname %s maxent %d flags %x\n", port, slot, dirname, maxent, flags);
546 #endif
548 flags &= 0xffff;
550 i = 0;
552 if (!flags) {
553 mcman_PS1curcluster = 0;
554 p = dirname;
555 do {
556 r = mcman_chrpos(p, '/');
557 if (r < 0)
558 break;
559 p += mcman_chrpos(p, '/') + 1;
560 } while (1);
562 strncpy(mcman_PS1curdir, p, 63);
566 if (maxent) {
567 do {
568 if (mcman_PS1curcluster >= 15)
569 break;
571 r = mcman_readdirentryPS1(port, slot, mcman_PS1curcluster, &fse);
572 if (r != sceMcResSucceed)
573 return r;
575 mcman_PS1curcluster++;
577 if (fse->mode != 0x51)
578 continue;
580 if (!mcman_checkdirpath(fse->name, mcman_PS1curdir))
581 continue;
583 memset((void *)info, 0, sizeof (sceMcTblGetDir));
585 info->AttrFile = 0x9417;
587 if (fse->field_7e == 1)
588 info->AttrFile = 0x9c17; //MC_ATTR_PDAEXEC set !!!
590 if (fse->field_7d == 1) {
591 if ((fse->field_2c & sceMcFileAttrClosed) != 0) {
592 info->AttrFile |= sceMcFileAttrClosed;
594 info->Reserve1 = fse->field_2e;
595 info->_Create = fse->created;
596 info->_Modify = fse->modified;
597 info->FileSizeByte = fse->field_38;
598 info->Reserve2 = fse->field_28;
600 else {
601 info->FileSizeByte = fse->length;
604 strncpy(info->EntryName, fse->name, 20);
605 info->EntryName[20] = 0;
607 i++;
608 info++;
609 maxent--;
610 } while (maxent);
612 return i;
615 //--------------------------------------------------------------
616 int mcman_delete1(int port, int slot, char *filename, int flags)
618 register int r;
619 McFsEntryPS1 *fse;
621 #ifdef DEBUG
622 DPRINTF("mcman: mcman_delete1 port%d slot%d filename %s flags %x\n", port, slot, filename, flags);
623 #endif
625 r = mcman_getPS1direntry(port, slot, filename, &fse, ((u32)flags < 1) ? 1 : 0);
626 if (r < 0)
627 return r;
629 r = mcman_clearPS1direntry(port, slot, r, flags);
631 return r;
634 //--------------------------------------------------------------
635 int mcman_close1(int fd)
637 register int r, temp;
638 MC_FHANDLE *fh = (MC_FHANDLE *)&mcman_fdhandles[fd];
639 McFsEntryPS1 *fse;
640 McCacheEntry *mce;
642 #ifdef DEBUG
643 DPRINTF("mcman: mcman_close1 fd %d\n", fd);
644 #endif
646 r = mcman_readdirentryPS1(fh->port, fh->slot, fh->freeclink, &fse);
647 if (r != sceMcResSucceed)
648 return -31;
650 mce = mcman_get1stcacheEntp();
652 if (fh->freeclink + 1 < 0)
653 temp = fh->freeclink + 8;
654 else
655 temp = fh->freeclink + 1;
657 mce->wr_flag |= 1 << ((fh->freeclink + 1) - ((temp >> 3) << 3));
659 if (fh->filesize == 0) {
660 fse->length = 0x2000;
662 else {
663 if ((fh->filesize - 1) < 0)
664 temp = (fh->filesize + 8190) >> 13;
665 else
666 temp = (fh->filesize - 1) >> 13;
668 temp++;
669 fse->length = temp << 13;
672 if (sio2man_type == XSIO2MAN) {
673 fse->field_7d = 0; // <--- To preserve for XMCMAN
674 fse->field_2c = 0; //
675 fse->field_38 = 0; //
676 memset((void *)&fse->created, 0, 8); //
677 memset((void *)&fse->modified, 0, 8); //
679 else { // MCMAN does as following
680 fse->field_7d = 1;
681 fse->field_38 = fh->filesize;
682 mcman_getmcrtime(&fse->modified);
685 fse->edc = mcman_calcEDC((void *)fse, 127);
687 r = mcman_flushmccache(fh->port, fh->slot);
688 if (r != sceMcResSucceed)
689 return r;
691 return sceMcResSucceed;
694 //--------------------------------------------------------------
695 int mcman_unformat1(int port, int slot)
697 register int r, i;
698 u32 *p;
700 #ifdef DEBUG
701 DPRINTF("mcman: mcman_unformat1 port%d slot%d\n", port, slot);
702 #endif
704 p = (u32 *)&mcman_PS1PDApagebuf;
705 for (i = 0; i < 32; i++)
706 *p++ = 0;
708 for (i = 0; i < 1024; i++) {
709 r = McWritePS1PDACard(port, slot, i, mcman_PS1PDApagebuf);
710 if (r != sceMcResSucceed)
711 return -41;
714 return r;
717 //--------------------------------------------------------------