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 <fileio-common.h>
25 
26 #define D(fmt, args...) printf("(%s:%s:%i):" #fmt, __FILE__, __FUNCTION__, __LINE__, ##args)
27 
28 extern int _iop_reboot_count;
29 extern SifRpcClientData_t _fio_cd;
30 extern int _fio_init;
31 extern int _fio_block_mode;
32 extern int _fio_io_sema;
33 extern int _fio_completion_sema;
34 extern int _fio_recv_data[512];
35 extern int _fio_intr_data[32];
36 
37 void _fio_read_intr(struct _fio_read_data *);
38 void _fio_intr();
39 
40 #ifdef F___fio_internals
41 SifRpcClientData_t _fio_cd;
42 int _fio_recv_data[512] __attribute__((aligned(64)));
43 int _fio_intr_data[32] __attribute__((aligned(64)));
44 int _fio_init = 0;
45 int _fio_block_mode;
46 int _fio_io_sema = -1;
47 int _fio_completion_sema = -1;
48 #endif
49 
50 #ifdef F_fio_init
51 int 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  sceSifInitRpc(0);
67 
68  while (((res = sceSifBindRpc(&_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
98 void _fio_intr(void)
99 {
100  iSignalSema(_fio_completion_sema);
101 }
102 #endif
103 
104 #ifdef F_fio_sync
105 int 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
145 void fioSetBlockMode(int blocking)
146 {
147  _fio_block_mode = blocking;
148 }
149 #endif
150 
151 #ifdef F_fio_exit
152 void 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
168 int 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 = sceSifCallRpc(&_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 sceSifCallRpc 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
198 int 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 = sceSifCallRpc(&_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 sceSifCallRpc 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
230 void _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
247 int 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  sceSifWriteBackDCache(ptr, size);
265 
266  if ((res = sceSifCallRpc(&_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 sceSifCallRpc 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
281 int 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  sceSifWriteBackDCache((void *)ptr, size);
310 
311  if ((res = sceSifCallRpc(&_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 sceSifCallRpc 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
326 int 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 = sceSifCallRpc(&_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 sceSifCallRpc 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
356 int 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 = sceSifCallRpc(&_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 sceSifCallRpc 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
388 int 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 = sceSifCallRpc(&_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 sceSifCallRpc 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
421 int 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 = sceSifCallRpc(&_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 sceSifCallRpc 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
454 int 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 = sceSifCallRpc(&_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 sceSifCallRpc 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
487 int fioPutc(int fd, int c)
488 {
489  return fioWrite(fd, &c, 1);
490 }
491 #endif
492 
493 #ifdef F_fio_getc
494 int 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
504 int 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
531 int 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 = sceSifCallRpc(&_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 sceSifCallRpc 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
564 int 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 = sceSifCallRpc(&_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 sceSifCallRpc 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
596 int 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  sceSifWriteBackDCache(buf, sizeof(io_dirent_t));
612 
613  if ((res = sceSifCallRpc(&_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 sceSifCallRpc 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
628 int 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  sceSifWriteBackDCache(buf, sizeof(io_stat_t));
645 
646  if ((res = sceSifCallRpc(&_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 sceSifCallRpc 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
661 int 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 = sceSifCallRpc(&_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 sceSifCallRpc 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
692 int 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 = sceSifCallRpc(&_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 sceSifCallRpc fails.
714  SignalSema(_fio_completion_sema);
715  result = res;
716  }
717 
718  SignalSema(_fio_io_sema);
719 
720  return result;
721 }
722 #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
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
_iop_reboot_count
int _iop_reboot_count
tamtypes.h
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