summaryrefslogtreecommitdiffstats
path: root/private/ntos/nthals/halx86/i386/ixbeep.asm
blob: 0722ca9df3d488df859ebc5f63750e8cebb1abbc (plain) (blame)
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