linux-old/arch/x86_64/boot/video.S
<<
>>
Prefs
   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
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.