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