VirtualBox

source: vbox/trunk/src/VBox/Devices/Graphics/BIOS/vbe.c@ 67548

Last change on this file since 67548 was 67548, checked in by vboxsync, 8 years ago

VBIOS: Rewrote set/get scanline length function in C.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 23.5 KB
Line 
1// ============================================================================================
2//
3// Copyright (C) 2002 Jeroen Janssen
4//
5// This library is free software; you can redistribute it and/or
6// modify it under the terms of the GNU Lesser General Public
7// License as published by the Free Software Foundation; either
8// version 2 of the License, or (at your option) any later version.
9//
10// This library is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13// Lesser General Public License for more details.
14//
15// You should have received a copy of the GNU Lesser General Public
16// License along with this library; if not, write to the Free Software
17// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18//
19// ============================================================================================
20//
21// This VBE is part of the VGA Bios specific to the plex86/bochs Emulated VGA card.
22// You can NOT drive any physical vga card with it.
23//
24// ============================================================================================
25//
26// This VBE Bios is based on information taken from :
27// - VESA BIOS EXTENSION (VBE) Core Functions Standard Version 3.0 located at www.vesa.org
28//
29// ============================================================================================
30
31
32/*
33 * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
34 * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
35 * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
36 * a choice of LGPL license versions is made available with the language indicating
37 * that LGPLv2 or any later version may be used, or where a choice of which version
38 * of the LGPL is applied is otherwise unspecified.
39 */
40
41// Use VBE new dynamic mode list. Note that without this option, no
42// checks are currently done to make sure that modes fit into the
43// framebuffer!
44#define VBE_NEW_DYN_LIST
45
46#include <inttypes.h>
47#include <stddef.h>
48#include "vbe.h"
49#include "vgadefs.h"
50#include "inlines.h"
51
52// disable VESA/VBE2 check in vbe info
53//#define VBE2_NO_VESA_CHECK
54
55// use bytewise i/o (Longhorn beta issue, not in released Vista)
56#define VBE_BYTEWISE_IO
57
58#ifdef VBE_BYTEWISE_IO
59 extern void do_out_dx_ax();
60 #pragma aux do_out_dx_ax "*";
61 extern void out_w(uint16_t port, uint16_t value);
62 #pragma aux out_w = \
63 "call do_out_dx_ax" \
64 parm [dx] [ax] modify nomemory;
65 extern void do_in_ax_dx();
66 #pragma aux do_in_ax_dx "*";
67 extern uint16_t in_w(uint16_t port);
68 #pragma aux in_w = \
69 "call do_in_ax_dx" \
70 parm [dx] value [ax] modify nomemory;
71#else
72 #define out_w outw
73 #define in_w inw
74#endif
75
76
77/* VESA signatures as integer constants. */
78#define SIG_VBE2 0x32454256 /* 'VBE2' */
79#define SIG_VESA 0x41534556 /* 'VESA' */
80
81
82/* Implemented in assembler. */
83extern void __cdecl vga_compat_setup(void);
84extern void dispi_set_enable(uint16_t enable);
85extern void dispi_set_bank(uint16_t bank);
86extern uint16_t __cdecl dispi_get_max_bpp(void);
87extern void __cdecl dispi_set_bank_farcall(void);
88
89// The current OEM Software Revision of this VBE Bios
90#define VBE_OEM_SOFTWARE_REV 0x0003
91
92// FIXME: 'merge' these (c) etc strings with the vgabios.c strings?
93char vbebios_copyright[] = "VirtualBox VESA BIOS";
94char vbebios_vendor_name[] = VBOX_VENDOR;
95char vbebios_product_name[] = VBOX_PRODUCT " VBE Adapter";
96char vbebios_product_revision[] = VBOX_PRODUCT " Version " VBOX_VERSION_STRING;
97
98char vbebios_info_string[] = "VirtualBox VBE Display Adapter enabled\r\n\r\n";
99char no_vbebios_info_string[] = "No VirtualBox VBE support available!\r\n\r\n";
100
101#ifdef VGA_DEBUG
102char msg_vbe_init[] = "VirtualBox Version " VBOX_VERSION_STRING " VBE Display Adapter\r\n";
103#endif
104
105static void dispi_set_xres(uint16_t xres)
106{
107#ifdef VGA_DEBUG
108 printf("vbe_set_xres: %04x\n", xres);
109#endif
110 out_w(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_XRES);
111 out_w(VBE_DISPI_IOPORT_DATA, xres);
112}
113
114static void dispi_set_yres(uint16_t yres)
115{
116#ifdef VGA_DEBUG
117 printf("vbe_set_yres: %04x\n", yres);
118#endif
119 out_w(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_YRES);
120 out_w(VBE_DISPI_IOPORT_DATA, yres);
121}
122
123static void dispi_set_bpp(uint16_t bpp)
124{
125#ifdef VGA_DEBUG
126 printf("vbe_set_bpp: %02x\n", bpp);
127#endif
128 out_w(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_BPP);
129 out_w(VBE_DISPI_IOPORT_DATA, bpp);
130}
131
132static uint16_t dispi_get_bpp(void)
133{
134 out_w(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_BPP);
135 return in_w(VBE_DISPI_IOPORT_DATA);
136}
137
138static void dispi_set_virt_width(uint16_t vwidth)
139{
140#ifdef VGA_DEBUG
141 printf("vbe_set_virt_width: %04x\n", vwidth);
142#endif
143 out_w(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_VIRT_WIDTH);
144 out_w(VBE_DISPI_IOPORT_DATA, vwidth);
145}
146
147static uint16_t dispi_get_virt_width(void)
148{
149 out_w(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_VIRT_WIDTH);
150 return in_w(VBE_DISPI_IOPORT_DATA);
151}
152
153static uint16_t dispi_get_virt_height(void)
154{
155 out_w(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_VIRT_HEIGHT);
156 return in_w(VBE_DISPI_IOPORT_DATA);
157}
158
159uint16_t in_word(uint16_t port, uint16_t addr)
160{
161 outw(port, addr);
162 return inw(port);
163}
164
165#ifdef VBE_NEW_DYN_LIST
166uint8_t in_byte(uint16_t port, uint16_t addr)
167{
168 outw(port, addr);
169 return inb(port);
170}
171#endif
172
173/* Display "chip" identification helpers. */
174static uint16_t dispi_get_id(void)
175{
176 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID);
177 return inw(VBE_DISPI_IOPORT_DATA);
178}
179
180static void dispi_set_id(uint16_t chip_id)
181{
182 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID);
183 outw(VBE_DISPI_IOPORT_DATA, chip_id);
184}
185
186/* VBE Init - Initialise the VESA BIOS Extension (VBE) support
187 * This function does a sanity check on the host side display code interface.
188 */
189void vbe_init(void)
190{
191 dispi_set_id(VBE_DISPI_ID0);
192 if (dispi_get_id() == VBE_DISPI_ID0) {
193 /* VBE support was detected. */
194 write_byte(BIOSMEM_SEG, BIOSMEM_VBE_FLAG, 1);
195 dispi_set_id(VBE_DISPI_ID4);
196 }
197#ifdef DEBUG_VGA
198 printf(msg_vbe_init);
199#endif
200}
201
202/* Find the offset of the desired mode, given its number. */
203#ifdef VBE_NEW_DYN_LIST
204static uint16_t mode_info_find_mode(uint16_t mode, Boolean using_lfb)
205{
206 uint16_t sig, vmode, attrs;
207 uint16_t cur_info_ofs; /* Current offset in mode list. */
208
209 /* Read and check the VBE Extra Data signature. */
210 sig = in_word(VBE_EXTRA_PORT, 0);
211 if (sig != VBEHEADER_MAGIC) {
212#ifdef DEBUG_VGA
213 printf("Signature NOT found! %x\n", sig);
214#endif
215 return 0;
216 }
217
218 cur_info_ofs = sizeof(VBEHeader);
219
220 vmode = in_word(VBE_EXTRA_PORT, cur_info_ofs + offsetof(ModeInfoListItem, mode)/*&cur_info->mode*/);
221 while (vmode != VBE_VESA_MODE_END_OF_LIST)
222 {
223 attrs = in_word(VBE_EXTRA_PORT, /*&cur_info->info.ModeAttributes*/cur_info_ofs + offsetof(ModeInfoListItem, info.ModeAttributes) );
224
225 if (vmode == mode)
226 {
227 if (!using_lfb)
228 return cur_info_ofs;
229 else if (attrs & VBE_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER_MODE)
230 return cur_info_ofs;
231 else {
232 cur_info_ofs += sizeof(ModeInfoListItem);
233 vmode = in_word(VBE_EXTRA_PORT, /*&cur_info->mode*/cur_info_ofs + offsetof(ModeInfoListItem, mode));
234 }
235 } else {
236 cur_info_ofs += sizeof(ModeInfoListItem);
237 vmode = in_word(VBE_EXTRA_PORT, /*&cur_info->mode*/cur_info_ofs + offsetof(ModeInfoListItem, mode));
238 }
239 }
240 return 0;
241}
242#else
243static ModeInfoListItem* mode_info_find_mode(uint16_t mode, Boolean using_lfb)
244{
245 ModeInfoListItem *cur_info = &mode_info_list;
246
247 while (cur_info->mode != VBE_VESA_MODE_END_OF_LIST)
248 {
249 if (cur_info->mode == mode)
250 {
251 if (!using_lfb)
252 return cur_info;
253 else if (cur_info->info.ModeAttributes & VBE_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER_MODE)
254 return cur_info;
255 else
256 cur_info++;
257 } else
258 cur_info++;
259 }
260 return 0;
261}
262#endif
263
264#ifndef VBOX
265; VBE Display Info - Display information on screen about the VBE
266
267vbe_display_info:
268 call _vbe_has_vbe_display
269 test ax, ax
270 jz no_vbe_flag
271 mov ax, #0xc000
272 mov ds, ax
273 mov si, #_vbebios_info_string
274 jmp _display_string
275no_vbe_flag:
276 mov ax, #0xc000
277 mov ds, ax
278 mov si, #_no_vbebios_info_string
279 jmp _display_string
280#endif
281
282/** Function 00h - Return VBE Controller Information
283 *
284 * Input:
285 * AX = 4F00h
286 * ES:DI = Pointer to buffer in which to place VbeInfoBlock structure
287 * (VbeSignature should be VBE2 when VBE 2.0 information is desired and
288 * the info block is 512 bytes in size)
289 * Output:
290 * AX = VBE Return Status
291 *
292 */
293void vbe_biosfn_return_controller_information(uint16_t STACK_BASED *AX, uint16_t ES, uint16_t DI)
294{
295 uint16_t status;
296 uint16_t vbe2_info;
297 uint16_t cur_mode = 0;
298 uint16_t cur_ptr=34;
299#ifdef VBE_NEW_DYN_LIST
300 uint16_t cur_info_ofs;
301 uint16_t sig, vmode;
302#else
303 ModeInfoListItem *cur_info = &mode_info_list;
304#endif
305 uint16_t max_bpp = dispi_get_max_bpp();
306 VbeInfoBlock __far *info_block;
307
308 info_block = ES :> (VbeInfoBlock *)DI;
309
310#ifdef VBE_NEW_DYN_LIST
311 /* Read VBE Extra Data signature */
312 sig = in_word(VBE_EXTRA_PORT, 0);
313 if (sig != VBEHEADER_MAGIC)
314 {
315 *AX = 0x0100;
316#ifdef DEBUG_VGA
317 printf("Signature NOT found\n");
318#endif
319 return;
320 }
321 cur_info_ofs = sizeof(VBEHeader);
322#endif
323 status = *AX;
324
325#ifdef VGA_DEBUG
326 printf("VBE vbe_biosfn_return_vbe_info ES%x DI%x AX%x\n",ES,DI,status);
327#endif
328
329 vbe2_info = 0;
330
331 /* Don't use a local copy of VbeInfoBlock on the stack; it's too big.
332 * The Ubuntu 8.04 64 bits splash screen emulator can't handle this.
333 */
334#ifdef VBE2_NO_VESA_CHECK
335#else /* !VBE2_NO_VESA_CHECK */
336 // check for VBE2 signature
337 if (info_block->VbeSignature.Sig32 == SIG_VBE2 || info_block->VbeSignature.Sig32 == SIG_VESA)
338 {
339 vbe2_info = 1;
340#ifdef VGA_DEBUG
341 printf("VBE correct VESA/VBE2 signature found\n");
342#endif
343 }
344#endif /* !VBE2_NO_VESA_CHECK */
345
346 /* VBE Signature - the compiler will optimize this into something sane. */
347 info_block->VbeSignature.SigChr[0] = 'V';
348 info_block->VbeSignature.SigChr[1] = 'E';
349 info_block->VbeSignature.SigChr[2] = 'S';
350 info_block->VbeSignature.SigChr[3] = 'A';
351
352 /* VBE Version supported. */
353 info_block->VbeVersion = 0x0200; /* Version 2.0. */
354
355 /* OEM String. */
356 info_block->OemString.Ptr = &vbebios_copyright;
357
358 /* Capabilities if this implementation. */
359 info_block->Capabilities[0] = VBE_CAPABILITY_8BIT_DAC;
360 info_block->Capabilities[1] = 0;
361 info_block->Capabilities[2] = 0;
362 info_block->Capabilities[3] = 0;
363
364 /* Video mode list pointer (dynamically generated). */
365 info_block->VideoModePtr_Seg = ES;
366 info_block->VideoModePtr_Off = DI + 34;
367
368 /* Total controller memory in 64K units. */
369 info_block->TotalMemory = in_word(VBE_EXTRA_PORT, 0xffff);
370
371 if (vbe2_info)
372 {
373 /* OEM information. */
374 info_block->OemSoftwareRev = VBE_OEM_SOFTWARE_REV;
375 info_block->OemVendorName.Ptr = &vbebios_vendor_name;
376 info_block->OemProductName.Ptr = &vbebios_product_name;
377 info_block->OemProductRev.Ptr = &vbebios_product_revision;
378 }
379
380#ifdef VBE_NEW_DYN_LIST
381 do
382 {
383 uint8_t data_b;
384
385 data_b = in_byte(VBE_EXTRA_PORT, cur_info_ofs + offsetof(ModeInfoListItem, info.BitsPerPixel) /*&cur_info->info.BitsPerPixel*/);
386 if (data_b <= max_bpp)
387 {
388 vmode = in_word(VBE_EXTRA_PORT, cur_info_ofs + offsetof(ModeInfoListItem, mode)/*&cur_info->mode*/);
389#ifdef VGA_DEBUG
390 printf("VBE found mode %x => %x\n", vmode, cur_mode);
391#endif
392 write_word(ES, DI + cur_ptr, vmode);
393 cur_mode++;
394 cur_ptr+=2;
395 }
396 cur_info_ofs += sizeof(ModeInfoListItem);
397 vmode = in_word(VBE_EXTRA_PORT, cur_info_ofs + offsetof(ModeInfoListItem, mode)/*&cur_info->mode*/);
398 } while (vmode != VBE_VESA_MODE_END_OF_LIST);
399
400 // Add vesa mode list terminator
401 write_word(ES, DI + cur_ptr, vmode);
402#else
403 do
404 {
405 if (cur_info->info.BitsPerPixel <= max_bpp) {
406#ifdef VGA_DEBUG
407 printf("VBE found mode %x => %x\n", cur_info->mode,cur_mode);
408#endif
409 write_word(ES, DI + cur_ptr, cur_info->mode);
410 cur_mode++;
411 cur_ptr += 2;
412 }
413 cur_info++;
414 } while (cur_info->mode != VBE_VESA_MODE_END_OF_LIST);
415
416 // Add vesa mode list terminator
417 write_word(ES, DI + cur_ptr, cur_info->mode);
418#endif // VBE_NEW_DYN_LIST
419 *AX = 0x004F;
420}
421
422/** Function 01h - Return VBE Mode Information
423 *
424 * Input:
425 * AX = 4F01h
426 * CX = Mode Number
427 * ES:DI = Pointer to buffer in which to place ModeInfoBlock structure
428 * Output:
429 * AX = VBE Return Status
430 *
431 */
432void vbe_biosfn_return_mode_information(uint16_t STACK_BASED *AX, uint16_t CX, uint16_t ES, uint16_t DI)
433{
434 uint16_t result = 0x0100;
435#ifdef VBE_NEW_DYN_LIST
436 uint16_t cur_info_ofs;
437#else
438 ModeInfoListItem *cur_info;
439#endif
440 Boolean using_lfb;
441 uint8_t win_attr;
442
443#ifdef VGA_DEBUG
444 printf("VBE vbe_biosfn_return_mode_information ES%x DI%x CX%x\n",ES,DI,CX);
445#endif
446
447 using_lfb = ((CX & VBE_MODE_LINEAR_FRAME_BUFFER) == VBE_MODE_LINEAR_FRAME_BUFFER);
448 CX = (CX & 0x1ff);
449
450#ifdef VBE_NEW_DYN_LIST
451 cur_info_ofs = mode_info_find_mode(CX, using_lfb);
452
453 if (cur_info_ofs) {
454 uint16_t i;
455#else
456 cur_info = mode_info_find_mode(CX, using_lfb);
457
458 if (cur_info != 0) {
459#endif
460#ifdef VGA_DEBUG
461 printf("VBE found mode %x\n",CX);
462#endif
463 memsetb(ES, DI, 0, 256); // The mode info size is fixed
464#ifdef VBE_NEW_DYN_LIST
465 for (i = 0; i < sizeof(ModeInfoBlockCompact); i++) {
466 uint8_t b;
467
468 b = in_byte(VBE_EXTRA_PORT, cur_info_ofs + offsetof(ModeInfoListItem, info) + i/*(char *)(&(cur_info->info)) + i*/);
469 write_byte(ES, DI + i, b);
470 }
471#else
472 memcpyb(ES, DI, 0xc000, &(cur_info->info), sizeof(ModeInfoBlockCompact));
473#endif
474 win_attr = read_byte(ES, DI + offsetof(ModeInfoBlock, WinAAttributes));
475 if (win_attr & VBE_WINDOW_ATTRIBUTE_RELOCATABLE) {
476 write_word(ES, DI + offsetof(ModeInfoBlock, WinFuncPtr), (uint16_t)(dispi_set_bank_farcall));
477 // If BIOS not at 0xC000 -> boom
478 write_word(ES, DI + offsetof(ModeInfoBlock, WinFuncPtr) + 2, 0xC000);
479 }
480 // Update the LFB physical address which may change at runtime
481 out_w(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_FB_BASE_HI);
482 write_word(ES, DI + offsetof(ModeInfoBlock, PhysBasePtr) + 2, in_w(VBE_DISPI_IOPORT_DATA));
483
484 result = 0x4f;
485 } else {
486#ifdef VGA_DEBUG
487 printf("VBE *NOT* found mode %x\n",CX);
488#endif
489 result = 0x100;
490 }
491
492 *AX = result;
493}
494
495/** Function 02h - Set VBE Mode
496 *
497 * Input:
498 * AX = 4F02h
499 * BX = Desired Mode to set
500 * ES:DI = Pointer to CRTCInfoBlock structure
501 * Output:
502 * AX = VBE Return Status
503 *
504 */
505void vbe_biosfn_set_mode(uint16_t STACK_BASED *AX, uint16_t BX, uint16_t ES, uint16_t DI)
506{
507 uint16_t result;
508#ifdef VBE_NEW_DYN_LIST
509 uint16_t cur_info_ofs;
510#else
511 ModeInfoListItem *cur_info;
512#endif
513 Boolean using_lfb;
514 uint8_t no_clear;
515 uint8_t lfb_flag;
516
517 using_lfb = ((BX & VBE_MODE_LINEAR_FRAME_BUFFER) == VBE_MODE_LINEAR_FRAME_BUFFER);
518 lfb_flag = using_lfb ? VBE_DISPI_LFB_ENABLED : 0;
519 no_clear = ((BX & VBE_MODE_PRESERVE_DISPLAY_MEMORY) == VBE_MODE_PRESERVE_DISPLAY_MEMORY) ? VBE_DISPI_NOCLEARMEM : 0;
520
521 BX = (BX & 0x1ff);
522
523 // check for non vesa mode
524 if (BX < VBE_MODE_VESA_DEFINED)
525 {
526 uint8_t mode;
527
528 dispi_set_enable(VBE_DISPI_DISABLED);
529 // call the vgabios in order to set the video mode
530 // this allows for going back to textmode with a VBE call (some applications expect that to work)
531 mode = (BX & 0xff);
532 biosfn_set_video_mode(mode);
533 result = 0x4f;
534 goto leave;
535 }
536
537#ifdef VBE_NEW_DYN_LIST
538 cur_info_ofs = mode_info_find_mode(BX, using_lfb);
539
540 if (cur_info_ofs != 0)
541 {
542 uint16_t xres, yres;
543 uint8_t bpp;
544
545 xres = in_word(VBE_EXTRA_PORT, cur_info_ofs + offsetof(ModeInfoListItem, info.XResolution) /*&cur_info->info.XResolution*/);
546 yres = in_word(VBE_EXTRA_PORT, cur_info_ofs + offsetof(ModeInfoListItem, info.YResolution) /*&cur_info->info.YResolution*/);
547 bpp = in_byte(VBE_EXTRA_PORT, cur_info_ofs + offsetof(ModeInfoListItem, info.BitsPerPixel) /*&cur_info->info.BitsPerPixel*/);
548
549#ifdef VGA_DEBUG
550 printf("VBE found mode %x, setting:\n", BX);
551 printf("\txres%x yres%x bpp%x\n", xres, yres, bpp);
552#endif
553#else
554 cur_info = mode_info_find_mode(BX, using_lfb);
555
556 if (cur_info != 0)
557 {
558#ifdef VGA_DEBUG
559 printf("VBE found mode %x, setting:\n", BX);
560 printf("\txres%x yres%x bpp%x\n",
561 cur_info->info.XResolution,
562 cur_info->info.YResolution,
563 cur_info->info.BitsPerPixel);
564#endif
565#endif // VBE_NEW_DYN_LIST
566
567 // first disable current mode (when switching between vesa modi)
568 dispi_set_enable(VBE_DISPI_DISABLED);
569
570#ifdef VBE_NEW_DYN_LIST
571 if (bpp == 4)
572#else
573 if (cur_info->info.BitsPerPixel == 4)
574#endif
575 {
576 biosfn_set_video_mode(0x6a);
577 }
578
579#ifdef VBE_NEW_DYN_LIST
580 dispi_set_bpp(bpp);
581 dispi_set_xres(xres);
582 dispi_set_yres(yres);
583#else
584 dispi_set_bpp(cur_info->info.BitsPerPixel);
585 dispi_set_xres(cur_info->info.XResolution);
586 dispi_set_yres(cur_info->info.YResolution);
587#endif
588 dispi_set_bank(0);
589 dispi_set_enable(VBE_DISPI_ENABLED | no_clear | lfb_flag);
590 vga_compat_setup();
591
592 write_word(BIOSMEM_SEG,BIOSMEM_VBE_MODE,BX);
593 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60 | no_clear));
594
595 result = 0x4f;
596 }
597 else
598 {
599#ifdef VGA_DEBUG
600 printf("VBE *NOT* found mode %x\n" , BX);
601#endif
602 result = 0x100;
603 }
604
605leave:
606 *AX = result;
607}
608
609uint16_t vbe_biosfn_read_video_state_size(void)
610{
611 return 9 * 2;
612}
613
614void vbe_biosfn_save_video_state(uint16_t ES, uint16_t BX)
615{
616 uint16_t enable, i;
617
618 outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_ENABLE);
619 enable = inw(VBE_DISPI_IOPORT_DATA);
620 write_word(ES, BX, enable);
621 BX += 2;
622 if (!(enable & VBE_DISPI_ENABLED))
623 return;
624 for(i = VBE_DISPI_INDEX_XRES; i <= VBE_DISPI_INDEX_Y_OFFSET; i++) {
625 if (i != VBE_DISPI_INDEX_ENABLE) {
626 outw(VBE_DISPI_IOPORT_INDEX, i);
627 write_word(ES, BX, inw(VBE_DISPI_IOPORT_DATA));
628 BX += 2;
629 }
630 }
631}
632
633
634void vbe_biosfn_restore_video_state(uint16_t ES, uint16_t BX)
635{
636 uint16_t enable, i;
637
638 enable = read_word(ES, BX);
639 BX += 2;
640
641 if (!(enable & VBE_DISPI_ENABLED)) {
642 outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_ENABLE);
643 outw(VBE_DISPI_IOPORT_DATA, enable);
644 } else {
645 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_XRES);
646 outw(VBE_DISPI_IOPORT_DATA, read_word(ES, BX));
647 BX += 2;
648 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_YRES);
649 outw(VBE_DISPI_IOPORT_DATA, read_word(ES, BX));
650 BX += 2;
651 outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_BPP);
652 outw(VBE_DISPI_IOPORT_DATA, read_word(ES, BX));
653 BX += 2;
654 outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_ENABLE);
655 outw(VBE_DISPI_IOPORT_DATA, enable);
656
657 for(i = VBE_DISPI_INDEX_BANK; i <= VBE_DISPI_INDEX_Y_OFFSET; i++) {
658 outw(VBE_DISPI_IOPORT_INDEX, i);
659 outw(VBE_DISPI_IOPORT_DATA, read_word(ES, BX));
660 BX += 2;
661 }
662 }
663}
664
665/** Function 04h - Save/Restore State
666 *
667 * Input:
668 * AX = 4F04h
669 * DL = 00h Return Save/Restore State buffer size
670 * 01h Save State
671 * 02h Restore State
672 * CX = Requested states
673 * ES:BX = Pointer to buffer (if DL <> 00h)
674 * Output:
675 * AX = VBE Return Status
676 * BX = Number of 64-byte blocks to hold the state buffer (if DL=00h)
677 *
678 */
679void vbe_biosfn_save_restore_state(uint16_t STACK_BASED *AX, uint16_t CX, uint16_t DX,
680 uint16_t ES, uint16_t STACK_BASED *BX)
681{
682 uint16_t result, val;
683
684 result = 0x004F;
685 switch(GET_DL()) {
686 case 0x00:
687 val = biosfn_read_video_state_size2(CX);
688#ifdef VGA_DEBUG
689 printf("VGA state size=%x\n", val);
690#endif
691 if (CX & 8)
692 val += vbe_biosfn_read_video_state_size();
693 *BX = (val + 63) / 64;
694 break;
695 case 0x01:
696 val = *BX;
697 val = biosfn_save_video_state(CX, ES, val);
698#ifdef VGA_DEBUG
699 printf("VGA save_state offset=%x\n", val);
700#endif
701 if (CX & 8)
702 vbe_biosfn_save_video_state(ES, val);
703 break;
704 case 0x02:
705 val = *BX;
706 val = biosfn_restore_video_state(CX, ES, val);
707#ifdef VGA_DEBUG
708 printf("VGA restore_state offset=%x\n", val);
709#endif
710 if (CX & 8)
711 vbe_biosfn_restore_video_state(ES, val);
712 break;
713 default:
714 // function failed
715 result = 0x100;
716 break;
717 }
718 *AX = result;
719}
720
721/** Function 06h - Set/Get Logical Scan Line Length
722 *
723 * Input:
724 * AX = 4F06h
725 * BL = 00h Set Scan Line Length in Pixels
726 * = 01h Get Scan Line Length
727 * = 02h Set Scan Line Length in Bytes
728 * = 03h Get Maximum Scan Line Length
729 * CX = If BL=00h Desired Width in Pixels
730 * If BL=02h Desired Width in Bytes
731 * (Ignored for Get Functions)
732 *
733 * Output:
734 * AX = VBE Return Status
735 * BX = Bytes Per Scan Line
736 * CX = Actual Pixels Per Scan Line (truncated to
737 * nearest complete pixel)
738 * DX = Maximum Number of Scan Lines
739 */
740void vbe_biosfn_get_set_scanline_length(uint16_t STACK_BASED *AX, uint16_t STACK_BASED *BX,
741 uint16_t STACK_BASED *CX, uint16_t STACK_BASED *DX)
742{
743 uint16_t val;
744 uint16_t result;
745 uint8_t bpp;
746 uint8_t subfn;
747
748 bpp = dispi_get_bpp();
749 result = 0x004F;
750 val = *CX;
751 subfn = *BX & 0xFF;
752#ifdef VGA_DEBUG
753 printf("VBE get/set scanline len fn=%x, CX=%x\n", subfn, *CX);
754#endif
755 switch(subfn) {
756 case 0x02:
757 if (bpp == 4)
758 val = val * 8;
759 else
760 val = val / (bpp / 8);
761 /* fall through */
762 case 0x00:
763 dispi_set_virt_width(val);
764 /* fall through */
765 case 0x01:
766 val = dispi_get_virt_width();
767 *CX = val; /* Width in pixels. */
768 if (bpp == 4)
769 val = val / 8;
770 else
771 val = val * (bpp / 8);
772 val = (val + 3) & ~3;
773 *BX = val; /* Bytes per scanline. */
774 *DX = dispi_get_virt_height(); /* Height in lines. */
775 break;
776 default:
777 // function failed
778 result = 0x100;
779 break;
780 }
781 *AX = result;
782}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette