Browse Source

add /dev/port

K. Lange 2 years ago
parent
commit
c1e42d2e07
3 changed files with 101 additions and 4 deletions
  1. 16 4
      apps/qemu-fwcfg.c
  2. 1 0
      boot/cstuff.c
  3. 84 0
      modules/portio.c

+ 16 - 4
apps/qemu-fwcfg.c

@@ -18,22 +18,27 @@
 #include <unistd.h>
 #include <getopt.h>
 #include <signal.h>
+#include <unistd.h>
+#include <fcntl.h>
 
 #define FW_CFG_PORT_OUT 0x510
 #define FW_CFG_PORT_IN  0x511
 #define FW_CFG_SELECT_QEMU 0x0000
 #define FW_CFG_SELECT_LIST 0x0019
 
+static int port_fd = -1;
 
 /* outw / inb helper functions */
 static void outports(unsigned short _port, unsigned short _data) {
-	asm volatile ("outw %1, %0" : : "dN" (_port), "a" (_data));
+	lseek(port_fd, _port, SEEK_SET);
+	write(port_fd, &_data, 2);
 }
 
 static unsigned char inportb(unsigned short _port) {
-	unsigned char rv;
-	asm volatile ("inb %1, %0" : "=a" (rv) : "dN" (_port));
-	return rv;
+	unsigned char out;
+	lseek(port_fd, _port, SEEK_SET);
+	read(port_fd, &out, 1);
+	return out;
 }
 
 /* Despite primarily emulating x86, these are all big-endian */
@@ -106,6 +111,13 @@ int main(int argc, char * argv[]) {
 		return usage(argv);
 	}
 
+	port_fd = open("/dev/port", O_RDWR);
+
+	if (port_fd < 0) {
+		fprintf(stderr, "%s: could not open port IO device\n", argv[0]);
+		return 1;
+	}
+
 	signal(SIGILL, sig_pass);
 
 	/* First check for QEMU */

+ 1 - 0
boot/cstuff.c

@@ -82,6 +82,7 @@ static char * modules[] = {
 	"RTL.KO",      // 20
 	"E1000.KO",    // 21
 	"PCSPKR.KO",   // 22
+	"PORTIO.KO",   // 23
 	0
 };
 

+ 84 - 0
modules/portio.c

@@ -0,0 +1,84 @@
+/* vim: tabstop=4 shiftwidth=4 noexpandtab
+ * This file is part of ToaruOS and is released under the terms
+ * of the NCSA / University of Illinois License - see LICENSE.md
+ * Copyright (C) 2018 K. Lange
+ *
+ * provides /dev/port
+ *
+ */
+
+#include <kernel/system.h>
+#include <kernel/fs.h>
+#include <kernel/module.h>
+
+static uint32_t read_port(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
+	switch (size) {
+		case 1:
+			buffer[0] = inportb(offset);
+			break;
+		case 2:
+			((uint16_t *)buffer)[0] = inports(offset);
+			break;
+		case 4:
+			((uint32_t *)buffer)[0] = inportl(offset);
+			break;
+		default:
+			for (unsigned int i = 0; i < size; ++i) {
+				buffer[i] = inportb(offset + i);
+			}
+			break;
+	}
+
+	return size;
+}
+
+static uint32_t write_port(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
+	switch (size) {
+		case 1:
+			outportb(offset, buffer[0]);
+			break;
+		case 2:
+			outports(offset, ((uint16_t*)buffer)[0]);
+			break;
+		case 4:
+			outportl(offset, ((uint32_t*)buffer)[0]);
+			break;
+		default:
+			for (unsigned int i = 0; i < size; ++i) {
+				outportb(offset +i, buffer[i]);
+			}
+			break;
+	}
+
+	return size;
+}
+
+static fs_node_t * port_device_create(void) {
+	fs_node_t * fnode = malloc(sizeof(fs_node_t));
+	memset(fnode, 0x00, sizeof(fs_node_t));
+	fnode->inode = 0;
+	strcpy(fnode->name, "port");
+	fnode->uid = 0;
+	fnode->gid = 0;
+	fnode->mask = 0660;
+	fnode->flags   = FS_CHARDEVICE;
+	fnode->read    = read_port;
+	fnode->write   = write_port;
+	fnode->open    = NULL;
+	fnode->close   = NULL;
+	fnode->readdir = NULL;
+	fnode->finddir = NULL;
+	fnode->ioctl   = NULL;
+	return fnode;
+}
+
+static int port_initialize(void) {
+	vfs_mount("/dev/port", port_device_create());
+	return 0;
+}
+
+static int port_finalize(void) {
+	return 0;
+}
+
+MODULE_DEF(portio, port_initialize, port_finalize);