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
100 #define PARAM_CAPABILITIES 0x36
102 /* Define DO_STORE according to CONFIG_VIDEO_RETAIN */
103 #ifdef CONFIG_VIDEO_RETAIN
104 #define DO_STORE call store_screen
107 #endif /* CONFIG_VIDEO_RETAIN */
109 # This is the main entry point called by setup.S
110 # %ds *must* be pointing to the bootsector
111 video: pushw %ds # We use different segments
112 pushw %ds # FS contains original DS
114 pushw %cs # DS is equal to CS
116 pushw %cs # ES is equal to CS
119 movw %ax, %gs # GS is zero
121 call basic_detect # Basic adapter type testing (EGA/VGA/MDA/CGA)
122 #ifdef CONFIG_VIDEO_SELECT
123 movw %fs:(0x01fa), %ax # User selected video mode
124 cmpw $ASK_VGA, %ax # Bring up the menu
127 call mode_set # Set the mode
131 leaw badmdt, %si # Invalid mode ID
135 #endif /* CONFIG_VIDEO_IGNORE_BAD_MODE */
138 #ifdef CONFIG_VIDEO_RETAIN
139 call restore_screen # Restore screen contents
140 #endif /* CONFIG_VIDEO_RETAIN */
142 #endif /* CONFIG_VIDEO_SELECT */
143 call mode_params # Store mode parameters
144 popw %ds # Restore original DS
147 # Detect if we have CGA, MDA, EGA or VGA and pass it to the kernel.
149 movb $0, %fs:(PARAM_HAVE_VGA)
150 movb $0x12, %ah # Check EGA/VGA
153 movw %bx, %fs:(PARAM_VIDEO_EGA_BX) # Identifies EGA to the kernel
154 cmpb $0x10, %bl # No, it's a CGA/MDA/HGA card.
158 movw $0x1a00, %ax # Check EGA or VGA?
160 cmpb $0x1a, %al # 1a means VGA...
161 jne basret # anything else is EGA.
163 incb %fs:(PARAM_HAVE_VGA) # We've detected a VGA
167 # Store the video mode parameters for later usage by the kernel.
168 # This is done by asking the BIOS except for the rows/columns
169 # parameters in the default 80x25 mode -- these are set directly,
170 # because some very obscure BIOSes supply insane values.
172 #ifdef CONFIG_VIDEO_SELECT
173 cmpb $0, graphic_mode
176 movb $0x03, %ah # Read cursor position
179 movw %dx, %fs:(PARAM_CURSOR_POS)
180 movb $0x0f, %ah # Read page/mode/width
182 movw %bx, %fs:(PARAM_VIDEO_PAGE)
183 movw %ax, %fs:(PARAM_VIDEO_MODE) # Video mode and screen width
184 cmpb $0x7, %al # MDA/HGA => segment differs
187 movw $0xb000, video_segment
188 mopar0: movw %gs:(0x485), %ax # Font size
189 movw %ax, %fs:(PARAM_FONT_POINTS) # (valid only on EGA/VGA)
190 movw force_size, %ax # Forced size?
194 movb %ah, %fs:(PARAM_VIDEO_COLS)
195 movb %al, %fs:(PARAM_VIDEO_LINES)
198 mopar1: movb $25, %al
199 cmpb $0, adapter # If we are on CGA/MDA/HGA, the
200 jz mopar2 # screen must have 25 lines.
202 movb %gs:(0x484), %al # On EGA/VGA, use the EGA+ BIOS
203 incb %al # location of max lines.
204 mopar2: movb %al, %fs:(PARAM_VIDEO_LINES)
207 #ifdef CONFIG_VIDEO_SELECT
208 # Fetching of VESA frame buffer parameters
210 leaw modelist+1024, %di
211 movb $0x23, %fs:(PARAM_HAVE_VGA)
213 movw %ax, %fs:(PARAM_LFB_LINELENGTH)
215 movw %ax, %fs:(PARAM_LFB_WIDTH)
217 movw %ax, %fs:(PARAM_LFB_HEIGHT)
220 movw %ax, %fs:(PARAM_LFB_DEPTH)
223 movw %ax, %fs:(PARAM_LFB_PAGES)
225 movl %eax, %fs:(PARAM_LFB_BASE)
227 movl %eax, %fs:(PARAM_LFB_COLORS)
229 movl %eax, %fs:(PARAM_LFB_COLORS+4)
231 movw %ax, %fs:(PARAM_VESA_ATTRIB)
234 leaw modelist+1024, %di
239 movl %eax, %fs:(PARAM_LFB_SIZE)
241 # store mode capabilities
243 movl %eax, %fs:(PARAM_CAPABILITIES)
245 # switching the DAC to 8-bit is for <= 8 bpp only
246 movw %fs:(PARAM_LFB_DEPTH), %ax
250 # get DAC switching capability
256 # attempt to switch DAC to 8-bit
262 movb %bh, dac_size # store actual DAC size
265 # set color size to DAC size
267 movb %al, %fs:(PARAM_LFB_COLORS+0)
268 movb %al, %fs:(PARAM_LFB_COLORS+2)
269 movb %al, %fs:(PARAM_LFB_COLORS+4)
270 movb %al, %fs:(PARAM_LFB_COLORS+6)
272 # set color offsets to 0
273 movb $0, %fs:(PARAM_LFB_COLORS+1)
274 movb $0, %fs:(PARAM_LFB_COLORS+3)
275 movb $0, %fs:(PARAM_LFB_COLORS+5)
276 movb $0, %fs:(PARAM_LFB_COLORS+7)
279 # get protected mode interface informations
287 movw %es, %fs:(PARAM_VESAPM_SEG)
288 movw %di, %fs:(PARAM_VESAPM_OFF)
291 # The video mode menu
293 leaw keymsg, %si # "Return/Space/Timeout" message
298 cmpb $0x0d, %al # ENTER ?
299 je listm # yes - manual mode selection
301 cmpb $0x20, %al # SPACE ?
302 je defmd1 # no - repeat
307 defmd1: ret # No mode chosen? Default 80x25
309 listm: call mode_table # List mode table
310 listm0: leaw name_bann, %si # Print adapter name
331 leaw listhdr, %si # Table header
333 movb $0x30, %dl # DL holds mode number
335 lm1: cmpw $ASK_VGA, (%si) # End?
338 movb %dl, %al # Menu selection number
346 movb $0x78, %al # the letter 'x'
349 call prtdec # Columns
350 movb $0x0d, %al # New line
354 incb %dl # Next character
361 lm2: leaw prompt, %si # Mode prompt
363 leaw edit_buf, %di # Editor buffer
365 cmpb $0x0d, %al # Enter?
368 cmpb $0x08, %al # Backspace?
371 cmpb $0x20, %al # Printable?
374 cmpw $edit_buf+4, %di # Enough space?
381 lmbs: cmpw $edit_buf, %di # Backspace
392 lment: movb $0, (%di)
396 cmpb $0, (%si) # Empty string = default mode
399 cmpb $0, 1(%si) # One character = menu selection
402 cmpw $0x6373, (%si) # "scan" => mode scanning
408 lmhx: xorw %bx, %bx # Else => mode ID in hex
431 lmuse1: movw %bx, %ax
434 mnusel: lodsb # Menu selection
445 subb $0x61-0x30-10, %al
452 lmbad: leaw unknt, %si
455 lmscan: cmpb $0, adapter # Scanning only on EGA/VGA
458 movw $0, mt_end # Scanning of modes is
459 movb $1, scanning # done as new autodetection.
464 # Additional parts of mode_set... (relative jumps, you know)
465 setv7: # Video7 extended modes
467 subb $VIDEO_FIRST_V7>>8, %bh
473 _setrec: jmp setrec # Ugly...
474 _set_80x25: jmp set_80x25
476 # Aliases for backward compatibility.
478 movw $VIDEO_80x25, %ax
482 movb $VIDEO_8POINT-VIDEO_FIRST_SPECIAL, %al
484 jnz setbad # Fall-through!
486 # Setting of user mode (AX=mode ID) => CF=success
488 movw %ax, %fs:(0x01fa) # Store mode for use in acpi_wakeup.S
493 testb $VIDEO_RECALC>>8, %ah
496 cmpb $VIDEO_FIRST_RESOLUTION>>8, %ah
499 cmpb $VIDEO_FIRST_SPECIAL>>8, %ah
502 cmpb $VIDEO_FIRST_V7>>8, %ah
505 cmpb $VIDEO_FIRST_VESA>>8, %ah
515 movb $0, do_restore # The screen needn't be restored
520 subb $VIDEO_FIRST_VESA>>8, %bh
521 movw $0x4f02, %ax # VESA BIOS mode set call
523 cmpw $0x004f, %ax # AL=4f if implemented
524 jnz setbad # AH=0 if OK
531 int $0x10 # Standard BIOS mode set call
533 movb $0x0f, %ah # Check if really set
542 setspc: xorb %bh, %bh # Set special mode
543 cmpb $VIDEO_LAST_SPECIAL-VIDEO_FIRST_SPECIAL, %bl
550 orb %al, %al # 80x25 is an exception
553 pushw %bx # Set mode chosen from menu
554 call mode_table # Build the mode table
561 movw (%si), %ax # Fetch mode ID
564 setres: pushw %bx # Set mode chosen by resolution
569 cmpw $ASK_VGA, %ax # End of the list?
576 movw -4(%si), %ax # Fetch mode ID
580 leaw modelist+1024, %di
581 subb $VIDEO_FIRST_VESA>>8, %bh
582 movw %bx, %cx # Get mode information structure
585 addb $VIDEO_FIRST_VESA>>8, %bh
589 movb (%di), %al # Check capabilities.
592 jz setvesa # This is a text mode
594 movb (%di), %al # Check capabilities.
597 jnz _setbad # Doh! No linear frame buffer.
599 subb $VIDEO_FIRST_VESA>>8, %bh
600 orw $0x4000, %bx # Use linear frame buffer
601 movw $0x4f02, %ax # VESA BIOS mode set call
603 cmpw $0x004f, %ax # AL=4f if implemented
604 jnz _setbad # AH=0 if OK
606 movb $1, graphic_mode # flag graphic mode
607 movb $0, do_restore # no screen restore
611 _setbad: jmp setbad # Ugly...
613 # Recalculate vertical display end registers -- this fixes various
614 # inconsistencies of extended modes on many adapters. Called when
615 # the VIDEO_RECALC flag is set in the mode ID.
617 setrec: subb $VIDEO_RECALC>>8, %ah # Set the base mode
621 movw %gs:(0x485), %ax # Font size in pixels
622 movb %gs:(0x484), %bl # Number of rows
624 mulb %bl # Number of visible
625 decw %ax # scan lines - 1
628 movb $0x12, %al # Lower 8 bits
631 movb $0x07, %al # Bits 8 and 9 in the overflow register
641 rct2: movb $0x07, %al
646 # Table of routines for setting of the special modes.
658 # Set the 80x25 mode. If already set, do nothing.
660 movw $0x5019, force_size # Override possibly broken BIOS
662 #ifdef CONFIG_VIDEO_400_HACK
663 movw $0x1202, %ax # Force 400 scan lines
667 movb $0x0f, %ah # Get current mode ID
669 cmpw $0x5007, %ax # Mode 7 (80x25 mono) is the only one available
670 jz st80 # on CGA/MDA/HGA and is also available on EGAM
672 cmpw $0x5003, %ax # Unknown mode, force 80x25 color
675 st80: cmpb $0, adapter # CGA/MDA/HGA => mode 3/7 is always 80x25
678 movb %gs:(0x0484), %al # This is EGA+ -- beware of 80x50 etc.
679 orb %al, %al # Some buggy BIOS'es set 0 rows
682 cmpb $24, %al # It's hopefully correct
684 #endif /* CONFIG_VIDEO_400_HACK */
686 movw $0x0003, %ax # Forced set
691 # Set the 80x50/80x43 8-pixel mode. Simple BIOS calls.
694 call use_80x25 # The base is 80x25
696 movw $0x1112, %ax # Use 8x8 font
699 movw $0x1200, %ax # Use alternate print screen
702 movw $0x1201, %ax # Turn off cursor emulation
705 movb $0x01, %ah # Define cursor scan lines 6-7
712 # Set the 80x28 mode. This mode works on all VGA's, because it's a standard
713 # 80x25 mode with 14-point fonts instead of 16-point.
716 call use_80x25 # The base is 80x25
717 set14: movw $0x1111, %ax # Use 9x14 font
720 movb $0x01, %ah # Define cursor scan lines 11-12
726 # Set the 80x43 mode. This mode is works on all VGA's.
727 # It's a 350-scanline mode with 8-pixel font.
730 movw $0x1201, %ax # Set 350 scans
733 movw $0x0003, %ax # Reset video mode
735 jmp set_8pt # Use 8-pixel font
737 # Set the 80x30 mode (all VGA's). 480 scanlines, 16-pixel font.
739 call use_80x25 # Start with real 80x25
741 movw $0x3cc, %dx # Get CRTC port
744 rorb %al # Mono or color?
748 set48a: movw $0x0c11, %ax # Vertical sync end (also unlocks CR0-7)
750 movw $0x0b06, %ax # Vertical total
752 movw $0x3e07, %ax # (Vertical) overflow
754 movw $0xea10, %ax # Vertical sync start
756 movw $0xdf12, %ax # Vertical display end
758 movw $0xe715, %ax # Vertical blank start
760 movw $0x0416, %ax # Vertical blank end
763 movb $0xcc, %dl # Misc output register (read)
765 movb $0xc2, %dl # (write)
766 andb $0x0d, %al # Preserve clock select bits and color bit
767 orb $0xe2, %al # Set correct sync polarity
770 movw $0x501e, force_size
774 # Set the 80x34 mode (all VGA's). 480 scans, 14-pixel font.
776 call set_80x30 # Set 480 scans
777 call set14 # And 14-pt font
778 movw $0xdb12, %ax # VGA vertical display end
779 movw $0x5022, force_size
784 # Set the 80x60 mode (all VGA's). 480 scans, 8-pixel font.
786 call set_80x30 # Set 480 scans
787 call set_8pt # And 8-pt font
788 movw $0xdf12, %ax # VGA vertical display end
789 movw $0x503c, force_size
792 # Special hack for ThinkPad graphics
794 #ifdef CONFIG_VIDEO_GFX_HACK
795 movw $VIDEO_GFX_BIOS_AX, %ax
796 movw $VIDEO_GFX_BIOS_BX, %bx
798 movw $VIDEO_GFX_DUMMY_RESOLUTION, force_size
803 #ifdef CONFIG_VIDEO_RETAIN
805 # Store screen contents to temporary buffer.
807 cmpb $0, do_restore # Already stored?
810 testb $CAN_USE_HEAP, loadflags # Have we space for storing?
815 pushw force_size # Don't force specific size
817 call mode_params # Obtain params of current mode
819 movb %fs:(PARAM_VIDEO_LINES), %ah
820 movb %fs:(PARAM_VIDEO_COLS), %al
821 movw %ax, %bx # BX=dimensions
823 movw %ax, %cx # CX=number of characters
824 addw %ax, %ax # Calculate image size
825 addw $modelist+1024+4, %ax
826 cmpw heap_end_ptr, %ax
827 jnc sts1 # Unfortunately, out of memory
829 movw %fs:(PARAM_CURSOR_POS), %ax # Store mode params
830 leaw modelist+1024, %di
834 pushw %ds # Store the screen
835 movw video_segment, %ds
840 incb do_restore # Screen will be restored later
845 # Restore screen contents from temporary buffer.
847 cmpb $0, do_restore # Has the screen been stored?
850 call mode_params # Get parameters of current mode
851 movb %fs:(PARAM_VIDEO_LINES), %cl
852 movb %fs:(PARAM_VIDEO_COLS), %ch
853 leaw modelist+1024, %si # Screen buffer
854 lodsw # Set cursor position
866 res3: movb $0x02, %ah
870 movb %ah, %dl # DL=number of lines
871 movb $0, %ah # BX=phys. length of orig. line
873 cmpb %cl, %dl # Too many?
884 res4: cmpb %ch, %al # Too wide?
887 movb %ch, %al # AX=width of src. line
890 movw %cx, %bp # BP=width of dest. line
892 movw video_segment, %es
893 xorw %di, %di # Move the data
894 addw %bx, %bx # Convert BX and BP to _bytes_
910 #endif /* CONFIG_VIDEO_RETAIN */
912 # Write to indexed VGA register (AL=index, AH=data, DX=index reg. port)
913 outidx: outb %al, %dx
922 # Build the table of video modes (stored after the setup.S code at the
923 # `modelist' label. Each video mode record looks like:
924 # .word MODE-ID (our special mode ID (see above))
925 # .byte rows (number of rows)
926 # .byte columns (number of columns)
927 # Returns address of the end of the table in DI, the end is marked
930 movw mt_end, %di # Already filled?
934 leaw modelist, %di # Store standard modes:
935 movl $VIDEO_80x25 + 0x50190000, %eax # The 80x25 mode (ALL)
937 movb adapter, %al # CGA/MDA/HGA -- no more modes
944 movl $VIDEO_8POINT + 0x502b0000, %eax # The 80x43 EGA mode
950 mtabv: leaw vga_modes, %si # All modes for std VGA
951 movw $vga_modes_end-vga_modes, %cx
952 rep # I'm unable to use movsw as I don't know how to store a half
953 movsb # of the expression above to cx without using explicit shr.
955 cmpb $0, scanning # Mode scan requested?
961 #ifdef CONFIG_VIDEO_LOCAL
963 #endif /* CONFIG_VIDEO_LOCAL */
965 #ifdef CONFIG_VIDEO_VESA
966 call vesa_modes # Detect VESA VGA modes
967 #endif /* CONFIG_VIDEO_VESA */
969 #ifdef CONFIG_VIDEO_SVGA
970 cmpb $0, scanning # Bypass when scanning
973 call svga_modes # Detect SVGA cards & modes
975 #endif /* CONFIG_VIDEO_SVGA */
979 #ifdef CONFIG_VIDEO_COMPACT
983 cmt1: cmpw %dx, %si # Scan all modes
986 leaw modelist, %bx # Find in previous entries
991 cmpw 2(%bx), %cx # Found => don't copy this entry
997 cmt4: movsl # Copy entry
1000 cmt5: addw $4, %si # Skip entry
1004 #endif /* CONFIG_VIDEO_COMPACT */
1006 movw $ASK_VGA, (%di) # End marker
1008 mtab1: leaw modelist, %si # SI=mode list, DI=list end
1011 # Modes usable on all standard VGAs
1014 .word 0x5032 # 80x50
1016 .word 0x502b # 80x43
1018 .word 0x501c # 80x28
1020 .word 0x501e # 80x30
1022 .word 0x5022 # 80x34
1024 .word 0x503c # 80x60
1025 #ifdef CONFIG_VIDEO_GFX_HACK
1026 .word VIDEO_GFX_HACK
1027 .word VIDEO_GFX_DUMMY_RESOLUTION
1031 # Detect VESA modes.
1033 #ifdef CONFIG_VIDEO_VESA
1035 cmpb $2, adapter # VGA only
1038 movw %di, %bp # BP=original mode table end
1039 addw $0x200, %di # Buffer space
1040 movw $0x4f00, %ax # VESA Get card info call
1043 cmpw $0x004f, %ax # Successful?
1046 cmpw $0x4556, 0x200(%di)
1049 cmpw $0x4153, 0x202(%di)
1052 movw $vesa_name, card_name # Set name to "VESA VGA"
1054 lgsw 0x20e(%di), %si # GS:SI=mode list
1055 movw $128, %cx # Iteration limit
1057 # gas version 2.9.1, using BFD version 2.9.1.0.23 buggers the next inst.
1058 # XXX: lodsw %gs:(%si), %ax # Get next mode in the list
1060 cmpw $0xffff, %ax # End of the table?
1063 cmpw $0x0080, %ax # Check validity of mode ID
1066 orb %ah, %ah # Valid IDs: 0x0000-0x007f/0x0100-0x07ff
1067 jz vesan # Certain BIOSes report 0x80-0xff!
1073 movw %ax, %cx # Get mode information structure
1076 movw %cx, %bx # BX=mode number
1077 addb $VIDEO_FIRST_VESA>>8, %bh
1080 jnz vesan # Don't report errors (buggy BIOSES)
1082 movb (%di), %al # Check capabilities. We require
1083 andb $0x19, %al # a color text mode.
1087 cmpw $0xb800, 8(%di) # Standard video memory address required
1090 testb $2, (%di) # Mode characteristics supplied?
1091 movw %bx, (%di) # Store mode number
1095 movw 0x12(%di), %bx # Width
1100 movw 0x14(%di), %ax # Height
1106 cmpw $8193, %ax # Small enough for Linux console driver?
1111 vesa3: subw $0x8108, %bx # This mode has no detailed info specified,
1112 jc vesan # so it must be a standard VESA mode.
1117 movw vesa_text_mode_table(%bx), %ax
1119 vesaok: addw $4, %di # The mode is valid. Store it.
1120 vesan: loop vesa1 # Next mode. Limit exceeded => error
1121 vesae: leaw vesaer, %si
1123 movw %bp, %di # Discard already found modes.
1127 # Dimensions of standard VESA text modes
1128 vesa_text_mode_table:
1130 .byte 25, 132 # 0109
1131 .byte 43, 132 # 010A
1132 .byte 50, 132 # 010B
1133 .byte 60, 132 # 010C
1134 #endif /* CONFIG_VIDEO_VESA */
1136 # Scan for video modes. A bit dirty, but should work.
1138 movw $0x0100, %cx # Start with mode 0
1139 scm1: movb $0, %ah # Test the mode
1145 jnz scm2 # Mode not set
1147 movw $0x3c0, %dx # Test if it's a text mode
1148 movb $0x10, %al # Mode bits
1153 movb $0xce, %dl # Another set of mode bits
1159 movb $0xd4, %dl # Cursor location
1165 movw %cx, %ax # Ok, store the mode
1167 movb %gs:(0x484), %al # Number of rows
1170 movw %gs:(0x44a), %ax # Number of columns
1175 movw $0x0003, %ax # Return back to mode 3
1179 tstidx: outw %ax, %dx # OUT DX,AX and inidx
1180 inidx: outb %al, %dx # Read from indexed VGA register
1181 incw %dx # AL=index, DX=index reg port -> AL=data
1186 # Try to detect type of SVGA card and supply (usually approximate) video
1187 # mode table for it.
1189 #ifdef CONFIG_VIDEO_SVGA
1191 leaw svga_table, %si # Test all known SVGA adapters
1193 movw %ax, %bp # Default mode table
1197 lodsw # Pointer to test routine
1203 call *%ax # Call test routine
1210 movw %bp, %si # Found, copy the modes
1211 movb svga_prefix, %ah
1220 didsv: movw %si, card_name # Store pointer to card name
1223 # Table of all known SVGA cards. For each card, we store a pointer to
1224 # a table of video modes supported by the card and a pointer to a routine
1225 # used for testing of presence of the card. The video mode table is always
1226 # followed by the name of the card or the chipset.
1228 .word ati_md, ati_test
1229 .word oak_md, oak_test
1230 .word paradise_md, paradise_test
1231 .word realtek_md, realtek_test
1232 .word s3_md, s3_test
1233 .word chips_md, chips_test
1234 .word video7_md, video7_test
1235 .word cirrus5_md, cirrus5_test
1236 .word cirrus6_md, cirrus6_test
1237 .word cirrus1_md, cirrus1_test
1238 .word ahead_md, ahead_test
1239 .word everex_md, everex_test
1240 .word genoa_md, genoa_test
1241 .word trident_md, trident_test
1242 .word tseng_md, tseng_test
1245 # Test routines and mode tables:
1247 # S3 - The test algorithm was taken from the SuperProbe package
1248 # for XFree86 1.2.1. Report bugs to Christoph.Niemann@linux.org
1250 movw $0x0f35, %cx # we store some constants in cl/ch
1254 movb %al, %bh # store current CRT-register 0x38
1256 call outidx # disable writing to special regs
1257 movb %cl, %al # check whether we can write special reg 0x35
1259 movb %al, %bl # save the current value of CRT reg 0x35
1260 andb $0xf0, %al # clear bits 0-3
1262 movb %cl, %al # and write it to CRT reg 0x35
1264 call inidx # now read it back
1265 andb %ch, %al # clear the upper 4 bits
1266 jz s3_2 # the first test failed. But we have a
1268 movb %bl, %ah # second chance
1271 jmp s3_1 # do the other tests
1273 s3_2: movw %cx, %ax # load ah with 0xf and al with 0x35
1274 orb %bl, %ah # set the upper 4 bits of ah with the orig value
1275 call outidx # write ...
1276 call inidx # ... and reread
1277 andb %cl, %al # turn off the upper 4 bits
1279 movb %bl, %ah # restore old value in register 0x35
1283 cmpb %ch, %al # setting lower 4 bits was successful => bad
1284 je no_s3 # writing is allowed => this is not an S3
1286 s3_1: movw $0x4838, %ax # allow writing to special regs by putting
1287 call outidx # magic number into CRT-register 0x38
1288 movb %cl, %al # check whether we can write special reg 0x35
1297 jnz no_s3 # no, we can't write => no S3
1305 movb %bl, %ah # restore old value in register 0x35
1310 jne no_s31 # writing not possible => no S3
1312 call inidx # now get the S3 id ...
1323 no_s3: movb $0x35, %al # restore CRT register 0x35
1326 no_s31: xorw %bp, %bp # Detection failed
1327 s3rest: movb %bh, %ah
1328 movb $0x38, %al # restore old value of CRT register 0x38
1331 idS3: .byte 0x81, 0x82, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95
1332 .byte 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa8, 0xb0
1334 s3_md: .byte 0x54, 0x2b, 0x84
1335 .byte 0x55, 0x19, 0x84
1352 idati: .ascii "761295520"
1354 ati_md: .byte 0x23, 0x19, 0x84
1355 .byte 0x33, 0x2c, 0x84
1356 .byte 0x22, 0x1e, 0x64
1357 .byte 0x21, 0x19, 0x64
1358 .byte 0x58, 0x21, 0x50
1359 .byte 0x5b, 0x1e, 0x50
1381 .byte 0x22, 0x2c, 0x84
1382 .byte 0x23, 0x19, 0x84
1383 .byte 0x24, 0x1c, 0x84
1384 .byte 0x2f, 0x32, 0xa0
1385 .byte 0x32, 0x22, 0x50
1386 .byte 0x34, 0x42, 0x50
1411 .byte 0x60, 0x19, 0x84
1412 .byte 0x61, 0x32, 0x84
1414 .ascii "Chips & Technologies"
1455 nocirr: xorw %bp, %bp
1456 iscirr: movw $0x3d4, %dx
1465 .byte 0x1f, 0x19, 0x84
1466 .byte 0x20, 0x2c, 0x84
1467 .byte 0x22, 0x1e, 0x84
1468 .byte 0x31, 0x25, 0x64
1470 .ascii "Cirrus Logic 5X0"
1478 movb %al, %bl # BL=backup
1512 c5fail: xorw %bp, %bp
1513 c5done: movb $6, %al
1519 .byte 0x14, 0x19, 0x84
1520 .byte 0x54, 0x2b, 0x84
1522 .ascii "Cirrus Logic 54XX"
1525 # Cirrus Logic 64XX -- no known extra modes, but must be identified, because
1526 # it's misidentified by the Ahead test.
1531 movb %al, %bl # BL=backup
1543 call inidx # 4X, 5X, 7X and 8X are valid 64XX chip ID's.
1557 c2fail: xorw %bp, %bp
1558 c6done: movb $0x0a, %al
1565 .ascii "Cirrus Logic 64XX"
1583 evtrid: leaw trident_md, %bp
1586 noevrx: xorw %bp, %bp
1590 .byte 0x03, 0x22, 0x50
1591 .byte 0x04, 0x3c, 0x50
1592 .byte 0x07, 0x2b, 0x64
1593 .byte 0x08, 0x4b, 0x64
1594 .byte 0x0a, 0x19, 0x84
1595 .byte 0x0b, 0x2c, 0x84
1596 .byte 0x16, 0x1e, 0x50
1597 .byte 0x18, 0x1b, 0x64
1598 .byte 0x21, 0x40, 0xa0
1599 .byte 0x40, 0x1e, 0x84
1601 .ascii "Everex/Trident"
1606 leaw idgenoa, %si # Check Genoa 'clues'
1608 movb %es:(0x37), %al
1627 idgenoa: .byte 0x77, 0x00, 0x99, 0x66
1630 .byte 0x58, 0x20, 0x50
1631 .byte 0x5a, 0x2a, 0x64
1632 .byte 0x60, 0x19, 0x84
1633 .byte 0x61, 0x1d, 0x84
1634 .byte 0x62, 0x20, 0x84
1635 .byte 0x63, 0x2c, 0x84
1636 .byte 0x64, 0x3c, 0x84
1637 .byte 0x6b, 0x4f, 0x64
1638 .byte 0x72, 0x3c, 0x50
1639 .byte 0x74, 0x42, 0x50
1640 .byte 0x78, 0x4b, 0x64
1657 idoakvga: .ascii "OAK VGA "
1659 oak_md: .byte 0x4e, 0x3c, 0x50
1660 .byte 0x4f, 0x3c, 0x84
1661 .byte 0x50, 0x19, 0x84
1662 .byte 0x51, 0x2b, 0x84
1669 leaw idparadise, %si
1679 idparadise: .ascii "VGA="
1682 .byte 0x41, 0x22, 0x50
1683 .byte 0x47, 0x1c, 0x84
1684 .byte 0x55, 0x19, 0x84
1685 .byte 0x54, 0x2c, 0x84
1702 movb %al, %bl # Strange thing ... in the book this wasn't
1703 andb $0x02, %bl # necessary but it worked on my card which
1704 jz setb2 # is a trident. Without it the screen goes
1709 setb2: orb $0x02, %al
1710 clrb2: outb %al, %dx
1719 .byte 0x50, 0x1e, 0x50
1720 .byte 0x51, 0x2b, 0x50
1721 .byte 0x52, 0x3c, 0x50
1722 .byte 0x57, 0x19, 0x84
1723 .byte 0x58, 0x1e, 0x84
1724 .byte 0x59, 0x2b, 0x84
1725 .byte 0x5a, 0x3c, 0x84
1733 inb %dx, %al # Could things be this simple ! :-)
1744 isnot: xorw %bp, %bp
1748 .byte 0x26, 0x3c, 0x50
1749 .byte 0x2a, 0x28, 0x64
1750 .byte 0x23, 0x19, 0x84
1751 .byte 0x24, 0x1c, 0x84
1752 .byte 0x22, 0x2c, 0x84
1753 .byte 0x21, 0x3c, 0x84
1767 even7: movb $0x0c, %al
1792 movb $VIDEO_FIRST_V7>>8, svga_prefix # Use special mode switching
1796 .byte 0x40, 0x2b, 0x50
1797 .byte 0x43, 0x3c, 0x50
1798 .byte 0x44, 0x3c, 0x64
1799 .byte 0x41, 0x19, 0x84
1800 .byte 0x42, 0x2c, 0x84
1801 .byte 0x45, 0x1c, 0x84
1818 idrtvga: .ascii "REALTEK VGA"
1821 .byte 0x1a, 0x3c, 0x50
1822 .byte 0x1b, 0x19, 0x84
1823 .byte 0x1c, 0x1e, 0x84
1824 .byte 0x1d, 0x2b, 0x84
1825 .byte 0x1e, 0x3c, 0x84
1830 #endif /* CONFIG_VIDEO_SVGA */
1832 # User-defined local mode table (VGA only)
1833 #ifdef CONFIG_VIDEO_LOCAL
1835 leaw local_mode_table, %si
1846 # This is the table of local video modes which can be supplied manually
1847 # by the user. Each entry consists of mode ID (word) and dimensions
1848 # (byte for column count and another byte for row count). These modes
1849 # are placed before all SVGA and VESA modes and override them if table
1850 # compacting is enabled. The table must end with a zero word followed
1851 # by NUL-terminated video adapter name.
1853 .word 0x0100 # Example: 40x25
1858 #endif /* CONFIG_VIDEO_LOCAL */
1860 # Read a key and return the ASCII code in al, scan code in ah
1861 getkey: xorb %ah, %ah
1865 # Read a key with a timeout of 30 seconds.
1866 # The hardware clock is used to get the time.
1868 addb $30, %al # Wait 30 seconds
1875 again: movb $0x01, %ah
1877 jnz getkey # key pressed, so get it
1883 movb $0x20, %al # timeout, return `space'
1886 # Flush the keyboard buffer
1887 flush: movb $0x01, %ah
1897 # Print hexadecimal number.
1907 prthn: cmpb $0x0a, %al
1911 prth1: addb $0x30, %al
1914 # Print decimal number in al
1926 lt100: addb $0x30, %al
1928 skip10: movb %ah, %al
1936 #ifdef CONFIG_FB_FIRMWARE_EDID
1937 pushw %es # just save all registers
1947 movl $0x13131313, %eax # memset block with 0x13
1954 movw $0x4f15, %ax # do VBE/DDC
1955 movw $0x00, %bx # INSTALLATION CHECK / CAPABILITIES
1963 movw $0x4f15, %ax # do VBE/DDC
1964 movw $0x01, %bx # READ_EDID
1971 popw %di # restore all registers
1980 # VIDEO_SELECT-only variables
1981 mt_end: .word 0 # End of video mode table if built
1982 edit_buf: .space 6 # Line editor buffer
1983 card_name: .word 0 # Pointer to adapter name
1984 scanning: .byte 0 # Performing mode scan
1985 do_restore: .byte 0 # Screen contents altered during mode change
1986 svga_prefix: .byte VIDEO_FIRST_BIOS>>8 # Default prefix for BIOS modes
1987 graphic_mode: .byte 0 # Graphic mode with a linear frame buffer
1988 dac_size: .byte 6 # DAC bit depth
1991 keymsg: .ascii "Press <RETURN> to see video modes available, "
1992 .ascii "<SPACE> to continue or wait 30 secs"
1995 listhdr: .byte 0x0d, 0x0a
1996 .ascii "Mode: COLSxROWS:"
1998 crlft: .byte 0x0d, 0x0a, 0
2000 prompt: .byte 0x0d, 0x0a
2001 .asciz "Enter mode number or `scan': "
2003 unknt: .asciz "Unknown mode ID. Try again."
2005 badmdt: .ascii "You passed an undefined mode number."
2008 vesaer: .ascii "Error: Scanning of VESA modes failed. Please "
2009 .ascii "report to <mj@ucw.cz>."
2012 old_name: .asciz "CGA/MDA/HGA"
2014 ega_name: .asciz "EGA"
2016 svga_name: .ascii " "
2018 vga_name: .asciz "VGA"
2020 vesa_name: .asciz "VESA"
2022 name_bann: .asciz "Video adapter: "
2023 #endif /* CONFIG_VIDEO_SELECT */
2026 adapter: .byte 0 # Video adapter: 0=CGA/MDA/HGA,1=EGA,2=VGA
2027 video_segment: .word 0xb800 # Video memory segment
2028 force_size: .word 0 # Use this size instead of the one in BIOS vars