diff options
-rw-r--r-- | com32/include/console.h | 9 | ||||
-rw-r--r-- | com32/include/dev.h | 3 | ||||
-rw-r--r-- | com32/lib/Makefile | 2 | ||||
-rw-r--r-- | com32/lib/sys/ansicon_write.c | 490 | ||||
-rw-r--r-- | com32/lib/sys/ansiserial_write.c | 56 | ||||
-rw-r--r-- | com32/lib/sys/serial_write.c | 2 | ||||
-rw-r--r-- | com32/modules/Makefile | 2 | ||||
-rw-r--r-- | com32/modules/fancyhello.c | 44 | ||||
-rw-r--r-- | com32/modules/hello.c | 2 |
9 files changed, 368 insertions, 242 deletions
diff --git a/com32/include/console.h b/com32/include/console.h index 55904277..494b0ba1 100644 --- a/com32/include/console.h +++ b/com32/include/console.h @@ -47,5 +47,14 @@ extern const struct output_dev dev_stdcon_w; extern const struct input_dev dev_rawcon_r; extern const struct output_dev dev_rawcon_w; +/* These are output-only consoles; combine with one of the input methods */ + +/* Serial port only */ +extern const struct output_dev dev_serial_w; +/* ANSI console (output only; combine with one of the input methods) */ +extern const struct output_dev dev_ansicon_w; +/* ANSI plus serial port */ +extern const struct output_dev dev_ansiserial_w; + #endif /* _CONSOLE_H */ diff --git a/com32/include/dev.h b/com32/include/dev.h index a8cea76c..a5afbaf1 100644 --- a/com32/include/dev.h +++ b/com32/include/dev.h @@ -44,9 +44,12 @@ struct output_dev; __extern int opendev(const struct input_dev *, const struct output_dev *, int); /* Common generic devices */ + +/* Null device */ extern const struct input_dev dev_null_r; extern const struct output_dev dev_null_w; +/* Error device */ extern const struct input_dev dev_error_r; extern const struct output_dev dev_error_w; diff --git a/com32/lib/Makefile b/com32/lib/Makefile index acc385fc..9896befd 100644 --- a/com32/lib/Makefile +++ b/com32/lib/Makefile @@ -25,7 +25,7 @@ LIBOBJS = abort.o atexit.o atoi.o atol.o atoll.o calloc.o creat.o \ sys/rawcon_read.o sys/rawcon_write.o \ sys/err_read.o sys/err_write.o \ sys/null_read.o sys/null_write.o \ - sys/ansicon_write.o + sys/serial_write.o sys/ansicon_write.o sys/ansiserial_write.o all: libcom32.a diff --git a/com32/lib/sys/ansicon_write.c b/com32/lib/sys/ansicon_write.c index 59eec01e..1e4e3cca 100644 --- a/com32/lib/sys/ansicon_write.c +++ b/com32/lib/sys/ansicon_write.c @@ -52,16 +52,14 @@ struct curxy { uint8_t x, y; } __attribute__((packed)); #define BIOS_CURXY ((struct curxy *)0x450) /* Array for each page */ -#define BIOS_ROWS (*(uint8_t *)0x449) /* Minus one */ +#define BIOS_ROWS (*(uint8_t *)0x484) /* Minus one; if zero use 24 (= 25 lines) */ #define BIOS_COLS (*(uint16_t *)0x44A) #define BIOS_PAGE (*(uint8_t *)0x462) -#define BIOS_FB (*(uint16_t *)0x44E) /* Current page fb address */ enum ansi_state { st_init, /* Normal (no ESC seen) */ st_esc, /* ESC seen */ - st_empty, /* CSI seen, empty position */ - st_digits, /* CSI seen, digits seen in this position */ + st_csi, /* CSI seen */ }; #define MAX_PARMS 16 @@ -89,7 +87,6 @@ static struct { .saved_xy = { 0, 0 }, .state = st_init, .nparms = 0, - .parms = { 0, }, }; /* Erase a region of the screen */ @@ -113,292 +110,309 @@ static void ansicon_putchar(int ch) const int cols = BIOS_COLS; const int page = BIOS_PAGE; struct curxy xy = BIOS_CURXY[page]; - int again; - do { - again = 0; - - switch ( st.state ) { - case st_init: - switch ( ch ) { - case '\a': - /* Ignore beep */ - break; - case '\b': - if ( xy.y > 0 ) xy.y--; - break; - case '\t': - { - int nsp = 8 - (xy.y & 7); - while ( nsp-- ) - ansicon_putchar(' '); - } - return; /* Cursor already updated */ - case '\n': - case '\v': - case '\f': - xy.y++; - break; - case '\r': - xy.x = 0; - break; - case '\0': - case 127: - /* Ignore null or delete */ - break; - case 27: - st.state = st_esc; - break; - default: - /* Print character */ - ireg.eax.b[1] = 0x09; - ireg.eax.b[0] = ch; - ireg.ebx.b[1] = page; - ireg.ebx.b[0] = st.attr; - ireg.ecx.w[0] = 1; - __intcall(0x10, &ireg, NULL); - xy.x++; - break; - } + switch ( st.state ) { + case st_init: + switch ( ch ) { + case '\a': + /* Ignore beep */ break; - - case st_esc: - if ( ch == '[' ) { - int i; - st.state = st_empty; - st.nparms = 0; - for ( i = 0 ; i < MAX_PARMS ; i++ ) - st.parms[i] = 1; /* 1 is the default, not 0 */ - } else { - st.state = st_init; - again = 1; + case '\b': + if ( xy.x > 0 ) xy.x--; + break; + case '\t': + { + int nsp = 8 - (xy.x & 7); + while ( nsp-- ) + ansicon_putchar(' '); } + return; /* Cursor already updated */ + case '\n': + case '\v': + case '\f': + xy.y++; + break; + case '\r': + xy.x = 0; + break; + case '\0': + case 127: + /* Ignore null or delete */ + break; + case 27: + st.state = st_esc; + break; + default: + /* Print character */ + ireg.eax.b[1] = 0x09; + ireg.eax.b[0] = ch; + ireg.ebx.b[1] = page; + ireg.ebx.b[0] = st.attr; + ireg.ecx.w[0] = 1; + __intcall(0x10, &ireg, NULL); + xy.x++; break; + } + break; - case st_empty: - case st_digits: - switch ( ch ) { - case '0' ... '9': - if ( st.state == st_empty ) { - st.parms[st.nparms] = ch - '0'; - st.state = st_digits; - } else { - st.parms[st.nparms] = st.parms[st.nparms]*10 + (ch-'0'); - } - break; - case ';': + case st_esc: + if ( ch == '[' ) { + st.state = st_csi; + st.nparms = 0; + memset(st.parms, 0, sizeof st.parms); + } else { + st.state = st_init; /* Discard ESC+other symbol */ + } + break; + + case st_csi: + { + int p0 = st.parms[0] ? st.parms[0] : 1; + + if ( ch >= '0' && ch <= '9' ) { + st.parms[st.nparms] = st.parms[st.nparms]*10 + (ch-'0'); + } else if ( ch == ';' ) { st.nparms++; if ( st.nparms >= MAX_PARMS ) st.nparms = MAX_PARMS-1; - st.state = st_empty; break; - case 'A': - { - int y = xy.y - st.parms[0]; - xy.y = (y < 0) ? 0 : y; - } - break; - case 'B': - { - int y = xy.y + st.parms[0]; - xy.y = (y >= rows) ? rows-1 : y; - } - break; - case 'C': - { - int x = xy.x + st.parms[0]; - xy.x = (x >= cols) ? cols-1 : x; - } - break; - case 'D': - { - int x = xy.x - st.parms[0]; - xy.x = (x < 0) ? 0 : x; - } - break; - case 'E': - { - int y = xy.y + st.parms[0]; - xy.y = (y >= rows) ? rows-1 : y; - xy.x = 0; - } - break; - case 'F': - { - int y = xy.y - st.parms[0]; - xy.y = (y < 0) ? 0 : y; - xy.x = 0; - } - break; - case 'H': - case 'f': - { - int x = st.parms[0]; - int y = st.parms[1]; - - xy.x = (x >= cols) ? cols-1 : x; - xy.y = (y >= rows) ? rows-1 : y; - } - break; - case 'J': - { - if ( st.parms[0] == 2 ) { - ansicon_erase(0, 0, cols-1, rows-1); - } else { - ansicon_erase(xy.x, xy.y, cols-1, xy.y); - if ( xy.y < rows-1 ) - ansicon_erase(0, xy.y+1, cols-1, rows-1); + } else { + switch ( ch ) { + case 'A': + { + int y = xy.y - p0; + xy.y = (y < 0) ? 0 : y; } - } - break; - case 'K': - { - if ( st.parms[0] == 2 ) - ansicon_erase(0, xy.y, cols-1, xy.y); - else - ansicon_erase(xy.x, xy.y, cols-1, xy.y); - } - break; - case 'm': - { - static const int ansi2pc[8] = { 0, 4, 2, 6, 1, 5, 3, 7 }; + break; + case 'B': + { + int y = xy.y + p0; + xy.y = (y >= rows) ? rows-1 : y; + } + break; + case 'C': + { + int x = xy.x + p0; + xy.x = (x >= cols) ? cols-1 : x; + } + break; + case 'D': + { + int x = xy.x - p0; + xy.x = (x < 0) ? 0 : x; + } + break; + case 'E': + { + int y = xy.y + p0; + xy.y = (y >= rows) ? rows-1 : y; + xy.x = 0; + } + break; + case 'F': + { + int y = xy.y - p0; + xy.y = (y < 0) ? 0 : y; + xy.x = 0; + } + break; + case 'H': + case 'f': + { + int x = st.parms[0] - 1; + int y = st.parms[1] - 1; - int i; - for ( i = 0 ; i < st.nparms ; i++ ) { - int a = st.parms[i]; - switch ( a ) { + xy.x = (x >= cols) ? cols-1 : (x < 0) ? 0 : x; + xy.y = (y >= rows) ? rows-1 : (y < 0) ? 0 : y; + } + break; + case 'J': + { + switch ( st.parms[0] ) { case 0: - st.fg = 7; - st.bg = 7; - st.intensity = 1; - st.underline = 0; - st.blink = 0; - st.reverse = 0; + ansicon_erase(xy.x, xy.y, cols-1, xy.y); + if ( xy.y < rows-1 ) + ansicon_erase(0, xy.y+1, cols-1, rows-1); break; + case 1: - st.intensity = 2; + if ( xy.y > 0 ) + ansicon_erase(0, 0, cols-1, xy.y-1); + if ( xy.y > 0 ) + ansicon_erase(0, xy.y, xy.x-1, xy.y); break; + case 2: - st.intensity = 0; - break; - case 4: - st.underline = 1; - break; - case 5: - st.blink = 1; - break; - case 7: - st.reverse = 1; - break; - case 21: - case 22: - st.intensity = 1; - break; - case 24: - st.underline = 0; + ansicon_erase(0, 0, cols-1, rows-1); break; - case 25: - st.blink = 0; - break; - case 27: - st.reverse = 0; - break; - case 30 ... 37: - st.fg = ansi2pc[a-30]; - break; - case 38: - st.fg = 7; - st.underline = 1; + + default: + /* Ignore */ break; - case 39: - st.fg = 7; - st.underline = 0; + } + } + break; + case 'K': + { + switch ( st.parms[0] ) { + case 0: + ansicon_erase(xy.x, xy.y, cols-1, xy.y); break; - case 40 ... 47: - st.bg = ansi2pc[a-40]; + + case 1: + if ( xy.x > 0 ) + ansicon_erase(0, xy.y, xy.x-1, xy.y); break; - case 49: - st.bg = 7; + + case 2: + ansicon_erase(0, xy.y, cols-1, xy.y); break; + default: - /* Do nothing */ + /* Ignore */ break; } } - - /* Turn into an attribute code */ + break; + case 'm': { - int bg = st.bg; - int fg; - - if ( st.underline ) - fg = 0x01; - else if ( st.intensity == 0 ) - fg = 0x08; - else - fg = st.fg; + static const int ansi2pc[8] = { 0, 4, 2, 6, 1, 5, 3, 7 }; - if ( st.reverse ) { - bg = fg & 0x07; - fg &= 0x08; - fg |= st.bg; + int i; + for ( i = 0 ; i <= st.nparms ; i++ ) { + int a = st.parms[i]; + switch ( a ) { + case 0: + st.fg = 7; + st.bg = 0; + st.intensity = 1; + st.underline = 0; + st.blink = 0; + st.reverse = 0; + break; + case 1: + st.intensity = 2; + break; + case 2: + st.intensity = 0; + break; + case 4: + st.underline = 1; + break; + case 5: + st.blink = 1; + break; + case 7: + st.reverse = 1; + break; + case 21: + case 22: + st.intensity = 1; + break; + case 24: + st.underline = 0; + break; + case 25: + st.blink = 0; + break; + case 27: + st.reverse = 0; + break; + case 30 ... 37: + st.fg = ansi2pc[a-30]; + break; + case 38: + st.fg = 7; + st.underline = 1; + break; + case 39: + st.fg = 7; + st.underline = 0; + break; + case 40 ... 47: + st.bg = ansi2pc[a-40]; + break; + case 49: + st.bg = 7; + break; + default: + /* Do nothing */ + break; + } } + + /* Turn into an attribute code */ + { + int bg = st.bg; + int fg; - if ( st.blink ) - bg ^= 0x08; + if ( st.underline ) + fg = 0x01; + else if ( st.intensity == 0 ) + fg = 0x08; + else + fg = st.fg; - if ( st.intensity == 2 ) - fg ^= 0x08; + if ( st.reverse ) { + bg = fg & 0x07; + fg &= 0x08; + fg |= st.bg; + } - st.attr = (bg << 4) | fg; + if ( st.blink ) + bg ^= 0x08; + + if ( st.intensity == 2 ) + fg ^= 0x08; + + st.attr = (bg << 4) | fg; + } } + break; + case 's': + st.saved_xy = xy; + break; + case 'u': + xy = st.saved_xy; + break; } - break; - case 's': - st.saved_xy = xy; - break; - case 'u': - xy = st.saved_xy; - break; + st.state = st_init; } } - } while ( again ); + break; + } /* If we fell off the end of the screen, adjust */ if ( xy.x >= cols ) { xy.x = 0; xy.y++; - if ( xy.y >= rows ) { - xy.y = 0; - ireg.eax.w[0] = 0x0601; - ireg.ebx.b[1] = st.attr; - ireg.ecx.w[0] = 0; - ireg.edx.b[1] = rows-1; - ireg.edx.b[0] = cols-1; - __intcall(0x10, &ireg, NULL); /* Scroll */ - } + } + while ( xy.y >= rows ) { + xy.y--; + ireg.eax.w[0] = 0x0601; + ireg.ebx.b[1] = st.attr; + ireg.ecx.w[0] = 0; + ireg.edx.b[1] = rows-1; + ireg.edx.b[0] = cols-1; + __intcall(0x10, &ireg, NULL); /* Scroll */ } /* Update cursor position */ - ireg.eax.b[1] = 0x04; - ireg.ebx.b[1] = BIOS_PAGE; + ireg.eax.b[1] = 0x02; + ireg.ebx.b[1] = page; ireg.edx.b[1] = xy.y; ireg.edx.b[0] = xy.x; __intcall(0x10, &ireg, NULL); } -static ssize_t ansicon_write(struct file_info *fp, const void *buf, size_t count) +ssize_t __ansicon_write(struct file_info *fp, const void *buf, size_t count) { - com32sys_t ireg; - const char *bufp = buf; + const unsigned char *bufp = buf; size_t n = 0; (void)fp; - memset(&ireg, 0, sizeof ireg); - ireg.eax.b[1] = 0x04; - while ( count-- ) { ansicon_putchar(*bufp++); n++; @@ -411,6 +425,6 @@ const struct output_dev dev_ansicon_w = { .dev_magic = __DEV_MAGIC, .flags = __DEV_TTY | __DEV_OUTPUT, .fileflags = O_WRONLY | O_CREAT | O_TRUNC | O_APPEND, - .write = ansicon_write, + .write = __ansicon_write, .close = NULL, }; diff --git a/com32/lib/sys/ansiserial_write.c b/com32/lib/sys/ansiserial_write.c new file mode 100644 index 00000000..95f1c747 --- /dev/null +++ b/com32/lib/sys/ansiserial_write.c @@ -0,0 +1,56 @@ +#ident "$Id$" +/* ----------------------------------------------------------------------- * + * + * Copyright 2004 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * ansiserial_write.c + * + * Write to both to the ANSI console and the serial port + */ + +#include <errno.h> +#include <string.h> +#include <com32.h> +#include <minmax.h> +#include "file.h" + +extern ssize_t __ansicon_write(struct file_info *, const void *, size_t); +extern ssize_t __serial_write(struct file_info *, const void *, size_t); + +static ssize_t __ansiserial_write(struct file_info *fp, const void *buf, size_t count) +{ + __ansicon_write(fp, buf, count); + return __serial_write(fp, buf, count); +} + +const struct output_dev dev_ansiserial_w = { + .dev_magic = __DEV_MAGIC, + .flags = __DEV_TTY | __DEV_OUTPUT, + .fileflags = O_WRONLY | O_CREAT | O_TRUNC | O_APPEND, + .write = __ansiserial_write, + .close = NULL, +}; diff --git a/com32/lib/sys/serial_write.c b/com32/lib/sys/serial_write.c index 27fd73ca..44f3137f 100644 --- a/com32/lib/sys/serial_write.c +++ b/com32/lib/sys/serial_write.c @@ -38,7 +38,7 @@ #include <minmax.h> #include "file.h" -static ssize_t __serial_write(struct file_info *fp, const void *buf, size_t count) +ssize_t __serial_write(struct file_info *fp, const void *buf, size_t count) { com32sys_t ireg; const char *bufp = buf; diff --git a/com32/modules/Makefile b/com32/modules/Makefile index af72f6bd..cfd44b43 100644 --- a/com32/modules/Makefile +++ b/com32/modules/Makefile @@ -35,7 +35,7 @@ LIBGCC := $(shell $(CC) --print-libgcc) .SUFFIXES: .lss .c .o .elf .c32 -all: hello.c32 +all: hello.c32 fancyhello.c32 .PRECIOUS: %.o %.o: %.S diff --git a/com32/modules/fancyhello.c b/com32/modules/fancyhello.c new file mode 100644 index 00000000..a59be43a --- /dev/null +++ b/com32/modules/fancyhello.c @@ -0,0 +1,44 @@ +#ident "$Id$" +/* ----------------------------------------------------------------------- * + * + * Copyright 2004 H. Peter Anvin - All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, Inc., 53 Temple Place Ste 330, + * Bostom MA 02111-1307, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +/* + * fancyhello.c + * + * Hello, World! using libcom32 and ASI console + */ + +#include <string.h> +#include <stdio.h> +#include <console.h> + +int main(void) +{ + char buffer[1024]; + + /* Write both to the ANSI console and the serial port, if configured */ + openconsole(&dev_stdcon_r, &dev_ansiserial_w); + + printf("(lifesign)\r\n(another)\r\n(another)\r\n"); + printf("\033[1;33;44m *** \033[37mHello, World!\033[33m *** \033[0m\r\n"); + + for (;;) { + printf("\033[1;36m>\033[0m "); + fgets(buffer, sizeof buffer, stdin); + /* fgets() prints an \n for us, but not \r */ + putchar('\r'); + if ( !strncmp(buffer, "exit", 4) ) + break; + printf("\033[1m:\033[0m %s\r", buffer); + } + return 0; +} diff --git a/com32/modules/hello.c b/com32/modules/hello.c index 98964e04..7d0504bc 100644 --- a/com32/modules/hello.c +++ b/com32/modules/hello.c @@ -1,7 +1,7 @@ #ident "$Id$" /* ----------------------------------------------------------------------- * * - * Copyright 2002 H. Peter Anvin - All Rights Reserved + * Copyright 2004 H. Peter Anvin - All Rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by |