blob: 8c2a6faeeae51b128e27b43e4669a7ac75dcf792 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/* video.S
2 *
3 * Display adapter & video mode setup, version 2.13 (14-May-99)
4 *
5 * Copyright (C) 1995 -- 1998 Martin Mares <mj@ucw.cz>
6 * Based on the original setup.S code (C) Linus Torvalds and Mats Anderson
7 *
8 * Rewritten to use GNU 'as' by Chris Noe <stiker@northlink.com> May 1999
9 *
10 * For further information, look at Documentation/svga.txt.
11 *
12 */
13
14#include <linux/config.h> /* for CONFIG_VIDEO_* */
15
16/* Enable autodetection of SVGA adapters and modes. */
17#undef CONFIG_VIDEO_SVGA
18
19/* Enable autodetection of VESA modes */
20#define CONFIG_VIDEO_VESA
21
22/* Enable compacting of mode table */
23#define CONFIG_VIDEO_COMPACT
24
25/* Retain screen contents when switching modes */
26#define CONFIG_VIDEO_RETAIN
27
28/* Enable local mode list */
29#undef CONFIG_VIDEO_LOCAL
30
31/* Force 400 scan lines for standard modes (hack to fix bad BIOS behaviour */
32#undef CONFIG_VIDEO_400_HACK
33
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 */
39
40/* This code uses an extended set of video mode numbers. These include:
41 * Aliases for standard modes
42 * NORMAL_VGA (-1)
43 * EXTENDED_VGA (-2)
44 * ASK_VGA (-3)
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.
47 */
48#define VIDEO_FIRST_MENU 0x0000
49
50/* Standard BIOS video modes (BIOS number + 0x0100) */
51#define VIDEO_FIRST_BIOS 0x0100
52
53/* VESA BIOS video modes (VESA number + 0x0200) */
54#define VIDEO_FIRST_VESA 0x0200
55
56/* Video7 special modes (BIOS number + 0x0900) */
57#define VIDEO_FIRST_V7 0x0900
58
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
71
72/* Video modes given by resolution */
73#define VIDEO_FIRST_RESOLUTION 0x1000
74
75/* The "recalculate timings" flag */
76#define VIDEO_RECALC 0x8000
77
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
88
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
Antonino A. Daplas89ec4c22006-04-10 22:55:48 -0700100#define PARAM_CAPABILITIES 0x36
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101
102/* Define DO_STORE according to CONFIG_VIDEO_RETAIN */
103#ifdef CONFIG_VIDEO_RETAIN
104#define DO_STORE call store_screen
105#else
106#define DO_STORE
107#endif /* CONFIG_VIDEO_RETAIN */
108
109# This is the main entry point called by setup.S
110# %ds *must* be pointing to the bootsector
111video: pushw %ds # We use different segments
112 pushw %ds # FS contains original DS
113 popw %fs
114 pushw %cs # DS is equal to CS
115 popw %ds
116 pushw %cs # ES is equal to CS
117 popw %es
118 xorw %ax, %ax
119 movw %ax, %gs # GS is zero
120 cld
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
125 jz vid2
126
127 call mode_set # Set the mode
128 jc vid1
129
130 leaw badmdt, %si # Invalid mode ID
131 call prtstr
132vid2: call mode_menu
133vid1:
134#ifdef CONFIG_VIDEO_RETAIN
135 call restore_screen # Restore screen contents
136#endif /* CONFIG_VIDEO_RETAIN */
137 call store_edid
138#endif /* CONFIG_VIDEO_SELECT */
139 call mode_params # Store mode parameters
140 popw %ds # Restore original DS
141 ret
142
143# Detect if we have CGA, MDA, EGA or VGA and pass it to the kernel.
144basic_detect:
145 movb $0, %fs:(PARAM_HAVE_VGA)
146 movb $0x12, %ah # Check EGA/VGA
147 movb $0x10, %bl
148 int $0x10
149 movw %bx, %fs:(PARAM_VIDEO_EGA_BX) # Identifies EGA to the kernel
150 cmpb $0x10, %bl # No, it's a CGA/MDA/HGA card.
151 je basret
152
153 incb adapter
154 movw $0x1a00, %ax # Check EGA or VGA?
155 int $0x10
156 cmpb $0x1a, %al # 1a means VGA...
157 jne basret # anything else is EGA.
158
159 incb %fs:(PARAM_HAVE_VGA) # We've detected a VGA
160 incb adapter
161basret: ret
162
163# Store the video mode parameters for later usage by the kernel.
164# This is done by asking the BIOS except for the rows/columns
165# parameters in the default 80x25 mode -- these are set directly,
166# because some very obscure BIOSes supply insane values.
167mode_params:
168#ifdef CONFIG_VIDEO_SELECT
169 cmpb $0, graphic_mode
170 jnz mopar_gr
171#endif
172 movb $0x03, %ah # Read cursor position
173 xorb %bh, %bh
174 int $0x10
175 movw %dx, %fs:(PARAM_CURSOR_POS)
176 movb $0x0f, %ah # Read page/mode/width
177 int $0x10
178 movw %bx, %fs:(PARAM_VIDEO_PAGE)
179 movw %ax, %fs:(PARAM_VIDEO_MODE) # Video mode and screen width
180 cmpb $0x7, %al # MDA/HGA => segment differs
181 jnz mopar0
182
183 movw $0xb000, video_segment
184mopar0: movw %gs:(0x485), %ax # Font size
185 movw %ax, %fs:(PARAM_FONT_POINTS) # (valid only on EGA/VGA)
186 movw force_size, %ax # Forced size?
187 orw %ax, %ax
188 jz mopar1
189
190 movb %ah, %fs:(PARAM_VIDEO_COLS)
191 movb %al, %fs:(PARAM_VIDEO_LINES)
192 ret
193
194mopar1: movb $25, %al
195 cmpb $0, adapter # If we are on CGA/MDA/HGA, the
196 jz mopar2 # screen must have 25 lines.
197
198 movb %gs:(0x484), %al # On EGA/VGA, use the EGA+ BIOS
199 incb %al # location of max lines.
200mopar2: movb %al, %fs:(PARAM_VIDEO_LINES)
201 ret
202
203#ifdef CONFIG_VIDEO_SELECT
204# Fetching of VESA frame buffer parameters
205mopar_gr:
206 leaw modelist+1024, %di
207 movb $0x23, %fs:(PARAM_HAVE_VGA)
208 movw 16(%di), %ax
209 movw %ax, %fs:(PARAM_LFB_LINELENGTH)
210 movw 18(%di), %ax
211 movw %ax, %fs:(PARAM_LFB_WIDTH)
212 movw 20(%di), %ax
213 movw %ax, %fs:(PARAM_LFB_HEIGHT)
214 movb 25(%di), %al
215 movb $0, %ah
216 movw %ax, %fs:(PARAM_LFB_DEPTH)
217 movb 29(%di), %al
218 movb $0, %ah
219 movw %ax, %fs:(PARAM_LFB_PAGES)
220 movl 40(%di), %eax
221 movl %eax, %fs:(PARAM_LFB_BASE)
222 movl 31(%di), %eax
223 movl %eax, %fs:(PARAM_LFB_COLORS)
224 movl 35(%di), %eax
225 movl %eax, %fs:(PARAM_LFB_COLORS+4)
226 movw 0(%di), %ax
227 movw %ax, %fs:(PARAM_VESA_ATTRIB)
228
229# get video mem size
230 leaw modelist+1024, %di
231 movw $0x4f00, %ax
232 int $0x10
233 xorl %eax, %eax
234 movw 18(%di), %ax
235 movl %eax, %fs:(PARAM_LFB_SIZE)
236
Antonino A. Daplas89ec4c22006-04-10 22:55:48 -0700237# store mode capabilities
238 movl 10(%di), %eax
239 movl %eax, %fs:(PARAM_CAPABILITIES)
240
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241# switching the DAC to 8-bit is for <= 8 bpp only
242 movw %fs:(PARAM_LFB_DEPTH), %ax
243 cmpw $8, %ax
244 jg dac_done
245
246# get DAC switching capability
247 xorl %eax, %eax
248 movb 10(%di), %al
249 testb $1, %al
250 jz dac_set
251
252# attempt to switch DAC to 8-bit
253 movw $0x4f08, %ax
254 movw $0x0800, %bx
255 int $0x10
256 cmpw $0x004f, %ax
257 jne dac_set
258 movb %bh, dac_size # store actual DAC size
259
260dac_set:
261# set color size to DAC size
262 movb dac_size, %al
263 movb %al, %fs:(PARAM_LFB_COLORS+0)
264 movb %al, %fs:(PARAM_LFB_COLORS+2)
265 movb %al, %fs:(PARAM_LFB_COLORS+4)
266 movb %al, %fs:(PARAM_LFB_COLORS+6)
267
268# set color offsets to 0
269 movb $0, %fs:(PARAM_LFB_COLORS+1)
270 movb $0, %fs:(PARAM_LFB_COLORS+3)
271 movb $0, %fs:(PARAM_LFB_COLORS+5)
272 movb $0, %fs:(PARAM_LFB_COLORS+7)
273
274dac_done:
275# get protected mode interface informations
276 movw $0x4f0a, %ax
277 xorw %bx, %bx
278 xorw %di, %di
279 int $0x10
280 cmp $0x004f, %ax
281 jnz no_pm
282
283 movw %es, %fs:(PARAM_VESAPM_SEG)
284 movw %di, %fs:(PARAM_VESAPM_OFF)
285no_pm: ret
286
287# The video mode menu
288mode_menu:
289 leaw keymsg, %si # "Return/Space/Timeout" message
290 call prtstr
291 call flush
292nokey: call getkt
293
294 cmpb $0x0d, %al # ENTER ?
295 je listm # yes - manual mode selection
296
297 cmpb $0x20, %al # SPACE ?
298 je defmd1 # no - repeat
299
300 call beep
301 jmp nokey
302
303defmd1: ret # No mode chosen? Default 80x25
304
305listm: call mode_table # List mode table
306listm0: leaw name_bann, %si # Print adapter name
307 call prtstr
308 movw card_name, %si
309 orw %si, %si
310 jnz an2
311
312 movb adapter, %al
313 leaw old_name, %si
314 orb %al, %al
315 jz an1
316
317 leaw ega_name, %si
318 decb %al
319 jz an1
320
321 leaw vga_name, %si
322 jmp an1
323
324an2: call prtstr
325 leaw svga_name, %si
326an1: call prtstr
327 leaw listhdr, %si # Table header
328 call prtstr
329 movb $0x30, %dl # DL holds mode number
330 leaw modelist, %si
331lm1: cmpw $ASK_VGA, (%si) # End?
332 jz lm2
333
334 movb %dl, %al # Menu selection number
335 call prtchr
336 call prtsp2
337 lodsw
338 call prthw # Mode ID
339 call prtsp2
340 movb 0x1(%si), %al
341 call prtdec # Rows
342 movb $0x78, %al # the letter 'x'
343 call prtchr
344 lodsw
345 call prtdec # Columns
346 movb $0x0d, %al # New line
347 call prtchr
348 movb $0x0a, %al
349 call prtchr
350 incb %dl # Next character
351 cmpb $0x3a, %dl
352 jnz lm1
353
354 movb $0x61, %dl
355 jmp lm1
356
357lm2: leaw prompt, %si # Mode prompt
358 call prtstr
359 leaw edit_buf, %di # Editor buffer
360lm3: call getkey
361 cmpb $0x0d, %al # Enter?
362 jz lment
363
364 cmpb $0x08, %al # Backspace?
365 jz lmbs
366
367 cmpb $0x20, %al # Printable?
368 jc lm3
369
370 cmpw $edit_buf+4, %di # Enough space?
371 jz lm3
372
373 stosb
374 call prtchr
375 jmp lm3
376
377lmbs: cmpw $edit_buf, %di # Backspace
378 jz lm3
379
380 decw %di
381 movb $0x08, %al
382 call prtchr
383 call prtspc
384 movb $0x08, %al
385 call prtchr
386 jmp lm3
387
388lment: movb $0, (%di)
389 leaw crlft, %si
390 call prtstr
391 leaw edit_buf, %si
392 cmpb $0, (%si) # Empty string = default mode
393 jz lmdef
394
395 cmpb $0, 1(%si) # One character = menu selection
396 jz mnusel
397
398 cmpw $0x6373, (%si) # "scan" => mode scanning
399 jnz lmhx
400
401 cmpw $0x6e61, 2(%si)
402 jz lmscan
403
404lmhx: xorw %bx, %bx # Else => mode ID in hex
405lmhex: lodsb
406 orb %al, %al
407 jz lmuse1
408
409 subb $0x30, %al
410 jc lmbad
411
412 cmpb $10, %al
413 jc lmhx1
414
415 subb $7, %al
416 andb $0xdf, %al
417 cmpb $10, %al
418 jc lmbad
419
420 cmpb $16, %al
421 jnc lmbad
422
423lmhx1: shlw $4, %bx
424 orb %al, %bl
425 jmp lmhex
426
427lmuse1: movw %bx, %ax
428 jmp lmuse
429
430mnusel: lodsb # Menu selection
431 xorb %ah, %ah
432 subb $0x30, %al
433 jc lmbad
434
435 cmpb $10, %al
436 jc lmuse
437
438 cmpb $0x61-0x30, %al
439 jc lmbad
440
441 subb $0x61-0x30-10, %al
442 cmpb $36, %al
443 jnc lmbad
444
445lmuse: call mode_set
446 jc lmdef
447
448lmbad: leaw unknt, %si
449 call prtstr
450 jmp lm2
451lmscan: cmpb $0, adapter # Scanning only on EGA/VGA
452 jz lmbad
453
454 movw $0, mt_end # Scanning of modes is
455 movb $1, scanning # done as new autodetection.
456 call mode_table
457 jmp listm0
458lmdef: ret
459
460# Additional parts of mode_set... (relative jumps, you know)
461setv7: # Video7 extended modes
462 DO_STORE
463 subb $VIDEO_FIRST_V7>>8, %bh
464 movw $0x6f05, %ax
465 int $0x10
466 stc
467 ret
468
469_setrec: jmp setrec # Ugly...
470_set_80x25: jmp set_80x25
471
472# Aliases for backward compatibility.
473setalias:
474 movw $VIDEO_80x25, %ax
475 incw %bx
476 jz mode_set
477
478 movb $VIDEO_8POINT-VIDEO_FIRST_SPECIAL, %al
479 incw %bx
480 jnz setbad # Fall-through!
481
482# Setting of user mode (AX=mode ID) => CF=success
483mode_set:
484 movw %ax, %fs:(0x01fa) # Store mode for use in acpi_wakeup.S
485 movw %ax, %bx
486 cmpb $0xff, %ah
487 jz setalias
488
489 testb $VIDEO_RECALC>>8, %ah
490 jnz _setrec
491
492 cmpb $VIDEO_FIRST_RESOLUTION>>8, %ah
493 jnc setres
494
495 cmpb $VIDEO_FIRST_SPECIAL>>8, %ah
496 jz setspc
497
498 cmpb $VIDEO_FIRST_V7>>8, %ah
499 jz setv7
500
501 cmpb $VIDEO_FIRST_VESA>>8, %ah
502 jnc check_vesa
503
504 orb %ah, %ah
505 jz setmenu
506
507 decb %ah
508 jz setbios
509
510setbad: clc
511 movb $0, do_restore # The screen needn't be restored
512 ret
513
514setvesa:
515 DO_STORE
516 subb $VIDEO_FIRST_VESA>>8, %bh
517 movw $0x4f02, %ax # VESA BIOS mode set call
518 int $0x10
519 cmpw $0x004f, %ax # AL=4f if implemented
520 jnz setbad # AH=0 if OK
521
522 stc
523 ret
524
525setbios:
526 DO_STORE
527 int $0x10 # Standard BIOS mode set call
528 pushw %bx
529 movb $0x0f, %ah # Check if really set
530 int $0x10
531 popw %bx
532 cmpb %bl, %al
533 jnz setbad
534
535 stc
536 ret
537
538setspc: xorb %bh, %bh # Set special mode
539 cmpb $VIDEO_LAST_SPECIAL-VIDEO_FIRST_SPECIAL, %bl
540 jnc setbad
541
542 addw %bx, %bx
543 jmp *spec_inits(%bx)
544
545setmenu:
546 orb %al, %al # 80x25 is an exception
547 jz _set_80x25
548
549 pushw %bx # Set mode chosen from menu
550 call mode_table # Build the mode table
551 popw %ax
552 shlw $2, %ax
553 addw %ax, %si
554 cmpw %di, %si
555 jnc setbad
556
557 movw (%si), %ax # Fetch mode ID
558_m_s: jmp mode_set
559
560setres: pushw %bx # Set mode chosen by resolution
561 call mode_table
562 popw %bx
563 xchgb %bl, %bh
564setr1: lodsw
565 cmpw $ASK_VGA, %ax # End of the list?
566 jz setbad
567
568 lodsw
569 cmpw %bx, %ax
570 jnz setr1
571
572 movw -4(%si), %ax # Fetch mode ID
573 jmp _m_s
574
575check_vesa:
576 leaw modelist+1024, %di
577 subb $VIDEO_FIRST_VESA>>8, %bh
578 movw %bx, %cx # Get mode information structure
579 movw $0x4f01, %ax
580 int $0x10
581 addb $VIDEO_FIRST_VESA>>8, %bh
582 cmpw $0x004f, %ax
583 jnz setbad
584
585 movb (%di), %al # Check capabilities.
586 andb $0x19, %al
587 cmpb $0x09, %al
588 jz setvesa # This is a text mode
589
590 movb (%di), %al # Check capabilities.
591 andb $0x99, %al
592 cmpb $0x99, %al
593 jnz _setbad # Doh! No linear frame buffer.
594
595 subb $VIDEO_FIRST_VESA>>8, %bh
596 orw $0x4000, %bx # Use linear frame buffer
597 movw $0x4f02, %ax # VESA BIOS mode set call
598 int $0x10
599 cmpw $0x004f, %ax # AL=4f if implemented
600 jnz _setbad # AH=0 if OK
601
602 movb $1, graphic_mode # flag graphic mode
603 movb $0, do_restore # no screen restore
604 stc
605 ret
606
607_setbad: jmp setbad # Ugly...
608
609# Recalculate vertical display end registers -- this fixes various
610# inconsistencies of extended modes on many adapters. Called when
611# the VIDEO_RECALC flag is set in the mode ID.
612
613setrec: subb $VIDEO_RECALC>>8, %ah # Set the base mode
614 call mode_set
615 jnc rct3
616
617 movw %gs:(0x485), %ax # Font size in pixels
618 movb %gs:(0x484), %bl # Number of rows
619 incb %bl
620 mulb %bl # Number of visible
621 decw %ax # scan lines - 1
622 movw $0x3d4, %dx
623 movw %ax, %bx
624 movb $0x12, %al # Lower 8 bits
625 movb %bl, %ah
626 outw %ax, %dx
627 movb $0x07, %al # Bits 8 and 9 in the overflow register
628 call inidx
629 xchgb %al, %ah
630 andb $0xbd, %ah
631 shrb %bh
632 jnc rct1
633 orb $0x02, %ah
634rct1: shrb %bh
635 jnc rct2
636 orb $0x40, %ah
637rct2: movb $0x07, %al
638 outw %ax, %dx
639 stc
640rct3: ret
641
642# Table of routines for setting of the special modes.
643spec_inits:
644 .word set_80x25
645 .word set_8pixel
646 .word set_80x43
647 .word set_80x28
648 .word set_current
649 .word set_80x30
650 .word set_80x34
651 .word set_80x60
652 .word set_gfx
653
654# Set the 80x25 mode. If already set, do nothing.
655set_80x25:
656 movw $0x5019, force_size # Override possibly broken BIOS
657use_80x25:
658#ifdef CONFIG_VIDEO_400_HACK
659 movw $0x1202, %ax # Force 400 scan lines
660 movb $0x30, %bl
661 int $0x10
662#else
663 movb $0x0f, %ah # Get current mode ID
664 int $0x10
665 cmpw $0x5007, %ax # Mode 7 (80x25 mono) is the only one available
666 jz st80 # on CGA/MDA/HGA and is also available on EGAM
667
668 cmpw $0x5003, %ax # Unknown mode, force 80x25 color
669 jnz force3
670
671st80: cmpb $0, adapter # CGA/MDA/HGA => mode 3/7 is always 80x25
672 jz set80
673
674 movb %gs:(0x0484), %al # This is EGA+ -- beware of 80x50 etc.
675 orb %al, %al # Some buggy BIOS'es set 0 rows
676 jz set80
677
678 cmpb $24, %al # It's hopefully correct
679 jz set80
680#endif /* CONFIG_VIDEO_400_HACK */
681force3: DO_STORE
682 movw $0x0003, %ax # Forced set
683 int $0x10
684set80: stc
685 ret
686
687# Set the 80x50/80x43 8-pixel mode. Simple BIOS calls.
688set_8pixel:
689 DO_STORE
690 call use_80x25 # The base is 80x25
691set_8pt:
692 movw $0x1112, %ax # Use 8x8 font
693 xorb %bl, %bl
694 int $0x10
695 movw $0x1200, %ax # Use alternate print screen
696 movb $0x20, %bl
697 int $0x10
698 movw $0x1201, %ax # Turn off cursor emulation
699 movb $0x34, %bl
700 int $0x10
701 movb $0x01, %ah # Define cursor scan lines 6-7
702 movw $0x0607, %cx
703 int $0x10
704set_current:
705 stc
706 ret
707
708# Set the 80x28 mode. This mode works on all VGA's, because it's a standard
709# 80x25 mode with 14-point fonts instead of 16-point.
710set_80x28:
711 DO_STORE
712 call use_80x25 # The base is 80x25
713set14: movw $0x1111, %ax # Use 9x14 font
714 xorb %bl, %bl
715 int $0x10
716 movb $0x01, %ah # Define cursor scan lines 11-12
717 movw $0x0b0c, %cx
718 int $0x10
719 stc
720 ret
721
722# Set the 80x43 mode. This mode is works on all VGA's.
723# It's a 350-scanline mode with 8-pixel font.
724set_80x43:
725 DO_STORE
726 movw $0x1201, %ax # Set 350 scans
727 movb $0x30, %bl
728 int $0x10
729 movw $0x0003, %ax # Reset video mode
730 int $0x10
731 jmp set_8pt # Use 8-pixel font
732
733# Set the 80x30 mode (all VGA's). 480 scanlines, 16-pixel font.
734set_80x30:
735 call use_80x25 # Start with real 80x25
736 DO_STORE
737 movw $0x3cc, %dx # Get CRTC port
738 inb %dx, %al
739 movb $0xd4, %dl
740 rorb %al # Mono or color?
741 jc set48a
742
743 movb $0xb4, %dl
744set48a: movw $0x0c11, %ax # Vertical sync end (also unlocks CR0-7)
745 call outidx
746 movw $0x0b06, %ax # Vertical total
747 call outidx
748 movw $0x3e07, %ax # (Vertical) overflow
749 call outidx
750 movw $0xea10, %ax # Vertical sync start
751 call outidx
752 movw $0xdf12, %ax # Vertical display end
753 call outidx
754 movw $0xe715, %ax # Vertical blank start
755 call outidx
756 movw $0x0416, %ax # Vertical blank end
757 call outidx
758 pushw %dx
759 movb $0xcc, %dl # Misc output register (read)
760 inb %dx, %al
761 movb $0xc2, %dl # (write)
762 andb $0x0d, %al # Preserve clock select bits and color bit
763 orb $0xe2, %al # Set correct sync polarity
764 outb %al, %dx
765 popw %dx
766 movw $0x501e, force_size
767 stc # That's all.
768 ret
769
770# Set the 80x34 mode (all VGA's). 480 scans, 14-pixel font.
771set_80x34:
772 call set_80x30 # Set 480 scans
773 call set14 # And 14-pt font
774 movw $0xdb12, %ax # VGA vertical display end
775 movw $0x5022, force_size
776setvde: call outidx
777 stc
778 ret
779
780# Set the 80x60 mode (all VGA's). 480 scans, 8-pixel font.
781set_80x60:
782 call set_80x30 # Set 480 scans
783 call set_8pt # And 8-pt font
784 movw $0xdf12, %ax # VGA vertical display end
785 movw $0x503c, force_size
786 jmp setvde
787
788# Special hack for ThinkPad graphics
789set_gfx:
790#ifdef CONFIG_VIDEO_GFX_HACK
791 movw $VIDEO_GFX_BIOS_AX, %ax
792 movw $VIDEO_GFX_BIOS_BX, %bx
793 int $0x10
794 movw $VIDEO_GFX_DUMMY_RESOLUTION, force_size
795 stc
796#endif
797 ret
798
799#ifdef CONFIG_VIDEO_RETAIN
800
801# Store screen contents to temporary buffer.
802store_screen:
803 cmpb $0, do_restore # Already stored?
804 jnz stsr
805
806 testb $CAN_USE_HEAP, loadflags # Have we space for storing?
807 jz stsr
808
809 pushw %ax
810 pushw %bx
811 pushw force_size # Don't force specific size
812 movw $0, force_size
813 call mode_params # Obtain params of current mode
814 popw force_size
815 movb %fs:(PARAM_VIDEO_LINES), %ah
816 movb %fs:(PARAM_VIDEO_COLS), %al
817 movw %ax, %bx # BX=dimensions
818 mulb %ah
819 movw %ax, %cx # CX=number of characters
820 addw %ax, %ax # Calculate image size
821 addw $modelist+1024+4, %ax
822 cmpw heap_end_ptr, %ax
823 jnc sts1 # Unfortunately, out of memory
824
825 movw %fs:(PARAM_CURSOR_POS), %ax # Store mode params
826 leaw modelist+1024, %di
827 stosw
828 movw %bx, %ax
829 stosw
830 pushw %ds # Store the screen
831 movw video_segment, %ds
832 xorw %si, %si
833 rep
834 movsw
835 popw %ds
836 incb do_restore # Screen will be restored later
837sts1: popw %bx
838 popw %ax
839stsr: ret
840
841# Restore screen contents from temporary buffer.
842restore_screen:
843 cmpb $0, do_restore # Has the screen been stored?
844 jz res1
845
846 call mode_params # Get parameters of current mode
847 movb %fs:(PARAM_VIDEO_LINES), %cl
848 movb %fs:(PARAM_VIDEO_COLS), %ch
849 leaw modelist+1024, %si # Screen buffer
850 lodsw # Set cursor position
851 movw %ax, %dx
852 cmpb %cl, %dh
853 jc res2
854
855 movb %cl, %dh
856 decb %dh
857res2: cmpb %ch, %dl
858 jc res3
859
860 movb %ch, %dl
861 decb %dl
862res3: movb $0x02, %ah
863 movb $0x00, %bh
864 int $0x10
865 lodsw # Display size
866 movb %ah, %dl # DL=number of lines
867 movb $0, %ah # BX=phys. length of orig. line
868 movw %ax, %bx
869 cmpb %cl, %dl # Too many?
870 jc res4
871
872 pushw %ax
873 movb %dl, %al
874 subb %cl, %al
875 mulb %bl
876 addw %ax, %si
877 addw %ax, %si
878 popw %ax
879 movb %cl, %dl
880res4: cmpb %ch, %al # Too wide?
881 jc res5
882
883 movb %ch, %al # AX=width of src. line
884res5: movb $0, %cl
885 xchgb %ch, %cl
886 movw %cx, %bp # BP=width of dest. line
887 pushw %es
888 movw video_segment, %es
889 xorw %di, %di # Move the data
890 addw %bx, %bx # Convert BX and BP to _bytes_
891 addw %bp, %bp
892res6: pushw %si
893 pushw %di
894 movw %ax, %cx
895 rep
896 movsw
897 popw %di
898 popw %si
899 addw %bp, %di
900 addw %bx, %si
901 decb %dl
902 jnz res6
903
904 popw %es # Done
905res1: ret
906#endif /* CONFIG_VIDEO_RETAIN */
907
908# Write to indexed VGA register (AL=index, AH=data, DX=index reg. port)
909outidx: outb %al, %dx
910 pushw %ax
911 movb %ah, %al
912 incw %dx
913 outb %al, %dx
914 decw %dx
915 popw %ax
916 ret
917
918# Build the table of video modes (stored after the setup.S code at the
919# `modelist' label. Each video mode record looks like:
920# .word MODE-ID (our special mode ID (see above))
921# .byte rows (number of rows)
922# .byte columns (number of columns)
923# Returns address of the end of the table in DI, the end is marked
924# with a ASK_VGA ID.
925mode_table:
926 movw mt_end, %di # Already filled?
927 orw %di, %di
928 jnz mtab1x
929
930 leaw modelist, %di # Store standard modes:
931 movl $VIDEO_80x25 + 0x50190000, %eax # The 80x25 mode (ALL)
932 stosl
933 movb adapter, %al # CGA/MDA/HGA -- no more modes
934 orb %al, %al
935 jz mtabe
936
937 decb %al
938 jnz mtabv
939
940 movl $VIDEO_8POINT + 0x502b0000, %eax # The 80x43 EGA mode
941 stosl
942 jmp mtabe
943
944mtab1x: jmp mtab1
945
946mtabv: leaw vga_modes, %si # All modes for std VGA
947 movw $vga_modes_end-vga_modes, %cx
948 rep # I'm unable to use movsw as I don't know how to store a half
949 movsb # of the expression above to cx without using explicit shr.
950
951 cmpb $0, scanning # Mode scan requested?
952 jz mscan1
953
954 call mode_scan
955mscan1:
956
957#ifdef CONFIG_VIDEO_LOCAL
958 call local_modes
959#endif /* CONFIG_VIDEO_LOCAL */
960
961#ifdef CONFIG_VIDEO_VESA
962 call vesa_modes # Detect VESA VGA modes
963#endif /* CONFIG_VIDEO_VESA */
964
965#ifdef CONFIG_VIDEO_SVGA
966 cmpb $0, scanning # Bypass when scanning
967 jnz mscan2
968
969 call svga_modes # Detect SVGA cards & modes
970mscan2:
971#endif /* CONFIG_VIDEO_SVGA */
972
973mtabe:
974
975#ifdef CONFIG_VIDEO_COMPACT
976 leaw modelist, %si
977 movw %di, %dx
978 movw %si, %di
979cmt1: cmpw %dx, %si # Scan all modes
980 jz cmt2
981
982 leaw modelist, %bx # Find in previous entries
983 movw 2(%si), %cx
984cmt3: cmpw %bx, %si
985 jz cmt4
986
987 cmpw 2(%bx), %cx # Found => don't copy this entry
988 jz cmt5
989
990 addw $4, %bx
991 jmp cmt3
992
993cmt4: movsl # Copy entry
994 jmp cmt1
995
996cmt5: addw $4, %si # Skip entry
997 jmp cmt1
998
999cmt2:
1000#endif /* CONFIG_VIDEO_COMPACT */
1001
1002 movw $ASK_VGA, (%di) # End marker
1003 movw %di, mt_end
1004mtab1: leaw modelist, %si # SI=mode list, DI=list end
1005ret0: ret
1006
1007# Modes usable on all standard VGAs
1008vga_modes:
1009 .word VIDEO_8POINT
1010 .word 0x5032 # 80x50
1011 .word VIDEO_80x43
1012 .word 0x502b # 80x43
1013 .word VIDEO_80x28
1014 .word 0x501c # 80x28
1015 .word VIDEO_80x30
1016 .word 0x501e # 80x30
1017 .word VIDEO_80x34
1018 .word 0x5022 # 80x34
1019 .word VIDEO_80x60
1020 .word 0x503c # 80x60
1021#ifdef CONFIG_VIDEO_GFX_HACK
1022 .word VIDEO_GFX_HACK
1023 .word VIDEO_GFX_DUMMY_RESOLUTION
1024#endif
1025
1026vga_modes_end:
1027# Detect VESA modes.
1028
1029#ifdef CONFIG_VIDEO_VESA
1030vesa_modes:
1031 cmpb $2, adapter # VGA only
1032 jnz ret0
1033
1034 movw %di, %bp # BP=original mode table end
1035 addw $0x200, %di # Buffer space
1036 movw $0x4f00, %ax # VESA Get card info call
1037 int $0x10
1038 movw %bp, %di
1039 cmpw $0x004f, %ax # Successful?
1040 jnz ret0
1041
1042 cmpw $0x4556, 0x200(%di)
1043 jnz ret0
1044
1045 cmpw $0x4153, 0x202(%di)
1046 jnz ret0
1047
1048 movw $vesa_name, card_name # Set name to "VESA VGA"
1049 pushw %gs
1050 lgsw 0x20e(%di), %si # GS:SI=mode list
1051 movw $128, %cx # Iteration limit
1052vesa1:
1053# gas version 2.9.1, using BFD version 2.9.1.0.23 buggers the next inst.
1054# XXX: lodsw %gs:(%si), %ax # Get next mode in the list
1055 gs; lodsw
1056 cmpw $0xffff, %ax # End of the table?
1057 jz vesar
1058
1059 cmpw $0x0080, %ax # Check validity of mode ID
1060 jc vesa2
1061
1062 orb %ah, %ah # Valid IDs: 0x0000-0x007f/0x0100-0x07ff
1063 jz vesan # Certain BIOSes report 0x80-0xff!
1064
1065 cmpw $0x0800, %ax
1066 jnc vesae
1067
1068vesa2: pushw %cx
1069 movw %ax, %cx # Get mode information structure
1070 movw $0x4f01, %ax
1071 int $0x10
1072 movw %cx, %bx # BX=mode number
1073 addb $VIDEO_FIRST_VESA>>8, %bh
1074 popw %cx
1075 cmpw $0x004f, %ax
1076 jnz vesan # Don't report errors (buggy BIOSES)
1077
1078 movb (%di), %al # Check capabilities. We require
1079 andb $0x19, %al # a color text mode.
1080 cmpb $0x09, %al
1081 jnz vesan
1082
1083 cmpw $0xb800, 8(%di) # Standard video memory address required
1084 jnz vesan
1085
1086 testb $2, (%di) # Mode characteristics supplied?
1087 movw %bx, (%di) # Store mode number
1088 jz vesa3
1089
1090 xorw %dx, %dx
1091 movw 0x12(%di), %bx # Width
1092 orb %bh, %bh
1093 jnz vesan
1094
1095 movb %bl, 0x3(%di)
1096 movw 0x14(%di), %ax # Height
1097 orb %ah, %ah
1098 jnz vesan
1099
1100 movb %al, 2(%di)
1101 mulb %bl
1102 cmpw $8193, %ax # Small enough for Linux console driver?
1103 jnc vesan
1104
1105 jmp vesaok
1106
1107vesa3: subw $0x8108, %bx # This mode has no detailed info specified,
1108 jc vesan # so it must be a standard VESA mode.
1109
1110 cmpw $5, %bx
1111 jnc vesan
1112
1113 movw vesa_text_mode_table(%bx), %ax
1114 movw %ax, 2(%di)
1115vesaok: addw $4, %di # The mode is valid. Store it.
1116vesan: loop vesa1 # Next mode. Limit exceeded => error
1117vesae: leaw vesaer, %si
1118 call prtstr
1119 movw %bp, %di # Discard already found modes.
1120vesar: popw %gs
1121 ret
1122
1123# Dimensions of standard VESA text modes
1124vesa_text_mode_table:
1125 .byte 60, 80 # 0108
1126 .byte 25, 132 # 0109
1127 .byte 43, 132 # 010A
1128 .byte 50, 132 # 010B
1129 .byte 60, 132 # 010C
1130#endif /* CONFIG_VIDEO_VESA */
1131
1132# Scan for video modes. A bit dirty, but should work.
1133mode_scan:
1134 movw $0x0100, %cx # Start with mode 0
1135scm1: movb $0, %ah # Test the mode
1136 movb %cl, %al
1137 int $0x10
1138 movb $0x0f, %ah
1139 int $0x10
1140 cmpb %cl, %al
1141 jnz scm2 # Mode not set
1142
1143 movw $0x3c0, %dx # Test if it's a text mode
1144 movb $0x10, %al # Mode bits
1145 call inidx
1146 andb $0x03, %al
1147 jnz scm2
1148
1149 movb $0xce, %dl # Another set of mode bits
1150 movb $0x06, %al
1151 call inidx
1152 shrb %al
1153 jc scm2
1154
1155 movb $0xd4, %dl # Cursor location
1156 movb $0x0f, %al
1157 call inidx
1158 orb %al, %al
1159 jnz scm2
1160
1161 movw %cx, %ax # Ok, store the mode
1162 stosw
1163 movb %gs:(0x484), %al # Number of rows
1164 incb %al
1165 stosb
1166 movw %gs:(0x44a), %ax # Number of columns
1167 stosb
1168scm2: incb %cl
1169 jns scm1
1170
1171 movw $0x0003, %ax # Return back to mode 3
1172 int $0x10
1173 ret
1174
1175tstidx: outw %ax, %dx # OUT DX,AX and inidx
1176inidx: outb %al, %dx # Read from indexed VGA register
1177 incw %dx # AL=index, DX=index reg port -> AL=data
1178 inb %dx, %al
1179 decw %dx
1180 ret
1181
1182# Try to detect type of SVGA card and supply (usually approximate) video
1183# mode table for it.
1184
1185#ifdef CONFIG_VIDEO_SVGA
1186svga_modes:
1187 leaw svga_table, %si # Test all known SVGA adapters
1188dosvga: lodsw
1189 movw %ax, %bp # Default mode table
1190 orw %ax, %ax
1191 jz didsv1
1192
1193 lodsw # Pointer to test routine
1194 pushw %si
1195 pushw %di
1196 pushw %es
1197 movw $0xc000, %bx
1198 movw %bx, %es
1199 call *%ax # Call test routine
1200 popw %es
1201 popw %di
1202 popw %si
1203 orw %bp, %bp
1204 jz dosvga
1205
1206 movw %bp, %si # Found, copy the modes
1207 movb svga_prefix, %ah
1208cpsvga: lodsb
1209 orb %al, %al
1210 jz didsv
1211
1212 stosw
1213 movsw
1214 jmp cpsvga
1215
1216didsv: movw %si, card_name # Store pointer to card name
1217didsv1: ret
1218
1219# Table of all known SVGA cards. For each card, we store a pointer to
1220# a table of video modes supported by the card and a pointer to a routine
1221# used for testing of presence of the card. The video mode table is always
1222# followed by the name of the card or the chipset.
1223svga_table:
1224 .word ati_md, ati_test
1225 .word oak_md, oak_test
1226 .word paradise_md, paradise_test
1227 .word realtek_md, realtek_test
1228 .word s3_md, s3_test
1229 .word chips_md, chips_test
1230 .word video7_md, video7_test
1231 .word cirrus5_md, cirrus5_test
1232 .word cirrus6_md, cirrus6_test
1233 .word cirrus1_md, cirrus1_test
1234 .word ahead_md, ahead_test
1235 .word everex_md, everex_test
1236 .word genoa_md, genoa_test
1237 .word trident_md, trident_test
1238 .word tseng_md, tseng_test
1239 .word 0
1240
1241# Test routines and mode tables:
1242
1243# S3 - The test algorithm was taken from the SuperProbe package
1244# for XFree86 1.2.1. Report bugs to Christoph.Niemann@linux.org
1245s3_test:
1246 movw $0x0f35, %cx # we store some constants in cl/ch
1247 movw $0x03d4, %dx
1248 movb $0x38, %al
1249 call inidx
1250 movb %al, %bh # store current CRT-register 0x38
1251 movw $0x0038, %ax
1252 call outidx # disable writing to special regs
1253 movb %cl, %al # check whether we can write special reg 0x35
1254 call inidx
1255 movb %al, %bl # save the current value of CRT reg 0x35
1256 andb $0xf0, %al # clear bits 0-3
1257 movb %al, %ah
1258 movb %cl, %al # and write it to CRT reg 0x35
1259 call outidx
1260 call inidx # now read it back
1261 andb %ch, %al # clear the upper 4 bits
1262 jz s3_2 # the first test failed. But we have a
1263
1264 movb %bl, %ah # second chance
1265 movb %cl, %al
1266 call outidx
1267 jmp s3_1 # do the other tests
1268
1269s3_2: movw %cx, %ax # load ah with 0xf and al with 0x35
1270 orb %bl, %ah # set the upper 4 bits of ah with the orig value
1271 call outidx # write ...
1272 call inidx # ... and reread
1273 andb %cl, %al # turn off the upper 4 bits
1274 pushw %ax
1275 movb %bl, %ah # restore old value in register 0x35
1276 movb %cl, %al
1277 call outidx
1278 popw %ax
1279 cmpb %ch, %al # setting lower 4 bits was successful => bad
1280 je no_s3 # writing is allowed => this is not an S3
1281
1282s3_1: movw $0x4838, %ax # allow writing to special regs by putting
1283 call outidx # magic number into CRT-register 0x38
1284 movb %cl, %al # check whether we can write special reg 0x35
1285 call inidx
1286 movb %al, %bl
1287 andb $0xf0, %al
1288 movb %al, %ah
1289 movb %cl, %al
1290 call outidx
1291 call inidx
1292 andb %ch, %al
1293 jnz no_s3 # no, we can't write => no S3
1294
1295 movw %cx, %ax
1296 orb %bl, %ah
1297 call outidx
1298 call inidx
1299 andb %ch, %al
1300 pushw %ax
1301 movb %bl, %ah # restore old value in register 0x35
1302 movb %cl, %al
1303 call outidx
1304 popw %ax
1305 cmpb %ch, %al
1306 jne no_s31 # writing not possible => no S3
1307 movb $0x30, %al
1308 call inidx # now get the S3 id ...
1309 leaw idS3, %di
1310 movw $0x10, %cx
1311 repne
1312 scasb
1313 je no_s31
1314
1315 movb %bh, %ah
1316 movb $0x38, %al
1317 jmp s3rest
1318
1319no_s3: movb $0x35, %al # restore CRT register 0x35
1320 movb %bl, %ah
1321 call outidx
1322no_s31: xorw %bp, %bp # Detection failed
1323s3rest: movb %bh, %ah
1324 movb $0x38, %al # restore old value of CRT register 0x38
1325 jmp outidx
1326
1327idS3: .byte 0x81, 0x82, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95
1328 .byte 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa8, 0xb0
1329
1330s3_md: .byte 0x54, 0x2b, 0x84
1331 .byte 0x55, 0x19, 0x84
1332 .byte 0
1333 .ascii "S3"
1334 .byte 0
1335
1336# ATI cards.
1337ati_test:
1338 leaw idati, %si
1339 movw $0x31, %di
1340 movw $0x09, %cx
1341 repe
1342 cmpsb
1343 je atiok
1344
1345 xorw %bp, %bp
1346atiok: ret
1347
1348idati: .ascii "761295520"
1349
1350ati_md: .byte 0x23, 0x19, 0x84
1351 .byte 0x33, 0x2c, 0x84
1352 .byte 0x22, 0x1e, 0x64
1353 .byte 0x21, 0x19, 0x64
1354 .byte 0x58, 0x21, 0x50
1355 .byte 0x5b, 0x1e, 0x50
1356 .byte 0
1357 .ascii "ATI"
1358 .byte 0
1359
1360# AHEAD
1361ahead_test:
1362 movw $0x200f, %ax
1363 movw $0x3ce, %dx
1364 outw %ax, %dx
1365 incw %dx
1366 inb %dx, %al
1367 cmpb $0x20, %al
1368 je isahed
1369
1370 cmpb $0x21, %al
1371 je isahed
1372
1373 xorw %bp, %bp
1374isahed: ret
1375
1376ahead_md:
1377 .byte 0x22, 0x2c, 0x84
1378 .byte 0x23, 0x19, 0x84
1379 .byte 0x24, 0x1c, 0x84
1380 .byte 0x2f, 0x32, 0xa0
1381 .byte 0x32, 0x22, 0x50
1382 .byte 0x34, 0x42, 0x50
1383 .byte 0
1384 .ascii "Ahead"
1385 .byte 0
1386
1387# Chips & Tech.
1388chips_test:
1389 movw $0x3c3, %dx
1390 inb %dx, %al
1391 orb $0x10, %al
1392 outb %al, %dx
1393 movw $0x104, %dx
1394 inb %dx, %al
1395 movb %al, %bl
1396 movw $0x3c3, %dx
1397 inb %dx, %al
1398 andb $0xef, %al
1399 outb %al, %dx
1400 cmpb $0xa5, %bl
1401 je cantok
1402
1403 xorw %bp, %bp
1404cantok: ret
1405
1406chips_md:
1407 .byte 0x60, 0x19, 0x84
1408 .byte 0x61, 0x32, 0x84
1409 .byte 0
1410 .ascii "Chips & Technologies"
1411 .byte 0
1412
1413# Cirrus Logic 5X0
1414cirrus1_test:
1415 movw $0x3d4, %dx
1416 movb $0x0c, %al
1417 outb %al, %dx
1418 incw %dx
1419 inb %dx, %al
1420 movb %al, %bl
1421 xorb %al, %al
1422 outb %al, %dx
1423 decw %dx
1424 movb $0x1f, %al
1425 outb %al, %dx
1426 incw %dx
1427 inb %dx, %al
1428 movb %al, %bh
1429 xorb %ah, %ah
1430 shlb $4, %al
1431 movw %ax, %cx
1432 movb %bh, %al
1433 shrb $4, %al
1434 addw %ax, %cx
1435 shlw $8, %cx
1436 addw $6, %cx
1437 movw %cx, %ax
1438 movw $0x3c4, %dx
1439 outw %ax, %dx
1440 incw %dx
1441 inb %dx, %al
1442 andb %al, %al
1443 jnz nocirr
1444
1445 movb %bh, %al
1446 outb %al, %dx
1447 inb %dx, %al
1448 cmpb $0x01, %al
1449 je iscirr
1450
1451nocirr: xorw %bp, %bp
1452iscirr: movw $0x3d4, %dx
1453 movb %bl, %al
1454 xorb %ah, %ah
1455 shlw $8, %ax
1456 addw $0x0c, %ax
1457 outw %ax, %dx
1458 ret
1459
1460cirrus1_md:
1461 .byte 0x1f, 0x19, 0x84
1462 .byte 0x20, 0x2c, 0x84
1463 .byte 0x22, 0x1e, 0x84
1464 .byte 0x31, 0x25, 0x64
1465 .byte 0
1466 .ascii "Cirrus Logic 5X0"
1467 .byte 0
1468
1469# Cirrus Logic 54XX
1470cirrus5_test:
1471 movw $0x3c4, %dx
1472 movb $6, %al
1473 call inidx
1474 movb %al, %bl # BL=backup
1475 movw $6, %ax
1476 call tstidx
1477 cmpb $0x0f, %al
1478 jne c5fail
1479
1480 movw $0x1206, %ax
1481 call tstidx
1482 cmpb $0x12, %al
1483 jne c5fail
1484
1485 movb $0x1e, %al
1486 call inidx
1487 movb %al, %bh
1488 movb %bh, %ah
1489 andb $0xc0, %ah
1490 movb $0x1e, %al
1491 call tstidx
1492 andb $0x3f, %al
1493 jne c5xx
1494
1495 movb $0x1e, %al
1496 movb %bh, %ah
1497 orb $0x3f, %ah
1498 call tstidx
1499 xorb $0x3f, %al
1500 andb $0x3f, %al
1501c5xx: pushf
1502 movb $0x1e, %al
1503 movb %bh, %ah
1504 outw %ax, %dx
1505 popf
1506 je c5done
1507
1508c5fail: xorw %bp, %bp
1509c5done: movb $6, %al
1510 movb %bl, %ah
1511 outw %ax, %dx
1512 ret
1513
1514cirrus5_md:
1515 .byte 0x14, 0x19, 0x84
1516 .byte 0x54, 0x2b, 0x84
1517 .byte 0
1518 .ascii "Cirrus Logic 54XX"
1519 .byte 0
1520
1521# Cirrus Logic 64XX -- no known extra modes, but must be identified, because
1522# it's misidentified by the Ahead test.
1523cirrus6_test:
1524 movw $0x3ce, %dx
1525 movb $0x0a, %al
1526 call inidx
1527 movb %al, %bl # BL=backup
1528 movw $0xce0a, %ax
1529 call tstidx
1530 orb %al, %al
1531 jne c2fail
1532
1533 movw $0xec0a, %ax
1534 call tstidx
1535 cmpb $0x01, %al
1536 jne c2fail
1537
1538 movb $0xaa, %al
1539 call inidx # 4X, 5X, 7X and 8X are valid 64XX chip ID's.
1540 shrb $4, %al
1541 subb $4, %al
1542 jz c6done
1543
1544 decb %al
1545 jz c6done
1546
1547 subb $2, %al
1548 jz c6done
1549
1550 decb %al
1551 jz c6done
1552
1553c2fail: xorw %bp, %bp
1554c6done: movb $0x0a, %al
1555 movb %bl, %ah
1556 outw %ax, %dx
1557 ret
1558
1559cirrus6_md:
1560 .byte 0
1561 .ascii "Cirrus Logic 64XX"
1562 .byte 0
1563
1564# Everex / Trident
1565everex_test:
1566 movw $0x7000, %ax
1567 xorw %bx, %bx
1568 int $0x10
1569 cmpb $0x70, %al
1570 jne noevrx
1571
1572 shrw $4, %dx
1573 cmpw $0x678, %dx
1574 je evtrid
1575
1576 cmpw $0x236, %dx
1577 jne evrxok
1578
1579evtrid: leaw trident_md, %bp
1580evrxok: ret
1581
1582noevrx: xorw %bp, %bp
1583 ret
1584
1585everex_md:
1586 .byte 0x03, 0x22, 0x50
1587 .byte 0x04, 0x3c, 0x50
1588 .byte 0x07, 0x2b, 0x64
1589 .byte 0x08, 0x4b, 0x64
1590 .byte 0x0a, 0x19, 0x84
1591 .byte 0x0b, 0x2c, 0x84
1592 .byte 0x16, 0x1e, 0x50
1593 .byte 0x18, 0x1b, 0x64
1594 .byte 0x21, 0x40, 0xa0
1595 .byte 0x40, 0x1e, 0x84
1596 .byte 0
1597 .ascii "Everex/Trident"
1598 .byte 0
1599
1600# Genoa.
1601genoa_test:
1602 leaw idgenoa, %si # Check Genoa 'clues'
1603 xorw %ax, %ax
1604 movb %es:(0x37), %al
1605 movw %ax, %di
1606 movw $0x04, %cx
1607 decw %si
1608 decw %di
1609l1: incw %si
1610 incw %di
1611 movb (%si), %al
1612 testb %al, %al
1613 jz l2
1614
1615 cmpb %es:(%di), %al
1616l2: loope l1
1617 orw %cx, %cx
1618 je isgen
1619
1620 xorw %bp, %bp
1621isgen: ret
1622
1623idgenoa: .byte 0x77, 0x00, 0x99, 0x66
1624
1625genoa_md:
1626 .byte 0x58, 0x20, 0x50
1627 .byte 0x5a, 0x2a, 0x64
1628 .byte 0x60, 0x19, 0x84
1629 .byte 0x61, 0x1d, 0x84
1630 .byte 0x62, 0x20, 0x84
1631 .byte 0x63, 0x2c, 0x84
1632 .byte 0x64, 0x3c, 0x84
1633 .byte 0x6b, 0x4f, 0x64
1634 .byte 0x72, 0x3c, 0x50
1635 .byte 0x74, 0x42, 0x50
1636 .byte 0x78, 0x4b, 0x64
1637 .byte 0
1638 .ascii "Genoa"
1639 .byte 0
1640
1641# OAK
1642oak_test:
1643 leaw idoakvga, %si
1644 movw $0x08, %di
1645 movw $0x08, %cx
1646 repe
1647 cmpsb
1648 je isoak
1649
1650 xorw %bp, %bp
1651isoak: ret
1652
1653idoakvga: .ascii "OAK VGA "
1654
1655oak_md: .byte 0x4e, 0x3c, 0x50
1656 .byte 0x4f, 0x3c, 0x84
1657 .byte 0x50, 0x19, 0x84
1658 .byte 0x51, 0x2b, 0x84
1659 .byte 0
1660 .ascii "OAK"
1661 .byte 0
1662
1663# WD Paradise.
1664paradise_test:
1665 leaw idparadise, %si
1666 movw $0x7d, %di
1667 movw $0x04, %cx
1668 repe
1669 cmpsb
1670 je ispara
1671
1672 xorw %bp, %bp
1673ispara: ret
1674
1675idparadise: .ascii "VGA="
1676
1677paradise_md:
1678 .byte 0x41, 0x22, 0x50
1679 .byte 0x47, 0x1c, 0x84
1680 .byte 0x55, 0x19, 0x84
1681 .byte 0x54, 0x2c, 0x84
1682 .byte 0
1683 .ascii "Paradise"
1684 .byte 0
1685
1686# Trident.
1687trident_test:
1688 movw $0x3c4, %dx
1689 movb $0x0e, %al
1690 outb %al, %dx
1691 incw %dx
1692 inb %dx, %al
1693 xchgb %al, %ah
1694 xorb %al, %al
1695 outb %al, %dx
1696 inb %dx, %al
1697 xchgb %ah, %al
1698 movb %al, %bl # Strange thing ... in the book this wasn't
1699 andb $0x02, %bl # necessary but it worked on my card which
1700 jz setb2 # is a trident. Without it the screen goes
1701 # blurred ...
1702 andb $0xfd, %al
1703 jmp clrb2
1704
1705setb2: orb $0x02, %al
1706clrb2: outb %al, %dx
1707 andb $0x0f, %ah
1708 cmpb $0x02, %ah
1709 je istrid
1710
1711 xorw %bp, %bp
1712istrid: ret
1713
1714trident_md:
1715 .byte 0x50, 0x1e, 0x50
1716 .byte 0x51, 0x2b, 0x50
1717 .byte 0x52, 0x3c, 0x50
1718 .byte 0x57, 0x19, 0x84
1719 .byte 0x58, 0x1e, 0x84
1720 .byte 0x59, 0x2b, 0x84
1721 .byte 0x5a, 0x3c, 0x84
1722 .byte 0
1723 .ascii "Trident"
1724 .byte 0
1725
1726# Tseng.
1727tseng_test:
1728 movw $0x3cd, %dx
1729 inb %dx, %al # Could things be this simple ! :-)
1730 movb %al, %bl
1731 movb $0x55, %al
1732 outb %al, %dx
1733 inb %dx, %al
1734 movb %al, %ah
1735 movb %bl, %al
1736 outb %al, %dx
1737 cmpb $0x55, %ah
1738 je istsen
1739
1740isnot: xorw %bp, %bp
1741istsen: ret
1742
1743tseng_md:
1744 .byte 0x26, 0x3c, 0x50
1745 .byte 0x2a, 0x28, 0x64
1746 .byte 0x23, 0x19, 0x84
1747 .byte 0x24, 0x1c, 0x84
1748 .byte 0x22, 0x2c, 0x84
1749 .byte 0x21, 0x3c, 0x84
1750 .byte 0
1751 .ascii "Tseng"
1752 .byte 0
1753
1754# Video7.
1755video7_test:
1756 movw $0x3cc, %dx
1757 inb %dx, %al
1758 movw $0x3b4, %dx
1759 andb $0x01, %al
1760 jz even7
1761
1762 movw $0x3d4, %dx
1763even7: movb $0x0c, %al
1764 outb %al, %dx
1765 incw %dx
1766 inb %dx, %al
1767 movb %al, %bl
1768 movb $0x55, %al
1769 outb %al, %dx
1770 inb %dx, %al
1771 decw %dx
1772 movb $0x1f, %al
1773 outb %al, %dx
1774 incw %dx
1775 inb %dx, %al
1776 movb %al, %bh
1777 decw %dx
1778 movb $0x0c, %al
1779 outb %al, %dx
1780 incw %dx
1781 movb %bl, %al
1782 outb %al, %dx
1783 movb $0x55, %al
1784 xorb $0xea, %al
1785 cmpb %bh, %al
1786 jne isnot
1787
1788 movb $VIDEO_FIRST_V7>>8, svga_prefix # Use special mode switching
1789 ret
1790
1791video7_md:
1792 .byte 0x40, 0x2b, 0x50
1793 .byte 0x43, 0x3c, 0x50
1794 .byte 0x44, 0x3c, 0x64
1795 .byte 0x41, 0x19, 0x84
1796 .byte 0x42, 0x2c, 0x84
1797 .byte 0x45, 0x1c, 0x84
1798 .byte 0
1799 .ascii "Video 7"
1800 .byte 0
1801
1802# Realtek VGA
1803realtek_test:
1804 leaw idrtvga, %si
1805 movw $0x45, %di
1806 movw $0x0b, %cx
1807 repe
1808 cmpsb
1809 je isrt
1810
1811 xorw %bp, %bp
1812isrt: ret
1813
1814idrtvga: .ascii "REALTEK VGA"
1815
1816realtek_md:
1817 .byte 0x1a, 0x3c, 0x50
1818 .byte 0x1b, 0x19, 0x84
1819 .byte 0x1c, 0x1e, 0x84
1820 .byte 0x1d, 0x2b, 0x84
1821 .byte 0x1e, 0x3c, 0x84
1822 .byte 0
1823 .ascii "REALTEK"
1824 .byte 0
1825
1826#endif /* CONFIG_VIDEO_SVGA */
1827
1828# User-defined local mode table (VGA only)
1829#ifdef CONFIG_VIDEO_LOCAL
1830local_modes:
1831 leaw local_mode_table, %si
1832locm1: lodsw
1833 orw %ax, %ax
1834 jz locm2
1835
1836 stosw
1837 movsw
1838 jmp locm1
1839
1840locm2: ret
1841
1842# This is the table of local video modes which can be supplied manually
1843# by the user. Each entry consists of mode ID (word) and dimensions
1844# (byte for column count and another byte for row count). These modes
1845# are placed before all SVGA and VESA modes and override them if table
1846# compacting is enabled. The table must end with a zero word followed
1847# by NUL-terminated video adapter name.
1848local_mode_table:
1849 .word 0x0100 # Example: 40x25
1850 .byte 25,40
1851 .word 0
1852 .ascii "Local"
1853 .byte 0
1854#endif /* CONFIG_VIDEO_LOCAL */
1855
1856# Read a key and return the ASCII code in al, scan code in ah
1857getkey: xorb %ah, %ah
1858 int $0x16
1859 ret
1860
1861# Read a key with a timeout of 30 seconds.
1862# The hardware clock is used to get the time.
1863getkt: call gettime
1864 addb $30, %al # Wait 30 seconds
1865 cmpb $60, %al
1866 jl lminute
1867
1868 subb $60, %al
1869lminute:
1870 movb %al, %cl
1871again: movb $0x01, %ah
1872 int $0x16
1873 jnz getkey # key pressed, so get it
1874
1875 call gettime
1876 cmpb %cl, %al
1877 jne again
1878
1879 movb $0x20, %al # timeout, return `space'
1880 ret
1881
1882# Flush the keyboard buffer
1883flush: movb $0x01, %ah
1884 int $0x16
1885 jz empty
1886
1887 xorb %ah, %ah
1888 int $0x16
1889 jmp flush
1890
1891empty: ret
1892
1893# Print hexadecimal number.
1894prthw: pushw %ax
1895 movb %ah, %al
1896 call prthb
1897 popw %ax
1898prthb: pushw %ax
1899 shrb $4, %al
1900 call prthn
1901 popw %ax
1902 andb $0x0f, %al
1903prthn: cmpb $0x0a, %al
1904 jc prth1
1905
1906 addb $0x07, %al
1907prth1: addb $0x30, %al
1908 jmp prtchr
1909
1910# Print decimal number in al
1911prtdec: pushw %ax
1912 pushw %cx
1913 xorb %ah, %ah
1914 movb $0x0a, %cl
1915 idivb %cl
1916 cmpb $0x09, %al
1917 jbe lt100
1918
1919 call prtdec
1920 jmp skip10
1921
1922lt100: addb $0x30, %al
1923 call prtchr
1924skip10: movb %ah, %al
1925 addb $0x30, %al
1926 call prtchr
1927 popw %cx
1928 popw %ax
1929 ret
1930
1931store_edid:
Antonino A. Daplasba707102006-06-26 00:26:37 -07001932#ifdef CONFIG_FIRMWARE_EDID
Domen Puncer125947f2005-05-05 16:16:15 -07001933 pushw %es # just save all registers
1934 pushw %ax
Linus Torvalds1da177e2005-04-16 15:20:36 -07001935 pushw %bx
1936 pushw %cx
1937 pushw %dx
1938 pushw %di
1939
Domen Puncer125947f2005-05-05 16:16:15 -07001940 pushw %fs
Linus Torvalds1da177e2005-04-16 15:20:36 -07001941 popw %es
1942
1943 movl $0x13131313, %eax # memset block with 0x13
1944 movw $32, %cx
1945 movw $0x140, %di
1946 cld
Domen Puncer125947f2005-05-05 16:16:15 -07001947 rep
1948 stosl
Linus Torvalds1da177e2005-04-16 15:20:36 -07001949
Antonino A. Daplasba707102006-06-26 00:26:37 -07001950 pushw %es # save ES
1951 xorw %di, %di # Report Capability
1952 pushw %di
1953 popw %es # ES:DI must be 0:0
1954 movw $0x4f15, %ax
1955 xorw %bx, %bx
1956 xorw %cx, %cx
1957 int $0x10
1958 popw %es # restore ES
1959
1960 cmpb $0x00, %ah # call successful
1961 jne no_edid
1962
1963 cmpb $0x4f, %al # function supported
1964 jne no_edid
1965
Domen Puncer125947f2005-05-05 16:16:15 -07001966 movw $0x4f15, %ax # do VBE/DDC
Linus Torvalds1da177e2005-04-16 15:20:36 -07001967 movw $0x01, %bx
1968 movw $0x00, %cx
Antonino A. Daplas5e518d72005-09-09 13:04:34 -07001969 movw $0x00, %dx
Linus Torvalds1da177e2005-04-16 15:20:36 -07001970 movw $0x140, %di
Domen Puncer125947f2005-05-05 16:16:15 -07001971 int $0x10
Linus Torvalds1da177e2005-04-16 15:20:36 -07001972
Antonino A. Daplasba707102006-06-26 00:26:37 -07001973no_edid:
Domen Puncer125947f2005-05-05 16:16:15 -07001974 popw %di # restore all registers
Linus Torvalds1da177e2005-04-16 15:20:36 -07001975 popw %dx
1976 popw %cx
1977 popw %bx
1978 popw %ax
Domen Puncer125947f2005-05-05 16:16:15 -07001979 popw %es
Antonino A. Daplas59153f72006-03-27 01:17:29 -08001980#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001981 ret
1982
1983# VIDEO_SELECT-only variables
1984mt_end: .word 0 # End of video mode table if built
1985edit_buf: .space 6 # Line editor buffer
1986card_name: .word 0 # Pointer to adapter name
1987scanning: .byte 0 # Performing mode scan
1988do_restore: .byte 0 # Screen contents altered during mode change
1989svga_prefix: .byte VIDEO_FIRST_BIOS>>8 # Default prefix for BIOS modes
1990graphic_mode: .byte 0 # Graphic mode with a linear frame buffer
1991dac_size: .byte 6 # DAC bit depth
1992
1993# Status messages
1994keymsg: .ascii "Press <RETURN> to see video modes available, "
1995 .ascii "<SPACE> to continue or wait 30 secs"
1996 .byte 0x0d, 0x0a, 0
1997
1998listhdr: .byte 0x0d, 0x0a
1999 .ascii "Mode: COLSxROWS:"
2000
2001crlft: .byte 0x0d, 0x0a, 0
2002
2003prompt: .byte 0x0d, 0x0a
2004 .asciz "Enter mode number or `scan': "
2005
2006unknt: .asciz "Unknown mode ID. Try again."
2007
2008badmdt: .ascii "You passed an undefined mode number."
2009 .byte 0x0d, 0x0a, 0
2010
2011vesaer: .ascii "Error: Scanning of VESA modes failed. Please "
2012 .ascii "report to <mj@ucw.cz>."
2013 .byte 0x0d, 0x0a, 0
2014
2015old_name: .asciz "CGA/MDA/HGA"
2016
2017ega_name: .asciz "EGA"
2018
2019svga_name: .ascii " "
2020
2021vga_name: .asciz "VGA"
2022
2023vesa_name: .asciz "VESA"
2024
2025name_bann: .asciz "Video adapter: "
2026#endif /* CONFIG_VIDEO_SELECT */
2027
2028# Other variables:
2029adapter: .byte 0 # Video adapter: 0=CGA/MDA/HGA,1=EGA,2=VGA
2030video_segment: .word 0xb800 # Video memory segment
2031force_size: .word 0 # Use this size instead of the one in BIOS vars