Subject: Re: bus_dmamem accessors
To: Chris G. Demetriou <cgd@sibyte.com>
From: Eduardo Horvath <eeh@turbolinux.com>
List: tech-kern
Date: 07/31/2000 11:36:43
On 31 Jul 2000, Chris G. Demetriou wrote:

> So, the issue of bus_dmamem accessors came up about a month ago
> (starting with
> http://mail-index.netbsd.org/tech-kern/2000/06/25/0000.html), and i
> was trying to ask a question about the specification of their
> behaviour and got what I thought was an inadequate reply (query quoted
> and response at
> http://mail-index.netbsd.org/tech-kern/2000/06/25/0010.html).
> 
> (btw, bus_dmamem_read_1 seemed to be missing from the original
> proposal, i dunno about the followups.  looking at the original
> proposal, i don't think i get the use of addr vs. offsets -- i'd think
> the latter would be more correct -- but since the list archives don't
> support reading my thread...)
> 
> 
> To be a bit more concrete about my example:
> 
> * PCI.
> 
> * HBA which can support byte swapping, and does byte swapping on PCI
> "word" (4-byte naturally aligned) boundaries.  i.e., it's willing to
> do:
> 
> 	(BE) mem addr 0:	1
> 	(BE) mem addr 1:	2
> 	(BE) mem addr 2:	3
> 	(BE) mem addr 3:	4
> 
> 	->
> 
> 	PCI byte 0 (BE#[0]):	1
> 	PCI byte 1 (BE#[0]):	2
> 	PCI byte 2 (BE#[0]):	3
> 	PCI byte 3 (BE#[0]):	4

Looks like you're allways reading the same location there 8^).

> (it's also willing to do unswapped accesses.)  This works regardless
> of sizing, i.e. if a PCI device asks for bytes 2 and 3, it'll always
> get values 3 and 4 respectively in those bytes.  (This makes sense,
> since PCI has a bus width of 4 bytes -- at least 32-bit wide PCI does,
> i dunno how 64-bit PCI affects things w.r.t. word ordering.)

If the device does `swapping' it should be doing so based on individual
accesses.  Otherwise the `swapping' is broken and should be turned
off.  It should not be doing swapping on arbitrary bit/byte boundaries.

HME is an example of a device that does swapping correctly.  When it reads
a short it swaps 2 bytes.  When it reads a long it swaps 4 bytes.

ISP is a device that does it wrong.  It's a word machine and always swaps
on 2-byte boundaries.  This means that the memory layout of the ISP queue
entries is different for SBus and PCI.

Don't you just love it when the H/W guys who don't really understand the
problem decide to be `helpful'?

> * another HBA which doesn't support swapping in HW.
> 
> * the DMA memory being fiddled with is actually a DMA descriptor,
> consisting for sake of argument of:
> 
> 	* 1 byte field at offset 0
> 	* 1 byte field at offset 1
> 	* 2 byte field at offset 2
>
> What is the correct set of bus_dmamem accessor calls to set and get
> the value of each of those fields, and what do those functions do
> internally?
> 
> 
> I believe the answer should be:
> 
> accessing the first:
> 
> 	bus_dmamem_{read,write}_1(map, 0);	/* 0 is offset */
> 
> 	which, on my first hypothetical ("swapping") system would
> 	access byte 0, but which on my second hypotehtical
> 	("non-swapping") system would access byte 3.

No.  In both cases that should be byte 0.

> 
> accessing the second:
> 
> 	bus_dmamem_{read,write}_1(map, 1);	/* 1 is offset */
> 
> 	accessing byte 1 on swapping system, or 2 on non-swapping
> 	system.

Once again that should always be byte 1.

> accessing the third:
> 
> 	bus_dmamem_{read,write}_2(map, 2);	/* 2 is offset */
> 	
> 	on a swapping system, this accesses bytes 2 and 3, and
> 	reads/writes a value in host order.  on a non-swapping system,
> 	this would access bytes 0 and 1, and need to do a byte-swap
> 	in software.

In this case, bytes 3 and 4 should be swapped, depending on whether you
specify that this is a BE device or a LE device.

> The response to my question (URL included above) could easily be read
> to indicate that the semantics are other than this, and specifically
> are that the HW will access and swap according to the "unit of
> access."
> 
> in other words, it might be that the intent is to require for the
> above:
> 
> 	bus_dmamem_{read,write}_1(map, be_host ? 3 : 0);
> 	bus_dmamem_{read,write}_1(map, be_host ? 2 : 1);
> 	bus_dmamem_{read,write}_2(map, be_host ? 0 : 2);
> 
> I'd argue that that's highly bogus.  8-)

That is not `highly bogus'.  The swapping must be done on the "unit of
access".  Anything else is broken.  Your so-called `swapping' device's
unit of access is 4.  Hence, if you insist on taking advantage of that
`swapping' you need to always do rmw accesses through
bus_dmamem_{read,write}_4.

Eduardo Horvath