os

Toy OS
git clone git://git.christosmarg.xyz
Log | Files | Refs | README | LICENSE

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 }