📄 tlan.c
字号:
TLan_SetBit(TLAN_NET_SIO_MCLK, sio); if (minten) TLan_SetBit(TLAN_NET_SIO_MINTEN, sio);} /* TLan_MiiWriteReg */ /*************************************************************** * TLan_SetMac * * Returns: * Nothing * Parms: * dev Pointer to device structure of adapter * on which to change the AREG. * areg The AREG to set the address in (0 - 3). * mac A pointer to an array of chars. Each * element stores one byte of the address. * IE, it isn't in ascii. * * This function transfers a MAC address to one of the * TLAN AREGs (address registers). The TLAN chip locks * the register on writing to offset 0 and unlocks the * register after writing to offset 5. If NULL is passed * in mac, then the AREG is filled with 0's. * **************************************************************/void TLan_SetMac(struct nic *nic __unused, int areg, char *mac){ int i; areg *= 6; if (mac != NULL) { for (i = 0; i < 6; i++) TLan_DioWrite8(BASE, TLAN_AREG_0 + areg + i, mac[i]); } else { for (i = 0; i < 6; i++) TLan_DioWrite8(BASE, TLAN_AREG_0 + areg + i, 0); }} /* TLan_SetMac */ /********************************************************************* * TLan_PhyDetect * * Returns: * Nothing * Parms: * dev A pointer to the device structure of the adapter * for which the PHY needs determined. * * So far I've found that adapters which have external PHYs * may also use the internal PHY for part of the functionality. * (eg, AUI/Thinnet). This function finds out if this TLAN * chip has an internal PHY, and then finds the first external * PHY (starting from address 0) if it exists). * ********************************************************************/void TLan_PhyDetect(struct nic *nic){ u16 control; u16 hi; u16 lo; u32 phy; if (tlan_pci_tbl[chip_idx].flags & TLAN_ADAPTER_UNMANAGED_PHY) { priv->phyNum = 0xFFFF; return; } TLan_MiiReadReg(nic, TLAN_PHY_MAX_ADDR, MII_GEN_ID_HI, &hi); if (hi != 0xFFFF) { priv->phy[0] = TLAN_PHY_MAX_ADDR; } else { priv->phy[0] = TLAN_PHY_NONE; } priv->phy[1] = TLAN_PHY_NONE; for (phy = 0; phy <= TLAN_PHY_MAX_ADDR; phy++) { TLan_MiiReadReg(nic, phy, MII_GEN_CTL, &control); TLan_MiiReadReg(nic, phy, MII_GEN_ID_HI, &hi); TLan_MiiReadReg(nic, phy, MII_GEN_ID_LO, &lo); if ((control != 0xFFFF) || (hi != 0xFFFF) || (lo != 0xFFFF)) { printf("PHY found at %hX %hX %hX %hX\n", phy, control, hi, lo); if ((priv->phy[1] == TLAN_PHY_NONE) && (phy != TLAN_PHY_MAX_ADDR)) { priv->phy[1] = phy; } } } if (priv->phy[1] != TLAN_PHY_NONE) { priv->phyNum = 1; } else if (priv->phy[0] != TLAN_PHY_NONE) { priv->phyNum = 0; } else { printf ("TLAN: Cannot initialize device, no PHY was found!\n"); }} /* TLan_PhyDetect */void TLan_PhyPowerDown(struct nic *nic){ u16 value; printf("%s: Powering down PHY(s).\n", priv->nic_name); value = MII_GC_PDOWN | MII_GC_LOOPBK | MII_GC_ISOLATE; TLan_MiiSync(BASE); TLan_MiiWriteReg(nic, priv->phy[priv->phyNum], MII_GEN_CTL, value); if ((priv->phyNum == 0) && (priv->phy[1] != TLAN_PHY_NONE) && (!(tlan_pci_tbl[chip_idx]. flags & TLAN_ADAPTER_USE_INTERN_10))) { TLan_MiiSync(BASE); TLan_MiiWriteReg(nic, priv->phy[1], MII_GEN_CTL, value); } /* Wait for 50 ms and powerup * This is abitrary. It is intended to make sure the * tranceiver settles. */ /* TLan_SetTimer( dev, (HZ/20), TLAN_TIMER_PHY_PUP ); */ mdelay(50); TLan_PhyPowerUp(nic);} /* TLan_PhyPowerDown */void TLan_PhyPowerUp(struct nic *nic){ u16 value; printf("%s: Powering up PHY.\n", priv->nic_name); TLan_MiiSync(BASE); value = MII_GC_LOOPBK; TLan_MiiWriteReg(nic, priv->phy[priv->phyNum], MII_GEN_CTL, value); TLan_MiiSync(BASE); /* Wait for 500 ms and reset the * tranceiver. The TLAN docs say both 50 ms and * 500 ms, so do the longer, just in case. */ mdelay(500); TLan_PhyReset(nic); /* TLan_SetTimer( dev, (HZ/20), TLAN_TIMER_PHY_RESET ); */} /* TLan_PhyPowerUp */void TLan_PhyReset(struct nic *nic){ u16 phy; u16 value; phy = priv->phy[priv->phyNum]; printf("%s: Reseting PHY.\n", priv->nic_name); TLan_MiiSync(BASE); value = MII_GC_LOOPBK | MII_GC_RESET; TLan_MiiWriteReg(nic, phy, MII_GEN_CTL, value); TLan_MiiReadReg(nic, phy, MII_GEN_CTL, &value); while (value & MII_GC_RESET) { TLan_MiiReadReg(nic, phy, MII_GEN_CTL, &value); } /* Wait for 500 ms and initialize. * I don't remember why I wait this long. * I've changed this to 50ms, as it seems long enough. */ /* TLan_SetTimer( dev, (HZ/20), TLAN_TIMER_PHY_START_LINK ); */ mdelay(50); TLan_PhyStartLink(nic);} /* TLan_PhyReset */void TLan_PhyStartLink(struct nic *nic){ u16 ability; u16 control; u16 data; u16 phy; u16 status; u16 tctl; phy = priv->phy[priv->phyNum]; printf("%s: Trying to activate link.\n", priv->nic_name); TLan_MiiReadReg(nic, phy, MII_GEN_STS, &status); TLan_MiiReadReg(nic, phy, MII_GEN_STS, &ability); if ((status & MII_GS_AUTONEG) && (!priv->aui)) { ability = status >> 11; if (priv->speed == TLAN_SPEED_10 && priv->duplex == TLAN_DUPLEX_HALF) { TLan_MiiWriteReg(nic, phy, MII_GEN_CTL, 0x0000); } else if (priv->speed == TLAN_SPEED_10 && priv->duplex == TLAN_DUPLEX_FULL) { priv->tlanFullDuplex = TRUE; TLan_MiiWriteReg(nic, phy, MII_GEN_CTL, 0x0100); } else if (priv->speed == TLAN_SPEED_100 && priv->duplex == TLAN_DUPLEX_HALF) { TLan_MiiWriteReg(nic, phy, MII_GEN_CTL, 0x2000); } else if (priv->speed == TLAN_SPEED_100 && priv->duplex == TLAN_DUPLEX_FULL) { priv->tlanFullDuplex = TRUE; TLan_MiiWriteReg(nic, phy, MII_GEN_CTL, 0x2100); } else { /* Set Auto-Neg advertisement */ TLan_MiiWriteReg(nic, phy, MII_AN_ADV, (ability << 5) | 1); /* Enablee Auto-Neg */ TLan_MiiWriteReg(nic, phy, MII_GEN_CTL, 0x1000); /* Restart Auto-Neg */ TLan_MiiWriteReg(nic, phy, MII_GEN_CTL, 0x1200); /* Wait for 4 sec for autonegotiation * to complete. The max spec time is less than this * but the card need additional time to start AN. * .5 sec should be plenty extra. */ printf("TLAN: %s: Starting autonegotiation.\n", priv->nic_name); mdelay(4000); TLan_PhyFinishAutoNeg(nic); /* TLan_SetTimer( dev, (2*HZ), TLAN_TIMER_PHY_FINISH_AN ); */ return; } } if ((priv->aui) && (priv->phyNum != 0)) { priv->phyNum = 0; data = TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN | TLAN_NET_CFG_PHY_EN; TLan_DioWrite16(BASE, TLAN_NET_CONFIG, data); mdelay(50); /* TLan_SetTimer( dev, (40*HZ/1000), TLAN_TIMER_PHY_PDOWN ); */ TLan_PhyPowerDown(nic); return; } else if (priv->phyNum == 0) { control = 0; TLan_MiiReadReg(nic, phy, TLAN_TLPHY_CTL, &tctl); if (priv->aui) { tctl |= TLAN_TC_AUISEL; } else { tctl &= ~TLAN_TC_AUISEL; if (priv->duplex == TLAN_DUPLEX_FULL) { control |= MII_GC_DUPLEX; priv->tlanFullDuplex = TRUE; } if (priv->speed == TLAN_SPEED_100) { control |= MII_GC_SPEEDSEL; } } TLan_MiiWriteReg(nic, phy, MII_GEN_CTL, control); TLan_MiiWriteReg(nic, phy, TLAN_TLPHY_CTL, tctl); } /* Wait for 2 sec to give the tranceiver time * to establish link. */ /* TLan_SetTimer( dev, (4*HZ), TLAN_TIMER_FINISH_RESET ); */ mdelay(2000); TLan_FinishReset(nic);} /* TLan_PhyStartLink */void TLan_PhyFinishAutoNeg(struct nic *nic){ u16 an_adv; u16 an_lpa; u16 data; u16 mode; u16 phy; u16 status; phy = priv->phy[priv->phyNum]; TLan_MiiReadReg(nic, phy, MII_GEN_STS, &status); udelay(1000); TLan_MiiReadReg(nic, phy, MII_GEN_STS, &status); if (!(status & MII_GS_AUTOCMPLT)) { /* Wait for 8 sec to give the process * more time. Perhaps we should fail after a while. */ if (!priv->neg_be_verbose++) { printf ("TLAN: Giving autonegotiation more time.\n"); printf ("TLAN: Please check that your adapter has\n"); printf ("TLAN: been properly connected to a HUB or Switch.\n"); printf ("TLAN: Trying to establish link in the background...\n"); } mdelay(8000); TLan_PhyFinishAutoNeg(nic); /* TLan_SetTimer( dev, (8*HZ), TLAN_TIMER_PHY_FINISH_AN ); */ return; } printf("TLAN: %s: Autonegotiation complete.\n", priv->nic_name); TLan_MiiReadReg(nic, phy, MII_AN_ADV, &an_adv); TLan_MiiReadReg(nic, phy, MII_AN_LPA, &an_lpa); mode = an_adv & an_lpa & 0x03E0; if (mode & 0x0100) { printf("Full Duplex\n"); priv->tlanFullDuplex = TRUE; } else if (!(mode & 0x0080) && (mode & 0x0040)) { priv->tlanFullDuplex = TRUE; printf("Full Duplex\n"); } if ((!(mode & 0x0180)) && (tlan_pci_tbl[chip_idx].flags & TLAN_ADAPTER_USE_INTERN_10) && (priv->phyNum != 0)) { priv->phyNum = 0; data = TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN | TLAN_NET_CFG_PHY_EN; TLan_DioWrite16(BASE, TLAN_NET_CONFIG, data); /* TLan_SetTimer( nic, (400*HZ/1000), TLAN_TIMER_PHY_PDOWN ); */ mdelay(400); TLan_PhyPowerDown(nic); return; } if (priv->phyNum == 0) { if ((priv->duplex == TLAN_DUPLEX_FULL) || (an_adv & an_lpa & 0x0040)) { TLan_MiiWriteReg(nic, phy, MII_GEN_CTL, MII_GC_AUTOENB | MII_GC_DUPLEX); printf ("TLAN: Starting internal PHY with FULL-DUPLEX\n"); } else { TLan_MiiWriteReg(nic, phy, MII_GEN_CTL, MII_GC_AUTOENB); printf ("TLAN: Starting internal PHY with HALF-DUPLEX\n"); } } /* Wait for 100 ms. No reason in partiticular. */ /* TLan_SetTimer( dev, (HZ/10), TLAN_TIMER_FINISH_RESET ); */ mdelay(100); TLan_FinishReset(nic);} /* TLan_PhyFinishAutoNeg */#ifdef MONITOR /********************************************************************* * * TLan_phyMonitor * * Returns: * None * * Params: * dev The device structure of this device. * * * This function monitors PHY condition by reading the status * register via the MII bus. This can be used to give info * about link changes (up/down), and possible switch to alternate * media. * * ******************************************************************/void TLan_PhyMonitor(struct net_device *dev){ TLanPrivateInfo *priv = dev->priv; u16 phy; u16 phy_status; phy = priv->phy[priv->phyNum]; /* Get PHY status register */ TLan_MiiReadReg(nic, phy, MII_GEN_STS, &phy_status); /* Check if link has been lost */ if (!(phy_status & MII_GS_LINK)) { if (priv->link) { priv->link = 0; printf("TLAN: %s has lost link\n", priv->nic_name); priv->flags &= ~IFF_RUNNING; mdelay(2000); TLan_PhyMonitor(nic); /* TLan_SetTimer( dev, (2*HZ), TLAN_TIMER_LINK_BEAT ); */ return; } } /* Link restablished? */ if ((phy_status & MII_GS_LINK) && !priv->link) { priv->link = 1; printf("TLAN: %s has reestablished link\n", priv->nic_name); priv->flags |= IFF_RUNNING; } /* Setup a new monitor */ /* TLan_SetTimer( dev, (2*HZ), TLAN_TIMER_LINK_BEAT ); */ mdelay(2000); TLan_PhyMonitor(nic);}#endif /* MONITOR */#ifdef EB51static struct pci_id tlan_nics[] = { PCI_ROM(0x0e11, 0xae34, "netel10", "Compaq Netelligent 10 T PCI UTP"), PCI_ROM(0x0e11, 0xae32, "netel100","Compaq Netelligent 10/100 TX PCI UTP"), PCI_ROM(0x0e11, 0xae35, "netflex3i", "Compaq Integrated NetFlex-3/P"), PCI_ROM(0x0e11, 0xf130, "thunder", "Compaq NetFlex-3/P"), PCI_ROM(0x0e11, 0xf150, "netflex3b", "Compaq NetFlex-3/P"), PCI_ROM(0x0e11, 0xae43, "netel100pi", "Compaq Netelligent Integrated 10/100 TX UTP"), PCI_ROM(0x0e11, 0xae40, "netel100d", "Compaq Netelligent Dual 10/100 TX PCI UTP"), PCI_ROM(0x0e11, 0xb011, "netel100i", "Compaq Netelligent 10/100 TX Embedded UTP"), PCI_ROM(0x108d, 0x0013, "oc2183", "Olicom OC-2183/2185"), PCI_ROM(0x108d, 0x0012, "oc2325", "Olicom OC-2325"), PCI_ROM(0x108d, 0x0014, "oc2326", "Olicom OC-2326"), PCI_ROM(0x0e11, 0xb030, "netelligent_10_100_ws_5100", "Compaq Netelligent 10/100 TX UTP"), PCI_ROM(0x0e11, 0xb012, "netelligent_10_t2", "Compaq Netelligent 10 T/2 PCI UTP/Coax"),};static struct pci_driver tlan_driver __pci_driver = { .type = NIC_DRIVER, .name = "TLAN/PCI", .probe = tlan_probe, .ids = tlan_nics, .id_count = sizeof(tlan_nics) / sizeof(tlan_nics[0]), .class = 0,};#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -