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
101 /* Define DO_STORE according to CONFIG_VIDEO_RETAIN */
102 #ifdef CONFIG_VIDEO_RETAIN
103 #define DO_STORE call store_screen
106 #endif /* CONFIG_VIDEO_RETAIN */
108 # This is the main entry point called by setup.S
109 # %ds *must* be pointing to the bootsector
110 video: pushw %ds # We use different segments
111 pushw %ds # FS contains original DS
113 pushw %cs # DS is equal to CS
115 pushw %cs # ES is equal to CS
118 movw %ax, %gs # GS is zero
120 call basic_detect # Basic adapter type testing (EGA/VGA/MDA/CGA)
121 #ifdef CONFIG_VIDEO_SELECT
122 movw %fs:(0x01fa), %ax # User selected video mode
123 cmpw $ASK_VGA, %ax # Bring up the menu
126 call mode_set # Set the mode
129 leaw badmdt, %si # Invalid mode ID
133 #ifdef CONFIG_VIDEO_RETAIN
134 call restore_screen # Restore screen contents
135 #endif /* CONFIG_VIDEO_RETAIN */
136 #endif /* CONFIG_VIDEO_SELECT */
137 call mode_params # Store mode parameters
138 popw %ds # Restore original DS
141 # Detect if we have CGA, MDA, EGA or VGA and pass it to the kernel.
143 movb $0, %fs:(PARAM_HAVE_VGA)
144 movb $0x12, %ah # Check EGA/VGA
147 movw %bx, %fs:(PARAM_VIDEO_EGA_BX) # Identifies EGA to the kernel
148 cmpb $0x10, %bl # No, it's a CGA/MDA/HGA card.
152 movw $0x1a00, %ax # Check EGA or VGA?
154 cmpb $0x1a, %al # 1a means VGA...
155 jne basret # anything else is EGA.
157 incb %fs:(PARAM_HAVE_VGA) # We've detected a VGA
161 # Store the video mode parameters for later usage by the kernel.
162 # This is done by asking the BIOS except for the rows/columns
163 # parameters in the default 80x25 mode -- these are set directly,
164 # because some very obscure BIOSes supply insane values.
166 #ifdef CONFIG_VIDEO_SELECT
167 cmpb $0, graphic_mode
170 movb $0x03, %ah # Read cursor position
173 movw %dx, %fs:(PARAM_CURSOR_POS)
174 movb $0x0f, %ah # Read page/mode/width
176 movw %bx, %fs:(PARAM_VIDEO_PAGE)
177 movw %ax, %fs:(PARAM_VIDEO_MODE) # Video mode and screen width
178 cmpb $0x7, %al # MDA/HGA => segment differs
181 movw $0xb000, video_segment
182 mopar0: movw %gs:(0x485), %ax # Font size
183 movw %ax, %fs:(PARAM_FONT_POINTS) # (valid only on EGA/VGA)
184 movw force_size, %ax # Forced size?
188 movb %ah, %fs:(PARAM_VIDEO_COLS)
189 movb %al, %fs:(PARAM_VIDEO_LINES)
192 mopar1: movb $25, %al
193 cmpb $0, adapter # If we are on CGA/MDA/HGA, the
194 jz mopar2 # screen must have 25 lines.
196 movb %gs:(0x484), %al # On EGA/VGA, use the EGA+ BIOS
197 incb %al # location of max lines.
198 mopar2: movb %al, %fs:(PARAM_VIDEO_LINES)
201 #ifdef CONFIG_VIDEO_SELECT
202 # Fetching of VESA frame buffer parameters
204 leaw modelist+1024, %di
205 movb $0x23, %fs:(PARAM_HAVE_VGA)
207 movw %ax, %fs:(PARAM_LFB_LINELENGTH)
209 movw %ax, %fs:(PARAM_LFB_WIDTH)
211 movw %ax, %fs:(PARAM_LFB_HEIGHT)
214 movw %ax, %fs:(PARAM_LFB_DEPTH)
217 movw %ax, %fs:(PARAM_LFB_PAGES)
219 movl %eax, %fs:(PARAM_LFB_BASE)
221 movl %eax, %fs:(PARAM_LFB_COLORS)
223 movl %eax, %fs:(PARAM_LFB_COLORS+4)
226 leaw modelist+1024, %di
231 movl %eax, %fs:(PARAM_LFB_SIZE)
232 # get protected mode interface informations
240 movw %es, %fs:(PARAM_VESAPM_SEG)
241 movw %di, %fs:(PARAM_VESAPM_OFF)
244 # The video mode menu
246 leaw keymsg, %si # "Return/Space/Timeout" message
251 cmpb $0x0d, %al # ENTER ?
252 je listm # yes - manual mode selection
254 cmpb $0x20, %al # SPACE ?
255 je defmd1 # no - repeat
260 defmd1: ret # No mode chosen? Default 80x25
262 listm: call mode_table # List mode table
263 listm0: leaw name_bann, %si # Print adapter name
284 leaw listhdr, %si # Table header
286 movb $0x30, %dl # DL holds mode number
288 lm1: cmpw $ASK_VGA, (%si) # End?
291 movb %dl, %al # Menu selection number
299 movb $0x78, %al # the letter 'x'
302 call prtdec # Columns
303 movb $0x0d, %al # New line
307 incb %dl # Next character
314 lm2: leaw prompt, %si # Mode prompt
316 leaw edit_buf, %di # Editor buffer
318 cmpb $0x0d, %al # Enter?
321 cmpb $0x08, %al # Backspace?
324 cmpb $0x20, %al # Printable?
327 cmpw $edit_buf+4, %di # Enough space?
334 lmbs: cmpw $edit_buf, %di # Backspace
345 lment: movb $0, (%di)
349 cmpb $0, (%si) # Empty string = default mode
352 cmpb $0, 1(%si) # One character = menu selection
355 cmpw $0x6373, (%si) # "scan" => mode scanning
361 lmhx: xorw %bx, %bx # Else => mode ID in hex
384 lmuse1: movw %bx, %ax
387 mnusel: lodsb # Menu selection
398 subb $0x61-0x30-10, %al
405 lmbad: leaw unknt, %si
408 lmscan: cmpb $0, adapter # Scanning only on EGA/VGA
411 movw $0, mt_end # Scanning of modes is
412 movb $1, scanning # done as new autodetection.
417 # Additional parts of mode_set... (relative jumps, you know)
418 setv7: # Video7 extended modes
420 subb $VIDEO_FIRST_V7>>8, %bh
426 _setrec: jmp setrec # Ugly...
427 _set_80x25: jmp set_80x25
429 # Aliases for backward compatibility.
431 movw $VIDEO_80x25, %ax
435 movb $VIDEO_8POINT-VIDEO_FIRST_SPECIAL, %al
437 jnz setbad # Fall-through!
439 # Setting of user mode (AX=mode ID) => CF=success
445 testb $VIDEO_RECALC>>8, %ah
448 cmpb $VIDEO_FIRST_RESOLUTION>>8, %ah
451 cmpb $VIDEO_FIRST_SPECIAL>>8, %ah
454 cmpb $VIDEO_FIRST_V7>>8, %ah
457 cmpb $VIDEO_FIRST_VESA>>8, %ah
467 movb $0, do_restore # The screen needn't be restored
472 subb $VIDEO_FIRST_VESA>>8, %bh
473 movw $0x4f02, %ax # VESA BIOS mode set call
475 cmpw $0x004f, %ax # AL=4f if implemented
476 jnz setbad # AH=0 if OK
483 int $0x10 # Standard BIOS mode set call
485 movb $0x0f, %ah # Check if really set
494 setspc: xorb %bh, %bh # Set special mode
495 cmpb $VIDEO_LAST_SPECIAL-VIDEO_FIRST_SPECIAL, %bl
499 .word 0xa7ff, spec_inits # JMP [BX+spec_inits]
502 orb %al, %al # 80x25 is an exception
505 pushw %bx # Set mode chosen from menu
506 call mode_table # Build the mode table
513 movw (%si), %ax # Fetch mode ID
516 setres: pushw %bx # Set mode chosen by resolution
521 cmpw $ASK_VGA, %ax # End of the list?
528 movw -4(%si), %ax # Fetch mode ID
532 leaw modelist+1024, %di
533 subb $VIDEO_FIRST_VESA>>8, %bh
534 movw %bx, %cx # Get mode information structure
537 addb $VIDEO_FIRST_VESA>>8, %bh
541 movb (%di), %al # Check capabilities.
544 jz setvesa # This is a text mode
546 movb (%di), %al # Check capabilities.
549 jnz _setbad # Doh! No linear frame buffer.
551 subb $VIDEO_FIRST_VESA>>8, %bh
552 orw $0x4000, %bx # Use linear frame buffer
553 movw $0x4f02, %ax # VESA BIOS mode set call
555 cmpw $0x004f, %ax # AL=4f if implemented
556 jnz _setbad # AH=0 if OK
558 movb $1, graphic_mode # flag graphic mode
559 movb $0, do_restore # no screen restore
563 _setbad: jmp setbad # Ugly...
565 # Recalculate vertical display end registers -- this fixes various
566 # inconsistencies of extended modes on many adapters. Called when
567 # the VIDEO_RECALC flag is set in the mode ID.
569 setrec: subb $VIDEO_RECALC>>8, %ah # Set the base mode
573 movw %gs:(0x485), %ax # Font size in pixels
574 movb %gs:(0x484), %bl # Number of rows
576 mulb %bl # Number of visible
577 decw %ax # scan lines - 1
580 movb $0x12, %al # Lower 8 bits
583 movb $0x07, %al # Bits 8 and 9 in the overflow register
593 rct2: movb $0x07, %al
598 # Table of routines for setting of the special modes.
610 # Set the 80x25 mode. If already set, do nothing.
612 movw $0x5019, force_size # Override possibly broken BIOS
614 #ifdef CONFIG_VIDEO_400_HACK
615 movw $0x1202, %ax # Force 400 scan lines
619 movb $0x0f, %ah # Get current mode ID
621 cmpw $0x5007, %ax # Mode 7 (80x25 mono) is the only one available
622 jz st80 # on CGA/MDA/HGA and is also available on EGAM
624 cmpw $0x5003, %ax # Unknown mode, force 80x25 color
627 st80: cmpb $0, adapter # CGA/MDA/HGA => mode 3/7 is always 80x25
630 movb %gs:(0x0484), %al # This is EGA+ -- beware of 80x50 etc.
631 orb %al, %al # Some buggy BIOS'es set 0 rows
634 cmpb $24, %al # It's hopefully correct
636 #endif /* CONFIG_VIDEO_400_HACK */
638 movw $0x0003, %ax # Forced set
643 # Set the 80x50/80x43 8-pixel mode. Simple BIOS calls.
646 call use_80x25 # The base is 80x25
648 movw $0x1112, %ax # Use 8x8 font
651 movw $0x1200, %ax # Use alternate print screen
654 movw $0x1201, %ax # Turn off cursor emulation
657 movb $0x01, %ah # Define cursor scan lines 6-7
664 # Set the 80x28 mode. This mode works on all VGA's, because it's a standard
665 # 80x25 mode with 14-point fonts instead of 16-point.
668 call use_80x25 # The base is 80x25
669 set14: movw $0x1111, %ax # Use 9x14 font
672 movb $0x01, %ah # Define cursor scan lines 11-12
678 # Set the 80x43 mode. This mode is works on all VGA's.
679 # It's a 350-scanline mode with 8-pixel font.
682 movw $0x1201, %ax # Set 350 scans
685 movw $0x0003, %ax # Reset video mode
687 jmp set_8pt # Use 8-pixel font
689 # Set the 80x30 mode (all VGA's). 480 scanlines, 16-pixel font.
691 call use_80x25 # Start with real 80x25
693 movw $0x3cc, %dx # Get CRTC port
696 rorb %al # Mono or color?
700 set48a: movw $0x0c11, %ax # Vertical sync end (also unlocks CR0-7)
702 movw $0x0b06, %ax # Vertical total
704 movw $0x3e07, %ax # (Vertical) overflow
706 movw $0xea10, %ax # Vertical sync start
708 movw $0xdf12, %ax # Vertical display end
710 movw $0xe715, %ax # Vertical blank start
712 movw $0x0416, %ax # Vertical blank end
715 movb $0xcc, %dl # Misc output register (read)
717 movb $0xc2, %dl # (write)
718 andb $0x0d, %al # Preserve clock select bits and color bit
719 orb $0xe2, %al # Set correct sync polarity
722 movw $0x501e, force_size
726 # Set the 80x34 mode (all VGA's). 480 scans, 14-pixel font.
728 call set_80x30 # Set 480 scans
729 call set14 # And 14-pt font
730 movw $0xdb12, %ax # VGA vertical display end
731 movw $0x5022, force_size
736 # Set the 80x60 mode (all VGA's). 480 scans, 8-pixel font.
738 call set_80x30 # Set 480 scans
739 call set_8pt # And 8-pt font
740 movw $0xdf12, %ax # VGA vertical display end
741 movw $0x503c, force_size
744 # Special hack for ThinkPad graphics
746 #ifdef CONFIG_VIDEO_GFX_HACK
747 movw $VIDEO_GFX_BIOS_AX, %ax
748 movw $VIDEO_GFX_BIOS_BX, %bx
750 movw $VIDEO_GFX_DUMMY_RESOLUTION, force_size
755 #ifdef CONFIG_VIDEO_RETAIN
757 # Store screen contents to temporary buffer.
759 cmpb $0, do_restore # Already stored?
762 testb $CAN_USE_HEAP, loadflags # Have we space for storing?
767 pushw force_size # Don't force specific size
769 call mode_params # Obtain params of current mode
771 movb %fs:(PARAM_VIDEO_LINES), %ah
772 movb %fs:(PARAM_VIDEO_COLS), %al
773 movw %ax, %bx # BX=dimensions
775 movw %ax, %cx # CX=number of characters
776 addw %ax, %ax # Calculate image size
777 addw $modelist+1024+4, %ax
778 cmpw heap_end_ptr, %ax
779 jnc sts1 # Unfortunately, out of memory
781 movw %fs:(PARAM_CURSOR_POS), %ax # Store mode params
782 leaw modelist+1024, %di
786 pushw %ds # Store the screen
787 movw video_segment, %ds
792 incb do_restore # Screen will be restored later
797 # Restore screen contents from temporary buffer.
799 cmpb $0, do_restore # Has the screen been stored?
802 call mode_params # Get parameters of current mode
803 movb %fs:(PARAM_VIDEO_LINES), %cl
804 movb %fs:(PARAM_VIDEO_COLS), %ch
805 leaw modelist+1024, %si # Screen buffer
806 lodsw # Set cursor position
818 res3: movb $0x02, %ah
822 movb %ah, %dl # DL=number of lines
823 movb $0, %ah # BX=phys. length of orig. line
825 cmpb %cl, %dl # Too many?
836 res4: cmpb %ch, %al # Too wide?
839 movb %ch, %al # AX=width of src. line
842 movw %cx, %bp # BP=width of dest. line
844 movw video_segment, %es
845 xorw %di, %di # Move the data
846 addw %bx, %bx # Convert BX and BP to _bytes_
862 #endif /* CONFIG_VIDEO_RETAIN */
864 # Write to indexed VGA register (AL=index, AH=data, DX=index reg. port)
865 outidx: outb %al, %dx
874 # Build the table of video modes (stored after the setup.S code at the
875 # `modelist' label. Each video mode record looks like:
876 # .word MODE-ID (our special mode ID (see above))
877 # .byte rows (number of rows)
878 # .byte columns (number of columns)
879 # Returns address of the end of the table in DI, the end is marked
882 movw mt_end, %di # Already filled?
886 leaw modelist, %di # Store standard modes:
887 movl $VIDEO_80x25 + 0x50190000, %eax # The 80x25 mode (ALL)
889 movb adapter, %al # CGA/MDA/HGA -- no more modes
896 movl $VIDEO_8POINT + 0x502b0000, %eax # The 80x43 EGA mode
902 mtabv: leaw vga_modes, %si # All modes for std VGA
903 movw $vga_modes_end-vga_modes, %cx
904 rep # I'm unable to use movsw as I don't know how to store a half
905 movsb # of the expression above to cx without using explicit shr.
907 cmpb $0, scanning # Mode scan requested?
913 #ifdef CONFIG_VIDEO_LOCAL
915 #endif /* CONFIG_VIDEO_LOCAL */
917 #ifdef CONFIG_VIDEO_VESA
918 call vesa_modes # Detect VESA VGA modes
919 #endif /* CONFIG_VIDEO_VESA */
921 #ifdef CONFIG_VIDEO_SVGA
922 cmpb $0, scanning # Bypass when scanning
925 call svga_modes # Detect SVGA cards & modes
927 #endif /* CONFIG_VIDEO_SVGA */
931 #ifdef CONFIG_VIDEO_COMPACT
935 cmt1: cmpw %dx, %si # Scan all modes
938 leaw modelist, %bx # Find in previous entries
943 cmpw 2(%bx), %cx # Found => don't copy this entry
949 cmt4: movsl # Copy entry
952 cmt5: addw $4, %si # Skip entry
956 #endif /* CONFIG_VIDEO_COMPACT */
958 movw $ASK_VGA, (%di) # End marker
960 mtab1: leaw modelist, %si # SI=mode list, DI=list end
963 # Modes usable on all standard VGAs
977 #ifdef CONFIG_VIDEO_GFX_HACK
979 .word VIDEO_GFX_DUMMY_RESOLUTION
985 #ifdef CONFIG_VIDEO_VESA
987 cmpb $2, adapter # VGA only
990 movw %di, %bp # BP=original mode table end
991 addw $0x200, %di # Buffer space
992 movw $0x4f00, %ax # VESA Get card info call
995 cmpw $0x004f, %ax # Successful?
998 cmpw $0x4556, 0x200(%di)
1001 cmpw $0x4153, 0x202(%di)
1004 movw $vesa_name, card_name # Set name to "VESA VGA"
1006 lgsw 0x20e(%di), %si # GS:SI=mode list
1007 movw $128, %cx # Iteration limit
1009 # gas version 2.9.1, using BFD version 2.9.1.0.23 buggers the next inst.
1010 # XXX: lodsw %gs:(%si), %ax # Get next mode in the list
1011 .byte 0x65, 0xAD # %gs seg prefix + lodsw
1012 cmpw $0xffff, %ax # End of the table?
1015 cmpw $0x0080, %ax # Check validity of mode ID
1018 orb %ah, %ah # Valid IDs: 0x0000-0x007f/0x0100-0x07ff
1019 jz vesan # Certain BIOSes report 0x80-0xff!
1025 movw %ax, %cx # Get mode information structure
1028 movw %cx, %bx # BX=mode number
1029 addb $VIDEO_FIRST_VESA>>8, %bh
1032 jnz vesan # Don't report errors (buggy BIOSES)
1034 movb (%di), %al # Check capabilities. We require
1035 andb $0x19, %al # a color text mode.
1039 cmpw $0xb800, 8(%di) # Standard video memory address required
1042 testb $2, (%di) # Mode characteristics supplied?
1043 movw %bx, (%di) # Store mode number
1047 movw 0x12(%di), %bx # Width
1052 movw 0x14(%di), %ax # Height
1058 cmpw $8193, %ax # Small enough for Linux console driver?
1063 vesa3: subw $0x8108, %bx # This mode has no detailed info specified,
1064 jc vesan # so it must be a standard VESA mode.
1069 movw vesa_text_mode_table(%bx), %ax
1071 vesaok: addw $4, %di # The mode is valid. Store it.
1072 vesan: loop vesa1 # Next mode. Limit exceeded => error
1073 vesae: leaw vesaer, %si
1075 movw %bp, %di # Discard already found modes.
1079 # Dimensions of standard VESA text modes
1080 vesa_text_mode_table:
1082 .byte 25, 132 # 0109
1083 .byte 43, 132 # 010A
1084 .byte 50, 132 # 010B
1085 .byte 60, 132 # 010C
1086 #endif /* CONFIG_VIDEO_VESA */
1088 # Scan for video modes. A bit dirty, but should work.
1090 movw $0x0100, %cx # Start with mode 0
1091 scm1: movb $0, %ah # Test the mode
1097 jnz scm2 # Mode not set
1099 movw $0x3c0, %dx # Test if it's a text mode
1100 movb $0x10, %al # Mode bits
1105 movb $0xce, %dl # Another set of mode bits
1111 movb $0xd4, %dl # Cursor location
1117 movw %cx, %ax # Ok, store the mode
1119 movb %gs:(0x484), %al # Number of rows
1122 movw %gs:(0x44a), %ax # Number of columns
1127 movw $0x0003, %ax # Return back to mode 3
1131 tstidx: outw %ax, %dx # OUT DX,AX and inidx
1132 inidx: outb %al, %dx # Read from indexed VGA register
1133 incw %dx # AL=index, DX=index reg port -> AL=data
1138 # Try to detect type of SVGA card and supply (usually approximate) video
1139 # mode table for it.
1141 #ifdef CONFIG_VIDEO_SVGA
1143 leaw svga_table, %si # Test all known SVGA adapters
1145 movw %ax, %bp # Default mode table
1149 lodsw # Pointer to test routine
1155 call *%ax # Call test routine
1162 movw %bp, %si # Found, copy the modes
1163 movb svga_prefix, %ah
1172 didsv: movw %si, card_name # Store pointer to card name
1175 # Table of all known SVGA cards. For each card, we store a pointer to
1176 # a table of video modes supported by the card and a pointer to a routine
1177 # used for testing of presence of the card. The video mode table is always
1178 # followed by the name of the card or the chipset.
1180 .word ati_md, ati_test
1181 .word oak_md, oak_test
1182 .word paradise_md, paradise_test
1183 .word realtek_md, realtek_test
1184 .word s3_md, s3_test
1185 .word chips_md, chips_test
1186 .word video7_md, video7_test
1187 .word cirrus5_md, cirrus5_test
1188 .word cirrus6_md, cirrus6_test
1189 .word cirrus1_md, cirrus1_test
1190 .word ahead_md, ahead_test
1191 .word everex_md, everex_test
1192 .word genoa_md, genoa_test
1193 .word trident_md, trident_test
1194 .word tseng_md, tseng_test
1197 # Test routines and mode tables:
1199 # S3 - The test algorithm was taken from the SuperProbe package
1200 # for XFree86 1.2.1. Report bugs to Christoph.Niemann@linux.org
1202 movw $0x0f35, %cx # we store some constants in cl/ch
1206 movb %al, %bh # store current CRT-register 0x38
1208 call outidx # disable writing to special regs
1209 movb %cl, %al # check whether we can write special reg 0x35
1211 movb %al, %bl # save the current value of CRT reg 0x35
1212 andb $0xf0, %al # clear bits 0-3
1214 movb %cl, %al # and write it to CRT reg 0x35
1216 call inidx # now read it back
1217 andb %ch, %al # clear the upper 4 bits
1218 jz s3_2 # the first test failed. But we have a
1220 movb %bl, %ah # second chance
1223 jmp s3_1 # do the other tests
1225 s3_2: movw %cx, %ax # load ah with 0xf and al with 0x35
1226 orb %bl, %ah # set the upper 4 bits of ah with the orig value
1227 call outidx # write ...
1228 call inidx # ... and reread
1229 andb %cl, %al # turn off the upper 4 bits
1231 movb %bl, %ah # restore old value in register 0x35
1235 cmpb %ch, %al # setting lower 4 bits was successful => bad
1236 je no_s3 # writing is allowed => this is not an S3
1238 s3_1: movw $0x4838, %ax # allow writing to special regs by putting
1239 call outidx # magic number into CRT-register 0x38
1240 movb %cl, %al # check whether we can write special reg 0x35
1249 jnz no_s3 # no, we can't write => no S3
1257 movb %bl, %ah # restore old value in register 0x35
1262 jne no_s31 # writing not possible => no S3
1264 call inidx # now get the S3 id ...
1275 no_s3: movb $0x35, %al # restore CRT register 0x35
1278 no_s31: xorw %bp, %bp # Detection failed
1279 s3rest: movb %bh, %ah
1280 movb $0x38, %al # restore old value of CRT register 0x38
1283 idS3: .byte 0x81, 0x82, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95
1284 .byte 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa8, 0xb0
1286 s3_md: .byte 0x54, 0x2b, 0x84
1287 .byte 0x55, 0x19, 0x84
1304 idati: .ascii "761295520"
1306 ati_md: .byte 0x23, 0x19, 0x84
1307 .byte 0x33, 0x2c, 0x84
1308 .byte 0x22, 0x1e, 0x64
1309 .byte 0x21, 0x19, 0x64
1310 .byte 0x58, 0x21, 0x50
1311 .byte 0x5b, 0x1e, 0x50
1333 .byte 0x22, 0x2c, 0x84
1334 .byte 0x23, 0x19, 0x84
1335 .byte 0x24, 0x1c, 0x84
1336 .byte 0x2f, 0x32, 0xa0
1337 .byte 0x32, 0x22, 0x50
1338 .byte 0x34, 0x42, 0x50
1363 .byte 0x60, 0x19, 0x84
1364 .byte 0x61, 0x32, 0x84
1366 .ascii "Chips & Technologies"
1407 nocirr: xorw %bp, %bp
1408 iscirr: movw $0x3d4, %dx
1417 .byte 0x1f, 0x19, 0x84
1418 .byte 0x20, 0x2c, 0x84
1419 .byte 0x22, 0x1e, 0x84
1420 .byte 0x31, 0x25, 0x64
1422 .ascii "Cirrus Logic 5X0"
1430 movb %al, %bl # BL=backup
1464 c5fail: xorw %bp, %bp
1465 c5done: movb $6, %al
1471 .byte 0x14, 0x19, 0x84
1472 .byte 0x54, 0x2b, 0x84
1474 .ascii "Cirrus Logic 54XX"
1477 # Cirrus Logic 64XX -- no known extra modes, but must be identified, because
1478 # it's misidentified by the Ahead test.
1483 movb %al, %bl # BL=backup
1495 call inidx # 4X, 5X, 7X and 8X are valid 64XX chip ID's.
1509 c2fail: xorw %bp, %bp
1510 c6done: movb $0x0a, %al
1517 .ascii "Cirrus Logic 64XX"
1535 evtrid: leaw trident_md, %bp
1538 noevrx: xorw %bp, %bp
1542 .byte 0x03, 0x22, 0x50
1543 .byte 0x04, 0x3c, 0x50
1544 .byte 0x07, 0x2b, 0x64
1545 .byte 0x08, 0x4b, 0x64
1546 .byte 0x0a, 0x19, 0x84
1547 .byte 0x0b, 0x2c, 0x84
1548 .byte 0x16, 0x1e, 0x50
1549 .byte 0x18, 0x1b, 0x64
1550 .byte 0x21, 0x40, 0xa0
1551 .byte 0x40, 0x1e, 0x84
1553 .ascii "Everex/Trident"
1558 leaw idgenoa, %si # Check Genoa 'clues'
1560 movb %es:(0x37), %al
1579 idgenoa: .byte 0x77, 0x00, 0x99, 0x66
1582 .byte 0x58, 0x20, 0x50
1583 .byte 0x5a, 0x2a, 0x64
1584 .byte 0x60, 0x19, 0x84
1585 .byte 0x61, 0x1d, 0x84
1586 .byte 0x62, 0x20, 0x84
1587 .byte 0x63, 0x2c, 0x84
1588 .byte 0x64, 0x3c, 0x84
1589 .byte 0x6b, 0x4f, 0x64
1590 .byte 0x72, 0x3c, 0x50
1591 .byte 0x74, 0x42, 0x50
1592 .byte 0x78, 0x4b, 0x64
1609 idoakvga: .ascii "OAK VGA "
1611 oak_md: .byte 0x4e, 0x3c, 0x50
1612 .byte 0x4f, 0x3c, 0x84
1613 .byte 0x50, 0x19, 0x84
1614 .byte 0x51, 0x2b, 0x84
1621 leaw idparadise, %si
1631 idparadise: .ascii "VGA="
1634 .byte 0x41, 0x22, 0x50
1635 .byte 0x47, 0x1c, 0x84
1636 .byte 0x55, 0x19, 0x84
1637 .byte 0x54, 0x2c, 0x84
1654 movb %al, %bl # Strange thing ... in the book this wasn't
1655 andb $0x02, %bl # necessary but it worked on my card which
1656 jz setb2 # is a trident. Without it the screen goes
1661 setb2: orb $0x02, %al
1662 clrb2: outb %al, %dx
1671 .byte 0x50, 0x1e, 0x50
1672 .byte 0x51, 0x2b, 0x50
1673 .byte 0x52, 0x3c, 0x50
1674 .byte 0x57, 0x19, 0x84
1675 .byte 0x58, 0x1e, 0x84
1676 .byte 0x59, 0x2b, 0x84
1677 .byte 0x5a, 0x3c, 0x84
1685 inb %dx, %al # Could things be this simple ! :-)
1696 isnot: xorw %bp, %bp
1700 .byte 0x26, 0x3c, 0x50
1701 .byte 0x2a, 0x28, 0x64
1702 .byte 0x23, 0x19, 0x84
1703 .byte 0x24, 0x1c, 0x84
1704 .byte 0x22, 0x2c, 0x84
1705 .byte 0x21, 0x3c, 0x84
1719 even7: movb $0x0c, %al
1744 movb $VIDEO_FIRST_V7>>8, svga_prefix # Use special mode switching
1748 .byte 0x40, 0x2b, 0x50
1749 .byte 0x43, 0x3c, 0x50
1750 .byte 0x44, 0x3c, 0x64
1751 .byte 0x41, 0x19, 0x84
1752 .byte 0x42, 0x2c, 0x84
1753 .byte 0x45, 0x1c, 0x84
1770 idrtvga: .ascii "REALTEK VGA"
1773 .byte 0x1a, 0x3c, 0x50
1774 .byte 0x1b, 0x19, 0x84
1775 .byte 0x1c, 0x1e, 0x84
1776 .byte 0x1d, 0x2b, 0x84
1777 .byte 0x1e, 0x3c, 0x84
1782 #endif /* CONFIG_VIDEO_SVGA */
1784 # User-defined local mode table (VGA only)
1785 #ifdef CONFIG_VIDEO_LOCAL
1787 leaw local_mode_table, %si
1798 # This is the table of local video modes which can be supplied manually
1799 # by the user. Each entry consists of mode ID (word) and dimensions
1800 # (byte for column count and another byte for row count). These modes
1801 # are placed before all SVGA and VESA modes and override them if table
1802 # compacting is enabled. The table must end with a zero word followed
1803 # by NUL-terminated video adapter name.
1805 .word 0x0100 # Example: 40x25
1810 #endif /* CONFIG_VIDEO_LOCAL */
1812 # Read a key and return the ASCII code in al, scan code in ah
1813 getkey: xorb %ah, %ah
1817 # Read a key with a timeout of 30 seconds.
1818 # The hardware clock is used to get the time.
1820 addb $30, %al # Wait 30 seconds
1827 again: movb $0x01, %ah
1829 jnz getkey # key pressed, so get it
1835 movb $0x20, %al # timeout, return `space'
1838 # Flush the keyboard buffer
1839 flush: movb $0x01, %ah
1849 # Print hexadecimal number.
1859 prthn: cmpb $0x0a, %al
1863 prth1: addb $0x30, %al
1866 # Print decimal number in al
1878 lt100: addb $0x30, %al
1880 skip10: movb %ah, %al
1887 # VIDEO_SELECT-only variables
1888 mt_end: .word 0 # End of video mode table if built
1889 edit_buf: .space 6 # Line editor buffer
1890 card_name: .word 0 # Pointer to adapter name
1891 scanning: .byte 0 # Performing mode scan
1892 do_restore: .byte 0 # Screen contents altered during mode change
1893 svga_prefix: .byte VIDEO_FIRST_BIOS>>8 # Default prefix for BIOS modes
1894 graphic_mode: .byte 0 # Graphic mode with a linear frame buffer
1897 keymsg: .ascii "Press <RETURN> to see video modes available, "
1898 .ascii "<SPACE> to continue or wait 30 secs"
1901 listhdr: .byte 0x0d, 0x0a
1902 .ascii "Mode: COLSxROWS:"
1904 crlft: .byte 0x0d, 0x0a, 0
1906 prompt: .byte 0x0d, 0x0a
1907 .asciz "Enter mode number or `scan': "
1909 unknt: .asciz "Unknown mode ID. Try again."
1911 badmdt: .ascii "You passed an undefined mode number."
1914 vesaer: .ascii "Error: Scanning of VESA modes failed. Please "
1915 .ascii "report to <mj@ucw.cz>."
1918 old_name: .asciz "CGA/MDA/HGA"
1920 ega_name: .asciz "EGA"
1922 svga_name: .ascii " "
1924 vga_name: .asciz "VGA"
1926 vesa_name: .asciz "VESA"
1928 name_bann: .asciz "Video adapter: "
1929 #endif /* CONFIG_VIDEO_SELECT */
1932 adapter: .byte 0 # Video adapter: 0=CGA/MDA/HGA,1=EGA,2=VGA
1933 video_segment: .word 0xb800 # Video memory segment
1934 force_size: .word 0 # Use this size instead of the one in BIOS vars