]> git.ipfire.org Git - people/ms/u-boot.git/blame - board/MAI/bios_emulator/scitech/src/common/vesavbe.c
* Code cleanup:
[people/ms/u-boot.git] / board / MAI / bios_emulator / scitech / src / common / vesavbe.c
CommitLineData
c7de829c
WD
1/****************************************************************************
2*
3* The SuperVGA Kit - UniVBE Software Development Kit
4*
5* ========================================================================
6*
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
11*
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.
16*
17* The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.
18*
19* The Initial Developer of the Original Code is SciTech Software, Inc.
20* All Rights Reserved.
21*
22* ========================================================================
23*
24* Language: ANSI C
25* Environment: IBM PC Real Mode and 16/32 bit Protected Mode.
26*
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.
31*
32* MUST be compiled in the LARGE or FLAT models.
33*
34****************************************************************************/
35
36#include <stdio.h>
37#include <stdlib.h>
38#include <string.h>
39#include "vesavbe.h"
40#include "pmapi.h"
41#include "drvlib/os/os.h"
42
43/*---------------------------- Global Variables ---------------------------*/
44
45#define VBE_SUCCESS 0x004F
46#define MAX_LIN_PTRS 10
47
48static uint VESABuf_len = 1024;/* Length of the VESABuf buffer */
49static ibool haveRiva128; /* True if we have a Riva128 */
50static VBE_state defState = {0}; /* Default state buffer */
51static VBE_state *state = &defState; /* Pointer to current buffer */
52static int VBE_shared = 0;
53#ifndef REALMODE
54static char localBuf[512]; /* Global PM string translate buf */
55#define MAX_LOCAL_BUF &localBuf[511]
56#endif
57
58/*----------------------------- Implementation ----------------------------*/
59
60/* static function in WinDirect for passing 32-bit registers to BIOS */
61int PMAPI WD_int386(int intno, RMREGS *in, RMREGS *out);
62
63void VBEAPI VBE_init(void)
64/****************************************************************************
65*
66* Function: VBE_init
67*
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.
72*
73****************************************************************************/
74{
75 if (!state->VESABuf_ptr) {
8bde7f77
WD
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!");
79 }
c7de829c
WD
80}
81
82void * VBEAPI VBE_getRMBuf(uint *len,uint *rseg,uint *roff)
83/****************************************************************************
84*
85* Function: VBE_getRMBuf
86*
87* Description: This function returns the location and length of the real
88* mode memory buffer for calling real mode functions.
89*
90****************************************************************************/
91{
92 *len = VESABuf_len;
93 *rseg = state->VESABuf_rseg;
94 *roff = state->VESABuf_roff;
95 return state->VESABuf_ptr;
96}
97
98void VBEAPI VBE_setStateBuffer(VBE_state *s)
99/****************************************************************************
100*
101* Function: VBE_setStateBuffer
102*
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.
107*
108****************************************************************************/
109{
110 state = s;
111}
112
113void VBEAPI VBE_callESDI(RMREGS *regs, void *buffer, int size)
114/****************************************************************************
115*
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
120*
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.
126*
127****************************************************************************/
128{
129 RMSREGS sregs;
130
131 if (!state->VESABuf_ptr)
8bde7f77 132 PM_fatalError("You *MUST* call VBE_init() before you can call the VESAVBE.C module!");
c7de829c
WD
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);
138}
139
140#ifndef REALMODE
141static char *VBE_copyStrToLocal(char *p,char *realPtr,char *max)
142/****************************************************************************
143*
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
148*
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
152* string.
153*
154****************************************************************************/
155{
156 uchar *v;
157
158 v = PM_mapRealPointer((uint)((ulong)realPtr >> 16), (uint)((ulong)realPtr & 0xFFFF));
159 while (*v != 0 && p < max)
8bde7f77 160 *p++ = *v++;
c7de829c
WD
161 *p++ = 0;
162 return p;
163}
164
165static void VBE_copyShortToLocal(ushort *p,ushort *realPtr)
166/****************************************************************************
167*
168* Function: VBE_copyShortToLocal
169* Parameters: p - Flat model buffer to copy to
170* realPtr - Real mode pointer to copy
171*
172* Description: Copies the mode table from real mode memory to the flat
173* model buffer.
174*
175****************************************************************************/
176{
177 ushort *v;
178
179 v = PM_mapRealPointer((uint)((ulong)realPtr >> 16),(uint)((ulong)realPtr & 0xFFFF));
180 while (*v != 0xFFFF)
8bde7f77 181 *p++ = *v++;
c7de829c
WD
182 *p = 0xFFFF;
183}
184#endif
185
186int VBEAPI VBE_detectEXT(VBE_vgaInfo *vgaInfo,ibool forceUniVBE)
187/****************************************************************************
188*
189* Function: VBE_detect
190* Parameters: vgaInfo - Place to store the VGA information block
191* Returns: VBE version number, or 0 if not detected.
192*
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.
196*
197****************************************************************************/
198{
199 RMREGS regs;
200
201 regs.x.ax = 0x4F00; /* Get SuperVGA information */
202 if (forceUniVBE) {
8bde7f77
WD
203 regs.x.bx = 0x1234;
204 regs.x.cx = 0x4321;
205 }
c7de829c 206 else {
8bde7f77
WD
207 regs.x.bx = 0;
208 regs.x.cx = 0;
209 }
c7de829c
WD
210 strncpy(vgaInfo->VESASignature,"VBE2",4);
211 VBE_callESDI(&regs, vgaInfo, sizeof(*vgaInfo));
212 if (regs.x.ax != VBE_SUCCESS)
8bde7f77 213 return 0;
c7de829c 214 if (strncmp(vgaInfo->VESASignature,"VESA",4) != 0)
8bde7f77 215 return 0;
c7de829c
WD
216
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.
220 */
221 if (vgaInfo->VESAVersion >= 0x200 && vgaInfo->OemVendorNamePtr == 0)
8bde7f77 222 vgaInfo->VESAVersion = 0x102;
c7de829c
WD
223#ifndef REALMODE
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.
228 */
229 {
8bde7f77 230 char *p,*p2;
c7de829c
WD
231 p2 = VBE_copyStrToLocal(localBuf,vgaInfo->OemStringPtr,MAX_LOCAL_BUF);
232 vgaInfo->OemStringPtr = localBuf;
233 if (vgaInfo->VESAVersion >= 0x200) {
8bde7f77
WD
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;
242 }
c7de829c 243 else {
8bde7f77
WD
244 VBE_copyShortToLocal((ushort*)p2,vgaInfo->VideoModePtr);
245 vgaInfo->VideoModePtr = (ushort*)p2;
246 }
c7de829c
WD
247 }
248#endif
249 state->VBEMemory = vgaInfo->TotalMemory * 64;
250
251 /* Check for Riva128 based cards since they have broken triple buffering
252 * and stereo support.
253 */
254 haveRiva128 = false;
255 if (vgaInfo->VESAVersion >= 0x300 &&
8bde7f77
WD
256 (strstr(vgaInfo->OemStringPtr,"NVidia") != NULL ||
257 strstr(vgaInfo->OemStringPtr,"Riva") != NULL)) {
258 haveRiva128 = true;
259 }
c7de829c
WD
260
261 /* Check for Matrox G400 cards which claim to be VBE 3.0
262 * compliant yet they don't implement the refresh rate control
263 * functions.
264 */
265 if (vgaInfo->VESAVersion >= 0x300 && (strcmp(vgaInfo->OemProductNamePtr,"Matrox G400") == 0))
8bde7f77 266 vgaInfo->VESAVersion = 0x200;
c7de829c
WD
267 return (state->VBEVersion = vgaInfo->VESAVersion);
268}
269
270int VBEAPI VBE_detect(VBE_vgaInfo *vgaInfo)
271/****************************************************************************
272*
273* Function: VBE_detect
274* Parameters: vgaInfo - Place to store the VGA information block
275* Returns: VBE version number, or 0 if not detected.
276*
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.
280*
281****************************************************************************/
282{
283 return VBE_detectEXT(vgaInfo,false);
284}
285
286ibool VBEAPI VBE_getModeInfo(int mode,VBE_modeInfo *modeInfo)
287/****************************************************************************
288*
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.
293*
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.
298*
299****************************************************************************/
300{
301 RMREGS regs;
302 int bits;
303
304 regs.x.ax = 0x4F01; /* Get mode information */
305 regs.x.cx = (ushort)mode;
306 VBE_callESDI(&regs, modeInfo, sizeof(*modeInfo));
307 if (regs.x.ax != VBE_SUCCESS)
8bde7f77 308 return false;
c7de829c 309 if ((modeInfo->ModeAttributes & vbeMdAvailable) == 0)
8bde7f77 310 return false;
c7de829c
WD
311
312 /* Map out triple buffer and stereo flags for NVidia Riva128
313 * chips.
314 */
315 if (haveRiva128) {
8bde7f77
WD
316 modeInfo->ModeAttributes &= ~vbeMdTripleBuf;
317 modeInfo->ModeAttributes &= ~vbeMdStereo;
318 }
c7de829c
WD
319
320 /* Support old style RGB definitions for VBE 1.1 BIOSes */
321 bits = modeInfo->BitsPerPixel;
322 if (modeInfo->MemoryModel == vbeMemPK && bits > 8) {
8bde7f77
WD
323 modeInfo->MemoryModel = vbeMemRGB;
324 switch (bits) {
325 case 15:
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;
334 break;
335 case 16:
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;
344 break;
345 case 24:
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;
354 break;
355 }
356 }
c7de829c
WD
357
358 /* Convert the 32k direct color modes of VBE 1.2+ BIOSes to
359 * be recognised as 15 bits per pixel modes.
360 */
361 if (bits == 16 && modeInfo->RsvdMaskSize == 1)
8bde7f77 362 modeInfo->BitsPerPixel = 15;
c7de829c
WD
363
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.
367 */
368 if (bits == 15 && (modeInfo->RsvdMaskSize != 1 || modeInfo->RsvdFieldPosition != 15)) {
8bde7f77
WD
369 modeInfo->RsvdMaskSize = 1;
370 modeInfo->RsvdFieldPosition = 15;
371 }
c7de829c
WD
372 return true;
373}
374
375long VBEAPI VBE_getPageSize(VBE_modeInfo *mi)
376/****************************************************************************
377*
378* Function: VBE_getPageSize
379* Parameters: mi - Pointer to mode information block
380* Returns: Caculated page size in bytes rounded to correct boundary
381*
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).
387*
388****************************************************************************/
389{
390 long size;
391
392 size = (long)mi->BytesPerScanLine * (long)mi->YResolution;
393 if (mi->BitsPerPixel == 4) {
8bde7f77
WD
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.
396 */
397
398 size = (size + 0x1FFFL) & 0xFFFFE000L;
399 if (size != 0x2000) {
400 size = (size + 0x3FFFL) & 0xFFFFC000L;
401 if (size != 0x4000) {
402 size = (size + 0x7FFFL) & 0xFFFF8000L;
403 if (size != 0x8000)
404 size = (size + 0xFFFFL) & 0xFFFF0000L;
405 }
406 }
407 }
c7de829c
WD
408 else size = (size + 0xFFFFL) & 0xFFFF0000L;
409 return size;
410}
411
412ibool VBEAPI VBE_setVideoModeExt(int mode,VBE_CRTCInfo *crtc)
413/****************************************************************************
414*
415* Function: VBE_setVideoModeExt
416* Parameters: mode - SuperVGA video mode to set.
417* Returns: True if the mode was set, false if not.
418*
419* Description: Attempts to set the specified video mode. This version
420* includes support for the VBE/Core 3.0 refresh rate control
421* mechanism.
422*
423****************************************************************************/
424{
425 RMREGS regs;
426
427 if (state->VBEVersion < 0x200 && mode < 0x100) {
8bde7f77
WD
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.
431 */
432 regs.h.al = (ushort)mode;
433 regs.h.ah = 0;
434 PM_int86(0x10,&regs,&regs);
435 }
c7de829c 436 else {
8bde7f77
WD
437 if (state->VBEVersion < 0x300 && (mode & vbeRefreshCtrl))
438 return false;
439 regs.x.ax = 0x4F02;
440 regs.x.bx = (ushort)mode;
441 if ((mode & vbeRefreshCtrl) && crtc)
442 VBE_callESDI(&regs, crtc, sizeof(*crtc));
443 else
444 PM_int86(0x10,&regs,&regs);
445 if (regs.x.ax != VBE_SUCCESS)
446 return false;
447 }
c7de829c
WD
448 return true;
449}
450
451ibool VBEAPI VBE_setVideoMode(int mode)
452/****************************************************************************
453*
454* Function: VBE_setVideoMode
455* Parameters: mode - SuperVGA video mode to set.
456* Returns: True if the mode was set, false if not.
457*
458* Description: Attempts to set the specified video mode.
459*
460****************************************************************************/
461{
462 return VBE_setVideoModeExt(mode,NULL);
463}
464
465int VBEAPI VBE_getVideoMode(void)
466/****************************************************************************
467*
468* Function: VBE_getVideoMode
469* Returns: Current video mode
470*
471****************************************************************************/
472{
473 RMREGS regs;
474
475 regs.x.ax = 0x4F03;
476 PM_int86(0x10,&regs,&regs);
477 if (regs.x.ax != VBE_SUCCESS)
8bde7f77 478 return -1;
c7de829c
WD
479 return regs.x.bx;
480}
481
482ibool VBEAPI VBE_setBank(int window,int bank)
483/****************************************************************************
484*
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.
489*
490****************************************************************************/
491{
492 RMREGS regs;
493
494 regs.x.ax = 0x4F05;
495 regs.h.bh = 0;
496 regs.h.bl = window;
497 regs.x.dx = bank;
498 PM_int86(0x10,&regs,&regs);
499 return regs.x.ax == VBE_SUCCESS;
500}
501
502int VBEAPI VBE_getBank(int window)
503/****************************************************************************
504*
505* Function: VBE_setBank
506* Parameters: window - Window to read
507* Returns: Bank number for the window (-1 on failure)
508*
509****************************************************************************/
510{
511 RMREGS regs;
512
513 regs.x.ax = 0x4F05;
514 regs.h.bh = 1;
515 regs.h.bl = window;
516 PM_int86(0x10,&regs,&regs);
517 if (regs.x.ax != VBE_SUCCESS)
8bde7f77 518 return -1;
c7de829c
WD
519 return regs.x.dx;
520}
521
522ibool VBEAPI VBE_setPixelsPerLine(int pixelsPerLine,int *newBytes,
523 int *newPixels,int *maxScanlines)
524/****************************************************************************
525*
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
532*
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).
537*
538****************************************************************************/
539{
540 RMREGS regs;
541
542 regs.x.ax = 0x4F06;
543 regs.h.bl = 0;
544 regs.x.cx = pixelsPerLine;
545 PM_int86(0x10,&regs,&regs);
546 *newBytes = regs.x.bx;
547 *newPixels = regs.x.cx;
548 *maxScanlines = regs.x.dx;
549 return regs.x.ax == VBE_SUCCESS;
550}
551
552ibool VBEAPI VBE_setBytesPerLine(int bytesPerLine,int *newBytes,
553 int *newPixels,int *maxScanlines)
554/****************************************************************************
555*
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
562*
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).
565*
566****************************************************************************/
567{
568 RMREGS regs;
569
570 regs.x.ax = 0x4F06;
571 regs.h.bl = 2;
572 regs.x.cx = bytesPerLine;
573 PM_int86(0x10,&regs,&regs);
574 *newBytes = regs.x.bx;
575 *newPixels = regs.x.cx;
576 *maxScanlines = regs.x.dx;
577 return regs.x.ax == VBE_SUCCESS;
578}
579
580ibool VBEAPI VBE_getScanlineLength(int *bytesPerLine,int *pixelsPerLine,
581 int *maxScanlines)
582/****************************************************************************
583*
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
589*
590****************************************************************************/
591{
592 RMREGS regs;
593
594 regs.x.ax = 0x4F06;
595 regs.h.bl = 1;
596 PM_int86(0x10,&regs,&regs);
597 *bytesPerLine = regs.x.bx;
598 *pixelsPerLine = regs.x.cx;
599 *maxScanlines = regs.x.dx;
600 return regs.x.ax == VBE_SUCCESS;
601}
602
603ibool VBEAPI VBE_getMaxScanlineLength(int *maxBytes,int *maxPixels)
604/****************************************************************************
605*
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
610*
611****************************************************************************/
612{
613 RMREGS regs;
614
615 regs.x.ax = 0x4F06;
616 regs.h.bl = 3;
617 PM_int86(0x10,&regs,&regs);
618 *maxBytes = regs.x.bx;
619 *maxPixels = regs.x.cx;
620 return regs.x.ax == VBE_SUCCESS;
621}
622
623ibool VBEAPI VBE_setDisplayStart(int x,int y,ibool waitVRT)
624/****************************************************************************
625*
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.
630*
631* Description: Sets the new starting display position to implement
632* hardware scrolling.
633*
634****************************************************************************/
635{
636 RMREGS regs;
637
638 regs.x.ax = 0x4F07;
639 if (waitVRT)
8bde7f77 640 regs.x.bx = 0x80;
c7de829c
WD
641 else regs.x.bx = 0x00;
642 regs.x.cx = x;
643 regs.x.dx = y;
644 PM_int86(0x10,&regs,&regs);
645 return regs.x.ax == VBE_SUCCESS;
646}
647
648ibool VBEAPI VBE_getDisplayStart(int *x,int *y)
649/****************************************************************************
650*
651* Function: VBE_getDisplayStart
652* Parameters: x,y - Place to store starting address value
653* Returns: True if function was successful.
654*
655****************************************************************************/
656{
657 RMREGS regs;
658
659 regs.x.ax = 0x4F07;
660 regs.x.bx = 0x01;
661 PM_int86(0x10,&regs,&regs);
662 *x = regs.x.cx;
663 *y = regs.x.dx;
664 return regs.x.ax == VBE_SUCCESS;
665}
666
667ibool VBEAPI VBE_setDisplayStartAlt(ulong startAddr,ibool waitVRT)
668/****************************************************************************
669*
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.
674*
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.
680*
681* NOTE: Requires VBE/Core 3.0
682*
683****************************************************************************/
684{
685 RMREGS regs;
686
687 if (state->VBEVersion >= 0x300) {
8bde7f77
WD
688 regs.x.ax = 0x4F07;
689 regs.x.bx = waitVRT ? 0x82 : 0x02;
690 regs.e.ecx = startAddr;
691 PM_int86(0x10,&regs,&regs);
692 return regs.x.ax == VBE_SUCCESS;
693 }
c7de829c
WD
694 return false;
695}
696
697int VBEAPI VBE_getDisplayStartStatus(void)
698/****************************************************************************
699*
700* Function: VBE_getDisplayStartStatus
701* Returns: 0 if last flip not occurred, 1 if already flipped
702* -1 if not supported
703*
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.
707*
708* NOTE: Requires VBE/Core 3.0
709*
710****************************************************************************/
711{
712 RMREGS regs;
713
714 if (state->VBEVersion >= 0x300) {
8bde7f77
WD
715 regs.x.ax = 0x4F07;
716 regs.x.bx = 0x0004;
717 PM_int86(0x10,&regs,&regs);
718 if (regs.x.ax == VBE_SUCCESS)
719 return (regs.x.cx != 0);
720 }
c7de829c
WD
721 return -1;
722}
723
724ibool VBEAPI VBE_enableStereoMode(void)
725/****************************************************************************
726*
727* Function: VBE_enableStereoMode
728* Returns: True if stereo mode enabled, false if not supported.
729*
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.
733*
734* NOTE: Requires VBE/Core 3.0
735*
736****************************************************************************/
737{
738 RMREGS regs;
739
740 if (state->VBEVersion >= 0x300) {
8bde7f77
WD
741 regs.x.ax = 0x4F07;
742 regs.x.bx = 0x0005;
743 PM_int86(0x10,&regs,&regs);
744 return regs.x.ax == VBE_SUCCESS;
745 }
c7de829c
WD
746 return false;
747}
748
749ibool VBEAPI VBE_disableStereoMode(void)
750/****************************************************************************
751*
752* Function: VBE_disableStereoMode
753* Returns: True if stereo mode disabled, false if not supported.
754*
755* Description: Puts the system back into normal, non-stereo display mode
756* after having stereo mode enabled.
757*
758* NOTE: Requires VBE/Core 3.0
759*
760****************************************************************************/
761{
762 RMREGS regs;
763
764 if (state->VBEVersion >= 0x300) {
8bde7f77
WD
765 regs.x.ax = 0x4F07;
766 regs.x.bx = 0x0006;
767 PM_int86(0x10,&regs,&regs);
768 return regs.x.ax == VBE_SUCCESS;
769 }
c7de829c
WD
770 return false;
771}
772
773ibool VBEAPI VBE_setStereoDisplayStart(ulong leftAddr,ulong rightAddr,
774 ibool waitVRT)
775/****************************************************************************
776*
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.
782*
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.
788*
789* NOTE: Requires VBE/Core 3.0
790*
791****************************************************************************/
792{
793 RMREGS regs;
794
795 if (state->VBEVersion >= 0x300) {
8bde7f77
WD
796 regs.x.ax = 0x4F07;
797 regs.x.bx = waitVRT ? 0x83 : 0x03;
798 regs.e.ecx = leftAddr;
799 regs.e.edx = rightAddr;
800 PM_int86(0x10,&regs,&regs);
801 return regs.x.ax == VBE_SUCCESS;
802 }
c7de829c
WD
803 return false;
804}
805
806ulong VBEAPI VBE_getClosestClock(ushort mode,ulong pixelClock)
807/****************************************************************************
808*
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)
813*
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
822* the hardware.
823*
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.
827*
828* NOTE: Requires VBE/Core 3.0
829*
830****************************************************************************/
831{
832 RMREGS regs;
833
834 if (state->VBEVersion >= 0x300) {
8bde7f77
WD
835 regs.x.ax = 0x4F0B;
836 regs.h.bl = 0x00;
837 regs.e.ecx = pixelClock;
838 regs.x.dx = mode;
839 PM_int86(0x10,&regs,&regs);
840 if (regs.x.ax == VBE_SUCCESS)
841 return regs.e.ecx;
842 }
c7de829c
WD
843 return -1;
844}
845
846ibool VBEAPI VBE_setDACWidth(int width)
847/****************************************************************************
848*
849* Function: VBE_setDACWidth
850* Parameters: width - Width to set the DAC to
851* Returns: True on success, false on failure
852*
853****************************************************************************/
854{
855 RMREGS regs;
856
857 regs.x.ax = 0x4F08;
858 regs.h.bl = 0x00;
859 regs.h.bh = width;
860 PM_int86(0x10,&regs,&regs);
861 return regs.x.ax == VBE_SUCCESS;
862}
863
864int VBEAPI VBE_getDACWidth(void)
865/****************************************************************************
866*
867* Function: VBE_getDACWidth
868* Returns: Current width of the palette DAC
869*
870****************************************************************************/
871{
872 RMREGS regs;
873
874 regs.x.ax = 0x4F08;
875 regs.h.bl = 0x01;
876 PM_int86(0x10,&regs,&regs);
877 if (regs.x.ax != VBE_SUCCESS)
8bde7f77 878 return -1;
c7de829c
WD
879 return regs.h.bh;
880}
881
882ibool VBEAPI VBE_setPalette(int start,int num,VBE_palette *pal,ibool waitVRT)
883/****************************************************************************
884*
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
891*
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.
894*
895****************************************************************************/
896{
897 RMREGS regs;
898
899 regs.x.ax = 0x4F09;
900 regs.h.bl = waitVRT ? 0x80 : 0x00;
901 regs.x.cx = num;
902 regs.x.dx = start;
903 VBE_callESDI(&regs, pal, sizeof(VBE_palette) * num);
904 return regs.x.ax == VBE_SUCCESS;
905}
906
907void * VBEAPI VBE_getBankedPointer(VBE_modeInfo *modeInfo)
908/****************************************************************************
909*
910* Function: VBE_getBankedPointer
911* Parameters: modeInfo - Mode info block for video mode
912* Returns: Selector to the linear framebuffer (0 on failure)
913*
914* Description: Returns a near pointer to the VGA framebuffer area.
915*
916****************************************************************************/
917{
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
920 * memory.
921 *
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
926 * near pointer.
927 */
928 ulong seg = (ushort)modeInfo->WinASegment;
929 if (seg != 0) {
8bde7f77
WD
930 if (seg == 0xA000)
931 return (void*)PM_getA0000Pointer();
932 else
933 return (void*)PM_mapPhysicalAddr(seg << 4,0xFFFF,true);
934 }
c7de829c
WD
935 return NULL;
936}
937
938#ifndef REALMODE
939
940void * VBEAPI VBE_getLinearPointer(VBE_modeInfo *modeInfo)
941/****************************************************************************
942*
943* Function: VBE_getLinearPointer
944* Parameters: modeInfo - Mode info block for video mode
945* Returns: Selector to the linear framebuffer (0 on failure)
946*
947* Description: Returns a near pointer to the linear framebuffer for the video
948* mode.
949*
950****************************************************************************/
951{
952 static ulong physPtr[MAX_LIN_PTRS] = {0};
953 static void *linPtr[MAX_LIN_PTRS] = {0};
954 static int numPtrs = 0;
955 int i;
956
957 /* Search for an already mapped pointer */
958 for (i = 0; i < numPtrs; i++) {
8bde7f77
WD
959 if (physPtr[i] == modeInfo->PhysBasePtr)
960 return linPtr[i];
961 }
c7de829c 962 if (numPtrs < MAX_LIN_PTRS) {
8bde7f77
WD
963 physPtr[numPtrs] = modeInfo->PhysBasePtr;
964 linPtr[numPtrs] = PM_mapPhysicalAddr(modeInfo->PhysBasePtr,(state->VBEMemory * 1024L)-1,true);
965 return linPtr[numPtrs++];
966 }
c7de829c
WD
967 return NULL;
968}
969
970static void InitPMCode(void)
971/****************************************************************************
972*
973* Function: InitPMCode - 32 bit protected mode version
974*
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.
979*
980* Note that this buffer _must_ be recopied after each mode set,
981* as the routines will change depending on the underlying
982* video mode.
983*
984****************************************************************************/
985{
986 RMREGS regs;
987 RMSREGS sregs;
988 uchar *code;
989 int pmLen;
990
991 if (!state->pmInfo && state->VBEVersion >= 0x200) {
8bde7f77
WD
992 regs.x.ax = 0x4F0A;
993 regs.x.bx = 0;
994 PM_int86x(0x10,&regs,&regs,&sregs);
995 if (regs.x.ax != VBE_SUCCESS)
996 return;
997 if (VBE_shared)
998 state->pmInfo = PM_mallocShared(regs.x.cx);
999 else
1000 state->pmInfo = PM_malloc(regs.x.cx);
1001 if (state->pmInfo == NULL)
1002 return;
1003 state->pmInfo32 = state->pmInfo;
1004 pmLen = regs.x.cx;
1005
1006 /* Relocate the block into our local data segment */
1007 code = PM_mapRealPointer(sregs.es,regs.x.di);
1008 memcpy(state->pmInfo,code,pmLen);
1009
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
1013 * we are screwed.
1014 */
1015 if (state->pmInfo->setWindow >= pmLen ||
1016 state->pmInfo->setDisplayStart >= pmLen ||
1017 state->pmInfo->setPalette >= pmLen ||
1018 state->pmInfo->IOPrivInfo >= pmLen) {
1019 if (VBE_shared)
1020 PM_freeShared(state->pmInfo);
1021 else
1022 PM_free(state->pmInfo);
1023 state->pmInfo32 = state->pmInfo = NULL;
1024 return;
1025 }
1026
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.
1032 */
1033 if (state->pmInfo->IOPrivInfo && !state->MMIOSel) {
1034 ushort *p = (ushort*)((uchar*)state->pmInfo + state->pmInfo->IOPrivInfo);
1035 while (*p != 0xFFFF)
1036 p++;
1037 p++;
1038 if (*p != 0xFFFF)
1039 VBE_freePMCode();
1040 }
1041 }
c7de829c
WD
1042}
1043
1044void * VBEAPI VBE_getSetBank(void)
1045/****************************************************************************
1046*
1047* Function: VBE_getSetBank
1048* Returns: Pointer to the 32 VBE 2.0 bit bank switching routine.
1049*
1050****************************************************************************/
1051{
1052 if (state->VBEVersion >= 0x200) {
8bde7f77
WD
1053 InitPMCode();
1054 if (state->pmInfo)
1055 return (uchar*)state->pmInfo + state->pmInfo->setWindow;
1056 }
c7de829c
WD
1057 return NULL;
1058}
1059
1060void * VBEAPI VBE_getSetDisplayStart(void)
1061/****************************************************************************
1062*
1063* Function: VBE_getSetDisplayStart
1064* Returns: Pointer to the 32 VBE 2.0 bit CRT start address routine.
1065*
1066****************************************************************************/
1067{
1068 if (state->VBEVersion >= 0x200) {
8bde7f77
WD
1069 InitPMCode();
1070 if (state->pmInfo)
1071 return (uchar*)state->pmInfo + state->pmInfo->setDisplayStart;
1072 }
c7de829c
WD
1073 return NULL;
1074}
1075
1076void * VBEAPI VBE_getSetPalette(void)
1077/****************************************************************************
1078*
1079* Function: VBE_getSetPalette
1080* Returns: Pointer to the 32 VBE 2.0 bit palette programming routine.
1081*
1082****************************************************************************/
1083{
1084 if (state->VBEVersion >= 0x200) {
8bde7f77
WD
1085 InitPMCode();
1086 if (state->pmInfo)
1087 return (uchar*)state->pmInfo + state->pmInfo->setPalette;
1088 }
c7de829c
WD
1089 return NULL;
1090}
1091
1092void VBEAPI VBE_freePMCode(void)
1093/****************************************************************************
1094*
1095* Function: VBE_freePMCode
1096*
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.
1103*
1104****************************************************************************/
1105{
1106 if (state->pmInfo) {
8bde7f77
WD
1107 if (VBE_shared)
1108 PM_freeShared(state->pmInfo);
1109 else
1110 PM_free(state->pmInfo);
1111 state->pmInfo = NULL;
1112 state->pmInfo32 = NULL;
1113 }
c7de829c
WD
1114}
1115
1116void VBEAPI VBE_sharePMCode(void)
1117/****************************************************************************
1118*
1119* Function: VBE_sharePMCode
1120*
1121* Description: Enables internal sharing of the PM code buffer for OS/2.
1122*
1123****************************************************************************/
1124{
1125 VBE_shared = true;
1126}
1127
1128/* Set of code stubs used to build the final bank switch code */
1129
1130#define VBE20_adjustOffset 7
1131
1132static 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 */
1138 };
1139
1140static uchar VBE20_bankFunc32_End[] = {
1141 0x59,0x5B, /* pop ecx,ebx */
1142 };
1143
1144static uchar bankFunc32[100];
1145
1146#define copy(p,b,a) memcpy(b,a,sizeof(a)); (p) = (b) + sizeof(a)
1147
1148ibool VBEAPI VBE_getBankFunc32(int *codeLen,void **bankFunc,int dualBanks,
1149 int bankAdjust)
1150/****************************************************************************
1151*
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.
1158*
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
1165* or later.
1166*
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.
1173*
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.
1177*
1178****************************************************************************/
1179{
1180 int len;
1181 uchar *code;
1182 uchar *p;
1183
1184 InitPMCode();
1185 if (state->VBEVersion >= 0x200 && state->pmInfo32 && !state->MMIOSel) {
8bde7f77
WD
1186 code = (uchar*)state->pmInfo32 + state->pmInfo32->setWindow;
1187 if (state->pmInfo32->extensionSig == VBE20_EXT_SIG)
1188 len = state->pmInfo32->setWindowLen-1;
1189 else {
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.
1194 */
1195 p = code;
1196 while (*p != 0xC3)
1197 p++;
1198 len = p - code;
1199 }
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);
1203 memcpy(p,code,len);
1204 p += len;
1205 copy(p,p,VBE20_bankFunc32_End);
1206 *codeLen = p - bankFunc32;
1207 bankFunc32[VBE20_adjustOffset] = (uchar)bankAdjust;
1208 *bankFunc = bankFunc32;
1209 return true;
1210 }
c7de829c
WD
1211 return false;
1212}
1213
1214#endif