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

4.11
Last change on this file since da08198 was da08198, checked in by Sebastian Huber <sebastian.huber@…>, on 09/07/15 at 06:33:16

if_dwc: Invalidate read buffer again

This may prevent problems in case a cache line prefetch added some lines
to the cache during a DMA transfer.

  • Property mode set to 100644
File size: 35.9 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                sc->rx_idx = next_rxidx(sc, idx);
919
920                m = sc->rxbuf_map[idx].mbuf;
921
922                m0 = dwc_alloc_mbufcl(sc);
923                if (m0 == NULL) {
924                        m0 = m;
925
926                        /* Account for m_adj() in dwc_setup_rxbuf() */
927                        m0->m_data = m0->m_ext.ext_buf;
928                }
929
930                if ((error = dwc_setup_rxbuf(sc, idx, m0)) != 0) {
931                        /*
932                         * XXX Now what?
933                         * We've got a hole in the rx ring.
934                         */
935                }
936
937                if (m0 == m) {
938                        /* Discard frame and continue */
939#ifndef __rtems__
940                        if_inc_counter(sc->ifp, IFCOUNTER_IQDROPS, 1);
941#else /* __rtems__ */
942                        ++ifp->if_iqdrops;
943#endif /* __rtems__ */
944                        continue;
945                }
946
947#ifndef __rtems__
948                bus_dmamap_sync(sc->rxbuf_tag, sc->rxbuf_map[idx].map,
949                    BUS_DMASYNC_POSTREAD);
950                bus_dmamap_unload(sc->rxbuf_tag, sc->rxbuf_map[idx].map);
951#endif /* __rtems__ */
952
953                len = (rdes0 >> DDESC_RDES0_FL_SHIFT) & DDESC_RDES0_FL_MASK;
954                if (len != 0) {
955                        m->m_pkthdr.rcvif = ifp;
956                        m->m_pkthdr.len = len;
957                        m->m_len = len;
958
959                        /* Check checksum offload flags. */
960                        if ((rdes0 & DDESC_RDES0_ESA) != 0) {
961                                rdes4 = sc->rxdesc_ring[idx].tdes4;
962
963                                /* TCP or UDP checks out, IP checks out too. */
964                                if ((rdes4 & DDESC_RDES4_IP_PYL_TYPE_MSK) ==
965                                    DDESC_RDES4_IP_PYL_UDP ||
966                                    (rdes4 & DDESC_RDES4_IP_PYL_TYPE_MSK) ==
967                                    DDESC_RDES4_IP_PYL_TCP) {
968                                        m->m_pkthdr.csum_flags |=
969                                                CSUM_IP_CHECKED |
970                                                CSUM_IP_VALID |
971                                                CSUM_DATA_VALID |
972                                                CSUM_PSEUDO_HDR;
973                                        m->m_pkthdr.csum_data = 0xffff;
974                                } else if ((rdes4 & (DDESC_RDES4_IP_PYL_ERR |
975                                    DDESC_RDES4_IP_HDR_ERR)) == 0) {
976                                        /* Only IP checks out. */
977                                        m->m_pkthdr.csum_flags |=
978                                                CSUM_IP_CHECKED |
979                                                CSUM_IP_VALID;
980                                        m->m_pkthdr.csum_data = 0xffff;
981                                }
982                        }
983
984#ifndef __rtems__
985                        if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
986#else /* __rtems__ */
987                        ++ifp->if_ipackets;
988                        rtems_cache_invalidate_multiple_data_lines(m->m_data, m->m_len);
989#endif /* __rtems__ */
990
991                        DWC_UNLOCK(sc);
992                        (*ifp->if_input)(ifp, m);
993                        DWC_LOCK(sc);
994                } else {
995                        /* XXX Zero-length packet ? */
996                }
997        }
998}
999
1000static void
1001dwc_intr(void *arg)
1002{
1003        struct dwc_softc *sc;
1004        uint32_t reg;
1005
1006        sc = arg;
1007
1008        DWC_LOCK(sc);
1009
1010        reg = READ4(sc, INTERRUPT_STATUS);
1011        if (reg) {
1012                mii_mediachg(sc->mii_softc);
1013                READ4(sc, SGMII_RGMII_SMII_CTRL_STATUS);
1014        }
1015
1016        reg = READ4(sc, DMA_STATUS);
1017        if (reg & DMA_STATUS_NIS) {
1018                if (reg & DMA_STATUS_RI)
1019                        dwc_rxfinish_locked(sc);
1020
1021                if (reg & DMA_STATUS_TI)
1022                        dwc_txfinish_locked(sc);
1023        }
1024
1025        if (reg & DMA_STATUS_AIS) {
1026                if (reg & DMA_STATUS_FBI) {
1027                        /* Fatal bus error */
1028                        device_printf(sc->dev,
1029                            "Ethernet DMA error, restarting controller.\n");
1030                        dwc_stop_locked(sc);
1031                        dwc_init_locked(sc);
1032                }
1033        }
1034
1035        WRITE4(sc, DMA_STATUS, reg & DMA_STATUS_INTR_MASK);
1036        DWC_UNLOCK(sc);
1037}
1038
1039static int
1040setup_dma(struct dwc_softc *sc)
1041{
1042        struct mbuf *m;
1043        int error;
1044        int nidx;
1045        int idx;
1046
1047        /*
1048         * Set up TX descriptor ring, descriptors, and dma maps.
1049         */
1050        error = bus_dma_tag_create(
1051            bus_get_dma_tag(sc->dev),   /* Parent tag. */
1052            DWC_DESC_RING_ALIGN, 0,     /* alignment, boundary */
1053            BUS_SPACE_MAXADDR_32BIT,    /* lowaddr */
1054            BUS_SPACE_MAXADDR,          /* highaddr */
1055            NULL, NULL,                 /* filter, filterarg */
1056            TX_DESC_SIZE, 1,            /* maxsize, nsegments */
1057            TX_DESC_SIZE,               /* maxsegsize */
1058            0,                          /* flags */
1059            NULL, NULL,                 /* lockfunc, lockarg */
1060            &sc->txdesc_tag);
1061        if (error != 0) {
1062                device_printf(sc->dev,
1063                    "could not create TX ring DMA tag.\n");
1064                goto out;
1065        }
1066
1067        error = bus_dmamem_alloc(sc->txdesc_tag, (void**)&sc->txdesc_ring,
1068            BUS_DMA_COHERENT | BUS_DMA_WAITOK | BUS_DMA_ZERO,
1069            &sc->txdesc_map);
1070        if (error != 0) {
1071                device_printf(sc->dev,
1072                    "could not allocate TX descriptor ring.\n");
1073                goto out;
1074        }
1075
1076#ifndef __rtems__
1077        error = bus_dmamap_load(sc->txdesc_tag, sc->txdesc_map,
1078            sc->txdesc_ring, TX_DESC_SIZE, dwc_get1paddr,
1079            &sc->txdesc_ring_paddr, 0);
1080        if (error != 0) {
1081                device_printf(sc->dev,
1082                    "could not load TX descriptor ring map.\n");
1083                goto out;
1084        }
1085#endif /* __rtems__ */
1086
1087        for (idx = 0; idx < TX_DESC_COUNT; idx++) {
1088                sc->txdesc_ring[idx].addr = 0;
1089                sc->txdesc_ring[idx].tdes0 = DDESC_TDES0_TXCHAIN;
1090                sc->txdesc_ring[idx].tdes1 = 0;
1091                nidx = next_txidx(sc, idx, 1);
1092#ifndef __rtems__
1093                sc->txdesc_ring[idx].addr_next = sc->txdesc_ring_paddr + \
1094                    (nidx * sizeof(struct dwc_hwdesc));
1095#else /* __rtems__ */
1096                sc->txdesc_ring[idx].addr_next =
1097                    (uint32_t)&sc->txdesc_ring[nidx];
1098#endif /* __rtems__ */
1099        }
1100
1101#ifndef __rtems__
1102        error = bus_dma_tag_create(
1103            bus_get_dma_tag(sc->dev),   /* Parent tag. */
1104            1, 0,                       /* alignment, boundary */
1105            BUS_SPACE_MAXADDR_32BIT,    /* lowaddr */
1106            BUS_SPACE_MAXADDR,          /* highaddr */
1107            NULL, NULL,                 /* filter, filterarg */
1108            MCLBYTES, TX_MAX_DMA_SEGS,  /* maxsize, nsegments */
1109            MCLBYTES,                   /* maxsegsize */
1110            0,                          /* flags */
1111            NULL, NULL,                 /* lockfunc, lockarg */
1112            &sc->txbuf_tag);
1113        if (error != 0) {
1114                device_printf(sc->dev,
1115                    "could not create TX ring DMA tag.\n");
1116                goto out;
1117        }
1118#endif /* __rtems__ */
1119
1120        for (idx = 0; idx < TX_DESC_COUNT; idx++) {
1121#ifndef __rtems__
1122                error = bus_dmamap_create(sc->txbuf_tag, BUS_DMA_COHERENT,
1123                    &sc->txbuf_map[idx].map);
1124                if (error != 0) {
1125                        device_printf(sc->dev,
1126                            "could not create TX buffer DMA map.\n");
1127                        goto out;
1128                }
1129#endif /* __rtems__ */
1130        }
1131
1132        /*
1133         * Set up RX descriptor ring, descriptors, dma maps, and mbufs.
1134         */
1135        error = bus_dma_tag_create(
1136            bus_get_dma_tag(sc->dev),   /* Parent tag. */
1137            DWC_DESC_RING_ALIGN, 0,     /* alignment, boundary */
1138            BUS_SPACE_MAXADDR_32BIT,    /* lowaddr */
1139            BUS_SPACE_MAXADDR,          /* highaddr */
1140            NULL, NULL,                 /* filter, filterarg */
1141            RX_DESC_SIZE, 1,            /* maxsize, nsegments */
1142            RX_DESC_SIZE,               /* maxsegsize */
1143            0,                          /* flags */
1144            NULL, NULL,                 /* lockfunc, lockarg */
1145            &sc->rxdesc_tag);
1146        if (error != 0) {
1147                device_printf(sc->dev,
1148                    "could not create RX ring DMA tag.\n");
1149                goto out;
1150        }
1151
1152        error = bus_dmamem_alloc(sc->rxdesc_tag, (void **)&sc->rxdesc_ring,
1153            BUS_DMA_COHERENT | BUS_DMA_WAITOK | BUS_DMA_ZERO,
1154            &sc->rxdesc_map);
1155        if (error != 0) {
1156                device_printf(sc->dev,
1157                    "could not allocate RX descriptor ring.\n");
1158                goto out;
1159        }
1160
1161#ifndef __rtems__
1162        error = bus_dmamap_load(sc->rxdesc_tag, sc->rxdesc_map,
1163            sc->rxdesc_ring, RX_DESC_SIZE, dwc_get1paddr,
1164            &sc->rxdesc_ring_paddr, 0);
1165        if (error != 0) {
1166                device_printf(sc->dev,
1167                    "could not load RX descriptor ring map.\n");
1168                goto out;
1169        }
1170
1171        error = bus_dma_tag_create(
1172            bus_get_dma_tag(sc->dev),   /* Parent tag. */
1173            1, 0,                       /* alignment, boundary */
1174            BUS_SPACE_MAXADDR_32BIT,    /* lowaddr */
1175            BUS_SPACE_MAXADDR,          /* highaddr */
1176            NULL, NULL,                 /* filter, filterarg */
1177            MCLBYTES, 1,                /* maxsize, nsegments */
1178            MCLBYTES,                   /* maxsegsize */
1179            0,                          /* flags */
1180            NULL, NULL,                 /* lockfunc, lockarg */
1181            &sc->rxbuf_tag);
1182        if (error != 0) {
1183                device_printf(sc->dev,
1184                    "could not create RX buf DMA tag.\n");
1185                goto out;
1186        }
1187#endif /* __rtems__ */
1188
1189        for (idx = 0; idx < RX_DESC_COUNT; idx++) {
1190#ifndef __rtems__
1191                error = bus_dmamap_create(sc->rxbuf_tag, BUS_DMA_COHERENT,
1192                    &sc->rxbuf_map[idx].map);
1193                if (error != 0) {
1194                        device_printf(sc->dev,
1195                            "could not create RX buffer DMA map.\n");
1196                        goto out;
1197                }
1198#endif /* __rtems__ */
1199                if ((m = dwc_alloc_mbufcl(sc)) == NULL) {
1200                        device_printf(sc->dev, "Could not alloc mbuf\n");
1201                        error = ENOMEM;
1202                        goto out;
1203                }
1204                if ((error = dwc_setup_rxbuf(sc, idx, m)) != 0) {
1205                        device_printf(sc->dev,
1206                            "could not create new RX buffer.\n");
1207                        goto out;
1208                }
1209                sc->rxdesc_ring[idx].tdes4 = 0;
1210        }
1211
1212out:
1213        if (error != 0)
1214                return (ENXIO);
1215
1216        return (0);
1217}
1218
1219static int
1220dwc_get_hwaddr(struct dwc_softc *sc, uint8_t *hwaddr)
1221{
1222#ifndef __rtems__
1223        int rnd;
1224#endif /* __rtems__ */
1225        int lo;
1226        int hi;
1227
1228        /*
1229         * Try to recover a MAC address from the running hardware. If there's
1230         * something non-zero there, assume the bootloader did the right thing
1231         * and just use it.
1232         *
1233         * Otherwise, set the address to a convenient locally assigned address,
1234         * 'bsd' + random 24 low-order bits.  'b' is 0x62, which has the locally
1235         * assigned bit set, and the broadcast/multicast bit clear.
1236         */
1237        lo = READ4(sc, MAC_ADDRESS_LOW(0));
1238        hi = READ4(sc, MAC_ADDRESS_HIGH(0)) & 0xffff;
1239        if ((lo != 0xffffffff) || (hi != 0xffff)) {
1240                hwaddr[0] = (lo >>  0) & 0xff;
1241                hwaddr[1] = (lo >>  8) & 0xff;
1242                hwaddr[2] = (lo >> 16) & 0xff;
1243                hwaddr[3] = (lo >> 24) & 0xff;
1244                hwaddr[4] = (hi >>  0) & 0xff;
1245                hwaddr[5] = (hi >>  8) & 0xff;
1246        } else {
1247#ifndef __rtems__
1248                rnd = arc4random() & 0x00ffffff;
1249                hwaddr[0] = 'b';
1250                hwaddr[1] = 's';
1251                hwaddr[2] = 'd';
1252                hwaddr[3] = rnd >> 16;
1253                hwaddr[4] = rnd >>  8;
1254                hwaddr[5] = rnd >>  0;
1255#else /* __rtems__ */
1256                rtems_bsd_get_mac_address(device_get_name(sc->dev),
1257                    device_get_unit(sc->dev), hwaddr);
1258#endif /* __rtems__ */
1259        }
1260
1261        return (0);
1262}
1263
1264static int
1265dwc_probe(device_t dev)
1266{
1267
1268#ifndef __rtems__
1269        if (!ofw_bus_status_okay(dev))
1270                return (ENXIO);
1271
1272        if (!ofw_bus_is_compatible(dev, "snps,dwmac"))
1273                return (ENXIO);
1274#endif /* __rtems__ */
1275
1276        device_set_desc(dev, "Gigabit Ethernet Controller");
1277        return (BUS_PROBE_DEFAULT);
1278}
1279
1280static int
1281dwc_attach(device_t dev)
1282{
1283        uint8_t macaddr[ETHER_ADDR_LEN];
1284        struct dwc_softc *sc;
1285        struct ifnet *ifp;
1286        int error;
1287        int reg;
1288        int i;
1289
1290        sc = device_get_softc(dev);
1291        sc->dev = dev;
1292        sc->mii_clk = MII_CLK_VAL;
1293        sc->rx_idx = 0;
1294        sc->txcount = 0;
1295
1296        if (bus_alloc_resources(dev, dwc_spec, sc->res)) {
1297                device_printf(dev, "could not allocate resources\n");
1298                return (ENXIO);
1299        }
1300
1301        /* Memory interface */
1302        sc->bst = rman_get_bustag(sc->res[0]);
1303        sc->bsh = rman_get_bushandle(sc->res[0]);
1304
1305        /* Read MAC before reset */
1306        if (dwc_get_hwaddr(sc, macaddr)) {
1307                device_printf(sc->dev, "can't get mac\n");
1308                return (ENXIO);
1309        }
1310
1311        /* Reset */
1312        reg = READ4(sc, BUS_MODE);
1313        reg |= (BUS_MODE_SWR);
1314        WRITE4(sc, BUS_MODE, reg);
1315
1316        for (i = 0; i < MAC_RESET_TIMEOUT; i++) {
1317                if ((READ4(sc, BUS_MODE) & BUS_MODE_SWR) == 0)
1318                        break;
1319                DELAY(10);
1320        }
1321        if (i >= MAC_RESET_TIMEOUT) {
1322                device_printf(sc->dev, "Can't reset DWC.\n");
1323                return (ENXIO);
1324        }
1325
1326        reg = READ4(sc, BUS_MODE);
1327        reg |= (BUS_MODE_ATDS);
1328        reg |= (BUS_MODE_EIGHTXPBL);
1329        reg |= (BUS_MODE_PBL_BEATS_8 << BUS_MODE_PBL_SHIFT);
1330        WRITE4(sc, BUS_MODE, reg);
1331
1332        /*
1333         * DMA must be stop while changing descriptor list addresses.
1334         */
1335        reg = READ4(sc, OPERATION_MODE);
1336        reg &= ~(MODE_ST | MODE_SR);
1337        WRITE4(sc, OPERATION_MODE, reg);
1338
1339        if (setup_dma(sc))
1340                return (ENXIO);
1341
1342        /* Setup addresses */
1343#ifndef __rtems__
1344        WRITE4(sc, RX_DESCR_LIST_ADDR, sc->rxdesc_ring_paddr);
1345        WRITE4(sc, TX_DESCR_LIST_ADDR, sc->txdesc_ring_paddr);
1346#else /* __rtems__ */
1347        WRITE4(sc, RX_DESCR_LIST_ADDR, (uint32_t)&sc->rxdesc_ring[0]);
1348        WRITE4(sc, TX_DESCR_LIST_ADDR, (uint32_t)&sc->txdesc_ring[0]);
1349#endif /* __rtems__ */
1350
1351        mtx_init(&sc->mtx, device_get_nameunit(sc->dev),
1352            MTX_NETWORK_LOCK, MTX_DEF);
1353
1354        callout_init_mtx(&sc->dwc_callout, &sc->mtx, 0);
1355
1356        /* Set up the ethernet interface. */
1357        sc->ifp = ifp = if_alloc(IFT_ETHER);
1358
1359        ifp->if_softc = sc;
1360        if_initname(ifp, device_get_name(dev), device_get_unit(dev));
1361        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
1362        ifp->if_capabilities |= IFCAP_HWCSUM | IFCAP_HWCSUM_IPV6 |
1363            IFCAP_VLAN_MTU | IFCAP_VLAN_HWCSUM;
1364        ifp->if_capenable = ifp->if_capabilities;
1365        ifp->if_hwassist = DWC_CKSUM_ASSIST;
1366        ifp->if_start = dwc_txstart;
1367        ifp->if_ioctl = dwc_ioctl;
1368        ifp->if_init = dwc_init;
1369        IFQ_SET_MAXLEN(&ifp->if_snd, TX_DESC_COUNT - 1);
1370        ifp->if_snd.ifq_drv_maxlen = TX_DESC_COUNT - 1;
1371        IFQ_SET_READY(&ifp->if_snd);
1372        ifp->if_hdrlen = sizeof(struct ether_vlan_header);
1373
1374        /* Attach the mii driver. */
1375        error = mii_attach(dev, &sc->miibus, ifp, dwc_media_change,
1376            dwc_media_status, BMSR_DEFCAPMASK, MII_PHY_ANY,
1377            MII_OFFSET_ANY, 0);
1378
1379        if (error != 0) {
1380                device_printf(dev, "PHY attach failed\n");
1381                return (ENXIO);
1382        }
1383        sc->mii_softc = device_get_softc(sc->miibus);
1384
1385        /* Setup interrupt handler. */
1386        error = bus_setup_intr(dev, sc->res[1], INTR_TYPE_NET | INTR_MPSAFE,
1387            NULL, dwc_intr, sc, &sc->intr_cookie);
1388        if (error != 0) {
1389                device_printf(dev, "could not setup interrupt handler.\n");
1390                return (ENXIO);
1391        }
1392
1393        /* All ready to run, attach the ethernet interface. */
1394        ether_ifattach(ifp, macaddr);
1395        sc->is_attached = true;
1396
1397        return (0);
1398}
1399
1400static int
1401dwc_miibus_read_reg(device_t dev, int phy, int reg)
1402{
1403        struct dwc_softc *sc;
1404        uint16_t mii;
1405        size_t cnt;
1406        int rv = 0;
1407
1408        sc = device_get_softc(dev);
1409
1410        mii = ((phy & GMII_ADDRESS_PA_MASK) << GMII_ADDRESS_PA_SHIFT)
1411            | ((reg & GMII_ADDRESS_GR_MASK) << GMII_ADDRESS_GR_SHIFT)
1412            | (sc->mii_clk << GMII_ADDRESS_CR_SHIFT)
1413            | GMII_ADDRESS_GB; /* Busy flag */
1414
1415        WRITE4(sc, GMII_ADDRESS, mii);
1416
1417        for (cnt = 0; cnt < 1000; cnt++) {
1418                if (!(READ4(sc, GMII_ADDRESS) & GMII_ADDRESS_GB)) {
1419                        rv = READ4(sc, GMII_DATA);
1420                        break;
1421                }
1422                DELAY(10);
1423        }
1424
1425        return rv;
1426}
1427
1428static int
1429dwc_miibus_write_reg(device_t dev, int phy, int reg, int val)
1430{
1431        struct dwc_softc *sc;
1432        uint16_t mii;
1433        size_t cnt;
1434
1435        sc = device_get_softc(dev);
1436
1437        mii = ((phy & GMII_ADDRESS_PA_MASK) << GMII_ADDRESS_PA_SHIFT)
1438            | ((reg & GMII_ADDRESS_GR_MASK) << GMII_ADDRESS_GR_SHIFT)
1439            | (sc->mii_clk << GMII_ADDRESS_CR_SHIFT)
1440            | GMII_ADDRESS_GB | GMII_ADDRESS_GW;
1441
1442        WRITE4(sc, GMII_DATA, val);
1443        WRITE4(sc, GMII_ADDRESS, mii);
1444
1445        for (cnt = 0; cnt < 1000; cnt++) {
1446                if (!(READ4(sc, GMII_ADDRESS) & GMII_ADDRESS_GB)) {
1447                        break;
1448                }
1449                DELAY(10);
1450        }
1451
1452        return (0);
1453}
1454
1455static void
1456dwc_miibus_statchg(device_t dev)
1457{
1458        struct dwc_softc *sc;
1459        struct mii_data *mii;
1460        int reg;
1461
1462        /*
1463         * Called by the MII bus driver when the PHY establishes
1464         * link to set the MAC interface registers.
1465         */
1466
1467        sc = device_get_softc(dev);
1468
1469        DWC_ASSERT_LOCKED(sc);
1470
1471        mii = sc->mii_softc;
1472
1473        if (mii->mii_media_status & IFM_ACTIVE)
1474                sc->link_is_up = true;
1475        else
1476                sc->link_is_up = false;
1477
1478        reg = READ4(sc, MAC_CONFIGURATION);
1479        switch (IFM_SUBTYPE(mii->mii_media_active)) {
1480        case IFM_1000_T:
1481        case IFM_1000_SX:
1482                reg &= ~(CONF_FES | CONF_PS);
1483                break;
1484        case IFM_100_TX:
1485                reg |= (CONF_FES | CONF_PS);
1486                break;
1487        case IFM_10_T:
1488                reg &= ~(CONF_FES);
1489                reg |= (CONF_PS);
1490                break;
1491        case IFM_NONE:
1492                sc->link_is_up = false;
1493                return;
1494        default:
1495                sc->link_is_up = false;
1496                device_printf(dev, "Unsupported media %u\n",
1497                    IFM_SUBTYPE(mii->mii_media_active));
1498                return;
1499        }
1500        if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0)
1501                reg |= (CONF_DM);
1502        else
1503                reg &= ~(CONF_DM);
1504        WRITE4(sc, MAC_CONFIGURATION, reg);
1505}
1506
1507static device_method_t dwc_methods[] = {
1508        DEVMETHOD(device_probe,         dwc_probe),
1509        DEVMETHOD(device_attach,        dwc_attach),
1510
1511        /* MII Interface */
1512        DEVMETHOD(miibus_readreg,       dwc_miibus_read_reg),
1513        DEVMETHOD(miibus_writereg,      dwc_miibus_write_reg),
1514        DEVMETHOD(miibus_statchg,       dwc_miibus_statchg),
1515
1516        { 0, 0 }
1517};
1518
1519static driver_t dwc_driver = {
1520        "dwc",
1521        dwc_methods,
1522        sizeof(struct dwc_softc),
1523};
1524
1525static devclass_t dwc_devclass;
1526
1527#ifndef __rtems__
1528DRIVER_MODULE(dwc, simplebus, dwc_driver, dwc_devclass, 0, 0);
1529#else /* __rtems__ */
1530DRIVER_MODULE(dwc, nexus, dwc_driver, dwc_devclass, 0, 0);
1531#endif /* __rtems__ */
1532DRIVER_MODULE(miibus, dwc, miibus_driver, miibus_devclass, 0, 0);
1533
1534MODULE_DEPEND(dwc, ether, 1, 1, 1);
1535MODULE_DEPEND(dwc, miibus, 1, 1, 1);
Note: See TracBrowser for help on using the repository browser.