PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
devfs.c
Go to the documentation of this file.
1/*
2# _____ ___ ____ ___ ____
3# ____| | ____| | | |____|
4# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5#-----------------------------------------------------------------------
6# Copyright 2001-2004, ps2dev - http://www.ps2dev.org
7# Licenced under Academic Free License version 2.0
8# Review ps2sdk README & LICENSE files for further details.
9*/
10
16#include "types.h"
17#include "defs.h"
18#include "irx.h"
19#include "loadcore.h"
20#include "thbase.h"
21#include "thevent.h"
22#include "thsemap.h"
23#include "intrman.h"
24#include "stdio.h"
25#include "sysclib.h"
26#include <errno.h>
27#include "devfs.h"
28#include "sysmem.h"
29#include "stdio.h"
30
31#ifdef USE_IOMAN
32#include "ioman.h"
33#else
34#include "iomanX.h"
35#endif
36
37#define MODNAME "devfs"
38IRX_ID(MODNAME, 1, 1);
39
40#define M_PRINTF(format, args...) printf(MODNAME ": " format, ## args)
41
42#define BANNER "DEVFS %s\n"
43#define VERSION "v0.1"
44#define MAX_OPENFILES 32
45#define MAX_OPEN_DIRFILES 16
46
47extern struct irx_export_table _exp_devfs;
48
49typedef struct
50
51{
52 void *data;
53 s32 valid;
54 u32 mode;
55 u32 open_refcount;
56 devfs_loc_t extent;
57 struct _ioman_data *open_files[MAX_OPENFILES];
58} subdev_t;
59
60typedef struct _devfs_device
61{
63 struct _devfs_device *forw, *back;
64 HDEV hDev;
65 devfs_node_t node;
67 u32 subdev_count;
68 u32 open_refcount;
70
71typedef struct _ioman_data
72{
73 HDEV hDev;
76 int subdev;
77 u32 mode;
78 devfs_loc_t loc;
80
83HDEV dev_count;
84
85typedef struct _directory_file
86
87{
91 u32 devno;
93 u32 opened;
95
96directory_file_t open_dirfiles[MAX_OPEN_DIRFILES];
97
103const char *devfs_subdev_to_str(int subdev)
104
105{
106 static char name[4]; /* Supports up to 999 subdevices */
107 int loop;
108
109 if((subdev > 999) || (subdev < 0))
110 {
111 name[0] = 0;
112 }
113 else
114 {
115 loop = 0;
116 name[loop++] = ((subdev / 100) % 10) + '0';
117 name[loop++] = ((subdev / 10) % 10) + '0';
118 name[loop++] = (subdev % 10) + '0';
119 name[loop++] = 0;
120 }
121
122 loop = 0;
123 if(name[0] == '0') loop = 1;
124 if((name[0] == '0') && (name[1] == '0')) loop = 2;
125
126 return &name[loop];
127}
128
137int devfs_fill_dirent(iox_dirent_t *dirent, int devno)
138
139{
140 devfs_device_t *dev_scan;
141 int curr_no = 0;
142 u32 subdev_loop;
143
144 dev_scan = root_device;
145
146 while(dev_scan != NULL)
147 {
148 if((curr_no + dev_scan->subdev_count) > (u32)devno)
149 {
150 for(subdev_loop = 0; subdev_loop < DEVFS_MAX_SUBDEVS; subdev_loop++)
151 {
152 if(dev_scan->subdevs[subdev_loop].valid)
153 {
154 if(curr_no == devno)
155 {
156 break;
157 }
158 curr_no++;
159 }
160 }
161
162 if(subdev_loop < DEVFS_MAX_SUBDEVS)
163 {
164 memset(dirent, 0, sizeof(iox_dirent_t));
165 dirent->stat.size = dev_scan->subdevs[subdev_loop].extent.loc32[0];
166 dirent->stat.hisize = dev_scan->subdevs[subdev_loop].extent.loc32[1];
167 dirent->stat.mode = FIO_S_IFREG;
168 if(dev_scan->subdevs[subdev_loop].mode & DEVFS_MODE_R)
169 {
170 dirent->stat.mode |= FIO_S_IRUSR;
171 }
172 if(dev_scan->subdevs[subdev_loop].mode & DEVFS_MODE_W)
173 {
174 dirent->stat.mode |= FIO_S_IWUSR;
175 }
176 dirent->name[0] = 0;
177 strcpy(dirent->name, dev_scan->node.name);
178 strcat(dirent->name, devfs_subdev_to_str(subdev_loop));
179
180 return strlen(dirent->name);
181 }
182 }
183
184 curr_no += dev_scan->subdev_count;
185
186 dev_scan = dev_scan->forw;
187 }
188
189 return 0;
190}
191
199
200{
201 devfs_device_t *dev;
202
203 if((node == NULL) || (node->name == NULL))
204 {
205 return NULL;
206 }
207
208 dev = AllocSysMemory(ALLOC_FIRST, sizeof(devfs_device_t), NULL);
209 if(dev == NULL)
210 {
211 printf("create_device: Alloc Failed\n");
212 return NULL;
213 }
214
215 memset(dev, 0, sizeof(devfs_device_t));
216 memcpy(&dev->node, node, sizeof(devfs_node_t));
217 if(dev->node.name != NULL)
218 {
219 dev->node.name = AllocSysMemory(ALLOC_FIRST, strlen(node->name) + 1, NULL);
220 if(dev->node.name == NULL)
221 {
222 FreeSysMemory(dev);
223 return NULL;
224 }
225 memcpy(dev->node.name, node->name, strlen(node->name) + 1);
226 }
227
228 if(dev->node.desc != NULL)
229 {
230 dev->node.desc = AllocSysMemory(ALLOC_FIRST, strlen(node->desc) + 1, NULL);
231 if(dev->node.name == NULL)
232 {
233 FreeSysMemory(dev->node.name);
234 FreeSysMemory(dev);
235 return NULL;
236 }
237 memcpy(dev->node.desc, node->desc, strlen(node->desc) + 1);
238 }
239
240 return dev;
241}
242
249
250{
251 if(dev != NULL)
252 {
253 if(dev->node.name)
254 {
255 FreeSysMemory(dev->node.name);
256 }
257
258 if(dev->node.desc)
259 {
260 FreeSysMemory(dev->node.desc);
261 }
262
263 FreeSysMemory(dev);
264 }
265
266 return 0;
267}
268
277
278{
279 devfs_device_t *dev_scan;
280
281 if(name == NULL)
282 {
283 return NULL;
284 }
285
286 dev_scan = root_device;
287
288 while(dev_scan != NULL)
289 {
290 /* Ensure name is at least less than or equal to the one we want to find */
291 if(strlen(dev_scan->node.name) <= strlen(name))
292 {
293 if(strncmp(dev_scan->node.name, name, strlen(dev_scan->node.name)) == 0)
294 {
295 return dev_scan;
296 }
297 }
298 dev_scan = dev_scan->forw;
299 }
300
301 return NULL;
302}
303
310
311{
312 devfs_device_t *dev_scan;
313
314 dev_scan = root_device;
315
316 while(dev_scan != NULL)
317 {
318 if(dev_scan->hDev == hDev)
319 {
320 return dev_scan;
321 }
322 dev_scan = dev_scan->forw;
323 }
324
325 return NULL;
326}
327
334#ifdef USE_IOMAN
335int devfs_open(iop_file_t *file, const char *name, int mode)
336#else
337int devfs_open(iop_file_t *file, const char *name, int mode, int unused)
338#endif
339{
340 devfs_device_t *dev;
341 int fn_offset = 0;
342
343 (void)unused;
344
345 //printf("devfs_open file=%p name=%s mode=%d\n", file, name, mode);
346 if(name == NULL)
347 {
348 M_PRINTF("open: Name is NULL\n");
349 return -EPERM;
350 }
351
352 if((name[0] == '\\') || (name[0] == '/'))
353 {
354 fn_offset = 1;
355 }
356
357 dev = devfs_find_devicename(name + fn_offset);
358
359 if(dev != NULL)
360 {
361 int loop;
362 char *endp;
363 int subdev;
364 int name_len;
365
366 name_len = strlen(dev->node.name);
367
368 if((unsigned int)name_len == strlen(name)) /* If this is has not got a subnumber */
369 {
370 M_PRINTF("open: No subdevice number in filename %s\n", name);
371 return -EPERM;
372 }
373
374 subdev = strtoul(&name[name_len + fn_offset], &endp, 10);
375 if(((subdev == 0) && (name[name_len + fn_offset] != '0'))
376 || (subdev >= DEVFS_MAX_SUBDEVS))
377 /* Invalid number */
378 {
379 M_PRINTF("open: Invalid subdev number %d\n", subdev);
380 return -EPERM;
381 }
382
383 if(*endp)
384 /* Extra charactes after filename */
385 {
386 M_PRINTF("open: Invalid filename\n");
387 return -EPERM;
388 }
389
390 if(!dev->subdevs[subdev].valid)
391 /* No subdev */
392 {
393 M_PRINTF("open: No subdev registered\n");
394 return -EPERM;
395 }
396
397 if((dev->subdevs[subdev].mode & DEVFS_MODE_EX)
398 && (dev->subdevs[subdev].open_refcount > 0))
399 /* Already opened in exclusive mode */
400 {
401 M_PRINTF("open: Exclusive subdevice already opened\n");
402 return -EPERM;
403 }
404
405 if(dev->subdevs[subdev].open_refcount == MAX_OPENFILES)
406 {
407 M_PRINTF("open: Reached open file limit for sub device\n");
408 }
409
410 /* Tried to open read but not allowed */
411 if(((mode & O_RDONLY) || ((mode & O_RDWR) == O_RDWR))
412 && !(dev->subdevs[subdev].mode & DEVFS_MODE_R))
413 {
414 M_PRINTF("open: Read mode requested but not permitted\n");
415 return -EPERM;
416 }
417
418 if(((mode & O_WRONLY) || ((mode & O_RDWR) == O_RDWR))
419 && !(dev->subdevs[subdev].mode & DEVFS_MODE_W))
420 {
421 M_PRINTF("open: Write mode requested but not permitted\n");
422 return -EPERM;
423 }
424
425 file->privdata = AllocSysMemory(ALLOC_FIRST, sizeof(ioman_data_t), NULL);
426 if(file->privdata == NULL)
427 {
428 M_PRINTF("open: Allocation failure\n");
429 return -EPERM;
430 }
431
432 ((ioman_data_t *) file->privdata)->hDev = dev->hDev;
433 ((ioman_data_t *) file->privdata)->subdev = subdev;
434 ((ioman_data_t *) file->privdata)->loc.loc64 = 0;
435 ((ioman_data_t *) file->privdata)->dev = dev;
436 ((ioman_data_t *) file->privdata)->mode = mode;
437
438 dev->subdevs[subdev].open_refcount++;
439 loop = 0;
440 while((loop < MAX_OPENFILES) && (dev->subdevs[subdev].open_files[loop]))
441 {
442 loop++;
443 }
444 if(loop == MAX_OPENFILES)
445 {
446 FreeSysMemory(file->privdata);
447 M_PRINTF("open: Inconsistency between number of open files and available slot\n");
448 return -EPERM;
449 }
450
451 dev->subdevs[subdev].open_files[loop] = file->privdata;
452 dev->open_refcount++;
453 M_PRINTF("open: Opened device %s subdev %d\n", dev->node.name, subdev);
454 }
455 else
456 {
457 M_PRINTF("open: Couldn't find the device\n");
458 return -EPERM;
459 }
460
461 return 0;
462}
463
470
471{
472 ioman_data_t *data = (ioman_data_t *) file->privdata;
473
474 if((data) && (data->hDev != INVALID_HDEV)) /* Invalid HDEV is a dir listing */
475 {
476 devfs_device_t *dev;
477 dev = data->dev;
478
479 if(dev != NULL)
480 {
481 int loop;
482
483 if(dev->subdevs[data->subdev].open_refcount > 0)
484 {
485 dev->subdevs[data->subdev].open_refcount--;
486 }
487 if(dev->open_refcount > 0)
488 {
489 dev->open_refcount--;
490 }
491
492 loop = 0;
493 while((loop < MAX_OPENFILES)
494 && (dev->subdevs[data->subdev].open_files[loop] != data))
495 {
496 loop++;
497 }
498
499 if(loop != MAX_OPENFILES)
500 {
501 dev->subdevs[data->subdev].open_files[loop] = NULL;
502 }
503 else
504 {
505 M_PRINTF("close: Could not find opened file\n");
506 }
507
508 M_PRINTF("close: Closing device %s subdev %d\n", dev->node.name, data->subdev);
509 FreeSysMemory(data);
510 }
511 else
512 {
513 FreeSysMemory(data);
514 file->privdata = NULL;
515 return -EPERM;
516 }
517 }
518 else
519 {
520 return -EPERM;
521 }
522
523 return 0;
524}
525
532int devfs_ioctl(iop_file_t *file, int cmd, void *args)
533
534{
535 devfs_device_t *dev;
536 ioman_data_t *data = (ioman_data_t *) file->privdata;
537
538 if(cmd == DEVFS_IOCTL_GETDESC)
539 {
540 return -EPERM; /* ioctl cannot support this call */
541 }
542
543 data = file->privdata;
544 if((data) && (data->hDev != INVALID_HDEV))
545 {
546 dev = data->dev;
547 if(dev == NULL) /* Device has been closed from under us */
548 {
549 /* Delete data to try and prevent a memory leak */
550 FreeSysMemory(data);
551 file->privdata = NULL;
552 return -EPERM;
553 }
554
555 if(dev->node.ioctl != NULL)
556 {
557 devfs_info_t dev_info;
558
559 dev_info.data = dev->subdevs[data->subdev].data;
560 dev_info.subdev = data->subdev;
561 dev_info.mode = data->mode;
562 dev_info.loc = data->loc;
563 return dev->node.ioctl(&dev_info, DEVFS_IOCTL_TYPE_1, cmd, args, 0, NULL, 0);
564 }
565
566 }
567
568 return -EPERM;
569}
570
580int devfs_ioctl2(iop_file_t *file, int cmd, void *args, unsigned int arglen, void *buf, unsigned int buflen)
581
582{
583 devfs_device_t *dev;
584 ioman_data_t *data = (ioman_data_t *) file->privdata;
585
586 data = file->privdata;
587 if((data) && (data->hDev != INVALID_HDEV))
588 {
589 dev = data->dev;
590 if(dev == NULL) /* Device has been closed from under us */
591 {
592 /* Delete data to try and prevent a memory leak */
593 FreeSysMemory(data);
594 file->privdata = NULL;
595 return -EPERM;
596 }
597
598 if((cmd == DEVFS_IOCTL_GETDESC) && (buf) && (buflen >= DEVFS_MAX_DESC_LENGTH))
599 {
600 if(dev->node.desc)
601 {
602 strncpy(buf, dev->node.desc, buflen-1);
603 *(((u8 *)buf + buflen)) = 0;
604 return strlen(buf);
605 }
606
607 return 0;
608 }
609
610 if(dev->node.ioctl != NULL)
611 {
612 devfs_info_t dev_info;
613
614 dev_info.data = dev->subdevs[data->subdev].data;
615 dev_info.subdev = data->subdev;
616 dev_info.mode = data->mode;
617 dev_info.loc = data->loc;
618 return dev->node.ioctl(&dev_info, DEVFS_IOCTL_TYPE_2, cmd, args, arglen, buf, buflen);
619 }
620
621 }
622
623 return -EPERM;
624}
625
632int devfs_read(iop_file_t *file, void *buf, int len)
633
634{
635 devfs_device_t *dev;
636 ioman_data_t *data = (ioman_data_t *) file->privdata;
637
638 //printf("devfs_read file=%p buf=%p len=%d\n", file, buf, len);
639
640 data = file->privdata;
641 if((data) && (data->hDev != INVALID_HDEV))
642 {
643 dev = data->dev;
644 if(dev == NULL) /* Device has been closed from under us */
645 {
646 /* Delete data to try and prevent a memory leak */
647 FreeSysMemory(data);
648 file->privdata = NULL;
649 return -EPERM;
650 }
651
652 if((dev->node.read != NULL)
653 && (dev->subdevs[data->subdev].mode & DEVFS_MODE_R))
654 {
655 devfs_info_t dev_info;
656 int bytes_read;
657
658 dev_info.data = dev->subdevs[data->subdev].data;
659 dev_info.subdev = data->subdev;
660 dev_info.mode = data->mode;
661 dev_info.loc = data->loc;
662 bytes_read = dev->node.read(&dev_info, buf, len);
663 if(bytes_read > 0)
664 {
665 data->loc.loc64 += (u64) bytes_read;
666 }
667 return bytes_read;
668 }
669 }
670
671 return -EPERM;
672}
673
680int devfs_write(iop_file_t *file, void *buf, int len)
681
682{
683 devfs_device_t *dev;
684 ioman_data_t *data = (ioman_data_t *) file->privdata;
685
686 //printf("devfs_write file=%p buf=%p len=%d\n", file, buf, len);
687 data = file->privdata;
688 if((data) && (data->hDev != INVALID_HDEV))
689 {
690 dev = data->dev;
691 if(dev == NULL) /* Device has been closed from under us */
692 {
693 /* Delete data to try and prevent a memory leak */
694 FreeSysMemory(data);
695 file->privdata = NULL;
696 return -EPERM;
697 }
698
699 if((dev->node.write != NULL)
700 && (dev->subdevs[data->subdev].mode & DEVFS_MODE_W))
701 {
702 devfs_info_t dev_info;
703 int bytes_written;
704
705 dev_info.data = dev->subdevs[data->subdev].data;
706 dev_info.subdev = data->subdev;
707 dev_info.mode = data->mode;
708 dev_info.loc = data->loc;
709 bytes_written = dev->node.write(&dev_info, buf, len);
710 if(bytes_written > 0)
711 {
712 data->loc.loc64 += (u64) bytes_written;
713 }
714 return bytes_written;
715 }
716 }
717
718 return -EPERM;
719}
720
727int devfs_lseek(iop_file_t *file, long loc, int whence)
728{
729 devfs_device_t *dev;
730 ioman_data_t *data = (ioman_data_t *) file->privdata;
731
732 //printf("devfs_lseek file=%p loc=%ld whence=%d\n", file, loc, whence);
733 data = file->privdata;
734 if((data) && (data->hDev != INVALID_HDEV))
735 {
736 dev = data->dev;
737 if(dev == NULL) /* Device has been closed from under us */
738 {
739 /* Delete data to try and prevent a memory leak */
740 FreeSysMemory(data);
741 file->privdata = NULL;
742 return -EPERM;
743 }
744
745 switch(whence)
746 {
747 case SEEK_SET: if(loc > 0)
748 data->loc.loc64 = (u64) loc;
749 break;
750 case SEEK_CUR: if(loc > 0)
751 data->loc.loc64 += (u64) loc;
752 else if((u64)((s64) -loc) < data->loc.loc64)
753 data->loc.loc64 += (s64) loc;
754 break;
755 case SEEK_END: if((loc > 0)
756 && (dev->subdevs[data->subdev].extent.loc64 >= (u64) loc))
757 data->loc.loc64 = dev->subdevs[data->subdev].extent.loc64 - (u64) loc;
758 break;
759 default: return -EPERM;
760 }
761 }
762 else
763 {
764 return -EPERM;
765 }
766
767 return data->loc.loc32[0];
768}
769
775int devfs_lseek64(iop_file_t *file, long long loc, int whence)
776{
777 devfs_device_t *dev;
778 ioman_data_t *data = (ioman_data_t *) file->privdata;
779
780 //printf("devfs_lseek64 file=%p loc= whence=%d\n", file, whence);
781 data = file->privdata;
782 if((data) && (data->hDev != INVALID_HDEV))
783 {
784 dev = data->dev;
785 if(dev == NULL) /* Device has been closed from under us */
786 {
787 /* Delete data to try and prevent a memory leak */
788 FreeSysMemory(data);
789 file->privdata = NULL;
790 return -EPERM;
791 }
792
793 switch(whence)
794 {
795 case SEEK_SET: if(loc > 0)
796 data->loc.loc64 = (u64) loc;
797 break;
798 case SEEK_CUR: if(loc > 0)
799 data->loc.loc64 += (u64) loc;
800 else if((u64)((s64) -loc) < data->loc.loc64)
801 data->loc.loc64 += (s64) loc;
802 break;
803 case SEEK_END: if((loc > 0) && (dev->subdevs[data->subdev].extent.loc64 >= (u64) loc))
804 data->loc.loc64 = dev->subdevs[data->subdev].extent.loc64 - (u64) loc;
805 break;
806 default: return -EPERM;
807 }
808
809 }
810 else
811 {
812 return -EPERM;
813 }
814
815 return data->loc.loc32[0];
816}
817
823int devfs_dopen(iop_file_t *file, const char *name)
824{
825 int dir_loop;
826
827 if((name == NULL) || ((name[0] != '\\') && (name[0] != '/')))
828 {
829 M_PRINTF("dopen: Not a valid directory name\n");
830 return -EPERM;
831 }
832
833 //M_PRINTF("dopen: file=%p name=%s\n", file, name);
834 for(dir_loop = 0; dir_loop < MAX_OPEN_DIRFILES; dir_loop++)
835 {
836 if(!open_dirfiles[dir_loop].opened)
837 {
838 open_dirfiles[dir_loop].devno = 0;
839 open_dirfiles[dir_loop].hDev = INVALID_HDEV;
840 file->privdata = &open_dirfiles[dir_loop];
841 return 0;
842 }
843 }
844
845 return -EPERM;
846}
847
853{
854 directory_file_t *dir;
855
856 //M_PRINTF("dclose: file=%p\n", file);
857 dir = (directory_file_t *) file->privdata;
858
859 if((dir) && (dir->hDev == INVALID_HDEV))
860 {
861 dir->opened = 0;
862 file->privdata = NULL;
863 }
864
865 return 0;
866}
867
868#ifdef USE_IOMAN
869int devfs_dread(iop_file_t *file, fio_dirent_t *buf)
870#else
871int devfs_dread(iop_file_t *file, iox_dirent_t *buf)
872#endif
873{
874 directory_file_t *dir;
875 int ret = 0;
876
877 //M_PRINTF("dread: file=%p buf=%p\n", file, buf);
878 dir = (directory_file_t *) file->privdata;
879 if((dir) && (dir->hDev == INVALID_HDEV) && (buf))
880 {
881 ret = devfs_fill_dirent(buf, dir->devno);
882 if(ret)
883 {
884 dir->devno++;
885 }
886 }
887
888 return ret;
889}
890
897#ifdef USE_IOMAN
898int devfs_getstat(iop_file_t *file, const char *name, fio_stat_t *stat)
899#else
900int devfs_getstat(iop_file_t *file, const char *name, iox_stat_t *stat)
901#endif
902{
903 devfs_device_t *dev;
904 int fn_offset = 0;
905
906 (void)file;
907
908 if(name == NULL)
909 {
910 return -EPERM;
911 }
912
913 if((name[0] == '\\') || (name[0] == '/'))
914 {
915 fn_offset = 1;
916 }
917
918 if(stat == NULL)
919 {
920 return -EPERM;
921 }
922
923 dev = devfs_find_devicename(name + fn_offset);
924
925 if(dev != NULL)
926 {
927 char *endp;
928 int subdev;
929 int name_len;
930
931 name_len = strlen(dev->node.name);
932
933 if((unsigned int)name_len == strlen(name)) /* If this is has not got a subnumber */
934 {
935 M_PRINTF("getstat: No subdevice number in filename %s\n", name);
936 return -EPERM;
937 }
938
939 subdev = strtoul(&name[name_len + fn_offset], &endp, 10);
940 if(((subdev == 0) && (name[name_len + fn_offset] != '0'))
941 || (subdev >= DEVFS_MAX_SUBDEVS))
942 /* Invalid number */
943 {
944 M_PRINTF("getstat: Invalid subdev number %d\n", subdev);
945 return -EPERM;
946 }
947
948 if(*endp)
949 /* Extra charactes after filename */
950 {
951 M_PRINTF("getstat: Invalid filename\n");
952 return -EPERM;
953 }
954
955 if(!dev->subdevs[subdev].valid)
956 {
957 M_PRINTF("getstat: No subdev registered\n");
958 return -EPERM;
959 }
960
961#ifdef USE_IOMAN
962 memset(stat, 0, sizeof(fio_stat_t));
963#else
964 memset(stat, 0, sizeof(iox_stat_t));
965#endif
966 stat->size = dev->subdevs[subdev].extent.loc32[0];
967 stat->hisize = dev->subdevs[subdev].extent.loc32[1];
968 stat->mode = FIO_S_IFREG;
969 if(dev->subdevs[subdev].mode & DEVFS_MODE_R)
970 {
971 stat->mode |= FIO_S_IRUSR;
972 }
973 if(dev->subdevs[subdev].mode & DEVFS_MODE_W)
974 {
975 stat->mode |= FIO_S_IWUSR;
976 }
977 }
978
979 return 0;
980}
981
982IOMANX_RETURN_VALUE_IMPL(0);
983IOMANX_RETURN_VALUE_IMPL(EPERM);
984
985static iop_device_ops_t devfs_ops = {
986 IOMANX_RETURN_VALUE(0), // init
987 IOMANX_RETURN_VALUE(0), // deinit
988 IOMANX_RETURN_VALUE(EPERM), // format
989 &devfs_open, // open
990 &devfs_close, // close
991 &devfs_read, // read
992 IOMANX_RETURN_VALUE(EPERM), // write
993 IOMANX_RETURN_VALUE(EPERM), // lseek
994 &devfs_ioctl, // ioctl
995 IOMANX_RETURN_VALUE(EPERM), // remove
996 IOMANX_RETURN_VALUE(EPERM), // mkdir
997 IOMANX_RETURN_VALUE(EPERM), // rmdir
998 &devfs_dopen, // dopen
999 &devfs_dclose, // dclose
1000 &devfs_dread, // dread
1001 &devfs_getstat, // getstat
1002 IOMANX_RETURN_VALUE(EPERM), // chstat
1003 IOMANX_RETURN_VALUE(EPERM), // rename
1004 IOMANX_RETURN_VALUE(EPERM), // chdir
1005 IOMANX_RETURN_VALUE(EPERM), // sync
1006 IOMANX_RETURN_VALUE(EPERM), // mount
1007 IOMANX_RETURN_VALUE(EPERM), // umount
1008 IOMANX_RETURN_VALUE_S64(EPERM), // lseek64
1009 IOMANX_RETURN_VALUE(EPERM), // devctl
1010 IOMANX_RETURN_VALUE(EPERM), // symlink
1011 IOMANX_RETURN_VALUE(EPERM), // readlink
1012 &devfs_ioctl2, // ioctl2
1013};
1014
1015static iop_device_t devfs_device = {
1016 "devfs",
1017 IOP_DT_FS | IOP_DT_FSEXT,
1018 0x100,
1019 "PS2 Device FS Driver",
1020 &devfs_ops,
1021};
1022
1026int init_devfs(void)
1027
1028{
1029 root_device = NULL;
1030 dev_count = 0;
1031
1032 memset(open_dirfiles, 0, sizeof(directory_file_t) * MAX_OPEN_DIRFILES);
1033
1034 DelDrv(devfs_device.name);
1035
1036 return AddDrv(&devfs_device);
1037}
1038
1044int _start(int argc, char *argv[])
1045{
1046 int res = MODULE_NO_RESIDENT_END;
1047 int err;
1048
1049 (void)argc;
1050 (void)argv;
1051
1052 printf(BANNER, VERSION);
1053
1054 if ((err = RegisterLibraryEntries(&_exp_devfs)) != 0) {
1055 M_PRINTF("Library is already registered, exiting.\n");
1056 printf("err=%d\n", err);
1057 }
1058 else
1059 {
1060 res = init_devfs() ? MODULE_NO_RESIDENT_END : MODULE_RESIDENT_END;
1061 }
1062
1063 M_PRINTF("devfs_device_t size=%d\n", (int)(sizeof(devfs_device_t)));
1064 M_PRINTF("Driver loaded.\n");
1065
1066 return res;
1067}
1068
1073int devfs_check_devname(const char *name)
1074/* Valid device name uses alphabetic characters only */
1075
1076{
1077 int str_loop;
1078
1079 if((name == NULL) || (name[0] == 0))
1080 {
1081 return 0;
1082 }
1083
1084 if(strlen(name) > DEVFS_MAX_DEVNAME_LENGTH)
1085 {
1086 return 0;
1087 }
1088
1089 str_loop = 0;
1090
1091 while(name[str_loop])
1092 {
1093 char ch;
1094
1095 ch = name[str_loop];
1096 if(((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z')))
1097 {
1098 str_loop++;
1099 }
1100 else
1101 {
1102 return 0;
1103 }
1104 }
1105
1106 return 1;
1107}
1108
1110
1111{
1112 devfs_device_t *dev = NULL;
1113 devfs_device_t *dev_scan;
1114
1115 //printf("AddDevice node=%p\n", node);
1116 if(node == NULL)
1117 {
1118 M_PRINTF("AddDevice: node == NULL\n");
1119 return INVALID_HDEV;
1120 }
1121
1122 if(!devfs_check_devname(node->name))
1123 {
1124 M_PRINTF("AddDevice: node name invalid\n");
1125 return INVALID_HDEV;
1126 }
1127
1128 if(devfs_find_devicename(node->name))
1129 {
1130 M_PRINTF("AddDevice: cannot add new device. Already exists\n");
1131 return INVALID_HDEV;
1132 }
1133
1134 dev = devfs_create_device(node);
1135 if(dev == NULL)
1136 {
1137 M_PRINTF("AddDevice: failed to allocate device structure\n");
1138 return INVALID_HDEV;
1139 }
1140 if(root_device == NULL)
1141 {
1142 root_device = dev;
1143 }
1144 else
1145 {
1146 dev_scan = root_device;
1147 while(dev_scan->forw) /* Scan the device linked list */
1148 {
1149 dev_scan = dev_scan->forw;
1150 }
1151 dev_scan->forw = dev;
1152 dev->back = dev_scan;
1153 }
1154
1155 dev->hDev = dev_count++;
1156 if(dev_count == INVALID_HDEV) dev_count++;
1157 M_PRINTF("AddDevice: Registered device (%s)\n", node->name);
1158
1159 return dev->hDev;
1160}
1161
1163
1164{
1165 devfs_device_t *dev;
1166 int ret = -1;
1167 devfs_device_t *forw, *back;
1168
1169 //printf("DelDevice hDev=%d\n", hDev);
1170 dev = devfs_find_deviceid(hDev);
1171 if(dev)
1172 {
1173 int subdev_loop;
1174 int openfile_loop;
1175
1176 forw = dev->forw;
1177 back = dev->back;
1178
1179 /* Delete the device even if open files */
1180 for(subdev_loop = 0; subdev_loop < DEVFS_MAX_SUBDEVS; subdev_loop++)
1181 {
1182 for(openfile_loop = 0; openfile_loop < MAX_OPENFILES; openfile_loop++)
1183 {
1184 if(dev->subdevs[subdev_loop].open_files[openfile_loop])
1185 {
1186 dev->subdevs[subdev_loop].open_files[openfile_loop]->dev = NULL;
1187 /* Set the device reference to NULL */
1188 }
1189 }
1190 }
1192
1193 if(back)
1194 {
1195 back->forw = forw;
1196 }
1197 else
1198 {
1199 root_device = NULL;
1200 }
1201
1202 if(forw)
1203 {
1204 forw->back = back;
1205 }
1206
1207 ret = 0;
1208 }
1209
1210 return ret;
1211}
1212
1213int DevFSAddSubDevice(HDEV hDev, u32 subdev_no, s32 mode, devfs_loc_t extent, void *data)
1214
1215{
1216 devfs_device_t *dev;
1217
1218 //M_PRINTF("AddSubDevice hDev=%d subdev_no=%d data=%p\n", hDev, subdev_no, data);
1219 dev = devfs_find_deviceid(hDev);
1220 if(dev != NULL)
1221 {
1222 if(subdev_no >= DEVFS_MAX_SUBDEVS)
1223 {
1224 M_PRINTF("AddSubDevice: Sub device number too big\n");
1225 return -1;
1226 }
1227
1228 if(dev->subdevs[subdev_no].valid)
1229 {
1230 M_PRINTF("AddSubDevice: Sub device already created\n");
1231 return -1;
1232 }
1233
1234 dev->subdevs[subdev_no].data = data;
1235 dev->subdevs[subdev_no].valid = 1;
1236 dev->subdevs[subdev_no].mode = mode;
1237 dev->subdevs[subdev_no].open_refcount = 0;
1238 dev->subdevs[subdev_no].extent = extent;
1239 memset(dev->subdevs[subdev_no].open_files, 0, sizeof(ioman_data_t *) * MAX_OPENFILES);
1240 dev->subdev_count++;
1241 }
1242 else
1243 {
1244 M_PRINTF("AddSubDevice: Couldn't find device ID\n");
1245 return -1;
1246 }
1247
1248 return 0;
1249}
1250
1251int DevFSDelSubDevice(HDEV hDev, u32 subdev_no)
1252
1253{
1254 devfs_device_t *dev;
1255
1256 //printf("DelSubDevice hDev=%d subdev_no=%d\n", hDev, subdev_no);
1257 dev = devfs_find_deviceid(hDev);
1258 if(dev != NULL)
1259 {
1260 int openfile_loop;
1261
1262 if(subdev_no >= DEVFS_MAX_SUBDEVS)
1263 {
1264 M_PRINTF("DelSubDevice: Sub device number too big\n");
1265 return -1;
1266 }
1267
1268 if(!dev->subdevs[subdev_no].valid)
1269 {
1270 M_PRINTF("DelSubDevice: Sub device not created\n");
1271 return -1;
1272 }
1273
1274 dev->subdevs[subdev_no].data = NULL;
1275 dev->subdevs[subdev_no].valid = 0;
1276 dev->subdevs[subdev_no].mode = 0;
1277 dev->subdevs[subdev_no].open_refcount = 0;
1278 dev->subdevs[subdev_no].extent.loc64= 0;
1279 for(openfile_loop = 0; openfile_loop < MAX_OPENFILES; openfile_loop++)
1280 {
1281 if(dev->subdevs[subdev_no].open_files[openfile_loop])
1282 {
1283 dev->subdevs[subdev_no].open_files[openfile_loop]->dev = NULL;
1284 dev->subdevs[subdev_no].open_files[openfile_loop] = NULL;
1285 }
1286 }
1287 dev->subdev_count--;
1288 }
1289
1290 return 0;
1291}
int devfs_dopen(iop_file_t *file, const char *name)
Definition devfs.c:823
devfs_device_t * dev
Definition devfs.c:75
int devfs_lseek64(iop_file_t *file, long long loc, int whence)
Definition devfs.c:775
int devfs_getstat(iop_file_t *file, const char *name, iox_stat_t *stat)
Definition devfs.c:900
int devfs_check_devname(const char *name)
Definition devfs.c:1073
int devfs_write(iop_file_t *file, void *buf, int len)
Definition devfs.c:680
int devfs_lseek(iop_file_t *file, long loc, int whence)
Definition devfs.c:727
int devfs_delete_device(devfs_device_t *dev)
Definition devfs.c:248
const char * devfs_subdev_to_str(int subdev)
Definition devfs.c:103
int _start(int argc, char *argv[])
Definition devfs.c:1044
int devfs_close(iop_file_t *file)
Definition devfs.c:469
int init_devfs(void)
Definition devfs.c:1026
int devfs_dclose(iop_file_t *file)
Definition devfs.c:852
int devfs_ioctl(iop_file_t *file, int cmd, void *args)
Definition devfs.c:532
devfs_device_t * root_device
Definition devfs.c:82
devfs_device_t * devfs_create_device(const devfs_node_t *node)
Definition devfs.c:198
struct _devfs_device * forw
Definition devfs.c:63
int devfs_open(iop_file_t *file, const char *name, int mode, int unused)
Definition devfs.c:337
int devfs_ioctl2(iop_file_t *file, int cmd, void *args, unsigned int arglen, void *buf, unsigned int buflen)
Definition devfs.c:580
devfs_device_t * devfs_find_devicename(const char *name)
Definition devfs.c:276
int devfs_read(iop_file_t *file, void *buf, int len)
Definition devfs.c:632
devfs_device_t * devfs_find_deviceid(HDEV hDev)
Definition devfs.c:309
int devfs_fill_dirent(iox_dirent_t *dirent, int devno)
Definition devfs.c:137
#define EPERM
Definition errno.h:21
char * name
Definition devfs.h:106
char * desc
Definition devfs.h:108
void * data
Definition devfs.h:83
u32 mode
Definition devfs.h:89
s32 subdev
Definition devfs.h:85
u32 loc32[2]
Definition devfs.h:73
read_handler read
Definition devfs.h:114
ioctl_handler ioctl
Definition devfs.h:118
u64 loc64
Definition devfs.h:75
write_handler write
Definition devfs.h:116
devfs_loc_t loc
Definition devfs.h:91
HDEV DevFSAddDevice(const devfs_node_t *node)
Definition devfs.c:1109
#define DEVFS_MAX_DESC_LENGTH
Definition devfs.h:32
int DevFSAddSubDevice(HDEV hDev, u32 subdev_no, s32 mode, devfs_loc_t extent, void *data)
Definition devfs.c:1213
s32 HDEV
Definition devfs.h:26
#define DEVFS_IOCTL_TYPE_1
Definition devfs.h:61
int DevFSDelDevice(HDEV hDev)
Definition devfs.c:1162
#define DEVFS_MAX_SUBDEVS
Definition devfs.h:28
#define DEVFS_MAX_DEVNAME_LENGTH
Definition devfs.h:30
#define INVALID_HDEV
Definition devfs.h:152
int DevFSDelSubDevice(HDEV hDev, u32 subdev_no)
Definition devfs.c:1251
#define DEVFS_IOCTL_GETDESC
Definition devfs.h:66
#define DEVFS_IOCTL_TYPE_2
Definition devfs.h:63
@ DEVFS_MODE_R
Definition devfs.h:42
@ DEVFS_MODE_EX
Definition devfs.h:38
@ DEVFS_MODE_W
Definition devfs.h:40
void * privdata
Definition ioman.h:61
#define IOP_DT_FSEXT
Definition iomanX.h:66
#define FIO_S_IRUSR
Definition iox_stat.h:58
#define FIO_S_IFREG
Definition iox_stat.h:43
#define FIO_S_IWUSR
Definition iox_stat.h:60