;       SCCSID = @(#)rasstru.asm	6.1 90/11/17
;      SCCSID = @(#)rasstru.asm	6.7 90/09/17
; ****************************************************************************
; *									     *
; *			  IBM/Microsoft Confidential			     *
; *									     *
; *		    Copyright (c) IBM Corporation  1987, 1990		     *
; *		    Copyright (c) Microsoft Corp.  1987, 1990		     *
; *			      All Rights Reserved			     *
; *									     *
; ****************************************************************************
	PAGE	,132  ; (CTRL-OH)   IBM PC PRINTER CONDENSED MODE
;************************* START OF SPECIFICATIONS *****************
;
;     SOURCE FILE NAME:	 RASSTRU.ASM
;
;     DESCRIPTIVE NAME:	 System Trace Resident Update Program
;			 System Trace Control Program
;			 Worker routines for STRUCHECK,
;			 STRURESUPDATE, DosSetTraceInfo and DosGetSTDA
;
;     STATUS:  N/A
;
;     FUNCTION:
;		w_StruCheck:  Determine Type of static tracing occuring
;
;	    w_StruResUpdate:  Update major and minor code tables
;
;	     w_SetTraceInfo:  Control various aspects of system tracing
;
;		  w_GetSTDA:  Get a copy of the system trace buffer
;     CHANGES:
;       96020 - 11/30/94 - Add time and date to STDA structure.  Start time
;       and date are set in ClearRasTrace, because it's an obvious restart of
;       tracing.  End time and date are set in PIDTraceOffAll, SuspendRasTrace
;       and IncErrorCount when err count is reached, because tracing may never
;       be resumed again.  Start time and date NOT changed in ResumeRasTrace or
;       PIDTraceOn because then we'd lose the original start time and date.
;       Multiple suspend/resumes will change the ending time and date each time.
;       Created SetEndTimeStamp procedure to set it in the 4 instances. - 96020
;************************** END OF SPECIFICATIONS ******************
;
;
.sall
	.XLIST
include dosseg.inc			 ; MUST be first include
include osconst.inc
include basemaca.inc
include osmaca.inc
include mi.inc
include proc.inc
include error.inc
include error2.inc
include struc.inc
include pmode.inc
include infoseg.inc
include mhandle.inc
include rasmacro.inc			 ; ras_mec_table addressibility
include systrace.inc
include perfhook.inc
include pgexport.inc
include vmexport.inc
include tkexport.inc
	.LIST
	CpuMode 286


if RAS
ReferGlobal ras_stda_addr,WORD		 ; selector for system trace buffer
ReferGlobal ras_systr_flags,BYTE	 ; System Trace Flags
ReferGlobal TraceValue,BYTE		 ; Value allowed in trace value
ReferGlobal _Sis2,BYTE			 ; system infoseg copy data
ReferTask   ptda_rasflag,BYTE		 ; ptda trace flag

PUBLIC	ras_min_table			 ; Minor Code table selector


EXTRN	 SISData:WORD
EXTRNFAR K_S_Systrace			 ; routine to record a trace record
EXTRNFAR FuBuff				 ; routine to copy buffer and check
					 ; protection fault
EXTRNFAR ProbeBuff			 ; ProbeBuff but don't copy
EXTRNFAR SuBuff
EXTRNFAR SemRequest			 ;
EXTRNFAR SemClear
EXTRNFAR SegAlloc			 ; Allocate memory
EXTRNFAR TCYield
EXTRNFAR ScanTasks

DATA segment
ras_min_table  dw 0			 ; Selector for minor code table
DATA ends


DATA segment
mec_array	 DB 32 dup (?)		 ; local Major code array
ras_error_count	 dw 0			 ; Number of errors encountered
ras_max_count	 dw 0			 ; Max errors before pause trace

; Ras Ram Semaphores - Anytime the RAS tables are being updated or
; the RAS system flags are being modified, we make sure no one touches
; them until the current update is complete.

ras_update_vars	  dd  ?			 ; Updating minor/major code tables
					 ; or updating ras system flags

DATA ends

endif ;RAS

	FARCODE HIGH4			 ; DCR 996
RASSWAPCODE SEGMENT
	ASSUME ds:nothing, es:nothing


;/************************** START OF SPECIFICATIONS *****************
;/*
;/*	SUBROUTINE NAME:   w_strucheck
;/*
;/*	DESCRIPTIVE NAME:  Worker routine that does the checking on
;/*			   tracing existence
;/*
;/*	FUNCTION: Worker routine invoked by SCI in DosStruCheck
;/*		  routine to check if STDA exist
;/*
;/*	NOTES:
;/*
;/*	ENTRY POINT:  w_strucheck
;/*	   LINKAGE:   CALL near from High4Code
;/*
;/*	INPUT: (PARAMETERS)
;/*
;/*	  None
;/*
;/*	EXIT-NORMAL: AX (data_flag) = 0 no trace buffer
;/*		     AX (data_flag) = 1 trace by major only
;/*		     AX (data_flag) = 2 trace by major and minor
;/*		     carry_flag = 1
;/*
;/*	EXIT-ERROR: N/A
;/*
;/*	EFFECTS:
;/*	    Uses: AX, DS, ES, Flags
;/*
;/*	INTERNAL REFERENCES: SetRasSem, FreeRasSem
;/*
;/*	EXTERNAL REFERENCES: None
;/*************************** END OF SPECIFICATIONS ******************



Procedure w_strucheck,HYBRID

if RAS

      Assume ds:nothing, es:nothing

; Since this procedure checks the ras system flags, we need to make
; sure no one is updating the flags before we check for type of
; tracing

     call  SetRasSem


     Assume ds:nothing, es:nothing

     DosContext ds			      ; get global segment address

     mov  ax,0				      ; Assume no tracing
     .if     <ras_stda_addr ne 0>	      ; Is tracing initialized?
	inc   ax			      ; YES, major code tracing (1)
	test  ras_systr_flags,RF_TRCMINORCD   ; Minor code tracing?
	.if nz				      ; Yes
	  inc  ax			      ; Major/minor code tracing (2)
	.endif				      ; End minor code tracing
     .endif				      ; End tracing Initialized

; Now free the semaphore

     call FreeRasSem

     stc				      ; Force return code in ax
else
     mov   ax,0
endif ;RAS

     RET

EndProc	  w_strucheck



;/************************** START OF SPECIFICATIONS *****************
;/*
;/*	SUBROUTINE NAME:   w_struresupdate
;/*
;/*	DESCRIPTIVE NAME:  Worker routine to update the major  event
;/*			   and minor event code arrays
;/*
;/*	FUNCTION: An Undocumented call used by the Trace Utility
;/*		  for updating the major and minor event code arrays.
;/*		  The first invocation of this procedure with a
;/*		  request to trace by minor code will result
;/*		  in an 8K minor event code table being allocated
;/*		  in fixed, high memory.   An internal trace record
;/*		  will be generated by invoking TESTTRACE to see
;/*		  if RAS major event code (0) is enabled then add
;/*		  record to the Circular Trace Buffer via STRP
;/*		  by calling K_S_Systrace
;/*
;/*	NOTES:
;/*
;/*	ENTRY POINT:  w_struresupdate
;/*	   LINKAGE:   CALL near from High4Code
;/*
;/*	INPUT: (PARAMETERS)
;/*
;/*	  BX:SI - address of the major code "bit mask"
;/*	  DX:DI - address of the minor code "bit mask"
;/*	  CX	- Type of request
;/*		  0 - major code tracing
;/*		  1 - Major and Minor code tracing
;/*	  AX	- on_off_flag which indicates the "ON/OFF" parameter
;/*		  1 = ON; 0 = OFF
;/*
;/*	EXIT-NORMAL: Major event code array is updated based on request.
;/*		     Minor event code array is updated (if minor code tracing)
;/*		     A trace record (RAS update record) is added to the trace
;/*		     buffer if major code 0 is on when this procedure is
;/*		     entered or if major code 0 is turned "on" by this
;/*		     procedure.
;/*		     AX =  0
;/*		     carry flag is clear
;/*
;/*	EXIT-ERROR:  AX = ERROR_NO_MC_TRACE (No Minor code trace)
;/*		     AX = ERROR_MC_TRACE (Bad Major/Minor code table)
;/*		     carry flag is set
;/*
;/*	EFFECTS:
;/*	    Uses: AX, BX, CX, DX, DI, SI, DS, ES, Flags
;/*
;/*	INTERNAL REFERENCES: SetRasSem, FreeRasSem
;/*
;/*	EXTERNAL REFERENCES:
;/*	   ROUTINES:
;/*
;/*		K_S_Systrace	     - record trace record
;/*		ProbeBuff	     - Check buffer boundaries
;/*		FuBuff		     - routine to copy buffer
;/*		SegAlloc	     - allocate 8K buffer
;/*************************** END OF SPECIFICATIONS ******************


Procedure w_struresupdate,HYBRID

if RAS

   LocalVar on_off_flag,WORD	     ; Enable/Disable tracing	     (ax)
   LocalVar major_minor_flag,WORD    ; Major or Minor tracing	     (cx)
   LocalVar minor_code_addr,DWORD    ; Addr of user minor code table (dx:di)
   LocalVar major_code_addr,DWORD    ; Addr of user major code table (bx:si)
   LocalVar err_code,WORD	     ; Error code		     (0)
   LocalVar ras_major_status,WORD    ; Status of RAS Major Code	     (0)


     EnterProc <ax,cx,dx,di,bx,si,0,0> ; allocate and set local variables

     ASSUME ds:nothing, es:nothing

     DosContext ds

; First check to see if system tracing exist, if it doesn't then exit

     .if <ras_stda_addr ne 0> near		 ; Tracing exist?

; Since we will be updating the major/minor code tables and possibly
; updating the ras system flags, we need to make sure no one else is
; updating the flags

	call SetRasSem				 ; Yes, get semaphore
	ASSUME ds:nothing, es:nothing


; First check to see if we need to allocate the 8K minor event code table
; We allocate the buffer if this is a request to trace by minor code
; and the minor event code table has not been allocated.

	DosContext ds

	.if <major_minor_flag eq RF_REQMINOR>	 ; Minor Code Request?
	  test	ras_systr_flags,RF_TRCMINORCD	 ; Yes
	  .if z					 ; Already Tracing by minor?
						 ; NO
; Not tracing by minor, call SegAlloc to allocate 8K buffer  (fixed, high)

	    xor ax,ax				 ; size
	    mov bx,RV_MINORSIZE			 ; allocate 8K
	    mov si,HF_FIXED+HF_HIMEM+HF_ZEROINIT  ; Type of memory
	    mov di,RASOWNER			 ; RAS is the owner
	    mov cl,SA_GDT			 ; selector allocation flags
	    mov ch,D_DATA0			 ; Access Flags
	    CALLFAR SegAlloc			 ; Allocate the memory
	    .if nc				 ; ERROR?
	      DosContext ds			 ; NO
	      mov  ras_min_table,bx		 ; save selector
	      or   ras_systr_flags,RF_TRCMINORCD ; Indicate trace by minor
	    .else				 ; Error from SegAlloc
	      mov  err_code,ERROR_NO_MC_TRACE	 ; No minor code tracing
	    .endif				 ; end SegAlloc error
	  .endif				 ; end minor code active
	.endif					 ; end request minor code

; Even if there was an error allocating the 8K minor code table, we will
; turn the requested major codes ON/OFF and tell the caller that only
; major code tracing is currently available
; We will now call FuBuff to copy the caller's 32 byte major event
; code bit mask to our local 32 byte byte "bit mask"

	DosContext es

	mov	di,offset es:mec_array		 ; ES:DI -> target (Kernel)
	mov	cx,RV_MECSIZE			 ; size to be moved
	mov	bx,major_code_addr.Segmt	 ; caller's 32 byte bit mask
	mov	si,major_code_addr.Offst	 ; BX:SI -> source "bit mask"
	CALLFAR FuBuff
	Assume ds:nothing, es:nothing

	.if  <nc> near				 ; Error?
	  DosContext  es

; Test to see if the RAS major code is ON.  This will be used later
; to place a status record in the system trace buffer.

	  TestTrace RV_RASMEC			 ; NO, check RAS major code
	  .if	  nz				 ; Code enabled?
	    mov	  ras_major_status,RV_ON	 ; Yes, indicate ON
	  .endif

; Now  and/or the passed major code bit mask with the system major
; event code table

	  DosContext ds
	  mov	  si, offset ds:mec_array	 ; DS:SI -> "bit mask"
	  mov	  di,offset es:ras_mec_table	 ; ES:DI -> system table
	  mov cx,RV_MECSIZE			 ; Size of table
	  cld
	  .if	  <on_off_flag eq RV_ON>	 ; Enabling tracing?
mec1:	    lodsb				 ; Yes, get source byte
	    or	es:[di],al			 ; Turn bit ON
	    inc di				 ; next byte
	    loop mec1				 ; loop until all MECs
	  .else					 ; Disable tracing
mec2:	    lodsb				 ; get source byte
	    and es:[di],al			 ; Turn bit OFF
	    inc di
	    loop mec2				 ; loop until all MECs

; 96020- Add ending time stamp to STDA structure.  May be changed by succesive
; suspend/resume sequences, TRACE OFF command (this case), error count hit, or
; turning off all PID tracing.
            call SetEndTimeStamp                 ; 96020
            DosContext  es                       ; 96020

	  .endif


; Since the major event code table has been updated we can now move it
; to the Global Information Segment for use by Device Drivers and Subsystems


	  DosContext ds				 ; DS:SI ->  Kernel table
	  mov cx,RV_MECSIZE			 ; Major Code table size
	  mov si,offset ds:ras_mec_table	 ; move from current table
IFDEF MMIOPH
	  .if <ds:SISData.SIS_MMIOBase eq 0>	 ; MMIO failed
	      and ds:[si],not PERFBIT		 ; Turn it off
	  .endif

ELSE
	  and	  ds:[si],NOT PERFBIT		 ; Production, Major code 1
						 ; is reserved.
ENDIF ;MMIOPH
	  mov di,offset es:SISData.SIS_mec_table ; ES:DI -> Info Segment
	  cld
	  rep	movsb				 ; move to info seg

;  Move into infoseg copy as well

	  assume es:nothing
	  mov es,[_Sis2].is_sel
	  mov si,offset ds:ras_mec_table	 ; move from current table
	  mov di,offset es:SIS_mec_table
	  mov cx,RV_MECSIZE			 ; Major Code table size
	  rep	movsb


;  Now lets determine if the minor code array must be manipulated


	  test ras_systr_flags,RF_TRCMINORCD	 ; Tracing by minor code?
	  .if <nz>				 ; Yes
	    mov	    si,minor_code_addr.Offst	 ; SI -> Caller "bit mask"
	    DosContext es
	    mov	    di,0			 ; Kernel minor code table
	    mov	    ax,ras_min_table		 ; Selector of minor code table
	    mov	    es,ax			 ; ES:DI -> Kernel minor code
	    Assume  es:nothing
	    mov	 cx,RV_MINORSIZE/RV_MINORMOVE	 ; 8k total (1 K at a time)
mec3:
	    CALLFAR TCYield			 ; Yield

;  Next we call ProbeBuf to probe the user's buffer to make sure it is OK
;  and present. We don't copy the buffer (using FuBuff) because this is
;  a large buffer.  If we copied the buffer, this would mean we would
;  have an 8K buffer passed by the user, an 8K area to copy the buffer
;  (allocate/freed on each call), and the Kernel's 8K fixed buffer
;
	    push   cx				 ; save counter
	    push   es				 ; start of kernel table
	    push   di				 ; offset of kernel table
	    push   si				 ; offset caller table
	    mov	   bx,minor_code_addr.Segmt	 ; segment to user buffer
	    mov	   si,minor_code_addr.Offst	 ; offset to user buffer
	    mov	   cx,RV_MINORSIZE		 ; It's an 8K buffer
	    mov	   dh,0				 ; Read Access only
	    CALLFAR ProbeBuff			 ; Check buffer

	    pop	 si
	    pop	 di
	    pop	 es				 ; ES:DI -> Kernel buffer
	    .if	 nc				 ; ERROR?
	      mov  ax,minor_code_addr.Segmt	 ; NO, Segment for user buffer
	      mov  ds,ax			 ; DS:SI -> User "bit mask"
	      Assume ds:nothing
	      mov  cx,RV_MINORMOVE		 ; Move only 1K at a time
	      cld
	      .if     <on_off_flag eq RV_ON>	 ; Enable the minor codes
mec4:		lodsb				 ; get byte off user table
		or  es:[di],al			 ; Turn ON minor code
		inc di				 ; next byte
		loop mec4			 ; loop til Minors are done
	      .else				 ; Disable the minor codes
mec5:		lodsb				 ; get source byte
		and es:[di],al			 ; Turn OFF minor code
		inc di
		loop mec5			 ; loop til Minors are done
	      .endif				 ; End enable/disable
	    .else				 ; Error with ProbeBuf
	      mov err_code,ERROR_MC_TRACE	 ; error minor code table
	      pop cx				 ; restore count
	      jmp mc6				 ; leave loop gracefully
	    .endif				 ; error ProbeBuff
	    pop cx				 ; restore 8K counter
	    loop  mec3				 ; get the next 1K

	  .endif				 ; End Minor Code Tracing

mc6:

; Check to see if the RAS major code was on when this procedure was
; entered or if it was turned on during the update of the RAS major
; event code table.  If either is true, then call the system trace
; routine  to place a record in the system trace buffer.
; Note: This is done even if we encounter an error updating the minor
; event code table.

	  DosContext  ds
	  TestTrace RV_RASMEC			 ; Check ras mec

	  .if  nz  or				 ; event enabled
	  .if  <ras_major_status eq RV_ON>	 ; trace event was ON
	    mov si,offset ds:ras_mec_table	 ; DS:SI -> Major table
	    mov al,RV_RASMEC			 ; major event code = 0
	    mov bx,RV_MECSIZE			 ; Major code table size
	    mov dx,RV_RASMINSTRU		 ; minor event code = 2
	    CALLFAR K_S_Systrace		 ; record the event
	  .endif

	.else					 ; error major code table
	  mov  err_code,ERROR_MC_TRACE
	.endif					 ; End (Fubuff error) major

; Now we need to clear the Ras semaphore

	call FreeRasSem
	ASSUME ds:nothing, es:nothing

     .else					 ; tracing not enabled
	  mov  err_code,ERROR_SYSTEM_TRACE
     .endif					 ; end

; Now store the error code

     mov  ax,err_code				 ; Set up return code
     cmp  ax,1					 ; Carry set if ax=zero
     cmc					 ; Set carry if ax is nonzero

     LeaveProc

else
     mov  ax,0
endif ;RAS
     RET

EndProc w_struresupdate                                       


BREAK	<w_SetTraceInfo - Set System Trace Options>

;/********************** START OF SPECIFICATIONS *********************
;/*
;/* SUBROUTINE NAME: w_SetTraceInfo
;/*
;/* DESCRIPTIVE NAME: Set System Trace Information/Options
;/*
;/* FUNCTION:	 To set the desired options for system tracing
;/*
;/* NOTES:	 Kernel worker routine for DosSetTraceInfo
;/*
;/* ENTRY POINT: w_SetTraceInfo
;/*    LINKAGE:	 Call near from HIGH4CODE
;/*
;/* INPUT:
;/*
;/*		   bx - Request Code
;/*
;/*			 0 - Suspend Trace logging
;/*			 1 - Resume Trace logging
;/*			 2 - Clear system trace buffer
;/*			 3 - Trace until error count
;/*			 4 - Trace Off until error
;/*			 5 - Increment error count
;/*			 6 - Trace ON Specific PID
;/*			 7 - Trace ON all PIDs
;/*			 8 - Trace OFF Specific PID
;/*			 9 - Trace OFF all PIDs
;/*
;/*		   dx - Maximum error count
;/*		   cx - PID
;/*
;/*
;/* EXIT-NORMAL: AX = 0
;/*		 carry flag is clear
;/*
;/* EXIT-ERROR:	 AX = error code:
;/*			error_trc_count_active
;/*			error_trc_count_inactive
;/*			error_trc_count_reached
;/*			error_trc_suspended_by_count
;/*			error_trc_pid_non_existent
;/*			error_trc_count_zero
;/*		 carry flag is set
;/*
;/* EFFECTS:
;/*	Uses: AX, BX, DX, DI, DS, ES, Flags
;/*
;/* INTERNAL REFERENCES:
;/*    ROUTINES:
;/*		 SuspendRasTrace  -  Suspend Tracing
;/*		 ResumeRasTrace	  -  Resume Tracing
;/*		 FreeRasTrace	  -  Clear buffer
;/*		 TraceTilError	  -  Trace til count
;/*		 TraceTilErrorOff -  Off trace til count
;/*		 IncErrorCount	  -  Increment count
;/*		 PIDTraceOn	  -  Trace by PID
;/*		 PIDTraceOnAll	  -  Trace all PIDs
;/*		 PIDTraceOff	  -  Turn 1 PID off
;/*		 PIDTraceOffAll	  -  Trace no PIDs
;/*		 SetRasSem	  -  Set Ras Ram Semaphore
;/*		 FreeRasSem	  -  Free Ras Ram Semaphore
;/*
;/* EXTERNAL REFERENCES:
;/*    ROUTINES:
;/*********************** END OF SPECIFICATIONS **********************

if RAS
;***DT	DosSetTraceInfo - Set Trace Information File
;
;    TRACE MINOR = 0x8000,
;	   TP	 = .w_SetTraceInfo,
;	   TYPE	 = (PRE,INT),
;	   GROUP = TSK,
;	   DESC	 = "(OS) DosSetTraceInfo  Pre-Invocation",
;	   REGS	 = (BX,CX,DX),
;	   FMT	 = "Request Code=%W PID=%w Count=%W"
;
;;Note: This is a Temporary Trace Point and will be removed during
;;	Component Test
endif ;RAS

Procedure w_SetTraceInfo,HYBRID

if RAS
	assume ds:nothing, es:nothing

	DosContext ds				    ; DOSGROUP

; First check to see if system trace is enabled,  if it is then make
; sure the request code is OK.  If all test pass, grab the RAS semaphore
; because we will be updating the ras system flags.

	 mov  ax,ERROR_SYSTEM_TRACE		    ; Assume no tracing

	.if <ras_stda_addr ne 0>		    ; is tracing available?
	  .if <bx b REQ_LEN>			    ; Yes, Is request OK?
	    call SetRasSem			    ; Yes, grab ras semaphore
	    ASSUME ds:nothing, es:nothing
	    DosContext ds
	    shl	 bx,1				    ; Pick-up routine to call
	    call WORD PTR RASSWAPCODE:req_tbl[bx]  ; call subfunction
	    call FreeRasSem			    ; release ras semaphore
	    ASSUME ds:nothing, es:nothing
	  .endif
	.endif					    ; end tracing available

	 cmp ax,1				    ; set carry if AX = zero
	 cmc					    ; set carry if AX not zero

;***DT	DosSetTraceInfo - Set Trace Information File Post
;
;    TRACE MINOR = 0xFFF1,
;	   TP	 = .w_SetTraceInfoExit,
;	   TYPE	 = (POST,INT),
;	   GROUP = TSK,
;	   DESC	 = "(OS) DosSetTraceInfo  Post-Invocation",
;	   REGS	 = (AX),
;	   FMT	 = "Return Code=%W"
;
;;Note: This is a Temporary Trace Point and will be removed during
;;	Component Test

public w_SetTraceInfoExit
w_SetTraceInfoExit:

endif ;DEBUG  - actually RAS /* 96020 */

	ret					    ; Return

if RAS
    ret                 ; Return

req_tbl:dw	offset RASSWAPCODE:SuspendRasTrace    ;Suspend Tracing	    0
	dw	offset RASSWAPCODE:ResumeRasTrace     ;Resume Tracing	    1
	dw	offset RASSWAPCODE:ClearRasTrace      ;Clear buffer	    2
	dw	offset RASSWAPCODE:TraceTilError      ;Trace til count	    3
	dw	offset RASSWAPCODE:TraceTilErrorOff   ;Off trace til count  4
	dw	offset RASSWAPCODE:IncErrorCount      ;Increment count	    5
	dw	offset RASSWAPCODE:PIDTraceOn	      ;Trace by PID	    6
	dw	offset RASSWAPCODE:PIDTraceOnAll      ;Trace all PIDs	    7
	dw	offset RASSWAPCODE:PIDTraceOff	      ;Turn 1 PID off	    8
	dw	offset RASSWAPCODE:PIDTraceOffAll     ;Trace no PIDs	    9

REQ_LEN equ	($ - req_tbl)/2

endif ;RAS


EndProc  w_SetTraceInfo

if RAS


;/********************** START OF SPECIFICATIONS *********************
;/*
;/* SUBROUTINE NAME: SetEndTimeStamp - completely new routine for 96020
;/*
;/* DESCRIPTIVE NAME: Set Ending time and Date Stamp in STDA
;/*
;/*
;/* ENTRY POINT: SetEndTimeStamp
;/*    LINKAGE:	 Call near from HIGH4CODE (local)
;/*
;/* INPUT:  DS - DOSGROUP
;/*	    Caller must have ownership of Ras Semaphore
;/*
;/* EXIT-NORMAL: AX = 0
;/*
;/* EXIT-ERROR:	 None
;/*
;/* EFFECTS:
;/*	Uses: AX, CX
;/*
;/* INTERNAL REFERENCES:
;/*    ROUTINES: None
;/*
;/* EXTERNAL REFERENCES:
;/*    ROUTINES:
;/*********************** END OF SPECIFICATIONS **********************

Procedure SetEndTimeStamp,near,local
	assume ds:DOSGROUP, es:nothing
; 96020- Add ending time stamp to STDA structure.  May be changed by succesive
; suspend/resume sequences, TRACE OFF command, error count hit, or
; turning off all PID tracing. - 96020

      mov  ax,ras_stda_addr     ; Selector to trace buffer                    96020
      mov  es,ax                ; Point to trace buffer                       96020
      Assume es:nothing
      mov cx,WORD PTR ds:SISData.SIS_SecTime  ; current time(low order bytes) 96020
      mov es:stda_end_sec,cx    ; save sec,hunds time in record               96020
      mov cx,WORD PTR ds:SISData.SIS_HrsTime ; current time(high order bytes) 96020
      mov es:stda_end_hrs,cx    ; save hrs, min time in record                96020
      mov cx,WORD PTR ds:SISData.SIS_DayDate ; current day and month          96020
      xchg cl,ch                ; switch to month and day                     96020
      mov es:stda_end_mon,cx    ; save month and day in record                96020
      mov cx,WORD PTR ds:SISData.SIS_YrsDate ; current year                   96020
      mov es:stda_end_yrs,cx    ; save year in record                         96020
      ret                       ;

EndProc  SetEndTimeStamp


BREAK	<SuspendRasTrace - Suspend/Pause RAS Tracing>


;/********************** START OF SPECIFICATIONS *********************
;/*
;/* SUBROUTINE NAME: SuspendRasTrace
;/*
;/* DESCRIPTIVE NAME: Suspend Ras System Tracing System Wide
;/*
;/*
;/* ENTRY POINT: SuspendRasTrace
;/*    LINKAGE:	 Call near from HIGH4CODE (local)
;/*
;/* INPUT:  DS - DOSGROUP
;/*	    Caller must have ownership of Ras Semaphore
;/*
;/* EXIT-NORMAL: AX = 0
;/*
;/* EXIT-ERROR:	 None
;/*
;/* EFFECTS:
;/*	Uses: AX, Flags
;/*
;/* INTERNAL REFERENCES:
;/*    ROUTINES: None
;/*
;/* EXTERNAL REFERENCES:
;/*    ROUTINES:
;/*********************** END OF SPECIFICATIONS **********************

Procedure SuspendRasTrace,near,local
	assume ds:DOSGROUP, es:nothing

; This is a request to pause tracing

; 96020- Add ending time stamp to STDA structure.  May be changed by succesive
; suspend/resume sequences, TRACE OFF command, error count hit, or
; turning off all PID tracing.
      call SetEndTimeStamp      ; 96020

	or   ras_systr_flags,RF_TRCPAUSED	   ; Pause tracing
	xor  ax,ax				   ; clear return code

	ret					   ; Return

EndProc	 SuspendRasTrace


BREAK	<ResumeRasTrace - Resume Ras Tracing>


;/********************** START OF SPECIFICATIONS *********************
;/*
;/* SUBROUTINE NAME: ResumeRasTrace
;/*
;/* DESCRIPTIVE NAME: Resume Ras System Tracing System Wide
;/*
;/* FUNCTION:  Resume Tracing across the system.  If tracing has
;/*	       been paused due to "trace until error count" being
;/*	       reached, then tracing remains paused and an error
;/*	       is returned.
;/*
;/* ENTRY POINT: ResumeRasTrace
;/*    LINKAGE:	 Call near HIGH4CODE (local)
;/*
;/* INPUT:  DS - DOSGROUP
;/*	    Caller must have ownership of Ras Semaphore
;/*
;/* EXIT-NORMAL: AX = 0
;/*
;/* EXIT-ERROR:	 AX = error_trc_suspended_by_count
;/*
;/* EFFECTS:
;/*	Uses: AX, Flags
;/*
;/* INTERNAL REFERENCES:
;/*    ROUTINES: None
;/*
;/* EXTERNAL REFERENCES:
;/*    ROUTINES:
;/*********************** END OF SPECIFICATIONS **********************
Procedure ResumeRasTrace,near,local
	assume ds:DOSGROUP, es:nothing

;  This is a request to resume tracing
;  Do not resume tracing if we paused due to an error count being
;  reached.


; If tracing has been suspended due to an error being reached,
; return the error, else resume tracing and set ax to zero.

       mov  ax,ERROR_TRC_SUSPENDED_BY_COUNT	    ; Paused due to error cnt
       test ras_systr_flags,RF_TRCSUSPEND	    ; Suspended by count?
      .if <z>					    ; NO, resume tracing
	 and  ras_systr_flags,not RF_TRCPAUSED	    ; resume tracing
	 xor  ax,ax				    ; no error
      .endif

      ret					    ; Return

EndProc	 ResumeRasTrace

BREAK	<ClearRasTrace - Clear RAS Trace buffer>

;/********************** START OF SPECIFICATIONS *********************
;/*
;/* SUBROUTINE NAME: ClearRasTrace
;/*
;/* DESCRIPTIVE NAME: Clear the RAS system trace buffer
;/*
;/* FUNCTION:  This routine will clear the RAS System Trace Buffer.
;/*	       The appropriate pointer are set to point to the
;/*	       beginning of the trace buffer and enough bytes in
;/*	       the buffer are zeroed to indicate to the TRACEFMT
;/*	       Utility that the buffer is clear.
;/*
;/* ENTRY POINT: ClearRasTrace
;/*    LINKAGE:	 Call near from HIGH4CODE (local)
;/*
;/* INPUT:  DS - DOSGROUP
;/*	    Caller must have ownership of Ras Semaphore
;/*
;/* EXIT-NORMAL: AX = 0
;/*
;/* EXIT-ERROR:	 None
;/*
;/* EFFECTS:
;/*	Uses: AX, BX, CX, DI, ES, Flags
;/*
;/* INTERNAL REFERENCES:
;/*    ROUTINES: None
;/*
;/* EXTERNAL REFERENCES:
;/*    ROUTINES:
;/*********************** END OF SPECIFICATIONS **********************

Procedure ClearRasTrace,near,local
	assume ds:DOSGROUP, es:nothing
;  This is a request to clear the RAS trace buffer
;  Pause tracing until buffer is clear to prevent pointers from being
;  updated by system trace.

       mov  bl,ras_systr_flags			    ; Save current status
       or   ras_systr_flags,RF_TRCPAUSED	    ; Pause til done

;  Get the address of the trace buffer.  Zero out 5 bytes at the
;  front of the buffer.  This makes the formatter believe the buffer is
;  clear.  The ptr3 variable points to the next available byte in the trace
;  buffer.

       mov  ax,ras_stda_addr			    ; Selector to trace buffer
       mov  es,ax				    ; Point to trace buffer
Assume es:nothing
       mov  cx,RV_CLEARLEN			    ; size, bytes to zero out
       xor  ax,ax				    ; zero out buffer
       mov  di,es:stda_start_buffer		    ; ES:DI -> Start of buffer
       cld
rep    stosb					    ; put al (zero) in first
						    ; 6 bytes of trace buffer
       mov  es:stda_current_offst,di		    ; Makes formatter believe
						    ; Buffer is empty.

; 
96020- Add starting time stamp to STDA structure since we are starting over maybe
      mov cx,WORD PTR ds:SISData.SIS_SecTime  ; current time(low order bytes) 96020
      mov es:stda_start_sec,cx    ; save sec,hunds time in record             96020
      mov cx,WORD PTR ds:SISData.SIS_HrsTime ; current time(high order bes)   96020
      mov es:stda_start_hrs,cx    ; save hrs, min time in record              96020
      mov cx,WORD PTR ds:SISData.SIS_DayDate ; current day and month          96020
      xchg  cl,ch                 ; switch to month and day                   96020
      mov es:stda_start_mon,cx    ; save month and day in record              96020
      mov cx,WORD PTR ds:SISData.SIS_YrsDate ; current year                   96020
      mov es:stda_start_yrs,cx    ; save year in record                       96020

       mov  ras_systr_flags,bl			    ; restore trace status

; AX zeroed above to indicate no error was encountered

       ret					    ; Return

EndProc	 ClearRasTrace

BREAK	<TraceTilError - Trace until error count reached>


;/********************** START OF SPECIFICATIONS *********************
;/*
;/* SUBROUTINE NAME: TraceTilError
;/*
;/* DESCRIPTIVE NAME: Trace Until a specified error count is reached
;/*
;/* FUNCTION:  This routine will initialize the trace until a
;/*	       specified error count is reached.  If tracing til
;/*	       error count is already active, an error is returned.
;/*
;/* ENTRY POINT: TraceTilError
;/*    LINKAGE:	 Call near from HIGH4CODE (local)
;/*
;/* INPUT:     DS - DOSGROUP
;/*	       DX - Maximum error count (trace til count reached)
;/*	       Caller must have ownership of Ras Semaphore
;/*
;/* EXIT-NORMAL: AX = 0
;/*
;/* EXIT-ERROR:	 AX = error_trc_count_active
;/*		      error_trc_count_zero
;/*
;/* EFFECTS:
;/*	Uses: AX, BX, ES, Flags
;/*
;/* INTERNAL REFERENCES:
;/*    ROUTINES: None
;/*
;/* EXTERNAL REFERENCES:
;/*    ROUTINES:
;/*********************** END OF SPECIFICATIONS **********************


Procedure TraceTilError,near,local
	assume ds:DOSGROUP, es:nothing

;  This is a request to initialze trace until error count reached
;  First, temporarily pause tracing until the operation is complete

       mov  bl,ras_systr_flags			    ; Copy current flags
       or   ras_systr_flags,RF_TRCPAUSED	    ; Pause til done

;  If tracing by error count is already active, then return an error.
;  If not active then reset the running error count and maximum error
;  count.  Turn on appropriate flag in BL

;  First check to make sure we are not passed an error count of zero

       .if  <dx ne 0>				    ; Is there a count
	 mov  ax,ERROR_TRC_COUNT_ACTIVE		    ; YES, init return code
	 test ras_systr_flags,RF_TRCERRCOUNT	    ; Tracing errors?
	 .if  <z>
	    DosContext es
	    mov	 es:ras_error_count,0		    ; NO, reset running count
	    mov	 es:ras_max_count,dx		    ; stop when count =
	    or	 bl,RF_TRCERRCOUNT		    ; Trace until error
	    xor	 ax,ax				    ; no error
	 .endif
       .else
	  mov  ax,ERROR_TRC_COUNT_ZERO		    ; count is zero
       .endif					    ; endif count zero

;  Update status flags and restore the original status of the
;  Pause flag.

       mov  ras_systr_flags,bl			    ; Update status flags

       ret					    ; Return

EndProc	 TraceTilError


BREAK	<TraceTilErrorOff - Turn Off Trace Til Error>


;/********************** START OF SPECIFICATIONS *********************
;/*
;/* SUBROUTINE NAME: TraceTilErrorOff
;/*
;/* DESCRIPTIVE NAME: Turn off tracing until an error count reached
;/*
;/* FUNCTION:  This routine cancels the request to trace until
;/*	       error count.  This is the only way to resume tracing
;/*	       once tracing has been suspended by error count.
;/*	       If "trace until error" is not active an error
;/*	       (error_trc_count_inactive) is returned.  If
;/*	       tracing was suspended due to an error count being
;/*	       reached, then tracing is resumed.
;/*
;/* ENTRY POINT: TraceTilErrorOff
;/*    LINKAGE:	 Call near from HIGH4CODE (local)
;/*
;/* INPUT: DS - DOSGROUP
;/*	   Caller must have ownership of Ras Semaphore
;/*
;/* EXIT-NORMAL: AX = 0
;/*
;/* EXIT-ERROR:	 AX = error_trc_count_inactive
;/*
;/* EFFECTS:
;/*	Uses: AX, BX, ES, Flags
;/*
;/* INTERNAL REFERENCES:
;/*    ROUTINES: None
;/*
;/* EXTERNAL REFERENCES:
;/*    ROUTINES:
;/*********************** END OF SPECIFICATIONS **********************

Procedure TraceTilErrorOff,near,local
	assume ds:DOSGROUP, es:nothing

;  This is a request to Cancel trace until error count reached.
;  First, temporarily pause tracing until the operation is complete

       mov  bl,ras_systr_flags			    ; Copy current flags
       or   ras_systr_flags,RF_TRCPAUSED	    ; Pause til done


;  This is a request to STOP Trace until error count
;  Reset system trace flags to indicate the following:
;
;	      1.  If the tracing has been suspended due to an error
;		  count then reset the pause bit and tracing suspended bit
;	      2.  Turn "off" tracing til error count bit

       mov  ax,ERROR_TRC_COUNT_INACTIVE		    ; not tracing by count
       test bl,RF_TRCERRCOUNT			    ; Tracing until count?
       .if nz					    ;
	 mov  al,RF_TRCERRCOUNT			    ; turn off error count
	 test bl,RF_TRCSUSPEND			    ; Tracing suspended?
	 .if <nz>				    ;
	    or	al,RF_TRCSUSPEND+RF_TRCPAUSED	    ; YES, reset bits
	 .endif

; Now, reverse the bits so only the following flags are turned off:
;		  RF_TRCPAUSED
;		  RF_TRCSUSPEND
;		  RF_TRCERRCOUNT

	 not  al				    ; turn off requests
	 and  bl,al				    ; set system flags
	 DosContext es
	 mov  es:ras_error_count,0		    ; reset error count
	 mov  es:ras_max_count,0		    ; reset max count
	 xor  ax,ax				    ; no error
       .endif					    ; End tracing by count

       mov  ras_systr_flags,bl			    ; Update status flags

       ret					    ; Return

EndProc	 TraceTilErrorOff



BREAK	<IncErrorCount - Increment Error Count>

;/********************** START OF SPECIFICATIONS *********************
;/*
;/* SUBROUTINE NAME: IncErrorCount
;/*
;/* DESCRIPTIVE NAME: Increment error count variable
;/*
;/* FUNCTION:  This routine increments the error count variable
;/*	       by 1 (used in conjunction with trace til error count).
;/*	       If "trace til error count"  is not active then an
;/*	       error (error_trc_count_inactive) is returned.
;/*	       If the newly incremented count equals "trace til count"
;/*	       then tracing is suspended.  Once the count exceeds
;/*	       that specified then an error (error_trc_count_reached)
;/*	       is returned.
;/*
;/* ENTRY POINT: IncErrorCount
;/*    LINKAGE:	 Call near HIGH4CODE (local)
;/*
;/* INPUT:  DS - DOSGROUP
;/*	    Caller must have ownership of Ras Semaphore
;/*
;/* EXIT-NORMAL: AX = 0
;/*
;/* EXIT-ERROR:	 AX = error_trc_count_inactive
;/*		      error_trc_count_reached
;/*
;/* EFFECTS:
;/*	Uses: AX, BX, ES, Flags
;/*
;/* INTERNAL REFERENCES:
;/*    ROUTINES: None
;/*
;/* EXTERNAL REFERENCES:
;/*    ROUTINES:
;/*********************** END OF SPECIFICATIONS **********************

Procedure IncErrorCount,near,local
	assume ds:DOSGROUP, es:nothing

;  This is a request to Increment the error count.
;  First, temporarily pause tracing until the operation is complete

       mov  bl,ras_systr_flags			    ; Copy current flags
       or   ras_systr_flags,RF_TRCPAUSED	    ; Pause til done

       mov  ax,ERROR_TRC_COUNT_INACTIVE		    ; initialize error code
       test bl,RF_TRCERRCOUNT			    ; Tracing until error on?
       .if  <nz>
	  DosContext es			    ; yes, perform operation
	  mov  ax,es:ras_error_count		    ; current count
	 .if  <ax ae <es:ras_max_count>>	    ; max count reached? Yes...

; 96020- Add ending time stamp to STDA structure.  May be changed by succesive
; suspend/resume sequences, TRACE OFF command, error count hit (this case), or
; turning off all PID tracing.
            call SetEndTimeStamp  ;  96020
	   mov ax,ERROR_TRC_COUNT_REACHED    ; yes, inform caller max count reached

	 .else					    ; no, increment counter
	   inc	es:ras_error_count		    ; increment count
	   inc	ax				    ; inc for comparison
	   .if	<ax ae <es:ras_max_count>>	    ; Reached count limit
	     or	 bl,RF_TRCPAUSED+RF_TRCSUSPEND	    ; YES, Pause tracing and
						    ; indicate suspended
						    ; due to count
	   .endif				    ; END count reached
	   xor ax,ax				    ; no error
	 .endif					    ; end increment count
       .endif					    ; endif trace error active

       mov  ras_systr_flags,bl			    ; Update status flags

       ret					    ; Return

EndProc	 IncErrorCount




BREAK	<PIDTraceOn - Trace by selected PID>


;/********************** START OF SPECIFICATIONS *********************
;/*
;/* SUBROUTINE NAME: PIDTraceOn
;/*
;/* DESCRIPTIVE NAME: Enable Ras Tracing for a specified PID
;/*
;/* FUNCTION:	 This request allows tracing to occur for a
;/*		 specified PID.  This only effects the requested
;/*		 PID.  If the requested PID is non-existent then
;/*		 an error (error_trc_pid_non_existent) is returned.
;/*
;/* NOTE:  TraceValue indicates what values are placed in the trace
;/*	   buffer.  TraceValue will always have a value of either
;/*	   0 or 0xFF depending on what type of PID tracing is occuring
;/*
;/* ENTRY POINT: PIDTraceOn
;/*    LINKAGE:	 Call near  from HIGH4CODE (local)
;/*
;/* INPUT:  DS - DOSGROUP
;/*	    CX - PID to enable
;/*	    Caller must have ownership of Ras Semaphore
;/*
;/* EXIT-NORMAL: AX = 0
;/*
;/* EXIT-ERROR:	 AX = error_trc_pid_non_existent
;/*
;/* EFFECTS:
;/*	Uses: AX, BX, DX, DI, ES, Flags
;/*
;/* INTERNAL REFERENCES:
;/*    ROUTINES: None
;/*
;/* EXTERNAL REFERENCES:
;/*    ROUTINES:	       ScanTasks
;/*********************** END OF SPECIFICATIONS **********************

Procedure PIDTraceOn,near,local
	assume ds:DOSGROUP, es:nothing

       LocalVar	 system_status,BYTE		    ; system flags
       EnterProc

; This is a request to trace by PID

; First save the current system trace status flags and
; then pause tracing until this operation is performed


       mov  al,ras_systr_flags			    ; Copy current flags
       mov  system_status,al			    ; save flags
       or   ras_systr_flags,RF_TRCPAUSED	    ; Pause til done

; NOTE: TraceValue controls what PIDs are allowed to be placed in the
; trace buffer.  A record is added if ptda_rasflag = TraceValue
; First check to see if tracing by PID is occuring.  If tracing by
; PID is not occuring, this is the enabling of trace by PID.  We
; simply change the ptda_rasflag to a 0xFF value and set TraceValue
; to that same value.
; If we are tracing by PID, we simply call ScanTasks and place the
; value of TraceValue in the ptda (because we are allowing TraceValue
; into the buffer.

       test system_status,RF_TRCPID
       .if z					    ; Tracing by PID?

; NO, we call scantasks to get the appropriate task and set the
; byte in the PTDA indicating that trace is occuring for that PID only
;	    bl - request
;	    bh - scan flags
;	    cx - PID		 (already set, passed by caller)
;	    di - offset of worker relative to caller's CS
;	    dl - value to place in PTDA Trace Variable

	  mov  bx,TK_TG_ONE			    ; NO, Scan specific task
	  MOVFAROFFSET di,SetOnePid,RASSWAPCODE	    ; worker
	  mov  dl,RF_TRCSELPID			    ; Trace selective PID
	  CALLFAR ScanTasks
	  Assume es:nothing
	  DosContext ds

	  .if  nc				    ; ERROR?
	    xor	 ax,ax				    ; NO, indicate such
	    or	 system_status,RF_TRCPID	    ; Tracing by PID
	    mov	 TraceValue,RF_TRCSELPID	    ; Only allow this PID
	  .else
	    mov	 ax,ERROR_TRC_PID_NON_EXISTENT	    ; PID not found
	  .endif

       .else					    ; Already PID tracing

; Tracing by PID is already occuring!  All we have to do is set the
; ptda_rasflag to the current value of TraceValue.
; We call scantasks to get the appropriate task and set the
; byte in the PTDA indicating that trace is also occuring for this PID
;	    bl - request
;	    bh - scan flags
;	    cx - PID		 (already set, passed by caller)
;	    di - offset of worker relative to caller's CS
;	    dl - value to place in PTDA Trace Variable

	  mov  bx,TK_TG_ONE			    ; Scan specific task
	  MOVFAROFFSET di,SetOnePid,RASSWAPCODE	    ; worker
	  mov  dl,TraceValue			    ; Tracing On
	  CALLFAR ScanTasks
	  Assume es:nothing
	  DosContext ds

	 .if  nc				    ; ERROR?
	   xor	ax,ax				    ; NO, indicate such
	 .else
	   mov	ax,ERROR_TRC_PID_NON_EXISTENT	    ; PID not found
	 .endif

       .endif


;  Update the RAS system status flags

       mov  bl,system_status
       mov  ras_systr_flags,bl			    ; Update status flags

       LeaveProc
       ret					    ; Return

EndProc	 PIDTraceOn



;****************************************************************************
;  This is where ScanTasks gives control if the specified PId is Found
;  (or if a request is made to scan all tasks).
;
;  Entry:
;	  ES - points to the  PTDA of the requested PID.
;	  DL - is set up by caller of scan task
;	       This is the value to be placed
;	       in the trace ptda variable
;
;  Exit:  Carry clear to indicate success
;
;  EFFECTS: Flags
;

	ASSUME	DS:NOTHING,ES:TASKAREA,SS:TASKAREA

Procedure SetOnePid,faronly
      mov  es:ptda_rasflag,dl		      ; Set the trace variable
      clc				      ; No error
      ret				      ; Pid set, return
EndProc	 SetOnePid

BREAK	<PIDTraceOnAll - Trace All PIDs>

;/********************** START OF SPECIFICATIONS *********************
;/*
;/* SUBROUTINE NAME: PIDTraceOnAll
;/*
;/* DESCRIPTIVE NAME: Enable Ras Tracing for all PIDs
;/*
;/* FUNCTION:	 This request enables tracing for all current and
;/*		 future PIDs. In essence this disables tracing by
;/*		 PID.
;/*
;/* NOTE:  TraceValue indicates what values are placed in the trace
;/*	   buffer.  TraceValue will always have a value of either
;/*	   0 or 0xFF depending on what type of PID tracing is occuring
;/*
;/* ENTRY POINT: PIDTraceOnALL
;/*    LINKAGE:	 Call near from HIGH4CODE (local)
;/*
;/* INPUT:  DS - DOSGROUP
;/*	    Caller must have ownership of Ras Semaphore
;/*
;/* EXIT-NORMAL: AX = 0
;/*
;/* EXIT-ERROR:	 AX = error_trc_pid_non_existent
;/*
;/* EFFECTS:
;/*	Uses: AX, BX, DX, DI, ES, Flags
;/*
;/* INTERNAL REFERENCES:
;/*    ROUTINES: None
;/*
;/* EXTERNAL REFERENCES:
;/*    ROUTINES:	  ScanTasks
;/*********************** END OF SPECIFICATIONS **********************

Procedure PIDTraceOnAll,near,local
	assume ds:DOSGROUP, es:nothing

; This is a request to enable tracing for all PIDs

       LocalVar	 system_status,BYTE		    ; system flags
       EnterProc

; First save the current system trace status flags and
; then pause tracing until this operation is performed

       mov  al,ras_systr_flags			    ; Copy current flags
       mov  system_status,al			    ; save flags
       or   ras_systr_flags,RF_TRCPAUSED	    ; Pause til done

; Test to see if we are tracing by PID,	 If we are then reset all
; of the PIDs.  If we are not tracing by PID, there is not need to perform
; an operation.

       xor  ax,ax				    ; Set error code
       test system_status,RF_TRCPID		    ; PID tracing?
       .if nz					    ;

; Now we call scantasks to set the trace variable byte in
; each PTDA indicating that trace is occuring for all PIDs
;	    bl - request
;	    bh - scan flags
;	    di - offset of worker relative to caller's CS
;	    dl - value to place in each PTDA trace variable

	 mov  bx,TK_TG_ALL			    ; YES, scan all tasks
	 MOVFAROFFSET di,SetOnePid,RASSWAPCODE	    ; worker
	 mov  dl,(not RF_TRCSELPID) and 0ffh	    ; Not selective tracing
	 CALLFAR ScanTasks
	 assume es:nothing
	 DosContext ds

; Since we scanned all Tasks, we should never get an error, but just in
; case, the condition is handled.

	 .if  nc				    ; ERROR?

; Indicate that we are no longer tracing by specific PID and set the trace
; variables to indicate all PIDs can enter the trace buffer
; TraceValue is set to zero and ptda_rasflag in all PTDAs are set to zero
; therefore all trace events will enter the trace buffer.

	   and	system_status,not RF_TRCPID	    ; Tracing by PID OFF
	   mov	TraceValue,(not RF_TRCSELPID) and 0ffffh    ; All PIDs in
	   xor	ax,ax				    ; NO error, indicate such
	 .else
	   mov	ax,ERROR_TRC_PID_NON_EXISTENT	    ; YES, error
	 .endif					    ; end error from ScanTasks
       .endif					    ; end Tracing by PID

;  Update the RAS system status flags

       mov  bl,system_status
       mov  ras_systr_flags,bl			    ; Update status flags

       LeaveProc
       ret					    ; Return

EndProc	 PIDTraceOnAll

BREAK	<PIDTraceOff - Disable Tracing for specified PID>

;/********************** START OF SPECIFICATIONS *********************
;/*
;/* SUBROUTINE NAME: PIDTraceOff
;/*
;/* DESCRIPTIVE NAME: Disable Ras Tracing for a specified PID
;/*
;/* FUNCTION:	 This request disables tracing for a specified
;/*		 PID.  If tracing by PID is not currently occuring,
;/*		 tracing by PID is activated and the specified
;/*		 PID is disabled.  If a caller specifies a PID which
;/*		 is non-existent, an error (error_trc_pid_non_existent)
;/*		 is returned to the caller.
;/*
;/* NOTE:  TraceValue indicates what values are placed in the trace
;/*	   buffer.  TraceValue will always have a value of either
;/*	   0 or 0xFF depending on what type of PID tracing is occuring
;/*
;/* ENTRY POINT: PIDTraceOff
;/*    LINKAGE:	 Call near from HIGH4CODE (local)
;/*
;/* INPUT:  DS - DOSGROUP
;/*	    CX - Pid to turn off
;/*	    Caller must have ownership of Ras Semaphore
;/*
;/* EXIT-NORMAL: AX = 0
;/*
;/* EXIT-ERROR:	 AX = error_trc_pid_non_existent
;/*
;/* EFFECTS:
;/*	Uses: AX, BX, DX, DI, ES, Flags
;/*
;/* INTERNAL REFERENCES:
;/*    ROUTINES: None
;/*
;/* EXTERNAL REFERENCES:
;/*    ROUTINES:	   ScanTasks
;/*********************** END OF SPECIFICATIONS **********************

Procedure PIDTraceOff,near,local
       assume ds:DOSGROUP, es:nothing

       LocalVar	 system_status,BYTE		    ; system flags
       EnterProc

; This is a request to disable a specific PID

; First save the current system trace status flags and
; then pause tracing until this operation is performed

       mov  al,ras_systr_flags			    ; Copy current flags
       mov  system_status,al			    ; save flags
       or   ras_systr_flags,RF_TRCPAUSED	    ; Pause til done

; NOTE: TraceValue controls what PIDs are allowed to be placed in the
; trace buffer.  A record is added if ptda_rasflag = TraceValue
; We simply place the opposite value of TraceValue in the ptda_rasflag and
; indicate trace by PID is occuring.  By placing the opposite value
; of TraceValue in the ptda_rasflag, this PID is not traced.



; We call scantasks to get the appropriate task and set the
; byte in the PTDA indicating that trace is not occuring for that PID only
;	    bl - request
;	    bh - scan flags
;	    cx - PID		 (already set, passed by caller)
;	    di - offset of worker relative to caller's CS
;	    dl - value to place in PTDA Trace Variable

	mov  bx,TK_TG_ONE			  ; Scan specific task
	MOVFAROFFSET di,SetOnePid,RASSWAPCODE	  ; worker
	mov  dl,TraceValue			  ; Trace Selective PID
	not  dl					  ; opposite TraceValue
	CALLFAR ScanTasks
	Assume es:nothing
	DosContext ds

	.if  nc					  ; ERROR?
	  xor  ax,ax				  ; NO, indicate such
	  or   system_status,RF_TRCPID		  ; Tracing by PID
	.else
	  mov  ax,ERROR_TRC_PID_NON_EXISTENT	  ; PID not found
	.endif


;  Update the RAS system status flags

       mov  bl,system_status
       mov  ras_systr_flags,bl			    ; Update status flags

       LeaveProc
       ret					    ; Return

EndProc	 PIDTraceOff

BREAK	<PIDTraceOffAll - Disable all PIDs from being traced>


;/********************** START OF SPECIFICATIONS *********************
;/*
;/* SUBROUTINE NAME: PIDTraceOffAll
;/*
;/* DESCRIPTIVE NAME: Disable Tracing for all PIDs
;/*
;/* FUNCTION:	 This request disables all PIDs from being traced.
;/*		 This essentially suspends tracing until a request
;/*		 to trace by PID is received.
;/*
;/* NOTE:  TraceValue indicates what values are placed in the trace
;/*	   buffer.  TraceValue will always have a value of either
;/*	   0 or 0xFF depending on what type of PID tracing is occuring
;/*
;/* ENTRY POINT: PIDTraceOffAll
;/*    LINKAGE:	 Call near from HIGH4CODE (local)
;/*
;/* INPUT:  DS - DOSGROUP
;/*	    Caller must have ownership of Ras Semaphore
;/*
;/* EXIT-NORMAL: AX = 0
;/*
;/* EXIT-ERROR:	 AX = error_trc_pid_non_existent
;/*
;/* EFFECTS:
;/*	Uses: AX, BX, DX, DI, ES, Flags
;/*
;/* INTERNAL REFERENCES:
;/*    ROUTINES: None
;/*
;/* EXTERNAL REFERENCES:
;/*    ROUTINES:	   ScanTasks
;/*********************** END OF SPECIFICATIONS **********************

Procedure PIDTraceOffAll,near,local
	assume ds:DOSGROUP, es:nothing

; This is a request to disable all PIDs from tracing

       LocalVar	 system_status,BYTE		    ; system flags
       EnterProc

; First save the current system trace status flags and
; then pause tracing until this operation is performed

       mov  al,ras_systr_flags			    ; Copy current flags
       mov  system_status,al			    ; save flags
       or   ras_systr_flags,RF_TRCPAUSED	    ; Pause til done

;  Check to see if Tracing by PID is occuring.  If it is not, then
;  we know all ptda_rasflag(s) contain a value of zero.  Therefore
;  we simply place a 0xFF in TraceValue and indicate Tracing by PID

       xor  ax,ax				    ; Set error code
       test system_status,RF_TRCPID		    ; PID tracing?
       .if nz					    ;


; Now we call scantasks to set the trace variable byte in
; each PTDA indicating that trace is disabled for all PIDs
;	    bl - request
;	    bh - scan flags
;	    di - offset of worker relative to caller's CS
;	    dl - value to place in each PTDA trace variable

	 mov  bx,TK_TG_ALL			    ; YES, Scan All tasks
	 MOVFAROFFSET di,SetOnePid,RASSWAPCODE	    ; worker
	 mov  dl,(not RF_TRCSELPID) and 0ffh	    ; Trace value
	 CALLFAR ScanTasks
	 assume es:nothing
	 DosContext ds

; Since we scanned all Tasks, we should never get an error, but just in
; case, the condition is handled.

	 .if  nc				    ; ERROR?

; Indicate that we are tracing by specific PID and set the trace
; variables to indicate such.  Even though we are tracing NO pids,
; this indicates we are tracing by PID, but no PIDs will enter the
; trace buffer.

	   or  system_status,RF_TRCPID		    ; No, Tracing by PID ON
	   mov	TraceValue,RF_TRCSELPID		    ; Set value
 
; 96020- Add ending time stamp to STDA structure.  May be changed by succesive
; suspend/resume sequences, TRACE OFF command, error count hit, or (this case)
; turning off all PID tracing.
         call  SetEndTimeStamp    ;  96020
	   xor	ax,ax				    ; NO error, indicate such
	 .else
	   mov	ax,ERROR_TRC_PID_NON_EXISTENT	    ; yes, error
	 .endif					    ; end error from ScanTasks

       .else					    ; not tracing by PID
	 or  system_status,RF_TRCPID		    ; Tracing by PID ON
	 mov  TraceValue,RF_TRCSELPID		    ; Set value
       .endif

;  Update the RAS system status flags

       mov  bl,system_status
       mov  ras_systr_flags,bl			    ; Update status flags

       LeaveProc
       ret					    ; Return

EndProc	 PIDTraceOffAll

BREAK	<SetRasSem - Set the RAS Ram Semaphore >


;/********************** START OF SPECIFICATIONS *********************
;/*
;/* SUBROUTINE NAME: SetRasSem
;/*
;/* DESCRIPTIVE NAME: Set the RAS system Semaphore
;/*
;/* FUNCTION:	 This procedure will grab the RAS RAM semaphore
;/*
;/* ENTRY POINT: SetRasSem
;/*    LINKAGE:	 Call near from HIGH4CODE (local)
;/*
;/* INPUT:	 None
;/*
;/* EXIT-NORMAL: RAS Semaphore is grabbed
;/*
;/* EXIT-ERROR:	 None
;/*
;/* EFFECTS:
;/*	Uses: DS, ES, Flags
;/*
;/* INTERNAL REFERENCES:
;/*    ROUTINES: None
;/*
;/* EXTERNAL REFERENCES:
;/*    ROUTINES:	   SemRequest
;/*********************** END OF SPECIFICATIONS **********************

Procedure SetRasSem,hybrid,local
	assume ds:Nothing, es:nothing

; Grab the Ras Ram Semaphore and wait until it is cleared.  There
; is no time out value

    pusha
    mov	    ax,DOSGROUP			    ; Ras Semaphore
    mov	    bx,offset DOSGROUP:ras_update_vars
    mov	    di,-1				    ; No timeout
    mov	    cx,di
    CALLFAR SemRequest		       ; SemRequest(ax:bx=dword,di:cx=timeout)
    popa

    ret						 ; Return

EndProc	 SetRasSem

BREAK	<FreeRasSem - Free the RAS Ram Semaphore >


;/********************** START OF SPECIFICATIONS *********************
;/*
;/* SUBROUTINE NAME: FreeRasSem
;/*
;/* DESCRIPTIVE NAME: Free the Ras Ram Semaphore
;/*
;/* FUNCTION:	 This procedure will free the RAS RAM semaphore
;/*
;/* ENTRY POINT: FreeRasSem
;/*    LINKAGE:	 Call near from HIGH4CODE (local)
;/*
;/* INPUT:	 None
;/*
;/* EXIT-NORMAL: RAS Semaphore is freed
;/*
;/* EXIT-ERROR:	 None
;/*
;/* EFFECTS:
;/*	Uses: DS, ES, Flags
;/*
;/* INTERNAL REFERENCES:
;/*    ROUTINES: None
;/*
;/* EXTERNAL REFERENCES:
;/*    ROUTINES:	   SemClear
;/*********************** END OF SPECIFICATIONS **********************

Procedure FreeRasSem,hybrid,local
	assume ds:nothing, es:nothing

; Free the Ras Ram Semaphore

    pusha
    mov	    ax,DOSGROUP
    mov	    bx,offset DOSGROUP:ras_update_vars
    CALLFAR SemClear			     ; SemClear(ax:bx=dword)
    popa

    ret						 ; Return

EndProc	 FreeRasSem

endif ;RAS

BREAK	<w_GetSTDA - Copy STDA To User's Buffer (worker)>
;/********************** START OF SPECIFICATIONS *********************
;/*
;/* SUBROUTINE NAME: w_GetSTDA
;/*
;/* DESCRIPTIVE NAME: Copy STDA to user's buffer
;/*
;/* FUNCTION:	 To copy the System Trace Data Area segment to
;/*		   a user's buffer
;/*
;/* NOTES:	 DosGetSTDA runs in protected mode under the caller's
;/*		   thread, in Kernel Mode, Ring 0.
;/*
;/* ENTRY POINT: w_GetSTDA
;/*    LINKAGE:	 Call near from HIGH4CODE
;/*
;/* INPUT:
;/*		 CX    = size of the user's buffer
;/*		 BX:DI = address of the user's buffer
;/*
;/* EXIT-NORMAL: CF = 0
;/*		 AX = 0
;/*
;/* EXIT-ERROR:	 CF = 1
;/*		 AX = error code:
;/*			error_system_trace
;/*
;/* EFFECTS:
;/*	Uses: AX, DS, ES, Flags
;/*
;/* INTERNAL REFERENCES: SetRasSem, FreeRasSem
;/*
;/* EXTERNAL REFERENCES: SuBuff
;/*
;/*********************** END OF SPECIFICATIONS **********************


if RAS
        ReferGlobal ras_stda_addr,WORD
endif

        Assume ds:nothing, es:nothing

        Procedure w_GetSTDA,HYBRID

if RAS
	LocalVar  user_buff,DWORD	      ; BX:DI -> User Targer Buffer
	LocalVar  error_code,WORD
	LocalVar  system_status,BYTE
	EnterProc  <bx,di,0,0>		      ;	 Initialize error code



	DosContext ds
	pusha

;	See if System Trace is active

	mov	ax,ras_stda_addr	      ; pick up STDA segment address
	.if	<ax eq 0>
	  mov	error_code,ERROR_SYSTEM_TRACE ; System Trace is not active
	.else

;  Since we will temporarily be modifying the RAS System flags, we
;  must wait until it is safe to do so

	  CALLFAR  SetRasSem
	  Assume ds:nothing, es:nothing

; Temporarily pause tracing to prevent the trace pointers from being
; updated during the time the trace buffer is copied

	  DosContext ds
	  mov	 bl,ras_systr_flags	      ; get system flags
	  mov	 system_status,bl	      ; save status
	  or	 ras_systr_flags,RF_TRCPAUSED ; pause tracing

;	  Calculate the number of bytes to copy

	  LOADSL bx,ax		      ; get limit of STDA segment
	  .if	<cx eq 0>	      ; bad size
	    mov	  error_code,ERROR_SYSTEM_TRACE ; Can't move to a zero buffer
	  .else			      ; good buffer size
	    dec	  cx			; adjust buffer size
	    .if	  <bx b cx>
	      mov cx,bx			; STDA is smaller than buffer
	    .endif
	    inc	  cx			; adjust length for first word

;	    Copy the data from the STDA to the user's buffer

	    mov	  ds,ax			; point to STDA, Kernel Buffer
	    assume ds:nothing
	    mov	  bx,user_buff.Segmt	; BX:DI -> User Target buffer
	    mov	  di,user_buff.Offst
	    xor	  si,si			; set up source pointer
	    cld				; insure direction flag clear

;*****************************************************************************
;
; Call SuBuff to move the trace buffer to user area
;
;	ENTRY	DS:SI -> pointer to source buffer
;		BX:DI -> target buffer
;		CX    =	 number of bytes to copy
;
;*****************************************************************************


	    CALLFAR SuBuff		  ; let SuBuff to the move
	    Assume ds:nothing, es:nothing

; check for and error from subuff and set appropriate error

	    .if <c>			   ; if error from Subuff
	      mov   error_code,ERROR_SYSTEM_TRACE ; System Trace is not active
	    .else			   ; no error
	      DosContext DS
	      call  ClearRasTrace	   ; Clear Trace Buffer
	    .endif			   ; no error from SuBuff

	  .endif			   ; zero buffer

	  DosContext ds
	  mov	bl,system_status	   ; restore system status
	  mov	ras_systr_flags,bl	   ; flags restored

;  The RAS flags have been restored, now it is OK to release the semaphore

	  CALLFAR  FreeRasSem		   ; Free the semaphore
	  Assume ds:nothing, es:nothing

	.endif				   ; system trace not active

	popa				   ; restore the registers

	mov  ax,error_code		   ; error code
	cmp  ax,1			   ; set carry if AX = zero
	cmc				   ; set carry if AX non zero


;	Return to the caller

	LeaveProc
	ret

else ;RAS
        mov  ax,ERROR_SYSTEM_TRACE
        cmc
        ret

endif ;RAS

EndProc w_GetSTDA



RASSWAPCODE  ENDS

        END
