1 !
2 ! Display adapter & video mode setup, version 2.7 (09-Apr-96)
3 !
4 ! Copyright (C) 1995, 1996 Martin Mares <mj@k332.feld.cvut.cz>
5 ! Based on the original setup.S code (C) Linus Torvalds
6 !
7
8 ! Enable autodetection of SVGA adapters and modes
9 #define CONFIG_VIDEO_SVGA
10
11 ! Enable autodetection of VESA modes
12 #define CONFIG_VIDEO_VESA
13
14 ! Enable compacting of mode table
15 #define CONFIG_VIDEO_COMPACT
16
17 ! Retain screen contents when switching modes
18 #define CONFIG_VIDEO_RETAIN
19
20 ! Enable local mode list
21 #undef CONFIG_VIDEO_LOCAL
22
23 ! This code uses an extended set of video mode numbers. These include:
24 ! Aliases for standard modes
25 ! NORMAL_VGA (-1)
26 ! EXTENDED_VGA (-2)
27 ! ASK_VGA (-3)
28 ! Video modes numbered by menu position -- NOT RECOMMENDED because of lack
29 ! of compatibility when extending the table. These are between 0x00 and 0xff.
30 #define VIDEO_FIRST_MENU 0x0000
31 ! Standard BIOS video modes (BIOS number + 0x0100)
32 #define VIDEO_FIRST_BIOS 0x0100
33 ! VESA BIOS video modes (VESA number + 0x0200)
34 #define VIDEO_FIRST_VESA 0x0200
35 ! Video7 special modes (BIOS number + 0x0900)
36 #define VIDEO_FIRST_V7 0x0900
37 ! Special video modes
38 #define VIDEO_FIRST_SPECIAL 0x0f00
39 #define VIDEO_80x25 0x0f00
40 #define VIDEO_8POINT 0x0f01
41 #define VIDEO_80x43 0x0f02
42 #define VIDEO_80x28 0x0f03
43 #define VIDEO_CURRENT_MODE 0x0f04
44 #define VIDEO_80x30 0x0f05
45 #define VIDEO_80x34 0x0f06
46 #define VIDEO_80x60 0x0f07
47 #define VIDEO_LAST_SPECIAL 0x0f08
48 ! Video modes given by resolution
49 #define VIDEO_FIRST_RESOLUTION 0x1000
50
51 ! The "recalculate timings" flag
52 #define VIDEO_RECALC 0x8000
53
54 ! Positions of various video parameters passed to the kernel
55 #define PARAM_CURSOR_POS 0
56 #define PARAM_VIDEO_PAGE 4
57 #define PARAM_VIDEO_MODE 6
58 #define PARAM_VIDEO_COLS 7
59 #define PARAM_VIDEO_EGA_BX 10
60 #define PARAM_VIDEO_LINES 14
61 #define PARAM_HAVE_VGA 15
62 #define PARAM_FONT_POINTS 16
63
64 ! Define DO_STORE according to CONFIG_VIDEO_RETAIN
65 #ifdef CONFIG_VIDEO_RETAIN
66 #define DO_STORE call store_screen
67 #else
68 #define DO_STORE
69 #endif
70
71 !
72 ! This is the main entry point called by setup.S
73 !
74 ! Input:
75 ! DS pointing to the bootsector
76
77 video: push ds ! We use different segments
78 push ds ! FS contains original DS
79 pop fs
80 push cs ! DS is equal to CS
81 pop ds
82 push cs ! ES is equal to CS
83 pop es
84 xor ax,ax
85 mov gs,ax ! GS is zero
86 cld
87 call basic_detect ! Basic adapter type testing (EGA/VGA/MDA/CGA)
88 seg fs ! User-selected video mode
89 mov ax,[0x01fa]
90 cmp ax,#ASK_VGA ! Bring up the menu
91 jz vid2
92 call mode_set ! Set the mode
93 jc vid1
94 lea si,badmdt ! Invalid mode ID
95 call prtstr
96 vid2: call mode_menu
97 vid1:
98 #ifdef CONFIG_VIDEO_RETAIN
99 call restore_screen ! Restore screen contents
100 #endif
101 call mode_params ! Store mode parameters
102 pop ds ! Restore original DS
103 ret
104
105 !
106 ! Detect if we have CGA, MDA, EGA or VGA and pass it to the kernel.
107 !
108
109 basic_detect:
110 seg fs ! Default is no VGA
111 movb [PARAM_HAVE_VGA],#0
112
113 mov ah,#0x12 ! Check EGA/VGA
114 mov bl,#0x10
115 int 0x10
116 seg fs
117 mov [PARAM_VIDEO_EGA_BX],bx ! Used for identification of EGA in the kernel
118 cmp bl,#0x10 ! No, this is a CGA/MDA/HGA card.
119 je basret
120 incb [adapter]
121
122 mov ax,#0x1a00 ! Check for EGA/VGA discrimination
123 int 0x10
124 cmp al,#0x1a ! 1a means VGA, anything else EGA
125 jne basret
126 seg fs
127 incb [PARAM_HAVE_VGA] ! We've detected a VGA
128 incb [adapter]
129
130 basret: ret
131
132 !
133 ! Store the video mode parameters for later usage by the kernel.
134 ! This is done by asking the BIOS except for the rows/columns
135 ! parameters in the default 80x25 mode -- these are set directly,
136 ! because some very obscure BIOSes supply insane values.
137 !
138
139 mode_params:
140 mov ah,#0x03 ! Read cursor position
141 xor bh,bh
142 int 0x10
143 seg fs
144 mov [PARAM_CURSOR_POS],dx
145
146 mov ah,#0x0f ! Read page/mode/width
147 int 0x10
148 seg fs
149 mov [PARAM_VIDEO_PAGE],bx
150 seg fs
151 mov [PARAM_VIDEO_MODE],ax ! Video mode and screen width
152 cmp al,#7 ! MDA/HGA => segment differs
153 jnz mopar0
154 mov [video_segment],#0xb000
155 mopar0: seg gs ! Font size
156 mov ax,[0x485]
157 seg fs
158 mov [PARAM_FONT_POINTS],ax ! (valid only on EGA/VGA)
159
160 mov ax,[force_size] ! Forced size?
161 or ax,ax
162 jz mopar1
163 seg fs
164 mov [PARAM_VIDEO_COLS],ah
165 seg fs
166 mov [PARAM_VIDEO_LINES],al
167 ret
168
169 mopar1: mov al,#25
170 cmpb [adapter],#0 ! If we are on CGA/MDA/HGA, the screen must
171 jz mopar2 ! have 25 lines.
172 seg gs ! On EGA/VGA, use the EGA+ BIOS variable
173 mov al,[0x484] ! containing maximal line number.
174 inc al
175 mopar2: seg fs
176 movb [PARAM_VIDEO_LINES],al
177 ret
178
179 !
180 ! The video mode menu
181 !
182
183 mode_menu:
184 lea si,keymsg ! "Return/Space/Timeout" message
185 call prtstr
186 call flush
187 nokey: call getkt
188 cmp al,#0x0d ! ENTER ?
189 je listm ! yes - manual mode selection
190 cmp al,#0x20 ! SPACE ?
191 je defmd1 ! no - repeat
192 call beep
193 jmp nokey
194 defmd1: ret ! No mode selected => use the 80x25 default
195
196 listm: call mode_table ! We need a mode table to be listed
197 listm0: lea si,name_bann ! Print adapter name
198 call prtstr
199 mov si,[card_name]
200 or si,si
201 jnz an2
202 mov al,[adapter]
203 lea si,old_name
204 or al,al
205 jz an1
206 lea si,ega_name
207 dec al
208 jz an1
209 lea si,vga_name
210 jmp an1
211 an2: call prtstr
212 lea si,svga_name
213 an1: call prtstr
214 lea si,listhdr ! Table header
215 call prtstr
216 mov dl,#0x30 ! DL holds mode number
217 lea si,modelist
218 lm1: cmp (si),#ASK_VGA ! End?
219 jz lm2
220 mov al,dl ! Menu selection number
221 call prtchr
222 call prtsp2
223 lodsw
224 call prthw ! Mode ID
225 call prtsp2
226 mov al,(si+1)
227 call prtdec ! Rows
228 mov al,#0x78 ! 'x'
229 call prtchr
230 lodsw
231 call prtdec ! Columns
232 mov al,#0x0d ! New line
233 call prtchr
234 mov al,#0x0a
235 call prtchr
236 inc dl ! Next character
237 cmp dl,#0x3a
238 jnz lm1
239 mov dl,#0x61
240 jmp lm1
241
242 lm2: lea si,prompt ! Mode prompt
243 call prtstr
244 lea di,edit_buf ! Editor buffer
245 lm3: call getkey
246 cmp al,#0x0d ! Enter?
247 jz lment
248 cmp al,#0x08 ! Backspace?
249 jz lmbs
250 cmp al,#0x20 ! Printable?
251 jc lm3
252 cmp di,#edit_buf+4 ! Enough space?
253 jz lm3
254 stosb
255 call prtchr
256 jmp lm3
257
258 lmbs: cmp di,#edit_buf ! Backspace
259 jz lm3
260 dec di
261 mov al,#0x08
262 call prtchr
263 call prtspc
264 mov al,#0x08
265 call prtchr
266 jmp lm3
267
268 lment: movb (di),#0
269 lea si,crlft
270 call prtstr
271 lea si,edit_buf
272 cmpb (si),#0 ! Empty string => use default mode
273 jz lmdef
274 cmpb (si+1),#0 ! One character => menu selection
275 jz mnusel
276 cmp (si),#0x6373 ! "scan" => mode scanning
277 jnz lmhx
278 cmp (si+2),#0x6e61
279 jz lmscan
280 lmhx: xor bx,bx ! Else => mode ID in hex
281 lmhex: lodsb
282 or al,al
283 jz lmuse1
284 sub al,#0x30
285 jc lmbad
286 cmp al,#10
287 jc lmhx1
288 sub al,#7
289 and al,#0xdf
290 cmp al,#10
291 jc lmbad
292 cmp al,#16
293 jnc lmbad
294 lmhx1: shl bx,#4
295 or bl,al
296 jmp lmhex
297 lmuse1: mov ax,bx
298 jmp lmuse
299
300 mnusel: lodsb ! Menu selection
301 xor ah,ah
302 sub al,#0x30
303 jc lmbad
304 cmp al,#10
305 jc lmuse
306 cmp al,#0x61-0x30
307 jc lmbad
308 sub al,#0x61-0x30-10
309 cmp al,#36
310 jnc lmbad
311 lmuse: call mode_set
312 jc lmdef
313 lmbad: lea si,unknt
314 call prtstr
315 br lm2
316
317 lmscan: cmpb [adapter],#0 ! Scanning supported only on EGA/VGA
318 jz lmbad
319 mov [mt_end],#0 ! Scanning of modes: done as new autodetection
320 movb [scanning],#1
321 call mode_table
322 br listm0
323
324 lmdef: ret
325
326 !
327 ! Additional parts of mode_set... (relative jumps, you know)
328 !
329
330 setv7: ! Video7 extended modes
331 DO_STORE
332 sub bh,#VIDEO_FIRST_V7>>8
333 mov ax,#0x6f05
334 int 0x10
335 stc
336 ret
337
338 !
339 ! Aliases for backward compatibility.
340 !
341
342 setalias:
343 mov ax,#VIDEO_80x25
344 inc bx
345 jz mode_set
346 mov al,#VIDEO_8POINT-VIDEO_FIRST_SPECIAL
347 inc bx
348 jnz setbad
349
350 ! Fall-thru !
351
352 !
353 ! Setting of user mode (AX=mode ID) => CF=success
354 !
355
356 mode_set:
357 mov bx,ax
358 cmp ah,#0xff
359 jz setalias
360 test ah,#VIDEO_RECALC>>8
361 jnz setrec
362 cmp ah,#VIDEO_FIRST_RESOLUTION>>8
363 jnc setres
364 cmp ah,#VIDEO_FIRST_SPECIAL>>8
365 jz setspc
366 cmp ah,#VIDEO_FIRST_V7>>8
367 jz setv7
368 cmp ah,#VIDEO_FIRST_VESA>>8
369 jnc setvesa
370 or ah,ah
371 jz setmenu
372 dec ah
373 jz setbios
374 setbad: clc
375 movb [do_restore],#0 ! The screen needn't be restored
376 ret
377
378 setvesa:
379 DO_STORE
380 sub bh,#VIDEO_FIRST_VESA>>8
381 mov ax,#0x4f02 ! VESA BIOS mode set call
382 int 0x10
383 cmp ax,#0x004f ! AL=4f if implemented, AH=0 if OK
384 jnz setbad
385 stc
386 ret
387
388 setbios:
389 DO_STORE
390 int 0x10 ! Standard BIOS mode set call
391 push bx
392 mov ah,#0x0f ! Check if really set
393 int 0x10
394 pop bx
395 cmp al,bl
396 jnz setbad
397 stc
398 ret
399
400 setspc: xor bh,bh ! Set special mode
401 cmp bl,#VIDEO_LAST_SPECIAL-VIDEO_FIRST_SPECIAL
402 jnc setbad
403 add bx,bx
404 .word 0xa7ff, spec_inits ! JMP [BX+spec_inits]
405
406 setmenu:
407 push bx ! Set mode chosen from menu
408 call mode_table ! Build the mode table
409 pop ax
410 shl ax,#2
411 add si,ax
412 cmp si,di
413 jnc setbad
414 mov ax,(si) ! Fetch mode ID
415 _m_s: jmp mode_set
416
417 setres:
418 push bx ! Set mode chosen by its resolution
419 call mode_table
420 pop bx
421 xchg bh,bl
422 setr1: lodsw
423 cmp ax,#ASK_VGA ! End of the list?
424 jz setbad
425 lodsw
426 cmp ax,bx
427 jnz setr1
428 mov ax,(si-4) ! Fetch mode ID
429 jmp _m_s
430
431 !
432 ! Recalculate vertical display end registers -- this fixes various
433 ! inconsistencies of extended modes on many adapters. Called when
434 ! the VIDEO_RECALC flag is set in the mode ID.
435 !
436
437 setrec: sub ah,#VIDEO_RECALC>>8 ! Set the base mode
438 call mode_set
439 jnc rct3
440 seg gs ! Font size in pixels
441 mov ax,[0x485]
442 seg gs ! Number of rows
443 mov bl,[0x484]
444 inc bl
445 mul bl ! Number of visible
446 dec ax ! scan lines - 1
447 mov dx,#0x3d4
448 mov bx,ax
449 mov al,#0x12 ! Lower 8 bits
450 mov ah,bl
451 out dx,ax
452 mov al,#0x07 ! Bits 8 and 9 in the overflow register
453 call inidx
454 xchg ah,al
455 and ah,#0xbd
456 shr bh,#1
457 jnc rct1
458 or ah,#0x02
459 rct1: shr bh,#1
460 jnc rct2
461 or ah,#0x40
462 rct2: mov al,#0x07
463 out dx,ax
464 stc
465 rct3: ret
466
467 !
468 ! Table of routines for setting of the special modes.
469 !
470
471 spec_inits:
472 .word set_80x25
473 .word set_8pixel
474 .word set_80x43
475 .word set_80x28
476 .word set_current
477 .word set_80x30
478 .word set_80x34
479 .word set_80x60
480
481 !
482 ! Set the 80x25 mode. If already set, do nothing.
483 !
484
485 set_80x25:
486 mov [force_size],#0x5019 ! Override possibly broken BIOS vars
487 use_80x25:
488 mov ah,#0x0f ! Get current mode ID
489 int 0x10
490 cmp ax,#0x5007 ! Mode 7 (80x25 mono) is the only one available
491 jz st80 ! on CGA/MDA/HGA and is also available on EGAM
492 cmp ax,#0x5003 ! Unknown mode => force 80x25 color
493 jnz force3
494 st80: cmpb [adapter],#0 ! CGA/MDA/HGA => mode 3/7 is always 80x25
495 jz set80
496 seg gs ! This is EGA+ -- beware of 80x50 etc.
497 mov al,[0x0484]
498 or al,al ! Some buggy BIOS'es set 0 rows
499 jz set80
500 cmp al,#24 ! It's hopefully correct
501 jz set80
502 force3: DO_STORE
503 mov ax,#0x0003 ! Forced set
504 int 0x10
505 set80: stc
506 ret
507
508 !
509 ! Set the 80x50/80x43 8-pixel mode. Simple BIOS calls.
510 !
511
512 set_8pixel:
513 DO_STORE
514 call use_80x25 ! The base is 80x25
515 set_8pt:
516 mov ax,#0x1112 ! Use 8x8 font
517 xor bl,bl
518 int 0x10
519 mov ax,#0x1200 ! Use alternate print screen
520 mov bl,#0x20
521 int 0x10
522 mov ax,#0x1201 ! Turn off cursor emulation
523 mov bl,#0x34
524 int 0x10
525 mov ah,#0x01 ! Define cursor (scan lines 6 to 7)
526 mov cx,#0x0607
527 int 0x10
528 set_current:
529 stc
530 ret
531
532 !
533 ! Set the 80x28 mode. This mode works on all VGA's, because it's a standard
534 ! 80x25 mode with 14-point fonts instead of 16-point.
535 !
536
537 set_80x28:
538 DO_STORE
539 call use_80x25 ! The base is 80x25
540 set14: mov ax,#0x1111 ! Use 9x14 font
541 xor bl,bl
542 int 0x10
543 mov ah,#0x01 ! Define cursor (scan lines 11 to 12)
544 mov cx,#0x0b0c
545 int 0x10
546 stc
547 ret
548
549 !
550 ! Set the 80x43 mode. This mode is works on all VGA's.
551 ! It's a 350-scanline mode with 8-pixel font.
552 !
553
554 set_80x43:
555 DO_STORE
556 mov ax,#0x1201 ! Set 350 scans
557 mov bl,#0x30
558 int 0x10
559 mov ax,#0x0003 ! Reset video mode
560 int 0x10
561 jmp set_8pt ! Use 8-pixel font
562
563 !
564 ! Set the 80x30 mode (all VGA's). 480 scanlines, 16-pixel font.
565 !
566
567 set_80x30:
568 call use_80x25 ! Start with real 80x25
569 DO_STORE
570 mov dx,#0x3cc ! Get CRTC port
571 in al,dx
572 mov dl,#0xd4
573 ror al,#1 ! Mono or color?
574 jc set48a
575 mov dl,#0xb4
576 set48a: mov ax,#0x0c11 ! Vertical sync end (also unlocks CR0-7)
577 call outidx
578 mov ax,#0x0b06 ! Vertical total
579 call outidx
580 mov ax,#0x3e07 ! (Vertical) overflow
581 call outidx
582 mov ax,#0xea10 ! Vertical sync start
583 call outidx
584 mov ax,#0xdf12 ! Vertical display end
585 call outidx
586 mov ax,#0xe715 ! Vertical blank start
587 call outidx
588 mov ax,#0x0416 ! Vertical blank end
589 call outidx
590 push dx
591 mov dl,#0xcc ! Misc output register (read)
592 in al,dx
593 mov dl,#0xc2 ! (write)
594 and al,#0x0d ! Preserve clock select bits and color bit
595 or al,#0xe2 ! Set correct sync polarity
596 out dx,al
597 pop dx
598 mov [force_size],#0x501e
599 stc ! That's all.
600 ret
601
602 !
603 ! Set the 80x34 mode (all VGA's). 480 scans, 14-pixel font.
604 !
605
606 set_80x34:
607 call set_80x30 ! Set 480 scans
608 call set14 ! And 14-pt font
609 mov ax,#0xdb12 ! VGA vertical display end
610 mov [force_size],#0x5022
611 setvde: call outidx
612 stc
613 ret
614
615 !
616 ! Set the 80x60 mode (all VGA's). 480 scans, 8-pixel font.
617 !
618
619 set_80x60:
620 call set_80x30 ! Set 480 scans
621 call set_8pt ! And 8-pt font
622 mov ax,#0xdf12 ! VGA vertical display end
623 mov [force_size],#0x503c
624 jmp setvde
625
626 #ifdef CONFIG_VIDEO_RETAIN
627
628 !
629 ! Store screen contents to temporary buffer.
630 !
631
632 store_screen:
633 cmpb [do_restore],#0 ! Already stored?
634 jnz stsr
635 testb [loadflags],#CAN_USE_HEAP ! Have we space for storing?
636 jz stsr
637 push ax
638 push bx
639 push [force_size] ! Don't force specific size
640 mov [force_size],#0
641 call mode_params ! Obtain params of current mode
642 pop [force_size]
643
644 seg fs
645 mov ah,[PARAM_VIDEO_LINES]
646 seg fs
647 mov al,[PARAM_VIDEO_COLS]
648 mov bx,ax ! BX=dimensions
649 mul ah
650 mov cx,ax ! CX=number of characters to store
651 add ax,ax ! Calculate image size
652 add ax,#modelist+1024+4
653 cmp ax,[heap_end_ptr]
654 jnc sts1 ! Unfortunately, out of memory
655
656 seg fs ! Store mode params
657 mov ax,[PARAM_CURSOR_POS]
658 lea di,modelist+1024
659 stosw
660 mov ax,bx
661 stosw
662
663 push ds ! Store the screen
664 mov ds,[video_segment]
665 xor si,si
666 rep
667 movsw
668 pop ds
669 incb [do_restore] ! Screen will be restored later
670 sts1: pop bx
671 pop ax
672 stsr: ret
673
674 !
675 ! Restore screen contents from temporary buffer.
676 !
677
678 restore_screen:
679 cmpb [do_restore],#0 ! Has the screen been stored?
680 jz res1
681 call mode_params ! Get parameters of current mode
682 seg fs
683 mov cl,[PARAM_VIDEO_LINES]
684 seg fs
685 mov ch,[PARAM_VIDEO_COLS]
686 lea si,modelist+1024 ! Screen buffer
687 lodsw ! Set cursor position
688 mov dx,ax
689 cmp dh,cl
690 jc res2
691 mov dh,cl
692 dec dh
693 res2: cmp dl,ch
694 jc res3
695 mov dl,ch
696 dec dl
697 res3: mov ah,#0x02
698 mov bh,#0x00
699 int 0x10
700 lodsw ! Display size
701 mov dl,ah ! DL=number of lines
702 mov ah,#0 ! BX=physical length of orig. line
703 mov bx,ax
704 cmp dl,cl ! Too many?
705 jc res4
706 push ax
707 mov al,dl
708 sub al,cl
709 mul bl
710 add si,ax
711 add si,ax
712 pop ax
713 mov dl,cl
714 res4: cmp al,ch ! Too wide?
715 jc res5
716 mov al,ch ! AX=width of src. line
717 res5: mov cl,#0
718 xchg cl,ch
719 mov bp,cx ! BP=width of dest. line
720 push es
721 mov es,[video_segment]
722 xor di,di ! Move the data
723 add bx,bx ! Convert BX and BP to _bytes_
724 add bp,bp
725 res6: push si
726 push di
727 mov cx,ax
728 rep
729 movsw
730 pop di
731 pop si
732 add di,bp
733 add si,bx
734 dec dl
735 jnz res6
736 pop es ! Done
737 res1: ret
738
739 #endif
740
741 !
742 ! Build the table of video modes (stored after the setup.S code at the
743 ! `modelist' label. Each video mode record looks like:
744 ! .word MODE-ID (our special mode ID (see above))
745 ! .byte rows (number of rows)
746 ! .byte columns (number of columns)
747 ! Returns address of the end of the table in DI, the end is marked
748 ! with a ASK_VGA ID.
749 !
750
751 mode_table:
752 mov di,[mt_end] ! Already filled?
753 or di,di
754 jnz mtab1x
755 lea di,modelist ! Store standard modes:
756
757 mov eax,#VIDEO_80x25 + 0x50190000 ! The 80x25 mode (ALL)
758 stosd
759 mov al,[adapter] ! CGA/MDA/HGA -- no more modes
760 or al,al
761 jz mtabe
762 dec al
763 jnz mtabv
764 mov eax,#VIDEO_8POINT + 0x502b0000 ! The 80x43 EGA mode
765 stosd
766 jmp mtabe
767 mtab1x: jmp mtab1
768
769 mtabv: lea si,vga_modes ! All modes for std VGA
770 mov cx,#12
771 rep
772 movsw
773
774 cmpb [scanning],#0 ! Mode scan requested?
775 jz mscan1
776 call mode_scan
777 mscan1:
778
779 #ifdef CONFIG_VIDEO_LOCAL
780 call local_modes
781 #endif
782 #ifdef CONFIG_VIDEO_VESA
783 call vesa_modes ! Detect VESA VGA modes
784 #endif
785 #ifdef CONFIG_VIDEO_SVGA
786 cmpb [scanning],#0 ! Bypass when scanning
787 jnz mscan2
788 call svga_modes ! Detect SVGA cards & modes
789 mscan2:
790 #endif
791
792 mtabe:
793
794 #ifdef CONFIG_VIDEO_COMPACT
795 lea si,modelist ! Compact video mode list if requested.
796 mov dx,di
797 mov di,si
798 cmt1: cmp si,dx ! Scan all modes
799 jz cmt2
800 lea bx,modelist ! Find in previous entries
801 mov cx,(si+2)
802 cmt3: cmp si,bx
803 jz cmt4
804 cmp cx,(bx+2) ! Found => don't copy this entry
805 jz cmt5
806 add bx,#4
807 jmp cmt3
808
809 cmt4: movsd ! Copy entry
810 jmp cmt1
811
812 cmt5: add si,#4 ! Skip entry
813 jmp cmt1
814
815 cmt2:
816 #endif
817
818 mov (di),#ASK_VGA ! End marker
819 mov [mt_end],di
820 mtab1: lea si,modelist ! Returning: SI=mode list, DI=list end
821 ret0: ret
822
823 ! Modes usable on all standard VGAs
824
825 vga_modes:
826 .word VIDEO_8POINT
827 .word 0x5032 ! 80x50
828 .word VIDEO_80x43
829 .word 0x502b ! 80x43
830 .word VIDEO_80x28
831 .word 0x501c ! 80x28
832 .word VIDEO_80x30
833 .word 0x501e ! 80x30
834 .word VIDEO_80x34
835 .word 0x5022 ! 80x34
836 .word VIDEO_80x60
837 .word 0x503c ! 80x60
838
839 !
840 ! Detect VESA modes.
841 !
842
843 #ifdef CONFIG_VIDEO_VESA
844
845 vesa_modes:
846 cmpb [adapter],#2 ! VGA only
847 jnz ret0
848 mov bp,di ! BP=original mode table end
849 add di,#0x200 ! Buffer space
850 mov ax,#0x4f00 ! VESA Get card info call
851 int #0x10
852 mov di,bp
853 cmp ax,#0x004f ! Successful?
854 jnz ret0
855 cmp (di+0x200),#0x4556
856 jnz ret0
857 cmp (di+0x202),#0x4153
858 jnz ret0
859 mov [card_name],#vesa_name ! Set name to "VESA VGA"
860 push gs
861 lgs si,(di+0x20e) ! GS:SI=mode list
862 mov cx,#128 ! Iteration limit
863 vesa1: seg gs ! Get next mode in the list
864 lodsw
865 cmp ax,#0xffff ! End of the table?
866 jz vesar
867 cmp ax,#0x0080 ! Check validity of mode ID
868 jc vesa2
869 or ah,ah ! Valid ID's are 0x0000-0x007f
870 jz vesae ! and 0x0100-0x07ff.
871 cmp ax,#0x0800
872 jnc vesae
873 vesa2: push cx
874 mov cx,ax ! Get mode information structure
875 mov ax,#0x4f01
876 int 0x10
877 mov bx,cx ! BX=mode number
878 add bh,#VIDEO_FIRST_VESA>>8
879 pop cx
880 cmp ax,#0x004f
881 jnz vesan ! Don't report errors (buggy BIOSES :-[ )
882 mov al,(di) ! Check capabilities. We require
883 and al,#0x19 ! a color text mode.
884 cmp al,#0x09
885 jnz vesan
886 cmp (di+8),#0xb800 ! Standard video memory address required
887 jnz vesan
888 testb (di),#2 ! Mode characteristics supplied?
889 mov (di),bx ! Store mode number
890 jz vesa3
891 xor dx,dx
892 mov bx,(di+0x12) ! Width
893 or bh,bh
894 jnz vesan
895 mov (di+3),bl
896 mov ax,(di+0x14) ! Height
897 or ah,ah
898 jnz vesan
899 mov (di+2),al
900 mul bl
901 cmp ax,#8193 ! Small enough for Linux console driver?
902 jnc vesan
903 jmp vesaok
904
905 vesa3: sub bx,#0x8108 ! This mode has no detailed info specified,
906 jc vesan ! so it must be a standard VESA mode.
907 cmp bx,#5
908 jnc vesan
909 mov ax,(bx+vesa_text_mode_table)
910 mov (di+2),ax
911 vesaok: add di,#4 ! The mode is valid. Store it.
912 vesan: loop vesa1 ! Next mode. Limit exceeded => error
913 vesae: lea si,vesaer
914 call prtstr
915 mov di,bp ! Discard already found modes.
916 vesar: pop gs
917 ret
918
919 !
920 ! Dimensions of standard VESA text modes
921 !
922
923 vesa_text_mode_table:
924 db 60, 80 ! 0108
925 db 25, 132 ! 0109
926 db 43, 132 ! 010A
927 db 50, 132 ! 010B
928 db 60, 132 ! 010C
929
930 #endif
931
932 !
933 ! Scan for video modes. A bit dirty, but should work.
934 !
935
936 mode_scan:
937 mov cx,#0x0100 ! Start with mode 0
938 scm1: mov ah,#0 ! Test the mode
939 mov al,cl
940 int 0x10
941 mov ah,#0x0f
942 int 0x10
943 cmp al,cl
944 jnz scm2 ! Mode not set
945 mov dx,#0x3c0 ! Test if it's a text mode
946 mov al,#0x10 ! Mode bits
947 call inidx
948 and al,#0x03
949 jnz scm2
950 mov dx,#0x3d4 ! Cursor location
951 mov al,#0x0f
952 call inidx
953 or al,al
954 jnz scm2
955 mov ax,cx ! OK, store the mode
956 stosw
957 seg gs ! Number of rows
958 mov al,[0x484]
959 inc al
960 stosb
961 seg gs ! Number of columns
962 mov ax,[0x44a]
963 stosb
964 scm2: inc cl
965 jns scm1
966 mov ax,#0x0003 ! Return back to mode 3
967 int 0x10
968 ret
969
970 tstidx: out dx,ax ! OUT DX,AX and inidx
971 inidx: out dx,al ! Read from indexed VGA register
972 inc dx ! AL=index, DX=index reg port -> AL=data
973 in al,dx
974 dec dx
975 ret
976
977 !
978 ! Try to detect type of SVGA card and supply (usually approximate) video
979 ! mode table for it.
980 !
981
982 #ifdef CONFIG_VIDEO_SVGA
983
984 svga_modes:
985 lea si,svga_table ! Test all known SVGA adapters
986 dosvga: lodsw
987 mov bp,ax ! Default mode table
988 or ax,ax
989 jz didsv1
990 lodsw ! Pointer to test routine
991 push si
992 push di
993 push es
994 mov bx,#0xc000
995 mov es,bx
996 call ax ! Call test routine
997 pop es
998 pop di
999 pop si
1000 or bp,bp
1001 jz dosvga
1002 mov si,bp ! Found, copy the modes
1003 mov ah,[svga_prefix]
1004 cpsvga: lodsb
1005 or al,al
1006 jz didsv
1007 stosw
1008 movsw
1009 jmp cpsvga
1010
1011 didsv: mov [card_name],si ! Store pointer to card name
1012 didsv1: ret
1013
1014 !
1015 ! Table of all known SVGA cards. For each card, we store a pointer to
1016 ! a table of video modes supported by the card and a pointer to a routine
1017 ! used for testing of presence of the card. The video mode table is always
1018 ! followed by the name of the card or the chipset.
1019 !
1020
1021 svga_table:
1022 .word ati_md, ati_test
1023 .word oak_md, oak_test
1024 .word paradise_md, paradise_test
1025 .word realtek_md, realtek_test
1026 .word s3_md, s3_test
1027 .word chips_md, chips_test
1028 .word video7_md, video7_test
1029 .word cirrus5_md, cirrus5_test
1030 .word cirrus6_md, cirrus6_test
1031 .word cirrus1_md, cirrus1_test
1032 .word ahead_md, ahead_test
1033 .word everex_md, everex_test
1034 .word genoa_md, genoa_test
1035 .word trident_md, trident_test
1036 .word tseng_md, tseng_test
1037 .word 0
1038
1039 !
1040 ! Test routines and mode tables:
1041 !
1042
1043 ! S3 - The test algorithm was taken from the SuperProbe package
1044 ! for XFree86 1.2.1. Report bugs to Christoph.Niemann@linux.org
1045
1046 s3_test:
1047 mov cx,#0x0f35 ! we store some constants in cl/ch
1048 mov dx,#0x03d4
1049 movb al,#0x38
1050 call inidx
1051 mov bh,al ! store current value of CRT-register 0x38
1052 mov ax,#0x0038
1053 call outidx ! disable writing to special regs
1054 movb al,cl ! check whether we can write special reg 0x35
1055 call inidx
1056 movb bl,al ! save the current value of CRT reg 0x35
1057 andb al,#0xf0 ! clear bits 0-3
1058 movb ah,al
1059 movb al,cl ! and write it to CRT reg 0x35
1060 call outidx
1061 call inidx ! now read it back
1062 andb al,ch ! clear the upper 4 bits
1063 jz s3_2 ! the first test failed. But we have a
1064 movb ah,bl ! second chance
1065 mov al,cl
1066 call outidx
1067 jmp s3_1 ! do the other tests
1068 s3_2: mov ax,cx ! load ah with 0xf and al with 0x35
1069 orb ah,bl ! set the upper 4 bits of ah with the orig value
1070 call outidx ! write ...
1071 call inidx ! ... and reread
1072 andb al,cl ! turn off the upper 4 bits
1073 push ax
1074 movb ah,bl ! restore old value in register 0x35
1075 movb al,cl
1076 call outidx
1077 pop ax
1078 cmp al,ch ! setting lower 4 bits was successful => bad
1079 je no_s3 ! writing is allowed => this is not an S3
1080 s3_1: mov ax,#0x4838 ! allow writing to special regs by putting
1081 call outidx ! magic number into CRT-register 0x38
1082 movb al,cl ! check whether we can write special reg 0x35
1083 call inidx
1084 movb bl,al
1085 andb al,#0xf0
1086 movb ah,al
1087 movb al,cl
1088 call outidx
1089 call inidx
1090 andb al,ch
1091 jnz no_s3 ! no, we can't write => no S3
1092 mov ax,cx
1093 orb ah,bl
1094 call outidx
1095 call inidx
1096 andb al,ch
1097 push ax
1098 movb ah,bl ! restore old value in register 0x35
1099 movb al,cl
1100 call outidx
1101 pop ax
1102 cmp al,ch
1103 jne no_s31 ! writing not possible => no S3
1104 movb al,#0x30
1105 call inidx ! now get the S3 id ...
1106 lea di,idS3
1107 mov cx,#0x10
1108 repne
1109 scasb
1110 je no_s31
1111 movb ah,bh
1112 movb al,#0x38
1113 jmp s3rest
1114 no_s3: movb al,#0x35 ! restore CRT register 0x35
1115 movb ah,bl
1116 call outidx
1117 no_s31: xor bp,bp ! Detection failed
1118 s3rest: movb ah,bh
1119 movb al,#0x38 ! restore old value of CRT register 0x38
1120 outidx: out dx,al ! Write to indexed VGA register
1121 push ax ! AL=index, AH=data, DX=index reg port
1122 mov al,ah
1123 inc dx
1124 out dx,al
1125 dec dx
1126 pop ax
1127 ret
1128
1129 idS3: .byte 0x81, 0x82, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95
1130 .byte 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa8, 0xb0
1131
1132 s3_md: .byte 0x54, 0x2b, 0x84
1133 .byte 0x55, 0x19, 0x84
1134 .byte 0
1135 .ascii "S3"
1136 .byte 0
1137
1138 ! ATI cards.
1139
1140 ati_test:
1141 lea si,idati
1142 mov di,#0x31
1143 mov cx,#0x09
1144 repe
1145 cmpsb
1146 je atiok
1147 xor bp,bp
1148 atiok: ret
1149
1150 idati: .ascii "761295520"
1151
1152 ati_md: .byte 0x23, 0x19, 0x84
1153 .byte 0x33, 0x2c, 0x84
1154 .byte 0x22, 0x1e, 0x64
1155 .byte 0x21, 0x19, 0x64
1156 .byte 0x58, 0x21, 0x50
1157 .byte 0x5b, 0x1e, 0x50
1158 .byte 0
1159 .ascii "ATI"
1160 .byte 0
1161
1162 ! AHEAD
1163
1164 ahead_test:
1165 mov ax,#0x200f
1166 mov dx,#0x3ce
1167 out dx,ax
1168 inc dx
1169 in al,dx
1170 cmp al,#0x20
1171 je isahed
1172 cmp al,#0x21
1173 je isahed
1174 xor bp,bp
1175 isahed: ret
1176
1177 ahead_md:
1178 .byte 0x22, 0x2c, 0x84
1179 .byte 0x23, 0x19, 0x84
1180 .byte 0x24, 0x1c, 0x84
1181 .byte 0x2f, 0x32, 0xa0
1182 .byte 0x32, 0x22, 0x50
1183 .byte 0x34, 0x42, 0x50
1184 .byte 0
1185 .ascii "Ahead"
1186 .byte 0
1187
1188 ! Chips & Tech.
1189
1190 chips_test:
1191 mov dx,#0x3c3
1192 in al,dx
1193 or al,#0x10
1194 out dx,al
1195 mov dx,#0x104
1196 in al,dx
1197 mov bl,al
1198 mov dx,#0x3c3
1199 in al,dx
1200 and al,#0xef
1201 out dx,al
1202 cmp bl,#0xa5
1203 je cantok
1204 xor bp,bp
1205 cantok: ret
1206
1207 chips_md:
1208 .byte 0x60, 0x19, 0x84
1209 .byte 0x61, 0x32, 0x84
1210 .byte 0
1211 .ascii "Chips & Technologies"
1212 .byte 0
1213
1214 ! Cirrus Logic 5X0
1215
1216 cirrus1_test:
1217 mov dx,#0x3d4
1218 mov al,#0x0c
1219 out dx,al
1220 inc dx
1221 in al,dx
1222 mov bl,al
1223 xor al,al
1224 out dx,al
1225 dec dx
1226 mov al,#0x1f
1227 out dx,al
1228 inc dx
1229 in al,dx
1230 mov bh,al
1231 xor ah,ah
1232 shl al,#4
1233 mov cx,ax
1234 mov al,bh
1235 shr al,#4
1236 add cx,ax
1237 shl cx,#8
1238 add cx,#6
1239 mov ax,cx
1240 mov dx,#0x3c4
1241 out dx,ax
1242 inc dx
1243 in al,dx
1244 and al,al
1245 jnz nocirr
1246 mov al,bh
1247 out dx,al
1248 in al,dx
1249 cmp al,#0x01
1250 je iscirr
1251 nocirr: xor bp,bp
1252 iscirr: mov dx,#0x3d4
1253 mov al,bl
1254 xor ah,ah
1255 shl ax,#8
1256 add ax,#0x0c
1257 out dx,ax
1258 ret
1259
1260 cirrus1_md:
1261 .byte 0x1f, 0x19, 0x84
1262 .byte 0x20, 0x2c, 0x84
1263 .byte 0x22, 0x1e, 0x84
1264 .byte 0x31, 0x25, 0x64
1265 .byte 0
1266 .ascii "Cirrus Logic 5X0"
1267 .byte 0
1268
1269 ! Cirrus Logic 54XX
1270
1271 cirrus5_test:
1272 mov dx,#0x3c4
1273 mov al,#6
1274 call inidx
1275 mov bl,al ! BL=backup
1276 mov ax,#6
1277 call tstidx
1278 cmp al,#0x0f
1279 jne c5fail
1280 mov ax,#0x1206
1281 call tstidx
1282 cmp al,#0x12
1283 jne c5fail
1284 mov al,#0x1e
1285 call inidx
1286 mov bh,al
1287 mov ah,bh
1288 and ah,#0xc0
1289 mov al,#0x1e
1290 call tstidx
1291 and al,#0x3f
1292 jne c5xx
1293 mov al,#0x1e
1294 mov ah,bh
1295 or ah,#0x3f
1296 call tstidx
1297 xor al,#0x3f
1298 and al,#0x3f
1299 c5xx: pushf
1300 mov al,#0x1e
1301 mov ah,bh
1302 out dx,ax
1303 popf
1304 je c5done
1305 c5fail: xor bp,bp
1306 c5done: mov al,#6
1307 mov ah,bl
1308 out dx,ax
1309 ret
1310
1311 cirrus5_md:
1312 .byte 0x14, 0x19, 0x84
1313 .byte 0x54, 0x2b, 0x84
1314 .byte 0
1315 .ascii "Cirrus Logic 54XX"
1316 .byte 0
1317
1318 ! Cirrus Logic 64XX -- no known extra modes, but must be identified, because
1319 ! it's misidentified by the Ahead test.
1320
1321 cirrus6_test:
1322 mov dx,#0x3ce
1323 mov al,#0x0a
1324 call inidx
1325 mov bl,al ! BL=backup
1326 mov ax,#0xce0a
1327 call tstidx
1328 or al,al
1329 jne c2fail
1330 mov ax,#0xec0a
1331 call tstidx
1332 cmp al,#0x01
1333 jne c2fail
1334 mov al,#0xaa
1335 call inidx ! 4X, 5X, 7X and 8X are valid 64XX chip ID's
1336 shr al,#4
1337 sub al,#4
1338 jz c6done
1339 dec al
1340 jz c6done
1341 sub al,#2
1342 jz c6done
1343 dec al
1344 jz c6done
1345 c2fail: xor bp,bp
1346 c6done: mov al,#0x0a
1347 mov ah,bl
1348 out dx,ax
1349 ret
1350
1351 cirrus6_md:
1352 .byte 0
1353 .ascii "Cirrus Logic 64XX"
1354 .byte 0
1355
1356 ! Everex / Trident
1357
1358 everex_test:
1359 mov ax,#0x7000
1360 xor bx,bx
1361 int 0x10
1362 cmp al,#0x70
1363 jne noevrx
1364 shr dx,#4
1365 cmp dx,#0x678
1366 je evtrid
1367 cmp dx,#0x236
1368 jne evrxok
1369 evtrid: lea bp,trident_md
1370 evrxok: ret
1371
1372 noevrx: xor bp,bp
1373 ret
1374
1375 everex_md:
1376 .byte 0x03, 0x22, 0x50
1377 .byte 0x04, 0x3c, 0x50
1378 .byte 0x07, 0x2b, 0x64
1379 .byte 0x08, 0x4b, 0x64
1380 .byte 0x0a, 0x19, 0x84
1381 .byte 0x0b, 0x2c, 0x84
1382 .byte 0x16, 0x1e, 0x50
1383 .byte 0x18, 0x1b, 0x64
1384 .byte 0x21, 0x40, 0xa0
1385 .byte 0x40, 0x1e, 0x84
1386 .byte 0
1387 .ascii "Everex/Trident"
1388 .byte 0
1389
1390 ! Genoa.
1391
1392 genoa_test:
1393 lea si,idgenoa ! Check Genoa 'clues'
1394 xor ax,ax
1395 seg es
1396 mov al,[0x37]
1397 mov di,ax
1398 mov cx,#0x04
1399 dec si
1400 dec di
1401 l1: inc si
1402 inc di
1403 mov al,(si)
1404 test al,al
1405 jz l2
1406 seg es
1407 cmp al,(di)
1408 l2: loope l1
1409 or cx,cx
1410 je isgen
1411 xor bp,bp
1412 isgen: ret
1413
1414 idgenoa: .byte 0x77, 0x00, 0x99, 0x66
1415
1416 genoa_md:
1417 .byte 0x58, 0x20, 0x50
1418 .byte 0x5a, 0x2a, 0x64
1419 .byte 0x60, 0x19, 0x84
1420 .byte 0x61, 0x1d, 0x84
1421 .byte 0x62, 0x20, 0x84
1422 .byte 0x63, 0x2c, 0x84
1423 .byte 0x64, 0x3c, 0x84
1424 .byte 0x6b, 0x4f, 0x64
1425 .byte 0x72, 0x3c, 0x50
1426 .byte 0x74, 0x42, 0x50
1427 .byte 0x78, 0x4b, 0x64
1428 .byte 0
1429 .ascii "Genoa"
1430 .byte 0
1431
1432 ! OAK
1433
1434 oak_test:
1435 lea si,idoakvga
1436 mov di,#0x08
1437 mov cx,#0x08
1438 repe
1439 cmpsb
1440 je isoak
1441 xor bp,bp
1442 isoak: ret
1443
1444 idoakvga: .ascii "OAK VGA "
1445
1446 oak_md: .byte 0x4e, 0x3c, 0x50
1447 .byte 0x4f, 0x3c, 0x84
1448 .byte 0x50, 0x19, 0x84
1449 .byte 0x51, 0x2b, 0x84
1450 .byte 0
1451 .ascii "OAK"
1452 .byte 0
1453
1454 ! WD Paradise.
1455
1456 paradise_test:
1457 lea si,idparadise
1458 mov di,#0x7d
1459 mov cx,#0x04
1460 repe
1461 cmpsb
1462 je ispara
1463 xor bp,bp
1464 ispara: ret
1465
1466 idparadise: .ascii "VGA="
1467
1468 paradise_md:
1469 .byte 0x41, 0x22, 0x50
1470 .byte 0x47, 0x1c, 0x84
1471 .byte 0x55, 0x19, 0x84
1472 .byte 0x54, 0x2c, 0x84
1473 .byte 0
1474 .ascii "Paradise"
1475 .byte 0
1476
1477 ! Trident.
1478
1479 trident_test:
1480 mov dx,#0x3c4
1481 mov al,#0x0e
1482 out dx,al
1483 inc dx
1484 in al,dx
1485 xchg ah,al
1486 xor al,al
1487 out dx,al
1488 in al,dx
1489 xchg al,ah
1490 mov bl,al ! Strange thing ... in the book this wasn't
1491 and bl,#0x02 ! necessary but it worked on my card which
1492 jz setb2 ! is a trident. Without it the screen goes
1493 and al,#0xfd ! blurred ...
1494 jmp clrb2 !
1495 setb2: or al,#0x02 !
1496 clrb2: out dx,al
1497 and ah,#0x0f
1498 cmp ah,#0x02
1499 je istrid
1500 xor bp,bp
1501 istrid: ret
1502
1503 trident_md:
1504 .byte 0x50, 0x1e, 0x50
1505 .byte 0x51, 0x2b, 0x50
1506 .byte 0x52, 0x3c, 0x50
1507 .byte 0x57, 0x19, 0x84
1508 .byte 0x58, 0x1e, 0x84
1509 .byte 0x59, 0x2b, 0x84
1510 .byte 0x5a, 0x3c, 0x84
1511 .byte 0
1512 .ascii "Trident"
1513 .byte 0
1514
1515 ! Tseng.
1516
1517 tseng_test:
1518 mov dx,#0x3cd
1519 in al,dx ! Could things be this simple ! :-)
1520 mov bl,al
1521 mov al,#0x55
1522 out dx,al
1523 in al,dx
1524 mov ah,al
1525 mov al,bl
1526 out dx,al
1527 cmp ah,#0x55
1528 je istsen
1529 isnot: xor bp,bp
1530 istsen: ret
1531
1532 tseng_md:
1533 .byte 0x26, 0x3c, 0x50
1534 .byte 0x2a, 0x28, 0x64
1535 .byte 0x23, 0x19, 0x84
1536 .byte 0x24, 0x1c, 0x84
1537 .byte 0x22, 0x2c, 0x84
1538 .byte 0x21, 0x3c, 0x84
1539 .byte 0
1540 .ascii "Tseng"
1541 .byte 0
1542
1543 ! Video7.
1544
1545 video7_test:
1546 mov dx,#0x3cc
1547 in al,dx
1548 mov dx,#0x3b4
1549 and al,#0x01
1550 jz even7
1551 mov dx,#0x3d4
1552 even7: mov al,#0x0c
1553 out dx,al
1554 inc dx
1555 in al,dx
1556 mov bl,al
1557 mov al,#0x55
1558 out dx,al
1559 in al,dx
1560 dec dx
1561 mov al,#0x1f
1562 out dx,al
1563 inc dx
1564 in al,dx
1565 mov bh,al
1566 dec dx
1567 mov al,#0x0c
1568 out dx,al
1569 inc dx
1570 mov al,bl
1571 out dx,al
1572 mov al,#0x55
1573 xor al,#0xea
1574 cmp al,bh
1575 jne isnot
1576 movb [svga_prefix],#VIDEO_FIRST_V7>>8 ! Use special mode switching
1577 ret
1578
1579 video7_md:
1580 .byte 0x40, 0x2b, 0x50
1581 .byte 0x43, 0x3c, 0x50
1582 .byte 0x44, 0x3c, 0x64
1583 .byte 0x41, 0x19, 0x84
1584 .byte 0x42, 0x2c, 0x84
1585 .byte 0x45, 0x1c, 0x84
1586 .byte 0
1587 .ascii "Video 7"
1588 .byte 0
1589
1590 ! Realtek VGA
1591
1592 realtek_test:
1593 lea si,idrtvga
1594 mov di,#0x45
1595 mov cx,#0x0b
1596 repe
1597 cmpsb
1598 je isrt
1599 xor bp,bp
1600 isrt: ret
1601
1602 idrtvga: .ascii "REALTEK VGA"
1603
1604 realtek_md:
1605 .byte 0x1a, 0x3c, 0x50
1606 .byte 0x1b, 0x19, 0x84
1607 .byte 0x1c, 0x1e, 0x84
1608 .byte 0x1d, 0x2b, 0x84
1609 .byte 0x1e, 0x3c, 0x84
1610 .byte 0
1611 .ascii "REALTEK"
1612 .byte 0
1613
1614 #endif
1615
1616 !
1617 ! User-defined local mode table (VGA only)
1618 !
1619
1620 #ifdef CONFIG_VIDEO_LOCAL
1621
1622 local_modes:
1623 lea si,local_mode_table
1624 locm1: lodsw
1625 or ax,ax
1626 jz locm2
1627 stosw
1628 movsw
1629 jmp locm1
1630 locm2: ret
1631
1632 ! This is the table of local video modes which can be supplied manually
1633 ! by the user. Each entry consists of mode ID (word) and dimensions
1634 ! (byte for column count and another byte for row count). These modes
1635 ! are placed before all SVGA and VESA modes and override them if table
1636 ! compacting is enabled. The table must end with a zero word followed
1637 ! by NUL-terminated video adapter name.
1638
1639 local_mode_table:
1640 .word 0x0100 ! Example: 40x25
1641 .byte 25,40
1642 .word 0
1643 .ascii "Local"
1644 .byte 0
1645
1646 #endif
1647
1648 !
1649 ! Read a key and return the ASCII code in al, scan code in ah
1650 !
1651
1652 getkey: xor ah,ah
1653 int 0x16
1654 ret
1655
1656 !
1657 ! Read a key with a timeout of 30 seconds. The hardware clock is used to get
1658 ! the time.
1659 !
1660
1661 getkt: call gettime
1662 add al,#30 ! Wait 30 seconds
1663 cmp al,#60
1664 jl lminute
1665 sub al,#60
1666 lminute:
1667 mov cl,al
1668 again: mov ah,#0x01
1669 int 0x16
1670 jnz getkey ! key pressed, so get it
1671 call gettime
1672 cmp al,cl
1673 jne again
1674 mov al,#0x20 ! timeout, return default char `space'
1675 ret
1676
1677 !
1678 ! Flush the keyboard buffer
1679 !
1680
1681 flush: mov ah,#0x01
1682 int 0x16
1683 jz empty
1684 xor ah,ah
1685 int 0x16
1686 jmp flush
1687 empty: ret
1688
1689 !
1690 ! Print hexadecimal number.
1691 !
1692
1693 prthw: push ax
1694 mov al,ah
1695 call prthb
1696 pop ax
1697 prthb: push ax
1698 shr al,#4
1699 call prthn
1700 pop ax
1701 and al,#0x0f
1702 prthn: cmp al,#0x0a
1703 jc prth1
1704 add al,#0x07
1705 prth1: add al,#0x30
1706 br prtchr
1707
1708 !
1709 ! Print decimal number (AL).
1710 !
1711
1712 prtdec: push ax
1713 push cx
1714 xor ah,ah ! Clear ah
1715 mov cl,#0x0a
1716 idiv cl
1717 cmp al,#0x09
1718 jbe lt100
1719 call prtdec
1720 jmp skip10
1721 lt100: add al,#0x30
1722 call prtchr
1723 skip10: mov al,ah
1724 add al,#0x30
1725 call prtchr
1726 pop cx
1727 pop ax
1728 ret
1729
1730 ! Variables:
1731
1732 adapter: .byte 0 ! Video adapter: 0=CGA/MDA/HGA,1=EGA,2=VGA
1733 mt_end: .word 0 ! End of video mode table if built
1734 edit_buf: .space 6 ! Line editor buffer
1735 card_name: .word 0 ! Pointer to adapter name
1736 scanning: .byte 0 ! Performing mode scan
1737 do_restore: .byte 0 ! Screen contents altered during mode change
1738 svga_prefix: .byte VIDEO_FIRST_BIOS>>8 ! Default prefix for BIOS modes
1739 video_segment: .word 0xb800 ! Video memory segment
1740 force_size: .word 0 ! Use this size instead of the one in BIOS vars
1741
1742 ! Messages:
1743
1744 keymsg: .ascii "Press <RETURN> to see video modes available, "
1745 .ascii "<SPACE> to continue or wait 30 secs"
1746 db 0x0d, 0x0a, 0
1747 listhdr: db 0x0d, 0x0a
1748 .ascii "Mode: COLSxROWS:"
1749 crlft: db 0x0d, 0x0a, 0
1750 prompt: db 0x0d, 0x0a
1751 .ascii "Enter mode number: "
1752 db 0
1753 unknt: .ascii "Unknown mode ID. Try again."
1754 db 0
1755 badmdt: .ascii "You passed an undefined mode number to setup."
1756 db 0x0d, 0x0a, 0
1757 vesaer: .ascii "Error: Scanning of VESA modes failed. Please "
1758 .ascii "report to <mj@k332.feld.cvut.cz>."
1759 db 0x0d, 0x0a, 0
1760 old_name: .ascii "CGA/MDA/HGA"
1761 db 0
1762 ega_name: .ascii "EGA"
1763 db 0
1764 svga_name: .ascii " "
1765 vga_name: .ascii "VGA"
1766 db 0
1767 vesa_name: .ascii "VESA"
1768 db 0
1769 name_bann: .ascii "Video adapter: "
1770 db 0