BarryServer : Git

All the code for all my projects
// BarryServer : Git / Nucleus / commit / 7864e7f8ed319f380849d97675be53f53c953f9d

// Related

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);
 }