comparison osdep/vbelib.c @ 9380:edfe34c5405d

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