tehuti.c
来自「linux 内核源代码」· C语言 代码 · 共 2,340 行 · 第 1/5 页
C
2,340 行
WRITE_REG(priv, regCLKPLL, val & ~CLKPLL_SFTRST); } /* check that the PLLs are locked and reset ended */ for (i = 0; i < 70; i++, mdelay(10)) if ((READ_REG(priv, regCLKPLL) & CLKPLL_LKD) == CLKPLL_LKD) { /* do any PCI-E read transaction */ READ_REG(priv, regRXD_CFG0_0); return 0; } ERR("tehuti: HW reset failed\n"); return 1; /* failure */}static int bdx_sw_reset(struct bdx_priv *priv){ int i; ENTER; /* 1. load MAC (obsolete) */ /* 2. disable Rx (and Tx) */ WRITE_REG(priv, regGMAC_RXF_A, 0); mdelay(100); /* 3. disable port */ WRITE_REG(priv, regDIS_PORT, 1); /* 4. disable queue */ WRITE_REG(priv, regDIS_QU, 1); /* 5. wait until hw is disabled */ for (i = 0; i < 50; i++) { if (READ_REG(priv, regRST_PORT) & 1) break; mdelay(10); } if (i == 50) ERR("%s: SW reset timeout. continuing anyway\n", priv->ndev->name); /* 6. disable intrs */ WRITE_REG(priv, regRDINTCM0, 0); WRITE_REG(priv, regTDINTCM0, 0); WRITE_REG(priv, regIMR, 0); READ_REG(priv, regISR); /* 7. reset queue */ WRITE_REG(priv, regRST_QU, 1); /* 8. reset port */ WRITE_REG(priv, regRST_PORT, 1); /* 9. zero all read and write pointers */ for (i = regTXD_WPTR_0; i <= regTXF_RPTR_3; i += 0x10) DBG("%x = %x\n", i, READ_REG(priv, i) & TXF_WPTR_WR_PTR); for (i = regTXD_WPTR_0; i <= regTXF_RPTR_3; i += 0x10) WRITE_REG(priv, i, 0); /* 10. unseet port disable */ WRITE_REG(priv, regDIS_PORT, 0); /* 11. unset queue disable */ WRITE_REG(priv, regDIS_QU, 0); /* 12. unset queue reset */ WRITE_REG(priv, regRST_QU, 0); /* 13. unset port reset */ WRITE_REG(priv, regRST_PORT, 0); /* 14. enable Rx */ /* skiped. will be done later */ /* 15. save MAC (obsolete) */ for (i = regTXD_WPTR_0; i <= regTXF_RPTR_3; i += 0x10) DBG("%x = %x\n", i, READ_REG(priv, i) & TXF_WPTR_WR_PTR); RET(0);}/* bdx_reset - performs right type of reset depending on hw type */static int bdx_reset(struct bdx_priv *priv){ ENTER; RET((priv->pdev->device == 0x3009) ? bdx_hw_reset(priv) : bdx_sw_reset(priv));}/** * bdx_close - Disables a network interface * @netdev: network interface device structure * * Returns 0, this is not allowed to fail * * The close entry point is called when an interface is de-activated * by the OS. The hardware is still under the drivers control, but * needs to be disabled. A global MAC reset is issued to stop the * hardware, and all transmit and receive resources are freed. **/static int bdx_close(struct net_device *ndev){ struct bdx_priv *priv = NULL; ENTER; priv = ndev->priv; napi_disable(&priv->napi); bdx_reset(priv); bdx_hw_stop(priv); bdx_rx_free(priv); bdx_tx_free(priv); RET(0);}/** * bdx_open - Called when a network interface is made active * @netdev: network interface device structure * * Returns 0 on success, negative value on failure * * The open entry point is called when a network interface is made * active by the system (IFF_UP). At this point all resources needed * for transmit and receive operations are allocated, the interrupt * handler is registered with the OS, the watchdog timer is started, * and the stack is notified that the interface is ready. **/static int bdx_open(struct net_device *ndev){ struct bdx_priv *priv; int rc; ENTER; priv = ndev->priv; bdx_reset(priv); if (netif_running(ndev)) netif_stop_queue(priv->ndev); if ((rc = bdx_tx_init(priv))) goto err; if ((rc = bdx_rx_init(priv))) goto err; if ((rc = bdx_fw_load(priv))) goto err; bdx_rx_alloc_skbs(priv, &priv->rxf_fifo0); if ((rc = bdx_hw_start(priv))) goto err; napi_enable(&priv->napi); print_fw_id(priv->nic); RET(0);err: bdx_close(ndev); RET(rc);}static void __init bdx_firmware_endianess(void){ int i; for (i = 0; i < sizeof(s_firmLoad) / sizeof(u32); i++) s_firmLoad[i] = CPU_CHIP_SWAP32(s_firmLoad[i]);}static int bdx_ioctl_priv(struct net_device *ndev, struct ifreq *ifr, int cmd){ struct bdx_priv *priv = ndev->priv; u32 data[3]; int error; ENTER; DBG("jiffies=%ld cmd=%d\n", jiffies, cmd); if (cmd != SIOCDEVPRIVATE) { error = copy_from_user(data, ifr->ifr_data, sizeof(data)); if (error) { ERR("cant copy from user\n"); RET(error); } DBG("%d 0x%x 0x%x\n", data[0], data[1], data[2]); } switch (data[0]) { case BDX_OP_READ: data[2] = READ_REG(priv, data[1]); DBG("read_reg(0x%x)=0x%x (dec %d)\n", data[1], data[2], data[2]); error = copy_to_user(ifr->ifr_data, data, sizeof(data)); if (error) RET(error); break; case BDX_OP_WRITE: WRITE_REG(priv, data[1], data[2]); DBG("write_reg(0x%x, 0x%x)\n", data[1], data[2]); break; default: RET(-EOPNOTSUPP); } return 0;}static int bdx_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd){ ENTER; if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) RET(bdx_ioctl_priv(ndev, ifr, cmd)); else RET(-EOPNOTSUPP);}/* * __bdx_vlan_rx_vid - private helper for adding/killing VLAN vid * by passing VLAN filter table to hardware * @ndev network device * @vid VLAN vid * @op add or kill operation */static void __bdx_vlan_rx_vid(struct net_device *ndev, uint16_t vid, int enable){ struct bdx_priv *priv = ndev->priv; u32 reg, bit, val; ENTER; DBG2("vid=%d value=%d\n", (int)vid, enable); if (unlikely(vid >= 4096)) { ERR("tehuti: invalid VID: %u (> 4096)\n", vid); RET(); } reg = regVLAN_0 + (vid / 32) * 4; bit = 1 << vid % 32; val = READ_REG(priv, reg); DBG2("reg=%x, val=%x, bit=%d\n", reg, val, bit); if (enable) val |= bit; else val &= ~bit; DBG2("new val %x\n", val); WRITE_REG(priv, reg, val); RET();}/* * bdx_vlan_rx_add_vid - kernel hook for adding VLAN vid to hw filtering table * @ndev network device * @vid VLAN vid to add */static void bdx_vlan_rx_add_vid(struct net_device *ndev, uint16_t vid){ __bdx_vlan_rx_vid(ndev, vid, 1);}/* * bdx_vlan_rx_kill_vid - kernel hook for killing VLAN vid in hw filtering table * @ndev network device * @vid VLAN vid to kill */static void bdx_vlan_rx_kill_vid(struct net_device *ndev, unsigned short vid){ __bdx_vlan_rx_vid(ndev, vid, 0);}/* * bdx_vlan_rx_register - kernel hook for adding VLAN group * @ndev network device * @grp VLAN group */static voidbdx_vlan_rx_register(struct net_device *ndev, struct vlan_group *grp){ struct bdx_priv *priv = ndev->priv; ENTER; DBG("device='%s', group='%p'\n", ndev->name, grp); priv->vlgrp = grp; RET();}/** * bdx_change_mtu - Change the Maximum Transfer Unit * @netdev: network interface device structure * @new_mtu: new value for maximum frame size * * Returns 0 on success, negative on failure */static int bdx_change_mtu(struct net_device *ndev, int new_mtu){ ENTER; if (new_mtu == ndev->mtu) RET(0); /* enforce minimum frame size */ if (new_mtu < ETH_ZLEN) { ERR("%s: %s mtu %d is less then minimal %d\n", BDX_DRV_NAME, ndev->name, new_mtu, ETH_ZLEN); RET(-EINVAL); } ndev->mtu = new_mtu; if (netif_running(ndev)) { bdx_close(ndev); bdx_open(ndev); } RET(0);}static void bdx_setmulti(struct net_device *ndev){ struct bdx_priv *priv = ndev->priv; u32 rxf_val = GMAC_RX_FILTER_AM | GMAC_RX_FILTER_AB | GMAC_RX_FILTER_OSEN; int i; ENTER; /* IMF - imperfect (hash) rx multicat filter */ /* PMF - perfect rx multicat filter */ /* FIXME: RXE(OFF) */ if (ndev->flags & IFF_PROMISC) { rxf_val |= GMAC_RX_FILTER_PRM; } else if (ndev->flags & IFF_ALLMULTI) { /* set IMF to accept all multicast frmaes */ for (i = 0; i < MAC_MCST_HASH_NUM; i++) WRITE_REG(priv, regRX_MCST_HASH0 + i * 4, ~0); } else if (ndev->mc_count) { u8 hash; struct dev_mc_list *mclist; u32 reg, val; /* set IMF to deny all multicast frames */ for (i = 0; i < MAC_MCST_HASH_NUM; i++) WRITE_REG(priv, regRX_MCST_HASH0 + i * 4, 0); /* set PMF to deny all multicast frames */ for (i = 0; i < MAC_MCST_NUM; i++) { WRITE_REG(priv, regRX_MAC_MCST0 + i * 8, 0); WRITE_REG(priv, regRX_MAC_MCST1 + i * 8, 0); } /* use PMF to accept first MAC_MCST_NUM (15) addresses */ /* TBD: sort addreses and write them in ascending order * into RX_MAC_MCST regs. we skip this phase now and accept ALL * multicast frames throu IMF */ mclist = ndev->mc_list; /* accept the rest of addresses throu IMF */ for (; mclist; mclist = mclist->next) { hash = 0; for (i = 0; i < ETH_ALEN; i++) hash ^= mclist->dmi_addr[i]; reg = regRX_MCST_HASH0 + ((hash >> 5) << 2); val = READ_REG(priv, reg); val |= (1 << (hash % 32)); WRITE_REG(priv, reg, val); } } else { DBG("only own mac %d\n", ndev->mc_count); rxf_val |= GMAC_RX_FILTER_AB; } WRITE_REG(priv, regGMAC_RXF_A, rxf_val); /* enable RX */ /* FIXME: RXE(ON) */ RET();}static int bdx_set_mac(struct net_device *ndev, void *p){ struct bdx_priv *priv = ndev->priv; struct sockaddr *addr = p; ENTER; /* if (netif_running(dev)) return -EBUSY */ memcpy(ndev->dev_addr, addr->sa_data, ndev->addr_len); bdx_restore_mac(ndev, priv); RET(0);}static int bdx_read_mac(struct bdx_priv *priv){ u16 macAddress[3], i; ENTER; macAddress[2] = READ_REG(priv, regUNC_MAC0_A); macAddress[2] = READ_REG(priv, regUNC_MAC0_A); macAddress[1] = READ_REG(priv, regUNC_MAC1_A); macAddress[1] = READ_REG(priv, regUNC_MAC1_A); macAddress[0] = READ_REG(priv, regUNC_MAC2_A); macAddress[0] = READ_REG(priv, regUNC_MAC2_A); for (i = 0; i < 3; i++) { priv->ndev->dev_addr[i * 2 + 1] = macAddress[i]; priv->ndev->dev_addr[i * 2] = macAddress[i] >> 8; } RET(0);}static u64 bdx_read_l2stat(struct bdx_priv *priv, int reg){ u64 val; val = READ_REG(priv, reg); val |= ((u64) READ_REG(priv, reg + 8)) << 32; return val;}/*Do the statistics-update work*/static void bdx_update_stats(struct bdx_priv *priv){ struct bdx_stats *stats = &priv->hw_stats; u64 *stats_vector = (u64 *) stats; int i; int addr; /*Fill HW structure */ addr = 0x7200; /*First 12 statistics - 0x7200 - 0x72B0 */ for (i = 0; i < 12; i++) { stats_vector[i] = bdx_read_l2stat(priv, addr); addr += 0x10; } BDX_ASSERT(addr != 0x72C0); /* 0x72C0-0x72E0 RSRV */ addr = 0x72F0; for (; i < 16; i++) { stats_vector[i] = bdx_read_l2stat(priv, addr); addr += 0x10; } BDX_ASSERT(addr != 0x7330); /* 0x7330-0x7360 RSRV */ addr = 0x7370; for (; i < 19; i++) { stats_vector[i] = bdx_read_l2stat(priv, addr); addr += 0x10; } BDX_ASSERT(addr != 0x73A0); /* 0x73A0-0x73B0 RSRV */ addr = 0x73C0; for (; i < 23; i++) { stats_vector[i] = bdx_read_l2stat(priv, addr); addr += 0x10; } BDX_ASSERT(addr != 0x7400); BDX_ASSERT((sizeof(struct bdx_stats) / sizeof(u64)) != i);}static struct net_device_stats *bdx_get_stats(struct net_device *ndev){ struct bdx_priv *priv = ndev->priv; struct net_device_stats *net_stat = &priv->net_stats; return net_stat;}static void print_rxdd(struct rxd_desc *rxdd, u32 rxd_val1, u16 len, u16 rxd_vlan);static void print_rxfd(struct rxf_desc *rxfd);/************************************************************************* * Rx DB * *************************************************************************/static void bdx_rxdb_destroy(struct rxdb *db){ if (db) vfree(db);}static struct rxdb *bdx_rxdb_create(int nelem)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?