Subject: Re: Gigabit Marvell ethernet card not configured
To: None <netbsd-users@netbsd.org>
From: Eye of the Beholder <eye.of.the.8eholder@gmail.com>
List: tech-kern
Date: 04/30/2006 18:36:00
--MP_m8qNVMW_iwBl9z/Vli1US..
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

Hello.

I tried to port the linux driver (sky2.{c,h}) as mr. Rizzo suggested,
but the only things i understood were the printfs and the comments :)
The unified driver from SysKonnect is way more mess than the sky2 one.
So, i tried the OpenBSD driver which is almost the same as the NetBSD one.

Result: It works ok for me with some glitches.

I have attached the necessary files for the change (I used -current sources).

If anynone having this card wants to try it, the steps are the following:

1) cd /usr/src/sys/dev/pci
2) patch -p0 -i 1-pcidevs.diff
3) make -f Makefile.pcidevs
4) patch -p0 -i 2-if_sk.diff
5) config and compile as usual.

I tried to use the minimum code from OpenBSD that worked. There was
other code too but i didn't understand it and when applied it
didn't have any obvious difference, so maybe the code i include is
incomplete and/or buggy. /* disclaimer part incase it blows any computer :) */

My dmesg output is the following:

ppb2 at pci0 dev 28 function 1: Intel 82801FB/FR PCI Express Port #1(rev. 0x03)
pci3 at ppb2 bus 3
pci3: i/o space, memory space enabled, rd/line, wr/inv ok
skc0 at pci3 dev 0 function 0: irq 11
skc0: interrupt moderation is 0 us
skc0: Marvell Yukon-2 EC rev. A2(0x1)
sk0 at skc0 port A: Ethernet address 00:11:2f:58:fa:03
makphy0 at sk0 phy 0: Marvell 88E1111 Gigabit PHY, rev. 2
makphy0: 10baseT, 10baseT-FDX, 100baseTX, 100baseTX-FDX,1000baseT,1000baseT-FDX, auto
ppb3 at pci0 dev 28 function 2: Intel 82801FB/FR PCI Express Port #2(rev. 0x03)
pci4 at ppb3 bus 2
pci4: i/o space, memory space enabled, rd/line, wr/inv ok
skc1 at pci4 dev 0 function 0: irq 10
skc1: interrupt moderation is 0 us
skc1: Marvell Yukon-2 EC rev. A2(0x1)
sk1 at skc1 port A: Ethernet address 00:11:2f:59:02:98
makphy1 at sk1 phy 0: Marvell 88E1111 Gigabit PHY, rev. 2
makphy1: 10baseT, 10baseT-FDX, 100baseTX, 100baseTX-FDX,1000baseT,1000baseT-FDX, auto
sk0: link state changed to UP
sk1: link state changed to DOWN

This is after boot (with cable connected to sk0) .
The following happens after running ifconfig

sk0: link state changed to DOWN
skc0: interrupt moderation is 100 us
sk0: link state changed to UP
sk0: watchdog timeout (every some secs)

My ifconfig output is the following:
sk0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
        address: 00:11:2f:58:fa:03
        media: Ethernet autoselect (100baseTX full-duplex)
        status: active
        inet 192.168.1.5 netmask 0xffffff00 broadcast 192.168.1.255
        inet6 fe80::211:2fff:fe58:fa03%sk0 prefixlen 64 scopeid 0x1

I disconnected my DSL router from the rtk0 card and connected it to the sk0 and i could ping ok the
router and internet, so i guess it works. I haven't tested it enough though.
Glitches:
1) Every some secs watchdog timeout is printed in the console.
2) When using the "shutdownhook_establish" hook, when running reboot/halt the kernel crashes.
When the "shutdownhook_establish" is removed reboot works ok, so i guess there is something wrong
with the sk_shutdown function. (Hint: the OpenBSD code had sk_stop removed from the sk_shutdown, but
it does the same without it)

I am not keen in hardware/NetBSD programming, so please someone with the required knowledge
(mr. Rizzo, mr. Zoulas ?) have a look at it.

I can test any patch that you will apply.

--MP_m8qNVMW_iwBl9z/Vli1US..
Content-Type: text/x-patch; name=1-pcidevs.diff
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename=1-pcidevs.diff

--- pcidevs	2006-04-30 00:23:55.000000000 +0300
+++ pcidevs	2006-04-30 10:54:06.000000000 +0300
@@ -1669,6 +1669,20 @@
 product GALILEO	GT64115		0x4111	GT-64115 System Controller
 product GALILEO	GT64011		0x4146	GT-64011 System Controller
 product GALILEO	SKNET		0x4320	SK-NET Gigabit Ethernet
+product GALILEO YUKONII_8021CU	0x4340	Yukon-II 88E8021CU
+product GALILEO YUKONII_8022CU	0x4341	Yukon-II 88E8022CU
+product GALILEO YUKONII_8061CU	0x4342	Yukon-II 88E8061CU
+product GALILEO YUKONII_8062CU	0x4343	Yukon-II 88E8062CU
+product GALILEO YUKONII_8021X	0x4344	Yukon-II 88E8021X
+product GALILEO YUKONII_8022X	0x4345	Yukon-II 88E8022X
+product GALILEO YUKONII_8061X	0x4346	Yukon-II 88E8061X
+product GALILEO YUKONII_8062X	0x4347	Yukon-II 88E8062X
+product GALILEO YUKON_8035	0x4350	Yukon 88E8035
+product GALILEO YUKON_8036	0x4351	Yukon 88E8036
+product GALILEO YUKON_8038	0x4352	Yukon 88E8038
+product GALILEO YUKON_8052	0x4360	Yukon 88E8052
+product GALILEO YUKON_8050	0x4361	Yukon 88E8050
+product GALILEO YUKON_8053	0x4362	Yukon 88E8053
 product GALILEO	GT64120		0x4620	GT-64120 System Controller
 product GALILEO	BELKIN		0x5005	Belkin Gigabit Ethernet
 product GALILEO	GT64130		0x6320	GT-64130 System Controller

--MP_m8qNVMW_iwBl9z/Vli1US..
Content-Type: text/x-patch; name=2-if_sk.diff
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename=2-if_sk.diff

--- if_skreg.h	2006-04-30 17:49:13.000000000 +0300
+++ if_skreg.h	2006-04-30 17:48:54.000000000 +0300
@@ -107,7 +107,6 @@
  * there are a few 16-bit and 8-bit ones as well.
  */
 
-
 /* Start of remappable register window. */
 #define SK_WIN_BASE		0x0080
 
@@ -322,8 +321,10 @@
 #define SK_CONFIG	0x011A
 #define SK_CHIPVER	0x011B
 #define SK_EPROM0	0x011C
-#define SK_EPROM1	0x011D
-#define SK_EPROM2	0x011E
+#define SK_EPROM1	0x011D		/* yukon/genesis */
+#define SK_Y2_CLKGATE	0x011D		/* yukon 2 */
+#define SK_EPROM2	0x011E		/* yukon/genesis */
+#define SK_Y2_HWRES	0x011E		/* yukon 2 */
 #define SK_EPROM3	0x011F
 #define SK_EP_ADDR	0x0120
 #define SK_EP_DATA	0x0124
@@ -361,28 +362,44 @@
 #define SK_YUKON_EC_U		0xB4
 #define SK_YUKON_EC		0xB6
 #define SK_YUKON_FE		0xB7
+
 #define SK_YUKON_FAMILY(x) ((x) & 0xB0)
-/* known revisions in SK_CONFIG */
+#define SK_IS_GENESIS(sc) \
+    ((sc)->sk_type == SK_GENESIS)
+#define SK_IS_YUKON(sc) \
+    ((sc)->sk_type >= SK_YUKON && (sc)->sk_type <= SK_YUKON_FE)
+#define SK_IS_YUKON2(sc) \
+    ((sc)->sk_type >= SK_YUKON_XL && (sc)->sk_type <= SK_YUKON_FE)
+
+/* Known revisions in SK_CONFIG */
 #define SK_YUKON_LITE_REV_A0	0x0 /* invented, see test in skc_attach */
 #define SK_YUKON_LITE_REV_A1	0x3
 #define SK_YUKON_LITE_REV_A3	0x7
 
+#define SK_YUKON_XL_REV_A0	0x0
+#define SK_YUKON_XL_REV_A1	0x1
+#define SK_YUKON_XL_REV_A2	0x2
+#define SK_YUKON_XL_REV_A3	0x3
+
 #define SK_YUKON_EC_REV_A1	0x0
 #define SK_YUKON_EC_REV_A2	0x1
 #define SK_YUKON_EC_REV_A3	0x2
 
+#define SK_YUKON_EC_U_REV_A0	0x1
+#define SK_YUKON_EC_U_REV_A1	0x2
+
 #define SK_IMCTL_STOP	0x02
 #define SK_IMCTL_START	0x04
 
 /* Number of ticks per usec for interrupt moderation */
-#define SK_IMTIMER_TICKS_GENESIS	54
+#define SK_IMTIMER_TICKS_GENESIS	53
 #define SK_IMTIMER_TICKS_YUKON		78
 #define SK_IMTIMER_TICKS_YUKON_EC	125
 #define SK_IM_USECS(x)		((x) * sk_imtimer_ticks)
+#define SK_IM_DEFAULT 100
+#define SK_IM_MIN 0
+#define SK_IM_MAX 10000
 
-#define SK_IM_MIN	0
-#define SK_IM_DEFAULT	100
-#define SK_IM_MAX	10000
 /*
  * The SK_EPROM0 register contains a byte that describes the
  * amount of SRAM mounted on the NIC. The value also tells if
@@ -421,9 +438,10 @@
 #define SK_CONFIG_SINGLEMAC	0x01
 #define SK_CONFIG_DIS_DSL_CLK	0x02
 
+#define SK_PMD_1000BASETX_ALT	0x31
+#define SK_PMD_1000BASECX	0x43
 #define SK_PMD_1000BASELX	0x4C
 #define SK_PMD_1000BASESX	0x53
-#define SK_PMD_1000BASECX	0x43
 #define SK_PMD_1000BASETX	0x54
 
 /* GPIO bits */
@@ -448,6 +466,20 @@
 #define SK_GPIO_DIR8		0x01000000
 #define SK_GPIO_DIR9           0x02000000
 
+#define	SK_Y2_CLKGATE_LINK2_INACTIVE	0x80	/* port 2 inactive */
+#define	SK_Y2_CLKGATE_LINK2_GATE_DIS	0x40	/* disable clock gate, 2 */
+#define	SK_Y2_CLKGATE_LINK2_CORE_DIS	0x20	/* disable core clock, 2 */
+#define	SK_Y2_CLKGATE_LINK2_PCI_DIS	0x10	/* disable pci clock, 2 */
+#define	SK_Y2_CLKGATE_LINK1_INACTIVE	0x08	/* port 1 inactive */
+#define	SK_Y2_CLKGATE_LINK1_GATE_DIS	0x04	/* disable clock gate, 1 */
+#define	SK_Y2_CLKGATE_LINK1_CORE_DIS	0x02	/* disable core clock, 1 */
+#define	SK_Y2_CLKGATE_LINK1_PCI_DIS	0x01	/* disable pci clock, 1 */
+
+#define	SK_Y2_HWRES_LINK_1	0x01
+#define	SK_Y2_HWRES_LINK_2	0x02
+#define	SK_Y2_HWRES_LINK_MASK	(SK_Y2_HWRES_LINK_1 | SK_Y2_HWRES_LINK_2)
+#define	SK_Y2_HWRES_LINK_DUAL	(SK_Y2_HWRES_LINK_1 | SK_Y2_HWRES_LINK_2)
+
 /* Block 3 Ram interface and MAC arbiter registers */
 #define SK_RAMADDR	0x0180
 #define SK_RAMDATA0	0x0184
@@ -613,6 +645,28 @@
 #define SK_RXQ1_TEST1		0x043C
 #define SK_RXQ1_TEST2		0x0440
 #define SK_RXQ1_TEST3		0x0444
+/* yukon-2 only */
+#define SK_RXQ1_Y2_WM		0x0440
+#define SK_RXQ1_Y2_AL		0x0442
+#define SK_RXQ1_Y2_RSP		0x0444
+#define SK_RXQ1_Y2_RSL		0x0446
+#define SK_RXQ1_Y2_RP		0x0448
+#define SK_RXQ1_Y2_RL		0x044A
+#define SK_RXQ1_Y2_WP		0x044C
+#define SK_RXQ1_Y2_WSP		0x044D
+#define SK_RXQ1_Y2_WL		0x044E
+#define SK_RXQ1_Y2_WSL		0x044F
+/* yukon-2 only (prefetch unit) */
+#define SK_RXQ1_Y2_PREF_CSR	0x0450
+#define SK_RXQ1_Y2_PREF_LIDX	0x0454
+#define SK_RXQ1_Y2_PREF_ADDRLO	0x0458
+#define SK_RXQ1_Y2_PREF_ADDRHI	0x045C
+#define SK_RXQ1_Y2_PREF_GETIDX	0x0460
+#define SK_RXQ1_Y2_PREF_PUTIDX	0x0464
+#define SK_RXQ1_Y2_PREF_FIFOWP	0x0470
+#define SK_RXQ1_Y2_PREF_FIFORP	0x0474
+#define SK_RXQ1_Y2_PREF_FIFOWM	0x0478
+#define SK_RXQ1_Y2_PREF_FIFOLV	0x047C
 
 /* Block 9 -- RX queue 2 */
 #define SK_RXQ2_BUFCNT		0x0480
@@ -637,6 +691,28 @@
 #define SK_RXQ2_TEST1		0x04BC
 #define SK_RXQ2_TEST2		0x04C0
 #define SK_RXQ2_TEST3		0x04C4
+/* yukon-2 only */
+#define SK_RXQ2_Y2_WM		0x04C0
+#define SK_RXQ2_Y2_AL		0x04C2
+#define SK_RXQ2_Y2_RSP		0x04C4
+#define SK_RXQ2_Y2_RSL		0x04C6
+#define SK_RXQ2_Y2_RP		0x04C8
+#define SK_RXQ2_Y2_RL		0x04CA
+#define SK_RXQ2_Y2_WP		0x04CC
+#define SK_RXQ2_Y2_WSP		0x04CD
+#define SK_RXQ2_Y2_WL		0x04CE
+#define SK_RXQ2_Y2_WSL		0x04CF
+/* yukon-2 only (prefetch unit) */
+#define SK_RXQ2_Y2_PREF_CSR	0x04D0
+#define SK_RXQ2_Y2_PREF_LIDX	0x04D4
+#define SK_RXQ2_Y2_PREF_ADDRLO	0x04D8
+#define SK_RXQ2_Y2_PREF_ADDRHI	0x04DC
+#define SK_RXQ2_Y2_PREF_GETIDX	0x04E0
+#define SK_RXQ2_Y2_PREF_PUTIDX	0x04E4
+#define SK_RXQ2_Y2_PREF_FIFOWP	0x04F0
+#define SK_RXQ2_Y2_PREF_FIFORP	0x04F4
+#define SK_RXQ2_Y2_PREF_FIFOWM	0x04F8
+#define SK_RXQ2_Y2_PREF_FIFOLV	0x04FC
 
 #define SK_RXBMU_CLR_IRQ_ERR		0x00000001
 #define SK_RXBMU_CLR_IRQ_EOF		0x00000002
@@ -695,6 +771,28 @@
 #define SK_TXQS1_TEST1		0x063C
 #define SK_TXQS1_TEST2		0x0640
 #define SK_TXQS1_TEST3		0x0644
+/* yukon-2 only */
+#define SK_TXQS1_Y2_WM		0x0640
+#define SK_TXQS1_Y2_AL		0x0642
+#define SK_TXQS1_Y2_RSP		0x0644
+#define SK_TXQS1_Y2_RSL		0x0646
+#define SK_TXQS1_Y2_RP		0x0648
+#define SK_TXQS1_Y2_RL		0x064A
+#define SK_TXQS1_Y2_WP		0x064C
+#define SK_TXQS1_Y2_WSP		0x064D
+#define SK_TXQS1_Y2_WL		0x064E
+#define SK_TXQS1_Y2_WSL		0x064F
+/* yukon-2 only (prefetch unit) */
+#define SK_TXQS1_Y2_PREF_CSR	0x0650
+#define SK_TXQS1_Y2_PREF_LIDX	0x0654
+#define SK_TXQS1_Y2_PREF_ADDRLO	0x0658
+#define SK_TXQS1_Y2_PREF_ADDRHI	0x065C
+#define SK_TXQS1_Y2_PREF_GETIDX	0x0660
+#define SK_TXQS1_Y2_PREF_PUTIDX	0x0664
+#define SK_TXQS1_Y2_PREF_FIFOWP	0x0670
+#define SK_TXQS1_Y2_PREF_FIFORP	0x0674
+#define SK_TXQS1_Y2_PREF_FIFOWM	0x0678
+#define SK_TXQS1_Y2_PREF_FIFOLV	0x067C
 
 /* Block 13 -- TX async queue 1 */
 #define SK_TXQA1_BUFCNT		0x0680
@@ -717,6 +815,28 @@
 #define SK_TXQA1_TEST1		0x06BC
 #define SK_TXQA1_TEST2		0x06C0
 #define SK_TXQA1_TEST3		0x06C4
+/* yukon-2 only */
+#define SK_TXQA1_Y2_WM		0x06C0
+#define SK_TXQA1_Y2_AL		0x06C2
+#define SK_TXQA1_Y2_RSP		0x06C4
+#define SK_TXQA1_Y2_RSL		0x06C6
+#define SK_TXQA1_Y2_RP		0x06C8
+#define SK_TXQA1_Y2_RL		0x06CA
+#define SK_TXQA1_Y2_WP		0x06CC
+#define SK_TXQA1_Y2_WSP		0x06CD
+#define SK_TXQA1_Y2_WL		0x06CE
+#define SK_TXQA1_Y2_WSL		0x06CF
+/* yukon-2 only (prefetch unit) */
+#define SK_TXQA1_Y2_PREF_CSR	0x06D0
+#define SK_TXQA1_Y2_PREF_LIDX	0x06D4
+#define SK_TXQA1_Y2_PREF_ADDRLO	0x06D8
+#define SK_TXQA1_Y2_PREF_ADDRHI	0x06DC
+#define SK_TXQA1_Y2_PREF_GETIDX	0x06E0
+#define SK_TXQA1_Y2_PREF_PUTIDX	0x06E4
+#define SK_TXQA1_Y2_PREF_FIFOWP	0x06F0
+#define SK_TXQA1_Y2_PREF_FIFORP	0x06F4
+#define SK_TXQA1_Y2_PREF_FIFOWM	0x06F8
+#define SK_TXQA1_Y2_PREF_FIFOLV	0x06FC
 
 /* Block 14 -- TX sync queue 2 */
 #define SK_TXQS2_BUFCNT		0x0700
@@ -739,6 +859,28 @@
 #define SK_TXQS2_TEST1		0x073C
 #define SK_TXQS2_TEST2		0x0740
 #define SK_TXQS2_TEST3		0x0744
+/* yukon-2 only */
+#define SK_TXQS2_Y2_WM		0x0740
+#define SK_TXQS2_Y2_AL		0x0742
+#define SK_TXQS2_Y2_RSP		0x0744
+#define SK_TXQS2_Y2_RSL		0x0746
+#define SK_TXQS2_Y2_RP		0x0748
+#define SK_TXQS2_Y2_RL		0x074A
+#define SK_TXQS2_Y2_WP		0x074C
+#define SK_TXQS2_Y2_WSP		0x074D
+#define SK_TXQS2_Y2_WL		0x074E
+#define SK_TXQS2_Y2_WSL		0x074F
+/* yukon-2 only (prefetch unit) */
+#define SK_TXQS2_Y2_PREF_CSR	0x0750
+#define SK_TXQS2_Y2_PREF_LIDX	0x0754
+#define SK_TXQS2_Y2_PREF_ADDRLO	0x0758
+#define SK_TXQS2_Y2_PREF_ADDRHI	0x075C
+#define SK_TXQS2_Y2_PREF_GETIDX	0x0760
+#define SK_TXQS2_Y2_PREF_PUTIDX	0x0764
+#define SK_TXQS2_Y2_PREF_FIFOWP	0x0770
+#define SK_TXQS2_Y2_PREF_FIFORP	0x0774
+#define SK_TXQS2_Y2_PREF_FIFOWM	0x0778
+#define SK_TXQS2_Y2_PREF_FIFOLV	0x077C
 
 /* Block 15 -- TX async queue 2 */
 #define SK_TXQA2_BUFCNT		0x0780
@@ -761,6 +903,28 @@
 #define SK_TXQA2_TEST1		0x07BC
 #define SK_TXQA2_TEST2		0x07C0
 #define SK_TXQA2_TEST3		0x07C4
+/* yukon-2 only */
+#define SK_TXQA2_Y2_WM		0x07C0
+#define SK_TXQA2_Y2_AL		0x07C2
+#define SK_TXQA2_Y2_RSP		0x07C4
+#define SK_TXQA2_Y2_RSL		0x07C6
+#define SK_TXQA2_Y2_RP		0x07C8
+#define SK_TXQA2_Y2_RL		0x07CA
+#define SK_TXQA2_Y2_WP		0x07CC
+#define SK_TXQA2_Y2_WSP		0x07CD
+#define SK_TXQA2_Y2_WL		0x07CE
+#define SK_TXQA2_Y2_WSL		0x07CF
+/* yukon-2 only (prefetch unit) */
+#define SK_TXQA2_Y2_PREF_CSR	0x07D0
+#define SK_TXQA2_Y2_PREF_LIDX	0x07D4
+#define SK_TXQA2_Y2_PREF_ADDRLO	0x07D8
+#define SK_TXQA2_Y2_PREF_ADDRHI	0x07DC
+#define SK_TXQA2_Y2_PREF_GETIDX	0x07E0
+#define SK_TXQA2_Y2_PREF_PUTIDX	0x07E4
+#define SK_TXQA2_Y2_PREF_FIFOWP	0x07F0
+#define SK_TXQA2_Y2_PREF_FIFORP	0x07F4
+#define SK_TXQA2_Y2_PREF_FIFOWM	0x07F8
+#define SK_TXQA2_Y2_PREF_FIFOLV	0x07FC
 
 #define SK_TXBMU_CLR_IRQ_ERR		0x00000001
 #define SK_TXBMU_CLR_IRQ_EOF		0x00000002
@@ -1250,10 +1414,6 @@
 #define SK_PCI_PWRMGMTCAP	0x004A /* 16 bits */
 #define SK_PCI_PWRMGMTCTRL	0x004C /* 16 bits */
 #define SK_PCI_PME_EVENT	0x004F
-#define SK_PCI_VPD_CAPID	0x0050
-#define SK_PCI_VPD_NEXTPTR	0x0051
-#define SK_PCI_VPD_ADDR		0x0052
-#define SK_PCI_VPD_DATA		0x0054
 
 #define SK_PSTATE_MASK		0x0003
 #define SK_PSTATE_D0		0x0000
@@ -1263,30 +1423,6 @@
 #define SK_PME_EN		0x0010
 #define SK_PME_STATUS		0x8000
 
-/*
- * VPD flag bit. Set to 0 to initiate a read, will become 1 when
- * read is complete. Set to 1 to initiate a write, will become 0
- * when write is finished.
- */
-#define SK_VPD_FLAG		0x8000
-
-/* VPD structures */
-struct vpd_res {
-	u_int8_t		vr_id;
-	u_int8_t		vr_len;
-	u_int8_t		vr_pad;
-};
-
-struct vpd_key {
-	char			vk_key[2];
-	u_int8_t		vk_len;
-};
-
-#define VPD_RES_ID	0x82	/* ID string */
-#define VPD_RES_READ	0x90	/* start of read only area */
-#define VPD_RES_WRITE	0x81	/* start of read/write area */
-#define VPD_RES_END	0x78	/* end tag */
-
 #define CSR_WRITE_4(sc, reg, val) \
 	bus_space_write_4((sc)->sk_btag, (sc)->sk_bhandle, (reg), (val))
 #define CSR_WRITE_2(sc, reg, val) \
--- if_skvar.h	2006-04-30 17:49:19.000000000 +0300
+++ if_skvar.h	2006-04-30 17:48:54.000000000 +0300
@@ -199,11 +199,11 @@
 	void			*sk_intrhand;	/* irq handler handle */
 	struct resource		*sk_irq;	/* IRQ resource handle */
 	struct resource		*sk_res;	/* I/O or shared mem handle */
+        u_int8_t                sk_coppertype;
+        u_int8_t                sk_macs;        /* # of MACs */
 	u_int8_t		sk_type;
 	u_int8_t		sk_rev;
   	const char		*sk_name;
-	char			*sk_vpd_prodname;
-	char			*sk_vpd_readonly;
 	u_int32_t		sk_rboff;	/* RAMbuffer offset */
 	u_int32_t		sk_ramsize;	/* amount of RAM on NIC */
 	u_int32_t		sk_pmd;		/* physical media type */
@@ -248,6 +248,8 @@
 
 struct skc_attach_args {
 	u_int16_t	skc_port;
+	u_int8_t	skc_type;
+	u_int8_t	skc_rev;
 };
 
 #endif /* _DEV_PCI_IF_SKVAR_H_ */
--- if_sk.c	2006-04-30 17:49:08.000000000 +0300
+++ if_sk.c	2006-04-30 17:48:54.000000000 +0300
@@ -148,6 +148,12 @@
 #include <netinet/if_ether.h>
 #endif
 
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#include <netinet/udp.h>
+
 #include <net/if_media.h>
 
 #if NBPFILTER > 0
@@ -201,11 +207,6 @@
 void sk_jfree(struct mbuf *, caddr_t, size_t, void *);
 int sk_init_rx_ring(struct sk_if_softc *);
 int sk_init_tx_ring(struct sk_if_softc *);
-u_int8_t sk_vpd_readbyte(struct sk_softc *, int);
-void sk_vpd_read_res(struct sk_softc *,
-					struct vpd_res *, int);
-void sk_vpd_read(struct sk_softc *);
-
 void sk_update_int_mod(struct sk_softc *);
 
 int sk_xmac_miibus_readreg(struct device *, int, int);
@@ -221,6 +222,7 @@
 void sk_setfilt(struct sk_if_softc *, caddr_t, int);
 void sk_setmulti(struct sk_if_softc *);
 void sk_tick(void *);
+void sk_rxcsum(struct ifnet *, struct mbuf *, const u_int16_t, const u_int16_t);
 
 /* #define SK_DEBUG 2 */
 #ifdef SK_DEBUG
@@ -269,6 +271,20 @@
 	{ PCI_VENDOR_SCHNEIDERKOCH, PCI_PRODUCT_SCHNEIDERKOCH_SK9821v2, },
 	{ PCI_VENDOR_GALILEO, PCI_PRODUCT_GALILEO_SKNET, },
 	{ PCI_VENDOR_GALILEO, PCI_PRODUCT_GALILEO_BELKIN, },
+        { PCI_VENDOR_GALILEO, PCI_PRODUCT_GALILEO_YUKON_8035, },
+        { PCI_VENDOR_GALILEO, PCI_PRODUCT_GALILEO_YUKON_8036, },
+        { PCI_VENDOR_GALILEO, PCI_PRODUCT_GALILEO_YUKON_8038, },
+        { PCI_VENDOR_GALILEO, PCI_PRODUCT_GALILEO_YUKON_8052, },
+        { PCI_VENDOR_GALILEO, PCI_PRODUCT_GALILEO_YUKON_8050, },
+        { PCI_VENDOR_GALILEO, PCI_PRODUCT_GALILEO_YUKON_8053, },
+        { PCI_VENDOR_GALILEO, PCI_PRODUCT_GALILEO_YUKONII_8021CU, },
+        { PCI_VENDOR_GALILEO, PCI_PRODUCT_GALILEO_YUKONII_8022CU, },
+        { PCI_VENDOR_GALILEO, PCI_PRODUCT_GALILEO_YUKONII_8021X, },
+        { PCI_VENDOR_GALILEO, PCI_PRODUCT_GALILEO_YUKONII_8022X, },
+        { PCI_VENDOR_GALILEO, PCI_PRODUCT_GALILEO_YUKONII_8061CU, },
+        { PCI_VENDOR_GALILEO, PCI_PRODUCT_GALILEO_YUKONII_8062CU, },
+        { PCI_VENDOR_GALILEO, PCI_PRODUCT_GALILEO_YUKONII_8061X, },
+        { PCI_VENDOR_GALILEO, PCI_PRODUCT_GALILEO_YUKONII_8062X, },
 	{ 0, 0, }
 };
 
@@ -340,93 +356,6 @@
 #endif
 }
 
-/*
- * The VPD EEPROM contains Vital Product Data, as suggested in
- * the PCI 2.1 specification. The VPD data is separared into areas
- * denoted by resource IDs. The SysKonnect VPD contains an ID string
- * resource (the name of the adapter), a read-only area resource
- * containing various key/data fields and a read/write area which
- * can be used to store asset management information or log messages.
- * We read the ID string and read-only into buffers attached to
- * the controller softc structure for later use. At the moment,
- * we only use the ID string during sk_attach().
- */
-u_int8_t
-sk_vpd_readbyte(struct sk_softc *sc, int addr)
-{
-	int			i;
-
-	sk_win_write_2(sc, SK_PCI_REG(SK_PCI_VPD_ADDR), addr);
-	for (i = 0; i < SK_TIMEOUT; i++) {
-		DELAY(1);
-		if (sk_win_read_2(sc,
-		    SK_PCI_REG(SK_PCI_VPD_ADDR)) & SK_VPD_FLAG)
-			break;
-	}
-
-	if (i == SK_TIMEOUT)
-		return(0);
-
-	return(sk_win_read_1(sc, SK_PCI_REG(SK_PCI_VPD_DATA)));
-}
-
-void
-sk_vpd_read_res(struct sk_softc *sc, struct vpd_res *res, int addr)
-{
-	int			i;
-	u_int8_t		*ptr;
-
-	ptr = (u_int8_t *)res;
-	for (i = 0; i < sizeof(struct vpd_res); i++)
-		ptr[i] = sk_vpd_readbyte(sc, i + addr);
-}
-
-void
-sk_vpd_read(struct sk_softc *sc)
-{
-	int			pos = 0, i;
-	struct vpd_res		res;
-
-	if (sc->sk_vpd_prodname != NULL)
-		free(sc->sk_vpd_prodname, M_DEVBUF);
-	if (sc->sk_vpd_readonly != NULL)
-		free(sc->sk_vpd_readonly, M_DEVBUF);
-	sc->sk_vpd_prodname = NULL;
-	sc->sk_vpd_readonly = NULL;
-
-	sk_vpd_read_res(sc, &res, pos);
-
-	if (res.vr_id != VPD_RES_ID) {
-		printf("%s: bad VPD resource id: expected %x got %x\n",
-		    sc->sk_dev.dv_xname, VPD_RES_ID, res.vr_id);
-		return;
-	}
-
-	pos += sizeof(res);
-	sc->sk_vpd_prodname = malloc(res.vr_len + 1, M_DEVBUF, M_NOWAIT);
-	if (sc->sk_vpd_prodname == NULL)
-		panic("sk_vpd_read");
-	for (i = 0; i < res.vr_len; i++)
-		sc->sk_vpd_prodname[i] = sk_vpd_readbyte(sc, i + pos);
-	sc->sk_vpd_prodname[i] = '\0';
-	pos += i;
-
-	sk_vpd_read_res(sc, &res, pos);
-
-	if (res.vr_id != VPD_RES_READ) {
-		printf("%s: bad VPD resource id: expected %x got %x\n",
-		    sc->sk_dev.dv_xname, VPD_RES_READ, res.vr_id);
-		return;
-	}
-
-	pos += sizeof(res);
-	sc->sk_vpd_readonly = malloc(res.vr_len, M_DEVBUF, M_NOWAIT);
-	if (sc->sk_vpd_readonly == NULL)
-		panic("sk_vpd_read");
-	for (i = 0; i < res.vr_len ; i++)
-		sc->sk_vpd_readonly[i] = sk_vpd_readbyte(sc, i + pos);
-}
-
 int
 sk_xmac_miibus_readreg(struct device *dev, int phy, int reg)
 {
@@ -574,6 +503,8 @@
 		if (SK_YU_READ_2(sc_if, YUKON_SMICR) & YU_SMICR_BUSY)
 			break;
 	}
+        if (i == SK_TIMEOUT)
+                printf("%s: phy write timed out\n", sc_if->sk_dev.dv_xname);
 }
 
 void
@@ -642,6 +573,10 @@
 	case SK_YUKON:
 	case SK_YUKON_LITE:
 	case SK_YUKON_LP:
+	case SK_YUKON_XL:
+	case SK_YUKON_EC_U:
+	case SK_YUKON_EC:
+	case SK_YUKON_FE:
 		SK_YU_WRITE_2(sc_if, YUKON_MCAH1, 0);
 		SK_YU_WRITE_2(sc_if, YUKON_MCAH2, 0);
 		SK_YU_WRITE_2(sc_if, YUKON_MCAH3, 0);
@@ -676,13 +611,18 @@
 				i++;
 			}
 			else {
-				switch (sc->sk_type) {
+				switch(sc->sk_type) {
 				case SK_GENESIS:
 					h = sk_xmac_hash(enm->enm_addrlo);
 					break;
+					
 				case SK_YUKON:
 				case SK_YUKON_LITE:
 				case SK_YUKON_LP:
+				case SK_YUKON_XL:
+				case SK_YUKON_EC_U:
+				case SK_YUKON_EC:
+				case SK_YUKON_FE:
 					h = sk_yukon_hash(enm->enm_addrlo);
 					break;
 				}
@@ -706,6 +646,10 @@
 	case SK_YUKON:
 	case SK_YUKON_LITE:
 	case SK_YUKON_LP:
+	case SK_YUKON_XL:
+	case SK_YUKON_EC_U:
+	case SK_YUKON_EC:
+	case SK_YUKON_FE:
 		SK_YU_WRITE_2(sc_if, YUKON_MCAH1, hashes[0] & 0xffff);
 		SK_YU_WRITE_2(sc_if, YUKON_MCAH2, (hashes[0] >> 16) & 0xffff);
 		SK_YU_WRITE_2(sc_if, YUKON_MCAH3, hashes[1] & 0xffff);
@@ -733,6 +677,9 @@
 			cd->sk_rx_chain[i].sk_next = &cd->sk_rx_chain[i + 1];
 			rd->sk_rx_ring[i].sk_next = SK_RX_RING_ADDR(sc_if,i+1);
 		}
+                rd->sk_rx_ring[i].sk_csum1_start = ETHER_HDR_LEN;
+                rd->sk_rx_ring[i].sk_csum2_start = ETHER_HDR_LEN +
+                    sizeof(struct ip);
 	}
 
 	for (i = 0; i < SK_RX_RING_CNT; i++) {
@@ -1047,6 +994,10 @@
 				case SK_YUKON:
 				case SK_YUKON_LITE:
 				case SK_YUKON_LP:
+				case SK_YUKON_XL:
+				case SK_YUKON_EC_U:
+				case SK_YUKON_EC:
+				case SK_YUKON_FE:
 					SK_YU_CLRBIT_2(sc_if, YUKON_RCR,
 					    YU_RCR_UFLEN | YU_RCR_MUFLEN);
 					break;
@@ -1063,14 +1014,20 @@
 				case SK_YUKON:
 				case SK_YUKON_LITE:
 				case SK_YUKON_LP:
+                                case SK_YUKON_XL:
+                                case SK_YUKON_EC_U:
+                                case SK_YUKON_EC:
+                                case SK_YUKON_FE:
 					SK_YU_SETBIT_2(sc_if, YUKON_RCR,
 					    YU_RCR_UFLEN | YU_RCR_MUFLEN);
 					break;
 				}
 
 				sk_setmulti(sc_if);
-			} else
-				(void) sk_init(ifp);
+			} else {
+                                if (!(ifp->if_flags & IFF_RUNNING))
+					(void) sk_init(ifp);
+			}
 		} else {
 			if (ifp->if_flags & IFF_RUNNING)
 				sk_stop(ifp,0);
@@ -1125,6 +1082,8 @@
 		sk_imtimer_ticks = SK_IMTIMER_TICKS_GENESIS;
 		break;
 	case SK_YUKON_EC:
+        case SK_YUKON_XL:
+        case SK_YUKON_FE:
 		sk_imtimer_ticks = SK_IMTIMER_TICKS_YUKON_EC;
 		break;
 	default:
@@ -1284,7 +1243,8 @@
 	 * dual port NIC. Our algorithm is to divide up the memory
 	 * evenly so that everyone gets a fair share.
 	 */
-	if (sk_win_read_1(sc, SK_CONFIG) & SK_CONFIG_SINGLEMAC) {
+        if (SK_IS_YUKON2(sc) ||
+            sk_win_read_1(sc, SK_CONFIG) & SK_CONFIG_SINGLEMAC) {
 		u_int32_t		chunk, val;
 
 		chunk = sc->sk_ramsize / 2;
@@ -1316,20 +1276,36 @@
 
 	/* Read and save PHY type and set PHY address */
 	sc_if->sk_phytype = sk_win_read_1(sc, SK_EPROM1) & 0xF;
-	switch (sc_if->sk_phytype) {
-	case SK_PHYTYPE_XMAC:
-		sc_if->sk_phyaddr = SK_PHYADDR_XMAC;
-		break;
-	case SK_PHYTYPE_BCOM:
-		sc_if->sk_phyaddr = SK_PHYADDR_BCOM;
-		break;
-	case SK_PHYTYPE_MARV_COPPER:
+ 
+        /* Set PHY address */
+        if (SK_IS_GENESIS(sc)) {
+                switch (sc_if->sk_phytype) {
+                        case SK_PHYTYPE_XMAC:
+                                sc_if->sk_phyaddr = SK_PHYADDR_XMAC;
+                                break;
+                        case SK_PHYTYPE_BCOM:
+                                sc_if->sk_phyaddr = SK_PHYADDR_BCOM;
+                                break;
+                        default:
+                                printf("%s: unsupported PHY type: %d\n",
+                                    sc->sk_dev.dv_xname, sc_if->sk_phytype);
+                                return;
+                }
+        }
+ 
+        if (SK_IS_YUKON(sc)) {
+                if ((sc_if->sk_phytype < SK_PHYTYPE_MARV_COPPER &&
+                    sc->sk_pmd != 'L' && sc->sk_pmd != 'S')) {
+                        /* not initialized, punt */
+                        sc_if->sk_phytype = SK_PHYTYPE_MARV_COPPER;
+ 
+                        sc->sk_coppertype = 1;
+                }
+
 		sc_if->sk_phyaddr = SK_PHYADDR_MARV;
-		break;
-	default:
-		aprint_error("%s: unsupported PHY type: %d\n",
-		    sc->sk_dev.dv_xname, sc_if->sk_phytype);
-		return;
+ 
+                if (!(sc->sk_coppertype))
+                        sc_if->sk_phytype = SK_PHYTYPE_MARV_FIBER;
 	}
 
 	/* Allocate the descriptor queues. */
@@ -1423,6 +1399,7 @@
 	ifp->if_init = sk_init;
 	ifp->if_watchdog = sk_watchdog;
 	ifp->if_capabilities = 0;
+        ifp->if_baudrate = 1000000000;
 	IFQ_SET_MAXLEN(&ifp->if_snd, SK_TX_RING_CNT - 1);
 	IFQ_SET_READY(&ifp->if_snd);
 	strcpy(ifp->if_xname, sc_if->sk_dev.dv_xname);
@@ -1437,6 +1414,10 @@
 	case SK_YUKON:
 	case SK_YUKON_LITE:
 	case SK_YUKON_LP:
+        case SK_YUKON_XL:
+        case SK_YUKON_EC_U:
+        case SK_YUKON_EC:
+        case SK_YUKON_FE:
 		sk_init_yukon(sc_if);
 		break;
 	default:
@@ -1447,19 +1428,14 @@
  	DPRINTFN(2, ("sk_attach: 1\n"));
 
 	sc_if->sk_mii.mii_ifp = ifp;
-	switch (sc->sk_type) {
-	case SK_GENESIS:
+        if (sc->sk_type == SK_GENESIS) {
 		sc_if->sk_mii.mii_readreg = sk_xmac_miibus_readreg;
 		sc_if->sk_mii.mii_writereg = sk_xmac_miibus_writereg;
 		sc_if->sk_mii.mii_statchg = sk_xmac_miibus_statchg;
-		break;
-	case SK_YUKON:
-	case SK_YUKON_LITE:
-	case SK_YUKON_LP:
+        } else {
 		sc_if->sk_mii.mii_readreg = sk_marv_miibus_readreg;
 		sc_if->sk_mii.mii_writereg = sk_marv_miibus_writereg;
 		sc_if->sk_mii.mii_statchg = sk_marv_miibus_statchg;
-		break;
 	}
 
 	ifmedia_init(&sc_if->sk_mii.mii_media, 0,
@@ -1491,6 +1467,7 @@
         rnd_attach_source(&sc->rnd_source, sc->sk_dev.dv_xname,
             RND_TYPE_NET, 0);
 #endif
+        shutdownhook_establish(sk_shutdown, sc);
 
 	DPRINTFN(2, ("sk_attach: end\n"));
 
@@ -1532,7 +1509,7 @@
 	bus_size_t iosize;
 	int s, rc, sk_nodenum;
 	u_int32_t command;
-	const char *revstr;
+	const char *revstr = NULL;
 	const struct sysctlnode *node;
 
 	DPRINTFN(2, ("begin skc_attach\n"));
@@ -1645,7 +1622,6 @@
 	sk_reset(sc);
 
 	/* Read and save vital product data from EEPROM. */
-	sk_vpd_read(sc);
 
 	if (sc->sk_type == SK_GENESIS) {
 		u_int8_t val = sk_win_read_1(sc, SK_EPROM0);
@@ -1688,89 +1664,63 @@
 	}
 
 	/* Read and save physical media type */
-	switch(sk_win_read_1(sc, SK_PMDTYPE)) {
-	case SK_PMD_1000BASESX:
-		sc->sk_pmd = IFM_1000_SX;
+        sc->sk_pmd = sk_win_read_1(sc, SK_PMDTYPE);
+ 
+        if (sc->sk_pmd == 'T' || sc->sk_pmd == '1' ||
+            (SK_IS_YUKON2(sc) && !(sc->sk_pmd == 'L' ||
+            sc->sk_pmd == 'S')))
+                sc->sk_coppertype = 1;
+        else
+                sc->sk_coppertype = 0;
+ 
+        switch (sc->sk_type) {
+        case SK_GENESIS:
+                sc->sk_name = "SysKonnect GEnesis";
+                break;
+	case SK_YUKON:
+                sc->sk_name = "Marvell Yukon";
+                break;
+        case SK_YUKON_LITE:
+                sc->sk_name = "Marvell Yukon Lite";
+                break;
+        case SK_YUKON_LP:
+                sc->sk_name = "Marvell Yukon LP";
+                break;
+        case SK_YUKON_XL:
+                sc->sk_name = "Marvell Yukon-2 XL";
 		break;
-	case SK_PMD_1000BASELX:
-		sc->sk_pmd = IFM_1000_LX;
+        case SK_YUKON_EC_U:
+                sc->sk_name = "Marvell Yukon-2 EC Ultra";
 		break;
-	case SK_PMD_1000BASECX:
-		sc->sk_pmd = IFM_1000_CX;
+        case SK_YUKON_EC:
+                sc->sk_name = "Marvell Yukon-2 EC";
 		break;
-	case SK_PMD_1000BASETX:
-		sc->sk_pmd = IFM_1000_T;
+        case SK_YUKON_FE:
+                sc->sk_name = "Marvell Yukon-2 FE";
 		break;
 	default:
-		aprint_error("%s: unknown media type: 0x%x\n",
-		    sc->sk_dev.dv_xname, sk_win_read_1(sc, SK_PMDTYPE));
-		goto fail;
+                sc->sk_name = "Marvell Yukon (Unknown)";
 	}
 
-	/* determine whether to name it with vpd or just make it up */
-	/* Marvell Yukon VPD's can freqently be bogus */
+        /* Yukon Lite Rev A0 needs special test, from sk98lin driver */
+        if (sc->sk_type == SK_YUKON || sc->sk_type == SK_YUKON_LP) {
+                u_int32_t flashaddr;
+                u_int8_t testbyte;
+
+                flashaddr = sk_win_read_4(sc, SK_EP_ADDR);
+
+                /* test Flash-Address Register */
+                sk_win_write_1(sc, SK_EP_ADDR+3, 0xff);
+                testbyte = sk_win_read_1(sc, SK_EP_ADDR+3);
+
+                if (testbyte != 0) {
+                        /* This is a Yukon Lite Rev A0 */
+                        sc->sk_type = SK_YUKON_LITE;
+                        sc->sk_rev = SK_YUKON_LITE_REV_A0;
+                        /* restore Flash-Address Register */
+                        sk_win_write_4(sc, SK_EP_ADDR, flashaddr);
 
-	switch (pa->pa_id) {
-	case PCI_ID_CODE(PCI_VENDOR_SCHNEIDERKOCH,
-			 PCI_PRODUCT_SCHNEIDERKOCH_SKNET_GE):
-	case PCI_PRODUCT_SCHNEIDERKOCH_SK9821v2:
-	case PCI_PRODUCT_3COM_3C940:
-	case PCI_PRODUCT_DLINK_DGE530T:
-	case PCI_PRODUCT_LINKSYS_EG1032:
-	case PCI_PRODUCT_LINKSYS_EG1064:
-	case PCI_ID_CODE(PCI_VENDOR_SCHNEIDERKOCH,
-			 PCI_PRODUCT_SCHNEIDERKOCH_SK9821v2):
-	case PCI_ID_CODE(PCI_VENDOR_3COM,PCI_PRODUCT_3COM_3C940):
-	case PCI_ID_CODE(PCI_VENDOR_DLINK,PCI_PRODUCT_DLINK_DGE530T):
-	case PCI_ID_CODE(PCI_VENDOR_LINKSYS,PCI_PRODUCT_LINKSYS_EG1032):
-	case PCI_ID_CODE(PCI_VENDOR_LINKSYS,PCI_PRODUCT_LINKSYS_EG1064):
- 		sc->sk_name = sc->sk_vpd_prodname;
- 		break;
-	case PCI_ID_CODE(PCI_VENDOR_GALILEO,PCI_PRODUCT_GALILEO_SKNET):
-	/* whoops yukon vpd prodname bears no resemblance to reality */
-		switch (sc->sk_type) {
-		case SK_GENESIS:
-			sc->sk_name = sc->sk_vpd_prodname;
-			break;
-		case SK_YUKON:
-			sc->sk_name = "Marvell Yukon Gigabit Ethernet";
-			break;
-		case SK_YUKON_LITE:
-			sc->sk_name = "Marvell Yukon Lite Gigabit Ethernet";
-			break;
-		case SK_YUKON_LP:
-			sc->sk_name = "Marvell Yukon LP Gigabit Ethernet";
-			break;
-		default:
-			sc->sk_name = "Marvell Yukon (Unknown) Gigabit Ethernet";
 		}
-
-	/* Yukon Lite Rev A0 needs special test, from sk98lin driver */
-
-		if ( sc->sk_type == SK_YUKON ) {
-			uint32_t flashaddr;
-			uint8_t testbyte;
-
-			flashaddr = sk_win_read_4(sc,SK_EP_ADDR);
-
-			/* test Flash-Address Register */
-			sk_win_write_1(sc,SK_EP_ADDR+3, 0xff);
-			testbyte = sk_win_read_1(sc, SK_EP_ADDR+3);
-
-			if (testbyte != 0) {
-				/* this is yukon lite Rev. A0 */
-				sc->sk_type = SK_YUKON_LITE;
-				sc->sk_rev = SK_YUKON_LITE_REV_A0;
-				/* restore Flash-Address Register */
-				sk_win_write_4(sc,SK_EP_ADDR,flashaddr);
-			}
-		}
-		break;
-	case PCI_ID_CODE(PCI_VENDOR_GALILEO,PCI_PRODUCT_GALILEO_BELKIN):
-		sc->sk_name = sc->sk_vpd_prodname;
-		break;
- 	default:
-		sc->sk_name = "Unknown Marvell";
 	}
 
 
@@ -1786,21 +1736,87 @@
 			revstr = "A3";
 			break;
 		default:
-			revstr = "";
+                        ;
+                }
+        }
+ 
+        if (sc->sk_type == SK_YUKON_XL) {
+                switch (sc->sk_rev) {
+                case SK_YUKON_XL_REV_A0:
+                        revstr = "A0";
+                        break;
+                case SK_YUKON_XL_REV_A1:
+                        revstr = "A1";
+                        break;
+                case SK_YUKON_XL_REV_A2:
+                        revstr = "A2";
+                        break;
+                case SK_YUKON_XL_REV_A3:
+                        revstr = "A3";
+                        break;
+                default:
+                        ;
+                }
+        }
+ 
+        if (sc->sk_type == SK_YUKON_EC) {
+                switch (sc->sk_rev) {
+                case SK_YUKON_EC_REV_A1:
+                        revstr = "A1";
+                        break;
+                case SK_YUKON_EC_REV_A2:
+                        revstr = "A2";
+                        break;
+                case SK_YUKON_EC_REV_A3:
+                        revstr = "A3";
+                        break;
+                default:
+                        ;
+                }
+        }
+
+        if (sc->sk_type == SK_YUKON_EC_U) {
+                switch (sc->sk_rev) {
+                case SK_YUKON_EC_U_REV_A0:
+                        revstr = "A0";
+                        break;
+                case SK_YUKON_EC_U_REV_A1:
+                        revstr = "A1";
+                        break;
+                default:
+                        ;
 		}
-	} else {
-		revstr = "";
 	}
 
 	/* Announce the product name. */
 	aprint_normal("%s: %s rev. %s(0x%x)\n", sc->sk_dev.dv_xname,
 			      sc->sk_name, revstr, sc->sk_rev);
+ 
+        sc->sk_macs = 1;
+ 
+        if (SK_IS_YUKON2(sc)) {
+                u_int8_t hw;
+ 
+                hw = sk_win_read_1(sc, SK_Y2_HWRES);
+                if ((hw & SK_Y2_HWRES_LINK_MASK) == SK_Y2_HWRES_LINK_DUAL) {
+                        if ((sk_win_read_1(sc, SK_Y2_CLKGATE) &
+                            SK_Y2_CLKGATE_LINK2_INACTIVE) == 0)
+                                sc->sk_macs++;
+                }
+        } else {
+                if (!(sk_win_read_1(sc, SK_CONFIG) & SK_CONFIG_SINGLEMAC))
+                        sc->sk_macs++;
+        }
 
 	skca.skc_port = SK_PORT_A;
+        skca.skc_type = sc->sk_type;
+        skca.skc_rev = sc->sk_rev;
 	(void)config_found(&sc->sk_dev, &skca, skcprint);
 
-	if (!(sk_win_read_1(sc, SK_CONFIG) & SK_CONFIG_SINGLEMAC)) {
+        if (sc->sk_macs > 1) {
 		skca.skc_port = SK_PORT_B;
+                skca.skc_type = sc->sk_type;
+                skca.skc_rev = sc->sk_rev;
 		(void)config_found(&sc->sk_dev, &skca, skcprint);
 	}
 
@@ -2032,6 +2048,7 @@
 	int			i, cur, total_len = 0;
 	u_int32_t		rxstat;
 	bus_dmamap_t		dmamap;
+        u_int16_t               csum1, csum2;
 
 	i = sc_if->sk_cdata.sk_rx_prod;
 
@@ -2063,7 +2080,8 @@
 		cur_rx->sk_mbuf = NULL;
 		total_len = SK_RXBYTES(cur_desc->sk_ctl);
 
-		sc_if->sk_cdata.sk_rx_map[cur] = 0;
+                csum1 = sc_if->sk_rdata->sk_rx_ring[i].sk_csum1;
+                csum2 = sc_if->sk_rdata->sk_rx_ring[i].sk_csum2;
 
 		SK_INC(i, SK_RX_RING_CNT);
 
@@ -2101,6 +2119,8 @@
 
 		ifp->if_ipackets++;
 
+                sk_rxcsum(ifp, m, csum1, csum2);
+ 
 #if NBPFILTER > 0
 		if (ifp->if_bpf)
 			bpf_mtap(ifp->if_bpf, m);
@@ -2110,6 +2130,100 @@
 	}
 }
 
+ void
+ sk_rxcsum(struct ifnet *ifp, struct mbuf *m, const u_int16_t csum1, const u_int16_t csum2)
+ {
+        struct ether_header *eh;
+        struct ip *ip;
+        u_int8_t *pp;
+        int hlen, len, plen;
+        u_int16_t iph_csum, ipo_csum, ipd_csum, csum;
+ 
+        pp = mtod(m, u_int8_t *);
+        plen = m->m_pkthdr.len;
+        if (plen < sizeof(*eh))
+                return;
+        eh = (struct ether_header *)pp;
+        iph_csum = in_cksum_addword(csum1, (~csum2 & 0xffff));
+ 
+        if (eh->ether_type == htons(ETHERTYPE_VLAN)) {
+                u_int16_t *xp = (u_int16_t *)pp;
+ 
+                xp = (u_int16_t *)pp;
+                if (xp[1] != htons(ETHERTYPE_IP))
+                        return;
+                iph_csum = in_cksum_addword(iph_csum, (~xp[0] & 0xffff));
+                iph_csum = in_cksum_addword(iph_csum, (~xp[1] & 0xffff));
+                xp = (u_int16_t *)(pp + sizeof(struct ip));
+                /*xp = (u_int16_t *)(pp + sizeof(struct ip));*/
+                iph_csum = in_cksum_addword(iph_csum, xp[0]);
+                iph_csum = in_cksum_addword(iph_csum, xp[1]);
+                /*pp += EVL_ENCAPLEN;*/
+                pp += 4;
+        } else if (eh->ether_type != htons(ETHERTYPE_IP))
+                return;
+ 
+        pp += sizeof(*eh);
+        plen -= sizeof(*eh);
+ 
+        ip = (struct ip *)pp;
+ 
+        if (ip->ip_v != 4)
+                return;
+ 
+        hlen = ip->ip_hl << 2;
+        if (hlen < sizeof(struct ip))
+                return;
+        if (hlen > ntohs(ip->ip_len))
+                return;
+ 
+        /* Don't deal with truncated or padded packets. */
+        if (plen != ntohs(ip->ip_len))
+                return;
+ 
+        /* Don't deal with truncated or padded packets. */
+        if (plen != ntohs(ip->ip_len))
+                return;
+ 
+        len = hlen - sizeof(struct ip);
+        if (len > 0) {
+                u_int16_t *p;
+ 
+                p = (u_int16_t *)(ip + 1);
+                ipo_csum = 0;
+                for (ipo_csum = 0; len > 0; len -= sizeof(*p), p++)
+                        ipo_csum = in_cksum_addword(ipo_csum, *p);
+                iph_csum = in_cksum_addword(iph_csum, ipo_csum);
+                ipd_csum = in_cksum_addword(csum2, (~ipo_csum & 0xffff));
+        } else
+                ipd_csum = csum2;
+ 
+        if (iph_csum != 0xffff)
+                return;
+        m->m_pkthdr.csum_flags |= 0x0008;
+ 
+        if (ip->ip_off & htons(IP_MF | IP_OFFMASK))
+                return;                 /* ip frag, we're done for now */
+ 
+        pp += hlen;
+ 
+        /* Only know checksum protocol for udp/tcp */
+        if (ip->ip_p == IPPROTO_UDP) {
+                struct udphdr *uh = (struct udphdr *)pp;
+
+                if (uh->uh_sum == 0)    /* udp with no checksum */
+                        return;
+        } else if (ip->ip_p != IPPROTO_TCP)
+                return;
+ 
+        csum = in_cksum_phdr(ip->ip_src.s_addr, ip->ip_dst.s_addr,
+            htonl(ntohs(ip->ip_len) - hlen + ip->ip_p) + ipd_csum);
+        if (csum == 0xffff) {
+                m->m_pkthdr.csum_flags |= (ip->ip_p == IPPROTO_TCP) ?
+                    0x0020 : 0x0080;
+        }
+ }
+
 void
 sk_txeof(struct sk_if_softc *sc_if)
 {
@@ -2599,17 +2713,10 @@
 	phy = SK_GPHY_INT_POL_HI | SK_GPHY_DIS_FC | SK_GPHY_DIS_SLEEP |
 		SK_GPHY_ENA_XC | SK_GPHY_ANEG_ALL | SK_GPHY_ENA_PAUSE;
 
-	switch(sc_if->sk_softc->sk_pmd) {
-	case IFM_1000_SX:
-	case IFM_1000_LX:
-		phy |= SK_GPHY_FIBER;
-		break;
-
-	case IFM_1000_CX:
-	case IFM_1000_T:
+        if (sc->sk_coppertype)
 		phy |= SK_GPHY_COPPER;
-		break;
-	}
+        else
+                phy |= SK_GPHY_FIBER;
 
 	DPRINTFN(3, ("sk_init_yukon: phy=%#x\n", phy));
 
@@ -2745,6 +2852,10 @@
 	case SK_YUKON:
 	case SK_YUKON_LITE:
 	case SK_YUKON_LP:
+        case SK_YUKON_XL:
+        case SK_YUKON_EC_U:
+        case SK_YUKON_EC:
+        case SK_YUKON_FE:
 		sk_init_yukon(sc_if);
 		break;
 	}
@@ -2815,6 +2926,8 @@
 		sk_imtimer_ticks = SK_IMTIMER_TICKS_GENESIS;
 		break;
 	case SK_YUKON_EC:
+        case SK_YUKON_XL:
+        case SK_YUKON_FE:
 		sk_imtimer_ticks = SK_IMTIMER_TICKS_YUKON_EC;
 		break;
 	default:
@@ -2902,6 +3015,10 @@
 	case SK_YUKON:
 	case SK_YUKON_LITE:
 	case SK_YUKON_LP:
+        case SK_YUKON_XL:
+        case SK_YUKON_EC_U:
+        case SK_YUKON_EC:
+        case SK_YUKON_FE:
 		SK_IF_WRITE_1(sc_if,0, SK_RXMF1_CTRL_TEST, SK_RFCTL_RESET_SET);
 		SK_IF_WRITE_1(sc_if,0, SK_TXMF1_CTRL_TEST, SK_TFCTL_RESET_SET);
 		break;

--MP_m8qNVMW_iwBl9z/Vli1US..--