NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
kern/42422: NetBSD 4.x and 5.x lacks support for Intel 82575/82576 NIC's
>Number: 42422
>Category: kern
>Synopsis: NetBSD 4.x and 5.x lacks support for Intel 82575/82576 NIC's
>Confidential: no
>Severity: serious
>Priority: high
>Responsible: kern-bug-people
>State: open
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Mon Dec 07 15:35:00 +0000 2009
>Originator: Dr. Wolfgang Stukenbrock
>Release: NetBSD 4.0
>Organization:
Dr. Nagler & Company GmbH
>Environment:
System: NetBSD s012 4.0 NetBSD 4.0 (NSW-S012) #9: Fri Mar 13 12:31:52 CET 2009
wgstuken@s012:/usr/src/sys/arch/amd64/compile/NSW-S012 amd64
Architecture: x86_64
Machine: amd64
>Description:
There is no support in 4.x and 5.x of NetBSD for Intel's latest
1000Tx-chips.
Accedently Intel has retiered most of the supported chips, so there is
a support problem for
actual hardware.
I've found a driver in FreeBSD that seems to base on Intel-Sources. In
this driver there
is a new interface type for the 82575 and 82676.
Most code parts are still shared with to older chips, but the
freeBSD-driver uses the new advanced
recieve buffer descriptors of the chip that are required if someone is
gooing to use the advanced
features (e.g. virtualisation) of theese chips.
As far as I see, NetBSD does not support features like that, so that it
is possible to use the
legacy interface of the 82575/82576.
The following patches enables the 82575 found on the Intel X38ML board.
remarks:
- The patch supports only the 82575. Accedently I found no HW-Manual
for the 82575, so I have used
the 82576 manual and the freeBSD-driver as reference.
- The patch does not support Fiber, Serdes or SGMII PHY. The X38ML
board has a normal GMII-Phy, so I
couldn't test any other. The Fiber/Serdes version may work with some
small changes. The SGMII interface
via I2C is completly new.
- I simply do not know what some of the timing parameter used in the
NetBSD-wm-driver or the freeBSD-driver mean.
So someone that has advanced knowledge on that should have a look at
it prior integrating it into NetBSD!
- The support for non-EEPROM setups is taken from freeBSD. I've no
chance to test it ...
- Some registers changes their address starting with the 82575. They
are still reachable vie the old addresse.
Due to the fact, that the first one of them are still rachable on the
old addresses for comparbility reasons,
I have only added the new addresses in if_wmreg.h, but still use the
old ones. Affected are the Queues, but
NetBSD uses only queue 0.
- The 82575 cannot be initialized until the RX-Queue is enabled.
Therefore I moved some parts of the setup
to a the end of the setup.
I think this oulb be a good idea for all chips, but I've no manual
for the old ones.
In fact, the RDT register is written twice on every chip - that makes
no sence ...
(first when allocating the memory while the Rx-queue is still
disables and than again after another reset of the chip.)
Other bugs found in the current NetBSD wm driver version:
- while waiting for the chip, the timeout variable is not decrented!
If a chip will not get ready the dirver will hang - this is fixed in
the patch.
- in wm_attach some settings for the GPIO-Pins are extracted from the
EEPROM and set into the CTLR register.
This information is lost after the next chip-reset, e.g. when
configuring the interface via "ifconfig".
The EEPROM-Info is not applied again in the CTLR-register setup.
For the X38ML-board this results in not setting the
Watchdog-enable-bit again.
I have no idea about the side effects when the bit is not set again.
This issue is NOT addresses in this patch! The EEPROM-information is
still lost after every chip-reset!
(At least on the X38ML-Board with the BIOS-setup we are using, it
seems to have no effect, but ...)
I found this by printing the CTLR register on every change for
debugging purpose.
The patches works fine for us. We have no problems with it up to now.
>How-To-Repeat:
not relevant.
>Fix:
The following patches to the pcidevs-database, if_wm.c and if_wmreg.h
enables support for the 82575
found on the Intel X38ML-Serverboard. The set of pcidevs added to the
pcidevs-database includes only the 82575
version (not the 82576 ones), but all of them.
I cannot garantie that other chips as the i82575EB (0x10a7) will work.
(the two BG-versions will be recognized too ...)
We are currently running an "upgraded" version of the wm-driver from
NetBSD-4.0 - upgraded from current version
some time ago. We have needed support for some additional chips ...
I've verified that there is still no support for the 82575/82576 in
current, but I cannot garantie that
the line numbers matches the current version or that there are no
effects that belongs to the latest changes
in the LWP management in NetBSD 5.0 and later. Sorry.
--- pcidevs 2009/04/14 12:32:59 1.3
+++ pcidevs 2009/12/07 14:36:01
@@ -2045,6 +2045,8 @@
product INTEL 82546GB_QUAD_COPPER 0x1099 i82546GB quad-port Gigabit Ethernet
product INTEL 82573L 0x109a i82573L Gigabit Ethernet
product INTEL 82571EB_QUAD_COPPER 0x10a4 i82571EB quad-1000baseT Ethernet
+product INTEL 82575EB_COPPER 0x10a7 i82575EB dual-1000baseT Ethernet
+product INTEL 82575EB_FIBER_SERDES 0x10a9 i82575EB dual-1000baseX Ethernet
(SERDES)
product INTEL 82546GB_QUAD_COPPER_KSP3 0x10b5 i82546GB quad-port Gigabit
Ethernet (KSP3)
product INTEL 82572EI 0x10b9 i82572EI 1000baseT Ethernet
product INTEL 80K3LAN_CPR_SPT 0x10ba i80003 1000baseT Ethernet
@@ -2060,8 +2062,10 @@
product INTEL 82801I_IGP_M_V 0x10cb i82801H IGP (MV) LAN Controller
product INTEL 82801J_D_BM_LF 0x10cd i82801J (LF) LAN Controller
product INTEL 82574L 0x10d3 i82574L 1000baseT Ethernet
+product INTEL 82575GB_QUAD_COPPER 0x10d6 i82575GB quad-1000baseT Ethernet
product INTEL 82567LM_3 0x10de i82567LM-3 LAN Controller
product INTEL 82567LF_3 0x10df i82567LF-3 LAN Controller
+product INTEL 82575GB_QUAD_COPPER_PM 0x10e2 i82575GB Quad-1000baseT Ethernet
(PM)
product INTEL 82801I_IGP_M_AMT 0x10f5 82801I Mobile (AMT) LAN Controller
product INTEL 82815_DC100_HUB 0x1100 82815 Hub
product INTEL 82815_DC100_AGP 0x1101 82815 AGP
--- pcidevs.h 2009/04/14 12:32:59 1.3
+++ pcidevs.h 2009/12/07 14:36:13
@@ -2052,6 +2052,9 @@
#define PCI_PRODUCT_INTEL_82546GB_QUAD_COPPER 0x1099 /*
i82546GB quad-port Gigabit Ethernet */
#define PCI_PRODUCT_INTEL_82573L 0x109a /* i82573L
Gigabit Ethernet */
#define PCI_PRODUCT_INTEL_82571EB_QUAD_COPPER 0x10a4 /*
i82571EB quad-1000baseT Ethernet */
+#define PCI_PRODUCT_INTEL_82571EB_QUAD_COPPER 0x10a4 /*
i82571EB quad-1000baseT Ethernet */
+#define PCI_PRODUCT_INTEL_82575EB_COPPER 0x10A7
+#define PCI_PRODUCT_INTEL_82575EB_FIBER_SERDES 0x10A9
#define PCI_PRODUCT_INTEL_82546GB_QUAD_COPPER_KSP3 0x10b5
/* i82546GB quad-port Gigabit Ethernet (KSP3) */
#define PCI_PRODUCT_INTEL_82572EI 0x10b9 /* i82572EI
1000baseT Ethernet */
#define PCI_PRODUCT_INTEL_80K3LAN_CPR_SPT 0x10ba /*
i80003 1000baseT Ethernet */
@@ -2067,8 +2070,10 @@
#define PCI_PRODUCT_INTEL_82801H_IGP_M_V 0x10cb /*
i82801H IGP (MV) LAN Controller */
#define PCI_PRODUCT_INTEL_82801J_D_BM_LF 0x10cd /*
i82801J (LF) LAN Controller */
#define PCI_PRODUCT_INTEL_82574L 0x10d3 /* i82574L
1000baseT Ethernet */
+#define PCI_PRODUCT_INTEL_82575GB_QUAD_COPPER 0x10D6
#define PCI_PRODUCT_INTEL_82567LM_3 0x10de /* i82567LM-3
LAN Controller */
#define PCI_PRODUCT_INTEL_82567LF_3 0x10df /* i82567LF-3
LAN Controller */
+#define PCI_PRODUCT_INTEL_82575GB_QUAD_COPPER_PM 0x10E2
#define PCI_PRODUCT_INTEL_82801I_IGP_M_AMT 0x10f5 /*
82801I Mobile (AMT) LAN Controller */
#define PCI_PRODUCT_INTEL_82815_DC100_HUB 0x1100 /*
82815 Hub */
#define PCI_PRODUCT_INTEL_82815_DC100_AGP 0x1101 /*
82815 AGP */
--- pcidevs_data.h 2009/04/14 12:32:59 1.3
+++ pcidevs_data.h 2009/12/07 14:36:45
@@ -7060,6 +7060,14 @@
"i82571EB quad-1000baseT Ethernet",
},
{
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82575EB_COPPER,
+ "i82575EB dual-1000baseT Ethernet",
+ },
+ {
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82575EB_FIBER_SERDES,
+ "i82575EB dual-1000baseX Ethernet (SERDES)",
+ },
+ {
PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82546GB_QUAD_COPPER_KSP3,
"i82546GB quad-port Gigabit Ethernet (KSP3)",
},
@@ -7120,6 +7128,10 @@
"i82574L 1000baseT Ethernet",
},
{
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82575GB_QUAD_COPPER,
+ "i82575GB quad-1000baseT Ethernet",
+ },
+ {
PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82567LM_3,
"i82567LM-3 LAN Controller",
},
@@ -7128,6 +7140,10 @@
"i82567LF-3 LAN Controller",
},
{
+ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82575GB_QUAD_COPPER_PM,
+ "i82575GB Quad-1000baseT Ethernet (PM)",
+ },
+ {
PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801I_IGP_M_AMT,
"82801I Mobile (AMT) LAN Controller",
},
@@ -13196,4 +13212,4 @@
"Video Controller",
},
};
-const int pci_nproducts = 2702;
+const int pci_nproducts = 2706;
--- if_wmreg.h 2009/04/14 12:33:22 1.3
+++ if_wmreg.h 2009/12/07 14:35:40
@@ -332,9 +332,11 @@
#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_SGMII 0x00800000
#define CTRL_EXT_LINK_MODE_TBI 0x00C00000
#define CTRL_EXT_LINK_MODE_KMRN 0x00000000
#define CTRL_EXT_LINK_MODE_SERDES 0x00C00000
+#define CTRL_EXT_I2C_ENA 0x02000000 /* I2C enable */
#define CTRL_EXT_DRV_LOAD 0x10000000
@@ -348,6 +350,12 @@
#define MDIC_I (1U << 29) /* interrupt on MDI complete */
#define MDIC_E (1U << 30) /* MDI error */
+#define WMREG_SCTL 0x0024 /* SerDes Control - RW */
+#define SCTL_CTL_READY (1U << 31) /* also used for other control
registers on the 82575 for the no-EEPROM case */
+#define SCTL_CTL_DATA_MASK 0x000000ff /* also used for other control
registers on the 82575 for the no-EEPROM case */
+#define SCTL_CTL_ADDR_SHIFT 8 /* also used for other control
registers on the 82575 for the no-EEPROM case */
+#define SCTL_CTL_POLL_TIMEOUT 640 /* also used for other control
registers on the 82575 for the no-EEPROM case */
+
#define WMREG_FCAL 0x0028 /* Flow Control Address Low */
#define FCAL_CONST 0x00c28001 /* Flow Control MAC addr low */
@@ -438,25 +446,50 @@
#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) */
#define WMREG_OLD_RDBA1_LO 0x0138 /* Receive Descriptor Base Low (ring
1) */
@@ -582,6 +615,11 @@
#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 */
#define WMREG_AIT 0x0458 /* Adaptive IFS Throttle */
@@ -608,6 +646,28 @@
#define WMREG_PBS 0x1000 /* Packet Buffer Size (ICH8 only ?) */
+#define WMREG_EICS 0x01520 /* Ext. Interrupt Cause Set - W0 */
+#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 */
@@ -622,6 +682,8 @@
#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_RXERRC 0x400C /* receive error Count - R/clr */
#define WMREG_COLC 0x4028 /* collision Count - R/clr */
#define WMREG_XONRXC 0x4048 /* XON Rx Count - R/clr */
@@ -662,6 +724,10 @@
#define WMREG_MANC2H 0x5860 /* Managment Control To Host - RW */
+#define WMREG_CCMCTL 0x5b48 /* CCM Control Register */
+#define WMREG_GIOCTL 0x5b44 /* GIO Analog 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 */
--- if_wm.c 2009/04/14 12:33:48 1.3
+++ if_wm.c 2009/12/07 14:37:24
@@ -253,6 +253,7 @@
WM_T_ICH8, /* ICH8 LAN */
WM_T_ICH9, /* ICH9 LAN */
WM_T_ICH10, /* ICH10 LAN */
+ WM_T_82575, /* i82575 */
} wm_chip_type;
#define WM_LINKUP_TIMEOUT 50
@@ -561,6 +562,9 @@
static int wm_gmii_i82544_readreg(struct device *, int, int);
static void wm_gmii_i82544_writereg(struct device *, int, int, int);
+static int wm_gmii_i82575_readreg(struct device *, int, int);
+static void wm_gmii_i82575_writereg(struct device *, int, int, int);
+
static int wm_gmii_i80003_readreg(struct device *, int, int);
static void wm_gmii_i80003_writereg(struct device *, int, int, int);
@@ -894,6 +898,20 @@
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82801J_D_BM_LF,
"i82801J (LF) LAN Controller",
WM_T_ICH10, WMP_F_1000T },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82575EB_COPPER,
+ "i82575EB dual-1000baseT Ethernet",
+ WM_T_82575, WMP_F_1000T },
+#if 0 /* not shure 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,
+ "i82575EB dual-1000baseX Ethernet (SERDES)",
+ WM_T_82575, WMP_F_SERDES },
+#endif
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82575GB_QUAD_COPPER,
+ "i82575GB Quad-1000baseT Ethernet",
+ WM_T_82575, WMP_F_1000T },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82575GB_QUAD_COPPER_PM,
+ "i82575GB Quad-1000baseT Ethernet (PM)",
+ WM_T_82575, WMP_F_1000T },
{ 0, 0,
NULL,
0, 0 },
@@ -955,6 +973,26 @@
return (0);
}
+static inline void _82575_write_8bit_ctlr_reg(struct wm_softc *sc, uint32_t
reg, uint32_t off, uint32_t data)
+{
+ uint32_t regval = (data & SCTL_CTL_DATA_MASK) | (off << SCTL_CTL_ADDR_SHIFT);
+ int i;
+
+ 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",
+ sc->sc_dev.dv_xname, reg);
+ }
+}
+
static void
wm_attach(struct device *parent, struct device *self, void *aux)
{
@@ -1300,6 +1338,38 @@
wm_reset(sc);
switch (sc->sc_type) {
+ case WM_T_82575:
+ reg = CSR_READ(sc, WMREG_EECD);
+ if ((reg & EECD_EE_PRES) == 0) {
+ /* special case - for 82575 - need to do manual init
... */
+ /* remark: this is untested code - we have no board
without EEPROM
+ * same setup as mentioned int the freeBSD
driver for the i82575
+ */
+ sc->sc_flags |= WM_F_EEPROM_INVALID; /* mark no EEPROM
present ... */
+
+ /* SerDes configuration via SERDESCTRL */
+ _82575_write_8bit_ctlr_reg(sc, WMREG_SCTL, 0x00, 0x0C);
+ _82575_write_8bit_ctlr_reg(sc, WMREG_SCTL, 0x01, 0x78);
+ _82575_write_8bit_ctlr_reg(sc, WMREG_SCTL, 0x1B, 0x23);
+ _82575_write_8bit_ctlr_reg(sc, WMREG_SCTL, 0x23, 0x15);
+
+ /* CCM configuration via CCMCTL register */
+ _82575_write_8bit_ctlr_reg(sc, WMREG_CCMCTL, 0x14,
0x00);
+ _82575_write_8bit_ctlr_reg(sc, WMREG_CCMCTL, 0x10,
0x00);
+
+ /* PCIe lanes configuration */
+ _82575_write_8bit_ctlr_reg(sc, WMREG_GIOCTL, 0x00,
0xEC);
+ _82575_write_8bit_ctlr_reg(sc, WMREG_GIOCTL, 0x61,
0xDF);
+ _82575_write_8bit_ctlr_reg(sc, WMREG_GIOCTL, 0x34,
0x05);
+ _82575_write_8bit_ctlr_reg(sc, WMREG_GIOCTL, 0x2F,
0x81);
+
+ /* PCIe PLL Configuration */
+ _82575_write_8bit_ctlr_reg(sc, WMREG_SCCTL, 0x02, 0x47);
+ _82575_write_8bit_ctlr_reg(sc, WMREG_SCCTL, 0x14, 0x00);
+ _82575_write_8bit_ctlr_reg(sc, WMREG_SCCTL, 0x10, 0x00);
+
+ }
+ /* fall throught ... */
case WM_T_82571:
case WM_T_82572:
case WM_T_82573:
@@ -1346,6 +1416,8 @@
sc->sc_flags |= WM_F_EEPROM_EERDEEWR;
else if (sc->sc_type > WM_T_82544)
sc->sc_flags |= WM_F_EEPROM_HANDSHAKE;
+ else if (sc->sc_type == WM_T_82575)
+ sc->sc_flags |= WM_F_EEPROM_EERDEEWR | WM_F_SWFW_SYNC; /* XXXX
just like 80003 .... just a guess ... */
if (sc->sc_type <= WM_T_82544)
sc->sc_ee_addrbits = 6;
@@ -1365,7 +1437,7 @@
} else if ((sc->sc_type == WM_T_82573 || sc->sc_type == WM_T_82574) &&
(wm_is_onboard_nvm_eeprom(sc) == 0)) {
sc->sc_flags |= WM_F_EEPROM_FLASH;
- } else {
+ } else if (!(sc->sc_flags & WM_F_EEPROM_INVALID)) {
/* Assume everything else is SPI. */
reg = CSR_READ(sc, WMREG_EECD);
sc->sc_flags |= WM_F_EEPROM_SPI;
@@ -1382,7 +1454,7 @@
* Validate the EEPROM checksum. If the checksum fails, flag this for
* later, so we can fail future reads from the EEPROM.
*/
- if (wm_validate_eeprom_checksum(sc)) {
+ if (!(sc->sc_flags & WM_F_EEPROM_INVALID) &&
wm_validate_eeprom_checksum(sc)) {
/*
* Read twice again because some PCI-e parts fail the first
* check due to the link being in sleep state.
@@ -1434,7 +1506,8 @@
* 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) {
+ || sc->sc_type == WM_T_82571 || sc->sc_type == WM_T_80003
+ || sc->sc_type == WM_T_82575) {
if ((CSR_READ(sc, WMREG_STATUS) >> STATUS_FUNCID_SHIFT) & 1)
enaddr[5] ^= 1;
}
@@ -1547,6 +1620,21 @@
|| sc->sc_type == WM_T_82574) {
/* STATUS_TBIMODE reserved/reused, can't rely on it */
wm_gmii_mediainit(sc);
+ } else if (sc->sc_type >= WM_T_82575) {
+ reg = CSR_READ(sc, WMREG_CTRL_EXT);
+ if ((reg & CTRL_EXT_LINK_MODE_MASK) ==
CTRL_EXT_LINK_MODE_SERDES) {
+ reg |= CTRL_EXT_I2C_ENA;
+aprint_error("%s: CTRL_EXT 0x%08x - WARNING - internal SERDES - still not
supported ...\n", sc->sc_dev.dv_xname, reg);
+wm_reset(sc); goto fail_5;
+ } else if (reg & CTRL_EXT_LINK_MODE_SGMII) {
+ reg |= CTRL_EXT_I2C_ENA;
+aprint_error("%s: CTRL_EXT 0x%08x - WARNING - SGMII - still not supported
...\n", sc->sc_dev.dv_xname, reg);
+wm_reset(sc); goto fail_5;
+ } else {
+ reg &= ~CTRL_EXT_I2C_ENA;
+ }
+ CSR_WRITE(sc, WMREG_CTRL_EXT, reg);
+ wm_gmii_mediainit(sc);
} else if (sc->sc_type < WM_T_82543 ||
(CSR_READ(sc, WMREG_STATUS) & STATUS_TBIMODE) != 0) {
if (wmp->wmp_flags & WMP_F_1000T)
@@ -3011,6 +3099,7 @@
case WM_T_82571:
case WM_T_82572:
case WM_T_80003:
+ case WM_T_82575: /* XXXX not 100% shure, but set in
freebsd driver .. */
sc->sc_pba = PBA_32K;
break;
case WM_T_82573:
@@ -3038,7 +3127,7 @@
sc->sc_ctrl |= CTRL_GIO_M_DIS;
CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
- while (timeout) {
+ while (timeout--) {
if ((CSR_READ(sc, WMREG_STATUS) & STATUS_GIO_M_ENA) ==
0)
break;
delay(100);
@@ -3202,6 +3291,7 @@
case WM_T_ICH8:
case WM_T_ICH9:
case WM_T_ICH10:
+ case WM_T_82575:
if (wm_check_mng_mode(sc) != 0)
wm_get_hw_control(sc);
break;
@@ -3232,10 +3322,15 @@
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_type < WM_T_82575) {
+ 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));
+ } else { /* remark: not shure if RX-part can be initialized
here - better to it below ... */
+ CSR_WRITE(sc, WMREG_TXDCTL, TXDCTL_QUEUE_ENABLE |
TXDCTL_PTHRESH(0) |
+ TXDCTL_HTHRESH(0) | TXDCTL_WTHRESH(0));
+ }
}
CSR_WRITE(sc, WMREG_TQSA_LO, 0);
CSR_WRITE(sc, WMREG_TQSA_HI, 0);
@@ -3269,10 +3364,25 @@
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_type >= WM_T_82575) {
+ /* setup interupt moderation for the all used interrupt
queues ... */
+ CSR_WRITE(sc, WMREG_EITR(0), 450); /* default
igb_ave_latency from freebsd-driver ... - not shure if this makes any sence */
+ if (MCLBYTES & ((1 << SRRCTL_BSIZEPKT_SHIFT) - 1))
+ panic("wm_init: MCLBYTES %d unsupported for
82575", MCLBYTES);
+ CSR_WRITE(sc, WMREG_SRRCTL, SRRCTL_DESCTYPE_LEGACY |
(MCLBYTES >> SRRCTL_BSIZEPKT_SHIFT));
+#if 1 /* values from freebsd - not shure if they are good ... */
+ CSR_WRITE(sc, WMREG_RXDCTL, RXDCTL_QUEUE_ENABLE |
RXDCTL_PTHRESH(16) |
+ RXDCTL_HTHRESH(8) | RXDCTL_WTHRESH(1));
+#else
+ CSR_WRITE(sc, WMREG_RXDCTL, RXDCTL_QUEUE_ENABLE |
RXDCTL_PTHRESH(0) |
+ RXDCTL_HTHRESH(0) | RXDCTL_WTHRESH(1));
+#endif
+ } else { /* some registers that are no longer present, have
different semantics or must be set later on 82575 and later ... */
+ 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];
@@ -3288,7 +3398,7 @@
wm_rxdrain(sc);
goto out;
}
- } else
+ } else if (sc->sc_type < WM_T_82575) /* need to enable reciever
prior setting RDT on 82575 and later */
WM_INIT_RXDESC(sc, i);
}
sc->sc_rxptr = 0;
@@ -3331,7 +3441,8 @@
/* Write the control registers. */
CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
- if (sc->sc_type >= WM_T_80003 && (sc->sc_flags & WM_F_HAS_MII)) {
+ if (sc->sc_type>= WM_T_82575) { /* cannot fill in RDT - even if the
EN-bit is set in RXDCTL, it is ignored until EN in RCTL is set ... */
+ } else if (sc->sc_type >= WM_T_80003 && (sc->sc_flags & WM_F_HAS_MII)) {
int val;
val = CSR_READ(sc, WMREG_CTRL_EXT);
val &= ~CTRL_EXT_LINK_MODE_MASK;
@@ -3424,6 +3535,7 @@
TCTL_COLD(TX_COLLISION_DISTANCE_FDX);
if (sc->sc_type >= WM_T_82571)
sc->sc_tctl |= TCTL_MULR;
+/* XXXX - order of WM_T_xxxx entries - the 82575 falls in here - this is
correct here - freebsd-driver does it too ... */
if (sc->sc_type >= WM_T_80003)
sc->sc_tctl |= TCTL_RTLC;
CSR_WRITE(sc, WMREG_TCTL, sc->sc_tctl);
@@ -3443,8 +3555,12 @@
sc->sc_rctl = RCTL_EN | RCTL_LBM_NONE | RCTL_RDMTS_1_2 | RCTL_DPF
| RCTL_MO(sc->sc_mchash_type);
+ if (sc->sc_type >= WM_T_82575) {
+ sc->sc_rctl |= RCTL_LPE;
+ CSR_WRITE(sc, WMREG_RLPML, ETHER_MAX_LEN_JUMBO);
+ }
/* 82573 doesn't support jumbo frame */
- if (sc->sc_type != WM_T_82573 && sc->sc_type != WM_T_82574 &&
+ else if (sc->sc_type != WM_T_82573 && sc->sc_type != WM_T_82574 &&
sc->sc_type != WM_T_ICH8)
sc->sc_rctl |= RCTL_LPE;
@@ -3472,6 +3588,11 @@
/* Set the receive filter. */
wm_set_filter(sc);
+ if (sc->sc_type>= WM_T_82575) { /* now fill in RDT - RCTL EN-bit has
been set in the last function ... */
+ CSR_WRITE(sc, WMREG_RDH, 0); /* this is read-only on 82576, but
freebsd driver write it too ... */
+ 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);
@@ -3540,6 +3661,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 EN bit again - needed for 82575 and
later */
/*
* Clear the interrupt mask to ensure the device cannot assert its
@@ -3583,6 +3705,7 @@
case WM_T_ICH8:
case WM_T_ICH9:
case WM_T_ICH10:
+ case WM_T_82575:
for (i = 10; i > 0; i--) {
if (CSR_READ(sc, WMREG_EECD) & EECD_EE_AUTORD)
break;
@@ -3599,7 +3722,8 @@
}
/* Phy configuration starts after EECD_AUTO_RD is set */
- if (sc->sc_type == WM_T_82573 || sc->sc_type == WM_T_82574)
+/* XXXX - should the 82575 go here too ? - added for security reasons ... */
+ if (sc->sc_type == WM_T_82573 || sc->sc_type == WM_T_82574 ||
sc->sc_type == WM_T_82575)
delay(25000);
}
@@ -3996,7 +4120,9 @@
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_type < WM_T_82575 || (sc->sc_rctl & RCTL_EN)) { /* on 575
and later set RDT only if RX enabled... */
+ WM_INIT_RXDESC(sc, idx);
+ }
return (0);
}
@@ -4463,7 +4589,7 @@
return;
}
}
- if (sc->sc_type == WM_T_80003) {
+ if (sc->sc_type == WM_T_80003 || sc->sc_type == WM_T_82575) { /* XXXXX
is this OK ??? - looks good to me */
func = (CSR_READ(sc, WMREG_STATUS) >> STATUS_FUNCID_SHIFT) & 1;
if (wm_get_swfw_semaphore(sc,
func ? SWFW_PHY1_SM : SWFW_PHY0_SM)) {
@@ -4508,7 +4634,7 @@
if ((sc->sc_type == WM_T_ICH8) || (sc->sc_type == WM_T_ICH9)
|| (sc->sc_type == WM_T_ICH10))
wm_put_swfwhw_semaphore(sc);
- if (sc->sc_type == WM_T_80003)
+ if (sc->sc_type == WM_T_80003 || sc->sc_type == WM_T_82575) /* XXXXX
see above ... */
wm_put_swfw_semaphore(sc, func ? SWFW_PHY1_SM : SWFW_PHY0_SM);
}
@@ -4525,7 +4651,9 @@
/* We have MII. */
sc->sc_flags |= WM_F_HAS_MII;
- if (sc->sc_type >= WM_T_80003)
+ if (sc->sc_type >= WM_T_82575) /* XXXX free bsd-driver sets normal
default values here - but it does it for ich-chips too ... */
+ sc->sc_tipg = TIPG_1000T_DFLT;
+ else if (sc->sc_type >= WM_T_80003)
sc->sc_tipg = TIPG_1000T_80003_DFLT;
else
sc->sc_tipg = TIPG_1000T_DFLT;
@@ -4545,6 +4673,9 @@
if (sc->sc_type == WM_T_ICH10) {
sc->sc_mii.mii_readreg = wm_gmii_bm_readreg;
sc->sc_mii.mii_writereg = wm_gmii_bm_writereg;
+ } else if (sc->sc_type >= WM_T_82575) {
+ sc->sc_mii.mii_readreg = wm_gmii_i82575_readreg;
+ sc->sc_mii.mii_writereg = wm_gmii_i82575_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;
@@ -4812,6 +4943,91 @@
}
/*
+ * wm_gmii_i82575_readreg: [mii interface function]
+ *
+ * Read a PHY register on the GMII.
+ */
+static int
+wm_gmii_i82575_readreg(struct device *self, int phy, int reg)
+{
+ struct wm_softc *sc = (void *) self;
+ uint32_t mdic = 0;
+ int i, rv;
+ int func = ((CSR_READ(sc, WMREG_STATUS) >> STATUS_FUNCID_SHIFT) & 1);
+
+ if (wm_get_swfw_semaphore(sc, func ? SWFW_PHY1_SM : SWFW_PHY0_SM)) {
+ aprint_error("%s: failed to get semaphore\n",
sc->sc_dev.dv_xname);
+ return 0;
+ }
+
+ CSR_WRITE(sc, WMREG_MDIC, MDIC_OP_READ | MDIC_PHYADD(phy) |
+ MDIC_REGADD(reg));
+
+ for (i = 0; i < 320; i++) {
+ mdic = CSR_READ(sc, WMREG_MDIC);
+ if (mdic & MDIC_READY)
+ break;
+ delay(10);
+ }
+
+ if ((mdic & MDIC_READY) == 0) {
+ log(LOG_WARNING, "%s: MDIC read timed out: phy %d reg %d\n",
+ sc->sc_dev.dv_xname, phy, reg);
+ rv = 0;
+ } else if (mdic & MDIC_E) {
+#if 0 /* This is normal if no PHY is present. */
+ log(LOG_WARNING, "%s: MDIC read error: phy %d reg %d\n",
+ sc->sc_dev.dv_xname, phy, reg);
+#endif
+ rv = 0;
+ } else {
+ rv = MDIC_DATA(mdic);
+ if (rv == 0xffff)
+ rv = 0;
+ }
+
+ wm_put_swfw_semaphore(sc, func ? SWFW_PHY1_SM : SWFW_PHY0_SM);
+ return (rv);
+}
+
+/*
+ * wm_gmii_i82575_writereg: [mii interface function]
+ *
+ * Write a PHY register on the GMII.
+ */
+static void
+wm_gmii_i82575_writereg(struct device *self, int phy, int reg, int val)
+{
+ struct wm_softc *sc = (void *) self;
+ uint32_t mdic = 0;
+ int i;
+ int func = ((CSR_READ(sc, WMREG_STATUS) >> STATUS_FUNCID_SHIFT) & 1);
+
+ if (wm_get_swfw_semaphore(sc, func ? SWFW_PHY1_SM : SWFW_PHY0_SM)) {
+ aprint_error("%s: failed to get semaphore\n",
sc->sc_dev.dv_xname);
+ return;
+ }
+
+ CSR_WRITE(sc, WMREG_MDIC, MDIC_OP_WRITE | MDIC_PHYADD(phy) |
+ MDIC_REGADD(reg) | MDIC_DATA(val));
+
+ for (i = 0; i < 320; i++) {
+ mdic = CSR_READ(sc, WMREG_MDIC);
+ if (mdic & MDIC_READY)
+ break;
+ delay(10);
+ }
+
+ if ((mdic & MDIC_READY) == 0)
+ log(LOG_WARNING, "%s: MDIC write timed out: phy %d reg %d\n",
+ sc->sc_dev.dv_xname, phy, reg);
+ else if (mdic & MDIC_E)
+ log(LOG_WARNING, "%s: MDIC write error: phy %d reg %d\n",
+ sc->sc_dev.dv_xname, phy, reg);
+ wm_put_swfw_semaphore(sc, func ? SWFW_PHY1_SM : SWFW_PHY0_SM);
+}
+
+/*
* wm_gmii_i80003_readreg: [mii interface function]
*
* Read a PHY register on the kumeran
@@ -5511,6 +5727,7 @@
case WM_T_82572:
case WM_T_82573:
case WM_T_80003:
+ case WM_T_82575:
rv = wm_check_mng_mode_generic(sc);
break;
default:
@@ -5586,6 +5803,7 @@
case WM_T_ICH8:
case WM_T_ICH9:
case WM_T_ICH10:
+ case WM_T_82575:
reg = CSR_READ(sc, WMREG_CTRL_EXT);
CSR_WRITE(sc, WMREG_CTRL_EXT, reg | CTRL_EXT_DRV_LOAD);
break;
>Unformatted:
Home |
Main Index |
Thread Index |
Old Index