X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/96cf56ea15a22b8b362aac6c3ab202d2608e9151..96e23fa3c6eabf8a6efebac24b740c5d4a2a1050:/lunaix-os/kernel/device/devfs.c diff --git a/lunaix-os/kernel/device/devfs.c b/lunaix-os/kernel/device/devfs.c new file mode 100644 index 0000000..73abac7 --- /dev/null +++ b/lunaix-os/kernel/device/devfs.c @@ -0,0 +1,147 @@ +#include +#include +#include +#include + +extern struct v_inode_ops devfs_inode_ops; +extern struct v_file_ops devfs_file_ops; + +int +devfs_read(struct v_inode* inode, void* buffer, size_t len, size_t fpos) +{ + assert(inode->data); + + struct device* dev = (struct device*)inode->data; + + if (!dev->read) { + return ENOTSUP; + } + + return dev->read(dev, buffer, fpos, len); +} + +int +devfs_write(struct v_inode* inode, void* buffer, size_t len, size_t fpos) +{ + assert(inode->data); + + struct device* dev = (struct device*)inode->data; + + if (!dev->write) { + return ENOTSUP; + } + + return dev->write(dev, buffer, fpos, len); +} + +int +devfs_get_itype(struct device* dev) +{ + int itype = VFS_IFFILE; + int dev_if = dev->dev_type & DEV_MSKIF; + if (dev_if == DEV_IFCAT) { + itype = VFS_IFDIR; + } else if (dev_if == DEV_IFVOL) { + itype |= VFS_IFVOLDEV; + } else { + itype |= VFS_IFSEQDEV; + } + return itype; +} + +int +devfs_mknod(struct v_dnode* dnode, struct device* dev) +{ + assert(dev); + + struct v_inode* devnod = vfs_i_find(dnode->super_block, dev->dev_id); + if (!devnod) { + if ((devnod = vfs_i_alloc(dnode->super_block))) { + devnod->id = dev->dev_id; + devnod->data = dev; + devnod->itype = devfs_get_itype(dev); + + vfs_i_addhash(devnod); + } else { + return ENOMEM; + } + } + + vfs_assign_inode(dnode, devnod); + return 0; +} + +int +devfs_dirlookup(struct v_inode* this, struct v_dnode* dnode) +{ + struct device* dev = device_getbyname(this->data, &dnode->name); + if (!dev) { + return ENOENT; + } + return devfs_mknod(dnode, dev); +} + +int +devfs_readdir(struct v_file* file, struct dir_context* dctx) +{ + struct device* dev = device_getbyoffset(file->inode->data, dctx->index); + if (!dev) { + return 0; + } + dctx->read_complete_callback( + dctx, dev->name.value, dev->name.len, devfs_get_itype(dev)); + return 1; +} + +void +devfs_init_inode(struct v_superblock* vsb, struct v_inode* inode) +{ + inode->ops = &devfs_inode_ops; + inode->default_fops = &devfs_file_ops; +} + +int +devfs_mount(struct v_superblock* vsb, struct v_dnode* mount_point) +{ + vsb->ops.init_inode = devfs_init_inode; + + struct v_inode* rootnod = vfs_i_alloc(vsb); + + if (!rootnod) { + return ENOMEM; + } + + rootnod->id = -1; + rootnod->itype = VFS_IFDIR; + + vfs_i_addhash(rootnod); + vfs_assign_inode(mount_point, rootnod); + + return 0; +} + +int +devfs_unmount(struct v_superblock* vsb) +{ + return 0; +} + +void +devfs_init() +{ + struct filesystem* fs = fsm_new_fs("devfs", 5); + fsm_register(fs); + fs->mount = devfs_mount; + fs->unmount = devfs_unmount; +} + +struct v_inode_ops devfs_inode_ops = { .dir_lookup = devfs_dirlookup, + .open = default_inode_open, + .mkdir = default_inode_mkdir, + .rmdir = default_inode_rmdir }; + +struct v_file_ops devfs_file_ops = { .close = default_file_close, + .read = devfs_read, + .write = devfs_write, + .seek = default_file_seek, + .readdir = devfs_readdir }; \ No newline at end of file