- applied new patch for the cirrus extension from suzu
[vgabios.git] / clext.c
blob052fda5b0896b713ae4b82347b48b388363777c4
1 //
2 // QEMU Cirrus CLGD 54xx VGABIOS Extension.
3 //
4 // Copyright (c) 2004 Makoto Suzuki (suzu)
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 //
21 //#define CIRRUS_VESA3_PMINFO
22 #ifdef VBE
23 #undef CIRRUS_VESA3_PMINFO
24 #endif
26 #define PM_BIOSMEM_CURRENT_MODE 0x449
27 #define PM_BIOSMEM_CRTC_ADDRESS 0x463
28 #define PM_BIOSMEM_VBE_MODE 0x4BA
30 typedef struct
32 /* + 0 */
33 unsigned short mode;
34 unsigned short width;
35 unsigned short height;
36 unsigned short depth;
37 /* + 8 */
38 unsigned short hidden_dac; /* 0x3c6 */
39 unsigned short *seq; /* 0x3c4 */
40 unsigned short *graph; /* 0x3ce */
41 unsigned short *crtc; /* 0x3d4 */
42 /* +16 */
43 unsigned char bitsperpixel;
44 unsigned char vesacolortype;
45 unsigned char vesaredmask;
46 unsigned char vesaredpos;
47 unsigned char vesagreenmask;
48 unsigned char vesagreenpos;
49 unsigned char vesabluemask;
50 unsigned char vesabluepos;
51 /* +24 */
52 unsigned char vesareservedmask;
53 unsigned char vesareservedpos;
54 } cirrus_mode_t;
55 #define CIRRUS_MODE_SIZE 26
58 /* For VESA BIOS 3.0 */
59 #define CIRRUS_PM16INFO_SIZE 20
61 /* VGA */
62 unsigned short cseq_vga[] = {0x0007,0xffff};
63 unsigned short cgraph_vga[] = {0x0009,0x000a,0x200b,0xffff};
64 unsigned short ccrtc_vga[] = {0x001a,0x001b,0x001d,0xffff};
66 /* extensions */
67 unsigned short cgraph_svgacolor[] = {
68 0x0000,0x0001,0x0002,0x0003,0x0004,0x4005,0x0506,0x0f07,0xff08,
69 0x0009,0x000a,0x200b,
70 0xffff
72 /* 640x480x8 */
73 unsigned short cseq_640x480x8[] = {
74 0x0100,0x2101,0x0f02,0x0003,0x0e04,0x1107,
75 0x580b,0x580c,0x580d,0x580e,
76 0x0412,0x0013,0x2017,
77 0x331b,0x331c,0x331d,0x331e,
78 0xffff
80 unsigned short ccrtc_640x480x8[] = {
81 0x2c11,
82 0x5f00,0x4f01,0x4f02,0x8003,0x5204,0x1e05,0x0b06,0x3e07,
83 0x4009,0x000c,0x000d,
84 0xea10,0xdf12,0x5013,0x4014,0xdf15,0x0b16,0xc317,0xff18,
85 0x001a,0x221b,0x001d,
86 0xffff
88 /* 640x480x16 */
89 unsigned short cseq_640x480x16[] = {
90 0x0100,0x2101,0x0f02,0x0003,0x0e04,0x1707,
91 0x580b,0x580c,0x580d,0x580e,
92 0x0412,0x0013,0x2017,
93 0x331b,0x331c,0x331d,0x331e,
94 0xffff
96 unsigned short ccrtc_640x480x16[] = {
97 0x2c11,
98 0x5f00,0x4f01,0x4f02,0x8003,0x5204,0x1e05,0x0b06,0x3e07,
99 0x4009,0x000c,0x000d,
100 0xea10,0xdf12,0xa013,0x4014,0xdf15,0x0b16,0xc317,0xff18,
101 0x001a,0x221b,0x001d,
102 0xffff
104 /* 640x480x24 */
105 unsigned short cseq_640x480x24[] = {
106 0x0100,0x2101,0x0f02,0x0003,0x0e04,0x1507,
107 0x580b,0x580c,0x580d,0x580e,
108 0x0412,0x0013,0x2017,
109 0x331b,0x331c,0x331d,0x331e,
110 0xffff
112 unsigned short ccrtc_640x480x24[] = {
113 0x2c11,
114 0x5f00,0x4f01,0x4f02,0x8003,0x5204,0x1e05,0x0b06,0x3e07,
115 0x4009,0x000c,0x000d,
116 0xea10,0xdf12,0x0013,0x4014,0xdf15,0x0b16,0xc317,0xff18,
117 0x001a,0x321b,0x001d,
118 0xffff
120 /* 800x600x8 */
121 unsigned short cseq_800x600x8[] = {
122 0x0100,0x2101,0x0f02,0x0003,0x0e04,0x1107,
123 0x230b,0x230c,0x230d,0x230e,
124 0x0412,0x0013,0x2017,
125 0x141b,0x141c,0x141d,0x141e,
126 0xffff
128 unsigned short ccrtc_800x600x8[] = {
129 0x2311,0x7d00,0x6301,0x6302,0x8003,0x6b04,0x1a05,0x9806,0xf007,
130 0x6009,0x000c,0x000d,
131 0x7d10,0x5712,0x6413,0x4014,0x5715,0x9816,0xc317,0xff18,
132 0x001a,0x221b,0x001d,
133 0xffff
135 /* 800x600x16 */
136 unsigned short cseq_800x600x16[] = {
137 0x0100,0x2101,0x0f02,0x0003,0x0e04,0x1707,
138 0x230b,0x230c,0x230d,0x230e,
139 0x0412,0x0013,0x2017,
140 0x141b,0x141c,0x141d,0x141e,
141 0xffff
143 unsigned short ccrtc_800x600x16[] = {
144 0x2311,0x7d00,0x6301,0x6302,0x8003,0x6b04,0x1a05,0x9806,0xf007,
145 0x6009,0x000c,0x000d,
146 0x7d10,0x5712,0xc813,0x4014,0x5715,0x9816,0xc317,0xff18,
147 0x001a,0x221b,0x001d,
148 0xffff
150 /* 800x600x24 */
151 unsigned short cseq_800x600x24[] = {
152 0x0100,0x2101,0x0f02,0x0003,0x0e04,0x1507,
153 0x230b,0x230c,0x230d,0x230e,
154 0x0412,0x0013,0x2017,
155 0x141b,0x141c,0x141d,0x141e,
156 0xffff
158 unsigned short ccrtc_800x600x24[] = {
159 0x2311,0x7d00,0x6301,0x6302,0x8003,0x6b04,0x1a05,0x9806,0xf007,
160 0x6009,0x000c,0x000d,
161 0x7d10,0x5712,0x2c13,0x4014,0x5715,0x9816,0xc317,0xff18,
162 0x001a,0x321b,0x001d,
163 0xffff
165 /* 1024x768x8 */
166 unsigned short cseq_1024x768x8[] = {
167 0x0100,0x2101,0x0f02,0x0003,0x0e04,0x1107,
168 0x760b,0x760c,0x760d,0x760e,
169 0x0412,0x0013,0x2017,
170 0x341b,0x341c,0x341d,0x341e,
171 0xffff
173 unsigned short ccrtc_1024x768x8[] = {
174 0x2911,0xa300,0x7f01,0x7f02,0x8603,0x8304,0x9405,0x2406,0xf507,
175 0x6009,0x000c,0x000d,
176 0x0310,0xff12,0x8013,0x4014,0xff15,0x2416,0xc317,0xff18,
177 0x001a,0x221b,0x001d,
178 0xffff
180 /* 1024x768x16 */
181 unsigned short cseq_1024x768x16[] = {
182 0x0100,0x2101,0x0f02,0x0003,0x0e04,0x1707,
183 0x760b,0x760c,0x760d,0x760e,
184 0x0412,0x0013,0x2017,
185 0x341b,0x341c,0x341d,0x341e,
186 0xffff
188 unsigned short ccrtc_1024x768x16[] = {
189 0x2911,0xa300,0x7f01,0x7f02,0x8603,0x8304,0x9405,0x2406,0xf507,
190 0x6009,0x000c,0x000d,
191 0x0310,0xff12,0x0013,0x4014,0xff15,0x2416,0xc317,0xff18,
192 0x001a,0x321b,0x001d,
193 0xffff
195 /* 1024x768x24 */
196 unsigned short cseq_1024x768x24[] = {
197 0x0100,0x2101,0x0f02,0x0003,0x0e04,0x1507,
198 0x760b,0x760c,0x760d,0x760e,
199 0x0412,0x0013,0x2017,
200 0x341b,0x341c,0x341d,0x341e,
201 0xffff
203 unsigned short ccrtc_1024x768x24[] = {
204 0x2911,0xa300,0x7f01,0x7f02,0x8603,0x8304,0x9405,0x2406,0xf507,
205 0x6009,0x000c,0x000d,
206 0x0310,0xff12,0x8013,0x4014,0xff15,0x2416,0xc317,0xff18,
207 0x001a,0x321b,0x001d,
208 0xffff
212 cirrus_mode_t cirrus_modes[] =
214 {0x5f,640,480,8,0x00,
215 cseq_640x480x8,cgraph_svgacolor,ccrtc_640x480x8,8,
216 4,0,0,0,0,0,0,0,0},
217 {0x64,640,480,16,0xe1,
218 cseq_640x480x16,cgraph_svgacolor,ccrtc_640x480x16,16,
219 6,5,11,6,5,5,0,0,0},
220 {0x66,640,480,15,0xf0,
221 cseq_640x480x16,cgraph_svgacolor,ccrtc_640x480x16,16,
222 6,5,10,5,5,5,0,1,15},
223 {0x71,640,480,24,0xe5,
224 cseq_640x480x24,cgraph_svgacolor,ccrtc_640x480x24,24,
225 6,8,16,8,8,8,0,0,0},
227 {0x5c,800,600,8,0x00,
228 cseq_800x600x8,cgraph_svgacolor,ccrtc_800x600x8,8,
229 4,0,0,0,0,0,0,0,0},
230 {0x65,800,600,16,0xe1,
231 cseq_800x600x16,cgraph_svgacolor,ccrtc_800x600x16,16,
232 6,5,11,6,5,5,0,0,0},
233 {0x67,800,600,15,0xf0,
234 cseq_800x600x16,cgraph_svgacolor,ccrtc_800x600x16,16,
235 6,5,10,5,5,5,0,1,15},
237 {0x60,1024,768,8,0x00,
238 cseq_1024x768x8,cgraph_svgacolor,ccrtc_1024x768x8,8,
239 4,0,0,0,0,0,0,0,0},
240 {0x74,1024,768,16,0xe1,
241 cseq_1024x768x16,cgraph_svgacolor,ccrtc_1024x768x16,16,
242 6,5,11,6,5,5,0,0,0},
243 {0x68,1024,768,15,0xf0,
244 cseq_1024x768x16,cgraph_svgacolor,ccrtc_1024x768x16,16,
245 6,5,10,5,5,5,0,1,15},
247 {0xe0,800,600,24,0xe5,
248 cseq_800x600x24,cgraph_svgacolor,ccrtc_800x600x24,24,
249 6,8,16,8,8,8,0,0,0},
250 {0xe1,1024,768,24,0xe5,
251 cseq_1024x768x24,cgraph_svgacolor,ccrtc_1024x768x24,24,
252 6,8,16,8,8,8,0,0,0},
254 {0xfe,0,0,0,0,cseq_vga,cgraph_vga,ccrtc_vga,0,
255 0xff,0,0,0,0,0,0,0,0},
256 {0xff,0,0,0,0,0,0,0,0,
257 0xff,0,0,0,0,0,0,0,0},
260 unsigned char cirrus_id_table[] = {
261 // 5430
262 0xA0, 0x32,
263 // 5446
264 0xB8, 0x39,
266 0xff, 0xff
270 unsigned short cirrus_vesa_modelist[] = {
271 // 640x480x8
272 0x101, 0x5f,
273 // 640x480x15
274 0x110, 0x66,
275 // 640x480x16
276 0x111, 0x64,
277 // 640x480x24
278 0x112, 0x71,
279 // 800x600x8
280 0x103, 0x5c,
281 // 800x600x15
282 0x113, 0x67,
283 // 800x600x16
284 0x114, 0x65,
285 // 800x600x24
286 0x115, 0xe0,
287 // 1024x768x8
288 0x105, 0x60,
289 // 1024x768x15
290 0x116, 0x68,
291 // 1024x768x16
292 0x117, 0x74,
293 // 1024x768x24
294 //0x118, 0xe1,
295 // invalid
296 0xffff,0xffff
300 ASM_START
302 cirrus_installed:
303 .ascii "cirrus-compatible VGA is detected"
304 .byte 0x0d,0x0a
305 .byte 0x0d,0x0a,0x00
307 cirrus_not_installed:
308 .ascii "cirrus-compatible VGA is not detected"
309 .byte 0x0d,0x0a
310 .byte 0x0d,0x0a,0x00
312 cirrus_vesa_vendorname:
313 cirrus_vesa_productname:
314 cirrus_vesa_oemname:
315 .ascii "VGABIOS Cirrus extension"
316 .byte 0
317 cirrus_vesa_productrevision:
318 .ascii "1.0"
319 .byte 0
321 cirrus_init:
322 call cirrus_check
323 jnz no_cirrus
324 SET_INT_VECTOR(0x10, #0xC000, #cirrus_int10_handler)
325 mov al, #0x0f
326 mov dx, #0x3C4
327 out dx, al
328 inc dx
329 in al, dx
330 and al, #0x18
331 mov ah, al
332 mov al, #0x0a
333 dec dx
334 out dx, ax
335 no_cirrus:
338 cirrus_display_info:
339 push ds
340 push si
341 push cs
342 pop ds
343 call cirrus_check
344 mov si, #cirrus_not_installed
345 jnz cirrus_msgnotinstalled
346 mov si, #cirrus_installed
348 cirrus_msgnotinstalled:
349 call _display_string
350 pop si
351 pop ds
354 cirrus_check:
355 push ax
356 push dx
357 mov ax, #0x9206
358 mov dx, #0x3C4
359 out dx, ax
360 inc dx
361 in al, dx
362 cmp al, #0x12
363 pop dx
364 pop ax
368 cirrus_int10_handler:
369 pushf
370 push bp
371 cmp ah, #0x00 ;; set video mode
372 jz cirrus_set_video_mode
373 cmp ah, #0x12 ;; cirrus extension
374 jz cirrus_extbios
375 cmp ah, #0x4F ;; VESA extension
376 jz cirrus_vesa
378 cirrus_unhandled:
379 pop bp
380 popf
381 jmp vgabios_int10_handler
383 cirrus_return:
384 #ifdef CIRRUS_DEBUG
385 call cirrus_debug_dump
386 #endif
387 pop bp
388 popf
389 iret
391 cirrus_set_video_mode:
392 #ifdef CIRRUS_DEBUG
393 call cirrus_debug_dump
394 #endif
395 push si
396 push ax
397 push bx
398 push ds
399 #ifdef CIRRUS_VESA3_PMINFO
400 db 0x2e ;; cs:
401 mov si, [cirrus_vesa_sel0000_data]
402 #else
403 xor si, si
404 #endif
405 mov ds, si
406 xor bx, bx
407 mov [PM_BIOSMEM_VBE_MODE], bx
408 pop ds
409 pop bx
410 call cirrus_get_modeentry
411 jnc cirrus_set_video_mode_extended
412 mov al, #0xfe
413 call cirrus_get_modeentry_nomask
414 call cirrus_switch_mode
415 pop ax
416 pop si
417 jmp cirrus_unhandled
419 cirrus_extbios:
420 #ifdef CIRRUS_DEBUG
421 call cirrus_debug_dump
422 #endif
423 cmp bl, #0x80
424 jb cirrus_unhandled
425 cmp bl, #0xAF
426 ja cirrus_unhandled
427 push bx
428 and bx, #0x7F
429 shl bx, 1
430 db 0x2e ;; cs:
431 mov bp, cirrus_extbios_handlers[bx]
432 pop bx
433 push #cirrus_return
434 push bp
437 cirrus_vesa:
438 #ifdef CIRRUS_DEBUG
439 call cirrus_debug_dump
440 #endif
441 cmp al, #0x0F
442 ja cirrus_vesa_not_handled
443 push bx
444 xor bx, bx
445 mov bl, al
446 shl bx, 1
447 db 0x2e ;; cs:
448 mov bp, cirrus_vesa_handlers[bx]
449 pop bx
450 push #cirrus_return
451 push bp
454 cirrus_vesa_not_handled:
455 mov ax, #0x014F ;; not implemented
456 jmp cirrus_return
458 #ifdef CIRRUS_DEBUG
459 cirrus_debug_dump:
460 push es
461 push ds
462 pusha
463 push cs
464 pop ds
465 call _cirrus_debugmsg
466 popa
467 pop ds
468 pop es
470 #endif
472 cirrus_set_video_mode_extended:
473 call cirrus_switch_mode
474 pop ax ;; mode
475 and al, #0x7f
477 push ds
478 #ifdef CIRRUS_VESA3_PMINFO
479 db 0x2e ;; cs:
480 mov si, [cirrus_vesa_sel0000_data]
481 #else
482 xor si, si
483 #endif
484 mov ds, si
485 mov [PM_BIOSMEM_CURRENT_MODE], al
486 pop ds
488 mov al, #0x20
490 pop si
491 jmp cirrus_return
493 cirrus_vesa_pmbios_init:
494 retf
495 cirrus_vesa_pmbios_entry:
496 pushf
497 push bp
498 cmp ah, #0x4F
499 jnz cirrus_vesa_pmbios_unimplemented
500 cmp al, #0x0F
501 ja cirrus_vesa_pmbios_unimplemented
502 push bx
503 xor bx, bx
504 mov bl, al
505 shl bx, 1
506 db 0x2e ;; cs:
507 mov bp, cirrus_vesa_handlers[bx]
508 pop bx
509 push #cirrus_vesa_pmbios_return
510 push bp
512 cirrus_vesa_pmbios_unimplemented:
513 mov ax, #0x014F
514 cirrus_vesa_pmbios_return:
515 pop bp
516 popf
517 retf
519 ; in si:mode table
520 cirrus_switch_mode:
521 push ds
522 push bx
523 push dx
524 push cs
525 pop ds
527 mov bx, [si+10] ;; seq
528 mov dx, #0x3c4
529 mov ax, #0x1206
530 out dx, ax ;; Unlock cirrus special
531 call cirrus_switch_mode_setregs
533 mov bx, [si+12] ;; graph
534 mov dx, #0x3ce
535 call cirrus_switch_mode_setregs
537 mov bx, [si+14] ;; crtc
538 call cirrus_get_crtc
539 call cirrus_switch_mode_setregs
541 mov dx, #0x3c6
542 mov al, #0x00
543 out dx, al
544 in al, dx
545 in al, dx
546 in al, dx
547 in al, dx
548 mov al, [si+8] ;; hidden dac
549 out dx, al
550 mov al, #0xff
551 out dx, al
553 mov al, #0x00
554 mov bl, [si+17] ;; memory model
555 or bl, bl
556 jz is_text_mode
557 mov al, #0x01
558 cmp bl, #0x03
559 jnz is_text_mode
560 or al, #0x40
561 is_text_mode:
562 mov bl, #0x10
563 call biosfn_get_single_palette_reg
564 and bh, #0xfe
565 or bh, al
566 call biosfn_set_single_palette_reg
568 pop dx
569 pop bx
570 pop ds
573 cirrus_enable_dualbank:
574 push ax
575 push dx
576 mov dx, #0x3ce
577 mov al, #0x0b
578 out dx, al
579 inc dx
580 in al, dx
581 or al, #0x21 ;; enable dual bank
582 out dx, al
583 pop dx
584 pop ax
587 cirrus_switch_mode_setregs:
588 csms_1:
589 mov ax, [bx]
590 cmp ax, #0xffff
591 jz csms_2
592 out dx, ax
593 add bx, #0x2
594 jmp csms_1
595 csms_2:
598 cirrus_extbios_80h:
599 push dx
600 call cirrus_get_crtc
601 mov al, #0x27
602 out dx, al
603 inc dx
604 in al, dx
605 mov bx, #_cirrus_id_table
606 c80h_1:
607 db 0x2e ;; cs:
608 mov ah, [bx]
609 cmp ah, al
610 jz c80h_2
611 cmp ah, #0xff
612 jz c80h_2
613 inc bx
614 inc bx
615 jmp c80h_1
616 c80h_2:
617 db 0x2e ;; cs:
618 mov al, 0x1[bx]
619 pop dx
620 mov ah, #0x00
621 xor bx, bx
624 cirrus_extbios_81h:
625 mov ax, #0x100 ;; XXX
627 cirrus_extbios_82h:
628 push dx
629 call cirrus_get_crtc
630 xor ax, ax
631 mov al, #0x27
632 out dx, al
633 inc dx
634 in al, dx
635 and al, #0x03
636 mov ah, #0xAF
637 pop dx
640 cirrus_extbios_85h:
641 push cx
642 push dx
643 mov dx, #0x3C4
644 mov al, #0x0f ;; get DRAM band width
645 out dx, al
646 inc dx
647 in al, dx
648 ;; al = 4 << bandwidth
649 mov cl, al
650 shr cl, #0x03
651 and cl, #0x03
652 mov al, #0x04
653 shl al, cl
654 pop dx
655 pop cx
658 cirrus_extbios_9Ah:
659 mov ax, #0x4060
660 mov cx, #0x1132
663 cirrus_extbios_A0h:
664 call cirrus_get_modeentry
665 mov ah, #0x01
666 sbb ah, #0x00
667 mov bx, cirrus_extbios_A0h_callback
668 mov si, #0xffff
669 mov di, bx
670 mov ds, bx
671 mov es, bx
674 cirrus_extbios_A0h_callback:
675 ;; fatal: not implemented yet
678 retf
680 cirrus_extbios_A1h:
681 mov bx, #0x0E00 ;; IBM 8512/8513, color
684 cirrus_extbios_A2h:
685 mov al, #0x07 ;; HSync 31.5 - 64.0 kHz
688 cirrus_extbios_AEh:
689 mov al, #0x01 ;; High Refresh 75Hz
692 cirrus_extbios_unimplemented:
695 cirrus_vesa_00h:
696 push ds
697 push si
698 mov bp, di
699 push es
700 pop ds
702 mov ax, [di]
703 cmp ax, #0x4256 ;; VB
704 jnz cv00_1
705 mov ax, [di+2]
706 cmp ax, #0x3245 ;; E2
707 jnz cv00_1
708 ;; VBE2
709 lea di, 0x14[bp]
710 mov ax, #0x0100 ;; soft ver.
711 stosw
712 mov ax, # cirrus_vesa_vendorname
713 stosw
714 mov ax, cs
715 stosw
716 mov ax, # cirrus_vesa_productname
717 stosw
718 mov ax, cs
719 stosw
720 mov ax, # cirrus_vesa_productrevision
721 stosw
722 mov ax, cs
723 stosw
724 cv00_1:
725 mov di, bp
726 mov ax, #0x4556 ;; VE
727 stosw
728 mov ax, #0x4153 ;; SA
729 stosw
730 mov ax, #0x0200 ;; v2.00
731 stosw
732 mov ax, # cirrus_vesa_oemname
733 stosw
734 mov ax, cs
735 stosw
736 xor ax, ax ;; caps
737 stosw
738 stosw
739 lea ax, 0x40[bp]
740 stosw
741 mov ax, es
742 stosw
743 call cirrus_extbios_85h ;; vram in 64k
744 mov ah, #0x00
745 stosw
747 push cs
748 pop ds
749 lea di, 0x40[bp]
750 mov si, #_cirrus_vesa_modelist
751 cv00_2:
752 lodsw
753 stosw
754 add si, #2
755 cmp ax, #0xffff
756 jnz cv00_2
758 mov ax, #0x004F
759 mov di, bp
760 pop si
761 pop ds
764 cirrus_vesa_01h:
765 mov ax, cx
766 and ax, #0x3fff
767 call cirrus_vesamode_to_mode
768 cmp ax, #0xffff
769 jnz cirrus_vesa_01h_1
770 jmp cirrus_vesa_unimplemented
771 cirrus_vesa_01h_1:
772 push ds
773 push si
774 push cx
775 push dx
776 push bx
777 mov bp, di
779 push cs
780 pop ds
781 call cirrus_get_modeentry_nomask
783 push di
784 xor ax, ax
785 mov cx, #0x80
787 stosw ;; clear buffer
788 pop di
790 mov ax, #0x003b ;; mode
791 stosw
792 mov ax, #0x0707 ;; attr
793 stosw
794 mov ax, #0x0010 ;; granularity =16K
795 stosw
796 mov ax, #0x0020 ;; size =32K
797 stosw
798 mov ax, #0xA000 ;; segment A
799 stosw
800 mov ax, #0xA800 ;; segment B
801 stosw
802 mov ax, #cirrus_vesa_05h_farentry
803 stosw
804 mov ax, cs
805 stosw
806 call cirrus_get_line_offset_entry
807 stosw ;; bytes per scan line
808 mov ax, [si+2] ;; width
809 stosw
810 mov ax, [si+4] ;; height
811 stosw
812 mov ax, #0x08
813 stosb
814 mov ax, #0x10
815 stosb
816 mov al, #1 ;; count of planes
817 stosb
818 mov al, [si+6] ;; bpp
819 stosb
820 mov al, #0x1 ;; XXX number of banks
821 stosb
822 mov al, [si+17]
823 stosb ;; memory model
824 mov al, #0x0 ;; XXX size of bank in K
825 stosb
826 call cirrus_get_line_offset_entry
827 mov bx, [si+4]
828 mul bx ;; dx:ax=vramdisp
829 or ax, ax
830 jz cirrus_vesa_01h_3
831 inc dx
832 cirrus_vesa_01h_3:
833 call cirrus_extbios_85h ;; al=vram in 64k
834 mov ah, #0x00
835 mov cx, dx
836 xor dx, dx
837 div cx
838 dec ax
839 stosb ;; number of image pages = vramtotal/vramdisp-1
840 mov al, #0x00
841 stosb
843 ;; v1.2+ stuffs
844 push si
845 add si, #18
846 movsw
847 movsw
848 movsw
849 movsw
850 pop si
852 mov ah, [si+16]
853 mov al, #0x0
854 sub ah, #9
855 rcl al, #1 ; bit 0=palette flag
856 stosb ;; direct screen mode info
858 ;; v2.0+ stuffs
859 ;; 32-bit LFB address
860 xor ax, ax
861 stosw
862 call cirrus_get_lfb_addr
863 stosw
864 or ax, ax
865 jz cirrus_vesa_01h_4
866 push di
867 mov di, bp
868 db 0x26 ;; es:
869 mov ax, [di]
870 or ax, #0x0080 ;; mode bit 7:LFB
871 stosw
872 pop di
873 cirrus_vesa_01h_4:
875 xor ax, ax
876 stosw ; reserved
877 stosw ; reserved
878 stosw ; reserved
880 mov ax, #0x004F
881 mov di, bp
882 pop bx
883 pop dx
884 pop cx
885 pop si
886 pop ds
888 test cx, #0x4000 ;; LFB flag
889 jz cirrus_vesa_01h_5
890 push cx
891 db 0x26 ;; es:
892 mov cx, [di]
893 cmp cx, #0x0080 ;; is LFB supported?
894 jnz cirrus_vesa_01h_6
895 mov ax, #0x014F ;; error - no LFB
896 cirrus_vesa_01h_6:
897 pop cx
898 cirrus_vesa_01h_5:
901 cirrus_vesa_02h:
902 ;; XXX support CRTC registers
903 test bx, #0x3e00
904 jnz cirrus_vesa_02h_2 ;; unknown flags
905 mov ax, bx
906 and ax, #0x1ff ;; bit 8-0 mode
907 cmp ax, #0x100 ;; legacy VGA mode
908 jb cirrus_vesa_02h_legacy
909 call cirrus_vesamode_to_mode
910 cmp ax, #0xffff
911 jnz cirrus_vesa_02h_1
912 cirrus_vesa_02h_2:
913 jmp cirrus_vesa_unimplemented
914 cirrus_vesa_02h_legacy:
915 #ifdef CIRRUS_VESA3_PMINFO
916 db 0x2e ;; cs:
917 cmp byte ptr [cirrus_vesa_is_protected_mode], #0
918 jnz cirrus_vesa_02h_2
919 #endif // CIRRUS_VESA3_PMINFO
920 int #0x10
921 mov ax, #0x004F
923 cirrus_vesa_02h_1:
924 push si
925 push ax
926 call cirrus_get_modeentry_nomask
927 call cirrus_switch_mode
928 test bx, #0x4000 ;; LFB
929 jz cirrus_vesa_02h_3
930 call cirrus_enable_dualbank
931 cirrus_vesa_02h_3:
932 pop ax
933 push ds
934 #ifdef CIRRUS_VESA3_PMINFO
935 db 0x2e ;; cs:
936 mov si, [cirrus_vesa_sel0000_data]
937 #else
938 xor si, si
939 #endif
940 mov ds, si
941 mov [PM_BIOSMEM_CURRENT_MODE], al
942 mov [PM_BIOSMEM_VBE_MODE], bx
943 pop ds
944 pop si
945 mov ax, #0x004F
948 cirrus_vesa_03h:
949 push ds
950 #ifdef CIRRUS_VESA3_PMINFO
951 db 0x2e ;; cs:
952 mov ax, [cirrus_vesa_sel0000_data]
953 #else
954 xor ax, ax
955 #endif
956 mov ds, ax
957 mov bx, # PM_BIOSMEM_VBE_MODE
958 mov ax, [bx]
959 mov bx, ax
960 test bx, bx
961 jnz cirrus_vesa_03h_1
962 mov bx, # PM_BIOSMEM_CURRENT_MODE
963 mov al, [bx]
964 mov bl, al
965 xor bh, bh
966 cirrus_vesa_03h_1:
967 mov ax, #0x004f
968 pop ds
971 cirrus_vesa_05h_farentry:
972 call cirrus_vesa_05h
973 retf
975 cirrus_vesa_05h:
976 cmp bl, #0x01
977 ja cirrus_vesa_05h_1
978 cmp bh, #0x00
979 jz cirrus_vesa_05h_setmempage
980 cmp bh, #0x01
981 jz cirrus_vesa_05h_getmempage
982 cirrus_vesa_05h_1:
983 jmp cirrus_vesa_unimplemented
984 cirrus_vesa_05h_setmempage:
985 or dh, dh ; address must be < 0x100
986 jnz cirrus_vesa_05h_1
987 push dx
988 mov al, bl ;; bl=bank number
989 add al, #0x09
990 mov ah, dl ;; dx=window address in granularity
991 mov dx, #0x3ce
992 out dx, ax
993 pop dx
994 mov ax, #0x004F
996 cirrus_vesa_05h_getmempage:
997 mov al, bl ;; bl=bank number
998 add al, #0x09
999 mov dx, #0x3ce
1000 out dx, al
1001 inc dx
1002 in al, dx
1003 xor dx, dx
1004 mov dl, al ;; dx=window address in granularity
1005 mov ax, #0x004F
1008 cirrus_vesa_06h:
1009 mov ax, cx
1010 cmp bl, #0x01
1011 je cirrus_vesa_06h_3
1012 cmp bl, #0x02
1013 je cirrus_vesa_06h_2
1014 jb cirrus_vesa_06h_1
1015 mov ax, #0x0100
1017 cirrus_vesa_06h_1:
1018 call cirrus_get_bpp_bytes
1019 mov bl, al
1020 xor bh, bh
1021 mov ax, cx
1022 mul bx
1023 cirrus_vesa_06h_2:
1024 call cirrus_set_line_offset
1025 cirrus_vesa_06h_3:
1026 call cirrus_get_bpp_bytes
1027 mov bl, al
1028 xor bh, bh
1029 xor dx, dx
1030 call cirrus_get_line_offset
1031 push ax
1032 div bx
1033 mov cx, ax
1034 pop bx
1035 call cirrus_extbios_85h ;; al=vram in 64k
1036 xor dx, dx
1037 mov dl, al
1038 xor ax, ax
1039 div bx
1040 mov dx, ax
1041 mov ax, #0x004f
1044 cirrus_vesa_07h:
1045 cmp bl, #0x80
1046 je cirrus_vesa_07h_1
1047 cmp bl, #0x01
1048 je cirrus_vesa_07h_2
1049 jb cirrus_vesa_07h_1
1050 mov ax, #0x0100
1052 cirrus_vesa_07h_1:
1053 push dx
1054 call cirrus_get_bpp_bytes
1055 mov bl, al
1056 xor bh, bh
1057 mov ax, cx
1058 mul bx
1059 pop bx
1060 push ax
1061 call cirrus_get_line_offset
1062 mul bx
1063 pop bx
1064 add ax, bx
1065 jnc cirrus_vesa_07h_3
1066 inc dx
1067 cirrus_vesa_07h_3:
1068 push dx
1069 mov bx, #0x04
1070 div bx
1071 pop dx
1072 shr dx, #2
1073 call cirrus_set_start_addr
1074 mov ax, #0x004f
1076 cirrus_vesa_07h_2:
1077 call cirrus_get_start_addr
1078 shl dx, #2
1079 push dx
1080 mov bx, #0x04
1081 mul bx
1082 pop bx
1083 or dx, bx
1084 push ax
1085 call cirrus_get_line_offset
1086 mov bx, ax
1087 pop ax
1088 div bx
1089 push ax
1090 push dx
1091 call cirrus_get_bpp_bytes
1092 mov bl, al
1093 xor bh, bh
1094 pop ax
1095 xor dx, dx
1096 div bx
1097 mov cx, ax
1098 pop dx
1099 mov ax, #0x004f
1102 cirrus_vesa_unimplemented:
1103 mov ax, #0x014F ;; not implemented
1107 ;; in ax:vesamode, out ax:cirrusmode
1108 cirrus_vesamode_to_mode:
1109 push ds
1110 push cx
1111 push si
1112 push cs
1113 pop ds
1114 mov cx, #0xffff
1115 mov si, #_cirrus_vesa_modelist
1116 cvtm_1:
1117 cmp [si],ax
1118 jz cvtm_2
1119 cmp [si],cx
1120 jz cvtm_2
1121 add si, #4
1122 jmp cvtm_1
1123 cvtm_2:
1124 mov ax,[si+2]
1125 pop si
1126 pop cx
1127 pop ds
1130 ; cirrus_get_crtc
1131 ;; NOTE - may be called in protected mode
1132 cirrus_get_crtc:
1133 push ds
1134 push ax
1135 mov dx, #0x3cc
1136 in al, dx
1137 and al, #0x01
1138 shl al, #5
1139 mov dx, #0x3b4
1140 add dl, al
1141 pop ax
1142 pop ds
1145 ;; in - al:mode, out - cflag:result, si:table, ax:destroyed
1146 cirrus_get_modeentry:
1147 and al, #0x7f
1148 cirrus_get_modeentry_nomask:
1149 mov si, #_cirrus_modes
1150 cgm_1:
1151 db 0x2e ;; cs:
1152 mov ah, [si]
1153 cmp al, ah
1154 jz cgm_2
1155 cmp ah, #0xff
1156 jz cgm_4
1157 add si, # CIRRUS_MODE_SIZE
1158 jmp cgm_1
1159 cgm_4:
1160 xor si, si
1161 stc ;; video mode is not supported
1162 jmp cgm_3
1163 cgm_2:
1164 clc ;; video mode is supported
1165 cgm_3:
1168 ; get LFB address
1169 ; out - ax:LFB address (high 16 bit)
1170 ;; NOTE - may be called in protected mode
1171 cirrus_get_lfb_addr:
1172 push cx
1173 push dx
1174 push eax
1175 xor cx, cx
1176 mov dl, #0x00
1177 call cirrus_pci_read
1178 cmp ax, #0xffff
1179 jz cirrus_get_lfb_addr_5
1180 cirrus_get_lfb_addr_3:
1181 mov dl, #0x00
1182 call cirrus_pci_read
1183 cmp ax, #0x1013 ;; cirrus
1184 jz cirrus_get_lfb_addr_4
1185 add cx, #0x8
1186 cmp cx, #0x200 ;; search bus #0 and #1
1187 jb cirrus_get_lfb_addr_3
1188 cirrus_get_lfb_addr_5:
1189 xor dx, dx ;; no LFB
1190 jmp cirrus_get_lfb_addr_6
1191 cirrus_get_lfb_addr_4:
1192 mov dl, #0x10 ;; I/O space #0
1193 call cirrus_pci_read
1194 test ax, #0xfff1
1195 jnz cirrus_get_lfb_addr_5
1196 shr eax, #16
1197 mov dx, ax ;; LFB address
1198 cirrus_get_lfb_addr_6:
1199 pop eax
1200 mov ax, dx
1201 pop dx
1202 pop cx
1205 cirrus_pci_read:
1206 mov eax, #0x00800000
1207 mov ax, cx
1208 shl eax, #8
1209 mov al, dl
1210 mov dx, #0xcf8
1211 out dx, eax
1212 add dl, #4
1213 in eax, dx
1216 ;; out - al:bytes per pixel
1217 cirrus_get_bpp_bytes:
1218 push dx
1219 mov dx, #0x03c4
1220 mov al, #0x07
1221 out dx, al
1222 inc dx
1223 in al, dx
1224 and al, #0x0e
1225 cmp al, #0x06
1226 jne cirrus_get_bpp_bytes_1
1227 and al, #0x02
1228 cirrus_get_bpp_bytes_1:
1229 shr al, #1
1230 cmp al, #0x04
1231 je cirrus_get_bpp_bytes_2
1232 inc al
1233 cirrus_get_bpp_bytes_2:
1234 pop dx
1237 ;; in - ax: new line offset
1238 cirrus_set_line_offset:
1239 shr ax, #3
1240 push ax
1241 call cirrus_get_crtc
1242 mov al, #0x13
1243 out dx, al
1244 inc dx
1245 pop ax
1246 out dx, al
1247 dec dx
1248 mov al, #0x1b
1249 out dx, al
1250 inc dx
1251 shl ah, #4
1252 in al, dx
1253 and al, #ef
1254 or al, ah
1255 out dx, al
1258 ;; out - ax: active line offset
1259 cirrus_get_line_offset:
1260 push dx
1261 push bx
1262 call cirrus_get_crtc
1263 mov al, #0x13
1264 out dx, al
1265 inc dx
1266 in al, dx
1267 mov bl, al
1268 dec dx
1269 mov al, #0x1b
1270 out dx, al
1271 inc dx
1272 in al, dx
1273 mov ah, al
1274 shr ah, #4
1275 and ah, #0x01
1276 mov al, bl
1277 shl ax, #3
1278 pop bx
1279 pop dx
1282 ;; in - si: table
1283 ;; out - ax: line offset for mode
1284 cirrus_get_line_offset_entry:
1285 push bx
1286 mov bx, [si+14] ;; crtc table
1287 push bx
1288 offset_loop1:
1289 mov ax, [bx]
1290 cmp al, #0x13
1291 je offset_found1
1292 inc bx
1293 inc bx
1294 jnz offset_loop1
1295 offset_found1:
1296 xor al, al
1297 shr ax, #5
1298 pop bx
1299 push ax
1300 offset_loop2:
1301 mov ax, [bx]
1302 cmp al, #0x1b
1303 je offset_found2
1304 inc bx
1305 inc bx
1306 jnz offset_loop2
1307 offset_found2:
1308 pop bx
1309 and ax, #0x1000
1310 shr ax, #1
1311 or ax, bx
1312 pop bx
1315 ;; in - new address in DX:AX
1316 cirrus_set_start_addr:
1317 push bx
1318 push dx
1319 push ax
1320 call cirrus_get_crtc
1321 mov al, #0x0d
1322 out dx, al
1323 inc dx
1324 pop ax
1325 out dx, al
1326 dec dx
1327 mov al, #0x0c
1328 out dx, al
1329 inc dx
1330 mov al, ah
1331 out dx, al
1332 dec dx
1333 mov al, #0x1d
1334 out dx, al
1335 inc dx
1336 in al, dx
1337 and al, #0x7f
1338 pop bx
1339 mov ah, bl
1340 shl bl, #4
1341 and bl, #0x80
1342 or al, bl
1343 out dx, al
1344 dec dx
1345 mov bl, ah
1346 and ah, #0x01
1347 shl bl, #1
1348 and bl, #0x0c
1349 or ah, bl
1350 mov al, #0x1b
1351 out dx, al
1352 inc dx
1353 in al, dx
1354 and al, #0xf2
1355 or al, ah
1356 out dx, al
1357 pop bx
1360 ;; out - current address in DX:AX
1361 cirrus_get_start_addr:
1362 push bx
1363 call cirrus_get_crtc
1364 mov al, #0x0c
1365 out dx, al
1366 inc dx
1367 in al, dx
1368 mov ah, al
1369 dec dx
1370 mov al, #0x0d
1371 out dx, al
1372 inc dx
1373 in al, dx
1374 push ax
1375 dec dx
1376 mov al, #0x1b
1377 out dx, al
1378 inc dx
1379 in al, dx
1380 dec dx
1381 mov bl, al
1382 and al, #0x01
1383 and bl, #0x0c
1384 shr bl, #1
1385 or bl, al
1386 mov al, #0x1d
1387 out dx, al
1388 inc dx
1389 in al, dx
1390 and al, #0x80
1391 shr al, #4
1392 or bl, al
1393 mov dl, bl
1394 xor dh, dh
1395 pop ax
1396 pop bx
1399 cirrus_extbios_handlers:
1400 ;; 80h
1401 dw cirrus_extbios_80h
1402 dw cirrus_extbios_81h
1403 dw cirrus_extbios_82h
1404 dw cirrus_extbios_unimplemented
1405 ;; 84h
1406 dw cirrus_extbios_unimplemented
1407 dw cirrus_extbios_85h
1408 dw cirrus_extbios_unimplemented
1409 dw cirrus_extbios_unimplemented
1410 ;; 88h
1411 dw cirrus_extbios_unimplemented
1412 dw cirrus_extbios_unimplemented
1413 dw cirrus_extbios_unimplemented
1414 dw cirrus_extbios_unimplemented
1415 ;; 8Ch
1416 dw cirrus_extbios_unimplemented
1417 dw cirrus_extbios_unimplemented
1418 dw cirrus_extbios_unimplemented
1419 dw cirrus_extbios_unimplemented
1420 ;; 90h
1421 dw cirrus_extbios_unimplemented
1422 dw cirrus_extbios_unimplemented
1423 dw cirrus_extbios_unimplemented
1424 dw cirrus_extbios_unimplemented
1425 ;; 94h
1426 dw cirrus_extbios_unimplemented
1427 dw cirrus_extbios_unimplemented
1428 dw cirrus_extbios_unimplemented
1429 dw cirrus_extbios_unimplemented
1430 ;; 98h
1431 dw cirrus_extbios_unimplemented
1432 dw cirrus_extbios_unimplemented
1433 dw cirrus_extbios_9Ah
1434 dw cirrus_extbios_unimplemented
1435 ;; 9Ch
1436 dw cirrus_extbios_unimplemented
1437 dw cirrus_extbios_unimplemented
1438 dw cirrus_extbios_unimplemented
1439 dw cirrus_extbios_unimplemented
1440 ;; A0h
1441 dw cirrus_extbios_A0h
1442 dw cirrus_extbios_A1h
1443 dw cirrus_extbios_A2h
1444 dw cirrus_extbios_unimplemented
1445 ;; A4h
1446 dw cirrus_extbios_unimplemented
1447 dw cirrus_extbios_unimplemented
1448 dw cirrus_extbios_unimplemented
1449 dw cirrus_extbios_unimplemented
1450 ;; A8h
1451 dw cirrus_extbios_unimplemented
1452 dw cirrus_extbios_unimplemented
1453 dw cirrus_extbios_unimplemented
1454 dw cirrus_extbios_unimplemented
1455 ;; ACh
1456 dw cirrus_extbios_unimplemented
1457 dw cirrus_extbios_unimplemented
1458 dw cirrus_extbios_AEh
1459 dw cirrus_extbios_unimplemented
1461 cirrus_vesa_handlers:
1462 ;; 00h
1463 dw cirrus_vesa_00h
1464 dw cirrus_vesa_01h
1465 dw cirrus_vesa_02h
1466 dw cirrus_vesa_03h
1467 ;; 04h
1468 dw cirrus_vesa_unimplemented
1469 dw cirrus_vesa_05h
1470 dw cirrus_vesa_06h
1471 dw cirrus_vesa_07h
1472 ;; 08h
1473 dw cirrus_vesa_unimplemented
1474 dw cirrus_vesa_unimplemented
1475 dw cirrus_vesa_unimplemented
1476 dw cirrus_vesa_unimplemented
1477 ;; 0Ch
1478 dw cirrus_vesa_unimplemented
1479 dw cirrus_vesa_unimplemented
1480 dw cirrus_vesa_unimplemented
1481 dw cirrus_vesa_unimplemented
1485 ASM_END
1487 #ifdef CIRRUS_VESA3_PMINFO
1488 ASM_START
1489 cirrus_vesa_pminfo:
1490 /* + 0 */
1491 .byte 0x50,0x4d,0x49,0x44 ;; signature[4]
1492 /* + 4 */
1493 dw cirrus_vesa_pmbios_entry ;; entry_bios
1494 dw cirrus_vesa_pmbios_init ;; entry_init
1495 /* + 8 */
1496 cirrus_vesa_sel0000_data:
1497 dw 0x0000 ;; sel_00000
1498 cirrus_vesa_selA000_data:
1499 dw 0xA000 ;; sel_A0000
1500 /* +12 */
1501 cirrus_vesa_selB000_data:
1502 dw 0xB000 ;; sel_B0000
1503 cirrus_vesa_selB800_data:
1504 dw 0xB800 ;; sel_B8000
1505 /* +16 */
1506 cirrus_vesa_selC000_data:
1507 dw 0xC000 ;; sel_C0000
1508 cirrus_vesa_is_protected_mode:
1509 db 0x00 ;; is_protected_mode
1510 db 0x00 ;; check_sum
1511 ASM_END
1512 #endif // CIRRUS_VESA3_PMINFO
1515 #ifdef CIRRUS_DEBUG
1516 static void cirrus_debugmsg(DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS)
1517 Bit16u DI, SI, BP, SP, BX, DX, CX, AX, ES, DS, FLAGS;
1519 if((GET_AH()!=0x0E)&&(GET_AH()!=0x02)&&(GET_AH()!=0x09)&&(AX!=0x4F05))
1520 printf("vgabios call ah%02x al%02x bx%04x cx%04x dx%04x\n",GET_AH(),GET_AL(),BX,CX,DX);
1522 #endif