summaryrefslogtreecommitdiff
path: root/kernel/serial.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/serial.c')
-rw-r--r--kernel/serial.c19
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);