diff options
Diffstat (limited to 'kernel')
| -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 |
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 |
