3 * Display adapter & video mode setup, version 2.13 (14-May-99)
5 * Copyright (C) 1995 -- 1998 Martin Mares <mj@ucw.cz>
6 * Based on the original setup.S code (C) Linus Torvalds and Mats Anderson
8 * Rewritten to use GNU 'as' by Chris Noe <stiker@northlink.com> May 1999
10 * For further information, look at Documentation/svga.txt.
14 #include <linux/config.h> /* for CONFIG_VIDEO_* */
16 /* Enable autodetection of SVGA adapters and modes. */
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 BIOS behaviour */
32 #undef CONFIG_VIDEO_400_HACK
34 /* Hack that lets you force specific BIOS mode ID and specific dimensions */
35 #undef CONFIG_VIDEO_GFX_HACK
36 #define VIDEO_GFX_BIOS_AX 0x4f02 /* 800x600 on ThinkPad */
37 #define VIDEO_GFX_BIOS_BX 0x0102
38 #define VIDEO_GFX_DUMMY_RESOLUTION 0x6425 /* 100x37 */
40 /* This code uses an extended set of video mode numbers. These include:
41 * Aliases for standard modes
45 * Video modes numbered by menu position -- NOT RECOMMENDED because of lack
46 * of compatibility when extending the table. These are between 0x00 and 0xff.
48 #define VIDEO_FIRST_MENU 0x0000
50 /* Standard BIOS video modes (BIOS number + 0x0100) */
51 #define VIDEO_FIRST_BIOS 0x0100
53 /* VESA BIOS video modes (VESA number + 0x0200) */
54 #define VIDEO_FIRST_VESA 0x0200
56 /* Video7 special modes (BIOS number + 0x0900) */
57 #define VIDEO_FIRST_V7 0x0900
59 /* Special video modes */
60 #define VIDEO_FIRST_SPECIAL 0x0f00
61 #define VIDEO_80x25 0x0f00
62 #define VIDEO_8POINT 0x0f01
63 #define VIDEO_80x43 0x0f02
64 #define VIDEO_80x28 0x0f03
65 #define VIDEO_CURRENT_MODE 0x0f04
66 #define VIDEO_80x30 0x0f05
67 #define VIDEO_80x34 0x0f06
68 #define VIDEO_80x60 0x0f07
69 #define VIDEO_GFX_HACK 0x0f08
70 #define VIDEO_LAST_SPECIAL 0x0f09
72 /* Video modes given by resolution */
73 #define VIDEO_FIRST_RESOLUTION 0x1000
75 /* The "recalculate timings" flag */
76 #define VIDEO_RECALC 0x8000
78 /* Positions of various video parameters passed to the kernel */
79 /* (see also include/linux/tty.h) */
80 #define PARAM_CURSOR_POS 0x00
81 #define PARAM_VIDEO_PAGE 0x04
82 #define PARAM_VIDEO_MODE 0x06
83 #define PARAM_VIDEO_COLS 0x07
84 #define PARAM_VIDEO_EGA_BX 0x0a
85 #define PARAM_VIDEO_LINES 0x0e
86 #define PARAM_HAVE_VGA 0x0f
87 #define PARAM_FONT_POINTS 0x10
89 #define PARAM_LFB_WIDTH 0x12
90 #define PARAM_LFB_HEIGHT 0x14
91 #define PARAM_LFB_DEPTH 0x16
92 #define PARAM_LFB_BASE 0x18
93 #define PARAM_LFB_SIZE 0x1c
94 #define PARAM_LFB_LINELENGTH 0x24
95 #define PARAM_LFB_COLORS 0x26
96 #define PARAM_VESAPM_SEG 0x2e
97 #define PARAM_VESAPM_OFF 0x30
98 #define PARAM_LFB_PAGES 0x32
99 #define PARAM_VESA_ATTRIB 0x34
101 /* Define DO_STORE according to CONFIG_VIDEO_RETAIN */
102 #ifdef CONFIG_VIDEO_RETAIN
103 #define DO_STORE call store_screen
106 #endif /* CONFIG_VIDEO_RETAIN */
108 # This is the main entry point called by setup.S
109 # %ds *must* be pointing to the bootsector
110 video: pushw %ds # We use different segments
111 pushw %ds # FS contains original DS
113 pushw %cs # DS is equal to CS
115 pushw %cs # ES is equal to CS
118 movw %ax, %gs # GS is zero
120 call basic_detect # Basic adapter type testing (EGA/VGA/MDA/CGA)
121 #ifdef CONFIG_VIDEO_SELECT
122 movw %fs:(0x01fa), %ax # User selected video mode
123 cmpw $ASK_VGA, %ax # Bring up the menu
126 call mode_set # Set the mode
129 leaw badmdt, %si # Invalid mode ID
133 #ifdef CONFIG_VIDEO_RETAIN
134 call restore_screen # Restore screen contents
135 #endif /* CONFIG_VIDEO_RETAIN */
137 #endif /* CONFIG_VIDEO_SELECT */
138 call mode_params # Store mode parameters
139 popw %ds # Restore original DS
142 # Detect if we have CGA, MDA, EGA or VGA and pass it to the kernel.
144 movb $0, %fs:(PARAM_HAVE_VGA)
145 movb $0x12, %ah # Check EGA/VGA
148 movw %bx, %fs:(PARAM_VIDEO_EGA_BX) # Identifies EGA to the kernel
149 cmpb $0x10, %bl # No, it's a CGA/MDA/HGA card.
153 movw $0x1a00, %ax # Check EGA or VGA?
155 cmpb $0x1a, %al # 1a means VGA...
156 jne basret # anything else is EGA.
158 incb %fs:(PARAM_HAVE_VGA) # We've detected a VGA
162 # Store the video mode parameters for later usage by the kernel.
163 # This is done by asking the BIOS except for the rows/columns
164 # parameters in the default 80x25 mode -- these are set directly,
165 # because some very obscure BIOSes supply insane values.
167 #ifdef CONFIG_VIDEO_SELECT
168 cmpb $0, graphic_mode
171 movb $0x03, %ah # Read cursor position
174 movw %dx, %fs:(PARAM_CURSOR_POS)
175 movb $0x0f, %ah # Read page/mode/width
177 movw %bx, %fs:(PARAM_VIDEO_PAGE)
178 movw %ax, %fs:(PARAM_VIDEO_MODE) # Video mode and screen width
179 cmpb $0x7, %al # MDA/HGA => segment differs
182 movw $0xb000, video_segment
183 mopar0: movw %gs:(0x485), %ax # Font size
184 movw %ax, %fs:(PARAM_FONT_POINTS) # (valid only on EGA/VGA)
185 movw force_size, %ax # Forced size?
189 movb %ah, %fs:(PARAM_VIDEO_COLS)
190 movb %al, %fs:(PARAM_VIDEO_LINES)
193 mopar1: movb $25, %al
194 cmpb $0, adapter # If we are on CGA/MDA/HGA, the
195 jz mopar2 # screen must have 25 lines.
197 movb %gs:(0x484), %al # On EGA/VGA, use the EGA+ BIOS
198 incb %al # location of max lines.
199 mopar2: movb %al, %fs:(PARAM_VIDEO_LINES)
202 #ifdef CONFIG_VIDEO_SELECT
203 # Fetching of VESA frame buffer parameters
205 leaw modelist+1024, %di
206 movb $0x23, %fs:(PARAM_HAVE_VGA)
208 movw %ax, %fs:(PARAM_LFB_LINELENGTH)
210 movw %ax, %fs:(PARAM_LFB_WIDTH)
212 movw %ax, %fs:(PARAM_LFB_HEIGHT)
215 movw %ax, %fs:(PARAM_LFB_DEPTH)
218 movw %ax, %fs:(PARAM_LFB_PAGES)
220 movl %eax, %fs:(PARAM_LFB_BASE)
222 movl %eax, %fs:(PARAM_LFB_COLORS)
224 movl %eax, %fs:(PARAM_LFB_COLORS+4)
226 movw %ax, %fs:(PARAM_VESA_ATTRIB)
229 leaw modelist+1024, %di
234 movl %eax, %fs:(PARAM_LFB_SIZE)
236 # switching the DAC to 8-bit is for <= 8 bpp only
237 movw %fs:(PARAM_LFB_DEPTH), %ax
241 # get DAC switching capability
247 # attempt to switch DAC to 8-bit
253 movb %bh, dac_size # store actual DAC size
256 # set color size to DAC size
258 movb %al, %fs:(PARAM_LFB_COLORS+0)
259 movb %al, %fs:(PARAM_LFB_COLORS+2)
260 movb %al, %fs:(PARAM_LFB_COLORS+4)
261 movb %al, %fs:(PARAM_LFB_COLORS+6)
263 # set color offsets to 0
264 movb $0, %fs:(PARAM_LFB_COLORS+1)
265 movb $0, %fs:(PARAM_LFB_COLORS+3)
266 movb $0, %fs:(PARAM_LFB_COLORS+5)
267 movb $0, %fs:(PARAM_LFB_COLORS+7)
270 # get protected mode interface informations
278 movw %es, %fs:(PARAM_VESAPM_SEG)
279 movw %di, %fs:(PARAM_VESAPM_OFF)
282 # The video mode menu
284 leaw keymsg, %si # "Return/Space/Timeout" message
289 cmpb $0x0d, %al # ENTER ?
290 je listm # yes - manual mode selection
292 cmpb $0x20, %al # SPACE ?
293 je defmd1 # no - repeat
298 defmd1: ret # No mode chosen? Default 80x25
300 listm: call mode_table # List mode table
301 listm0: leaw name_bann, %si # Print adapter name
322 leaw listhdr, %si # Table header
324 movb $0x30, %dl # DL holds mode number
326 lm1: cmpw $ASK_VGA, (%si) # End?
329 movb %dl, %al # Menu selection number
337 movb $0x78, %al # the letter 'x'
340 call prtdec # Columns
341 movb $0x0d, %al # New line
345 incb %dl # Next character
352 lm2: leaw prompt, %si # Mode prompt
354 leaw edit_buf, %di # Editor buffer
356 cmpb $0x0d, %al # Enter?
359 cmpb $0x08, %al # Backspace?
362 cmpb $0x20, %al # Printable?
365 cmpw $edit_buf+4, %di # Enough space?
372 lmbs: cmpw $edit_buf, %di # Backspace
383 lment: movb $0, (%di)
387 cmpb $0, (%si) # Empty string = default mode
390 cmpb $0, 1(%si) # One character = menu selection
393 cmpw $0x6373, (%si) # "scan" => mode scanning
399 lmhx: xorw %bx, %bx # Else => mode ID in hex
422 lmuse1: movw %bx, %ax
425 mnusel: lodsb # Menu selection
436 subb $0x61-0x30-10, %al
443 lmbad: leaw unknt, %si
446 lmscan: cmpb $0, adapter # Scanning only on EGA/VGA
449 movw $0, mt_end # Scanning of modes is
450 movb $1, scanning # done as new autodetection.
455 # Additional parts of mode_set... (relative jumps, you know)
456 setv7: # Video7 extended modes
458 subb $VIDEO_FIRST_V7>>8, %bh
464 _setrec: jmp setrec # Ugly...
465 _set_80x25: jmp set_80x25
467 # Aliases for backward compatibility.
469 movw $VIDEO_80x25, %ax
473 movb $VIDEO_8POINT-VIDEO_FIRST_SPECIAL, %al
475 jnz setbad # Fall-through!
477 # Setting of user mode (AX=mode ID) => CF=success
479 movw %ax, %fs:(0x01fa) # Store mode for use in acpi_wakeup.S
484 testb $VIDEO_RECALC>>8, %ah
487 cmpb $VIDEO_FIRST_RESOLUTION>>8, %ah
490 cmpb $VIDEO_FIRST_SPECIAL>>8, %ah
493 cmpb $VIDEO_FIRST_V7>>8, %ah
496 cmpb $VIDEO_FIRST_VESA>>8, %ah
506 movb $0, do_restore # The screen needn't be restored
511 subb $VIDEO_FIRST_VESA>>8, %bh
512 movw $0x4f02, %ax # VESA BIOS mode set call
514 cmpw $0x004f, %ax # AL=4f if implemented
515 jnz setbad # AH=0 if OK
522 int $0x10 # Standard BIOS mode set call
524 movb $0x0f, %ah # Check if really set
533 setspc: xorb %bh, %bh # Set special mode
534 cmpb $VIDEO_LAST_SPECIAL-VIDEO_FIRST_SPECIAL, %bl
541 orb %al, %al # 80x25 is an exception
544 pushw %bx # Set mode chosen from menu
545 call mode_table # Build the mode table
552 movw (%si), %ax # Fetch mode ID
555 setres: pushw %bx # Set mode chosen by resolution
560 cmpw $ASK_VGA, %ax # End of the list?
567 movw -4(%si), %ax # Fetch mode ID
571 leaw modelist+1024, %di
572 subb $VIDEO_FIRST_VESA>>8, %bh
573 movw %bx, %cx # Get mode information structure
576 addb $VIDEO_FIRST_VESA>>8, %bh
580 movb (%di), %al # Check capabilities.
583 jz setvesa # This is a text mode
585 movb (%di), %al # Check capabilities.
588 jnz _setbad # Doh! No linear frame buffer.
590 subb $VIDEO_FIRST_VESA>>8, %bh
591 orw $0x4000, %bx # Use linear frame buffer
592 movw $0x4f02, %ax # VESA BIOS mode set call
594 cmpw $0x004f, %ax # AL=4f if implemented
595 jnz _setbad # AH=0 if OK
597 movb $1, graphic_mode # flag graphic mode
598 movb $0, do_restore # no screen restore
602 _setbad: jmp setbad # Ugly...
604 # Recalculate vertical display end registers -- this fixes various
605 # inconsistencies of extended modes on many adapters. Called when
606 # the VIDEO_RECALC flag is set in the mode ID.
608 setrec: subb $VIDEO_RECALC>>8, %ah # Set the base mode
612 movw %gs:(0x485), %ax # Font size in pixels
613 movb %gs:(0x484), %bl # Number of rows
615 mulb %bl # Number of visible
616 decw %ax # scan lines - 1
619 movb $0x12, %al # Lower 8 bits
622 movb $0x07, %al # Bits 8 and 9 in the overflow register
632 rct2: movb $0x07, %al
637 # Table of routines for setting of the special modes.
649 # Set the 80x25 mode. If already set, do nothing.
651 movw $0x5019, force_size # Override possibly broken BIOS
653 #ifdef CONFIG_VIDEO_400_HACK
654 movw $0x1202, %ax # Force 400 scan lines
658 movb $0x0f, %ah # Get current mode ID
660 cmpw $0x5007, %ax # Mode 7 (80x25 mono) is the only one available
661 jz st80 # on CGA/MDA/HGA and is also available on EGAM
663 cmpw $0x5003, %ax # Unknown mode, force 80x25 color
666 st80: cmpb $0, adapter # CGA/MDA/HGA => mode 3/7 is always 80x25
669 movb %gs:(0x0484), %al # This is EGA+ -- beware of 80x50 etc.
670 orb %al, %al # Some buggy BIOS'es set 0 rows
673 cmpb $24, %al # It's hopefully correct
675 #endif /* CONFIG_VIDEO_400_HACK */
677 movw $0x0003, %ax # Forced set
682 # Set the 80x50/80x43 8-pixel mode. Simple BIOS calls.
685 call use_80x25 # The base is 80x25
687 movw $0x1112, %ax # Use 8x8 font
690 movw $0x1200, %ax # Use alternate print screen
693 movw $0x1201, %ax # Turn off cursor emulation
696 movb $0x01, %ah # Define cursor scan lines 6-7
703 # Set the 80x28 mode. This mode works on all VGA's, because it's a standard
704 # 80x25 mode with 14-point fonts instead of 16-point.
707 call use_80x25 # The base is 80x25
708 set14: movw $0x1111, %ax # Use 9x14 font
711 movb $0x01, %ah # Define cursor scan lines 11-12
717 # Set the 80x43 mode. This mode is works on all VGA's.
718 # It's a 350-scanline mode with 8-pixel font.
721 movw $0x1201, %ax # Set 350 scans
724 movw $0x0003, %ax # Reset video mode
726 jmp set_8pt # Use 8-pixel font
728 # Set the 80x30 mode (all VGA's). 480 scanlines, 16-pixel font.
730 call use_80x25 # Start with real 80x25
732 movw $0x3cc, %dx # Get CRTC port
735 rorb %al # Mono or color?
739 set48a: movw $0x0c11, %ax # Vertical sync end (also unlocks CR0-7)
741 movw $0x0b06, %ax # Vertical total
743 movw $0x3e07, %ax # (Vertical) overflow
745 movw $0xea10, %ax # Vertical sync start
747 movw $0xdf12, %ax # Vertical display end
749 movw $0xe715, %ax # Vertical blank start
751 movw $0x0416, %ax # Vertical blank end
754 movb $0xcc, %dl # Misc output register (read)
756 movb $0xc2, %dl # (write)
757 andb $0x0d, %al # Preserve clock select bits and color bit
758 orb $0xe2, %al # Set correct sync polarity
761 movw $0x501e, force_size
765 # Set the 80x34 mode (all VGA's). 480 scans, 14-pixel font.
767 call set_80x30 # Set 480 scans
768 call set14 # And 14-pt font
769 movw $0xdb12, %ax # VGA vertical display end
770 movw $0x5022, force_size
775 # Set the 80x60 mode (all VGA's). 480 scans, 8-pixel font.
777 call set_80x30 # Set 480 scans
778 call set_8pt # And 8-pt font
779 movw $0xdf12, %ax # VGA vertical display end
780 movw $0x503c, force_size
783 # Special hack for ThinkPad graphics
785 #ifdef CONFIG_VIDEO_GFX_HACK
786 movw $VIDEO_GFX_BIOS_AX, %ax
787 movw $VIDEO_GFX_BIOS_BX, %bx
789 movw $VIDEO_GFX_DUMMY_RESOLUTION, force_size
794 #ifdef CONFIG_VIDEO_RETAIN
796 # Store screen contents to temporary buffer.
798 cmpb $0, do_restore # Already stored?
801 testb $CAN_USE_HEAP, loadflags # Have we space for storing?
806 pushw force_size # Don't force specific size
808 call mode_params # Obtain params of current mode
810 movb %fs:(PARAM_VIDEO_LINES), %ah
811 movb %fs:(PARAM_VIDEO_COLS), %al
812 movw %ax, %bx # BX=dimensions
814 movw %ax, %cx # CX=number of characters
815 addw %ax, %ax # Calculate image size
816 addw $modelist+1024+4, %ax
817 cmpw heap_end_ptr, %ax
818 jnc sts1 # Unfortunately, out of memory
820 movw %fs:(PARAM_CURSOR_POS), %ax # Store mode params
821 leaw modelist+1024, %di
825 pushw %ds # Store the screen
826 movw video_segment, %ds
831 incb do_restore # Screen will be restored later
836 # Restore screen contents from temporary buffer.
838 cmpb $0, do_restore # Has the screen been stored?
841 call mode_params # Get parameters of current mode
842 movb %fs:(PARAM_VIDEO_LINES), %cl
843 movb %fs:(PARAM_VIDEO_COLS), %ch
844 leaw modelist+1024, %si # Screen buffer
845 lodsw # Set cursor position
857 res3: movb $0x02, %ah
861 movb %ah, %dl # DL=number of lines
862 movb $0, %ah # BX=phys. length of orig. line
864 cmpb %cl, %dl # Too many?
875 res4: cmpb %ch, %al # Too wide?
878 movb %ch, %al # AX=width of src. line
881 movw %cx, %bp # BP=width of dest. line
883 movw video_segment, %es
884 xorw %di, %di # Move the data
885 addw %bx, %bx # Convert BX and BP to _bytes_
901 #endif /* CONFIG_VIDEO_RETAIN */
903 # Write to indexed VGA register (AL=index, AH=data, DX=index reg. port)
904 outidx: outb %al, %dx
913 # Build the table of video modes (stored after the setup.S code at the
914 # `modelist' label. Each video mode record looks like:
915 # .word MODE-ID (our special mode ID (see above))
916 # .byte rows (number of rows)
917 # .byte columns (number of columns)
918 # Returns address of the end of the table in DI, the end is marked
921 movw mt_end, %di # Already filled?
925 leaw modelist, %di # Store standard modes:
926 movl $VIDEO_80x25 + 0x50190000, %eax # The 80x25 mode (ALL)
928 movb adapter, %al # CGA/MDA/HGA -- no more modes
935 movl $VIDEO_8POINT + 0x502b0000, %eax # The 80x43 EGA mode
941 mtabv: leaw vga_modes, %si # All modes for std VGA
942 movw $vga_modes_end-vga_modes, %cx
943 rep # I'm unable to use movsw as I don't know how to store a half
944 movsb # of the expression above to cx without using explicit shr.
946 cmpb $0, scanning # Mode scan requested?
952 #ifdef CONFIG_VIDEO_LOCAL
954 #endif /* CONFIG_VIDEO_LOCAL */
956 #ifdef CONFIG_VIDEO_VESA
957 call vesa_modes # Detect VESA VGA modes
958 #endif /* CONFIG_VIDEO_VESA */
960 #ifdef CONFIG_VIDEO_SVGA
961 cmpb $0, scanning # Bypass when scanning
964 call svga_modes # Detect SVGA cards & modes
966 #endif /* CONFIG_VIDEO_SVGA */
970 #ifdef CONFIG_VIDEO_COMPACT
974 cmt1: cmpw %dx, %si # Scan all modes
977 leaw modelist, %bx # Find in previous entries
982 cmpw 2(%bx), %cx # Found => don't copy this entry
988 cmt4: movsl # Copy entry
991 cmt5: addw $4, %si # Skip entry
995 #endif /* CONFIG_VIDEO_COMPACT */
997 movw $ASK_VGA, (%di) # End marker
999 mtab1: leaw modelist, %si # SI=mode list, DI=list end
1002 # Modes usable on all standard VGAs
1005 .word 0x5032 # 80x50
1007 .word 0x502b # 80x43
1009 .word 0x501c # 80x28
1011 .word 0x501e # 80x30
1013 .word 0x5022 # 80x34
1015 .word 0x503c # 80x60
1016 #ifdef CONFIG_VIDEO_GFX_HACK
1017 .word VIDEO_GFX_HACK
1018 .word VIDEO_GFX_DUMMY_RESOLUTION
1022 # Detect VESA modes.
1024 #ifdef CONFIG_VIDEO_VESA
1026 cmpb $2, adapter # VGA only
1029 movw %di, %bp # BP=original mode table end
1030 addw $0x200, %di # Buffer space
1031 movw $0x4f00, %ax # VESA Get card info call
1034 cmpw $0x004f, %ax # Successful?
1037 cmpw $0x4556, 0x200(%di)
1040 cmpw $0x4153, 0x202(%di)
1043 movw $vesa_name, card_name # Set name to "VESA VGA"
1045 lgsw 0x20e(%di), %si # GS:SI=mode list
1046 movw $128, %cx # Iteration limit
1048 # gas version 2.9.1, using BFD version 2.9.1.0.23 buggers the next inst.
1049 # XXX: lodsw %gs:(%si), %ax # Get next mode in the list
1051 cmpw $0xffff, %ax # End of the table?
1054 cmpw $0x0080, %ax # Check validity of mode ID
1057 orb %ah, %ah # Valid IDs: 0x0000-0x007f/0x0100-0x07ff
1058 jz vesan # Certain BIOSes report 0x80-0xff!
1064 movw %ax, %cx # Get mode information structure
1067 movw %cx, %bx # BX=mode number
1068 addb $VIDEO_FIRST_VESA>>8, %bh
1071 jnz vesan # Don't report errors (buggy BIOSES)
1073 movb (%di), %al # Check capabilities. We require
1074 andb $0x19, %al # a color text mode.
1078 cmpw $0xb800, 8(%di) # Standard video memory address required
1081 testb $2, (%di) # Mode characteristics supplied?
1082 movw %bx, (%di) # Store mode number
1086 movw 0x12(%di), %bx # Width
1091 movw 0x14(%di), %ax # Height
1097 cmpw $8193, %ax # Small enough for Linux console driver?
1102 vesa3: subw $0x8108, %bx # This mode has no detailed info specified,
1103 jc vesan # so it must be a standard VESA mode.
1108 movw vesa_text_mode_table(%bx), %ax
1110 vesaok: addw $4, %di # The mode is valid. Store it.
1111 vesan: loop vesa1 # Next mode. Limit exceeded => error
1112 vesae: leaw vesaer, %si
1114 movw %bp, %di # Discard already found modes.
1118 # Dimensions of standard VESA text modes
1119 vesa_text_mode_table:
1121 .byte 25, 132 # 0109
1122 .byte 43, 132 # 010A
1123 .byte 50, 132 # 010B
1124 .byte 60, 132 # 010C
1125 #endif /* CONFIG_VIDEO_VESA */
1127 # Scan for video modes. A bit dirty, but should work.
1129 movw $0x0100, %cx # Start with mode 0
1130 scm1: movb $0, %ah # Test the mode
1136 jnz scm2 # Mode not set
1138 movw $0x3c0, %dx # Test if it's a text mode
1139 movb $0x10, %al # Mode bits
1144 movb $0xce, %dl # Another set of mode bits
1150 movb $0xd4, %dl # Cursor location
1156 movw %cx, %ax # Ok, store the mode
1158 movb %gs:(0x484), %al # Number of rows
1161 movw %gs:(0x44a), %ax # Number of columns
1166 movw $0x0003, %ax # Return back to mode 3
1170 tstidx: outw %ax, %dx # OUT DX,AX and inidx
1171 inidx: outb %al, %dx # Read from indexed VGA register
1172 incw %dx # AL=index, DX=index reg port -> AL=data
1177 # Try to detect type of SVGA card and supply (usually approximate) video
1178 # mode table for it.
1180 #ifdef CONFIG_VIDEO_SVGA
1182 leaw svga_table, %si # Test all known SVGA adapters
1184 movw %ax, %bp # Default mode table
1188 lodsw # Pointer to test routine
1194 call *%ax # Call test routine
1201 movw %bp, %si # Found, copy the modes
1202 movb svga_prefix, %ah
1211 didsv: movw %si, card_name # Store pointer to card name
1214 # Table of all known SVGA cards. For each card, we store a pointer to
1215 # a table of video modes supported by the card and a pointer to a routine
1216 # used for testing of presence of the card. The video mode table is always
1217 # followed by the name of the card or the chipset.
1219 .word ati_md, ati_test
1220 .word oak_md, oak_test
1221 .word paradise_md, paradise_test
1222 .word realtek_md, realtek_test
1223 .word s3_md, s3_test
1224 .word chips_md, chips_test
1225 .word video7_md, video7_test
1226 .word cirrus5_md, cirrus5_test
1227 .word cirrus6_md, cirrus6_test
1228 .word cirrus1_md, cirrus1_test
1229 .word ahead_md, ahead_test
1230 .word everex_md, everex_test
1231 .word genoa_md, genoa_test
1232 .word trident_md, trident_test
1233 .word tseng_md, tseng_test
1236 # Test routines and mode tables:
1238 # S3 - The test algorithm was taken from the SuperProbe package
1239 # for XFree86 1.2.1. Report bugs to Christoph.Niemann@linux.org
1241 movw $0x0f35, %cx # we store some constants in cl/ch
1245 movb %al, %bh # store current CRT-register 0x38
1247 call outidx # disable writing to special regs
1248 movb %cl, %al # check whether we can write special reg 0x35
1250 movb %al, %bl # save the current value of CRT reg 0x35
1251 andb $0xf0, %al # clear bits 0-3
1253 movb %cl, %al # and write it to CRT reg 0x35
1255 call inidx # now read it back
1256 andb %ch, %al # clear the upper 4 bits
1257 jz s3_2 # the first test failed. But we have a
1259 movb %bl, %ah # second chance
1262 jmp s3_1 # do the other tests
1264 s3_2: movw %cx, %ax # load ah with 0xf and al with 0x35
1265 orb %bl, %ah # set the upper 4 bits of ah with the orig value
1266 call outidx # write ...
1267 call inidx # ... and reread
1268 andb %cl, %al # turn off the upper 4 bits
1270 movb %bl, %ah # restore old value in register 0x35
1274 cmpb %ch, %al # setting lower 4 bits was successful => bad
1275 je no_s3 # writing is allowed => this is not an S3
1277 s3_1: movw $0x4838, %ax # allow writing to special regs by putting
1278 call outidx # magic number into CRT-register 0x38
1279 movb %cl, %al # check whether we can write special reg 0x35
1288 jnz no_s3 # no, we can't write => no S3
1296 movb %bl, %ah # restore old value in register 0x35
1301 jne no_s31 # writing not possible => no S3
1303 call inidx # now get the S3 id ...
1314 no_s3: movb $0x35, %al # restore CRT register 0x35
1317 no_s31: xorw %bp, %bp # Detection failed
1318 s3rest: movb %bh, %ah
1319 movb $0x38, %al # restore old value of CRT register 0x38
1322 idS3: .byte 0x81, 0x82, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95
1323 .byte 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa8, 0xb0
1325 s3_md: .byte 0x54, 0x2b, 0x84
1326 .byte 0x55, 0x19, 0x84
1343 idati: .ascii "761295520"
1345 ati_md: .byte 0x23, 0x19, 0x84
1346 .byte 0x33, 0x2c, 0x84
1347 .byte 0x22, 0x1e, 0x64
1348 .byte 0x21, 0x19, 0x64
1349 .byte 0x58, 0x21, 0x50
1350 .byte 0x5b, 0x1e, 0x50
1372 .byte 0x22, 0x2c, 0x84
1373 .byte 0x23, 0x19, 0x84
1374 .byte 0x24, 0x1c, 0x84
1375 .byte 0x2f, 0x32, 0xa0
1376 .byte 0x32, 0x22, 0x50
1377 .byte 0x34, 0x42, 0x50
1402 .byte 0x60, 0x19, 0x84
1403 .byte 0x61, 0x32, 0x84
1405 .ascii "Chips & Technologies"
1446 nocirr: xorw %bp, %bp
1447 iscirr: movw $0x3d4, %dx
1456 .byte 0x1f, 0x19, 0x84
1457 .byte 0x20, 0x2c, 0x84
1458 .byte 0x22, 0x1e, 0x84
1459 .byte 0x31, 0x25, 0x64
1461 .ascii "Cirrus Logic 5X0"
1469 movb %al, %bl # BL=backup
1503 c5fail: xorw %bp, %bp
1504 c5done: movb $6, %al
1510 .byte 0x14, 0x19, 0x84
1511 .byte 0x54, 0x2b, 0x84
1513 .ascii "Cirrus Logic 54XX"
1516 # Cirrus Logic 64XX -- no known extra modes, but must be identified, because
1517 # it's misidentified by the Ahead test.
1522 movb %al, %bl # BL=backup
1534 call inidx # 4X, 5X, 7X and 8X are valid 64XX chip ID's.
1548 c2fail: xorw %bp, %bp
1549 c6done: movb $0x0a, %al
1556 .ascii "Cirrus Logic 64XX"
1574 evtrid: leaw trident_md, %bp
1577 noevrx: xorw %bp, %bp
1581 .byte 0x03, 0x22, 0x50
1582 .byte 0x04, 0x3c, 0x50
1583 .byte 0x07, 0x2b, 0x64
1584 .byte 0x08, 0x4b, 0x64
1585 .byte 0x0a, 0x19, 0x84
1586 .byte 0x0b, 0x2c, 0x84
1587 .byte 0x16, 0x1e, 0x50
1588 .byte 0x18, 0x1b, 0x64
1589 .byte 0x21, 0x40, 0xa0
1590 .byte 0x40, 0x1e, 0x84
1592 .ascii "Everex/Trident"
1597 leaw idgenoa, %si # Check Genoa 'clues'
1599 movb %es:(0x37), %al
1618 idgenoa: .byte 0x77, 0x00, 0x99, 0x66
1621 .byte 0x58, 0x20, 0x50
1622 .byte 0x5a, 0x2a, 0x64
1623 .byte 0x60, 0x19, 0x84
1624 .byte 0x61, 0x1d, 0x84
1625 .byte 0x62, 0x20, 0x84
1626 .byte 0x63, 0x2c, 0x84
1627 .byte 0x64, 0x3c, 0x84
1628 .byte 0x6b, 0x4f, 0x64
1629 .byte 0x72, 0x3c, 0x50
1630 .byte 0x74, 0x42, 0x50
1631 .byte 0x78, 0x4b, 0x64
1648 idoakvga: .ascii "OAK VGA "
1650 oak_md: .byte 0x4e, 0x3c, 0x50
1651 .byte 0x4f, 0x3c, 0x84
1652 .byte 0x50, 0x19, 0x84
1653 .byte 0x51, 0x2b, 0x84
1660 leaw idparadise, %si
1670 idparadise: .ascii "VGA="
1673 .byte 0x41, 0x22, 0x50
1674 .byte 0x47, 0x1c, 0x84
1675 .byte 0x55, 0x19, 0x84
1676 .byte 0x54, 0x2c, 0x84
1693 movb %al, %bl # Strange thing ... in the book this wasn't
1694 andb $0x02, %bl # necessary but it worked on my card which
1695 jz setb2 # is a trident. Without it the screen goes
1700 setb2: orb $0x02, %al
1701 clrb2: outb %al, %dx
1710 .byte 0x50, 0x1e, 0x50
1711 .byte 0x51, 0x2b, 0x50
1712 .byte 0x52, 0x3c, 0x50
1713 .byte 0x57, 0x19, 0x84
1714 .byte 0x58, 0x1e, 0x84
1715 .byte 0x59, 0x2b, 0x84
1716 .byte 0x5a, 0x3c, 0x84
1724 inb %dx, %al # Could things be this simple ! :-)
1735 isnot: xorw %bp, %bp
1739 .byte 0x26, 0x3c, 0x50
1740 .byte 0x2a, 0x28, 0x64
1741 .byte 0x23, 0x19, 0x84
1742 .byte 0x24, 0x1c, 0x84
1743 .byte 0x22, 0x2c, 0x84
1744 .byte 0x21, 0x3c, 0x84
1758 even7: movb $0x0c, %al
1783 movb $VIDEO_FIRST_V7>>8, svga_prefix # Use special mode switching
1787 .byte 0x40, 0x2b, 0x50
1788 .byte 0x43, 0x3c, 0x50
1789 .byte 0x44, 0x3c, 0x64
1790 .byte 0x41, 0x19, 0x84
1791 .byte 0x42, 0x2c, 0x84
1792 .byte 0x45, 0x1c, 0x84
1809 idrtvga: .ascii "REALTEK VGA"
1812 .byte 0x1a, 0x3c, 0x50
1813 .byte 0x1b, 0x19, 0x84
1814 .byte 0x1c, 0x1e, 0x84
1815 .byte 0x1d, 0x2b, 0x84
1816 .byte 0x1e, 0x3c, 0x84
1821 #endif /* CONFIG_VIDEO_SVGA */
1823 # User-defined local mode table (VGA only)
1824 #ifdef CONFIG_VIDEO_LOCAL
1826 leaw local_mode_table, %si
1837 # This is the table of local video modes which can be supplied manually
1838 # by the user. Each entry consists of mode ID (word) and dimensions
1839 # (byte for column count and another byte for row count). These modes
1840 # are placed before all SVGA and VESA modes and override them if table
1841 # compacting is enabled. The table must end with a zero word followed
1842 # by NUL-terminated video adapter name.
1844 .word 0x0100 # Example: 40x25
1849 #endif /* CONFIG_VIDEO_LOCAL */
1851 # Read a key and return the ASCII code in al, scan code in ah
1852 getkey: xorb %ah, %ah
1856 # Read a key with a timeout of 30 seconds.
1857 # The hardware clock is used to get the time.
1859 addb $30, %al # Wait 30 seconds
1866 again: movb $0x01, %ah
1868 jnz getkey # key pressed, so get it
1874 movb $0x20, %al # timeout, return `space'
1877 # Flush the keyboard buffer
1878 flush: movb $0x01, %ah
1888 # Print hexadecimal number.
1898 prthn: cmpb $0x0a, %al
1902 prth1: addb $0x30, %al
1905 # Print decimal number in al
1917 lt100: addb $0x30, %al
1919 skip10: movb %ah, %al
1927 pushw %es # just save all registers
1937 movl $0x13131313, %eax # memset block with 0x13
1944 movw $0x4f15, %ax # do VBE/DDC
1951 popw %di # restore all registers
1959 # VIDEO_SELECT-only variables
1960 mt_end: .word 0 # End of video mode table if built
1961 edit_buf: .space 6 # Line editor buffer
1962 card_name: .word 0 # Pointer to adapter name
1963 scanning: .byte 0 # Performing mode scan
1964 do_restore: .byte 0 # Screen contents altered during mode change
1965 svga_prefix: .byte VIDEO_FIRST_BIOS>>8 # Default prefix for BIOS modes
1966 graphic_mode: .byte 0 # Graphic mode with a linear frame buffer
1967 dac_size: .byte 6 # DAC bit depth
1970 keymsg: .ascii "Press <RETURN> to see video modes available, "
1971 .ascii "<SPACE> to continue or wait 30 secs"
1974 listhdr: .byte 0x0d, 0x0a
1975 .ascii "Mode: COLSxROWS:"
1977 crlft: .byte 0x0d, 0x0a, 0
1979 prompt: .byte 0x0d, 0x0a
1980 .asciz "Enter mode number or `scan': "
1982 unknt: .asciz "Unknown mode ID. Try again."
1984 badmdt: .ascii "You passed an undefined mode number."
1987 vesaer: .ascii "Error: Scanning of VESA modes failed. Please "
1988 .ascii "report to <mj@ucw.cz>."
1991 old_name: .asciz "CGA/MDA/HGA"
1993 ega_name: .asciz "EGA"
1995 svga_name: .ascii " "
1997 vga_name: .asciz "VGA"
1999 vesa_name: .asciz "VESA"
2001 name_bann: .asciz "Video adapter: "
2002 #endif /* CONFIG_VIDEO_SELECT */
2005 adapter: .byte 0 # Video adapter: 0=CGA/MDA/HGA,1=EGA,2=VGA
2006 video_segment: .word 0xb800 # Video memory segment
2007 force_size: .word 0 # Use this size instead of the one in BIOS vars