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 leaw modelist+1024, %di
579 subb $VIDEO_FIRST_VESA>>8, %bh
580 movw %bx, %cx # Get mode information structure
583 addb $VIDEO_FIRST_VESA>>8, %bh
587 movb (%di), %al # Check capabilities.
590 jz setvesa # This is a text mode
592 movb (%di), %al # Check capabilities.
595 jnz _setbad # Doh! No linear frame buffer.
597 subb $VIDEO_FIRST_VESA>>8, %bh
598 orw $0x4000, %bx # Use linear frame buffer
599 movw $0x4f02, %ax # VESA BIOS mode set call
601 cmpw $0x004f, %ax # AL=4f if implemented
602 jnz _setbad # AH=0 if OK
604 movb $1, graphic_mode # flag graphic mode
605 movb $0, do_restore # no screen restore
609 _setbad: jmp setbad # Ugly...
611 # Recalculate vertical display end registers -- this fixes various
612 # inconsistencies of extended modes on many adapters. Called when
613 # the VIDEO_RECALC flag is set in the mode ID.
615 setrec: subb $VIDEO_RECALC>>8, %ah # Set the base mode
619 movw %gs:(0x485), %ax # Font size in pixels
620 movb %gs:(0x484), %bl # Number of rows
622 mulb %bl # Number of visible
623 decw %ax # scan lines - 1
626 movb $0x12, %al # Lower 8 bits
629 movb $0x07, %al # Bits 8 and 9 in the overflow register
639 rct2: movb $0x07, %al
644 # Table of routines for setting of the special modes.
656 # Set the 80x25 mode. If already set, do nothing.
658 movw $0x5019, force_size # Override possibly broken BIOS
660 #ifdef CONFIG_VIDEO_400_HACK
661 movw $0x1202, %ax # Force 400 scan lines
665 movb $0x0f, %ah # Get current mode ID
667 cmpw $0x5007, %ax # Mode 7 (80x25 mono) is the only one available
668 jz st80 # on CGA/MDA/HGA and is also available on EGAM
670 cmpw $0x5003, %ax # Unknown mode, force 80x25 color
673 st80: cmpb $0, adapter # CGA/MDA/HGA => mode 3/7 is always 80x25
676 movb %gs:(0x0484), %al # This is EGA+ -- beware of 80x50 etc.
677 orb %al, %al # Some buggy BIOS'es set 0 rows
680 cmpb $24, %al # It's hopefully correct
682 #endif /* CONFIG_VIDEO_400_HACK */
684 movw $0x0003, %ax # Forced set
689 # Set the 80x50/80x43 8-pixel mode. Simple BIOS calls.
692 call use_80x25 # The base is 80x25
694 movw $0x1112, %ax # Use 8x8 font
697 movw $0x1200, %ax # Use alternate print screen
700 movw $0x1201, %ax # Turn off cursor emulation
703 movb $0x01, %ah # Define cursor scan lines 6-7
710 # Set the 80x28 mode. This mode works on all VGA's, because it's a standard
711 # 80x25 mode with 14-point fonts instead of 16-point.
714 call use_80x25 # The base is 80x25
715 set14: movw $0x1111, %ax # Use 9x14 font
718 movb $0x01, %ah # Define cursor scan lines 11-12
724 # Set the 80x43 mode. This mode is works on all VGA's.
725 # It's a 350-scanline mode with 8-pixel font.
728 movw $0x1201, %ax # Set 350 scans
731 movw $0x0003, %ax # Reset video mode
733 jmp set_8pt # Use 8-pixel font
735 # Set the 80x30 mode (all VGA's). 480 scanlines, 16-pixel font.
737 call use_80x25 # Start with real 80x25
739 movw $0x3cc, %dx # Get CRTC port
742 rorb %al # Mono or color?
746 set48a: movw $0x0c11, %ax # Vertical sync end (also unlocks CR0-7)
748 movw $0x0b06, %ax # Vertical total
750 movw $0x3e07, %ax # (Vertical) overflow
752 movw $0xea10, %ax # Vertical sync start
754 movw $0xdf12, %ax # Vertical display end
756 movw $0xe715, %ax # Vertical blank start
758 movw $0x0416, %ax # Vertical blank end
761 movb $0xcc, %dl # Misc output register (read)
763 movb $0xc2, %dl # (write)
764 andb $0x0d, %al # Preserve clock select bits and color bit
765 orb $0xe2, %al # Set correct sync polarity
768 movw $0x501e, force_size
772 # Set the 80x34 mode (all VGA's). 480 scans, 14-pixel font.
774 call set_80x30 # Set 480 scans
775 call set14 # And 14-pt font
776 movw $0xdb12, %ax # VGA vertical display end
777 movw $0x5022, force_size
782 # Set the 80x60 mode (all VGA's). 480 scans, 8-pixel font.
784 call set_80x30 # Set 480 scans
785 call set_8pt # And 8-pt font
786 movw $0xdf12, %ax # VGA vertical display end
787 movw $0x503c, force_size
790 # Special hack for ThinkPad graphics
792 #ifdef CONFIG_VIDEO_GFX_HACK
793 movw $VIDEO_GFX_BIOS_AX, %ax
794 movw $VIDEO_GFX_BIOS_BX, %bx
796 movw $VIDEO_GFX_DUMMY_RESOLUTION, force_size
801 #ifdef CONFIG_VIDEO_RETAIN
803 # Store screen contents to temporary buffer.
805 cmpb $0, do_restore # Already stored?
808 testb $CAN_USE_HEAP, loadflags # Have we space for storing?
813 pushw force_size # Don't force specific size
815 call mode_params # Obtain params of current mode
817 movb %fs:(PARAM_VIDEO_LINES), %ah
818 movb %fs:(PARAM_VIDEO_COLS), %al
819 movw %ax, %bx # BX=dimensions
821 movw %ax, %cx # CX=number of characters
822 addw %ax, %ax # Calculate image size
823 addw $modelist+1024+4, %ax
824 cmpw heap_end_ptr, %ax
825 jnc sts1 # Unfortunately, out of memory
827 movw %fs:(PARAM_CURSOR_POS), %ax # Store mode params
828 leaw modelist+1024, %di
832 pushw %ds # Store the screen
833 movw video_segment, %ds
838 incb do_restore # Screen will be restored later
843 # Restore screen contents from temporary buffer.
845 cmpb $0, do_restore # Has the screen been stored?
848 call mode_params # Get parameters of current mode
849 movb %fs:(PARAM_VIDEO_LINES), %cl
850 movb %fs:(PARAM_VIDEO_COLS), %ch
851 leaw modelist+1024, %si # Screen buffer
852 lodsw # Set cursor position
864 res3: movb $0x02, %ah
868 movb %ah, %dl # DL=number of lines
869 movb $0, %ah # BX=phys. length of orig. line
871 cmpb %cl, %dl # Too many?
882 res4: cmpb %ch, %al # Too wide?
885 movb %ch, %al # AX=width of src. line
888 movw %cx, %bp # BP=width of dest. line
890 movw video_segment, %es
891 xorw %di, %di # Move the data
892 addw %bx, %bx # Convert BX and BP to _bytes_
908 #endif /* CONFIG_VIDEO_RETAIN */
910 # Write to indexed VGA register (AL=index, AH=data, DX=index reg. port)
911 outidx: outb %al, %dx
920 # Build the table of video modes (stored after the setup.S code at the
921 # `modelist' label. Each video mode record looks like:
922 # .word MODE-ID (our special mode ID (see above))
923 # .byte rows (number of rows)
924 # .byte columns (number of columns)
925 # Returns address of the end of the table in DI, the end is marked
928 movw mt_end, %di # Already filled?
932 leaw modelist, %di # Store standard modes:
933 movl $VIDEO_80x25 + 0x50190000, %eax # The 80x25 mode (ALL)
935 movb adapter, %al # CGA/MDA/HGA -- no more modes
942 movl $VIDEO_8POINT + 0x502b0000, %eax # The 80x43 EGA mode
948 mtabv: leaw vga_modes, %si # All modes for std VGA
949 movw $vga_modes_end-vga_modes, %cx
950 rep # I'm unable to use movsw as I don't know how to store a half
951 movsb # of the expression above to cx without using explicit shr.
953 cmpb $0, scanning # Mode scan requested?
959 #ifdef CONFIG_VIDEO_LOCAL
961 #endif /* CONFIG_VIDEO_LOCAL */
963 #ifdef CONFIG_VIDEO_VESA
964 call vesa_modes # Detect VESA VGA modes
965 #endif /* CONFIG_VIDEO_VESA */
967 #ifdef CONFIG_VIDEO_SVGA
968 cmpb $0, scanning # Bypass when scanning
971 call svga_modes # Detect SVGA cards & modes
973 #endif /* CONFIG_VIDEO_SVGA */
977 #ifdef CONFIG_VIDEO_COMPACT
981 cmt1: cmpw %dx, %si # Scan all modes
984 leaw modelist, %bx # Find in previous entries
989 cmpw 2(%bx), %cx # Found => don't copy this entry
995 cmt4: movsl # Copy entry
998 cmt5: addw $4, %si # Skip entry
1002 #endif /* CONFIG_VIDEO_COMPACT */
1004 movw $ASK_VGA, (%di) # End marker
1006 mtab1: leaw modelist, %si # SI=mode list, DI=list end
1009 # Modes usable on all standard VGAs
1012 .word 0x5032 # 80x50
1014 .word 0x502b # 80x43
1016 .word 0x501c # 80x28
1018 .word 0x501e # 80x30
1020 .word 0x5022 # 80x34
1022 .word 0x503c # 80x60
1023 #ifdef CONFIG_VIDEO_GFX_HACK
1024 .word VIDEO_GFX_HACK
1025 .word VIDEO_GFX_DUMMY_RESOLUTION
1029 # Detect VESA modes.
1031 #ifdef CONFIG_VIDEO_VESA
1033 cmpb $2, adapter # VGA only
1036 movw %di, %bp # BP=original mode table end
1037 addw $0x200, %di # Buffer space
1038 movw $0x4f00, %ax # VESA Get card info call
1041 cmpw $0x004f, %ax # Successful?
1044 cmpw $0x4556, 0x200(%di)
1047 cmpw $0x4153, 0x202(%di)
1050 movw $vesa_name, card_name # Set name to "VESA VGA"
1052 lgsw 0x20e(%di), %si # GS:SI=mode list
1053 movw $128, %cx # Iteration limit
1055 # gas version 2.9.1, using BFD version 2.9.1.0.23 buggers the next inst.
1056 # XXX: lodsw %gs:(%si), %ax # Get next mode in the list
1058 cmpw $0xffff, %ax # End of the table?
1061 cmpw $0x0080, %ax # Check validity of mode ID
1064 orb %ah, %ah # Valid IDs: 0x0000-0x007f/0x0100-0x07ff
1065 jz vesan # Certain BIOSes report 0x80-0xff!
1071 movw %ax, %cx # Get mode information structure
1074 movw %cx, %bx # BX=mode number
1075 addb $VIDEO_FIRST_VESA>>8, %bh
1078 jnz vesan # Don't report errors (buggy BIOSES)
1080 movb (%di), %al # Check capabilities. We require
1081 andb $0x19, %al # a color text mode.
1085 cmpw $0xb800, 8(%di) # Standard video memory address required
1088 testb $2, (%di) # Mode characteristics supplied?
1089 movw %bx, (%di) # Store mode number
1093 movw 0x12(%di), %bx # Width
1098 movw 0x14(%di), %ax # Height
1104 cmpw $8193, %ax # Small enough for Linux console driver?
1109 vesa3: subw $0x8108, %bx # This mode has no detailed info specified,
1110 jc vesan # so it must be a standard VESA mode.
1115 movw vesa_text_mode_table(%bx), %ax
1117 vesaok: addw $4, %di # The mode is valid. Store it.
1118 vesan: loop vesa1 # Next mode. Limit exceeded => error
1119 vesae: leaw vesaer, %si
1121 movw %bp, %di # Discard already found modes.
1125 # Dimensions of standard VESA text modes
1126 vesa_text_mode_table:
1128 .byte 25, 132 # 0109
1129 .byte 43, 132 # 010A
1130 .byte 50, 132 # 010B
1131 .byte 60, 132 # 010C
1132 #endif /* CONFIG_VIDEO_VESA */
1134 # Scan for video modes. A bit dirty, but should work.
1136 movw $0x0100, %cx # Start with mode 0
1137 scm1: movb $0, %ah # Test the mode
1143 jnz scm2 # Mode not set
1145 movw $0x3c0, %dx # Test if it's a text mode
1146 movb $0x10, %al # Mode bits
1151 movb $0xce, %dl # Another set of mode bits
1157 movb $0xd4, %dl # Cursor location
1163 movw %cx, %ax # Ok, store the mode
1165 movb %gs:(0x484), %al # Number of rows
1168 movw %gs:(0x44a), %ax # Number of columns
1173 movw $0x0003, %ax # Return back to mode 3
1177 tstidx: outw %ax, %dx # OUT DX,AX and inidx
1178 inidx: outb %al, %dx # Read from indexed VGA register
1179 incw %dx # AL=index, DX=index reg port -> AL=data
1184 # Try to detect type of SVGA card and supply (usually approximate) video
1185 # mode table for it.
1187 #ifdef CONFIG_VIDEO_SVGA
1189 leaw svga_table, %si # Test all known SVGA adapters
1191 movw %ax, %bp # Default mode table
1195 lodsw # Pointer to test routine
1201 call *%ax # Call test routine
1208 movw %bp, %si # Found, copy the modes
1209 movb svga_prefix, %ah
1218 didsv: movw %si, card_name # Store pointer to card name
1221 # Table of all known SVGA cards. For each card, we store a pointer to
1222 # a table of video modes supported by the card and a pointer to a routine
1223 # used for testing of presence of the card. The video mode table is always
1224 # followed by the name of the card or the chipset.
1226 .word ati_md, ati_test
1227 .word oak_md, oak_test
1228 .word paradise_md, paradise_test
1229 .word realtek_md, realtek_test
1230 .word s3_md, s3_test
1231 .word chips_md, chips_test
1232 .word video7_md, video7_test
1233 .word cirrus5_md, cirrus5_test
1234 .word cirrus6_md, cirrus6_test
1235 .word cirrus1_md, cirrus1_test
1236 .word ahead_md, ahead_test
1237 .word everex_md, everex_test
1238 .word genoa_md, genoa_test
1239 .word trident_md, trident_test
1240 .word tseng_md, tseng_test
1243 # Test routines and mode tables:
1245 # S3 - The test algorithm was taken from the SuperProbe package
1246 # for XFree86 1.2.1. Report bugs to Christoph.Niemann@linux.org
1248 movw $0x0f35, %cx # we store some constants in cl/ch
1252 movb %al, %bh # store current CRT-register 0x38
1254 call outidx # disable writing to special regs
1255 movb %cl, %al # check whether we can write special reg 0x35
1257 movb %al, %bl # save the current value of CRT reg 0x35
1258 andb $0xf0, %al # clear bits 0-3
1260 movb %cl, %al # and write it to CRT reg 0x35
1262 call inidx # now read it back
1263 andb %ch, %al # clear the upper 4 bits
1264 jz s3_2 # the first test failed. But we have a
1266 movb %bl, %ah # second chance
1269 jmp s3_1 # do the other tests
1271 s3_2: movw %cx, %ax # load ah with 0xf and al with 0x35
1272 orb %bl, %ah # set the upper 4 bits of ah with the orig value
1273 call outidx # write ...
1274 call inidx # ... and reread
1275 andb %cl, %al # turn off the upper 4 bits
1277 movb %bl, %ah # restore old value in register 0x35
1281 cmpb %ch, %al # setting lower 4 bits was successful => bad
1282 je no_s3 # writing is allowed => this is not an S3
1284 s3_1: movw $0x4838, %ax # allow writing to special regs by putting
1285 call outidx # magic number into CRT-register 0x38
1286 movb %cl, %al # check whether we can write special reg 0x35
1295 jnz no_s3 # no, we can't write => no S3
1303 movb %bl, %ah # restore old value in register 0x35
1308 jne no_s31 # writing not possible => no S3
1310 call inidx # now get the S3 id ...
1321 no_s3: movb $0x35, %al # restore CRT register 0x35
1324 no_s31: xorw %bp, %bp # Detection failed
1325 s3rest: movb %bh, %ah
1326 movb $0x38, %al # restore old value of CRT register 0x38
1329 idS3: .byte 0x81, 0x82, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95
1330 .byte 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa8, 0xb0
1332 s3_md: .byte 0x54, 0x2b, 0x84
1333 .byte 0x55, 0x19, 0x84
1350 idati: .ascii "761295520"
1352 ati_md: .byte 0x23, 0x19, 0x84
1353 .byte 0x33, 0x2c, 0x84
1354 .byte 0x22, 0x1e, 0x64
1355 .byte 0x21, 0x19, 0x64
1356 .byte 0x58, 0x21, 0x50
1357 .byte 0x5b, 0x1e, 0x50
1379 .byte 0x22, 0x2c, 0x84
1380 .byte 0x23, 0x19, 0x84
1381 .byte 0x24, 0x1c, 0x84
1382 .byte 0x2f, 0x32, 0xa0
1383 .byte 0x32, 0x22, 0x50
1384 .byte 0x34, 0x42, 0x50
1409 .byte 0x60, 0x19, 0x84
1410 .byte 0x61, 0x32, 0x84
1412 .ascii "Chips & Technologies"
1453 nocirr: xorw %bp, %bp
1454 iscirr: movw $0x3d4, %dx
1463 .byte 0x1f, 0x19, 0x84
1464 .byte 0x20, 0x2c, 0x84
1465 .byte 0x22, 0x1e, 0x84
1466 .byte 0x31, 0x25, 0x64
1468 .ascii "Cirrus Logic 5X0"
1476 movb %al, %bl # BL=backup
1510 c5fail: xorw %bp, %bp
1511 c5done: movb $6, %al
1517 .byte 0x14, 0x19, 0x84
1518 .byte 0x54, 0x2b, 0x84
1520 .ascii "Cirrus Logic 54XX"
1523 # Cirrus Logic 64XX -- no known extra modes, but must be identified, because
1524 # it's misidentified by the Ahead test.
1529 movb %al, %bl # BL=backup
1541 call inidx # 4X, 5X, 7X and 8X are valid 64XX chip ID's.
1555 c2fail: xorw %bp, %bp
1556 c6done: movb $0x0a, %al
1563 .ascii "Cirrus Logic 64XX"
1581 evtrid: leaw trident_md, %bp
1584 noevrx: xorw %bp, %bp
1588 .byte 0x03, 0x22, 0x50
1589 .byte 0x04, 0x3c, 0x50
1590 .byte 0x07, 0x2b, 0x64
1591 .byte 0x08, 0x4b, 0x64
1592 .byte 0x0a, 0x19, 0x84
1593 .byte 0x0b, 0x2c, 0x84
1594 .byte 0x16, 0x1e, 0x50
1595 .byte 0x18, 0x1b, 0x64
1596 .byte 0x21, 0x40, 0xa0
1597 .byte 0x40, 0x1e, 0x84
1599 .ascii "Everex/Trident"
1604 leaw idgenoa, %si # Check Genoa 'clues'
1606 movb %es:(0x37), %al
1625 idgenoa: .byte 0x77, 0x00, 0x99, 0x66
1628 .byte 0x58, 0x20, 0x50
1629 .byte 0x5a, 0x2a, 0x64
1630 .byte 0x60, 0x19, 0x84
1631 .byte 0x61, 0x1d, 0x84
1632 .byte 0x62, 0x20, 0x84
1633 .byte 0x63, 0x2c, 0x84
1634 .byte 0x64, 0x3c, 0x84
1635 .byte 0x6b, 0x4f, 0x64
1636 .byte 0x72, 0x3c, 0x50
1637 .byte 0x74, 0x42, 0x50
1638 .byte 0x78, 0x4b, 0x64
1655 idoakvga: .ascii "OAK VGA "
1657 oak_md: .byte 0x4e, 0x3c, 0x50
1658 .byte 0x4f, 0x3c, 0x84
1659 .byte 0x50, 0x19, 0x84
1660 .byte 0x51, 0x2b, 0x84
1667 leaw idparadise, %si
1677 idparadise: .ascii "VGA="
1680 .byte 0x41, 0x22, 0x50
1681 .byte 0x47, 0x1c, 0x84
1682 .byte 0x55, 0x19, 0x84
1683 .byte 0x54, 0x2c, 0x84
1700 movb %al, %bl # Strange thing ... in the book this wasn't
1701 andb $0x02, %bl # necessary but it worked on my card which
1702 jz setb2 # is a trident. Without it the screen goes
1707 setb2: orb $0x02, %al
1708 clrb2: outb %al, %dx
1717 .byte 0x50, 0x1e, 0x50
1718 .byte 0x51, 0x2b, 0x50
1719 .byte 0x52, 0x3c, 0x50
1720 .byte 0x57, 0x19, 0x84
1721 .byte 0x58, 0x1e, 0x84
1722 .byte 0x59, 0x2b, 0x84
1723 .byte 0x5a, 0x3c, 0x84
1731 inb %dx, %al # Could things be this simple ! :-)
1742 isnot: xorw %bp, %bp
1746 .byte 0x26, 0x3c, 0x50
1747 .byte 0x2a, 0x28, 0x64
1748 .byte 0x23, 0x19, 0x84
1749 .byte 0x24, 0x1c, 0x84
1750 .byte 0x22, 0x2c, 0x84
1751 .byte 0x21, 0x3c, 0x84
1765 even7: movb $0x0c, %al
1790 movb $VIDEO_FIRST_V7>>8, svga_prefix # Use special mode switching
1794 .byte 0x40, 0x2b, 0x50
1795 .byte 0x43, 0x3c, 0x50
1796 .byte 0x44, 0x3c, 0x64
1797 .byte 0x41, 0x19, 0x84
1798 .byte 0x42, 0x2c, 0x84
1799 .byte 0x45, 0x1c, 0x84
1816 idrtvga: .ascii "REALTEK VGA"
1819 .byte 0x1a, 0x3c, 0x50
1820 .byte 0x1b, 0x19, 0x84
1821 .byte 0x1c, 0x1e, 0x84
1822 .byte 0x1d, 0x2b, 0x84
1823 .byte 0x1e, 0x3c, 0x84
1828 #endif /* CONFIG_VIDEO_SVGA */
1830 # User-defined local mode table (VGA only)
1831 #ifdef CONFIG_VIDEO_LOCAL
1833 leaw local_mode_table, %si
1844 # This is the table of local video modes which can be supplied manually
1845 # by the user. Each entry consists of mode ID (word) and dimensions
1846 # (byte for column count and another byte for row count). These modes
1847 # are placed before all SVGA and VESA modes and override them if table
1848 # compacting is enabled. The table must end with a zero word followed
1849 # by NUL-terminated video adapter name.
1851 .word 0x0100 # Example: 40x25
1856 #endif /* CONFIG_VIDEO_LOCAL */
1858 # Read a key and return the ASCII code in al, scan code in ah
1859 getkey: xorb %ah, %ah
1863 # Read a key with a timeout of 30 seconds.
1864 # The hardware clock is used to get the time.
1866 addb $30, %al # Wait 30 seconds
1873 again: movb $0x01, %ah
1875 jnz getkey # key pressed, so get it
1881 movb $0x20, %al # timeout, return `space'
1884 # Flush the keyboard buffer
1885 flush: movb $0x01, %ah
1895 # Print hexadecimal number.
1905 prthn: cmpb $0x0a, %al
1909 prth1: addb $0x30, %al
1912 # Print decimal number in al
1924 lt100: addb $0x30, %al
1926 skip10: movb %ah, %al
1934 #ifdef CONFIG_FIRMWARE_EDID
1935 pushw %es # just save all registers
1945 movl $0x13131313, %eax # memset block with 0x13
1953 xorw %di, %di # Report Capability
1955 popw %es # ES:DI must be 0:0
1960 popw %es # restore ES
1962 cmpb $0x00, %ah # call successful
1965 cmpb $0x4f, %al # function supported
1968 movw $0x4f15, %ax # do VBE/DDC
1976 popw %di # restore all registers
1985 # VIDEO_SELECT-only variables
1986 mt_end: .word 0 # End of video mode table if built
1987 edit_buf: .space 6 # Line editor buffer
1988 card_name: .word 0 # Pointer to adapter name
1989 scanning: .byte 0 # Performing mode scan
1990 do_restore: .byte 0 # Screen contents altered during mode change
1991 svga_prefix: .byte VIDEO_FIRST_BIOS>>8 # Default prefix for BIOS modes
1992 graphic_mode: .byte 0 # Graphic mode with a linear frame buffer
1993 dac_size: .byte 6 # DAC bit depth
1996 keymsg: .ascii "Press <RETURN> to see video modes available, "
1997 .ascii "<SPACE> to continue or wait 30 secs"
2000 listhdr: .byte 0x0d, 0x0a
2001 .ascii "Mode: COLSxROWS:"
2003 crlft: .byte 0x0d, 0x0a, 0
2005 prompt: .byte 0x0d, 0x0a
2006 .asciz "Enter mode number or `scan': "
2008 unknt: .asciz "Unknown mode ID. Try again."
2010 badmdt: .ascii "You passed an undefined mode number."
2013 vesaer: .ascii "Error: Scanning of VESA modes failed. Please "
2014 .ascii "report to <mj@ucw.cz>."
2017 old_name: .asciz "CGA/MDA/HGA"
2019 ega_name: .asciz "EGA"
2021 svga_name: .ascii " "
2023 vga_name: .asciz "VGA"
2025 vesa_name: .asciz "VESA"
2027 name_bann: .asciz "Video adapter: "
2028 #endif /* CONFIG_VIDEO_SELECT */
2031 adapter: .byte 0 # Video adapter: 0=CGA/MDA/HGA,1=EGA,2=VGA
2032 video_segment: .word 0xb800 # Video memory segment
2033 force_size: .word 0 # Use this size instead of the one in BIOS vars