blob: 9628f790d7525ff512352584987205f92cca0ddb [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// * introduce "struct vregs", or add ebp to struct bregs.
11// * Integrate vga_modes/pallete?/line_to_vpti/dac_regs/video_param_table
12// * define structs for save/restore state
13// * review correctness of converted asm by comparing with RBIL
14// * eliminate unimplemented() calls
15// * eliminate DEBUG defs
16// * more syntax cleanups
17// * refactor redundant code into sub-functions
18// * See if there is a method to the in/out stuff that can be encapsulated.
19// * remove "biosfn" prefixes
20// * don't hardcode 0xc000
21// * add defs for 0xa000/0xb800
22// * verify all funcs static
23//
24// * separate code into separate files
25// * extract hw code from bios interfaces
26//
27// * convert vbe/clext code
28
29#include "bregs.h" // struct bregs
30#include "biosvar.h" // GET_BDA
31#include "util.h" // memset
32#include "vgatables.h" // vga_modes
33
34// XXX
35#define CONFIG_VBE 0
36#define CONFIG_CIRRUS 0
37
38// XXX
39#define DEBUG_VGA_POST 1
40#define DEBUG_VGA_10 3
41
42#define SET_VGA(var, val) SET_FARVAR(0xc000, (var), (val))
43
44
45// ===================================================================
46//
47// Video Utils
48//
49// ===================================================================
50
51// -------------------------------------------------------------------
52static u8
53find_vga_entry(u8 mode)
54{
55 u8 i;
56 for (i = 0; i <= MODE_MAX; i++)
57 if (GET_GLOBAL(vga_modes[i].svgamode) == mode)
58 return i;
59 return 0xFF;
60}
61
62inline void
63call16_vgaint(u32 eax, u32 ebx)
64{
65 asm volatile(
66 "int $0x10\n"
67 "cli\n"
68 "cld"
69 :
70 : "a"(eax), "b"(ebx)
71 : "cc", "memory");
72}
73
74// XXX
75inline void
76memcpy16_far(u16 d_seg, void *d_far, u16 s_seg, const void *s_far, size_t len)
77{
78 memcpy_far(d_seg, d_far, s_seg, s_far, len);
79}
80
81
82// ===================================================================
83//
84// BIOS functions
85//
86// ===================================================================
87
88// -------------------------------------------------------------------
89static void
90biosfn_perform_gray_scale_summing(u16 start, u16 count)
91{
92 u8 r, g, b;
93 u16 i;
94 u16 index;
95
96 inb(VGAREG_ACTL_RESET);
97 outb(0x00, VGAREG_ACTL_ADDRESS);
98
99 for (index = 0; index < count; index++) {
100 // set read address and switch to read mode
101 outb(start, VGAREG_DAC_READ_ADDRESS);
102 // get 6-bit wide RGB data values
103 r = inb(VGAREG_DAC_DATA);
104 g = inb(VGAREG_DAC_DATA);
105 b = inb(VGAREG_DAC_DATA);
106
107 // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue )
108 i = ((77 * r + 151 * g + 28 * b) + 0x80) >> 8;
109
110 if (i > 0x3f)
111 i = 0x3f;
112
113 // set write address and switch to write mode
114 outb(start, VGAREG_DAC_WRITE_ADDRESS);
115 // write new intensity value
116 outb(i & 0xff, VGAREG_DAC_DATA);
117 outb(i & 0xff, VGAREG_DAC_DATA);
118 outb(i & 0xff, VGAREG_DAC_DATA);
119 start++;
120 }
121 inb(VGAREG_ACTL_RESET);
122 outb(0x20, VGAREG_ACTL_ADDRESS);
123}
124
125// -------------------------------------------------------------------
126static void
127biosfn_set_cursor_shape(u8 CH, u8 CL)
128{
129 u16 cheight, curs, crtc_addr;
130 u8 modeset_ctl;
131
132 CH &= 0x3f;
133 CL &= 0x1f;
134
135 curs = (CH << 8) + CL;
136 SET_BDA(cursor_type, curs);
137
138 modeset_ctl = GET_BDA(modeset_ctl);
139 cheight = GET_BDA(char_height);
140 if ((modeset_ctl & 0x01) && (cheight > 8) && (CL < 8) && (CH < 0x20)) {
141 if (CL != (CH + 1)) {
142 CH = ((CH + 1) * cheight / 8) - 1;
143 } else {
144 CH = ((CL + 1) * cheight / 8) - 2;
145 }
146 CL = ((CL + 1) * cheight / 8) - 1;
147 }
148 // CTRC regs 0x0a and 0x0b
149 crtc_addr = GET_BDA(crtc_address);
150 outb(0x0a, crtc_addr);
151 outb(CH, crtc_addr + 1);
152 outb(0x0b, crtc_addr);
153 outb(CL, crtc_addr + 1);
154}
155
156// -------------------------------------------------------------------
157static void
158biosfn_set_cursor_pos(u8 page, u16 cursor)
159{
160 u8 xcurs, ycurs, current;
161 u16 nbcols, nbrows, address, crtc_addr;
162
163 // Should not happen...
164 if (page > 7)
165 return;
166
167 // Bios cursor pos
168 SET_BDA(cursor_pos[page], cursor);
169
170 // Set the hardware cursor
171 current = GET_BDA(video_page);
172 if (page == current) {
173 // Get the dimensions
174 nbcols = GET_BDA(video_cols);
175 nbrows = GET_BDA(video_rows) + 1;
176
177 xcurs = cursor & 0x00ff;
178 ycurs = (cursor & 0xff00) >> 8;
179
180 // Calculate the address knowing nbcols nbrows and page num
181 address =
182 SCREEN_IO_START(nbcols, nbrows, page) + xcurs + ycurs * nbcols;
183
184 // CRTC regs 0x0e and 0x0f
185 crtc_addr = GET_BDA(crtc_address);
186 outb(0x0e, crtc_addr);
187 outb((address & 0xff00) >> 8, crtc_addr + 1);
188 outb(0x0f, crtc_addr);
189 outb(address & 0x00ff, crtc_addr + 1);
190 }
191}
192
193// -------------------------------------------------------------------
194static void
195biosfn_get_cursor_pos(u8 page, u16 *shape, u16 *pos)
196{
197 // Default
198 *shape = 0;
199 *pos = 0;
200 if (page > 7)
201 return;
202
203 // FIXME should handle VGA 14/16 lines
204 *shape = GET_BDA(cursor_type);
205 *pos = GET_BDA(cursor_pos[page]);
206}
207
208// -------------------------------------------------------------------
209static void
210biosfn_set_active_page(u8 page)
211{
212 u16 cursor, dummy, crtc_addr;
213 u16 nbcols, nbrows, address;
214 u8 mode, line;
215
216 if (page > 7)
217 return;
218
219 // Get the mode
220 mode = GET_BDA(video_mode);
221 line = find_vga_entry(mode);
222 if (line == 0xFF)
223 return;
224
225 // Get pos curs pos for the right page
226 biosfn_get_cursor_pos(page, &dummy, &cursor);
227
228 if (GET_GLOBAL(vga_modes[line].class) == TEXT) {
229 // Get the dimensions
230 nbcols = GET_BDA(video_cols);
231 nbrows = GET_BDA(video_rows) + 1;
232
233 // Calculate the address knowing nbcols nbrows and page num
234 address = SCREEN_MEM_START(nbcols, nbrows, page);
235 SET_BDA(video_pagestart, address);
236
237 // Start address
238 address = SCREEN_IO_START(nbcols, nbrows, page);
239 } else {
240 address = page * GET_GLOBAL(video_param_table[GET_GLOBAL(line_to_vpti[line])].slength);
241 }
242
243 // CRTC regs 0x0c and 0x0d
244 crtc_addr = GET_BDA(crtc_address);
245 outb(0x0c, crtc_addr);
246 outb((address & 0xff00) >> 8, crtc_addr + 1);
247 outb(0x0d, crtc_addr);
248 outb(address & 0x00ff, crtc_addr + 1);
249
250 // And change the BIOS page
251 SET_BDA(video_page, page);
252
Kevin O'Connora12c2152009-05-13 22:06:16 -0400253 dprintf(1, "Set active page %02x address %04x\n", page, address);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400254
255 // Display the cursor, now the page is active
256 biosfn_set_cursor_pos(page, cursor);
257}
258
259static void
260biosfn_set_video_mode(u8 mode)
261{ // mode: Bit 7 is 1 if no clear screen
262 // Should we clear the screen ?
263 u8 noclearmem = mode & 0x80;
264 u8 line, mmask, *palette, vpti;
265 u16 i, twidth, theightm1, cheight;
266 u8 modeset_ctl, video_ctl, vga_switches;
267
268 if (CONFIG_CIRRUS)
269 cirrus_set_video_mode(mode);
270
271#ifdef VBE
272 if (vbe_has_vbe_display())
273 dispi_set_enable(VBE_DISPI_DISABLED);
274#endif
275
276 // The real mode
277 mode = mode & 0x7f;
278
279 // find the entry in the video modes
280 line = find_vga_entry(mode);
281
Kevin O'Connora12c2152009-05-13 22:06:16 -0400282 dprintf(1, "mode search %02x found line %02x\n", mode, line);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400283
284 if (line == 0xFF)
285 return;
286
287 vpti = GET_GLOBAL(line_to_vpti[line]);
288 twidth = GET_GLOBAL(video_param_table[vpti].twidth);
289 theightm1 = GET_GLOBAL(video_param_table[vpti].theightm1);
290 cheight = GET_GLOBAL(video_param_table[vpti].cheight);
291
292 // Read the bios vga control
293 video_ctl = GET_BDA(video_ctl);
294
295 // Read the bios vga switches
296 vga_switches = GET_BDA(video_switches);
297
298 // Read the bios mode set control
299 modeset_ctl = GET_BDA(modeset_ctl);
300
301 // Then we know the number of lines
302// FIXME
303
304 // if palette loading (bit 3 of modeset ctl = 0)
305 if ((modeset_ctl & 0x08) == 0) { // Set the PEL mask
306 outb(GET_GLOBAL(vga_modes[line].pelmask), VGAREG_PEL_MASK);
307
308 // Set the whole dac always, from 0
309 outb(0x00, VGAREG_DAC_WRITE_ADDRESS);
310
311 // From which palette
312 switch (GET_GLOBAL(vga_modes[line].dacmodel)) {
313 default:
314 case 0:
315 palette = palette0;
316 break;
317 case 1:
318 palette = palette1;
319 break;
320 case 2:
321 palette = palette2;
322 break;
323 case 3:
324 palette = palette3;
325 break;
326 }
327 // Always 256*3 values
328 for (i = 0; i < 0x0100; i++) {
329 if (i <= GET_GLOBAL(dac_regs[GET_GLOBAL(vga_modes[line].dacmodel)])) {
330 outb(GET_GLOBAL(palette[(i * 3) + 0]), VGAREG_DAC_DATA);
331 outb(GET_GLOBAL(palette[(i * 3) + 1]), VGAREG_DAC_DATA);
332 outb(GET_GLOBAL(palette[(i * 3) + 2]), VGAREG_DAC_DATA);
333 } else {
334 outb(0, VGAREG_DAC_DATA);
335 outb(0, VGAREG_DAC_DATA);
336 outb(0, VGAREG_DAC_DATA);
337 }
338 }
339 if ((modeset_ctl & 0x02) == 0x02)
340 biosfn_perform_gray_scale_summing(0x00, 0x100);
341 }
342 // Reset Attribute Ctl flip-flop
343 inb(VGAREG_ACTL_RESET);
344
345 // Set Attribute Ctl
346 for (i = 0; i <= 0x13; i++) {
347 outb(i, VGAREG_ACTL_ADDRESS);
348 outb(GET_GLOBAL(video_param_table[vpti].actl_regs[i])
349 , VGAREG_ACTL_WRITE_DATA);
350 }
351 outb(0x14, VGAREG_ACTL_ADDRESS);
352 outb(0x00, VGAREG_ACTL_WRITE_DATA);
353
354 // Set Sequencer Ctl
355 outb(0, VGAREG_SEQU_ADDRESS);
356 outb(0x03, VGAREG_SEQU_DATA);
357 for (i = 1; i <= 4; i++) {
358 outb(i, VGAREG_SEQU_ADDRESS);
359 outb(GET_GLOBAL(video_param_table[vpti].sequ_regs[i - 1])
360 , VGAREG_SEQU_DATA);
361 }
362
363 // Set Grafx Ctl
364 for (i = 0; i <= 8; i++) {
365 outb(i, VGAREG_GRDC_ADDRESS);
366 outb(GET_GLOBAL(video_param_table[vpti].grdc_regs[i])
367 , VGAREG_GRDC_DATA);
368 }
369
370 // Set CRTC address VGA or MDA
371 u16 crtc_addr = VGAREG_VGA_CRTC_ADDRESS;
372 if (GET_GLOBAL(vga_modes[line].memmodel) == MTEXT)
373 crtc_addr = VGAREG_MDA_CRTC_ADDRESS;
374
375 // Disable CRTC write protection
376 outw(0x0011, crtc_addr);
377 // Set CRTC regs
378 for (i = 0; i <= 0x18; i++) {
379 outb(i, crtc_addr);
380 outb(GET_GLOBAL(video_param_table[vpti].crtc_regs[i]), crtc_addr + 1);
381 }
382
383 // Set the misc register
384 outb(GET_GLOBAL(video_param_table[vpti].miscreg), VGAREG_WRITE_MISC_OUTPUT);
385
386 // Enable video
387 outb(0x20, VGAREG_ACTL_ADDRESS);
388 inb(VGAREG_ACTL_RESET);
389
390 if (noclearmem == 0x00) {
391 if (GET_GLOBAL(vga_modes[line].class) == TEXT) {
392 memset16_far(GET_GLOBAL(vga_modes[line].sstart)
393 , 0, 0x0720, 0x4000); // 32k
394 } else {
395 if (mode < 0x0d) {
396 memset16_far(GET_GLOBAL(vga_modes[line].sstart)
397 , 0, 0x0000, 0x4000); // 32k
398 } else {
399 outb(0x02, VGAREG_SEQU_ADDRESS);
400 mmask = inb(VGAREG_SEQU_DATA);
401 outb(0x0f, VGAREG_SEQU_DATA); // all planes
402 memset16_far(GET_GLOBAL(vga_modes[line].sstart)
403 , 0, 0x0000, 0x8000); // 64k
404 outb(mmask, VGAREG_SEQU_DATA);
405 }
406 }
407 }
408 // Set the BIOS mem
409 SET_BDA(video_mode, mode);
410 SET_BDA(video_cols, twidth);
411 SET_BDA(video_pagesize, GET_GLOBAL(video_param_table[vpti].slength));
412 SET_BDA(crtc_address, crtc_addr);
413 SET_BDA(video_rows, theightm1);
414 SET_BDA(char_height, cheight);
415 SET_BDA(video_ctl, (0x60 | noclearmem));
416 SET_BDA(video_switches, 0xF9);
417 SET_BDA(modeset_ctl, GET_BDA(modeset_ctl) & 0x7f);
418
419 // FIXME We nearly have the good tables. to be reworked
420 SET_BDA(dcc_index, 0x08); // 8 is VGA should be ok for now
421 SET_BDA(video_savetable_ptr, (u32)video_save_pointer_table);
422 SET_BDA(video_savetable_seg, 0xc000);
423
424 // FIXME
425 SET_BDA(video_msr, 0x00); // Unavailable on vanilla vga, but...
426 SET_BDA(video_pal, 0x00); // Unavailable on vanilla vga, but...
427
428 // Set cursor shape
429 if (GET_GLOBAL(vga_modes[line].class) == TEXT)
430 biosfn_set_cursor_shape(0x06, 0x07);
431 // Set cursor pos for page 0..7
432 for (i = 0; i < 8; i++)
433 biosfn_set_cursor_pos(i, 0x0000);
434
435 // Set active page 0
436 biosfn_set_active_page(0x00);
437
438 // Write the fonts in memory
439 if (GET_GLOBAL(vga_modes[line].class) == TEXT) {
440 call16_vgaint(0x1104, 0);
441 call16_vgaint(0x1103, 0);
442 }
443 // Set the ints 0x1F and 0x43
444 SET_IVT(0x1f, 0xC000, (u32)&vgafont8[128 * 8]);
445
446 switch (cheight) {
447 case 8:
448 SET_IVT(0x43, 0xC000, (u32)vgafont8);
449 break;
450 case 14:
451 SET_IVT(0x43, 0xC000, (u32)vgafont14);
452 break;
453 case 16:
454 SET_IVT(0x43, 0xC000, (u32)vgafont16);
455 break;
456 }
457}
458
459// -------------------------------------------------------------------
460static void
461vgamem_copy_pl4(u8 xstart, u8 ysrc, u8 ydest, u8 cols, u8 nbcols,
462 u8 cheight)
463{
464 u16 src = ysrc * cheight * nbcols + xstart;
465 u16 dest = ydest * cheight * nbcols + xstart;
466 outw(0x0105, VGAREG_GRDC_ADDRESS);
467 u8 i;
468 for (i = 0; i < cheight; i++)
469 memcpy_far(0xa000, (void*)(dest + i * nbcols)
470 , 0xa000, (void*)(src + i * nbcols), cols);
471 outw(0x0005, VGAREG_GRDC_ADDRESS);
472}
473
474// -------------------------------------------------------------------
475static void
476vgamem_fill_pl4(u8 xstart, u8 ystart, u8 cols, u8 nbcols, u8 cheight,
477 u8 attr)
478{
479 u16 dest = ystart * cheight * nbcols + xstart;
480 outw(0x0205, VGAREG_GRDC_ADDRESS);
481 u8 i;
482 for (i = 0; i < cheight; i++)
483 memset_far(0xa000, (void*)(dest + i * nbcols), attr, cols);
484 outw(0x0005, VGAREG_GRDC_ADDRESS);
485}
486
487// -------------------------------------------------------------------
488static void
489vgamem_copy_cga(u8 xstart, u8 ysrc, u8 ydest, u8 cols, u8 nbcols,
490 u8 cheight)
491{
492 u16 src = ((ysrc * cheight * nbcols) >> 1) + xstart;
493 u16 dest = ((ydest * cheight * nbcols) >> 1) + xstart;
494 u8 i;
495 for (i = 0; i < cheight; i++)
496 if (i & 1)
497 memcpy_far(0xb800, (void*)(0x2000 + dest + (i >> 1) * nbcols)
498 , 0xb800, (void*)(0x2000 + src + (i >> 1) * nbcols)
499 , cols);
500 else
501 memcpy_far(0xb800, (void*)(dest + (i >> 1) * nbcols)
502 , 0xb800, (void*)(src + (i >> 1) * nbcols), cols);
503}
504
505// -------------------------------------------------------------------
506static void
507vgamem_fill_cga(u8 xstart, u8 ystart, u8 cols, u8 nbcols, u8 cheight,
508 u8 attr)
509{
510 u16 dest = ((ystart * cheight * nbcols) >> 1) + xstart;
511 u8 i;
512 for (i = 0; i < cheight; i++)
513 if (i & 1)
514 memset_far(0xb800, (void*)(0x2000 + dest + (i >> 1) * nbcols)
515 , attr, cols);
516 else
517 memset_far(0xb800, (void*)(dest + (i >> 1) * nbcols), attr, cols);
518}
519
520// -------------------------------------------------------------------
521static void
522biosfn_scroll(u8 nblines, u8 attr, u8 rul, u8 cul, u8 rlr, u8 clr, u8 page,
523 u8 dir)
524{
525 // page == 0xFF if current
526
527 u8 mode, line, cheight, bpp, cols;
528 u16 nbcols, nbrows, i;
529
530 if (rul > rlr)
531 return;
532 if (cul > clr)
533 return;
534
535 // Get the mode
536 mode = GET_BDA(video_mode);
537 line = find_vga_entry(mode);
538 if (line == 0xFF)
539 return;
540
541 // Get the dimensions
542 nbrows = GET_BDA(video_rows) + 1;
543 nbcols = GET_BDA(video_cols);
544
545 // Get the current page
546 if (page == 0xFF)
547 page = GET_BDA(video_page);
548
549 if (rlr >= nbrows)
550 rlr = nbrows - 1;
551 if (clr >= nbcols)
552 clr = nbcols - 1;
553 if (nblines > nbrows)
554 nblines = 0;
555 cols = clr - cul + 1;
556
557 if (GET_GLOBAL(vga_modes[line].class) == TEXT) {
558 // Compute the address
559 void *address = (void*)(SCREEN_MEM_START(nbcols, nbrows, page));
Kevin O'Connora12c2152009-05-13 22:06:16 -0400560 dprintf(1, "Scroll, address %p (%d %d %02x)\n"
561 , address, nbrows, nbcols, page);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400562
563 if (nblines == 0 && rul == 0 && cul == 0 && rlr == nbrows - 1
564 && clr == nbcols - 1) {
565 memset16_far(GET_GLOBAL(vga_modes[line].sstart), address
566 , (u16)attr * 0x100 + ' ', nbrows * nbcols);
567 } else { // if Scroll up
568 if (dir == SCROLL_UP) {
569 for (i = rul; i <= rlr; i++) {
570 if ((i + nblines > rlr) || (nblines == 0))
571 memset16_far(GET_GLOBAL(vga_modes[line].sstart)
572 , address + (i * nbcols + cul) * 2
573 , (u16)attr * 0x100 + ' ', cols);
574 else
575 memcpy16_far(GET_GLOBAL(vga_modes[line].sstart)
576 , address + (i * nbcols + cul) * 2
577 , GET_GLOBAL(vga_modes[line].sstart)
578 , (void*)(((i + nblines) * nbcols + cul) * 2)
579 , cols);
580 }
581 } else {
582 for (i = rlr; i >= rul; i--) {
583 if ((i < rul + nblines) || (nblines == 0))
584 memset16_far(GET_GLOBAL(vga_modes[line].sstart)
585 , address + (i * nbcols + cul) * 2
586 , (u16)attr * 0x100 + ' ', cols);
587 else
588 memcpy16_far(GET_GLOBAL(vga_modes[line].sstart)
589 , address + (i * nbcols + cul) * 2
590 , GET_GLOBAL(vga_modes[line].sstart)
591 , (void*)(((i - nblines) * nbcols + cul) * 2)
592 , cols);
593 if (i > rlr)
594 break;
595 }
596 }
597 }
598 } else {
599 // FIXME gfx mode not complete
600 cheight = GET_GLOBAL(video_param_table[GET_GLOBAL(line_to_vpti[line])].cheight);
601 switch (GET_GLOBAL(vga_modes[line].memmodel)) {
602 case PLANAR4:
603 case PLANAR1:
604 if (nblines == 0 && rul == 0 && cul == 0 && rlr == nbrows - 1
605 && clr == nbcols - 1) {
606 outw(0x0205, VGAREG_GRDC_ADDRESS);
607 memset_far(GET_GLOBAL(vga_modes[line].sstart), 0, attr,
608 nbrows * nbcols * cheight);
609 outw(0x0005, VGAREG_GRDC_ADDRESS);
610 } else { // if Scroll up
611 if (dir == SCROLL_UP) {
612 for (i = rul; i <= rlr; i++) {
613 if ((i + nblines > rlr) || (nblines == 0))
614 vgamem_fill_pl4(cul, i, cols, nbcols, cheight,
615 attr);
616 else
617 vgamem_copy_pl4(cul, i + nblines, i, cols,
618 nbcols, cheight);
619 }
620 } else {
621 for (i = rlr; i >= rul; i--) {
622 if ((i < rul + nblines) || (nblines == 0))
623 vgamem_fill_pl4(cul, i, cols, nbcols, cheight,
624 attr);
625 else
626 vgamem_copy_pl4(cul, i, i - nblines, cols,
627 nbcols, cheight);
628 if (i > rlr)
629 break;
630 }
631 }
632 }
633 break;
634 case CGA:
635 bpp = GET_GLOBAL(vga_modes[line].pixbits);
636 if (nblines == 0 && rul == 0 && cul == 0 && rlr == nbrows - 1
637 && clr == nbcols - 1) {
638 memset_far(GET_GLOBAL(vga_modes[line].sstart), 0, attr,
639 nbrows * nbcols * cheight * bpp);
640 } else {
641 if (bpp == 2) {
642 cul <<= 1;
643 cols <<= 1;
644 nbcols <<= 1;
645 }
646 // if Scroll up
647 if (dir == SCROLL_UP) {
648 for (i = rul; i <= rlr; i++) {
649 if ((i + nblines > rlr) || (nblines == 0))
650 vgamem_fill_cga(cul, i, cols, nbcols, cheight,
651 attr);
652 else
653 vgamem_copy_cga(cul, i + nblines, i, cols,
654 nbcols, cheight);
655 }
656 } else {
657 for (i = rlr; i >= rul; i--) {
658 if ((i < rul + nblines) || (nblines == 0))
659 vgamem_fill_cga(cul, i, cols, nbcols, cheight,
660 attr);
661 else
662 vgamem_copy_cga(cul, i, i - nblines, cols,
663 nbcols, cheight);
664 if (i > rlr)
665 break;
666 }
667 }
668 }
669 break;
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400670 default:
Kevin O'Connora12c2152009-05-13 22:06:16 -0400671 dprintf(1, "Scroll in graphics mode\n");
672#ifdef DEBUG
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400673 unimplemented();
674#endif
675 }
676 }
677}
678
679// -------------------------------------------------------------------
680static void
681biosfn_read_char_attr(u8 page, u16 *car)
682{
683 u8 xcurs, ycurs, mode, line;
684 u16 nbcols, nbrows;
685 u16 cursor, dummy;
686
687 // Get the mode
688 mode = GET_BDA(video_mode);
689 line = find_vga_entry(mode);
690 if (line == 0xFF)
691 return;
692
693 // Get the cursor pos for the page
694 biosfn_get_cursor_pos(page, &dummy, &cursor);
695 xcurs = cursor & 0x00ff;
696 ycurs = (cursor & 0xff00) >> 8;
697
698 // Get the dimensions
699 nbrows = GET_BDA(video_rows) + 1;
700 nbcols = GET_BDA(video_cols);
701
702 if (GET_GLOBAL(vga_modes[line].class) == TEXT) {
703 // Compute the address
704 u16 *address = (void*)(SCREEN_MEM_START(nbcols, nbrows, page)
705 + (xcurs + ycurs * nbcols) * 2);
706
707 *car = GET_FARVAR(GET_GLOBAL(vga_modes[line].sstart), *address);
708 } else {
709 // FIXME gfx mode
710#ifdef DEBUG
711 unimplemented();
712#endif
713 }
714}
715
716// -------------------------------------------------------------------
717static void
718write_gfx_char_pl4(u8 car, u8 attr, u8 xcurs, u8 ycurs, u8 nbcols,
719 u8 cheight)
720{
721 u8 i, j, mask;
722 u8 *fdata;
723 u16 addr, src;
724
725 switch (cheight) {
726 case 14:
727 fdata = vgafont14;
728 break;
729 case 16:
730 fdata = vgafont16;
731 break;
732 default:
733 fdata = vgafont8;
734 }
735 addr = xcurs + ycurs * cheight * nbcols;
736 src = car * cheight;
737 outw(0x0f02, VGAREG_SEQU_ADDRESS);
738 outw(0x0205, VGAREG_GRDC_ADDRESS);
739 if (attr & 0x80)
740 outw(0x1803, VGAREG_GRDC_ADDRESS);
741 else
742 outw(0x0003, VGAREG_GRDC_ADDRESS);
743 for (i = 0; i < cheight; i++) {
744 u8 *dest = (void*)(addr + i * nbcols);
745 for (j = 0; j < 8; j++) {
746 mask = 0x80 >> j;
747 outw((mask << 8) | 0x08, VGAREG_GRDC_ADDRESS);
748 GET_FARVAR(0xa000, *dest);
749 if (GET_GLOBAL(fdata[src + i]) & mask)
750 SET_FARVAR(0xa000, *dest, attr & 0x0f);
751 else
752 SET_FARVAR(0xa000, *dest, 0x00);
753 }
754 }
755 outw(0xff08, VGAREG_GRDC_ADDRESS);
756 outw(0x0005, VGAREG_GRDC_ADDRESS);
757 outw(0x0003, VGAREG_GRDC_ADDRESS);
758}
759
760// -------------------------------------------------------------------
761static void
762write_gfx_char_cga(u8 car, u8 attr, u8 xcurs, u8 ycurs, u8 nbcols, u8 bpp)
763{
764 u8 *fdata = vgafont8;
765 u16 addr = (xcurs * bpp) + ycurs * 320;
766 u16 src = car * 8;
767 u8 i;
768 for (i = 0; i < 8; i++) {
769 u8 *dest = (void*)(addr + (i >> 1) * 80);
770 if (i & 1)
771 dest += 0x2000;
772 u8 mask = 0x80;
773 if (bpp == 1) {
774 u8 data = 0;
775 if (attr & 0x80)
776 data = GET_FARVAR(0xb800, *dest);
777 u8 j;
778 for (j = 0; j < 8; j++) {
779 if (GET_GLOBAL(fdata[src + i]) & mask) {
780 if (attr & 0x80)
781 data ^= (attr & 0x01) << (7 - j);
782 else
783 data |= (attr & 0x01) << (7 - j);
784 }
785 mask >>= 1;
786 }
787 SET_FARVAR(0xb800, *dest, data);
788 } else {
789 while (mask > 0) {
790 u8 data = 0;
791 if (attr & 0x80)
792 data = GET_FARVAR(0xb800, *dest);
793 u8 j;
794 for (j = 0; j < 4; j++) {
795 if (GET_GLOBAL(fdata[src + i]) & mask) {
796 if (attr & 0x80)
797 data ^= (attr & 0x03) << ((3 - j) * 2);
798 else
799 data |= (attr & 0x03) << ((3 - j) * 2);
800 }
801 mask >>= 1;
802 }
803 SET_FARVAR(0xb800, *dest, data);
804 dest += 1;
805 }
806 }
807 }
808}
809
810// -------------------------------------------------------------------
811static void
812write_gfx_char_lin(u8 car, u8 attr, u8 xcurs, u8 ycurs, u8 nbcols)
813{
814 u8 *fdata = vgafont8;
815 u16 addr = xcurs * 8 + ycurs * nbcols * 64;
816 u16 src = car * 8;
817 u8 i;
818 for (i = 0; i < 8; i++) {
819 u8 *dest = (void*)(addr + i * nbcols * 8);
820 u8 mask = 0x80;
821 u8 j;
822 for (j = 0; j < 8; j++) {
823 u8 data = 0x00;
824 if (GET_GLOBAL(fdata[src + i]) & mask)
825 data = attr;
826 SET_FARVAR(0xa000, dest[j], data);
827 mask >>= 1;
828 }
829 }
830}
831
832// -------------------------------------------------------------------
833static void
834biosfn_write_char_attr(u8 car, u8 page, u8 attr, u16 count)
835{
836 u8 cheight, xcurs, ycurs, mode, line, bpp;
837 u16 nbcols, nbrows;
838 u16 cursor, dummy;
839
840 // Get the mode
841 mode = GET_BDA(video_mode);
842 line = find_vga_entry(mode);
843 if (line == 0xFF)
844 return;
845
846 // Get the cursor pos for the page
847 biosfn_get_cursor_pos(page, &dummy, &cursor);
848 xcurs = cursor & 0x00ff;
849 ycurs = (cursor & 0xff00) >> 8;
850
851 // Get the dimensions
852 nbrows = GET_BDA(video_rows) + 1;
853 nbcols = GET_BDA(video_cols);
854
855 if (GET_GLOBAL(vga_modes[line].class) == TEXT) {
856 // Compute the address
857 void *address = (void*)(SCREEN_MEM_START(nbcols, nbrows, page)
858 + (xcurs + ycurs * nbcols) * 2);
859
860 dummy = ((u16)attr << 8) + car;
861 memset16_far(GET_GLOBAL(vga_modes[line].sstart), address, dummy, count);
862 } else {
863 // FIXME gfx mode not complete
864 cheight = GET_GLOBAL(video_param_table[GET_GLOBAL(line_to_vpti[line])].cheight);
865 bpp = GET_GLOBAL(vga_modes[line].pixbits);
866 while ((count-- > 0) && (xcurs < nbcols)) {
867 switch (GET_GLOBAL(vga_modes[line].memmodel)) {
868 case PLANAR4:
869 case PLANAR1:
870 write_gfx_char_pl4(car, attr, xcurs, ycurs, nbcols,
871 cheight);
872 break;
873 case CGA:
874 write_gfx_char_cga(car, attr, xcurs, ycurs, nbcols, bpp);
875 break;
876 case LINEAR8:
877 write_gfx_char_lin(car, attr, xcurs, ycurs, nbcols);
878 break;
879#ifdef DEBUG
880 default:
881 unimplemented();
882#endif
883 }
884 xcurs++;
885 }
886 }
887}
888
889// -------------------------------------------------------------------
890static void
891biosfn_write_char_only(u8 car, u8 page, u8 attr, u16 count)
892{
893 u8 cheight, xcurs, ycurs, mode, line, bpp;
894 u16 nbcols, nbrows;
895 u16 cursor, dummy;
896
897 // Get the mode
898 mode = GET_BDA(video_mode);
899 line = find_vga_entry(mode);
900 if (line == 0xFF)
901 return;
902
903 // Get the cursor pos for the page
904 biosfn_get_cursor_pos(page, &dummy, &cursor);
905 xcurs = cursor & 0x00ff;
906 ycurs = (cursor & 0xff00) >> 8;
907
908 // Get the dimensions
909 nbrows = GET_BDA(video_rows) + 1;
910 nbcols = GET_BDA(video_cols);
911
912 if (GET_GLOBAL(vga_modes[line].class) == TEXT) {
913 // Compute the address
914 u8 *address = (void*)(SCREEN_MEM_START(nbcols, nbrows, page)
915 + (xcurs + ycurs * nbcols) * 2);
916 while (count-- > 0) {
917 SET_FARVAR(GET_GLOBAL(vga_modes[line].sstart), *address, car);
918 address += 2;
919 }
920 } else {
921 // FIXME gfx mode not complete
922 cheight = GET_GLOBAL(video_param_table[GET_GLOBAL(line_to_vpti[line])].cheight);
923 bpp = GET_GLOBAL(vga_modes[line].pixbits);
924 while ((count-- > 0) && (xcurs < nbcols)) {
925 switch (GET_GLOBAL(vga_modes[line].memmodel)) {
926 case PLANAR4:
927 case PLANAR1:
928 write_gfx_char_pl4(car, attr, xcurs, ycurs, nbcols,
929 cheight);
930 break;
931 case CGA:
932 write_gfx_char_cga(car, attr, xcurs, ycurs, nbcols, bpp);
933 break;
934 case LINEAR8:
935 write_gfx_char_lin(car, attr, xcurs, ycurs, nbcols);
936 break;
937#ifdef DEBUG
938 default:
939 unimplemented();
940#endif
941 }
942 xcurs++;
943 }
944 }
945}
946
947
948
949// -------------------------------------------------------------------
950static void
951biosfn_set_border_color(struct bregs *regs)
952{
953 inb(VGAREG_ACTL_RESET);
954 outb(0x00, VGAREG_ACTL_ADDRESS);
955 u8 al = regs->bl & 0x0f;
956 if (al & 0x08)
957 al += 0x08;
Kevin O'Connord9fc0a02009-05-07 22:00:25 -0400958 outb(al, VGAREG_ACTL_WRITE_DATA);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400959 u8 bl = regs->bl & 0x10;
960
961 int i;
962 for (i = 1; i < 4; i++) {
963 outb(i, VGAREG_ACTL_ADDRESS);
964
965 al = inb(VGAREG_ACTL_READ_DATA);
966 al &= 0xef;
967 al |= bl;
Kevin O'Connord9fc0a02009-05-07 22:00:25 -0400968 outb(al, VGAREG_ACTL_WRITE_DATA);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400969 }
970 outb(0x20, VGAREG_ACTL_ADDRESS);
971}
972
973static void
974biosfn_set_palette(struct bregs *regs)
975{
976 inb(VGAREG_ACTL_RESET);
977 u8 bl = regs->bl & 0x01;
978 int i;
979 for (i = 1; i < 4; i++) {
980 outb(i, VGAREG_ACTL_ADDRESS);
981
982 u8 al = inb(VGAREG_ACTL_READ_DATA);
983 al &= 0xfe;
984 al |= bl;
Kevin O'Connord9fc0a02009-05-07 22:00:25 -0400985 outb(al, VGAREG_ACTL_WRITE_DATA);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -0400986 }
987 outb(0x20, VGAREG_ACTL_ADDRESS);
988}
989
990// -------------------------------------------------------------------
991static void
992biosfn_write_pixel(u8 BH, u8 AL, u16 CX, u16 DX)
993{
994 u8 mask, attr, data;
995
996 // Get the mode
997 u8 mode = GET_BDA(video_mode);
998 u8 line = find_vga_entry(mode);
999 if (line == 0xFF)
1000 return;
1001 if (GET_GLOBAL(vga_modes[line].class) == TEXT)
1002 return;
1003
1004 u8 *addr;
1005 switch (GET_GLOBAL(vga_modes[line].memmodel)) {
1006 case PLANAR4:
1007 case PLANAR1:
1008 addr = (void*)(CX / 8 + DX * GET_BDA(video_cols));
1009 mask = 0x80 >> (CX & 0x07);
1010 outw((mask << 8) | 0x08, VGAREG_GRDC_ADDRESS);
1011 outw(0x0205, VGAREG_GRDC_ADDRESS);
1012 data = GET_FARVAR(0xa000, *addr);
1013 if (AL & 0x80)
1014 outw(0x1803, VGAREG_GRDC_ADDRESS);
1015 SET_FARVAR(0xa000, *addr, AL);
1016 outw(0xff08, VGAREG_GRDC_ADDRESS);
1017 outw(0x0005, VGAREG_GRDC_ADDRESS);
1018 outw(0x0003, VGAREG_GRDC_ADDRESS);
1019 break;
1020 case CGA:
1021 if (GET_GLOBAL(vga_modes[line].pixbits) == 2)
1022 addr = (void*)((CX >> 2) + (DX >> 1) * 80);
1023 else
1024 addr = (void*)((CX >> 3) + (DX >> 1) * 80);
1025 if (DX & 1)
1026 addr += 0x2000;
1027 data = GET_FARVAR(0xb800, *addr);
1028 if (GET_GLOBAL(vga_modes[line].pixbits) == 2) {
1029 attr = (AL & 0x03) << ((3 - (CX & 0x03)) * 2);
1030 mask = 0x03 << ((3 - (CX & 0x03)) * 2);
1031 } else {
1032 attr = (AL & 0x01) << (7 - (CX & 0x07));
1033 mask = 0x01 << (7 - (CX & 0x07));
1034 }
1035 if (AL & 0x80) {
1036 data ^= attr;
1037 } else {
1038 data &= ~mask;
1039 data |= attr;
1040 }
1041 SET_FARVAR(0xb800, *addr, data);
1042 break;
1043 case LINEAR8:
1044 addr = (void*)(CX + DX * (GET_BDA(video_cols) * 8));
1045 SET_FARVAR(0xa000, *addr, AL);
1046 break;
1047#ifdef DEBUG
1048 default:
1049 unimplemented();
1050#endif
1051 }
1052}
1053
1054// -------------------------------------------------------------------
1055static void
1056biosfn_read_pixel(u8 BH, u16 CX, u16 DX, u16 *AX)
1057{
1058 u8 mode, line, mask, attr, data, i;
1059
1060 // Get the mode
1061 mode = GET_BDA(video_mode);
1062 line = find_vga_entry(mode);
1063 if (line == 0xFF)
1064 return;
1065 if (GET_GLOBAL(vga_modes[line].class) == TEXT)
1066 return;
1067
1068 u8 *addr;
1069 switch (GET_GLOBAL(vga_modes[line].memmodel)) {
1070 case PLANAR4:
1071 case PLANAR1:
1072 addr = (void*)(CX / 8 + DX * GET_BDA(video_cols));
1073 mask = 0x80 >> (CX & 0x07);
1074 attr = 0x00;
1075 for (i = 0; i < 4; i++) {
1076 outw((i << 8) | 0x04, VGAREG_GRDC_ADDRESS);
1077 data = GET_FARVAR(0xa000, *addr) & mask;
1078 if (data > 0)
1079 attr |= (0x01 << i);
1080 }
1081 break;
1082 case CGA:
1083 addr = (void*)((CX >> 2) + (DX >> 1) * 80);
1084 if (DX & 1)
1085 addr += 0x2000;
1086 data = GET_FARVAR(0xb800, *addr);
1087 if (GET_GLOBAL(vga_modes[line].pixbits) == 2)
1088 attr = (data >> ((3 - (CX & 0x03)) * 2)) & 0x03;
1089 else
1090 attr = (data >> (7 - (CX & 0x07))) & 0x01;
1091 break;
1092 case LINEAR8:
1093 addr = (void*)(CX + DX * (GET_BDA(video_cols) * 8));
1094 attr = GET_FARVAR(0xa000, *addr);
1095 break;
1096 default:
1097#ifdef DEBUG
1098 unimplemented();
1099#endif
1100 attr = 0;
1101 }
1102 *AX = (*AX & 0xff00) | attr;
1103}
1104
1105// -------------------------------------------------------------------
1106static void
1107biosfn_write_teletype(u8 car, u8 page, u8 attr, u8 flag)
1108{ // flag = WITH_ATTR / NO_ATTR
1109 u8 cheight, xcurs, ycurs, mode, line, bpp;
1110 u16 nbcols, nbrows;
1111 u16 cursor, dummy;
1112
1113 // special case if page is 0xff, use current page
1114 if (page == 0xff)
1115 page = GET_BDA(video_page);
1116
1117 // Get the mode
1118 mode = GET_BDA(video_mode);
1119 line = find_vga_entry(mode);
1120 if (line == 0xFF)
1121 return;
1122
1123 // Get the cursor pos for the page
1124 biosfn_get_cursor_pos(page, &dummy, &cursor);
1125 xcurs = cursor & 0x00ff;
1126 ycurs = (cursor & 0xff00) >> 8;
1127
1128 // Get the dimensions
1129 nbrows = GET_BDA(video_rows) + 1;
1130 nbcols = GET_BDA(video_cols);
1131
1132 switch (car) {
1133 case 7:
1134 //FIXME should beep
1135 break;
1136
1137 case 8:
1138 if (xcurs > 0)
1139 xcurs--;
1140 break;
1141
1142 case '\r':
1143 xcurs = 0;
1144 break;
1145
1146 case '\n':
1147 ycurs++;
1148 break;
1149
1150 case '\t':
1151 do {
1152 biosfn_write_teletype(' ', page, attr, flag);
1153 biosfn_get_cursor_pos(page, &dummy, &cursor);
1154 xcurs = cursor & 0x00ff;
1155 ycurs = (cursor & 0xff00) >> 8;
1156 } while (xcurs % 8 == 0);
1157 break;
1158
1159 default:
1160
1161 if (GET_GLOBAL(vga_modes[line].class) == TEXT) {
1162 // Compute the address
1163 u8 *address = (void*)(SCREEN_MEM_START(nbcols, nbrows, page)
1164 + (xcurs + ycurs * nbcols) * 2);
1165 // Write the char
1166 SET_FARVAR(GET_GLOBAL(vga_modes[line].sstart), address[0], car);
1167 if (flag == WITH_ATTR)
1168 SET_FARVAR(GET_GLOBAL(vga_modes[line].sstart), address[1], attr);
1169 } else {
1170 // FIXME gfx mode not complete
1171 cheight = GET_GLOBAL(video_param_table[GET_GLOBAL(line_to_vpti[line])].cheight);
1172 bpp = GET_GLOBAL(vga_modes[line].pixbits);
1173 switch (GET_GLOBAL(vga_modes[line].memmodel)) {
1174 case PLANAR4:
1175 case PLANAR1:
1176 write_gfx_char_pl4(car, attr, xcurs, ycurs, nbcols,
1177 cheight);
1178 break;
1179 case CGA:
1180 write_gfx_char_cga(car, attr, xcurs, ycurs, nbcols, bpp);
1181 break;
1182 case LINEAR8:
1183 write_gfx_char_lin(car, attr, xcurs, ycurs, nbcols);
1184 break;
1185#ifdef DEBUG
1186 default:
1187 unimplemented();
1188#endif
1189 }
1190 }
1191 xcurs++;
1192 }
1193
1194 // Do we need to wrap ?
1195 if (xcurs == nbcols) {
1196 xcurs = 0;
1197 ycurs++;
1198 }
1199 // Do we need to scroll ?
1200 if (ycurs == nbrows) {
1201 if (GET_GLOBAL(vga_modes[line].class) == TEXT)
1202 biosfn_scroll(0x01, 0x07, 0, 0, nbrows - 1, nbcols - 1, page,
1203 SCROLL_UP);
1204 else
1205 biosfn_scroll(0x01, 0x00, 0, 0, nbrows - 1, nbcols - 1, page,
1206 SCROLL_UP);
1207 ycurs -= 1;
1208 }
1209 // Set the cursor for the page
1210 cursor = ycurs;
1211 cursor <<= 8;
1212 cursor += xcurs;
1213 biosfn_set_cursor_pos(page, cursor);
1214}
1215
1216// -------------------------------------------------------------------
1217static void
1218biosfn_get_video_mode(struct bregs *regs)
1219{
1220 regs->bh = GET_BDA(video_page);
1221 regs->al = GET_BDA(video_mode) | (GET_BDA(video_ctl) & 0x80);
1222 regs->ah = GET_BDA(video_cols);
1223}
1224
1225// -------------------------------------------------------------------
1226static void
1227biosfn_set_overscan_border_color(struct bregs *regs)
1228{
1229 inb(VGAREG_ACTL_RESET);
1230 outb(0x11, VGAREG_ACTL_ADDRESS);
Kevin O'Connord9fc0a02009-05-07 22:00:25 -04001231 outb(regs->bh, VGAREG_ACTL_WRITE_DATA);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -04001232 outb(0x20, VGAREG_ACTL_ADDRESS);
1233}
1234
1235// -------------------------------------------------------------------
1236static void
1237biosfn_set_all_palette_reg(struct bregs *regs)
1238{
1239 inb(VGAREG_ACTL_RESET);
1240
1241 u8 *data = (u8*)(regs->dx + 0);
1242 int i;
1243 for (i = 0; i < 0x10; i++) {
1244 outb(i, VGAREG_ACTL_ADDRESS);
1245 u8 val = GET_FARVAR(regs->es, *data);
Kevin O'Connord9fc0a02009-05-07 22:00:25 -04001246 outb(val, VGAREG_ACTL_WRITE_DATA);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -04001247 data++;
1248 }
1249 outb(0x11, VGAREG_ACTL_ADDRESS);
Kevin O'Connord9fc0a02009-05-07 22:00:25 -04001250 outb(GET_FARVAR(regs->es, *data), VGAREG_ACTL_WRITE_DATA);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -04001251 outb(0x20, VGAREG_ACTL_ADDRESS);
1252}
1253
1254// -------------------------------------------------------------------
1255static void
1256biosfn_toggle_intensity(struct bregs *regs)
1257{
1258 inb(VGAREG_ACTL_RESET);
1259 outb(0x10, VGAREG_ACTL_ADDRESS);
1260 u8 val = (inb(VGAREG_ACTL_READ_DATA) & 0x7f) | ((regs->bl & 0x01) << 3);
Kevin O'Connord9fc0a02009-05-07 22:00:25 -04001261 outb(val, VGAREG_ACTL_WRITE_DATA);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -04001262 outb(0x20, VGAREG_ACTL_ADDRESS);
1263}
1264
1265// -------------------------------------------------------------------
1266void
1267biosfn_set_single_palette_reg(u8 reg, u8 val)
1268{
1269 inb(VGAREG_ACTL_RESET);
1270 outb(reg, VGAREG_ACTL_ADDRESS);
Kevin O'Connord9fc0a02009-05-07 22:00:25 -04001271 outb(val, VGAREG_ACTL_WRITE_DATA);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -04001272 outb(0x20, VGAREG_ACTL_ADDRESS);
1273}
1274
1275// -------------------------------------------------------------------
1276u8
1277biosfn_get_single_palette_reg(u8 reg)
1278{
1279 inb(VGAREG_ACTL_RESET);
1280 outb(reg, VGAREG_ACTL_ADDRESS);
1281 u8 v = inb(VGAREG_ACTL_READ_DATA);
1282 inb(VGAREG_ACTL_RESET);
1283 outb(0x20, VGAREG_ACTL_ADDRESS);
1284 return v;
1285}
1286
1287// -------------------------------------------------------------------
1288static void
1289biosfn_read_overscan_border_color(struct bregs *regs)
1290{
1291 inb(VGAREG_ACTL_RESET);
1292 outb(0x11, VGAREG_ACTL_ADDRESS);
1293 regs->bh = inb(VGAREG_ACTL_READ_DATA);
1294 inb(VGAREG_ACTL_RESET);
1295 outb(0x20, VGAREG_ACTL_ADDRESS);
1296}
1297
1298// -------------------------------------------------------------------
1299static void
1300biosfn_get_all_palette_reg(struct bregs *regs)
1301{
1302 u8 *data = (u8*)(regs->dx + 0);
1303 int i;
1304 for (i = 0; i < 0x10; i++) {
1305 inb(VGAREG_ACTL_RESET);
1306 outb(i, VGAREG_ACTL_ADDRESS);
1307 SET_FARVAR(regs->es, *data, inb(VGAREG_ACTL_READ_DATA));
1308 data++;
1309 }
1310 inb(VGAREG_ACTL_RESET);
1311 outb(0x11, VGAREG_ACTL_ADDRESS);
1312 SET_FARVAR(regs->es, *data, inb(VGAREG_ACTL_READ_DATA));
1313 inb(VGAREG_ACTL_RESET);
1314 outb(0x20, VGAREG_ACTL_ADDRESS);
1315}
1316
1317// -------------------------------------------------------------------
1318static void
1319biosfn_set_single_dac_reg(struct bregs *regs)
1320{
1321 outb(regs->bl, VGAREG_DAC_WRITE_ADDRESS);
1322 outb(regs->dh, VGAREG_DAC_DATA);
1323 outb(regs->ch, VGAREG_DAC_DATA);
1324 outb(regs->cl, VGAREG_DAC_DATA);
1325}
1326
1327// -------------------------------------------------------------------
1328static void
1329biosfn_set_all_dac_reg(struct bregs *regs)
1330{
1331 outb(regs->bl, VGAREG_DAC_WRITE_ADDRESS);
1332 u8 *data = (u8*)(regs->dx + 0);
1333 int count = regs->cx;
1334 while (count) {
1335 outb(GET_FARVAR(regs->es, *data), VGAREG_DAC_DATA);
1336 data++;
1337 outb(GET_FARVAR(regs->es, *data), VGAREG_DAC_DATA);
1338 data++;
1339 outb(GET_FARVAR(regs->es, *data), VGAREG_DAC_DATA);
1340 data++;
1341 count--;
1342 }
1343}
1344
1345// -------------------------------------------------------------------
1346static void
1347biosfn_select_video_dac_color_page(struct bregs *regs)
1348{
1349 inb(VGAREG_ACTL_RESET);
1350 outb(0x10, VGAREG_ACTL_ADDRESS);
1351 u8 val = inb(VGAREG_ACTL_READ_DATA);
1352 if (!(regs->bl & 0x01)) {
1353 val = (val & 0x7f) | (regs->bh << 7);
Kevin O'Connord9fc0a02009-05-07 22:00:25 -04001354 outb(val, VGAREG_ACTL_WRITE_DATA);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -04001355 outb(0x20, VGAREG_ACTL_ADDRESS);
1356 return;
1357 }
1358 inb(VGAREG_ACTL_RESET);
1359 outb(0x14, VGAREG_ACTL_ADDRESS);
1360 u8 bh = regs->bh;
1361 if (!(val & 0x80))
1362 bh <<= 2;
1363 bh &= 0x0f;
Kevin O'Connord9fc0a02009-05-07 22:00:25 -04001364 outb(bh, VGAREG_ACTL_WRITE_DATA);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -04001365 outb(0x20, VGAREG_ACTL_ADDRESS);
1366}
1367
1368// -------------------------------------------------------------------
1369static void
1370biosfn_read_single_dac_reg(struct bregs *regs)
1371{
1372 outb(regs->bl, VGAREG_DAC_READ_ADDRESS);
1373 regs->dh = inb(VGAREG_DAC_DATA);
1374 regs->ch = inb(VGAREG_DAC_DATA);
1375 regs->cl = inb(VGAREG_DAC_DATA);
1376}
1377
1378// -------------------------------------------------------------------
1379static void
1380biosfn_read_all_dac_reg(struct bregs *regs)
1381{
1382 outb(regs->bl, VGAREG_DAC_READ_ADDRESS);
1383 u8 *data = (u8*)(regs->dx + 0);
1384 int count = regs->cx;
1385 while (count) {
1386 SET_FARVAR(regs->es, *data, inb(VGAREG_DAC_DATA));
1387 data++;
1388 SET_FARVAR(regs->es, *data, inb(VGAREG_DAC_DATA));
1389 data++;
1390 SET_FARVAR(regs->es, *data, inb(VGAREG_DAC_DATA));
1391 data++;
1392 count--;
1393 }
1394}
1395
1396// -------------------------------------------------------------------
1397static void
1398biosfn_set_pel_mask(struct bregs *regs)
1399{
1400 outb(regs->bl, VGAREG_PEL_MASK);
1401}
1402
1403// -------------------------------------------------------------------
1404static void
1405biosfn_read_pel_mask(struct bregs *regs)
1406{
1407 regs->bl = inb(VGAREG_PEL_MASK);
1408}
1409
1410// -------------------------------------------------------------------
1411static void
1412biosfn_read_video_dac_state(struct bregs *regs)
1413{
1414 inb(VGAREG_ACTL_RESET);
1415 outb(0x10, VGAREG_ACTL_ADDRESS);
1416 u8 val1 = inb(VGAREG_ACTL_READ_DATA) >> 7;
1417
1418 inb(VGAREG_ACTL_RESET);
1419 outb(0x14, VGAREG_ACTL_ADDRESS);
1420 u8 val2 = inb(VGAREG_ACTL_READ_DATA) & 0x0f;
1421 if (!(val1 & 0x01))
1422 val2 >>= 2;
1423
1424 inb(VGAREG_ACTL_RESET);
1425 outb(0x20, VGAREG_ACTL_ADDRESS);
1426
1427 regs->bl = val1;
1428 regs->bh = val2;
1429}
1430
1431// -------------------------------------------------------------------
1432static void
1433get_font_access()
1434{
1435 outw(0x0100, VGAREG_SEQU_ADDRESS);
1436 outw(0x0402, VGAREG_SEQU_ADDRESS);
1437 outw(0x0704, VGAREG_SEQU_ADDRESS);
1438 outw(0x0300, VGAREG_SEQU_ADDRESS);
1439 outw(0x0204, VGAREG_GRDC_ADDRESS);
1440 outw(0x0005, VGAREG_GRDC_ADDRESS);
1441 outw(0x0406, VGAREG_GRDC_ADDRESS);
1442}
1443
1444static void
1445release_font_access()
1446{
1447 outw(0x0100, VGAREG_SEQU_ADDRESS);
1448 outw(0x0302, VGAREG_SEQU_ADDRESS);
1449 outw(0x0304, VGAREG_SEQU_ADDRESS);
1450 outw(0x0300, VGAREG_SEQU_ADDRESS);
1451 u16 v = inw(VGAREG_READ_MISC_OUTPUT);
1452 v = ((v & 0x01) << 10) | 0x0a06;
1453 outw(v, VGAREG_GRDC_ADDRESS);
1454 outw(0x0004, VGAREG_GRDC_ADDRESS);
1455 outw(0x1005, VGAREG_GRDC_ADDRESS);
1456}
1457
1458static void
1459set_scan_lines(u8 lines)
1460{
1461 u16 crtc_addr, cols, vde;
1462 u8 crtc_r9, ovl, rows;
1463
1464 crtc_addr = GET_BDA(crtc_address);
1465 outb(0x09, crtc_addr);
1466 crtc_r9 = inb(crtc_addr + 1);
1467 crtc_r9 = (crtc_r9 & 0xe0) | (lines - 1);
1468 outb(crtc_r9, crtc_addr + 1);
1469 if (lines == 8)
1470 biosfn_set_cursor_shape(0x06, 0x07);
1471 else
1472 biosfn_set_cursor_shape(lines - 4, lines - 3);
1473 SET_BDA(char_height, lines);
1474 outb(0x12, crtc_addr);
1475 vde = inb(crtc_addr + 1);
1476 outb(0x07, crtc_addr);
1477 ovl = inb(crtc_addr + 1);
1478 vde += (((ovl & 0x02) << 7) + ((ovl & 0x40) << 3) + 1);
1479 rows = vde / lines;
1480 SET_BDA(video_rows, rows - 1);
1481 cols = GET_BDA(video_cols);
1482 SET_BDA(video_pagesize, rows * cols * 2);
1483}
1484
1485static void
1486biosfn_load_text_user_pat(u8 AL, u16 ES, u16 BP, u16 CX, u16 DX, u8 BL,
1487 u8 BH)
1488{
1489 get_font_access();
1490 u16 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
1491 u16 i;
1492 for (i = 0; i < CX; i++) {
1493 void *src = (void*)(BP + i * BH);
1494 void *dest = (void*)(blockaddr + (DX + i) * 32);
1495 memcpy_far(0xA000, dest, ES, src, BH);
1496 }
1497 release_font_access();
1498 if (AL >= 0x10)
1499 set_scan_lines(BH);
1500}
1501
1502static void
1503biosfn_load_text_8_14_pat(u8 AL, u8 BL)
1504{
1505 get_font_access();
1506 u16 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
1507 u16 i;
1508 for (i = 0; i < 0x100; i++) {
1509 u16 src = i * 14;
1510 void *dest = (void*)(blockaddr + i * 32);
1511 memcpy_far(0xA000, dest, 0xC000, &vgafont14[src], 14);
1512 }
1513 release_font_access();
1514 if (AL >= 0x10)
1515 set_scan_lines(14);
1516}
1517
1518static void
1519biosfn_load_text_8_8_pat(u8 AL, u8 BL)
1520{
1521 get_font_access();
1522 u16 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
1523 u16 i;
1524 for (i = 0; i < 0x100; i++) {
1525 u16 src = i * 8;
1526 void *dest = (void*)(blockaddr + i * 32);
1527 memcpy_far(0xA000, dest, 0xC000, &vgafont8[src], 8);
1528 }
1529 release_font_access();
1530 if (AL >= 0x10)
1531 set_scan_lines(8);
1532}
1533
1534// -------------------------------------------------------------------
1535static void
1536biosfn_set_text_block_specifier(struct bregs *regs)
1537{
1538 outw((regs->bl << 8) | 0x03, VGAREG_SEQU_ADDRESS);
1539}
1540
1541// -------------------------------------------------------------------
1542static void
1543biosfn_load_text_8_16_pat(u8 AL, u8 BL)
1544{
1545 get_font_access();
1546 u16 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
1547 u16 i;
1548 for (i = 0; i < 0x100; i++) {
1549 u16 src = i * 16;
1550 void *dest = (void*)(blockaddr + i * 32);
1551 memcpy_far(0xA000, dest, 0xC000, &vgafont16[src], 16);
1552 }
1553 release_font_access();
1554 if (AL >= 0x10)
1555 set_scan_lines(16);
1556}
1557
1558// -------------------------------------------------------------------
1559static void
1560biosfn_get_font_info(u8 BH, u16 *ES, u16 *BP, u16 *CX, u16 *DX)
1561{
1562 switch (BH) {
1563 case 0x00: {
1564 u32 segoff = GET_IVT(0x1f).segoff;
1565 *ES = segoff >> 16;
1566 *BP = segoff;
1567 break;
1568 }
1569 case 0x01: {
1570 u32 segoff = GET_IVT(0x43).segoff;
1571 *ES = segoff >> 16;
1572 *BP = segoff;
1573 break;
1574 }
1575 case 0x02:
1576 *ES = 0xC000;
1577 *BP = (u32)vgafont14;
1578 break;
1579 case 0x03:
1580 *ES = 0xC000;
1581 *BP = (u32)vgafont8;
1582 break;
1583 case 0x04:
1584 *ES = 0xC000;
1585 *BP = (u32)vgafont8 + 128 * 8;
1586 break;
1587 case 0x05:
1588 *ES = 0xC000;
1589 *BP = (u32)vgafont14alt;
1590 break;
1591 case 0x06:
1592 *ES = 0xC000;
1593 *BP = (u32)vgafont16;
1594 break;
1595 case 0x07:
1596 *ES = 0xC000;
1597 *BP = (u32)vgafont16alt;
1598 break;
1599 default:
Kevin O'Connora12c2152009-05-13 22:06:16 -04001600 dprintf(1, "Get font info BH(%02x) was discarded\n", BH);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -04001601 return;
1602 }
1603 // Set byte/char of on screen font
1604 *CX = GET_BDA(char_height) & 0xff;
1605
1606 // Set Highest char row
1607 *DX = GET_BDA(video_rows);
1608}
1609
1610// -------------------------------------------------------------------
1611static void
1612biosfn_get_ega_info(struct bregs *regs)
1613{
1614 regs->cx = GET_BDA(video_switches) & 0x0f;
1615 regs->ax = GET_BDA(crtc_address);
1616 if (regs->ax == VGAREG_MDA_CRTC_ADDRESS)
1617 regs->bx = 0x0103;
1618 else
1619 regs->bx = 0x0003;
1620}
1621
1622// -------------------------------------------------------------------
1623static void
1624biosfn_select_vert_res(struct bregs *regs)
1625{
1626 u8 mctl = GET_BDA(modeset_ctl);
1627 u8 vswt = GET_BDA(video_switches);
1628
1629 switch (regs->al) {
1630 case 0x00:
1631 // 200 lines
1632 mctl = (mctl & ~0x10) | 0x80;
1633 vswt = (vswt & ~0x0f) | 0x08;
1634 break;
1635 case 0x01:
1636 // 350 lines
1637 mctl &= ~0x90;
1638 vswt = (vswt & ~0x0f) | 0x09;
1639 break;
1640 case 0x02:
1641 // 400 lines
1642 mctl = (mctl & ~0x80) | 0x10;
1643 vswt = (vswt & ~0x0f) | 0x09;
1644 break;
1645 default:
Kevin O'Connora12c2152009-05-13 22:06:16 -04001646 dprintf(1, "Select vert res (%02x) was discarded\n", regs->al);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -04001647 break;
1648 }
1649 SET_BDA(modeset_ctl, mctl);
1650 SET_BDA(video_switches, vswt);
1651 regs->ax = 0x1212;
1652}
1653
1654static void
1655biosfn_enable_default_palette_loading(struct bregs *regs)
1656{
1657 u8 v = (regs->al & 0x01) << 3;
1658 u8 mctl = GET_BDA(video_ctl) & ~0x08;
1659 SET_BDA(video_ctl, mctl | v);
1660 regs->ax = 0x1212;
1661}
1662
1663static void
1664biosfn_enable_video_addressing(struct bregs *regs)
1665{
1666 u8 v = ((regs->al << 1) & 0x02) ^ 0x02;
1667 u8 v2 = inb(VGAREG_READ_MISC_OUTPUT) & ~0x02;
1668 outb(v | v2, VGAREG_WRITE_MISC_OUTPUT);
1669 regs->ax = 0x1212;
1670}
1671
1672
1673static void
1674biosfn_enable_grayscale_summing(struct bregs *regs)
1675{
1676 u8 v = ((regs->al << 1) & 0x02) ^ 0x02;
1677 u8 v2 = GET_BDA(modeset_ctl) & ~0x02;
1678 SET_BDA(modeset_ctl, v | v2);
1679 regs->ax = 0x1212;
1680}
1681
1682static void
1683biosfn_enable_cursor_emulation(struct bregs *regs)
1684{
1685 u8 v = (regs->al & 0x01) ^ 0x01;
1686 u8 v2 = GET_BDA(modeset_ctl) & ~0x01;
1687 SET_BDA(modeset_ctl, v | v2);
1688 regs->ax = 0x1212;
1689}
1690
1691// -------------------------------------------------------------------
1692static void
1693biosfn_write_string(u8 flag, u8 page, u8 attr, u16 count, u8 row, u8 col,
1694 u16 seg, u8 *offset)
1695{
1696 u16 newcurs, oldcurs, dummy;
1697 u8 car;
1698
1699 // Read curs info for the page
1700 biosfn_get_cursor_pos(page, &dummy, &oldcurs);
1701
1702 // if row=0xff special case : use current cursor position
1703 if (row == 0xff) {
1704 col = oldcurs & 0x00ff;
1705 row = (oldcurs & 0xff00) >> 8;
1706 }
1707
1708 newcurs = row;
1709 newcurs <<= 8;
1710 newcurs += col;
1711 biosfn_set_cursor_pos(page, newcurs);
1712
1713 while (count-- != 0) {
1714 car = GET_FARVAR(seg, *offset);
1715 offset++;
1716 if ((flag & 0x02) != 0) {
1717 attr = GET_FARVAR(seg, *offset);
1718 offset++;
1719 }
1720
1721 biosfn_write_teletype(car, page, attr, WITH_ATTR);
1722 }
1723
1724 // Set back curs pos
1725 if ((flag & 0x01) == 0)
1726 biosfn_set_cursor_pos(page, oldcurs);
1727}
1728
1729// -------------------------------------------------------------------
1730static void
1731biosfn_read_display_code(struct bregs *regs)
1732{
1733 regs->bx = GET_BDA(dcc_index);
1734 regs->al = 0x1a;
1735}
1736
1737static void
1738biosfn_set_display_code(struct bregs *regs)
1739{
1740 SET_BDA(dcc_index, regs->bl);
Kevin O'Connora12c2152009-05-13 22:06:16 -04001741 dprintf(1, "Alternate Display code (%02x) was discarded\n", regs->bh);
Kevin O'Connor1f2c3072009-05-06 23:35:59 -04001742 regs->al = 0x1a;
1743}
1744
1745// -------------------------------------------------------------------
1746static void
1747biosfn_read_state_info(u16 BX, u16 ES, u16 DI)
1748{
1749 // Address of static functionality table
1750 SET_FARVAR(ES, *(u16*)(DI + 0x00), (u32)static_functionality);
1751 SET_FARVAR(ES, *(u16*)(DI + 0x02), 0xC000);
1752
1753 // Hard coded copy from BIOS area. Should it be cleaner ?
1754 memcpy_far(ES, (void*)(DI + 0x04), SEG_BDA, (void*)0x49, 30);
1755 memcpy_far(ES, (void*)(DI + 0x22), SEG_BDA, (void*)0x84, 3);
1756
1757 SET_FARVAR(ES, *(u8*)(DI + 0x25), GET_BDA(dcc_index));
1758 SET_FARVAR(ES, *(u8*)(DI + 0x26), 0);
1759 SET_FARVAR(ES, *(u8*)(DI + 0x27), 16);
1760 SET_FARVAR(ES, *(u8*)(DI + 0x28), 0);
1761 SET_FARVAR(ES, *(u8*)(DI + 0x29), 8);
1762 SET_FARVAR(ES, *(u8*)(DI + 0x2a), 2);
1763 SET_FARVAR(ES, *(u8*)(DI + 0x2b), 0);
1764 SET_FARVAR(ES, *(u8*)(DI + 0x2c), 0);
1765 SET_FARVAR(ES, *(u8*)(DI + 0x31), 3);
1766 SET_FARVAR(ES, *(u8*)(DI + 0x32), 0);
1767
1768 memset_far(ES, (void*)(DI + 0x33), 0, 13);
1769}
1770
1771// -------------------------------------------------------------------
1772// -------------------------------------------------------------------
1773static u16
1774biosfn_read_video_state_size(u16 CX)
1775{
1776 u16 size = 0;
1777 if (CX & 1)
1778 size += 0x46;
1779 if (CX & 2)
1780 size += (5 + 8 + 5) * 2 + 6;
1781 if (CX & 4)
1782 size += 3 + 256 * 3 + 1;
1783 return size;
1784}
1785
1786static u16
1787biosfn_save_video_state(u16 CX, u16 ES, u16 BX)
1788{
1789 u16 i, crtc_addr, ar_index;
1790
1791 crtc_addr = GET_BDA(crtc_address);
1792 if (CX & 1) {
1793 SET_FARVAR(ES, *(u8*)(BX+0), inb(VGAREG_SEQU_ADDRESS));
1794 BX++;
1795 SET_FARVAR(ES, *(u8*)(BX+0), inb(crtc_addr));
1796 BX++;
1797 SET_FARVAR(ES, *(u8*)(BX+0), inb(VGAREG_GRDC_ADDRESS));
1798 BX++;
1799 inb(VGAREG_ACTL_RESET);
1800 ar_index = inb(VGAREG_ACTL_ADDRESS);
1801 SET_FARVAR(ES, *(u8*)(BX+0), ar_index);
1802 BX++;
1803 SET_FARVAR(ES, *(u8*)(BX+0), inb(VGAREG_READ_FEATURE_CTL));
1804 BX++;
1805
1806 for (i = 1; i <= 4; i++) {
1807 outb(i, VGAREG_SEQU_ADDRESS);
1808 SET_FARVAR(ES, *(u8*)(BX+0), inb(VGAREG_SEQU_DATA));
1809 BX++;
1810 }
1811 outb(0, VGAREG_SEQU_ADDRESS);
1812 SET_FARVAR(ES, *(u8*)(BX+0), inb(VGAREG_SEQU_DATA));
1813 BX++;
1814
1815 for (i = 0; i <= 0x18; i++) {
1816 outb(i, crtc_addr);
1817 SET_FARVAR(ES, *(u8*)(BX+0), inb(crtc_addr + 1));
1818 BX++;
1819 }
1820
1821 for (i = 0; i <= 0x13; i++) {
1822 inb(VGAREG_ACTL_RESET);
1823 outb(i | (ar_index & 0x20), VGAREG_ACTL_ADDRESS);
1824 SET_FARVAR(ES, *(u8*)(BX+0), inb(VGAREG_ACTL_READ_DATA));
1825 BX++;
1826 }
1827 inb(VGAREG_ACTL_RESET);
1828
1829 for (i = 0; i <= 8; i++) {
1830 outb(i, VGAREG_GRDC_ADDRESS);
1831 SET_FARVAR(ES, *(u8*)(BX+0), inb(VGAREG_GRDC_DATA));
1832 BX++;
1833 }
1834
1835 SET_FARVAR(ES, *(u16*)(BX+0), crtc_addr);
1836 BX += 2;
1837
1838 /* XXX: read plane latches */
1839 SET_FARVAR(ES, *(u8*)(BX+0), 0);
1840 BX++;
1841 SET_FARVAR(ES, *(u8*)(BX+0), 0);
1842 BX++;
1843 SET_FARVAR(ES, *(u8*)(BX+0), 0);
1844 BX++;
1845 SET_FARVAR(ES, *(u8*)(BX+0), 0);
1846 BX++;
1847 }
1848 if (CX & 2) {
1849 SET_FARVAR(ES, *(u8*)(BX+0), GET_BDA(video_mode));
1850 BX++;
1851 SET_FARVAR(ES, *(u16*)(BX+0), GET_BDA(video_cols));
1852 BX += 2;
1853 SET_FARVAR(ES, *(u16*)(BX+0), GET_BDA(video_pagesize));
1854 BX += 2;
1855 SET_FARVAR(ES, *(u16*)(BX+0), GET_BDA(crtc_address));
1856 BX += 2;
1857 SET_FARVAR(ES, *(u8*)(BX+0), GET_BDA(video_rows));
1858 BX++;
1859 SET_FARVAR(ES, *(u16*)(BX+0), GET_BDA(char_height));
1860 BX += 2;
1861 SET_FARVAR(ES, *(u8*)(BX+0), GET_BDA(video_ctl));
1862 BX++;
1863 SET_FARVAR(ES, *(u8*)(BX+0), GET_BDA(video_switches));
1864 BX++;
1865 SET_FARVAR(ES, *(u8*)(BX+0), GET_BDA(modeset_ctl));
1866 BX++;
1867 SET_FARVAR(ES, *(u16*)(BX+0), GET_BDA(cursor_type));
1868 BX += 2;
1869 for (i = 0; i < 8; i++) {
1870 SET_FARVAR(ES, *(u16*)(BX+0), GET_BDA(cursor_pos[i]));
1871 BX += 2;
1872 }
1873 SET_FARVAR(ES, *(u16*)(BX+0), GET_BDA(video_pagestart));
1874 BX += 2;
1875 SET_FARVAR(ES, *(u8*)(BX+0), GET_BDA(video_page));
1876 BX++;
1877 /* current font */
1878 SET_FARVAR(ES, *(u16*)(BX+0), GET_FARVAR(0, *(u16*)(0x1f * 4)));
1879 BX += 2;
1880 SET_FARVAR(ES, *(u16*)(BX+0), GET_FARVAR(0, *(u16*)(0x1f * 4 + 2)));
1881 BX += 2;
1882 SET_FARVAR(ES, *(u16*)(BX+0), GET_FARVAR(0, *(u16*)(0x43 * 4)));
1883 BX += 2;
1884 SET_FARVAR(ES, *(u16*)(BX+0), GET_FARVAR(0, *(u16*)(0x43 * 4 + 2)));
1885 BX += 2;
1886 }
1887 if (CX & 4) {
1888 /* XXX: check this */
1889 SET_FARVAR(ES, *(u8*)(BX+0), inb(VGAREG_DAC_STATE));
1890 BX++; /* read/write mode dac */
1891 SET_FARVAR(ES, *(u8*)(BX+0), inb(VGAREG_DAC_WRITE_ADDRESS));
1892 BX++; /* pix address */
1893 SET_FARVAR(ES, *(u8*)(BX+0), inb(VGAREG_PEL_MASK));
1894 BX++;
1895 // Set the whole dac always, from 0
1896 outb(0x00, VGAREG_DAC_WRITE_ADDRESS);
1897 for (i = 0; i < 256 * 3; i++) {
1898 SET_FARVAR(ES, *(u8*)(BX+0), inb(VGAREG_DAC_DATA));
1899 BX++;
1900 }
1901 SET_FARVAR(ES, *(u8*)(BX+0), 0);
1902 BX++; /* color select register */
1903 }
1904 return BX;
1905}
1906
1907static u16
1908biosfn_restore_video_state(u16 CX, u16 ES, u16 BX)
1909{
1910 u16 i, crtc_addr, v, addr1, ar_index;
1911
1912 if (CX & 1) {
1913 // Reset Attribute Ctl flip-flop
1914 inb(VGAREG_ACTL_RESET);
1915
1916 crtc_addr = GET_FARVAR(ES, *(u16*)(BX + 0x40));
1917 addr1 = BX;
1918 BX += 5;
1919
1920 for (i = 1; i <= 4; i++) {
1921 outb(i, VGAREG_SEQU_ADDRESS);
1922 outb(GET_FARVAR(ES, *(u8*)(BX+0)), VGAREG_SEQU_DATA);
1923 BX++;
1924 }
1925 outb(0, VGAREG_SEQU_ADDRESS);
1926 outb(GET_FARVAR(ES, *(u8*)(BX+0)), VGAREG_SEQU_DATA);
1927 BX++;
1928
1929 // Disable CRTC write protection
1930 outw(0x0011, crtc_addr);
1931 // Set CRTC regs
1932 for (i = 0; i <= 0x18; i++) {
1933 if (i != 0x11) {
1934 outb(i, crtc_addr);
1935 outb(GET_FARVAR(ES, *(u8*)(BX+0)), crtc_addr + 1);
1936 }
1937 BX++;
1938 }
1939 // select crtc base address
1940 v = inb(VGAREG_READ_MISC_OUTPUT) & ~0x01;
Kevin O'Connord9fc0a02009-05-07 22:00:25 -04001941 if (crtc_addr == VGAREG_VGA_CRTC_ADDRESS)
Kevin O'Connor1f2c3072009-05-06 23:35:59 -04001942 v |= 0x01;
1943 outb(v, VGAREG_WRITE_MISC_OUTPUT);
1944
1945 // enable write protection if needed
1946 outb(0x11, crtc_addr);
1947 outb(GET_FARVAR(ES, *(u8*)(BX - 0x18 + 0x11)), crtc_addr + 1);
1948
1949 // Set Attribute Ctl
1950 ar_index = GET_FARVAR(ES, *(u8*)(addr1 + 0x03));
1951 inb(VGAREG_ACTL_RESET);
1952 for (i = 0; i <= 0x13; i++) {
1953 outb(i | (ar_index & 0x20), VGAREG_ACTL_ADDRESS);
1954 outb(GET_FARVAR(ES, *(u8*)(BX+0)), VGAREG_ACTL_WRITE_DATA);
1955 BX++;
1956 }
1957 outb(ar_index, VGAREG_ACTL_ADDRESS);
1958 inb(VGAREG_ACTL_RESET);
1959
1960 for (i = 0; i <= 8; i++) {
1961 outb(i, VGAREG_GRDC_ADDRESS);
1962 outb(GET_FARVAR(ES, *(u8*)(BX+0)), VGAREG_GRDC_DATA);
1963 BX++;
1964 }
1965 BX += 2; /* crtc_addr */
1966 BX += 4; /* plane latches */
1967
1968 outb(GET_FARVAR(ES, *(u8*)(addr1+0)), VGAREG_SEQU_ADDRESS);
1969 addr1++;
1970 outb(GET_FARVAR(ES, *(u8*)(addr1+0)), crtc_addr);
1971 addr1++;
1972 outb(GET_FARVAR(ES, *(u8*)(addr1+0)), VGAREG_GRDC_ADDRESS);
1973 addr1++;
1974 addr1++;
1975 outb(GET_FARVAR(ES, *(u8*)(addr1+0)), crtc_addr - 0x4 + 0xa);
1976 addr1++;
1977 }
1978 if (CX & 2) {
1979 SET_BDA(video_mode, GET_FARVAR(ES, *(u8*)(BX+0)));
1980 BX++;
1981 SET_BDA(video_cols, GET_FARVAR(ES, *(u16*)(BX+0)));
1982 BX += 2;
1983 SET_BDA(video_pagesize, GET_FARVAR(ES, *(u16*)(BX+0)));
1984 BX += 2;
1985 SET_BDA(crtc_address, GET_FARVAR(ES, *(u16*)(BX+0)));
1986 BX += 2;
1987 SET_BDA(video_rows, GET_FARVAR(ES, *(u8*)(BX+0)));
1988 BX++;
1989 SET_BDA(char_height, GET_FARVAR(ES, *(u16*)(BX+0)));
1990 BX += 2;
1991 SET_BDA(video_ctl, GET_FARVAR(ES, *(u8*)(BX+0)));
1992 BX++;
1993 SET_BDA(video_switches, GET_FARVAR(ES, *(u8*)(BX+0)));
1994 BX++;
1995 SET_BDA(modeset_ctl, GET_FARVAR(ES, *(u8*)(BX+0)));
1996 BX++;
1997 SET_BDA(cursor_type, GET_FARVAR(ES, *(u16*)(BX+0)));
1998 BX += 2;
1999 for (i = 0; i < 8; i++) {
2000 SET_BDA(cursor_pos[i], GET_FARVAR(ES, *(u16*)(BX+0)));
2001 BX += 2;
2002 }
2003 SET_BDA(video_pagestart, GET_FARVAR(ES, *(u16*)(BX+0)));
2004 BX += 2;
2005 SET_BDA(video_page, GET_FARVAR(ES, *(u8*)(BX+0)));
2006 BX++;
2007 /* current font */
2008 SET_IVT(0x1f, GET_FARVAR(ES, *(u16*)(BX+2)), GET_FARVAR(ES, *(u16*)(BX+0)));
2009 BX += 4;
2010 SET_IVT(0x43, GET_FARVAR(ES, *(u16*)(BX+2)), GET_FARVAR(ES, *(u16*)(BX+0)));
2011 BX += 4;
2012 }
2013 if (CX & 4) {
2014 BX++;
2015 v = GET_FARVAR(ES, *(u8*)(BX+0));
2016 BX++;
2017 outb(GET_FARVAR(ES, *(u8*)(BX+0)), VGAREG_PEL_MASK);
2018 BX++;
2019 // Set the whole dac always, from 0
2020 outb(0x00, VGAREG_DAC_WRITE_ADDRESS);
2021 for (i = 0; i < 256 * 3; i++) {
2022 outb(GET_FARVAR(ES, *(u8*)(BX+0)), VGAREG_DAC_DATA);
2023 BX++;
2024 }
2025 BX++;
2026 outb(v, VGAREG_DAC_WRITE_ADDRESS);
2027 }
2028 return BX;
2029}
2030
2031
2032/****************************************************************
2033 * VGA int 10 handler
2034 ****************************************************************/
2035
2036static void
2037handle_1000(struct bregs *regs)
2038{
2039 // XXX - inline
2040 biosfn_set_video_mode(regs->al);
2041 switch(regs->al & 0x7F) {
2042 case 6:
2043 regs->al = 0x3F;
2044 break;
2045 case 0:
2046 case 1:
2047 case 2:
2048 case 3:
2049 case 4:
2050 case 5:
2051 case 7:
2052 regs->al = 0x30;
2053 break;
2054 default:
2055 regs->al = 0x20;
2056 }
2057}
2058
2059static void
2060handle_1001(struct bregs *regs)
2061{
2062 biosfn_set_cursor_shape(regs->ch, regs->cl);
2063}
2064
2065static void
2066handle_1002(struct bregs *regs)
2067{
2068 biosfn_set_cursor_pos(regs->bh, regs->dx);
2069}
2070
2071static void
2072handle_1003(struct bregs *regs)
2073{
2074 biosfn_get_cursor_pos(regs->bh, &regs->cx, &regs->dx);
2075}
2076
2077// Read light pen pos (unimplemented)
2078static void
2079handle_1004(struct bregs *regs)
2080{
2081 debug_stub(regs);
2082 regs->ax = regs->bx = regs->cx = regs->dx = 0;
2083}
2084
2085static void
2086handle_1005(struct bregs *regs)
2087{
2088 biosfn_set_active_page(regs->al);
2089}
2090
2091static void
2092handle_1006(struct bregs *regs)
2093{
2094 biosfn_scroll(regs->al, regs->bh, regs->ch, regs->cl, regs->dh, regs->dl
2095 , 0xFF, SCROLL_UP);
2096}
2097
2098static void
2099handle_1007(struct bregs *regs)
2100{
2101 biosfn_scroll(regs->al, regs->bh, regs->ch, regs->cl, regs->dh, regs->dl
2102 , 0xFF, SCROLL_DOWN);
2103}
2104
2105static void
2106handle_1008(struct bregs *regs)
2107{
2108 // XXX - inline
2109 biosfn_read_char_attr(regs->bh, &regs->ax);
2110}
2111
2112static void
2113handle_1009(struct bregs *regs)
2114{
2115 // XXX - inline
2116 biosfn_write_char_attr(regs->al, regs->bh, regs->bl, regs->cx);
2117}
2118
2119static void
2120handle_100a(struct bregs *regs)
2121{
2122 // XXX - inline
2123 biosfn_write_char_only(regs->al, regs->bh, regs->bl, regs->cx);
2124}
2125
2126
2127static void
2128handle_100b00(struct bregs *regs)
2129{
2130 // XXX - inline
2131 biosfn_set_border_color(regs);
2132}
2133
2134static void
2135handle_100b01(struct bregs *regs)
2136{
2137 // XXX - inline
2138 biosfn_set_palette(regs);
2139}
2140
2141static void
2142handle_100bXX(struct bregs *regs)
2143{
2144 debug_stub(regs);
2145}
2146
2147static void
2148handle_100b(struct bregs *regs)
2149{
2150 switch (regs->bh) {
2151 case 0x00: handle_100b00(regs); break;
2152 case 0x01: handle_100b01(regs); break;
2153 default: handle_100bXX(regs); break;
2154 }
2155}
2156
2157
2158static void
2159handle_100c(struct bregs *regs)
2160{
2161 // XXX - inline
2162 biosfn_write_pixel(regs->bh, regs->al, regs->cx, regs->dx);
2163}
2164
2165static void
2166handle_100d(struct bregs *regs)
2167{
2168 // XXX - inline
2169 biosfn_read_pixel(regs->bh, regs->cx, regs->dx, &regs->ax);
2170}
2171
2172static void
2173handle_100e(struct bregs *regs)
2174{
2175 // Ralf Brown Interrupt list is WRONG on bh(page)
2176 // We do output only on the current page !
2177 biosfn_write_teletype(regs->al, 0xff, regs->bl, NO_ATTR);
2178}
2179
2180static void
2181handle_100f(struct bregs *regs)
2182{
2183 // XXX - inline
2184 biosfn_get_video_mode(regs);
2185}
2186
2187
2188static void
2189handle_101000(struct bregs *regs)
2190{
2191 if (regs->bl > 0x14)
2192 return;
2193 biosfn_set_single_palette_reg(regs->bl, regs->bh);
2194}
2195
2196static void
2197handle_101001(struct bregs *regs)
2198{
2199 // XXX - inline
2200 biosfn_set_overscan_border_color(regs);
2201}
2202
2203static void
2204handle_101002(struct bregs *regs)
2205{
2206 // XXX - inline
2207 biosfn_set_all_palette_reg(regs);
2208}
2209
2210static void
2211handle_101003(struct bregs *regs)
2212{
2213 // XXX - inline
2214 biosfn_toggle_intensity(regs);
2215}
2216
2217static void
2218handle_101007(struct bregs *regs)
2219{
2220 if (regs->bl > 0x14)
2221 return;
2222 regs->bh = biosfn_get_single_palette_reg(regs->bl);
2223}
2224
2225static void
2226handle_101008(struct bregs *regs)
2227{
2228 // XXX - inline
2229 biosfn_read_overscan_border_color(regs);
2230}
2231
2232static void
2233handle_101009(struct bregs *regs)
2234{
2235 // XXX - inline
2236 biosfn_get_all_palette_reg(regs);
2237}
2238
2239static void
2240handle_101010(struct bregs *regs)
2241{
2242 // XXX - inline
2243 biosfn_set_single_dac_reg(regs);
2244}
2245
2246static void
2247handle_101012(struct bregs *regs)
2248{
2249 // XXX - inline
2250 biosfn_set_all_dac_reg(regs);
2251}
2252
2253static void
2254handle_101013(struct bregs *regs)
2255{
2256 // XXX - inline
2257 biosfn_select_video_dac_color_page(regs);
2258}
2259
2260static void
2261handle_101015(struct bregs *regs)
2262{
2263 // XXX - inline
2264 biosfn_read_single_dac_reg(regs);
2265}
2266
2267static void
2268handle_101017(struct bregs *regs)
2269{
2270 // XXX - inline
2271 biosfn_read_all_dac_reg(regs);
2272}
2273
2274static void
2275handle_101018(struct bregs *regs)
2276{
2277 // XXX - inline
2278 biosfn_set_pel_mask(regs);
2279}
2280
2281static void
2282handle_101019(struct bregs *regs)
2283{
2284 // XXX - inline
2285 biosfn_read_pel_mask(regs);
2286}
2287
2288static void
2289handle_10101a(struct bregs *regs)
2290{
2291 // XXX - inline
2292 biosfn_read_video_dac_state(regs);
2293}
2294
2295static void
2296handle_10101b(struct bregs *regs)
2297{
2298 biosfn_perform_gray_scale_summing(regs->bx, regs->cx);
2299}
2300
2301static void
2302handle_1010XX(struct bregs *regs)
2303{
2304 debug_stub(regs);
2305}
2306
2307static void
2308handle_1010(struct bregs *regs)
2309{
2310 switch (regs->al) {
2311 case 0x00: handle_101000(regs); break;
2312 case 0x01: handle_101001(regs); break;
2313 case 0x02: handle_101002(regs); break;
2314 case 0x03: handle_101003(regs); break;
2315 case 0x07: handle_101007(regs); break;
2316 case 0x08: handle_101008(regs); break;
2317 case 0x09: handle_101009(regs); break;
2318 case 0x10: handle_101010(regs); break;
2319 case 0x12: handle_101012(regs); break;
2320 case 0x13: handle_101013(regs); break;
2321 case 0x15: handle_101015(regs); break;
2322 case 0x17: handle_101017(regs); break;
2323 case 0x18: handle_101018(regs); break;
2324 case 0x19: handle_101019(regs); break;
2325 case 0x1a: handle_10101a(regs); break;
2326 case 0x1b: handle_10101b(regs); break;
2327 default: handle_1010XX(regs); break;
2328 }
2329}
2330
2331
2332static void
2333handle_101100(struct bregs *regs)
2334{
2335 // XXX - inline
2336 biosfn_load_text_user_pat(regs->al, regs->es, 0 // XXX - regs->bp
2337 , regs->cx, regs->dx, regs->bl, regs->bh);
2338}
2339
2340static void
2341handle_101101(struct bregs *regs)
2342{
2343 // XXX - inline
2344 biosfn_load_text_8_14_pat(regs->al, regs->bl);
2345}
2346
2347static void
2348handle_101102(struct bregs *regs)
2349{
2350 // XXX - inline
2351 biosfn_load_text_8_8_pat(regs->al, regs->bl);
2352}
2353
2354static void
2355handle_101103(struct bregs *regs)
2356{
2357 // XXX - inline
2358 biosfn_set_text_block_specifier(regs);
2359}
2360
2361static void
2362handle_101104(struct bregs *regs)
2363{
2364 // XXX - inline
2365 biosfn_load_text_8_16_pat(regs->al, regs->bl);
2366}
2367
2368static void
2369handle_101110(struct bregs *regs)
2370{
2371 handle_101100(regs);
2372}
2373
2374static void
2375handle_101111(struct bregs *regs)
2376{
2377 handle_101101(regs);
2378}
2379
2380static void
2381handle_101112(struct bregs *regs)
2382{
2383 handle_101102(regs);
2384}
2385
2386static void
2387handle_101114(struct bregs *regs)
2388{
2389 handle_101104(regs);
2390}
2391
2392static void
2393handle_101130(struct bregs *regs)
2394{
2395 // XXX - inline
2396 biosfn_get_font_info(regs->bh, &regs->es, 0 // &regs->bp
2397 , &regs->cx, &regs->dx);
2398}
2399
2400static void
2401handle_1011XX(struct bregs *regs)
2402{
2403 debug_stub(regs);
2404}
2405
2406static void
2407handle_1011(struct bregs *regs)
2408{
2409 switch (regs->al) {
2410 case 0x00: handle_101100(regs); break;
2411 case 0x01: handle_101101(regs); break;
2412 case 0x02: handle_101102(regs); break;
2413 case 0x03: handle_101103(regs); break;
2414 case 0x04: handle_101104(regs); break;
2415 case 0x10: handle_101110(regs); break;
2416 case 0x11: handle_101111(regs); break;
2417 case 0x12: handle_101112(regs); break;
2418 case 0x14: handle_101114(regs); break;
2419 case 0x30: handle_101130(regs); break;
2420 default: handle_1011XX(regs); break;
2421 }
2422}
2423
2424
2425static void
2426handle_101210(struct bregs *regs)
2427{
2428 // XXX - inline
2429 biosfn_get_ega_info(regs);
2430}
2431
2432static void
2433handle_101230(struct bregs *regs)
2434{
2435 // XXX - inline
2436 biosfn_select_vert_res(regs);
2437}
2438
2439static void
2440handle_101231(struct bregs *regs)
2441{
2442 // XXX - inline
2443 biosfn_enable_default_palette_loading(regs);
2444}
2445
2446static void
2447handle_101232(struct bregs *regs)
2448{
2449 // XXX - inline
2450 biosfn_enable_video_addressing(regs);
2451}
2452
2453static void
2454handle_101233(struct bregs *regs)
2455{
2456 // XXX - inline
2457 biosfn_enable_grayscale_summing(regs);
2458}
2459
2460static void
2461handle_101234(struct bregs *regs)
2462{
2463 // XXX - inline
2464 biosfn_enable_cursor_emulation(regs);
2465}
2466
2467static void
2468handle_101235(struct bregs *regs)
2469{
2470 debug_stub(regs);
2471 regs->al = 0x12;
2472}
2473
2474static void
2475handle_101236(struct bregs *regs)
2476{
2477 debug_stub(regs);
2478 regs->al = 0x12;
2479}
2480
2481static void
2482handle_1012XX(struct bregs *regs)
2483{
2484 debug_stub(regs);
2485}
2486
2487static void
2488handle_1012(struct bregs *regs)
2489{
2490 switch (regs->bl) {
2491 case 0x10: handle_101210(regs); break;
2492 case 0x30: handle_101230(regs); break;
2493 case 0x31: handle_101231(regs); break;
2494 case 0x32: handle_101232(regs); break;
2495 case 0x33: handle_101233(regs); break;
2496 case 0x34: handle_101234(regs); break;
2497 case 0x35: handle_101235(regs); break;
2498 case 0x36: handle_101236(regs); break;
2499 default: handle_1012XX(regs); break;
2500 }
2501
2502 // XXX - cirrus has 1280, 1281, 1282, 1285, 129a, 12a0, 12a1, 12a2, 12ae
2503}
2504
2505
2506static void
2507handle_1013(struct bregs *regs)
2508{
2509 // XXX - inline
2510 biosfn_write_string(regs->al, regs->bh, regs->bl, regs->cx
2511 , regs->dh, regs->dl, regs->es, 0); // regs->bp);
2512}
2513
2514
2515static void
2516handle_101a00(struct bregs *regs)
2517{
2518 // XXX - inline
2519 biosfn_read_display_code(regs);
2520}
2521
2522static void
2523handle_101a01(struct bregs *regs)
2524{
2525 // XXX - inline
2526 biosfn_set_display_code(regs);
2527}
2528
2529static void
2530handle_101aXX(struct bregs *regs)
2531{
2532 debug_stub(regs);
2533}
2534
2535static void
2536handle_101a(struct bregs *regs)
2537{
2538 switch (regs->al) {
2539 case 0x00: handle_101a00(regs); break;
2540 case 0x01: handle_101a01(regs); break;
2541 default: handle_101aXX(regs); break;
2542 }
2543}
2544
2545
2546static void
2547handle_101b(struct bregs *regs)
2548{
2549 // XXX - inline
2550 biosfn_read_state_info(regs->bx, regs->es, regs->di);
2551 regs->al = 0x1B;
2552}
2553
2554
2555static void
2556handle_101c00(struct bregs *regs)
2557{
2558 // XXX - inline
2559 regs->bx = biosfn_read_video_state_size(regs->cx);
2560}
2561
2562static void
2563handle_101c01(struct bregs *regs)
2564{
2565 // XXX - inline
2566 biosfn_save_video_state(regs->cx, regs->es, regs->bx);
2567}
2568
2569static void
2570handle_101c02(struct bregs *regs)
2571{
2572 // XXX - inline
2573 biosfn_restore_video_state(regs->cx, regs->es, regs->bx);
2574}
2575
2576static void
2577handle_101cXX(struct bregs *regs)
2578{
2579 debug_stub(regs);
2580}
2581
2582static void
2583handle_101c(struct bregs *regs)
2584{
2585 switch (regs->al) {
2586 case 0x00: handle_101c00(regs); break;
2587 case 0x01: handle_101c01(regs); break;
2588 case 0x02: handle_101c02(regs); break;
2589 default: handle_101cXX(regs); break;
2590 }
2591}
2592
2593
2594static void
2595handle_104f00(struct bregs *regs)
2596{
2597 // XXX - vbe_biosfn_return_controller_information(&AX,ES,DI);
2598 // XXX - OR cirrus_vesa_00h
2599}
2600
2601static void
2602handle_104f01(struct bregs *regs)
2603{
2604 // XXX - vbe_biosfn_return_mode_information(&AX,CX,ES,DI);
2605 // XXX - OR cirrus_vesa_01h
2606}
2607
2608static void
2609handle_104f02(struct bregs *regs)
2610{
2611 // XXX - vbe_biosfn_set_mode(&AX,BX,ES,DI);
2612 // XXX - OR cirrus_vesa_02h
2613}
2614
2615static void
2616handle_104f03(struct bregs *regs)
2617{
2618 // XXX - vbe_biosfn_return_current_mode
2619 // XXX - OR cirrus_vesa_03h
2620}
2621
2622static void
2623handle_104f04(struct bregs *regs)
2624{
2625 // XXX - vbe_biosfn_save_restore_state(&AX, CX, DX, ES, &BX);
2626}
2627
2628static void
2629handle_104f05(struct bregs *regs)
2630{
2631 // XXX - vbe_biosfn_display_window_control
2632 // XXX - OR cirrus_vesa_05h
2633}
2634
2635static void
2636handle_104f06(struct bregs *regs)
2637{
2638 // XXX - vbe_biosfn_set_get_logical_scan_line_length
2639 // XXX - OR cirrus_vesa_06h
2640}
2641
2642static void
2643handle_104f07(struct bregs *regs)
2644{
2645 // XXX - vbe_biosfn_set_get_display_start
2646 // XXX - OR cirrus_vesa_07h
2647}
2648
2649static void
2650handle_104f08(struct bregs *regs)
2651{
2652 // XXX - vbe_biosfn_set_get_dac_palette_format
2653}