Earlier today, someone asked me why 64bit versions of windows don’t support the internal PC speaker beeps. The answer is somewhat complicated and ends up being an interesting intersection between a host of conflicting tensions in the PC ecosystem.
Let’s start by talking about how the Beep hardware worked way back in the day. The original IBM PC contained an Intel 8254 programmable interval timer chip to manage the system clock. Because the IBM engineers felt that the PC needed to be able to play sound (but not particularly high quality sound), they decided that they could use the 8254 as a very primitive square wave generator. To do this, they programmed the 3rd timer on the chip to operate in Square Wave mode and to count down with the desired output frequency. This caused the Out2 line on the chip to toggle from high to low every time the clock went to 0. The hardware designers tied the Out2 line on the chip to the PC speaker and voila – they were able to use the clock chip to program the PC speaker to make a noise (not a very high quality noise but a noise nonetheless).
The Beep() Win32 API is basically a thin wrapper around the 8254 PIC functionality. So when you call the Beep() API, you program the 8254 to play sounds on the PC speaker.
Fast forward about 25 years… The PC industry has largely changed and the PC architecture has changed with it. At this point they don’t actually use the 8254 as the programmable interrupt controller, but it’s still in modern PCs. And that’s because the 8254 is still used to drive the PC speaker.
One of the other things that happened in the intervening 25 years was that machines got a whole lot more capable. Now machines come with capabilities like newfangled hard disk drives (some of which can even hold more than 30 megabytes of storage (but I don’t know why on earth anyone would ever want a hard disk that can hold that much stuff)). And every non server machine sold today has a PC sound card. So every single machine sold today has two ways of generating sounds – the PC sound card and the old 8254 which is tied to the internal PC speaker (or to a dedicated input on the sound card – more on this later).
There’s something else that happened in the past 25 years. PCs became commodity systems. And that started exerting a huge amount of pressure on PC manufacturers to cut costs. They looked at the 8254 and asked “why can’t we remove this?”
It turns out that they couldn’t. And the answer to why they couldn’t came from a totally unexpected place. The American’s with Disabilities Act.
The ADA? What on earth could the ADA have to do with a PC making a beep? Well it turns out that at some point in the intervening 25 years, the Win32 Beep() was used for assistive technologies – in particular the sounds made when you enable the assistive technologies like StickyKeys were generated using the Beep() API. There are about 6 different assistive technology (AT) sounds built into windows, their implementation is plumbed fairly deep inside the win32k.sys driver.
But why does that matter? Well it turns out that many enterprises (both governments and corporations) have requirements that prevent them from purchasing equipment that lacks accessible technologies and that meant that you couldn’t sell computers that didn’t have beep hardware to those enterprises.
This issue was first noticed when Microsoft was developing the first 64bit version of WIndows. Because the original 64bit windows was intended for servers, the hardware requirements for 64bit machines didn’t include support for an 8254 (apparently the AT requirements are relaxed on servers). But when we started building a client 64bit OS, we had a problem – client OS’s had to support AT so we needed to bring the beep back even on machines that didn’t have beep hardware.
For Windows XP this was solved with some custom code in winlogon which worked but had some unexpected complications (none of which are relevant to this discussion). For Windows Vista, I redesigned the mechanism to move the accessibility beep logic to a new “user mode system sounds agent”.
Because the only machines with this problem were 64bit machines, this functionality was restricted to 64bit versions of Windows.
That in turn meant that PC manufacturers still had to include support for the 8254 hardware – after all if the user chose to buy the machine with a 32bit operating system on it they might want to use the AT functionality.
For Windows 7, we resolved the issue completely – we moved all the functionality that used to be contained in Beep.Sys into the user mode system sounds agent – now when you call the Beep() API instead of manipulating the 8254 chip the call is re-routed into a user mode agent which actually plays the sounds.
There was another benefit associated with this plan: Remember above when I mentioned that the 8254 output line was tied to a dedicated input on the sound card? Because of this input to the sound card, the sound hardware needed to stay powered on at full power all the time because the system couldn’t know when an application might call Beep and thus activate the 8254 (there’s no connection between the 8254 and the power management infrastructure so the system can’t power on the sound hardware when someone programs the 3rd timer on the 8254). By redirecting the Beep calls through the system audio hardware the system was able to put the sound hardware to sleep until it was needed.
This redirection also had had a couple of unexpected benefits. For instance when you accidentally type (or grep) through a file containing 0x07 characters in it (like a .obj file) you can finally turn off the annoying noise – since the beeps are played through the PC speakers, the PC mute key works to shut them up. It also means that you can now control the volume of the beeps.
There were also some unexpected consequences. The biggest was that people started noticing when applications called Beep(). They had placed their PCs far enough away (or there was enough ambient noise) that they had never noticed when their PC was beeping at them until the sounds started coming out their speakers.
 Thus providing me with an justification to keep my old Intel component data catalogs from back in the 1980s.