Subject: Machine-independent device drivers
To: None <tech-kern@NetBSD.ORG>
From: Charles M. Hannum <firstname.lastname@example.org>
Date: 04/12/1995 23:53:46
The subject may sound like an oxymoron to some of you, but it's not.
Really. Basically, the idea is to encapsulate most or all of the
knowledge about a specific device in machine-independent code. The
question I'm going to explore here is how to do that.
There are a few things to consider:
* Different machines map device registers and memory differently.
* In some cases, multiple mappings are possible on the same machine.
* In some weirder cases, you might even have one device mapped in I/O
space, and another one of the same type mapped in memory space, on the
So, the question becomes how to gloss over these differences.
One answer is to make all register accesses to the device into calls
through function pointers, and implement simple conversion functions
in a machine-dependent module. In some cases (e.g. the LANCE), this
may even be sufficient; most of the access after initialization is
However, if you look at the cases of the DP8390 and the NS16550, this
approach clearly becomes intractable. The overhead of the function
calls would simply kill performance.
Another idea I just had is to implement a sort of `millicode' using
function pointers. If you look at the DP8390 and NS16550 drivers, for
example, it's fairly clear that the register acccesses are clustered
is small areas of high concentration. Those areas could each be
separated out into machine- (and bus- and mapping-of-that-bus-)
The LANCE driver, for example, would need only 2 such `millicode'
callbacks, in addition to general register read/write routines for
The DP8390 driver would need more, but I think that the number could
be minimized sufficiently that it would be bearable. Having those
pieces separated would actually allow better register reuse in some
cases, so it's even possible that the negative impact might be
negligible. (This will be most noticable on machines where arguments
are passed in registers.)
Does anyone have comments about this, or should I `just do it', as a
proof of concept?