dev: implement object callbacks for devices. add misc device
This commit is contained in:
134
dev/core.c
134
dev/core.c
@@ -1,34 +1,72 @@
|
|||||||
#include <socks/status.h>
|
#include <socks/status.h>
|
||||||
#include <socks/object.h>
|
#include <socks/object.h>
|
||||||
#include <socks/device.h>
|
#include <socks/device.h>
|
||||||
|
#include <socks/libc/stdio.h>
|
||||||
|
|
||||||
#define DEVICE_CAST(p) OBJECT_C_CAST(struct device, dev_base, &device_type, p)
|
#define DEVICE_CAST(p) OBJECT_C_CAST(struct device, dev_base, &device_type, p)
|
||||||
|
|
||||||
static struct device *root_device = NULL;
|
static struct object *dev_folder = NULL;
|
||||||
|
static struct device *__root_device = NULL;
|
||||||
|
static struct device *__misc_device = NULL;
|
||||||
|
static kern_status_t device_object_destroy(struct object *);
|
||||||
|
static kern_status_t device_object_query_name(struct object *, char out[OBJECT_NAME_MAX]);
|
||||||
|
static kern_status_t device_object_get_child_at(struct object *, size_t, struct object **);
|
||||||
|
static kern_status_t device_object_get_child_named(struct object *, const char *, struct object **);
|
||||||
static struct object_type device_type = {
|
static struct object_type device_type = {
|
||||||
.ob_name = "device",
|
.ob_name = "device",
|
||||||
.ob_size = sizeof(struct device),
|
.ob_size = sizeof(struct device),
|
||||||
.ob_ops = {
|
.ob_ops = {
|
||||||
.destroy = NULL,
|
.destroy = device_object_destroy,
|
||||||
|
.query_name = device_object_query_name,
|
||||||
|
.get_at = device_object_get_child_at,
|
||||||
|
.get_named = device_object_get_child_named,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static kern_status_t set_root_device(struct device *dev)
|
||||||
|
{
|
||||||
|
if (__root_device) {
|
||||||
|
set_remove_object(dev_folder, &__root_device->dev_base);
|
||||||
|
object_deref(&__root_device->dev_base);
|
||||||
|
}
|
||||||
|
|
||||||
|
object_ref(&dev->dev_base);
|
||||||
|
set_add_object(dev_folder, &dev->dev_base);
|
||||||
|
__root_device = dev;
|
||||||
|
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
kern_status_t device_init(void)
|
kern_status_t device_init(void)
|
||||||
{
|
{
|
||||||
object_type_register(&device_type);
|
object_type_register(&device_type);
|
||||||
|
dev_folder = set_create("dev");
|
||||||
|
object_publish(global_namespace(), "/", dev_folder);
|
||||||
|
|
||||||
|
struct bus_device *system_dev = bus_device_create();
|
||||||
|
struct device *system_dev_base = bus_device_base(system_dev);
|
||||||
|
snprintf(system_dev_base->dev_name, sizeof system_dev_base->dev_name, "system");
|
||||||
|
|
||||||
|
set_root_device(system_dev_base);
|
||||||
|
|
||||||
|
struct bus_device *misc_dev = bus_device_create();
|
||||||
|
struct device *misc_dev_base = bus_device_base(misc_dev);
|
||||||
|
snprintf(misc_dev_base->dev_name, sizeof misc_dev_base->dev_name, "misc");
|
||||||
|
__misc_device = misc_dev_base;
|
||||||
|
|
||||||
|
device_register(__misc_device, __root_device);
|
||||||
|
|
||||||
return KERN_OK;
|
return KERN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
kern_status_t set_root_device(struct device *dev)
|
struct device *root_device(void)
|
||||||
{
|
{
|
||||||
if (root_device) {
|
return __root_device;
|
||||||
object_deref(&root_device->dev_base);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
object_ref(&dev->dev_base);
|
struct device *misc_device(void)
|
||||||
root_device = dev;
|
{
|
||||||
|
return __misc_device;
|
||||||
return KERN_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct device *device_alloc(void)
|
struct device *device_alloc(void)
|
||||||
@@ -40,3 +78,79 @@ struct device *device_alloc(void)
|
|||||||
|
|
||||||
return DEVICE_CAST(dev_object);
|
return DEVICE_CAST(dev_object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static kern_status_t device_object_destroy(struct object *obj)
|
||||||
|
{
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static kern_status_t device_object_query_name(struct object *obj, char out[OBJECT_NAME_MAX])
|
||||||
|
{
|
||||||
|
struct device *dev = DEVICE_CAST(obj);
|
||||||
|
if (!dev) {
|
||||||
|
return KERN_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
strncpy(out, dev->dev_name, OBJECT_NAME_MAX - 1);
|
||||||
|
out[OBJECT_NAME_MAX - 1] = 0;
|
||||||
|
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static kern_status_t device_object_get_child_at(struct object *obj, size_t at, struct object **out)
|
||||||
|
{
|
||||||
|
struct device *dev = DEVICE_CAST(obj);
|
||||||
|
size_t i = 0;
|
||||||
|
queue_foreach(struct device, child, &dev->dev_children, dev_childent) {
|
||||||
|
if (i == at) {
|
||||||
|
*out = object_ref(&child->dev_base);
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return KERN_NO_ENTRY;
|
||||||
|
}
|
||||||
|
|
||||||
|
static kern_status_t device_object_get_child_named(struct object *obj, const char *name, struct object **out)
|
||||||
|
{
|
||||||
|
struct device *dev = DEVICE_CAST(obj);
|
||||||
|
if (!dev) {
|
||||||
|
return KERN_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
queue_foreach(struct device, child, &dev->dev_children, dev_childent) {
|
||||||
|
if (!strcmp(child->dev_name, name)) {
|
||||||
|
*out = object_ref(&child->dev_base);
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return KERN_NO_ENTRY;
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_status_t device_register(struct device *dev, struct device *parent)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
device_lock_irqsave(dev, &flags);
|
||||||
|
|
||||||
|
kern_status_t status = KERN_OK;
|
||||||
|
|
||||||
|
queue_foreach (struct device, child, &dev->dev_children, dev_childent) {
|
||||||
|
if (!strcmp(dev->dev_name, child->dev_name)) {
|
||||||
|
status = KERN_NAME_EXISTS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
device_unlock_irqrestore(dev, flags);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
queue_push_back(&parent->dev_children, &dev->dev_childent);
|
||||||
|
|
||||||
|
device_unlock_irqrestore(dev, flags);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
|
|
||||||
struct device;
|
struct device;
|
||||||
|
|
||||||
|
#define DEV_NAME_MAX OBJECT_NAME_MAX
|
||||||
|
|
||||||
#define BLOCK_DEVICE(dev) ((dev)->dev_type == DEV_TYPE_BLOCK ? &(dev)->blk : NULL);
|
#define BLOCK_DEVICE(dev) ((dev)->dev_type == DEV_TYPE_BLOCK ? &(dev)->blk : NULL);
|
||||||
#define CHAR_DEVICE(dev) ((dev)->dev_type == DEV_TYPE_CHAR ? &(dev)->chr : NULL);
|
#define CHAR_DEVICE(dev) ((dev)->dev_type == DEV_TYPE_CHAR ? &(dev)->chr : NULL);
|
||||||
#define NET_DEVICE(dev) ((dev)->dev_type == DEV_TYPE_NET ? &(dev)->net : NULL);
|
#define NET_DEVICE(dev) ((dev)->dev_type == DEV_TYPE_NET ? &(dev)->net : NULL);
|
||||||
@@ -73,6 +75,7 @@ struct device {
|
|||||||
struct device *dev_parent;
|
struct device *dev_parent;
|
||||||
struct queue dev_children;
|
struct queue dev_children;
|
||||||
struct queue_entry dev_childent;
|
struct queue_entry dev_childent;
|
||||||
|
char dev_name[DEV_NAME_MAX];
|
||||||
|
|
||||||
void *dev_priv;
|
void *dev_priv;
|
||||||
|
|
||||||
@@ -86,9 +89,19 @@ struct device {
|
|||||||
};
|
};
|
||||||
|
|
||||||
extern kern_status_t device_init(void);
|
extern kern_status_t device_init(void);
|
||||||
extern kern_status_t set_root_device(struct device *dev);
|
extern struct device *root_device(void);
|
||||||
|
extern struct device *misc_device(void);
|
||||||
|
|
||||||
extern struct device *device_alloc(void);
|
extern struct device *device_alloc(void);
|
||||||
|
static inline void device_lock_irqsave(struct device *dev, unsigned long *flags)
|
||||||
|
{
|
||||||
|
object_lock(&dev->dev_base, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void device_unlock_irqrestore(struct device *dev, unsigned long flags)
|
||||||
|
{
|
||||||
|
object_unlock(&dev->dev_base, flags);
|
||||||
|
}
|
||||||
|
|
||||||
extern struct char_device *char_device_create(void);
|
extern struct char_device *char_device_create(void);
|
||||||
extern struct block_device *block_device_create(void);
|
extern struct block_device *block_device_create(void);
|
||||||
|
|||||||
Reference in New Issue
Block a user