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

