X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=bootcensus;a=blobdiff_plain;f=src%2Fcontty.c;fp=src%2Fcontty.c;h=9a78ca2a7bf53be4a4129823d9a7886cb72e6562;hp=0000000000000000000000000000000000000000;hb=d1e8a437c1fab4535f82c4c214ec3330ac32e48d;hpb=34ae2440d7cd133051523bce2aac0760cf8296eb diff --git a/src/contty.c b/src/contty.c new file mode 100644 index 0000000..9a78ca2 --- /dev/null +++ b/src/contty.c @@ -0,0 +1,202 @@ +#include +#include +#include "contty.h" +#include "serial.h" +#include "asmops.h" +#include "config.h" + +#define VIRT_ROWS 200 + +#define NCOLS 80 +#define NROWS 25 +#define TEXT_ADDR ((char*)0xb8000) + +#define CRTC_ADDR 0x3d4 +#define CRTC_DATA 0x3d5 + +#define CRTC_REG_CURSTART 0x0a +#define CRTC_REG_CUREND 0x0b +#define CRTC_REG_START_H 0x0c +#define CRTC_REG_START_L 0x0d +#define CRTC_REG_CURLOC_H 0x0e +#define CRTC_REG_CURLOC_L 0x0f + +#define VMEM_CHAR(c, attr) \ + ((uint16_t)(c) | ((uint16_t)(attr) << 8)) + +static void scroll(void); +static void crtc_cursor(int x, int y); +static void crtc_setstart(int y); +static inline unsigned char crtc_read(int reg); +static inline void crtc_write(int reg, unsigned char val); +static inline void crtc_write_bits(int reg, unsigned char val, unsigned char mask); + +extern int cursor_x, cursor_y; +static unsigned char txattr = 0x07; +static int start_line; + +int con_init(void) +{ +#ifdef CON_SERIAL + ser_open(0, 9600, SER_8N1); +#endif + +#ifdef CON_TEXTMODE + con_show_cursor(1); + crtc_setstart(0); + crtc_cursor(cursor_x, cursor_y); + /* + printf("curloc: %x %x\n", (unsigned int)crtc_read(CRTC_REG_CURLOC_H), + (unsigned int)crtc_read(CRTC_REG_CURLOC_L)); + printf("curstart: %x\n", (unsigned int)crtc_read(CRTC_REG_CURSTART)); + printf("curend: %x\n", (unsigned int)crtc_read(CRTC_REG_CUREND)); + */ +#endif + + return 0; +} + +void con_show_cursor(int show) +{ +#ifdef CON_TEXTMODE + unsigned char val = show ? 0 : 0x20; + + crtc_write_bits(CRTC_REG_CURSTART, val, 0x20); +#endif +} + +void con_cursor(int x, int y) +{ +#ifdef CON_TEXTMODE + cursor_x = x; + cursor_y = y; + crtc_cursor(x, y); +#endif +} + +void con_fgcolor(int c) +{ + txattr = (txattr & 0xf0) | c; +} + +void con_bgcolor(int c) +{ + txattr = (txattr & 0x0f) | (c << 4); +} + +void con_clear(void) +{ +#ifdef CON_TEXTMODE + memset(TEXT_ADDR, 0, NCOLS * NROWS * 2); + + start_line = 0; + crtc_setstart(0); + + cursor_x = cursor_y = 0; + crtc_cursor(0, 0); +#endif +} + +static inline void linefeed(void) +{ + if(++cursor_y >= NROWS) { + scroll(); + --cursor_y; + } +} + +void con_putchar(int c) +{ +#ifdef CON_TEXTMODE + uint16_t *ptr; + + switch(c) { + case '\n': + linefeed(); + case '\r': + cursor_x = 0; + crtc_cursor(cursor_x, cursor_y); + break; + + case '\t': + cursor_x = (cursor_x & 0x7) + 8; + if(cursor_x >= NCOLS) { + linefeed(); + cursor_x = 0; + } + crtc_cursor(cursor_x, cursor_y); + break; + + default: + ptr = (uint16_t*)TEXT_ADDR; + ptr[(cursor_y + start_line) * NCOLS + cursor_x] = VMEM_CHAR(c, txattr); + + if(++cursor_x >= NCOLS) { + linefeed(); + cursor_x = 0; + } + crtc_cursor(cursor_x, cursor_y); + } +#endif + +#ifdef CON_SERIAL + ser_putchar(c); +#endif +} + +static void scroll(void) +{ + int new_line; + + if(++start_line > VIRT_ROWS - NROWS) { + /* The bottom of the visible range reached the end of our text buffer. + * Copy the rest of the lines to the top and reset start_line. + */ + memcpy(TEXT_ADDR, TEXT_ADDR + start_line * NCOLS, (NROWS - 1) * NCOLS * 2); + start_line = 0; + } + + /* clear the next line that will be revealed by scrolling */ + new_line = start_line + NROWS - 1; + memset16(TEXT_ADDR + new_line * NCOLS, VMEM_CHAR(' ', txattr), NCOLS); + crtc_setstart(start_line); +} + +static void crtc_cursor(int x, int y) +{ + unsigned int addr; + + addr = (y + start_line) * NCOLS + x; + + crtc_write(CRTC_REG_CURLOC_L, addr); + crtc_write(CRTC_REG_CURLOC_H, addr >> 8); +} + +static void crtc_setstart(int y) +{ + unsigned int addr = y * NCOLS; + + crtc_write(CRTC_REG_START_L, addr); + crtc_write(CRTC_REG_START_H, addr >> 8); +} + +static inline unsigned char crtc_read(int reg) +{ + outb(reg, CRTC_ADDR); + return inb(CRTC_DATA); +} + +static inline void crtc_write(int reg, unsigned char val) +{ + outb(reg, CRTC_ADDR); + outb(val, CRTC_DATA); +} + +static inline void crtc_write_bits(int reg, unsigned char val, unsigned char mask) +{ + unsigned char prev; + outb(reg, CRTC_ADDR); + prev = inb(CRTC_DATA); + val = (prev & ~mask) | (val & mask); + outb(val, CRTC_DATA); +}