summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--include/asm/interrupt.h27
-rw-r--r--include/kernel/con.h2
-rw-r--r--include/kernel/serial.h10
-rw-r--r--include/kernel/sys.h3
-rw-r--r--include/stdio.h4
-rw-r--r--include/unistd.h21
-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
-rw-r--r--lib/stdio.c2
-rw-r--r--usrbin/main.c20
14 files changed, 174 insertions, 25 deletions
diff --git a/Makefile b/Makefile
index f043bea..391597f 100644
--- a/Makefile
+++ b/Makefile
@@ -21,7 +21,7 @@ clean:
rm -f $(TARGET)
run: $(TARGET)
- qemu-system-x86_64 -s -kernel $(TARGET) -drive file=hd.img,format=raw
+ qemu-system-x86_64 -s -kernel $(TARGET) -drive file=hd.img,format=raw -serial stdio
#qemu-system-x86_64 -s -S -kernel $(TARGET) -drive file=hd.img,format=raw
.FORCE:
diff --git a/include/asm/interrupt.h b/include/asm/interrupt.h
index d1ea6c1..1187fef 100644
--- a/include/asm/interrupt.h
+++ b/include/asm/interrupt.h
@@ -1,2 +1,29 @@
+#include <stdint.h>
+
+#define irq_enable(n) \
+ __asm__ volatile ( \
+ "inb $0xA1, %%al\n" \
+ "shl $8, %%ax\n" \
+ "inb $0x21, %%al\n" \
+ "xor $0xFFFF, %%bx\n" \
+ "and %%bx, %%ax\n" \
+ "outb %%al, $0x21\n" \
+ "shr $8, %%ax\n" \
+ "outb %%al, $0xA1\n" \
+ :: "b" (n) \
+ );
+
+#define irq_disable(n) \
+ __asm__ volatile ( \
+ "inb $0xA1, %%al\n" \
+ "shl $8, %%ax\n" \
+ "inb $0x21, %%al\n" \
+ "or %%bx, %%ax\n" \
+ "outb %%al, $0x21\n" \
+ "shr $8, %%ax\n" \
+ "outb %%al, $0xA1\n" \
+ :: "b" (n) \
+ );
+
void register_isr(uint8_t n, uint8_t dpl, void *handler);
void register_trap(uint8_t n, uint8_t dpl, void *handler);
diff --git a/include/kernel/con.h b/include/kernel/con.h
index d28daff..9dd9dbe 100644
--- a/include/kernel/con.h
+++ b/include/kernel/con.h
@@ -13,6 +13,4 @@ void con_clear(void);
int printk(char*, ...);
-int rsputs(char*);
-
#endif
diff --git a/include/kernel/serial.h b/include/kernel/serial.h
new file mode 100644
index 0000000..dbfa7f2
--- /dev/null
+++ b/include/kernel/serial.h
@@ -0,0 +1,10 @@
+#ifndef _SERIAL_H
+#define _SERIAL_H
+
+#include <sys/types.h>
+
+int rsputs(char*);
+
+ssize_t rsread(void*, size_t);
+
+#endif
diff --git a/include/kernel/sys.h b/include/kernel/sys.h
index 32788b1..c428c72 100644
--- a/include/kernel/sys.h
+++ b/include/kernel/sys.h
@@ -8,6 +8,7 @@ extern int sys_signal(void);
extern int sys_alarm(void);
extern int sys_pause(void);
extern int sys_ctty(void);
+extern int sys_read(void);
extern int sys_dummy(void);
syscall_t call_table[256] = {
@@ -19,7 +20,7 @@ syscall_t call_table[256] = {
[5] = &sys_alarm,
[6] = &sys_pause,
[7] = &sys_ctty,
- [8] = &sys_dummy,
+ [8] = &sys_read,
[9] = &sys_dummy,
[10] = &sys_dummy,
[11] = &sys_dummy,
diff --git a/include/stdio.h b/include/stdio.h
index 824eb31..f94e783 100644
--- a/include/stdio.h
+++ b/include/stdio.h
@@ -2,6 +2,8 @@
#define _STDIO_H
#include <stdarg.h>
+#include <sys/types.h>
+#include <unistd.h>
#define EOF -1
@@ -12,6 +14,8 @@ int sprintf(char*, char*, ...);
int vsprintf(char*, char*, va_list);
+ssize_t read(void *buf, size_t len);
+
int ctty(int ctty);
#endif
diff --git a/include/unistd.h b/include/unistd.h
index 746c829..ef6d059 100644
--- a/include/unistd.h
+++ b/include/unistd.h
@@ -3,6 +3,11 @@
#include <stdint.h>
+#ifndef _SSIZE_T
+#define _SSIZE_T
+typedef int32_t ssize_t;
+#endif
+
typedef uint16_t pid_t;
#define __SYS_puts 0
@@ -13,6 +18,7 @@ typedef uint16_t pid_t;
#define __SYS_alarm 5
#define __SYS_pause 6
#define __SYS_ctty 7
+#define __SYS_read 8
#define _syscall0(type, name) \
type name(void) { \
@@ -21,7 +27,7 @@ typedef uint16_t pid_t;
"int $0x80" \
: "=a" (__res) \
: "a" (__SYS_##name) \
- :); \
+ ); \
return __res; \
}
@@ -32,7 +38,18 @@ typedef uint16_t pid_t;
"int $0x80" \
: "=a" (__res) \
: "a" (__SYS_##name), "b" (a) \
- :); \
+ ); \
+ return __res; \
+ }
+
+#define _syscall2(type, name, atype, a, btype, b) \
+ type name(atype a, btype b) { \
+ type __res; \
+ __asm__ volatile ( \
+ "int $0x80" \
+ : "=a" (__res) \
+ : "a" (__SYS_##name), "b" (a), "c" (b) \
+ ); \
return __res; \
}
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
diff --git a/lib/stdio.c b/lib/stdio.c
index 67f0a54..7eac64c 100644
--- a/lib/stdio.c
+++ b/lib/stdio.c
@@ -1,9 +1,11 @@
#include <stdarg.h>
#include <stdio.h>
+#include <sys/types.h>
#include <unistd.h>
_syscall1(int, puts, char*, s);
_syscall1(int, ctty, int, ctty);
+_syscall2(ssize_t, read, void*, buf, size_t, len);
int printf(char *fmt, ...) {
int ret;
diff --git a/usrbin/main.c b/usrbin/main.c
index 68f1a5c..31d38c1 100644
--- a/usrbin/main.c
+++ b/usrbin/main.c
@@ -4,21 +4,17 @@
#include <time.h>
#include <unistd.h>
-void sighandler(int sig) {
- printf("Caught SIGALRM!\n");
-}
-
void pid1(void) {
- printf("We did it ma!\n");
+ ssize_t in;
+ char buf[2] = { 0, 0 };
- signal(SIGALRM, &sighandler);
- alarm(2);
- pause();
- printf("Alarm expired!\n");
- pause();
+ printf("We did it ma!\n");
- while(1)
- printf("It's didn't work!\n");
+ while(1) {
+ in = read(buf, 1);
+ if(in > 0)
+ puts(buf);
+ }
}
void pid2(void) {