17c478bdstevel@tonic-gate/* $Id: tg3.c,v 1.5 2003/03/19 21:26:20 gbaum Exp $
27c478bdstevel@tonic-gate * tg3.c: Broadcom Tigon3 ethernet driver.
37c478bdstevel@tonic-gate *
47c478bdstevel@tonic-gate * Copyright (C) 2001, 2002 David S. Miller (davem@redhat.com)
57c478bdstevel@tonic-gate * Copyright (C) 2001, 2002 Jeff Garzik (jgarzik@mandrakesoft.com)
67c478bdstevel@tonic-gate * Copyright (C) 2003 Eric Biederman (ebiederman@lnxi.com)  [etherboot port]
77c478bdstevel@tonic-gate */
87c478bdstevel@tonic-gate
97c478bdstevel@tonic-gate/* 11-13-2003	timlegge	Fix Issue with NetGear GA302T
107c478bdstevel@tonic-gate * 11-18-2003   ebiederm        Generalize NetGear Fix to what the code was supposed to be.
117c478bdstevel@tonic-gate */
127c478bdstevel@tonic-gate
137c478bdstevel@tonic-gate#include "etherboot.h"
147c478bdstevel@tonic-gate#include "nic.h"
157c478bdstevel@tonic-gate#include "pci.h"
167c478bdstevel@tonic-gate#include "timer.h"
177c478bdstevel@tonic-gate/*#include "string.h"*/
187c478bdstevel@tonic-gate#include "tg3.h"
197c478bdstevel@tonic-gate
207c478bdstevel@tonic-gate#define SUPPORT_COPPER_PHY  1
217c478bdstevel@tonic-gate#define SUPPORT_FIBER_PHY   1
227c478bdstevel@tonic-gate#define SUPPORT_LINK_REPORT 1
237c478bdstevel@tonic-gate#define SUPPORT_PARTNO_STR  1
247c478bdstevel@tonic-gate#define SUPPORT_PHY_STR     1
257c478bdstevel@tonic-gate
267c478bdstevel@tonic-gatestruct tg3 tg3;
277c478bdstevel@tonic-gate
287c478bdstevel@tonic-gate/* Dummy defines for error handling */
297c478bdstevel@tonic-gate#define EBUSY  1
307c478bdstevel@tonic-gate#define ENODEV 2
317c478bdstevel@tonic-gate#define EINVAL 3
327c478bdstevel@tonic-gate#define ENOMEM 4
337c478bdstevel@tonic-gate
347c478bdstevel@tonic-gate
357c478bdstevel@tonic-gate/* These numbers seem to be hard coded in the NIC firmware somehow.
367c478bdstevel@tonic-gate * You can't change the ring sizes, but you can change where you place
377c478bdstevel@tonic-gate * them in the NIC onboard memory.
387c478bdstevel@tonic-gate */
397c478bdstevel@tonic-gate#define TG3_RX_RING_SIZE		512
407c478bdstevel@tonic-gate#define TG3_DEF_RX_RING_PENDING		20	/* RX_RING_PENDING seems to be o.k. at 20 and 200 */
417c478bdstevel@tonic-gate#define TG3_RX_RCB_RING_SIZE	1024
427c478bdstevel@tonic-gate
437c478bdstevel@tonic-gate/*	(GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ? \
447c478bdstevel@tonic-gate	 512 : 1024) */
457c478bdstevel@tonic-gate #define TG3_TX_RING_SIZE		512
467c478bdstevel@tonic-gate#define TG3_DEF_TX_RING_PENDING		(TG3_TX_RING_SIZE - 1)
477c478bdstevel@tonic-gate
487c478bdstevel@tonic-gate#define TG3_RX_RING_BYTES	(sizeof(struct tg3_rx_buffer_desc) * TG3_RX_RING_SIZE)
497c478bdstevel@tonic-gate#define TG3_RX_RCB_RING_BYTES	(sizeof(struct tg3_rx_buffer_desc) * TG3_RX_RCB_RING_SIZE)
507c478bdstevel@tonic-gate
517c478bdstevel@tonic-gate#define TG3_TX_RING_BYTES	(sizeof(struct tg3_tx_buffer_desc) * TG3_TX_RING_SIZE)
527c478bdstevel@tonic-gate#define NEXT_TX(N)		(((N) + 1) & (TG3_TX_RING_SIZE - 1))
537c478bdstevel@tonic-gate#define PREV_TX(N)		(((N) - 1) & (TG3_TX_RING_SIZE - 1))
547c478bdstevel@tonic-gate
557c478bdstevel@tonic-gate#define RX_PKT_BUF_SZ		(1536 + 2 + 64)
567c478bdstevel@tonic-gate
577c478bdstevel@tonic-gate
587c478bdstevel@tonic-gatestatic struct bss {
597c478bdstevel@tonic-gate	struct tg3_rx_buffer_desc rx_std[TG3_RX_RING_SIZE];
607c478bdstevel@tonic-gate	struct tg3_rx_buffer_desc rx_rcb[TG3_RX_RCB_RING_SIZE];
617c478bdstevel@tonic-gate	struct tg3_tx_buffer_desc tx_ring[TG3_TX_RING_SIZE];
627c478bdstevel@tonic-gate	struct tg3_hw_status      hw_status;
637c478bdstevel@tonic-gate	struct tg3_hw_stats       hw_stats;
647c478bdstevel@tonic-gate	unsigned char             rx_bufs[TG3_DEF_RX_RING_PENDING][RX_PKT_BUF_SZ];
657c478bdstevel@tonic-gate} tg3_bss;
667c478bdstevel@tonic-gate
677c478bdstevel@tonic-gate/**
687c478bdstevel@tonic-gate * pci_save_state - save the PCI configuration space of a device before suspending
697c478bdstevel@tonic-gate * @dev: - PCI device that we're dealing with
707c478bdstevel@tonic-gate * @buffer: - buffer to hold config space context
717c478bdstevel@tonic-gate *
727c478bdstevel@tonic-gate * @buffer must be large enough to hold the entire PCI 2.2 config space
737c478bdstevel@tonic-gate * (>= 64 bytes).
747c478bdstevel@tonic-gate */
757c478bdstevel@tonic-gatestatic int pci_save_state(struct pci_device *dev, uint32_t *buffer)
767c478bdstevel@tonic-gate{
777c478bdstevel@tonic-gate	int i;
787c478bdstevel@tonic-gate	for (i = 0; i < 16; i++)
797c478bdstevel@tonic-gate		pci_read_config_dword(dev, i * 4,&buffer[i]);
807c478bdstevel@tonic-gate	return 0;
817c478bdstevel@tonic-gate}
827c478bdstevel@tonic-gate
837c478bdstevel@tonic-gate/**
847c478bdstevel@tonic-gate * pci_restore_state - Restore the saved state of a PCI device
857c478bdstevel@tonic-gate * @dev: - PCI device that we're dealing with
867c478bdstevel@tonic-gate * @buffer: - saved PCI config space
877c478bdstevel@tonic-gate *
887c478bdstevel@tonic-gate */
897c478bdstevel@tonic-gatestatic int pci_restore_state(struct pci_device *dev, uint32_t *buffer)
907c478bdstevel@tonic-gate{
917c478bdstevel@tonic-gate	int i;
927c478bdstevel@tonic-gate
937c478bdstevel@tonic-gate	for (i = 0; i < 16; i++)
947c478bdstevel@tonic-gate		pci_write_config_dword(dev,i * 4, buffer[i]);
957c478bdstevel@tonic-gate	return 0;
967c478bdstevel@tonic-gate}
977c478bdstevel@tonic-gate
987c478bdstevel@tonic-gatestatic void tg3_write_indirect_reg32(uint32_t off, uint32_t val)
997c478bdstevel@tonic-gate{
1007c478bdstevel@tonic-gate	pci_write_config_dword(tg3.pdev, TG3PCI_REG_BASE_ADDR, off);
1017c478bdstevel@tonic-gate	pci_write_config_dword(tg3.pdev, TG3PCI_REG_DATA, val);
1027c478bdstevel@tonic-gate}
1037c478bdstevel@tonic-gate
1047c478bdstevel@tonic-gate#define tw32(reg,val)		tg3_write_indirect_reg32((reg),(val))
1057c478bdstevel@tonic-gate#define tw32_mailbox(reg, val)	writel(((val) & 0xffffffff), tg3.regs + (reg))
1067c478bdstevel@tonic-gate#define tw16(reg,val)		writew(((val) & 0xffff), tg3.regs + (reg))
1077c478bdstevel@tonic-gate#define tw8(reg,val)		writeb(((val) & 0xff), tg3.regs + (reg))
1087c478bdstevel@tonic-gate#define tr32(reg)		readl(tg3.regs + (reg))
1097c478bdstevel@tonic-gate#define tr16(reg)		readw(tg3.regs + (reg))
1107c478bdstevel@tonic-gate#define tr8(reg)		readb(tg3.regs + (reg))
1117c478bdstevel@tonic-gate
1127c478bdstevel@tonic-gatestatic void tw32_carefully(uint32_t reg, uint32_t val)
1137c478bdstevel@tonic-gate{
1147c478bdstevel@tonic-gate	tw32(reg, val);
1157c478bdstevel@tonic-gate	tr32(reg);
1167c478bdstevel@tonic-gate	udelay(100);
1177c478bdstevel@tonic-gate}
1187c478bdstevel@tonic-gate
1197c478bdstevel@tonic-gatestatic void tw32_mailbox2(uint32_t reg, uint32_t val)
1207c478bdstevel@tonic-gate{
1217c478bdstevel@tonic-gate	tw32_mailbox(reg, val);
1227c478bdstevel@tonic-gate	tr32(reg);
1237c478bdstevel@tonic-gate}
1247c478bdstevel@tonic-gate
1257c478bdstevel@tonic-gatestatic void tg3_write_mem(uint32_t off, uint32_t val)
1267c478bdstevel@tonic-gate{
1277c478bdstevel@tonic-gate	pci_write_config_dword(tg3.pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
1287c478bdstevel@tonic-gate	pci_write_config_dword(tg3.pdev, TG3PCI_MEM_WIN_DATA, val);
1297c478bdstevel@tonic-gate
1307c478bdstevel@tonic-gate	/* Always leave this as zero. */
1317c478bdstevel@tonic-gate	pci_write_config_dword(tg3.pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
1327c478bdstevel@tonic-gate}
1337c478bdstevel@tonic-gate
1347c478bdstevel@tonic-gatestatic void tg3_read_mem(uint32_t off, uint32_t *val)
1357c478bdstevel@tonic-gate{
1367c478bdstevel@tonic-gate	pci_write_config_dword(tg3.pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
1377c478bdstevel@tonic-gate	pci_read_config_dword(tg3.pdev, TG3PCI_MEM_WIN_DATA, val);
1387c478bdstevel@tonic-gate
1397c478bdstevel@tonic-gate	/* Always leave this as zero. */
1407c478bdstevel@tonic-gate	pci_write_config_dword(tg3.pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
1417c478bdstevel@tonic-gate}
1427c478bdstevel@tonic-gate
1437c478bdstevel@tonic-gatestatic void tg3_disable_ints(struct tg3 *tp)
1447c478bdstevel@tonic-gate{
1457c478bdstevel@tonic-gate	tw32(TG3PCI_MISC_HOST_CTRL,
1467c478bdstevel@tonic-gate	     (tp->misc_host_ctrl | MISC_HOST_CTRL_MASK_PCI_INT));
1477c478bdstevel@tonic-gate	tw32_mailbox2(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
1487c478bdstevel@tonic-gate}
1497c478bdstevel@tonic-gate
1507c478bdstevel@tonic-gatestatic void tg3_switch_clocks(struct tg3 *tp)
1517c478bdstevel@tonic-gate{
1527c478bdstevel@tonic-gate	uint32_t orig_clock_ctrl, clock_ctrl;
1537c478bdstevel@tonic-gate
1547c478bdstevel@tonic-gate	clock_ctrl = tr32(TG3PCI_CLOCK_CTRL);
1557c478bdstevel@tonic-gate
1567c478bdstevel@tonic-gate	orig_clock_ctrl = clock_ctrl;
1577c478bdstevel@tonic-gate	clock_ctrl &= (CLOCK_CTRL_FORCE_CLKRUN | CLOCK_CTRL_CLKRUN_OENABLE | 0x1f);
1587c478bdstevel@tonic-gate	tp->pci_clock_ctrl = clock_ctrl;
1597c478bdstevel@tonic-gate
1607c478bdstevel@tonic-gate	if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) &&
1617c478bdstevel@tonic-gate		(orig_clock_ctrl & CLOCK_CTRL_44MHZ_CORE)!=0) {
1627c478bdstevel@tonic-gate		tw32_carefully(TG3PCI_CLOCK_CTRL,
1637c478bdstevel@tonic-gate			clock_ctrl | (CLOCK_CTRL_44MHZ_CORE | CLOCK_CTRL_ALTCLK));
1647c478bdstevel@tonic-gate		tw32_carefully(TG3PCI_CLOCK_CTRL,
1657c478bdstevel@tonic-gate			clock_ctrl | (CLOCK_CTRL_ALTCLK));
1667c478bdstevel@tonic-gate	}
1677c478bdstevel@tonic-gate	tw32_carefully(TG3PCI_CLOCK_CTRL, clock_ctrl);
1687c478bdstevel@tonic-gate}
1697c478bdstevel@tonic-gate
1707c478bdstevel@tonic-gate#define PHY_BUSY_LOOPS	5000
1717c478bdstevel@tonic-gate
1727c478bdstevel@tonic-gatestatic int tg3_readphy(struct tg3 *tp, int reg, uint32_t *val)
1737c478bdstevel@tonic-gate{
1747c478bdstevel@tonic-gate	uint32_t frame_val;
1757c478bdstevel@tonic-gate	int loops, ret;
1767c478bdstevel@tonic-gate
1777c478bdstevel@tonic-gate	tw32_carefully(MAC_MI_MODE, tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL);
1787c478bdstevel@tonic-gate
1797c478bdstevel@tonic-gate	*val = 0xffffffff;
1807c478bdstevel@tonic-gate
1817c478bdstevel@tonic-gate	frame_val  = ((PHY_ADDR << MI_COM_PHY_ADDR_SHIFT) &
1827c478bdstevel@tonic-gate		      MI_COM_PHY_ADDR_MASK);
1837c478bdstevel@tonic-gate	frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) &
1847c478bdstevel@tonic-gate		      MI_COM_REG_ADDR_MASK);
1857c478bdstevel@tonic-gate	frame_val |= (MI_COM_CMD_READ | MI_COM_START);
1867c478bdstevel@tonic-gate
1877c478bdstevel@tonic-gate	tw32_carefully(MAC_MI_COM, frame_val);
1887c478bdstevel@tonic-gate
1897c478bdstevel@tonic-gate	loops = PHY_BUSY_LOOPS;
1907c478bdstevel@tonic-gate	while (loops-- > 0) {
1917c478bdstevel@tonic-gate		udelay(10);
1927c478bdstevel@tonic-gate		frame_val = tr32(MAC_MI_COM);
1937c478bdstevel@tonic-gate
1947c478bdstevel@tonic-gate		if ((frame_val & MI_COM_BUSY) == 0) {
1957c478bdstevel@tonic-gate			udelay(5);
1967c478bdstevel@tonic-gate			frame_val = tr32(MAC_MI_COM);
1977c478bdstevel@tonic-gate			break;
1987c478bdstevel@tonic-gate		}
1997c478bdstevel@tonic-gate	}
2007c478bdstevel@tonic-gate
2017c478bdstevel@tonic-gate	ret = -EBUSY;
2027c478bdstevel@tonic-gate	if (loops > 0) {
2037c478bdstevel@tonic-gate		*val = frame_val & MI_COM_DATA_MASK;
2047c478bdstevel@tonic-gate		ret = 0;
2057c478bdstevel@tonic-gate	}
2067c478bdstevel@tonic-gate
2077c478bdstevel@tonic-gate	tw32_carefully(MAC_MI_MODE, tp->mi_mode);
2087c478bdstevel@tonic-gate
2097c478bdstevel@tonic-gate	return ret;
2107c478bdstevel@tonic-gate}
2117c478bdstevel@tonic-gate
2127c478bdstevel@tonic-gatestatic int tg3_writephy(struct tg3 *tp, int reg, uint32_t val)
2137c478bdstevel@tonic-gate{
2147c478bdstevel@tonic-gate	uint32_t frame_val;
2157c478bdstevel@tonic-gate	int loops, ret;
2167c478bdstevel@tonic-gate
2177c478bdstevel@tonic-gate	tw32_carefully(MAC_MI_MODE, tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL);
2187c478bdstevel@tonic-gate
2197c478bdstevel@tonic-gate	frame_val  = ((PHY_ADDR << MI_COM_PHY_ADDR_SHIFT) &
2207c478bdstevel@tonic-gate		      MI_COM_PHY_ADDR_MASK);
2217c478bdstevel@tonic-gate	frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) &
2227c478bdstevel@tonic-gate		      MI_COM_REG_ADDR_MASK);
2237c478bdstevel@tonic-gate	frame_val |= (val & MI_COM_DATA_MASK);
2247c478bdstevel@tonic-gate	frame_val |= (MI_COM_CMD_WRITE | MI_COM_START);
2257c478bdstevel@tonic-gate
2267c478bdstevel@tonic-gate	tw32_carefully(MAC_MI_COM, frame_val);
2277c478bdstevel@tonic-gate
2287c478bdstevel@tonic-gate	loops = PHY_BUSY_LOOPS;
2297c478bdstevel@tonic-gate	while (loops-- > 0) {
2307c478bdstevel@tonic-gate		udelay(10);
2317c478bdstevel@tonic-gate		frame_val = tr32(MAC_MI_COM);
2327c478bdstevel@tonic-gate		if ((frame_val & MI_COM_BUSY) == 0) {
2337c478bdstevel@tonic-gate			udelay(5);
2347c478bdstevel@tonic-gate			frame_val = tr32(MAC_MI_COM);
2357c478bdstevel@tonic-gate			break;
2367c478bdstevel@tonic-gate		}
2377c478bdstevel@tonic-gate	}
2387c478bdstevel@tonic-gate
2397c478bdstevel@tonic-gate	ret = -EBUSY;
2407c478bdstevel@tonic-gate	if (loops > 0)
2417c478bdstevel@tonic-gate		ret = 0;
2427c478bdstevel@tonic-gate
2437c478bdstevel@tonic-gate	tw32_carefully(MAC_MI_MODE, tp->mi_mode);
2447c478bdstevel@tonic-gate
2457c478bdstevel@tonic-gate	return ret;
2467c478bdstevel@tonic-gate}
2477c478bdstevel@tonic-gate
2487c478bdstevel@tonic-gatestatic int tg3_writedsp(struct tg3 *tp, uint16_t addr, uint16_t val)
2497c478bdstevel@tonic-gate{
2507c478bdstevel@tonic-gate	int err;
2517c478bdstevel@tonic-gate	err  = tg3_writephy(tp, MII_TG3_DSP_ADDRESS, addr);
2527c478bdstevel@tonic-gate	err |= tg3_writephy(tp, MII_TG3_DSP_RW_PORT, val);
2537c478bdstevel@tonic-gate	return err;
2547c478bdstevel@tonic-gate}
2557c478bdstevel@tonic-gate
2567c478bdstevel@tonic-gate
2577c478bdstevel@tonic-gatestatic void tg3_phy_set_wirespeed(struct tg3 *tp)
2587c478bdstevel@tonic-gate{
2597c478bdstevel@tonic-gate	uint32_t val;
2607c478bdstevel@tonic-gate
2617c478bdstevel@tonic-gate	if (tp->tg3_flags2 & TG3_FLG2_NO_ETH_WIRE_SPEED)
2627c478bdstevel@tonic-gate		return;
2637c478bdstevel@tonic-gate
2647c478bdstevel@tonic-gate	tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x7007);
2657c478bdstevel@tonic-gate	tg3_readphy(tp, MII_TG3_AUX_CTRL, &val);
2667c478bdstevel@tonic-gate	tg3_writephy(tp, MII_TG3_AUX_CTRL, (val | (1 << 15) | (1 << 4)));
2677c478bdstevel@tonic-gate}
2687c478bdstevel@tonic-gate
2697c478bdstevel@tonic-gatestatic int tg3_bmcr_reset(struct tg3 *tp)
2707c478bdstevel@tonic-gate{
2717c478bdstevel@tonic-gate	uint32_t phy_control;
2727c478bdstevel@tonic-gate	int limit, err;
2737c478bdstevel@tonic-gate
2747c478bdstevel@tonic-gate	/* OK, reset it, and poll the BMCR_RESET bit until it
2757c478bdstevel@tonic-gate	 * clears or we time out.
2767c478bdstevel@tonic-gate	 */
2777c478bdstevel@tonic-gate	phy_control = BMCR_RESET;
2787c478bdstevel@tonic-gate	err = tg3_writephy(tp, MII_BMCR, phy_control);
2797c478bdstevel@tonic-gate	if (err != 0)
2807c478bdstevel@tonic-gate		return -EBUSY;
2817c478bdstevel@tonic-gate
2827c478bdstevel@tonic-gate	limit = 5000;
2837c478bdstevel@tonic-gate	while (limit--) {
2847c478bdstevel@tonic-gate		err = tg3_readphy(tp, MII_BMCR, &phy_control);
2857c478bdstevel@tonic-gate		if (err != 0)
2867c478bdstevel@tonic-gate			return -EBUSY;
2877c478bdstevel@tonic-gate
2887c478bdstevel@tonic-gate		if ((phy_control & BMCR_RESET) == 0) {
2897c478bdstevel@tonic-gate			udelay(40);
2907c478bdstevel@tonic-gate			break;
2917c478bdstevel@tonic-gate		}
2927c478bdstevel@tonic-gate		udelay(10);
2937c478bdstevel@tonic-gate	}
2947c478bdstevel@tonic-gate	if (limit <= 0)
2957c478bdstevel@tonic-gate		return -EBUSY;
2967c478bdstevel@tonic-gate
2977c478bdstevel@tonic-gate	return 0;
2987c478bdstevel@tonic-gate}
2997c478bdstevel@tonic-gate
3007c478bdstevel@tonic-gatestatic int tg3_wait_macro_done(struct tg3 *tp)
3017c478bdstevel@tonic-gate{
3027c478bdstevel@tonic-gate	int limit = 100;
3037c478bdstevel@tonic-gate
3047c478bdstevel@tonic-gate	while (limit--) {
3057c478bdstevel@tonic-gate		uint32_t tmp32;
3067c478bdstevel@tonic-gate
3077c478bdstevel@tonic-gate		tg3_readphy(tp, 0x16, &tmp32);
3087c478bdstevel@tonic-gate		if ((tmp32 & 0x1000) == 0)
3097c478bdstevel@tonic-gate			break;
3107c478bdstevel@tonic-gate	}
3117c478bdstevel@tonic-gate	if (limit <= 0)
3127c478bdstevel@tonic-gate		return -EBUSY;
3137c478bdstevel@tonic-gate
3147c478bdstevel@tonic-gate	return 0;
3157c478bdstevel@tonic-gate}
3167c478bdstevel@tonic-gate
3177c478bdstevel@tonic-gatestatic int tg3_phy_write_and_check_testpat(struct tg3 *tp, int *resetp)
3187c478bdstevel@tonic-gate{
3197c478bdstevel@tonic-gate	static const uint32_t test_pat[4][6] = {
3207c478bdstevel@tonic-gate	{ 0x00005555, 0x00000005, 0x00002aaa, 0x0000000a, 0x00003456, 0x00000003 },
3217c478bdstevel@tonic-gate	{ 0x00002aaa, 0x0000000a, 0x00003333, 0x00000003, 0x0000789a, 0x00000005 },
3227c478bdstevel@tonic-gate	{ 0x00005a5a, 0x00000005, 0x00002a6a, 0x0000000a, 0x00001bcd, 0x00000003 },
3237c478bdstevel@tonic-gate	{ 0x00002a5a, 0x0000000a, 0x000033c3, 0x00000003, 0x00002ef1, 0x00000005 }
3247c478bdstevel@tonic-gate	};
3257c478bdstevel@tonic-gate	int chan;
3267c478bdstevel@tonic-gate
3277c478bdstevel@tonic-gate	for (chan = 0; chan < 4; chan++) {
3287c478bdstevel@tonic-gate		int i;
3297c478bdstevel@tonic-gate
3307c478bdstevel@tonic-gate		tg3_writephy(tp, MII_TG3_DSP_ADDRESS,
3317c478bdstevel@tonic-gate			(chan * 0x2000) | 0x0200);
3327c478bdstevel@tonic-gate		tg3_writephy(tp, 0x16, 0x0002);
3337c478bdstevel@tonic-gate
3347c478bdstevel@tonic-gate		for (i = 0; i < 6; i++)
3357c478bdstevel@tonic-gate			tg3_writephy(tp, MII_TG3_DSP_RW_PORT,
3367c478bdstevel@tonic-gate				test_pat[chan][i]);
3377c478bdstevel@tonic-gate
3387c478bdstevel@tonic-gate		tg3_writephy(tp, 0x16, 0x0202);
3397c478bdstevel@tonic-gate		if (tg3_wait_macro_done(tp)) {
3407c478bdstevel@tonic-gate			*resetp = 1;
3417c478bdstevel@tonic-gate			return -EBUSY;
3427c478bdstevel@tonic-gate		}
3437c478bdstevel@tonic-gate
3447c478bdstevel@tonic-gate		tg3_writephy(tp, MII_TG3_DSP_ADDRESS,
3457c478bdstevel@tonic-gate			     (chan * 0x2000) | 0x0200);
3467c478bdstevel@tonic-gate		tg3_writephy(tp, 0x16, 0x0082);
3477c478bdstevel@tonic-gate		if (tg3_wait_macro_done(tp)) {
3487c478bdstevel@tonic-gate			*resetp = 1;
3497c478bdstevel@tonic-gate			return -EBUSY;
3507c478bdstevel@tonic-gate		}
3517c478bdstevel@tonic-gate
3527c478bdstevel@tonic-gate		tg3_writephy(tp, 0x16, 0x0802);
3537c478bdstevel@tonic-gate		if (tg3_wait_macro_done(tp)) {
3547c478bdstevel@tonic-gate			*resetp = 1;
3557c478bdstevel@tonic-gate			return -EBUSY;
3567c478bdstevel@tonic-gate		}
3577c478bdstevel@tonic-gate
3587c478bdstevel@tonic-gate		for (i = 0; i < 6; i += 2) {
3597c478bdstevel@tonic-gate			uint32_t low, high;
3607c478bdstevel@tonic-gate
3617c478bdstevel@tonic-gate			tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &low);
3627c478bdstevel@tonic-gate			tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &high);
3637c478bdstevel@tonic-gate			if (tg3_wait_macro_done(tp)) {
3647c478bdstevel@tonic-gate				*resetp = 1;
3657c478bdstevel@tonic-gate				return -EBUSY;
3667c478bdstevel@tonic-gate			}
3677c478bdstevel@tonic-gate			low &= 0x7fff;
3687c478bdstevel@tonic-gate			high &= 0x000f;
3697c478bdstevel@tonic-gate			if (low != test_pat[chan][i] ||
3707c478bdstevel@tonic-gate			    high != test_pat[chan][i+1]) {
3717c478bdstevel@tonic-gate				tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000b);
3727c478bdstevel@tonic-gate				tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x4001);
3737c478bdstevel@tonic-gate				tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x4005);
3747c478bdstevel@tonic-gate
3757c478bdstevel@tonic-gate				return -EBUSY;
3767c478bdstevel@tonic-gate			}
3777c478bdstevel@tonic-gate		}
3787c478bdstevel@tonic-gate	}
3797c478bdstevel@tonic-gate
3807c478bdstevel@tonic-gate	return 0;
3817c478bdstevel@tonic-gate}
3827c478bdstevel@tonic-gate
3837c478bdstevel@tonic-gatestatic int tg3_phy_reset_chanpat(struct tg3 *tp)
3847c478bdstevel@tonic-gate{
3857c478bdstevel@tonic-gate	int chan;
3867c478bdstevel@tonic-gate
3877c478bdstevel@tonic-gate	for (chan = 0; chan < 4; chan++) {
3887c478bdstevel@tonic-gate		int i;
3897c478bdstevel@tonic-gate
3907c478bdstevel@tonic-gate		tg3_writephy(tp, MII_TG3_DSP_ADDRESS,
3917c478bdstevel@tonic-gate			     (chan * 0x2000) | 0x0200);
3927c478bdstevel@tonic-gate		tg3_writephy(tp, 0x16, 0x0002);
3937c478bdstevel@tonic-gate		for (i = 0; i < 6; i++)
3947c478bdstevel@tonic-gate			tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x000);
3957c478bdstevel@tonic-gate		tg3_writephy(tp, 0x16, 0x0202);
3967c478bdstevel@tonic-gate		if (tg3_wait_macro_done(tp))
3977c478bdstevel@tonic-gate			return -EBUSY;
3987c478bdstevel@tonic-gate	}
3997c478bdstevel@tonic-gate
4007c478bdstevel@tonic-gate	return 0;
4017c478bdstevel@tonic-gate}
4027c478bdstevel@tonic-gate
4037c478bdstevel@tonic-gatestatic int tg3_phy_reset_5703_4_5(struct tg3 *tp)
4047c478bdstevel@tonic-gate{
4057c478bdstevel@tonic-gate	uint32_t reg32, phy9_orig;
4067c478bdstevel@tonic-gate	int retries, do_phy_reset, err;
4077c478bdstevel@tonic-gate
4087c478bdstevel@tonic-gate	retries = 10;
4097c478bdstevel@tonic-gate	do_phy_reset = 1;
4107c478bdstevel@tonic-gate	do {
4117c478bdstevel@tonic-gate		if (do_phy_reset) {
4127c478bdstevel@tonic-gate			err = tg3_bmcr_reset(tp);
4137c478bdstevel@tonic-gate			if (err)
4147c478bdstevel@tonic-gate				return err;
4157c478bdstevel@tonic-gate			do_phy_reset = 0;
4167c478bdstevel@tonic-gate		}
4177c478bdstevel@tonic-gate
4187c478bdstevel@tonic-gate		/* Disable transmitter and interrupt.  */
4197c478bdstevel@tonic-gate		tg3_readphy(tp, MII_TG3_EXT_CTRL, &reg32);
4207c478bdstevel@tonic-gate		reg32 |= 0x3000;
4217c478bdstevel@tonic-gate		tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32);
4227c478bdstevel@tonic-gate
4237c478bdstevel@tonic-gate		/* Set full-duplex, 1000 mbps.  */
4247c478bdstevel@tonic-gate		tg3_writephy(tp, MII_BMCR,
4257c478bdstevel@tonic-gate			BMCR_FULLDPLX | TG3_BMCR_SPEED1000);
4267c478bdstevel@tonic-gate
4277c478bdstevel@tonic-gate		/* Set to master mode.  */
4287c478bdstevel@tonic-gate		tg3_readphy(tp, MII_TG3_CTRL, &phy9_orig);
4297c478bdstevel@tonic-gate		tg3_writephy(tp, MII_TG3_CTRL,
4307c478bdstevel@tonic-gate			(MII_TG3_CTRL_AS_MASTER |
4317c478bdstevel@tonic-gate				MII_TG3_CTRL_ENABLE_AS_MASTER));
4327c478bdstevel@tonic-gate
4337c478bdstevel@tonic-gate		/* Enable SM_DSP_CLOCK and 6dB.  */
4347c478bdstevel@tonic-gate		tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00);
4357c478bdstevel@tonic-gate
4367c478bdstevel@tonic-gate		/* Block the PHY control access.  */
4377c478bdstevel@tonic-gate		tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8005);
4387c478bdstevel@tonic-gate		tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x0800);
4397c478bdstevel@tonic-gate
4407c478bdstevel@tonic-gate		err = tg3_phy_write_and_check_testpat(tp, &do_phy_reset);
4417c478bdstevel@tonic-gate		if (!err)
4427c478bdstevel@tonic-gate			break;
4437c478bdstevel@tonic-gate	} while (--retries);
4447c478bdstevel@tonic-gate
4457c478bdstevel@tonic-gate	err = tg3_phy_reset_chanpat(tp);
4467c478bdstevel@tonic-gate	if (err)
4477c478bdstevel@tonic-gate		return err;
4487c478bdstevel@tonic-gate
4497c478bdstevel@tonic-gate	tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8005);
4507c478bdstevel@tonic-gate	tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x0000);
4517c478bdstevel@tonic-gate
4527c478bdstevel@tonic-gate	tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8200);
4537c478bdstevel@tonic-gate	tg3_writephy(tp, 0x16, 0x0000);
4547c478bdstevel@tonic-gate
4557c478bdstevel@tonic-gate	tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0400);
4567c478bdstevel@tonic-gate
4577c478bdstevel@tonic-gate	tg3_writephy(tp, MII_TG3_CTRL, phy9_orig);
4587c478bdstevel@tonic-gate
4597c478bdstevel@tonic-gate	tg3_readphy(tp, MII_TG3_EXT_CTRL, &reg32);
4607c478bdstevel@tonic-gate	reg32 &= ~0x3000;
4617c478bdstevel@tonic-gate	tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32);
4627c478bdstevel@tonic-gate
4637c478bdstevel@tonic-gate	return err;
4647c478bdstevel@tonic-gate}
4657c478bdstevel@tonic-gate
4667c478bdstevel@tonic-gate/* This will reset the tigon3 PHY if there is no valid
4677c478bdstevel@tonic-gate * link.
4687c478bdstevel@tonic-gate */
4697c478bdstevel@tonic-gatestatic int tg3_phy_reset(struct tg3 *tp)
4707c478bdstevel@tonic-gate{
4717c478bdstevel@tonic-gate	uint32_t phy_status;
4727c478bdstevel@tonic-gate	int err;
4737c478bdstevel@tonic-gate
4747c478bdstevel@tonic-gate	err  = tg3_readphy(tp, MII_BMSR, &phy_status);
4757c478bdstevel@tonic-gate	err |= tg3_readphy(tp, MII_BMSR, &phy_status);
4767c478bdstevel@tonic-gate	if (err != 0)
4777c478bdstevel@tonic-gate		return -EBUSY;
4787c478bdstevel@tonic-gate
4797c478bdstevel@tonic-gate	if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703) ||
4807c478bdstevel@tonic-gate		(GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) ||
4817c478bdstevel@tonic-gate		(GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705)) {
4827c478bdstevel@tonic-gate		err = tg3_phy_reset_5703_4_5(tp);
4837c478bdstevel@tonic-gate		if (err)
4847c478bdstevel@tonic-gate			return err;
4857c478bdstevel@tonic-gate		goto out;
4867c478bdstevel@tonic-gate	}
4877c478bdstevel@tonic-gate	err = tg3_bmcr_reset(tp);
4887c478bdstevel@tonic-gate	if (err)
4897c478bdstevel@tonic-gate		return err;
4907c478bdstevel@tonic-gate out:
4917c478bdstevel@tonic-gate	tg3_phy_set_wirespeed(tp);
4927c478bdstevel@tonic-gate	return 0;
4937c478bdstevel@tonic-gate}
4947c478bdstevel@tonic-gate
4957c478bdstevel@tonic-gatestatic void tg3_set_power_state_0(struct tg3 *tp)
4967c478bdstevel@tonic-gate{
4977c478bdstevel@tonic-gate	uint16_t power_control;
4987c478bdstevel@tonic-gate	int pm = tp->pm_cap;
4997c478bdstevel@tonic-gate
5007c478bdstevel@tonic-gate	/* Make sure register accesses (indirect or otherwise)
5017c478bdstevel@tonic-gate	 * will function correctly.
5027c478bdstevel@tonic-gate	 */
5037c478bdstevel@tonic-gate	pci_write_config_dword(tp->pdev,  TG3PCI_MISC_HOST_CTRL, tp->misc_host_ctrl);
5047c478bdstevel@tonic-gate
5057c478bdstevel@tonic-gate	pci_read_config_word(tp->pdev, pm + PCI_PM_CTRL, &power_control);
5067c478bdstevel@tonic-gate
5077c478bdstevel@tonic-gate	power_control |= PCI_PM_CTRL_PME_STATUS;
5087c478bdstevel@tonic-gate	power_control &= ~(PCI_PM_CTRL_STATE_MASK);
5097c478bdstevel@tonic-gate	power_control |= 0;
5107c478bdstevel@tonic-gate	pci_write_config_word(tp->pdev, pm + PCI_PM_CTRL, power_control);
5117c478bdstevel@tonic-gate
5127c478bdstevel@tonic-gate	tw32_carefully(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
5137c478bdstevel@tonic-gate
5147c478bdstevel@tonic-gate	return;
5157c478bdstevel@tonic-gate}
5167c478bdstevel@tonic-gate
5177c478bdstevel@tonic-gate
5187c478bdstevel@tonic-gate#if SUPPORT_LINK_REPORT
5197c478bdstevel@tonic-gatestatic void tg3_link_report(struct tg3 *tp)
5207c478bdstevel@tonic-gate{
5217c478bdstevel@tonic-gate	if (!tp->carrier_ok) {
5227c478bdstevel@tonic-gate		printf("Link is down.\n");
5237c478bdstevel@tonic-gate	} else {
5247c478bdstevel@tonic-gate		printf("Link is up at %d Mbps, %s duplex. %s %s %s\n",
5257c478bdstevel@tonic-gate			(tp->link_config.active_speed == SPEED_1000 ?
5267c478bdstevel@tonic-gate			       1000 :
5277c478bdstevel@tonic-gate			(tp->link_config.active_speed == SPEED_100 ?
5287c478bdstevel@tonic-gate				100 : 10)),
5297c478bdstevel@tonic-gate			(tp->link_config.active_duplex == DUPLEX_FULL ?
5307c478bdstevel@tonic-gate				"full" : "half"),
5317c478bdstevel@tonic-gate			(tp->tg3_flags & TG3_FLAG_TX_PAUSE) ? "TX" : "",
5327c478bdstevel@tonic-gate			(tp->tg3_flags & TG3_FLAG_RX_PAUSE) ? "RX" : "",
5337c478bdstevel@tonic-gate			(tp->tg3_flags & (TG3_FLAG_TX_PAUSE |TG3_FLAG_RX_PAUSE)) ? "flow control" : "");
5347c478bdstevel@tonic-gate	}
5357c478bdstevel@tonic-gate}
5367c478bdstevel@tonic-gate#else
5377c478bdstevel@tonic-gate#define tg3_link_report(tp)
5387c478bdstevel@tonic-gate#endif
5397c478bdstevel@tonic-gate
5407c478bdstevel@tonic-gatestatic void tg3_setup_flow_control(struct tg3 *tp, uint32_t local_adv, uint32_t remote_adv)
5417c478bdstevel@tonic-gate{
5427c478bdstevel@tonic-gate	uint32_t new_tg3_flags = 0;
5437c478bdstevel@tonic-gate
5447c478bdstevel@tonic-gate	if (local_adv & ADVERTISE_PAUSE_CAP) {
5457c478bdstevel@tonic-gate		if (local_adv & ADVERTISE_PAUSE_ASYM) {
5467c478bdstevel@tonic-gate			if (remote_adv & LPA_PAUSE_CAP)
5477c478bdstevel@tonic-gate				new_tg3_flags |=
5487c478bdstevel@tonic-gate					(TG3_FLAG_RX_PAUSE |
5497c478bdstevel@tonic-gate					 TG3_FLAG_TX_PAUSE);
5507c478bdstevel@tonic-gate			else if (remote_adv & LPA_PAUSE_ASYM)
5517c478bdstevel@tonic-gate				new_tg3_flags |=
5527c478bdstevel@tonic-gate					(TG3_FLAG_RX_PAUSE);
5537c478bdstevel@tonic-gate		} else {
5547c478bdstevel@tonic-gate			if (remote_adv & LPA_PAUSE_CAP)
5557c478bdstevel@tonic-gate				new_tg3_flags |=
5567c478bdstevel@tonic-gate					(TG3_FLAG_RX_PAUSE |
5577c478bdstevel@tonic-gate					 TG3_FLAG_TX_PAUSE);
5587c478bdstevel@tonic-gate		}
5597c478bdstevel@tonic-gate	} else if (local_adv & ADVERTISE_PAUSE_ASYM) {
5607c478bdstevel@tonic-gate		if ((remote_adv & LPA_PAUSE_CAP) &&
5617c478bdstevel@tonic-gate		    (remote_adv & LPA_PAUSE_ASYM))
5627c478bdstevel@tonic-gate			new_tg3_flags |= TG3_FLAG_TX_PAUSE;
5637c478bdstevel@tonic-gate	}
5647c478bdstevel@tonic-gate
5657c478bdstevel@tonic-gate	tp->tg3_flags &= ~(TG3_FLAG_RX_PAUSE | TG3_FLAG_TX_PAUSE);
5667c478bdstevel@tonic-gate	tp->tg3_flags |= new_tg3_flags;
5677c478bdstevel@tonic-gate
5687c478bdstevel@tonic-gate	if (new_tg3_flags & TG3_FLAG_RX_PAUSE)
5697c478bdstevel@tonic-gate		tp->rx_mode |= RX_MODE_FLOW_CTRL_ENABLE;
5707c478bdstevel@tonic-gate	else
5717c478bdstevel@tonic-gate		tp->rx_mode &= ~RX_MODE_FLOW_CTRL_ENABLE;
5727c478bdstevel@tonic-gate
5737c478bdstevel@tonic-gate	if (new_tg3_flags & TG3_FLAG_TX_PAUSE)
5747c478bdstevel@tonic-gate		tp->tx_mode |= TX_MODE_FLOW_CTRL_ENABLE;
5757c478bdstevel@tonic-gate	else
5767c478bdstevel@tonic-gate		tp->tx_mode &= ~TX_MODE_FLOW_CTRL_ENABLE;
5777c478bdstevel@tonic-gate}
5787c478bdstevel@tonic-gate
5797c478bdstevel@tonic-gate#if SUPPORT_COPPER_PHY
5807c478bdstevel@tonic-gatestatic void tg3_aux_stat_to_speed_duplex(
5817c478bdstevel@tonic-gate	struct tg3 *tp __unused, uint32_t val, uint8_t *speed, uint8_t *duplex)
5827c478bdstevel@tonic-gate{
5837c478bdstevel@tonic-gate	static const uint8_t map[] = {
5847c478bdstevel@tonic-gate		[0] = (SPEED_INVALID << 2) | DUPLEX_INVALID,
5857c478bdstevel@tonic-gate		[MII_TG3_AUX_STAT_10HALF >> 8]   = (SPEED_10 << 2) | DUPLEX_HALF,
5867c478bdstevel@tonic-gate		[MII_TG3_AUX_STAT_10FULL >> 8]   = (SPEED_10 << 2) | DUPLEX_FULL,
5877c478bdstevel@tonic-gate		[MII_TG3_AUX_STAT_100HALF >> 8]  = (SPEED_100 << 2) | DUPLEX_HALF,
5887c478bdstevel@tonic-gate		[MII_TG3_AUX_STAT_100_4 >> 8] = (SPEED_INVALID << 2) | DUPLEX_INVALID,
5897c478bdstevel@tonic-gate		[MII_TG3_AUX_STAT_100FULL >> 8]  = (SPEED_100 << 2) | DUPLEX_FULL,
5907c478bdstevel@tonic-gate		[MII_TG3_AUX_STAT_1000HALF >> 8] = (SPEED_1000 << 2) | DUPLEX_HALF,
5917c478bdstevel@tonic-gate		[MII_TG3_AUX_STAT_1000FULL >> 8] = (SPEED_1000 << 2) | DUPLEX_FULL,
5927c478bdstevel@tonic-gate	};
5937c478bdstevel@tonic-gate	uint8_t result;
5947c478bdstevel@tonic-gate	result = map[(val & MII_TG3_AUX_STAT_SPDMASK) >> 8];
5957c478bdstevel@tonic-gate	*speed = result >> 2;
5967c478bdstevel@tonic-gate	*duplex = result & 3;
5977c478bdstevel@tonic-gate}
5987c478bdstevel@tonic-gate
5997c478bdstevel@tonic-gatestatic int tg3_phy_copper_begin(struct tg3 *tp)
6007c478bdstevel@tonic-gate{
6017c478bdstevel@tonic-gate	uint32_t new_adv;
6027c478bdstevel@tonic-gate
6037c478bdstevel@tonic-gate	tp->link_config.advertising =
6047c478bdstevel@tonic-gate		(ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
6057c478bdstevel@tonic-gate			ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full |
6067c478bdstevel@tonic-gate			ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full |
6077c478bdstevel@tonic-gate			ADVERTISED_Autoneg | ADVERTISED_MII);
6087c478bdstevel@tonic-gate
6097c478bdstevel@tonic-gate	if (tp->tg3_flags & TG3_FLAG_10_100_ONLY) {
6107c478bdstevel@tonic-gate		tp->link_config.advertising &=
6117c478bdstevel@tonic-gate			~(ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full);
6127c478bdstevel@tonic-gate	}
6137c478bdstevel@tonic-gate
6147c478bdstevel@tonic-gate	new_adv = (ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
6157c478bdstevel@tonic-gate	if (tp->link_config.advertising & ADVERTISED_10baseT_Half) {
6167c478bdstevel@tonic-gate		new_adv |= ADVERTISE_10HALF;
6177c478bdstevel@tonic-gate	}
6187c478bdstevel@tonic-gate	if (tp->link_config.advertising & ADVERTISED_10baseT_Full) {
6197c478bdstevel@tonic-gate		new_adv |= ADVERTISE_10FULL;
6207c478bdstevel@tonic-gate	}
6217c478bdstevel@tonic-gate	if (tp->link_config.advertising & ADVERTISED_100baseT_Half) {
6227c478bdstevel@tonic-gate		new_adv |= ADVERTISE_100HALF;
6237c478bdstevel@tonic-gate	}
6247c478bdstevel@tonic-gate	if (tp->link_config.advertising & ADVERTISED_100baseT_Full) {
6257c478bdstevel@tonic-gate		new_adv |= ADVERTISE_100FULL;
6267c478bdstevel@tonic-gate	}
6277c478bdstevel@tonic-gate	tg3_writephy(tp, MII_ADVERTISE, new_adv);
6287c478bdstevel@tonic-gate
6297c478bdstevel@tonic-gate	if (tp->link_config.advertising &
6307c478bdstevel@tonic-gate		(ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full)) {
6317c478bdstevel@tonic-gate		new_adv = 0;
6327c478bdstevel@tonic-gate		if (tp->link_config.advertising & ADVERTISED_1000baseT_Half) {
6337c478bdstevel@tonic-gate			new_adv |= MII_TG3_CTRL_ADV_1000_HALF;
6347c478bdstevel@tonic-gate		}
6357c478bdstevel@tonic-gate		if (tp->link_config.advertising & ADVERTISED_1000baseT_Full) {
6367c478bdstevel@tonic-gate			new_adv |= MII_TG3_CTRL_ADV_1000_FULL;
6377c478bdstevel@tonic-gate		}
6387c478bdstevel@tonic-gate		if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY) &&
6397c478bdstevel@tonic-gate			(tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 ||
6407c478bdstevel@tonic-gate				tp->pci_chip_rev_id == CHIPREV_ID_5701_B0)) {
6417c478bdstevel@tonic-gate			new_adv |= (MII_TG3_CTRL_AS_MASTER |
6427c478bdstevel@tonic-gate				MII_TG3_CTRL_ENABLE_AS_MASTER);
6437c478bdstevel@tonic-gate		}
6447c478bdstevel@tonic-gate		tg3_writephy(tp, MII_TG3_CTRL, new_adv);
6457c478bdstevel@tonic-gate	} else {
6467c478bdstevel@tonic-gate		tg3_writephy(tp, MII_TG3_CTRL, 0);
6477c478bdstevel@tonic-gate	}
6487c478bdstevel@tonic-gate
6497c478bdstevel@tonic-gate	tg3_writephy(tp, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART);
6507c478bdstevel@tonic-gate
6517c478bdstevel@tonic-gate	return 0;
6527c478bdstevel@tonic-gate}
6537c478bdstevel@tonic-gate
6547c478bdstevel@tonic-gatestatic int tg3_init_5401phy_dsp(struct tg3 *tp)
6557c478bdstevel@tonic-gate{
6567c478bdstevel@tonic-gate	int err;
6577c478bdstevel@tonic-gate
6587c478bdstevel@tonic-gate	/* Turn off tap power management. */
6597c478bdstevel@tonic-gate	err  = tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c20);
6607c478bdstevel@tonic-gate
6617c478bdstevel@tonic-gate	err |= tg3_writedsp(tp, 0x0012, 0x1804);
6627c478bdstevel@tonic-gate	err |= tg3_writedsp(tp, 0x0013, 0x1204);
6637c478bdstevel@tonic-gate	err |= tg3_writedsp(tp, 0x8006, 0x0132);
6647c478bdstevel@tonic-gate	err |= tg3_writedsp(tp, 0x8006, 0x0232);
6657c478bdstevel@tonic-gate	err |= tg3_writedsp(tp, 0x201f, 0x0a20);
6667c478bdstevel@tonic-gate
6677c478bdstevel@tonic-gate	udelay(40);
6687c478bdstevel@tonic-gate
6697c478bdstevel@tonic-gate	return err;
6707c478bdstevel@tonic-gate}
6717c478bdstevel@tonic-gate
6727c478bdstevel@tonic-gatestatic int tg3_setup_copper_phy(struct tg3 *tp)
6737c478bdstevel@tonic-gate{
6747c478bdstevel@tonic-gate	int current_link_up;
6757c478bdstevel@tonic-gate	uint32_t bmsr, dummy;
6767c478bdstevel@tonic-gate	int i, err;
6777c478bdstevel@tonic-gate
6787c478bdstevel@tonic-gate	tw32_carefully(MAC_STATUS,
6797c478bdstevel@tonic-gate		(MAC_STATUS_SYNC_CHANGED | MAC_STATUS_CFG_CHANGED));
6807c478bdstevel@tonic-gate
6817c478bdstevel@tonic-gate	tp->mi_mode = MAC_MI_MODE_BASE;
6827c478bdstevel@tonic-gate	tw32_carefully(MAC_MI_MODE, tp->mi_mode);
6837c478bdstevel@tonic-gate
6847c478bdstevel@tonic-gate	tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x02);
6857c478bdstevel@tonic-gate
6867c478bdstevel@tonic-gate	/* Some third-party PHYs need to be reset on link going
6877c478bdstevel@tonic-gate	 * down.
6887c478bdstevel@tonic-gate	 */
6897c478bdstevel@tonic-gate	if (	(	(GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703) ||
6907c478bdstevel@tonic-gate			(GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) ||
6917c478bdstevel@tonic-gate			(tp->pci_chip_rev_id == CHIPREV_ID_5705_A0)) &&
6927c478bdstevel@tonic-gate		(tp->carrier_ok)) {
6937c478bdstevel@tonic-gate		tg3_readphy(tp, MII_BMSR, &bmsr);
6947c478bdstevel@tonic-gate		tg3_readphy(tp, MII_BMSR, &bmsr);
6957c478bdstevel@tonic-gate		if (!(bmsr & BMSR_LSTATUS))
6967c478bdstevel@tonic-gate			tg3_phy_reset(tp);
6977c478bdstevel@tonic-gate	}
6987c478bdstevel@tonic-gate
6997c478bdstevel@tonic-gate	if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) {
7007c478bdstevel@tonic-gate		tg3_readphy(tp, MII_BMSR, &bmsr);
7017c478bdstevel@tonic-gate		tg3_readphy(tp, MII_BMSR, &bmsr);
7027c478bdstevel@tonic-gate
7037c478bdstevel@tonic-gate		if (!(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE))
7047c478bdstevel@tonic-gate			bmsr = 0;
7057c478bdstevel@tonic-gate
7067c478bdstevel@tonic-gate		if (!(bmsr & BMSR_LSTATUS)) {
7077c478bdstevel@tonic-gate			err = tg3_init_5401phy_dsp(tp);
7087c478bdstevel@tonic-gate			if (err)
7097c478bdstevel@tonic-gate				return err;
7107c478bdstevel@tonic-gate
7117c478bdstevel@tonic-gate			tg3_readphy(tp, MII_BMSR, &bmsr);
7127c478bdstevel@tonic-gate			for (i = 0; i < 1000; i++) {
7137c478bdstevel@tonic-gate				udelay(10);
7147c478bdstevel@tonic-gate				tg3_readphy(tp, MII_BMSR, &bmsr);
7157c478bdstevel@tonic-gate				if (bmsr & BMSR_LSTATUS) {
7167c478bdstevel@tonic-gate					udelay(40);
7177c478bdstevel@tonic-gate					break;
7187c478bdstevel@tonic-gate				}
7197c478bdstevel@tonic-gate			}
7207c478bdstevel@tonic-gate
7217c478bdstevel@tonic-gate			if ((tp->phy_id & PHY_ID_REV_MASK) == PHY_REV_BCM5401_B0 &&
7227c478bdstevel@tonic-gate			    !(bmsr & BMSR_LSTATUS) &&
7237c478bdstevel@tonic-gate			    tp->link_config.active_speed == SPEED_1000) {
7247c478bdstevel@tonic-gate				err = tg3_phy_reset(tp);
7257c478bdstevel@tonic-gate				if (!err)
7267c478bdstevel@tonic-gate					err = tg3_init_5401phy_dsp(tp);
7277c478bdstevel@tonic-gate				if (err)
7287c478bdstevel@tonic-gate					return err;
7297c478bdstevel@tonic-gate			}
7307c478bdstevel@tonic-gate		}
7317c478bdstevel@tonic-gate	} else if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 ||
7327c478bdstevel@tonic-gate		   tp->pci_chip_rev_id == CHIPREV_ID_5701_B0) {
7337c478bdstevel@tonic-gate		/* 5701 {A0,B0} CRC bug workaround */
7347c478bdstevel@tonic-gate		tg3_writephy(tp, 0x15, 0x0a75);
7357c478bdstevel@tonic-gate		tg3_writephy(tp, 0x1c, 0x8c68);
7367c478bdstevel@tonic-gate		tg3_writephy(tp, 0x1c, 0x8d68);
7377c478bdstevel@tonic-gate		tg3_writephy(tp, 0x1c, 0x8c68);
7387c478bdstevel@tonic-gate	}
7397c478bdstevel@tonic-gate
7407c478bdstevel@tonic-gate	/* Clear pending interrupts... */
7417c478bdstevel@tonic-gate	tg3_readphy(tp, MII_TG3_ISTAT, &dummy);
7427c478bdstevel@tonic-gate	tg3_readphy(tp, MII_TG3_ISTAT, &dummy);
7437c478bdstevel@tonic-gate
7447c478bdstevel@tonic-gate	tg3_writephy(tp, MII_TG3_IMASK, ~0);
7457c478bdstevel@tonic-gate
7467c478bdstevel@tonic-gate	if (tp->led_mode == led_mode_three_link)
7477c478bdstevel@tonic-gate		tg3_writephy(tp, MII_TG3_EXT_CTRL,
7487c478bdstevel@tonic-gate			     MII_TG3_EXT_CTRL_LNK3_LED_MODE);
7497c478bdstevel@tonic-gate	else
7507c478bdstevel@tonic-gate		tg3_writephy(tp, MII_TG3_EXT_CTRL, 0);
7517c478bdstevel@tonic-gate
7527c478bdstevel@tonic-gate	current_link_up = 0;
7537c478bdstevel@tonic-gate
7547c478bdstevel@tonic-gate	tg3_readphy(tp, MII_BMSR, &bmsr);
7557c478bdstevel@tonic-gate	tg3_readphy(tp, MII_BMSR, &bmsr);
7567c478bdstevel@tonic-gate
7577c478bdstevel@tonic-gate	if (bmsr & BMSR_LSTATUS) {
7587c478bdstevel@tonic-gate		uint32_t aux_stat, bmcr;
7597c478bdstevel@tonic-gate
7607c478bdstevel@tonic-gate		tg3_readphy(tp, MII_TG3_AUX_STAT, &aux_stat);
7617c478bdstevel@tonic-gate		for (i = 0; i < 2000; i++) {
7627c478bdstevel@tonic-gate			udelay(10);
7637c478bdstevel@tonic-gate			tg3_readphy(tp, MII_TG3_AUX_STAT, &aux_stat);
7647c478bdstevel@tonic-gate			if (aux_stat)
7657c478bdstevel@tonic-gate				break;
7667c478bdstevel@tonic-gate		}
7677c478bdstevel@tonic-gate
7687c478bdstevel@tonic-gate		tg3_aux_stat_to_speed_duplex(tp, aux_stat,
7697c478bdstevel@tonic-gate			&tp->link_config.active_speed,
7707c478bdstevel@tonic-gate			&tp->link_config.active_duplex);
7717c478bdstevel@tonic-gate		tg3_readphy(tp, MII_BMCR, &bmcr);
7727c478bdstevel@tonic-gate		tg3_readphy(tp, MII_BMCR, &bmcr);
7737c478bdstevel@tonic-gate		if (bmcr & BMCR_ANENABLE) {
7747c478bdstevel@tonic-gate			uint32_t gig_ctrl;
7757c478bdstevel@tonic-gate
7767c478bdstevel@tonic-gate			current_link_up = 1;
7777c478bdstevel@tonic-gate
7787c478bdstevel@tonic-gate			/* Force autoneg restart if we are exiting
7797c478bdstevel@tonic-gate			 * low power mode.
7807c478bdstevel@tonic-gate			 */
7817c478bdstevel@tonic-gate			tg3_readphy(tp, MII_TG3_CTRL, &gig_ctrl);
7827c478bdstevel@tonic-gate			if (!(gig_ctrl & (MII_TG3_CTRL_ADV_1000_HALF |
7837c478bdstevel@tonic-gate				      MII_TG3_CTRL_ADV_1000_FULL))) {
7847c478bdstevel@tonic-gate				current_link_up = 0;
7857c478bdstevel@tonic-gate			}
7867c478bdstevel@tonic-gate		} else {
7877c478bdstevel@tonic-gate			current_link_up = 0;
7887c478bdstevel@tonic-gate		}
7897c478bdstevel@tonic-gate	}
7907c478bdstevel@tonic-gate
7917c478bdstevel@tonic-gate	if (current_link_up == 1 &&
7927c478bdstevel@tonic-gate		(tp->link_config.active_duplex == DUPLEX_FULL)) {
7937c478bdstevel@tonic-gate		uint32_t local_adv, remote_adv;
7947c478bdstevel@tonic-gate
7957c478bdstevel@tonic-gate		tg3_readphy(tp, MII_ADVERTISE, &local_adv);
7967c478bdstevel@tonic-gate		local_adv &= (ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
7977c478bdstevel@tonic-gate
7987c478bdstevel@tonic-gate		tg3_readphy(tp, MII_LPA, &remote_adv);
7997c478bdstevel@tonic-gate		remote_adv &= (LPA_PAUSE_CAP | LPA_PAUSE_ASYM);
8007c478bdstevel@tonic-gate
8017c478bdstevel@tonic-gate		/* If we are not advertising full pause capability,
8027c478bdstevel@tonic-gate		 * something is wrong.  Bring the link down and reconfigure.
8037c478bdstevel@tonic-gate		 */
8047c478bdstevel@tonic-gate		if (local_adv != ADVERTISE_PAUSE_CAP) {
8057c478bdstevel@tonic-gate			current_link_up = 0;
8067c478bdstevel@tonic-gate		} else {
8077c478bdstevel@tonic-gate			tg3_setup_flow_control(tp, local_adv, remote_adv);
8087c478bdstevel@tonic-gate		}
8097c478bdstevel@tonic-gate	}
8107c478bdstevel@tonic-gate
8117c478bdstevel@tonic-gate	if (current_link_up == 0) {
8127c478bdstevel@tonic-gate		uint32_t tmp;
8137c478bdstevel@tonic-gate
8147c478bdstevel@tonic-gate		tg3_phy_copper_begin(tp);
8157c478bdstevel@tonic-gate
8167c478bdstevel@tonic-gate		tg3_readphy(tp, MII_BMSR, &tmp);
8177c478bdstevel@tonic-gate		tg3_readphy(tp, MII_BMSR, &tmp);
8187c478bdstevel@tonic-gate		if (tmp & BMSR_LSTATUS)
8197c478bdstevel@tonic-gate			current_link_up = 1;
8207c478bdstevel@tonic-gate	}
8217c478bdstevel@tonic-gate
8227c478bdstevel@tonic-gate	tp->mac_mode &= ~MAC_MODE_PORT_MODE_MASK;
8237c478bdstevel@tonic-gate	if (current_link_up == 1) {
8247c478bdstevel@tonic-gate		if (tp->link_config.active_speed == SPEED_100 ||
8257c478bdstevel@tonic-gate		    tp->link_config.active_speed == SPEED_10)
8267c478bdstevel@tonic-gate			tp->mac_mode |= MAC_MODE_PORT_MODE_MII;
8277c478bdstevel@tonic-gate		else
8287c478bdstevel@tonic-gate			tp->mac_mode |= MAC_MODE_PORT_MODE_GMII;
8297c478bdstevel@tonic-gate	} else
8307c478bdstevel@tonic-gate		tp->mac_mode |= MAC_MODE_PORT_MODE_GMII;
8317c478bdstevel@tonic-gate
8327c478bdstevel@tonic-gate	tp->mac_mode &= ~MAC_MODE_HALF_DUPLEX;
8337c478bdstevel@tonic-gate	if (tp->link_config.active_duplex == DUPLEX_HALF)
8347c478bdstevel@tonic-gate		tp->mac_mode |= MAC_MODE_HALF_DUPLEX;
8357c478bdstevel@tonic-gate
8367c478bdstevel@tonic-gate	tp->mac_mode &= ~MAC_MODE_LINK_POLARITY;
8377c478bdstevel@tonic-gate	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) {
8387c478bdstevel@tonic-gate		if ((tp->led_mode == led_mode_link10) ||
8397c478bdstevel@tonic-gate		    (current_link_up == 1 &&
8407c478bdstevel@tonic-gate		     tp->link_config.active_speed == SPEED_10))
8417c478bdstevel@tonic-gate			tp->mac_mode |= MAC_MODE_LINK_POLARITY;
8427c478bdstevel@tonic-gate	} else {
8437c478bdstevel@tonic-gate		if (current_link_up == 1)
8447c478bdstevel@tonic-gate			tp->mac_mode |= MAC_MODE_LINK_POLARITY;
8457c478bdstevel@tonic-gate		tw32(MAC_LED_CTRL, LED_CTRL_PHY_MODE_1);
8467c478bdstevel@tonic-gate	}
8477c478bdstevel@tonic-gate
8487c478bdstevel@tonic-gate	/* ??? Without this setting Netgear GA302T PHY does not
8497c478bdstevel@tonic-gate	 * ??? send/receive packets...
8507c478bdstevel@tonic-gate	 * With this other PHYs cannot bring up the link
8517c478bdstevel@tonic-gate	 */
8527c478bdstevel@tonic-gate	if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5411 &&
8537c478bdstevel@tonic-gate		tp->pci_chip_rev_id == CHIPREV_ID_5700_ALTIMA) {
8547c478bdstevel@tonic-gate		tp->mi_mode |= MAC_MI_MODE_AUTO_POLL;
8557c478bdstevel@tonic-gate		tw32_carefully(MAC_MI_MODE, tp->mi_mode);
8567c478bdstevel@tonic-gate	}
8577c478bdstevel@tonic-gate
8587c478bdstevel@tonic-gate	tw32_carefully(MAC_MODE, tp->mac_mode);
8597c478bdstevel@tonic-gate
8607c478bdstevel@tonic-gate	/* Link change polled. */
8617c478bdstevel@tonic-gate	tw32_carefully(MAC_EVENT, 0);
8627c478bdstevel@tonic-gate
8637c478bdstevel@tonic-gate	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 &&
8647c478bdstevel@tonic-gate	    current_link_up == 1 &&
8657c478bdstevel@tonic-gate	    tp->link_config.active_speed == SPEED_1000 &&
8667c478bdstevel@tonic-gate	    ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) ||
8677c478bdstevel@tonic-gate	     (tp->tg3_flags & TG3_FLAG_PCI_HIGH_SPEED))) {
8687c478bdstevel@tonic-gate		udelay(120);
8697c478bdstevel@tonic-gate		tw32_carefully(MAC_STATUS,
8707c478bdstevel@tonic-gate			(MAC_STATUS_SYNC_CHANGED | MAC_STATUS_CFG_CHANGED));
8717c478bdstevel@tonic-gate		tg3_write_mem(
8727c478bdstevel@tonic-gate			      NIC_SRAM_FIRMWARE_MBOX,
8737c478bdstevel@tonic-gate			      NIC_SRAM_FIRMWARE_MBOX_MAGIC2);
8747c478bdstevel@tonic-gate	}
8757c478bdstevel@tonic-gate
8767c478bdstevel@tonic-gate	if (current_link_up != tp->carrier_ok) {
8777c478bdstevel@tonic-gate		tp->carrier_ok = current_link_up;
8787c478bdstevel@tonic-gate		tg3_link_report(tp);
8797c478bdstevel@tonic-gate	}
8807c478bdstevel@tonic-gate
8817c478bdstevel@tonic-gate	return 0;
8827c478bdstevel@tonic-gate}
8837c478bdstevel@tonic-gate#else
8847c478bdstevel@tonic-gate#define tg3_setup_copper_phy(TP) (-EINVAL)
8857c478bdstevel@tonic-gate#endif /* SUPPORT_COPPER_PHY */
8867c478bdstevel@tonic-gate
8877c478bdstevel@tonic-gate#if SUPPORT_FIBER_PHY
8887c478bdstevel@tonic-gatestruct tg3_fiber_aneginfo {
8897c478bdstevel@tonic-gate	int state;
8907c478bdstevel@tonic-gate#define ANEG_STATE_UNKNOWN		0
8917c478bdstevel@tonic-gate#define ANEG_STATE_AN_ENABLE		1
8927c478bdstevel@tonic-gate#define ANEG_STATE_RESTART_INIT		2
8937c478bdstevel@tonic-gate#define ANEG_STATE_RESTART		3
8947c478bdstevel@tonic-gate#define ANEG_STATE_DISABLE_LINK_OK	4
8957c478bdstevel@tonic-gate#define ANEG_STATE_ABILITY_DETECT_INIT	5
8967c478bdstevel@tonic-gate#define ANEG_STATE_ABILITY_DETECT	6
8977c478bdstevel@tonic-gate#define ANEG_STATE_ACK_DETECT_INIT	7
8987c478bdstevel@tonic-gate#define ANEG_STATE_ACK_DETECT		8
8997c478bdstevel@tonic-gate#define ANEG_STATE_COMPLETE_ACK_INIT	9
9007c478bdstevel@tonic-gate#define ANEG_STATE_COMPLETE_ACK		10
9017c478bdstevel@tonic-gate#define ANEG_STATE_IDLE_DETECT_INIT	11
9027c478bdstevel@tonic-gate#define ANEG_STATE_IDLE_DETECT		12
9037c478bdstevel@tonic-gate#define ANEG_STATE_LINK_OK		13
9047c478bdstevel@tonic-gate#define ANEG_STATE_NEXT_PAGE_WAIT_INIT	14
9057c478bdstevel@tonic-gate#define ANEG_STATE_NEXT_PAGE_WAIT	15
9067c478bdstevel@tonic-gate
9077c478bdstevel@tonic-gate	uint32_t flags;
9087c478bdstevel@tonic-gate#define MR_AN_ENABLE		0x00000001
9097c478bdstevel@tonic-gate#define MR_RESTART_AN		0x00000002
9107c478bdstevel@tonic-gate#define MR_AN_COMPLETE		0x00000004
9117c478bdstevel@tonic-gate#define MR_PAGE_RX		0x00000008
9127c478bdstevel@tonic-gate#define MR_NP_LOADED		0x00000010
9137c478bdstevel@tonic-gate#define MR_TOGGLE_TX		0x00000020
9147c478bdstevel@tonic-gate#define MR_LP_ADV_FULL_DUPLEX	0x00000040
9157c478bdstevel@tonic-gate#define MR_LP_ADV_HALF_DUPLEX	0x00000080
9167c478bdstevel@tonic-gate#define MR_LP_ADV_SYM_PAUSE	0x00000100
9177c478bdstevel@tonic-gate#define MR_LP_ADV_ASYM_PAUSE	0x00000200
9187c478bdstevel@tonic-gate#define MR_LP_ADV_REMOTE_FAULT1	0x00000400
9197c478bdstevel@tonic-gate#define MR_LP_ADV_REMOTE_FAULT2	0x00000800
9207c478bdstevel@tonic-gate#define MR_LP_ADV_NEXT_PAGE	0x00001000
9217c478bdstevel@tonic-gate#define MR_TOGGLE_RX		0x00002000
9227c478bdstevel@tonic-gate#define MR_NP_RX		0x00004000
9237c478bdstevel@tonic-gate
9247c478bdstevel@tonic-gate#define MR_LINK_OK		0x80000000
9257c478bdstevel@tonic-gate
9267c478bdstevel@tonic-gate	unsigned long link_time, cur_time;
9277c478bdstevel@tonic-gate
9287c478bdstevel@tonic-gate	uint32_t ability_match_cfg;
9297c478bdstevel@tonic-gate	int ability_match_count;
9307c478bdstevel@tonic-gate
9317c478bdstevel@tonic-gate	char ability_match, idle_match, ack_match;
9327c478bdstevel@tonic-gate
9337c478bdstevel@tonic-gate	uint32_t txconfig, rxconfig;
9347c478bdstevel@tonic-gate#define ANEG_CFG_NP		0x00000080
9357c478bdstevel@tonic-gate#define ANEG_CFG_ACK		0x00000040
9367c478bdstevel@tonic-gate#define ANEG_CFG_RF2		0x00000020
9377c478bdstevel@tonic-gate#define ANEG_CFG_RF1		0x00000010
9387c478bdstevel@tonic-gate#define ANEG_CFG_PS2		0x00000001
9397c478bdstevel@tonic-gate#define ANEG_CFG_PS1		0x00008000
9407c478bdstevel@tonic-gate#define ANEG_CFG_HD		0x00004000
9417c478bdstevel@tonic-gate#define ANEG_CFG_FD		0x00002000
9427c478bdstevel@tonic-gate#define ANEG_CFG_INVAL		0x00001f06
9437c478bdstevel@tonic-gate
9447c478bdstevel@tonic-gate};
9457c478bdstevel@tonic-gate#define ANEG_OK		0
9467c478bdstevel@tonic-gate#define ANEG_DONE	1
9477c478bdstevel@tonic-gate#define ANEG_TIMER_ENAB	2
9487c478bdstevel@tonic-gate#define ANEG_FAILED	-1
9497c478bdstevel@tonic-gate
9507c478bdstevel@tonic-gate#define ANEG_STATE_SETTLE_TIME	10000
9517c478bdstevel@tonic-gate
9527c478bdstevel@tonic-gatestatic int tg3_fiber_aneg_smachine(struct tg3 *tp,
9537c478bdstevel@tonic-gate				   struct tg3_fiber_aneginfo *ap)
9547c478bdstevel@tonic-gate{
9557c478bdstevel@tonic-gate	unsigned long delta;
9567c478bdstevel@tonic-gate	uint32_t rx_cfg_reg;
9577c478bdstevel@tonic-gate	int ret;
9587c478bdstevel@tonic-gate
9597c478bdstevel@tonic-gate	if (ap->state == ANEG_STATE_UNKNOWN) {
9607c478bdstevel@tonic-gate		ap->rxconfig = 0;
9617c478bdstevel@tonic-gate		ap->link_time = 0;
9627c478bdstevel@tonic-gate		ap->cur_time = 0;
9637c478bdstevel@tonic-gate		ap->ability_match_cfg = 0;
9647c478bdstevel@tonic-gate		ap->ability_match_count = 0;
9657c478bdstevel@tonic-gate		ap->ability_match = 0;
9667c478bdstevel@tonic-gate		ap->idle_match = 0;
9677c478bdstevel@tonic-gate		ap->ack_match = 0;
9687c478bdstevel@tonic-gate	}
9697c478bdstevel@tonic-gate	ap->cur_time++;
9707c478bdstevel@tonic-gate
9717c478bdstevel@tonic-gate	if (tr32(MAC_STATUS) & MAC_STATUS_RCVD_CFG) {
9727c478bdstevel@tonic-gate		rx_cfg_reg = tr32(MAC_RX_AUTO_NEG);
9737c478bdstevel@tonic-gate
9747c478bdstevel@tonic-gate		if (rx_cfg_reg != ap->ability_match_cfg) {
9757c478bdstevel@tonic-gate			ap->ability_match_cfg = rx_cfg_reg;
9767c478bdstevel@tonic-gate			ap->ability_match = 0;
9777c478bdstevel@tonic-gate			ap->ability_match_count = 0;
9787c478bdstevel@tonic-gate		} else {
9797c478bdstevel@tonic-gate			if (++ap->ability_match_count > 1) {
9807c478bdstevel@tonic-gate				ap->ability_match = 1;
9817c478bdstevel@tonic-gate				ap->ability_match_cfg = rx_cfg_reg;
9827c478bdstevel@tonic-gate			}
9837c478bdstevel@tonic-gate		}
9847c478bdstevel@tonic-gate		if (rx_cfg_reg & ANEG_CFG_ACK)
9857c478bdstevel@tonic-gate			ap->ack_match = 1;
9867c478bdstevel@tonic-gate		else
9877c478bdstevel@tonic-gate			ap->ack_match = 0;
9887c478bdstevel@tonic-gate
9897c478bdstevel@tonic-gate		ap->idle_match = 0;
9907c478bdstevel@tonic-gate	} else {
9917c478bdstevel@tonic-gate		ap->idle_match = 1;
9927c478bdstevel@tonic-gate		ap->ability_match_cfg = 0;
9937c478bdstevel@tonic-gate		ap->ability_match_count = 0;
9947c478bdstevel@tonic-gate		ap->ability_match = 0;
9957c478bdstevel@tonic-gate		ap->ack_match = 0;
9967c478bdstevel@tonic-gate
9977c478bdstevel@tonic-gate		rx_cfg_reg = 0;
9987c478bdstevel@tonic-gate	}
9997c478bdstevel@tonic-gate
10007c478bdstevel@tonic-gate	ap->rxconfig = rx_cfg_reg;
10017c478bdstevel@tonic-gate	ret = ANEG_OK;
10027c478bdstevel@tonic-gate
10037c478bdstevel@tonic-gate	switch(ap->state) {
10047c478bdstevel@tonic-gate	case ANEG_STATE_UNKNOWN:
10057c478bdstevel@tonic-gate		if (ap->flags & (MR_AN_ENABLE | MR_RESTART_AN))
10067c478bdstevel@tonic-gate			ap->state = ANEG_STATE_AN_ENABLE;
10077c478bdstevel@tonic-gate
10087c478bdstevel@tonic-gate		/* fallthru */
10097c478bdstevel@tonic-gate	case ANEG_STATE_AN_ENABLE:
10107c478bdstevel@tonic-gate		ap->flags &= ~(MR_AN_COMPLETE | MR_PAGE_RX);
10117c478bdstevel@tonic-gate		if (ap->flags & MR_AN_ENABLE) {
10127c478bdstevel@tonic-gate			ap->link_time = 0;
10137c478bdstevel@tonic-gate			ap->cur_time = 0;
10147c478bdstevel@tonic-gate			ap->ability_match_cfg = 0;
10157c478bdstevel@tonic-gate			ap->ability_match_count = 0;
10167c478bdstevel@tonic-gate			ap->ability_match = 0;
10177c478bdstevel@tonic-gate			ap->idle_match = 0;
10187c478bdstevel@tonic-gate			ap->ack_match = 0;
10197c478bdstevel@tonic-gate
10207c478bdstevel@tonic-gate			ap->state = ANEG_STATE_RESTART_INIT;
10217c478bdstevel@tonic-gate		} else {
10227c478bdstevel@tonic-gate			ap->state = ANEG_STATE_DISABLE_LINK_OK;
10237c478bdstevel@tonic-gate		}
10247c478bdstevel@tonic-gate		break;
10257c478bdstevel@tonic-gate
10267c478bdstevel@tonic-gate	case ANEG_STATE_RESTART_INIT:
10277c478bdstevel@tonic-gate		ap->link_time = ap->cur_time;
10287c478bdstevel@tonic-gate		ap->flags &= ~(MR_NP_LOADED);
10297c478bdstevel@tonic-gate		ap->txconfig = 0;
10307c478bdstevel@tonic-gate		tw32(MAC_TX_AUTO_NEG, 0);
10317c478bdstevel@tonic-gate		tp->mac_mode |= MAC_MODE_SEND_CONFIGS;
10327c478bdstevel@tonic-gate		tw32_carefully(MAC_MODE, tp->mac_mode);
10337c478bdstevel@tonic-gate
10347c478bdstevel@tonic-gate		ret = ANEG_TIMER_ENAB;
10357c478bdstevel@tonic-gate		ap->state = ANEG_STATE_RESTART;
10367c478bdstevel@tonic-gate
10377c478bdstevel@tonic-gate		/* fallthru */
10387c478bdstevel@tonic-gate	case ANEG_STATE_RESTART:
10397c478bdstevel@tonic-gate		delta = ap->cur_time - ap->link_time;
10407c478bdstevel@tonic-gate		if (delta > ANEG_STATE_SETTLE_TIME) {
10417c478bdstevel@tonic-gate			ap->state = ANEG_STATE_ABILITY_DETECT_INIT;
10427c478bdstevel@tonic-gate		} else {
10437c478bdstevel@tonic-gate			ret = ANEG_TIMER_ENAB;
10447c478bdstevel@tonic-gate		}
10457c478bdstevel@tonic-gate		break;
10467c478bdstevel@tonic-gate
10477c478bdstevel@tonic-gate	case ANEG_STATE_DISABLE_LINK_OK:
10487c478bdstevel@tonic-gate		ret = ANEG_DONE;
10497c478bdstevel@tonic-gate		break;
10507c478bdstevel@tonic-gate
10517c478bdstevel@tonic-gate	case ANEG_STATE_ABILITY_DETECT_INIT:
10527c478bdstevel@tonic-gate		ap->flags &= ~(MR_TOGGLE_TX);
10537c478bdstevel@tonic-gate		ap->txconfig = (ANEG_CFG_FD | ANEG_CFG_PS1);
10547c478bdstevel@tonic-gate		tw32(MAC_TX_AUTO_NEG, ap->txconfig);
10557c478bdstevel@tonic-gate		tp->mac_mode |= MAC_MODE_SEND_CONFIGS;
10567c478bdstevel@tonic-gate		tw32_carefully(MAC_MODE, tp->mac_mode);
10577c478bdstevel@tonic-gate
10587c478bdstevel@tonic-gate		ap->state = ANEG_STATE_ABILITY_DETECT;
10597c478bdstevel@tonic-gate		break;
10607c478bdstevel@tonic-gate
10617c478bdstevel@tonic-gate	case ANEG_STATE_ABILITY_DETECT:
10627c478bdstevel@tonic-gate		if (ap->ability_match != 0 && ap->rxconfig != 0) {
10637c478bdstevel@tonic-gate			ap->state = ANEG_STATE_ACK_DETECT_INIT;
10647c478bdstevel@tonic-gate		}
10657c478bdstevel@tonic-gate		break;
10667c478bdstevel@tonic-gate
10677c478bdstevel@tonic-gate	case ANEG_STATE_ACK_DETECT_INIT:
10687c478bdstevel@tonic-gate		ap->txconfig |= ANEG_CFG_ACK;
10697c478bdstevel@tonic-gate		tw32(MAC_TX_AUTO_NEG, ap->txconfig);
10707c478bdstevel@tonic-gate		tp->mac_mode |= MAC_MODE_SEND_CONFIGS;
10717c478bdstevel@tonic-gate		tw32_carefully(MAC_MODE, tp->mac_mode);
10727c478bdstevel@tonic-gate
10737c478bdstevel@tonic-gate		ap->state = ANEG_STATE_ACK_DETECT;
10747c478bdstevel@tonic-gate
10757c478bdstevel@tonic-gate		/* fallthru */
10767c478bdstevel@tonic-gate	case ANEG_STATE_ACK_DETECT:
10777c478bdstevel@tonic-gate		if (ap->ack_match != 0) {
10787c478bdstevel@tonic-gate			if ((ap->rxconfig & ~ANEG_CFG_ACK) ==
10797c478bdstevel@tonic-gate			    (ap->ability_match_cfg & ~ANEG_CFG_ACK)) {
10807c478bdstevel@tonic-gate				ap->state = ANEG_STATE_COMPLETE_ACK_INIT;
10817c478bdstevel@tonic-gate			} else {
10827c478bdstevel@tonic-gate				ap->state = ANEG_STATE_AN_ENABLE;
10837c478bdstevel@tonic-gate			}
10847c478bdstevel@tonic-gate		} else if (ap->ability_match != 0 &&
10857c478bdstevel@tonic-gate			   ap->rxconfig == 0) {
10867c478bdstevel@tonic-gate			ap->state = ANEG_STATE_AN_ENABLE;
10877c478bdstevel@tonic-gate		}
10887c478bdstevel@tonic-gate		break;
10897c478bdstevel@tonic-gate
10907c478bdstevel@tonic-gate	case ANEG_STATE_COMPLETE_ACK_INIT:
10917c478bdstevel@tonic-gate		if (ap->rxconfig & ANEG_CFG_INVAL) {
10927c478bdstevel@tonic-gate			ret = ANEG_FAILED;
10937c478bdstevel@tonic-gate			break;
10947c478bdstevel@tonic-gate		}
10957c478bdstevel@tonic-gate		ap->flags &= ~(MR_LP_ADV_FULL_DUPLEX |
10967c478bdstevel@tonic-gate			       MR_LP_ADV_HALF_DUPLEX |
10977c478bdstevel@tonic-gate			       MR_LP_ADV_SYM_PAUSE |
10987c478bdstevel@tonic-gate			       MR_LP_ADV_ASYM_PAUSE |
10997c478bdstevel@tonic-gate			       MR_LP_ADV_REMOTE_FAULT1 |
11007c478bdstevel@tonic-gate			       MR_LP_ADV_REMOTE_FAULT2 |
11017c478bdstevel@tonic-gate			       MR_LP_ADV_NEXT_PAGE |
11027c478bdstevel@tonic-gate			       MR_TOGGLE_RX |
11037c478bdstevel@tonic-gate			       MR_NP_RX);
11047c478bdstevel@tonic-gate		if (ap->rxconfig & ANEG_CFG_FD)
11057c478bdstevel@tonic-gate			ap->flags |= MR_LP_ADV_FULL_DUPLEX;
11067c478bdstevel@tonic-gate		if (ap->rxconfig & ANEG_CFG_HD)
11077c478bdstevel@tonic-gate			ap->flags |= MR_LP_ADV_HALF_DUPLEX;
11087c478bdstevel@tonic-gate		if (ap->rxconfig & ANEG_CFG_PS1)
11097c478bdstevel@tonic-gate			ap->flags |= MR_LP_ADV_SYM_PAUSE;
11107c478bdstevel@tonic-gate		if (ap->rxconfig & ANEG_CFG_PS2)
11117c478bdstevel@tonic-gate			ap->flags |= MR_LP_ADV_ASYM_PAUSE;
11127c478bdstevel@tonic-gate		if (ap->rxconfig & ANEG_CFG_RF1)
11137c478bdstevel@tonic-gate			ap->flags |= MR_LP_ADV_REMOTE_FAULT1;
11147c478bdstevel@tonic-gate		if (ap->rxconfig & ANEG_CFG_RF2)
11157c478bdstevel@tonic-gate			ap->flags |= MR_LP_ADV_REMOTE_FAULT2;
11167c478bdstevel@tonic-gate		if (ap->rxconfig & ANEG_CFG_NP)
11177c478bdstevel@tonic-gate			ap->flags |= MR_LP_ADV_NEXT_PAGE;
11187c478bdstevel@tonic-gate
11197c478bdstevel@tonic-gate		ap->link_time = ap->cur_time;
11207c478bdstevel@tonic-gate
11217c478bdstevel@tonic-gate		ap->flags ^= (MR_TOGGLE_TX);
11227c478bdstevel@tonic-gate		if (ap->rxconfig & 0x0008)
11237c478bdstevel@tonic-gate			ap->flags |= MR_TOGGLE_RX;
11247c478bdstevel@tonic-gate		if (ap->rxconfig & ANEG_CFG_NP)
11257c478bdstevel@tonic-gate			ap->flags |= MR_NP_RX;
11267c478bdstevel@tonic-gate		ap->flags |= MR_PAGE_RX;
11277c478bdstevel@tonic-gate
11287c478bdstevel@tonic-gate		ap->state = ANEG_STATE_COMPLETE_ACK;
11297c478bdstevel@tonic-gate		ret = ANEG_TIMER_ENAB;
11307c478bdstevel@tonic-gate		break;
11317c478bdstevel@tonic-gate
11327c478bdstevel@tonic-gate	case ANEG_STATE_COMPLETE_ACK:
11337c478bdstevel@tonic-gate		if (ap->ability_match != 0 &&
11347c478bdstevel@tonic-gate		    ap->rxconfig == 0) {
11357c478bdstevel@tonic-gate			ap->state = ANEG_STATE_AN_ENABLE;
11367c478bdstevel@tonic-gate			break;
11377c478bdstevel@tonic-gate		}
11387c478bdstevel@tonic-gate		delta = ap->cur_time - ap->link_time;
11397c478bdstevel@tonic-gate		if (delta > ANEG_STATE_SETTLE_TIME) {
11407c478bdstevel@tonic-gate			if (!(ap->flags & (MR_LP_ADV_NEXT_PAGE))) {
11417c478bdstevel@tonic-gate				ap->state = ANEG_STATE_IDLE_DETECT_INIT;
11427c478bdstevel@tonic-gate			} else {
11437c478bdstevel@tonic-gate				if ((ap->txconfig & ANEG_CFG_NP) == 0 &&
11447c478bdstevel@tonic-gate				    !(ap->flags & MR_NP_RX)) {
11457c478bdstevel@tonic-gate					ap->state = ANEG_STATE_IDLE_DETECT_INIT;
11467c478bdstevel@tonic-gate				} else {
11477c478bdstevel@tonic-gate					ret = ANEG_FAILED;
11487c478bdstevel@tonic-gate				}
11497c478bdstevel@tonic-gate			}
11507c478bdstevel@tonic-gate		}
11517c478bdstevel@tonic-gate		break;
11527c478bdstevel@tonic-gate
11537c478bdstevel@tonic-gate	case ANEG_STATE_IDLE_DETECT_INIT:
11547c478bdstevel@tonic-gate		ap->link_time = ap->cur_time;
11557c478bdstevel@tonic-gate		tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS;
11567c478bdstevel@tonic-gate		tw32_carefully(MAC_MODE, tp->mac_mode);
11577c478bdstevel@tonic-gate
11587c478bdstevel@tonic-gate		ap->state = ANEG_STATE_IDLE_DETECT;
11597c478bdstevel@tonic-gate		ret = ANEG_TIMER_ENAB;
11607c478bdstevel@tonic-gate		break;
11617c478bdstevel@tonic-gate
11627c478bdstevel@tonic-gate	case ANEG_STATE_IDLE_DETECT:
11637c478bdstevel@tonic-gate		if (ap->ability_match != 0 &&
11647c478bdstevel@tonic-gate		    ap->rxconfig == 0) {
11657c478bdstevel@tonic-gate			ap->state = ANEG_STATE_AN_ENABLE;
11667c478bdstevel@tonic-gate			break;
11677c478bdstevel@tonic-gate		}
11687c478bdstevel@tonic-gate		delta = ap->cur_time - ap->link_time;
11697c478bdstevel@tonic-gate		if (delta > ANEG_STATE_SETTLE_TIME) {
11707c478bdstevel@tonic-gate			/* XXX another gem from the Broadcom driver :( */
11717c478bdstevel@tonic-gate			ap->state = ANEG_STATE_LINK_OK;
11727c478bdstevel@tonic-gate		}
11737c478bdstevel@tonic-gate		break;
11747c478bdstevel@tonic-gate
11757c478bdstevel@tonic-gate	case ANEG_STATE_LINK_OK:
11767c478bdstevel@tonic-gate		ap->flags |= (MR_AN_COMPLETE | MR_LINK_OK);
11777c478bdstevel@tonic-gate		ret = ANEG_DONE;
11787c478bdstevel@tonic-gate		break;
11797c478bdstevel@tonic-gate
11807c478bdstevel@tonic-gate	case ANEG_STATE_NEXT_PAGE_WAIT_INIT:
11817c478bdstevel@tonic-gate		/* ??? unimplemented */
11827c478bdstevel@tonic-gate		break;
11837c478bdstevel@tonic-gate
11847c478bdstevel@tonic-gate	case ANEG_STATE_NEXT_PAGE_WAIT:
11857c478bdstevel@tonic-gate		/* ??? unimplemented */
11867c478bdstevel@tonic-gate		break;
11877c478bdstevel@tonic-gate
11887c478bdstevel@tonic-gate	default:
11897c478bdstevel@tonic-gate		ret = ANEG_FAILED;
11907c478bdstevel@tonic-gate		break;
11917c478bdstevel@tonic-gate	};
11927c478bdstevel@tonic-gate
11937c478bdstevel@tonic-gate	return ret;
11947c478bdstevel@tonic-gate}
11957c478bdstevel@tonic-gate
11967c478bdstevel@tonic-gatestatic int tg3_setup_fiber_phy(struct tg3 *tp)
11977c478bdstevel@tonic-gate{
11987c478bdstevel@tonic-gate	uint32_t orig_pause_cfg;
11997c478bdstevel@tonic-gate	uint16_t orig_active_speed;
12007c478bdstevel@tonic-gate	uint8_t orig_active_duplex;
12017c478bdstevel@tonic-gate	int current_link_up;
12027c478bdstevel@tonic-gate	int i;
12037c478bdstevel@tonic-gate
12047c478bdstevel@tonic-gate	orig_pause_cfg =
12057c478bdstevel@tonic-gate		(tp->tg3_flags & (TG3_FLAG_RX_PAUSE |
12067c478bdstevel@tonic-gate				  TG3_FLAG_TX_PAUSE));
12077c478bdstevel@tonic-gate	orig_active_speed = tp->link_config.active_speed;
12087c478bdstevel@tonic-gate	orig_active_duplex = tp->link_config.active_duplex;
12097c478bdstevel@tonic-gate
12107c478bdstevel@tonic-gate	tp->mac_mode &= ~(MAC_MODE_PORT_MODE_MASK | MAC_MODE_HALF_DUPLEX);
12117c478bdstevel@tonic-gate	tp->mac_mode |= MAC_MODE_PORT_MODE_TBI;
12127c478bdstevel@tonic-gate	tw32_carefully(MAC_MODE, tp->mac_mode);
12137c478bdstevel@tonic-gate
12147c478bdstevel@tonic-gate	/* Reset when initting first time or we have a link. */
12157c478bdstevel@tonic-gate	if (!(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) ||
12167c478bdstevel@tonic-gate	    (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED)) {
12177c478bdstevel@tonic-gate		/* Set PLL lock range. */
12187c478bdstevel@tonic-gate		tg3_writephy(tp, 0x16, 0x8007);
12197c478bdstevel@tonic-gate
12207c478bdstevel@tonic-gate		/* SW reset */
12217c478bdstevel@tonic-gate		tg3_writephy(tp, MII_BMCR, BMCR_RESET);
12227c478bdstevel@tonic-gate
12237c478bdstevel@tonic-gate		/* Wait for reset to complete. */
12247c478bdstevel@tonic-gate		mdelay(5);
12257c478bdstevel@tonic-gate
12267c478bdstevel@tonic-gate		/* Config mode; select PMA/Ch 1 regs. */
12277c478bdstevel@tonic-gate		tg3_writephy(tp, 0x10, 0x8411);
12287c478bdstevel@tonic-gate
12297c478bdstevel@tonic-gate		/* Enable auto-lock and comdet, select txclk for tx. */
12307c478bdstevel@tonic-gate		tg3_writephy(tp, 0x11, 0x0a10);
12317c478bdstevel@tonic-gate
12327c478bdstevel@tonic-gate		tg3_writephy(tp, 0x18, 0x00a0);
12337c478bdstevel@tonic-gate		tg3_writephy(tp, 0x16, 0x41ff);
12347c478bdstevel@tonic-gate
12357c478bdstevel@tonic-gate		/* Assert and deassert POR. */
12367c478bdstevel@tonic-gate		tg3_writephy(tp, 0x13, 0x0400);
12377c478bdstevel@tonic-gate		udelay(40);
12387c478bdstevel@tonic-gate		tg3_writephy(tp, 0x13, 0x0000);
12397c478bdstevel@tonic-gate
12407c478bdstevel@tonic-gate		tg3_writephy(tp, 0x11, 0x0a50);
12417c478bdstevel@tonic-gate		udelay(40);
12427c478bdstevel@tonic-gate		tg3_writephy(tp, 0x11, 0x0a10);
12437c478bdstevel@tonic-gate
12447c478bdstevel@tonic-gate		/* Wait for signal to stabilize */
12457c478bdstevel@tonic-gate		mdelay(150);
12467c478bdstevel@tonic-gate
12477c478bdstevel@tonic-gate		/* Deselect the channel register so we can read the PHYID
12487c478bdstevel@tonic-gate		 * later.
12497c478bdstevel@tonic-gate		 */
12507c478bdstevel@tonic-gate		tg3_writephy(tp, 0x10, 0x8011);
12517c478bdstevel@tonic-gate	}
12527c478bdstevel@tonic-gate
12537c478bdstevel@tonic-gate	/* Disable link change interrupt.  */
12547c478bdstevel@tonic-gate	tw32_carefully(MAC_EVENT, 0);
12557c478bdstevel@tonic-gate
12567c478bdstevel@tonic-gate	current_link_up = 0;
12577c478bdstevel@tonic-gate	if (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) {
12587c478bdstevel@tonic-gate		if (!(tp->tg3_flags & TG3_FLAG_GOT_SERDES_FLOWCTL)) {
12597c478bdstevel@tonic-gate			struct tg3_fiber_aneginfo aninfo;
12607c478bdstevel@tonic-gate			int status = ANEG_FAILED;
12617c478bdstevel@tonic-gate			unsigned int tick;
12627c478bdstevel@tonic-gate			uint32_t tmp;
12637c478bdstevel@tonic-gate
12647c478bdstevel@tonic-gate			memset(&aninfo, 0, sizeof(aninfo));
12657c478bdstevel@tonic-gate			aninfo.flags |= (MR_AN_ENABLE);
12667c478bdstevel@tonic-gate
12677c478bdstevel@tonic-gate			tw32(MAC_TX_AUTO_NEG, 0);
12687c478bdstevel@tonic-gate
12697c478bdstevel@tonic-gate			tmp = tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK;
12707c478bdstevel@tonic-gate			tw32_carefully(MAC_MODE, tmp | MAC_MODE_PORT_MODE_GMII);
12717c478bdstevel@tonic-gate
12727c478bdstevel@tonic-gate			tw32_carefully(MAC_MODE, tp->mac_mode | MAC_MODE_SEND_CONFIGS);
12737c478bdstevel@tonic-gate
12747c478bdstevel@tonic-gate			aninfo.state = ANEG_STATE_UNKNOWN;
12757c478bdstevel@tonic-gate			aninfo.cur_time = 0;
12767c478bdstevel@tonic-gate			tick = 0;
12777c478bdstevel@tonic-gate			while (++tick < 195000) {
12787c478bdstevel@tonic-gate				status = tg3_fiber_aneg_smachine(tp, &aninfo);
12797c478bdstevel@tonic-gate				if (status == ANEG_DONE ||
12807c478bdstevel@tonic-gate				    status == ANEG_FAILED)
12817c478bdstevel@tonic-gate					break;
12827c478bdstevel@tonic-gate
12837c478bdstevel@tonic-gate				udelay(1);
12847c478bdstevel@tonic-gate			}
12857c478bdstevel@tonic-gate
12867c478bdstevel@tonic-gate			tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS;
12877c478bdstevel@tonic-gate			tw32_carefully(MAC_MODE, tp->mac_mode);
12887c478bdstevel@tonic-gate
12897c478bdstevel@tonic-gate			if (status == ANEG_DONE &&
12907c478bdstevel@tonic-gate			    (aninfo.flags &
12917c478bdstevel@tonic-gate			     (MR_AN_COMPLETE | MR_LINK_OK |
12927c478bdstevel@tonic-gate			      MR_LP_ADV_FULL_DUPLEX))) {
12937c478bdstevel@tonic-gate				uint32_t local_adv, remote_adv;
12947c478bdstevel@tonic-gate
12957c478bdstevel@tonic-gate				local_adv = ADVERTISE_PAUSE_CAP;
12967c478bdstevel@tonic-gate				remote_adv = 0;
12977c478bdstevel@tonic-gate				if (aninfo.flags & MR_LP_ADV_SYM_PAUSE)
12987c478bdstevel@tonic-gate					remote_adv |= LPA_PAUSE_CAP;
12997c478bdstevel@tonic-gate				if (aninfo.flags & MR_LP_ADV_ASYM_PAUSE)
13007c478bdstevel@tonic-gate					remote_adv |= LPA_PAUSE_ASYM;
13017c478bdstevel@tonic-gate
13027c478bdstevel@tonic-gate				tg3_setup_flow_control(tp, local_adv, remote_adv);
13037c478bdstevel@tonic-gate
13047c478bdstevel@tonic-gate				tp->tg3_flags |=
13057c478bdstevel@tonic-gate					TG3_FLAG_GOT_SERDES_FLOWCTL;
13067c478bdstevel@tonic-gate				current_link_up = 1;
13077c478bdstevel@tonic-gate			}
13087c478bdstevel@tonic-gate			for (i = 0; i < 60; i++) {
13097c478bdstevel@tonic-gate				udelay(20);
13107c478bdstevel@tonic-gate				tw32_carefully(MAC_STATUS,
13117c478bdstevel@tonic-gate					(MAC_STATUS_SYNC_CHANGED | MAC_STATUS_CFG_CHANGED));
13127c478bdstevel@tonic-gate				if ((tr32(MAC_STATUS) &
13137c478bdstevel@tonic-gate				     (MAC_STATUS_SYNC_CHANGED |
13147c478bdstevel@tonic-gate				      MAC_STATUS_CFG_CHANGED)) == 0)
13157c478bdstevel@tonic-gate					break;
13167c478bdstevel@tonic-gate			}
13177c478bdstevel@tonic-gate			if (current_link_up == 0 &&
13187c478bdstevel@tonic-gate			    (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED)) {
13197c478bdstevel@tonic-gate				current_link_up = 1;
13207c478bdstevel@tonic-gate			}
13217c478bdstevel@tonic-gate		} else {
13227c478bdstevel@tonic-gate			/* Forcing 1000FD link up. */
13237c478bdstevel@tonic-gate			current_link_up = 1;
13247c478bdstevel@tonic-gate		}
13257c478bdstevel@tonic-gate	}
13267c478bdstevel@tonic-gate
13277c478bdstevel@tonic-gate	tp->mac_mode &= ~MAC_MODE_LINK_POLARITY;
13287c478bdstevel@tonic-gate	tw32_carefully(MAC_MODE, tp->mac_mode);
13297c478bdstevel@tonic-gate
13307c478bdstevel@tonic-gate	tp->hw_status->status =
13317c478bdstevel@tonic-gate		(SD_STATUS_UPDATED |
13327c478bdstevel@tonic-gate		 (tp->hw_status->status & ~SD_STATUS_LINK_CHG));
13337c478bdstevel@tonic-gate
13347c478bdstevel@tonic-gate	for (i = 0; i < 100; i++) {
13357c478bdstevel@tonic-gate		udelay(20);
13367c478bdstevel@tonic-gate		tw32_carefully(MAC_STATUS,
13377c478bdstevel@tonic-gate			(MAC_STATUS_SYNC_CHANGED | MAC_STATUS_CFG_CHANGED));
13387c478bdstevel@tonic-gate		if ((tr32(MAC_STATUS) &
13397c478bdstevel@tonic-gate		     (MAC_STATUS_SYNC_CHANGED |
13407c478bdstevel@tonic-gate		      MAC_STATUS_CFG_CHANGED)) == 0)
13417c478bdstevel@tonic-gate			break;
13427c478bdstevel@tonic-gate	}
13437c478bdstevel@tonic-gate
13447c478bdstevel@tonic-gate	if ((tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) == 0)
13457c478bdstevel@tonic-gate		current_link_up = 0;
13467c478bdstevel@tonic-gate
13477c478bdstevel@tonic-gate	if (current_link_up == 1) {
13487c478bdstevel@tonic-gate		tp->link_config.active_speed = SPEED_1000;
13497c478bdstevel@tonic-gate		tp->link_config.active_duplex = DUPLEX_FULL;
13507c478bdstevel@tonic-gate	} else {
13517c478bdstevel@tonic-gate		tp->link_config.active_speed = SPEED_INVALID;
13527c478bdstevel@tonic-gate		tp->link_config.active_duplex = DUPLEX_INVALID;
13537c478bdstevel@tonic-gate	}
13547c478bdstevel@tonic-gate
13557c478bdstevel@tonic-gate	if (current_link_up != tp->carrier_ok) {
13567c478bdstevel@tonic-gate		tp->carrier_ok = current_link_up;
13577c478bdstevel@tonic-gate		tg3_link_report(tp);
13587c478bdstevel@tonic-gate	} else {
13597c478bdstevel@tonic-gate		uint32_t now_pause_cfg =
13607c478bdstevel@tonic-gate			tp->tg3_flags & (TG3_FLAG_RX_PAUSE |
13617c478bdstevel@tonic-gate					 TG3_FLAG_TX_PAUSE);
13627c478bdstevel@tonic-gate		if (orig_pause_cfg != now_pause_cfg ||
13637c478bdstevel@tonic-gate		    orig_active_speed != tp->link_config.active_speed ||
13647c478bdstevel@tonic-gate		    orig_active_duplex != tp->link_config.active_duplex)
13657c478bdstevel@tonic-gate			tg3_link_report(tp);
13667c478bdstevel@tonic-gate	}
13677c478bdstevel@tonic-gate
13687c478bdstevel@tonic-gate	if ((tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) == 0) {
13697c478bdstevel@tonic-gate		tw32_carefully(MAC_MODE, tp->mac_mode | MAC_MODE_LINK_POLARITY);
13707c478bdstevel@tonic-gate		if (tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) {
13717c478bdstevel@tonic-gate			tw32_carefully(MAC_MODE, tp->mac_mode);
13727c478bdstevel@tonic-gate		}
13737c478bdstevel@tonic-gate	}
13747c478bdstevel@tonic-gate
13757c478bdstevel@tonic-gate	return 0;
13767c478bdstevel@tonic-gate}
13777c478bdstevel@tonic-gate#else
13787c478bdstevel@tonic-gate#define tg3_setup_fiber_phy(TP) (-EINVAL)
13797c478bdstevel@tonic-gate#endif /* SUPPORT_FIBER_PHY */
13807c478bdstevel@tonic-gate
13817c478bdstevel@tonic-gatestatic int tg3_setup_phy(struct tg3 *tp)
13827c478bdstevel@tonic-gate{
13837c478bdstevel@tonic-gate	int err;
13847c478bdstevel@tonic-gate
13857c478bdstevel@tonic-gate	if (tp->phy_id == PHY_ID_SERDES) {
13867c478bdstevel@tonic-gate		err = tg3_setup_fiber_phy(tp);
13877c478bdstevel@tonic-gate	} else {
13887c478bdstevel@tonic-gate		err = tg3_setup_copper_phy(tp);
13897c478bdstevel@tonic-gate	}
13907c478bdstevel@tonic-gate
13917c478bdstevel@tonic-gate	if (tp->link_config.active_speed == SPEED_1000 &&
13927c478bdstevel@tonic-gate	    tp->link_config.active_duplex == DUPLEX_HALF)
13937c478bdstevel@tonic-gate		tw32(MAC_TX_LENGTHS,
13947c478bdstevel@tonic-gate		     ((2 << TX_LENGTHS_IPG_CRS_SHIFT) |
13957c478bdstevel@tonic-gate		      (6 << TX_LENGTHS_IPG_SHIFT) |
13967c478bdstevel@tonic-gate		      (0xff << TX_LENGTHS_SLOT_TIME_SHIFT)));
13977c478bdstevel@tonic-gate	else
13987c478bdstevel@tonic-gate		tw32(MAC_TX_LENGTHS,
13997c478bdstevel@tonic-gate		     ((2 << TX_LENGTHS_IPG_CRS_SHIFT) |
14007c478bdstevel@tonic-gate		      (6 << TX_LENGTHS_IPG_SHIFT) |
14017c478bdstevel@tonic-gate		      (32 << TX_LENGTHS_SLOT_TIME_SHIFT)));
14027c478bdstevel@tonic-gate
14037c478bdstevel@tonic-gate	return err;
14047c478bdstevel@tonic-gate}
14057c478bdstevel@tonic-gate
14067c478bdstevel@tonic-gate
14077c478bdstevel@tonic-gate#define MAX_WAIT_CNT 1000
14087c478bdstevel@tonic-gate
14097c478bdstevel@tonic-gate/* To stop a block, clear the enable bit and poll till it
14107c478bdstevel@tonic-gate * clears.
14117c478bdstevel@tonic-gate */
14127c478bdstevel@tonic-gatestatic int tg3_stop_block(struct tg3 *tp, unsigned long ofs, uint32_t enable_bit)
14137c478bdstevel@tonic-gate{
14147c478bdstevel@tonic-gate	unsigned int i;
14157c478bdstevel@tonic-gate	uint32_t val;
14167c478bdstevel@tonic-gate
14177c478bdstevel@tonic-gate	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
14187c478bdstevel@tonic-gate		switch(ofs) {
14197c478bdstevel@tonic-gate		case RCVLSC_MODE:
14207c478bdstevel@tonic-gate		case DMAC_MODE:
14217c478bdstevel@tonic-gate		case MBFREE_MODE:
14227c478bdstevel@tonic-gate		case BUFMGR_MODE:
14237c478bdstevel@tonic-gate		case MEMARB_MODE:
14247c478bdstevel@tonic-gate			/* We can't enable/disable these bits of the
14257c478bdstevel@tonic-gate			 * 5705, just say success.
14267c478bdstevel@tonic-gate			 */
14277c478bdstevel@tonic-gate			return 0;
14287c478bdstevel@tonic-gate		default:
14297c478bdstevel@tonic-gate			break;
14307c478bdstevel@tonic-gate		}
14317c478bdstevel@tonic-gate	}
14327c478bdstevel@tonic-gate	val = tr32(ofs);
14337c478bdstevel@tonic-gate	val &= ~enable_bit;
14347c478bdstevel@tonic-gate	tw32(ofs, val);
14357c478bdstevel@tonic-gate	tr32(ofs);
14367c478bdstevel@tonic-gate
14377c478bdstevel@tonic-gate	for (i = 0; i < MAX_WAIT_CNT; i++) {
14387c478bdstevel@tonic-gate		udelay(100);
14397c478bdstevel@tonic-gate		val = tr32(ofs);
14407c478bdstevel@tonic-gate		if ((val & enable_bit) == 0)
14417c478bdstevel@tonic-gate			break;
14427c478bdstevel@tonic-gate	}
14437c478bdstevel@tonic-gate
14447c478bdstevel@tonic-gate	if (i == MAX_WAIT_CNT) {
14457c478bdstevel@tonic-gate		printf("tg3_stop_block timed out, ofs=%lx enable_bit=%x\n",
14467c478bdstevel@tonic-gate		       ofs, enable_bit);
14477c478bdstevel@tonic-gate		return -ENODEV;
14487c478bdstevel@tonic-gate	}
14497c478bdstevel@tonic-gate
14507c478bdstevel@tonic-gate	return 0;
14517c478bdstevel@tonic-gate}
14527c478bdstevel@tonic-gate
14537c478bdstevel@tonic-gatestatic int tg3_abort_hw(struct tg3 *tp)
14547c478bdstevel@tonic-gate{
14557c478bdstevel@tonic-gate	int i, err;
14567c478bdstevel@tonic-gate
14577c478bdstevel@tonic-gate	tg3_disable_ints(tp);
14587c478bdstevel@tonic-gate
14597c478bdstevel@tonic-gate	tp->rx_mode &= ~RX_MODE_ENABLE;
14607c478bdstevel@tonic-gate	tw32_carefully(MAC_RX_MODE, tp->rx_mode);
14617c478bdstevel@tonic-gate
14627c478bdstevel@tonic-gate	err  = tg3_stop_block(tp, RCVBDI_MODE,   RCVBDI_MODE_ENABLE);
14637c478bdstevel@tonic-gate	err |= tg3_stop_block(tp, RCVLPC_MODE,   RCVLPC_MODE_ENABLE);
14647c478bdstevel@tonic-gate	err |= tg3_stop_block(tp, RCVLSC_MODE,   RCVLSC_MODE_ENABLE);
14657c478bdstevel@tonic-gate	err |= tg3_stop_block(tp, RCVDBDI_MODE,  RCVDBDI_MODE_ENABLE);
14667c478bdstevel@tonic-gate	err |= tg3_stop_block(tp, RCVDCC_MODE,   RCVDCC_MODE_ENABLE);
14677c478bdstevel@tonic-gate	err |= tg3_stop_block(tp, RCVCC_MODE,    RCVCC_MODE_ENABLE);
14687c478bdstevel@tonic-gate
14697c478bdstevel@tonic-gate	err |= tg3_stop_block(tp, SNDBDS_MODE,   SNDBDS_MODE_ENABLE);
14707c478bdstevel@tonic-gate	err |= tg3_stop_block(tp, SNDBDI_MODE,   SNDBDI_MODE_ENABLE);
14717c478bdstevel@tonic-gate	err |= tg3_stop_block(tp, SNDDATAI_MODE, SNDDATAI_MODE_ENABLE);
14727c478bdstevel@tonic-gate	err |= tg3_stop_block(tp, RDMAC_MODE,    RDMAC_MODE_ENABLE);
14737c478bdstevel@tonic-gate	err |= tg3_stop_block(tp, SNDDATAC_MODE, SNDDATAC_MODE_ENABLE);
14747c478bdstevel@tonic-gate	err |= tg3_stop_block(tp, SNDBDC_MODE,   SNDBDC_MODE_ENABLE);
14757c478bdstevel@tonic-gate	if (err)
14767c478bdstevel@tonic-gate		goto out;
14777c478bdstevel@tonic-gate
14787c478bdstevel@tonic-gate	tp->mac_mode &= ~MAC_MODE_TDE_ENABLE;
14797c478bdstevel@tonic-gate	tw32_carefully(MAC_MODE, tp->mac_mode);
14807c478bdstevel@tonic-gate
14817c478bdstevel@tonic-gate	tp->tx_mode &= ~TX_MODE_ENABLE;
14827c478bdstevel@tonic-gate	tw32_carefully(MAC_TX_MODE, tp->tx_mode);
14837c478bdstevel@tonic-gate
14847c478bdstevel@tonic-gate	for (i = 0; i < MAX_WAIT_CNT; i++) {
14857c478bdstevel@tonic-gate		udelay(100);
14867c478bdstevel@tonic-gate		if (!(tr32(MAC_TX_MODE) & TX_MODE_ENABLE))
14877c478bdstevel@tonic-gate			break;
14887c478bdstevel@tonic-gate	}
14897c478bdstevel@tonic-gate	if (i >= MAX_WAIT_CNT) {
14907c478bdstevel@tonic-gate		printf("tg3_abort_hw timed out TX_MODE_ENABLE will not clear MAC_TX_MODE=%x\n",
14917c478bdstevel@tonic-gate			tr32(MAC_TX_MODE));
14927c478bdstevel@tonic-gate		return -ENODEV;
14937c478bdstevel@tonic-gate	}
14947c478bdstevel@tonic-gate
14957c478bdstevel@tonic-gate	err  = tg3_stop_block(tp, HOSTCC_MODE, HOSTCC_MODE_ENABLE);
14967c478bdstevel@tonic-gate	err |= tg3_stop_block(tp, WDMAC_MODE,  WDMAC_MODE_ENABLE);
14977c478bdstevel@tonic-gate	err |= tg3_stop_block(tp, MBFREE_MODE, MBFREE_MODE_ENABLE);
14987c478bdstevel@tonic-gate
14997c478bdstevel@tonic-gate	tw32(FTQ_RESET, 0xffffffff);
15007c478bdstevel@tonic-gate	tw32(FTQ_RESET, 0x00000000);
15017c478bdstevel@tonic-gate
15027c478bdstevel@tonic-gate	err |= tg3_stop_block(tp, BUFMGR_MODE, BUFMGR_MODE_ENABLE);
15037c478bdstevel@tonic-gate	err |= tg3_stop_block(tp, MEMARB_MODE, MEMARB_MODE_ENABLE);
15047c478bdstevel@tonic-gate	if (err)
15057c478bdstevel@tonic-gate		goto out;
15067c478bdstevel@tonic-gate
15077c478bdstevel@tonic-gate	memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE);
15087c478bdstevel@tonic-gate
15097c478bdstevel@tonic-gateout:
15107c478bdstevel@tonic-gate	return err;
15117c478bdstevel@tonic-gate}
15127c478bdstevel@tonic-gate
15137c478bdstevel@tonic-gatestatic void tg3_chip_reset(struct tg3 *tp)
15147c478bdstevel@tonic-gate{
15157c478bdstevel@tonic-gate	uint32_t val;
15167c478bdstevel@tonic-gate
15177c478bdstevel@tonic-gate	if (!(tp->tg3_flags2 & TG3_FLG2_SUN_5704)) {
15187c478bdstevel@tonic-gate		/* Force NVRAM to settle.
15197c478bdstevel@tonic-gate		 * This deals with a chip bug which can result in EEPROM
15207c478bdstevel@tonic-gate		 * corruption.
15217c478bdstevel@tonic-gate		 */
15227c478bdstevel@tonic-gate		if (tp->tg3_flags & TG3_FLAG_NVRAM) {
15237c478bdstevel@tonic-gate			int i;
15247c478bdstevel@tonic-gate
15257c478bdstevel@tonic-gate			tw32(NVRAM_SWARB, SWARB_REQ_SET1);
15267c478bdstevel@tonic-gate			for (i = 0; i < 100000; i++) {
15277c478bdstevel@tonic-gate				if (tr32(NVRAM_SWARB) & SWARB_GNT1)
15287c478bdstevel@tonic-gate					break;
15297c478bdstevel@tonic-gate				udelay(10);
15307c478bdstevel@tonic-gate			}
15317c478bdstevel@tonic-gate		}
15327c478bdstevel@tonic-gate	}
15337c478bdstevel@tonic-gate	/* In Etherboot we don't need to worry about the 5701
15347c478bdstevel@tonic-gate	 * REG_WRITE_BUG because we do all register writes indirectly.
15357c478bdstevel@tonic-gate	 */
15367c478bdstevel@tonic-gate
15377c478bdstevel@tonic-gate	/* do the reset */
15387c478bdstevel@tonic-gate	val = GRC_MISC_CFG_CORECLK_RESET;
15397c478bdstevel@tonic-gate	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705)
15407c478bdstevel@tonic-gate		val |= GRC_MISC_CFG_KEEP_GPHY_POWER;
15417c478bdstevel@tonic-gate	tw32(GRC_MISC_CFG, val);
15427c478bdstevel@tonic-gate
15437c478bdstevel@tonic-gate	/* Flush PCI posted writes.  The normal MMIO registers
15447c478bdstevel@tonic-gate	 * are inaccessible at this time so this is the only
15457c478bdstevel@tonic-gate	 * way to make this reliably.  I tried to use indirect
15467c478bdstevel@tonic-gate	 * register read/write but this upset some 5701 variants.
15477c478bdstevel@tonic-gate	 */
15487c478bdstevel@tonic-gate	pci_read_config_dword(tp->pdev, PCI_COMMAND, &val);
15497c478bdstevel@tonic-gate
15507c478bdstevel@tonic-gate	udelay(120);
15517c478bdstevel@tonic-gate
15527c478bdstevel@tonic-gate	/* Re-enable indirect register accesses. */
15537c478bdstevel@tonic-gate	pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
15547c478bdstevel@tonic-gate			       tp->misc_host_ctrl);
15557c478bdstevel@tonic-gate
15567c478bdstevel@tonic-gate	/* Set MAX PCI retry to zero. */
15577c478bdstevel@tonic-gate	val = (PCISTATE_ROM_ENABLE | PCISTATE_ROM_RETRY_ENABLE);
15587c478bdstevel@tonic-gate	if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 &&
15597c478bdstevel@tonic-gate	    (tp->tg3_flags & TG3_FLAG_PCIX_MODE))
15607c478bdstevel@tonic-gate		val |= PCISTATE_RETRY_SAME_DMA;
15617c478bdstevel@tonic-gate	pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, val);
15627c478bdstevel@tonic-gate
15637c478bdstevel@tonic-gate	pci_restore_state(tp->pdev, tp->pci_cfg_state);
15647c478bdstevel@tonic-gate
15657c478bdstevel@tonic-gate	/* Make sure PCI-X relaxed ordering bit is clear. */
15667c478bdstevel@tonic-gate	pci_read_config_dword(tp->pdev, TG3PCI_X_CAPS, &val);
15677c478bdstevel@tonic-gate	val &= ~PCIX_CAPS_RELAXED_ORDERING;
15687c478bdstevel@tonic-gate	pci_write_config_dword(tp->pdev, TG3PCI_X_CAPS, val);
15697c478bdstevel@tonic-gate
15707c478bdstevel@tonic-gate	tw32(MEMARB_MODE, MEMARB_MODE_ENABLE);
15717c478bdstevel@tonic-gate
15727c478bdstevel@tonic-gate	if (((tp->nic_sram_data_cfg & NIC_SRAM_DATA_CFG_MINI_PCI) != 0) &&
15737c478bdstevel@tonic-gate		(GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705)) {
15747c478bdstevel@tonic-gate		tp->pci_clock_ctrl |=
15757c478bdstevel@tonic-gate			(CLOCK_CTRL_FORCE_CLKRUN | CLOCK_CTRL_CLKRUN_OENABLE);
15767c478bdstevel@tonic-gate		tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl);
15777c478bdstevel@tonic-gate	}
15787c478bdstevel@tonic-gate
15797c478bdstevel@tonic-gate	tw32(TG3PCI_MISC_HOST_CTRL, tp->misc_host_ctrl);
15807c478bdstevel@tonic-gate}
15817c478bdstevel@tonic-gate
15827c478bdstevel@tonic-gatestatic void tg3_stop_fw(struct tg3 *tp)
15837c478bdstevel@tonic-gate{
15847c478bdstevel@tonic-gate	if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) {
15857c478bdstevel@tonic-gate		uint32_t val;
15867c478bdstevel@tonic-gate		int i;
15877c478bdstevel@tonic-gate
15887c478bdstevel@tonic-gate		tg3_write_mem(NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_PAUSE_FW);
15897c478bdstevel@tonic-gate		val = tr32(GRC_RX_CPU_EVENT);
15907c478bdstevel@tonic-gate		val |= (1 << 14);
15917c478bdstevel@tonic-gate		tw32(GRC_RX_CPU_EVENT, val);
15927c478bdstevel@tonic-gate
15937c478bdstevel@tonic-gate		/* Wait for RX cpu to ACK the event.  */
15947c478bdstevel@tonic-gate		for (i = 0; i < 100; i++) {
15957c478bdstevel@tonic-gate			if (!(tr32(GRC_RX_CPU_EVENT) & (1 << 14)))
15967c478bdstevel@tonic-gate				break;
15977c478bdstevel@tonic-gate			udelay(1);
15987c478bdstevel@tonic-gate		}
15997c478bdstevel@tonic-gate	}
16007c478bdstevel@tonic-gate}
16017c478bdstevel@tonic-gate
16027c478bdstevel@tonic-gatestatic int tg3_restart_fw(struct tg3 *tp, uint32_t state)
16037c478bdstevel@tonic-gate{
16047c478bdstevel@tonic-gate	uint32_t val;
16057c478bdstevel@tonic-gate	int i;
16067c478bdstevel@tonic-gate
16077c478bdstevel@tonic-gate	tg3_write_mem(NIC_SRAM_FIRMWARE_MBOX,
16087c478bdstevel@tonic-gate		NIC_SRAM_FIRMWARE_MBOX_MAGIC1);
16097c478bdstevel@tonic-gate	/* Wait for firmware initialization to complete. */
16107c478bdstevel@tonic-gate	for (i = 0; i < 100000; i++) {
16117c478bdstevel@tonic-gate		tg3_read_mem(NIC_SRAM_FIRMWARE_MBOX, &val);
16127c478bdstevel@tonic-gate		if (val == (uint32_t) ~NIC_SRAM_FIRMWARE_MBOX_MAGIC1)
16137c478bdstevel@tonic-gate			break;
16147c478bdstevel@tonic-gate		udelay(10);
16157c478bdstevel@tonic-gate	}
16167c478bdstevel@tonic-gate	if (i >= 100000 &&
16177c478bdstevel@tonic-gate		    !(tp->tg3_flags2 & TG3_FLG2_SUN_5704)) {
16187c478bdstevel@tonic-gate		printf("Firmware will not restart magic=%x\n",
16197c478bdstevel@tonic-gate			val);
16207c478bdstevel@tonic-gate		return -ENODEV;
16217c478bdstevel@tonic-gate	}
16227c478bdstevel@tonic-gate	if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) {
16237c478bdstevel@tonic-gate		state = DRV_STATE_SUSPEND;
16247c478bdstevel@tonic-gate	}
16257c478bdstevel@tonic-gate	tg3_write_mem(NIC_SRAM_FW_DRV_STATE_MBOX, state);
16267c478bdstevel@tonic-gate	return 0;
16277c478bdstevel@tonic-gate}
16287c478bdstevel@tonic-gate
16297c478bdstevel@tonic-gatestatic int tg3_halt(struct tg3 *tp)
16307c478bdstevel@tonic-gate{
16317c478bdstevel@tonic-gate	tg3_stop_fw(tp);
16327c478bdstevel@tonic-gate	tg3_abort_hw(tp);
16337c478bdstevel@tonic-gate	tg3_chip_reset(tp);
16347c478bdstevel@tonic-gate	return tg3_restart_fw(tp, DRV_STATE_UNLOAD);
16357c478bdstevel@tonic-gate}
16367c478bdstevel@tonic-gate
16377c478bdstevel@tonic-gatestatic void __tg3_set_mac_addr(struct tg3 *tp)
16387c478bdstevel@tonic-gate{
16397c478bdstevel@tonic-gate	uint32_t addr_high, addr_low;
16407c478bdstevel@tonic-gate	int i;
16417c478bdstevel@tonic-gate
16427c478bdstevel@tonic-gate	addr_high = ((tp->nic->node_addr[0] << 8) |
16437c478bdstevel@tonic-gate		     tp->nic->node_addr[1]);
16447c478bdstevel@tonic-gate	addr_low = ((tp->nic->node_addr[2] << 24) |
16457c478bdstevel@tonic-gate		    (tp->nic->node_addr[3] << 16) |
16467c478bdstevel@tonic-gate		    (tp->nic->node_addr[4] <<  8) |
16477c478bdstevel@tonic-gate		    (tp->nic->node_addr[5] <<  0));
16487c478bdstevel@tonic-gate	for (i = 0; i < 4; i++) {
16497c478bdstevel@tonic-gate		tw32(MAC_ADDR_0_HIGH + (i * 8), addr_high);
16507c478bdstevel@tonic-gate		tw32(MAC_ADDR_0_LOW + (i * 8), addr_low);
16517c478bdstevel@tonic-gate	}
16527c478bdstevel@tonic-gate
16537c478bdstevel@tonic-gate	if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700) &&
16547c478bdstevel@tonic-gate		(GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) &&
16557c478bdstevel@tonic-gate		(GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705)) {
16567c478bdstevel@tonic-gate		for(i = 0; i < 12; i++) {
16577c478bdstevel@tonic-gate			tw32(MAC_EXTADDR_0_HIGH + (i * 8), addr_high);
16587c478bdstevel@tonic-gate			tw32(MAC_EXTADDR_0_LOW + (i * 8), addr_low);
16597c478bdstevel@tonic-gate		}
16607c478bdstevel@tonic-gate	}
16617c478bdstevel@tonic-gate	addr_high = (tp->nic->node_addr[0] +
16627c478bdstevel@tonic-gate		     tp->nic->node_addr[1] +
16637c478bdstevel@tonic-gate		     tp->nic->node_addr[2] +
16647c478bdstevel@tonic-gate		     tp->nic->node_addr[3] +
16657c478bdstevel@tonic-gate		     tp->nic->node_addr[4] +
16667c478bdstevel@tonic-gate		     tp->nic->node_addr[5]) &
16677c478bdstevel@tonic-gate		TX_BACKOFF_SEED_MASK;
16687c478bdstevel@tonic-gate	tw32(MAC_TX_BACKOFF_SEED, addr_high);
16697c478bdstevel@tonic-gate}
16707c478bdstevel@tonic-gate
16717c478bdstevel@tonic-gatestatic void tg3_set_bdinfo(struct tg3 *tp, uint32_t bdinfo_addr,
16727c478bdstevel@tonic-gate			   dma_addr_t mapping, uint32_t maxlen_flags,
16737c478bdstevel@tonic-gate			   uint32_t nic_addr)
16747c478bdstevel@tonic-gate{
16757c478bdstevel@tonic-gate	tg3_write_mem((bdinfo_addr +
16767c478bdstevel@tonic-gate		       TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_HIGH),
16777c478bdstevel@tonic-gate		      ((uint64_t) mapping >> 32));
16787c478bdstevel@tonic-gate	tg3_write_mem((bdinfo_addr +
16797c478bdstevel@tonic-gate		       TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_LOW),
16807c478bdstevel@tonic-gate		      ((uint64_t) mapping & 0xffffffff));
16817c478bdstevel@tonic-gate	tg3_write_mem((bdinfo_addr +
16827c478bdstevel@tonic-gate		       TG3_BDINFO_MAXLEN_FLAGS),
16837c478bdstevel@tonic-gate		       maxlen_flags);
16847c478bdstevel@tonic-gate	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) {
16857c478bdstevel@tonic-gate		tg3_write_mem((bdinfo_addr + TG3_BDINFO_NIC_ADDR), nic_addr);
16867c478bdstevel@tonic-gate	}
16877c478bdstevel@tonic-gate}
16887c478bdstevel@tonic-gate
16897c478bdstevel@tonic-gate
16907c478bdstevel@tonic-gatestatic void tg3_init_rings(struct tg3 *tp)
16917c478bdstevel@tonic-gate{
16927c478bdstevel@tonic-gate	unsigned i;
16937c478bdstevel@tonic-gate
16947c478bdstevel@tonic-gate	/* Zero out the tg3 variables */
16957c478bdstevel@tonic-gate	memset(&tg3_bss, 0, sizeof(tg3_bss));
16967c478bdstevel@tonic-gate	tp->rx_std    = &tg3_bss.rx_std[0];
16977c478bdstevel@tonic-gate	tp->rx_rcb    = &tg3_bss.rx_rcb[0];
16987c478bdstevel@tonic-gate	tp->tx_ring   = &tg3_bss.tx_ring[0];
16997c478bdstevel@tonic-gate	tp->hw_status = &tg3_bss.hw_status;
17007c478bdstevel@tonic-gate	tp->hw_stats  = &tg3_bss.hw_stats;
17017c478bdstevel@tonic-gate	tp->mac_mode  = 0;
17027c478bdstevel@tonic-gate
17037c478bdstevel@tonic-gate
17047c478bdstevel@tonic-gate	/* Initialize tx/rx rings for packet processing.
17057c478bdstevel@tonic-gate	 *
17067c478bdstevel@tonic-gate	 * The chip has been shut down and the driver detached from
17077c478bdstevel@tonic-gate	 * the networking, so no interrupts or new tx packets will
17087c478bdstevel@tonic-gate	 * end up in the driver.
17097c478bdstevel@tonic-gate	 */
17107c478bdstevel@tonic-gate
17117c478bdstevel@tonic-gate	/* Initialize invariants of the rings, we only set this
17127c478bdstevel@tonic-gate	 * stuff once.  This works because the card does not
17137c478bdstevel@tonic-gate	 * write into the rx buffer posting rings.
17147c478bdstevel@tonic-gate	 */
17157c478bdstevel@tonic-gate	for (i = 0; i < TG3_RX_RING_SIZE; i++) {
17167c478bdstevel@tonic-gate		struct tg3_rx_buffer_desc *rxd;
17177c478bdstevel@tonic-gate
17187c478bdstevel@tonic-gate		rxd = &tp->rx_std[i];
17197c478bdstevel@tonic-gate		rxd->idx_len = (RX_PKT_BUF_SZ - 2 - 64)	<< RXD_LEN_SHIFT;
17207c478bdstevel@tonic-gate		rxd->type_flags = (RXD_FLAG_END << RXD_FLAGS_SHIFT);
17217c478bdstevel@tonic-gate		rxd->opaque = (RXD_OPAQUE_RING_STD | (i << RXD_OPAQUE_INDEX_SHIFT));
17227c478bdstevel@tonic-gate
17237c478bdstevel@tonic-gate		/* Note where the receive buffer for the ring is placed */
17247c478bdstevel@tonic-gate		rxd->addr_hi = 0;
17257c478bdstevel@tonic-gate		rxd->addr_lo = virt_to_bus(
17267c478bdstevel@tonic-gate			&tg3_bss.rx_bufs[i%TG3_DEF_RX_RING_PENDING][2]);
17277c478bdstevel@tonic-gate	}
17287c478bdstevel@tonic-gate}
17297c478bdstevel@tonic-gate
17307c478bdstevel@tonic-gate#define TG3_WRITE_SETTINGS(TABLE) \
17317c478bdstevel@tonic-gatedo { \
17327c478bdstevel@tonic-gate	const uint32_t *_table, *_end; \
17337c478bdstevel@tonic-gate	_table = TABLE; \
17347c478bdstevel@tonic-gate	_end = _table + sizeof(TABLE)/sizeof(TABLE[0]);  \
17357c478bdstevel@tonic-gate	for(; _table < _end; _table += 2) { \
17367c478bdstevel@tonic-gate		tw32(_table[0], _table[1]); \
17377c478bdstevel@tonic-gate	} \
17387c478bdstevel@tonic-gate} while(0)
17397c478bdstevel@tonic-gate
17407c478bdstevel@tonic-gate
17417c478bdstevel@tonic-gate/* initialize/reset the tg3 */
17427c478bdstevel@tonic-gatestatic int tg3_setup_hw(struct tg3 *tp)
17437c478bdstevel@tonic-gate{
17447c478bdstevel@tonic-gate	uint32_t val, rdmac_mode;
17457c478bdstevel@tonic-gate	int i, err, limit;
17467c478bdstevel@tonic-gate
17477c478bdstevel@tonic-gate	/* Simply don't support setups with extremly buggy firmware in etherboot */
17487c478bdstevel@tonic-gate	if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0) {
17497c478bdstevel@tonic-gate		printf("Error 5701_A0 firmware bug detected\n");
17507c478bdstevel@tonic-gate		return -EINVAL;
17517c478bdstevel@tonic-gate	}
17527c478bdstevel@tonic-gate
17537c478bdstevel@tonic-gate	tg3_disable_ints(tp);
17547c478bdstevel@tonic-gate
17557c478bdstevel@tonic-gate	/* Originally this was all in tg3_init_hw */
17567c478bdstevel@tonic-gate
17577c478bdstevel@tonic-gate	/* Force the chip into D0. */
17587c478bdstevel@tonic-gate	tg3_set_power_state_0(tp);
17597c478bdstevel@tonic-gate
17607c478bdstevel@tonic-gate	tg3_switch_clocks(tp);
17617c478bdstevel@tonic-gate
17627c478bdstevel@tonic-gate	tw32(TG3PCI_MEM_WIN_BASE_ADDR, 0);
17637c478bdstevel@tonic-gate
17647c478bdstevel@tonic-gate
17657c478bdstevel@tonic-gate	/* Originally this was all in tg3_reset_hw */
17667c478bdstevel@tonic-gate
17677c478bdstevel@tonic-gate	tg3_stop_fw(tp);
17687c478bdstevel@tonic-gate
17697c478bdstevel@tonic-gate	/* No need to call tg3_abort_hw here, it is called before tg3_setup_hw. */
17707c478bdstevel@tonic-gate
17717c478bdstevel@tonic-gate	tg3_chip_reset(tp);
17727c478bdstevel@tonic-gate
17737c478bdstevel@tonic-gate	tw32(GRC_MODE, tp->grc_mode);  /* Redundant? */
17747c478bdstevel@tonic-gate
17757c478bdstevel@tonic-gate	err = tg3_restart_fw(tp, DRV_STATE_START);
17767c478bdstevel@tonic-gate	if (err)
17777c478bdstevel@tonic-gate		return err;
17787c478bdstevel@tonic-gate
17797c478bdstevel@tonic-gate	if (tp->phy_id == PHY_ID_SERDES) {
17807c478bdstevel@tonic-gate		tp->mac_mode = MAC_MODE_PORT_MODE_TBI;
17817c478bdstevel@tonic-gate	}
17827c478bdstevel@tonic-gate	tw32_carefully(MAC_MODE, tp->mac_mode);
17837c478bdstevel@tonic-gate
17847c478bdstevel@tonic-gate
17857c478bdstevel@tonic-gate	/* This works around an issue with Athlon chipsets on
17867c478bdstevel@tonic-gate	 * B3 tigon3 silicon.  This bit has no effect on any
17877c478bdstevel@tonic-gate	 * other revision.
17887c478bdstevel@tonic-gate	 */
17897c478bdstevel@tonic-gate	tp->pci_clock_ctrl |= CLOCK_CTRL_DELAY_PCI_GRANT;
17907c478bdstevel@tonic-gate	tw32_carefully(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl);
17917c478bdstevel@tonic-gate
17927c478bdstevel@tonic-gate	if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 &&
17937c478bdstevel@tonic-gate	    (tp->tg3_flags & TG3_FLAG_PCIX_MODE)) {
17947c478bdstevel@tonic-gate		val = tr32(TG3PCI_PCISTATE);
17957c478bdstevel@tonic-gate		val |= PCISTATE_RETRY_SAME_DMA;
17967c478bdstevel@tonic-gate		tw32(TG3PCI_PCISTATE, val);
17977c478bdstevel@tonic-gate	}
17987c478bdstevel@tonic-gate
17997c478bdstevel@tonic-gate	/* Descriptor ring init may make accesses to the
18007c478bdstevel@tonic-gate	 * NIC SRAM area to setup the TX descriptors, so we
18017c478bdstevel@tonic-gate	 * can only do this after the hardware has been
18027c478bdstevel@tonic-gate	 * successfully reset.
18037c478bdstevel@tonic-gate	 */
18047c478bdstevel@tonic-gate	tg3_init_rings(tp);
18057c478bdstevel@tonic-gate
18067c478bdstevel@tonic-gate	/* Clear statistics/status block in chip */
18077c478bdstevel@tonic-gate	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) {
18087c478bdstevel@tonic-gate		for (i = NIC_SRAM_STATS_BLK;
18097c478bdstevel@tonic-gate		     i < NIC_SRAM_STATUS_BLK + TG3_HW_STATUS_SIZE;
18107c478bdstevel@tonic-gate		     i += sizeof(uint32_t)) {
18117c478bdstevel@tonic-gate			tg3_write_mem(i, 0);
18127c478bdstevel@tonic-gate			udelay(40);
18137c478bdstevel@tonic-gate		}
18147c478bdstevel@tonic-gate	}
18157c478bdstevel@tonic-gate
18167c478bdstevel@tonic-gate	/* This value is determined during the probe time DMA
18177c478bdstevel@tonic-gate	 * engine test, tg3_setup_dma.
18187c478bdstevel@tonic-gate	 */
18197c478bdstevel@tonic-gate	tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl);
18207c478bdstevel@tonic-gate
18217c478bdstevel@tonic-gate	tp->grc_mode &= ~(GRC_MODE_HOST_SENDBDS |
18227c478bdstevel@tonic-gate			  GRC_MODE_4X_NIC_SEND_RINGS |
18237c478bdstevel@tonic-gate			  GRC_MODE_NO_TX_PHDR_CSUM |
18247c478bdstevel@tonic-gate			  GRC_MODE_NO_RX_PHDR_CSUM);
18257c478bdstevel@tonic-gate	tp->grc_mode |= GRC_MODE_HOST_SENDBDS;
18267c478bdstevel@tonic-gate	tp->grc_mode |= GRC_MODE_NO_TX_PHDR_CSUM;
18277c478bdstevel@tonic-gate	tp->grc_mode |= GRC_MODE_NO_RX_PHDR_CSUM;
18287c478bdstevel@tonic-gate
18297c478bdstevel@tonic-gate	tw32(GRC_MODE,
18307c478bdstevel@tonic-gate		tp->grc_mode |
18317c478bdstevel@tonic-gate		(GRC_MODE_IRQ_ON_MAC_ATTN | GRC_MODE_HOST_STACKUP));
18327c478bdstevel@tonic-gate
18337c478bdstevel@tonic-gate	/* Setup the timer prescalar register.  Clock is always 66Mhz. */
18347c478bdstevel@tonic-gate	tw32(GRC_MISC_CFG,
18357c478bdstevel@tonic-gate	     (65 << GRC_MISC_CFG_PRESCALAR_SHIFT));
18367c478bdstevel@tonic-gate
18377c478bdstevel@tonic-gate	/* Initialize MBUF/DESC pool. */
18387c478bdstevel@tonic-gate	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) {
18397c478bdstevel@tonic-gate		tw32(BUFMGR_MB_POOL_ADDR, NIC_SRAM_MBUF_POOL_BASE);
18407c478bdstevel@tonic-gate		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704)
18417c478bdstevel@tonic-gate			tw32(BUFMGR_MB_POOL_SIZE, NIC_SRAM_MBUF_POOL_SIZE64);
18427c478bdstevel@tonic-gate		else
18437c478bdstevel@tonic-gate			tw32(BUFMGR_MB_POOL_SIZE, NIC_SRAM_MBUF_POOL_SIZE96);
18447c478bdstevel@tonic-gate		tw32(BUFMGR_DMA_DESC_POOL_ADDR, NIC_SRAM_DMA_DESC_POOL_BASE);
18457c478bdstevel@tonic-gate		tw32(BUFMGR_DMA_DESC_POOL_SIZE, NIC_SRAM_DMA_DESC_POOL_SIZE);
18467c478bdstevel@tonic-gate	}
18477c478bdstevel@tonic-gate	if (!(tp->tg3_flags & TG3_FLAG_JUMBO_ENABLE)) {
18487c478bdstevel@tonic-gate		tw32(BUFMGR_MB_RDMA_LOW_WATER,
18497c478bdstevel@tonic-gate		     tp->bufmgr_config.mbuf_read_dma_low_water);
18507c478bdstevel@tonic-gate		tw32(BUFMGR_MB_MACRX_LOW_WATER,
18517c478bdstevel@tonic-gate		     tp->bufmgr_config.mbuf_mac_rx_low_water);
18527c478bdstevel@tonic-gate		tw32(BUFMGR_MB_HIGH_WATER,
18537c478bdstevel@tonic-gate		     tp->bufmgr_config.mbuf_high_water);
18547c478bdstevel@tonic-gate	} else {
18557c478bdstevel@tonic-gate		tw32(BUFMGR_MB_RDMA_LOW_WATER,
18567c478bdstevel@tonic-gate		     tp->bufmgr_config.mbuf_read_dma_low_water_jumbo);
18577c478bdstevel@tonic-gate		tw32(BUFMGR_MB_MACRX_LOW_WATER,
18587c478bdstevel@tonic-gate		     tp->bufmgr_config.mbuf_mac_rx_low_water_jumbo);
18597c478bdstevel@tonic-gate		tw32(BUFMGR_MB_HIGH_WATER,
18607c478bdstevel@tonic-gate		     tp->bufmgr_config.mbuf_high_water_jumbo);
18617c478bdstevel@tonic-gate	}
18627c478bdstevel@tonic-gate	tw32(BUFMGR_DMA_LOW_WATER,
18637c478bdstevel@tonic-gate	     tp->bufmgr_config.dma_low_water);
18647c478bdstevel@tonic-gate	tw32(BUFMGR_DMA_HIGH_WATER,
18657c478bdstevel@tonic-gate	     tp->bufmgr_config.dma_high_water);
18667c478bdstevel@tonic-gate
18677c478bdstevel@tonic-gate	tw32(BUFMGR_MODE, BUFMGR_MODE_ENABLE | BUFMGR_MODE_ATTN_ENABLE);
18687c478bdstevel@tonic-gate	for (i = 0; i < 2000; i++) {
18697c478bdstevel@tonic-gate		if (tr32(BUFMGR_MODE) & BUFMGR_MODE_ENABLE)
18707c478bdstevel@tonic-gate			break;
18717c478bdstevel@tonic-gate		udelay(10);
18727c478bdstevel@tonic-gate	}
18737c478bdstevel@tonic-gate	if (i >= 2000) {
18747c478bdstevel@tonic-gate		printf("tg3_setup_hw cannot enable BUFMGR\n");
18757c478bdstevel@tonic-gate		return -ENODEV;
18767c478bdstevel@tonic-gate	}
18777c478bdstevel@tonic-gate
18787c478bdstevel@tonic-gate	tw32(FTQ_RESET, 0xffffffff);
18797c478bdstevel@tonic-gate	tw32(FTQ_RESET, 0x00000000);
18807c478bdstevel@tonic-gate	for (i = 0; i < 2000; i++) {
18817c478bdstevel@tonic-gate		if (tr32(FTQ_RESET) == 0x00000000)
18827c478bdstevel@tonic-gate			break;
18837c478bdstevel@tonic-gate		udelay(10);
18847c478bdstevel@tonic-gate	}
18857c478bdstevel@tonic-gate	if (i >= 2000) {
18867c478bdstevel@tonic-gate		printf("tg3_setup_hw cannot reset FTQ\n");
18877c478bdstevel@tonic-gate		return -ENODEV;
18887c478bdstevel@tonic-gate	}
18897c478bdstevel@tonic-gate
18907c478bdstevel@tonic-gate	/* Initialize TG3_BDINFO's at:
18917c478bdstevel@tonic-gate	 *  RCVDBDI_STD_BD:	standard eth size rx ring
18927c478bdstevel@tonic-gate	 *  RCVDBDI_JUMBO_BD:	jumbo frame rx ring
18937c478bdstevel@tonic-gate	 *  RCVDBDI_MINI_BD:	small frame rx ring (??? does not work)
18947c478bdstevel@tonic-gate	 *
18957c478bdstevel@tonic-gate	 * like so:
18967c478bdstevel@tonic-gate	 *  TG3_BDINFO_HOST_ADDR:	high/low parts of DMA address of ring
18977c478bdstevel@tonic-gate	 *  TG3_BDINFO_MAXLEN_FLAGS:	(rx max buffer size << 16) |
18987c478bdstevel@tonic-gate	 *                              ring attribute flags
18997c478bdstevel@tonic-gate	 *  TG3_BDINFO_NIC_ADDR:	location of descriptors in nic SRAM
19007c478bdstevel@tonic-gate	 *
19017c478bdstevel@tonic-gate	 * Standard receive ring @ NIC_SRAM_RX_BUFFER_DESC, 512 entries.
19027c478bdstevel@tonic-gate	 * Jumbo receive ring @ NIC_SRAM_RX_JUMBO_BUFFER_DESC, 256 entries.
19037c478bdstevel@tonic-gate	 *
19047c478bdstevel@tonic-gate	 * ??? No space allocated for mini receive ring? :(
19057c478bdstevel@tonic-gate	 *
19067c478bdstevel@tonic-gate	 * The size of each ring is fixed in the firmware, but the location is
19077c478bdstevel@tonic-gate	 * configurable.
19087c478bdstevel@tonic-gate	 */
19097c478bdstevel@tonic-gate	{
19107c478bdstevel@tonic-gate		static const uint32_t table_all[] = {
19117c478bdstevel@tonic-gate			/* Setup replenish thresholds. */
19127c478bdstevel@tonic-gate			RCVBDI_STD_THRESH, TG3_DEF_RX_RING_PENDING / 8,
19137c478bdstevel@tonic-gate
19147c478bdstevel@tonic-gate			/* Etherboot lives below 4GB */
19157c478bdstevel@tonic-gate			RCVDBDI_STD_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_HIGH, 0,
19167c478bdstevel@tonic-gate			RCVDBDI_STD_BD + TG3_BDINFO_NIC_ADDR, NIC_SRAM_RX_BUFFER_DESC,
19177c478bdstevel@tonic-gate		};
19187c478bdstevel@tonic-gate		static const uint32_t table_not_5705[] = {
19197c478bdstevel@tonic-gate			/* Buffer maximum length */
19207c478bdstevel@tonic-gate			RCVDBDI_STD_BD + TG3_BDINFO_MAXLEN_FLAGS, RX_STD_MAX_SIZE << BDINFO_FLAGS_MAXLEN_SHIFT,
19217c478bdstevel@tonic-gate
19227c478bdstevel@tonic-gate			/* Disable the mini frame rx ring */
19237c478bdstevel@tonic-gate			RCVDBDI_MINI_BD + TG3_BDINFO_MAXLEN_FLAGS,	BDINFO_FLAGS_DISABLED,
19247c478bdstevel@tonic-gate
19257c478bdstevel@tonic-gate			/* Disable the jumbo frame rx ring */
19267c478bdstevel@tonic-gate			RCVBDI_JUMBO_THRESH, 0,
19277c478bdstevel@tonic-gate			RCVDBDI_JUMBO_BD + TG3_BDINFO_MAXLEN_FLAGS, BDINFO_FLAGS_DISABLED,
19287c478bdstevel@tonic-gate
19297c478bdstevel@tonic-gate
19307c478bdstevel@tonic-gate		};
19317c478bdstevel@tonic-gate		TG3_WRITE_SETTINGS(table_all);
19327c478bdstevel@tonic-gate		tw32(RCVDBDI_STD_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_LOW,
19337c478bdstevel@tonic-gate			virt_to_bus(tp->rx_std));
19347c478bdstevel@tonic-gate		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
19357c478bdstevel@tonic-gate			tw32(RCVDBDI_STD_BD + TG3_BDINFO_MAXLEN_FLAGS,
19367c478bdstevel@tonic-gate				RX_STD_MAX_SIZE_5705 << BDINFO_FLAGS_MAXLEN_SHIFT);
19377c478bdstevel@tonic-gate		} else {
19387c478bdstevel@tonic-gate			TG3_WRITE_SETTINGS(table_not_5705);
19397c478bdstevel@tonic-gate		}
19407c478bdstevel@tonic-gate	}
19417c478bdstevel@tonic-gate
19427c478bdstevel@tonic-gate
19437c478bdstevel@tonic-gate	/* There is only one send ring on 5705, no need to explicitly
19447c478bdstevel@tonic-gate	 * disable the others.
19457c478bdstevel@tonic-gate	 */
19467c478bdstevel@tonic-gate	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) {
19477c478bdstevel@tonic-gate		/* Clear out send RCB ring in SRAM. */
19487c478bdstevel@tonic-gate		for (i = NIC_SRAM_SEND_RCB; i < NIC_SRAM_RCV_RET_RCB; i += TG3_BDINFO_SIZE)
19497c478bdstevel@tonic-gate			tg3_write_mem(i + TG3_BDINFO_MAXLEN_FLAGS, BDINFO_FLAGS_DISABLED);
19507c478bdstevel@tonic-gate	}
19517c478bdstevel@tonic-gate
19527c478bdstevel@tonic-gate	tp->tx_prod = 0;
19537c478bdstevel@tonic-gate	tw32_mailbox(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW, 0);
19547c478bdstevel@tonic-gate	tw32_mailbox2(MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW, 0);
19557c478bdstevel@tonic-gate
19567c478bdstevel@tonic-gate	tg3_set_bdinfo(tp,
19577c478bdstevel@tonic-gate		NIC_SRAM_SEND_RCB,
19587c478bdstevel@tonic-gate		virt_to_bus(tp->tx_ring),
19597c478bdstevel@tonic-gate		(TG3_TX_RING_SIZE << BDINFO_FLAGS_MAXLEN_SHIFT),
19607c478bdstevel@tonic-gate		NIC_SRAM_TX_BUFFER_DESC);
19617c478bdstevel@tonic-gate
19627c478bdstevel@tonic-gate	/* There is only one receive return ring on 5705, no need to explicitly
19637c478bdstevel@tonic-gate	 * disable the others.
19647c478bdstevel@tonic-gate	 */
19657c478bdstevel@tonic-gate	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) {
19667c478bdstevel@tonic-gate		for (i = NIC_SRAM_RCV_RET_RCB; i < NIC_SRAM_STATS_BLK; i += TG3_BDINFO_SIZE) {
19677c478bdstevel@tonic-gate			tg3_write_mem(i + TG3_BDINFO_MAXLEN_FLAGS,
19687c478bdstevel@tonic-gate				BDINFO_FLAGS_DISABLED);
19697c478bdstevel@tonic-gate		}
19707c478bdstevel@tonic-gate	}
19717c478bdstevel@tonic-gate
19727c478bdstevel@tonic-gate	tp->rx_rcb_ptr = 0;
19737c478bdstevel@tonic-gate	tw32_mailbox2(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW, 0);
19747c478bdstevel@tonic-gate
19757c478bdstevel@tonic-gate	tg3_set_bdinfo(tp,
19767c478bdstevel@tonic-gate		NIC_SRAM_RCV_RET_RCB,
19777c478bdstevel@tonic-gate		virt_to_bus(tp->rx_rcb),
19787c478bdstevel@tonic-gate		(TG3_RX_RCB_RING_SIZE << BDINFO_FLAGS_MAXLEN_SHIFT),
19797c478bdstevel@tonic-gate		0);
19807c478bdstevel@tonic-gate
19817c478bdstevel@tonic-gate	tp->rx_std_ptr = TG3_DEF_RX_RING_PENDING;
19827c478bdstevel@tonic-gate	tw32_mailbox2(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW,
19837c478bdstevel@tonic-gate		     tp->rx_std_ptr);
19847c478bdstevel@tonic-gate
19857c478bdstevel@tonic-gate	tw32_mailbox2(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW, 0);
19867c478bdstevel@tonic-gate
19877c478bdstevel@tonic-gate	/* Initialize MAC address and backoff seed. */
19887c478bdstevel@tonic-gate	__tg3_set_mac_addr(tp);
19897c478bdstevel@tonic-gate
19907c478bdstevel@tonic-gate	/* Calculate RDMAC_MODE setting early, we need it to determine
19917c478bdstevel@tonic-gate	 * the RCVLPC_STATE_ENABLE mask.
19927c478bdstevel@tonic-gate	 */
19937c478bdstevel@tonic-gate	rdmac_mode = (RDMAC_MODE_ENABLE | RDMAC_MODE_TGTABORT_ENAB |
19947c478bdstevel@tonic-gate		RDMAC_MODE_MSTABORT_ENAB | RDMAC_MODE_PARITYERR_ENAB |
19957c478bdstevel@tonic-gate		RDMAC_MODE_ADDROFLOW_ENAB | RDMAC_MODE_FIFOOFLOW_ENAB |
19967c478bdstevel@tonic-gate		RDMAC_MODE_FIFOURUN_ENAB | RDMAC_MODE_FIFOOREAD_ENAB |
19977c478bdstevel@tonic-gate		RDMAC_MODE_LNGREAD_ENAB);
19987c478bdstevel@tonic-gate	if (tp->tg3_flags & TG3_FLAG_SPLIT_MODE)
19997c478bdstevel@tonic-gate		rdmac_mode |= RDMAC_MODE_SPLIT_ENABLE;
20007c478bdstevel@tonic-gate	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
20017c478bdstevel@tonic-gate		if (tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) {
20027c478bdstevel@tonic-gate			if (!(tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH) &&
20037c478bdstevel@tonic-gate				!(tp->tg3_flags2 & TG3_FLG2_IS_5788)) {
20047c478bdstevel@tonic-gate				rdmac_mode |= RDMAC_MODE_FIFO_LONG_BURST;
20057c478bdstevel@tonic-gate			}
20067c478bdstevel@tonic-gate		}
20077c478bdstevel@tonic-gate	}
20087c478bdstevel@tonic-gate
20097c478bdstevel@tonic-gate	/* Setup host coalescing engine. */
20107c478bdstevel@tonic-gate	tw32(HOSTCC_MODE, 0);
20117c478bdstevel@tonic-gate	for (i = 0; i < 2000; i++) {
20127c478bdstevel@tonic-gate		if (!(tr32(HOSTCC_MODE) & HOSTCC_MODE_ENABLE))
20137c478bdstevel@tonic-gate			break;
20147c478bdstevel@tonic-gate		udelay(10);
20157c478bdstevel@tonic-gate	}
20167c478bdstevel@tonic-gate
20177c478bdstevel@tonic-gate	tp->mac_mode = MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE |
20187c478bdstevel@tonic-gate		MAC_MODE_TDE_ENABLE | MAC_MODE_RDE_ENABLE | MAC_MODE_FHDE_ENABLE;
20197c478bdstevel@tonic-gate	tw32_carefully(MAC_MODE, tp->mac_mode | MAC_MODE_RXSTAT_CLEAR | MAC_MODE_TXSTAT_CLEAR);
20207c478bdstevel@tonic-gate
20217c478bdstevel@tonic-gate	tp->grc_local_ctrl = GRC_LCLCTRL_INT_ON_ATTN | GRC_LCLCTRL_AUTO_SEEPROM;
20227c478bdstevel@tonic-gate	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700)
20237c478bdstevel@tonic-gate		tp->grc_local_ctrl |= (GRC_LCLCTRL_GPIO_OE1 |
20247c478bdstevel@tonic-gate				       GRC_LCLCTRL_GPIO_OUTPUT1);
20257c478bdstevel@tonic-gate	tw32_carefully(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
20267c478bdstevel@tonic-gate
20277c478bdstevel@tonic-gate	tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0);
20287c478bdstevel@tonic-gate	tr32(MAILBOX_INTERRUPT_0);
20297c478bdstevel@tonic-gate
20307c478bdstevel@tonic-gate	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) {
20317c478bdstevel@tonic-gate		tw32_carefully(DMAC_MODE, DMAC_MODE_ENABLE);
20327c478bdstevel@tonic-gate	}
20337c478bdstevel@tonic-gate
20347c478bdstevel@tonic-gate	val = (	WDMAC_MODE_ENABLE | WDMAC_MODE_TGTABORT_ENAB |
20357c478bdstevel@tonic-gate		WDMAC_MODE_MSTABORT_ENAB | WDMAC_MODE_PARITYERR_ENAB |
20367c478bdstevel@tonic-gate		WDMAC_MODE_ADDROFLOW_ENAB | WDMAC_MODE_FIFOOFLOW_ENAB |
20377c478bdstevel@tonic-gate		WDMAC_MODE_FIFOURUN_ENAB | WDMAC_MODE_FIFOOREAD_ENAB |
20387c478bdstevel@tonic-gate		WDMAC_MODE_LNGREAD_ENAB);
20397c478bdstevel@tonic-gate	if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) &&
20407c478bdstevel@tonic-gate		((tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH) != 0) &&
20417c478bdstevel@tonic-gate		!(tp->tg3_flags2 & TG3_FLG2_IS_5788)) {
20427c478bdstevel@tonic-gate		val |= WDMAC_MODE_RX_ACCEL;
20437c478bdstevel@tonic-gate	}
20447c478bdstevel@tonic-gate	tw32_carefully(WDMAC_MODE, val);
20457c478bdstevel@tonic-gate
20467c478bdstevel@tonic-gate	if ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) != 0) {
20477c478bdstevel@tonic-gate		val = tr32(TG3PCI_X_CAPS);
20487c478bdstevel@tonic-gate		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703) {
20497c478bdstevel@tonic-gate			val &= PCIX_CAPS_BURST_MASK;
20507c478bdstevel@tonic-gate			val |= (PCIX_CAPS_MAX_BURST_CPIOB << PCIX_CAPS_BURST_SHIFT);
20517c478bdstevel@tonic-gate		} else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
20527c478bdstevel@tonic-gate			val &= ~(PCIX_CAPS_SPLIT_MASK | PCIX_CAPS_BURST_MASK);
20537c478bdstevel@tonic-gate			val |= (PCIX_CAPS_MAX_BURST_CPIOB << PCIX_CAPS_BURST_SHIFT);
20547c478bdstevel@tonic-gate			if (tp->tg3_flags & TG3_FLAG_SPLIT_MODE)
20557c478bdstevel@tonic-gate				val |= (tp->split_mode_max_reqs <<
20567c478bdstevel@tonic-gate					PCIX_CAPS_SPLIT_SHIFT);
20577c478bdstevel@tonic-gate		}
20587c478bdstevel@tonic-gate		tw32(TG3PCI_X_CAPS, val);
20597c478bdstevel@tonic-gate	}
20607c478bdstevel@tonic-gate
20617c478bdstevel@tonic-gate	tw32_carefully(RDMAC_MODE, rdmac_mode);
20627c478bdstevel@tonic-gate	{
20637c478bdstevel@tonic-gate		static const uint32_t table_all[] = {
20647c478bdstevel@tonic-gate			/* MTU + ethernet header + FCS + optional VLAN tag */
20657c478bdstevel@tonic-gate			MAC_RX_MTU_SIZE, ETH_MAX_MTU + ETH_HLEN + 8,
20667c478bdstevel@tonic-gate
20677c478bdstevel@tonic-gate			/* The slot time is changed by tg3_setup_phy if we
20687c478bdstevel@tonic-gate			 * run at gigabit with half duplex.
20697c478bdstevel@tonic-gate			 */
20707c478bdstevel@tonic-gate			MAC_TX_LENGTHS,
20717c478bdstevel@tonic-gate			(2 << TX_LENGTHS_IPG_CRS_SHIFT) |
20727c478bdstevel@tonic-gate			(6 << TX_LENGTHS_IPG_SHIFT) |
20737c478bdstevel@tonic-gate			(32 << TX_LENGTHS_SLOT_TIME_SHIFT),
20747c478bdstevel@tonic-gate
20757c478bdstevel@tonic-gate			/* Receive rules. */
20767c478bdstevel@tonic-gate			MAC_RCV_RULE_CFG, RCV_RULE_CFG_DEFAULT_CLASS,
20777c478bdstevel@tonic-gate			RCVLPC_CONFIG, 0x0181,
20787c478bdstevel@tonic-gate
20797c478bdstevel@tonic-gate			/* Receive/send statistics. */
20807c478bdstevel@tonic-gate			RCVLPC_STATS_ENABLE, 0xffffff,
20817c478bdstevel@tonic-gate			RCVLPC_STATSCTRL, RCVLPC_STATSCTRL_ENABLE,
20827c478bdstevel@tonic-gate			SNDDATAI_STATSENAB, 0xffffff,
20837c478bdstevel@tonic-gate			SNDDATAI_STATSCTRL, (SNDDATAI_SCTRL_ENABLE |SNDDATAI_SCTRL_FASTUPD),
20847c478bdstevel@tonic-gate
20857c478bdstevel@tonic-gate			/* Host coalescing engine */
20867c478bdstevel@tonic-gate			HOSTCC_RXCOL_TICKS, 0,
20877c478bdstevel@tonic-gate			HOSTCC_TXCOL_TICKS, LOW_TXCOL_TICKS,
20887c478bdstevel@tonic-gate			HOSTCC_RXMAX_FRAMES, 1,
20897c478bdstevel@tonic-gate			HOSTCC_TXMAX_FRAMES, LOW_RXMAX_FRAMES,
20907c478bdstevel@tonic-gate			HOSTCC_RXCOAL_MAXF_INT, 1,
20917c478bdstevel@tonic-gate			HOSTCC_TXCOAL_MAXF_INT, 0,
20927c478bdstevel@tonic-gate
20937c478bdstevel@tonic-gate			/* Status/statistics block address. */
20947c478bdstevel@tonic-gate			/* Etherboot lives below 4GB, so HIGH == 0 */
20957c478bdstevel@tonic-gate			HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_HIGH, 0,
20967c478bdstevel@tonic-gate
20977c478bdstevel@tonic-gate			/* No need to enable 32byte coalesce mode. */
20987c478bdstevel@tonic-gate			HOSTCC_MODE, HOSTCC_MODE_ENABLE | 0,
20997c478bdstevel@tonic-gate
21007c478bdstevel@tonic-gate			RCVCC_MODE, RCVCC_MODE_ENABLE | RCVCC_MODE_ATTN_ENABLE,
21017c478bdstevel@tonic-gate			RCVLPC_MODE, RCVLPC_MODE_ENABLE,
21027c478bdstevel@tonic-gate
21037c478bdstevel@tonic-gate			RCVDCC_MODE, RCVDCC_MODE_ENABLE | RCVDCC_MODE_ATTN_ENABLE,
21047c478bdstevel@tonic-gate
21057c478bdstevel@tonic-gate			SNDDATAC_MODE, SNDDATAC_MODE_ENABLE,
21067c478bdstevel@tonic-gate			SNDBDC_MODE, SNDBDC_MODE_ENABLE | SNDBDC_MODE_ATTN_ENABLE,
21077c478bdstevel@tonic-gate			RCVBDI_MODE, RCVBDI_MODE_ENABLE | RCVBDI_MODE_RCB_ATTN_ENAB,
21087c478bdstevel@tonic-gate			RCVDBDI_MODE, RCVDBDI_MODE_ENABLE | RCVDBDI_MODE_INV_RING_SZ,
21097c478bdstevel@tonic-gate			SNDDATAI_MODE, SNDDATAI_MODE_ENABLE,
21107c478bdstevel@tonic-gate			SNDBDI_MODE, SNDBDI_MODE_ENABLE | SNDBDI_MODE_ATTN_ENABLE,
21117c478bdstevel@tonic-gate			SNDBDS_MODE, SNDBDS_MODE_ENABLE | SNDBDS_MODE_ATTN_ENABLE,
21127c478bdstevel@tonic-gate
21137c478bdstevel@tonic-gate			/* Accept all multicast frames. */
21147c478bdstevel@tonic-gate			MAC_HASH_REG_0, 0xffffffff,
21157c478bdstevel@tonic-gate			MAC_HASH_REG_1, 0xffffffff,
21167c478bdstevel@tonic-gate			MAC_HASH_REG_2, 0xffffffff,
21177c478bdstevel@tonic-gate			MAC_HASH_REG_3, 0xffffffff,
21187c478bdstevel@tonic-gate		};
21197c478bdstevel@tonic-gate		static const uint32_t table_not_5705[] = {
21207c478bdstevel@tonic-gate			/* Host coalescing engine */
21217c478bdstevel@tonic-gate			HOSTCC_RXCOAL_TICK_INT, 0,
21227c478bdstevel@tonic-gate			HOSTCC_TXCOAL_TICK_INT, 0,
21237c478bdstevel@tonic-gate
21247c478bdstevel@tonic-gate			/* Status/statistics block address. */
21257c478bdstevel@tonic-gate			/* Etherboot lives below 4GB, so HIGH == 0 */
21267c478bdstevel@tonic-gate			HOSTCC_STAT_COAL_TICKS, DEFAULT_STAT_COAL_TICKS,
21277c478bdstevel@tonic-gate			HOSTCC_STATS_BLK_HOST_ADDR + TG3_64BIT_REG_HIGH, 0,
21287c478bdstevel@tonic-gate			HOSTCC_STATS_BLK_NIC_ADDR, NIC_SRAM_STATS_BLK,
21297c478bdstevel@tonic-gate			HOSTCC_STATUS_BLK_NIC_ADDR, NIC_SRAM_STATUS_BLK,
21307c478bdstevel@tonic-gate
21317c478bdstevel@tonic-gate			RCVLSC_MODE, RCVLSC_MODE_ENABLE | RCVLSC_MODE_ATTN_ENABLE,
21327c478bdstevel@tonic-gate
21337c478bdstevel@tonic-gate			MBFREE_MODE, MBFREE_MODE_ENABLE,
21347c478bdstevel@tonic-gate		};
21357c478bdstevel@tonic-gate		TG3_WRITE_SETTINGS(table_all);
21367c478bdstevel@tonic-gate		tw32(HOSTCC_STATS_BLK_HOST_ADDR + TG3_64BIT_REG_LOW,
21377c478bdstevel@tonic-gate			virt_to_bus(tp->hw_stats));
21387c478bdstevel@tonic-gate		tw32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_LOW,
21397c478bdstevel@tonic-gate			virt_to_bus(tp->hw_status));
21407c478bdstevel@tonic-gate		if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) {
21417c478bdstevel@tonic-gate			TG3_WRITE_SETTINGS(table_not_5705);
21427c478bdstevel@tonic-gate		}
21437c478bdstevel@tonic-gate	}
21447c478bdstevel@tonic-gate
21457c478bdstevel@tonic-gate	tp->tx_mode = TX_MODE_ENABLE;
21467c478bdstevel@tonic-gate	tw32_carefully(MAC_TX_MODE, tp->tx_mode);
21477c478bdstevel@tonic-gate
21487c478bdstevel@tonic-gate	tp->rx_mode = RX_MODE_ENABLE;
21497c478bdstevel@tonic-gate	tw32_carefully(MAC_RX_MODE, tp->rx_mode);
21507c478bdstevel@tonic-gate
21517c478bdstevel@tonic-gate	tp->mi_mode = MAC_MI_MODE_BASE;
21527c478bdstevel@tonic-gate	tw32_carefully(MAC_MI_MODE, tp->mi_mode);
21537c478bdstevel@tonic-gate
21547c478bdstevel@tonic-gate	tw32(MAC_LED_CTRL, 0);
21557c478bdstevel@tonic-gate	tw32(MAC_MI_STAT, MAC_MI_STAT_LNKSTAT_ATTN_ENAB);
21567c478bdstevel@tonic-gate	if (tp->phy_id == PHY_ID_SERDES) {
21577c478bdstevel@tonic-gate		tw32_carefully(MAC_RX_MODE, RX_MODE_RESET);
21587c478bdstevel@tonic-gate	}
21597c478bdstevel@tonic-gate	tp->rx_mode |= RX_MODE_KEEP_VLAN_TAG; /* drop tagged vlan packets */
21607c478bdstevel@tonic-gate	tw32_carefully(MAC_RX_MODE, tp->rx_mode);
21617c478bdstevel@tonic-gate
21627c478bdstevel@tonic-gate	if (tp->pci_chip_rev_id == CHIPREV_ID_5703_A1)
21637c478bdstevel@tonic-gate		tw32(MAC_SERDES_CFG, 0x616000);
21647c478bdstevel@tonic-gate
21657c478bdstevel@tonic-gate	/* Prevent chip from dropping frames when flow control
21667c478bdstevel@tonic-gate	 * is enabled.
21677c478bdstevel@tonic-gate	 */
21687c478bdstevel@tonic-gate	tw32(MAC_LOW_WMARK_MAX_RX_FRAME, 2);
21697c478bdstevel@tonic-gate	tr32(MAC_LOW_WMARK_MAX_RX_FRAME);
21707c478bdstevel@tonic-gate
21717c478bdstevel@tonic-gate	err = tg3_setup_phy(tp);
21727c478bdstevel@tonic-gate
21737c478bdstevel@tonic-gate	/* Ignore CRC stats */
21747c478bdstevel@tonic-gate
21757c478bdstevel@tonic-gate	/* Initialize receive rules. */
21767c478bdstevel@tonic-gate	tw32(MAC_RCV_RULE_0,  0xc2000000 & RCV_RULE_DISABLE_MASK);
21777c478bdstevel@tonic-gate	tw32(MAC_RCV_VALUE_0, 0xffffffff & RCV_RULE_DISABLE_MASK);
21787c478bdstevel@tonic-gate	tw32(MAC_RCV_RULE_1,  0x86000004 & RCV_RULE_DISABLE_MASK);
21797c478bdstevel@tonic-gate	tw32(MAC_RCV_VALUE_1, 0xffffffff & RCV_RULE_DISABLE_MASK);
21807c478bdstevel@tonic-gate
21817c478bdstevel@tonic-gate	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705)
21827c478bdstevel@tonic-gate		limit = 8;
21837c478bdstevel@tonic-gate	else
21847c478bdstevel@tonic-gate		limit = 16;
21857c478bdstevel@tonic-gate	if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF)
21867c478bdstevel@tonic-gate		limit -= 4;
21877c478bdstevel@tonic-gate	switch (limit) {
21887c478bdstevel@tonic-gate	case 16:	tw32(MAC_RCV_RULE_15,  0); tw32(MAC_RCV_VALUE_15,  0);
21897c478bdstevel@tonic-gate	case 15:	tw32(MAC_RCV_RULE_14,  0); tw32(MAC_RCV_VALUE_14,  0);
21907c478bdstevel@tonic-gate	case 14:	tw32(MAC_RCV_RULE_13,  0); tw32(MAC_RCV_VALUE_13,  0);
21917c478bdstevel@tonic-gate	case 13:	tw32(MAC_RCV_RULE_12,  0); tw32(MAC_RCV_VALUE_12,  0);
21927c478bdstevel@tonic-gate	case 12:	tw32(MAC_RCV_RULE_11,  0); tw32(MAC_RCV_VALUE_11,  0);
21937c478bdstevel@tonic-gate	case 11:	tw32(MAC_RCV_RULE_10,  0); tw32(MAC_RCV_VALUE_10,  0);
21947c478bdstevel@tonic-gate	case 10:	tw32(MAC_RCV_RULE_9,  0);  tw32(MAC_RCV_VALUE_9,  0);
21957c478bdstevel@tonic-gate	case 9:		tw32(MAC_RCV_RULE_8,  0);  tw32(MAC_RCV_VALUE_8,  0);
21967c478bdstevel@tonic-gate	case 8:		tw32(MAC_RCV_RULE_7,  0);  tw32(MAC_RCV_VALUE_7,  0);
21977c478bdstevel@tonic-gate	case 7:		tw32(MAC_RCV_RULE_6,  0);  tw32(MAC_RCV_VALUE_6,  0);
21987c478bdstevel@tonic-gate	case 6:		tw32(MAC_RCV_RULE_5,  0);  tw32(MAC_RCV_VALUE_5,  0);
21997c478bdstevel@tonic-gate	case 5:		tw32(MAC_RCV_RULE_4,  0);  tw32(MAC_RCV_VALUE_4,  0);
22007c478bdstevel@tonic-gate	case 4:		/* tw32(MAC_RCV_RULE_3,  0); tw32(MAC_RCV_VALUE_3,  0); */
22017c478bdstevel@tonic-gate	case 3:		/* tw32(MAC_RCV_RULE_2,  0); tw32(MAC_RCV_VALUE_2,  0); */
22027c478bdstevel@tonic-gate	case 2:
22037c478bdstevel@tonic-gate	case 1:
22047c478bdstevel@tonic-gate	default:
22057c478bdstevel@tonic-gate		break;
22067c478bdstevel@tonic-gate	};
22077c478bdstevel@tonic-gate
22087c478bdstevel@tonic-gate	return err;
22097c478bdstevel@tonic-gate}
22107c478bdstevel@tonic-gate
22117c478bdstevel@tonic-gate
22127c478bdstevel@tonic-gate
22137c478bdstevel@tonic-gate/* Chips other than 5700/5701 use the NVRAM for fetching info. */
22147c478bdstevel@tonic-gatestatic void tg3_nvram_init(struct tg3 *tp)
22157c478bdstevel@tonic-gate{
22167c478bdstevel@tonic-gate	tw32(GRC_EEPROM_ADDR,
22177c478bdstevel@tonic-gate	     (EEPROM_ADDR_FSM_RESET |
22187c478bdstevel@tonic-gate	      (EEPROM_DEFAULT_CLOCK_PERIOD <<
22197c478bdstevel@tonic-gate	       EEPROM_ADDR_CLKPERD_SHIFT)));
22207c478bdstevel@tonic-gate
22217c478bdstevel@tonic-gate	mdelay(1);
22227c478bdstevel@tonic-gate
22237c478bdstevel@tonic-gate	/* Enable seeprom accesses. */
22247c478bdstevel@tonic-gate	tw32_carefully(GRC_LOCAL_CTRL,
22257c478bdstevel@tonic-gate		tr32(GRC_LOCAL_CTRL) | GRC_LCLCTRL_AUTO_SEEPROM);
22267c478bdstevel@tonic-gate
22277c478bdstevel@tonic-gate	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 &&
22287c478bdstevel@tonic-gate	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) {
22297c478bdstevel@tonic-gate		uint32_t nvcfg1 = tr32(NVRAM_CFG1);
22307c478bdstevel@tonic-gate
22317c478bdstevel@tonic-gate		tp->tg3_flags |= TG3_FLAG_NVRAM;
22327c478bdstevel@tonic-gate		if (nvcfg1 & NVRAM_CFG1_FLASHIF_ENAB) {
22337c478bdstevel@tonic-gate			if (nvcfg1 & NVRAM_CFG1_BUFFERED_MODE)
22347c478bdstevel@tonic-gate				tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
22357c478bdstevel@tonic-gate		} else {
22367c478bdstevel@tonic-gate			nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS;
22377c478bdstevel@tonic-gate			tw32(NVRAM_CFG1, nvcfg1);
22387c478bdstevel@tonic-gate		}
22397c478bdstevel@tonic-gate
22407c478bdstevel@tonic-gate	} else {
22417c478bdstevel@tonic-gate		tp->tg3_flags &= ~(TG3_FLAG_NVRAM | TG3_FLAG_NVRAM_BUFFERED);
22427c478bdstevel@tonic-gate	}
22437c478bdstevel@tonic-gate}
22447c478bdstevel@tonic-gate
22457c478bdstevel@tonic-gate
22467c478bdstevel@tonic-gatestatic int tg3_nvram_read_using_eeprom(
22477c478bdstevel@tonic-gate	struct tg3 *tp __unused, uint32_t offset, uint32_t *val)
22487c478bdstevel@tonic-gate{
22497c478bdstevel@tonic-gate	uint32_t tmp;
22507c478bdstevel@tonic-gate	int i;
22517c478bdstevel@tonic-gate
22527c478bdstevel@tonic-gate	if (offset > EEPROM_ADDR_ADDR_MASK ||
22537c478bdstevel@tonic-gate		(offset % 4) != 0) {
22547c478bdstevel@tonic-gate		return -EINVAL;
22557c478bdstevel@tonic-gate	}
22567c478bdstevel@tonic-gate
22577c478bdstevel@tonic-gate	tmp = tr32(GRC_EEPROM_ADDR) & ~(EEPROM_ADDR_ADDR_MASK |
22587c478bdstevel@tonic-gate					EEPROM_ADDR_DEVID_MASK |
22597c478bdstevel@tonic-gate					EEPROM_ADDR_READ);
22607c478bdstevel@tonic-gate	tw32(GRC_EEPROM_ADDR,
22617c478bdstevel@tonic-gate	     tmp |
22627c478bdstevel@tonic-gate	     (0 << EEPROM_ADDR_DEVID_SHIFT) |
22637c478bdstevel@tonic-gate	     ((offset << EEPROM_ADDR_ADDR_SHIFT) &
22647c478bdstevel@tonic-gate	      EEPROM_ADDR_ADDR_MASK) |
22657c478bdstevel@tonic-gate	     EEPROM_ADDR_READ | EEPROM_ADDR_START);
22667c478bdstevel@tonic-gate
22677c478bdstevel@tonic-gate	for (i = 0; i < 10000; i++) {
22687c478bdstevel@tonic-gate		tmp = tr32(GRC_EEPROM_ADDR);
22697c478bdstevel@tonic-gate
22707c478bdstevel@tonic-gate		if (tmp & EEPROM_ADDR_COMPLETE)
22717c478bdstevel@tonic-gate			break;
22727c478bdstevel@tonic-gate		udelay(100);
22737c478bdstevel@tonic-gate	}
22747c478bdstevel@tonic-gate	if (!(tmp & EEPROM_ADDR_COMPLETE)) {
22757c478bdstevel@tonic-gate		return -EBUSY;
22767c478bdstevel@tonic-gate	}
22777c478bdstevel@tonic-gate
22787c478bdstevel@tonic-gate	*val = tr32(GRC_EEPROM_DATA);
22797c478bdstevel@tonic-gate	return 0;
22807c478bdstevel@tonic-gate}
22817c478bdstevel@tonic-gate
22827c478bdstevel@tonic-gatestatic int tg3_nvram_read(struct tg3 *tp, uint32_t offset, uint32_t *val)
22837c478bdstevel@tonic-gate{
22847c478bdstevel@tonic-gate	int i, saw_done_clear;
22857c478bdstevel@tonic-gate
22867c478bdstevel@tonic-gate	if (!(tp->tg3_flags & TG3_FLAG_NVRAM))
22877c478bdstevel@tonic-gate		return tg3_nvram_read_using_eeprom(tp, offset, val);
22887c478bdstevel@tonic-gate
22897c478bdstevel@tonic-gate	if (tp->tg3_flags & TG3_FLAG_NVRAM_BUFFERED)
22907c478bdstevel@tonic-gate		offset = ((offset / NVRAM_BUFFERED_PAGE_SIZE) <<
22917c478bdstevel@tonic-gate			  NVRAM_BUFFERED_PAGE_POS) +
22927c478bdstevel@tonic-gate			(offset % NVRAM_BUFFERED_PAGE_SIZE);
22937c478bdstevel@tonic-gate
22947c478bdstevel@tonic-gate	if (offset > NVRAM_ADDR_MSK)
22957c478bdstevel@tonic-gate		return -EINVAL;
22967c478bdstevel@tonic-gate
22977c478bdstevel@tonic-gate	tw32(NVRAM_SWARB, SWARB_REQ_SET1);
22987c478bdstevel@tonic-gate	for (i = 0; i < 1000; i++) {
22997c478bdstevel@tonic-gate		if (tr32(NVRAM_SWARB) & SWARB_GNT1)
23007c478bdstevel@tonic-gate			break;
23017c478bdstevel@tonic-gate		udelay(20);
23027c478bdstevel@tonic-gate	}
23037c478bdstevel@tonic-gate
23047c478bdstevel@tonic-gate	tw32(NVRAM_ADDR, offset);
23057c478bdstevel@tonic-gate	tw32(NVRAM_CMD,
23067c478bdstevel@tonic-gate	     NVRAM_CMD_RD | NVRAM_CMD_GO |
23077c478bdstevel@tonic-gate	     NVRAM_CMD_FIRST | NVRAM_CMD_LAST | NVRAM_CMD_DONE);
23087c478bdstevel@tonic-gate
23097c478bdstevel@tonic-gate	/* Wait for done bit to clear then set again. */
23107c478bdstevel@tonic-gate	saw_done_clear = 0;
23117c478bdstevel@tonic-gate	for (i = 0; i < 1000; i++) {
23127c478bdstevel@tonic-gate		udelay(10);
23137c478bdstevel@tonic-gate		if (!saw_done_clear &&
23147c478bdstevel@tonic-gate		    !(tr32(NVRAM_CMD) & NVRAM_CMD_DONE))
23157c478bdstevel@tonic-gate			saw_done_clear = 1;
23167c478bdstevel@tonic-gate		else if (saw_done_clear &&
23177c478bdstevel@tonic-gate			 (tr32(NVRAM_CMD) & NVRAM_CMD_DONE))
23187c478bdstevel@tonic-gate			break;
23197c478bdstevel@tonic-gate	}
23207c478bdstevel@tonic-gate	if (i >= 1000) {
23217c478bdstevel@tonic-gate		tw32(NVRAM_SWARB, SWARB_REQ_CLR1);
23227c478bdstevel@tonic-gate		return -EBUSY;
23237c478bdstevel@tonic-gate	}
23247c478bdstevel@tonic-gate
23257c478bdstevel@tonic-gate	*val = bswap_32(tr32(NVRAM_RDDATA));
23267c478bdstevel@tonic-gate	tw32(NVRAM_SWARB, 0x20);
23277c478bdstevel@tonic-gate
23287c478bdstevel@tonic-gate	return 0;
23297c478bdstevel@tonic-gate}
23307c478bdstevel@tonic-gate
23317c478bdstevel@tonic-gatestruct subsys_tbl_ent {
23327c478bdstevel@tonic-gate	uint16_t subsys_vendor, subsys_devid;
23337c478bdstevel@tonic-gate	uint32_t phy_id;
23347c478bdstevel@tonic-gate};
23357c478bdstevel@tonic-gate
23367c478bdstevel@tonic-gatestatic struct subsys_tbl_ent subsys_id_to_phy_id[] = {
23377c478bdstevel@tonic-gate	/* Broadcom boards. */
23387c478bdstevel@tonic-gate	{ 0x14e4, 0x1644, PHY_ID_BCM5401 }, /* BCM95700A6 */
23397c478bdstevel@tonic-gate	{ 0x14e4, 0x0001, PHY_ID_BCM5701 }, /* BCM95701A5 */
23407c478bdstevel@tonic-gate	{ 0x14e4, 0x0002, PHY_ID_BCM8002 }, /* BCM95700T6 */
23417c478bdstevel@tonic-gate	{ 0x14e4, 0x0003, PHY_ID_SERDES  }, /* BCM95700A9 */
23427c478bdstevel@tonic-gate	{ 0x14e4, 0x0005, PHY_ID_BCM5701 }, /* BCM95701T1 */
23437c478bdstevel@tonic-gate	{ 0x14e4, 0x0006, PHY_ID_BCM5701 }, /* BCM95701T8 */
23447c478bdstevel@tonic-gate	{ 0x14e4, 0x0007, PHY_ID_SERDES  }, /* BCM95701A7 */
23457c478bdstevel@tonic-gate	{ 0x14e4, 0x0008, PHY_ID_BCM5701 }, /* BCM95701A10 */
23467c478bdstevel@tonic-gate	{ 0x14e4, 0x8008, PHY_ID_BCM5701 }, /* BCM95701A12 */
23477c478bdstevel@tonic-gate	{ 0x14e4, 0x0009, PHY_ID_BCM5701 }, /* BCM95703Ax1 */
23487c478bdstevel@tonic-gate	{ 0x14e4, 0x8009, PHY_ID_BCM5701 }, /* BCM95703Ax2 */
23497c478bdstevel@tonic-gate
23507c478bdstevel@tonic-gate	/* 3com boards. */
23517c478bdstevel@tonic-gate	{ PCI_VENDOR_ID_3COM, 0x1000, PHY_ID_BCM5401 }, /* 3C996T */
23527c478bdstevel@tonic-gate	{ PCI_VENDOR_ID_3COM, 0x1006, PHY_ID_BCM5701 }, /* 3C996BT */
23537c478bdstevel@tonic-gate	/* { PCI_VENDOR_ID_3COM, 0x1002, PHY_ID_XXX },     3C996CT */
23547c478bdstevel@tonic-gate	/* { PCI_VENDOR_ID_3COM, 0x1003, PHY_ID_XXX },     3C997T */
23557c478bdstevel@tonic-gate	{ PCI_VENDOR_ID_3COM, 0x1004, PHY_ID_SERDES  }, /* 3C996SX */
23567c478bdstevel@tonic-gate	/* { PCI_VENDOR_ID_3COM, 0x1005, PHY_ID_XXX },     3C997SZ */
23577c478bdstevel@tonic-gate	{ PCI_VENDOR_ID_3COM, 0x1007, PHY_ID_BCM5701 }, /* 3C1000T */
23587c478bdstevel@tonic-gate	{ PCI_VENDOR_ID_3COM, 0x1008, PHY_ID_BCM5701 }, /* 3C940BR01 */
23597c478bdstevel@tonic-gate
23607c478bdstevel@tonic-gate	/* DELL boards. */
23617c478bdstevel@tonic-gate	{ PCI_VENDOR_ID_DELL, 0x00d1, PHY_ID_BCM5401 }, /* VIPER */
23627c478bdstevel@tonic-gate	{ PCI_VENDOR_ID_DELL, 0x0106, PHY_ID_BCM5401 }, /* JAGUAR */
23637c478bdstevel@tonic-gate	{ PCI_VENDOR_ID_DELL, 0x0109, PHY_ID_BCM5411 }, /* MERLOT */
23647c478bdstevel@tonic-gate	{ PCI_VENDOR_ID_DELL, 0x010a, PHY_ID_BCM5411 }, /* SLIM_MERLOT */
23657c478bdstevel@tonic-gate
23667c478bdstevel@tonic-gate	/* Compaq boards. */
23677c478bdstevel@tonic-gate	{ PCI_VENDOR_ID_COMPAQ, 0x007c, PHY_ID_BCM5701 }, /* BANSHEE */
23687c478bdstevel@tonic-gate	{ PCI_VENDOR_ID_COMPAQ, 0x009a, PHY_ID_BCM5701 }, /* BANSHEE_2 */
23697c478bdstevel@tonic-gate	{ PCI_VENDOR_ID_COMPAQ, 0x007d, PHY_ID_SERDES  }, /* CHANGELING */
23707c478bdstevel@tonic-gate	{ PCI_VENDOR_ID_COMPAQ, 0x0085, PHY_ID_BCM5701 }, /* NC7780 */
23717c478bdstevel@tonic-gate	{ PCI_VENDOR_ID_COMPAQ, 0x0099, PHY_ID_BCM5701 }  /* NC7780_2 */
23727c478bdstevel@tonic-gate};
23737c478bdstevel@tonic-gate
23747c478bdstevel@tonic-gatestatic int tg3_phy_probe(struct tg3 *tp)
23757c478bdstevel@tonic-gate{
23767c478bdstevel@tonic-gate	uint32_t eeprom_phy_id, hw_phy_id_1, hw_phy_id_2;
23777c478bdstevel@tonic-gate	uint32_t hw_phy_id, hw_phy_id_masked;
23787c478bdstevel@tonic-gate	enum phy_led_mode eeprom_led_mode;
23797c478bdstevel@tonic-gate	uint32_t val;
23807c478bdstevel@tonic-gate	unsigned i;
23817c478bdstevel@tonic-gate	int eeprom_signature_found, err;
23827c478bdstevel@tonic-gate
23837c478bdstevel@tonic-gate	tp->phy_id = PHY_ID_INVALID;
23847c478bdstevel@tonic-gate
23857c478bdstevel@tonic-gate	for (i = 0; i < sizeof(subsys_id_to_phy_id)/sizeof(subsys_id_to_phy_id[0]); i++) {
23867c478bdstevel@tonic-gate		if ((subsys_id_to_phy_id[i].subsys_vendor == tp->subsystem_vendor) &&
23877c478bdstevel@tonic-gate			(subsys_id_to_phy_id[i].subsys_devid == tp->subsystem_device)) {
23887c478bdstevel@tonic-gate			tp->phy_id = subsys_id_to_phy_id[i].phy_id;
23897c478bdstevel@tonic-gate			break;
23907c478bdstevel@tonic-gate		}
23917c478bdstevel@tonic-gate	}
23927c478bdstevel@tonic-gate
23937c478bdstevel@tonic-gate	eeprom_phy_id = PHY_ID_INVALID;
23947c478bdstevel@tonic-gate	eeprom_led_mode = led_mode_auto;
23957c478bdstevel@tonic-gate	eeprom_signature_found = 0;
23967c478bdstevel@tonic-gate	tg3_read_mem(NIC_SRAM_DATA_SIG, &val);
23977c478bdstevel@tonic-gate	if (val == NIC_SRAM_DATA_SIG_MAGIC) {
23987c478bdstevel@tonic-gate		uint32_t nic_cfg;
23997c478bdstevel@tonic-gate
24007c478bdstevel@tonic-gate		tg3_read_mem(NIC_SRAM_DATA_CFG, &nic_cfg);
24017c478bdstevel@tonic-gate		tp->nic_sram_data_cfg = nic_cfg;
24027c478bdstevel@tonic-gate
24037c478bdstevel@tonic-gate		eeprom_signature_found = 1;
24047c478bdstevel@tonic-gate
24057c478bdstevel@tonic-gate		if ((nic_cfg & NIC_SRAM_DATA_CFG_PHY_TYPE_MASK) ==
24067c478bdstevel@tonic-gate		    NIC_SRAM_DATA_CFG_PHY_TYPE_FIBER) {
24077c478bdstevel@tonic-gate			eeprom_phy_id = PHY_ID_SERDES;
24087c478bdstevel@tonic-gate		} else {
24097c478bdstevel@tonic-gate			uint32_t nic_phy_id;
24107c478bdstevel@tonic-gate
24117c478bdstevel@tonic-gate			tg3_read_mem(NIC_SRAM_DATA_PHY_ID, &nic_phy_id);
24127c478bdstevel@tonic-gate			if (nic_phy_id != 0) {
24137c478bdstevel@tonic-gate				uint32_t id1 = nic_phy_id & NIC_SRAM_DATA_PHY_ID1_MASK;
24147c478bdstevel@tonic-gate				uint32_t id2 = nic_phy_id & NIC_SRAM_DATA_PHY_ID2_MASK;
24157c478bdstevel@tonic-gate
24167c478bdstevel@tonic-gate				eeprom_phy_id  = (id1 >> 16) << 10;
24177c478bdstevel@tonic-gate				eeprom_phy_id |= (id2 & 0xfc00) << 16;
24187c478bdstevel@tonic-gate				eeprom_phy_id |= (id2 & 0x03ff) <<  0;
24197c478bdstevel@tonic-gate			}
24207c478bdstevel@tonic-gate		}
24217c478bdstevel@tonic-gate
24227c478bdstevel@tonic-gate		switch (nic_cfg & NIC_SRAM_DATA_CFG_LED_MODE_MASK) {
24237c478bdstevel@tonic-gate		case NIC_SRAM_DATA_CFG_LED_TRIPLE_SPD:
24247c478bdstevel@tonic-gate			eeprom_led_mode = led_mode_three_link;
24257c478bdstevel@tonic-gate			break;
24267c478bdstevel@tonic-gate
24277c478bdstevel@tonic-gate		case NIC_SRAM_DATA_CFG_LED_LINK_SPD:
24287c478bdstevel@tonic-gate			eeprom_led_mode = led_mode_link10;
24297c478bdstevel@tonic-gate			break;
24307c478bdstevel@tonic-gate
24317c478bdstevel@tonic-gate		default:
24327c478bdstevel@tonic-gate			eeprom_led_mode = led_mode_auto;
24337c478bdstevel@tonic-gate			break;
24347c478bdstevel@tonic-gate		};
24357c478bdstevel@tonic-gate		if (((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703) ||
24367c478bdstevel@tonic-gate			(GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) ||
24377c478bdstevel@tonic-gate			(GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705)) &&
24387c478bdstevel@tonic-gate			(nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP)) {
24397c478bdstevel@tonic-gate			tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT;
24407c478bdstevel@tonic-gate		}
24417c478bdstevel@tonic-gate
24427c478bdstevel@tonic-gate		if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE)
24437c478bdstevel@tonic-gate			tp->tg3_flags |= TG3_FLAG_ENABLE_ASF;
24447c478bdstevel@tonic-gate		if (nic_cfg & NIC_SRAM_DATA_CFG_FIBER_WOL)
24457c478bdstevel@tonic-gate			tp->tg3_flags |= TG3_FLAG_SERDES_WOL_CAP;
24467c478bdstevel@tonic-gate	}
24477c478bdstevel@tonic-gate
24487c478bdstevel@tonic-gate	/* Now read the physical PHY_ID from the chip and verify
24497c478bdstevel@tonic-gate	 * that it is sane.  If it doesn't look good, we fall back
24507c478bdstevel@tonic-gate	 * to either the hard-coded table based PHY_ID and failing
24517c478bdstevel@tonic-gate	 * that the value found in the eeprom area.
24527c478bdstevel@tonic-gate	 */
24537c478bdstevel@tonic-gate	err  = tg3_readphy(tp, MII_PHYSID1, &hw_phy_id_1);
24547c478bdstevel@tonic-gate	err |= tg3_readphy(tp, MII_PHYSID2, &hw_phy_id_2);
24557c478bdstevel@tonic-gate
24567c478bdstevel@tonic-gate	hw_phy_id  = (hw_phy_id_1 & 0xffff) << 10;
24577c478bdstevel@tonic-gate	hw_phy_id |= (hw_phy_id_2 & 0xfc00) << 16;
24587c478bdstevel@tonic-gate	hw_phy_id |= (hw_phy_id_2 & 0x03ff) <<  0;
24597c478bdstevel@tonic-gate
24607c478bdstevel@tonic-gate	hw_phy_id_masked = hw_phy_id & PHY_ID_MASK;
24617c478bdstevel@tonic-gate
24627c478bdstevel@tonic-gate	if (!err && KNOWN_PHY_ID(hw_phy_id_masked)) {
24637c478bdstevel@tonic-gate		tp->phy_id = hw_phy_id;
24647c478bdstevel@tonic-gate	} else {
24657c478bdstevel@tonic-gate		/* phy_id currently holds the value found in the
24667c478bdstevel@tonic-gate		 * subsys_id_to_phy_id[] table or PHY_ID_INVALID
24677c478bdstevel@tonic-gate		 * if a match was not found there.
24687c478bdstevel@tonic-gate		 */
24697c478bdstevel@tonic-gate		if (tp->phy_id == PHY_ID_INVALID) {
24707c478bdstevel@tonic-gate			if (!eeprom_signature_found ||
24717c478bdstevel@tonic-gate			    !KNOWN_PHY_ID(eeprom_phy_id & PHY_ID_MASK))
24727c478bdstevel@tonic-gate				return -ENODEV;
24737c478bdstevel@tonic-gate			tp->phy_id = eeprom_phy_id;
24747c478bdstevel@tonic-gate		}
24757c478bdstevel@tonic-gate	}
24767c478bdstevel@tonic-gate
24777c478bdstevel@tonic-gate	err = tg3_phy_reset(tp);
24787c478bdstevel@tonic-gate	if (err)
24797c478bdstevel@tonic-gate		return err;
24807c478bdstevel@tonic-gate
24817c478bdstevel@tonic-gate	if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 ||
24827c478bdstevel@tonic-gate	    tp->pci_chip_rev_id == CHIPREV_ID_5701_B0) {
24837c478bdstevel@tonic-gate		uint32_t mii_tg3_ctrl;
24847c478bdstevel@tonic-gate
24857c478bdstevel@tonic-gate		/* These chips, when reset, only advertise 10Mb
24867c478bdstevel@tonic-gate		 * capabilities.  Fix that.
24877c478bdstevel@tonic-gate		 */
24887c478bdstevel@tonic-gate		err  = tg3_writephy(tp, MII_ADVERTISE,
24897c478bdstevel@tonic-gate				    (ADVERTISE_CSMA |
24907c478bdstevel@tonic-gate				     ADVERTISE_PAUSE_CAP |
24917c478bdstevel@tonic-gate				     ADVERTISE_10HALF |
24927c478bdstevel@tonic-gate				     ADVERTISE_10FULL |
24937c478bdstevel@tonic-gate				     ADVERTISE_100HALF |
24947c478bdstevel@tonic-gate				     ADVERTISE_100FULL));
24957c478bdstevel@tonic-gate		mii_tg3_ctrl = (MII_TG3_CTRL_ADV_1000_HALF |
24967c478bdstevel@tonic-gate				MII_TG3_CTRL_ADV_1000_FULL |
24977c478bdstevel@tonic-gate				MII_TG3_CTRL_AS_MASTER |
24987c478bdstevel@tonic-gate				MII_TG3_CTRL_ENABLE_AS_MASTER);
24997c478bdstevel@tonic-gate		if (tp->tg3_flags & TG3_FLAG_10_100_ONLY)
25007c478bdstevel@tonic-gate			mii_tg3_ctrl = 0;
25017c478bdstevel@tonic-gate
25027c478bdstevel@tonic-gate		err |= tg3_writephy(tp, MII_TG3_CTRL, mii_tg3_ctrl);
25037c478bdstevel@tonic-gate		err |= tg3_writephy(tp, MII_BMCR,
25047c478bdstevel@tonic-gate				    (BMCR_ANRESTART | BMCR_ANENABLE));
25057c478bdstevel@tonic-gate	}
25067c478bdstevel@tonic-gate
25077c478bdstevel@tonic-gate	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703) {
25087c478bdstevel@tonic-gate		tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00);
25097c478bdstevel@tonic-gate		tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x201f);
25107c478bdstevel@tonic-gate		tg3_writedsp(tp, MII_TG3_DSP_RW_PORT, 0x2aaa);
25117c478bdstevel@tonic-gate	}
25127c478bdstevel@tonic-gate
25137c478bdstevel@tonic-gate	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
25147c478bdstevel@tonic-gate		tg3_writephy(tp, 0x1c, 0x8d68);
25157c478bdstevel@tonic-gate		tg3_writephy(tp, 0x1c, 0x8d68);
25167c478bdstevel@tonic-gate	}
25177c478bdstevel@tonic-gate
25187c478bdstevel@tonic-gate	/* Enable Ethernet@WireSpeed */
25197c478bdstevel@tonic-gate	tg3_phy_set_wirespeed(tp);
25207c478bdstevel@tonic-gate
25217c478bdstevel@tonic-gate	if (!err && ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401)) {
25227c478bdstevel@tonic-gate		err = tg3_init_5401phy_dsp(tp);
25237c478bdstevel@tonic-gate	}
25247c478bdstevel@tonic-gate
25257c478bdstevel@tonic-gate	/* Determine the PHY led mode.
25267c478bdstevel@tonic-gate	 * Be careful if this gets set wrong it can result in an inability to
25277c478bdstevel@tonic-gate	 * establish a link.
25287c478bdstevel@tonic-gate	 */
25297c478bdstevel@tonic-gate	if (tp->phy_id == PHY_ID_SERDES) {
25307c478bdstevel@tonic-gate		tp->led_mode = led_mode_three_link;
25317c478bdstevel@tonic-gate	}
25327c478bdstevel@tonic-gate	else if (tp->subsystem_vendor == PCI_VENDOR_ID_DELL) {
25337c478bdstevel@tonic-gate		tp->led_mode = led_mode_link10;
25347c478bdstevel@tonic-gate	} else {
25357c478bdstevel@tonic-gate		tp->led_mode = led_mode_three_link;
25367c478bdstevel@tonic-gate		if (eeprom_signature_found &&
25377c478bdstevel@tonic-gate		    eeprom_led_mode != led_mode_auto)
25387c478bdstevel@tonic-gate			tp->led_mode = eeprom_led_mode;
25397c478bdstevel@tonic-gate	}
25407c478bdstevel@tonic-gate
25417c478bdstevel@tonic-gate	if (tp->phy_id == PHY_ID_SERDES)
25427c478bdstevel@tonic-gate		tp->link_config.advertising =
25437c478bdstevel@tonic-gate			(ADVERTISED_1000baseT_Half |
25447c478bdstevel@tonic-gate			 ADVERTISED_1000baseT_Full |
25457c478bdstevel@tonic-gate			 ADVERTISED_Autoneg |
25467c478bdstevel@tonic-gate			 ADVERTISED_FIBRE);
25477c478bdstevel@tonic-gate	if (tp->tg3_flags & TG3_FLAG_10_100_ONLY)
25487c478bdstevel@tonic-gate		tp->link_config.advertising &=
25497c478bdstevel@tonic-gate			~(ADVERTISED_1000baseT_Half |
25507c478bdstevel@tonic-gate			  ADVERTISED_1000baseT_Full);
25517c478bdstevel@tonic-gate
25527c478bdstevel@tonic-gate	return err;
25537c478bdstevel@tonic-gate}
25547c478bdstevel@tonic-gate
25557c478bdstevel@tonic-gate#if SUPPORT_PARTNO_STR
25567c478bdstevel@tonic-gatestatic void tg3_read_partno(struct tg3 *tp)
25577c478bdstevel@tonic-gate{
25587c478bdstevel@tonic-gate	unsigned char vpd_data[256];
25597c478bdstevel@tonic-gate	int i;
25607c478bdstevel@tonic-gate
25617c478bdstevel@tonic-gate	for (i = 0; i < 256; i += 4) {
25627c478bdstevel@tonic-gate		uint32_t tmp;
25637c478bdstevel@tonic-gate
25647c478bdstevel@tonic-gate		if (tg3_nvram_read(tp, 0x100 + i, &tmp))
25657c478bdstevel@tonic-gate			goto out_not_found;
25667c478bdstevel@tonic-gate
25677c478bdstevel@tonic-gate		vpd_data[i + 0] = ((tmp >>  0) & 0xff);
25687c478bdstevel@tonic-gate		vpd_data[i + 1] = ((tmp >>  8) & 0xff);
25697c478bdstevel@tonic-gate		vpd_data[i + 2] = ((tmp >> 16) & 0xff);
25707c478bdstevel@tonic-gate		vpd_data[i + 3] = ((tmp >> 24) & 0xff);
25717c478bdstevel@tonic-gate	}
25727c478bdstevel@tonic-gate
25737c478bdstevel@tonic-gate	/* Now parse and find the part number. */
25747c478bdstevel@tonic-gate	for (i = 0; i < 256; ) {
25757c478bdstevel@tonic-gate		unsigned char val = vpd_data[i];
25767c478bdstevel@tonic-gate		int block_end;
25777c478bdstevel@tonic-gate
25787c478bdstevel@tonic-gate		if (val == 0x82 || val == 0x91) {
25797c478bdstevel@tonic-gate			i = (i + 3 +
25807c478bdstevel@tonic-gate			     (vpd_data[i + 1] +
25817c478bdstevel@tonic-gate			      (vpd_data[i + 2] << 8)));
25827c478bdstevel@tonic-gate			continue;
25837c478bdstevel@tonic-gate		}
25847c478bdstevel@tonic-gate
25857c478bdstevel@tonic-gate		if (val != 0x90)
25867c478bdstevel@tonic-gate			goto out_not_found;
25877c478bdstevel@tonic-gate
25887c478bdstevel@tonic-gate		block_end = (i + 3 +
25897c478bdstevel@tonic-gate			     (vpd_data[i + 1] +
25907c478bdstevel@tonic-gate			      (vpd_data[i + 2] << 8)));
25917c478bdstevel@tonic-gate		i += 3;
25927c478bdstevel@tonic-gate		while (i < block_end) {
25937c478bdstevel@tonic-gate			if (vpd_data[i + 0] == 'P' &&
25947c478bdstevel@tonic-gate			    vpd_data[i + 1] == 'N') {
25957c478bdstevel@tonic-gate				int partno_len = vpd_data[i + 2];
25967c478bdstevel@tonic-gate
25977c478bdstevel@tonic-gate				if (partno_len > 24)
25987c478bdstevel@tonic-gate					goto out_not_found;
25997c478bdstevel@tonic-gate
26007c478bdstevel@tonic-gate				memcpy(tp->board_part_number,
26017c478bdstevel@tonic-gate				       &vpd_data[i + 3],
26027c478bdstevel@tonic-gate				       partno_len);
26037c478bdstevel@tonic-gate
26047c478bdstevel@tonic-gate				/* Success. */
26057c478bdstevel@tonic-gate				return;
26067c478bdstevel@tonic-gate			}
26077c478bdstevel@tonic-gate		}
26087c478bdstevel@tonic-gate
26097c478bdstevel@tonic-gate		/* Part number not found. */
26107c478bdstevel@tonic-gate		goto out_not_found;
26117c478bdstevel@tonic-gate	}
26127c478bdstevel@tonic-gate
26137c478bdstevel@tonic-gateout_not_found:
26147c478bd</