Module Name: src Committed By: msaitoh Date: Tue Feb 16 15:17:18 UTC 2010
Modified Files: src/sys/dev/pci: if_wm.c if_wmreg.h if_wmvar.h Log Message: Add support for 82575, 82576 and 82580(ER). - Apply the patch for 82575 from Wolfgang Stukenbrock (PR#42422). We use only one RX ring and with the legacy mode. - Add support for 82576. - Partial support for 82580. - Partial support for the serdes systems. To generate a diff of this commit: cvs rdiff -u -r1.198 -r1.199 src/sys/dev/pci/if_wm.c cvs rdiff -u -r1.37 -r1.38 src/sys/dev/pci/if_wmreg.h cvs rdiff -u -r1.8 -r1.9 src/sys/dev/pci/if_wmvar.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/pci/if_wm.c diff -u src/sys/dev/pci/if_wm.c:1.198 src/sys/dev/pci/if_wm.c:1.199 --- src/sys/dev/pci/if_wm.c:1.198 Tue Feb 16 10:06:19 2010 +++ src/sys/dev/pci/if_wm.c Tue Feb 16 15:17:17 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: if_wm.c,v 1.198 2010/02/16 10:06:19 msaitoh Exp $ */ +/* $NetBSD: if_wm.c,v 1.199 2010/02/16 15:17:17 msaitoh Exp $ */ /* * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc. @@ -76,7 +76,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.198 2010/02/16 10:06:19 msaitoh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.199 2010/02/16 15:17:17 msaitoh Exp $"); #include "rnd.h" @@ -231,6 +231,13 @@ #define WM_LINKUP_TIMEOUT 50 +static uint16_t swfwphysem[] = { + SWFW_PHY0_SM, + SWFW_PHY1_SM, + SWFW_PHY2_SM, + SWFW_PHY3_SM +}; + /* * Software state per device. */ @@ -243,31 +250,33 @@ bus_space_tag_t sc_flasht; /* flash registers space tag */ bus_space_handle_t sc_flashh; /* flash registers space handle */ bus_dma_tag_t sc_dmat; /* bus DMA tag */ + bus_dmamap_t sc_cddmamap; /* control data DMA map */ +#define sc_cddma sc_cddmamap->dm_segs[0].ds_addr + struct ethercom sc_ethercom; /* ethernet common data */ + struct mii_data sc_mii; /* MII/media information */ + pci_chipset_tag_t sc_pc; pcitag_t sc_pcitag; + int sc_bus_speed; /* PCI/PCIX bus speed */ + int sc_pcixe_capoff; /* PCI[Xe] capability register offset */ wm_chip_type sc_type; /* MAC type */ int sc_rev; /* MAC revision */ wm_phy_type sc_phytype; /* PHY type */ + int sc_funcid; /* unit number of the chip (0 to 3) */ int sc_flags; /* flags; see below */ int sc_if_flags; /* last if_flags */ - int sc_bus_speed; /* PCI/PCIX bus speed */ - int sc_pcix_offset; /* PCIX capability register offset */ int sc_flowflags; /* 802.3x flow control flags */ + int sc_align_tweak; void *sc_ih; /* interrupt cookie */ - - int sc_ee_addrbits; /* EEPROM address bits */ - - struct mii_data sc_mii; /* MII/media information */ - callout_t sc_tick_ch; /* tick callout */ - bus_dmamap_t sc_cddmamap; /* control data DMA map */ -#define sc_cddma sc_cddmamap->dm_segs[0].ds_addr - - int sc_align_tweak; + int sc_ee_addrbits; /* EEPROM address bits */ + int sc_ich8_flash_base; + int sc_ich8_flash_bank_size; + int sc_nvm_k1_enabled; /* * Software state for the transmit and receive descriptors. @@ -364,9 +373,6 @@ #if NRND > 0 rndsource_element_t rnd_source; /* random source */ #endif - int sc_ich8_flash_base; - int sc_ich8_flash_bank_size; - int sc_nvm_k1_enabled; }; #define WM_RXCHAIN_RESET(sc) \ @@ -523,6 +529,8 @@ static void wm_gmii_bm_writereg(device_t, int, int, int); static int wm_gmii_hv_readreg(device_t, int, int); static void wm_gmii_hv_writereg(device_t, int, int, int); +static int wm_sgmii_readreg(device_t, int, int); +static void wm_sgmii_writereg(device_t, int, int, int); static void wm_gmii_statchg(device_t); @@ -533,7 +541,7 @@ static int wm_kmrn_readreg(struct wm_softc *, int); static void wm_kmrn_writereg(struct wm_softc *, int, int); -static void wm_set_spiaddrsize(struct wm_softc *); +static void wm_set_spiaddrbits(struct wm_softc *); static int wm_match(device_t, cfdata_t, void *); static void wm_attach(device_t, device_t, void *); static int wm_is_onboard_nvm_eeprom(struct wm_softc *); @@ -566,6 +574,8 @@ static void wm_hv_phy_workaround_ich8lan(struct wm_softc *); static void wm_k1_gig_workaround_hv(struct wm_softc *, int); static void wm_configure_k1_ich8lan(struct wm_softc *, int); +static void wm_set_pcie_completion_timeout(struct wm_softc *); +static void wm_reset_init_script_82575(struct wm_softc *); CFATTACH_DECL_NEW(wm, sizeof(struct wm_softc), wm_match, wm_attach, NULL, NULL); @@ -882,6 +892,72 @@ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_PCH_D_DC, "PCH LAN (82578DC) Controller", WM_T_PCH, WMP_F_1000T }, + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82575EB_COPPER, + "82575EB dual-1000baseT Ethernet", + WM_T_82575, WMP_F_1000T }, +#if 0 + /* + * not sure if WMP_F_1000X or WMP_F_SERDES - we do not have it - so + * disabled for now ... + */ + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82575EB_FIBER_SERDES, + "82575EB dual-1000baseX Ethernet (SERDES)", + WM_T_82575, WMP_F_SERDES }, +#endif + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82575GB_QUAD_COPPER, + "82575GB quad-1000baseT Ethernet", + WM_T_82575, WMP_F_1000T }, + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82575GB_QUAD_COPPER_PM, + "82575GB quad-1000baseT Ethernet (PM)", + WM_T_82575, WMP_F_1000T }, + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82576_COPPER, + "82576 1000BaseT Ethernet", + WM_T_82576, WMP_F_1000T }, + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82576_FIBER, + "82576 1000BaseX Ethernet", + WM_T_82576, WMP_F_1000X }, +#if 0 + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82576_SERDES, + "82576 gigabit Ethernet (SERDES)", + WM_T_82576, WMP_F_SERDES }, +#endif + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82576_QUAD_COPPER, + "82576 quad-1000BaseT Ethernet", + WM_T_82576, WMP_F_1000T }, + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82576_NS, + "82576 gigabit Ethernet", + WM_T_82576, WMP_F_1000T }, +#if 0 + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82576_NS_SERDES, + "82576 gigabit Ethernet (SERDES)", + WM_T_82576, WMP_F_SERDES }, + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82576_SERDES_QUAD, + "82576 quad-gigabit Ethernet (SERDES)", + WM_T_82576, WMP_F_SERDES }, +#endif + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82580_COPPER, + "82580 1000BaseT Ethernet", + WM_T_82580, WMP_F_1000T }, + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82580_FIBER, + "82580 1000BaseX Ethernet", + WM_T_82580, WMP_F_1000X }, +#if 0 + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82580_SERDES, + "82580 1000BaseT Ethernet (SERDES)", + WM_T_82580, WMP_F_SERDES }, +#endif + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82580_SGMII, + "82580 gigabit Ethernet (SGMII)", + WM_T_82580, WMP_F_1000T }, + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82580_COPPER_DUAL, + "82580 dual-1000BaseT Ethernet", + WM_T_82580, WMP_F_1000T }, + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82580_ER, + "82580 1000BaseT Ethernet", + WM_T_82580ER, WMP_F_1000T }, + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82580_ER_DUAL, + "82580 dual-1000BaseT Ethernet", + WM_T_82580ER, WMP_F_1000T }, { 0, 0, NULL, 0, 0 }, @@ -910,6 +986,28 @@ } static inline void +wm_82575_write_8bit_ctlr_reg(struct wm_softc *sc, uint32_t reg, uint32_t off, + uint32_t data) +{ + uint32_t regval; + int i; + + regval = (data & SCTL_CTL_DATA_MASK) | (off << SCTL_CTL_ADDR_SHIFT); + + CSR_WRITE(sc, reg, regval); + + for (i = 0; i < SCTL_CTL_POLL_TIMEOUT; i++) { + delay(5); + if (CSR_READ(sc, reg) & SCTL_CTL_READY) + break; + } + if (i == SCTL_CTL_POLL_TIMEOUT) { + aprint_error("%s: WARNING: i82575 reg 0x%08x setup did not indicate ready\n", + device_xname(sc->sc_dev), reg); + } +} + +static inline void wm_set_dma_addr(volatile wiseman_addr_t *wa, bus_addr_t v) { wa->wa_low = htole32(v & 0xffffffffU); @@ -920,7 +1018,7 @@ } static void -wm_set_spiaddrsize(struct wm_softc *sc) +wm_set_spiaddrbits(struct wm_softc *sc) { uint32_t reg; @@ -1010,6 +1108,10 @@ sc->sc_type = WM_T_82542_2_0; } + if ((sc->sc_type == WM_T_82575) || (sc->sc_type == WM_T_82576) + || (sc->sc_type == WM_T_82580) || (sc->sc_type == WM_T_82580ER)) + sc->sc_flags |= WM_F_NEWQUEUE; + /* Set device properties (mactype) */ dict = device_properties(sc->sc_dev); prop_dictionary_set_uint32(dict, "mactype", sc->sc_type); @@ -1110,6 +1212,17 @@ aprint_normal_dev(sc->sc_dev, "interrupting at %s\n", intrstr); /* + * Check the function ID (unit number of the chip). + */ + if ((sc->sc_type == WM_T_82546) || (sc->sc_type == WM_T_82546_3) + || (sc->sc_type == WM_T_82571) || (sc->sc_type == WM_T_80003) + || (sc->sc_type == WM_T_82575)) + sc->sc_funcid = (CSR_READ(sc, WMREG_STATUS) + >> STATUS_FUNCID_SHIFT) & STATUS_FUNCID_MASK; + else + sc->sc_funcid = 0; + + /* * Determine a few things about the bus we're connected to. */ if (sc->sc_type < WM_T_82543) { @@ -1135,8 +1248,15 @@ sc->sc_flags |= WM_F_PCIE; if ((sc->sc_type != WM_T_ICH8) && (sc->sc_type != WM_T_ICH9) && (sc->sc_type != WM_T_ICH10) - && (sc->sc_type != WM_T_PCH)) + && (sc->sc_type != WM_T_PCH)) { sc->sc_flags |= WM_F_EEPROM_SEMAPHORE; + /* ICH* and PCH have no PCIe capability registers */ + if (pci_get_capability(pa->pa_pc, pa->pa_tag, + PCI_CAP_PCIEXPRESS, &sc->sc_pcixe_capoff, + NULL) == 0) + aprint_error_dev(sc->sc_dev, + "unable to find PCIe capability\n"); + } aprint_verbose_dev(sc->sc_dev, "PCI-Express bus\n"); } else { reg = CSR_READ(sc, WMREG_STATUS); @@ -1147,7 +1267,7 @@ sc->sc_flags |= WM_F_PCIX; if (pci_get_capability(pa->pa_pc, pa->pa_tag, - PCI_CAP_PCIX, &sc->sc_pcix_offset, NULL) == 0) + PCI_CAP_PCIX, &sc->sc_pcixe_capoff, NULL) == 0) aprint_error_dev(sc->sc_dev, "unable to find PCIX capability\n"); else if (sc->sc_type != WM_T_82545_3 && @@ -1158,9 +1278,9 @@ * incorrectly. */ pcix_cmd = pci_conf_read(pa->pa_pc, pa->pa_tag, - sc->sc_pcix_offset + PCI_PCIX_CMD); + sc->sc_pcixe_capoff + PCI_PCIX_CMD); pcix_sts = pci_conf_read(pa->pa_pc, pa->pa_tag, - sc->sc_pcix_offset + PCI_PCIX_STATUS); + sc->sc_pcixe_capoff + PCI_PCIX_STATUS); bytecnt = (pcix_cmd & PCI_PCIX_CMD_BYTECNT_MASK) >> @@ -1176,7 +1296,7 @@ ~PCI_PCIX_CMD_BYTECNT_MASK) | (maxb << PCI_PCIX_CMD_BYTECNT_SHIFT); pci_conf_write(pa->pa_pc, pa->pa_tag, - sc->sc_pcix_offset + PCI_PCIX_CMD, + sc->sc_pcixe_capoff + PCI_PCIX_CMD, pcix_cmd); } } @@ -1348,7 +1468,7 @@ reg = CSR_READ(sc, WMREG_EECD); if (reg & EECD_EE_TYPE) { /* SPI */ - wm_set_spiaddrsize(sc); + wm_set_spiaddrbits(sc); } else /* Microwire */ sc->sc_ee_addrbits = (reg & EECD_EE_ABITS) ? 8 : 6; @@ -1357,7 +1477,7 @@ case WM_T_82571: case WM_T_82572: /* SPI */ - wm_set_spiaddrsize(sc); + wm_set_spiaddrbits(sc); sc->sc_flags |= WM_F_EEPROM_HANDSHAKE; break; case WM_T_82573: @@ -1367,25 +1487,21 @@ sc->sc_flags |= WM_F_EEPROM_FLASH; else { /* SPI */ - wm_set_spiaddrsize(sc); + wm_set_spiaddrbits(sc); } sc->sc_flags |= WM_F_EEPROM_EERDEEWR; break; + case WM_T_82575: + case WM_T_82576: + case WM_T_82580: + case WM_T_82580ER: case WM_T_80003: /* SPI */ - wm_set_spiaddrsize(sc); + wm_set_spiaddrbits(sc); sc->sc_flags |= WM_F_EEPROM_EERDEEWR | WM_F_SWFW_SYNC; break; case WM_T_ICH8: case WM_T_ICH9: - /* Check whether EEPROM is present or not */ - if ((CSR_READ(sc, WMREG_EECD) & EECD_EE_PRES) == 0) { - /* Not found */ - aprint_error_dev(sc->sc_dev, - "EEPROM PRESENT bit isn't set\n"); - sc->sc_flags |= WM_F_EEPROM_INVALID; - } - /* FALLTHROUGH */ case WM_T_ICH10: case WM_T_PCH: /* FLASH */ @@ -1400,10 +1516,10 @@ reg = ICH8_FLASH_READ32(sc, ICH_FLASH_GFPREG); sc->sc_ich8_flash_base = (reg & ICH_GFPREG_BASE_MASK) * ICH_FLASH_SECTOR_SIZE; - sc->sc_ich8_flash_bank_size = - ((reg >> 16) & ICH_GFPREG_BASE_MASK) + 1; + sc->sc_ich8_flash_bank_size = + ((reg >> 16) & ICH_GFPREG_BASE_MASK) + 1; sc->sc_ich8_flash_bank_size -= - (reg & ICH_GFPREG_BASE_MASK); + (reg & ICH_GFPREG_BASE_MASK); sc->sc_ich8_flash_bank_size *= ICH_FLASH_SECTOR_SIZE; sc->sc_ich8_flash_bank_size /= 2 * sizeof(uint16_t); break; @@ -1475,9 +1591,10 @@ * Toggle the LSB of the MAC address on the second port * of the dual port controller. */ - if (sc->sc_type == WM_T_82546 || sc->sc_type == WM_T_82546_3 - || sc->sc_type == WM_T_82571 || sc->sc_type == WM_T_80003) { - if ((CSR_READ(sc, WMREG_STATUS) >> STATUS_FUNCID_SHIFT) & 1) + if ((sc->sc_type == WM_T_82546) || (sc->sc_type == WM_T_82546_3) + || (sc->sc_type == WM_T_82571) || (sc->sc_type == WM_T_80003) + || (sc->sc_type == WM_T_82575)) { + if (sc->sc_funcid == 1) enaddr[5] ^= 1; } @@ -1588,7 +1705,7 @@ } /* - * Determine if we're TBI or GMII mode, and initialize the + * Determine if we're TBI,GMII or SGMII mode, and initialize the * media structures accordingly. */ if (sc->sc_type == WM_T_ICH8 || sc->sc_type == WM_T_ICH9 @@ -1604,10 +1721,41 @@ "WARNING: TBIMODE set on 1000BASE-T product!\n"); wm_tbi_mediainit(sc); } else { - if (wmp->wmp_flags & WMP_F_1000X) - aprint_error_dev(sc->sc_dev, - "WARNING: TBIMODE clear on 1000BASE-X product!\n"); - wm_gmii_mediainit(sc, wmp->wmp_product); + switch (sc->sc_type) { + case WM_T_82575: + case WM_T_82576: + case WM_T_82580: + case WM_T_82580ER: + reg = CSR_READ(sc, WMREG_CTRL_EXT); + switch (reg & CTRL_EXT_LINK_MODE_MASK) { + case CTRL_EXT_LINK_MODE_SGMII: + aprint_verbose_dev(sc->sc_dev, "SGMII\n"); + sc->sc_flags |= WM_F_SGMII; + CSR_WRITE(sc, WMREG_CTRL_EXT, + reg | CTRL_EXT_I2C_ENA); + wm_gmii_mediainit(sc, wmp->wmp_product); + break; + case CTRL_EXT_LINK_MODE_1000KX: + case CTRL_EXT_LINK_MODE_PCIE_SERDES: + aprint_verbose_dev(sc->sc_dev, "1000KX or SERDES\n"); + CSR_WRITE(sc, WMREG_CTRL_EXT, + reg | CTRL_EXT_I2C_ENA); + panic("not supported yet\n"); + break; + case CTRL_EXT_LINK_MODE_GMII: + default: + CSR_WRITE(sc, WMREG_CTRL_EXT, + reg & ~CTRL_EXT_I2C_ENA); + wm_gmii_mediainit(sc, wmp->wmp_product); + break; + } + break; + default: + if (wmp->wmp_flags & WMP_F_1000X) + aprint_error_dev(sc->sc_dev, + "WARNING: TBIMODE clear on 1000BASE-X product!\n"); + wm_gmii_mediainit(sc, wmp->wmp_product); + } } ifp = &sc->sc_ethercom.ec_if; @@ -1634,6 +1782,10 @@ case WM_T_82571: case WM_T_82572: case WM_T_82574: + case WM_T_82575: + case WM_T_82576: + case WM_T_82580: + case WM_T_82580ER: case WM_T_80003: case WM_T_ICH9: case WM_T_ICH10: @@ -3108,7 +3260,7 @@ wm_reset(struct wm_softc *sc) { int phy_reset = 0; - uint32_t reg, func, mask; + uint32_t reg, mask; int i; /* @@ -3129,9 +3281,17 @@ break; case WM_T_82571: case WM_T_82572: + case WM_T_82575: /* XXX need special handing for jumbo frames */ case WM_T_80003: sc->sc_pba = PBA_32K; break; + case WM_T_82580: + case WM_T_82580ER: + sc->sc_pba = PBA_35K; + break; + case WM_T_82576: + sc->sc_pba = PBA_64K; + break; case WM_T_82573: sc->sc_pba = PBA_12K; break; @@ -3155,6 +3315,7 @@ } CSR_WRITE(sc, WMREG_PBA, sc->sc_pba); + /* Prevent the PCI-E bus from sticking */ if (sc->sc_flags & WM_F_PCIE) { int timeout = 800; @@ -3168,14 +3329,19 @@ } } - /* clear interrupt */ + /* Set the completion timeout for interface */ + if ((sc->sc_type == WM_T_82575) || (sc->sc_type == WM_T_82576)) + wm_set_pcie_completion_timeout(sc); + + /* Clear interrupt */ CSR_WRITE(sc, WMREG_IMC, 0xffffffffU); /* Stop the transmit and receive processes. */ CSR_WRITE(sc, WMREG_RCTL, 0); CSR_WRITE(sc, WMREG_TCTL, TCTL_PSP); + sc->sc_rctl &= ~RCTL_EN; - /* set_tbi_sbp_82543() */ + /* XXX set_tbi_sbp_82543() */ delay(10*1000); @@ -3241,8 +3407,7 @@ CSR_WRITE(sc, WMREG_CTRL_SHADOW, CTRL_RST); break; case WM_T_80003: - func = (CSR_READ(sc, WMREG_STATUS) >> STATUS_FUNCID_SHIFT) & 1; - mask = func ? SWFW_PHY1_SM : SWFW_PHY0_SM; + mask = swfwphysem[sc->sc_funcid]; reg = CSR_READ(sc, WMREG_CTRL) | CTRL_RST; wm_get_swfw_semaphore(sc, mask); CSR_WRITE(sc, WMREG_CTRL, reg); @@ -3280,6 +3445,8 @@ case WM_T_82572: case WM_T_82573: case WM_T_82574: + case WM_T_82575: + case WM_T_82576: case WM_T_82583: default: /* Everything else can safely use the documented method. */ @@ -3336,6 +3503,8 @@ || (sc->sc_type == WM_T_82583)) delay(25*1000); break; + case WM_T_82575: + case WM_T_82576: case WM_T_80003: case WM_T_ICH8: case WM_T_ICH9: @@ -3350,6 +3519,28 @@ panic("%s: unknown type\n", __func__); } + /* Check whether EEPROM is present or not */ + switch (sc->sc_type) { + case WM_T_82575: + case WM_T_82576: + case WM_T_82580: + case WM_T_ICH8: + case WM_T_ICH9: + if ((CSR_READ(sc, WMREG_EECD) & EECD_EE_PRES) == 0) { + /* Not found */ + sc->sc_flags |= WM_F_EEPROM_INVALID; + if (sc->sc_type == WM_T_82575) /* 82575 only */ + wm_reset_init_script_82575(sc); + } + break; + default: + break; + } + + /* Clear any pending interrupt events. */ + CSR_WRITE(sc, WMREG_IMC, 0xffffffffU); + reg = CSR_READ(sc, WMREG_ICR); + /* reload sc_ctrl */ sc->sc_ctrl = CSR_READ(sc, WMREG_CTRL); @@ -3364,18 +3555,10 @@ if (sc->sc_type == WM_T_PCH) CSR_WRITE(sc, WMREG_CRC_OFFSET, 0x65656565); -#if 0 - for (i = 0; i < 1000; i++) { - if ((CSR_READ(sc, WMREG_CTRL) & CTRL_RST) == 0) { - return; - } - delay(20); - } + if ((sc->sc_flags & WM_F_NEWQUEUE) != 0) + CSR_WRITE(sc, WMREG_WUC, 0); - if (CSR_READ(sc, WMREG_CTRL) & CTRL_RST) - log(LOG_ERR, "%s: reset failed to complete\n", - device_xname(sc->sc_dev)); -#endif + /* XXX need special handling for 82580 */ } /* @@ -3471,10 +3654,16 @@ CSR_WRITE(sc, WMREG_TIDV, 375); /* ITR / 4 */ CSR_WRITE(sc, WMREG_TADV, 375); /* should be same */ - CSR_WRITE(sc, WMREG_TXDCTL, TXDCTL_PTHRESH(0) | - TXDCTL_HTHRESH(0) | TXDCTL_WTHRESH(0)); - CSR_WRITE(sc, WMREG_RXDCTL, RXDCTL_PTHRESH(0) | - RXDCTL_HTHRESH(0) | RXDCTL_WTHRESH(1)); + if ((sc->sc_flags & WM_F_NEWQUEUE) != 0) + CSR_WRITE(sc, WMREG_TXDCTL, TXDCTL_QUEUE_ENABLE + | TXDCTL_PTHRESH(0) | TXDCTL_HTHRESH(0) + | TXDCTL_WTHRESH(0)); + else { + CSR_WRITE(sc, WMREG_TXDCTL, TXDCTL_PTHRESH(0) | + TXDCTL_HTHRESH(0) | TXDCTL_WTHRESH(0)); + CSR_WRITE(sc, WMREG_RXDCTL, RXDCTL_PTHRESH(0) | + RXDCTL_HTHRESH(0) | RXDCTL_WTHRESH(1)); + } } CSR_WRITE(sc, WMREG_TQSA_LO, 0); CSR_WRITE(sc, WMREG_TQSA_HI, 0); @@ -3508,10 +3697,21 @@ CSR_WRITE(sc, WMREG_RDBAH, WM_CDRXADDR_HI(sc, 0)); CSR_WRITE(sc, WMREG_RDBAL, WM_CDRXADDR_LO(sc, 0)); CSR_WRITE(sc, WMREG_RDLEN, sizeof(sc->sc_rxdescs)); - CSR_WRITE(sc, WMREG_RDH, 0); - CSR_WRITE(sc, WMREG_RDT, 0); - CSR_WRITE(sc, WMREG_RDTR, 375 | RDTR_FPD); /* ITR/4 */ - CSR_WRITE(sc, WMREG_RADV, 375); /* MUST be same */ + if ((sc->sc_flags & WM_F_NEWQUEUE) != 0) { + CSR_WRITE(sc, WMREG_EITR(0), 450); + if (MCLBYTES & ((1 << SRRCTL_BSIZEPKT_SHIFT) - 1)) + panic("%s: MCLBYTES %d unsupported for i2575 or higher\n", __func__, MCLBYTES); + CSR_WRITE(sc, WMREG_SRRCTL, SRRCTL_DESCTYPE_LEGACY + | (MCLBYTES >> SRRCTL_BSIZEPKT_SHIFT)); + CSR_WRITE(sc, WMREG_RXDCTL, RXDCTL_QUEUE_ENABLE + | RXDCTL_PTHRESH(16) | RXDCTL_HTHRESH(8) + | RXDCTL_WTHRESH(1)); + } else { + CSR_WRITE(sc, WMREG_RDH, 0); + CSR_WRITE(sc, WMREG_RDT, 0); + CSR_WRITE(sc, WMREG_RDTR, 375 | RDTR_FPD); /* ITR/4 */ + CSR_WRITE(sc, WMREG_RADV, 375); /* MUST be same */ + } } for (i = 0; i < WM_NRXDESC; i++) { rxs = &sc->sc_rxsoft[i]; @@ -3527,8 +3727,10 @@ wm_rxdrain(sc); goto out; } - } else - WM_INIT_RXDESC(sc, i); + } else { + if ((sc->sc_flags & WM_F_NEWQUEUE) == 0) + WM_INIT_RXDESC(sc, i); + } } sc->sc_rxptr = 0; sc->sc_rxdiscard = 0; @@ -3720,8 +3922,11 @@ | RCTL_MO(sc->sc_mchash_type); if (((sc->sc_ethercom.ec_capabilities & ETHERCAP_JUMBO_MTU) != 0) - && (ifp->if_mtu > ETHERMTU)) - sc->sc_rctl |= RCTL_LPE; + && (ifp->if_mtu > ETHERMTU)) { + sc->sc_rctl |= RCTL_LPE; + if ((sc->sc_flags & WM_F_NEWQUEUE) != 0) + CSR_WRITE(sc, WMREG_RLPML, ETHER_MAX_LEN_JUMBO); + } if (MCLBYTES == 2048) { sc->sc_rctl |= RCTL_2k; @@ -3748,6 +3953,11 @@ /* Set the receive filter. */ wm_set_filter(sc); + /* On 575 and later set RDT only if RX enabled... */ + if ((sc->sc_flags & WM_F_NEWQUEUE) != 0) + for (i = 0; i < WM_NRXDESC; i++) + WM_INIT_RXDESC(sc, i); + /* Start the one second link check clock. */ callout_reset(&sc->sc_tick_ch, hz, wm_tick, sc); @@ -3815,6 +4025,7 @@ /* Stop the transmit and receive processes. */ CSR_WRITE(sc, WMREG_TCTL, 0); CSR_WRITE(sc, WMREG_RCTL, 0); + sc->sc_rctl &= ~RCTL_EN; /* * Clear the interrupt mask to ensure the device cannot assert its @@ -3841,6 +4052,11 @@ if (disable) wm_rxdrain(sc); + +#if 0 /* notyet */ + if (sc->sc_type >= WM_T_82544) + CSR_WRITE(sc, WMREG_WUC, 0); +#endif } void @@ -3855,6 +4071,8 @@ case WM_T_82573: case WM_T_82574: case WM_T_82583: + case WM_T_82575: + case WM_T_82576: case WM_T_80003: case WM_T_ICH8: case WM_T_ICH9: @@ -3907,7 +4125,6 @@ void wm_get_cfg_done(struct wm_softc *sc) { - int func = 0; int mask; uint32_t reg; int i; @@ -3938,12 +4155,10 @@ case WM_T_80003: case WM_T_82571: case WM_T_82572: - if (sc->sc_type == WM_T_80003) - func = (CSR_READ(sc, WMREG_STATUS) - >> STATUS_FUNCID_SHIFT) & 1; - else - func = 0; /* XXX Is it true for 82571? */ - mask = (func == 1) ? EEMNGCTL_CFGDONE_1 : EEMNGCTL_CFGDONE_0; + case WM_T_82575: + case WM_T_82576: + case WM_T_82580: + mask = EEMNGCTL_CFGDONE_0 << sc->sc_funcid; for (i = 0; i < WM_PHY_CFG_TIMEOUT; i++) { if (CSR_READ(sc, WMREG_EEMNGCTL) & mask) break; @@ -4367,7 +4582,11 @@ bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0, rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD); - WM_INIT_RXDESC(sc, idx); + if ((sc->sc_flags & WM_F_NEWQUEUE) != 0) { + if ((sc->sc_rctl & RCTL_EN) != 0) + WM_INIT_RXDESC(sc, idx); + } else + WM_INIT_RXDESC(sc, idx); return 0; } @@ -4826,7 +5045,6 @@ wm_gmii_reset(struct wm_softc *sc) { uint32_t reg; - int func = 0; /* XXX gcc */ int rv; /* get phy semaphore */ @@ -4839,10 +5057,12 @@ /* XXX should get sw semaphore, too */ rv = wm_get_swsm_semaphore(sc); break; + case WM_T_82575: + case WM_T_82576: + case WM_T_82580: + case WM_T_82580ER: case WM_T_80003: - func = (CSR_READ(sc, WMREG_STATUS) >> STATUS_FUNCID_SHIFT) & 1; - rv = wm_get_swfw_semaphore(sc, - func ? SWFW_PHY1_SM : SWFW_PHY0_SM); + rv = wm_get_swfw_semaphore(sc, swfwphysem[sc->sc_funcid]); break; case WM_T_ICH8: case WM_T_ICH9: @@ -4906,6 +5126,10 @@ case WM_T_82572: case WM_T_82573: case WM_T_82574: + case WM_T_82575: + case WM_T_82576: + case WM_T_82580: + case WM_T_82580ER: case WM_T_82583: case WM_T_80003: /* generic reset */ @@ -4948,8 +5172,12 @@ /* XXX sould put sw semaphore, too */ wm_put_swsm_semaphore(sc); break; + case WM_T_82575: + case WM_T_82576: + case WM_T_82580: + case WM_T_82580ER: case WM_T_80003: - wm_put_swfw_semaphore(sc, func ? SWFW_PHY1_SM : SWFW_PHY0_SM); + wm_put_swfw_semaphore(sc, swfwphysem[sc->sc_funcid]); break; case WM_T_ICH8: case WM_T_ICH9: @@ -4983,6 +5211,10 @@ case WM_T_82572: case WM_T_82573: case WM_T_82574: + case WM_T_82575: + case WM_T_82576: + case WM_T_82580: + case WM_T_82580ER: case WM_T_82583: case WM_T_80003: /* null */ @@ -5088,7 +5320,10 @@ sc->sc_mii.mii_writereg = wm_gmii_bm_writereg; break; default: - if (sc->sc_type >= WM_T_80003) { + if ((sc->sc_flags & WM_F_SGMII) != 0) { + sc->sc_mii.mii_readreg = wm_sgmii_readreg; + sc->sc_mii.mii_writereg = wm_sgmii_writereg; + } else if (sc->sc_type >= WM_T_80003) { sc->sc_mii.mii_readreg = wm_gmii_i80003_readreg; sc->sc_mii.mii_writereg = wm_gmii_i80003_writereg; } else if (sc->sc_type >= WM_T_82544) { @@ -5378,13 +5613,14 @@ wm_gmii_i80003_readreg(device_t self, int phy, int reg) { struct wm_softc *sc = device_private(self); - int func = ((CSR_READ(sc, WMREG_STATUS) >> STATUS_FUNCID_SHIFT) & 1); + int sem; int rv; if (phy != 1) /* only one PHY on kumeran bus */ return 0; - if (wm_get_swfw_semaphore(sc, func ? SWFW_PHY1_SM : SWFW_PHY0_SM)) { + sem = swfwphysem[sc->sc_funcid]; + if (wm_get_swfw_semaphore(sc, sem)) { aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n", __func__); return 0; @@ -5402,7 +5638,7 @@ rv = wm_gmii_i82544_readreg(self, phy, reg & GG82563_MAX_REG_ADDRESS); delay(200); - wm_put_swfw_semaphore(sc, func ? SWFW_PHY1_SM : SWFW_PHY0_SM); + wm_put_swfw_semaphore(sc, sem); return rv; } @@ -5417,12 +5653,13 @@ wm_gmii_i80003_writereg(device_t self, int phy, int reg, int val) { struct wm_softc *sc = device_private(self); - int func = ((CSR_READ(sc, WMREG_STATUS) >> STATUS_FUNCID_SHIFT) & 1); + int sem; if (phy != 1) /* only one PHY on kumeran bus */ return; - if (wm_get_swfw_semaphore(sc, func ? SWFW_PHY1_SM : SWFW_PHY0_SM)) { + sem = swfwphysem[sc->sc_funcid]; + if (wm_get_swfw_semaphore(sc, sem)) { aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n", __func__); return; @@ -5440,7 +5677,7 @@ wm_gmii_i82544_writereg(self, phy, reg & GG82563_MAX_REG_ADDRESS, val); delay(200); - wm_put_swfw_semaphore(sc, func ? SWFW_PHY1_SM : SWFW_PHY0_SM); + wm_put_swfw_semaphore(sc, sem); } /* @@ -5454,10 +5691,11 @@ wm_gmii_bm_readreg(device_t self, int phy, int reg) { struct wm_softc *sc = device_private(self); - int func = ((CSR_READ(sc, WMREG_STATUS) >> STATUS_FUNCID_SHIFT) & 1); + int sem; int rv; - if (wm_get_swfw_semaphore(sc, func ? SWFW_PHY1_SM : SWFW_PHY0_SM)) { + sem = swfwphysem[sc->sc_funcid]; + if (wm_get_swfw_semaphore(sc, sem)) { aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n", __func__); return 0; @@ -5474,7 +5712,7 @@ } rv = wm_gmii_i82544_readreg(self, phy, reg & GG82563_MAX_REG_ADDRESS); - wm_put_swfw_semaphore(sc, func ? SWFW_PHY1_SM : SWFW_PHY0_SM); + wm_put_swfw_semaphore(sc, sem); return rv; } @@ -5489,9 +5727,10 @@ wm_gmii_bm_writereg(device_t self, int phy, int reg, int val) { struct wm_softc *sc = device_private(self); - int func = ((CSR_READ(sc, WMREG_STATUS) >> STATUS_FUNCID_SHIFT) & 1); + int sem; - if (wm_get_swfw_semaphore(sc, func ? SWFW_PHY1_SM : SWFW_PHY0_SM)) { + sem = swfwphysem[sc->sc_funcid]; + if (wm_get_swfw_semaphore(sc, sem)) { aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n", __func__); return; @@ -5508,7 +5747,7 @@ } wm_gmii_i82544_writereg(self, phy, reg & GG82563_MAX_REG_ADDRESS, val); - wm_put_swfw_semaphore(sc, func ? SWFW_PHY1_SM : SWFW_PHY0_SM); + wm_put_swfw_semaphore(sc, sem); } static void @@ -5659,6 +5898,89 @@ } /* + * wm_gmii_hv_readreg: [mii interface function] + * + * Read a PHY register on the kumeran + * This could be handled by the PHY layer if we didn't have to lock the + * ressource ... + */ +static int +wm_sgmii_readreg(device_t self, int phy, int reg) +{ + struct wm_softc *sc = device_private(self); + uint32_t i2ccmd; + int i, rv; + + if (wm_get_swfw_semaphore(sc, swfwphysem[sc->sc_funcid])) { + aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n", + __func__); + return 0; + } + + i2ccmd = (reg << I2CCMD_REG_ADDR_SHIFT) + | (phy << I2CCMD_PHY_ADDR_SHIFT) + | I2CCMD_OPCODE_READ; + CSR_WRITE(sc, WMREG_I2CCMD, i2ccmd); + + /* Poll the ready bit */ + for (i = 0; i < I2CCMD_PHY_TIMEOUT; i++) { + delay(50); + i2ccmd = CSR_READ(sc, WMREG_I2CCMD); + if (i2ccmd & I2CCMD_READY) + break; + } + if ((i2ccmd & I2CCMD_READY) == 0) + aprint_error_dev(sc->sc_dev, "I2CCMD Read did not complete\n"); + if ((i2ccmd & I2CCMD_ERROR) != 0) + aprint_error_dev(sc->sc_dev, "I2CCMD Error bit set\n"); + + rv = ((i2ccmd >> 8) & 0x00ff) | ((i2ccmd << 8) & 0xff00); + + wm_put_swfw_semaphore(sc, swfwphysem[sc->sc_funcid]); + return rv; +} + +/* + * wm_gmii_hv_writereg: [mii interface function] + * + * Write a PHY register on the kumeran. + * This could be handled by the PHY layer if we didn't have to lock the + * ressource ... + */ +static void +wm_sgmii_writereg(device_t self, int phy, int reg, int val) +{ + struct wm_softc *sc = device_private(self); + uint32_t i2ccmd; + int i; + + if (wm_get_swfw_semaphore(sc, swfwphysem[sc->sc_funcid])) { + aprint_error_dev(sc->sc_dev, "%s: failed to get semaphore\n", + __func__); + return; + } + + i2ccmd = (reg << I2CCMD_REG_ADDR_SHIFT) + | (phy << I2CCMD_PHY_ADDR_SHIFT) + | I2CCMD_OPCODE_WRITE; + CSR_WRITE(sc, WMREG_I2CCMD, i2ccmd); + + /* Poll the ready bit */ + for (i = 0; i < I2CCMD_PHY_TIMEOUT; i++) { + delay(50); + i2ccmd = CSR_READ(sc, WMREG_I2CCMD); + if (i2ccmd & I2CCMD_READY) + break; + } + if ((i2ccmd & I2CCMD_READY) == 0) + aprint_error_dev(sc->sc_dev, "I2CCMD Write did not complete\n"); + if ((i2ccmd & I2CCMD_ERROR) != 0) + aprint_error_dev(sc->sc_dev, "I2CCMD Error bit set\n"); + + wm_put_swfw_semaphore(sc, SWFW_PHY0_SM); +} + +/* * wm_gmii_statchg: [mii interface function] * * Callback from MII layer when media changes. @@ -6544,3 +6866,64 @@ CSR_WRITE(sc, WMREG_CTRL_EXT, ctrl_ext); delay(20); } + +static void +wm_set_pcie_completion_timeout(struct wm_softc *sc) +{ + uint32_t gcr; + pcireg_t ctrl2; + + gcr = CSR_READ(sc, WMREG_GCR); + + /* Only take action if timeout value is defaulted to 0 */ + if ((gcr & GCR_CMPL_TMOUT_MASK) != 0) + goto out; + + if ((gcr & GCR_CAP_VER2) == 0) { + gcr |= GCR_CMPL_TMOUT_10MS; + goto out; + } + + ctrl2 = pci_conf_read(sc->sc_pc, sc->sc_pcitag, + sc->sc_pcixe_capoff + PCI_PCIE_DCSR2); + ctrl2 |= WM_PCI_PCIE_DCSR2_16MS; + pci_conf_write(sc->sc_pc, sc->sc_pcitag, + sc->sc_pcixe_capoff + PCI_PCIE_DCSR2, ctrl2); + +out: + /* Disable completion timeout resend */ + gcr &= ~GCR_CMPL_TMOUT_RESEND; + + CSR_WRITE(sc, WMREG_GCR, gcr); +} + +/* special case - for 82575 - need to do manual init ... */ +static void +wm_reset_init_script_82575(struct wm_softc *sc) +{ + /* + * remark: this is untested code - we have no board without EEPROM + * same setup as mentioned int the freeBSD driver for the i82575 + */ + + /* SerDes configuration via SERDESCTRL */ + wm_82575_write_8bit_ctlr_reg(sc, WMREG_SCTL, 0x00, 0x0c); + wm_82575_write_8bit_ctlr_reg(sc, WMREG_SCTL, 0x01, 0x78); + wm_82575_write_8bit_ctlr_reg(sc, WMREG_SCTL, 0x1b, 0x23); + wm_82575_write_8bit_ctlr_reg(sc, WMREG_SCTL, 0x23, 0x15); + + /* CCM configuration via CCMCTL register */ + wm_82575_write_8bit_ctlr_reg(sc, WMREG_CCMCTL, 0x14, 0x00); + wm_82575_write_8bit_ctlr_reg(sc, WMREG_CCMCTL, 0x10, 0x00); + + /* PCIe lanes configuration */ + wm_82575_write_8bit_ctlr_reg(sc, WMREG_GIOCTL, 0x00, 0xec); + wm_82575_write_8bit_ctlr_reg(sc, WMREG_GIOCTL, 0x61, 0xdf); + wm_82575_write_8bit_ctlr_reg(sc, WMREG_GIOCTL, 0x34, 0x05); + wm_82575_write_8bit_ctlr_reg(sc, WMREG_GIOCTL, 0x2f, 0x81); + + /* PCIe PLL Configuration */ + wm_82575_write_8bit_ctlr_reg(sc, WMREG_SCCTL, 0x02, 0x47); + wm_82575_write_8bit_ctlr_reg(sc, WMREG_SCCTL, 0x14, 0x00); + wm_82575_write_8bit_ctlr_reg(sc, WMREG_SCCTL, 0x10, 0x00); +} Index: src/sys/dev/pci/if_wmreg.h diff -u src/sys/dev/pci/if_wmreg.h:1.37 src/sys/dev/pci/if_wmreg.h:1.38 --- src/sys/dev/pci/if_wmreg.h:1.37 Tue Feb 16 10:06:19 2010 +++ src/sys/dev/pci/if_wmreg.h Tue Feb 16 15:17:17 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: if_wmreg.h,v 1.37 2010/02/16 10:06:19 msaitoh Exp $ */ +/* $NetBSD: if_wmreg.h,v 1.38 2010/02/16 15:17:17 msaitoh Exp $ */ /* * Copyright (c) 2001 Wasabi Systems, Inc. @@ -338,12 +338,16 @@ #define CTRL_EXT_SPD_BYPS (1U << 15) /* speed select bypass */ #define CTRL_EXT_IPS1 (1U << 16) /* invert power state bit 1 */ #define CTRL_EXT_RO_DIS (1U << 17) /* relaxed ordering disabled */ -#define CTRL_EXT_LINK_MODE_MASK 0x00C00000 -#define CTRL_EXT_LINK_MODE_GMII 0x00000000 -#define CTRL_EXT_LINK_MODE_TBI 0x00C00000 -#define CTRL_EXT_LINK_MODE_KMRN 0x00000000 -#define CTRL_EXT_LINK_MODE_SERDES 0x00C00000 +#define CTRL_EXT_LINK_MODE_MASK 0x00C00000 +#define CTRL_EXT_LINK_MODE_GMII 0x00000000 +#define CTRL_EXT_LINK_MODE_KMRN 0x00000000 +#define CTRL_EXT_LINK_MODE_1000KX 0x00400000 +#define CTRL_EXT_LINK_MODE_SGMII 0x00800000 +#define CTRL_EXT_LINK_MODE_PCIX_SERDES 0x00800000 +#define CTRL_EXT_LINK_MODE_TBI 0x00C00000 +#define CTRL_EXT_LINK_MODE_PCIE_SERDES 0x00C00000 #define CTRL_EXT_PHYPDEN 0x00100000 +#define CTRL_EXT_I2C_ENA 0x02000000 /* I2C enable */ #define CTRL_EXT_DRV_LOAD 0x10000000 @@ -357,6 +361,16 @@ #define MDIC_I (1U << 29) /* interrupt on MDI complete */ #define MDIC_E (1U << 30) /* MDI error */ +#define WMREG_SCTL 0x0024 /* SerDes Control - RW */ +/* + * These 4 macros are also used for other 8bit control registers on the + * 82575 + */ +#define SCTL_CTL_READY (1U << 31) +#define SCTL_CTL_DATA_MASK 0x000000ff +#define SCTL_CTL_ADDR_SHIFT 8 +#define SCTL_CTL_POLL_TIMEOUT 640 + #define WMREG_FCAL 0x0028 /* Flow Control Address Low */ #define FCAL_CONST 0x00c28001 /* Flow Control MAC addr low */ @@ -447,24 +461,48 @@ #define WMREG_OLD_RDBAL0 0x0110 /* Receive Descriptor Base Low (ring 0) */ #define WMREG_RDBAL 0x2800 +#define WMREG_RDBAL_2 0x0c00 /* for 82576 ... */ #define WMREG_OLD_RDBAH0 0x0114 /* Receive Descriptor Base High (ring 0) */ #define WMREG_RDBAH 0x2804 +#define WMREG_RDBAH_2 0x0c04 /* for 82576 ... */ #define WMREG_OLD_RDLEN0 0x0118 /* Receive Descriptor Length (ring 0) */ #define WMREG_RDLEN 0x2808 +#define WMREG_RDLEN_2 0x0c08 /* for 82576 ... */ + +#define WMREG_SRRCTL 0x280c /* additional recieve control used in 82575 ... */ +#define WMREG_SRRCTL_2 0x0c0c /* for 82576 ... */ +#define SRRCTL_BSIZEPKT_MASK 0x0000007f +#define SRRCTL_BSIZEPKT_SHIFT 10 /* Shift _right_ */ +#define SRRCTL_BSIZEHDRSIZE_MASK 0x00000f00 +#define SRRCTL_BSIZEHDRSIZE_SHIFT 2 /* Shift _left_ */ +#define SRRCTL_DESCTYPE_LEGACY 0x00000000 +#define SRRCTL_DESCTYPE_ADV_ONEBUF (1U << 25) +#define SRRCTL_DESCTYPE_HDR_SPLIT (2U << 25) +#define SRRCTL_DESCTYPE_HDR_REPLICATION (3U << 25) +#define SRRCTL_DESCTYPE_HDR_REPLICATION_LARGE_PKT (4U << 25) +#define SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS (5U << 25) /* 82575 only */ +#define SRRCTL_DESCTYPE_MASK (7U << 25) +#define SRRCTL_DROP_EN 0x80000000 #define WMREG_OLD_RDH0 0x0120 /* Receive Descriptor Head (ring 0) */ #define WMREG_RDH 0x2810 +#define WMREG_RDH_2 0x0c10 /* for 82576 ... */ #define WMREG_OLD_RDT0 0x0128 /* Receive Descriptor Tail (ring 0) */ #define WMREG_RDT 0x2818 +#define WMREG_RDT_2 0x0c18 /* for 82576 ... */ #define WMREG_RXDCTL 0x2828 /* Receive Descriptor Control */ +#define WMREG_RXDCTL_2 0x0c28 /* for 82576 ... */ #define RXDCTL_PTHRESH(x) ((x) << 0) /* prefetch threshold */ #define RXDCTL_HTHRESH(x) ((x) << 8) /* host threshold */ #define RXDCTL_WTHRESH(x) ((x) << 16) /* write back threshold */ #define RXDCTL_GRAN (1U << 24) /* 0 = cacheline, 1 = descriptor */ +/* flags used starting with 82575 ... */ +#define RXDCTL_QUEUE_ENABLE 0x02000000 /* Enable specific Tx Queue */ +#define RXDCTL_SWFLSH 0x04000000 /* Rx Desc. write-back flushing */ #define WMREG_OLD_RDTR1 0x0130 /* Receive Delay Timer (ring 1) */ @@ -590,6 +628,10 @@ #define TXDCTL_PTHRESH(x) ((x) << 0) /* prefetch threshold */ #define TXDCTL_HTHRESH(x) ((x) << 8) /* host threshold */ #define TXDCTL_WTHRESH(x) ((x) << 16) /* write back threshold */ +/* flags used starting with 82575 ... */ +#define TXDCTL_QUEUE_ENABLE 0x02000000 /* Enable specific Tx Queue */ +#define TXDCTL_SWFLSH 0x04000000 /* Tx Desc. write-back flushing */ +#define TXDCTL_PRIORITY 0x08000000 #define WMREG_TADV 0x382c /* Transmit Absolute Interrupt Delay Timer */ @@ -613,8 +655,10 @@ #define PBA_24K 0x0018 #define PBA_30K 0x001e #define PBA_32K 0x0020 +#define PBA_35K 0x0023 #define PBA_40K 0x0028 #define PBA_48K 0x0030 /* 48K, default Rx allocation */ +#define PBA_64K 0x0040 #define WMREG_PBS 0x1008 /* Packet Buffer Size (ICH) */ @@ -622,6 +666,42 @@ #define EEMNGCTL_CFGDONE_0 0x040000 /* MNG config cycle done */ #define EEMNGCTL_CFGDONE_1 0x080000 /* 2nd port */ +#define WMREG_I2CCMD 0x1028 /* SFPI2C Command Register - RW */ +#define I2CCMD_REG_ADDR_SHIFT 16 +#define I2CCMD_REG_ADDR 0x00ff0000 +#define I2CCMD_PHY_ADDR_SHIFT 24 +#define I2CCMD_PHY_ADDR 0x07000000 +#define I2CCMD_OPCODE_READ 0x08000000 +#define I2CCMD_OPCODE_WRITE 0x00000000 +#define I2CCMD_RESET 0x10000000 +#define I2CCMD_READY 0x20000000 +#define I2CCMD_INTERRUPT_ENA 0x40000000 +#define I2CCMD_ERROR 0x80000000 +#define MAX_SGMII_PHY_REG_ADDR 255 +#define I2CCMD_PHY_TIMEOUT 200 + +#define WMREG_EICS 0x01520 /* Ext. Interrupt Cause Set - WO */ +#define WMREG_EIMS 0x01524 /* Ext. Interrupt Mask Set/Read - RW */ +#define WMREG_EIMC 0x01528 /* Ext. Interrupt Mask Clear - WO */ +#define WMREG_EIAC 0x0152C /* Ext. Interrupt Auto Clear - RW */ +#define WMREG_EIAM 0x01530 /* Ext. Interrupt Ack Auto Clear Mask - RW */ + +#define WMREG_EICR 0x01580 /* Ext. Interrupt Cause Read - R/clr */ + +#define EITR_RX_QUEUE0 0x00000001 /* Rx Queue 0 Interrupt */ +#define EITR_RX_QUEUE1 0x00000002 /* Rx Queue 1 Interrupt */ +#define EITR_RX_QUEUE2 0x00000004 /* Rx Queue 2 Interrupt */ +#define EITR_RX_QUEUE3 0x00000008 /* Rx Queue 3 Interrupt */ +#define EITR_TX_QUEUE0 0x00000100 /* Tx Queue 0 Interrupt */ +#define EITR_TX_QUEUE1 0x00000200 /* Tx Queue 1 Interrupt */ +#define EITR_TX_QUEUE2 0x00000400 /* Tx Queue 2 Interrupt */ +#define EITR_TX_QUEUE3 0x00000800 /* Tx Queue 3 Interrupt */ +#define EITR_TCP_TIMER 0x40000000 /* TCP Timer */ +#define EITR_OTHER 0x80000000 /* Interrupt Cause Active */ + +#define WMREG_EITR(x) (0x01680 + (0x4 * (x))) +#define EITR_ITR_INT_MASK 0x0000ffff + #define WMREG_TXDMAC 0x3000 /* Transfer DMA Control */ #define TXDMAC_DPP (1U << 0) /* disable packet prefetch */ @@ -636,12 +716,6 @@ #define TSPMT_TSMT(x) (x) /* TCP seg min transfer */ #define TSPMT_TSPBP(x) ((x) << 16) /* TCP seg pkt buf padding */ -#define WMREG_RXCSUM 0x5000 /* Receive Checksum register */ -#define RXCSUM_PCSS 0x000000ff /* Packet Checksum Start */ -#define RXCSUM_IPOFL (1U << 8) /* IP checksum offload */ -#define RXCSUM_TUOFL (1U << 9) /* TCP/UDP checksum offload */ -#define RXCSUM_IPV6OFL (1U << 10) /* IPv6 checksum offload */ - #define WMREG_CRCERRS 0x4000 /* CRC Error Count */ #define WMREG_ALGNERRC 0x4004 /* Alignment Error Count */ #define WMREG_SYMERRC 0x4008 /* Symbol Error Count */ @@ -692,11 +766,36 @@ #define WMREG_MDPHYA 0x003C /* PHY address - RW */ +#define WMREG_RXCSUM 0x5000 /* Receive Checksum register */ +#define RXCSUM_PCSS 0x000000ff /* Packet Checksum Start */ +#define RXCSUM_IPOFL (1U << 8) /* IP checksum offload */ +#define RXCSUM_TUOFL (1U << 9) /* TCP/UDP checksum offload */ +#define RXCSUM_IPV6OFL (1U << 10) /* IPv6 checksum offload */ + +#define WMREG_RLPML 0x5004 /* Rx Long Packet Max Length */ + +#define WMREG_WUC 0x5800 /* Wakeup Control */ + #define WMREG_MANC 0x5820 /* Management Control */ #define MANC_BLK_PHY_RST_ON_IDE 0x00040000 #define WMREG_MANC2H 0x5860 /* Manaegment Control To Host - RW */ +#define WMREG_GCR 0x5b00 /* PCIe Control */ +#define GCR_RXD_NO_SNOOP 0x00000001 +#define GCR_RXDSCW_NO_SNOOP 0x00000002 +#define GCR_RXDSCR_NO_SNOOP 0x00000004 +#define GCR_TXD_NO_SNOOP 0x00000008 +#define GCR_TXDSCW_NO_SNOOP 0x00000010 +#define GCR_TXDSCR_NO_SNOOP 0x00000020 +#define GCR_CMPL_TMOUT_MASK 0x0000f000 +#define GCR_CMPL_TMOUT_10MS 0x00001000 +#define GCR_CMPL_TMOUT_RESEND 0x00010000 +#define GCR_CAP_VER2 0x00040000 +#define WMREG_GIOCTL 0x5b44 /* GIO Analog Control Register */ +#define WMREG_CCMCTL 0x5b48 /* CCM Control Register */ +#define WMREG_SCCTL 0x5b4c /* PCIc PLL Configuration Register */ + #define WMREG_SWSM 0x5b50 /* SW Semaphore */ #define SWSM_SMBI 0x00000001 /* Driver Semaphore bit */ #define SWSM_SWESMBI 0x00000002 /* FW Semaphore bit */ @@ -715,6 +814,8 @@ #define SWFW_PHY0_SM 0x0002 /* first ctrl phy access */ #define SWFW_PHY1_SM 0x0004 /* second ctrl phy access */ #define SWFW_MAC_CSR_SM 0x0008 +#define SWFW_PHY2_SM 0x0020 /* first ctrl phy access */ +#define SWFW_PHY3_SM 0x0040 /* first ctrl phy access */ #define SWFW_SOFT_SHIFT 0 /* software semaphores */ #define SWFW_FIRM_SHIFT 16 /* firmware semaphores */ @@ -784,3 +885,6 @@ #define ICH_NVM_SIG_WORD 0x13 #define ICH_NVM_SIG_MASK 0xc000 + +/* for PCI express Capability registers */ +#define WM_PCI_PCIE_DCSR2_16MS 0x00000005 Index: src/sys/dev/pci/if_wmvar.h diff -u src/sys/dev/pci/if_wmvar.h:1.8 src/sys/dev/pci/if_wmvar.h:1.9 --- src/sys/dev/pci/if_wmvar.h:1.8 Thu Jan 14 18:56:02 2010 +++ src/sys/dev/pci/if_wmvar.h Tue Feb 16 15:17:17 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: if_wmvar.h,v 1.8 2010/01/14 18:56:02 msaitoh Exp $ */ +/* $NetBSD: if_wmvar.h,v 1.9 2010/02/16 15:17:17 msaitoh Exp $ */ /* * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc. @@ -86,6 +86,8 @@ #define WM_F_PCIE 0x0800 /* bus is PCI-Express */ #define WM_F_SWFW_SYNC 0x1000 /* Software-Firmware synchronisation */ #define WM_F_SWFWHW_SYNC 0x2000 /* Software-Firmware synchronisation */ +#define WM_F_SGMII 0x4000 /* use SGMII */ +#define WM_F_NEWQUEUE 0x8000 /* chips which has the new queue system */ typedef enum { WM_T_unknown = 0, @@ -107,6 +109,10 @@ WM_T_82573, /* i82573 */ WM_T_82574, /* i82574 */ WM_T_82583, /* i82583 */ + WM_T_82575, /* i82575 */ + WM_T_82576, /* i82576 */ + WM_T_82580, /* i82580 */ + WM_T_82580ER, /* i82580ER */ WM_T_80003, /* i80003 */ WM_T_ICH8, /* ICH8 LAN */ WM_T_ICH9, /* ICH9 LAN */