Add ttyS0

This commit is contained in:
Mark
2020-01-22 15:01:37 +02:00
parent 89b7b86fbb
commit dad41847e3
10 changed files with 108 additions and 12 deletions
+4
View File
@@ -2,6 +2,10 @@
#include <stdint.h>
#define RS232_COM1 0x3F8
struct chrdev;
int rs232_putc(void *dev, char c);
void rs232_set_tty(uint16_t com, struct chrdev *tty);
void rs232_init(uint16_t port);
void rs232_send(uint16_t port, char c);
+1
View File
@@ -5,6 +5,7 @@ enum {
CFG_ROOT = 1,
CFG_INIT,
CFG_RDINIT,
CFG_CONSOLE,
__CFG_SIZE
};
+1
View File
@@ -6,6 +6,7 @@ struct thread;
#define RING_SIGNAL_BRK (1 << 0)
#define RING_SIGNAL_EOF (1 << 1)
#define RING_SIGNAL_RET (1 << 2)
// Ring buffer
struct ring {
+4 -1
View File
@@ -5,6 +5,9 @@
#define TIOCSPGRP 0x5410
#define TIOCGWINSZ 0x5413
// Input flags
#define ICANON (1 << 1)
// Output flags
#define OPOST (1 << 0)
#define ONLCR (1 << 2)
@@ -20,7 +23,7 @@
#define TERMIOS_DEFAULT \
{ \
.c_iflag = 0, \
.c_iflag = ICANON, \
.c_oflag = OPOST, \
.c_cflag = 0, \
.c_lflag = ECHO | ECHONL | ECHOE | ECHOK, \
+40 -3
View File
@@ -29,12 +29,27 @@
#define RS232_LSR_TEMT 64
#define RS232_LSR_ERR 128
static struct chrdev *_rs232_tty[4] = {NULL};
void rs232_send(uint16_t port, char c) {
while (!(inb(port + RS232_LSR) & RS232_LSR_THRE)) {
}
outb(port, c);
}
int rs232_putc(void *dev, char c) {
rs232_send(((uintptr_t) dev) & 0xFFFF, c);
return 0;
}
void rs232_set_tty(uint16_t com, struct chrdev *tty) {
switch (com) {
case RS232_COM1:
_rs232_tty[0] = tty;
break;
}
}
static uint32_t rs232_irq(void *ctx) {
uint16_t port = (uint16_t) (uintptr_t) ctx;
int has_data = 0;
@@ -44,11 +59,33 @@ static uint32_t rs232_irq(void *ctx) {
has_data = 1;
uint8_t c = inb(port);
if (c == '\r') {
c = '\n';
if (c < ' ') {
kdebug("Special character in serial input: 0x%02x\n", c);
}
// TODO: send data to bound TTY
// Translate serial codes to proper values recognized by kernel
// line discipline. TODO: make c_cc in termios handle special characters
int control = 0;
switch (c) {
case 0x0D:
c = '\n';
break;
case 0x7F:
c = '\b';
break;
case 0x04:
control = 'd';
break;
}
if (_rs232_tty[0]) {
if (!control) {
tty_data_write(_rs232_tty[0], c);
} else {
tty_control_write(_rs232_tty[0], control);
}
}
}
return has_data ? IRQ_HANDLED : IRQ_UNHANDLED;
+14 -2
View File
@@ -256,7 +256,10 @@ int sys_select(int nfds, fd_set *rd, fd_set *wr, fd_set *exc, struct timeval *tv
}
}
uint64_t deadline = tv->tv_sec * 1000000000ULL + tv->tv_usec * 1000ULL + system_time;
uint64_t deadline = (uint64_t) -1;
if (tv) {
deadline = tv->tv_sec * 1000000000ULL + tv->tv_usec * 1000ULL + system_time;
}
int res;
while (1) {
@@ -269,11 +272,20 @@ int sys_select(int nfds, fd_set *rd, fd_set *wr, fd_set *exc, struct timeval *tv
struct chrdev *chr = fd->vnode->dev;
_assert(chr);
if (ring_readable(&chr->buffer) > 0) {
if (chr->buffer.flags & (RING_SIGNAL_EOF | RING_SIGNAL_BRK | RING_SIGNAL_RET)) {
FD_SET(i, rd);
res = 0;
goto done;
}
// Report data available for non-canonical devices
if (chr->type == CHRDEV_TTY && !(chr->tc.c_iflag & ICANON)) {
if (ring_readable(&chr->buffer) > 0) {
FD_SET(i, rd);
res = 0;
goto done;
}
}
}
}
+2
View File
@@ -16,6 +16,7 @@ static const struct __kernel_cmdline_pair {
{ "root", CFG_ROOT, VALUE_STRING },
{ "init", CFG_INIT, VALUE_STRING },
{ "rdinit", CFG_RDINIT, VALUE_STRING },
{ "console", CFG_CONSOLE, VALUE_STRING },
};
// Default config
@@ -24,6 +25,7 @@ uintptr_t kernel_config[__CFG_SIZE] = {
[CFG_ROOT] = (uintptr_t) "ram0",
[CFG_INIT] = (uintptr_t) "/init",
[CFG_RDINIT] = (uintptr_t) "/init",
[CFG_CONSOLE] = (uintptr_t) "tty0",
};
static int parse_number(const char *s, intptr_t *res) {
+3 -2
View File
@@ -22,6 +22,7 @@
extern uintptr_t argp_copy(struct thread *thr, const char *const argv[], size_t *arg_count);
static int user_init_start(const char *init_filename) {
const char *init_console = (const char *) kernel_config[CFG_CONSOLE];
struct ofile fd;
struct stat st;
struct thread *user_init;
@@ -100,8 +101,8 @@ static int user_init_start(const char *init_filename) {
stderr = stdout;
struct vnode *stdout_device;
if ((res = dev_find(DEV_CLASS_CHAR, "tty0", &stdout_device)) != 0) {
panic("%s: %s\n", "tty0", kstrerror(res));
if ((res = dev_find(DEV_CLASS_CHAR, init_console, &stdout_device)) != 0) {
panic("%s: %s\n", init_console, kstrerror(res));
}
if ((res = vfs_open_vnode(&user_init->ioctx, stdin, stdout_device, O_RDONLY)) != 0) {
+11 -1
View File
@@ -4,6 +4,7 @@
#include "sys/chr.h"
#include "sys/tty.h"
#include "sys/amd64/cpu.h"
#include "sys/line.h"
ssize_t line_read(struct chrdev *chr, void *buf, size_t pos, size_t lim) {
struct thread *thr = get_cpu()->thread;
@@ -15,8 +16,16 @@ ssize_t line_read(struct chrdev *chr, void *buf, size_t pos, size_t lim) {
char *wr = buf;
char c;
// Only needed for stuff like select(), which is called before read()
chr->buffer.flags &= ~RING_SIGNAL_RET;
if (r->flags & RING_SIGNAL_EOF) {
return -1;
return 0;
}
if (!(chr->tc.c_iflag & ICANON)) {
// Just spit out data as soon as it's available
return simple_line_read(chr, buf, pos, lim);
}
// NO ICANON YET
@@ -68,6 +77,7 @@ ssize_t line_read(struct chrdev *chr, void *buf, size_t pos, size_t lim) {
}
}
chr->buffer.flags &= ~RING_SIGNAL_RET;
return rd;
}
+28 -3
View File
@@ -10,6 +10,7 @@
#include "sys/string.h"
#include "sys/assert.h"
#include "sys/termios.h"
#include "sys/amd64/hw/rs232.h"
#include "sys/ring.h"
#include "sys/mm.h"
#include "sys/amd64/cpu.h"
@@ -45,6 +46,23 @@ static struct chrdev _dev_tty0 = {
.ioctl = tty_ioctl
};
// Serial console
static struct tty_data _dev_ttyS0_data = {
.fg_pgid = 1,
.out_dev = (void *) RS232_COM1,
.out_putc = rs232_putc
};
static struct chrdev _dev_ttyS0 = {
.type = CHRDEV_TTY,
.dev_data = &_dev_ttyS0_data,
.tc = TERMIOS_DEFAULT,
.write = tty_write,
// Line discipline
.read = line_read,
.ioctl = tty_ioctl
};
void tty_control_write(struct chrdev *tty, char c) {
struct tty_data *data = tty->dev_data;
_assert(data);
@@ -72,6 +90,10 @@ void tty_data_write(struct chrdev *tty, char c) {
if (tty->tc.c_lflag & ECHONL) {
tty_putc(tty, c);
}
if (tty->tc.c_iflag & ICANON) {
// Trigger line flush
ring_signal(&tty->buffer, RING_SIGNAL_RET);
}
break;
case '\b':
break;
@@ -101,12 +123,15 @@ void tty_putc(struct chrdev *tty, char c) {
}
void tty_init(void) {
// tty0
ring_init(&_dev_tty0.buffer, 16);
// Bind tty0 to keyboard
ps2_kbd_set_tty(&_dev_tty0);
dev_add(DEV_CLASS_CHAR, DEV_CHAR_TTY, &_dev_tty0, "tty0");
// ttyS0
ring_init(&_dev_ttyS0.buffer, 16);
rs232_set_tty(RS232_COM1, &_dev_ttyS0);
dev_add(DEV_CLASS_CHAR, DEV_CHAR_TTY, &_dev_ttyS0, "ttyS0");
}
static ssize_t tty_write(struct chrdev *tty, const void *buf, size_t pos, size_t lim) {