3 // Copyright (C) 2009 Kevin O'Connor <kevin@koconnor.net>
4 // Copyright (C) 2001-2008 the LGPL VGABios developers Team
6 // This file may be distributed under the terms of the GNU LGPLv3 license.
13 #include "vgatables.h"
15 #define GET_FARVAR(seg, ofs) (ofs)
16 #define SET_FARVAR(seg, ofs, val) ((ofs) = (val))
18 static struct saveBDAstate BDA
;
20 #define GET_BDA(field) (BDA.field)
21 #define GET_GLOBAL(val) (val)
24 // * replace direct in/out calls with wrapper functions
27 /****************************************************************
29 ****************************************************************/
32 vgahw_screen_disable(void)
34 inb(VGAREG_ACTL_RESET
);
35 outb(0x00, VGAREG_ACTL_ADDRESS
);
39 vgahw_screen_enable(void)
41 inb(VGAREG_ACTL_RESET
);
42 outb(0x20, VGAREG_ACTL_ADDRESS
);
46 vgahw_set_border_color(u8 color
)
48 inb(VGAREG_ACTL_RESET
);
49 outb(0x00, VGAREG_ACTL_ADDRESS
);
53 outb(v1
, VGAREG_ACTL_WRITE_DATA
);
57 for (i
= 1; i
< 4; i
++) {
58 outb(i
, VGAREG_ACTL_ADDRESS
);
60 u8 cur
= inb(VGAREG_ACTL_READ_DATA
);
63 outb(cur
, VGAREG_ACTL_WRITE_DATA
);
65 outb(0x20, VGAREG_ACTL_ADDRESS
);
69 vgahw_set_overscan_border_color(u8 color
)
71 inb(VGAREG_ACTL_RESET
);
72 outb(0x11, VGAREG_ACTL_ADDRESS
);
73 outb(color
, VGAREG_ACTL_WRITE_DATA
);
74 outb(0x20, VGAREG_ACTL_ADDRESS
);
78 vgahw_get_overscan_border_color(void)
80 inb(VGAREG_ACTL_RESET
);
81 outb(0x11, VGAREG_ACTL_ADDRESS
);
82 u8 v
= inb(VGAREG_ACTL_READ_DATA
);
83 inb(VGAREG_ACTL_RESET
);
84 outb(0x20, VGAREG_ACTL_ADDRESS
);
89 vgahw_set_palette(u8 palid
)
91 inb(VGAREG_ACTL_RESET
);
94 for (i
= 1; i
< 4; i
++) {
95 outb(i
, VGAREG_ACTL_ADDRESS
);
97 u8 v
= inb(VGAREG_ACTL_READ_DATA
);
100 outb(v
, VGAREG_ACTL_WRITE_DATA
);
102 outb(0x20, VGAREG_ACTL_ADDRESS
);
106 vgahw_set_single_palette_reg(u8 reg
, u8 val
)
108 inb(VGAREG_ACTL_RESET
);
109 outb(reg
, VGAREG_ACTL_ADDRESS
);
110 outb(val
, VGAREG_ACTL_WRITE_DATA
);
111 outb(0x20, VGAREG_ACTL_ADDRESS
);
115 vgahw_get_single_palette_reg(u8 reg
)
117 inb(VGAREG_ACTL_RESET
);
118 outb(reg
, VGAREG_ACTL_ADDRESS
);
119 u8 v
= inb(VGAREG_ACTL_READ_DATA
);
120 inb(VGAREG_ACTL_RESET
);
121 outb(0x20, VGAREG_ACTL_ADDRESS
);
126 vgahw_set_all_palette_reg(u8
*data_far
)
128 inb(VGAREG_ACTL_RESET
);
130 for (i
= 0; i
< 0x10; i
++) {
131 outb(i
, VGAREG_ACTL_ADDRESS
);
132 u8 val
= GET_FARVAR(seg
, *data_far
);
133 outb(val
, VGAREG_ACTL_WRITE_DATA
);
136 outb(0x11, VGAREG_ACTL_ADDRESS
);
137 outb(GET_FARVAR(seg
, *data_far
), VGAREG_ACTL_WRITE_DATA
);
138 outb(0x20, VGAREG_ACTL_ADDRESS
);
142 vgahw_get_all_palette_reg(u8
*data_far
)
145 for (i
= 0; i
< 0x10; i
++) {
146 inb(VGAREG_ACTL_RESET
);
147 outb(i
, VGAREG_ACTL_ADDRESS
);
148 SET_FARVAR(seg
, *data_far
, inb(VGAREG_ACTL_READ_DATA
));
151 inb(VGAREG_ACTL_RESET
);
152 outb(0x11, VGAREG_ACTL_ADDRESS
);
153 SET_FARVAR(seg
, *data_far
, inb(VGAREG_ACTL_READ_DATA
));
154 inb(VGAREG_ACTL_RESET
);
155 outb(0x20, VGAREG_ACTL_ADDRESS
);
159 vgahw_toggle_intensity(u8 flag
)
161 inb(VGAREG_ACTL_RESET
);
162 outb(0x10, VGAREG_ACTL_ADDRESS
);
163 u8 val
= (inb(VGAREG_ACTL_READ_DATA
) & 0xf7) | ((flag
& 0x01) << 3);
164 outb(val
, VGAREG_ACTL_WRITE_DATA
);
165 outb(0x20, VGAREG_ACTL_ADDRESS
);
169 vgahw_select_video_dac_color_page(u8 flag
, u8 data
)
171 inb(VGAREG_ACTL_RESET
);
172 outb(0x10, VGAREG_ACTL_ADDRESS
);
173 u8 val
= inb(VGAREG_ACTL_READ_DATA
);
174 if (!(flag
& 0x01)) {
175 // select paging mode
176 val
= (val
& 0x7f) | (data
<< 7);
177 outb(val
, VGAREG_ACTL_WRITE_DATA
);
178 outb(0x20, VGAREG_ACTL_ADDRESS
);
182 inb(VGAREG_ACTL_RESET
);
183 outb(0x14, VGAREG_ACTL_ADDRESS
);
187 outb(data
, VGAREG_ACTL_WRITE_DATA
);
188 outb(0x20, VGAREG_ACTL_ADDRESS
);
192 vgahw_read_video_dac_state(u8
*pmode
, u8
*curpage
)
194 inb(VGAREG_ACTL_RESET
);
195 outb(0x10, VGAREG_ACTL_ADDRESS
);
196 u8 val1
= inb(VGAREG_ACTL_READ_DATA
) >> 7;
198 inb(VGAREG_ACTL_RESET
);
199 outb(0x14, VGAREG_ACTL_ADDRESS
);
200 u8 val2
= inb(VGAREG_ACTL_READ_DATA
) & 0x0f;
204 inb(VGAREG_ACTL_RESET
);
205 outb(0x20, VGAREG_ACTL_ADDRESS
);
212 /****************************************************************
214 ****************************************************************/
217 vgahw_set_dac_regs(u8
*data_far
, u8 start
, int count
)
219 outb(start
, VGAREG_DAC_WRITE_ADDRESS
);
221 outb(GET_FARVAR(seg
, *data_far
), VGAREG_DAC_DATA
);
223 outb(GET_FARVAR(seg
, *data_far
), VGAREG_DAC_DATA
);
225 outb(GET_FARVAR(seg
, *data_far
), VGAREG_DAC_DATA
);
232 vgahw_get_dac_regs(u8
*data_far
, u8 start
, int count
)
234 outb(start
, VGAREG_DAC_READ_ADDRESS
);
236 SET_FARVAR(seg
, *data_far
, inb(VGAREG_DAC_DATA
));
238 SET_FARVAR(seg
, *data_far
, inb(VGAREG_DAC_DATA
));
240 SET_FARVAR(seg
, *data_far
, inb(VGAREG_DAC_DATA
));
247 vgahw_set_pel_mask(u8 val
)
249 outb(val
, VGAREG_PEL_MASK
);
253 vgahw_get_pel_mask(void)
255 return inb(VGAREG_PEL_MASK
);
259 vgahw_save_dac_state(struct saveDACcolors
*info
)
261 /* XXX: check this */
262 SET_FARVAR(seg
, info
->rwmode
, inb(VGAREG_DAC_STATE
));
263 SET_FARVAR(seg
, info
->peladdr
, inb(VGAREG_DAC_WRITE_ADDRESS
));
264 SET_FARVAR(seg
, info
->pelmask
, inb(VGAREG_PEL_MASK
));
265 vgahw_get_dac_regs(info
->dac
, 0, 256);
266 SET_FARVAR(seg
, info
->color_select
, 0);
270 vgahw_restore_dac_state(struct saveDACcolors
*info
)
272 outb(GET_FARVAR(seg
, info
->pelmask
), VGAREG_PEL_MASK
);
273 vgahw_set_dac_regs(info
->dac
, 0, 256);
274 outb(GET_FARVAR(seg
, info
->peladdr
), VGAREG_DAC_WRITE_ADDRESS
);
278 /****************************************************************
280 ****************************************************************/
283 vgahw_sequ_write(u8 index
, u8 value
)
285 outw((value
<<8) | index
, VGAREG_SEQU_ADDRESS
);
289 vgahw_grdc_write(u8 index
, u8 value
)
291 outw((value
<<8) | index
, VGAREG_GRDC_ADDRESS
);
295 vgahw_set_text_block_specifier(u8 spec
)
297 outw((spec
<< 8) | 0x03, VGAREG_SEQU_ADDRESS
);
301 get_font_access(void)
303 outw(0x0100, VGAREG_SEQU_ADDRESS
);
304 outw(0x0402, VGAREG_SEQU_ADDRESS
);
305 outw(0x0704, VGAREG_SEQU_ADDRESS
);
306 outw(0x0300, VGAREG_SEQU_ADDRESS
);
307 outw(0x0204, VGAREG_GRDC_ADDRESS
);
308 outw(0x0005, VGAREG_GRDC_ADDRESS
);
309 outw(0x0406, VGAREG_GRDC_ADDRESS
);
313 release_font_access(void)
315 outw(0x0100, VGAREG_SEQU_ADDRESS
);
316 outw(0x0302, VGAREG_SEQU_ADDRESS
);
317 outw(0x0304, VGAREG_SEQU_ADDRESS
);
318 outw(0x0300, VGAREG_SEQU_ADDRESS
);
319 u16 v
= (inw(VGAREG_READ_MISC_OUTPUT
) & 0x01) ? 0x0e : 0x0a;
320 outw((v
<< 8) | 0x06, VGAREG_GRDC_ADDRESS
);
321 outw(0x0004, VGAREG_GRDC_ADDRESS
);
322 outw(0x1005, VGAREG_GRDC_ADDRESS
);
326 /****************************************************************
328 ****************************************************************/
333 return GET_BDA(crtc_address
);
337 vgahw_set_cursor_shape(u8 start
, u8 end
)
339 u16 crtc_addr
= get_crtc();
340 outb(0x0a, crtc_addr
);
341 outb(start
, crtc_addr
+ 1);
342 outb(0x0b, crtc_addr
);
343 outb(end
, crtc_addr
+ 1);
347 vgahw_set_active_page(u16 address
)
349 u16 crtc_addr
= get_crtc();
350 outb(0x0c, crtc_addr
);
351 outb((address
& 0xff00) >> 8, crtc_addr
+ 1);
352 outb(0x0d, crtc_addr
);
353 outb(address
& 0x00ff, crtc_addr
+ 1);
357 vgahw_set_cursor_pos(u16 address
)
359 u16 crtc_addr
= get_crtc();
360 outb(0x0e, crtc_addr
);
361 outb((address
& 0xff00) >> 8, crtc_addr
+ 1);
362 outb(0x0f, crtc_addr
);
363 outb(address
& 0x00ff, crtc_addr
+ 1);
367 vgahw_set_scan_lines(u8 lines
)
369 u16 crtc_addr
= get_crtc();
370 outb(0x09, crtc_addr
);
371 u8 crtc_r9
= inb(crtc_addr
+ 1);
372 crtc_r9
= (crtc_r9
& 0xe0) | (lines
- 1);
373 outb(crtc_r9
, crtc_addr
+ 1);
376 // Get vertical display end
380 u16 crtc_addr
= get_crtc();
381 outb(0x12, crtc_addr
);
382 u16 vde
= inb(crtc_addr
+ 1);
383 outb(0x07, crtc_addr
);
384 u8 ovl
= inb(crtc_addr
+ 1);
385 vde
+= (((ovl
& 0x02) << 7) + ((ovl
& 0x40) << 3) + 1);
390 /****************************************************************
391 * Save/Restore/Set state
392 ****************************************************************/
395 vgahw_save_state(struct saveVideoHardware
*info
)
397 u16 crtc_addr
= get_crtc();
398 SET_FARVAR(seg
, info
->sequ_index
, inb(VGAREG_SEQU_ADDRESS
));
399 SET_FARVAR(seg
, info
->crtc_index
, inb(crtc_addr
));
400 SET_FARVAR(seg
, info
->grdc_index
, inb(VGAREG_GRDC_ADDRESS
));
401 inb(VGAREG_ACTL_RESET
);
402 u16 ar_index
= inb(VGAREG_ACTL_ADDRESS
);
403 SET_FARVAR(seg
, info
->actl_index
, ar_index
);
404 SET_FARVAR(seg
, info
->feature
, inb(VGAREG_READ_FEATURE_CTL
));
407 for (i
=0; i
<4; i
++) {
408 outb(i
+1, VGAREG_SEQU_ADDRESS
);
409 SET_FARVAR(seg
, info
->sequ_regs
[i
], inb(VGAREG_SEQU_DATA
));
411 outb(0, VGAREG_SEQU_ADDRESS
);
412 SET_FARVAR(seg
, info
->sequ0
, inb(VGAREG_SEQU_DATA
));
414 for (i
=0; i
<25; i
++) {
416 SET_FARVAR(seg
, info
->crtc_regs
[i
], inb(crtc_addr
+ 1));
419 for (i
=0; i
<20; i
++) {
420 inb(VGAREG_ACTL_RESET
);
421 outb(i
| (ar_index
& 0x20), VGAREG_ACTL_ADDRESS
);
422 SET_FARVAR(seg
, info
->actl_regs
[i
], inb(VGAREG_ACTL_READ_DATA
));
424 inb(VGAREG_ACTL_RESET
);
426 for (i
=0; i
<9; i
++) {
427 outb(i
, VGAREG_GRDC_ADDRESS
);
428 SET_FARVAR(seg
, info
->grdc_regs
[i
], inb(VGAREG_GRDC_DATA
));
431 SET_FARVAR(seg
, info
->crtc_addr
, crtc_addr
);
433 /* XXX: read plane latches */
435 SET_FARVAR(seg
, info
->plane_latch
[i
], 0);
439 vgahw_restore_state(struct saveVideoHardware
*info
)
441 // Reset Attribute Ctl flip-flop
442 inb(VGAREG_ACTL_RESET
);
444 u16 crtc_addr
= GET_FARVAR(seg
, info
->crtc_addr
);
447 for (i
=0; i
<4; i
++) {
448 outb(i
+1, VGAREG_SEQU_ADDRESS
);
449 outb(GET_FARVAR(seg
, info
->sequ_regs
[i
]), VGAREG_SEQU_DATA
);
451 outb(0, VGAREG_SEQU_ADDRESS
);
452 outb(GET_FARVAR(seg
, info
->sequ0
), VGAREG_SEQU_DATA
);
454 // Disable CRTC write protection
455 outw(0x0011, crtc_addr
);
460 outb(GET_FARVAR(seg
, info
->crtc_regs
[i
]), crtc_addr
+ 1);
462 // select crtc base address
463 u16 v
= inb(VGAREG_READ_MISC_OUTPUT
) & ~0x01;
464 if (crtc_addr
== VGAREG_VGA_CRTC_ADDRESS
)
466 outb(v
, VGAREG_WRITE_MISC_OUTPUT
);
468 // enable write protection if needed
469 outb(0x11, crtc_addr
);
470 outb(GET_FARVAR(seg
, info
->crtc_regs
[0x11]), crtc_addr
+ 1);
473 u16 ar_index
= GET_FARVAR(seg
, info
->actl_index
);
474 inb(VGAREG_ACTL_RESET
);
475 for (i
=0; i
<20; i
++) {
476 outb(i
| (ar_index
& 0x20), VGAREG_ACTL_ADDRESS
);
477 outb(GET_FARVAR(seg
, info
->actl_regs
[i
]), VGAREG_ACTL_WRITE_DATA
);
479 outb(ar_index
, VGAREG_ACTL_ADDRESS
);
480 inb(VGAREG_ACTL_RESET
);
482 for (i
=0; i
<9; i
++) {
483 outb(i
, VGAREG_GRDC_ADDRESS
);
484 outb(GET_FARVAR(seg
, info
->grdc_regs
[i
]), VGAREG_GRDC_DATA
);
487 outb(GET_FARVAR(seg
, info
->sequ_index
), VGAREG_SEQU_ADDRESS
);
488 outb(GET_FARVAR(seg
, info
->crtc_index
), crtc_addr
);
489 outb(GET_FARVAR(seg
, info
->grdc_index
), VGAREG_GRDC_ADDRESS
);
490 outb(GET_FARVAR(seg
, info
->feature
), crtc_addr
- 0x4 + 0xa);
494 vgahw_set_mode(struct VideoParam_s
*vparam_g
)
496 // Reset Attribute Ctl flip-flop
497 inb(VGAREG_ACTL_RESET
);
501 for (i
= 0; i
<= 0x13; i
++) {
502 outb(i
, VGAREG_ACTL_ADDRESS
);
503 outb(GET_GLOBAL(vparam_g
->actl_regs
[i
]), VGAREG_ACTL_WRITE_DATA
);
505 outb(0x14, VGAREG_ACTL_ADDRESS
);
506 outb(0x00, VGAREG_ACTL_WRITE_DATA
);
509 outb(0, VGAREG_SEQU_ADDRESS
);
510 outb(0x03, VGAREG_SEQU_DATA
);
511 for (i
= 1; i
<= 4; i
++) {
512 outb(i
, VGAREG_SEQU_ADDRESS
);
513 outb(GET_GLOBAL(vparam_g
->sequ_regs
[i
- 1]), VGAREG_SEQU_DATA
);
517 for (i
= 0; i
<= 8; i
++) {
518 outb(i
, VGAREG_GRDC_ADDRESS
);
519 outb(GET_GLOBAL(vparam_g
->grdc_regs
[i
]), VGAREG_GRDC_DATA
);
522 // Set CRTC address VGA or MDA
523 u8 miscreg
= GET_GLOBAL(vparam_g
->miscreg
);
524 u16 crtc_addr
= VGAREG_VGA_CRTC_ADDRESS
;
526 crtc_addr
= VGAREG_MDA_CRTC_ADDRESS
;
528 // Disable CRTC write protection
529 outw(0x0011, crtc_addr
);
531 for (i
= 0; i
<= 0x18; i
++) {
533 outb(GET_GLOBAL(vparam_g
->crtc_regs
[i
]), crtc_addr
+ 1);
536 // Set the misc register
537 outb(miscreg
, VGAREG_WRITE_MISC_OUTPUT
);
540 outb(0x20, VGAREG_ACTL_ADDRESS
);
541 inb(VGAREG_ACTL_RESET
);
545 /****************************************************************
547 ****************************************************************/
550 vgahw_enable_video_addressing(u8 disable
)
552 u8 v
= (disable
& 1) ? 0x00 : 0x02;
553 u8 v2
= inb(VGAREG_READ_MISC_OUTPUT
) & ~0x02;
554 outb(v
| v2
, VGAREG_WRITE_MISC_OUTPUT
);
560 struct vgamode_s
*vmode_g
;
565 uint16_t class = pci_config_readw(bdf
, PCI_CLASS_DEVICE
);
566 if (class == PCI_CLASS_DISPLAY_VGA
)
574 vmode_g
= find_vga_entry(3);
576 vgahw_sequ_write(0, 1); // Assert sync reset
578 // Switch to color mode and enable CPU access 480 lines
579 outb(0xc3, VGAREG_WRITE_MISC_OUTPUT
);
581 vgahw_sequ_write(0, 3); // De-assert sync reset
583 vgahw_set_mode(vmode_g
->vparam
);
585 vgahw_sequ_write(4, 0x06); // disable odd/even + chain4
586 vgahw_sequ_write(1, vmode_g
->vparam
->sequ_regs
[1] | 0x20); // disable video
587 vgahw_grdc_write(5, vmode_g
->vparam
->grdc_regs
[5] & 0xef); // disable odd/even
588 vgahw_grdc_write(6, 0x05); // set mem map to 0xa0000 and graphics mode
589 vgahw_sequ_write(2, 0x04); // enable write plane 2
592 unsigned char *font_ptr
= pci_mem_base
+ SEG_GRAPH
*16;
595 for (i
= 0; i
< 0x100; i
++)
596 __builtin_memcpy(font_ptr
+ i
*32, vgafont16
+ i
*16, 16);
600 int i
= vmode_g
->dacsize
/ 3;
601 vgahw_set_dac_regs(vmode_g
->dac
, 0, i
);
604 vgahw_sequ_write(4, 0x2); // enable odd/even
605 vgahw_set_mode(vmode_g
->vparam
);