home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.2 / LINUX-1.2 / LINUX-1 / linux / arch / i386 / boot / setup.S < prev   
Encoding:
Text File  |  1995-01-05  |  20.1 KB  |  1,012 lines

  1. !
  2. !    setup.S        Copyright (C) 1991, 1992 Linus Torvalds
  3. !
  4. ! setup.s is responsible for getting the system data from the BIOS,
  5. ! and putting them into the appropriate places in system memory.
  6. ! both setup.s and system has been loaded by the bootblock.
  7. !
  8. ! This code asks the bios for memory/disk/other parameters, and
  9. ! puts them in a "safe" place: 0x90000-0x901FF, ie where the
  10. ! boot-block used to be. It is then up to the protected mode
  11. ! system to read them from there before the area is overwritten
  12. ! for buffer-blocks.
  13. !
  14. ! Move PS/2 aux init code to psaux.c
  15. ! (troyer@saifr00.cfsat.Honeywell.COM) 03Oct92
  16. !
  17. ! some changes and additional features by Christoph Niemann,
  18. ! March 1993/June 1994 (Christoph.Niemann@linux.org)
  19. !
  20.  
  21. ! NOTE! These had better be the same as in bootsect.s!
  22. #define __ASSEMBLY__
  23. #include <linux/config.h>
  24. #include <asm/segment.h>
  25.  
  26. #ifndef SVGA_MODE
  27. #define SVGA_MODE ASK_VGA
  28. #endif
  29.  
  30. ! Signature words to ensure LILO loaded us right
  31. #define SIG1    0xAA55
  32. #define SIG2    0x5A5A
  33.  
  34. INITSEG  = DEF_INITSEG    ! we move boot here - out of the way
  35. SYSSEG   = DEF_SYSSEG    ! system loaded at 0x10000 (65536).
  36. SETUPSEG = DEF_SETUPSEG    ! this is the current segment
  37.  
  38. .globl begtext, begdata, begbss, endtext, enddata, endbss
  39. .text
  40. begtext:
  41. .data
  42. begdata:
  43. .bss
  44. begbss:
  45. .text
  46.  
  47. entry start
  48. start:
  49. ! Bootlin depends on this being done early
  50.     mov    ax,#0x01500
  51.     mov    dl,#0x81
  52.     int    0x13
  53.  
  54. ! Check signature at end of setup
  55.     mov    ax,#SETUPSEG
  56.     mov    ds,ax
  57.     cmp    setup_sig1,#SIG1
  58.     jne    bad_sig
  59.     cmp    setup_sig2,#SIG2
  60.     jne    bad_sig
  61.     jmp    good_sig1
  62.  
  63. ! Routine to print asciiz-string at DS:SI
  64.  
  65. prtstr:    lodsb
  66.     and    al,al
  67.     jz    fin
  68.     call    prnt1
  69.     jmp    prtstr
  70. fin:    ret
  71.  
  72. ! Part of above routine, this one just prints ascii al
  73.  
  74. prnt1:    push    ax
  75.     push    cx
  76.     xor    bh,bh
  77.     mov    cx,#0x01
  78.     mov    ah,#0x0e
  79.     int    0x10
  80.     pop    cx
  81.     pop    ax
  82.     ret
  83.  
  84. beep:    mov    al,#0x07
  85.     jmp    prnt1
  86.     
  87. no_sig_mess:    .ascii    "No setup signature found ..."
  88.         db    0x00
  89. start_sys_seg:    .word    SYSSEG
  90.  
  91. good_sig1:
  92.     jmp    good_sig
  93.  
  94. ! We now have to find the rest of the setup code/data
  95. bad_sig:
  96.     mov    ax,#INITSEG
  97.     mov    ds,ax
  98.     xor    bh,bh
  99.     mov    bl,[497]    ! get setup sects from boot sector
  100.     sub    bx,#4        ! LILO loads 4 sectors of setup
  101.     shl    bx,#8        ! convert to words
  102.     mov    cx,bx
  103.     shr    bx,#3        ! convert to segment
  104.     add    bx,#SYSSEG
  105.     seg cs
  106.     mov    start_sys_seg,bx
  107.  
  108. ! Move rest of setup code/data to here
  109.     mov    di,#2048    ! four sectors loaded by LILO
  110.     sub    si,si
  111.     mov    ax,#SETUPSEG
  112.     mov    es,ax
  113.     mov    ax,#SYSSEG
  114.     mov    ds,ax
  115.     rep
  116.     movsw
  117.  
  118.     mov    ax,#SETUPSEG
  119.     mov    ds,ax
  120.     cmp    setup_sig1,#SIG1
  121.     jne    no_sig
  122.     cmp    setup_sig2,#SIG2
  123.     jne    no_sig
  124.     jmp    good_sig
  125.  
  126. no_sig:
  127.     lea    si,no_sig_mess
  128.     call    prtstr
  129. no_sig_loop:
  130.     jmp    no_sig_loop
  131.  
  132. good_sig:
  133.     mov    ax,#INITSEG
  134.     mov    ds,ax
  135.  
  136. ! Get memory size (extended mem, kB)
  137.  
  138.     mov    ah,#0x88
  139.     int    0x15
  140.     mov    [2],ax
  141.  
  142. ! set the keyboard repeat rate to the max
  143.  
  144.     mov    ax,#0x0305
  145.     xor    bx,bx        ! clear bx
  146.     int    0x16
  147.  
  148. ! check for EGA/VGA and some config parameters
  149.  
  150.     mov    ah,#0x12
  151.     mov    bl,#0x10
  152.     int    0x10
  153.     mov    [8],ax
  154.     mov    [10],bx
  155.     mov    [12],cx
  156.     mov    ax,#0x5019
  157.     cmp    bl,#0x10
  158.     je    novga
  159.     mov    ax,#0x1a00    ! Added check for EGA/VGA discrimination
  160.     int    0x10
  161.     mov    bx,ax
  162.     mov    ax,#0x5019
  163.     cmp    bl,#0x1a    ! 1a means VGA, anything else EGA or lower
  164.     jne    novga    
  165.     call    chsvga
  166. novga:    mov    [14],ax
  167.     mov    ah,#0x03    ! read cursor pos
  168.     xor    bh,bh        ! clear bh
  169.     int    0x10        ! save it in known place, con_init fetches
  170.     mov    [0],dx        ! it from 0x90000.
  171.     
  172. ! Get video-card data:
  173.     
  174.     mov    ah,#0x0f
  175.     int    0x10
  176.     mov    [4],bx        ! bh = display page
  177.     mov    [6],ax        ! al = video mode, ah = window width
  178.  
  179. ! Get hd0 data
  180.  
  181.     xor    ax,ax        ! clear ax
  182.     mov    ds,ax
  183.     lds    si,[4*0x41]
  184.     mov    ax,#INITSEG
  185.     push    ax
  186.     mov    es,ax
  187.     mov    di,#0x0080
  188.     mov    cx,#0x10
  189.     push    cx
  190.     cld
  191.     rep
  192.     movsb
  193.  
  194. ! Get hd1 data
  195.  
  196.     xor    ax,ax        ! clear ax
  197.     mov    ds,ax
  198.     lds    si,[4*0x46]
  199.     pop    cx
  200.     pop    es
  201.     mov    di,#0x0090
  202.     rep
  203.     movsb
  204.  
  205. ! Check that there IS a hd1 :-)
  206.  
  207.     mov    ax,#0x01500
  208.     mov    dl,#0x81
  209.     int    0x13
  210.     jc    no_disk1
  211.     cmp    ah,#3
  212.     je    is_disk1
  213. no_disk1:
  214.     mov    ax,#INITSEG
  215.     mov    es,ax
  216.     mov    di,#0x0090
  217.     mov    cx,#0x10
  218.     xor    ax,ax        ! clear ax
  219.     cld
  220.     rep
  221.     stosb
  222. is_disk1:
  223.  
  224. ! check for PS/2 pointing device
  225.  
  226.     mov    ax,#INITSEG
  227.     mov    ds,ax
  228.     mov    [0x1ff],#0    ! default is no pointing device
  229.     int    0x11        ! int 0x11: equipment determination
  230.     test    al,#0x04    ! check if pointing device installed
  231.     jz    no_psmouse
  232.     mov    [0x1ff],#0xaa    ! device present
  233. no_psmouse:
  234. ! now we want to move to protected mode ...
  235.  
  236.     cli            ! no interrupts allowed !
  237.     mov    al,#0x80    ! disable NMI for the bootup sequence
  238.     out    #0x70,al
  239.  
  240. ! first we move the system to its rightful place
  241.  
  242.     mov    ax,#0x100    ! start of destination segment
  243.     seg cs
  244.     mov    bx,start_sys_seg    ! start of source segment
  245.     cld            ! 'direction'=0, movs moves forward
  246. do_move:
  247.     mov    es,ax        ! destination segment
  248.     inc    ah        ! instead of add ax,#0x100
  249.     cmp    ax,#0x9000
  250.     jz    end_move
  251.     mov    ds,bx        ! source segment
  252.     add    bx,#0x100
  253.     sub    di,di
  254.     sub    si,si
  255.     mov     cx,#0x800
  256.     rep
  257.     movsw
  258.     jmp    do_move
  259.  
  260. ! then we load the segment descriptors
  261.  
  262. end_move:
  263.     mov    ax,#SETUPSEG    ! right, forgot this at first. didn't work :-)
  264.     mov    ds,ax
  265.     lidt    idt_48        ! load idt with 0,0
  266.     lgdt    gdt_48        ! load gdt with whatever appropriate
  267.  
  268. ! that was painless, now we enable A20
  269.  
  270.     call    empty_8042
  271.     mov    al,#0xD1        ! command write
  272.     out    #0x64,al
  273.     call    empty_8042
  274.     mov    al,#0xDF        ! A20 on
  275.     out    #0x60,al
  276.     call    empty_8042
  277.  
  278. ! make sure any possible coprocessor is properly reset..
  279.  
  280.     xor    ax,ax
  281.     out    #0xf0,al
  282.     call    delay
  283.     out    #0xf1,al
  284.     call    delay
  285.  
  286. ! well, that went ok, I hope. Now we have to reprogram the interrupts :-(
  287. ! we put them right after the intel-reserved hardware interrupts, at
  288. ! int 0x20-0x2F. There they won't mess up anything. Sadly IBM really
  289. ! messed this up with the original PC, and they haven't been able to
  290. ! rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f,
  291. ! which is used for the internal hardware interrupts as well. We just
  292. ! have to reprogram the 8259's, and it isn't fun.
  293.  
  294.     mov    al,#0x11        ! initialization sequence
  295.     out    #0x20,al        ! send it to 8259A-1
  296.     call    delay
  297.     out    #0xA0,al        ! and to 8259A-2
  298.     call    delay
  299.     mov    al,#0x20        ! start of hardware int's (0x20)
  300.     out    #0x21,al
  301.     call    delay
  302.     mov    al,#0x28        ! start of hardware int's 2 (0x28)
  303.     out    #0xA1,al
  304.     call    delay
  305.     mov    al,#0x04        ! 8259-1 is master
  306.     out    #0x21,al
  307.     call    delay
  308.     mov    al,#0x02        ! 8259-2 is slave
  309.     out    #0xA1,al
  310.     call    delay
  311.     mov    al,#0x01        ! 8086 mode for both
  312.     out    #0x21,al
  313.     call    delay
  314.     out    #0xA1,al
  315.     call    delay
  316.     mov    al,#0xFF        ! mask off all interrupts for now
  317.     out    #0xA1,al
  318.     call    delay
  319.     mov    al,#0xFB        ! mask all irq's but irq2 which
  320.     out    #0x21,al        ! is cascaded
  321.  
  322. ! well, that certainly wasn't fun :-(. Hopefully it works, and we don't
  323. ! need no steenking BIOS anyway (except for the initial loading :-).
  324. ! The BIOS-routine wants lots of unnecessary data, and it's less
  325. ! "interesting" anyway. This is how REAL programmers do it.
  326. !
  327. ! Well, now's the time to actually move into protected mode. To make
  328. ! things as simple as possible, we do no register set-up or anything,
  329. ! we let the gnu-compiled 32-bit programs do that. We just jump to
  330. ! absolute address 0x00000, in 32-bit protected mode.
  331. !
  332. ! Note that the short jump isn't strictly needed, although there are
  333. ! reasons why it might be a good idea. It won't hurt in any case.
  334. !
  335.     xor    ax,ax
  336.     inc    ax        ! protected mode (PE) bit
  337.     lmsw    ax        ! This is it!
  338.     jmp    flush_instr
  339. flush_instr:
  340.     jmpi    0x1000,KERNEL_CS    ! jmp offset 1000 of segment 0x10 (cs)
  341.  
  342. ! This routine checks that the keyboard command queue is empty
  343. ! (after emptying the output buffers)
  344. !
  345. ! No timeout is used - if this hangs there is something wrong with
  346. ! the machine, and we probably couldn't proceed anyway.
  347. empty_8042:
  348.     call    delay
  349.     in    al,#0x64    ! 8042 status port
  350.     test    al,#1        ! output buffer?
  351.     jz    no_output
  352.     call    delay
  353.     in    al,#0x60    ! read it
  354.     jmp    empty_8042
  355. no_output:
  356.     test    al,#2        ! is input buffer full?
  357.     jnz    empty_8042    ! yes - loop
  358.     ret
  359. !
  360. ! Read a key and return the (US-)ascii code in al, scan code in ah
  361. !
  362. getkey:
  363.     xor    ah,ah
  364.     int    0x16
  365.     ret
  366.  
  367. !
  368. ! Read a key with a timeout of 30 seconds. The cmos clock is used to get
  369. ! the time.
  370. !
  371. getkt:
  372.     call    gettime
  373.     add    al,#30        ! wait 30 seconds
  374.     cmp    al,#60
  375.     jl    lminute
  376.     sub    al,#60
  377. lminute:
  378.     mov    cl,al
  379. again:    mov    ah,#0x01
  380.     int    0x16
  381.     jnz    getkey        ! key pressed, so get it
  382.     call    gettime
  383.     cmp    al,cl
  384.     jne    again
  385.     mov    al,#0x20    ! timeout, return default char `space'
  386.     ret
  387.  
  388. !
  389. ! Flush the keyboard buffer
  390. !
  391. flush:    mov    ah,#0x01
  392.     int    0x16
  393.     jz    empty
  394.     xor    ah,ah
  395.     int    0x16
  396.     jmp    flush
  397. empty:    ret
  398.  
  399. !
  400. ! Read the cmos clock. Return the seconds in al
  401. !
  402. gettime:
  403.     push    cx
  404.     mov    ah,#0x02
  405.     int    0x1a
  406.     mov    al,dh            ! dh contains the seconds
  407.     and    al,#0x0f
  408.     mov    ah,dh
  409.     mov    cl,#0x04
  410.     shr    ah,cl
  411.     aad
  412.     pop    cx
  413.     ret
  414.  
  415. !
  416. ! Delay is needed after doing i/o
  417. !
  418. delay:
  419.     .word    0x00eb            ! jmp $+2
  420.     ret
  421.  
  422. ! Routine trying to recognize type of SVGA-board present (if any)
  423. ! and if it recognize one gives the choices of resolution it offers.
  424. ! If one is found the resolution chosen is given by al,ah (rows,cols).
  425.  
  426. chsvga:    cld
  427.     push    ds
  428.     push    cs
  429.     mov    ax,[0x01fa]
  430.     pop    ds
  431.     mov    modesave,ax
  432.     mov     ax,#0xc000
  433.     mov    es,ax
  434.     mov    ax,modesave
  435.     cmp    ax,#NORMAL_VGA
  436.     je    defvga
  437.     cmp    ax,#EXTENDED_VGA
  438.     je    vga50
  439.     cmp    ax,#ASK_VGA
  440.     jne    svga
  441.     lea    si,msg1
  442.     call    prtstr
  443.     call    flush
  444. nokey:    call    getkt
  445.     cmp    al,#0x0d        ! enter ?
  446.     je    svga            ! yes - svga selection
  447.     cmp    al,#0x20        ! space ?
  448.     je    defvga            ! no - repeat
  449.     call     beep
  450.     jmp    nokey
  451. defvga:    mov    ax,#0x5019
  452.     pop    ds
  453.     ret
  454. /* extended vga mode: 80x50 */
  455. vga50:
  456.     mov    ax,#0x1112
  457.     xor    bl,bl
  458.     int    0x10        ! use 8x8 font set (50 lines on VGA)
  459.     mov    ax,#0x1200
  460.     mov    bl,#0x20
  461.     int    0x10        ! use alternate print screen
  462.     mov    ax,#0x1201
  463.     mov    bl,#0x34
  464.     int    0x10        ! turn off cursor emulation
  465.     mov    ah,#0x01
  466.     mov    cx,#0x0607
  467.     int    0x10        ! turn on cursor (scan lines 6 to 7)
  468.     pop    ds
  469.     mov    ax,#0x5032    ! return 80x50
  470.     ret
  471. /* extended vga mode: 80x28 */
  472. vga28:
  473.     pop    ax        ! clean the stack
  474.     mov    ax,#0x1111
  475.     xor    bl,bl
  476.     int    0x10        ! use 9x14 fontset (28 lines on VGA)
  477.     mov    ah, #0x01
  478.     mov    cx,#0x0b0c
  479.     int    0x10        ! turn on cursor (scan lines 11 to 12)
  480.     pop    ds
  481.     mov    ax,#0x501c    ! return 80x28
  482.     ret
  483. /* svga modes */
  484. !
  485. !    test for presence of an S3 VGA chip. The algorithm was taken
  486. !    from the SuperProbe package of XFree86 1.2.1
  487. !    report bugs to Christoph.Niemann@linux.org
  488. !
  489. svga:   cld
  490.     mov    cx,#0x0f35    ! we store some constants in cl/ch
  491.     mov    dx,#0x03d4
  492.     movb    al,#0x38
  493.     call    inidx
  494.     mov    bh,al        ! store current value of CRT-register 0x38
  495.     mov    ax,#0x0038
  496.     call    outidx        ! disable writing to special regs
  497.     movb    al,cl        ! check whether we can write special reg 0x35
  498.     call    inidx
  499.     movb    bl,al        ! save the current value of CRT reg 0x35
  500.     andb    al,#0xf0    ! clear bits 0-3
  501.     movb    ah,al
  502.     movb    al,cl        ! and write it to CRT reg 0x35
  503.     call    outidx
  504.     call    inidx        ! now read it back
  505.     andb    al,ch        ! clear the upper 4 bits
  506.     jz    s3_2        ! the first test failed. But we have a
  507.     movb    ah,bl        ! second chance
  508.     mov    al,cl
  509.     call    outidx
  510.     jmp    s3_1        ! do the other tests
  511. s3_2:    mov    ax,cx        ! load ah with 0xf and al with 0x35
  512.     orb    ah,bl        ! set the upper 4 bits of ah with the orig value
  513.     call    outidx        ! write ...
  514.     call    inidx        ! ... and reread 
  515.     andb    al,cl        ! turn off the upper 4 bits
  516.     push    ax
  517.     movb    ah,bl        ! restore old value in register 0x35
  518.     movb    al,cl
  519.     call    outidx
  520.     pop    ax
  521.     cmp    al,ch        ! setting lower 4 bits was successful => bad
  522.     je    no_s3        ! writing is allowed => this is not an S3
  523. s3_1:    mov    ax,#0x4838    ! allow writing to special regs by putting
  524.     call    outidx        ! magic number into CRT-register 0x38
  525.     movb    al,cl        ! check whether we can write special reg 0x35
  526.     call    inidx
  527.     movb    bl,al
  528.     andb    al,#0xf0
  529.     movb    ah,al
  530.     movb    al,cl
  531.     call    outidx
  532.     call    inidx
  533.     andb    al,ch
  534.     jnz    no_s3        ! no, we can't write => no S3
  535.     mov    ax,cx
  536.     orb    ah,bl
  537.     call    outidx
  538.     call    inidx
  539.     andb    al,ch
  540.     push    ax
  541.     movb    ah,bl        ! restore old value in register 0x35
  542.     movb    al,cl
  543.     call    outidx
  544.     pop    ax
  545.     cmp    al,ch
  546.     jne    no_s31        ! writing not possible => no S3
  547.     movb    al,#0x30
  548.     call    inidx        ! now get the S3 id ...
  549.     lea    di,idS3
  550.     mov    cx,#0x10
  551.     repne
  552.     scasb
  553.     je    no_s31
  554.     lea     si,dsc_S3    ! table of descriptions of video modes for BIOS
  555.     lea    di,mo_S3    ! table of sizes of video modes for my BIOS
  556.     movb    ah,bh
  557.     movb    al,#0x38
  558.     call    outidx        ! restore old value of CRT register 0x38
  559.     br    selmod        ! go ask for video mode
  560. no_s3:    movb    al,#0x35    ! restore CRT register 0x35
  561.     movb    ah,bl
  562.     call    outidx
  563. no_s31:    movb    ah,bh
  564.     movb    al,#0x38
  565.     call    outidx        ! restore old value of CRT register 0x38
  566.  
  567.     lea     si,idati        ! Check ATI 'clues'
  568.     mov    di,#0x31
  569.     mov     cx,#0x09
  570.     repe
  571.     cmpsb
  572.     jne    noati
  573.     lea    si,dscati
  574.     lea    di,moati
  575.     br    selmod
  576. noati:    mov    ax,#0x200f        ! Check Ahead 'clues'
  577.     mov    dx,#0x3ce
  578.     out    dx,ax
  579.     inc    dx
  580.     in    al,dx
  581.     cmp    al,#0x20
  582.     je    isahed
  583.     cmp    al,#0x21
  584.     jne    noahed
  585. isahed:    lea    si,dscahead
  586.     lea    di,moahead
  587.     br    selmod
  588. noahed:    mov    dx,#0x3c3        ! Check Chips & Tech. 'clues'
  589.     in    al,dx
  590.     or    al,#0x10
  591.     out    dx,al
  592.     mov    dx,#0x104        
  593.     in    al,dx
  594.     mov    bl,al
  595.     mov    dx,#0x3c3
  596.     in    al,dx
  597.     and    al,#0xef
  598.     out    dx,al
  599.     cmp    bl,[idcandt]
  600.     jne    nocant
  601.     lea    si,dsccandt
  602.     lea    di,mocandt
  603.     br    selmod
  604. nocant:    mov    dx,#0x3d4        ! Check Cirrus 'clues'
  605.     mov    al,#0x0c
  606.     out    dx,al
  607.     inc    dx
  608.     in    al,dx
  609.     mov    bl,al
  610.     xor    al,al
  611.     out    dx,al
  612.     dec    dx
  613.     mov    al,#0x1f
  614.     out    dx,al
  615.     inc    dx
  616.     in    al,dx
  617.     mov    bh,al
  618.     xor    ah,ah
  619.     shl    al,#4
  620.     mov    cx,ax
  621.     mov    al,bh
  622.     shr    al,#4
  623.     add    cx,ax
  624.     shl    cx,#8
  625.     add    cx,#6
  626.     mov    ax,cx
  627.     mov    dx,#0x3c4
  628.     out    dx,ax
  629.     inc    dx
  630.     in    al,dx
  631.     and    al,al
  632.     jnz    nocirr
  633.     mov    al,bh
  634.     out    dx,al
  635.     in    al,dx
  636.     cmp    al,#0x01
  637.     jne    nocirr
  638.     call    rst3d4    
  639.     lea    si,dsccirrus
  640.     lea    di,mocirrus
  641.     br    selmod
  642. rst3d4:    mov    dx,#0x3d4
  643.     mov    al,bl
  644.     xor    ah,ah
  645.     shl    ax,#8
  646.     add    ax,#0x0c
  647.     out    dx,ax
  648.     ret    
  649. nocirr:    call    rst3d4            ! Check Everex 'clues'
  650.     mov    ax,#0x7000
  651.     xor    bx,bx
  652.     int    0x10
  653.     cmp    al,#0x70
  654.     jne    noevrx
  655.     shr    dx,#4
  656.     cmp    dx,#0x678
  657.     je    istrid
  658.     cmp    dx,#0x236
  659.     je    istrid
  660.     lea    si,dsceverex
  661.     lea    di,moeverex
  662.     br    selmod
  663. istrid:    lea    cx,ev2tri
  664.     jmp    cx
  665. noevrx:    lea    si,idgenoa        ! Check Genoa 'clues'
  666.     xor     ax,ax
  667.     seg es
  668.     mov    al,[0x37]
  669.     mov    di,ax
  670.     mov    cx,#0x04
  671.     dec    si
  672.     dec    di
  673. l1:    inc    si
  674.     inc    di
  675.     mov    al,(si)
  676.     test    al,al
  677.     jz    l2
  678.     seg es
  679.     cmp    al,(di)
  680. l2:    loope     l1
  681.     cmp    cx,#0x00
  682.     jne    nogen
  683.     lea    si,dscgenoa
  684.     lea    di,mogenoa
  685.     br    selmod
  686. nogen:    cld
  687.     lea    si,idoakvga
  688.     mov    di,#0x08
  689.     mov    cx,#0x08
  690.     repe
  691.     cmpsb
  692.     jne    nooak
  693.     lea    si,dscoakvga
  694.     lea    di,mooakvga
  695.     br    selmod
  696. nooak:    cld
  697.     lea    si,idparadise        ! Check Paradise 'clues'
  698.     mov    di,#0x7d
  699.     mov    cx,#0x04
  700.     repe
  701.     cmpsb
  702.     jne    nopara
  703.     lea    si,dscparadise
  704.     lea    di,moparadise
  705.     br    selmod
  706. nopara:    mov    dx,#0x3c4        ! Check Trident 'clues'
  707.     mov    al,#0x0e
  708.     out    dx,al
  709.     inc    dx
  710.     in    al,dx
  711.     xchg    ah,al
  712.     xor    al,al
  713.     out    dx,al
  714.     in    al,dx
  715.     xchg    al,ah
  716.     mov    bl,al        ! Strange thing ... in the book this wasn't
  717.     and    bl,#0x02    ! necessary but it worked on my card which
  718.     jz    setb2        ! is a trident. Without it the screen goes
  719.     and    al,#0xfd    ! blurred ...
  720.     jmp    clrb2        !
  721. setb2:    or    al,#0x02    !
  722. clrb2:    out    dx,al
  723.     and    ah,#0x0f
  724.     cmp    ah,#0x02
  725.     jne    notrid
  726. ev2tri:    lea    si,dsctrident
  727.     lea    di,motrident
  728.     jmp    selmod
  729. notrid:    mov    dx,#0x3cd        ! Check Tseng 'clues'
  730.     in    al,dx            ! Could things be this simple ! :-)
  731.     mov    bl,al
  732.     mov    al,#0x55
  733.     out    dx,al
  734.     in    al,dx
  735.     mov    ah,al
  736.     mov    al,bl
  737.     out    dx,al
  738.     cmp    ah,#0x55
  739.      jne    notsen
  740.     lea    si,dsctseng
  741.     lea    di,motseng
  742.     jmp    selmod
  743. notsen:    mov    dx,#0x3cc        ! Check Video7 'clues'
  744.     in    al,dx
  745.     mov    dx,#0x3b4
  746.     and    al,#0x01
  747.     jz    even7
  748.     mov    dx,#0x3d4
  749. even7:    mov    al,#0x0c
  750.     out    dx,al
  751.     inc    dx
  752.     in    al,dx
  753.     mov    bl,al
  754.     mov    al,#0x55
  755.     out    dx,al
  756.     in    al,dx
  757.     dec    dx
  758.     mov    al,#0x1f
  759.     out    dx,al
  760.     inc    dx
  761.     in    al,dx
  762.     mov    bh,al
  763.     dec    dx
  764.     mov    al,#0x0c
  765.     out    dx,al
  766.     inc    dx
  767.     mov    al,bl
  768.     out    dx,al
  769.     mov    al,#0x55
  770.     xor    al,#0xea
  771.     cmp    al,bh
  772.     jne    novid7
  773.     lea    si,dscvideo7
  774.     lea    di,movideo7
  775.     jmp    selmod
  776. novid7:    lea    si,dsunknown
  777.     lea    di,mounknown
  778. selmod:    xor    cx,cx
  779.     mov    cl,(di)
  780.     mov    ax,modesave
  781.     cmp    ax,#ASK_VGA
  782.     je    askmod
  783.     cmp    ax,#NORMAL_VGA
  784.     je    askmod
  785.     cmp    al,cl
  786.     jl    gotmode
  787.     push    si
  788.     lea    si,msg4
  789.     call    prtstr
  790.     pop    si
  791. askmod:    push    si
  792.     lea    si,msg2
  793.     call    prtstr
  794.     pop    si
  795.     push    si
  796.     push    cx
  797. tbl:    pop    bx
  798.     push    bx
  799.     mov    al,bl
  800.     sub    al,cl
  801.     call    modepr
  802.     lodsw
  803.     xchg    al,ah
  804.     call    dprnt
  805.     xchg    ah,al
  806.     push    ax
  807.     mov    al,#0x78
  808.     call    prnt1
  809.     pop    ax
  810.     call    dprnt
  811.     push    si
  812.     lea    si,crlf        ! print CR+LF
  813.     call    prtstr
  814.     pop    si
  815.     loop    tbl
  816.     pop    cx
  817.     lea    si,msg3
  818.     call    prtstr
  819.     pop    si
  820.     add    cl,#0x30
  821.     jmp    nonum
  822. nonumb:    call    beep
  823. nonum:    call    getkey
  824.     cmp    al,#0x30    ! ascii `0'
  825.     jb    nonumb
  826.     cmp    al,#0x3a    ! ascii `9'
  827.     jbe    number
  828.     cmp    al,#0x61    ! ascii `a'
  829.     jb    nonumb
  830.     cmp    al,#0x7a    ! ascii `z'
  831.     ja    nonumb
  832.     sub    al,#0x27
  833.     cmp    al,cl
  834.     jae    nonumb
  835.     sub    al,#0x30
  836.     jmp    gotmode
  837. number: cmp    al,cl
  838.     jae    nonumb
  839.     sub    al,#0x30
  840. gotmode:    xor    ah,ah
  841.     or    al,al
  842.     beq    vga50
  843.     push    ax
  844.     dec    ax
  845.     beq    vga28
  846.     add    di,ax
  847.     mov    al,(di)
  848.     int     0x10
  849.     pop    ax
  850.     shl    ax,#1
  851.     add    si,ax
  852.     lodsw
  853.     pop    ds
  854.     ret
  855.  
  856. ! Routine to write al into a VGA-register that is
  857. ! accessed via an index register
  858. !
  859. ! dx contains the address of the index register
  860. ! al contains the index
  861. ! ah contains the value to write to the data register (dx + 1)
  862. !
  863. ! no registers are changed
  864.  
  865. outidx:    out    dx,al
  866.     push    ax
  867.     mov    al,ah
  868.     inc    dx
  869.     out    dx,al
  870.     dec    dx
  871.     pop    ax
  872.     ret
  873. inidx:    out    dx,al
  874.     inc    dx
  875.     in    al,dx
  876.     dec    dx
  877.     ret
  878.  
  879. ! Routine to print a decimal value on screen, the value to be
  880. ! printed is put in al (i.e 0-255). 
  881.  
  882. dprnt:    push    ax
  883.     push    cx
  884.     xor    ah,ah        ! Clear ah
  885.     mov    cl,#0x0a
  886.     idiv    cl
  887.     cmp    al,#0x09
  888.     jbe    lt100
  889.     call    dprnt
  890.     jmp    skip10
  891. lt100:    add    al,#0x30
  892.     call    prnt1
  893. skip10:    mov    al,ah
  894.     add    al,#0x30
  895.     call    prnt1    
  896.     pop    cx
  897.     pop    ax
  898.     ret
  899.  
  900. !
  901. ! Routine to print the mode number key on screen. Mode numbers
  902. ! 0-9 print the ascii values `0' to '9', 10-35 are represented by
  903. ! the letters `a' to `z'. This routine prints some spaces around the
  904. ! mode no.
  905. !
  906.  
  907. modepr:    push    ax
  908.     cmp    al,#0x0a
  909.     jb    digit        ! Here is no check for number > 35
  910.     add    al,#0x27
  911. digit:    add    al,#0x30
  912.     mov    modenr, al
  913.     push     si
  914.     lea    si, modestring
  915.     call    prtstr
  916.     pop    si
  917.     pop    ax
  918.     ret
  919.  
  920. gdt:
  921.     .word    0,0,0,0        ! dummy
  922.  
  923.     .word    0,0,0,0        ! unused
  924.  
  925.     .word    0x07FF        ! 8Mb - limit=2047 (2048*4096=8Mb)
  926.     .word    0x0000        ! base address=0
  927.     .word    0x9A00        ! code read/exec
  928.     .word    0x00C0        ! granularity=4096, 386
  929.  
  930.     .word    0x07FF        ! 8Mb - limit=2047 (2048*4096=8Mb)
  931.     .word    0x0000        ! base address=0
  932.     .word    0x9200        ! data read/write
  933.     .word    0x00C0        ! granularity=4096, 386
  934.  
  935. idt_48:
  936.     .word    0            ! idt limit=0
  937.     .word    0,0            ! idt base=0L
  938.  
  939. gdt_48:
  940.     .word    0x800        ! gdt limit=2048, 256 GDT entries
  941.     .word    512+gdt,0x9    ! gdt base = 0X9xxxx
  942.  
  943. msg1:        .ascii    "Press <RETURN> to see SVGA-modes available, <SPACE> to continue or wait 30 secs."
  944.         db    0x0d, 0x0a, 0x0a, 0x00
  945. msg2:        .ascii    "Mode:  COLSxROWS:"
  946.         db    0x0d, 0x0a, 0x0a, 0x00
  947. msg3:        db    0x0d, 0x0a
  948.         .ascii    "Choose mode by pressing the corresponding number or letter."
  949. crlf:        db    0x0d, 0x0a, 0x00
  950. msg4:        .ascii    "You passed an undefined mode number to setup. Please choose a new mode."
  951.         db    0x0d, 0x0a, 0x0a, 0x07, 0x00
  952. modestring:    .ascii    "   "
  953. modenr:        db    0x00    ! mode number
  954.         .ascii    ":    "
  955.         db    0x00
  956.         
  957. idati:        .ascii    "761295520"
  958. idcandt:    .byte    0xa5
  959. idgenoa:    .byte    0x77, 0x00, 0x99, 0x66
  960. idparadise:    .ascii    "VGA="
  961. idoakvga:    .ascii  "OAK VGA "
  962. idS3:        .byte    0x81, 0x82, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95
  963.         .byte    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa8, 0xb0
  964.  
  965. ! Manufacturer:      Numofmodes+2:    Mode:
  966. ! Number of modes is the number of chip-specific svga modes plus the extended
  967. ! modes available on any vga (currently 2)
  968.  
  969. moati:        .byte    0x06,    0x23, 0x33, 0x22, 0x21
  970. moahead:    .byte    0x07,    0x22, 0x23, 0x24, 0x2f, 0x34
  971. mocandt:    .byte    0x04,    0x60, 0x61
  972. mocirrus:    .byte    0x06,    0x1f, 0x20, 0x22, 0x31
  973. moeverex:    .byte    0x0c,    0x03, 0x04, 0x07, 0x08, 0x0a, 0x0b, 0x16, 0x18, 0x21, 0x40
  974. mogenoa:    .byte    0x0c,    0x58, 0x5a, 0x60, 0x61, 0x62, 0x63, 0x64, 0x72, 0x74, 0x78
  975. moparadise:    .byte    0x04,    0x55, 0x54
  976. motrident:    .byte    0x09,    0x50, 0x51, 0x52, 0x57, 0x58, 0x59, 0x5a
  977. motseng:    .byte    0x07,    0x26, 0x2a, 0x23, 0x24, 0x22
  978. movideo7:    .byte    0x08,    0x40, 0x43, 0x44, 0x41, 0x42, 0x45
  979. mooakvga:    .byte   0x08,   0x00, 0x07, 0x4e, 0x4f, 0x50, 0x51
  980. mo_S3:        .byte    0x04,    0x54, 0x55
  981. mounknown:    .byte    0x02
  982.  
  983. !            msb = Cols lsb = Rows:
  984. ! The first two modes are standard vga modes available on any vga.
  985. ! mode 0 is 80x50 and mode 1 is 80x28
  986.  
  987. dscati:        .word    0x5032, 0x501c, 0x8419, 0x842c, 0x641e, 0x6419
  988. dscahead:    .word    0x5032, 0x501c, 0x842c, 0x8419, 0x841c, 0xa032, 0x5042
  989. dsccandt:    .word    0x5032, 0x501c, 0x8419, 0x8432
  990. dsccirrus:    .word    0x5032, 0x501c, 0x8419, 0x842c, 0x841e, 0x6425
  991. dsceverex:    .word    0x5032, 0x501c, 0x5022, 0x503c, 0x642b, 0x644b, 0x8419, 0x842c, 0x501e, 0x641b, 0xa040, 0x841e
  992. dscgenoa:    .word    0x5032, 0x501c, 0x5020, 0x642a, 0x8419, 0x841d, 0x8420, 0x842c, 0x843c, 0x503c, 0x5042, 0x644b
  993. dscparadise:    .word    0x5032, 0x501c, 0x8419, 0x842c
  994. dsctrident:    .word     0x5032, 0x501c, 0x501e, 0x502b, 0x503c, 0x8419, 0x841e, 0x842b, 0x843c
  995. dsctseng:    .word    0x5032, 0x501c, 0x503c, 0x6428, 0x8419, 0x841c, 0x842c
  996. dscvideo7:    .word    0x5032, 0x501c, 0x502b, 0x503c, 0x643c, 0x8419, 0x842c, 0x841c
  997. dscoakvga:    .word   0x5032, 0x501c, 0x2819, 0x5019, 0x503c, 0x843c, 0x8419, 0x842b
  998. dsc_S3:        .word    0x5032, 0x501c, 0x842b, 0x8419
  999. dsunknown:    .word    0x5032, 0x501c
  1000. modesave:    .word    SVGA_MODE
  1001.  
  1002. ! This must be last
  1003. setup_sig1:    .word    SIG1
  1004. setup_sig2:    .word    SIG2
  1005.  
  1006. .text
  1007. endtext:
  1008. .data
  1009. enddata:
  1010. .bss
  1011. endbss:
  1012.