linux-mips-fnet
[Top] [All Lists]

Re: pointer assignment (fwd)

To: linux-mips@fnet.fr
Subject: Re: pointer assignment (fwd)
From: Richard van den Berg <R.vandenBerg@inter.NL.net>
Date: Thu, 17 Sep 1998 16:42:11 +0200 (MET DST)
Hi,

Thought more people might be interested in this answer (and Harald, this
answers my SSR writing question):

---------- Forwarded message ----------
Date: Thu, 17 Sep 1998 13:58:35 GMT
From: Chris Torek <torek@elf.bsdi.com>
Newsgroups: comp.lang.c.moderated
Subject: Re: pointer assignment

In article <clcm-19980915-0004@plethora.net> Richard van den Berg
<R.vandenBerg@inter.NL.net> quotes himself and others, and writes:

[Richard van den Berg]
> struct lance_regs {
>         unsigned short rdp;     /* register data port */
>         unsigned short rap;     /* register acces port */
>};

[Doug Gwyn]
>There is an assumption there that the struct has no padding
>between the members. ...

[Richard again]
>That is a gcc little endian MIPS cross-compiler on a Linux i486, but
>don't know how it implements.

In private mail to me, he mentions also that the target machine
is a DECstation (hence "little-endian MIPS" above).

An important point that has been missing from all of the discussion
here is that this particular DEC box does not "do" 16-bit accesses
to external hardware, even if that hardware requires 16-bit accesses.
The machine only does 32-bit accesses.

To compensate for this, external hardware that requires 16-bit
access (such as the AMD Lance) is connected via some special
address-mapping hardware, so that every 16-bit "word" is accessible
to the processor in every *other* 16-bit address.  (The values in
the "padding" between these words are probably either copies, or
float high or low, depending on how the wiring works.)

>This works:
>       unsigned char *p = 0;
>and use p[base_addr] and p[base_addr + 4] for reading and writing ...

This is no better (in fact it is worse, because it retrieves only one
of the two bytes making up the 16-bit value).

One thing that would work is:

        struct lance_regs {
                unsigned short rdp;
                unsigned short pad0;
                unsigned short rap;
                unsigned short pad1;    /* (this member could be omitted) */
        };

Note that this data definition is wrong on *other* machines, where
the bus (or bus bridge, or adapter, or whatever they call the glue
between the CPU and the I/O devices) does not introduce padding.

The NetBSD operating system has a rather well-thought-out concept
of "bus spaces" and "bus I/O operations" that allows a single driver
(such as an AMD Lance driver) to operate on machines as disparate
as the i386 (no padding, and uses inw/outw to talk to the registers),
this same DECstation (2 bytes of padding per shortword), a DEC
Alpha (6 bytes of padding), a SPARCstation (no padding, but
big-endian), and so on.  There is some performance penalty in going
through all the layering, and it can be rather confusing to work
with ("do I need a read_multi_2" or a "read_region_2" here?), but
once you buy into it, you gain quite a bit of portability.
-- 
In-Real-Life: Chris Torek, Berkeley Software Design Inc
El Cerrito, CA  Domain: torek@bsdi.com  +1 510 234 3167
Antispam notice: unsolicited commercial email will be handled at my
consulting rate; pyramid-scheme mail will be forwarded to the FTC.
-- 
comp.lang.c.moderated - clcm@plethora.net


<Prev in Thread] Current Thread [Next in Thread>
  • Re: pointer assignment (fwd), Richard van den Berg <=