1 !
2 ! Display adapter & video mode setup, version 2.8 (14-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 ! Write to indexed VGA register (AL=index, AH=data, DX=index reg. port)
743 !
744
745 outidx: out dx,al
746 push ax
747 mov al,ah
748 inc dx
749 out dx,al
750 dec dx
751 pop ax
752 ret
753
754 !
755 ! Build the table of video modes (stored after the setup.S code at the
756 ! `modelist' label. Each video mode record looks like:
757 ! .word MODE-ID (our special mode ID (see above))
758 ! .byte rows (number of rows)
759 ! .byte columns (number of columns)
760 ! Returns address of the end of the table in DI, the end is marked
761 ! with a ASK_VGA ID.
762 !
763
764 mode_table:
765 mov di,[mt_end] ! Already filled?
766 or di,di
767 jnz mtab1x
768 lea di,modelist ! Store standard modes:
769
770 mov eax,#VIDEO_80x25 + 0x50190000 ! The 80x25 mode (ALL)
771 stosd
772 mov al,[adapter] ! CGA/MDA/HGA -- no more modes
773 or al,al
774 jz mtabe
775 dec al
776 jnz mtabv
777 mov eax,#VIDEO_8POINT + 0x502b0000 ! The 80x43 EGA mode
778 stosd
779 jmp mtabe
780 mtab1x: jmp mtab1
781
782 mtabv: lea si,vga_modes ! All modes for std VGA
783 mov cx,#12
784 rep
785 movsw
786
787 cmpb [scanning],#0 ! Mode scan requested?
788 jz mscan1
789 call mode_scan
790 mscan1:
791
792 #ifdef CONFIG_VIDEO_LOCAL
793 call local_modes
794 #endif
795 #ifdef CONFIG_VIDEO_VESA
796 call vesa_modes ! Detect VESA VGA modes
797 #endif
798 #ifdef CONFIG_VIDEO_SVGA
799 cmpb [scanning],#0 ! Bypass when scanning
800 jnz mscan2
801 call svga_modes ! Detect SVGA cards & modes
802 mscan2:
803 #endif
804
805 mtabe:
806
807 #ifdef CONFIG_VIDEO_COMPACT
808 lea si,modelist ! Compact video mode list if requested.
809 mov dx,di
810 mov di,si
811 cmt1: cmp si,dx ! Scan all modes
812 jz cmt2
813 lea bx,modelist ! Find in previous entries
814 mov cx,(si+2)
815 cmt3: cmp si,bx
816 jz cmt4
817 cmp cx,(bx+2) ! Found => don't copy this entry
818 jz cmt5
819 add bx,#4
820 jmp cmt3
821
822 cmt4: movsd ! Copy entry
823 jmp cmt1
824
825 cmt5: add si,#4 ! Skip entry
826 jmp cmt1
827
828 cmt2:
829 #endif
830
831 mov (di),#ASK_VGA ! End marker
832 mov [mt_end],di
833 mtab1: lea si,modelist ! Returning: SI=mode list, DI=list end
834 ret0: ret
835
836 ! Modes usable on all standard VGAs
837
838 vga_modes:
839 .word VIDEO_8POINT
840 .word 0x5032 ! 80x50
841 .word VIDEO_80x43
842 .word 0x502b ! 80x43
843 .word VIDEO_80x28
844 .word 0x501c ! 80x28
845 .word VIDEO_80x30
846 .word 0x501e ! 80x30
847 .word VIDEO_80x34
848 .word 0x5022 ! 80x34
849 .word VIDEO_80x60
850 .word 0x503c ! 80x60
851
852 !
853 ! Detect VESA modes.
854 !
855
856 #ifdef CONFIG_VIDEO_VESA
857
858 vesa_modes:
859 cmpb [adapter],#2 ! VGA only
860 jnz ret0
861 mov bp,di ! BP=original mode table end
862 add di,#0x200 ! Buffer space
863 mov ax,#0x4f00 ! VESA Get card info call
864 int #0x10
865 mov di,bp
866 cmp ax,#0x004f ! Successful?
867 jnz ret0
868 cmp (di+0x200),#0x4556
869 jnz ret0
870 cmp (di+0x202),#0x4153
871 jnz ret0
872 mov [card_name],#vesa_name ! Set name to "VESA VGA"
873 push gs
874 lgs si,(di+0x20e) ! GS:SI=mode list
875 mov cx,#128 ! Iteration limit
876 vesa1: seg gs ! Get next mode in the list
877 lodsw
878 cmp ax,#0xffff ! End of the table?
879 jz vesar
880 cmp ax,#0x0080 ! Check validity of mode ID
881 jc vesa2
882 or ah,ah ! Valid ID's are 0x0000-0x007f
883 jz vesae ! and 0x0100-0x07ff.
884 cmp ax,#0x0800
885 jnc vesae
886 vesa2: push cx
887 mov cx,ax ! Get mode information structure
888 mov ax,#0x4f01
889 int 0x10
890 mov bx,cx ! BX=mode number
891 add bh,#VIDEO_FIRST_VESA>>8
892 pop cx
893 cmp ax,#0x004f
894 jnz vesan ! Don't report errors (buggy BIOSES :-[ )
895 mov al,(di) ! Check capabilities. We require
896 and al,#0x19 ! a color text mode.
897 cmp al,#0x09
898 jnz vesan
899 cmp (di+8),#0xb800 ! Standard video memory address required
900 jnz vesan
901 testb (di),#2 ! Mode characteristics supplied?
902 mov (di),bx ! Store mode number
903 jz vesa3
904 xor dx,dx
905 mov bx,(di+0x12) ! Width
906 or bh,bh
907 jnz vesan
908 mov (di+3),bl
909 mov ax,(di+0x14) ! Height
910 or ah,ah
911 jnz vesan
912 mov (di+2),al
913 mul bl
914 cmp ax,#8193 ! Small enough for Linux console driver?
915 jnc vesan
916 jmp vesaok
917
918 vesa3: sub bx,#0x8108 ! This mode has no detailed info specified,
919 jc vesan ! so it must be a standard VESA mode.
920 cmp bx,#5
921 jnc vesan
922 mov ax,(bx+vesa_text_mode_table)
923 mov (di+2),ax
924 vesaok: add di,#4 ! The mode is valid. Store it.
925 vesan: loop vesa1 ! Next mode. Limit exceeded => error
926 vesae: lea si,vesaer
927 call prtstr
928 mov di,bp ! Discard already found modes.
929 vesar: pop gs
930 ret
931
932 !
933 ! Dimensions of standard VESA text modes
934 !
935
936 vesa_text_mode_table:
937 db 60, 80 ! 0108
938 db 25, 132 ! 0109
939 db 43, 132 ! 010A
940 db 50, 132 ! 010B
941 db 60, 132 ! 010C
942
943 #endif
944
945 !
946 ! Scan for video modes. A bit dirty, but should work.
947 !
948
949 mode_scan:
950 mov cx,#0x0100 ! Start with mode 0
951 scm1: mov ah,#0 ! Test the mode
952 mov al,cl
953 int 0x10
954 mov ah,#0x0f
955 int 0x10
956 cmp al,cl
957 jnz scm2 ! Mode not set
958 mov dx,#0x3c0 ! Test if it's a text mode
959 mov al,#0x10 ! Mode bits
960 call inidx
961 and al,#0x03
962 jnz scm2
963 mov dl,#0xce ! Another set of mode bits
964 mov al,#0x06
965 call inidx
966 shr al,#1
967 jc scm2
968 mov dl,#0xd4 ! Cursor location
969 mov al,#0x0f
970 call inidx
971 or al,al
972 jnz scm2
973 mov ax,cx ! OK, store the mode
974 stosw
975 seg gs ! Number of rows
976 mov al,[0x484]
977 inc al
978 stosb
979 seg gs ! Number of columns
980 mov ax,[0x44a]
981 stosb
982 scm2: inc cl
983 jns scm1
984 mov ax,#0x0003 ! Return back to mode 3
985 int 0x10
986 ret
987
988 tstidx: out dx,ax ! OUT DX,AX and inidx
989 inidx: out dx,al ! Read from indexed VGA register
990 inc dx ! AL=index, DX=index reg port -> AL=data
991 in al,dx
992 dec dx
993 ret
994
995 !
996 ! Try to detect type of SVGA card and supply (usually approximate) video
997 ! mode table for it.
998 !
999
1000 #ifdef CONFIG_VIDEO_SVGA
1001
1002 svga_modes:
1003 lea si,svga_table ! Test all known SVGA adapters
1004 dosvga: lodsw
1005 mov bp,ax ! Default mode table
1006 or ax,ax
1007 jz didsv1
1008 lodsw ! Pointer to test routine
1009 push si
1010 push di
1011 push es
1012 mov bx,#0xc000
1013 mov es,bx
1014 call ax ! Call test routine
1015 pop es
1016 pop di
1017 pop si
1018 or bp,bp
1019 jz dosvga
1020 mov si,bp ! Found, copy the modes
1021 mov ah,[svga_prefix]
1022 cpsvga: lodsb
1023 or al,al
1024 jz didsv
1025 stosw
1026 movsw
1027 jmp cpsvga
1028
1029 didsv: mov [card_name],si ! Store pointer to card name
1030 didsv1: ret
1031
1032 !
1033 ! Table of all known SVGA cards. For each card, we store a pointer to
1034 ! a table of video modes supported by the card and a pointer to a routine
1035 ! used for testing of presence of the card. The video mode table is always
1036 ! followed by the name of the card or the chipset.
1037 !
1038
1039 svga_table:
1040 .word ati_md, ati_test
1041 .word oak_md, oak_test
1042 .word paradise_md, paradise_test
1043 .word realtek_md, realtek_test
1044 .word s3_md, s3_test
1045 .word chips_md, chips_test
1046 .word video7_md, video7_test
1047 .word cirrus5_md, cirrus5_test
1048 .word cirrus6_md, cirrus6_test
1049 .word cirrus1_md, cirrus1_test
1050 .word ahead_md, ahead_test
1051 .word everex_md, everex_test
1052 .word genoa_md, genoa_test
1053 .word trident_md, trident_test
1054 .word tseng_md, tseng_test
1055 .word 0
1056
1057 !
1058 ! Test routines and mode tables:
1059 !
1060
1061 ! S3 - The test algorithm was taken from the SuperProbe package
1062 ! for XFree86 1.2.1. Report bugs to Christoph.Niemann@linux.org
1063
1064 s3_test:
1065 mov cx,#0x0f35 ! we store some constants in cl/ch
1066 mov dx,#0x03d4
1067 movb al,#0x38
1068 call inidx
1069 mov bh,al ! store current value of CRT-register 0x38
1070 mov ax,#0x0038
1071 call outidx ! disable writing to special regs
1072 movb al,cl ! check whether we can write special reg 0x35
1073 call inidx
1074 movb bl,al ! save the current value of CRT reg 0x35
1075 andb al,#0xf0 ! clear bits 0-3
1076 movb ah,al
1077 movb al,cl ! and write it to CRT reg 0x35
1078 call outidx
1079 call inidx ! now read it back
1080 andb al,ch ! clear the upper 4 bits
1081 jz s3_2 ! the first test failed. But we have a
1082 movb ah,bl ! second chance
1083 mov al,cl
1084 call outidx
1085 jmp s3_1 ! do the other tests
1086 s3_2: mov ax,cx ! load ah with 0xf and al with 0x35
1087 orb ah,bl ! set the upper 4 bits of ah with the orig value
1088 call outidx ! write ...
1089 call inidx ! ... and reread
1090 andb al,cl ! turn off the upper 4 bits
1091 push ax
1092 movb ah,bl ! restore old value in register 0x35
1093 movb al,cl
1094 call outidx
1095 pop ax
1096 cmp al,ch ! setting lower 4 bits was successful => bad
1097 je no_s3 ! writing is allowed => this is not an S3
1098 s3_1: mov ax,#0x4838 ! allow writing to special regs by putting
1099 call outidx ! magic number into CRT-register 0x38
1100 movb al,cl ! check whether we can write special reg 0x35
1101 call inidx
1102 movb bl,al
1103 andb al,#0xf0
1104 movb ah,al
1105 movb al,cl
1106 call outidx
1107 call inidx
1108 andb al,ch
1109 jnz no_s3 ! no, we can't write => no S3
1110 mov ax,cx
1111 orb ah,bl
1112 call outidx
1113 call inidx
1114 andb al,ch
1115 push ax
1116 movb ah,bl ! restore old value in register 0x35
1117 movb al,cl
1118 call outidx
1119 pop ax
1120 cmp al,ch
1121 jne no_s31 ! writing not possible => no S3
1122 movb al,#0x30
1123 call inidx ! now get the S3 id ...
1124 lea di,idS3
1125 mov cx,#0x10
1126 repne
1127 scasb
1128 je no_s31
1129 movb ah,bh
1130 movb al,#0x38
1131 jmp s3rest
1132 no_s3: movb al,#0x35 ! restore CRT register 0x35
1133 movb ah,bl
1134 call outidx
1135 no_s31: xor bp,bp ! Detection failed
1136 s3rest: movb ah,bh
1137 movb al,#0x38 ! restore old value of CRT register 0x38
1138 br outidx
1139
1140 idS3: .byte 0x81, 0x82, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95
1141 .byte 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa8, 0xb0
1142
1143 s3_md: .byte 0x54, 0x2b, 0x84
1144 .byte 0x55, 0x19, 0x84
1145 .byte 0
1146 .ascii "S3"
1147 .byte 0
1148
1149 ! ATI cards.
1150
1151 ati_test:
1152 lea si,idati
1153 mov di,#0x31
1154 mov cx,#0x09
1155 repe
1156 cmpsb
1157 je atiok
1158 xor bp,bp
1159 atiok: ret
1160
1161 idati: .ascii "761295520"
1162
1163 ati_md: .byte 0x23, 0x19, 0x84
1164 .byte 0x33, 0x2c, 0x84
1165 .byte 0x22, 0x1e, 0x64
1166 .byte 0x21, 0x19, 0x64
1167 .byte 0x58, 0x21, 0x50
1168 .byte 0x5b, 0x1e, 0x50
1169 .byte 0
1170 .ascii "ATI"
1171 .byte 0
1172
1173 ! AHEAD
1174
1175 ahead_test:
1176 mov ax,#0x200f
1177 mov dx,#0x3ce
1178 out dx,ax
1179 inc dx
1180 in al,dx
1181 cmp al,#0x20
1182 je isahed
1183 cmp al,#0x21
1184 je isahed
1185 xor bp,bp
1186 isahed: ret
1187
1188 ahead_md:
1189 .byte 0x22, 0x2c, 0x84
1190 .byte 0x23, 0x19, 0x84
1191 .byte 0x24, 0x1c, 0x84
1192 .byte 0x2f, 0x32, 0xa0
1193 .byte 0x32, 0x22, 0x50
1194 .byte 0x34, 0x42, 0x50
1195 .byte 0
1196 .ascii "Ahead"
1197 .byte 0
1198
1199 ! Chips & Tech.
1200
1201 chips_test:
1202 mov dx,#0x3c3
1203 in al,dx
1204 or al,#0x10
1205 out dx,al
1206 mov dx,#0x104
1207 in al,dx
1208 mov bl,al
1209 mov dx,#0x3c3
1210 in al,dx
1211 and al,#0xef
1212 out dx,al
1213 cmp bl,#0xa5
1214 je cantok
1215 xor bp,bp
1216 cantok: ret
1217
1218 chips_md:
1219 .byte 0x60, 0x19, 0x84
1220 .byte 0x61, 0x32, 0x84
1221 .byte 0
1222 .ascii "Chips & Technologies"
1223 .byte 0
1224
1225 ! Cirrus Logic 5X0
1226
1227 cirrus1_test:
1228 mov dx,#0x3d4
1229 mov al,#0x0c
1230 out dx,al
1231 inc dx
1232 in al,dx
1233 mov bl,al
1234 xor al,al
1235 out dx,al
1236 dec dx
1237 mov al,#0x1f
1238 out dx,al
1239 inc dx
1240 in al,dx
1241 mov bh,al
1242 xor ah,ah
1243 shl al,#4
1244 mov cx,ax
1245 mov al,bh
1246 shr al,#4
1247 add cx,ax
1248 shl cx,#8
1249 add cx,#6
1250 mov ax,cx
1251 mov dx,#0x3c4
1252 out dx,ax
1253 inc dx
1254 in al,dx
1255 and al,al
1256 jnz nocirr
1257 mov al,bh
1258 out dx,al
1259 in al,dx
1260 cmp al,#0x01
1261 je iscirr
1262 nocirr: xor bp,bp
1263 iscirr: mov dx,#0x3d4
1264 mov al,bl
1265 xor ah,ah
1266 shl ax,#8
1267 add ax,#0x0c
1268 out dx,ax
1269 ret
1270
1271 cirrus1_md:
1272 .byte 0x1f, 0x19, 0x84
1273 .byte 0x20, 0x2c, 0x84
1274 .byte 0x22, 0x1e, 0x84
1275 .byte 0x31, 0x25, 0x64
1276 .byte 0
1277 .ascii "Cirrus Logic 5X0"
1278 .byte 0
1279
1280 ! Cirrus Logic 54XX
1281
1282 cirrus5_test:
1283 mov dx,#0x3c4
1284 mov al,#6
1285 call inidx
1286 mov bl,al ! BL=backup
1287 mov ax,#6
1288 call tstidx
1289 cmp al,#0x0f
1290 jne c5fail
1291 mov ax,#0x1206
1292 call tstidx
1293 cmp al,#0x12
1294 jne c5fail
1295 mov al,#0x1e
1296 call inidx
1297 mov bh,al
1298 mov ah,bh
1299 and ah,#0xc0
1300 mov al,#0x1e
1301 call tstidx
1302 and al,#0x3f
1303 jne c5xx
1304 mov al,#0x1e
1305 mov ah,bh
1306 or ah,#0x3f
1307 call tstidx
1308 xor al,#0x3f
1309 and al,#0x3f
1310 c5xx: pushf
1311 mov al,#0x1e
1312 mov ah,bh
1313 out dx,ax
1314 popf
1315 je c5done
1316 c5fail: xor bp,bp
1317 c5done: mov al,#6
1318 mov ah,bl
1319 out dx,ax
1320 ret
1321
1322 cirrus5_md:
1323 .byte 0x14, 0x19, 0x84
1324 .byte 0x54, 0x2b, 0x84
1325 .byte 0
1326 .ascii "Cirrus Logic 54XX"
1327 .byte 0
1328
1329 ! Cirrus Logic 64XX -- no known extra modes, but must be identified, because
1330 ! it's misidentified by the Ahead test.
1331
1332 cirrus6_test:
1333 mov dx,#0x3ce
1334 mov al,#0x0a
1335 call inidx
1336 mov bl,al ! BL=backup
1337 mov ax,#0xce0a
1338 call tstidx
1339 or al,al
1340 jne c2fail
1341 mov ax,#0xec0a
1342 call tstidx
1343 cmp al,#0x01
1344 jne c2fail
1345 mov al,#0xaa
1346 call inidx ! 4X, 5X, 7X and 8X are valid 64XX chip ID's
1347 shr al,#4
1348 sub al,#4
1349 jz c6done
1350 dec al
1351 jz c6done
1352 sub al,#2
1353 jz c6done
1354 dec al
1355 jz c6done
1356 c2fail: xor bp,bp
1357 c6done: mov al,#0x0a
1358 mov ah,bl
1359 out dx,ax
1360 ret
1361
1362 cirrus6_md:
1363 .byte 0
1364 .ascii "Cirrus Logic 64XX"
1365 .byte 0
1366
1367 ! Everex / Trident
1368
1369 everex_test:
1370 mov ax,#0x7000
1371 xor bx,bx
1372 int 0x10
1373 cmp al,#0x70
1374 jne noevrx
1375 shr dx,#4
1376 cmp dx,#0x678
1377 je evtrid
1378 cmp dx,#0x236
1379 jne evrxok
1380 evtrid: lea bp,trident_md
1381 evrxok: ret
1382
1383 noevrx: xor bp,bp
1384 ret
1385
1386 everex_md:
1387 .byte 0x03, 0x22, 0x50
1388 .byte 0x04, 0x3c, 0x50
1389 .byte 0x07, 0x2b, 0x64
1390 .byte 0x08, 0x4b, 0x64
1391 .byte 0x0a, 0x19, 0x84
1392 .byte 0x0b, 0x2c, 0x84
1393 .byte 0x16, 0x1e, 0x50
1394 .byte 0x18, 0x1b, 0x64
1395 .byte 0x21, 0x40, 0xa0
1396 .byte 0x40, 0x1e, 0x84
1397 .byte 0
1398 .ascii "Everex/Trident"
1399 .byte 0
1400
1401 ! Genoa.
1402
1403 genoa_test:
1404 lea si,idgenoa ! Check Genoa 'clues'
1405 xor ax,ax
1406 seg es
1407 mov al,[0x37]
1408 mov di,ax
1409 mov cx,#0x04
1410 dec si
1411 dec di
1412 l1: inc si
1413 inc di
1414 mov al,(si)
1415 test al,al
1416 jz l2
1417 seg es
1418 cmp al,(di)
1419 l2: loope l1
1420 or cx,cx
1421 je isgen
1422 xor bp,bp
1423 isgen: ret
1424
1425 idgenoa: .byte 0x77, 0x00, 0x99, 0x66
1426
1427 genoa_md:
1428 .byte 0x58, 0x20, 0x50
1429 .byte 0x5a, 0x2a, 0x64
1430 .byte 0x60, 0x19, 0x84
1431 .byte 0x61, 0x1d, 0x84
1432 .byte 0x62, 0x20, 0x84
1433 .byte 0x63, 0x2c, 0x84
1434 .byte 0x64, 0x3c, 0x84
1435 .byte 0x6b, 0x4f, 0x64
1436 .byte 0x72, 0x3c, 0x50
1437 .byte 0x74, 0x42, 0x50
1438 .byte 0x78, 0x4b, 0x64
1439 .byte 0
1440 .ascii "Genoa"
1441 .byte 0
1442
1443 ! OAK
1444
1445 oak_test:
1446 lea si,idoakvga
1447 mov di,#0x08
1448 mov cx,#0x08
1449 repe
1450 cmpsb
1451 je isoak
1452 xor bp,bp
1453 isoak: ret
1454
1455 idoakvga: .ascii "OAK VGA "
1456
1457 oak_md: .byte 0x4e, 0x3c, 0x50
1458 .byte 0x4f, 0x3c, 0x84
1459 .byte 0x50, 0x19, 0x84
1460 .byte 0x51, 0x2b, 0x84
1461 .byte 0
1462 .ascii "OAK"
1463 .byte 0
1464
1465 ! WD Paradise.
1466
1467 paradise_test:
1468 lea si,idparadise
1469 mov di,#0x7d
1470 mov cx,#0x04
1471 repe
1472 cmpsb
1473 je ispara
1474 xor bp,bp
1475 ispara: ret
1476
1477 idparadise: .ascii "VGA="
1478
1479 paradise_md:
1480 .byte 0x41, 0x22, 0x50
1481 .byte 0x47, 0x1c, 0x84
1482 .byte 0x55, 0x19, 0x84
1483 .byte 0x54, 0x2c, 0x84
1484 .byte 0
1485 .ascii "Paradise"
1486 .byte 0
1487
1488 ! Trident.
1489
1490 trident_test:
1491 mov dx,#0x3c4
1492 mov al,#0x0e
1493 out dx,al
1494 inc dx
1495 in al,dx
1496 xchg ah,al
1497 xor al,al
1498 out dx,al
1499 in al,dx
1500 xchg al,ah
1501 mov bl,al ! Strange thing ... in the book this wasn't
1502 and bl,#0x02 ! necessary but it worked on my card which
1503 jz setb2 ! is a trident. Without it the screen goes
1504 and al,#0xfd ! blurred ...
1505 jmp clrb2 !
1506 setb2: or al,#0x02 !
1507 clrb2: out dx,al
1508 and ah,#0x0f
1509 cmp ah,#0x02
1510 je istrid
1511 xor bp,bp
1512 istrid: ret
1513
1514 trident_md:
1515 .byte 0x50, 0x1e, 0x50
1516 .byte 0x51, 0x2b, 0x50
1517 .byte 0x52, 0x3c, 0x50
1518 .byte 0x57, 0x19, 0x84
1519 .byte 0x58, 0x1e, 0x84
1520 .byte 0x59, 0x2b, 0x84
1521 .byte 0x5a, 0x3c, 0x84
1522 .byte 0
1523 .ascii "Trident"
1524 .byte 0
1525
1526 ! Tseng.
1527
1528 tseng_test:
1529 mov dx,#0x3cd
1530 in al,dx ! Could things be this simple ! :-)
1531 mov bl,al
1532 mov al,#0x55
1533 out dx,al
1534 in al,dx
1535 mov ah,al
1536 mov al,bl
1537 out dx,al
1538 cmp ah,#0x55
1539 je istsen
1540 isnot: xor bp,bp
1541 istsen: ret
1542
1543 tseng_md:
1544 .byte 0x26, 0x3c, 0x50
1545 .byte 0x2a, 0x28, 0x64
1546 .byte 0x23, 0x19, 0x84
1547 .byte 0x24, 0x1c, 0x84
1548 .byte 0x22, 0x2c, 0x84
1549 .byte 0x21, 0x3c, 0x84
1550 .byte 0
1551 .ascii "Tseng"
1552 .byte 0
1553
1554 ! Video7.
1555
1556 video7_test:
1557 mov dx,#0x3cc
1558 in al,dx
1559 mov dx,#0x3b4
1560 and al,#0x01
1561 jz even7
1562 mov dx,#0x3d4
1563 even7: mov al,#0x0c
1564 out dx,al
1565 inc dx
1566 in al,dx
1567 mov bl,al
1568 mov al,#0x55
1569 out dx,al
1570 in al,dx
1571 dec dx
1572 mov al,#0x1f
1573 out dx,al
1574 inc dx
1575 in al,dx
1576 mov bh,al
1577 dec dx
1578 mov al,#0x0c
1579 out dx,al
1580 inc dx
1581 mov al,bl
1582 out dx,al
1583 mov al,#0x55
1584 xor al,#0xea
1585 cmp al,bh
1586 jne isnot
1587 movb [svga_prefix],#VIDEO_FIRST_V7>>8 ! Use special mode switching
1588 ret
1589
1590 video7_md:
1591 .byte 0x40, 0x2b, 0x50
1592 .byte 0x43, 0x3c, 0x50
1593 .byte 0x44, 0x3c, 0x64
1594 .byte 0x41, 0x19, 0x84
1595 .byte 0x42, 0x2c, 0x84
1596 .byte 0x45, 0x1c, 0x84
1597 .byte 0
1598 .ascii "Video 7"
1599 .byte 0
1600
1601 ! Realtek VGA
1602
1603 realtek_test:
1604 lea si,idrtvga
1605 mov di,#0x45
1606 mov cx,#0x0b
1607 repe
1608 cmpsb
1609 je isrt
1610 xor bp,bp
1611 isrt: ret
1612
1613 idrtvga: .ascii "REALTEK VGA"
1614
1615 realtek_md:
1616 .byte 0x1a, 0x3c, 0x50
1617 .byte 0x1b, 0x19, 0x84
1618 .byte 0x1c, 0x1e, 0x84
1619 .byte 0x1d, 0x2b, 0x84
1620 .byte 0x1e, 0x3c, 0x84
1621 .byte 0
1622 .ascii "REALTEK"
1623 .byte 0
1624
1625 #endif
1626
1627 !
1628 ! User-defined local mode table (VGA only)
1629 !
1630
1631 #ifdef CONFIG_VIDEO_LOCAL
1632
1633 local_modes:
1634 lea si,local_mode_table
1635 locm1: lodsw
1636 or ax,ax
1637 jz locm2
1638 stosw
1639 movsw
1640 jmp locm1
1641 locm2: ret
1642
1643 ! This is the table of local video modes which can be supplied manually
1644 ! by the user. Each entry consists of mode ID (word) and dimensions
1645 ! (byte for column count and another byte for row count). These modes
1646 ! are placed before all SVGA and VESA modes and override them if table
1647 ! compacting is enabled. The table must end with a zero word followed
1648 ! by NUL-terminated video adapter name.
1649
1650 local_mode_table:
1651 .word 0x0100 ! Example: 40x25
1652 .byte 25,40
1653 .word 0
1654 .ascii "Local"
1655 .byte 0
1656
1657 #endif
1658
1659 !
1660 ! Read a key and return the ASCII code in al, scan code in ah
1661 !
1662
1663 getkey: xor ah,ah
1664 int 0x16
1665 ret
1666
1667 !
1668 ! Read a key with a timeout of 30 seconds. The hardware clock is used to get
1669 ! the time.
1670 !
1671
1672 getkt: call gettime
1673 add al,#30 ! Wait 30 seconds
1674 cmp al,#60
1675 jl lminute
1676 sub al,#60
1677 lminute:
1678 mov cl,al
1679 again: mov ah,#0x01
1680 int 0x16
1681 jnz getkey ! key pressed, so get it
1682 call gettime
1683 cmp al,cl
1684 jne again
1685 mov al,#0x20 ! timeout, return default char `space'
1686 ret
1687
1688 !
1689 ! Flush the keyboard buffer
1690 !
1691
1692 flush: mov ah,#0x01
1693 int 0x16
1694 jz empty
1695 xor ah,ah
1696 int 0x16
1697 jmp flush
1698 empty: ret
1699
1700 !
1701 ! Print hexadecimal number.
1702 !
1703
1704 prthw: push ax
1705 mov al,ah
1706 call prthb
1707 pop ax
1708 prthb: push ax
1709 shr al,#4
1710 call prthn
1711 pop ax
1712 and al,#0x0f
1713 prthn: cmp al,#0x0a
1714 jc prth1
1715 add al,#0x07
1716 prth1: add al,#0x30
1717 br prtchr
1718
1719 !
1720 ! Print decimal number (AL).
1721 !
1722
1723 prtdec: push ax
1724 push cx
1725 xor ah,ah ! Clear ah
1726 mov cl,#0x0a
1727 idiv cl
1728 cmp al,#0x09
1729 jbe lt100
1730 call prtdec
1731 jmp skip10
1732 lt100: add al,#0x30
1733 call prtchr
1734 skip10: mov al,ah
1735 add al,#0x30
1736 call prtchr
1737 pop cx
1738 pop ax
1739 ret
1740
1741 ! Variables:
1742
1743 adapter: .byte 0 ! Video adapter: 0=CGA/MDA/HGA,1=EGA,2=VGA
1744 mt_end: .word 0 ! End of video mode table if built
1745 edit_buf: .space 6 ! Line editor buffer
1746 card_name: .word 0 ! Pointer to adapter name
1747 scanning: .byte 0 ! Performing mode scan
1748 do_restore: .byte 0 ! Screen contents altered during mode change
1749 svga_prefix: .byte VIDEO_FIRST_BIOS>>8 ! Default prefix for BIOS modes
1750 video_segment: .word 0xb800 ! Video memory segment
1751 force_size: .word 0 ! Use this size instead of the one in BIOS vars
1752
1753 ! Messages:
1754
1755 keymsg: .ascii "Press <RETURN> to see video modes available, "
1756 .ascii "<SPACE> to continue or wait 30 secs"
1757 db 0x0d, 0x0a, 0
1758 listhdr: db 0x0d, 0x0a
1759 .ascii "Mode: COLSxROWS:"
1760 crlft: db 0x0d, 0x0a, 0
1761 prompt: db 0x0d, 0x0a
1762 .ascii "Enter mode number: "
1763 db 0
1764 unknt: .ascii "Unknown mode ID. Try again."
1765 db 0
1766 badmdt: .ascii "You passed an undefined mode number to setup."
1767 db 0x0d, 0x0a, 0
1768 vesaer: .ascii "Error: Scanning of VESA modes failed. Please "
1769 .ascii "report to <mj@k332.feld.cvut.cz>."
1770 db 0x0d, 0x0a, 0
1771 old_name: .ascii "CGA/MDA/HGA"
1772 db 0
1773 ega_name: .ascii "EGA"
1774 db 0
1775 svga_name: .ascii " "
1776 vga_name: .ascii "VGA"
1777 db 0
1778 vesa_name: .ascii "VESA"
1779 db 0
1780 name_bann: .ascii "Video adapter: "
1781 db 0