Get front row seat and watch the development of micro-isv. We make cool product that solves all your problems...

logo

Friends
         
Learning Hardware from Linux
2008-12-04

The Linux kernel source code has always been seen (by me at least) as something big and scary. The people who develop it are the scary geniuses, and mere mortals should stay well away. This is only half true.

The people who develop it are geniuses, but the resulting code is some of the nicest I've ever seen. As someone who is interested in hardware, I wanted to find an example of the register set interface between some common PC peripheral and the host processor. Let's have a look at how the OLPC finds out the state of the battery.

We are going to need three tools: cscope, jedit and the kernel source. First off unpack the kernel and tell cscope to build an index of it:

# cscope -bRs .

That will save us a few seconds later on. Cscope has a weird user interface, but don't let that put you off.

Ok, lets find the driver that understands the OLPC's battery monitor. It is a driver, for the power management code, for the OLPC battery, so 'drivers/power/olpc_battery.c' doesn't seem such a bad place to start.

That starts with a whole bunch of #defines talking about voltage, current and temperature, so we appear to be on the right track. The whole thing is less than 500 lines long, so a quick skim of it reveals that olpc_bat_get_property seem to be important. It doesn't seem to do any IO directly, but there are lots of calls to 'olpc_ec_cmd' e.g.:

olpc_ec_cmd(EC_BAT_STATUS, NULL, 0, &ec_byte, 1);



Ok, lets chase that down. Fire up cscope:

# cscope -d   # -d means 'use the index we build earlier



We enter 'olpc_ec_cmd' in the 'Find definition' box and hit enter. The definition is in arch/x86/kernel/olpc.c:

/*

 * This allows the kernel to run Embedded Controller commands.  The EC is

 * documented at <http://wiki.laptop.org/go/Embedded_controller>, and the

 * available EC commands are here:

 * <http://wiki.laptop.org/go/Ec_specification>.  Unfortunately, while

 * OpenFirmware's source is available, the EC's is not.

 */

int olpc_ec_cmd(unsigned char cmd, unsigned char *inbuf, size_t inlen,

                unsigned char *outbuf,  size_t outlen)



Ah, it seems like it takes a command, a input buffer and an output buffer. Skimming the code reveals that it sends the command byte to a port (a serial port FIFO?), streams the buffer then reads the response back into outbuf.

We can inspect the details in olpc_battery.c to find out how any specific command works, but the interface is not memory-mapped at all as we had first assumed: it uses a synchronous message passing interface instead.

So there you go. Next time you are interested in 'how it works' try Linux. It contains a functional description of nearly every piece of PC hardware ever made.