summaryrefslogtreecommitdiff
path: root/kernel/serial.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/serial.c')
-rw-r--r--kernel/serial.c60
1 files changed, 58 insertions, 2 deletions
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;
+ }
}