PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
fileio.c
Go to the documentation of this file.
1/*
2# _____ ___ ____ ___ ____
3# ____| | ____| | | |____|
4# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5#-----------------------------------------------------------------------
6# (C)2001, Gustavo Scotti (gustavo@scotti.com)
7# (c) 2003 Marcus R. Brown (mrbrown@0xd6.org)
8# Licenced under Academic Free License version 2.0
9# Review ps2sdk README & LICENSE files for further details.
10*/
11
17#include <tamtypes.h>
18#include <ps2lib_err.h>
19#include <kernel.h>
20#include <sifrpc.h>
21#define NEWLIB_PORT_AWARE
22#include <fileio.h>
23#include <string.h>
24#include <fileio-common.h>
25
26#define D(fmt, args...) printf("(%s:%s:%i):" #fmt, __FILE__, __FUNCTION__, __LINE__, ##args)
27
28extern int _iop_reboot_count;
29extern SifRpcClientData_t _fio_cd;
30extern int _fio_init;
31extern int _fio_block_mode;
32extern int _fio_io_sema;
33extern int _fio_completion_sema;
34extern int _fio_recv_data[512];
35extern int _fio_intr_data[32];
36
37void _fio_read_intr(struct _fio_read_data *);
38void _fio_intr();
39
40#ifdef F___fio_internals
41SifRpcClientData_t _fio_cd;
42int _fio_recv_data[512] __attribute__((aligned(64)));
43int _fio_intr_data[32] __attribute__((aligned(64)));
44int _fio_init = 0;
45int _fio_block_mode;
46int _fio_io_sema = -1;
47int _fio_completion_sema = -1;
48#endif
49
50#ifdef F_fio_init
51int fioInit(void)
52{
53 int res;
54 ee_sema_t sema;
55 static int _rb_count = 0;
56
57 if (_rb_count != _iop_reboot_count) {
58 _rb_count = _iop_reboot_count;
59
60 fioExit();
61 }
62
63 if (_fio_init)
64 return 0;
65
66 SifInitRpc(0);
67
68 while (((res = SifBindRpc(&_fio_cd, 0x80000001, 0)) >= 0) &&
69 (_fio_cd.server == NULL))
70 nopdelay();
71
72 if (res < 0)
73 return res;
74
75 sema.init_count = 1;
76 sema.max_count = 1;
77 sema.option = 0;
78 _fio_completion_sema = CreateSema(&sema);
79 if (_fio_completion_sema < 0)
80 return -E_LIB_SEMA_CREATE;
81
82 // Unofficial: create a locking semaphore to prevent a thread from overwriting another thread's return status.
83 sema.init_count = 1;
84 sema.max_count = 1;
85 sema.option = 0;
86 _fio_io_sema = CreateSema(&sema);
87 if (_fio_io_sema < 0)
88 return -E_LIB_SEMA_CREATE;
89
90 _fio_init = 1;
91 _fio_block_mode = FIO_WAIT;
92
93 return 0;
94}
95#endif
96
97#ifdef F__fio_intr
98void _fio_intr(void)
99{
100 iSignalSema(_fio_completion_sema);
101}
102#endif
103
104#ifdef F_fio_sync
105int fioSync(int mode, int *retVal)
106{
107 int res;
108
109 if ((res = fioInit()) < 0)
110 return res;
111
112 if (_fio_block_mode != FIO_NOWAIT)
113 return -E_LIB_UNSUPPORTED;
114
115 switch (mode) {
116 case FIO_WAIT:
117
118 WaitSema(_fio_completion_sema);
119 SignalSema(_fio_completion_sema);
120
121 if (retVal != NULL)
122 *retVal = *(int *)UNCACHED_SEG(&_fio_recv_data[0]);
123
124 return FIO_COMPLETE;
125
126 case FIO_NOWAIT:
127
128 if (PollSema(_fio_completion_sema) < 0)
129 return FIO_INCOMPLETE;
130
131 SignalSema(_fio_completion_sema);
132
133 if (retVal != NULL)
134 *retVal = *(int *)UNCACHED_SEG(&_fio_recv_data[0]);
135
136 return FIO_COMPLETE;
137
138 default:
139 return -E_LIB_UNSUPPORTED;
140 }
141}
142#endif
143
144#ifdef F_fio_setblockmode
145void fioSetBlockMode(int blocking)
146{
147 _fio_block_mode = blocking;
148}
149#endif
150
151#ifdef F_fio_exit
152void fioExit(void)
153{
154 if (_fio_init) {
155 _fio_init = 0;
156 memset(&_fio_cd, 0, sizeof _fio_cd);
157 if (_fio_completion_sema >= 0) {
158 DeleteSema(_fio_completion_sema);
159 }
160 if (_fio_io_sema >= 0) {
161 DeleteSema(_fio_io_sema);
162 }
163 }
164}
165#endif
166
167#ifdef F_fio_open
168int fioOpen(const char *name, int mode)
169{
170 struct _fio_open_arg arg;
171 int res, result;
172
173 if ((res = fioInit()) < 0)
174 return res;
175
176 WaitSema(_fio_io_sema);
177 WaitSema(_fio_completion_sema);
178
179 arg.mode = mode;
180 strncpy(arg.name, name, FIO_PATH_MAX - 1);
181 arg.name[FIO_PATH_MAX - 1] = 0;
182
183 if ((res = SifCallRpc(&_fio_cd, FIO_F_OPEN, _fio_block_mode, &arg, sizeof arg,
184 _fio_recv_data, 4, (void *)_fio_intr, NULL)) >= 0) {
185 result = (_fio_block_mode == FIO_NOWAIT) ? 0 : _fio_recv_data[0];
186 } else { // Signal semaphore to avoid a deadlock if SifCallRpc fails.
187 SignalSema(_fio_completion_sema);
188 result = res;
189 }
190
191 SignalSema(_fio_io_sema);
192
193 return result;
194}
195#endif
196
197#ifdef F_fio_close
198int fioClose(int fd)
199{
200 union
201 {
202 int fd;
203 int result;
204 } arg;
205 int res, result;
206
207 if ((res = fioInit()) < 0)
208 return res;
209
210 WaitSema(_fio_io_sema);
211 WaitSema(_fio_completion_sema);
212
213 arg.fd = fd;
214
215 if ((res = SifCallRpc(&_fio_cd, FIO_F_CLOSE, 0, &arg, 4, &arg, 4,
216 (void *)_fio_intr, NULL)) >= 0) {
217 result = arg.result;
218 } else { // Signal semaphore to avoid a deadlock if SifCallRpc fails.
219 SignalSema(_fio_completion_sema);
220 result = res;
221 }
222
223 SignalSema(_fio_io_sema);
224
225 return result;
226}
227#endif
228
229#ifdef F__fio_read_intr
230void _fio_read_intr(struct _fio_read_data *data)
231{
232 struct _fio_read_data *uncached = UNCACHED_SEG(data);
233
234 if (uncached->size1 && uncached->dest1) {
235 memcpy(uncached->dest1, uncached->buf1, uncached->size1);
236 }
237
238 if (uncached->size2 && uncached->dest2) {
239 memcpy(uncached->dest2, uncached->buf2, uncached->size2);
240 }
241
242 iSignalSema(_fio_completion_sema);
243}
244#endif
245
246#ifdef F_fio_read
247int fioRead(int fd, void *ptr, int size)
248{
249 struct _fio_read_arg arg;
250 int res, result;
251
252 if ((res = fioInit()) < 0)
253 return res;
254
255 WaitSema(_fio_io_sema);
256 WaitSema(_fio_completion_sema);
257
258 arg.fd = fd;
259 arg.ptr = ptr;
260 arg.size = size;
261 arg.read_data = (struct _fio_read_data *)_fio_intr_data;
262
263 if (!IS_UNCACHED_SEG(ptr))
264 SifWriteBackDCache(ptr, size);
265
266 if ((res = SifCallRpc(&_fio_cd, FIO_F_READ, _fio_block_mode, &arg, sizeof arg,
267 _fio_recv_data, 4, (void *)_fio_read_intr, _fio_intr_data)) >= 0) {
268 result = (_fio_block_mode == FIO_NOWAIT) ? 0 : _fio_recv_data[0];
269 } else { // Signal semaphore to avoid a deadlock if SifCallRpc fails.
270 SignalSema(_fio_completion_sema);
271 result = res;
272 }
273
274 SignalSema(_fio_io_sema);
275
276 return result;
277}
278#endif
279
280#ifdef F_fio_write
281int fioWrite(int fd, const void *ptr, int size)
282{
283 struct _fio_write_arg arg;
284 int mis, res, result;
285
286 if ((res = fioInit()) < 0)
287 return res;
288
289 WaitSema(_fio_io_sema);
290 WaitSema(_fio_completion_sema);
291
292 arg.fd = fd;
293 arg.ptr = ptr;
294 arg.size = size;
295
296 /* Copy the unaligned (16-byte) portion into the argument */
297 mis = 0;
298 if ((u32)ptr & 0xf) {
299 mis = 16 - ((u32)ptr & 0xf);
300 if (mis > size)
301 mis = size;
302 }
303 arg.mis = mis;
304
305 if (mis)
306 memcpy(arg.aligned, ptr, mis);
307
308 if (!IS_UNCACHED_SEG(ptr))
309 SifWriteBackDCache((void *)ptr, size);
310
311 if ((res = SifCallRpc(&_fio_cd, FIO_F_WRITE, _fio_block_mode, &arg, sizeof arg,
312 _fio_recv_data, 4, (void *)_fio_intr, NULL)) >= 0) {
313 result = (_fio_block_mode == FIO_NOWAIT) ? 0 : _fio_recv_data[0];
314 } else { // Signal semaphore to avoid a deadlock if SifCallRpc fails.
315 SignalSema(_fio_completion_sema);
316 result = res;
317 }
318
319 SignalSema(_fio_io_sema);
320
321 return result;
322}
323#endif
324
325#ifdef F_fio_lseek
326int fioLseek(int fd, int offset, int whence)
327{
328 struct _fio_lseek_arg arg;
329 int res, result;
330
331 if ((res = fioInit()) < 0)
332 return res;
333
334 WaitSema(_fio_io_sema);
335 WaitSema(_fio_completion_sema);
336
337 arg.p.fd = fd;
338 arg.offset = offset;
339 arg.whence = whence;
340
341 if ((res = SifCallRpc(&_fio_cd, FIO_F_LSEEK, 0, &arg, sizeof arg,
342 &arg, 4, (void *)_fio_intr, NULL)) >= 0) {
343 result = arg.p.result;
344 } else { // Signal semaphore to avoid a deadlock if SifCallRpc fails.
345 SignalSema(_fio_completion_sema);
346 result = res;
347 }
348
349 SignalSema(_fio_io_sema);
350
351 return result;
352}
353#endif
354
355#ifdef F_fio_ioctl
356int fioIoctl(int fd, int request, void *data)
357{
358 struct _fio_ioctl_arg arg;
359 int res, result;
360
361 if ((res = fioInit()) < 0)
362 return res;
363
364 WaitSema(_fio_io_sema);
365 WaitSema(_fio_completion_sema);
366
367 arg.p.fd = fd;
368 arg.request = request;
369
370 if (data != NULL)
371 memcpy(arg.data, data, 1024);
372
373 if ((res = SifCallRpc(&_fio_cd, FIO_F_IOCTL, 0, &arg, sizeof arg,
374 &arg, 4, (void *)_fio_intr, NULL)) >= 0) {
375 result = arg.p.result;
376 } else { // Signal semaphore to avoid a deadlock if SifCallRpc fails.
377 SignalSema(_fio_completion_sema);
378 result = res;
379 }
380
381 SignalSema(_fio_io_sema);
382
383 return result;
384}
385#endif
386
387#ifdef F_fio_remove
388int fioRemove(const char *name)
389{
390 union
391 {
392 char path[FIO_PATH_MAX];
393 int result;
394 } arg;
395 int res, result;
396
397 if ((res = fioInit()) < 0)
398 return res;
399
400 WaitSema(_fio_io_sema);
401 WaitSema(_fio_completion_sema);
402
403 strncpy(arg.path, name, FIO_PATH_MAX - 1);
404 arg.path[FIO_PATH_MAX - 1] = 0;
405
406 if ((res = SifCallRpc(&_fio_cd, FIO_F_REMOVE, 0, &arg, sizeof arg,
407 &arg, 4, (void *)_fio_intr, NULL)) >= 0) {
408 result = arg.result;
409 } else { // Signal semaphore to avoid a deadlock if SifCallRpc fails.
410 SignalSema(_fio_completion_sema);
411 result = res;
412 }
413
414 SignalSema(_fio_io_sema);
415
416 return result;
417}
418#endif
419
420#ifdef F_fio_mkdir
421int fioMkdir(const char *path)
422{
423 union
424 {
425 char path[FIO_PATH_MAX];
426 int result;
427 } arg;
428 int res, result;
429
430 if ((res = fioInit()) < 0)
431 return res;
432
433 WaitSema(_fio_io_sema);
434 WaitSema(_fio_completion_sema);
435
436 strncpy(arg.path, path, FIO_PATH_MAX - 1);
437 arg.path[FIO_PATH_MAX - 1] = 0;
438
439 if ((res = SifCallRpc(&_fio_cd, FIO_F_MKDIR, 0, &arg, sizeof arg,
440 &arg, 4, (void *)_fio_intr, NULL)) >= 0) {
441 result = arg.result;
442 } else { // Signal semaphore to avoid a deadlock if SifCallRpc fails.
443 SignalSema(_fio_completion_sema);
444 result = res;
445 }
446
447 SignalSema(_fio_io_sema);
448
449 return result;
450}
451#endif
452
453#ifdef F_fio_rmdir
454int fioRmdir(const char *dirname)
455{
456 union
457 {
458 char path[FIO_PATH_MAX];
459 int result;
460 } arg;
461 int res, result;
462
463 if ((res = fioInit()) < 0)
464 return res;
465
466 WaitSema(_fio_io_sema);
467 WaitSema(_fio_completion_sema);
468
469 strncpy(arg.path, dirname, FIO_PATH_MAX - 1);
470 arg.path[FIO_PATH_MAX - 1] = 0;
471
472 if ((res = SifCallRpc(&_fio_cd, FIO_F_RMDIR, 0, &arg, sizeof arg,
473 &arg, 4, (void *)_fio_intr, NULL)) >= 0) {
474 result = arg.result;
475 } else { // Signal semaphore to avoid a deadlock if SifCallRpc fails.
476 SignalSema(_fio_completion_sema);
477 result = res;
478 }
479
480 SignalSema(_fio_io_sema);
481
482 return result;
483}
484#endif
485
486#ifdef F_fio_putc
487int fioPutc(int fd, int c)
488{
489 return fioWrite(fd, &c, 1);
490}
491#endif
492
493#ifdef F_fio_getc
494int fioGetc(int fd)
495{
496 int c;
497
498 fioRead(fd, &c, 1);
499 return c;
500}
501#endif
502
503#ifdef F_fio_gets
504int fioGets(int fd, char *buff, int n)
505{
506 // Rather than doing a slow byte-at-a-time read
507 // read upto the max langth, then re-position file afterwards
508 int read, i;
509
510 read = fioRead(fd, buff, n);
511
512 for (i = 0; i < (read - 1); i++) {
513 switch (buff[i]) {
514 case '\n':
515 fioLseek(fd, (i + 1) - read, SEEK_CUR);
516 buff[i] = 0; // terminate after newline
517 return i;
518
519 case 0:
520 fioLseek(fd, i - read, SEEK_CUR);
521 return i;
522 }
523 }
524
525 // if we reached here, then we havent found the end of a string
526 return i;
527}
528#endif
529
530#ifdef F_fio_dopen
531int fioDopen(const char *name)
532{
533 union
534 {
535 char name[FIO_PATH_MAX];
536 int result;
537 } arg;
538 int res, result;
539
540 if ((res = fioInit()) < 0)
541 return res;
542
543 WaitSema(_fio_io_sema);
544 WaitSema(_fio_completion_sema);
545
546 strncpy(arg.name, name, FIO_PATH_MAX - 1);
547 arg.name[FIO_PATH_MAX - 1] = 0;
548
549 if ((res = SifCallRpc(&_fio_cd, FIO_F_DOPEN, 0, &arg, sizeof arg,
550 &arg, 4, (void *)_fio_intr, NULL)) >= 0) {
551 result = arg.result;
552 } else { // Signal semaphore to avoid a deadlock if SifCallRpc fails.
553 SignalSema(_fio_completion_sema);
554 result = res;
555 }
556
557 SignalSema(_fio_io_sema);
558
559 return result;
560}
561#endif
562
563#ifdef F_fio_dclose
564int fioDclose(int fd)
565{
566 union
567 {
568 int fd;
569 int result;
570 } arg;
571 int res, result;
572
573 if ((res = fioInit()) < 0)
574 return res;
575
576 WaitSema(_fio_io_sema);
577 WaitSema(_fio_completion_sema);
578
579 arg.fd = fd;
580
581 if ((res = SifCallRpc(&_fio_cd, FIO_F_DCLOSE, 0, &arg, sizeof arg,
582 &arg, 4, (void *)_fio_intr, NULL)) >= 0) {
583 result = arg.result;
584 } else { // Signal semaphore to avoid a deadlock if SifCallRpc fails.
585 SignalSema(_fio_completion_sema);
586 result = res;
587 }
588
589 SignalSema(_fio_io_sema);
590
591 return result;
592}
593#endif
594
595#ifdef F_fio_dread
596int fioDread(int fd, io_dirent_t *buf)
597{
598 struct _fio_dread_arg arg;
599 int res, result;
600
601 if ((res = fioInit()) < 0)
602 return res;
603
604 WaitSema(_fio_io_sema);
605 WaitSema(_fio_completion_sema);
606
607 arg.p.fd = fd;
608 arg.buf = buf;
609
610 if (!IS_UNCACHED_SEG(buf))
611 SifWriteBackDCache(buf, sizeof(io_dirent_t));
612
613 if ((res = SifCallRpc(&_fio_cd, FIO_F_DREAD, 0, &arg, sizeof arg,
614 &arg, 4, (void *)_fio_intr, NULL)) >= 0) {
615 result = arg.p.result;
616 } else { // Signal semaphore to avoid a deadlock if SifCallRpc fails.
617 SignalSema(_fio_completion_sema);
618 result = res;
619 }
620
621 SignalSema(_fio_io_sema);
622
623 return result;
624}
625#endif
626
627#ifdef F_fio_getstat
628int fioGetstat(const char *name, io_stat_t *buf)
629{
630 struct _fio_getstat_arg arg;
631 int res, result;
632
633 if ((res = fioInit()) < 0)
634 return res;
635
636 WaitSema(_fio_io_sema);
637 WaitSema(_fio_completion_sema);
638
639 arg.p.buf = buf;
640 strncpy(arg.name, name, FIO_PATH_MAX - 1);
641 arg.name[FIO_PATH_MAX - 1] = 0;
642
643 if (!IS_UNCACHED_SEG(buf))
644 SifWriteBackDCache(buf, sizeof(io_stat_t));
645
646 if ((res = SifCallRpc(&_fio_cd, FIO_F_GETSTAT, 0, &arg, sizeof arg,
647 &arg, 4, (void *)_fio_intr, NULL)) >= 0) {
648 result = arg.p.result;
649 } else { // Signal semaphore to avoid a deadlock if SifCallRpc fails.
650 SignalSema(_fio_completion_sema);
651 result = res;
652 }
653
654 SignalSema(_fio_io_sema);
655
656 return result;
657}
658#endif
659
660#ifdef F_fio_chstat
661int fioChstat(const char *name, io_stat_t *buf, u32 cbit)
662{
663 struct _fio_chstat_arg arg;
664 int res, result;
665
666 if ((res = fioInit()) < 0)
667 return res;
668
669 WaitSema(_fio_io_sema);
670 WaitSema(_fio_completion_sema);
671
672 arg.p.cbit = cbit;
673 memcpy(&arg.stat, buf, sizeof(io_stat_t));
674 strncpy(arg.name, name, FIO_PATH_MAX - 1);
675 arg.name[FIO_PATH_MAX - 1] = 0;
676
677 if ((res = SifCallRpc(&_fio_cd, FIO_F_CHSTAT, 0, &arg, sizeof arg,
678 &arg, 4, (void *)_fio_intr, NULL)) >= 0) {
679 result = arg.p.result;
680 } else { // Signal semaphore to avoid a deadlock if SifCallRpc fails.
681 SignalSema(_fio_completion_sema);
682 result = res;
683 }
684
685 SignalSema(_fio_io_sema);
686
687 return result;
688}
689#endif
690
691#ifdef F_fio_format
692int fioFormat(const char *name)
693{
694 union
695 {
696 char path[FIO_PATH_MAX];
697 int result;
698 } arg;
699 int res, result;
700
701 if ((res = fioInit()) < 0)
702 return res;
703
704 WaitSema(_fio_io_sema);
705 WaitSema(_fio_completion_sema);
706
707 strncpy(arg.path, name, FIO_PATH_MAX - 1);
708 arg.path[FIO_PATH_MAX - 1] = 0;
709
710 if ((res = SifCallRpc(&_fio_cd, FIO_F_FORMAT, 0, &arg, sizeof arg,
711 &arg, 4, (void *)_fio_intr, NULL)) >= 0) {
712 result = arg.result;
713 } else { // Signal semaphore to avoid a deadlock if SifCallRpc fails.
714 SignalSema(_fio_completion_sema);
715 result = res;
716 }
717
718 SignalSema(_fio_io_sema);
719
720 return result;
721}
722#endif
@ E_LIB_SEMA_CREATE
Definition ps2lib_err.h:70
@ E_LIB_UNSUPPORTED
Definition ps2lib_err.h:76