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 + -
显示快捷键?