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