From 307eaac66d378c1f6150519123ec1204277464d9 Mon Sep 17 00:00:00 2001 From: Jake Mannens Date: Sun, 26 Aug 2018 13:29:33 +1000 Subject: Updated the style of the code in lib/string.c to conform to the rest of the project. Added the system call 'sys_panic' as well as the corresponding library function panic() whose prototype is defined in unistd.h. This is to allow userspace programs to deliberately crash the kernel for the purpose of debugging. Added the element 'write' as a function pointer in the tty_struct structure. The purpose of this function pointer is to provide a means for the TTY subsystem to notify the device driver of any newly added data to the write queue. Added the tty_write() function to the TTY subsystem. This function will copy data provided by the user into the specified TTY device's write queue, blocking if the queue's buffer is full. tty_write() will then call the driver's write() function to notify it of new data. Added the rsint_tx() function to the serial driver to handle transmit interrupts by re-supplying the UART's transmit FIFO. --- include/kernel/sys.h | 8 ++++--- include/kernel/tty.h | 2 ++ include/stdio.h | 5 ++-- include/string.h | 26 ++++++++++----------- include/unistd.h | 6 ++++- kernel/rs.s | 34 ++++++++++++++++++++++++++-- kernel/serial.c | 39 ++++++++++++++++++++++++++++---- kernel/sys.c | 9 ++++++++ kernel/tty.c | 64 +++++++++++++++++++++++++++++++++++++++++++++------- lib/panic.c | 8 +++++++ lib/stdio.c | 14 +++++++++++- lib/string.c | 56 ++++++++++++++++++++++----------------------- usrbin/main.c | 4 ++++ 13 files changed, 213 insertions(+), 62 deletions(-) create mode 100644 lib/panic.c diff --git a/include/kernel/sys.h b/include/kernel/sys.h index 2cefd09..e5275cf 100644 --- a/include/kernel/sys.h +++ b/include/kernel/sys.h @@ -9,8 +9,10 @@ extern int sys_alarm(void); extern int sys_pause(void); extern int sys_ctty(void); extern int sys_read(void); +extern int sys_write(void); extern int sys_kill(void); extern int sys_dummy(void); +extern int sys_panic(void); syscall_t call_table[256] = { [0] = &sys_puts, @@ -22,9 +24,9 @@ syscall_t call_table[256] = { [6] = &sys_pause, [7] = &sys_ctty, [8] = &sys_read, - [9] = &sys_kill, - [10] = &sys_dummy, - [11] = &sys_dummy, + [9] = &sys_write, + [10] = &sys_kill, + [11] = &sys_panic, [12] = &sys_dummy, [13] = &sys_dummy, [14] = &sys_dummy, diff --git a/include/kernel/tty.h b/include/kernel/tty.h index b3f3012..7c0fc6e 100644 --- a/include/kernel/tty.h +++ b/include/kernel/tty.h @@ -15,11 +15,13 @@ struct tty_queue { struct tty_struct { void (*init) (void); + void (*write) (void); struct tty_queue rqueue; struct tty_queue wqueue; }; ssize_t tty_read(unsigned, void*, size_t); +ssize_t tty_write(unsigned, void*, size_t); void tty_init(void); diff --git a/include/stdio.h b/include/stdio.h index f94e783..5387db0 100644 --- a/include/stdio.h +++ b/include/stdio.h @@ -14,8 +14,9 @@ int sprintf(char*, char*, ...); int vsprintf(char*, char*, va_list); -ssize_t read(void *buf, size_t len); +ssize_t read(void*, size_t); +ssize_t write(void*, size_t); -int ctty(int ctty); +int ctty(int); #endif diff --git a/include/string.h b/include/string.h index 72c2b2e..d2f738b 100644 --- a/include/string.h +++ b/include/string.h @@ -12,26 +12,26 @@ typedef uint32_t size_t; #endif -void* memchr(const void*, int, size_t); +void *memchr(const void*, int, size_t); int memcmp(const void*, const void*, size_t); -void* memcpy(void*, const void*, size_t); -void* memmove(void*, const void*, size_t); -void* memset(void*, int, size_t); +void *memcpy(void*, const void*, size_t); +void *memmove(void*, const void*, size_t); +void *memset(void*, int, size_t); size_t strlen(const char*); -char* strcat(char*, const char*); -char* strncat(char*, const char*, size_t); -char* strchr(const char*, int); -char* strrchr(char*, int); +char *strcat(char*, const char*); +char *strncat(char*, const char*, size_t); +char *strchr(const char*, int); +char *strrchr(char*, int); int strcmp(const char*, const char*); int strncmp(const char*, const char*, size_t); -char* strcpy(char*, const char*); -char* strncpy(char*, const char*, size_t); +char *strcpy(char*, const char*); +char *strncpy(char*, const char*, size_t); size_t strcspn(const char*, const char*); size_t strspn(const char*, const char*); -char* strpbrk(const char*, const char*); -char* strstr(const char*, const char*); -char* strtok(char*, const char*); +char *strpbrk(const char*, const char*); +char *strstr(const char*, const char*); +char *strtok(char*, const char*); size_t strxfrm(char*, const char*, size_t); #endif diff --git a/include/unistd.h b/include/unistd.h index c337e57..a7e4f32 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -19,7 +19,9 @@ typedef int16_t pid_t; #define __SYS_pause 6 #define __SYS_ctty 7 #define __SYS_read 8 -#define __SYS_kill 9 +#define __SYS_write 9 +#define __SYS_kill 10 +#define __SYS_panic 11 #define _syscall0(type, name) \ type name(void) { \ @@ -59,4 +61,6 @@ void *getpdir(void); int pause(void); +void panic(void); + #endif diff --git a/kernel/rs.s b/kernel/rs.s index 9f3d4a6..69d31ae 100644 --- a/kernel/rs.s +++ b/kernel/rs.s @@ -1,7 +1,20 @@ global rs_isr -extern rs_handler +extern rsint_rx +extern rsint_tx extern rsputs +%define RSBASE 0x3F8 + +%define RSDATA RSBASE +%define RSINTEN (RSBASE + 1) +%define RSFIFOC (RSBASE + 2) +%define RSINTID (RSBASE + 2) +%define RSLINEC (RSBASE + 3) +%define RSMODEMC (RSBASE + 4) +%define RSLINES (RSBASE + 5) +%define RSMODEMS (RSBASE + 6) +%define RSSCRATCH (RSBASE + 7) + rs_isr: pusha mov ax, ds @@ -12,7 +25,24 @@ rs_isr: mov fs, ax mov gs, ax - call rs_handler + mov dx, RSINTID + in al, dx + test al, 1 + jnz .skip + and al, 0x0E + cmp al, 0x04 + je .rx + cmp al, 0x0C + je .rx + cmp al, 0x02 + je .tx + jmp .skip +.tx: + call rsint_tx + jmp .skip +.rx: + call rsint_rx +.skip: mov al, 0x20 out 0x20, al diff --git a/kernel/serial.c b/kernel/serial.c index 39c5ee0..a133865 100644 --- a/kernel/serial.c +++ b/kernel/serial.c @@ -16,6 +16,7 @@ #define RSDATA RSBASE #define RSINTEN (RSBASE + 1) #define RSFIFOC (RSBASE + 2) +#define RSINTID (RSBASE + 2) #define RSLINEC (RSBASE + 3) #define RSMODEMC (RSBASE + 4) #define RSLINES (RSBASE + 5) @@ -27,8 +28,12 @@ extern void rs_isr(void); +/* internal function prototypes */ +void rsint_tx(void); + struct tty_struct tty_rs = { - .init = &serial_init + .init = &serial_init, + .write = &rsint_tx }; static char present; @@ -70,11 +75,18 @@ void serial_init(void) { /* restore access to the divisor */ outb(RSLINEC, inb(RSLINEC) & 0x7F); /* configure port parameters */ - outb(RSFIFOC, 0x06); + outb(RSFIFOC, 0x07); outb(RSLINEC, 0x03); outb(RSMODEMC, 0x0B); - outb(RSINTEN, 0x01); + outb(RSINTEN, 0x03); inb(RSDATA); + + /* test FIFO functionality */ + if(inb(RSINTID) & 0xC0 != 0xC0) { + printk("[rs] Failed to enable FIFO on COM0!\n"); + return; + } + /* register the interrupt handler */ register_isr(0x24, 0, &rs_isr); irq_enable(0x10); @@ -85,7 +97,7 @@ void serial_init(void) { present = 1; } -void rs_handler(void) { +void rsint_rx(void) { struct tty_queue *q = &tty_rs.rqueue; if((inb(RSLINES) & 1) == 0) @@ -98,3 +110,22 @@ void rs_handler(void) { wake_up(&q->waiting); } + +void rsint_tx(void) { + int copied = 0; + struct tty_queue *q = &tty_rs.wqueue; + + while(q->pread != q->pwrite) { + /* we're done if the TX FIFO is full */ + if((inb(RSLINES) & 0x20) == 0) + break; + + outb(RSDATA, q->buf[q->pread]); + q->pread = (q->pread + 1) % TTY_BUF_SIZE; + + copied = 1; + } + + if(copied) + wake_up(&q->waiting); +} diff --git a/kernel/sys.c b/kernel/sys.c index 6127f58..8e28edd 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -84,6 +85,14 @@ ssize_t sys_read(void *buf, size_t len) { return tty_read(ctask->ctty, buf, len); } +ssize_t sys_write(void *buf, size_t len) { + return tty_write(ctask->ctty, buf, len); +} + +void sys_panic(void) { + panic(); +} + int sys_dummy(void) { return -ENOSYS; } diff --git a/kernel/tty.c b/kernel/tty.c index 1946110..75c3701 100644 --- a/kernel/tty.c +++ b/kernel/tty.c @@ -16,11 +16,8 @@ static struct tty_struct *ttys[] = { &tty_rs }; -/* check if the buffer's empty and if so, go to sleep */ +/* check if a buffer's empty and if so, go to sleep */ static int sleep_while_empty(struct tty_queue *q) { - if(q->pread != q->pwrite) - return 0; - cli(); while(1) { if(q->pread == q->pwrite) @@ -37,6 +34,24 @@ static int sleep_while_empty(struct tty_queue *q) { } } +/* check if a buffer's full and if so, go to sleep */ +static int sleep_while_full(struct tty_queue *q) { + cli(); + while(1) { + if(q->pwrite == (q->pread - 1 % sizeof(q->buf))) + interruptible_sleep_on(&q->waiting); + + /* check again to see if anything was removed, or we were interrupted */ + if(q->pwrite == (q->pread - 1 % sizeof(q->buf))) { + sti(); + return -1; + } + + sti(); + return 0; + } +} + ssize_t tty_read(unsigned tty, void *buf, size_t len) { size_t i; char *b = buf; @@ -61,9 +76,45 @@ ssize_t tty_read(unsigned tty, void *buf, size_t len) { } *b++ = q->buf[q->pread]; - q->pread = q->pread + 1 % TTY_BUF_SIZE; + q->pread = (q->pread + 1) % TTY_BUF_SIZE; + } + + return len; +} + +ssize_t tty_write(unsigned tty, void *buf, size_t len) { + size_t i; + char *b = buf; + struct tty_queue *q = &ttys[tty]->wqueue; + + if(tty > NRTTY || ttys[tty] == NULL) + return -1; + + if(len == 0) + return 0; + + if(len > SSIZE_MAX) + len = SSIZE_MAX; + + for(i = 0; i < len; i++) { + /* check if the buffer's full and if so, go to sleep */ + if(sleep_while_full(q) < 0) { + if(i == 0) + return -EINTR; + + return i; + } + + q->buf[q->pwrite] = *b++; + q->pwrite = (q->pwrite + 1) % TTY_BUF_SIZE; } + /* tell the driver that new data is available */ + cli(); + if(ttys[tty]->write) + ttys[tty]->write(); + sti(); + return len; } @@ -77,9 +128,6 @@ void tty_init(void) { memset(&ttys[i]->rqueue, 0, sizeof(struct tty_queue)); memset(&ttys[i]->wqueue, 0, sizeof(struct tty_queue)); - ttys[i]->rqueue.pwrite = 1; - ttys[i]->wqueue.pwrite = 1; - if(ttys[i]->init) ttys[i]->init(); } diff --git a/lib/panic.c b/lib/panic.c new file mode 100644 index 0000000..a3eb0af --- /dev/null +++ b/lib/panic.c @@ -0,0 +1,8 @@ +#include + +void panic(void) { + __asm__ volatile ( + "int $0x80" + :: "a" (__SYS_panic) + ); +} diff --git a/lib/stdio.c b/lib/stdio.c index 7eac64c..b1c00ba 100644 --- a/lib/stdio.c +++ b/lib/stdio.c @@ -1,11 +1,23 @@ #include #include +#include #include #include -_syscall1(int, puts, char*, s); _syscall1(int, ctty, int, ctty); _syscall2(ssize_t, read, void*, buf, size_t, len); +_syscall2(ssize_t, write, void*, buf, size_t, len); + +int puts(char *s) { + size_t len = strlen(s); + ssize_t ret; + + ret = write(s, len); + if(ret < 0) + return EOF; + + return 0; +} int printf(char *fmt, ...) { int ret; diff --git a/lib/string.c b/lib/string.c index 0e8fbeb..e8659ad 100644 --- a/lib/string.c +++ b/lib/string.c @@ -1,6 +1,6 @@ #include -void* memchr(const void* s, int c, size_t n) { +void *memchr(const void *s, int c, size_t n) { unsigned char *p = (unsigned char*) s; while(n--) { if(*p != (unsigned char) c) { @@ -12,9 +12,9 @@ void* memchr(const void* s, int c, size_t n) { return 0; } -int memcmp(const void* s1, const void* s2, size_t n) { - const unsigned char* p1 = (const unsigned char*) s1; - const unsigned char* p2 = (const unsigned char*) s2; +int memcmp(const void *s1, const void *s2, size_t n) { + const unsigned char *p1 = (const unsigned char*) s1; + const unsigned char *p2 = (const unsigned char*) s2; while(n--) { if(*p1 != *p2) { return *p1 - *p2; @@ -25,33 +25,33 @@ int memcmp(const void* s1, const void* s2, size_t n) { return 0; } -void* memcpy(void* dest, const void* src, size_t n) { +void *memcpy(void *dest, const void *src, size_t n) { char *dp = (char*) dest; const char *sp = (const char*) src; while(n--) *dp++ = *sp++; return dest; } -void* memmove(void* dest, const void* src, size_t n) { +void *memmove(void *dest, const void *src, size_t n) { unsigned char tmp[n]; memcpy(tmp, src, n); memcpy(dest, tmp, n); return dest; } -void* memset(void* s, int c, size_t n) { - unsigned char* p = (unsigned char*) s; +void *memset(void *s, int c, size_t n) { + unsigned char *p = (unsigned char*) s; while(n--) *p++ = (unsigned char) c; return s; } -size_t strlen(const char* str) { - const char* s; +size_t strlen(const char *str) { + const char *s; for(s = str; *s; ++s) {} return (s - str); } -char* strcat(char* dest, const char* src) { +char *strcat(char *dest, const char *src) { size_t dest_len = strlen(dest); size_t i; @@ -62,7 +62,7 @@ char* strcat(char* dest, const char* src) { return dest; } -char* strncat(char* dest, const char* src, size_t n) { +char *strncat(char *dest, const char *src, size_t n) { size_t dest_len = strlen(dest); size_t i; @@ -73,27 +73,27 @@ char* strncat(char* dest, const char* src, size_t n) { return dest; } -char* strchr(const char* s, int c) { +char *strchr(const char *s, int c) { while(*s != (char) c) { if(!*s++) return 0; } return (char*) s; } -char* strrchr(char* s, int c) { - char* ret = 0; +char *strrchr(char *s, int c) { + char *ret = 0; do { if(*s == (char) c) ret = s; } while(*s++); return ret; } -int strcmp(const char* s1, const char* s2) { +int strcmp(const char *s1, const char *s2) { while(*s1 && (*s1 == *s2)) s1++, s2++; return *(const unsigned char*) s1 - *(const unsigned char*) s2; } -int strncmp(const char* s1, const char* s2, size_t n) { +int strncmp(const char *s1, const char *s2, size_t n) { while(n--) { if(*s1++ != *s2++) { return *(unsigned char*) (s1 - 1) - *(unsigned char*) (s2 - 1); @@ -102,14 +102,14 @@ int strncmp(const char* s1, const char* s2, size_t n) { return 0; } -char* strcpy(char* dest, const char* src) { - char* ret = dest; +char *strcpy(char *dest, const char *src) { + char *ret = dest; while(*dest++ = *src++); return ret; } -char* strncpy(char* dest, const char* src, size_t n) { - char* ret = dest; +char *strncpy(char *dest, const char *src, size_t n) { + char *ret = dest; do { if(!n--) return ret; } while (*dest++ = *src++); @@ -117,7 +117,7 @@ char* strncpy(char* dest, const char* src, size_t n) { return ret; } -size_t strcspn(const char* s1, const char* s2) { +size_t strcspn(const char *s1, const char *s2) { size_t ret = 0; while(*s1) { if(strchr(s2, *s1)) { @@ -129,20 +129,20 @@ size_t strcspn(const char* s1, const char* s2) { return ret; } -size_t strspn(const char* s1, const char* s2) { +size_t strspn(const char *s1, const char *s2) { size_t ret = 0; while(*s1 && strchr(s2, *s1++)) ret++; return ret; } -char* strpbrk(const char* s1, const char* s2) { +char *strpbrk(const char *s1, const char *s2) { while(*s1) { if(strchr(s2, *s1++)) return (char*) --s1; } return 0; } -char* strstr(const char* s1, const char* s2) { +char *strstr(const char *s1, const char *s2) { size_t n = strlen(s2); while(*s1) { if(!memcmp(s1++, s2, n)) { @@ -152,8 +152,8 @@ char* strstr(const char* s1, const char* s2) { return 0; } -char* strtok(char* str, const char* delim) { - static char* p = 0; +char *strtok(char *str, const char *delim) { + static char *p = 0; if(str) { p = str; } else if(!p) { @@ -166,7 +166,7 @@ char* strtok(char* str, const char* delim) { return str; } -size_t strxfrm(char* dest, const char* src, size_t n) { +size_t strxfrm(char *dest, const char *src, size_t n) { size_t n2 = strlen(src); if(n > n2) strcpy(dest, src); return n2; diff --git a/usrbin/main.c b/usrbin/main.c index a545a11..3b6dd97 100644 --- a/usrbin/main.c +++ b/usrbin/main.c @@ -27,6 +27,10 @@ void pid1(void) { kill(getpid(), SIGKILL); } } + if(in == 0) { + printf("EOF detected!\n"); + panic(); + } if(in > 0) puts(buf); } -- cgit v1.3