Subject: Re: bus.h style question
To: Ignatios Souvatzis <ignatios@cs.uni-bonn.de>
From: Jonathan Stone <jonathan@DSG.Stanford.EDU>
List: tech-kern
Date: 08/20/1997 03:33:11
On Wed, 20 Aug 1997 11:11:11 +0200 (MET DST),
  Ignatios Souvatzis <ignatios@cs.uni-bonn.de> writes:

 >c) Jonathan proposes to provide a bus_space_read_swapped_2(), which would be,
 >on little-endian busses like ISA, be equivalent to:
 >
 >        (bus_space_read_1(t, h, (o)+1) | (bus_space_read_1(t, h, o)<<8))
 >

Err,  actually I thought I was proposing semantics more like

	#define bus_space_read_swapped_2 (t, h, o) \
		NTOHS(bus_space_read_2(t, h, (o))

	#define bus_space_read_swapped_4 (t, h, o) \
		NTOHL(bus_space_read_2(t, h, (o))

(with whatever names we choose for a endian-neutral byteswap
substituted).  so that we only do one i/o access. 

And, really only for the multi-datum methods: see below.

 >d) Either one should take advantage of bridge hardware (meaning that the
 >bridge driver would decide, knowing what endianness the bus and the CPU have,
 >which functions to use, and maybe which alternative addressing of the bridge,
 >to do proper (non-)swapping.


 >e) expand this to the _multi_ and the _region_ stuff.


Those are the ones I was really interested in. If the bus_space method
is only moving one datum, I don't see a strong argument for folding
the byteswap into the bus_space method.

Maybe the `byteswapped' (i.e., from CPU byteorder) methods should be

	bus_space_{read,write}_multi_stream_2()
	bus_space_{read,write}_multi_stream_4()

	bus_space_{read,write}_region_stream_2()
	bus_space_{read,write}_region_stream_4()

to emphasise that they're for handling bytestream data, and so
logically don't get any bridge-specific byteswapping done?  (of course
they might get byteswapped twice, if the bus hardware does
byteswapping, but you get what I mean.)


I think that for mixed CPU and bus byteorder, the natural usage is:
  (a) for accessing device registers,  typically wants to
      read and write one datum in CPU byteorder, so  byteswapped
      (either by bridge or address prefrobnication) values, in
      CPU byteorder, are what you want. CGD's example is perfect
      here; if a 16-bit device register logically contains 0x1234,
      you want the CPU to  get 0x1234 from a bus_space_read_2().

  (b) when moing PIO data to or from the device via FIFO
      registers, you're moving bytestream data like disk or tape
      blocks or Ethernet packets via bus_space_{read,write}_multi_N.
      You want this data to go to the device registers as bytestream data,
      so (assuming diferent-endian bus and CPU) you probably want the
      _ opposite_ byteorder from case (a).

  (c) Dealing with bytestreams like disk or tape blocks or Ethernet
      packets via a shared-memory buffer in bus space (e.g, ne2000),
      using bus_space_{read,write}_region_N().

      Again, ignoring endian-agile I/O chips, I think you'd probably want
      the opposite byte-order here from part (a), but it may well
      depend on where the memory physically resides and how
      the bus is wired up.

I could well be wrong, but I don't see the non-bytestream versions of
_region_ and _multi_ being used much at all.


There really are two logically different types of data that pass
across the bus_space interface: device_register data and ``data''
(bytestream) data.  If the bus.h layer needs to handle those
differently -- byteswapping one and not byteswapping the other -- then
the kind of information being transferred needs to go through the
<bus.h> interface, so it can Do The Right Thing.

We could encode it in bus-space tags, but that doesn't make much sense
for a PIO device that has both kinds of access...

Yah, I know DMA is important, and I buy that for PCI on big-endian
systems, but this should work well for m68k<->ISA machines too, and
pragmatically, a lot of ISA devices *are* shared-memory or PIO.