|
|
title "Hal Beep" ;++ ; ;Copyright (c) 1991 Microsoft Corporation ; ;Module Name: ; ; ixbeep.asm ; ;Abstract: ; ; HAL routine to make noise. It needs to synchronize its access to the ; 8254, since we also use the 8254 for the profiling interrupt. ; ; ;Author: ; ; John Vert (jvert) 31-Jul-1991 ; ;Revision History: ; ;--
.386p .xlist include hal386.inc include callconv.inc ; calling convention macros include i386\kimacro.inc include mac386.inc .list
EXTRNP _HalpAcquireSystemHardwareSpinLock,0 EXTRNP _HalpReleaseSystemHardwareSpinLock,0
; ; Defines used to program the i8254 for the speaker. ;
ifdef NEC_98 I8254_TIMER_CONTROL_PORT equ 3fdfh ; write mode port (for N mode) I8254_TIMER_DATA_PORT equ 3fdbh ; count port (for N mode) I8254_TIMER_CLOCK_IN equ 2457600 I8254_TIMER_TONE_MAX equ 65536 I8254_TIMER_CONTROL_SELECT equ 76h SPEAKER_CONTROL_PORT equ 37h ; system port C, set command port SPEAKER_OFF equ 07h SPEAKER_ON equ 06h else ; NEC_98 I8254_TIMER_CONTROL_PORT EQU 43h I8254_TIMER_DATA_PORT EQU 42h I8254_TIMER_CLOCK_IN EQU 1193167 I8254_TIMER_TONE_MAX EQU 65536 I8254_TIMER_CONTROL_SELECT EQU 0B6h SPEAKER_CONTROL_PORT EQU 61h SPEAKER_OFF_MASK EQU 0FCh SPEAKER_ON_MASK EQU 03h endif ; NEC_98
_TEXT$03 SEGMENT DWORD PUBLIC 'CODE' ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
page ,132 subttl "HalMakeBeep" ;++ ; ; BOOLEAN ; HalMakeBeep( ; IN ULONG Frequency ; ) ; ; Routine Description: ; ; This function sets the frequency of the speaker, causing it to sound a ; tone. The tone will sound until the speaker is explicitly turned off, ; so the driver is responsible for controlling the duration of the tone. ; ;Arguments: ; ; Frequency - Supplies the frequency of the desired tone. A frequency of ; 0 means the speaker should be shut off. ; ;Return Value: ; ; TRUE - Operation was successful (frequency within range or zero) ; FALSE - Operation was unsuccessful (frequency was out of range) ; Current tone (if any) is unchanged. ; ;--
Frequency equ [ebp + 8]
cPublicProc _HalMakeBeep , 1
push ebp ; save ebp mov ebp, esp ;
stdCall _HalpAcquireSystemHardwareSpinLock ; intr disabled
; ; Stop the speaker. ;
ifdef NEC_98 mov al, SPEAKER_OFF out SPEAKER_CONTROL_PORT, al out 5Fh, al ; IoDelay else ; NEC_98 in al, SPEAKER_CONTROL_PORT jmp $+2 and al, SPEAKER_OFF_MASK out SPEAKER_CONTROL_PORT, al jmp $+2 endif ; NEC_98
; ; Calculate Tone: Tone = 1.193MHz / Frequency. ; N.B. Tone must fit in 16 bits. ;
mov ecx, DWORD PTR [Frequency] ; ecx <- frequency or ecx, ecx ; (ecx) == 0? je SHORT Hmb30 ; goto Hmb30
mov eax, I8254_TIMER_CLOCK_IN ; eax <- 1.193MHz, the clockin ; for the speaker tone sub edx, edx ; edx <- zero div ecx ; eax <- 1.193MHz / frequency cmp eax, I8254_TIMER_TONE_MAX ; (eax) < 2**16? jb SHORT Hmb20 ; goto Hmb20
; ; Invalid frequency. Return FALSE. ;
sub al, al jmp SHORT Hmb40 Hmb20: ; ; Program the 8254 with the calculated tone. ;
ifdef NEC_98 mov dx, I8254_TIMER_CONTROL_PORT ; port address for N mov cx, I8254_TIMER_DATA_PORT
push eax ; save Tone mov al, I8254_TIMER_CONTROL_SELECT out dx, al ; select timer control register out 5Fh, al ; IoDelay
pop eax ; restore Tone mov dx, cx ; set 'write mode' port addr out dx, al ; program 8254 with Tone lsb out 5Fh, al ; IoDelay mov al, ah out dx, al ; program 8254 with Tone msb out 5Fh, al ; IoDelay
; ; Turn the speaker on. ;
mov al,SPEAKER_ON out SPEAKER_CONTROL_PORT, al out 5Fh, al ; IoDelay else ; NEC_98 push eax ; save Tone mov al, I8254_TIMER_CONTROL_SELECT out I8254_TIMER_CONTROL_PORT, al ; select timer control register jmp $+2
pop eax ; restore Tone out I8254_TIMER_DATA_PORT, al ; program 8254 with Tone lsb jmp $+2 mov al, ah out I8254_TIMER_DATA_PORT, al ; program 8254 with Tone msb jmp $+2
; ; Turn the speaker on. ;
in al, SPEAKER_CONTROL_PORT jmp $+2 or al, SPEAKER_ON_MASK out SPEAKER_CONTROL_PORT, al jmp $+2 endif ; NEC_98
Hmb30: ; ; Return TRUE. ;
mov al, 1
Hmb40: stdCall _HalpReleaseSystemHardwareSpinLock
pop ebp ; restore ebp stdRET _HalMakeBeep
stdENDP _HalMakeBeep
_TEXT$03 ends end
|