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_defs.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(struct device_meta* dm)
70 int itype = VFS_IFDEV;
72 if (valid_device_subtype_ref(dm, DEV_CAT)) {
76 struct device* dev = resolve_device(dm);
77 int dev_if = dev->dev_type & DEV_MSKIF;
79 if (dev_if == DEV_IFVOL) {
80 itype |= VFS_IFVOLDEV;
83 // otherwise, the mapping is considered to be generic seq dev.
88 devfs_get_dtype(struct device_meta* dev)
90 if (valid_device_subtype_ref(dev, DEV_CAT)) {
97 devfs_mknod(struct v_dnode* dnode, struct device_meta* dev)
101 struct v_inode* devnod = vfs_i_find(dnode->super_block, dev->dev_uid);
103 if ((devnod = vfs_i_alloc(dnode->super_block))) {
104 devnod->id = dev->dev_uid;
106 devnod->itype = devfs_get_itype(dev);
108 vfs_i_addhash(devnod);
114 vfs_assign_inode(dnode, devnod);
119 devfs_dirlookup(struct v_inode* this, struct v_dnode* dnode)
121 void* data = this->data;
122 struct device_meta* rootdev = resolve_device_meta(data);
124 if (data && !rootdev) {
128 struct device_meta* dev =
129 device_getbyhname(rootdev, &dnode->name);
135 return devfs_mknod(dnode, dev);
139 devfs_readdir(struct v_file* file, struct dir_context* dctx)
141 void* data = file->inode->data;
142 struct device_meta* rootdev = resolve_device_meta(data);
144 if (data && !rootdev) {
148 if (fsapi_handle_pseudo_dirent(file, dctx)) {
152 struct device_meta* dev =
153 device_getbyoffset(rootdev, file->f_pos - 2);
159 dctx->read_complete_callback(
160 dctx, dev->name.value, dev->name.len, devfs_get_dtype(dev));
165 devfs_init_inode(struct v_superblock* vsb, struct v_inode* inode)
167 inode->ops = &devfs_inode_ops;
168 inode->default_fops = &devfs_file_ops;
172 devfs_mount(struct v_superblock* vsb, struct v_dnode* mount_point)
174 vsb->ops.init_inode = devfs_init_inode;
176 struct v_inode* rootnod = vfs_i_alloc(vsb);
183 rootnod->itype = VFS_IFDIR;
185 vfs_i_addhash(rootnod);
186 vfs_assign_inode(mount_point, rootnod);
192 devfs_unmount(struct v_superblock* vsb)
200 struct filesystem* fs;
201 fs = fsapi_fs_declare("devfs", FSTYPE_PSEUDO);
203 fsapi_fs_set_mntops(fs, devfs_mount, devfs_unmount);
204 fsapi_fs_finalise(fs);
206 EXPORT_FILE_SYSTEM(devfs, devfs_init);
208 struct v_inode_ops devfs_inode_ops = { .dir_lookup = devfs_dirlookup,
209 .open = default_inode_open,
210 .mkdir = default_inode_mkdir,
211 .rmdir = default_inode_rmdir };
213 struct v_file_ops devfs_file_ops = { .close = default_file_close,
215 .read_page = devfs_read_page,
216 .write = devfs_write,
217 .write_page = devfs_write_page,
218 .seek = default_file_seek,
219 .readdir = devfs_readdir };