2 * Copyright (c) 2012-2014 Bjoern A. Zeeb
5 * This software was developed by SRI International and the University of
6 * Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-11-C-0249
7 * ("MRC2"), as part of the DARPA MRC research programme.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * This driver is modelled after atse(4). We need to seriously reduce the
31 * per-driver code we have to write^wcopy & paste.
34 * - figure out on the HW side why some data is LE and some is BE.
35 * - general set of improvements possible (e.g., reduce times of copying,
36 * do on-the-copy checksum calculations)
39 #include <sys/cdefs.h>
40 __FBSDID("$FreeBSD$");
42 #include "opt_device_polling.h"
43 #include "opt_netfpga.h"
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/kernel.h>
49 #include <sys/endian.h>
51 #include <sys/module.h>
52 #include <sys/mutex.h>
54 #include <sys/socket.h>
55 #include <sys/sockio.h>
56 #include <sys/types.h>
58 #include <net/ethernet.h>
60 #include <net/if_var.h>
61 #include <net/if_dl.h>
62 #include <net/if_media.h>
63 #include <net/if_types.h>
64 #include <net/if_vlan_var.h>
68 #include <machine/bus.h>
69 #include <machine/resource.h>
72 #include "if_nf10bmacreg.h"
74 #ifndef NF10BMAC_MAX_PKTS
76 * We have a 4k buffer in HW, so do not try to send more than 3 packets.
77 * At the time of writing HW is orders of magnitude faster than we can
78 * enqueue so it would not matter but need an escape.
80 #define NF10BMAC_MAX_PKTS 3
83 #ifndef NF10BMAC_WATCHDOG_TIME
84 #define NF10BMAC_WATCHDOG_TIME 5 /* seconds */
88 static poll_handler_t nf10bmac_poll;
91 #define NF10BMAC_LOCK(_sc) mtx_lock(&(_sc)->nf10bmac_mtx)
92 #define NF10BMAC_UNLOCK(_sc) mtx_unlock(&(_sc)->nf10bmac_mtx)
93 #define NF10BMAC_LOCK_ASSERT(_sc) \
94 mtx_assert(&(_sc)->nf10bmac_mtx, MA_OWNED)
96 #define NF10BMAC_CTRL0 0x00
97 #define NF10BMAC_TX_DATA 0x00
98 #define NF10BMAC_TX_META 0x08
99 #define NF10BMAC_TX_LEN 0x10
100 #define NF10BMAC_RX_DATA 0x00
101 #define NF10BMAC_RX_META 0x08
102 #define NF10BMAC_RX_LEN 0x10
103 #define NF10BMAC_INTR_CLEAR_DIS 0x00
104 #define NF10BMAC_INTR_CTRL 0x08
106 #define NF10BMAC_TUSER_MAC0 (1 << 0)
107 #define NF10BMAC_TUSER_CPU0 (1 << 1)
108 #define NF10BMAC_TUSER_MAC1 (1 << 2)
109 #define NF10BMAC_TUSER_CPU1 (1 << 3)
110 #define NF10BMAC_TUSER_MAC2 (1 << 4)
111 #define NF10BMAC_TUSER_CPU2 (1 << 5)
112 #define NF10BMAC_TUSER_MAC3 (1 << 6)
113 #define NF10BMAC_TUSER_CPU3 (1 << 7)
115 #define NF10BMAC_DATA_LEN_MASK 0x0000ffff
116 #define NF10BMAC_DATA_DPORT_MASK 0xff000000
117 #define NF10BMAC_DATA_DPORT_SHIFT 24
118 #define NF10BMAC_DATA_SPORT_MASK 0x00ff0000
119 #define NF10BMAC_DATA_SPORT_SHIFT 16
120 #define NF10BMAC_DATA_LAST 0x00008000
121 #ifdef NF10BMAC_64BIT
122 #define NF10BMAC_DATA_STRB 0x000000ff
123 #define REGWTYPE uint64_t
125 #define NF10BMAC_DATA_STRB 0x0000000f
126 #define REGWTYPE uint32_t
131 nf10bmac_write(struct resource *res, REGWTYPE reg, REGWTYPE val,
132 const char *f __unused, const int l __unused)
135 #ifdef NF10BMAC_64BIT
136 bus_write_8(res, reg, htole64(val));
138 bus_write_4(res, reg, htole32(val));
142 static inline REGWTYPE
143 nf10bmac_read(struct resource *res, REGWTYPE reg,
144 const char *f __unused, const int l __unused)
147 #ifdef NF10BMAC_64BIT
148 return (le64toh(bus_read_8(res, reg)));
150 return (le32toh(bus_read_4(res, reg)));
155 nf10bmac_write_be(struct resource *res, REGWTYPE reg, REGWTYPE val,
156 const char *f __unused, const int l __unused)
159 #ifdef NF10BMAC_64BIT
160 bus_write_8(res, reg, htobe64(val));
162 bus_write_4(res, reg, htobe32(val));
167 static inline REGWTYPE
168 nf10bmac_read_be(struct resource *res, REGWTYPE reg,
169 const char *f __unused, const int l __unused)
172 #ifdef NF10BMAC_64BIT
173 return (be64toh(bus_read_8(res, reg)));
175 return (be32toh(bus_read_4(res, reg)));
179 #define NF10BMAC_WRITE_CTRL(sc, reg, val) \
180 nf10bmac_write((sc)->nf10bmac_ctrl_res, (reg), (val), \
182 #define NF10BMAC_WRITE(sc, reg, val) \
183 nf10bmac_write((sc)->nf10bmac_tx_mem_res, (reg), (val), \
185 #define NF10BMAC_READ(sc, reg) \
186 nf10bmac_read((sc)->nf10bmac_rx_mem_res, (reg), \
188 #define NF10BMAC_WRITE_BE(sc, reg, val) \
189 nf10bmac_write_be((sc)->nf10bmac_tx_mem_res, (reg), (val), \
191 #define NF10BMAC_READ_BE(sc, reg) \
192 nf10bmac_read_be((sc)->nf10bmac_rx_mem_res, (reg), \
195 #define NF10BMAC_WRITE_INTR(sc, reg, val, _f, _l) \
196 nf10bmac_write((sc)->nf10bmac_intr_res, (reg), (val), \
199 #define NF10BMAC_RX_INTR_CLEAR_DIS(sc) \
200 NF10BMAC_WRITE_INTR((sc), NF10BMAC_INTR_CLEAR_DIS, 1, \
202 #define NF10BMAC_RX_INTR_ENABLE(sc) \
203 NF10BMAC_WRITE_INTR((sc), NF10BMAC_INTR_CTRL, 1, \
205 #define NF10BMAC_RX_INTR_DISABLE(sc) \
206 NF10BMAC_WRITE_INTR((sc), NF10BMAC_INTR_CTRL, 0, \
210 #ifdef ENABLE_WATCHDOG
211 static void nf10bmac_tick(void *);
213 static int nf10bmac_detach(device_t);
215 devclass_t nf10bmac_devclass;
219 nf10bmac_tx_locked(struct nf10bmac_softc *sc, struct mbuf *m)
224 NF10BMAC_LOCK_ASSERT(sc);
226 KASSERT(m != NULL, ("%s: m is null: sc=%p", __func__, sc));
227 KASSERT(m->m_flags & M_PKTHDR, ("%s: not a pkthdr: m=%p", __func__, m));
229 * Copy to buffer to minimize our pain as we can only store
230 * double words which, after the first mbuf gets out of alignment
233 m_copydata(m, 0, m->m_pkthdr.len, sc->nf10bmac_tx_buf);
234 len = m->m_pkthdr.len;
236 /* Write the length at start of packet. */
237 NF10BMAC_WRITE(sc, NF10BMAC_TX_LEN, len);
239 /* Write the meta data and data. */
240 ml = len / sizeof(val);
241 len -= (ml * sizeof(val));
242 for (l = 0; l <= ml; l++) {
246 md = (NF10BMAC_TUSER_CPU0 << NF10BMAC_DATA_SPORT_SHIFT);
247 if (l == ml || (len == 0 && l == (ml - 1))) {
248 if (l == ml && len == 0) {
258 for (s = 0, sl = len; sl > 0; sl--)
259 s |= (1 << (sl - 1));
260 md |= (s & NF10BMAC_DATA_STRB);
261 md |= NF10BMAC_DATA_LAST;
264 md |= NF10BMAC_DATA_STRB;
266 NF10BMAC_WRITE(sc, NF10BMAC_TX_META, md);
267 bcopy(&sc->nf10bmac_tx_buf[l*sizeof(val)], &val, cl);
268 NF10BMAC_WRITE_BE(sc, NF10BMAC_TX_DATA, val);
271 /* If anyone is interested give them a copy. */
272 BPF_MTAP(sc->nf10bmac_ifp, m);
280 nf10bmac_start_locked(struct ifnet *ifp)
282 struct nf10bmac_softc *sc;
286 NF10BMAC_LOCK_ASSERT(sc);
288 if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
289 IFF_DRV_RUNNING || (sc->nf10bmac_flags & NF10BMAC_FLAGS_LINK) == 0)
292 #ifdef ENABLE_WATCHDOG
294 * Disable the watchdog while sending, we are batching packets.
295 * Though we should never reach 5 seconds, and are holding the lock,
298 sc->nf10bmac_watchdog_timer = 0;
301 /* Send up to MAX_PKTS_PER_TX_LOOP packets. */
302 for (count = 0; !IFQ_DRV_IS_EMPTY(&ifp->if_snd) &&
303 count < NF10BMAC_MAX_PKTS; count++) {
306 IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
309 error = nf10bmac_tx_locked(sc, m);
314 #ifdef ENABLE_WATCHDOG
316 /* If the IP core walks into Nekromanteion try to bail out. */
317 /* XXX-BZ useless until we have direct FIFO fill status feedback. */
319 sc->nf10bmac_watchdog_timer = NF10BMAC_WATCHDOG_TIME;
324 nf10bmac_start(struct ifnet *ifp)
326 struct nf10bmac_softc *sc;
330 nf10bmac_start_locked(ifp);
335 nf10bmac_eat_packet_munch_munch(struct nf10bmac_softc *sc)
340 md = NF10BMAC_READ_BE(sc, NF10BMAC_RX_META);
341 if ((md & NF10BMAC_DATA_STRB) != 0)
342 val = NF10BMAC_READ_BE(sc, NF10BMAC_RX_DATA);
343 } while ((md & NF10BMAC_DATA_STRB) != 0 &&
344 (md & NF10BMAC_DATA_LAST) == 0);
348 nf10bmac_rx_locked(struct nf10bmac_softc *sc)
356 * General problem here in case we need to sync ourselves to the
357 * beginning of a packet. Length will only be set for the first
358 * read, and together with strb we can detect the beginning (or
362 len = NF10BMAC_READ(sc, NF10BMAC_RX_LEN) & NF10BMAC_DATA_LEN_MASK;
363 if (len > (MCLBYTES - ETHER_ALIGN)) {
364 nf10bmac_eat_packet_munch_munch(sc);
368 md = NF10BMAC_READ(sc, NF10BMAC_RX_META);
369 if (len == 0 && (md & NF10BMAC_DATA_STRB) == 0) {
370 /* No packet data available. */
372 } else if (len == 0 && (md & NF10BMAC_DATA_STRB) != 0) {
373 /* We are in the middle of a packet. */
374 nf10bmac_eat_packet_munch_munch(sc);
376 } else if ((md & NF10BMAC_DATA_STRB) == 0) {
377 /* Invalid length "hint". */
378 device_printf(sc->nf10bmac_dev,
379 "Unexpected length %d on zero strb\n", len);
383 /* Assume at this point that we have data and a full packet. */
384 if ((len + ETHER_ALIGN) >= MINCLSIZE) {
386 m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
389 m->m_len = m->m_pkthdr.len = MCLBYTES;
391 /* Hey this still fits into the mbuf+pkthdr. */
392 m = m_gethdr(M_NOWAIT, MT_DATA);
395 m->m_len = m->m_pkthdr.len = MHLEN;
397 /* Make sure upper layers will be aligned. */
398 m_adj(m, ETHER_ALIGN);
400 ifp = sc->nf10bmac_ifp;
403 while ((md & NF10BMAC_DATA_STRB) != 0 && l < len) {
408 if ((md & NF10BMAC_DATA_LAST) == 0 &&
409 (len - l) < sizeof(val)) {
411 * Our length and LAST disagree. We have a valid STRB.
412 * We could continue until we fill the mbuf and just
413 * log the invlid length "hint". For now drop the
414 * packet on the floor and count the error.
416 nf10bmac_eat_packet_munch_munch(sc);
417 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
420 } else if ((len - l) <= sizeof(val)) {
426 /* Read the first bytes of data as well. */
427 val = NF10BMAC_READ_BE(sc, NF10BMAC_RX_DATA);
428 bcopy(&val, (uint8_t *)(m->m_data + l), cl);
431 if ((md & NF10BMAC_DATA_LAST) != 0 || l >= len)
435 md = NF10BMAC_READ(sc, NF10BMAC_RX_META);
439 while ((md & NF10BMAC_DATA_STRB) == 0 && cl-- > 0) {
441 md = NF10BMAC_READ(sc, NF10BMAC_RX_META);
444 /* We should get out of this loop with tlast and tsrb. */
445 if ((md & NF10BMAC_DATA_LAST) == 0 || (md & NF10BMAC_DATA_STRB) == 0) {
446 device_printf(sc->nf10bmac_dev, "Unexpected rx loop end state: "
447 "md=0x%08jx len=%d l=%d\n", (uintmax_t)md, len, l);
448 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
453 m->m_pkthdr.len = m->m_len = len;
454 m->m_pkthdr.rcvif = ifp;
455 if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
458 (*ifp->if_input)(ifp, m);
466 nf10bmac_stop_locked(struct nf10bmac_softc *sc)
470 NF10BMAC_LOCK_ASSERT(sc);
472 #ifdef ENABLE_WATCHDOG
473 sc->nf10bmac_watchdog_timer = 0;
474 callout_stop(&sc->nf10bmac_tick);
477 ifp = sc->nf10bmac_ifp;
478 ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
479 NF10BMAC_RX_INTR_CLEAR_DIS(sc);
481 sc->nf10bmac_flags &= ~NF10BMAC_FLAGS_LINK;
482 if_link_state_change(ifp, LINK_STATE_DOWN);
488 nf10bmac_reset(struct nf10bmac_softc *sc)
492 * If we do not have an ether address set, initialize to the same
493 * OUI as NetFPGA-10G Linux driver does (which luckily seems
494 * unallocated). We just change the NIC specific part from
495 * the slightly long "\0NF10C0" to "\0NFBSD".
496 * Oh and we keep the way of setting it from a string as they do.
497 * It's an amazing way to hide it.
498 * XXX-BZ If NetFPGA gets their own OUI we should fix this.
500 if (sc->nf10bmac_eth_addr[0] == 0x00 &&
501 sc->nf10bmac_eth_addr[1] == 0x00 &&
502 sc->nf10bmac_eth_addr[2] == 0x00 &&
503 sc->nf10bmac_eth_addr[3] == 0x00 &&
504 sc->nf10bmac_eth_addr[4] == 0x00 &&
505 sc->nf10bmac_eth_addr[5] == 0x00) {
506 memcpy(&sc->nf10bmac_eth_addr, "\0NFBSD", ETHER_ADDR_LEN);
507 sc->nf10bmac_eth_addr[5] += sc->nf10bmac_unit;
514 nf10bmac_init_locked(struct nf10bmac_softc *sc)
519 NF10BMAC_LOCK_ASSERT(sc);
520 ifp = sc->nf10bmac_ifp;
522 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
526 * Must update the ether address if changed. Given we do not handle
527 * in nf10bmac_ioctl() but it's in the general framework, just always
528 * do it here before nf10bmac_reset().
530 eaddr = IF_LLADDR(sc->nf10bmac_ifp);
531 bcopy(eaddr, &sc->nf10bmac_eth_addr, ETHER_ADDR_LEN);
532 /* XXX-BZ we do not have any way to tell the NIC our ether address. */
534 /* Make things frind to halt, cleanup, ... */
535 nf10bmac_stop_locked(sc);
539 /* Memory rings? DMA engine? MC filter? MII? */
540 /* Instead drain the FIFO; or at least a possible first packet.. */
541 nf10bmac_eat_packet_munch_munch(sc);
543 #ifdef DEVICE_POLLING
544 /* Only enable interrupts if we are not polling. */
545 if (ifp->if_capenable & IFCAP_POLLING) {
546 NF10BMAC_RX_INTR_CLEAR_DIS(sc);
550 NF10BMAC_RX_INTR_ENABLE(sc);
553 ifp->if_drv_flags |= IFF_DRV_RUNNING;
554 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
556 /* We have no underlying media, fake link state. */
557 sc->nf10bmac_flags = NF10BMAC_FLAGS_LINK; /* Always up. */
558 if_link_state_change(sc->nf10bmac_ifp, LINK_STATE_UP);
560 #ifdef ENABLE_WATCHDOG
561 callout_reset(&sc->nf10bmac_tick, hz, nf10bmac_tick, sc);
566 nf10bmac_init(void *xsc)
568 struct nf10bmac_softc *sc;
570 sc = (struct nf10bmac_softc *)xsc;
572 nf10bmac_init_locked(sc);
576 #ifdef ENABLE_WATCHDOG
578 nf10bmac_watchdog(struct nf10bmac_softc *sc)
581 NF10BMAC_LOCK_ASSERT(sc);
583 if (sc->nf10bmac_watchdog_timer == 0 || --sc->nf10bmac_watchdog_timer > 0)
586 device_printf(sc->nf10bmac_dev, "watchdog timeout\n");
587 sc->nf10if_inc_counter(bmac_ifp, IFCOUNTER_OERRORS, 1);
589 sc->nf10bmac_ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
590 nf10bmac_init_locked(sc);
592 if (!IFQ_DRV_IS_EMPTY(&sc->nf10bmac_ifp->if_snd))
593 nf10bmac_start_locked(sc->nf10bmac_ifp);
597 nf10bmac_tick(void *xsc)
599 struct nf10bmac_softc *sc;
602 sc = (struct nf10bmac_softc *)xsc;
603 NF10BMAC_LOCK_ASSERT(sc);
604 ifp = sc->nf10bmac_ifp;
606 nf10bmac_watchdog(sc);
607 callout_reset(&sc->nf10bmac_tick, hz, nf10bmac_tick, sc);
612 nf10bmac_intr(void *arg)
614 struct nf10bmac_softc *sc;
618 sc = (struct nf10bmac_softc *)arg;
619 ifp = sc->nf10bmac_ifp;
622 #ifdef DEVICE_POLLING
623 if (ifp->if_capenable & IFCAP_POLLING) {
629 /* NF10BMAC_RX_INTR_DISABLE(sc); */
630 NF10BMAC_RX_INTR_CLEAR_DIS(sc);
632 /* We only have an RX interrupt and no status information. */
634 while (rx_npkts < NF10BMAC_MAX_PKTS) {
637 c = nf10bmac_rx_locked(sc);
643 if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
644 /* Re-enable interrupts. */
645 NF10BMAC_RX_INTR_ENABLE(sc);
647 if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
648 nf10bmac_start_locked(ifp);
654 #ifdef DEVICE_POLLING
656 nf10bmac_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
658 struct nf10bmac_softc *sc;
663 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
668 while (rx_npkts < count) {
671 c = nf10bmac_rx_locked(sc);
676 nf10bmac_start_locked(ifp);
678 if (rx_npkts > 0 || cmd == POLL_AND_CHECK_STATUS) {
679 /* We currently cannot do much. */
687 #error We only support polling mode
688 #endif /* DEVICE_POLLING */
691 nf10bmac_media_change(struct ifnet *ifp __unused)
699 nf10bmac_media_status(struct ifnet *ifp __unused, struct ifmediareq *imr)
702 imr->ifm_status = IFM_AVALID | IFM_ACTIVE;
703 imr->ifm_active = IFM_ETHER | IFM_10G_T | IFM_FDX;
707 nf10bmac_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
709 struct nf10bmac_softc *sc;
715 ifr = (struct ifreq *)data;
720 if (ifp->if_flags & IFF_UP) {
721 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0 &&
722 ((ifp->if_flags ^ sc->nf10bmac_if_flags) &
723 (IFF_PROMISC | IFF_ALLMULTI)) != 0)
724 /* Nothing we can do. */ ;
726 nf10bmac_init_locked(sc);
727 } else if (ifp->if_drv_flags & IFF_DRV_RUNNING)
728 nf10bmac_stop_locked(sc);
729 sc->nf10bmac_if_flags = ifp->if_flags;
734 mask = ifr->ifr_reqcap ^ ifp->if_capenable;
735 #ifdef DEVICE_POLLING
736 if ((mask & IFCAP_POLLING) != 0 &&
737 (IFCAP_POLLING & ifp->if_capabilities) != 0) {
738 ifp->if_capenable ^= IFCAP_POLLING;
739 if ((IFCAP_POLLING & ifp->if_capenable) != 0) {
741 error = ether_poll_register(nf10bmac_poll, ifp);
747 NF10BMAC_RX_INTR_CLEAR_DIS(sc);
750 * Do not allow disabling of polling if we do
751 * not have interrupts.
753 } else if (sc->nf10bmac_rx_irq_res != NULL) {
754 error = ether_poll_deregister(ifp);
755 /* Enable interrupts. */
756 NF10BMAC_RX_INTR_ENABLE(sc);
758 ifp->if_capenable ^= IFCAP_POLLING;
762 #endif /* DEVICE_POLLING */
767 error = ifmedia_ioctl(ifp, ifr, &sc->nf10bmac_media, command);
770 error = ether_ioctl(ifp, command, data);
778 * Generic device handling routines.
781 nf10bmac_attach(device_t dev)
783 struct nf10bmac_softc *sc;
787 sc = device_get_softc(dev);
789 mtx_init(&sc->nf10bmac_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
792 #ifdef ENABLE_WATCHDOG
793 callout_init_mtx(&sc->nf10bmac_tick, &sc->nf10bmac_mtx, 0);
796 sc->nf10bmac_tx_buf = malloc(ETHER_MAX_LEN_JUMBO, M_DEVBUF, M_WAITOK);
798 /* Reset the adapter. */
801 /* Setup interface. */
802 ifp = sc->nf10bmac_ifp = if_alloc(IFT_ETHER);
804 device_printf(dev, "if_alloc() failed\n");
809 if_initname(ifp, device_get_name(dev), device_get_unit(dev));
810 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; /* | IFF_MULTICAST; */
811 ifp->if_ioctl = nf10bmac_ioctl;
812 ifp->if_start = nf10bmac_start;
813 ifp->if_init = nf10bmac_init;
814 IFQ_SET_MAXLEN(&ifp->if_snd, NF10BMAC_MAX_PKTS - 1);
815 ifp->if_snd.ifq_drv_maxlen = NF10BMAC_MAX_PKTS - 1;
816 IFQ_SET_READY(&ifp->if_snd);
818 /* Call media-indepedent attach routine. */
819 ether_ifattach(ifp, sc->nf10bmac_eth_addr);
821 /* Tell the upper layer(s) about vlan mtu support. */
822 ifp->if_hdrlen = sizeof(struct ether_vlan_header);
823 ifp->if_capabilities |= IFCAP_VLAN_MTU;
824 ifp->if_capenable = ifp->if_capabilities;
825 #ifdef DEVICE_POLLING
826 /* We will enable polling by default if no irqs available. See below. */
827 ifp->if_capabilities |= IFCAP_POLLING;
830 /* We need more media attention. Fake it! */
831 ifmedia_init(&sc->nf10bmac_media, 0, nf10bmac_media_change,
832 nf10bmac_media_status);
833 ifmedia_add(&sc->nf10bmac_media, IFM_ETHER | IFM_10G_T, 0, NULL);
834 ifmedia_set(&sc->nf10bmac_media, IFM_ETHER | IFM_10G_T);
839 /* Hook up interrupts. Well the one. */
840 if (sc->nf10bmac_rx_irq_res != NULL) {
841 error = bus_setup_intr(dev, sc->nf10bmac_rx_irq_res,
842 INTR_TYPE_NET | INTR_MPSAFE, NULL, nf10bmac_intr,
843 sc, &sc->nf10bmac_rx_intrhand);
845 device_printf(dev, "enabling RX IRQ failed\n");
851 if ((ifp->if_capenable & IFCAP_POLLING) != 0 ||
852 sc->nf10bmac_rx_irq_res == NULL) {
853 #ifdef DEVICE_POLLING
854 /* If not on and no IRQs force it on. */
855 if (sc->nf10bmac_rx_irq_res == NULL) {
856 ifp->if_capenable |= IFCAP_POLLING;
858 "forcing to polling due to no interrupts\n");
860 error = ether_poll_register(nf10bmac_poll, ifp);
864 device_printf(dev, "no DEVICE_POLLING in kernel and no IRQs\n");
868 NF10BMAC_RX_INTR_ENABLE(sc);
873 nf10bmac_detach(dev);
879 nf10bmac_detach(device_t dev)
881 struct nf10bmac_softc *sc;
884 sc = device_get_softc(dev);
885 KASSERT(mtx_initialized(&sc->nf10bmac_mtx),
886 ("%s: mutex not initialized", device_get_nameunit(dev)));
887 ifp = sc->nf10bmac_ifp;
889 #ifdef DEVICE_POLLING
890 if (ifp->if_capenable & IFCAP_POLLING)
891 ether_poll_deregister(ifp);
894 /* Only cleanup if attach succeeded. */
895 if (device_is_attached(dev)) {
897 nf10bmac_stop_locked(sc);
899 #ifdef ENABLE_WATCHDOG
900 callout_drain(&sc->nf10bmac_tick);
905 if (sc->nf10bmac_rx_intrhand)
906 bus_teardown_intr(dev, sc->nf10bmac_rx_irq_res,
907 sc->nf10bmac_rx_intrhand);
911 ifmedia_removeall(&sc->nf10bmac_media);
913 mtx_destroy(&sc->nf10bmac_mtx);
918 /* Shared with the attachment specific (e.g., fdt) implementation. */
920 nf10bmac_detach_resources(device_t dev)
922 struct nf10bmac_softc *sc;
924 sc = device_get_softc(dev);
926 if (sc->nf10bmac_rx_irq_res != NULL) {
927 bus_release_resource(dev, SYS_RES_IRQ, sc->nf10bmac_rx_irq_rid,
928 sc->nf10bmac_rx_irq_res);
929 sc->nf10bmac_rx_irq_res = NULL;
931 if (sc->nf10bmac_intr_res != NULL) {
932 bus_release_resource(dev, SYS_RES_MEMORY,
933 sc->nf10bmac_intr_rid, sc->nf10bmac_intr_res);
934 sc->nf10bmac_intr_res = NULL;
936 if (sc->nf10bmac_rx_mem_res != NULL) {
937 bus_release_resource(dev, SYS_RES_MEMORY,
938 sc->nf10bmac_rx_mem_rid, sc->nf10bmac_rx_mem_res);
939 sc->nf10bmac_rx_mem_res = NULL;
941 if (sc->nf10bmac_tx_mem_res != NULL) {
942 bus_release_resource(dev, SYS_RES_MEMORY,
943 sc->nf10bmac_tx_mem_rid, sc->nf10bmac_tx_mem_res);
944 sc->nf10bmac_tx_mem_res = NULL;
946 if (sc->nf10bmac_ctrl_res != NULL) {
947 bus_release_resource(dev, SYS_RES_MEMORY,
948 sc->nf10bmac_ctrl_rid, sc->nf10bmac_ctrl_res);
949 sc->nf10bmac_ctrl_res = NULL;
954 nf10bmac_detach_dev(device_t dev)
958 error = nf10bmac_detach(dev);
960 /* We are basically in undefined state now. */
961 device_printf(dev, "nf10bmac_detach() failed: %d\n", error);
965 nf10bmac_detach_resources(dev);