e90d48f0ed7083f05fa1c8cf42cae805ec7c68ef
[seabios.git] / vgasrc / stdvga.c
1 // VGA io port access
2 //
3 // Copyright (C) 2009  Kevin O'Connor <kevin@koconnor.net>
4 // Copyright (C) 2001-2008 the LGPL VGABios developers Team
5 //
6 // This file may be distributed under the terms of the GNU LGPLv3 license.
7
8 #include "stdvga.h" // stdvga_init
9 #include "ioport.h" // outb
10 #include "farptr.h" // SET_FARVAR
11 #include "biosvar.h" // GET_GLOBAL
12 #include "util.h" // memcpy_far
13 #include "vbe.h" // VBE_RETURN_STATUS_FAILED
14 #include "vgabios.h" // find_vga_entry
15
16 // TODO
17 //  * replace direct in/out calls with wrapper functions
18
19
20 /****************************************************************
21  * Attribute control
22  ****************************************************************/
23
24 static void
25 stdvga_screen_disable(void)
26 {
27     inb(VGAREG_ACTL_RESET);
28     outb(0x00, VGAREG_ACTL_ADDRESS);
29 }
30
31 static void
32 stdvga_screen_enable(void)
33 {
34     inb(VGAREG_ACTL_RESET);
35     outb(0x20, VGAREG_ACTL_ADDRESS);
36 }
37
38 void
39 stdvga_set_border_color(u8 color)
40 {
41     inb(VGAREG_ACTL_RESET);
42     outb(0x00, VGAREG_ACTL_ADDRESS);
43     u8 v1 = color & 0x0f;
44     if (v1 & 0x08)
45         v1 += 0x08;
46     outb(v1, VGAREG_ACTL_WRITE_DATA);
47
48     u8 v2 = color & 0x10;
49     int i;
50     for (i = 1; i < 4; i++) {
51         outb(i, VGAREG_ACTL_ADDRESS);
52
53         u8 cur = inb(VGAREG_ACTL_READ_DATA);
54         cur &= 0xef;
55         cur |= v2;
56         outb(cur, VGAREG_ACTL_WRITE_DATA);
57     }
58     outb(0x20, VGAREG_ACTL_ADDRESS);
59 }
60
61 void
62 stdvga_set_overscan_border_color(u8 color)
63 {
64     inb(VGAREG_ACTL_RESET);
65     outb(0x11, VGAREG_ACTL_ADDRESS);
66     outb(color, VGAREG_ACTL_WRITE_DATA);
67     outb(0x20, VGAREG_ACTL_ADDRESS);
68 }
69
70 u8
71 stdvga_get_overscan_border_color(void)
72 {
73     inb(VGAREG_ACTL_RESET);
74     outb(0x11, VGAREG_ACTL_ADDRESS);
75     u8 v = inb(VGAREG_ACTL_READ_DATA);
76     inb(VGAREG_ACTL_RESET);
77     outb(0x20, VGAREG_ACTL_ADDRESS);
78     return v;
79 }
80
81 void
82 stdvga_set_palette(u8 palid)
83 {
84     inb(VGAREG_ACTL_RESET);
85     palid &= 0x01;
86     int i;
87     for (i = 1; i < 4; i++) {
88         outb(i, VGAREG_ACTL_ADDRESS);
89
90         u8 v = inb(VGAREG_ACTL_READ_DATA);
91         v &= 0xfe;
92         v |= palid;
93         outb(v, VGAREG_ACTL_WRITE_DATA);
94     }
95     outb(0x20, VGAREG_ACTL_ADDRESS);
96 }
97
98 void
99 stdvga_set_single_palette_reg(u8 reg, u8 val)
100 {
101     inb(VGAREG_ACTL_RESET);
102     outb(reg, VGAREG_ACTL_ADDRESS);
103     outb(val, VGAREG_ACTL_WRITE_DATA);
104     outb(0x20, VGAREG_ACTL_ADDRESS);
105 }
106
107 u8
108 stdvga_get_single_palette_reg(u8 reg)
109 {
110     inb(VGAREG_ACTL_RESET);
111     outb(reg, VGAREG_ACTL_ADDRESS);
112     u8 v = inb(VGAREG_ACTL_READ_DATA);
113     inb(VGAREG_ACTL_RESET);
114     outb(0x20, VGAREG_ACTL_ADDRESS);
115     return v;
116 }
117
118 void
119 stdvga_set_all_palette_reg(u16 seg, u8 *data_far)
120 {
121     inb(VGAREG_ACTL_RESET);
122     int i;
123     for (i = 0; i < 0x10; i++) {
124         outb(i, VGAREG_ACTL_ADDRESS);
125         u8 val = GET_FARVAR(seg, *data_far);
126         outb(val, VGAREG_ACTL_WRITE_DATA);
127         data_far++;
128     }
129     outb(0x11, VGAREG_ACTL_ADDRESS);
130     outb(GET_FARVAR(seg, *data_far), VGAREG_ACTL_WRITE_DATA);
131     outb(0x20, VGAREG_ACTL_ADDRESS);
132 }
133
134 void
135 stdvga_get_all_palette_reg(u16 seg, u8 *data_far)
136 {
137     int i;
138     for (i = 0; i < 0x10; i++) {
139         inb(VGAREG_ACTL_RESET);
140         outb(i, VGAREG_ACTL_ADDRESS);
141         SET_FARVAR(seg, *data_far, inb(VGAREG_ACTL_READ_DATA));
142         data_far++;
143     }
144     inb(VGAREG_ACTL_RESET);
145     outb(0x11, VGAREG_ACTL_ADDRESS);
146     SET_FARVAR(seg, *data_far, inb(VGAREG_ACTL_READ_DATA));
147     inb(VGAREG_ACTL_RESET);
148     outb(0x20, VGAREG_ACTL_ADDRESS);
149 }
150
151 void
152 stdvga_toggle_intensity(u8 flag)
153 {
154     inb(VGAREG_ACTL_RESET);
155     outb(0x10, VGAREG_ACTL_ADDRESS);
156     u8 val = (inb(VGAREG_ACTL_READ_DATA) & 0xf7) | ((flag & 0x01) << 3);
157     outb(val, VGAREG_ACTL_WRITE_DATA);
158     outb(0x20, VGAREG_ACTL_ADDRESS);
159 }
160
161 void
162 stdvga_select_video_dac_color_page(u8 flag, u8 data)
163 {
164     inb(VGAREG_ACTL_RESET);
165     outb(0x10, VGAREG_ACTL_ADDRESS);
166     u8 val = inb(VGAREG_ACTL_READ_DATA);
167     if (!(flag & 0x01)) {
168         // select paging mode
169         val = (val & 0x7f) | (data << 7);
170         outb(val, VGAREG_ACTL_WRITE_DATA);
171         outb(0x20, VGAREG_ACTL_ADDRESS);
172         return;
173     }
174     // select page
175     inb(VGAREG_ACTL_RESET);
176     outb(0x14, VGAREG_ACTL_ADDRESS);
177     if (!(val & 0x80))
178         data <<= 2;
179     data &= 0x0f;
180     outb(data, VGAREG_ACTL_WRITE_DATA);
181     outb(0x20, VGAREG_ACTL_ADDRESS);
182 }
183
184 void
185 stdvga_read_video_dac_state(u8 *pmode, u8 *curpage)
186 {
187     inb(VGAREG_ACTL_RESET);
188     outb(0x10, VGAREG_ACTL_ADDRESS);
189     u8 val1 = inb(VGAREG_ACTL_READ_DATA) >> 7;
190
191     inb(VGAREG_ACTL_RESET);
192     outb(0x14, VGAREG_ACTL_ADDRESS);
193     u8 val2 = inb(VGAREG_ACTL_READ_DATA) & 0x0f;
194     if (!(val1 & 0x01))
195         val2 >>= 2;
196
197     inb(VGAREG_ACTL_RESET);
198     outb(0x20, VGAREG_ACTL_ADDRESS);
199
200     *pmode = val1;
201     *curpage = val2;
202 }
203
204
205 /****************************************************************
206  * DAC control
207  ****************************************************************/
208
209 void
210 stdvga_set_dac_regs(u16 seg, u8 *data_far, u8 start, int count)
211 {
212     outb(start, VGAREG_DAC_WRITE_ADDRESS);
213     while (count) {
214         outb(GET_FARVAR(seg, *data_far), VGAREG_DAC_DATA);
215         data_far++;
216         outb(GET_FARVAR(seg, *data_far), VGAREG_DAC_DATA);
217         data_far++;
218         outb(GET_FARVAR(seg, *data_far), VGAREG_DAC_DATA);
219         data_far++;
220         count--;
221     }
222 }
223
224 void
225 stdvga_get_dac_regs(u16 seg, u8 *data_far, u8 start, int count)
226 {
227     outb(start, VGAREG_DAC_READ_ADDRESS);
228     while (count) {
229         SET_FARVAR(seg, *data_far, inb(VGAREG_DAC_DATA));
230         data_far++;
231         SET_FARVAR(seg, *data_far, inb(VGAREG_DAC_DATA));
232         data_far++;
233         SET_FARVAR(seg, *data_far, inb(VGAREG_DAC_DATA));
234         data_far++;
235         count--;
236     }
237 }
238
239 void
240 stdvga_set_pel_mask(u8 val)
241 {
242     outb(val, VGAREG_PEL_MASK);
243 }
244
245 u8
246 stdvga_get_pel_mask(void)
247 {
248     return inb(VGAREG_PEL_MASK);
249 }
250
251 void
252 stdvga_save_dac_state(u16 seg, struct saveDACcolors *info)
253 {
254     /* XXX: check this */
255     SET_FARVAR(seg, info->rwmode, inb(VGAREG_DAC_STATE));
256     SET_FARVAR(seg, info->peladdr, inb(VGAREG_DAC_WRITE_ADDRESS));
257     SET_FARVAR(seg, info->pelmask, inb(VGAREG_PEL_MASK));
258     stdvga_get_dac_regs(seg, info->dac, 0, 256);
259     SET_FARVAR(seg, info->color_select, 0);
260 }
261
262 void
263 stdvga_restore_dac_state(u16 seg, struct saveDACcolors *info)
264 {
265     outb(GET_FARVAR(seg, info->pelmask), VGAREG_PEL_MASK);
266     stdvga_set_dac_regs(seg, info->dac, 0, 256);
267     outb(GET_FARVAR(seg, info->peladdr), VGAREG_DAC_WRITE_ADDRESS);
268 }
269
270 void
271 stdvga_perform_gray_scale_summing(u16 start, u16 count)
272 {
273     stdvga_screen_disable();
274     int i;
275     for (i = start; i < start+count; i++) {
276         u8 rgb[3];
277         stdvga_get_dac_regs(GET_SEG(SS), rgb, i, 1);
278
279         // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue )
280         u16 intensity = ((77 * rgb[0] + 151 * rgb[1] + 28 * rgb[2]) + 0x80) >> 8;
281         if (intensity > 0x3f)
282             intensity = 0x3f;
283
284         stdvga_set_dac_regs(GET_SEG(SS), rgb, i, 1);
285     }
286     stdvga_screen_enable();
287 }
288
289
290 /****************************************************************
291  * Memory control
292  ****************************************************************/
293
294 void
295 stdvga_sequ_write(u8 index, u8 value)
296 {
297     outw((value<<8) | index, VGAREG_SEQU_ADDRESS);
298 }
299
300 void
301 stdvga_grdc_write(u8 index, u8 value)
302 {
303     outw((value<<8) | index, VGAREG_GRDC_ADDRESS);
304 }
305
306 void
307 stdvga_set_text_block_specifier(u8 spec)
308 {
309     outw((spec << 8) | 0x03, VGAREG_SEQU_ADDRESS);
310 }
311
312
313 /****************************************************************
314  * Font loading
315  ****************************************************************/
316
317 static void
318 get_font_access(void)
319 {
320     outw(0x0100, VGAREG_SEQU_ADDRESS);
321     outw(0x0402, VGAREG_SEQU_ADDRESS);
322     outw(0x0704, VGAREG_SEQU_ADDRESS);
323     outw(0x0300, VGAREG_SEQU_ADDRESS);
324     outw(0x0204, VGAREG_GRDC_ADDRESS);
325     outw(0x0005, VGAREG_GRDC_ADDRESS);
326     outw(0x0406, VGAREG_GRDC_ADDRESS);
327 }
328
329 static void
330 release_font_access(void)
331 {
332     outw(0x0100, VGAREG_SEQU_ADDRESS);
333     outw(0x0302, VGAREG_SEQU_ADDRESS);
334     outw(0x0304, VGAREG_SEQU_ADDRESS);
335     outw(0x0300, VGAREG_SEQU_ADDRESS);
336     u16 v = (inb(VGAREG_READ_MISC_OUTPUT) & 0x01) ? 0x0e : 0x0a;
337     outw((v << 8) | 0x06, VGAREG_GRDC_ADDRESS);
338     outw(0x0004, VGAREG_GRDC_ADDRESS);
339     outw(0x1005, VGAREG_GRDC_ADDRESS);
340 }
341
342 void
343 stdvga_load_font(u16 seg, void *src_far, u16 count
344                  , u16 start, u8 destflags, u8 fontsize)
345 {
346     get_font_access();
347     u16 blockaddr = ((destflags & 0x03) << 14) + ((destflags & 0x04) << 11);
348     void *dest_far = (void*)(blockaddr + start*32);
349     u16 i;
350     for (i = 0; i < count; i++)
351         memcpy_far(SEG_GRAPH, dest_far + i*32
352                    , seg, src_far + i*fontsize, fontsize);
353     release_font_access();
354 }
355
356
357 /****************************************************************
358  * CRTC registers
359  ****************************************************************/
360
361 u16
362 stdvga_get_crtc(void)
363 {
364     if (inb(VGAREG_READ_MISC_OUTPUT) & 1)
365         return VGAREG_VGA_CRTC_ADDRESS;
366     return VGAREG_MDA_CRTC_ADDRESS;
367 }
368
369 void
370 stdvga_set_cursor_shape(u8 start, u8 end)
371 {
372     u16 crtc_addr = stdvga_get_crtc();
373     outb(0x0a, crtc_addr);
374     outb(start, crtc_addr + 1);
375     outb(0x0b, crtc_addr);
376     outb(end, crtc_addr + 1);
377 }
378
379 void
380 stdvga_set_active_page(u16 address)
381 {
382     u16 crtc_addr = stdvga_get_crtc();
383     outb(0x0c, crtc_addr);
384     outb((address & 0xff00) >> 8, crtc_addr + 1);
385     outb(0x0d, crtc_addr);
386     outb(address & 0x00ff, crtc_addr + 1);
387 }
388
389 void
390 stdvga_set_cursor_pos(u16 address)
391 {
392     u16 crtc_addr = stdvga_get_crtc();
393     outb(0x0e, crtc_addr);
394     outb((address & 0xff00) >> 8, crtc_addr + 1);
395     outb(0x0f, crtc_addr);
396     outb(address & 0x00ff, crtc_addr + 1);
397 }
398
399 void
400 stdvga_set_scan_lines(u8 lines)
401 {
402     u16 crtc_addr = stdvga_get_crtc();
403     outb(0x09, crtc_addr);
404     u8 crtc_r9 = inb(crtc_addr + 1);
405     crtc_r9 = (crtc_r9 & 0xe0) | (lines - 1);
406     outb(crtc_r9, crtc_addr + 1);
407 }
408
409 // Get vertical display end
410 u16
411 stdvga_get_vde(void)
412 {
413     u16 crtc_addr = stdvga_get_crtc();
414     outb(0x12, crtc_addr);
415     u16 vde = inb(crtc_addr + 1);
416     outb(0x07, crtc_addr);
417     u8 ovl = inb(crtc_addr + 1);
418     vde += (((ovl & 0x02) << 7) + ((ovl & 0x40) << 3) + 1);
419     return vde;
420 }
421
422
423 /****************************************************************
424  * Save/Restore/Set state
425  ****************************************************************/
426
427 void
428 stdvga_save_state(u16 seg, struct saveVideoHardware *info)
429 {
430     u16 crtc_addr = stdvga_get_crtc();
431     SET_FARVAR(seg, info->sequ_index, inb(VGAREG_SEQU_ADDRESS));
432     SET_FARVAR(seg, info->crtc_index, inb(crtc_addr));
433     SET_FARVAR(seg, info->grdc_index, inb(VGAREG_GRDC_ADDRESS));
434     inb(VGAREG_ACTL_RESET);
435     u16 ar_index = inb(VGAREG_ACTL_ADDRESS);
436     SET_FARVAR(seg, info->actl_index, ar_index);
437     SET_FARVAR(seg, info->feature, inb(VGAREG_READ_FEATURE_CTL));
438
439     u16 i;
440     for (i=0; i<4; i++) {
441         outb(i+1, VGAREG_SEQU_ADDRESS);
442         SET_FARVAR(seg, info->sequ_regs[i], inb(VGAREG_SEQU_DATA));
443     }
444     outb(0, VGAREG_SEQU_ADDRESS);
445     SET_FARVAR(seg, info->sequ0, inb(VGAREG_SEQU_DATA));
446
447     for (i=0; i<25; i++) {
448         outb(i, crtc_addr);
449         SET_FARVAR(seg, info->crtc_regs[i], inb(crtc_addr + 1));
450     }
451
452     for (i=0; i<20; i++) {
453         inb(VGAREG_ACTL_RESET);
454         outb(i | (ar_index & 0x20), VGAREG_ACTL_ADDRESS);
455         SET_FARVAR(seg, info->actl_regs[i], inb(VGAREG_ACTL_READ_DATA));
456     }
457     inb(VGAREG_ACTL_RESET);
458
459     for (i=0; i<9; i++) {
460         outb(i, VGAREG_GRDC_ADDRESS);
461         SET_FARVAR(seg, info->grdc_regs[i], inb(VGAREG_GRDC_DATA));
462     }
463
464     SET_FARVAR(seg, info->crtc_addr, crtc_addr);
465
466     /* XXX: read plane latches */
467     for (i=0; i<4; i++)
468         SET_FARVAR(seg, info->plane_latch[i], 0);
469 }
470
471 void
472 stdvga_restore_state(u16 seg, struct saveVideoHardware *info)
473 {
474     // Reset Attribute Ctl flip-flop
475     inb(VGAREG_ACTL_RESET);
476
477     u16 crtc_addr = GET_FARVAR(seg, info->crtc_addr);
478
479     u16 i;
480     for (i=0; i<4; i++) {
481         outb(i+1, VGAREG_SEQU_ADDRESS);
482         outb(GET_FARVAR(seg, info->sequ_regs[i]), VGAREG_SEQU_DATA);
483     }
484     outb(0, VGAREG_SEQU_ADDRESS);
485     outb(GET_FARVAR(seg, info->sequ0), VGAREG_SEQU_DATA);
486
487     // Disable CRTC write protection
488     outw(0x0011, crtc_addr);
489     // Set CRTC regs
490     for (i=0; i<25; i++)
491         if (i != 0x11) {
492             outb(i, crtc_addr);
493             outb(GET_FARVAR(seg, info->crtc_regs[i]), crtc_addr + 1);
494         }
495     // select crtc base address
496     u16 v = inb(VGAREG_READ_MISC_OUTPUT) & ~0x01;
497     if (crtc_addr == VGAREG_VGA_CRTC_ADDRESS)
498         v |= 0x01;
499     outb(v, VGAREG_WRITE_MISC_OUTPUT);
500
501     // enable write protection if needed
502     outb(0x11, crtc_addr);
503     outb(GET_FARVAR(seg, info->crtc_regs[0x11]), crtc_addr + 1);
504
505     // Set Attribute Ctl
506     u16 ar_index = GET_FARVAR(seg, info->actl_index);
507     inb(VGAREG_ACTL_RESET);
508     for (i=0; i<20; i++) {
509         outb(i | (ar_index & 0x20), VGAREG_ACTL_ADDRESS);
510         outb(GET_FARVAR(seg, info->actl_regs[i]), VGAREG_ACTL_WRITE_DATA);
511     }
512     outb(ar_index, VGAREG_ACTL_ADDRESS);
513     inb(VGAREG_ACTL_RESET);
514
515     for (i=0; i<9; i++) {
516         outb(i, VGAREG_GRDC_ADDRESS);
517         outb(GET_FARVAR(seg, info->grdc_regs[i]), VGAREG_GRDC_DATA);
518     }
519
520     outb(GET_FARVAR(seg, info->sequ_index), VGAREG_SEQU_ADDRESS);
521     outb(GET_FARVAR(seg, info->crtc_index), crtc_addr);
522     outb(GET_FARVAR(seg, info->grdc_index), VGAREG_GRDC_ADDRESS);
523     outb(GET_FARVAR(seg, info->feature), crtc_addr - 0x4 + 0xa);
524 }
525
526 static void
527 clear_screen(struct vgamode_s *vmode_g)
528 {
529     switch (GET_GLOBAL(vmode_g->memmodel)) {
530     case MM_TEXT:
531         memset16_far(GET_GLOBAL(vmode_g->sstart), 0, 0x0720, 32*1024);
532         break;
533     case MM_CGA:
534         memset16_far(GET_GLOBAL(vmode_g->sstart), 0, 0x0000, 32*1024);
535         break;
536     default:
537         // XXX - old code gets/sets/restores sequ register 2 to 0xf -
538         // but it should always be 0xf anyway.
539         memset16_far(GET_GLOBAL(vmode_g->sstart), 0, 0x0000, 64*1024);
540     }
541 }
542
543 int
544 stdvga_set_mode(int mode, int flags)
545 {
546     // find the entry in the video modes
547     struct vgamode_s *vmode_g = find_vga_entry(mode);
548     dprintf(1, "mode search %02x found %p\n", mode, vmode_g);
549     if (!vmode_g)
550         return VBE_RETURN_STATUS_FAILED;
551
552     // if palette loading (bit 3 of modeset ctl = 0)
553     if (!(flags & MF_NOPALETTE)) {    // Set the PEL mask
554         stdvga_set_pel_mask(GET_GLOBAL(vmode_g->pelmask));
555
556         // From which palette
557         u8 *palette_g = GET_GLOBAL(vmode_g->dac);
558         u16 palsize = GET_GLOBAL(vmode_g->dacsize) / 3;
559
560         // Always 256*3 values
561         stdvga_set_dac_regs(get_global_seg(), palette_g, 0, palsize);
562         u16 i;
563         for (i = palsize; i < 0x0100; i++) {
564             static u8 rgb[3] VAR16;
565             stdvga_set_dac_regs(get_global_seg(), rgb, i, 1);
566         }
567
568         if (flags & MF_GRAYSUM)
569             stdvga_perform_gray_scale_summing(0x00, 0x100);
570     }
571
572     // Reset Attribute Ctl flip-flop
573     inb(VGAREG_ACTL_RESET);
574
575     // Set Attribute Ctl
576     u8 *regs = GET_GLOBAL(vmode_g->actl_regs);
577     u16 i;
578     for (i = 0; i <= 0x13; i++) {
579         outb(i, VGAREG_ACTL_ADDRESS);
580         outb(GET_GLOBAL(regs[i]), VGAREG_ACTL_WRITE_DATA);
581     }
582     outb(0x14, VGAREG_ACTL_ADDRESS);
583     outb(0x00, VGAREG_ACTL_WRITE_DATA);
584
585     // Set Sequencer Ctl
586     outb(0, VGAREG_SEQU_ADDRESS);
587     outb(0x03, VGAREG_SEQU_DATA);
588     regs = GET_GLOBAL(vmode_g->sequ_regs);
589     for (i = 1; i <= 4; i++) {
590         outb(i, VGAREG_SEQU_ADDRESS);
591         outb(GET_GLOBAL(regs[i - 1]), VGAREG_SEQU_DATA);
592     }
593
594     // Set Grafx Ctl
595     regs = GET_GLOBAL(vmode_g->grdc_regs);
596     for (i = 0; i <= 8; i++) {
597         outb(i, VGAREG_GRDC_ADDRESS);
598         outb(GET_GLOBAL(regs[i]), VGAREG_GRDC_DATA);
599     }
600
601     // Set CRTC address VGA or MDA
602     u8 miscreg = GET_GLOBAL(vmode_g->miscreg);
603     u16 crtc_addr = VGAREG_VGA_CRTC_ADDRESS;
604     if (!(miscreg & 1))
605         crtc_addr = VGAREG_MDA_CRTC_ADDRESS;
606
607     // Disable CRTC write protection
608     outw(0x0011, crtc_addr);
609     // Set CRTC regs
610     regs = GET_GLOBAL(vmode_g->crtc_regs);
611     for (i = 0; i <= 0x18; i++) {
612         outb(i, crtc_addr);
613         outb(GET_GLOBAL(regs[i]), crtc_addr + 1);
614     }
615
616     // Set the misc register
617     outb(miscreg, VGAREG_WRITE_MISC_OUTPUT);
618
619     // Enable video
620     outb(0x20, VGAREG_ACTL_ADDRESS);
621     inb(VGAREG_ACTL_RESET);
622
623     // Clear screen
624     if (!(flags & MF_NOCLEARMEM))
625         clear_screen(vmode_g);
626
627     // Write the fonts in memory
628     u8 memmodel = GET_GLOBAL(vmode_g->memmodel);
629     if (memmodel == MM_TEXT)
630         stdvga_load_font(get_global_seg(), vgafont16, 0x100, 0, 0, 16);
631
632     // Setup BDA variables
633     modeswitch_set_bda(mode, flags, vmode_g);
634
635     return 0;
636 }
637
638
639 /****************************************************************
640  * Misc
641  ****************************************************************/
642
643 void
644 stdvga_enable_video_addressing(u8 disable)
645 {
646     u8 v = (disable & 1) ? 0x00 : 0x02;
647     u8 v2 = inb(VGAREG_READ_MISC_OUTPUT) & ~0x02;
648     outb(v | v2, VGAREG_WRITE_MISC_OUTPUT);
649 }
650
651 int
652 stdvga_init(void)
653 {
654     // switch to color mode and enable CPU access 480 lines
655     outb(0xc3, VGAREG_WRITE_MISC_OUTPUT);
656     // more than 64k 3C4/04
657     outb(0x04, VGAREG_SEQU_ADDRESS);
658     outb(0x02, VGAREG_SEQU_DATA);
659
660     return 0;
661 }