1 /* 2 * PROJECT: ReactOS HAL 3 * LICENSE: BSD - See COPYING.ARM in the top level directory 4 * FILE: hal/halx86/generic/beep.c 5 * PURPOSE: Speaker support (beeping) 6 * PROGRAMMERS: ReactOS Portable Systems Group 7 */ 8 9 /* INCLUDES ******************************************************************/ 10 11 #include <hal.h> 12 #define NDEBUG 13 #include <debug.h> 14 15 /* FUNCTIONS *****************************************************************/ 16 17 /* 18 * @implemented 19 */ 20 BOOLEAN 21 NTAPI 22 HalMakeBeep(IN ULONG Frequency) 23 { 24 SYSTEM_CONTROL_PORT_B_REGISTER SystemControl; 25 TIMER_CONTROL_PORT_REGISTER TimerControl; 26 ULONG Divider; 27 BOOLEAN Result = FALSE; 28 29 // 30 // Acquire CMOS Lock 31 // 32 HalpAcquireCmosSpinLock(); 33 34 // 35 // Turn the timer off by disconnecting its output pin and speaker gate 36 // 37 SystemControl.Bits = __inbyte(SYSTEM_CONTROL_PORT_B); 38 SystemControl.SpeakerDataEnable = FALSE; 39 SystemControl.Timer2GateToSpeaker = FALSE; 40 __outbyte(SYSTEM_CONTROL_PORT_B, SystemControl.Bits); 41 42 // 43 // Check if we have a frequency 44 // 45 if (Frequency) 46 { 47 // 48 // Set the divider 49 // 50 Divider = PIT_FREQUENCY / Frequency; 51 52 // 53 // Check if it's too large 54 // 55 if (Divider <= 0x10000) 56 { 57 // 58 // Program the PIT for binary mode 59 // 60 TimerControl.BcdMode = FALSE; 61 62 // 63 // Program the PIT to generate a square wave (Mode 3) on channel 2. 64 // Channel 0 is used for the IRQ0 clock interval timer, and channel 65 // 1 is used for DRAM refresh. 66 // 67 // Mode 2 gives much better accuracy, but generates an output signal 68 // that drops to low for each input signal cycle at 0.8381 useconds. 69 // This is too fast for the PC speaker to process and would result 70 // in no sound being emitted. 71 // 72 // Mode 3 will generate a high pulse that is a bit longer and will 73 // allow the PC speaker to notice. Additionally, take note that on 74 // channel 2, when input goes low the counter will stop and output 75 // will go to high. 76 // 77 TimerControl.OperatingMode = PitOperatingMode3; 78 TimerControl.Channel = PitChannel2; 79 80 // 81 // Set the access mode that we'll use to program the reload value. 82 // 83 TimerControl.AccessMode = PitAccessModeLowHigh; 84 85 // 86 // Now write the programming bits 87 // 88 __outbyte(TIMER_CONTROL_PORT, TimerControl.Bits); 89 90 // 91 // Next we write the reload value for channel 2 92 // 93 __outbyte(TIMER_CHANNEL2_DATA_PORT, Divider & 0xFF); 94 __outbyte(TIMER_CHANNEL2_DATA_PORT, (Divider >> 8) & 0xFF); 95 96 // 97 // Reconnect the speaker to the timer and re-enable the output pin 98 // 99 SystemControl.Bits = __inbyte(SYSTEM_CONTROL_PORT_B); 100 SystemControl.SpeakerDataEnable = TRUE; 101 SystemControl.Timer2GateToSpeaker = TRUE; 102 __outbyte(SYSTEM_CONTROL_PORT_B, SystemControl.Bits); 103 Result = TRUE; 104 } 105 } 106 107 // 108 // Release CMOS lock 109 // 110 HalpReleaseCmosSpinLock(); 111 112 // 113 // Return success 114 // 115 return Result; 116 } 117