Tue Jun 2 11:08:00 CEST 2009

Writing device drivers

What I'd really like to figure out is if there is a proper workflow
when writing a device driver.  I'm getting a good dose of it with the
USB code.

In my experience it is always trial and error: even if the datasheet
has correct information, it is usually presented in such a way that
you have to "sort it" first..  Then, if there is example code, it is
usually difficult to understand the underlying idea from a big ball of
mud that works.  Usually you want to do it slightly different for
whatever reason, so picking out the right information from example
code becomes error-prone.

The problem is really state: as I've mentioned before, hardware is
very stateful and very sensitive to the order of operations.  Its
state space usually contains a lot of non-working or even lockup
states that have to be avoided.

This seems to get only worse for modern equipment: devices get more
complicated and much of the "getting it right" is left to the
software.  This makes sense: hardware becomes simpler to build and is
more flexible that way, while software just needs to be written once.

However, this doesn't make the life of the driver writer much fun..
If I'm to tackle any real problem, maybe this is the one?

So, what is a device driver exactly?  It's the missing piece of
control software that abstracts a collection of loosely coupled state
machines as a coherent piece of equipment with simple services and a
couple of modes: an object.  The number of modes (states) presented to
the used should probably be kept to a minimum.  The most flexible
approach is a simple on/off mode.

Why is writing a device driver so difficult?  Individuality of modules
gets lost.  Idially, you want to hide state but instead the controller
(driver software) gets to manage all of it.  So the first thing to do
is to abstract all items that are actually independent.

I've found building these abstractions to be the most difficult point
because of interdependency (i.e. resource sharing) being very hard to

Let's find some pubs.  NDL[1][2] seems to be the state of the art.
Summarized it has the following features:

  - Bitfields are individually addressable.

  - The language understands the conept of "device state".

  - States can be coupled: state transitions might cascade.

  - Accesses can be predicated (only valid in certain states + state
    transitions generated)

Optimizations (metric = # IO ops)

  - idempotence (prune successive writes to state registers)
  - field aggregation (combine stores to bitfields)

These features seem simple yet effective.  Maybe some similar approach
could be taken with some Staapl Forth extensions.

[1] http://www1.cs.columbia.edu/~sedwards/papers/conway2004ndl.pdf
[2] http://cs.nyu.edu/~cconway/present/ndl-overview-ibm.pdf