Annotation of src/sys/dev/usb/if_axen.c, Revision 1.2.2.1
1.2.2.1 ! tls 1: /* $NetBSD: if_axen.c,v 1.2 2013/10/29 16:10:49 joerg Exp $ */
1.1 nonaka 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@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>
1.2.2.1 ! tls 26: __KERNEL_RCSID(0, "$NetBSD: if_axen.c,v 1.2 2013/10/29 16:10:49 joerg Exp $");
1.1 nonaka 27:
28: #ifdef _KERNEL_OPT
29: #include "opt_inet.h"
30: #endif
31:
32: #include <sys/param.h>
33: #include <sys/bus.h>
34: #include <sys/device.h>
35: #include <sys/kernel.h>
36: #include <sys/mbuf.h>
37: #include <sys/module.h>
38: #include <sys/rwlock.h>
39: #include <sys/socket.h>
40: #include <sys/sockio.h>
41: #include <sys/systm.h>
42:
43: #include <sys/rnd.h>
44:
45: #include <net/if.h>
46: #include <net/if_dl.h>
47: #include <net/if_ether.h>
48: #include <net/if_media.h>
49:
50: #include <net/bpf.h>
51:
52: #include <dev/mii/mii.h>
53: #include <dev/mii/miivar.h>
54:
55: #include <dev/usb/usb.h>
56: #include <dev/usb/usbdi.h>
57: #include <dev/usb/usbdi_util.h>
58: #include <dev/usb/usbdivar.h>
59: #include <dev/usb/usbdevs.h>
60:
61: #include <dev/usb/if_axenreg.h>
62:
63: #ifdef AXEN_DEBUG
64: #define DPRINTF(x) do { if (axendebug) printf x; } while (/*CONSTCOND*/0)
65: #define DPRINTFN(n,x) do { if (axendebug >= (n)) printf x; } while (/*CONSTCOND*/0)
66: int axendebug = 0;
67: #else
68: #define DPRINTF(x)
69: #define DPRINTFN(n,x)
70: #endif
71:
72: #define AXEN_TOE /* enable checksum offload function */
73:
74: /*
75: * Various supported device vendors/products.
76: */
77: static const struct axen_type axen_devs[] = {
78: #if 0 /* not tested */
79: { { USB_VENDOR_ASIX, USB_PRODUCT_ASIX_AX88178A}, AX178A },
80: #endif
81: { { USB_VENDOR_ASIX, USB_PRODUCT_ASIX_AX88179}, AX179 }
82: };
83:
84: #define axen_lookup(v, p) ((const struct axen_type *)usb_lookup(axen_devs, v, p))
85:
86: static int axen_match(device_t, cfdata_t, void *);
87: static void axen_attach(device_t, device_t, void *);
88: static int axen_detach(device_t, int);
89: static int axen_activate(device_t, devact_t);
90:
91: CFATTACH_DECL_NEW(axen, sizeof(struct axen_softc),
92: axen_match, axen_attach, axen_detach, axen_activate);
93:
94: static int axen_tx_list_init(struct axen_softc *);
95: static int axen_rx_list_init(struct axen_softc *);
96: static struct mbuf *axen_newbuf(void);
97: static int axen_encap(struct axen_softc *, struct mbuf *, int);
98: static void axen_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
99: static void axen_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
100: static void axen_tick(void *);
101: static void axen_tick_task(void *);
102: static void axen_start(struct ifnet *);
103: static int axen_ioctl(struct ifnet *, u_long, void *);
104: static int axen_init(struct ifnet *);
105: static void axen_stop(struct ifnet *, int);
106: static void axen_watchdog(struct ifnet *);
107: static int axen_miibus_readreg(device_t, int, int);
108: static void axen_miibus_writereg(device_t, int, int, int);
109: static void axen_miibus_statchg(struct ifnet *);
110: static int axen_cmd(struct axen_softc *, int, int, int, void *);
111: static int axen_ifmedia_upd(struct ifnet *);
112: static void axen_ifmedia_sts(struct ifnet *, struct ifmediareq *);
113: static void axen_reset(struct axen_softc *sc);
114: #if 0
115: static int axen_ax88179_eeprom(struct axen_softc *, void *);
116: #endif
117:
118: static void axen_iff(struct axen_softc *);
119: static void axen_lock_mii(struct axen_softc *sc);
120: static void axen_unlock_mii(struct axen_softc *sc);
121:
122: static void axen_ax88179_init(struct axen_softc *);
123:
124: /* Get exclusive access to the MII registers */
125: static void
126: axen_lock_mii(struct axen_softc *sc)
127: {
128:
129: sc->axen_refcnt++;
130: rw_enter(&sc->axen_mii_lock, RW_WRITER);
131: }
132:
133: static void
134: axen_unlock_mii(struct axen_softc *sc)
135: {
136:
137: rw_exit(&sc->axen_mii_lock);
138: if (--sc->axen_refcnt < 0)
139: usb_detach_wakeupold(sc->axen_dev);
140: }
141:
142: static int
143: axen_cmd(struct axen_softc *sc, int cmd, int index, int val, void *buf)
144: {
145: usb_device_request_t req;
146: usbd_status err;
147:
148: KASSERT(rw_lock_held(&sc->axen_mii_lock));
149:
150: if (sc->axen_dying)
151: return 0;
152:
153: if (AXEN_CMD_DIR(cmd))
154: req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
155: else
156: req.bmRequestType = UT_READ_VENDOR_DEVICE;
157: req.bRequest = AXEN_CMD_CMD(cmd);
158: USETW(req.wValue, val);
159: USETW(req.wIndex, index);
160: USETW(req.wLength, AXEN_CMD_LEN(cmd));
161:
162: err = usbd_do_request(sc->axen_udev, &req, buf);
163: DPRINTFN(5, ("axen_cmd: cmd 0x%04x val 0x%04x len %d\n",
164: cmd, val, AXEN_CMD_LEN(cmd)));
165:
166: if (err) {
167: DPRINTF(("axen_cmd err: cmd: %d, error: %d\n", cmd, err));
168: return -1;
169: }
170:
171: return 0;
172: }
173:
174: static int
175: axen_miibus_readreg(device_t dev, int phy, int reg)
176: {
177: struct axen_softc *sc = device_private(dev);
178: usbd_status err;
179: uint16_t val;
180: int ival;
181:
182: if (sc->axen_dying) {
183: DPRINTF(("axen: dying\n"));
184: return 0;
185: }
186:
187: if (sc->axen_phyno != phy)
188: return 0;
189:
190: axen_lock_mii(sc);
191: err = axen_cmd(sc, AXEN_CMD_MII_READ_REG, reg, phy, &val);
192: axen_unlock_mii(sc);
193:
194: if (err) {
195: aprint_error_dev(sc->axen_dev, "read PHY failed\n");
196: return -1;
197: }
198:
199: ival = le16toh(val);
200: DPRINTFN(2,("axen_miibus_readreg: phy 0x%x reg 0x%x val 0x%x\n",
201: phy, reg, ival));
202:
203: if (reg == MII_BMSR) {
204: ival &= ~BMSR_EXTCAP;
205: }
206:
207: return ival;
208: }
209:
210: static void
211: axen_miibus_writereg(device_t dev, int phy, int reg, int val)
212: {
213: struct axen_softc *sc = device_private(dev);
214: usbd_status err;
215: uint16_t uval;
216:
217: if (sc->axen_dying)
218: return;
219:
220: if (sc->axen_phyno != phy)
221: return;
222:
223: uval = htole16(val);
224: axen_lock_mii(sc);
225: err = axen_cmd(sc, AXEN_CMD_MII_WRITE_REG, reg, phy, &uval);
226: axen_unlock_mii(sc);
227: DPRINTFN(2, ("axen_miibus_writereg: phy 0x%x reg 0x%x val 0x%0x\n",
228: phy, reg, val));
229:
230: if (err) {
231: aprint_error_dev(sc->axen_dev, "write PHY failed\n");
232: return;
233: }
234: }
235:
236: static void
237: axen_miibus_statchg(struct ifnet *ifp)
238: {
239: struct axen_softc *sc = ifp->if_softc;
240: struct mii_data *mii = GET_MII(sc);
241: int err;
242: uint16_t val;
243: uint16_t wval;
244:
245: sc->axen_link = 0;
246: if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) ==
247: (IFM_ACTIVE | IFM_AVALID)) {
248: switch (IFM_SUBTYPE(mii->mii_media_active)) {
249: case IFM_10_T:
250: case IFM_100_TX:
251: sc->axen_link++;
252: break;
253: case IFM_1000_T:
254: sc->axen_link++;
255: break;
256: default:
257: break;
258: }
259: }
260:
261: /* Lost link, do nothing. */
262: if (sc->axen_link == 0)
263: return;
264:
265: val = 0;
266: if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX)
267: val |= AXEN_MEDIUM_FDX;
268:
269: val |= (AXEN_MEDIUM_RECV_EN | AXEN_MEDIUM_ALWAYS_ONE);
270: val |= (AXEN_MEDIUM_RXFLOW_CTRL_EN | AXEN_MEDIUM_TXFLOW_CTRL_EN);
271:
272: switch (IFM_SUBTYPE(mii->mii_media_active)) {
273: case IFM_1000_T:
274: val |= AXEN_MEDIUM_GIGA | AXEN_MEDIUM_EN_125MHZ;
275: break;
276: case IFM_100_TX:
277: val |= AXEN_MEDIUM_PS;
278: break;
279: case IFM_10_T:
280: /* doesn't need to be handled */
281: break;
282: }
283:
284: DPRINTF(("axen_miibus_statchg: val=0x%x\n", val));
285: wval = htole16(val);
286: axen_lock_mii(sc);
287: err = axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MEDIUM_STATUS, &wval);
288: axen_unlock_mii(sc);
289: if (err) {
290: aprint_error_dev(sc->axen_dev, "media change failed\n");
291: return;
292: }
293: }
294:
295: /*
296: * Set media options.
297: */
298: static int
299: axen_ifmedia_upd(struct ifnet *ifp)
300: {
301: struct axen_softc *sc = ifp->if_softc;
302: struct mii_data *mii = GET_MII(sc);
303: int rc;
304:
305: sc->axen_link = 0;
306:
307: if (mii->mii_instance) {
308: struct mii_softc *miisc;
309:
310: LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
311: mii_phy_reset(miisc);
312: }
313:
314: if ((rc = mii_mediachg(mii)) == ENXIO)
315: return 0;
316: return rc;
317: }
318:
319: /*
320: * Report current media status.
321: */
322: static void
323: axen_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
324: {
325: struct axen_softc *sc = ifp->if_softc;
326: struct mii_data *mii = GET_MII(sc);
327:
328: mii_pollstat(mii);
329: ifmr->ifm_active = mii->mii_media_active;
330: ifmr->ifm_status = mii->mii_media_status;
331: }
332:
333: static void
334: axen_iff(struct axen_softc *sc)
335: {
336: struct ifnet *ifp = GET_IFP(sc);
337: struct ethercom *ec = &sc->axen_ec;
338: struct ether_multi *enm;
339: struct ether_multistep step;
340: uint32_t h = 0;
341: uint16_t rxmode;
342: uint8_t hashtbl[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
343: uint16_t wval;
344:
345: if (sc->axen_dying)
346: return;
347:
348: rxmode = 0;
349:
350: /* Enable receiver, set RX mode */
351: axen_lock_mii(sc);
352: axen_cmd(sc, AXEN_CMD_MAC_READ2, 2, AXEN_MAC_RXCTL, &wval);
353: rxmode = le16toh(wval);
354: rxmode &= ~(AXEN_RXCTL_ACPT_ALL_MCAST | AXEN_RXCTL_ACPT_PHY_MCAST |
355: AXEN_RXCTL_PROMISC);
356: ifp->if_flags &= ~IFF_ALLMULTI;
357:
358: /*
359: * Always accept broadcast frames.
360: * Always accept frames destined to our station address.
361: */
362: rxmode |= AXEN_RXCTL_ACPT_BCAST;
363:
364: if (ifp->if_flags & IFF_PROMISC || ec->ec_multicnt > 0 /* XXX */) {
365: ifp->if_flags |= IFF_ALLMULTI;
366: rxmode |= AXEN_RXCTL_ACPT_ALL_MCAST | AXEN_RXCTL_ACPT_PHY_MCAST;
367: if (ifp->if_flags & IFF_PROMISC)
368: rxmode |= AXEN_RXCTL_PROMISC;
369: } else {
370: rxmode |= AXEN_RXCTL_ACPT_ALL_MCAST | AXEN_RXCTL_ACPT_PHY_MCAST;
371:
372: /* now program new ones */
373: ETHER_FIRST_MULTI(step, ec, enm);
374: while (enm != NULL) {
375: h = ether_crc32_be(enm->enm_addrlo,
376: ETHER_ADDR_LEN) >> 26;
377: hashtbl[h / 8] |= 1 << (h % 8);
378: ETHER_NEXT_MULTI(step, enm);
379: }
380: }
381:
382: axen_cmd(sc, AXEN_CMD_MAC_WRITE_FILTER, 8, AXEN_FILTER_MULTI, hashtbl);
383: wval = htole16(rxmode);
384: axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MAC_RXCTL, &wval);
385: axen_unlock_mii(sc);
386: }
387:
388: static void
389: axen_reset(struct axen_softc *sc)
390: {
391:
392: if (sc->axen_dying)
393: return;
394: /* XXX What to reset? */
395:
396: /* Wait a little while for the chip to get its brains in order. */
397: DELAY(1000);
398: }
399:
400: #if 0 /* not used */
401: #define AXEN_GPIO_WRITE(x,y) do { \
402: axen_cmd(sc, AXEN_CMD_WRITE_GPIO, 0, (x), NULL); \
403: usbd_delay_ms(sc->axen_udev, (y)); \
404: } while (/*CONSTCOND*/0)
405:
406: static int
407: axen_ax88179_eeprom(struct axen_softc *sc, void *addr)
408: {
409: int i, retry;
410: uint8_t eeprom[20];
411: uint16_t csum;
412: uint16_t buf;
413:
414: for (i = 0; i < 6; i++) {
415: /* set eeprom address */
416: buf = htole16(i);
417: axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_MAC_EEPROM_ADDR, &buf);
418:
419: /* set eeprom command */
420: buf = htole16(AXEN_EEPROM_READ);
421: axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_MAC_EEPROM_CMD, &buf);
422:
423: /* check the value is ready */
424: retry = 3;
425: do {
426: buf = htole16(AXEN_EEPROM_READ);
427: usbd_delay_ms(sc->axen_udev, 10);
428: axen_cmd(sc, AXEN_CMD_MAC_READ, 1, AXEN_MAC_EEPROM_CMD,
429: &buf);
430: retry--;
431: if (retry < 0)
432: return EINVAL;
433: } while ((le16toh(buf) & 0xff) & AXEN_EEPROM_BUSY);
434:
435: /* read data */
436: axen_cmd(sc, AXEN_CMD_MAC_READ2, 2, AXEN_EEPROM_READ,
437: &eeprom[i * 2]);
438:
439: /* sanity check */
440: if ((i == 0) && (eeprom[0] == 0xff))
441: return EINVAL;
442: }
443:
444: /* check checksum */
445: csum = eeprom[6] + eeprom[7] + eeprom[8] + eeprom[9];
446: csum = (csum >> 8) + (csum & 0xff) + eeprom[10];
447: if (csum != 0xff) {
448: printf("eeprom checksum mismatchi(0x%02x)\n", csum);
449: return EINVAL;
450: }
451:
452: memcpy(addr, eeprom, ETHER_ADDR_LEN);
453: return 0;
454: }
455: #endif
456:
457: static void
458: axen_ax88179_init(struct axen_softc *sc)
459: {
460: struct axen_qctrl qctrl;
461: uint16_t ctl, temp;
462: uint16_t wval;
463: uint8_t val;
464:
465: axen_lock_mii(sc);
466:
467: /* XXX: ? */
468: axen_cmd(sc, AXEN_CMD_MAC_READ, 1, AXEN_UNK_05, &val);
469: DPRINTFN(5, ("AXEN_CMD_MAC_READ(0x05): 0x%02x\n", val));
470:
471: /* check AX88179 version, UA1 / UA2 */
472: axen_cmd(sc, AXEN_CMD_MAC_READ, 1, AXEN_GENERAL_STATUS, &val);
473: /* UA1 */
474: if (!(val & AXEN_GENERAL_STATUS_MASK)) {
475: sc->axen_rev = AXEN_REV_UA1;
476: DPRINTF(("AX88179 ver. UA1\n"));
477: } else {
478: sc->axen_rev = AXEN_REV_UA2;
479: DPRINTF(("AX88179 ver. UA2\n"));
480: }
481:
482: /* power up ethernet PHY */
483: wval = htole16(0);
484: axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_PHYPWR_RSTCTL, &wval);
485:
486: wval = htole16(AXEN_PHYPWR_RSTCTL_IPRL);
487: axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_PHYPWR_RSTCTL, &wval);
488: usbd_delay_ms(sc->axen_udev, 200);
489:
490: /* set clock mode */
491: val = AXEN_PHYCLK_ACS | AXEN_PHYCLK_BCS;
492: axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_PHYCLK, &val);
493: usbd_delay_ms(sc->axen_udev, 100);
494:
495: /* set monitor mode (disable) */
496: val = AXEN_MONITOR_NONE;
497: axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_MONITOR_MODE, &val);
498:
499: /* enable auto detach */
500: axen_cmd(sc, AXEN_CMD_EEPROM_READ, 2, AXEN_EEPROM_STAT, &wval);
501: temp = le16toh(wval);
502: DPRINTFN(2,("EEPROM0x43 = 0x%04x\n", temp));
503: if (!(temp == 0xffff) && !(temp & 0x0100)) {
504: /* Enable auto detach bit */
505: val = 0;
506: axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_PHYCLK, &val);
507: val = AXEN_PHYCLK_ULR;
508: axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_PHYCLK, &val);
509: usbd_delay_ms(sc->axen_udev, 100);
510:
511: axen_cmd(sc, AXEN_CMD_MAC_READ2, 2, AXEN_PHYPWR_RSTCTL, &wval);
512: ctl = le16toh(wval);
513: ctl |= AXEN_PHYPWR_RSTCTL_AUTODETACH;
514: wval = htole16(ctl);
515: axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_PHYPWR_RSTCTL, &wval);
516: usbd_delay_ms(sc->axen_udev, 200);
517: aprint_error_dev(sc->axen_dev, "enable auto detach (0x%04x)\n",
518: ctl);
519: }
520:
521: /* bulkin queue setting */
522: axen_cmd(sc, AXEN_CMD_MAC_READ, 1, AXEN_USB_UPLINK, &val);
523: switch (val) {
524: case AXEN_USB_FS:
525: DPRINTF(("uplink: USB1.1\n"));
526: qctrl.ctrl = 0x07;
527: qctrl.timer_low = 0xcc;
528: qctrl.timer_high = 0x4c;
529: qctrl.bufsize = AXEN_BUFSZ_LS - 1;
530: qctrl.ifg = 0x08;
531: break;
532: case AXEN_USB_HS:
533: DPRINTF(("uplink: USB2.0\n"));
534: qctrl.ctrl = 0x07;
535: qctrl.timer_low = 0x02;
536: qctrl.timer_high = 0xa0;
537: qctrl.bufsize = AXEN_BUFSZ_HS - 1;
538: qctrl.ifg = 0xff;
539: break;
540: case AXEN_USB_SS:
541: DPRINTF(("uplink: USB3.0\n"));
542: qctrl.ctrl = 0x07;
543: qctrl.timer_low = 0x4f;
544: qctrl.timer_high = 0x00;
545: qctrl.bufsize = AXEN_BUFSZ_SS - 1;
546: qctrl.ifg = 0xff;
547: break;
548: default:
549: aprint_error_dev(sc->axen_dev, "unknown uplink bus:0x%02x\n",
550: val);
551: axen_unlock_mii(sc);
552: return;
553: }
554: axen_cmd(sc, AXEN_CMD_MAC_SET_RXSR, 5, AXEN_RX_BULKIN_QCTRL, &qctrl);
555:
556: /*
557: * set buffer high/low watermark to pause/resume.
558: * write 2byte will set high/log simultaneous with AXEN_PAUSE_HIGH.
559: * XXX: what is the best value? OSX driver uses 0x3c-0x4c as LOW-HIGH
560: * watermark parameters.
561: */
562: val = 0x34;
563: axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_PAUSE_LOW_WATERMARK, &val);
564: val = 0x52;
565: axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_PAUSE_HIGH_WATERMARK, &val);
566:
567: /* Set RX/TX configuration. */
568: /* Offloadng enable */
569: #ifdef AXEN_TOE
570: val = AXEN_RXCOE_IPv4 | AXEN_RXCOE_TCPv4 | AXEN_RXCOE_UDPv4 |
571: AXEN_RXCOE_TCPv6 | AXEN_RXCOE_UDPv6;
572: #else
573: val = AXEN_RXCOE_OFF;
574: #endif
575: axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_RX_COE, &val);
576:
577: #ifdef AXEN_TOE
578: val = AXEN_TXCOE_IPv4 | AXEN_TXCOE_TCPv4 | AXEN_TXCOE_UDPv4 |
579: AXEN_TXCOE_TCPv6 | AXEN_TXCOE_UDPv6;
580: #else
581: val = AXEN_TXCOE_OFF;
582: #endif
583: axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_TX_COE, &val);
584:
585: /* Set RX control register */
586: ctl = AXEN_RXCTL_IPE | AXEN_RXCTL_DROPCRCERR | AXEN_RXCTL_AUTOB;
587: ctl |= AXEN_RXCTL_ACPT_PHY_MCAST | AXEN_RXCTL_ACPT_ALL_MCAST;
588: ctl |= AXEN_RXCTL_START;
589: wval = htole16(ctl);
590: axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MAC_RXCTL, &wval);
591:
592: /* set monitor mode (enable) */
593: val = AXEN_MONITOR_PMETYPE | AXEN_MONITOR_PMEPOL | AXEN_MONITOR_RWMP;
594: axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_MONITOR_MODE, &val);
595: axen_cmd(sc, AXEN_CMD_MAC_READ, 1, AXEN_MONITOR_MODE, &val);
596: DPRINTF(("axen: Monitor mode = 0x%02x\n", val));
597:
598: /* set medium type */
599: ctl = AXEN_MEDIUM_GIGA | AXEN_MEDIUM_FDX | AXEN_MEDIUM_ALWAYS_ONE |
600: AXEN_MEDIUM_RXFLOW_CTRL_EN | AXEN_MEDIUM_TXFLOW_CTRL_EN;
601: ctl |= AXEN_MEDIUM_RECV_EN;
602: wval = htole16(ctl);
603: DPRINTF(("axen: set to medium mode: 0x%04x\n", ctl));
604: axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MEDIUM_STATUS, &wval);
605: usbd_delay_ms(sc->axen_udev, 100);
606:
607: axen_cmd(sc, AXEN_CMD_MAC_READ2, 2, AXEN_MEDIUM_STATUS, &wval);
608: DPRINTF(("axen: current medium mode: 0x%04x\n", le16toh(wval)));
609:
610: axen_unlock_mii(sc);
611:
612: #if 0 /* XXX: TBD.... */
613: #define GMII_LED_ACTIVE 0x1a
614: #define GMII_PHY_PAGE_SEL 0x1e
615: #define GMII_PHY_PAGE_SEL 0x1f
616: #define GMII_PAGE_EXT 0x0007
617: axen_miibus_writereg(&sc->axen_dev, sc->axen_phyno, GMII_PHY_PAGE_SEL,
618: GMII_PAGE_EXT);
619: axen_miibus_writereg(&sc->axen_dev, sc->axen_phyno, GMII_PHY_PAGE,
620: 0x002c);
621: #endif
622:
623: #if 1 /* XXX: phy hack ? */
624: axen_miibus_writereg(sc->axen_dev, sc->axen_phyno, 0x1F, 0x0005);
625: axen_miibus_writereg(sc->axen_dev, sc->axen_phyno, 0x0C, 0x0000);
626: val = axen_miibus_readreg(sc->axen_dev, sc->axen_phyno, 0x0001);
627: axen_miibus_writereg(sc->axen_dev, sc->axen_phyno, 0x01,
628: val | 0x0080);
629: axen_miibus_writereg(sc->axen_dev, sc->axen_phyno, 0x1F, 0x0000);
630: #endif
631: }
632:
633: static int
634: axen_match(device_t parent, cfdata_t match, void *aux)
635: {
636: struct usb_attach_arg *uaa = aux;
637:
638: return axen_lookup(uaa->vendor, uaa->product) != NULL ?
639: UMATCH_VENDOR_PRODUCT : UMATCH_NONE;
640: }
641:
642: static void
643: axen_attach(device_t parent, device_t self, void *aux)
644: {
645: struct axen_softc *sc = device_private(self);
646: struct usb_attach_arg *uaa = aux;
647: struct usbd_device *dev = uaa->device;
648: usbd_status err;
649: usb_interface_descriptor_t *id;
650: usb_endpoint_descriptor_t *ed;
651: struct mii_data *mii;
652: uint8_t eaddr[ETHER_ADDR_LEN];
653: char *devinfop;
654: const char *devname = device_xname(self);
655: struct ifnet *ifp;
656: int i, s;
657:
658: aprint_naive("\n");
659: aprint_normal("\n");
660:
661: sc->axen_dev = self;
662: sc->axen_udev = dev;
663:
664: devinfop = usbd_devinfo_alloc(dev, 0);
665: aprint_normal_dev(self, "%s\n", devinfop);
666: usbd_devinfo_free(devinfop);
667:
668: err = usbd_set_config_no(dev, AXEN_CONFIG_NO, 1);
669: if (err) {
670: aprint_error_dev(self, "failed to set configuration"
671: ", err=%s\n", usbd_errstr(err));
672: return;
673: }
674:
675: sc->axen_flags = axen_lookup(uaa->vendor, uaa->product)->axen_flags;
676:
677: rw_init(&sc->axen_mii_lock);
678: usb_init_task(&sc->axen_tick_task, axen_tick_task, sc, 0);
679:
680: err = usbd_device2interface_handle(dev, AXEN_IFACE_IDX,&sc->axen_iface);
681: if (err) {
682: aprint_error_dev(self, "getting interface handle failed\n");
683: return;
684: }
685:
686: sc->axen_product = uaa->product;
687: sc->axen_vendor = uaa->vendor;
688:
689: id = usbd_get_interface_descriptor(sc->axen_iface);
690:
691: /* XXX fix when USB3.0 HC is supported */
692: /* decide on what our bufsize will be */
693: sc->axen_bufsz = (sc->axen_udev->speed == USB_SPEED_HIGH) ?
694: AXEN_BUFSZ_HS * 1024 : AXEN_BUFSZ_LS * 1024;
695:
696: /* Find endpoints. */
697: for (i = 0; i < id->bNumEndpoints; i++) {
698: ed = usbd_interface2endpoint_descriptor(sc->axen_iface, i);
699: if (!ed) {
700: aprint_error_dev(self, "couldn't get ep %d\n", i);
701: return;
702: }
703: if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
704: UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
705: sc->axen_ed[AXEN_ENDPT_RX] = ed->bEndpointAddress;
706: } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
707: UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
708: sc->axen_ed[AXEN_ENDPT_TX] = ed->bEndpointAddress;
709: } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
710: UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
711: sc->axen_ed[AXEN_ENDPT_INTR] = ed->bEndpointAddress;
712: }
713: }
714:
715: s = splnet();
716:
717: sc->axen_phyno = AXEN_PHY_ID;
718: DPRINTF(("%s: phyno %d\n", device_xname(self), sc->axen_phyno));
719:
720: /*
721: * Get station address.
722: */
723: #if 0 /* read from eeprom */
724: if (axen_ax88179_eeprom(sc, &eaddr)) {
725: printf("EEPROM checksum error\n");
726: return;
727: }
728: #else /* use MAC command */
729: axen_lock_mii(sc);
730: axen_cmd(sc, AXEN_CMD_MAC_READ_ETHER, 6, AXEN_CMD_MAC_NODE_ID, &eaddr);
731: axen_unlock_mii(sc);
732: #endif
733: axen_ax88179_init(sc);
734:
735: /*
736: * An ASIX chip was detected. Inform the world.
737: */
738: if (sc->axen_flags & AX178A)
739: aprint_normal_dev(self, "AX88178a\n");
740: else if (sc->axen_flags & AX179)
741: aprint_normal_dev(self, "AX88179\n");
742: aprint_normal_dev(self, "Ethernet address %s\n", ether_sprintf(eaddr));
743:
744: /* Initialize interface info.*/
745:
746: ifp = &sc->sc_if;
747: ifp->if_softc = sc;
748: strlcpy(ifp->if_xname, devname, IFNAMSIZ);
749: ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
750: ifp->if_ioctl = axen_ioctl;
751: ifp->if_start = axen_start;
752: ifp->if_init = axen_init;
753: ifp->if_stop = axen_stop;
754: ifp->if_watchdog = axen_watchdog;
755:
756: IFQ_SET_READY(&ifp->if_snd);
757:
758: sc->axen_ec.ec_capabilities = ETHERCAP_VLAN_MTU;
759: #ifdef AXEN_TOE
760: ifp->if_capabilities |= IFCAP_CSUM_IPv4_Rx | IFCAP_CSUM_IPv4_Tx |
761: IFCAP_CSUM_TCPv4_Rx | IFCAP_CSUM_TCPv4_Tx |
762: IFCAP_CSUM_UDPv4_Rx | IFCAP_CSUM_UDPv4_Tx |
763: IFCAP_CSUM_TCPv6_Rx | IFCAP_CSUM_TCPv6_Tx |
764: IFCAP_CSUM_UDPv6_Rx | IFCAP_CSUM_UDPv6_Tx;
765: #endif
766:
767: /* Initialize MII/media info. */
768: mii = &sc->axen_mii;
769: mii->mii_ifp = ifp;
770: mii->mii_readreg = axen_miibus_readreg;
771: mii->mii_writereg = axen_miibus_writereg;
772: mii->mii_statchg = axen_miibus_statchg;
773: mii->mii_flags = MIIF_AUTOTSLEEP;
774:
775: sc->axen_ec.ec_mii = mii;
776: ifmedia_init(&mii->mii_media, 0, axen_ifmedia_upd, axen_ifmedia_sts);
777: mii_attach(self, mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, 0);
778:
779: if (LIST_FIRST(&mii->mii_phys) == NULL) {
780: ifmedia_add(&mii->mii_media, IFM_ETHER | IFM_NONE, 0, NULL);
781: ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_NONE);
782: } else
783: ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO);
784:
785: /* Attach the interface. */
786: if_attach(ifp);
787: ether_ifattach(ifp, eaddr);
788: rnd_attach_source(&sc->rnd_source, device_xname(sc->axen_dev),
1.2.2.1 ! tls 789: RND_TYPE_NET, RND_FLAG_DEFAULT);
1.1 nonaka 790:
791: callout_init(&sc->axen_stat_ch, 0);
792: callout_setfunc(&sc->axen_stat_ch, axen_tick, sc);
793:
794: sc->axen_attached = true;
795: splx(s);
796:
797: usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->axen_udev,sc->axen_dev);
798: }
799:
800: static int
801: axen_detach(device_t self, int flags)
802: {
803: struct axen_softc *sc = device_private(self);
804: struct ifnet *ifp = GET_IFP(sc);
805: int s;
806:
807: DPRINTFN(2,("%s: %s: enter\n", device_xname(sc->axen_dev), __func__));
808:
809: /* Detached before attached finished, so just bail out. */
810: if (!sc->axen_attached)
811: return 0;
812:
813: sc->axen_dying = true;
814:
815: /*
816: * Remove any pending tasks. They cannot be executing because they run
817: * in the same thread as detach.
818: */
819: usb_rem_task(sc->axen_udev, &sc->axen_tick_task);
820:
821: s = splusb();
822:
823: if (ifp->if_flags & IFF_RUNNING)
824: axen_stop(ifp, 1);
825:
826: callout_destroy(&sc->axen_stat_ch);
827: rnd_detach_source(&sc->rnd_source);
828: mii_detach(&sc->axen_mii, MII_PHY_ANY, MII_OFFSET_ANY);
829: ifmedia_delete_instance(&sc->axen_mii.mii_media, IFM_INST_ANY);
830: ether_ifdetach(ifp);
831: if_detach(ifp);
832:
833: #ifdef DIAGNOSTIC
834: if (sc->axen_ep[AXEN_ENDPT_TX] != NULL ||
835: sc->axen_ep[AXEN_ENDPT_RX] != NULL ||
836: sc->axen_ep[AXEN_ENDPT_INTR] != NULL)
837: aprint_debug_dev(self, "detach has active endpoints\n");
838: #endif
839:
840: sc->axen_attached = false;
841:
842: if (--sc->axen_refcnt >= 0) {
843: /* Wait for processes to go away. */
844: usb_detach_waitold(sc->axen_dev);
845: }
846: splx(s);
847:
848: usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->axen_udev,sc->axen_dev);
849:
850: rw_destroy(&sc->axen_mii_lock);
851:
852: return 0;
853: }
854:
855: static int
856: axen_activate(device_t self, devact_t act)
857: {
858: struct axen_softc *sc = device_private(self);
859: struct ifnet *ifp = GET_IFP(sc);
860:
861: DPRINTFN(2,("%s: %s: enter\n", device_xname(sc->axen_dev), __func__));
862:
863: switch (act) {
864: case DVACT_DEACTIVATE:
865: if_deactivate(ifp);
866: sc->axen_dying = true;
867: return 0;
868: default:
869: return EOPNOTSUPP;
870: }
871: }
872:
873: static struct mbuf *
874: axen_newbuf(void)
875: {
876: struct mbuf *m;
877:
878: MGETHDR(m, M_DONTWAIT, MT_DATA);
879: if (m == NULL)
880: return NULL;
881:
882: MCLGET(m, M_DONTWAIT);
883: if (!(m->m_flags & M_EXT)) {
884: m_freem(m);
885: return NULL;
886: }
887:
888: m->m_len = m->m_pkthdr.len = MCLBYTES;
889: m_adj(m, ETHER_ALIGN);
890:
891: return m;
892: }
893:
894: static int
895: axen_rx_list_init(struct axen_softc *sc)
896: {
897: struct axen_cdata *cd;
898: struct axen_chain *c;
899: int i;
900:
901: DPRINTF(("%s: %s: enter\n", device_xname(sc->axen_dev), __func__));
902:
903: cd = &sc->axen_cdata;
904: for (i = 0; i < AXEN_RX_LIST_CNT; i++) {
905: c = &cd->axen_rx_chain[i];
906: c->axen_sc = sc;
907: c->axen_idx = i;
908: if (c->axen_xfer == NULL) {
909: c->axen_xfer = usbd_alloc_xfer(sc->axen_udev);
910: if (c->axen_xfer == NULL)
911: return ENOBUFS;
912: c->axen_buf = usbd_alloc_buffer(c->axen_xfer,
913: sc->axen_bufsz);
914: if (c->axen_buf == NULL) {
915: usbd_free_xfer(c->axen_xfer);
916: return ENOBUFS;
917: }
918: }
919: }
920:
921: return 0;
922: }
923:
924: static int
925: axen_tx_list_init(struct axen_softc *sc)
926: {
927: struct axen_cdata *cd;
928: struct axen_chain *c;
929: int i;
930:
931: DPRINTF(("%s: %s: enter\n", device_xname(sc->axen_dev), __func__));
932:
933: cd = &sc->axen_cdata;
934: for (i = 0; i < AXEN_TX_LIST_CNT; i++) {
935: c = &cd->axen_tx_chain[i];
936: c->axen_sc = sc;
937: c->axen_idx = i;
938: if (c->axen_xfer == NULL) {
939: c->axen_xfer = usbd_alloc_xfer(sc->axen_udev);
940: if (c->axen_xfer == NULL)
941: return ENOBUFS;
942: c->axen_buf = usbd_alloc_buffer(c->axen_xfer,
943: sc->axen_bufsz);
944: if (c->axen_buf == NULL) {
945: usbd_free_xfer(c->axen_xfer);
946: return ENOBUFS;
947: }
948: }
949: }
950:
951: return 0;
952: }
953:
954: /*
955: * A frame has been uploaded: pass the resulting mbuf chain up to
956: * the higher level protocols.
957: */
958: static void
959: axen_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
960: {
961: struct axen_chain *c = (struct axen_chain *)priv;
962: struct axen_softc *sc = c->axen_sc;
963: struct ifnet *ifp = GET_IFP(sc);
964: uint8_t *buf = c->axen_buf;
965: struct mbuf *m;
966: uint32_t total_len;
967: uint32_t rx_hdr, pkt_hdr;
968: uint32_t *hdr_p;
969: uint16_t hdr_offset, pkt_count;
970: size_t pkt_len;
971: size_t temp;
972: int s;
973:
974: DPRINTFN(10,("%s: %s: enter\n", device_xname(sc->axen_dev), __func__));
975:
976: if (sc->axen_dying)
977: return;
978:
979: if (!(ifp->if_flags & IFF_RUNNING))
980: return;
981:
982: if (status != USBD_NORMAL_COMPLETION) {
983: if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
984: return;
985: if (usbd_ratecheck(&sc->axen_rx_notice)) {
986: aprint_error_dev(sc->axen_dev, "usb errors on rx: %s\n",
987: usbd_errstr(status));
988: }
989: if (status == USBD_STALLED)
990: usbd_clear_endpoint_stall_async(sc->axen_ep[AXEN_ENDPT_RX]);
991: goto done;
992: }
993:
994: usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
995:
996: if (total_len < sizeof(pkt_hdr)) {
997: ifp->if_ierrors++;
998: goto done;
999: }
1000:
1001: /*
1002: * buffer map
1003: * [packet #0]...[packet #n][pkt hdr#0]..[pkt hdr#n][recv_hdr]
1004: * each packet has 0xeeee as psuedo header..
1005: */
1006: hdr_p = (uint32_t *)(buf + total_len - sizeof(uint32_t));
1007: rx_hdr = le32toh(*hdr_p);
1008: hdr_offset = (uint16_t)(rx_hdr >> 16);
1009: pkt_count = (uint16_t)(rx_hdr & 0xffff);
1010:
1011: if (total_len > sc->axen_bufsz) {
1012: aprint_error_dev(sc->axen_dev, "rxeof: too large transfer\n");
1013: goto done;
1014: }
1015:
1016: /* sanity check */
1.2 joerg 1017: if (hdr_offset > total_len) {
1.1 nonaka 1018: ifp->if_ierrors++;
1019: usbd_delay_ms(sc->axen_udev, 100);
1020: goto done;
1021: }
1022:
1023: /* point first packet header */
1024: hdr_p = (uint32_t *)(buf + hdr_offset);
1025:
1026: /*
1027: * ax88179 will pack multiple ip packet to a USB transaction.
1028: * process all of packets in the buffer
1029: */
1030:
1031: #if 1 /* XXX: paranoiac check. need to remove later */
1032: #define AXEN_MAX_PACKED_PACKET 200
1033: if (pkt_count > AXEN_MAX_PACKED_PACKET) {
1034: DPRINTF(("%s: Too many packets (%d) in a transaction, discard.\n",
1035: device_xname(sc->axen_dev), pkt_count));
1036: goto done;
1037: }
1038: #endif
1039:
1040: do {
1041: if ((buf[0] != 0xee) || (buf[1] != 0xee)){
1042: aprint_error_dev(sc->axen_dev,
1043: "invalid buffer(pkt#%d), continue\n", pkt_count);
1044: ifp->if_ierrors += pkt_count;
1045: goto done;
1046: }
1047:
1048: pkt_hdr = le32toh(*hdr_p);
1049: pkt_len = (pkt_hdr >> 16) & 0x1fff;
1050: DPRINTFN(10,
1051: ("%s: rxeof: packet#%d, pkt_hdr 0x%08x, pkt_len %zu\n",
1052: device_xname(sc->axen_dev), pkt_count, pkt_hdr, pkt_len));
1053:
1054: if ((pkt_hdr & AXEN_RXHDR_CRC_ERR) ||
1055: (pkt_hdr & AXEN_RXHDR_DROP_ERR)) {
1056: ifp->if_ierrors++;
1057: /* move to next pkt header */
1058: DPRINTF(("%s: crc err (pkt#%d)\n",
1059: device_xname(sc->axen_dev), pkt_count));
1060: goto nextpkt;
1061: }
1062:
1063: /* process each packet */
1064: /* allocate mbuf */
1065: m = axen_newbuf();
1066: if (m == NULL) {
1067: ifp->if_ierrors++;
1068: goto nextpkt;
1069: }
1070:
1071: /* skip pseudo header (2byte) */
1072: ifp->if_ipackets++;
1073: m->m_pkthdr.rcvif = ifp;
1074: m->m_pkthdr.len = m->m_len = pkt_len - 2;
1075:
1076: #ifdef AXEN_TOE
1077: /* cheksum err */
1078: if ((pkt_hdr & AXEN_RXHDR_L3CSUM_ERR) ||
1079: (pkt_hdr & AXEN_RXHDR_L4CSUM_ERR)) {
1080: aprint_error_dev(sc->axen_dev,
1081: "checksum err (pkt#%d)\n", pkt_count);
1082: goto nextpkt;
1083: } else {
1084: m->m_pkthdr.csum_flags |= M_CSUM_IPv4;
1085: }
1086:
1087: int l4_type = (pkt_hdr & AXEN_RXHDR_L4_TYPE_MASK) >>
1088: AXEN_RXHDR_L4_TYPE_OFFSET;
1089:
1090: if ((l4_type == AXEN_RXHDR_L4_TYPE_TCP) ||
1091: (l4_type == AXEN_RXHDR_L4_TYPE_UDP)) {
1092: m->m_pkthdr.csum_flags |= M_CSUM_TCPv4 |
1093: M_CSUM_UDPv4; /* XXX v6? */
1094: }
1095: #endif
1096:
1097: memcpy(mtod(m, char *), buf + 2, pkt_len - 2);
1098:
1099: /* push the packet up */
1100: s = splnet();
1101: bpf_mtap(ifp, m);
1102: (*(ifp)->if_input)((ifp), (m));
1103: splx(s);
1104:
1105: nextpkt:
1106: /*
1107: * prepare next packet
1108: * as each packet will be aligned 8byte boundary,
1109: * need to fix up the start point of the buffer.
1110: */
1111: temp = ((pkt_len + 7) & 0xfff8);
1112: buf = buf + temp;
1113: hdr_p++;
1114: pkt_count--;
1115: } while( pkt_count > 0);
1116:
1117: done:
1118: /* clear buffer for next transaction */
1119: memset(c->axen_buf, 0, sc->axen_bufsz);
1120:
1121: /* Setup new transfer. */
1122: usbd_setup_xfer(xfer, sc->axen_ep[AXEN_ENDPT_RX],
1123: c, c->axen_buf, sc->axen_bufsz,
1124: USBD_SHORT_XFER_OK | USBD_NO_COPY,
1125: USBD_NO_TIMEOUT, axen_rxeof);
1126: usbd_transfer(xfer);
1127:
1128: DPRINTFN(10,("%s: %s: start rx\n",device_xname(sc->axen_dev),__func__));
1129: }
1130:
1131: /*
1132: * A frame was downloaded to the chip. It's safe for us to clean up
1133: * the list buffers.
1134: */
1135: static void
1136: axen_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
1137: {
1138: struct axen_chain *c = (struct axen_chain *)priv;
1139: struct axen_softc *sc = c->axen_sc;
1140: struct ifnet *ifp = GET_IFP(sc);
1141: int s;
1142:
1143: if (sc->axen_dying)
1144: return;
1145:
1146: s = splnet();
1147:
1148: if (status != USBD_NORMAL_COMPLETION) {
1149: if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
1150: splx(s);
1151: return;
1152: }
1153: ifp->if_oerrors++;
1154: aprint_error_dev(sc->axen_dev, "usb error on tx: %s\n",
1155: usbd_errstr(status));
1156: if (status == USBD_STALLED)
1157: usbd_clear_endpoint_stall_async(sc->axen_ep[AXEN_ENDPT_TX]);
1158: splx(s);
1159: return;
1160: }
1161:
1162: ifp->if_timer = 0;
1163: ifp->if_flags &= ~IFF_OACTIVE;
1164:
1165: if (!IFQ_IS_EMPTY(&ifp->if_snd))
1166: axen_start(ifp);
1167:
1168: ifp->if_opackets++;
1169: splx(s);
1170: }
1171:
1172: static void
1173: axen_tick(void *xsc)
1174: {
1175: struct axen_softc *sc = xsc;
1176:
1177: if (sc == NULL)
1178: return;
1179:
1180: DPRINTFN(0xff,("%s: %s: enter\n", device_xname(sc->axen_dev),__func__));
1181:
1182: if (sc->axen_dying)
1183: return;
1184:
1185: /* Perform periodic stuff in process context */
1186: usb_add_task(sc->axen_udev, &sc->axen_tick_task, USB_TASKQ_DRIVER);
1187: }
1188:
1189: static void
1190: axen_tick_task(void *xsc)
1191: {
1192: int s;
1193: struct axen_softc *sc;
1194: struct ifnet *ifp;
1195: struct mii_data *mii;
1196:
1197: sc = xsc;
1198:
1199: if (sc == NULL)
1200: return;
1201:
1202: if (sc->axen_dying)
1203: return;
1204:
1205: ifp = GET_IFP(sc);
1206: mii = GET_MII(sc);
1207: if (mii == NULL)
1208: return;
1209:
1210: s = splnet();
1211:
1212: mii_tick(mii);
1213: if (sc->axen_link == 0 &&
1214: (mii->mii_media_status & IFM_ACTIVE) != 0 &&
1215: IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) {
1216: DPRINTF(("%s: %s: got link\n", device_xname(sc->axen_dev),
1217: __func__));
1218: sc->axen_link++;
1219: if (!IFQ_IS_EMPTY(&ifp->if_snd))
1220: axen_start(ifp);
1221: }
1222:
1223: callout_schedule(&sc->axen_stat_ch, hz);
1224:
1225: splx(s);
1226: }
1227:
1228: static int
1229: axen_encap(struct axen_softc *sc, struct mbuf *m, int idx)
1230: {
1231: struct ifnet *ifp = GET_IFP(sc);
1232: struct axen_chain *c;
1233: usbd_status err;
1234: struct axen_sframe_hdr hdr;
1235: int length, boundary;
1236:
1237: c = &sc->axen_cdata.axen_tx_chain[idx];
1238:
1239: boundary = (sc->axen_udev->speed == USB_SPEED_HIGH) ? 512 : 64;
1240:
1241: hdr.plen = htole32(m->m_pkthdr.len);
1242: hdr.gso = 0; /* disable segmentation offloading */
1243:
1244: memcpy(c->axen_buf, &hdr, sizeof(hdr));
1245: length = sizeof(hdr);
1246:
1247: m_copydata(m, 0, m->m_pkthdr.len, c->axen_buf + length);
1248: length += m->m_pkthdr.len;
1249:
1250: if ((length % boundary) == 0) {
1251: hdr.plen = 0x0;
1252: hdr.gso |= 0x80008000; /* enable padding */
1253: memcpy(c->axen_buf + length, &hdr, sizeof(hdr));
1254: length += sizeof(hdr);
1255: }
1256:
1257: usbd_setup_xfer(c->axen_xfer, sc->axen_ep[AXEN_ENDPT_TX],
1258: c, c->axen_buf, length, USBD_FORCE_SHORT_XFER | USBD_NO_COPY,
1259: 10000, axen_txeof);
1260:
1261: /* Transmit */
1262: err = usbd_transfer(c->axen_xfer);
1263: if (err != USBD_IN_PROGRESS) {
1264: axen_stop(ifp, 0);
1265: return EIO;
1266: }
1267:
1268: sc->axen_cdata.axen_tx_cnt++;
1269:
1270: return 0;
1271: }
1272:
1273: static void
1274: axen_start(struct ifnet *ifp)
1275: {
1276: struct axen_softc *sc;
1277: struct mbuf *m;
1278:
1279: sc = ifp->if_softc;
1280:
1281: if (sc->axen_link == 0)
1282: return;
1283:
1284: if ((ifp->if_flags & (IFF_OACTIVE|IFF_RUNNING)) != IFF_RUNNING)
1285: return;
1286:
1287: IFQ_POLL(&ifp->if_snd, m);
1288: if (m == NULL)
1289: return;
1290:
1291: if (axen_encap(sc, m, 0)) {
1292: ifp->if_flags |= IFF_OACTIVE;
1293: return;
1294: }
1295: IFQ_DEQUEUE(&ifp->if_snd, m);
1296:
1297: /*
1298: * If there's a BPF listener, bounce a copy of this frame
1299: * to him.
1300: */
1301: bpf_mtap(ifp, m);
1302: m_freem(m);
1303:
1304: ifp->if_flags |= IFF_OACTIVE;
1305:
1306: /*
1307: * Set a timeout in case the chip goes out to lunch.
1308: */
1309: ifp->if_timer = 5;
1310: }
1311:
1312: static int
1313: axen_init(struct ifnet *ifp)
1314: {
1315: struct axen_softc *sc = ifp->if_softc;
1316: struct axen_chain *c;
1317: usbd_status err;
1318: int i, s;
1319: uint16_t rxmode;
1320: uint16_t wval;
1321: uint8_t bval;
1322:
1323: s = splnet();
1324:
1325: if (ifp->if_flags & IFF_RUNNING)
1326: axen_stop(ifp, 0);
1327:
1328: /*
1329: * Cancel pending I/O and free all RX/TX buffers.
1330: */
1331: axen_reset(sc);
1332:
1333: /* XXX: ? */
1334: axen_lock_mii(sc);
1335: bval = 0x01;
1336: axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_UNK_28, &bval);
1337: axen_unlock_mii(sc);
1338:
1339: /* Init RX ring. */
1340: if (axen_rx_list_init(sc) == ENOBUFS) {
1341: aprint_error_dev(sc->axen_dev, "rx list init failed\n");
1342: axen_unlock_mii(sc);
1343: splx(s);
1344: return ENOBUFS;
1345: }
1346:
1347: /* Init TX ring. */
1348: if (axen_tx_list_init(sc) == ENOBUFS) {
1349: aprint_error_dev(sc->axen_dev, "tx list init failed\n");
1350: axen_unlock_mii(sc);
1351: splx(s);
1352: return ENOBUFS;
1353: }
1354:
1355: /* Program promiscuous mode and multicast filters. */
1356: axen_iff(sc);
1357:
1358: /* Enable receiver, set RX mode */
1359: axen_lock_mii(sc);
1360: axen_cmd(sc, AXEN_CMD_MAC_READ2, 2, AXEN_MAC_RXCTL, &wval);
1361: rxmode = le16toh(wval);
1362: rxmode |= AXEN_RXCTL_START;
1363: wval = htole16(rxmode);
1364: axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MAC_RXCTL, &wval);
1365: axen_unlock_mii(sc);
1366:
1367: /* Open RX and TX pipes. */
1368: err = usbd_open_pipe(sc->axen_iface, sc->axen_ed[AXEN_ENDPT_RX],
1369: USBD_EXCLUSIVE_USE, &sc->axen_ep[AXEN_ENDPT_RX]);
1370: if (err) {
1371: aprint_error_dev(sc->axen_dev, "open rx pipe failed: %s\n",
1372: usbd_errstr(err));
1373: splx(s);
1374: return EIO;
1375: }
1376:
1377: err = usbd_open_pipe(sc->axen_iface, sc->axen_ed[AXEN_ENDPT_TX],
1378: USBD_EXCLUSIVE_USE, &sc->axen_ep[AXEN_ENDPT_TX]);
1379: if (err) {
1380: aprint_error_dev(sc->axen_dev, "open tx pipe failed: %s\n",
1381: usbd_errstr(err));
1382: splx(s);
1383: return EIO;
1384: }
1385:
1386: /* Start up the receive pipe. */
1387: for (i = 0; i < AXEN_RX_LIST_CNT; i++) {
1388: c = &sc->axen_cdata.axen_rx_chain[i];
1389: usbd_setup_xfer(c->axen_xfer, sc->axen_ep[AXEN_ENDPT_RX],
1390: c, c->axen_buf, sc->axen_bufsz,
1391: USBD_SHORT_XFER_OK | USBD_NO_COPY,
1392: USBD_NO_TIMEOUT, axen_rxeof);
1393: usbd_transfer(c->axen_xfer);
1394: }
1395:
1396: ifp->if_flags |= IFF_RUNNING;
1397: ifp->if_flags &= ~IFF_OACTIVE;
1398:
1399: splx(s);
1400:
1401: callout_schedule(&sc->axen_stat_ch, hz);
1402: return 0;
1403: }
1404:
1405: static int
1406: axen_ioctl(struct ifnet *ifp, u_long cmd, void *data)
1407: {
1408: struct axen_softc *sc = ifp->if_softc;
1409: int s;
1410: int error = 0;
1411:
1412: s = splnet();
1413:
1414: switch (cmd) {
1415: case SIOCSIFFLAGS:
1416: if ((error = ifioctl_common(ifp, cmd, data)) != 0)
1417: break;
1418:
1419: switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
1420: case IFF_RUNNING:
1421: axen_stop(ifp, 1);
1422: break;
1423: case IFF_UP:
1424: axen_init(ifp);
1425: break;
1426: case IFF_UP | IFF_RUNNING:
1427: if ((ifp->if_flags ^ sc->axen_if_flags) == IFF_PROMISC)
1428: axen_iff(sc);
1429: else
1430: axen_init(ifp);
1431: break;
1432: }
1433: sc->axen_if_flags = ifp->if_flags;
1434: break;
1435:
1436: default:
1437: if ((error = ether_ioctl(ifp, cmd, data)) != ENETRESET)
1438: break;
1439:
1440: error = 0;
1441:
1442: if (cmd == SIOCADDMULTI || cmd == SIOCDELMULTI)
1443: axen_iff(sc);
1444: break;
1445: }
1446: splx(s);
1447:
1448: return error;
1449: }
1450:
1451: static void
1452: axen_watchdog(struct ifnet *ifp)
1453: {
1454: struct axen_softc *sc;
1455: struct axen_chain *c;
1456: usbd_status stat;
1457: int s;
1458:
1459: sc = ifp->if_softc;
1460:
1461: ifp->if_oerrors++;
1462: aprint_error_dev(sc->axen_dev, "watchdog timeout\n");
1463:
1464: s = splusb();
1465: c = &sc->axen_cdata.axen_tx_chain[0];
1466: usbd_get_xfer_status(c->axen_xfer, NULL, NULL, NULL, &stat);
1467: axen_txeof(c->axen_xfer, c, stat);
1468:
1469: if (!IFQ_IS_EMPTY(&ifp->if_snd))
1470: axen_start(ifp);
1471: splx(s);
1472: }
1473:
1474: /*
1475: * Stop the adapter and free any mbufs allocated to the
1476: * RX and TX lists.
1477: */
1478: static void
1479: axen_stop(struct ifnet *ifp, int disable)
1480: {
1481: struct axen_softc *sc = ifp->if_softc;
1482: usbd_status err;
1483: int i;
1484:
1485: axen_reset(sc);
1486:
1487: ifp->if_timer = 0;
1488: ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
1489:
1490: callout_stop(&sc->axen_stat_ch);
1491:
1492: /* Stop transfers. */
1493: if (sc->axen_ep[AXEN_ENDPT_RX] != NULL) {
1494: err = usbd_abort_pipe(sc->axen_ep[AXEN_ENDPT_RX]);
1495: if (err) {
1496: aprint_error_dev(sc->axen_dev,
1497: "abort rx pipe failed: %s\n", usbd_errstr(err));
1498:
1499: }
1500: err = usbd_close_pipe(sc->axen_ep[AXEN_ENDPT_RX]);
1501: if (err) {
1502: aprint_error_dev(sc->axen_dev,
1503: "close rx pipe failed: %s\n", usbd_errstr(err));
1504: }
1505: sc->axen_ep[AXEN_ENDPT_RX] = NULL;
1506: }
1507:
1508: if (sc->axen_ep[AXEN_ENDPT_TX] != NULL) {
1509: err = usbd_abort_pipe(sc->axen_ep[AXEN_ENDPT_TX]);
1510: if (err) {
1511: aprint_error_dev(sc->axen_dev,
1512: "abort tx pipe failed: %s\n", usbd_errstr(err));
1513: }
1514: err = usbd_close_pipe(sc->axen_ep[AXEN_ENDPT_TX]);
1515: if (err) {
1516: aprint_error_dev(sc->axen_dev,
1517: "close tx pipe failed: %s\n", usbd_errstr(err));
1518: }
1519: sc->axen_ep[AXEN_ENDPT_TX] = NULL;
1520: }
1521:
1522: if (sc->axen_ep[AXEN_ENDPT_INTR] != NULL) {
1523: err = usbd_abort_pipe(sc->axen_ep[AXEN_ENDPT_INTR]);
1524: if (err) {
1525: aprint_error_dev(sc->axen_dev,
1526: "abort intr pipe failed: %s\n", usbd_errstr(err));
1527: }
1528: err = usbd_close_pipe(sc->axen_ep[AXEN_ENDPT_INTR]);
1529: if (err) {
1530: aprint_error_dev(sc->axen_dev,
1531: "close intr pipe failed: %s\n", usbd_errstr(err));
1532: }
1533: sc->axen_ep[AXEN_ENDPT_INTR] = NULL;
1534: }
1535:
1536: /* Free RX resources. */
1537: for (i = 0; i < AXEN_RX_LIST_CNT; i++) {
1538: if (sc->axen_cdata.axen_rx_chain[i].axen_xfer != NULL) {
1539: usbd_free_xfer(sc->axen_cdata.axen_rx_chain[i].axen_xfer);
1540: sc->axen_cdata.axen_rx_chain[i].axen_xfer = NULL;
1541: }
1542: }
1543:
1544: /* Free TX resources. */
1545: for (i = 0; i < AXEN_TX_LIST_CNT; i++) {
1546: if (sc->axen_cdata.axen_tx_chain[i].axen_xfer != NULL) {
1547: usbd_free_xfer(sc->axen_cdata.axen_tx_chain[i].axen_xfer);
1548: sc->axen_cdata.axen_tx_chain[i].axen_xfer = NULL;
1549: }
1550: }
1551:
1552: sc->axen_link = 0;
1553: }
1554:
1555: MODULE(MODULE_CLASS_DRIVER, if_axen, "bpf");
1556:
1557: #ifdef _MODULE
1558: #include "ioconf.c"
1559: #endif
1560:
1561: static int
1562: if_axen_modcmd(modcmd_t cmd, void *aux)
1563: {
1564: int error = 0;
1565:
1566: switch (cmd) {
1567: case MODULE_CMD_INIT:
1568: #ifdef _MODULE
1569: error = config_init_component(cfdriver_ioconf_axen,
1570: cfattach_ioconf_axen, cfdata_ioconf_axen);
1571: #endif
1572: return error;
1573: case MODULE_CMD_FINI:
1574: #ifdef _MODULE
1575: error = config_fini_component(cfdriver_ioconf_axen,
1576: cfattach_ioconf_axen, cfdata_ioconf_axen);
1577: #endif
1578: return error;
1579: default:
1580: return ENOTTY;
1581: }
1582: }
CVSweb <webmaster@jp.NetBSD.org>