Do a major clean-up of the BUSDMA architecture. A large number of
[dragonfly.git] / sys / dev / netif / rue / if_rue.c
CommitLineData
3c374c15
SZ
1/*-
2 * Copyright (c) 2001-2003, Shunsuke Akiyama <akiyama@FreeBSD.org>.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26/*-
27 * Copyright (c) 1997, 1998, 1999, 2000
28 * Bill Paul <wpaul@ee.columbia.edu>. All rights reserved.
29 *
30 * Redistribution and use in source and binary forms, with or without
31 * modification, are permitted provided that the following conditions
32 * are met:
33 * 1. Redistributions of source code must retain the above copyright
34 * notice, this list of conditions and the following disclaimer.
35 * 2. Redistributions in binary form must reproduce the above copyright
36 * notice, this list of conditions and the following disclaimer in the
37 * documentation and/or other materials provided with the distribution.
38 * 3. All advertising materials mentioning features or use of this software
39 * must display the following acknowledgement:
40 * This product includes software developed by Bill Paul.
41 * 4. Neither the name of the author nor the names of any co-contributors
42 * may be used to endorse or promote products derived from this software
43 * without specific prior written permission.
44 *
45 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
49 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
50 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
51 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
52 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
53 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
54 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
55 * THE POSSIBILITY OF SUCH DAMAGE.
56 *
57 * $FreeBSD: src/sys/dev/usb/if_rue.c,v 1.14 2004/06/09 14:34:03 naddy Exp $
1f7ab7c9 58 * $DragonFly: src/sys/dev/netif/rue/if_rue.c,v 1.7 2006/10/25 20:55:58 dillon Exp $
3c374c15
SZ
59 */
60
61/*
62 * RealTek RTL8150 USB to fast ethernet controller driver.
63 * Datasheet is available from
64 * ftp://ftp.realtek.com.tw/lancard/data_sheet/8150/.
65 */
66
67#include <sys/param.h>
68#include <sys/systm.h>
69#include <sys/sockio.h>
70#include <sys/mbuf.h>
71#include <sys/malloc.h>
72#include <sys/kernel.h>
73#include <sys/module.h>
74#include <sys/socket.h>
75#include <sys/sysctl.h>
1f7ab7c9 76#include <sys/bus.h>
3c374c15
SZ
77
78#include <net/if.h>
79#include <net/if_arp.h>
80#include <net/ethernet.h>
81#include <net/if_dl.h>
82#include <net/if_media.h>
83#include <net/ifq_var.h>
84
85#include <net/bpf.h>
86
3c374c15
SZ
87#include <bus/usb/usb.h>
88#include <bus/usb/usbdi.h>
89#include <bus/usb/usbdi_util.h>
90#include <bus/usb/usbdivar.h>
91#include <bus/usb/usbdevs.h>
92#include <bus/usb/usb_ethersubr.h>
93
94#include <dev/netif/mii_layer/mii.h>
95#include <dev/netif/mii_layer/miivar.h>
96
97#include <dev/netif/rue/if_ruereg.h>
98
99#include "miibus_if.h"
100
101#ifdef RUE_DEBUG
102SYSCTL_NODE(_hw, OID_AUTO, rue, CTLFLAG_RW, 0, "USB rue");
103
104Static int rue_debug = 0;
105SYSCTL_INT(_hw_rue, OID_AUTO, debug, CTLFLAG_RW, &rue_debug, 0,
106 "rue debug level");
107
108/* XXX DPRINTF/DPRINTFN can be used only after rue_attach() */
109#define DPRINTFN(n, x) do { if (rue_debug > (n)) if_printf x; } while (0)
110#else
111#define DPRINTFN(n, x)
112#endif
113#define DPRINTF(x) DPRINTFN(0, x)
114
115/*
116 * Various supported device vendors/products.
117 */
118
119Static struct rue_type rue_devs[] = {
120 { USB_VENDOR_MELCO, USB_PRODUCT_MELCO_LUAKTX },
121 { USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_USBKR100 },
122 { 0, 0 }
123};
124
125Static int rue_match(device_ptr_t);
126Static int rue_attach(device_ptr_t);
127Static int rue_detach(device_ptr_t);
128
129Static int rue_tx_list_init(struct rue_softc *);
130Static int rue_rx_list_init(struct rue_softc *);
131Static int rue_newbuf(struct rue_softc *, struct rue_chain *, struct mbuf *);
132Static int rue_encap(struct rue_softc *, struct mbuf *, int);
133#ifdef RUE_INTR_PIPE
134Static void rue_intr(usbd_xfer_handle, usbd_private_handle, usbd_status);
135#endif
136Static void rue_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
137Static void rue_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
138Static void rue_tick(void *);
139Static void rue_rxstart(struct ifnet *);
140Static void rue_start(struct ifnet *);
141Static int rue_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *);
142Static void rue_init(void *);
143Static void rue_stop(struct rue_softc *);
144Static void rue_watchdog(struct ifnet *);
145Static void rue_shutdown(device_ptr_t);
146Static int rue_ifmedia_upd(struct ifnet *);
147Static void rue_ifmedia_sts(struct ifnet *, struct ifmediareq *);
148
149Static int rue_miibus_readreg(device_ptr_t, int, int);
150Static int rue_miibus_writereg(device_ptr_t, int, int, int);
151Static void rue_miibus_statchg(device_ptr_t);
152
153Static void rue_setmulti(struct rue_softc *);
154Static void rue_reset(struct rue_softc *);
155
156Static int rue_read_mem(struct rue_softc *, u_int16_t, void *, u_int16_t);
157Static int rue_write_mem(struct rue_softc *, u_int16_t, void *, u_int16_t);
158Static int rue_csr_read_1(struct rue_softc *, int);
159Static int rue_csr_write_1(struct rue_softc *, int, u_int8_t);
160Static int rue_csr_read_2(struct rue_softc *, int);
161Static int rue_csr_write_2(struct rue_softc *, int, u_int16_t);
162Static int rue_csr_write_4(struct rue_softc *, int, u_int32_t);
163
164Static device_method_t rue_methods[] = {
165 /* Device interface */
166 DEVMETHOD(device_probe, rue_match),
167 DEVMETHOD(device_attach, rue_attach),
168 DEVMETHOD(device_detach, rue_detach),
169 DEVMETHOD(device_shutdown, rue_shutdown),
170
171 /* Bus interface */
172 DEVMETHOD(bus_print_child, bus_generic_print_child),
173 DEVMETHOD(bus_driver_added, bus_generic_driver_added),
174
175 /* MII interface */
176 DEVMETHOD(miibus_readreg, rue_miibus_readreg),
177 DEVMETHOD(miibus_writereg, rue_miibus_writereg),
178 DEVMETHOD(miibus_statchg, rue_miibus_statchg),
179
180 { 0, 0 }
181};
182
183Static driver_t rue_driver = {
184 "rue",
185 rue_methods,
186 sizeof(struct rue_softc)
187};
188
189Static devclass_t rue_devclass;
190
191DRIVER_MODULE(rue, uhub, rue_driver, rue_devclass, usbd_driver_load, 0);
192DRIVER_MODULE(miibus, rue, miibus_driver, miibus_devclass, 0, 0);
193MODULE_DEPEND(rue, usb, 1, 1, 1);
194MODULE_DEPEND(rue, miibus, 1, 1, 1);
195
196#define RUE_SETBIT(sc, reg, x) \
197 rue_csr_write_1(sc, reg, rue_csr_read_1(sc, reg) | (x))
198
199#define RUE_CLRBIT(sc, reg, x) \
200 rue_csr_write_1(sc, reg, rue_csr_read_1(sc, reg) & ~(x))
201
202#define RUE_SETBIT_2(sc, reg, x) \
203 rue_csr_write_2(sc, reg, rue_csr_read_2(sc, reg) | (x))
204
205#define RUE_CLRBIT_2(sc, reg, x) \
206 rue_csr_write_2(sc, reg, rue_csr_read_2(sc, reg) & ~(x))
207
208Static int
209rue_read_mem(struct rue_softc *sc, u_int16_t addr, void *buf, u_int16_t len)
210{
211 usb_device_request_t req;
212 usbd_status err;
213
214 if (sc->rue_dying)
215 return (0);
216
217 RUE_LOCK(sc);
218
219 req.bmRequestType = UT_READ_VENDOR_DEVICE;
220 req.bRequest = UR_SET_ADDRESS;
221 USETW(req.wValue, addr);
222 USETW(req.wIndex, 0);
223 USETW(req.wLength, len);
224
225 err = usbd_do_request(sc->rue_udev, &req, buf);
226
227 RUE_UNLOCK(sc);
228
229 if (err) {
230 if_printf(&sc->arpcom.ac_if, "control pipe read failed: %s\n",
231 usbd_errstr(err));
232 return (-1);
233 }
234
235 return (0);
236}
237
238Static int
239rue_write_mem(struct rue_softc *sc, u_int16_t addr, void *buf, u_int16_t len)
240{
241 usb_device_request_t req;
242 usbd_status err;
243
244 if (sc->rue_dying)
245 return (0);
246
247 RUE_LOCK(sc);
248
249 req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
250 req.bRequest = UR_SET_ADDRESS;
251 USETW(req.wValue, addr);
252 USETW(req.wIndex, 0);
253 USETW(req.wLength, len);
254
255 err = usbd_do_request(sc->rue_udev, &req, buf);
256
257 RUE_UNLOCK(sc);
258
259 if (err) {
260 if_printf(&sc->arpcom.ac_if, "control pipe write failed: %s\n",
261 usbd_errstr(err));
262 return (-1);
263 }
264
265 return (0);
266}
267
268Static int
269rue_csr_read_1(struct rue_softc *sc, int reg)
270{
271 int err;
272 u_int8_t val = 0;
273
274 err = rue_read_mem(sc, reg, &val, 1);
275
276 if (err)
277 return (0);
278
279 return (val);
280}
281
282Static int
283rue_csr_read_2(struct rue_softc *sc, int reg)
284{
285 int err;
286 u_int16_t val = 0;
287 uWord w;
288
289 USETW(w, val);
290 err = rue_read_mem(sc, reg, &w, 2);
291 val = UGETW(w);
292
293 if (err)
294 return (0);
295
296 return (val);
297}
298
299Static int
300rue_csr_write_1(struct rue_softc *sc, int reg, u_int8_t val)
301{
302 int err;
303
304 err = rue_write_mem(sc, reg, &val, 1);
305
306 if (err)
307 return (-1);
308
309 return (0);
310}
311
312Static int
313rue_csr_write_2(struct rue_softc *sc, int reg, u_int16_t val)
314{
315 int err;
316 uWord w;
317
318 USETW(w, val);
319 err = rue_write_mem(sc, reg, &w, 2);
320
321 if (err)
322 return (-1);
323
324 return (0);
325}
326
327Static int
328rue_csr_write_4(struct rue_softc *sc, int reg, u_int32_t val)
329{
330 int err;
331 uDWord dw;
332
333 USETDW(dw, val);
334 err = rue_write_mem(sc, reg, &dw, 4);
335
336 if (err)
337 return (-1);
338
339 return (0);
340}
341
342Static int
343rue_miibus_readreg(device_ptr_t dev, int phy, int reg)
344{
345 struct rue_softc *sc = USBGETSOFTC(dev);
346 int rval;
347 int ruereg;
348
349 if (phy != 0) /* RTL8150 supports PHY == 0, only */
350 return (0);
351
352 switch (reg) {
353 case MII_BMCR:
354 ruereg = RUE_BMCR;
355 break;
356 case MII_BMSR:
357 ruereg = RUE_BMSR;
358 break;
359 case MII_ANAR:
360 ruereg = RUE_ANAR;
361 break;
362 case MII_ANER:
363 ruereg = RUE_AER;
364 break;
365 case MII_ANLPAR:
366 ruereg = RUE_ANLP;
367 break;
368 case MII_PHYIDR1:
369 case MII_PHYIDR2:
370 return (0);
371 break;
372 default:
373 if (RUE_REG_MIN <= reg && reg <= RUE_REG_MAX) {
374 rval = rue_csr_read_1(sc, reg);
375 return (rval);
376 }
377 if_printf(&sc->arpcom.ac_if, "bad phy register\n");
378 return (0);
379 }
380
381 rval = rue_csr_read_2(sc, ruereg);
382
383 return (rval);
384}
385
386Static int
387rue_miibus_writereg(device_ptr_t dev, int phy, int reg, int data)
388{
389 struct rue_softc *sc = USBGETSOFTC(dev);
390 int ruereg;
391
392 if (phy != 0) /* RTL8150 supports PHY == 0, only */
393 return (0);
394
395 switch (reg) {
396 case MII_BMCR:
397 ruereg = RUE_BMCR;
398 break;
399 case MII_BMSR:
400 ruereg = RUE_BMSR;
401 break;
402 case MII_ANAR:
403 ruereg = RUE_ANAR;
404 break;
405 case MII_ANER:
406 ruereg = RUE_AER;
407 break;
408 case MII_ANLPAR:
409 ruereg = RUE_ANLP;
410 break;
411 case MII_PHYIDR1:
412 case MII_PHYIDR2:
413 return (0);
414 break;
415 default:
416 if (RUE_REG_MIN <= reg && reg <= RUE_REG_MAX) {
417 rue_csr_write_1(sc, reg, data);
418 return (0);
419 }
420 if_printf(&sc->arpcom.ac_if, "bad phy register\n");
421 return (0);
422 }
423 rue_csr_write_2(sc, ruereg, data);
424
425 return (0);
426}
427
428Static void
429rue_miibus_statchg(device_ptr_t dev)
430{
3c374c15
SZ
431}
432
433/*
434 * Program the 64-bit multicast hash filter.
435 */
436
437Static void
438rue_setmulti(struct rue_softc *sc)
439{
440 struct ifnet *ifp;
441 int h = 0;
442 u_int32_t hashes[2] = { 0, 0 };
443 struct ifmultiaddr *ifma;
444 u_int32_t rxcfg;
445 int mcnt = 0;
446
447 ifp = &sc->arpcom.ac_if;
448
449 rxcfg = rue_csr_read_2(sc, RUE_RCR);
450
451 if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
452 rxcfg |= (RUE_RCR_AAM | RUE_RCR_AAP);
453 rxcfg &= ~RUE_RCR_AM;
454 rue_csr_write_2(sc, RUE_RCR, rxcfg);
455 rue_csr_write_4(sc, RUE_MAR0, 0xFFFFFFFF);
456 rue_csr_write_4(sc, RUE_MAR4, 0xFFFFFFFF);
457 return;
458 }
459
460 /* first, zot all the existing hash bits */
461 rue_csr_write_4(sc, RUE_MAR0, 0);
462 rue_csr_write_4(sc, RUE_MAR4, 0);
463
464 /* now program new ones */
465 LIST_FOREACH (ifma, &ifp->if_multiaddrs, ifma_link) {
466 if (ifma->ifma_addr->sa_family != AF_LINK)
467 continue;
468 h = ether_crc32_be(LLADDR((struct sockaddr_dl *)
469 ifma->ifma_addr), ETHER_ADDR_LEN) >> 26;
470 if (h < 32)
471 hashes[0] |= (1 << h);
472 else
473 hashes[1] |= (1 << (h - 32));
474 mcnt++;
475 }
476
477 if (mcnt)
478 rxcfg |= RUE_RCR_AM;
479 else
480 rxcfg &= ~RUE_RCR_AM;
481
482 rxcfg &= ~(RUE_RCR_AAM | RUE_RCR_AAP);
483
484 rue_csr_write_2(sc, RUE_RCR, rxcfg);
485 rue_csr_write_4(sc, RUE_MAR0, hashes[0]);
486 rue_csr_write_4(sc, RUE_MAR4, hashes[1]);
487}
488
489Static void
490rue_reset(struct rue_softc *sc)
491{
492 int i;
493
494 rue_csr_write_1(sc, RUE_CR, RUE_CR_SOFT_RST);
495
496 for (i = 0; i < RUE_TIMEOUT; i++) {
497 DELAY(500);
498 if (!(rue_csr_read_1(sc, RUE_CR) & RUE_CR_SOFT_RST))
499 break;
500 }
501 if (i == RUE_TIMEOUT)
502 if_printf(&sc->arpcom.ac_if, "reset never completed!\n");
503
504 DELAY(10000);
505}
506
507/*
508 * Probe for a RTL8150 chip.
509 */
510
511USB_MATCH(rue)
512{
513 USB_MATCH_START(rue, uaa);
514 struct rue_type *t;
515
516 if (uaa->iface == NULL)
517 return (UMATCH_NONE);
518
519 t = rue_devs;
520 while (t->rue_vid) {
521 if (uaa->vendor == t->rue_vid &&
522 uaa->product == t->rue_did) {
523 return (UMATCH_VENDOR_PRODUCT);
524 }
525 t++;
526 }
527
528 return (UMATCH_NONE);
529}
530
531/*
532 * Attach the interface. Allocate softc structures, do ifmedia
533 * setup and ethernet/BPF attach.
534 */
535
536USB_ATTACH(rue)
537{
538 USB_ATTACH_START(rue, sc, uaa);
539 char devinfo[1024];
540 uint8_t eaddr[ETHER_ADDR_LEN];
541 struct ifnet *ifp;
542 usb_interface_descriptor_t *id;
543 usb_endpoint_descriptor_t *ed;
544 int i;
545
546 sc->rue_udev = uaa->device;
547
548 if (usbd_set_config_no(sc->rue_udev, RUE_CONFIG_NO, 0)) {
549 device_printf(self, "setting config no %d failed\n",
550 RUE_CONFIG_NO);
551 USB_ATTACH_ERROR_RETURN;
552 }
553
554 if (usbd_device2interface_handle(uaa->device, RUE_IFACE_IDX,
555 &sc->rue_iface)) {
556 device_printf(self, "getting interface handle failed\n");
557 USB_ATTACH_ERROR_RETURN;
558 }
559
560 id = usbd_get_interface_descriptor(sc->rue_iface);
561
562 usbd_devinfo(uaa->device, 0, devinfo);
563 device_set_desc_copy(self, devinfo);
564 device_printf(self, "%s\n", devinfo);
565
566 /* Find endpoints */
567 for (i = 0; i < id->bNumEndpoints; i++) {
568 ed = usbd_interface2endpoint_descriptor(sc->rue_iface, i);
569 if (ed == NULL) {
570 device_printf(self, "couldn't get ep %d\n", i);
571 USB_ATTACH_ERROR_RETURN;
572 }
573 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
574 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
575 sc->rue_ed[RUE_ENDPT_RX] = ed->bEndpointAddress;
576 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
577 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
578 sc->rue_ed[RUE_ENDPT_TX] = ed->bEndpointAddress;
579 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
580 UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
581 sc->rue_ed[RUE_ENDPT_INTR] = ed->bEndpointAddress;
582 }
583 }
584
585 ifp = &sc->arpcom.ac_if;
586 if_initname(ifp, device_get_name(self), device_get_unit(self));
587
588 /* Reset the adapter */
589 rue_reset(sc);
590
591 /* Get station address from the EEPROM */
592 if (rue_read_mem(sc, RUE_EEPROM_IDR0, eaddr, ETHER_ADDR_LEN)) {
593 device_printf(self, "couldn't get station address\n");
594 USB_ATTACH_ERROR_RETURN;
595 }
596
597 ifp->if_softc = sc;
598 ifp->if_mtu = ETHERMTU;
599 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
600 ifp->if_ioctl = rue_ioctl;
601 ifp->if_start = rue_start;
602 ifp->if_watchdog = rue_watchdog;
603 ifp->if_init = rue_init;
604 ifp->if_baudrate = 10000000;
605 ifq_set_maxlen(&ifp->if_snd, IFQ_MAXLEN);
606 ifq_set_ready(&ifp->if_snd);
607
608 /* MII setup */
609 if (mii_phy_probe(self, &sc->rue_miibus,
610 rue_ifmedia_upd, rue_ifmedia_sts)) {
611 device_printf(self, "MII without any PHY!\n");
612 USB_ATTACH_ERROR_RETURN;
613 }
614
615 /* Call MI attach routine */
78195a76 616 ether_ifattach(ifp, eaddr, NULL);
3c374c15
SZ
617
618 callout_init(&sc->rue_stat_ch);
619 sc->rue_dying = 0;
620
621 usb_register_netisr();
622
623 USB_ATTACH_SUCCESS_RETURN;
624}
625
626Static int
627rue_detach(device_ptr_t dev)
628{
629 struct rue_softc *sc;
630 struct ifnet *ifp;
631
632 sc = device_get_softc(dev);
633 RUE_LOCK(sc);
634 ifp = &sc->arpcom.ac_if;
635
636 sc->rue_dying = 1;
637 callout_stop(&sc->rue_stat_ch);
638
639 ether_ifdetach(ifp);
640
641 if (sc->rue_ep[RUE_ENDPT_TX] != NULL)
642 usbd_abort_pipe(sc->rue_ep[RUE_ENDPT_TX]);
643 if (sc->rue_ep[RUE_ENDPT_RX] != NULL)
644 usbd_abort_pipe(sc->rue_ep[RUE_ENDPT_RX]);
645#ifdef RUE_INTR_PIPE
646 if (sc->rue_ep[RUE_ENDPT_INTR] != NULL)
647 usbd_abort_pipe(sc->rue_ep[RUE_ENDPT_INTR]);
648#endif
649
650 RUE_UNLOCK(sc);
651
652 return (0);
653}
654
655/*
656 * Initialize an RX descriptor and attach an MBUF cluster.
657 */
658
659Static int
660rue_newbuf(struct rue_softc *sc, struct rue_chain *c, struct mbuf *m)
661{
662 struct mbuf *m_new = NULL;
663
664 if (m == NULL) {
665 m_new = m_getcl(MB_DONTWAIT, MT_DATA, M_PKTHDR);
666 if (m_new == NULL) {
667 if_printf(&sc->arpcom.ac_if, "no memory for rx list "
668 "-- packet dropped!\n");
669 return (ENOBUFS);
670 }
671 m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
672 } else {
673 m_new = m;
674 m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
675 m_new->m_data = m_new->m_ext.ext_buf;
676 }
677
678 m_adj(m_new, ETHER_ALIGN);
679 c->rue_mbuf = m_new;
680
681 return (0);
682}
683
684Static int
685rue_rx_list_init(struct rue_softc *sc)
686{
687 struct rue_cdata *cd;
688 struct rue_chain *c;
689 int i;
690
691 cd = &sc->rue_cdata;
692 for (i = 0; i < RUE_RX_LIST_CNT; i++) {
693 c = &cd->rue_rx_chain[i];
694 c->rue_sc = sc;
695 c->rue_idx = i;
696 if (rue_newbuf(sc, c, NULL) == ENOBUFS)
697 return (ENOBUFS);
698 if (c->rue_xfer == NULL) {
699 c->rue_xfer = usbd_alloc_xfer(sc->rue_udev);
700 if (c->rue_xfer == NULL)
701 return (ENOBUFS);
702 }
703 }
704
705 return (0);
706}
707
708Static int
709rue_tx_list_init(struct rue_softc *sc)
710{
711 struct rue_cdata *cd;
712 struct rue_chain *c;
713 int i;
714
715 cd = &sc->rue_cdata;
716 for (i = 0; i < RUE_TX_LIST_CNT; i++) {
717 c = &cd->rue_tx_chain[i];
718 c->rue_sc = sc;
719 c->rue_idx = i;
720 c->rue_mbuf = NULL;
721 if (c->rue_xfer == NULL) {
722 c->rue_xfer = usbd_alloc_xfer(sc->rue_udev);
723 if (c->rue_xfer == NULL)
724 return (ENOBUFS);
725 }
efda3bd0 726 c->rue_buf = kmalloc(RUE_BUFSZ, M_USBDEV, M_WAITOK);
3c374c15
SZ
727 }
728
729 return (0);
730}
731
732#ifdef RUE_INTR_PIPE
733Static void
734rue_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
735{
736 struct rue_softc *sc = priv;
737 struct ifnet *ifp;
738 struct rue_intrpkt *p;
739
740 RUE_LOCK(sc);
741 ifp = &sc->arpcom.ac_if;
742
743 if (!(ifp->if_flags & IFF_RUNNING)) {
744 RUE_UNLOCK(sc);
745 return;
746 }
747
748 if (status != USBD_NORMAL_COMPLETION) {
749 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
750 RUE_UNLOCK(sc);
751 return;
752 }
753 if_printf(ifp, "usb error on intr: %s\n", usbd_errstr(status));
754 if (status == USBD_STALLED)
755 usbd_clear_endpoint_stall(sc->rue_ep[RUE_ENDPT_INTR]);
756 RUE_UNLOCK(sc);
757 return;
758 }
759
760 usbd_get_xfer_status(xfer, NULL, (void **)&p, NULL, NULL);
761
762 ifp->if_ierrors += p->rue_rxlost_cnt;
763 ifp->if_ierrors += p->rue_crcerr_cnt;
764 ifp->if_collisions += p->rue_col_cnt;
765
766 RUE_UNLOCK(sc);
767}
768#endif
769
770Static void
771rue_rxstart(struct ifnet *ifp)
772{
773 struct rue_softc *sc;
774 struct rue_chain *c;
775
776 sc = ifp->if_softc;
777 RUE_LOCK(sc);
778 c = &sc->rue_cdata.rue_rx_chain[sc->rue_cdata.rue_rx_prod];
779
780 if (rue_newbuf(sc, c, NULL) == ENOBUFS) {
781 ifp->if_ierrors++;
782 RUE_UNLOCK(sc);
783 return;
784 }
785
786 /* Setup new transfer. */
787 usbd_setup_xfer(c->rue_xfer, sc->rue_ep[RUE_ENDPT_RX],
788 c, mtod(c->rue_mbuf, char *), RUE_BUFSZ, USBD_SHORT_XFER_OK,
789 USBD_NO_TIMEOUT, rue_rxeof);
790 usbd_transfer(c->rue_xfer);
791
792 RUE_UNLOCK(sc);
793}
794
795/*
796 * A frame has been uploaded: pass the resulting mbuf chain up to
797 * the higher level protocols.
798 */
799
800Static void
801rue_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
802{
803 struct rue_chain *c = priv;
804 struct rue_softc *sc = c->rue_sc;
805 struct mbuf *m;
806 struct ifnet *ifp;
807 int total_len = 0;
808 struct rue_rxpkt r;
809
810 if (sc->rue_dying)
811 return;
812 RUE_LOCK(sc);
813 ifp = &sc->arpcom.ac_if;
814
815 if (!(ifp->if_flags & IFF_RUNNING)) {
816 RUE_UNLOCK(sc);
817 return;
818 }
819
820 if (status != USBD_NORMAL_COMPLETION) {
821 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
822 RUE_UNLOCK(sc);
823 return;
824 }
825 if (usbd_ratecheck(&sc->rue_rx_notice)) {
826 if_printf(ifp, "usb error on rx: %s\n",
827 usbd_errstr(status));
828 }
829 if (status == USBD_STALLED)
830 usbd_clear_endpoint_stall(sc->rue_ep[RUE_ENDPT_RX]);
831 goto done;
832 }
833
834 usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
835
836 if (total_len <= ETHER_CRC_LEN) {
837 ifp->if_ierrors++;
838 goto done;
839 }
840
841 m = c->rue_mbuf;
842 bcopy(mtod(m, char *) + total_len - 4, (char *)&r, sizeof (r));
843
844 /* Check recieve packet was valid or not */
845 if ((r.rue_rxstat & RUE_RXSTAT_VALID) == 0) {
846 ifp->if_ierrors++;
847 goto done;
848 }
849
850 /* No errors; receive the packet. */
851 total_len -= ETHER_CRC_LEN;
852
853 ifp->if_ipackets++;
854 m->m_pkthdr.rcvif = ifp;
855 m->m_pkthdr.len = m->m_len = total_len;
856
857 /* Put the packet on the special USB input queue. */
858 usb_ether_input(m);
859 rue_rxstart(ifp);
860
861 RUE_UNLOCK(sc);
862 return;
863
864 done:
865 /* Setup new transfer. */
866 usbd_setup_xfer(xfer, sc->rue_ep[RUE_ENDPT_RX],
867 c, mtod(c->rue_mbuf, char *), RUE_BUFSZ,
868 USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, rue_rxeof);
869 usbd_transfer(xfer);
870 RUE_UNLOCK(sc);
871}
872
873/*
874 * A frame was downloaded to the chip. It's safe for us to clean up
875 * the list buffers.
876 */
877
878Static void
879rue_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
880{
881 struct rue_chain *c = priv;
882 struct rue_softc *sc = c->rue_sc;
883 struct ifnet *ifp;
884 usbd_status err;
885
886 RUE_LOCK(sc);
887
888 ifp = &sc->arpcom.ac_if;
889
890 if (status != USBD_NORMAL_COMPLETION) {
891 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
892 RUE_UNLOCK(sc);
893 return;
894 }
895 if_printf(ifp, "usb error on tx: %s\n", usbd_errstr(status));
896 if (status == USBD_STALLED)
897 usbd_clear_endpoint_stall(sc->rue_ep[RUE_ENDPT_TX]);
898 RUE_UNLOCK(sc);
899 return;
900 }
901
902 ifp->if_timer = 0;
903 ifp->if_flags &= ~IFF_OACTIVE;
904 usbd_get_xfer_status(c->rue_xfer, NULL, NULL, NULL, &err);
905
906 if (c->rue_mbuf != NULL) {
907 m_freem(c->rue_mbuf);
908 c->rue_mbuf = NULL;
909 }
910
911 if (err)
912 ifp->if_oerrors++;
913 else
914 ifp->if_opackets++;
915
916 if (!ifq_is_empty(&ifp->if_snd))
917 ifp->if_start(ifp);
918
919 RUE_UNLOCK(sc);
920}
921
922Static void
923rue_tick(void *xsc)
924{
925 struct rue_softc *sc = xsc;
926 struct ifnet *ifp;
927 struct mii_data *mii;
928
929 if (sc == NULL)
930 return;
931
932 RUE_LOCK(sc);
933
934 ifp = &sc->arpcom.ac_if;
935 mii = GET_MII(sc);
936 if (mii == NULL) {
937 RUE_UNLOCK(sc);
938 return;
939 }
940
941 mii_tick(mii);
942 if (!sc->rue_link && mii->mii_media_status & IFM_ACTIVE &&
943 IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) {
944 sc->rue_link++;
945 if (!ifq_is_empty(&ifp->if_snd))
946 rue_start(ifp);
947 }
948
949 callout_reset(&sc->rue_stat_ch, hz, rue_tick, sc);
950
951 RUE_UNLOCK(sc);
952}
953
954Static int
955rue_encap(struct rue_softc *sc, struct mbuf *m, int idx)
956{
957 int total_len;
958 struct rue_chain *c;
959 usbd_status err;
960
961 c = &sc->rue_cdata.rue_tx_chain[idx];
962
963 /*
964 * Copy the mbuf data into a contiguous buffer
965 */
966 m_copydata(m, 0, m->m_pkthdr.len, c->rue_buf);
967 c->rue_mbuf = m;
968
969 total_len = m->m_pkthdr.len;
970
971 /*
972 * This is an undocumented behavior.
973 * RTL8150 chip doesn't send frame length smaller than
974 * RUE_MIN_FRAMELEN (60) byte packet.
975 */
976 if (total_len < RUE_MIN_FRAMELEN)
977 total_len = RUE_MIN_FRAMELEN;
978
979 usbd_setup_xfer(c->rue_xfer, sc->rue_ep[RUE_ENDPT_TX],
980 c, c->rue_buf, total_len, USBD_FORCE_SHORT_XFER,
981 10000, rue_txeof);
982
983 /* Transmit */
984 err = usbd_transfer(c->rue_xfer);
985 if (err != USBD_IN_PROGRESS) {
986 rue_stop(sc);
987 return (EIO);
988 }
989
990 sc->rue_cdata.rue_tx_cnt++;
991
992 return (0);
993}
994
995Static void
996rue_start(struct ifnet *ifp)
997{
998 struct rue_softc *sc = ifp->if_softc;
999 struct mbuf *m_head = NULL;
1000
1001 RUE_LOCK(sc);
1002
1003 if (!sc->rue_link) {
1004 RUE_UNLOCK(sc);
1005 return;
1006 }
1007
1008 if (ifp->if_flags & IFF_OACTIVE) {
1009 RUE_UNLOCK(sc);
1010 return;
1011 }
1012
1013 m_head = ifq_poll(&ifp->if_snd);
1014 if (m_head == NULL) {
1015 RUE_UNLOCK(sc);
1016 return;
1017 }
1018
1019 if (rue_encap(sc, m_head, 0)) {
1020 ifp->if_flags |= IFF_OACTIVE;
1021 RUE_UNLOCK(sc);
1022 return;
1023 }
d2c71fa0 1024 ifq_dequeue(&ifp->if_snd, m_head);
3c374c15
SZ
1025
1026 /*
1027 * If there's a BPF listener, bounce a copy of this frame
1028 * to him.
1029 */
1030 BPF_MTAP(ifp, m_head);
1031
1032 ifp->if_flags |= IFF_OACTIVE;
1033
1034 /*
1035 * Set a timeout in case the chip goes out to lunch.
1036 */
1037 ifp->if_timer = 5;
1038
1039 RUE_UNLOCK(sc);
1040}
1041
1042Static void
1043rue_init(void *xsc)
1044{
1045 struct rue_softc *sc = xsc;
1046 struct ifnet *ifp = &sc->arpcom.ac_if;
1047 struct mii_data *mii = GET_MII(sc);
1048 struct rue_chain *c;
1049 usbd_status err;
1050 int i;
1051 int rxcfg;
1052
1053 RUE_LOCK(sc);
1054
1055 if (ifp->if_flags & IFF_RUNNING) {
1056 RUE_UNLOCK(sc);
1057 return;
1058 }
1059
1060 /*
1061 * Cancel pending I/O and free all RX/TX buffers.
1062 */
1063 rue_reset(sc);
1064
1065 /* Set MAC address */
1066 rue_write_mem(sc, RUE_IDR0, sc->arpcom.ac_enaddr, ETHER_ADDR_LEN);
1067
1068 /* Init TX ring. */
1069 if (rue_tx_list_init(sc) == ENOBUFS) {
1070 if_printf(ifp, "tx list init failed\n");
1071 RUE_UNLOCK(sc);
1072 return;
1073 }
1074
1075 /* Init RX ring. */
1076 if (rue_rx_list_init(sc) == ENOBUFS) {
1077 if_printf(ifp, "rx list init failed\n");
1078 RUE_UNLOCK(sc);
1079 return;
1080 }
1081
1082#ifdef RUE_INTR_PIPE
efda3bd0 1083 sc->rue_cdata.rue_ibuf = kmalloc(RUE_INTR_PKTLEN, M_USBDEV, M_WAITOK);
3c374c15
SZ
1084#endif
1085
1086 /*
1087 * Set the initial TX and RX configuration.
1088 */
1089 rue_csr_write_1(sc, RUE_TCR, RUE_TCR_CONFIG);
1090
1091 rxcfg = RUE_RCR_CONFIG;
1092
1093 /* Set capture broadcast bit to capture broadcast frames. */
1094 if (ifp->if_flags & IFF_BROADCAST)
1095 rxcfg |= RUE_RCR_AB;
1096 else
1097 rxcfg &= ~RUE_RCR_AB;
1098
1099 /* If we want promiscuous mode, set the allframes bit. */
1100 if (ifp->if_flags & IFF_PROMISC)
1101 rxcfg |= RUE_RCR_AAP;
1102 else
1103 rxcfg &= ~RUE_RCR_AAP;
1104
1105 rue_csr_write_2(sc, RUE_RCR, rxcfg);
1106
1107 /* Load the multicast filter. */
1108 rue_setmulti(sc);
1109
1110 /* Enable RX and TX */
1111 rue_csr_write_1(sc, RUE_CR, (RUE_CR_TE | RUE_CR_RE | RUE_CR_EP3CLREN));
1112
1113 mii_mediachg(mii);
1114
1115 /* Open RX and TX pipes. */
1116 err = usbd_open_pipe(sc->rue_iface, sc->rue_ed[RUE_ENDPT_RX],
1117 USBD_EXCLUSIVE_USE, &sc->rue_ep[RUE_ENDPT_RX]);
1118 if (err) {
1119 if_printf(ifp, "open rx pipe failed: %s\n", usbd_errstr(err));
1120 RUE_UNLOCK(sc);
1121 return;
1122 }
1123 err = usbd_open_pipe(sc->rue_iface, sc->rue_ed[RUE_ENDPT_TX],
1124 USBD_EXCLUSIVE_USE, &sc->rue_ep[RUE_ENDPT_TX]);
1125 if (err) {
1126 if_printf(ifp, "open tx pipe failed: %s\n", usbd_errstr(err));
1127 RUE_UNLOCK(sc);
1128 return;
1129 }
1130
1131#ifdef RUE_INTR_PIPE
1132 err = usbd_open_pipe_intr(sc->rue_iface, sc->rue_ed[RUE_ENDPT_INTR],
1133 USBD_SHORT_XFER_OK,
1134 &sc->rue_ep[RUE_ENDPT_INTR], sc,
1135 sc->rue_cdata.rue_ibuf, RUE_INTR_PKTLEN,
1136 rue_intr, RUE_INTR_INTERVAL);
1137 if (err) {
1138 if_printf(ifp, "open intr pipe failed: %s\n", usbd_errstr(err));
1139 RUE_UNLOCK(sc);
1140 return;
1141 }
1142#endif
1143
1144 /* Start up the receive pipe. */
1145 for (i = 0; i < RUE_RX_LIST_CNT; i++) {
1146 c = &sc->rue_cdata.rue_rx_chain[i];
1147 usbd_setup_xfer(c->rue_xfer, sc->rue_ep[RUE_ENDPT_RX],
1148 c, mtod(c->rue_mbuf, char *), RUE_BUFSZ,
1149 USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, rue_rxeof);
1150 usbd_transfer(c->rue_xfer);
1151 }
1152
1153 ifp->if_flags |= IFF_RUNNING;
1154 ifp->if_flags &= ~IFF_OACTIVE;
1155
1156 callout_reset(&sc->rue_stat_ch, hz, rue_tick, sc);
1157
1158 RUE_UNLOCK(sc);
1159}
1160
1161/*
1162 * Set media options.
1163 */
1164
1165Static int
1166rue_ifmedia_upd(struct ifnet *ifp)
1167{
1168 struct rue_softc *sc = ifp->if_softc;
1169 struct mii_data *mii = GET_MII(sc);
1170
1171 sc->rue_link = 0;
1172 if (mii->mii_instance) {
1173 struct mii_softc *miisc;
1174 LIST_FOREACH (miisc, &mii->mii_phys, mii_list)
1175 mii_phy_reset(miisc);
1176 }
1177 mii_mediachg(mii);
1178
1179 return (0);
1180}
1181
1182/*
1183 * Report current media status.
1184 */
1185
1186Static void
1187rue_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
1188{
1189 struct rue_softc *sc = ifp->if_softc;
1190 struct mii_data *mii = GET_MII(sc);
1191
1192 mii_pollstat(mii);
1193 ifmr->ifm_active = mii->mii_media_active;
1194 ifmr->ifm_status = mii->mii_media_status;
1195}
1196
1197Static int
1198rue_ioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr)
1199{
1200 struct rue_softc *sc = ifp->if_softc;
1201 struct ifreq *ifr = (struct ifreq *)data;
1202 struct mii_data *mii;
1203 int error = 0;
1204
1205 RUE_LOCK(sc);
1206
1207 switch (command) {
1208 case SIOCSIFFLAGS:
1209 if (ifp->if_flags & IFF_UP) {
1210 if (ifp->if_flags & IFF_RUNNING &&
1211 ifp->if_flags & IFF_PROMISC &&
1212 !(sc->rue_if_flags & IFF_PROMISC)) {
1213 RUE_SETBIT_2(sc, RUE_RCR,
1214 (RUE_RCR_AAM | RUE_RCR_AAP));
1215 rue_setmulti(sc);
1216 } else if (ifp->if_flags & IFF_RUNNING &&
1217 !(ifp->if_flags & IFF_PROMISC) &&
1218 sc->rue_if_flags & IFF_PROMISC) {
1219 RUE_CLRBIT_2(sc, RUE_RCR,
1220 (RUE_RCR_AAM | RUE_RCR_AAP));
1221 rue_setmulti(sc);
1222 } else if (!(ifp->if_flags & IFF_RUNNING))
1223 rue_init(sc);
1224 } else {
1225 if (ifp->if_flags & IFF_RUNNING)
1226 rue_stop(sc);
1227 }
1228 sc->rue_if_flags = ifp->if_flags;
1229 error = 0;
1230 break;
1231 case SIOCADDMULTI:
1232 case SIOCDELMULTI:
1233 rue_setmulti(sc);
1234 error = 0;
1235 break;
1236 case SIOCGIFMEDIA:
1237 case SIOCSIFMEDIA:
1238 mii = GET_MII(sc);
1239 error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
1240 break;
1241 default:
1242 error = ether_ioctl(ifp, command, data);
1243 break;
1244 }
1245
1246 RUE_UNLOCK(sc);
1247
1248 return (error);
1249}
1250
1251Static void
1252rue_watchdog(struct ifnet *ifp)
1253{
1254 struct rue_softc *sc = ifp->if_softc;
1255 struct rue_chain *c;
1256 usbd_status stat;
1257
1258 RUE_LOCK(sc);
1259
1260 ifp->if_oerrors++;
1261 if_printf(ifp, "watchdog timeout\n");
1262
1263 c = &sc->rue_cdata.rue_tx_chain[0];
1264 usbd_get_xfer_status(c->rue_xfer, NULL, NULL, NULL, &stat);
1265 rue_txeof(c->rue_xfer, c, stat);
1266
1267 if (!ifq_is_empty(&ifp->if_snd))
1268 rue_start(ifp);
1269
1270 RUE_UNLOCK(sc);
1271}
1272
1273/*
1274 * Stop the adapter and free any mbufs allocated to the
1275 * RX and TX lists.
1276 */
1277
1278Static void
1279rue_stop(struct rue_softc *sc)
1280{
1281 usbd_status err;
1282 struct ifnet *ifp;
1283 int i;
1284
1285 RUE_LOCK(sc);
1286
1287 ifp = &sc->arpcom.ac_if;
1288 ifp->if_timer = 0;
1289
1290 rue_csr_write_1(sc, RUE_CR, 0x00);
1291 rue_reset(sc);
1292
1293 callout_stop(&sc->rue_stat_ch);
1294
1295 /* Stop transfers. */
1296 if (sc->rue_ep[RUE_ENDPT_RX] != NULL) {
1297 err = usbd_abort_pipe(sc->rue_ep[RUE_ENDPT_RX]);
1298 if (err) {
1299 if_printf(ifp, "abort rx pipe failed: %s\n",
1300 usbd_errstr(err));
1301 }
1302 err = usbd_close_pipe(sc->rue_ep[RUE_ENDPT_RX]);
1303 if (err) {
1304 if_printf(ifp, "close rx pipe failed: %s\n",
1305 usbd_errstr(err));
1306 }
1307 sc->rue_ep[RUE_ENDPT_RX] = NULL;
1308 }
1309
1310 if (sc->rue_ep[RUE_ENDPT_TX] != NULL) {
1311 err = usbd_abort_pipe(sc->rue_ep[RUE_ENDPT_TX]);
1312 if (err) {
1313 if_printf(ifp, "abort tx pipe failed: %s\n",
1314 usbd_errstr(err));
1315 }
1316 err = usbd_close_pipe(sc->rue_ep[RUE_ENDPT_TX]);
1317 if (err) {
1318 if_printf(ifp, "close tx pipe failed: %s\n",
1319 usbd_errstr(err));
1320 }
1321 sc->rue_ep[RUE_ENDPT_TX] = NULL;
1322 }
1323
1324#ifdef RUE_INTR_PIPE
1325 if (sc->rue_ep[RUE_ENDPT_INTR] != NULL) {
1326 err = usbd_abort_pipe(sc->rue_ep[RUE_ENDPT_INTR]);
1327 if (err) {
1328 if_printf(ifp, "abort intr pipe failed: %s\n",
1329 usbd_errstr(err));
1330 }
1331 err = usbd_close_pipe(sc->rue_ep[RUE_ENDPT_INTR]);
1332 if (err) {
1333 if_printf(ifp, "close intr pipe failed: %s\n",
1334 usbd_errstr(err));
1335 }
1336 sc->rue_ep[RUE_ENDPT_INTR] = NULL;
1337 }
1338#endif
1339
1340 /* Free RX resources. */
1341 for (i = 0; i < RUE_RX_LIST_CNT; i++) {
1342 if (sc->rue_cdata.rue_rx_chain[i].rue_buf != NULL) {
efda3bd0 1343 kfree(sc->rue_cdata.rue_rx_chain[i].rue_buf, M_USBDEV);
3c374c15
SZ
1344 sc->rue_cdata.rue_rx_chain[i].rue_buf = NULL;
1345 }
1346 if (sc->rue_cdata.rue_rx_chain[i].rue_mbuf != NULL) {
1347 m_freem(sc->rue_cdata.rue_rx_chain[i].rue_mbuf);
1348 sc->rue_cdata.rue_rx_chain[i].rue_mbuf = NULL;
1349 }
1350 if (sc->rue_cdata.rue_rx_chain[i].rue_xfer != NULL) {
1351 usbd_free_xfer(sc->rue_cdata.rue_rx_chain[i].rue_xfer);
1352 sc->rue_cdata.rue_rx_chain[i].rue_xfer = NULL;
1353 }
1354 }
1355
1356 /* Free TX resources. */
1357 for (i = 0; i < RUE_TX_LIST_CNT; i++) {
1358 if (sc->rue_cdata.rue_tx_chain[i].rue_buf != NULL) {
efda3bd0 1359 kfree(sc->rue_cdata.rue_tx_chain[i].rue_buf, M_USBDEV);
3c374c15
SZ
1360 sc->rue_cdata.rue_tx_chain[i].rue_buf = NULL;
1361 }
1362 if (sc->rue_cdata.rue_tx_chain[i].rue_mbuf != NULL) {
1363 m_freem(sc->rue_cdata.rue_tx_chain[i].rue_mbuf);
1364 sc->rue_cdata.rue_tx_chain[i].rue_mbuf = NULL;
1365 }
1366 if (sc->rue_cdata.rue_tx_chain[i].rue_xfer != NULL) {
1367 usbd_free_xfer(sc->rue_cdata.rue_tx_chain[i].rue_xfer);
1368 sc->rue_cdata.rue_tx_chain[i].rue_xfer = NULL;
1369 }
1370 }
1371
1372#ifdef RUE_INTR_PIPE
4ad01c4c 1373 if (sc->rue_cdata.rue_ibuf != NULL) {
efda3bd0 1374 kfree(sc->rue_cdata.rue_ibuf, M_USBDEV);
4ad01c4c
SZ
1375 sc->rue_cdata.rue_ibuf = NULL;
1376 }
3c374c15
SZ
1377#endif
1378
1379 sc->rue_link = 0;
1380
1381 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
1382
1383 RUE_UNLOCK(sc);
1384}
1385
1386/*
1387 * Stop all chip I/O so that the kernel's probe routines don't
1388 * get confused by errant DMAs when rebooting.
1389 */
1390
1391Static void
1392rue_shutdown(device_ptr_t dev)
1393{
1394 struct rue_softc *sc;
1395
1396 sc = device_get_softc(dev);
1397
1398 sc->rue_dying++;
1399 RUE_LOCK(sc);
1400 rue_reset(sc);
1401 rue_stop(sc);
1402 RUE_UNLOCK(sc);
1403}