[En-Nut-Discussion] FW: AVR32 / ARM support

Bernd Walter enut at cicely.de
Tue Sep 28 23:18:26 CEST 2010


On Tue, Sep 28, 2010 at 04:57:16PM -0300, Thiago A. Corrêa wrote:
> Hi,
> 
> On Tue, Sep 28, 2010 at 3:38 PM, Bernd Walter <enut at cicely.de> wrote:
> > On Tue, Sep 28, 2010 at 11:43:07AM -0300, Thiago A. Corrêa wrote:
> >
> > I have no expirience with the Micrel, but I'm running AT91SAM7X256 with
> > RTL8305SC.
> > The RTL8305SC - and I think the Micrel too - uses multiple PHY addressings
> > for the ports and additional for further VLAN registers.
> > PHY0 contains link speed/duplex information for port0, PHY1 for port1, ...
> 
> Interesting. From what I understand the phy does the actuall switching
> (copy data from one port to another and maintain address tables)
> right?

Yes.
The difference to a phy is that a phy has a single phy address with
multiple registers.
You can connect multiple PHY to a single MAC, e.g. one for cooper and
another one for fiber.
Each PHY has a single address and registers to configure, including
registers about the link negotiation.
The link registers are standardized and most of the PHY agree to that,
so that it is not really important to know the exact PHY.
A switch usually has multiple addresses for each physical port, but
none of them is of direct interest for the link speed of the MAC.
If you read out PHY0 for link negotiation you get the physical cooper
port0, which has nothing to do with the MII - the MII is running without
negotiation at all, since the switch is no real PHY for the MAC.
You might notice this when you connect the switch to the MAC that some
wires a slightly different than for a real PHY.

> > When negotiating link specification for MII you need to hardcode the
> > values to 100M-FDX instead of using the unrelated port0 negotiation.
> 
> If I'm not mistaken, it can be taken care of in the nutconf. I think
> the ARM code has that option.

I never saw that in code, so whatever nutconf does it can't influence
how it works.

> Quite easy to do in the other archs.
> 
> > Getting the MII wiring right is by far more difficult than to do the
> > software part - nothing to worry about.
> > My local patch is available under http://www.cicely.de/~ticso/at91_emac.c
> >
> 
> Got a 404 on the link.

Sorry - did something wrong during upload.

> Would you care to send to the list or the tracker for merging?
> 
> >> > 3.       IPv6 support.
> >
> > Unfortunately there is a lot of work to be done.
> [..]
> > We should start with multiple address support and then do multicast.
> > Although multicast isn't that important for IPv4 it is a basic
> > IPv6 requirement and it needs multiple addresses first, since we need
> > to maintain a list of participated multicast groups.
> > Each NIC driver should to be extended for multicast to setup multicast
> > hashes - as a bad workaround activating promiscuous will do, but that
> > way the CPU will have to parse several unrelated packets even in a
> > switched network.
> 
> I need to study this. I know how IPv4 works, but I'm completely
> ignorant on IPv6.
> 
> 
> > I know how to calculate the hash tables with AT91 ATE interfaces, since
> > I recently fixed the hash calculation in the FreeBSD driver - to get
> > IPv6 working on AT91RM9200...
> >
> 
> The AT91 and AVR32 MAC are almost the same, with very few differences.
> I could try to port to avr32.
> How would it affect the upper layers?

Are you talking about multicast here?
If not - the PHY isn't related to uppper layer in any way.
For multicast you need multiple IP addresses at first.
One of them needs to be known as primary address as replacement for
unspecified address (all 0 in IPv4 and IPv6).
IPs need other flags as well, such as a multicast flag.
Since we only support a single interface it doesn't matter much where
you store it, but you need a list with a ability to add and remove
entries.
If you change the list the hash table in the MAC needs to be recalculated
and written to registers.
A UDP socket or TCP listen socket must support single address or any
address and routed acordingly to the given socket.
For multicast only UDP is required, but it should be done completely
in any case.

This is the FreeBSD MAC hashing code, which is proofed to work:
static uint32_t
ate_mac_hash(const uint8_t *buf)
{
        uint32_t index = 0;
        for (int i = 0; i < 48; i++) {
                index ^= ((buf[i >> 3] >> (i & 7)) & 1) << (i % 6);
        }
        return (index);
}

static int
ate_setmcast(struct ate_softc *sc)
{
        uint32_t index;
        uint32_t mcaf[2];
        u_char *af = (u_char *) mcaf;
        struct ifmultiaddr *ifma;
        struct ifnet *ifp;

        ifp = sc->ifp;

        if ((ifp->if_flags & IFF_PROMISC) != 0)
                return (0);
        if ((ifp->if_flags & IFF_ALLMULTI) != 0) {
                WR4(sc, ETH_HSL, 0xffffffff);
                WR4(sc, ETH_HSH, 0xffffffff);
                return (1);
        }

        /*
         * Compute the multicast hash.
         */
        mcaf[0] = 0;
        mcaf[1] = 0;
        if_maddr_rlock(ifp);
        TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
                if (ifma->ifma_addr->sa_family != AF_LINK)
                        continue;
                index = ate_mac_hash(LLADDR((struct sockaddr_dl *)
                    ifma->ifma_addr));
                af[index >> 3] |= 1 << (index & 7);
        }
        if_maddr_runlock(ifp);

        /*
         * Write the hash to the hash register.  This card can also
         * accept unicast packets as well as multicast packets using this
         * register for easier bridging operations, but we don't take
         * advantage of that.  Locks here are to avoid LOR with the
         * if_maddr_rlock, but might not be strictly necessary.
         */
        WR4(sc, ETH_HSL, mcaf[0]);
        WR4(sc, ETH_HSH, mcaf[1]);
        return (mcaf[0] || mcaf[1]);
}


-- 
B.Walter <bernd at bwct.de> http://www.bwct.de
Modbus/TCP Ethernet I/O Baugruppen, ARM basierte FreeBSD Rechner uvm.



More information about the En-Nut-Discussion mailing list