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

55-freebsd-126-freebsd-12
Last change on this file since 051b634 was 051b634, checked in by Sebastian Huber <sebastian.huber@…>, on 04/07/15 at 11:54:23

if_dwc: Avoid mbuf use after free

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