;*DDK*************************************************************************/
;
; COPYRIGHT (C) Microsoft Corporation, 1989
; COPYRIGHT    Copyright (C) 1995 IBM Corporation
;
;    The following IBM OS/2 WARP source code is provided to you solely for
;    the purpose of assisting you in your development of OS/2 WARP device
;    drivers. You may use this code in accordance with the IBM License
;    Agreement provided in the IBM Device Driver Source Kit for OS/2. This
;    Copyright statement may not be removed.;
;*****************************************************************************/
;       SCCSID = @(#)clkvdm.asm	6.6 91/10/22
	PAGE	,132
	NAME	CLOCK
	TITLE	Physical Clock Device Driver

;***	Physical Clock Device Driver (CLK)
;
;	SCCSID = @(#)clkvdm.asm	6.6 91/10/22
;
;
;
;
;	CLK-VCMS Communication Interface
;
;	DESCRIPTION
;	    This module contains all the CLK-VCMOS communication
;	    interface procedures.
;
;	MODIFICATION HISTORY
;	02/02/90 MTS	Created.


	.xlist
INCL_MI EQU	1
	include mvdm.inc	;mvdm definitions for dos macros
	include cmos.inc	;cmos hardware constants
	include vcmospdd.inc	;definitions common to both cmos VDD and PDD
	include clkseg.inc	;segment definitions
	.list

	.386p

ClkCode SEGMENT

	PUBLIC	selClkData		;%%% BUGBUG loader should resolve
selClkData  dw	0			;%%% instead of storing ds away

EVEN					;make sure it's word aligned
ClkFuncTable label word
	dw	offset ClkCode:ClkRegister
	dw	offset ClkCode:ClkReadCMOS
ClkMaxFunc	EQU	($-ClkFuncTable)/2-1


;***LP	ClkVDDProc(ulFunc, ul1, ul2) - VDD request router
;
;	This subroutine is registered by the PDD during system initialization
;	via DevHlp_RegisterPDD, and is called by the VDD to perform various
;	services.  See all the CLKCMD_* equates for a brief list of those
;	services.
;
;	ENTRY
;	    (TOS+8) = ulFunc
;	    (TOS+4) = ul1
;	    (TOS)   = ul2
;
;	    Refer to vcmospdd.h for details of ul1 and ul2.
;
;	EXIT
;	    SUCCESS
;		(eax) = TRUE
;	    FAILURE
;		(eax) = FALSE
;
;	USES
;	    All except bx,si,di,bp,ds,es
;
;	CONTEXT
;	    VDD Init-time
;	    VDM Task-time
;
;	PSEUDOCODE
;	    route to appropriate Clk* worker function;
;
;	NOTE
;	    Assume function code can be used as direct function table index.

	ASSUME	CS:ClkCode,DS:NOTHING,ES:NOTHING,SS:NOTHING
Procedure ClkVDDProc,far

	?abase	= 8 + 2 		;%%% ret. addr. is 8 bytes, bp 2 bytes
	ArgVar	ul2,ULONG		;BUGBUG Procedure, EndProc should
	ArgVar	ul1,ULONG		;	be changed to support 16:32
	ArgVar	ulFunc,ULONG		;	type of procedure calling.

	EnterProc
	SaveReg <bx,si,di,ds,es>

	mov	ds,cs:[selClkData]
	ASSUME	DS:ClkData

	sub	eax,eax 		;assume failure

	mov	bx,WORD PTR [ulFunc]	;(bx)=ulFunc
	sub	bx,CLKCMD_REGISTER	;don't make assumptions on register equ
	cmp	bx,ClkMaxFunc		;is it a valid function?
	ja	cvpx			;NO, goto error exit

	shl	bx,1			;adjust bx as word index

	mov	cx,WORD PTR [ul1+2]
	mov	si,WORD PTR [ul1]	;(cx:si)=ul1
	mov	dx,WORD PTR [ul2+2]
	mov	di,WORD PTR [ul2]	;(dx:di)=ul2

	call	cs:ClkFuncTable[bx]	;process requested function

cvpx:	RestoreReg <es,ds,di,si,bx>
	ASSUME	DS:NOTHING

	LeaveProc

	retfd	?aframe 		;%%%

EndProc ClkVDDProc


;***LP	ClkRegister() - VDD registration
;
;	Record the entry point being registered for the VDD.  This is in
;	response to CLKCMD_REGISTER and is invoked by the VDM manager
;	in VDHOpenPDD.
;
;	ENTRY
;	    (si:dx,di) = NULL -> VDD entry point
;
;	EXIT
;	    SUCCESS
;	       (eax) = TRUE	//always successful
;
;	USES
;	    None
;
;	CONTEXT
;	    VDD Init-time
;
;	NOTE
;	    Currently, we don't need a VCMOS entry point.
;	    So we just store it and forget about it.  This routine
;	    must be present because VDM manager will call us no matter
;	    we have a valid entry point or not.
;
;	PSEUDO-CODE

	ASSUME	CS:ClkCode,DS:ClkData,ES:NOTHING,SS:NOTHING
Procedure ClkRegister,near

	mov	eax,CTRUE			;return success

	ret

EndProc ClkRegister


;***LP	ClkReadCMOS() - VDD Read CMOS
;
;	The VDD call this procedure to read the CMOS locations.
;
;	ENTRY
;	    (cx:si) -> ReadReq
;	    (dx:di) -> CMOSArray
;
;	EXIT
;	    SUCCESS
;		(eax) = TRUE
;
;	USES
;	    All
;
;	CONTEXT
;	    VDM Task
;
;	NOTE
;	    This function always succeeds because we will enforce a
;	    valid CMOS address range by masking the extra address bits.
;
;	PSEUDOCODE
;	    fChanged = FALSE;
;	    do {
;		for each byte in the range specified {
;		    read CMOS;
;		    if it has been changed since the last iteration {
;			fChanged = TRUE;
;			store the new value;
;		    }
;		}
;	    } while (fChanged);

	ASSUME	CS:ClkCode,DS:ClkData,ES:NOTHING,SS:NOTHING
Procedure ClkReadCMOS,hybrid						

	mov	ds,cx			;(ds:si)->ReadReq packet
	mov	es,dx			;(es:di)->CMOS array

crc10:	mov	bx,di			;(es:bx)->CMOS array
	mov	al,[si].rdrq_CMOSAddr	;(al)=start CMOS address
	and	al,ADDR_MASK		;make sure address within range
	xor	ch,ch
	mov	cl,[si].rdrq_nbCMOS	;(cx)=number of bytes to read
	xor	dx,dx			;(dx)=fChanged=FALSE

crc20:  pushf								
	cli								
	out	PORT_ADDRLATCH,al	;set port address		
	inc	al			;(al)=next port
	xchg	al,ah			;(ah)=next port address
	IODelay
	in	al,PORT_DATALATCH	;(al)=value of CMOS location
	popf								
	cmp	al,es:[bx]		;is this byte the same as before?
	je	crc30			;YES, continue

	inc	dx			;set fChanged flag
	mov	es:[bx],al		;store new value

crc30:	inc	bx			;increment buffer pointer
	xchg	ah,al			;(al)=next port address
	loop	crc20			;read next byte if we are not done yet

	cmp	dx,0			;have CMOS values changed?
	jne	crc10			;YES, try again

	mov	al,ADDR_DIAGS+ADDR_NMIENABLE;re-enable NMI
	pushf								
	cli								
	out	PORT_ADDRLATCH,al
	IODelay
	in	al,PORT_DATALATCH	;dummy read
	popf								

	mov	eax,CTRUE		;return TRUE
	ret

EndProc ClkReadCMOS

ClkCode ENDS


	END
