1 /*-
2 * Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
3 *
4 * This software was developed by SRI International and the University of
5 * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
6 * ("CTSRD"), as part of the DARPA CRASH research programme.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30 /*
31 * Ethernet media access controller (EMAC)
32 * Chapter 17, Altera Cyclone V Device Handbook (CV-5V2 2014.07.22)
33 *
34 * EMAC is an instance of the Synopsys DesignWare 3504-0
35 * Universal 10/100/1000 Ethernet MAC (DWC_gmac).
36 */
37
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/bus.h>
41 #include <sys/gpio.h>
42 #include <sys/kernel.h>
43 #include <sys/lock.h>
44 #include <sys/malloc.h>
45 #include <sys/mbuf.h>
46 #include <sys/module.h>
47 #include <sys/mutex.h>
48 #include <sys/rman.h>
49 #include <sys/socket.h>
50 #include <sys/sockio.h>
51
52 #include <net/bpf.h>
53 #include <net/if.h>
54 #include <net/ethernet.h>
55 #include <net/if_dl.h>
56 #include <net/if_media.h>
57 #include <net/if_types.h>
58 #include <net/if_var.h>
59
60 #include <machine/bus.h>
61
62 #include <dev/clk/clk.h>
63 #include <dev/hwreset/hwreset.h>
64
65 #include <dev/mii/mii.h>
66 #include <dev/mii/miivar.h>
67 #include <dev/ofw/ofw_bus.h>
68 #include <dev/ofw/ofw_bus_subr.h>
69 #include <dev/mii/mii_fdt.h>
70
71 #include <dev/dwc/if_dwcvar.h>
72 #include <dev/dwc/dwc1000_core.h>
73 #include <dev/dwc/dwc1000_dma.h>
74
75 #include "if_dwc_if.h"
76 #include "gpio_if.h"
77 #include "miibus_if.h"
78
79 static struct resource_spec dwc_spec[] = {
80 { SYS_RES_MEMORY, 0, RF_ACTIVE },
81 { SYS_RES_IRQ, 0, RF_ACTIVE },
82 { -1, 0 }
83 };
84
85 static void dwc_stop_locked(struct dwc_softc *sc);
86
87 static void dwc_tick(void *arg);
88
89 /*
90 * Media functions
91 */
92
93 static void
dwc_media_status(if_t ifp,struct ifmediareq * ifmr)94 dwc_media_status(if_t ifp, struct ifmediareq *ifmr)
95 {
96 struct dwc_softc *sc;
97 struct mii_data *mii;
98
99 sc = if_getsoftc(ifp);
100 mii = sc->mii_softc;
101 DWC_LOCK(sc);
102 mii_pollstat(mii);
103 ifmr->ifm_active = mii->mii_media_active;
104 ifmr->ifm_status = mii->mii_media_status;
105 DWC_UNLOCK(sc);
106 }
107
108 static int
dwc_media_change_locked(struct dwc_softc * sc)109 dwc_media_change_locked(struct dwc_softc *sc)
110 {
111
112 return (mii_mediachg(sc->mii_softc));
113 }
114
115 static int
dwc_media_change(if_t ifp)116 dwc_media_change(if_t ifp)
117 {
118 struct dwc_softc *sc;
119 int error;
120
121 sc = if_getsoftc(ifp);
122
123 DWC_LOCK(sc);
124 error = dwc_media_change_locked(sc);
125 DWC_UNLOCK(sc);
126 return (error);
127 }
128
129 /*
130 * if_ functions
131 */
132
133 static void
dwc_txstart_locked(struct dwc_softc * sc)134 dwc_txstart_locked(struct dwc_softc *sc)
135 {
136 if_t ifp;
137
138 DWC_ASSERT_LOCKED(sc);
139
140 if (!sc->link_is_up)
141 return;
142
143 ifp = sc->ifp;
144
145 if ((if_getdrvflags(ifp) & (IFF_DRV_RUNNING|IFF_DRV_OACTIVE)) !=
146 IFF_DRV_RUNNING)
147 return;
148 dma1000_txstart(sc);
149 }
150
151 static void
dwc_txstart(if_t ifp)152 dwc_txstart(if_t ifp)
153 {
154 struct dwc_softc *sc = if_getsoftc(ifp);
155
156 DWC_LOCK(sc);
157 dwc_txstart_locked(sc);
158 DWC_UNLOCK(sc);
159 }
160
161 static void
dwc_init_locked(struct dwc_softc * sc)162 dwc_init_locked(struct dwc_softc *sc)
163 {
164 if_t ifp = sc->ifp;
165
166 DWC_ASSERT_LOCKED(sc);
167
168 if (if_getdrvflags(ifp) & IFF_DRV_RUNNING)
169 return;
170
171 /*
172 * Call mii_mediachg() which will call back into dwc1000_miibus_statchg()
173 * to set up the remaining config registers based on current media.
174 */
175 mii_mediachg(sc->mii_softc);
176
177 dwc1000_setup_rxfilter(sc);
178 dwc1000_core_setup(sc);
179 dwc1000_enable_mac(sc, true);
180 dwc1000_enable_csum_offload(sc);
181 dma1000_start(sc);
182
183 if_setdrvflagbits(ifp, IFF_DRV_RUNNING, IFF_DRV_OACTIVE);
184
185 callout_reset(&sc->dwc_callout, hz, dwc_tick, sc);
186 }
187
188 static void
dwc_init(void * if_softc)189 dwc_init(void *if_softc)
190 {
191 struct dwc_softc *sc = if_softc;
192
193 DWC_LOCK(sc);
194 dwc_init_locked(sc);
195 DWC_UNLOCK(sc);
196 }
197
198 static void
dwc_stop_locked(struct dwc_softc * sc)199 dwc_stop_locked(struct dwc_softc *sc)
200 {
201 if_t ifp;
202
203 DWC_ASSERT_LOCKED(sc);
204
205 ifp = sc->ifp;
206 if_setdrvflagbits(ifp, 0, IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
207 sc->tx_watchdog_count = 0;
208 sc->stats_harvest_count = 0;
209
210 callout_stop(&sc->dwc_callout);
211
212 dma1000_stop(sc);
213 dwc1000_enable_mac(sc, false);
214 }
215
216 static int
dwc_ioctl(if_t ifp,u_long cmd,caddr_t data)217 dwc_ioctl(if_t ifp, u_long cmd, caddr_t data)
218 {
219 struct dwc_softc *sc;
220 struct mii_data *mii;
221 struct ifreq *ifr;
222 int flags, mask, error;
223
224 sc = if_getsoftc(ifp);
225 ifr = (struct ifreq *)data;
226
227 error = 0;
228 switch (cmd) {
229 case SIOCSIFFLAGS:
230 DWC_LOCK(sc);
231 if (if_getflags(ifp) & IFF_UP) {
232 if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) {
233 flags = if_getflags(ifp) ^ sc->if_flags;
234 if ((flags & (IFF_PROMISC|IFF_ALLMULTI)) != 0)
235 dwc1000_setup_rxfilter(sc);
236 } else {
237 if (!sc->is_detaching)
238 dwc_init_locked(sc);
239 }
240 } else {
241 if (if_getdrvflags(ifp) & IFF_DRV_RUNNING)
242 dwc_stop_locked(sc);
243 }
244 sc->if_flags = if_getflags(ifp);
245 DWC_UNLOCK(sc);
246 break;
247 case SIOCADDMULTI:
248 case SIOCDELMULTI:
249 if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) {
250 DWC_LOCK(sc);
251 dwc1000_setup_rxfilter(sc);
252 DWC_UNLOCK(sc);
253 }
254 break;
255 case SIOCSIFMEDIA:
256 case SIOCGIFMEDIA:
257 mii = sc->mii_softc;
258 error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd);
259 break;
260 case SIOCSIFCAP:
261 mask = ifr->ifr_reqcap ^ if_getcapenable(ifp);
262 if (mask & IFCAP_VLAN_MTU) {
263 /* No work to do except acknowledge the change took */
264 if_togglecapenable(ifp, IFCAP_VLAN_MTU);
265 }
266 if (mask & (IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6))
267 if_togglecapenable(ifp, IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6);
268 if (mask & IFCAP_TXCSUM) {
269 if_togglecapenable(ifp, IFCAP_TXCSUM);
270 if_togglehwassist(ifp, CSUM_IP | CSUM_DELAY_DATA);
271 }
272 if (mask & IFCAP_TXCSUM_IPV6) {
273 if_togglecapenable(ifp, IFCAP_TXCSUM_IPV6);
274 if_togglehwassist(ifp, CSUM_DELAY_DATA_IPV6);
275 }
276
277 if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) {
278 DWC_LOCK(sc);
279 dwc1000_enable_csum_offload(sc);
280 DWC_UNLOCK(sc);
281 }
282 break;
283
284 default:
285 error = ether_ioctl(ifp, cmd, data);
286 break;
287 }
288
289 return (error);
290 }
291
292 /*
293 * Interrupts functions
294 */
295
296
297 static void
dwc_intr(void * arg)298 dwc_intr(void *arg)
299 {
300 struct dwc_softc *sc;
301 int rv;
302
303 sc = arg;
304 DWC_LOCK(sc);
305 dwc1000_intr(sc);
306 rv = dma1000_intr(sc);
307 if (rv == EIO) {
308 device_printf(sc->dev,
309 "Ethernet DMA error, restarting controller.\n");
310 dwc_stop_locked(sc);
311 dwc_init_locked(sc);
312 }
313 DWC_UNLOCK(sc);
314 }
315
316 static void
dwc_tick(void * arg)317 dwc_tick(void *arg)
318 {
319 struct dwc_softc *sc;
320 if_t ifp;
321 int link_was_up;
322
323 sc = arg;
324
325 DWC_ASSERT_LOCKED(sc);
326
327 ifp = sc->ifp;
328
329 if ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) == 0)
330 return;
331
332 /*
333 * Typical tx watchdog. If this fires it indicates that we enqueued
334 * packets for output and never got a txdone interrupt for them. Maybe
335 * it's a missed interrupt somehow, just pretend we got one.
336 */
337 if (sc->tx_watchdog_count > 0) {
338 if (--sc->tx_watchdog_count == 0) {
339 dma1000_txfinish_locked(sc);
340 }
341 }
342
343 /* Gather stats from hardware counters. */
344 dwc1000_harvest_stats(sc);
345
346 /* Check the media status. */
347 link_was_up = sc->link_is_up;
348 mii_tick(sc->mii_softc);
349 if (sc->link_is_up && !link_was_up)
350 dwc_txstart_locked(sc);
351
352 /* Schedule another check one second from now. */
353 callout_reset(&sc->dwc_callout, hz, dwc_tick, sc);
354 }
355
356 static int
dwc_reset_phy(struct dwc_softc * sc)357 dwc_reset_phy(struct dwc_softc *sc)
358 {
359 pcell_t gpio_prop[4];
360 pcell_t delay_prop[3];
361 phandle_t gpio_node;
362 device_t gpio;
363 uint32_t pin, flags;
364 uint32_t pin_value;
365
366 /*
367 * All those properties are deprecated but still used in some DTS.
368 * The new way to deal with this is to use the generic bindings
369 * present in the ethernet-phy node.
370 */
371 if (OF_getencprop(sc->node, "snps,reset-gpio",
372 gpio_prop, sizeof(gpio_prop)) <= 0)
373 return (0);
374
375 if (OF_getencprop(sc->node, "snps,reset-delays-us",
376 delay_prop, sizeof(delay_prop)) <= 0) {
377 device_printf(sc->dev,
378 "Wrong property for snps,reset-delays-us");
379 return (ENXIO);
380 }
381
382 gpio_node = OF_node_from_xref(gpio_prop[0]);
383 if ((gpio = OF_device_from_xref(gpio_prop[0])) == NULL) {
384 device_printf(sc->dev,
385 "Can't find gpio controller for phy reset\n");
386 return (ENXIO);
387 }
388
389 if (GPIO_MAP_GPIOS(gpio, sc->node, gpio_node,
390 nitems(gpio_prop) - 1,
391 gpio_prop + 1, &pin, &flags) != 0) {
392 device_printf(sc->dev, "Can't map gpio for phy reset\n");
393 return (ENXIO);
394 }
395
396 pin_value = GPIO_PIN_LOW;
397 if (OF_hasprop(sc->node, "snps,reset-active-low"))
398 pin_value = GPIO_PIN_HIGH;
399
400 GPIO_PIN_SETFLAGS(gpio, pin, GPIO_PIN_OUTPUT);
401 GPIO_PIN_SET(gpio, pin, pin_value);
402 DELAY(delay_prop[0] * 5);
403 GPIO_PIN_SET(gpio, pin, !pin_value);
404 DELAY(delay_prop[1] * 5);
405 GPIO_PIN_SET(gpio, pin, pin_value);
406 DELAY(delay_prop[2] * 5);
407
408 return (0);
409 }
410
411 static int
dwc_clock_init(struct dwc_softc * sc)412 dwc_clock_init(struct dwc_softc *sc)
413 {
414 int rv;
415 int64_t freq;
416
417 /* Required clock */
418 rv = clk_get_by_ofw_name(sc->dev, 0, "stmmaceth", &sc->clk_stmmaceth);
419 if (rv != 0) {
420 device_printf(sc->dev, "Cannot get GMAC main clock\n");
421 return (ENXIO);
422 }
423 if ((rv = clk_enable(sc->clk_stmmaceth)) != 0) {
424 device_printf(sc->dev, "could not enable main clock\n");
425 return (rv);
426 }
427
428 /* Optional clock */
429 rv = clk_get_by_ofw_name(sc->dev, 0, "pclk", &sc->clk_pclk);
430 if (rv != 0)
431 return (0);
432 if ((rv = clk_enable(sc->clk_pclk)) != 0) {
433 device_printf(sc->dev, "could not enable peripheral clock\n");
434 return (rv);
435 }
436
437 if (bootverbose) {
438 clk_get_freq(sc->clk_stmmaceth, &freq);
439 device_printf(sc->dev, "MAC clock(%s) freq: %jd\n",
440 clk_get_name(sc->clk_stmmaceth), (intmax_t)freq);
441 }
442
443 return (0);
444 }
445
446 static int
dwc_reset_deassert(struct dwc_softc * sc)447 dwc_reset_deassert(struct dwc_softc *sc)
448 {
449 int rv;
450
451 /* Required reset */
452 rv = hwreset_get_by_ofw_name(sc->dev, 0, "stmmaceth", &sc->rst_stmmaceth);
453 if (rv != 0) {
454 device_printf(sc->dev, "Cannot get GMAC reset\n");
455 return (ENXIO);
456 }
457 rv = hwreset_deassert(sc->rst_stmmaceth);
458 if (rv != 0) {
459 device_printf(sc->dev, "could not de-assert GMAC reset\n");
460 return (rv);
461 }
462
463 /* Optional reset */
464 rv = hwreset_get_by_ofw_name(sc->dev, 0, "ahb", &sc->rst_ahb);
465 if (rv != 0)
466 return (0);
467 rv = hwreset_deassert(sc->rst_ahb);
468 if (rv != 0) {
469 device_printf(sc->dev, "could not de-assert AHB reset\n");
470 return (rv);
471 }
472
473 return (0);
474 }
475
476 /*
477 * Probe/Attach functions
478 */
479
480 static int
dwc_probe(device_t dev)481 dwc_probe(device_t dev)
482 {
483
484 if (!ofw_bus_status_okay(dev))
485 return (ENXIO);
486
487 if (!ofw_bus_is_compatible(dev, "snps,dwmac"))
488 return (ENXIO);
489
490 device_set_desc(dev, "Gigabit Ethernet Controller");
491 return (BUS_PROBE_DEFAULT);
492 }
493
494 static int
dwc_attach(device_t dev)495 dwc_attach(device_t dev)
496 {
497 uint8_t macaddr[ETHER_ADDR_LEN];
498 struct dwc_softc *sc;
499 if_t ifp;
500 int error;
501 uint32_t pbl;
502
503 sc = device_get_softc(dev);
504 sc->dev = dev;
505 sc->rx_idx = 0;
506 sc->tx_desccount = TX_DESC_COUNT;
507 sc->tx_mapcount = 0;
508
509 sc->node = ofw_bus_get_node(dev);
510 sc->phy_mode = mii_fdt_get_contype(sc->node);
511 switch (sc->phy_mode) {
512 case MII_CONTYPE_RGMII:
513 case MII_CONTYPE_RGMII_ID:
514 case MII_CONTYPE_RGMII_RXID:
515 case MII_CONTYPE_RGMII_TXID:
516 case MII_CONTYPE_RMII:
517 case MII_CONTYPE_MII:
518 break;
519 default:
520 device_printf(dev, "Unsupported MII type\n");
521 return (ENXIO);
522 }
523
524 if (OF_getencprop(sc->node, "snps,pbl", &pbl, sizeof(uint32_t)) <= 0)
525 pbl = DMA_DEFAULT_PBL;
526 if (OF_getencprop(sc->node, "snps,txpbl", &sc->txpbl, sizeof(uint32_t)) <= 0)
527 sc->txpbl = pbl;
528 if (OF_getencprop(sc->node, "snps,rxpbl", &sc->rxpbl, sizeof(uint32_t)) <= 0)
529 sc->rxpbl = pbl;
530 if (OF_hasprop(sc->node, "snps,no-pbl-x8") == 1)
531 sc->nopblx8 = true;
532 if (OF_hasprop(sc->node, "snps,fixed-burst") == 1)
533 sc->fixed_burst = true;
534 if (OF_hasprop(sc->node, "snps,mixed-burst") == 1)
535 sc->mixed_burst = true;
536 if (OF_hasprop(sc->node, "snps,aal") == 1)
537 sc->aal = true;
538
539 error = clk_set_assigned(dev, ofw_bus_get_node(dev));
540 if (error != 0 && error != ENOENT) {
541 device_printf(dev, "clk_set_assigned failed\n");
542 return (error);
543 }
544
545 /* Enable main clock */
546 if ((error = dwc_clock_init(sc)) != 0)
547 return (error);
548 /* De-assert main reset */
549 if ((error = dwc_reset_deassert(sc)) != 0)
550 return (error);
551
552 if (IF_DWC_INIT(dev) != 0)
553 return (ENXIO);
554
555 if ((sc->mii_clk = IF_DWC_MII_CLK(dev)) < 0) {
556 device_printf(dev, "Cannot get mii clock value %d\n", -sc->mii_clk);
557 return (ENXIO);
558 }
559
560 if (bus_alloc_resources(dev, dwc_spec, sc->res)) {
561 device_printf(dev, "could not allocate resources\n");
562 return (ENXIO);
563 }
564
565 /* Read MAC before reset */
566 dwc1000_get_hwaddr(sc, macaddr);
567
568 /* Reset the PHY if needed */
569 if (dwc_reset_phy(sc) != 0) {
570 device_printf(dev, "Can't reset the PHY\n");
571 bus_release_resources(dev, dwc_spec, sc->res);
572 return (ENXIO);
573 }
574
575 /* Reset */
576 if ((error = dma1000_reset(sc)) != 0) {
577 device_printf(sc->dev, "Can't reset DMA controller.\n");
578 bus_release_resources(sc->dev, dwc_spec, sc->res);
579 return (error);
580 }
581
582 if (dma1000_init(sc)) {
583 bus_release_resources(dev, dwc_spec, sc->res);
584 return (ENXIO);
585 }
586
587 mtx_init(&sc->mtx, device_get_nameunit(sc->dev),
588 MTX_NETWORK_LOCK, MTX_DEF);
589
590 callout_init_mtx(&sc->dwc_callout, &sc->mtx, 0);
591
592 /* Setup interrupt handler. */
593 error = bus_setup_intr(dev, sc->res[1], INTR_TYPE_NET | INTR_MPSAFE,
594 NULL, dwc_intr, sc, &sc->intr_cookie);
595 if (error != 0) {
596 device_printf(dev, "could not setup interrupt handler.\n");
597 bus_release_resources(dev, dwc_spec, sc->res);
598 return (ENXIO);
599 }
600
601 /* Set up the ethernet interface. */
602 sc->ifp = ifp = if_alloc(IFT_ETHER);
603
604 if_setsoftc(ifp, sc);
605 if_initname(ifp, device_get_name(dev), device_get_unit(dev));
606 if_setflags(sc->ifp, IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST);
607 if_setstartfn(ifp, dwc_txstart);
608 if_setioctlfn(ifp, dwc_ioctl);
609 if_setinitfn(ifp, dwc_init);
610 if_setsendqlen(ifp, TX_MAP_COUNT - 1);
611 if_setsendqready(sc->ifp);
612 if_sethwassist(sc->ifp, CSUM_IP | CSUM_DELAY_DATA | CSUM_DELAY_DATA_IPV6);
613 if_setcapabilities(sc->ifp, IFCAP_VLAN_MTU | IFCAP_HWCSUM | IFCAP_HWCSUM_IPV6);
614 if_setcapenable(sc->ifp, if_getcapabilities(sc->ifp));
615
616 /* Attach the mii driver. */
617 error = mii_attach(dev, &sc->miibus, ifp, dwc_media_change,
618 dwc_media_status, BMSR_DEFCAPMASK, MII_PHY_ANY,
619 MII_OFFSET_ANY, 0);
620
621 if (error != 0) {
622 device_printf(dev, "PHY attach failed\n");
623 bus_teardown_intr(dev, sc->res[1], sc->intr_cookie);
624 bus_release_resources(dev, dwc_spec, sc->res);
625 return (ENXIO);
626 }
627 sc->mii_softc = device_get_softc(sc->miibus);
628
629 /* All ready to run, attach the ethernet interface. */
630 ether_ifattach(ifp, macaddr);
631 sc->is_attached = true;
632
633 return (0);
634 }
635
636 static int
dwc_detach(device_t dev)637 dwc_detach(device_t dev)
638 {
639 struct dwc_softc *sc;
640
641 sc = device_get_softc(dev);
642
643 /*
644 * Disable and tear down interrupts before anything else, so we don't
645 * race with the handler.
646 */
647 dwc1000_intr_disable(sc);
648 if (sc->intr_cookie != NULL) {
649 bus_teardown_intr(dev, sc->res[1], sc->intr_cookie);
650 }
651
652 if (sc->is_attached) {
653 DWC_LOCK(sc);
654 sc->is_detaching = true;
655 dwc_stop_locked(sc);
656 DWC_UNLOCK(sc);
657 callout_drain(&sc->dwc_callout);
658 ether_ifdetach(sc->ifp);
659 }
660
661 bus_generic_detach(dev);
662
663 /* Free DMA descriptors */
664 dma1000_free(sc);
665
666 if (sc->ifp != NULL) {
667 if_free(sc->ifp);
668 sc->ifp = NULL;
669 }
670
671 bus_release_resources(dev, dwc_spec, sc->res);
672
673 mtx_destroy(&sc->mtx);
674 return (0);
675 }
676
677 static device_method_t dwc_methods[] = {
678 DEVMETHOD(device_probe, dwc_probe),
679 DEVMETHOD(device_attach, dwc_attach),
680 DEVMETHOD(device_detach, dwc_detach),
681
682 /* MII Interface */
683 DEVMETHOD(miibus_readreg, dwc1000_miibus_read_reg),
684 DEVMETHOD(miibus_writereg, dwc1000_miibus_write_reg),
685 DEVMETHOD(miibus_statchg, dwc1000_miibus_statchg),
686
687 DEVMETHOD_END
688 };
689
690 driver_t dwc_driver = {
691 "dwc",
692 dwc_methods,
693 sizeof(struct dwc_softc),
694 };
695
696 DRIVER_MODULE(dwc, simplebus, dwc_driver, 0, 0);
697 DRIVER_MODULE(miibus, dwc, miibus_driver, 0, 0);
698
699 MODULE_DEPEND(dwc, ether, 1, 1, 1);
700 MODULE_DEPEND(dwc, miibus, 1, 1, 1);
701