Subject: Re: resource allocation, pcmcia, isapnp, etc.
To: None <tech-kern@netbsd.org>
From: Warner Losh <imp@harmony.village.org>
List: tech-kern
Date: 06/20/1999 15:34:46
On thing that I've not seen so far in this discussion is how new-bus
and newconfig are really different. I've also not seen an
articulation of why new-bus even happened in the first place. I do
not try in this message to present the strengths of both newconfig and
new-bus, but rather try to present how new-bus differs from newconfig
or how things are done on systems where newconfig is implemented.
The following areas are where I see new-bus shining better than
newconfig are the areas of a stable, extensible ABI; integrated
hierarchical resource management; integrated power control; and
mutability of API. newconfig systems have come up with various
ways of dealing with these issues, some of which are implemented and
others are on the drawing board.
The first area where I see new-bus differing from newconfig is in
features it uses and implements to keep the ABI more stable. No
structures are part of the ABI (unlike newconfig) which are accessed
by the drivers directly. Since they are all accessed via some form of
indirection, the underlying implementation can be changed or augmented
w/o requiring a recompile. With newconfig, if you change the size of
a structure, you must recompile all the places that use that structure
since things are built in.
The much maligned DEVMETHOD also insultate changes to interfaces in
the kernel. For example, many chipsets implement "chip" functions in
different ways. The example I always use is pccard. The
pcmcia_chip_functions structure defines the ABI for drivers
implementing pcmcia_chip_functions. If a new function is later found
to be needed, all drivers that user the pcmcia_chip_functions
structure must be recompiled. With DEVMETHOD, there is enough
indirection to not require this. Each interface defines a set of
routines that it needs. Drivers then implement those functions and
provide a mapping table with the aid of the DEVMETHOD macro. At run
time, this table is compiled and merged with the default
implementations of any functions which aren't implemented by the
device (so if you only wanted to implement attach and detach, but have
defaults for all other methods, then the device will still do
reasonable things when the missing methods are called).
These two items together make decouple the interface presented from
the evolution of the interface. If a implementor of SMP, say, needed
a driver lock for every driver on ths system, then that driver lock
could be added to the driver_t structure and all the drivers would
still work since their driver_t's are not allocated by inline
functions. The system could then use this driver lock for whatever
reasons it needs. Or there could be a new method added. For example,
let us say that a new interface to ifconfig is created whereby it can
ask the interface driver for interface driver specific information in
ASCII form. The default method for this would be to return nothing.
Old drivers will work w/o recompilation, new drivers are free to add
this method so that this information could be displayed.
This sort of thing can be done by hand, but having a compiler/script
generate it makes it a lot easier to deal with.
The second area that new-bus excels at is the area of resource
management. All requests for a resource are filtered up through the
device instance tree via an interface implemented as described above.
The default methods simply pass the information to the next higher
level. This felxibility allows for bridges to cause things to happen
as the request goes up the chain. A pccard bridge would no longer
need the map/unmap functions that are presently implemented in the
pcmcia_chip_functions structure. Children devices just request
resources, and after the bus driver figures out from the CIS or other
black magic where the card must live, the requests just filter up the
tree. The pcic driver (or the pcic98 or cbb or ...) sees these
requests going up the tree. It says to itself "hmmm, this device is
going to be mapped into thus and such space, I better tell the bridge
chip to make those mappings so that the driver will actually work" and
then does just that. It passes things up the tree for its parent
drivers to cope with the request. It does the mapping after it knows
that its parent has said that "yes, you can have this range".
One thing that this buys you is a decreased need to have special code
for every bus possible. Since the bus drivers know how to locate and
allocate resource, a more generic attach routine is possible. The
driver interface gives one the ability to get the bus tag and bus
handle generically, and the bus{space,dma} routines tie in here as
well to give the ability to write a high level of bus-generic code for
most drivers. I'll be the first to admit (and even point out) that
many of FreeBSD's drivers haven't been updated to take advantage of
this.
The third area where new-bus excels is in its integrated power
management. Each device has a suspend and resume routine. The device
is given the opportunity to approve or reject the suspend request as
well as knowing that it happend. Right now in FreeBSD, apm is
implemented with special case code that says in the event of an APM
suspend do this function. With ACPI on the horizon, it no longer
makes sense to tie it to APM. Also, other platforms are starting to
have power management with no relationship at all to either APM or
ACPI (eg the Vr41xx MIPS chips).
The generic message passing mechanism that DEVMETHOD gives one is
quite flexible. There is little doubt in my mind that one could
rework systems using config.new to use this machanism for different
things. It is a very generic mechanism that many things could be
built on. There have been discussions of generic message passing
mechanisms in the newbsd-kern list. I don't know what the status of
these are, but it might make sense to look at how new-bus implements
them.
The fourth area where new-bus can excell is in the area of shims.
Using old-config shims, most of the drivers in the FreeBSD just worked
in a new-bus world, even though they were written for old config.
New-bus quietly wrapped them in their own world so that they usually
didn't need much modification. I believe that config.new wrappers are
also possible and highly desirable. The ability of new-bus to change
the interface it presents to external entities makes it more flexible
than new-config, in this area.
I hope that I've been clear in this area. I have not answered the big
question (why even do this at all?), but I hope I have presented a
balanced view of the high spots in new-bus and how it differs from
newconfig. If I haven't, feel free to ask me to be more specific or
offer clarifications.
Warner