1 /**
2  ** u_vesa.c ---- interface utility functions to VESA BIOS inquiry calls
3  **
4  ** Copyright (c) 1995 Csaba Biegl, 820 Stirrup Dr, Nashville, TN 37221
5  ** [e-mail: csaba@vuse.vanderbilt.edu]
6  **
7  ** This file is part of the GRX graphics library.
8  **
9  ** The GRX graphics library is free software; you can redistribute it
10  ** and/or modify it under some conditions; see the "copying.grx" file
11  ** for details.
12  **
13  ** This library is distributed in the hope that it will be useful,
14  ** but WITHOUT ANY WARRANTY; without even the implied warranty of
15  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16  **
17  ** Contributions by: (See "doc/credits.doc" for details)
18  ** Hartmut Schirmer (hsc@xaphod.techfak.uni-kiel.d400.de)
19  **/
20 
21 #include "libgrx.h"
22 #include "allocate.h"
23 #include "vesa.h"
24 #include "mempeek.h"
25 #include "memfill.h"
26 #include "int86.h"
27 
28 #ifndef IREG_AX
29 
_GrViDrvVESAgetVGAinfo(VESAvgaInfoBlock * ib)30 int _GrViDrvVESAgetVGAinfo(VESAvgaInfoBlock *ib)
31 {
32 	return(FALSE);
33 }
_GrViDrvVESAgetModeInfo(int mode,VESAmodeInfoBlock * ib)34 int _GrViDrvVESAgetModeInfo(int mode,VESAmodeInfoBlock *ib)
35 {
36 	return(FALSE);
37 }
38 
_GrViDrvVESAgetPMinfo(void)39 VESApmInfoBlock * _GrViDrvVESAgetPMinfo(void)
40 {
41 	return(NULL);
42 }
43 
44 #else
45 
46 #if defined(__WATCOMC__) && defined(__386__)
47 #define FAR _far
48 #else
49 #define FAR far
50 #endif /* __WATCOMC__ && __386__*/
51 
_GrViDrvVESAgetVGAinfo(VESAvgaInfoBlock * ib)52 int _GrViDrvVESAgetVGAinfo(VESAvgaInfoBlock *ib)
53 {
54 	static char  *nmcopy = NULL;
55 	static short *mdcopy = NULL;
56 	Int86Regs regs;
57 	short FAR *mp;
58 	short *modes;
59 	char FAR *p1;
60 	char *p2;
61 	int  ii;
62 	DECLARE_XFER_BUFFER(1000);
63 	/*
64 	 * copy VBE 2.0 tag into XFER buffer
65 	 */
66 	setup_far_selector(LINP_SEL(XFER_BUFFER));
67 	p1 = (char FAR *)LINP_PTR(XFER_BUFFER);
68 	poke_b_f(p1,'V'); ++p1;
69 	poke_b_f(p1,'B'); ++p1;
70 	poke_b_f(p1,'E'); ++p1;
71 	poke_b_f(p1,'2'); ++p1;
72 	/*
73 	 * set up registers and call interrupt
74 	 */
75 	sttzero(&regs);
76 	IREG_AX(regs) = VESA_FUNC + VESA_VGA_INFO;
77 	IREG_ES(regs) = FP_SEG(XFER_BUFFER);
78 	IREG_DI(regs) = FP_OFF(XFER_BUFFER);
79 	int10x(&regs);
80 	if(IREG_AX(regs) != VESA_SUCCESS) {
81 		DELETE_XFER_BUFFER;
82 		return(FALSE);
83 	}
84 	/*
85 	 * copy VESA info block into accessible memory
86 	 */
87 	setup_far_selector(LINP_SEL(XFER_BUFFER));
88 	p1 = (char FAR *)LINP_PTR(XFER_BUFFER);
89 	p2 = (char *)ib;
90 	for(ii = sizeof(*ib); --ii >= 0; p1++,p2++) *p2 = peek_b_f(p1);
91 
92 	if ( ib->VESAsignature[0] != 'V' ||
93 	     ib->VESAsignature[1] != 'E' ||
94 	     ib->VESAsignature[2] != 'S' ||
95 	     ib->VESAsignature[3] != 'A'  ) {
96 	  DELETE_XFER_BUFFER;
97 	  return(FALSE);
98 	}
99 	/*
100 	 * allocate space and copy mode list into accessible memory
101 	 */
102 	mp = LINP_PTR(MK_FP(FP86_SEG(ib->VideoModePtr),FP86_OFF(ib->VideoModePtr)));
103 	p1 = (char FAR *)mp;
104 	for(ii = 1; (short)peek_w_f(mp) != (short)(-1); mp++,ii++);
105 	modes = mdcopy = realloc(mdcopy,ii * sizeof(short));
106 	if(!modes) { DELETE_XFER_BUFFER; return(FALSE); }
107 	ib->VideoModePtr = modes;
108 	mp = (short far *)p1;
109 	for( ; --ii >= 0; mp++,modes++) *modes = peek_w_f(mp);
110 	/*
111 	 * allocate space and copy ID string into accessible memory
112 	 */
113 	p1 = LINP_PTR(MK_FP(FP86_SEG(ib->OEMstringPtr),FP86_OFF(ib->OEMstringPtr)));
114 	mp = (short FAR *)p1;
115 	for(ii = 1; (char)peek_b_f(p1) != (char)(0); p1++,ii++);
116 	p2 = nmcopy = realloc(nmcopy,ii * sizeof(char));
117 	if(!p2) { DELETE_XFER_BUFFER; return(FALSE); }
118 	ib->OEMstringPtr = p2;
119 	p1 = (char FAR *)mp;
120 	for( ; --ii >= 0; p1++,p2++) *p2 = peek_b_f(p1);
121 	DELETE_XFER_BUFFER;
122 	return(TRUE);
123 }
124 
_GrViDrvVESAgetPMinfo(void)125 VESApmInfoBlock * _GrViDrvVESAgetPMinfo(void) {
126   Int86Regs r;
127   static VESApmInfoBlock *ib = NULL;
128   unsigned Length, ii;
129   char FAR *p1;
130   char *p2;
131 
132   sttzero(&r);
133   IREG_AX(r) = VESA_FUNC + VESA_PM_INTERF;
134   IREG_BX(r) = 0x0000;
135   DBGPRINTF(DBG_DRIVER,("Getting protected mode interface\n"));
136   int10x(&r);
137   if(IREG_AX(r) != VESA_SUCCESS)
138     return(NULL);
139   /* Now we have : CX    = length of table and routines (bytes)
140 		   ES:DI = pointer to table
141 			    ES_DI+00: offset PM set window routine
142 				 +02: offset PM set display start
143 				 +04: offset PM set primary palette
144 				 +06: offset PM description table  */
145   Length = (unsigned)IREG_CX(r);
146   if( Length == 0) return(NULL);
147   ib = realloc(ib, Length + VESApmInfoBlock_BASEOFF);
148   if (ib == NULL) return(NULL);
149 
150   ib->RealMode_SEG   = IREG_ES(r);
151   ib->RealMode_OFF   = IREG_DI(r);
152   ib->PhysicalLength = IREG_CX(r);
153 
154   setup_far_selector(LINP_SEL(MK_FP( IREG_ES(r),IREG_DI(r))));
155   p1 = LINP_PTR( MK_FP( IREG_ES(r),IREG_DI(r) ) );
156   p2 = (char *) &(ib->SetWindow_off);
157   for(ii = 0; ii < Length; p1++,ii++) *(p2++) = peek_b_f(p1);
158   DBGPRINTF(DBG_DRIVER,("Protected Mode Interface :-\n" ));
159   DBGPRINTF(DBG_DRIVER,("  Real mode address = 0x%04x:0x%04x\n",ib->RealMode_SEG,ib->RealMode_OFF));
160   DBGPRINTF(DBG_DRIVER,("  Length = 0x%08x\n",ib->PhysicalLength));
161   DBGPRINTF(DBG_DRIVER,("  SetWindow function offset = 0x%08x\n",ib->SetWindow_off));
162   DBGPRINTF(DBG_DRIVER,("  SetDisplayStart function offset = 0x%08x\n",ib->DisplStart_off));
163   DBGPRINTF(DBG_DRIVER,("  Primary Palette function offset = 0x%08x\n",ib->PPalette_off));
164   DBGPRINTF(DBG_DRIVER,("  Resource Sub-Table offset = 0x%08x\n",ib->SubTable_off));
165 #ifdef DUMP_PM_TABLE
166   {
167     static int once = 0;
168     if (!once) {
169       int len;
170       FILE *dump = fopen("vesapm.s", "wt");
171       once = 1;
172       if (dump) {
173 	p2 = (char *) &(ib->SetWindow_off);
174 	fprintf(dump, ".text\n_vesa_pm_table:\n");
175 	for (len=0; len < Length; ++len) {
176 	  fprintf(dump, "\t.byte %u\n", *(unsigned char *)p2);
177 	  ++p2;
178 	}
179 	fclose(dump);
180       }
181       dump = fopen("vesapm.dmp", "wb");
182       if (dump) {
183 	p2 = (char *) &(ib->SetWindow_off);
184 	fwrite(p2,Length,1,dump);
185 	fclose(dump);
186       }
187     }
188   }
189 #endif
190   return(ib);
191 }
192 
_GrViDrvVESAgetModeInfo(int mode,VESAmodeInfoBlock * ib)193 int _GrViDrvVESAgetModeInfo(int mode,VESAmodeInfoBlock *ib)
194 {
195 	Int86Regs regs;
196 	char FAR *p1;
197 	char *p2;
198 	int  ii;
199 	DECLARE_XFER_BUFFER(1000);
200 	/*
201 	 * set up registers and call interrupt
202 	 */
203 	sttzero(&regs);
204 	IREG_AX(regs) = VESA_FUNC + VESA_MODE_INFO;
205 	IREG_CX(regs) = mode;
206 	IREG_ES(regs) = FP_SEG(XFER_BUFFER);
207 	IREG_DI(regs) = FP_OFF(XFER_BUFFER);
208 	int10x(&regs);
209 	if(IREG_AX(regs) != VESA_SUCCESS) {
210 		DELETE_XFER_BUFFER;
211 		return(FALSE);
212 	}
213 	/*
214 	 * copy VESA info block into accessible memory
215 	 */
216 	setup_far_selector(LINP_SEL(XFER_BUFFER));
217 	p1 = (char FAR *)LINP_PTR(XFER_BUFFER);
218 	p2 = (char *)ib;
219 	for(ii = sizeof(*ib); --ii >= 0; p1++,p2++) *p2 = peek_b_f(p1);
220 	DELETE_XFER_BUFFER;
221 	return((ib->ModeAttributes & MODE_SUPPORTED) ? TRUE : FALSE);
222 }
223 
224 #endif
225 
226