X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/f6ab9c9ababa2cf6e5c723b83ffb9362094054e8..6f6da1abb22dff69dbb710bd2fd9d95f083f2b43:/lunaix-os/kernel/device/device.c?ds=inline diff --git a/lunaix-os/kernel/device/device.c b/lunaix-os/kernel/device/device.c index 979b461..d26808a 100644 --- a/lunaix-os/kernel/device/device.c +++ b/lunaix-os/kernel/device/device.c @@ -1,4 +1,4 @@ -#include + #include #include #include @@ -8,19 +8,61 @@ #include #include +#include + +#include +#include + static DEFINE_LLIST(root_list); -static volatile dev_t devid = 0; +static volatile u32_t devid = 0; + +struct devclass default_devclass = {}; + +void +device_prepare(struct device* dev, struct devclass* class) +{ + dev->magic = DEV_STRUCT_MAGIC; + dev->dev_uid = devid++; + dev->class = class ? class : &default_devclass; + + llist_init_head(&dev->children); +} + +static void +device_setname_vargs(struct device* dev, char* fmt, va_list args) +{ + size_t strlen = + __ksprintf_internal(dev->name_val, fmt, DEVICE_NAME_SIZE, args); + + dev->name = HSTR(dev->name_val, strlen); + + hstr_rehash(&dev->name, HSTR_FULL_HASH); +} + +void +device_setname(struct device* dev, char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + + device_setname_vargs(dev, fmt, args); + + va_end(args); +} struct device* -device_add(struct device* parent, - void* underlay, - char* name_fmt, - u32_t type, - va_list args) +device_add_vargs(struct device* parent, + void* underlay, + char* name_fmt, + u32_t type, + struct devclass* class, + va_list args) { struct device* dev = vzalloc(sizeof(struct device)); + device_prepare(dev, class); + if (parent) { assert((parent->dev_type & DEV_MSKIF) == DEV_IFCAT); llist_append(&parent->children, &dev->siblings); @@ -28,56 +70,81 @@ device_add(struct device* parent, llist_append(&root_list, &dev->siblings); } - size_t strlen = - __ksprintf_internal(dev->name_val, name_fmt, DEVICE_NAME_SIZE, args); + if (name_fmt) { + device_setname_vargs(dev, name_fmt, args); + } - dev->magic = DEV_STRUCT_MAGIC; - 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_init_head(&dev->children); + return dev; +} + +struct device* +device_add(struct device* parent, + struct devclass* class, + void* underlay, + u32_t type, + char* name_fmt, + ...) +{ + va_list args; + va_start(args, name_fmt); + + struct device* dev = + device_add_vargs(parent, underlay, name_fmt, type, class, args); + va_end(args); return dev; } struct device* -device_addsys(struct device* parent, void* underlay, char* name_fmt, ...) +device_addsys(struct device* parent, + struct devclass* class, + 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); + device_add_vargs(parent, underlay, name_fmt, DEV_IFSYS, class, args); va_end(args); return dev; } struct device* -device_addseq(struct device* parent, void* underlay, char* name_fmt, ...) +device_addseq(struct device* parent, + struct devclass* class, + 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); + device_add_vargs(parent, underlay, name_fmt, DEV_IFSEQ, class, args); va_end(args); return dev; } struct device* -device_addvol(struct device* parent, void* underlay, char* name_fmt, ...) +device_addvol(struct device* parent, + struct devclass* class, + 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); + device_add_vargs(parent, underlay, name_fmt, DEV_IFVOL, class, args); va_end(args); return dev; @@ -89,20 +156,21 @@ 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); + struct device* dev = + device_add_vargs(parent, NULL, name_fmt, DEV_IFCAT, NULL, args); va_end(args); return dev; } struct device* -device_getbyid(struct llist_header* devlist, dev_t id) +device_getbyid(struct llist_header* devlist, u32_t id) { devlist = devlist ? devlist : &root_list; struct device *pos, *n; llist_for_each(pos, n, devlist, siblings) { - if (pos->dev_id == id) { + if (pos->dev_uid == id) { return pos; } } @@ -156,26 +224,50 @@ device_getbyoffset(struct device* root_dev, int offset) return NULL; } +static inline void +device_populate_info(struct device* dev, struct dev_info* devinfo) +{ + devinfo->dev_id.meta = dev->class->meta; + devinfo->dev_id.device = dev->class->device; + devinfo->dev_id.variant = dev->class->variant; + + if (!devinfo->dev_name.buf) { + return; + } + + struct device_def* def = devdef_byclass(dev->class); + size_t buflen = devinfo->dev_name.buf_len; + + strncpy(devinfo->dev_name.buf, def->name, buflen); + devinfo->dev_name.buf[buflen - 1] = 0; +} + __DEFINE_LXSYSCALL3(int, ioctl, int, fd, int, req, va_list, args) { - int errno; + int errno = -1; struct v_fd* fd_s; - if ((errno = vfs_getfd(fd, &fd_s))) { + 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; + errno &= ENODEV; goto done; } + if (req == DEVIOIDENT) { + struct dev_info* devinfo = va_arg(args, struct dev_info*); + device_populate_info(dev, devinfo); + errno = 0; + } + 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);