e5a913f2c97256f76203c1ae29fa808c76596413
[lunaix-os.git] / lunaix-os / kernel / tty / tty.c
1 #include <klibc/string.h>
2 #include <lunaix/spike.h>
3 #include <lunaix/tty/tty.h>
4 #include <stdint.h>
5
6 #include <sys/port_io.h>
7
8 vga_attribute* tty_vga_buffer;
9
10 vga_attribute tty_theme_color = VGA_COLOR_BLACK;
11
12 inline void
13 tty_clear()
14 {
15     asm volatile("rep stosw" ::"D"(tty_vga_buffer),
16                  "c"(TTY_HEIGHT * TTY_WIDTH),
17                  "a"(tty_theme_color)
18                  : "memory");
19 }
20
21 void
22 tty_init(void* vga_buf)
23 {
24     tty_vga_buffer = (vga_attribute*)vga_buf;
25
26     tty_clear();
27
28     port_wrbyte(0x3D4, 0x0A);
29     port_wrbyte(0x3D5, (port_rdbyte(0x3D5) & 0xC0) | 13);
30
31     port_wrbyte(0x3D4, 0x0B);
32     port_wrbyte(0x3D5, (port_rdbyte(0x3D5) & 0xE0) | 15);
33 }
34
35 void
36 tty_set_cursor(u8_t x, u8_t y)
37 {
38     if (x >= TTY_WIDTH || y >= TTY_HEIGHT) {
39         x = y = 0;
40     }
41     u32_t pos = y * TTY_WIDTH + x;
42     port_wrbyte(0x3D4, 14);
43     port_wrbyte(0x3D5, pos / 256);
44     port_wrbyte(0x3D4, 15);
45     port_wrbyte(0x3D5, pos % 256);
46 }
47
48 void
49 tty_set_theme(vga_attribute fg, vga_attribute bg)
50 {
51     tty_theme_color = (bg << 4 | fg) << 8;
52 }
53
54 void
55 tty_flush_buffer(struct fifo_buf* buf)
56 {
57     int x = 0, y = 0;
58
59     // Clear screen
60     tty_clear();
61
62     char chr;
63     while (fifo_readone_async(buf, (u8_t*)&chr)) {
64         switch (chr) {
65             case '\t':
66                 x += 4;
67                 break;
68             case '\n':
69                 y++;
70                 // fall through
71             case '\r':
72                 x = 0;
73                 break;
74             default:
75                 *(tty_vga_buffer + x + y * TTY_WIDTH) =
76                     (tty_theme_color | chr);
77                 (x)++;
78                 break;
79         }
80
81         if (x >= TTY_WIDTH) {
82             x = 0;
83             y++;
84         }
85         if (y >= TTY_HEIGHT) {
86             y--;
87             break;
88         }
89     }
90
91     tty_set_cursor(x, y);
92 }
93
94 void
95 tty_clear_line(int line_num)
96 {
97     asm volatile("rep stosw" ::"D"(tty_vga_buffer + line_num * TTY_WIDTH),
98                  "c"(TTY_WIDTH),
99                  "a"(tty_theme_color)
100                  : "memory");
101 }
102
103 void
104 tty_put_str_at(char* str, int x, int y)
105 {
106     char c;
107     while ((c = (*str)) && y < TTY_HEIGHT) {
108         *(tty_vga_buffer + x + y * TTY_WIDTH) = c | tty_theme_color;
109         x++;
110         if (x >= TTY_WIDTH) {
111             y++;
112             x = 0;
113         }
114         str++;
115     }
116 }