source: rtems-libbsd/freebsd/sys/dev/dwc/if_dwc.c @ ebc797f

4.1155-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since ebc797f was ebc797f, checked in by Sebastian Huber <sebastian.huber@…>, on 04/07/15 at 11:53:16

if_dwc: Increase DMA descriptor count

This prevents some packet loss under heavy load conditions.

  • Property mode set to 100644
File size: 35.7 KB
Line 
1#include <machine/rtems-bsd-kernel-space.h>
2
3/*-
4 * Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
5 * All rights reserved.
6 *
7 * This software was developed by SRI International and the University of
8 * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
9 * ("CTSRD"), as part of the DARPA CRASH research programme.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in the
18 *    documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33/*
34 * Ethernet media access controller (EMAC)
35 * Chapter 17, Altera Cyclone V Device Handbook (CV-5V2 2014.07.22)
36 *
37 * EMAC is an instance of the Synopsys DesignWare 3504-0
38 * Universal 10/100/1000 Ethernet MAC (DWC_gmac).
39 */
40
41#include <sys/cdefs.h>
42__FBSDID("$FreeBSD$");
43
44#include <rtems/bsd/sys/param.h>
45#include <sys/systm.h>
46#include <sys/bus.h>
47#include <sys/kernel.h>
48#include <sys/module.h>
49#include <sys/malloc.h>
50#include <sys/rman.h>
51#include <sys/endian.h>
52#include <rtems/bsd/sys/lock.h>
53#include <sys/mbuf.h>
54#include <sys/mutex.h>
55#include <sys/socket.h>
56#include <sys/sockio.h>
57#include <sys/sysctl.h>
58
59#ifndef __rtems__
60#include <dev/fdt/fdt_common.h>
61#include <dev/ofw/openfirm.h>
62#include <dev/ofw/ofw_bus.h>
63#include <dev/ofw/ofw_bus_subr.h>
64#endif /* __rtems__ */
65
66#include <net/bpf.h>
67#include <net/if.h>
68#include <net/ethernet.h>
69#include <net/if_dl.h>
70#include <net/if_media.h>
71#include <net/if_types.h>
72#include <net/if_var.h>
73#include <net/if_vlan_var.h>
74
75#include <machine/bus.h>
76#ifndef __rtems__
77#include <machine/fdt.h>
78#endif /* __rtems__ */
79
80#include <dev/mii/mii.h>
81#include <dev/mii/miivar.h>
82#include <rtems/bsd/local/miibus_if.h>
83#ifdef __rtems__
84#pragma GCC diagnostic ignored "-Wpointer-sign"
85#include <rtems/bsd/bsd.h>
86#endif /* __rtems__ */
87
88#define READ4(_sc, _reg) \
89        bus_read_4((_sc)->res[0], _reg)
90#define WRITE4(_sc, _reg, _val) \
91        bus_write_4((_sc)->res[0], _reg, _val)
92
93#define MAC_RESET_TIMEOUT       100
94#define WATCHDOG_TIMEOUT_SECS   5
95#define STATS_HARVEST_INTERVAL  2
96#define MII_CLK_VAL             2
97
98#include <dev/dwc/if_dwc.h>
99
100#define DWC_LOCK(sc)                    mtx_lock(&(sc)->mtx)
101#define DWC_UNLOCK(sc)                  mtx_unlock(&(sc)->mtx)
102#define DWC_ASSERT_LOCKED(sc)           mtx_assert(&(sc)->mtx, MA_OWNED);
103#define DWC_ASSERT_UNLOCKED(sc)         mtx_assert(&(sc)->mtx, MA_NOTOWNED);
104
105#define DDESC_TDES0_OWN                 (1 << 31)
106#define DDESC_TDES0_TXINT               (1 << 30)
107#define DDESC_TDES0_TXLAST              (1 << 29)
108#define DDESC_TDES0_TXFIRST             (1 << 28)
109#define DDESC_TDES0_TXCRCDIS            (1 << 27)
110#define DDESC_TDES0_CIC_IP_HDR          (0x1 << 22)
111#define DDESC_TDES0_CIC_IP_HDR_PYL      (0x2 << 22)
112#define DDESC_TDES0_CIC_IP_HDR_PYL_PHDR (0x3 << 22)
113#define DDESC_TDES0_TXRINGEND           (1 << 21)
114#define DDESC_TDES0_TXCHAIN             (1 << 20)
115
116#define DDESC_RDES0_OWN                 (1 << 31)
117#define DDESC_RDES0_FL_MASK             0x3fff
118#define DDESC_RDES0_FL_SHIFT            16      /* Frame Length */
119#define DDESC_RDES0_ESA                 (1 << 0)
120#define DDESC_RDES1_CHAINED             (1 << 14)
121#define DDESC_RDES4_IP_PYL_ERR          (1 << 4)
122#define DDESC_RDES4_IP_HDR_ERR          (1 << 3)
123#define DDESC_RDES4_IP_PYL_TYPE_MSK     0x7
124#define DDESC_RDES4_IP_PYL_UDP          1
125#define DDESC_RDES4_IP_PYL_TCP          2
126
127struct dwc_bufmap {
128#ifndef __rtems__
129        bus_dmamap_t    map;
130#endif /* __rtems__ */
131        struct mbuf     *mbuf;
132};
133
134/*
135 * A hardware buffer descriptor.  Rx and Tx buffers have the same descriptor
136 * layout, but the bits in the flags field have different meanings.
137 */
138struct dwc_hwdesc
139{
140        uint32_t tdes0;
141        uint32_t tdes1;
142        uint32_t addr;          /* pointer to buffer data */
143        uint32_t addr_next;     /* link to next descriptor */
144        uint32_t tdes4;
145        uint32_t tdes5;
146        uint32_t timestamp_low;
147        uint32_t timestamp_high;
148};
149
150/*
151 * Driver data and defines.
152 */
153#ifndef __rtems__
154#define RX_DESC_COUNT   1024
155#else /* __rtems__ */
156#define RX_DESC_COUNT   256
157#endif /* __rtems__ */
158#define RX_DESC_SIZE    (sizeof(struct dwc_hwdesc) * RX_DESC_COUNT)
159#define TX_DESC_COUNT   1024
160#define TX_DESC_SIZE    (sizeof(struct dwc_hwdesc) * TX_DESC_COUNT)
161#define TX_MAX_DMA_SEGS 8       /* maximum segs in a tx mbuf dma */
162
163/*
164 * The hardware imposes alignment restrictions on various objects involved in
165 * DMA transfers.  These values are expressed in bytes (not bits).
166 */
167#define DWC_DESC_RING_ALIGN             2048
168
169#define DWC_CKSUM_ASSIST        (CSUM_IP | CSUM_TCP | CSUM_UDP | \
170                                 CSUM_TCP_IPV6 | CSUM_UDP_IPV6)
171
172struct dwc_softc {
173        struct resource         *res[2];
174        bus_space_tag_t         bst;
175        bus_space_handle_t      bsh;
176        device_t                dev;
177        int                     mii_clk;
178        device_t                miibus;
179        struct mii_data *       mii_softc;
180        struct ifnet            *ifp;
181        int                     if_flags;
182        struct mtx              mtx;
183        void *                  intr_cookie;
184        struct callout          dwc_callout;
185        uint8_t                 phy_conn_type;
186        uint8_t                 mactype;
187        boolean_t               link_is_up;
188        boolean_t               is_attached;
189        boolean_t               is_detaching;
190        int                     tx_watchdog_count;
191        int                     stats_harvest_count;
192
193        /* RX */
194        bus_dma_tag_t           rxdesc_tag;
195        bus_dmamap_t            rxdesc_map;
196        struct dwc_hwdesc       *rxdesc_ring;
197#ifndef __rtems__
198        bus_addr_t              rxdesc_ring_paddr;
199        bus_dma_tag_t           rxbuf_tag;
200#endif /* __rtems__ */
201        struct dwc_bufmap       rxbuf_map[RX_DESC_COUNT];
202        uint32_t                rx_idx;
203
204        /* TX */
205        bus_dma_tag_t           txdesc_tag;
206        bus_dmamap_t            txdesc_map;
207        struct dwc_hwdesc       *txdesc_ring;
208#ifndef __rtems__
209        bus_addr_t              txdesc_ring_paddr;
210        bus_dma_tag_t           txbuf_tag;
211#endif /* __rtems__ */
212        struct dwc_bufmap       txbuf_map[TX_DESC_COUNT];
213        uint32_t                tx_idx_head;
214        uint32_t                tx_idx_tail;
215        int                     txcount;
216};
217
218static struct resource_spec dwc_spec[] = {
219        { SYS_RES_MEMORY,       0,      RF_ACTIVE },
220        { SYS_RES_IRQ,          0,      RF_ACTIVE },
221        { -1, 0 }
222};
223
224static void dwc_txfinish_locked(struct dwc_softc *sc);
225static void dwc_rxfinish_locked(struct dwc_softc *sc);
226static void dwc_stop_locked(struct dwc_softc *sc);
227static void dwc_setup_rxfilter(struct dwc_softc *sc);
228
229static inline uint32_t
230next_rxidx(struct dwc_softc *sc, uint32_t curidx)
231{
232
233        return ((curidx + 1) % RX_DESC_COUNT);
234}
235
236static inline uint32_t
237next_txidx(struct dwc_softc *sc, uint32_t curidx, int inc)
238{
239
240        return ((curidx + (uint32_t)inc) % TX_DESC_COUNT);
241}
242
243#ifndef __rtems__
244static void
245dwc_get1paddr(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
246{
247
248        if (error != 0)
249                return;
250        *(bus_addr_t *)arg = segs[0].ds_addr;
251}
252#endif /* __rtems__ */
253
254static void
255dwc_setup_txdesc(struct dwc_softc *sc, int csum_flags, int idx,
256    bus_dma_segment_t segs[TX_MAX_DMA_SEGS], int nsegs)
257{
258        int i;
259
260        sc->txcount += nsegs;
261
262        idx = next_txidx(sc, idx, nsegs);
263        sc->tx_idx_head = idx;
264
265        /*
266         * Fill in the TX descriptors back to front so that OWN bit in first
267         * descriptor is set last.
268         */
269        for (i = nsegs - 1; i >= 0; i--) {
270                uint32_t tdes0;
271
272                idx = next_txidx(sc, idx, -1);
273
274                sc->txdesc_ring[idx].addr = segs[i].ds_addr;
275                sc->txdesc_ring[idx].tdes1 = segs[i].ds_len;
276                wmb();
277
278                tdes0 = DDESC_TDES0_TXCHAIN | DDESC_TDES0_TXINT |
279                    DDESC_TDES0_OWN;
280
281                if (i == 0) {
282                        tdes0 |= DDESC_TDES0_TXFIRST;
283
284                        if ((csum_flags & (CSUM_TCP | CSUM_UDP |
285                            CSUM_TCP_IPV6 | CSUM_UDP_IPV6)) != 0)
286                                tdes0 |= DDESC_TDES0_CIC_IP_HDR_PYL_PHDR;
287                        else if ((csum_flags & CSUM_IP) != 0)
288                                tdes0 |= DDESC_TDES0_CIC_IP_HDR;
289                }
290
291                if (i == nsegs - 1)
292                        tdes0 |= DDESC_TDES0_TXLAST;
293
294                sc->txdesc_ring[idx].tdes0 = tdes0;
295                wmb();
296
297                if (i != 0)
298                        sc->txbuf_map[idx].mbuf = NULL;
299        }
300}
301
302#ifdef __rtems__
303static int
304dwc_get_segs_for_tx(struct mbuf *m, bus_dma_segment_t segs[TX_MAX_DMA_SEGS],
305    int *nsegs)
306{
307        int i = 0;
308
309        do {
310                if (m->m_len > 0) {
311                        segs[i].ds_addr = mtod(m, bus_addr_t);
312                        segs[i].ds_len = m->m_len;
313                        rtems_cache_flush_multiple_data_lines(m->m_data, m->m_len);
314                        ++i;
315                }
316
317                m = m->m_next;
318
319                if (m == NULL) {
320                        *nsegs = i;
321
322                        return (0);
323                }
324        } while (i < TX_MAX_DMA_SEGS);
325
326        return (EFBIG);
327}
328#endif /* __rtems__ */
329static void
330dwc_setup_txbuf(struct dwc_softc *sc, struct mbuf *m, int *start_tx)
331{
332        bus_dma_segment_t segs[TX_MAX_DMA_SEGS];
333        int error, nsegs, idx;
334
335        idx = sc->tx_idx_head;
336#ifndef __rtems__
337        error = bus_dmamap_load_mbuf_sg(sc->txbuf_tag, sc->txbuf_map[idx].map,
338            m, &seg, &nsegs, BUS_DMA_NOWAIT);
339
340#else /* __rtems__ */
341        error = dwc_get_segs_for_tx(m, segs, &nsegs);
342#endif /* __rtems__ */
343        if (error == EFBIG) {
344                /* Too many segments!  Defrag and try again. */
345                struct mbuf *m2 = m_defrag(m, M_NOWAIT);
346
347                if (m2 == NULL) {
348                        m_freem(m);
349                        return;
350                }
351                m = m2;
352#ifndef __rtems__
353                error = bus_dmamap_load_mbuf_sg(sc->txbuf_tag,
354                    sc->txbuf_map[idx].map, m, &seg, &nsegs, BUS_DMA_NOWAIT);
355#else /* __rtems__ */
356                error = dwc_get_segs_for_tx(m, segs, &nsegs);
357#endif /* __rtems__ */
358        }
359        if (error != 0) {
360                /* Give up. */
361                m_freem(m);
362                return;
363        }
364
365        sc->txbuf_map[idx].mbuf = m;
366
367#ifndef __rtems__
368        bus_dmamap_sync(sc->txbuf_tag, sc->txbuf_map[idx].map,
369            BUS_DMASYNC_PREWRITE);
370#endif /* __rtems__ */
371
372        dwc_setup_txdesc(sc, m->m_pkthdr.csum_flags, idx, segs, nsegs);
373
374        ETHER_BPF_MTAP(sc->ifp, m);
375        *start_tx = 1;
376}
377
378static void
379dwc_txstart_locked(struct dwc_softc *sc)
380{
381        struct ifnet *ifp;
382        struct mbuf *m;
383        int start_tx;
384
385        DWC_ASSERT_LOCKED(sc);
386
387        if (!sc->link_is_up)
388                return;
389
390        ifp = sc->ifp;
391
392        start_tx = 0;
393
394        for (;;) {
395                if (sc->txcount >= (TX_DESC_COUNT - 1 - TX_MAX_DMA_SEGS)) {
396                        ifp->if_drv_flags |= IFF_DRV_OACTIVE;
397                        break;
398                }
399
400                IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
401                if (m == NULL)
402                        break;
403
404                dwc_setup_txbuf(sc, m, &start_tx);
405        }
406
407        if (start_tx != 0) {
408                WRITE4(sc, TRANSMIT_POLL_DEMAND, 0x1);
409                sc->tx_watchdog_count = WATCHDOG_TIMEOUT_SECS;
410        }
411}
412
413static void
414dwc_txstart(struct ifnet *ifp)
415{
416        struct dwc_softc *sc = ifp->if_softc;
417
418        DWC_LOCK(sc);
419        if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0)
420                dwc_txstart_locked(sc);
421        DWC_UNLOCK(sc);
422}
423
424static void
425dwc_stop_locked(struct dwc_softc *sc)
426{
427        struct ifnet *ifp;
428        int reg;
429
430        DWC_ASSERT_LOCKED(sc);
431
432        ifp = sc->ifp;
433        ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
434        sc->tx_watchdog_count = 0;
435        sc->stats_harvest_count = 0;
436
437        callout_stop(&sc->dwc_callout);
438
439        /* Stop DMA TX */
440        reg = READ4(sc, OPERATION_MODE);
441        reg &= ~(MODE_ST);
442        WRITE4(sc, OPERATION_MODE, reg);
443
444        /* Flush TX */
445        reg = READ4(sc, OPERATION_MODE);
446        reg |= (MODE_FTF);
447        WRITE4(sc, OPERATION_MODE, reg);
448
449        /* Stop transmitters */
450        reg = READ4(sc, MAC_CONFIGURATION);
451        reg &= ~(CONF_TE | CONF_RE);
452        WRITE4(sc, MAC_CONFIGURATION, reg);
453
454        /* Stop DMA RX */
455        reg = READ4(sc, OPERATION_MODE);
456        reg &= ~(MODE_SR);
457        WRITE4(sc, OPERATION_MODE, reg);
458}
459
460static void dwc_clear_stats(struct dwc_softc *sc)
461{
462        int reg;
463
464        reg = READ4(sc, MMC_CONTROL);
465        reg |= (MMC_CONTROL_CNTRST);
466        WRITE4(sc, MMC_CONTROL, reg);
467}
468
469static void
470dwc_harvest_stats(struct dwc_softc *sc)
471{
472        struct ifnet *ifp;
473
474        /* We don't need to harvest too often. */
475        if (++sc->stats_harvest_count < STATS_HARVEST_INTERVAL)
476                return;
477
478        sc->stats_harvest_count = 0;
479        ifp = sc->ifp;
480
481#ifndef __rtems__
482        if_inc_counter(ifp, IFCOUNTER_IPACKETS, READ4(sc, RXFRAMECOUNT_GB));
483        if_inc_counter(ifp, IFCOUNTER_IMCASTS, READ4(sc, RXMULTICASTFRAMES_G));
484        if_inc_counter(ifp, IFCOUNTER_IERRORS,
485            READ4(sc, RXOVERSIZE_G) + READ4(sc, RXUNDERSIZE_G) +
486            READ4(sc, RXCRCERROR) + READ4(sc, RXALIGNMENTERROR) +
487            READ4(sc, RXRUNTERROR) + READ4(sc, RXJABBERERROR) +
488            READ4(sc, RXLENGTHERROR));
489
490        if_inc_counter(ifp, IFCOUNTER_OPACKETS, READ4(sc, TXFRAMECOUNT_G));
491        if_inc_counter(ifp, IFCOUNTER_OMCASTS, READ4(sc, TXMULTICASTFRAMES_G));
492        if_inc_counter(ifp, IFCOUNTER_OERRORS,
493            READ4(sc, TXOVERSIZE_G) + READ4(sc, TXEXCESSDEF) +
494            READ4(sc, TXCARRIERERR) + READ4(sc, TXUNDERFLOWERROR));
495
496        if_inc_counter(ifp, IFCOUNTER_COLLISIONS,
497            READ4(sc, TXEXESSCOL) + READ4(sc, TXLATECOL));
498#else /* __rtems__ */
499        ifp->if_ipackets += READ4(sc, RXFRAMECOUNT_GB);
500        ifp->if_imcasts += READ4(sc, RXMULTICASTFRAMES_G);
501        ifp->if_ierrors +=
502            READ4(sc, RXOVERSIZE_G) + READ4(sc, RXUNDERSIZE_G) +
503            READ4(sc, RXCRCERROR) + READ4(sc, RXALIGNMENTERROR) +
504            READ4(sc, RXRUNTERROR) + READ4(sc, RXJABBERERROR) +
505            READ4(sc, RXLENGTHERROR);
506
507        ifp->if_opackets += READ4(sc, TXFRAMECOUNT_G);
508        ifp->if_omcasts += READ4(sc, TXMULTICASTFRAMES_G);
509        ifp->if_oerrors +=
510            READ4(sc, TXOVERSIZE_G) + READ4(sc, TXEXCESSDEF) +
511            READ4(sc, TXCARRIERERR) + READ4(sc, TXUNDERFLOWERROR);
512
513        ifp->if_collisions +=
514            READ4(sc, TXEXESSCOL) + READ4(sc, TXLATECOL);
515#endif /* __rtems__ */
516
517        dwc_clear_stats(sc);
518}
519
520static void
521dwc_tick(void *arg)
522{
523        struct dwc_softc *sc;
524        struct ifnet *ifp;
525        int link_was_up;
526
527        sc = arg;
528
529        DWC_ASSERT_LOCKED(sc);
530
531        ifp = sc->ifp;
532
533        if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
534            return;
535
536        /*
537         * Typical tx watchdog.  If this fires it indicates that we enqueued
538         * packets for output and never got a txdone interrupt for them.  Maybe
539         * it's a missed interrupt somehow, just pretend we got one.
540         */
541        if (sc->tx_watchdog_count > 0) {
542                if (--sc->tx_watchdog_count == 0) {
543                        dwc_txfinish_locked(sc);
544                }
545        }
546
547        /* Gather stats from hardware counters. */
548        dwc_harvest_stats(sc);
549
550        /* Check the media status. */
551        link_was_up = sc->link_is_up;
552        mii_tick(sc->mii_softc);
553        if (sc->link_is_up && !link_was_up)
554                dwc_txstart_locked(sc);
555
556        /* Schedule another check one second from now. */
557        callout_reset(&sc->dwc_callout, hz, dwc_tick, sc);
558}
559
560static void
561dwc_init_locked(struct dwc_softc *sc)
562{
563        struct ifnet *ifp = sc->ifp;
564        int reg;
565
566        DWC_ASSERT_LOCKED(sc);
567
568        if (ifp->if_drv_flags & IFF_DRV_RUNNING)
569                return;
570
571        ifp->if_drv_flags |= IFF_DRV_RUNNING;
572
573        dwc_setup_rxfilter(sc);
574
575        /* Initializa DMA and enable transmitters */
576        reg = READ4(sc, OPERATION_MODE);
577        reg |= (MODE_TSF | MODE_OSF | MODE_FUF);
578        reg &= ~(MODE_RSF);
579        reg |= (MODE_RTC_LEV32 << MODE_RTC_SHIFT);
580        WRITE4(sc, OPERATION_MODE, reg);
581
582        WRITE4(sc, INTERRUPT_ENABLE, INT_EN_DEFAULT);
583
584        /* Start DMA */
585        reg = READ4(sc, OPERATION_MODE);
586        reg |= (MODE_ST | MODE_SR);
587        WRITE4(sc, OPERATION_MODE, reg);
588
589        /* Enable transmitters */
590        reg = READ4(sc, MAC_CONFIGURATION);
591        reg |= (CONF_IPC);
592        reg |= (CONF_JD | CONF_ACS | CONF_BE);
593        reg |= (CONF_TE | CONF_RE);
594        WRITE4(sc, MAC_CONFIGURATION, reg);
595
596        /*
597         * Call mii_mediachg() which will call back into dwc_miibus_statchg()
598         * to set up the remaining config registers based on current media.
599         */
600        mii_mediachg(sc->mii_softc);
601        callout_reset(&sc->dwc_callout, hz, dwc_tick, sc);
602}
603
604static void
605dwc_init(void *if_softc)
606{
607        struct dwc_softc *sc = if_softc;
608
609        DWC_LOCK(sc);
610        dwc_init_locked(sc);
611        DWC_UNLOCK(sc);
612}
613
614inline static uint32_t
615dwc_setup_rxdesc(struct dwc_softc *sc, int idx, bus_addr_t paddr)
616{
617        uint32_t nidx;
618
619        sc->rxdesc_ring[idx].addr = (uint32_t)paddr;
620        nidx = next_rxidx(sc, idx);
621#ifndef __rtems__
622        sc->rxdesc_ring[idx].addr_next = sc->rxdesc_ring_paddr +        \
623            (nidx * sizeof(struct dwc_hwdesc));
624#else /* __rtems__ */
625        sc->rxdesc_ring[idx].addr_next = (uint32_t)&sc->rxdesc_ring[nidx];
626#endif /* __rtems__ */
627        sc->rxdesc_ring[idx].tdes1 = DDESC_RDES1_CHAINED | MCLBYTES;
628
629        wmb();
630        sc->rxdesc_ring[idx].tdes0 = DDESC_RDES0_OWN;
631        wmb();
632
633        return (nidx);
634}
635
636static int
637dwc_setup_rxbuf(struct dwc_softc *sc, int idx, struct mbuf *m)
638{
639        bus_dma_segment_t seg;
640#ifndef __rtems__
641        int error, nsegs;
642#endif /* __rtems__ */
643
644        m_adj(m, ETHER_ALIGN);
645
646#ifndef __rtems__
647        error = bus_dmamap_load_mbuf_sg(sc->rxbuf_tag, sc->rxbuf_map[idx].map,
648            m, &seg, &nsegs, 0);
649        if (error != 0) {
650                return (error);
651        }
652
653        KASSERT(nsegs == 1, ("%s: %d segments returned!", __func__, nsegs));
654
655        bus_dmamap_sync(sc->rxbuf_tag, sc->rxbuf_map[idx].map,
656            BUS_DMASYNC_PREREAD);
657#else /* __rtems__ */
658        rtems_cache_invalidate_multiple_data_lines(m->m_data, m->m_len);
659        seg.ds_addr = mtod(m, bus_addr_t);
660#endif /* __rtems__ */
661
662        sc->rxbuf_map[idx].mbuf = m;
663        dwc_setup_rxdesc(sc, idx, seg.ds_addr);
664
665        return (0);
666}
667
668static struct mbuf *
669dwc_alloc_mbufcl(struct dwc_softc *sc)
670{
671        struct mbuf *m;
672
673        m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
674        if (m != NULL)
675                m->m_pkthdr.len = m->m_len = m->m_ext.ext_size;
676
677        return (m);
678}
679
680static void
681dwc_media_status(struct ifnet * ifp, struct ifmediareq *ifmr)
682{
683        struct dwc_softc *sc;
684        struct mii_data *mii;
685
686        sc = ifp->if_softc;
687        mii = sc->mii_softc;
688        DWC_LOCK(sc);
689        mii_pollstat(mii);
690        ifmr->ifm_active = mii->mii_media_active;
691        ifmr->ifm_status = mii->mii_media_status;
692        DWC_UNLOCK(sc);
693}
694
695static int
696dwc_media_change_locked(struct dwc_softc *sc)
697{
698
699        return (mii_mediachg(sc->mii_softc));
700}
701
702static int
703dwc_media_change(struct ifnet * ifp)
704{
705        struct dwc_softc *sc;
706        int error;
707
708        sc = ifp->if_softc;
709
710        DWC_LOCK(sc);
711        error = dwc_media_change_locked(sc);
712        DWC_UNLOCK(sc);
713        return (error);
714}
715
716static const uint8_t nibbletab[] = {
717        /* 0x0 0000 -> 0000 */  0x0,
718        /* 0x1 0001 -> 1000 */  0x8,
719        /* 0x2 0010 -> 0100 */  0x4,
720        /* 0x3 0011 -> 1100 */  0xc,
721        /* 0x4 0100 -> 0010 */  0x2,
722        /* 0x5 0101 -> 1010 */  0xa,
723        /* 0x6 0110 -> 0110 */  0x6,
724        /* 0x7 0111 -> 1110 */  0xe,
725        /* 0x8 1000 -> 0001 */  0x1,
726        /* 0x9 1001 -> 1001 */  0x9,
727        /* 0xa 1010 -> 0101 */  0x5,
728        /* 0xb 1011 -> 1101 */  0xd,
729        /* 0xc 1100 -> 0011 */  0x3,
730        /* 0xd 1101 -> 1011 */  0xb,
731        /* 0xe 1110 -> 0111 */  0x7,
732        /* 0xf 1111 -> 1111 */  0xf, };
733
734static uint8_t
735bitreverse(uint8_t x)
736{
737
738        return (nibbletab[x & 0xf] << 4) | nibbletab[x >> 4];
739}
740
741static void
742dwc_setup_rxfilter(struct dwc_softc *sc)
743{
744        struct ifmultiaddr *ifma;
745        struct ifnet *ifp;
746        uint8_t *eaddr;
747        uint32_t crc;
748        uint8_t val;
749        int hashbit;
750        int hashreg;
751        int ffval;
752        int reg;
753        int lo;
754        int hi;
755
756        DWC_ASSERT_LOCKED(sc);
757
758        ifp = sc->ifp;
759
760        /*
761         * Set the multicast (group) filter hash.
762         */
763        if ((ifp->if_flags & IFF_ALLMULTI))
764                ffval = (FRAME_FILTER_PM);
765        else {
766                ffval = (FRAME_FILTER_HMC);
767                if_maddr_rlock(ifp);
768                TAILQ_FOREACH(ifma, &sc->ifp->if_multiaddrs, ifma_link) {
769                        if (ifma->ifma_addr->sa_family != AF_LINK)
770                                continue;
771                        crc = ether_crc32_le(LLADDR((struct sockaddr_dl *)
772                                ifma->ifma_addr), ETHER_ADDR_LEN);
773
774                        /* Take lower 8 bits and reverse it */
775                        val = bitreverse(~crc & 0xff);
776                        hashreg = (val >> 5);
777                        hashbit = (val & 31);
778
779                        reg = READ4(sc, HASH_TABLE_REG(hashreg));
780                        reg |= (1 << hashbit);
781                        WRITE4(sc, HASH_TABLE_REG(hashreg), reg);
782                }
783                if_maddr_runlock(ifp);
784        }
785
786        /*
787         * Set the individual address filter hash.
788         */
789        if (ifp->if_flags & IFF_PROMISC)
790                ffval |= (FRAME_FILTER_PR);
791
792        /*
793         * Set the primary address.
794         */
795        eaddr = IF_LLADDR(ifp);
796        lo = eaddr[0] | (eaddr[1] << 8) | (eaddr[2] << 16) |
797            (eaddr[3] << 24);
798        hi = eaddr[4] | (eaddr[5] << 8);
799        WRITE4(sc, MAC_ADDRESS_LOW(0), lo);
800        WRITE4(sc, MAC_ADDRESS_HIGH(0), hi);
801        WRITE4(sc, MAC_FRAME_FILTER, ffval);
802}
803
804static int
805dwc_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
806{
807        struct dwc_softc *sc;
808        struct mii_data *mii;
809        struct ifreq *ifr;
810        int mask, error;
811
812        sc = ifp->if_softc;
813        ifr = (struct ifreq *)data;
814
815        error = 0;
816        switch (cmd) {
817        case SIOCSIFFLAGS:
818                DWC_LOCK(sc);
819                if (ifp->if_flags & IFF_UP) {
820                        if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
821                                if ((ifp->if_flags ^ sc->if_flags) &
822                                    (IFF_PROMISC | IFF_ALLMULTI))
823                                        dwc_setup_rxfilter(sc);
824                        } else {
825                                if (!sc->is_detaching)
826                                        dwc_init_locked(sc);
827                        }
828                } else {
829                        if (ifp->if_drv_flags & IFF_DRV_RUNNING)
830                                dwc_stop_locked(sc);
831                }
832                sc->if_flags = ifp->if_flags;
833                DWC_UNLOCK(sc);
834                break;
835        case SIOCADDMULTI:
836        case SIOCDELMULTI:
837                if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
838                        DWC_LOCK(sc);
839                        dwc_setup_rxfilter(sc);
840                        DWC_UNLOCK(sc);
841                }
842                break;
843        case SIOCSIFMEDIA:
844        case SIOCGIFMEDIA:
845                mii = sc->mii_softc;
846                error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd);
847                break;
848        case SIOCSIFCAP:
849                mask = ifp->if_capenable ^ ifr->ifr_reqcap;
850                if (mask & IFCAP_VLAN_MTU) {
851                        /* No work to do except acknowledge the change took */
852                        ifp->if_capenable ^= IFCAP_VLAN_MTU;
853                }
854                break;
855
856        default:
857                error = ether_ioctl(ifp, cmd, data);
858                break;
859        }
860
861        return (error);
862}
863
864static void
865dwc_txfinish_locked(struct dwc_softc *sc)
866{
867        struct dwc_bufmap *bmap;
868        struct dwc_hwdesc *desc;
869
870        DWC_ASSERT_LOCKED(sc);
871
872        while (sc->tx_idx_tail != sc->tx_idx_head) {
873                desc = &sc->txdesc_ring[sc->tx_idx_tail];
874                if ((desc->tdes0 & DDESC_TDES0_OWN) != 0)
875                        break;
876                bmap = &sc->txbuf_map[sc->tx_idx_tail];
877#ifndef __rtems__
878                bus_dmamap_sync(sc->txbuf_tag, bmap->map,
879                    BUS_DMASYNC_POSTWRITE);
880                bus_dmamap_unload(sc->txbuf_tag, bmap->map);
881#endif /* __rtems__ */
882                m_freem(bmap->mbuf);
883                bmap->mbuf = NULL;
884                --sc->txcount;
885                sc->tx_idx_tail = next_txidx(sc, sc->tx_idx_tail, 1);
886        }
887
888        sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
889        dwc_txstart_locked(sc);
890
891        /* If there are no buffers outstanding, muzzle the watchdog. */
892        if (sc->tx_idx_tail == sc->tx_idx_head) {
893                sc->tx_watchdog_count = 0;
894        }
895}
896
897static void
898dwc_rxfinish_locked(struct dwc_softc *sc)
899{
900        struct ifnet *ifp;
901        struct mbuf *m0;
902        struct mbuf *m;
903        int error;
904        uint32_t rdes0;
905        uint32_t rdes4;
906        int idx;
907        int len;
908
909        ifp = sc->ifp;
910
911        for (;;) {
912                idx = sc->rx_idx;
913
914                rdes0 = sc->rxdesc_ring[idx].tdes0;
915                if ((rdes0 & DDESC_RDES0_OWN) != 0)
916                        break;
917
918#ifndef __rtems__
919                bus_dmamap_sync(sc->rxbuf_tag, sc->rxbuf_map[idx].map,
920                    BUS_DMASYNC_POSTREAD);
921                bus_dmamap_unload(sc->rxbuf_tag, sc->rxbuf_map[idx].map);
922#endif /* __rtems__ */
923
924                len = (rdes0 >> DDESC_RDES0_FL_SHIFT) & DDESC_RDES0_FL_MASK;
925                if (len != 0) {
926                        m = sc->rxbuf_map[idx].mbuf;
927                        m->m_pkthdr.rcvif = ifp;
928                        m->m_pkthdr.len = len;
929                        m->m_len = len;
930
931                        /* Check checksum offload flags. */
932                        if ((rdes0 & DDESC_RDES0_ESA) != 0) {
933                                rdes4 = sc->rxdesc_ring[idx].tdes4;
934
935                                /* TCP or UDP checks out, IP checks out too. */
936                                if ((rdes4 & DDESC_RDES4_IP_PYL_TYPE_MSK) ==
937                                    DDESC_RDES4_IP_PYL_UDP ||
938                                    (rdes4 & DDESC_RDES4_IP_PYL_TYPE_MSK) ==
939                                    DDESC_RDES4_IP_PYL_TCP) {
940                                        m->m_pkthdr.csum_flags |=
941                                                CSUM_IP_CHECKED |
942                                                CSUM_IP_VALID |
943                                                CSUM_DATA_VALID |
944                                                CSUM_PSEUDO_HDR;
945                                        m->m_pkthdr.csum_data = 0xffff;
946                                } else if ((rdes4 & (DDESC_RDES4_IP_PYL_ERR |
947                                    DDESC_RDES4_IP_HDR_ERR)) == 0) {
948                                        /* Only IP checks out. */
949                                        m->m_pkthdr.csum_flags |=
950                                                CSUM_IP_CHECKED |
951                                                CSUM_IP_VALID;
952                                        m->m_pkthdr.csum_data = 0xffff;
953                                }
954                        }
955
956#ifndef __rtems__
957                        if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
958#else /* __rtems__ */
959                        ++ifp->if_ipackets;
960#endif /* __rtems__ */
961
962                        DWC_UNLOCK(sc);
963                        (*ifp->if_input)(ifp, m);
964                        DWC_LOCK(sc);
965                } else {
966                        /* XXX Zero-length packet ? */
967                }
968
969                if ((m0 = dwc_alloc_mbufcl(sc)) != NULL) {
970                        if ((error = dwc_setup_rxbuf(sc, idx, m0)) != 0) {
971                                /*
972                                 * XXX Now what?
973                                 * We've got a hole in the rx ring.
974                                 */
975                        }
976                } else
977#ifndef __rtems__
978                        if_inc_counter(sc->ifp, IFCOUNTER_IQDROPS, 1);
979#else /* __rtems__ */
980                        ++ifp->if_iqdrops;
981#endif /* __rtems__ */
982
983                sc->rx_idx = next_rxidx(sc, sc->rx_idx);
984        }
985}
986
987static void
988dwc_intr(void *arg)
989{
990        struct dwc_softc *sc;
991        uint32_t reg;
992
993        sc = arg;
994
995        DWC_LOCK(sc);
996
997        reg = READ4(sc, INTERRUPT_STATUS);
998        if (reg) {
999                mii_mediachg(sc->mii_softc);
1000                READ4(sc, SGMII_RGMII_SMII_CTRL_STATUS);
1001        }
1002
1003        reg = READ4(sc, DMA_STATUS);
1004        if (reg & DMA_STATUS_NIS) {
1005                if (reg & DMA_STATUS_RI)
1006                        dwc_rxfinish_locked(sc);
1007
1008                if (reg & DMA_STATUS_TI)
1009                        dwc_txfinish_locked(sc);
1010        }
1011
1012        if (reg & DMA_STATUS_AIS) {
1013                if (reg & DMA_STATUS_FBI) {
1014                        /* Fatal bus error */
1015                        device_printf(sc->dev,
1016                            "Ethernet DMA error, restarting controller.\n");
1017                        dwc_stop_locked(sc);
1018                        dwc_init_locked(sc);
1019                }
1020        }
1021
1022        WRITE4(sc, DMA_STATUS, reg & DMA_STATUS_INTR_MASK);
1023        DWC_UNLOCK(sc);
1024}
1025
1026static int
1027setup_dma(struct dwc_softc *sc)
1028{
1029        struct mbuf *m;
1030        int error;
1031        int nidx;
1032        int idx;
1033
1034        /*
1035         * Set up TX descriptor ring, descriptors, and dma maps.
1036         */
1037        error = bus_dma_tag_create(
1038            bus_get_dma_tag(sc->dev),   /* Parent tag. */
1039            DWC_DESC_RING_ALIGN, 0,     /* alignment, boundary */
1040            BUS_SPACE_MAXADDR_32BIT,    /* lowaddr */
1041            BUS_SPACE_MAXADDR,          /* highaddr */
1042            NULL, NULL,                 /* filter, filterarg */
1043            TX_DESC_SIZE, 1,            /* maxsize, nsegments */
1044            TX_DESC_SIZE,               /* maxsegsize */
1045            0,                          /* flags */
1046            NULL, NULL,                 /* lockfunc, lockarg */
1047            &sc->txdesc_tag);
1048        if (error != 0) {
1049                device_printf(sc->dev,
1050                    "could not create TX ring DMA tag.\n");
1051                goto out;
1052        }
1053
1054        error = bus_dmamem_alloc(sc->txdesc_tag, (void**)&sc->txdesc_ring,
1055            BUS_DMA_COHERENT | BUS_DMA_WAITOK | BUS_DMA_ZERO,
1056            &sc->txdesc_map);
1057        if (error != 0) {
1058                device_printf(sc->dev,
1059                    "could not allocate TX descriptor ring.\n");
1060                goto out;
1061        }
1062
1063#ifndef __rtems__
1064        error = bus_dmamap_load(sc->txdesc_tag, sc->txdesc_map,
1065            sc->txdesc_ring, TX_DESC_SIZE, dwc_get1paddr,
1066            &sc->txdesc_ring_paddr, 0);
1067        if (error != 0) {
1068                device_printf(sc->dev,
1069                    "could not load TX descriptor ring map.\n");
1070                goto out;
1071        }
1072#endif /* __rtems__ */
1073
1074        for (idx = 0; idx < TX_DESC_COUNT; idx++) {
1075                sc->txdesc_ring[idx].addr = 0;
1076                sc->txdesc_ring[idx].tdes0 = DDESC_TDES0_TXCHAIN;
1077                sc->txdesc_ring[idx].tdes1 = 0;
1078                nidx = next_txidx(sc, idx, 1);
1079#ifndef __rtems__
1080                sc->txdesc_ring[idx].addr_next = sc->txdesc_ring_paddr + \
1081                    (nidx * sizeof(struct dwc_hwdesc));
1082#else /* __rtems__ */
1083                sc->txdesc_ring[idx].addr_next =
1084                    (uint32_t)&sc->txdesc_ring[nidx];
1085#endif /* __rtems__ */
1086        }
1087
1088#ifndef __rtems__
1089        error = bus_dma_tag_create(
1090            bus_get_dma_tag(sc->dev),   /* Parent tag. */
1091            1, 0,                       /* alignment, boundary */
1092            BUS_SPACE_MAXADDR_32BIT,    /* lowaddr */
1093            BUS_SPACE_MAXADDR,          /* highaddr */
1094            NULL, NULL,                 /* filter, filterarg */
1095            MCLBYTES, TX_MAX_DMA_SEGS,  /* maxsize, nsegments */
1096            MCLBYTES,                   /* maxsegsize */
1097            0,                          /* flags */
1098            NULL, NULL,                 /* lockfunc, lockarg */
1099            &sc->txbuf_tag);
1100        if (error != 0) {
1101                device_printf(sc->dev,
1102                    "could not create TX ring DMA tag.\n");
1103                goto out;
1104        }
1105#endif /* __rtems__ */
1106
1107        for (idx = 0; idx < TX_DESC_COUNT; idx++) {
1108#ifndef __rtems__
1109                error = bus_dmamap_create(sc->txbuf_tag, BUS_DMA_COHERENT,
1110                    &sc->txbuf_map[idx].map);
1111                if (error != 0) {
1112                        device_printf(sc->dev,
1113                            "could not create TX buffer DMA map.\n");
1114                        goto out;
1115                }
1116#endif /* __rtems__ */
1117        }
1118
1119        /*
1120         * Set up RX descriptor ring, descriptors, dma maps, and mbufs.
1121         */
1122        error = bus_dma_tag_create(
1123            bus_get_dma_tag(sc->dev),   /* Parent tag. */
1124            DWC_DESC_RING_ALIGN, 0,     /* alignment, boundary */
1125            BUS_SPACE_MAXADDR_32BIT,    /* lowaddr */
1126            BUS_SPACE_MAXADDR,          /* highaddr */
1127            NULL, NULL,                 /* filter, filterarg */
1128            RX_DESC_SIZE, 1,            /* maxsize, nsegments */
1129            RX_DESC_SIZE,               /* maxsegsize */
1130            0,                          /* flags */
1131            NULL, NULL,                 /* lockfunc, lockarg */
1132            &sc->rxdesc_tag);
1133        if (error != 0) {
1134                device_printf(sc->dev,
1135                    "could not create RX ring DMA tag.\n");
1136                goto out;
1137        }
1138
1139        error = bus_dmamem_alloc(sc->rxdesc_tag, (void **)&sc->rxdesc_ring,
1140            BUS_DMA_COHERENT | BUS_DMA_WAITOK | BUS_DMA_ZERO,
1141            &sc->rxdesc_map);
1142        if (error != 0) {
1143                device_printf(sc->dev,
1144                    "could not allocate RX descriptor ring.\n");
1145                goto out;
1146        }
1147
1148#ifndef __rtems__
1149        error = bus_dmamap_load(sc->rxdesc_tag, sc->rxdesc_map,
1150            sc->rxdesc_ring, RX_DESC_SIZE, dwc_get1paddr,
1151            &sc->rxdesc_ring_paddr, 0);
1152        if (error != 0) {
1153                device_printf(sc->dev,
1154                    "could not load RX descriptor ring map.\n");
1155                goto out;
1156        }
1157
1158        error = bus_dma_tag_create(
1159            bus_get_dma_tag(sc->dev),   /* Parent tag. */
1160            1, 0,                       /* alignment, boundary */
1161            BUS_SPACE_MAXADDR_32BIT,    /* lowaddr */
1162            BUS_SPACE_MAXADDR,          /* highaddr */
1163            NULL, NULL,                 /* filter, filterarg */
1164            MCLBYTES, 1,                /* maxsize, nsegments */
1165            MCLBYTES,                   /* maxsegsize */
1166            0,                          /* flags */
1167            NULL, NULL,                 /* lockfunc, lockarg */
1168            &sc->rxbuf_tag);
1169        if (error != 0) {
1170                device_printf(sc->dev,
1171                    "could not create RX buf DMA tag.\n");
1172                goto out;
1173        }
1174#endif /* __rtems__ */
1175
1176        for (idx = 0; idx < RX_DESC_COUNT; idx++) {
1177#ifndef __rtems__
1178                error = bus_dmamap_create(sc->rxbuf_tag, BUS_DMA_COHERENT,
1179                    &sc->rxbuf_map[idx].map);
1180                if (error != 0) {
1181                        device_printf(sc->dev,
1182                            "could not create RX buffer DMA map.\n");
1183                        goto out;
1184                }
1185#endif /* __rtems__ */
1186                if ((m = dwc_alloc_mbufcl(sc)) == NULL) {
1187                        device_printf(sc->dev, "Could not alloc mbuf\n");
1188                        error = ENOMEM;
1189                        goto out;
1190                }
1191                if ((error = dwc_setup_rxbuf(sc, idx, m)) != 0) {
1192                        device_printf(sc->dev,
1193                            "could not create new RX buffer.\n");
1194                        goto out;
1195                }
1196                sc->rxdesc_ring[idx].tdes4 = 0;
1197        }
1198
1199out:
1200        if (error != 0)
1201                return (ENXIO);
1202
1203        return (0);
1204}
1205
1206static int
1207dwc_get_hwaddr(struct dwc_softc *sc, uint8_t *hwaddr)
1208{
1209#ifndef __rtems__
1210        int rnd;
1211#endif /* __rtems__ */
1212        int lo;
1213        int hi;
1214
1215        /*
1216         * Try to recover a MAC address from the running hardware. If there's
1217         * something non-zero there, assume the bootloader did the right thing
1218         * and just use it.
1219         *
1220         * Otherwise, set the address to a convenient locally assigned address,
1221         * 'bsd' + random 24 low-order bits.  'b' is 0x62, which has the locally
1222         * assigned bit set, and the broadcast/multicast bit clear.
1223         */
1224        lo = READ4(sc, MAC_ADDRESS_LOW(0));
1225        hi = READ4(sc, MAC_ADDRESS_HIGH(0)) & 0xffff;
1226        if ((lo != 0xffffffff) || (hi != 0xffff)) {
1227                hwaddr[0] = (lo >>  0) & 0xff;
1228                hwaddr[1] = (lo >>  8) & 0xff;
1229                hwaddr[2] = (lo >> 16) & 0xff;
1230                hwaddr[3] = (lo >> 24) & 0xff;
1231                hwaddr[4] = (hi >>  0) & 0xff;
1232                hwaddr[5] = (hi >>  8) & 0xff;
1233        } else {
1234#ifndef __rtems__
1235                rnd = arc4random() & 0x00ffffff;
1236                hwaddr[0] = 'b';
1237                hwaddr[1] = 's';
1238                hwaddr[2] = 'd';
1239                hwaddr[3] = rnd >> 16;
1240                hwaddr[4] = rnd >>  8;
1241                hwaddr[5] = rnd >>  0;
1242#else /* __rtems__ */
1243                rtems_bsd_get_mac_address(device_get_name(sc->dev),
1244                    device_get_unit(sc->dev), hwaddr);
1245#endif /* __rtems__ */
1246        }
1247
1248        return (0);
1249}
1250
1251static int
1252dwc_probe(device_t dev)
1253{
1254
1255#ifndef __rtems__
1256        if (!ofw_bus_status_okay(dev))
1257                return (ENXIO);
1258
1259        if (!ofw_bus_is_compatible(dev, "snps,dwmac"))
1260                return (ENXIO);
1261#endif /* __rtems__ */
1262
1263        device_set_desc(dev, "Gigabit Ethernet Controller");
1264        return (BUS_PROBE_DEFAULT);
1265}
1266
1267static int
1268dwc_attach(device_t dev)
1269{
1270        uint8_t macaddr[ETHER_ADDR_LEN];
1271        struct dwc_softc *sc;
1272        struct ifnet *ifp;
1273        int error;
1274        int reg;
1275        int i;
1276
1277        sc = device_get_softc(dev);
1278        sc->dev = dev;
1279        sc->mii_clk = MII_CLK_VAL;
1280        sc->rx_idx = 0;
1281        sc->txcount = 0;
1282
1283        if (bus_alloc_resources(dev, dwc_spec, sc->res)) {
1284                device_printf(dev, "could not allocate resources\n");
1285                return (ENXIO);
1286        }
1287
1288        /* Memory interface */
1289        sc->bst = rman_get_bustag(sc->res[0]);
1290        sc->bsh = rman_get_bushandle(sc->res[0]);
1291
1292        /* Read MAC before reset */
1293        if (dwc_get_hwaddr(sc, macaddr)) {
1294                device_printf(sc->dev, "can't get mac\n");
1295                return (ENXIO);
1296        }
1297
1298        /* Reset */
1299        reg = READ4(sc, BUS_MODE);
1300        reg |= (BUS_MODE_SWR);
1301        WRITE4(sc, BUS_MODE, reg);
1302
1303        for (i = 0; i < MAC_RESET_TIMEOUT; i++) {
1304                if ((READ4(sc, BUS_MODE) & BUS_MODE_SWR) == 0)
1305                        break;
1306                DELAY(10);
1307        }
1308        if (i >= MAC_RESET_TIMEOUT) {
1309                device_printf(sc->dev, "Can't reset DWC.\n");
1310                return (ENXIO);
1311        }
1312
1313        reg = READ4(sc, BUS_MODE);
1314        reg |= (BUS_MODE_ATDS);
1315        reg |= (BUS_MODE_EIGHTXPBL);
1316        reg |= (BUS_MODE_PBL_BEATS_8 << BUS_MODE_PBL_SHIFT);
1317        WRITE4(sc, BUS_MODE, reg);
1318
1319        /*
1320         * DMA must be stop while changing descriptor list addresses.
1321         */
1322        reg = READ4(sc, OPERATION_MODE);
1323        reg &= ~(MODE_ST | MODE_SR);
1324        WRITE4(sc, OPERATION_MODE, reg);
1325
1326        if (setup_dma(sc))
1327                return (ENXIO);
1328
1329        /* Setup addresses */
1330#ifndef __rtems__
1331        WRITE4(sc, RX_DESCR_LIST_ADDR, sc->rxdesc_ring_paddr);
1332        WRITE4(sc, TX_DESCR_LIST_ADDR, sc->txdesc_ring_paddr);
1333#else /* __rtems__ */
1334        WRITE4(sc, RX_DESCR_LIST_ADDR, (uint32_t)&sc->rxdesc_ring[0]);
1335        WRITE4(sc, TX_DESCR_LIST_ADDR, (uint32_t)&sc->txdesc_ring[0]);
1336#endif /* __rtems__ */
1337
1338        mtx_init(&sc->mtx, device_get_nameunit(sc->dev),
1339            MTX_NETWORK_LOCK, MTX_DEF);
1340
1341        callout_init_mtx(&sc->dwc_callout, &sc->mtx, 0);
1342
1343        /* Set up the ethernet interface. */
1344        sc->ifp = ifp = if_alloc(IFT_ETHER);
1345
1346        ifp->if_softc = sc;
1347        if_initname(ifp, device_get_name(dev), device_get_unit(dev));
1348        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
1349        ifp->if_capabilities |= IFCAP_HWCSUM | IFCAP_HWCSUM_IPV6 |
1350            IFCAP_VLAN_MTU | IFCAP_VLAN_HWCSUM;
1351        ifp->if_capenable = ifp->if_capabilities;
1352        ifp->if_hwassist = DWC_CKSUM_ASSIST;
1353        ifp->if_start = dwc_txstart;
1354        ifp->if_ioctl = dwc_ioctl;
1355        ifp->if_init = dwc_init;
1356        IFQ_SET_MAXLEN(&ifp->if_snd, TX_DESC_COUNT - 1);
1357        ifp->if_snd.ifq_drv_maxlen = TX_DESC_COUNT - 1;
1358        IFQ_SET_READY(&ifp->if_snd);
1359        ifp->if_hdrlen = sizeof(struct ether_vlan_header);
1360
1361        /* Attach the mii driver. */
1362        error = mii_attach(dev, &sc->miibus, ifp, dwc_media_change,
1363            dwc_media_status, BMSR_DEFCAPMASK, MII_PHY_ANY,
1364            MII_OFFSET_ANY, 0);
1365
1366        if (error != 0) {
1367                device_printf(dev, "PHY attach failed\n");
1368                return (ENXIO);
1369        }
1370        sc->mii_softc = device_get_softc(sc->miibus);
1371
1372        /* Setup interrupt handler. */
1373        error = bus_setup_intr(dev, sc->res[1], INTR_TYPE_NET | INTR_MPSAFE,
1374            NULL, dwc_intr, sc, &sc->intr_cookie);
1375        if (error != 0) {
1376                device_printf(dev, "could not setup interrupt handler.\n");
1377                return (ENXIO);
1378        }
1379
1380        /* All ready to run, attach the ethernet interface. */
1381        ether_ifattach(ifp, macaddr);
1382        sc->is_attached = true;
1383
1384        return (0);
1385}
1386
1387static int
1388dwc_miibus_read_reg(device_t dev, int phy, int reg)
1389{
1390        struct dwc_softc *sc;
1391        uint16_t mii;
1392        size_t cnt;
1393        int rv = 0;
1394
1395        sc = device_get_softc(dev);
1396
1397        mii = ((phy & GMII_ADDRESS_PA_MASK) << GMII_ADDRESS_PA_SHIFT)
1398            | ((reg & GMII_ADDRESS_GR_MASK) << GMII_ADDRESS_GR_SHIFT)
1399            | (sc->mii_clk << GMII_ADDRESS_CR_SHIFT)
1400            | GMII_ADDRESS_GB; /* Busy flag */
1401
1402        WRITE4(sc, GMII_ADDRESS, mii);
1403
1404        for (cnt = 0; cnt < 1000; cnt++) {
1405                if (!(READ4(sc, GMII_ADDRESS) & GMII_ADDRESS_GB)) {
1406                        rv = READ4(sc, GMII_DATA);
1407                        break;
1408                }
1409                DELAY(10);
1410        }
1411
1412        return rv;
1413}
1414
1415static int
1416dwc_miibus_write_reg(device_t dev, int phy, int reg, int val)
1417{
1418        struct dwc_softc *sc;
1419        uint16_t mii;
1420        size_t cnt;
1421
1422        sc = device_get_softc(dev);
1423
1424        mii = ((phy & GMII_ADDRESS_PA_MASK) << GMII_ADDRESS_PA_SHIFT)
1425            | ((reg & GMII_ADDRESS_GR_MASK) << GMII_ADDRESS_GR_SHIFT)
1426            | (sc->mii_clk << GMII_ADDRESS_CR_SHIFT)
1427            | GMII_ADDRESS_GB | GMII_ADDRESS_GW;
1428
1429        WRITE4(sc, GMII_DATA, val);
1430        WRITE4(sc, GMII_ADDRESS, mii);
1431
1432        for (cnt = 0; cnt < 1000; cnt++) {
1433                if (!(READ4(sc, GMII_ADDRESS) & GMII_ADDRESS_GB)) {
1434                        break;
1435                }
1436                DELAY(10);
1437        }
1438
1439        return (0);
1440}
1441
1442static void
1443dwc_miibus_statchg(device_t dev)
1444{
1445        struct dwc_softc *sc;
1446        struct mii_data *mii;
1447        int reg;
1448
1449        /*
1450         * Called by the MII bus driver when the PHY establishes
1451         * link to set the MAC interface registers.
1452         */
1453
1454        sc = device_get_softc(dev);
1455
1456        DWC_ASSERT_LOCKED(sc);
1457
1458        mii = sc->mii_softc;
1459
1460        if (mii->mii_media_status & IFM_ACTIVE)
1461                sc->link_is_up = true;
1462        else
1463                sc->link_is_up = false;
1464
1465        reg = READ4(sc, MAC_CONFIGURATION);
1466        switch (IFM_SUBTYPE(mii->mii_media_active)) {
1467        case IFM_1000_T:
1468        case IFM_1000_SX:
1469                reg &= ~(CONF_FES | CONF_PS);
1470                break;
1471        case IFM_100_TX:
1472                reg |= (CONF_FES | CONF_PS);
1473                break;
1474        case IFM_10_T:
1475                reg &= ~(CONF_FES);
1476                reg |= (CONF_PS);
1477                break;
1478        case IFM_NONE:
1479                sc->link_is_up = false;
1480                return;
1481        default:
1482                sc->link_is_up = false;
1483                device_printf(dev, "Unsupported media %u\n",
1484                    IFM_SUBTYPE(mii->mii_media_active));
1485                return;
1486        }
1487        if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0)
1488                reg |= (CONF_DM);
1489        else
1490                reg &= ~(CONF_DM);
1491        WRITE4(sc, MAC_CONFIGURATION, reg);
1492}
1493
1494static device_method_t dwc_methods[] = {
1495        DEVMETHOD(device_probe,         dwc_probe),
1496        DEVMETHOD(device_attach,        dwc_attach),
1497
1498        /* MII Interface */
1499        DEVMETHOD(miibus_readreg,       dwc_miibus_read_reg),
1500        DEVMETHOD(miibus_writereg,      dwc_miibus_write_reg),
1501        DEVMETHOD(miibus_statchg,       dwc_miibus_statchg),
1502
1503        { 0, 0 }
1504};
1505
1506static driver_t dwc_driver = {
1507        "dwc",
1508        dwc_methods,
1509        sizeof(struct dwc_softc),
1510};
1511
1512static devclass_t dwc_devclass;
1513
1514#ifndef __rtems__
1515DRIVER_MODULE(dwc, simplebus, dwc_driver, dwc_devclass, 0, 0);
1516#else /* __rtems__ */
1517DRIVER_MODULE(dwc, nexus, dwc_driver, dwc_devclass, 0, 0);
1518#endif /* __rtems__ */
1519DRIVER_MODULE(miibus, dwc, miibus_driver, miibus_devclass, 0, 0);
1520
1521MODULE_DEPEND(dwc, ether, 1, 1, 1);
1522MODULE_DEPEND(dwc, miibus, 1, 1, 1);
Note: See TracBrowser for help on using the repository browser.