4142 lines
116 KiB
NASM
4142 lines
116 KiB
NASM
PAGE ,132
|
|
TITLE Windows Protect Mode Routines
|
|
|
|
.list
|
|
include kernel.inc
|
|
include protect.inc
|
|
include pdb.inc
|
|
include newexe.inc
|
|
.list
|
|
|
|
.286p
|
|
|
|
ifdef WOW
|
|
|
|
;
|
|
; the dpmi func 04f1h is idential to function 00h, except that
|
|
; the descriptor base and limit are not initialized to zero.
|
|
;
|
|
|
|
;
|
|
; the dpmi func 04f2h is identical to 0ch except that it
|
|
; sets 'count' (in cx) LDTs at one time. The first selector is in
|
|
; register bx. The descriptor data is in gdtdsc[bx], gdtdsc[bx+8]
|
|
; etc. This data is shared between dpmi (dosx.exe) and us and thus
|
|
; need not be passed in es:di
|
|
|
|
WOW_DPMIFUNC_00 equ 04f1h
|
|
WOW_DPMIFUNC_0C equ 04f2h
|
|
endif
|
|
|
|
MovsDsc Macro ;Move (copy) a descriptor (4 words)
|
|
cld
|
|
rept 4
|
|
movsw
|
|
endm
|
|
endm
|
|
|
|
CheckDS Macro
|
|
local okDS
|
|
push ax
|
|
mov ax, ds
|
|
cmp ax, pGlobalHeap
|
|
je okDS
|
|
int 3
|
|
okDS:
|
|
pop ax
|
|
endm
|
|
|
|
CheckLDT Macro selector
|
|
if KDEBUG
|
|
test selector,SEL_LDT
|
|
jnz @F
|
|
int 3
|
|
@@:
|
|
endif
|
|
Endm
|
|
|
|
DPMICALL MACRO callno
|
|
mov ax, callno
|
|
call DPMIProc
|
|
ENDM
|
|
|
|
CHECKSEL MACRO selector
|
|
ENDM
|
|
|
|
extrn GlobalHandle:FAR
|
|
extrn GlobalRealloc:FAR
|
|
extrn GlobalFix:FAR
|
|
extrn GlobalUnFix:FAR
|
|
extrn IGlobalFix:FAR ;Far calls in this segment
|
|
extrn IGlobalFlags:FAR
|
|
IF KDEBUG
|
|
extrn GlobalHandleNorip:FAR
|
|
ELSE
|
|
extrn IGlobalHandle:FAR
|
|
ENDIF
|
|
|
|
DataBegin
|
|
|
|
ifdef WOW
|
|
externW SelectorFreeBlock
|
|
externW UserSelArray
|
|
endif
|
|
|
|
externW WinFlags
|
|
|
|
extrn kr1dsc:WORD
|
|
extrn kr2dsc:WORD
|
|
extrn blotdsc:WORD
|
|
extrn DemandLoadSel:WORD
|
|
extrn temp_sel:WORD
|
|
|
|
externW MyCSSeg
|
|
externW selWoaPdb
|
|
externW cpLowHeap
|
|
externW selLowHeap
|
|
externW pGlobalHeap
|
|
externW SelTableLen
|
|
|
|
externW MyCSAlias
|
|
|
|
extrn SelTableStart:DWORD
|
|
extrn sel_alias_array:WORD
|
|
|
|
if ROM
|
|
externW selROMTOC
|
|
externW selROMLDT
|
|
externW sel1stAvail
|
|
endif
|
|
|
|
if ROM
|
|
externD lmaHiROM
|
|
externD cbHiROM
|
|
endif
|
|
|
|
globalD lpProc,0
|
|
|
|
DataEnd
|
|
|
|
|
|
DataBegin INIT
|
|
|
|
RModeCallStructure STRUC
|
|
RMCS_DI dw 0
|
|
dw 0
|
|
RMCS_ESI dd 0
|
|
RMCS_EBP dd 0
|
|
RMCS_Res dd 0
|
|
RMCS_EBX dd 0
|
|
RMCS_EDX dd 0
|
|
RMCS_ECX dd 0
|
|
RMCS_EAX dd 0
|
|
RMCS_Flags dw 0
|
|
RMCS_ES dw 0
|
|
RMCS_DS dw 0
|
|
RMCS_FS dw 0
|
|
RMCS_GS dw 0
|
|
RMCS_IP dw 0
|
|
RMCS_CS dw 0
|
|
RMCS_SP dw 0
|
|
RMCS_SS dw 0
|
|
RModeCallStructure ENDS
|
|
|
|
MyCallStruc RModeCallStructure <>
|
|
|
|
public MS_DOS_Name_String
|
|
MS_DOS_Name_String db "MS-DOS", 0
|
|
|
|
DataEnd INIT
|
|
|
|
sBegin CODE
|
|
|
|
externW MyCSDS
|
|
externW gdtdsc
|
|
ifdef WOW
|
|
externD prevInt31proc
|
|
endif
|
|
|
|
sEnd CODE
|
|
|
|
sBegin INITCODE
|
|
assumes cs,CODE
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; SwitchToPMODE ;
|
|
; ;
|
|
; Entry: ;
|
|
; In Real or Virtual Mode ;
|
|
; DS -> Data Segment ;
|
|
; ES -> PSP ;
|
|
; ;
|
|
; Returns: ;
|
|
; In Protect Mode ;
|
|
; BX -> LDT selector ;
|
|
; SI -> Segment of start of available memory ;
|
|
; ES -> PSP ;
|
|
; ;
|
|
; Error Returns: ;
|
|
; Exits via DOS call 4Ch ;
|
|
; ;
|
|
; Registers Preserved: ;
|
|
; ;
|
|
; ;
|
|
; Registers Destroyed: ;
|
|
; ;
|
|
; Calls: ;
|
|
; ;
|
|
; History: ;
|
|
; ;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,DATA
|
|
assumes es,nothing
|
|
|
|
ife ROM
|
|
|
|
cProc SwitchToPMODE,<PUBLIC,NEAR>
|
|
cBegin nogen
|
|
|
|
push cx
|
|
push es ; Current PSP
|
|
|
|
mov ax, 1687h
|
|
int 2Fh ; Get PMODE switch entry
|
|
or ax, ax ; Can we do it?
|
|
jz @F
|
|
NoPMODEj:
|
|
jmp NoPMODE
|
|
@@:
|
|
xor bh, bh ; Set CPU type now
|
|
mov bl,WF_CPU286
|
|
cmp cl, 2 ; At least a 286?
|
|
jb NoPMODEj ; No, Fail
|
|
je @F ; It is a 286?
|
|
mov bl,WF_CPU386
|
|
cmp cl,3 ; No, 386?
|
|
je @F
|
|
mov bl,WF_CPU486 ; No, assume 486 for now
|
|
@@:
|
|
mov WinFlags, bx ; Save away CPU type
|
|
mov word ptr [lpProc][0], di
|
|
mov word ptr [lpProc][2], es
|
|
pop ax ; PSP
|
|
add ax, 10h ; Skip the PSP
|
|
mov es, ax ; Give this to the DOS extender
|
|
add si, ax ; Start of memory available to us
|
|
mov selWoaPdb, si ; PDB for WOA
|
|
add si, 10h ; Move start on another 256 bytes
|
|
|
|
xor ax, ax ; 16-bit app
|
|
call [lpProc] ; Switch to PROTECTED mode
|
|
jc short NoPMODEj ; No, still Real/Virtual mode
|
|
|
|
mov ax, cs
|
|
and al, 7 ; LDT, Ring 3
|
|
cmp al, 7
|
|
je @F
|
|
jmp BadDPMI ; Insist on Ring 3!
|
|
@@:
|
|
|
|
mov bx, cs ; Allocate CS Alias
|
|
DPMICALL 000Ah
|
|
|
|
mov MyCSAlias, ax ; Save CS Alias in DS
|
|
|
|
mov bx, ds ; Use alias to update code seg var
|
|
mov ds, ax
|
|
assumes ds, CODE
|
|
|
|
mov MyCSDS, bx ; The DS selector
|
|
|
|
mov ds, bx
|
|
ReSetKernelDS
|
|
|
|
push si ; Unlock all of our memory
|
|
mov bx, si ; Segment address of start of our memory
|
|
mov di, es:[PDB_block_len] ; End of our memory
|
|
sub di, bx ; Size of our block in paragraphs
|
|
mov cpLowHeap, di ; (MAY NEED INCREMENTING!!!)
|
|
xor si, si ; Calculate # bytes in SI:DI
|
|
REPT 4
|
|
shl di, 1
|
|
rcl si, 1
|
|
ENDM
|
|
mov cx, bx ; Convert start of block to linear
|
|
xor bx, bx ; address
|
|
REPT 4
|
|
shl cx, 1
|
|
rcl bx, 1
|
|
ENDM
|
|
mov ax, 0602h
|
|
;BUGBUGBUGBUG
|
|
int 31h ; Mark region as pageable.
|
|
|
|
pop bx
|
|
DPMICALL 0002h ; Convert start of memory to selector
|
|
mov si, ax
|
|
mov selLowHeap, ax ; Save for WOA (MAY NEED PARA LESS!!!)
|
|
|
|
mov bx, selWoaPdb ; Convert WOA PDB segment to selector
|
|
DPMICALL 0002h
|
|
mov selWoaPdb, ax
|
|
|
|
push si
|
|
push es
|
|
mov ax, 168Ah ; See if we have MS-DOS extensions
|
|
mov si, dataOffset MS_DOS_Name_String
|
|
int 2Fh
|
|
cmp al, 8Ah
|
|
je short BadDPMI ; No extensions, screwed
|
|
|
|
mov word ptr [lpProc][0], di ; Save CallBack address
|
|
mov word ptr [lpProc][2], es
|
|
|
|
mov ax, 0100h ; Get base of LDT
|
|
call [lpProc]
|
|
jc short NoLDTParty
|
|
ifndef WOW
|
|
verw ax ; Writeable?
|
|
else
|
|
verr ax ; for WOW we can use read access
|
|
endif
|
|
jnz short NoLDTParty ; nope, don't bother with it
|
|
|
|
mov es, MyCSAlias
|
|
assumes es,CODE
|
|
mov gdtdsc, ax
|
|
assumes es,nothing
|
|
|
|
NoLDTParty: ; Well, we'll just have to use DPMI!
|
|
pop es
|
|
pop si
|
|
xor bx, bx
|
|
pop cx
|
|
ret
|
|
|
|
BadDPMI:
|
|
;
|
|
; Call real/virtual mode to whine
|
|
;
|
|
xor cx, cx ; Nothing on stack to copy
|
|
xor bh, bh ; Flags to DPMI
|
|
mov ax, MyCSSeg
|
|
mov MyCallStruc.RMCS_DS, ax ; Real mode DS will be parent PDB
|
|
mov MyCallStruc.RMCS_ES, cx ; Real mode ES will be 0
|
|
mov MyCallStruc.RMCS_CS, ax ; Real mode CS
|
|
mov MyCallStruc.RMCS_IP, codeoffset RModeCode ; Real mode IP
|
|
|
|
smov es, ds
|
|
mov di, dataoffset MyCallStruc ; ES:DI points to call structure
|
|
mov ax, 0301h ; Call Real Mode Procedure
|
|
int 31h
|
|
jmps GoodBye
|
|
|
|
RModeCode:
|
|
mov dx, codeoffset szInadequate
|
|
mov ah, 9
|
|
int 21h
|
|
retf
|
|
|
|
;szInadequate:
|
|
; DB 'KRNL286: Inadequate DPMI Server',13,10,'$'
|
|
externB <szNoPMode, szInadequate>
|
|
|
|
NoPMODE: ; NOTE: stack trashed...
|
|
ifdef WOW
|
|
;** Put Up a Dialog Box If we fail to Enter Protect Mode
|
|
;** Prepare the dialog box
|
|
push cs ;In our DS
|
|
push codeOFFSET szNoPMode ; -> unable to enter Prot Mode
|
|
|
|
push ds
|
|
externB <syserr>
|
|
push dataOffset syserr ;Caption
|
|
|
|
push 0 ;No left button
|
|
|
|
push SEB_CLOSE + SEB_DEFBUTTON ;Button 1 style
|
|
|
|
push 0 ;No right button
|
|
externFP kSYSERRORBOX
|
|
call kSYSERRORBOX ;Put up the system error message
|
|
externNP ExitKernel
|
|
jmp ExitKernel
|
|
|
|
else ; Not WOW
|
|
|
|
mov dx, codeoffset szNoPMode
|
|
; call complain
|
|
; DB 'KRNL286: Unable to enter Protected Mode',7,7,7,13,10,'$'
|
|
;complain:
|
|
; pop dx
|
|
push cs
|
|
pop ds ; DS:DX -> error message
|
|
mov ah,9 ; Print error message
|
|
int 21h
|
|
|
|
endif ; WOW
|
|
|
|
|
|
GoodBye:
|
|
mov ax, 4CFFh
|
|
int 21h
|
|
cEnd nogen
|
|
|
|
endif ;ROM
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; LDT_Init ;
|
|
; ;
|
|
; Entry: ;
|
|
; ;
|
|
; Returns: ;
|
|
; ;
|
|
; Error Returns: ;
|
|
; ;
|
|
; Registers Preserved: ;
|
|
; AX,BX,CX,DX,DI,SI,DS,ES ;
|
|
; ;
|
|
; Registers Destroyed: ;
|
|
; ;
|
|
; Calls: ;
|
|
; ;
|
|
; History: ;
|
|
; ;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc LDT_Init,<PUBLIC,NEAR>,<ax,bx,cx,di,es>
|
|
cBegin
|
|
|
|
ReSetKernelDS
|
|
mov es, bx ; Selector for LDT if any
|
|
|
|
push es ; Get random selectors
|
|
smov es, ds
|
|
ReSetKernelDS es
|
|
assumes ds,nothing
|
|
mov cx, 1 ; Argument to get_sel
|
|
call get_sel
|
|
mov kr1dsc, si
|
|
call get_sel
|
|
mov blotdsc, si
|
|
call get_sel
|
|
or si, SEG_RING
|
|
mov DemandLoadSel, si
|
|
|
|
mov ax, DSC_DATA+DSC_PRESENT; Get an array of 16 selectors
|
|
cCall alloc_sel,<0000h,0BADh,0FFFFh> ; This covers 1Mb.
|
|
mov kr2dsc, ax
|
|
smov ds, es
|
|
pop es
|
|
assumes es,nothing
|
|
cEnd
|
|
|
|
sEnd INITCODE
|
|
|
|
sBegin CODE
|
|
assumes cs,CODE
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; AllocSelector
|
|
;
|
|
;
|
|
; Entry:
|
|
;
|
|
; Returns:
|
|
; AX = New selector
|
|
; = 0 if out of selectors
|
|
;
|
|
; Registers Destroyed:
|
|
;
|
|
; History:
|
|
; Thu 08-Dec-1988 14:17:38 -by- David N. Weise [davidw]
|
|
; Wrote it!
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc AllocSelectorWOW,<PUBLIC,FAR>
|
|
parmW selector
|
|
cBegin
|
|
; same as allocselector but doesn't set the descriptor
|
|
cCall inner_alloc_selector,<selector,0ffffh>
|
|
cEnd
|
|
|
|
cProc AllocSelector,<PUBLIC,FAR>
|
|
parmW selector
|
|
cBegin
|
|
cCall inner_alloc_selector,<selector,0>
|
|
cEnd
|
|
|
|
|
|
labelFP <PUBLIC, IAllocCStoDSAlias>
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; AllocAlias
|
|
;
|
|
; This allocates a data alias for the passed in selector, which
|
|
; can be either code or data. The alias will track segment
|
|
; motion.
|
|
;
|
|
; Entry:
|
|
; parmW selector selector to get an alias for
|
|
;
|
|
; Returns:
|
|
; AX = selector
|
|
; = 0 failure
|
|
;
|
|
; Registers Destroyed:
|
|
;
|
|
; History:
|
|
; Sat 20-Jan-1990 23:40:32 -by- David N. Weise [davidw]
|
|
; Cleaning up.
|
|
;
|
|
; Fri 02-Dec-1988 11:04:58 -by- David N. Weise [davidw]
|
|
; Wrote it!
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc AllocAlias,<FAR,PUBLIC>
|
|
|
|
parmW selector
|
|
cBegin
|
|
ifdef WOW
|
|
push bx ; Whitewater tool ObjDraw needs this too
|
|
endif
|
|
cCall inner_alloc_selector,<selector,1>
|
|
; WhiteWater Resource Toolkit (shipped with Borland's Turbo
|
|
; Pascal) depends on dx being the data selector which was true
|
|
; in 3.0 but in 3.1 validation layer destroys it.
|
|
mov dx,selector
|
|
ifdef WOW
|
|
pop bx
|
|
endif
|
|
cEnd
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; AllocDStoCSAlias
|
|
;
|
|
; This allocates a code alias for the passed in selector, which
|
|
; should be data. The alias will track segment motion. The
|
|
; passed in selector must be less than 64K.
|
|
;
|
|
; Entry:
|
|
; parmW selector selector to get an alias for
|
|
;
|
|
; Returns:
|
|
; AX = selector
|
|
; = 0 failure
|
|
;
|
|
; Registers Destroyed:
|
|
;
|
|
; History:
|
|
; Sat 20-Jan-1990 23:40:32 -by- David N. Weise [davidw]
|
|
; Cleaning up.
|
|
;
|
|
; Fri 02-Dec-1988 11:04:58 -by- David N. Weise [davidw]
|
|
; Wrote it!
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc IAllocDStoCSAlias,<FAR,PUBLIC>, <cx,si,di>
|
|
parmW data_selector
|
|
cBegin
|
|
;** AllocDStoCSAlias has an interesting hack. A fix was made to
|
|
;** not allow apps to GlobalAlloc fixed memory. This was done
|
|
;** for performance reasons. The only reason we can ascertain
|
|
;** for an app needing fixed GlobalAlloc'ed memory is in the case
|
|
;** of alias selectors. We assume that all apps needing alias
|
|
;** selectors will use this function to make the alias. So, if
|
|
;** we see a DStoCS alias being made, we make sure the DS is fixed.
|
|
mov ax, data_selector ;Get handle
|
|
push ax
|
|
IF KDEBUG
|
|
call GlobalHandleNorip ;Make sure it's really a handle
|
|
ELSE
|
|
call IGlobalHandle ;Make sure it's really a handle
|
|
ENDIF
|
|
test ax, 1 ;Fixed blocks have low bit set
|
|
jnz ADCA_Already_Fixed ;It's already a fixed block!
|
|
|
|
;** If the block is not fixed, it may be locked so we must check this.
|
|
push ax ;Save returned selector
|
|
push ax ;Use as parameter
|
|
call IGlobalFlags ;Returns lock count if any
|
|
or al, al ;Non-zero lock count?
|
|
pop ax ;Get selector back
|
|
jnz ADCA_Already_Fixed ;Yes, don't mess with it
|
|
|
|
;** Fix the memory. Note that we're only doing this for
|
|
;** apps that are calling this on non-fixed or -locked memory.
|
|
;** This will cause them to rip on the GlobalFree call to this
|
|
;** memory, but at least it won't move on them!
|
|
push ax ;Fix it
|
|
call IGlobalFix
|
|
ADCA_Already_Fixed:
|
|
|
|
cCall inner_alloc_selector,<data_selector,2>
|
|
if ALIASES
|
|
or ax,ax
|
|
jz ada_nope
|
|
mov bx,data_selector
|
|
call add_alias
|
|
ada_nope:
|
|
endif
|
|
smov es,0
|
|
|
|
; WhiteWater Resource Toolkit (shipped with Borland's Turbo
|
|
; Pascal) depends on dx being the data selector which was
|
|
; true in 3.0 but in 3.1 validation layer destroys it.
|
|
mov dx,data_selector
|
|
cEnd
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; inner_alloc_selector
|
|
;
|
|
;
|
|
; Entry:
|
|
;
|
|
; Returns:
|
|
;
|
|
; Registers Destroyed:
|
|
;
|
|
; History:
|
|
; Sat 20-Jan-1990 23:40:32 -by- David N. Weise [davidw]
|
|
;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc inner_alloc_selector,<PUBLIC,NEAR>,<di,si>
|
|
|
|
parmW selector
|
|
parmW sel_type
|
|
localV DscBuf,DSC_LEN
|
|
cBegin
|
|
mov cx, 1
|
|
mov di, selector
|
|
and di, not SEG_RING_MASK
|
|
jnz as1
|
|
|
|
call get_sel
|
|
jnz short as_exit ; We got it
|
|
jmps as_exit1
|
|
|
|
as1:
|
|
mov bx, selector
|
|
lea di, DscBuf
|
|
smov es, ss
|
|
|
|
ifdef WOW
|
|
DPMICALL 000Bh ; Get existing descriptor
|
|
else
|
|
push ds
|
|
mov ds, gdtdsc
|
|
push si ; Get Descriptor
|
|
mov si, bx
|
|
and si, not 7
|
|
MovsDsc
|
|
lea di, [di-DSC_LEN] ; Restore DI
|
|
pop si
|
|
pop ds
|
|
endif
|
|
mov cl, DscBuf.dsc_hlimit
|
|
and cl, 0Fh
|
|
inc cl ; # selectors
|
|
|
|
call get_sel
|
|
jz short as_exit1
|
|
ifdef WOW
|
|
cmp sel_type, 0ffffh ; called from AllocSelectorWOW ?
|
|
jz as_exit ; yes . dont set descriptor
|
|
endif
|
|
cmp sel_type,0 ; called from AllocSelector?
|
|
jz as_fill ; done if so
|
|
mov al,DSC_PRESENT+DSC_DATA
|
|
cmp sel_type,1 ; called from AllocAlias?
|
|
jz @F
|
|
or al,DSC_CODE_BIT ; called from AllocDStoCSAlias
|
|
@@:
|
|
mov DscBuf.dsc_access,al
|
|
as_fill:
|
|
mov bx, si
|
|
or bl, SEG_RING
|
|
|
|
call fill_in_selector_array
|
|
|
|
as_exit:
|
|
or si, SEG_RING
|
|
as_exit1:
|
|
mov ax,si
|
|
smov es, 0
|
|
cEnd
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; get_sel ;
|
|
; ;
|
|
; Entry: ;
|
|
; CX = # of selectors required ;
|
|
; ;
|
|
; Returns: ;
|
|
; SI = First Selector ;
|
|
; DS = LDT ;
|
|
; ZF = 0 ;
|
|
; ;
|
|
; Error Returns: ;
|
|
; SI = 0 ;
|
|
; ZF = 1 ;
|
|
; ;
|
|
; Registers Preserved: ;
|
|
; AX,BX,CX,DX,DI,ES ;
|
|
; ;
|
|
; Registers Destroyed: ;
|
|
; ;
|
|
; Calls: ;
|
|
; ;
|
|
; History: ;
|
|
; ;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
cProc AllocSelectorArray,<PUBLIC,FAR>,<si>
|
|
parmW nSels
|
|
cBegin
|
|
mov cx, nSels
|
|
call get_sel
|
|
mov ax, si
|
|
jz asa_fail
|
|
|
|
or si, SEG_RING
|
|
mov bx, si
|
|
mov dx, cx
|
|
mov cx, DSC_DATA+DSC_PRESENT ; Mark all as Data and Present
|
|
ifdef WOW
|
|
fill_in_access:
|
|
DPMICALL 0009h
|
|
lea bx, [bx+DSC_LEN]
|
|
dec dx
|
|
jnz fill_in_access
|
|
else
|
|
push ds
|
|
mov ds, gdtdsc
|
|
push bx
|
|
and bl, not 7
|
|
fill_in_access:
|
|
mov word ptr ds:[bx].dsc_access, cx
|
|
if 0 ;;ROM and KDEBUG
|
|
call CheckROMSelector
|
|
endif
|
|
lea bx, [bx+DSC_LEN]
|
|
dec dx
|
|
jnz fill_in_access
|
|
pop bx
|
|
pop ds
|
|
endif; WOW
|
|
mov ax, si
|
|
|
|
asa_fail:
|
|
cEnd
|
|
|
|
|
|
cProc get_sel,<PUBLIC,NEAR>
|
|
cBegin nogen
|
|
call SetKernelDSProc ; Must call procedure here
|
|
ReSetKernelDS
|
|
push ax
|
|
push cx
|
|
xor ax, ax
|
|
cmp cx, 1 ; One selector only?
|
|
jne gs_int31
|
|
cmp temp_sel, ax ; Have one waiting?
|
|
je gs_int31 ; no, get one
|
|
xchg temp_sel, ax ; Use the waiting selector
|
|
jmps gs_got_sel
|
|
gs_int31:
|
|
DPMICALL 0000h
|
|
CHECKSEL ax
|
|
|
|
gs_got_sel:
|
|
mov si, ax
|
|
and si, not SEG_RING_MASK
|
|
|
|
if KDEBUG
|
|
jnz got_sel
|
|
push es
|
|
pusha
|
|
kerror 0,<Out of selectors>
|
|
popa
|
|
pop es
|
|
jmps gs_exit
|
|
got_sel:
|
|
endif
|
|
|
|
mov ax, si
|
|
shr ax, 2
|
|
cmp ax, SelTableLen ; Make sure we can associate it
|
|
jae gs_free_sels
|
|
|
|
gs_exit:
|
|
mov ds, gdtdsc ; SIDE EFFECT...
|
|
UnSetKernelDS
|
|
gs_exit_2:
|
|
pop cx
|
|
pop ax
|
|
or si, si
|
|
ret
|
|
|
|
gs_free_sels:
|
|
ReSetKernelDS
|
|
cmp SelTableLen, 0
|
|
je gs_exit ; Not set yet, so we are ok
|
|
|
|
mov ds, gdtdsc
|
|
UnSetKernelDS
|
|
push bx
|
|
mov bx, si ; Could not associate, so free them
|
|
xor si, si
|
|
or bl, SEG_RING
|
|
as_free:
|
|
DPMICALL 0001h
|
|
lea bx, [bx+DSC_LEN]
|
|
loop as_free
|
|
pop bx
|
|
jmps gs_exit_2
|
|
|
|
cEnd nogen
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; FreeSelector ;
|
|
; free_sel ;
|
|
; FreeSelArray
|
|
; ;
|
|
; Entry: ;
|
|
; ;
|
|
; Returns: ;
|
|
; ;
|
|
; Error Returns: ;
|
|
; ;
|
|
; Registers Preserved: ;
|
|
; BX,CX,DX,DI,SI,DS,ES ;
|
|
; ;
|
|
; Registers Destroyed: ;
|
|
; ;
|
|
; Calls: ;
|
|
; ;
|
|
; History: ;
|
|
; ;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc IFreeSelector,<FAR,PUBLIC>,<di,si>
|
|
parmW selector
|
|
cBegin
|
|
CheckLDT selector
|
|
if ALIASES
|
|
mov ax,selector
|
|
call delete_alias
|
|
endif
|
|
xor ax, ax
|
|
mov es, ax ; GRRRRRRRR!
|
|
cCall FreeSelArray,<selector>
|
|
cEnd
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc free_sel,<PUBLIC,NEAR>,<ax,bx>
|
|
parmW selector
|
|
cBegin
|
|
pushf ; !! for the nonce
|
|
mov bx,selector ; must be careful in gcompact
|
|
; to ignore error return
|
|
if KDEBUG
|
|
or bx, SEG_RING ; Ensure Table bit correct
|
|
endif
|
|
|
|
DPMICALL 0001h
|
|
popf
|
|
cEnd
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc FreeSelArray,<PUBLIC,NEAR>,<ax,bx,cx>
|
|
parmW selector
|
|
cBegin
|
|
mov bx,selector ; to ignore error return
|
|
|
|
cCall GetSelectorCount
|
|
mov cx, ax
|
|
|
|
fsa_loop:
|
|
DPMICALL 0001h
|
|
lea bx, [bx+DSC_LEN]
|
|
loop fsa_loop ; Any left to free
|
|
cEnd
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; GrowSelArray ;
|
|
; ;
|
|
; This is called from within grealloc. The point is to grow the ;
|
|
; number of contiguous selectors to tile the memory object. ;
|
|
; If we can't get a contiguous set then we attempt to find a set ;
|
|
; anywhere. ;
|
|
; ;
|
|
; Entry: ;
|
|
; ES => arena header ;
|
|
; ;
|
|
; Returns: ;
|
|
; AX => new selector array ;
|
|
; CX => new number of selectors ;
|
|
; ;
|
|
; Error Returns: ;
|
|
; ;
|
|
; Registers Preserved: ;
|
|
; BX,DX,DI,SI,DS,ES ;
|
|
; ;
|
|
; Registers Destroyed: ;
|
|
; ;
|
|
; Calls: ;
|
|
; ;
|
|
; History: ;
|
|
; ;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc GrowSelArray,<PUBLIC,NEAR>,<bx,si,di,ds>
|
|
localV DscBuf,DSC_LEN
|
|
localW oldCount
|
|
cBegin
|
|
mov bx, es:[ga_handle]
|
|
mov di, bx
|
|
|
|
cCall GetSelectorCount
|
|
mov word ptr oldCount, ax
|
|
|
|
mov cx, si ; New size
|
|
dec cx ; Paragraph limit
|
|
shr cx, 12
|
|
inc cx ; new # selectors
|
|
cmp al, cl ; Same # of selectors required?
|
|
je gsa_done ; yes, just return!
|
|
|
|
call get_sel ; get a new selector array
|
|
jz short gsa_nosels
|
|
xchg si, di ; DI now new array, SI old array
|
|
|
|
push es
|
|
push cx
|
|
and bx, SEG_RING_MASK ; Ring bits
|
|
or bx, di ; New handle
|
|
mov cx, word ptr oldCount
|
|
push ds ; Copy Descriptor(s)
|
|
push si
|
|
mov es, gdtdsc
|
|
mov ds, gdtdsc
|
|
and si, not 7
|
|
|
|
shl cx, 2 ; CX = 4 * Descriptors = words to copy
|
|
rep movsw
|
|
|
|
pop si
|
|
pop ds
|
|
ifdef WOW
|
|
; set the descriptors
|
|
push bx
|
|
mov cx, word ptr oldCount
|
|
or bx, SEG_RING_MASK ; start selector
|
|
DPMICALL WOW_DPMIFUNC_0C
|
|
pop bx
|
|
endif; WOW
|
|
pop cx
|
|
pop es
|
|
|
|
SetKernelDS
|
|
mov ds, pGlobalHeap
|
|
UnSetKernelDS
|
|
cCall AssociateSelector,<si,0>
|
|
mov es:[ga_handle], bx
|
|
cCall AssociateSelector,<bx,es>
|
|
jmps gsa_done
|
|
|
|
gsa_nosels:
|
|
xor bx, bx ; Indicate failure
|
|
gsa_done:
|
|
mov ax, bx
|
|
or ax, ax ; Indicate success
|
|
gsa_ret:
|
|
cEnd
|
|
|
|
|
|
assumes ds, nothing
|
|
assumes es, nothing
|
|
|
|
cProc PreallocSel,<PUBLIC,NEAR>
|
|
cBegin nogen
|
|
push ds
|
|
push cx
|
|
push si
|
|
mov cx, 1
|
|
call get_sel
|
|
call SetKernelDSProc
|
|
ReSetKernelDS
|
|
mov temp_sel, si
|
|
or si, si ; Set flags for caller
|
|
pop si
|
|
pop cx
|
|
pop ds
|
|
UnSetKernelDS
|
|
ret
|
|
cEnd nogen
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; alloc_sel ;
|
|
; alloc_data_sel
|
|
; ;
|
|
; Entry: ;
|
|
; parmD Address 32 bit address ;
|
|
; parmW Limit limit in paragraphs (limit of 1 meg) ;
|
|
; AX = flags alloc_sel only ;
|
|
; ;
|
|
; Returns: ;
|
|
; AX = new selector ;
|
|
; ;
|
|
; Error Returns: ;
|
|
; AX = 0 ;
|
|
; ;
|
|
; Registers Preserved: ;
|
|
; AX,BX,CX,DX,DI,SI,DS,ES ;
|
|
; ;
|
|
; Registers Destroyed: ;
|
|
; ;
|
|
; Calls: ;
|
|
; ;
|
|
; History: ;
|
|
; ;
|
|
; Thu 07-Apr-1988 21:33:27 -by- David N. Weise [davidw] ;
|
|
; Added the GlobalNotify check. ;
|
|
; ;
|
|
; Sun Feb 01, 1987 07:48:39p -by- David N. Weise [davidw] ;
|
|
; Added this nifty comment block. ;
|
|
;-----------------------------------------------------------------------;
|
|
assumes ds, nothing
|
|
assumes es, nothing
|
|
|
|
if ROM
|
|
public far_alloc_data_sel16
|
|
far_alloc_data_sel16 equ this far
|
|
endif
|
|
|
|
cProc far_alloc_data_sel,<PUBLIC,FAR>
|
|
parmD Address
|
|
parmW Limit
|
|
cBegin
|
|
cCall alloc_data_sel,<Address,Limit>
|
|
cEnd
|
|
|
|
if ROM
|
|
public alloc_data_sel16
|
|
alloc_data_sel16 equ this near
|
|
endif
|
|
|
|
cProc alloc_data_sel,<PUBLIC,NEAR>
|
|
; parmD Address
|
|
; parmW Limit
|
|
cBegin nogen
|
|
mov ax, DSC_DATA+DSC_PRESENT
|
|
errn$ alloc_sel
|
|
cEnd nogen
|
|
|
|
|
|
cProc alloc_sel,<PUBLIC,NEAR>,<bx,cx,dx,si,di,ds,es>
|
|
parmD Address
|
|
parmW Limit
|
|
localV DscBuf,DSC_LEN
|
|
cBegin
|
|
mov cx, 1
|
|
test al, DSC_PRESENT
|
|
jz as_oneonly
|
|
|
|
mov cx, Limit ; Calculate how many selectors required
|
|
add cx, 0FFFh
|
|
rcr cx, 1 ; 17 bitdom
|
|
shr cx, 11
|
|
|
|
as_oneonly:
|
|
call get_sel
|
|
jz short a_s_exit
|
|
|
|
mov bx, si ; Selector in bx for DPMI
|
|
or bl, SEL_LDT
|
|
lea di, DscBuf
|
|
smov es, ss ; es:di points to descriptor buffer
|
|
push ax ; Save access word
|
|
|
|
mov ax, Address.lo ; Set descriptor base
|
|
mov DscBuf.dsc_lbase, ax
|
|
mov ax, Address.hi
|
|
mov DscBuf.dsc_mbase, al
|
|
mov DscBuf.dsc_hbase, ah
|
|
|
|
pop ax ; Access word
|
|
test al, DSC_PRESENT ; If selector not present, limit is
|
|
jnz short set_everything ; as passed, not a paragraph count
|
|
|
|
mov word ptr DscBuf.dsc_access, ax
|
|
mov ax, word ptr Limit
|
|
mov DscBuf.dsc_limit, ax
|
|
ifdef WOW
|
|
DPMICALL 000Ch ; Fill in our stuff in the descriptor
|
|
else
|
|
push ds
|
|
push bx ; Set Descriptor
|
|
mov ds, gdtdsc
|
|
and bl, not 7
|
|
mov ax, es:[di] ; This looks slow but it isn't...
|
|
mov ds:[bx], ax
|
|
mov ax, es:[di][2]
|
|
mov ds:[bx][2], ax
|
|
mov ax, es:[di][4]
|
|
mov ds:[bx][4], ax
|
|
mov ax, es:[di][6]
|
|
mov ds:[bx][6], ax
|
|
if 0 ;;ROM and KDEBUG
|
|
call CheckROMSelector
|
|
endif
|
|
pop bx
|
|
pop ds
|
|
endif; WOW
|
|
jmps as_done
|
|
|
|
set_everything:
|
|
dec cl
|
|
and ah, not 0Fh ; Zero limit 19:16
|
|
or ah, cl ; Fill in limit 19:16
|
|
inc cl
|
|
mov word ptr DscBuf.dsc_access, ax
|
|
mov ax, Limit
|
|
shl ax, 4 ; Convert paragraphs to byte limit
|
|
dec ax
|
|
mov DscBuf.dsc_limit, ax
|
|
|
|
call fill_in_selector_array
|
|
|
|
as_done:
|
|
or si, SEG_RING
|
|
a_s_exit:
|
|
mov ax, si
|
|
cEnd
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; fill_in_selector_array ;
|
|
; ;
|
|
; Entry: ;
|
|
; AX = size of object in paragraphs ;
|
|
; DH = Discard bit for descriptors ;
|
|
; DL = Access bits ;
|
|
; CX:BX = 32 bit base address of object ;
|
|
; SI = index into LDT ;
|
|
; Returns: ;
|
|
; ;
|
|
; Error Returns: ;
|
|
; ;
|
|
; Registers Preserved: ;
|
|
; SI, DI, DS, ES ;
|
|
; ;
|
|
; Registers Destroyed: ;
|
|
; AX,BX,CX,DX ;
|
|
; ;
|
|
; Calls: ;
|
|
; ;
|
|
; History: ;
|
|
; ;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds, nothing
|
|
assumes es, nothing
|
|
|
|
cProc fill_in_selector_array,<PUBLIC,NEAR>
|
|
cBegin nogen
|
|
CheckLDT bl
|
|
|
|
push ds
|
|
push es:[di].dsc_limit ; Save limit for last selector
|
|
SetKernelDS
|
|
test WinFlags, WF_CPU286 ; protect mode on a 286?
|
|
jz next_sel
|
|
mov es:[di].dsc_limit, 0FFFFh ; Others get 64k limit on 286
|
|
|
|
next_sel:
|
|
cmp cx, 1 ; Last selector?
|
|
jne fsa_not_last
|
|
pop es:[di].dsc_limit ; yes, get its limit
|
|
fsa_not_last:
|
|
DPMICALL 000Ch ; Set this descriptor
|
|
lea bx, [bx+DSC_LEN] ; On to next selector
|
|
add es:[di].dsc_mbase, 1 ; Add 64kb to address
|
|
adc es:[di].dsc_hbase, 0
|
|
dec es:[di].dsc_hlimit ; subtract 64kb from limit
|
|
loop next_sel
|
|
|
|
pop ds
|
|
ret
|
|
cEnd nogen
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; GetSelectorBase
|
|
; get_physical_address
|
|
;
|
|
;
|
|
; Entry:
|
|
;
|
|
; Returns:
|
|
; DX:AX 32 bit physical address
|
|
; Registers Destroyed:
|
|
; none
|
|
;
|
|
; History:
|
|
; Sat 09-Jul-1988 16:40:59 -by- David N. Weise [davidw]
|
|
;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc GetSelectorBase,<PUBLIC,FAR>
|
|
parmW selector
|
|
cBegin
|
|
cCall get_physical_address,<selector>
|
|
cEnd
|
|
|
|
cProc get_physical_address,<PUBLIC,NEAR>
|
|
parmW selector
|
|
cBegin
|
|
push bx
|
|
push cx
|
|
mov bx, selector
|
|
CheckLDT bl
|
|
ifdef WOWJUNK
|
|
DPMICALL 0006h
|
|
mov ax, dx
|
|
mov dx, cx
|
|
else
|
|
push ds ; Get Segment Base Address
|
|
mov ds, gdtdsc
|
|
and bl, not 7
|
|
mov ax, ds:[bx].dsc_lbase
|
|
mov dl, ds:[bx].dsc_mbase
|
|
mov dh, ds:[bx].dsc_hbase
|
|
pop ds
|
|
endif; WOW
|
|
pop cx
|
|
pop bx
|
|
cEnd
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; set_physical_address
|
|
;
|
|
;
|
|
; Entry:
|
|
; DX:AX 32 bit physical address
|
|
; Returns:
|
|
;
|
|
; Registers Destroyed:
|
|
;
|
|
; History:
|
|
; Sat 09-Jul-1988 16:40:59 -by- David N. Weise [davidw]
|
|
;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc set_physical_address,<PUBLIC,NEAR>,<ax,bx,cx,dx>
|
|
parmW selector
|
|
cBegin
|
|
CheckLDT selector
|
|
|
|
push di
|
|
|
|
push ax ; save low bits of address
|
|
mov bx, selector
|
|
call GetSelectorCount
|
|
mov di, ax
|
|
mov cx, dx ; CX:DX has new address
|
|
pop dx
|
|
|
|
set_bases:
|
|
DPMICALL 0007h ; Set selector base
|
|
lea bx, [bx+DSC_LEN] ; On to next selector
|
|
inc cx ; Add 64k to base
|
|
dec di
|
|
jnz set_bases
|
|
|
|
pop di
|
|
|
|
cEnd
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; get_selector_length16
|
|
;
|
|
;
|
|
; Entry:
|
|
;
|
|
; Returns:
|
|
; AX 16 bit segment length
|
|
; Registers Destroyed:
|
|
;
|
|
; History:
|
|
; Sat 09-Jul-1988 16:40:59 -by- David N. Weise [davidw]
|
|
;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc get_selector_length16,<PUBLIC,NEAR>
|
|
parmW selector
|
|
cBegin
|
|
mov ax, -1
|
|
lsl ax, selector
|
|
inc ax ; length is one bigger!
|
|
cEnd
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; set_sel_limit
|
|
; SIDE EFFECT: descriptor bases and access are set based
|
|
; on the first in the array
|
|
;
|
|
; Entry:
|
|
; CX:BX = length of segment
|
|
; Returns:
|
|
;
|
|
; Registers Destroyed:
|
|
; CX
|
|
;
|
|
; History:
|
|
; Fri 15-Jul-1988 19:41:44 -by- David N. Weise [davidw]
|
|
;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc set_sel_limit,<PUBLIC,NEAR>,<ax,bx,dx>
|
|
parmW selector
|
|
localV DscBuf,DSC_LEN
|
|
cBegin
|
|
|
|
push es
|
|
push di
|
|
|
|
push bx ; Get existing descriptor
|
|
smov es, ss
|
|
lea di, DscBuf
|
|
mov bx, selector
|
|
CheckLDT bl
|
|
ifdef WOW
|
|
DPMICALL 000Bh
|
|
else
|
|
push ds ; Get Descriptor
|
|
mov ds, gdtdsc
|
|
push si
|
|
mov si, bx
|
|
and si, not 7
|
|
MovsDsc
|
|
lea di, [di-DSC_LEN] ; Restore DI
|
|
pop si
|
|
pop ds
|
|
endif; WOW
|
|
pop bx
|
|
|
|
mov dx, word ptr [DscBuf.dsc_access]
|
|
and dh, 0F0h ; Zap old hlimit bits
|
|
|
|
sub bx, 1 ; Turn length into linit
|
|
sbb cx, 0
|
|
and cx, 0Fh ; Get bits 19:16 of new limit
|
|
or dh, cl ; Set new hlimit bits
|
|
|
|
mov word ptr DscBuf.dsc_access, dx
|
|
mov DscBuf.dsc_limit, bx
|
|
mov bx, Selector
|
|
|
|
jcxz ssl_set_limit1 ; Only one, fast out
|
|
|
|
inc cx ; Turn CX into selector count
|
|
call fill_in_selector_array
|
|
jmps ssl_done
|
|
|
|
ssl_set_limit1: ; Fast out for one only
|
|
ifdef WOW
|
|
DPMICALL 000Ch
|
|
else
|
|
push ds
|
|
push bx ; Set Descriptor
|
|
mov ds, gdtdsc
|
|
and bl, not 7
|
|
mov ax, es:[di] ; This looks slow but it isn't...
|
|
mov ds:[bx], ax
|
|
mov ax, es:[di][2]
|
|
mov ds:[bx][2], ax
|
|
mov ax, es:[di][4]
|
|
mov ds:[bx][4], ax
|
|
mov ax, es:[di][6]
|
|
mov ds:[bx][6], ax
|
|
if 0 ;;ROM and KDEBUG
|
|
call CheckROMSelector
|
|
endif
|
|
pop bx
|
|
pop ds
|
|
endif; WOW
|
|
ssl_done:
|
|
pop di
|
|
pop es
|
|
|
|
smov ss,ss ; It might be SS we're changing
|
|
cEnd
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; mark_sel_NP
|
|
;
|
|
;
|
|
; Entry:
|
|
;
|
|
; Returns:
|
|
;
|
|
; Registers Destroyed:
|
|
;
|
|
; History:
|
|
; Fri 15-Jul-1988 21:37:22 -by- David N. Weise [davidw]
|
|
;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc mark_sel_NP,<PUBLIC,NEAR>
|
|
parmW selector
|
|
parmW owner
|
|
localV DscBuf,DSC_LEN
|
|
cBegin
|
|
push es
|
|
push ax
|
|
push bx
|
|
push di
|
|
ifdef WOW
|
|
lea di, DscBuf
|
|
smov es, ss
|
|
mov bx, selector
|
|
DPMICALL 000Bh
|
|
and DscBuf.dsc_access, not DSC_PRESENT
|
|
or DscBuf.dsc_hlimit, DSC_DISCARDABLE
|
|
mov ax, owner
|
|
mov DscBuf.dsc_owner, ax
|
|
DPMICALL 000Ch
|
|
else
|
|
push ds ; Get Descriptor
|
|
mov ds, gdtdsc
|
|
mov bx, selector
|
|
and bl, not 7
|
|
and [bx].dsc_access, not DSC_PRESENT
|
|
or [bx].dsc_hlimit, DSC_DISCARDABLE
|
|
mov ax, owner
|
|
mov [bx].dsc_owner, ax
|
|
pop ds
|
|
endif; WOW
|
|
SetKernelDS
|
|
mov ds, pGlobalHeap
|
|
UnSetKernelDS
|
|
cCall AssociateSelector,<bx,owner>
|
|
pop di
|
|
pop bx
|
|
pop ax
|
|
pop es
|
|
cEnd
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; mark_sel_PRESENT
|
|
;
|
|
; This little routine is called from grealloc, specifically
|
|
; racreate.
|
|
;
|
|
; Entry:
|
|
; parmW arena_sel
|
|
; parmW selector
|
|
;
|
|
; Returns:
|
|
; SI = selector to client area (may have changed)
|
|
;
|
|
; Registers Destroyed:
|
|
;
|
|
; History:
|
|
; Tue 06-Feb-1990 00:29:56 -by- David N. Weise [davidw]
|
|
; Cleaning up tony's int 1's way too late.
|
|
;
|
|
; Fri 15-Jul-1988 21:37:22 -by- David N. Weise [davidw]
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc mark_sel_PRESENT,<PUBLIC,NEAR>,<ax,bx,cx,dx,di,ds>
|
|
parmW arena_sel
|
|
parmW selector
|
|
localV DscBuf,DSC_LEN
|
|
cBegin
|
|
push es
|
|
smov es, ss
|
|
lea di, DscBuf ; ES:DI -> descriptor buffer
|
|
mov bx, selector
|
|
ifdef WOW
|
|
DPMICALL 000Bh ; Get old descriptor
|
|
else
|
|
push ds ; Get Descriptor
|
|
mov ds, gdtdsc
|
|
push si
|
|
mov si, bx
|
|
and si, not 7
|
|
MovsDsc
|
|
lea di, [di-DSC_LEN] ; Restore DI
|
|
pop si
|
|
pop ds
|
|
endif; WOW
|
|
or DscBuf.dsc_access, DSC_PRESENT
|
|
|
|
mov ds, arena_sel
|
|
mov bl, DscBuf.dsc_hlimit
|
|
and bl, 0Fh ; Current number of selectors - 1
|
|
inc bl
|
|
mov ax, ds:[ga_size]
|
|
mov cx, ax
|
|
dec cx
|
|
shr cx, 12 ; New number of selectors - 1
|
|
inc cl
|
|
sub bl, cl
|
|
jz go_ahead ; Same number, just fill in array
|
|
jb get_big ; More, must get more
|
|
|
|
; here to get small
|
|
|
|
and DscBuf.dsc_hlimit, NOT 0Fh
|
|
dec cl
|
|
or DscBuf.dsc_hlimit, cl ; Put new number of selectors in limit
|
|
inc cl
|
|
push cx
|
|
xor bh,bh ; BX = number of selectors to free
|
|
shl cx,3
|
|
.errnz DSC_LEN - 8
|
|
add cx,selector ; CX = selector to start to free
|
|
xchg bx,cx
|
|
@@: cCall free_sel,<bx>
|
|
lea bx, [bx+DSC_LEN]
|
|
loop @B
|
|
pop cx
|
|
jmps go_ahead ; And fill in remaining selectors
|
|
|
|
get_big:
|
|
push ax ; # paragraphs
|
|
mov bx, ds
|
|
DPMICALL 0006h ; Get base address of arena
|
|
add dx, 10h ; Move on to block
|
|
adc cx, 0
|
|
pop bx ; # paragraphs
|
|
mov ax, word ptr DscBuf.dsc_access ; Access bits in ax
|
|
cCall alloc_sel,<cx,dx,bx>
|
|
mov si, ax
|
|
or ax,ax ; did we get a set?
|
|
jz return_new_handle
|
|
or si, SEG_RING
|
|
test selector, IS_SELECTOR
|
|
jnz @F
|
|
StoH si
|
|
HtoS selector
|
|
@@:
|
|
SetKernelDS
|
|
mov ds, pGlobalHeap
|
|
UnSetKernelDS
|
|
cCall AssociateSelector,<selector,0>
|
|
cCall FreeSelArray,<selector> ; Zap old handle
|
|
jmps return_new_handle
|
|
|
|
go_ahead:
|
|
shl ax, 4 ; AX had length in paras
|
|
dec ax ; now limit in bytes
|
|
mov DscBuf.dsc_limit, ax ; Put in descriptor
|
|
push cx
|
|
mov bx, ds
|
|
DPMICALL 0006h ; Get base address of arena
|
|
add dx, 10h ; Move on to block
|
|
adc cx, 0
|
|
mov DscBuf.dsc_lbase, dx
|
|
mov DscBuf.dsc_mbase, cl
|
|
mov DscBuf.dsc_hbase, ch
|
|
pop cx ; # selectors
|
|
mov bx, selector
|
|
|
|
call fill_in_selector_array
|
|
mov si, selector ; return old selector in SI
|
|
return_new_handle:
|
|
pop es
|
|
cEnd
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; alloc_data_sel_below
|
|
;
|
|
;
|
|
; Entry:
|
|
;
|
|
; Returns:
|
|
;
|
|
; Registers Destroyed:
|
|
;
|
|
; History:
|
|
; Sat 09-Jul-1988 19:10:14 -by- David N. Weise [davidw]
|
|
;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc alloc_data_sel_below,<PUBLIC,NEAR>,<bx,cx,dx>
|
|
parmW selector
|
|
parmW paras
|
|
cBegin
|
|
mov bx, paras
|
|
xor cx, cx
|
|
rept 4
|
|
shl bx, 1
|
|
rcl cx, 1
|
|
endm
|
|
cCall get_physical_address,<selector>
|
|
sub ax, bx
|
|
sbb dx, cx
|
|
cCall alloc_data_sel,<dx, ax, 1>
|
|
cEnd
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; alloc_data_sel_above
|
|
;
|
|
;
|
|
; Entry:
|
|
;
|
|
; Returns:
|
|
;
|
|
; Registers Destroyed:
|
|
;
|
|
; History:
|
|
; Sat 09-Jul-1988 19:10:14 -by- David N. Weise [davidw]
|
|
;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc alloc_data_sel_above,<PUBLIC,NEAR>,<bx,cx,dx>
|
|
parmW selector
|
|
parmW paras
|
|
cBegin
|
|
mov bx, paras
|
|
xor cx, cx
|
|
rept 4
|
|
shl bx, 1
|
|
rcl cx, 1
|
|
endm
|
|
cCall get_physical_address,<selector>
|
|
add ax, bx
|
|
adc dx, cx
|
|
cCall alloc_data_sel,<dx, ax, 1>
|
|
cEnd
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; cmp_sel_address
|
|
;
|
|
; Compares the physical addresses corresponding to two selectors
|
|
;
|
|
; Entry:
|
|
;
|
|
; Returns:
|
|
;
|
|
; Registers Destroyed:
|
|
;
|
|
; History:
|
|
; Sat 09-Jul-1988 19:10:14 -by- David N. Weise [davidw]
|
|
;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc cmp_sel_address,<PUBLIC,NEAR>,<ax,bx,cx,dx>
|
|
parmW sel1
|
|
parmW sel2
|
|
cBegin
|
|
cCall get_physical_address,<sel1>
|
|
mov cx, dx
|
|
mov bx, ax
|
|
cCall get_physical_address,<sel2>
|
|
cmp cx, dx
|
|
jne csa_done
|
|
cmp bx, ax
|
|
csa_done:
|
|
cEnd
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; get_arena_pointer
|
|
;
|
|
;
|
|
; Entry:
|
|
;
|
|
; Returns:
|
|
;
|
|
; Registers Destroyed:
|
|
;
|
|
; History:
|
|
; Sat 09-Jul-1988 20:11:27 -by- David N. Weise [davidw]
|
|
;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc far_get_arena_pointer,<FAR,PUBLIC>
|
|
parmW selector
|
|
cBegin
|
|
cCall get_arena_pointer,<selector>
|
|
cEnd
|
|
|
|
cProc get_arena_pointer,<PUBLIC,NEAR>
|
|
parmW selector
|
|
cBegin
|
|
push bx
|
|
push ds
|
|
push es
|
|
|
|
mov bx, selector
|
|
cCall get_selector_association
|
|
ReSetKernelDS es
|
|
|
|
if ROM
|
|
test al,1 ; If the low bit isn't set
|
|
jnz @f ; then it's either 0 or the
|
|
xor ax,ax ; special ROM owner selector
|
|
jmps gap_exit ; (see Get/SetROMOwner)
|
|
@@:
|
|
endif
|
|
|
|
if KDEBUG
|
|
or ax, ax
|
|
jz gap_exit
|
|
mov ds, ax ; Sanity checks:
|
|
|
|
cmp ds:[ne_magic], NEMAGIC
|
|
je gap_exit
|
|
cmp ds:[0], 020CDh ; PSP - not a very good check,
|
|
je gap_exit ; but OK for DEBUG
|
|
push si
|
|
mov si, ds:[ga_handle] ; Make sure handle matches
|
|
sel_check si
|
|
or si, si
|
|
jz short gap_match ; Boot time...
|
|
sub bx, word ptr SelTableStart
|
|
shl bx, 2
|
|
cmp bx, si
|
|
je short gap_match
|
|
xor ax, ax ; put back in 5 feb 90, alias avoided
|
|
;;; xor ax, ax ; Removed - may be an alias!
|
|
gap_match:
|
|
pop si
|
|
endif ; KDEBUG
|
|
gap_exit:
|
|
pop es
|
|
pop ds
|
|
pop bx
|
|
cEnd
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; AssociateSelector
|
|
;
|
|
; Put the arena pointer or owner in the selector table slot
|
|
; corresponding to the given selector.
|
|
;
|
|
;
|
|
; Entry:
|
|
;
|
|
; Returns:
|
|
;
|
|
; Registers Destroyed:
|
|
; flags
|
|
;
|
|
; History:
|
|
;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc FarAssociateSelector,<PUBLIC,FAR>
|
|
parmW Selector
|
|
parmW ArenaSel
|
|
cBegin
|
|
cCall AssociateSelector,<Selector,ArenaSel>
|
|
cEnd
|
|
|
|
cProc AssociateSelector,<PUBLIC,NEAR>,<ax,bx,es>
|
|
parmW selector
|
|
parmW ArenaSel
|
|
cBegin
|
|
SetKernelDS es
|
|
|
|
CheckDS ; DS must bp pGlobalHeap
|
|
mov bx, selector
|
|
and bl, NOT SEG_RING_MASK
|
|
shr bx, 2 ; 2 bytes per selector: divide by 4
|
|
if KDEBUG
|
|
cmp bx, SelTableLen ; More sanity
|
|
jb @F
|
|
INT3_WARN
|
|
jmps bad
|
|
@@:
|
|
endif
|
|
|
|
add bx, word ptr SelTableStart
|
|
mov ax, ArenaSel
|
|
|
|
if KDEBUG
|
|
or ax, ax ; Zero means deleting entry
|
|
jz okay
|
|
CheckLDT al ; Ensure we won't GP fault later
|
|
okay:
|
|
endif
|
|
|
|
mov ds:[bx], ax ; Finally fill in table entry
|
|
bad:
|
|
cEnd
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; get_selector_association
|
|
;
|
|
; Returns the arena pointer or owner field from the selector table that
|
|
; was set by AssociateSelector.
|
|
;
|
|
;
|
|
; Entry:
|
|
; BX = selector to get associated arena pointer/owner
|
|
;
|
|
; Returns:
|
|
; AX = arena pointer/owner or 0
|
|
; DS = pGlobalHeap
|
|
; ES = Kernel DS
|
|
;
|
|
; Registers Destroyed:
|
|
; BX, flags
|
|
;
|
|
; History:
|
|
;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc get_selector_association,<PUBLIC,NEAR>
|
|
cBegin nogen
|
|
|
|
SetKernelDS es
|
|
mov ds, pGlobalHeap
|
|
|
|
and bl, NOT SEG_RING_MASK
|
|
shr bx, 2 ; 2 bytes per selector: divide by 4
|
|
|
|
if ROM ;-------------------------------
|
|
|
|
cmp bx, SelTableLen ; Selector in range? Make this check
|
|
jb gsa_in_range ; even if not debug kernel.
|
|
xor ax,ax ; No, just fail
|
|
jmps gsa_exit
|
|
gsa_in_range:
|
|
|
|
else ;ROM ------------------------
|
|
|
|
if KDEBUG
|
|
cmp bx, SelTableLen ; Selector in range?
|
|
jb @F
|
|
INT3_WARN
|
|
xor ax, ax ; No, just fail
|
|
jmps gsa_exit
|
|
@@:
|
|
endif
|
|
endif ;ROM ------------------------
|
|
|
|
add bx, word ptr SelTableStart
|
|
mov ax, ds:[bx] ; Get associated value
|
|
|
|
gsa_exit:
|
|
ret
|
|
cEnd nogen
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; pdref ;
|
|
; ;
|
|
; Dereferences the given global handle, i.e. gives back abs. address. ;
|
|
; ;
|
|
; Arguments: ;
|
|
; DX = selector ;
|
|
; DS:DI = BURGERMASTER ;
|
|
; ;
|
|
; Returns: ;
|
|
; ES:DI = address of arena header ;
|
|
; AX = address of client data ;
|
|
; CH = lock count or 0 for fixed objects ;
|
|
; CL = flags ;
|
|
; SI = handle, 0 for fixed objects ;
|
|
; ;
|
|
; Error Returns: ;
|
|
; ZF = 1 if invalid or discarded ;
|
|
; AX = 0 ;
|
|
; BX = owner of discarded object ;
|
|
; ;
|
|
; Registers Preserved: ;
|
|
; ;
|
|
; Registers Destroyed: ;
|
|
; ;
|
|
; Calls: ;
|
|
; ghdref ;
|
|
; ;
|
|
; History: ;
|
|
; ;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc pdref,<PUBLIC,NEAR>
|
|
|
|
cBegin nogen
|
|
mov si, dx
|
|
sel_check si
|
|
|
|
or si, si ; Null handle?
|
|
mov ax, si
|
|
jz pd_exit ; yes, return 0
|
|
|
|
cCall GetAccessWord,<dx> ; Get the access bits
|
|
or ax, ax
|
|
jz pd_totally_bogus
|
|
|
|
; We should beef up the check for a valid discarded sel.
|
|
|
|
xor cx,cx
|
|
test ah, DSC_DISCARDABLE
|
|
jz pd_not_discardable
|
|
or cl,GA_DISCARDABLE
|
|
; Discardable, is it code?
|
|
test al,DSC_CODE_BIT
|
|
jz pd_not_code
|
|
or cl,GA_DISCCODE
|
|
pd_not_code:
|
|
|
|
pd_not_discardable:
|
|
test al,DSC_PRESENT
|
|
jnz pd_not_discarded
|
|
|
|
; object discarded
|
|
|
|
or cl,HE_DISCARDED
|
|
ife RING-1
|
|
or si, SEG_RING+1 ; Handles are RING 2
|
|
else
|
|
or si, SEG_RING-1 ; Handles are RING 2
|
|
endif
|
|
cCall get_arena_pointer,<si> ; get the owner
|
|
mov bx, ax
|
|
xor ax,ax
|
|
jmps pd_exit
|
|
|
|
pd_not_discarded:
|
|
if KDEBUG
|
|
or si, SEG_RING ; For the sel_check later
|
|
endif
|
|
cCall get_arena_pointer,<si>
|
|
or ax, ax
|
|
jz pd_nomatch
|
|
mov es, ax
|
|
mov ax, es:[ga_handle] ; The real thing
|
|
mov si, ax
|
|
cmp ax, dx ; Quick check - handle in header
|
|
je pd_match ; matches what we were given?
|
|
|
|
test dl, IS_SELECTOR ; NOW, we MUST have been given
|
|
jz pd_totally_bogus ; a selector!!
|
|
test al, GA_FIXED ; Fixed segment?
|
|
jnz pd_nomatch ; Doesn't match arena header...
|
|
push ax
|
|
HtoS al
|
|
cmp ax, dx ; Selector must match
|
|
pop ax
|
|
jne pd_nomatch
|
|
pd_match:
|
|
or cl, es:[ga_flags]
|
|
and cl, NOT HE_DISCARDED ; same as GA_NOTIFY!!
|
|
test al, GA_FIXED
|
|
jnz pd_fixed
|
|
mov ch, es:[ga_count]
|
|
HtoS al ; Back to ring 1
|
|
|
|
pd_exit:
|
|
or ax,ax
|
|
ret
|
|
|
|
pd_totally_bogus:
|
|
if KDEBUG
|
|
or dx,dx
|
|
jnz dref_invalid
|
|
pd_null_passed:
|
|
endif
|
|
xor dx,dx
|
|
|
|
pd_nomatch: ; Handle did not match...
|
|
mov ax, dx ; Must be an alias...
|
|
pd_fixed:
|
|
xor si, si
|
|
xor dx, dx
|
|
jmps pd_exit
|
|
|
|
if KDEBUG
|
|
dref_invalid:
|
|
push ax
|
|
kerror ERR_GMEMHANDLE,<gdref: invalid handle>,0,dx
|
|
pop ax
|
|
jmps pd_null_passed
|
|
endif
|
|
cEnd nogen
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; get_rover_2 ;
|
|
; ;
|
|
; Entry: ;
|
|
; ;
|
|
; Returns: ;
|
|
; ;
|
|
; Error Returns: ;
|
|
; ;
|
|
; Registers Preserved: ;
|
|
; AX,BX,CX,DX,DI,SI,DS ;
|
|
; ;
|
|
; Registers Destroyed: ;
|
|
; ;
|
|
; Calls: ;
|
|
; ;
|
|
; History: ;
|
|
; ;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc get_rover_2,<PUBLIC,NEAR>,<ax,bx,di>
|
|
localV DscBuf,DSC_LEN
|
|
cBegin
|
|
mov bx, es
|
|
lea di, DscBuf
|
|
smov es, ss
|
|
ifdef WOW
|
|
DPMICALL 000Bh ; Get source descriptor
|
|
else
|
|
push ds ; Get Descriptor
|
|
mov ds, gdtdsc
|
|
push si
|
|
mov si, bx
|
|
and si, not 7
|
|
MovsDsc
|
|
lea di, [di-DSC_LEN] ; Restore DI
|
|
pop si
|
|
pop ds
|
|
endif; WOW
|
|
SetKernelDS es
|
|
mov bx, kr2dsc ; Will set kr2 to point there
|
|
or bl, SEG_RING
|
|
mov word ptr DscBuf.dsc_access, DSC_PRESENT+DSC_DATA
|
|
mov DscBuf.dsc_limit, 0FFFFh
|
|
smov es, ss
|
|
UnSetKernelDS es
|
|
ifdef WOW
|
|
DPMICALL 000Ch
|
|
else
|
|
push ds
|
|
mov ds, gdtdsc
|
|
push bx ; Set Descriptor
|
|
and bl, not 7
|
|
mov ax, es:[di] ; This looks slow but it isn't...
|
|
mov ds:[bx], ax
|
|
mov ax, es:[di][2]
|
|
mov ds:[bx][2], ax
|
|
mov ax, es:[di][4]
|
|
mov ds:[bx][4], ax
|
|
mov ax, es:[di][6]
|
|
mov ds:[bx][6], ax
|
|
if 0 ;;ROM and KDEBUG
|
|
call CheckROMSelector
|
|
endif
|
|
pop bx
|
|
pop ds
|
|
endif; WOW
|
|
mov es, bx
|
|
cEnd
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; get_blotto
|
|
;
|
|
;
|
|
; Entry:
|
|
; AX = arena header
|
|
;
|
|
; Returns:
|
|
;
|
|
; Registers Destroyed:
|
|
;
|
|
; History:
|
|
; Sun 31-Jul-1988 16:20:53 -by- David N. Weise [davidw]
|
|
;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc get_blotto,<PUBLIC,NEAR>,<bx,di,es>
|
|
localV DscBuf,DSC_LEN
|
|
cBegin
|
|
mov bx, ax
|
|
lea di, DscBuf
|
|
smov es, ss
|
|
ifdef WOW
|
|
DPMICALL 000Bh ; Get source descriptor
|
|
else
|
|
push ds ; Get Descriptor
|
|
mov ds, gdtdsc
|
|
push si
|
|
mov si, bx
|
|
and si, not 7
|
|
MovsDsc
|
|
lea di, [di-DSC_LEN] ; Restore DI
|
|
pop si
|
|
pop ds
|
|
endif
|
|
SetKernelDS es
|
|
mov bx, blotdsc ; Will set kr2 to point there
|
|
or bl, SEG_RING
|
|
mov word ptr DscBuf.dsc_access, DSC_PRESENT+DSC_DATA
|
|
mov DscBuf.dsc_limit, 0FFFFh
|
|
mov DscBuf.dsc_hlimit, 0Fh
|
|
add DscBuf.dsc_lbase, 10h ; Move on to object from arena
|
|
adc DscBuf.dsc_mbase, 0
|
|
adc DscBuf.dsc_hbase, 0
|
|
smov es, ss
|
|
UnSetKernelDS es
|
|
ifdef WOW
|
|
DPMICALL 000Ch ; Set new descriptor
|
|
else
|
|
push ds
|
|
mov ds, gdtdsc
|
|
push bx ; Set Descriptor
|
|
and bl, not 7
|
|
mov ax, es:[di] ; This looks slow but it isn't...
|
|
mov ds:[bx], ax
|
|
mov ax, es:[di][2]
|
|
mov ds:[bx][2], ax
|
|
mov ax, es:[di][4]
|
|
mov ds:[bx][4], ax
|
|
mov ax, es:[di][6]
|
|
mov ds:[bx][6], ax
|
|
if 0 ;;ROM and KDEBUG
|
|
call CheckROMSelector
|
|
endif
|
|
pop bx
|
|
pop ds
|
|
endif ;WOW
|
|
mov ax, bx ; Return new selector
|
|
cEnd
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; get_temp_sel
|
|
; far_get_temp_sel
|
|
;
|
|
;
|
|
; Entry:
|
|
;
|
|
; Returns:
|
|
;
|
|
; Registers Destroyed:
|
|
;
|
|
; History:
|
|
; Mon 08-Aug-1988 19:14:45 -by- David N. Weise [davidw]
|
|
;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc far_get_temp_sel,<FAR,PUBLIC>
|
|
cBegin nogen
|
|
cCall get_temp_sel
|
|
ret
|
|
cEnd nogen
|
|
|
|
cProc get_temp_sel,<PUBLIC,NEAR>,<ax,bx,cx,di,si,ds>
|
|
localV DscBuf,DSC_LEN
|
|
cBegin
|
|
mov cx, 1
|
|
call get_sel
|
|
mov ax, si
|
|
jz gts_exit
|
|
|
|
mov bx, es
|
|
smov es, ss
|
|
lea di, DscBuf
|
|
ifdef WOW
|
|
DPMICALL 000Bh ; Get existing descriptor
|
|
else
|
|
push ds ; Get Descriptor
|
|
mov ds, gdtdsc
|
|
push si
|
|
mov si, bx
|
|
and si, not 7
|
|
MovsDsc
|
|
lea di, [di-DSC_LEN] ; Restore DI
|
|
pop si
|
|
pop ds
|
|
endif ; WOW
|
|
|
|
mov DscBuf.dsc_access,DSC_PRESENT+DSC_DATA
|
|
mov DscBuf.dsc_limit,0ffffh
|
|
IFNDEF WOW
|
|
or DscBuf.dsc_hlimit, 0Fh ; Max length ; bugbug daveh
|
|
ENDIF
|
|
mov bx, si
|
|
or bl, SEG_RING
|
|
ifdef WOW
|
|
DPMICALL 000Ch ; Set new descriptor
|
|
else
|
|
push ds
|
|
mov ds, gdtdsc
|
|
push bx ; Set Descriptor
|
|
and bl, not 7
|
|
mov ax, es:[di] ; This looks slow but it isn't...
|
|
mov ds:[bx], ax
|
|
mov ax, es:[di][2]
|
|
mov ds:[bx][2], ax
|
|
mov ax, es:[di][4]
|
|
mov ds:[bx][4], ax
|
|
mov ax, es:[di][6]
|
|
mov ds:[bx][6], ax
|
|
if 0 ;;ROM and KDEBUG
|
|
call CheckROMSelector
|
|
endif
|
|
pop bx
|
|
pop ds
|
|
endif ; WOW
|
|
mov es, bx ; and return selector in ES
|
|
gts_exit:
|
|
cEnd
|
|
|
|
cProc far_free_temp_sel,<FAR,PUBLIC>
|
|
parmW selector
|
|
cBegin
|
|
cCall free_sel,<selector>
|
|
cEnd
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; PrestoChangoSel
|
|
;
|
|
;
|
|
; Entry:
|
|
;
|
|
; Returns:
|
|
;
|
|
; Registers Destroyed:
|
|
;
|
|
; History:
|
|
; Thu 08-Dec-1988 14:17:38 -by- David N. Weise [davidw]
|
|
; Wrote it!
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc IPrestoChangoSelector,<PUBLIC,FAR>,<di,si>
|
|
parmW sourcesel
|
|
parmW destsel
|
|
localV DscBuf,DSC_LEN
|
|
cBegin
|
|
smov es, ss
|
|
lea di, DscBuf
|
|
mov bx, sourcesel
|
|
ifdef WOW
|
|
DPMICALL 000Bh
|
|
else
|
|
push ds ; Get Descriptor
|
|
mov ds, gdtdsc
|
|
push si
|
|
mov si, bx
|
|
and si, not 7
|
|
MovsDsc
|
|
lea di, [di-DSC_LEN] ; Restore DI
|
|
pop si
|
|
pop ds
|
|
endif ; WOW
|
|
xor DscBuf.dsc_access, DSC_CODE_BIT
|
|
mov bx, destsel
|
|
ifdef WOW
|
|
DPMICALL 000Ch
|
|
else
|
|
push ds
|
|
mov ds, gdtdsc
|
|
push bx ; Set Descriptor
|
|
and bl, not 7
|
|
mov ax, es:[di] ; This looks slow but it isn't...
|
|
mov ds:[bx], ax
|
|
mov ax, es:[di][2]
|
|
mov ds:[bx][2], ax
|
|
mov ax, es:[di][4]
|
|
mov ds:[bx][4], ax
|
|
mov ax, es:[di][6]
|
|
mov ds:[bx][6], ax
|
|
if 0 ;;ROM and KDEBUG
|
|
call CheckROMSelector
|
|
endif
|
|
pop bx
|
|
pop ds
|
|
endif; WOW
|
|
mov ax, bx
|
|
smov es, 0
|
|
cEnd
|
|
|
|
|
|
if 0
|
|
;-----------------------------------------------------------------------;
|
|
; pmnum ;
|
|
; ;
|
|
; Enumerates the allocated selectors in the GDT with the ;
|
|
; specified discard level. ;
|
|
; ;
|
|
; Arguments: ;
|
|
; SI = zero first time called. Otherwise contains a pointer ;
|
|
; to the last handle returned. ;
|
|
; CX = #handles remaining. Zero first time called. ;
|
|
; DI = address of local arena information structure. ;
|
|
; ;
|
|
; Returns: ;
|
|
; SI = address of handle table entry ;
|
|
; CX = #handles remaining, including the one returned. ;
|
|
; ZF = 1 if SI = 0 and no more handle table entries. ;
|
|
; ;
|
|
; Error Returns: ;
|
|
; ;
|
|
; Registers Preserved: ;
|
|
; ;
|
|
; Registers Destroyed: ;
|
|
; AX ;
|
|
; ;
|
|
; Calls: ;
|
|
; nothing ;
|
|
; ;
|
|
; History: ;
|
|
; ;
|
|
; Tue Oct 14, 1986 04:19:15p -by- David N. Weise [davidw] ;
|
|
; Added this nifty comment block. ;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
cProc pmnum,<PUBLIC,NEAR>
|
|
cBegin nogen
|
|
or si,si ; Beginning of enumeration?
|
|
jnz lcdhenext ; No, return next handle
|
|
mov ax,[di].hi_htable ; Yes, start with last handle table block
|
|
|
|
lcdhtloop:
|
|
mov si,ax ; SI = address of handle table block
|
|
or si,si ; Any more handle table blocks?
|
|
jz lcdheall ; No, return zero
|
|
lodsw ; Get # handles in this block
|
|
errnz ht_count
|
|
mov cx,ax ; into CX
|
|
lcdheloop: ; Loop to process each handle table entry
|
|
mov ax,word ptr [si].lhe_flags
|
|
errnz <lhe_flags - he_flags>
|
|
errnz <2-lhe_flags>
|
|
errnz <3-lhe_count>
|
|
|
|
inc ax ; Free handle?
|
|
jz lcdhenext ; Yes, skip this handle
|
|
errnz <LHE_FREEHANDLE - 0FFFFh>
|
|
errnz <LHE_FREEHANDLE - HE_FREEHANDLE >
|
|
dec ax
|
|
|
|
cmp [di].hi_dislevel,0 ; Enumerating all allocated handles?
|
|
je lcdheall ; Yes, return this handle
|
|
|
|
test al,LHE_DISCARDED ; No, handle already discarded?
|
|
jnz lcdhenext ; Yes, skip this handle
|
|
|
|
and al,LHE_DISCARDABLE ; Test if DISCARDABLE
|
|
cmp [di].hi_dislevel,al ; at the current discard level
|
|
jne lcdhenext ; No, skip this handle
|
|
|
|
or ah,ah ; Is handle locked?
|
|
jnz lcdhenext ; Yes, skip this handle
|
|
|
|
lcdheall:
|
|
or si,si ; No, then return handle to caller
|
|
ret ; with Z flag clear
|
|
|
|
lcdhenext:
|
|
lea si,[si].SIZE LocalHandleEntry ; Point to next handle table entry
|
|
errnz <LocalHandleEntry - HandleEntry>
|
|
loop lcdheloop ; Process next handle table entry
|
|
lodsw ; end of this block, go to next
|
|
jmp lcdhtloop
|
|
cEnd nogen
|
|
endif
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; LongPtrAdd
|
|
;
|
|
; Performs segment arithmetic on a long pointer and a DWORD offset
|
|
; The resulting pointer is normalized to a paragraph boundary.
|
|
; The offset cannot be greater than a megabyte.
|
|
;
|
|
; Entry:
|
|
;
|
|
; Returns:
|
|
; DX:AX new segment:offset
|
|
;
|
|
; Error returns:
|
|
; DX:AX = 0
|
|
;
|
|
; Registers Destroyed:
|
|
; BX,CX
|
|
;
|
|
; History:
|
|
; Mon 19-Dec-1988 18:37:23 -by- David N. Weise [davidw]
|
|
; Wrote it!
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
ifdef WOW
|
|
|
|
LPTRADDWOW_SETBASE equ 01h
|
|
|
|
;cProc LongPtrAddWOW,<PUBLIC,FAR>,<si,di>
|
|
; parmD long_ptr
|
|
; parmD delta
|
|
; parmW RefSelector
|
|
; parmW flBaseSetting
|
|
;
|
|
; effectively pops RefSelector and flBaseSetting into dx and ax.
|
|
; and jumps to longptrAddWorker.
|
|
;
|
|
; RefSelector is used only if the descriptor needs to be set.
|
|
;
|
|
|
|
labelFP <PUBLIC,LongPtrAddWOW>
|
|
pop ax
|
|
pop dx ; far return address
|
|
mov bx,sp
|
|
xchg ax, ss:[bx] ; replace the 'dword' with the return address
|
|
xchg dx, ss:[bx+2]
|
|
jmps LongPtrAddWorker ; ax = flags; dx = reference selector
|
|
|
|
labelFP <PUBLIC,LongPtrAdd>
|
|
mov ax, LPTRADDWOW_SETBASE
|
|
xor dx, dx
|
|
; fall through
|
|
|
|
cProc LongPtrAddWorker,<PUBLIC,FAR>,<si,di>
|
|
parmD long_ptr
|
|
parmD delta
|
|
localV DscBuf,DSC_LEN
|
|
localW flBaseSetting
|
|
localW RefSelector
|
|
cBegin
|
|
mov flBaseSetting, ax ; save in localvariables
|
|
mov RefSelector, dx
|
|
or dx, dx ; if RefSelector is nonzero
|
|
jz @F ; use it for querying descriptor info.
|
|
xchg dx, word ptr long_ptr[2] ; and store the selector to be set in
|
|
mov RefSelector, dx ; the localvariable
|
|
@@:
|
|
else
|
|
|
|
cProc LongPtrAdd,<PUBLIC,FAR>,<si,di>
|
|
parmD long_ptr
|
|
parmD delta
|
|
localV DscBuf,DSC_LEN
|
|
cBegin
|
|
|
|
endif
|
|
mov bx,word ptr long_ptr[2]
|
|
lea di, DscBuf
|
|
smov es, ss
|
|
ifdef WOW
|
|
DPMICALL 000Bh ; Pick up old descriptor
|
|
else
|
|
push ds ; Get Descriptor
|
|
mov ds, gdtdsc
|
|
push si
|
|
mov si, bx
|
|
and si, not 7
|
|
MovsDsc
|
|
lea di, [di-DSC_LEN] ; Restore DI
|
|
pop si
|
|
pop ds
|
|
endif ; WOW
|
|
mov ax,word ptr long_ptr[0] ; get the pointer into SI:AX
|
|
and ax,0FFF0h
|
|
|
|
mov si, DscBuf.dsc_lbase ; DX:SI gets old base
|
|
mov dl, DscBuf.dsc_mbase
|
|
mov dh, DscBuf.dsc_hbase
|
|
|
|
add si, ax ; Add in old pointer offset
|
|
adc dx, 0
|
|
|
|
mov cx, word ptr delta[2] ; add the segment and MSW
|
|
test cx, 0FFF0h
|
|
ifdef WOW
|
|
jz @F
|
|
test flBaseSetting, LPTRADDWOW_SETBASE
|
|
jnz lptr_mustset
|
|
jmp short lpa_too_big
|
|
@@:
|
|
else
|
|
jnz short lpa_too_big
|
|
endif
|
|
|
|
add si, word ptr delta[0]
|
|
adc dx, cx
|
|
|
|
ifdef WOW
|
|
lptr_mustset:
|
|
endif
|
|
|
|
mov cl, DscBuf.dsc_hlimit ; Calculate # selectors now in array
|
|
and cl, 0Fh
|
|
xor ch, ch
|
|
inc cx
|
|
|
|
ifdef WOW
|
|
test flBaseSetting, LPTRADDWOW_SETBASE
|
|
jz lptr_dontset
|
|
cmp RefSelector, 0
|
|
jz @F
|
|
mov bx, RefSelector
|
|
mov word ptr long_ptr[2], bx
|
|
@@:
|
|
endif
|
|
mov DscBuf.dsc_lbase, si ; Put new base back in descriptor
|
|
mov DscBuf.dsc_mbase, dl
|
|
mov DscBuf.dsc_hbase, dh
|
|
|
|
call fill_in_selector_array
|
|
|
|
ifdef WOW
|
|
lptr_dontset:
|
|
test word ptr delta[2], 0fff0h
|
|
jz @F
|
|
mov cx, word ptr delta[2]
|
|
jmps lpa_too_big
|
|
@@:
|
|
endif
|
|
mov dx,word ptr long_ptr[2]
|
|
mov ax,word ptr long_ptr[0]
|
|
and ax, 0Fh
|
|
jmps lpa_exit
|
|
|
|
lpa_too_big:
|
|
xor ax,ax
|
|
xor dx,dx
|
|
lpa_exit:
|
|
smov es,0
|
|
cEnd
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; SetSelectorBase
|
|
;
|
|
; Sets the base and limit of the given selector.
|
|
;
|
|
; Entry:
|
|
; parmW selector
|
|
; parmD selbase
|
|
;
|
|
; Returns:
|
|
; AX = selector
|
|
;
|
|
; Error Returns:
|
|
; AX = 0
|
|
;
|
|
; History:
|
|
; Tue 23-May-1989 21:10:29 -by- David N. Weise [davidw]
|
|
; Wrote it!
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc SetSelectorBase,<PUBLIC,FAR>
|
|
parmW selector
|
|
parmD selbase
|
|
cBegin
|
|
mov bx, selector
|
|
mov dx, selbase.lo
|
|
mov cx, selbase.hi
|
|
ifdef WOW
|
|
DPMICALL 0007h
|
|
else
|
|
push ds
|
|
mov ds, gdtdsc
|
|
push bx
|
|
and bl, not 7
|
|
mov ds:[bx].dsc_lbase, dx
|
|
mov ds:[bx].dsc_mbase, cl
|
|
mov ds:[bx].dsc_hbase, ch
|
|
pop bx
|
|
pop ds
|
|
endif ; WOW
|
|
mov ax, 0
|
|
jc ssb_exit
|
|
mov ax, selector ; Return selector
|
|
ssb_exit:
|
|
cEnd
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; GetSelectorLimit
|
|
;
|
|
; Gets the limit of the given selector.
|
|
;
|
|
; Entry:
|
|
; parmW selector
|
|
;
|
|
; Returns:
|
|
; DX:AX = limit of selector
|
|
;
|
|
; Registers Destroyed:
|
|
;
|
|
; History:
|
|
; Tue 23-May-1989 21:10:29 -by- David N. Weise [davidw]
|
|
; Wrote it!
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc GetSelectorLimit,<PUBLIC,FAR>
|
|
parmW selector
|
|
localV DscBuf,DSC_LEN
|
|
cBegin
|
|
mov bx, selector
|
|
ifdef WOW
|
|
lea di, DscBuf
|
|
smov es, ss
|
|
DPMICALL 000Bh
|
|
xor dx, dx
|
|
mov ax, DscBuf.dsc_limit
|
|
mov dl, DscBuf.dsc_hlimit
|
|
and dx, 0Fh ; AND out flags
|
|
else
|
|
push ds ; Get Descriptor
|
|
mov ds, gdtdsc
|
|
and bl, not 7
|
|
mov ax, [bx].dsc_limit
|
|
mov dl, [bx].dsc_hlimit
|
|
and dx, 0Fh ; AND out flags
|
|
pop ds
|
|
endif ; WOW
|
|
cEnd
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; SetSelectorLimit
|
|
;
|
|
; Sets the limit of the given selector.
|
|
;
|
|
; Entry:
|
|
; parmW selector
|
|
; parmD sellimit
|
|
;
|
|
; Returns:
|
|
; AX = 0 success
|
|
;
|
|
; Registers Destroyed:
|
|
;
|
|
; History:
|
|
; Tue 23-May-1989 21:10:29 -by- David N. Weise [davidw]
|
|
; Wrote it!
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc SetSelectorLimit,<PUBLIC,FAR>
|
|
parmW selector
|
|
parmD sellimit
|
|
localV DscBuf,DSC_LEN
|
|
cBegin
|
|
mov bx, selector
|
|
ifdef WOW
|
|
push di
|
|
lea di, DscBuf
|
|
smov es, ss
|
|
DPMICALL 000Bh
|
|
mov ax, word ptr sellimit[0]
|
|
mov DscBuf.dsc_limit, ax
|
|
mov al, byte ptr sellimit[2]
|
|
and al, 0Fh
|
|
and DscBuf.dsc_hlimit, 0F0h
|
|
or DscBuf.dsc_hlimit, al
|
|
DPMICALL 000Ch
|
|
pop di
|
|
else
|
|
push ds ; Get Descriptor
|
|
mov ds, gdtdsc
|
|
push si
|
|
mov si, bx
|
|
and si, not 7
|
|
mov ax, sellimit.lo
|
|
mov [si].dsc_limit, ax
|
|
mov ax, sellimit.hi
|
|
and al, 0Fh
|
|
and [si].dsc_hlimit, 0F0h
|
|
or [si].dsc_hlimit, al
|
|
pop si
|
|
pop ds
|
|
endif ;WOW
|
|
xor ax,ax ; for now always return success
|
|
cEnd
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; SelectorAccessRights
|
|
;
|
|
; Sets the access and other bytes of the given selector.
|
|
;
|
|
; Entry:
|
|
; parmW selector
|
|
; parmW getsetflag
|
|
; parmD selrights
|
|
;
|
|
; Returns:
|
|
; AX = 0 success
|
|
;
|
|
; Registers Destroyed:
|
|
;
|
|
; History:
|
|
; Tue 23-May-1989 21:10:29 -by- David N. Weise [davidw]
|
|
; Wrote it!
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc SelectorAccessRights,<PUBLIC,FAR>
|
|
|
|
parmW selector
|
|
parmW getsetflag
|
|
parmW selrights
|
|
localV DscBuf,DSC_LEN
|
|
cBegin
|
|
|
|
cCall GetAccessWord,<selector>
|
|
cmp getsetflag,0
|
|
jnz short sar_set
|
|
|
|
and ax, 0D01Eh ; Hide bits they can't play with
|
|
jmps sar_exit
|
|
|
|
sar_set:
|
|
mov cx, selrights
|
|
and cx, 0D01Eh ; Zap bits they can't set and
|
|
and ax, NOT 0D01Eh ; get them from existing access rights
|
|
or cx, ax
|
|
mov bx, selector
|
|
ifdef WOW
|
|
push di
|
|
lea di, DscBuf
|
|
smov es, ss
|
|
DPMICALL 000Bh ; Set new access rights
|
|
mov word ptr DscBuf.dsc_access, cx
|
|
DPMICALL 000Ch
|
|
pop di
|
|
else
|
|
push ds ; Get Descriptor
|
|
mov ds, gdtdsc
|
|
and bx, not 7
|
|
mov word ptr [bx].dsc_access, cx
|
|
pop ds
|
|
endif ;WOW
|
|
xor ax,ax ; for now always return success
|
|
|
|
sar_exit:
|
|
|
|
cEnd
|
|
|
|
;
|
|
; Direct GDT access is really helpful here - you are supposed
|
|
; to use LAR to get the high access bits, but this
|
|
; cannot be done on a 286 where we are STILL using
|
|
; these bits in a 386 compatible manner
|
|
;
|
|
|
|
cProc GetAccessWord,<PUBLIC,NEAR>
|
|
parmW selector
|
|
localV DscBuf,DSC_LEN
|
|
cBegin
|
|
push bx
|
|
push es
|
|
cmp gdtdsc, 0 ; Do we have LDT access?
|
|
je do_it_the_really_slow_way ; no, must make DPMI call
|
|
|
|
mov es, gdtdsc ; Go grab it out of the LDT
|
|
mov bx, selector
|
|
sel_check bl
|
|
mov ax, word ptr es:[bx].dsc_access
|
|
jmps gaw_exit
|
|
|
|
do_it_the_really_slow_way:
|
|
push di
|
|
lea di, DscBuf
|
|
smov es, ss
|
|
mov bx, selector
|
|
DPMICALL 000Bh
|
|
mov ax, word ptr DscBuf.dsc_access
|
|
pop di
|
|
gaw_exit:
|
|
pop es
|
|
pop bx
|
|
gaw_exit1:
|
|
cEnd
|
|
|
|
;
|
|
; Setting it is WORSE....
|
|
;
|
|
cProc SetAccessWord,<PUBLIC,NEAR>,<ax,bx,es>
|
|
parmW selector
|
|
parmW access
|
|
localV DscBuf,DSC_LEN
|
|
cBegin
|
|
mov bx, selector
|
|
ifndef WOW ; For WOW we have to call DMPI, LATER for mips this should party directly
|
|
cmp gdtdsc, 0
|
|
je slow_again
|
|
|
|
mov es, gdtdsc ; Go stuff it in the LDT
|
|
sel_check bl
|
|
mov ax, access
|
|
mov word ptr es:[bx].dsc_access, ax
|
|
jmps saw_exit
|
|
|
|
endif ; WOW
|
|
slow_again:
|
|
;
|
|
; The DPMI guys changed their mind, NOW call 9h
|
|
; WILL set the AVL bit in the descriptor on
|
|
; all implementations.
|
|
;
|
|
sel_check bl
|
|
push cx
|
|
mov cx, access
|
|
DPMICALL 0009h
|
|
pop cx
|
|
saw_exit:
|
|
cEnd
|
|
|
|
;
|
|
; Selector in BX
|
|
;
|
|
cProc GetSelectorCount,<PUBLIC,NEAR>
|
|
cBegin nogen
|
|
cmp gdtdsc, 0
|
|
je @F
|
|
push ds
|
|
push bx
|
|
mov ds, gdtdsc
|
|
sel_check bl
|
|
mov al, ds:[bx].dsc_hlimit
|
|
pop bx
|
|
pop ds
|
|
and ax, 0Fh
|
|
inc al
|
|
ret
|
|
@@:
|
|
push es
|
|
push di
|
|
sub sp, DSC_LEN
|
|
mov di, sp
|
|
smov es, ss
|
|
DPMICALL 000Bh
|
|
mov al, es:[di].dsc_hlimit
|
|
add sp, DSC_LEN
|
|
pop di
|
|
pop es
|
|
and ax, 0Fh
|
|
inc al
|
|
ret
|
|
cEnd nogen
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; GlobalPageLock
|
|
;
|
|
; Page locks the memory associated with the Handle.
|
|
;
|
|
; Entry:
|
|
; parmW handle
|
|
;
|
|
; Returns:
|
|
; AX = new lock count
|
|
;
|
|
; History:
|
|
; Fri 16-Feb-1990 02:13:09 -by- David N. Weise [davidw]
|
|
; Should it or shouldn't it? At the very least it must lock
|
|
; the object to be consitent with 386pmode.
|
|
;
|
|
; Wed 31-May-1989 22:14:21 -by- David N. Weise [davidw]
|
|
; Wrote it!
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc IGlobalPageLock,<PUBLIC,FAR>,<si,di>
|
|
|
|
parmW handle
|
|
cBegin
|
|
cCall GlobalFix,<handle>
|
|
cCall GetSelectorLimit,<handle>
|
|
mov si, dx
|
|
mov di, ax
|
|
cCall get_physical_address,<handle>
|
|
mov bx, dx
|
|
mov cx, ax
|
|
DPMICALL 0600h
|
|
mov ax, 1
|
|
cEnd
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; GlobalPageUnlock
|
|
;
|
|
; Page unlocks the memory associated with the Handle.
|
|
;
|
|
; Entry:
|
|
; parmW handle
|
|
;
|
|
; Returns:
|
|
; AX = new lock count
|
|
;
|
|
; History:
|
|
; Fri 16-Feb-1990 02:13:09 -by- David N. Weise [davidw]
|
|
; Should it or shouldn't it? At the very least it must unlock
|
|
; the object to be consitent with 386pmode.
|
|
;
|
|
; Wed 31-May-1989 22:14:21 -by- David N. Weise [davidw]
|
|
; Wrote it!
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc IGlobalPageUnlock,<PUBLIC,FAR>,<si,di>
|
|
|
|
parmW handle
|
|
cBegin
|
|
cCall GlobalUnFix,<handle>
|
|
cCall GetSelectorLimit,<handle>
|
|
mov si, dx
|
|
mov di, ax
|
|
cCall get_physical_address,<handle>
|
|
mov bx, dx
|
|
mov cx, ax
|
|
DPMICALL 0601h
|
|
xor ax,ax ; page lock count is zero
|
|
cEnd
|
|
|
|
|
|
if ROM ;----------------------------------------------------------------
|
|
|
|
;-----------------------------------------------------------------------
|
|
; ChangeROMHandle
|
|
;
|
|
; Changes the handle of an allocated memory block. Used when loading
|
|
; segments from ROM to RAM so RAM copy can use the handle expected by
|
|
; other ROM code.
|
|
;
|
|
; Entry:
|
|
; parmW hOld
|
|
; parmW hNew
|
|
;
|
|
; Returns:
|
|
; AX = hNew if successful, 0 if not
|
|
;
|
|
; History:
|
|
;
|
|
;-----------------------------------------------------------------------
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
|
|
cProc ChangeROMHandle,<PUBLIC,FAR>,<bx,si,di,ds,es>
|
|
parmW hOld
|
|
parmW hNew
|
|
localV DscBuf,DSC_LEN
|
|
cBegin
|
|
mov bx,hOld ; Get arena pointer for old handle
|
|
cCall get_arena_pointer,<bx>
|
|
or ax,ax
|
|
if KDEBUG
|
|
jnz @f
|
|
INT3_WARN
|
|
jmps ch_ret
|
|
@@:
|
|
else
|
|
jz ch_ret
|
|
endif
|
|
push ax
|
|
mov si, bx
|
|
and bx, SEG_RING_MASK ; Ring bits
|
|
or bx, hNew ; New handle
|
|
smov es, ss
|
|
lea di, DscBuf
|
|
xchg bx ,si
|
|
DPMICALL 000Bh ; Get old descriptor
|
|
xchg bx, si
|
|
DPMICALL 000Ch ; Set new descriptor
|
|
pop es ; es -> arena (or owner)
|
|
|
|
SetKernelDS
|
|
mov ds, pGlobalHeap
|
|
UnSetKernelDS
|
|
cCall AssociateSelector,<si,0> ; Old sel has not association
|
|
|
|
test DscBuf.dsc_access,DSC_PRESENT ; Change handle in arena
|
|
jz crh_np ; if selector is present
|
|
mov es:[ga_handle], bx
|
|
crh_np:
|
|
cCall AssociateSelector,<bx,es> ; New sel associated with this
|
|
; arena or owner
|
|
cCall FreeSelArray,<hOld> ; Free old selector
|
|
|
|
mov ax,bx
|
|
ch_ret:
|
|
cEnd
|
|
|
|
;-----------------------------------------------------------------------
|
|
; CloneROMSelector
|
|
;
|
|
; Changes the base and limit of the clone selector to point to the
|
|
; ROM selector's original ROM segment. ROM segment selectors may be
|
|
; changed when loading a ROM segment to RAM.
|
|
;
|
|
; Entry:
|
|
; parmW selROM
|
|
; parmW selClone
|
|
;
|
|
; Returns:
|
|
;
|
|
; History:
|
|
;
|
|
;-----------------------------------------------------------------------
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc CloneROMSelector,<PUBLIC,NEAR>,<bx, si, di, ds, es>
|
|
parmW selROM
|
|
parmW selClone
|
|
localV DscBuf,DSC_LEN
|
|
cBegin
|
|
SetKernelDS es
|
|
mov ax,selROMLDT
|
|
mov es,selROMToc
|
|
assumes es,nothing
|
|
|
|
mov bx,selROM
|
|
|
|
if KDEBUG
|
|
cmp bx,es:[FirstROMsel] ; sanity checks to make sure
|
|
jae @f ; selector is within ROM range
|
|
INT3_WARN
|
|
@@:
|
|
push bx
|
|
and bl,not SEG_RING_MASK
|
|
sub bx,es:[FirstROMsel]
|
|
shr bx,3
|
|
cmp bx,es:[cROMsels]
|
|
jbe @f
|
|
INT3_WARN
|
|
@@:
|
|
pop bx
|
|
endif
|
|
mov si, bx
|
|
and si, NOT SEG_RING_MASK
|
|
sub si, es:[FirstROMsel] ; si = offset in ROM LDT of descriptor
|
|
|
|
mov ds, ax ; copy ROM desciptor to stack buffer
|
|
smov es, ss
|
|
lea di, DscBuf
|
|
|
|
errnz <8 - DSC_LEN>
|
|
movsw
|
|
movsw
|
|
movsw
|
|
movsw
|
|
|
|
mov bx, selClone ; clone descriptor to orig ROM contents
|
|
lea di, DscBuf
|
|
DPMICALL 000Ch
|
|
|
|
SetKernelDS
|
|
mov ds, pGlobalHeap
|
|
UnSetKernelDS
|
|
cCall AssociateSelector,<bx,0> ; no arena/owner currently
|
|
|
|
mov ax,bx ; return with selClone in AX
|
|
cEnd
|
|
|
|
endif ;ROM ---------------------------------------------------------
|
|
|
|
|
|
cProc SetKernelCSDwordProc,<PUBLIC,NEAR>,<ax,bx,ds>
|
|
parmw addr
|
|
parmw hiword
|
|
parmw loword
|
|
cBegin
|
|
SetKernelDS
|
|
mov ds, MyCSAlias
|
|
UnSetKernelDS
|
|
mov bx, addr
|
|
mov ax, loword
|
|
mov [bx], ax
|
|
mov ax, hiword
|
|
mov [bx+2], ax
|
|
cEnd
|
|
|
|
cProc GetKernelDataSeg,<PUBLIC,NEAR>
|
|
cBegin nogen
|
|
mov ax, cs:MyCSDS
|
|
ret
|
|
cEnd nogen
|
|
|
|
cProc SetKernelDSProc,<PUBLIC,NEAR>
|
|
cBegin nogen
|
|
mov ds, cs:MyCSDS
|
|
ret
|
|
cEnd nogen
|
|
|
|
cProc SetKernelESProc,<PUBLIC,NEAR>
|
|
cBegin nogen
|
|
mov es, cs:MyCSDS
|
|
ret
|
|
cEnd nogen
|
|
|
|
cProc CheckKernelDSProc,<PUBLIC,NEAR>
|
|
cBegin nogen
|
|
if KDEBUG
|
|
cmp ax, cs:MyCSDS
|
|
je dsok
|
|
INT3_WARN
|
|
dsok:
|
|
endif
|
|
ret
|
|
cEnd nogen
|
|
|
|
assumes ds, nothing
|
|
assumes es, nothing
|
|
|
|
cProc FarGetOwner,<PUBLIC,FAR>,<bx>
|
|
parmW Selector
|
|
cBegin
|
|
cCall GetOwner,<Selector>
|
|
cEnd
|
|
|
|
cProc GetOwner,<PUBLIC,NEAR>,<es>
|
|
parmW Selector
|
|
cBegin
|
|
cCall get_arena_pointer,<Selector>
|
|
if ROM
|
|
or ax,ax ; get_arena_pointer fails on
|
|
jnz go_got_it ; ROM segments so give it
|
|
cCall GetROMOwner,<Selector> ; another try
|
|
jmps go_end
|
|
go_got_it:
|
|
else
|
|
or ax, ax
|
|
jz go_end
|
|
endif
|
|
mov es, ax
|
|
mov ax, es:[ga_owner]
|
|
go_end:
|
|
cEnd
|
|
|
|
assumes ds, nothing
|
|
assumes es, nothing
|
|
|
|
cProc FarSetOwner,<PUBLIC,FAR>
|
|
parmW Selector
|
|
parmW owner
|
|
cBegin
|
|
cCall SetOwner,<Selector,owner>
|
|
cEnd
|
|
|
|
assumes ds, nothing
|
|
assumes es, nothing
|
|
|
|
cProc SetOwner,<PUBLIC,NEAR>,<ax,es>
|
|
parmW Selector
|
|
parmW owner
|
|
cBegin
|
|
cCall get_arena_pointer,<Selector>
|
|
mov es, ax
|
|
push owner
|
|
pop es:[ga_owner]
|
|
cEnd
|
|
|
|
|
|
if ROM ;----------------------------------------------------------------
|
|
|
|
;-----------------------------------------------------------------------
|
|
; Set/GetROMOwner
|
|
;
|
|
; The Get/SetROMOwner routines use AssociateSelector and the inverse
|
|
; get_selector_association routines to track the owner of an object
|
|
; in ROM. ROM objects (like code segments and resources) don't have
|
|
; a global heap arena to store the owner's ID in.
|
|
;
|
|
; NOTE: THIS CODE DEPENDS ON WINDOWS RUNNING IN RING 1 OR 3!! The low
|
|
; bit of the associated value is set to zero to indicate the object is
|
|
; in ROM. SetROMOwner expects the owner selector to have the low bit
|
|
; set, and GetROMOwner returns the owner field with the low bit set.
|
|
;
|
|
;-----------------------------------------------------------------------
|
|
assumes ds, nothing
|
|
assumes es, nothing
|
|
|
|
cProc FarSetROMOwner,<PUBLIC,FAR>
|
|
parmW Selector
|
|
parmW Owner
|
|
cBegin
|
|
cCall SetROMOwner,<Selector,Owner>
|
|
cEnd
|
|
|
|
cProc SetROMOwner,<PUBLIC,NEAR>,<ds>
|
|
parmW Selector
|
|
parmW Owner
|
|
cBegin
|
|
mov ax,Owner
|
|
and al,NOT 1 ; mark this as a ROM selector
|
|
SetKernelDS
|
|
mov ds,pGlobalHeap
|
|
UnSetKernelDS
|
|
cCall AssociateSelector,<Selector,ax>
|
|
cEnd
|
|
|
|
|
|
cProc GetROMOwner,<PUBLIC,NEAR>,<bx,es,ds>
|
|
parmW Selector
|
|
cBegin
|
|
mov bx,Selector
|
|
cCall get_selector_association
|
|
or ax,ax
|
|
jz gro_exit
|
|
|
|
test al,1 ; low bit off if ROM owner
|
|
jnz gro_not_rom_owner
|
|
|
|
or al,1 ; restore bit cleared by SetROMOwner
|
|
jmps gro_exit
|
|
|
|
gro_not_rom_owner:
|
|
xor ax,ax
|
|
|
|
gro_exit:
|
|
cEnd
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; IsROMObject
|
|
;
|
|
; Determines if a given selector points into the ROM area.
|
|
;
|
|
; Entry:
|
|
; selector selector to check
|
|
;
|
|
; Returns:
|
|
; AX != 0 & CY set if selector points to ROM
|
|
; AX = 0 & CY clr if selector does not point to ROM
|
|
;
|
|
; Registers Destroyed:
|
|
; none
|
|
;
|
|
; History:
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc FarIsROMObject, <PUBLIC, FAR>
|
|
parmW selector
|
|
cBegin
|
|
cCall IsROMObject, <selector>
|
|
cEnd
|
|
|
|
cProc IsROMObject,<PUBLIC,NEAR>,<bx,di,es>
|
|
parmW selector
|
|
localV DscBuf,DSC_LEN
|
|
cBegin
|
|
|
|
push ds
|
|
SetKernelDS
|
|
|
|
if KDEBUG
|
|
mov ax,selector
|
|
sel_check ax
|
|
endif
|
|
mov bx,selector
|
|
smov es,ss
|
|
lea di,DscBuf
|
|
DPMICALL 000Bh ; Get current descriptor
|
|
|
|
mov bh,DscBuf.dsc_hbase ; is descriptor base at or
|
|
mov bl,DscBuf.dsc_mbase ; above start of ROM?
|
|
mov ax,DscBuf.dsc_lbase
|
|
sub ax,lmaHiROM.off
|
|
sbb bx,lmaHiROM.sel
|
|
jc iro_not_rom
|
|
|
|
sub ax,cbHiROM.off ; make sure it's not above
|
|
sbb bx,cbHiROM.sel ; the end of the ROM
|
|
jnc iro_not_rom
|
|
|
|
mov al,1 ; in ROM range, ret AX != 0 & CY set
|
|
jmps iro_exit
|
|
|
|
iro_not_rom:
|
|
xor ax,ax ; not in ROM, AX = 0 & CY clear
|
|
|
|
iro_exit:
|
|
pop ds
|
|
assumes ds,nothing
|
|
cEnd
|
|
|
|
|
|
endif ;ROM ---------------------------------------------------------
|
|
|
|
|
|
assumes ds, nothing
|
|
assumes es, nothing
|
|
|
|
cProc FarValidatePointer,<PUBLIC,FAR>
|
|
parmD p
|
|
cBegin
|
|
cCall ValidatePointer,<p>
|
|
cEnd
|
|
|
|
cProc ValidatePointer,<PUBLIC,NEAR>
|
|
parmD p
|
|
cBegin
|
|
lsl ax, seg_p
|
|
jnz short bad_p ; can we access this selector?
|
|
cmp ax, off_p ; yes, is the offset valid?
|
|
jae short good_p
|
|
bad_p:
|
|
xor ax, ax
|
|
jmps vp_done
|
|
good_p:
|
|
mov ax, 1
|
|
vp_done:
|
|
cEnd
|
|
|
|
assumes ds, nothing
|
|
assumes es, nothing
|
|
|
|
OneParaBytes dw 10h
|
|
|
|
cProc SelToSeg,<PUBLIC,NEAR>,<dx>
|
|
parmW selector
|
|
cBegin
|
|
cCall get_physical_address,<selector>
|
|
div OneParaBytes ; Smaller than rotates
|
|
cEnd
|
|
|
|
|
|
|
|
cProc SegToSelector,<PUBLIC,NEAR>,<bx>
|
|
parmW smegma
|
|
cBegin
|
|
mov bx, smegma
|
|
DPMICALL 0002h
|
|
cEnd
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; set_discarded_sel_owner
|
|
;
|
|
; Sets the owner of a selector that points to a discarded object,
|
|
; which lives in the limit field.
|
|
;
|
|
; Entry:
|
|
; BX = selector to mark
|
|
; ES = owner
|
|
;
|
|
; Returns:
|
|
; nothing
|
|
;
|
|
; Registers Destroyed:
|
|
; BX
|
|
;
|
|
; History:
|
|
; Sun 03-Dec-1989 21:02:24 -by- David N. Weise [davidw]
|
|
; Wrote it!
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc set_discarded_sel_owner,<PUBLIC,FAR>,<ds,di>
|
|
localV DscBuf,DSC_LEN
|
|
cBegin
|
|
mov cx, es
|
|
ifdef WOW
|
|
push ax
|
|
lea di, DscBuf
|
|
smov es, ss
|
|
DPMICALL 000Bh
|
|
mov DscBuf.dsc_owner, cx
|
|
DPMICALL 000Ch
|
|
pop ax
|
|
else
|
|
push ds ; Get Descriptor
|
|
mov ds, gdtdsc
|
|
push di
|
|
mov di, bx
|
|
and di, not 7
|
|
mov [di].dsc_owner, cx
|
|
pop di
|
|
pop ds
|
|
endif ; WOW
|
|
SetKernelDS
|
|
mov ds, pGlobalHeap
|
|
UnSetKernelDS
|
|
cCall AssociateSelector,<bx,cx>
|
|
mov es, cx ; Restore ES
|
|
cEnd
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; SetResourceOwner
|
|
;
|
|
; Sets the owner of a selector that points to a not present resource
|
|
;
|
|
; Entry:
|
|
;
|
|
; Returns:
|
|
; nothing
|
|
;
|
|
; Registers Destroyed:
|
|
;
|
|
; History:
|
|
;-----------------------------------------------------------------------;
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc SetResourceOwner,<PUBLIC,NEAR>,<ax,bx,cx,di,ds,es>
|
|
parmW selector
|
|
parmW owner
|
|
parmW selCount
|
|
localV DscBuf,DSC_LEN
|
|
cBegin
|
|
mov bx, selector
|
|
mov cx, owner
|
|
ifdef WOW
|
|
|
|
smov es, ss
|
|
lea di, DscBuf
|
|
DPMICALL 000Bh ; Get current descriptor
|
|
mov DscBuf.dsc_owner, cx
|
|
mov DscBuf.dsc_access, DSC_DATA
|
|
mov cx,selCount
|
|
dec cl
|
|
and cl,00001111b
|
|
or cl,DSC_DISCARDABLE
|
|
mov DscBuf.dsc_hlimit, cl ; Save number of selectors here
|
|
DPMICALL 000Ch ; Set it with new owner
|
|
else
|
|
push ds ; Get Descriptor
|
|
mov ds, gdtdsc
|
|
push bx
|
|
and bx, not 7
|
|
mov [bx].dsc_owner, cx
|
|
mov [bx].dsc_access, DSC_DATA
|
|
mov cx,selCount
|
|
dec cl
|
|
and cl,00001111b
|
|
or cl,DSC_DISCARDABLE
|
|
mov [bx].dsc_hlimit, cl ; Save number of selectors here
|
|
pop bx
|
|
pop ds
|
|
endif ; WOW
|
|
SetKernelDS
|
|
mov ds, pGlobalHeap
|
|
UnSetKernelDS
|
|
cCall AssociateSelector,<bx,owner> ; And save in selector table
|
|
cEnd
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
;
|
|
; Alias stuff moved out due to gross bloating of this file
|
|
;
|
|
;-----------------------------------------------------------------------;
|
|
if ALIASES
|
|
include aliases.asm
|
|
endif
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; DPMIProc
|
|
;
|
|
; Called NEAR by the DPMICALL macro -
|
|
; this is better than intercepting int 31h
|
|
;
|
|
; By sheer fluke, all intercepts return with
|
|
; Carry clear ie no error.
|
|
;
|
|
;-----------------------------------------------------------------------;
|
|
cProc DPMIProc,<PUBLIC,NEAR>
|
|
cBegin nogen
|
|
or ah, ah
|
|
jz @F
|
|
CallServer:
|
|
ifndef WOW
|
|
int 31h ; Nope, call DPMI server
|
|
ret
|
|
else
|
|
test word ptr [prevInt31Proc + 2],0FFFFh
|
|
jz dp30
|
|
dp20: pushf
|
|
call [prevInt31Proc]
|
|
ret
|
|
endif
|
|
@@:
|
|
if ROM
|
|
cmp al, 01h ; Free selector?
|
|
jne @f
|
|
push ds
|
|
SetKernelDS
|
|
cmp bx,sel1stAvail ; Yes, don't free selectors in
|
|
pop ds ; the preallocated ROM range
|
|
UnSetKernelDS
|
|
jae CallServer
|
|
ret
|
|
@@:
|
|
endif ;ROM
|
|
ifdef WOW
|
|
cmp gdtdsc, 0 ; Can we party?
|
|
jz CallServer ; Nope
|
|
endif
|
|
push ds
|
|
mov ds, gdtdsc
|
|
ifdef WOW
|
|
|
|
or al, al
|
|
jnz @F
|
|
mov ax, WOW_DPMIFUNC_00
|
|
pop ds
|
|
jmps CallServer
|
|
@@:
|
|
endif
|
|
cmp al, 0Bh
|
|
jne @F
|
|
|
|
test bx,4
|
|
jnz xx1
|
|
|
|
; On MIPS if Win87EM is processing an NPX exception the selector
|
|
; to Dosx's stack is being looked up here. Since it is a global
|
|
; selector the normal lookup will not find it and Win87EM will
|
|
; fault. This is solved by calling Dosx since it knows about the
|
|
; global selectors that we don't. - MarkRi [6/93]
|
|
;
|
|
pop ds
|
|
jmps CallServer
|
|
|
|
xx1: push si ; Get Descriptor - used very often!
|
|
mov si, bx
|
|
and si, not 7
|
|
MovsDsc
|
|
lea di, [di-DSC_LEN] ; Restore DI
|
|
pop si
|
|
pop ds
|
|
ret
|
|
|
|
ifndef WOW
|
|
@@:
|
|
cmp al, 0Ch
|
|
jne @F
|
|
|
|
push bx ; Set Descriptor
|
|
and bl, not 7
|
|
mov ax, es:[di] ; This looks slow but it isn't...
|
|
mov ds:[bx], ax
|
|
mov ax, es:[di][2]
|
|
mov ds:[bx][2], ax
|
|
mov ax, es:[di][4]
|
|
mov ds:[bx][4], ax
|
|
mov ax, es:[di][6]
|
|
mov ds:[bx][6], ax
|
|
if 0 ;;ROM and KDEBUG
|
|
call CheckROMSelector
|
|
endif
|
|
pop bx
|
|
pop ds
|
|
ret
|
|
|
|
@@:
|
|
cmp al, 07h ; Set Segment Base Address
|
|
jne @F
|
|
push bx
|
|
and bl, not 7
|
|
mov ds:[bx].dsc_lbase, dx
|
|
mov ds:[bx].dsc_mbase, cl
|
|
mov ds:[bx].dsc_hbase, ch
|
|
pop bx
|
|
pop ds
|
|
ret
|
|
endif
|
|
@@:
|
|
cmp al, 06h ; Get Segment Base Address
|
|
jne @F
|
|
push bx
|
|
and bl, not 7
|
|
mov dx, ds:[bx].dsc_lbase
|
|
mov cl, ds:[bx].dsc_mbase
|
|
mov ch, ds:[bx].dsc_hbase
|
|
pop bx
|
|
pop ds
|
|
ret
|
|
ifndef WOW
|
|
@@:
|
|
cmp al, 09h ; Set Descriptor Access Rights
|
|
jne @F
|
|
push bx
|
|
and bl, not 7
|
|
mov word ptr ds:[bx].dsc_access, cx
|
|
if 0 ;;ROM and KDEBUG
|
|
call CheckROMSelector
|
|
endif
|
|
pop bx
|
|
pop ds
|
|
ret
|
|
endif
|
|
@@:
|
|
pop ds
|
|
jmp CallServer
|
|
|
|
ifdef WOW
|
|
dp30: int 31h
|
|
ret
|
|
endif
|
|
cEnd nogen
|
|
|
|
|
|
if ROM
|
|
if1
|
|
%out CheckROMSelector -- fix me!! (what exactly is wrong?)
|
|
endif
|
|
endif
|
|
|
|
if 0 ;;ROM and KDEBUG
|
|
|
|
;------------------------------------------------------------------------
|
|
; CheckROMSelector
|
|
;
|
|
; ROM Windows debug hack to ensure that Windows code doesn't try writing
|
|
; to the ROM image. It does this by making any data selector to the
|
|
; ROM read only.
|
|
;
|
|
; Entry:
|
|
; DS:BX -> descriptor to check
|
|
;
|
|
; Returns:
|
|
; nothing
|
|
;
|
|
; Registers Destroyed:
|
|
; none
|
|
;
|
|
;------------------------------------------------------------------------
|
|
|
|
assumes ds,nothing
|
|
assumes es,nothing
|
|
|
|
cProc CheckROMSelector,<PUBLIC,NEAR>
|
|
cBegin nogen
|
|
|
|
test ds:[bx].dsc_access,DSC_CODEDATA ; code or data dsc?
|
|
jz crs_exit ; no, skip it
|
|
|
|
test ds:[bx].dsc_access,DSC_CODE_BIT ; code?
|
|
jnz crs_exit ; yes, skip it
|
|
|
|
push ax
|
|
push dx
|
|
mov dh,ds:[bx].dsc_hbase ; is descriptor base at or
|
|
mov dl,ds:[bx].dsc_mbase ; above start of ROM?
|
|
mov ax,ds:[bx].dsc_lbase
|
|
sub ax,lmaHiROM.off
|
|
sbb dx,lmaHiROM.sel
|
|
jc crs_exit1
|
|
|
|
sub ax,cbHiROM.off ; make sure it's not above
|
|
sbb dx,cbHiROM.sel ; the end of the ROM
|
|
jnc crs_exit1
|
|
|
|
and ds:[bx].dsc_access,NOT DSC_RW_BIT ; make it read only
|
|
|
|
crs_exit1:
|
|
pop dx
|
|
pop ax
|
|
|
|
crs_exit:
|
|
ret
|
|
|
|
cEnd nogen
|
|
|
|
endif ;ROM and KDEBUG
|
|
|
|
ifdef WOW
|
|
|
|
|
|
cProc alloc_special_sel,<PUBLIC,NEAR>,<bx,cx,dx,si,di,ds>
|
|
parmW AllocFlags
|
|
parmW SelFreeBlock
|
|
parmW SizeFreeBlock
|
|
parmW SizeNewFreeBlock
|
|
parmW AdjustedSize
|
|
parmB fBaseAddressToUse
|
|
|
|
localD AddressNewFreeBlock
|
|
localD Address
|
|
localW Limit
|
|
localW cFreeBlock
|
|
localW cTotalSelectors
|
|
localW EachSelectorLimit
|
|
cBegin
|
|
|
|
;
|
|
; this will be our ds
|
|
;
|
|
|
|
mov ds, gdtdsc
|
|
|
|
;
|
|
; replace allocflags with accessword
|
|
;
|
|
|
|
mov bx, AllocFlags
|
|
and bx, ((GA_CODE_DATA+GA_DISCARDABLE) shl 8) + GA_DGROUP
|
|
or bl, bh
|
|
xor bh, bh
|
|
shl bx, 1
|
|
mov ax, cs:SelAccessWord[bx] ; Pick up access rights for selector
|
|
mov AllocFlags, ax ; allocflags = access rights
|
|
|
|
;
|
|
; Limit for data selectors
|
|
;
|
|
|
|
mov ax, AdjustedSize
|
|
dec ax
|
|
mov Limit, ax
|
|
|
|
;
|
|
; compute base address for new freeblock and the first selector
|
|
; the base address is dependent on fBaseAddressToUse flag
|
|
;
|
|
|
|
cCall get_physical_address,<SelFreeBlock>
|
|
|
|
cmp fBaseAddressToUse, ga_prev
|
|
jne @F
|
|
|
|
mov bx, SizeNewFreeBlock
|
|
xor cx,cx
|
|
REPT 4
|
|
shl bx,1
|
|
rcl cx,1
|
|
ENDM
|
|
|
|
add ax, bx
|
|
adc dx, cx
|
|
|
|
mov AddressNewFreeBlock.lo, ax
|
|
mov AddressNewFreeBlock.hi, dx
|
|
|
|
;
|
|
; compute base address for first selector
|
|
;
|
|
|
|
add ax, 10h
|
|
adc dx, 00h
|
|
|
|
mov Address.lo, ax
|
|
mov Address.hi, dx
|
|
|
|
jmps alloc_checkforfreeblock
|
|
@@:
|
|
|
|
push ax ; save base address of freeblock
|
|
push dx
|
|
|
|
add ax, 10h
|
|
adc dx, 00h
|
|
|
|
mov Address.lo, ax ; address of first selector
|
|
mov Address.hi, dx
|
|
|
|
pop dx
|
|
pop ax
|
|
|
|
mov bx, AdjustedSize
|
|
xor cx,cx
|
|
REPT 4
|
|
shl bx,1
|
|
rcl cx,1
|
|
ENDM
|
|
|
|
add ax, bx
|
|
adc dx, cx
|
|
|
|
mov AddressNewFreeBlock.lo, ax
|
|
mov AddressNewFreeBlock.hi, dx
|
|
|
|
alloc_checkforfreeblock:
|
|
|
|
;
|
|
; check if a 'new' free block needs to be created.
|
|
; cFreeBlock = (SizeNewFreeBlock) ? 1 : 0;
|
|
;
|
|
|
|
mov cFreeBlock, 0
|
|
mov cx, SizeNewFreeBlock
|
|
jcxz alloc_nofreeblock
|
|
mov cFreeBlock, 1
|
|
|
|
alloc_nofreeblock:
|
|
|
|
|
|
;
|
|
; start of processing
|
|
;
|
|
|
|
mov cx, 1
|
|
mov ax, AllocFlags
|
|
test al, DSC_PRESENT
|
|
jz allocspecial_oneonly
|
|
; limit in paras
|
|
mov cx, Limit ; Calculate how many selectors required
|
|
add cx, 0FFFh
|
|
rcr cx, 1 ; 17 bitdom
|
|
shr cx, 11
|
|
|
|
allocspecial_oneonly:
|
|
push cx
|
|
add cx, cFreeBlock ; cFreeBlock is zero or one
|
|
mov cTotalSelectors, cx
|
|
|
|
;
|
|
; the dpmi func is 04f1h. This is idential to function 00h, except that
|
|
; the descriptor base and limit are not initialized to zero.
|
|
;
|
|
|
|
DPMICALL WOW_DPMIFUNC_00
|
|
pop cx
|
|
jnz allocspecial_continue
|
|
jmp allocspecial_exit
|
|
|
|
allocspecial_continue:
|
|
|
|
push ax ; save the first selector
|
|
and ax, not SEG_RING
|
|
|
|
mov bx, ax ; Selector in bx for DPMI
|
|
|
|
mov ax, Address.lo ; Set descriptor base
|
|
mov [bx].dsc_lbase, ax
|
|
mov di, ax ; used later
|
|
mov ax, Address.hi
|
|
mov [bx].dsc_mbase, al
|
|
mov [bx].dsc_hbase, ah
|
|
|
|
mov ax, AllocFlags
|
|
test al, DSC_PRESENT ; If selector not present, limit is
|
|
jnz short allocspecial_present ; as passed, not a paragraph count
|
|
|
|
allocspecial_not_present:
|
|
|
|
mov word ptr [bx].dsc_access, ax
|
|
mov ax, word ptr Limit
|
|
mov [bx].dsc_limit, ax
|
|
|
|
jmps allocspecial_done
|
|
|
|
allocspecial_present:
|
|
|
|
dec cl
|
|
and ah, not 0Fh ; Zero limit 19:16
|
|
or ah, cl ; Fill in limit 19:16
|
|
inc cl
|
|
mov word ptr [bx].dsc_access, ax
|
|
mov si, ax ; save for later use
|
|
mov ax, Limit
|
|
shl ax, 4 ; Convert paragraphs to byte limit
|
|
dec ax
|
|
mov [bx].dsc_limit, ax
|
|
|
|
dec cx
|
|
jcxz allocspecial_done ; if sel=1 done.
|
|
|
|
mov EachSelectorLimit, ax ; ax the limit from above
|
|
mov al, [bx].dsc_mbase ;
|
|
mov ah, [bx].dsc_hbase
|
|
mov dl, [bx].dsc_hlimit
|
|
|
|
push ds
|
|
SetKernelDS
|
|
test WinFlags, WF_CPU286 ; protect mode on a 286?
|
|
pop ds
|
|
|
|
|
|
push [bx].dsc_limit ; Save limit for last selector
|
|
jz allocspecial_next_sel ; the result of the test above
|
|
mov EachSelectorLimit, 0FFFFh ; Others get 64k limit on 286
|
|
|
|
allocspecial_next_sel:
|
|
push ax
|
|
mov ax, EachSelectorLimit
|
|
mov [bx].dsc_limit, ax ; limit for current selector
|
|
pop ax
|
|
|
|
lea bx, [bx+DSC_LEN] ; On to next selector
|
|
cmp cx, 1 ; Last selector?
|
|
jne allocspecial_fsa_not_last
|
|
pop [bx].dsc_limit ; yes, get its limit
|
|
|
|
allocspecial_fsa_not_last:
|
|
mov [bx].dsc_lbase, di
|
|
mov word ptr [bx].dsc_access, si
|
|
inc ax
|
|
mov [bx].dsc_mbase, al ; Add 64kb to address
|
|
mov [bx].dsc_hbase, ah
|
|
dec dl
|
|
mov [bx].dsc_hlimit, dl ; subtract 64kb from limit
|
|
loop allocspecial_next_sel
|
|
|
|
allocspecial_done:
|
|
cmp cFreeBlock, 1
|
|
jne allocspecial_nofreeblock
|
|
|
|
allocspecial_freeblock:
|
|
|
|
mov ax, AddressNewFreeBlock.lo ; the base for freeblock
|
|
mov dx, AddressNewFreeBlock.hi
|
|
|
|
|
|
lea bx, [bx+DSC_LEN] ; On to next selector
|
|
mov [bx].dsc_limit, 0fh ; = 1 para
|
|
mov [bx].dsc_lbase, ax
|
|
mov [bx].dsc_mbase, dl
|
|
mov [bx].dsc_hbase, dh
|
|
|
|
mov ax, DSC_DATA+DSC_PRESENT
|
|
and ah, not 0Fh ; Zero limit 19:16
|
|
mov word ptr [bx].dsc_access, ax
|
|
|
|
allocspecial_nofreeblock:
|
|
|
|
pop si ; restore the first selector
|
|
|
|
push bx
|
|
mov cx, cTotalSelectors
|
|
mov bx, si
|
|
|
|
;
|
|
; the dpmi func is 04f2h. This is identical to 0ch except that it
|
|
; sets 'count' (in cx) LDTs at one time. The first selector is in
|
|
; register bx. The descriptor data is in gdtdsc[bx], gdtdsc[bx+8]
|
|
; etc. This data is shared between dpmi (dosx.exe) and us and thus
|
|
; need not be passed in es:di
|
|
|
|
DPMICALL WOW_DPMIFUNC_0C
|
|
pop bx
|
|
|
|
SetKernelDS
|
|
|
|
;
|
|
; sanity check. done so late because if this check was done
|
|
; somewhere eariler, we would have had to Save and Restor DS. Since
|
|
; this check would be successful most of the time, it is quite Ok
|
|
; to do it now and we would avoid unneccessary loading of DS.
|
|
|
|
mov ax, bx
|
|
shr ax, 2
|
|
cmp ax, SelTableLen ; Make sure we can associate it
|
|
jb @F
|
|
xor ax, ax ; set zero flag
|
|
jmps allocspecial_exit
|
|
|
|
@@:
|
|
mov UserSelArray, si ; the selector for user data
|
|
mov ax, bx
|
|
or ax, SEG_RING ; selector of new freeblock, if one is
|
|
; created. sets nz flag.
|
|
mov SelectorFreeBlock, ax ;
|
|
allocspecial_exit:
|
|
cEnd
|
|
|
|
|
|
;----------------------------------------------------------------------------
|
|
; grabbed from 2gmem.asm
|
|
;
|
|
;----------------------------------------------------------------------------
|
|
|
|
SelAccessWord dw DSC_DATA+DSC_PRESENT
|
|
dw (DSC_DISCARDABLE SHL 8) + DSC_DATA+DSC_PRESENT
|
|
dw DSC_CODE+DSC_PRESENT
|
|
dw (DSC_DISCARDABLE SHL 8) + DSC_CODE+DSC_PRESENT
|
|
dw DSC_DATA+DSC_PRESENT
|
|
dw (DSC_DISCARDABLE SHL 8) + DSC_DATA+DSC_PRESENT
|
|
dw DSC_DATA+DSC_PRESENT
|
|
dw (DSC_DISCARDABLE SHL 8) + DSC_DATA+DSC_PRESENT
|
|
|
|
|
|
|
|
;-----------------------------------------------------------------------------
|
|
; Grab the selector 0x47 so that we dont need to special case the biosdata
|
|
; selector (0x40) while converting seg:off address to flat 32bit address
|
|
;
|
|
; This, however should not be part of Krnl286 heap.
|
|
;
|
|
; - Nanduri Ramakrishna
|
|
;-----------------------------------------------------------------------------
|
|
cProc AllocSelector_0x47,<PUBLIC,FAR>, <ax, bx, cx, ds>
|
|
cBegin
|
|
|
|
; alloc the specific selector
|
|
|
|
mov bx, 047h
|
|
DPMICALL 0dh
|
|
jc as47_exit
|
|
|
|
; initialize the LDT
|
|
|
|
and bx, not SEG_RING
|
|
mov ds, gdtdsc
|
|
mov [bx].dsc_limit, 00h ; = 1 byte
|
|
mov [bx].dsc_lbase, 0400h
|
|
mov [bx].dsc_mbase, 00h
|
|
mov [bx].dsc_hbase, 00h
|
|
|
|
mov ax, DSC_DATA+DSC_PRESENT
|
|
and ah, not 0Fh ; Zero limit 19:16
|
|
mov word ptr [bx].dsc_access, ax
|
|
|
|
; set the LDT
|
|
|
|
mov cx,1
|
|
mov bx, 047h
|
|
DPMICALL WOW_DPMIFUNC_0C
|
|
|
|
as47_exit:
|
|
cEnd
|
|
sEnd CODE
|
|
|
|
sBegin NRESCODE
|
|
|
|
assumes CS,NRESCODE
|
|
assumes DS,NOTHING
|
|
assumes ES,NOTHING
|
|
|
|
|
|
cProc get_sel_flags,<PUBLIC,NEAR>
|
|
parmW selector
|
|
cBegin
|
|
; Not used in krnl286
|
|
xor ax,ax
|
|
xor dx,dx
|
|
cEnd
|
|
|
|
cProc set_sel_for_dib,<PUBLIC,NEAR>
|
|
parmW selector
|
|
parmW flags
|
|
parmD address
|
|
parmW csel
|
|
cBegin
|
|
; Not used in krnl286
|
|
xor ax,ax
|
|
xor dx,dx
|
|
cEnd
|
|
|
|
cProc RestoreDib,<PUBLIC,NEAR>
|
|
parmW selector
|
|
parmW flags
|
|
parmD address
|
|
cBegin
|
|
; Not used in krnl286
|
|
xor ax,ax
|
|
xor dx,dx
|
|
cEnd
|
|
|
|
cProc DibRealloc,<PUBLIC,FAR>
|
|
parmW Selector
|
|
parmW NewSize
|
|
cBegin
|
|
cEnd
|
|
|
|
endif
|
|
|
|
sEnd NRESCODE
|
|
|
|
end
|