Subject: mii_attach(): where is the PHY?
To: None <tech-kern@netbsd.org>
From: Emmanuel Dreyfus <p99dreyf@criens.u-psud.fr>
List: tech-kern
Date: 06/30/2001 19:21:58
Hello

As some of you might know, the if_xi driver does not work with the
Xircom REM56G100 card.

I had a look at the problem, and it is located in mii_attach(): it tries
32 locations, and it does not find any PHY. If always fails at this
test:

      bmsr = (*mii->mii_readreg)(parent, ma.mii_phyno, MII_BMSR);
      if (bmsr == 0 || bmsr == 0xffff ||
          (bmsr & BMSR_MEDIAMASK) == 0) {
         /* Assume no PHY at this address. */
         continue;
      }

If I comment out the continue and hence force ukphy to attach at this
location, ukphy will not find any device either. I also tried to
increase phyno to 256 instead of 32, no success.

The question is: how do I find where the PHY really is? Is there a
method for that?

There might be some usefull information to take from the Linux driver,
because it works with theses cards. Attached is the part that seems
revelant to me, if someone find something helpful in it, please tell me!


/****************
 * Initialize the Media-Independent-Interface
 * Returns: True if we have a good MII
 */
static int
init_mii(struct net_device *dev)
{
    local_info_t *local = dev->priv;
    ioaddr_t ioaddr = dev->base_addr;
    unsigned control, status, linkpartner;
    int i; 
        
    status = mii_rd(ioaddr,  0, 1);
    if ((status & 0xff00) != 0x7800)
        return 0; /* No MII */
        
    local->new_mii = (mii_rd(ioaddr, 0, 2) != 0xffff); 
            
    if (local->probe_port)
        control = 0x1000; /* auto neg */
    else if (dev->if_port == 4)
        control = 0x2000; /* no auto neg, 100mbs mode */
    else
        control = 0x0000; /* no auto neg, 10mbs mode */
    mii_wr(ioaddr,  0, 0, control, 16);
    udelay(100);
    control = mii_rd(ioaddr, 0, 0);

    if (control & 0x0400) {
        printk(KERN_NOTICE "%s can't take PHY out of isolation mode\n",
               dev->name);
        local->probe_port = 0;
        return 0;
    }

    if (local->probe_port) {
        /* according to the DP83840A specs the auto negotiation process
         * may take up to 3.5 sec, so we use this also for our ML6692
         * Fixme: Better to use a timer here!
         */
        for (i=0; i < 35; i++) {
            busy_loop(HZ/10);    /* wait 100 msec */
            status = mii_rd(ioaddr,  0, 1);
            if ((status & 0x0020) && (status & 0x0004))
                break;
        }

        if (!(status & 0x0020)) {
            printk(KERN_INFO "%s: autonegotiation failed;"
                   " using 10mbs\n", dev->name);
            if (!local->new_mii) {
                control = 0x0000;
                mii_wr(ioaddr,  0, 0, control, 16);
                udelay(100);
                SelectPage(0);
                dev->if_port = (GetByte(XIRCREG_ESR) & MediaSelect) ? 1
: 2;
            }
        } else {
            linkpartner = mii_rd(ioaddr, 0, 5);
            printk(KERN_INFO "%s: MII link partner: %04x\n",
                   dev->name, linkpartner);
            if (linkpartner & 0x0080) {
                dev->if_port = 4;
            } else
                dev->if_port = 1;
        }
    }

    return 1;
}


-- 
Emmanuel Dreyfus.
"Le 80x86 n'est pas si complexe - il n'a simplement pas de sens"
(Mike Johnson, responsable de la conception x86 chez AMD) 
p99dreyf@criens.u-psud.fr