首页 > 代码库 > boot/setup.S

boot/setup.S

!
!    setup.S        Copyright (C) 1991, 1992 Linus Torvalds
!
! setup.s is responsible for getting the system data from the BIOS,
! and putting them into the appropriate places in system memory.
! both setup.s and system has been loaded by the bootblock.
!
! This code asks the bios for memory/disk/other parameters, and
! puts them in a "safe" place: 0x90000-0x901FF, ie where the
! boot-block used to be. It is then up to the protected mode
! system to read them from there before the area is overwritten
! for buffer-blocks.
!
! Move PS/2 aux init code to psaux.c
! (troyer@saifr00.cfsat.Honeywell.COM) 03Oct92
!
! some changes and additional features by Christoph Niemann, March 1993
! (niemann@rubdv15.ETDV.Ruhr-Uni-Bochum.De)
!

! NOTE! These had better be the same as in bootsect.s!
#include <linux/config.h>
#include <linux/segment.h>

#ifndef SVGA_MODE
#define SVGA_MODE ASK_VGA
#endif

INITSEG  = DEF_INITSEG    ! we move boot here - out of the way
SYSSEG   = DEF_SYSSEG    ! system loaded at 0x10000 (65536).
SETUPSEG = DEF_SETUPSEG    ! this is the current segment

.globl begtext, begdata, begbss, endtext, enddata, endbss
.text
begtext:
.data
begdata:
.bss
begbss:
.text

! 程序入口
entry start
start:

! ok, the read went well so we get current cursor position and save it for
! posterity.
! ok,读取正常,现在我们获取当前光标位置然后保存

    ! 设定ds段位置
    mov    ax,#INITSEG    ! this is done in bootsect already, but...
    mov    ds,ax

! Get memory size (extended mem, kB)
! 获取内存
    mov    ah,#0x88
    int    0x15
    mov    [2],ax

! set the keyboard repeat rate to the max
! 设置键盘最大重复速率
    mov    ax,#0x0305
    xor    bx,bx        ! clear bx
    int    0x16

! check for EGA/VGA and some config parameters
! 检测EGA/VGA并配置参数

    mov    ah,#0x12
    mov    bl,#0x10
    int    0x10
    mov    [8],ax
    mov    [10],bx
    mov    [12],cx
    mov    ax,#0x5019
    cmp    bl,#0x10
    je    novga
    mov    ax,#0x1a00    ! Added check for EGA/VGA discrimination
    int    0x10
    mov    bx,ax
    mov    ax,#0x5019
    cmp    bl,#0x1a    ! 1a means VGA, anything else EGA or lower
    jne    novga    
    call    chsvga  ! 子函数,过程比较简单,但是读取的可能配置比较多
novga:    mov    [14],ax
    mov    ah,#0x03    ! read cursor pos
    xor    bh,bh        ! clear bh
    int    0x10        ! save it in known place, con_init fetches
    mov    [0],dx        ! it from 0x90000.
    
! Get video-card data:
! 获取显卡数据
    
    mov    ah,#0x0f
    int    0x10
    mov    [4],bx        ! bh = display page
    mov    [6],ax        ! al = video mode, ah = window width

! Get hd0 data
! 获取第一个硬盘数据

    xor    ax,ax        ! clear ax
    mov    ds,ax
    lds    si,[4*0x41]
    mov    ax,#INITSEG
    mov    es,ax
    mov    di,#0x0080
    mov    cx,#0x10
    cld
    rep
    movsb

! Get hd1 data
! 获取第二个硬盘数据

    xor    ax,ax        ! clear ax
    mov    ds,ax
    lds    si,[4*0x46]
    mov    ax,#INITSEG
    mov    es,ax
    mov    di,#0x0090
    mov    cx,#0x10
    cld
    rep
    movsb

! Check that there IS a hd1 :-)
! 检测硬盘数量
    mov    ax,#0x01500
    mov    dl,#0x81
    int    0x13
    jc    no_disk1
    cmp    ah,#3
    je    is_disk1
no_disk1:           ! 没有第二块硬盘的处理
    mov    ax,#INITSEG
    mov    es,ax
    mov    di,#0x0090
    mov    cx,#0x10
    xor    ax,ax        ! clear ax
    cld
    rep
    stosb
is_disk1:

! check for PS/2 pointing device
! 检测PS/2设备,应该是鼠标
    mov    ax,#INITSEG
    mov    ds,ax
    mov    [0x1ff],#0    ! default is no pointing device
    int    0x11        ! int 0x11: equipment determination
    test    al,#0x04    ! check if pointing device installed
    jz    no_psmouse
    mov    [0x1ff],#0xaa    ! device present
no_psmouse:
! now we want to move to protected mode ...
! 准备进入保护模式
    cli            ! no interrupts allowed !
    mov    al,#0x80    ! disable NMI for the bootup sequence
    out    #0x70,al

! first we move the system to its rightful place
! 首先我们移动system到正确的位置
    mov    ax,#0x100    ! start of destination segment
    mov    bx,#0x1000    ! start of source segment
    cld            ! ‘direction‘=0, movs moves forward
do_move:            ! 上面是初始化,下面开始移动
    mov    es,ax        ! destination segment
    add    ax,#0x100
    cmp    ax,#0x9000
    jz    end_move
    mov    ds,bx        ! source segment
    add    bx,#0x100
    sub    di,di
    sub    si,si
    mov     cx,#0x800
    rep
    movsw
    jmp    do_move

! then we load the segment descriptors
! 移动完毕,我们加载段描述符

end_move:
    mov    ax,#SETUPSEG    ! right, forgot this at first. didn‘t work :-)
    mov    ds,ax
    ! 加载idt
    lidt    idt_48        ! load idt with 0,0   
    ! 加载gdt
    lgdt    gdt_48        ! load gdt with whatever appropriate

! that was painless, now we enable A20
! 设置完毕,我们现在准备打开A20地址线

    call    empty_8042
    mov    al,#0xD1        ! command write
    out    #0x64,al
    call    empty_8042
    mov    al,#0xDF        ! A20 on
    out    #0x60,al
    call    empty_8042

! make sure any possible coprocessor is properly reset..
! 确保处理器正确设置

    xor    ax,ax
    out    #0xf0,al
    call    delay
    out    #0xf1,al
    call    delay

! well, that went ok, I hope. Now we have to reprogram the interrupts :-(
! we put them right after the intel-reserved hardware interrupts, at
! int 0x20-0x2F. There they won‘t mess up anything. Sadly IBM really
! messed this up with the original PC, and they haven‘t been able to
! rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f,
! which is used for the internal hardware interrupts as well. We just
! have to reprogram the 8259‘s, and it isn‘t fun.

! 重新设置中断
    mov    al,#0x11        ! initialization sequence
    out    #0x20,al        ! send it to 8259A-1
    call    delay
    out    #0xA0,al        ! and to 8259A-2
    call    delay
    mov    al,#0x20        ! start of hardware int‘s (0x20)
    out    #0x21,al
    call    delay
    mov    al,#0x28        ! start of hardware int‘s 2 (0x28)
    out    #0xA1,al
    call    delay
    mov    al,#0x04        ! 8259-1 is master
    out    #0x21,al
    call    delay
    mov    al,#0x02        ! 8259-2 is slave
    out    #0xA1,al
    call    delay
    mov    al,#0x01        ! 8086 mode for both
    out    #0x21,al
    call    delay
    out    #0xA1,al
    call    delay
    mov    al,#0xFF        ! mask off all interrupts for now
    out    #0xA1,al
    call    delay
    mov    al,#0xFB        ! mask all irq‘s but irq2 which
    out    #0x21,al        ! is cascaded

! well, that certainly wasn‘t fun :-(. Hopefully it works, and we don‘t
! need no steenking BIOS anyway (except for the initial loading :-).
! The BIOS-routine wants lots of unnecessary data, and it‘s less
! "interesting" anyway. This is how REAL programmers do it.
!
! Well, now‘s the time to actually move into protected mode. To make
! things as simple as possible, we do no register set-up or anything,
! we let the gnu-compiled 32-bit programs do that. We just jump to
! absolute address 0x00000, in 32-bit protected mode.
!
! Note that the short jump isn‘t strictly needed, althought there are
! reasons why it might be a good idea. It won‘t hurt in any case.
!
! 打开地址线,进入保护模式
    mov    ax,#0x0001    ! protected mode (PE) bit
    lmsw    ax        ! This is it!
    jmp    flush_instr
flush_instr:
    jmpi    0x1000,KERNEL_CS    ! jmp offset 1000 of segment 0x10 (cs)
    ! 跳转到cs段的偏移为0x1000处执行,即执行zBoot/head.s

! This routine checks that the keyboard command queue is empty
! (after emptying the output buffers)
!
! No timeout is used - if this hangs there is something wrong with
! the machine, and we probably couldn‘t proceed anyway.
empty_8042:
    call    delay
    in    al,#0x64    ! 8042 status port
    test    al,#1        ! output buffer?
    jz    no_output
    call    delay
    in    al,#0x60    ! read it
    jmp    empty_8042
no_output:
    test    al,#2        ! is input buffer full?
    jnz    empty_8042    ! yes - loop
    ret
!
! Read a key and return the (US-)ascii code in al, scan code in ah
!
getkey:
    xor    ah,ah
    int    0x16
    ret

!
! Read a key with a timeout of 30 seconds. The cmos clock is used to get
! the time.
!
getkt:
    call    gettime
    add    al,#30        ! wait 30 seconds
    cmp    al,#60
    jl    lminute
    sub    al,#60
lminute:
    mov    cl,al
again:    mov    ah,#0x01
    int    0x16
    jnz    getkey        ! key pressed, so get it
    call    gettime
    cmp    al,cl
    jne    again
    mov    al,#0x20    ! timeout, return default char `space‘
    ret

!
! Flush the keyboard buffer
!
flush:    mov    ah,#0x01
    int    0x16
    jz    empty
    xor    ah,ah
    int    0x16
    jmp    flush
empty:    ret

!
! Read the cmos clock. Return the seconds in al
!
gettime:
    push    cx
    mov    ah,#0x02
    int    0x1a
    mov    al,dh            ! dh contains the seconds
    and    al,#0x0f
    mov    ah,dh
    mov    cl,#0x04
    shr    ah,cl
    aad
    pop    cx
    ret

!
! Delay is needed after doing i/o
!
delay:
    .word    0x00eb            ! jmp $+2
    ret

! Routine trying to recognize type of SVGA-board present (if any)
! and if it recognize one gives the choices of resolution it offers.
! If one is found the resolution chosen is given by al,ah (rows,cols).

chsvga:    cld
    push    ds
    push    cs
    mov    ax,[0x01fa]
    pop    ds
    mov    modesave,ax
    mov     ax,#0xc000
    mov    es,ax
    mov    ax,modesave
    cmp    ax,#NORMAL_VGA
    je    defvga
    cmp    ax,#EXTENDED_VGA
    je    vga50
    cmp    ax,#ASK_VGA
    jne    svga
    lea    si,msg1
    call    prtstr
    call    flush
nokey:    call    getkt
    cmp    al,#0x0d        ! enter ?
    je    svga            ! yes - svga selection
    cmp    al,#0x20        ! space ?
    je    defvga            ! no - repeat
    call     beep
    jmp    nokey
defvga:    mov    ax,#0x5019
    pop    ds
    ret
/* extended vga mode: 80x50 */
vga50:
    mov    ax,#0x1112
    xor    bl,bl
    int    0x10        ! use 8x8 font set (50 lines on VGA)
    mov    ax,#0x1200
    mov    bl,#0x20
    int    0x10        ! use alternate print screen
    mov    ax,#0x1201
    mov    bl,#0x34
    int    0x10        ! turn off cursor emulation
    mov    ah,#0x01
    mov    cx,#0x0607
    int    0x10        ! turn on cursor (scan lines 6 to 7)
    pop    ds
    mov    ax,#0x5032    ! return 80x50
    ret
/* extended vga mode: 80x28 */
vga28:
    pop    ax        ! clean the stack
    mov    ax,#0x1111
    xor    bl,bl
    int    0x10        ! use 9x14 fontset (28 lines on VGA)
    mov    ah, #0x01
    mov    cx,#0x0b0c
    int    0x10        ! turn on cursor (scan lines 11 to 12)
    pop    ds
    mov    ax,#0x501c    ! return 80x28
    ret
/* svga modes */
svga:   cld
        lea     si,id9GXE    ! Check for the #9GXE (jyanowit@orixa.mtholyoke.edu,thanks dlm40629@uxa.cso.uiuc.edu)
        mov     di,#0x49    ! id string is at c000:049
        mov     cx,#0x11    ! length of "Graphics Power By"
        repe
        cmpsb
        jne     of1280
is9GXE:    lea     si,dsc9GXE    ! table of descriptions of video modes for BIOS
    lea    di,mo9GXE    ! table of sizes of video modes for my BIOS
    br    selmod        ! go ask for video mode
of1280:    cld    
    lea    si,idf1280    ! Check for Orchid F1280 (dingbat@diku.dk)
    mov    di,#0x10a    ! id string is at c000:010a
    mov    cx,#0x21    ! length
    repe
    cmpsb
    jne    nf1280    
isVRAM:    lea    si,dscf1280
    lea    di,mof1280
    br    selmod
nf1280:    lea    si,idVRAM
    mov    di,#0x10a
    mov    cx,#0x0c
    repe
    cmpsb
    je    isVRAM
    cld
    lea     si,idati        ! Check ATI ‘clues‘
    mov    di,#0x31
    mov     cx,#0x09
    repe
    cmpsb
    jne    noati
    lea    si,dscati
    lea    di,moati
    br    selmod
noati:    mov    ax,#0x200f        ! Check Ahead ‘clues‘
    mov    dx,#0x3ce
    out    dx,ax
    inc    dx
    in    al,dx
    cmp    al,#0x20
    je    isahed
    cmp    al,#0x21
    jne    noahed
isahed:    lea    si,dscahead
    lea    di,moahead
    br    selmod
noahed:    mov    dx,#0x3c3        ! Check Chips & Tech. ‘clues‘
    in    al,dx
    or    al,#0x10
    out    dx,al
    mov    dx,#0x104        
    in    al,dx
    mov    bl,al
    mov    dx,#0x3c3
    in    al,dx
    and    al,#0xef
    out    dx,al
    cmp    bl,[idcandt]
    jne    nocant
    lea    si,dsccandt
    lea    di,mocandt
    br    selmod
nocant:    mov    dx,#0x3d4        ! Check Cirrus ‘clues‘
    mov    al,#0x0c
    out    dx,al
    inc    dx
    in    al,dx
    mov    bl,al
    xor    al,al
    out    dx,al
    dec    dx
    mov    al,#0x1f
    out    dx,al
    inc    dx
    in    al,dx
    mov    bh,al
    xor    ah,ah
    shl    al,#4
    mov    cx,ax
    mov    al,bh
    shr    al,#4
    add    cx,ax
    shl    cx,#8
    add    cx,#6
    mov    ax,cx
    mov    dx,#0x3c4
    out    dx,ax
    inc    dx
    in    al,dx
    and    al,al
    jnz    nocirr
    mov    al,bh
    out    dx,al
    in    al,dx
    cmp    al,#0x01
    jne    nocirr
    call    rst3d4    
    lea    si,dsccirrus
    lea    di,mocirrus
    br    selmod
rst3d4:    mov    dx,#0x3d4
    mov    al,bl
    xor    ah,ah
    shl    ax,#8
    add    ax,#0x0c
    out    dx,ax
    ret    
nocirr:    call    rst3d4            ! Check Everex ‘clues‘
    mov    ax,#0x7000
    xor    bx,bx
    int    0x10
    cmp    al,#0x70
    jne    noevrx
    shr    dx,#4
    cmp    dx,#0x678
    je    istrid
    cmp    dx,#0x236
    je    istrid
    lea    si,dsceverex
    lea    di,moeverex
    br    selmod
istrid:    lea    cx,ev2tri
    jmp    cx
noevrx:    lea    si,idgenoa        ! Check Genoa ‘clues‘
    xor     ax,ax
    seg es
    mov    al,[0x37]
    mov    di,ax
    mov    cx,#0x04
    dec    si
    dec    di
l1:    inc    si
    inc    di
    mov    al,(si)
    test    al,al
    jz    l2
    seg es
    cmp    al,(di)
l2:    loope     l1
    cmp    cx,#0x00
    jne    nogen
    lea    si,dscgenoa
    lea    di,mogenoa
    br    selmod
nogen:    cld
    lea    si,idoakvga
    mov    di,#0x08
    mov    cx,#0x08
    repe
    cmpsb
    jne    nooak
    lea    si,dscoakvga
    lea    di,mooakvga
    br    selmod
nooak:    cld
    lea    si,idparadise        ! Check Paradise ‘clues‘
    mov    di,#0x7d
    mov    cx,#0x04
    repe
    cmpsb
    jne    nopara
    lea    si,dscparadise
    lea    di,moparadise
    br    selmod
nopara:    mov    dx,#0x3c4        ! Check Trident ‘clues‘
    mov    al,#0x0e
    out    dx,al
    inc    dx
    in    al,dx
    xchg    ah,al
    xor    al,al
    out    dx,al
    in    al,dx
    xchg    al,ah
    mov    bl,al        ! Strange thing ... in the book this wasn‘t
    and    bl,#0x02    ! necessary but it worked on my card which
    jz    setb2        ! is a trident. Without it the screen goes
    and    al,#0xfd    ! blurred ...
    jmp    clrb2        !
setb2:    or    al,#0x02    !
clrb2:    out    dx,al
    and    ah,#0x0f
    cmp    ah,#0x02
    jne    notrid
ev2tri:    lea    si,dsctrident
    lea    di,motrident
    jmp    selmod
notrid:    mov    dx,#0x3cd        ! Check Tseng ‘clues‘
    in    al,dx            ! Could things be this simple ! :-)
    mov    bl,al
    mov    al,#0x55
    out    dx,al
    in    al,dx
    mov    ah,al
    mov    al,bl
    out    dx,al
    cmp    ah,#0x55
     jne    notsen
    lea    si,dsctseng
    lea    di,motseng
    jmp    selmod
notsen:    mov    dx,#0x3cc        ! Check Video7 ‘clues‘
    in    al,dx
    mov    dx,#0x3b4
    and    al,#0x01
    jz    even7
    mov    dx,#0x3d4
even7:    mov    al,#0x0c
    out    dx,al
    inc    dx
    in    al,dx
    mov    bl,al
    mov    al,#0x55
    out    dx,al
    in    al,dx
    dec    dx
    mov    al,#0x1f
    out    dx,al
    inc    dx
    in    al,dx
    mov    bh,al
    dec    dx
    mov    al,#0x0c
    out    dx,al
    inc    dx
    mov    al,bl
    out    dx,al
    mov    al,#0x55
    xor    al,#0xea
    cmp    al,bh
    jne    novid7
    lea    si,dscvideo7
    lea    di,movideo7
    jmp    selmod
novid7:    lea    si,dsunknown
    lea    di,mounknown
selmod:    xor    cx,cx
    mov    cl,(di)
    mov    ax,modesave
    cmp    ax,#ASK_VGA
    je    askmod
    cmp    ax,#NORMAL_VGA
    je    askmod
    cmp    al,cl
    jl    gotmode
    push    si
    lea    si,msg4
    call    prtstr
    pop    si
askmod:    push    si
    lea    si,msg2
    call    prtstr
    pop    si
    push    si
    push    cx
tbl:    pop    bx
    push    bx
    mov    al,bl
    sub    al,cl
    call    modepr
    lodsw
    xchg    al,ah
    call    dprnt
    xchg    ah,al
    push    ax
    mov    al,#0x78
    call    prnt1
    pop    ax
    call    dprnt
    push    si
    lea    si,crlf        ! print CR+LF
    call    prtstr
    pop    si
    loop    tbl
    pop    cx
    lea    si,msg3
    call    prtstr
    pop    si
    add    cl,#0x30
    jmp    nonum
nonumb:    call    beep
nonum:    call    getkey
    cmp    al,#0x30    ! ascii `0‘
    jb    nonumb
    cmp    al,#0x3a    ! ascii `9‘
    jbe    number
    cmp    al,#0x61    ! ascii `a‘
    jb    nonumb
    cmp    al,#0x7a    ! ascii `z‘
    ja    nonumb
    sub    al,#0x27
    cmp    al,cl
    jae    nonumb
    sub    al,#0x30
    jmp    gotmode
number: cmp    al,cl
    jae    nonumb
    sub    al,#0x30
gotmode:    xor    ah,ah
    or    al,al
    beq    vga50
    push    ax
    dec    ax
    beq    vga28
    add    di,ax
    mov    al,(di)
    int     0x10
    pop    ax
    shl    ax,#1
    add    si,ax
    lodsw
    pop    ds
    ret

! Routine to print asciiz-string at DS:SI

prtstr:    lodsb
    and    al,al
    jz    fin
    call    prnt1
    jmp    prtstr
fin:    ret

! Routine to print a decimal value on screen, the value to be
! printed is put in al (i.e 0-255).

dprnt:    push    ax
    push    cx
    xor    ah,ah        ! Clear ah
    mov    cl,#0x0a
    idiv    cl
    cmp    al,#0x09
    jbe    lt100
    call    dprnt
    jmp    skip10
lt100:    add    al,#0x30
    call    prnt1
skip10:    mov    al,ah
    add    al,#0x30
    call    prnt1    
    pop    cx
    pop    ax
    ret

!
! Routine to print the mode number key on screen. Mode numbers
! 0-9 print the ascii values `0‘ to ‘9‘, 10-35 are represented by
! the letters `a‘ to `z‘. This routine prints some spaces around the
! mode no.
!

modepr:    push    ax
    cmp    al,#0x0a
    jb    digit        ! Here is no check for number > 35
    add    al,#0x27
digit:    add    al,#0x30
    mov    modenr, al
    push     si
    lea    si, modestring
    call    prtstr
    pop    si
    pop    ax
    ret

! Part of above routine, this one just prints ascii al

prnt1:    push    ax
    push    cx
    xor    bh,bh
    mov    cx,#0x01
    mov    ah,#0x0e
    int    0x10
    pop    cx
    pop    ax
    ret

beep:    mov    al,#0x07
    jmp    prnt1
    
gdt:
    .word    0,0,0,0        ! dummy

    .word    0,0,0,0        ! unused

    .word    0x07FF        ! 8Mb - limit=2047 (2048*4096=8Mb)
    .word    0x0000        ! base address=0
    .word    0x9A00        ! code read/exec
    .word    0x00C0        ! granularity=4096, 386

    .word    0x07FF        ! 8Mb - limit=2047 (2048*4096=8Mb)
    .word    0x0000        ! base address=0
    .word    0x9200        ! data read/write
    .word    0x00C0        ! granularity=4096, 386

idt_48:
    .word    0            ! idt limit=0
    .word    0,0            ! idt base=0L

gdt_48:
    .word    0x800        ! gdt limit=2048, 256 GDT entries
    .word    512+gdt,0x9    ! gdt base = 0X9xxxx

msg1:        .ascii    "Press <RETURN> to see SVGA-modes available, <SPACE> to continue or wait 30 secs."
        db    0x0d, 0x0a, 0x0a, 0x00
msg2:        .ascii    "Mode:  COLSxROWS:"
        db    0x0d, 0x0a, 0x0a, 0x00
msg3:        db    0x0d, 0x0a
        .ascii    "Choose mode by pressing the corresponding number or letter."
crlf:        db    0x0d, 0x0a, 0x00
msg4:        .ascii    "You passed an undefined mode number to setup. Please choose a new mode."
        db    0x0d, 0x0a, 0x0a, 0x07, 0x00
modestring:    .ascii    "   "
modenr:        db    0x00    ! mode number
        .ascii    ":    "
        db    0x00
        
idati:        .ascii    "761295520"
idcandt:    .byte    0xa5
idgenoa:    .byte    0x77, 0x00, 0x99, 0x66
idparadise:    .ascii    "VGA="
idoakvga:    .ascii  "OAK VGA "
idf1280:    .ascii    "Orchid Technology Fahrenheit 1280"
id9GXE:        .ascii  "Graphics Power By"
idVRAM:        .ascii    "Stealth VRAM"

! Manufacturer:      Numofmodes+2:    Mode:
! Number of modes is the number of chip-specific svga modes plus the extended
! modes available on any vga (currently 2)

moati:        .byte    0x04,    0x23, 0x33
moahead:    .byte    0x07,    0x22, 0x23, 0x24, 0x2f, 0x34
mocandt:    .byte    0x04,    0x60, 0x61
mocirrus:    .byte    0x06,    0x1f, 0x20, 0x22, 0x31
moeverex:    .byte    0x0c,    0x03, 0x04, 0x07, 0x08, 0x0a, 0x0b, 0x16, 0x18, 0x21, 0x40
mogenoa:    .byte    0x0c,    0x58, 0x5a, 0x60, 0x61, 0x62, 0x63, 0x64, 0x72, 0x74, 0x78
moparadise:    .byte    0x04,    0x55, 0x54
motrident:    .byte    0x09,    0x50, 0x51, 0x52, 0x57, 0x58, 0x59, 0x5a
motseng:    .byte    0x07,    0x26, 0x2a, 0x23, 0x24, 0x22
movideo7:    .byte    0x08,    0x40, 0x43, 0x44, 0x41, 0x42, 0x45
mooakvga:    .byte   0x08,   0x00, 0x07, 0x4e, 0x4f, 0x50, 0x51
mo9GXE:        .byte    0x04,    0x54, 0x55
mof1280:    .byte    0x04,    0x54, 0x55
mounknown:    .byte    0x02

!            msb = Cols lsb = Rows:
! The first two modes are standard vga modes available on any vga.
! mode 0 is 80x50 and mode 1 is 80x28

dscati:        .word    0x5032, 0x501c, 0x8419, 0x842c
dscahead:    .word    0x5032, 0x501c, 0x842c, 0x8419, 0x841c, 0xa032, 0x5042
dsccandt:    .word    0x5032, 0x501c, 0x8419, 0x8432
dsccirrus:    .word    0x5032, 0x501c, 0x8419, 0x842c, 0x841e, 0x6425
dsceverex:    .word    0x5032, 0x501c, 0x5022, 0x503c, 0x642b, 0x644b, 0x8419, 0x842c, 0x501e, 0x641b, 0xa040, 0x841e
dscgenoa:    .word    0x5032, 0x501c, 0x5020, 0x642a, 0x8419, 0x841d, 0x8420, 0x842c, 0x843c, 0x503c, 0x5042, 0x644b
dscparadise:    .word    0x5032, 0x501c, 0x8419, 0x842b
dsctrident:    .word     0x5032, 0x501c, 0x501e, 0x502b, 0x503c, 0x8419, 0x841e, 0x842b, 0x843c
dsctseng:    .word    0x5032, 0x501c, 0x503c, 0x6428, 0x8419, 0x841c, 0x842c
dscvideo7:    .word    0x5032, 0x501c, 0x502b, 0x503c, 0x643c, 0x8419, 0x842c, 0x841c
dscoakvga:    .word   0x5032, 0x501c, 0x2819, 0x5019, 0x503c, 0x843c, 0x8419, 0x842b
dscf1280:    .word    0x5032, 0x501c, 0x842b, 0x8419
dsc9GXE:    .word    0x5032, 0x501c, 0x842b, 0x8419
dsunknown:    .word    0x5032, 0x501c
modesave:    .word    SVGA_MODE

    
.text
endtext:
.data
enddata:
.bss
endbss: