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