;       SCCSID = @(#)dhrouter.asm       6.11 91/11/16
SCCSID  equ     "@(#)dhrouter.asm       6.11 91/11/16"
PAGE    ,132
TITLE   DevHlp Router - Interface to device driver helper routines.

;**     DHROUTER - DevHelp Router
;
;       IBM/Microsoft Confidential
;
;       Copyright (c) IBM Corporation 1987, 1989
;       Copyright (c) Microsoft Corporation 1987, 1989
;
;       All Rights Reserved
;
;       When a device is initialized, it is passed the address of the DevHelp
;       Router.
;
;       Device drivers invoke the various functions by calling this procedure
;       and indicating the desired subfunctions.  Some subfunctions are only
;       valid at task-time, some at interrupt time, and some both.  Most
;       of these subfunctions are offered as a convenience, it may be
;       required that some be used... see the individual documentation.
;
;       80030 - 3/2/94 - RAC Uncomment devhelp for RAS so call is made to
;                        dh_RAS subroutine.
;
;       82818 ChangeTeam 02/07/95                                    ;82818
;       82818     Moving r206 debug .mk command to R207              ;82818
;  	148753 03/15/96 Interim PNP Solution			     ;148753	
;

INCL_DOSERRORS  EQU     1

.xlist
.xcref
include dosseg.inc
include basemaca.inc
include fnodev.inc
include osmaca.inc
include defdbug.inc
include dossymc.inc
include ostypes.inc
include osconst.inc
include sigdef.inc
include except.inc
include devhlp.inc
include devsym.inc
include exec.inc
include mmpha.inc               ;if removed replace with include rasmacro.inc
include mi.inc
include pmode.inc
include struc.inc               ; 148753
include infoseg.inc
include pgexport.inc
include vmowner.inc
include vmexport.inc
include selxport.inc
include tkexport.inc
include curdir.inc
include dirent.inc
include find.inc
include screen.inc
include sem.inc
include kmode.inc
include tkptda.inc
include aberror.inc
include bseerr.inc                                 ;DCR1535
include devclass.inc                               ;DCR1535
.cref
.list
        CpuMode 386

        ModName dhrouter,FNO_DHROUTER_ASM

        ReferGlobal     InDos,BYTE
        ReferGlobal     InterruptLevel,DWORD
        ReferGlobal     TaskData,WORD
        ReferGlobal     ABIOS_present,BYTE
        ReferGlobal     DevClassTables,WORD              ;DCR1535
        ReferFlat       _pVDMInt13,DWORD


        EXTRNF32        INTDHSetIRQ
        EXTRNF32        INTDHUnSetIRQ
        EXTRNF32        INTDHEOI
        EXTRNF32        INTDHSetROMVector
        EXTRNF32        INTDHRegisterStackUsage
        EXTRNF32        KMExitKmodeEvents
        EXTRNF32        SecDevRoute                                       ;@SEC
        EXTRNFAR        w_KillProc                                        ;@SEC
        EXTRN32         _QSQuerySysState                                  ;@SEC

        EXTRN32         _VDMInt13CreateMiniVDM
        EXTRN32         _TKCreateVDMProcess
        EXTRN32         _SELVirtToLin

        EXTRN32         _dhw_32KrnlExit                  ; F78693

        EXTRN           _VMDH_AllocRemoveAccess:NEAR
        EXTRN           _VDMMDHRegisterPDD:NEAR
        EXTRN           AllocPhysDM:NEAR
        EXTRN           dh_AllocReqPacket:NEAR
        EXTRN           DevDone:NEAR
        EXTRN           dh_ABIOSCall:NEAR
        EXTRN           dh_ABIOSGetParms:NEAR
        EXTRN           dh_ABIOSCommonEntry:NEAR
        EXTRN           dh_AttachDD:NEAR
        EXTRN           dh_DeRegister:NEAR
        EXTRN           dh_FreeLIDEntry:NEAR
        EXTRN           dh_GetLIDEntry:NEAR
        EXTRN           dh_GetDeviceBlock:NEAR
        EXTRN           dh_LogEntry:NEAR
        EXTRN           dh_ModifyPriority:NEAR
        EXTRN           dh_MonFlush:NEAR
        EXTRN           dh_MonitorCreate:NEAR
        EXTRN           dh_MonWrite:NEAR
        EXTRN           dh_PhysToVirt:NEAR
        EXTRN           dh_RAS:NEAR                       ; 80030
        EXTRN           dh_Register:NEAR
IFDEF PROFILE
        EXTRN           dh_RegisterProfile:NEAR
ENDIF;PROFILE
        EXTRN           dh_ResetTimer:NEAR
        EXTRN           dh_SemClear:NEAR
        EXTRN           dh_SemHandle:NEAR
        EXTRN           dh_SemRequest:NEAR
        EXTRN           dh_SendEvent:NEAR
        EXTRN           dh_SetTimer:NEAR
        EXTRN           dh_TickCount:NEAR
        EXTRN           dh_UnPhysToVirt:NEAR
        EXTRN           dh_VerifyAccess:NEAR
        EXTRN           dh_Yield:NEAR
        EXTRN           dh_YieldTC:NEAR

        EXTRN           dh_RegisterBeep:NEAR
        EXTRN           dh_RegisterFreq:NEAR
        EXTRN           dh_Beep:NEAR

        EXTRN           dh_AllocateGDTSelector:NEAR
        EXTRN           dh_PhysToGDTSelector:NEAR
        EXTRN           dh_FreeGDTSelector:NEAR
        EXTRN           dh_PhysToGDTSel:NEAR    ;BUGBUG - temporary
        EXTRN           dh_RealToProt:NEAR
        EXTRN           dh_ProtToReal:NEAR
        EXTRN           dh_InternalError:NEAR

        EXTRN           FreePhysDM:NEAR
        EXTRN           dh_FreeReqPacket:NEAR
        EXTRN           GetDOSVar:NEAR
        EXTRN           dh_PhysToUVirt:NEAR
        EXTRN           PhysToVirtDM:NEAR
        EXTRN           dh_ProcBlock:NEAR
        EXTRN           dh_ProcRun:NEAR
        EXTRN           dh_ProcRun2:NEAR
        EXTRN           PushRequest:NEAR
        EXTRN           PullRequest:NEAR
        EXTRN           PullParticular:NEAR
        EXTRN           QueueFlush:NEAR
        EXTRN           QueueWrite:NEAR
        EXTRN           QueueRead:NEAR

if RAS
;       EXTRN           RASRST:FAR
endif

        EXTRN           SchedAddr:NEAR
        EXTRN           SegLockDM:NEAR
        EXTRN           SegUnlockDM:NEAR
        EXTRN           SortRequest:NEAR
        EXTRN           VirtToPhysDM:NEAR
        EXTRN           dh_ReallocSeg:NEAR

        EXTRN           dh_VMLock:NEAR
        EXTRN           dh_VMUnlock:NEAR
        EXTRN           dh_VMAlloc:NEAR
        EXTRN           dh_VMSetMem:NEAR
        EXTRN           dh_VMFree:NEAR
        EXTRN           dh_VMProcessToGlobal:NEAR
        EXTRN           dh_VMGlobalToProcess:NEAR
        EXTRN           dh_VirtToLin:NEAR
        EXTRN           dh_LinToGDTSelector:NEAR
        EXTRN           dh_GetDescInfo:NEAR
        EXTRN           dh_PageListToLin:NEAR
        EXTRN           dh_LinToPageList:NEAR
        EXTRN           dh_PageListToGDTSelector:NEAR
        EXTRN           dh_RegisterTmrDD:NEAR
        EXTRN           dh_RegisterPerfCtrs:NEAR

        EXTRN           Save_Message:NEAR
        EXTRN           dh_VideoPause:NEAR                              ;  D607

        EXTRN           dh_AllocateCtxHook:NEAR
        EXTRN           dh_FreeCtxHook:NEAR
        EXTRN           dh_ArmCtxHook:NEAR

        EXTRN           dh_OpenEventSem:NEAR
        EXTRN           dh_CloseEventSem:NEAR
        EXTRN           dh_PostEventSem:NEAR
        EXTRN           dh_PMPostEventSem:NEAR
        EXTRN           dh_ResetEventSem:NEAR
        EXTRN           dh_DynamicAPI:NEAR

;148753	begin
DevHlp_SYIOpenFile      EQU     127     ; 7FH  File open
DevHlp_SYICloseFile     EQU     128     ; 80H  File close
DevHlp_SYIReadFile      EQU     129     ; 81H  File system Read
DevHlp_SYIReadAtFile    EQU     130     ; 82H  File system Read Seek

        EXTRN           SYIOpenFile:NEAR
        EXTRN           SYICloseFile:NEAR
        EXTRN           SYIReadFile:NEAR
        EXTRN           syiReadAtFile:NEAR
;148753 end

_DATA   SEGMENT

;***ED  _fpfnDHKernelExit - kernel exit address for the devhlp router
;
                        public  _fpfnDHKernelExit
_fpfnDHKernelExit       df      dhKernelExit

_DATA   ENDS

CONSTANTS       SEGMENT

;**     dh_tabl - macro for devhlp router table entries
;

dh_tabl macro   rout,mode
        dw      offset DOSCODE:rout
        db      mode
        NumFunctions = NumFunctions+1
endm

dh_tablsize = 3                 ; no. of bytes generated by the dh_tabl macro

NumFunctions = 0

IT = 1          ; callable at device driver initialization time
KM = 2          ; callable in kernel-task mode
IM = 4          ; callable in interrupt mode
AB = 8          ; Available only on ABIOS machine

;*************************************************************************
;*                                                                       *
;* DEVHELP STATISTICS CODE                                               *
;*                                                                       *
;*   This code adds an array of counters that can be viewed with the     *
;* kernel debugger at DHFuncTbl.  These counters record the invocations  *
;* each DevHelp.  The total count of DevHelps is accumulated in the      *
;* 64-bit variable (dhhiinvoks,dhinvoks).   A per-second invocation      *
;* count is stored in lastseccount.                                      *
;*                                     --Rob Rose 03/28/94               *
;* (This is part 1 of a two part #ifdef block)                           *
;*************************************************************************
IFDEF 0
        EVEN                            ;RAR
        public startcounttik,dhinvoks,dhhiinvoks,lastseccount
        public DHFuncTbl
startcounttik   dd      0               ;RAR
dhinvoks        dd      0               ;RAR
dhhiinvoks      dd      0               ;RAR
lastseccount    dd      0               ;RAR
DHFuncTbl       dd      (100h) dup (0)  ;RAR
ENDIF

        EVEN
        public  DevhlpFuncDisp
DevhlpFuncDisp  label   word

dh_tabl SchedAddr,        <KM+   IT>    ;  0 Returns SchedClock's address
dh_tabl DevDone,          <KM+IM   >    ;  1 Device I/O complete
dh_tabl dh_Yield,         <KM      >    ;  2 Yield CPU
dh_tabl dh_YieldTC,       <KM      >    ;  3 Yield CPU to time critical
dh_tabl dh_ProcBlock,     <KM   +IT>    ;  4 Block on event
dh_tabl dh_ProcRun,       <KM+IM   >    ;  5 Unblock process

dh_tabl dh_SemRequest,    <KM      >    ;  6 Claim a semaphore
dh_tabl dh_SemClear,      <KM+IM   >    ;  7 Release a semaphore
dh_tabl dh_SemHandle,     <KM+IM   >    ;  8 Get a semaphore handle

dh_tabl PushRequest,      <KM      >    ;  9 Push the request
dh_tabl PullRequest,      <KM+IM   >    ;  A Pull next request from Q
dh_tabl PullParticular,   <KM+IM   >    ;  B Pull a specific request
dh_tabl SortRequest,      <KM      >    ;  C Push request in sorted order

dh_tabl dh_AllocReqPacket, <KM      >   ;  D allocate a tiled request packet
dh_tabl dh_FreeReqPacket,  <KM      >   ;  E free a tiled request packet

dh_tabl QueueFlush,       <KM+IM+IT>    ;  F Init char queue
dh_tabl QueueFlush,       <KM+IM   >    ; 10 Clear a char queue
dh_tabl QueueWrite,       <KM+IM   >    ; 11 Put a char in the queue
dh_tabl QueueRead,        <KM+IM   >    ; 12 Get a char from the queue

dh_tabl SegLockDM,        <KM   +IT>    ; 13 Lock memory object
dh_tabl SegUnlockDM,      <KM   +IT>    ; 14 Unlock memory object

dh_tabl dh_PhysToVirt,    <KM+IM+IT>    ; 15 convert physical to virtual addr
dh_tabl VirtToPhysDM,     <KM   +IT>    ; 16 convert virtual to physical addr
dh_tabl dh_PhysToUVirt,   <KM   +IT>    ; 17 convert phys to LDT

dh_tabl AllocPhysDM,      <KM   +IT>    ; 18 allocate physical
dh_tabl FreePhysDM,       <KM   +IT>    ; 19 free physical

dh_tabl dh_SetROMVector,  <KM   +IT>    ; 1A set a ROM service routine vector
dh_tabl dh_SetIRQ,        <KM   +IT>    ; 1B set an IRQ interrupt
dh_tabl dh_UnSetIRQ,      <KM+IM+IT>    ; 1C unset an IRQ interrupt

dh_tabl dh_SetTimer,      <KM+IM+IT>    ; 1D set timer request handler
dh_tabl dh_ResetTimer,    <KM+IM+IT>    ; 1E unset timer request handler

dh_tabl dh_MonitorCreate, <KM   +IT>    ; 1F create monitor
dh_tabl dh_Register,      <KM      >    ; 20 register monitor
dh_tabl dh_DeRegister,    <KM      >    ; 21 de-register monitor
dh_tabl dh_MonWrite,      <KM+IM   >    ; 22 pass data to monitor
dh_tabl dh_MonFlush,      <KM      >    ; 23 remove all data from stream

dh_tabl GetDOSVar,        <KM   +IT>    ; 24 Return pointer to DOS variable
dh_tabl dh_SendEvent,     <KM+IM   >    ; 25 Event occurred
dh_tabl dvhe,             <KM+IM+IT>    ; 26 ROM Critical Section

dh_tabl dh_VerifyAccess,  <KM      >    ; 27 Verify access to memory
dh_tabl dh_RAS,           <KM+IM+IT>    ; 28 Put info in RAS trace buffer ;80030
dh_tabl dh_ABIOSGetParms, <      IT+AB> ; 29 Get ABIOS Parameters
dh_tabl dh_AttachDD       <KM+IM+IT>    ; 2A Attach to a device driver
dh_tabl dh_InternalError, <KM+IM+IT>    ; 2B Signal an internal error
dh_tabl dh_ModifyPriority,<KM+IM+IT>    ; 2C Undocumented! (used by PM)
dh_tabl dh_AllocateGDTSelector, <KM+   IT> ; 2D Allocate GDT Selectors
dh_tabl dh_PhysToGDTSelector,   <KM+IM+IT> ; 2E Convert phys addr to GDT sel
dh_tabl dh_RealToProt,    <KM+IM   >    ; 2F Change from real to protected mode
dh_tabl dh_ProtToReal,    <KM+IM   >    ; 30 Change from protected to real mode
dh_tabl dh_EOI,           <   IM+IT>    ; 31 Send EOI to PIC
dh_tabl dh_UnPhysToVirt,  <KM+IM+IT>    ; 32 convert physical to virtual addr
dh_tabl dh_TickCount,     <KM+IM+IT>    ; 33 modify timer
dh_tabl dh_GetLIDEntry,   <KM   +IT+AB> ; 34 Get Logical ID
dh_tabl dh_FreeLIDEntry,  <KM   +IT+AB> ; 35 Release Logical ID
dh_tabl dh_ABIOSCall,     <KM+IM+IT+AB> ; 36 Call ABIOS
dh_tabl dh_ABIOSCommonEntry,    <KM+IM+IT+AB> ; 37 Call ABIOS Common Entry Point
dh_tabl dh_GetDeviceBlock,<      IT+AB> ; 38 Get ABIOS Device Block
IFDEF PROFILE
dh_tabl dh_RegisterProfile,     <KM+IM+IT> ; 39 Register Profile DD Handler
ELSE
dh_tabl dvhe,             <KM+IM+IT>    ; 39 Reserved for Profile
ENDIF;PROFILE
dh_tabl dh_RegisterStackUsage,  <      IT> ; 3A Register for Stack Usage
dh_tabl dh_LogEntry,      <KM+IM   >    ; 3B Log Entry

dh_tabl dh_VideoPause,    <KM+IM+   IT>  ; 3C VideoPause entry             D607
dh_tabl Save_Message,     <         IT>  ; 3D  Display INIT messages
dh_tabl dh_ReallocSeg,    <KM      +IT>  ; 3E  realloc segment
dh_tabl SortRequest,      <KM         >  ; 3F Sort requests (internal)
dh_tabl PullRequest,      <KM+IM      >  ; 40 Pull requests (internal)
dh_tabl dvhe,             <KM+IM+IT>     ; 41 AOX addr conversion (withdrawn)
dh_tabl dvhe,             <KM+IM+IT>     ; 42 AOX addr conversion (withdrawn)
dh_tabl dh_RegisterDeviceClass, <KM+  +IT> ; 43 Register Adapter Dev Driver
; dh_Sec security devhlp need to be called in task mode for audit hooks ;@SEC
; and at interrupt time for the keyboard dd (trusted path notify).      ;@SEC
dh_tabl dh_Sec,           <KM+IM   +IT>  ; 44 Security Functions        ;@SEC

REPT  (050h-NumFunctions)                ; 45-4F Pad out unused devhlp numbers
dh_tabl dvhe,             <KM+IM+IT>
ENDM
;
; 32-Bit DevHelps start at 80 (50h)
;
dh_tabl dh_RegisterPDD,   <KM   +IT>    ; 50 Register PDD for VDD (MVDM)
dh_tabl dh_RegisterBeep,  <KM   +IT>    ; 51 Register Beep entry point
dh_tabl dh_Beep,          <KM+IM+IT>    ; 52 Device beep support
dh_tabl dh_FreeGDTSelector,     <KM+   IT> ; 53 Free Sel allocated via 2D
dh_tabl dh_PhysToGDTSel,  <KM+IM+IT>    ; 54 Phys addr to GDT sel with access
dh_tabl dh_VMLock,      <KM     +IT>    ; 55 Lock linear address range
dh_tabl dh_VMUnlock,    <KM     +IT>    ; 56 Unlock linear address range
dh_tabl dh_VMAlloc,     <KM     +IT>    ; 57 Allocate memory
dh_tabl dh_VMFree,      <KM     +IT>    ; 58 Free memory or mapping
dh_tabl dh_VMProcessToGlobal,   <KM   > ; 59 Create global mapping to task mem.
dh_tabl dh_VMGlobalToProcess,   <KM   > ; 5A Create task mapping to global mem.
dh_tabl dh_VirtToLin,   <KM +IM +IT>    ; 5B Convert virtual address to linear
dh_tabl dh_LinToGDTSelector, <KM+IM+IT> ; 5C Convert linear address to virtual
dh_tabl dh_GetDescInfo  <KM +IM +IT>    ; 5D Return descriptor info.
dh_tabl dh_LinToPageList, <KM+IM+IT>    ; 5E build PageList array from lin addr
dh_tabl dh_PageListToLin, <KM+IM+IT>    ; 5F map PageList array to lin addr
dh_tabl dh_PageListToGDTSelector <KM+IM+IT>; 60 map PageList array to GDT sel
dh_tabl dh_RegisterTmrDD, <IT>          ; 61 Register Tmr DD
dh_tabl dh_RegisterPerfCtrs, <IT>       ; 62 Register DD Performance Ctrs

dh_tabl dh_AllocateCtxHook <KM   +IT>   ; 63 allocate a context hook
dh_tabl dh_FreeCtxHook     <KM   +IT>   ; 64 free a context hook
dh_tabl dh_ArmCtxHook      <KM+IM+IT>   ; 65 arm a context hook
dh_tabl dh_VMSetMem        <KM   +IT>   ; 66 commit/decommit memory

dh_tabl dh_OpenEventSem,   <KM      >   ; 67 Open an Event Semaphore
dh_tabl dh_CloseEventSem,  <KM      >   ; 68 Close an Event Semaphore
dh_tabl dh_PostEventSem,   <KM      >   ; 69 Post an Event Semaphore
dh_tabl dh_ResetEventSem,  <KM      >   ; 6A Reset an Event Semaphore
dh_tabl dh_RegisterFreq,   <KM   +IT>   ; 6B Register Freq entry point
dh_tabl dh_DynamicAPI,     <KM   +IT>   ; 6C Add a dynamic API
dh_tabl dh_ProcRun2,      <KM+IM   >    ; 6D Unblock process
dh_tabl dh_CreateInt13VDM  <      IT>   ; 6E Create Int 13 VDM (Internal Only)
dh_tabl dh_RegisterKrnlExit <KM   +IT>  ; 6F Register Kernel Exits F78693
dh_tabl dh_PMPostEventSem, <KM+IM   >   ; 70 Post an Event Semaphore
REPT  (12)                              ; 71-7C used by other OS/2 verions  ;@SEC
dh_tabl dvhe,              <KM+IM+IT>                                     ;@SEC
ENDM                                                                      ;@SEC
dh_tabl dh_KillProc,       <KM      >   ; 7D Kill Proc                    ;@SEC
dh_tabl dh_QSysState,      <KM      >   ; 7E Query System State           ;@SEC

;148753 begin
dh_tabl dh_SYIOpenFile,         <      IT> ;7F sysinit open file
dh_tabl dh_SYICloseFile,        <      IT> ;80 sysinit close file
dh_tabl dh_SYIReadFile,         <      IT> ;81 sysinit read file
dh_tabl dh_SYIReadAtFile,       <      IT> ;82 sysinit read at file (seek)


.errnz (NumFunctions - DevHlp_SYIReadAtFile - 1)
.errnz (NumFunctions - 83h)

;148753 .errnz (NumFunctions - DevHlp_QSysState - 1)                              ;@SEC
;148753 .errnz (NumFunctions - 7Fh)                                               ;@SEC
;148753 end

CONSTANTS       ENDS

IF RAS

        FARCODE HIGH4
RASLOCKCODE SEGMENT

;***    RAStable assigns the following to each DevHelp, in this order:
;       1) Pre-invocation tracepoint routine
;       2) Pre-invocation minor code
;       3) Post-invocation tracepoint routine
;       4) Post-invocation minor code
;
;       See aboisras.asm and rasdevhl.asm for the actual entry points.
;       See RASStubProc in rasdevhl.asm for stubbed-out RAS entry points.

        public  RASDevHlpFuncDisp
RASDevHlpFuncDisp       label   word

RAStable macro  rout,preminor
        EXTRN   RAS_&rout&:near
        EXTRN   RAS_&rout&_post:near
        RASrouter      <offset DOSHIGH4CODE:RAS_&rout,       preminor, \
                        offset DOSHIGH4CODE:RAS_&rout&_post, preminor + 0080H>
        NumRASFunctions = NumRASFunctions + 1
        endm

NumRASFunctions = 0

RAStable SchedAddr,             2CH     ;  0 SchedClock - sched. time base
RAStable DevDone,               0BH     ;  1 Device I/O complete
RAStable Yield,                 45H     ;  2 Yield CPU
RAStable dh_YieldTC,            35H     ;  3 Yield CPU to time critical

RAStable ProcBlock,             09H     ;  4 Block on event
RAStable ProcRun,               2BH     ;  5 Unblock process

RAStable dh_SemRequest,         2FH     ;  6 Claim a semaphore
RAStable dh_SemClear,           2DH     ;  7 Release a semaphore
RAStable dh_SemHandle,          2EH     ;  8 Get a semaphore handle

RAStable PushRequest,           20H     ;  9 Push the request
RAStable PullRequest,           1FH     ;  A Pull next request from Q
RAStable PullParticular,        1EH     ;  B Pull a specific request
RAStable SortRequest,           34H     ;  C Push request in sorted order

RAStable AllocReqPacket,        07H     ;  D allocate a tiled request packet
RAStable FreeReqPacket,         0FH     ;  E free a tiled request packet

RAStable QueueInit,             22H     ;  F Init char queue
RAStable QueueFlush,            21H     ; 10 Clear a char queue
RAStable QueueWrite,            24H     ; 11 Put a char in the queue
RAStable QueueRead,             23H     ; 12 Get a char from the queue

RAStable SegLockDM,             14H     ; 13 Lock memory object
RAStable SegUnlockDM,           37H     ; 14 Unlock memory object

RAStable dh_PhysToVirt,         1BH     ; 15 convert physical to virtual addr
RAStable VirtToPhysDM,          3CH     ; 16 convert virtual to physical addr
RAStable dh_PhysToUVirt,        1AH     ; 17 convert phys to LDT

RAStable AllocPhysDM,           06H     ; 18 allocate physical
RAStable FreePhysDM,            0EH     ; 19 free physical

RAStable dh_SetROMVector,       32H     ; 1A set a ROM service routine vector
RAStable dh_SetIRQ,             31H     ; 1B set an IRQ interrupt
RAStable dh_UnSetIRQ,           39H     ; 1C unset an IRQ interrupt

RAStable dh_SetTimer,           33H     ; 1D set timer request handler
RAStable dh_ResetTimer,         28H     ; 1E unset timer request handler

RAStable dh_MonitorCreate,      16H     ; 1F create monitor
RAStable dh_Register,           26H     ; 20 register monitor
RAStable dh_DeRegister,         0AH     ; 21 de-register monitor
RAStable dh_MonWrite,           18H     ; 22 pass data to monitor
RAStable dh_MonFlush,           17H     ; 23 remove all data from stream

RAStable GetDOSVar,             11H     ; 24 Return pointer to DOS variable
RAStable dh_SendEvent,          30H     ; 25 Event occurred
RAStable dh_ROMCritSection,     2AH     ; 26 ROM Critical Section

RAStable dh_VerifyAccess,       3AH     ; 27 Verify access to memory
RAStable dh_RAS,                04H     ; 28 Put info in RAS trace buffer
RAStable dh_ABIOSGetParms,      03H     ; 29 ABIOS Get Parameters
RAStable dh_AttachDD,           08H     ; 2A Attach to a device driver
RAStable dh_InternalError,      13H     ; 2B Signal an internal error
;RAStable dh_ModifyPriority,   7F2CH    ; 2C Undocumented! (used by PM)  defect 59714
RAStable dh_ModifyPriority,     6CH     ; 2C Undocumented! (used by PM)  defect 59714
RAStable dh_AllocGDTSelector,   05H     ; 2D Allocate GDT Selectors
RAStable dh_PhysToGDTSelector,  19H     ; 2E Convert phys addr to GDT sel
RAStable dh_RealToProt,         25H     ; 2F Change from real to protected mode
RAStable dh_ProtToReal,         1DH     ; 30 Change from protected to real mode

RAStable dh_EOI,                0CH     ; 31 Send EOI to PIC
RAStable dh_UnPhysToVirt,       38H     ; 32 convert physical to virtual addr
RAStable dh_TickCount,          36H     ; 33 modify timer
RAStable dh_GetLIDEntry,        12H     ; 34 Get Logical ID
RAStable dh_FreeLIDEntry,       0DH     ; 35 Release Logical ID
RAStable dh_ABIOSCall,          01H     ; 36 Call ABIOS
RAStable dh_ABIOSCommonEntry,   02H     ; 37 Call ABIOS Common Entry Point
RAStable dh_GetDeviceBlock,     10H     ; 38 Get ABIOS Device Block
RAStable dvh39,                 1CH     ; 39 used for profile DD
RAStable dh_RegisterStackUsage, 27H     ; 3A register for stack usage
RAStable dh_LogEntry,           15H     ; 3B Log Entry

RAStable dh_VideoPause          52H     ; 3C VideoPause                    D607
RAStable Save_Message           50H     ; 3D Display INIT messages
RAStable dh_ReallocSeg          00H     ; 3E Realloc DD protect mode segment
RAStable SortRequest,           34H     ; 3F Sort Requests (internal)
RAStable PullRequest,           1FH     ; 40 Pull Requests (internal)
RAStable dvhe,                  00H     ; 41 AOX BusMaster support (withdrawn)
RAStable dvhe,                  00H     ; 42 AOX BusMaster support (withdrawn)
RAStable dh_RegisterDeviceClass 00h     ; 43 Register Adapter Device Driver
RAStable dvhe,                  00h     ; 44 Security Device Help         ;@SEC

REPT  (050h-NumRASFunctions)            ; 45-4f Pad out unused devhlp numbers
RAStable dvhe,                  00h
ENDM
;
; 32-Bit DevHelps start at 80 (50h)
;
;RAStable dh_RegisterPDD,      7F3CH    ; 50 MVDM PDD registration entry  defect 59714
RAStable dh_RegisterPDD,        7CH     ; 50 MVDM PDD registration entry  defect 59714
;RAStable dh_RegisterBeep,     7F3DH    ; 51 register Beep entry point    defect 59714
RAStable dh_RegisterBeep,       7DH     ; 51 register Beep entry point    defect 59714
;RAStable dh_Beep,             7F3EH    ; 52 device Beep                  defect 59714
RAStable dh_Beep,               7EH     ; 52 device Beep                  defect 59714

RAStable dh_FreeGDTSelector,    49H     ; 53 Free Sel allocated via 2D
RAStable dh_PhysToGDTSel,       51H     ; 54 Phys addr to GDT sel with access
RAStable dh_VMLock,             41H     ; 55 Lock linear addr range
RAStable dh_VMUnlock,           43H     ; 56 Unlock linear addr range
RAStable dh_VMAlloc,            3DH     ; 57 Allocate memory
RAStable dh_VMFree,             3EH     ; 58 Free memory or mapping
RAStable dh_VMProcessToGlobal,  42H     ; 59 Create global mapping to task mem.
RAStable dh_VMGlobalToProcess,  3FH     ; 5A Create task mapping to global mem.
RAStable dh_VirtToLin,          4AH     ; 5B Convert virtual addr. to linear
RAStable dh_LinToGDTSelector,   4BH     ; 5C Convert linear addr. to virtual
RAStable dh_GetDescInfo,        4CH     ; 5D Return descriptor info.
RAStable dh_LinToPageList,      4DH     ; 5E Build PageList array from lin. addr.
RAStable dh_PageListToLin,      4EH     ; 5F Map PageList array to lin. addr.
RAStable dh_PageListToGDTSelector,4FH   ; 60 Map PageList array to GDT sel
;RAStable dh_RegisterTmrDD     7F4DH    ; 61 Reserved for TMR              defect 59714
RAStable dh_RegisterTmrDD       6DH     ; 61 Reserved for TMR              defect 59714
;RAStable dh_RegisterPerfCtrs  7F4EH    ; 62 Register DD Performance Ctrs  defect 59714
RAStable dh_RegisterPerfCtrs    6EH     ; 62 Register DD Performance Ctrs  defect 59714
RAStable dh_AllocateCtxHook     53H     ; 63 Allocate a Context Hook
RAStable dh_AllocateCtxHook     54H     ; 64 Free a Context Hook
RAStable dh_AllocateCtxHook     55H     ; 65 Arm a Context Hook
RAStable dh_VMSetMem            56H     ; 66 Commit/decommit memory

RAStable dh_OpenEventSem        57H     ; 67 Open an Event Semaphore
RAStable dh_CloseEventSem       58H     ; 68 Close an Event Semaphore
RAStable dh_PostEventSem        59H     ; 69 Post an Event Semaphore
RAStable dh_ResetEventSem       5AH     ; 6A Reset an Event Semaphore
RAStable dh_RegisterFreq        5BH     ; 6B register Freq entry point
RAStable dh_DynamicAPI          5CH     ; 6C Reset an Event Semaphore
RAStable ProcRun2,              5DH     ; 6D Unblock process
RAStable dh_CreateInt13VDM      5EH     ; 6E Create Int 13 VDM
RAStable dh_RegisterKrnlExit    5FH     ; 6F Register Kernel Exits F78693
RAStable dvhe,                  00h     ; Pad out Table for function check
REPT  (12)                              ; 6F-7C used by other OS/2 verions
RAStable dvhe,                  00h                                       ;@SEC
ENDM                                                                      ;@SEC
RAStable dh_KillProc            6DH     ; 7D Kill Proc                    ;@SEC
RAStable dh_QSysState           6EH     ; 7E Query Sys State              ;@SEC

;148753 begin
REPT  (4)                               ; 7F-82 jls fs functions add
RAStable dvhe,                  00h
ENDM
;148753 end

.errnz (NumFunctions - NumRASFunctions)

;***    RASPreTraceRouter - Routes to appropriate pre-trace routine
;
;       ENTRY:  (DL) = DevHlp function code
;               (DS) = DosGroup
;
;       EXIT:   NONE
;
;       USES:   NONE


Procedure RASPreTraceRouter,FARONLY
        ASSUME DS:DOSGROUP,ES:NOTHING,SS:NOTHING

        push    ebp
        movzx   ebp,dl                          ; (EBP) = Function number
        lea     ebp,cs:RASDevHlpFuncDisp[ebp*8] ; (EBP) = RAS info packet addr.
        call    cs:[ebp].pretrace_addr
        pop     ebp

        ret
EndProc RASPreTraceRouter


;***    RASPostTraceRouter - Route to proper post trace routine
;
;       ENTRY:  (BP) = DevHlp function code (high byte garbage)
;               (DS) = DosGroup
;
;       EXIT:   NONE
;
;       USES:   Flags.


Procedure RASPostTraceRouter,FARONLY
        ASSUME DS:DOSGROUP,ES:NOTHING,SS:NOTHING

        push    ebp
        and     ebp,0ffh                        ;(EBP) = Function number
        lea     ebp,cs:RASDevHlpFuncDisp[ebp*8] ;(EBP) = RAS info packet addr.
        call    cs:[ebp].posttrace_addr
        pop     ebp

        ret
EndProc RASPostTraceRouter

RASLOCKCODE    ENDS

ENDIF ; RAS


        FARCODE LOW
CODE    SEGMENT

IF RAS

MMPHDevHlpTables                        ; Perf Hook jmp + minor code tables

;***    mmph_PreDevHlp - Performance Pre Hook Routines (6101h-614Ah)
;
;       WARNING: This code is tied to dvh_PreTraceDone in DeviceHelpDM.
;
;       ENTRY:  (DL) = DevHlp function code
;
;       EXIT:   NONE
;
;       USES:   NONE

MMPHPreDevHelp


;***    mmph_PostDevHlp - Performance Post Hook Routines (6181h-61C6h)
;
;       WARNING: This code is tied to dvh_PostTraceDone1 & 2 in DeviceHelpDM.
;
;       ENTRY:  (BP) = DevHlp function code (high byte garbage)
;               (DS) = DosGroup
;
;       EXIT:   NONE
;
;       USES:   NONE

MMPHPostDevHelp


;***    dvh_PreTrace - Pre-invocation RAS trace for DevHlps.
;
;       WARNING: This code is tied to dvh_PreTraceDone in DeviceHelpDM.
;
;       ENTRY:  (DL) = DevHlp function code
;               (DS) = DosGroup
;
;       EXIT:   NONE
;
;       USES:   Flags.

Procedure dvh_PreTrace
        CALLFAR RASPreTraceRouter
        jmp     dvh_PreTraceDone
EndProc dvh_PreTrace


;***    dvh_PostTrace1 - Post-invocation RAS trace for DevHlps.  (#1)
;
;       WARNING: This code is tied to dvh_PostTraceDone1 in DeviceHelpDM.
;
;       ENTRY:  (BP) = DevHlp function code (high byte garbage)
;               (DS) = DosGroup
;
;       EXIT:   NONE
;
;       USES:   Flags.

Procedure dvh_PostTrace1
        CALLFAR RASPostTraceRouter
        jmp     dvh_PostTraceDone1
EndProc dvh_PostTrace1


;***    dvh_PostTrace2 - Post-invocation RAS trace for DevHlps.  (#2)
;
;       WARNING: This code is tied to dvh_PostTraceDone2 in DeviceHelpDM.
;
;       ENTRY:  (BP) = DevHlp function code (high byte garbage)
;               (DS) = DosGroup
;
;       EXIT:   NONE
;
;       USES:   Flags.

Procedure dvh_PostTrace2
        CALLFAR RASPostTraceRouter
        jmp     dvh_PostTraceDone2
EndProc dvh_PostTrace2

ENDIF ; RAS


BREAK   <Dos function dispatch>

;       These two macros (dhPUSH and dhPOP) are here to compute the depth
;       of the DeviceHelp stack frame, specifically the offset from BP to
;       the callers CS:EIP on the stack.  The CS and EIP are used by a
;       number of DevHlp worker routines who need to establish the identity
;       of their callers.

public dhFrameIP
public dhFrameCS
dhFrameIP = 0
dhFrameCS = 2

dhPUSH macro    value
    dhFrameCS = dhFrameCS + 2
    dhFrameIP = dhFrameIP + 2
    irp x,<eax,ebx,ecx,edx,esp,ebp,esi,edi,eflg>  ;82818
        ifidni  <value>,<x>                       ;82818
            dhFrameCS = dhFrameCS + 2             ;82818
            dhFrameIP = dhFrameIP + 2             ;82818
        endif                                     ;82818
    endm                                          ;82818
    ifidni <eflg>,<value>                         ;82818
       pushfd                                     ;82818
    else                                          ;82818
       push value                                 ;82818
    endif                                         ;82818
endm

dhPOP macro     value
    dhFrameCS = dhFrameCS - 2
    dhFrameIP = dhFrameIP - 2
    irp x,<eax,ebx,ecx,edx,esp,ebp,esi,edi,eflg>  ;82818
        ifidni  <value>,<x>                       ;82818
            dhFrameCS = dhFrameCS - 2             ;82818
            dhFrameIP = dhFrameIP - 2             ;82818
        endif                                     ;82818
    endm                                          ;82818
    ifidni <eflg>,<value>                         ;82818
       popfd                                      ;82818
    else                                          ;82818
       pop value                                  ;82818
    endif                                         ;82818
endm

;   ENTRY
;**     DeviceHelpRM - Provide standard services to device drivers.
;**     DeviceHelpDM - Dual mode entry point.
;
;       DeviceHelpRM and DeviceHelpDM are called by device drivers
;       to perform some DOS related function.
;
;       DeviceHelpRM is only entered from dual-mode non-resident device
;       drivers while they are running in real mode.
;
;       DeviceHelpDM is entered from resident device drivers in both
;       real and protected mode.  It is also entered from non-resident
;       device drivers in protected mode, both at initialization time
;       (at ring 3) and later on (at ring 0).  Non-resident device drivers
;       use a call gate selector, allocated and initialized in GDTInitRM,
;       which tiles the DeviceHelpRM (yes, RM) entry point, but dispatches
;       directly to DeviceHelpDM in protected mode.  The tiled call gate
;       remains a call gate forever, but is ring 3 accessible during
;       initialization and ring 0 accessible thereafter.
;
;       The only case where we need to execute the below far jump is
;       in the real mode non-resident case, where we enter the procedure
;       with the wrong CS:IP.  In the protected mode non-resident case,
;       the call gate maps CS:IP to the correct values, and allows us to
;       skip the far jump.  In the dual mode resident case, device drivers
;       are never entered in ring 3, so they can use the correct tiled
;       CS:IP directly.
;
;       ENTRY   (DL) = Function code
;               Other registers as required by specified function
;
;       EXIT    Registers as set by specified function
;
;       USES    Flags changed upon entry to specific FCN
;               upon return to caller, registers (except BP) used
;                   as required by specific functiond
;
        ASSUME  DS:NOTHING, ES:NOTHING, SS:NOTHING

dvhe:   InternalError <DevHlp Usage Error>

IFDEF DEVSTRICT

dvhesel: InternalError <DevHlp corrupted FS or GS>

ENDIF

Procedure DeviceHelpRM,faronly

;       We should do a "jmp far ptr dvh3", but masm "optimizes" it into
;       a near, short jump plus some nops.  We should do a "dd dvh3",
;       but the linker "optimizes" that into a near jump plus some nops.

        db      MI_LONG_JMP
        dw      offset DOSCODE:dvh3, DOSCODE

Entry DeviceHelpDM,faronly
dvh3:
        DBPRT   40h,80h,<DevHlp 40:80 - $b\n>,<dx>
        cmp     dl,NumFunctions         ; legal function?
        jae     short dvhe              ; InternalError if not

;*** 82818 ************************************
ifdef PMDEBUG
        dhPUSH  eax                     ; space for old TCBpDHRetAddr
        dhPUSH  eflg
        dhPUSH  eax

        mov     eax,cr0
        test    eax,CR0_PE
        jz      short dvh1

        dhPUSH  ebx
        dhPUSH  ds

        FlatContext <ds>,ax

        movzx   eax,sp
        add     ax,dhFrameIP
        SSToDS  eax
        mov     ebx,_pTCBCur
        xchg    [ebx].TCBpDHRetAddr,eax
        mov     bx,sp
        mov     dword ptr ss:[bx+14],eax; save old TCBpDHRetAddr

        dhPOP   ds
        dhPOP   ebx
dvh1:
        dhPOP   eax
        dhPOP   eflg
endif
;**** End 82818 **********************

        dhPUSH  ebp                     ; save registers
        dhPUSH  ds
        dhPUSH  edx
        DosContext ds

;*************************************************************************
;*                                                                       *
;* DEVHELP STATISTICS CODE                                               *
;*                                                                       *
;*   This code adds an array of counters that can be viewed with the     *
;* kernel debugger at DHFuncTbl.  These counters record the invocations  *
;* each DevHelp.  The total count of DevHelps is accumulated in the      *
;* 64-bit variable (dhhiinvoks,dhinvoks).   A per-second invocation      *
;* count is stored in lastseccount.                                      *
;*                                     --Rob Rose 03/28/94               *
;* (This is part 2 of a two part #ifdef block)                           *
;*************************************************************************/
IFDEF 0
        push    edx
        movzx   edx,dl
        inc     DHFuncTbl[edx*4]
        pop     edx
        inc     dhinvoks
        adc     dhhiinvoks,0
        push    eax
        mov     eax,ds:SISData.SIS_MsCount
        sub     eax,startcounttik
        cmp     eax,1000
        jl      noupd
        mov     eax,dhinvoks
        mov     lastseccount,eax
        mov     eax,ds:SISData.SIS_MsCount
        mov     startcounttik,eax
        xor     eax,eax
        mov     dhinvoks,eax
        mov     dhhiinvoks,eax
noupd:
        pop     eax
ENDIF

        movzx   edx,dl                  ; edx= index into DevhlpFunc table
        lea     ebp, DevhlpFuncDisp(edx*2)
        add     bp, dx                  ; the devhlp table is 3 bytes wide

IF RAS
;       (DL) = Devhlp Index
        MMPHPreDevHelpTest              ; Performance Hooks (6101h - 614Ah)

        TestTrace RAS_MC_DEVHLP         ; If devhlp major code enabled,
        jnz     dvh_PreTrace            ; jump to dvh_PreTrace, which
dvh_PreTraceDone:                       ; jumps back here when done.
ENDIF ; RAS

dvh4:   cmp     InterruptLevel,-1
        jne     short dvh5              ; jump if interrupt time

        cmp     InDos,0
        je      dvh8                    ; jump if not in kernel mode

;*      We are in kernel mode

        test    byte ptr ds:[bp+2], KM+IT
ifdef PMDEBUG                           ;82818
        jz      dvhe                    ; jump if not allowed in kernel mode
else                                    ;82818
        jz      short dvhe              ; jump if not allowed in kernel mode
endif                                   ;82818
        jmp     short dvh6

;*  We are in interrupt mode

dvh5:   test    byte ptr ds:[bp+2], IM
ifdef PMDEBUG                           ;82818
        jz      dvhe                    ; jmp if interrupt mode not allowed
else                                    ;82818
        jz      short dvhe              ; jmp if interrupt mode not allowed
endif                                   ;82818

;*  We are in kernel mode, or at interrupt time.

dvh6:   mov     bp,ds:[bp]              ; (BP) = address of devhlp routine
        dhPOP   edx                     ; restore EDX
        dhPOP   ds                      ; restore DS
    ASSUME   DS:NOTHING

;       We're in kernel mode or at interrupt time, make the call.
;
;       (BP) = devhlp subroutine from dispatch table
;       Set up BP frame

        dhPUSH  bp
        mov     bp, sp                  ; [bp] = devhlp subroutine

IFDEF DEVSTRICT
        push    dx                      ; save function code
        push    fs                      ; save caller's FS
        push    gs                      ; save caller's GS
ENDIF

        push    dx
        call    [bp]                    ; call devhlp already in kernel mode

        pop     bp                      ; (BP) = function code

IF RAS
;       (BP) = function code
        pushf
        push    ds
        DosContext ds
        MMPHPostDevHelpTest(dvh_PostTraceDone1) ; Perf Hooks (6181h - 61CAh)

        TestTrace RAS_MC_DEVHLP         ; If devhlp major code enabled,
        jnz     dvh_PostTrace1          ; jump to dvh_PostTrace1, which
dvh_PostTraceDone1:                     ; jumps back here when done.
    ASSUME   DS:NOTHING
        pop     ds
        popf
ENDIF ; RAS

IFDEF DEVSTRICT

        pushf
        push    ax                      ; Save AX
        mov     bp,sp
        add     bp,10

;       Stack now looks like this:
;
;       SS:BP   SS:SP+10
;       SS:BP-2 SS:SP+8 function code
;       SS:BP-4 SS:SP+6 original FS
;       SS:BP-6 SS:SP+4 original GS
;               SS:SP+2 flags
;               SS:SP   AX
;
;       Here we verify that FS and GS have not changed
;       (unless function code == DevHlp_FreeGDTSelector)
;
;       We can use ebp since it will be restored immediately.

        mov     ax,fs                   ; (AX) = current FS
        cmp     ax,ss:[bp-4]            ; Does current FS equal original FS?
        je      short dvh7              ;  Yes, check GS

        or      ax,ax                   ; current FS == 0?
        jnz     dvhesel                 ;  No, internal error

        cmp     byte ptr ss:[bp-2],DevHlp_FreeGDTSelector
                                        ; function code == FreeGDTSel?
        jne     dvhesel                 ;  No, internal error

dvh7:   mov     ax,gs                   ; (AX) = current GS
        cmp     ax,ss:[bp-6]            ; Does current GS equal original GS?
        je      short dvh7a             ;  Yes, clean up

        or      ax,ax                   ; GS == 0?
        jne     dvhesel                 ;  No, internal error

        cmp     byte ptr ss:[bp-2],DevHlp_FreeGDTSelector
                                        ; function code == FreeGDTSel?
        jne     dvhesel                 ;  No, internal error

dvh7a:  pop     ax                      ; Restore AX
        popf                            ; Restore flags
        mov     sp,bp                   ; Clean off FS, GS, function code
ENDIF

;       Find the right address for FAR RET and make a near return there
ifdef PMDEBUG                           ;82818
dvh7b:                                  ;82818
endif                                   ;82818
        pop     bp                      ; remove Devhlp worker address
        pop     ebp                     ; restore caller's EBP

;*** 82818  *************************************************
ifdef PMDEBUG
        dhPUSH  eflg
        dhPUSH  eax
        dhPUSH  ebx
        dhPUSH  ds

        mov     bx,sp
        mov     eax,dword ptr ss:[bx+10]; EAX = eflags
        xchg    eax,dword ptr ss:[bx+14]; EAX = old TCBpDHRetAddr

        mov     ebx,cr0
        test    ebx,CR0_PE
        jz      short dvh7c

        FlatContext <ds>,bx

        mov     ebx,_pTCBCur
        mov     [ebx].TCBpDHRetAddr,eax

dvh7c:
        dhPOP   ds
        dhPOP   ebx
        dhPOP   eax
        add     sp,4                    ; remove filler
        dhPOP   eflg
endif
;***** End 82818 *******************************************

        RETF                            ; FAR return with no stack cleanup

;       We're in protected mode and in user context.  This should only happen
;       when initializing resident and installable device drivers.  Set up a bp
;       frame so we can determine the location of the return address for the
;       purpose of initializing the TCB's TCB_CSIP_Ptr.
;
;       (DS:BP) = points to address of devhlp subroutine from dispatch table

dvh8:   test    byte ptr ds:[bp+2], IT
        jz      dvhe                    ; jmp if wrong access

        mov     bp, ds:[bp]             ; (BP) = Address of Devhlp routine
        pop     edx                     ; restore EDX
        pop     ds                      ; restore DS
    ASSUME   DS:NOTHING

        push    bp                      ; set up bp frame
        mov     bp,sp

; Enter kernel mode

        KMEnterKmodeDH                  ; Preserves all registers

IFDEF DEVSTRICT
        push    dx                      ; save function code
        push    fs                      ; save caller's FS
        push    gs                      ; save caller's GS
ENDIF

        push    dx
        call    [bp]                    ; call devhlp after switching to kmode

        pop     bp                      ; bp points to Function code

IF RAS
;       (BP) = function code
        pushf
        push    ds
        DosContext ds
        MMPHPostDevHelpTest(dvh_PostTraceDone2) ; Perf Hooks (6181h - 61CAh)

        TestTrace RAS_MC_DEVHLP         ; If devhlp major code enabled,
        jnz     dvh_PostTrace2          ; jump to dvh_PostTrace2, which
dvh_PostTraceDone2:                     ; jumps back here when done.
    ASSUME   DS:NOTHING
        pop     ds
        popf
ENDIF ; RAS

IFDEF DEVSTRICT

        pushf
        push    ax                      ; Save AX
        mov     bp,sp
        add     bp,10

;       Stack now looks like this:
;
;       SS:BP   SS:SP+10
;       SS:BP-2 SS:SP+8 function code
;       SS:BP-4 SS:SP+6 original FS
;       SS:BP-6 SS:SP+4 original GS
;               SS:SP+2 flags
;               SS:SP   AX
;
;       Here we verify that FS and GS have not changed
;       (unless function code == DevHlp_FreeGDTSelector)
;
;       We can use ebp since it will be restored immediately.

        mov     ax,fs                   ; (AX) = current FS
        cmp     ax,ss:[bp-4]            ; Does current FS equal original FS?
        je      short dvh9              ;  Yes, check GS

        or      ax,ax                   ; current FS == 0?
        jnz     dvhesel                 ;  No, internal error

        cmp     byte ptr ss:[bp-2],DevHlp_FreeGDTSelector
                                        ; function code == FreeGDTSel?
        jne     dvhesel                 ;  No, internal error

dvh9:   mov     ax,gs                   ; (AX) = current GS
        cmp     ax,ss:[bp-6]            ; Does current GS equal original GS?
        je      short dvh9a             ;  Yes, clean up

        or      ax,ax                   ; GS == 0?
        jne     dvhesel                 ;  No, internal error

        cmp     byte ptr ss:[bp-2],DevHlp_FreeGDTSelector
                                        ; function code == FreeGDTSel?
        jne     dvhesel                 ;  No, internal error

dvh9a:  pop     ax                      ; Restore AX
        popf                            ; Restore flags
        mov     sp,bp                   ; Clean off FS, GS, function code
ENDIF

dhKernelExit:
        KMExitKmodeDH

ifdef PMDEBUG                           ;82818
        jmp     dvh7b                   ;82818
else                                    ;82818
        pop     bp                      ; clear worker addr from stack
        pop     ebp                     ; restore caller's ebp
        RETF                            ; return
endif                                   ;82818

EndProc DeviceHelpRM

; 16 bit stubs for the 32 bit interrupt manager routines
; FS and GS must be preserved (DevHelp requirement)

Procedure dh_SetIRQ,near,local
        CALLF32 INTDHSetIRQ,,nocheck
        ret
EndProc   dh_SetIRQ

Procedure dh_UnSetIRQ,near,local
        CALLF32 INTDHUnSetIRQ,,nocheck
        ret
EndProc   dh_UnSetIRQ

Procedure dh_EOI,near,local
        CALLF32 INTDHEOI,,nocheck
        ret
EndProc   dh_EOI

Procedure dh_SetROMVector,near,local
        CALLF32 INTDHSetROMVector,,nocheck
        ret
EndProc   dh_SetROMVector

Procedure dh_RegisterStackUsage,near,local
        CALLF32 INTDHRegisterStackUsage,,nocheck
        ret
EndProc   dh_RegisterStackUsage

Procedure dh_Sec,near,local                                               ;@SEC
        CALLF32 SecDevRoute,,nocheck                                      ;@SEC
        ret                                                               ;@SEC
EndProc   dh_Sec                                                          ;@SEC

ifdef SECURITY
;***LP  dh_KillProc - Kills a specifed process                            ;@SEC
;                                                                         ;@SEC
;       This DevHelp unconditionally kills the specifed process.          ;@SEC
;                                                                         ;@SEC
;       ENTRY   BX - PID to termninate                                    ;@SEC
;                                                                         ;@SEC
;       EXIT    Carry clear if success                                    ;@SEC
;               Carry set if error                                        ;@SEC
;                   (EAX) = Error code                                    ;@SEC
;       USES    EAX, EFlags                                               ;@SEC
;                                                                         ;@SEC
;               FS and GS must be preserved (DevHelp requirement)         ;@SEC
;                                                                         ;@SEC
;       PseudoCode:                                                       ;@SEC
;                                                                         ;@SEC
;       Call w_KillProc                                                   ;@SEC
;       return                                                            ;@SEC
;                                                                         ;@SEC
Procedure dh_KillProc,near                                                ;@SEC
    assume ds:nothing, es:nothing, fs:nothing, gs:nothing, ss:nothing     ;@SEC
                                                                          ;@SEC
        ; Save user registers                                             ;@SEC
        SaveReg <ebx, ecx, edx, esi, edi, ds, es, fs, gs>                 ;@SEC
        NullContext <fs, gs>                                              ;@SEC
                                                                          ;@SEC
        CALLFAR w_KillProc                                                ;@SEC
        movzx eax,ax                                                      ;@SEC
                                                                          ;@SEC
        ; Restore saved registers                                         ;@SEC
        RestoreReg <gs, fs, es, ds, edi, esi, edx, ecx, ebx>              ;@SEC
        ret                                                               ;@SEC
EndProc   dh_KillProc                                                     ;@SEC
                                                                          ;@SEC
                                                                          ;@SEC
;***LP  dh_QSysState - Query System State                                 ;@SEC
;                                                                         ;@SEC
;       dh_QSysState loads system data structure information into a       ;@SEC
;       user supplied buffer based on the list of system entites for      ;@SEC
;       which data is requested.                                          ;@SEC
;                                                                         ;@SEC
;       ENTRY   EAX - elist        Designates what informtion is sought.  ;@SEC
;               EBX - elevel       Designates the level of info sought.   ;@SEC
;               EDI - pid/tid      Process ID; 0 = all processes.         ;@SEC
;                                  Thread ID; 0 = all threads.            ;@SEC
;               ESI - pulStateBuf  Pointer to user buffer                 ;@SEC
;               ECX   cchStateBuf  Size of buffer in bytes                ;@SEC
;                                                                         ;@SEC
;       EXIT    Carry clear if success                                    ;@SEC
;               Carry set if error                                        ;@SEC
;                   (EAX) = Error code                                    ;@SEC
;       USES    EAX, EFlags                                               ;@SEC
;                                                                         ;@SEC
;               FS and GS must be preserved (DevHelp requirement)         ;@SEC
;                                                                         ;@SEC
;       PseudoCode:                                                       ;@SEC
;                                                                         ;@SEC
;       Call QSQuerySysState                                              ;@SEC
;       return                                                            ;@SEC
;                                                                         ;@SEC
Procedure dh_QSysState,near                                               ;@SEC
    assume ds:nothing, es:nothing, fs:nothing, gs:nothing, ss:nothing     ;@SEC
                                                                          ;@SEC
        ; Save user registers                                             ;@SEC
        SaveReg <ebx, ecx, edx, esi, edi, ds, es, fs, gs>                 ;@SEC
        NullContext <fs, gs>                                              ;@SEC
        FlatContext <ds, es>                                              ;@SEC
                                                                          ;@SEC
; ulong_t QSQuerySysState(elist,elevel,pid,tid,pulStateBuf,cchStateBuf)   ;@SEC
                                                                          ;@SEC
        mov     edx,edi                                                   ;@SEC
        shr     edx,16                                                    ;@SEC
        and     edi,0000ffffh                                             ;@SEC
                                                                          ;@SEC
        CCALL32 _QSQuerySysState <eax, ebx, edx, edi, esi,ecx>            ;@SEC
                                                                          ;@SEC
        or      eax, eax                        ; clears carry            ;@SEC
        .errnz  NO_ERROR                                                  ;@SEC
        jz      short qs10                                                ;@SEC
                                                                          ;@SEC
        stc                                                               ;@SEC
                                                                          ;@SEC
        ; Restore saved registers                                         ;@SEC
qs10:   RestoreReg <gs, fs, es, ds, edi, esi, edx, ecx, ebx>              ;@SEC
        ret                                                               ;@SEC
EndProc   dh_QSysState                                                    ;@SEC
else                                                                      ;@SEC
;***LP  dh_KillProc - Kills a specifed process                            ;@SEC
;                                                                         ;@SEC
;       No security installed so this routine does nothing                ;@SEC
;                                                                         ;@SEC
;                                                                         ;@SEC
Procedure dh_KillProc,near                                                ;@SEC
    assume ds:nothing, es:nothing, fs:nothing, gs:nothing, ss:nothing     ;@SEC
                                                                          ;@SEC
        ret                                                               ;@SEC
EndProc   dh_KillProc                                                     ;@SEC
                                                                          ;@SEC
                                                                          ;@SEC
;***LP  dh_QSysState - Query System State                                 ;@SEC
;                                                                         ;@SEC
;       No security installed so this routine does nothing                ;@SEC
;                                                                         ;@SEC
;                                                                         ;@SEC
Procedure dh_QSysState,near                                               ;@SEC
    assume ds:nothing, es:nothing, fs:nothing, gs:nothing, ss:nothing     ;@SEC
                                                                          ;@SEC
        ret                                                               ;@SEC
EndProc   dh_QSysState                                                    ;@SEC
endif

; 148753 begin

;***  dh_SYIOpenFile
; INPUT:
;               es:di -> points to the following structure
;                  es:[di]+0 -> Length of parameter field
;                  es:[di]+2 -> pointer to the ASCIIZ file name
;                  es:[di]+6 -> size of file opened
; Output:
;                  es:[di]+6 -> size of file opened
;

Procedure dh_SYIOpenFile,near,local
   .if < <word ptr es:[di]+0> eq 8 >
     SaveReg <es,di>
     les   di,es:[di]+2         ; get pointer to file name
     call  SYIOpenFile
     RestoreReg <di,es>
     .if nc
       mov ax,NO_ERROR
       mov es:[di]+6,bx         ; save file size being opened
       mov es:[di]+8,ax
     .else
       mov dword ptr es:[di]+6,0        ; on error show no file size
     .endif
   .else
     stc                ; Error Structure size must be correct for expansion
     mov ax,ERROR_BAD_LENGTH
   .endif
   ret
EndProc   dh_SYIOpenFile

;***  dh_SYICloseFile
; Close the file.
;
; NOTES:        The file must first be opened via dh_SYIOpenFile.

; INPUT:
;               None;
; Output:
;               None
;

Procedure dh_SYICloseFile,near,local
   .if < <word ptr es:[di]+0> eq 2 >
     call SYICloseFile
   .else
     stc                ; Error Structure size must be correct for expansion
     mov ax,ERROR_BAD_LENGTH
   .endif
   ret
EndProc   dh_SYICloseFile

;***  dh_SYIReadFile
; INPUT:
;               es:di -> points to the following structure
;                  es:[di]+0 -> file buffer (virtual address)
;                  es:[di]+2 -> number of bytes to read
;                       0 => entire file
;

Procedure dh_SYIReadFile,near,local
   .if < <word ptr es:[di]+0> eq 8 >
     mov   bx,es:[di]+2      ; get virtual file buffer address
     mov   ax,es:[di]+4
     mov   dx,es:[di]+6      ; get number of bytes to read
     mov   cx,es:[di]+8
     call  SYIReadFile       ; ax:bx -> virt addr of buffer below 1MB
   .else
     stc                ; Error Structure size must be correct for expansion
     mov ax,ERROR_BAD_LENGTH
   .endif
   ret
EndProc   dh_SYIReadFile

;***  dh_SYIReadAtFile
; INPUT:
;               es:di -> points to the following structure
;                  es:[di]+0 -> file buffer (virtual address)
;                  es:[di]+2 -> number of bytes to read
;                  es:[di]+4 -> Seek offset
;

Procedure dh_SYIReadAtFile,near,local

   .if < <word ptr es:[di]+0> eq 12 >
     mov   eax,es:[di]+2     ; get virtual file buffer address
     mov   ecx,es:[di]+6     ; get number of bytes to read
     mov   ebx,es:[di]+0Ah   ; get seek offset
     call  syiReadAtFile     ; ax:bx -> virt addr of buffer below 1MB
   .else
     stc                ; Error Structure size must be correct for expansion
     mov ax,ERROR_BAD_LENGTH
   .endif
   ret
EndProc   dh_SYIReadAtFile

; 148753 end

;*  dh_RegisterPDD - Register a PDD with VDM Manager
;
;   dh_RegisterPDD is used by device drivers to regiter their names
;   and a VDD entry point with VDM Manager. Later VDD using VDHOpenPDD
;   opens a communication with PDD.
;
;   ENTRY   es:di  PDD Entry POint for VDD
;           ds:si  PDD Name
;
;   EXIT    None
;
;   CONTEXT Initialization
;

Procedure dh_RegisterPDD,near,local
        SaveReg <ds,es,fs,gs,edi>
        SaveAlignESP
        movzx   edi,di
        PushP   es              ; fpfnPDDProc (16:32 PDD Entry Point)
        PushP   edi             ;     "       (32-bit offset)
        PushP   esi             ; pszName (16:16 PDD Name)
        mov     [esp].Segmt,ds  ;     "        (set selector)
        FlatContext <ds,es>,ax
        NullContext <fs,gs>,ax    ; zero FS and GS in case we block
        CCALL32 _VDMMDHRegisterPDD,,,PushP
        pop     esp
        RestoreReg <edi,gs,fs,es,ds>
        or      eax,eax
        jz      short sout

        Panic <"dh_RegisterPDD: PDD Registration failed">

sout:   ret

EndProc   dh_RegisterPDD

;                                               start of DCR1535 changes
;*  dh_RegisterDeviceClass - Add Device Driver entry to Device Class table
;
;   dh_RegisterDeviceClass is used by a device drivers to register its
;   name and entry point with the kernel. Upper level system managers (DDs
;   communicating with DDs) may obtain a pointer to the kernel table
;   listing currently registered DDs via DevHlp_DOSGetVar.
;
;   ENTRY
;      ds:si   ASCIIZ string (can be name of device, file, etc.)
;      ax:bx   DD's Direct call command handler
;      di      Device Class specific flags
;      cx      Device Class (table number)
;
;   EXIT
;      Carry flag clear if successful
;            AX = Handle
;      Carry flag set if error
;            AX = ERROR_NOT_ENOUGH_MEMORY
;                  if CX out of range
;                  if table is full
;
;
;   CONTEXT All
;

Procedure dh_RegisterDeviceClass,near,local
        SaveReg <es,cx,di,si,dx,bx>
        mov     dx,ax
        SaveAlignESP                    ;trashes ax, must save/restore
        mov     ax,dx

        DosContext ES,dx

        cmp     cx,0                    ;check index, don't want to mess
        jle     rdc_err1                ;up kernel data by writing outside
        cmp     cx,MAXDEVCLASSTABLES    ;of our tables.
        jg      rdc_err1

        push    di                      ; save DC flags
        push    bx                      ; save offset
        xor     ch,ch
        mov     bx,cx
        dec     bx                      ; was 1 based, make it 0 based
        shl     bx,1                    ; convert into word offset
        mov     di,es:DevClassTables[bx];  es:[di] = specific DC table
        pop     bx                      ; restore offset
        pop     cx                      ; restore DC flags (in CX)

        push    di                      ; save offset to specific ADD table

        push    ax
        push    bx
        mov     ax,es:[di].DCCount
        cmp     ax,es:[di].DCMaxCount ;entry available?
        jge     rdc_err2              ;no, error

        lea     di,es:[di].DCTableEntries
        mov     bx, size DevClassTableEntry
        mul     bx
        add     di,ax                  ;es:[di] -> DC Table entry
        pop     bx
        pop     ax
        mov     es:[di].DCSelector,ax ; store selector:offset
        mov     es:[di].DCOffset,bx   ;
        mov     es:[di].DCFlags,cx    ; store ADD flags (popped to CX above)
                                      ;ds:si -> ASCIIZ ADD name
        lea     di,es:[di].DCName     ;es:di -> ADD Table name field
        xor     bx,bx                 ;  (bx will count letters)

rdc_trychar:
        lodsb                          ; copy the character (use lodsb/stosb
        stosb                          ;  so character will be in AL)
        cmp     al,0                   ;found end of string?
        je      rdc_goodret
        inc     bx
        cmp     bx,MAXDEVCLASSNAMELEN  ;string length limit?
        jb      rdc_trychar            ; no, go back and keep copying
        mov     byte ptr es:[di]-1,0   ; yes, zero terminiate string (DI was
                                       ;   inc'ed with stosb, so must -1)
rdc_goodret:
        pop     di                     ;es:[di] = specific ADD table
        mov     ax,es:[di].DCCount
        inc     ax                     ;AX=handle (ADDCount+1)
        mov     es:[di].DCCount,ax    ;setup ADDCount for next time through
        clc
        jmp     rdc_x

rdc_err2:
        pop     bx
        pop     ax
        pop     di
rdc_err1:
        mov     ax,ERROR_NOT_ENOUGH_MEMORY
        stc

rdc_x:
        pop     esp
        RestoreReg <bx,dx,si,di,cx,es>
        ret

EndProc   dh_RegisterDeviceClass

;
;*  dh_RegisterKrnlExit -                                     F78693
;                                                             F78693
;   Entry:                                                    F78693
;       AX= flags                                             F78693
;               del_Kernel_exit    0x0000                     F78693
;               add_Kernel_exit    0x1000                     F78693
;               query_Kernel_exit  0x2000                     F78693
;                                                             F78693
;       CX= exit type to register for                         F78693
;               NMI_exit           0x0000                     F78693
;               SFF_exit           0x0001                     F78693
;                                                             F78693
;       BX= Selector of exit routine                          F78693
;                                                             F78693
;       SI= Offset   of exit routine                          F78693
;                                                             F78693
;       DS= Data Segment of exit routine                      F78693
;                                                             F78693
;   Exit:                                                     F78693
;      EAX= return code (set by  dhw_32KrnlExit)              F78693
;                                                             F78693

Procedure dh_RegisterKrnlExit,near,local

        SaveReg <es,ds,di,dx>

 ; zero out high order bits                                               F78693

        shl      eax,16               ; Flags                             F78693

        movzx    ecx,cx               ; Exit Type user is registering for F78693

        shl      ebx,16               ; Selector to high order bits       F78693
        mov      bx,si                ; Offset   of user exit             F78693

        xor      edx,edx              ; zero out register for DS          F78693
        push     ds                   ; Data Segement for Exit Routine    F78693
        pop      dx                   ; put in  DX register               F78693

        FlatContext <ds, es>                                        ;F78693
        CCALL32  _dhw_32KrnlExit <ebx, edx, ecx, eax>               ;F78693

        RestoreReg <dx,di,ds,es>                                    ;F78693

        ret                                                         ;F78693

EndProc   dh_RegisterKrnlExit                                       ;F78693

;*  dh_CreateInt13VDM - Create Int 13 VDM thread
;
;   dh_CreateInt13VDM is an internal only DevHlp.
;
;   This devhlp is used by the Generic Int13 ADD to create
;   a VDM Task which is used to run BIOS Int 13 requests
;
;   The DiskDD passes a 16:16 address of a communication
;   communication area in ES:BX.
;
;
;   ENTRY
;
;         AX:SI - VDM <> Int13 ADD Communication Area (See VDMINT13.H)
;
;
;   EXIT    None
;
;   CONTEXT All
;

Procedure dh_CreateInt13VDM,near,local

        LocalVar ResultCode, DWORD

        EnterProc

        movzx   eax, ax
        movzx   esi, si

        SaveReg <ds,es>

        FlatContext <ds, es>, dx
        CCALL32 _SELVirtToLin <esi, eax>
        cmp     eax,-1
        jz      short cint1300

        mov     _pVDMInt13, eax
;
;       Try to start-up VDM
;
        lea     eax, ResultCode
        SSToDS  eax
        CCALL32 _TKCreateVDMProcess,<<offset FLAT:_VDMInt13CreateMiniVDM>,0,eax>

cint1300:
        RestoreReg  <es,ds>
        ExitProc

EndProc   dh_CreateInt13VDM
;                                               end of DCR1535 changes

;*   dh_AbiosStub - stub routine for abios devhlps on non-abios machines
;
;    _DevHlpDisableAccess will replace the addresses of the Abios DevHlp
;    routines with this routine, when OS/2 is running on non-Abios machine
;
;    Entry   none
;
;    Exit    ax = ERROR_ABIOS_NOT_PRESENT
;
;    Context all
;

Procedure dh_AbiosStub, near, local
        mov         ax, ERROR_ABIOS_NOT_PRESENT
        stc
        ret
EndProc   dh_AbiosStub

CODE    ENDS

        FARCODE HIGH32
CINIT_TEXT segment

;***    _DevhlpDisableAccess - Disable access to init time DevHelp routines
;
;       _DevhlpDisableAccess disables access to Init Time only DevHlp
;       routines by storing the Internal Error's address for Devhlp usage
;       error in the Devhlp table.
;
;       ENTRY   NONE
;       EXIT    NONE
;       USES    EAX, ECX, EDX, EFlags

Procedure _DevhlpDisableAccess,far32
        assume ds:nothing, es:nothing, fs:nothing, gs:nothing, ss:nothing

        ; Save registers that will be used

        push    ds
        push    es

        mov     ax, DOSCODE
        mov     ds, ax
        mov     dx, offset ds:dvhe          ; Offset of Devhlp usage error
        mov     bx, offset ds:dh_AbiosStub  ; offset of ABios stub routine
        DosContext ds, ax
        mov     eax, offset ds:DevhlpFuncDisp
        mov     ecx, NumFunctions

dda20:  cmp     byte ptr [eax+2], IT        ; Init time only?
        jz      short  dda25                ; jmp if so

        cmp     byte ptr [eax+2], IT+AB     ; Init time only Abios?
        jnz     dda30                       ; jmp is not

dda25:  mov     [eax], dx                   ; replace with Internal Error
        jmp     dda40

dda30:  test    ABIOS_present,-1            ; abios machine?
        jnz     dda40

        test    byte ptr [eax+2], AB        ; abios only?
        jz      short dda40

        mov     [eax], bx                   ; replace with stub routine
dda40:  add     eax, dh_tablsize            ; size of dh_tabl
        loop    dda20

        ; Now disable user level access for the Init time allocated DevHelp
        ; memory

        FlatContext <ds, es>, cx
        CCALL32     _VMDH_AllocRemoveAccess

        pop     es
        pop     ds
        RETC
EndProc _DevhlpDisableAccess

CINIT_TEXT ends

        END
