home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-04-14 | 47.5 KB | 1,461 lines |
- ;*DDK*************************************************************************/
- ;
- ; COPYRIGHT Copyright (C) 1995 IBM Corporation
- ;
- ; The following IBM OS/2 WARP source code is provided to you solely for
- ; the purpose of assisting you in your development of OS/2 WARP device
- ; drivers. You may use this code in accordance with the IBM License
- ; Agreement provided in the IBM Device Driver Source Kit for OS/2. This
- ; Copyright statement may not be removed.;
- ;*****************************************************************************/
- ; SCCSID = @(#)osmaca.inc 6.4 91/10/18
- ;*** OSMACA.INC
- ;
- ; Macro file for OS/2 kernel
- ;
- ; SCCSID = @(#)osmaca.inc 6.4 91/10/18
- ;
- ; This file provides the following macros:
- ;
- ; AsmVars
- ; AsmVar
- ; EXTRNFAR
- ; EXTRN16
- ; EXTRN32
- ; EXTRNF32
- ; DDFAR
- ; MOVFAROFFSET
- ; CALLFAR
- ; CALL16
- ; JMPFAR
- ; JMP16
- ; CALLF32
- ; CCALL32
- ; PCALL32
- ; CALL32
- ; JMP32
- ; ThunkFar32
- ; CallInstall
- ; SegContext
- ; DosContext
- ; GDTContext
- ; TaskContext
- ; DosInitContext
- ; DosMTEContext
- ; FlatContext
- ; NullContext
- ; ReferGlobal
- ; ReferGDT
- ; ReferTask
- ; ReferHigh2
- ; ReferInitGlobal
- ; ReferFlat
- ; FARCODE
- ; InternalError
- ; Panic
- ; ModName
- ; BeginNoBlock
- ; EndNoBlock
- ; AssertCLD
- ; AssertNoBuf
- ; DefTaskData
- ; CallGate
- ; StampRPL
-
- ; 12/15/93 RAC 76699 Make Perfview and Tracing Optional in system
- ; 1/4/94 RAC 77052 Add check for MMIO build to include RAS
-
- ;*** OLD usage equates
-
- ifndef BREAK
- BREAK equ <Break>
- endif
-
- ifndef CpuMode
- CpuMode equ <CPUMode>
- endif
-
- ;
- ; The RAS flag causes all RAS related code to be assembled as
- ; part of the DOS. All RAS related code should be surrounded
- ; by:
- ; IF RAS
- ; :
- ; ras code
- ; :
- ; ENDIF ; RAS
- ;
-
- ; If building Perfview and tracing kernal, turn on RAS, otherwise turn it off
- ; D 76699. D 77052, adds check for MMIO build.
- ifdef PERFVIEW
- RAS EQU 1
- else
- ifdef MMIOPH
- RAS EQU 1
- else
- RAS EQU 0
- endif ; MMIOPH
- endif ; PERFVIEW
-
- ;*** AsmVars - initialize variables
- ;
- ; Each variable in varlist is examined to see if it has already
- ; been defined. If so, nothing happens. Otherwise it is
- ; defined with the value "value".
- ;
- ; ENTRY: varlist = list of variables enclosed in < >
- ; value = a value to assign to all undefined variables.
- ;
- ; EXIT: undefined variables in varlist are set to "value."
-
- AsmVars macro varlist, value
- irp var,<varlist>
- AsmVar var, value
- endm
- endm
-
- ;*** AsmVar - initialize a variable
- ;
- ; The variable "var" is examined to see if it has already
- ; been defined. If so, nothing happens. Otherwise it is
- ; defined with the value "value."
- ;
- ; ENTRY: var = a variable
- ; value = value to assign to var
- ;
- ; EXIT: var is set to "value" if it wasn't previously defined.
-
- AsmVar macro var, value
- ifndef var
- ifb <value>
- var = FALSE
- else
- var = value
- endif
- endif
- endm
-
- ; Check if all (or most) the checking flags are to be enabled.
-
- ifdef ALLSTRICT
- AsmVar DEMSTRICT, TRUE
- AsmVar EM86STRICT, TRUE
- AsmVar VDHSTRICT, TRUE
- AsmVar VDDSTRICT, TRUE
- AsmVar VDMMSTRICT, TRUE
- AsmVar DEVSTRICT, TRUE
- AsmVar FSSTRICT, TRUE
- AsmVar PIPESTRICT, TRUE
- AsmVar INFOSTRICT, TRUE
- AsmVar INTERRPRT, TRUE
- AsmVar KMSTRICT, TRUE
- AsmVar LDRSTRICT, TRUE
- AsmVar MISCSTRICT, TRUE
- AsmVar MODECHECK, TRUE
- AsmVar PERFSTRICT, TRUE
- AsmVar PGSTRICT, TRUE
- AsmVar SELSTRICT, TRUE
- AsmVar SEMSTRICT, TRUE
- AsmVar SMSTRICT, TRUE
- AsmVar VMSTRICT, TRUE
- AsmVar VOLPTRCHK, TRUE
- AsmVar ALIGNCODE, TRUE
- AsmVar DBGSTRICT, TRUE
- AsmVar PTSTRICT, TRUE
- endif
-
- ifdef INTERRPRT
- IntErrF = TRUE ; for v86code only
- else
- IntErrF = FALSE ; for v86code only
- endif
-
- AsmVars <Debug,ShareF>
-
- ?om1 = 0 ;; osmaca.inc scratch variable
-
- ;*** ?GenCall - generate a call to a hybrid procedure
- ;
- ; It generates either far call or near call depending on the
- ; last use of the FARCODE macro.
- ;
- ; ENTRY: target = name of hybrid procedure
- ; targetseg = SN_targetseg of target segment
- ; (global variables)
- ; ?farcode = <targetseg> - generate appropriate type call
- ;
- ; EXIT: code generated to call the hybrid procedure
- ;
- ; SEE ALSO: Procedure
-
- ?GenCall macro target, targetseg
- if (?farcode eq targetseg) ;; source and target in same segment?
- if2
- ifndef target
- extrn target:near
- endif
- endif
- call target ;; near 16 or 32 bit call
- elseif (?cstype eq ?CS_32bit) ;; source in 32 bit segment?
- CALL16 target ;; far 32 bit call
- elseif (targetseg eq SN_DosHigh32Code) ;; target in 32 bit segment?
- if2
- ifndef target
- extrn target:near
- endif
- endif
- CALL32 target ;; near 32 bit call (with thunk)
- else ;; else source & target in 16 bit segs
- CALLFAR target ;; far 16 bit call
- endif
- endm
-
-
- ;*** EXTRNFAR - generate an extrn for the hybrid symbol.
- ;*** EXTRN16 - generate an extrn for the far16 symbol.
- ;*** EXTRN32 - generate an extrn for the near 32 bit symbol.
- ;*** EXTRNF32 - generate an extrn for the far32 symbol.
- ; Skip it has already been defined or the skip argument is nonblank.
- ;
- ; ENTRY name = symbol
- ; skip = blank - generate the extrn
- ; = non-blank - don't generate the extrn
- ; EXIT an extrn generated if skip is blank.
- ; SEE ALSO Procedure
-
- EXTRNFAR macro name, skip
- if2
- ?GenExtrn %HYBPRE_, name,, far, skip
- endif
- endm
-
- EXTRN16 macro name, skip
- ?GenExtrn %F16PRE_, name,, far, skip
- endm
-
- EXTRN32 macro name, skip
- ?GenExtrn , name, fflat, near, skip
- endm
-
- EXTRNF32 macro name, skip
- .386p
- ?GenExtrn %F32PRE_, name, fflat, far, skip
- CpuMode reset
- endm
-
- ?GenExtrn macro prefix, name, fflat, distance, skip
- ifb <skip>
- ifndef prefix&name
- ifnb <fflat>
- if (?cstype ne ?CS_32bit)
- _TEXT segment
- endif
- endif
- .lall
- extrn prefix&name:distance
- .xall
- ifnb <fflat>
- if (?cstype ne ?CS_32bit)
- _TEXT ends
- endif
- endif
- endif
- endif
- endm
-
-
- ;*** DDFAR - generate far pointer to hybrid procedure
- ;*** DDOFF16 - generate 32 bit offset of far16 procedure
- ;*** DWOFF16 - generate 16 bit offset of far16 procedure
- ;
- ; ENTRY: name = name of hybrid/far16 procedure.
- ; Must be defined in the current file.
- ;
- ; EXIT: double word generated containing the far pointer (seg, off),
- ; double word generated containing the 32 bit offset,
- ; OR word generated containing the 16 bit offset.
- ;
- ; SEE ALSO: Procedure
-
- DDFAR macro name
- CatPrefix <dw offset>, %HYBPRE_, <name>
- CatPrefix <dw seg>, %HYBPRE_, <name>
- endm
-
- DDOFF16 macro name
- CatPrefix <dd offset>, %F16PRE_, <name>
- endm
-
- DWOFF16 macro name
- CatPrefix <dw offset>, %F16PRE_, <name>
- endm
-
- ;*** MOVFAROFFSET - move the offset of the far entry of a hybrid or
- ; a faronly procedure into a register or memory.
- ;
- ; The offset is relative to the current group/segment cs is
- ; assuming or relative to the supplied segment/group name.
- ;
- ; ENTRY: target = register or memory to receive the offset.
- ; name = hybrid/faronly procedure name
- ; group = blank - use whatever group cs is assuming
- ; = non-blank - use this as the group/segment to
- ; calculate the offset.
- ;
- ; EXIT: "mov" instruction generated to move an offset into the
- ; target.
-
- MOVFAROFFSET macro target,name,group
- ifb <group>
- CatPrefix <mov target, offset cs:>, %HYBPRE_, <name>
- else
- CatPrefix <mov target, offset group:>, %HYBPRE_, <name>
- endif
- endm
-
- ;*** CALLFAR - generate a far16 call to a faronly/hybrid procedure
- ;*** CALL16 - generate a far32 call to a far16 procedure
- ;*** JMPFAR - generate a far16 jump to a faronly/hybrid procedure
- ;*** JMP16 - generate a far32 jump to a far16 procedure
- ;
- ; The procedure must already be defined in the current file
- ; in a Procedure declaration or via EXTRNFAR or EXTRN16.
- ;
- ; ENTRY name = name of hybrid/faronly/far16 procedure
- ; EXIT generated a far call to the given procedure
- ; SEE ALSO Procedure
-
- CALLFAR macro name ;; call far16 ptr HYBPRE_&name
- if2
- if ?cstype eq ?CS_32bit
- ProcError <CALLFAR name in 32 bit code>
- .err
- endif
- ifdef SN_DosInitR3Code
- if ?farcode eq SN_DosInitR3Code
- ProcError <CALLFAR name in ring 3 code>
- .err
- endif
- endif
- endif
- CatPrefix <call far ptr>, %HYBPRE_, <name>
- endm
-
- CALL16 macro name ;; call far32 ptr F16PRE_&name
- if2
- if (?cstype ne ?CS_32bit)
- ProcError <CALL16 name in 16 bit code>
- .err
- endif
- endif
- assume cs:DOSHIGH32CODE ;; disable assume cs:FLAT
- ;; can't use a plain far call because masm turns it into a 16 bit far call
- ;; call far ptr %F16PRE_&name
- db MI_LONG_CALL
- CatPrefix <df>, %F16PRE_, <name>
- ?ASSUMECS
- endm
-
- JMPFAR macro name
- if2
- if ?cstype eq ?CS_32bit
- ProcError <JMPFAR name in 32 bit code>
- .err
- endif
- ifdef SN_DosInitR3Code
- if ?farcode eq SN_DosInitR3Code
- ProcError <JMPFAR name in ring 3 code>
- .err
- endif
- endif
- endif
- CatPrefix <jmp far ptr>, %HYBPRE_, <name>
- endm
-
- JMP16 macro name ;; jmp far ptr F16PRE_&name
- if2
- if (?cstype ne ?CS_32bit)
- ProcError <JMP16 name in 16 bit code>
- .err
- endif
- endif
- assume cs:DOSHIGH32CODE ;; disable assume cs:FLAT
- ;; CatPrefix <jmp far ptr>, %F16PRE_, <name>
- ;; use explicit opcodes to avoid masm 5 trailing nop
- db MI_OPERANDSIZE, MI_LONG_JMP
- CatPrefix <dw offset>, %F16PRE_, <name>
- CatPrefix <dw seg>, %F16PRE_, <name>
- ?ASSUMECS
- endm
-
- ;*** CCALL32 - call 32-bit near "C" procedure from a 16-bit segment
- ;*** CALLF32 - call 32-bit far "C" procedure from a 16-bit segment
- ;*** PCALL32 - call 32-bit near "PASCAL" procedure from a 16-bit segment
- ;*** CALL32 - call 32-bit procedure from a 16-bit segment
- ;*** JMP32 - jump to 32-bit procedure from a 16-bit segment
- ;
- ; This macro calls or jumps to a 32-bit procedure from a 16-bit
- ; code segment. If requested (CALL32 only), it sets DS and ES
- ; to the flat ring 0 data selector before calling the function.
- ;
- ; CCALL32 target, [<args>], [<segargs>]
- ; CALLF32 target, [<args>], [<segargs>], [CCall modifiers]
- ; PCALL32 target, [<args>], [<segargs>]
- ; CALL32 target, [<segargs>], [calltype], [args], [CCall modifiers]
- ;
- ; ENTRY target - name of function to call
- ; args - list of argument parameters
- ; segargs - optional parameter
- ; nocheck: suppress verification of DS and ES
- ; nosegcheck: suppress verification thunk seg
- ; nofar32: suppress far32 call
- ; far32: use far32 call
- ; nocall: use far jmp thunk (preserve SP for call)
- ; noalignesp: suppress alignment of esp
- ; tgtseg: causes thunk to be placed in tgtseg
- ; EXIT As from called function
- ; USES EAX, ECX, EDX (optionally DS, ES), Flags
-
- ?thcnt = 0
- ?Call32Label macro modname, n, lab
- ; public modname&n&lab Defect 61299 workaround. Paul.
- modname&n&lab:
- endm
-
- CALLF32 macro target, args, segargs, testarg
- CALL32 <target>,<far32,segargs>,,<args>,,<testarg>
- endm
-
- CCALL32 macro target, args, segargs, modifiers, testarg
- CALL32 <target>,<segargs>,<CCall>,<args>,<modifiers>,<testarg>
- endm
-
- PCALL32 macro target, args, segargs, testarg
- CALL32 <target>,<segargs>,<PCall>,<args>,,<testarg>
- endm
-
- ?S_NOCHECK equ 01h ;; <nocheck> - suppress AssertDSESFlat
- ?S_NOSEGCHECK equ 02h ;; <nosegcheck> - suppress far32 address check
- ?S_NOFAR32 equ 04h ;; <nofar32> - suppress far32 call
- ?S_FAR32 equ 08h ;; <far32> - use far32 call
- ?S_NOCALL equ 10h ;; <nocall> - suppress near thunk call
- ?S_NOALIGNESP equ 20h ;; <noalignesp> - suppress align esp
- ?S_SEG equ 40h ;; <???> - specify thunk segment name
- ?thunkcodeseg equ <.err>
-
- CALL32 macro target, segargs, calltype, args, modifiers, testarg
- local label32, label16
- .386p
- ?sflags = 0 ;; assert ds/es FLAT, resident thunk with retfd
- ?thunkcodeseg catstr ?ThunkSeg
- irp x,<segargs> ;; examine segargs
- ifnb <x>
- ifidn <x>,<nocheck>
- ?sflags = ?sflags or ?S_NOCHECK ;; don't assert ds,es FLAT
- elseifidn <x>,<nosegcheck>
- ?sflags = ?sflags or ?S_NOSEGCHECK;; don't assert thunk seg
- elseifidn <x>,<nofar32>
- ?sflags = ?sflags or ?S_NOFAR32 ;; don't call F32PRE_&target
- elseifidn <x>,<far32>
- ?sflags = ?sflags or ?S_FAR32 ;; use call F32PRE_&target
- elseifidn <x>,<nocall>
- ?sflags = ?sflags or ?S_NOCALL ;; use jmp32/jmp16
- elseifidn <x>,<noalignesp>
- ?sflags = ?sflags or ?S_NOALIGNESP ;; don't align esp
- else
- ?sflags = ?sflags or ?S_SEG ;; use specified segment
- ?thunkcodeseg catstr x
- endif
- endif
- endm
- irp x,<modifiers> ;; examine modifiers
- ifidn <x>,<PushP>
- if (?sflags and ?S_FAR32)
- ProcError <CCALL32 target: PushP conflicts with call>
- endif
- if ((?sflags and ?S_NOALIGNESP) eq 0)
- ?sflags = ?sflags or ?S_NOALIGNESP
- endif
- ?sflags = ?sflags or ?S_NOCALL ;; don't use retfd
- endif
- endm
- .lall
- ?om1 = ?sflags ;; only for listing files
- .xall
- if2
- ifdef SN_DosInitR3Code
- if ?farcode eq SN_DosInitR3Code
- ProcError <CCALL32 target in ring 3 code>
- .err
- endif
- endif
- ?om1 = ?sflags and (?S_FAR32 or ?S_NOFAR32 or ?S_NOCALL)
- if (?om1 and (?om1 - 1)) ;; verify only one bit set
- ProcError <CCALL32 target: nofar32/far32/nocall conflict>
- endif
- if ((?sflags and ?S_FAR32) eq 0)
- ifb <calltype>
- ifnb <args>
- ProcError <CALL32 target: use CCALL32/CALLF32 with parms>
- endif
- ifnb <modifiers>
- ProcError <CALL32 target: use CCALL32/CALLF32 with CCall_modifiers>
- endif
- endif
- endif
- ifnb <testarg>
- ProcError <CCALL32 target: too many args: testarg>
- endif
- endif
- if ((?cstype eq ?CS_32bit) eq 0)
- if ((?sflags and (?S_FAR32 or ?S_NOFAR32 or ?S_NOCALL)) eq 0)
- ifb <args>
- ?sflags = ?sflags or ?S_FAR32
- endif
- endif
- if ((?sflags and ?S_FAR32) eq 0) ;; thunk required?
- % ?Eval ?thunkcodeseg <segment> ;; put thunk in 32 bit code
- assume cs:FLAT ;; change to flat cs
- ?Call32Label %@FileName, %?thcnt, target
- ?thcnt = ?thcnt + 1
- label32 label near
- % ?Eval ?thunkcodeseg <ends>
- ?ASSUMECS ;; back to original cs
-
- if (?sflags and ?S_NOCALL)
- JMP32 label32 ;; generate a 32-bit far jump
- .386p
- else
- call far ptr FLAT:label32 ;; generate a 32-bit far call
- endif
-
- label16 label far ;; and label for return jump
- % ?Eval ?thunkcodeseg <segment> ;; put thunk in 32 bit code
- assume cs:FLAT ;; change to flat cs
- endif
- else
- ?sflags = ?sflags or ?S_NOALIGNESP ;; don't align esp
- endif
- if ((?sflags and ?S_NOALIGNESP) eq 0) ;; align esp?
- ; push ebp
- ; lea ebp,4[esp]
- ; and esp,not 3
- ; push ebp
- ; mov ebp,ss:-4[ebp]
- endif
- if ((?cstype eq ?CS_32bit) eq 0)
- if ((?sflags and ?S_FAR32) eq 0) ;; thunk required?
- ?ThunkStrict %?sflags,, label16,, target
- endif
- endif
-
- if (?sflags and ?S_FAR32) ;; 32-bit far global thunk?
- CCall <target>,<args>,<far32,modifiers> ;; make 32 bit near call
- elseifnb <calltype>
- calltype <target>,<args>,<modifiers> ;; make 32 bit near call
- else
- call target ;; make 32-bit near call
- endif
- if ((?sflags and ?S_NOALIGNESP) eq 0) ;; was esp aligned?
- ; pop esp
- endif
-
- if ((?cstype eq ?CS_32bit) eq 0)
- if ((?sflags and ?S_FAR32) eq 0)
- if (?sflags and ?S_NOCALL) ;; if should use jmp
- ;; jmp far ptr label16 ;; jmp far 16:16 back to caller
- ;; use explicit opcodes to avoid masm 5 trailing nop
- db MI_OPERANDSIZE, MI_LONG_JMP
- dw offset label16, seg label16
- else
- retf ;; retfd back to caller
- endif
- % ?Eval ?thunkcodeseg <ends>
-
- ?ASSUMECS ;; back to original cs
- endif
- endif
- CpuMode reset ;; back to original cpu mode
- endm
-
- JMP32 macro name ;; jmp far ptr FLAT:name
- if2
- if (?cstype eq ?CS_32bit)
- ProcError <JMP32 name from 32 bit segment>
- .err
- endif
- endif
- .386p
- jmp far ptr FLAT:name
- CpuMode reset ;; back to original cpu mode
- endm
-
- ThunkFar32 macro name, lcl, segname, fnocheck
- if2
- ifnb <fnocheck>
- ifdif <fnocheck>,<nocheck>
- %out <ThunkFar32: bad nocheck arg: fnocheck>
- .err
- endif
- endif
- endif
- FARCODE HIGH32
- segname segment
- if2
- ifndef name
- extrn name:near
- endif
- endif
- GenFar32 name, lcl, <usecall>, <tolabel>
- ifnb <fnocheck>
- ?ThunkStrict ?S_NOCHECK, %F32PRE_, name,, name
- else
- ?ThunkStrict 0, %F32PRE_, name,, name
- endif
- GenFar32 name, lcl, <usecall>, <afterlabel>
- segname ends
- endm
-
-
- ?ThunkStrict macro sflags, srcpre, srclabel, tgtpre, tgtlabel
- ifdef MISCSTRICT
- if ((sflags and ?S_NOCHECK) eq 0)
- ?GenCall _AssertDSESFlat, ?farcode ;; force near call
- endif
- if ((sflags and ?S_NOSEGCHECK) eq 0)
- THUNKINIT_DATA segment
- dd offset FLAT:srcpre&srclabel ;; source address
- dd offset FLAT:tgtpre&tgtlabel ;; target address
- THUNKINIT_DATA ends
- endif
- endif
- endm
-
- ;*** SaveAlignESP - Save and Align ESP
- ;
- ; Save Current ESP and Align it
- SaveAlignESP macro ereg
- ifnb <ereg>
- mov ereg,esp
- and esp,not 3
- push ereg
- else
- mov eax,esp
- and esp,not 3
- push eax
- endif
- endm
-
- ;*** SegContext - load segment register(s)
- ;
- ; Make all given segment registers point to "base".
- ;
- ; ENTRY: srl = segment registers list in < >
- ; gr = general register to speed operation
- ; = blank - use slow way of loading registers
- ; noassume = blank - generate an assume sr:grpnam for
- ; each segment register sr
- ; = non-blank - don't generate assumes.
- ; base = value to be loaded into segment register(s)
- ; grpnam = name of group/segment to assume
- ;
- ; EXIT: code generated to load segment registers. If "gr" is
- ; supplied, its content is lost.
- ;
- ; SEE ALSO: TaskContext, DosHighContext, DosInitContext.
-
- ?smov macro a1, a2
- mov a1,a2
- endm
-
- SegContext macro srl,gr,noassume,base,grpnam
- local i
- ifnb <gr> ;; if intermediate general register
- ?gr1 equ <gr> ;; assume 16 bit gr
- irp r,<ax,bx,cx,dx,si,di>
- ifidni <e&&r&&>,<gr>
- ?gr1 equ <r> ;; oops, load selector into 16 bit gr
- exitm
- endif
- endm
- if (?cstype eq ?CS_32bit)
- ?gr2 catstr <e>,?gr1 ;; load sr from 32 bit gr
- else
- ?gr2 catstr <>,?gr1 ;; load sr from 16 bit gr
- endif
- ?smov %?gr1,<base> ;; load selector into 16 bit gr
- irp sr,<srl>
- ?smov sr,%?gr2 ;; load sr from native size gr
- endm
- else
- irp sr,<srl> ;; for sr = *first* segreg in list
- i = 0
- irp r,<srl> ;; for r = each segreg in list
- i = i + 1
- if (i eq 1) ;; if r is first in list
- push base
- else ;; else r is second (or later) in list
- push sr ;; and sr contains desired value
- endif
- pop r
- endm
- exitm ;; quit after sr = first in list
- endm
- endif
- ifb <noassume>
- irp sr,<srl>
- .lall
- assume sr:grpnam
- .xall
- endm
- endif
- endm
-
- ;*** DosContext - make segment register(s) point to DOSGROUP
- ;*** DosHighContext - make segment register(s) point to DOSHIGHDATA
- ;*** GDTContext - make segment register(s) point to DOSGDTDATA
- ;*** TaskContext - make segment register(s) point to SS; SS must be TASKAREA
- ;*** DosInitContext - make segment register(s) point to DOSINITDATA
- ;*** DosMTEContext - make segment register(s) point to DOSMTE
- ;*** FlatContext - make segment register(s) point to FLAT descriptor
- ;*** NullContext - make segment register(s) point to nothing
- ;
- ; Loads all given segment registers with the specified group.
- ; This is often used to set up DS in order to use a global DOS variable.
- ;
- ; ENTRY: srl = segment registers list in < >
- ; gr = general register to speed operation
- ; = blank - use slow way of loading registers
- ; noassume = blank - generate an assume sr:DOSGROUP for
- ; each segment register sr in "srl".
- ; = non-blank - don't generate assumes.
- ; (global variables)
- ; groups defined in dosseg.inc
- ;
- ; EXIT: code generated to load segment registers. If "gr" is
- ; supplied, its content is lost.
- ;
- ; SEE ALSO: SegContext
-
- DosContext macro srl,gr,noassume
- SegContext <srl>,gr,noassume,DOSGROUP,DOSGROUP
- endm
-
- DosHighContext macro srl,gr,noassume
- SegContext <srl>,gr,noassume,DOSHIGHDATA,DOSHIGHDATA
- endm
-
- GDTContext macro srl,gr,noassume
- SegContext <srl>,gr,noassume,DOSGDTDATA,DOSGDTDATA
- endm
-
- TaskContext macro srl,gr,noassume
- SegContext <srl>,gr,noassume,SS,TASKAREA
- endm
-
- DosInitContext macro srl,gr,noassume
- SegContext <srl>,gr,noassume,DOSINITDATA,DOSINITDATA
- endm
-
- DosMTEContext macro srl,gr,noassume
- SegContext <srl>,gr,noassume,DOSMTE,DOSMTE
- endm
-
- FlatContext macro srl,gr,noassume
- SegContext <srl>,gr,noassume,<seg FLAT:DGROUP>,FLAT
- endm
-
- NullContext macro srl,gr,noassume
- SegContext <srl>,gr,noassume,0,NOTHING
- endm
-
- ;*** ReferGlobal - declare external symbol in DOSGROUP.
- ;*** ReferGDT - declare external symbol in the DOSGDTDATA.
- ;*** ReferTask - declare external symbol in TASKGROUP.
- ;*** ReferHigh2 - declare external symbol in DOSHIGH2CODE.
- ;*** ReferInitGlobal - declare external symbol in DOSINITDATA.
- ;*** ReferFlat - Declare an external symbol in FLAT group.
- ;
- ; Declares a symbol as an external symbol in the appropriate segment.
- ;
- ; ENTRY sym = symbol name
- ; symtype = valid masm type
- ; = blank implies byte
- ; BUGBUG: ReferTask allows obsolete symtype values
- ; (global variables)
- ; segments defined in dosseg.inc
- ;
- ; EXIT extrn generated for the symbol.
-
- ReferGlobal macro sym, symtype, ifundef
- ?refer CONSTANTS, sym, symtype, ifundef
- endm
-
- ReferGDT macro sym, symtype, ifundef
- ?refer GDTSTART, sym, symtype, ifundef
- endm
-
- ReferTask macro sym, symtype, ifundef, nocheck
- local a
- ifb <nocheck>
- ifdef TKOPTDA
- %out ReferTask: not compatable with tkptda.inc
- .err
- endif
- endif
-
- ifnb <symtype>
- a = 0
- irp x, <83, 128, MAXMETANAME, MAXPATHLEN, PMPATHLEN, SRCHBUFSIZE>
- ifidn <symtype>, <x> ; Is symtype a known obsolete value?
- a = 1
- exitm
- endif
- endm
- else
- a = 1
- endif
- if a
- ?refer TASKDATA, sym, byte, ifundef
- else
- ?refer TASKDATA, sym, symtype, ifundef
- endif
- endm
-
- ReferHigh2 macro sym, symtype, ifundef
- ?refer HIGH2CODE, sym, symtype, ifundef
- endm
-
-
- ReferInitGlobal macro sym, symtype, ifundef
- ?refer INITDATA, sym, symtype, ifundef
- endm
-
- ReferFlat macro sym, symtype, ifundef
- .386p
- ?refer _DATA, sym, symtype, ifundef
- CpuMode reset
- endm
-
- ?refer macro segname, sym, symtype, ifundef
- ifnb <ifundef>
- if2
- ifndef sym
- segname segment
- ifb <symtype>
- .lall
- extrn sym:byte
- .xall
- else
- .lall
- extrn sym:symtype
- .xall
- endif
- segname ends
- endif
- endif
- else
- segname segment
- ifb <symtype>
- .lall
- extrn sym:byte
- .xall
- else
- .lall
- extrn sym:symtype
- .xall
- endif
- segname ends
- endif
- endm
-
- ifndef SN_DosCode
- ; We need SN_DosCode to be defined to compare against ?farcode.
- ; dosseg.inc may never be included after dosmac.inc, if used at all.
- SN_DosCode equ 0 ; meaningless, non-redefinable value
- endif
- ?farcode = SN_DosCode ; default to near code
-
- ;*** FARCODE - Introduce high DOS code segment
- ;
- ; Tell macros that generates hybrid procedure call's to generate
- ; far call's. (E.g. InternalError, DBPRT, PMONLY) This remains
- ; in effect until FARCODE is invoked again. This should be invoked
- ; just prior to every code segment declaration, and outside of all
- ; segments. If FARCODE is not invoked, the default is "FARCODE LOW".
- ;
- ; ENTRY: segname = "LOW" - select the DOSCODE group
- ; = "INIT" - select the DOSCODE group
- ; = "INITR3" - select the DOSINITR3CODE group
- ; = "HIGH2" - select the DOSHIGH2CODE group
- ; = "HIGH3" - select the DOSHIGH3CODE group
- ; = "HIGH4" - select the DOSHIGH4CODE group
- ; = "HIGH32" - select the DOSHIGH32CODE group
- ; NoPanic = blank - generate extrn's for the Panic
- ; and InternalError macro support routines,
- ; if they haven't been defined yet
- ; = non-blank - don't generate extrn's for
- ; IntErr and IntErrNull
- ; NoProtReal = blank - generate extrn's for the mode
- ; checking routines (see RMONLY, PMONLY)
- ; if they haven't been defined yet and
- ; MODECHECK is defined.
- ; = non-blank - don't generate extrn's for
- ; the mode checking routines.
- ; NoDPRINTF = blank - generate extern's for DPRINTF and
- ; dbtest if they haven't been defined yet
- ; and Debug is non-zero.
- ; = non-blank - don't generate extrn's for
- ; DPRINTF and dbtest.
- ; (global variables)
- ; DOSCODE = group defined in dosseg.inc
- ; MODECHECK = flag to enable the mode checking routines
- ; Debug = flag to control the DPRINTF and dbtest
- ; routines.
- ;
- ; EXIT: an assume cs: generated with the proper group name
- ; extrn's generated for debugging/mode-checking routines.
- ; (global variables)
- ; ?farcode = set to SN_xxx to remember which group was selected.
- ; ?cstype = set to ?CS_16bit or ?CS_32bit, according to the
- ; D bit setting for the new CS
-
- .386p
- assume fs:FLAT ;; to enable the FLAT keyword
- assume fs:nothing
- CpuMode reset
-
- ?ThunkSeg equ <THUNK_TEXT>
- ?PanicSuffix equ <bad suffix>
-
- FARCODE macro segname, NoPanic, NoProtReal, NoDPRINTF, NoAssertNoBuf
- ?cstype = ?CS_16bit ;; default is 16-bit code
- ?farcode = SN_DosCode ;; Indicate low code segment
- ?ASSUMECS macro
- assume cs:DOSCODE
- endm
- ?ThunkSeg equ <THUNK_TEXT>
- ?PanicSuffix equ <>
- ifidn <segname>,<LOW>
- ?PanicSuffix equ <LOW>
- elseifidn <segname>,<INIT>
- ?PanicSuffix equ <LOW>
- ?ThunkSeg equ <THUNKINIT_TEXT>
- elseifidn <segname>,<INITR3>
- ?PanicSuffix equ <INITR3>
- ?farcode = SN_DosInitR3Code ;; Indicate which far code segment
- ?ASSUMECS macro
- assume cs:DOSINITR3CODE
- endm
- ?ThunkSeg equ <no ring 3 thunks>
- elseifidn <segname>,<HIGH2>
- ?PanicSuffix equ <HIGH2>
- ?farcode = SN_DosHigh2Code ;; Indicate which far code segment
- ?ASSUMECS macro
- assume cs:DOSHIGH2CODE
- endm
- elseifidn <segname>,<HIGH3>
- ?PanicSuffix equ <HIGH3>
- ?farcode = SN_DosHigh3Code ;; Indicate which far code segment
- ?ASSUMECS macro
- assume cs:DOSHIGH3CODE
- endm
- elseifidn <segname>,<HIGH4>
- ?PanicSuffix equ <HIGH4>
- ?farcode = SN_DosHigh4Code ;; Indicate which far code segment
- ?ASSUMECS macro
- assume cs:DOSHIGH4CODE
- endm
- elseifidn <segname>,<HIGH32>
- ?PanicSuffix equ <HIGH32>
- ?farcode = SN_DosHigh32Code ;; Indicate which far code segment
- ?cstype = ?CS_32bit ;; Mark as 32-bit code segment
- ?ASSUMECS macro
- assume cs:FLAT
- endm
- elseif2
- %out FARCODE: bad segment name: segname
- .err
- endif
- if1
- ifndef _TKSSBase
- ReferFlat _TKSSBase,dword
- endif
- endif
- ifdef INTERRPRT
- EXTRNFAR __panicsprintf,<NoPanic>
- endif
- ifdef MODECHECK
- EXTRN16 TaskOnly,<NoProtReal>
- EXTRNFAR TaskOnly,<NoProtReal>
- EXTRNFAR ProtTaskOnly,<NoProtReal>
- EXTRNFAR ProtOnly,<NoProtReal>
- EXTRNFAR RealTaskOnly,<NoProtReal>
- EXTRNFAR RealOnly,<NoProtReal>
- EXTRNFAR RealProcTaskOnly,<NoProtReal>
- endif
- if Debug
- EXTRNFAR DPRINTF,<NoDPRINTF>
- EXTRNFAR dbtest,<NoDPRINTF>
- endif
- ifdef FSSTRICT
- if ?farcode ne SN_DosHigh2Code
- EXTRNFAR AssertNoBufProc,<NoAssertNoBuf>
- endif
- endif
- ?ASSUMECS
- .386p
- assume ds:nothing,es:nothing,fs:nothing,gs:nothing,ss:nothing
- CpuMode reset
- endm
-
-
- ;*** InternalError - panic when things go wrong
- ;
- ; Calls Panic macro.
- ;
- ; ENTRY arg = error message to display before system halts
- ; EXIT Panic macro invoked.
-
- InternalError macro arg
- if (?farcode eq SN_DosCode) ;; if in tiled code, assume realmode
- Panic <'&arg&'>,,,realmode
- else
- Panic <'&arg&'>
- endif
- endm
-
- ;*** Panic - print panic message and halt the system
- ;
- ; This macro prints the specified panic message (with parameters) and
- ; halts the system.
- ;
- ; ENTRY fmt - message format string
- ; parmlist - parameter list
- ; n - source-file-unique Panic number
- ; frealmode - "realmode" flag
- ; EXIT *DOES NOT RETURN*
-
- PANICBASE equ 60000 ; start high to avoid source line conflict
- ?paniccnt = PANICBASE
- ?PF_TILED equ 01h
- ?PF_FILE equ 02h
- ?panicfile = 0
- ?panicmsgseg equ <bad seg>
-
- Panic macro fmt,parmlist,n,frealmode
- local fmtoff, cparms, rmode
- if2
- ifnb <frealmode>
- ifdif <frealmode>,<realmode>
- ProcError <Panic: bad realmode arg: frealmode>
- .err
- endif
- endif
- endif
- .386p
- ?panicfn equ <__panic>
- rmode = 0
- ifnb <frealmode>
- if (?farcode eq SN_DosCode) ;; If in tiled code segment
- ?panicfn equ <__panicRM>
- rmode = 1
- endif
- endif
- ?om1 = 0
- ifdef INTERRPRT
- ifndef NOINTERRPRT
- ifnb <fmt>
- ?om1 = 1 ;; display filename and message text
- endif
- endif
- endif
- if (?om1 ne 0)
- ?panicfn equ <__panicfnmsg>
- ?panicmsgseg equ <PANICMSG>
- ifnb <frealmode> ;; don't use rmode flag!!
-
- ;; If this invocation requires __FILE__ in the tiled data segment,
- ;; then make sure the first Panic invocation put it there.
-
- if (rmode ne 0)
- if ((?panicfile and (?PF_FILE or ?PF_TILED)) eq ?PF_FILE)
- if2
- ProcError <first Panic must specify realmode>
- .err
- endif
- exitm
- endif
- ?panicfn equ <__panicfnmsgRM>
- endif
-
- ;; Put the strings in the low (tiled) data segment if realmode was
- ;; specified in the tiled code segment (DOSCODE) OR if this is the
- ;; very first Panic invocation and the realmode flag was specified.
- ;; This allows a real mode Panic invocation to access the __FILE__
- ;; and fmtoff strings. rmode is non-zero when InternalError was
- ;; invoked in DOSCODE. ?panicfile is zero when this is the first
- ;; Panic invocation.
-
- if ((rmode ne 0) or (?panicfile eq 0))
- ?panicmsgseg equ <INTERRMSG>
- if (?panicfile eq 0)
- ?panicfile = ?panicfile or ?PF_TILED
- endif
- endif
- endif
- % ?Eval ?panicmsgseg <segment> ;; put string in proper segment
- if ((?panicfile and ?PF_FILE) eq 0)
- ifdef SCCSID
- __FILE__ db SCCSID, 0
- else
- if2
- % %out @FileName.asm: Panic: SCCSID undefined
- .err
- endif
- % __FILE__ db '&@FileName&.asm', 0
- endif
- ?panicfile = ?panicfile or ?PF_FILE
- endif
- fmtoff db fmt, 0 ;; Format string
- % ?Eval ?panicmsgseg <ends>
-
- cparms = 0
- irp x,<parmlist>
- cparms = cparms + 1 ;; Count arguments
- PUSHD <x> ;; Push arguments
- endm
- if (rmode ne 0)
- push offset DOSGROUP:fmtoff ;; Push format string address
- else
- PUSHD <offset FLAT:fmtoff> ;; Push FLAT format string address
- endif
- if (cparms ne 0) ;; sprintf into a buffer
- if2
- if (rmode ne 0)
- ProcError <Panic: no parms in realmode>
- .err
- endif
- ifdef SN_DosInitR3Code
- if ?farcode eq SN_DosInitR3Code
- ProcError <Panic: no parms in ring 3>
- .err
- endif
- endif
- endif
- if ?cstype eq ?CS_32bit
- ?GenCall __panicsprintf, SN_DosHigh32Code
- else
- CALLFAR __panicsprintf
- endif
- lea esp,[esp + (cparms * 4)] ;; clean up the stack
- ?panicfn equ <__panicfn>
- endif
- if (rmode ne 0)
- push offset DOSGROUP:__FILE__ ;; Push filename address
- else
- PUSHD <offset FLAT:__FILE__> ;; Push FLAT filename address
- endif
- endif
- CpuMode reset ;; reset cpu mode
- if (rmode eq 0)
- ?panicfn catstr ?panicfn,?PanicSuffix;; build panic function name
- endif
- ?GenCall %?panicfn, %?farcode ;; call panic thunk near
- if (?ModNumber eq 0ffffh)
- ?ModNumber = 0
- if2
- % %out @FileName.asm: Panic: FNO_NUM undefined - use ModName macro
- .err
- endif
- endif
- dw ?ModNumber ;; store file number
- ifnb <n>
- dw n ;; store specified "line number"
- else
- dw ?paniccnt ;; store computed "line number"
- ?paniccnt = ?paniccnt + 1
- endif
- endm
-
- ;*** ModName - declare module name for debugging purpose
- ;
- ; The module number is used for generating Panic file numbers.
- ;
- ; ENTRY: modname = module name (ignored; see masm's @FileName feature)
- ; modnumber = module number (used for Panic invocations)
- ;
- ; EXIT:
- ; (global variables)
- ; ?ModNumber = file number
-
- ?ModNumber = 0ffffh
-
- ModName macro modname, modnumber
- ifnb <modnumber>
- ?ModNumber = modnumber
- endif
- endm
-
- ;*** BeginNoBlock/EndNoBlock - begin/end kernel critical section.
- ;
- ; Debugging aid only. If ProcBlocks or task switches are attempted
- ; between a BeginNoBlock/EndNoBlock pair, an internal error will result.
-
- BeginNoBlock macro segreg
- ?NoBlock segreg,<inc>,<BeginNoBlock>
- endm
-
- EndNoBlock macro segreg
- ?NoBlock segreg,<dec>,<EndNoBlock>
- endm
-
- ?NoBlock macro segreg,incdec,beginend
- ifdef MISCSTRICT
- ifndef _cTKNoBlock
- ReferGlobal _cTKNoBlock, byte
- endif
- pushf
- ifnb <segreg>
-
- ;; inc FLAT:[_cTKNoBlock] generates a FLAT-relative 16 bit
- ;; offset fixup, which the linker rejects. inc DS:[_cTKNoBlock]
- ;; with DS assumed FLAT by the caller generates a FLAT-relative
- ;; 32 bit fixup, which works ok.
-
- if2
- ifidn <segreg>,<FLAT>
- ProcError <beginend: masm will not allow segreg>
- .err
- endif
- endif
- incdec segreg:[_cTKNoBlock] ;; inc/dec counter
- elseif (?cstype eq ?CS_32bit)
- incdec [_cTKNoBlock] ;; inc/dec counter
- else
-
- ;; The following doesn't work if the chosen segment register is
- ;; already assumed FLAT. In such a case, masm generates a FLAT
- ;; relative reference with a non-FLAT segment register. We use
- ;; FS here and disallow the construct in 32 bit code in a feeble
- ;; attempt to avoid using a segment register that is assumed FLAT.
-
- .386p
- push fs
- DosContext fs,,noassume
- incdec fs:[_cTKNoBlock] ;; inc/dec counter
- pop fs
- CpuMode reset
- endif
- popf
- endif
- endm
-
- ;*** TaskTime - enforce non-InterruptLevel execution context
- ;
- ; Debugging aid only. If running at InterruptLevel,
- ; an internal error will be generated.
-
- TaskTime macro
- ifdef MODECHECK
- ?GenCall TaskOnly, SN_DosCode
- endif
- endm
-
- ;*** AssertCLD - Check the state of the direction flag
- ;
- ; Entry: none
- ; Exit: none
- ; Uses: <reg>, Flags
- ;
- ; Causes an internal error if the direction flag is set
- ;
- AssertCLD macro proc, reg
- local acld
- ifdef MISCSTRICT
- ifnb <reg>
- pushf
- pop reg
- test reg,F_DIRECTION ;; make sure mi.inc is included
- else
- push ax
- pushf
- pop ax
- test ax,F_DIRECTION ;; make sure mi.inc is included
- pop ax
- endif
- jz acld ;; jmp if direction flag is clear
- InternalError <&proc&: direction flag set>
- acld:
- endif
- endm
-
- ;*** AssertNoBuf - Assert that current thread isn't holding a buffer
- ;
- ; AssertNoBuf is used to detect certain states that often lead to
- ; deadlock. In particular, we'll often deadlock if we call the
- ; swapper while holding a buffer. We can call the swapper either
- ; via a call to the memory manager, or via taking a not-present
- ; fault touching a swappable segment. AssertNoBuf should be placed
- ; anywhere we might do these things to help catch accidentally doing
- ; them with a buffer locked.
- ;
- ; AssertNoBuf is turned on by the FSSTRICT flag.
- ;
- ; AssertNoBuf is by no means fool-proof, but should detect the
- ; majority of cases where we have a buffer locked.
- ;
- ; ENTRY (SS) = TASKAREA
- ; EXIT None if OK, InternalError if error found
- ; USES None, including flags
- ;
-
- AssertNoBuf macro
- ifdef FSSTRICT
- ?GenCall AssertNoBufProc, SN_DosHigh2Code
- endif
- endm
-
- ;*** DefTaskData - define resizable task control data structures
- ;
- ; This macro is used to declare a task control data
- ; structure that can be resized after the maximum
- ; number of threads allowed in the system has been
- ; determined
- ;
- ; INPUT name Name of pointer to structure
- ; width Width of an element in structure
- ; length Number of elements in structure
- ; value Initial value for each element
- ; flatname Name of flat pointer to structure
-
- DefTaskData macro name,width,length,value,flatname
- local l
-
- CONSTANTS segment
- public name
- name dw offset DOSGROUP:l
- CONSTANTS ends
-
- .386p
- _DATA segment
- ifb <flatname>
- public fl_&name
- fl_&name dd offset FLAT:l
- else
- public flatname
- flatname dd offset FLAT:l
- endif
- _DATA ends
-
- LASTDATA segment
- dw offset DOSGROUP:name ;; point to pointer to this array
- ifb <flatname>
- dd offset FLAT:fl_&name ;; point to flat pointer to this array
- else
- dd offset FLAT:flatname ;; point to flat pointer to this array
- endif
- ifidni <width>,<word>
- db 2 ;; give the width of the item
- l dw length dup (value) ;; reserve space for the item
- elseifidni <width>,<byte>
- db 1
- l db length dup (value)
- elseifidni <width>,<dword>
- db 4
- l dd length dup (value)
- else
- db width
- l db length dup (width dup (value))
- endif
- LASTDATA ends
- CpuMode reset
- endm
-
- ;*** CallGate - call API from ring3 code
- ;
- ; This is for system init process or for kernel exitlist or
- ; signal dispatch code to get into kernel mode. Kernel entry
- ; looks just like an API call.
- ;
- ; ENTRY: gate = name of api routine
- ; (global variables)
- ; GDT_&gate = GDT entry defined in api.asm, api2.asm
- ;
- ; EXIT: a call instruction generated to call the call gate.
-
- CallGate macro gate
- ifndef GDT_&gate
- extrn GDT_&gate:BYTE
- endif
- db MI_LONG_CALL ; far ret
- dw 0,GSEL GDT_&gate ; selector of call gate
- endm
-
- ;*** StampRPL - Stamps the RPL of the selector parameter with the RPL
- ; of the SS of the caller.
- ;
- ; Entry: <sel> contains selector to be stamped (not base register)
- ; <reg> contains a free index register (if it exists). It is
- ; used to access the user Stack Segment, else the bp is used.
- ; <curtcbreg> is a register that already contains [CurrTCB].
- ;
- ; Exit: Stamped selector in <sel> register
- ;
- ; Uses: <sel,reg>
- ;
-
- StampRPL macro sel, reg, currtcbreg
- .errnb <currtcbreg>
- ifb <reg>
- push bp
- mov bp,ss:[TKOPTDA].CurrTSD
- mov bp,ss:[bp].TSDUserSS
- arpl sel,bp
- pop bp
- else
- mov reg,ss:[TKOPTDA].CurrTSD
- mov reg,ss:[reg].TSDUserSS
- arpl sel,reg
- endif
- endm
-
- ;*** JPathChar, JNPathChar
- ;*** TestPathChar
- ;
- ; Conditional jumps based on whether AL is a path seperator character.
- ;
- ; IMPORTANT NOTE: These macros do NOT account for / as a possible
- ; path separator character. Only \ is tested for.
- ;
- ; JPathChar, JNPathChar - jump if AL contains a path char
- ; (JPathChar) or if AL does not contain a path char
- ; (JNPathChar).
- ;
- ; TestPathChar - just set Z flag based on whether AL is path char.
- ; (no jump is performed).
- ;
- ; ENTRY: AL: character to test
- ;
- ; EXIT : ZR: character is a path character
- ; NZ: character is not a path character
- ;
- ; USES : AL
- ;
-
-
- JPathChar MACRO target
- cmp al,'\'
- je target
- ENDM
-
- JNPathChar MACRO target
- cmp al,'\'
- jne target
- ENDM
-
- TestPathChar MACRO
- cmp al,'\'
- ENDM
-