1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
|
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
extrn _Halp8254Lock:DWORD
;
; 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$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 ;
push ebx ; save ebx
Hmb10: pushfd ; save flags
cli ; disable interrupts
ifndef NT_UP
lea eax, _Halp8254Lock
ACQUIRE_SPINLOCK eax,Hmb99
endif
;
; 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 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.
;
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
Hmb30:
;
; Return TRUE.
;
mov al, 1
Hmb40:
ifndef NT_UP
lea ebx, _Halp8254Lock
RELEASE_SPINLOCK ebx
endif
popfd
pop ebx ; restore ebx
pop ebp ; restore ebp
stdRET _HalMakeBeep
ifndef NT_UP
Hmb99: popfd
SPIN_ON_SPINLOCK eax,<Hmb10>
endif
stdENDP _HalMakeBeep
_TEXT$03 ends
end
|