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

;       Performance hook include file
;

;
;   Dekko card memory mapped I/O address data area
;
DEKKO_ADDR  STRUC
RESV0       DD      ?               ; Reserved double word              +0
MAJMIN_CODE DW      ?               ; Major (hi) minor (lo) code        +4
RESV1       DW      ?               ; Reserved                          +6
PERF_DATA_4 DD      ?               ; Performance data 4 byte area      +8
PERF_DATA   DW      ?               ; Performance data 2 byte area      +C
DEKKO_ADDR  ENDS

LO_QUAD_WORD EQU    PERF_DATA_4     ; Offset to lo word of 4 byte data area
HI_QUAD_WORD EQU    PERF_DATA_4+2   ; Offset to hi word of 4 byte data area

;
;
;
PERFTRACE   EQU     1               ; Set for major code '01'
PERFBIT     EQU     40h             ; Bit for major code 1


; Definitions for the Dekko Card Configuration.  These equates are used
; to Query PS/2 POS and determine where the Dekko card is located

MAX_SLOTS   EQU       20H           ; Max number of slots for PS/2 (inflated)
START_SLOT  EQU        8h           ; Starting Slot - 1
PORT_SELECT EQU       96h           ; Query a POS slot number
CARD_ID     EQU      100h           ; Query POS DEKKO Card ID
DEKKO_ID    EQU    0EED7h           ; DEKKO ID
POS_BASE    EQU      102h           ; Query POS DEKKO Information

; The following equates represent how to use the bits returned from POS 102h
; to translate into a proper address
;
;        POS 102            Hex value         Address range
;        xxx0100x              08             C8000 - C9FFF
;        xxx0101x              0Ah            CA000 - CBFFF
;        xxx0110x              0Ch            CC000 - CDFFF
;        xxx0111x              0Eh            CE000 - CFFFF
;        xxx1000x              10h            D0000 - D1FFF
;        xxx1001x              12h            D2000 - D3FFF
;        xxx1010x              14h            D4000 - D5FFF
;        xxx1011x              16h            D6000 - D7FFF
;        xxx1100x              18h            D8000 - D9FFF
;        xxx1101x              1Ah            DA000 - DBFFF
;        xxx1110x              1Ch            DC000 - DDFFF
;        xxx1111x              1Eh            DE000 - DFFFF

DEKKO_MASK  EQU       1Eh           ; DEKKO Bits of interest
DEKKO_SLOTS EQU       0Ch           ; Number of Possible addresses for DEKKO
START_SLOT  EQU        8h           ; Starting Slot
DEKKO_START EQU    0c800h           ; Starting Segment for dekko
DEKKO_LIMIT EQU  (1024*2)-1         ; Limit for DEKKO GDT entry


TestTraceMM MACRO mec,SegReg
; macro to test if specified major code is currently enabled - return
; zero flag = zero if code is enabled or zero flag = 1 if disabled
; or System Tracing doesn't exist.
; This is used for Memory Mapped IO.  Since MMIO is conditional, it should
; never do an assume!

  .ERRB <mec>                     ;;assembler error if mec blank
  .ERRNZ mec LT 0 OR mec GT 255   ;;assembler error if mec out of range
;test if specified major code is currently enabled - return in zero flag
  test SegReg:SIS_mec_table+(mec SHR 3), 80h SHR (mec AND 7)
endm


;******************************************************************************
;
; SendAsDouble
;
;       Function: Moves the contents of the given 16 bit register to the quad
;                 area of the dekko card (reg -> lo word, 0 -> hi word). The
;                 card will ship the data when both words have been loaded.
;
;       Inputs  : ES is set to the dekko mapped memory
;                 LO - value to be loaded into the LO word of the quad
;                 HI - optional value to be loaded into the HI word of the
;                      quad. If not specified, defaults to zero.
;
;******************************************************************************

SendAsDouble    MACRO   LO,HI
               .ERRB   <LO>                             ; Error if LO blank

                mov     WORD PTR es:[LO_QUAD_WORD],LO   ; load lo word of quad

                IFB    <HI>                             ; No HI parameter ?
                mov     WORD PTR es:[HI_QUAD_WORD],0    ; load 0 into hi word
                ELSE
                mov     WORD PTR es:[HI_QUAD_WORD],HI   ; load hi word of quad
                ENDIF
                ENDM

;******************************************************************************
;
; SendDouble
;
;       Function: Moves the contents of the given 16 bit register to the quad
;                 area of the dekko card (reg -> lo word, 0 -> hi word). The
;                 card will ship the data when both words have been loaded.
;
;       NOTE    : This macro differs from SendAsDouble in that it uses the
;                 FS register to contain the segment of the dekko mapped
;                 memory. Used by DevHelp hooks
;
;       Inputs  : FS is set to the dekko mapped memory
;                 LO - value to be loaded into the LO word of the quad
;                 HI - optional value to be loaded into the HI word of the
;                      quad. If not specified, defaults to zero.
;
;******************************************************************************

SendDouble      MACRO   LO,HI
               .ERRB   <LO>                             ; Error if LO blank

                mov     WORD PTR fs:[LO_QUAD_WORD],LO   ; load lo word of quad

                IFB    <HI>                             ; No HI parameter ?
                mov     WORD PTR fs:[HI_QUAD_WORD],0    ; load 0 into hi word
                ELSE
                mov     WORD PTR fs:[HI_QUAD_WORD],HI   ; load hi word of quad
                ENDIF
                ENDM

;******************************************************************************
;
; SendCarryFlag
;
;       Function: Sends a 1 or a 0 to the +C offset of the dekko card based
;                 on the current value of the CF flag. This macro is used
;                 ONLY in the DevHelp Hooks
;
;       Inputs  : FS is set to the dekko mapped memory
;                 The flags are on the top of the stack
;
; 09/19: MHW -  Added <ext> parm to allow quad writes of carry flag
;
;******************************************************************************

SendCarryFlag   MACRO   lab,ext
               .ERRB   <lab>                        ; error if no label
                popf                                ; restore flag values
                jc      scf1&lab                    ; jmp if CF=1

                mov     fs:[PERF_DATA&ext],0        ; DEKKO: %w/%d=0
                jmp     scf2&lab
    scf1&lab:
                mov     fs:[PERF_DATA&ext],1        ; DEKKO: %w/%d=1
    scf2&lab:
                sub     esp,2                       ; restore ESP for exit
                ENDM

;******************************************************************************
;
; SendReturnCode
;
;       Function: Move the contents of the shadow DI register into either the
;                 two or four byte data area of the dekko card. If into the
;                 four byte area, the hi word is always zero.
;
;       Inputs  : ES is set to the dekko mapped memory
;                 SS:BP - points to the shadow register structure
;                 SIZE  - indicates if return code sent as word (16) or
;                         double word (32)
;
;******************************************************************************

SendReturnCode  MACRO   SIZE
               .ERRB   <SIZE>                       ; Error if SIZE blank
               .ERRNZ  SIZE NE 16 AND SIZE NE 32    ; Error if not 16 or 32

                push    ax
                if ?sci_sreg_di eq ?SCI_IN_USE     ; if DI is shadowed,
                   mov     ax,[bp].sreg_di         ;   set AX = shadow DI
                else                               ; otherwise,
                   mov     ax,di                   ;   set AX = real DI
                endif

                IFIDN   <SIZE>,<16>
                mov     es:[PERF_DATA],ax       ; DATA: (%w) Return Code
                ELSE
                SendAsDouble ax                 ; DATA: (%d) Return Code
                ENDIF

                pop     ax                      ;    restore AX register
                ENDM

;******************************************************************************
;
; GetQuadCount
;
;       Function: Given a byte count, this macro calculates the number of
;                 quads needed to send the bytes.
;
;       Inputs  : CX is set to the number of bytes
;
;       Outputs : CX is set to the number of quads
;
;******************************************************************************

GetQuadCount    MACRO   lab
               .ERRB   <lab>            ; assembler error if no parameter

                test    cx,03h          ; check for even number of quads
                jz      gqc&lab         ; jump if even number of quads
                add     cx,4            ; allow for last quad
    gqc&lab:    shr     cx,2            ; calculate number of quads
                ENDM

;******************************************************************************
;
; SendAsciiz
;
;       Function: Moves an asciiz type string to the 4 byte (offset +8)
;                 area of the dekko area. The last quad contains the
;                 null terminator which is transmitted. Any unused bytes
;                 in the last quad will be indeterminate.
;
;       Inputs  : ES is set to the dekko mapped memory
;                 DS:DI indicates the starting location of the asciiz string
;
; 06/13: MHW -  Added macro reference to calculate numb quads to send
; 06/25: MHW -  Fix made to allow "NULL" strings (i.e. 00h in the first byte)
;
;******************************************************************************

SendAsciiz      MACRO   lab
               .ERRB   <lab>            ; assembler error if no parameter

                cmp     di,0            ; is the string pointer NULL?
                jne     saz0&lab        ; jmp if not

                SendAsDouble    0       ; Send null string to Dekko...
                jmp     saz4&lab        ; and we're outa here

    saz0&lab:   SaveReg <cx,di,si>
                                        ; GET THE NUMBER OF BYTES IN STRING
                xor     cx,cx           ; initialize byte count
                mov     si,di           ; save the starting index

    saz1&lab:   cmp     BYTE PTR ds:[di],0  ; look for string terminator
                je      saz2&lab
                inc     cx              ; bump the byte count
                inc     di              ; look at the next byte
                jmp     saz1&lab

    saz2&lab:   inc     cx              ; count the string terminator byte
                GetQuadCount    lab     ; sets CX to number quads to send
                cmp     cx,00h          ; check for null string
                jne     saz3&lab        ; jmp if at least 1 quad to send
                inc     cx              ; force one quad out

    saz3&lab:   mov     di,PERF_DATA_4  ; point to quad offset of dekko area
                movsw                   ; moves 4 bytes from ds:[si] (string)...
                movsw                   ;    to es:[di] (dekko) 2 bytes/move
                loop    saz3&lab

                RestoreReg <si,di,cx>
    saz4&lab:                           ; jump here if null string
                ENDM

;******************************************************************************
;
; SendAsciiz32
;
;       Function: Moves an asciiz type string to the 4 byte (offset +8)
;                 area of the dekko area. The last quad contains the
;                 null terminator which is transmitted. Any unused bytes
;                 in the last quad will be garbage.
;
;       Inputs  : ES is set to the dekko mapped memory
;                 DS:EDI indicates the starting location of the asciiz string
;
;       NOTE    : This is the 32-bit version of SendAsciiz
;
; 06/13: MHW -  Added macro reference to calculate numb quads to send
; 06/25: MHW -  Fix made to allow "NULL" strings (i.e. 00h in the first byte)
; 06/23/91 CJJ - Use ECX for counter not CX.
;
;******************************************************************************

SendAsciiz32    MACRO   lab
               .ERRB   <lab>            ; assembler error if no parameter

                cmp     edi,0           ; is the string pointer NULL?
                jne     saz0&lab        ; jmp if not

                SendAsDouble    0       ; Send null string to Dekko...
                jmp     saz4&lab        ; and we're outa here

    saz0&lab:   SaveReg <ecx,edi,esi>
                                        ; GET THE NUMBER OF BYTES IN STRING
                xor     ecx,ecx         ; initialize byte count
                mov     esi,edi         ; save the starting index

    saz1&lab:   cmp     BYTE PTR ds:[edi],0 ; look for string terminator
                je      saz2&lab
                inc     ecx             ; bump the byte count
                inc     edi             ; look at the next byte
                jmp     saz1&lab

    saz2&lab:   inc     ecx             ; count the string terminator byte
                GetQuadCount    lab     ; sets CX to number quads to send
                cmp     ecx,00h         ; check for null string
                jne     saz3&lab        ; jmp if at least 1 quad to send
                inc     ecx             ; force one quad out

    saz3&lab:   mov     edi,PERF_DATA_4 ; point to quad offset of dekko area
                movsd                   ; moves 4 bytes from ds:[esi] (string)...
                                        ;    to es:[edi] (dekko) 2 bytes/move
                loop    saz3&lab

                RestoreReg <esi,edi,ecx>
    saz4&lab:                           ; jump here if null string
                ENDM

;******************************************************************************
;
; SendLenStr
;
;       Function: Moves alength string or data structure to the dekko card.
;                 The first byte of the string/structure contains the number
;                 of bytes to send. This value -1 is sent to the dekko card as
;                 a word to the 2 byte data area of the card. The actual data
;                 bytes are sent to the 4 byte area of the dekko card as quads
;                 with the unused bytes of the last quad as garbage.
;
;       Inputs  : ES is set to the dekko mapped memory
;                 DS:DI indicates the starting location of the length string
;
; 06/25: MHW -  Test added for zero length strings. Dump length only
;
;******************************************************************************

SendLenStr      MACRO   lab
               .ERRB   <lab>            ; assembler error if no parameter

                cmp     di,0            ; is the DS:DI pointer NULL?
                jne     sls0&lab        ; jmp if not

                mov     es:[PERF_DATA],0; Send 0 count to Dekko...
                jmp     sls3&lab        ;     and we're outa here
    sls0&lab:
                SaveReg <cx,si>

                mov     cl,ds:[di]      ; get count from first byte
                xor     ch,ch           ; clear the high byte of register

                mov     es:[PERF_DATA],cx   ; send the byte count to dekko card

                GetQuadCount    lab     ; sets CX to number quads to send
                cmp     cx,00h          ; check for zero length string
                je      sls2&lab        ; jmp if no quads to send

                mov     si,di           ; load the starting index...
    sls1&lab:   mov     di,PERF_DATA_4  ; point to quad offset of dekko area
                movsw                   ; move 4 bytes from ds:[si] (string)...
                movsw                   ;    to es:[di] (dekko) in 2 byte moves
                loop    sls1&lab
    sls2&lab:
                RestoreReg <si,cx>
    sls3&lab:
                ENDM
