dev: implement generic devices
generic devices don't have a type (char, block, etc) and are created by bus drivers to represent the device until a suitable driver is found. generic devices are registered by the bus driver. once a more suitable driver is found, that driver will re-register the device under itself.
This commit is contained in:
@@ -11,3 +11,9 @@ struct block_device *block_device_create(void)
|
|||||||
|
|
||||||
return BLOCK_DEVICE(dev);
|
return BLOCK_DEVICE(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct block_device *block_device_from_generic(struct device *dev)
|
||||||
|
{
|
||||||
|
dev->dev_type = DEV_TYPE_BLOCK;
|
||||||
|
return BLOCK_DEVICE(dev);
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,3 +11,9 @@ struct char_device *char_device_create(void)
|
|||||||
|
|
||||||
return CHAR_DEVICE(dev);
|
return CHAR_DEVICE(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct char_device *char_device_from_generic(struct device *dev)
|
||||||
|
{
|
||||||
|
dev->dev_type = DEV_TYPE_CHAR;
|
||||||
|
return CHAR_DEVICE(dev);
|
||||||
|
}
|
||||||
|
|||||||
13
dev/core.c
13
dev/core.c
@@ -228,6 +228,19 @@ kern_status_t device_register(struct device *dev, struct driver *owner, struct d
|
|||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
device_lock_irqsave(dev, &flags);
|
device_lock_irqsave(dev, &flags);
|
||||||
|
|
||||||
|
if (dev->dev_owner) {
|
||||||
|
struct driver *prev_owner = dev->dev_owner;
|
||||||
|
|
||||||
|
/* migrate device to new driver */
|
||||||
|
driver_lock(prev_owner);
|
||||||
|
driver_remove_device(prev_owner, dev);
|
||||||
|
driver_free_minor(prev_owner, dev->dev_minor);
|
||||||
|
dev->dev_minor = DEV_MINOR_INVALID;
|
||||||
|
dev->dev_owner = NULL;
|
||||||
|
driver_unlock(prev_owner);
|
||||||
|
}
|
||||||
|
|
||||||
driver_lock(owner);
|
driver_lock(owner);
|
||||||
|
|
||||||
if (owner->drv_major == DEV_MAJOR_INVALID) {
|
if (owner->drv_major == DEV_MAJOR_INVALID) {
|
||||||
|
|||||||
43
dev/driver.c
43
dev/driver.c
@@ -44,13 +44,10 @@ struct driver *driver_create(struct kext *self, const char *name)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(driver, 0x0, sizeof *driver);
|
if (driver_init(driver, self, name) != KERN_OK) {
|
||||||
|
vm_cache_free(&driver_cache, driver);
|
||||||
driver->drv_owner = self;
|
return NULL;
|
||||||
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;
|
return driver;
|
||||||
}
|
}
|
||||||
@@ -61,6 +58,30 @@ kern_status_t driver_destroy(struct driver *driver)
|
|||||||
return KERN_BUSY;
|
return KERN_BUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kern_status_t status = driver_deinit(driver);
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
vm_cache_free(&driver_cache, driver);
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_status_t driver_init(struct driver *driver, struct kext *self, const char *name)
|
||||||
|
{
|
||||||
|
memset(driver, 0x0, sizeof *driver);
|
||||||
|
|
||||||
|
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 KERN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_status_t driver_deinit(struct driver *driver)
|
||||||
|
{
|
||||||
|
/* TODO */
|
||||||
return KERN_UNIMPLEMENTED;
|
return KERN_UNIMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,7 +112,7 @@ kern_status_t driver_register(struct driver *driver)
|
|||||||
put_driver(&drivers, driver);
|
put_driver(&drivers, driver);
|
||||||
|
|
||||||
spin_unlock_irqrestore(&drivers_lock, flags);
|
spin_unlock_irqrestore(&drivers_lock, flags);
|
||||||
return KERN_UNIMPLEMENTED;
|
return KERN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
kern_status_t driver_unregister(struct driver *driver)
|
kern_status_t driver_unregister(struct driver *driver)
|
||||||
@@ -147,3 +168,9 @@ kern_status_t driver_add_device(struct driver *driver, struct device *dev)
|
|||||||
|
|
||||||
return KERN_OK;
|
return KERN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kern_status_t driver_remove_device(struct driver *driver, struct device *dev)
|
||||||
|
{
|
||||||
|
btree_delete(&driver->drv_children, &dev->dev_driverent);
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
|
|||||||
31
dev/fb.c
31
dev/fb.c
@@ -17,6 +17,12 @@ struct framebuffer_device *framebuffer_device_create(void)
|
|||||||
return FRAMEBUFFER_DEVICE(dev);
|
return FRAMEBUFFER_DEVICE(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct framebuffer_device *framebuffer_device_from_generic(struct device *dev)
|
||||||
|
{
|
||||||
|
dev->dev_type = DEV_TYPE_FRAMEBUFFER;
|
||||||
|
return FRAMEBUFFER_DEVICE(dev);
|
||||||
|
}
|
||||||
|
|
||||||
static kern_status_t generate_name(struct framebuffer_device *dev, char out[DEV_NAME_MAX])
|
static kern_status_t generate_name(struct framebuffer_device *dev, char out[DEV_NAME_MAX])
|
||||||
{
|
{
|
||||||
snprintf(out, DEV_NAME_MAX, "fb%u", dev->fb_id);
|
snprintf(out, DEV_NAME_MAX, "fb%u", dev->fb_id);
|
||||||
@@ -42,6 +48,31 @@ kern_status_t framebuffer_device_register(struct device *dev)
|
|||||||
return object_namespace_create_link(global_namespace(), path, &dev->dev_base);
|
return object_namespace_create_link(global_namespace(), path, &dev->dev_base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kern_status_t framebuffer_get_varinfo(struct device *dev, struct framebuffer_varinfo *varinfo)
|
||||||
|
{
|
||||||
|
struct framebuffer_device *fbdev = FRAMEBUFFER_DEVICE(dev);
|
||||||
|
if (!fbdev) {
|
||||||
|
return KERN_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(varinfo, &fbdev->fb_varinfo, sizeof *varinfo);
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_status_t framebuffer_set_varinfo(struct device *dev, const struct framebuffer_varinfo *varinfo)
|
||||||
|
{
|
||||||
|
struct framebuffer_device *fbdev = FRAMEBUFFER_DEVICE(dev);
|
||||||
|
if (!fbdev) {
|
||||||
|
return KERN_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fbdev->fb_ops || !fbdev->fb_ops->set_varinfo) {
|
||||||
|
return KERN_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fbdev->fb_ops->set_varinfo(dev, varinfo);
|
||||||
|
}
|
||||||
|
|
||||||
struct device_type_ops framebuffer_type_ops = {
|
struct device_type_ops framebuffer_type_ops = {
|
||||||
.register_device = framebuffer_device_register,
|
.register_device = framebuffer_device_register,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -24,6 +24,12 @@ struct input_device *input_device_create(void)
|
|||||||
return INPUT_DEVICE(dev);
|
return INPUT_DEVICE(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct input_device *input_device_from_generic(struct device *dev)
|
||||||
|
{
|
||||||
|
dev->dev_type = DEV_TYPE_INPUT;
|
||||||
|
return INPUT_DEVICE(dev);
|
||||||
|
}
|
||||||
|
|
||||||
kern_status_t input_device_report_event(struct input_device *dev, const struct input_event *ev, bool noblock)
|
kern_status_t input_device_report_event(struct input_device *dev, const struct input_event *ev, bool noblock)
|
||||||
{
|
{
|
||||||
struct ringbuffer *event_queue = &dev->i_events;
|
struct ringbuffer *event_queue = &dev->i_events;
|
||||||
|
|||||||
@@ -11,3 +11,9 @@ struct net_device *net_device_create(void)
|
|||||||
|
|
||||||
return NET_DEVICE(dev);
|
return NET_DEVICE(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct net_device *net_device_from_generic(struct device *dev)
|
||||||
|
{
|
||||||
|
dev->dev_type = DEV_TYPE_NET;
|
||||||
|
return NET_DEVICE(dev);
|
||||||
|
}
|
||||||
|
|||||||
@@ -115,6 +115,7 @@ struct device {
|
|||||||
struct btree_node dev_driverent;
|
struct btree_node dev_driverent;
|
||||||
char dev_name[DEV_NAME_MAX];
|
char dev_name[DEV_NAME_MAX];
|
||||||
|
|
||||||
|
void *dev_bus_priv;
|
||||||
void *dev_priv;
|
void *dev_priv;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
@@ -130,7 +131,12 @@ struct device {
|
|||||||
struct driver;
|
struct driver;
|
||||||
|
|
||||||
struct driver_ops {
|
struct driver_ops {
|
||||||
|
/* called when a bus driver finds a device for this driver to manage. */
|
||||||
kern_status_t(*bind)(struct driver *, struct device *, struct device *);
|
kern_status_t(*bind)(struct driver *, struct device *, struct device *);
|
||||||
|
/* called when driver is registered. */
|
||||||
|
kern_status_t(*install)(struct driver *);
|
||||||
|
/* called when driver is unregistered. */
|
||||||
|
kern_status_t(*uninstall)(struct driver *);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct driver {
|
struct driver {
|
||||||
@@ -184,6 +190,13 @@ extern struct input_device *input_device_create(void);
|
|||||||
extern struct bus_device *bus_device_create(void);
|
extern struct bus_device *bus_device_create(void);
|
||||||
extern struct framebuffer_device *framebuffer_device_create(void);
|
extern struct framebuffer_device *framebuffer_device_create(void);
|
||||||
|
|
||||||
|
extern struct char_device *char_device_from_generic(struct device *dev);
|
||||||
|
extern struct block_device *block_device_from_generic(struct device *dev);
|
||||||
|
extern struct net_device *net_device_from_generic(struct device *dev);
|
||||||
|
extern struct input_device *input_device_from_generic(struct device *dev);
|
||||||
|
extern struct bus_device *bus_device_from_generic(struct device *dev);
|
||||||
|
extern struct framebuffer_device *framebuffer_device_from_generic(struct device *dev);
|
||||||
|
|
||||||
static inline struct device *char_device_base(struct char_device *dev)
|
static inline struct device *char_device_base(struct char_device *dev)
|
||||||
{
|
{
|
||||||
return (struct device *)((char *)dev - offsetof(struct device, chr));
|
return (struct device *)((char *)dev - offsetof(struct device, chr));
|
||||||
@@ -221,14 +234,20 @@ extern kern_status_t input_device_read(struct device *dev, void *buf, size_t siz
|
|||||||
|
|
||||||
extern struct driver *driver_create(struct kext *self, const char *name);
|
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_destroy(struct driver *driver);
|
||||||
|
extern kern_status_t driver_init(struct driver *driver, struct kext *self, const char *name);
|
||||||
|
extern kern_status_t driver_deinit(struct driver *driver);
|
||||||
extern kern_status_t driver_register(struct driver *driver);
|
extern kern_status_t driver_register(struct driver *driver);
|
||||||
extern kern_status_t driver_unregister(struct driver *driver);
|
extern kern_status_t driver_unregister(struct driver *driver);
|
||||||
extern unsigned int driver_alloc_minor(struct driver *driver);
|
extern unsigned int driver_alloc_minor(struct driver *driver);
|
||||||
extern void driver_free_minor(struct driver *driver, unsigned int minor);
|
extern void driver_free_minor(struct driver *driver, unsigned int minor);
|
||||||
extern struct device *driver_get_device(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 kern_status_t driver_add_device(struct driver *driver, struct device *dev);
|
||||||
|
extern kern_status_t driver_remove_device(struct driver *driver, struct device *dev);
|
||||||
extern struct driver *system_driver(void);
|
extern struct driver *system_driver(void);
|
||||||
|
|
||||||
|
extern kern_status_t framebuffer_get_varinfo(struct device *dev, struct framebuffer_varinfo *varinfo);
|
||||||
|
extern kern_status_t framebuffer_set_varinfo(struct device *dev, const struct framebuffer_varinfo *varinfo);
|
||||||
|
|
||||||
static inline void driver_lock(struct driver *driver)
|
static inline void driver_lock(struct driver *driver)
|
||||||
{
|
{
|
||||||
spin_lock(&driver->drv_lock);
|
spin_lock(&driver->drv_lock);
|
||||||
|
|||||||
Reference in New Issue
Block a user