📄 tg3.c
字号:
return 0;}static int tg3_abort_hw(struct tg3 *tp){ int i, err; tg3_disable_ints(tp); tp->rx_mode &= ~RX_MODE_ENABLE; tw32_carefully(MAC_RX_MODE, tp->rx_mode); err = tg3_stop_block(tp, RCVBDI_MODE, RCVBDI_MODE_ENABLE); err |= tg3_stop_block(tp, RCVLPC_MODE, RCVLPC_MODE_ENABLE); err |= tg3_stop_block(tp, RCVLSC_MODE, RCVLSC_MODE_ENABLE); err |= tg3_stop_block(tp, RCVDBDI_MODE, RCVDBDI_MODE_ENABLE); err |= tg3_stop_block(tp, RCVDCC_MODE, RCVDCC_MODE_ENABLE); err |= tg3_stop_block(tp, RCVCC_MODE, RCVCC_MODE_ENABLE); err |= tg3_stop_block(tp, SNDBDS_MODE, SNDBDS_MODE_ENABLE); err |= tg3_stop_block(tp, SNDBDI_MODE, SNDBDI_MODE_ENABLE); err |= tg3_stop_block(tp, SNDDATAI_MODE, SNDDATAI_MODE_ENABLE); err |= tg3_stop_block(tp, RDMAC_MODE, RDMAC_MODE_ENABLE); err |= tg3_stop_block(tp, SNDDATAC_MODE, SNDDATAC_MODE_ENABLE); err |= tg3_stop_block(tp, SNDBDC_MODE, SNDBDC_MODE_ENABLE); if (err) goto out; tp->mac_mode &= ~MAC_MODE_TDE_ENABLE; tw32_carefully(MAC_MODE, tp->mac_mode); tp->tx_mode &= ~TX_MODE_ENABLE; tw32_carefully(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) { printf("tg3_abort_hw timed out TX_MODE_ENABLE will not clear MAC_TX_MODE=%x\n", tr32(MAC_TX_MODE)); return -ENODEV; } err = tg3_stop_block(tp, HOSTCC_MODE, HOSTCC_MODE_ENABLE); err |= tg3_stop_block(tp, WDMAC_MODE, WDMAC_MODE_ENABLE); err |= tg3_stop_block(tp, MBFREE_MODE, MBFREE_MODE_ENABLE); tw32(FTQ_RESET, 0xffffffff); tw32(FTQ_RESET, 0x00000000); err |= tg3_stop_block(tp, BUFMGR_MODE, BUFMGR_MODE_ENABLE); err |= tg3_stop_block(tp, MEMARB_MODE, MEMARB_MODE_ENABLE); if (err) goto out; memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE);out: return err;}static void tg3_chip_reset(struct tg3 *tp){ uint32_t val; if (!(tp->tg3_flags2 & TG3_FLG2_SUN_5704)) { /* Force NVRAM to settle. * This deals with a chip bug which can result in EEPROM * corruption. */ if (tp->tg3_flags & TG3_FLAG_NVRAM) { int i; tw32(NVRAM_SWARB, SWARB_REQ_SET1); for (i = 0; i < 100000; i++) { if (tr32(NVRAM_SWARB) & SWARB_GNT1) break; udelay(10); } } } /* In Etherboot we don't need to worry about the 5701 * REG_WRITE_BUG because we do all register writes indirectly. */ /* do the reset */ val = GRC_MISC_CFG_CORECLK_RESET; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) val |= GRC_MISC_CFG_KEEP_GPHY_POWER; tw32(GRC_MISC_CFG, val); /* Flush PCI posted writes. The normal MMIO registers * are inaccessible at this time so this is the only * way to make this reliably. I tried to use indirect * register read/write but this upset some 5701 variants. */ pci_read_config_dword(tp->pdev, PCI_COMMAND, &val); udelay(120); /* Re-enable indirect register accesses. */ pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL, 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; pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, val); pci_restore_state(tp->pdev, tp->pci_cfg_state); /* Make sure PCI-X relaxed ordering bit is clear. */ pci_read_config_dword(tp->pdev, TG3PCI_X_CAPS, &val); val &= ~PCIX_CAPS_RELAXED_ORDERING; pci_write_config_dword(tp->pdev, TG3PCI_X_CAPS, val); tw32(MEMARB_MODE, MEMARB_MODE_ENABLE); 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_FORCE_CLKRUN | CLOCK_CTRL_CLKRUN_OENABLE); tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl); } tw32(TG3PCI_MISC_HOST_CTRL, tp->misc_host_ctrl);}static void tg3_stop_fw(struct tg3 *tp){ if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) { uint32_t val; int i; tg3_write_mem(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); } }}static int tg3_restart_fw(struct tg3 *tp, uint32_t state){ uint32_t val; int i; tg3_write_mem(NIC_SRAM_FIRMWARE_MBOX, NIC_SRAM_FIRMWARE_MBOX_MAGIC1); /* Wait for firmware initialization to complete. */ for (i = 0; i < 100000; i++) { tg3_read_mem(NIC_SRAM_FIRMWARE_MBOX, &val); if (val == ~NIC_SRAM_FIRMWARE_MBOX_MAGIC1) break; udelay(10); } if (i >= 100000 && !(tp->tg3_flags2 & TG3_FLG2_SUN_5704)) { printf("Firmware will not restart magic=%x\n", val); return -ENODEV; } if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) { state = DRV_STATE_SUSPEND; } tg3_write_mem(NIC_SRAM_FW_DRV_STATE_MBOX, state); return 0;}static int tg3_halt(struct tg3 *tp){ tg3_stop_fw(tp); tg3_abort_hw(tp); tg3_chip_reset(tp); return tg3_restart_fw(tp, DRV_STATE_UNLOAD);}static void __tg3_set_mac_addr(struct tg3 *tp){ uint32_t addr_high, addr_low; int i; addr_high = ((tp->nic->node_addr[0] << 8) | tp->nic->node_addr[1]); addr_low = ((tp->nic->node_addr[2] << 24) | (tp->nic->node_addr[3] << 16) | (tp->nic->node_addr[4] << 8) | (tp->nic->node_addr[5] << 0)); for (i = 0; i < 4; i++) { tw32(MAC_ADDR_0_HIGH + (i * 8), addr_high); tw32(MAC_ADDR_0_LOW + (i * 8), addr_low); } if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700) && (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) && (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705)) { for(i = 0; i < 12; i++) { tw32(MAC_EXTADDR_0_HIGH + (i * 8), addr_high); tw32(MAC_EXTADDR_0_LOW + (i * 8), addr_low); } } addr_high = (tp->nic->node_addr[0] + tp->nic->node_addr[1] + tp->nic->node_addr[2] + tp->nic->node_addr[3] + tp->nic->node_addr[4] + tp->nic->node_addr[5]) & TX_BACKOFF_SEED_MASK; tw32(MAC_TX_BACKOFF_SEED, addr_high);}static void tg3_set_bdinfo(struct tg3 *tp, uint32_t bdinfo_addr, dma_addr_t mapping, uint32_t maxlen_flags, uint32_t nic_addr){ tg3_write_mem((bdinfo_addr + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_HIGH), ((uint64_t) mapping >> 32)); tg3_write_mem((bdinfo_addr + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_LOW), ((uint64_t) mapping & 0xffffffff)); tg3_write_mem((bdinfo_addr + TG3_BDINFO_MAXLEN_FLAGS), maxlen_flags); if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) { tg3_write_mem((bdinfo_addr + TG3_BDINFO_NIC_ADDR), nic_addr); }}static void tg3_init_rings(struct tg3 *tp){ unsigned i; /* Zero out the tg3 variables */ memset(&tg3_bss, 0, sizeof(tg3_bss)); tp->rx_std = &tg3_bss.rx_std[0]; tp->rx_rcb = &tg3_bss.rx_rcb[0]; tp->tx_ring = &tg3_bss.tx_ring[0]; tp->hw_status = &tg3_bss.hw_status; tp->hw_stats = &tg3_bss.hw_stats; tp->mac_mode = 0; /* Initialize tx/rx rings for packet processing. * * The chip has been shut down and the driver detached from * the networking, so no interrupts or new tx packets will * end up in the driver. */ /* Initialize invariants of the rings, we only set this * stuff once. This works because the card does not * write into the rx buffer posting rings. */ for (i = 0; i < TG3_RX_RING_SIZE; i++) { struct tg3_rx_buffer_desc *rxd; rxd = &tp->rx_std[i]; rxd->idx_len = (RX_PKT_BUF_SZ - 2 - 64) << RXD_LEN_SHIFT; rxd->type_flags = (RXD_FLAG_END << RXD_FLAGS_SHIFT); rxd->opaque = (RXD_OPAQUE_RING_STD | (i << RXD_OPAQUE_INDEX_SHIFT)); /* Note where the receive buffer for the ring is placed */ rxd->addr_hi = 0; rxd->addr_lo = virt_to_bus( &tg3_bss.rx_bufs[i%TG3_DEF_RX_RING_PENDING][2]); }}#define TG3_WRITE_SETTINGS(TABLE) \do { \ const uint32_t *_table, *_end; \ _table = TABLE; \ _end = _table + sizeof(TABLE)/sizeof(TABLE[0]); \ for(; _table < _end; _table += 2) { \ tw32(_table[0], _table[1]); \ } \} while(0)/* initialize/reset the tg3 */static int tg3_setup_hw(struct tg3 *tp){ uint32_t val, rdmac_mode; int i, err, limit; /* Simply don't support setups with extremly buggy firmware in etherboot */ if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0) { printf("Error 5701_A0 firmware bug detected\n"); return -EINVAL; } tg3_disable_ints(tp); /* Originally this was all in tg3_init_hw */ /* Force the chip into D0. */ tg3_set_power_state_0(tp); tg3_switch_clocks(tp); tw32(TG3PCI_MEM_WIN_BASE_ADDR, 0); /* Originally this was all in tg3_reset_hw */ tg3_stop_fw(tp); /* No need to call tg3_abort_hw here, it is called before tg3_setup_hw. */ tg3_chip_reset(tp); tw32(GRC_MODE, tp->grc_mode); /* Redundant? */ err = tg3_restart_fw(tp, DRV_STATE_START); if (err) return err; if (tp->phy_id == PHY_ID_SERDES) { tp->mac_mode = MAC_MODE_PORT_MODE_TBI; } tw32_carefully(MAC_MODE, tp->mac_mode); /* This works around an issue with Athlon chipsets on * B3 tigon3 silicon. This bit has no effect on any * other revision. */ tp->pci_clock_ctrl |= CLOCK_CTRL_DELAY_PCI_GRANT; tw32_carefully(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl); if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 && (tp->tg3_flags & TG3_FLAG_PCIX_MODE)) { val = tr32(TG3PCI_PCISTATE); val |= PCISTATE_RETRY_SAME_DMA; tw32(TG3PCI_PCISTATE, val); } /* Descriptor ring init may make accesses to the * NIC SRAM area to setup the TX descriptors, so we * can only do this after the hardware has been * successfully reset. */ tg3_init_rings(tp); /* Clear statistics/status block in chip */ if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) { for (i = NIC_SRAM_STATS_BLK; i < NIC_SRAM_STATUS_BLK + TG3_HW_STATUS_SIZE; i += sizeof(uint32_t)) { tg3_write_mem(i, 0); udelay(40); } } /* This value is determined during the probe time DMA * engine test, tg3_setup_dma. */ tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl); tp->grc_mode &= ~(GRC_MODE_HOST_SENDBDS | GRC_MODE_4X_NIC_SEND_RINGS | GRC_MODE_NO_TX_PHDR_CSUM | GRC_MODE_NO_RX_PHDR_CSUM); tp->grc_mode |= GRC_MODE_HOST_SENDBDS; tp->grc_mode |= GRC_MODE_NO_TX_PHDR_CSUM; tp->grc_mode |= GRC_MODE_NO_RX_PHDR_CSUM; tw32(GRC_MODE, tp->grc_mode | (GRC_MODE_IRQ_ON_MAC_ATTN | GRC_MODE_HOST_STACKUP)); /* Setup the timer prescalar register. Clock is always 66Mhz. */ tw32(GRC_MISC_CFG, (65 << GRC_MISC_CFG_PRESCALAR_SHIFT)); /* Initialize MBUF/DESC pool. */ if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) { tw32(BUFMGR_MB_POOL_ADDR, NIC_SRAM_MBUF_POOL_BASE); if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) tw32(BUFMGR_MB_POOL_SIZE, NIC_SRAM_MBUF_POOL_SIZE64); else tw32(BUFMGR_MB_POOL_SIZE, NIC_SRAM_MBUF_POOL_SIZE96); tw32(BUFMGR_DMA_DESC_POOL_ADDR, NIC_SRAM_DMA_DESC_POOL_BASE); tw32(BUFMGR_DMA_DESC_POOL_SIZE, NIC_SRAM_DMA_DESC_POOL_SIZE); } if (!(tp->tg3_flags & TG3_FLAG_JUMBO_ENABLE)) { tw32(BUFMGR_MB_RDMA_LOW_WATER, tp->bufmgr_config.mbuf_read_dma_low_water); tw32(BUFMGR_MB_MACRX_LOW_WATER, tp->bufmgr_config.mbuf_mac_rx_low_water); tw32(BUFMGR_MB_HIGH_WATER, tp->bufmgr_config.mbuf_high_water); } else { tw32(BUFMGR_MB_RDMA_LOW_WATER, tp->bufmgr_config.mbuf_read_dma_low_water_jumbo); tw32(BUFMGR_MB_MACRX_LOW_WATER, tp->bufmgr_config.mbuf_mac_rx_low_water_jumbo); tw32(BUFMGR_MB_HIGH_WATER, tp->bufmgr_config.mbuf_high_water_jumbo); } tw32(BUFMGR_DMA_LOW_WATER, tp->bufmgr_config.dma_low_water); tw32(BUFMGR_DMA_HIGH_WATER, tp->bufmgr_config.dma_high_water); tw32(BUFMGR_MODE, BUFMGR_MODE_ENABLE | BUFMGR_MODE_ATTN_ENABLE); for (i = 0; i < 2000; i++) { if (tr32(BUFMGR_MODE) & BUFMGR_MODE_ENABLE) break; udelay(10); } if (i >= 2000) { printf("tg3_setup_hw cannot enable BUFMGR\n"); return -ENODEV; } tw32(FTQ_RESET, 0xffffffff); tw32(FTQ_RESET, 0x00000000); for (i = 0; i < 2000; i++) { if (tr32(FTQ_RESET) == 0x00000000) break; udelay(10); } if (i >= 2000) { printf("tg3_setup_hw cannot reset FTQ\n"); return -ENODEV; } /* Initialize TG3_BDINFO's at: * RCVDBDI_STD_BD: standard eth size rx ring * RCVDBDI_JUMBO_BD: jumbo frame rx ring * RCVDBDI_MINI_BD: small frame rx ring (??? does not work) * * like so: * TG3_BDINFO_HOST_ADDR: high/low parts of DMA address of ring * TG3_BDINFO_MAXLEN_FLAGS: (rx max buffer size << 16) | * ring attribute flags * TG3_BDINFO_NIC_ADDR: location of descriptors in nic SRAM * * Standard receive ring @ NIC_SRAM_RX_BUFFER_DESC, 512 entries. * Jumbo receive ring @ NIC_SRAM_RX_JUMBO_BUFFER_DESC, 256 entries. * * ??? No space allocated for mini receive ring? :( * * The size of each ring is fixed in the firmware, but the location is * configurable. */ { static const uint32_t table_all[] = { /* Setup replenish thresholds. */ RCVBDI_STD_THRESH, TG3_DEF_RX_RING_PENDING / 8, /* Etherboot lives below 4GB */ RCVDBDI_STD_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_HIGH, 0, RCVDBDI_STD_BD + TG3_BDINFO_NIC_ADDR, NIC_SRAM_RX_BUFFER_DESC, }; static const uint32_t table_not_5705[] = { /* Buffer maximum length */ RCVDBDI_STD_BD + TG3_BDINFO_MAXLEN_FLAGS, RX_STD_MAX_SIZE << BDINFO_FLAGS_MAXLEN_SHIFT, /* Disable the mini frame rx ring */ RCVDBDI_MINI_BD + TG3_BDINFO_MAXLEN_FLAGS, BDINFO_FLAGS_DISABLED, /* Disable the jumbo frame rx ring */ RCVBDI_JUMBO_THRESH, 0, RCVDBDI_JUMBO_BD + TG3_BDINFO_MAXLEN_FLAGS, BDINFO_FLAGS_DISABLED, }; TG3_WRITE_SETTINGS(table_all); tw32(RCVDBDI_STD_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_LOW,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -