add /dev/port

This commit is contained in:
K. Lange 2018-09-28 13:59:14 +09:00
parent cdcc0edb0b
commit c1e42d2e07
3 changed files with 101 additions and 4 deletions

View File

@ -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 */

View File

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

84
modules/portio.c Normal file
View File

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