1 #include <lunaix/device.h>
2 #include <lunaix/fs/api.h>
3 #include <lunaix/fs/devfs.h>
4 #include <lunaix/spike.h>
6 #include <usr/lunaix/dirent.h>
8 extern struct v_inode_ops devfs_inode_ops;
9 extern struct v_file_ops devfs_file_ops;
12 devfs_read(struct v_inode* inode, void* buffer, size_t len, size_t fpos)
16 struct device* dev = resolve_device(inode->data);
18 if (!dev || !dev->ops.read) {
22 return dev->ops.read(dev, buffer, fpos, len);
26 devfs_write(struct v_inode* inode, void* buffer, size_t len, size_t fpos)
30 struct device* dev = resolve_device(inode->data);
32 if (!dev || !dev->ops.write) {
36 return dev->ops.write(dev, buffer, fpos, len);
40 devfs_read_page(struct v_inode* inode, void* buffer, size_t fpos)
44 struct device* dev = resolve_device(inode->data);
46 if (!dev || !dev->ops.read_page) {
50 return dev->ops.read_page(dev, buffer, fpos);
54 devfs_write_page(struct v_inode* inode, void* buffer, size_t fpos)
58 struct device* dev = resolve_device(inode->data);
60 if (!dev || !dev->ops.read_page) {
64 return dev->ops.read_page(dev, buffer, fpos);
68 devfs_get_itype(morph_t* obj)
70 int itype = VFS_IFDEV;
72 if (morph_type_of(obj, devcat_morpher)) {
76 struct device* dev = resolve_device(obj);
82 int dev_if = dev->dev_type & DEV_MSKIF;
83 if (dev_if == DEV_IFVOL) {
84 itype |= VFS_IFVOLDEV;
87 // otherwise, the mapping is considered to be generic seq dev.
92 devfs_get_dtype(morph_t* dev_morph)
94 if (morph_type_of(dev_morph, devcat_morpher)) {
100 static inline morph_t*
101 __try_resolve(struct v_inode* inode)
104 return dev_object_root;
107 return resolve_device_morph(inode->data);
111 devfs_mknod(struct v_dnode* dnode, morph_t* obj)
113 struct v_inode* devnod;
117 devnod = vfs_i_find(dnode->super_block, morpher_uid(obj));
119 if ((devnod = vfs_i_alloc(dnode->super_block))) {
120 devnod->id = morpher_uid(obj);
121 devnod->data = changeling_ref(obj);
122 devnod->itype = devfs_get_itype(obj);
124 vfs_i_addhash(devnod);
130 vfs_assign_inode(dnode, devnod);
135 devfs_dirlookup(struct v_inode* this, struct v_dnode* dnode)
137 morph_t *mobj, *root;
139 root = __try_resolve(this);
144 mobj = changeling_find(root, &dnode->name);
149 return devfs_mknod(dnode, mobj);
153 devfs_readdir(struct v_file* file, struct dir_context* dctx)
155 morph_t *mobj, *root;
157 root = __try_resolve(file->inode);
162 if (fsapi_handle_pseudo_dirent(file, dctx)) {
166 mobj = changeling_get_at(root, file->f_pos - 2);
171 dctx->read_complete_callback(dctx,
172 mobj->name.value, mobj->name.len,
173 devfs_get_dtype(mobj));
178 devfs_init_inode(struct v_superblock* vsb, struct v_inode* inode)
180 inode->ops = &devfs_inode_ops;
181 inode->default_fops = &devfs_file_ops;
183 // we set default access right to be 0775.
184 // TODO need a way to allow this to be changed
186 fsapi_inode_setaccess(inode, FSACL_DEFAULT);
187 fsapi_inode_setowner(inode, 0, 0);
191 devfs_mount(struct v_superblock* vsb, struct v_dnode* mount_point)
193 vsb->ops.init_inode = devfs_init_inode;
195 struct v_inode* rootnod = vfs_i_alloc(vsb);
202 rootnod->itype = VFS_IFDIR;
204 vfs_i_addhash(rootnod);
205 vfs_assign_inode(mount_point, rootnod);
211 devfs_unmount(struct v_superblock* vsb)
219 struct filesystem* fs;
220 fs = fsapi_fs_declare("devfs", FSTYPE_PSEUDO);
222 fsapi_fs_set_mntops(fs, devfs_mount, devfs_unmount);
223 fsapi_fs_finalise(fs);
225 EXPORT_FILE_SYSTEM(devfs, devfs_init);
227 struct v_inode_ops devfs_inode_ops = { .dir_lookup = devfs_dirlookup,
228 .open = default_inode_open,
229 .mkdir = default_inode_mkdir,
230 .rmdir = default_inode_rmdir };
232 struct v_file_ops devfs_file_ops = { .close = default_file_close,
234 .read_page = devfs_read_page,
235 .write = devfs_write,
236 .write_page = devfs_write_page,
237 .seek = default_file_seek,
238 .readdir = devfs_readdir };