Subject: Re: sharing drivers (was re: m68k comman...)
To: Julian Bean <jules@mailbox.co.uk>
From: Chris G Demetriou <Chris_G_Demetriou@UX2.SP.CS.CMU.EDU>
List: current-users
Date: 03/22/1996 10:41:32
> I don't have a great deal of experience with driver code, but can't we
> #define all the interfaces to the driver data. Something like:
>
> #define ADriverRegA (*(int *)(0xAddress))
> #define ADriverRegB (*(int *)(0xAddress))
>
> in <machince/ADriver.h>, on a memory mapped machine, and have equivalent
> code on the I/O space machines.
except:
(1) register addresses are hardly ever fixed, and
(2) even if they are, this is the hard way to do this.
The right way to do this is to define registers as offsets from a base
(which they usually are), then 'do the right thing'.
> Then, the actual code in ADriver.c can be
>
> ADriverRegIER |= A_FLAG;
> ADriverRegA = 0x45;
>
> ADriverPoll();
>
> return ADriverRegB;
except, that's not at all portable to machines that use I/O space,
or that use memory space in weird ways (e.g. the alpha). You need to
make them macro invocations, of the form:
read_register(foo, bar, baz)
write_register(foo, bar, baz, value)
This is no problem, and in fact, to be portable, drivers that use only
I/O or only memory space have to do this as well!
The problem for drivers that can use both is "how do you pick which
one to use"?
If you do it at run-time, it's slower.
If you do it at compile-time, it becomes harder to share code, e.g.
if you have an ISA (io-mapped) 8390 (ethernet NIC) in an amiga, and a
'native' memory-mapped 8390, and you can only compile your common
driver for one at a time, what do you do?
Sharing drivers between two different architectures is relatively
easy, as the current proliferation of drivers that do it demonstrates.
Using a single driver (shared between architectures or not) for
multiple access methods on a single machine at the same time is a lot
harder. I've yet to see an example that actually _does_ it, probably
because it's relatively hard to do in a reasonable way.
cgd