X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/8c06c883e7b13c115d5ff207f79d4b68fccd5ad6..35a7d633d3f16c1e0539af6ca5d8e7482926cd93:/lunaix-os/kernel/device/device.c diff --git a/lunaix-os/kernel/device/device.c b/lunaix-os/kernel/device/device.c index 8765755..9af8ac3 100644 --- a/lunaix-os/kernel/device/device.c +++ b/lunaix-os/kernel/device/device.c @@ -1,4 +1,3 @@ - #include #include #include @@ -7,73 +6,67 @@ #include #include #include +#include #include #include static DEFINE_LLIST(root_list); -static volatile u32_t devid = 0; - -struct devclass default_devclass = {}; +morph_t* device_mobj_root; void -device_setname_vargs(struct device* dev, char* fmt, va_list args) +device_setname_vargs(struct device_meta* dev, char* fmt, va_list args) { - size_t strlen = - ksnprintfv(dev->name_val, fmt, DEVICE_NAME_SIZE, args); - - dev->name = HSTR(dev->name_val, strlen); - - hstr_rehash(&dev->name, HSTR_FULL_HASH); + ksnprintfv(dev->name_val, fmt, DEVICE_NAME_SIZE, args); + changeling_setname(dev_mobj(dev), dev->name_val); } void -device_register(struct device* dev, struct devclass* class, char* fmt, ...) +device_register_generic(struct device_meta* devm, struct devclass* class, + char* fmt, ...) { va_list args; + morph_t* morphed, *parent; + + morphed = &devm->mobj; va_start(args, fmt); if (fmt) { - device_setname_vargs(dev, fmt, args); + device_setname_vargs(devm, fmt, args); } - if (class) { - dev->ident = (struct devident){ .fn_grp = class->fn_grp, - .unique = DEV_UNIQUE(class->device, - class->variant) }; + if (class && morph_type_of(morphed, device_morpher)) + { + struct device* dev = to_dev(devm); + dev->ident = (struct devident) { + .fn_grp = class->fn_grp, + .unique = DEV_UNIQUE(class->device, class->variant) + }; } - dev->dev_uid = devid++; - - struct device* parent = dev->parent; + parent = morphed->parent; if (parent) { - assert((parent->dev_type & DEV_MSKIF) == DEV_IFCAT); - llist_append(&parent->children, &dev->siblings); - } else { - llist_append(&root_list, &dev->siblings); + changeling_attach(parent, morphed); } va_end(args); } void -device_create(struct device* dev, - struct device* parent, - u32_t type, - void* underlay) +device_create(struct device* dev, struct device_meta* parent, + u32_t type, void* underlay) { - dev->magic = DEV_STRUCT_MAGIC; dev->underlay = underlay; dev->dev_type = type; - dev->parent = parent; - llist_init_head(&dev->children); + llist_init_head(&dev->potentium); mutex_init(&dev->lock); + iopoll_init_evt_q(&dev->pollers); } struct device* -device_alloc(struct device* parent, u32_t type, void* underlay) +device_alloc(struct device_meta* parent, u32_t type, void* underlay) { struct device* dev = vzalloc(sizeof(struct device)); @@ -82,12 +75,43 @@ device_alloc(struct device* parent, u32_t type, void* underlay) } device_create(dev, parent, type, underlay); + changeling_morph(dev_morph(parent), dev->mobj, NULL, device_morpher); + + return dev; +} + +struct device_alias* +device_alloc_alias(struct device_meta* parent, struct device_meta* aliased) +{ + struct device_alias* dev = vzalloc(sizeof(struct device_alias)); + + if (!dev) { + return NULL; + } + + dev->alias = aliased; + changeling_ref(dev_mobj(aliased)); + changeling_morph(dev_morph(parent), dev->mobj, NULL, devalias_morpher); + + return dev; +} + +struct device_cat* +device_alloc_cat(struct device_meta* parent) +{ + struct device_cat* dev = vzalloc(sizeof(struct device_cat)); + + if (!dev) { + return NULL; + } + + changeling_morph(dev_morph(parent), dev->mobj, NULL, devcat_morpher); return dev; } void -device_setname(struct device* dev, char* fmt, ...) +device_setname(struct device_meta* dev, char* fmt, ...) { va_list args; va_start(args, fmt); @@ -97,82 +121,44 @@ device_setname(struct device* dev, char* fmt, ...) va_end(args); } -struct device* -device_addcat(struct device* parent, char* name_fmt, ...) +struct device_cat* +device_addcat(struct device_meta* parent, char* name_fmt, ...) { va_list args; va_start(args, name_fmt); - struct device* dev = device_alloc(parent, DEV_IFCAT, NULL); + struct device_cat* dev = device_alloc_cat(parent); - device_setname_vargs(dev, name_fmt, args); - device_register(dev, NULL, NULL); + device_setname_vargs(dev_meta(dev), name_fmt, args); + device_register_generic(dev_meta(dev), NULL, NULL); va_end(args); return dev; } -struct device* -device_getbyid(struct llist_header* devlist, u32_t id) +struct device_alias* +device_addalias(struct device_meta* parent, + struct device_meta* aliased, char* name_fmt, ...) { - devlist = devlist ? devlist : &root_list; - struct device *pos, *n; - llist_for_each(pos, n, devlist, siblings) - { - if (pos->dev_uid == id) { - return pos; - } - } - - return NULL; -} - -struct device* -device_getbyhname(struct device* root_dev, struct hstr* name) -{ - struct llist_header* devlist = root_dev ? &root_dev->children : &root_list; - struct device *pos, *n; - llist_for_each(pos, n, devlist, siblings) - { - if (HSTR_EQ(&pos->name, name)) { - return pos; - } - } + va_list args; + va_start(args, name_fmt); - return NULL; -} + struct device_alias* dev = device_alloc_alias(parent, aliased); -struct device* -device_getbyname(struct device* root_dev, const char* name, size_t len) -{ - struct hstr hname = HSTR(name, len); - hstr_rehash(&hname, HSTR_FULL_HASH); + device_setname_vargs(dev_meta(dev), name_fmt, args); + device_register_generic(dev_meta(dev), NULL, NULL); - return device_getbyhname(root_dev, &hname); + va_end(args); + return dev; } void -device_remove(struct device* dev) +device_remove(struct device_meta* dev) { - llist_delete(&dev->siblings); + changeling_isolate(&dev->mobj); vfree(dev); } -struct device* -device_getbyoffset(struct device* root_dev, int offset) -{ - struct llist_header* devlist = root_dev ? &root_dev->children : &root_list; - struct device *pos, *n; - int off = 0; - llist_for_each(pos, n, devlist, siblings) - { - if (off++ >= offset) { - return pos; - } - } - return NULL; -} - void device_populate_info(struct device* dev, struct dev_info* devinfo) { @@ -190,28 +176,110 @@ device_populate_info(struct device* dev, struct dev_info* devinfo) devinfo->dev_name.buf[buflen - 1] = 0; } -struct device* -device_cast(void* obj) +morph_t* +resolve_device_morph(void* maybe_dev) +{ + struct device_alias* da = NULL; + morph_t *morphed; + + morphed = morphed_ptr(maybe_dev); + + if (!is_changeling(morphed)) { + return NULL; + } + + if (morph_type_of(morphed, device_morpher)) + { + return morphed; + } + + if (morph_type_of(morphed, devcat_morpher)) + { + return morphed; + } + + while(morph_type_of(morphed, devalias_morpher)) + { + da = changeling_reveal(morphed, devalias_morpher); + morphed = &da->alias->mobj; + } + + return da ? morphed : NULL; +} + +void +device_alert_poller(struct device* dev, int poll_evt) +{ + dev->poll_evflags = poll_evt; + iopoll_wake_pollers(&dev->pollers); +} + +void +device_chain_loader(struct device_def* def, devdef_ldfn fn) +{ + struct device_ldfn_chain* node; + + node = valloc(sizeof(*node)); + node->load = fn; + + if (!def->load_chain) { + node->chain = NULL; + } + else { + node->chain = def->load_chain; + } + + def->load_chain = node; +} + +void +device_chain_load_once(struct device_def* def) { - struct device* dev = (struct device*)obj; - if (dev && dev->magic == DEV_STRUCT_MAGIC) { - return dev; + struct device_ldfn_chain *node, *next; + + if (def->load) { + def->load(def); } - return NULL; + node = def->load_chain; + def->load_chain = NULL; + + while (node) + { + node->load(def); + next = node->chain; + vfree(node); + + node = next; + } + + if (def->flags.no_default_realm) { + return; + } + + if (!def->create) { + return; + } + + def->create(def, NULL); + } -__DEFINE_LXSYSCALL3(int, ioctl, int, fd, int, req, va_list, args) +__DEFINE_LXSYSCALL3(int, ioctl, int, fd, int, req, sc_va_list, _args) { int errno = -1; struct v_fd* fd_s; + va_list args; + + convert_valist(&args, _args); + if ((errno &= vfs_getfd(fd, &fd_s))) { goto done; } - struct device* dev = (struct device*)fd_s->file->inode->data; - if (dev->magic != DEV_STRUCT_MAGIC) { - errno &= ENODEV; + struct device* dev = resolve_device(fd_s->file->inode->data); + if (!dev) { + errno = ENODEV; goto done; } @@ -222,12 +290,19 @@ __DEFINE_LXSYSCALL3(int, ioctl, int, fd, int, req, va_list, args) } if (!dev->ops.exec_cmd) { - errno &= ENOTSUP; + errno = ENOTSUP; goto done; } - errno &= dev->ops.exec_cmd(dev, req, args); + errno = dev->ops.exec_cmd(dev, req, args); done: return DO_STATUS_OR_RETURN(errno); -} \ No newline at end of file +} + +static void +__device_subsys_init() +{ + device_mobj_root = changeling_spawn(NULL, "devices"); +} +owloysius_fetch_init(__device_subsys_init, on_sysconf); \ No newline at end of file