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