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