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