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
130 leaw badmdt, %si # Invalid mode ID
134 #endif /* CONFIG_VIDEO_IGNORE_BAD_MODE */
137 #ifdef CONFIG_VIDEO_RETAIN
138 call restore_screen # Restore screen contents
139 #endif /* CONFIG_VIDEO_RETAIN */
141 #endif /* CONFIG_VIDEO_SELECT */
142 call mode_params # Store mode parameters
143 popw %ds # Restore original DS
146 # Detect if we have CGA, MDA, EGA or VGA and pass it to the kernel.
148 movb $0, %fs:(PARAM_HAVE_VGA)
149 movb $0x12, %ah # Check EGA/VGA
152 movw %bx, %fs:(PARAM_VIDEO_EGA_BX) # Identifies EGA to the kernel
153 cmpb $0x10, %bl # No, it's a CGA/MDA/HGA card.
157 movw $0x1a00, %ax # Check EGA or VGA?
159 cmpb $0x1a, %al # 1a means VGA...
160 jne basret # anything else is EGA.
162 incb %fs:(PARAM_HAVE_VGA) # We've detected a VGA
166 # Store the video mode parameters for later usage by the kernel.
167 # This is done by asking the BIOS except for the rows/columns
168 # parameters in the default 80x25 mode -- these are set directly,
169 # because some very obscure BIOSes supply insane values.
171 #ifdef CONFIG_VIDEO_SELECT
172 cmpb $0, graphic_mode
175 movb $0x03, %ah # Read cursor position
178 movw %dx, %fs:(PARAM_CURSOR_POS)
179 movb $0x0f, %ah # Read page/mode/width
181 movw %bx, %fs:(PARAM_VIDEO_PAGE)
182 movw %ax, %fs:(PARAM_VIDEO_MODE) # Video mode and screen width
183 cmpb $0x7, %al # MDA/HGA => segment differs
186 movw $0xb000, video_segment
187 mopar0: movw %gs:(0x485), %ax # Font size
188 movw %ax, %fs:(PARAM_FONT_POINTS) # (valid only on EGA/VGA)
189 movw force_size, %ax # Forced size?
193 movb %ah, %fs:(PARAM_VIDEO_COLS)
194 movb %al, %fs:(PARAM_VIDEO_LINES)
197 mopar1: movb $25, %al
198 cmpb $0, adapter # If we are on CGA/MDA/HGA, the
199 jz mopar2 # screen must have 25 lines.
201 movb %gs:(0x484), %al # On EGA/VGA, use the EGA+ BIOS
202 incb %al # location of max lines.
203 mopar2: movb %al, %fs:(PARAM_VIDEO_LINES)
206 #ifdef CONFIG_VIDEO_SELECT
207 # Fetching of VESA frame buffer parameters
209 leaw modelist+1024, %di
210 movb $0x23, %fs:(PARAM_HAVE_VGA)
212 movw %ax, %fs:(PARAM_LFB_LINELENGTH)
214 movw %ax, %fs:(PARAM_LFB_WIDTH)
216 movw %ax, %fs:(PARAM_LFB_HEIGHT)
219 movw %ax, %fs:(PARAM_LFB_DEPTH)
222 movw %ax, %fs:(PARAM_LFB_PAGES)
224 movl %eax, %fs:(PARAM_LFB_BASE)
226 movl %eax, %fs:(PARAM_LFB_COLORS)
228 movl %eax, %fs:(PARAM_LFB_COLORS+4)
230 movw %ax, %fs:(PARAM_VESA_ATTRIB)
233 leaw modelist+1024, %di
238 movl %eax, %fs:(PARAM_LFB_SIZE)
239 # get protected mode interface informations
247 movw %es, %fs:(PARAM_VESAPM_SEG)
248 movw %di, %fs:(PARAM_VESAPM_OFF)
251 # The video mode menu
253 leaw keymsg, %si # "Return/Space/Timeout" message
258 cmpb $0x0d, %al # ENTER ?
259 je listm # yes - manual mode selection
261 cmpb $0x20, %al # SPACE ?
262 je defmd1 # no - repeat
267 defmd1: ret # No mode chosen? Default 80x25
269 listm: call mode_table # List mode table
270 listm0: leaw name_bann, %si # Print adapter name
291 leaw listhdr, %si # Table header
293 movb $0x30, %dl # DL holds mode number
295 lm1: cmpw $ASK_VGA, (%si) # End?
298 movb %dl, %al # Menu selection number
306 movb $0x78, %al # the letter 'x'
309 call prtdec # Columns
310 movb $0x0d, %al # New line
314 incb %dl # Next character
321 lm2: leaw prompt, %si # Mode prompt
323 leaw edit_buf, %di # Editor buffer
325 cmpb $0x0d, %al # Enter?
328 cmpb $0x08, %al # Backspace?
331 cmpb $0x20, %al # Printable?
334 cmpw $edit_buf+4, %di # Enough space?
341 lmbs: cmpw $edit_buf, %di # Backspace
352 lment: movb $0, (%di)
356 cmpb $0, (%si) # Empty string = default mode
359 cmpb $0, 1(%si) # One character = menu selection
362 cmpw $0x6373, (%si) # "scan" => mode scanning
368 lmhx: xorw %bx, %bx # Else => mode ID in hex
391 lmuse1: movw %bx, %ax
394 mnusel: lodsb # Menu selection
405 subb $0x61-0x30-10, %al
412 lmbad: leaw unknt, %si
415 lmscan: cmpb $0, adapter # Scanning only on EGA/VGA
418 movw $0, mt_end # Scanning of modes is
419 movb $1, scanning # done as new autodetection.
424 # Additional parts of mode_set... (relative jumps, you know)
425 setv7: # Video7 extended modes
427 subb $VIDEO_FIRST_V7>>8, %bh
433 _setrec: jmp setrec # Ugly...
434 _set_80x25: jmp set_80x25
436 # Aliases for backward compatibility.
438 movw $VIDEO_80x25, %ax
442 movb $VIDEO_8POINT-VIDEO_FIRST_SPECIAL, %al
444 jnz setbad # Fall-through!
446 # Setting of user mode (AX=mode ID) => CF=success
448 movw %ax, %fs:(0x01fa) # Store mode for use in acpi_wakeup.S
453 testb $VIDEO_RECALC>>8, %ah
456 cmpb $VIDEO_FIRST_RESOLUTION>>8, %ah
459 cmpb $VIDEO_FIRST_SPECIAL>>8, %ah
462 cmpb $VIDEO_FIRST_V7>>8, %ah
465 cmpb $VIDEO_FIRST_VESA>>8, %ah
475 movb $0, do_restore # The screen needn't be restored
480 subb $VIDEO_FIRST_VESA>>8, %bh
481 movw $0x4f02, %ax # VESA BIOS mode set call
483 cmpw $0x004f, %ax # AL=4f if implemented
484 jnz setbad # AH=0 if OK
491 int $0x10 # Standard BIOS mode set call
493 movb $0x0f, %ah # Check if really set
502 setspc: xorb %bh, %bh # Set special mode
503 cmpb $VIDEO_LAST_SPECIAL-VIDEO_FIRST_SPECIAL, %bl
510 orb %al, %al # 80x25 is an exception
513 pushw %bx # Set mode chosen from menu
514 call mode_table # Build the mode table
521 movw (%si), %ax # Fetch mode ID
524 setres: pushw %bx # Set mode chosen by resolution
529 cmpw $ASK_VGA, %ax # End of the list?
536 movw -4(%si), %ax # Fetch mode ID
540 leaw modelist+1024, %di
541 subb $VIDEO_FIRST_VESA>>8, %bh
542 movw %bx, %cx # Get mode information structure
545 addb $VIDEO_FIRST_VESA>>8, %bh
549 movb (%di), %al # Check capabilities.
552 jz setvesa # This is a text mode
554 movb (%di), %al # Check capabilities.
557 jnz _setbad # Doh! No linear frame buffer.
559 subb $VIDEO_FIRST_VESA>>8, %bh
560 orw $0x4000, %bx # Use linear frame buffer
561 movw $0x4f02, %ax # VESA BIOS mode set call
563 cmpw $0x004f, %ax # AL=4f if implemented
564 jnz _setbad # AH=0 if OK
566 movb $1, graphic_mode # flag graphic mode
567 movb $0, do_restore # no screen restore
571 _setbad: jmp setbad # Ugly...
573 # Recalculate vertical display end registers -- this fixes various
574 # inconsistencies of extended modes on many adapters. Called when
575 # the VIDEO_RECALC flag is set in the mode ID.
577 setrec: subb $VIDEO_RECALC>>8, %ah # Set the base mode
581 movw %gs:(0x485), %ax # Font size in pixels
582 movb %gs:(0x484), %bl # Number of rows
584 mulb %bl # Number of visible
585 decw %ax # scan lines - 1
588 movb $0x12, %al # Lower 8 bits
591 movb $0x07, %al # Bits 8 and 9 in the overflow register
601 rct2: movb $0x07, %al
606 # Table of routines for setting of the special modes.
618 # Set the 80x25 mode. If already set, do nothing.
620 movw $0x5019, force_size # Override possibly broken BIOS
622 #ifdef CONFIG_VIDEO_400_HACK
623 movw $0x1202, %ax # Force 400 scan lines
627 movb $0x0f, %ah # Get current mode ID
629 cmpw $0x5007, %ax # Mode 7 (80x25 mono) is the only one available
630 jz st80 # on CGA/MDA/HGA and is also available on EGAM
632 cmpw $0x5003, %ax # Unknown mode, force 80x25 color
635 st80: cmpb $0, adapter # CGA/MDA/HGA => mode 3/7 is always 80x25
638 movb %gs:(0x0484), %al # This is EGA+ -- beware of 80x50 etc.
639 orb %al, %al # Some buggy BIOS'es set 0 rows
642 cmpb $24, %al # It's hopefully correct
644 #endif /* CONFIG_VIDEO_400_HACK */
646 movw $0x0003, %ax # Forced set
651 # Set the 80x50/80x43 8-pixel mode. Simple BIOS calls.
654 call use_80x25 # The base is 80x25
656 movw $0x1112, %ax # Use 8x8 font
659 movw $0x1200, %ax # Use alternate print screen
662 movw $0x1201, %ax # Turn off cursor emulation
665 movb $0x01, %ah # Define cursor scan lines 6-7
672 # Set the 80x28 mode. This mode works on all VGA's, because it's a standard
673 # 80x25 mode with 14-point fonts instead of 16-point.
676 call use_80x25 # The base is 80x25
677 set14: movw $0x1111, %ax # Use 9x14 font
680 movb $0x01, %ah # Define cursor scan lines 11-12
686 # Set the 80x43 mode. This mode is works on all VGA's.
687 # It's a 350-scanline mode with 8-pixel font.
690 movw $0x1201, %ax # Set 350 scans
693 movw $0x0003, %ax # Reset video mode
695 jmp set_8pt # Use 8-pixel font
697 # Set the 80x30 mode (all VGA's). 480 scanlines, 16-pixel font.
699 call use_80x25 # Start with real 80x25
701 movw $0x3cc, %dx # Get CRTC port
704 rorb %al # Mono or color?
708 set48a: movw $0x0c11, %ax # Vertical sync end (also unlocks CR0-7)
710 movw $0x0b06, %ax # Vertical total
712 movw $0x3e07, %ax # (Vertical) overflow
714 movw $0xea10, %ax # Vertical sync start
716 movw $0xdf12, %ax # Vertical display end
718 movw $0xe715, %ax # Vertical blank start
720 movw $0x0416, %ax # Vertical blank end
723 movb $0xcc, %dl # Misc output register (read)
725 movb $0xc2, %dl # (write)
726 andb $0x0d, %al # Preserve clock select bits and color bit
727 orb $0xe2, %al # Set correct sync polarity
730 movw $0x501e, force_size
734 # Set the 80x34 mode (all VGA's). 480 scans, 14-pixel font.
736 call set_80x30 # Set 480 scans
737 call set14 # And 14-pt font
738 movw $0xdb12, %ax # VGA vertical display end
739 movw $0x5022, force_size
744 # Set the 80x60 mode (all VGA's). 480 scans, 8-pixel font.
746 call set_80x30 # Set 480 scans
747 call set_8pt # And 8-pt font
748 movw $0xdf12, %ax # VGA vertical display end
749 movw $0x503c, force_size
752 # Special hack for ThinkPad graphics
754 #ifdef CONFIG_VIDEO_GFX_HACK
755 movw $VIDEO_GFX_BIOS_AX, %ax
756 movw $VIDEO_GFX_BIOS_BX, %bx
758 movw $VIDEO_GFX_DUMMY_RESOLUTION, force_size
763 #ifdef CONFIG_VIDEO_RETAIN
765 # Store screen contents to temporary buffer.
767 cmpb $0, do_restore # Already stored?
770 testb $CAN_USE_HEAP, loadflags # Have we space for storing?
775 pushw force_size # Don't force specific size
777 call mode_params # Obtain params of current mode
779 movb %fs:(PARAM_VIDEO_LINES), %ah
780 movb %fs:(PARAM_VIDEO_COLS), %al
781 movw %ax, %bx # BX=dimensions
783 movw %ax, %cx # CX=number of characters
784 addw %ax, %ax # Calculate image size
785 addw $modelist+1024+4, %ax
786 cmpw heap_end_ptr, %ax
787 jnc sts1 # Unfortunately, out of memory
789 movw %fs:(PARAM_CURSOR_POS), %ax # Store mode params
790 leaw modelist+1024, %di
794 pushw %ds # Store the screen
795 movw video_segment, %ds
800 incb do_restore # Screen will be restored later
805 # Restore screen contents from temporary buffer.
807 cmpb $0, do_restore # Has the screen been stored?
810 call mode_params # Get parameters of current mode
811 movb %fs:(PARAM_VIDEO_LINES), %cl
812 movb %fs:(PARAM_VIDEO_COLS), %ch
813 leaw modelist+1024, %si # Screen buffer
814 lodsw # Set cursor position
826 res3: movb $0x02, %ah
830 movb %ah, %dl # DL=number of lines
831 movb $0, %ah # BX=phys. length of orig. line
833 cmpb %cl, %dl # Too many?
844 res4: cmpb %ch, %al # Too wide?
847 movb %ch, %al # AX=width of src. line
850 movw %cx, %bp # BP=width of dest. line
852 movw video_segment, %es
853 xorw %di, %di # Move the data
854 addw %bx, %bx # Convert BX and BP to _bytes_
870 #endif /* CONFIG_VIDEO_RETAIN */
872 # Write to indexed VGA register (AL=index, AH=data, DX=index reg. port)
873 outidx: outb %al, %dx
882 # Build the table of video modes (stored after the setup.S code at the
883 # `modelist' label. Each video mode record looks like:
884 # .word MODE-ID (our special mode ID (see above))
885 # .byte rows (number of rows)
886 # .byte columns (number of columns)
887 # Returns address of the end of the table in DI, the end is marked
890 movw mt_end, %di # Already filled?
894 leaw modelist, %di # Store standard modes:
895 movl $VIDEO_80x25 + 0x50190000, %eax # The 80x25 mode (ALL)
897 movb adapter, %al # CGA/MDA/HGA -- no more modes
904 movl $VIDEO_8POINT + 0x502b0000, %eax # The 80x43 EGA mode
910 mtabv: leaw vga_modes, %si # All modes for std VGA
911 movw $vga_modes_end-vga_modes, %cx
912 rep # I'm unable to use movsw as I don't know how to store a half
913 movsb # of the expression above to cx without using explicit shr.
915 cmpb $0, scanning # Mode scan requested?
921 #ifdef CONFIG_VIDEO_LOCAL
923 #endif /* CONFIG_VIDEO_LOCAL */
925 #ifdef CONFIG_VIDEO_VESA
926 call vesa_modes # Detect VESA VGA modes
927 #endif /* CONFIG_VIDEO_VESA */
929 #ifdef CONFIG_VIDEO_SVGA
930 cmpb $0, scanning # Bypass when scanning
933 call svga_modes # Detect SVGA cards & modes
935 #endif /* CONFIG_VIDEO_SVGA */
939 #ifdef CONFIG_VIDEO_COMPACT
943 cmt1: cmpw %dx, %si # Scan all modes
946 leaw modelist, %bx # Find in previous entries
951 cmpw 2(%bx), %cx # Found => don't copy this entry
957 cmt4: movsl # Copy entry
960 cmt5: addw $4, %si # Skip entry
964 #endif /* CONFIG_VIDEO_COMPACT */
966 movw $ASK_VGA, (%di) # End marker
968 mtab1: leaw modelist, %si # SI=mode list, DI=list end
971 # Modes usable on all standard VGAs
985 #ifdef CONFIG_VIDEO_GFX_HACK
987 .word VIDEO_GFX_DUMMY_RESOLUTION
993 #ifdef CONFIG_VIDEO_VESA
995 cmpb $2, adapter # VGA only
998 movw %di, %bp # BP=original mode table end
999 addw $0x200, %di # Buffer space
1000 movw $0x4f00, %ax # VESA Get card info call
1003 cmpw $0x004f, %ax # Successful?
1006 cmpw $0x4556, 0x200(%di)
1009 cmpw $0x4153, 0x202(%di)
1012 movw $vesa_name, card_name # Set name to "VESA VGA"
1014 lgsw 0x20e(%di), %si # GS:SI=mode list
1015 movw $128, %cx # Iteration limit
1017 # gas version 2.9.1, using BFD version 2.9.1.0.23 buggers the next inst.
1018 # XXX: lodsw %gs:(%si), %ax # Get next mode in the list
1020 cmpw $0xffff, %ax # End of the table?
1023 cmpw $0x0080, %ax # Check validity of mode ID
1026 orb %ah, %ah # Valid IDs: 0x0000-0x007f/0x0100-0x07ff
1027 jz vesan # Certain BIOSes report 0x80-0xff!
1033 movw %ax, %cx # Get mode information structure
1036 movw %cx, %bx # BX=mode number
1037 addb $VIDEO_FIRST_VESA>>8, %bh
1040 jnz vesan # Don't report errors (buggy BIOSES)
1042 movb (%di), %al # Check capabilities. We require
1043 andb $0x19, %al # a color text mode.
1047 cmpw $0xb800, 8(%di) # Standard video memory address required
1050 testb $2, (%di) # Mode characteristics supplied?
1051 movw %bx, (%di) # Store mode number
1055 movw 0x12(%di), %bx # Width
1060 movw 0x14(%di), %ax # Height
1066 cmpw $8193, %ax # Small enough for Linux console driver?
1071 vesa3: subw $0x8108, %bx # This mode has no detailed info specified,
1072 jc vesan # so it must be a standard VESA mode.
1077 movw vesa_text_mode_table(%bx), %ax
1079 vesaok: addw $4, %di # The mode is valid. Store it.
1080 vesan: loop vesa1 # Next mode. Limit exceeded => error
1081 vesae: leaw vesaer, %si
1083 movw %bp, %di # Discard already found modes.
1087 # Dimensions of standard VESA text modes
1088 vesa_text_mode_table:
1090 .byte 25, 132 # 0109
1091 .byte 43, 132 # 010A
1092 .byte 50, 132 # 010B
1093 .byte 60, 132 # 010C
1094 #endif /* CONFIG_VIDEO_VESA */
1096 # Scan for video modes. A bit dirty, but should work.
1098 movw $0x0100, %cx # Start with mode 0
1099 scm1: movb $0, %ah # Test the mode
1105 jnz scm2 # Mode not set
1107 movw $0x3c0, %dx # Test if it's a text mode
1108 movb $0x10, %al # Mode bits
1113 movb $0xce, %dl # Another set of mode bits
1119 movb $0xd4, %dl # Cursor location
1125 movw %cx, %ax # Ok, store the mode
1127 movb %gs:(0x484), %al # Number of rows
1130 movw %gs:(0x44a), %ax # Number of columns
1135 movw $0x0003, %ax # Return back to mode 3
1139 tstidx: outw %ax, %dx # OUT DX,AX and inidx
1140 inidx: outb %al, %dx # Read from indexed VGA register
1141 incw %dx # AL=index, DX=index reg port -> AL=data
1146 # Try to detect type of SVGA card and supply (usually approximate) video
1147 # mode table for it.
1149 #ifdef CONFIG_VIDEO_SVGA
1151 leaw svga_table, %si # Test all known SVGA adapters
1153 movw %ax, %bp # Default mode table
1157 lodsw # Pointer to test routine
1163 call *%ax # Call test routine
1170 movw %bp, %si # Found, copy the modes
1171 movb svga_prefix, %ah
1180 didsv: movw %si, card_name # Store pointer to card name
1183 # Table of all known SVGA cards. For each card, we store a pointer to
1184 # a table of video modes supported by the card and a pointer to a routine
1185 # used for testing of presence of the card. The video mode table is always
1186 # followed by the name of the card or the chipset.
1188 .word ati_md, ati_test
1189 .word oak_md, oak_test
1190 .word paradise_md, paradise_test
1191 .word realtek_md, realtek_test
1192 .word s3_md, s3_test
1193 .word chips_md, chips_test
1194 .word video7_md, video7_test
1195 .word cirrus5_md, cirrus5_test
1196 .word cirrus6_md, cirrus6_test
1197 .word cirrus1_md, cirrus1_test
1198 .word ahead_md, ahead_test
1199 .word everex_md, everex_test
1200 .word genoa_md, genoa_test
1201 .word trident_md, trident_test
1202 .word tseng_md, tseng_test
1205 # Test routines and mode tables:
1207 # S3 - The test algorithm was taken from the SuperProbe package
1208 # for XFree86 1.2.1. Report bugs to Christoph.Niemann@linux.org
1210 movw $0x0f35, %cx # we store some constants in cl/ch
1214 movb %al, %bh # store current CRT-register 0x38
1216 call outidx # disable writing to special regs
1217 movb %cl, %al # check whether we can write special reg 0x35
1219 movb %al, %bl # save the current value of CRT reg 0x35
1220 andb $0xf0, %al # clear bits 0-3
1222 movb %cl, %al # and write it to CRT reg 0x35
1224 call inidx # now read it back
1225 andb %ch, %al # clear the upper 4 bits
1226 jz s3_2 # the first test failed. But we have a
1228 movb %bl, %ah # second chance
1231 jmp s3_1 # do the other tests
1233 s3_2: movw %cx, %ax # load ah with 0xf and al with 0x35
1234 orb %bl, %ah # set the upper 4 bits of ah with the orig value
1235 call outidx # write ...
1236 call inidx # ... and reread
1237 andb %cl, %al # turn off the upper 4 bits
1239 movb %bl, %ah # restore old value in register 0x35
1243 cmpb %ch, %al # setting lower 4 bits was successful => bad
1244 je no_s3 # writing is allowed => this is not an S3
1246 s3_1: movw $0x4838, %ax # allow writing to special regs by putting
1247 call outidx # magic number into CRT-register 0x38
1248 movb %cl, %al # check whether we can write special reg 0x35
1257 jnz no_s3 # no, we can't write => no S3
1265 movb %bl, %ah # restore old value in register 0x35
1270 jne no_s31 # writing not possible => no S3
1272 call inidx # now get the S3 id ...
1283 no_s3: movb $0x35, %al # restore CRT register 0x35
1286 no_s31: xorw %bp, %bp # Detection failed
1287 s3rest: movb %bh, %ah
1288 movb $0x38, %al # restore old value of CRT register 0x38
1291 idS3: .byte 0x81, 0x82, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95
1292 .byte 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa8, 0xb0
1294 s3_md: .byte 0x54, 0x2b, 0x84
1295 .byte 0x55, 0x19, 0x84
1312 idati: .ascii "761295520"
1314 ati_md: .byte 0x23, 0x19, 0x84
1315 .byte 0x33, 0x2c, 0x84
1316 .byte 0x22, 0x1e, 0x64
1317 .byte 0x21, 0x19, 0x64
1318 .byte 0x58, 0x21, 0x50
1319 .byte 0x5b, 0x1e, 0x50
1341 .byte 0x22, 0x2c, 0x84
1342 .byte 0x23, 0x19, 0x84
1343 .byte 0x24, 0x1c, 0x84
1344 .byte 0x2f, 0x32, 0xa0
1345 .byte 0x32, 0x22, 0x50
1346 .byte 0x34, 0x42, 0x50
1371 .byte 0x60, 0x19, 0x84
1372 .byte 0x61, 0x32, 0x84
1374 .ascii "Chips & Technologies"
1415 nocirr: xorw %bp, %bp
1416 iscirr: movw $0x3d4, %dx
1425 .byte 0x1f, 0x19, 0x84
1426 .byte 0x20, 0x2c, 0x84
1427 .byte 0x22, 0x1e, 0x84
1428 .byte 0x31, 0x25, 0x64
1430 .ascii "Cirrus Logic 5X0"
1438 movb %al, %bl # BL=backup
1472 c5fail: xorw %bp, %bp
1473 c5done: movb $6, %al
1479 .byte 0x14, 0x19, 0x84
1480 .byte 0x54, 0x2b, 0x84
1482 .ascii "Cirrus Logic 54XX"
1485 # Cirrus Logic 64XX -- no known extra modes, but must be identified, because
1486 # it's misidentified by the Ahead test.
1491 movb %al, %bl # BL=backup
1503 call inidx # 4X, 5X, 7X and 8X are valid 64XX chip ID's.
1517 c2fail: xorw %bp, %bp
1518 c6done: movb $0x0a, %al
1525 .ascii "Cirrus Logic 64XX"
1543 evtrid: leaw trident_md, %bp
1546 noevrx: xorw %bp, %bp
1550 .byte 0x03, 0x22, 0x50
1551 .byte 0x04, 0x3c, 0x50
1552 .byte 0x07, 0x2b, 0x64
1553 .byte 0x08, 0x4b, 0x64
1554 .byte 0x0a, 0x19, 0x84
1555 .byte 0x0b, 0x2c, 0x84
1556 .byte 0x16, 0x1e, 0x50
1557 .byte 0x18, 0x1b, 0x64
1558 .byte 0x21, 0x40, 0xa0
1559 .byte 0x40, 0x1e, 0x84
1561 .ascii "Everex/Trident"
1566 leaw idgenoa, %si # Check Genoa 'clues'
1568 movb %es:(0x37), %al
1587 idgenoa: .byte 0x77, 0x00, 0x99, 0x66
1590 .byte 0x58, 0x20, 0x50
1591 .byte 0x5a, 0x2a, 0x64
1592 .byte 0x60, 0x19, 0x84
1593 .byte 0x61, 0x1d, 0x84
1594 .byte 0x62, 0x20, 0x84
1595 .byte 0x63, 0x2c, 0x84
1596 .byte 0x64, 0x3c, 0x84
1597 .byte 0x6b, 0x4f, 0x64
1598 .byte 0x72, 0x3c, 0x50
1599 .byte 0x74, 0x42, 0x50
1600 .byte 0x78, 0x4b, 0x64
1617 idoakvga: .ascii "OAK VGA "
1619 oak_md: .byte 0x4e, 0x3c, 0x50
1620 .byte 0x4f, 0x3c, 0x84
1621 .byte 0x50, 0x19, 0x84
1622 .byte 0x51, 0x2b, 0x84
1629 leaw idparadise, %si
1639 idparadise: .ascii "VGA="
1642 .byte 0x41, 0x22, 0x50
1643 .byte 0x47, 0x1c, 0x84
1644 .byte 0x55, 0x19, 0x84
1645 .byte 0x54, 0x2c, 0x84
1662 movb %al, %bl # Strange thing ... in the book this wasn't
1663 andb $0x02, %bl # necessary but it worked on my card which
1664 jz setb2 # is a trident. Without it the screen goes
1669 setb2: orb $0x02, %al
1670 clrb2: outb %al, %dx
1679 .byte 0x50, 0x1e, 0x50
1680 .byte 0x51, 0x2b, 0x50
1681 .byte 0x52, 0x3c, 0x50
1682 .byte 0x57, 0x19, 0x84
1683 .byte 0x58, 0x1e, 0x84
1684 .byte 0x59, 0x2b, 0x84
1685 .byte 0x5a, 0x3c, 0x84
1693 inb %dx, %al # Could things be this simple ! :-)
1704 isnot: xorw %bp, %bp
1708 .byte 0x26, 0x3c, 0x50
1709 .byte 0x2a, 0x28, 0x64
1710 .byte 0x23, 0x19, 0x84
1711 .byte 0x24, 0x1c, 0x84
1712 .byte 0x22, 0x2c, 0x84
1713 .byte 0x21, 0x3c, 0x84
1727 even7: movb $0x0c, %al
1752 movb $VIDEO_FIRST_V7>>8, svga_prefix # Use special mode switching
1756 .byte 0x40, 0x2b, 0x50
1757 .byte 0x43, 0x3c, 0x50
1758 .byte 0x44, 0x3c, 0x64
1759 .byte 0x41, 0x19, 0x84
1760 .byte 0x42, 0x2c, 0x84
1761 .byte 0x45, 0x1c, 0x84
1778 idrtvga: .ascii "REALTEK VGA"
1781 .byte 0x1a, 0x3c, 0x50
1782 .byte 0x1b, 0x19, 0x84
1783 .byte 0x1c, 0x1e, 0x84
1784 .byte 0x1d, 0x2b, 0x84
1785 .byte 0x1e, 0x3c, 0x84
1790 #endif /* CONFIG_VIDEO_SVGA */
1792 # User-defined local mode table (VGA only)
1793 #ifdef CONFIG_VIDEO_LOCAL
1795 leaw local_mode_table, %si
1806 # This is the table of local video modes which can be supplied manually
1807 # by the user. Each entry consists of mode ID (word) and dimensions
1808 # (byte for column count and another byte for row count). These modes
1809 # are placed before all SVGA and VESA modes and override them if table
1810 # compacting is enabled. The table must end with a zero word followed
1811 # by NUL-terminated video adapter name.
1813 .word 0x0100 # Example: 40x25
1818 #endif /* CONFIG_VIDEO_LOCAL */
1820 # Read a key and return the ASCII code in al, scan code in ah
1821 getkey: xorb %ah, %ah
1825 # Read a key with a timeout of 30 seconds.
1826 # The hardware clock is used to get the time.
1828 addb $30, %al # Wait 30 seconds
1835 again: movb $0x01, %ah
1837 jnz getkey # key pressed, so get it
1843 movb $0x20, %al # timeout, return `space'
1846 # Flush the keyboard buffer
1847 flush: movb $0x01, %ah
1857 # Print hexadecimal number.
1867 prthn: cmpb $0x0a, %al
1871 prth1: addb $0x30, %al
1874 # Print decimal number in al
1886 lt100: addb $0x30, %al
1888 skip10: movb %ah, %al
1896 pushw %es # just save all registers
1906 movl $0x13131313, %eax # memset block with 0x13
1913 movw $0x4f15, %ax # do VBE/DDC
1920 popw %di # restore all registers
1928 # VIDEO_SELECT-only variables
1929 mt_end: .word 0 # End of video mode table if built
1930 edit_buf: .space 6 # Line editor buffer
1931 card_name: .word 0 # Pointer to adapter name
1932 scanning: .byte 0 # Performing mode scan
1933 do_restore: .byte 0 # Screen contents altered during mode change
1934 svga_prefix: .byte VIDEO_FIRST_BIOS>>8 # Default prefix for BIOS modes
1935 graphic_mode: .byte 0 # Graphic mode with a linear frame buffer
1938 keymsg: .ascii "Press <RETURN> to see video modes available, "
1939 .ascii "<SPACE> to continue or wait 30 secs"
1942 listhdr: .byte 0x0d, 0x0a
1943 .ascii "Mode: COLSxROWS:"
1945 crlft: .byte 0x0d, 0x0a, 0
1947 prompt: .byte 0x0d, 0x0a
1948 .asciz "Enter mode number or `scan': "
1950 unknt: .asciz "Unknown mode ID. Try again."
1952 badmdt: .ascii "You passed an undefined mode number."
1955 vesaer: .ascii "Error: Scanning of VESA modes failed. Please "
1956 .ascii "report to <mj@ucw.cz>."
1959 old_name: .asciz "CGA/MDA/HGA"
1961 ega_name: .asciz "EGA"
1963 svga_name: .ascii " "
1965 vga_name: .asciz "VGA"
1967 vesa_name: .asciz "VESA"
1969 name_bann: .asciz "Video adapter: "
1970 #endif /* CONFIG_VIDEO_SELECT */
1973 adapter: .byte 0 # Video adapter: 0=CGA/MDA/HGA,1=EGA,2=VGA
1974 video_segment: .word 0xb800 # Video memory segment
1975 force_size: .word 0 # Use this size instead of the one in BIOS vars