blob: 48fcdeb769c1d5ef8e0e278b767a24ab1234ef06 [file] [log] [blame]
Kevin O'Connor1f2c3072009-05-06 23:35:59 -04001// VGA bios implementation
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
9// TODO:
Kevin O'Connor1f2c3072009-05-06 23:35:59 -040010// * define structs for save/restore state
11// * review correctness of converted asm by comparing with RBIL
Kevin O'Connor1f2c3072009-05-06 23:35:59 -040012// * refactor redundant code into sub-functions
13// * See if there is a method to the in/out stuff that can be encapsulated.
14// * remove "biosfn" prefixes
Kevin O'Connor1f2c3072009-05-06 23:35:59 -040015// * verify all funcs static
16//
Kevin O'Connor6ace78f2009-05-14 19:24:49 -040017// * convert vbe/clext code
18//
Kevin O'Connor1f2c3072009-05-06 23:35:59 -040019// * separate code into separate files
20// * extract hw code from bios interfaces
Kevin O'Connor1f2c3072009-05-06 23:35:59 -040021
22#include "bregs.h" // struct bregs
23#include "biosvar.h" // GET_BDA
24#include "util.h" // memset
Kevin O'Connorc0c7df62009-05-17 18:11:33 -040025#include "vgatables.h" // find_vga_entry
Kevin O'Connor1f2c3072009-05-06 23:35:59 -040026
27// XXX
28#define CONFIG_VBE 0
29#define CONFIG_CIRRUS 0
30
31// XXX
32#define DEBUG_VGA_POST 1
33#define DEBUG_VGA_10 3
34
Kevin O'Connord113a992009-05-16 21:05:02 -040035#define SET_VGA(var, val) SET_FARVAR(get_global_seg(), (var), (val))
Kevin O'Connor1f2c3072009-05-06 23:35:59 -040036
37
38// ===================================================================
39//
40// Video Utils
41//
42// ===================================================================
43
44// -------------------------------------------------------------------
Kevin O'Connor1f2c3072009-05-06 23:35:59 -040045inline void
46call16_vgaint(u32 eax, u32 ebx)
47{
48 asm volatile(
49 "int $0x10\n"
50 "cli\n"
51 "cld"
52 :
53 : "a"(eax), "b"(ebx)
54 : "cc", "memory");
55}
56
Kevin O'Connor1f2c3072009-05-06 23:35:59 -040057
58// ===================================================================
59//
60// BIOS functions
61//
62// ===================================================================
63
64// -------------------------------------------------------------------
65static void
66biosfn_perform_gray_scale_summing(u16 start, u16 count)
67{
Kevin O'Connor1f2c3072009-05-06 23:35:59 -040068 inb(VGAREG_ACTL_RESET);
69 outb(0x00, VGAREG_ACTL_ADDRESS);
70
Kevin O'Connordd2be772009-05-16 15:41:23 -040071 int i;
72 for (i = start; i < start+count; i++) {
Kevin O'Connor1f2c3072009-05-06 23:35:59 -040073 // set read address and switch to read mode
Kevin O'Connordd2be772009-05-16 15:41:23 -040074 outb(i, VGAREG_DAC_READ_ADDRESS);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -040075 // get 6-bit wide RGB data values
Kevin O'Connordd2be772009-05-16 15:41:23 -040076 u8 r = inb(VGAREG_DAC_DATA);
77 u8 g = inb(VGAREG_DAC_DATA);
78 u8 b = inb(VGAREG_DAC_DATA);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -040079
80 // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue )
Kevin O'Connordd2be772009-05-16 15:41:23 -040081 u16 intensity = ((77 * r + 151 * g + 28 * b) + 0x80) >> 8;
Kevin O'Connor1f2c3072009-05-06 23:35:59 -040082
Kevin O'Connordd2be772009-05-16 15:41:23 -040083 if (intensity > 0x3f)
84 intensity = 0x3f;
Kevin O'Connor1f2c3072009-05-06 23:35:59 -040085
86 // set write address and switch to write mode
Kevin O'Connordd2be772009-05-16 15:41:23 -040087 outb(i, VGAREG_DAC_WRITE_ADDRESS);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -040088 // write new intensity value
Kevin O'Connordd2be772009-05-16 15:41:23 -040089 outb(intensity & 0xff, VGAREG_DAC_DATA);
90 outb(intensity & 0xff, VGAREG_DAC_DATA);
91 outb(intensity & 0xff, VGAREG_DAC_DATA);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -040092 }
93 inb(VGAREG_ACTL_RESET);
94 outb(0x20, VGAREG_ACTL_ADDRESS);
95}
96
97// -------------------------------------------------------------------
98static void
99biosfn_set_cursor_shape(u8 CH, u8 CL)
100{
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400101 CH &= 0x3f;
102 CL &= 0x1f;
103
Kevin O'Connordd2be772009-05-16 15:41:23 -0400104 u16 curs = (CH << 8) + CL;
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400105 SET_BDA(cursor_type, curs);
106
Kevin O'Connordd2be772009-05-16 15:41:23 -0400107 u8 modeset_ctl = GET_BDA(modeset_ctl);
108 u16 cheight = GET_BDA(char_height);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400109 if ((modeset_ctl & 0x01) && (cheight > 8) && (CL < 8) && (CH < 0x20)) {
Kevin O'Connordd2be772009-05-16 15:41:23 -0400110 if (CL != (CH + 1))
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400111 CH = ((CH + 1) * cheight / 8) - 1;
Kevin O'Connordd2be772009-05-16 15:41:23 -0400112 else
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400113 CH = ((CL + 1) * cheight / 8) - 2;
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400114 CL = ((CL + 1) * cheight / 8) - 1;
115 }
116 // CTRC regs 0x0a and 0x0b
Kevin O'Connordd2be772009-05-16 15:41:23 -0400117 u16 crtc_addr = GET_BDA(crtc_address);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400118 outb(0x0a, crtc_addr);
119 outb(CH, crtc_addr + 1);
120 outb(0x0b, crtc_addr);
121 outb(CL, crtc_addr + 1);
122}
123
Kevin O'Connor0818e1a2009-05-16 18:00:19 -0400124static u16
125biosfn_get_cursor_shape(u8 page)
126{
127 if (page > 7)
128 return 0;
129 // FIXME should handle VGA 14/16 lines
130 return GET_BDA(cursor_type);
131}
132
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400133// -------------------------------------------------------------------
134static void
135biosfn_set_cursor_pos(u8 page, u16 cursor)
136{
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400137 // Should not happen...
138 if (page > 7)
139 return;
140
141 // Bios cursor pos
142 SET_BDA(cursor_pos[page], cursor);
143
144 // Set the hardware cursor
Kevin O'Connordd2be772009-05-16 15:41:23 -0400145 u8 current = GET_BDA(video_page);
146 if (page != current)
147 return;
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400148
Kevin O'Connordd2be772009-05-16 15:41:23 -0400149 // Get the dimensions
150 u16 nbcols = GET_BDA(video_cols);
151 u16 nbrows = GET_BDA(video_rows) + 1;
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400152
Kevin O'Connordd2be772009-05-16 15:41:23 -0400153 u8 xcurs = cursor & 0x00ff;
154 u8 ycurs = (cursor & 0xff00) >> 8;
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400155
Kevin O'Connordd2be772009-05-16 15:41:23 -0400156 // Calculate the address knowing nbcols nbrows and page num
157 u16 address = SCREEN_IO_START(nbcols, nbrows, page) + xcurs + ycurs * nbcols;
158
159 // CRTC regs 0x0e and 0x0f
160 u16 crtc_addr = GET_BDA(crtc_address);
161 outb(0x0e, crtc_addr);
162 outb((address & 0xff00) >> 8, crtc_addr + 1);
163 outb(0x0f, crtc_addr);
164 outb(address & 0x00ff, crtc_addr + 1);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400165}
166
Kevin O'Connorc0c7df62009-05-17 18:11:33 -0400167u16
Kevin O'Connor0818e1a2009-05-16 18:00:19 -0400168biosfn_get_cursor_pos(u8 page)
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400169{
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400170 if (page > 7)
Kevin O'Connor0818e1a2009-05-16 18:00:19 -0400171 return 0;
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400172 // FIXME should handle VGA 14/16 lines
Kevin O'Connor0818e1a2009-05-16 18:00:19 -0400173 return GET_BDA(cursor_pos[page]);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400174}
175
176// -------------------------------------------------------------------
177static void
178biosfn_set_active_page(u8 page)
179{
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400180 if (page > 7)
181 return;
182
183 // Get the mode
Kevin O'Connor5727c292009-05-16 17:29:32 -0400184 struct vgamode_s *vmode_g = find_vga_entry(GET_BDA(video_mode));
185 if (!vmode_g)
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400186 return;
187
188 // Get pos curs pos for the right page
Kevin O'Connor0818e1a2009-05-16 18:00:19 -0400189 u16 cursor = biosfn_get_cursor_pos(page);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400190
Kevin O'Connordd2be772009-05-16 15:41:23 -0400191 u16 address;
Kevin O'Connor5727c292009-05-16 17:29:32 -0400192 if (GET_GLOBAL(vmode_g->class) == TEXT) {
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400193 // Get the dimensions
Kevin O'Connordd2be772009-05-16 15:41:23 -0400194 u16 nbcols = GET_BDA(video_cols);
195 u16 nbrows = GET_BDA(video_rows) + 1;
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400196
197 // Calculate the address knowing nbcols nbrows and page num
198 address = SCREEN_MEM_START(nbcols, nbrows, page);
199 SET_BDA(video_pagestart, address);
200
201 // Start address
202 address = SCREEN_IO_START(nbcols, nbrows, page);
203 } else {
Kevin O'Connor5727c292009-05-16 17:29:32 -0400204 struct VideoParam_s *vparam_g = GET_GLOBAL(vmode_g->vparam);
205 address = page * GET_GLOBAL(vparam_g->slength);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400206 }
207
208 // CRTC regs 0x0c and 0x0d
Kevin O'Connordd2be772009-05-16 15:41:23 -0400209 u16 crtc_addr = GET_BDA(crtc_address);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400210 outb(0x0c, crtc_addr);
211 outb((address & 0xff00) >> 8, crtc_addr + 1);
212 outb(0x0d, crtc_addr);
213 outb(address & 0x00ff, crtc_addr + 1);
214
215 // And change the BIOS page
216 SET_BDA(video_page, page);
217
Kevin O'Connora12c2152009-05-13 22:06:16 -0400218 dprintf(1, "Set active page %02x address %04x\n", page, address);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400219
220 // Display the cursor, now the page is active
221 biosfn_set_cursor_pos(page, cursor);
222}
223
224static void
225biosfn_set_video_mode(u8 mode)
226{ // mode: Bit 7 is 1 if no clear screen
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400227 if (CONFIG_CIRRUS)
228 cirrus_set_video_mode(mode);
229
Kevin O'Connor21079f42009-05-16 21:30:10 -0400230 if (CONFIG_VBE)
231 if (vbe_has_vbe_display())
232 dispi_set_enable(VBE_DISPI_DISABLED);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400233
234 // The real mode
Kevin O'Connordd2be772009-05-16 15:41:23 -0400235 u8 noclearmem = mode & 0x80;
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400236 mode = mode & 0x7f;
237
238 // find the entry in the video modes
Kevin O'Connor5727c292009-05-16 17:29:32 -0400239 struct vgamode_s *vmode_g = find_vga_entry(mode);
240 dprintf(1, "mode search %02x found %p\n", mode, vmode_g);
241 if (!vmode_g)
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400242 return;
243
Kevin O'Connor5727c292009-05-16 17:29:32 -0400244 struct VideoParam_s *vparam_g = GET_GLOBAL(vmode_g->vparam);
245 u16 twidth = GET_GLOBAL(vparam_g->twidth);
246 u16 theightm1 = GET_GLOBAL(vparam_g->theightm1);
247 u16 cheight = GET_GLOBAL(vparam_g->cheight);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400248
249 // Read the bios mode set control
Kevin O'Connordd2be772009-05-16 15:41:23 -0400250 u8 modeset_ctl = GET_BDA(modeset_ctl);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400251
252 // Then we know the number of lines
253// FIXME
254
255 // if palette loading (bit 3 of modeset ctl = 0)
256 if ((modeset_ctl & 0x08) == 0) { // Set the PEL mask
Kevin O'Connor5727c292009-05-16 17:29:32 -0400257 outb(GET_GLOBAL(vmode_g->pelmask), VGAREG_PEL_MASK);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400258
259 // Set the whole dac always, from 0
260 outb(0x00, VGAREG_DAC_WRITE_ADDRESS);
261
262 // From which palette
Kevin O'Connor5727c292009-05-16 17:29:32 -0400263 u8 *palette_g = GET_GLOBAL(vmode_g->dac);
Kevin O'Connor3c3c8312009-05-17 16:16:29 -0400264 u16 palsize = GET_GLOBAL(vmode_g->dacsize) / 3;
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400265 // Always 256*3 values
Kevin O'Connordd2be772009-05-16 15:41:23 -0400266 u16 i;
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400267 for (i = 0; i < 0x0100; i++) {
Kevin O'Connor3c3c8312009-05-17 16:16:29 -0400268 if (i < palsize) {
Kevin O'Connordd2be772009-05-16 15:41:23 -0400269 outb(GET_GLOBAL(palette_g[(i * 3) + 0]), VGAREG_DAC_DATA);
270 outb(GET_GLOBAL(palette_g[(i * 3) + 1]), VGAREG_DAC_DATA);
271 outb(GET_GLOBAL(palette_g[(i * 3) + 2]), VGAREG_DAC_DATA);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400272 } else {
273 outb(0, VGAREG_DAC_DATA);
274 outb(0, VGAREG_DAC_DATA);
275 outb(0, VGAREG_DAC_DATA);
276 }
277 }
278 if ((modeset_ctl & 0x02) == 0x02)
279 biosfn_perform_gray_scale_summing(0x00, 0x100);
280 }
281 // Reset Attribute Ctl flip-flop
282 inb(VGAREG_ACTL_RESET);
283
284 // Set Attribute Ctl
Kevin O'Connordd2be772009-05-16 15:41:23 -0400285 u16 i;
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400286 for (i = 0; i <= 0x13; i++) {
287 outb(i, VGAREG_ACTL_ADDRESS);
Kevin O'Connor5727c292009-05-16 17:29:32 -0400288 outb(GET_GLOBAL(vparam_g->actl_regs[i]), VGAREG_ACTL_WRITE_DATA);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400289 }
290 outb(0x14, VGAREG_ACTL_ADDRESS);
291 outb(0x00, VGAREG_ACTL_WRITE_DATA);
292
293 // Set Sequencer Ctl
294 outb(0, VGAREG_SEQU_ADDRESS);
295 outb(0x03, VGAREG_SEQU_DATA);
296 for (i = 1; i <= 4; i++) {
297 outb(i, VGAREG_SEQU_ADDRESS);
Kevin O'Connor5727c292009-05-16 17:29:32 -0400298 outb(GET_GLOBAL(vparam_g->sequ_regs[i - 1]), VGAREG_SEQU_DATA);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400299 }
300
301 // Set Grafx Ctl
302 for (i = 0; i <= 8; i++) {
303 outb(i, VGAREG_GRDC_ADDRESS);
Kevin O'Connor5727c292009-05-16 17:29:32 -0400304 outb(GET_GLOBAL(vparam_g->grdc_regs[i]), VGAREG_GRDC_DATA);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400305 }
306
307 // Set CRTC address VGA or MDA
308 u16 crtc_addr = VGAREG_VGA_CRTC_ADDRESS;
Kevin O'Connor5727c292009-05-16 17:29:32 -0400309 if (GET_GLOBAL(vmode_g->memmodel) == MTEXT)
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400310 crtc_addr = VGAREG_MDA_CRTC_ADDRESS;
311
312 // Disable CRTC write protection
313 outw(0x0011, crtc_addr);
314 // Set CRTC regs
315 for (i = 0; i <= 0x18; i++) {
316 outb(i, crtc_addr);
Kevin O'Connor5727c292009-05-16 17:29:32 -0400317 outb(GET_GLOBAL(vparam_g->crtc_regs[i]), crtc_addr + 1);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400318 }
319
320 // Set the misc register
Kevin O'Connor5727c292009-05-16 17:29:32 -0400321 outb(GET_GLOBAL(vparam_g->miscreg), VGAREG_WRITE_MISC_OUTPUT);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400322
323 // Enable video
324 outb(0x20, VGAREG_ACTL_ADDRESS);
325 inb(VGAREG_ACTL_RESET);
326
327 if (noclearmem == 0x00) {
Kevin O'Connor5727c292009-05-16 17:29:32 -0400328 if (GET_GLOBAL(vmode_g->class) == TEXT) {
329 memset16_far(GET_GLOBAL(vmode_g->sstart), 0, 0x0720, 32*1024);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400330 } else {
331 if (mode < 0x0d) {
Kevin O'Connor5727c292009-05-16 17:29:32 -0400332 memset16_far(GET_GLOBAL(vmode_g->sstart), 0, 0x0000, 32*1024);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400333 } else {
334 outb(0x02, VGAREG_SEQU_ADDRESS);
Kevin O'Connordd2be772009-05-16 15:41:23 -0400335 u8 mmask = inb(VGAREG_SEQU_DATA);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400336 outb(0x0f, VGAREG_SEQU_DATA); // all planes
Kevin O'Connor5727c292009-05-16 17:29:32 -0400337 memset16_far(GET_GLOBAL(vmode_g->sstart), 0, 0x0000, 64*1024);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400338 outb(mmask, VGAREG_SEQU_DATA);
339 }
340 }
341 }
342 // Set the BIOS mem
343 SET_BDA(video_mode, mode);
344 SET_BDA(video_cols, twidth);
Kevin O'Connor5727c292009-05-16 17:29:32 -0400345 SET_BDA(video_pagesize, GET_GLOBAL(vparam_g->slength));
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400346 SET_BDA(crtc_address, crtc_addr);
347 SET_BDA(video_rows, theightm1);
348 SET_BDA(char_height, cheight);
349 SET_BDA(video_ctl, (0x60 | noclearmem));
350 SET_BDA(video_switches, 0xF9);
351 SET_BDA(modeset_ctl, GET_BDA(modeset_ctl) & 0x7f);
352
353 // FIXME We nearly have the good tables. to be reworked
354 SET_BDA(dcc_index, 0x08); // 8 is VGA should be ok for now
355 SET_BDA(video_savetable_ptr, (u32)video_save_pointer_table);
Kevin O'Connord113a992009-05-16 21:05:02 -0400356 SET_BDA(video_savetable_seg, get_global_seg());
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400357
358 // FIXME
359 SET_BDA(video_msr, 0x00); // Unavailable on vanilla vga, but...
360 SET_BDA(video_pal, 0x00); // Unavailable on vanilla vga, but...
361
362 // Set cursor shape
Kevin O'Connor5727c292009-05-16 17:29:32 -0400363 if (GET_GLOBAL(vmode_g->class) == TEXT)
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400364 biosfn_set_cursor_shape(0x06, 0x07);
365 // Set cursor pos for page 0..7
366 for (i = 0; i < 8; i++)
367 biosfn_set_cursor_pos(i, 0x0000);
368
369 // Set active page 0
370 biosfn_set_active_page(0x00);
371
372 // Write the fonts in memory
Kevin O'Connor5727c292009-05-16 17:29:32 -0400373 if (GET_GLOBAL(vmode_g->class) == TEXT) {
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400374 call16_vgaint(0x1104, 0);
375 call16_vgaint(0x1103, 0);
376 }
377 // Set the ints 0x1F and 0x43
Kevin O'Connord113a992009-05-16 21:05:02 -0400378 SET_IVT(0x1f, get_global_seg(), (u32)&vgafont8[128 * 8]);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400379
380 switch (cheight) {
381 case 8:
Kevin O'Connord113a992009-05-16 21:05:02 -0400382 SET_IVT(0x43, get_global_seg(), (u32)vgafont8);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400383 break;
384 case 14:
Kevin O'Connord113a992009-05-16 21:05:02 -0400385 SET_IVT(0x43, get_global_seg(), (u32)vgafont14);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400386 break;
387 case 16:
Kevin O'Connord113a992009-05-16 21:05:02 -0400388 SET_IVT(0x43, get_global_seg(), (u32)vgafont16);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400389 break;
390 }
391}
392
393// -------------------------------------------------------------------
394static void
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400395biosfn_write_teletype(u8 car, u8 page, u8 attr, u8 flag)
396{ // flag = WITH_ATTR / NO_ATTR
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400397 // special case if page is 0xff, use current page
398 if (page == 0xff)
399 page = GET_BDA(video_page);
400
401 // Get the mode
Kevin O'Connor5727c292009-05-16 17:29:32 -0400402 struct vgamode_s *vmode_g = find_vga_entry(GET_BDA(video_mode));
403 if (!vmode_g)
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400404 return;
405
406 // Get the cursor pos for the page
Kevin O'Connor0818e1a2009-05-16 18:00:19 -0400407 u16 cursor = biosfn_get_cursor_pos(page);
Kevin O'Connordd2be772009-05-16 15:41:23 -0400408 u8 xcurs = cursor & 0x00ff;
409 u8 ycurs = (cursor & 0xff00) >> 8;
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400410
411 // Get the dimensions
Kevin O'Connordd2be772009-05-16 15:41:23 -0400412 u16 nbrows = GET_BDA(video_rows) + 1;
413 u16 nbcols = GET_BDA(video_cols);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400414
415 switch (car) {
416 case 7:
417 //FIXME should beep
418 break;
419
420 case 8:
421 if (xcurs > 0)
422 xcurs--;
423 break;
424
425 case '\r':
426 xcurs = 0;
427 break;
428
429 case '\n':
430 ycurs++;
431 break;
432
433 case '\t':
434 do {
435 biosfn_write_teletype(' ', page, attr, flag);
Kevin O'Connor0818e1a2009-05-16 18:00:19 -0400436 cursor = biosfn_get_cursor_pos(page);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400437 xcurs = cursor & 0x00ff;
438 ycurs = (cursor & 0xff00) >> 8;
439 } while (xcurs % 8 == 0);
440 break;
441
442 default:
Kevin O'Connorc0c7df62009-05-17 18:11:33 -0400443 if (flag == WITH_ATTR)
444 biosfn_write_char_attr(car, page, attr, 1);
445 else
446 biosfn_write_char_only(car, page, attr, 1);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400447 xcurs++;
448 }
449
450 // Do we need to wrap ?
451 if (xcurs == nbcols) {
452 xcurs = 0;
453 ycurs++;
454 }
455 // Do we need to scroll ?
456 if (ycurs == nbrows) {
Kevin O'Connor5727c292009-05-16 17:29:32 -0400457 if (GET_GLOBAL(vmode_g->class) == TEXT)
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400458 biosfn_scroll(0x01, 0x07, 0, 0, nbrows - 1, nbcols - 1, page,
459 SCROLL_UP);
460 else
461 biosfn_scroll(0x01, 0x00, 0, 0, nbrows - 1, nbcols - 1, page,
462 SCROLL_UP);
463 ycurs -= 1;
464 }
465 // Set the cursor for the page
466 cursor = ycurs;
467 cursor <<= 8;
468 cursor += xcurs;
469 biosfn_set_cursor_pos(page, cursor);
470}
471
472// -------------------------------------------------------------------
473static void
474biosfn_get_video_mode(struct bregs *regs)
475{
476 regs->bh = GET_BDA(video_page);
477 regs->al = GET_BDA(video_mode) | (GET_BDA(video_ctl) & 0x80);
478 regs->ah = GET_BDA(video_cols);
479}
480
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400481static void
482set_scan_lines(u8 lines)
483{
Kevin O'Connordd2be772009-05-16 15:41:23 -0400484 u16 crtc_addr = GET_BDA(crtc_address);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400485 outb(0x09, crtc_addr);
Kevin O'Connordd2be772009-05-16 15:41:23 -0400486 u8 crtc_r9 = inb(crtc_addr + 1);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400487 crtc_r9 = (crtc_r9 & 0xe0) | (lines - 1);
488 outb(crtc_r9, crtc_addr + 1);
489 if (lines == 8)
490 biosfn_set_cursor_shape(0x06, 0x07);
491 else
492 biosfn_set_cursor_shape(lines - 4, lines - 3);
493 SET_BDA(char_height, lines);
494 outb(0x12, crtc_addr);
Kevin O'Connordd2be772009-05-16 15:41:23 -0400495 u16 vde = inb(crtc_addr + 1);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400496 outb(0x07, crtc_addr);
Kevin O'Connordd2be772009-05-16 15:41:23 -0400497 u8 ovl = inb(crtc_addr + 1);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400498 vde += (((ovl & 0x02) << 7) + ((ovl & 0x40) << 3) + 1);
Kevin O'Connordd2be772009-05-16 15:41:23 -0400499 u8 rows = vde / lines;
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400500 SET_BDA(video_rows, rows - 1);
Kevin O'Connordd2be772009-05-16 15:41:23 -0400501 u16 cols = GET_BDA(video_cols);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400502 SET_BDA(video_pagesize, rows * cols * 2);
503}
504
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400505// -------------------------------------------------------------------
506static void
507biosfn_get_font_info(u8 BH, u16 *ES, u16 *BP, u16 *CX, u16 *DX)
508{
509 switch (BH) {
510 case 0x00: {
511 u32 segoff = GET_IVT(0x1f).segoff;
512 *ES = segoff >> 16;
513 *BP = segoff;
514 break;
515 }
516 case 0x01: {
517 u32 segoff = GET_IVT(0x43).segoff;
518 *ES = segoff >> 16;
519 *BP = segoff;
520 break;
521 }
522 case 0x02:
Kevin O'Connord113a992009-05-16 21:05:02 -0400523 *ES = get_global_seg();
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400524 *BP = (u32)vgafont14;
525 break;
526 case 0x03:
Kevin O'Connord113a992009-05-16 21:05:02 -0400527 *ES = get_global_seg();
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400528 *BP = (u32)vgafont8;
529 break;
530 case 0x04:
Kevin O'Connord113a992009-05-16 21:05:02 -0400531 *ES = get_global_seg();
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400532 *BP = (u32)vgafont8 + 128 * 8;
533 break;
534 case 0x05:
Kevin O'Connord113a992009-05-16 21:05:02 -0400535 *ES = get_global_seg();
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400536 *BP = (u32)vgafont14alt;
537 break;
538 case 0x06:
Kevin O'Connord113a992009-05-16 21:05:02 -0400539 *ES = get_global_seg();
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400540 *BP = (u32)vgafont16;
541 break;
542 case 0x07:
Kevin O'Connord113a992009-05-16 21:05:02 -0400543 *ES = get_global_seg();
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400544 *BP = (u32)vgafont16alt;
545 break;
546 default:
Kevin O'Connora12c2152009-05-13 22:06:16 -0400547 dprintf(1, "Get font info BH(%02x) was discarded\n", BH);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400548 return;
549 }
550 // Set byte/char of on screen font
551 *CX = GET_BDA(char_height) & 0xff;
552
553 // Set Highest char row
554 *DX = GET_BDA(video_rows);
555}
556
557// -------------------------------------------------------------------
558static void
559biosfn_get_ega_info(struct bregs *regs)
560{
561 regs->cx = GET_BDA(video_switches) & 0x0f;
562 regs->ax = GET_BDA(crtc_address);
563 if (regs->ax == VGAREG_MDA_CRTC_ADDRESS)
564 regs->bx = 0x0103;
565 else
566 regs->bx = 0x0003;
567}
568
569// -------------------------------------------------------------------
570static void
571biosfn_select_vert_res(struct bregs *regs)
572{
573 u8 mctl = GET_BDA(modeset_ctl);
574 u8 vswt = GET_BDA(video_switches);
575
576 switch (regs->al) {
577 case 0x00:
578 // 200 lines
579 mctl = (mctl & ~0x10) | 0x80;
580 vswt = (vswt & ~0x0f) | 0x08;
581 break;
582 case 0x01:
583 // 350 lines
584 mctl &= ~0x90;
585 vswt = (vswt & ~0x0f) | 0x09;
586 break;
587 case 0x02:
588 // 400 lines
589 mctl = (mctl & ~0x80) | 0x10;
590 vswt = (vswt & ~0x0f) | 0x09;
591 break;
592 default:
Kevin O'Connora12c2152009-05-13 22:06:16 -0400593 dprintf(1, "Select vert res (%02x) was discarded\n", regs->al);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400594 break;
595 }
596 SET_BDA(modeset_ctl, mctl);
597 SET_BDA(video_switches, vswt);
598 regs->ax = 0x1212;
599}
600
601static void
602biosfn_enable_default_palette_loading(struct bregs *regs)
603{
604 u8 v = (regs->al & 0x01) << 3;
605 u8 mctl = GET_BDA(video_ctl) & ~0x08;
606 SET_BDA(video_ctl, mctl | v);
607 regs->ax = 0x1212;
608}
609
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400610
611static void
612biosfn_enable_grayscale_summing(struct bregs *regs)
613{
614 u8 v = ((regs->al << 1) & 0x02) ^ 0x02;
615 u8 v2 = GET_BDA(modeset_ctl) & ~0x02;
616 SET_BDA(modeset_ctl, v | v2);
617 regs->ax = 0x1212;
618}
619
620static void
621biosfn_enable_cursor_emulation(struct bregs *regs)
622{
623 u8 v = (regs->al & 0x01) ^ 0x01;
624 u8 v2 = GET_BDA(modeset_ctl) & ~0x01;
625 SET_BDA(modeset_ctl, v | v2);
626 regs->ax = 0x1212;
627}
628
629// -------------------------------------------------------------------
630static void
631biosfn_write_string(u8 flag, u8 page, u8 attr, u16 count, u8 row, u8 col,
Kevin O'Connordd2be772009-05-16 15:41:23 -0400632 u16 seg, u8 *offset_far)
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400633{
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400634 // Read curs info for the page
Kevin O'Connor0818e1a2009-05-16 18:00:19 -0400635 u16 oldcurs = biosfn_get_cursor_pos(page);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400636
637 // if row=0xff special case : use current cursor position
638 if (row == 0xff) {
639 col = oldcurs & 0x00ff;
640 row = (oldcurs & 0xff00) >> 8;
641 }
642
Kevin O'Connordd2be772009-05-16 15:41:23 -0400643 u16 newcurs = row;
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400644 newcurs <<= 8;
645 newcurs += col;
646 biosfn_set_cursor_pos(page, newcurs);
647
648 while (count-- != 0) {
Kevin O'Connordd2be772009-05-16 15:41:23 -0400649 u8 car = GET_FARVAR(seg, *offset_far);
650 offset_far++;
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400651 if ((flag & 0x02) != 0) {
Kevin O'Connordd2be772009-05-16 15:41:23 -0400652 attr = GET_FARVAR(seg, *offset_far);
653 offset_far++;
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400654 }
655
656 biosfn_write_teletype(car, page, attr, WITH_ATTR);
657 }
658
659 // Set back curs pos
660 if ((flag & 0x01) == 0)
661 biosfn_set_cursor_pos(page, oldcurs);
662}
663
664// -------------------------------------------------------------------
665static void
666biosfn_read_display_code(struct bregs *regs)
667{
668 regs->bx = GET_BDA(dcc_index);
669 regs->al = 0x1a;
670}
671
672static void
673biosfn_set_display_code(struct bregs *regs)
674{
675 SET_BDA(dcc_index, regs->bl);
Kevin O'Connora12c2152009-05-13 22:06:16 -0400676 dprintf(1, "Alternate Display code (%02x) was discarded\n", regs->bh);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400677 regs->al = 0x1a;
678}
679
680// -------------------------------------------------------------------
681static void
682biosfn_read_state_info(u16 BX, u16 ES, u16 DI)
683{
684 // Address of static functionality table
685 SET_FARVAR(ES, *(u16*)(DI + 0x00), (u32)static_functionality);
Kevin O'Connord113a992009-05-16 21:05:02 -0400686 SET_FARVAR(ES, *(u16*)(DI + 0x02), get_global_seg());
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400687
688 // Hard coded copy from BIOS area. Should it be cleaner ?
689 memcpy_far(ES, (void*)(DI + 0x04), SEG_BDA, (void*)0x49, 30);
690 memcpy_far(ES, (void*)(DI + 0x22), SEG_BDA, (void*)0x84, 3);
691
692 SET_FARVAR(ES, *(u8*)(DI + 0x25), GET_BDA(dcc_index));
693 SET_FARVAR(ES, *(u8*)(DI + 0x26), 0);
694 SET_FARVAR(ES, *(u8*)(DI + 0x27), 16);
695 SET_FARVAR(ES, *(u8*)(DI + 0x28), 0);
696 SET_FARVAR(ES, *(u8*)(DI + 0x29), 8);
697 SET_FARVAR(ES, *(u8*)(DI + 0x2a), 2);
698 SET_FARVAR(ES, *(u8*)(DI + 0x2b), 0);
699 SET_FARVAR(ES, *(u8*)(DI + 0x2c), 0);
700 SET_FARVAR(ES, *(u8*)(DI + 0x31), 3);
701 SET_FARVAR(ES, *(u8*)(DI + 0x32), 0);
702
703 memset_far(ES, (void*)(DI + 0x33), 0, 13);
704}
705
706// -------------------------------------------------------------------
707// -------------------------------------------------------------------
708static u16
709biosfn_read_video_state_size(u16 CX)
710{
711 u16 size = 0;
712 if (CX & 1)
713 size += 0x46;
714 if (CX & 2)
715 size += (5 + 8 + 5) * 2 + 6;
716 if (CX & 4)
717 size += 3 + 256 * 3 + 1;
718 return size;
719}
720
721static u16
722biosfn_save_video_state(u16 CX, u16 ES, u16 BX)
723{
Kevin O'Connordd2be772009-05-16 15:41:23 -0400724 u16 crtc_addr = GET_BDA(crtc_address);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400725 if (CX & 1) {
726 SET_FARVAR(ES, *(u8*)(BX+0), inb(VGAREG_SEQU_ADDRESS));
727 BX++;
728 SET_FARVAR(ES, *(u8*)(BX+0), inb(crtc_addr));
729 BX++;
730 SET_FARVAR(ES, *(u8*)(BX+0), inb(VGAREG_GRDC_ADDRESS));
731 BX++;
732 inb(VGAREG_ACTL_RESET);
Kevin O'Connordd2be772009-05-16 15:41:23 -0400733 u16 ar_index = inb(VGAREG_ACTL_ADDRESS);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400734 SET_FARVAR(ES, *(u8*)(BX+0), ar_index);
735 BX++;
736 SET_FARVAR(ES, *(u8*)(BX+0), inb(VGAREG_READ_FEATURE_CTL));
737 BX++;
738
Kevin O'Connordd2be772009-05-16 15:41:23 -0400739 u16 i;
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400740 for (i = 1; i <= 4; i++) {
741 outb(i, VGAREG_SEQU_ADDRESS);
742 SET_FARVAR(ES, *(u8*)(BX+0), inb(VGAREG_SEQU_DATA));
743 BX++;
744 }
745 outb(0, VGAREG_SEQU_ADDRESS);
746 SET_FARVAR(ES, *(u8*)(BX+0), inb(VGAREG_SEQU_DATA));
747 BX++;
748
749 for (i = 0; i <= 0x18; i++) {
750 outb(i, crtc_addr);
751 SET_FARVAR(ES, *(u8*)(BX+0), inb(crtc_addr + 1));
752 BX++;
753 }
754
755 for (i = 0; i <= 0x13; i++) {
756 inb(VGAREG_ACTL_RESET);
757 outb(i | (ar_index & 0x20), VGAREG_ACTL_ADDRESS);
758 SET_FARVAR(ES, *(u8*)(BX+0), inb(VGAREG_ACTL_READ_DATA));
759 BX++;
760 }
761 inb(VGAREG_ACTL_RESET);
762
763 for (i = 0; i <= 8; i++) {
764 outb(i, VGAREG_GRDC_ADDRESS);
765 SET_FARVAR(ES, *(u8*)(BX+0), inb(VGAREG_GRDC_DATA));
766 BX++;
767 }
768
769 SET_FARVAR(ES, *(u16*)(BX+0), crtc_addr);
770 BX += 2;
771
772 /* XXX: read plane latches */
773 SET_FARVAR(ES, *(u8*)(BX+0), 0);
774 BX++;
775 SET_FARVAR(ES, *(u8*)(BX+0), 0);
776 BX++;
777 SET_FARVAR(ES, *(u8*)(BX+0), 0);
778 BX++;
779 SET_FARVAR(ES, *(u8*)(BX+0), 0);
780 BX++;
781 }
782 if (CX & 2) {
783 SET_FARVAR(ES, *(u8*)(BX+0), GET_BDA(video_mode));
784 BX++;
785 SET_FARVAR(ES, *(u16*)(BX+0), GET_BDA(video_cols));
786 BX += 2;
787 SET_FARVAR(ES, *(u16*)(BX+0), GET_BDA(video_pagesize));
788 BX += 2;
789 SET_FARVAR(ES, *(u16*)(BX+0), GET_BDA(crtc_address));
790 BX += 2;
791 SET_FARVAR(ES, *(u8*)(BX+0), GET_BDA(video_rows));
792 BX++;
793 SET_FARVAR(ES, *(u16*)(BX+0), GET_BDA(char_height));
794 BX += 2;
795 SET_FARVAR(ES, *(u8*)(BX+0), GET_BDA(video_ctl));
796 BX++;
797 SET_FARVAR(ES, *(u8*)(BX+0), GET_BDA(video_switches));
798 BX++;
799 SET_FARVAR(ES, *(u8*)(BX+0), GET_BDA(modeset_ctl));
800 BX++;
801 SET_FARVAR(ES, *(u16*)(BX+0), GET_BDA(cursor_type));
802 BX += 2;
Kevin O'Connordd2be772009-05-16 15:41:23 -0400803 u16 i;
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400804 for (i = 0; i < 8; i++) {
805 SET_FARVAR(ES, *(u16*)(BX+0), GET_BDA(cursor_pos[i]));
806 BX += 2;
807 }
808 SET_FARVAR(ES, *(u16*)(BX+0), GET_BDA(video_pagestart));
809 BX += 2;
810 SET_FARVAR(ES, *(u8*)(BX+0), GET_BDA(video_page));
811 BX++;
812 /* current font */
Kevin O'Connorf61afb82009-05-16 21:32:27 -0400813 SET_FARVAR(ES, *(u32*)(BX+0), GET_IVT(0x1f).segoff);
814 BX += 4;
815 SET_FARVAR(ES, *(u32*)(BX+0), GET_IVT(0x43).segoff);
816 BX += 4;
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400817 }
818 if (CX & 4) {
819 /* XXX: check this */
820 SET_FARVAR(ES, *(u8*)(BX+0), inb(VGAREG_DAC_STATE));
821 BX++; /* read/write mode dac */
822 SET_FARVAR(ES, *(u8*)(BX+0), inb(VGAREG_DAC_WRITE_ADDRESS));
823 BX++; /* pix address */
824 SET_FARVAR(ES, *(u8*)(BX+0), inb(VGAREG_PEL_MASK));
825 BX++;
826 // Set the whole dac always, from 0
827 outb(0x00, VGAREG_DAC_WRITE_ADDRESS);
Kevin O'Connordd2be772009-05-16 15:41:23 -0400828 u16 i;
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400829 for (i = 0; i < 256 * 3; i++) {
830 SET_FARVAR(ES, *(u8*)(BX+0), inb(VGAREG_DAC_DATA));
831 BX++;
832 }
833 SET_FARVAR(ES, *(u8*)(BX+0), 0);
834 BX++; /* color select register */
835 }
836 return BX;
837}
838
839static u16
840biosfn_restore_video_state(u16 CX, u16 ES, u16 BX)
841{
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400842 if (CX & 1) {
843 // Reset Attribute Ctl flip-flop
844 inb(VGAREG_ACTL_RESET);
845
Kevin O'Connordd2be772009-05-16 15:41:23 -0400846 u16 crtc_addr = GET_FARVAR(ES, *(u16*)(BX + 0x40));
847 u16 addr1 = BX;
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400848 BX += 5;
849
Kevin O'Connordd2be772009-05-16 15:41:23 -0400850 u16 i;
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400851 for (i = 1; i <= 4; i++) {
852 outb(i, VGAREG_SEQU_ADDRESS);
853 outb(GET_FARVAR(ES, *(u8*)(BX+0)), VGAREG_SEQU_DATA);
854 BX++;
855 }
856 outb(0, VGAREG_SEQU_ADDRESS);
857 outb(GET_FARVAR(ES, *(u8*)(BX+0)), VGAREG_SEQU_DATA);
858 BX++;
859
860 // Disable CRTC write protection
861 outw(0x0011, crtc_addr);
862 // Set CRTC regs
863 for (i = 0; i <= 0x18; i++) {
864 if (i != 0x11) {
865 outb(i, crtc_addr);
866 outb(GET_FARVAR(ES, *(u8*)(BX+0)), crtc_addr + 1);
867 }
868 BX++;
869 }
870 // select crtc base address
Kevin O'Connordd2be772009-05-16 15:41:23 -0400871 u16 v = inb(VGAREG_READ_MISC_OUTPUT) & ~0x01;
Kevin O'Connord9fc0a02009-05-07 22:00:25 -0400872 if (crtc_addr == VGAREG_VGA_CRTC_ADDRESS)
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400873 v |= 0x01;
874 outb(v, VGAREG_WRITE_MISC_OUTPUT);
875
876 // enable write protection if needed
877 outb(0x11, crtc_addr);
878 outb(GET_FARVAR(ES, *(u8*)(BX - 0x18 + 0x11)), crtc_addr + 1);
879
880 // Set Attribute Ctl
Kevin O'Connordd2be772009-05-16 15:41:23 -0400881 u16 ar_index = GET_FARVAR(ES, *(u8*)(addr1 + 0x03));
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400882 inb(VGAREG_ACTL_RESET);
883 for (i = 0; i <= 0x13; i++) {
884 outb(i | (ar_index & 0x20), VGAREG_ACTL_ADDRESS);
885 outb(GET_FARVAR(ES, *(u8*)(BX+0)), VGAREG_ACTL_WRITE_DATA);
886 BX++;
887 }
888 outb(ar_index, VGAREG_ACTL_ADDRESS);
889 inb(VGAREG_ACTL_RESET);
890
891 for (i = 0; i <= 8; i++) {
892 outb(i, VGAREG_GRDC_ADDRESS);
893 outb(GET_FARVAR(ES, *(u8*)(BX+0)), VGAREG_GRDC_DATA);
894 BX++;
895 }
896 BX += 2; /* crtc_addr */
897 BX += 4; /* plane latches */
898
899 outb(GET_FARVAR(ES, *(u8*)(addr1+0)), VGAREG_SEQU_ADDRESS);
900 addr1++;
901 outb(GET_FARVAR(ES, *(u8*)(addr1+0)), crtc_addr);
902 addr1++;
903 outb(GET_FARVAR(ES, *(u8*)(addr1+0)), VGAREG_GRDC_ADDRESS);
904 addr1++;
905 addr1++;
906 outb(GET_FARVAR(ES, *(u8*)(addr1+0)), crtc_addr - 0x4 + 0xa);
907 addr1++;
908 }
909 if (CX & 2) {
910 SET_BDA(video_mode, GET_FARVAR(ES, *(u8*)(BX+0)));
911 BX++;
912 SET_BDA(video_cols, GET_FARVAR(ES, *(u16*)(BX+0)));
913 BX += 2;
914 SET_BDA(video_pagesize, GET_FARVAR(ES, *(u16*)(BX+0)));
915 BX += 2;
916 SET_BDA(crtc_address, GET_FARVAR(ES, *(u16*)(BX+0)));
917 BX += 2;
918 SET_BDA(video_rows, GET_FARVAR(ES, *(u8*)(BX+0)));
919 BX++;
920 SET_BDA(char_height, GET_FARVAR(ES, *(u16*)(BX+0)));
921 BX += 2;
922 SET_BDA(video_ctl, GET_FARVAR(ES, *(u8*)(BX+0)));
923 BX++;
924 SET_BDA(video_switches, GET_FARVAR(ES, *(u8*)(BX+0)));
925 BX++;
926 SET_BDA(modeset_ctl, GET_FARVAR(ES, *(u8*)(BX+0)));
927 BX++;
928 SET_BDA(cursor_type, GET_FARVAR(ES, *(u16*)(BX+0)));
929 BX += 2;
Kevin O'Connordd2be772009-05-16 15:41:23 -0400930 u16 i;
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400931 for (i = 0; i < 8; i++) {
932 SET_BDA(cursor_pos[i], GET_FARVAR(ES, *(u16*)(BX+0)));
933 BX += 2;
934 }
935 SET_BDA(video_pagestart, GET_FARVAR(ES, *(u16*)(BX+0)));
936 BX += 2;
937 SET_BDA(video_page, GET_FARVAR(ES, *(u8*)(BX+0)));
938 BX++;
939 /* current font */
940 SET_IVT(0x1f, GET_FARVAR(ES, *(u16*)(BX+2)), GET_FARVAR(ES, *(u16*)(BX+0)));
941 BX += 4;
942 SET_IVT(0x43, GET_FARVAR(ES, *(u16*)(BX+2)), GET_FARVAR(ES, *(u16*)(BX+0)));
943 BX += 4;
944 }
945 if (CX & 4) {
946 BX++;
Kevin O'Connordd2be772009-05-16 15:41:23 -0400947 u16 v = GET_FARVAR(ES, *(u8*)(BX+0));
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400948 BX++;
949 outb(GET_FARVAR(ES, *(u8*)(BX+0)), VGAREG_PEL_MASK);
950 BX++;
951 // Set the whole dac always, from 0
952 outb(0x00, VGAREG_DAC_WRITE_ADDRESS);
Kevin O'Connordd2be772009-05-16 15:41:23 -0400953 u16 i;
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400954 for (i = 0; i < 256 * 3; i++) {
955 outb(GET_FARVAR(ES, *(u8*)(BX+0)), VGAREG_DAC_DATA);
956 BX++;
957 }
958 BX++;
959 outb(v, VGAREG_DAC_WRITE_ADDRESS);
960 }
961 return BX;
962}
963
964
965/****************************************************************
966 * VGA int 10 handler
967 ****************************************************************/
968
969static void
970handle_1000(struct bregs *regs)
971{
972 // XXX - inline
973 biosfn_set_video_mode(regs->al);
974 switch(regs->al & 0x7F) {
975 case 6:
976 regs->al = 0x3F;
977 break;
978 case 0:
979 case 1:
980 case 2:
981 case 3:
982 case 4:
983 case 5:
984 case 7:
985 regs->al = 0x30;
986 break;
987 default:
988 regs->al = 0x20;
989 }
990}
991
992static void
993handle_1001(struct bregs *regs)
994{
995 biosfn_set_cursor_shape(regs->ch, regs->cl);
996}
997
998static void
999handle_1002(struct bregs *regs)
1000{
1001 biosfn_set_cursor_pos(regs->bh, regs->dx);
1002}
1003
1004static void
1005handle_1003(struct bregs *regs)
1006{
Kevin O'Connor0818e1a2009-05-16 18:00:19 -04001007 regs->cx = biosfn_get_cursor_shape(regs->bh);
1008 regs->dx = biosfn_get_cursor_pos(regs->bh);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -04001009}
1010
1011// Read light pen pos (unimplemented)
1012static void
1013handle_1004(struct bregs *regs)
1014{
1015 debug_stub(regs);
1016 regs->ax = regs->bx = regs->cx = regs->dx = 0;
1017}
1018
1019static void
1020handle_1005(struct bregs *regs)
1021{
1022 biosfn_set_active_page(regs->al);
1023}
1024
1025static void
1026handle_1006(struct bregs *regs)
1027{
1028 biosfn_scroll(regs->al, regs->bh, regs->ch, regs->cl, regs->dh, regs->dl
1029 , 0xFF, SCROLL_UP);
1030}
1031
1032static void
1033handle_1007(struct bregs *regs)
1034{
1035 biosfn_scroll(regs->al, regs->bh, regs->ch, regs->cl, regs->dh, regs->dl
1036 , 0xFF, SCROLL_DOWN);
1037}
1038
1039static void
1040handle_1008(struct bregs *regs)
1041{
1042 // XXX - inline
1043 biosfn_read_char_attr(regs->bh, &regs->ax);
1044}
1045
1046static void
1047handle_1009(struct bregs *regs)
1048{
1049 // XXX - inline
1050 biosfn_write_char_attr(regs->al, regs->bh, regs->bl, regs->cx);
1051}
1052
1053static void
1054handle_100a(struct bregs *regs)
1055{
1056 // XXX - inline
1057 biosfn_write_char_only(regs->al, regs->bh, regs->bl, regs->cx);
1058}
1059
1060
1061static void
1062handle_100b00(struct bregs *regs)
1063{
1064 // XXX - inline
1065 biosfn_set_border_color(regs);
1066}
1067
1068static void
1069handle_100b01(struct bregs *regs)
1070{
1071 // XXX - inline
1072 biosfn_set_palette(regs);
1073}
1074
1075static void
1076handle_100bXX(struct bregs *regs)
1077{
1078 debug_stub(regs);
1079}
1080
1081static void
1082handle_100b(struct bregs *regs)
1083{
1084 switch (regs->bh) {
1085 case 0x00: handle_100b00(regs); break;
1086 case 0x01: handle_100b01(regs); break;
1087 default: handle_100bXX(regs); break;
1088 }
1089}
1090
1091
1092static void
1093handle_100c(struct bregs *regs)
1094{
1095 // XXX - inline
1096 biosfn_write_pixel(regs->bh, regs->al, regs->cx, regs->dx);
1097}
1098
1099static void
1100handle_100d(struct bregs *regs)
1101{
1102 // XXX - inline
1103 biosfn_read_pixel(regs->bh, regs->cx, regs->dx, &regs->ax);
1104}
1105
1106static void
1107handle_100e(struct bregs *regs)
1108{
1109 // Ralf Brown Interrupt list is WRONG on bh(page)
1110 // We do output only on the current page !
1111 biosfn_write_teletype(regs->al, 0xff, regs->bl, NO_ATTR);
1112}
1113
1114static void
1115handle_100f(struct bregs *regs)
1116{
1117 // XXX - inline
1118 biosfn_get_video_mode(regs);
1119}
1120
1121
1122static void
1123handle_101000(struct bregs *regs)
1124{
1125 if (regs->bl > 0x14)
1126 return;
1127 biosfn_set_single_palette_reg(regs->bl, regs->bh);
1128}
1129
1130static void
1131handle_101001(struct bregs *regs)
1132{
1133 // XXX - inline
1134 biosfn_set_overscan_border_color(regs);
1135}
1136
1137static void
1138handle_101002(struct bregs *regs)
1139{
1140 // XXX - inline
1141 biosfn_set_all_palette_reg(regs);
1142}
1143
1144static void
1145handle_101003(struct bregs *regs)
1146{
1147 // XXX - inline
1148 biosfn_toggle_intensity(regs);
1149}
1150
1151static void
1152handle_101007(struct bregs *regs)
1153{
1154 if (regs->bl > 0x14)
1155 return;
1156 regs->bh = biosfn_get_single_palette_reg(regs->bl);
1157}
1158
1159static void
1160handle_101008(struct bregs *regs)
1161{
1162 // XXX - inline
1163 biosfn_read_overscan_border_color(regs);
1164}
1165
1166static void
1167handle_101009(struct bregs *regs)
1168{
1169 // XXX - inline
1170 biosfn_get_all_palette_reg(regs);
1171}
1172
1173static void
1174handle_101010(struct bregs *regs)
1175{
1176 // XXX - inline
1177 biosfn_set_single_dac_reg(regs);
1178}
1179
1180static void
1181handle_101012(struct bregs *regs)
1182{
1183 // XXX - inline
1184 biosfn_set_all_dac_reg(regs);
1185}
1186
1187static void
1188handle_101013(struct bregs *regs)
1189{
1190 // XXX - inline
1191 biosfn_select_video_dac_color_page(regs);
1192}
1193
1194static void
1195handle_101015(struct bregs *regs)
1196{
1197 // XXX - inline
1198 biosfn_read_single_dac_reg(regs);
1199}
1200
1201static void
1202handle_101017(struct bregs *regs)
1203{
1204 // XXX - inline
1205 biosfn_read_all_dac_reg(regs);
1206}
1207
1208static void
1209handle_101018(struct bregs *regs)
1210{
1211 // XXX - inline
1212 biosfn_set_pel_mask(regs);
1213}
1214
1215static void
1216handle_101019(struct bregs *regs)
1217{
1218 // XXX - inline
1219 biosfn_read_pel_mask(regs);
1220}
1221
1222static void
1223handle_10101a(struct bregs *regs)
1224{
1225 // XXX - inline
1226 biosfn_read_video_dac_state(regs);
1227}
1228
1229static void
1230handle_10101b(struct bregs *regs)
1231{
1232 biosfn_perform_gray_scale_summing(regs->bx, regs->cx);
1233}
1234
1235static void
1236handle_1010XX(struct bregs *regs)
1237{
1238 debug_stub(regs);
1239}
1240
1241static void
1242handle_1010(struct bregs *regs)
1243{
1244 switch (regs->al) {
1245 case 0x00: handle_101000(regs); break;
1246 case 0x01: handle_101001(regs); break;
1247 case 0x02: handle_101002(regs); break;
1248 case 0x03: handle_101003(regs); break;
1249 case 0x07: handle_101007(regs); break;
1250 case 0x08: handle_101008(regs); break;
1251 case 0x09: handle_101009(regs); break;
1252 case 0x10: handle_101010(regs); break;
1253 case 0x12: handle_101012(regs); break;
1254 case 0x13: handle_101013(regs); break;
1255 case 0x15: handle_101015(regs); break;
1256 case 0x17: handle_101017(regs); break;
1257 case 0x18: handle_101018(regs); break;
1258 case 0x19: handle_101019(regs); break;
1259 case 0x1a: handle_10101a(regs); break;
1260 case 0x1b: handle_10101b(regs); break;
1261 default: handle_1010XX(regs); break;
1262 }
1263}
1264
1265
1266static void
1267handle_101100(struct bregs *regs)
1268{
Kevin O'Connorc0c7df62009-05-17 18:11:33 -04001269 biosfn_load_text_user_pat(regs->es, regs->bp
Kevin O'Connor1f2c3072009-05-06 23:35:59 -04001270 , regs->cx, regs->dx, regs->bl, regs->bh);
1271}
1272
1273static void
1274handle_101101(struct bregs *regs)
1275{
Kevin O'Connorc0c7df62009-05-17 18:11:33 -04001276 biosfn_load_text_8_14_pat(regs->bl);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -04001277}
1278
1279static void
1280handle_101102(struct bregs *regs)
1281{
Kevin O'Connorc0c7df62009-05-17 18:11:33 -04001282 biosfn_load_text_8_8_pat(regs->bl);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -04001283}
1284
1285static void
1286handle_101103(struct bregs *regs)
1287{
1288 // XXX - inline
1289 biosfn_set_text_block_specifier(regs);
1290}
1291
1292static void
1293handle_101104(struct bregs *regs)
1294{
Kevin O'Connorc0c7df62009-05-17 18:11:33 -04001295 biosfn_load_text_8_16_pat(regs->bl);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -04001296}
1297
1298static void
1299handle_101110(struct bregs *regs)
1300{
Kevin O'Connorc0c7df62009-05-17 18:11:33 -04001301 biosfn_load_text_user_pat(regs->es, regs->bp
1302 , regs->cx, regs->dx, regs->bl, regs->bh);
1303 set_scan_lines(regs->bh);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -04001304}
1305
1306static void
1307handle_101111(struct bregs *regs)
1308{
Kevin O'Connorc0c7df62009-05-17 18:11:33 -04001309 biosfn_load_text_8_14_pat(regs->bl);
1310 set_scan_lines(14);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -04001311}
1312
1313static void
1314handle_101112(struct bregs *regs)
1315{
Kevin O'Connorc0c7df62009-05-17 18:11:33 -04001316 biosfn_load_text_8_8_pat(regs->bl);
1317 set_scan_lines(8);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -04001318}
1319
1320static void
1321handle_101114(struct bregs *regs)
1322{
Kevin O'Connorc0c7df62009-05-17 18:11:33 -04001323 biosfn_load_text_8_16_pat(regs->bl);
1324 set_scan_lines(16);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -04001325}
1326
1327static void
1328handle_101130(struct bregs *regs)
1329{
1330 // XXX - inline
Kevin O'Connor99e08b72009-05-17 00:07:31 -04001331 biosfn_get_font_info(regs->bh, &regs->es, &regs->bp
Kevin O'Connor1f2c3072009-05-06 23:35:59 -04001332 , &regs->cx, &regs->dx);
1333}
1334
1335static void
1336handle_1011XX(struct bregs *regs)
1337{
1338 debug_stub(regs);
1339}
1340
1341static void
1342handle_1011(struct bregs *regs)
1343{
1344 switch (regs->al) {
1345 case 0x00: handle_101100(regs); break;
1346 case 0x01: handle_101101(regs); break;
1347 case 0x02: handle_101102(regs); break;
1348 case 0x03: handle_101103(regs); break;
1349 case 0x04: handle_101104(regs); break;
1350 case 0x10: handle_101110(regs); break;
1351 case 0x11: handle_101111(regs); break;
1352 case 0x12: handle_101112(regs); break;
1353 case 0x14: handle_101114(regs); break;
1354 case 0x30: handle_101130(regs); break;
1355 default: handle_1011XX(regs); break;
1356 }
1357}
1358
1359
1360static void
1361handle_101210(struct bregs *regs)
1362{
1363 // XXX - inline
1364 biosfn_get_ega_info(regs);
1365}
1366
1367static void
1368handle_101230(struct bregs *regs)
1369{
1370 // XXX - inline
1371 biosfn_select_vert_res(regs);
1372}
1373
1374static void
1375handle_101231(struct bregs *regs)
1376{
1377 // XXX - inline
1378 biosfn_enable_default_palette_loading(regs);
1379}
1380
1381static void
1382handle_101232(struct bregs *regs)
1383{
1384 // XXX - inline
1385 biosfn_enable_video_addressing(regs);
1386}
1387
1388static void
1389handle_101233(struct bregs *regs)
1390{
1391 // XXX - inline
1392 biosfn_enable_grayscale_summing(regs);
1393}
1394
1395static void
1396handle_101234(struct bregs *regs)
1397{
1398 // XXX - inline
1399 biosfn_enable_cursor_emulation(regs);
1400}
1401
1402static void
1403handle_101235(struct bregs *regs)
1404{
1405 debug_stub(regs);
1406 regs->al = 0x12;
1407}
1408
1409static void
1410handle_101236(struct bregs *regs)
1411{
1412 debug_stub(regs);
1413 regs->al = 0x12;
1414}
1415
1416static void
1417handle_1012XX(struct bregs *regs)
1418{
1419 debug_stub(regs);
1420}
1421
1422static void
1423handle_1012(struct bregs *regs)
1424{
1425 switch (regs->bl) {
1426 case 0x10: handle_101210(regs); break;
1427 case 0x30: handle_101230(regs); break;
1428 case 0x31: handle_101231(regs); break;
1429 case 0x32: handle_101232(regs); break;
1430 case 0x33: handle_101233(regs); break;
1431 case 0x34: handle_101234(regs); break;
1432 case 0x35: handle_101235(regs); break;
1433 case 0x36: handle_101236(regs); break;
1434 default: handle_1012XX(regs); break;
1435 }
1436
1437 // XXX - cirrus has 1280, 1281, 1282, 1285, 129a, 12a0, 12a1, 12a2, 12ae
1438}
1439
1440
1441static void
1442handle_1013(struct bregs *regs)
1443{
1444 // XXX - inline
1445 biosfn_write_string(regs->al, regs->bh, regs->bl, regs->cx
Kevin O'Connor99e08b72009-05-17 00:07:31 -04001446 , regs->dh, regs->dl, regs->es, (void*)(regs->bp + 0));
Kevin O'Connor1f2c3072009-05-06 23:35:59 -04001447}
1448
1449
1450static void
1451handle_101a00(struct bregs *regs)
1452{
1453 // XXX - inline
1454 biosfn_read_display_code(regs);
1455}
1456
1457static void
1458handle_101a01(struct bregs *regs)
1459{
1460 // XXX - inline
1461 biosfn_set_display_code(regs);
1462}
1463
1464static void
1465handle_101aXX(struct bregs *regs)
1466{
1467 debug_stub(regs);
1468}
1469
1470static void
1471handle_101a(struct bregs *regs)
1472{
1473 switch (regs->al) {
1474 case 0x00: handle_101a00(regs); break;
1475 case 0x01: handle_101a01(regs); break;
1476 default: handle_101aXX(regs); break;
1477 }
1478}
1479
1480
1481static void
1482handle_101b(struct bregs *regs)
1483{
1484 // XXX - inline
1485 biosfn_read_state_info(regs->bx, regs->es, regs->di);
1486 regs->al = 0x1B;
1487}
1488
1489
1490static void
1491handle_101c00(struct bregs *regs)
1492{
1493 // XXX - inline
1494 regs->bx = biosfn_read_video_state_size(regs->cx);
1495}
1496
1497static void
1498handle_101c01(struct bregs *regs)
1499{
1500 // XXX - inline
1501 biosfn_save_video_state(regs->cx, regs->es, regs->bx);
1502}
1503
1504static void
1505handle_101c02(struct bregs *regs)
1506{
1507 // XXX - inline
1508 biosfn_restore_video_state(regs->cx, regs->es, regs->bx);
1509}
1510
1511static void
1512handle_101cXX(struct bregs *regs)
1513{
1514 debug_stub(regs);
1515}
1516
1517static void
1518handle_101c(struct bregs *regs)
1519{
1520 switch (regs->al) {
1521 case 0x00: handle_101c00(regs); break;
1522 case 0x01: handle_101c01(regs); break;
1523 case 0x02: handle_101c02(regs); break;
1524 default: handle_101cXX(regs); break;
1525 }
1526}
1527
1528
1529static void
1530handle_104f00(struct bregs *regs)
1531{
1532 // XXX - vbe_biosfn_return_controller_information(&AX,ES,DI);
1533 // XXX - OR cirrus_vesa_00h
1534}
1535
1536static void
1537handle_104f01(struct bregs *regs)
1538{
1539 // XXX - vbe_biosfn_return_mode_information(&AX,CX,ES,DI);
1540 // XXX - OR cirrus_vesa_01h
1541}
1542
1543static void
1544handle_104f02(struct bregs *regs)
1545{
1546 // XXX - vbe_biosfn_set_mode(&AX,BX,ES,DI);
1547 // XXX - OR cirrus_vesa_02h
1548}
1549
1550static void
1551handle_104f03(struct bregs *regs)
1552{
1553 // XXX - vbe_biosfn_return_current_mode
1554 // XXX - OR cirrus_vesa_03h
1555}
1556
1557static void
1558handle_104f04(struct bregs *regs)
1559{
1560 // XXX - vbe_biosfn_save_restore_state(&AX, CX, DX, ES, &BX);
1561}
1562
1563static void
1564handle_104f05(struct bregs *regs)
1565{
1566 // XXX - vbe_biosfn_display_window_control
1567 // XXX - OR cirrus_vesa_05h
1568}
1569
1570static void
1571handle_104f06(struct bregs *regs)
1572{
1573 // XXX - vbe_biosfn_set_get_logical_scan_line_length
1574 // XXX - OR cirrus_vesa_06h
1575}
1576
1577static void
1578handle_104f07(struct bregs *regs)
1579{
1580 // XXX - vbe_biosfn_set_get_display_start
1581 // XXX - OR cirrus_vesa_07h
1582}
1583
1584static void
1585handle_104f08(struct bregs *regs)
1586{
1587 // XXX - vbe_biosfn_set_get_dac_palette_format
1588}
1589
1590static void
1591handle_104f0a(struct bregs *regs)
1592{
1593 // XXX - vbe_biosfn_return_protected_mode_interface
1594}
1595
1596static void
1597handle_104fXX(struct bregs *regs)
1598{
1599 debug_stub(regs);
1600 regs->ax = 0x0100;
1601}
1602
1603static void
1604handle_104f(struct bregs *regs)
1605{
Kevin O'Connor99e08b72009-05-17 00:07:31 -04001606 if (! CONFIG_VBE || !vbe_has_vbe_display()) {
Kevin O'Connor1f2c3072009-05-06 23:35:59 -04001607 handle_104fXX(regs);
1608 return;
1609 }
1610
Kevin O'Connor1f2c3072009-05-06 23:35:59 -04001611 switch (regs->al) {
1612 case 0x00: handle_104f00(regs); break;
1613 case 0x01: handle_104f01(regs); break;
1614 case 0x02: handle_104f02(regs); break;
1615 case 0x03: handle_104f03(regs); break;
1616 case 0x04: handle_104f04(regs); break;
1617 case 0x05: handle_104f05(regs); break;
1618 case 0x06: handle_104f06(regs); break;
1619 case 0x07: handle_104f07(regs); break;
1620 case 0x08: handle_104f08(regs); break;
1621 case 0x0a: handle_104f0a(regs); break;
1622 default: handle_104fXX(regs); break;
1623 }
1624}
1625
1626
1627static void
1628handle_10XX(struct bregs *regs)
1629{
1630 debug_stub(regs);
1631}
1632
1633// INT 10h Video Support Service Entry Point
1634void VISIBLE16
1635handle_10(struct bregs *regs)
1636{
1637 debug_enter(regs, DEBUG_VGA_10);
1638 switch (regs->ah) {
1639 case 0x00: handle_1000(regs); break;
1640 case 0x01: handle_1001(regs); break;
1641 case 0x02: handle_1002(regs); break;
1642 case 0x03: handle_1003(regs); break;
1643 case 0x04: handle_1004(regs); break;
1644 case 0x05: handle_1005(regs); break;
1645 case 0x06: handle_1006(regs); break;
1646 case 0x07: handle_1007(regs); break;
1647 case 0x08: handle_1008(regs); break;
1648 case 0x09: handle_1009(regs); break;
1649 case 0x0a: handle_100a(regs); break;
1650 case 0x0b: handle_100b(regs); break;
1651 case 0x0c: handle_100c(regs); break;
1652 case 0x0d: handle_100d(regs); break;
1653 case 0x0e: handle_100e(regs); break;
1654 case 0x0f: handle_100f(regs); break;
1655 case 0x10: handle_1010(regs); break;
1656 case 0x11: handle_1011(regs); break;
1657 case 0x12: handle_1012(regs); break;
1658 case 0x13: handle_1013(regs); break;
1659 case 0x1a: handle_101a(regs); break;
1660 case 0x1b: handle_101b(regs); break;
1661 case 0x1c: handle_101c(regs); break;
1662 case 0x4f: handle_104f(regs); break;
1663 default: handle_10XX(regs); break;
1664 }
1665}
1666
1667
1668/****************************************************************
1669 * VGA post
1670 ****************************************************************/
1671
1672static void
1673init_bios_area()
1674{
1675 // init detected hardware BIOS Area
1676 // set 80x25 color (not clear from RBIL but usual)
1677 u16 eqf = GET_BDA(equipment_list_flags);
1678 SET_BDA(equipment_list_flags, (eqf & 0xffcf) | 0x20);
1679
1680 // Just for the first int10 find its children
1681
1682 // the default char height
1683 SET_BDA(char_height, 0x10);
1684
1685 // Clear the screen
1686 SET_BDA(video_ctl, 0x60);
1687
1688 // Set the basic screen we have
1689 SET_BDA(video_switches, 0xf9);
1690
1691 // Set the basic modeset options
1692 SET_BDA(modeset_ctl, 0x51);
1693
1694 // Set the default MSR
1695 SET_BDA(video_msr, 0x09);
1696}
1697
Kevin O'Connor1f2c3072009-05-06 23:35:59 -04001698void VISIBLE16
1699vga_post(struct bregs *regs)
1700{
1701 debug_enter(regs, DEBUG_VGA_POST);
1702
1703 init_vga_card();
1704
1705 init_bios_area();
1706
Kevin O'Connor21079f42009-05-16 21:30:10 -04001707 if (CONFIG_VBE)
1708 vbe_init();
Kevin O'Connor1f2c3072009-05-06 23:35:59 -04001709
1710 extern void entry_10(void);
Kevin O'Connord113a992009-05-16 21:05:02 -04001711 SET_IVT(0x10, get_global_seg(), (u32)entry_10);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -04001712
1713 if (CONFIG_CIRRUS)
1714 cirrus_init();
1715
1716 // XXX - clear screen and display info
1717
1718 // XXX: fill it
1719 SET_VGA(video_save_pointer_table[0], (u32)video_param_table);
Kevin O'Connord113a992009-05-16 21:05:02 -04001720 SET_VGA(video_save_pointer_table[1], get_global_seg());
Kevin O'Connor1f2c3072009-05-06 23:35:59 -04001721
1722 // Fixup checksum
1723 extern u8 _rom_header_size, _rom_header_checksum;
1724 SET_VGA(_rom_header_checksum, 0);
Kevin O'Connord113a992009-05-16 21:05:02 -04001725 u8 sum = -checksum_far(get_global_seg(), 0, _rom_header_size * 512);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -04001726 SET_VGA(_rom_header_checksum, sum);
1727}