root/arch/i386/boot/video.S

/* [previous][next][first][last][top][bottom][index][help] */
   1 !
   2 !       Display adapter & video mode setup, version 2.8 (14-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 ! Write to indexed VGA register (AL=index, AH=data, DX=index reg. port)
 743 !
 744 
 745 outidx: out     dx,al
 746         push    ax
 747         mov     al,ah
 748         inc     dx
 749         out     dx,al
 750         dec     dx
 751         pop     ax
 752         ret
 753 
 754 !
 755 ! Build the table of video modes (stored after the setup.S code at the
 756 ! `modelist' label. Each video mode record looks like:
 757 !       .word   MODE-ID         (our special mode ID (see above))
 758 !       .byte   rows            (number of rows)
 759 !       .byte   columns         (number of columns)
 760 ! Returns address of the end of the table in DI, the end is marked
 761 ! with a ASK_VGA ID.
 762 !
 763 
 764 mode_table:
 765         mov     di,[mt_end]     ! Already filled?
 766         or      di,di
 767         jnz     mtab1x
 768         lea     di,modelist     ! Store standard modes:
 769 
 770         mov     eax,#VIDEO_80x25 + 0x50190000   ! The 80x25 mode (ALL)
 771         stosd
 772         mov     al,[adapter]    ! CGA/MDA/HGA -- no more modes
 773         or      al,al
 774         jz      mtabe
 775         dec     al
 776         jnz     mtabv
 777         mov     eax,#VIDEO_8POINT + 0x502b0000  ! The 80x43 EGA mode
 778         stosd
 779         jmp     mtabe
 780 mtab1x: jmp     mtab1
 781 
 782 mtabv:  lea     si,vga_modes                    ! All modes for std VGA
 783         mov     cx,#12
 784         rep
 785         movsw
 786 
 787         cmpb    [scanning],#0                   ! Mode scan requested?
 788         jz      mscan1
 789         call    mode_scan
 790 mscan1:
 791 
 792 #ifdef CONFIG_VIDEO_LOCAL
 793         call    local_modes
 794 #endif
 795 #ifdef CONFIG_VIDEO_VESA
 796         call    vesa_modes                      ! Detect VESA VGA modes
 797 #endif
 798 #ifdef CONFIG_VIDEO_SVGA
 799         cmpb    [scanning],#0                   ! Bypass when scanning
 800         jnz     mscan2
 801         call    svga_modes                      ! Detect SVGA cards & modes
 802 mscan2:
 803 #endif
 804 
 805 mtabe:
 806 
 807 #ifdef CONFIG_VIDEO_COMPACT
 808         lea     si,modelist     ! Compact video mode list if requested.
 809         mov     dx,di
 810         mov     di,si
 811 cmt1:   cmp     si,dx           ! Scan all modes
 812         jz      cmt2
 813         lea     bx,modelist     ! Find in previous entries
 814         mov     cx,(si+2)
 815 cmt3:   cmp     si,bx
 816         jz      cmt4
 817         cmp     cx,(bx+2)       ! Found => don't copy this entry
 818         jz      cmt5
 819         add     bx,#4
 820         jmp     cmt3
 821 
 822 cmt4:   movsd                   ! Copy entry
 823         jmp     cmt1
 824 
 825 cmt5:   add     si,#4           ! Skip entry
 826         jmp     cmt1
 827 
 828 cmt2:
 829 #endif  /* CONFIG_VIDEO_COMPACT */
 830 
 831         mov     (di),#ASK_VGA   ! End marker
 832         mov     [mt_end],di
 833 mtab1:  lea     si,modelist     ! Returning: SI=mode list, DI=list end
 834 ret0:   ret
 835 
 836 ! Modes usable on all standard VGAs
 837 
 838 vga_modes:
 839         .word   VIDEO_8POINT
 840         .word   0x5032          ! 80x50
 841         .word   VIDEO_80x43
 842         .word   0x502b          ! 80x43
 843         .word   VIDEO_80x28
 844         .word   0x501c          ! 80x28
 845         .word   VIDEO_80x30
 846         .word   0x501e          ! 80x30
 847         .word   VIDEO_80x34
 848         .word   0x5022          ! 80x34
 849         .word   VIDEO_80x60
 850         .word   0x503c          ! 80x60
 851 
 852 !
 853 ! Detect VESA modes.
 854 !
 855 
 856 #ifdef CONFIG_VIDEO_VESA
 857 
 858 vesa_modes:
 859         cmpb    [adapter],#2    ! VGA only
 860         jnz     ret0
 861         mov     bp,di           ! BP=original mode table end
 862         add     di,#0x200       ! Buffer space
 863         mov     ax,#0x4f00      ! VESA Get card info call
 864         int     #0x10
 865         mov     di,bp
 866         cmp     ax,#0x004f      ! Successful?
 867         jnz     ret0
 868         cmp     (di+0x200),#0x4556
 869         jnz     ret0
 870         cmp     (di+0x202),#0x4153
 871         jnz     ret0
 872         mov     [card_name],#vesa_name  ! Set name to "VESA VGA"
 873         push    gs
 874         lgs     si,(di+0x20e)   ! GS:SI=mode list
 875         mov     cx,#128         ! Iteration limit
 876 vesa1:  seg     gs              ! Get next mode in the list
 877         lodsw
 878         cmp     ax,#0xffff      ! End of the table?
 879         jz      vesar
 880         cmp     ax,#0x0080      ! Check validity of mode ID
 881         jc      vesa2
 882         or      ah,ah           ! Valid ID's are 0x0000-0x007f
 883         jz      vesae           ! and 0x0100-0x07ff.
 884         cmp     ax,#0x0800
 885         jnc     vesae
 886 vesa2:  push    cx
 887         mov     cx,ax           ! Get mode information structure
 888         mov     ax,#0x4f01
 889         int     0x10
 890         mov     bx,cx           ! BX=mode number
 891         add     bh,#VIDEO_FIRST_VESA>>8
 892         pop     cx
 893         cmp     ax,#0x004f
 894         jnz     vesan           ! Don't report errors (buggy BIOSES :-[ )
 895         mov     al,(di)         ! Check capabilities. We require
 896         and     al,#0x19        ! a color text mode.
 897         cmp     al,#0x09
 898         jnz     vesan
 899         cmp     (di+8),#0xb800  ! Standard video memory address required
 900         jnz     vesan
 901         testb   (di),#2         ! Mode characteristics supplied?
 902         mov     (di),bx         ! Store mode number
 903         jz      vesa3
 904         xor     dx,dx
 905         mov     bx,(di+0x12)    ! Width
 906         or      bh,bh
 907         jnz     vesan
 908         mov     (di+3),bl
 909         mov     ax,(di+0x14)    ! Height
 910         or      ah,ah
 911         jnz     vesan
 912         mov     (di+2),al
 913         mul     bl
 914         cmp     ax,#8193        ! Small enough for Linux console driver?
 915         jnc     vesan
 916         jmp     vesaok
 917 
 918 vesa3:  sub     bx,#0x8108      ! This mode has no detailed info specified,
 919         jc      vesan           ! so it must be a standard VESA mode.
 920         cmp     bx,#5
 921         jnc     vesan
 922         mov     ax,(bx+vesa_text_mode_table)
 923         mov     (di+2),ax
 924 vesaok: add     di,#4           ! The mode is valid. Store it.
 925 vesan:  loop    vesa1           ! Next mode. Limit exceeded => error
 926 vesae:  lea     si,vesaer
 927         call    prtstr
 928         mov     di,bp           ! Discard already found modes.
 929 vesar:  pop     gs
 930         ret
 931 
 932 !
 933 ! Dimensions of standard VESA text modes
 934 !
 935 
 936 vesa_text_mode_table:
 937         db      60, 80          ! 0108
 938         db      25, 132         ! 0109
 939         db      43, 132         ! 010A
 940         db      50, 132         ! 010B
 941         db      60, 132         ! 010C
 942 
 943 #endif  /* CONFIG_VIDEO_VESA */
 944 
 945 !
 946 ! Scan for video modes. A bit dirty, but should work.
 947 !
 948 
 949 mode_scan:
 950         mov     cx,#0x0100      ! Start with mode 0
 951 scm1:   mov     ah,#0           ! Test the mode
 952         mov     al,cl
 953         int     0x10
 954         mov     ah,#0x0f
 955         int     0x10
 956         cmp     al,cl
 957         jnz     scm2            ! Mode not set
 958         mov     dx,#0x3c0       ! Test if it's a text mode
 959         mov     al,#0x10                ! Mode bits
 960         call    inidx
 961         and     al,#0x03
 962         jnz     scm2
 963         mov     dl,#0xce                ! Another set of mode bits
 964         mov     al,#0x06
 965         call    inidx
 966         shr     al,#1
 967         jc      scm2
 968         mov     dl,#0xd4                ! Cursor location
 969         mov     al,#0x0f
 970         call    inidx
 971         or      al,al
 972         jnz     scm2
 973         mov     ax,cx           ! OK, store the mode
 974         stosw
 975         seg     gs              ! Number of rows
 976         mov     al,[0x484]
 977         inc     al
 978         stosb
 979         seg     gs              ! Number of columns
 980         mov     ax,[0x44a]
 981         stosb
 982 scm2:   inc     cl
 983         jns     scm1
 984         mov     ax,#0x0003      ! Return back to mode 3
 985         int     0x10
 986         ret
 987 
 988 tstidx: out     dx,ax           ! OUT DX,AX and inidx
 989 inidx:  out     dx,al           ! Read from indexed VGA register
 990         inc     dx              ! AL=index, DX=index reg port -> AL=data
 991         in      al,dx
 992         dec     dx
 993         ret
 994 
 995 !
 996 ! Try to detect type of SVGA card and supply (usually approximate) video
 997 ! mode table for it.
 998 !
 999 
1000 #ifdef CONFIG_VIDEO_SVGA
1001 
1002 svga_modes:
1003         lea     si,svga_table   ! Test all known SVGA adapters
1004 dosvga: lodsw
1005         mov     bp,ax           ! Default mode table
1006         or      ax,ax
1007         jz      didsv1
1008         lodsw                   ! Pointer to test routine
1009         push    si
1010         push    di
1011         push    es
1012         mov     bx,#0xc000
1013         mov     es,bx
1014         call    ax              ! Call test routine
1015         pop     es
1016         pop     di
1017         pop     si
1018         or      bp,bp
1019         jz      dosvga
1020         mov     si,bp           ! Found, copy the modes
1021         mov     ah,[svga_prefix]
1022 cpsvga: lodsb
1023         or      al,al
1024         jz      didsv
1025         stosw
1026         movsw
1027         jmp     cpsvga
1028 
1029 didsv:  mov     [card_name],si  ! Store pointer to card name
1030 didsv1: ret
1031 
1032 !
1033 ! Table of all known SVGA cards. For each card, we store a pointer to
1034 ! a table of video modes supported by the card and a pointer to a routine
1035 ! used for testing of presence of the card. The video mode table is always
1036 ! followed by the name of the card or the chipset.
1037 !
1038 
1039 svga_table:
1040         .word   ati_md, ati_test
1041         .word   oak_md, oak_test
1042         .word   paradise_md, paradise_test
1043         .word   realtek_md, realtek_test
1044         .word   s3_md, s3_test
1045         .word   chips_md, chips_test
1046         .word   video7_md, video7_test
1047         .word   cirrus5_md, cirrus5_test
1048         .word   cirrus6_md, cirrus6_test
1049         .word   cirrus1_md, cirrus1_test
1050         .word   ahead_md, ahead_test
1051         .word   everex_md, everex_test
1052         .word   genoa_md, genoa_test
1053         .word   trident_md, trident_test
1054         .word   tseng_md, tseng_test
1055         .word   0
1056 
1057 !
1058 ! Test routines and mode tables:
1059 !
1060 
1061 ! S3 - The test algorithm was taken from the SuperProbe package
1062 ! for XFree86 1.2.1. Report bugs to Christoph.Niemann@linux.org
1063 
1064 s3_test:
1065         mov     cx,#0x0f35      ! we store some constants in cl/ch
1066         mov     dx,#0x03d4
1067         movb    al,#0x38
1068         call    inidx
1069         mov     bh,al           ! store current value of CRT-register 0x38
1070         mov     ax,#0x0038
1071         call    outidx          ! disable writing to special regs
1072         movb    al,cl           ! check whether we can write special reg 0x35
1073         call    inidx
1074         movb    bl,al           ! save the current value of CRT reg 0x35
1075         andb    al,#0xf0        ! clear bits 0-3
1076         movb    ah,al
1077         movb    al,cl           ! and write it to CRT reg 0x35
1078         call    outidx
1079         call    inidx           ! now read it back
1080         andb    al,ch           ! clear the upper 4 bits
1081         jz      s3_2            ! the first test failed. But we have a
1082         movb    ah,bl           ! second chance
1083         mov     al,cl
1084         call    outidx
1085         jmp     s3_1            ! do the other tests
1086 s3_2:   mov     ax,cx           ! load ah with 0xf and al with 0x35
1087         orb     ah,bl           ! set the upper 4 bits of ah with the orig value
1088         call    outidx          ! write ...
1089         call    inidx           ! ... and reread 
1090         andb    al,cl           ! turn off the upper 4 bits
1091         push    ax
1092         movb    ah,bl           ! restore old value in register 0x35
1093         movb    al,cl
1094         call    outidx
1095         pop     ax
1096         cmp     al,ch           ! setting lower 4 bits was successful => bad
1097         je      no_s3           ! writing is allowed => this is not an S3
1098 s3_1:   mov     ax,#0x4838      ! allow writing to special regs by putting
1099         call    outidx          ! magic number into CRT-register 0x38
1100         movb    al,cl           ! check whether we can write special reg 0x35
1101         call    inidx
1102         movb    bl,al
1103         andb    al,#0xf0
1104         movb    ah,al
1105         movb    al,cl
1106         call    outidx
1107         call    inidx
1108         andb    al,ch
1109         jnz     no_s3           ! no, we can't write => no S3
1110         mov     ax,cx
1111         orb     ah,bl
1112         call    outidx
1113         call    inidx
1114         andb    al,ch
1115         push    ax
1116         movb    ah,bl           ! restore old value in register 0x35
1117         movb    al,cl
1118         call    outidx
1119         pop     ax
1120         cmp     al,ch
1121         jne     no_s31          ! writing not possible => no S3
1122         movb    al,#0x30
1123         call    inidx           ! now get the S3 id ...
1124         lea     di,idS3
1125         mov     cx,#0x10
1126         repne
1127         scasb
1128         je      no_s31
1129         movb    ah,bh
1130         movb    al,#0x38
1131         jmp     s3rest
1132 no_s3:  movb    al,#0x35        ! restore CRT register 0x35
1133         movb    ah,bl
1134         call    outidx
1135 no_s31: xor     bp,bp           ! Detection failed
1136 s3rest: movb    ah,bh
1137         movb    al,#0x38        ! restore old value of CRT register 0x38
1138         br      outidx
1139 
1140 idS3:   .byte   0x81, 0x82, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95
1141         .byte   0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa8, 0xb0
1142 
1143 s3_md:  .byte   0x54, 0x2b, 0x84
1144         .byte   0x55, 0x19, 0x84
1145         .byte   0
1146         .ascii  "S3"
1147         .byte   0
1148 
1149 ! ATI cards.
1150 
1151 ati_test:
1152         lea     si,idati
1153         mov     di,#0x31
1154         mov     cx,#0x09
1155         repe
1156         cmpsb
1157         je      atiok
1158         xor     bp,bp
1159 atiok:  ret
1160 
1161 idati:  .ascii  "761295520"
1162 
1163 ati_md: .byte   0x23, 0x19, 0x84
1164         .byte   0x33, 0x2c, 0x84
1165         .byte   0x22, 0x1e, 0x64
1166         .byte   0x21, 0x19, 0x64
1167         .byte   0x58, 0x21, 0x50
1168         .byte   0x5b, 0x1e, 0x50
1169         .byte   0
1170         .ascii  "ATI"
1171         .byte   0
1172 
1173 ! AHEAD
1174 
1175 ahead_test:
1176         mov     ax,#0x200f
1177         mov     dx,#0x3ce
1178         out     dx,ax
1179         inc     dx
1180         in      al,dx
1181         cmp     al,#0x20
1182         je      isahed
1183         cmp     al,#0x21
1184         je      isahed
1185         xor     bp,bp
1186 isahed: ret
1187 
1188 ahead_md:
1189         .byte   0x22, 0x2c, 0x84
1190         .byte   0x23, 0x19, 0x84
1191         .byte   0x24, 0x1c, 0x84
1192         .byte   0x2f, 0x32, 0xa0
1193         .byte   0x32, 0x22, 0x50
1194         .byte   0x34, 0x42, 0x50
1195         .byte   0
1196         .ascii  "Ahead"
1197         .byte   0
1198 
1199 ! Chips & Tech.
1200 
1201 chips_test:
1202         mov     dx,#0x3c3
1203         in      al,dx
1204         or      al,#0x10
1205         out     dx,al
1206         mov     dx,#0x104               
1207         in      al,dx
1208         mov     bl,al
1209         mov     dx,#0x3c3
1210         in      al,dx
1211         and     al,#0xef
1212         out     dx,al
1213         cmp     bl,#0xa5
1214         je      cantok
1215         xor     bp,bp
1216 cantok: ret
1217 
1218 chips_md:
1219         .byte   0x60, 0x19, 0x84
1220         .byte   0x61, 0x32, 0x84
1221         .byte   0
1222         .ascii  "Chips & Technologies"
1223         .byte   0
1224 
1225 ! Cirrus Logic 5X0
1226 
1227 cirrus1_test:
1228         mov     dx,#0x3d4
1229         mov     al,#0x0c
1230         out     dx,al
1231         inc     dx
1232         in      al,dx
1233         mov     bl,al
1234         xor     al,al
1235         out     dx,al
1236         dec     dx
1237         mov     al,#0x1f
1238         out     dx,al
1239         inc     dx
1240         in      al,dx
1241         mov     bh,al
1242         xor     ah,ah
1243         shl     al,#4
1244         mov     cx,ax
1245         mov     al,bh
1246         shr     al,#4
1247         add     cx,ax
1248         shl     cx,#8
1249         add     cx,#6
1250         mov     ax,cx
1251         mov     dx,#0x3c4
1252         out     dx,ax
1253         inc     dx
1254         in      al,dx
1255         and     al,al
1256         jnz     nocirr
1257         mov     al,bh
1258         out     dx,al
1259         in      al,dx
1260         cmp     al,#0x01
1261         je      iscirr
1262 nocirr: xor     bp,bp
1263 iscirr: mov     dx,#0x3d4
1264         mov     al,bl
1265         xor     ah,ah
1266         shl     ax,#8
1267         add     ax,#0x0c
1268         out     dx,ax
1269         ret
1270 
1271 cirrus1_md:
1272         .byte   0x1f, 0x19, 0x84
1273         .byte   0x20, 0x2c, 0x84
1274         .byte   0x22, 0x1e, 0x84
1275         .byte   0x31, 0x25, 0x64
1276         .byte   0
1277         .ascii  "Cirrus Logic 5X0"
1278         .byte   0
1279 
1280 ! Cirrus Logic 54XX
1281 
1282 cirrus5_test:
1283         mov     dx,#0x3c4
1284         mov     al,#6
1285         call    inidx
1286         mov     bl,al                   ! BL=backup
1287         mov     ax,#6
1288         call    tstidx
1289         cmp     al,#0x0f
1290         jne     c5fail
1291         mov     ax,#0x1206
1292         call    tstidx
1293         cmp     al,#0x12
1294         jne     c5fail
1295         mov     al,#0x1e
1296         call    inidx
1297         mov     bh,al
1298         mov     ah,bh
1299         and     ah,#0xc0
1300         mov     al,#0x1e
1301         call    tstidx
1302         and     al,#0x3f
1303         jne     c5xx
1304         mov     al,#0x1e
1305         mov     ah,bh
1306         or      ah,#0x3f
1307         call    tstidx
1308         xor     al,#0x3f
1309         and     al,#0x3f
1310 c5xx:   pushf
1311         mov     al,#0x1e
1312         mov     ah,bh
1313         out     dx,ax
1314         popf
1315         je      c5done
1316 c5fail: xor     bp,bp
1317 c5done: mov     al,#6
1318         mov     ah,bl
1319         out     dx,ax
1320         ret
1321 
1322 cirrus5_md:
1323         .byte   0x14, 0x19, 0x84
1324         .byte   0x54, 0x2b, 0x84
1325         .byte   0
1326         .ascii  "Cirrus Logic 54XX"
1327         .byte   0
1328 
1329 ! Cirrus Logic 64XX -- no known extra modes, but must be identified, because
1330 ! it's misidentified by the Ahead test.
1331 
1332 cirrus6_test:
1333         mov     dx,#0x3ce
1334         mov     al,#0x0a
1335         call    inidx
1336         mov     bl,al                   ! BL=backup
1337         mov     ax,#0xce0a
1338         call    tstidx
1339         or      al,al
1340         jne     c2fail
1341         mov     ax,#0xec0a
1342         call    tstidx
1343         cmp     al,#0x01
1344         jne     c2fail
1345         mov     al,#0xaa
1346         call    inidx   ! 4X, 5X, 7X and 8X are valid 64XX chip ID's
1347         shr     al,#4
1348         sub     al,#4
1349         jz      c6done
1350         dec     al
1351         jz      c6done
1352         sub     al,#2
1353         jz      c6done
1354         dec     al
1355         jz      c6done
1356 c2fail: xor     bp,bp
1357 c6done: mov     al,#0x0a
1358         mov     ah,bl
1359         out     dx,ax
1360         ret
1361 
1362 cirrus6_md:
1363         .byte   0
1364         .ascii  "Cirrus Logic 64XX"
1365         .byte   0
1366 
1367 ! Everex / Trident
1368 
1369 everex_test:
1370         mov     ax,#0x7000
1371         xor     bx,bx
1372         int     0x10
1373         cmp     al,#0x70
1374         jne     noevrx
1375         shr     dx,#4
1376         cmp     dx,#0x678
1377         je      evtrid
1378         cmp     dx,#0x236
1379         jne     evrxok
1380 evtrid: lea     bp,trident_md
1381 evrxok: ret
1382 
1383 noevrx: xor     bp,bp
1384         ret
1385 
1386 everex_md:
1387         .byte   0x03, 0x22, 0x50
1388         .byte   0x04, 0x3c, 0x50
1389         .byte   0x07, 0x2b, 0x64
1390         .byte   0x08, 0x4b, 0x64
1391         .byte   0x0a, 0x19, 0x84
1392         .byte   0x0b, 0x2c, 0x84
1393         .byte   0x16, 0x1e, 0x50
1394         .byte   0x18, 0x1b, 0x64
1395         .byte   0x21, 0x40, 0xa0
1396         .byte   0x40, 0x1e, 0x84
1397         .byte   0
1398         .ascii  "Everex/Trident"
1399         .byte   0
1400 
1401 ! Genoa.
1402 
1403 genoa_test:
1404         lea     si,idgenoa              ! Check Genoa 'clues'
1405         xor     ax,ax
1406         seg es
1407         mov     al,[0x37]
1408         mov     di,ax
1409         mov     cx,#0x04
1410         dec     si
1411         dec     di
1412 l1:     inc     si
1413         inc     di
1414         mov     al,(si)
1415         test    al,al
1416         jz      l2
1417         seg es
1418         cmp     al,(di)
1419 l2:     loope   l1
1420         or      cx,cx
1421         je      isgen
1422         xor     bp,bp
1423 isgen:  ret
1424 
1425 idgenoa: .byte  0x77, 0x00, 0x99, 0x66
1426 
1427 genoa_md:
1428         .byte   0x58, 0x20, 0x50
1429         .byte   0x5a, 0x2a, 0x64
1430         .byte   0x60, 0x19, 0x84
1431         .byte   0x61, 0x1d, 0x84
1432         .byte   0x62, 0x20, 0x84
1433         .byte   0x63, 0x2c, 0x84
1434         .byte   0x64, 0x3c, 0x84
1435         .byte   0x6b, 0x4f, 0x64
1436         .byte   0x72, 0x3c, 0x50
1437         .byte   0x74, 0x42, 0x50
1438         .byte   0x78, 0x4b, 0x64
1439         .byte   0
1440         .ascii  "Genoa"
1441         .byte   0
1442 
1443 ! OAK
1444 
1445 oak_test:
1446         lea     si,idoakvga
1447         mov     di,#0x08
1448         mov     cx,#0x08
1449         repe
1450         cmpsb
1451         je      isoak
1452         xor     bp,bp
1453 isoak:  ret
1454 
1455 idoakvga: .ascii  "OAK VGA "
1456 
1457 oak_md: .byte   0x4e, 0x3c, 0x50
1458         .byte   0x4f, 0x3c, 0x84
1459         .byte   0x50, 0x19, 0x84
1460         .byte   0x51, 0x2b, 0x84
1461         .byte   0
1462         .ascii  "OAK"
1463         .byte   0
1464 
1465 ! WD Paradise.
1466 
1467 paradise_test:
1468         lea     si,idparadise
1469         mov     di,#0x7d
1470         mov     cx,#0x04
1471         repe
1472         cmpsb
1473         je      ispara
1474         xor     bp,bp
1475 ispara: ret
1476 
1477 idparadise:     .ascii  "VGA="
1478 
1479 paradise_md:
1480         .byte   0x41, 0x22, 0x50
1481         .byte   0x47, 0x1c, 0x84
1482         .byte   0x55, 0x19, 0x84
1483         .byte   0x54, 0x2c, 0x84
1484         .byte   0
1485         .ascii  "Paradise"
1486         .byte   0
1487 
1488 ! Trident.
1489 
1490 trident_test:
1491         mov     dx,#0x3c4
1492         mov     al,#0x0e
1493         out     dx,al
1494         inc     dx
1495         in      al,dx
1496         xchg    ah,al
1497         xor     al,al
1498         out     dx,al
1499         in      al,dx
1500         xchg    al,ah
1501         mov     bl,al           ! Strange thing ... in the book this wasn't
1502         and     bl,#0x02        ! necessary but it worked on my card which
1503         jz      setb2           ! is a trident. Without it the screen goes
1504         and     al,#0xfd        ! blurred ...
1505         jmp     clrb2           !
1506 setb2:  or      al,#0x02        !
1507 clrb2:  out     dx,al
1508         and     ah,#0x0f
1509         cmp     ah,#0x02
1510         je      istrid
1511         xor     bp,bp
1512 istrid: ret
1513 
1514 trident_md:
1515         .byte   0x50, 0x1e, 0x50
1516         .byte   0x51, 0x2b, 0x50
1517         .byte   0x52, 0x3c, 0x50
1518         .byte   0x57, 0x19, 0x84
1519         .byte   0x58, 0x1e, 0x84
1520         .byte   0x59, 0x2b, 0x84
1521         .byte   0x5a, 0x3c, 0x84
1522         .byte   0
1523         .ascii  "Trident"
1524         .byte   0
1525 
1526 ! Tseng.
1527 
1528 tseng_test:
1529         mov     dx,#0x3cd
1530         in      al,dx                   ! Could things be this simple ! :-)
1531         mov     bl,al
1532         mov     al,#0x55
1533         out     dx,al
1534         in      al,dx
1535         mov     ah,al
1536         mov     al,bl
1537         out     dx,al
1538         cmp     ah,#0x55
1539         je      istsen
1540 isnot:  xor     bp,bp
1541 istsen: ret
1542 
1543 tseng_md:
1544         .byte   0x26, 0x3c, 0x50
1545         .byte   0x2a, 0x28, 0x64
1546         .byte   0x23, 0x19, 0x84
1547         .byte   0x24, 0x1c, 0x84
1548         .byte   0x22, 0x2c, 0x84
1549         .byte   0x21, 0x3c, 0x84
1550         .byte   0
1551         .ascii  "Tseng"
1552         .byte   0
1553 
1554 ! Video7.
1555 
1556 video7_test:
1557         mov     dx,#0x3cc
1558         in      al,dx
1559         mov     dx,#0x3b4
1560         and     al,#0x01
1561         jz      even7
1562         mov     dx,#0x3d4
1563 even7:  mov     al,#0x0c
1564         out     dx,al
1565         inc     dx
1566         in      al,dx
1567         mov     bl,al
1568         mov     al,#0x55
1569         out     dx,al
1570         in      al,dx
1571         dec     dx
1572         mov     al,#0x1f
1573         out     dx,al
1574         inc     dx
1575         in      al,dx
1576         mov     bh,al
1577         dec     dx
1578         mov     al,#0x0c
1579         out     dx,al
1580         inc     dx
1581         mov     al,bl
1582         out     dx,al
1583         mov     al,#0x55
1584         xor     al,#0xea
1585         cmp     al,bh
1586         jne     isnot
1587         movb    [svga_prefix],#VIDEO_FIRST_V7>>8        ! Use special mode switching
1588         ret
1589 
1590 video7_md:
1591         .byte   0x40, 0x2b, 0x50
1592         .byte   0x43, 0x3c, 0x50
1593         .byte   0x44, 0x3c, 0x64
1594         .byte   0x41, 0x19, 0x84
1595         .byte   0x42, 0x2c, 0x84
1596         .byte   0x45, 0x1c, 0x84
1597         .byte   0
1598         .ascii  "Video 7"
1599         .byte   0
1600 
1601 ! Realtek VGA
1602 
1603 realtek_test:
1604         lea     si,idrtvga
1605         mov     di,#0x45
1606         mov     cx,#0x0b
1607         repe
1608         cmpsb
1609         je      isrt
1610         xor     bp,bp
1611 isrt:   ret
1612 
1613 idrtvga:        .ascii  "REALTEK VGA"
1614 
1615 realtek_md:
1616         .byte   0x1a, 0x3c, 0x50
1617         .byte   0x1b, 0x19, 0x84
1618         .byte   0x1c, 0x1e, 0x84
1619         .byte   0x1d, 0x2b, 0x84
1620         .byte   0x1e, 0x3c, 0x84
1621         .byte   0
1622         .ascii  "REALTEK"
1623         .byte   0
1624 
1625 #endif  /* CONFIG_VIDEO_SVGA */
1626 
1627 !
1628 ! User-defined local mode table (VGA only)
1629 !
1630 
1631 #ifdef CONFIG_VIDEO_LOCAL
1632 
1633 local_modes:
1634         lea     si,local_mode_table
1635 locm1:  lodsw
1636         or      ax,ax
1637         jz      locm2
1638         stosw
1639         movsw
1640         jmp     locm1
1641 locm2:  ret
1642 
1643 ! This is the table of local video modes which can be supplied manually
1644 ! by the user. Each entry consists of mode ID (word) and dimensions
1645 ! (byte for column count and another byte for row count). These modes
1646 ! are placed before all SVGA and VESA modes and override them if table
1647 ! compacting is enabled. The table must end with a zero word followed
1648 ! by NUL-terminated video adapter name.
1649 
1650 local_mode_table:
1651         .word   0x0100          ! Example: 40x25
1652         .byte   25,40
1653         .word   0
1654         .ascii  "Local"
1655         .byte   0
1656 
1657 #endif  /* CONFIG_VIDEO_LOCAL */
1658 
1659 !
1660 ! Read a key and return the ASCII code in al, scan code in ah
1661 !
1662 
1663 getkey: xor     ah,ah
1664         int     0x16
1665         ret
1666 
1667 !
1668 ! Read a key with a timeout of 30 seconds. The hardware clock is used to get
1669 ! the time.
1670 !
1671 
1672 getkt:  call    gettime
1673         add     al,#30          ! Wait 30 seconds
1674         cmp     al,#60
1675         jl      lminute
1676         sub     al,#60
1677 lminute:
1678         mov     cl,al
1679 again:  mov     ah,#0x01
1680         int     0x16
1681         jnz     getkey          ! key pressed, so get it
1682         call    gettime
1683         cmp     al,cl
1684         jne     again
1685         mov     al,#0x20        ! timeout, return default char `space'
1686         ret
1687 
1688 !
1689 ! Flush the keyboard buffer
1690 !
1691 
1692 flush:  mov     ah,#0x01
1693         int     0x16
1694         jz      empty
1695         xor     ah,ah
1696         int     0x16
1697         jmp     flush
1698 empty:  ret
1699 
1700 !
1701 ! Print hexadecimal number.
1702 !
1703 
1704 prthw:  push    ax
1705         mov     al,ah
1706         call    prthb
1707         pop     ax
1708 prthb:  push    ax
1709         shr     al,#4
1710         call    prthn
1711         pop     ax
1712         and     al,#0x0f
1713 prthn:  cmp     al,#0x0a
1714         jc      prth1
1715         add     al,#0x07
1716 prth1:  add     al,#0x30
1717         br      prtchr
1718 
1719 !
1720 ! Print decimal number (AL).
1721 !
1722 
1723 prtdec: push    ax
1724         push    cx
1725         xor     ah,ah           ! Clear ah
1726         mov     cl,#0x0a
1727         idiv    cl
1728         cmp     al,#0x09
1729         jbe     lt100
1730         call    prtdec
1731         jmp     skip10
1732 lt100:  add     al,#0x30
1733         call    prtchr
1734 skip10: mov     al,ah
1735         add     al,#0x30
1736         call    prtchr  
1737         pop     cx
1738         pop     ax
1739         ret
1740 
1741 ! Variables:
1742 
1743 adapter:        .byte   0       ! Video adapter: 0=CGA/MDA/HGA,1=EGA,2=VGA
1744 mt_end:         .word   0       ! End of video mode table if built
1745 edit_buf:       .space  6       ! Line editor buffer
1746 card_name:      .word   0       ! Pointer to adapter name
1747 scanning:       .byte   0       ! Performing mode scan
1748 do_restore:     .byte   0       ! Screen contents altered during mode change
1749 svga_prefix:    .byte   VIDEO_FIRST_BIOS>>8     ! Default prefix for BIOS modes
1750 video_segment:  .word   0xb800  ! Video memory segment
1751 force_size:     .word   0       ! Use this size instead of the one in BIOS vars
1752 
1753 ! Messages:
1754 
1755 keymsg:         .ascii  "Press <RETURN> to see video modes available, "
1756                 .ascii  "<SPACE> to continue or wait 30 secs"
1757                 db      0x0d, 0x0a, 0
1758 listhdr:        db      0x0d, 0x0a
1759                 .ascii  "Mode:    COLSxROWS:"
1760 crlft:          db      0x0d, 0x0a, 0
1761 prompt:         db      0x0d, 0x0a
1762                 .ascii  "Enter mode number: "
1763                 db      0
1764 unknt:          .ascii  "Unknown mode ID. Try again."
1765                 db      0
1766 badmdt:         .ascii  "You passed an undefined mode number to setup."
1767                 db      0x0d, 0x0a, 0
1768 vesaer:         .ascii  "Error: Scanning of VESA modes failed. Please "
1769                 .ascii  "report to <mj@k332.feld.cvut.cz>."
1770                 db      0x0d, 0x0a, 0
1771 old_name:       .ascii  "CGA/MDA/HGA"
1772                 db      0
1773 ega_name:       .ascii  "EGA"
1774                 db      0
1775 svga_name:      .ascii  " "
1776 vga_name:       .ascii  "VGA"
1777                 db      0
1778 vesa_name:      .ascii  "VESA"
1779                 db      0
1780 name_bann:      .ascii  "Video adapter: "
1781                 db      0

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