;       SCCSID = @(#)rasstrp.asm	6.4 91/11/13
; ****************************************************************************
; *                                                                          *
; *                       IBM/Microsoft Confidential                         *
; *                                                                          *
; *                 Copyright (c) IBM Corporation  1987, 1990                *
; *                 Copyright (c) Microsoft Corp.  1987, 1990                *
; *                           All Rights Reserved                            *
; *                                                                          *
; ****************************************************************************
;

                PAGE    ,132;
        TITLE RASSTRP - System Trace Kernel Trace Routines

;************************* START OF SPECIFICATIONS *****************
;
;     SOURCE FILE NAME: RASSTRP
;
;     DESCRIPTIVE NAME: RAS System Trace Resident Program
;
;     FUNCTION:  Handles placing trace data into the system
;                trace buffer.  This can occur through the
;                use of static trace points or dynamic trace
;                points.  The entry - K_F_Systrace is used by
;                the Dynamic Trace Interpreter to place records in
;                the trace buffer.
;     CHANGES:
;       96020-11/28/94-will always timestamp records
;
;
;     RESTRICTIONS:   This routine should never block
;
;************************** END OF SPECIFICATIONS ******************

        .XLIST
  include dosseg.inc                             ; MUST be first include
  include defdbug.inc
  include basemaca.inc
  include osmaca.inc
  include error.inc
  include struc.inc
  include mi.inc
  include pmode.inc
  include infoseg.inc
  include kmode.inc
  include sysentry.inc
  include ordinals.inc
  include tcbdata.inc
  include systrace.inc
        .LIST
.sall


if RAS

  ReferTask Pid,WORD
  ReferTask ptda_rasflag,BYTE

  ReferGlobal InterruptLevel,BYTE
  ReferGlobal TaskData,WORD
  ReferGlobal ras_min_table,WORD

  EXTRN     SISData:WORD
  EXTRNFAR  FuBuff

 PUBLIC w_systrace,K_T_Systrace,K_S_Systrace
 PUBLIC K_F_Systrace

 PUBLIC ras_mec_table,ras_systr_flags,ras_stda_addr,ras_stda_phys
 PUBLIC TraceValue

 PUBLIC _RASselSTDA

 PUBLIC ras_stda_addr
endif

CONSTANTS SEGMENT

if RAS

  ras_mec_table    db 32 dup(0) ; Kernel Major Event Code Table
  ras_systr_flags  db 0         ; Tracing Flags
                                ; See: Systrace Include for definitions

  _RASselSTDA   LABEL   WORD    ; C label - RAS selector to STDA.
  ras_stda_addr    dw 0         ; STDA Selector
  ras_stda_phys    dw 0         ;
  TraceValue       db 0         ; Value allowed to be traced (PID tracing)



  record_header  stda_rec_header<> ; Header for each trace record

endif ; RAS

CONSTANTS ENDS

BREAK   <w_Systrace - Add trace event for ring 2 or 3>

     FARCODE HIGH4
RASLOCKCODE SEGMENT
PUBLIC strp_common                    ; Public for Dekko Card

       ASSUME es:nothing,ds:nothing
       Dos_Group_selector dw DOSGROUP ; Kernel Data Segment

;**************** START OF SPECIFICATIONS ******************************
;*
;* SUBROUTINE NAME:  w_Systrace
;*
;* DESCRIPTIVE NAME: Test major event code and record data in Buffer.
;*                   Static Trace Entry Point
;*
;* FUNCTION: Test major event code.  If the major code and
;*           corresponding minor code is "ON",  then the trace
;*           data is added to the trace buffer.
;*
;* NOTES:
;*           1.  This entry point is worker routine for DosSystrace
;*           2.  If the trace code is "busy", the caller will receive
;*               trace not available return code.
;*           3.  Various other checks are done by this module
;*               which could prevent an event from being placed
;*               in the buffer:
;*                 - If tracing is suspended
;*                 - If tracing by PID and the current
;*                   PID is not being traced.
;*
;* ENTRY POINT:  w_Systrace
;*    LINKAGE:   CALL near from HIGH4CODE segment
;*
;* INPUT: AX =  major event code
;*        BX =  length of user data
;*        DX =  minor event code
;*     DS:SI -> address of user data
;*
;* EXIT-NORMAL: Carry flag = 0
;*                  System Trace Data Area Modified
;*
;* EXIT-ERROR: Carry flag = 1
;*
;* EFFECTS:
;*     Uses: AX, ES, Flags
;*
;* EXTERNAL REFERENCES: FuBuff
;**************** END OF SPECIFICATIONS ********************************

Procedure w_systrace,HYBRID

if RAS

  push 0                             ; Insure ES doesn't cause GP
  pop  es
  assume es:nothing

  call NEAR PTR testrecord           ; Test major code/record data
  .if c                              ; ERROR?
    mov ax,ERROR_SYSTEM_TRACE        ; YES, set up ax with error
  .endif

else ;RAS

strp_common:

endif ;RAS

  ret

EndProc  w_systrace

if RAS

BREAK   <traceentry - Standard entry, save registers etc>
;**************** START OF SPECIFICATIONS ******************************
;*
;* SUBROUTINE NAME: traceentry                              (STRP)
;*
;* DESCRIPTIVE NAME: Macro used for each entry point into testrecord
;*
;* FUNCTION: Saves all general registers, DS and ES.  Sets up the caller
;*           type (API or kernel), and sets up DS to point to DosGroup
;*
;* ENTRY POINT: traceentry
;*    LINKAGE: macro with parameter F
;*
;* INPUT: F = the initialized flags with the correct caller type set up
;*               bit 0 = 0 - kernel caller
;*                       1 - API caller
;*               bit 1 = 0 - a time stamp exists
;*                       1 - no time stamp exists - 96020 always timestamps
;*               bit 2 = 0 - undefined
;*                       1 - current mode is protect
;*               bit 3 = 0 - Static Trace point
;*                       1 - Dynamic Trace point
;*               bit 4 = 0 - Record complete
;*                       1 - Dynamic Trace error, record incomplete
;*
;* EXIT-NORMAL: DS pointing to kernel global data segment (DOSGROUP),
;*              all general registers, DS, and ES saved on the stack, and
;*              trace flags set up in AH
;*
;* EXIT-ERROR: NONE
;*
;* EFFECTS: MUST use TraceExit upon leaving
;/*    Uses: AH, DS
;**************** END OF SPECIFICATIONS ********************************


; Internal macro to save general registers, set up caller type, save segment
; register and set it up for the kernel global data group

traceentry MACRO num
  pusha
  mov ah,num                         ; Caller type
  push ds
  mov ds,cs:Dos_Group_selector       ; DS -> DOSGROUP
  push es
 ASSUME ds:DOSGROUP
endm

BREAK   <tracebasicexit - Basic exit, restore registers, etc>
;**************** START OF SPECIFICATIONS ******************************
;*
;* SUBROUTINE NAME: tracebasicexit                          (STRP)
;*
;* DESCRIPTIVE NAME: Macro to be used prior to exit from testrecord
;*
;* FUNCTION: Restores registers saved by Traceentry.
;*
;* NOTES:
;*
;* ENTRY POINT: tracebasicexit
;*    LINKAGE: macro with no parameters
;*
;* INPUT: none
;*
;* EXIT-NORMAL: general registers, DS, and ES are restored
;*              and a return near done (no true exit for this macro)
;*
;* EXIT-ERROR: NONE
;*
;* EFFECTS:
;*          prior to traceentry macro being used.
;**************** END OF SPECIFICATIONS ********************************

; Restore Registers and Return

tracebasicexit MACRO
  pop es
  pop ds
  popa
  ret
endm


BREAK   <movekerneldata - Move kernel caller data to buffer>

;**************** START OF SPECIFICATIONS ******************************
;*
;* SUBROUTINE NAME: movekerneldata                          (STRP)
;*
;* DESCRIPTIVE NAME: Macro to move passed data to Trace Circular Buffer
;*                   for kernel callers
;*
;* FUNCTION: Moves passed data to the System Trace Circular Buffer,
;*           taking into account a possible wrap and updating a passed
;*           pointer to the current byte of the Buffer appropriately.
;*
;* NOTES:
;*
;* ENTRY POINT: movekerneldata
;*    LINKAGE: macro with no parameters
;*
;* INPUT: DS:SI -> data to move
;*           BX =  size of data to be moved
;*        ES:DI -> Next available byte in the trace buffer
;*
;* EXIT-NORMAL: ES:DI -> Point to next available byte in trace buffer
;*              System Trace data area modified
;*
;* EXIT-ERROR: NONE
;*
;* EFFECTS:
;*    Uses: BX, CX, DI, SI, Flags
;*
;**************** END OF SPECIFICATIONS ********************************

movekerneldata MACRO

; Calculate if wrap might occur

  mov cx,es:stda_end_buffer          ; get end_ptr
  sub cx,di                          ; # of bytes left - 1
  cld

; Determine if two moves needed because Wrap will occur

  .if <bx a cx>                      ; check for wrap and two moves
    inc cx                           ; bytes left in buffer
    sub bx,cx                        ; remaining # of bytes after this
    rep movs es:BYTE PTR[di],ds:[si] ; move to end of buffer cx bytes
    mov di,es:stda_start_buffer      ; es:di -> start of trace buffer
  .endif

; Move all or remaining bytes to Circular Buffer and return (also, "rep"
; instruction will handle if no data is left to be moved as its first check)

  mov cx,bx                          ; remaining bytes to move
  rep movs es:BYTE PTR[di],ds:[si]   ; move all, rest,or no data (cx bytes)
endm

BREAK   <getapibuf - Move ring 3 data to buffer>

;**************** START OF SPECIFICATIONS ******************************
;*
;* SUBROUTINE NAME: getapibuf                               (STRP)
;*
;* DESCRIPTIVE NAME: Macro to do the actual movement of data from an
;*                   API's buffer to the Trace Circular Buffer using
;*                   FuBuff.
;*
;* FUNCTION: Moves passed data to the System Trace Circular Buffer
;*
;* NOTES:
;*
;* ENTRY POINT: getapibuf
;*    LINKAGE:  macro with no parameters
;*
;* INPUT:    SI = offset of data to move
;*           CX = size of data to be moved
;*        ES:DI -> Next available byte in trace buffer
;*
;* EXIT-NORMAL: ES:DI -> Next available byte in Trace Buffer
;*              System Trace Data Area is modified
;*
;* EXIT-ERROR: NONE
;*
;* EFFECTS:
;*    Uses: CX, DI, SI, Flags
;*
;* EXTERNAL REFERENCES: FuBuff
;**************** END OF SPECIFICATIONS ********************************

getapibuf MACRO

; Save registers effected

 push ax
 push bx
 push ds
 push es

; Point to the API caller's buffer

 mov bx,[bp+2]                            ; Saved on Stack

; Call FuBuff to move the data into the Trace Circular Buffer and do
; the necessary setup if a General Protection Fault occurs with accessing
; the API's buffer

 CALLFAR FuBuff

; Restore registers

 pop es
 pop ds
 pop bx
 pop ax

; Check if General Protection Fault occured moving the API caller's data

 .if C                               ;ERROR

   or ds:ras_systr_flags,RF_TRCAVAIL ; make trace available
   stc                               ; Indicate error
   tracebasicexit                    ; Return to caller

 .endif

endm

BREAK   <moveapidata - move ring 3 data to buffer>

;**************** START OF SPECIFICATIONS ******************************
;*
;* SUBROUTINE NAME: moveapidata                             (STRP)
;*
;* DESCRIPTIVE NAME: Macro to move passed data to Trace Circular Buffer
;*                   for API callers
;*
;* FUNCTION: Moves passed data to the System Trace Circular Buffer,
;*           taking into account a possible wrap and updating a passed
;*           pointer to the current byte of the Buffer appropriately.
;*
;* NOTES:
;*
;* ENTRY POINT: moveapidata
;*    LINKAGE: macro with no parameters
;*
;* INPUT:    SI = offset of data to move
;*                (BX is set to the selector of the data later in code)
;*           BX = size of data to be moved
;*        ES:DI -> Next available byte in the trace buffer
;*
;* EXIT-NORMAL: ES:DI -> Next available byte in the trace buffer
;*              System Trace Data Area Modified
;*
;* EXIT-ERROR: NONE
;*
;* EFFECTS:
;*    Uses: BX, CX, DI, SI, Flags
;**************** END OF SPECIFICATIONS ********************************


moveapidata MACRO

; calculate if wrap might occur

  mov cx,es:stda_end_buffer          ; get end_ptr
  sub cx,di                          ; # of bytes left - 1

; Determine if two moves needed because Wrap will occur

  .if <bx a cx>                      ; If this request will fill up buffer
                                     ; do 2 moves
    inc cx                           ; Bytes left in buffer
    sub bx,cx                        ; remaining # of bytes after this
    getapibuf                        ; move to end of buffer cx bytes
    mov di,es:stda_start_buffer      ; es:di -> Start of trace buffer
  .endif

; Move all or remaining bytes to Circular Buffer and return (also, "rep"
; instruction will handle if no data is left to be moved as its first check)

  mov cx,bx                          ; Bytes left to move
  getapibuf                          ; move all, rest,or no data (cx bytes)
endm


BREAK   <K_T_Systrace - Check major code, add kernel data>

;**************** START OF SPECIFICATIONS ******************************
;*
;* SUBROUTINE NAME:  K_T_Systrace
;*
;* DESCRIPTIVE NAME: Test major event code and record data to Buffer.
;*
;* FUNCTION: Test major event code.  If the major code and
;*           corresponding minor code is "ON",  then the trace
;*           data is added to the trace buffer.
;*
;* NOTES:
;*           1.  This entry point is for kernel callers of static
;*               tracing.
;*           2.  If the trace code is "busy", the caller will
;*               receive trace not available.
;*           3.  Various other checks are done by this module
;*               which could prevent an event from being placed
;*               in the buffer:
;*                 - If tracing is suspended
;*                 - If tracing by PID and the current
;*                   PID is not being traced.
;*
;* ENTRY POINT:  K_T_Systrace, (testrecord from w_systrace)
;*    LINKAGE:   CALL near in HIGH4CODE segment
;*
;* INPUT: AL = major event code
;*        BX = length of user data
;*        DX = minor event code
;*     DS:SI -> address of user data
;*
;* EXIT-NORMAL: Carry flag = 0
;*              System Trace Data Area Modified
;*
;* EXIT-ERROR: Carry flag = 1
;*
;* EFFECTS:
;*     Uses: Flags
;*
;**************** END OF SPECIFICATIONS ********************************
;
Procedure K_T_Systrace,hybrid

  traceentry RF_KERNEL               ; kernel entry save registers
  jmp SHORT kernel_testrecord        ; skip API's worker entry point

testrecord:                          ; entry point from API worker routine
  traceentry RF_DYNLINK              ; API entry

kernel_testrecord:

; Set up and test major event code

  mov di,ax
  and di,00f8h                       ; major event code
  shr di,3                           ; divide to get BYTE # within mec table
  mov cl,al                          ; move original mec to shift register
  and cl,07h                         ; determine offset within array byte
  mov ch,80h                         ; initialize mask to first bit within byte
  shr ch,cl                          ; shift mask to correct bit position
  test ds:ras_mec_table[di],ch       ; zero flag indicates if event enabled
  .if z                              ; Event disabled?
    stc                              ; YES, set error flag
    tracebasicexit                   ; recover registers/fix stack and return
  .endif

; Major event code enabled - continue
  jmp SHORT strp_common              ; major event code is enabled

BREAK   <K_F_Systrace - Dynamic Trace entry point (treat as kernel)>

;**************** START OF SPECIFICATIONS ******************************
;*
;* SUBROUTINE NAME:  K_F_Systrace
;*
;* DESCRIPTIVE NAME: Record Data to Trace Buffer.
;*
;* FUNCTION: Data is placed in the system trace data buffer.
;*
;* NOTES:
;*           1.  This entry point is for the kernel code which
;*               handles dynamic tracing
;*           2.  If the trace code is "busy", the user will recieve
;*               trace not available.
;*           3.  No checking of minor codes is done.
;*           4.  Various other checks are done by this module
;*               which could prevent an event from being placed
;*               in the buffer:
;*                 - If tracing is suspended
;*                 - If tracing by PID and the current
;*                   PID is not being traced.
;*
;* ENTRY POINT:  K_F_Systrace
;*    LINKAGE:   CALL near from HIGH4CODE segment (far from all others)
;*
;* INPUT: AL = major event code
;*        AH = Flags  (See SysTrace include file for definition)
;*        BX = length of user data
;*        DX = minor event code
;*     DS:SI -> address of user data
;*
;* EXIT-NORMAL: Carry flag = 0
;*              System Trace Data Area Modified
;*
;* EXIT-ERROR: Carry flag = 1
;*
;* EFFECTS:
;*     Uses: Flags
;*
;**************** END OF SPECIFICATIONS ********************************

Entry K_F_Systrace,hybrid            ; Dynamic Trace entry skips test of MEC
  traceentry ah                      ; Flags stored in ah by Intrepreter
  jmp  SHORT strp_common


BREAK   <K_S_Systrace - Ship check, add kernel data to buffer >
;**************** START OF SPECIFICATIONS ******************************
;*
;* SUBROUTINE NAME:  K_S_Systrace
;*
;* DESCRIPTIVE NAME: Record data to Trace Buffer.
;*
;* FUNCTION: Check to see if minor code is enabled for this
;*           major code, if it is enabled,  then the trace
;*           data is added to the trace buffer.
;*
;* NOTES:
;*           1.  This entry point is for kernel callers of static
;*               tracing.
;*           2.  If the trace code is "busy",caller will receive
;*               trace not available.
;*           3.  Various other checks are done by this module
;*               which could prevent an event from being placed
;*               in the buffer:
;*                 - If tracing is suspended
;*                 - If tracing by PID and the current
;*                   PID is not being traced.
;*
;*           FS and GS must be preserved (DevHelp requirement)
;*
;* ENTRY POINT:  K_S_Systrace
;*    LINKAGE:   CALL near from HIGH4CODE segment (far from all other segs)
;*
;* INPUT: AL = major event code
;*        BX = length of user data
;*        DX = minor event code
;*     DS:SI = address of user data
;*
;* EXIT-NORMAL: Carry flag = 0
;*                  System Trace Data Area Modified
;*
;* EXIT-ERROR: Carry flag = 1
;*
;* EFFECTS:
;*     Uses: Flags
;*
;* INTERNAL REFERENCES:
;*
;* EXTERNAL REFERENCES: NONE
;**************** END OF SPECIFICATIONS ********************************

Procedure K_S_Systrace,hybrid             ; kernel entry, skips test of MEC
  traceentry RF_KERNEL                    ; kernel entry

; NOTE: The strp_common label is used by the Austin Performance group's
; Performance monitor to allow for an address which their device driver
; can jump to and overlay the code to do the performance tracing. Originally
; this label was used in ver. 1.0 and 1.1 to do the same type of thing for
; MMPH tracing, however, in 1.2 and 2.0 it had become  obsolete.
; It is now critical to the performance monitor as it is the only place
; the monitor knows to go to overlay code for intercepting trace info.

strp_common:                              ; Entry Point for Dekko device
                                          ; also, entry point from K_F_Systrace
                                          ; and from K_T_Systrace

; Check to see if tracing is paused, if so leave

  test ras_systr_flags,RF_TRCPAUSED       ; Check for pause
  .if nz                                  ; tracing is paused
      stc                                 ; paused, don't trace
      tracebasicexit                      ; leave now
  .endif

  mov cl,ras_systr_flags                  ; Get flags
  and cl,not RF_TRCAVAIL                  ; Set trace not available
  xchg ds:ras_systr_flags,cl              ;
  test cl,RF_TRCAVAIL
  .if z                                   ; Trace busy?
      stc                                 ; YES, indicate error
      tracebasicexit                      ; Leave now
  .endif


; Now check to see if static, minor code tracing is available

  test ras_systr_flags,RF_TRCMINORCD      ; Tracing by minor
  .if <nz>                                ; yes


     test  ah,RF_DYNTRC
     .if <z>                              ; Dynamic Trace record?
       push  ax                           ; NO, OK to check minor codes
       mov   ah,32                        ; Bytes per major code
       mul   ah                           ; ax = offset to major code
       mov   di,dx                        ; di = minor code
                                          ; only lower two bytes count
       and   di,00f8h                     ; ignore lower bits
       shr   di,3                         ; get byte within minor code
       mov   cl,dl
       and   cl,07h
       mov   ch,80h
       shr   ch,cl                        ; ch is bit to test
       add   di,ax                        ; add offset to correct major code
       mov   ax,ras_min_table
       mov   es,ax                        ; selector for minor code table
       test  es:[di],ch
       pop   ax
       .if  <z>
         or ds:ras_systr_flags,RF_TRCAVAIL ; make trace available
         stc                              ; minor code not traced
         tracebasicexit                   ; basic clean up and return near
       .endif
     .endif                               ; endif dynamic trace
  .endif                                  ; endif minor code tracing


strp_pid:


   mov bp,sp                               ;


; Now Get the Process ID and the Trace Flag from the PTDA.
; The following may occur:
;      1.  TASK Time:  Obtain the PID and Trace Flag from the PTDA
;      2.  Interrupt Time:  Neither the Trace Flag or PID can be obtained

   LOADAR cx,ss                          ; look for expand up (can't get pid)
   test ch,04h                           ; non-zero = expand down
   .if <nz> and                          ; Must be expand down and
   .if <InterruptLevel eq -1>            ; task time to get PID
     mov cx,ss:Pid                       ; Yes, Get Pid
     mov record_header.stda_rec_procid,cx
     mov cl,ss:ptda_rasflag              ; Get trace flag
   .else
     mov record_header.stda_rec_procid,0  ; Int time, No Pid association
     mov cl,1                             ; No Trace flag
   .endif


; Now check for to see if this PID is being traced
; The following may occur:
;    1. Tracing by PID is not active so all events are placed in the buffer
;    2. Tracing by PID is active
;       - Task Time - Check to see if this PID is being traced
;       - Interrupt Time - Don't place the record in the buffer because
;                          there is no PID associated with the event


   test  ras_systr_flags,RF_TRCPID
   .if  nz                                ; Tracing by PID
      .if <cl ne TraceValue> or           ; This Pid being traced?
      .if <InterruptLevel ne -1>          ; Interupt Time, No Pid
        or ds:ras_systr_flags,RF_TRCAVAIL ; make trace available
        stc                               ; NO, indicate error
        tracebasicexit                    ; basic clean up and return
      .endif
   .endif                                 ; end PID being traced


  .if <bx a RV_MAXVAR>                    ; size of data passed too big?
    mov bx,RV_MAXVAR                      ; YES, set max size
  .endif

strp_release_start:


; Set up for moving data/header and use default size of data if too large

  mov es,ds:ras_stda_addr                 ; es:0 -> start of Trace buffer
  assume es:nothing

  test  ah,RF_DYNTRC                      ; Dynamic Tracing?
  .if z
    or ah,RF_PROTECT                      ; NO, set flag to indicate protect
  .endif

  mov record_header.stda_rec_minor,dx     ; Minor code into header
  mov record_header.stda_rec_datalen,bx   ; save length of user data
  mov record_header.stda_rec_major,al     ; save major event code


  mov di,es:stda_current_offst            ; es:di -> Next avaiable byte

  .if <bx ne 0>  near                     ; Any user data?
    test ah,RF_DYNTRC                     ; Yes, Dynamic Trace record?
    jnz k1                                ; Yes, use kernel mover

; Check for a Dynlink or Kernel caller


    test ah,RF_DYNLINK                    ; Test API caller flag

    .if nz                                ; Dynalink Caller?
      moveapidata                         ; YES, move using FuBuff
    .else                                 ; Kernel caller
k1:   mov ds,[bp+2]                       ; ds -> caller's data
      assume ds:nothing
      movekerneldata                      ; Move kernel caller's data
    .endif                                ; API caller flag off

    mov ds,cs:Dos_Group_selector          ; ds -> DosGroup
  .endif

   assume ds:DOSGROUP

;set up trace record header
  mov cx,WORD PTR ds:SISData.SIS_SecTime  ; current time(low order bytes)
  xor bx,bx
  mov bl,SIZE record_header               ; set up size of trace record header
  mov si,OFFSET DOSGROUP:record_header    ; index to record header to be moved
; 96020 .if <record_header.stda_rec_time ne cx> ; New time?
  mov record_header.stda_rec_sechun,cx    ; save sec,hunds time in record  96020
  mov cx,WORD PTR ds:SISData.SIS_HrsTime  ; current time(high order bytes) 96020
  mov record_header.stda_rec_hrsmin,cx    ; save hrs, min time in record   96020
; 96020.else                                   ; time hasn't changed - skip it
; 96020  or ah,RF_NOTIME                       ; No time stamp in record
; 96020  sub bl,2                              ; two less bytes to move
; 96020  add si,2                              ; Skip time field
; 96020.endif

  mov record_header.stda_rec_flags,ah     ;indicate API or kernel caller

; Move header to Circular Buffer

  movekerneldata                          ; move record header to STDA

; Reset the buffer pointer to next available byte

  mov es:stda_current_offst,di            ; Save current point
  or ds:ras_systr_flags,RF_TRCAVAIL       ; Make trace available
  clc                                     ; good return code
  tracebasicexit                          ; exit

EndProc K_S_Systrace
EndProc K_T_Systrace


;       K_S_Systrace - far16 stub to near K_S_Systrace
;
;       It is not possible to change K_S_Systrace to far16 in
;       RASSTRP.ASM at the current time, due to the way it was coded.
;
;       ENTRY   See RASSTRP.ASM
;       EXIT    See RASSTRP.ASM
;       USES    See RASSTRP.ASM

Procedure       K_S_Systrace,far16
        call    K_S_Systrace
        RETP
EndProc K_S_Systrace

endif ;RAS

RASLOCKCODE ENDS


        END
