feat: (iso9660) finishing up unmount
[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_read_page(struct v_inode* inode, void* buffer, size_t len, size_t fpos)
40 {
41     assert(inode->data);
42
43     struct device* dev = (struct device*)inode->data;
44
45     if (!dev->read_page) {
46         return ENOTSUP;
47     }
48
49     return dev->read_page(dev, buffer, fpos);
50 }
51
52 int
53 devfs_write_page(struct v_inode* inode, void* buffer, size_t len, size_t fpos)
54 {
55     assert(inode->data);
56
57     struct device* dev = (struct device*)inode->data;
58
59     if (!dev->read_page) {
60         return ENOTSUP;
61     }
62
63     return dev->read_page(dev, buffer, fpos);
64 }
65
66 int
67 devfs_get_itype(struct device* dev)
68 {
69     int itype = VFS_IFFILE;
70     int dev_if = dev->dev_type & DEV_MSKIF;
71     if (dev_if == DEV_IFCAT) {
72         itype = VFS_IFDIR;
73     } else if (dev_if == DEV_IFVOL) {
74         itype |= VFS_IFVOLDEV;
75     } else {
76         itype |= VFS_IFSEQDEV;
77     }
78     return itype;
79 }
80
81 int
82 devfs_get_dtype(struct device* dev)
83 {
84     switch (dev->dev_type & DEV_MSKIF) {
85         case DEV_IFCAT:
86             return DT_DIR;
87
88         default:
89             return DT_FILE;
90     }
91 }
92
93 int
94 devfs_mknod(struct v_dnode* dnode, struct device* dev)
95 {
96     assert(dev);
97
98     struct v_inode* devnod = vfs_i_find(dnode->super_block, dev->dev_id);
99     if (!devnod) {
100         if ((devnod = vfs_i_alloc(dnode->super_block))) {
101             devnod->id = dev->dev_id;
102             devnod->data = dev;
103             devnod->itype = devfs_get_itype(dev);
104
105             vfs_i_addhash(devnod);
106         } else {
107             return ENOMEM;
108         }
109     }
110
111     vfs_assign_inode(dnode, devnod);
112     return 0;
113 }
114
115 int
116 devfs_dirlookup(struct v_inode* this, struct v_dnode* dnode)
117 {
118     struct device* dev =
119       device_getbyhname((struct device*)this->data, &dnode->name);
120     if (!dev) {
121         return ENOENT;
122     }
123     return devfs_mknod(dnode, dev);
124 }
125
126 int
127 devfs_readdir(struct v_file* file, struct dir_context* dctx)
128 {
129     struct device* dev =
130       device_getbyoffset((struct device*)(file->inode->data), dctx->index);
131     if (!dev) {
132         return 0;
133     }
134     dctx->read_complete_callback(
135       dctx, dev->name.value, dev->name.len, devfs_get_dtype(dev));
136     return 1;
137 }
138
139 void
140 devfs_init_inode(struct v_superblock* vsb, struct v_inode* inode)
141 {
142     inode->ops = &devfs_inode_ops;
143     inode->default_fops = &devfs_file_ops;
144 }
145
146 int
147 devfs_mount(struct v_superblock* vsb, struct v_dnode* mount_point)
148 {
149     vsb->ops.init_inode = devfs_init_inode;
150
151     struct v_inode* rootnod = vfs_i_alloc(vsb);
152
153     if (!rootnod) {
154         return ENOMEM;
155     }
156
157     rootnod->id = -1;
158     rootnod->itype = VFS_IFDIR;
159
160     vfs_i_addhash(rootnod);
161     vfs_assign_inode(mount_point, rootnod);
162
163     return 0;
164 }
165
166 int
167 devfs_unmount(struct v_superblock* vsb)
168 {
169     return 0;
170 }
171
172 void
173 devfs_init()
174 {
175     struct filesystem* fs = fsm_new_fs("devfs", 5);
176     fsm_register(fs);
177     fs->mount = devfs_mount;
178     fs->unmount = devfs_unmount;
179 }
180
181 struct v_inode_ops devfs_inode_ops = { .dir_lookup = devfs_dirlookup,
182                                        .open = default_inode_open,
183                                        .mkdir = default_inode_mkdir,
184                                        .rmdir = default_inode_rmdir };
185
186 struct v_file_ops devfs_file_ops = { .close = default_file_close,
187                                      .read = devfs_read,
188                                      .read_page = devfs_read_page,
189                                      .write = devfs_write,
190                                      .write_page = devfs_write_page,
191                                      .seek = default_file_seek,
192                                      .readdir = devfs_readdir };