|
|
title "Hal Beep" ;++ ; ;Copyright (c) 1991 Microsoft Corporation ; ;Module Name: ; ; spbeep.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 include i386\spmp.inc
.list
extrn _HalpSystemHardwareLock:DWORD extrn _SpType:BYTE
; ; Defines used to program the i8254 for the speaker. ;
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
_TEXT 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 ; push ebx ; save ebx
Hmb10Sp:pushfd ; save flags cli ; disable interrupts
lea eax, _HalpSystemHardwareLock ACQUIRE_SPINLOCK eax,Hmb99Sp
cmp _SpType, SMP_SYSPRO2 ; On SysPro2 do it differently je HalMakeBeepSmp
; ; Stop the speaker. ;
in al, SPEAKER_CONTROL_PORT jmp $+2 and al, SPEAKER_OFF_MASK out SPEAKER_CONTROL_PORT, al jmp $+2
; ; 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 Hmb30Sp ; goto Hmb30Sp
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 Hmb20Sp ; goto Hmb20Sp
; ; Invalid frequency. Return FALSE. ;
sub al, al jmp SHORT Hmb40Sp Hmb20Sp: ; ; Program the 8254 with the calculated tone. ;
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
Hmb30Sp: ; ; Return TRUE. ;
mov al, 1
Hmb40Sp: lea ebx, _HalpSystemHardwareLock RELEASE_SPINLOCK ebx
popfd pop ebx ; restore ebx pop ebp ; restore ebp stdRET _HalMakeBeep
Hmb99Sp:popfd SPIN_ON_SPINLOCK eax,<Hmb10Sp>
HalMakeBeepSmp: ; A BELIZE/PHOENIX machine MUST always enable and disable the beep via ; CPU 0 regardless of the originating CPU. This is done through indexed ; IO. ; ; Note the indexed IO is serialized with the 8254 spinlock
; ; Stop the speaker. ;
INDEXED_IO_READ 0,SPEAKER_CONTROL_PORT and al, SPEAKER_OFF_MASK
INDEXED_IO_WRITE 0,SPEAKER_CONTROL_PORT,al
; ; 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 Hmb30Sp ; 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 Hmb40Sp Hmb20: ; ; Program the 8254 with the calculated tone. ;
push eax ; save Tone mov al, I8254_TIMER_CONTROL_SELECT
INDEXED_IO_WRITE 0,I8254_TIMER_CONTROL_PORT,al
pop eax ; restore Tone
INDEXED_IO_WRITE 0,I8254_TIMER_DATA_PORT,al mov al, ah
INDEXED_IO_WRITE 0,I8254_TIMER_DATA_PORT,al
; ; Turn the speaker on. ;
INDEXED_IO_READ 0,SPEAKER_CONTROL_PORT or al, SPEAKER_ON_MASK
INDEXED_IO_WRITE 0,SPEAKER_CONTROL_PORT,al jmp Hmb30Sp
stdENDP _HalMakeBeep _TEXT ends end
|