dev: implement driver objects to organise and identify devices
This commit is contained in:
@@ -22,7 +22,7 @@ kern_status_t acpi_init(void)
|
|||||||
acpi_dev->b_ops = &acpi_ops;
|
acpi_dev->b_ops = &acpi_ops;
|
||||||
snprintf(base->dev_name, sizeof base->dev_name, "acpi");
|
snprintf(base->dev_name, sizeof base->dev_name, "acpi");
|
||||||
|
|
||||||
device_register(base, root_device());
|
device_register(base, system_driver(), root_device());
|
||||||
|
|
||||||
return KERN_OK;
|
return KERN_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include <socks/pmap.h>
|
#include <socks/pmap.h>
|
||||||
#include <socks/device.h>
|
#include <socks/device.h>
|
||||||
|
#include <socks/kext.h>
|
||||||
#include <socks/clock.h>
|
#include <socks/clock.h>
|
||||||
#include <socks/types.h>
|
#include <socks/types.h>
|
||||||
#include <socks/object.h>
|
#include <socks/object.h>
|
||||||
@@ -79,6 +80,8 @@ int ml_init(uintptr_t arg)
|
|||||||
vm_bootstrap(vm_zones, sizeof vm_zones / sizeof vm_zones[0]);
|
vm_bootstrap(vm_zones, sizeof vm_zones / sizeof vm_zones[0]);
|
||||||
|
|
||||||
object_bootstrap();
|
object_bootstrap();
|
||||||
|
init_kernel_kext();
|
||||||
|
|
||||||
sched_init();
|
sched_init();
|
||||||
|
|
||||||
device_init();
|
device_init();
|
||||||
|
|||||||
@@ -8,5 +8,6 @@ struct block_device *block_device_create(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
dev->dev_type = DEV_TYPE_BLOCK;
|
dev->dev_type = DEV_TYPE_BLOCK;
|
||||||
|
|
||||||
return BLOCK_DEVICE(dev);
|
return BLOCK_DEVICE(dev);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,5 +8,6 @@ struct bus_device *bus_device_create(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
dev->dev_type = DEV_TYPE_BUS;
|
dev->dev_type = DEV_TYPE_BUS;
|
||||||
|
|
||||||
return BUS_DEVICE(dev);
|
return BUS_DEVICE(dev);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,5 +8,6 @@ struct char_device *char_device_create(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
dev->dev_type = DEV_TYPE_CHAR;
|
dev->dev_type = DEV_TYPE_CHAR;
|
||||||
|
|
||||||
return CHAR_DEVICE(dev);
|
return CHAR_DEVICE(dev);
|
||||||
}
|
}
|
||||||
|
|||||||
90
dev/core.c
90
dev/core.c
@@ -1,6 +1,7 @@
|
|||||||
#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/bitmap.h>
|
||||||
#include <socks/libc/stdio.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)
|
||||||
@@ -15,6 +16,8 @@ static kern_status_t device_object_query_name(struct object *, char out[OBJECT_N
|
|||||||
static kern_status_t device_object_get_child_at(struct object *, size_t, struct object **);
|
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 kern_status_t device_object_get_child_named(struct object *, const char *, struct object **);
|
||||||
|
|
||||||
|
extern kern_status_t init_driver_tree(void);
|
||||||
|
|
||||||
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),
|
||||||
@@ -42,36 +45,31 @@ static kern_status_t set_root_device(struct device *dev)
|
|||||||
return KERN_OK;
|
return KERN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static kern_status_t device_generate_name(struct device *dev)
|
|
||||||
{
|
|
||||||
switch (dev->dev_type) {
|
|
||||||
case DEV_TYPE_INPUT:
|
|
||||||
return input_device_generate_name(&dev->input);
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return KERN_UNSUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
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");
|
dev_folder = set_create("dev");
|
||||||
object_publish(global_namespace(), "/", dev_folder);
|
object_publish(global_namespace(), "/", dev_folder);
|
||||||
|
|
||||||
|
kern_status_t status = init_driver_tree();
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
struct bus_device *system_dev = bus_device_create();
|
struct bus_device *system_dev = bus_device_create();
|
||||||
struct device *system_dev_base = bus_device_base(system_dev);
|
struct device *system_dev_base = bus_device_base(system_dev);
|
||||||
snprintf(system_dev_base->dev_name, sizeof system_dev_base->dev_name, "system");
|
snprintf(system_dev_base->dev_name, sizeof system_dev_base->dev_name, "system");
|
||||||
|
__root_device = bus_device_base(system_dev);
|
||||||
set_root_device(system_dev_base);
|
|
||||||
|
|
||||||
struct bus_device *misc_dev = bus_device_create();
|
struct bus_device *misc_dev = bus_device_create();
|
||||||
struct device *misc_dev_base = bus_device_base(misc_dev);
|
struct device *misc_dev_base = bus_device_base(misc_dev);
|
||||||
snprintf(misc_dev_base->dev_name, sizeof misc_dev_base->dev_name, "misc");
|
snprintf(misc_dev_base->dev_name, sizeof misc_dev_base->dev_name, "misc");
|
||||||
__misc_device = misc_dev_base;
|
__misc_device = misc_dev_base;
|
||||||
|
|
||||||
device_register(__misc_device, __root_device);
|
struct driver *system = system_driver();
|
||||||
|
|
||||||
|
device_register(__root_device, system, NULL);
|
||||||
|
device_register(__misc_device, system, __root_device);
|
||||||
|
|
||||||
return KERN_OK;
|
return KERN_OK;
|
||||||
}
|
}
|
||||||
@@ -179,23 +177,11 @@ static kern_status_t device_object_get_child_named(struct object *obj, const cha
|
|||||||
return KERN_NO_ENTRY;
|
return KERN_NO_ENTRY;
|
||||||
}
|
}
|
||||||
|
|
||||||
kern_status_t device_register(struct device *dev, struct device *parent)
|
static kern_status_t add_device_to_parent(struct device *dev, struct device *parent)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
|
||||||
device_lock_irqsave(dev, &flags);
|
|
||||||
|
|
||||||
kern_status_t status = KERN_OK;
|
kern_status_t status = KERN_OK;
|
||||||
|
|
||||||
if (dev->dev_name[0] == 0) {
|
queue_foreach (struct device, child, &parent->dev_children, dev_childent) {
|
||||||
status = device_generate_name(dev);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status != KERN_OK) {
|
|
||||||
device_unlock_irqrestore(dev, flags);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
queue_foreach (struct device, child, &dev->dev_children, dev_childent) {
|
|
||||||
if (!strcmp(dev->dev_name, child->dev_name)) {
|
if (!strcmp(dev->dev_name, child->dev_name)) {
|
||||||
status = KERN_NAME_EXISTS;
|
status = KERN_NAME_EXISTS;
|
||||||
break;
|
break;
|
||||||
@@ -203,12 +189,56 @@ kern_status_t device_register(struct device *dev, struct device *parent)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (status != KERN_OK) {
|
if (status != KERN_OK) {
|
||||||
device_unlock_irqrestore(dev, flags);
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
queue_push_back(&parent->dev_children, &dev->dev_childent);
|
queue_push_back(&parent->dev_children, &dev->dev_childent);
|
||||||
|
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_status_t device_register(struct device *dev, struct driver *owner, struct device *parent)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
device_lock_irqsave(dev, &flags);
|
||||||
|
driver_lock(owner);
|
||||||
|
|
||||||
|
unsigned int minor = driver_alloc_minor(owner);
|
||||||
|
|
||||||
|
if (minor == DEV_MINOR_INVALID) {
|
||||||
|
driver_unlock(owner);
|
||||||
|
device_unlock_irqrestore(dev, flags);
|
||||||
|
/* TODO better error message for lack of resources? */
|
||||||
|
return KERN_BUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_status_t status = KERN_OK;
|
||||||
|
if (parent) {
|
||||||
|
status = add_device_to_parent(dev, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
driver_unlock(owner);
|
||||||
device_unlock_irqrestore(dev, flags);
|
device_unlock_irqrestore(dev, flags);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dev->dev_minor = minor;
|
||||||
|
dev->dev_owner = owner;
|
||||||
|
|
||||||
|
driver_add_device(owner, dev);
|
||||||
|
|
||||||
|
switch (dev->dev_type) {
|
||||||
|
case DEV_TYPE_INPUT:
|
||||||
|
status = input_device_register(INPUT_DEVICE(dev));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
driver_unlock(owner);
|
||||||
|
device_unlock_irqrestore(dev, flags);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|||||||
146
dev/driver.c
Normal file
146
dev/driver.c
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
#include <socks/device.h>
|
||||||
|
#include <socks/bitmap.h>
|
||||||
|
#include <socks/btree.h>
|
||||||
|
#include <socks/kext.h>
|
||||||
|
#include <socks/vm.h>
|
||||||
|
|
||||||
|
static struct vm_cache driver_cache = {
|
||||||
|
.c_name = "driver",
|
||||||
|
.c_obj_size = sizeof(struct driver),
|
||||||
|
};
|
||||||
|
|
||||||
|
static DECLARE_BITMAP(major_numbers, DEV_MAJOR_MAX);
|
||||||
|
static struct btree drivers;
|
||||||
|
static spin_lock_t drivers_lock = SPIN_LOCK_INIT;
|
||||||
|
|
||||||
|
static struct driver *__system_driver;
|
||||||
|
|
||||||
|
BTREE_DEFINE_SIMPLE_INSERT(struct driver, drv_ent, drv_major, put_driver)
|
||||||
|
BTREE_DEFINE_SIMPLE_GET(struct driver, unsigned int, drv_ent, drv_major, get_driver_by_major)
|
||||||
|
|
||||||
|
BTREE_DEFINE_SIMPLE_INSERT(struct device, dev_driverent, dev_minor, put_device)
|
||||||
|
BTREE_DEFINE_SIMPLE_GET(struct device, unsigned int, dev_driverent, dev_minor, get_device_by_minor)
|
||||||
|
|
||||||
|
kern_status_t init_driver_tree(void)
|
||||||
|
{
|
||||||
|
vm_cache_init(&driver_cache);
|
||||||
|
bitmap_set(major_numbers, 0);
|
||||||
|
|
||||||
|
__system_driver = driver_create(kernel_kext(), "system");
|
||||||
|
driver_register(__system_driver);
|
||||||
|
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct driver *driver_create(struct kext *self, const char *name)
|
||||||
|
{
|
||||||
|
if (!self || !name) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct driver *driver = vm_cache_alloc(&driver_cache, 0);
|
||||||
|
if (!driver) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
driver->drv_owner = self;
|
||||||
|
strncpy(driver->drv_name, name, sizeof driver->drv_name - 1);
|
||||||
|
driver->drv_name[sizeof driver->drv_name - 1] = 0;
|
||||||
|
|
||||||
|
bitmap_set(driver->drv_minors, DEV_MINOR_INVALID);
|
||||||
|
|
||||||
|
return driver;
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_status_t driver_destroy(struct driver *driver)
|
||||||
|
{
|
||||||
|
if (btree_first(&driver->drv_children)) {
|
||||||
|
return KERN_BUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return KERN_UNIMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_status_t driver_register(struct driver *driver)
|
||||||
|
{
|
||||||
|
if (driver->drv_major != DEV_MAJOR_INVALID) {
|
||||||
|
return KERN_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long flags;
|
||||||
|
spin_lock_irqsave(&drivers_lock, &flags);
|
||||||
|
|
||||||
|
struct btree_node *cur = btree_first(&drivers);
|
||||||
|
while (cur) {
|
||||||
|
struct driver *cur_driver = BTREE_CONTAINER(struct driver, drv_ent, cur);
|
||||||
|
if (driver->drv_owner == cur_driver->drv_owner && !strcmp(driver->drv_name, cur_driver->drv_name)) {
|
||||||
|
spin_unlock_irqrestore(&drivers_lock, flags);
|
||||||
|
return KERN_NAME_EXISTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
cur = btree_next(cur);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long major = bitmap_lowest_clear(major_numbers, DEV_MAJOR_MAX);
|
||||||
|
bitmap_set(major_numbers, major);
|
||||||
|
|
||||||
|
driver->drv_major = major;
|
||||||
|
put_driver(&drivers, driver);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&drivers_lock, flags);
|
||||||
|
return KERN_UNIMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_status_t driver_unregister(struct driver *driver)
|
||||||
|
{
|
||||||
|
if (driver->drv_major == DEV_MAJOR_INVALID) {
|
||||||
|
return KERN_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long flags;
|
||||||
|
spin_lock_irqsave(&drivers_lock, &flags);
|
||||||
|
|
||||||
|
btree_delete(&drivers, &driver->drv_ent);
|
||||||
|
bitmap_clear(major_numbers, driver->drv_major);
|
||||||
|
driver->drv_major = DEV_MAJOR_INVALID;
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&drivers_lock, flags);
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int driver_alloc_minor(struct driver *driver)
|
||||||
|
{
|
||||||
|
unsigned int minor = bitmap_lowest_clear(driver->drv_minors, DEV_MINOR_MAX);
|
||||||
|
if (minor == BITMAP_NPOS) {
|
||||||
|
return DEV_MINOR_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
bitmap_set(driver->drv_minors, minor);
|
||||||
|
return minor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void driver_free_minor(struct driver *driver, unsigned int minor)
|
||||||
|
{
|
||||||
|
bitmap_clear(driver->drv_minors, minor);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct driver *system_driver(void)
|
||||||
|
{
|
||||||
|
return __system_driver;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct device *driver_get_device(struct driver *driver, unsigned int minor)
|
||||||
|
{
|
||||||
|
return get_device_by_minor(&driver->drv_children, minor);
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_status_t driver_add_device(struct driver *driver, struct device *dev)
|
||||||
|
{
|
||||||
|
if (get_device_by_minor(&driver->drv_children, dev->dev_minor)) {
|
||||||
|
return KERN_NAME_EXISTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
put_device(&driver->drv_children, dev);
|
||||||
|
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
32
dev/input.c
32
dev/input.c
@@ -21,14 +21,6 @@ struct input_device *input_device_create(void)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long flags;
|
|
||||||
spin_lock_irqsave(&input_device_ids_lock, &flags);
|
|
||||||
unsigned int id = bitmap_lowest_clear(input_device_ids, INPUT_DEVICE_MAX);
|
|
||||||
bitmap_set(input_device_ids, id);
|
|
||||||
spin_unlock_irqrestore(&input_device_ids_lock, flags);
|
|
||||||
|
|
||||||
input_dev->i_id = id;
|
|
||||||
|
|
||||||
return INPUT_DEVICE(dev);
|
return INPUT_DEVICE(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,9 +55,27 @@ kern_status_t input_device_read(struct device *dev, void *buf, size_t size, size
|
|||||||
return KERN_OK;
|
return KERN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
kern_status_t input_device_generate_name(struct input_device *dev)
|
static kern_status_t generate_name(struct input_device *dev, char out[DEV_NAME_MAX])
|
||||||
{
|
{
|
||||||
struct device *d = input_device_base(dev);
|
snprintf(out, DEV_NAME_MAX, "input%u", dev->i_id);
|
||||||
snprintf(d->dev_name, sizeof d->dev_name, "input%u", dev->i_id);
|
|
||||||
return KERN_OK;
|
return KERN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kern_status_t input_device_register(struct input_device *dev)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
spin_lock_irqsave(&input_device_ids_lock, &flags);
|
||||||
|
unsigned int id = bitmap_lowest_clear(input_device_ids, INPUT_DEVICE_MAX);
|
||||||
|
bitmap_set(input_device_ids, id);
|
||||||
|
spin_unlock_irqrestore(&input_device_ids_lock, flags);
|
||||||
|
|
||||||
|
dev->i_id = id;
|
||||||
|
|
||||||
|
char name[DEV_NAME_MAX];
|
||||||
|
generate_name(dev, name);
|
||||||
|
char path[OBJECT_PATH_MAX];
|
||||||
|
snprintf(path, sizeof path, "/dev/input/%s", name);
|
||||||
|
|
||||||
|
struct device *base = input_device_base(dev);
|
||||||
|
return object_namespace_create_link(global_namespace(), path, &base->dev_base);
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,5 +8,6 @@ struct net_device *net_device_create(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
dev->dev_type = DEV_TYPE_NET;
|
dev->dev_type = DEV_TYPE_NET;
|
||||||
|
|
||||||
return NET_DEVICE(dev);
|
return NET_DEVICE(dev);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,9 @@
|
|||||||
#define SOCKS_DEVICE_H_
|
#define SOCKS_DEVICE_H_
|
||||||
|
|
||||||
#include <socks/queue.h>
|
#include <socks/queue.h>
|
||||||
|
#include <socks/btree.h>
|
||||||
#include <socks/status.h>
|
#include <socks/status.h>
|
||||||
|
#include <socks/bitmap.h>
|
||||||
#include <socks/object.h>
|
#include <socks/object.h>
|
||||||
#include <socks/ringbuffer.h>
|
#include <socks/ringbuffer.h>
|
||||||
|
|
||||||
@@ -10,17 +12,22 @@ struct device;
|
|||||||
struct input_event;
|
struct input_event;
|
||||||
|
|
||||||
#define DEV_NAME_MAX OBJECT_NAME_MAX
|
#define DEV_NAME_MAX OBJECT_NAME_MAX
|
||||||
|
#define DEV_MAJOR_MAX 1024
|
||||||
|
#define DEV_MINOR_MAX 1024
|
||||||
|
#define DEV_MAJOR_INVALID ((unsigned int)0)
|
||||||
|
#define DEV_MINOR_INVALID ((unsigned int)0)
|
||||||
|
|
||||||
#define INPUT_DEVICE_EVENT_QUEUE_SIZE 128
|
#define INPUT_DEVICE_EVENT_QUEUE_SIZE 128
|
||||||
#define INPUT_DEVICE_MAX 4096
|
#define INPUT_DEVICE_MAX 4096
|
||||||
|
|
||||||
#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)
|
||||||
#define INPUT_DEVICE(dev) ((dev)->dev_type == DEV_TYPE_INPUT ? &(dev)->input : NULL);
|
#define INPUT_DEVICE(dev) ((dev)->dev_type == DEV_TYPE_INPUT ? &(dev)->input : NULL)
|
||||||
#define BUS_DEVICE(dev) ((dev)->dev_type == DEV_TYPE_BUS ? &(dev)->bus : NULL);
|
#define BUS_DEVICE(dev) ((dev)->dev_type == DEV_TYPE_BUS ? &(dev)->bus : NULL)
|
||||||
|
|
||||||
enum device_type {
|
enum device_type {
|
||||||
|
DEV_TYPE_UNKNOWN = 0,
|
||||||
DEV_TYPE_BLOCK,
|
DEV_TYPE_BLOCK,
|
||||||
DEV_TYPE_CHAR,
|
DEV_TYPE_CHAR,
|
||||||
DEV_TYPE_NET,
|
DEV_TYPE_NET,
|
||||||
@@ -78,10 +85,14 @@ struct bus_device {
|
|||||||
|
|
||||||
struct device {
|
struct device {
|
||||||
struct object dev_base;
|
struct object dev_base;
|
||||||
|
unsigned int dev_minor;
|
||||||
|
|
||||||
enum device_type dev_type;
|
enum device_type dev_type;
|
||||||
struct device *dev_parent;
|
struct device *dev_parent;
|
||||||
|
struct driver *dev_owner;
|
||||||
struct queue dev_children;
|
struct queue dev_children;
|
||||||
struct queue_entry dev_childent;
|
struct queue_entry dev_childent;
|
||||||
|
struct btree_node dev_driverent;
|
||||||
char dev_name[DEV_NAME_MAX];
|
char dev_name[DEV_NAME_MAX];
|
||||||
|
|
||||||
void *dev_priv;
|
void *dev_priv;
|
||||||
@@ -95,19 +106,48 @@ struct device {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct driver;
|
||||||
|
|
||||||
|
struct driver_ops {
|
||||||
|
kern_status_t(*bind)(struct driver *, struct device *, struct device *);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct driver {
|
||||||
|
struct kext *drv_owner;
|
||||||
|
unsigned int drv_major;
|
||||||
|
DECLARE_BITMAP(drv_minors, DEV_MINOR_MAX);
|
||||||
|
char drv_name[DEV_NAME_MAX];
|
||||||
|
struct btree drv_children;
|
||||||
|
struct btree_node drv_ent;
|
||||||
|
spin_lock_t drv_lock;
|
||||||
|
|
||||||
|
void *drv_priv;
|
||||||
|
struct driver_ops *drv_ops;
|
||||||
|
};
|
||||||
|
|
||||||
extern kern_status_t device_init(void);
|
extern kern_status_t device_init(void);
|
||||||
extern struct device *root_device(void);
|
extern struct device *root_device(void);
|
||||||
extern struct device *misc_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(struct device *dev)
|
||||||
|
{
|
||||||
|
object_lock(&dev->dev_base);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void device_unlock(struct device *dev)
|
||||||
|
{
|
||||||
|
object_unlock(&dev->dev_base);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void device_lock_irqsave(struct device *dev, unsigned long *flags)
|
static inline void device_lock_irqsave(struct device *dev, unsigned long *flags)
|
||||||
{
|
{
|
||||||
object_lock(&dev->dev_base, flags);
|
object_lock_irqsave(&dev->dev_base, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void device_unlock_irqrestore(struct device *dev, unsigned long flags)
|
static inline void device_unlock_irqrestore(struct device *dev, unsigned long flags)
|
||||||
{
|
{
|
||||||
object_unlock(&dev->dev_base, flags);
|
object_unlock_irqrestore(&dev->dev_base, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern kern_status_t device_read(struct device *dev, void *buf, size_t size, size_t *bytes_read, socks_flags_t flags);
|
extern kern_status_t device_read(struct device *dev, void *buf, size_t size, size_t *bytes_read, socks_flags_t flags);
|
||||||
@@ -146,10 +186,40 @@ static inline struct device *bus_device_base(struct bus_device *dev)
|
|||||||
return (struct device *)((char *)dev - offsetof(struct device, bus));
|
return (struct device *)((char *)dev - offsetof(struct device, bus));
|
||||||
}
|
}
|
||||||
|
|
||||||
extern kern_status_t device_register(struct device *dev, struct device *parent);
|
extern kern_status_t device_register(struct device *dev, struct driver *owner, struct device *parent);
|
||||||
|
|
||||||
extern kern_status_t input_device_report_event(struct input_device *dev, const struct input_event *ev, bool noblock);
|
extern kern_status_t input_device_report_event(struct input_device *dev, const struct input_event *ev, bool noblock);
|
||||||
extern kern_status_t input_device_read(struct device *dev, void *buf, size_t size, size_t *bytes_read, socks_flags_t flags);
|
extern kern_status_t input_device_read(struct device *dev, void *buf, size_t size, size_t *bytes_read, socks_flags_t flags);
|
||||||
extern kern_status_t input_device_generate_name(struct input_device *dev);
|
extern kern_status_t input_device_register(struct input_device *dev);
|
||||||
|
|
||||||
|
extern struct driver *driver_create(struct kext *self, const char *name);
|
||||||
|
extern kern_status_t driver_destroy(struct driver *driver);
|
||||||
|
extern kern_status_t driver_register(struct driver *driver);
|
||||||
|
extern kern_status_t driver_unregister(struct driver *driver);
|
||||||
|
extern unsigned int driver_alloc_minor(struct driver *driver);
|
||||||
|
extern void driver_free_minor(struct driver *driver, unsigned int minor);
|
||||||
|
extern struct device *driver_get_device(struct driver *driver, unsigned int minor);
|
||||||
|
extern kern_status_t driver_add_device(struct driver *driver, struct device *dev);
|
||||||
|
extern struct driver *system_driver(void);
|
||||||
|
|
||||||
|
static inline void driver_lock(struct driver *driver)
|
||||||
|
{
|
||||||
|
spin_lock(&driver->drv_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void driver_unlock(struct driver *driver)
|
||||||
|
{
|
||||||
|
spin_unlock(&driver->drv_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void driver_lock_irqsave(struct driver *driver, unsigned long *flags)
|
||||||
|
{
|
||||||
|
spin_lock_irqsave(&driver->drv_lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void driver_unlock_irqrestore(struct driver *driver, unsigned long flags)
|
||||||
|
{
|
||||||
|
spin_unlock_irqrestore(&driver->drv_lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -86,6 +86,9 @@ struct kext {
|
|||||||
extern kern_status_t scan_internal_kexts(void);
|
extern kern_status_t scan_internal_kexts(void);
|
||||||
extern kern_status_t bring_internal_kexts_online(void);
|
extern kern_status_t bring_internal_kexts_online(void);
|
||||||
|
|
||||||
|
extern kern_status_t init_kernel_kext(void);
|
||||||
|
extern struct kext *kernel_kext(void);
|
||||||
|
|
||||||
extern kern_status_t kext_cache_init(void);
|
extern kern_status_t kext_cache_init(void);
|
||||||
extern struct kext *kext_alloc(void);
|
extern struct kext *kext_alloc(void);
|
||||||
extern void kext_release(struct kext *kext);
|
extern void kext_release(struct kext *kext);
|
||||||
|
|||||||
@@ -12,6 +12,9 @@ typedef __aligned(8) ml_hwlock_t spin_lock_t;
|
|||||||
|
|
||||||
#define SPIN_LOCK_INIT ML_HWLOCK_INIT
|
#define SPIN_LOCK_INIT ML_HWLOCK_INIT
|
||||||
|
|
||||||
|
#define spin_lock(lck) ml_hwlock_lock(lck);
|
||||||
|
#define spin_unlock(lck) ml_hwlock_unlock(lck);
|
||||||
|
|
||||||
#define spin_lock_irqsave(lck, flags) ml_hwlock_lock_irqsave(lck, flags);
|
#define spin_lock_irqsave(lck, flags) ml_hwlock_lock_irqsave(lck, flags);
|
||||||
#define spin_unlock_irqrestore(lck, flags) ml_hwlock_unlock_irqrestore(lck, flags);
|
#define spin_unlock_irqrestore(lck, flags) ml_hwlock_unlock_irqrestore(lck, flags);
|
||||||
|
|
||||||
|
|||||||
@@ -173,12 +173,12 @@ extern void end_charge_period(void);
|
|||||||
|
|
||||||
static inline void task_lock_irqsave(struct task *task, unsigned long *flags)
|
static inline void task_lock_irqsave(struct task *task, unsigned long *flags)
|
||||||
{
|
{
|
||||||
object_lock(&task->t_base, flags);
|
object_lock_irqsave(&task->t_base, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void task_unlock_irqrestore(struct task *task, unsigned long flags)
|
static inline void task_unlock_irqrestore(struct task *task, unsigned long flags)
|
||||||
{
|
{
|
||||||
object_unlock(&task->t_base, flags);
|
object_unlock_irqrestore(&task->t_base, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern struct thread *thread_alloc(void);
|
extern struct thread *thread_alloc(void);
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ typedef unsigned int kern_status_t;
|
|||||||
#define KERN_NO_MEMORY (5)
|
#define KERN_NO_MEMORY (5)
|
||||||
#define KERN_NO_ENTRY (6)
|
#define KERN_NO_ENTRY (6)
|
||||||
#define KERN_WOULD_BLOCK (7)
|
#define KERN_WOULD_BLOCK (7)
|
||||||
|
#define KERN_BUSY (8)
|
||||||
|
|
||||||
extern const char *kern_status_string(kern_status_t status);
|
extern const char *kern_status_string(kern_status_t status);
|
||||||
|
|
||||||
|
|||||||
20
init/main.c
20
init/main.c
@@ -182,31 +182,19 @@ void kernel_init(uintptr_t arg)
|
|||||||
|
|
||||||
printk("kernel_init() running on processor %u", this_cpu());
|
printk("kernel_init() running on processor %u", this_cpu());
|
||||||
|
|
||||||
run_all_tests();
|
|
||||||
|
|
||||||
create_kernel_thread(background_thread);
|
create_kernel_thread(background_thread);
|
||||||
|
|
||||||
struct object *kbd;
|
struct object *kbd;
|
||||||
status = object_namespace_get_object(global_namespace(), "/dev/system/misc/input0", &kbd);
|
|
||||||
|
run_all_tests();
|
||||||
|
|
||||||
|
status = object_namespace_get_object(global_namespace(), "/dev/input/input0", &kbd);
|
||||||
if (status != KERN_OK) {
|
if (status != KERN_OK) {
|
||||||
printk("no keyboard available");
|
printk("no keyboard available");
|
||||||
hang();
|
hang();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
struct device *kbd_dev = cast_to_device(kbd_obj);
|
|
||||||
if (!kbd_dev) {
|
|
||||||
printk("no keyboard available");
|
|
||||||
hang();
|
|
||||||
}
|
|
||||||
|
|
||||||
struct input_device *kbd = INPUT_DEVICE(kbd_dev);
|
|
||||||
if (!kbd) {
|
|
||||||
printk("no keyboard available");
|
|
||||||
hang();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
struct input_event ev;
|
struct input_event ev;
|
||||||
size_t r;
|
size_t r;
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ static const enum input_keycode *keymaps[] = {
|
|||||||
keymap_l4,
|
keymap_l4,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct driver *ps2_driver = NULL;
|
||||||
static struct input_device *keyboard = NULL, *mouse = NULL;
|
static struct input_device *keyboard = NULL, *mouse = NULL;
|
||||||
|
|
||||||
static void send_cmd(uint8_t cmd)
|
static void send_cmd(uint8_t cmd)
|
||||||
@@ -201,21 +202,28 @@ static int init_controller(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static kern_status_t create_devices(void)
|
static kern_status_t create_devices(struct kext *self)
|
||||||
{
|
{
|
||||||
|
ps2_driver = driver_create(self, "ps2");
|
||||||
|
if (!ps2_driver) {
|
||||||
|
return KERN_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
struct input_device *kbd = input_device_create();
|
struct input_device *kbd = input_device_create();
|
||||||
struct device *kbd_base = input_device_base(kbd);
|
struct device *kbd_base = input_device_base(kbd);
|
||||||
|
snprintf(kbd_base->dev_name, sizeof kbd_base->dev_name, "ps2kbd");
|
||||||
|
|
||||||
struct input_device *ms = input_device_create();
|
struct input_device *ms = input_device_create();
|
||||||
struct device *ms_base = input_device_base(ms);
|
struct device *ms_base = input_device_base(ms);
|
||||||
|
snprintf(ms_base->dev_name, sizeof ms_base->dev_name, "ps2mouse");
|
||||||
|
|
||||||
kern_status_t status = device_register(kbd_base, misc_device());
|
kern_status_t status = device_register(kbd_base, ps2_driver, misc_device());
|
||||||
if (status != KERN_OK) {
|
if (status != KERN_OK) {
|
||||||
/* TODO destroy devices */
|
/* TODO destroy devices */
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = device_register(ms_base, misc_device());
|
status = device_register(ms_base, ps2_driver, misc_device());
|
||||||
if (status != KERN_OK) {
|
if (status != KERN_OK) {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@@ -237,7 +245,7 @@ static kern_status_t online(struct kext *self)
|
|||||||
return KERN_UNSUPPORTED;
|
return KERN_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
kern_status_t status = create_devices();
|
kern_status_t status = create_devices(self);
|
||||||
if (status != KERN_OK) {
|
if (status != KERN_OK) {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,6 +74,11 @@ static kern_status_t create_kext_from_info(struct kext_info *info, struct kext *
|
|||||||
return KERN_OK;
|
return KERN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct kext *kernel_kext(void)
|
||||||
|
{
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
kern_status_t register_internal_kexts(void)
|
kern_status_t register_internal_kexts(void)
|
||||||
{
|
{
|
||||||
struct kext_info *cur = (struct kext_info *)__kexts_start;
|
struct kext_info *cur = (struct kext_info *)__kexts_start;
|
||||||
@@ -122,7 +127,7 @@ kern_status_t resolve_internal_dependencies(void)
|
|||||||
return KERN_OK;
|
return KERN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
kern_status_t scan_internal_kexts(void)
|
kern_status_t init_kernel_kext(void)
|
||||||
{
|
{
|
||||||
kext_cache_init();
|
kext_cache_init();
|
||||||
|
|
||||||
@@ -138,7 +143,11 @@ kern_status_t scan_internal_kexts(void)
|
|||||||
self->k_dependencies = NULL;
|
self->k_dependencies = NULL;
|
||||||
|
|
||||||
kext_register(self);
|
kext_register(self);
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_status_t scan_internal_kexts(void)
|
||||||
|
{
|
||||||
kern_status_t status = register_internal_kexts();
|
kern_status_t status = register_internal_kexts();
|
||||||
if (status != KERN_OK) {
|
if (status != KERN_OK) {
|
||||||
return status;
|
return status;
|
||||||
|
|||||||
Reference in New Issue
Block a user