home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / dyndd.zip / dyndd.asm next >
Assembly Source File  |  1997-12-01  |  19KB  |  527 lines

  1. ; Dynamic Trace Exit - sample device driver           
  2. ; Author: Richard Moore
  3. ; Date:    1st December 1997
  4. ; Version: 1.0
  5. ;
  6. ; This device drive implements a number of functions that are 
  7. ; invoked using RPN commands as follows:
  8. ;
  9. ;
  10. ;   push parm1
  11. ;   ....
  12. ;   push parmn
  13. ;   push function
  14. ;   call dd
  15. ;
  16. ; The functions implemented are:
  17. ;
  18. ; 0 - log the buffer contents and reset the buffer
  19. ; 1 - compare two ASCIIZ strings from flat addresses
  20. ;     The addresses are popped from the RPN stack and
  21. ;     the result of the compare is pushed. If the
  22. ;     addresses are equal then the result is 0, if not
  23. ;     then the result is -1. If an exception occurs then
  24. ;     a error message is logged and no result is pushed.
  25. ; 2 - compare two ASCIIZ strings from segmented addresses.
  26. ;     An offset, then segment of the first comparand is 
  27. ;     popped from the RPN stack, followed by the offset
  28. ;     and segment of the 2nd comparand. This functions 
  29. ;     then proceeds as for function 1.
  30. ; 3/4 Test device driver fault handler behaviour.
  31. ; 5 - Get a DWORD global variable. An index (0-15) is popped
  32. ;     from the RPN stack and the value of the corresponding
  33. ;     global variable is pushed onto the stack.
  34. ; 6 - Put a DWORD value into a global variable. An index (0-15) is 
  35. ;     popped followed by the variable value.
  36. ;     The corresponding global variable is updated.
  37. ;     Global variable may be shared across dynamic trace objects,
  38. ;     unlike local variables, which are local to a DTO.
  39. ;
  40. ; 7 - log the buffer contents skipping the initial 3-byte prefix 
  41. ;     and reset the buffer. If the buffer contains less than 3 bytes
  42. ;     then a null record is logged.
  43. ;
  44. ;     See DYNDD.RPN for example of these functions being used.
  45. ;
  46. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  47.  
  48.         PAGE    255,133
  49.         .386p   
  50.         .SALL
  51. include devhlp.inc
  52. include dynapi.inc
  53. include basemaca.inc
  54.         PUBLIC  Strat,DynExit,DynFault
  55. ; RPN stack manipulation macros
  56.  
  57. ; RPNPush - increment top of RPN stack pointer.
  58. ;
  59. ;    RPNPush increments the top of stack pointer held in EDX.
  60. ;    No data transfer to the RPN stack occurs.
  61.  
  62. RPNPush macro
  63.     inc    edx
  64.     and    edx,15    ; assumes RPN stack size is 16 DWORDS
  65. endm
  66.  
  67.  
  68. ; RPNPop - decrement top of RPN stack pointer.
  69. ;
  70. ;    RPNPop decrement the top of stack pointer held in EDX.
  71. ;    No data transfer to the RPN stack occurs.
  72.  
  73. RPNPop    macro
  74.     dec    edx
  75.     and    edx,15    ; assumes RPN stack size is 16 DWORDS 
  76. endm
  77.  
  78.  
  79. ; RPNGetTOS - Move top element of RPN stack to a register
  80. ;
  81. ;    RPNGetTOS <reg>
  82. ;
  83. ;    RPNGetTOS moves the top element of the RPN stack into a register.
  84. ;    No motion of the RPN stack occurs.
  85.  
  86. RPNGetTOS macro reg
  87.    mov   reg,edx
  88.    shl   reg,2
  89.    add   reg,esi
  90.    mov    reg,es:[reg]
  91. endm
  92.  
  93.  
  94. ; RPNPutTOS - Move register to top element of RPN stack 
  95. ;
  96. ;    RPNPutTOS <reg>
  97. ;
  98. ;    RPNPutTOS moves a register to the top element of the RPN stack.
  99. ;    No motion of the RPN stack occurs.
  100.  
  101. RPNPutTOS macro reg
  102.    push  reg
  103.    mov   reg,edx
  104.    shl   reg,2
  105.    add   reg,esi
  106.     pop   DWORD PTR es:[reg]
  107.    mov   reg,es:[reg]
  108. endm
  109.  
  110.  
  111. ;   Standard Request Packet Header definition
  112. RP              equ     es:[bx]                 ;use mnemonic
  113. RPP             equ     [bp-4]                  ;saved address of RP
  114. RP_COMMAND      equ     byte ptr es:[bx+2]      ;location of command byte
  115. RPCmdInit       equ     0                       ;Initialize
  116. RPInitDevHlp    equ    dword ptr es:[bx+14]     ;Offset&Segment of DevHlp
  117. RPInitEndCode   equ     word ptr es:[bx+14]     ;end of code segment
  118. RPInitEndData   equ     word ptr es:[bx+16]     ;end of data segment
  119. RPInitParmPtr   equ    dword ptr es:[bx+18]     ;address of parameters
  120. RPCmdRead       equ     4                       ;device read 
  121. RPCmdWrite      equ     8                       ;device write
  122. RPCmdWriteV     equ     9                       ;device write with verify
  123. RPRWPhysAdrL    equ     word ptr es:[bx+14]     ;low half of phys addr
  124. RPRWPhysAdrH    equ     word ptr es:[bx+16]     ;high half of phys addr
  125. RPRWLen         equ     word ptr es:[bx+18]     ;length of read/write
  126. RPCmdOpen       equ     13                      ;device open
  127. RPCmdClose      equ     14                      ;device close
  128. RP_STATUS       equ     word ptr es:[bx+3]
  129. DONEAOK         equ     0100H
  130. DONENOK         equ     8100H           ;use one of the below with DONENOK 
  131. CMDBAD          equ     3
  132. GENFAIL         equ     12
  133. INVPARM         equ     19
  134. DEVBUSY         equ     20
  135. ;
  136. ;**     Device Driver Type definitions 
  137. Dev_Char_Dev    equ 1000000000000000B ;Device is a character device
  138. Dev_30          equ 0000100000000000B ;Accepts Open/Close/Rem. Media
  139. DevLev_1        equ 0000000110000000B ;OS/2 Device Driver+bitstrip
  140. DDattr          equ Dev_Char_Dev+Dev_30+DevLev_1
  141. ;
  142.         PUBLIC DevHdr
  143.         PUBLIC DevHlp
  144.         PUBLIC Iflag 
  145.         PUBLIC trbuffer
  146.         PUBLIC dynreq
  147.         PUBLIC fltmsg
  148.         PUBLIC FlatSel
  149.         PUBLIC dynddx
  150.         PUBLIC EntrySP
  151.         PUBLIC sel1
  152.         PUBLIC sel2
  153.         PUBLIC off1
  154.         PUBLIC off2
  155.         PUBLIC GlobalV
  156. _DATA   segment para public use16 'DATA'
  157. DevHdr  dd      -1              ;+00  chain pointer
  158.         dw      DDattr          ;+04  device attributes  
  159.         dw      Strat           ;+06  strategy routine
  160.         dw      0               ;+08  inter dd comm entry
  161.         db      'DYNDD   '      ;+0A  device name
  162.         db      8 dup (0)       ;+12  reserved
  163.         dd      00000001H       ;+1A  capability bitstrip, >16Mb support
  164. DevHlp  dd      0               ;+1C  address of device help entry point
  165. Iflag   db      0               ;+20  operational flags
  166. Inited  =       128
  167. trbuffer db     'DynExit - invalid request'   ;Static trace buffer
  168.         db      0
  169. dynreq  dd      0
  170. trsize  equ     $-trbuffer
  171. fltmsg   db     'DynExit - encountered a GP Fault'
  172.         db      0
  173. fltsize equ     $-fltmsg
  174. FlatSel dw      0
  175. dynddx  dd      0
  176. ;
  177. EntrySP dw      0               ; Entry SP 
  178. off1    dw      ?
  179. sel1    dw      ?
  180. off2    dw      ?
  181. sel2    dw      ?
  182. ;
  183. GlobalV dd      16 dup(0)       ; array of 16 global variables
  184. ;
  185. DATASIZ equ     $-Devhdr        ;size of resident data
  186. _DATA   ends
  187. ;
  188. _TEXT   segment para public use16 'CODE'
  189. CSBeg   equ     $
  190.         assume  CS:_TEXT, DS:_DATA
  191.  
  192. ; Dynamic Trace exit routine
  193. DynExit proc far
  194.         push ds               ; save the flat data sel
  195.         mov  ds,ax            ; restore the data segment
  196.         pop  [FlatSel]
  197.         mov  [EntrySP],sp             ; save entry sp for use by the fault handler
  198.         mov  WORD PTR [dynddx],di     ; save ddx address for realoding after a fault
  199.         mov  WORD PTR [dynddx+2],fs
  200.         mov  edx,fs:[di].ddx_StackIndex
  201.         xor  esi,esi
  202.         les  si,fs:[di].ddx_StackStart
  203.         RPNGetTOS eax         ; get function request from TOS
  204.         RPNPop                         ; Pop the function code from TOS
  205.         cmp  eax,0            ; log buffer function?
  206.         jz   LogBuffer
  207.         cmp  eax,1            ; Compare strings from Flat addresses
  208.         jz   CompStrF
  209.         cmp  eax,2            ; Compare strings from Segmented addresses
  210.         jz   CompStrS
  211.         cmp  eax,3            ; Test fault handler
  212.         jz   TestFault
  213.         cmp  eax,4            ; Test fault without a local handler
  214.         jz   TestFaultNH
  215.         cmp  eax,5            ; Get Global Var
  216.         jz   GetGlobalVar
  217.         cmp  eax,6            ; Put Global Var
  218.         jz   PutGlobalVar
  219.         cmp  eax,7            ; log buffer without prefix function?
  220.         jz   LogBufferNP
  221.         RPNPush               ; Restore the stack pointer - we don't regognise
  222.                               ; the request, it could be for another exit
  223.  
  224. ; write out an error message via a static trace record
  225.         mov  [dynreq],eax     ; log the function
  226.         mov  eax,fs:[di].ddx_Major     ; original major code
  227.         mov  ecx,fs:[di].ddx_Minor     ; original minor code
  228.         mov  bx,trsize        ; size of trace data
  229.         mov  si,Offset trbuffer      ; ds:si->trbuffer
  230.         mov  dl,DevHlp_RAS    ; SysTrace DevHlp
  231.         call    [DevHlp]      ; call SysTrace
  232.         jmp  DynEnd
  233.  
  234.  
  235. ; log out the existing buffer using static trace and reset the log buffer
  236.         PUBLIC LogBuffer
  237. LogBuffer:
  238.         mov  eax,fs:[di].ddx_Major     ; original major code
  239.         mov  ebx,fs:[di].ddx_LogIndex  ; size of log data
  240.         mov  ecx,fs:[di].ddx_Minor     ; original minor code
  241.         push ds                        ; save ds
  242.         pop  es                        ; as es
  243.         push si                        ; save si
  244.         lds  si,fs:[di].ddx_LogStart   ; ds:si->log buffer
  245.         mov  dl,DevHlp_RAS             ; SysTrace DevHlp
  246.         call es:[DevHlp]               ; write out the log
  247.         pop  si                        ; restore our si
  248.         push es
  249.         pop  ds                        ; restore our ds
  250.         xor  eax,eax
  251.         mov  fs:[di].ddx_LogIndex,eax  ; reset log index
  252.         jmp  DynEnd
  253.  
  254. ; log out the existing buffer without the initial prefix using static trace 
  255. ; and reset the log buffer
  256.         PUBLIC LogBufferNP
  257. LogBufferNP:
  258.         mov  eax,fs:[di].ddx_Major     ; original major code
  259.         mov  ebx,fs:[di].ddx_LogIndex  ; size of log data
  260.         mov  ecx,fs:[di].ddx_Minor     ; original minor code
  261.         push ds                        ; save ds
  262.         pop  es                        ; as es
  263.         push si                        ; save si
  264.         lds  si,fs:[di].ddx_LogStart   ; ds:si->log buffer
  265.         add  si,3                      ; bypass prefix
  266.         or   bx,bx                     ; if 0, 1 or 2 bytes in log then
  267.         jz   @F                        ; leave length zero
  268.         dec  bx                        ; (don't bother adjusting si - it's not used).
  269.         jz   @F                        ;
  270.         dec  bx                        ;
  271.         jz   @F                        ;
  272.         dec  bx                        ;
  273. @@:     mov  dl,DevHlp_RAS             ; SysTrace DevHlp
  274.         call es:[DevHlp]               ; write out the log
  275.         pop  si                        ; restore our si
  276.         push es
  277.         pop  ds                        ; restore our ds
  278.         xor  eax,eax
  279.         mov  fs:[di].ddx_LogIndex,eax  ; reset log index
  280.         jmp  DynEnd
  281.  
  282. ; Compare two zero terminated strings pointed to by the flat address on the RPN stack
  283. ; push 0 if equal, -1 if not
  284.         PUBLIC CompStrF
  285. CompStrF:  
  286.         RPNGetTOS eax                  ; get addess of 1st string address
  287.         RPNPop
  288.         RPNGetTOS ebx                  ; get addess of 2st string address
  289.                                        ; don't pop here - we'll replace TOS
  290.                                        ; with the result
  291.  
  292.         push cs                        ; set up a fault handler 
  293.         pop  cx
  294.         shl  cx,16
  295.         mov  cx,offset DynFault        
  296.         mov  fs:[di].ddx_pfnFault,ecx
  297. ; note use fs instead of ds in string instructions - this makes fault recovery
  298. ; easier. The system will pass the fault handler the value of ds in use at the
  299. ; time the trap occurred in ax. If we re-use ds - life gets difficult.
  300.         SaveReg    <edi,esi,es,fs>
  301.         mov  fs,[FlatSel]
  302.         push fs
  303.         pop  es
  304.         mov  esi,eax
  305.         mov  edi,ebx
  306.         xor  eax,eax
  307. CFloop: cmp  BYTE PTR fs:[esi],0
  308.         jne  CF1
  309.         cmp  BYTE PTR es:[edi],0
  310.         je   CFeq
  311.         jmp  CF2    
  312. CF1:    cmp  BYTE PTR es:[edi],0
  313.         jne  CF2     
  314.         je   CFne
  315.  
  316. CF2:    cmps  BYTE PTR fs:[esi], BYTE PTR es:[edi]
  317.         jnz   CFne
  318.         jmp   CFloop
  319.  
  320.  
  321. CFeq:
  322.         RestoreReg <fs,es,esi,edi>
  323.         RPNPutTOS <eax>
  324.         jmp  DynEnd
  325.  
  326. CFne:
  327.         RestoreReg <fs,es,esi,edi>
  328.         dec  eax
  329.         RPNPutTOS <eax>
  330.         jmp  DynEnd
  331.  
  332. ; Compare two zero terminated strings pointed to by 16:16 addresses on the RPN stack
  333. ; push 0 if equal, -1 if not
  334.         PUBLIC CompStrS
  335. CompStrS:  
  336.         push cs                        ; set up a fault handler 
  337.         pop  cx
  338.         shl  cx,16
  339.         mov  cx,offset DynFault        
  340.         mov  fs:[di].ddx_pfnFault,ecx
  341.         RPNGetTOS eax                  ; get offset of  1st string
  342.         RPNPop
  343.         mov  ds:[off1],ax 
  344.         RPNGetTOS eax                  ; get segment of 1st string 
  345.         RPNPop
  346.         mov  ds:[sel1],ax 
  347.         RPNGetTOS eax                  ; get offset of 2st string 
  348.         RPNPop
  349.         mov  ds:[off2],ax 
  350.         RPNGetTOS eax                  ; get segment of 2st string 
  351.                                        ; don't pop here - we'll replace TOS
  352.                                        ; with the result
  353.         mov  ds:[sel2],ax 
  354.  
  355. ; note use fs instead of ds in string instructions - this makes fault recovery
  356. ; easier. The system will pass the fault handler the value of ds in use at the
  357. ; time the trap occurred in ax. If we re-use ds - life gets difficult.
  358.         SaveReg    <di,si,es,fs>
  359.         mov  di,ds:[off2]
  360.         push ds:[sel2]
  361.         pop  es
  362.         mov  si,ds:[off1]
  363.         push ds:[sel1]
  364.         pop  fs
  365.         xor  eax,eax
  366. CSloop: cmp  BYTE PTR fs:[si],0
  367.         jne  CS1
  368.         cmp  BYTE PTR es:[di],0
  369.         je   CSeq
  370.         jmp  CS2    
  371. CS1:    cmp  BYTE PTR es:[di],0
  372.         jne  CS2     
  373.         je   CSne
  374.  
  375. CS2:    cmps  BYTE PTR fs:[si], BYTE PTR es:[di]
  376.         jnz   CSne
  377.         jmp   CSloop
  378.  
  379.  
  380. CSeq:
  381.         RestoreReg <fs,es,si,di>
  382.         RPNPutTOS <eax>
  383.         jmp  DynEnd
  384.  
  385. CSne:
  386.         RestoreReg <fs,es,si,di>
  387.         dec  eax
  388.         RPNPutTOS <eax>
  389.         jmp  DynEnd
  390.  
  391. ;Test Fault handling - register a fault handler and cause a fault
  392.         PUBLIC TestFault
  393. TestFault:
  394.         push cs                        ; set up a fault handler 
  395.         pop  cx
  396.         shl  cx,16
  397.         mov  cx,offset DynFault        
  398.         mov  fs:[di].ddx_pfnFault,ecx
  399.         mov  ax,fs:[0ffffh]            ; cause a fault
  400.         int  2                         ; should not execute
  401.  
  402. ;Test Fault handling - no fault handler registered 
  403.         PUBLIC TestFaultNH
  404. TestFaultNH:
  405.         mov  ax,fs:[0ffffh]            ; cause a fault
  406.         int  2                         ; should not execute
  407.  
  408. ;Get a Global Variable 
  409. ;Pop GVAR index from TOS adjust modulo 16, index GlobalV, Push DWORD
  410.         PUBLIC GetGlobalVar
  411. GetGlobalVar:
  412.         RPNGetTOS ebx
  413.         and  ebx,15
  414.         mov  eax,[GlobalV].[ebx*4]
  415.         RPNPutTOS eax
  416.         jmp  DynEnd                    
  417.  
  418. ;Put a Global Variable 
  419. ;Pop a GVAR value then a GVAR index from TOS adjust modulo 16, store value in GVAR
  420.         PUBLIC PutGlobalVar
  421. PutGlobalVar:
  422.         RPNGetTOS eax
  423.         RPNPop        
  424.         RPNGetTOS ebx
  425.         and  ebx,15
  426.         mov  [GlobalV].[ebx*4],eax
  427. ;fall through to DynEnd
  428. ;       jmp  DynEnd                        
  429.  
  430.  
  431. DynEnd: xor  ax,ax                         ; allow other registered dyn exits to be called
  432.         mov  fs:[di].ddx_StackIndex,edx    ; reset the RPN TOS   
  433.         mov  fs:[di].ddx_pfnFault,eax      ; cancel fault handler
  434.         push ds:[FlatSel]
  435.         pop  ds                            ; restore ds
  436.         retf
  437. DynExit endp
  438.  
  439. DynFault proc far
  440.           push ds               ; save system's ds
  441.           mov  ds,ax            ; restore our data segment
  442.           assume ds:_DATA
  443.           lfs  di,dynddx        ; reload the ddx ptr
  444. ; write out an error message via a static trace record
  445.           mov  eax,fs:[di].ddx_Major     ; original major code
  446.           mov  ecx,fs:[di].ddx_Minor     ; original minor code
  447.           mov  bx,fltsize       ; size of trace data
  448.           mov  si,Offset fltmsg ; ds:si->fltmsg
  449.           mov  dl,DevHlp_RAS    ; SysTrace DevHlp
  450.           call    [DevHlp]      ; call SysTrace
  451.           mov  ax,[EntrySP]     ; prepare to restore stack
  452.           pop  ds               ; restore system's ds
  453.           mov  sp,ax            ; Stack now as on entry
  454.           retf               
  455. DynFault  endp
  456.  
  457. ;Device Driver strategy entry point. Request Packet is at es:[bx]
  458. Strat   proc    far
  459. ;       int 3
  460.         push    bp                      ;standard
  461.         mov     bp,sp                   ;linkage
  462.         SaveReg <es,bx,cx,dx,si,di>     ;save es,bx,cx,dx,si,di
  463.         pushf                           ;save flags @ [bp-e] 
  464.         cld                             ;insure up for string ops
  465.         mov     al,RP_COMMAND           ;get command
  466.         cmp     al,RPCmdInit            ;is it Init?
  467.         jne     short DoneOK            ;no, go get PID
  468.         test    Iflag,Inited            ;already initialized?
  469.         jz      Init                    ;no, go initialize
  470.         jmp     short DoneOK            ;yes, do not initialize twice
  471.  
  472. BadCmd: mov     ax,DONENOK+CMDBAD       ;bad command
  473.         jmp     short Done              ;exit
  474.  
  475. GenErr: mov     ax,DONENOK+GENFAIL      ;general failure
  476.         jmp     short Done              ;exit
  477.  
  478. InUse:  mov     ax,DONENOK+DEVBUSY      ;device in use
  479.         jmp      short Done             ;exit
  480.  
  481. InvPrm: mov     ax,DONENOK+INVPARM      ;invalid parm
  482.         jmp     short Done              ;exit
  483.  
  484. DoneOK: mov     ax,DONEAOK              ;result status
  485. ;       jmp     short Done              ;exit
  486.  
  487. Done:   popf                            ;restore flags
  488.         RestoreReg <di,si,dx,cx,bx,es>  ;restore di,si,dx,cx,bx,es
  489.         mov     RP_STATUS,ax            ;set request packet status
  490.         pop     bp                      ;restore bp
  491. ;       int     3
  492.         ret                             ;back to caller
  493.  
  494. CODESIZ equ     $-CSBeg
  495. ;end of resident code
  496. ;
  497. ;init    runs at pl=3, discarded after use.
  498.  
  499. InitOK: les     bx,RPP                  ;refresh RP pointer
  500.         mov     RPInitParmPtr,0         ;set to zero
  501.         or      Iflag,Inited            ;set initialized flag
  502.         jmp     DoneOK                  ;Initialize complete
  503. InitNo: les     bx,RPP                  ;refresh RP address
  504.         mov     RPInitEndCode,0         ;no code
  505.         mov     RPInitEndData,0         ;no data
  506.         mov     RPInitParmPtr,0         ;set to zero
  507.         jmp     GenErr                  ;decline installation
  508. Init:   mov     eax,RPInitDevHlp        ;get DevHlp offset:segment
  509.         mov     DevHlp,eax              ;save it
  510.         mov     RPInitEndData,DATASIZ   ;set resident data size
  511.         mov     RPInitEndCode,CODESIZ   ;set resident code size
  512. ; now register for Dynamic Trace
  513.         mov     bx,cs                   ; same CS
  514.         and     bl,0f8h                 ; make sure will be CPL=0
  515.         mov     esi,OFFSET _TEXT:DynExit  ; offset myapi
  516.         mov     ax,1000h                ; add exit
  517.         mov     cx,3                    ; DYN_Exit
  518.         mov     dl,DevHlp_RegisterKrnlExit ; register exit
  519. ;       int 3
  520.         call    [DevHlp]                ; do it.
  521. ;       int 3
  522.         jmp     InitOK
  523. Strat   endp
  524. _TEXT   ends
  525.         end     Strat
  526.