Nucleus
Barry Device driver interface 7864e7f (3 years, 2 months ago)
diff --git a/drivers/devices.c b/drivers/devices.c
index 19ec2e5..a5873df 100644
--- a/drivers/devices.c
+++ b/drivers/devices.c
@@ -50,7 +50,7 @@ init_pci_device(int bus, int dev, int func)
if (devices[d].vendor != vendor
|| devices[d].device != device)
continue;
- kprintf("PCI(%d,%d,%d) \"%s\"", bus, dev, func,
+ kprintf("PCI(%d,%d,%d) %s", bus, dev, func,
devices[d].name);
if (devices[d].init)
devices[d].init(bus, dev, func);
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;
+}
diff --git a/drivers/storage/ata.c b/drivers/storage/ata.c
index 4d26ab2..d0ff1e8 100644
--- a/drivers/storage/ata.c
+++ b/drivers/storage/ata.c
@@ -5,7 +5,9 @@
*/
#include <stdint.h>
+#include <sys/stat.h>
#include <io.h>
+#include <nucleus/driver.h>
#include <nucleus/panic.h>
#include <nucleus/vfs.h>
#include "ide.h"
@@ -169,11 +171,16 @@ ata_init(struct IDEDevice *dev)
static void *ataDmaArea = NULL;
if (!ataDmaArea)
ataDmaArea = (void *) alloc_frame();
+ static int ataMajor = 0;
+ if (!ataMajor)
+ ataMajor = register_driver(1, &ataFileOps);
+
/* Create device node */
char name[16];
+ int minor = drive * 16;
sprintf(name, "/dev/hd%d", drive);
-// mknod(name, S_IFBLK | 0600, MKDEV());
+ mknod(name, S_IFBLK | 0600, MKDEV(ataMajor, minor));
kprintf(" ATA drive [%s] (%d MB) %s", name,
dev->size / 1024 / 2, dev->model);
@@ -186,7 +193,7 @@ ata_init(struct IDEDevice *dev)
if (!part[i].type)
continue;
sprintf(name, "/dev/hd%dp%d", drive, i);
-// mknod(name, S_IFBLK | 0600, MKDEV(ideDriver.major, ());
+ mknod(name, S_IFBLK | 0600, MKDEV(ataMajor, minor + i + 1));
kprintf(" Partition [%s] %#.8x - %#.8x", name,
part[i].lba*512, (part[i].lba + part[i].size) * 512);
}
diff --git a/include/nucleus/driver.h b/include/nucleus/driver.h
new file mode 100644
index 0000000..53df5ec
--- /dev/null
+++ b/include/nucleus/driver.h
@@ -0,0 +1,19 @@
+#ifndef _NUCLEUS_DRIVER_H
+#define _NUCLEUS_DRIVER_H
+
+#include <sys/types.h>
+#include <nucleus/object.h>
+#include <nucleus/vfs.h>
+
+#define MKDEV(maj,min) ((dev_t) (((maj & 0xFFFF) << 16) | (min & 0xFFFF)))
+#define MAJOR(dev) ((dev >> 16) & 0xFFFF)
+#define MINOR(dev) (dev & 0xFFFF)
+
+typedef struct Driver Driver;
+
+extern ObjectType driverType;
+
+unsigned short register_driver(unsigned short major, FileOps *ops);
+FileOps *find_driver(unsigned short major);
+
+#endif
diff --git a/vfs/devfs/file.c b/vfs/devfs/file.c
index a984c1d..0217a8e 100644
--- a/vfs/devfs/file.c
+++ b/vfs/devfs/file.c
@@ -1,6 +1,9 @@
#include <stdint.h>
#include <stddef.h>
#include <string.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <nucleus/driver.h>
#include <nucleus/memory.h>
#include <nucleus/vfs.h>
@@ -71,5 +74,14 @@ devfs_write(File *file, char *buf, size_t size, off_t offset)
int
devfs_open(File *file)
{
- return 0;
+ if (S_ISREG(file->inode->mode) || S_ISDIR(file->inode->mode))
+ return 0;
+
+ /* Assign correct File Operations */
+ file->ops = find_driver(MAJOR(file->inode->dev));
+ if (!file->ops)
+ return -ENXIO;
+ if (!file->ops->open)
+ return 0;
+ return file->ops->open(file);
}