summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/hd.c4
-rw-r--r--kernel/rs.s25
-rw-r--r--kernel/serial.c60
-rw-r--r--kernel/sys.c17
-rw-r--r--kernel/timer.s2
5 files changed, 101 insertions, 7 deletions
diff --git a/kernel/hd.c b/kernel/hd.c
index 706d503..65ebfd7 100644
--- a/kernel/hd.c
+++ b/kernel/hd.c
@@ -27,13 +27,13 @@ void hd_init(void) {
s = inb(0x1F7);
if(!s) {
printk("[hd] Master drive not detected on primary bus!\n");
- panic();
+ return;
}
if(s & ST_ERR) {
if(!inb(0x1F4) && !inb(0x1F5))
continue;
printk("[hd] IDENTIFY command error!\n");
- panic();
+ return;
}
if(s & ST_DRQ && !(s & ST_ERR))
break;
diff --git a/kernel/rs.s b/kernel/rs.s
new file mode 100644
index 0000000..9f3d4a6
--- /dev/null
+++ b/kernel/rs.s
@@ -0,0 +1,25 @@
+global rs_isr
+extern rs_handler
+extern rsputs
+
+rs_isr:
+ pusha
+ mov ax, ds
+ push ax
+ mov ax, 0x10
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+
+ call rs_handler
+ mov al, 0x20
+ out 0x20, al
+
+ pop ax
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+ popa
+ iret
diff --git a/kernel/serial.c b/kernel/serial.c
index 86bbd87..d96359b 100644
--- a/kernel/serial.c
+++ b/kernel/serial.c
@@ -1,5 +1,9 @@
+#include <asm/interrupt.h>
#include <asm/io.h>
#include <kernel/con.h>
+#include <kernel/sched.h>
+#include <sys/types.h>
+#include <unistd.h>
/* 115200 baud */
#define DIVISOR 1
@@ -18,10 +22,16 @@
#define rswait()\
while((inb(RSLINES) & 0x20) == 0);
+extern void rs_isr(void);
+
+static char rxbuf[256];
+static unsigned rxread, rxwrite;
+static struct task_struct *waiting_task;
+
int rsputs(char *s) {
while(*s) {
rswait();
- if(*s == '\n') {
+ if(*s == '\n' || *s == '\r') {
outb(RSDATA, '\n');
rswait();
outb(RSDATA, '\r');
@@ -50,9 +60,55 @@ void serial_init(void) {
/* restore access to the divisor */
outb(RSLINEC, inb(RSLINEC) & 0x7F);
/* configure port parameters */
+ outb(RSFIFOC, 0x06);
outb(RSLINEC, 0x03);
- outb(RSINTEN, 0x00);
+ outb(RSMODEMC, 0x0B);
+ outb(RSINTEN, 0x01);
+ inb(RSDATA);
+ /* register the interrupt handler */
+ register_isr(0x24, 0, &rs_isr);
+ irq_enable(0x10);
rsputs("[kernel] Serial monitor initialized!\n\r");
printk("[rs] Serial port COM0 initialized!\n");
+
+ rxread = 0;
+ rxwrite = 1;
+ waiting_task = NULL;
+}
+
+ssize_t rsread(void *buf, size_t len) {
+ ssize_t n = len;
+ char *b = buf;
+
+ if(len == 0)
+ return 0;
+
+ while(n--) {
+ if(rxread == rxwrite) {
+ /* put the current task to sleep */
+ waiting_task = ctask;
+ ctask->state = TSTATE_UNINTERRUPTIBLE;
+ reschedule();
+ }
+
+ *b++ = rxbuf[rxread];
+ rxread = rxread + 1 % sizeof(rxbuf);
+ }
+
+ return len;
+}
+
+void rs_handler(void) {
+ if((inb(RSLINES) & 1) == 0)
+ return;
+ if(rxwrite == (rxread - 1 % sizeof(rxbuf)))
+ return;
+ rxbuf[rxwrite] = inb(RSDATA);
+ rxwrite = rxwrite + 1 % sizeof(rxbuf);
+
+ if(waiting_task != NULL) {
+ waiting_task->state = TSTATE_RUNNING;
+ waiting_task = NULL;
+ }
}
diff --git a/kernel/sys.c b/kernel/sys.c
index 986c4dd..cfe9483 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -1,6 +1,7 @@
#include <errno.h>
#include <kernel/con.h>
#include <kernel/sched.h>
+#include <kernel/serial.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
@@ -10,14 +11,15 @@
int sys_puts(char *s) {
char buf[8];
- sprintf(buf, "[%04x] ", ctask->pid);
if(ctask->ctty < 0)
return EOF;
+ sprintf(buf, "[%04x] ", ctask->pid);
+
switch(ctask->ctty) {
case 1:
- rsputs(buf);
+ /* rsputs(buf); */
return rsputs(s);
break;
default:
@@ -77,6 +79,17 @@ int sys_ctty(int ctty) {
return 0;
}
+ssize_t sys_read(void *buf, size_t len) {
+ switch(ctask->ctty) {
+ case 1:
+ return rsread(buf, len);
+ break;
+ default:
+ return -EBADF;
+ break;
+ }
+}
+
int sys_dummy(void) {
return -ENOSYS;
}
diff --git a/kernel/timer.s b/kernel/timer.s
index 6d95281..e6da428 100644
--- a/kernel/timer.s
+++ b/kernel/timer.s
@@ -55,7 +55,7 @@ timer_init:
push dword 0x20
call register_isr
add esp, 12
- ; initialize the pit
+ ; initialize the PIT
mov ax, 0x36
out 0x43, al
mov ax, 0x2E9C ; 10ms tick interval