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

4.1155-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since 822aa5de was 822aa5de, checked in by Sebastian Huber <sebastian.huber@…>, on 03/30/15 at 09:51:36

if_dwc: Simplify tx desc setup

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