;       SCCSID = @(#)timapia.asm	6.1 90/11/17
PAGE	,132
TITLE	TIMAPIA.ASM - helper routines for Timer APIs
NAME	TIMAPIA

;      TIMAPIA.ASM
;
;      SCCSID = @(#)timapia.asm   13.0 90/01/20
;
;      IBM/Microsoft Confidential
;
;      Copyright (c) IBM Corporation 1987, 1989
;      Copyright (c) Microsoft Corporation 1987, 1989
;
;      All Rights Reserved
;
;      Title:
;
;      Timer Dos APIs helper routines
;
;      Description:
;
;      Routines:
;	    TIMSEMHANDLE
;	    TIMSEMCLEAR
;      Modification History:
;
;      Created: Sudeep Bharati	    01/20/90


.xlist
	include basemaca.inc
	include osmaca.inc
	include dosseg.inc
	include dossymc.inc
	include mi.inc
.list

	CpuMode 386
	ModName timapia

	EXTRN16   SemHandle
	EXTRN16   SemClear

	ReferFlat _ahtimer,dword
	ReferFlat _ntimers,dword

	  FARCODE HIGH32
HIGH32CODE SEGMENT

;***EP	TIMSEMHANDLE - Handle old semaphores
;
;	ENTRY
;	    hsem = semaphore handle
;	    flop = operation type
;		    1 - Validate that passed semaphore is system semaphore
;		    0 - decrement refernce count
;
;	EXIT
;	    SUCCESS - returns transformed sem handle
;	    FAILURE - returns 0
;
;	PCODE
;	    call semhandle with dh = flop
;	    if flop == 0
;		return success
;	    else
;		check that passed semaphore is system semaphore
;		if so
;		    return transformed semaphore handle
;		else
;		    return 0
;	    endif

Procedure TIMSEMHANDLE,near
ArgVar	  flop,DWORD
ArgVar	  hsem,DWORD

	EnterProc
	SaveReg <ebx,ecx,edx,esi,edi,ds,es>
	mov	edx,[flop]
	mov	dh,dl		    ; dh = 0 if not is use and 1 if in use
	mov	eax,[hsem]
	mov	bx,ax		    ; low word of semaphore in bx
	ror	eax,16		    ; high word of semaphore in ax
	CALL16	SemHandle	    ; IN : AX;BX - semhandle
				    ;	    Dl = 0 not in use
				    ;	    DL = 1 in use
				    ; OUT: AX;BX translated semaphore
				    ; Carry set if error;

	pushf			    ; save carry
	mov	ecx,[flop]
	or	cx,cx		    ; if not_in_use case no error check
	je	short tim_exit1     ; required

	popf
	jc	short sem_error     ; did Semhandle return error?
	mov	ecx,[hsem]	    ; to be a RAM semaphore ax = cx and
	mov	dx,cx		    ; bx = dx.
	ror	ecx,16
	cmp	ax,cx
	jne	short sem_ok

	cmp	bx,dx
	jne	short sem_ok

sem_error:
	xor	eax,eax
	jmp	short tim_exit2

tim_exit1:
	popf

sem_ok: rol	eax,16
	mov	ax,bx

tim_exit2:
	RestoreReg <es,ds,edi,esi,edx,ecx,ebx>
	ExitProc
EndProc TIMSEMHANDLE

;***EP	TIMSEMCLEAR - Clear a V1.* semaphore
;
;	ENTRY
;	    hsem = semaphore handle
;
;	EXIT
;	    None
;
;	PCODE
;	    call semclear

Procedure TIMSEMCLEAR,near
ArgVar	   hsem,DWORD

	EnterProc

	SaveReg <ebx,ecx,edx,esi,edi,ds,es>
	mov	eax,[hsem]
	mov	bx,ax
	ror	eax,16
	CALL16	SemClear		    ; ax:bx is the hsem
	RestoreReg <es,ds,edi,esi,edx,ecx,ebx>

	ExitProc

EndProc TIMSEMCLEAR

;***EP	TIMGSETHTIMER - Get a free timer handle slot or mark a slot
;		       as free.
;
;	ENTRY
;	    fop - operation to do
;		0 - get a free timer handle
;		1 - free the specified timer handle
;	    htimer - if fop is 1 then free this timer else ignore it.
;
;	EXIT
;	    SUCCESS returns a value less then ntimers
;	    FAILURE returns a value greater then or equal to ntimers
;
;	PCODE
;	    if fop is to get a free timer
;		scan the timer handle array for a free entry
;		if found return entry index as timer handle
;		else return ntimers
;	    else
;		mark the given index as free

Procedure TIMGSETHTIMER,near
ArgVar	   htimer,DWORD
ArgVar	   fop,DWORD

	EnterProc

	SaveReg <ebx,ecx,edx,esi,edi,ds,es>

	cmp	[fop],0
	je	short get_free		; go to get a free entry

	mov	esi,[_ahtimer]
	mov	ecx,htimer

test_next:
	cmp	ecx,020h		; go to that dword where htimer lies
	jae	short next_dword

	mov	eax,dword ptr [esi]	; get the word
	mov	ebx,1
	shl	ebx,cl			; get the bit in position
	not	ebx
	and	eax,ebx 		; set the bit
	mov	dword ptr [esi],eax	; store back the word
	xor	eax,eax 		; return always sucsess
	jmp	tgs_xit

next_dword:
	add	esi,04
	sub	ecx,020h
	jmp	short test_next

get_free:
	mov	esi,[_ahtimer]		; esi = start address of array
	xor	edx,edx 		; edx = searching index number

next_itr:
	mov	ebx,1			; bit fileld to test a bit set or not
	mov	eax, dword ptr [esi]	; read a dword from array
	add	esi,04		      ; esi = next dword in array

next_bit:
	cmp	edx,[_ntimers]
	je	short over		; none available

	or	ebx,ebx
	je	short next_itr		; process next dword

	push	eax
	and	eax,ebx 		; test if the bit is free
	pop	eax
	jz	short got_it		; yes got it

	shl	ebx,1			; bit field for next bit in dword
	inc	edx			; next search index
	jmp	short next_bit		; test next bit

got_it: or	eax,ebx
	sub	esi,04
	mov	dword ptr [esi],eax

over:
	mov	eax,edx 		; return htimer index

tgs_xit:
	RestoreReg <es,ds,edi,esi,edx,ecx,ebx>

	ExitProc
EndProc TIMGSETHTIMER

HIGH32CODE ENDS

	END
