Subject: Re: diff betw. bus_space_{read,write} and
To: None <bouyer@antioche.lip6.fr>
From: Ken Nakata <kenn@synap.ne.jp>
List: tech-kern
Date: 08/24/1998 09:04:07
On Mon, 27 Jul 1998 03:50:45 +0200, Manuel Bouyer wrote:
> On Aug 22, Ken Nakata wrote
> > And you say wrong byte-order will occur WITH a byte-swapper.  Why?  I
> > suspect we speak two different languages; i.e. I don't call something
> > what you call a byte-swapper a byte-swapper.
> 
> I suspect the confusion is in the endian byte order notion.
> 
> suppose you have the string "NetBSD". This is an endian-independant quantity
> That is, on your IDE drive you will have 'N' in byte 0, 'e' in 1, 't' in 2, ...
> If you transfert this in the mac's memory you will have, because of
> the bridge conversion, 'e' in byte 0, 'N' in byte 1, 'B' in byte 2,
> 't' in byte 3 ... and this will be printed "eNBtDS".

Ok... I think I'm getting at it.  In my notion, a byte-swapper is a
hardware entity (well, it's just a bunch of wirings but
nevertheless...) but in your notion, byte-swapping occurs when order
of bytes changes.  So, when host's bits 24-31 and bits 16-23 are wired
to IDE bus's bits 0-7 and bits 8-16, respectively, I see a byte-
swapper there, but in the bus_space context, I should not.  It
preserves byte order between IDE and host buses, so there is NO
byte-swapping occurring.

bus_space_read{,_multi}_2() read values as 16-bit quantities from the
I/O bus, therefore it has to byte-swap each quantity read if host and
I/O buses' byte orders are different _and_ the bridge between them
preserves the order of byte stream.

So, in mac68k's case, bus_space_read_muilti_2() should byte-swap each
u_int16_t, but it does not.

> byte-order is only important for 16 and 32 bit integer values. So
> only these integer values will be stored differently in memory for a
> little-endian and a big-endian CPU. All other values (8-bit
> integers, strings, ieee floating points numbers) are identical.

A minor nit: I think it is also important for IEEE floats.  They are
usually not treated as strings of bytes.

> So doing byte-swapping at hardware level is plain wrong, because only some
> values need to be byte-swapped.

Ok, if I understand it correctly, the bridge does not byte-swap, so
it's okay, right?

> > [...]
> > No.  The stupid bridge always does its only job to preserve the byte
> > order, and that's why I'm getting every short in the wrong order (in
> > little endian, that is).
> 
> So  there's something wrong: either the bridge doens't do byte-swapping, or
> bus_space_read_2 does.

No, its behavior is consistent.  And, you're right, in this context,
the hardware bridge does NOT byte-swap.  See my argument about the
notion of byte-swapper above.

> It's a standart IDE drive (i.e a quantun, IBM or something else you've
> purchased in a PC hardware reseller) or an APPLE one ?

Doesn't matter.  They behave the same in this respect (If they did
not, the IDE Mac owners would not be able to purchase a third-party
IDE drive and swap the original drive with it!)

> With a standart IDE drive, in datas returned by the IDENTIFY
> command, shorts are in little-endian format and strings are their
> letters swapped 2 by 2 (i.e. for "IBM" you have B in byte 0, I in
> byte 1, ' ' in byte 2 and M in byte 3. That's not because it's
> little-endian, that's because ATA(PI) specs are silly).

I know.

My proposal to "fix" wdc.c for mac68k:

Since mac68k bus_space_{read,write}{,_multi}_2() do not byte-swap, and
making them conditionally do so depending on the tag would give all
other bus_space_{read,write}*() a performance hit, not just the
byte-swapping accesses, I propose wdc_get_parms() be changed like
this:

                /* Read in parameter block. */
                bus_space_read_multi_2(wdc->sc_iot, wdc->sc_ioh, wd_data,
                    (u_int16_t *)tb, sizeof(tb) >> 1);
#if !defined(__BUS_SPACE_HAS_STREAM_METHODS) && (BYTE_ORDER == BIG_ENDIAN)
		for (i = 0; i < sizeof(tb); i += 2) {
			register u_int16_t t = *(u_int16_t *)(&tb[i]);
			*(u_int16_t *)(&tbl[i]) = (t << 8) | (t >> 8);
		}
#endif
                bcopy(tb, &d_link->sc_params, sizeof(struct wdparams));

If the arch does not have the stream methods, I don't think you can
expect the non-stream bus_space_read_multi_2() to handle endian
difference.  You cannot, at least with the mac68k bus_space
implementation.

How about this?

Ken