Thu Mar 3 05:54:11 2022 UTC ()
axen(4): Use axen mii read/write reg routines, not usbnet ones.

The usbnet wrappers don't add anything important.  We already test
usbnet_isdying in axen_cmd, and that's already a best-effort thing
(which should probably be done better by having usbd_do_request fail
promptly if detaching anyway).


(riastradh)
diff -r1.86 -r1.87 src/sys/dev/usb/if_axen.c

cvs diff -r1.86 -r1.87 src/sys/dev/usb/if_axen.c (switch to unified diff)

--- src/sys/dev/usb/if_axen.c 2022/03/03 05:54:03 1.86
+++ src/sys/dev/usb/if_axen.c 2022/03/03 05:54:11 1.87
@@ -1,936 +1,936 @@ @@ -1,936 +1,936 @@
1/* $NetBSD: if_axen.c,v 1.86 2022/03/03 05:54:03 riastradh Exp $ */ 1/* $NetBSD: if_axen.c,v 1.87 2022/03/03 05:54:11 riastradh Exp $ */
2/* $OpenBSD: if_axen.c,v 1.3 2013/10/21 10:10:22 yuo Exp $ */ 2/* $OpenBSD: if_axen.c,v 1.3 2013/10/21 10:10:22 yuo Exp $ */
3 3
4/* 4/*
5 * Copyright (c) 2013 Yojiro UO <yuo@openbsd.org> 5 * Copyright (c) 2013 Yojiro UO <yuo@openbsd.org>
6 * 6 *
7 * Permission to use, copy, modify, and distribute this software for any 7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above 8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies. 9 * copyright notice and this permission notice appear in all copies.
10 * 10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */ 18 */
19 19
20/* 20/*
21 * ASIX Electronics AX88178a USB 2.0 ethernet and AX88179 USB 3.0 Ethernet 21 * ASIX Electronics AX88178a USB 2.0 ethernet and AX88179 USB 3.0 Ethernet
22 * driver. 22 * driver.
23 */ 23 */
24 24
25#include <sys/cdefs.h> 25#include <sys/cdefs.h>
26__KERNEL_RCSID(0, "$NetBSD: if_axen.c,v 1.86 2022/03/03 05:54:03 riastradh Exp $"); 26__KERNEL_RCSID(0, "$NetBSD: if_axen.c,v 1.87 2022/03/03 05:54:11 riastradh Exp $");
27 27
28#ifdef _KERNEL_OPT 28#ifdef _KERNEL_OPT
29#include "opt_usb.h" 29#include "opt_usb.h"
30#endif 30#endif
31 31
32#include <sys/param.h> 32#include <sys/param.h>
33 33
34#include <netinet/in.h> /* XXX for netinet/ip.h */ 34#include <netinet/in.h> /* XXX for netinet/ip.h */
35#include <netinet/ip.h> /* XXX for IP_MAXPACKET */ 35#include <netinet/ip.h> /* XXX for IP_MAXPACKET */
36 36
37#include <dev/usb/usbnet.h> 37#include <dev/usb/usbnet.h>
38 38
39#include <dev/usb/if_axenreg.h> 39#include <dev/usb/if_axenreg.h>
40 40
41#ifdef AXEN_DEBUG 41#ifdef AXEN_DEBUG
42#define DPRINTF(x) do { if (axendebug) printf x; } while (/*CONSTCOND*/0) 42#define DPRINTF(x) do { if (axendebug) printf x; } while (/*CONSTCOND*/0)
43#define DPRINTFN(n, x) do { if (axendebug >= (n)) printf x; } while (/*CONSTCOND*/0) 43#define DPRINTFN(n, x) do { if (axendebug >= (n)) printf x; } while (/*CONSTCOND*/0)
44int axendebug = 0; 44int axendebug = 0;
45#else 45#else
46#define DPRINTF(x) 46#define DPRINTF(x)
47#define DPRINTFN(n, x) 47#define DPRINTFN(n, x)
48#endif 48#endif
49 49
50struct axen_type { 50struct axen_type {
51 struct usb_devno axen_devno; 51 struct usb_devno axen_devno;
52 uint16_t axen_flags; 52 uint16_t axen_flags;
53#define AX178A 0x0001 /* AX88178a */ 53#define AX178A 0x0001 /* AX88178a */
54#define AX179 0x0002 /* AX88179 */ 54#define AX179 0x0002 /* AX88179 */
55}; 55};
56 56
57/* 57/*
58 * Various supported device vendors/products. 58 * Various supported device vendors/products.
59 */ 59 */
60static const struct axen_type axen_devs[] = { 60static const struct axen_type axen_devs[] = {
61#if 0 /* not tested */ 61#if 0 /* not tested */
62 { { USB_VENDOR_ASIX, USB_PRODUCT_ASIX_AX88178A}, AX178A }, 62 { { USB_VENDOR_ASIX, USB_PRODUCT_ASIX_AX88178A}, AX178A },
63#endif 63#endif
64 { { USB_VENDOR_ASIX, USB_PRODUCT_ASIX_AX88179}, AX179 }, 64 { { USB_VENDOR_ASIX, USB_PRODUCT_ASIX_AX88179}, AX179 },
65 { { USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DUB1312}, AX179 } 65 { { USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DUB1312}, AX179 }
66}; 66};
67 67
68#define axen_lookup(v, p) ((const struct axen_type *)usb_lookup(axen_devs, v, p)) 68#define axen_lookup(v, p) ((const struct axen_type *)usb_lookup(axen_devs, v, p))
69 69
70static int axen_match(device_t, cfdata_t, void *); 70static int axen_match(device_t, cfdata_t, void *);
71static void axen_attach(device_t, device_t, void *); 71static void axen_attach(device_t, device_t, void *);
72 72
73CFATTACH_DECL_NEW(axen, sizeof(struct usbnet), 73CFATTACH_DECL_NEW(axen, sizeof(struct usbnet),
74 axen_match, axen_attach, usbnet_detach, usbnet_activate); 74 axen_match, axen_attach, usbnet_detach, usbnet_activate);
75 75
76static int axen_cmd(struct usbnet *, int, int, int, void *); 76static int axen_cmd(struct usbnet *, int, int, int, void *);
77static void axen_reset(struct usbnet *); 77static void axen_reset(struct usbnet *);
78static int axen_get_eaddr(struct usbnet *, void *); 78static int axen_get_eaddr(struct usbnet *, void *);
79static void axen_ax88179_init(struct usbnet *); 79static void axen_ax88179_init(struct usbnet *);
80 80
81static void axen_uno_stop(struct ifnet *, int); 81static void axen_uno_stop(struct ifnet *, int);
82static int axen_uno_ioctl(struct ifnet *, u_long, void *); 82static int axen_uno_ioctl(struct ifnet *, u_long, void *);
83static void axen_uno_mcast(struct ifnet *); 83static void axen_uno_mcast(struct ifnet *);
84static int axen_uno_mii_read_reg(struct usbnet *, int, int, uint16_t *); 84static int axen_uno_mii_read_reg(struct usbnet *, int, int, uint16_t *);
85static int axen_uno_mii_write_reg(struct usbnet *, int, int, uint16_t); 85static int axen_uno_mii_write_reg(struct usbnet *, int, int, uint16_t);
86static void axen_uno_mii_statchg(struct ifnet *); 86static void axen_uno_mii_statchg(struct ifnet *);
87static void axen_uno_rx_loop(struct usbnet *, struct usbnet_chain *, 87static void axen_uno_rx_loop(struct usbnet *, struct usbnet_chain *,
88 uint32_t); 88 uint32_t);
89static unsigned axen_uno_tx_prepare(struct usbnet *, struct mbuf *, 89static unsigned axen_uno_tx_prepare(struct usbnet *, struct mbuf *,
90 struct usbnet_chain *); 90 struct usbnet_chain *);
91static int axen_uno_init(struct ifnet *); 91static int axen_uno_init(struct ifnet *);
92 92
93static const struct usbnet_ops axen_ops = { 93static const struct usbnet_ops axen_ops = {
94 .uno_stop = axen_uno_stop, 94 .uno_stop = axen_uno_stop,
95 .uno_ioctl = axen_uno_ioctl, 95 .uno_ioctl = axen_uno_ioctl,
96 .uno_mcast = axen_uno_mcast, 96 .uno_mcast = axen_uno_mcast,
97 .uno_read_reg = axen_uno_mii_read_reg, 97 .uno_read_reg = axen_uno_mii_read_reg,
98 .uno_write_reg = axen_uno_mii_write_reg, 98 .uno_write_reg = axen_uno_mii_write_reg,
99 .uno_statchg = axen_uno_mii_statchg, 99 .uno_statchg = axen_uno_mii_statchg,
100 .uno_tx_prepare = axen_uno_tx_prepare, 100 .uno_tx_prepare = axen_uno_tx_prepare,
101 .uno_rx_loop = axen_uno_rx_loop, 101 .uno_rx_loop = axen_uno_rx_loop,
102 .uno_init = axen_uno_init, 102 .uno_init = axen_uno_init,
103}; 103};
104 104
105static int 105static int
106axen_cmd(struct usbnet *un, int cmd, int index, int val, void *buf) 106axen_cmd(struct usbnet *un, int cmd, int index, int val, void *buf)
107{ 107{
108 usb_device_request_t req; 108 usb_device_request_t req;
109 usbd_status err; 109 usbd_status err;
110 110
111 if (usbnet_isdying(un)) 111 if (usbnet_isdying(un))
112 return 0; 112 return 0;
113 113
114 if (AXEN_CMD_DIR(cmd)) 114 if (AXEN_CMD_DIR(cmd))
115 req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 115 req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
116 else 116 else
117 req.bmRequestType = UT_READ_VENDOR_DEVICE; 117 req.bmRequestType = UT_READ_VENDOR_DEVICE;
118 req.bRequest = AXEN_CMD_CMD(cmd); 118 req.bRequest = AXEN_CMD_CMD(cmd);
119 USETW(req.wValue, val); 119 USETW(req.wValue, val);
120 USETW(req.wIndex, index); 120 USETW(req.wIndex, index);
121 USETW(req.wLength, AXEN_CMD_LEN(cmd)); 121 USETW(req.wLength, AXEN_CMD_LEN(cmd));
122 122
123 err = usbd_do_request(un->un_udev, &req, buf); 123 err = usbd_do_request(un->un_udev, &req, buf);
124 DPRINTFN(5, ("axen_cmd: cmd 0x%04x val 0x%04x len %d\n", 124 DPRINTFN(5, ("axen_cmd: cmd 0x%04x val 0x%04x len %d\n",
125 cmd, val, AXEN_CMD_LEN(cmd))); 125 cmd, val, AXEN_CMD_LEN(cmd)));
126 126
127 if (err) { 127 if (err) {
128 DPRINTF(("%s: cmd: %d, error: %d\n", __func__, cmd, err)); 128 DPRINTF(("%s: cmd: %d, error: %d\n", __func__, cmd, err));
129 return -1; 129 return -1;
130 } 130 }
131 131
132 return 0; 132 return 0;
133} 133}
134 134
135static int 135static int
136axen_uno_mii_read_reg(struct usbnet *un, int phy, int reg, uint16_t *val) 136axen_uno_mii_read_reg(struct usbnet *un, int phy, int reg, uint16_t *val)
137{ 137{
138 uint16_t data; 138 uint16_t data;
139 139
140 if (un->un_phyno != phy) 140 if (un->un_phyno != phy)
141 return EINVAL; 141 return EINVAL;
142 142
143 usbd_status err = axen_cmd(un, AXEN_CMD_MII_READ_REG, reg, phy, &data); 143 usbd_status err = axen_cmd(un, AXEN_CMD_MII_READ_REG, reg, phy, &data);
144 if (err) 144 if (err)
145 return EIO; 145 return EIO;
146 146
147 *val = le16toh(data); 147 *val = le16toh(data);
148 if (reg == MII_BMSR) 148 if (reg == MII_BMSR)
149 *val &= ~BMSR_EXTCAP; 149 *val &= ~BMSR_EXTCAP;
150 150
151 return 0; 151 return 0;
152} 152}
153 153
154static int 154static int
155axen_uno_mii_write_reg(struct usbnet *un, int phy, int reg, uint16_t val) 155axen_uno_mii_write_reg(struct usbnet *un, int phy, int reg, uint16_t val)
156{ 156{
157 uint16_t uval = htole16(val); 157 uint16_t uval = htole16(val);
158 158
159 if (un->un_phyno != phy) 159 if (un->un_phyno != phy)
160 return EINVAL; 160 return EINVAL;
161 161
162 usbd_status err = axen_cmd(un, AXEN_CMD_MII_WRITE_REG, reg, phy, &uval); 162 usbd_status err = axen_cmd(un, AXEN_CMD_MII_WRITE_REG, reg, phy, &uval);
163 if (err) 163 if (err)
164 return EIO; 164 return EIO;
165 165
166 return 0; 166 return 0;
167} 167}
168 168
169static void 169static void
170axen_uno_mii_statchg(struct ifnet *ifp) 170axen_uno_mii_statchg(struct ifnet *ifp)
171{ 171{
172 struct usbnet * const un = ifp->if_softc; 172 struct usbnet * const un = ifp->if_softc;
173 struct mii_data * const mii = usbnet_mii(un); 173 struct mii_data * const mii = usbnet_mii(un);
174 int err; 174 int err;
175 uint16_t val; 175 uint16_t val;
176 uint16_t wval; 176 uint16_t wval;
177 177
178 if (usbnet_isdying(un)) 178 if (usbnet_isdying(un))
179 return; 179 return;
180 180
181 if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) == 181 if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) ==
182 (IFM_ACTIVE | IFM_AVALID)) { 182 (IFM_ACTIVE | IFM_AVALID)) {
183 switch (IFM_SUBTYPE(mii->mii_media_active)) { 183 switch (IFM_SUBTYPE(mii->mii_media_active)) {
184 case IFM_10_T: 184 case IFM_10_T:
185 case IFM_100_TX: 185 case IFM_100_TX:
186 usbnet_set_link(un, true); 186 usbnet_set_link(un, true);
187 break; 187 break;
188 case IFM_1000_T: 188 case IFM_1000_T:
189 usbnet_set_link(un, true); 189 usbnet_set_link(un, true);
190 break; 190 break;
191 default: 191 default:
192 break; 192 break;
193 } 193 }
194 } 194 }
195 195
196 /* Lost link, do nothing. */ 196 /* Lost link, do nothing. */
197 if (!usbnet_havelink(un)) 197 if (!usbnet_havelink(un))
198 return; 198 return;
199 199
200 val = 0; 200 val = 0;
201 if ((mii->mii_media_active & IFM_FDX) != 0) 201 if ((mii->mii_media_active & IFM_FDX) != 0)
202 val |= AXEN_MEDIUM_FDX; 202 val |= AXEN_MEDIUM_FDX;
203 203
204 val |= AXEN_MEDIUM_RXFLOW_CTRL_EN | AXEN_MEDIUM_TXFLOW_CTRL_EN | 204 val |= AXEN_MEDIUM_RXFLOW_CTRL_EN | AXEN_MEDIUM_TXFLOW_CTRL_EN |
205 AXEN_MEDIUM_RECV_EN; 205 AXEN_MEDIUM_RECV_EN;
206 switch (IFM_SUBTYPE(mii->mii_media_active)) { 206 switch (IFM_SUBTYPE(mii->mii_media_active)) {
207 case IFM_1000_T: 207 case IFM_1000_T:
208 val |= AXEN_MEDIUM_GIGA | AXEN_MEDIUM_EN_125MHZ; 208 val |= AXEN_MEDIUM_GIGA | AXEN_MEDIUM_EN_125MHZ;
209 break; 209 break;
210 case IFM_100_TX: 210 case IFM_100_TX:
211 val |= AXEN_MEDIUM_PS; 211 val |= AXEN_MEDIUM_PS;
212 break; 212 break;
213 case IFM_10_T: 213 case IFM_10_T:
214 /* doesn't need to be handled */ 214 /* doesn't need to be handled */
215 break; 215 break;
216 } 216 }
217 217
218 DPRINTF(("%s: val=%#x\n", __func__, val)); 218 DPRINTF(("%s: val=%#x\n", __func__, val));
219 wval = htole16(val); 219 wval = htole16(val);
220 err = axen_cmd(un, AXEN_CMD_MAC_WRITE2, 2, AXEN_MEDIUM_STATUS, &wval); 220 err = axen_cmd(un, AXEN_CMD_MAC_WRITE2, 2, AXEN_MEDIUM_STATUS, &wval);
221 if (err) 221 if (err)
222 aprint_error_dev(un->un_dev, "media change failed\n"); 222 aprint_error_dev(un->un_dev, "media change failed\n");
223} 223}
224 224
225static void 225static void
226axen_uno_mcast(struct ifnet *ifp) 226axen_uno_mcast(struct ifnet *ifp)
227{ 227{
228 struct usbnet * const un = ifp->if_softc; 228 struct usbnet * const un = ifp->if_softc;
229 struct ethercom *ec = usbnet_ec(un); 229 struct ethercom *ec = usbnet_ec(un);
230 struct ether_multi *enm; 230 struct ether_multi *enm;
231 struct ether_multistep step; 231 struct ether_multistep step;
232 uint32_t h = 0; 232 uint32_t h = 0;
233 uint16_t rxmode; 233 uint16_t rxmode;
234 uint8_t hashtbl[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 234 uint8_t hashtbl[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
235 uint16_t wval; 235 uint16_t wval;
236 236
237 if (usbnet_isdying(un)) 237 if (usbnet_isdying(un))
238 return; 238 return;
239 239
240 rxmode = 0; 240 rxmode = 0;
241 241
242 /* Enable receiver, set RX mode */ 242 /* Enable receiver, set RX mode */
243 axen_cmd(un, AXEN_CMD_MAC_READ2, 2, AXEN_MAC_RXCTL, &wval); 243 axen_cmd(un, AXEN_CMD_MAC_READ2, 2, AXEN_MAC_RXCTL, &wval);
244 rxmode = le16toh(wval); 244 rxmode = le16toh(wval);
245 rxmode &= ~(AXEN_RXCTL_ACPT_ALL_MCAST | AXEN_RXCTL_PROMISC | 245 rxmode &= ~(AXEN_RXCTL_ACPT_ALL_MCAST | AXEN_RXCTL_PROMISC |
246 AXEN_RXCTL_ACPT_MCAST); 246 AXEN_RXCTL_ACPT_MCAST);
247 247
248 if (ifp->if_flags & IFF_PROMISC) { 248 if (ifp->if_flags & IFF_PROMISC) {
249 DPRINTF(("%s: promisc\n", device_xname(un->un_dev))); 249 DPRINTF(("%s: promisc\n", device_xname(un->un_dev)));
250 rxmode |= AXEN_RXCTL_PROMISC; 250 rxmode |= AXEN_RXCTL_PROMISC;
251allmulti: 251allmulti:
252 ETHER_LOCK(ec); 252 ETHER_LOCK(ec);
253 ec->ec_flags |= ETHER_F_ALLMULTI; 253 ec->ec_flags |= ETHER_F_ALLMULTI;
254 ETHER_UNLOCK(ec); 254 ETHER_UNLOCK(ec);
255 rxmode |= AXEN_RXCTL_ACPT_ALL_MCAST 255 rxmode |= AXEN_RXCTL_ACPT_ALL_MCAST
256 /* | AXEN_RXCTL_ACPT_PHY_MCAST */; 256 /* | AXEN_RXCTL_ACPT_PHY_MCAST */;
257 } else { 257 } else {
258 /* now program new ones */ 258 /* now program new ones */
259 DPRINTF(("%s: initializing hash table\n", 259 DPRINTF(("%s: initializing hash table\n",
260 device_xname(un->un_dev))); 260 device_xname(un->un_dev)));
261 ETHER_LOCK(ec); 261 ETHER_LOCK(ec);
262 ec->ec_flags &= ~ETHER_F_ALLMULTI; 262 ec->ec_flags &= ~ETHER_F_ALLMULTI;
263 263
264 ETHER_FIRST_MULTI(step, ec, enm); 264 ETHER_FIRST_MULTI(step, ec, enm);
265 while (enm != NULL) { 265 while (enm != NULL) {
266 if (memcmp(enm->enm_addrlo, enm->enm_addrhi, 266 if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
267 ETHER_ADDR_LEN)) { 267 ETHER_ADDR_LEN)) {
268 DPRINTF(("%s: allmulti\n", 268 DPRINTF(("%s: allmulti\n",
269 device_xname(un->un_dev))); 269 device_xname(un->un_dev)));
270 memset(hashtbl, 0, sizeof(hashtbl)); 270 memset(hashtbl, 0, sizeof(hashtbl));
271 ETHER_UNLOCK(ec); 271 ETHER_UNLOCK(ec);
272 goto allmulti; 272 goto allmulti;
273 } 273 }
274 h = ether_crc32_be(enm->enm_addrlo, 274 h = ether_crc32_be(enm->enm_addrlo,
275 ETHER_ADDR_LEN) >> 26; 275 ETHER_ADDR_LEN) >> 26;
276 hashtbl[h / 8] |= 1 << (h % 8); 276 hashtbl[h / 8] |= 1 << (h % 8);
277 DPRINTF(("%s: %s added\n", 277 DPRINTF(("%s: %s added\n",
278 device_xname(un->un_dev), 278 device_xname(un->un_dev),
279 ether_sprintf(enm->enm_addrlo))); 279 ether_sprintf(enm->enm_addrlo)));
280 ETHER_NEXT_MULTI(step, enm); 280 ETHER_NEXT_MULTI(step, enm);
281 } 281 }
282 ETHER_UNLOCK(ec); 282 ETHER_UNLOCK(ec);
283 rxmode |= AXEN_RXCTL_ACPT_MCAST; 283 rxmode |= AXEN_RXCTL_ACPT_MCAST;
284 } 284 }
285 285
286 axen_cmd(un, AXEN_CMD_MAC_WRITE_FILTER, 8, AXEN_FILTER_MULTI, hashtbl); 286 axen_cmd(un, AXEN_CMD_MAC_WRITE_FILTER, 8, AXEN_FILTER_MULTI, hashtbl);
287 wval = htole16(rxmode); 287 wval = htole16(rxmode);
288 axen_cmd(un, AXEN_CMD_MAC_WRITE2, 2, AXEN_MAC_RXCTL, &wval); 288 axen_cmd(un, AXEN_CMD_MAC_WRITE2, 2, AXEN_MAC_RXCTL, &wval);
289} 289}
290 290
291static void 291static void
292axen_reset(struct usbnet *un) 292axen_reset(struct usbnet *un)
293{ 293{
294 usbnet_isowned_core(un); 294 usbnet_isowned_core(un);
295 if (usbnet_isdying(un)) 295 if (usbnet_isdying(un))
296 return; 296 return;
297 /* XXX What to reset? */ 297 /* XXX What to reset? */
298 298
299 /* Wait a little while for the chip to get its brains in order. */ 299 /* Wait a little while for the chip to get its brains in order. */
300 DELAY(1000); 300 DELAY(1000);
301} 301}
302 302
303static int 303static int
304axen_get_eaddr(struct usbnet *un, void *addr) 304axen_get_eaddr(struct usbnet *un, void *addr)
305{ 305{
306#if 1 306#if 1
307 return axen_cmd(un, AXEN_CMD_MAC_READ_ETHER, 6, AXEN_CMD_MAC_NODE_ID, 307 return axen_cmd(un, AXEN_CMD_MAC_READ_ETHER, 6, AXEN_CMD_MAC_NODE_ID,
308 addr); 308 addr);
309#else 309#else
310 int i, retry; 310 int i, retry;
311 uint8_t eeprom[20]; 311 uint8_t eeprom[20];
312 uint16_t csum; 312 uint16_t csum;
313 uint16_t buf; 313 uint16_t buf;
314 314
315 for (i = 0; i < 6; i++) { 315 for (i = 0; i < 6; i++) {
316 /* set eeprom address */ 316 /* set eeprom address */
317 buf = htole16(i); 317 buf = htole16(i);
318 axen_cmd(un, AXEN_CMD_MAC_WRITE, 1, AXEN_MAC_EEPROM_ADDR, &buf); 318 axen_cmd(un, AXEN_CMD_MAC_WRITE, 1, AXEN_MAC_EEPROM_ADDR, &buf);
319 319
320 /* set eeprom command */ 320 /* set eeprom command */
321 buf = htole16(AXEN_EEPROM_READ); 321 buf = htole16(AXEN_EEPROM_READ);
322 axen_cmd(un, AXEN_CMD_MAC_WRITE, 1, AXEN_MAC_EEPROM_CMD, &buf); 322 axen_cmd(un, AXEN_CMD_MAC_WRITE, 1, AXEN_MAC_EEPROM_CMD, &buf);
323 323
324 /* check the value is ready */ 324 /* check the value is ready */
325 retry = 3; 325 retry = 3;
326 do { 326 do {
327 buf = htole16(AXEN_EEPROM_READ); 327 buf = htole16(AXEN_EEPROM_READ);
328 usbd_delay_ms(un->un_udev, 10); 328 usbd_delay_ms(un->un_udev, 10);
329 axen_cmd(un, AXEN_CMD_MAC_READ, 1, AXEN_MAC_EEPROM_CMD, 329 axen_cmd(un, AXEN_CMD_MAC_READ, 1, AXEN_MAC_EEPROM_CMD,
330 &buf); 330 &buf);
331 retry--; 331 retry--;
332 if (retry < 0) 332 if (retry < 0)
333 return EINVAL; 333 return EINVAL;
334 } while ((le16toh(buf) & 0xff) & AXEN_EEPROM_BUSY); 334 } while ((le16toh(buf) & 0xff) & AXEN_EEPROM_BUSY);
335 335
336 /* read data */ 336 /* read data */
337 axen_cmd(un, AXEN_CMD_MAC_READ2, 2, AXEN_EEPROM_READ, 337 axen_cmd(un, AXEN_CMD_MAC_READ2, 2, AXEN_EEPROM_READ,
338 &eeprom[i * 2]); 338 &eeprom[i * 2]);
339 339
340 /* sanity check */ 340 /* sanity check */
341 if ((i == 0) && (eeprom[0] == 0xff)) 341 if ((i == 0) && (eeprom[0] == 0xff))
342 return EINVAL; 342 return EINVAL;
343 } 343 }
344 344
345 /* check checksum */ 345 /* check checksum */
346 csum = eeprom[6] + eeprom[7] + eeprom[8] + eeprom[9]; 346 csum = eeprom[6] + eeprom[7] + eeprom[8] + eeprom[9];
347 csum = (csum >> 8) + (csum & 0xff) + eeprom[10]; 347 csum = (csum >> 8) + (csum & 0xff) + eeprom[10];
348 if (csum != 0xff) { 348 if (csum != 0xff) {
349 printf("eeprom checksum mismatch(0x%02x)\n", csum); 349 printf("eeprom checksum mismatch(0x%02x)\n", csum);
350 return EINVAL; 350 return EINVAL;
351 } 351 }
352 352
353 memcpy(addr, eeprom, ETHER_ADDR_LEN); 353 memcpy(addr, eeprom, ETHER_ADDR_LEN);
354 return 0; 354 return 0;
355#endif 355#endif
356} 356}
357 357
358static void 358static void
359axen_ax88179_init(struct usbnet *un) 359axen_ax88179_init(struct usbnet *un)
360{ 360{
361 struct axen_qctrl qctrl; 361 struct axen_qctrl qctrl;
362 uint16_t ctl, temp; 362 uint16_t ctl, temp;
363 uint16_t wval; 363 uint16_t wval;
364 uint8_t val; 364 uint8_t val;
365 365
366 usbnet_lock_core(un); 366 usbnet_lock_core(un);
367 367
368 /* XXX: ? */ 368 /* XXX: ? */
369 axen_cmd(un, AXEN_CMD_MAC_READ, 1, AXEN_UNK_05, &val); 369 axen_cmd(un, AXEN_CMD_MAC_READ, 1, AXEN_UNK_05, &val);
370 DPRINTFN(5, ("AXEN_CMD_MAC_READ(0x05): 0x%02x\n", val)); 370 DPRINTFN(5, ("AXEN_CMD_MAC_READ(0x05): 0x%02x\n", val));
371 371
372 /* check AX88179 version, UA1 / UA2 */ 372 /* check AX88179 version, UA1 / UA2 */
373 axen_cmd(un, AXEN_CMD_MAC_READ, 1, AXEN_GENERAL_STATUS, &val); 373 axen_cmd(un, AXEN_CMD_MAC_READ, 1, AXEN_GENERAL_STATUS, &val);
374 /* UA1 */ 374 /* UA1 */
375 if (!(val & AXEN_GENERAL_STATUS_MASK)) { 375 if (!(val & AXEN_GENERAL_STATUS_MASK)) {
376 DPRINTF(("AX88179 ver. UA1\n")); 376 DPRINTF(("AX88179 ver. UA1\n"));
377 } else { 377 } else {
378 DPRINTF(("AX88179 ver. UA2\n")); 378 DPRINTF(("AX88179 ver. UA2\n"));
379 } 379 }
380 380
381 /* power up ethernet PHY */ 381 /* power up ethernet PHY */
382 wval = htole16(0); 382 wval = htole16(0);
383 axen_cmd(un, AXEN_CMD_MAC_WRITE2, 2, AXEN_PHYPWR_RSTCTL, &wval); 383 axen_cmd(un, AXEN_CMD_MAC_WRITE2, 2, AXEN_PHYPWR_RSTCTL, &wval);
384 384
385 wval = htole16(AXEN_PHYPWR_RSTCTL_IPRL); 385 wval = htole16(AXEN_PHYPWR_RSTCTL_IPRL);
386 axen_cmd(un, AXEN_CMD_MAC_WRITE2, 2, AXEN_PHYPWR_RSTCTL, &wval); 386 axen_cmd(un, AXEN_CMD_MAC_WRITE2, 2, AXEN_PHYPWR_RSTCTL, &wval);
387 usbd_delay_ms(un->un_udev, 200); 387 usbd_delay_ms(un->un_udev, 200);
388 388
389 /* set clock mode */ 389 /* set clock mode */
390 val = AXEN_PHYCLK_ACS | AXEN_PHYCLK_BCS; 390 val = AXEN_PHYCLK_ACS | AXEN_PHYCLK_BCS;
391 axen_cmd(un, AXEN_CMD_MAC_WRITE, 1, AXEN_PHYCLK, &val); 391 axen_cmd(un, AXEN_CMD_MAC_WRITE, 1, AXEN_PHYCLK, &val);
392 usbd_delay_ms(un->un_udev, 100); 392 usbd_delay_ms(un->un_udev, 100);
393 393
394 /* set monitor mode (disable) */ 394 /* set monitor mode (disable) */
395 val = AXEN_MONITOR_NONE; 395 val = AXEN_MONITOR_NONE;
396 axen_cmd(un, AXEN_CMD_MAC_WRITE, 1, AXEN_MONITOR_MODE, &val); 396 axen_cmd(un, AXEN_CMD_MAC_WRITE, 1, AXEN_MONITOR_MODE, &val);
397 397
398 /* enable auto detach */ 398 /* enable auto detach */
399 axen_cmd(un, AXEN_CMD_EEPROM_READ, 2, AXEN_EEPROM_STAT, &wval); 399 axen_cmd(un, AXEN_CMD_EEPROM_READ, 2, AXEN_EEPROM_STAT, &wval);
400 temp = le16toh(wval); 400 temp = le16toh(wval);
401 DPRINTFN(2,("EEPROM0x43 = 0x%04x\n", temp)); 401 DPRINTFN(2,("EEPROM0x43 = 0x%04x\n", temp));
402 if (!(temp == 0xffff) && !(temp & 0x0100)) { 402 if (!(temp == 0xffff) && !(temp & 0x0100)) {
403 /* Enable auto detach bit */ 403 /* Enable auto detach bit */
404 val = 0; 404 val = 0;
405 axen_cmd(un, AXEN_CMD_MAC_WRITE, 1, AXEN_PHYCLK, &val); 405 axen_cmd(un, AXEN_CMD_MAC_WRITE, 1, AXEN_PHYCLK, &val);
406 val = AXEN_PHYCLK_ULR; 406 val = AXEN_PHYCLK_ULR;
407 axen_cmd(un, AXEN_CMD_MAC_WRITE, 1, AXEN_PHYCLK, &val); 407 axen_cmd(un, AXEN_CMD_MAC_WRITE, 1, AXEN_PHYCLK, &val);
408 usbd_delay_ms(un->un_udev, 100); 408 usbd_delay_ms(un->un_udev, 100);
409 409
410 axen_cmd(un, AXEN_CMD_MAC_READ2, 2, AXEN_PHYPWR_RSTCTL, &wval); 410 axen_cmd(un, AXEN_CMD_MAC_READ2, 2, AXEN_PHYPWR_RSTCTL, &wval);
411 ctl = le16toh(wval); 411 ctl = le16toh(wval);
412 ctl |= AXEN_PHYPWR_RSTCTL_AUTODETACH; 412 ctl |= AXEN_PHYPWR_RSTCTL_AUTODETACH;
413 wval = htole16(ctl); 413 wval = htole16(ctl);
414 axen_cmd(un, AXEN_CMD_MAC_WRITE2, 2, AXEN_PHYPWR_RSTCTL, &wval); 414 axen_cmd(un, AXEN_CMD_MAC_WRITE2, 2, AXEN_PHYPWR_RSTCTL, &wval);
415 usbd_delay_ms(un->un_udev, 200); 415 usbd_delay_ms(un->un_udev, 200);
416 aprint_error_dev(un->un_dev, "enable auto detach (0x%04x)\n", 416 aprint_error_dev(un->un_dev, "enable auto detach (0x%04x)\n",
417 ctl); 417 ctl);
418 } 418 }
419 419
420 /* bulkin queue setting */ 420 /* bulkin queue setting */
421 axen_cmd(un, AXEN_CMD_MAC_READ, 1, AXEN_USB_UPLINK, &val); 421 axen_cmd(un, AXEN_CMD_MAC_READ, 1, AXEN_USB_UPLINK, &val);
422 switch (val) { 422 switch (val) {
423 case AXEN_USB_FS: 423 case AXEN_USB_FS:
424 DPRINTF(("uplink: USB1.1\n")); 424 DPRINTF(("uplink: USB1.1\n"));
425 qctrl.ctrl = 0x07; 425 qctrl.ctrl = 0x07;
426 qctrl.timer_low = 0xcc; 426 qctrl.timer_low = 0xcc;
427 qctrl.timer_high = 0x4c; 427 qctrl.timer_high = 0x4c;
428 qctrl.bufsize = AXEN_BUFSZ_LS - 1; 428 qctrl.bufsize = AXEN_BUFSZ_LS - 1;
429 qctrl.ifg = 0x08; 429 qctrl.ifg = 0x08;
430 break; 430 break;
431 case AXEN_USB_HS: 431 case AXEN_USB_HS:
432 DPRINTF(("uplink: USB2.0\n")); 432 DPRINTF(("uplink: USB2.0\n"));
433 qctrl.ctrl = 0x07; 433 qctrl.ctrl = 0x07;
434 qctrl.timer_low = 0x02; 434 qctrl.timer_low = 0x02;
435 qctrl.timer_high = 0xa0; 435 qctrl.timer_high = 0xa0;
436 qctrl.bufsize = AXEN_BUFSZ_HS - 1; 436 qctrl.bufsize = AXEN_BUFSZ_HS - 1;
437 qctrl.ifg = 0xff; 437 qctrl.ifg = 0xff;
438 break; 438 break;
439 case AXEN_USB_SS: 439 case AXEN_USB_SS:
440 DPRINTF(("uplink: USB3.0\n")); 440 DPRINTF(("uplink: USB3.0\n"));
441 qctrl.ctrl = 0x07; 441 qctrl.ctrl = 0x07;
442 qctrl.timer_low = 0x4f; 442 qctrl.timer_low = 0x4f;
443 qctrl.timer_high = 0x00; 443 qctrl.timer_high = 0x00;
444 qctrl.bufsize = AXEN_BUFSZ_SS - 1; 444 qctrl.bufsize = AXEN_BUFSZ_SS - 1;
445 qctrl.ifg = 0xff; 445 qctrl.ifg = 0xff;
446 break; 446 break;
447 default: 447 default:
448 aprint_error_dev(un->un_dev, "unknown uplink bus:0x%02x\n", 448 aprint_error_dev(un->un_dev, "unknown uplink bus:0x%02x\n",
449 val); 449 val);
450 usbnet_unlock_core(un); 450 usbnet_unlock_core(un);
451 return; 451 return;
452 } 452 }
453 axen_cmd(un, AXEN_CMD_MAC_SET_RXSR, 5, AXEN_RX_BULKIN_QCTRL, &qctrl); 453 axen_cmd(un, AXEN_CMD_MAC_SET_RXSR, 5, AXEN_RX_BULKIN_QCTRL, &qctrl);
454 454
455 /* 455 /*
456 * set buffer high/low watermark to pause/resume. 456 * set buffer high/low watermark to pause/resume.
457 * write 2byte will set high/log simultaneous with AXEN_PAUSE_HIGH. 457 * write 2byte will set high/log simultaneous with AXEN_PAUSE_HIGH.
458 * XXX: what is the best value? OSX driver uses 0x3c-0x4c as LOW-HIGH 458 * XXX: what is the best value? OSX driver uses 0x3c-0x4c as LOW-HIGH
459 * watermark parameters. 459 * watermark parameters.
460 */ 460 */
461 val = 0x34; 461 val = 0x34;
462 axen_cmd(un, AXEN_CMD_MAC_WRITE, 1, AXEN_PAUSE_LOW_WATERMARK, &val); 462 axen_cmd(un, AXEN_CMD_MAC_WRITE, 1, AXEN_PAUSE_LOW_WATERMARK, &val);
463 val = 0x52; 463 val = 0x52;
464 axen_cmd(un, AXEN_CMD_MAC_WRITE, 1, AXEN_PAUSE_HIGH_WATERMARK, &val); 464 axen_cmd(un, AXEN_CMD_MAC_WRITE, 1, AXEN_PAUSE_HIGH_WATERMARK, &val);
465 465
466 /* Set RX/TX configuration. */ 466 /* Set RX/TX configuration. */
467 /* Set RX control register */ 467 /* Set RX control register */
468 ctl = AXEN_RXCTL_IPE | AXEN_RXCTL_DROPCRCERR | AXEN_RXCTL_AUTOB; 468 ctl = AXEN_RXCTL_IPE | AXEN_RXCTL_DROPCRCERR | AXEN_RXCTL_AUTOB;
469 wval = htole16(ctl); 469 wval = htole16(ctl);
470 axen_cmd(un, AXEN_CMD_MAC_WRITE2, 2, AXEN_MAC_RXCTL, &wval); 470 axen_cmd(un, AXEN_CMD_MAC_WRITE2, 2, AXEN_MAC_RXCTL, &wval);
471 471
472 /* set monitor mode (enable) */ 472 /* set monitor mode (enable) */
473 val = AXEN_MONITOR_PMETYPE | AXEN_MONITOR_PMEPOL | AXEN_MONITOR_RWMP; 473 val = AXEN_MONITOR_PMETYPE | AXEN_MONITOR_PMEPOL | AXEN_MONITOR_RWMP;
474 axen_cmd(un, AXEN_CMD_MAC_WRITE, 1, AXEN_MONITOR_MODE, &val); 474 axen_cmd(un, AXEN_CMD_MAC_WRITE, 1, AXEN_MONITOR_MODE, &val);
475 axen_cmd(un, AXEN_CMD_MAC_READ, 1, AXEN_MONITOR_MODE, &val); 475 axen_cmd(un, AXEN_CMD_MAC_READ, 1, AXEN_MONITOR_MODE, &val);
476 DPRINTF(("axen: Monitor mode = 0x%02x\n", val)); 476 DPRINTF(("axen: Monitor mode = 0x%02x\n", val));
477 477
478 /* set medium type */ 478 /* set medium type */
479 ctl = AXEN_MEDIUM_GIGA | AXEN_MEDIUM_FDX | AXEN_MEDIUM_EN_125MHZ | 479 ctl = AXEN_MEDIUM_GIGA | AXEN_MEDIUM_FDX | AXEN_MEDIUM_EN_125MHZ |
480 AXEN_MEDIUM_RXFLOW_CTRL_EN | AXEN_MEDIUM_TXFLOW_CTRL_EN | 480 AXEN_MEDIUM_RXFLOW_CTRL_EN | AXEN_MEDIUM_TXFLOW_CTRL_EN |
481 AXEN_MEDIUM_RECV_EN; 481 AXEN_MEDIUM_RECV_EN;
482 wval = htole16(ctl); 482 wval = htole16(ctl);
483 DPRINTF(("axen: set to medium mode: 0x%04x\n", ctl)); 483 DPRINTF(("axen: set to medium mode: 0x%04x\n", ctl));
484 axen_cmd(un, AXEN_CMD_MAC_WRITE2, 2, AXEN_MEDIUM_STATUS, &wval); 484 axen_cmd(un, AXEN_CMD_MAC_WRITE2, 2, AXEN_MEDIUM_STATUS, &wval);
485 usbd_delay_ms(un->un_udev, 100); 485 usbd_delay_ms(un->un_udev, 100);
486 486
487 axen_cmd(un, AXEN_CMD_MAC_READ2, 2, AXEN_MEDIUM_STATUS, &wval); 487 axen_cmd(un, AXEN_CMD_MAC_READ2, 2, AXEN_MEDIUM_STATUS, &wval);
488 DPRINTF(("axen: current medium mode: 0x%04x\n", le16toh(wval))); 488 DPRINTF(("axen: current medium mode: 0x%04x\n", le16toh(wval)));
489 489
490#if 0 /* XXX: TBD.... */ 490#if 0 /* XXX: TBD.... */
491#define GMII_LED_ACTIVE 0x1a 491#define GMII_LED_ACTIVE 0x1a
492#define GMII_PHY_PAGE_SEL 0x1e 492#define GMII_PHY_PAGE_SEL 0x1e
493#define GMII_PHY_PAGE_SEL 0x1f 493#define GMII_PHY_PAGE_SEL 0x1f
494#define GMII_PAGE_EXT 0x0007 494#define GMII_PAGE_EXT 0x0007
495 usbnet_mii_writereg(un->un_dev, un->un_phyno, GMII_PHY_PAGE_SEL, 495 axen_uno_mii_write_reg(un, un->un_phyno, GMII_PHY_PAGE_SEL,
496 GMII_PAGE_EXT); 496 GMII_PAGE_EXT);
497 usbnet_mii_writereg(un->un_dev, un->un_phyno, GMII_PHY_PAGE, 497 axen_uno_mii_write_reg(un, un->un_phyno, GMII_PHY_PAGE,
498 0x002c); 498 0x002c);
499#endif 499#endif
500 500
501#if 1 /* XXX: phy hack ? */ 501#if 1 /* XXX: phy hack ? */
502 usbnet_mii_writereg(un->un_dev, un->un_phyno, 0x1F, 0x0005); 502 axen_uno_mii_write_reg(un, un->un_phyno, 0x1F, 0x0005);
503 usbnet_mii_writereg(un->un_dev, un->un_phyno, 0x0C, 0x0000); 503 axen_uno_mii_write_reg(un, un->un_phyno, 0x0C, 0x0000);
504 usbnet_mii_readreg(un->un_dev, un->un_phyno, 0x0001, &wval); 504 axen_uno_mii_read_reg(un, un->un_phyno, 0x0001, &wval);
505 usbnet_mii_writereg(un->un_dev, un->un_phyno, 0x01, wval | 0x0080); 505 axen_uno_mii_write_reg(un, un->un_phyno, 0x01, wval | 0x0080);
506 usbnet_mii_writereg(un->un_dev, un->un_phyno, 0x1F, 0x0000); 506 axen_uno_mii_write_reg(un, un->un_phyno, 0x1F, 0x0000);
507#endif 507#endif
508 508
509 usbnet_unlock_core(un); 509 usbnet_unlock_core(un);
510} 510}
511 511
512static void 512static void
513axen_setoe_locked(struct usbnet *un) 513axen_setoe_locked(struct usbnet *un)
514{ 514{
515 struct ifnet * const ifp = usbnet_ifp(un); 515 struct ifnet * const ifp = usbnet_ifp(un);
516 uint64_t enabled = ifp->if_capenable; 516 uint64_t enabled = ifp->if_capenable;
517 uint8_t val; 517 uint8_t val;
518 518
519 KASSERT(IFNET_LOCKED(ifp)); 519 KASSERT(IFNET_LOCKED(ifp));
520 520
521 val = AXEN_RXCOE_OFF; 521 val = AXEN_RXCOE_OFF;
522 if (enabled & IFCAP_CSUM_IPv4_Rx) 522 if (enabled & IFCAP_CSUM_IPv4_Rx)
523 val |= AXEN_RXCOE_IPv4; 523 val |= AXEN_RXCOE_IPv4;
524 if (enabled & IFCAP_CSUM_TCPv4_Rx) 524 if (enabled & IFCAP_CSUM_TCPv4_Rx)
525 val |= AXEN_RXCOE_TCPv4; 525 val |= AXEN_RXCOE_TCPv4;
526 if (enabled & IFCAP_CSUM_UDPv4_Rx) 526 if (enabled & IFCAP_CSUM_UDPv4_Rx)
527 val |= AXEN_RXCOE_UDPv4; 527 val |= AXEN_RXCOE_UDPv4;
528 if (enabled & IFCAP_CSUM_TCPv6_Rx) 528 if (enabled & IFCAP_CSUM_TCPv6_Rx)
529 val |= AXEN_RXCOE_TCPv6; 529 val |= AXEN_RXCOE_TCPv6;
530 if (enabled & IFCAP_CSUM_UDPv6_Rx) 530 if (enabled & IFCAP_CSUM_UDPv6_Rx)
531 val |= AXEN_RXCOE_UDPv6; 531 val |= AXEN_RXCOE_UDPv6;
532 axen_cmd(un, AXEN_CMD_MAC_WRITE, 1, AXEN_RX_COE, &val); 532 axen_cmd(un, AXEN_CMD_MAC_WRITE, 1, AXEN_RX_COE, &val);
533 533
534 val = AXEN_TXCOE_OFF; 534 val = AXEN_TXCOE_OFF;
535 if (enabled & IFCAP_CSUM_IPv4_Tx) 535 if (enabled & IFCAP_CSUM_IPv4_Tx)
536 val |= AXEN_TXCOE_IPv4; 536 val |= AXEN_TXCOE_IPv4;
537 if (enabled & IFCAP_CSUM_TCPv4_Tx) 537 if (enabled & IFCAP_CSUM_TCPv4_Tx)
538 val |= AXEN_TXCOE_TCPv4; 538 val |= AXEN_TXCOE_TCPv4;
539 if (enabled & IFCAP_CSUM_UDPv4_Tx) 539 if (enabled & IFCAP_CSUM_UDPv4_Tx)
540 val |= AXEN_TXCOE_UDPv4; 540 val |= AXEN_TXCOE_UDPv4;
541 if (enabled & IFCAP_CSUM_TCPv6_Tx) 541 if (enabled & IFCAP_CSUM_TCPv6_Tx)
542 val |= AXEN_TXCOE_TCPv6; 542 val |= AXEN_TXCOE_TCPv6;
543 if (enabled & IFCAP_CSUM_UDPv6_Tx) 543 if (enabled & IFCAP_CSUM_UDPv6_Tx)
544 val |= AXEN_TXCOE_UDPv6; 544 val |= AXEN_TXCOE_UDPv6;
545 axen_cmd(un, AXEN_CMD_MAC_WRITE, 1, AXEN_TX_COE, &val); 545 axen_cmd(un, AXEN_CMD_MAC_WRITE, 1, AXEN_TX_COE, &val);
546} 546}
547 547
548static int 548static int
549axen_uno_ioctl(struct ifnet *ifp, u_long cmd, void *data) 549axen_uno_ioctl(struct ifnet *ifp, u_long cmd, void *data)
550{ 550{
551 struct usbnet * const un = ifp->if_softc; 551 struct usbnet * const un = ifp->if_softc;
552 552
553 usbnet_lock_core(un); 553 usbnet_lock_core(un);
554 554
555 switch (cmd) { 555 switch (cmd) {
556 case SIOCSIFCAP: 556 case SIOCSIFCAP:
557 axen_setoe_locked(un); 557 axen_setoe_locked(un);
558 break; 558 break;
559 default: 559 default:
560 break; 560 break;
561 } 561 }
562 562
563 usbnet_unlock_core(un); 563 usbnet_unlock_core(un);
564 564
565 return 0; 565 return 0;
566} 566}
567 567
568static int 568static int
569axen_match(device_t parent, cfdata_t match, void *aux) 569axen_match(device_t parent, cfdata_t match, void *aux)
570{ 570{
571 struct usb_attach_arg *uaa = aux; 571 struct usb_attach_arg *uaa = aux;
572 572
573 return axen_lookup(uaa->uaa_vendor, uaa->uaa_product) != NULL ? 573 return axen_lookup(uaa->uaa_vendor, uaa->uaa_product) != NULL ?
574 UMATCH_VENDOR_PRODUCT : UMATCH_NONE; 574 UMATCH_VENDOR_PRODUCT : UMATCH_NONE;
575} 575}
576 576
577static void 577static void
578axen_attach(device_t parent, device_t self, void *aux) 578axen_attach(device_t parent, device_t self, void *aux)
579{ 579{
580 USBNET_MII_DECL_DEFAULT(unm); 580 USBNET_MII_DECL_DEFAULT(unm);
581 struct usbnet * const un = device_private(self); 581 struct usbnet * const un = device_private(self);
582 struct usb_attach_arg *uaa = aux; 582 struct usb_attach_arg *uaa = aux;
583 struct usbd_device *dev = uaa->uaa_device; 583 struct usbd_device *dev = uaa->uaa_device;
584 usbd_status err; 584 usbd_status err;
585 usb_interface_descriptor_t *id; 585 usb_interface_descriptor_t *id;
586 usb_endpoint_descriptor_t *ed; 586 usb_endpoint_descriptor_t *ed;
587 char *devinfop; 587 char *devinfop;
588 uint16_t axen_flags; 588 uint16_t axen_flags;
589 int i; 589 int i;
590 590
591 aprint_naive("\n"); 591 aprint_naive("\n");
592 aprint_normal("\n"); 592 aprint_normal("\n");
593 devinfop = usbd_devinfo_alloc(dev, 0); 593 devinfop = usbd_devinfo_alloc(dev, 0);
594 aprint_normal_dev(self, "%s\n", devinfop); 594 aprint_normal_dev(self, "%s\n", devinfop);
595 usbd_devinfo_free(devinfop); 595 usbd_devinfo_free(devinfop);
596 596
597 un->un_dev = self; 597 un->un_dev = self;
598 un->un_udev = dev; 598 un->un_udev = dev;
599 un->un_sc = un; 599 un->un_sc = un;
600 un->un_ops = &axen_ops; 600 un->un_ops = &axen_ops;
601 un->un_rx_xfer_flags = USBD_SHORT_XFER_OK; 601 un->un_rx_xfer_flags = USBD_SHORT_XFER_OK;
602 un->un_tx_xfer_flags = USBD_FORCE_SHORT_XFER; 602 un->un_tx_xfer_flags = USBD_FORCE_SHORT_XFER;
603 un->un_rx_list_cnt = AXEN_RX_LIST_CNT; 603 un->un_rx_list_cnt = AXEN_RX_LIST_CNT;
604 un->un_tx_list_cnt = AXEN_TX_LIST_CNT; 604 un->un_tx_list_cnt = AXEN_TX_LIST_CNT;
605 605
606 err = usbd_set_config_no(dev, AXEN_CONFIG_NO, 1); 606 err = usbd_set_config_no(dev, AXEN_CONFIG_NO, 1);
607 if (err) { 607 if (err) {
608 aprint_error_dev(self, "failed to set configuration" 608 aprint_error_dev(self, "failed to set configuration"
609 ", err=%s\n", usbd_errstr(err)); 609 ", err=%s\n", usbd_errstr(err));
610 return; 610 return;
611 } 611 }
612 612
613 axen_flags = axen_lookup(uaa->uaa_vendor, uaa->uaa_product)->axen_flags; 613 axen_flags = axen_lookup(uaa->uaa_vendor, uaa->uaa_product)->axen_flags;
614 614
615 err = usbd_device2interface_handle(dev, AXEN_IFACE_IDX, &un->un_iface); 615 err = usbd_device2interface_handle(dev, AXEN_IFACE_IDX, &un->un_iface);
616 if (err) { 616 if (err) {
617 aprint_error_dev(self, "getting interface handle failed\n"); 617 aprint_error_dev(self, "getting interface handle failed\n");
618 return; 618 return;
619 } 619 }
620 620
621 /* decide on what our bufsize will be */ 621 /* decide on what our bufsize will be */
622 switch (dev->ud_speed) { 622 switch (dev->ud_speed) {
623 case USB_SPEED_SUPER: 623 case USB_SPEED_SUPER:
624 un->un_rx_bufsz = AXEN_BUFSZ_SS * 1024; 624 un->un_rx_bufsz = AXEN_BUFSZ_SS * 1024;
625 break; 625 break;
626 case USB_SPEED_HIGH: 626 case USB_SPEED_HIGH:
627 un->un_rx_bufsz = AXEN_BUFSZ_HS * 1024; 627 un->un_rx_bufsz = AXEN_BUFSZ_HS * 1024;
628 break; 628 break;
629 default: 629 default:
630 un->un_rx_bufsz = AXEN_BUFSZ_LS * 1024; 630 un->un_rx_bufsz = AXEN_BUFSZ_LS * 1024;
631 break; 631 break;
632 } 632 }
633 un->un_tx_bufsz = IP_MAXPACKET + ETHER_HDR_LEN + ETHER_CRC_LEN + 633 un->un_tx_bufsz = IP_MAXPACKET + ETHER_HDR_LEN + ETHER_CRC_LEN +
634 ETHER_VLAN_ENCAP_LEN + sizeof(struct axen_sframe_hdr); 634 ETHER_VLAN_ENCAP_LEN + sizeof(struct axen_sframe_hdr);
635 635
636 /* Find endpoints. */ 636 /* Find endpoints. */
637 id = usbd_get_interface_descriptor(un->un_iface); 637 id = usbd_get_interface_descriptor(un->un_iface);
638 for (i = 0; i < id->bNumEndpoints; i++) { 638 for (i = 0; i < id->bNumEndpoints; i++) {
639 ed = usbd_interface2endpoint_descriptor(un->un_iface, i); 639 ed = usbd_interface2endpoint_descriptor(un->un_iface, i);
640 if (!ed) { 640 if (!ed) {
641 aprint_error_dev(self, "couldn't get ep %d\n", i); 641 aprint_error_dev(self, "couldn't get ep %d\n", i);
642 return; 642 return;
643 } 643 }
644 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 644 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
645 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 645 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
646 un->un_ed[USBNET_ENDPT_RX] = ed->bEndpointAddress; 646 un->un_ed[USBNET_ENDPT_RX] = ed->bEndpointAddress;
647 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && 647 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
648 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 648 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
649 un->un_ed[USBNET_ENDPT_TX] = ed->bEndpointAddress; 649 un->un_ed[USBNET_ENDPT_TX] = ed->bEndpointAddress;
650#if 0 /* not used yet */ 650#if 0 /* not used yet */
651 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 651 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
652 UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { 652 UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
653 un->un_ed[USBNET_ENDPT_INTR] = ed->bEndpointAddress; 653 un->un_ed[USBNET_ENDPT_INTR] = ed->bEndpointAddress;
654#endif 654#endif
655 } 655 }
656 } 656 }
657 657
658 /* Set these up now for axen_cmd(). */ 658 /* Set these up now for axen_cmd(). */
659 usbnet_attach(un, "axendet"); 659 usbnet_attach(un, "axendet");
660 660
661 un->un_phyno = AXEN_PHY_ID; 661 un->un_phyno = AXEN_PHY_ID;
662 DPRINTF(("%s: phyno %d\n", device_xname(self), un->un_phyno)); 662 DPRINTF(("%s: phyno %d\n", device_xname(self), un->un_phyno));
663 663
664 /* Get station address. */ 664 /* Get station address. */
665 usbnet_lock_core(un); 665 usbnet_lock_core(un);
666 if (axen_get_eaddr(un, &un->un_eaddr)) { 666 if (axen_get_eaddr(un, &un->un_eaddr)) {
667 usbnet_unlock_core(un); 667 usbnet_unlock_core(un);
668 printf("EEPROM checksum error\n"); 668 printf("EEPROM checksum error\n");
669 return; 669 return;
670 } 670 }
671 usbnet_unlock_core(un); 671 usbnet_unlock_core(un);
672 672
673 axen_ax88179_init(un); 673 axen_ax88179_init(un);
674 674
675 /* An ASIX chip was detected. Inform the world. */ 675 /* An ASIX chip was detected. Inform the world. */
676 if (axen_flags & AX178A) 676 if (axen_flags & AX178A)
677 aprint_normal_dev(self, "AX88178a\n"); 677 aprint_normal_dev(self, "AX88178a\n");
678 else if (axen_flags & AX179) 678 else if (axen_flags & AX179)
679 aprint_normal_dev(self, "AX88179\n"); 679 aprint_normal_dev(self, "AX88179\n");
680 else 680 else
681 aprint_normal_dev(self, "(unknown)\n"); 681 aprint_normal_dev(self, "(unknown)\n");
682 682
683 struct ethercom *ec = usbnet_ec(un); 683 struct ethercom *ec = usbnet_ec(un);
684 ec->ec_capabilities = ETHERCAP_VLAN_MTU; 684 ec->ec_capabilities = ETHERCAP_VLAN_MTU;
685 685
686 /* Adapter does not support TSOv6 (They call it LSOv2). */ 686 /* Adapter does not support TSOv6 (They call it LSOv2). */
687 struct ifnet *ifp = usbnet_ifp(un); 687 struct ifnet *ifp = usbnet_ifp(un);
688 ifp->if_capabilities |= IFCAP_TSOv4 | 688 ifp->if_capabilities |= IFCAP_TSOv4 |
689 IFCAP_CSUM_IPv4_Rx | IFCAP_CSUM_IPv4_Tx | 689 IFCAP_CSUM_IPv4_Rx | IFCAP_CSUM_IPv4_Tx |
690 IFCAP_CSUM_TCPv4_Rx | IFCAP_CSUM_TCPv4_Tx | 690 IFCAP_CSUM_TCPv4_Rx | IFCAP_CSUM_TCPv4_Tx |
691 IFCAP_CSUM_UDPv4_Rx | IFCAP_CSUM_UDPv4_Tx | 691 IFCAP_CSUM_UDPv4_Rx | IFCAP_CSUM_UDPv4_Tx |
692 IFCAP_CSUM_TCPv6_Rx | IFCAP_CSUM_TCPv6_Tx | 692 IFCAP_CSUM_TCPv6_Rx | IFCAP_CSUM_TCPv6_Tx |
693 IFCAP_CSUM_UDPv6_Rx | IFCAP_CSUM_UDPv6_Tx; 693 IFCAP_CSUM_UDPv6_Rx | IFCAP_CSUM_UDPv6_Tx;
694 694
695 usbnet_attach_ifp(un, IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST, 695 usbnet_attach_ifp(un, IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST,
696 0, &unm); 696 0, &unm);
697} 697}
698 698
699static int 699static int
700axen_csum_flags_rx(struct ifnet *ifp, uint32_t pkt_hdr) 700axen_csum_flags_rx(struct ifnet *ifp, uint32_t pkt_hdr)
701{ 701{
702 int enabled_flags = ifp->if_csum_flags_rx; 702 int enabled_flags = ifp->if_csum_flags_rx;
703 int csum_flags = 0; 703 int csum_flags = 0;
704 int l3_type, l4_type; 704 int l3_type, l4_type;
705 705
706 if (enabled_flags == 0) 706 if (enabled_flags == 0)
707 return 0; 707 return 0;
708 708
709 l3_type = (pkt_hdr & AXEN_RXHDR_L3_TYPE_MASK) >> 709 l3_type = (pkt_hdr & AXEN_RXHDR_L3_TYPE_MASK) >>
710 AXEN_RXHDR_L3_TYPE_OFFSET; 710 AXEN_RXHDR_L3_TYPE_OFFSET;
711 711
712 if (l3_type == AXEN_RXHDR_L3_TYPE_IPV4) 712 if (l3_type == AXEN_RXHDR_L3_TYPE_IPV4)
713 csum_flags |= M_CSUM_IPv4; 713 csum_flags |= M_CSUM_IPv4;
714 714
715 l4_type = (pkt_hdr & AXEN_RXHDR_L4_TYPE_MASK) >> 715 l4_type = (pkt_hdr & AXEN_RXHDR_L4_TYPE_MASK) >>
716 AXEN_RXHDR_L4_TYPE_OFFSET; 716 AXEN_RXHDR_L4_TYPE_OFFSET;
717 717
718 switch (l4_type) { 718 switch (l4_type) {
719 case AXEN_RXHDR_L4_TYPE_TCP: 719 case AXEN_RXHDR_L4_TYPE_TCP:
720 if (l3_type == AXEN_RXHDR_L3_TYPE_IPV4) 720 if (l3_type == AXEN_RXHDR_L3_TYPE_IPV4)
721 csum_flags |= M_CSUM_TCPv4; 721 csum_flags |= M_CSUM_TCPv4;
722 else 722 else
723 csum_flags |= M_CSUM_TCPv6; 723 csum_flags |= M_CSUM_TCPv6;
724 break; 724 break;
725 case AXEN_RXHDR_L4_TYPE_UDP: 725 case AXEN_RXHDR_L4_TYPE_UDP:
726 if (l3_type == AXEN_RXHDR_L3_TYPE_IPV4) 726 if (l3_type == AXEN_RXHDR_L3_TYPE_IPV4)
727 csum_flags |= M_CSUM_UDPv4; 727 csum_flags |= M_CSUM_UDPv4;
728 else 728 else
729 csum_flags |= M_CSUM_UDPv6; 729 csum_flags |= M_CSUM_UDPv6;
730 break; 730 break;
731 default: 731 default:
732 break; 732 break;
733 } 733 }
734 734
735 csum_flags &= enabled_flags; 735 csum_flags &= enabled_flags;
736 if ((csum_flags & M_CSUM_IPv4) && (pkt_hdr & AXEN_RXHDR_L3CSUM_ERR)) 736 if ((csum_flags & M_CSUM_IPv4) && (pkt_hdr & AXEN_RXHDR_L3CSUM_ERR))
737 csum_flags |= M_CSUM_IPv4_BAD; 737 csum_flags |= M_CSUM_IPv4_BAD;
738 if ((csum_flags & ~M_CSUM_IPv4) && (pkt_hdr & AXEN_RXHDR_L4CSUM_ERR)) 738 if ((csum_flags & ~M_CSUM_IPv4) && (pkt_hdr & AXEN_RXHDR_L4CSUM_ERR))
739 csum_flags |= M_CSUM_TCP_UDP_BAD; 739 csum_flags |= M_CSUM_TCP_UDP_BAD;
740 740
741 return csum_flags; 741 return csum_flags;
742} 742}
743 743
744static void 744static void
745axen_uno_rx_loop(struct usbnet *un, struct usbnet_chain *c, uint32_t total_len) 745axen_uno_rx_loop(struct usbnet *un, struct usbnet_chain *c, uint32_t total_len)
746{ 746{
747 struct ifnet *ifp = usbnet_ifp(un); 747 struct ifnet *ifp = usbnet_ifp(un);
748 uint8_t *buf = c->unc_buf; 748 uint8_t *buf = c->unc_buf;
749 uint32_t rx_hdr, pkt_hdr; 749 uint32_t rx_hdr, pkt_hdr;
750 uint32_t *hdr_p; 750 uint32_t *hdr_p;
751 uint16_t hdr_offset, pkt_count; 751 uint16_t hdr_offset, pkt_count;
752 size_t pkt_len; 752 size_t pkt_len;
753 size_t temp; 753 size_t temp;
754 754
755 if (total_len < sizeof(pkt_hdr)) { 755 if (total_len < sizeof(pkt_hdr)) {
756 aprint_error_dev(un->un_dev, "rxeof: too short transfer\n"); 756 aprint_error_dev(un->un_dev, "rxeof: too short transfer\n");
757 if_statinc(ifp, if_ierrors); 757 if_statinc(ifp, if_ierrors);
758 return; 758 return;
759 } 759 }
760 760
761 /* 761 /*
762 * buffer map 762 * buffer map
763 * [packet #0]...[packet #n][pkt hdr#0]..[pkt hdr#n][recv_hdr] 763 * [packet #0]...[packet #n][pkt hdr#0]..[pkt hdr#n][recv_hdr]
764 * each packet has 0xeeee as psuedo header.. 764 * each packet has 0xeeee as psuedo header..
765 */ 765 */
766 hdr_p = (uint32_t *)(buf + total_len - sizeof(uint32_t)); 766 hdr_p = (uint32_t *)(buf + total_len - sizeof(uint32_t));
767 rx_hdr = le32toh(*hdr_p); 767 rx_hdr = le32toh(*hdr_p);
768 hdr_offset = (uint16_t)(rx_hdr >> 16); 768 hdr_offset = (uint16_t)(rx_hdr >> 16);
769 pkt_count = (uint16_t)(rx_hdr & 0xffff); 769 pkt_count = (uint16_t)(rx_hdr & 0xffff);
770 770
771 /* sanity check */ 771 /* sanity check */
772 if (hdr_offset > total_len) { 772 if (hdr_offset > total_len) {
773 aprint_error_dev(un->un_dev, 773 aprint_error_dev(un->un_dev,
774 "rxeof: invalid hdr offset (%u > %u)\n", 774 "rxeof: invalid hdr offset (%u > %u)\n",
775 hdr_offset, total_len); 775 hdr_offset, total_len);
776 if_statinc(ifp, if_ierrors); 776 if_statinc(ifp, if_ierrors);
777 usbd_delay_ms(un->un_udev, 100); 777 usbd_delay_ms(un->un_udev, 100);
778 return; 778 return;
779 } 779 }
780 780
781 /* point first packet header */ 781 /* point first packet header */
782 hdr_p = (uint32_t *)(buf + hdr_offset); 782 hdr_p = (uint32_t *)(buf + hdr_offset);
783 783
784 /* 784 /*
785 * ax88179 will pack multiple ip packet to a USB transaction. 785 * ax88179 will pack multiple ip packet to a USB transaction.
786 * process all of packets in the buffer 786 * process all of packets in the buffer
787 */ 787 */
788 788
789#if 1 /* XXX: paranoiac check. need to remove later */ 789#if 1 /* XXX: paranoiac check. need to remove later */
790#define AXEN_MAX_PACKED_PACKET 200 790#define AXEN_MAX_PACKED_PACKET 200
791 if (pkt_count > AXEN_MAX_PACKED_PACKET) { 791 if (pkt_count > AXEN_MAX_PACKED_PACKET) {
792 DPRINTF(("%s: Too many packets (%d) in a transaction, discard.\n", 792 DPRINTF(("%s: Too many packets (%d) in a transaction, discard.\n",
793 device_xname(un->un_dev), pkt_count)); 793 device_xname(un->un_dev), pkt_count));
794 return; 794 return;
795 } 795 }
796#endif 796#endif
797 797
798 if (pkt_count) 798 if (pkt_count)
799 rnd_add_uint32(usbnet_rndsrc(un), pkt_count); 799 rnd_add_uint32(usbnet_rndsrc(un), pkt_count);
800 800
801 do { 801 do {
802 if ((buf[0] != 0xee) || (buf[1] != 0xee)) { 802 if ((buf[0] != 0xee) || (buf[1] != 0xee)) {
803 aprint_error_dev(un->un_dev, 803 aprint_error_dev(un->un_dev,
804 "invalid buffer(pkt#%d), continue\n", pkt_count); 804 "invalid buffer(pkt#%d), continue\n", pkt_count);
805 if_statadd(ifp, if_ierrors, pkt_count); 805 if_statadd(ifp, if_ierrors, pkt_count);
806 return; 806 return;
807 } 807 }
808 808
809 pkt_hdr = le32toh(*hdr_p); 809 pkt_hdr = le32toh(*hdr_p);
810 pkt_len = (pkt_hdr >> 16) & 0x1fff; 810 pkt_len = (pkt_hdr >> 16) & 0x1fff;
811 DPRINTFN(10, 811 DPRINTFN(10,
812 ("%s: rxeof: packet#%d, pkt_hdr 0x%08x, pkt_len %zu\n", 812 ("%s: rxeof: packet#%d, pkt_hdr 0x%08x, pkt_len %zu\n",
813 device_xname(un->un_dev), pkt_count, pkt_hdr, pkt_len)); 813 device_xname(un->un_dev), pkt_count, pkt_hdr, pkt_len));
814 814
815 if (pkt_hdr & (AXEN_RXHDR_CRC_ERR | AXEN_RXHDR_DROP_ERR)) { 815 if (pkt_hdr & (AXEN_RXHDR_CRC_ERR | AXEN_RXHDR_DROP_ERR)) {
816 if_statinc(ifp, if_ierrors); 816 if_statinc(ifp, if_ierrors);
817 /* move to next pkt header */ 817 /* move to next pkt header */
818 DPRINTF(("%s: %s err (pkt#%d)\n", 818 DPRINTF(("%s: %s err (pkt#%d)\n",
819 device_xname(un->un_dev), 819 device_xname(un->un_dev),
820 (pkt_hdr & AXEN_RXHDR_CRC_ERR) ? "crc" : "drop", 820 (pkt_hdr & AXEN_RXHDR_CRC_ERR) ? "crc" : "drop",
821 pkt_count)); 821 pkt_count));
822 goto nextpkt; 822 goto nextpkt;
823 } 823 }
824 824
825 usbnet_enqueue(un, buf + ETHER_ALIGN, pkt_len - 6, 825 usbnet_enqueue(un, buf + ETHER_ALIGN, pkt_len - 6,
826 axen_csum_flags_rx(ifp, pkt_hdr), 0, 0); 826 axen_csum_flags_rx(ifp, pkt_hdr), 0, 0);
827 827
828nextpkt: 828nextpkt:
829 /* 829 /*
830 * prepare next packet 830 * prepare next packet
831 * as each packet will be aligned 8byte boundary, 831 * as each packet will be aligned 8byte boundary,
832 * need to fix up the start point of the buffer. 832 * need to fix up the start point of the buffer.
833 */ 833 */
834 temp = ((pkt_len + 7) & 0xfff8); 834 temp = ((pkt_len + 7) & 0xfff8);
835 buf = buf + temp; 835 buf = buf + temp;
836 hdr_p++; 836 hdr_p++;
837 pkt_count--; 837 pkt_count--;
838 } while (pkt_count > 0); 838 } while (pkt_count > 0);
839} 839}
840 840
841static unsigned 841static unsigned
842axen_uno_tx_prepare(struct usbnet *un, struct mbuf *m, struct usbnet_chain *c) 842axen_uno_tx_prepare(struct usbnet *un, struct mbuf *m, struct usbnet_chain *c)
843{ 843{
844 struct axen_sframe_hdr hdr; 844 struct axen_sframe_hdr hdr;
845 u_int length, boundary; 845 u_int length, boundary;
846 846
847 if ((unsigned)m->m_pkthdr.len > un->un_tx_bufsz - sizeof(hdr)) 847 if ((unsigned)m->m_pkthdr.len > un->un_tx_bufsz - sizeof(hdr))
848 return 0; 848 return 0;
849 length = m->m_pkthdr.len + sizeof(hdr); 849 length = m->m_pkthdr.len + sizeof(hdr);
850 850
851 /* XXX Is this needed? wMaxPacketSize? */ 851 /* XXX Is this needed? wMaxPacketSize? */
852 switch (un->un_udev->ud_speed) { 852 switch (un->un_udev->ud_speed) {
853 case USB_SPEED_SUPER: 853 case USB_SPEED_SUPER:
854 boundary = 4096; 854 boundary = 4096;
855 break; 855 break;
856 case USB_SPEED_HIGH: 856 case USB_SPEED_HIGH:
857 boundary = 512; 857 boundary = 512;
858 break; 858 break;
859 default: 859 default:
860 boundary = 64; 860 boundary = 64;
861 break; 861 break;
862 } 862 }
863 863
864 hdr.plen = htole32(m->m_pkthdr.len); 864 hdr.plen = htole32(m->m_pkthdr.len);
865 865
866 hdr.gso = (m->m_pkthdr.csum_flags & M_CSUM_TSOv4) ? 866 hdr.gso = (m->m_pkthdr.csum_flags & M_CSUM_TSOv4) ?
867 m->m_pkthdr.segsz : 0; 867 m->m_pkthdr.segsz : 0;
868 if ((length % boundary) == 0) { 868 if ((length % boundary) == 0) {
869 DPRINTF(("%s: boundary hit\n", device_xname(un->un_dev))); 869 DPRINTF(("%s: boundary hit\n", device_xname(un->un_dev)));
870 hdr.gso |= 0x80008000; /* XXX enable padding */ 870 hdr.gso |= 0x80008000; /* XXX enable padding */
871 } 871 }
872 hdr.gso = htole32(hdr.gso); 872 hdr.gso = htole32(hdr.gso);
873 873
874 memcpy(c->unc_buf, &hdr, sizeof(hdr)); 874 memcpy(c->unc_buf, &hdr, sizeof(hdr));
875 m_copydata(m, 0, m->m_pkthdr.len, c->unc_buf + sizeof(hdr)); 875 m_copydata(m, 0, m->m_pkthdr.len, c->unc_buf + sizeof(hdr));
876 876
877 return length; 877 return length;
878} 878}
879 879
880static int 880static int
881axen_uno_init(struct ifnet *ifp) 881axen_uno_init(struct ifnet *ifp)
882{ 882{
883 struct usbnet * const un = ifp->if_softc; 883 struct usbnet * const un = ifp->if_softc;
884 uint16_t rxmode; 884 uint16_t rxmode;
885 uint16_t wval; 885 uint16_t wval;
886 uint8_t bval; 886 uint8_t bval;
887 887
888 usbnet_isowned_core(un); 888 usbnet_isowned_core(un);
889 889
890 if (usbnet_isdying(un)) 890 if (usbnet_isdying(un))
891 return EIO; 891 return EIO;
892 892
893 /* Cancel pending I/O */ 893 /* Cancel pending I/O */
894 usbnet_stop(un, ifp, 1); 894 usbnet_stop(un, ifp, 1);
895 895
896 /* Reset the ethernet interface. */ 896 /* Reset the ethernet interface. */
897 axen_reset(un); 897 axen_reset(un);
898 898
899 /* XXX: ? */ 899 /* XXX: ? */
900 bval = 0x01; 900 bval = 0x01;
901 axen_cmd(un, AXEN_CMD_MAC_WRITE, 1, AXEN_UNK_28, &bval); 901 axen_cmd(un, AXEN_CMD_MAC_WRITE, 1, AXEN_UNK_28, &bval);
902 902
903 /* Configure offloading engine. */ 903 /* Configure offloading engine. */
904 axen_setoe_locked(un); 904 axen_setoe_locked(un);
905 905
906 /* Enable receiver, set RX mode */ 906 /* Enable receiver, set RX mode */
907 axen_cmd(un, AXEN_CMD_MAC_READ2, 2, AXEN_MAC_RXCTL, &wval); 907 axen_cmd(un, AXEN_CMD_MAC_READ2, 2, AXEN_MAC_RXCTL, &wval);
908 rxmode = le16toh(wval); 908 rxmode = le16toh(wval);
909 rxmode |= AXEN_RXCTL_START; 909 rxmode |= AXEN_RXCTL_START;
910 wval = htole16(rxmode); 910 wval = htole16(rxmode);
911 axen_cmd(un, AXEN_CMD_MAC_WRITE2, 2, AXEN_MAC_RXCTL, &wval); 911 axen_cmd(un, AXEN_CMD_MAC_WRITE2, 2, AXEN_MAC_RXCTL, &wval);
912 912
913 return usbnet_init_rx_tx(un); 913 return usbnet_init_rx_tx(un);
914} 914}
915 915
916static void 916static void
917axen_uno_stop(struct ifnet *ifp, int disable) 917axen_uno_stop(struct ifnet *ifp, int disable)
918{ 918{
919 struct usbnet * const un = ifp->if_softc; 919 struct usbnet * const un = ifp->if_softc;
920 uint16_t rxmode, wval; 920 uint16_t rxmode, wval;
921 921
922 axen_reset(un); 922 axen_reset(un);
923 923
924 /* Disable receiver, set RX mode */ 924 /* Disable receiver, set RX mode */
925 axen_cmd(un, AXEN_CMD_MAC_READ2, 2, AXEN_MAC_RXCTL, &wval); 925 axen_cmd(un, AXEN_CMD_MAC_READ2, 2, AXEN_MAC_RXCTL, &wval);
926 rxmode = le16toh(wval); 926 rxmode = le16toh(wval);
927 rxmode &= ~AXEN_RXCTL_START; 927 rxmode &= ~AXEN_RXCTL_START;
928 wval = htole16(rxmode); 928 wval = htole16(rxmode);
929 axen_cmd(un, AXEN_CMD_MAC_WRITE2, 2, AXEN_MAC_RXCTL, &wval); 929 axen_cmd(un, AXEN_CMD_MAC_WRITE2, 2, AXEN_MAC_RXCTL, &wval);
930} 930}
931 931
932#ifdef _MODULE 932#ifdef _MODULE
933#include "ioconf.c" 933#include "ioconf.c"
934#endif 934#endif
935 935
936USBNET_MODULE(axen) 936USBNET_MODULE(axen)