if_axe.c revision 1.10 1 /* $NetBSD: if_axe.c,v 1.10 2005/11/10 10:00:19 tron Exp $ */
2
3 /*
4 * Copyright (c) 1997, 1998, 1999, 2000-2003
5 * Bill Paul <wpaul (at) windriver.com>. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Bill Paul.
18 * 4. Neither the name of the author nor the names of any co-contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
26 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
32 * THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35 /*
36 * ASIX Electronics AX88172 USB 2.0 ethernet driver. Used in the
37 * LinkSys USB200M and various other adapters.
38 *
39 * Manuals available from:
40 * http://www.asix.com.tw/datasheet/mac/Ax88172.PDF
41 * (also http://people.freebsd.org/~wpaul/ASIX/Ax88172.PDF)
42 * Note: you need the manual for the AX88170 chip (USB 1.x ethernet
43 * controller) to find the definitions for the RX control register.
44 * http://www.asix.com.tw/datasheet/mac/Ax88170.PDF
45 *
46 * Written by Bill Paul <wpaul (at) windriver.com>
47 * Senior Engineer
48 * Wind River Systems
49 */
50
51 /*
52 * The AX88172 provides USB ethernet supports at 10 and 100Mbps.
53 * It uses an external PHY (reference designs use a RealTek chip),
54 * and has a 64-bit multicast hash filter. There is some information
55 * missing from the manual which one needs to know in order to make
56 * the chip function:
57 *
58 * - You must set bit 7 in the RX control register, otherwise the
59 * chip won't receive any packets.
60 * - You must initialize all 3 IPG registers, or you won't be able
61 * to send any packets.
62 *
63 * Note that this device appears to only support loading the station
64 * address via autload from the EEPROM (i.e. there's no way to manaully
65 * set it).
66 *
67 * (Adam Weinberger wanted me to name this driver if_gir.c.)
68 */
69
70 /*
71 * Ported to OpenBSD 3/28/2004 by Greg Taleck <taleck (at) oz.net>
72 * with bits and pieces from the aue and url drivers.
73 */
74
75 #include <sys/cdefs.h>
76 __KERNEL_RCSID(0, "$NetBSD: if_axe.c,v 1.10 2005/11/10 10:00:19 tron Exp $");
77
78 #if defined(__NetBSD__)
79 #include "opt_inet.h"
80 #include "opt_ns.h"
81 #include "rnd.h"
82 #endif
83
84 #include "bpfilter.h"
85
86 #include <sys/param.h>
87 #include <sys/systm.h>
88 #include <sys/sockio.h>
89 #include <sys/lock.h>
90 #include <sys/mbuf.h>
91 #include <sys/kernel.h>
92 #if defined(__OpenBSD__)
93 #include <sys/proc.h>
94 #endif
95 #include <sys/socket.h>
96
97 #include <sys/device.h>
98 #if NRND > 0
99 #include <sys/rnd.h>
100 #endif
101
102 #include <net/if.h>
103 #if defined(__NetBSD__)
104 #include <net/if_arp.h>
105 #endif
106 #include <net/if_dl.h>
107 #include <net/if_media.h>
108
109 #define BPF_MTAP(ifp, m) bpf_mtap((ifp)->if_bpf, (m))
110
111 #if NBPFILTER > 0
112 #include <net/bpf.h>
113 #endif
114
115 #if defined(__NetBSD__)
116 #include <net/if_ether.h>
117 #ifdef INET
118 #include <netinet/in.h>
119 #include <netinet/if_inarp.h>
120 #endif
121 #endif /* defined(__NetBSD__) */
122
123 #if defined(__OpenBSD__)
124 #ifdef INET
125 #include <netinet/in.h>
126 #include <netinet/in_systm.h>
127 #include <netinet/in_var.h>
128 #include <netinet/ip.h>
129 #include <netinet/if_ether.h>
130 #endif
131 #endif /* defined(__OpenBSD__) */
132
133 #ifdef NS
134 #include <netns/ns.h>
135 #include <netns/ns_if.h>
136 #endif
137
138 #include <dev/mii/mii.h>
139 #include <dev/mii/miivar.h>
140
141 #include <dev/usb/usb.h>
142 #include <dev/usb/usbdi.h>
143 #include <dev/usb/usbdi_util.h>
144 #include <dev/usb/usbdevs.h>
145
146 #include <dev/usb/if_axereg.h>
147
148 #ifdef AXE_DEBUG
149 #define DPRINTF(x) do { if (axedebug) logprintf x; } while (0)
150 #define DPRINTFN(n,x) do { if (axedebug >= (n)) logprintf x; } while (0)
151 int axedebug = 0;
152 #else
153 #define DPRINTF(x)
154 #define DPRINTFN(n,x)
155 #endif
156
157 /*
158 * Various supported device vendors/products.
159 */
160 Static const struct axe_type axe_devs[] = {
161 { { USB_VENDOR_ASIX, USB_PRODUCT_ASIX_AX88172}, 0 },
162 { { USB_VENDOR_COREGA, USB_PRODUCT_COREGA_FETHER_USB2_TX }, 0},
163 { { USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DUBE100}, 0 },
164 { { USB_VENDOR_LINKSYS2, USB_PRODUCT_LINKSYS2_USB200M}, 0 },
165 { { USB_VENDOR_MELCO, USB_PRODUCT_MELCO_LUAU2KTX}, 0 },
166 { { USB_VENDOR_NETGEAR, USB_PRODUCT_NETGEAR_FA120}, 0 },
167 { { USB_VENDOR_SITECOM, USB_PRODUCT_SITECOM_LN029}, 0 },
168 { { USB_VENDOR_SYSTEMTALKS, USB_PRODUCT_SYSTEMTALKS_SGCX2UL}, 0 },
169 };
170 #define axe_lookup(v, p) ((const struct axe_type *)usb_lookup(axe_devs, v, p))
171
172 USB_DECLARE_DRIVER(axe);
173
174 Static int axe_tx_list_init(struct axe_softc *);
175 Static int axe_rx_list_init(struct axe_softc *);
176 Static int axe_newbuf(struct axe_softc *, struct axe_chain *, struct mbuf *);
177 Static int axe_encap(struct axe_softc *, struct mbuf *, int);
178 Static void axe_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
179 Static void axe_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
180 Static void axe_tick(void *);
181 Static void axe_tick_task(void *);
182 #if 0
183 Static void axe_rxstart(struct ifnet *);
184 #endif
185 Static void axe_start(struct ifnet *);
186 Static int axe_ioctl(struct ifnet *, u_long, caddr_t);
187 Static void axe_init(void *);
188 Static void axe_stop(struct axe_softc *);
189 Static void axe_watchdog(struct ifnet *);
190 Static int axe_miibus_readreg(device_ptr_t, int, int);
191 Static void axe_miibus_writereg(device_ptr_t, int, int, int);
192 Static void axe_miibus_statchg(device_ptr_t);
193 Static int axe_cmd(struct axe_softc *, int, int, int, void *);
194 Static int axe_ifmedia_upd(struct ifnet *);
195 Static void axe_ifmedia_sts(struct ifnet *, struct ifmediareq *);
196 Static void axe_reset(struct axe_softc *sc);
197
198 Static void axe_setmulti(struct axe_softc *);
199 Static void axe_lock_mii(struct axe_softc *sc);
200 Static void axe_unlock_mii(struct axe_softc *sc);
201
202 /* Get exclusive access to the MII registers */
203 Static void
204 axe_lock_mii(struct axe_softc *sc)
205 {
206 sc->axe_refcnt++;
207 usb_lockmgr(&sc->axe_mii_lock, LK_EXCLUSIVE, NULL);
208 }
209
210 Static void
211 axe_unlock_mii(struct axe_softc *sc)
212 {
213 usb_lockmgr(&sc->axe_mii_lock, LK_RELEASE, NULL);
214 if (--sc->axe_refcnt < 0)
215 usb_detach_wakeup(USBDEV(sc->axe_dev));
216 }
217
218 Static int
219 axe_cmd(struct axe_softc *sc, int cmd, int index, int val, void *buf)
220 {
221 usb_device_request_t req;
222 usbd_status err;
223
224 if (sc->axe_dying)
225 return(0);
226
227 axe_lock_mii(sc);
228 if (AXE_CMD_DIR(cmd))
229 req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
230 else
231 req.bmRequestType = UT_READ_VENDOR_DEVICE;
232 req.bRequest = AXE_CMD_CMD(cmd);
233 USETW(req.wValue, val);
234 USETW(req.wIndex, index);
235 USETW(req.wLength, AXE_CMD_LEN(cmd));
236
237 err = usbd_do_request(sc->axe_udev, &req, buf);
238 axe_unlock_mii(sc);
239
240 if (err)
241 return(-1);
242
243 return(0);
244 }
245
246 Static int
247 axe_miibus_readreg(device_ptr_t dev, int phy, int reg)
248 {
249 struct axe_softc *sc = USBGETSOFTC(dev);
250 usbd_status err;
251 u_int16_t val;
252
253 if (sc->axe_dying) {
254 DPRINTF(("axe: dying\n"));
255 return(0);
256 }
257
258 #ifdef notdef
259 /*
260 * The chip tells us the MII address of any supported
261 * PHYs attached to the chip, so only read from those.
262 */
263
264 if (sc->axe_phyaddrs[0] != AXE_NOPHY && phy != sc->axe_phyaddrs[0])
265 return (0);
266
267 if (sc->axe_phyaddrs[1] != AXE_NOPHY && phy != sc->axe_phyaddrs[1])
268 return (0);
269 #endif
270 if (sc->axe_phyaddrs[0] != 0xFF && sc->axe_phyaddrs[0] != phy)
271 return (0);
272
273 val = 0;
274
275 axe_lock_mii(sc);
276 axe_cmd(sc, AXE_CMD_MII_OPMODE_SW, 0, 0, NULL);
277 err = axe_cmd(sc, AXE_CMD_MII_READ_REG, reg, phy, (void *)&val);
278 axe_cmd(sc, AXE_CMD_MII_OPMODE_HW, 0, 0, NULL);
279 axe_unlock_mii(sc);
280
281 if (err) {
282 printf("%s: read PHY failed\n", USBDEVNAME(sc->axe_dev));
283 return(-1);
284 }
285
286 if (val)
287 sc->axe_phyaddrs[0] = phy;
288
289 return (le16toh(val));
290 }
291
292 Static void
293 axe_miibus_writereg(device_ptr_t dev, int phy, int reg, int val)
294 {
295 struct axe_softc *sc = USBGETSOFTC(dev);
296 usbd_status err;
297
298 if (sc->axe_dying)
299 return;
300
301 val = htole32(val);
302 axe_lock_mii(sc);
303 axe_cmd(sc, AXE_CMD_MII_OPMODE_SW, 0, 0, NULL);
304 err = axe_cmd(sc, AXE_CMD_MII_WRITE_REG, reg, phy, (void *)&val);
305 axe_cmd(sc, AXE_CMD_MII_OPMODE_HW, 0, 0, NULL);
306 axe_unlock_mii(sc);
307
308 if (err) {
309 printf("%s: write PHY failed\n", USBDEVNAME(sc->axe_dev));
310 return;
311 }
312 }
313
314 Static void
315 axe_miibus_statchg(device_ptr_t dev)
316 {
317 struct axe_softc *sc = USBGETSOFTC(dev);
318 struct mii_data *mii = GET_MII(sc);
319 int val, err;
320
321 if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX)
322 val = AXE_MEDIA_FULL_DUPLEX;
323 else
324 val = 0;
325 DPRINTF(("axe_miibus_statchg: val=0x%x\n", val));
326 err = axe_cmd(sc, AXE_CMD_WRITE_MEDIA, 0, val, NULL);
327 if (err) {
328 printf("%s: media change failed\n", USBDEVNAME(sc->axe_dev));
329 return;
330 }
331 }
332
333 /*
334 * Set media options.
335 */
336 Static int
337 axe_ifmedia_upd(struct ifnet *ifp)
338 {
339 struct axe_softc *sc = ifp->if_softc;
340 struct mii_data *mii = GET_MII(sc);
341
342 sc->axe_link = 0;
343 if (mii->mii_instance) {
344 struct mii_softc *miisc;
345 LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
346 mii_phy_reset(miisc);
347 }
348 mii_mediachg(mii);
349
350 return (0);
351 }
352
353 /*
354 * Report current media status.
355 */
356 Static void
357 axe_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
358 {
359 struct axe_softc *sc = ifp->if_softc;
360 struct mii_data *mii = GET_MII(sc);
361
362 mii_pollstat(mii);
363 ifmr->ifm_active = mii->mii_media_active;
364 ifmr->ifm_status = mii->mii_media_status;
365 }
366
367 Static void
368 axe_setmulti(struct axe_softc *sc)
369 {
370 struct ifnet *ifp;
371 struct ether_multi *enm;
372 struct ether_multistep step;
373 u_int32_t h = 0;
374 u_int16_t rxmode;
375 u_int8_t hashtbl[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
376
377 if (sc->axe_dying)
378 return;
379
380 ifp = GET_IFP(sc);
381
382 axe_cmd(sc, AXE_CMD_RXCTL_READ, 0, 0, (void *)&rxmode);
383 rxmode = le16toh(rxmode);
384
385 if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
386 allmulti:
387 rxmode |= AXE_RXCMD_ALLMULTI;
388 axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, rxmode, NULL);
389 return;
390 } else
391 rxmode &= ~AXE_RXCMD_ALLMULTI;
392
393 /* now program new ones */
394 #if defined(__NetBSD__)
395 ETHER_FIRST_MULTI(step, &sc->axe_ec, enm);
396 #else
397 ETHER_FIRST_MULTI(step, &sc->arpcom, enm);
398 #endif
399 while (enm != NULL) {
400 if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
401 ETHER_ADDR_LEN) != 0)
402 goto allmulti;
403
404 h = ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN) >> 26;
405 hashtbl[h / 8] |= 1 << (h % 8);
406 ETHER_NEXT_MULTI(step, enm);
407 }
408
409 ifp->if_flags &= ~IFF_ALLMULTI;
410 axe_cmd(sc, AXE_CMD_WRITE_MCAST, 0, 0, (void *)&hashtbl);
411 axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, rxmode, NULL);
412 return;
413 }
414
415 Static void
416 axe_reset(struct axe_softc *sc)
417 {
418 if (sc->axe_dying)
419 return;
420 /* XXX What to reset? */
421
422 /* Wait a little while for the chip to get its brains in order. */
423 DELAY(1000);
424 return;
425 }
426
427 /*
428 * Probe for a AX88172 chip.
429 */
430 USB_MATCH(axe)
431 {
432 USB_MATCH_START(axe, uaa);
433
434 if (!uaa->iface) {
435 return(UMATCH_NONE);
436 }
437
438 return (axe_lookup(uaa->vendor, uaa->product) != NULL ?
439 UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
440 }
441
442 /*
443 * Attach the interface. Allocate softc structures, do ifmedia
444 * setup and ethernet/BPF attach.
445 */
446 USB_ATTACH(axe)
447 {
448 USB_ATTACH_START(axe, sc, uaa);
449 usbd_device_handle dev = uaa->device;
450 usbd_status err;
451 usb_interface_descriptor_t *id;
452 usb_endpoint_descriptor_t *ed;
453 struct mii_data *mii;
454 u_char eaddr[ETHER_ADDR_LEN];
455 char *devinfop;
456 char *devname = USBDEVNAME(sc->axe_dev);
457 struct ifnet *ifp;
458 int i, s;
459
460 devinfop = usbd_devinfo_alloc(dev, 0);
461 USB_ATTACH_SETUP;
462
463 err = usbd_set_config_no(dev, AXE_CONFIG_NO, 1);
464 if (err) {
465 printf("%s: getting interface handle failed\n",
466 USBDEVNAME(sc->axe_dev));
467 USB_ATTACH_ERROR_RETURN;
468 }
469
470 usb_init_task(&sc->axe_tick_task, axe_tick_task, sc);
471 lockinit(&sc->axe_mii_lock, PZERO, "axemii", 0, LK_CANRECURSE);
472 usb_init_task(&sc->axe_stop_task, (void (*)(void *))axe_stop, sc);
473
474 err = usbd_device2interface_handle(dev, AXE_IFACE_IDX, &sc->axe_iface);
475 if (err) {
476 printf("%s: getting interface handle failed\n",
477 USBDEVNAME(sc->axe_dev));
478 USB_ATTACH_ERROR_RETURN;
479 }
480
481 sc->axe_udev = dev;
482 sc->axe_product = uaa->product;
483 sc->axe_vendor = uaa->vendor;
484
485 id = usbd_get_interface_descriptor(sc->axe_iface);
486
487 printf("%s: %s\n", USBDEVNAME(sc->axe_dev), devinfop);
488 usbd_devinfo_free(devinfop);
489
490 /* Find endpoints. */
491 for (i = 0; i < id->bNumEndpoints; i++) {
492 ed = usbd_interface2endpoint_descriptor(sc->axe_iface, i);
493 if (!ed) {
494 printf("%s: couldn't get ep %d\n",
495 USBDEVNAME(sc->axe_dev), i);
496 USB_ATTACH_ERROR_RETURN;
497 }
498 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
499 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
500 sc->axe_ed[AXE_ENDPT_RX] = ed->bEndpointAddress;
501 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
502 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
503 sc->axe_ed[AXE_ENDPT_TX] = ed->bEndpointAddress;
504 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
505 UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
506 sc->axe_ed[AXE_ENDPT_INTR] = ed->bEndpointAddress;
507 }
508 }
509
510 s = splnet();
511
512 /*
513 * Get station address.
514 */
515 axe_cmd(sc, AXE_CMD_READ_NODEID, 0, 0, &eaddr);
516
517 /*
518 * Load IPG values and PHY indexes.
519 */
520 axe_cmd(sc, AXE_CMD_READ_IPG012, 0, 0, (void *)&sc->axe_ipgs);
521 axe_cmd(sc, AXE_CMD_READ_PHYID, 0, 0, (void *)&sc->axe_phyaddrs);
522
523 /*
524 * Work around broken adapters that appear to lie about
525 * their PHY addresses.
526 */
527 sc->axe_phyaddrs[0] = sc->axe_phyaddrs[1] = 0xFF;
528
529 /*
530 * An ASIX chip was detected. Inform the world.
531 */
532 printf("%s: Ethernet address %s\n", USBDEVNAME(sc->axe_dev),
533 ether_sprintf(eaddr));
534
535 /* Initialize interface info.*/
536 ifp = GET_IFP(sc);
537 ifp->if_softc = sc;
538 strncpy(ifp->if_xname, devname, IFNAMSIZ);
539 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
540 ifp->if_ioctl = axe_ioctl;
541 ifp->if_start = axe_start;
542
543 ifp->if_watchdog = axe_watchdog;
544
545 /* ifp->if_baudrate = 10000000; */
546 /* ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;*/
547
548 IFQ_SET_READY(&ifp->if_snd);
549
550 /* Initialize MII/media info. */
551 mii = &sc->axe_mii;
552 mii->mii_ifp = ifp;
553 mii->mii_readreg = axe_miibus_readreg;
554 mii->mii_writereg = axe_miibus_writereg;
555 mii->mii_statchg = axe_miibus_statchg;
556 mii->mii_flags = MIIF_AUTOTSLEEP;
557
558 ifmedia_init(&mii->mii_media, 0, axe_ifmedia_upd, axe_ifmedia_sts);
559 mii_attach(self, mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, 0);
560
561 if (LIST_FIRST(&mii->mii_phys) == NULL) {
562 ifmedia_add(&mii->mii_media, IFM_ETHER | IFM_NONE, 0, NULL);
563 ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_NONE);
564 } else
565 ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO);
566
567 /* Attach the interface. */
568 if_attach(ifp);
569 Ether_ifattach(ifp, eaddr);
570 #if NRND > 0
571 rnd_attach_source(&sc->rnd_source, USBDEVNAME(sc->axe_dev),
572 RND_TYPE_NET, 0);
573 #endif
574
575 usb_callout_init(sc->axe_stat_ch);
576
577 sc->axe_attached = 1;
578 splx(s);
579
580 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->axe_udev,
581 USBDEV(sc->axe_dev));
582
583 USB_ATTACH_SUCCESS_RETURN;
584 }
585
586 USB_DETACH(axe)
587 {
588 USB_DETACH_START(axe, sc);
589 int s;
590 struct ifnet *ifp = GET_IFP(sc);
591
592 DPRINTFN(2,("%s: %s: enter\n", USBDEVNAME(sc->axe_dev), __func__));
593
594 /* Detached before attached finished, so just bail out. */
595 if (!sc->axe_attached)
596 return (0);
597
598 usb_uncallout(sc->axe_stat_ch, axe_tick, sc);
599
600 sc->axe_dying = 1;
601
602 ether_ifdetach(ifp);
603
604 if (sc->axe_ep[AXE_ENDPT_TX] != NULL)
605 usbd_abort_pipe(sc->axe_ep[AXE_ENDPT_TX]);
606 if (sc->axe_ep[AXE_ENDPT_RX] != NULL)
607 usbd_abort_pipe(sc->axe_ep[AXE_ENDPT_RX]);
608 if (sc->axe_ep[AXE_ENDPT_INTR] != NULL)
609 usbd_abort_pipe(sc->axe_ep[AXE_ENDPT_INTR]);
610
611 /*
612 * Remove any pending tasks. They cannot be executing because they run
613 * in the same thread as detach.
614 */
615 usb_rem_task(sc->axe_udev, &sc->axe_tick_task);
616 usb_rem_task(sc->axe_udev, &sc->axe_stop_task);
617
618 s = splusb();
619
620 if (--sc->axe_refcnt >= 0) {
621 /* Wait for processes to go away */
622 usb_detach_wait(USBDEV(sc->axe_dev));
623 }
624
625 if (ifp->if_flags & IFF_RUNNING)
626 axe_stop(sc);
627
628 #if defined(__NetBSD__)
629 #if NRND > 0
630 rnd_detach_source(&sc->rnd_source);
631 #endif
632 #endif /* __NetBSD__ */
633 mii_detach(&sc->axe_mii, MII_PHY_ANY, MII_OFFSET_ANY);
634 ifmedia_delete_instance(&sc->axe_mii.mii_media, IFM_INST_ANY);
635 ether_ifdetach(ifp);
636 if_detach(ifp);
637
638 #ifdef DIAGNOSTIC
639 if (sc->axe_ep[AXE_ENDPT_TX] != NULL ||
640 sc->axe_ep[AXE_ENDPT_RX] != NULL ||
641 sc->axe_ep[AXE_ENDPT_INTR] != NULL)
642 printf("%s: detach has active endpoints\n",
643 USBDEVNAME(sc->axe_dev));
644 #endif
645
646 sc->axe_attached = 0;
647
648 if (--sc->axe_refcnt >= 0) {
649 /* Wait for processes to go away. */
650 usb_detach_wait(USBDEV(sc->axe_dev));
651 }
652 splx(s);
653
654 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->axe_udev,
655 USBDEV(sc->axe_dev));
656
657 return (0);
658 }
659
660 int
661 axe_activate(device_ptr_t self, enum devact act)
662 {
663 struct axe_softc *sc = (struct axe_softc *)self;
664
665 DPRINTFN(2,("%s: %s: enter\n", USBDEVNAME(sc->axe_dev), __func__));
666
667 switch (act) {
668 case DVACT_ACTIVATE:
669 return (EOPNOTSUPP);
670 break;
671
672 case DVACT_DEACTIVATE:
673 if_deactivate(&sc->axe_ec.ec_if);
674 sc->axe_dying = 1;
675 break;
676 }
677 return (0);
678 }
679
680 /*
681 * Initialize an RX descriptor and attach an MBUF cluster.
682 */
683 Static int
684 axe_newbuf(struct axe_softc *sc, struct axe_chain *c, struct mbuf *m)
685 {
686 struct mbuf *m_new = NULL;
687
688 DPRINTFN(10,("%s: %s: enter\n", USBDEVNAME(sc->axe_dev),__func__));
689
690 if (m == NULL) {
691 MGETHDR(m_new, M_DONTWAIT, MT_DATA);
692 if (m_new == NULL) {
693 printf("%s: no memory for rx list "
694 "-- packet dropped!\n", USBDEVNAME(sc->axe_dev));
695 return (ENOBUFS);
696 }
697
698 MCLGET(m_new, M_DONTWAIT);
699 if (!(m_new->m_flags & M_EXT)) {
700 printf("%s: no memory for rx list "
701 "-- packet dropped!\n", USBDEVNAME(sc->axe_dev));
702 m_freem(m_new);
703 return (ENOBUFS);
704 }
705 m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
706 } else {
707 m_new = m;
708 m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
709 m_new->m_data = m_new->m_ext.ext_buf;
710 }
711
712 m_adj(m_new, ETHER_ALIGN);
713 c->axe_mbuf = m_new;
714
715 return (0);
716 }
717
718 Static int
719 axe_rx_list_init(struct axe_softc *sc)
720 {
721 struct axe_cdata *cd;
722 struct axe_chain *c;
723 int i;
724
725 DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->axe_dev), __func__));
726
727 cd = &sc->axe_cdata;
728 for (i = 0; i < AXE_RX_LIST_CNT; i++) {
729 c = &cd->axe_rx_chain[i];
730 c->axe_sc = sc;
731 c->axe_idx = i;
732 if (axe_newbuf(sc, c, NULL) == ENOBUFS)
733 return (ENOBUFS);
734 if (c->axe_xfer == NULL) {
735 c->axe_xfer = usbd_alloc_xfer(sc->axe_udev);
736 if (c->axe_xfer == NULL)
737 return (ENOBUFS);
738 c->axe_buf = usbd_alloc_buffer(c->axe_xfer, AXE_BUFSZ);
739 if (c->axe_buf == NULL) {
740 usbd_free_xfer(c->axe_xfer);
741 return (ENOBUFS);
742 }
743 }
744 }
745
746 return (0);
747 }
748
749 Static int
750 axe_tx_list_init(struct axe_softc *sc)
751 {
752 struct axe_cdata *cd;
753 struct axe_chain *c;
754 int i;
755
756 DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->axe_dev), __func__));
757
758 cd = &sc->axe_cdata;
759 for (i = 0; i < AXE_TX_LIST_CNT; i++) {
760 c = &cd->axe_tx_chain[i];
761 c->axe_sc = sc;
762 c->axe_idx = i;
763 c->axe_mbuf = NULL;
764 if (c->axe_xfer == NULL) {
765 c->axe_xfer = usbd_alloc_xfer(sc->axe_udev);
766 if (c->axe_xfer == NULL)
767 return (ENOBUFS);
768 c->axe_buf = usbd_alloc_buffer(c->axe_xfer, AXE_BUFSZ);
769 if (c->axe_buf == NULL) {
770 usbd_free_xfer(c->axe_xfer);
771 return (ENOBUFS);
772 }
773 }
774 }
775
776 return (0);
777 }
778
779 #if 0
780 Static void
781 axe_rxstart(struct ifnet *ifp)
782 {
783 struct axe_softc *sc;
784 struct axe_chain *c;
785
786 sc = ifp->if_softc;
787 axe_lock_mii(sc);
788 c = &sc->axe_cdata.axe_rx_chain[sc->axe_cdata.axe_rx_prod];
789
790 if (axe_newbuf(sc, c, NULL) == ENOBUFS) {
791 ifp->if_ierrors++;
792 axe_unlock_mii(sc);
793 return;
794 }
795
796 /* Setup new transfer. */
797 usbd_setup_xfer(c->axe_xfer, sc->axe_ep[AXE_ENDPT_RX],
798 c, mtod(c->axe_mbuf, char *), AXE_BUFSZ, USBD_SHORT_XFER_OK,
799 USBD_NO_TIMEOUT, axe_rxeof);
800 usbd_transfer(c->axe_xfer);
801 axe_unlock_mii(sc);
802
803 return;
804 }
805 #endif
806
807 /*
808 * A frame has been uploaded: pass the resulting mbuf chain up to
809 * the higher level protocols.
810 */
811 Static void
812 axe_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
813 {
814 struct axe_softc *sc;
815 struct axe_chain *c;
816 struct ifnet *ifp;
817 struct mbuf *m;
818 u_int32_t total_len;
819 int s;
820
821 c = priv;
822 sc = c->axe_sc;
823 ifp = GET_IFP(sc);
824
825 DPRINTFN(10,("%s: %s: enter\n", USBDEVNAME(sc->axe_dev),__func__));
826
827 if (sc->axe_dying)
828 return;
829
830 if (!(ifp->if_flags & IFF_RUNNING))
831 return;
832
833 if (status != USBD_NORMAL_COMPLETION) {
834 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
835 return;
836 if (usbd_ratecheck(&sc->axe_rx_notice)) {
837 printf("%s: usb errors on rx: %s\n",
838 USBDEVNAME(sc->axe_dev), usbd_errstr(status));
839 }
840 if (status == USBD_STALLED)
841 usbd_clear_endpoint_stall(sc->axe_ep[AXE_ENDPT_RX]);
842 goto done;
843 }
844
845 usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
846
847 m = c->axe_mbuf;
848
849 if (total_len <= sizeof(struct ether_header)) {
850 ifp->if_ierrors++;
851 goto done;
852 }
853
854 ifp->if_ipackets++;
855 m->m_pkthdr.rcvif = ifp;
856 m->m_pkthdr.len = m->m_len = total_len;
857
858
859 memcpy(mtod(c->axe_mbuf, char *), c->axe_buf, total_len);
860
861 /* No errors; receive the packet. */
862 total_len -= ETHER_CRC_LEN + 4;
863
864 s = splnet();
865
866 /* XXX ugly */
867 if (axe_newbuf(sc, c, NULL) == ENOBUFS) {
868 ifp->if_ierrors++;
869 goto done1;
870 }
871
872 #if NBPFILTER > 0
873 if (ifp->if_bpf)
874 BPF_MTAP(ifp, m);
875 #endif
876
877 DPRINTFN(10,("%s: %s: deliver %d\n", USBDEVNAME(sc->axe_dev),
878 __func__, m->m_len));
879 IF_INPUT(ifp, m);
880 done1:
881 splx(s);
882
883 done:
884
885 /* Setup new transfer. */
886 usbd_setup_xfer(xfer, sc->axe_ep[AXE_ENDPT_RX],
887 c, c->axe_buf, AXE_BUFSZ,
888 USBD_SHORT_XFER_OK | USBD_NO_COPY,
889 USBD_NO_TIMEOUT, axe_rxeof);
890 usbd_transfer(xfer);
891
892 DPRINTFN(10,("%s: %s: start rx\n", USBDEVNAME(sc->axe_dev),
893 __func__));
894 return;
895 }
896
897 /*
898 * A frame was downloaded to the chip. It's safe for us to clean up
899 * the list buffers.
900 */
901
902 Static void
903 axe_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
904 {
905 struct axe_softc *sc;
906 struct axe_chain *c;
907 struct ifnet *ifp;
908 int s;
909
910 c = priv;
911 sc = c->axe_sc;
912 ifp = GET_IFP(sc);
913
914 if (sc->axe_dying)
915 return;
916
917 s = splnet();
918
919 if (status != USBD_NORMAL_COMPLETION) {
920 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
921 splx(s);
922 return;
923 }
924 ifp->if_oerrors++;
925 printf("%s: usb error on tx: %s\n", USBDEVNAME(sc->axe_dev),
926 usbd_errstr(status));
927 if (status == USBD_STALLED)
928 usbd_clear_endpoint_stall(sc->axe_ep[AXE_ENDPT_TX]);
929 splx(s);
930 return;
931 }
932
933 ifp->if_timer = 0;
934 ifp->if_flags &= ~IFF_OACTIVE;
935
936 m_freem(c->axe_mbuf);
937 c->axe_mbuf = NULL;
938
939 if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
940 axe_start(ifp);
941
942 ifp->if_opackets++;
943 splx(s);
944 return;
945 }
946
947 Static void
948 axe_tick(void *xsc)
949 {
950 struct axe_softc *sc = xsc;
951
952 if (sc == NULL)
953 return;
954
955 DPRINTFN(0xff, ("%s: %s: enter\n", USBDEVNAME(sc->axe_dev),
956 __func__));
957
958 if (sc->axe_dying)
959 return;
960
961 /* Perform periodic stuff in process context */
962 usb_add_task(sc->axe_udev, &sc->axe_tick_task);
963
964 }
965
966 Static void
967 axe_tick_task(void *xsc)
968 {
969 int s;
970 struct axe_softc *sc;
971 struct ifnet *ifp;
972 struct mii_data *mii;
973
974 sc = xsc;
975
976 if (sc == NULL)
977 return;
978
979 if (sc->axe_dying)
980 return;
981
982 ifp = GET_IFP(sc);
983 mii = GET_MII(sc);
984 if (mii == NULL)
985 return;
986
987 s = splnet();
988
989 mii_tick(mii);
990 if (!sc->axe_link) {
991 mii_pollstat(mii);
992 if (mii->mii_media_status & IFM_ACTIVE &&
993 IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) {
994 DPRINTF(("%s: %s: got link\n",
995 USBDEVNAME(sc->axe_dev), __func__));
996 sc->axe_link++;
997 if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
998 axe_start(ifp);
999 }
1000 }
1001
1002 usb_callout(sc->axe_stat_ch, hz, axe_tick, sc);
1003
1004 splx(s);
1005 }
1006
1007 Static int
1008 axe_encap(struct axe_softc *sc, struct mbuf *m, int idx)
1009 {
1010 struct axe_chain *c;
1011 usbd_status err;
1012
1013 c = &sc->axe_cdata.axe_tx_chain[idx];
1014
1015 /*
1016 * Copy the mbuf data into a contiguous buffer, leaving two
1017 * bytes at the beginning to hold the frame length.
1018 */
1019 m_copydata(m, 0, m->m_pkthdr.len, c->axe_buf);
1020 c->axe_mbuf = m;
1021
1022 usbd_setup_xfer(c->axe_xfer, sc->axe_ep[AXE_ENDPT_TX],
1023 c, c->axe_buf, m->m_pkthdr.len, USBD_FORCE_SHORT_XFER, 10000,
1024 axe_txeof);
1025
1026 /* Transmit */
1027 err = usbd_transfer(c->axe_xfer);
1028 if (err != USBD_IN_PROGRESS) {
1029 axe_stop(sc);
1030 return(EIO);
1031 }
1032
1033 sc->axe_cdata.axe_tx_cnt++;
1034
1035 return(0);
1036 }
1037
1038 Static void
1039 axe_start(struct ifnet *ifp)
1040 {
1041 struct axe_softc *sc;
1042 struct mbuf *m_head = NULL;
1043
1044 sc = ifp->if_softc;
1045
1046 if (!sc->axe_link) {
1047 return;
1048 }
1049
1050 if (ifp->if_flags & IFF_OACTIVE) {
1051 return;
1052 }
1053
1054 IF_DEQUEUE(&ifp->if_snd, m_head);
1055 if (m_head == NULL) {
1056 return;
1057 }
1058
1059 if (axe_encap(sc, m_head, 0)) {
1060 IF_PREPEND(&ifp->if_snd, m_head);
1061 ifp->if_flags |= IFF_OACTIVE;
1062 return;
1063 }
1064
1065 /*
1066 * If there's a BPF listener, bounce a copy of this frame
1067 * to him.
1068 */
1069 #if NBPFILTER > 0
1070 if (ifp->if_bpf)
1071 BPF_MTAP(ifp, m_head);
1072 #endif
1073
1074 ifp->if_flags |= IFF_OACTIVE;
1075
1076 /*
1077 * Set a timeout in case the chip goes out to lunch.
1078 */
1079 ifp->if_timer = 5;
1080
1081 return;
1082 }
1083
1084 Static void
1085 axe_init(void *xsc)
1086 {
1087 struct axe_softc *sc = xsc;
1088 struct ifnet *ifp = GET_IFP(sc);
1089 struct axe_chain *c;
1090 usbd_status err;
1091 int rxmode;
1092 int i, s;
1093
1094 if (ifp->if_flags & IFF_RUNNING)
1095 return;
1096
1097 s = splnet();
1098
1099 /*
1100 * Cancel pending I/O and free all RX/TX buffers.
1101 */
1102 axe_reset(sc);
1103
1104 /* Enable RX logic. */
1105
1106 /* Init RX ring. */
1107 if (axe_rx_list_init(sc) == ENOBUFS) {
1108 printf("%s: rx list init failed\n", USBDEVNAME(sc->axe_dev));
1109 splx(s);
1110 return;
1111 }
1112
1113 /* Init TX ring. */
1114 if (axe_tx_list_init(sc) == ENOBUFS) {
1115 printf("%s: tx list init failed\n", USBDEVNAME(sc->axe_dev));
1116 splx(s);
1117 return;
1118 }
1119
1120 /* Set transmitter IPG values */
1121 axe_cmd(sc, AXE_CMD_WRITE_IPG0, 0, sc->axe_ipgs[0], NULL);
1122 axe_cmd(sc, AXE_CMD_WRITE_IPG1, 0, sc->axe_ipgs[1], NULL);
1123 axe_cmd(sc, AXE_CMD_WRITE_IPG2, 0, sc->axe_ipgs[2], NULL);
1124
1125 /* Enable receiver, set RX mode */
1126 rxmode = AXE_RXCMD_UNICAST|AXE_RXCMD_MULTICAST|AXE_RXCMD_ENABLE;
1127
1128 /* If we want promiscuous mode, set the allframes bit. */
1129 if (ifp->if_flags & IFF_PROMISC)
1130 rxmode |= AXE_RXCMD_PROMISC;
1131
1132 if (ifp->if_flags & IFF_BROADCAST)
1133 rxmode |= AXE_RXCMD_BROADCAST;
1134
1135 axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, rxmode, NULL);
1136
1137 /* Load the multicast filter. */
1138 axe_setmulti(sc);
1139
1140 /* Open RX and TX pipes. */
1141 err = usbd_open_pipe(sc->axe_iface, sc->axe_ed[AXE_ENDPT_RX],
1142 USBD_EXCLUSIVE_USE, &sc->axe_ep[AXE_ENDPT_RX]);
1143 if (err) {
1144 printf("%s: open rx pipe failed: %s\n",
1145 USBDEVNAME(sc->axe_dev), usbd_errstr(err));
1146 splx(s);
1147 return;
1148 }
1149
1150 err = usbd_open_pipe(sc->axe_iface, sc->axe_ed[AXE_ENDPT_TX],
1151 USBD_EXCLUSIVE_USE, &sc->axe_ep[AXE_ENDPT_TX]);
1152 if (err) {
1153 printf("%s: open tx pipe failed: %s\n",
1154 USBDEVNAME(sc->axe_dev), usbd_errstr(err));
1155 splx(s);
1156 return;
1157 }
1158
1159 /* Start up the receive pipe. */
1160 for (i = 0; i < AXE_RX_LIST_CNT; i++) {
1161 c = &sc->axe_cdata.axe_rx_chain[i];
1162 usbd_setup_xfer(c->axe_xfer, sc->axe_ep[AXE_ENDPT_RX],
1163 c, mtod(c->axe_mbuf, char *), AXE_BUFSZ,
1164 USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, axe_rxeof);
1165 usbd_transfer(c->axe_xfer);
1166 }
1167
1168 ifp->if_flags |= IFF_RUNNING;
1169 ifp->if_flags &= ~IFF_OACTIVE;
1170
1171 splx(s);
1172
1173 usb_callout_init(sc->axe_stat_ch);
1174 usb_callout(sc->axe_stat_ch, hz, axe_tick, sc);
1175 return;
1176 }
1177
1178 Static int
1179 axe_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1180 {
1181 struct axe_softc *sc = ifp->if_softc;
1182 struct ifreq *ifr = (struct ifreq *)data;
1183 struct ifaddr *ifa = (struct ifaddr *)data;
1184 struct mii_data *mii;
1185 u_int16_t rxmode;
1186 int error = 0;
1187
1188 switch(cmd) {
1189 case SIOCSIFADDR:
1190 ifp->if_flags |= IFF_UP;
1191 axe_init(sc);
1192
1193 switch (ifa->ifa_addr->sa_family) {
1194 #ifdef INET
1195 case AF_INET:
1196 #if defined(__NetBSD__)
1197 arp_ifinit(ifp, ifa);
1198 #else
1199 arp_ifinit(&sc->arpcom, ifa);
1200 #endif
1201 break;
1202 #endif /* INET */
1203 #ifdef NS
1204 case AF_NS:
1205 {
1206 struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
1207
1208 if (ns_nullhost(*ina))
1209 ina->x_host = *(union ns_host *)
1210 LLADDR(ifp->if_sadl);
1211 else
1212 memcpy(LLADDR(ifp->if_sadl),
1213 ina->x_host.c_host,
1214 ifp->if_addrlen);
1215 break;
1216 }
1217 #endif /* NS */
1218 }
1219 break;
1220
1221 case SIOCSIFMTU:
1222 if (ifr->ifr_mtu > ETHERMTU)
1223 error = EINVAL;
1224 else
1225 ifp->if_mtu = ifr->ifr_mtu;
1226 break;
1227
1228 case SIOCSIFFLAGS:
1229 if (ifp->if_flags & IFF_UP) {
1230 if (ifp->if_flags & IFF_RUNNING &&
1231 ifp->if_flags & IFF_PROMISC &&
1232 !(sc->axe_if_flags & IFF_PROMISC)) {
1233
1234 axe_cmd(sc, AXE_CMD_RXCTL_READ,
1235 0, 0, (void *)&rxmode);
1236 rxmode = le16toh(rxmode) | AXE_RXCMD_PROMISC;
1237 axe_cmd(sc, AXE_CMD_RXCTL_WRITE,
1238 0, rxmode, NULL);
1239
1240 axe_setmulti(sc);
1241 } else if (ifp->if_flags & IFF_RUNNING &&
1242 !(ifp->if_flags & IFF_PROMISC) &&
1243 sc->axe_if_flags & IFF_PROMISC) {
1244 axe_cmd(sc, AXE_CMD_RXCTL_READ,
1245 0, 0, (void *)&rxmode);
1246 rxmode = le16toh(rxmode) & ~AXE_RXCMD_PROMISC;
1247 axe_cmd(sc, AXE_CMD_RXCTL_WRITE,
1248 0, rxmode, NULL);
1249 axe_setmulti(sc);
1250 } else if (!(ifp->if_flags & IFF_RUNNING))
1251 axe_init(sc);
1252 } else {
1253 if (ifp->if_flags & IFF_RUNNING)
1254 axe_stop(sc);
1255 }
1256 sc->axe_if_flags = ifp->if_flags;
1257 error = 0;
1258 break;
1259 case SIOCADDMULTI:
1260 case SIOCDELMULTI:
1261 #ifdef __NetBSD__
1262 error = (cmd == SIOCADDMULTI) ?
1263 ether_addmulti(ifr, &sc->axe_ec) :
1264 ether_delmulti(ifr, &sc->axe_ec);
1265 #else
1266 error = (cmd == SIOCADDMULTI) ?
1267 ether_addmulti(ifr, &sc->arpcom) :
1268 ether_delmulti(ifr, &sc->arpcom);
1269 #endif /* __NetBSD__ */
1270 if (error == ENETRESET) {
1271 /*
1272 * Multicast list has changed; set the hardware
1273 * filter accordingly.
1274 */
1275 if (ifp->if_flags & IFF_RUNNING)
1276 axe_setmulti(sc);
1277 error = 0;
1278 }
1279 break;
1280 case SIOCGIFMEDIA:
1281 case SIOCSIFMEDIA:
1282 mii = GET_MII(sc);
1283 error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd);
1284 break;
1285
1286 default:
1287 error = EINVAL;
1288 break;
1289 }
1290
1291 return(error);
1292 }
1293
1294 /*
1295 * XXX
1296 * You can't call axe_txeof since the USB transfer has not
1297 * completed yet.
1298 */
1299 Static void
1300 axe_watchdog(struct ifnet *ifp)
1301 {
1302 struct axe_softc *sc;
1303 struct axe_chain *c;
1304 usbd_status stat;
1305 int s;
1306
1307 sc = ifp->if_softc;
1308
1309 ifp->if_oerrors++;
1310 printf("%s: watchdog timeout\n", USBDEVNAME(sc->axe_dev));
1311
1312 s = splusb();
1313 c = &sc->axe_cdata.axe_tx_chain[0];
1314 usbd_get_xfer_status(c->axe_xfer, NULL, NULL, NULL, &stat);
1315 axe_txeof(c->axe_xfer, c, stat);
1316
1317 if (ifp->if_snd.ifq_head != NULL)
1318 axe_start(ifp);
1319 splx(s);
1320 }
1321
1322 /*
1323 * Stop the adapter and free any mbufs allocated to the
1324 * RX and TX lists.
1325 */
1326 Static void
1327 axe_stop(struct axe_softc *sc)
1328 {
1329 usbd_status err;
1330 struct ifnet *ifp;
1331 int i;
1332
1333 axe_reset(sc);
1334
1335 ifp = GET_IFP(sc);
1336 ifp->if_timer = 0;
1337
1338 usb_uncallout(sc->axe_stat_ch, axe_tick, sc);
1339
1340 /* Stop transfers. */
1341 if (sc->axe_ep[AXE_ENDPT_RX] != NULL) {
1342 err = usbd_abort_pipe(sc->axe_ep[AXE_ENDPT_RX]);
1343 if (err) {
1344 printf("%s: abort rx pipe failed: %s\n",
1345 USBDEVNAME(sc->axe_dev), usbd_errstr(err));
1346 }
1347 err = usbd_close_pipe(sc->axe_ep[AXE_ENDPT_RX]);
1348 if (err) {
1349 printf("%s: close rx pipe failed: %s\n",
1350 USBDEVNAME(sc->axe_dev), usbd_errstr(err));
1351 }
1352 sc->axe_ep[AXE_ENDPT_RX] = NULL;
1353 }
1354
1355 if (sc->axe_ep[AXE_ENDPT_TX] != NULL) {
1356 err = usbd_abort_pipe(sc->axe_ep[AXE_ENDPT_TX]);
1357 if (err) {
1358 printf("%s: abort tx pipe failed: %s\n",
1359 USBDEVNAME(sc->axe_dev), usbd_errstr(err));
1360 }
1361 err = usbd_close_pipe(sc->axe_ep[AXE_ENDPT_TX]);
1362 if (err) {
1363 printf("%s: close tx pipe failed: %s\n",
1364 USBDEVNAME(sc->axe_dev), usbd_errstr(err));
1365 }
1366 sc->axe_ep[AXE_ENDPT_TX] = NULL;
1367 }
1368
1369 if (sc->axe_ep[AXE_ENDPT_INTR] != NULL) {
1370 err = usbd_abort_pipe(sc->axe_ep[AXE_ENDPT_INTR]);
1371 if (err) {
1372 printf("%s: abort intr pipe failed: %s\n",
1373 USBDEVNAME(sc->axe_dev), usbd_errstr(err));
1374 }
1375 err = usbd_close_pipe(sc->axe_ep[AXE_ENDPT_INTR]);
1376 if (err) {
1377 printf("%s: close intr pipe failed: %s\n",
1378 USBDEVNAME(sc->axe_dev), usbd_errstr(err));
1379 }
1380 sc->axe_ep[AXE_ENDPT_INTR] = NULL;
1381 }
1382
1383 /* Free RX resources. */
1384 for (i = 0; i < AXE_RX_LIST_CNT; i++) {
1385 if (sc->axe_cdata.axe_rx_chain[i].axe_mbuf != NULL) {
1386 m_freem(sc->axe_cdata.axe_rx_chain[i].axe_mbuf);
1387 sc->axe_cdata.axe_rx_chain[i].axe_mbuf = NULL;
1388 }
1389 if (sc->axe_cdata.axe_rx_chain[i].axe_xfer != NULL) {
1390 usbd_free_xfer(sc->axe_cdata.axe_rx_chain[i].axe_xfer);
1391 sc->axe_cdata.axe_rx_chain[i].axe_xfer = NULL;
1392 }
1393 }
1394
1395 /* Free TX resources. */
1396 for (i = 0; i < AXE_TX_LIST_CNT; i++) {
1397 if (sc->axe_cdata.axe_tx_chain[i].axe_mbuf != NULL) {
1398 m_freem(sc->axe_cdata.axe_tx_chain[i].axe_mbuf);
1399 sc->axe_cdata.axe_tx_chain[i].axe_mbuf = NULL;
1400 }
1401 if (sc->axe_cdata.axe_tx_chain[i].axe_xfer != NULL) {
1402 usbd_free_xfer(sc->axe_cdata.axe_tx_chain[i].axe_xfer);
1403 sc->axe_cdata.axe_tx_chain[i].axe_xfer = NULL;
1404 }
1405 }
1406
1407 sc->axe_link = 0;
1408 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
1409 }
1410
1411