another endianness issue...

Geert Uytterhoeven geert at linux-m68k.org
Mon Jun 25 00:52:34 EST 2001


On Sun, 24 Jun 2001, Guillaume Laurès wrote:
> Timothy A. Seufert wrote:
> > Kill the struct definition, and replace it with a bunch of accessor
> > macros that mask-and-shift.  When moving the register value to or
> > from the hardware, use le32_to_cpu() and cpu_to_le32() as appropriate.
>
> Okay, so as this are my first steps in kernel programming, let's take an
> example :-)
>
> Somewhere at the beginning of the driver we have something like this:
>
> while (DAC960_LA_InitializationInProgressP(BaseAddress))
> {blabla}
>
> DAC960_LA_InitializationInProgressP() is defined as follows in the .h:
>
> static inline
> boolean DAC960_BA_InitializationInProgressP(void *ControllerBaseAddress)
> {
>   DAC960_BA_InboundDoorBellRegister_T InboundDoorBellRegister;
>   InboundDoorBellRegister.All =
>    readb(ControllerBaseAddress + DAC960_BA_InboundDoorBellRegisterOffset);
>   return !InboundDoorBellRegister.Read.InitializationNotInProgress;
> }
>
> and, for the record, the DAC960_BA_InboundDoorBellRegister_T is
> something like this:
>
> typedef union DAC960_BA_InboundDoorBellRegister
> {
>   unsigned char All;
>   struct {
>    boolean HardwareMailboxNewCommand:1;                /* Bit 0 */
>    boolean AcknowledgeHardwareMailboxStatus:1;         /* Bit 1 */
>    boolean GenerateInterrupt:1;                        /* Bit 2 */
>    boolean ControllerReset:1;                          /* Bit 3 */
>    boolean MemoryMailboxNewCommand:1;                  /* Bit 4 */
>    unsigned char :3;                                   /* Bits 5-7 */
>   } Write;
>   struct {
>    boolean HardwareMailboxEmpty:1;                     /* Bit 0 */
>    boolean InitializationNotInProgress:1;              /* Bit 1 */
>    unsigned char :6;                                   /* Bits 2-7 */
>   } Read;
> }
> DAC960_BA_InboundDoorBellRegister_T;
>
>
>
> What would I do now is modify  DAC960_LA_InitializationInProgressP() as
> follows:
>
> static inline
> boolean DAC960_BA_InitializationInProgressP(void *ControllerBaseAddress)
> {
>   unsigned long InboundDoorBellRegister =
>    le32_to_cpu(ControllerBaseAddress +
> DAC960_BA_InboundDoorBellRegisterOffset);
>   return (boolean) !(InboundDoorBellRegister & 0x0002);
> }
>
> Is it correct ?

No, you must still use readb(), not a direct memory access.
Furthermore readw() and readl() do byteswapping theirselves on big-endian
architectures.

For this case le32_to_cpu() is wrong too, because it's meant for 32-bit
access while the original code used readb(), which does an 8 bit-access.
And 8-bit accesses don't have to be swapped.

Their is another issue with bitfields, though: their definition is reversed
for little and big endian machines. So you need two different struct
definitions, depending on the endianness.

> And where can I find the cpu_to_le32() and le32_to_cpu() declaration or
> a guide on how to use them ?

include/linux/byteorder/

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
							    -- Linus Torvalds


** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/





More information about the Linuxppc-dev mailing list