Alternative models for memory-mapped devices
Device drivers typically communicate with hardware devices through device registers. A driver sends commands or data to a device by storing into device registers, or retrieves status information or data from a device by reading from device registers.
Many processors use memory-mapped I/O, which maps device registers to fixed addresses in the conventional memory space. To a C or C++ programmer, a memory-mapped device register looks very much like an ordinary data object. Programs can use built-in operators such as assignment to move values to or from memory-mapped device registers.
Some processors use port-mapped I/O, which maps device registers to addresses in a separate address space, apart from the conventional memory space. Port-mapped I/O usually requires special machine instructions, such as the in and out instructions of the Intel x86 processors, to move data to or from device registers. To a C or C++ programmer, port-mapped device registers don't look like ordinary memory.
The C and C++ standards say nothing about port-mapped I/O. Programs that perform port-mapped I/O must use nonstandard, platform-specific language or library extensions, or worse, assembly code. On the other hand, programs can perform memory-mapped I/O using only standard language features. Fortunately, port-mapped I/O appears to be gradually fading away, and fewer programmers need to fuss with it.
Several years ago, I wrote a series of articles on accessing memory-mapped device registers using C and C++.1, 2, 3 At the time, I focused on how to set up pointers (in C or C++) or references (in C++) to enable access to memory-mapped registers. I followed those articles with another discussing some alternatives for choosing the types that represent the registers themselves.4
In the years since then, I've had many discussions with readers and conference attendees who use other techniques for representing device registers. I find that many programmers are still using approaches that are inconvenient and error-prone. This month, I'll compare some popular alternatives, focusing more on the interface design issues than on the implementation details.