add /dev/port
This commit is contained in:
parent
cdcc0edb0b
commit
c1e42d2e07
@ -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 */
|
||||
|
@ -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
84
modules/portio.c
Normal 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);
|
Loading…
Reference in New Issue
Block a user