chore: fixes and refactorings.
#include <lunaix/ds/hstr.h>
#include <lunaix/ds/llist.h>
+#define DEV_MSKIF 0x00000003
+
+#define DEV_IFVOL 0x0 // volumetric (block) device
+#define DEV_IFSEQ 0x1 // sequential (character) device
+#define DEV_IFCAT 0x2 // a device category (as device groupping)
+
typedef unsigned int dev_t;
struct device
{
- struct llist_header dev_list;
+ struct llist_header siblings;
struct device* parent;
struct hstr name;
dev_t dev_id;
+ int dev_type;
char name_val[DEVICE_NAME_SIZE];
void* underlay;
- void* fs_node;
int (*read)(struct device* dev, void* buf, size_t offset, size_t len);
int (*write)(struct device* dev, void* buf, size_t offset, size_t len);
};
-void
-device_init();
-
struct device*
device_addseq(struct device* parent, void* underlay, char* name_fmt, ...);
struct device*
device_addvol(struct device* parent, void* underlay, char* name_fmt, ...);
+struct device*
+device_addcat(struct device* parent, char* name_fmt, ...);
+
void
device_remove(struct device* dev);
+struct device*
+device_getbyid(struct llist_header* devlist, dev_t id);
+
+struct device*
+device_getbyname(struct llist_header* devlist, struct hstr* name);
+
+struct device*
+device_getbyoffset(struct llist_header* devlist, int pos);
+
#endif /* __LUNAIX_DEVICE_H */
return elem->next == elem && elem->prev == elem;
}
+#define DEFINE_LLIST(name) \
+ struct llist_header name = (struct llist_header) \
+ { \
+ .prev = &name, .next = &name \
+ }
+
/**
* list_entry - get the struct for this entry
* @ptr: the &struct list_head pointer.
--- /dev/null
+#ifndef __LUNAIX_DEVFS_H
+#define __LUNAIX_DEVFS_H
+
+void
+devfs_init();
+
+#endif /* __LUNAIX_DEVFS_H */
+++ /dev/null
-#include <klibc/stdio.h>
-#include <lunaix/device.h>
-#include <lunaix/fs/twifs.h>
-#include <lunaix/mm/valloc.h>
-
-struct llist_header dev_list;
-
-static struct twifs_node* dev_root;
-
-int
-__dev_read(struct v_inode* inode, void* buffer, size_t len, size_t fpos);
-
-int
-__dev_write(struct v_inode* inode, void* buffer, size_t len, size_t fpos);
-
-void
-device_init()
-{
- dev_root = twifs_toplevel_node("dev", 3, 0);
-
- llist_init_head(&dev_list);
-}
-
-struct device*
-__device_add(struct device* parent,
- void* underlay,
- char* name_fmt,
- uint32_t type,
- va_list args)
-{
- struct device* dev = vzalloc(sizeof(struct device));
-
- size_t strlen =
- __sprintf_internal(dev->name_val, name_fmt, DEVICE_NAME_SIZE, args);
-
- dev->name = HSTR(dev->name_val, strlen);
- dev->parent = parent;
- dev->underlay = underlay;
-
- hstr_rehash(&dev->name, HSTR_FULL_HASH);
- llist_append(&dev_list, &dev->dev_list);
-
- struct twifs_node* dev_node =
- twifs_file_node(dev_root, dev->name_val, strlen, type);
- dev_node->data = dev;
- dev_node->ops.read = __dev_read;
- dev_node->ops.write = __dev_write;
-
- dev->fs_node = dev_node;
-
- return dev;
-}
-
-struct device*
-device_addseq(struct device* parent, void* underlay, char* name_fmt, ...)
-{
- va_list args;
- va_start(args, name_fmt);
-
- struct device* dev =
- __device_add(parent, underlay, name_fmt, VFS_IFSEQDEV, args);
-
- va_end(args);
- return dev;
-}
-
-struct device*
-device_addvol(struct device* parent, void* underlay, char* name_fmt, ...)
-{
- va_list args;
- va_start(args, name_fmt);
-
- struct device* dev =
- __device_add(parent, underlay, name_fmt, VFS_IFVOLDEV, args);
-
- va_end(args);
- return dev;
-}
-
-int
-__dev_read(struct v_inode* inode, void* buffer, size_t len, size_t fpos)
-{
- struct twifs_node* dev_node = (struct twifs_node*)inode->data;
- struct device* dev = (struct device*)dev_node->data;
-
- if (!dev->read) {
- return ENOTSUP;
- }
- return dev->read(dev, buffer, fpos, len);
-}
-
-int
-__dev_write(struct v_inode* inode, void* buffer, size_t len, size_t fpos)
-{
- struct twifs_node* dev_node = (struct twifs_node*)inode->data;
- struct device* dev = (struct device*)dev_node->data;
-
- if (!dev->write) {
- return ENOTSUP;
- }
- return dev->write(dev, buffer, fpos, len);
-}
-
-void
-device_remove(struct device* dev)
-{
- llist_delete(&dev->dev_list);
- twifs_rm_node((struct twifs_node*)dev->fs_node);
- vfree(dev);
-}
\ No newline at end of file
--- /dev/null
+#include <lunaix/device.h>
+#include <lunaix/fs.h>
+#include <lunaix/fs/devfs.h>
+#include <lunaix/spike.h>
+
+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
--- /dev/null
+#include <klibc/stdio.h>
+#include <lunaix/device.h>
+#include <lunaix/fs/twifs.h>
+#include <lunaix/mm/valloc.h>
+#include <lunaix/spike.h>
+
+static DEFINE_LLIST(root_list);
+
+static volatile dev_t devid = 0;
+
+struct device*
+__device_add(struct device* parent,
+ void* underlay,
+ char* name_fmt,
+ uint32_t type,
+ va_list args)
+{
+ struct device* dev = vzalloc(sizeof(struct device));
+
+ if (parent) {
+ assert((parent->dev_type & DEV_MSKIF) == DEV_IFCAT);
+ }
+
+ size_t strlen =
+ __sprintf_internal(dev->name_val, name_fmt, DEVICE_NAME_SIZE, args);
+
+ dev->dev_id = devid++;
+ dev->name = HSTR(dev->name_val, strlen);
+ dev->parent = parent;
+ dev->underlay = underlay;
+ dev->dev_type = type;
+
+ hstr_rehash(&dev->name, HSTR_FULL_HASH);
+ llist_append(&root_list, &dev->siblings);
+
+ return dev;
+}
+
+struct device*
+device_addseq(struct device* parent, void* underlay, char* name_fmt, ...)
+{
+ va_list args;
+ va_start(args, name_fmt);
+
+ struct device* dev =
+ __device_add(parent, underlay, name_fmt, DEV_IFSEQ, args);
+
+ va_end(args);
+ return dev;
+}
+
+struct device*
+device_addvol(struct device* parent, void* underlay, char* name_fmt, ...)
+{
+ va_list args;
+ va_start(args, name_fmt);
+
+ struct device* dev =
+ __device_add(parent, underlay, name_fmt, DEV_IFVOL, args);
+
+ va_end(args);
+ return dev;
+}
+
+struct device*
+device_addcat(struct device* parent, char* name_fmt, ...)
+{
+ va_list args;
+ va_start(args, name_fmt);
+
+ struct device* dev = __device_add(parent, NULL, name_fmt, DEV_IFCAT, args);
+
+ va_end(args);
+ return dev;
+}
+
+struct device*
+device_getbyid(struct llist_header* devlist, dev_t id)
+{
+ devlist = devlist ? devlist : &root_list;
+ struct device *pos, *n;
+ llist_for_each(pos, n, devlist, siblings)
+ {
+ if (pos->dev_id == id) {
+ return pos;
+ }
+ }
+
+ return NULL;
+}
+
+struct device*
+device_getbyname(struct llist_header* devlist, struct hstr* name)
+{
+ devlist = devlist ? devlist : &root_list;
+ struct device *pos, *n;
+ llist_for_each(pos, n, devlist, siblings)
+ {
+ if (HSTR_EQ(&pos->name, name)) {
+ return pos;
+ }
+ }
+
+ return NULL;
+}
+
+void
+device_remove(struct device* dev)
+{
+ llist_delete(&dev->siblings);
+ vfree(dev);
+}
+
+struct device*
+device_getbyoffset(struct llist_header* devlist, int offset)
+{
+ devlist = devlist ? devlist : &root_list;
+ struct device *pos, *n;
+ int off = 0;
+ llist_for_each(pos, n, devlist, siblings)
+ {
+ if (off++ >= offset) {
+ return pos;
+ }
+ }
+ return NULL;
+}
\ No newline at end of file
#include <lunaix/fs.h>
+#include <lunaix/fs/devfs.h>
#include <lunaix/fs/ramfs.h>
#include <lunaix/fs/twifs.h>
{
ramfs_init();
twifs_init();
- // Add more fs implementation
+ devfs_init();
+
+ // ... more fs implementation
}
\ No newline at end of file
// By our convention.
// XXX could we do better?
- struct device* device = (struct device*)dev->data;
+ struct device* device = (struct device*)dev->inode->data;
if (!(dev->inode->itype & VFS_IFVOLDEV) || !device) {
errno = ENOTDEV;
if (parent) {
dnode->super_block = parent->super_block;
+ dnode->mnt = parent->mnt;
}
lru_use_one(dnode_lru, &dnode->lru);
cake_init();
valloc_init();
+ lxconsole_init();
+
vfs_init();
fsm_init();
- device_init();
-
if ((errno = vfs_mount_root("ramfs", NULL))) {
panickf("Fail to mount root. (errno=%d)", errno);
}
- // FIXME replace with more specific fs for device.
- vfs_mount("/dev", "twifs", NULL, MNT_RO);
-
- lxconsole_init();
+ vfs_mount("/dev", "devfs", NULL, 0);
+ vfs_mount("/sys", "twifs", NULL, MNT_RO);
sched_init();
#define USE_DEMO
// #define DEMO_SIGNAL
-#define DEMO_READDIR
-//#define DEMO_IOTEST
+//#define DEMO_READDIR
+#define DEMO_IOTEST
extern void
_pconsole_main();
#else
_lxinit_main();
#endif
+ _exit(0);
}
waitpid(p, 0, 0);