📄 tulip.c
字号:
case DC21041: if (tulip_debug > 2) printk(KERN_DEBUG "%s: 21041 media tick CSR12 %8.8x.\n", dev->name, csr12); switch (dev->if_port) { case 0: case 3: case 4: if (csr12 & 0x0004) { /*LnkFail */ /* 10baseT is dead. Check for activity on alternate port. */ tp->mediasense = 1; if (csr12 & 0x0200) dev->if_port = 2; else dev->if_port = 1; printk(KERN_INFO "%s: No 21041 10baseT link beat, Media switched to %s.\n", dev->name, medianame[dev->if_port]); outl(0, ioaddr + CSR13); /* Reset */ outl(t21041_csr14[dev->if_port], ioaddr + CSR14); outl(t21041_csr15[dev->if_port], ioaddr + CSR15); outl(t21041_csr13[dev->if_port], ioaddr + CSR13); next_tick = 10*HZ; /* 2.4 sec. */ } else next_tick = 30*HZ; break; case 1: /* 10base2 */ case 2: /* AUI */ if (csr12 & 0x0100) { next_tick = (30*HZ); /* 30 sec. */ tp->mediasense = 0; } else if ((csr12 & 0x0004) == 0) { printk(KERN_INFO "%s: 21041 media switched to 10baseT.\n", dev->name); dev->if_port = 0; select_media(dev, 0); next_tick = (24*HZ)/10; /* 2.4 sec. */ } else if (tp->mediasense || (csr12 & 0x0002)) { dev->if_port = 3 - dev->if_port; /* Swap ports. */ select_media(dev, 0); next_tick = 20*HZ; } else { next_tick = 20*HZ; } break; } break; case DC21140: case DC21142: case MX98713: default: { struct medialeaf *mleaf; unsigned char *p; if (tp->mtable == NULL) { /* No EEPROM info, use generic code. */ /* Not much that can be done. Assume this a generic MII or SYM transceiver. */ next_tick = 60*HZ; if (tulip_debug > 2) printk(KERN_DEBUG "%s: network media monitor CSR6 %8.8x " "CSR12 0x%2.2x.\n", dev->name, inl(ioaddr + CSR6), csr12 & 0xff); break; } mleaf = &tp->mtable->mleaf[tp->cur_index]; p = mleaf->leafdata; switch (mleaf->type) { case 0: case 4: { /* Type 0 serial or 4 SYM transceiver. Check the link beat bit. */ int offset = mleaf->type == 4 ? 5 : 2; s8 bitnum = p[offset]; if (p[offset+1] & 0x80) { if (tulip_debug > 1) printk(KERN_DEBUG"%s: Transceiver monitor tick " "CSR12=%#2.2x, no media sense.\n", dev->name, csr12); if (mleaf->type == 4) { if (mleaf->media == 3 && (csr12 & 0x02)) goto select_next_media; } break; } if (tulip_debug > 2) printk(KERN_DEBUG "%s: Transceiver monitor tick: CSR12=%#2.2x" " bit %d is %d, expecting %d.\n", dev->name, csr12, (bitnum >> 1) & 7, (csr12 & (1 << ((bitnum >> 1) & 7))) != 0, (bitnum >= 0)); /* Check that the specified bit has the proper value. */ if ((bitnum < 0) != ((csr12 & (1 << ((bitnum >> 1) & 7))) != 0)) { if (tulip_debug > 1) printk(KERN_DEBUG "%s: Link beat detected for %s.\n", dev->name, medianame[mleaf->media]); if ((p[2] & 0x61) == 0x01) /* Bogus Znyx board. */ goto actually_mii; break; } if (tp->medialock) break; select_next_media: if (--tp->cur_index < 0) { /* We start again, but should instead look for default. */ tp->cur_index = tp->mtable->leafcount - 1; } dev->if_port = tp->mtable->mleaf[tp->cur_index].media; if (media_cap[dev->if_port] & MediaIsFD) goto select_next_media; /* Skip FD entries. */ if (tulip_debug > 1) printk(KERN_DEBUG "%s: No link beat on media %s," " trying transceiver type %s.\n", dev->name, medianame[mleaf->media & 15], medianame[tp->mtable->mleaf[tp->cur_index].media]); select_media(dev, 0); /* Restart the transmit process. */ outl(tp->csr6 | 0x0002, ioaddr + CSR6); outl(tp->csr6 | 0x2002, ioaddr + CSR6); next_tick = (24*HZ)/10; break; } case 1: case 3: { /* 21140, 21142 MII */ int mii_reg1, mii_reg5; actually_mii: mii_reg1 = mdio_read(dev, tp->phys[0], 1); mii_reg5 = mdio_read(dev, tp->phys[0], 5); if (tulip_debug > 1) printk(KERN_INFO "%s: MII status %4.4x, Link partner report " "%4.4x, CSR12 %2.2x, %cD.\n", dev->name, mii_reg1, mii_reg5, csr12, tp->full_duplex ? 'F' : 'H'); if (mii_reg1 != 0xffff && (mii_reg1 & 0x0004) == 0) { int new_reg1 = mdio_read(dev, tp->phys[0], 1); if ((new_reg1 & 0x0004) == 0) { printk(KERN_INFO "%s: No link beat on the MII interface," " status then %4.4x now %4.4x.\n", dev->name, mii_reg1, new_reg1); if (tp->mtable && tp->mtable->has_nonmii) goto select_next_media; } } if (mii_reg5 == 0xffff || mii_reg5 == 0x0000) ; /* No MII device or no link partner report */ else if (tp->full_duplex_lock) ; else { int negotiated = mii_reg5 & tp->advertising[0]; int duplex = ((negotiated & 0x0100) != 0 || (negotiated & 0x00C0) == 0x0040); /* 100baseTx-FD or 10T-FD, but not 100-HD */ if (tp->full_duplex != duplex) { tp->full_duplex = duplex; if (tp->full_duplex) tp->csr6 |= 0x0200; else tp->csr6 &= ~0x0200; outl(tp->csr6 | 0x0002, ioaddr + CSR6); outl(tp->csr6 | 0x2002, ioaddr + CSR6); if (tulip_debug > 0) /* Gurppp, should be >1 */ printk(KERN_INFO "%s: Setting %s-duplex based on MII" " Xcvr #%d parter capability of %4.4x.\n", dev->name, tp->full_duplex ? "full" : "half", tp->phys[0], mii_reg5); } } next_tick = 60*HZ; break; } case 2: /* 21142 serial block has no link beat. */ default: break; } } break; } if (next_tick) { tp->timer.expires = RUN_AT(next_tick); add_timer(&tp->timer); }}/* Handle the 21143 uniquely: do autoselect with NWay, not the EEPROM list of available transceivers. */static void t21142_timer(unsigned long data){ struct device *dev = (struct device *)data; struct tulip_private *tp = (struct tulip_private *)dev->priv; long ioaddr = dev->base_addr; int csr12 = inl(ioaddr + CSR12); int next_tick = 60*HZ; int new_csr6 = 0; if (tulip_debug > 1) printk(KERN_INFO"%s: 21142 negotiation status %8.8x, %s.\n", dev->name, csr12, medianame[dev->if_port]); if (dev->if_port == 3) { if (csr12 & 2) { /* No 100mbps link beat, revert to 10mbps. */ new_csr6 = 0x82420200; outl(new_csr6, ioaddr + CSR6); outl(0x0000, ioaddr + CSR13); outl(0x0003FFFF, ioaddr + CSR14); outl(0x0008, ioaddr + CSR15); outl(0x0001, ioaddr + CSR13); outl(0x1301, ioaddr + CSR12); /* Start NWay. */ } } else if ((csr12 & 0x7000) != 0x5000) { /* Negotiation failed. Search media types. */ if (tulip_debug > 1) printk(KERN_INFO"%s: 21142 negotiation failed, status %8.8x.\n", dev->name, csr12); if (!(csr12 & 4)) { /* 10mbps link beat good. */ new_csr6 = 0x82420000; dev->if_port = 0; outl(0, ioaddr + CSR13); outl(0x0003FFFF, ioaddr + CSR14); outl(t21142_csr15[dev->if_port], ioaddr + CSR15); outl(t21142_csr13[dev->if_port], ioaddr + CSR13); } else if (csr12 & 0x100) { new_csr6 = 0x82420200; dev->if_port = 2; outl(0, ioaddr + CSR13); outl(0x0003FFFF, ioaddr + CSR14); outl(0x0008, ioaddr + CSR15); outl(0x0001, ioaddr + CSR13); } else { /* Select 100mbps port to check for link beat. */ new_csr6 = 0x83860000; dev->if_port = 3; outl(0, ioaddr + CSR13); outl(0x0003FF7F, ioaddr + CSR14); outl(8, ioaddr + CSR15); outl(1, ioaddr + CSR13); } if (tulip_debug > 1) printk(KERN_INFO"%s: Testing new 21142 media %s.\n", dev->name, medianame[dev->if_port]); if (new_csr6 != (tp->csr6 & ~0x00D5)) { tp->csr6 &= 0x00D5; tp->csr6 |= new_csr6; outl(0x0301, ioaddr + CSR12); outl(tp->csr6 | 0x0002, ioaddr + CSR6); outl(tp->csr6 | 0x2002, ioaddr + CSR6); } } tp->timer.expires = RUN_AT(next_tick); add_timer(&tp->timer);}static void t21142_lnk_change( struct device *dev){ struct tulip_private *tp = (struct tulip_private *)dev->priv; long ioaddr = dev->base_addr; int csr12 = inl(ioaddr + CSR12); if (tulip_debug > 1) printk(KERN_INFO"%s: 21142 link status interrupt %8.8x, CSR5 %x.\n", dev->name, csr12, inl(ioaddr + CSR5)); if ((csr12 & 0x7000) == 0x5000) { if (csr12 & 0x01800000) { /* Switch to 100mbps mode. */ outl(tp->csr6 | 0x0002, ioaddr + CSR6); if (csr12 & 0x01000000) { dev->if_port = 5; tp->csr6 = 0x83860200; } else { dev->if_port = 3; tp->csr6 = 0x83860000; } outl(tp->csr6 | 0x2002, ioaddr + CSR6); } /* Else 10baseT-FD is handled automatically. */ } else if (dev->if_port == 3) { if (!(csr12 & 2)) printk(KERN_INFO"%s: 21142 100baseTx link beat good.\n", dev->name); else dev->if_port = 0; } else if (dev->if_port == 0) { if (!(csr12 & 4)) printk(KERN_INFO"%s: 21142 10baseT link beat good.\n", dev->name); } else if (!(csr12 & 4)) { /* 10mbps link beat good. */ printk(KERN_INFO"%s: 21142 10mpbs sensed media.\n", dev->name); dev->if_port = 0; } else { /* 100mbps link beat good. */ printk(KERN_INFO"%s: 21142 100baseTx sensed media.\n", dev->name); dev->if_port = 3; tp->csr6 = 0x83860000; outl(0x0003FF7F, ioaddr + CSR14); outl(0x0301, ioaddr + CSR12); outl(tp->csr6 | 0x0002, ioaddr + CSR6); outl(tp->csr6 | 0x2002, ioaddr + CSR6); }} static void mxic_timer(unsigned long data){ struct device *dev = (struct device *)data; struct tulip_private *tp = (struct tulip_private *)dev->priv; long ioaddr = dev->base_addr; int next_tick = 60*HZ; if (tulip_debug > 3) { printk(KERN_INFO"%s: MXIC negotiation status %8.8x.\n", dev->name, inl(ioaddr + CSR12)); } if (next_tick) { tp->timer.expires = RUN_AT(next_tick); add_timer(&tp->timer); }}static void pnic_timer(unsigned long data){ struct device *dev = (struct device *)data; struct tulip_private *tp = (struct tulip_private *)dev->priv; long ioaddr = dev->base_addr; int csr12 = inl(ioaddr + CSR12); int next_tick = 60*HZ; int new_csr6 = tp->csr6 & ~0x40C40200; if (media_cap[dev->if_port] & MediaIsMII) { int negotiated = mdio_read(dev, tp->phys[0], 5) & tp->advertising[0]; if (tulip_debug > 1) printk(KERN_DEBUG "%s: LC82C168 negotiated capability %8.8x, " "CSR5 %8.8x.\n", dev->name, negotiated, inl(ioaddr + CSR5)); if (negotiated & 0x0380) /* 10 vs 100mbps */ new_csr6 |= 0x812E0000; else new_csr6 |= 0x816E0000; if (((negotiated & 0x0300) == 0x0100) /* Duplex */ || (negotiated & 0x00C0) == 0x0040 || tp->full_duplex_lock) { tp->full_duplex = 1; new_csr6 |= 0x0200; } if (tulip_debug > 1) printk(KERN_DEBUG "%s: LC82C168 MII PHY status %4.4x, Link " "partner report %4.4x, csr6 %8.8x/%8.8x.\n", dev->name, mdio_read(dev, tp->phys[0], 1), negotiated, tp->csr6, inl(ioaddr + CSR6)); } else { int phy_reg = inl(ioaddr + 0xB8); int csr5 = inl(ioaddr + CSR5); if (tulip_debug > 1) printk(KERN_DEBUG "%s: LC82C168 phy status %8.8x, CSR5 %8.8x.\n", dev->name, phy_reg, csr5); if (phy_reg & 0x04000000) { /* Remote link fault */ /*outl(0x0201F078, ioaddr + 0xB8);*/ next_tick = 3*HZ; } if (inl(ioaddr + CSR5) & TPLnkFail) { /* 100baseTx link beat */ if (tulip_debug > 1) printk(KERN_DEBUG "%s: %s link beat failed, CSR12 %4.4x, " "CSR5 %8.8x, PHY %3.3x.\n", dev->name, medianame[dev->if_port], csr12, inl(ioaddr + CSR5), inl(ioaddr + 0xB8)); if (tp->medialock) { } else if (dev->if_port == 0) { dev->if_port = 3; outl(0x33, ioaddr + CSR12); new_csr6 = 0x01860000; outl(0x1F868, ioaddr + 0xB8); } else { dev->if_port = 0; outl(0x32, ioaddr + CSR12); new_csr6 = 0x00420000; outl(0x1F078, ioaddr + 0xB8); } new_csr6 |= (tp->csr6 & 0xfdff); next_tick = 3*HZ; } else new_csr6 = tp->csr6; if (tp->full_duplex_lock || (phy_reg & 0x30000000) != 0) { tp->full_duplex = 1; new_csr6 |= 0x00000200; } } if (tp->csr6 != new_csr6) { tp->csr6 = new_csr6; outl(tp->csr6 | 0x0002, ioaddr + CSR6); /* Restart Tx */ outl(tp->csr6 | 0x2002, ioaddr + CSR6); dev->trans_start = jiffies; if (tulip_debug > 0) /* Gurppp, should be >1 */ printk(KERN_INFO "%s: Changing PNIC configuration to %s-duplex, " "CSR6 %8.8x.\n", dev->name, tp->full_duplex ? "full" : "half", new_csr6); } tp->timer.expires = RUN_AT(next_tick); add_timer(&tp->timer);}static void tulip_tx_timeout(struct dev
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -