PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
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
34IRX_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
44static iop_io_device_t *dev_list[MAX_DEVICES];
45iop_io_file_t file_table[MAX_FILES];
46
47static int should_print_known_devices = 1;
48
49#define isnum(c) ((c) >= '0' && (c) <= '9')
50
51#ifdef _IOP
52extern struct irx_export_table _exp_ioman;
53#endif
54
55IOMAN_RETURN_VALUE_IMPL(0);
56
57iop_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
77iop_io_device_t tty_device = {
78 "tty",
79 IOP_DT_CHAR,
80 1,
81 "CONSOLE",
82 &tty_dev_operations,
83};
84
85static int add_tty_device(void)
86{
87 return io_AddDrv(&tty_device);
88}
89
90static 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
104static 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
117static 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.
124static 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
134int _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
154int 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
186int 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
201static 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
221static 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
270iop_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
281iop_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
312int 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
343int 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
360int 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
370int 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
380int 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
399int 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
409int 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. */
437static int path_common(const char *name, int arg, int code)
438{
439 iop_io_file_t *f = get_new_file();
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
473int io_mkdir(const char *name)
474{
475 return path_common(name, 0, 4);
476}
477
478int io_rmdir(const char *name)
479{
480 return path_common(name, 0, 5);
481}
482
483int 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
512int 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
529int 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
544int 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
569int 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
594int 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}
#define EINVAL
Definition errno.h:63
#define EMFILE
Definition errno.h:67
#define ENODEV
Definition errno.h:57
#define EBADF
Definition errno.h:37
int CpuResumeIntr(int state)
Definition intrman.c:227
int CpuSuspendIntr(int *state)
Definition intrman.c:205
struct _iop_io_device * device
Definition ioman_mod.h:61