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