root/arch/i386/boot/setup.S

/* [previous][next][first][last][top][bottom][index][help] */
   1 !
   2 !       setup.S         Copyright (C) 1991, 1992 Linus Torvalds
   3 !
   4 ! This code performs all initialization procedures that should be done
   5 ! before entering the protected mode. It's responsible for getting of all
   6 ! system data offered by BIOS and for detection / selection of video
   7 ! mode. All information is put in a "safe" place: 0x90000-0x901FF, i. e.
   8 ! where the boot-block used to be.  It is then up to the protected mode
   9 ! system to read them from there before the area is overwritten
  10 ! for buffer-blocks.
  11 !
  12 ! Move PS/2 aux init code to psaux.c
  13 ! (troyer@saifr00.cfsat.Honeywell.COM) 03Oct92
  14 !
  15 ! Some changes and additional features by Christoph Niemann,
  16 ! March 1993/June 1994 (Christoph.Niemann@linux.org)
  17 !
  18 ! Completely new video-mode handling code, VESA mode detection, support
  19 ! for new Cirrus Logic cards and some additional changes
  20 ! by Martin Mares <mj@k332.feld.cvut.cz>, October 1995.
  21 !
  22 
  23 ! NOTE! These had better be the same as in bootsect.S!
  24 #define __ASSEMBLY__
  25 #include <linux/config.h>
  26 #include <asm/segment.h>
  27 
  28 ! Uncomment this if you want the BIOS mode numbers to be listed
  29 !#define SHOW_BIOS_MODES
  30 
  31 ! Signature words to ensure LILO loaded us right
  32 #define SIG1    0xAA55
  33 #define SIG2    0x5A5A
  34 
  35 INITSEG  = DEF_INITSEG  ! we move boot here - out of the way
  36 SYSSEG   = DEF_SYSSEG   ! system loaded at 0x10000 (65536).
  37 SETUPSEG = DEF_SETUPSEG ! this is the current segment
  38 
  39 .globl begtext, begdata, begbss, endtext, enddata, endbss
  40 .text
  41 begtext:
  42 .data
  43 begdata:
  44 .bss
  45 begbss:
  46 .text
  47 
  48 entry start
  49 start:
  50 
  51 ! Bootlin depends on this being done early
  52         mov     ax,#0x01500
  53         mov     dl,#0x81
  54         int     0x13
  55 
  56 ! Check signature at end of setup
  57         mov     ax,#SETUPSEG
  58         mov     ds,ax
  59         cmp     setup_sig1,#SIG1
  60         jne     bad_sig
  61         cmp     setup_sig2,#SIG2
  62         jne     bad_sig
  63         jmp     good_sig1
  64 
  65 ! Routine to print asciiz-string at DS:SI
  66 
  67 prtstr: lodsb
  68         and     al,al
  69         jz      fin
  70         call    prnt1
  71         jmp     prtstr
  72 fin:    ret
  73 
  74 ! Part of above routine, this one just prints ascii al
  75 
  76 prnt1:  push    ax
  77         push    bx
  78         push    cx
  79         xor     bh,bh
  80         mov     cx,#0x01
  81         mov     ah,#0x0e
  82         int     0x10
  83         pop     cx
  84         pop     bx
  85         pop     ax
  86         ret
  87 
  88 beep:   mov     al,#0x07
  89         jmp     prnt1
  90         
  91 no_sig_mess:    .ascii  "No setup signature found ..."
  92                 db      0x00
  93 start_sys_seg:  .word   SYSSEG
  94 
  95 good_sig1:
  96         jmp     good_sig
  97 
  98 ! We now have to find the rest of the setup code/data
  99 bad_sig:
 100         mov     ax,#INITSEG
 101         mov     ds,ax
 102         xor     bh,bh
 103         mov     bl,[497]        ! get setup sects from boot sector
 104         sub     bx,#4           ! LILO loads 4 sectors of setup
 105         shl     bx,#8           ! convert to words
 106         mov     cx,bx
 107         shr     bx,#3           ! convert to segment
 108         add     bx,#SYSSEG
 109         seg cs
 110         mov     start_sys_seg,bx
 111 
 112 ! Move rest of setup code/data to here
 113         mov     di,#2048        ! four sectors loaded by LILO
 114         sub     si,si
 115         mov     ax,#SETUPSEG
 116         mov     es,ax
 117         mov     ax,#SYSSEG
 118         mov     ds,ax
 119         rep
 120         movsw
 121 
 122         mov     ax,#SETUPSEG
 123         mov     ds,ax
 124         cmp     setup_sig1,#SIG1
 125         jne     no_sig
 126         cmp     setup_sig2,#SIG2
 127         jne     no_sig
 128         jmp     good_sig
 129 
 130 no_sig:
 131         lea     si,no_sig_mess
 132         call    prtstr
 133 no_sig_loop:
 134         jmp     no_sig_loop
 135 
 136 good_sig:
 137         mov     ax,#INITSEG
 138         mov     ds,ax
 139 
 140 ! Get memory size (extended mem, kB)
 141 
 142         mov     ah,#0x88
 143         int     0x15
 144         mov     [2],ax
 145 
 146 ! set the keyboard repeat rate to the max
 147 
 148         mov     ax,#0x0305
 149         xor     bx,bx           ! clear bx
 150         int     0x16
 151 
 152 ! Check for video adapter and its parameters
 153 ! Video mode selection is also handled here
 154 
 155         call    video
 156 
 157 ! Get hd0 data
 158 
 159         xor     ax,ax           ! clear ax
 160         mov     ds,ax
 161         lds     si,[4*0x41]
 162         mov     ax,#INITSEG
 163         push    ax
 164         mov     es,ax
 165         mov     di,#0x0080
 166         mov     cx,#0x10
 167         push    cx
 168         cld
 169         rep
 170         movsb
 171 
 172 ! Get hd1 data
 173 
 174         xor     ax,ax           ! clear ax
 175         mov     ds,ax
 176         lds     si,[4*0x46]
 177         pop     cx
 178         pop     es
 179         mov     di,#0x0090
 180         rep
 181         movsb
 182 
 183 ! Check that there IS a hd1 :-)
 184 
 185         mov     ax,#0x01500
 186         mov     dl,#0x81
 187         int     0x13
 188         jc      no_disk1
 189         cmp     ah,#3
 190         je      is_disk1
 191 no_disk1:
 192         mov     ax,#INITSEG
 193         mov     es,ax
 194         mov     di,#0x0090
 195         mov     cx,#0x10
 196         xor     ax,ax           ! clear ax
 197         cld
 198         rep
 199         stosb
 200 is_disk1:
 201 
 202 ! check for PS/2 pointing device
 203 
 204         mov     ax,#INITSEG
 205         mov     ds,ax
 206         mov     [0x1ff],#0      ! default is no pointing device
 207         int     0x11            ! int 0x11: equipment determination
 208         test    al,#0x04        ! check if pointing device installed
 209         jz      no_psmouse
 210         mov     [0x1ff],#0xaa   ! device present
 211 no_psmouse:
 212 ! now we want to move to protected mode ...
 213 
 214         cli                     ! no interrupts allowed !
 215         mov     al,#0x80        ! disable NMI for the bootup sequence
 216         out     #0x70,al
 217 
 218 ! first we move the system to its rightful place
 219 
 220         mov     ax,#0x100       ! start of destination segment
 221         seg cs
 222         mov     bx,start_sys_seg        ! start of source segment
 223         cld                     ! 'direction'=0, movs moves forward
 224 do_move:
 225         mov     es,ax           ! destination segment
 226         inc     ah              ! instead of add ax,#0x100
 227         cmp     ax,#0x9000
 228         jz      end_move
 229         mov     ds,bx           ! source segment
 230         add     bx,#0x100
 231         sub     di,di
 232         sub     si,si
 233         mov     cx,#0x800
 234         rep
 235         movsw
 236         jmp     do_move
 237 
 238 ! then we load the segment descriptors
 239 
 240 end_move:
 241         mov     ax,#SETUPSEG    ! right, forgot this at first. didn't work :-)
 242         mov     ds,ax
 243         lidt    idt_48          ! load idt with 0,0
 244         lgdt    gdt_48          ! load gdt with whatever appropriate
 245 
 246 ! that was painless, now we enable A20
 247 
 248         call    empty_8042
 249         mov     al,#0xD1                ! command write
 250         out     #0x64,al
 251         call    empty_8042
 252         mov     al,#0xDF                ! A20 on
 253         out     #0x60,al
 254         call    empty_8042
 255 
 256 ! make sure any possible coprocessor is properly reset..
 257 
 258         xor     ax,ax
 259         out     #0xf0,al
 260         call    delay
 261         out     #0xf1,al
 262         call    delay
 263 
 264 ! well, that went ok, I hope. Now we have to reprogram the interrupts :-(
 265 ! we put them right after the intel-reserved hardware interrupts, at
 266 ! int 0x20-0x2F. There they won't mess up anything. Sadly IBM really
 267 ! messed this up with the original PC, and they haven't been able to
 268 ! rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f,
 269 ! which is used for the internal hardware interrupts as well. We just
 270 ! have to reprogram the 8259's, and it isn't fun.
 271 
 272         mov     al,#0x11                ! initialization sequence
 273         out     #0x20,al                ! send it to 8259A-1
 274         call    delay
 275         out     #0xA0,al                ! and to 8259A-2
 276         call    delay
 277         mov     al,#0x20                ! start of hardware int's (0x20)
 278         out     #0x21,al
 279         call    delay
 280         mov     al,#0x28                ! start of hardware int's 2 (0x28)
 281         out     #0xA1,al
 282         call    delay
 283         mov     al,#0x04                ! 8259-1 is master
 284         out     #0x21,al
 285         call    delay
 286         mov     al,#0x02                ! 8259-2 is slave
 287         out     #0xA1,al
 288         call    delay
 289         mov     al,#0x01                ! 8086 mode for both
 290         out     #0x21,al
 291         call    delay
 292         out     #0xA1,al
 293         call    delay
 294         mov     al,#0xFF                ! mask off all interrupts for now
 295         out     #0xA1,al
 296         call    delay
 297         mov     al,#0xFB                ! mask all irq's but irq2 which
 298         out     #0x21,al                ! is cascaded
 299 
 300 ! well, that certainly wasn't fun :-(. Hopefully it works, and we don't
 301 ! need no steenking BIOS anyway (except for the initial loading :-).
 302 ! The BIOS-routine wants lots of unnecessary data, and it's less
 303 ! "interesting" anyway. This is how REAL programmers do it.
 304 !
 305 ! Well, now's the time to actually move into protected mode. To make
 306 ! things as simple as possible, we do no register set-up or anything,
 307 ! we let the gnu-compiled 32-bit programs do that. We just jump to
 308 ! absolute address 0x10000, in 32-bit protected mode.
 309 !
 310 ! Note that the short jump isn't strictly needed, although there are
 311 ! reasons why it might be a good idea. It won't hurt in any case.
 312 !
 313         mov     ax,#1           ! protected mode (PE) bit
 314         lmsw    ax              ! This is it!
 315         jmp     flush_instr
 316 flush_instr:
 317         xor     bx,bx           ! Flag to indicate a boot
 318         jmpi    0x1000,KERNEL_CS        ! jmp offset 1000 of segment 0x10 (cs)
 319 
 320 ! This routine checks that the keyboard command queue is empty
 321 ! (after emptying the output buffers)
 322 !
 323 ! No timeout is used - if this hangs there is something wrong with
 324 ! the machine, and we probably couldn't proceed anyway.
 325 empty_8042:
 326         call    delay
 327         in      al,#0x64        ! 8042 status port
 328         test    al,#1           ! output buffer?
 329         jz      no_output
 330         call    delay
 331         in      al,#0x60        ! read it
 332         jmp     empty_8042
 333 no_output:
 334         test    al,#2           ! is input buffer full?
 335         jnz     empty_8042      ! yes - loop
 336         ret
 337 
 338 !
 339 ! Delay is needed after doing i/o
 340 !
 341 delay:
 342         .word   0x00eb                  ! jmp $+2
 343         ret
 344 
 345 !
 346 ! Video card / mode detection. We do some hardware testing and build
 347 ! a video mode list (placed directly after our code and data). Then we
 348 ! choose the right mode given in the configuration or ask the user if
 349 ! we are requested to do so. After all, all video parameters are stored
 350 ! for later perusal by the kernel.
 351 !
 352 
 353 video:  movb    [15],#0         ! Default is no VGA
 354         mov     ax,[0x01fa]
 355         push    ds
 356         push    ds
 357         pop     fs              ! In this routine: FS=orig. DS
 358         push    cs
 359         pop     ds              ! ES=DS=CS
 360         push    cs
 361         pop     es
 362         mov     modesave,ax
 363         lea     di,modelist     ! ES:DI points to current item in our mode list
 364         mov     eax,#0x50190000 ! Store current mode: 80x25
 365         cld
 366         stosd
 367 
 368         mov     ah,#0x12        ! Check EGA/VGA
 369         mov     bl,#0x10
 370         int     0x10
 371         seg     fs
 372         mov     [10],bx         ! Used for identification of VGA in the kernel
 373         cmp     bl,#0x10        ! Not EGA nor VGA -> 80x25 only
 374         je      selmd1
 375 
 376         mov     eax,#0x5032FFFF ! EGA or VGA: 80x50 supported
 377         stosd
 378 
 379         mov     ax,#0x1a00      ! Added check for EGA/VGA discrimination
 380         int     0x10
 381         cmp     al,#0x1a        ! 1a means VGA, anything else EGA
 382         jne     selmd1
 383         seg     fs
 384         movb    [15],#1         ! We've detected a VGA
 385 
 386         mov     eax,#0x501cFFFE ! VGA: 80x28 supported
 387         stosd
 388 
 389         lea     si,vgatable     ! Test all known SVGA adapters
 390 dosvga: lodsw
 391         mov     bp,ax           ! Default mode table
 392         or      ax,ax
 393         jz      didsv
 394         lodsw                   ! Pointer to test routine
 395         push    si
 396         push    di
 397         push    es
 398         mov     bx,#0xc000
 399         mov     es,bx
 400         call    ax              ! Call test routine
 401         pop     es
 402         pop     di
 403         pop     si
 404         or      bp,bp
 405         jz      dosvga
 406         mov     si,bp           ! Found, copy the modes
 407         mov     ah,#0
 408 cpsvga: lodsb
 409         or      al,al
 410         jz      didsv
 411         stosw
 412         movsw
 413         jmp     cpsvga
 414 
 415 selmd1: jmp     selmd
 416 
 417 didsv:  mov     ax,#0x4f00      ! Fetch VESA information to ES:DI+0x400
 418         add     di,#0x400
 419         int     0x10
 420         sub     di,#0x400
 421         cmp     al,#0x4f
 422         jne     selmd
 423         lgs     bx,(di+0x40e)
 424         cmp     (di+0x400),#0x4556
 425         jne     selmd
 426         cmp     (di+0x402),#0x4153
 427         jne     selmd
 428 
 429 vesa1:  seg     gs
 430         mov     cx,(bx)
 431         add     bx,#2
 432         cmp     cx,#0xffff
 433         je      selmd
 434         mov     ax,#0x4f01
 435         add     di,#0xc00
 436         int     0x10
 437         sub     di,#0xc00
 438         cmp     al,#0x4f
 439         jne     selmd
 440         testb   (di+0xc00),#0x10        ! Is it a text mode?
 441         jne     vesa1
 442         testb   (di+0xc00),#0x08        ! Has it colors?
 443         je      vesa1
 444         mov     dh,(di+0xc12)   ! DX=dimensions, CX=mode
 445         mov     dl,(di+0xc14)
 446 
 447         lea     si,modelist     ! Check if it's already on the list
 448 vesa2:  lodsw
 449         lodsw
 450         cmp     ax,dx
 451         je      vesa1
 452         cmp     si,di
 453         jc      vesa2
 454 
 455         mov     ax,cx           ! New mode, store it
 456         stosw
 457         mov     ax,dx
 458         stosw
 459         jmp     vesa1
 460 
 461 !
 462 ! Video mode table built. Determine the mode we should use and set it.
 463 !
 464 selmd:  mov     ax,modesave
 465         cmp     ax,#NORMAL_VGA  ! Current mode (80x25)
 466         je      defmd1
 467         cmp     ax,#EXTENDED_VGA ! 80x50 mode
 468         je      try50
 469         cmp     ax,#ASK_VGA
 470         jne     usemd
 471 banner: lea     si,keymsg
 472         call    prtstr
 473         call    flush
 474 nokey:  call    getkt
 475         cmp     al,#0x0d        ! ENTER ?
 476         je      listm           ! yes - manual mode selection
 477         cmp     al,#0x20        ! SPACE ?
 478         je      defmd1          ! no - repeat
 479         call    beep
 480         jmp     nokey
 481 
 482 defmd1: br      defmd
 483 
 484 listm:  call    listmodes       ! List all available modes
 485 keymd:  call    getkey          ! Get key representing mode ID
 486         xor     ah,ah
 487         sub     al,#0x30
 488         jc      keymd
 489         cmp     al,#10
 490         jc      usemd
 491         sub     al,#39
 492         cmp     al,#10
 493         jc      keymd
 494         cmp     al,#26
 495         jnc     keymd
 496         jmp     usemd
 497 
 498 try50:  mov     ax,#1           ! 80x50 is mode #1
 499 usemd:  shl     ax,#2           ! We're requested to set mode in AX
 500         lea     si,modelist
 501         add     si,ax
 502         cmp     si,di
 503         jc      mdok
 504         cmp     modesave,#ASK_VGA
 505         je      keymd
 506         lea     si,undefd
 507         call    prtstr
 508         jmp     banner
 509 
 510 mdok:   lodsw                   ! AX=mode number
 511         cmp     ah,#0xff
 512         jz      mdspec
 513         or      ax,ax
 514         jz      mdsetd
 515         or      ah,ah
 516         jz      mdset
 517         mov     bx,ax
 518         mov     ax,#0x4f02
 519 mdset:  int     0x10
 520 mdsetd: lodsb                   ! AL=number of lines
 521         jmp     getpar
 522 
 523 mdspec: inc     ax              ! Special modes
 524         jz      m80x50
 525 
 526 m80x28: mov     ax,#0x1111      ! Setting 80x28 (VGA with EGA font)
 527         xor     bl,bl
 528         int     0x10            ! use 9x14 fontset (28 lines on VGA)
 529         mov     ah,#0x01
 530         mov     cx,#0x0b0c
 531         int     0x10            ! turn on cursor (scan lines 11 to 12)
 532         mov     al,#28
 533         jmp     getpar
 534 
 535 m80x50: mov     ax,#0x1112      ! Setting 80x50 (EGA/VGA)
 536         xor     bl,bl
 537         int     0x10            ! use 8x8 font set
 538         mov     ax,#0x1200
 539         mov     bl,#0x20
 540         int     0x10            ! use alternate print screen
 541         mov     ax,#0x1201
 542         mov     bl,#0x34
 543         int     0x10            ! turn off cursor emulation
 544         mov     ah,#0x01
 545         mov     cx,#0x0607
 546         int     0x10            ! turn on cursor (scan lines 6 to 7)
 547         mov     al,#50
 548         jmp     getpar
 549 
 550 defmd:  mov     al,#25          ! Default is 25 lines
 551 
 552 !
 553 ! Correct video mode set. Determine the remaining parameters.
 554 !
 555 
 556 getpar: pop     ds              ! Restore original DS
 557         mov     [14],al         ! Number of lines
 558 
 559         mov     ah,#0x03        ! read cursor pos
 560         xor     bh,bh           ! clear bh
 561         int     0x10            ! save it in known place, con_init fetches
 562         mov     [0],dx          ! it from 0x90000.
 563         
 564         mov     ah,#0x0f
 565         int     0x10
 566         mov     [4],bx          ! bh = display page
 567         mov     [6],ax          ! al = video mode, ah = window width
 568         xor     ax,ax
 569         mov     es,ax           ! Access low memory
 570         seg es
 571         mov     ax,[0x485]      ! POINTS - Height of character matrix
 572         mov     [16],ax
 573 
 574         ret                     ! Well done...
 575 
 576 !
 577 ! Table of all known SVGA cards. For each card, we store a pointer to
 578 ! a table of video modes supported by the card and a pointer to a routine
 579 ! used for testing of presence of the card.
 580 !
 581 
 582 vgatable:
 583         .word   s3_md, s3_test
 584         .word   ati_md, ati_test
 585         .word   ahead_md, ahead_test
 586         .word   chips_md, chips_test
 587         .word   cirrus2_md, cirrus2_test
 588         .word   cirrus1_md, cirrus1_test
 589         .word   everex_md, everex_test
 590         .word   genoa_md, genoa_test
 591         .word   oak_md, oak_test
 592         .word   paradise_md, paradise_test
 593         .word   trident_md, trident_test
 594         .word   tseng_md, tseng_test
 595         .word   video7_md, video7_test
 596         .word   0
 597 
 598 !
 599 ! Test routines and mode tables:
 600 !
 601 
 602 ! S3 - The test algorithm was taken from the SuperProbe package
 603 ! for XFree86 1.2.1. Report bugs to Christoph.Niemann@linux.org
 604 
 605 s3_test:
 606         mov     cx,#0x0f35      ! we store some constants in cl/ch
 607         mov     dx,#0x03d4
 608         movb    al,#0x38
 609         call    inidx
 610         mov     bh,al           ! store current value of CRT-register 0x38
 611         mov     ax,#0x0038
 612         call    outidx          ! disable writing to special regs
 613         movb    al,cl           ! check whether we can write special reg 0x35
 614         call    inidx
 615         movb    bl,al           ! save the current value of CRT reg 0x35
 616         andb    al,#0xf0        ! clear bits 0-3
 617         movb    ah,al
 618         movb    al,cl           ! and write it to CRT reg 0x35
 619         call    outidx
 620         call    inidx           ! now read it back
 621         andb    al,ch           ! clear the upper 4 bits
 622         jz      s3_2            ! the first test failed. But we have a
 623         movb    ah,bl           ! second chance
 624         mov     al,cl
 625         call    outidx
 626         jmp     s3_1            ! do the other tests
 627 s3_2:   mov     ax,cx           ! load ah with 0xf and al with 0x35
 628         orb     ah,bl           ! set the upper 4 bits of ah with the orig value
 629         call    outidx          ! write ...
 630         call    inidx           ! ... and reread 
 631         andb    al,cl           ! turn off the upper 4 bits
 632         push    ax
 633         movb    ah,bl           ! restore old value in register 0x35
 634         movb    al,cl
 635         call    outidx
 636         pop     ax
 637         cmp     al,ch           ! setting lower 4 bits was successful => bad
 638         je      no_s3           ! writing is allowed => this is not an S3
 639 s3_1:   mov     ax,#0x4838      ! allow writing to special regs by putting
 640         call    outidx          ! magic number into CRT-register 0x38
 641         movb    al,cl           ! check whether we can write special reg 0x35
 642         call    inidx
 643         movb    bl,al
 644         andb    al,#0xf0
 645         movb    ah,al
 646         movb    al,cl
 647         call    outidx
 648         call    inidx
 649         andb    al,ch
 650         jnz     no_s3           ! no, we can't write => no S3
 651         mov     ax,cx
 652         orb     ah,bl
 653         call    outidx
 654         call    inidx
 655         andb    al,ch
 656         push    ax
 657         movb    ah,bl           ! restore old value in register 0x35
 658         movb    al,cl
 659         call    outidx
 660         pop     ax
 661         cmp     al,ch
 662         jne     no_s31          ! writing not possible => no S3
 663         movb    al,#0x30
 664         call    inidx           ! now get the S3 id ...
 665         lea     di,idS3
 666         mov     cx,#0x10
 667         repne
 668         scasb
 669         je      no_s31
 670         movb    ah,bh
 671         movb    al,#0x38
 672         jmp     s3rest
 673 no_s3:  movb    al,#0x35        ! restore CRT register 0x35
 674         movb    ah,bl
 675         call    outidx
 676 no_s31: xor     bp,bp           ! Detection failed
 677 s3rest: movb    ah,bh
 678         movb    al,#0x38        ! restore old value of CRT register 0x38
 679 outidx: out     dx,al           ! Write to indexed VGA register
 680         push    ax              ! AL=index, AH=data, DX=index reg port
 681         mov     al,ah
 682         inc     dx
 683         out     dx,al
 684         dec     dx
 685         pop     ax
 686         ret
 687 
 688 tstidx: out     dx,ax           ! OUT DX,AX and inidx
 689 inidx:  out     dx,al           ! Read from indexed VGA register
 690         inc     dx              ! AL=index, DX=index reg port -> AL=data
 691         in      al,dx
 692         dec     dx
 693         ret
 694 
 695 idS3:   .byte   0x81, 0x82, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95
 696         .byte   0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa8, 0xb0
 697 
 698 s3_md:  .byte   0x54, 0x2b, 0x84
 699         .byte   0x55, 0x19, 0x84
 700         .byte   0
 701 
 702 ! ATI cards.
 703 
 704 ati_test:
 705         lea     si,idati
 706         mov     di,#0x31
 707         mov     cx,#0x09
 708         repe
 709         cmpsb
 710         je      atiok
 711         xor     bp,bp
 712 atiok:  ret
 713 
 714 idati:  .ascii  "761295520"
 715 
 716 ati_md: .byte   0x23, 0x19, 0x84
 717         .byte   0x33, 0x2c, 0x84
 718         .byte   0x22, 0x1e, 0x64
 719         .byte   0x21, 0x19, 0x64
 720         .byte   0x58, 0x21, 0x50
 721         .byte   0x5b, 0x1e, 0x50
 722         .byte   0
 723 
 724 ! AHEAD
 725 
 726 ahead_test:
 727         mov     ax,#0x200f
 728         mov     dx,#0x3ce
 729         out     dx,ax
 730         inc     dx
 731         in      al,dx
 732         cmp     al,#0x20
 733         je      isahed
 734         cmp     al,#0x21
 735         je      isahed
 736         xor     bp,bp
 737 isahed: ret
 738 
 739 ahead_md:
 740         .byte   0x22, 0x2c, 0x84
 741         .byte   0x23, 0x19, 0x84
 742         .byte   0x24, 0x1c, 0x84
 743         .byte   0x2f, 0x32, 0xa0
 744         .byte   0x32, 0x22, 0x50
 745         .byte   0x34, 0x42, 0x50
 746         .byte   0
 747 
 748 ! Chips & Tech.
 749 
 750 chips_test:
 751         mov     dx,#0x3c3
 752         in      al,dx
 753         or      al,#0x10
 754         out     dx,al
 755         mov     dx,#0x104               
 756         in      al,dx
 757         mov     bl,al
 758         mov     dx,#0x3c3
 759         in      al,dx
 760         and     al,#0xef
 761         out     dx,al
 762         cmp     bl,#0xa5
 763         je      cantok
 764         xor     bp,bp
 765 cantok: ret
 766 
 767 chips_md:
 768         .byte   0x60, 0x19, 0x84
 769         .byte   0x61, 0x32, 0x84
 770         .byte   0
 771 
 772 ! Cirrus Logic 5X0
 773 
 774 cirrus1_test:
 775         mov     dx,#0x3d4
 776         mov     al,#0x0c
 777         out     dx,al
 778         inc     dx
 779         in      al,dx
 780         mov     bl,al
 781         xor     al,al
 782         out     dx,al
 783         dec     dx
 784         mov     al,#0x1f
 785         out     dx,al
 786         inc     dx
 787         in      al,dx
 788         mov     bh,al
 789         xor     ah,ah
 790         shl     al,#4
 791         mov     cx,ax
 792         mov     al,bh
 793         shr     al,#4
 794         add     cx,ax
 795         shl     cx,#8
 796         add     cx,#6
 797         mov     ax,cx
 798         mov     dx,#0x3c4
 799         out     dx,ax
 800         inc     dx
 801         in      al,dx
 802         and     al,al
 803         jnz     nocirr
 804         mov     al,bh
 805         out     dx,al
 806         in      al,dx
 807         cmp     al,#0x01
 808         je      iscirr
 809 nocirr: xor     bp,bp
 810 iscirr: mov     dx,#0x3d4
 811         mov     al,bl
 812         xor     ah,ah
 813         shl     ax,#8
 814         add     ax,#0x0c
 815         out     dx,ax
 816         ret
 817 
 818 cirrus1_md:
 819         .byte   0x1f, 0x19, 0x84
 820         .byte   0x20, 0x2c, 0x84
 821         .byte   0x22, 0x1e, 0x84
 822         .byte   0x31, 0x25, 0x64
 823         .byte   0
 824 
 825 ! Cirrus Logic 54XX
 826 
 827 cirrus2_test:
 828         mov     dx,#0x3c4
 829         mov     al,#6
 830         call    inidx
 831         mov     bl,al                   ! BL=backup
 832         mov     al,#6
 833         xor     ah,ah
 834         call    tstidx
 835         cmp     al,#0x0f
 836         jne     c2fail
 837         mov     ax,#0x1206
 838         call    tstidx
 839         cmp     al,#0x12
 840         jne     c2fail
 841         mov     al,#0x1e
 842         call    inidx
 843         mov     bh,al
 844         and     bh,#0xc0
 845         mov     ah,bh
 846         mov     al,#0x1e
 847         call    tstidx
 848         xor     al,bh
 849         and     al,#0x3f
 850         jne     c2xx
 851         mov     al,#0x1e
 852         mov     ah,bh
 853         or      ah,#0x3f
 854         call    tstidx
 855         xor     al,bh
 856         xor     al,#0x3f
 857         and     al,#0x3f
 858 c2xx:   pushf
 859         mov     al,#0x1e
 860         mov     ah,bh
 861         out     dx,ax
 862         popf
 863         je      c2done
 864 c2fail: xor     bp,bp
 865 c2done: mov     al,#6
 866         mov     ah,bl
 867         out     dx,ax
 868         ret
 869 
 870 cirrus2_md:
 871         .byte   0x14, 0x19, 0x84
 872         .byte   0x54, 0x2b, 0x84
 873         .byte   0
 874 
 875 ! Everex / Trident
 876 
 877 everex_test:
 878         mov     ax,#0x7000
 879         xor     bx,bx
 880         int     0x10
 881         cmp     al,#0x70
 882         jne     noevrx
 883         shr     dx,#4
 884         cmp     dx,#0x678
 885         je      evtrid
 886         cmp     dx,#0x236
 887         jne     evrxok
 888 evtrid: lea     bp,trident_md
 889 evrxok: ret
 890 
 891 noevrx: xor     bp,bp
 892         ret
 893 
 894 everex_md:
 895         .byte   0x03, 0x22, 0x50
 896         .byte   0x04, 0x3c, 0x50
 897         .byte   0x07, 0x2b, 0x64
 898         .byte   0x08, 0x4b, 0x64
 899         .byte   0x0a, 0x19, 0x84
 900         .byte   0x0b, 0x2c, 0x84
 901         .byte   0x16, 0x1e, 0x50
 902         .byte   0x18, 0x1b, 0x64
 903         .byte   0x21, 0x40, 0xa0
 904         .byte   0x40, 0x1e, 0x84
 905         .byte   0
 906 
 907 ! Genoa.
 908 
 909 genoa_test:
 910         lea     si,idgenoa              ! Check Genoa 'clues'
 911         xor     ax,ax
 912         seg es
 913         mov     al,[0x37]
 914         mov     di,ax
 915         mov     cx,#0x04
 916         dec     si
 917         dec     di
 918 l1:     inc     si
 919         inc     di
 920         mov     al,(si)
 921         test    al,al
 922         jz      l2
 923         seg es
 924         cmp     al,(di)
 925 l2:     loope   l1
 926         or      cx,cx
 927         je      isgen
 928         xor     bp,bp
 929 isgen:  ret
 930 
 931 idgenoa: .byte  0x77, 0x00, 0x99, 0x66
 932 
 933 genoa_md:
 934         .byte   0x58, 0x20, 0x50
 935         .byte   0x5a, 0x2a, 0x64
 936         .byte   0x60, 0x19, 0x84
 937         .byte   0x61, 0x1d, 0x84
 938         .byte   0x62, 0x20, 0x84
 939         .byte   0x63, 0x2c, 0x84
 940         .byte   0x64, 0x3c, 0x84
 941         .byte   0x6b, 0x4f, 0x64
 942         .byte   0x72, 0x3c, 0x50
 943         .byte   0x74, 0x42, 0x50
 944         .byte   0x78, 0x4b, 0x64
 945         .byte   0
 946 
 947 ! OAK
 948 
 949 oak_test:
 950         lea     si,idoakvga
 951         mov     di,#0x08
 952         mov     cx,#0x08
 953         repe
 954         cmpsb
 955         je      isoak
 956         xor     bp,bp
 957 isoak:  ret
 958 
 959 idoakvga: .ascii  "OAK VGA "
 960 
 961 oak_md: .byte   0x4e, 0x3c, 0x50
 962         .byte   0x4f, 0x3c, 0x84
 963         .byte   0x50, 0x19, 0x84
 964         .byte   0x51, 0x2b, 0x84
 965         .byte   0
 966 
 967 ! WD Paradise.
 968 
 969 paradise_test:
 970         lea     si,idparadise
 971         mov     di,#0x7d
 972         mov     cx,#0x04
 973         repe
 974         cmpsb
 975         je      ispara
 976         xor     bp,bp
 977 ispara: ret
 978 
 979 idparadise:     .ascii  "VGA="
 980 
 981 paradise_md:
 982         .byte   0x41, 0x22, 0x50
 983         .byte   0x47, 0x1c, 0x84
 984         .byte   0x55, 0x19, 0x84
 985         .byte   0x54, 0x2c, 0x84
 986         .byte   0
 987 
 988 ! Trident.
 989 
 990 trident_test:
 991         mov     dx,#0x3c4
 992         mov     al,#0x0e
 993         out     dx,al
 994         inc     dx
 995         in      al,dx
 996         xchg    ah,al
 997         xor     al,al
 998         out     dx,al
 999         in      al,dx
1000         xchg    al,ah
1001         mov     bl,al           ! Strange thing ... in the book this wasn't
1002         and     bl,#0x02        ! necessary but it worked on my card which
1003         jz      setb2           ! is a trident. Without it the screen goes
1004         and     al,#0xfd        ! blurred ...
1005         jmp     clrb2           !
1006 setb2:  or      al,#0x02        !
1007 clrb2:  out     dx,al
1008         and     ah,#0x0f
1009         cmp     ah,#0x02
1010         je      istrid
1011         xor     bp,bp
1012 istrid: ret
1013 
1014 trident_md:
1015         .byte   0x50, 0x1e, 0x50
1016         .byte   0x51, 0x2b, 0x50
1017         .byte   0x52, 0x3c, 0x50
1018         .byte   0x57, 0x19, 0x84
1019         .byte   0x58, 0x1e, 0x84
1020         .byte   0x59, 0x2b, 0x84
1021         .byte   0x5a, 0x3c, 0x84
1022         .byte   0
1023 
1024 ! Tseng.
1025 
1026 tseng_test:
1027         mov     dx,#0x3cd
1028         in      al,dx                   ! Could things be this simple ! :-)
1029         mov     bl,al
1030         mov     al,#0x55
1031         out     dx,al
1032         in      al,dx
1033         mov     ah,al
1034         mov     al,bl
1035         out     dx,al
1036         cmp     ah,#0x55
1037         je      istsen
1038         xor     bp,bp
1039 istsen: ret
1040 
1041 tseng_md:
1042         .byte   0x26, 0x3c, 0x50
1043         .byte   0x2a, 0x28, 0x64
1044         .byte   0x23, 0x19, 0x84
1045         .byte   0x24, 0x1c, 0x84
1046         .byte   0x22, 0x2c, 0x84
1047         .byte   0
1048 
1049 ! Video7.
1050 
1051 video7_test:
1052         mov     dx,#0x3cc
1053         in      al,dx
1054         mov     dx,#0x3b4
1055         and     al,#0x01
1056         jz      even7
1057         mov     dx,#0x3d4
1058 even7:  mov     al,#0x0c
1059         out     dx,al
1060         inc     dx
1061         in      al,dx
1062         mov     bl,al
1063         mov     al,#0x55
1064         out     dx,al
1065         in      al,dx
1066         dec     dx
1067         mov     al,#0x1f
1068         out     dx,al
1069         inc     dx
1070         in      al,dx
1071         mov     bh,al
1072         dec     dx
1073         mov     al,#0x0c
1074         out     dx,al
1075         inc     dx
1076         mov     al,bl
1077         out     dx,al
1078         mov     al,#0x55
1079         xor     al,#0xea
1080         cmp     al,bh
1081         je      isvid7
1082         xor     bp,bp
1083 isvid7: ret
1084 
1085 video7_md:
1086         .byte   0x40, 0x2b, 0x50
1087         .byte   0x43, 0x3c, 0x50
1088         .byte   0x44, 0x3c, 0x64
1089         .byte   0x41, 0x19, 0x84
1090         .byte   0x42, 0x2c, 0x84
1091         .byte   0x45, 0x1c, 0x84
1092         .byte   0
1093 
1094 !
1095 ! Displaying of the mode list.
1096 !
1097 
1098 listmodes:
1099         lea     si,listhdr
1100         call    prtstr
1101         lea     bx,modelist
1102         mov     cl,#0x30
1103 listm1: mov     modenr,cl
1104         lea     si,modestring
1105         call    prtstr
1106         mov     al,(bx+3)
1107         call    dprnt
1108         mov     al,#0x78
1109         call    prnt1
1110         mov     al,(bx+2)
1111         call    dprnt
1112 #ifdef SHOW_BIOS_MODES
1113         mov     al,#0x20
1114         call    prnt1
1115         mov     al,#0x28
1116         call    prnt1
1117         mov     al,(bx+1)
1118         call    prthex
1119         mov     al,(bx)
1120         call    prthex
1121         mov     al,#0x29
1122         call    prnt1
1123 #endif
1124         lea     si,crlf
1125         call    prtstr
1126         add     bx,#4
1127         inc     cl
1128         cmp     cl,#0x3a
1129         jnz     listm2
1130         mov     cl,#0x61
1131 listm2: cmp     bx,di
1132         jc      listm1
1133         lea     si,prompt
1134         br      prtstr
1135 
1136 ! Routine to print a hexadecimal byte (AL) on screen.
1137 
1138 #ifdef SHOW_BIOS_MODES
1139 prthex: push    ax
1140         shr     al,#4
1141         call    prth1
1142         pop     ax
1143 prth1:  and     al,#15
1144         cmp     al,#10
1145         jc      prth2
1146         add     al,#7
1147 prth2:  add     al,#0x30
1148         br      prnt1
1149 #endif
1150 
1151 ! Routine to print a decimal value on screen, the value to be
1152 ! printed is put in AL (i.e 0-255). 
1153 
1154 dprnt:  push    ax
1155         push    cx
1156         xor     ah,ah           ! Clear ah
1157         mov     cl,#0x0a
1158         idiv    cl
1159         cmp     al,#0x09
1160         jbe     lt100
1161         call    dprnt
1162         jmp     skip10
1163 lt100:  add     al,#0x30
1164         call    prnt1
1165 skip10: mov     al,ah
1166         add     al,#0x30
1167         call    prnt1   
1168         pop     cx
1169         pop     ax
1170         ret
1171 
1172 !
1173 ! Read a key and return the (US-)ascii code in al, scan code in ah
1174 !
1175 getkey:
1176         xor     ah,ah
1177         int     0x16
1178         ret
1179 
1180 !
1181 ! Read a key with a timeout of 30 seconds. The cmos clock is used to get
1182 ! the time.
1183 !
1184 getkt:
1185         call    gettime
1186         add     al,#30          ! wait 30 seconds
1187         cmp     al,#60
1188         jl      lminute
1189         sub     al,#60
1190 lminute:
1191         mov     cl,al
1192 again:  mov     ah,#0x01
1193         int     0x16
1194         jnz     getkey          ! key pressed, so get it
1195         call    gettime
1196         cmp     al,cl
1197         jne     again
1198         mov     al,#0x20        ! timeout, return default char `space'
1199         ret
1200 
1201 !
1202 ! Flush the keyboard buffer
1203 !
1204 flush:  mov     ah,#0x01
1205         int     0x16
1206         jz      empty
1207         xor     ah,ah
1208         int     0x16
1209         jmp     flush
1210 empty:  ret
1211 
1212 !
1213 ! Read the cmos clock. Return the seconds in al
1214 !
1215 gettime:
1216         push    cx
1217         mov     ah,#0x02
1218         int     0x1a
1219         mov     al,dh                   ! dh contains the seconds
1220         and     al,#0x0f
1221         mov     ah,dh
1222         mov     cl,#0x04
1223         shr     ah,cl
1224         aad
1225         pop     cx
1226         ret
1227 
1228 !
1229 ! Descriptor table for our protected mode transition.
1230 !
1231 
1232 gdt:
1233         .word   0,0,0,0         ! dummy
1234 
1235         .word   0,0,0,0         ! unused
1236 
1237         .word   0x07FF          ! 8Mb - limit=2047 (2048*4096=8Mb)
1238         .word   0x0000          ! base address=0
1239         .word   0x9A00          ! code read/exec
1240         .word   0x00C0          ! granularity=4096, 386
1241 
1242         .word   0x07FF          ! 8Mb - limit=2047 (2048*4096=8Mb)
1243         .word   0x0000          ! base address=0
1244         .word   0x9200          ! data read/write
1245         .word   0x00C0          ! granularity=4096, 386
1246 
1247 idt_48:
1248         .word   0                       ! idt limit=0
1249         .word   0,0                     ! idt base=0L
1250 
1251 gdt_48:
1252         .word   0x800           ! gdt limit=2048, 256 GDT entries
1253         .word   512+gdt,0x9     ! gdt base = 0X9xxxx
1254 
1255 !
1256 ! Assorted messages.
1257 !
1258 
1259 keymsg:         .ascii  "Press <RETURN> to see video modes available, <SPACE> to continue or wait 30 secs"
1260                 db      0x0d, 0x0a, 0x00
1261 listhdr:        .ascii  "Mode:  COLSxROWS:"
1262                 db      0x0d, 0x0a, 0x0a, 0x00
1263 prompt:         db      0x0d, 0x0a
1264                 .ascii  "Choose mode by pressing the corresponding number or letter."
1265 crlf:           db      0x0d, 0x0a, 0x00
1266 undefd:         .ascii  "You passed an undefined mode number to setup. Please choose a new mode."
1267                 db      0x0d, 0x0a, 0x0a, 0x07, 0x00
1268 modestring:     .ascii  "   "
1269 modenr:         db      0x00    ! mode number
1270                 .ascii  ":    "
1271                 db      0x00
1272 
1273 modesave:       .word   0       ! Requsted mode ID.
1274 
1275 ! This must be last
1276 setup_sig1:     .word   SIG1
1277 setup_sig2:     .word   SIG2
1278 
1279 ! After our code and data, we'll store the mode list.
1280 ! Mode record:  .word   modenr
1281 !               .byte   lines
1282 !               .byte   columns
1283 ! Mode numbers used: 0=current, >=0x100=VESA, -1=80x50, -2=80x28
1284 modelist:
1285 
1286 .text
1287 endtext:
1288 .data
1289 enddata:
1290 .bss
1291 endbss:

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