tty.c (2196B)
1 #include "io.h" 2 #include "port.h" 3 #include "tty.h" 4 5 static struct tty_info tty; 6 7 void 8 tty_clear(void) 9 { 10 size_t y, x; 11 12 tty_curs_enable(0x0e, 0x0f); /* Low cursor shape. */ 13 tty_curs_setpos(0, 0); 14 tty.row = 0; 15 tty.col = 0; 16 tty.color = VGA_SET_COLOR(VGA_BLUE, VGA_WHITE); 17 tty.buf = (uint16_t *)_VGA_MEM; 18 for (x = 0; x < _VGA_COLS; x++) 19 for (y = 0; y < _VGA_ROWS; y++) 20 tty.buf[y * _VGA_COLS + x] = _PUTC(' '); 21 } 22 23 void 24 tty_putc(char c) 25 { 26 switch (c) { 27 case '\n': 28 tty.row++; 29 tty.col = 0; 30 break; 31 case '\b': 32 tty.col--; 33 tty.buf[tty.row * _VGA_COLS + tty.col] = _PUTC(' '); 34 break; 35 case '\r': 36 tty.col = 0; 37 break; 38 case '\t': 39 tty.col += 8; 40 break; 41 default: 42 tty.buf[tty.row * _VGA_COLS + tty.col] = _PUTC(c); 43 tty.col++; 44 } 45 46 if (tty.row >= _VGA_ROWS) { 47 tty.row = 0; 48 tty.col = 0; 49 } 50 if (tty.col >= _VGA_COLS) { 51 tty.row++; 52 tty.col = 0; 53 } 54 tty_curs_setpos(tty.col, tty.row); 55 } 56 57 void 58 tty_write(const char *str) 59 { 60 while (*str != '\0') 61 tty_putc(*str++); 62 } 63 64 /* 65 * The arguments `start` and `end` define the shape of the cursor. 66 * The lowest scaline value is 0x00 and the highest 0x0f. A cursor shape 67 * with `start = 0x00` and `end = 0x0f` is effectively a block cursor. 68 */ 69 void 70 tty_curs_enable(uint8_t start, uint8_t end) 71 { 72 /* 0x0a: Low cursor shape */ 73 outb(P_CURS_CMD, 0x0a); 74 outb(P_CURS_DATA, (inb(P_CURS_DATA) & 0xc0) | start); 75 outb(P_CURS_CMD, 0x0b); 76 outb(P_CURS_DATA, (inb(P_CURS_DATA) & 0xe0) | end); 77 } 78 79 void 80 tty_curs_disable(void) 81 { 82 outb(P_CURS_CMD, 0x0a); 83 /* 84 * Bit representation: 85 * 7 6 | 5 | 4 0 86 * Unused | Disable | Shape 87 */ 88 outb(P_CURS_DATA, 0x20); 89 } 90 91 /* 92 * Returns the position in `y * _VGA_COLS + x` format. 93 * x = pos % _VGA_COLS 94 * y = pos / _VGA_COLS 95 */ 96 uint16_t 97 tty_curs_getpos(void) 98 { 99 uint16_t pos = 0; 100 101 outb(P_CURS_CMD, 0x0e); 102 pos |= (uint16_t)inb(P_CURS_DATA) << 8; 103 outb(P_CURS_CMD, 0x0f); 104 pos |= inb(P_CURS_DATA); 105 106 return pos; 107 } 108 109 void 110 tty_curs_setpos(int x, int y) 111 { 112 uint16_t pos = y * _VGA_COLS + x; 113 114 /* Expect 8 highest bits */ 115 outb(P_CURS_CMD, 0x0e); 116 outb(P_CURS_DATA, (uint8_t)((pos >> 8) & 0xff)); 117 /* Expect 8 lowest bits */ 118 outb(P_CURS_CMD, 0x0f); 119 outb(P_CURS_DATA, (uint8_t)(pos & 0xff)); 120 }