📄 biosinit.a86
字号:
DOSUpperMemoryRoot:
;------------------
les bx,cs:drdos_ptr
mov es:DRDOS_DMD_UPPER[bx],dx ; remember upper memory link
if DOS5
les bx,cs:func52_ptr
mov es:F52_DMD_UPPER[bx],dx ; remember upper memory link
endif
xor ax,ax
retf 2
HMAAlloc:
;--------
; On Entry:
; BX = # bytes to allocate
; On Exit:
; ES:DI -> start of allocated block
; BX trashed
;
push ds
push ax
push cx
push dx
push si
push bp
push cs ! pop ds ; establish data seg
mov cx,bx ; CX = bytes wanted
mov dx,0FFFFh ; anywhere is OK
call AllocHMA ; ES:DI -> allocated data
pop bp
pop si
pop dx
pop cx
pop ax
pop ds
iret
HMAQueryFree:
;------------
; On Entry:
; None
; On Exit:
; BX = Size of block remaining (0 if no HMA)
; ES:DI -> start of available HMA (FFFF:FFFF if no HMA)
;
push ds
push ax
push cx
push dx
push si
push bp
push cs ! pop ds ; establish data seg
call SetupHMA ; allocate the HMA for OS use
les bx,cs:drdos_ptr
mov di,es:DRDOS_HIMEM_ROOT[bx]
mov ax,0FFFFh ; get offset of HMA entry
mov es,ax
test di,di ; do we have a himem root ?
jz HMAQueryFree10 ; no, return failure
mov bx,es:2[di] ; BX = size of region
mov ax,di ; para align the base
add ax,15 ; because the allocation will
and ax,not 15
sub ax,di ; AX bytes left in the para
add di,ax ; bias the starting location
sub bx,ax ; that many less available
ja HMAQueryFree20 ; if non-zero, return it
HMAQueryFree10:
xor bx,bx ; BX = zero on failure
mov di,0FFFFh ; ES:DI -> FFFF:FFFF
HMAQueryFree20:
pop bp
pop si
pop dx
pop cx
pop ax
pop ds
iret
Public AllocHMA
AllocHMA:
;--------
; On Entry:
; CX = bytes to allocate
; DX = offset of allocation
; On Exit:
; CY set if no can do and ES:DI = FFFF:FFFF
; else
; ES:DI -> memory allocated (para aligned)
; CX preserved
; DX = segment to fixup
;
les bx,cs:drdos_ptr
mov di,es:DRDOS_HIMEM_ROOT[bx]
test di,di ; have we a HIMEM chain ?
jz AllocHMA20
cmp di,dx ; low enough for us
ja AllocHMA20
mov ax,0FFFFh ; relocate to magic segment
mov es,ax ; lets examine high memory
mov ax,es:2[di] ; get size of himem entry
mov si,es:[di] ; and get himem link
mov bx,di
add bx,15
and bx,not 15 ; BX is now para aligned
sub bx,di ; BX is bytes left in para
sub ax,bx ; so we only have this much
jc AllocHMA20 ; less than a para ?
add di,15 ; para align the base, dropping
and di,not 15 ; non-aligned bit on floor
cmp ax,cx ; is himem entry big enough ?
jb AllocHMA20 ; no, allocate from 1st MByte
je AllocHMA10 ; just made it!
sub ax,cx ; how much is left
cmp ax,2*WORD ; is it to small to keep ?
jb AllocHMA10 ; no, discard the remainder
mov bx,di ; point to new entry
add bx,cx ; this many byte up
mov es:[bx],si ; fill in link field
mov es:2[bx],ax ; and length
mov si,bx ; make this new root
AllocHMA10:
push cx ; save length of CODE
push dx ; and offset of CODE
les bx,cs:drdos_ptr
mov es:DRDOS_HIMEM_ROOT[bx],si
pop ax ; AX = offset of CODE
mov cl,4
shr ax,cl ; make it paras
mov dx,0ffffh
mov es,dx ; ES:DI -> destination of CODE
mov dx,di
mov cl,4
shr dx,cl ; DX = offset from FFFF in para's
dec dx ; DX = offset from 10000
sub dx,ax ; DX = fixup segment
pop cx ; CX = bytes to move
clc ; made it!
ret
AllocHMA20:
mov di,0FFFFh ; set ES:DI = FFFF:FFFF
mov es,di
stc ; can't do it
ret
Public SetupHMA
SetupHMA:
;--------
; We have a client for the high memory area at segment FFFF
; We should try and setup a high memory free chain
; XMS only supports allocation of the complete area, so try and grab
; it all and do our own sub-allocations within it.
;
push es
les bx,cs:drdos_ptr
cmp es:DRDOS_HIMEM_ROOT[bx],0; do we already have a chain ?
jnz SetupHMA10 ; if so skip XMS allocation
mov ax,4300h ; check for XMS installation
int 2fh
cmp al,80h
jne SetupHMA20
mov ax,4310h ; get address of XMS driver
int 2fh
mov word ptr xms_driver,bx
mov word ptr xms_driver+2,es
mov ah,0 ; version number check
callf xms_driver
cmp dx,1 ; does HiMem exist ?
jne SetupHMA20
mov ah,1 ; allocate whole HiMem
mov dx,0ffffh
callf xms_driver
cmp ax,1 ; did we succeed ?
jne SetupHMA20
mov ah,3 ; enable a20 gate
callf xms_driver
cmp ax,1 ; did we succeed ?
jne SetupHMA20
les bx,cs:drdos_ptr
mov es:DRDOS_HIMEM_ROOT[bx],COMMAND_BASE
mov ax,0FFFFh ; one entry of FFF0 bytes covers
mov es,ax ; the complete HMA
inc ax
mov es:word ptr .COMMAND_BASE,ax
mov es:word ptr .COMMAND_BASE+2,-COMMAND_BASE
mov di,10h ; copy a dummy VDISK header
mov si,offset dummyVDISK
mov cx,10h
rep movsw ; copy up 0x20 bytes
push ds ; now fixup JMPF in hi-memory for CALL5
mov ds,ax ; link for PC-NFS
mov si,4*30h ; DS:SI -> Int 30 vector
lea di,10h[si] ; ES:DI -> himem alias
movsw ! movsw ! movsb ; copy the JMPF
pop ds
SetupHMA10:
les bx,cs:drdos_ptr ; private data area in ES:BX
mov dx,COMMAND_BASE
cmp dx,es:DRDOS_HIMEM_ROOT[bx]
jne SetupHMA20 ; should we be reserving space for OS?
mov cx,systemSize ; we should reserve this much
call ReserveHMA ; for the OS in the HMA
jc SetupHMA20
mov systemHMA,ax ; save for re-use
SetupHMA20:
pop es
ret
Public alloc_instseg
alloc_instseg:
; allocate AX paragraphs for data that will have to be instanced during
; multitasking. if Vladivar kernel available ask that, or else just
; try for normal upper memory
push ax
push bx ; save registers
push cx
mov cx,F_Version ; is the multi-tasker loaded ?
mov ax,OS386_FUNC
int OS386_INT
int 2Fh ; check for Vladivar
test cx,cx ; CX=0 if it's there
pop cx
pop bx
pop ax
jnz alloc_hiseg ; no, allocate normally
push ax
push bx
push cx
push dx
mov dx,ax ; DX = paragraphs required
mov cx,F_RealAllocI ; ask nicely for memory
mov ax,OS386_FUNC
int OS386_INT
pop dx
pop cx
pop bx
jc alloc_intseg10 ; did we get any ?
add sp,WORD
clc ; we've done it !!
ret
alloc_intseg10:
pop ax ; we didn't manage it...
; jmp alloc_hiseg
Public alloc_hiseg
alloc_hiseg:
; allocate AX paragraphs in high memory if possible, otherwise allocate
; it in conventional memory
cmp hidos,0 ; do we want to relocate DOS ?
je alloc_seg ; no, allocate conventionally
call alloc_upper ; try to allocate some upper memory
jc alloc_seg ; can't, so allocate conventional
ret ; else return address of allocated mem
alloc_seg_with_padding:
; On Entry:
; AX = para's required
; DX = minimum acceptable offset
; On Exit:
; AX = base para
;
; If gate A20 is enabled we can't use negative offset's for DOS/BIOS so
; we pad conventional memory to avoid this. Avoid seg=0 while here.
push cx
push dx
add dx,15+16 ; DX is the offset we will be using
mov cl,4 ; so make sure base is high enough
shr dx,cl ; convert "offset" to a segment value
cmp dx,mem_current ; make sure we don't generate a
jbe alloc_seg_nopad ; negative segement value as this
mov mem_current,dx ; will crash if a20 enabled
alloc_seg_nopad: ; pad if necessary
mov dl,'M' ; allocate for DOS
call alloc_seg ; now we can allocate OK
pop dx
pop cx
ret
Public alloc_seg
alloc_seg:
;---------
; On Entry:
; AX = para's required
; DL = subsegment type
; On Exit:
; AX = base para
;
push ds
push cx
mov cx,ax ; remember how much was wanted
inc ax ; allow an extra para for a header
add ax,mem_current ; Return a pointer to AX paragraphs
cmp ax,mem_max ; of memory to the calling routine.
jae alloc_s10
xchg ax,mem_current
mov ds,ax ; DS:0 -> header
inc ax ; AX:0 -> buffer
mov ds:DMD_ID,dl ; remember the type
mov ds:DMD_PSP,ax ; owner = itself
mov ds:DMD_LEN,cx ; size in para
xor cx,cx ; zero rest for cosmetic reasons
mov ds:word ptr DMD_NAME-3,cx
mov ds:word ptr DMD_NAME-2,cx
mov ds:word ptr DMD_NAME,'S'+256*'D'
mov ds:word ptr DMD_NAME+2,cx
mov ds:word ptr DMD_NAME+4,cx
mov ds:word ptr DMD_NAME+6,cx
pop cx
pop ds
ret
alloc_s10:
hlt ; ##jc##
jmps alloc_s10
alloc_upper:
;-----------
; On Entry:
; AX = paragraphs required
; On Exit:
; CY clear: AX = paragraphs address of allocated memory
; CY set: cannot allocate memory (All regs preserved)
;
push bx
push ax ; save para required
cmp himem_base,0 ; we have already allocated some ?
je alloc_upper10 ; nothing to grow, allocate new block
mov bx,himem_size ; himem was this big
add bx,ax ; try and extend it
push es
mov es,himem_base ; point at existing himem
mov ah,MS_M_SETBLOCK ; and try and set to new size
int DOS_INT
pop es
jc alloc_upper10 ; can't grow, so allocate new block
mov ax,himem_base
add ax,himem_size ; return seg above old alloc
pop bx ; recover para required
add himem_size,bx ; add into himem size
pop bx
clc ; success..
ret ; return AX = seg
alloc_upper10:
mov ax,(MS_M_STRATEGY*256)+1; set allocation strategy
mov bl,41h ; to best fit, high only
int DOS_INT
pop bx ! push bx ; recover para required in BX
mov ah, MS_M_ALLOC ; and try to allocate them
int DOS_INT
pushf ! push ax ; save CF and possible address
mov ax,(MS_M_STRATEGY*256)+1; set allocation strategy
mov bl,0 ; to first fit
int DOS_INT
pop ax ! popf ; restore CF and possible address
jc alloc_upper20 ; can't allocate, use conventional
cmp ax,mem_size ; is it from upper memory ?
ja alloc_upper15 ; yes, we can use it
push es ; it's conventional, free it up
mov es,ax ; seg address in ES
mov ah,MS_M_FREE
int DOS_INT ; free up this memory
pop es
jmps alloc_upper20 ; try again with XMS
alloc_upper15:
mov himem_base,ax ; save base value
pop himem_size ; save size
pop bx ; and return seg in AX
clc ; success..
ret
alloc_upper20:
pop ax
pop bx ; restore regs
push ds ! push es
push bx ! push cx ! push dx ! push si ! push di ! push bp
push ax ; save allocation size
mov ax,4300h ; check for XMS installation
int 2fh
cmp al,80h
jne alloc_upper30
mov ax,4310h ; get address of XMS driver
int 2fh
mov word ptr xms_driver,bx
mov word ptr xms_driver+2,es
pop dx ! push dx ; DX = allocation size
mov ah,10h ; allocate upper memory block
callf xms_driver
cmp ax,1 ; did we succeed ?
jne alloc_upper30
pop ax ; recover allocation size
mov ax,bx ; return para address of himem
pop bp ! pop di ! pop si ! pop dx ! pop cx ! pop bx
pop es ! pop ds
clc ; success
ret
alloc_upper30:
pop ax ; recover allocation size
pop bp ! pop di ! pop si ! pop dx ! pop cx ! pop bx
pop es ! pop ds
stc ; failure....
ret
mark_system_memory:
;------------------
; ensure any memory we have allocated is owned by PSP 0008, a magic value
; used to indicate system memory
push es
les bx,func52_ptr ; get internal data in ES:BX
mov es,es:F52_DMDROOT[bx] ; get 1st DMD entry
mov ah,MS_P_GETPSP
int DOS_INT ; get our PSP in BX
mark_sm10:
cmp es:DMD_ID,'M'
je mark_sm20 ; check we have a valid DMD
cmp es:DMD_ID,'Z'
jne mark_sm50 ; stop if we don't
mark_sm20:
cmp bx,es:DMD_PSP ; is it ours ??
jne mark_sm30
mov es:DMD_PSP,0008 ; mark as system
mark_sm30:
cmp es:DMD_PSP,0008 ; if system mark as SC
jne mark_sm40
xor ax,ax ; zero rest for cosmetic reasons
mov ds:word ptr DMD_NAME-3,ax
mov ds:word ptr DMD_NAME-2,ax
mov ds:word ptr DMD_NAME,'S'+256*'C'
mov ds:word ptr DMD_NAME+2,ax
mov ds:word ptr DMD_NAME+4,ax
mov ds:word ptr DMD_NAME+6,ax
mark_sm40:
cmp es:DMD_ID,'Z' ; is it the last DMD ?
je mark_sm50 ; then stop
mov ax,es
inc ax ; skip DMD header and add
add ax,DMD_LEN ; length to find next DMD
mov es,ax
jmps mark_sm10 ; now go and look at that
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -