linux-c-programming.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Confuse with big endian bitwise field
@ 2007-06-26 10:20 Li YanBo
  2007-06-26 18:09 ` Kristof Provost
  2007-06-28 14:39 ` Arjan van de Ven
  0 siblings, 2 replies; 7+ messages in thread
From: Li YanBo @ 2007-06-26 10:20 UTC (permalink / raw)
  To: linux-c-programming; +Cc: kernelnewbies

hi all,

I am try  to define a hardware specific struct, it is like below:

struct xxx {
        __be32 pdu_cnt:6;
        __be32 y:3;
        __be32 wep_key:2;
        __be32 uses_wep_key:1;
        __be32 keep_alive:1;
        __be32 buff_tail_addr:19;

        __be32 cts_11g:1;
        __be32 rts_11g:1;
        __be32 x:2;
        __be32 frag_size:12;
        __be32 payload_len:12;
        __be32 frag_num:4;
}

but I am confuse with how to assign the values to the fields
"buff_tail_addr" and "payload_len", I think there  are two ways to
assign values to them, but I don't know which is right?

eg: I declare a variable  struct xxx X;

1: X.buff_tail_addr = 0x3456;                        X.payload_len = 0x20;
2: X.buff_tail_addr = cpu_to_be32(0x3456);    X.payload_len = cpu_to_be16(0x20);

There are two way I think to assign values. Could anyone tell me which
is right or both are wrong? I will be appreciate for any hints, thanks
in advance!

BR

lyb

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Confuse with big endian bitwise field
  2007-06-26 10:20 Confuse with big endian bitwise field Li YanBo
@ 2007-06-26 18:09 ` Kristof Provost
  2007-06-28 14:39 ` Arjan van de Ven
  1 sibling, 0 replies; 7+ messages in thread
From: Kristof Provost @ 2007-06-26 18:09 UTC (permalink / raw)
  To: Li YanBo; +Cc: linux-c-programming, kernelnewbies

On 2007-06-26 18:20:35 (+0800), Li YanBo <dreamfly281@gmail.com> wrote:
> hi all,
> 
> I am try  to define a hardware specific struct, it is like below:
> 
> struct xxx {
>        __be32 pdu_cnt:6;
>        __be32 y:3;
>        __be32 wep_key:2;
>        __be32 uses_wep_key:1;
>        __be32 keep_alive:1;
>        __be32 buff_tail_addr:19;
> 
>        __be32 cts_11g:1;
>        __be32 rts_11g:1;
>        __be32 x:2;
>        __be32 frag_size:12;
>        __be32 payload_len:12;
>        __be32 frag_num:4;
> }
> 
> but I am confuse with how to assign the values to the fields
> "buff_tail_addr" and "payload_len", I think there  are two ways to
> assign values to them, but I don't know which is right?
> 
> eg: I declare a variable  struct xxx X;
> 
> 1: X.buff_tail_addr = 0x3456;                        X.payload_len = 0x20;
> 2: X.buff_tail_addr = cpu_to_be32(0x3456);    X.payload_len = 
> cpu_to_be16(0x20);
> 
> There are two way I think to assign values. Could anyone tell me which
> is right or both are wrong? I will be appreciate for any hints, thanks
> in advance!
> 
> BR
> 
> lyb

Disclaimer: I'm not exactly an expert, so someone tell me if I'm wrong.

You'll need to use cpu_to_be32, to make sure the values you assign are
big endian too. You'll need to do this for every field larger than 8
bits (as endianness is not an issue if there's only one byte).

You should be able to test this if you write a small program to populate
that struct and then dump it byte per byte (or just use gdb to see the
content).

Kristof

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Confuse with big endian bitwise field
  2007-06-26 10:20 Confuse with big endian bitwise field Li YanBo
  2007-06-26 18:09 ` Kristof Provost
@ 2007-06-28 14:39 ` Arjan van de Ven
  2007-06-28 14:59   ` Li YanBo
  2007-06-28 15:25   ` Ranjan Sinha
  1 sibling, 2 replies; 7+ messages in thread
From: Arjan van de Ven @ 2007-06-28 14:39 UTC (permalink / raw)
  To: Li YanBo; +Cc: linux-c-programming, kernelnewbies

On Tue, 2007-06-26 at 18:20 +0800, Li YanBo wrote:
> hi all,
> 
> I am try  to define a hardware specific struct, it is like below:
> 
> struct xxx {
>         __be32 pdu_cnt:6;
>         __be32 y:3;
>         __be32 wep_key:2;
>         __be32 uses_wep_key:1;
>         __be32 keep_alive:1;
>         __be32 buff_tail_addr:19;
> 
>         __be32 cts_11g:1;
>         __be32 rts_11g:1;
>         __be32 x:2;
>         __be32 frag_size:12;
>         __be32 payload_len:12;
>         __be32 frag_num:4;
> }

this isn't safe if you want to mimic hardware layout; the order of the
bits in the struct is different for little endian and big endian
machines...

-- 
if you want to mail me at work (you don't), use arjan (at) linux.intel.com
Test the interaction between Linux and your BIOS via http://www.linuxfirmwarekit.org


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Confuse with big endian bitwise field
  2007-06-28 14:39 ` Arjan van de Ven
@ 2007-06-28 14:59   ` Li YanBo
  2007-06-28 15:25   ` Ranjan Sinha
  1 sibling, 0 replies; 7+ messages in thread
From: Li YanBo @ 2007-06-28 14:59 UTC (permalink / raw)
  To: Arjan van de Ven; +Cc: linux-c-programming, kernelnewbies

On 6/28/07, Arjan van de Ven <arjan@infradead.org> wrote:
> On Tue, 2007-06-26 at 18:20 +0800, Li YanBo wrote:
> > hi all,
> >
> > I am try  to define a hardware specific struct, it is like below:
> >
> > struct xxx {
> >         __be32 pdu_cnt:6;
> >         __be32 y:3;
> >         __be32 wep_key:2;
> >         __be32 uses_wep_key:1;
> >         __be32 keep_alive:1;
> >         __be32 buff_tail_addr:19;
> >
> >         __be32 cts_11g:1;
> >         __be32 rts_11g:1;
> >         __be32 x:2;
> >         __be32 frag_size:12;
> >         __be32 payload_len:12;
> >         __be32 frag_num:4;
> > }
>
> this isn't safe if you want to mimic hardware layout; the order of the
> bits in the struct is different for little endian and big endian
> machines...
>

Yes, I realize it now, and maybe shifting bits is a more portability solution.

> Kristof wrote:
>You'll need to use cpu_to_be32, to make sure the values you assign
arebig endian too. >You'll need to do this for every field larger than
8 bits (as endianness is not an issue if >there's only one byte).

I have done many tests and it seemed by using cpu_to_be32 to the field
larger than 8 bits is not a correct solution. it will generate wrong
data too. Anywhere the switch between Be to Le or from Le to Be is a
complex thing, because it is not just the order of bytes but also the
order of bits, I found a good article to describe this problem
"http://www.linuxjournal.com/article/6788"

Thank for all your suggestion.

BR

LiYanBo

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Confuse with big endian bitwise field
  2007-06-28 14:39 ` Arjan van de Ven
  2007-06-28 14:59   ` Li YanBo
@ 2007-06-28 15:25   ` Ranjan Sinha
  2007-07-03  4:12     ` Li YanBo
  1 sibling, 1 reply; 7+ messages in thread
From: Ranjan Sinha @ 2007-06-28 15:25 UTC (permalink / raw)
  To: Arjan van de Ven; +Cc: Li YanBo, linux-c-programming, kernelnewbies

Thanks for this discussion, since this really gets confusing at times.
> >
> > struct xxx {
> >         __be32 pdu_cnt:6;
> >         __be32 y:3;
> >         __be32 wep_key:2;
> >         __be32 uses_wep_key:1;
> >         __be32 keep_alive:1;
> >         __be32 buff_tail_addr:19;
> >
> >         __be32 cts_11g:1;
> >         __be32 rts_11g:1;
> >         __be32 x:2;
> >         __be32 frag_size:12;
> >         __be32 payload_len:12;
> >         __be32 frag_num:4;
> > }
>
> this isn't safe if you want to mimic hardware layout; the order of the
> bits in the struct is different for little endian and big endian
> machines...
>
What is the best way in such scenario? Should we then use an unsigned
char array and then keep separate mappings of each bit for little and
big endian machines ?

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Confuse with big endian bitwise field
  2007-06-28 15:25   ` Ranjan Sinha
@ 2007-07-03  4:12     ` Li YanBo
  2007-07-10  3:58       ` Li YanBo
  0 siblings, 1 reply; 7+ messages in thread
From: Li YanBo @ 2007-07-03  4:12 UTC (permalink / raw)
  To: Ranjan Sinha; +Cc: Arjan van de Ven, linux-c-programming, kernelnewbies

On 6/28/07, Ranjan Sinha <rnjn.sinha@gmail.com> wrote:
> Thanks for this discussion, since this really gets confusing at times.
> > >
> > > struct xxx {
> > >         __be32 pdu_cnt:6;
> > >         __be32 y:3;
> > >         __be32 wep_key:2;
> > >         __be32 uses_wep_key:1;
> > >         __be32 keep_alive:1;
> > >         __be32 buff_tail_addr:19;
> > >
> > >         __be32 cts_11g:1;
> > >         __be32 rts_11g:1;
> > >         __be32 x:2;
> > >         __be32 frag_size:12;
> > >         __be32 payload_len:12;
> > >         __be32 frag_num:4;
> > > }
> >
> > this isn't safe if you want to mimic hardware layout; the order of the
> > bits in the struct is different for little endian and big endian
> > machines...
> >
> What is the best way in such scenario? Should we then use an unsigned
> char array and then keep separate mappings of each bit for little and
> big endian machines ?
>

I am sorry I still can't figure out how to use bits shift and make it
can be portability to any Be or Le endian machine. what I can tell you
is if the bits fields was define for Be, and if the host is Le, so you
just need reverse the order of bits field and it will work well. For
example:

That a specs define for Be:
Descriptor(big endian)  size   offset
RTS                            1        0
multicast                     1        1
x                                15       2
y                                15       17

If you want define it in Le host, we can define it like this
struct desc {
         y:15;
         x:15;
         muticast:1;
         rts:1;
} __attribute__ ((packed));
	
That only my personal opinion, CMIIW. if anyone know better method,
please share with us. thanks!

BR

lyb

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Confuse with big endian bitwise field
  2007-07-03  4:12     ` Li YanBo
@ 2007-07-10  3:58       ` Li YanBo
  0 siblings, 0 replies; 7+ messages in thread
From: Li YanBo @ 2007-07-10  3:58 UTC (permalink / raw)
  To: Ranjan Sinha; +Cc: Arjan van de Ven, linux-c-programming, kernelnewbies

On 7/3/07, Li YanBo <dreamfly281@gmail.com> wrote:
> On 6/28/07, Ranjan Sinha <rnjn.sinha@gmail.com> wrote:
> > Thanks for this discussion, since this really gets confusing at times.
> > > >
> > > > struct xxx {
> > > >         __be32 pdu_cnt:6;
> > > >         __be32 y:3;
> > > >         __be32 wep_key:2;
> > > >         __be32 uses_wep_key:1;
> > > >         __be32 keep_alive:1;
> > > >         __be32 buff_tail_addr:19;
> > > >
> > > >         __be32 cts_11g:1;
> > > >         __be32 rts_11g:1;
> > > >         __be32 x:2;situation
> > > >         __be32 frag_size:12;
> > > >         __be32 payload_len:12;
> > > >         __be32 frag_num:4;
> > > > }
> > >
> > > this isn't safe if you want to mimic hardware layout; the order of the
> > > bits in the struct is different for little endian and big endian
> > > machines...
> > >
> > What is the best way in such scenario? Should we then use an unsigned
> > char array and then keep separate mappings of each bit for little and
> > big endian machines ?
> >
>
> I am sorry I still can't figure out how to use bits shift and make it
> can be portability to any Be or Le endian machine. what I can tell you
> is if the bits fields was define for Be, and if the host is Le, so you
> just need reverse the order of bits field and it will work well. For
> example:
>
> That a specs define for Be:
> Descriptor(big endian)  size   offset
> RTS                            1        0
> multicast                     1        1
> x                                15       2
> y                                15       17
>
> If you want define it in Le host, we can define it like this
> struct desc {
>          y:15;
>          x:15;
>          muticast:1;
>          rts:1;
> } __attribute__ ((packed));
>
> That only my personal opinion, CMIIW. if anyone know better method,
> please share with us. thanks!
>

Define the bits field as follow can be portable to either  Le or Be host.
For the above sample, we can define it like that:

#define RTS         0x80000000
#define multicast  0x40000000
#define x              0x3FFF8000
#define y              0x00007FFF
I think that can make sure it can be portable in Be or Le host.

But there is another  situation confuse me, if the data are come from
net, ie the wireless 802.11 header, even we define the structure like
that, we also need to do cpu_to_le32 or le32_to_cpu() manual. I don't
know is it different for data that transport from CPU to IO device or
data that transport from CPU to net?

BR
lyb

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2007-07-10  3:58 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-06-26 10:20 Confuse with big endian bitwise field Li YanBo
2007-06-26 18:09 ` Kristof Provost
2007-06-28 14:39 ` Arjan van de Ven
2007-06-28 14:59   ` Li YanBo
2007-06-28 15:25   ` Ranjan Sinha
2007-07-03  4:12     ` Li YanBo
2007-07-10  3:58       ` Li YanBo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).