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