Mercurial > mplayer.hg
annotate linux/vbelib.c @ 4132:84ecfd03c86a
test for preinit errors and correct handling subdevice
author | nick |
---|---|
date | Sun, 13 Jan 2002 10:30:10 +0000 |
parents | ea414257856f |
children | 7eda15bbb3f9 |
rev | line source |
---|---|
2243 | 1 /* |
2 This file contains implementation of VESA library which is based on | |
3 LRMI (Linux real-mode interface). | |
4 So it's not an emulator - it calls real int 10h handler under Linux. | |
5 Note: VESA is available only on x86 systems. | |
6 You can redistribute this file under terms and conditions | |
2632 | 7 of GNU General Public licence v2. |
2243 | 8 Written by Nick Kurshev <nickols_k@mail.ru> |
9 */ | |
10 #include "vbelib.h" | |
11 #include "lrmi.h" | |
12 #include <stdlib.h> | |
13 #include <string.h> | |
14 #include <stdio.h> | |
15 #include <sys/io.h> | |
2610 | 16 #include <sys/mman.h> |
17 #include <sys/types.h> | |
18 #include <sys/stat.h> | |
2407 | 19 #include <ctype.h> |
2610 | 20 #include <unistd.h> |
21 #include <fcntl.h> | |
2243 | 22 |
23 static struct VesaProtModeInterface vbe_pm_info; | |
2632 | 24 static struct VesaModeInfoBlock curr_mode_info; |
2243 | 25 |
2536 | 26 static inline int VERR(const void *p) |
2515 | 27 { |
28 register int retval; | |
29 __asm __volatile( | |
30 "xorl %0, %0\n\t" | |
31 "verr %1\n\t" | |
32 "setnz %b0" | |
33 :"=r"(retval) | |
34 :"m"(*(unsigned char *)p) | |
35 :"memory"); | |
36 return retval; | |
37 } | |
38 | |
39 #if 0 | |
2536 | 40 static inline int VERW(const void *p) |
2515 | 41 { |
42 register int retval; | |
43 __asm __volatile( | |
44 "xorl %0, %0\n\t" | |
45 "verw %1\n\t" | |
46 "setnz %b0" | |
47 :"=r"(retval) | |
48 :"m"(*(unsigned char *)p) | |
49 :"memory"); | |
50 return retval; | |
51 } | |
52 #endif | |
53 | |
2294 | 54 #define HAVE_VERBOSE_VAR 1 |
55 | |
56 #ifdef HAVE_VERBOSE_VAR | |
57 extern int verbose; | |
58 | |
59 static void __dump_regs(struct LRMI_regs *r) | |
60 { | |
61 printf("vbelib: eax=%08lXh ebx=%08lXh ecx=%08lXh edx=%08lXh\n" | |
62 "vbelib: edi=%08lXh esi=%08lXh ebp=%08lXh esp=%08lXh\n" | |
2445 | 63 "vbelib: ds=%04Xh es=%04Xh ss=%04Xh cs:ip=%04X:%04X\n" |
64 "vbelib: fs=%04Xh gs=%04Xh ss:sp=%04X:%04X flags=%04X\n" | |
65 ,(unsigned long)r->eax,(unsigned long)r->ebx,(unsigned long)r->ecx,(unsigned long)r->edx | |
66 ,(unsigned long)r->edi,(unsigned long)r->esi,(unsigned long)r->ebp,(unsigned long)r->reserved | |
2294 | 67 ,r->ds,r->es,r->ss,r->cs,r->ip |
68 ,r->fs,r->gs,r->ss,r->sp,r->flags); | |
69 } | |
70 | |
71 static inline int VBE_LRMI_int(int int_no, struct LRMI_regs *r) | |
72 { | |
73 int retval; | |
74 if(verbose > 1) | |
75 { | |
76 printf("vbelib: registers before int %02X\n",int_no); | |
77 __dump_regs(r); | |
78 } | |
79 retval = LRMI_int(int_no,r); | |
80 if(verbose > 1) | |
81 { | |
2445 | 82 printf("vbelib: Interrupt handler returns: %X\n",retval); |
2294 | 83 printf("vbelib: registers after int %02X\n",int_no); |
84 __dump_regs(r); | |
85 } | |
86 return retval; | |
87 } | |
88 #else | |
89 #define VBE_LRMI_int(int_no,regs) (VBE_LRMI_int(int_no,regs)) | |
90 #endif | |
91 | |
3016
ea414257856f
Hide terminal's output and text-mode cursor for LCD and DFP
nick
parents:
2913
diff
changeset
|
92 static FILE *my_stdin; |
ea414257856f
Hide terminal's output and text-mode cursor for LCD and DFP
nick
parents:
2913
diff
changeset
|
93 static FILE *my_stdout; |
ea414257856f
Hide terminal's output and text-mode cursor for LCD and DFP
nick
parents:
2913
diff
changeset
|
94 static FILE *my_stderr; |
ea414257856f
Hide terminal's output and text-mode cursor for LCD and DFP
nick
parents:
2913
diff
changeset
|
95 |
ea414257856f
Hide terminal's output and text-mode cursor for LCD and DFP
nick
parents:
2913
diff
changeset
|
96 static void __set_cursor_type(FILE *stdout_fd,int cursor_on) |
ea414257856f
Hide terminal's output and text-mode cursor for LCD and DFP
nick
parents:
2913
diff
changeset
|
97 { |
ea414257856f
Hide terminal's output and text-mode cursor for LCD and DFP
nick
parents:
2913
diff
changeset
|
98 fprintf(stdout_fd,"\033[?25%c",cursor_on?'h':'l'); |
ea414257856f
Hide terminal's output and text-mode cursor for LCD and DFP
nick
parents:
2913
diff
changeset
|
99 } |
ea414257856f
Hide terminal's output and text-mode cursor for LCD and DFP
nick
parents:
2913
diff
changeset
|
100 |
ea414257856f
Hide terminal's output and text-mode cursor for LCD and DFP
nick
parents:
2913
diff
changeset
|
101 /* TODO: do it only on LCD or DFP. We should extract such info from DDC */ |
ea414257856f
Hide terminal's output and text-mode cursor for LCD and DFP
nick
parents:
2913
diff
changeset
|
102 static void hide_terminal_output( void ) |
ea414257856f
Hide terminal's output and text-mode cursor for LCD and DFP
nick
parents:
2913
diff
changeset
|
103 { |
ea414257856f
Hide terminal's output and text-mode cursor for LCD and DFP
nick
parents:
2913
diff
changeset
|
104 my_stdin = fopen(ttyname(fileno(stdin )),"r"); |
ea414257856f
Hide terminal's output and text-mode cursor for LCD and DFP
nick
parents:
2913
diff
changeset
|
105 my_stdout = fopen(ttyname(fileno(stdout)),"w"); |
ea414257856f
Hide terminal's output and text-mode cursor for LCD and DFP
nick
parents:
2913
diff
changeset
|
106 my_stderr = fopen(ttyname(fileno(stderr)),"w"); |
ea414257856f
Hide terminal's output and text-mode cursor for LCD and DFP
nick
parents:
2913
diff
changeset
|
107 __set_cursor_type(stdout,0); |
ea414257856f
Hide terminal's output and text-mode cursor for LCD and DFP
nick
parents:
2913
diff
changeset
|
108 /*if(isatty(fileno(stdin ))) stdin =freopen("/dev/null","r",stdin );*/ |
ea414257856f
Hide terminal's output and text-mode cursor for LCD and DFP
nick
parents:
2913
diff
changeset
|
109 if(isatty(fileno(stdout))) stdout=freopen("/dev/null","w",stdout); |
ea414257856f
Hide terminal's output and text-mode cursor for LCD and DFP
nick
parents:
2913
diff
changeset
|
110 if(isatty(fileno(stderr))) stderr=freopen("/dev/null","w",stderr); |
ea414257856f
Hide terminal's output and text-mode cursor for LCD and DFP
nick
parents:
2913
diff
changeset
|
111 } |
ea414257856f
Hide terminal's output and text-mode cursor for LCD and DFP
nick
parents:
2913
diff
changeset
|
112 |
2407 | 113 static unsigned hh_int_10_seg; |
2610 | 114 static int fd_mem; |
2243 | 115 int vbeInit( void ) |
116 { | |
2407 | 117 unsigned short iopl_port; |
2359 | 118 size_t i; |
2552 | 119 int retval; |
2243 | 120 if(!LRMI_init()) return VBE_VM86_FAIL; |
121 /* | |
122 Allow read/write to ALL io ports | |
123 */ | |
2407 | 124 hh_int_10_seg = *(unsigned short *)PhysToVirtSO(0x0000,0x0042); |
2359 | 125 /* Video BIOS should be at C000:0000 and above */ |
2407 | 126 hh_int_10_seg >>= 12; |
127 if(hh_int_10_seg < 0xC) return VBE_BROKEN_BIOS; | |
2243 | 128 ioperm(0, 1024, 1); |
129 iopl(3); | |
130 memset(&vbe_pm_info,0,sizeof(struct VesaProtModeInterface)); | |
2552 | 131 retval = vbeGetProtModeInfo(&vbe_pm_info); |
132 if(retval != VBE_OK) return retval; | |
2359 | 133 i = 0; |
2913 | 134 if(vbe_pm_info.iopl_ports) /* Can be NULL !!!*/ |
2552 | 135 while((iopl_port=vbe_pm_info.iopl_ports[i]) != 0xFFFF |
136 && vbe_pm_info.iopl_ports[i++] > 1023) ioperm(iopl_port,1,1); | |
2359 | 137 iopl(3); |
2610 | 138 fd_mem = open("/dev/mem",O_RDWR); |
3016
ea414257856f
Hide terminal's output and text-mode cursor for LCD and DFP
nick
parents:
2913
diff
changeset
|
139 hide_terminal_output(); |
2243 | 140 return VBE_OK; |
141 } | |
142 | |
2610 | 143 int vbeDestroy( void ) |
144 { | |
3016
ea414257856f
Hide terminal's output and text-mode cursor for LCD and DFP
nick
parents:
2913
diff
changeset
|
145 __set_cursor_type(my_stdout,1); |
2610 | 146 close(fd_mem); |
147 return VBE_OK; | |
148 } | |
2243 | 149 |
2536 | 150 /* Fixme!!! This code is compatible only with mplayer's version of lrmi*/ |
151 static inline int is_addr_valid(const void *p) | |
152 { | |
153 return (p < (const void *)0x502) || | |
154 (p >= (const void *)0x10000 && p < (const void *)0x20000) || | |
155 (p >= (const void *)0xa0000 && p < (const void *)0x100000); | |
156 } | |
157 | |
158 static int check_str(const unsigned char *str) | |
2515 | 159 { |
160 size_t i; | |
161 int null_found = 0; | |
162 for(i = 0;i < 256;i++) | |
163 { | |
2536 | 164 if(is_addr_valid(&str[i])) |
2515 | 165 { |
2536 | 166 if(VERR(&str[i])) |
167 { | |
168 if(!str[i]) { null_found = 1; break; } | |
169 } | |
170 else break; | |
2515 | 171 } |
172 else break; | |
173 } | |
174 return null_found; | |
175 } | |
176 | |
2536 | 177 static int check_wrd(const unsigned short *str) |
2515 | 178 { |
179 size_t i; | |
180 int ffff_found = 0; | |
181 for(i = 0;i < 1024;i++) | |
182 { | |
2536 | 183 if(is_addr_valid(&str[i])) |
2515 | 184 { |
2536 | 185 if(VERR(&str[i])) |
186 { | |
187 if(str[i] == 0xffff) { ffff_found = 1; break; } | |
188 } | |
189 else break; | |
2515 | 190 } |
191 else break; | |
192 } | |
193 return ffff_found; | |
194 } | |
195 | |
2407 | 196 static void print_str(unsigned char *str) |
197 { | |
198 size_t i; | |
199 fflush(stdout); | |
200 printf("vbelib: "); | |
201 for(i = 0;i < 256;i++) { printf("%02X(%c) ",str[i],isprint(str[i])?str[i]:'.'); if(!str[i]) break; } | |
202 printf("\n"); | |
203 fflush(stdout); | |
204 } | |
205 | |
206 static void print_wrd(unsigned short *str) | |
207 { | |
208 size_t i; | |
209 fflush(stdout); | |
210 printf("vbelib: "); | |
211 for(i = 0;i < 256;i++) { printf("%04X ",str[i]); if(str[i] == 0xffff) break; } | |
212 printf("\n"); | |
213 fflush(stdout); | |
214 } | |
215 | |
2243 | 216 int vbeGetControllerInfo(struct VbeInfoBlock *data) |
217 { | |
218 struct LRMI_regs r; | |
219 void *rm_space; | |
220 int retval; | |
221 if(!(rm_space = LRMI_alloc_real(sizeof(struct VbeInfoBlock)))) return VBE_OUT_OF_DOS_MEM; | |
222 memcpy(rm_space,data,sizeof(struct VbeInfoBlock)); | |
223 memset(&r,0,sizeof(struct LRMI_regs)); | |
224 r.eax = 0x4f00; | |
225 r.es = VirtToPhysSeg(rm_space); | |
226 r.edi = VirtToPhysOff(rm_space); | |
2294 | 227 if(!VBE_LRMI_int(0x10,&r)) |
2243 | 228 { |
229 LRMI_free_real(rm_space); | |
230 return VBE_VM86_FAIL; | |
231 } | |
232 retval = r.eax & 0xffff; | |
233 if(retval == 0x4f) | |
234 { | |
235 FarPtr fpdata; | |
236 retval = VBE_OK; | |
237 memcpy(data,rm_space,sizeof(struct VbeInfoBlock)); | |
238 fpdata.seg = (unsigned long)(data->OemStringPtr) >> 16; | |
239 fpdata.off = (unsigned long)(data->OemStringPtr) & 0xffff; | |
240 data->OemStringPtr = PhysToVirt(fpdata); | |
2515 | 241 if(!check_str(data->OemStringPtr)) data->OemStringPtr = NULL; |
2294 | 242 #ifdef HAVE_VERBOSE_VAR |
2407 | 243 if(verbose > 1) |
244 { | |
245 printf("vbelib: OemStringPtr=%04X:%04X => %p\n",fpdata.seg,fpdata.off,data->OemStringPtr); | |
2515 | 246 if(data->OemStringPtr) print_str(data->OemStringPtr); |
2518 | 247 fflush(stdout); |
2407 | 248 } |
2294 | 249 #endif |
2243 | 250 fpdata.seg = (unsigned long)(data->VideoModePtr) >> 16; |
251 fpdata.off = (unsigned long)(data->VideoModePtr) & 0xffff; | |
252 data->VideoModePtr = PhysToVirt(fpdata); | |
2515 | 253 if(!check_wrd(data->VideoModePtr)) |
254 { | |
255 data->VideoModePtr = NULL; | |
256 retval = VBE_BROKEN_BIOS; | |
257 } | |
2294 | 258 #ifdef HAVE_VERBOSE_VAR |
2407 | 259 if(verbose > 1) |
260 { | |
261 printf("vbelib: VideoModePtr=%04X:%04X => %p\n",fpdata.seg,fpdata.off,data->VideoModePtr); | |
2515 | 262 if(data->VideoModePtr) print_wrd(data->VideoModePtr); |
2518 | 263 fflush(stdout); |
2407 | 264 } |
2294 | 265 #endif |
2243 | 266 fpdata.seg = (unsigned long)(data->OemVendorNamePtr) >> 16; |
267 fpdata.off = (unsigned long)(data->OemVendorNamePtr) & 0xffff; | |
268 data->OemVendorNamePtr = PhysToVirt(fpdata); | |
2515 | 269 if(!check_str(data->OemVendorNamePtr)) data->OemVendorNamePtr = NULL; |
2294 | 270 #ifdef HAVE_VERBOSE_VAR |
2407 | 271 if(verbose > 1) |
272 { | |
273 printf("vbelib: OemVendorNamePtr=%04X:%04X => %p\n",fpdata.seg,fpdata.off,data->OemVendorNamePtr); | |
2515 | 274 if(data->OemVendorNamePtr) print_str(data->OemVendorNamePtr); |
2518 | 275 fflush(stdout); |
2407 | 276 } |
2294 | 277 #endif |
2243 | 278 fpdata.seg = (unsigned long)(data->OemProductNamePtr) >> 16; |
279 fpdata.off = (unsigned long)(data->OemProductNamePtr) & 0xffff; | |
280 data->OemProductNamePtr = PhysToVirt(fpdata); | |
2515 | 281 if(!check_str(data->OemProductNamePtr)) data->OemProductNamePtr = NULL; |
2294 | 282 #ifdef HAVE_VERBOSE_VAR |
2407 | 283 if(verbose > 1) |
284 { | |
285 printf("vbelib: OemProductNamePtr=%04X:%04X => %p\n",fpdata.seg,fpdata.off,data->OemProductNamePtr); | |
2515 | 286 if(data->OemVendorNamePtr) print_str(data->OemProductNamePtr); |
2518 | 287 fflush(stdout); |
2407 | 288 } |
2294 | 289 #endif |
2243 | 290 fpdata.seg = (unsigned long)(data->OemProductRevPtr) >> 16; |
291 fpdata.off = (unsigned long)(data->OemProductRevPtr) & 0xffff; | |
292 data->OemProductRevPtr = PhysToVirt(fpdata); | |
2515 | 293 if(!check_str(data->OemProductRevPtr)) data->OemProductRevPtr = NULL; |
2294 | 294 #ifdef HAVE_VERBOSE_VAR |
2407 | 295 if(verbose > 1) |
296 { | |
297 printf("vbelib: OemProductRevPtr=%04X:%04X => %p\n",fpdata.seg,fpdata.off,data->OemProductRevPtr); | |
2515 | 298 if(data->OemProductRevPtr) print_str(data->OemProductRevPtr); |
2518 | 299 fflush(stdout); |
2407 | 300 } |
2294 | 301 #endif |
2243 | 302 } |
303 return retval; | |
304 } | |
305 | |
306 int vbeGetModeInfo(unsigned mode,struct VesaModeInfoBlock *data) | |
307 { | |
308 struct LRMI_regs r; | |
309 void *rm_space; | |
310 int retval; | |
311 if(!(rm_space = LRMI_alloc_real(sizeof(struct VesaModeInfoBlock)))) return VBE_OUT_OF_DOS_MEM; | |
312 memset(&r,0,sizeof(struct LRMI_regs)); | |
313 r.eax = 0x4f01; | |
314 r.ecx = mode; | |
315 r.es = VirtToPhysSeg(rm_space); | |
316 r.edi = VirtToPhysOff(rm_space); | |
2294 | 317 if(!VBE_LRMI_int(0x10,&r)) |
2243 | 318 { |
319 LRMI_free_real(rm_space); | |
320 return VBE_VM86_FAIL; | |
321 } | |
322 retval = r.eax & 0xffff; | |
323 if(retval == 0x4f) | |
324 { | |
325 retval = VBE_OK; | |
326 memcpy(data,rm_space,sizeof(struct VesaModeInfoBlock)); | |
327 } | |
328 return retval; | |
329 } | |
330 | |
331 int vbeSetMode(unsigned mode,struct VesaCRTCInfoBlock *data) | |
332 { | |
333 struct LRMI_regs r; | |
334 void *rm_space = NULL; | |
335 int retval; | |
336 memset(&r,0,sizeof(struct LRMI_regs)); | |
337 if(data) | |
338 { | |
339 if(!(rm_space = LRMI_alloc_real(sizeof(struct VesaCRTCInfoBlock)))) return VBE_OUT_OF_DOS_MEM; | |
340 r.es = VirtToPhysSeg(rm_space); | |
341 r.edi = VirtToPhysOff(rm_space); | |
342 memcpy(rm_space,data,sizeof(struct VesaCRTCInfoBlock)); | |
343 } | |
344 r.eax = 0x4f02; | |
345 r.ebx = mode; | |
2294 | 346 retval = VBE_LRMI_int(0x10,&r); |
2243 | 347 if(rm_space) LRMI_free_real(rm_space); |
348 if(!retval) return VBE_VM86_FAIL; | |
349 retval = r.eax & 0xffff; | |
2632 | 350 if(retval == 0x4f) |
351 { | |
352 /* Just info for internal use (currently in SetDiplayStart func). */ | |
353 vbeGetModeInfo(mode&0x1f,&curr_mode_info); | |
354 retval = VBE_OK; | |
355 } | |
2243 | 356 return retval; |
357 } | |
358 | |
359 int vbeGetMode(unsigned *mode) | |
360 { | |
361 struct LRMI_regs r; | |
362 int retval; | |
363 memset(&r,0,sizeof(struct LRMI_regs)); | |
364 r.eax = 0x4f03; | |
2294 | 365 if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL; |
2243 | 366 retval = r.eax & 0xffff; |
367 if(retval == 0x4f) | |
368 { | |
369 *mode = r.ebx; | |
370 retval = VBE_OK; | |
371 } | |
372 return retval; | |
373 } | |
374 | |
375 int vbeSaveState(void **data) | |
376 { | |
377 struct LRMI_regs r; | |
378 int retval; | |
379 void *rm_space; | |
380 memset(&r,0,sizeof(struct LRMI_regs)); | |
381 r.eax = 0x4f04; | |
382 r.edx = 0x00; | |
383 r.ecx = 0x0f; | |
2294 | 384 if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL; |
2243 | 385 retval = r.eax & 0xffff; |
386 if(retval != 0x4f) return retval; | |
387 if(!(rm_space = LRMI_alloc_real((r.ebx & 0xffff)*64))) return VBE_OUT_OF_DOS_MEM; | |
388 r.eax = 0x4f04; | |
389 r.edx = 0x01; | |
390 r.ecx = 0x0f; | |
391 r.es = VirtToPhysSeg(rm_space); | |
2254
6e5b548790c9
Fixed bug of 32-bit mode interface detection and save-restore mechanism
nick
parents:
2243
diff
changeset
|
392 r.ebx = VirtToPhysOff(rm_space); |
2294 | 393 if(!VBE_LRMI_int(0x10,&r)) |
2243 | 394 { |
395 LRMI_free_real(rm_space); | |
396 return VBE_VM86_FAIL; | |
397 } | |
398 retval = r.eax & 0xffff; | |
399 if(retval != 0x4f) | |
400 { | |
401 LRMI_free_real(rm_space); | |
402 return retval; | |
403 } | |
404 *data = rm_space; | |
405 return VBE_OK; | |
406 } | |
407 | |
408 int vbeRestoreState(void *data) | |
409 { | |
410 struct LRMI_regs r; | |
411 int retval; | |
412 memset(&r,0,sizeof(struct LRMI_regs)); | |
413 r.eax = 0x4f04; | |
414 r.edx = 0x02; | |
415 r.ecx = 0x0f; | |
416 r.es = VirtToPhysSeg(data); | |
2254
6e5b548790c9
Fixed bug of 32-bit mode interface detection and save-restore mechanism
nick
parents:
2243
diff
changeset
|
417 r.ebx = VirtToPhysOff(data); |
2294 | 418 retval = VBE_LRMI_int(0x10,&r); |
2243 | 419 LRMI_free_real(data); |
420 if(!retval) return VBE_VM86_FAIL; | |
421 retval = r.eax & 0xffff; | |
422 if(retval == 0x4f) retval = VBE_OK; | |
423 return retval; | |
424 } | |
425 | |
426 int vbeGetWindow(unsigned *win_num) | |
427 { | |
428 struct LRMI_regs r; | |
429 int retval; | |
430 memset(&r,0,sizeof(struct LRMI_regs)); | |
431 r.eax = 0x4f05; | |
432 r.ebx = (*win_num & 0x0f) | 0x0100; | |
2294 | 433 if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL; |
2243 | 434 retval = r.eax & 0xffff; |
435 if(retval == 0x4f) | |
436 { | |
437 *win_num = r.edx & 0xffff; | |
438 retval = VBE_OK; | |
439 } | |
440 return retval; | |
441 } | |
442 | |
443 int vbeSetWindow(unsigned win_num,unsigned win_gran) | |
444 { | |
445 int retval; | |
446 if(vbe_pm_info.SetWindowCall) | |
447 { | |
2294 | 448 /* Don't verbose this stuff from performance reasons */ |
2243 | 449 /* 32-bit function call is much better of int 10h */ |
450 __asm __volatile( | |
451 "pushl %%ebx\n" | |
452 "movl %1, %%ebx\n" | |
453 ::"a"(0x4f05),"S"(win_num & 0x0f),"d"(win_gran):"memory"); | |
454 (*vbe_pm_info.SetWindowCall)(); | |
2254
6e5b548790c9
Fixed bug of 32-bit mode interface detection and save-restore mechanism
nick
parents:
2243
diff
changeset
|
455 __asm __volatile("popl %%ebx":::"memory"); |
6e5b548790c9
Fixed bug of 32-bit mode interface detection and save-restore mechanism
nick
parents:
2243
diff
changeset
|
456 retval = VBE_OK; |
2243 | 457 } |
458 else | |
459 { | |
460 struct LRMI_regs r; | |
461 memset(&r,0,sizeof(struct LRMI_regs)); | |
462 r.eax = 0x4f05; | |
463 r.ebx = win_num & 0x0f; | |
464 r.edx = win_gran; | |
2294 | 465 if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL; |
2243 | 466 retval = r.eax & 0xffff; |
2254
6e5b548790c9
Fixed bug of 32-bit mode interface detection and save-restore mechanism
nick
parents:
2243
diff
changeset
|
467 if(retval == 0x4f) retval = VBE_OK; |
2243 | 468 } |
469 return retval; | |
470 } | |
471 | |
2632 | 472 int vbeGetScanLineLength(unsigned *num_pixels,unsigned *num_bytes) |
473 { | |
474 struct LRMI_regs r; | |
475 int retval; | |
476 memset(&r,0,sizeof(struct LRMI_regs)); | |
477 r.eax = 0x4f06; | |
478 r.ebx = 1; | |
479 if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL; | |
480 retval = r.eax & 0xffff; | |
481 if(retval == 0x4f) | |
482 { | |
483 if(num_bytes) *num_bytes = r.ebx & 0xffff; | |
484 if(num_pixels) *num_pixels= r.ecx & 0xffff; | |
485 retval = VBE_OK; | |
486 } | |
487 return retval; | |
488 } | |
489 | |
490 int vbeGetMaxScanLines(unsigned *num_pixels,unsigned *num_bytes, unsigned *num_lines) | |
491 { | |
492 struct LRMI_regs r; | |
493 int retval; | |
494 memset(&r,0,sizeof(struct LRMI_regs)); | |
495 r.eax = 0x4f06; | |
496 r.ebx = 3; | |
497 if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL; | |
498 retval = r.eax & 0xffff; | |
499 if(retval == 0x4f) | |
500 { | |
501 if(num_bytes) *num_bytes = r.ebx & 0xffff; | |
502 if(num_pixels) *num_pixels= r.ecx & 0xffff; | |
503 if(num_lines) *num_lines = r.edx & 0xffff; | |
504 retval = VBE_OK; | |
505 } | |
506 return retval; | |
507 } | |
508 | |
509 int vbeSetScanLineLength(unsigned num_pixels) | |
510 { | |
511 int retval; | |
512 struct LRMI_regs r; | |
513 memset(&r,0,sizeof(struct LRMI_regs)); | |
514 r.eax = 0x4f06; | |
515 r.ebx = 0; | |
516 r.ecx = num_pixels; | |
517 if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL; | |
518 retval = r.eax & 0xffff; | |
519 if(retval == 0x4f) retval = VBE_OK; | |
520 return retval; | |
521 } | |
522 | |
523 int vbeSetScanLineLengthB(unsigned num_bytes) | |
524 { | |
525 int retval; | |
526 struct LRMI_regs r; | |
527 memset(&r,0,sizeof(struct LRMI_regs)); | |
528 r.eax = 0x4f06; | |
529 r.ebx = 2; | |
530 r.ecx = num_bytes; | |
531 if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL; | |
532 retval = r.eax & 0xffff; | |
533 if(retval == 0x4f) retval = VBE_OK; | |
534 return retval; | |
535 } | |
536 | |
537 int vbeGetDisplayStart(unsigned *pixel_num,unsigned *scan_line) | |
538 { | |
539 struct LRMI_regs r; | |
540 int retval; | |
541 memset(&r,0,sizeof(struct LRMI_regs)); | |
542 r.eax = 0x4f07; | |
543 r.ebx = 1; | |
544 if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL; | |
545 retval = r.eax & 0xffff; | |
546 if(retval == 0x4f) | |
547 { | |
548 if(pixel_num) *pixel_num = r.ecx & 0xffff; | |
549 if(scan_line) *scan_line = r.edx & 0xffff; | |
550 retval = VBE_OK; | |
551 } | |
552 return retval; | |
553 } | |
554 | |
555 int vbeSetDisplayStart(unsigned long offset, int vsync) | |
556 { | |
557 int retval; | |
558 if(vbe_pm_info.SetDisplayStart) | |
559 { | |
560 /* Don't verbose this stuff from performance reasons */ | |
561 /* 32-bit function call is much better of int 10h */ | |
562 __asm __volatile( | |
563 "pushl %%ebx\n" | |
564 "movl %1, %%ebx\n" | |
565 ::"a"(0x4f07),"S"(vsync ? 0x80 : 0), | |
2686 | 566 "c"((offset>>2) & 0xffff),"d"((offset>>18)&0xffff):"memory"); |
2632 | 567 (*vbe_pm_info.SetDisplayStart)(); |
568 __asm __volatile("popl %%ebx":::"memory"); | |
569 retval = VBE_OK; | |
570 } | |
571 else | |
572 { | |
2686 | 573 #if 0 |
574 /* Something wrong here */ | |
2632 | 575 struct LRMI_regs r; |
576 unsigned long pixel_num; | |
577 memset(&r,0,sizeof(struct LRMI_regs)); | |
2686 | 578 pixel_num = offset%(unsigned long)curr_mode_info.BytesPerScanLine; |
579 if(pixel_num*(unsigned long)curr_mode_info.BytesPerScanLine!=offset) pixel_num++; | |
2632 | 580 r.eax = 0x4f07; |
2693 | 581 r.ebx = vsync ? 0x82 : 2; |
2632 | 582 r.ecx = pixel_num; |
583 r.edx = offset/(unsigned long)curr_mode_info.BytesPerScanLine; | |
584 if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL; | |
585 retval = r.eax & 0xffff; | |
586 if(retval == 0x4f) retval = VBE_OK; | |
2686 | 587 #endif |
588 retval = VBE_BROKEN_BIOS; | |
2632 | 589 } |
590 return retval; | |
591 } | |
592 | |
2693 | 593 int vbeSetScheduledDisplayStart(unsigned long offset, int vsync) |
594 { | |
595 int retval; | |
596 struct LRMI_regs r; | |
597 unsigned long pixel_num; | |
598 memset(&r,0,sizeof(struct LRMI_regs)); | |
599 pixel_num = offset%(unsigned long)curr_mode_info.BytesPerScanLine; | |
600 if(pixel_num*(unsigned long)curr_mode_info.BytesPerScanLine!=offset) pixel_num++; | |
601 r.eax = 0x4f07; | |
602 r.ebx = vsync ? 0x82 : 2; | |
603 r.ecx = offset; | |
604 if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL; | |
605 retval = r.eax & 0xffff; | |
606 if(retval == 0x4f) retval = VBE_OK; | |
607 return retval; | |
608 } | |
609 | |
2243 | 610 struct realVesaProtModeInterface |
611 { | |
612 unsigned short SetWindowCall; | |
613 unsigned short SetDisplayStart; | |
614 unsigned short SetPaletteData; | |
615 unsigned short iopl_ports; | |
616 }__attribute__((packed)); | |
617 | |
618 int vbeGetProtModeInfo(struct VesaProtModeInterface *pm_info) | |
619 { | |
620 struct LRMI_regs r; | |
621 int retval; | |
2254
6e5b548790c9
Fixed bug of 32-bit mode interface detection and save-restore mechanism
nick
parents:
2243
diff
changeset
|
622 unsigned info_offset; |
2243 | 623 struct realVesaProtModeInterface *rm_info; |
624 memset(&r,0,sizeof(struct LRMI_regs)); | |
625 r.eax = 0x4f0a; | |
626 r.ebx = 0; | |
2294 | 627 if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL; |
2243 | 628 retval = r.eax & 0xffff; |
629 if(retval == 0x4f) | |
630 { | |
2407 | 631 retval = VBE_OK; |
2254
6e5b548790c9
Fixed bug of 32-bit mode interface detection and save-restore mechanism
nick
parents:
2243
diff
changeset
|
632 info_offset = r.edi&0xffff; |
2407 | 633 if((r.es >> 12) != hh_int_10_seg) retval = VBE_BROKEN_BIOS; |
2254
6e5b548790c9
Fixed bug of 32-bit mode interface detection and save-restore mechanism
nick
parents:
2243
diff
changeset
|
634 rm_info = PhysToVirtSO(r.es,info_offset); |
6e5b548790c9
Fixed bug of 32-bit mode interface detection and save-restore mechanism
nick
parents:
2243
diff
changeset
|
635 pm_info->SetWindowCall = PhysToVirtSO(r.es,info_offset+rm_info->SetWindowCall); |
2552 | 636 if(!is_addr_valid(pm_info->SetWindowCall)) retval = VBE_BROKEN_BIOS; |
2294 | 637 #ifdef HAVE_VERBOSE_VAR |
638 if(verbose > 1) printf("vbelib: SetWindowCall=%04X:%04X => %p\n",r.es,info_offset+rm_info->SetWindowCall,pm_info->SetWindowCall); | |
639 #endif | |
2254
6e5b548790c9
Fixed bug of 32-bit mode interface detection and save-restore mechanism
nick
parents:
2243
diff
changeset
|
640 pm_info->SetDisplayStart = PhysToVirtSO(r.es,info_offset+rm_info->SetDisplayStart); |
2552 | 641 if(!is_addr_valid(pm_info->SetDisplayStart)) retval = VBE_BROKEN_BIOS; |
2294 | 642 #ifdef HAVE_VERBOSE_VAR |
643 if(verbose > 1) printf("vbelib: SetDisplayStart=%04X:%04X => %p\n",r.es,info_offset+rm_info->SetDisplayStart,pm_info->SetDisplayStart); | |
644 #endif | |
2254
6e5b548790c9
Fixed bug of 32-bit mode interface detection and save-restore mechanism
nick
parents:
2243
diff
changeset
|
645 pm_info->SetPaletteData = PhysToVirtSO(r.es,info_offset+rm_info->SetPaletteData); |
2552 | 646 if(!is_addr_valid(pm_info->SetPaletteData)) retval = VBE_BROKEN_BIOS; |
2294 | 647 #ifdef HAVE_VERBOSE_VAR |
648 if(verbose > 1) printf("vbelib: SetPaletteData=%04X:%04X => %p\n",r.es,info_offset+rm_info->SetPaletteData,pm_info->SetPaletteData); | |
649 #endif | |
2254
6e5b548790c9
Fixed bug of 32-bit mode interface detection and save-restore mechanism
nick
parents:
2243
diff
changeset
|
650 pm_info->iopl_ports = PhysToVirtSO(r.es,info_offset+rm_info->iopl_ports); |
2913 | 651 if(!rm_info->iopl_ports) pm_info->iopl_ports = NULL; |
652 else | |
2515 | 653 if(!check_wrd(pm_info->iopl_ports)) |
654 { | |
655 pm_info->iopl_ports = NULL; | |
2913 | 656 /* retval = VBE_BROKEN_BIOS; <- It's for broken BIOSes only */ |
2515 | 657 } |
2294 | 658 #ifdef HAVE_VERBOSE_VAR |
2407 | 659 if(verbose > 1) |
660 { | |
661 printf("vbelib: iopl_ports=%04X:%04X => %p\n",r.es,info_offset+rm_info->iopl_ports,pm_info->iopl_ports); | |
2515 | 662 if(pm_info->iopl_ports) print_wrd(pm_info->iopl_ports); |
2518 | 663 fflush(stdout); |
2407 | 664 } |
2294 | 665 #endif |
2243 | 666 } |
667 return retval; | |
668 } | |
2410 | 669 /* --------- Standard VGA stuff -------------- */ |
670 int vbeWriteString(int x, int y, int attr, char *str) | |
671 { | |
672 struct LRMI_regs r; | |
673 void *rm_space = NULL; | |
674 int retval; | |
675 memset(&r,0,sizeof(struct LRMI_regs)); | |
676 r.ecx = strlen(str); | |
677 r.edx = ((y<<8)&0xff00)|(x&0xff); | |
678 r.ebx = attr; | |
679 if(!(rm_space = LRMI_alloc_real(r.ecx))) return VBE_OUT_OF_DOS_MEM; | |
680 r.es = VirtToPhysSeg(rm_space); | |
681 r.ebp = VirtToPhysOff(rm_space); | |
682 memcpy(rm_space,str,r.ecx); | |
683 r.eax = 0x1300; | |
684 retval = VBE_LRMI_int(0x10,&r); | |
685 if(rm_space) LRMI_free_real(rm_space); | |
686 if(!retval) return VBE_VM86_FAIL; | |
687 retval = r.eax & 0xffff; | |
688 if(retval == 0x4f) retval = VBE_OK; | |
689 return retval; | |
2460 | 690 } |
2610 | 691 |
692 void * vbeMapVideoBuffer(unsigned long phys_addr,unsigned long size) | |
693 { | |
694 void *lfb; | |
695 if(fd_mem == -1) return NULL; | |
696 if(verbose > 1) printf("vbelib: vbeMapVideoBuffer(%08lX,%08lX)\n",phys_addr,size); | |
697 /* Here we don't need with MAP_FIXED and prefered address (first argument) */ | |
698 lfb = mmap((void *)0,size,PROT_READ | PROT_WRITE,MAP_SHARED,fd_mem,phys_addr); | |
699 return lfb == (void *)-1 ? 0 : lfb; | |
700 } | |
701 | |
702 void vbeUnmapVideoBuffer(unsigned long linear_addr,unsigned long size) | |
703 { | |
704 if(verbose > 1) printf("vbelib: vbeUnmapVideoBuffer(%08lX,%08lX)\n",linear_addr,size); | |
705 munmap((void *)linear_addr,size); | |
706 } |