/* * 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) /* 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 /* tp->lock is held. */ static int tg3_halt(struct tg3 *tp, int kind, int silent) { /* Not yet ported */ 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; }