fix: load x87 fpu default settings
[lunaix-os.git] / lunaix-os / kernel / device / devfs.c
1 #include <lunaix/device.h>
2 #include <lunaix/dirent.h>
3 #include <lunaix/fs.h>
4 #include <lunaix/fs/devfs.h>
5 #include <lunaix/spike.h>
6
7 extern struct v_inode_ops devfs_inode_ops;
8 extern struct v_file_ops devfs_file_ops;
9
10 int
11 devfs_read(struct v_inode* inode, void* buffer, size_t len, size_t fpos)
12 {
13     assert(inode->data);
14
15     struct device* dev = (struct device*)inode->data;
16
17     if (!dev->read) {
18         return ENOTSUP;
19     }
20
21     return dev->read(dev, buffer, fpos, len);
22 }
23
24 int
25 devfs_write(struct v_inode* inode, void* buffer, size_t len, size_t fpos)
26 {
27     assert(inode->data);
28
29     struct device* dev = (struct device*)inode->data;
30
31     if (!dev->write) {
32         return ENOTSUP;
33     }
34
35     return dev->write(dev, buffer, fpos, len);
36 }
37
38 int
39 devfs_get_itype(struct device* dev)
40 {
41     int itype = VFS_IFFILE;
42     int dev_if = dev->dev_type & DEV_MSKIF;
43     if (dev_if == DEV_IFCAT) {
44         itype = VFS_IFDIR;
45     } else if (dev_if == DEV_IFVOL) {
46         itype |= VFS_IFVOLDEV;
47     } else {
48         itype |= VFS_IFSEQDEV;
49     }
50     return itype;
51 }
52
53 int
54 devfs_get_dtype(struct device* dev)
55 {
56     switch (dev->dev_type & DEV_MSKIF) {
57         case DEV_IFCAT:
58             return DT_DIR;
59
60         default:
61             return DT_FILE;
62     }
63 }
64
65 int
66 devfs_mknod(struct v_dnode* dnode, struct device* dev)
67 {
68     assert(dev);
69
70     struct v_inode* devnod = vfs_i_find(dnode->super_block, dev->dev_id);
71     if (!devnod) {
72         if ((devnod = vfs_i_alloc(dnode->super_block))) {
73             devnod->id = dev->dev_id;
74             devnod->data = dev;
75             devnod->itype = devfs_get_itype(dev);
76
77             vfs_i_addhash(devnod);
78         } else {
79             return ENOMEM;
80         }
81     }
82
83     vfs_assign_inode(dnode, devnod);
84     return 0;
85 }
86
87 int
88 devfs_dirlookup(struct v_inode* this, struct v_dnode* dnode)
89 {
90     struct device* dev =
91       device_getbyhname((struct device*)this->data, &dnode->name);
92     if (!dev) {
93         return ENOENT;
94     }
95     return devfs_mknod(dnode, dev);
96 }
97
98 int
99 devfs_readdir(struct v_file* file, struct dir_context* dctx)
100 {
101     struct device* dev =
102       device_getbyoffset((struct device*)(file->inode->data), dctx->index);
103     if (!dev) {
104         return 0;
105     }
106     dctx->read_complete_callback(
107       dctx, dev->name.value, dev->name.len, devfs_get_dtype(dev));
108     return 1;
109 }
110
111 void
112 devfs_init_inode(struct v_superblock* vsb, struct v_inode* inode)
113 {
114     inode->ops = &devfs_inode_ops;
115     inode->default_fops = &devfs_file_ops;
116 }
117
118 int
119 devfs_mount(struct v_superblock* vsb, struct v_dnode* mount_point)
120 {
121     vsb->ops.init_inode = devfs_init_inode;
122
123     struct v_inode* rootnod = vfs_i_alloc(vsb);
124
125     if (!rootnod) {
126         return ENOMEM;
127     }
128
129     rootnod->id = -1;
130     rootnod->itype = VFS_IFDIR;
131
132     vfs_i_addhash(rootnod);
133     vfs_assign_inode(mount_point, rootnod);
134
135     return 0;
136 }
137
138 int
139 devfs_unmount(struct v_superblock* vsb)
140 {
141     return 0;
142 }
143
144 void
145 devfs_init()
146 {
147     struct filesystem* fs = fsm_new_fs("devfs", 5);
148     fsm_register(fs);
149     fs->mount = devfs_mount;
150     fs->unmount = devfs_unmount;
151 }
152
153 struct v_inode_ops devfs_inode_ops = { .dir_lookup = devfs_dirlookup,
154                                        .open = default_inode_open,
155                                        .mkdir = default_inode_mkdir,
156                                        .rmdir = default_inode_rmdir };
157
158 struct v_file_ops devfs_file_ops = { .close = default_file_close,
159                                      .read = devfs_read,
160                                      .write = devfs_write,
161                                      .seek = default_file_seek,
162                                      .readdir = devfs_readdir };