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