?? 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.
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
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
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
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
lidt idt_48 ! load idt with 0,0
lgdt gdt_48 ! load gdt with whatever appropriate
! that was painless, now we enable 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)
! 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
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -