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