if_axe.c revision 1.7.2.1 1 /* $NetBSD: if_axe.c,v 1.7.2.1 2005/11/10 23:56:13 snj 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.7.2.1 2005/11/10 23:56:13 snj 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) ((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 devinfo[1024];
456 char *devname = USBDEVNAME(sc->axe_dev);
457 struct ifnet *ifp;
458 int i, s;
459
460 usbd_devinfo(dev, 0, devinfo, sizeof devinfo);
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), devinfo);
488
489 /* Find endpoints. */
490 for (i = 0; i < id->bNumEndpoints; i++) {
491 ed = usbd_interface2endpoint_descriptor(sc->axe_iface, i);
492 if (!ed) {
493 printf("%s: couldn't get ep %d\n",
494 USBDEVNAME(sc->axe_dev), i);
495 USB_ATTACH_ERROR_RETURN;
496 }
497 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
498 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
499 sc->axe_ed[AXE_ENDPT_RX] = ed->bEndpointAddress;
500 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
501 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
502 sc->axe_ed[AXE_ENDPT_TX] = ed->bEndpointAddress;
503 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
504 UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
505 sc->axe_ed[AXE_ENDPT_INTR] = ed->bEndpointAddress;
506 }
507 }
508
509 s = splnet();
510
511 /*
512 * Get station address.
513 */
514 axe_cmd(sc, AXE_CMD_READ_NODEID, 0, 0, &eaddr);
515
516 /*
517 * Load IPG values and PHY indexes.
518 */
519 axe_cmd(sc, AXE_CMD_READ_IPG012, 0, 0, (void *)&sc->axe_ipgs);
520 axe_cmd(sc, AXE_CMD_READ_PHYID, 0, 0, (void *)&sc->axe_phyaddrs);
521
522 /*
523 * Work around broken adapters that appear to lie about
524 * their PHY addresses.
525 */
526 sc->axe_phyaddrs[0] = sc->axe_phyaddrs[1] = 0xFF;
527
528 /*
529 * An ASIX chip was detected. Inform the world.
530 */
531 printf("%s: Ethernet address %s\n", USBDEVNAME(sc->axe_dev),
532 ether_sprintf(eaddr));
533
534 /* Initialize interface info.*/
535 ifp = GET_IFP(sc);
536 ifp->if_softc = sc;
537 strncpy(ifp->if_xname, devname, IFNAMSIZ);
538 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
539 ifp->if_ioctl = axe_ioctl;
540 ifp->if_start = axe_start;
541
542 ifp->if_watchdog = axe_watchdog;
543
544 /* ifp->if_baudrate = 10000000; */
545 /* ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;*/
546
547 IFQ_SET_READY(&ifp->if_snd);
548
549 /* Initialize MII/media info. */
550 mii = &sc->axe_mii;
551 mii->mii_ifp = ifp;
552 mii->mii_readreg = axe_miibus_readreg;
553 mii->mii_writereg = axe_miibus_writereg;
554 mii->mii_statchg = axe_miibus_statchg;
555 mii->mii_flags = MIIF_AUTOTSLEEP;
556
557 ifmedia_init(&mii->mii_media, 0, axe_ifmedia_upd, axe_ifmedia_sts);
558 mii_attach(self, mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, 0);
559
560 if (LIST_FIRST(&mii->mii_phys) == NULL) {
561 ifmedia_add(&mii->mii_media, IFM_ETHER | IFM_NONE, 0, NULL);
562 ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_NONE);
563 } else
564 ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO);
565
566 /* Attach the interface. */
567 if_attach(ifp);
568 Ether_ifattach(ifp, eaddr);
569 #if NRND > 0
570 rnd_attach_source(&sc->rnd_source, USBDEVNAME(sc->axe_dev),
571 RND_TYPE_NET, 0);
572 #endif
573
574 usb_callout_init(sc->axe_stat_ch);
575
576 sc->axe_attached = 1;
577 splx(s);
578
579 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->axe_udev,
580 USBDEV(sc->axe_dev));
581
582 USB_ATTACH_SUCCESS_RETURN;
583 }
584
585 USB_DETACH(axe)
586 {
587 USB_DETACH_START(axe, sc);
588 int s;
589 struct ifnet *ifp = GET_IFP(sc);
590
591 DPRINTFN(2,("%s: %s: enter\n", USBDEVNAME(sc->axe_dev), __func__));
592
593 /* Detached before attached finished, so just bail out. */
594 if (!sc->axe_attached)
595 return (0);
596
597 usb_uncallout(sc->axe_stat_ch, axe_tick, sc);
598
599 sc->axe_dying = 1;
600
601 ether_ifdetach(ifp);
602
603 if (sc->axe_ep[AXE_ENDPT_TX] != NULL)
604 usbd_abort_pipe(sc->axe_ep[AXE_ENDPT_TX]);
605 if (sc->axe_ep[AXE_ENDPT_RX] != NULL)
606 usbd_abort_pipe(sc->axe_ep[AXE_ENDPT_RX]);
607 if (sc->axe_ep[AXE_ENDPT_INTR] != NULL)
608 usbd_abort_pipe(sc->axe_ep[AXE_ENDPT_INTR]);
609
610 /*
611 * Remove any pending tasks. They cannot be executing because they run
612 * in the same thread as detach.
613 */
614 usb_rem_task(sc->axe_udev, &sc->axe_tick_task);
615 usb_rem_task(sc->axe_udev, &sc->axe_stop_task);
616
617 s = splusb();
618
619 if (--sc->axe_refcnt >= 0) {
620 /* Wait for processes to go away */
621 usb_detach_wait(USBDEV(sc->axe_dev));
622 }
623
624 if (ifp->if_flags & IFF_RUNNING)
625 axe_stop(sc);
626
627 #if defined(__NetBSD__)
628 #if NRND > 0
629 rnd_detach_source(&sc->rnd_source);
630 #endif
631 #endif /* __NetBSD__ */
632 mii_detach(&sc->axe_mii, MII_PHY_ANY, MII_OFFSET_ANY);
633 ifmedia_delete_instance(&sc->axe_mii.mii_media, IFM_INST_ANY);
634 ether_ifdetach(ifp);
635 if_detach(ifp);
636
637 #ifdef DIAGNOSTIC
638 if (sc->axe_ep[AXE_ENDPT_TX] != NULL ||
639 sc->axe_ep[AXE_ENDPT_RX] != NULL ||
640 sc->axe_ep[AXE_ENDPT_INTR] != NULL)
641 printf("%s: detach has active endpoints\n",
642 USBDEVNAME(sc->axe_dev));
643 #endif
644
645 sc->axe_attached = 0;
646
647 if (--sc->axe_refcnt >= 0) {
648 /* Wait for processes to go away. */
649 usb_detach_wait(USBDEV(sc->axe_dev));
650 }
651 splx(s);
652
653 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->axe_udev,
654 USBDEV(sc->axe_dev));
655
656 return (0);
657 }
658
659 int
660 axe_activate(device_ptr_t self, enum devact act)
661 {
662 struct axe_softc *sc = (struct axe_softc *)self;
663
664 DPRINTFN(2,("%s: %s: enter\n", USBDEVNAME(sc->axe_dev), __func__));
665
666 switch (act) {
667 case DVACT_ACTIVATE:
668 return (EOPNOTSUPP);
669 break;
670
671 case DVACT_DEACTIVATE:
672 if_deactivate(&sc->axe_ec.ec_if);
673 sc->axe_dying = 1;
674 break;
675 }
676 return (0);
677 }
678
679 /*
680 * Initialize an RX descriptor and attach an MBUF cluster.
681 */
682 Static int
683 axe_newbuf(struct axe_softc *sc, struct axe_chain *c, struct mbuf *m)
684 {
685 struct mbuf *m_new = NULL;
686
687 DPRINTFN(10,("%s: %s: enter\n", USBDEVNAME(sc->axe_dev),__func__));
688
689 if (m == NULL) {
690 MGETHDR(m_new, M_DONTWAIT, MT_DATA);
691 if (m_new == NULL) {
692 printf("%s: no memory for rx list "
693 "-- packet dropped!\n", USBDEVNAME(sc->axe_dev));
694 return (ENOBUFS);
695 }
696
697 MCLGET(m_new, M_DONTWAIT);
698 if (!(m_new->m_flags & M_EXT)) {
699 printf("%s: no memory for rx list "
700 "-- packet dropped!\n", USBDEVNAME(sc->axe_dev));
701 m_freem(m_new);
702 return (ENOBUFS);
703 }
704 m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
705 } else {
706 m_new = m;
707 m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
708 m_new->m_data = m_new->m_ext.ext_buf;
709 }
710
711 m_adj(m_new, ETHER_ALIGN);
712 c->axe_mbuf = m_new;
713
714 return (0);
715 }
716
717 Static int
718 axe_rx_list_init(struct axe_softc *sc)
719 {
720 struct axe_cdata *cd;
721 struct axe_chain *c;
722 int i;
723
724 DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->axe_dev), __func__));
725
726 cd = &sc->axe_cdata;
727 for (i = 0; i < AXE_RX_LIST_CNT; i++) {
728 c = &cd->axe_rx_chain[i];
729 c->axe_sc = sc;
730 c->axe_idx = i;
731 if (axe_newbuf(sc, c, NULL) == ENOBUFS)
732 return (ENOBUFS);
733 if (c->axe_xfer == NULL) {
734 c->axe_xfer = usbd_alloc_xfer(sc->axe_udev);
735 if (c->axe_xfer == NULL)
736 return (ENOBUFS);
737 c->axe_buf = usbd_alloc_buffer(c->axe_xfer, AXE_BUFSZ);
738 if (c->axe_buf == NULL) {
739 usbd_free_xfer(c->axe_xfer);
740 return (ENOBUFS);
741 }
742 }
743 }
744
745 return (0);
746 }
747
748 Static int
749 axe_tx_list_init(struct axe_softc *sc)
750 {
751 struct axe_cdata *cd;
752 struct axe_chain *c;
753 int i;
754
755 DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->axe_dev), __func__));
756
757 cd = &sc->axe_cdata;
758 for (i = 0; i < AXE_TX_LIST_CNT; i++) {
759 c = &cd->axe_tx_chain[i];
760 c->axe_sc = sc;
761 c->axe_idx = i;
762 c->axe_mbuf = NULL;
763 if (c->axe_xfer == NULL) {
764 c->axe_xfer = usbd_alloc_xfer(sc->axe_udev);
765 if (c->axe_xfer == NULL)
766 return (ENOBUFS);
767 c->axe_buf = usbd_alloc_buffer(c->axe_xfer, AXE_BUFSZ);
768 if (c->axe_buf == NULL) {
769 usbd_free_xfer(c->axe_xfer);
770 return (ENOBUFS);
771 }
772 }
773 }
774
775 return (0);
776 }
777
778 #if 0
779 Static void
780 axe_rxstart(struct ifnet *ifp)
781 {
782 struct axe_softc *sc;
783 struct axe_chain *c;
784
785 sc = ifp->if_softc;
786 axe_lock_mii(sc);
787 c = &sc->axe_cdata.axe_rx_chain[sc->axe_cdata.axe_rx_prod];
788
789 if (axe_newbuf(sc, c, NULL) == ENOBUFS) {
790 ifp->if_ierrors++;
791 axe_unlock_mii(sc);
792 return;
793 }
794
795 /* Setup new transfer. */
796 usbd_setup_xfer(c->axe_xfer, sc->axe_ep[AXE_ENDPT_RX],
797 c, mtod(c->axe_mbuf, char *), AXE_BUFSZ, USBD_SHORT_XFER_OK,
798 USBD_NO_TIMEOUT, axe_rxeof);
799 usbd_transfer(c->axe_xfer);
800 axe_unlock_mii(sc);
801
802 return;
803 }
804 #endif
805
806 /*
807 * A frame has been uploaded: pass the resulting mbuf chain up to
808 * the higher level protocols.
809 */
810 Static void
811 axe_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
812 {
813 struct axe_softc *sc;
814 struct axe_chain *c;
815 struct ifnet *ifp;
816 struct mbuf *m;
817 u_int32_t total_len;
818 int s;
819
820 c = priv;
821 sc = c->axe_sc;
822 ifp = GET_IFP(sc);
823
824 DPRINTFN(10,("%s: %s: enter\n", USBDEVNAME(sc->axe_dev),__func__));
825
826 if (sc->axe_dying)
827 return;
828
829 if (!(ifp->if_flags & IFF_RUNNING))
830 return;
831
832 if (status != USBD_NORMAL_COMPLETION) {
833 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
834 return;
835 if (usbd_ratecheck(&sc->axe_rx_notice)) {
836 printf("%s: usb errors on rx: %s\n",
837 USBDEVNAME(sc->axe_dev), usbd_errstr(status));
838 }
839 if (status == USBD_STALLED)
840 usbd_clear_endpoint_stall(sc->axe_ep[AXE_ENDPT_RX]);
841 goto done;
842 }
843
844 usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
845
846 m = c->axe_mbuf;
847
848 if (total_len <= sizeof(struct ether_header)) {
849 ifp->if_ierrors++;
850 goto done;
851 }
852
853 ifp->if_ipackets++;
854 m->m_pkthdr.rcvif = ifp;
855 m->m_pkthdr.len = m->m_len = total_len;
856
857
858 memcpy(mtod(c->axe_mbuf, char *), c->axe_buf, total_len);
859
860 /* No errors; receive the packet. */
861 total_len -= ETHER_CRC_LEN + 4;
862
863 s = splnet();
864
865 /* XXX ugly */
866 if (axe_newbuf(sc, c, NULL) == ENOBUFS) {
867 ifp->if_ierrors++;
868 goto done1;
869 }
870
871 #if NBPFILTER > 0
872 if (ifp->if_bpf)
873 BPF_MTAP(ifp, m);
874 #endif
875
876 DPRINTFN(10,("%s: %s: deliver %d\n", USBDEVNAME(sc->axe_dev),
877 __func__, m->m_len));
878 IF_INPUT(ifp, m);
879 done1:
880 splx(s);
881
882 done:
883
884 /* Setup new transfer. */
885 usbd_setup_xfer(xfer, sc->axe_ep[AXE_ENDPT_RX],
886 c, c->axe_buf, AXE_BUFSZ,
887 USBD_SHORT_XFER_OK | USBD_NO_COPY,
888 USBD_NO_TIMEOUT, axe_rxeof);
889 usbd_transfer(xfer);
890
891 DPRINTFN(10,("%s: %s: start rx\n", USBDEVNAME(sc->axe_dev),
892 __func__));
893 return;
894 }
895
896 /*
897 * A frame was downloaded to the chip. It's safe for us to clean up
898 * the list buffers.
899 */
900
901 Static void
902 axe_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
903 {
904 struct axe_softc *sc;
905 struct axe_chain *c;
906 struct ifnet *ifp;
907 int s;
908
909 c = priv;
910 sc = c->axe_sc;
911 ifp = GET_IFP(sc);
912
913 if (sc->axe_dying)
914 return;
915
916 s = splnet();
917
918 if (status != USBD_NORMAL_COMPLETION) {
919 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
920 splx(s);
921 return;
922 }
923 ifp->if_oerrors++;
924 printf("%s: usb error on tx: %s\n", USBDEVNAME(sc->axe_dev),
925 usbd_errstr(status));
926 if (status == USBD_STALLED)
927 usbd_clear_endpoint_stall(sc->axe_ep[AXE_ENDPT_TX]);
928 splx(s);
929 return;
930 }
931
932 ifp->if_timer = 0;
933 ifp->if_flags &= ~IFF_OACTIVE;
934
935 m_freem(c->axe_mbuf);
936 c->axe_mbuf = NULL;
937
938 if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
939 axe_start(ifp);
940
941 ifp->if_opackets++;
942 splx(s);
943 return;
944 }
945
946 Static void
947 axe_tick(void *xsc)
948 {
949 struct axe_softc *sc = xsc;
950
951 if (sc == NULL)
952 return;
953
954 DPRINTFN(0xff, ("%s: %s: enter\n", USBDEVNAME(sc->axe_dev),
955 __func__));
956
957 if (sc->axe_dying)
958 return;
959
960 /* Perform periodic stuff in process context */
961 usb_add_task(sc->axe_udev, &sc->axe_tick_task);
962
963 }
964
965 Static void
966 axe_tick_task(void *xsc)
967 {
968 int s;
969 struct axe_softc *sc;
970 struct ifnet *ifp;
971 struct mii_data *mii;
972
973 sc = xsc;
974
975 if (sc == NULL)
976 return;
977
978 if (sc->axe_dying)
979 return;
980
981 ifp = GET_IFP(sc);
982 mii = GET_MII(sc);
983 if (mii == NULL)
984 return;
985
986 s = splnet();
987
988 mii_tick(mii);
989 if (!sc->axe_link) {
990 mii_pollstat(mii);
991 if (mii->mii_media_status & IFM_ACTIVE &&
992 IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) {
993 DPRINTF(("%s: %s: got link\n",
994 USBDEVNAME(sc->axe_dev), __func__));
995 sc->axe_link++;
996 if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
997 axe_start(ifp);
998 }
999 }
1000
1001 usb_callout(sc->axe_stat_ch, hz, axe_tick, sc);
1002
1003 splx(s);
1004 }
1005
1006 Static int
1007 axe_encap(struct axe_softc *sc, struct mbuf *m, int idx)
1008 {
1009 struct axe_chain *c;
1010 usbd_status err;
1011
1012 c = &sc->axe_cdata.axe_tx_chain[idx];
1013
1014 /*
1015 * Copy the mbuf data into a contiguous buffer, leaving two
1016 * bytes at the beginning to hold the frame length.
1017 */
1018 m_copydata(m, 0, m->m_pkthdr.len, c->axe_buf);
1019 c->axe_mbuf = m;
1020
1021 usbd_setup_xfer(c->axe_xfer, sc->axe_ep[AXE_ENDPT_TX],
1022 c, c->axe_buf, m->m_pkthdr.len, USBD_FORCE_SHORT_XFER, 10000,
1023 axe_txeof);
1024
1025 /* Transmit */
1026 err = usbd_transfer(c->axe_xfer);
1027 if (err != USBD_IN_PROGRESS) {
1028 axe_stop(sc);
1029 return(EIO);
1030 }
1031
1032 sc->axe_cdata.axe_tx_cnt++;
1033
1034 return(0);
1035 }
1036
1037 Static void
1038 axe_start(struct ifnet *ifp)
1039 {
1040 struct axe_softc *sc;
1041 struct mbuf *m_head = NULL;
1042
1043 sc = ifp->if_softc;
1044
1045 if (!sc->axe_link) {
1046 return;
1047 }
1048
1049 if (ifp->if_flags & IFF_OACTIVE) {
1050 return;
1051 }
1052
1053 IF_DEQUEUE(&ifp->if_snd, m_head);
1054 if (m_head == NULL) {
1055 return;
1056 }
1057
1058 if (axe_encap(sc, m_head, 0)) {
1059 IF_PREPEND(&ifp->if_snd, m_head);
1060 ifp->if_flags |= IFF_OACTIVE;
1061 return;
1062 }
1063
1064 /*
1065 * If there's a BPF listener, bounce a copy of this frame
1066 * to him.
1067 */
1068 #if NBPFILTER > 0
1069 if (ifp->if_bpf)
1070 BPF_MTAP(ifp, m_head);
1071 #endif
1072
1073 ifp->if_flags |= IFF_OACTIVE;
1074
1075 /*
1076 * Set a timeout in case the chip goes out to lunch.
1077 */
1078 ifp->if_timer = 5;
1079
1080 return;
1081 }
1082
1083 Static void
1084 axe_init(void *xsc)
1085 {
1086 struct axe_softc *sc = xsc;
1087 struct ifnet *ifp = GET_IFP(sc);
1088 struct axe_chain *c;
1089 usbd_status err;
1090 int rxmode;
1091 int i, s;
1092
1093 if (ifp->if_flags & IFF_RUNNING)
1094 return;
1095
1096 s = splnet();
1097
1098 /*
1099 * Cancel pending I/O and free all RX/TX buffers.
1100 */
1101 axe_reset(sc);
1102
1103 /* Enable RX logic. */
1104
1105 /* Init RX ring. */
1106 if (axe_rx_list_init(sc) == ENOBUFS) {
1107 printf("%s: rx list init failed\n", USBDEVNAME(sc->axe_dev));
1108 splx(s);
1109 return;
1110 }
1111
1112 /* Init TX ring. */
1113 if (axe_tx_list_init(sc) == ENOBUFS) {
1114 printf("%s: tx list init failed\n", USBDEVNAME(sc->axe_dev));
1115 splx(s);
1116 return;
1117 }
1118
1119 /* Set transmitter IPG values */
1120 axe_cmd(sc, AXE_CMD_WRITE_IPG0, 0, sc->axe_ipgs[0], NULL);
1121 axe_cmd(sc, AXE_CMD_WRITE_IPG1, 0, sc->axe_ipgs[1], NULL);
1122 axe_cmd(sc, AXE_CMD_WRITE_IPG2, 0, sc->axe_ipgs[2], NULL);
1123
1124 /* Enable receiver, set RX mode */
1125 rxmode = AXE_RXCMD_UNICAST|AXE_RXCMD_MULTICAST|AXE_RXCMD_ENABLE;
1126
1127 /* If we want promiscuous mode, set the allframes bit. */
1128 if (ifp->if_flags & IFF_PROMISC)
1129 rxmode |= AXE_RXCMD_PROMISC;
1130
1131 if (ifp->if_flags & IFF_BROADCAST)
1132 rxmode |= AXE_RXCMD_BROADCAST;
1133
1134 axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, rxmode, NULL);
1135
1136 /* Load the multicast filter. */
1137 axe_setmulti(sc);
1138
1139 /* Open RX and TX pipes. */
1140 err = usbd_open_pipe(sc->axe_iface, sc->axe_ed[AXE_ENDPT_RX],
1141 USBD_EXCLUSIVE_USE, &sc->axe_ep[AXE_ENDPT_RX]);
1142 if (err) {
1143 printf("%s: open rx pipe failed: %s\n",
1144 USBDEVNAME(sc->axe_dev), usbd_errstr(err));
1145 splx(s);
1146 return;
1147 }
1148
1149 err = usbd_open_pipe(sc->axe_iface, sc->axe_ed[AXE_ENDPT_TX],
1150 USBD_EXCLUSIVE_USE, &sc->axe_ep[AXE_ENDPT_TX]);
1151 if (err) {
1152 printf("%s: open tx pipe failed: %s\n",
1153 USBDEVNAME(sc->axe_dev), usbd_errstr(err));
1154 splx(s);
1155 return;
1156 }
1157
1158 /* Start up the receive pipe. */
1159 for (i = 0; i < AXE_RX_LIST_CNT; i++) {
1160 c = &sc->axe_cdata.axe_rx_chain[i];
1161 usbd_setup_xfer(c->axe_xfer, sc->axe_ep[AXE_ENDPT_RX],
1162 c, mtod(c->axe_mbuf, char *), AXE_BUFSZ,
1163 USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, axe_rxeof);
1164 usbd_transfer(c->axe_xfer);
1165 }
1166
1167 ifp->if_flags |= IFF_RUNNING;
1168 ifp->if_flags &= ~IFF_OACTIVE;
1169
1170 splx(s);
1171
1172 usb_callout_init(sc->axe_stat_ch);
1173 usb_callout(sc->axe_stat_ch, hz, axe_tick, sc);
1174 return;
1175 }
1176
1177 Static int
1178 axe_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1179 {
1180 struct axe_softc *sc = ifp->if_softc;
1181 struct ifreq *ifr = (struct ifreq *)data;
1182 struct ifaddr *ifa = (struct ifaddr *)data;
1183 struct mii_data *mii;
1184 u_int16_t rxmode;
1185 int error = 0;
1186
1187 switch(cmd) {
1188 case SIOCSIFADDR:
1189 ifp->if_flags |= IFF_UP;
1190 axe_init(sc);
1191
1192 switch (ifa->ifa_addr->sa_family) {
1193 #ifdef INET
1194 case AF_INET:
1195 #if defined(__NetBSD__)
1196 arp_ifinit(ifp, ifa);
1197 #else
1198 arp_ifinit(&sc->arpcom, ifa);
1199 #endif
1200 break;
1201 #endif /* INET */
1202 #ifdef NS
1203 case AF_NS:
1204 {
1205 struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
1206
1207 if (ns_nullhost(*ina))
1208 ina->x_host = *(union ns_host *)
1209 LLADDR(ifp->if_sadl);
1210 else
1211 memcpy(LLADDR(ifp->if_sadl),
1212 ina->x_host.c_host,
1213 ifp->if_addrlen);
1214 break;
1215 }
1216 #endif /* NS */
1217 }
1218 break;
1219
1220 case SIOCSIFMTU:
1221 if (ifr->ifr_mtu > ETHERMTU)
1222 error = EINVAL;
1223 else
1224 ifp->if_mtu = ifr->ifr_mtu;
1225 break;
1226
1227 case SIOCSIFFLAGS:
1228 if (ifp->if_flags & IFF_UP) {
1229 if (ifp->if_flags & IFF_RUNNING &&
1230 ifp->if_flags & IFF_PROMISC &&
1231 !(sc->axe_if_flags & IFF_PROMISC)) {
1232
1233 axe_cmd(sc, AXE_CMD_RXCTL_READ,
1234 0, 0, (void *)&rxmode);
1235 rxmode = le16toh(rxmode) | AXE_RXCMD_PROMISC;
1236 axe_cmd(sc, AXE_CMD_RXCTL_WRITE,
1237 0, rxmode, NULL);
1238
1239 axe_setmulti(sc);
1240 } else if (ifp->if_flags & IFF_RUNNING &&
1241 !(ifp->if_flags & IFF_PROMISC) &&
1242 sc->axe_if_flags & IFF_PROMISC) {
1243 axe_cmd(sc, AXE_CMD_RXCTL_READ,
1244 0, 0, (void *)&rxmode);
1245 rxmode = le16toh(rxmode) & ~AXE_RXCMD_PROMISC;
1246 axe_cmd(sc, AXE_CMD_RXCTL_WRITE,
1247 0, rxmode, NULL);
1248 axe_setmulti(sc);
1249 } else if (!(ifp->if_flags & IFF_RUNNING))
1250 axe_init(sc);
1251 } else {
1252 if (ifp->if_flags & IFF_RUNNING)
1253 axe_stop(sc);
1254 }
1255 sc->axe_if_flags = ifp->if_flags;
1256 error = 0;
1257 break;
1258 case SIOCADDMULTI:
1259 case SIOCDELMULTI:
1260 #ifdef __NetBSD__
1261 error = (cmd == SIOCADDMULTI) ?
1262 ether_addmulti(ifr, &sc->axe_ec) :
1263 ether_delmulti(ifr, &sc->axe_ec);
1264 #else
1265 error = (cmd == SIOCADDMULTI) ?
1266 ether_addmulti(ifr, &sc->arpcom) :
1267 ether_delmulti(ifr, &sc->arpcom);
1268 #endif /* __NetBSD__ */
1269 if (error == ENETRESET) {
1270 /*
1271 * Multicast list has changed; set the hardware
1272 * filter accordingly.
1273 */
1274 if (ifp->if_flags & IFF_RUNNING)
1275 axe_setmulti(sc);
1276 error = 0;
1277 }
1278 break;
1279 case SIOCGIFMEDIA:
1280 case SIOCSIFMEDIA:
1281 mii = GET_MII(sc);
1282 error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd);
1283 break;
1284
1285 default:
1286 error = EINVAL;
1287 break;
1288 }
1289
1290 return(error);
1291 }
1292
1293 /*
1294 * XXX
1295 * You can't call axe_txeof since the USB transfer has not
1296 * completed yet.
1297 */
1298 Static void
1299 axe_watchdog(struct ifnet *ifp)
1300 {
1301 struct axe_softc *sc;
1302 struct axe_chain *c;
1303 usbd_status stat;
1304 int s;
1305
1306 sc = ifp->if_softc;
1307
1308 ifp->if_oerrors++;
1309 printf("%s: watchdog timeout\n", USBDEVNAME(sc->axe_dev));
1310
1311 s = splusb();
1312 c = &sc->axe_cdata.axe_tx_chain[0];
1313 usbd_get_xfer_status(c->axe_xfer, NULL, NULL, NULL, &stat);
1314 axe_txeof(c->axe_xfer, c, stat);
1315
1316 if (ifp->if_snd.ifq_head != NULL)
1317 axe_start(ifp);
1318 splx(s);
1319 }
1320
1321 /*
1322 * Stop the adapter and free any mbufs allocated to the
1323 * RX and TX lists.
1324 */
1325 Static void
1326 axe_stop(struct axe_softc *sc)
1327 {
1328 usbd_status err;
1329 struct ifnet *ifp;
1330 int i;
1331
1332 axe_reset(sc);
1333
1334 ifp = GET_IFP(sc);
1335 ifp->if_timer = 0;
1336
1337 usb_uncallout(sc->axe_stat_ch, axe_tick, sc);
1338
1339 /* Stop transfers. */
1340 if (sc->axe_ep[AXE_ENDPT_RX] != NULL) {
1341 err = usbd_abort_pipe(sc->axe_ep[AXE_ENDPT_RX]);
1342 if (err) {
1343 printf("%s: abort rx pipe failed: %s\n",
1344 USBDEVNAME(sc->axe_dev), usbd_errstr(err));
1345 }
1346 err = usbd_close_pipe(sc->axe_ep[AXE_ENDPT_RX]);
1347 if (err) {
1348 printf("%s: close rx pipe failed: %s\n",
1349 USBDEVNAME(sc->axe_dev), usbd_errstr(err));
1350 }
1351 sc->axe_ep[AXE_ENDPT_RX] = NULL;
1352 }
1353
1354 if (sc->axe_ep[AXE_ENDPT_TX] != NULL) {
1355 err = usbd_abort_pipe(sc->axe_ep[AXE_ENDPT_TX]);
1356 if (err) {
1357 printf("%s: abort tx pipe failed: %s\n",
1358 USBDEVNAME(sc->axe_dev), usbd_errstr(err));
1359 }
1360 err = usbd_close_pipe(sc->axe_ep[AXE_ENDPT_TX]);
1361 if (err) {
1362 printf("%s: close tx pipe failed: %s\n",
1363 USBDEVNAME(sc->axe_dev), usbd_errstr(err));
1364 }
1365 sc->axe_ep[AXE_ENDPT_TX] = NULL;
1366 }
1367
1368 if (sc->axe_ep[AXE_ENDPT_INTR] != NULL) {
1369 err = usbd_abort_pipe(sc->axe_ep[AXE_ENDPT_INTR]);
1370 if (err) {
1371 printf("%s: abort intr pipe failed: %s\n",
1372 USBDEVNAME(sc->axe_dev), usbd_errstr(err));
1373 }
1374 err = usbd_close_pipe(sc->axe_ep[AXE_ENDPT_INTR]);
1375 if (err) {
1376 printf("%s: close intr pipe failed: %s\n",
1377 USBDEVNAME(sc->axe_dev), usbd_errstr(err));
1378 }
1379 sc->axe_ep[AXE_ENDPT_INTR] = NULL;
1380 }
1381
1382 /* Free RX resources. */
1383 for (i = 0; i < AXE_RX_LIST_CNT; i++) {
1384 if (sc->axe_cdata.axe_rx_chain[i].axe_mbuf != NULL) {
1385 m_freem(sc->axe_cdata.axe_rx_chain[i].axe_mbuf);
1386 sc->axe_cdata.axe_rx_chain[i].axe_mbuf = NULL;
1387 }
1388 if (sc->axe_cdata.axe_rx_chain[i].axe_xfer != NULL) {
1389 usbd_free_xfer(sc->axe_cdata.axe_rx_chain[i].axe_xfer);
1390 sc->axe_cdata.axe_rx_chain[i].axe_xfer = NULL;
1391 }
1392 }
1393
1394 /* Free TX resources. */
1395 for (i = 0; i < AXE_TX_LIST_CNT; i++) {
1396 if (sc->axe_cdata.axe_tx_chain[i].axe_mbuf != NULL) {
1397 m_freem(sc->axe_cdata.axe_tx_chain[i].axe_mbuf);
1398 sc->axe_cdata.axe_tx_chain[i].axe_mbuf = NULL;
1399 }
1400 if (sc->axe_cdata.axe_tx_chain[i].axe_xfer != NULL) {
1401 usbd_free_xfer(sc->axe_cdata.axe_tx_chain[i].axe_xfer);
1402 sc->axe_cdata.axe_tx_chain[i].axe_xfer = NULL;
1403 }
1404 }
1405
1406 sc->axe_link = 0;
1407 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
1408 }
1409
1410