build multiple disk images, and console to vid & serial
[eightysix] / kern / src / vid.c
1 #include <string.h>
2 #include "vid.h"
3 #include "asmutil.h"
4 #include "dbg.h"
5
6 #define CRTC_ADDR_PORT  (iobase | 4)
7 #define CRTC_DATA_PORT  (iobase | 5)
8
9 /* CRTC registers */
10 #define CRTC_START_H    0x0c
11 #define CRTC_START_L    0x0d
12 #define CRTC_CURPOS_H   0x0e
13 #define CRTC_CURPOS_L   0x0f
14
15 static void detect_video(void);
16 static int detect_vgainfo(void);
17 static int detect_egainfo(void);
18 static void detect_eqlist(void);
19 static void crtc_write(int reg, unsigned char val);
20
21 static uint16_t __far *vmem;
22 static int iobase;
23
24 static uint16_t cur_attr;
25 static int cur_x, cur_y;
26 static int cur_scroll;
27 static int mono;
28
29 int vid_type;
30
31
32 void vid_init(void)
33 {
34         detect_video();
35         if(mono) {
36                 vmem = MK_FP(0xb000, 0);
37                 iobase = 0x3b0;
38         } else {
39                 vmem = MK_FP(0xb800, 0);
40                 iobase = 0x3d0;
41         }
42
43         vid_reset();
44 }
45
46 static void detect_video(void)
47 {
48         mono = 0;
49         vid_type = VID_UNK;
50         return;         /* XXX */
51
52         if(detect_vgainfo() == 0) {
53                 return;
54         }
55         if(detect_egainfo() == 0) {
56                 return;
57         }
58         detect_eqlist();
59 }
60
61 static int detect_vgainfo(void)
62 {
63         union regs regs;
64
65         regs.w.ax = 0x1a00;
66         int86(0x10, &regs, &regs);
67         if(regs.h.al != 0x1a) {
68                 return -1;
69         }
70
71         switch(regs.h.bl) {
72         case 1:
73                 vid_type = VID_MDA;
74                 mono = 1;
75                 break;
76         case 2:
77                 vid_type = VID_CGA;
78                 break;
79         case 4:
80                 vid_type = VID_EGA;
81                 break;
82         case 5:
83                 vid_type = VID_EGA;
84                 mono = 1;
85                 break;
86         case 6:
87                 vid_type = VID_PGA;
88                 break;
89         case 7:
90                 vid_type = VID_VGA;
91                 mono = 1;
92                 break;
93         case 8:
94                 vid_type = VID_VGA;
95                 break;
96         case 0xa:
97         case 0xc:
98                 vid_type = VID_MCGA;
99                 break;
100         case 0xb:
101                 vid_type = VID_MCGA;
102                 mono = 1;
103                 break;
104         default:
105                 return -1;
106         }
107         return 0;
108 }
109
110 static int detect_egainfo(void)
111 {
112         union regs regs;
113
114         regs.w.ax = 0x1200;
115         regs.w.bx = 0xff10;
116         int86(0x10, &regs, &regs);
117         if(regs.h.bh == 0xff) {
118                 return -1;
119         }
120
121         vid_type = VID_EGA;
122         mono = regs.h.bh;
123         return 0;
124 }
125
126 static void detect_eqlist(void)
127 {
128         union regs regs;
129
130         int86(0x11, &regs, &regs);
131         switch(regs.w.ax & 0x30) {
132         case 0:
133                 vid_type = VID_EGA;
134                 break;
135
136         case 0x10:
137         case 0x20:
138                 vid_type = VID_CGA;
139                 break;
140
141         case 0x30:
142                 vid_type = VID_MDA;
143                 mono = 1;
144                 break;
145         }
146 }
147
148 void vid_reset(void)
149 {
150         vid_fgcolor(LTGREY);
151         vid_bgcolor(BLACK);
152         vid_scroll(0);
153         vid_setcursor(0, 0);
154         fmemset(vmem, 0, 80 * 25 * 2);
155 }
156
157 void vid_clearline(int row)
158 {
159         int i;
160         uint16_t __far *ptr;
161
162         row += cur_scroll;
163
164         ptr = vmem + row * 80;
165         for(i=0; i<80; i++) {
166                 ptr[i] = cur_attr;
167         }
168
169         if(row - 32 >= 0) {
170                 /* write a copy to wrap-around future scrolling */
171                 ptr -= 80 * 32;
172                 for(i=0; i<80; i++) {
173                         ptr[i] = cur_attr;
174                 }
175         }
176 }
177
178 void vid_clear(void)
179 {
180         int i;
181         for(i=0; i<25; i++) {
182                 vid_clearline(i);
183         }
184 }
185
186 void vid_scroll(int line)
187 {
188         int offs;
189         cur_scroll = line & 0x1f;
190         offs = cur_scroll * 80;
191         crtc_write(CRTC_START_H, offs >> 8);
192         crtc_write(CRTC_START_L, offs);
193 }
194
195 void vid_setcursor(int x, int y)
196 {
197         int loc = (y + cur_scroll) * 80 + x;
198         cur_x = x;
199         cur_y = y;
200         crtc_write(CRTC_CURPOS_H, loc >> 8);
201         crtc_write(CRTC_CURPOS_L, loc);
202 }
203
204 void vid_fgcolor(int color)
205 {
206         cur_attr = (cur_attr & 0xf0) | color;
207 }
208
209 void vid_bgcolor(int color)
210 {
211         cur_attr = (cur_attr & 0x0f) | (color << 4);
212 }
213
214 void vid_char(int x, int y, int c, int attr)
215 {
216         uint16_t __far *ptr;
217         uint16_t val = c | (attr << 8);
218
219         y += cur_scroll;
220
221         ptr = vmem + y * 80 + x;
222         *ptr = val;
223
224         if(y - 32 >= 0) {
225                 /* write a copy to wrap-around future scrolling */
226                 ptr -= 80 * 32;
227                 *ptr = val;
228         }
229 }
230
231 void vid_text(int x, int y, const char *s, int attr)
232 {
233         int len = 0;
234         uint16_t __far *ptr;
235
236         y += cur_scroll;
237
238         ptr = vmem + y * 80 + x;
239         while(*s) {
240                 *ptr++ = *s++ | (attr << 8);
241                 len++;
242         }
243
244         if(y - 32 >= 0) {
245                 /* write a copy to wrap-around future scrolling */
246                 ptr -= 80 * 32 + len;
247                 s -= len;
248                 while(*s) {
249                         *ptr++ = *s++ | (attr << 8);
250                 }
251         }
252 }
253
254 void vid_putchar(int c)
255 {
256         int x;
257
258         switch(c) {
259         case '\r':
260                 vid_setcursor(0, cur_y);
261                 break;
262
263         case '\n':
264                 if(cur_y >= cur_scroll + 25) {
265                         vid_scroll(cur_scroll + 1);
266                         vid_setcursor(0, cur_y);
267                 } else {
268                         vid_setcursor(0, cur_y + 1);
269                 }
270                 break;
271
272         case '\t':
273                 x = (cur_x + 8) & 0xf8;
274                 if(x >= 80) {
275                         vid_putchar('\n');
276                 } else {
277                         vid_setcursor(x, cur_y);
278                 }
279                 break;
280
281         default:
282                 vid_char(cur_x, cur_y, c, cur_attr);
283                 if(cur_x + 1 >= 80) {
284                         vid_putchar('\n');
285                 } else {
286                         vid_setcursor(cur_x + 1, cur_y);
287                 }
288         }
289 }
290
291 static void crtc_write(int reg, unsigned char val)
292 {
293         outp(CRTC_ADDR_PORT, reg);
294         outp(CRTC_DATA_PORT, val);
295 }