~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/vgabios/vbe.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// ============================================================================================
 
2
//  
 
3
//  Copyright (C) 2002 Jeroen Janssen
 
4
//
 
5
//  This library is free software; you can redistribute it and/or
 
6
//  modify it under the terms of the GNU Lesser General Public
 
7
//  License as published by the Free Software Foundation; either
 
8
//  version 2 of the License, or (at your option) any later version.
 
9
//
 
10
//  This library is distributed in the hope that it will be useful,
 
11
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
13
//  Lesser General Public License for more details.
 
14
//
 
15
//  You should have received a copy of the GNU Lesser General Public
 
16
//  License along with this library; if not, write to the Free Software
 
17
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 
18
// 
 
19
// ============================================================================================
 
20
//  
 
21
//  This VBE is part of the VGA Bios specific to the plex86/bochs Emulated VGA card. 
 
22
//  You can NOT drive any physical vga card with it. 
 
23
//
 
24
// ============================================================================================
 
25
//  
 
26
//  This VBE Bios is based on information taken from :
 
27
//   - VESA BIOS EXTENSION (VBE) Core Functions Standard Version 3.0 located at www.vesa.org
 
28
//
 
29
// ============================================================================================
 
30
 
 
31
 
 
32
// defines available
 
33
 
 
34
// disable VESA/VBE2 check in vbe info
 
35
//#define VBE2_NO_VESA_CHECK
 
36
 
 
37
 
 
38
#include "vbe.h"
 
39
#include "vbetables.h"
 
40
 
 
41
// The current OEM Software Revision of this VBE Bios
 
42
#define VBE_OEM_SOFTWARE_REV 0x0002;
 
43
 
 
44
extern char vbebios_copyright;
 
45
extern char vbebios_vendor_name;
 
46
extern char vbebios_product_name;
 
47
extern char vbebios_product_revision;
 
48
 
 
49
ASM_START
 
50
// FIXME: 'merge' these (c) etc strings with the vgabios.c strings?
 
51
_vbebios_copyright:
 
52
.ascii       "Bochs/Plex86 VBE(C) 2003 http://savannah.nongnu.org/projects/vgabios/"
 
53
.byte        0x00
 
54
 
 
55
_vbebios_vendor_name:
 
56
.ascii       "Bochs/Plex86 Developers"
 
57
.byte        0x00
 
58
 
 
59
_vbebios_product_name:
 
60
.ascii       "Bochs/Plex86 VBE Adapter"
 
61
.byte        0x00
 
62
 
 
63
_vbebios_product_revision:
 
64
.ascii       "$Id$"
 
65
.byte        0x00
 
66
 
 
67
_vbebios_info_string:
 
68
.ascii      "Bochs VBE Display Adapter enabled"
 
69
.byte   0x0a,0x0d
 
70
.byte   0x0a,0x0d
 
71
.byte   0x00
 
72
 
 
73
_no_vbebios_info_string:
 
74
.ascii      "NO Bochs VBE Support available!"
 
75
.byte   0x0a,0x0d
 
76
.byte   0x0a,0x0d
 
77
.byte 0x00
 
78
 
 
79
#if defined(USE_BX_INFO) || defined(DEBUG)
 
80
msg_vbe_init:
 
81
.ascii      "VBE Bios $Id$"
 
82
.byte   0x0a,0x0d, 0x00
 
83
#endif
 
84
 
 
85
  .align 2
 
86
vesa_pm_start:
 
87
  dw vesa_pm_set_window - vesa_pm_start
 
88
  dw vesa_pm_set_display_start - vesa_pm_start
 
89
  dw vesa_pm_unimplemented - vesa_pm_start
 
90
  dw vesa_pm_io_ports_table - vesa_pm_start
 
91
vesa_pm_io_ports_table:
 
92
  dw VBE_DISPI_IOPORT_INDEX
 
93
  dw VBE_DISPI_IOPORT_INDEX + 1
 
94
  dw VBE_DISPI_IOPORT_DATA
 
95
  dw VBE_DISPI_IOPORT_DATA + 1
 
96
  dw 0xffff
 
97
  dw 0xffff
 
98
 
 
99
  USE32
 
100
vesa_pm_set_window:
 
101
  cmp  bx, #0x00
 
102
  je  vesa_pm_set_display_window1
 
103
  mov  ax, #0x0100
 
104
  ret
 
105
vesa_pm_set_display_window1:
 
106
  mov  ax, dx
 
107
  push dx
 
108
  push ax
 
109
  mov  dx, # VBE_DISPI_IOPORT_INDEX
 
110
  mov  ax, # VBE_DISPI_INDEX_BANK
 
111
  out  dx, ax
 
112
  pop  ax
 
113
  mov  dx, # VBE_DISPI_IOPORT_DATA
 
114
  out  dx, ax
 
115
  in   ax, dx
 
116
  pop  dx
 
117
  cmp  dx, ax
 
118
  jne  illegal_window
 
119
  mov  ax, #0x004f
 
120
  ret
 
121
illegal_window:
 
122
  mov  ax, #0x014f
 
123
  ret
 
124
 
 
125
vesa_pm_set_display_start:
 
126
  cmp  bl, #0x80
 
127
  je   vesa_pm_set_display_start1
 
128
  cmp  bl, #0x00
 
129
  je   vesa_pm_set_display_start1
 
130
  mov  ax, #0x0100
 
131
  ret
 
132
vesa_pm_set_display_start1:
 
133
; convert offset to (X, Y) coordinate 
 
134
; (would be simpler to change Bochs VBE API...)
 
135
  push eax
 
136
  push ecx
 
137
  push edx
 
138
  push esi
 
139
  push edi
 
140
  shl edx, #16
 
141
  and ecx, #0xffff
 
142
  or ecx, edx
 
143
  shl ecx, #2
 
144
  mov eax, ecx
 
145
 
 
146
  push eax
 
147
  mov  dx, # VBE_DISPI_IOPORT_INDEX
 
148
  mov  ax, # VBE_DISPI_INDEX_VIRT_WIDTH
 
149
  out  dx, ax
 
150
  mov  dx, # VBE_DISPI_IOPORT_DATA
 
151
  in   ax, dx
 
152
  movzx ecx, ax
 
153
 
 
154
  mov  dx, # VBE_DISPI_IOPORT_INDEX
 
155
  mov  ax, # VBE_DISPI_INDEX_BPP
 
156
  out  dx, ax
 
157
  mov  dx, # VBE_DISPI_IOPORT_DATA
 
158
  in   ax, dx
 
159
  movzx esi, ax
 
160
  pop  eax
 
161
 
 
162
  cmp esi, #4
 
163
  jz bpp4_mode
 
164
  add esi, #7
 
165
  shr esi, #3
 
166
  imul ecx, esi
 
167
  xor edx, edx
 
168
  div ecx
 
169
  mov edi, eax
 
170
  mov eax, edx
 
171
  xor edx, edx
 
172
  div esi
 
173
  jmp set_xy_regs
 
174
 
 
175
bpp4_mode:
 
176
  shr ecx, #1
 
177
  xor edx, edx
 
178
  div ecx
 
179
  mov edi, eax
 
180
  mov eax, edx
 
181
  shl eax, #1
 
182
 
 
183
set_xy_regs:
 
184
  push dx
 
185
  push ax
 
186
  mov  dx, # VBE_DISPI_IOPORT_INDEX
 
187
  mov  ax, # VBE_DISPI_INDEX_X_OFFSET
 
188
  out  dx, ax
 
189
  pop  ax
 
190
  mov  dx, # VBE_DISPI_IOPORT_DATA
 
191
  out  dx, ax
 
192
  pop  dx
 
193
 
 
194
  mov  ax, di
 
195
  push dx
 
196
  push ax
 
197
  mov  dx, # VBE_DISPI_IOPORT_INDEX
 
198
  mov  ax, # VBE_DISPI_INDEX_Y_OFFSET
 
199
  out  dx, ax
 
200
  pop  ax
 
201
  mov  dx, # VBE_DISPI_IOPORT_DATA
 
202
  out  dx, ax
 
203
  pop  dx
 
204
 
 
205
  pop edi
 
206
  pop esi
 
207
  pop edx
 
208
  pop ecx
 
209
  pop eax
 
210
  mov  ax, #0x004f
 
211
  ret
 
212
 
 
213
vesa_pm_unimplemented:
 
214
  mov ax, #0x014f
 
215
  ret
 
216
  USE16
 
217
vesa_pm_end:
 
218
 
 
219
; DISPI ioport functions
 
220
 
 
221
dispi_get_id:
 
222
  push dx
 
223
  mov  dx, # VBE_DISPI_IOPORT_INDEX
 
224
  mov  ax, # VBE_DISPI_INDEX_ID
 
225
  out  dx, ax
 
226
  mov  dx, # VBE_DISPI_IOPORT_DATA
 
227
  in   ax, dx
 
228
  pop  dx
 
229
  ret
 
230
 
 
231
dispi_set_id:
 
232
  push dx
 
233
  push ax
 
234
  mov  dx, # VBE_DISPI_IOPORT_INDEX
 
235
  mov  ax, # VBE_DISPI_INDEX_ID
 
236
  out  dx, ax
 
237
  pop  ax
 
238
  mov  dx, # VBE_DISPI_IOPORT_DATA
 
239
  out  dx, ax
 
240
  pop  dx
 
241
  ret
 
242
ASM_END
 
243
 
 
244
static void dispi_set_xres(xres)
 
245
  Bit16u xres;
 
246
{
 
247
ASM_START
 
248
  push bp
 
249
  mov  bp, sp
 
250
  push ax
 
251
  push dx
 
252
 
 
253
  mov  dx, # VBE_DISPI_IOPORT_INDEX
 
254
  mov  ax, # VBE_DISPI_INDEX_XRES
 
255
  out  dx, ax
 
256
  mov  dx, # VBE_DISPI_IOPORT_DATA
 
257
  mov  ax, 4[bp] ; xres
 
258
  out  dx, ax
 
259
 
 
260
  pop  dx
 
261
  pop  ax
 
262
  pop  bp
 
263
ASM_END
 
264
}
 
265
 
 
266
static void dispi_set_yres(yres)
 
267
  Bit16u yres;
 
268
{
 
269
  outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_YRES);
 
270
  outw(VBE_DISPI_IOPORT_DATA,yres);
 
271
}
 
272
 
 
273
static void dispi_set_bpp(bpp)
 
274
  Bit16u bpp;
 
275
{
 
276
  outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_BPP);
 
277
  outw(VBE_DISPI_IOPORT_DATA,bpp);
 
278
}
 
279
 
 
280
ASM_START
 
281
; AL = bits per pixel / AH = bytes per pixel
 
282
dispi_get_bpp:
 
283
  push dx
 
284
  mov  dx, # VBE_DISPI_IOPORT_INDEX
 
285
  mov  ax, # VBE_DISPI_INDEX_BPP
 
286
  out  dx, ax
 
287
  mov  dx, # VBE_DISPI_IOPORT_DATA
 
288
  in   ax, dx
 
289
  mov  ah, al
 
290
  shr  ah, 3
 
291
  test al, #0x07
 
292
  jz   get_bpp_noinc
 
293
  inc  ah
 
294
get_bpp_noinc:
 
295
  pop  dx
 
296
  ret
 
297
 
 
298
; get display capabilities
 
299
 
 
300
_dispi_get_max_xres:
 
301
  push dx
 
302
  push bx
 
303
  call dispi_get_enable
 
304
  mov  bx, ax
 
305
  or   ax, # VBE_DISPI_GETCAPS
 
306
  call _dispi_set_enable
 
307
  mov  dx, # VBE_DISPI_IOPORT_INDEX
 
308
  mov  ax, # VBE_DISPI_INDEX_XRES
 
309
  out  dx, ax
 
310
  mov  dx, # VBE_DISPI_IOPORT_DATA
 
311
  in   ax, dx
 
312
  push ax
 
313
  mov  ax, bx
 
314
  call _dispi_set_enable
 
315
  pop  ax
 
316
  pop  bx
 
317
  pop  dx
 
318
  ret
 
319
 
 
320
_dispi_get_max_bpp:
 
321
  push dx
 
322
  push bx
 
323
  call dispi_get_enable
 
324
  mov  bx, ax
 
325
  or   ax, # VBE_DISPI_GETCAPS
 
326
  call _dispi_set_enable
 
327
  mov  dx, # VBE_DISPI_IOPORT_INDEX
 
328
  mov  ax, # VBE_DISPI_INDEX_BPP
 
329
  out  dx, ax
 
330
  mov  dx, # VBE_DISPI_IOPORT_DATA
 
331
  in   ax, dx
 
332
  push ax
 
333
  mov  ax, bx
 
334
  call _dispi_set_enable
 
335
  pop  ax
 
336
  pop  bx
 
337
  pop  dx
 
338
  ret
 
339
 
 
340
_dispi_set_enable:
 
341
  push dx
 
342
  push ax
 
343
  mov  dx, # VBE_DISPI_IOPORT_INDEX
 
344
  mov  ax, # VBE_DISPI_INDEX_ENABLE
 
345
  out  dx, ax
 
346
  pop  ax
 
347
  mov  dx, # VBE_DISPI_IOPORT_DATA
 
348
  out  dx, ax
 
349
  pop  dx
 
350
  ret
 
351
 
 
352
dispi_get_enable:
 
353
  push dx
 
354
  mov  dx, # VBE_DISPI_IOPORT_INDEX
 
355
  mov  ax, # VBE_DISPI_INDEX_ENABLE
 
356
  out  dx, ax
 
357
  mov  dx, # VBE_DISPI_IOPORT_DATA
 
358
  in   ax, dx
 
359
  pop  dx
 
360
  ret
 
361
 
 
362
_dispi_set_bank:
 
363
  push dx
 
364
  push ax
 
365
  mov  dx, # VBE_DISPI_IOPORT_INDEX
 
366
  mov  ax, # VBE_DISPI_INDEX_BANK
 
367
  out  dx, ax
 
368
  pop  ax
 
369
  mov  dx, # VBE_DISPI_IOPORT_DATA
 
370
  out  dx, ax
 
371
  pop  dx
 
372
  ret
 
373
 
 
374
dispi_get_bank:
 
375
  push dx
 
376
  mov  dx, # VBE_DISPI_IOPORT_INDEX
 
377
  mov  ax, # VBE_DISPI_INDEX_BANK
 
378
  out  dx, ax
 
379
  mov  dx, # VBE_DISPI_IOPORT_DATA
 
380
  in   ax, dx
 
381
  pop  dx
 
382
  ret
 
383
ASM_END
 
384
 
 
385
static void dispi_set_bank_farcall()
 
386
{
 
387
ASM_START
 
388
  cmp bx,#0x0100
 
389
  je dispi_set_bank_farcall_get
 
390
  or bx,bx
 
391
  jnz dispi_set_bank_farcall_error
 
392
  mov ax,dx
 
393
  push dx
 
394
  push ax
 
395
  mov ax,# VBE_DISPI_INDEX_BANK
 
396
  mov dx,# VBE_DISPI_IOPORT_INDEX
 
397
  out dx,ax
 
398
  pop ax
 
399
  mov dx,# VBE_DISPI_IOPORT_DATA
 
400
  out dx,ax
 
401
  in  ax,dx
 
402
  pop dx
 
403
  cmp dx,ax
 
404
  jne dispi_set_bank_farcall_error
 
405
  mov ax, #0x004f
 
406
  retf
 
407
dispi_set_bank_farcall_get:
 
408
  mov ax,# VBE_DISPI_INDEX_BANK
 
409
  mov dx,# VBE_DISPI_IOPORT_INDEX
 
410
  out dx,ax
 
411
  mov dx,# VBE_DISPI_IOPORT_DATA
 
412
  in ax,dx
 
413
  mov dx,ax
 
414
  retf
 
415
dispi_set_bank_farcall_error:
 
416
  mov ax,#0x014F
 
417
  retf
 
418
ASM_END
 
419
}
 
420
 
 
421
ASM_START
 
422
dispi_set_x_offset:
 
423
  push dx
 
424
  push ax
 
425
  mov  dx, # VBE_DISPI_IOPORT_INDEX
 
426
  mov  ax, # VBE_DISPI_INDEX_X_OFFSET
 
427
  out  dx, ax
 
428
  pop  ax
 
429
  mov  dx, # VBE_DISPI_IOPORT_DATA
 
430
  out  dx, ax
 
431
  pop  dx
 
432
  ret
 
433
 
 
434
dispi_get_x_offset:
 
435
  push dx
 
436
  mov  dx, # VBE_DISPI_IOPORT_INDEX
 
437
  mov  ax, # VBE_DISPI_INDEX_X_OFFSET
 
438
  out  dx, ax
 
439
  mov  dx, # VBE_DISPI_IOPORT_DATA
 
440
  in   ax, dx
 
441
  pop  dx
 
442
  ret
 
443
 
 
444
dispi_set_y_offset:
 
445
  push dx
 
446
  push ax
 
447
  mov  dx, # VBE_DISPI_IOPORT_INDEX
 
448
  mov  ax, # VBE_DISPI_INDEX_Y_OFFSET
 
449
  out  dx, ax
 
450
  pop  ax
 
451
  mov  dx, # VBE_DISPI_IOPORT_DATA
 
452
  out  dx, ax
 
453
  pop  dx
 
454
  ret
 
455
 
 
456
dispi_get_y_offset:
 
457
  push dx
 
458
  mov  dx, # VBE_DISPI_IOPORT_INDEX
 
459
  mov  ax, # VBE_DISPI_INDEX_Y_OFFSET
 
460
  out  dx, ax
 
461
  mov  dx, # VBE_DISPI_IOPORT_DATA
 
462
  in   ax, dx
 
463
  pop  dx
 
464
  ret
 
465
 
 
466
vga_set_virt_width:
 
467
  push ax
 
468
  push bx
 
469
  push dx
 
470
  mov  bx, ax
 
471
  call dispi_get_bpp
 
472
  cmp  al, #0x04
 
473
  ja   set_width_svga
 
474
  shr  bx, #1
 
475
set_width_svga:
 
476
  shr  bx, #3
 
477
  mov  dx, # VGAREG_VGA_CRTC_ADDRESS
 
478
  mov  ah, bl
 
479
  mov  al, #0x13
 
480
  out  dx, ax
 
481
  pop  dx
 
482
  pop  bx
 
483
  pop  ax
 
484
  ret
 
485
 
 
486
dispi_set_virt_width:
 
487
  call vga_set_virt_width
 
488
  push dx
 
489
  push ax
 
490
  mov  dx, # VBE_DISPI_IOPORT_INDEX
 
491
  mov  ax, # VBE_DISPI_INDEX_VIRT_WIDTH
 
492
  out  dx, ax
 
493
  pop  ax
 
494
  mov  dx, # VBE_DISPI_IOPORT_DATA
 
495
  out  dx, ax
 
496
  pop  dx
 
497
  ret
 
498
 
 
499
dispi_get_virt_width:
 
500
  push dx
 
501
  mov  dx, # VBE_DISPI_IOPORT_INDEX
 
502
  mov  ax, # VBE_DISPI_INDEX_VIRT_WIDTH
 
503
  out  dx, ax
 
504
  mov  dx, # VBE_DISPI_IOPORT_DATA
 
505
  in   ax, dx
 
506
  pop  dx
 
507
  ret
 
508
 
 
509
dispi_get_virt_height:
 
510
  push dx
 
511
  mov  dx, # VBE_DISPI_IOPORT_INDEX
 
512
  mov  ax, # VBE_DISPI_INDEX_VIRT_HEIGHT
 
513
  out  dx, ax
 
514
  mov  dx, # VBE_DISPI_IOPORT_DATA
 
515
  in   ax, dx
 
516
  pop  dx
 
517
  ret
 
518
 
 
519
_vga_compat_setup:
 
520
  push ax
 
521
  push dx
 
522
 
 
523
  ; set CRT X resolution
 
524
  mov  dx, # VBE_DISPI_IOPORT_INDEX
 
525
  mov  ax, # VBE_DISPI_INDEX_XRES
 
526
  out  dx, ax
 
527
  mov  dx, # VBE_DISPI_IOPORT_DATA
 
528
  in   ax, dx
 
529
  push ax
 
530
  mov  dx, # VGAREG_VGA_CRTC_ADDRESS
 
531
  mov  ax, #0x0011
 
532
  out  dx, ax
 
533
  pop  ax
 
534
  push ax
 
535
  shr  ax, #3
 
536
  dec  ax
 
537
  mov  ah, al
 
538
  mov  al, #0x01
 
539
  out  dx, ax
 
540
  pop  ax
 
541
  call vga_set_virt_width
 
542
 
 
543
  ; set CRT Y resolution
 
544
  mov  dx, # VBE_DISPI_IOPORT_INDEX
 
545
  mov  ax, # VBE_DISPI_INDEX_YRES
 
546
  out  dx, ax
 
547
  mov  dx, # VBE_DISPI_IOPORT_DATA
 
548
  in   ax, dx
 
549
  dec  ax
 
550
  push ax
 
551
  mov  dx, # VGAREG_VGA_CRTC_ADDRESS
 
552
  mov  ah, al
 
553
  mov  al, #0x12
 
554
  out  dx, ax
 
555
  pop  ax
 
556
  mov  al, #0x07
 
557
  out  dx, al
 
558
  inc  dx
 
559
  in   al, dx
 
560
  and  al, #0xbd
 
561
  test ah, #0x01
 
562
  jz   bit8_clear
 
563
  or   al, #0x02
 
564
bit8_clear:
 
565
  test ah, #0x02
 
566
  jz   bit9_clear
 
567
  or   al, #0x40
 
568
bit9_clear:
 
569
  out  dx, al
 
570
 
 
571
  ; other settings
 
572
  mov  dx, # VGAREG_VGA_CRTC_ADDRESS
 
573
  mov  ax, #0x0009
 
574
  out  dx, ax
 
575
  mov  al, #0x17
 
576
  out  dx, al
 
577
  mov  dx, # VGAREG_VGA_CRTC_DATA
 
578
  in   al, dx
 
579
  or   al, #0x03
 
580
  out  dx, al
 
581
  mov  dx, # VGAREG_ACTL_RESET
 
582
  in   al, dx
 
583
  mov  dx, # VGAREG_ACTL_ADDRESS
 
584
  mov  al, #0x10
 
585
  out  dx, al
 
586
  mov  dx, # VGAREG_ACTL_READ_DATA
 
587
  in   al, dx
 
588
  or   al, #0x01
 
589
  mov  dx, # VGAREG_ACTL_ADDRESS
 
590
  out  dx, al
 
591
  mov  al, #0x20
 
592
  out  dx, al
 
593
  mov  dx, # VGAREG_GRDC_ADDRESS
 
594
  mov  ax, #0x0506
 
595
  out  dx, ax
 
596
  mov  dx, # VGAREG_SEQU_ADDRESS
 
597
  mov  ax, #0x0f02
 
598
  out  dx, ax
 
599
 
 
600
  ; settings for >= 8bpp
 
601
  mov  dx, # VBE_DISPI_IOPORT_INDEX
 
602
  mov  ax, # VBE_DISPI_INDEX_BPP
 
603
  out  dx, ax
 
604
  mov  dx, # VBE_DISPI_IOPORT_DATA
 
605
  in   ax, dx
 
606
  cmp  al, #0x08
 
607
  jb   vga_compat_end
 
608
  mov  dx, # VGAREG_VGA_CRTC_ADDRESS
 
609
  mov  al, #0x14
 
610
  out  dx, al
 
611
  mov  dx, # VGAREG_VGA_CRTC_DATA
 
612
  in   al, dx
 
613
  or   al, #0x40
 
614
  out  dx, al
 
615
  mov  dx, # VGAREG_ACTL_RESET
 
616
  in   al, dx
 
617
  mov  dx, # VGAREG_ACTL_ADDRESS
 
618
  mov  al, #0x10
 
619
  out  dx, al
 
620
  mov  dx, # VGAREG_ACTL_READ_DATA
 
621
  in   al, dx
 
622
  or   al, #0x40
 
623
  mov  dx, # VGAREG_ACTL_ADDRESS
 
624
  out  dx, al
 
625
  mov  al, #0x20
 
626
  out  dx, al
 
627
  mov  dx, # VGAREG_SEQU_ADDRESS
 
628
  mov  al, #0x04
 
629
  out  dx, al
 
630
  mov  dx, # VGAREG_SEQU_DATA
 
631
  in   al, dx
 
632
  or   al, #0x08
 
633
  out  dx, al
 
634
  mov  dx, # VGAREG_GRDC_ADDRESS
 
635
  mov  al, #0x05
 
636
  out  dx, al
 
637
  mov  dx, # VGAREG_GRDC_DATA
 
638
  in   al, dx
 
639
  and  al, #0x9f
 
640
  or   al, #0x40
 
641
  out  dx, al
 
642
 
 
643
vga_compat_end:
 
644
  pop  dx
 
645
  pop  ax
 
646
ASM_END
 
647
 
 
648
 
 
649
// ModeInfo helper function
 
650
static ModeInfoListItem* mode_info_find_mode(mode, using_lfb)
 
651
  Bit16u mode; Boolean using_lfb;
 
652
{
 
653
  ModeInfoListItem  *cur_info=&mode_info_list;
 
654
 
 
655
  while (cur_info->mode != VBE_VESA_MODE_END_OF_LIST)
 
656
  {
 
657
    if (cur_info->mode == mode)
 
658
    {
 
659
      if (!using_lfb)
 
660
      {
 
661
        return cur_info;
 
662
      }
 
663
      else if (cur_info->info.ModeAttributes & VBE_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER_MODE)
 
664
      {
 
665
        return cur_info;
 
666
      }
 
667
      else
 
668
      {
 
669
        cur_info++;
 
670
      }
 
671
    }
 
672
    else
 
673
    {
 
674
      cur_info++;
 
675
    }
 
676
  }
 
677
 
 
678
  return 0;
 
679
}
 
680
 
 
681
ASM_START
 
682
 
 
683
; Has VBE display - Returns true if VBE display detected
 
684
 
 
685
_vbe_has_vbe_display:
 
686
  push ds
 
687
  push bx
 
688
  mov  ax, # BIOSMEM_SEG
 
689
  mov  ds, ax
 
690
  mov  bx, # BIOSMEM_VBE_FLAG
 
691
  mov  al, [bx]
 
692
  and  al, #0x01
 
693
  xor  ah, ah
 
694
  pop  bx
 
695
  pop  ds
 
696
  ret
 
697
 
 
698
; VBE Init - Initialise the Vesa Bios Extension Code
 
699
; This function does a sanity check on the host side display code interface.
 
700
 
 
701
vbe_init:
 
702
  mov  ax, # VBE_DISPI_ID0
 
703
  call dispi_set_id
 
704
  call dispi_get_id
 
705
  cmp  ax, # VBE_DISPI_ID0
 
706
  jne  no_vbe_interface
 
707
  push ds
 
708
  push bx
 
709
  mov  ax, # BIOSMEM_SEG
 
710
  mov  ds, ax
 
711
  mov  bx, # BIOSMEM_VBE_FLAG
 
712
  mov  al, #0x01
 
713
  mov  [bx], al
 
714
  pop  bx
 
715
  pop  ds
 
716
  mov  ax, # VBE_DISPI_ID5
 
717
  call dispi_set_id
 
718
no_vbe_interface:
 
719
#if defined(USE_BX_INFO) || defined(DEBUG)
 
720
  mov  bx, #msg_vbe_init
 
721
  push bx
 
722
  call _printf
 
723
  inc  sp
 
724
  inc  sp
 
725
#endif
 
726
  ret
 
727
 
 
728
; VBE Display Info - Display information on screen about the VBE
 
729
 
 
730
vbe_display_info:
 
731
  call _vbe_has_vbe_display
 
732
  test ax, ax
 
733
  jz   no_vbe_flag
 
734
  mov  ax, #0xc000
 
735
  mov  ds, ax
 
736
  mov  si, #_vbebios_info_string
 
737
  jmp  _display_string
 
738
no_vbe_flag:
 
739
  mov  ax, #0xc000
 
740
  mov  ds, ax
 
741
  mov  si, #_no_vbebios_info_string
 
742
  jmp  _display_string
 
743
 
 
744
; helper function for memory size calculation
 
745
 
 
746
lmulul:
 
747
  and eax, #0x0000FFFF
 
748
  shl ebx, #16
 
749
  or  eax, ebx
 
750
  SEG SS
 
751
  mul eax, dword ptr [di]
 
752
  mov ebx, eax
 
753
  shr ebx, #16
 
754
  ret
 
755
ASM_END
 
756
 
 
757
/** Function 00h - Return VBE Controller Information
 
758
 * 
 
759
 * Input:
 
760
 *              AX      = 4F00h
 
761
 *              ES:DI   = Pointer to buffer in which to place VbeInfoBlock structure
 
762
 *                        (VbeSignature should be VBE2 when VBE 2.0 information is desired and
 
763
 *                        the info block is 512 bytes in size)
 
764
 * Output:
 
765
 *              AX      = VBE Return Status
 
766
 * 
 
767
 */
 
768
void vbe_biosfn_return_controller_information(AX, ES, DI)
 
769
Bit16u *AX;Bit16u ES;Bit16u DI;
 
770
{
 
771
        Bit16u            ss=get_SS();
 
772
        VbeInfoBlock      vbe_info_block;
 
773
        Bit16u            status;
 
774
        Bit16u            result;
 
775
        Bit16u            vbe2_info;
 
776
        Bit16u            cur_mode=0;
 
777
        Bit16u            cur_ptr=34;
 
778
        Bit16u            size_64k;
 
779
        ModeInfoListItem  *cur_info=&mode_info_list;
 
780
 
 
781
        status = read_word(ss, AX);
 
782
 
 
783
#ifdef DEBUG
 
784
        printf("VBE vbe_biosfn_return_vbe_info ES%x DI%x AX%x\n",ES,DI,status);
 
785
#endif
 
786
 
 
787
        vbe2_info = 0;
 
788
#ifdef VBE2_NO_VESA_CHECK
 
789
#else
 
790
        // get vbe_info_block into local variable
 
791
        memcpyb(ss, &vbe_info_block, ES, DI, sizeof(vbe_info_block));
 
792
 
 
793
        // check for VBE2 signature
 
794
        if (((vbe_info_block.VbeSignature[0] == 'V') &&
 
795
             (vbe_info_block.VbeSignature[1] == 'B') &&
 
796
             (vbe_info_block.VbeSignature[2] == 'E') &&
 
797
             (vbe_info_block.VbeSignature[3] == '2')) ||
 
798
 
 
799
            ((vbe_info_block.VbeSignature[0] == 'V') &&
 
800
             (vbe_info_block.VbeSignature[1] == 'E') &&
 
801
             (vbe_info_block.VbeSignature[2] == 'S') &&
 
802
             (vbe_info_block.VbeSignature[3] == 'A')) )
 
803
        {
 
804
                vbe2_info = 1;
 
805
#ifdef DEBUG
 
806
                printf("VBE correct VESA/VBE2 signature found\n");
 
807
#endif
 
808
        }
 
809
#endif
 
810
 
 
811
        // VBE Signature
 
812
        vbe_info_block.VbeSignature[0] = 'V';
 
813
        vbe_info_block.VbeSignature[1] = 'E';
 
814
        vbe_info_block.VbeSignature[2] = 'S';
 
815
        vbe_info_block.VbeSignature[3] = 'A';
 
816
 
 
817
        // VBE Version supported
 
818
        vbe_info_block.VbeVersion = 0x0200;
 
819
 
 
820
        // OEM String
 
821
        vbe_info_block.OemStringPtr_Seg = 0xc000;
 
822
        vbe_info_block.OemStringPtr_Off = &vbebios_copyright;
 
823
 
 
824
        // Capabilities
 
825
        vbe_info_block.Capabilities[0] = VBE_CAPABILITY_8BIT_DAC;
 
826
        vbe_info_block.Capabilities[1] = 0;
 
827
        vbe_info_block.Capabilities[2] = 0;
 
828
        vbe_info_block.Capabilities[3] = 0;
 
829
 
 
830
        // VBE Video Mode Pointer (dynamicly generated from the mode_info_list)
 
831
        vbe_info_block.VideoModePtr_Seg= ES ;
 
832
        vbe_info_block.VideoModePtr_Off= DI + 34;
 
833
 
 
834
        // VBE Total Memory (in 64k blocks)
 
835
        outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_VIDEO_MEMORY_64K);
 
836
        vbe_info_block.TotalMemory = inw(VBE_DISPI_IOPORT_DATA);
 
837
 
 
838
        if (vbe2_info)
 
839
        {
 
840
                // OEM Stuff
 
841
                vbe_info_block.OemSoftwareRev = VBE_OEM_SOFTWARE_REV;
 
842
                vbe_info_block.OemVendorNamePtr_Seg = 0xc000;
 
843
                vbe_info_block.OemVendorNamePtr_Off = &vbebios_vendor_name;
 
844
                vbe_info_block.OemProductNamePtr_Seg = 0xc000;
 
845
                vbe_info_block.OemProductNamePtr_Off = &vbebios_product_name;
 
846
                vbe_info_block.OemProductRevPtr_Seg = 0xc000;
 
847
                vbe_info_block.OemProductRevPtr_Off = &vbebios_product_revision;
 
848
 
 
849
                // copy updates in vbe_info_block back
 
850
                memcpyb(ES, DI, ss, &vbe_info_block, sizeof(vbe_info_block));
 
851
        }
 
852
        else
 
853
        {
 
854
                // copy updates in vbe_info_block back (VBE 1.x compatibility)
 
855
                memcpyb(ES, DI, ss, &vbe_info_block, 256);
 
856
        }
 
857
 
 
858
        do
 
859
        {
 
860
                size_64k = (Bit16u)((Bit32u)cur_info->info.XResolution * cur_info->info.XResolution * cur_info->info.BitsPerPixel) >> 19;
 
861
 
 
862
                if ((cur_info->info.XResolution <= dispi_get_max_xres()) &&
 
863
                    (cur_info->info.BitsPerPixel <= dispi_get_max_bpp()) &&
 
864
                    (size_64k <= vbe_info_block.TotalMemory)) {
 
865
#ifdef DEBUG
 
866
                  printf("VBE found mode %x => %x\n", cur_info->mode,cur_mode);
 
867
#endif
 
868
                  write_word(ES, DI + cur_ptr, cur_info->mode);
 
869
                  cur_mode++;
 
870
                  cur_ptr+=2;
 
871
                } else {
 
872
#ifdef DEBUG
 
873
                  printf("VBE mode %x (xres=%x / bpp=%02x) not supported \n", cur_info->mode,cur_info->info.XResolution,cur_info->info.BitsPerPixel);
 
874
#endif
 
875
                }
 
876
                cur_info++;
 
877
        } while (cur_info->mode != VBE_VESA_MODE_END_OF_LIST);
 
878
 
 
879
        // Add vesa mode list terminator
 
880
        write_word(ES, DI + cur_ptr, cur_info->mode);
 
881
 
 
882
        result = 0x4f;
 
883
 
 
884
        write_word(ss, AX, result);
 
885
}
 
886
 
 
887
 
 
888
/** Function 01h - Return VBE Mode Information
 
889
 * 
 
890
 * Input:
 
891
 *              AX      = 4F01h
 
892
 *              CX      = Mode Number
 
893
 *              ES:DI   = Pointer to buffer in which to place ModeInfoBlock structure
 
894
 * Output:
 
895
 *              AX      = VBE Return Status
 
896
 * 
 
897
 */
 
898
void vbe_biosfn_return_mode_information(AX, CX, ES, DI)
 
899
Bit16u *AX;Bit16u CX; Bit16u ES;Bit16u DI;
 
900
{
 
901
        Bit16u            result=0x0100;
 
902
        Bit16u            ss=get_SS();
 
903
        ModeInfoBlock     info;
 
904
        ModeInfoListItem  *cur_info;
 
905
        Boolean           using_lfb;
 
906
        Bit16u            lfb_addr;
 
907
 
 
908
#ifdef DEBUG
 
909
        printf("VBE vbe_biosfn_return_mode_information ES%x DI%x CX%x\n",ES,DI,CX);
 
910
#endif
 
911
 
 
912
        using_lfb=((CX & VBE_MODE_LINEAR_FRAME_BUFFER) == VBE_MODE_LINEAR_FRAME_BUFFER);
 
913
 
 
914
        CX = (CX & 0x1ff);
 
915
 
 
916
        cur_info = mode_info_find_mode(CX, using_lfb, &cur_info);
 
917
 
 
918
        if (cur_info != 0)
 
919
        {
 
920
#ifdef DEBUG
 
921
                printf("VBE found mode %x\n",CX);
 
922
#endif
 
923
                memsetb(ss, &info, 0, sizeof(ModeInfoBlock));
 
924
                memcpyb(ss, &info, 0xc000, &(cur_info->info), sizeof(ModeInfoBlockCompact));
 
925
                if (using_lfb) {
 
926
                  info.NumberOfBanks = 1;
 
927
                }
 
928
#ifdef PCI_VID
 
929
                lfb_addr = pci_get_lfb_addr(PCI_VID);
 
930
#else
 
931
                lfb_addr = 0;
 
932
#endif
 
933
                if (lfb_addr > 0) {
 
934
                  info.PhysBasePtr = ((Bit32u)lfb_addr << 16);
 
935
                }
 
936
                if (info.WinAAttributes & VBE_WINDOW_ATTRIBUTE_RELOCATABLE) {
 
937
                  info.WinFuncPtr = 0xC0000000UL;
 
938
                  *(Bit16u *)&(info.WinFuncPtr) = (Bit16u)(dispi_set_bank_farcall);
 
939
                }
 
940
 
 
941
                result = 0x4f;
 
942
        }
 
943
        else
 
944
        {
 
945
#ifdef DEBUG
 
946
                printf("VBE *NOT* found mode %x\n",CX);
 
947
#endif
 
948
                result = 0x100;
 
949
        }
 
950
 
 
951
        if (result == 0x4f)
 
952
        {
 
953
                // copy updates in mode_info_block back
 
954
                memcpyb(ES, DI, ss, &info, sizeof(info));
 
955
        }
 
956
 
 
957
        write_word(ss, AX, result);
 
958
}
 
959
 
 
960
/** Function 02h - Set VBE Mode
 
961
 * 
 
962
 * Input:
 
963
 *              AX      = 4F02h
 
964
 *              BX      = Desired Mode to set
 
965
 *              ES:DI   = Pointer to CRTCInfoBlock structure
 
966
 * Output:
 
967
 *              AX      = VBE Return Status
 
968
 * 
 
969
 */
 
970
void vbe_biosfn_set_mode(AX, BX, ES, DI)
 
971
Bit16u *AX;Bit16u BX; Bit16u ES;Bit16u DI;
 
972
{
 
973
        Bit16u            ss = get_SS();
 
974
        Bit16u            result;
 
975
        ModeInfoListItem  *cur_info;
 
976
        Boolean           using_lfb;
 
977
        Bit8u             no_clear;
 
978
        Bit8u             lfb_flag;
 
979
 
 
980
        using_lfb=((BX & VBE_MODE_LINEAR_FRAME_BUFFER) == VBE_MODE_LINEAR_FRAME_BUFFER);
 
981
        lfb_flag=using_lfb?VBE_DISPI_LFB_ENABLED:0;
 
982
        no_clear=((BX & VBE_MODE_PRESERVE_DISPLAY_MEMORY) == VBE_MODE_PRESERVE_DISPLAY_MEMORY)?VBE_DISPI_NOCLEARMEM:0;
 
983
 
 
984
        BX = (BX & 0x1ff);
 
985
 
 
986
        //result=read_word(ss,AX);
 
987
 
 
988
        // check for non vesa mode
 
989
        if (BX<VBE_MODE_VESA_DEFINED)
 
990
        {
 
991
                Bit8u   mode;
 
992
 
 
993
                dispi_set_enable(VBE_DISPI_DISABLED);
 
994
                // call the vgabios in order to set the video mode
 
995
                // this allows for going back to textmode with a VBE call (some applications expect that to work)
 
996
 
 
997
                mode=(BX & 0xff);
 
998
                biosfn_set_video_mode(mode);
 
999
                result = 0x4f;
 
1000
        }
 
1001
 
 
1002
        cur_info = mode_info_find_mode(BX, using_lfb, &cur_info);
 
1003
 
 
1004
        if (cur_info != 0)
 
1005
        {
 
1006
#ifdef DEBUG
 
1007
                printf("VBE found mode %x, setting:\n", BX);
 
1008
                printf("\txres%x yres%x bpp%x\n",
 
1009
                        cur_info->info.XResolution,
 
1010
                        cur_info->info.YResolution,
 
1011
                        cur_info->info.BitsPerPixel);
 
1012
#endif
 
1013
 
 
1014
                // first disable current mode (when switching between vesa modi)
 
1015
                dispi_set_enable(VBE_DISPI_DISABLED);
 
1016
 
 
1017
                if (cur_info->info.BitsPerPixel == 4)
 
1018
                {
 
1019
                  biosfn_set_video_mode(0x6a);
 
1020
                }
 
1021
 
 
1022
                dispi_set_bpp(cur_info->info.BitsPerPixel);
 
1023
                dispi_set_xres(cur_info->info.XResolution);
 
1024
                dispi_set_yres(cur_info->info.YResolution);
 
1025
                dispi_set_bank(0);
 
1026
                dispi_set_enable(VBE_DISPI_ENABLED | no_clear | lfb_flag);
 
1027
                vga_compat_setup();
 
1028
 
 
1029
                write_word(BIOSMEM_SEG,BIOSMEM_VBE_MODE,BX);
 
1030
                write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60 | no_clear));
 
1031
 
 
1032
                result = 0x4f;
 
1033
        }
 
1034
        else
 
1035
        {
 
1036
#ifdef DEBUG
 
1037
                printf("VBE *NOT* found mode %x\n" , BX);
 
1038
#endif
 
1039
                result = 0x100;
 
1040
 
 
1041
                // FIXME: redirect non VBE modi to normal VGA bios operation
 
1042
                //        (switch back to VGA mode
 
1043
                if (BX == 3)
 
1044
                        result = 0x4f;
 
1045
        }
 
1046
 
 
1047
        write_word(ss, AX, result);
 
1048
}
 
1049
 
 
1050
/** Function 03h - Return Current VBE Mode
 
1051
 * 
 
1052
 * Input:
 
1053
 *              AX      = 4F03h
 
1054
 * Output:
 
1055
 *              AX      = VBE Return Status
 
1056
 *              BX      = Current VBE Mode
 
1057
 * 
 
1058
 */
 
1059
ASM_START
 
1060
vbe_biosfn_return_current_mode:
 
1061
  push ds
 
1062
  mov  ax, # BIOSMEM_SEG
 
1063
  mov  ds, ax
 
1064
  call dispi_get_enable
 
1065
  and  ax, # VBE_DISPI_ENABLED
 
1066
  jz   no_vbe_mode
 
1067
  mov  bx, # BIOSMEM_VBE_MODE
 
1068
  mov  ax, [bx]
 
1069
  mov  bx, ax
 
1070
  jnz  vbe_03_ok
 
1071
no_vbe_mode:
 
1072
  mov  bx, # BIOSMEM_CURRENT_MODE
 
1073
  mov  al, [bx]
 
1074
  mov  bl, al
 
1075
  xor  bh, bh
 
1076
vbe_03_ok:
 
1077
  mov  ax, #0x004f
 
1078
  pop  ds
 
1079
  ret
 
1080
ASM_END
 
1081
 
 
1082
 
 
1083
Bit16u vbe_biosfn_read_video_state_size()
 
1084
{
 
1085
    return 9 * 2;
 
1086
}
 
1087
 
 
1088
void vbe_biosfn_save_video_state(ES, BX)
 
1089
     Bit16u ES; Bit16u BX;
 
1090
{
 
1091
    Bit16u enable, i;
 
1092
 
 
1093
    outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_ENABLE);
 
1094
    enable = inw(VBE_DISPI_IOPORT_DATA);
 
1095
    write_word(ES, BX, enable);
 
1096
    BX += 2;
 
1097
    if (!(enable & VBE_DISPI_ENABLED)) 
 
1098
        return;
 
1099
    for(i = VBE_DISPI_INDEX_XRES; i <= VBE_DISPI_INDEX_Y_OFFSET; i++) {
 
1100
        if (i != VBE_DISPI_INDEX_ENABLE) {
 
1101
            outw(VBE_DISPI_IOPORT_INDEX, i);
 
1102
            write_word(ES, BX, inw(VBE_DISPI_IOPORT_DATA));
 
1103
            BX += 2;
 
1104
        }
 
1105
    }
 
1106
}
 
1107
 
 
1108
 
 
1109
void vbe_biosfn_restore_video_state(ES, BX)
 
1110
     Bit16u ES; Bit16u BX;
 
1111
{
 
1112
    Bit16u enable, i;
 
1113
 
 
1114
    enable = read_word(ES, BX);
 
1115
    BX += 2;
 
1116
 
 
1117
    if (!(enable & VBE_DISPI_ENABLED)) {
 
1118
        outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_ENABLE);
 
1119
        outw(VBE_DISPI_IOPORT_DATA, enable);
 
1120
    } else {
 
1121
        outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_XRES);
 
1122
        outw(VBE_DISPI_IOPORT_DATA, read_word(ES, BX));
 
1123
        BX += 2;
 
1124
        outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_YRES);
 
1125
        outw(VBE_DISPI_IOPORT_DATA, read_word(ES, BX));
 
1126
        BX += 2;
 
1127
        outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_BPP);
 
1128
        outw(VBE_DISPI_IOPORT_DATA, read_word(ES, BX));
 
1129
        BX += 2;
 
1130
        outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_ENABLE);
 
1131
        outw(VBE_DISPI_IOPORT_DATA, enable);
 
1132
 
 
1133
        for(i = VBE_DISPI_INDEX_BANK; i <= VBE_DISPI_INDEX_Y_OFFSET; i++) {
 
1134
            outw(VBE_DISPI_IOPORT_INDEX, i);
 
1135
            outw(VBE_DISPI_IOPORT_DATA, read_word(ES, BX));
 
1136
            BX += 2;
 
1137
        }
 
1138
    }
 
1139
}
 
1140
 
 
1141
/** Function 04h - Save/Restore State
 
1142
 * 
 
1143
 * Input:
 
1144
 *              AX      = 4F04h
 
1145
 *              DL      = 00h Return Save/Restore State buffer size
 
1146
 *                        01h Save State
 
1147
 *                        02h Restore State
 
1148
 *              CX      = Requested states
 
1149
 *              ES:BX   = Pointer to buffer (if DL <> 00h)
 
1150
 * Output:
 
1151
 *              AX      = VBE Return Status
 
1152
 *              BX      = Number of 64-byte blocks to hold the state buffer (if DL=00h)
 
1153
 * 
 
1154
 */
 
1155
void vbe_biosfn_save_restore_state(AX, CX, DX, ES, BX)
 
1156
Bit16u *AX; Bit16u CX; Bit16u DX; Bit16u ES; Bit16u *BX;
 
1157
{
 
1158
    Bit16u ss=get_SS();
 
1159
    Bit16u result, val;
 
1160
 
 
1161
    result = 0x4f;
 
1162
    switch(GET_DL()) {
 
1163
    case 0x00:
 
1164
        val = biosfn_read_video_state_size2(CX);
 
1165
#ifdef DEBUG
 
1166
        printf("VGA state size=%x\n", val);
 
1167
#endif
 
1168
        if (CX & 8)
 
1169
            val += vbe_biosfn_read_video_state_size();
 
1170
        write_word(ss, BX, val);
 
1171
        break;
 
1172
    case 0x01:
 
1173
        val = read_word(ss, BX);
 
1174
        val = biosfn_save_video_state(CX, ES, val);
 
1175
#ifdef DEBUG
 
1176
        printf("VGA save_state offset=%x\n", val);
 
1177
#endif
 
1178
        if (CX & 8)
 
1179
            vbe_biosfn_save_video_state(ES, val);
 
1180
        break;
 
1181
    case 0x02:
 
1182
        val = read_word(ss, BX);
 
1183
        val = biosfn_restore_video_state(CX, ES, val);
 
1184
#ifdef DEBUG
 
1185
        printf("VGA restore_state offset=%x\n", val);
 
1186
#endif
 
1187
        if (CX & 8)
 
1188
            vbe_biosfn_restore_video_state(ES, val);
 
1189
        break;
 
1190
    default:
 
1191
        // function failed
 
1192
        result = 0x100;
 
1193
        break;
 
1194
    }
 
1195
    write_word(ss, AX, result);
 
1196
}
 
1197
 
 
1198
/** Function 05h - Display Window Control
 
1199
 * 
 
1200
 * Input:
 
1201
 *              AX      = 4F05h
 
1202
 *     (16-bit) BH      = 00h Set memory window
 
1203
 *                      = 01h Get memory window
 
1204
 *              BL      = Window number
 
1205
 *                      = 00h Window A
 
1206
 *                      = 01h Window B
 
1207
 *              DX      = Window number in video memory in window
 
1208
 *                        granularity units (Set Memory Window only)
 
1209
 * Note:
 
1210
 *              If this function is called while in a linear frame buffer mode,
 
1211
 *              this function must fail with completion code AH=03h
 
1212
 * 
 
1213
 * Output:
 
1214
 *              AX      = VBE Return Status
 
1215
 *              DX      = Window number in window granularity units
 
1216
 *                        (Get Memory Window only)
 
1217
 */
 
1218
ASM_START
 
1219
vbe_biosfn_display_window_control:
 
1220
  cmp  bl, #0x00
 
1221
  jne  vbe_05_failed
 
1222
  cmp  bh, #0x01
 
1223
  je   get_display_window
 
1224
  jb   set_display_window
 
1225
  mov  ax, #0x0100
 
1226
  ret
 
1227
set_display_window:
 
1228
  mov  ax, dx
 
1229
  call _dispi_set_bank
 
1230
  call dispi_get_bank
 
1231
  cmp  ax, dx
 
1232
  jne  vbe_05_failed
 
1233
  mov  ax, #0x004f
 
1234
  ret
 
1235
get_display_window:
 
1236
  call dispi_get_bank
 
1237
  mov  dx, ax
 
1238
  mov  ax, #0x004f
 
1239
  ret
 
1240
vbe_05_failed:
 
1241
  mov  ax, #0x014f
 
1242
  ret
 
1243
ASM_END
 
1244
 
 
1245
 
 
1246
/** Function 06h - Set/Get Logical Scan Line Length
 
1247
 *
 
1248
 * Input:
 
1249
 *              AX      = 4F06h
 
1250
 *              BL      = 00h Set Scan Line Length in Pixels
 
1251
 *                      = 01h Get Scan Line Length
 
1252
 *                      = 02h Set Scan Line Length in Bytes
 
1253
 *                      = 03h Get Maximum Scan Line Length
 
1254
 *              CX      = If BL=00h Desired Width in Pixels
 
1255
 *                        If BL=02h Desired Width in Bytes
 
1256
 *                        (Ignored for Get Functions)
 
1257
 * 
 
1258
 * Output: 
 
1259
 *              AX      = VBE Return Status
 
1260
 *              BX      = Bytes Per Scan Line
 
1261
 *              CX      = Actual Pixels Per Scan Line
 
1262
 *                        (truncated to nearest complete pixel)
 
1263
 *              DX      = Maximum Number of Scan Lines 
 
1264
 */
 
1265
ASM_START
 
1266
vbe_biosfn_set_get_logical_scan_line_length:
 
1267
  mov  ax, cx
 
1268
  cmp  bl, #0x01
 
1269
  je   get_logical_scan_line_length
 
1270
  cmp  bl, #0x02
 
1271
  je   set_logical_scan_line_bytes
 
1272
  jb   set_logical_scan_line_pixels
 
1273
  mov  ax, #0x0100
 
1274
  ret
 
1275
set_logical_scan_line_bytes:
 
1276
  push ax
 
1277
  call dispi_get_bpp
 
1278
  xor  bh, bh
 
1279
  mov  bl, ah
 
1280
  or   bl, bl
 
1281
  jnz  no_4bpp_1
 
1282
  shl  ax, #3
 
1283
  mov  bl, #1
 
1284
no_4bpp_1:
 
1285
  xor  dx, dx
 
1286
  pop  ax
 
1287
  div  bx
 
1288
set_logical_scan_line_pixels:
 
1289
  call dispi_set_virt_width
 
1290
get_logical_scan_line_length:
 
1291
  call dispi_get_bpp
 
1292
  xor  bh, bh
 
1293
  mov  bl, ah
 
1294
  call dispi_get_virt_width
 
1295
  mov  cx, ax
 
1296
  or   bl, bl
 
1297
  jnz  no_4bpp_2
 
1298
  shr  ax, #3
 
1299
  mov  bl, #1
 
1300
no_4bpp_2:
 
1301
  mul  bx
 
1302
  mov  bx, ax
 
1303
  call dispi_get_virt_height
 
1304
  mov  dx, ax
 
1305
  mov  ax, #0x004f
 
1306
  ret
 
1307
ASM_END
 
1308
 
 
1309
 
 
1310
/** Function 07h - Set/Get Display Start
 
1311
 * 
 
1312
 * Input(16-bit):
 
1313
 *              AX      = 4F07h
 
1314
 *              BH      = 00h Reserved and must be 00h
 
1315
 *              BL      = 00h Set Display Start
 
1316
 *                      = 01h Get Display Start
 
1317
 *                      = 02h Schedule Display Start (Alternate)
 
1318
 *                      = 03h Schedule Stereoscopic Display Start
 
1319
 *                      = 04h Get Scheduled Display Start Status
 
1320
 *                      = 05h Enable Stereoscopic Mode
 
1321
 *                      = 06h Disable Stereoscopic Mode
 
1322
 *                      = 80h Set Display Start during Vertical Retrace
 
1323
 *                      = 82h Set Display Start during Vertical Retrace (Alternate)
 
1324
 *                      = 83h Set Stereoscopic Display Start during Vertical Retrace
 
1325
 *              ECX     = If BL=02h/82h Display Start Address in bytes
 
1326
 *                        If BL=03h/83h Left Image Start Address in bytes
 
1327
 *              EDX     = If BL=03h/83h Right Image Start Address in bytes
 
1328
 *              CX      = If BL=00h/80h First Displayed Pixel In Scan Line
 
1329
 *              DX      = If BL=00h/80h First Displayed Scan Line
 
1330
 *
 
1331
 * Output:
 
1332
 *              AX      = VBE Return Status
 
1333
 *              BH      = If BL=01h Reserved and will be 0
 
1334
 *              CX      = If BL=01h First Displayed Pixel In Scan Line
 
1335
 *                        If BL=04h 0 if flip has not occurred, not 0 if it has
 
1336
 *              DX      = If BL=01h First Displayed Scan Line
 
1337
 *
 
1338
 * Input(32-bit): 
 
1339
 *              BH      = 00h Reserved and must be 00h
 
1340
 *              BL      = 00h Set Display Start
 
1341
 *                      = 80h Set Display Start during Vertical Retrace
 
1342
 *              CX      = Bits 0-15 of display start address
 
1343
 *              DX      = Bits 16-31 of display start address
 
1344
 *              ES      = Selector for memory mapped registers 
 
1345
 */
 
1346
ASM_START
 
1347
vbe_biosfn_set_get_display_start:
 
1348
  cmp  bl, #0x80
 
1349
  je   set_display_start
 
1350
  cmp  bl, #0x01
 
1351
  je   get_display_start
 
1352
  jb   set_display_start
 
1353
  mov  ax, #0x0100
 
1354
  ret
 
1355
set_display_start:
 
1356
  mov  ax, cx
 
1357
  call dispi_set_x_offset
 
1358
  mov  ax, dx
 
1359
  call dispi_set_y_offset
 
1360
  mov  ax, #0x004f
 
1361
  ret
 
1362
get_display_start:
 
1363
  call dispi_get_x_offset
 
1364
  mov  cx, ax
 
1365
  call dispi_get_y_offset
 
1366
  mov  dx, ax
 
1367
  xor  bh, bh
 
1368
  mov  ax, #0x004f
 
1369
  ret
 
1370
ASM_END
 
1371
  
 
1372
 
 
1373
/** Function 08h - Set/Get Dac Palette Format
 
1374
 * 
 
1375
 * Input:
 
1376
 *              AX      = 4F08h
 
1377
 *              BL      = 00h set DAC palette width
 
1378
 *                      = 01h get DAC palette width
 
1379
 *              BH      = If BL=00h: desired number of bits per primary color
 
1380
 * Output:
 
1381
 *              AX      = VBE Return Status
 
1382
 *              BH      = current number of bits per primary color (06h = standard VGA)
 
1383
 */
 
1384
ASM_START
 
1385
vbe_biosfn_set_get_dac_palette_format:
 
1386
  cmp  bl, #0x01
 
1387
  je   get_dac_palette_format
 
1388
  jb   set_dac_palette_format
 
1389
  mov  ax, #0x0100
 
1390
  ret
 
1391
set_dac_palette_format:
 
1392
  call dispi_get_enable
 
1393
  cmp  bh, #0x06
 
1394
  je   set_normal_dac
 
1395
  cmp  bh, #0x08
 
1396
  jne  vbe_08_unsupported
 
1397
  or   ax, # VBE_DISPI_8BIT_DAC
 
1398
  jnz  set_dac_mode
 
1399
set_normal_dac:
 
1400
  and  ax, #~ VBE_DISPI_8BIT_DAC
 
1401
set_dac_mode:
 
1402
  call _dispi_set_enable
 
1403
get_dac_palette_format:
 
1404
  mov  bh, #0x06
 
1405
  call dispi_get_enable
 
1406
  and  ax, # VBE_DISPI_8BIT_DAC
 
1407
  jz   vbe_08_ok
 
1408
  mov  bh, #0x08
 
1409
vbe_08_ok:
 
1410
  mov  ax, #0x004f
 
1411
  ret
 
1412
vbe_08_unsupported:
 
1413
  mov  ax, #0x014f
 
1414
  ret
 
1415
ASM_END
 
1416
 
 
1417
 
 
1418
/** Function 09h - Set/Get Palette Data
 
1419
 * 
 
1420
 * Input:
 
1421
 *              AX      = 4F09h
 
1422
 * Output:
 
1423
 *              AX      = VBE Return Status
 
1424
 *
 
1425
 * FIXME: incomplete API description, Input & Output
 
1426
 */
 
1427
void vbe_biosfn_set_get_palette_data(AX)
 
1428
{
 
1429
}
 
1430
 
 
1431
/** Function 0Ah - Return VBE Protected Mode Interface
 
1432
 * Input:    AX   = 4F0Ah   VBE 2.0 Protected Mode Interface
 
1433
 *           BL   = 00h          Return protected mode table
 
1434
 *
 
1435
 *
 
1436
 * Output:   AX   =         Status
 
1437
 *           ES   =         Real Mode Segment of Table
 
1438
 *           DI   =         Offset of Table
 
1439
 *           CX   =         Length of Table including protected mode code
 
1440
 *                          (for copying purposes)
 
1441
 */
 
1442
ASM_START
 
1443
vbe_biosfn_return_protected_mode_interface:
 
1444
  test bl, bl
 
1445
  jnz _fail
 
1446
  mov di, #0xc000
 
1447
  mov es, di
 
1448
  mov di, # vesa_pm_start
 
1449
  mov cx, # vesa_pm_end
 
1450
  sub cx, di
 
1451
  mov ax, #0x004f
 
1452
  ret
 
1453
_fail:
 
1454
  mov ax, #0x014f
 
1455
  ret
 
1456
ASM_END