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: netbsd-users
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..--