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 /* Enable autodetection of SVGA adapters and modes. */
15 #undef CONFIG_VIDEO_SVGA
17 /* Enable autodetection of VESA modes */
18 #define CONFIG_VIDEO_VESA
20 /* Enable compacting of mode table */
21 #define CONFIG_VIDEO_COMPACT
23 /* Retain screen contents when switching modes */
24 #define CONFIG_VIDEO_RETAIN
26 /* Enable local mode list */
27 #undef CONFIG_VIDEO_LOCAL
29 /* Force 400 scan lines for standard modes (hack to fix bad BIOS behaviour */
30 #undef CONFIG_VIDEO_400_HACK
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 */
38 /* This code uses an extended set of video mode numbers. These include:
39 * Aliases for standard modes
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.
46 #define VIDEO_FIRST_MENU 0x0000
48 /* Standard BIOS video modes (BIOS number + 0x0100) */
49 #define VIDEO_FIRST_BIOS 0x0100
51 /* VESA BIOS video modes (VESA number + 0x0200) */
52 #define VIDEO_FIRST_VESA 0x0200
54 /* Video7 special modes (BIOS number + 0x0900) */
55 #define VIDEO_FIRST_V7 0x0900
57 /* Special video modes */
58 #define VIDEO_FIRST_SPECIAL 0x0f00
59 #define VIDEO_80x25 0x0f00
60 #define VIDEO_8POINT 0x0f01
61 #define VIDEO_80x43 0x0f02
62 #define VIDEO_80x28 0x0f03
63 #define VIDEO_CURRENT_MODE 0x0f04
64 #define VIDEO_80x30 0x0f05
65 #define VIDEO_80x34 0x0f06
66 #define VIDEO_80x60 0x0f07
67 #define VIDEO_GFX_HACK 0x0f08
68 #define VIDEO_LAST_SPECIAL 0x0f09
70 /* Video modes given by resolution */
71 #define VIDEO_FIRST_RESOLUTION 0x1000
73 /* The "recalculate timings" flag */
74 #define VIDEO_RECALC 0x8000
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
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
100 /* Define DO_STORE according to CONFIG_VIDEO_RETAIN */
101 #ifdef CONFIG_VIDEO_RETAIN
102 #define DO_STORE call store_screen
105 #endif /* CONFIG_VIDEO_RETAIN */
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
112 pushw %cs # DS is equal to CS
114 pushw %cs # ES is equal to CS
117 movw %ax, %gs # GS is zero
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
125 call mode_set # Set the mode
129 leaw badmdt, %si # Invalid mode ID
133 #endif /* CONFIG_VIDEO_IGNORE_BAD_MODE */
136 #ifdef CONFIG_VIDEO_RETAIN
137 call restore_screen # Restore screen contents
138 #endif /* CONFIG_VIDEO_RETAIN */
140 #endif /* CONFIG_VIDEO_SELECT */
141 call mode_params # Store mode parameters
142 popw %ds # Restore original DS
145 # Detect if we have CGA, MDA, EGA or VGA and pass it to the kernel.
147 movb $0, %fs:(PARAM_HAVE_VGA)
148 movb $0x12, %ah # Check EGA/VGA
151 movw %bx, %fs:(PARAM_VIDEO_EGA_BX) # Identifies EGA to the kernel
152 cmpb $0x10, %bl # No, it's a CGA/MDA/HGA card.
156 movw $0x1a00, %ax # Check EGA or VGA?
158 cmpb $0x1a, %al # 1a means VGA...
159 jne basret # anything else is EGA.
161 incb %fs:(PARAM_HAVE_VGA) # We've detected a VGA
165 # Store the video mode parameters for later usage by the kernel.
166 # This is done by asking the BIOS except for the rows/columns
167 # parameters in the default 80x25 mode -- these are set directly,
168 # because some very obscure BIOSes supply insane values.
170 #ifdef CONFIG_VIDEO_SELECT
171 cmpb $0, graphic_mode
174 movb $0x03, %ah # Read cursor position
177 movw %dx, %fs:(PARAM_CURSOR_POS)
178 movb $0x0f, %ah # Read page/mode/width
180 movw %bx, %fs:(PARAM_VIDEO_PAGE)
181 movw %ax, %fs:(PARAM_VIDEO_MODE) # Video mode and screen width
182 cmpb $0x7, %al # MDA/HGA => segment differs
185 movw $0xb000, video_segment
186 mopar0: movw %gs:(0x485), %ax # Font size
187 movw %ax, %fs:(PARAM_FONT_POINTS) # (valid only on EGA/VGA)
188 movw force_size, %ax # Forced size?
192 movb %ah, %fs:(PARAM_VIDEO_COLS)
193 movb %al, %fs:(PARAM_VIDEO_LINES)
196 mopar1: movb $25, %al
197 cmpb $0, adapter # If we are on CGA/MDA/HGA, the
198 jz mopar2 # screen must have 25 lines.
200 movb %gs:(0x484), %al # On EGA/VGA, use the EGA+ BIOS
201 incb %al # location of max lines.
202 mopar2: movb %al, %fs:(PARAM_VIDEO_LINES)
205 #ifdef CONFIG_VIDEO_SELECT
206 # Fetching of VESA frame buffer parameters
208 leaw modelist+1024, %di
209 movb $0x23, %fs:(PARAM_HAVE_VGA)
211 movw %ax, %fs:(PARAM_LFB_LINELENGTH)
213 movw %ax, %fs:(PARAM_LFB_WIDTH)
215 movw %ax, %fs:(PARAM_LFB_HEIGHT)
218 movw %ax, %fs:(PARAM_LFB_DEPTH)
221 movw %ax, %fs:(PARAM_LFB_PAGES)
223 movl %eax, %fs:(PARAM_LFB_BASE)
225 movl %eax, %fs:(PARAM_LFB_COLORS)
227 movl %eax, %fs:(PARAM_LFB_COLORS+4)
229 movw %ax, %fs:(PARAM_VESA_ATTRIB)
232 leaw modelist+1024, %di
237 movl %eax, %fs:(PARAM_LFB_SIZE)
239 # store mode capabilities
241 movl %eax, %fs:(PARAM_CAPABILITIES)
243 # switching the DAC to 8-bit is for <= 8 bpp only
244 movw %fs:(PARAM_LFB_DEPTH), %ax
248 # get DAC switching capability
254 # attempt to switch DAC to 8-bit
260 movb %bh, dac_size # store actual DAC size
263 # set color size to DAC size
265 movb %al, %fs:(PARAM_LFB_COLORS+0)
266 movb %al, %fs:(PARAM_LFB_COLORS+2)
267 movb %al, %fs:(PARAM_LFB_COLORS+4)
268 movb %al, %fs:(PARAM_LFB_COLORS+6)
270 # set color offsets to 0
271 movb $0, %fs:(PARAM_LFB_COLORS+1)
272 movb $0, %fs:(PARAM_LFB_COLORS+3)
273 movb $0, %fs:(PARAM_LFB_COLORS+5)
274 movb $0, %fs:(PARAM_LFB_COLORS+7)
277 # get protected mode interface informations
285 movw %es, %fs:(PARAM_VESAPM_SEG)
286 movw %di, %fs:(PARAM_VESAPM_OFF)
289 # The video mode menu
291 leaw keymsg, %si # "Return/Space/Timeout" message
296 cmpb $0x0d, %al # ENTER ?
297 je listm # yes - manual mode selection
299 cmpb $0x20, %al # SPACE ?
300 je defmd1 # no - repeat
305 defmd1: ret # No mode chosen? Default 80x25
307 listm: call mode_table # List mode table
308 listm0: leaw name_bann, %si # Print adapter name
329 leaw listhdr, %si # Table header
331 movb $0x30, %dl # DL holds mode number
333 lm1: cmpw $ASK_VGA, (%si) # End?
336 movb %dl, %al # Menu selection number
344 movb $0x78, %al # the letter 'x'
347 call prtdec # Columns
348 movb $0x0d, %al # New line
352 incb %dl # Next character
359 lm2: leaw prompt, %si # Mode prompt
361 leaw edit_buf, %di # Editor buffer
363 cmpb $0x0d, %al # Enter?
366 cmpb $0x08, %al # Backspace?
369 cmpb $0x20, %al # Printable?
372 cmpw $edit_buf+4, %di # Enough space?
379 lmbs: cmpw $edit_buf, %di # Backspace
390 lment: movb $0, (%di)
394 cmpb $0, (%si) # Empty string = default mode
397 cmpb $0, 1(%si) # One character = menu selection
400 cmpw $0x6373, (%si) # "scan" => mode scanning
406 lmhx: xorw %bx, %bx # Else => mode ID in hex
429 lmuse1: movw %bx, %ax
432 mnusel: lodsb # Menu selection
443 subb $0x61-0x30-10, %al
450 lmbad: leaw unknt, %si
453 lmscan: cmpb $0, adapter # Scanning only on EGA/VGA
456 movw $0, mt_end # Scanning of modes is
457 movb $1, scanning # done as new autodetection.
462 # Additional parts of mode_set... (relative jumps, you know)
463 setv7: # Video7 extended modes
465 subb $VIDEO_FIRST_V7>>8, %bh
471 _setrec: jmp setrec # Ugly...
472 _set_80x25: jmp set_80x25
474 # Aliases for backward compatibility.
476 movw $VIDEO_80x25, %ax
480 movb $VIDEO_8POINT-VIDEO_FIRST_SPECIAL, %al
482 jnz setbad # Fall-through!
484 # Setting of user mode (AX=mode ID) => CF=success
486 movw %ax, %fs:(0x01fa) # Store mode for use in acpi_wakeup.S
491 testb $VIDEO_RECALC>>8, %ah
494 cmpb $VIDEO_FIRST_RESOLUTION>>8, %ah
497 cmpb $VIDEO_FIRST_SPECIAL>>8, %ah
500 cmpb $VIDEO_FIRST_V7>>8, %ah
503 cmpb $VIDEO_FIRST_VESA>>8, %ah
513 movb $0, do_restore # The screen needn't be restored
518 subb $VIDEO_FIRST_VESA>>8, %bh
519 movw $0x4f02, %ax # VESA BIOS mode set call
521 cmpw $0x004f, %ax # AL=4f if implemented
522 jnz setbad # AH=0 if OK
529 int $0x10 # Standard BIOS mode set call
531 movb $0x0f, %ah # Check if really set
540 setspc: xorb %bh, %bh # Set special mode
541 cmpb $VIDEO_LAST_SPECIAL-VIDEO_FIRST_SPECIAL, %bl
548 orb %al, %al # 80x25 is an exception
551 pushw %bx # Set mode chosen from menu
552 call mode_table # Build the mode table
559 movw (%si), %ax # Fetch mode ID
562 setres: pushw %bx # Set mode chosen by resolution
567 cmpw $ASK_VGA, %ax # End of the list?
574 movw -4(%si), %ax # Fetch mode ID
578 #ifdef CONFIG_FIRMWARE_EDID
579 leaw modelist+1024, %di
586 movw %ax, vbe_version
588 leaw modelist+1024, %di
589 subb $VIDEO_FIRST_VESA>>8, %bh
590 movw %bx, %cx # Get mode information structure
593 addb $VIDEO_FIRST_VESA>>8, %bh
597 movb (%di), %al # Check capabilities.
600 jz setvesa # This is a text mode
602 movb (%di), %al # Check capabilities.
605 jnz _setbad # Doh! No linear frame buffer.
607 subb $VIDEO_FIRST_VESA>>8, %bh
608 orw $0x4000, %bx # Use linear frame buffer
609 movw $0x4f02, %ax # VESA BIOS mode set call
611 cmpw $0x004f, %ax # AL=4f if implemented
612 jnz _setbad # AH=0 if OK
614 movb $1, graphic_mode # flag graphic mode
615 movb $0, do_restore # no screen restore
619 _setbad: jmp setbad # Ugly...
621 # Recalculate vertical display end registers -- this fixes various
622 # inconsistencies of extended modes on many adapters. Called when
623 # the VIDEO_RECALC flag is set in the mode ID.
625 setrec: subb $VIDEO_RECALC>>8, %ah # Set the base mode
629 movw %gs:(0x485), %ax # Font size in pixels
630 movb %gs:(0x484), %bl # Number of rows
632 mulb %bl # Number of visible
633 decw %ax # scan lines - 1
636 movb $0x12, %al # Lower 8 bits
639 movb $0x07, %al # Bits 8 and 9 in the overflow register
649 rct2: movb $0x07, %al
654 # Table of routines for setting of the special modes.
666 # Set the 80x25 mode. If already set, do nothing.
668 movw $0x5019, force_size # Override possibly broken BIOS
670 #ifdef CONFIG_VIDEO_400_HACK
671 movw $0x1202, %ax # Force 400 scan lines
675 movb $0x0f, %ah # Get current mode ID
677 cmpw $0x5007, %ax # Mode 7 (80x25 mono) is the only one available
678 jz st80 # on CGA/MDA/HGA and is also available on EGAM
680 cmpw $0x5003, %ax # Unknown mode, force 80x25 color
683 st80: cmpb $0, adapter # CGA/MDA/HGA => mode 3/7 is always 80x25
686 movb %gs:(0x0484), %al # This is EGA+ -- beware of 80x50 etc.
687 orb %al, %al # Some buggy BIOS'es set 0 rows
690 cmpb $24, %al # It's hopefully correct
692 #endif /* CONFIG_VIDEO_400_HACK */
694 movw $0x0003, %ax # Forced set
699 # Set the 80x50/80x43 8-pixel mode. Simple BIOS calls.
702 call use_80x25 # The base is 80x25
704 movw $0x1112, %ax # Use 8x8 font
707 movw $0x1200, %ax # Use alternate print screen
710 movw $0x1201, %ax # Turn off cursor emulation
713 movb $0x01, %ah # Define cursor scan lines 6-7
720 # Set the 80x28 mode. This mode works on all VGA's, because it's a standard
721 # 80x25 mode with 14-point fonts instead of 16-point.
724 call use_80x25 # The base is 80x25
725 set14: movw $0x1111, %ax # Use 9x14 font
728 movb $0x01, %ah # Define cursor scan lines 11-12
734 # Set the 80x43 mode. This mode is works on all VGA's.
735 # It's a 350-scanline mode with 8-pixel font.
738 movw $0x1201, %ax # Set 350 scans
741 movw $0x0003, %ax # Reset video mode
743 jmp set_8pt # Use 8-pixel font
745 # Set the 80x30 mode (all VGA's). 480 scanlines, 16-pixel font.
747 call use_80x25 # Start with real 80x25
749 movw $0x3cc, %dx # Get CRTC port
752 rorb %al # Mono or color?
756 set48a: movw $0x0c11, %ax # Vertical sync end (also unlocks CR0-7)
758 movw $0x0b06, %ax # Vertical total
760 movw $0x3e07, %ax # (Vertical) overflow
762 movw $0xea10, %ax # Vertical sync start
764 movw $0xdf12, %ax # Vertical display end
766 movw $0xe715, %ax # Vertical blank start
768 movw $0x0416, %ax # Vertical blank end
771 movb $0xcc, %dl # Misc output register (read)
773 movb $0xc2, %dl # (write)
774 andb $0x0d, %al # Preserve clock select bits and color bit
775 orb $0xe2, %al # Set correct sync polarity
778 movw $0x501e, force_size
782 # Set the 80x34 mode (all VGA's). 480 scans, 14-pixel font.
784 call set_80x30 # Set 480 scans
785 call set14 # And 14-pt font
786 movw $0xdb12, %ax # VGA vertical display end
787 movw $0x5022, force_size
792 # Set the 80x60 mode (all VGA's). 480 scans, 8-pixel font.
794 call set_80x30 # Set 480 scans
795 call set_8pt # And 8-pt font
796 movw $0xdf12, %ax # VGA vertical display end
797 movw $0x503c, force_size
800 # Special hack for ThinkPad graphics
802 #ifdef CONFIG_VIDEO_GFX_HACK
803 movw $VIDEO_GFX_BIOS_AX, %ax
804 movw $VIDEO_GFX_BIOS_BX, %bx
806 movw $VIDEO_GFX_DUMMY_RESOLUTION, force_size
811 #ifdef CONFIG_VIDEO_RETAIN
813 # Store screen contents to temporary buffer.
815 cmpb $0, do_restore # Already stored?
818 testb $CAN_USE_HEAP, loadflags # Have we space for storing?
823 pushw force_size # Don't force specific size
825 call mode_params # Obtain params of current mode
827 movb %fs:(PARAM_VIDEO_LINES), %ah
828 movb %fs:(PARAM_VIDEO_COLS), %al
829 movw %ax, %bx # BX=dimensions
831 movw %ax, %cx # CX=number of characters
832 addw %ax, %ax # Calculate image size
833 addw $modelist+1024+4, %ax
834 cmpw heap_end_ptr, %ax
835 jnc sts1 # Unfortunately, out of memory
837 movw %fs:(PARAM_CURSOR_POS), %ax # Store mode params
838 leaw modelist+1024, %di
842 pushw %ds # Store the screen
843 movw video_segment, %ds
848 incb do_restore # Screen will be restored later
853 # Restore screen contents from temporary buffer.
855 cmpb $0, do_restore # Has the screen been stored?
858 call mode_params # Get parameters of current mode
859 movb %fs:(PARAM_VIDEO_LINES), %cl
860 movb %fs:(PARAM_VIDEO_COLS), %ch
861 leaw modelist+1024, %si # Screen buffer
862 lodsw # Set cursor position
874 res3: movb $0x02, %ah
878 movb %ah, %dl # DL=number of lines
879 movb $0, %ah # BX=phys. length of orig. line
881 cmpb %cl, %dl # Too many?
892 res4: cmpb %ch, %al # Too wide?
895 movb %ch, %al # AX=width of src. line
898 movw %cx, %bp # BP=width of dest. line
900 movw video_segment, %es
901 xorw %di, %di # Move the data
902 addw %bx, %bx # Convert BX and BP to _bytes_
918 #endif /* CONFIG_VIDEO_RETAIN */
920 # Write to indexed VGA register (AL=index, AH=data, DX=index reg. port)
921 outidx: outb %al, %dx
930 # Build the table of video modes (stored after the setup.S code at the
931 # `modelist' label. Each video mode record looks like:
932 # .word MODE-ID (our special mode ID (see above))
933 # .byte rows (number of rows)
934 # .byte columns (number of columns)
935 # Returns address of the end of the table in DI, the end is marked
938 movw mt_end, %di # Already filled?
942 leaw modelist, %di # Store standard modes:
943 movl $VIDEO_80x25 + 0x50190000, %eax # The 80x25 mode (ALL)
945 movb adapter, %al # CGA/MDA/HGA -- no more modes
952 movl $VIDEO_8POINT + 0x502b0000, %eax # The 80x43 EGA mode
958 mtabv: leaw vga_modes, %si # All modes for std VGA
959 movw $vga_modes_end-vga_modes, %cx
960 rep # I'm unable to use movsw as I don't know how to store a half
961 movsb # of the expression above to cx without using explicit shr.
963 cmpb $0, scanning # Mode scan requested?
969 #ifdef CONFIG_VIDEO_LOCAL
971 #endif /* CONFIG_VIDEO_LOCAL */
973 #ifdef CONFIG_VIDEO_VESA
974 call vesa_modes # Detect VESA VGA modes
975 #endif /* CONFIG_VIDEO_VESA */
977 #ifdef CONFIG_VIDEO_SVGA
978 cmpb $0, scanning # Bypass when scanning
981 call svga_modes # Detect SVGA cards & modes
983 #endif /* CONFIG_VIDEO_SVGA */
987 #ifdef CONFIG_VIDEO_COMPACT
991 cmt1: cmpw %dx, %si # Scan all modes
994 leaw modelist, %bx # Find in previous entries
999 cmpw 2(%bx), %cx # Found => don't copy this entry
1005 cmt4: movsl # Copy entry
1008 cmt5: addw $4, %si # Skip entry
1012 #endif /* CONFIG_VIDEO_COMPACT */
1014 movw $ASK_VGA, (%di) # End marker
1016 mtab1: leaw modelist, %si # SI=mode list, DI=list end
1019 # Modes usable on all standard VGAs
1022 .word 0x5032 # 80x50
1024 .word 0x502b # 80x43
1026 .word 0x501c # 80x28
1028 .word 0x501e # 80x30
1030 .word 0x5022 # 80x34
1032 .word 0x503c # 80x60
1033 #ifdef CONFIG_VIDEO_GFX_HACK
1034 .word VIDEO_GFX_HACK
1035 .word VIDEO_GFX_DUMMY_RESOLUTION
1039 # Detect VESA modes.
1041 #ifdef CONFIG_VIDEO_VESA
1043 cmpb $2, adapter # VGA only
1046 movw %di, %bp # BP=original mode table end
1047 addw $0x200, %di # Buffer space
1048 movw $0x4f00, %ax # VESA Get card info call
1051 cmpw $0x004f, %ax # Successful?
1054 cmpw $0x4556, 0x200(%di)
1057 cmpw $0x4153, 0x202(%di)
1060 movw $vesa_name, card_name # Set name to "VESA VGA"
1062 lgsw 0x20e(%di), %si # GS:SI=mode list
1063 movw $128, %cx # Iteration limit
1065 # gas version 2.9.1, using BFD version 2.9.1.0.23 buggers the next inst.
1066 # XXX: lodsw %gs:(%si), %ax # Get next mode in the list
1068 cmpw $0xffff, %ax # End of the table?
1071 cmpw $0x0080, %ax # Check validity of mode ID
1074 orb %ah, %ah # Valid IDs: 0x0000-0x007f/0x0100-0x07ff
1075 jz vesan # Certain BIOSes report 0x80-0xff!
1081 movw %ax, %cx # Get mode information structure
1084 movw %cx, %bx # BX=mode number
1085 addb $VIDEO_FIRST_VESA>>8, %bh
1088 jnz vesan # Don't report errors (buggy BIOSES)
1090 movb (%di), %al # Check capabilities. We require
1091 andb $0x19, %al # a color text mode.
1095 cmpw $0xb800, 8(%di) # Standard video memory address required
1098 testb $2, (%di) # Mode characteristics supplied?
1099 movw %bx, (%di) # Store mode number
1103 movw 0x12(%di), %bx # Width
1108 movw 0x14(%di), %ax # Height
1114 cmpw $8193, %ax # Small enough for Linux console driver?
1119 vesa3: subw $0x8108, %bx # This mode has no detailed info specified,
1120 jc vesan # so it must be a standard VESA mode.
1125 movw vesa_text_mode_table(%bx), %ax
1127 vesaok: addw $4, %di # The mode is valid. Store it.
1128 vesan: loop vesa1 # Next mode. Limit exceeded => error
1129 vesae: leaw vesaer, %si
1131 movw %bp, %di # Discard already found modes.
1135 # Dimensions of standard VESA text modes
1136 vesa_text_mode_table:
1138 .byte 25, 132 # 0109
1139 .byte 43, 132 # 010A
1140 .byte 50, 132 # 010B
1141 .byte 60, 132 # 010C
1142 #endif /* CONFIG_VIDEO_VESA */
1144 # Scan for video modes. A bit dirty, but should work.
1146 movw $0x0100, %cx # Start with mode 0
1147 scm1: movb $0, %ah # Test the mode
1153 jnz scm2 # Mode not set
1155 movw $0x3c0, %dx # Test if it's a text mode
1156 movb $0x10, %al # Mode bits
1161 movb $0xce, %dl # Another set of mode bits
1167 movb $0xd4, %dl # Cursor location
1173 movw %cx, %ax # Ok, store the mode
1175 movb %gs:(0x484), %al # Number of rows
1178 movw %gs:(0x44a), %ax # Number of columns
1183 movw $0x0003, %ax # Return back to mode 3
1187 tstidx: outw %ax, %dx # OUT DX,AX and inidx
1188 inidx: outb %al, %dx # Read from indexed VGA register
1189 incw %dx # AL=index, DX=index reg port -> AL=data
1194 # Try to detect type of SVGA card and supply (usually approximate) video
1195 # mode table for it.
1197 #ifdef CONFIG_VIDEO_SVGA
1199 leaw svga_table, %si # Test all known SVGA adapters
1201 movw %ax, %bp # Default mode table
1205 lodsw # Pointer to test routine
1211 call *%ax # Call test routine
1218 movw %bp, %si # Found, copy the modes
1219 movb svga_prefix, %ah
1228 didsv: movw %si, card_name # Store pointer to card name
1231 # Table of all known SVGA cards. For each card, we store a pointer to
1232 # a table of video modes supported by the card and a pointer to a routine
1233 # used for testing of presence of the card. The video mode table is always
1234 # followed by the name of the card or the chipset.
1236 .word ati_md, ati_test
1237 .word oak_md, oak_test
1238 .word paradise_md, paradise_test
1239 .word realtek_md, realtek_test
1240 .word s3_md, s3_test
1241 .word chips_md, chips_test
1242 .word video7_md, video7_test
1243 .word cirrus5_md, cirrus5_test
1244 .word cirrus6_md, cirrus6_test
1245 .word cirrus1_md, cirrus1_test
1246 .word ahead_md, ahead_test
1247 .word everex_md, everex_test
1248 .word genoa_md, genoa_test
1249 .word trident_md, trident_test
1250 .word tseng_md, tseng_test
1253 # Test routines and mode tables:
1255 # S3 - The test algorithm was taken from the SuperProbe package
1256 # for XFree86 1.2.1. Report bugs to Christoph.Niemann@linux.org
1258 movw $0x0f35, %cx # we store some constants in cl/ch
1262 movb %al, %bh # store current CRT-register 0x38
1264 call outidx # disable writing to special regs
1265 movb %cl, %al # check whether we can write special reg 0x35
1267 movb %al, %bl # save the current value of CRT reg 0x35
1268 andb $0xf0, %al # clear bits 0-3
1270 movb %cl, %al # and write it to CRT reg 0x35
1272 call inidx # now read it back
1273 andb %ch, %al # clear the upper 4 bits
1274 jz s3_2 # the first test failed. But we have a
1276 movb %bl, %ah # second chance
1279 jmp s3_1 # do the other tests
1281 s3_2: movw %cx, %ax # load ah with 0xf and al with 0x35
1282 orb %bl, %ah # set the upper 4 bits of ah with the orig value
1283 call outidx # write ...
1284 call inidx # ... and reread
1285 andb %cl, %al # turn off the upper 4 bits
1287 movb %bl, %ah # restore old value in register 0x35
1291 cmpb %ch, %al # setting lower 4 bits was successful => bad
1292 je no_s3 # writing is allowed => this is not an S3
1294 s3_1: movw $0x4838, %ax # allow writing to special regs by putting
1295 call outidx # magic number into CRT-register 0x38
1296 movb %cl, %al # check whether we can write special reg 0x35
1305 jnz no_s3 # no, we can't write => no S3
1313 movb %bl, %ah # restore old value in register 0x35
1318 jne no_s31 # writing not possible => no S3
1320 call inidx # now get the S3 id ...
1331 no_s3: movb $0x35, %al # restore CRT register 0x35
1334 no_s31: xorw %bp, %bp # Detection failed
1335 s3rest: movb %bh, %ah
1336 movb $0x38, %al # restore old value of CRT register 0x38
1339 idS3: .byte 0x81, 0x82, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95
1340 .byte 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa8, 0xb0
1342 s3_md: .byte 0x54, 0x2b, 0x84
1343 .byte 0x55, 0x19, 0x84
1360 idati: .ascii "761295520"
1362 ati_md: .byte 0x23, 0x19, 0x84
1363 .byte 0x33, 0x2c, 0x84
1364 .byte 0x22, 0x1e, 0x64
1365 .byte 0x21, 0x19, 0x64
1366 .byte 0x58, 0x21, 0x50
1367 .byte 0x5b, 0x1e, 0x50
1389 .byte 0x22, 0x2c, 0x84
1390 .byte 0x23, 0x19, 0x84
1391 .byte 0x24, 0x1c, 0x84
1392 .byte 0x2f, 0x32, 0xa0
1393 .byte 0x32, 0x22, 0x50
1394 .byte 0x34, 0x42, 0x50
1419 .byte 0x60, 0x19, 0x84
1420 .byte 0x61, 0x32, 0x84
1422 .ascii "Chips & Technologies"
1463 nocirr: xorw %bp, %bp
1464 iscirr: movw $0x3d4, %dx
1473 .byte 0x1f, 0x19, 0x84
1474 .byte 0x20, 0x2c, 0x84
1475 .byte 0x22, 0x1e, 0x84
1476 .byte 0x31, 0x25, 0x64
1478 .ascii "Cirrus Logic 5X0"
1486 movb %al, %bl # BL=backup
1520 c5fail: xorw %bp, %bp
1521 c5done: movb $6, %al
1527 .byte 0x14, 0x19, 0x84
1528 .byte 0x54, 0x2b, 0x84
1530 .ascii "Cirrus Logic 54XX"
1533 # Cirrus Logic 64XX -- no known extra modes, but must be identified, because
1534 # it's misidentified by the Ahead test.
1539 movb %al, %bl # BL=backup
1551 call inidx # 4X, 5X, 7X and 8X are valid 64XX chip ID's.
1565 c2fail: xorw %bp, %bp
1566 c6done: movb $0x0a, %al
1573 .ascii "Cirrus Logic 64XX"
1591 evtrid: leaw trident_md, %bp
1594 noevrx: xorw %bp, %bp
1598 .byte 0x03, 0x22, 0x50
1599 .byte 0x04, 0x3c, 0x50
1600 .byte 0x07, 0x2b, 0x64
1601 .byte 0x08, 0x4b, 0x64
1602 .byte 0x0a, 0x19, 0x84
1603 .byte 0x0b, 0x2c, 0x84
1604 .byte 0x16, 0x1e, 0x50
1605 .byte 0x18, 0x1b, 0x64
1606 .byte 0x21, 0x40, 0xa0
1607 .byte 0x40, 0x1e, 0x84
1609 .ascii "Everex/Trident"
1614 leaw idgenoa, %si # Check Genoa 'clues'
1616 movb %es:(0x37), %al
1635 idgenoa: .byte 0x77, 0x00, 0x99, 0x66
1638 .byte 0x58, 0x20, 0x50
1639 .byte 0x5a, 0x2a, 0x64
1640 .byte 0x60, 0x19, 0x84
1641 .byte 0x61, 0x1d, 0x84
1642 .byte 0x62, 0x20, 0x84
1643 .byte 0x63, 0x2c, 0x84
1644 .byte 0x64, 0x3c, 0x84
1645 .byte 0x6b, 0x4f, 0x64
1646 .byte 0x72, 0x3c, 0x50
1647 .byte 0x74, 0x42, 0x50
1648 .byte 0x78, 0x4b, 0x64
1665 idoakvga: .ascii "OAK VGA "
1667 oak_md: .byte 0x4e, 0x3c, 0x50
1668 .byte 0x4f, 0x3c, 0x84
1669 .byte 0x50, 0x19, 0x84
1670 .byte 0x51, 0x2b, 0x84
1677 leaw idparadise, %si
1687 idparadise: .ascii "VGA="
1690 .byte 0x41, 0x22, 0x50
1691 .byte 0x47, 0x1c, 0x84
1692 .byte 0x55, 0x19, 0x84
1693 .byte 0x54, 0x2c, 0x84
1710 movb %al, %bl # Strange thing ... in the book this wasn't
1711 andb $0x02, %bl # necessary but it worked on my card which
1712 jz setb2 # is a trident. Without it the screen goes
1717 setb2: orb $0x02, %al
1718 clrb2: outb %al, %dx
1727 .byte 0x50, 0x1e, 0x50
1728 .byte 0x51, 0x2b, 0x50
1729 .byte 0x52, 0x3c, 0x50
1730 .byte 0x57, 0x19, 0x84
1731 .byte 0x58, 0x1e, 0x84
1732 .byte 0x59, 0x2b, 0x84
1733 .byte 0x5a, 0x3c, 0x84
1741 inb %dx, %al # Could things be this simple ! :-)
1752 isnot: xorw %bp, %bp
1756 .byte 0x26, 0x3c, 0x50
1757 .byte 0x2a, 0x28, 0x64
1758 .byte 0x23, 0x19, 0x84
1759 .byte 0x24, 0x1c, 0x84
1760 .byte 0x22, 0x2c, 0x84
1761 .byte 0x21, 0x3c, 0x84
1775 even7: movb $0x0c, %al
1800 movb $VIDEO_FIRST_V7>>8, svga_prefix # Use special mode switching
1804 .byte 0x40, 0x2b, 0x50
1805 .byte 0x43, 0x3c, 0x50
1806 .byte 0x44, 0x3c, 0x64
1807 .byte 0x41, 0x19, 0x84
1808 .byte 0x42, 0x2c, 0x84
1809 .byte 0x45, 0x1c, 0x84
1826 idrtvga: .ascii "REALTEK VGA"
1829 .byte 0x1a, 0x3c, 0x50
1830 .byte 0x1b, 0x19, 0x84
1831 .byte 0x1c, 0x1e, 0x84
1832 .byte 0x1d, 0x2b, 0x84
1833 .byte 0x1e, 0x3c, 0x84
1838 #endif /* CONFIG_VIDEO_SVGA */
1840 # User-defined local mode table (VGA only)
1841 #ifdef CONFIG_VIDEO_LOCAL
1843 leaw local_mode_table, %si
1854 # This is the table of local video modes which can be supplied manually
1855 # by the user. Each entry consists of mode ID (word) and dimensions
1856 # (byte for column count and another byte for row count). These modes
1857 # are placed before all SVGA and VESA modes and override them if table
1858 # compacting is enabled. The table must end with a zero word followed
1859 # by NUL-terminated video adapter name.
1861 .word 0x0100 # Example: 40x25
1866 #endif /* CONFIG_VIDEO_LOCAL */
1868 # Read a key and return the ASCII code in al, scan code in ah
1869 getkey: xorb %ah, %ah
1873 # Read a key with a timeout of 30 seconds.
1874 # The hardware clock is used to get the time.
1876 addb $30, %al # Wait 30 seconds
1883 again: movb $0x01, %ah
1885 jnz getkey # key pressed, so get it
1891 movb $0x20, %al # timeout, return `space'
1894 # Flush the keyboard buffer
1895 flush: movb $0x01, %ah
1905 # Print hexadecimal number.
1915 prthn: cmpb $0x0a, %al
1919 prth1: addb $0x30, %al
1922 # Print decimal number in al
1934 lt100: addb $0x30, %al
1936 skip10: movb %ah, %al
1944 #ifdef CONFIG_FIRMWARE_EDID
1945 pushw %es # just save all registers
1955 movl $0x13131313, %eax # memset block with 0x13
1962 cmpw $0x0200, vbe_version # only do EDID on >= VBE2.0
1966 xorw %di, %di # Report Capability
1968 popw %es # ES:DI must be 0:0
1973 popw %es # restore ES
1975 cmpb $0x00, %ah # call successful
1978 cmpb $0x4f, %al # function supported
1981 movw $0x4f15, %ax # do VBE/DDC
1989 popw %di # restore all registers
1998 # VIDEO_SELECT-only variables
1999 mt_end: .word 0 # End of video mode table if built
2000 edit_buf: .space 6 # Line editor buffer
2001 card_name: .word 0 # Pointer to adapter name
2002 scanning: .byte 0 # Performing mode scan
2003 do_restore: .byte 0 # Screen contents altered during mode change
2004 svga_prefix: .byte VIDEO_FIRST_BIOS>>8 # Default prefix for BIOS modes
2005 graphic_mode: .byte 0 # Graphic mode with a linear frame buffer
2006 dac_size: .byte 6 # DAC bit depth
2007 vbe_version: .word 0 # VBE bios version
2010 keymsg: .ascii "Press <RETURN> to see video modes available, "
2011 .ascii "<SPACE> to continue or wait 30 secs"
2014 listhdr: .byte 0x0d, 0x0a
2015 .ascii "Mode: COLSxROWS:"
2017 crlft: .byte 0x0d, 0x0a, 0
2019 prompt: .byte 0x0d, 0x0a
2020 .asciz "Enter mode number or `scan': "
2022 unknt: .asciz "Unknown mode ID. Try again."
2024 badmdt: .ascii "You passed an undefined mode number."
2027 vesaer: .ascii "Error: Scanning of VESA modes failed. Please "
2028 .ascii "report to <mj@ucw.cz>."
2031 old_name: .asciz "CGA/MDA/HGA"
2033 ega_name: .asciz "EGA"
2035 svga_name: .ascii " "
2037 vga_name: .asciz "VGA"
2039 vesa_name: .asciz "VESA"
2041 name_bann: .asciz "Video adapter: "
2042 #endif /* CONFIG_VIDEO_SELECT */
2045 adapter: .byte 0 # Video adapter: 0=CGA/MDA/HGA,1=EGA,2=VGA
2046 video_segment: .word 0xb800 # Video memory segment
2047 force_size: .word 0 # Use this size instead of the one in BIOS vars