PS2SDK
PS2 Homebrew Libraries
ioman.c
Go to the documentation of this file.
1 /*
2 # _____ ___ ____ ___ ____
3 # ____| | ____| | | |____|
4 # | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5 #-----------------------------------------------------------------------
6 # Copyright (c) 2003 Marcus R. Brown <mrbrown@0xd6.org>
7 # Copyright (c) 2004 adresd <adresd_ps2dev@yahoo.com>
8 # Licenced under Academic Free License version 2.0
9 # Review ps2sdk README & LICENSE files for further details.
10 */
11 
17 #include "types.h"
18 #ifdef _IOP
19 #include "sysmem.h"
20 #include "loadcore.h"
21 #endif
22 #include "ioman_mod.h"
23 #ifdef _IOP
24 #include "sysclib.h"
25 #else
26 #include <string.h>
27 #define index strchr
28 #endif
29 #include "stdarg.h"
30 #include "intrman.h"
31 
32 #define MODNAME "ioman"
33 #ifdef _IOP
34 IRX_ID("IO/File_Manager", 1, 1);
35 #endif
36 
37 #include "errno.h"
38 
39 #include <ioman.h>
40 
41 #define MAX_DEVICES 16
42 #define MAX_FILES 16
43 
44 static iop_io_device_t *dev_list[MAX_DEVICES];
45 iop_io_file_t file_table[MAX_FILES];
46 
47 static int should_print_known_devices = 1;
48 
49 #define isnum(c) ((c) >= '0' && (c) <= '9')
50 
51 #ifdef _IOP
52 extern struct irx_export_table _exp_ioman;
53 #endif
54 
55 IOMAN_RETURN_VALUE_IMPL(0);
56 
57 iop_io_device_ops_t tty_dev_operations = {
58  IOMAN_RETURN_VALUE(0), // init
59  IOMAN_RETURN_VALUE(0), // deinit
60  IOMAN_RETURN_VALUE(0), // format
61  IOMAN_RETURN_VALUE(0), // open
62  IOMAN_RETURN_VALUE(0), // close
63  IOMAN_RETURN_VALUE(0), // read
64  IOMAN_RETURN_VALUE(0), // write
65  IOMAN_RETURN_VALUE(0), // lseek
66  IOMAN_RETURN_VALUE(0), // ioctl
67  IOMAN_RETURN_VALUE(0), // remove
68  IOMAN_RETURN_VALUE(0), // mkdir
69  IOMAN_RETURN_VALUE(0), // rmdir
70  IOMAN_RETURN_VALUE(0), // dopen
71  IOMAN_RETURN_VALUE(0), // dclose
72  IOMAN_RETURN_VALUE(0), // dread
73  IOMAN_RETURN_VALUE(0), // getstat
74  IOMAN_RETURN_VALUE(0), // chstat
75 };
76 
77 iop_io_device_t tty_device = {
78  "tty",
79  IOP_DT_CHAR,
80  1,
81  "CONSOLE",
82  &tty_dev_operations,
83 };
84 
85 static int add_tty_device(void)
86 {
87  return io_AddDrv(&tty_device);
88 }
89 
90 static int open_tty_handles(void)
91 {
92  int result;
93 
94  io_close(0);
95  io_close(1);
96  result = io_open("tty00:", 3);
97  if (result == 0)
98  {
99  return io_open("tty00:", 2);
100  }
101  return result;
102 }
103 
104 static int setup_tty_device(int should_not_add_tty_device)
105 {
106  int result;
107 
108  result = io_DelDrv("tty");
109  if (should_not_add_tty_device == 0)
110  {
111  add_tty_device();
112  return open_tty_handles();
113  }
114  return result;
115 }
116 
117 static int print_abort_error_io(const char *str1, const char *str2)
118 {
119  return Kprintf("ioabort exit:%s %s\n", str1, str2);
120 }
121 
122 #if 0
123 // Unused code.
124 static int print_unsupported_operation(void)
125 {
126  {
127  const char *unsupported_operation_str = "io request for unsupported operation\r\n";
128  io_write(1, unsupported_operation_str, strlen(unsupported_operation_str));
129  }
130  return -1;
131 }
132 #endif
133 
134 int _start(int argc, char *argv[])
135 {
136  (void)argc;
137  (void)argv;
138 
139 #ifdef _IOP
140  if(RegisterLibraryEntries(&_exp_ioman) != 0)
141  {
142  return MODULE_NO_RESIDENT_END;
143  }
144 #endif
145 
146  memset(dev_list, 0, sizeof(dev_list));
147  memset(file_table, 0, sizeof(file_table));
148 
149  setup_tty_device(0);
150 
151  return MODULE_RESIDENT_END;
152 }
153 
154 int io_AddDrv(iop_io_device_t *device)
155 {
156  int i;
157 
158  for (i = 0; i < MAX_DEVICES; i++)
159  {
160  if (dev_list[i] == NULL)
161  break;
162  }
163 
164  if (i >= MAX_DEVICES)
165  {
166  return(-1);
167  }
168 
169  dev_list[i] = device;
170 
171 #ifdef _IOP
172  FlushIcache();
173 #endif
174 
175  if (device->ops->io_init(device) < 0)
176  {
177  dev_list[i] = NULL;
178  return(-1);
179  }
180 
181  should_print_known_devices = 1;
182 
183  return(0);
184 }
185 
186 int io_DelDrv(const char *name)
187 {
188  int i;
189 
190  for (i = 0; i < MAX_DEVICES; i++) {
191  if (dev_list[i] != NULL && !strcmp(name, dev_list[i]->name)) {
192  dev_list[i]->ops->io_deinit(dev_list[i]);
193  dev_list[i] = NULL;
194  return 0;
195  }
196  }
197 
198  return -1;
199 }
200 
201 static void print_known_devices(void)
202 {
203  if (should_print_known_devices)
204  {
205  int i;
206 
207  Kprintf("Known devices are ");
208  for (i = 0; i < MAX_DEVICES; i++)
209  {
210  if (dev_list[i] != NULL && dev_list[i]->name != NULL)
211  {
212  Kprintf(" %s:(%s) ", dev_list[i]->name, dev_list[i]->desc);
213  }
214  }
215  Kprintf("\n");
216  }
217  should_print_known_devices = 0;
218 }
219 
220 
221 static char * find_iop_device(const char *dev, int *unit, iop_io_device_t **device)
222 {
223  char canon[32];
224  char *filename, *tail, *d = (char *)dev;
225  int i, len;
226 
227  while (*d == ' ')
228  d += 1;
229 
230  if ((tail = index(d, ':')) == NULL)
231  return (char *)-1;
232 
233  len = (int)(tail - d);
234  strncpy(canon, d, len);
235  canon[len] = '\0';
236 
237  /* This is the name passed to the device op. */
238  filename = d + len + 1;
239 
240  /* Search backward for the unit number. */
241  while (isnum(canon[len - 1]))
242  len -= 1;
243  if (unit) {
244  int num;
245 
246  num = 0;
247  if (isnum(canon[len])) {
248  num = strtol(canon + len, 0, 10);
249  }
250  *unit = num;
251  }
252 
253  /* Find the actual device. */
254  canon[len] = '\0';
255  for (i = 0; i < MAX_DEVICES; i++) {
256  if (dev_list[i] != NULL && !strcmp(canon, dev_list[i]->name)) {
257  if (device)
258  *device = dev_list[i];
259 
260  return filename;
261  }
262  }
263 
264  Kprintf("Unknown device '%s'\n", canon);
265  print_known_devices();
266 
267  return (char *)-1;
268 }
269 
270 iop_io_file_t *get_file(int fd)
271 {
272  if (fd >= MAX_FILES)
273  return NULL;
274 
275  if (file_table[fd].device != NULL)
276  return &file_table[fd];
277 
278  return NULL;
279 }
280 
281 iop_io_file_t *get_new_file(void)
282 {
283  int i;
284  iop_io_file_t *fd = NULL;
285  int oldIntr;
286 
287  CpuSuspendIntr(&oldIntr);
288 
289  for (i = 0; i < MAX_FILES; i++)
290  {
291  if (!file_table[i].device)
292  {
293  fd = &file_table[i];
294 
295  // fill in "device" temporarily to mark the fd as allocated.
296  fd->device = (iop_io_device_t *) 0xFFFFFFFF;
297  break;
298  }
299  }
300 
301  CpuResumeIntr(oldIntr);
302 
303  if (i >= MAX_DEVICES)
304  {
305  print_abort_error_io("out of file descriptors", "");
306  return NULL;
307  }
308 
309  return fd;
310 }
311 
312 int io_open(const char *name, int mode)
313 {
314  iop_io_file_t *f = get_new_file();
315  char *filename;
316  int res;
317 
318  if (!f)
319  {
320  return -EMFILE;
321  }
322 
323  if ((filename = find_iop_device(name, &f->unit, &f->device)) == (char *)-1)
324  {
325  f->device = NULL;
326  return -ENODEV;
327  }
328 
329  f->mode = mode;
330  if ((res = f->device->ops->io_open(f, filename, mode)) >= 0)
331  {
332  res = (int)(f - file_table);
333  }
334  else
335  {
336  f->mode = 0;
337  f->device = NULL;
338  }
339 
340  return res;
341 }
342 
343 int io_close(int fd)
344 {
345  iop_io_file_t *f;
346  int res;
347 
348  if ((f = get_file(fd)) == NULL)
349  {
350  return -EBADF;
351  }
352 
353  res = f->device->ops->io_close(f);
354 
355  f->mode = 0;
356  f->device = NULL;
357  return res;
358 }
359 
360 int io_read(int fd, void *ptr, size_t size)
361 {
362  iop_io_file_t *f = get_file(fd);
363 
364  if (f == NULL || !(f->mode & FIO_O_RDONLY))
365  return -EBADF;
366 
367  return f->device->ops->io_read(f, ptr, size);
368 }
369 
370 int io_write(int fd, void *ptr, size_t size)
371 {
372  iop_io_file_t *f = get_file(fd);
373 
374  if (f == NULL || !(f->mode & FIO_O_WRONLY))
375  return -EBADF;
376 
377  return f->device->ops->io_write(f, ptr, size);
378 }
379 
380 int io_lseek(int fd, int offset, int whence)
381 {
382  iop_io_file_t *f = get_file(fd);
383 
384  if (f == NULL)
385  return -EBADF;
386 
387  if (whence < FIO_SEEK_SET || whence > FIO_SEEK_END)
388  {
389  {
390  const char *invalid_lssek_address_str = "invalid lseek arg\r\n";
391  io_write(1, (void *)invalid_lssek_address_str, strlen(invalid_lssek_address_str));
392  }
393  return -EINVAL;
394  }
395 
396  return f->device->ops->io_lseek(f, offset, whence);
397 }
398 
399 int io_ioctl(int fd, unsigned long arg, void *param)
400 {
401  iop_io_file_t *f = get_file(fd);
402 
403  if (f == NULL)
404  return -EBADF;
405 
406  return f->device->ops->io_ioctl(f, arg, param);
407 }
408 
409 int io_remove(const char *name)
410 {
411  iop_io_file_t *f = get_new_file();
412  char *filename;
413  int res;
414 
415  if (!f)
416  {
417  return -EMFILE;
418  }
419 
420  if ((filename = find_iop_device(name, &(f->unit), &(f->device))) == (char *)-1)
421  {
422  f->device = NULL;
423  return -ENODEV;
424  }
425 
426  res = f->device->ops->io_remove(f, filename);
427 
428  f->unit = 0;
429  f->device = NULL;
430 
431  return res;
432 }
433 
434 /* Because mkdir, rmdir, chdir, and sync have similiar arguments (each starts
435  with a path followed by an optional integer), we use a common routine to
436  handle all of them. */
437 static int path_common(const char *name, int arg, int code)
438 {
439  iop_io_file_t *f = get_new_file();
440  iop_io_device_ops_t *dops;
441  char *filename;
442  int res = -EINVAL;
443 
444  if (!f)
445  {
446  return -EMFILE;
447  }
448 
449  if ((filename = find_iop_device(name, &(f->unit), &(f->device))) == (char *)-1)
450  {
451  f->device = NULL;
452  return -ENODEV;
453  }
454 
455  dops = (iop_io_device_ops_t *)f->device->ops;
456  switch (code) {
457  case 4: /* mkdir() */
458  res = dops->io_mkdir(f, filename);
459  break;
460  case 5: /* rmdir() */
461  res = dops->io_rmdir(f, filename);
462  break;
463  default:
464  break;
465  }
466 
467  f->unit = 0;
468  f->device = NULL;
469 
470  return res;
471 }
472 
473 int io_mkdir(const char *name)
474 {
475  return path_common(name, 0, 4);
476 }
477 
478 int io_rmdir(const char *name)
479 {
480  return path_common(name, 0, 5);
481 }
482 
483 int io_dopen(const char *name, int mode)
484 {
485  iop_io_file_t *f = get_new_file();
486  char *filename;
487  int res;
488 
489  (void)mode;
490 
491  if (!f)
492  return -EMFILE;
493 
494  if ((filename = find_iop_device(name, &f->unit, &f->device)) == (char *)-1)
495  {
496  f->device = NULL;
497  return -ENODEV;
498  }
499 
500  f->mode = 0;
501  if ((res = f->device->ops->io_dopen(f, filename)) >= 0)
502  res = (int)(f - file_table);
503  else
504  {
505  f->mode = 0;
506  f->device = NULL;
507  }
508 
509  return res;
510 }
511 
512 int io_dclose(int fd)
513 {
514  iop_io_file_t *f;
515  int res;
516 
517  if ((f = get_file(fd)) == NULL)
518  {
519  return -EBADF;
520  }
521 
522  res = f->device->ops->io_dclose(f);
523 
524  f->mode = 0;
525  f->device = NULL;
526  return res;
527 }
528 
529 int io_dread(int fd, io_dirent_t *io_dirent)
530 {
531  iop_io_file_t *f;
532  int res;
533 
534  if ((f = get_file(fd)) == NULL)
535  {
536  return -EBADF;
537  }
538 
539  res = f->device->ops->io_dread(f, io_dirent);
540 
541  return res;
542 }
543 
544 int io_getstat(const char *name, io_stat_t *stat)
545 {
546  iop_io_file_t *f = get_new_file();
547  char *filename;
548  int res;
549 
550  if (!f)
551  {
552  return -EMFILE;
553  }
554 
555  if ((filename = find_iop_device(name, &(f->unit), &(f->device))) == (char *)-1)
556  {
557  f->device = NULL;
558  return -ENODEV;
559  }
560 
561  res = f->device->ops->io_getstat(f, filename, stat);
562 
563  f->unit = 0;
564  f->device = NULL;
565 
566  return res;
567 }
568 
569 int io_chstat(const char *name, io_stat_t *stat, unsigned int mask)
570 {
571  iop_io_file_t *f = get_new_file();
572  char *filename;
573  int res;
574 
575  if (!f)
576  {
577  return -EMFILE;
578  }
579 
580  if ((filename = find_iop_device(name, &(f->unit), &(f->device))) == (char *)-1)
581  {
582  f->device = NULL;
583  return -ENODEV;
584  }
585 
586  res = f->device->ops->io_chstat(f, filename, stat, mask);
587 
588  f->unit = 0;
589  f->device = NULL;
590 
591  return res;
592 }
593 
594 int io_format(const char *dev)
595 {
596  iop_io_file_t *f = get_new_file();
597  int res;
598 
599  if (!f)
600  {
601  return -EMFILE;
602  }
603 
604  if ((find_iop_device(dev, &(f->unit), &(f->device))) == (char *)-1)
605  {
606  f->device = NULL;
607  return -ENODEV;
608  }
609 
610  res = f->device->ops->io_format(f);
611 
612  f->unit = 0;
613  f->device = NULL;
614 
615  return res;
616 }
_iop_io_device_ops
Definition: ioman_mod.h:81
sysclib.h
_iop_io_file
Definition: ioman_mod.h:55
CpuSuspendIntr
int CpuSuspendIntr(int *state)
Definition: intrman.c:195
loadcore.h
_iop_io_file::unit
int unit
Definition: ioman_mod.h:59
_iop_io_file::device
struct _iop_io_device * device
Definition: ioman_mod.h:61
irx_export_table
Definition: irx.h:90
io_stat_t
Definition: io_common.h:47
ioman.h
ioman_mod.h
CpuResumeIntr
int CpuResumeIntr(int state)
Definition: intrman.c:217
EBADF
#define EBADF
Definition: errno.h:37
io_dirent_t
Definition: io_common.h:58
sysmem.h
_iop_io_device
Definition: ioman_mod.h:66
EINVAL
#define EINVAL
Definition: errno.h:63
intrman.h
_iop_io_file::mode
int mode
Definition: ioman_mod.h:57
errno.h
EMFILE
#define EMFILE
Definition: errno.h:67
ENODEV
#define ENODEV
Definition: errno.h:57