Nucleus
Barry Device driver interface 7864e7f (3 years, 2 months ago)
diff --git a/drivers/driver.c b/drivers/driver.c
new file mode 100644
index 0000000..5309c1a
--- /dev/null
+++ b/drivers/driver.c
@@ -0,0 +1,70 @@
+/*
+ * This file controls the Device Driver Interface. It allows a driver to
+ * register a set of file operations and a major number. This number can later
+ * be used to find the correct operations for a device file.
+ */
+
+#include <nucleus/driver.h>
+#include <nucleus/object.h>
+#include <nucleus/vfs.h>
+
+/* Structure for a Driver object */
+struct Driver {
+ Object obj;
+ unsigned short major;
+ FileOps *ops;
+};
+
+/* Driver object type */
+ObjectType driverType = {
+ .name = "DRIVER",
+ .size = sizeof(Driver),
+};
+
+static ObjectList *drivers;
+
+/* Compare the major numbers of two Drivers */
+static int
+compare_driver(void *a, void *b)
+{
+ Driver *da = a, *db = b;
+ return (da->major - db->major);
+}
+
+/* Register a driver */
+unsigned short
+register_driver(unsigned short major, FileOps *ops)
+{
+ if (!drivers)
+ drivers = create_list(&driverType, LIST_ORDERED,
+ compare_driver);
+ Driver *driver = new(&driverType);
+ driver->major = major;
+ driver->ops = ops;
+
+ /* Ensure major is unique */
+ if (!driver->major)
+ driver->major = 1;
+ Driver *collision;
+ foreach (drivers, collision) {
+ if (driver->major == collision->major)
+ driver->major++;
+ else if (driver->major < collision->major)
+ break;
+ }
+
+ add(drivers, driver);
+ return driver->major;
+}
+
+/* Find a driver from a major number */
+FileOps *
+find_driver(unsigned short major)
+{
+ Driver *driver;
+ foreach (drivers, driver) {
+ if (driver->major == major)
+ break;
+ }
+ return driver->ops;
+}