⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tg3.c

📁 linux下从网卡远程启动
💻 C
📖 第 1 页 / 共 5 页
字号:
		ap->ack_match = 0;	}	ap->cur_time++;	if (tr32(MAC_STATUS) & MAC_STATUS_RCVD_CFG) {		rx_cfg_reg = tr32(MAC_RX_AUTO_NEG);		if (rx_cfg_reg != ap->ability_match_cfg) {			ap->ability_match_cfg = rx_cfg_reg;			ap->ability_match = 0;			ap->ability_match_count = 0;		} else {			if (++ap->ability_match_count > 1) {				ap->ability_match = 1;				ap->ability_match_cfg = rx_cfg_reg;			}		}		if (rx_cfg_reg & ANEG_CFG_ACK)			ap->ack_match = 1;		else			ap->ack_match = 0;		ap->idle_match = 0;	} else {		ap->idle_match = 1;		ap->ability_match_cfg = 0;		ap->ability_match_count = 0;		ap->ability_match = 0;		ap->ack_match = 0;		rx_cfg_reg = 0;	}	ap->rxconfig = rx_cfg_reg;	ret = ANEG_OK;	switch(ap->state) {	case ANEG_STATE_UNKNOWN:		if (ap->flags & (MR_AN_ENABLE | MR_RESTART_AN))			ap->state = ANEG_STATE_AN_ENABLE;		/* fallthru */	case ANEG_STATE_AN_ENABLE:		ap->flags &= ~(MR_AN_COMPLETE | MR_PAGE_RX);		if (ap->flags & MR_AN_ENABLE) {			ap->link_time = 0;			ap->cur_time = 0;			ap->ability_match_cfg = 0;			ap->ability_match_count = 0;			ap->ability_match = 0;			ap->idle_match = 0;			ap->ack_match = 0;			ap->state = ANEG_STATE_RESTART_INIT;		} else {			ap->state = ANEG_STATE_DISABLE_LINK_OK;		}		break;	case ANEG_STATE_RESTART_INIT:		ap->link_time = ap->cur_time;		ap->flags &= ~(MR_NP_LOADED);		ap->txconfig = 0;		tw32(MAC_TX_AUTO_NEG, 0);		tp->mac_mode |= MAC_MODE_SEND_CONFIGS;		tw32_carefully(MAC_MODE, tp->mac_mode);		ret = ANEG_TIMER_ENAB;		ap->state = ANEG_STATE_RESTART;		/* fallthru */	case ANEG_STATE_RESTART:		delta = ap->cur_time - ap->link_time;		if (delta > ANEG_STATE_SETTLE_TIME) {			ap->state = ANEG_STATE_ABILITY_DETECT_INIT;		} else {			ret = ANEG_TIMER_ENAB;		}		break;	case ANEG_STATE_DISABLE_LINK_OK:		ret = ANEG_DONE;		break;	case ANEG_STATE_ABILITY_DETECT_INIT:		ap->flags &= ~(MR_TOGGLE_TX);		ap->txconfig = (ANEG_CFG_FD | ANEG_CFG_PS1);		tw32(MAC_TX_AUTO_NEG, ap->txconfig);		tp->mac_mode |= MAC_MODE_SEND_CONFIGS;		tw32_carefully(MAC_MODE, tp->mac_mode);		ap->state = ANEG_STATE_ABILITY_DETECT;		break;	case ANEG_STATE_ABILITY_DETECT:		if (ap->ability_match != 0 && ap->rxconfig != 0) {			ap->state = ANEG_STATE_ACK_DETECT_INIT;		}		break;	case ANEG_STATE_ACK_DETECT_INIT:		ap->txconfig |= ANEG_CFG_ACK;		tw32(MAC_TX_AUTO_NEG, ap->txconfig);		tp->mac_mode |= MAC_MODE_SEND_CONFIGS;		tw32_carefully(MAC_MODE, tp->mac_mode);		ap->state = ANEG_STATE_ACK_DETECT;		/* fallthru */	case ANEG_STATE_ACK_DETECT:		if (ap->ack_match != 0) {			if ((ap->rxconfig & ~ANEG_CFG_ACK) ==			    (ap->ability_match_cfg & ~ANEG_CFG_ACK)) {				ap->state = ANEG_STATE_COMPLETE_ACK_INIT;			} else {				ap->state = ANEG_STATE_AN_ENABLE;			}		} else if (ap->ability_match != 0 &&			   ap->rxconfig == 0) {			ap->state = ANEG_STATE_AN_ENABLE;		}		break;	case ANEG_STATE_COMPLETE_ACK_INIT:		if (ap->rxconfig & ANEG_CFG_INVAL) {			ret = ANEG_FAILED;			break;		}		ap->flags &= ~(MR_LP_ADV_FULL_DUPLEX |			       MR_LP_ADV_HALF_DUPLEX |			       MR_LP_ADV_SYM_PAUSE |			       MR_LP_ADV_ASYM_PAUSE |			       MR_LP_ADV_REMOTE_FAULT1 |			       MR_LP_ADV_REMOTE_FAULT2 |			       MR_LP_ADV_NEXT_PAGE |			       MR_TOGGLE_RX |			       MR_NP_RX);		if (ap->rxconfig & ANEG_CFG_FD)			ap->flags |= MR_LP_ADV_FULL_DUPLEX;		if (ap->rxconfig & ANEG_CFG_HD)			ap->flags |= MR_LP_ADV_HALF_DUPLEX;		if (ap->rxconfig & ANEG_CFG_PS1)			ap->flags |= MR_LP_ADV_SYM_PAUSE;		if (ap->rxconfig & ANEG_CFG_PS2)			ap->flags |= MR_LP_ADV_ASYM_PAUSE;		if (ap->rxconfig & ANEG_CFG_RF1)			ap->flags |= MR_LP_ADV_REMOTE_FAULT1;		if (ap->rxconfig & ANEG_CFG_RF2)			ap->flags |= MR_LP_ADV_REMOTE_FAULT2;		if (ap->rxconfig & ANEG_CFG_NP)			ap->flags |= MR_LP_ADV_NEXT_PAGE;		ap->link_time = ap->cur_time;		ap->flags ^= (MR_TOGGLE_TX);		if (ap->rxconfig & 0x0008)			ap->flags |= MR_TOGGLE_RX;		if (ap->rxconfig & ANEG_CFG_NP)			ap->flags |= MR_NP_RX;		ap->flags |= MR_PAGE_RX;		ap->state = ANEG_STATE_COMPLETE_ACK;		ret = ANEG_TIMER_ENAB;		break;	case ANEG_STATE_COMPLETE_ACK:		if (ap->ability_match != 0 &&		    ap->rxconfig == 0) {			ap->state = ANEG_STATE_AN_ENABLE;			break;		}		delta = ap->cur_time - ap->link_time;		if (delta > ANEG_STATE_SETTLE_TIME) {			if (!(ap->flags & (MR_LP_ADV_NEXT_PAGE))) {				ap->state = ANEG_STATE_IDLE_DETECT_INIT;			} else {				if ((ap->txconfig & ANEG_CFG_NP) == 0 &&				    !(ap->flags & MR_NP_RX)) {					ap->state = ANEG_STATE_IDLE_DETECT_INIT;				} else {					ret = ANEG_FAILED;				}			}		}		break;	case ANEG_STATE_IDLE_DETECT_INIT:		ap->link_time = ap->cur_time;		tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS;		tw32_carefully(MAC_MODE, tp->mac_mode);		ap->state = ANEG_STATE_IDLE_DETECT;		ret = ANEG_TIMER_ENAB;		break;	case ANEG_STATE_IDLE_DETECT:		if (ap->ability_match != 0 &&		    ap->rxconfig == 0) {			ap->state = ANEG_STATE_AN_ENABLE;			break;		}		delta = ap->cur_time - ap->link_time;		if (delta > ANEG_STATE_SETTLE_TIME) {			/* XXX another gem from the Broadcom driver :( */			ap->state = ANEG_STATE_LINK_OK;		}		break;	case ANEG_STATE_LINK_OK:		ap->flags |= (MR_AN_COMPLETE | MR_LINK_OK);		ret = ANEG_DONE;		break;	case ANEG_STATE_NEXT_PAGE_WAIT_INIT:		/* ??? unimplemented */		break;	case ANEG_STATE_NEXT_PAGE_WAIT:		/* ??? unimplemented */		break;	default:		ret = ANEG_FAILED;		break;	};	return ret;}static int tg3_setup_fiber_phy(struct tg3 *tp){	uint32_t orig_pause_cfg;	uint16_t orig_active_speed;	uint8_t orig_active_duplex;	int current_link_up;	int i;	orig_pause_cfg =		(tp->tg3_flags & (TG3_FLAG_RX_PAUSE |				  TG3_FLAG_TX_PAUSE));	orig_active_speed = tp->link_config.active_speed;	orig_active_duplex = tp->link_config.active_duplex;	tp->mac_mode &= ~(MAC_MODE_PORT_MODE_MASK | MAC_MODE_HALF_DUPLEX);	tp->mac_mode |= MAC_MODE_PORT_MODE_TBI;	tw32_carefully(MAC_MODE, tp->mac_mode);	/* Reset when initting first time or we have a link. */	if (!(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) ||	    (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED)) {		/* Set PLL lock range. */		tg3_writephy(tp, 0x16, 0x8007);		/* SW reset */		tg3_writephy(tp, MII_BMCR, BMCR_RESET);		/* Wait for reset to complete. */		mdelay(5);		/* Config mode; select PMA/Ch 1 regs. */		tg3_writephy(tp, 0x10, 0x8411);		/* Enable auto-lock and comdet, select txclk for tx. */		tg3_writephy(tp, 0x11, 0x0a10);		tg3_writephy(tp, 0x18, 0x00a0);		tg3_writephy(tp, 0x16, 0x41ff);		/* Assert and deassert POR. */		tg3_writephy(tp, 0x13, 0x0400);		udelay(40);		tg3_writephy(tp, 0x13, 0x0000);		tg3_writephy(tp, 0x11, 0x0a50);		udelay(40);		tg3_writephy(tp, 0x11, 0x0a10);		/* Wait for signal to stabilize */		mdelay(150);		/* Deselect the channel register so we can read the PHYID		 * later.		 */		tg3_writephy(tp, 0x10, 0x8011);	}	/* Disable link change interrupt.  */	tw32_carefully(MAC_EVENT, 0);	current_link_up = 0;	if (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) {		if (!(tp->tg3_flags & TG3_FLAG_GOT_SERDES_FLOWCTL)) {			struct tg3_fiber_aneginfo aninfo;			int status = ANEG_FAILED;			unsigned int tick;			uint32_t tmp;			memset(&aninfo, 0, sizeof(aninfo));			aninfo.flags |= (MR_AN_ENABLE);			tw32(MAC_TX_AUTO_NEG, 0);			tmp = tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK;			tw32_carefully(MAC_MODE, tmp | MAC_MODE_PORT_MODE_GMII);			tw32_carefully(MAC_MODE, tp->mac_mode | MAC_MODE_SEND_CONFIGS);			aninfo.state = ANEG_STATE_UNKNOWN;			aninfo.cur_time = 0;			tick = 0;			while (++tick < 195000) {				status = tg3_fiber_aneg_smachine(tp, &aninfo);				if (status == ANEG_DONE ||				    status == ANEG_FAILED)					break;				udelay(1);			}			tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS;			tw32_carefully(MAC_MODE, tp->mac_mode);			if (status == ANEG_DONE &&			    (aninfo.flags &			     (MR_AN_COMPLETE | MR_LINK_OK |			      MR_LP_ADV_FULL_DUPLEX))) {				uint32_t local_adv, remote_adv;				local_adv = ADVERTISE_PAUSE_CAP;				remote_adv = 0;				if (aninfo.flags & MR_LP_ADV_SYM_PAUSE)					remote_adv |= LPA_PAUSE_CAP;				if (aninfo.flags & MR_LP_ADV_ASYM_PAUSE)					remote_adv |= LPA_PAUSE_ASYM;				tg3_setup_flow_control(tp, local_adv, remote_adv);				tp->tg3_flags |=					TG3_FLAG_GOT_SERDES_FLOWCTL;				current_link_up = 1;			}			for (i = 0; i < 60; i++) {				udelay(20);				tw32_carefully(MAC_STATUS,					(MAC_STATUS_SYNC_CHANGED | MAC_STATUS_CFG_CHANGED));				if ((tr32(MAC_STATUS) &				     (MAC_STATUS_SYNC_CHANGED |				      MAC_STATUS_CFG_CHANGED)) == 0)					break;			}			if (current_link_up == 0 &&			    (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED)) {				current_link_up = 1;			}		} else {			/* Forcing 1000FD link up. */			current_link_up = 1;		}	}	tp->mac_mode &= ~MAC_MODE_LINK_POLARITY;	tw32_carefully(MAC_MODE, tp->mac_mode);	tp->hw_status->status =		(SD_STATUS_UPDATED |		 (tp->hw_status->status & ~SD_STATUS_LINK_CHG));	for (i = 0; i < 100; i++) {		udelay(20);		tw32_carefully(MAC_STATUS,			(MAC_STATUS_SYNC_CHANGED | MAC_STATUS_CFG_CHANGED));		if ((tr32(MAC_STATUS) &		     (MAC_STATUS_SYNC_CHANGED |		      MAC_STATUS_CFG_CHANGED)) == 0)			break;	}	if ((tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) == 0)		current_link_up = 0;	if (current_link_up == 1) {		tp->link_config.active_speed = SPEED_1000;		tp->link_config.active_duplex = DUPLEX_FULL;	} else {		tp->link_config.active_speed = SPEED_INVALID;		tp->link_config.active_duplex = DUPLEX_INVALID;	}	if (current_link_up != tp->carrier_ok) {		tp->carrier_ok = current_link_up;		tg3_link_report(tp);	} else {		uint32_t now_pause_cfg =			tp->tg3_flags & (TG3_FLAG_RX_PAUSE |					 TG3_FLAG_TX_PAUSE);		if (orig_pause_cfg != now_pause_cfg ||		    orig_active_speed != tp->link_config.active_speed ||		    orig_active_duplex != tp->link_config.active_duplex)			tg3_link_report(tp);	}	if ((tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) == 0) {		tw32_carefully(MAC_MODE, tp->mac_mode | MAC_MODE_LINK_POLARITY);		if (tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) {			tw32_carefully(MAC_MODE, tp->mac_mode);		}	}	return 0;}#else#define tg3_setup_fiber_phy(TP) (-EINVAL)#endif /* SUPPORT_FIBER_PHY */static int tg3_setup_phy(struct tg3 *tp){	int err;	if (tp->phy_id == PHY_ID_SERDES) {		err = tg3_setup_fiber_phy(tp);	} else {		err = tg3_setup_copper_phy(tp);	}	if (tp->link_config.active_speed == SPEED_1000 &&	    tp->link_config.active_duplex == DUPLEX_HALF)		tw32(MAC_TX_LENGTHS,		     ((2 << TX_LENGTHS_IPG_CRS_SHIFT) |		      (6 << TX_LENGTHS_IPG_SHIFT) |		      (0xff << TX_LENGTHS_SLOT_TIME_SHIFT)));	else		tw32(MAC_TX_LENGTHS,		     ((2 << TX_LENGTHS_IPG_CRS_SHIFT) |		      (6 << TX_LENGTHS_IPG_SHIFT) |		      (32 << TX_LENGTHS_SLOT_TIME_SHIFT)));	return err;}#define MAX_WAIT_CNT 1000/* To stop a block, clear the enable bit and poll till it * clears.   */static int tg3_stop_block(struct tg3 *tp, unsigned long ofs, uint32_t enable_bit){	unsigned int i;	uint32_t val;	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {		switch(ofs) {		case RCVLSC_MODE:		case DMAC_MODE:		case MBFREE_MODE:		case BUFMGR_MODE:		case MEMARB_MODE:			/* We can't enable/disable these bits of the			 * 5705, just say success.			 */			return 0;		default:			break;		}	}	val = tr32(ofs);	val &= ~enable_bit;	tw32(ofs, val);	tr32(ofs);	for (i = 0; i < MAX_WAIT_CNT; i++) {		udelay(100);		val = tr32(ofs);		if ((val & enable_bit) == 0)			break;	}	if (i == MAX_WAIT_CNT) {		printf("tg3_stop_block timed out, ofs=%lx enable_bit=%x\n",		       ofs, enable_bit);		return -ENODEV;	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -