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