diff options
Diffstat (limited to 'kernel/serial.c')
| -rw-r--r-- | kernel/serial.c | 19 |
1 files changed, 18 insertions, 1 deletions
diff --git a/kernel/serial.c b/kernel/serial.c index d96359b..911f02c 100644 --- a/kernel/serial.c +++ b/kernel/serial.c @@ -1,5 +1,6 @@ #include <asm/interrupt.h> #include <asm/io.h> +#include <errno.h> #include <kernel/con.h> #include <kernel/sched.h> #include <sys/types.h> @@ -24,11 +25,16 @@ extern void rs_isr(void); +static char present; + static char rxbuf[256]; static unsigned rxread, rxwrite; static struct task_struct *waiting_task; int rsputs(char *s) { + if(!present) + return -ENXIO; + while(*s) { rswait(); if(*s == '\n' || *s == '\r') { @@ -45,6 +51,8 @@ int rsputs(char *s) { } void serial_init(void) { + present = 0; + outb(RSSCRATCH, 0x00); outb(RSSCRATCH, 0xAA); if(inb(RSSCRATCH) != 0xAA) { @@ -75,12 +83,16 @@ void serial_init(void) { rxread = 0; rxwrite = 1; waiting_task = NULL; + present = 1; } ssize_t rsread(void *buf, size_t len) { ssize_t n = len; char *b = buf; + if(!present) + return -ENXIO; + if(len == 0) return 0; @@ -88,9 +100,14 @@ ssize_t rsread(void *buf, size_t len) { if(rxread == rxwrite) { /* put the current task to sleep */ waiting_task = ctask; - ctask->state = TSTATE_UNINTERRUPTIBLE; + ctask->state = TSTATE_INTERRUPTIBLE; reschedule(); } + /* check again to see if anything was read, or we were interrupted */ + if(rxread == rxwrite) { + waiting_task = NULL; + return -EINTR; + } *b++ = rxbuf[rxread]; rxread = rxread + 1 % sizeof(rxbuf); |
