- cirrus init: set standard vga mode and reset bitblt
[vgabios.git] / clext.c
blobbd630de3118188b9eb22c183b6229ef391d8b1d3
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 0x0300,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 0x0300,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 0x0300,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 0x0300,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 0x0300,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 0x0300,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 0x0300,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 0x0300,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 0x0300,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
210 /* 1280x1024x8 */
211 unsigned short cseq_1280x1024x8[] = {
212 0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1107,
213 0x760b,0x760c,0x760d,0x760e,
214 0x0412,0x0013,0x2017,
215 0x341b,0x341c,0x341d,0x341e,
216 0xffff
218 unsigned short ccrtc_1280x1024x8[] = {
219 0x2911,0xc300,0x9f01,0x9f02,0x8603,0x8304,0x9405,0x2406,0xf707,
220 0x6009,0x000c,0x000d,
221 0x0310,0xff12,0xa013,0x4014,0xff15,0x2416,0xc317,0xff18,
222 0x001a,0x221b,0x001d,
223 0xffff
227 cirrus_mode_t cirrus_modes[] =
229 {0x5f,640,480,8,0x00,
230 cseq_640x480x8,cgraph_svgacolor,ccrtc_640x480x8,8,
231 4,0,0,0,0,0,0,0,0},
232 {0x64,640,480,16,0xe1,
233 cseq_640x480x16,cgraph_svgacolor,ccrtc_640x480x16,16,
234 6,5,11,6,5,5,0,0,0},
235 {0x66,640,480,15,0xf0,
236 cseq_640x480x16,cgraph_svgacolor,ccrtc_640x480x16,16,
237 6,5,10,5,5,5,0,1,15},
238 {0x71,640,480,24,0xe5,
239 cseq_640x480x24,cgraph_svgacolor,ccrtc_640x480x24,24,
240 6,8,16,8,8,8,0,0,0},
242 {0x5c,800,600,8,0x00,
243 cseq_800x600x8,cgraph_svgacolor,ccrtc_800x600x8,8,
244 4,0,0,0,0,0,0,0,0},
245 {0x65,800,600,16,0xe1,
246 cseq_800x600x16,cgraph_svgacolor,ccrtc_800x600x16,16,
247 6,5,11,6,5,5,0,0,0},
248 {0x67,800,600,15,0xf0,
249 cseq_800x600x16,cgraph_svgacolor,ccrtc_800x600x16,16,
250 6,5,10,5,5,5,0,1,15},
252 {0x60,1024,768,8,0x00,
253 cseq_1024x768x8,cgraph_svgacolor,ccrtc_1024x768x8,8,
254 4,0,0,0,0,0,0,0,0},
255 {0x74,1024,768,16,0xe1,
256 cseq_1024x768x16,cgraph_svgacolor,ccrtc_1024x768x16,16,
257 6,5,11,6,5,5,0,0,0},
258 {0x68,1024,768,15,0xf0,
259 cseq_1024x768x16,cgraph_svgacolor,ccrtc_1024x768x16,16,
260 6,5,10,5,5,5,0,1,15},
262 {0x78,800,600,24,0xe5,
263 cseq_800x600x24,cgraph_svgacolor,ccrtc_800x600x24,24,
264 6,8,16,8,8,8,0,0,0},
265 {0x79,1024,768,24,0xe5,
266 cseq_1024x768x24,cgraph_svgacolor,ccrtc_1024x768x24,24,
267 6,8,16,8,8,8,0,0,0},
269 {0x6d,1280,1024,8,0x00,
270 cseq_1280x1024x8,cgraph_svgacolor,ccrtc_1280x1024x8,8,
271 4,0,0,0,0,0,0,0,0},
273 {0xfe,0,0,0,0,cseq_vga,cgraph_vga,ccrtc_vga,0,
274 0xff,0,0,0,0,0,0,0,0},
275 {0xff,0,0,0,0,0,0,0,0,
276 0xff,0,0,0,0,0,0,0,0},
279 unsigned char cirrus_id_table[] = {
280 // 5430
281 0xA0, 0x32,
282 // 5446
283 0xB8, 0x39,
285 0xff, 0xff
289 unsigned short cirrus_vesa_modelist[] = {
290 // 640x480x8
291 0x101, 0x5f,
292 // 640x480x15
293 0x110, 0x66,
294 // 640x480x16
295 0x111, 0x64,
296 // 640x480x24
297 0x112, 0x71,
298 // 800x600x8
299 0x103, 0x5c,
300 // 800x600x15
301 0x113, 0x67,
302 // 800x600x16
303 0x114, 0x65,
304 // 800x600x24
305 0x115, 0x78,
306 // 1024x768x8
307 0x105, 0x60,
308 // 1024x768x15
309 0x116, 0x68,
310 // 1024x768x16
311 0x117, 0x74,
312 // 1024x768x24
313 //0x118, 0x79,
314 // 1280x1024x8
315 0x107, 0x6d,
316 // invalid
317 0xffff,0xffff
321 ASM_START
323 cirrus_installed:
324 .ascii "cirrus-compatible VGA is detected"
325 .byte 0x0d,0x0a
326 .byte 0x0d,0x0a,0x00
328 cirrus_not_installed:
329 .ascii "cirrus-compatible VGA is not detected"
330 .byte 0x0d,0x0a
331 .byte 0x0d,0x0a,0x00
333 cirrus_vesa_vendorname:
334 cirrus_vesa_productname:
335 cirrus_vesa_oemname:
336 .ascii "VGABIOS Cirrus extension"
337 .byte 0
338 cirrus_vesa_productrevision:
339 .ascii "1.0"
340 .byte 0
342 cirrus_init:
343 call cirrus_check
344 jnz no_cirrus
345 SET_INT_VECTOR(0x10, #0xC000, #cirrus_int10_handler)
346 mov al, #0x0f ; memory setup
347 mov dx, #0x3C4
348 out dx, al
349 inc dx
350 in al, dx
351 and al, #0x18
352 mov ah, al
353 mov al, #0x0a
354 dec dx
355 out dx, ax
356 mov ax, #0x0007 ; set vga mode
357 out dx, ax
358 mov ax, #0x0431 ; reset bitblt
359 mov dx, #0x3CE
360 out dx, ax
361 mov ax, #0x0031
362 out dx, ax
363 no_cirrus:
366 cirrus_display_info:
367 push ds
368 push si
369 push cs
370 pop ds
371 call cirrus_check
372 mov si, #cirrus_not_installed
373 jnz cirrus_msgnotinstalled
374 mov si, #cirrus_installed
376 cirrus_msgnotinstalled:
377 call _display_string
378 pop si
379 pop ds
382 cirrus_check:
383 push ax
384 push dx
385 mov ax, #0x9206
386 mov dx, #0x3C4
387 out dx, ax
388 inc dx
389 in al, dx
390 cmp al, #0x12
391 pop dx
392 pop ax
396 cirrus_int10_handler:
397 pushf
398 push bp
399 cmp ah, #0x00 ;; set video mode
400 jz cirrus_set_video_mode
401 cmp ah, #0x12 ;; cirrus extension
402 jz cirrus_extbios
403 cmp ah, #0x4F ;; VESA extension
404 jz cirrus_vesa
406 cirrus_unhandled:
407 pop bp
408 popf
409 jmp vgabios_int10_handler
411 cirrus_return:
412 #ifdef CIRRUS_DEBUG
413 call cirrus_debug_dump
414 #endif
415 pop bp
416 popf
417 iret
419 cirrus_set_video_mode:
420 #ifdef CIRRUS_DEBUG
421 call cirrus_debug_dump
422 #endif
423 push si
424 push ax
425 push bx
426 push ds
427 #ifdef CIRRUS_VESA3_PMINFO
428 db 0x2e ;; cs:
429 mov si, [cirrus_vesa_sel0000_data]
430 #else
431 xor si, si
432 #endif
433 mov ds, si
434 xor bx, bx
435 mov [PM_BIOSMEM_VBE_MODE], bx
436 pop ds
437 pop bx
438 call cirrus_get_modeentry
439 jnc cirrus_set_video_mode_extended
440 mov al, #0xfe
441 call cirrus_get_modeentry_nomask
442 call cirrus_switch_mode
443 pop ax
444 pop si
445 jmp cirrus_unhandled
447 cirrus_extbios:
448 #ifdef CIRRUS_DEBUG
449 call cirrus_debug_dump
450 #endif
451 cmp bl, #0x80
452 jb cirrus_unhandled
453 cmp bl, #0xAF
454 ja cirrus_unhandled
455 push bx
456 and bx, #0x7F
457 shl bx, 1
458 db 0x2e ;; cs:
459 mov bp, cirrus_extbios_handlers[bx]
460 pop bx
461 push #cirrus_return
462 push bp
465 cirrus_vesa:
466 #ifdef CIRRUS_DEBUG
467 call cirrus_debug_dump
468 #endif
469 cmp al, #0x0F
470 ja cirrus_vesa_not_handled
471 push bx
472 xor bx, bx
473 mov bl, al
474 shl bx, 1
475 db 0x2e ;; cs:
476 mov bp, cirrus_vesa_handlers[bx]
477 pop bx
478 push #cirrus_return
479 push bp
482 cirrus_vesa_not_handled:
483 mov ax, #0x014F ;; not implemented
484 jmp cirrus_return
486 #ifdef CIRRUS_DEBUG
487 cirrus_debug_dump:
488 push es
489 push ds
490 pusha
491 push cs
492 pop ds
493 call _cirrus_debugmsg
494 popa
495 pop ds
496 pop es
498 #endif
500 cirrus_set_video_mode_extended:
501 call cirrus_switch_mode
502 pop ax ;; mode
503 and al, #0x7f
505 push ds
506 #ifdef CIRRUS_VESA3_PMINFO
507 db 0x2e ;; cs:
508 mov si, [cirrus_vesa_sel0000_data]
509 #else
510 xor si, si
511 #endif
512 mov ds, si
513 mov [PM_BIOSMEM_CURRENT_MODE], al
514 pop ds
516 mov al, #0x20
518 pop si
519 jmp cirrus_return
521 cirrus_vesa_pmbios_init:
522 retf
523 cirrus_vesa_pmbios_entry:
524 pushf
525 push bp
526 cmp ah, #0x4F
527 jnz cirrus_vesa_pmbios_unimplemented
528 cmp al, #0x0F
529 ja cirrus_vesa_pmbios_unimplemented
530 push bx
531 xor bx, bx
532 mov bl, al
533 shl bx, 1
534 db 0x2e ;; cs:
535 mov bp, cirrus_vesa_handlers[bx]
536 pop bx
537 push #cirrus_vesa_pmbios_return
538 push bp
540 cirrus_vesa_pmbios_unimplemented:
541 mov ax, #0x014F
542 cirrus_vesa_pmbios_return:
543 pop bp
544 popf
545 retf
547 ; in si:mode table
548 cirrus_switch_mode:
549 push ds
550 push bx
551 push dx
552 push cs
553 pop ds
555 mov bx, [si+10] ;; seq
556 mov dx, #0x3c4
557 mov ax, #0x1206
558 out dx, ax ;; Unlock cirrus special
559 call cirrus_switch_mode_setregs
561 mov bx, [si+12] ;; graph
562 mov dx, #0x3ce
563 call cirrus_switch_mode_setregs
565 mov bx, [si+14] ;; crtc
566 call cirrus_get_crtc
567 call cirrus_switch_mode_setregs
569 mov dx, #0x3c6
570 mov al, #0x00
571 out dx, al
572 in al, dx
573 in al, dx
574 in al, dx
575 in al, dx
576 mov al, [si+8] ;; hidden dac
577 out dx, al
578 mov al, #0xff
579 out dx, al
581 mov al, #0x00
582 mov bl, [si+17] ;; memory model
583 or bl, bl
584 jz is_text_mode
585 mov al, #0x01
586 cmp bl, #0x03
587 jnz is_text_mode
588 or al, #0x40
589 is_text_mode:
590 mov bl, #0x10
591 call biosfn_get_single_palette_reg
592 and bh, #0xfe
593 or bh, al
594 call biosfn_set_single_palette_reg
596 pop dx
597 pop bx
598 pop ds
601 cirrus_enable_dualbank:
602 push ax
603 push dx
604 mov dx, #0x3ce
605 mov al, #0x0b
606 out dx, al
607 inc dx
608 in al, dx
609 or al, #0x21 ;; enable dual bank
610 out dx, al
611 pop dx
612 pop ax
615 cirrus_switch_mode_setregs:
616 csms_1:
617 mov ax, [bx]
618 cmp ax, #0xffff
619 jz csms_2
620 out dx, ax
621 add bx, #0x2
622 jmp csms_1
623 csms_2:
626 cirrus_extbios_80h:
627 push dx
628 call cirrus_get_crtc
629 mov al, #0x27
630 out dx, al
631 inc dx
632 in al, dx
633 mov bx, #_cirrus_id_table
634 c80h_1:
635 db 0x2e ;; cs:
636 mov ah, [bx]
637 cmp ah, al
638 jz c80h_2
639 cmp ah, #0xff
640 jz c80h_2
641 inc bx
642 inc bx
643 jmp c80h_1
644 c80h_2:
645 db 0x2e ;; cs:
646 mov al, 0x1[bx]
647 pop dx
648 mov ah, #0x00
649 xor bx, bx
652 cirrus_extbios_81h:
653 mov ax, #0x100 ;; XXX
655 cirrus_extbios_82h:
656 push dx
657 call cirrus_get_crtc
658 xor ax, ax
659 mov al, #0x27
660 out dx, al
661 inc dx
662 in al, dx
663 and al, #0x03
664 mov ah, #0xAF
665 pop dx
668 cirrus_extbios_85h:
669 push cx
670 push dx
671 mov dx, #0x3C4
672 mov al, #0x0f ;; get DRAM band width
673 out dx, al
674 inc dx
675 in al, dx
676 ;; al = 4 << bandwidth
677 mov cl, al
678 shr cl, #0x03
679 and cl, #0x03
680 cmp cl, #0x03
681 je c85h2
682 mov al, #0x04
683 shl al, cl
684 jmp c85h3
685 c85h2:
686 ;; 4MB or 2MB
687 and al, #0x80
688 mov al, #0x20 ;; 2 MB
689 je c85h3
690 mov al, #0x40 ;; 4 MB
691 c85h3:
692 pop dx
693 pop cx
696 cirrus_extbios_9Ah:
697 mov ax, #0x4060
698 mov cx, #0x1132
701 cirrus_extbios_A0h:
702 call cirrus_get_modeentry
703 mov ah, #0x01
704 sbb ah, #0x00
705 mov bx, cirrus_extbios_A0h_callback
706 mov si, #0xffff
707 mov di, bx
708 mov ds, bx
709 mov es, bx
712 cirrus_extbios_A0h_callback:
713 ;; fatal: not implemented yet
716 retf
718 cirrus_extbios_A1h:
719 mov bx, #0x0E00 ;; IBM 8512/8513, color
722 cirrus_extbios_A2h:
723 mov al, #0x07 ;; HSync 31.5 - 64.0 kHz
726 cirrus_extbios_AEh:
727 mov al, #0x01 ;; High Refresh 75Hz
730 cirrus_extbios_unimplemented:
733 cirrus_vesa_00h:
734 push ds
735 push si
736 mov bp, di
737 push es
738 pop ds
740 mov ax, [di]
741 cmp ax, #0x4256 ;; VB
742 jnz cv00_1
743 mov ax, [di+2]
744 cmp ax, #0x3245 ;; E2
745 jnz cv00_1
746 ;; VBE2
747 lea di, 0x14[bp]
748 mov ax, #0x0100 ;; soft ver.
749 stosw
750 mov ax, # cirrus_vesa_vendorname
751 stosw
752 mov ax, cs
753 stosw
754 mov ax, # cirrus_vesa_productname
755 stosw
756 mov ax, cs
757 stosw
758 mov ax, # cirrus_vesa_productrevision
759 stosw
760 mov ax, cs
761 stosw
762 cv00_1:
763 mov di, bp
764 mov ax, #0x4556 ;; VE
765 stosw
766 mov ax, #0x4153 ;; SA
767 stosw
768 mov ax, #0x0200 ;; v2.00
769 stosw
770 mov ax, # cirrus_vesa_oemname
771 stosw
772 mov ax, cs
773 stosw
774 xor ax, ax ;; caps
775 stosw
776 stosw
777 lea ax, 0x40[bp]
778 stosw
779 mov ax, es
780 stosw
781 call cirrus_extbios_85h ;; vram in 64k
782 mov ah, #0x00
783 stosw
785 push cs
786 pop ds
787 lea di, 0x40[bp]
788 mov si, #_cirrus_vesa_modelist
789 cv00_2:
790 lodsw
791 stosw
792 add si, #2
793 cmp ax, #0xffff
794 jnz cv00_2
796 mov ax, #0x004F
797 mov di, bp
798 pop si
799 pop ds
802 cirrus_vesa_01h:
803 mov ax, cx
804 and ax, #0x3fff
805 call cirrus_vesamode_to_mode
806 cmp ax, #0xffff
807 jnz cirrus_vesa_01h_1
808 jmp cirrus_vesa_unimplemented
809 cirrus_vesa_01h_1:
810 push ds
811 push si
812 push cx
813 push dx
814 push bx
815 mov bp, di
817 push cs
818 pop ds
819 call cirrus_get_modeentry_nomask
821 push di
822 xor ax, ax
823 mov cx, #0x80
825 stosw ;; clear buffer
826 pop di
828 mov ax, #0x003b ;; mode
829 stosw
830 mov ax, #0x0707 ;; attr
831 stosw
832 mov ax, #0x0010 ;; granularity =16K
833 stosw
834 mov ax, #0x0020 ;; size =32K
835 stosw
836 mov ax, #0xA000 ;; segment A
837 stosw
838 mov ax, #0xA800 ;; segment B
839 stosw
840 mov ax, #cirrus_vesa_05h_farentry
841 stosw
842 mov ax, cs
843 stosw
844 call cirrus_get_line_offset_entry
845 stosw ;; bytes per scan line
846 mov ax, [si+2] ;; width
847 stosw
848 mov ax, [si+4] ;; height
849 stosw
850 mov ax, #0x08
851 stosb
852 mov ax, #0x10
853 stosb
854 mov al, #1 ;; count of planes
855 stosb
856 mov al, [si+6] ;; bpp
857 stosb
858 mov al, #0x1 ;; XXX number of banks
859 stosb
860 mov al, [si+17]
861 stosb ;; memory model
862 mov al, #0x0 ;; XXX size of bank in K
863 stosb
864 call cirrus_get_line_offset_entry
865 mov bx, [si+4]
866 mul bx ;; dx:ax=vramdisp
867 or ax, ax
868 jz cirrus_vesa_01h_3
869 inc dx
870 cirrus_vesa_01h_3:
871 call cirrus_extbios_85h ;; al=vram in 64k
872 mov ah, #0x00
873 mov cx, dx
874 xor dx, dx
875 div cx
876 dec ax
877 stosb ;; number of image pages = vramtotal/vramdisp-1
878 mov al, #0x00
879 stosb
881 ;; v1.2+ stuffs
882 push si
883 add si, #18
884 movsw
885 movsw
886 movsw
887 movsw
888 pop si
890 mov ah, [si+16]
891 mov al, #0x0
892 sub ah, #9
893 rcl al, #1 ; bit 0=palette flag
894 stosb ;; direct screen mode info
896 ;; v2.0+ stuffs
897 ;; 32-bit LFB address
898 xor ax, ax
899 stosw
900 call cirrus_get_lfb_addr
901 stosw
902 or ax, ax
903 jz cirrus_vesa_01h_4
904 push di
905 mov di, bp
906 db 0x26 ;; es:
907 mov ax, [di]
908 or ax, #0x0080 ;; mode bit 7:LFB
909 stosw
910 pop di
911 cirrus_vesa_01h_4:
913 xor ax, ax
914 stosw ; reserved
915 stosw ; reserved
916 stosw ; reserved
918 mov ax, #0x004F
919 mov di, bp
920 pop bx
921 pop dx
922 pop cx
923 pop si
924 pop ds
926 test cx, #0x4000 ;; LFB flag
927 jz cirrus_vesa_01h_5
928 push cx
929 db 0x26 ;; es:
930 mov cx, [di]
931 cmp cx, #0x0080 ;; is LFB supported?
932 jnz cirrus_vesa_01h_6
933 mov ax, #0x014F ;; error - no LFB
934 cirrus_vesa_01h_6:
935 pop cx
936 cirrus_vesa_01h_5:
939 cirrus_vesa_02h:
940 ;; XXX support CRTC registers
941 test bx, #0x3e00
942 jnz cirrus_vesa_02h_2 ;; unknown flags
943 mov ax, bx
944 and ax, #0x1ff ;; bit 8-0 mode
945 cmp ax, #0x100 ;; legacy VGA mode
946 jb cirrus_vesa_02h_legacy
947 call cirrus_vesamode_to_mode
948 cmp ax, #0xffff
949 jnz cirrus_vesa_02h_1
950 cirrus_vesa_02h_2:
951 jmp cirrus_vesa_unimplemented
952 cirrus_vesa_02h_legacy:
953 #ifdef CIRRUS_VESA3_PMINFO
954 db 0x2e ;; cs:
955 cmp byte ptr [cirrus_vesa_is_protected_mode], #0
956 jnz cirrus_vesa_02h_2
957 #endif // CIRRUS_VESA3_PMINFO
958 int #0x10
959 mov ax, #0x004F
961 cirrus_vesa_02h_1:
962 push si
963 push ax
964 call cirrus_get_modeentry_nomask
965 call cirrus_switch_mode
966 test bx, #0x4000 ;; LFB
967 jz cirrus_vesa_02h_3
968 call cirrus_enable_dualbank
969 cirrus_vesa_02h_3:
970 pop ax
971 push ds
972 #ifdef CIRRUS_VESA3_PMINFO
973 db 0x2e ;; cs:
974 mov si, [cirrus_vesa_sel0000_data]
975 #else
976 xor si, si
977 #endif
978 mov ds, si
979 mov [PM_BIOSMEM_CURRENT_MODE], al
980 mov [PM_BIOSMEM_VBE_MODE], bx
981 pop ds
982 pop si
983 mov ax, #0x004F
986 cirrus_vesa_03h:
987 push ds
988 #ifdef CIRRUS_VESA3_PMINFO
989 db 0x2e ;; cs:
990 mov ax, [cirrus_vesa_sel0000_data]
991 #else
992 xor ax, ax
993 #endif
994 mov ds, ax
995 mov bx, # PM_BIOSMEM_VBE_MODE
996 mov ax, [bx]
997 mov bx, ax
998 test bx, bx
999 jnz cirrus_vesa_03h_1
1000 mov bx, # PM_BIOSMEM_CURRENT_MODE
1001 mov al, [bx]
1002 mov bl, al
1003 xor bh, bh
1004 cirrus_vesa_03h_1:
1005 mov ax, #0x004f
1006 pop ds
1009 cirrus_vesa_05h_farentry:
1010 call cirrus_vesa_05h
1011 retf
1013 cirrus_vesa_05h:
1014 cmp bl, #0x01
1015 ja cirrus_vesa_05h_1
1016 cmp bh, #0x00
1017 jz cirrus_vesa_05h_setmempage
1018 cmp bh, #0x01
1019 jz cirrus_vesa_05h_getmempage
1020 cirrus_vesa_05h_1:
1021 jmp cirrus_vesa_unimplemented
1022 cirrus_vesa_05h_setmempage:
1023 or dh, dh ; address must be < 0x100
1024 jnz cirrus_vesa_05h_1
1025 push dx
1026 mov al, bl ;; bl=bank number
1027 add al, #0x09
1028 mov ah, dl ;; dx=window address in granularity
1029 mov dx, #0x3ce
1030 out dx, ax
1031 pop dx
1032 mov ax, #0x004F
1034 cirrus_vesa_05h_getmempage:
1035 mov al, bl ;; bl=bank number
1036 add al, #0x09
1037 mov dx, #0x3ce
1038 out dx, al
1039 inc dx
1040 in al, dx
1041 xor dx, dx
1042 mov dl, al ;; dx=window address in granularity
1043 mov ax, #0x004F
1046 cirrus_vesa_06h:
1047 mov ax, cx
1048 cmp bl, #0x01
1049 je cirrus_vesa_06h_3
1050 cmp bl, #0x02
1051 je cirrus_vesa_06h_2
1052 jb cirrus_vesa_06h_1
1053 mov ax, #0x0100
1055 cirrus_vesa_06h_1:
1056 call cirrus_get_bpp_bytes
1057 mov bl, al
1058 xor bh, bh
1059 mov ax, cx
1060 mul bx
1061 cirrus_vesa_06h_2:
1062 call cirrus_set_line_offset
1063 cirrus_vesa_06h_3:
1064 call cirrus_get_bpp_bytes
1065 mov bl, al
1066 xor bh, bh
1067 xor dx, dx
1068 call cirrus_get_line_offset
1069 push ax
1070 div bx
1071 mov cx, ax
1072 pop bx
1073 call cirrus_extbios_85h ;; al=vram in 64k
1074 xor dx, dx
1075 mov dl, al
1076 xor ax, ax
1077 div bx
1078 mov dx, ax
1079 mov ax, #0x004f
1082 cirrus_vesa_07h:
1083 cmp bl, #0x80
1084 je cirrus_vesa_07h_1
1085 cmp bl, #0x01
1086 je cirrus_vesa_07h_2
1087 jb cirrus_vesa_07h_1
1088 mov ax, #0x0100
1090 cirrus_vesa_07h_1:
1091 push dx
1092 call cirrus_get_bpp_bytes
1093 mov bl, al
1094 xor bh, bh
1095 mov ax, cx
1096 mul bx
1097 pop bx
1098 push ax
1099 call cirrus_get_line_offset
1100 mul bx
1101 pop bx
1102 add ax, bx
1103 jnc cirrus_vesa_07h_3
1104 inc dx
1105 cirrus_vesa_07h_3:
1106 push dx
1107 and dx, #0x0003
1108 mov bx, #0x04
1109 div bx
1110 pop dx
1111 shr dx, #2
1112 call cirrus_set_start_addr
1113 mov ax, #0x004f
1115 cirrus_vesa_07h_2:
1116 call cirrus_get_start_addr
1117 shl dx, #2
1118 push dx
1119 mov bx, #0x04
1120 mul bx
1121 pop bx
1122 or dx, bx
1123 push ax
1124 call cirrus_get_line_offset
1125 mov bx, ax
1126 pop ax
1127 div bx
1128 push ax
1129 push dx
1130 call cirrus_get_bpp_bytes
1131 mov bl, al
1132 xor bh, bh
1133 pop ax
1134 xor dx, dx
1135 div bx
1136 mov cx, ax
1137 pop dx
1138 mov ax, #0x004f
1141 cirrus_vesa_unimplemented:
1142 mov ax, #0x014F ;; not implemented
1146 ;; in ax:vesamode, out ax:cirrusmode
1147 cirrus_vesamode_to_mode:
1148 push ds
1149 push cx
1150 push si
1151 push cs
1152 pop ds
1153 mov cx, #0xffff
1154 mov si, #_cirrus_vesa_modelist
1155 cvtm_1:
1156 cmp [si],ax
1157 jz cvtm_2
1158 cmp [si],cx
1159 jz cvtm_2
1160 add si, #4
1161 jmp cvtm_1
1162 cvtm_2:
1163 mov ax,[si+2]
1164 pop si
1165 pop cx
1166 pop ds
1169 ; cirrus_get_crtc
1170 ;; NOTE - may be called in protected mode
1171 cirrus_get_crtc:
1172 push ds
1173 push ax
1174 mov dx, #0x3cc
1175 in al, dx
1176 and al, #0x01
1177 shl al, #5
1178 mov dx, #0x3b4
1179 add dl, al
1180 pop ax
1181 pop ds
1184 ;; in - al:mode, out - cflag:result, si:table, ax:destroyed
1185 cirrus_get_modeentry:
1186 and al, #0x7f
1187 cirrus_get_modeentry_nomask:
1188 mov si, #_cirrus_modes
1189 cgm_1:
1190 db 0x2e ;; cs:
1191 mov ah, [si]
1192 cmp al, ah
1193 jz cgm_2
1194 cmp ah, #0xff
1195 jz cgm_4
1196 add si, # CIRRUS_MODE_SIZE
1197 jmp cgm_1
1198 cgm_4:
1199 xor si, si
1200 stc ;; video mode is not supported
1201 jmp cgm_3
1202 cgm_2:
1203 clc ;; video mode is supported
1204 cgm_3:
1207 ; get LFB address
1208 ; out - ax:LFB address (high 16 bit)
1209 ;; NOTE - may be called in protected mode
1210 cirrus_get_lfb_addr:
1211 push cx
1212 push dx
1213 push eax
1214 xor cx, cx
1215 mov dl, #0x00
1216 call cirrus_pci_read
1217 cmp ax, #0xffff
1218 jz cirrus_get_lfb_addr_5
1219 cirrus_get_lfb_addr_3:
1220 mov dl, #0x00
1221 call cirrus_pci_read
1222 cmp ax, #0x1013 ;; cirrus
1223 jz cirrus_get_lfb_addr_4
1224 add cx, #0x8
1225 cmp cx, #0x200 ;; search bus #0 and #1
1226 jb cirrus_get_lfb_addr_3
1227 cirrus_get_lfb_addr_5:
1228 xor dx, dx ;; no LFB
1229 jmp cirrus_get_lfb_addr_6
1230 cirrus_get_lfb_addr_4:
1231 mov dl, #0x10 ;; I/O space #0
1232 call cirrus_pci_read
1233 test ax, #0xfff1
1234 jnz cirrus_get_lfb_addr_5
1235 shr eax, #16
1236 mov dx, ax ;; LFB address
1237 cirrus_get_lfb_addr_6:
1238 pop eax
1239 mov ax, dx
1240 pop dx
1241 pop cx
1244 cirrus_pci_read:
1245 mov eax, #0x00800000
1246 mov ax, cx
1247 shl eax, #8
1248 mov al, dl
1249 mov dx, #0xcf8
1250 out dx, eax
1251 add dl, #4
1252 in eax, dx
1255 ;; out - al:bytes per pixel
1256 cirrus_get_bpp_bytes:
1257 push dx
1258 mov dx, #0x03c4
1259 mov al, #0x07
1260 out dx, al
1261 inc dx
1262 in al, dx
1263 and al, #0x0e
1264 cmp al, #0x06
1265 jne cirrus_get_bpp_bytes_1
1266 and al, #0x02
1267 cirrus_get_bpp_bytes_1:
1268 shr al, #1
1269 cmp al, #0x04
1270 je cirrus_get_bpp_bytes_2
1271 inc al
1272 cirrus_get_bpp_bytes_2:
1273 pop dx
1276 ;; in - ax: new line offset
1277 cirrus_set_line_offset:
1278 shr ax, #3
1279 push ax
1280 call cirrus_get_crtc
1281 mov al, #0x13
1282 out dx, al
1283 inc dx
1284 pop ax
1285 out dx, al
1286 dec dx
1287 mov al, #0x1b
1288 out dx, al
1289 inc dx
1290 shl ah, #4
1291 in al, dx
1292 and al, #ef
1293 or al, ah
1294 out dx, al
1297 ;; out - ax: active line offset
1298 cirrus_get_line_offset:
1299 push dx
1300 push bx
1301 call cirrus_get_crtc
1302 mov al, #0x13
1303 out dx, al
1304 inc dx
1305 in al, dx
1306 mov bl, al
1307 dec dx
1308 mov al, #0x1b
1309 out dx, al
1310 inc dx
1311 in al, dx
1312 mov ah, al
1313 shr ah, #4
1314 and ah, #0x01
1315 mov al, bl
1316 shl ax, #3
1317 pop bx
1318 pop dx
1321 ;; in - si: table
1322 ;; out - ax: line offset for mode
1323 cirrus_get_line_offset_entry:
1324 push bx
1325 mov bx, [si+14] ;; crtc table
1326 push bx
1327 offset_loop1:
1328 mov ax, [bx]
1329 cmp al, #0x13
1330 je offset_found1
1331 inc bx
1332 inc bx
1333 jnz offset_loop1
1334 offset_found1:
1335 xor al, al
1336 shr ax, #5
1337 pop bx
1338 push ax
1339 offset_loop2:
1340 mov ax, [bx]
1341 cmp al, #0x1b
1342 je offset_found2
1343 inc bx
1344 inc bx
1345 jnz offset_loop2
1346 offset_found2:
1347 pop bx
1348 and ax, #0x1000
1349 shr ax, #1
1350 or ax, bx
1351 pop bx
1354 ;; in - new address in DX:AX
1355 cirrus_set_start_addr:
1356 push bx
1357 push dx
1358 push ax
1359 call cirrus_get_crtc
1360 mov al, #0x0d
1361 out dx, al
1362 inc dx
1363 pop ax
1364 out dx, al
1365 dec dx
1366 mov al, #0x0c
1367 out dx, al
1368 inc dx
1369 mov al, ah
1370 out dx, al
1371 dec dx
1372 mov al, #0x1d
1373 out dx, al
1374 inc dx
1375 in al, dx
1376 and al, #0x7f
1377 pop bx
1378 mov ah, bl
1379 shl bl, #4
1380 and bl, #0x80
1381 or al, bl
1382 out dx, al
1383 dec dx
1384 mov bl, ah
1385 and ah, #0x01
1386 shl bl, #1
1387 and bl, #0x0c
1388 or ah, bl
1389 mov al, #0x1b
1390 out dx, al
1391 inc dx
1392 in al, dx
1393 and al, #0xf2
1394 or al, ah
1395 out dx, al
1396 pop bx
1399 ;; out - current address in DX:AX
1400 cirrus_get_start_addr:
1401 push bx
1402 call cirrus_get_crtc
1403 mov al, #0x0c
1404 out dx, al
1405 inc dx
1406 in al, dx
1407 mov ah, al
1408 dec dx
1409 mov al, #0x0d
1410 out dx, al
1411 inc dx
1412 in al, dx
1413 push ax
1414 dec dx
1415 mov al, #0x1b
1416 out dx, al
1417 inc dx
1418 in al, dx
1419 dec dx
1420 mov bl, al
1421 and al, #0x01
1422 and bl, #0x0c
1423 shr bl, #1
1424 or bl, al
1425 mov al, #0x1d
1426 out dx, al
1427 inc dx
1428 in al, dx
1429 and al, #0x80
1430 shr al, #4
1431 or bl, al
1432 mov dl, bl
1433 xor dh, dh
1434 pop ax
1435 pop bx
1438 cirrus_extbios_handlers:
1439 ;; 80h
1440 dw cirrus_extbios_80h
1441 dw cirrus_extbios_81h
1442 dw cirrus_extbios_82h
1443 dw cirrus_extbios_unimplemented
1444 ;; 84h
1445 dw cirrus_extbios_unimplemented
1446 dw cirrus_extbios_85h
1447 dw cirrus_extbios_unimplemented
1448 dw cirrus_extbios_unimplemented
1449 ;; 88h
1450 dw cirrus_extbios_unimplemented
1451 dw cirrus_extbios_unimplemented
1452 dw cirrus_extbios_unimplemented
1453 dw cirrus_extbios_unimplemented
1454 ;; 8Ch
1455 dw cirrus_extbios_unimplemented
1456 dw cirrus_extbios_unimplemented
1457 dw cirrus_extbios_unimplemented
1458 dw cirrus_extbios_unimplemented
1459 ;; 90h
1460 dw cirrus_extbios_unimplemented
1461 dw cirrus_extbios_unimplemented
1462 dw cirrus_extbios_unimplemented
1463 dw cirrus_extbios_unimplemented
1464 ;; 94h
1465 dw cirrus_extbios_unimplemented
1466 dw cirrus_extbios_unimplemented
1467 dw cirrus_extbios_unimplemented
1468 dw cirrus_extbios_unimplemented
1469 ;; 98h
1470 dw cirrus_extbios_unimplemented
1471 dw cirrus_extbios_unimplemented
1472 dw cirrus_extbios_9Ah
1473 dw cirrus_extbios_unimplemented
1474 ;; 9Ch
1475 dw cirrus_extbios_unimplemented
1476 dw cirrus_extbios_unimplemented
1477 dw cirrus_extbios_unimplemented
1478 dw cirrus_extbios_unimplemented
1479 ;; A0h
1480 dw cirrus_extbios_A0h
1481 dw cirrus_extbios_A1h
1482 dw cirrus_extbios_A2h
1483 dw cirrus_extbios_unimplemented
1484 ;; A4h
1485 dw cirrus_extbios_unimplemented
1486 dw cirrus_extbios_unimplemented
1487 dw cirrus_extbios_unimplemented
1488 dw cirrus_extbios_unimplemented
1489 ;; A8h
1490 dw cirrus_extbios_unimplemented
1491 dw cirrus_extbios_unimplemented
1492 dw cirrus_extbios_unimplemented
1493 dw cirrus_extbios_unimplemented
1494 ;; ACh
1495 dw cirrus_extbios_unimplemented
1496 dw cirrus_extbios_unimplemented
1497 dw cirrus_extbios_AEh
1498 dw cirrus_extbios_unimplemented
1500 cirrus_vesa_handlers:
1501 ;; 00h
1502 dw cirrus_vesa_00h
1503 dw cirrus_vesa_01h
1504 dw cirrus_vesa_02h
1505 dw cirrus_vesa_03h
1506 ;; 04h
1507 dw cirrus_vesa_unimplemented
1508 dw cirrus_vesa_05h
1509 dw cirrus_vesa_06h
1510 dw cirrus_vesa_07h
1511 ;; 08h
1512 dw cirrus_vesa_unimplemented
1513 dw cirrus_vesa_unimplemented
1514 dw cirrus_vesa_unimplemented
1515 dw cirrus_vesa_unimplemented
1516 ;; 0Ch
1517 dw cirrus_vesa_unimplemented
1518 dw cirrus_vesa_unimplemented
1519 dw cirrus_vesa_unimplemented
1520 dw cirrus_vesa_unimplemented
1524 ASM_END
1526 #ifdef CIRRUS_VESA3_PMINFO
1527 ASM_START
1528 cirrus_vesa_pminfo:
1529 /* + 0 */
1530 .byte 0x50,0x4d,0x49,0x44 ;; signature[4]
1531 /* + 4 */
1532 dw cirrus_vesa_pmbios_entry ;; entry_bios
1533 dw cirrus_vesa_pmbios_init ;; entry_init
1534 /* + 8 */
1535 cirrus_vesa_sel0000_data:
1536 dw 0x0000 ;; sel_00000
1537 cirrus_vesa_selA000_data:
1538 dw 0xA000 ;; sel_A0000
1539 /* +12 */
1540 cirrus_vesa_selB000_data:
1541 dw 0xB000 ;; sel_B0000
1542 cirrus_vesa_selB800_data:
1543 dw 0xB800 ;; sel_B8000
1544 /* +16 */
1545 cirrus_vesa_selC000_data:
1546 dw 0xC000 ;; sel_C0000
1547 cirrus_vesa_is_protected_mode:
1548 ;; protected mode flag and checksum
1549 dw (~((0xf2 + (cirrus_vesa_pmbios_entry >> 8) + (cirrus_vesa_pmbios_entry) \
1550 + (cirrus_vesa_pmbios_init >> 8) + (cirrus_vesa_pmbios_init)) & 0xff) << 8) + 0x01
1551 ASM_END
1552 #endif // CIRRUS_VESA3_PMINFO
1555 #ifdef CIRRUS_DEBUG
1556 static void cirrus_debugmsg(DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS)
1557 Bit16u DI, SI, BP, SP, BX, DX, CX, AX, ES, DS, FLAGS;
1559 if((GET_AH()!=0x0E)&&(GET_AH()!=0x02)&&(GET_AH()!=0x09)&&(AX!=0x4F05))
1560 printf("vgabios call ah%02x al%02x bx%04x cx%04x dx%04x\n",GET_AH(),GET_AL(),BX,CX,DX);
1562 #endif