main kernel startup, libc, console tty, asmops, build flags fixes
[bootcensus] / src / contty.c
1 #include <stdio.h>
2 #include <string.h>
3 #include "contty.h"
4 #include "serial.h"
5 #include "asmops.h"
6 #include "config.h"
7
8 #define VIRT_ROWS       200
9
10 #define NCOLS           80
11 #define NROWS           25
12 #define TEXT_ADDR       ((char*)0xb8000)
13
14 #define CRTC_ADDR       0x3d4
15 #define CRTC_DATA       0x3d5
16
17 #define CRTC_REG_CURSTART       0x0a
18 #define CRTC_REG_CUREND         0x0b
19 #define CRTC_REG_START_H        0x0c
20 #define CRTC_REG_START_L        0x0d
21 #define CRTC_REG_CURLOC_H       0x0e
22 #define CRTC_REG_CURLOC_L       0x0f
23
24 #define VMEM_CHAR(c, attr) \
25         ((uint16_t)(c) | ((uint16_t)(attr) << 8))
26
27 static void scroll(void);
28 static void crtc_cursor(int x, int y);
29 static void crtc_setstart(int y);
30 static inline unsigned char crtc_read(int reg);
31 static inline void crtc_write(int reg, unsigned char val);
32 static inline void crtc_write_bits(int reg, unsigned char val, unsigned char mask);
33
34 extern int cursor_x, cursor_y;
35 static unsigned char txattr = 0x07;
36 static int start_line;
37
38 int con_init(void)
39 {
40 #ifdef CON_SERIAL
41         ser_open(0, 9600, SER_8N1);
42 #endif
43
44 #ifdef CON_TEXTMODE
45         con_show_cursor(1);
46         crtc_setstart(0);
47         crtc_cursor(cursor_x, cursor_y);
48         /*
49         printf("curloc: %x %x\n", (unsigned int)crtc_read(CRTC_REG_CURLOC_H),
50                         (unsigned int)crtc_read(CRTC_REG_CURLOC_L));
51         printf("curstart: %x\n", (unsigned int)crtc_read(CRTC_REG_CURSTART));
52         printf("curend: %x\n", (unsigned int)crtc_read(CRTC_REG_CUREND));
53         */
54 #endif
55
56         return 0;
57 }
58
59 void con_show_cursor(int show)
60 {
61 #ifdef CON_TEXTMODE
62         unsigned char val = show ? 0 : 0x20;
63
64         crtc_write_bits(CRTC_REG_CURSTART, val, 0x20);
65 #endif
66 }
67
68 void con_cursor(int x, int y)
69 {
70 #ifdef CON_TEXTMODE
71         cursor_x = x;
72         cursor_y = y;
73         crtc_cursor(x, y);
74 #endif
75 }
76
77 void con_fgcolor(int c)
78 {
79         txattr = (txattr & 0xf0) | c;
80 }
81
82 void con_bgcolor(int c)
83 {
84         txattr = (txattr & 0x0f) | (c << 4);
85 }
86
87 void con_clear(void)
88 {
89 #ifdef CON_TEXTMODE
90         memset(TEXT_ADDR, 0, NCOLS * NROWS * 2);
91
92         start_line = 0;
93         crtc_setstart(0);
94
95         cursor_x = cursor_y = 0;
96         crtc_cursor(0, 0);
97 #endif
98 }
99
100 static inline void linefeed(void)
101 {
102         if(++cursor_y >= NROWS) {
103                 scroll();
104                 --cursor_y;
105         }
106 }
107
108 void con_putchar(int c)
109 {
110 #ifdef CON_TEXTMODE
111         uint16_t *ptr;
112
113         switch(c) {
114         case '\n':
115                 linefeed();
116         case '\r':
117                 cursor_x = 0;
118                 crtc_cursor(cursor_x, cursor_y);
119                 break;
120
121         case '\t':
122                 cursor_x = (cursor_x & 0x7) + 8;
123                 if(cursor_x >= NCOLS) {
124                         linefeed();
125                         cursor_x = 0;
126                 }
127                 crtc_cursor(cursor_x, cursor_y);
128                 break;
129
130         default:
131                 ptr = (uint16_t*)TEXT_ADDR;
132                 ptr[(cursor_y + start_line) * NCOLS + cursor_x] = VMEM_CHAR(c, txattr);
133
134                 if(++cursor_x >= NCOLS) {
135                         linefeed();
136                         cursor_x = 0;
137                 }
138                 crtc_cursor(cursor_x, cursor_y);
139         }
140 #endif
141
142 #ifdef CON_SERIAL
143         ser_putchar(c);
144 #endif
145 }
146
147 static void scroll(void)
148 {
149         int new_line;
150
151         if(++start_line > VIRT_ROWS - NROWS) {
152                 /* The bottom of the visible range reached the end of our text buffer.
153                  * Copy the rest of the lines to the top and reset start_line.
154                  */
155                 memcpy(TEXT_ADDR, TEXT_ADDR + start_line * NCOLS, (NROWS - 1) * NCOLS * 2);
156                 start_line = 0;
157         }
158
159         /* clear the next line that will be revealed by scrolling */
160         new_line = start_line + NROWS - 1;
161         memset16(TEXT_ADDR + new_line * NCOLS, VMEM_CHAR(' ', txattr), NCOLS);
162         crtc_setstart(start_line);
163 }
164
165 static void crtc_cursor(int x, int y)
166 {
167         unsigned int addr;
168
169         addr = (y + start_line) * NCOLS + x;
170
171         crtc_write(CRTC_REG_CURLOC_L, addr);
172         crtc_write(CRTC_REG_CURLOC_H, addr >> 8);
173 }
174
175 static void crtc_setstart(int y)
176 {
177         unsigned int addr = y * NCOLS;
178
179         crtc_write(CRTC_REG_START_L, addr);
180         crtc_write(CRTC_REG_START_H, addr >> 8);
181 }
182
183 static inline unsigned char crtc_read(int reg)
184 {
185         outb(reg, CRTC_ADDR);
186         return inb(CRTC_DATA);
187 }
188
189 static inline void crtc_write(int reg, unsigned char val)
190 {
191         outb(reg, CRTC_ADDR);
192         outb(val, CRTC_DATA);
193 }
194
195 static inline void crtc_write_bits(int reg, unsigned char val, unsigned char mask)
196 {
197         unsigned char prev;
198         outb(reg, CRTC_ADDR);
199         prev = inb(CRTC_DATA);
200         val = (prev & ~mask) | (val & mask);
201         outb(val, CRTC_DATA);
202 }