diff options
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | include/asm/interrupt.h | 27 | ||||
| -rw-r--r-- | include/kernel/con.h | 2 | ||||
| -rw-r--r-- | include/kernel/serial.h | 10 | ||||
| -rw-r--r-- | include/kernel/sys.h | 3 | ||||
| -rw-r--r-- | include/stdio.h | 4 | ||||
| -rw-r--r-- | include/unistd.h | 21 | ||||
| -rw-r--r-- | kernel/hd.c | 4 | ||||
| -rw-r--r-- | kernel/rs.s | 25 | ||||
| -rw-r--r-- | kernel/serial.c | 60 | ||||
| -rw-r--r-- | kernel/sys.c | 17 | ||||
| -rw-r--r-- | kernel/timer.s | 2 | ||||
| -rw-r--r-- | lib/stdio.c | 2 | ||||
| -rw-r--r-- | usrbin/main.c | 20 |
14 files changed, 174 insertions, 25 deletions
@@ -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) { |
