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