root/arch/i386/boot/video.S

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

/* [previous][next][first][last][top][bottom][index][help] */