Thinking about how bus_space_barrier is specced as working, and especially
about how one could produce a pathalogical bus_space for debugging, I
think I've come up with some cases where the semantics of
bus_space_barrier aren't strong enough to allow a correct driver to be
written of a device.
My first example is the transmit half of a very simple UART (based on the
Archimedes keyboard interface). It has a single 8-bit register and a
single (level-sensitive) interrupt output. Writing a byte to the register
causes it to start being output. When the device is ready to accept
another byte, it asserts its interrupt line, and it deasserts it when a
new byte is written.
So, our interrupt handler for such a device might look like:
int
foointr(void *cookie)
{
struct foo_softc *sc = cookie;
u_int8_t byte;
/* Get another byte from somewhere */
bus_space_write_1(sc->sc_iot, sc->sc_ioh, byte);
return 1;
}
This is all very well, but it has a problem. If the bus space needs
barriers, the write might be indefinitely delayed. Specifically, it might
be delayed until after the system has re-enabled interrupts, at which
point this interrupt routine will be called again, with predictable
results. As far as I can see, there's no bus_space_barrier call that can
be used to ensure that this doesn't happen.
Another, more plausible example, is a network card (something like an
i82586) attached to an ISA bus. It has some memory (accessed through the
ISA memory space) and some registers (accessed through the ISA I/O
space). To transmit a packet, we compose the packet in the board's
memory, then poke one of its registers. We clearly need some kind of
write barrier between writing to the memory and the registers, but they've
got different bus_space_tags, and bus_space_barrier doesn't provide for
barriers that span more than one tag.
Can someone who understands bus_space_barrier explain the correct way to
barrier each of the above? If not, perhaps the API needs a bit of
extension before barriers become mandatory.
--
Ben Harris <bjh21@netbsd.org>
Portmaster, NetBSD/arm26 <URL:http://www.netbsd.org/Ports/arm26/>