;*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.;
;*****************************************************************************/
	PAGE	,132
	NAME	PTD
	TITLE	Physical Timer Device Driver


;***	Physical Timer Device Driver (PTD)
;
;	SCCSID = @(#)ptdbeep.asm	6.6 91/10/22
;
;	DESCRIPTION
;	This module contains the PTD's beep services.
;
;	MODIFICATION HISTORY
;	04/07/89 MTS	Created.


	.xlist
INCL_MI 	EQU	1
	include mvdm.inc	;mvdm definitions for dos macros
	include ptimer.inc	;physical timer public constants
	include timer.inc	;timer hardware constants
INCL_ERRORS	EQU	1
	include bseerr.inc	;error numbers
	include clkseg.inc	;segment definitions
	include clkdata.inc	;physical timer constants
	include vtdptd.inc	;ptimer/vtimer interface constants
	.list

;***	Exports
;
	PUBLIC	PTBeep,PTBeepOff

;***	Imports
;
	EXTRN	selClkData:WORD
	EXTRN	fpfnVTProc:FWORD
	EXTRN	fsPTFlags:WORD

ClkCode SEGMENT


BeepFuncTable label word
	dw	offset ClkCode:PTBeepOff
	dw	offset ClkCode:PTBeepOn
	dw	offset ClkCode:PTBeepFreq
	dw	offset ClkCode:PTBeepOpen
	dw	offset ClkCode:PTBeepClose
BeepMaxFunc	EQU	($-BeepFuncTable)/2-1


;***LP	PTBeep(ulFunc, ulParam) - Device Beep Service
;
;	PTBeep provides the primitive functions which is needed
;	in generating tone from the system speaker.
;
;	ENTRY
;	    ulFunc  = beep services: BEEP_OFF, BEEP_ON, BEEP_FREQ
;	    ulParam = parameter for the beep service
;			BEEP_OFF:  ulParam = 0
;			BEEP_ON:   ulParam = 0
;			BEEP_FREQ: ulParam = ulFreq (freq. of the beep)
;
;	EXIT
;	    SUCCESS
;		(eax) = 0
;	    FAILURE
;		(eax) = error code - ERROR_INVALID_FUNCTION
;
;	USES
;	    None
;
;	CONTEXT
;	    Task
;	    Interrupt
;
;	PSEUDOCODE
;	    rc = 0;
;	    switch(usFunc) {
;		case BEEP_OFF:
;		    PTBeepOff();
;		    break;
;		case BEEP_ON:
;		    PTBeepOn();
;		    break;
;		case BEEP_FREQ:
;		    PTBeepFreq(usParam);
;		    break;
;		default:
;		    rc = ERROR_INVALID_FUNCTION;
;	    }
;	    return rc;


	ASSUME	CS:ClkCode,DS:NOTHING,ES:NOTHING,SS:NOTHING
Procedure PTBeep,FAR

	.386p

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

	EnterProc
	SaveReg <bx>

	mov	ax,WORD PTR [ulFunc]	;(ax)=ulFunc
	mov	bx,WORD PTR [ulParm]	;(bx)=ulParm

	cmp	ax,BeepMaxFunc		;is it a valid function?
	ja	pbe			;NO, goto error exit

	push	si			;save si
	mov	si,ax			;(si)=usFunc
	shl	si,1			;adjust si as word index
	call	cs:BeepFuncTable[si]	;process requested function
	pop	si			;restore si

	xor	eax,eax 		;(eax)=ERROR_NONE

pbx:	RestoreReg <bx>
	ASSUME	DS:NOTHING

	LeaveProc

	retfd	?aframe 		;%%%

pbe:	mov	eax,ERROR_INVALID_FUNCTION
	jmp	short pbx

	CpuMode reset

EndProc PTBeep


;***LP	PTBeepOn() - Turn Speaker On
;
;	Turn the system speaker on by enabling it.
;
;	ENTRY
;	    None
;
;	EXIT
;	    None
;
;	USES
;	    None
;
;	CONTEXT
;	    Any
;
;	PSEUDOCODE
;	    read SysB;
;	    enable speaker bits;
;	    write SysB;

	ASSUME	CS:ClkCode,DS:NOTHING,ES:NOTHING,SS:NOTHING
Procedure PTBeepOn,NEAR

	push	ax			;save ax

	in	al,PORT_SYSB		;(al) = SYSB
	IODelay
	or	al,SYSB_SPKGATE+SYSB_SPKENABLE;turn on speaker enable bits
	out	PORT_SYSB,al		;enable speaker

	pop	ax			;restore ax

	ret

EndProc PTBeepOn


;***LP	PTBeepOff() - Turn Speaker Off
;
;	Turn the system speaker off by disabling it.
;
;	ENTRY
;	    None
;
;	EXIT
;	    None
;
;	USES
;	    None
;
;	CONTEXT
;	    Any
;
;	PSEUDOCODE
;	    read SysB;
;	    disable speaker bits;
;	    write SysB;

	ASSUME	CS:ClkCode,DS:NOTHING,ES:NOTHING,SS:NOTHING
Procedure PTBeepOff,NEAR

	push	ax			;save ax

	in	al,PORT_SYSB		;(al) = SYSB
	IODelay
	and	al,NOT(SYSB_SPKGATE+SYSB_SPKENABLE);turn off speaker enable bits
	out	PORT_SYSB,al		;disable speaker

	pop	ax			;restore ax

	ret

EndProc PTBeepOff


;***LP	PTBeepFreq(usFreq) - Set Beep Frequency
;
;	Set the speaker timer with the given frequency in Hz.
;
;	ENTRY
;	    (bx) - usFreq = beep frequency in Hz
;
;	EXIT
;	    None
;
;	USES
;	    None
;
;	CONTEXT
;	    Any
;
;	PSEUDOCODE
;	    if (usFreq < BEEPFREQ_LO)
;		usFreq = BEEPFREQ_LO;
;	    convert usFreq to usTicks;
;	    program speaker timer with usTicks;

	ASSUME	CS:ClkCode,DS:NOTHING,ES:NOTHING,SS:NOTHING
Procedure PTBeepFreq,NEAR

	SaveReg <ax,bx,dx>

	cmp	bx,BEEPFREQ_LO		;below minimum frequency?
	jae	pbf10			;NO, continue

	mov	bx,BEEPFREQ_LO		;set usFreq to minimum frequency

pbf10:	mov	al,SC_CNT2+RW_LSBMSB+CM_MODE3
	out	PORT_CW,al		;reset the byte index
	mov	dx,TIMERFREQ_HI
	mov	ax,TIMERFREQ_LO 	;(dx:ax) = TIMERFREQ (1.19MHz)
	div	bx			;(ax) = usTick in timer counts

	out	PORT_CNT2,al		;program low byte of timer count
	IODelay
	xchg	al,ah			;(al) = high byte of timer count
	out	PORT_CNT2,al		;program high byte of timer count

	RestoreReg <dx,bx,ax>

	ret

EndProc PTBeepFreq


;***LP	PTBeepOpen() - Get beep access
;
;	If vtimer has the speaker ownership, call vtimer to get
;	the speaker access.
;
;	ENTRY
;	    None
;
;	EXIT
;	    None
;
;	USES
;	    All except ds,es
;
;	CONTEXT
;	    Any
;
;	PSEUDOCODE
;	    if vtimer has the speaker ownership
;		call vtimer to get it;

	ASSUME	CS:ClkCode,DS:NOTHING,ES:NOTHING,SS:NOTHING
Procedure PTBeepOpen,NEAR

	SaveReg <ds,es>
	mov	ds,cs:[selClkData]
	ASSUME	DS:ClkData

	test	fsPTFlags,PTF_OWNT2	;ptimer already has the ownership?
	jnz	ptbox			;YES, exit

	or	fsPTFlags,PTF_OWNT2
	.386p
	xor	eax,eax
	push	DWORD PTR VTDCMD_PREEMPTT2;(TOS+8)=VTDCMD_PREEMPTT2
	push	eax			;(TOS+4)=0
	push	eax			;(TOS)=0

	;Should ASSERTNONZERO(fpfnVTProc)
	call	FWORD PTR [fpfnVTProc]
	CpuMode reset

ptbox:	RestoreReg <es,ds>
	ASSUME	DS:NOTHING

	ret

EndProc PTBeepOpen


;***LP	PTBeepClose() - Release beep access
;
;	If ptimer has the speaker ownership, call vtimer to release
;	the speaker.
;
;	ENTRY
;	    None
;
;	EXIT
;	    None
;
;	USES
;	    All except ds,es
;
;	CONTEXT
;	    Any
;
;	PSEUDOCODE
;	    if ptimer has the speaker ownership and there is a vtimer
;		call vtimer to release ownership;

	ASSUME	CS:ClkCode,DS:NOTHING,ES:NOTHING,SS:NOTHING
Procedure PTBeepClose,NEAR

	SaveReg <ds,es>
	mov	ds,cs:[selClkData]
	ASSUME	DS:ClkData

	test	fsPTFlags,PTF_OWNT2	;ptimer has the ownership?
	jz	ptbcx			;NO, exit

	.386p
	cmp	DWORD PTR fpfnVTProc,0	;vtimer exist?
	je	ptbcx			;NO, exit

	and	fsPTFlags,NOT PTF_OWNT2
	xor	eax,eax
	push	DWORD PTR VTDCMD_RELEASET2;(TOS+8)=VTDCMD_RELEASET2
	push	eax			;(TOS+4)=0
	push	eax			;(TOS)=0

	call	FWORD PTR [fpfnVTProc]
	CpuMode reset

ptbcx:	RestoreReg <es,ds>

	ret

EndProc PTBeepClose

ClkCode ENDS


	END
