]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/netfpga10g/nf10bmac/if_nf10bmac.c
MFV r329502: 7614 zfs device evacuation/removal
[FreeBSD/FreeBSD.git] / sys / dev / netfpga10g / nf10bmac / if_nf10bmac.c
1 /*-
2  * Copyright (c) 2012-2014 Bjoern A. Zeeb
3  * All rights reserved.
4  *
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.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
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.
17  *
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
28  * SUCH DAMAGE.
29  *
30  * This driver is modelled after atse(4).  We need to seriously reduce the
31  * per-driver code we have to write^wcopy & paste.
32  *
33  * TODO:
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)
37  */
38
39 #include <sys/cdefs.h>
40 __FBSDID("$FreeBSD$");
41
42 #include "opt_device_polling.h"
43 #include "opt_netfpga.h"
44
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/kernel.h>
48 #include <sys/bus.h>
49 #include <sys/endian.h>
50 #include <sys/lock.h>
51 #include <sys/module.h>
52 #include <sys/mutex.h>
53 #include <sys/proc.h>
54 #include <sys/socket.h>
55 #include <sys/sockio.h>
56 #include <sys/types.h>
57
58 #include <net/ethernet.h>
59 #include <net/if.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>
65
66 #include <net/bpf.h>
67
68 #include <machine/bus.h>
69 #include <machine/resource.h>
70 #include <sys/rman.h>
71
72 #include "if_nf10bmacreg.h"
73
74 #ifndef NF10BMAC_MAX_PKTS
75 /*
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.
79  */
80 #define NF10BMAC_MAX_PKTS               3
81 #endif
82
83 #ifndef NF10BMAC_WATCHDOG_TIME
84 #define NF10BMAC_WATCHDOG_TIME          5       /* seconds */
85 #endif
86
87 #ifdef DEVICE_POLLING
88 static poll_handler_t nf10bmac_poll;
89 #endif
90
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)
95
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
105
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)
114
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
124 #else
125 #define NF10BMAC_DATA_STRB              0x0000000f
126 #define REGWTYPE                        uint32_t
127 #endif
128
129
130 static inline void
131 nf10bmac_write(struct resource *res, REGWTYPE reg, REGWTYPE val,
132     const char *f __unused, const int l __unused)
133 {
134
135 #ifdef NF10BMAC_64BIT
136         bus_write_8(res, reg, htole64(val));
137 #else
138         bus_write_4(res, reg, htole32(val));
139 #endif
140 }
141
142 static inline REGWTYPE
143 nf10bmac_read(struct resource *res, REGWTYPE reg,
144     const char *f __unused, const int l __unused)
145 {
146
147 #ifdef NF10BMAC_64BIT
148         return (le64toh(bus_read_8(res, reg)));
149 #else
150         return (le32toh(bus_read_4(res, reg)));
151 #endif
152 }
153
154 static inline void
155 nf10bmac_write_be(struct resource *res, REGWTYPE reg, REGWTYPE val,
156     const char *f __unused, const int l __unused)
157 {
158
159 #ifdef NF10BMAC_64BIT
160         bus_write_8(res, reg, htobe64(val));
161 #else
162         bus_write_4(res, reg, htobe32(val));
163 #endif
164 }
165
166
167 static inline REGWTYPE
168 nf10bmac_read_be(struct resource *res, REGWTYPE reg,
169     const char *f __unused, const int l __unused)
170 {
171
172 #ifdef NF10BMAC_64BIT
173         return (be64toh(bus_read_8(res, reg)));
174 #else
175         return (be32toh(bus_read_4(res, reg)));
176 #endif
177 }
178
179 #define NF10BMAC_WRITE_CTRL(sc, reg, val)                               \
180         nf10bmac_write((sc)->nf10bmac_ctrl_res, (reg), (val),           \
181             __func__, __LINE__)
182 #define NF10BMAC_WRITE(sc, reg, val)                                    \
183         nf10bmac_write((sc)->nf10bmac_tx_mem_res, (reg), (val),         \
184             __func__, __LINE__)
185 #define NF10BMAC_READ(sc, reg)                                          \
186         nf10bmac_read((sc)->nf10bmac_rx_mem_res, (reg),                 \
187             __func__, __LINE__)
188 #define NF10BMAC_WRITE_BE(sc, reg, val)                                 \
189         nf10bmac_write_be((sc)->nf10bmac_tx_mem_res, (reg), (val),      \
190             __func__, __LINE__)
191 #define NF10BMAC_READ_BE(sc, reg)                                       \
192         nf10bmac_read_be((sc)->nf10bmac_rx_mem_res, (reg),              \
193             __func__, __LINE__)
194
195 #define NF10BMAC_WRITE_INTR(sc, reg, val, _f, _l)                       \
196         nf10bmac_write((sc)->nf10bmac_intr_res, (reg), (val),           \
197             (_f), (_l))
198
199 #define NF10BMAC_RX_INTR_CLEAR_DIS(sc)                                  \
200         NF10BMAC_WRITE_INTR((sc), NF10BMAC_INTR_CLEAR_DIS, 1,           \
201         __func__, __LINE__)
202 #define NF10BMAC_RX_INTR_ENABLE(sc)                                     \
203         NF10BMAC_WRITE_INTR((sc), NF10BMAC_INTR_CTRL, 1,                \
204         __func__, __LINE__)
205 #define NF10BMAC_RX_INTR_DISABLE(sc)                                    \
206         NF10BMAC_WRITE_INTR((sc), NF10BMAC_INTR_CTRL, 0,                \
207         __func__, __LINE__)
208
209
210 #ifdef ENABLE_WATCHDOG
211 static void nf10bmac_tick(void *);
212 #endif
213 static int nf10bmac_detach(device_t);
214
215 devclass_t nf10bmac_devclass;
216
217
218 static int
219 nf10bmac_tx_locked(struct nf10bmac_softc *sc, struct mbuf *m)
220 {
221         int32_t len, l, ml;
222         REGWTYPE md, val;
223
224         NF10BMAC_LOCK_ASSERT(sc);
225
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));
228         /*
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
231          * quite quickly.
232          */
233         m_copydata(m, 0, m->m_pkthdr.len, sc->nf10bmac_tx_buf);
234         len = m->m_pkthdr.len;
235
236         /* Write the length at start of packet. */
237         NF10BMAC_WRITE(sc, NF10BMAC_TX_LEN, len);
238
239         /* Write the meta data and data. */
240         ml = len / sizeof(val);
241         len -= (ml * sizeof(val));
242         for (l = 0; l <= ml; l++) {
243                 int32_t cl;
244
245                 cl = sizeof(val);
246                 md = (NF10BMAC_TUSER_CPU0 << NF10BMAC_DATA_SPORT_SHIFT);
247                 if (l == ml || (len == 0 && l == (ml - 1))) {
248                         if (l == ml && len == 0) {
249                                 break;
250                         } else {
251                                 uint8_t s;
252                                 int sl;
253
254                                 if (l == (ml - 1))
255                                         len = sizeof(val);
256                                 cl = len;
257
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;
262                         }
263                 } else {
264                         md |= NF10BMAC_DATA_STRB;
265                 }
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);   
269         }
270
271         /* If anyone is interested give them a copy. */
272         BPF_MTAP(sc->nf10bmac_ifp, m);
273
274         m_freem(m);
275
276         return (0);
277 }
278
279 static void
280 nf10bmac_start_locked(struct ifnet *ifp)
281 {
282         struct nf10bmac_softc *sc;
283         int count, error;
284
285         sc = ifp->if_softc;
286         NF10BMAC_LOCK_ASSERT(sc);
287
288         if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
289             IFF_DRV_RUNNING || (sc->nf10bmac_flags & NF10BMAC_FLAGS_LINK) == 0)
290                 return;
291
292 #ifdef ENABLE_WATCHDOG
293         /*
294          * Disable the watchdog while sending, we are batching packets.
295          * Though we should never reach 5 seconds, and are holding the lock,
296          * but who knows.
297          */
298         sc->nf10bmac_watchdog_timer = 0;
299 #endif
300
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++) {
304                 struct mbuf *m;
305
306                 IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
307                 if (m == NULL)
308                         break;
309                 error = nf10bmac_tx_locked(sc, m);
310                 if (error != 0)
311                         break;
312         }
313
314 #ifdef ENABLE_WATCHDOG
315 done:
316         /* If the IP core walks into Nekromanteion try to bail out. */
317         /* XXX-BZ useless until we have direct FIFO fill status feedback. */
318         if (count > 0)
319                 sc->nf10bmac_watchdog_timer = NF10BMAC_WATCHDOG_TIME;
320 #endif
321 }
322
323 static void
324 nf10bmac_start(struct ifnet *ifp)
325 {
326         struct nf10bmac_softc *sc;
327
328         sc = ifp->if_softc;
329         NF10BMAC_LOCK(sc);
330         nf10bmac_start_locked(ifp);
331         NF10BMAC_UNLOCK(sc);
332 }
333
334 static void
335 nf10bmac_eat_packet_munch_munch(struct nf10bmac_softc *sc)
336 {
337         REGWTYPE md, val;
338
339         do {
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);
345 }
346
347 static int
348 nf10bmac_rx_locked(struct nf10bmac_softc *sc)
349 {
350         struct ifnet *ifp;
351         struct mbuf *m;
352         REGWTYPE md, val;
353         int32_t len, l;
354
355         /*
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
359          * skip to tlast).
360          */
361
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);
365                 return (0);
366         }
367
368         md = NF10BMAC_READ(sc, NF10BMAC_RX_META);
369         if (len == 0 && (md & NF10BMAC_DATA_STRB) == 0) {
370                 /* No packet data available. */
371                 return (0);
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);
375                 return (0);
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);
380                 return (0);
381         }
382
383         /* Assume at this point that we have data and a full packet. */
384         if ((len + ETHER_ALIGN) >= MINCLSIZE) {
385                 /* Get a cluster. */
386                 m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
387                 if (m == NULL)
388                         return (0);
389                 m->m_len = m->m_pkthdr.len = MCLBYTES;
390         } else {
391                 /* Hey this still fits into the mbuf+pkthdr. */
392                 m = m_gethdr(M_NOWAIT, MT_DATA);
393                 if (m == NULL)
394                         return (0);
395                 m->m_len = m->m_pkthdr.len = MHLEN;
396         }
397         /* Make sure upper layers will be aligned. */
398         m_adj(m, ETHER_ALIGN);
399
400         ifp = sc->nf10bmac_ifp;
401         l = 0;
402 /*
403         while ((md & NF10BMAC_DATA_STRB) != 0 && l < len) {
404 */
405         while (l < len) {
406                 size_t cl;
407
408                 if ((md & NF10BMAC_DATA_LAST) == 0 &&
409                     (len - l) < sizeof(val)) {
410                         /*
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.
415                          */
416                         nf10bmac_eat_packet_munch_munch(sc);            
417                         if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
418                         m_freem(m);
419                         return (0);
420                 } else if ((len - l) <= sizeof(val)) {
421                         cl = len - l;
422                 } else {
423                         cl = sizeof(val);
424                 }
425
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);
429                 l += cl;
430
431                 if ((md & NF10BMAC_DATA_LAST) != 0 || l >= len)
432                         break;
433                 else {
434                         DELAY(50);
435                         md = NF10BMAC_READ(sc, NF10BMAC_RX_META);
436                 }
437
438                 cl = 10;
439                 while ((md & NF10BMAC_DATA_STRB) == 0 && cl-- > 0) {
440                         DELAY(10);
441                         md = NF10BMAC_READ(sc, NF10BMAC_RX_META);
442                 }
443         }
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);
449                 m_freem(m);
450                 return (0);
451         }
452
453         m->m_pkthdr.len = m->m_len = len;
454         m->m_pkthdr.rcvif = ifp;
455         if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
456
457         NF10BMAC_UNLOCK(sc);
458         (*ifp->if_input)(ifp, m);
459         NF10BMAC_LOCK(sc);
460
461         return (1);
462 }
463
464
465 static int
466 nf10bmac_stop_locked(struct nf10bmac_softc *sc)
467 {
468         struct ifnet *ifp;
469
470         NF10BMAC_LOCK_ASSERT(sc);
471
472 #ifdef ENABLE_WATCHDOG
473         sc->nf10bmac_watchdog_timer = 0;
474         callout_stop(&sc->nf10bmac_tick);
475 #endif
476
477         ifp = sc->nf10bmac_ifp;
478         ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
479         NF10BMAC_RX_INTR_CLEAR_DIS(sc);
480
481         sc->nf10bmac_flags &= ~NF10BMAC_FLAGS_LINK;
482         if_link_state_change(ifp, LINK_STATE_DOWN);
483
484         return (0);
485 }
486
487 static int
488 nf10bmac_reset(struct nf10bmac_softc *sc)
489 {
490
491         /*
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.
499          */
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;
508         }
509
510         return (0);
511 }
512
513 static void
514 nf10bmac_init_locked(struct nf10bmac_softc *sc)
515 {
516         struct ifnet *ifp;
517         uint8_t *eaddr;
518
519         NF10BMAC_LOCK_ASSERT(sc);
520         ifp = sc->nf10bmac_ifp;
521
522         if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
523                 return;
524
525         /*
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().
529          */
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. */
533
534         /* Make things frind to halt, cleanup, ... */
535         nf10bmac_stop_locked(sc);
536         /* ... reset, ... */
537         nf10bmac_reset(sc);
538
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);
542
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);
547         } else
548 #endif
549         {
550                 NF10BMAC_RX_INTR_ENABLE(sc);
551         }
552
553         ifp->if_drv_flags |= IFF_DRV_RUNNING;
554         ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
555
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);
559
560 #ifdef ENABLE_WATCHDOG
561         callout_reset(&sc->nf10bmac_tick, hz, nf10bmac_tick, sc);
562 #endif
563 }
564
565 static void
566 nf10bmac_init(void *xsc)
567 {
568         struct nf10bmac_softc *sc;
569
570         sc = (struct nf10bmac_softc *)xsc;
571         NF10BMAC_LOCK(sc);
572         nf10bmac_init_locked(sc);
573         NF10BMAC_UNLOCK(sc);
574 }
575
576 #ifdef ENABLE_WATCHDOG
577 static void
578 nf10bmac_watchdog(struct nf10bmac_softc *sc)
579 {
580
581         NF10BMAC_LOCK_ASSERT(sc);
582
583         if (sc->nf10bmac_watchdog_timer == 0 || --sc->nf10bmac_watchdog_timer > 0)
584                 return;
585
586         device_printf(sc->nf10bmac_dev, "watchdog timeout\n");
587         sc->nf10if_inc_counter(bmac_ifp, IFCOUNTER_OERRORS, 1);
588
589         sc->nf10bmac_ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
590         nf10bmac_init_locked(sc);
591
592         if (!IFQ_DRV_IS_EMPTY(&sc->nf10bmac_ifp->if_snd))
593                 nf10bmac_start_locked(sc->nf10bmac_ifp);
594 }
595
596 static void
597 nf10bmac_tick(void *xsc)
598 {
599         struct nf10bmac_softc *sc;
600         struct ifnet *ifp;
601
602         sc = (struct nf10bmac_softc *)xsc;
603         NF10BMAC_LOCK_ASSERT(sc);
604         ifp = sc->nf10bmac_ifp;
605
606         nf10bmac_watchdog(sc);
607         callout_reset(&sc->nf10bmac_tick, hz, nf10bmac_tick, sc);
608 }
609 #endif
610
611 static void
612 nf10bmac_intr(void *arg)
613 {
614         struct nf10bmac_softc *sc;
615         struct ifnet *ifp;
616         int rx_npkts;
617
618         sc = (struct nf10bmac_softc *)arg;
619         ifp = sc->nf10bmac_ifp;
620
621         NF10BMAC_LOCK(sc);
622 #ifdef DEVICE_POLLING
623         if (ifp->if_capenable & IFCAP_POLLING) {
624                 NF10BMAC_UNLOCK(sc);
625                 return;
626         } 
627 #endif
628
629         /* NF10BMAC_RX_INTR_DISABLE(sc); */
630         NF10BMAC_RX_INTR_CLEAR_DIS(sc);
631
632         /* We only have an RX interrupt and no status information. */
633         rx_npkts = 0;
634         while (rx_npkts < NF10BMAC_MAX_PKTS) {
635                 int c;
636
637                 c = nf10bmac_rx_locked(sc);
638                 rx_npkts += c;
639                 if (c == 0)
640                         break;
641         }
642
643         if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
644                 /* Re-enable interrupts. */
645                 NF10BMAC_RX_INTR_ENABLE(sc);
646
647                 if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
648                         nf10bmac_start_locked(ifp);
649         }
650         NF10BMAC_UNLOCK(sc);
651 }
652
653
654 #ifdef DEVICE_POLLING
655 static int
656 nf10bmac_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
657 {
658         struct nf10bmac_softc *sc;
659         int rx_npkts = 0;
660
661         sc = ifp->if_softc;
662         NF10BMAC_LOCK(sc);
663         if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
664                 NF10BMAC_UNLOCK(sc);
665                 return (rx_npkts);
666         }
667
668         while (rx_npkts < count) {
669                 int c;
670
671                 c = nf10bmac_rx_locked(sc);
672                 rx_npkts += c;
673                 if (c == 0)
674                         break;
675         }
676         nf10bmac_start_locked(ifp);
677
678         if (rx_npkts > 0 || cmd == POLL_AND_CHECK_STATUS) {
679                 /* We currently cannot do much. */
680                 ;
681         }
682
683         NF10BMAC_UNLOCK(sc);
684         return (rx_npkts);
685 }
686 #else
687 #error We only support polling mode
688 #endif /* DEVICE_POLLING */
689
690 static int
691 nf10bmac_media_change(struct ifnet *ifp __unused)
692 {
693
694         /* Do nothing. */
695         return (0);
696 }
697
698 static void
699 nf10bmac_media_status(struct ifnet *ifp __unused, struct ifmediareq *imr)
700
701
702         imr->ifm_status = IFM_AVALID | IFM_ACTIVE;
703         imr->ifm_active = IFM_ETHER | IFM_10G_T | IFM_FDX;
704 }
705
706 static int
707 nf10bmac_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
708 {
709         struct nf10bmac_softc *sc;
710         struct ifreq *ifr;
711         int error, mask;
712
713         error = 0;
714         sc = ifp->if_softc;
715         ifr = (struct ifreq *)data;
716
717         switch (command) {
718         case SIOCSIFFLAGS:
719                 NF10BMAC_LOCK(sc);
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. */ ;
725                         else
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;
730                 NF10BMAC_UNLOCK(sc);
731                 break;
732         case SIOCSIFCAP:
733                 NF10BMAC_LOCK(sc);
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) {
740
741                                 error = ether_poll_register(nf10bmac_poll, ifp);
742                                 if (error != 0) {
743                                         NF10BMAC_UNLOCK(sc);
744                                         break;
745                                 }
746
747                                 NF10BMAC_RX_INTR_CLEAR_DIS(sc);
748
749                         /*
750                          * Do not allow disabling of polling if we do
751                          * not have interrupts.
752                          */
753                         } else if (sc->nf10bmac_rx_irq_res != NULL) {
754                                 error = ether_poll_deregister(ifp);
755                                 /* Enable interrupts. */
756                                 NF10BMAC_RX_INTR_ENABLE(sc);
757                         } else {
758                                 ifp->if_capenable ^= IFCAP_POLLING;
759                                 error = EINVAL;
760                         }
761                 }
762 #endif /* DEVICE_POLLING */
763                 NF10BMAC_UNLOCK(sc);
764                 break;
765         case SIOCGIFMEDIA:
766         case SIOCSIFMEDIA:
767                 error = ifmedia_ioctl(ifp, ifr, &sc->nf10bmac_media, command);
768                 break;
769         default:
770                 error = ether_ioctl(ifp, command, data);
771                 break;
772         }
773
774         return (error);
775 }
776
777 /*
778  * Generic device handling routines.
779  */
780 int
781 nf10bmac_attach(device_t dev)
782 {
783         struct nf10bmac_softc *sc;
784         struct ifnet *ifp;
785         int error;
786
787         sc = device_get_softc(dev);
788
789         mtx_init(&sc->nf10bmac_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
790             MTX_DEF);
791
792 #ifdef  ENABLE_WATCHDOG
793         callout_init_mtx(&sc->nf10bmac_tick, &sc->nf10bmac_mtx, 0);
794 #endif
795
796         sc->nf10bmac_tx_buf = malloc(ETHER_MAX_LEN_JUMBO, M_DEVBUF, M_WAITOK);
797
798         /* Reset the adapter. */
799         nf10bmac_reset(sc);
800
801         /* Setup interface. */
802         ifp = sc->nf10bmac_ifp = if_alloc(IFT_ETHER);
803         if (ifp == NULL) {   
804                 device_printf(dev, "if_alloc() failed\n");
805                 error = ENOSPC;
806                 goto err;
807         }
808         ifp->if_softc = sc;
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);
817
818         /* Call media-indepedent attach routine. */
819         ether_ifattach(ifp, sc->nf10bmac_eth_addr);
820
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;
828 #endif
829
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);
835
836         /* Initialise. */
837         error = 0;
838
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);
844                 if (error != 0) {
845                         device_printf(dev, "enabling RX IRQ failed\n");
846                         ether_ifdetach(ifp);
847                         goto err;
848                 }
849         }
850
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;
857                         device_printf(dev,
858                             "forcing to polling due to no interrupts\n");
859                 }
860                 error = ether_poll_register(nf10bmac_poll, ifp);
861                 if (error != 0)
862                         goto err;
863 #else
864                 device_printf(dev, "no DEVICE_POLLING in kernel and no IRQs\n");
865                 error = ENXIO;
866 #endif
867         } else {
868                 NF10BMAC_RX_INTR_ENABLE(sc);
869         }
870
871 err:
872         if (error != 0)
873                 nf10bmac_detach(dev);
874
875         return (error);                                                                                                                                                                      
876 }
877
878 static int
879 nf10bmac_detach(device_t dev)
880 {
881         struct nf10bmac_softc *sc;
882         struct ifnet *ifp;
883
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;
888
889 #ifdef DEVICE_POLLING
890         if (ifp->if_capenable & IFCAP_POLLING)
891                 ether_poll_deregister(ifp);
892 #endif
893
894         /* Only cleanup if attach succeeded. */
895         if (device_is_attached(dev)) {
896                 NF10BMAC_LOCK(sc);
897                 nf10bmac_stop_locked(sc);
898                 NF10BMAC_UNLOCK(sc);
899 #ifdef ENABLE_WATCHDOG
900                 callout_drain(&sc->nf10bmac_tick);
901 #endif
902                 ether_ifdetach(ifp);
903         }
904
905         if (sc->nf10bmac_rx_intrhand)
906                 bus_teardown_intr(dev, sc->nf10bmac_rx_irq_res,
907                     sc->nf10bmac_rx_intrhand);
908
909         if (ifp != NULL)
910                 if_free(ifp);
911         ifmedia_removeall(&sc->nf10bmac_media);
912
913         mtx_destroy(&sc->nf10bmac_mtx);
914
915         return (0);
916 }
917
918 /* Shared with the attachment specific (e.g., fdt) implementation. */
919 void
920 nf10bmac_detach_resources(device_t dev)
921 {
922         struct nf10bmac_softc *sc;
923
924         sc = device_get_softc(dev);
925
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;
930         }
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;
935         }
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;
940         }
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;
945         }
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;
950         }
951 }
952
953 int
954 nf10bmac_detach_dev(device_t dev)
955 {
956         int error;
957
958         error = nf10bmac_detach(dev);
959         if (error) {
960                 /* We are basically in undefined state now. */
961                 device_printf(dev, "nf10bmac_detach() failed: %d\n", error);
962                 return (error);
963         }
964
965         nf10bmac_detach_resources(dev);
966
967         return (0);
968 }
969
970 /* end */