source: npl/system/vesautils/vesautils/libvbe/vbe.c @ 0105685

gcc484ntopperl-5.22
Last change on this file since 0105685 was c5c522c, checked in by Edwin Eefting <edwin@datux.nl>, 8 years ago

initial commit, transferred from cleaned syn3 svn tree

  • Property mode set to 100644
File size: 20.9 KB
Line 
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   Neomagic TV out support by Rudolf Marek <r.marek et sh.cvut.cz>
10*/
11
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#include <sys/ioctl.h>
23#include <linux/kd.h>
24
25#include <lrmi.h>
26#include "vbe.h"
27
28int vbeVersion(void)
29{
30    return 0x0002; // 0.2
31}
32
33static struct VesaProtModeInterface vbe_pm_info;
34static struct VesaModeInfoBlock curr_mode_info;
35
36static inline int VERR(const void *p)
37{
38  register int retval;
39  __asm __volatile(
40        "xorl   %0, %0\n\t"
41        "verr   %1\n\t"
42        "setnz  %b0"
43        :"=q"(retval)
44        :"m"(*(unsigned char *)p)
45        :"memory","cc");
46  return retval;
47}
48
49#if 0
50static inline int VERW(const void *p)
51{
52  register int retval;
53  __asm __volatile(
54        "xorl   %0, %0\n\t"
55        "verw   %1\n\t"
56        "setnz  %b0"
57        :"=q"(retval)
58        :"m"(*(unsigned char *)p)
59        :"memory","cc");
60  return retval;
61}
62#endif
63
64//#define HAVE_VERBOSE_VAR 1
65
66#ifdef HAVE_VERBOSE_VAR
67extern int verbose;
68
69static void __dump_regs(struct LRMI_regs *r)
70{
71  printf("vbelib:    eax=%08lXh ebx=%08lXh ecx=%08lXh edx=%08lXh\n"
72         "vbelib:    edi=%08lXh esi=%08lXh ebp=%08lXh esp=%08lXh\n"
73         "vbelib:    ds=%04Xh es=%04Xh ss=%04Xh cs:ip=%04X:%04X\n"
74         "vbelib:    fs=%04Xh gs=%04Xh ss:sp=%04X:%04X flags=%04X\n"
75         ,(unsigned long)r->eax,(unsigned long)r->ebx,(unsigned long)r->ecx,(unsigned long)r->edx
76         ,(unsigned long)r->edi,(unsigned long)r->esi,(unsigned long)r->ebp,(unsigned long)r->reserved
77         ,r->ds,r->es,r->ss,r->cs,r->ip
78         ,r->fs,r->gs,r->ss,r->sp,r->flags);
79}
80
81static inline int VBE_LRMI_int(int int_no, struct LRMI_regs *r)
82{
83  int retval;
84  if(verbose > 1)
85  {
86    printf("vbelib: registers before int %02X\n",int_no);
87    __dump_regs(r);
88  }   
89  retval = LRMI_int(int_no,r);
90  if(verbose > 1)
91  {
92    printf("vbelib: Interrupt handler returns: %X\n",retval);
93    printf("vbelib: registers after int %02X\n",int_no);
94    __dump_regs(r);
95  }   
96  return retval;
97}
98#else
99#define VBE_LRMI_int(int_no,regs) (LRMI_int(int_no,regs))
100#endif
101
102/**
103 * Set console to graphics or text mode.
104 * This is a clean way to enable/disable console text output
105 * and cursor blinking.
106 *
107 * @param mode The new wanted mode. Can be either KD_GRAPHICS to switch
108 *             to graphics mode or anything else to switch back to the
109 *             original mode.
110 */
111static void kd_set_mode(int mode)
112{
113  static int old_mode = KD_TEXT;
114  int fd;
115
116  if ((fd = open("/dev/tty0", O_RDWR)) < 0)
117    return;
118  if(mode == KD_GRAPHICS)
119    old_mode = ioctl(fd, KDGETMODE);
120  else
121    mode = old_mode;
122  ioctl(fd, KDSETMODE, mode);
123  close(fd);
124}
125
126static unsigned hh_int_10_seg;
127static int fd_mem;
128/*
129the list of supported video modes is stored in the reserved portion of
130the SuperVGA information record by some implementations, and it may
131thus be necessary to either copy the mode list or use a different
132buffer for all subsequent VESA calls
133*/
134static void *controller_info;
135int vbeInit( void )
136{
137   unsigned short iopl_port;
138   size_t i;
139   if(!LRMI_init()) return VBE_VM86_FAIL;
140   if(!(controller_info = LRMI_alloc_real(sizeof(struct VbeInfoBlock)))) return VBE_OUT_OF_DOS_MEM;
141   /*
142    Allow read/write to ALL io ports
143   */
144   hh_int_10_seg = *(unsigned short *)PhysToVirtSO(0x0000,0x0042);
145   /* Video BIOS should be at C000:0000 and above */
146   hh_int_10_seg >>= 12;
147   if(hh_int_10_seg < 0xC) return VBE_BROKEN_BIOS;
148   ioperm(0, 1024, 1);
149   iopl(3);
150   memset(&vbe_pm_info,0,sizeof(struct VesaProtModeInterface));
151   vbeGetProtModeInfo(&vbe_pm_info);
152   i = 0;
153   if(vbe_pm_info.iopl_ports) /* Can be NULL !!!*/
154   while((iopl_port=vbe_pm_info.iopl_ports[i]) != 0xFFFF
155         && vbe_pm_info.iopl_ports[i++] > 1023) ioperm(iopl_port,1,1);
156   iopl(3);
157   fd_mem = open("/dev/mem",O_RDWR);
158   kd_set_mode(KD_GRAPHICS);
159   return VBE_OK;
160}
161
162int vbeDestroy( void )
163{
164  kd_set_mode(KD_TEXT);
165  close(fd_mem);
166  LRMI_free_real(controller_info);
167  return VBE_OK;
168}
169
170/* Fixme!!! This code is compatible only with mplayer's version of lrmi*/
171static inline int is_addr_valid(const void *p)
172{
173  return (p < (const void *)0x502) ||
174         (p >= (const void *)0x10000 && p < (const void *)0x20000) ||
175         (p >= (const void *)0xa0000 && p < (const void *)0x100000);
176}
177
178static int check_str(const unsigned char *str)
179{
180  size_t i;
181  int null_found = 0;
182  for(i = 0;i < 256;i++)
183  {
184    if(is_addr_valid(&str[i]))
185    {
186      if(VERR(&str[i]))
187      {
188        if(!str[i]) { null_found = 1; break; }
189      }
190      else break;
191    }
192    else break;
193  }
194  return null_found;
195}
196
197static int check_wrd(const unsigned short *str)
198{
199  size_t i;
200  int ffff_found = 0;
201  for(i = 0;i < 1024;i++)
202  {
203    if(is_addr_valid(&str[i]))
204    {
205      if(VERR(&str[i]))
206      {
207        if(str[i] == 0xffff) { ffff_found = 1; break; }
208      }
209      else break;
210    }
211    else break;
212  }
213  return ffff_found;
214}
215
216static void print_str(unsigned char *str)
217{
218  size_t i;
219  fflush(stdout);
220  printf("vbelib:    ");
221  for(i = 0;i < 256;i++) { printf("%02X(%c) ",str[i],isprint(str[i])?str[i]:'.'); if(!str[i]) break; }
222  printf("\n");
223  fflush(stdout);
224}
225
226static void print_wrd(unsigned short *str)
227{
228  size_t i;
229  fflush(stdout);
230  printf("vbelib:    ");
231  for(i = 0;i < 256;i++) { printf("%04X ",str[i]); if(str[i] == 0xffff) break; }
232  printf("\n");
233  fflush(stdout);
234}
235
236int vbeGetControllerInfo(struct VbeInfoBlock *data)
237{
238  struct LRMI_regs r;
239  int retval;
240  memcpy(controller_info,data,sizeof(struct VbeInfoBlock));
241  memset(&r,0,sizeof(struct LRMI_regs));
242  r.eax = 0x4f00;
243  r.es  = VirtToPhysSeg(controller_info);
244  r.edi = VirtToPhysOff(controller_info);
245  if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL;
246  retval = r.eax & 0xffff;
247  if(retval == 0x4f)
248  {
249    FarPtr fpdata;
250    retval = VBE_OK;
251    memcpy(data,controller_info,sizeof(struct VbeInfoBlock));
252    fpdata.seg = (unsigned long)(data->OemStringPtr) >> 16;
253    fpdata.off = (unsigned long)(data->OemStringPtr) & 0xffff;
254    data->OemStringPtr = PhysToVirt(fpdata);
255    if(!check_str(data->OemStringPtr)) data->OemStringPtr = NULL;
256#ifdef HAVE_VERBOSE_VAR
257    if(verbose > 1)
258    {
259      printf("vbelib:  OemStringPtr=%04X:%04X => %p\n",fpdata.seg,fpdata.off,data->OemStringPtr);
260      if(data->OemStringPtr) print_str(data->OemStringPtr);
261      fflush(stdout);
262    }
263#endif
264    fpdata.seg = (unsigned long)(data->VideoModePtr) >> 16;
265    fpdata.off = (unsigned long)(data->VideoModePtr) & 0xffff;
266    data->VideoModePtr = PhysToVirt(fpdata);
267    if(!check_wrd(data->VideoModePtr))
268    {
269        data->VideoModePtr = NULL;
270        retval = VBE_BROKEN_BIOS;
271    }   
272#ifdef HAVE_VERBOSE_VAR
273    if(verbose > 1)
274    {
275      printf("vbelib:  VideoModePtr=%04X:%04X => %p\n",fpdata.seg,fpdata.off,data->VideoModePtr);
276      if(data->VideoModePtr) print_wrd(data->VideoModePtr);
277      fflush(stdout);
278    }
279#endif
280    fpdata.seg = (unsigned long)(data->OemVendorNamePtr) >> 16;
281    fpdata.off = (unsigned long)(data->OemVendorNamePtr) & 0xffff;
282    data->OemVendorNamePtr = PhysToVirt(fpdata);
283    if(!check_str(data->OemVendorNamePtr)) data->OemVendorNamePtr = NULL;
284#ifdef HAVE_VERBOSE_VAR
285    if(verbose > 1)
286    {
287      printf("vbelib:  OemVendorNamePtr=%04X:%04X => %p\n",fpdata.seg,fpdata.off,data->OemVendorNamePtr);
288      if(data->OemVendorNamePtr) print_str(data->OemVendorNamePtr);
289      fflush(stdout);
290    }
291#endif
292    fpdata.seg = (unsigned long)(data->OemProductNamePtr) >> 16;
293    fpdata.off = (unsigned long)(data->OemProductNamePtr) & 0xffff;
294    data->OemProductNamePtr = PhysToVirt(fpdata);
295    if(!check_str(data->OemProductNamePtr)) data->OemProductNamePtr = NULL;
296#ifdef HAVE_VERBOSE_VAR
297    if(verbose > 1)
298    {
299      printf("vbelib:  OemProductNamePtr=%04X:%04X => %p\n",fpdata.seg,fpdata.off,data->OemProductNamePtr);
300      if(data->OemVendorNamePtr) print_str(data->OemProductNamePtr);
301      fflush(stdout);
302    }
303#endif
304    fpdata.seg = (unsigned long)(data->OemProductRevPtr) >> 16;
305    fpdata.off = (unsigned long)(data->OemProductRevPtr) & 0xffff;
306    data->OemProductRevPtr = PhysToVirt(fpdata);
307    if(!check_str(data->OemProductRevPtr)) data->OemProductRevPtr = NULL;
308#ifdef HAVE_VERBOSE_VAR
309    if(verbose > 1)
310    {
311      printf("vbelib:  OemProductRevPtr=%04X:%04X => %p\n",fpdata.seg,fpdata.off,data->OemProductRevPtr);
312      if(data->OemProductRevPtr) print_str(data->OemProductRevPtr);
313      fflush(stdout);
314    }
315#endif
316  }
317  return retval;
318}
319
320int vbeGetModeInfo(unsigned mode,struct VesaModeInfoBlock *data)
321{
322  struct LRMI_regs r;
323  void *rm_space;
324  int retval;
325  if(!(rm_space = LRMI_alloc_real(sizeof(struct VesaModeInfoBlock)))) return VBE_OUT_OF_DOS_MEM;
326  memset(&r,0,sizeof(struct LRMI_regs));
327  r.eax = 0x4f01;
328  r.ecx = mode;
329  r.es  = VirtToPhysSeg(rm_space);
330  r.edi = VirtToPhysOff(rm_space);
331  if(!VBE_LRMI_int(0x10,&r))
332  {
333     LRMI_free_real(rm_space);
334     return VBE_VM86_FAIL;
335  }
336  retval = r.eax & 0xffff;
337  if(retval == 0x4f)
338  {
339    retval = VBE_OK;
340    memcpy(data,rm_space,sizeof(struct VesaModeInfoBlock));
341  }
342  LRMI_free_real(rm_space);
343  return retval;
344}
345
346
347int vbeSetTV(unsigned int vesa_mode,unsigned int TV_mode) {
348
349#define NR_MODES 8
350
351unsigned int mode_table[NR_MODES] =   
352                        {0x101,0x103,0x111,0x114,0x120,0x121,0x122,0x123};
353unsigned int tv_table[][NR_MODES] = {
354                        {0x201,0x202,0x211,0x212,0x221,0x231,0x222,0x232},
355                        {0x200,0x203,0x210,0x213,0x220,0x230,0xFFFF,0xFFFF}};
356
357/*
358
359Alternate mode map. If modes like 320x240 and 400x300 does not work, but
360640x480 and 800x600 work, then try to replace above two lines with this
361lines and write email to me if it works.
362r.marek et sh.cvut.cz
363
364                        {0x201,0x202,0x211,0x212,0x222,0x223,0x224,0x225},
365                        {0x200,0x203,0x210,0x213,0x220,0x221,0xFFFF,0xFFFF}};
366
367*/                               
368  int i,retval;
369  struct LRMI_regs r;
370
371  memset(&r,0,sizeof(struct LRMI_regs));
372  for (i=0;((mode_table[i]!=(vesa_mode&0x3FF))&&(i<NR_MODES));i++) ;
373 
374  if (i==NR_MODES) return 0;
375#ifdef HAVE_VERBOSE_VAR
376  if(verbose > 1) printf("vbelib: Trying to set TV mode %x\n",tv_table[TV_mode][i]);
377#endif
378  r.eax = 0x4f14;
379  r.ebx = 0x20;
380  r.edx = 0;
381  r.edi = 0;
382  r.ecx =  tv_table[TV_mode][i];
383  retval = VBE_LRMI_int(0x10,&r);
384  if(!retval) return VBE_VM86_FAIL;
385  return r.eax & 0xffff;
386 
387}
388int vbeSetMode(unsigned mode,struct VesaCRTCInfoBlock *data)
389{
390  struct LRMI_regs r;
391  void *rm_space = NULL;
392  int retval;
393  memset(&r,0,sizeof(struct LRMI_regs));
394  if(data)
395  {
396    if(!(rm_space = LRMI_alloc_real(sizeof(struct VesaCRTCInfoBlock)))) return VBE_OUT_OF_DOS_MEM;
397    r.es  = VirtToPhysSeg(rm_space);
398    r.edi = VirtToPhysOff(rm_space);
399    memcpy(rm_space,data,sizeof(struct VesaCRTCInfoBlock));
400  }
401  r.eax = 0x4f02;
402  r.ebx = mode;
403  retval = VBE_LRMI_int(0x10,&r);
404  LRMI_free_real(rm_space);
405  if(!retval) return VBE_VM86_FAIL;
406  retval = r.eax & 0xffff;
407  if(retval == 0x4f)
408  {
409    /* Just info for internal use (currently in SetDiplayStart func). */
410    vbeGetModeInfo(mode,&curr_mode_info);
411    retval = VBE_OK;
412  }
413  return retval;
414}
415
416int vbeGetMode(unsigned *mode)
417{
418  struct LRMI_regs r;
419  int retval;
420  memset(&r,0,sizeof(struct LRMI_regs));
421  r.eax = 0x4f03;
422  if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL;
423  retval = r.eax & 0xffff;
424  if(retval == 0x4f)
425  {
426    *mode = r.ebx;
427    retval = VBE_OK;
428  }
429  return retval;
430}
431
432int vbeGetPixelClock(unsigned *mode,unsigned *pixel_clock) // in Hz
433{
434  struct LRMI_regs r;
435  int retval;
436  memset(&r,0,sizeof(struct LRMI_regs));
437  r.eax = 0x4f0b;
438  r.ebx = 0;
439  r.edx = *mode;
440  r.ecx = *pixel_clock;
441  if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL;
442  retval = r.eax & 0xffff;
443  if(retval == 0x4f)
444  {
445    *pixel_clock = r.ecx;
446    retval = VBE_OK;
447  }
448  return retval;
449}
450
451
452int vbeSaveState(void **data)
453{
454  struct LRMI_regs r;
455  int retval;
456  void *rm_space;
457  memset(&r,0,sizeof(struct LRMI_regs));
458  r.eax = 0x4f04;
459  r.edx = 0x00;
460  r.ecx = 0x0f;
461  if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL;
462  retval = r.eax & 0xffff;
463  if(retval != 0x4f) return retval;
464  if(!(rm_space = LRMI_alloc_real((r.ebx & 0xffff)*64))) return VBE_OUT_OF_DOS_MEM;
465  r.eax = 0x4f04;
466  r.edx = 0x01;
467  r.ecx = 0x0f;
468  r.es  = VirtToPhysSeg(rm_space);
469  r.ebx = VirtToPhysOff(rm_space);
470  if(!VBE_LRMI_int(0x10,&r))
471  {
472    LRMI_free_real(rm_space);
473    return VBE_VM86_FAIL;
474  }
475  retval = r.eax & 0xffff;
476  if(retval != 0x4f)
477  {
478    LRMI_free_real(rm_space);
479    return retval;
480  }
481  *data = rm_space;
482  return VBE_OK;
483}
484
485int vbeRestoreState(void *data)
486{
487  struct LRMI_regs r;
488  int retval;
489  memset(&r,0,sizeof(struct LRMI_regs));
490  r.eax = 0x4f04;
491  r.edx = 0x02;
492  r.ecx = 0x0f;
493  r.es  = VirtToPhysSeg(data);
494  r.ebx = VirtToPhysOff(data);
495  retval = VBE_LRMI_int(0x10,&r);
496  LRMI_free_real(data);
497  if(!retval) return VBE_VM86_FAIL;
498  retval = r.eax & 0xffff;
499  if(retval == 0x4f) retval = VBE_OK;
500  return retval;
501}
502
503int vbeGetWindow(unsigned *win_num)
504{
505  struct LRMI_regs r;
506  int retval;
507  memset(&r,0,sizeof(struct LRMI_regs));
508  r.eax = 0x4f05;
509  r.ebx = (*win_num & 0x0f) | 0x0100;
510  if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL;
511  retval = r.eax & 0xffff;
512  if(retval == 0x4f)
513  {
514    *win_num = r.edx & 0xffff;
515    retval = VBE_OK;
516  }
517  return retval;
518}
519
520int vbeSetWindow(unsigned win_num,unsigned win_gran)
521{
522  int retval;
523  if(vbe_pm_info.SetWindowCall)
524  {
525     /* Don't verbose this stuff from performance reasons */
526     /* 32-bit function call is much better of int 10h */
527     __asm __volatile(
528        "pushl  %%ebx\n"
529        "movl   %1, %%ebx\n"
530        "call   *%2\n"
531        "popl   %%ebx"
532        ::"a"(0x4f05),"S"(win_num & 0x0f),"D"(vbe_pm_info.SetWindowCall),
533        "d"(win_gran):"memory");
534    retval = VBE_OK;
535  }
536  else
537  {
538    struct LRMI_regs r;
539    memset(&r,0,sizeof(struct LRMI_regs));
540    r.eax = 0x4f05;
541    r.ebx = win_num & 0x0f;
542    r.edx = win_gran;
543    if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL;
544    retval = r.eax & 0xffff;
545    if(retval == 0x4f) retval = VBE_OK;
546  }
547  return retval;
548}
549
550int vbeGetScanLineLength(unsigned *num_pixels,unsigned *num_bytes)
551{
552  struct LRMI_regs r;
553  int retval;
554  memset(&r,0,sizeof(struct LRMI_regs));
555  r.eax = 0x4f06;
556  r.ebx = 1;
557  if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL;
558  retval = r.eax & 0xffff;
559  if(retval == 0x4f)
560  {
561    if(num_bytes)  *num_bytes = r.ebx & 0xffff;
562    if(num_pixels) *num_pixels= r.ecx & 0xffff;
563    retval = VBE_OK;
564  }
565  return retval;
566}
567
568int vbeGetMaxScanLines(unsigned *num_pixels,unsigned *num_bytes, unsigned *num_lines)
569{
570  struct LRMI_regs r;
571  int retval;
572  memset(&r,0,sizeof(struct LRMI_regs));
573  r.eax = 0x4f06;
574  r.ebx = 3;
575  if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL;
576  retval = r.eax & 0xffff;
577  if(retval == 0x4f)
578  {
579    if(num_bytes)  *num_bytes = r.ebx & 0xffff;
580    if(num_pixels) *num_pixels= r.ecx & 0xffff;
581    if(num_lines)  *num_lines = r.edx & 0xffff;
582    retval = VBE_OK;
583  }
584  return retval;
585}
586
587int vbeSetScanLineLength(unsigned num_pixels)
588{
589  int retval;
590  struct LRMI_regs r;
591  memset(&r,0,sizeof(struct LRMI_regs));
592  r.eax = 0x4f06;
593  r.ebx = 0;
594  r.ecx = num_pixels;
595  if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL;
596  retval = r.eax & 0xffff;
597  if(retval == 0x4f) retval = VBE_OK;
598  return retval;
599}
600
601int vbeSetScanLineLengthB(unsigned num_bytes)
602{
603  int retval;
604  struct LRMI_regs r;
605  memset(&r,0,sizeof(struct LRMI_regs));
606  r.eax = 0x4f06;
607  r.ebx = 2;
608  r.ecx = num_bytes;
609  if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL;
610  retval = r.eax & 0xffff;
611  if(retval == 0x4f) retval = VBE_OK;
612  return retval;
613}
614
615int vbeGetDisplayStart(unsigned *pixel_num,unsigned *scan_line)
616{
617  struct LRMI_regs r;
618  int retval;
619  memset(&r,0,sizeof(struct LRMI_regs));
620  r.eax = 0x4f07;
621  r.ebx = 1;
622  if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL;
623  retval = r.eax & 0xffff;
624  if(retval == 0x4f)
625  {
626    if(pixel_num) *pixel_num = r.ecx & 0xffff;
627    if(scan_line) *scan_line = r.edx & 0xffff;
628    retval = VBE_OK;
629  }
630  return retval;
631}
632
633int vbeSetDisplayStart(unsigned long offset, int vsync)
634{
635  int retval;
636  if(vbe_pm_info.SetDisplayStart)
637  {
638     /* Don't verbose this stuff from performance reasons */
639     /* 32-bit function call is much better of int 10h */
640     __asm __volatile(
641        "pushl  %%ebx\n"
642        "movl   %1, %%ebx\n"
643        "call   *%2\n"
644        "popl   %%ebx\n"
645        ::"a"(0x4f07),"S"(vsync ? 0x80 : 0),"D"(vbe_pm_info.SetDisplayStart),
646          "c"((offset>>2) & 0xffff),"d"((offset>>18)&0xffff):"memory");
647    retval = VBE_OK;
648  }
649  else
650  {
651    struct LRMI_regs r;
652    unsigned long pixel_num;
653    memset(&r,0,sizeof(struct LRMI_regs));
654    pixel_num = offset%(unsigned long)curr_mode_info.BytesPerScanLine;
655    if(pixel_num*(unsigned long)curr_mode_info.BytesPerScanLine!=offset) pixel_num++;
656    r.eax = 0x4f07;
657    r.ebx = vsync ? 0x82 : 2;
658    r.ecx = pixel_num;
659    r.edx = offset/(unsigned long)curr_mode_info.BytesPerScanLine;
660    if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL;
661    retval = r.eax & 0xffff;
662    if(retval == 0x4f) retval = VBE_OK;
663    else retval = VBE_BROKEN_BIOS;
664  }
665  return retval;
666}
667
668int vbeSetScheduledDisplayStart(unsigned long offset, int vsync)
669{
670  int retval;
671  struct LRMI_regs r;
672  unsigned long pixel_num;
673  memset(&r,0,sizeof(struct LRMI_regs));
674  pixel_num = offset%(unsigned long)curr_mode_info.BytesPerScanLine;
675  if(pixel_num*(unsigned long)curr_mode_info.BytesPerScanLine!=offset) pixel_num++;
676  r.eax = 0x4f07;
677  r.ebx = vsync ? 0x82 : 2;
678  r.ecx = offset;
679  if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL;
680  retval = r.eax & 0xffff;
681  if(retval == 0x4f) retval = VBE_OK;
682  return retval;
683}
684
685struct realVesaProtModeInterface
686{
687  unsigned short SetWindowCall;
688  unsigned short SetDisplayStart;
689  unsigned short SetPaletteData;
690  unsigned short iopl_ports;
691}__attribute__((packed));
692
693int vbeGetProtModeInfo(struct VesaProtModeInterface *pm_info)
694{
695  struct LRMI_regs r;
696  int retval;
697  unsigned info_offset;
698  struct realVesaProtModeInterface *rm_info;
699  memset(&r,0,sizeof(struct LRMI_regs));
700  r.eax = 0x4f0a;
701  r.ebx = 0;
702  if(!VBE_LRMI_int(0x10,&r)) return VBE_VM86_FAIL;
703  retval = r.eax & 0xffff;
704  if(retval == 0x4f)
705  {
706    retval = VBE_OK;
707    info_offset = r.edi&0xffff;
708    if((r.es >> 12) != hh_int_10_seg) retval = VBE_BROKEN_BIOS;
709    rm_info = PhysToVirtSO(r.es,info_offset);
710    pm_info->SetWindowCall   = PhysToVirtSO(r.es,info_offset+rm_info->SetWindowCall);
711    if(!is_addr_valid(pm_info->SetWindowCall)) retval = VBE_BROKEN_BIOS;
712#ifdef HAVE_VERBOSE_VAR
713    if(verbose > 1) printf("vbelib:  SetWindowCall=%04X:%04X => %p\n",r.es,info_offset+rm_info->SetWindowCall,pm_info->SetWindowCall);
714#endif
715    pm_info->SetDisplayStart = PhysToVirtSO(r.es,info_offset+rm_info->SetDisplayStart);
716    if(!is_addr_valid(pm_info->SetDisplayStart)) retval = VBE_BROKEN_BIOS;
717#ifdef HAVE_VERBOSE_VAR
718    if(verbose > 1) printf("vbelib:  SetDisplayStart=%04X:%04X => %p\n",r.es,info_offset+rm_info->SetDisplayStart,pm_info->SetDisplayStart);
719#endif
720    pm_info->SetPaletteData  = PhysToVirtSO(r.es,info_offset+rm_info->SetPaletteData);
721    if(!is_addr_valid(pm_info->SetPaletteData)) retval = VBE_BROKEN_BIOS;
722#ifdef HAVE_VERBOSE_VAR
723    if(verbose > 1) printf("vbelib:  SetPaletteData=%04X:%04X => %p\n",r.es,info_offset+rm_info->SetPaletteData,pm_info->SetPaletteData);
724#endif
725    pm_info->iopl_ports      = PhysToVirtSO(r.es,info_offset+rm_info->iopl_ports);
726    if(!rm_info->iopl_ports) pm_info->iopl_ports = NULL;
727    else
728    if(!check_wrd(pm_info->iopl_ports))
729    {
730        pm_info->iopl_ports = NULL;
731/*      retval = VBE_BROKEN_BIOS; <- It's for broken BIOSes only */
732    }   
733#ifdef HAVE_VERBOSE_VAR
734    if(verbose > 1)
735    {
736      printf("vbelib:  iopl_ports=%04X:%04X => %p\n",r.es,info_offset+rm_info->iopl_ports,pm_info->iopl_ports);
737      if(pm_info->iopl_ports) print_wrd(pm_info->iopl_ports);
738      fflush(stdout);
739    }
740#endif
741  }
742  return retval;
743}
744/* --------- Standard VGA stuff -------------- */
745int vbeWriteString(int x, int y, int attr, char *str)
746{
747  struct LRMI_regs r;
748  void *rm_space = NULL;
749  int retval;
750  memset(&r,0,sizeof(struct LRMI_regs));
751  r.ecx = strlen(str);
752  r.edx = ((y<<8)&0xff00)|(x&0xff);
753  r.ebx = attr;
754  if(!(rm_space = LRMI_alloc_real(r.ecx))) return VBE_OUT_OF_DOS_MEM;
755  r.es  = VirtToPhysSeg(rm_space);
756  r.ebp = VirtToPhysOff(rm_space);
757  memcpy(rm_space,str,r.ecx);
758  r.eax = 0x1300;
759  retval = VBE_LRMI_int(0x10,&r);
760  LRMI_free_real(rm_space);
761  if(!retval) return VBE_VM86_FAIL;
762  retval = r.eax & 0xffff;
763  if(retval == 0x4f) retval = VBE_OK;
764  return retval;
765}
766
767void * vbeMapVideoBuffer(unsigned long phys_addr,unsigned long size)
768{
769  void *lfb;
770  if(fd_mem == -1) return NULL;
771#ifdef HAVE_VERBOSE_VAR
772  if(verbose > 1) printf("vbelib: vbeMapVideoBuffer(%08lX,%08lX)\n",phys_addr,size);
773#endif
774  /* Here we don't need with MAP_FIXED and prefered address (first argument) */
775  lfb = mmap((void *)0,size,PROT_READ | PROT_WRITE,MAP_SHARED,fd_mem,phys_addr);
776  return lfb == (void *)-1 ? 0 : lfb;
777}
778
779void vbeUnmapVideoBuffer(unsigned long linear_addr,unsigned long size)
780{
781#ifdef HAVE_VERBOSE_VAR
782  if(verbose > 1) printf("vbelib: vbeUnmapVideoBuffer(%08lX,%08lX)\n",linear_addr,size);
783#endif
784  munmap((void *)linear_addr,size);
785}
Note: See TracBrowser for help on using the repository browser.