1 /****************************************************************************
3 * The SuperVGA Kit - UniVBE Software Development Kit
5 * ========================================================================
7 * The contents of this file are subject to the SciTech MGL Public
8 * License Version 1.0 (the "License"); you may not use this file
9 * except in compliance with the License. You may obtain a copy of
10 * the License at http://www.scitechsoft.com/mgl-license.txt
12 * Software distributed under the License is distributed on an
13 * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
14 * implied. See the License for the specific language governing
15 * rights and limitations under the License.
17 * The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.
19 * The Initial Developer of the Original Code is SciTech Software, Inc.
20 * All Rights Reserved.
22 * ========================================================================
25 * Environment: IBM PC Real Mode and 16/32 bit Protected Mode.
27 * Description: Module to implement a C callable interface to the standard
28 * VESA VBE routines. You should rip out this module and use it
29 * directly in your own applications, or you can use the
30 * high level SDK functions.
32 * MUST be compiled in the LARGE or FLAT models.
34 ****************************************************************************/
41 #include "drvlib/os/os.h"
43 /*---------------------------- Global Variables ---------------------------*/
45 #define VBE_SUCCESS 0x004F
46 #define MAX_LIN_PTRS 10
48 static uint VESABuf_len
= 1024;/* Length of the VESABuf buffer */
49 static ibool haveRiva128
; /* True if we have a Riva128 */
50 static VBE_state defState
= {0}; /* Default state buffer */
51 static VBE_state
*state
= &defState
; /* Pointer to current buffer */
52 static int VBE_shared
= 0;
54 static char localBuf
[512]; /* Global PM string translate buf */
55 #define MAX_LOCAL_BUF &localBuf[511]
58 /*----------------------------- Implementation ----------------------------*/
60 /* static function in WinDirect for passing 32-bit registers to BIOS */
61 int PMAPI
WD_int386(int intno
, RMREGS
*in
, RMREGS
*out
);
63 void VBEAPI
VBE_init(void)
64 /****************************************************************************
68 * Description: Initialises the VBE transfer buffer in real mode DC.memory.
69 * This routine is called by the VESAVBE module every time
70 * it needs to use the transfer buffer, so we simply allocate
71 * it once and then return.
73 ****************************************************************************/
75 if (!state
->VESABuf_ptr
) {
76 /* Allocate a global buffer for communicating with the VESA VBE */
77 if ((state
->VESABuf_ptr
= PM_getVESABuf(&VESABuf_len
, &state
->VESABuf_rseg
, &state
->VESABuf_roff
)) == NULL
)
78 PM_fatalError("VESAVBE.C: Real mode memory allocation failed!");
82 void * VBEAPI
VBE_getRMBuf(uint
*len
,uint
*rseg
,uint
*roff
)
83 /****************************************************************************
85 * Function: VBE_getRMBuf
87 * Description: This function returns the location and length of the real
88 * mode memory buffer for calling real mode functions.
90 ****************************************************************************/
93 *rseg
= state
->VESABuf_rseg
;
94 *roff
= state
->VESABuf_roff
;
95 return state
->VESABuf_ptr
;
98 void VBEAPI
VBE_setStateBuffer(VBE_state
*s
)
99 /****************************************************************************
101 * Function: VBE_setStateBuffer
103 * Description: This functions sets the internal state buffer for the
104 * VBE module to the passed in buffer. By default the internal
105 * global buffer is used, but you must use separate buffers
106 * for each device in a multi-controller environment.
108 ****************************************************************************/
113 void VBEAPI
VBE_callESDI(RMREGS
*regs
, void *buffer
, int size
)
114 /****************************************************************************
116 * Function: VBE_callESDI
117 * Parameters: regs - Registers to load when calling VBE
118 * buffer - Buffer to copy VBE info block to
119 * size - Size of buffer to fill
121 * Description: Calls the VESA VBE and passes in a buffer for the VBE to
122 * store information in, which is then copied into the users
123 * buffer space. This works in protected mode as the buffer
124 * passed to the VESA VBE is allocated in conventional
125 * memory, and is then copied into the users memory block.
127 ****************************************************************************/
131 if (!state
->VESABuf_ptr
)
132 PM_fatalError("You *MUST* call VBE_init() before you can call the VESAVBE.C module!");
133 sregs
.es
= (ushort
)state
->VESABuf_rseg
;
134 regs
->x
.di
= (ushort
)state
->VESABuf_roff
;
135 memcpy(state
->VESABuf_ptr
, buffer
, size
);
136 PM_int86x(0x10, regs
, regs
, &sregs
);
137 memcpy(buffer
, state
->VESABuf_ptr
, size
);
141 static char *VBE_copyStrToLocal(char *p
,char *realPtr
,char *max
)
142 /****************************************************************************
144 * Function: VBE_copyStrToLocal
145 * Parameters: p - Flat model buffer to copy to
146 * realPtr - Real mode pointer to copy
147 * Returns: Pointer to the next byte after string
149 * Description: Copies the string from the real mode location pointed to
150 * by 'realPtr' into the flat model buffer pointed to by
151 * 'p'. We return a pointer to the next byte past the copied
154 ****************************************************************************/
158 v
= PM_mapRealPointer((uint
)((ulong
)realPtr
>> 16), (uint
)((ulong
)realPtr
& 0xFFFF));
159 while (*v
!= 0 && p
< max
)
165 static void VBE_copyShortToLocal(ushort
*p
,ushort
*realPtr
)
166 /****************************************************************************
168 * Function: VBE_copyShortToLocal
169 * Parameters: p - Flat model buffer to copy to
170 * realPtr - Real mode pointer to copy
172 * Description: Copies the mode table from real mode memory to the flat
175 ****************************************************************************/
179 v
= PM_mapRealPointer((uint
)((ulong
)realPtr
>> 16),(uint
)((ulong
)realPtr
& 0xFFFF));
186 int VBEAPI
VBE_detectEXT(VBE_vgaInfo
*vgaInfo
,ibool forceUniVBE
)
187 /****************************************************************************
189 * Function: VBE_detect
190 * Parameters: vgaInfo - Place to store the VGA information block
191 * Returns: VBE version number, or 0 if not detected.
193 * Description: Detects if a VESA VBE is out there and functioning
194 * correctly. If we detect a VBE interface we return the
195 * VGAInfoBlock returned by the VBE and the VBE version number.
197 ****************************************************************************/
201 regs
.x
.ax
= 0x4F00; /* Get SuperVGA information */
210 strncpy(vgaInfo
->VESASignature
,"VBE2",4);
211 VBE_callESDI(®s
, vgaInfo
, sizeof(*vgaInfo
));
212 if (regs
.x
.ax
!= VBE_SUCCESS
)
214 if (strncmp(vgaInfo
->VESASignature
,"VESA",4) != 0)
217 /* Check for bogus BIOSes that return a VBE version number that is
218 * not correct, and fix it up. We also check the OemVendorNamePtr for a
219 * valid value, and if it is invalid then we also reset to VBE 1.2.
221 if (vgaInfo
->VESAVersion
>= 0x200 && vgaInfo
->OemVendorNamePtr
== 0)
222 vgaInfo
->VESAVersion
= 0x102;
224 /* Relocate all the indirect information (mode tables, OEM strings
225 * etc) from the low 1Mb memory region into a static buffer in
226 * our default data segment. We do this to insulate the application
227 * from mapping the strings from real mode to protected mode.
231 p2
= VBE_copyStrToLocal(localBuf
,vgaInfo
->OemStringPtr
,MAX_LOCAL_BUF
);
232 vgaInfo
->OemStringPtr
= localBuf
;
233 if (vgaInfo
->VESAVersion
>= 0x200) {
234 p
= VBE_copyStrToLocal(p2
,vgaInfo
->OemVendorNamePtr
,MAX_LOCAL_BUF
);
235 vgaInfo
->OemVendorNamePtr
= p2
;
236 p2
= VBE_copyStrToLocal(p
,vgaInfo
->OemProductNamePtr
,MAX_LOCAL_BUF
);
237 vgaInfo
->OemProductNamePtr
= p
;
238 p
= VBE_copyStrToLocal(p2
,vgaInfo
->OemProductRevPtr
,MAX_LOCAL_BUF
);
239 vgaInfo
->OemProductRevPtr
= p2
;
240 VBE_copyShortToLocal((ushort
*)p
,vgaInfo
->VideoModePtr
);
241 vgaInfo
->VideoModePtr
= (ushort
*)p
;
244 VBE_copyShortToLocal((ushort
*)p2
,vgaInfo
->VideoModePtr
);
245 vgaInfo
->VideoModePtr
= (ushort
*)p2
;
249 state
->VBEMemory
= vgaInfo
->TotalMemory
* 64;
251 /* Check for Riva128 based cards since they have broken triple buffering
252 * and stereo support.
255 if (vgaInfo
->VESAVersion
>= 0x300 &&
256 (strstr(vgaInfo
->OemStringPtr
,"NVidia") != NULL
||
257 strstr(vgaInfo
->OemStringPtr
,"Riva") != NULL
)) {
261 /* Check for Matrox G400 cards which claim to be VBE 3.0
262 * compliant yet they don't implement the refresh rate control
265 if (vgaInfo
->VESAVersion
>= 0x300 && (strcmp(vgaInfo
->OemProductNamePtr
,"Matrox G400") == 0))
266 vgaInfo
->VESAVersion
= 0x200;
267 return (state
->VBEVersion
= vgaInfo
->VESAVersion
);
270 int VBEAPI
VBE_detect(VBE_vgaInfo
*vgaInfo
)
271 /****************************************************************************
273 * Function: VBE_detect
274 * Parameters: vgaInfo - Place to store the VGA information block
275 * Returns: VBE version number, or 0 if not detected.
277 * Description: Detects if a VESA VBE is out there and functioning
278 * correctly. If we detect a VBE interface we return the
279 * VGAInfoBlock returned by the VBE and the VBE version number.
281 ****************************************************************************/
283 return VBE_detectEXT(vgaInfo
,false);
286 ibool VBEAPI
VBE_getModeInfo(int mode
,VBE_modeInfo
*modeInfo
)
287 /****************************************************************************
289 * Function: VBE_getModeInfo
290 * Parameters: mode - VBE mode to get information for
291 * modeInfo - Place to store VBE mode information
292 * Returns: True on success, false if function failed.
294 * Description: Obtains information about a specific video mode from the
295 * VBE. You should use this function to find the video mode
296 * you wish to set, as the new VBE 2.0 mode numbers may be
297 * completely arbitrary.
299 ****************************************************************************/
304 regs
.x
.ax
= 0x4F01; /* Get mode information */
305 regs
.x
.cx
= (ushort
)mode
;
306 VBE_callESDI(®s
, modeInfo
, sizeof(*modeInfo
));
307 if (regs
.x
.ax
!= VBE_SUCCESS
)
309 if ((modeInfo
->ModeAttributes
& vbeMdAvailable
) == 0)
312 /* Map out triple buffer and stereo flags for NVidia Riva128
316 modeInfo
->ModeAttributes
&= ~vbeMdTripleBuf
;
317 modeInfo
->ModeAttributes
&= ~vbeMdStereo
;
320 /* Support old style RGB definitions for VBE 1.1 BIOSes */
321 bits
= modeInfo
->BitsPerPixel
;
322 if (modeInfo
->MemoryModel
== vbeMemPK
&& bits
> 8) {
323 modeInfo
->MemoryModel
= vbeMemRGB
;
326 modeInfo
->RedMaskSize
= 5;
327 modeInfo
->RedFieldPosition
= 10;
328 modeInfo
->GreenMaskSize
= 5;
329 modeInfo
->GreenFieldPosition
= 5;
330 modeInfo
->BlueMaskSize
= 5;
331 modeInfo
->BlueFieldPosition
= 0;
332 modeInfo
->RsvdMaskSize
= 1;
333 modeInfo
->RsvdFieldPosition
= 15;
336 modeInfo
->RedMaskSize
= 5;
337 modeInfo
->RedFieldPosition
= 11;
338 modeInfo
->GreenMaskSize
= 5;
339 modeInfo
->GreenFieldPosition
= 5;
340 modeInfo
->BlueMaskSize
= 5;
341 modeInfo
->BlueFieldPosition
= 0;
342 modeInfo
->RsvdMaskSize
= 0;
343 modeInfo
->RsvdFieldPosition
= 0;
346 modeInfo
->RedMaskSize
= 8;
347 modeInfo
->RedFieldPosition
= 16;
348 modeInfo
->GreenMaskSize
= 8;
349 modeInfo
->GreenFieldPosition
= 8;
350 modeInfo
->BlueMaskSize
= 8;
351 modeInfo
->BlueFieldPosition
= 0;
352 modeInfo
->RsvdMaskSize
= 0;
353 modeInfo
->RsvdFieldPosition
= 0;
358 /* Convert the 32k direct color modes of VBE 1.2+ BIOSes to
359 * be recognised as 15 bits per pixel modes.
361 if (bits
== 16 && modeInfo
->RsvdMaskSize
== 1)
362 modeInfo
->BitsPerPixel
= 15;
364 /* Fix up bogus BIOS'es that report incorrect reserved pixel masks
365 * for 32K color modes. Quite a number of BIOS'es have this problem,
366 * and this affects our OS/2 drivers in VBE fallback mode.
368 if (bits
== 15 && (modeInfo
->RsvdMaskSize
!= 1 || modeInfo
->RsvdFieldPosition
!= 15)) {
369 modeInfo
->RsvdMaskSize
= 1;
370 modeInfo
->RsvdFieldPosition
= 15;
375 long VBEAPI
VBE_getPageSize(VBE_modeInfo
*mi
)
376 /****************************************************************************
378 * Function: VBE_getPageSize
379 * Parameters: mi - Pointer to mode information block
380 * Returns: Caculated page size in bytes rounded to correct boundary
382 * Description: Computes the page size in bytes for the specified mode
383 * information block, rounded up to the appropriate boundary
384 * (8k, 16k, 32k or 64k). Pages >= 64k in size are always
385 * rounded to the nearest 64k boundary (so the start of a
386 * page is always bank aligned).
388 ****************************************************************************/
392 size
= (long)mi
->BytesPerScanLine
* (long)mi
->YResolution
;
393 if (mi
->BitsPerPixel
== 4) {
394 /* We have a 16 color video mode, so round up the page size to
395 * 8k, 16k, 32k or 64k boundaries depending on how large it is.
398 size
= (size
+ 0x1FFFL
) & 0xFFFFE000L
;
399 if (size
!= 0x2000) {
400 size
= (size
+ 0x3FFFL
) & 0xFFFFC000L
;
401 if (size
!= 0x4000) {
402 size
= (size
+ 0x7FFFL
) & 0xFFFF8000L
;
404 size
= (size
+ 0xFFFFL
) & 0xFFFF0000L
;
408 else size
= (size
+ 0xFFFFL
) & 0xFFFF0000L
;
412 ibool VBEAPI
VBE_setVideoModeExt(int mode
,VBE_CRTCInfo
*crtc
)
413 /****************************************************************************
415 * Function: VBE_setVideoModeExt
416 * Parameters: mode - SuperVGA video mode to set.
417 * Returns: True if the mode was set, false if not.
419 * Description: Attempts to set the specified video mode. This version
420 * includes support for the VBE/Core 3.0 refresh rate control
423 ****************************************************************************/
427 if (state
->VBEVersion
< 0x200 && mode
< 0x100) {
428 /* Some VBE implementations barf terribly if you try to set non-VBE
429 * video modes with the VBE set mode call. VBE 2.0 implementations
430 * must be able to handle this.
432 regs
.h
.al
= (ushort
)mode
;
434 PM_int86(0x10,®s
,®s
);
437 if (state
->VBEVersion
< 0x300 && (mode
& vbeRefreshCtrl
))
440 regs
.x
.bx
= (ushort
)mode
;
441 if ((mode
& vbeRefreshCtrl
) && crtc
)
442 VBE_callESDI(®s
, crtc
, sizeof(*crtc
));
444 PM_int86(0x10,®s
,®s
);
445 if (regs
.x
.ax
!= VBE_SUCCESS
)
451 ibool VBEAPI
VBE_setVideoMode(int mode
)
452 /****************************************************************************
454 * Function: VBE_setVideoMode
455 * Parameters: mode - SuperVGA video mode to set.
456 * Returns: True if the mode was set, false if not.
458 * Description: Attempts to set the specified video mode.
460 ****************************************************************************/
462 return VBE_setVideoModeExt(mode
,NULL
);
465 int VBEAPI
VBE_getVideoMode(void)
466 /****************************************************************************
468 * Function: VBE_getVideoMode
469 * Returns: Current video mode
471 ****************************************************************************/
476 PM_int86(0x10,®s
,®s
);
477 if (regs
.x
.ax
!= VBE_SUCCESS
)
482 ibool VBEAPI
VBE_setBank(int window
,int bank
)
483 /****************************************************************************
485 * Function: VBE_setBank
486 * Parameters: window - Window to set
487 * bank - Bank number to set window to
488 * Returns: True on success, false on failure.
490 ****************************************************************************/
498 PM_int86(0x10,®s
,®s
);
499 return regs
.x
.ax
== VBE_SUCCESS
;
502 int VBEAPI
VBE_getBank(int window
)
503 /****************************************************************************
505 * Function: VBE_setBank
506 * Parameters: window - Window to read
507 * Returns: Bank number for the window (-1 on failure)
509 ****************************************************************************/
516 PM_int86(0x10,®s
,®s
);
517 if (regs
.x
.ax
!= VBE_SUCCESS
)
522 ibool VBEAPI
VBE_setPixelsPerLine(int pixelsPerLine
,int *newBytes
,
523 int *newPixels
,int *maxScanlines
)
524 /****************************************************************************
526 * Function: VBE_setPixelsPerLine
527 * Parameters: pixelsPerLine - Pixels per scanline
528 * newBytes - Storage for bytes per line value set
529 * newPixels - Storage for pixels per line value set
530 * maxScanLines - Storage for maximum number of scanlines
531 * Returns: True on success, false on failure
533 * Description: Sets the scanline length for the video mode to the specified
534 * number of pixels per scanline. If you need more granularity
535 * in TrueColor modes, use the VBE_setBytesPerLine routine
536 * (only valid for VBE 2.0).
538 ****************************************************************************/
544 regs
.x
.cx
= pixelsPerLine
;
545 PM_int86(0x10,®s
,®s
);
546 *newBytes
= regs
.x
.bx
;
547 *newPixels
= regs
.x
.cx
;
548 *maxScanlines
= regs
.x
.dx
;
549 return regs
.x
.ax
== VBE_SUCCESS
;
552 ibool VBEAPI
VBE_setBytesPerLine(int bytesPerLine
,int *newBytes
,
553 int *newPixels
,int *maxScanlines
)
554 /****************************************************************************
556 * Function: VBE_setBytesPerLine
557 * Parameters: pixelsPerLine - Pixels per scanline
558 * newBytes - Storage for bytes per line value set
559 * newPixels - Storage for pixels per line value set
560 * maxScanLines - Storage for maximum number of scanlines
561 * Returns: True on success, false on failure
563 * Description: Sets the scanline length for the video mode to the specified
564 * number of bytes per scanline (valid for VBE 2.0 only).
566 ****************************************************************************/
572 regs
.x
.cx
= bytesPerLine
;
573 PM_int86(0x10,®s
,®s
);
574 *newBytes
= regs
.x
.bx
;
575 *newPixels
= regs
.x
.cx
;
576 *maxScanlines
= regs
.x
.dx
;
577 return regs
.x
.ax
== VBE_SUCCESS
;
580 ibool VBEAPI
VBE_getScanlineLength(int *bytesPerLine
,int *pixelsPerLine
,
582 /****************************************************************************
584 * Function: VBE_getScanlineLength
585 * Parameters: bytesPerLine - Storage for bytes per scanline
586 * pixelsPerLine - Storage for pixels per scanline
587 * maxScanLines - Storage for maximum number of scanlines
588 * Returns: True on success, false on failure
590 ****************************************************************************/
596 PM_int86(0x10,®s
,®s
);
597 *bytesPerLine
= regs
.x
.bx
;
598 *pixelsPerLine
= regs
.x
.cx
;
599 *maxScanlines
= regs
.x
.dx
;
600 return regs
.x
.ax
== VBE_SUCCESS
;
603 ibool VBEAPI
VBE_getMaxScanlineLength(int *maxBytes
,int *maxPixels
)
604 /****************************************************************************
606 * Function: VBE_getMaxScanlineLength
607 * Parameters: maxBytes - Maximum scanline width in bytes
608 * maxPixels - Maximum scanline width in pixels
609 * Returns: True if successful, false if function failed
611 ****************************************************************************/
617 PM_int86(0x10,®s
,®s
);
618 *maxBytes
= regs
.x
.bx
;
619 *maxPixels
= regs
.x
.cx
;
620 return regs
.x
.ax
== VBE_SUCCESS
;
623 ibool VBEAPI
VBE_setDisplayStart(int x
,int y
,ibool waitVRT
)
624 /****************************************************************************
626 * Function: VBE_setDisplayStart
627 * Parameters: x,y - Position of the first pixel to display
628 * waitVRT - True to wait for retrace, false if not
629 * Returns: True if function was successful.
631 * Description: Sets the new starting display position to implement
632 * hardware scrolling.
634 ****************************************************************************/
641 else regs
.x
.bx
= 0x00;
644 PM_int86(0x10,®s
,®s
);
645 return regs
.x
.ax
== VBE_SUCCESS
;
648 ibool VBEAPI
VBE_getDisplayStart(int *x
,int *y
)
649 /****************************************************************************
651 * Function: VBE_getDisplayStart
652 * Parameters: x,y - Place to store starting address value
653 * Returns: True if function was successful.
655 ****************************************************************************/
661 PM_int86(0x10,®s
,®s
);
664 return regs
.x
.ax
== VBE_SUCCESS
;
667 ibool VBEAPI
VBE_setDisplayStartAlt(ulong startAddr
,ibool waitVRT
)
668 /****************************************************************************
670 * Function: VBE_setDisplayStartAlt
671 * Parameters: startAddr - 32-bit starting address in display memory
672 * waitVRT - True to wait for vertical retrace, false if not
673 * Returns: True if function was successful, false if not supported.
675 * Description: Sets the new starting display position to the specified
676 * 32-bit display start address. Note that this function is
677 * different the the version above, since it takes a 32-bit
678 * byte offset in video memory as the starting address which
679 * gives the programmer maximum control over the stat address.
681 * NOTE: Requires VBE/Core 3.0
683 ****************************************************************************/
687 if (state
->VBEVersion
>= 0x300) {
689 regs
.x
.bx
= waitVRT
? 0x82 : 0x02;
690 regs
.e
.ecx
= startAddr
;
691 PM_int86(0x10,®s
,®s
);
692 return regs
.x
.ax
== VBE_SUCCESS
;
697 int VBEAPI
VBE_getDisplayStartStatus(void)
698 /****************************************************************************
700 * Function: VBE_getDisplayStartStatus
701 * Returns: 0 if last flip not occurred, 1 if already flipped
702 * -1 if not supported
704 * Description: Returns the status of the previous display start request.
705 * If this function is supported the programmer can implement
706 * hardware triple buffering using this function.
708 * NOTE: Requires VBE/Core 3.0
710 ****************************************************************************/
714 if (state
->VBEVersion
>= 0x300) {
717 PM_int86(0x10,®s
,®s
);
718 if (regs
.x
.ax
== VBE_SUCCESS
)
719 return (regs
.x
.cx
!= 0);
724 ibool VBEAPI
VBE_enableStereoMode(void)
725 /****************************************************************************
727 * Function: VBE_enableStereoMode
728 * Returns: True if stereo mode enabled, false if not supported.
730 * Description: Puts the system into hardware stereo mode for LC shutter
731 * glasses, where the display swaps between two display start
732 * addresses every vertical retrace.
734 * NOTE: Requires VBE/Core 3.0
736 ****************************************************************************/
740 if (state
->VBEVersion
>= 0x300) {
743 PM_int86(0x10,®s
,®s
);
744 return regs
.x
.ax
== VBE_SUCCESS
;
749 ibool VBEAPI
VBE_disableStereoMode(void)
750 /****************************************************************************
752 * Function: VBE_disableStereoMode
753 * Returns: True if stereo mode disabled, false if not supported.
755 * Description: Puts the system back into normal, non-stereo display mode
756 * after having stereo mode enabled.
758 * NOTE: Requires VBE/Core 3.0
760 ****************************************************************************/
764 if (state
->VBEVersion
>= 0x300) {
767 PM_int86(0x10,®s
,®s
);
768 return regs
.x
.ax
== VBE_SUCCESS
;
773 ibool VBEAPI
VBE_setStereoDisplayStart(ulong leftAddr
,ulong rightAddr
,
775 /****************************************************************************
777 * Function: VBE_setStereoDisplayStart
778 * Parameters: leftAddr - 32-bit start address for left image
779 * rightAddr - 32-bit start address for right image
780 * waitVRT - True to wait for vertical retrace, false if not
781 * Returns: True if function was successful, false if not supported.
783 * Description: Sets the new starting display position to the specified
784 * 32-bit display start address. Note that this function is
785 * different the the version above, since it takes a 32-bit
786 * byte offset in video memory as the starting address which
787 * gives the programmer maximum control over the stat address.
789 * NOTE: Requires VBE/Core 3.0
791 ****************************************************************************/
795 if (state
->VBEVersion
>= 0x300) {
797 regs
.x
.bx
= waitVRT
? 0x83 : 0x03;
798 regs
.e
.ecx
= leftAddr
;
799 regs
.e
.edx
= rightAddr
;
800 PM_int86(0x10,®s
,®s
);
801 return regs
.x
.ax
== VBE_SUCCESS
;
806 ulong VBEAPI
VBE_getClosestClock(ushort mode
,ulong pixelClock
)
807 /****************************************************************************
809 * Function: VBE_getClosestClock
810 * Parameters: mode - VBE mode to be used (include vbeLinearBuffer)
811 * pixelClock - Desired pixel clock
812 * Returns: Closest pixel clock to desired clock (-1 if not supported)
814 * Description: Calls the VBE/Core 3.0 interface to determine the closest
815 * pixel clock to the requested value. The BIOS will always
816 * search for a pixel clock that is no more than 1% below the
817 * requested clock or somewhere higher than the clock. If the
818 * clock is higher note that it may well be many Mhz higher
819 * that requested and the application will have to check that
820 * the returned value is suitable for it's needs. This function
821 * returns the actual pixel clock that will be programmed by
824 * Note that if the pixel clock will be used with a linear
825 * framebuffer mode, make sure you pass in the linear
826 * framebuffer flag to this function.
828 * NOTE: Requires VBE/Core 3.0
830 ****************************************************************************/
834 if (state
->VBEVersion
>= 0x300) {
837 regs
.e
.ecx
= pixelClock
;
839 PM_int86(0x10,®s
,®s
);
840 if (regs
.x
.ax
== VBE_SUCCESS
)
846 ibool VBEAPI
VBE_setDACWidth(int width
)
847 /****************************************************************************
849 * Function: VBE_setDACWidth
850 * Parameters: width - Width to set the DAC to
851 * Returns: True on success, false on failure
853 ****************************************************************************/
860 PM_int86(0x10,®s
,®s
);
861 return regs
.x
.ax
== VBE_SUCCESS
;
864 int VBEAPI
VBE_getDACWidth(void)
865 /****************************************************************************
867 * Function: VBE_getDACWidth
868 * Returns: Current width of the palette DAC
870 ****************************************************************************/
876 PM_int86(0x10,®s
,®s
);
877 if (regs
.x
.ax
!= VBE_SUCCESS
)
882 ibool VBEAPI
VBE_setPalette(int start
,int num
,VBE_palette
*pal
,ibool waitVRT
)
883 /****************************************************************************
885 * Function: VBE_setPalette
886 * Parameters: start - Starting palette index to program
887 * num - Number of palette indexes to program
888 * pal - Palette buffer containing values
889 * waitVRT - Wait for vertical retrace flag
890 * Returns: True on success, false on failure
892 * Description: Sets a block of palette registers by calling the VBE 2.0
893 * BIOS. This function will fail on VBE 1.2 implementations.
895 ****************************************************************************/
900 regs
.h
.bl
= waitVRT
? 0x80 : 0x00;
903 VBE_callESDI(®s
, pal
, sizeof(VBE_palette
) * num
);
904 return regs
.x
.ax
== VBE_SUCCESS
;
907 void * VBEAPI
VBE_getBankedPointer(VBE_modeInfo
*modeInfo
)
908 /****************************************************************************
910 * Function: VBE_getBankedPointer
911 * Parameters: modeInfo - Mode info block for video mode
912 * Returns: Selector to the linear framebuffer (0 on failure)
914 * Description: Returns a near pointer to the VGA framebuffer area.
916 ****************************************************************************/
918 /* We just map the pointer every time, since the pointer will always
919 * be in real mode memory, so we wont actually be mapping any real
922 * NOTE: We cannot currently map a near pointer to the banked frame
923 * buffer for Watcom Win386, so we create a 16:16 far pointer to
924 * the video memory. All the assembler code will render to the
925 * video memory by loading the selector rather than using a
928 ulong seg
= (ushort
)modeInfo
->WinASegment
;
931 return (void*)PM_getA0000Pointer();
933 return (void*)PM_mapPhysicalAddr(seg
<< 4,0xFFFF,true);
940 void * VBEAPI
VBE_getLinearPointer(VBE_modeInfo
*modeInfo
)
941 /****************************************************************************
943 * Function: VBE_getLinearPointer
944 * Parameters: modeInfo - Mode info block for video mode
945 * Returns: Selector to the linear framebuffer (0 on failure)
947 * Description: Returns a near pointer to the linear framebuffer for the video
950 ****************************************************************************/
952 static ulong physPtr
[MAX_LIN_PTRS
] = {0};
953 static void *linPtr
[MAX_LIN_PTRS
] = {0};
954 static int numPtrs
= 0;
957 /* Search for an already mapped pointer */
958 for (i
= 0; i
< numPtrs
; i
++) {
959 if (physPtr
[i
] == modeInfo
->PhysBasePtr
)
962 if (numPtrs
< MAX_LIN_PTRS
) {
963 physPtr
[numPtrs
] = modeInfo
->PhysBasePtr
;
964 linPtr
[numPtrs
] = PM_mapPhysicalAddr(modeInfo
->PhysBasePtr
,(state
->VBEMemory
* 1024L)-1,true);
965 return linPtr
[numPtrs
++];
970 static void InitPMCode(void)
971 /****************************************************************************
973 * Function: InitPMCode - 32 bit protected mode version
975 * Description: Finds the address of and relocates the protected mode
976 * code block from the VBE 2.0 into a local memory block. The
977 * memory block is allocated with malloc() and must be freed
978 * with VBE_freePMCode() after graphics processing is complete.
980 * Note that this buffer _must_ be recopied after each mode set,
981 * as the routines will change depending on the underlying
984 ****************************************************************************/
991 if (!state
->pmInfo
&& state
->VBEVersion
>= 0x200) {
994 PM_int86x(0x10,®s
,®s
,&sregs
);
995 if (regs
.x
.ax
!= VBE_SUCCESS
)
998 state
->pmInfo
= PM_mallocShared(regs
.x
.cx
);
1000 state
->pmInfo
= PM_malloc(regs
.x
.cx
);
1001 if (state
->pmInfo
== NULL
)
1003 state
->pmInfo32
= state
->pmInfo
;
1006 /* Relocate the block into our local data segment */
1007 code
= PM_mapRealPointer(sregs
.es
,regs
.x
.di
);
1008 memcpy(state
->pmInfo
,code
,pmLen
);
1010 /* Now do a sanity check on the information we recieve to ensure
1011 * that is is correct. Some BIOS return totally bogus information
1012 * in here (Matrox is one)! Under DOS this works OK, but under OS/2
1015 if (state
->pmInfo
->setWindow
>= pmLen
||
1016 state
->pmInfo
->setDisplayStart
>= pmLen
||
1017 state
->pmInfo
->setPalette
>= pmLen
||
1018 state
->pmInfo
->IOPrivInfo
>= pmLen
) {
1020 PM_freeShared(state
->pmInfo
);
1022 PM_free(state
->pmInfo
);
1023 state
->pmInfo32
= state
->pmInfo
= NULL
;
1027 /* Read the IO priveledge info and determine if we need to
1028 * pass a selector to MMIO registers to the bank switch code.
1029 * Since we no longer support selector allocation, we no longer
1030 * support this mechanism so we disable the protected mode
1031 * interface in this case.
1033 if (state
->pmInfo
->IOPrivInfo
&& !state
->MMIOSel
) {
1034 ushort
*p
= (ushort
*)((uchar
*)state
->pmInfo
+ state
->pmInfo
->IOPrivInfo
);
1035 while (*p
!= 0xFFFF)
1044 void * VBEAPI
VBE_getSetBank(void)
1045 /****************************************************************************
1047 * Function: VBE_getSetBank
1048 * Returns: Pointer to the 32 VBE 2.0 bit bank switching routine.
1050 ****************************************************************************/
1052 if (state
->VBEVersion
>= 0x200) {
1055 return (uchar
*)state
->pmInfo
+ state
->pmInfo
->setWindow
;
1060 void * VBEAPI
VBE_getSetDisplayStart(void)
1061 /****************************************************************************
1063 * Function: VBE_getSetDisplayStart
1064 * Returns: Pointer to the 32 VBE 2.0 bit CRT start address routine.
1066 ****************************************************************************/
1068 if (state
->VBEVersion
>= 0x200) {
1071 return (uchar
*)state
->pmInfo
+ state
->pmInfo
->setDisplayStart
;
1076 void * VBEAPI
VBE_getSetPalette(void)
1077 /****************************************************************************
1079 * Function: VBE_getSetPalette
1080 * Returns: Pointer to the 32 VBE 2.0 bit palette programming routine.
1082 ****************************************************************************/
1084 if (state
->VBEVersion
>= 0x200) {
1087 return (uchar
*)state
->pmInfo
+ state
->pmInfo
->setPalette
;
1092 void VBEAPI
VBE_freePMCode(void)
1093 /****************************************************************************
1095 * Function: VBE_freePMCode
1097 * Description: This routine frees the protected mode code blocks that
1098 * we copied from the VBE 2.0 interface. This routine must
1099 * be after you have finished graphics processing to free up
1100 * the memory occupied by the routines. This is necessary
1101 * because the PM info memory block must be re-copied after
1102 * every video mode set from the VBE 2.0 implementation.
1104 ****************************************************************************/
1106 if (state
->pmInfo
) {
1108 PM_freeShared(state
->pmInfo
);
1110 PM_free(state
->pmInfo
);
1111 state
->pmInfo
= NULL
;
1112 state
->pmInfo32
= NULL
;
1116 void VBEAPI
VBE_sharePMCode(void)
1117 /****************************************************************************
1119 * Function: VBE_sharePMCode
1121 * Description: Enables internal sharing of the PM code buffer for OS/2.
1123 ****************************************************************************/
1128 /* Set of code stubs used to build the final bank switch code */
1130 #define VBE20_adjustOffset 7
1132 static uchar VBE20A_bankFunc32_Start
[] = {
1133 0x53,0x51, /* push ebx,ecx */
1134 0x8B,0xD0, /* mov edx,eax */
1135 0x33,0xDB, /* xor ebx,ebx */
1136 0xB1,0x00, /* mov cl,0 */
1137 0xD2,0xE2, /* shl dl,cl */
1140 static uchar VBE20_bankFunc32_End
[] = {
1141 0x59,0x5B, /* pop ecx,ebx */
1144 static uchar bankFunc32
[100];
1146 #define copy(p,b,a) memcpy(b,a,sizeof(a)); (p) = (b) + sizeof(a)
1148 ibool VBEAPI
VBE_getBankFunc32(int *codeLen
,void **bankFunc
,int dualBanks
,
1150 /****************************************************************************
1152 * Function: VBE_getBankFunc32
1153 * Parameters: codeLen - Place to store length of code
1154 * bankFunc - Place to store pointer to bank switch code
1155 * dualBanks - True if dual banks are in effect
1156 * bankAdjust - Bank shift adjustment factor
1157 * Returns: True on success, false if not compatible.
1159 * Description: Creates a local 32 bit bank switch function from the
1160 * VBE 2.0 bank switch code that is compatible with the
1161 * virtual flat framebuffer devices (does not have a return
1162 * instruction at the end and takes the bank number in EAX
1163 * not EDX). Note that this 32 bit code cannot include int 10h
1164 * instructions, so we can only do this if we have VBE 2.0
1167 * Note that we need to know the length of the 32 bit
1168 * bank switch function, which the standard VBE 2.0 spec
1169 * does not provide. In order to support this we have
1170 * extended the VBE 2.0 state->pmInfo structure in UniVBE 5.2 in a
1171 * way to support this, and we hope that this will become
1172 * a VBE 2.0 ammendment.
1174 * Note also that we cannot run the linear framebuffer
1175 * emulation code with bank switching routines that require
1176 * a selector to the memory mapped registers passed in ES.
1178 ****************************************************************************/
1185 if (state
->VBEVersion
>= 0x200 && state
->pmInfo32
&& !state
->MMIOSel
) {
1186 code
= (uchar
*)state
->pmInfo32
+ state
->pmInfo32
->setWindow
;
1187 if (state
->pmInfo32
->extensionSig
== VBE20_EXT_SIG
)
1188 len
= state
->pmInfo32
->setWindowLen
-1;
1190 /* We are running on a system without the UniVBE 5.2 extension.
1191 * We do as best we can by scanning through the code for the
1192 * ret function to determine the length. This is not foolproof,
1193 * but is the best we can do.
1200 if ((len
+ sizeof(VBE20A_bankFunc32_Start
) + sizeof(VBE20_bankFunc32_End
)) > sizeof(bankFunc32
))
1201 PM_fatalError("32-bit bank switch function too long!");
1202 copy(p
,bankFunc32
,VBE20A_bankFunc32_Start
);
1205 copy(p
,p
,VBE20_bankFunc32_End
);
1206 *codeLen
= p
- bankFunc32
;
1207 bankFunc32
[VBE20_adjustOffset
] = (uchar
)bankAdjust
;
1208 *bankFunc
= bankFunc32
;