/* * tg3.c: Broadcom Tigon3 ethernet driver. * * Copyright (C) 2006 Kristian Van Der Vliet (vanders@liqwyd.com) * Copyright (C) 2001, 2002, 2003, 2004 David S. Miller (davem@redhat.com) * Copyright (C) 2001, 2002, 2003 Jeff Garzik (jgarzik@pobox.com) * Copyright (C) 2004 Sun Microsystems Inc. * Copyright (C) 2005 Broadcom Corporation. * * Firmware is: * Derived from proprietary unpublished source code, * Copyright (C) 2000-2003 Broadcom Corporation. * * Permission is hereby granted for the distribution of this firmware * data in hexadecimal or equivalent format, provided this copyright * notice is accompanying it. */ #include #include #include #include #include #include #include #include #include #include #define NO_DEBUG_STUBS 1 #include #include static PCI_bus_s* g_psBus; #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 #define TG3_DEF_TX_MODE 0 /* length of time before we decide the hardware is borked, * and dev->tx_timeout() should be called to fix the problem */ #define TG3_TX_TIMEOUT (5 * HZ) /* hardware minimum and maximum for a single frame's data payload */ #define TG3_MIN_MTU 60 #define TG3_MAX_MTU(tp) \ ((tp->tg3_flags2 & TG3_FLG2_JUMBO_CAPABLE) ? 9000 : 1500) /* These numbers seem to be hard coded in the NIC firmware somehow. * You can't change the ring sizes, but you can change where you place * them in the NIC onboard memory. */ #define TG3_RX_RING_SIZE 512 #define TG3_DEF_RX_RING_PENDING 200 #define TG3_RX_JUMBO_RING_SIZE 256 #define TG3_DEF_RX_JUMBO_RING_PENDING 100 /* Do not place this n-ring entries value into the tp struct itself, * we really want to expose these constants to GCC so that modulo et * al. operations are done with shifts and masks instead of with * hw multiply/modulo instructions. Another solution would be to * replace things like '% foo' with '& (foo - 1)'. */ #define TG3_RX_RCB_RING_SIZE(tp) \ ((tp->tg3_flags2 & TG3_FLG2_5705_PLUS) ? 512 : 1024) #define TG3_TX_RING_SIZE 512 #define TG3_DEF_TX_RING_PENDING (TG3_TX_RING_SIZE - 1) #define TG3_RX_RING_BYTES (sizeof(struct tg3_rx_buffer_desc) * \ TG3_RX_RING_SIZE) #define TG3_RX_JUMBO_RING_BYTES (sizeof(struct tg3_rx_buffer_desc) * \ TG3_RX_JUMBO_RING_SIZE) #define TG3_RX_RCB_RING_BYTES(tp) (sizeof(struct tg3_rx_buffer_desc) * \ TG3_RX_RCB_RING_SIZE(tp)) #define TG3_TX_RING_BYTES (sizeof(struct tg3_tx_buffer_desc) * \ TG3_TX_RING_SIZE) #define NEXT_TX(N) (((N) + 1) & (TG3_TX_RING_SIZE - 1)) #define RX_PKT_BUF_SZ (1536 + tp->rx_offset + 64) #define RX_JUMBO_PKT_BUF_SZ (9046 + tp->rx_offset + 64) /* These vendor and device IDs should all be in the system header pci_vendors.h */ #define PCI_VENDOR_ID_BROADCOM 0x14e4 #define PCI_DEVICE_ID_TIGON3_5752 0x1600 #define PCI_DEVICE_ID_TIGON3_5752M 0x1601 #define PCI_DEVICE_ID_TIGON3_5700 0x1644 #define PCI_DEVICE_ID_TIGON3_5701 0x1645 #define PCI_DEVICE_ID_TIGON3_5702 0x1646 #define PCI_DEVICE_ID_TIGON3_5703 0x1647 #define PCI_DEVICE_ID_TIGON3_5704 0x1648 #define PCI_DEVICE_ID_TIGON3_5704S_2 0x1649 #define PCI_DEVICE_ID_TIGON3_5702FE 0x164d #define PCI_DEVICE_ID_TIGON3_5705 0x1653 #define PCI_DEVICE_ID_TIGON3_5705_2 0x1654 #define PCI_DEVICE_ID_TIGON3_5720 0x1658 #define PCI_DEVICE_ID_TIGON3_5721 0x1659 #define PCI_DEVICE_ID_TIGON3_5705M 0x165d #define PCI_DEVICE_ID_TIGON3_5705M_2 0x165e #define PCI_DEVICE_ID_TIGON3_5714 0x1668 #define PCI_DEVICE_ID_TIGON3_5714S 0x1669 #define PCI_DEVICE_ID_TIGON3_5780 0x166a #define PCI_DEVICE_ID_TIGON3_5780S 0x166b #define PCI_DEVICE_ID_TIGON3_5705F 0x166e #define PCI_DEVICE_ID_TIGON3_5754M 0x1672 #define PCI_DEVICE_ID_TIGON3_5755M 0x1673 #define PCI_DEVICE_ID_TIGON3_5750 0x1676 #define PCI_DEVICE_ID_TIGON3_5751 0x1677 #define PCI_DEVICE_ID_TIGON3_5715 0x1678 #define PCI_DEVICE_ID_TIGON3_5715S 0x1679 #define PCI_DEVICE_ID_TIGON3_5754 0x167a #define PCI_DEVICE_ID_TIGON3_5755 0x167b #define PCI_DEVICE_ID_TIGON3_5750M 0x167c #define PCI_DEVICE_ID_TIGON3_5751M 0x167d #define PCI_DEVICE_ID_TIGON3_5751F 0x167e #define PCI_DEVICE_ID_TIGON3_5787M 0x1693 #define PCI_DEVICE_ID_TIGON3_5782 0x1696 #define PCI_DEVICE_ID_TIGON3_5786 0x169a #define PCI_DEVICE_ID_TIGON3_5787 0x169b #define PCI_DEVICE_ID_TIGON3_5788 0x169c #define PCI_DEVICE_ID_TIGON3_5789 0x169d #define PCI_DEVICE_ID_TIGON3_5702X 0x16a6 #define PCI_DEVICE_ID_TIGON3_5703X 0x16a7 #define PCI_DEVICE_ID_TIGON3_5704S 0x16a8 #define PCI_DEVICE_ID_TIGON3_5702A3 0x16c6 #define PCI_DEVICE_ID_TIGON3_5703A3 0x16c7 #define PCI_DEVICE_ID_TIGON3_5781 0x16dd #define PCI_DEVICE_ID_TIGON3_5753 0x16f7 #define PCI_DEVICE_ID_TIGON3_5753M 0x16fd #define PCI_DEVICE_ID_TIGON3_5753F 0x16fe #define PCI_DEVICE_ID_TIGON3_5901 0x170d #define PCI_DEVICE_ID_TIGON3_5901_2 0x170e #define PCI_VENDOR_ID_SYSKONNECT 0x1148 #define PCI_DEVICE_ID_SYSKONNECT_9DXX 0x4400 #define PCI_DEVICE_ID_SYSKONNECT_9MXX 0x4500 #define PCI_VENDOR_ID_ALTIMA 0x173b #define PCI_DEVICE_ID_ALTIMA_AC1000 0x03e8 #define PCI_DEVICE_ID_ALTIMA_AC1001 0x03e9 #define PCI_DEVICE_ID_ALTIMA_AC9100 0x03ea #define PCI_DEVICE_ID_ALTIMA_AC1003 0x03eb #define PCI_VENDOR_ID_APPLE 0x106b #define PCI_DEVICE_ID_APPLE_TIGON3 0x1645 static struct pci_device_id tg3_pci_tbl[] = { { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5700, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5701, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5703, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702FE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705M, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705M_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702X, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5703X, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704S, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702A3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5703A3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5782, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5788, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5789, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704S_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5720, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5721, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5750, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5750M, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751M, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5752, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5752M, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753M, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754M, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755M, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5786, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787M, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714S, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5715, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5715S, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780S, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5781, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9DXX, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9MXX, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC9100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_TIGON3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { 0, } }; static void tg3_write32(struct tg3 *tp, u32 off, u32 val) { writel(val, tp->regs + off); } static u32 tg3_read32(struct tg3 *tp, u32 off) { return (readl(tp->regs + off)); } static void tg3_write_indirect_reg32(struct tg3 *tp, u32 off, u32 val) { unsigned long flags; spin_lock_irqsave(&tp->indirect_lock, flags); g_psBus->write_pci_config(tp->pdev->nBus, tp->pdev->nDevice, tp->pdev->nFunction, TG3PCI_REG_BASE_ADDR, 4, off); g_psBus->write_pci_config(tp->pdev->nBus, tp->pdev->nDevice, tp->pdev->nFunction, TG3PCI_REG_DATA, 4, val); spin_unlock_irqrestore(&tp->indirect_lock, flags); } static void tg3_write_flush_reg32(struct tg3 *tp, u32 off, u32 val) { writel(val, tp->regs + off); readl(tp->regs + off); } static u32 tg3_read_indirect_reg32(struct tg3 *tp, u32 off) { unsigned long flags; u32 val; spin_lock_irqsave(&tp->indirect_lock, flags); g_psBus->write_pci_config(tp->pdev->nBus, tp->pdev->nDevice, tp->pdev->nFunction, TG3PCI_REG_BASE_ADDR, 4, (uint32)off); val = g_psBus->read_pci_config(tp->pdev->nBus, tp->pdev->nDevice, tp->pdev->nFunction, TG3PCI_REG_DATA, sizeof(val)); spin_unlock_irqrestore(&tp->indirect_lock, flags); return val; } static void tg3_write_indirect_mbox(struct tg3 *tp, u32 off, u32 val) { unsigned long flags; if (off == (MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW)) { g_psBus->write_pci_config(tp->pdev->nBus, tp->pdev->nDevice, tp->pdev->nFunction, TG3PCI_RCV_RET_RING_CON_IDX + TG3_64BIT_REG_LOW, 4, val); return; } if (off == (MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW)) { g_psBus->write_pci_config(tp->pdev->nBus, tp->pdev->nDevice, tp->pdev->nFunction, TG3PCI_STD_RING_PROD_IDX + TG3_64BIT_REG_LOW, 4, val); return; } spin_lock_irqsave(&tp->indirect_lock, flags); g_psBus->write_pci_config(tp->pdev->nBus, tp->pdev->nDevice, tp->pdev->nFunction, TG3PCI_REG_BASE_ADDR, 4, off + 0x5600); g_psBus->write_pci_config(tp->pdev->nBus, tp->pdev->nDevice, tp->pdev->nFunction, TG3PCI_REG_DATA, 4, val); spin_unlock_irqrestore(&tp->indirect_lock, flags); /* In indirect mode when disabling interrupts, we also need * to clear the interrupt bit in the GRC local ctrl register. */ if ((off == (MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW)) && (val == 0x1)) { g_psBus->write_pci_config(tp->pdev->nBus, tp->pdev->nDevice, tp->pdev->nFunction, TG3PCI_MISC_LOCAL_CTRL, 4, tp->grc_local_ctrl|GRC_LCLCTRL_CLEARINT); } } static u32 tg3_read_indirect_mbox(struct tg3 *tp, u32 off) { unsigned long flags; u32 val; spin_lock_irqsave(&tp->indirect_lock, flags); g_psBus->write_pci_config(tp->pdev->nBus, tp->pdev->nDevice, tp->pdev->nFunction, TG3PCI_REG_BASE_ADDR, 4, (uint32)off + 0x5600); val = g_psBus->read_pci_config(tp->pdev->nBus, tp->pdev->nDevice, tp->pdev->nFunction, TG3PCI_REG_DATA, sizeof(val)); spin_unlock_irqrestore(&tp->indirect_lock, flags); return val; } /* usec_wait specifies the wait time in usec when writing to certain registers * where it is unsafe to read back the register without some delay. * GRC_LOCAL_CTRL is one example if the GPIOs are toggled to switch power. * TG3PCI_CLOCK_CTRL is another example if the clock frequencies are changed. */ static void _tw32_flush(struct tg3 *tp, u32 off, u32 val, u32 usec_wait) { if ((tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG) || (tp->tg3_flags2 & TG3_FLG2_ICH_WORKAROUND)) /* Non-posted methods */ tp->write32(tp, off, val); else { /* Posted method */ tg3_write32(tp, off, val); if (usec_wait) udelay(usec_wait); tp->read32(tp, off); } /* Wait again after the read for the posted method to guarantee that * the wait time is met. */ if (usec_wait) udelay(usec_wait); } static inline void tw32_mailbox_flush(struct tg3 *tp, u32 off, u32 val) { tp->write32_mbox(tp, off, val); if (!(tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) && !(tp->tg3_flags2 & TG3_FLG2_ICH_WORKAROUND)) tp->read32_mbox(tp, off); } static void tg3_write32_tx_mbox(struct tg3 *tp, u32 off, u32 val) { void *mbox = tp->regs + off; writel(val, mbox); if (tp->tg3_flags & TG3_FLAG_TXD_MBOX_HWBUG) writel(val, mbox); if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) readl(mbox); } #define tw32_mailbox(reg, val) tp->write32_mbox(tp, reg, val) #define tw32_mailbox_f(reg, val) tw32_mailbox_flush(tp, (reg), (val)) #define tw32_rx_mbox(reg, val) tp->write32_rx_mbox(tp, reg, val) #define tw32_tx_mbox(reg, val) tp->write32_tx_mbox(tp, reg, val) #define tr32_mailbox(reg) tp->read32_mbox(tp, reg) #define tw32(reg,val) tp->write32(tp, reg, val) #define tw32_f(reg,val) _tw32_flush(tp,(reg),(val), 0) #define tw32_wait_f(reg,val,us) _tw32_flush(tp,(reg),(val), (us)) #define tr32(reg) tp->read32(tp, reg) static void tg3_write_mem(struct tg3 *tp, u32 off, u32 val) { unsigned long flags; spin_lock_irqsave(&tp->indirect_lock, flags); if (tp->tg3_flags & TG3_FLAG_SRAM_USE_CONFIG) { g_psBus->write_pci_config(tp->pdev->nBus, tp->pdev->nDevice, tp->pdev->nFunction, TG3PCI_MEM_WIN_BASE_ADDR, 4, off); g_psBus->write_pci_config(tp->pdev->nBus, tp->pdev->nDevice, tp->pdev->nFunction, TG3PCI_MEM_WIN_DATA, 4, val); /* Always leave this as zero. */ g_psBus->write_pci_config(tp->pdev->nBus, tp->pdev->nDevice, tp->pdev->nFunction, TG3PCI_MEM_WIN_BASE_ADDR, 4, 0); } else { tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off); tw32_f(TG3PCI_MEM_WIN_DATA, val); /* Always leave this as zero. */ tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0); } spin_unlock_irqrestore(&tp->indirect_lock, flags); } static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val) { unsigned long flags; spin_lock_irqsave(&tp->indirect_lock, flags); if (tp->tg3_flags & TG3_FLAG_SRAM_USE_CONFIG) { g_psBus->write_pci_config(tp->pdev->nBus, tp->pdev->nDevice, tp->pdev->nFunction, TG3PCI_MEM_WIN_BASE_ADDR, 4, off); *val = g_psBus->read_pci_config(tp->pdev->nBus, tp->pdev->nDevice, tp->pdev->nFunction, TG3PCI_MEM_WIN_DATA, 4); /* Always leave this as zero. */ g_psBus->write_pci_config(tp->pdev->nBus, tp->pdev->nDevice, tp->pdev->nFunction, TG3PCI_MEM_WIN_BASE_ADDR, 4, 0); } else { tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off); *val = tr32(TG3PCI_MEM_WIN_DATA); /* Always leave this as zero. */ tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0); } spin_unlock_irqrestore(&tp->indirect_lock, flags); } static void tg3_disable_ints(struct tg3 *tp) { tw32(TG3PCI_MISC_HOST_CTRL, (tp->misc_host_ctrl | MISC_HOST_CTRL_MASK_PCI_INT)); tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001); } /* Device interface */ static status_t tg3_dev_open( void* pNode, uint32 nFlags, void **pCookie ) { return 0; } static status_t tg3_dev_close( void* pNode, void* pCookie ) { return 0; } static status_t tg3_dev_ioctl( void* pNode, void* pCookie, uint32 nCommand, void* pArgs, bool bFromKernel ) { return ENOSYS; } static int tg3_dev_write( void* pNode, void* pCookie, off_t nPosition, const void* pBuffer, size_t nSize ) { return -ENOSYS; } static DeviceOperations_s g_sDevOps = { tg3_dev_open, tg3_dev_close, tg3_dev_ioctl, NULL, /* dop_read */ tg3_dev_write, NULL, /* dop_readv */ NULL, /* dop_writev */ NULL, /* dop_add_select_req */ NULL /* dop_rem_select_req */ }; #define RESET_KIND_SHUTDOWN 0 #define RESET_KIND_INIT 1 #define RESET_KIND_SUSPEND 2 #define MAX_WAIT_CNT 1000 /* To stop a block, clear the enable bit and poll till it * clears. tp->lock is held. */ static int tg3_stop_block(struct tg3 *tp, unsigned long ofs, u32 enable_bit, int silent) { unsigned int i; u32 val; if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) { switch (ofs) { case RCVLSC_MODE: case DMAC_MODE: case MBFREE_MODE: case BUFMGR_MODE: case MEMARB_MODE: /* We can't enable/disable these bits of the * 5705/5750, just say success. */ return 0; default: break; }; } val = tr32(ofs); val &= ~enable_bit; tw32_f(ofs, val); for (i = 0; i < MAX_WAIT_CNT; i++) { udelay(100); val = tr32(ofs); if ((val & enable_bit) == 0) break; } if (i == MAX_WAIT_CNT && !silent) { kerndbg( KERN_WARNING, "tg3_stop_block timed out, " "ofs=%lx enable_bit=%x\n", ofs, enable_bit); return -ENODEV; } return 0; } /* tp->lock is held. */ static int tg3_abort_hw(struct tg3 *tp, int silent) { int i, err; tg3_disable_ints(tp); tp->rx_mode &= ~RX_MODE_ENABLE; tw32_f(MAC_RX_MODE, tp->rx_mode); udelay(10); err = tg3_stop_block(tp, RCVBDI_MODE, RCVBDI_MODE_ENABLE, silent); err |= tg3_stop_block(tp, RCVLPC_MODE, RCVLPC_MODE_ENABLE, silent); err |= tg3_stop_block(tp, RCVLSC_MODE, RCVLSC_MODE_ENABLE, silent); err |= tg3_stop_block(tp, RCVDBDI_MODE, RCVDBDI_MODE_ENABLE, silent); err |= tg3_stop_block(tp, RCVDCC_MODE, RCVDCC_MODE_ENABLE, silent); err |= tg3_stop_block(tp, RCVCC_MODE, RCVCC_MODE_ENABLE, silent); err |= tg3_stop_block(tp, SNDBDS_MODE, SNDBDS_MODE_ENABLE, silent); err |= tg3_stop_block(tp, SNDBDI_MODE, SNDBDI_MODE_ENABLE, silent); err |= tg3_stop_block(tp, SNDDATAI_MODE, SNDDATAI_MODE_ENABLE, silent); err |= tg3_stop_block(tp, RDMAC_MODE, RDMAC_MODE_ENABLE, silent); err |= tg3_stop_block(tp, SNDDATAC_MODE, SNDDATAC_MODE_ENABLE, silent); err |= tg3_stop_block(tp, DMAC_MODE, DMAC_MODE_ENABLE, silent); err |= tg3_stop_block(tp, SNDBDC_MODE, SNDBDC_MODE_ENABLE, silent); tp->mac_mode &= ~MAC_MODE_TDE_ENABLE; tw32_f(MAC_MODE, tp->mac_mode); udelay(40); tp->tx_mode &= ~TX_MODE_ENABLE; tw32_f(MAC_TX_MODE, tp->tx_mode); for (i = 0; i < MAX_WAIT_CNT; i++) { udelay(100); if (!(tr32(MAC_TX_MODE) & TX_MODE_ENABLE)) break; } if (i >= MAX_WAIT_CNT) { kerndbg( KERN_WARNING, "tg3_abort_hw timed out for %s, " "TX_MODE_ENABLE will not clear MAC_TX_MODE=%08x\n", tp->dev->name, tr32(MAC_TX_MODE)); err |= -ENODEV; } err |= tg3_stop_block(tp, HOSTCC_MODE, HOSTCC_MODE_ENABLE, silent); err |= tg3_stop_block(tp, WDMAC_MODE, WDMAC_MODE_ENABLE, silent); err |= tg3_stop_block(tp, MBFREE_MODE, MBFREE_MODE_ENABLE, silent); tw32(FTQ_RESET, 0xffffffff); tw32(FTQ_RESET, 0x00000000); err |= tg3_stop_block(tp, BUFMGR_MODE, BUFMGR_MODE_ENABLE, silent); err |= tg3_stop_block(tp, MEMARB_MODE, MEMARB_MODE_ENABLE, silent); if (tp->hw_status) memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE); if (tp->hw_stats) memset(tp->hw_stats, 0, sizeof(struct tg3_hw_stats)); return err; } /* tp->lock is held. */ static int tg3_nvram_lock(struct tg3 *tp) { if (tp->tg3_flags & TG3_FLAG_NVRAM) { int i; if (tp->nvram_lock_cnt == 0) { tw32(NVRAM_SWARB, SWARB_REQ_SET1); for (i = 0; i < 8000; i++) { if (tr32(NVRAM_SWARB) & SWARB_GNT1) break; udelay(20); } if (i == 8000) { tw32(NVRAM_SWARB, SWARB_REQ_CLR1); return -ENODEV; } } tp->nvram_lock_cnt++; } return 0; } /* tp->lock is held. */ static void tg3_nvram_unlock(struct tg3 *tp) { if (tp->tg3_flags & TG3_FLAG_NVRAM) { if (tp->nvram_lock_cnt > 0) tp->nvram_lock_cnt--; if (tp->nvram_lock_cnt == 0) tw32_f(NVRAM_SWARB, SWARB_REQ_CLR1); } } /* tp->lock is held. */ static void tg3_write_sig_pre_reset(struct tg3 *tp, int kind) { tg3_write_mem(tp, NIC_SRAM_FIRMWARE_MBOX, NIC_SRAM_FIRMWARE_MBOX_MAGIC1); if (tp->tg3_flags2 & TG3_FLG2_ASF_NEW_HANDSHAKE) { switch (kind) { case RESET_KIND_INIT: tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX, DRV_STATE_START); break; case RESET_KIND_SHUTDOWN: tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX, DRV_STATE_UNLOAD); break; case RESET_KIND_SUSPEND: tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX, DRV_STATE_SUSPEND); break; default: break; }; } } /* tp->lock is held. */ static void tg3_write_sig_post_reset(struct tg3 *tp, int kind) { if (tp->tg3_flags2 & TG3_FLG2_ASF_NEW_HANDSHAKE) { switch (kind) { case RESET_KIND_INIT: tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX, DRV_STATE_START_DONE); break; case RESET_KIND_SHUTDOWN: tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX, DRV_STATE_UNLOAD_DONE); break; default: break; }; } } /* tp->lock is held. */ static void tg3_write_sig_legacy(struct tg3 *tp, int kind) { if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) { switch (kind) { case RESET_KIND_INIT: tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX, DRV_STATE_START); break; case RESET_KIND_SHUTDOWN: tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX, DRV_STATE_UNLOAD); break; case RESET_KIND_SUSPEND: tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX, DRV_STATE_SUSPEND); break; default: break; }; } } static void tg3_stop_fw(struct tg3 *); /* tp->lock is held. */ static int tg3_chip_reset(struct tg3 *tp) { u32 val; void (*write_op)(struct tg3 *, u32, u32); int i; tg3_nvram_lock(tp); /* No matching tg3_nvram_unlock() after this because * chip reset below will undo the nvram lock. */ tp->nvram_lock_cnt = 0; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) tw32(GRC_FASTBOOT_PC, 0); /* * We must avoid the readl() that normally takes place. * It locks machines, causes machine checks, and other * fun things. So, temporarily disable the 5701 * hardware workaround, while we do the reset. */ write_op = tp->write32; if (write_op == tg3_write_flush_reg32) tp->write32 = tg3_write32; /* do the reset */ val = GRC_MISC_CFG_CORECLK_RESET; if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) { if (tr32(0x7e2c) == 0x60) { tw32(0x7e2c, 0x20); } if (tp->pci_chip_rev_id != CHIPREV_ID_5750_A0) { tw32(GRC_MISC_CFG, (1 << 29)); val |= (1 << 29); } } if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) val |= GRC_MISC_CFG_KEEP_GPHY_POWER; tw32(GRC_MISC_CFG, val); /* restore 5701 hardware bug workaround write method */ tp->write32 = write_op; /* Unfortunately, we have to delay before the PCI read back. * Some 575X chips even will not respond to a PCI cfg access * when the reset command is given to the chip. * * How do these hardware designers expect things to work * properly if the PCI write is posted for a long period * of time? It is always necessary to have some method by * which a register read back can occur to push the write * out which does the reset. * * For most tg3 variants the trick below was working. * Ho hum... */ udelay(120); /* Flush PCI posted writes. The normal MMIO registers * are inaccessible at this time so this is the only * way to make this reliably (actually, this is no longer * the case, see above). I tried to use indirect * register read/write but this upset some 5701 variants. */ val = g_psBus->read_pci_config(tp->pdev->nBus, tp->pdev->nDevice, tp->pdev->nFunction, PCI_COMMAND, 4); udelay(120); if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) { if (tp->pci_chip_rev_id == CHIPREV_ID_5750_A0) { int i; u32 cfg_val; /* Wait for link training to complete. */ for (i = 0; i < 5000; i++) udelay(100); cfg_val = g_psBus->read_pci_config(tp->pdev->nBus, tp->pdev->nDevice, tp->pdev->nFunction, 0xc4, 4); g_psBus->write_pci_config(tp->pdev->nBus, tp->pdev->nDevice, tp->pdev->nFunction, 0xc4, 4, cfg_val | (1 << 15)); } /* Set PCIE max payload size and clear error status. */ g_psBus->write_pci_config(tp->pdev->nBus, tp->pdev->nDevice, tp->pdev->nFunction, 0xd8, 4, 0xf5000); } /* Re-enable indirect register accesses. */ g_psBus->write_pci_config(tp->pdev->nBus, tp->pdev->nDevice, tp->pdev->nFunction, TG3PCI_MISC_HOST_CTRL, 4, tp->misc_host_ctrl); /* Set MAX PCI retry to zero. */ val = (PCISTATE_ROM_ENABLE | PCISTATE_ROM_RETRY_ENABLE); if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 && (tp->tg3_flags & TG3_FLAG_PCIX_MODE)) val |= PCISTATE_RETRY_SAME_DMA; g_psBus->write_pci_config(tp->pdev->nBus, tp->pdev->nDevice, tp->pdev->nFunction, TG3PCI_PCISTATE, 4, val); pci_restore_state(tp->pdev); /* Make sure PCI-X relaxed ordering bit is clear. */ val = g_psBus->read_pci_config(tp->pdev->nBus, tp->pdev->nDevice, tp->pdev->nFunction, TG3PCI_X_CAPS, 4); val &= ~PCIX_CAPS_RELAXED_ORDERING; g_psBus->write_pci_config(tp->pdev->nBus, tp->pdev->nDevice, tp->pdev->nFunction, TG3PCI_X_CAPS, 4, val); if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) { u32 val; /* Chip reset on 5780 will reset MSI enable bit, * so need to restore it. */ if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) { u16 ctrl; ctrl = g_psBus->read_pci_config(tp->pdev->nBus, tp->pdev->nDevice, tp->pdev->nFunction, tp->msi_cap + PCI_MSI_FLAGS, 2); g_psBus->write_pci_config(tp->pdev->nBus, tp->pdev->nDevice, tp->pdev->nFunction, tp->msi_cap + PCI_MSI_FLAGS, 2, ctrl | PCI_MSI_FLAGS_ENABLE); val = tr32(MSGINT_MODE); tw32(MSGINT_MODE, val | MSGINT_MODE_ENABLE); } val = tr32(MEMARB_MODE); tw32(MEMARB_MODE, val | MEMARB_MODE_ENABLE); } else tw32(MEMARB_MODE, MEMARB_MODE_ENABLE); if (tp->pci_chip_rev_id == CHIPREV_ID_5750_A3) { tg3_stop_fw(tp); tw32(0x5000, 0x400); } tw32(GRC_MODE, tp->grc_mode); if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A0) { u32 val = tr32(0xc4); tw32(0xc4, val | (1 << 15)); } if ((tp->nic_sram_data_cfg & NIC_SRAM_DATA_CFG_MINI_PCI) != 0 && GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) { tp->pci_clock_ctrl |= CLOCK_CTRL_CLKRUN_OENABLE; if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A0) tp->pci_clock_ctrl |= CLOCK_CTRL_FORCE_CLKRUN; tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl); } if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) { tp->mac_mode = MAC_MODE_PORT_MODE_TBI; tw32_f(MAC_MODE, tp->mac_mode); } else if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) { tp->mac_mode = MAC_MODE_PORT_MODE_GMII; tw32_f(MAC_MODE, tp->mac_mode); } else tw32_f(MAC_MODE, 0); udelay(40); /* Wait for firmware initialization to complete. */ for (i = 0; i < 100000; i++) { tg3_read_mem(tp, NIC_SRAM_FIRMWARE_MBOX, &val); if (val == ~NIC_SRAM_FIRMWARE_MBOX_MAGIC1) break; udelay(10); } /* Chip might not be fitted with firmare. Some Sun onboard * parts are configured like that. So don't signal the timeout * of the above loop as an error, but do report the lack of * running firmware once. */ if (i >= 100000 && !(tp->tg3_flags2 & TG3_FLG2_NO_FWARE_REPORTED)) { tp->tg3_flags2 |= TG3_FLG2_NO_FWARE_REPORTED; kerndbg( KERN_INFO, "%s: No firmware running.\n", tp->dev->name); } if ((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) && tp->pci_chip_rev_id != CHIPREV_ID_5750_A0) { u32 val = tr32(0x7c00); tw32(0x7c00, val | (1 << 25)); } /* Reprobe ASF enable state. */ tp->tg3_flags &= ~TG3_FLAG_ENABLE_ASF; tp->tg3_flags2 &= ~TG3_FLG2_ASF_NEW_HANDSHAKE; tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val); if (val == NIC_SRAM_DATA_SIG_MAGIC) { u32 nic_cfg; tg3_read_mem(tp, NIC_SRAM_DATA_CFG, &nic_cfg); if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE) { tp->tg3_flags |= TG3_FLAG_ENABLE_ASF; if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) tp->tg3_flags2 |= TG3_FLG2_ASF_NEW_HANDSHAKE; } } return 0; } /* tp->lock is held. */ static void tg3_stop_fw(struct tg3 *tp) { if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) { u32 val; int i; tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_PAUSE_FW); val = tr32(GRC_RX_CPU_EVENT); val |= (1 << 14); tw32(GRC_RX_CPU_EVENT, val); /* Wait for RX cpu to ACK the event. */ for (i = 0; i < 100; i++) { if (!(tr32(GRC_RX_CPU_EVENT) & (1 << 14))) break; udelay(1); } } } /* tp->lock is held. */ static int tg3_halt(struct tg3 *tp, int kind, int silent) { int err; tg3_stop_fw(tp); tg3_write_sig_pre_reset(tp, kind); tg3_abort_hw(tp, silent); err = tg3_chip_reset(tp); tg3_write_sig_legacy(tp, kind); tg3_write_sig_post_reset(tp, kind); if (err) return err; return 0; } static int tg3_get_invariants(struct tg3 *tp) { /* Not yet ported */ return 0; } static int tg3_get_device_address(struct tg3 *tp) { /* Not yet ported */ return 0; } static int tg3_test_dma(struct tg3 *tp) { /* Not yet ported */ return 0; } static void tg3_init_link_config(struct tg3 *tp) { tp->link_config.advertising = (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full | ADVERTISED_Autoneg | ADVERTISED_MII); tp->link_config.speed = SPEED_INVALID; tp->link_config.duplex = DUPLEX_INVALID; tp->link_config.autoneg = AUTONEG_ENABLE; tp->link_config.active_speed = SPEED_INVALID; tp->link_config.active_duplex = DUPLEX_INVALID; tp->link_config.phy_is_low_power = 0; tp->link_config.orig_speed = SPEED_INVALID; tp->link_config.orig_duplex = DUPLEX_INVALID; tp->link_config.orig_autoneg = AUTONEG_INVALID; } static void tg3_init_bufmgr_config(struct tg3 *tp) { if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) { tp->bufmgr_config.mbuf_read_dma_low_water = DEFAULT_MB_RDMA_LOW_WATER_5705; tp->bufmgr_config.mbuf_mac_rx_low_water = DEFAULT_MB_MACRX_LOW_WATER_5705; tp->bufmgr_config.mbuf_high_water = DEFAULT_MB_HIGH_WATER_5705; tp->bufmgr_config.mbuf_read_dma_low_water_jumbo = DEFAULT_MB_RDMA_LOW_WATER_JUMBO_5780; tp->bufmgr_config.mbuf_mac_rx_low_water_jumbo = DEFAULT_MB_MACRX_LOW_WATER_JUMBO_5780; tp->bufmgr_config.mbuf_high_water_jumbo = DEFAULT_MB_HIGH_WATER_JUMBO_5780; } else { tp->bufmgr_config.mbuf_read_dma_low_water = DEFAULT_MB_RDMA_LOW_WATER; tp->bufmgr_config.mbuf_mac_rx_low_water = DEFAULT_MB_MACRX_LOW_WATER; tp->bufmgr_config.mbuf_high_water = DEFAULT_MB_HIGH_WATER; tp->bufmgr_config.mbuf_read_dma_low_water_jumbo = DEFAULT_MB_RDMA_LOW_WATER_JUMBO; tp->bufmgr_config.mbuf_mac_rx_low_water_jumbo = DEFAULT_MB_MACRX_LOW_WATER_JUMBO; tp->bufmgr_config.mbuf_high_water_jumbo = DEFAULT_MB_HIGH_WATER_JUMBO; } tp->bufmgr_config.dma_low_water = DEFAULT_DMA_LOW_WATER; tp->bufmgr_config.dma_high_water = DEFAULT_DMA_HIGH_WATER; } static char * tg3_phy_string(struct tg3 *tp) { switch (tp->phy_id & PHY_ID_MASK) { case PHY_ID_BCM5400: return "5400"; case PHY_ID_BCM5401: return "5401"; case PHY_ID_BCM5411: return "5411"; case PHY_ID_BCM5701: return "5701"; case PHY_ID_BCM5703: return "5703"; case PHY_ID_BCM5704: return "5704"; case PHY_ID_BCM5705: return "5705"; case PHY_ID_BCM5750: return "5750"; case PHY_ID_BCM5752: return "5752"; case PHY_ID_BCM5714: return "5714"; case PHY_ID_BCM5780: return "5780"; case PHY_ID_BCM5755: return "5755"; case PHY_ID_BCM5787: return "5787"; case PHY_ID_BCM8002: return "8002/serdes"; case 0: return "serdes"; default: return "unknown"; }; } static char * tg3_bus_string(struct tg3 *tp, char *str) { if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) { strcpy(str, "PCI Express"); return str; } else if (tp->tg3_flags & TG3_FLAG_PCIX_MODE) { u32 clock_ctrl = tr32(TG3PCI_CLOCK_CTRL) & 0x1f; strcpy(str, "PCIX:"); if ((clock_ctrl == 7) || ((tr32(GRC_MISC_CFG) & GRC_MISC_CFG_BOARD_ID_MASK) == GRC_MISC_CFG_BOARD_ID_5704CIOBE)) strcat(str, "133MHz"); else if (clock_ctrl == 0) strcat(str, "33MHz"); else if (clock_ctrl == 2) strcat(str, "50MHz"); else if (clock_ctrl == 4) strcat(str, "66MHz"); else if (clock_ctrl == 6) strcat(str, "100MHz"); } else { strcpy(str, "PCI:"); if (tp->tg3_flags & TG3_FLAG_PCI_HIGH_SPEED) strcat(str, "66MHz"); else strcat(str, "33MHz"); } if (tp->tg3_flags & TG3_FLAG_PCI_32BIT) strcat(str, ":32-bit"); else strcat(str, ":64-bit"); return str; } static PCI_Info_s * tg3_find_peer(struct tg3 *tp) { /* Not yet ported */ return NULL; } static int tg3_init_one( PCI_Info_s *pDev, struct net_device *pNetDev ) { int i, nError = 0; struct tg3 *tp; unsigned long tg3reg_base, tg3reg_len; uint8 pm_cap; char str[40]; /* Enable device */ uint32 nOldCommand, nNewCommand; nOldCommand = g_psBus->read_pci_config( pDev->nBus, pDev->nDevice, pDev->nFunction, PCI_COMMAND, 2 ); nNewCommand = nOldCommand | ( PCI_COMMAND_MEMORY & 7); if( nOldCommand != nNewCommand ) g_psBus->write_pci_config( pDev->nBus, pDev->nDevice, pDev->nFunction, PCI_COMMAND, 2, nNewCommand ); g_psBus->enable_pci_master( pDev->nBus, pDev->nDevice, pDev->nFunction ); /* Find power-management capability. */ pm_cap = g_psBus->get_pci_capability( pDev->nBus, pDev->nDevice, pDev->nFunction, PCI_CAP_ID_PM ); if( pm_cap == 0 ) { kerndbg( KERN_WARNING, "tg3: Cannot find PowerManagement capability, aborting.\n"); nError = -EIO; goto err_out; } tg3reg_base = pDev->u.h0.nBase0 & PCI_ADDRESS_MEMORY_32_MASK; tg3reg_len = pci_resource_len( pDev, 0 ); tp = netdev_priv(pNetDev); tp->pdev = pDev; tp->dev = pNetDev; tp->pm_cap = pm_cap; tp->mac_mode = TG3_DEF_MAC_MODE; tp->rx_mode = TG3_DEF_RX_MODE; tp->tx_mode = TG3_DEF_TX_MODE; tp->mi_mode = MAC_MI_MODE_BASE; /* The word/byte swap controls here control register access byte * swapping. DMA data byte swapping is controlled in the GRC_MODE * setting below. */ tp->misc_host_ctrl = MISC_HOST_CTRL_MASK_PCI_INT | MISC_HOST_CTRL_WORD_SWAP | MISC_HOST_CTRL_INDIR_ACCESS | MISC_HOST_CTRL_PCISTATE_RW; /* The NONFRM (non-frame) byte/word swap controls take effect * on descriptor entries, anything which isn't packet data. * * The StrongARM chips on the board (one for tx, one for rx) * are running in big-endian mode. */ tp->grc_mode = (GRC_MODE_WSWAP_DATA | GRC_MODE_BSWAP_DATA | GRC_MODE_WSWAP_NONFRM_DATA); spinlock_init(&tp->lock, "tg3"); spinlock_init(&tp->indirect_lock, "tg3_indirect"); /* Map the device registers into memory. The address is page-aligned. */ tp->reg_area = create_area ("tg3_register", (void **)&tp->regs, tg3reg_len, tg3reg_len, AREA_KERNEL | AREA_ANY_ADDRESS, AREA_NO_LOCK ); if( tp->reg_area < 0 ) { kerndbg ( KERN_DEBUG, "tg3: failed to create register area (%d)\n", tp->reg_area ); nError = -EIO; goto err_out; } if( remap_area (tp->reg_area, (void *)(tg3reg_base & PAGE_MASK) ) < 0 ) { kerndbg( KERN_DEBUG, "tg3: failed to remap register area (%d)\n", tp->reg_area ); nError = -EIO; goto err_out; } tp->regs = (void*)( (uint32)tp->regs + ( tg3reg_base - ( tg3reg_base & PAGE_MASK ) ) ); tg3_init_link_config(tp); tp->rx_pending = TG3_DEF_RX_RING_PENDING; tp->rx_jumbo_pending = TG3_DEF_RX_JUMBO_RING_PENDING; tp->tx_pending = TG3_DEF_TX_RING_PENDING; nError = tg3_get_invariants(tp); if( nError ) { kerndbg(KERN_WARNING, "tg3: Problem fetching invariants of chip, aborting.\n"); goto err_out_iounmap; } tg3_init_bufmgr_config(tp); if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A1 && !(tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) && !(tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH)) { tp->tg3_flags2 |= TG3_FLG2_MAX_RXPEND_64; tp->rx_pending = 63; } if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) || (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714)) tp->pdev_peer = tg3_find_peer(tp); nError = tg3_get_device_address(tp); if( nError ) { kerndbg( KERN_WARNING, "tg3: Could not obtain valid ethernet address, aborting.\n"); goto err_out_iounmap; } /* * Reset chip in case UNDI or EFI driver did not shutdown * DMA self test will enable WDMAC and we'll see (spurious) * pending DMA on the PCI bus at that point. */ if ((tr32(HOSTCC_MODE) & HOSTCC_MODE_ENABLE) || (tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) { pci_save_state(tp->pdev); tw32(MEMARB_MODE, MEMARB_MODE_ENABLE); tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); } nError = tg3_test_dma(tp); if( nError ) { kerndbg( KERN_WARNING, "tg3: DMA engine test failed, aborting.\n"); goto err_out_iounmap; } tp->tg3_flags &= ~TG3_FLAG_RX_CHECKSUMS; /* flow control autonegotiation is default behavior */ tp->tg3_flags |= TG3_FLAG_PAUSE_AUTONEG; /* Now that we have fully setup the chip, save away a snapshot * of the PCI config space. We need to restore this after * GRC_MISC_CFG core clock resets and some resume events. */ pci_save_state(tp->pdev); printk( "%s: Tigon3 [partno(%s) rev %04x PHY(%s)] (%s) %sBaseT Ethernet ", pNetDev->name, tp->board_part_number, tp->pci_chip_rev_id, tg3_phy_string(tp), tg3_bus_string(tp, str), (tp->tg3_flags & TG3_FLAG_10_100_ONLY) ? "10/100" : "10/100/1000"); for (i = 0; i < 6; i++) printk("%2.2x%c", pNetDev->dev_addr[i], i == 5 ? '\n' : ':'); printk( "%s: RXcsums[%d] LinkChgREG[%d] " "MIirq[%d] ASF[%d] Split[%d] WireSpeed[%d] " "TSOcap[%d] \n", pNetDev->name, (tp->tg3_flags & TG3_FLAG_RX_CHECKSUMS) != 0, (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) != 0, (tp->tg3_flags & TG3_FLAG_USE_MI_INTERRUPT) != 0, (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) != 0, (tp->tg3_flags & TG3_FLAG_SPLIT_MODE) != 0, (tp->tg3_flags2 & TG3_FLG2_NO_ETH_WIRE_SPEED) == 0, (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) != 0); printk( "%s: dma_rwctrl[%08x]\n", pNetDev->name, tp->dma_rwctrl); netif_carrier_off(tp->dev); return 0; err_out_iounmap: if( tp->reg_area ) delete_area( tp->reg_area ); tp->regs = NULL; err_out: return nError; } static int tg3_probe( int nDeviceID ) { int nCardsFound = 0; PCI_Info_s sInfo; int i, j; for( i = 0; g_psBus->get_pci_info( &sInfo, i ) == 0; ++i ) { for( j = 0; tg3_pci_tbl[j].vendor_id != 0; j++ ) { if ( sInfo.nVendorID == tg3_pci_tbl[j].vendor_id && sInfo.nDeviceID == tg3_pci_tbl[j].device_id) { struct net_device *pNetDev = NULL; struct tg3 *pPrivate = NULL; if( claim_device( nDeviceID, sInfo.nHandle, "Broadcom Tigon3", DEVICE_NET ) < 0 ) continue; pNetDev = kmalloc( sizeof( *pNetDev ), MEMF_KERNEL | MEMF_CLEAR ); if( NULL == pNetDev ) { kerndbg( KERN_WARNING, "tg3_probe(): Could not allocate memory for device.\n" ); continue; } pNetDev->name = "tg3"; pNetDev->device_handle = nDeviceID; pNetDev->irq = sInfo.u.h0.nInterruptLine; pPrivate = kmalloc( sizeof( *pPrivate ), MEMF_KERNEL | MEMF_CLEAR ); if( NULL == pPrivate ) { kerndbg( KERN_WARNING, "tg3_probe(): Could not allocate memory for device.\n" ); kfree( pNetDev ); continue; } pNetDev->priv = pPrivate; set_device_data( sInfo.nHandle, pNetDev ); if( tg3_init_one( &sInfo, pNetDev ) == 0 ) { char zNodePath[64]; sprintf( zNodePath, "net/eth/tg3-%d", nCardsFound ); kerndbg( KERN_DEBUG, "tg3_probe(): Create node %s\n", zNodePath ); pNetDev->node_handle = create_device_node( nDeviceID, sInfo.nHandle, zNodePath, &g_sDevOps, pNetDev ); nCardsFound++; } } } } if( nCardsFound == 0 ) disable_device( nDeviceID ); return nCardsFound ? 0 : -ENODEV; } /* Driver management */ status_t device_init( int nDeviceID ) { /* Get PCI bus */ g_psBus = get_busmanager( PCI_BUS_NAME, PCI_BUS_VERSION ); if( g_psBus == NULL ) return -ENODEV; return tg3_probe( nDeviceID ); } status_t device_uninit( int nDeviceID ) { return 0; }