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