Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

4141 lines
116 KiB

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