source: rtems-libbsd/freebsd/sys/arm/ti/cpsw/if_cpsw.c @ 8ae22c4

55-freebsd-12
Last change on this file since 8ae22c4 was 8ae22c4, checked in by Christian Mauderer <christian.mauderer@…>, on Dec 19, 2018 at 9:53:54 PM

freebsd/if_cpsw: Port.

  • Property mode set to 100644
File size: 78.0 KB
Line 
1#include <machine/rtems-bsd-kernel-space.h>
2
3/*-
4 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
5 *
6 * Copyright (c) 2012 Damjan Marion <dmarion@Freebsd.org>
7 * Copyright (c) 2016 Rubicon Communications, LLC (Netgate)
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * TI Common Platform Ethernet Switch (CPSW) Driver
34 * Found in TI8148 "DaVinci" and AM335x "Sitara" SoCs.
35 *
36 * This controller is documented in the AM335x Technical Reference
37 * Manual, in the TMS320DM814x DaVinci Digital Video Processors TRM
38 * and in the TMS320C6452 3 Port Switch Ethernet Subsystem TRM.
39 *
40 * It is basically a single Ethernet port (port 0) wired internally to
41 * a 3-port store-and-forward switch connected to two independent
42 * "sliver" controllers (port 1 and port 2).  You can operate the
43 * controller in a variety of different ways by suitably configuring
44 * the slivers and the Address Lookup Engine (ALE) that routes packets
45 * between the ports.
46 *
47 * This code was developed and tested on a BeagleBone with
48 * an AM335x SoC.
49 */
50
51#include <sys/cdefs.h>
52__FBSDID("$FreeBSD$");
53
54#include <rtems/bsd/local/opt_cpsw.h>
55
56#include <sys/param.h>
57#include <sys/bus.h>
58#include <sys/kernel.h>
59#include <sys/lock.h>
60#include <sys/mbuf.h>
61#include <sys/module.h>
62#include <sys/mutex.h>
63#include <sys/rman.h>
64#include <sys/socket.h>
65#include <sys/sockio.h>
66#include <sys/sysctl.h>
67
68#include <machine/bus.h>
69#include <machine/resource.h>
70#include <machine/stdarg.h>
71
72#include <net/ethernet.h>
73#include <net/bpf.h>
74#include <net/if.h>
75#include <net/if_dl.h>
76#include <net/if_media.h>
77#include <net/if_types.h>
78
79#include <arm/ti/ti_scm.h>
80#include <arm/ti/am335x/am335x_scm.h>
81
82#include <dev/mii/mii.h>
83#include <dev/mii/miivar.h>
84
85#include <dev/ofw/ofw_bus.h>
86#include <dev/ofw/ofw_bus_subr.h>
87 
88#ifdef CPSW_ETHERSWITCH
89#include <dev/etherswitch/etherswitch.h>
90#include <rtems/bsd/local/etherswitch_if.h>
91#endif
92
93#include "if_cpswreg.h"
94#include "if_cpswvar.h"
95
96#include <rtems/bsd/local/miibus_if.h>
97
98/* Device probe/attach/detach. */
99static int cpsw_probe(device_t);
100static int cpsw_attach(device_t);
101static int cpsw_detach(device_t);
102static int cpswp_probe(device_t);
103static int cpswp_attach(device_t);
104static int cpswp_detach(device_t);
105
106static phandle_t cpsw_get_node(device_t, device_t);
107
108/* Device Init/shutdown. */
109static int cpsw_shutdown(device_t);
110static void cpswp_init(void *);
111static void cpswp_init_locked(void *);
112static void cpswp_stop_locked(struct cpswp_softc *);
113
114/* Device Suspend/Resume. */
115static int cpsw_suspend(device_t);
116static int cpsw_resume(device_t);
117
118/* Ioctl. */
119static int cpswp_ioctl(struct ifnet *, u_long command, caddr_t data);
120
121static int cpswp_miibus_readreg(device_t, int phy, int reg);
122static int cpswp_miibus_writereg(device_t, int phy, int reg, int value);
123static void cpswp_miibus_statchg(device_t);
124
125/* Send/Receive packets. */
126static void cpsw_intr_rx(void *arg);
127static struct mbuf *cpsw_rx_dequeue(struct cpsw_softc *);
128static void cpsw_rx_enqueue(struct cpsw_softc *);
129static void cpswp_start(struct ifnet *);
130static void cpsw_intr_tx(void *);
131static void cpswp_tx_enqueue(struct cpswp_softc *);
132static int cpsw_tx_dequeue(struct cpsw_softc *);
133
134/* Misc interrupts and watchdog. */
135static void cpsw_intr_rx_thresh(void *);
136static void cpsw_intr_misc(void *);
137static void cpswp_tick(void *);
138static void cpswp_ifmedia_sts(struct ifnet *, struct ifmediareq *);
139static int cpswp_ifmedia_upd(struct ifnet *);
140static void cpsw_tx_watchdog(void *);
141
142/* ALE support */
143static void cpsw_ale_read_entry(struct cpsw_softc *, uint16_t, uint32_t *);
144static void cpsw_ale_write_entry(struct cpsw_softc *, uint16_t, uint32_t *);
145static int cpsw_ale_mc_entry_set(struct cpsw_softc *, uint8_t, int, uint8_t *);
146static void cpsw_ale_dump_table(struct cpsw_softc *);
147static int cpsw_ale_update_vlan_table(struct cpsw_softc *, int, int, int, int,
148        int);
149static int cpswp_ale_update_addresses(struct cpswp_softc *, int);
150
151/* Statistics and sysctls. */
152static void cpsw_add_sysctls(struct cpsw_softc *);
153static void cpsw_stats_collect(struct cpsw_softc *);
154static int cpsw_stats_sysctl(SYSCTL_HANDLER_ARGS);
155
156#ifdef CPSW_ETHERSWITCH
157static etherswitch_info_t *cpsw_getinfo(device_t);
158static int cpsw_getport(device_t, etherswitch_port_t *);
159static int cpsw_setport(device_t, etherswitch_port_t *);
160static int cpsw_getconf(device_t, etherswitch_conf_t *);
161static int cpsw_getvgroup(device_t, etherswitch_vlangroup_t *);
162static int cpsw_setvgroup(device_t, etherswitch_vlangroup_t *);
163static int cpsw_readreg(device_t, int);
164static int cpsw_writereg(device_t, int, int);
165static int cpsw_readphy(device_t, int, int);
166static int cpsw_writephy(device_t, int, int, int);
167#endif
168
169/*
170 * Arbitrary limit on number of segments in an mbuf to be transmitted.
171 * Packets with more segments than this will be defragmented before
172 * they are queued.
173 */
174#define CPSW_TXFRAGS            16
175
176/* Shared resources. */
177static device_method_t cpsw_methods[] = {
178        /* Device interface */
179        DEVMETHOD(device_probe,         cpsw_probe),
180        DEVMETHOD(device_attach,        cpsw_attach),
181        DEVMETHOD(device_detach,        cpsw_detach),
182        DEVMETHOD(device_shutdown,      cpsw_shutdown),
183        DEVMETHOD(device_suspend,       cpsw_suspend),
184        DEVMETHOD(device_resume,        cpsw_resume),
185        /* Bus interface */
186        DEVMETHOD(bus_add_child,        device_add_child_ordered),
187        /* OFW methods */
188        DEVMETHOD(ofw_bus_get_node,     cpsw_get_node),
189#ifdef CPSW_ETHERSWITCH
190        /* etherswitch interface */
191        DEVMETHOD(etherswitch_getinfo,  cpsw_getinfo),
192        DEVMETHOD(etherswitch_readreg,  cpsw_readreg),
193        DEVMETHOD(etherswitch_writereg, cpsw_writereg),
194        DEVMETHOD(etherswitch_readphyreg,       cpsw_readphy),
195        DEVMETHOD(etherswitch_writephyreg,      cpsw_writephy),
196        DEVMETHOD(etherswitch_getport,  cpsw_getport),
197        DEVMETHOD(etherswitch_setport,  cpsw_setport),
198        DEVMETHOD(etherswitch_getvgroup,        cpsw_getvgroup),
199        DEVMETHOD(etherswitch_setvgroup,        cpsw_setvgroup),
200        DEVMETHOD(etherswitch_getconf,  cpsw_getconf),
201#endif
202        DEVMETHOD_END
203};
204
205static driver_t cpsw_driver = {
206        "cpswss",
207        cpsw_methods,
208        sizeof(struct cpsw_softc),
209};
210
211static devclass_t cpsw_devclass;
212
213DRIVER_MODULE(cpswss, simplebus, cpsw_driver, cpsw_devclass, 0, 0);
214
215/* Port/Slave resources. */
216static device_method_t cpswp_methods[] = {
217        /* Device interface */
218        DEVMETHOD(device_probe,         cpswp_probe),
219        DEVMETHOD(device_attach,        cpswp_attach),
220        DEVMETHOD(device_detach,        cpswp_detach),
221        /* MII interface */
222        DEVMETHOD(miibus_readreg,       cpswp_miibus_readreg),
223        DEVMETHOD(miibus_writereg,      cpswp_miibus_writereg),
224        DEVMETHOD(miibus_statchg,       cpswp_miibus_statchg),
225        DEVMETHOD_END
226};
227
228static driver_t cpswp_driver = {
229        "cpsw",
230        cpswp_methods,
231        sizeof(struct cpswp_softc),
232};
233
234static devclass_t cpswp_devclass;
235
236#ifdef CPSW_ETHERSWITCH
237DRIVER_MODULE(etherswitch, cpswss, etherswitch_driver, etherswitch_devclass, 0, 0);
238MODULE_DEPEND(cpswss, etherswitch, 1, 1, 1);
239#endif
240
241DRIVER_MODULE(cpsw, cpswss, cpswp_driver, cpswp_devclass, 0, 0);
242DRIVER_MODULE(miibus, cpsw, miibus_driver, miibus_devclass, 0, 0);
243MODULE_DEPEND(cpsw, ether, 1, 1, 1);
244MODULE_DEPEND(cpsw, miibus, 1, 1, 1);
245
246#ifdef CPSW_ETHERSWITCH
247static struct cpsw_vlangroups cpsw_vgroups[CPSW_VLANS];
248#endif
249
250static uint32_t slave_mdio_addr[] = { 0x4a100200, 0x4a100300 };
251
252static struct resource_spec irq_res_spec[] = {
253        { SYS_RES_IRQ, 0, RF_ACTIVE | RF_SHAREABLE },
254        { SYS_RES_IRQ, 1, RF_ACTIVE | RF_SHAREABLE },
255        { SYS_RES_IRQ, 2, RF_ACTIVE | RF_SHAREABLE },
256        { SYS_RES_IRQ, 3, RF_ACTIVE | RF_SHAREABLE },
257        { -1, 0 }
258};
259
260static struct {
261        void (*cb)(void *);
262} cpsw_intr_cb[] = {
263        { cpsw_intr_rx_thresh },
264        { cpsw_intr_rx },
265        { cpsw_intr_tx },
266        { cpsw_intr_misc },
267};
268
269/* Number of entries here must match size of stats
270 * array in struct cpswp_softc. */
271static struct cpsw_stat {
272        int     reg;
273        char *oid;
274} cpsw_stat_sysctls[CPSW_SYSCTL_COUNT] = {
275        {0x00, "GoodRxFrames"},
276        {0x04, "BroadcastRxFrames"},
277        {0x08, "MulticastRxFrames"},
278        {0x0C, "PauseRxFrames"},
279        {0x10, "RxCrcErrors"},
280        {0x14, "RxAlignErrors"},
281        {0x18, "OversizeRxFrames"},
282        {0x1c, "RxJabbers"},
283        {0x20, "ShortRxFrames"},
284        {0x24, "RxFragments"},
285        {0x30, "RxOctets"},
286        {0x34, "GoodTxFrames"},
287        {0x38, "BroadcastTxFrames"},
288        {0x3c, "MulticastTxFrames"},
289        {0x40, "PauseTxFrames"},
290        {0x44, "DeferredTxFrames"},
291        {0x48, "CollisionsTxFrames"},
292        {0x4c, "SingleCollisionTxFrames"},
293        {0x50, "MultipleCollisionTxFrames"},
294        {0x54, "ExcessiveCollisions"},
295        {0x58, "LateCollisions"},
296        {0x5c, "TxUnderrun"},
297        {0x60, "CarrierSenseErrors"},
298        {0x64, "TxOctets"},
299        {0x68, "RxTx64OctetFrames"},
300        {0x6c, "RxTx65to127OctetFrames"},
301        {0x70, "RxTx128to255OctetFrames"},
302        {0x74, "RxTx256to511OctetFrames"},
303        {0x78, "RxTx512to1024OctetFrames"},
304        {0x7c, "RxTx1024upOctetFrames"},
305        {0x80, "NetOctets"},
306        {0x84, "RxStartOfFrameOverruns"},
307        {0x88, "RxMiddleOfFrameOverruns"},
308        {0x8c, "RxDmaOverruns"}
309};
310
311/*
312 * Basic debug support.
313 */
314
315static void
316cpsw_debugf_head(const char *funcname)
317{
318        int t = (int)(time_second % (24 * 60 * 60));
319
320        printf("%02d:%02d:%02d %s ", t / (60 * 60), (t / 60) % 60, t % 60, funcname);
321}
322
323static void
324cpsw_debugf(const char *fmt, ...)
325{
326        va_list ap;
327
328        va_start(ap, fmt);
329        vprintf(fmt, ap);
330        va_end(ap);
331        printf("\n");
332
333}
334
335#define CPSW_DEBUGF(_sc, a) do {                                        \
336        if ((_sc)->debug) {                                             \
337                cpsw_debugf_head(__func__);                             \
338                cpsw_debugf a;                                          \
339        }                                                               \
340} while (0)
341
342/*
343 * Locking macros
344 */
345#define CPSW_TX_LOCK(sc) do {                                           \
346                mtx_assert(&(sc)->rx.lock, MA_NOTOWNED);                \
347                mtx_lock(&(sc)->tx.lock);                               \
348} while (0)
349
350#define CPSW_TX_UNLOCK(sc)      mtx_unlock(&(sc)->tx.lock)
351#define CPSW_TX_LOCK_ASSERT(sc) mtx_assert(&(sc)->tx.lock, MA_OWNED)
352
353#define CPSW_RX_LOCK(sc) do {                                           \
354                mtx_assert(&(sc)->tx.lock, MA_NOTOWNED);                \
355                mtx_lock(&(sc)->rx.lock);                               \
356} while (0)
357
358#define CPSW_RX_UNLOCK(sc)              mtx_unlock(&(sc)->rx.lock)
359#define CPSW_RX_LOCK_ASSERT(sc) mtx_assert(&(sc)->rx.lock, MA_OWNED)
360
361#define CPSW_PORT_LOCK(_sc) do {                                        \
362                mtx_assert(&(_sc)->lock, MA_NOTOWNED);                  \
363                mtx_lock(&(_sc)->lock);                                 \
364} while (0)
365
366#define CPSW_PORT_UNLOCK(_sc)   mtx_unlock(&(_sc)->lock)
367#define CPSW_PORT_LOCK_ASSERT(_sc)      mtx_assert(&(_sc)->lock, MA_OWNED)
368
369/*
370 * Read/Write macros
371 */
372#define cpsw_read_4(_sc, _reg)          bus_read_4((_sc)->mem_res, (_reg))
373#define cpsw_write_4(_sc, _reg, _val)                                   \
374        bus_write_4((_sc)->mem_res, (_reg), (_val))
375
376#define cpsw_cpdma_bd_offset(i) (CPSW_CPPI_RAM_OFFSET + ((i)*16))
377
378#ifdef __rtems__
379/* Missing in the bus.h provided by rtems. */
380#define BUS_SPACE_PHYSADDR(res, offs) \
381        ((u_int)(rman_get_start(res)+(offs)))
382#endif /* __rtems__ */
383#define cpsw_cpdma_bd_paddr(sc, slot)                                   \
384        BUS_SPACE_PHYSADDR(sc->mem_res, slot->bd_offset)
385#define cpsw_cpdma_read_bd(sc, slot, val)                               \
386        bus_read_region_4(sc->mem_res, slot->bd_offset, (uint32_t *) val, 4)
387#define cpsw_cpdma_write_bd(sc, slot, val)                              \
388        bus_write_region_4(sc->mem_res, slot->bd_offset, (uint32_t *) val, 4)
389#define cpsw_cpdma_write_bd_next(sc, slot, next_slot)                   \
390        cpsw_write_4(sc, slot->bd_offset, cpsw_cpdma_bd_paddr(sc, next_slot))
391#define cpsw_cpdma_write_bd_flags(sc, slot, val)                        \
392        bus_write_2(sc->mem_res, slot->bd_offset + 14, val)
393#define cpsw_cpdma_read_bd_flags(sc, slot)                              \
394        bus_read_2(sc->mem_res, slot->bd_offset + 14)
395#define cpsw_write_hdp_slot(sc, queue, slot)                            \
396        cpsw_write_4(sc, (queue)->hdp_offset, cpsw_cpdma_bd_paddr(sc, slot))
397#define CP_OFFSET (CPSW_CPDMA_TX_CP(0) - CPSW_CPDMA_TX_HDP(0))
398#define cpsw_read_cp(sc, queue)                                         \
399        cpsw_read_4(sc, (queue)->hdp_offset + CP_OFFSET)
400#define cpsw_write_cp(sc, queue, val)                                   \
401        cpsw_write_4(sc, (queue)->hdp_offset + CP_OFFSET, (val))
402#define cpsw_write_cp_slot(sc, queue, slot)                             \
403        cpsw_write_cp(sc, queue, cpsw_cpdma_bd_paddr(sc, slot))
404
405#if 0
406/* XXX temporary function versions for debugging. */
407static void
408cpsw_write_hdp_slotX(struct cpsw_softc *sc, struct cpsw_queue *queue, struct cpsw_slot *slot)
409{
410        uint32_t reg = queue->hdp_offset;
411        uint32_t v = cpsw_cpdma_bd_paddr(sc, slot);
412        CPSW_DEBUGF(("HDP <=== 0x%08x (was 0x%08x)", v, cpsw_read_4(sc, reg)));
413        cpsw_write_4(sc, reg, v);
414}
415
416static void
417cpsw_write_cp_slotX(struct cpsw_softc *sc, struct cpsw_queue *queue, struct cpsw_slot *slot)
418{
419        uint32_t v = cpsw_cpdma_bd_paddr(sc, slot);
420        CPSW_DEBUGF(("CP <=== 0x%08x (expecting 0x%08x)", v, cpsw_read_cp(sc, queue)));
421        cpsw_write_cp(sc, queue, v);
422}
423#endif
424
425/*
426 * Expanded dump routines for verbose debugging.
427 */
428static void
429cpsw_dump_slot(struct cpsw_softc *sc, struct cpsw_slot *slot)
430{
431        static const char *flags[] = {"SOP", "EOP", "Owner", "EOQ",
432            "TDownCmplt", "PassCRC", "Long", "Short", "MacCtl", "Overrun",
433            "PktErr1", "PortEn/PktErr0", "RxVlanEncap", "Port2", "Port1",
434            "Port0"};
435        struct cpsw_cpdma_bd bd;
436        const char *sep;
437        int i;
438
439        cpsw_cpdma_read_bd(sc, slot, &bd);
440        printf("BD Addr : 0x%08x   Next  : 0x%08x\n",
441            cpsw_cpdma_bd_paddr(sc, slot), bd.next);
442        printf("  BufPtr: 0x%08x   BufLen: 0x%08x\n", bd.bufptr, bd.buflen);
443        printf("  BufOff: 0x%08x   PktLen: 0x%08x\n", bd.bufoff, bd.pktlen);
444        printf("  Flags: ");
445        sep = "";
446        for (i = 0; i < 16; ++i) {
447                if (bd.flags & (1 << (15 - i))) {
448                        printf("%s%s", sep, flags[i]);
449                        sep = ",";
450                }
451        }
452        printf("\n");
453        if (slot->mbuf) {
454                printf("  Ether:  %14D\n",
455                    (char *)(slot->mbuf->m_data), " ");
456                printf("  Packet: %16D\n",
457                    (char *)(slot->mbuf->m_data) + 14, " ");
458        }
459}
460
461#define CPSW_DUMP_SLOT(cs, slot) do {                           \
462        IF_DEBUG(sc) {                                          \
463                cpsw_dump_slot(sc, slot);                       \
464        }                                                       \
465} while (0)
466
467static void
468cpsw_dump_queue(struct cpsw_softc *sc, struct cpsw_slots *q)
469{
470        struct cpsw_slot *slot;
471        int i = 0;
472        int others = 0;
473
474        STAILQ_FOREACH(slot, q, next) {
475                if (i > CPSW_TXFRAGS)
476                        ++others;
477                else
478                        cpsw_dump_slot(sc, slot);
479                ++i;
480        }
481        if (others)
482                printf(" ... and %d more.\n", others);
483        printf("\n");
484}
485
486#define CPSW_DUMP_QUEUE(sc, q) do {                             \
487        IF_DEBUG(sc) {                                          \
488                cpsw_dump_queue(sc, q);                         \
489        }                                                       \
490} while (0)
491
492static void
493cpsw_init_slots(struct cpsw_softc *sc)
494{
495        struct cpsw_slot *slot;
496        int i;
497
498        STAILQ_INIT(&sc->avail);
499
500        /* Put the slot descriptors onto the global avail list. */
501        for (i = 0; i < nitems(sc->_slots); i++) {
502                slot = &sc->_slots[i];
503                slot->bd_offset = cpsw_cpdma_bd_offset(i);
504                STAILQ_INSERT_TAIL(&sc->avail, slot, next);
505        }
506}
507
508static int
509cpsw_add_slots(struct cpsw_softc *sc, struct cpsw_queue *queue, int requested)
510{
511        const int max_slots = nitems(sc->_slots);
512        struct cpsw_slot *slot;
513        int i;
514
515        if (requested < 0)
516                requested = max_slots;
517
518        for (i = 0; i < requested; ++i) {
519                slot = STAILQ_FIRST(&sc->avail);
520                if (slot == NULL)
521                        return (0);
522                if (bus_dmamap_create(sc->mbuf_dtag, 0, &slot->dmamap)) {
523                        device_printf(sc->dev, "failed to create dmamap\n");
524                        return (ENOMEM);
525                }
526                STAILQ_REMOVE_HEAD(&sc->avail, next);
527                STAILQ_INSERT_TAIL(&queue->avail, slot, next);
528                ++queue->avail_queue_len;
529                ++queue->queue_slots;
530        }
531        return (0);
532}
533
534static void
535cpsw_free_slot(struct cpsw_softc *sc, struct cpsw_slot *slot)
536{
537        int error;
538
539        if (slot->dmamap) {
540                if (slot->mbuf)
541                        bus_dmamap_unload(sc->mbuf_dtag, slot->dmamap);
542                error = bus_dmamap_destroy(sc->mbuf_dtag, slot->dmamap);
543                KASSERT(error == 0, ("Mapping still active"));
544                slot->dmamap = NULL;
545        }
546        if (slot->mbuf) {
547                m_freem(slot->mbuf);
548                slot->mbuf = NULL;
549        }
550}
551
552static void
553cpsw_reset(struct cpsw_softc *sc)
554{
555        int i;
556
557        callout_stop(&sc->watchdog.callout);
558
559        /* Reset RMII/RGMII wrapper. */
560        cpsw_write_4(sc, CPSW_WR_SOFT_RESET, 1);
561        while (cpsw_read_4(sc, CPSW_WR_SOFT_RESET) & 1)
562                ;
563
564        /* Disable TX and RX interrupts for all cores. */
565        for (i = 0; i < 3; ++i) {
566                cpsw_write_4(sc, CPSW_WR_C_RX_THRESH_EN(i), 0x00);
567                cpsw_write_4(sc, CPSW_WR_C_TX_EN(i), 0x00);
568                cpsw_write_4(sc, CPSW_WR_C_RX_EN(i), 0x00);
569                cpsw_write_4(sc, CPSW_WR_C_MISC_EN(i), 0x00);
570        }
571
572        /* Reset CPSW subsystem. */
573        cpsw_write_4(sc, CPSW_SS_SOFT_RESET, 1);
574        while (cpsw_read_4(sc, CPSW_SS_SOFT_RESET) & 1)
575                ;
576
577        /* Reset Sliver port 1 and 2 */
578        for (i = 0; i < 2; i++) {
579                /* Reset */
580                cpsw_write_4(sc, CPSW_SL_SOFT_RESET(i), 1);
581                while (cpsw_read_4(sc, CPSW_SL_SOFT_RESET(i)) & 1)
582                        ;
583        }
584
585        /* Reset DMA controller. */
586        cpsw_write_4(sc, CPSW_CPDMA_SOFT_RESET, 1);
587        while (cpsw_read_4(sc, CPSW_CPDMA_SOFT_RESET) & 1)
588                ;
589
590        /* Disable TX & RX DMA */
591        cpsw_write_4(sc, CPSW_CPDMA_TX_CONTROL, 0);
592        cpsw_write_4(sc, CPSW_CPDMA_RX_CONTROL, 0);
593
594        /* Clear all queues. */
595        for (i = 0; i < 8; i++) {
596                cpsw_write_4(sc, CPSW_CPDMA_TX_HDP(i), 0);
597                cpsw_write_4(sc, CPSW_CPDMA_RX_HDP(i), 0);
598                cpsw_write_4(sc, CPSW_CPDMA_TX_CP(i), 0);
599                cpsw_write_4(sc, CPSW_CPDMA_RX_CP(i), 0);
600        }
601
602        /* Clear all interrupt Masks */
603        cpsw_write_4(sc, CPSW_CPDMA_RX_INTMASK_CLEAR, 0xFFFFFFFF);
604        cpsw_write_4(sc, CPSW_CPDMA_TX_INTMASK_CLEAR, 0xFFFFFFFF);
605}
606
607static void
608cpsw_init(struct cpsw_softc *sc)
609{
610        struct cpsw_slot *slot;
611        uint32_t reg;
612
613        /* Disable the interrupt pacing. */
614        reg = cpsw_read_4(sc, CPSW_WR_INT_CONTROL);
615        reg &= ~(CPSW_WR_INT_PACE_EN | CPSW_WR_INT_PRESCALE_MASK);
616        cpsw_write_4(sc, CPSW_WR_INT_CONTROL, reg);
617
618        /* Clear ALE */
619        cpsw_write_4(sc, CPSW_ALE_CONTROL, CPSW_ALE_CTL_CLEAR_TBL);
620
621        /* Enable ALE */
622        reg = CPSW_ALE_CTL_ENABLE;
623        if (sc->dualemac)
624                reg |= CPSW_ALE_CTL_VLAN_AWARE;
625        cpsw_write_4(sc, CPSW_ALE_CONTROL, reg);
626
627        /* Set Host Port Mapping. */
628        cpsw_write_4(sc, CPSW_PORT_P0_CPDMA_TX_PRI_MAP, 0x76543210);
629        cpsw_write_4(sc, CPSW_PORT_P0_CPDMA_RX_CH_MAP, 0);
630
631        /* Initialize ALE: set host port to forwarding(3). */
632        cpsw_write_4(sc, CPSW_ALE_PORTCTL(0),
633            ALE_PORTCTL_INGRESS | ALE_PORTCTL_FORWARD);
634
635        cpsw_write_4(sc, CPSW_SS_PTYPE, 0);
636
637        /* Enable statistics for ports 0, 1 and 2 */
638        cpsw_write_4(sc, CPSW_SS_STAT_PORT_EN, 7);
639
640        /* Turn off flow control. */
641        cpsw_write_4(sc, CPSW_SS_FLOW_CONTROL, 0);
642
643        /* Make IP hdr aligned with 4 */
644        cpsw_write_4(sc, CPSW_CPDMA_RX_BUFFER_OFFSET, 2);
645
646        /* Initialize RX Buffer Descriptors */
647        cpsw_write_4(sc, CPSW_CPDMA_RX_PENDTHRESH(0), 0);
648        cpsw_write_4(sc, CPSW_CPDMA_RX_FREEBUFFER(0), 0);
649
650        /* Enable TX & RX DMA */
651        cpsw_write_4(sc, CPSW_CPDMA_TX_CONTROL, 1);
652        cpsw_write_4(sc, CPSW_CPDMA_RX_CONTROL, 1);
653
654        /* Enable Interrupts for core 0 */
655        cpsw_write_4(sc, CPSW_WR_C_RX_THRESH_EN(0), 0xFF);
656        cpsw_write_4(sc, CPSW_WR_C_RX_EN(0), 0xFF);
657        cpsw_write_4(sc, CPSW_WR_C_TX_EN(0), 0xFF);
658        cpsw_write_4(sc, CPSW_WR_C_MISC_EN(0), 0x1F);
659
660        /* Enable host Error Interrupt */
661        cpsw_write_4(sc, CPSW_CPDMA_DMA_INTMASK_SET, 3);
662
663        /* Enable interrupts for RX and TX on Channel 0 */
664        cpsw_write_4(sc, CPSW_CPDMA_RX_INTMASK_SET,
665            CPSW_CPDMA_RX_INT(0) | CPSW_CPDMA_RX_INT_THRESH(0));
666        cpsw_write_4(sc, CPSW_CPDMA_TX_INTMASK_SET, 1);
667
668        /* Initialze MDIO - ENABLE, PREAMBLE=0, FAULTENB, CLKDIV=0xFF */
669        /* TODO Calculate MDCLK=CLK/(CLKDIV+1) */
670        cpsw_write_4(sc, MDIOCONTROL, MDIOCTL_ENABLE | MDIOCTL_FAULTENB | 0xff);
671
672        /* Select MII in GMII_SEL, Internal Delay mode */
673        //ti_scm_reg_write_4(0x650, 0);
674
675        /* Initialize active queues. */
676        slot = STAILQ_FIRST(&sc->tx.active);
677        if (slot != NULL)
678                cpsw_write_hdp_slot(sc, &sc->tx, slot);
679        slot = STAILQ_FIRST(&sc->rx.active);
680        if (slot != NULL)
681                cpsw_write_hdp_slot(sc, &sc->rx, slot);
682        cpsw_rx_enqueue(sc);
683        cpsw_write_4(sc, CPSW_CPDMA_RX_FREEBUFFER(0), sc->rx.active_queue_len);
684        cpsw_write_4(sc, CPSW_CPDMA_RX_PENDTHRESH(0), CPSW_TXFRAGS);
685
686        /* Activate network interface. */
687        sc->rx.running = 1;
688        sc->tx.running = 1;
689        sc->watchdog.timer = 0;
690        callout_init(&sc->watchdog.callout, 0);
691        callout_reset(&sc->watchdog.callout, hz, cpsw_tx_watchdog, sc);
692}
693
694/*
695 *
696 * Device Probe, Attach, Detach.
697 *
698 */
699
700static int
701cpsw_probe(device_t dev)
702{
703
704        if (!ofw_bus_status_okay(dev))
705                return (ENXIO);
706
707        if (!ofw_bus_is_compatible(dev, "ti,cpsw"))
708                return (ENXIO);
709
710        device_set_desc(dev, "3-port Switch Ethernet Subsystem");
711        return (BUS_PROBE_DEFAULT);
712}
713
714static int
715cpsw_intr_attach(struct cpsw_softc *sc)
716{
717        int i;
718
719        for (i = 0; i < CPSW_INTR_COUNT; i++) {
720                if (bus_setup_intr(sc->dev, sc->irq_res[i],
721                    INTR_TYPE_NET | INTR_MPSAFE, NULL,
722                    cpsw_intr_cb[i].cb, sc, &sc->ih_cookie[i]) != 0) {
723                        return (-1);
724                }
725        }
726
727        return (0);
728}
729
730static void
731cpsw_intr_detach(struct cpsw_softc *sc)
732{
733        int i;
734
735        for (i = 0; i < CPSW_INTR_COUNT; i++) {
736                if (sc->ih_cookie[i]) {
737                        bus_teardown_intr(sc->dev, sc->irq_res[i],
738                            sc->ih_cookie[i]);
739                }
740        }
741}
742
743static int
744cpsw_get_fdt_data(struct cpsw_softc *sc, int port)
745{
746        char *name;
747        int len, phy, vlan;
748        pcell_t phy_id[3], vlan_id;
749        phandle_t child;
750        unsigned long mdio_child_addr;
751
752        /* Find any slave with phy_id */
753        phy = -1;
754        vlan = -1;
755        for (child = OF_child(sc->node); child != 0; child = OF_peer(child)) {
756                if (OF_getprop_alloc(child, "name", (void **)&name) < 0)
757                        continue;
758                if (sscanf(name, "slave@%lx", &mdio_child_addr) != 1) {
759                        OF_prop_free(name);
760                        continue;
761                }
762                OF_prop_free(name);
763                if (mdio_child_addr != slave_mdio_addr[port])
764                        continue;
765
766                len = OF_getproplen(child, "phy_id");
767                if (len / sizeof(pcell_t) == 2) {
768                        /* Get phy address from fdt */
769                        if (OF_getencprop(child, "phy_id", phy_id, len) > 0)
770                                phy = phy_id[1];
771                }
772
773                len = OF_getproplen(child, "dual_emac_res_vlan");
774                if (len / sizeof(pcell_t) == 1) {
775                        /* Get phy address from fdt */
776                        if (OF_getencprop(child, "dual_emac_res_vlan",
777                            &vlan_id, len) > 0) {
778                                vlan = vlan_id;
779                        }
780                }
781
782                break;
783        }
784        if (phy == -1)
785                return (ENXIO);
786        sc->port[port].phy = phy;
787        sc->port[port].vlan = vlan;
788
789        return (0);
790}
791
792static int
793cpsw_attach(device_t dev)
794{
795        int error, i;
796        struct cpsw_softc *sc;
797        uint32_t reg;
798
799        sc = device_get_softc(dev);
800        sc->dev = dev;
801        sc->node = ofw_bus_get_node(dev);
802        getbinuptime(&sc->attach_uptime);
803
804        if (OF_getencprop(sc->node, "active_slave", &sc->active_slave,
805            sizeof(sc->active_slave)) <= 0) {
806                sc->active_slave = 0;
807        }
808        if (sc->active_slave > 1)
809                sc->active_slave = 1;
810
811        if (OF_hasprop(sc->node, "dual_emac"))
812                sc->dualemac = 1;
813
814        for (i = 0; i < CPSW_PORTS; i++) {
815                if (!sc->dualemac && i != sc->active_slave)
816                        continue;
817                if (cpsw_get_fdt_data(sc, i) != 0) {
818                        device_printf(dev,
819                            "failed to get PHY address from FDT\n");
820                        return (ENXIO);
821                }
822        }
823
824        /* Initialize mutexes */
825        mtx_init(&sc->tx.lock, device_get_nameunit(dev),
826            "cpsw TX lock", MTX_DEF);
827        mtx_init(&sc->rx.lock, device_get_nameunit(dev),
828            "cpsw RX lock", MTX_DEF);
829
830        /* Allocate IRQ resources */
831        error = bus_alloc_resources(dev, irq_res_spec, sc->irq_res);
832        if (error) {
833                device_printf(dev, "could not allocate IRQ resources\n");
834                cpsw_detach(dev);
835                return (ENXIO);
836        }
837
838        sc->mem_rid = 0;
839        sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 
840            &sc->mem_rid, RF_ACTIVE);
841        if (sc->mem_res == NULL) {
842                device_printf(sc->dev, "failed to allocate memory resource\n");
843                cpsw_detach(dev);
844                return (ENXIO);
845        }
846
847        reg = cpsw_read_4(sc, CPSW_SS_IDVER);
848        device_printf(dev, "CPSW SS Version %d.%d (%d)\n", (reg >> 8 & 0x7),
849                reg & 0xFF, (reg >> 11) & 0x1F);
850
851        cpsw_add_sysctls(sc);
852
853        /* Allocate a busdma tag and DMA safe memory for mbufs. */
854        error = bus_dma_tag_create(
855                bus_get_dma_tag(sc->dev),       /* parent */
856                1, 0,                           /* alignment, boundary */
857                BUS_SPACE_MAXADDR_32BIT,        /* lowaddr */
858                BUS_SPACE_MAXADDR,              /* highaddr */
859                NULL, NULL,                     /* filtfunc, filtfuncarg */
860                MCLBYTES, CPSW_TXFRAGS,         /* maxsize, nsegments */
861                MCLBYTES, 0,                    /* maxsegsz, flags */
862                NULL, NULL,                     /* lockfunc, lockfuncarg */
863                &sc->mbuf_dtag);                /* dmatag */
864        if (error) {
865                device_printf(dev, "bus_dma_tag_create failed\n");
866                cpsw_detach(dev);
867                return (error);
868        }
869
870        /* Allocate a NULL buffer for padding. */
871        sc->nullpad = malloc(ETHER_MIN_LEN, M_DEVBUF, M_WAITOK | M_ZERO);
872
873        cpsw_init_slots(sc);
874
875        /* Allocate slots to TX and RX queues. */
876        STAILQ_INIT(&sc->rx.avail);
877        STAILQ_INIT(&sc->rx.active);
878        STAILQ_INIT(&sc->tx.avail);
879        STAILQ_INIT(&sc->tx.active);
880        // For now:  128 slots to TX, rest to RX.
881        // XXX TODO: start with 32/64 and grow dynamically based on demand.
882        if (cpsw_add_slots(sc, &sc->tx, 128) ||
883            cpsw_add_slots(sc, &sc->rx, -1)) {
884                device_printf(dev, "failed to allocate dmamaps\n");
885                cpsw_detach(dev);
886                return (ENOMEM);
887        }
888        device_printf(dev, "Initial queue size TX=%d RX=%d\n",
889            sc->tx.queue_slots, sc->rx.queue_slots);
890
891        sc->tx.hdp_offset = CPSW_CPDMA_TX_HDP(0);
892        sc->rx.hdp_offset = CPSW_CPDMA_RX_HDP(0);
893
894        if (cpsw_intr_attach(sc) == -1) {
895                device_printf(dev, "failed to setup interrupts\n");
896                cpsw_detach(dev);
897                return (ENXIO);
898        }
899
900#ifdef CPSW_ETHERSWITCH
901        for (i = 0; i < CPSW_VLANS; i++)
902                cpsw_vgroups[i].vid = -1;
903#endif
904
905        /* Reset the controller. */
906        cpsw_reset(sc);
907        cpsw_init(sc);
908
909        for (i = 0; i < CPSW_PORTS; i++) {
910                if (!sc->dualemac && i != sc->active_slave)
911                        continue;
912                sc->port[i].dev = device_add_child(dev, "cpsw", i);
913                if (sc->port[i].dev == NULL) {
914                        cpsw_detach(dev);
915                        return (ENXIO);
916                }
917        }
918        bus_generic_probe(dev);
919        bus_generic_attach(dev);
920
921        return (0);
922}
923
924static int
925cpsw_detach(device_t dev)
926{
927        struct cpsw_softc *sc;
928        int error, i;
929
930        bus_generic_detach(dev);
931        sc = device_get_softc(dev);
932
933        for (i = 0; i < CPSW_PORTS; i++) {
934                if (sc->port[i].dev)
935                        device_delete_child(dev, sc->port[i].dev);
936        }
937
938        if (device_is_attached(dev)) {
939                callout_stop(&sc->watchdog.callout);
940                callout_drain(&sc->watchdog.callout);
941        }
942
943        /* Stop and release all interrupts */
944        cpsw_intr_detach(sc);
945
946        /* Free dmamaps and mbufs */
947        for (i = 0; i < nitems(sc->_slots); ++i)
948                cpsw_free_slot(sc, &sc->_slots[i]);
949
950        /* Free null padding buffer. */
951        if (sc->nullpad)
952                free(sc->nullpad, M_DEVBUF);
953
954        /* Free DMA tag */
955        if (sc->mbuf_dtag) {
956                error = bus_dma_tag_destroy(sc->mbuf_dtag);
957                KASSERT(error == 0, ("Unable to destroy DMA tag"));
958        }
959
960        /* Free IO memory handler */
961        if (sc->mem_res != NULL)
962                bus_release_resource(dev, SYS_RES_MEMORY, sc->mem_rid, sc->mem_res);
963        bus_release_resources(dev, irq_res_spec, sc->irq_res);
964
965        /* Destroy mutexes */
966        mtx_destroy(&sc->rx.lock);
967        mtx_destroy(&sc->tx.lock);
968
969        /* Detach the switch device, if present. */
970        error = bus_generic_detach(dev);
971        if (error != 0)
972                return (error);
973       
974        return (device_delete_children(dev));
975}
976
977static phandle_t
978cpsw_get_node(device_t bus, device_t dev)
979{
980
981        /* Share controller node with port device. */
982        return (ofw_bus_get_node(bus));
983}
984
985static int
986cpswp_probe(device_t dev)
987{
988
989        if (device_get_unit(dev) > 1) {
990                device_printf(dev, "Only two ports are supported.\n");
991                return (ENXIO);
992        }
993        device_set_desc(dev, "Ethernet Switch Port");
994
995        return (BUS_PROBE_DEFAULT);
996}
997
998static int
999cpswp_attach(device_t dev)
1000{
1001        int error;
1002        struct ifnet *ifp;
1003        struct cpswp_softc *sc;
1004        uint32_t reg;
1005        uint8_t mac_addr[ETHER_ADDR_LEN];
1006
1007        sc = device_get_softc(dev);
1008        sc->dev = dev;
1009        sc->pdev = device_get_parent(dev);
1010        sc->swsc = device_get_softc(sc->pdev);
1011        sc->unit = device_get_unit(dev);
1012        sc->phy = sc->swsc->port[sc->unit].phy;
1013        sc->vlan = sc->swsc->port[sc->unit].vlan;
1014        if (sc->swsc->dualemac && sc->vlan == -1)
1015                sc->vlan = sc->unit + 1;
1016
1017        if (sc->unit == 0) {
1018                sc->physel = MDIOUSERPHYSEL0;
1019                sc->phyaccess = MDIOUSERACCESS0;
1020        } else {
1021                sc->physel = MDIOUSERPHYSEL1;
1022                sc->phyaccess = MDIOUSERACCESS1;
1023        }
1024
1025        mtx_init(&sc->lock, device_get_nameunit(dev), "cpsw port lock",
1026            MTX_DEF);
1027
1028        /* Allocate network interface */
1029        ifp = sc->ifp = if_alloc(IFT_ETHER);
1030        if (ifp == NULL) {
1031                cpswp_detach(dev);
1032                return (ENXIO);
1033        }
1034
1035        if_initname(ifp, device_get_name(sc->dev), sc->unit);
1036        ifp->if_softc = sc;
1037        ifp->if_flags = IFF_SIMPLEX | IFF_MULTICAST | IFF_BROADCAST;
1038        ifp->if_capabilities = IFCAP_VLAN_MTU | IFCAP_HWCSUM; //FIXME VLAN?
1039        ifp->if_capenable = ifp->if_capabilities;
1040
1041        ifp->if_init = cpswp_init;
1042        ifp->if_start = cpswp_start;
1043        ifp->if_ioctl = cpswp_ioctl;
1044
1045        ifp->if_snd.ifq_drv_maxlen = sc->swsc->tx.queue_slots;
1046        IFQ_SET_MAXLEN(&ifp->if_snd, ifp->if_snd.ifq_drv_maxlen);
1047        IFQ_SET_READY(&ifp->if_snd);
1048
1049        /* Get high part of MAC address from control module (mac_id[0|1]_hi) */
1050        ti_scm_reg_read_4(SCM_MAC_ID0_HI + sc->unit * 8, &reg);
1051        mac_addr[0] = reg & 0xFF;
1052        mac_addr[1] = (reg >>  8) & 0xFF;
1053        mac_addr[2] = (reg >> 16) & 0xFF;
1054        mac_addr[3] = (reg >> 24) & 0xFF;
1055
1056        /* Get low part of MAC address from control module (mac_id[0|1]_lo) */
1057        ti_scm_reg_read_4(SCM_MAC_ID0_LO + sc->unit * 8, &reg);
1058        mac_addr[4] = reg & 0xFF;
1059        mac_addr[5] = (reg >>  8) & 0xFF;
1060
1061        error = mii_attach(dev, &sc->miibus, ifp, cpswp_ifmedia_upd,
1062            cpswp_ifmedia_sts, BMSR_DEFCAPMASK, sc->phy, MII_OFFSET_ANY, 0);
1063        if (error) {
1064                device_printf(dev, "attaching PHYs failed\n");
1065                cpswp_detach(dev);
1066                return (error);
1067        }
1068        sc->mii = device_get_softc(sc->miibus);
1069
1070        /* Select PHY and enable interrupts */
1071        cpsw_write_4(sc->swsc, sc->physel,
1072            MDIO_PHYSEL_LINKINTENB | (sc->phy & 0x1F));
1073
1074        ether_ifattach(sc->ifp, mac_addr);
1075        callout_init(&sc->mii_callout, 0);
1076
1077        return (0);
1078}
1079
1080static int
1081cpswp_detach(device_t dev)
1082{
1083        struct cpswp_softc *sc;
1084
1085        sc = device_get_softc(dev);
1086        CPSW_DEBUGF(sc->swsc, (""));
1087        if (device_is_attached(dev)) {
1088                ether_ifdetach(sc->ifp);
1089                CPSW_PORT_LOCK(sc);
1090                cpswp_stop_locked(sc);
1091                CPSW_PORT_UNLOCK(sc);
1092                callout_drain(&sc->mii_callout);
1093        }
1094
1095        bus_generic_detach(dev);
1096
1097        if_free(sc->ifp);
1098        mtx_destroy(&sc->lock);
1099
1100        return (0);
1101}
1102
1103/*
1104 *
1105 * Init/Shutdown.
1106 *
1107 */
1108
1109static int
1110cpsw_ports_down(struct cpsw_softc *sc)
1111{
1112        struct cpswp_softc *psc;
1113        struct ifnet *ifp1, *ifp2;
1114
1115        if (!sc->dualemac)
1116                return (1);
1117        psc = device_get_softc(sc->port[0].dev);
1118        ifp1 = psc->ifp;
1119        psc = device_get_softc(sc->port[1].dev);
1120        ifp2 = psc->ifp;
1121        if ((ifp1->if_flags & IFF_UP) == 0 && (ifp2->if_flags & IFF_UP) == 0)
1122                return (1);
1123
1124        return (0);
1125}
1126
1127static void
1128cpswp_init(void *arg)
1129{
1130        struct cpswp_softc *sc = arg;
1131
1132        CPSW_DEBUGF(sc->swsc, (""));
1133        CPSW_PORT_LOCK(sc);
1134        cpswp_init_locked(arg);
1135        CPSW_PORT_UNLOCK(sc);
1136}
1137
1138static void
1139cpswp_init_locked(void *arg)
1140{
1141#ifdef CPSW_ETHERSWITCH
1142        int i;
1143#endif
1144        struct cpswp_softc *sc = arg;
1145        struct ifnet *ifp;
1146        uint32_t reg;
1147
1148        CPSW_DEBUGF(sc->swsc, (""));
1149        CPSW_PORT_LOCK_ASSERT(sc);
1150        ifp = sc->ifp;
1151        if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
1152                return;
1153
1154        getbinuptime(&sc->init_uptime);
1155
1156        if (!sc->swsc->rx.running && !sc->swsc->tx.running) {
1157                /* Reset the controller. */
1158                cpsw_reset(sc->swsc);
1159                cpsw_init(sc->swsc);
1160        }
1161
1162        /* Set Slave Mapping. */
1163        cpsw_write_4(sc->swsc, CPSW_SL_RX_PRI_MAP(sc->unit), 0x76543210);
1164        cpsw_write_4(sc->swsc, CPSW_PORT_P_TX_PRI_MAP(sc->unit + 1),
1165            0x33221100);
1166        cpsw_write_4(sc->swsc, CPSW_SL_RX_MAXLEN(sc->unit), 0x5f2);
1167        /* Enable MAC RX/TX modules. */
1168        /* TODO: Docs claim that IFCTL_B and IFCTL_A do the same thing? */
1169        /* Huh?  Docs call bit 0 "Loopback" some places, "FullDuplex" others. */
1170        reg = cpsw_read_4(sc->swsc, CPSW_SL_MACCONTROL(sc->unit));
1171        reg |= CPSW_SL_MACTL_GMII_ENABLE;
1172        cpsw_write_4(sc->swsc, CPSW_SL_MACCONTROL(sc->unit), reg);
1173
1174        /* Initialize ALE: set port to forwarding, initialize addrs */
1175        cpsw_write_4(sc->swsc, CPSW_ALE_PORTCTL(sc->unit + 1),
1176            ALE_PORTCTL_INGRESS | ALE_PORTCTL_FORWARD);
1177        cpswp_ale_update_addresses(sc, 1);
1178
1179        if (sc->swsc->dualemac) {
1180                /* Set Port VID. */
1181                cpsw_write_4(sc->swsc, CPSW_PORT_P_VLAN(sc->unit + 1),
1182                    sc->vlan & 0xfff);
1183                cpsw_ale_update_vlan_table(sc->swsc, sc->vlan,
1184                    (1 << (sc->unit + 1)) | (1 << 0), /* Member list */
1185                    (1 << (sc->unit + 1)) | (1 << 0), /* Untagged egress */
1186                    (1 << (sc->unit + 1)) | (1 << 0), 0); /* mcast reg flood */
1187#ifdef CPSW_ETHERSWITCH
1188                for (i = 0; i < CPSW_VLANS; i++) {
1189                        if (cpsw_vgroups[i].vid != -1)
1190                                continue;
1191                        cpsw_vgroups[i].vid = sc->vlan;
1192                        break;
1193                }
1194#endif
1195        }
1196
1197        mii_mediachg(sc->mii);
1198        callout_reset(&sc->mii_callout, hz, cpswp_tick, sc);
1199        ifp->if_drv_flags |= IFF_DRV_RUNNING;
1200        ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1201}
1202
1203static int
1204cpsw_shutdown(device_t dev)
1205{
1206        struct cpsw_softc *sc;
1207        struct cpswp_softc *psc;
1208        int i;
1209
1210        sc = device_get_softc(dev);
1211        CPSW_DEBUGF(sc, (""));
1212        for (i = 0; i < CPSW_PORTS; i++) {
1213                if (!sc->dualemac && i != sc->active_slave)
1214                        continue;
1215                psc = device_get_softc(sc->port[i].dev);
1216                CPSW_PORT_LOCK(psc);
1217                cpswp_stop_locked(psc);
1218                CPSW_PORT_UNLOCK(psc);
1219        }
1220
1221        return (0);
1222}
1223
1224static void
1225cpsw_rx_teardown(struct cpsw_softc *sc)
1226{
1227        int i = 0;
1228
1229        CPSW_RX_LOCK(sc);
1230        CPSW_DEBUGF(sc, ("starting RX teardown"));
1231        sc->rx.teardown = 1;
1232        cpsw_write_4(sc, CPSW_CPDMA_RX_TEARDOWN, 0);
1233        CPSW_RX_UNLOCK(sc);
1234        while (sc->rx.running) {
1235                if (++i > 10) {
1236                        device_printf(sc->dev,
1237                            "Unable to cleanly shutdown receiver\n");
1238                        return;
1239                }
1240                DELAY(200);
1241        }
1242        if (!sc->rx.running)
1243                CPSW_DEBUGF(sc, ("finished RX teardown (%d retries)", i));
1244}
1245
1246static void
1247cpsw_tx_teardown(struct cpsw_softc *sc)
1248{
1249        int i = 0;
1250
1251        CPSW_TX_LOCK(sc);
1252        CPSW_DEBUGF(sc, ("starting TX teardown"));
1253        /* Start the TX queue teardown if queue is not empty. */
1254        if (STAILQ_FIRST(&sc->tx.active) != NULL)
1255                cpsw_write_4(sc, CPSW_CPDMA_TX_TEARDOWN, 0);
1256        else
1257                sc->tx.teardown = 1;
1258        cpsw_tx_dequeue(sc);
1259        while (sc->tx.running && ++i < 10) {
1260                DELAY(200);
1261                cpsw_tx_dequeue(sc);
1262        }
1263        if (sc->tx.running) {
1264                device_printf(sc->dev,
1265                    "Unable to cleanly shutdown transmitter\n");
1266        }
1267        CPSW_DEBUGF(sc,
1268            ("finished TX teardown (%d retries, %d idle buffers)", i,
1269             sc->tx.active_queue_len));
1270        CPSW_TX_UNLOCK(sc);
1271}
1272
1273static void
1274cpswp_stop_locked(struct cpswp_softc *sc)
1275{
1276        struct ifnet *ifp;
1277        uint32_t reg;
1278
1279        ifp = sc->ifp;
1280        CPSW_DEBUGF(sc->swsc, (""));
1281        CPSW_PORT_LOCK_ASSERT(sc);
1282
1283        if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
1284                return;
1285
1286        /* Disable interface */
1287        ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
1288        ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1289
1290        /* Stop ticker */
1291        callout_stop(&sc->mii_callout);
1292
1293        /* Tear down the RX/TX queues. */
1294        if (cpsw_ports_down(sc->swsc)) {
1295                cpsw_rx_teardown(sc->swsc);
1296                cpsw_tx_teardown(sc->swsc);
1297        }
1298
1299        /* Stop MAC RX/TX modules. */
1300        reg = cpsw_read_4(sc->swsc, CPSW_SL_MACCONTROL(sc->unit));
1301        reg &= ~CPSW_SL_MACTL_GMII_ENABLE;
1302        cpsw_write_4(sc->swsc, CPSW_SL_MACCONTROL(sc->unit), reg);
1303
1304        if (cpsw_ports_down(sc->swsc)) {
1305                /* Capture stats before we reset controller. */
1306                cpsw_stats_collect(sc->swsc);
1307
1308                cpsw_reset(sc->swsc);
1309                cpsw_init(sc->swsc);
1310        }
1311}
1312
1313/*
1314 *  Suspend/Resume.
1315 */
1316
1317static int
1318cpsw_suspend(device_t dev)
1319{
1320        struct cpsw_softc *sc;
1321        struct cpswp_softc *psc;
1322        int i;
1323
1324        sc = device_get_softc(dev);
1325        CPSW_DEBUGF(sc, (""));
1326        for (i = 0; i < CPSW_PORTS; i++) {
1327                if (!sc->dualemac && i != sc->active_slave)
1328                        continue;
1329                psc = device_get_softc(sc->port[i].dev);
1330                CPSW_PORT_LOCK(psc);
1331                cpswp_stop_locked(psc);
1332                CPSW_PORT_UNLOCK(psc);
1333        }
1334
1335        return (0);
1336}
1337
1338static int
1339cpsw_resume(device_t dev)
1340{
1341        struct cpsw_softc *sc;
1342
1343        sc  = device_get_softc(dev);
1344        CPSW_DEBUGF(sc, ("UNIMPLEMENTED"));
1345
1346        return (0);
1347}
1348
1349/*
1350 *
1351 *  IOCTL
1352 *
1353 */
1354
1355static void
1356cpsw_set_promisc(struct cpswp_softc *sc, int set)
1357{
1358        uint32_t reg;
1359
1360        /*
1361         * Enabling promiscuous mode requires ALE_BYPASS to be enabled.
1362         * That disables the ALE forwarding logic and causes every
1363         * packet to be sent only to the host port.  In bypass mode,
1364         * the ALE processes host port transmit packets the same as in
1365         * normal mode.
1366         */
1367        reg = cpsw_read_4(sc->swsc, CPSW_ALE_CONTROL);
1368        reg &= ~CPSW_ALE_CTL_BYPASS;
1369        if (set)
1370                reg |= CPSW_ALE_CTL_BYPASS;
1371        cpsw_write_4(sc->swsc, CPSW_ALE_CONTROL, reg);
1372}
1373
1374static void
1375cpsw_set_allmulti(struct cpswp_softc *sc, int set)
1376{
1377        if (set) {
1378                printf("All-multicast mode unimplemented\n");
1379        }
1380}
1381
1382static int
1383cpswp_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
1384{
1385        struct cpswp_softc *sc;
1386        struct ifreq *ifr;
1387        int error;
1388        uint32_t changed;
1389
1390        error = 0;
1391        sc = ifp->if_softc;
1392        ifr = (struct ifreq *)data;
1393
1394        switch (command) {
1395        case SIOCSIFCAP:
1396                changed = ifp->if_capenable ^ ifr->ifr_reqcap;
1397                if (changed & IFCAP_HWCSUM) {
1398                        if ((ifr->ifr_reqcap & changed) & IFCAP_HWCSUM)
1399                                ifp->if_capenable |= IFCAP_HWCSUM;
1400                        else
1401                                ifp->if_capenable &= ~IFCAP_HWCSUM;
1402                }
1403                error = 0;
1404                break;
1405        case SIOCSIFFLAGS:
1406                CPSW_PORT_LOCK(sc);
1407                if (ifp->if_flags & IFF_UP) {
1408                        if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
1409                                changed = ifp->if_flags ^ sc->if_flags;
1410                                CPSW_DEBUGF(sc->swsc,
1411                                    ("SIOCSIFFLAGS: UP & RUNNING (changed=0x%x)",
1412                                    changed));
1413                                if (changed & IFF_PROMISC)
1414                                        cpsw_set_promisc(sc,
1415                                            ifp->if_flags & IFF_PROMISC);
1416                                if (changed & IFF_ALLMULTI)
1417                                        cpsw_set_allmulti(sc,
1418                                            ifp->if_flags & IFF_ALLMULTI);
1419                        } else {
1420                                CPSW_DEBUGF(sc->swsc,
1421                                    ("SIOCSIFFLAGS: starting up"));
1422                                cpswp_init_locked(sc);
1423                        }
1424                } else if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
1425                        CPSW_DEBUGF(sc->swsc, ("SIOCSIFFLAGS: shutting down"));
1426                        cpswp_stop_locked(sc);
1427                }
1428
1429                sc->if_flags = ifp->if_flags;
1430                CPSW_PORT_UNLOCK(sc);
1431                break;
1432        case SIOCADDMULTI:
1433                cpswp_ale_update_addresses(sc, 0);
1434                break;
1435        case SIOCDELMULTI:
1436                /* Ugh.  DELMULTI doesn't provide the specific address
1437                   being removed, so the best we can do is remove
1438                   everything and rebuild it all. */
1439                cpswp_ale_update_addresses(sc, 1);
1440                break;
1441        case SIOCGIFMEDIA:
1442        case SIOCSIFMEDIA:
1443                error = ifmedia_ioctl(ifp, ifr, &sc->mii->mii_media, command);
1444                break;
1445        default:
1446                error = ether_ioctl(ifp, command, data);
1447        }
1448        return (error);
1449}
1450
1451/*
1452 *
1453 * MIIBUS
1454 *
1455 */
1456static int
1457cpswp_miibus_ready(struct cpsw_softc *sc, uint32_t reg)
1458{
1459        uint32_t r, retries = CPSW_MIIBUS_RETRIES;
1460
1461        while (--retries) {
1462                r = cpsw_read_4(sc, reg);
1463                if ((r & MDIO_PHYACCESS_GO) == 0)
1464                        return (1);
1465                DELAY(CPSW_MIIBUS_DELAY);
1466        }
1467
1468        return (0);
1469}
1470
1471static int
1472cpswp_miibus_readreg(device_t dev, int phy, int reg)
1473{
1474        struct cpswp_softc *sc;
1475        uint32_t cmd, r;
1476
1477        sc = device_get_softc(dev);
1478        if (!cpswp_miibus_ready(sc->swsc, sc->phyaccess)) {
1479                device_printf(dev, "MDIO not ready to read\n");
1480                return (0);
1481        }
1482
1483        /* Set GO, reg, phy */
1484        cmd = MDIO_PHYACCESS_GO | (reg & 0x1F) << 21 | (phy & 0x1F) << 16;
1485        cpsw_write_4(sc->swsc, sc->phyaccess, cmd);
1486
1487        if (!cpswp_miibus_ready(sc->swsc, sc->phyaccess)) {
1488                device_printf(dev, "MDIO timed out during read\n");
1489                return (0);
1490        }
1491
1492        r = cpsw_read_4(sc->swsc, sc->phyaccess);
1493        if ((r & MDIO_PHYACCESS_ACK) == 0) {
1494                device_printf(dev, "Failed to read from PHY.\n");
1495                r = 0;
1496        }
1497        return (r & 0xFFFF);
1498}
1499
1500static int
1501cpswp_miibus_writereg(device_t dev, int phy, int reg, int value)
1502{
1503        struct cpswp_softc *sc;
1504        uint32_t cmd;
1505
1506        sc = device_get_softc(dev);
1507        if (!cpswp_miibus_ready(sc->swsc, sc->phyaccess)) {
1508                device_printf(dev, "MDIO not ready to write\n");
1509                return (0);
1510        }
1511
1512        /* Set GO, WRITE, reg, phy, and value */
1513        cmd = MDIO_PHYACCESS_GO | MDIO_PHYACCESS_WRITE |
1514            (reg & 0x1F) << 21 | (phy & 0x1F) << 16 | (value & 0xFFFF);
1515        cpsw_write_4(sc->swsc, sc->phyaccess, cmd);
1516
1517        if (!cpswp_miibus_ready(sc->swsc, sc->phyaccess)) {
1518                device_printf(dev, "MDIO timed out during write\n");
1519                return (0);
1520        }
1521
1522        return (0);
1523}
1524
1525static void
1526cpswp_miibus_statchg(device_t dev)
1527{
1528        struct cpswp_softc *sc;
1529        uint32_t mac_control, reg;
1530
1531        sc = device_get_softc(dev);
1532        CPSW_DEBUGF(sc->swsc, (""));
1533
1534        reg = CPSW_SL_MACCONTROL(sc->unit);
1535        mac_control = cpsw_read_4(sc->swsc, reg);
1536        mac_control &= ~(CPSW_SL_MACTL_GIG | CPSW_SL_MACTL_IFCTL_A |
1537            CPSW_SL_MACTL_IFCTL_B | CPSW_SL_MACTL_FULLDUPLEX);
1538
1539        switch(IFM_SUBTYPE(sc->mii->mii_media_active)) {
1540        case IFM_1000_SX:
1541        case IFM_1000_LX:
1542        case IFM_1000_CX:
1543        case IFM_1000_T:
1544                mac_control |= CPSW_SL_MACTL_GIG;
1545                break;
1546
1547        case IFM_100_TX:
1548                mac_control |= CPSW_SL_MACTL_IFCTL_A;
1549                break;
1550        }
1551        if (sc->mii->mii_media_active & IFM_FDX)
1552                mac_control |= CPSW_SL_MACTL_FULLDUPLEX;
1553
1554        cpsw_write_4(sc->swsc, reg, mac_control);
1555}
1556
1557/*
1558 *
1559 * Transmit/Receive Packets.
1560 *
1561 */
1562static void
1563cpsw_intr_rx(void *arg)
1564{
1565        struct cpsw_softc *sc;
1566        struct ifnet *ifp;
1567        struct mbuf *received, *next;
1568
1569        sc = (struct cpsw_softc *)arg;
1570        CPSW_RX_LOCK(sc);
1571        if (sc->rx.teardown) {
1572                sc->rx.running = 0;
1573                sc->rx.teardown = 0;
1574                cpsw_write_cp(sc, &sc->rx, 0xfffffffc);
1575        }
1576        received = cpsw_rx_dequeue(sc);
1577        cpsw_rx_enqueue(sc);
1578        cpsw_write_4(sc, CPSW_CPDMA_CPDMA_EOI_VECTOR, 1);
1579        CPSW_RX_UNLOCK(sc);
1580
1581        while (received != NULL) {
1582                next = received->m_nextpkt;
1583                received->m_nextpkt = NULL;
1584                ifp = received->m_pkthdr.rcvif;
1585                (*ifp->if_input)(ifp, received);
1586                if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
1587                received = next;
1588        }
1589}
1590
1591static struct mbuf *
1592cpsw_rx_dequeue(struct cpsw_softc *sc)
1593{
1594        int nsegs, port, removed;
1595        struct cpsw_cpdma_bd bd;
1596        struct cpsw_slot *last, *slot;
1597        struct cpswp_softc *psc;
1598        struct mbuf *m, *m0, *mb_head, *mb_tail;
1599        uint16_t m0_flags;
1600
1601        nsegs = 0;
1602        m0 = NULL;
1603        last = NULL;
1604        mb_head = NULL;
1605        mb_tail = NULL;
1606        removed = 0;
1607
1608        /* Pull completed packets off hardware RX queue. */
1609        while ((slot = STAILQ_FIRST(&sc->rx.active)) != NULL) {
1610                cpsw_cpdma_read_bd(sc, slot, &bd);
1611
1612                /*
1613                 * Stop on packets still in use by hardware, but do not stop
1614                 * on packets with the teardown complete flag, they will be
1615                 * discarded later.
1616                 */
1617                if ((bd.flags & (CPDMA_BD_OWNER | CPDMA_BD_TDOWNCMPLT)) ==
1618                    CPDMA_BD_OWNER)
1619                        break;
1620
1621                last = slot;
1622                ++removed;
1623                STAILQ_REMOVE_HEAD(&sc->rx.active, next);
1624                STAILQ_INSERT_TAIL(&sc->rx.avail, slot, next);
1625
1626                bus_dmamap_sync(sc->mbuf_dtag, slot->dmamap, BUS_DMASYNC_POSTREAD);
1627                bus_dmamap_unload(sc->mbuf_dtag, slot->dmamap);
1628
1629                m = slot->mbuf;
1630                slot->mbuf = NULL;
1631
1632                if (bd.flags & CPDMA_BD_TDOWNCMPLT) {
1633                        CPSW_DEBUGF(sc, ("RX teardown is complete"));
1634                        m_freem(m);
1635                        sc->rx.running = 0;
1636                        sc->rx.teardown = 0;
1637                        break;
1638                }
1639
1640                port = (bd.flags & CPDMA_BD_PORT_MASK) - 1;
1641                KASSERT(port >= 0 && port <= 1,
1642                    ("patcket received with invalid port: %d", port));
1643                psc = device_get_softc(sc->port[port].dev);
1644
1645                /* Set up mbuf */
1646                m->m_data += bd.bufoff;
1647                m->m_len = bd.buflen;
1648                if (bd.flags & CPDMA_BD_SOP) {
1649                        m->m_pkthdr.len = bd.pktlen;
1650                        m->m_pkthdr.rcvif = psc->ifp;
1651                        m->m_flags |= M_PKTHDR;
1652                        m0_flags = bd.flags;
1653                        m0 = m;
1654                }
1655                nsegs++;
1656                m->m_next = NULL;
1657                m->m_nextpkt = NULL;
1658                if (bd.flags & CPDMA_BD_EOP && m0 != NULL) {
1659                        if (m0_flags & CPDMA_BD_PASS_CRC)
1660                                m_adj(m0, -ETHER_CRC_LEN);
1661                        m0_flags = 0;
1662                        m0 = NULL;
1663                        if (nsegs > sc->rx.longest_chain)
1664                                sc->rx.longest_chain = nsegs;
1665                        nsegs = 0;
1666                }
1667
1668                if ((psc->ifp->if_capenable & IFCAP_RXCSUM) != 0) {
1669                        /* check for valid CRC by looking into pkt_err[5:4] */
1670                        if ((bd.flags &
1671                            (CPDMA_BD_SOP | CPDMA_BD_PKT_ERR_MASK)) ==
1672                            CPDMA_BD_SOP) {
1673                                m->m_pkthdr.csum_flags |= CSUM_IP_CHECKED;
1674                                m->m_pkthdr.csum_flags |= CSUM_IP_VALID;
1675                                m->m_pkthdr.csum_data = 0xffff;
1676                        }
1677                }
1678
1679                if (STAILQ_FIRST(&sc->rx.active) != NULL &&
1680                    (bd.flags & (CPDMA_BD_EOP | CPDMA_BD_EOQ)) ==
1681                    (CPDMA_BD_EOP | CPDMA_BD_EOQ)) {
1682                        cpsw_write_hdp_slot(sc, &sc->rx,
1683                            STAILQ_FIRST(&sc->rx.active));
1684                        sc->rx.queue_restart++;
1685                }
1686
1687                /* Add mbuf to packet list to be returned. */
1688                if (mb_tail != NULL && (bd.flags & CPDMA_BD_SOP)) {
1689                        mb_tail->m_nextpkt = m;
1690                } else if (mb_tail != NULL) {
1691                        mb_tail->m_next = m;
1692                } else if (mb_tail == NULL && (bd.flags & CPDMA_BD_SOP) == 0) {
1693                        if (bootverbose)
1694                                printf(
1695                                    "%s: %s: discanding fragment packet w/o header\n",
1696                                    __func__, psc->ifp->if_xname);
1697                        m_freem(m);
1698                        continue;
1699                } else {
1700                        mb_head = m;
1701                }
1702                mb_tail = m;
1703        }
1704
1705        if (removed != 0) {
1706                cpsw_write_cp_slot(sc, &sc->rx, last);
1707                sc->rx.queue_removes += removed;
1708                sc->rx.avail_queue_len += removed;
1709                sc->rx.active_queue_len -= removed;
1710                if (sc->rx.avail_queue_len > sc->rx.max_avail_queue_len)
1711                        sc->rx.max_avail_queue_len = sc->rx.avail_queue_len;
1712                CPSW_DEBUGF(sc, ("Removed %d received packet(s) from RX queue", removed));
1713        }
1714
1715        return (mb_head);
1716}
1717
1718static void
1719cpsw_rx_enqueue(struct cpsw_softc *sc)
1720{
1721        bus_dma_segment_t seg[1];
1722        struct cpsw_cpdma_bd bd;
1723        struct cpsw_slot *first_new_slot, *last_old_slot, *next, *slot;
1724        int error, nsegs, added = 0;
1725
1726        /* Register new mbufs with hardware. */
1727        first_new_slot = NULL;
1728        last_old_slot = STAILQ_LAST(&sc->rx.active, cpsw_slot, next);
1729        while ((slot = STAILQ_FIRST(&sc->rx.avail)) != NULL) {
1730                if (first_new_slot == NULL)
1731                        first_new_slot = slot;
1732                if (slot->mbuf == NULL) {
1733                        slot->mbuf = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
1734                        if (slot->mbuf == NULL) {
1735                                device_printf(sc->dev,
1736                                    "Unable to fill RX queue\n");
1737                                break;
1738                        }
1739                        slot->mbuf->m_len =
1740                            slot->mbuf->m_pkthdr.len =
1741                            slot->mbuf->m_ext.ext_size;
1742                }
1743
1744                error = bus_dmamap_load_mbuf_sg(sc->mbuf_dtag, slot->dmamap,
1745                    slot->mbuf, seg, &nsegs, BUS_DMA_NOWAIT);
1746
1747                KASSERT(nsegs == 1, ("More than one segment (nsegs=%d)", nsegs));
1748                KASSERT(error == 0, ("DMA error (error=%d)", error));
1749                if (error != 0 || nsegs != 1) {
1750                        device_printf(sc->dev,
1751                            "%s: Can't prep RX buf for DMA (nsegs=%d, error=%d)\n",
1752                            __func__, nsegs, error);
1753                        bus_dmamap_unload(sc->mbuf_dtag, slot->dmamap);
1754                        m_freem(slot->mbuf);
1755                        slot->mbuf = NULL;
1756                        break;
1757                }
1758
1759#ifndef __rtems__
1760                bus_dmamap_sync(sc->mbuf_dtag, slot->dmamap, BUS_DMASYNC_PREREAD);
1761#endif /* __rtems__ */
1762
1763                /* Create and submit new rx descriptor. */
1764                if ((next = STAILQ_NEXT(slot, next)) != NULL)
1765                        bd.next = cpsw_cpdma_bd_paddr(sc, next);
1766                else
1767                        bd.next = 0;
1768                bd.bufptr = seg->ds_addr;
1769                bd.bufoff = 0;
1770                bd.buflen = MCLBYTES - 1;
1771                bd.pktlen = bd.buflen;
1772                bd.flags = CPDMA_BD_OWNER;
1773#ifdef __rtems__
1774                rtems_cache_invalidate_multiple_data_lines(
1775                    seg->ds_addr, bd.buflen);
1776#endif /* __rtems__ */
1777                cpsw_cpdma_write_bd(sc, slot, &bd);
1778                ++added;
1779
1780                STAILQ_REMOVE_HEAD(&sc->rx.avail, next);
1781                STAILQ_INSERT_TAIL(&sc->rx.active, slot, next);
1782        }
1783
1784        if (added == 0 || first_new_slot == NULL)
1785                return;
1786
1787        CPSW_DEBUGF(sc, ("Adding %d buffers to RX queue", added));
1788
1789        /* Link new entries to hardware RX queue. */
1790        if (last_old_slot == NULL) {
1791                /* Start a fresh queue. */
1792                cpsw_write_hdp_slot(sc, &sc->rx, first_new_slot);
1793        } else {
1794                /* Add buffers to end of current queue. */
1795                cpsw_cpdma_write_bd_next(sc, last_old_slot, first_new_slot);
1796        }
1797        sc->rx.queue_adds += added;
1798        sc->rx.avail_queue_len -= added;
1799        sc->rx.active_queue_len += added;
1800        cpsw_write_4(sc, CPSW_CPDMA_RX_FREEBUFFER(0), added);
1801        if (sc->rx.active_queue_len > sc->rx.max_active_queue_len)
1802                sc->rx.max_active_queue_len = sc->rx.active_queue_len;
1803}
1804
1805static void
1806cpswp_start(struct ifnet *ifp)
1807{
1808        struct cpswp_softc *sc;
1809
1810        sc = ifp->if_softc;
1811        if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
1812            sc->swsc->tx.running == 0) {
1813                return;
1814        }
1815        CPSW_TX_LOCK(sc->swsc);
1816        cpswp_tx_enqueue(sc);
1817        cpsw_tx_dequeue(sc->swsc);
1818        CPSW_TX_UNLOCK(sc->swsc);
1819}
1820
1821static void
1822cpsw_intr_tx(void *arg)
1823{
1824        struct cpsw_softc *sc;
1825
1826        sc = (struct cpsw_softc *)arg;
1827        CPSW_TX_LOCK(sc);
1828        if (cpsw_read_4(sc, CPSW_CPDMA_TX_CP(0)) == 0xfffffffc)
1829                cpsw_write_cp(sc, &sc->tx, 0xfffffffc);
1830        cpsw_tx_dequeue(sc);
1831        cpsw_write_4(sc, CPSW_CPDMA_CPDMA_EOI_VECTOR, 2);
1832        CPSW_TX_UNLOCK(sc);
1833}
1834
1835static void
1836cpswp_tx_enqueue(struct cpswp_softc *sc)
1837{
1838        bus_dma_segment_t segs[CPSW_TXFRAGS];
1839        struct cpsw_cpdma_bd bd;
1840        struct cpsw_slot *first_new_slot, *last, *last_old_slot, *next, *slot;
1841        struct mbuf *m0;
1842        int error, nsegs, seg, added = 0, padlen;
1843
1844        /* Pull pending packets from IF queue and prep them for DMA. */
1845        last = NULL;
1846        first_new_slot = NULL;
1847        last_old_slot = STAILQ_LAST(&sc->swsc->tx.active, cpsw_slot, next);
1848        while ((slot = STAILQ_FIRST(&sc->swsc->tx.avail)) != NULL) {
1849                IF_DEQUEUE(&sc->ifp->if_snd, m0);
1850                if (m0 == NULL)
1851                        break;
1852
1853                slot->mbuf = m0;
1854                padlen = ETHER_MIN_LEN - ETHER_CRC_LEN - m0->m_pkthdr.len;
1855                if (padlen < 0)
1856                        padlen = 0;
1857                else if (padlen > 0)
1858                        m_append(slot->mbuf, padlen, sc->swsc->nullpad);
1859
1860                /* Create mapping in DMA memory */
1861                error = bus_dmamap_load_mbuf_sg(sc->swsc->mbuf_dtag,
1862                    slot->dmamap, slot->mbuf, segs, &nsegs, BUS_DMA_NOWAIT);
1863                /* If the packet is too fragmented, try to simplify. */
1864                if (error == EFBIG ||
1865                    (error == 0 && nsegs > sc->swsc->tx.avail_queue_len)) {
1866                        bus_dmamap_unload(sc->swsc->mbuf_dtag, slot->dmamap);
1867                        m0 = m_defrag(slot->mbuf, M_NOWAIT);
1868                        if (m0 == NULL) {
1869                                device_printf(sc->dev,
1870                                    "Can't defragment packet; dropping\n");
1871                                m_freem(slot->mbuf);
1872                        } else {
1873                                CPSW_DEBUGF(sc->swsc,
1874                                    ("Requeueing defragmented packet"));
1875                                IF_PREPEND(&sc->ifp->if_snd, m0);
1876                        }
1877                        slot->mbuf = NULL;
1878                        continue;
1879                }
1880                if (error != 0) {
1881                        device_printf(sc->dev,
1882                            "%s: Can't setup DMA (error=%d), dropping packet\n",
1883                            __func__, error);
1884                        bus_dmamap_unload(sc->swsc->mbuf_dtag, slot->dmamap);
1885                        m_freem(slot->mbuf);
1886                        slot->mbuf = NULL;
1887                        break;
1888                }
1889
1890#ifndef __rtems__
1891                bus_dmamap_sync(sc->swsc->mbuf_dtag, slot->dmamap,
1892                                BUS_DMASYNC_PREWRITE);
1893#endif /* __rtems__ */
1894
1895                CPSW_DEBUGF(sc->swsc,
1896                    ("Queueing TX packet: %d segments + %d pad bytes",
1897                    nsegs, padlen));
1898
1899                if (first_new_slot == NULL)
1900                        first_new_slot = slot;
1901
1902                /* Link from the previous descriptor. */
1903                if (last != NULL)
1904                        cpsw_cpdma_write_bd_next(sc->swsc, last, slot);
1905
1906                slot->ifp = sc->ifp;
1907
1908                /* If there is only one segment, the for() loop
1909                 * gets skipped and the single buffer gets set up
1910                 * as both SOP and EOP. */
1911                if (nsegs > 1) {
1912                        next = STAILQ_NEXT(slot, next);
1913                        bd.next = cpsw_cpdma_bd_paddr(sc->swsc, next);
1914                } else
1915                        bd.next = 0;
1916                /* Start by setting up the first buffer. */
1917                bd.bufptr = segs[0].ds_addr;
1918                bd.bufoff = 0;
1919                bd.buflen = segs[0].ds_len;
1920                bd.pktlen = m_length(slot->mbuf, NULL);
1921                bd.flags =  CPDMA_BD_SOP | CPDMA_BD_OWNER;
1922                if (sc->swsc->dualemac) {
1923                        bd.flags |= CPDMA_BD_TO_PORT;
1924                        bd.flags |= ((sc->unit + 1) & CPDMA_BD_PORT_MASK);
1925                }
1926#ifdef __rtems__
1927                rtems_cache_flush_multiple_data_lines((void *)segs[0].ds_addr,
1928                    segs[0].ds_len);
1929#endif /* __rtems__ */
1930                for (seg = 1; seg < nsegs; ++seg) {
1931                        /* Save the previous buffer (which isn't EOP) */
1932                        cpsw_cpdma_write_bd(sc->swsc, slot, &bd);
1933                        STAILQ_REMOVE_HEAD(&sc->swsc->tx.avail, next);
1934                        STAILQ_INSERT_TAIL(&sc->swsc->tx.active, slot, next);
1935                        slot = STAILQ_FIRST(&sc->swsc->tx.avail);
1936
1937                        /* Setup next buffer (which isn't SOP) */
1938                        if (nsegs > seg + 1) {
1939                                next = STAILQ_NEXT(slot, next);
1940                                bd.next = cpsw_cpdma_bd_paddr(sc->swsc, next);
1941                        } else
1942                                bd.next = 0;
1943                        bd.bufptr = segs[seg].ds_addr;
1944                        bd.bufoff = 0;
1945                        bd.buflen = segs[seg].ds_len;
1946                        bd.pktlen = 0;
1947                        bd.flags = CPDMA_BD_OWNER;
1948#ifdef __rtems__
1949                        rtems_cache_flush_multiple_data_lines(
1950                            (void *)segs[seg].ds_addr, segs[seg].ds_len);
1951#endif /* __rtems__ */
1952                }
1953
1954                /* Save the final buffer. */
1955                bd.flags |= CPDMA_BD_EOP;
1956                cpsw_cpdma_write_bd(sc->swsc, slot, &bd);
1957                STAILQ_REMOVE_HEAD(&sc->swsc->tx.avail, next);
1958                STAILQ_INSERT_TAIL(&sc->swsc->tx.active, slot, next);
1959
1960                last = slot;
1961                added += nsegs;
1962                if (nsegs > sc->swsc->tx.longest_chain)
1963                        sc->swsc->tx.longest_chain = nsegs;
1964
1965                BPF_MTAP(sc->ifp, m0);
1966        }
1967
1968        if (first_new_slot == NULL)
1969                return;
1970
1971        /* Attach the list of new buffers to the hardware TX queue. */
1972        if (last_old_slot != NULL &&
1973            (cpsw_cpdma_read_bd_flags(sc->swsc, last_old_slot) &
1974             CPDMA_BD_EOQ) == 0) {
1975                /* Add buffers to end of current queue. */
1976                cpsw_cpdma_write_bd_next(sc->swsc, last_old_slot,
1977                    first_new_slot);
1978        } else {
1979                /* Start a fresh queue. */
1980                cpsw_write_hdp_slot(sc->swsc, &sc->swsc->tx, first_new_slot);
1981        }
1982        sc->swsc->tx.queue_adds += added;
1983        sc->swsc->tx.avail_queue_len -= added;
1984        sc->swsc->tx.active_queue_len += added;
1985        if (sc->swsc->tx.active_queue_len > sc->swsc->tx.max_active_queue_len) {
1986                sc->swsc->tx.max_active_queue_len = sc->swsc->tx.active_queue_len;
1987        }
1988        CPSW_DEBUGF(sc->swsc, ("Queued %d TX packet(s)", added));
1989}
1990
1991static int
1992cpsw_tx_dequeue(struct cpsw_softc *sc)
1993{
1994        struct cpsw_slot *slot, *last_removed_slot = NULL;
1995        struct cpsw_cpdma_bd bd;
1996        uint32_t flags, removed = 0;
1997
1998        /* Pull completed buffers off the hardware TX queue. */
1999        slot = STAILQ_FIRST(&sc->tx.active);
2000        while (slot != NULL) {
2001                flags = cpsw_cpdma_read_bd_flags(sc, slot);
2002
2003                /* TearDown complete is only marked on the SOP for the packet. */
2004                if ((flags & (CPDMA_BD_SOP | CPDMA_BD_TDOWNCMPLT)) ==
2005                    (CPDMA_BD_SOP | CPDMA_BD_TDOWNCMPLT)) {
2006                        sc->tx.teardown = 1;
2007                }
2008
2009                if ((flags & (CPDMA_BD_SOP | CPDMA_BD_OWNER)) ==
2010                    (CPDMA_BD_SOP | CPDMA_BD_OWNER) && sc->tx.teardown == 0)
2011                        break; /* Hardware is still using this packet. */
2012
2013                bus_dmamap_sync(sc->mbuf_dtag, slot->dmamap, BUS_DMASYNC_POSTWRITE);
2014                bus_dmamap_unload(sc->mbuf_dtag, slot->dmamap);
2015                m_freem(slot->mbuf);
2016                slot->mbuf = NULL;
2017
2018                if (slot->ifp) {
2019                        if (sc->tx.teardown == 0)
2020                                if_inc_counter(slot->ifp, IFCOUNTER_OPACKETS, 1);
2021                        else
2022                                if_inc_counter(slot->ifp, IFCOUNTER_OQDROPS, 1);
2023                }
2024
2025                /* Dequeue any additional buffers used by this packet. */
2026                while (slot != NULL && slot->mbuf == NULL) {
2027                        STAILQ_REMOVE_HEAD(&sc->tx.active, next);
2028                        STAILQ_INSERT_TAIL(&sc->tx.avail, slot, next);
2029                        ++removed;
2030                        last_removed_slot = slot;
2031                        slot = STAILQ_FIRST(&sc->tx.active);
2032                }
2033
2034                cpsw_write_cp_slot(sc, &sc->tx, last_removed_slot);
2035
2036                /* Restart the TX queue if necessary. */
2037                cpsw_cpdma_read_bd(sc, last_removed_slot, &bd);
2038                if (slot != NULL && bd.next != 0 && (bd.flags &
2039                    (CPDMA_BD_EOP | CPDMA_BD_OWNER | CPDMA_BD_EOQ)) ==
2040                    (CPDMA_BD_EOP | CPDMA_BD_EOQ)) {
2041                        cpsw_write_hdp_slot(sc, &sc->tx, slot);
2042                        sc->tx.queue_restart++;
2043                        break;
2044                }
2045        }
2046
2047        if (removed != 0) {
2048                sc->tx.queue_removes += removed;
2049                sc->tx.active_queue_len -= removed;
2050                sc->tx.avail_queue_len += removed;
2051                if (sc->tx.avail_queue_len > sc->tx.max_avail_queue_len)
2052                        sc->tx.max_avail_queue_len = sc->tx.avail_queue_len;
2053                CPSW_DEBUGF(sc, ("TX removed %d completed packet(s)", removed));
2054        }
2055
2056        if (sc->tx.teardown && STAILQ_EMPTY(&sc->tx.active)) {
2057                CPSW_DEBUGF(sc, ("TX teardown is complete"));
2058                sc->tx.teardown = 0;
2059                sc->tx.running = 0;
2060        }
2061
2062        return (removed);
2063}
2064
2065/*
2066 *
2067 * Miscellaneous interrupts.
2068 *
2069 */
2070
2071static void
2072cpsw_intr_rx_thresh(void *arg)
2073{
2074        struct cpsw_softc *sc;
2075        struct ifnet *ifp;
2076        struct mbuf *received, *next;
2077
2078        sc = (struct cpsw_softc *)arg;
2079        CPSW_RX_LOCK(sc);
2080        received = cpsw_rx_dequeue(sc);
2081        cpsw_rx_enqueue(sc);
2082        cpsw_write_4(sc, CPSW_CPDMA_CPDMA_EOI_VECTOR, 0);
2083        CPSW_RX_UNLOCK(sc);
2084
2085        while (received != NULL) {
2086                next = received->m_nextpkt;
2087                received->m_nextpkt = NULL;
2088                ifp = received->m_pkthdr.rcvif;
2089                (*ifp->if_input)(ifp, received);
2090                if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
2091                received = next;
2092        }
2093}
2094
2095static void
2096cpsw_intr_misc_host_error(struct cpsw_softc *sc)
2097{
2098        uint32_t intstat;
2099        uint32_t dmastat;
2100        int txerr, rxerr, txchan, rxchan;
2101
2102        printf("\n\n");
2103        device_printf(sc->dev,
2104            "HOST ERROR:  PROGRAMMING ERROR DETECTED BY HARDWARE\n");
2105        printf("\n\n");
2106        intstat = cpsw_read_4(sc, CPSW_CPDMA_DMA_INTSTAT_MASKED);
2107        device_printf(sc->dev, "CPSW_CPDMA_DMA_INTSTAT_MASKED=0x%x\n", intstat);
2108        dmastat = cpsw_read_4(sc, CPSW_CPDMA_DMASTATUS);
2109        device_printf(sc->dev, "CPSW_CPDMA_DMASTATUS=0x%x\n", dmastat);
2110
2111        txerr = (dmastat >> 20) & 15;
2112        txchan = (dmastat >> 16) & 7;
2113        rxerr = (dmastat >> 12) & 15;
2114        rxchan = (dmastat >> 8) & 7;
2115
2116        switch (txerr) {
2117        case 0: break;
2118        case 1: printf("SOP error on TX channel %d\n", txchan);
2119                break;
2120        case 2: printf("Ownership bit not set on SOP buffer on TX channel %d\n", txchan);
2121                break;
2122        case 3: printf("Zero Next Buffer but not EOP on TX channel %d\n", txchan);
2123                break;
2124        case 4: printf("Zero Buffer Pointer on TX channel %d\n", txchan);
2125                break;
2126        case 5: printf("Zero Buffer Length on TX channel %d\n", txchan);
2127                break;
2128        case 6: printf("Packet length error on TX channel %d\n", txchan);
2129                break;
2130        default: printf("Unknown error on TX channel %d\n", txchan);
2131                break;
2132        }
2133
2134        if (txerr != 0) {
2135                printf("CPSW_CPDMA_TX%d_HDP=0x%x\n",
2136                    txchan, cpsw_read_4(sc, CPSW_CPDMA_TX_HDP(txchan)));
2137                printf("CPSW_CPDMA_TX%d_CP=0x%x\n",
2138                    txchan, cpsw_read_4(sc, CPSW_CPDMA_TX_CP(txchan)));
2139                cpsw_dump_queue(sc, &sc->tx.active);
2140        }
2141
2142        switch (rxerr) {
2143        case 0: break;
2144        case 2: printf("Ownership bit not set on RX channel %d\n", rxchan);
2145                break;
2146        case 4: printf("Zero Buffer Pointer on RX channel %d\n", rxchan);
2147                break;
2148        case 5: printf("Zero Buffer Length on RX channel %d\n", rxchan);
2149                break;
2150        case 6: printf("Buffer offset too big on RX channel %d\n", rxchan);
2151                break;
2152        default: printf("Unknown RX error on RX channel %d\n", rxchan);
2153                break;
2154        }
2155
2156        if (rxerr != 0) {
2157                printf("CPSW_CPDMA_RX%d_HDP=0x%x\n",
2158                    rxchan, cpsw_read_4(sc,CPSW_CPDMA_RX_HDP(rxchan)));
2159                printf("CPSW_CPDMA_RX%d_CP=0x%x\n",
2160                    rxchan, cpsw_read_4(sc, CPSW_CPDMA_RX_CP(rxchan)));
2161                cpsw_dump_queue(sc, &sc->rx.active);
2162        }
2163
2164        printf("\nALE Table\n");
2165        cpsw_ale_dump_table(sc);
2166
2167        // XXX do something useful here??
2168        panic("CPSW HOST ERROR INTERRUPT");
2169
2170        // Suppress this interrupt in the future.
2171        cpsw_write_4(sc, CPSW_CPDMA_DMA_INTMASK_CLEAR, intstat);
2172        printf("XXX HOST ERROR INTERRUPT SUPPRESSED\n");
2173        // The watchdog will probably reset the controller
2174        // in a little while.  It will probably fail again.
2175}
2176
2177static void
2178cpsw_intr_misc(void *arg)
2179{
2180        struct cpsw_softc *sc = arg;
2181        uint32_t stat = cpsw_read_4(sc, CPSW_WR_C_MISC_STAT(0));
2182
2183        if (stat & CPSW_WR_C_MISC_EVNT_PEND)
2184                CPSW_DEBUGF(sc, ("Time sync event interrupt unimplemented"));
2185        if (stat & CPSW_WR_C_MISC_STAT_PEND)
2186                cpsw_stats_collect(sc);
2187        if (stat & CPSW_WR_C_MISC_HOST_PEND)
2188                cpsw_intr_misc_host_error(sc);
2189        if (stat & CPSW_WR_C_MISC_MDIOLINK) {
2190                cpsw_write_4(sc, MDIOLINKINTMASKED,
2191                    cpsw_read_4(sc, MDIOLINKINTMASKED));
2192        }
2193        if (stat & CPSW_WR_C_MISC_MDIOUSER) {
2194                CPSW_DEBUGF(sc,
2195                    ("MDIO operation completed interrupt unimplemented"));
2196        }
2197        cpsw_write_4(sc, CPSW_CPDMA_CPDMA_EOI_VECTOR, 3);
2198}
2199
2200/*
2201 *
2202 * Periodic Checks and Watchdog.
2203 *
2204 */
2205
2206static void
2207cpswp_tick(void *msc)
2208{
2209        struct cpswp_softc *sc = msc;
2210
2211        /* Check for media type change */
2212        mii_tick(sc->mii);
2213        if (sc->media_status != sc->mii->mii_media.ifm_media) {
2214                printf("%s: media type changed (ifm_media=%x)\n", __func__, 
2215                        sc->mii->mii_media.ifm_media);
2216                cpswp_ifmedia_upd(sc->ifp);
2217        }
2218
2219        /* Schedule another timeout one second from now */
2220        callout_reset(&sc->mii_callout, hz, cpswp_tick, sc);
2221}
2222
2223static void
2224cpswp_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
2225{
2226        struct cpswp_softc *sc;
2227        struct mii_data *mii;
2228
2229        sc = ifp->if_softc;
2230        CPSW_DEBUGF(sc->swsc, (""));
2231        CPSW_PORT_LOCK(sc);
2232
2233        mii = sc->mii;
2234        mii_pollstat(mii);
2235
2236        ifmr->ifm_active = mii->mii_media_active;
2237        ifmr->ifm_status = mii->mii_media_status;
2238        CPSW_PORT_UNLOCK(sc);
2239}
2240
2241static int
2242cpswp_ifmedia_upd(struct ifnet *ifp)
2243{
2244        struct cpswp_softc *sc;
2245
2246        sc = ifp->if_softc;
2247        CPSW_DEBUGF(sc->swsc, (""));
2248        CPSW_PORT_LOCK(sc);
2249        mii_mediachg(sc->mii);
2250        sc->media_status = sc->mii->mii_media.ifm_media;
2251        CPSW_PORT_UNLOCK(sc);
2252
2253        return (0);
2254}
2255
2256static void
2257cpsw_tx_watchdog_full_reset(struct cpsw_softc *sc)
2258{
2259        struct cpswp_softc *psc;
2260        int i;
2261
2262        cpsw_debugf_head("CPSW watchdog");
2263        device_printf(sc->dev, "watchdog timeout\n");
2264        printf("CPSW_CPDMA_TX%d_HDP=0x%x\n", 0,
2265            cpsw_read_4(sc, CPSW_CPDMA_TX_HDP(0)));
2266        printf("CPSW_CPDMA_TX%d_CP=0x%x\n", 0,
2267            cpsw_read_4(sc, CPSW_CPDMA_TX_CP(0)));
2268        cpsw_dump_queue(sc, &sc->tx.active);
2269        for (i = 0; i < CPSW_PORTS; i++) {
2270                if (!sc->dualemac && i != sc->active_slave)
2271                        continue;
2272                psc = device_get_softc(sc->port[i].dev);
2273                CPSW_PORT_LOCK(psc);
2274                cpswp_stop_locked(psc);
2275                CPSW_PORT_UNLOCK(psc);
2276        }
2277}
2278
2279static void
2280cpsw_tx_watchdog(void *msc)
2281{
2282        struct cpsw_softc *sc;
2283
2284        sc = msc;
2285        CPSW_TX_LOCK(sc);
2286        if (sc->tx.active_queue_len == 0 || !sc->tx.running) {
2287                sc->watchdog.timer = 0; /* Nothing to do. */
2288        } else if (sc->tx.queue_removes > sc->tx.queue_removes_at_last_tick) {
2289                sc->watchdog.timer = 0;  /* Stuff done while we weren't looking. */
2290        } else if (cpsw_tx_dequeue(sc) > 0) {
2291                sc->watchdog.timer = 0;  /* We just did something. */
2292        } else {
2293                /* There was something to do but it didn't get done. */
2294                ++sc->watchdog.timer;
2295                if (sc->watchdog.timer > 5) {
2296                        sc->watchdog.timer = 0;
2297                        ++sc->watchdog.resets;
2298                        cpsw_tx_watchdog_full_reset(sc);
2299                }
2300        }
2301        sc->tx.queue_removes_at_last_tick = sc->tx.queue_removes;
2302        CPSW_TX_UNLOCK(sc);
2303
2304        /* Schedule another timeout one second from now */
2305        callout_reset(&sc->watchdog.callout, hz, cpsw_tx_watchdog, sc);
2306}
2307
2308/*
2309 *
2310 * ALE support routines.
2311 *
2312 */
2313
2314static void
2315cpsw_ale_read_entry(struct cpsw_softc *sc, uint16_t idx, uint32_t *ale_entry)
2316{
2317        cpsw_write_4(sc, CPSW_ALE_TBLCTL, idx & 1023);
2318        ale_entry[0] = cpsw_read_4(sc, CPSW_ALE_TBLW0);
2319        ale_entry[1] = cpsw_read_4(sc, CPSW_ALE_TBLW1);
2320        ale_entry[2] = cpsw_read_4(sc, CPSW_ALE_TBLW2);
2321}
2322
2323static void
2324cpsw_ale_write_entry(struct cpsw_softc *sc, uint16_t idx, uint32_t *ale_entry)
2325{
2326        cpsw_write_4(sc, CPSW_ALE_TBLW0, ale_entry[0]);
2327        cpsw_write_4(sc, CPSW_ALE_TBLW1, ale_entry[1]);
2328        cpsw_write_4(sc, CPSW_ALE_TBLW2, ale_entry[2]);
2329        cpsw_write_4(sc, CPSW_ALE_TBLCTL, 1 << 31 | (idx & 1023));
2330}
2331
2332static void
2333cpsw_ale_remove_all_mc_entries(struct cpsw_softc *sc)
2334{
2335        int i;
2336        uint32_t ale_entry[3];
2337
2338        /* First four entries are link address and broadcast. */
2339        for (i = 10; i < CPSW_MAX_ALE_ENTRIES; i++) {
2340                cpsw_ale_read_entry(sc, i, ale_entry);
2341                if ((ALE_TYPE(ale_entry) == ALE_TYPE_ADDR ||
2342                    ALE_TYPE(ale_entry) == ALE_TYPE_VLAN_ADDR) &&
2343                    ALE_MCAST(ale_entry)  == 1) { /* MCast link addr */
2344                        ale_entry[0] = ale_entry[1] = ale_entry[2] = 0;
2345                        cpsw_ale_write_entry(sc, i, ale_entry);
2346                }
2347        }
2348}
2349
2350static int
2351cpsw_ale_mc_entry_set(struct cpsw_softc *sc, uint8_t portmap, int vlan,
2352        uint8_t *mac)
2353{
2354        int free_index = -1, matching_index = -1, i;
2355        uint32_t ale_entry[3], ale_type;
2356
2357        /* Find a matching entry or a free entry. */
2358        for (i = 10; i < CPSW_MAX_ALE_ENTRIES; i++) {
2359                cpsw_ale_read_entry(sc, i, ale_entry);
2360
2361                /* Entry Type[61:60] is 0 for free entry */ 
2362                if (free_index < 0 && ALE_TYPE(ale_entry) == 0)
2363                        free_index = i;
2364
2365                if ((((ale_entry[1] >> 8) & 0xFF) == mac[0]) &&
2366                    (((ale_entry[1] >> 0) & 0xFF) == mac[1]) &&
2367                    (((ale_entry[0] >>24) & 0xFF) == mac[2]) &&
2368                    (((ale_entry[0] >>16) & 0xFF) == mac[3]) &&
2369                    (((ale_entry[0] >> 8) & 0xFF) == mac[4]) &&
2370                    (((ale_entry[0] >> 0) & 0xFF) == mac[5])) {
2371                        matching_index = i;
2372                        break;
2373                }
2374        }
2375
2376        if (matching_index < 0) {
2377                if (free_index < 0)
2378                        return (ENOMEM);
2379                i = free_index;
2380        }
2381
2382        if (vlan != -1)
2383                ale_type = ALE_TYPE_VLAN_ADDR << 28 | vlan << 16;
2384        else
2385                ale_type = ALE_TYPE_ADDR << 28;
2386
2387        /* Set MAC address */
2388        ale_entry[0] = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
2389        ale_entry[1] = mac[0] << 8 | mac[1];
2390
2391        /* Entry type[61:60] and Mcast fwd state[63:62] is fw(3). */
2392        ale_entry[1] |= ALE_MCAST_FWD | ale_type;
2393
2394        /* Set portmask [68:66] */
2395        ale_entry[2] = (portmap & 7) << 2;
2396
2397        cpsw_ale_write_entry(sc, i, ale_entry);
2398
2399        return 0;
2400}
2401
2402static void
2403cpsw_ale_dump_table(struct cpsw_softc *sc) {
2404        int i;
2405        uint32_t ale_entry[3];
2406        for (i = 0; i < CPSW_MAX_ALE_ENTRIES; i++) {
2407                cpsw_ale_read_entry(sc, i, ale_entry);
2408                switch (ALE_TYPE(ale_entry)) {
2409                case ALE_TYPE_VLAN:
2410                        printf("ALE[%4u] %08x %08x %08x ", i, ale_entry[2],
2411                                ale_entry[1], ale_entry[0]);
2412                        printf("type: %u ", ALE_TYPE(ale_entry));
2413                        printf("vlan: %u ", ALE_VLAN(ale_entry));
2414                        printf("untag: %u ", ALE_VLAN_UNTAG(ale_entry));
2415                        printf("reg flood: %u ", ALE_VLAN_REGFLOOD(ale_entry));
2416                        printf("unreg flood: %u ", ALE_VLAN_UNREGFLOOD(ale_entry));
2417                        printf("members: %u ", ALE_VLAN_MEMBERS(ale_entry));
2418                        printf("\n");
2419                        break;
2420                case ALE_TYPE_ADDR:
2421                case ALE_TYPE_VLAN_ADDR:
2422                        printf("ALE[%4u] %08x %08x %08x ", i, ale_entry[2],
2423                                ale_entry[1], ale_entry[0]);
2424                        printf("type: %u ", ALE_TYPE(ale_entry));
2425                        printf("mac: %02x:%02x:%02x:%02x:%02x:%02x ",
2426                                (ale_entry[1] >> 8) & 0xFF,
2427                                (ale_entry[1] >> 0) & 0xFF,
2428                                (ale_entry[0] >>24) & 0xFF,
2429                                (ale_entry[0] >>16) & 0xFF,
2430                                (ale_entry[0] >> 8) & 0xFF,
2431                                (ale_entry[0] >> 0) & 0xFF);
2432                        printf(ALE_MCAST(ale_entry) ? "mcast " : "ucast ");
2433                        if (ALE_TYPE(ale_entry) == ALE_TYPE_VLAN_ADDR)
2434                                printf("vlan: %u ", ALE_VLAN(ale_entry));
2435                        printf("port: %u ", ALE_PORTS(ale_entry));
2436                        printf("\n");
2437                        break;
2438                }
2439        }
2440        printf("\n");
2441}
2442
2443static int
2444cpswp_ale_update_addresses(struct cpswp_softc *sc, int purge)
2445{
2446        uint8_t *mac;
2447        uint32_t ale_entry[3], ale_type, portmask;
2448        struct ifmultiaddr *ifma;
2449
2450        if (sc->swsc->dualemac) {
2451                ale_type = ALE_TYPE_VLAN_ADDR << 28 | sc->vlan << 16;
2452                portmask = 1 << (sc->unit + 1) | 1 << 0;
2453        } else {
2454                ale_type = ALE_TYPE_ADDR << 28;
2455                portmask = 7;
2456        }
2457
2458        /*
2459         * Route incoming packets for our MAC address to Port 0 (host).
2460         * For simplicity, keep this entry at table index 0 for port 1 and
2461         * at index 2 for port 2 in the ALE.
2462         */
2463        if_addr_rlock(sc->ifp);
2464        mac = LLADDR((struct sockaddr_dl *)sc->ifp->if_addr->ifa_addr);
2465        ale_entry[0] = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
2466        ale_entry[1] = ale_type | mac[0] << 8 | mac[1]; /* addr entry + mac */
2467        ale_entry[2] = 0; /* port = 0 */
2468        cpsw_ale_write_entry(sc->swsc, 0 + 2 * sc->unit, ale_entry);
2469
2470        /* Set outgoing MAC Address for slave port. */
2471        cpsw_write_4(sc->swsc, CPSW_PORT_P_SA_HI(sc->unit + 1),
2472            mac[3] << 24 | mac[2] << 16 | mac[1] << 8 | mac[0]);
2473        cpsw_write_4(sc->swsc, CPSW_PORT_P_SA_LO(sc->unit + 1),
2474            mac[5] << 8 | mac[4]);
2475        if_addr_runlock(sc->ifp);
2476
2477        /* Keep the broadcast address at table entry 1 (or 3). */
2478        ale_entry[0] = 0xffffffff; /* Lower 32 bits of MAC */
2479        /* ALE_MCAST_FWD, Addr type, upper 16 bits of Mac */ 
2480        ale_entry[1] = ALE_MCAST_FWD | ale_type | 0xffff;
2481        ale_entry[2] = portmask << 2;
2482        cpsw_ale_write_entry(sc->swsc, 1 + 2 * sc->unit, ale_entry);
2483
2484        /* SIOCDELMULTI doesn't specify the particular address
2485           being removed, so we have to remove all and rebuild. */
2486        if (purge)
2487                cpsw_ale_remove_all_mc_entries(sc->swsc);
2488
2489        /* Set other multicast addrs desired. */
2490        if_maddr_rlock(sc->ifp);
2491        CK_STAILQ_FOREACH(ifma, &sc->ifp->if_multiaddrs, ifma_link) {
2492                if (ifma->ifma_addr->sa_family != AF_LINK)
2493                        continue;
2494                cpsw_ale_mc_entry_set(sc->swsc, portmask, sc->vlan,
2495                    LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
2496        }
2497        if_maddr_runlock(sc->ifp);
2498
2499        return (0);
2500}
2501
2502static int
2503cpsw_ale_update_vlan_table(struct cpsw_softc *sc, int vlan, int ports,
2504        int untag, int mcregflood, int mcunregflood)
2505{
2506        int free_index, i, matching_index;
2507        uint32_t ale_entry[3];
2508
2509        free_index = matching_index = -1;
2510        /* Find a matching entry or a free entry. */
2511        for (i = 5; i < CPSW_MAX_ALE_ENTRIES; i++) {
2512                cpsw_ale_read_entry(sc, i, ale_entry);
2513
2514                /* Entry Type[61:60] is 0 for free entry */ 
2515                if (free_index < 0 && ALE_TYPE(ale_entry) == 0)
2516                        free_index = i;
2517
2518                if (ALE_VLAN(ale_entry) == vlan) {
2519                        matching_index = i;
2520                        break;
2521                }
2522        }
2523
2524        if (matching_index < 0) {
2525                if (free_index < 0)
2526                        return (-1);
2527                i = free_index;
2528        }
2529
2530        ale_entry[0] = (untag & 7) << 24 | (mcregflood & 7) << 16 |
2531            (mcunregflood & 7) << 8 | (ports & 7);
2532        ale_entry[1] = ALE_TYPE_VLAN << 28 | vlan << 16;
2533        ale_entry[2] = 0;
2534        cpsw_ale_write_entry(sc, i, ale_entry);
2535
2536        return (0);
2537}
2538
2539/*
2540 *
2541 * Statistics and Sysctls.
2542 *
2543 */
2544
2545#if 0
2546static void
2547cpsw_stats_dump(struct cpsw_softc *sc)
2548{
2549        int i;
2550        uint32_t r;
2551
2552        for (i = 0; i < CPSW_SYSCTL_COUNT; ++i) {
2553                r = cpsw_read_4(sc, CPSW_STATS_OFFSET +
2554                    cpsw_stat_sysctls[i].reg);
2555                CPSW_DEBUGF(sc, ("%s: %ju + %u = %ju", cpsw_stat_sysctls[i].oid,
2556                    (intmax_t)sc->shadow_stats[i], r,
2557                    (intmax_t)sc->shadow_stats[i] + r));
2558        }
2559}
2560#endif
2561
2562static void
2563cpsw_stats_collect(struct cpsw_softc *sc)
2564{
2565        int i;
2566        uint32_t r;
2567
2568        CPSW_DEBUGF(sc, ("Controller shadow statistics updated."));
2569
2570        for (i = 0; i < CPSW_SYSCTL_COUNT; ++i) {
2571                r = cpsw_read_4(sc, CPSW_STATS_OFFSET +
2572                    cpsw_stat_sysctls[i].reg);
2573                sc->shadow_stats[i] += r;
2574                cpsw_write_4(sc, CPSW_STATS_OFFSET + cpsw_stat_sysctls[i].reg,
2575                    r);
2576        }
2577}
2578
2579static int
2580cpsw_stats_sysctl(SYSCTL_HANDLER_ARGS)
2581{
2582        struct cpsw_softc *sc;
2583        struct cpsw_stat *stat;
2584        uint64_t result;
2585
2586        sc = (struct cpsw_softc *)arg1;
2587        stat = &cpsw_stat_sysctls[oidp->oid_number];
2588        result = sc->shadow_stats[oidp->oid_number];
2589        result += cpsw_read_4(sc, CPSW_STATS_OFFSET + stat->reg);
2590        return (sysctl_handle_64(oidp, &result, 0, req));
2591}
2592
2593static int
2594cpsw_stat_attached(SYSCTL_HANDLER_ARGS)
2595{
2596        struct cpsw_softc *sc;
2597        struct bintime t;
2598        unsigned result;
2599
2600        sc = (struct cpsw_softc *)arg1;
2601        getbinuptime(&t);
2602        bintime_sub(&t, &sc->attach_uptime);
2603        result = t.sec;
2604        return (sysctl_handle_int(oidp, &result, 0, req));
2605}
2606
2607static int
2608cpsw_intr_coalesce(SYSCTL_HANDLER_ARGS)
2609{
2610        int error;
2611        struct cpsw_softc *sc;
2612        uint32_t ctrl, intr_per_ms;
2613
2614        sc = (struct cpsw_softc *)arg1;
2615        error = sysctl_handle_int(oidp, &sc->coal_us, 0, req);
2616        if (error != 0 || req->newptr == NULL)
2617                return (error);
2618
2619        ctrl = cpsw_read_4(sc, CPSW_WR_INT_CONTROL);
2620        ctrl &= ~(CPSW_WR_INT_PACE_EN | CPSW_WR_INT_PRESCALE_MASK);
2621        if (sc->coal_us == 0) {
2622                /* Disable the interrupt pace hardware. */
2623                cpsw_write_4(sc, CPSW_WR_INT_CONTROL, ctrl);
2624                cpsw_write_4(sc, CPSW_WR_C_RX_IMAX(0), 0);
2625                cpsw_write_4(sc, CPSW_WR_C_TX_IMAX(0), 0);
2626                return (0);
2627        }
2628
2629        if (sc->coal_us > CPSW_WR_C_IMAX_US_MAX)
2630                sc->coal_us = CPSW_WR_C_IMAX_US_MAX;
2631        if (sc->coal_us < CPSW_WR_C_IMAX_US_MIN)
2632                sc->coal_us = CPSW_WR_C_IMAX_US_MIN;
2633        intr_per_ms = 1000 / sc->coal_us;
2634        /* Just to make sure... */
2635        if (intr_per_ms > CPSW_WR_C_IMAX_MAX)
2636                intr_per_ms = CPSW_WR_C_IMAX_MAX;
2637        if (intr_per_ms < CPSW_WR_C_IMAX_MIN)
2638                intr_per_ms = CPSW_WR_C_IMAX_MIN;
2639
2640        /* Set the prescale to produce 4us pulses from the 125 Mhz clock. */
2641        ctrl |= (125 * 4) & CPSW_WR_INT_PRESCALE_MASK;
2642
2643        /* Enable the interrupt pace hardware. */
2644        cpsw_write_4(sc, CPSW_WR_C_RX_IMAX(0), intr_per_ms);
2645        cpsw_write_4(sc, CPSW_WR_C_TX_IMAX(0), intr_per_ms);
2646        ctrl |= CPSW_WR_INT_C0_RX_PULSE | CPSW_WR_INT_C0_TX_PULSE;
2647        cpsw_write_4(sc, CPSW_WR_INT_CONTROL, ctrl);
2648
2649        return (0);
2650}
2651
2652static int
2653cpsw_stat_uptime(SYSCTL_HANDLER_ARGS)
2654{
2655        struct cpsw_softc *swsc;
2656        struct cpswp_softc *sc;
2657        struct bintime t;
2658        unsigned result;
2659
2660        swsc = arg1;
2661        sc = device_get_softc(swsc->port[arg2].dev);
2662        if (sc->ifp->if_drv_flags & IFF_DRV_RUNNING) {
2663                getbinuptime(&t);
2664                bintime_sub(&t, &sc->init_uptime);
2665                result = t.sec;
2666        } else
2667                result = 0;
2668        return (sysctl_handle_int(oidp, &result, 0, req));
2669}
2670
2671static void
2672cpsw_add_queue_sysctls(struct sysctl_ctx_list *ctx, struct sysctl_oid *node,
2673        struct cpsw_queue *queue)
2674{
2675        struct sysctl_oid_list *parent;
2676
2677        parent = SYSCTL_CHILDREN(node);
2678        SYSCTL_ADD_INT(ctx, parent, OID_AUTO, "totalBuffers",
2679            CTLFLAG_RD, &queue->queue_slots, 0,
2680            "Total buffers currently assigned to this queue");
2681        SYSCTL_ADD_INT(ctx, parent, OID_AUTO, "activeBuffers",
2682            CTLFLAG_RD, &queue->active_queue_len, 0,
2683            "Buffers currently registered with hardware controller");
2684        SYSCTL_ADD_INT(ctx, parent, OID_AUTO, "maxActiveBuffers",
2685            CTLFLAG_RD, &queue->max_active_queue_len, 0,
2686            "Max value of activeBuffers since last driver reset");
2687        SYSCTL_ADD_INT(ctx, parent, OID_AUTO, "availBuffers",
2688            CTLFLAG_RD, &queue->avail_queue_len, 0,
2689            "Buffers allocated to this queue but not currently "
2690            "registered with hardware controller");
2691        SYSCTL_ADD_INT(ctx, parent, OID_AUTO, "maxAvailBuffers",
2692            CTLFLAG_RD, &queue->max_avail_queue_len, 0,
2693            "Max value of availBuffers since last driver reset");
2694        SYSCTL_ADD_UINT(ctx, parent, OID_AUTO, "totalEnqueued",
2695            CTLFLAG_RD, &queue->queue_adds, 0,
2696            "Total buffers added to queue");
2697        SYSCTL_ADD_UINT(ctx, parent, OID_AUTO, "totalDequeued",
2698            CTLFLAG_RD, &queue->queue_removes, 0,
2699            "Total buffers removed from queue");
2700        SYSCTL_ADD_UINT(ctx, parent, OID_AUTO, "queueRestart",
2701            CTLFLAG_RD, &queue->queue_restart, 0,
2702            "Total times the queue has been restarted");
2703        SYSCTL_ADD_UINT(ctx, parent, OID_AUTO, "longestChain",
2704            CTLFLAG_RD, &queue->longest_chain, 0,
2705            "Max buffers used for a single packet");
2706}
2707
2708static void
2709cpsw_add_watchdog_sysctls(struct sysctl_ctx_list *ctx, struct sysctl_oid *node,
2710        struct cpsw_softc *sc)
2711{
2712        struct sysctl_oid_list *parent;
2713
2714        parent = SYSCTL_CHILDREN(node);
2715        SYSCTL_ADD_INT(ctx, parent, OID_AUTO, "resets",
2716            CTLFLAG_RD, &sc->watchdog.resets, 0,
2717            "Total number of watchdog resets");
2718}
2719
2720static void
2721cpsw_add_sysctls(struct cpsw_softc *sc)
2722{
2723        struct sysctl_ctx_list *ctx;
2724        struct sysctl_oid *stats_node, *queue_node, *node;
2725        struct sysctl_oid_list *parent, *stats_parent, *queue_parent;
2726        struct sysctl_oid_list *ports_parent, *port_parent;
2727        char port[16];
2728        int i;
2729
2730        ctx = device_get_sysctl_ctx(sc->dev);
2731        parent = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev));
2732
2733        SYSCTL_ADD_INT(ctx, parent, OID_AUTO, "debug",
2734            CTLFLAG_RW, &sc->debug, 0, "Enable switch debug messages");
2735
2736        SYSCTL_ADD_PROC(ctx, parent, OID_AUTO, "attachedSecs",
2737            CTLTYPE_UINT | CTLFLAG_RD, sc, 0, cpsw_stat_attached, "IU",
2738            "Time since driver attach");
2739
2740        SYSCTL_ADD_PROC(ctx, parent, OID_AUTO, "intr_coalesce_us",
2741            CTLTYPE_UINT | CTLFLAG_RW, sc, 0, cpsw_intr_coalesce, "IU",
2742            "minimum time between interrupts");
2743
2744        node = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "ports",
2745            CTLFLAG_RD, NULL, "CPSW Ports Statistics");
2746        ports_parent = SYSCTL_CHILDREN(node);
2747        for (i = 0; i < CPSW_PORTS; i++) {
2748                if (!sc->dualemac && i != sc->active_slave)
2749                        continue;
2750                port[0] = '0' + i;
2751                port[1] = '\0';
2752                node = SYSCTL_ADD_NODE(ctx, ports_parent, OID_AUTO,
2753                    port, CTLFLAG_RD, NULL, "CPSW Port Statistics");
2754                port_parent = SYSCTL_CHILDREN(node);
2755                SYSCTL_ADD_PROC(ctx, port_parent, OID_AUTO, "uptime",
2756                    CTLTYPE_UINT | CTLFLAG_RD, sc, i,
2757                    cpsw_stat_uptime, "IU", "Seconds since driver init");
2758        }
2759
2760        stats_node = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "stats",
2761                                     CTLFLAG_RD, NULL, "CPSW Statistics");
2762        stats_parent = SYSCTL_CHILDREN(stats_node);
2763        for (i = 0; i < CPSW_SYSCTL_COUNT; ++i) {
2764                SYSCTL_ADD_PROC(ctx, stats_parent, i,
2765                                cpsw_stat_sysctls[i].oid,
2766                                CTLTYPE_U64 | CTLFLAG_RD, sc, 0,
2767                                cpsw_stats_sysctl, "IU",
2768                                cpsw_stat_sysctls[i].oid);
2769        }
2770
2771        queue_node = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "queue",
2772            CTLFLAG_RD, NULL, "CPSW Queue Statistics");
2773        queue_parent = SYSCTL_CHILDREN(queue_node);
2774
2775        node = SYSCTL_ADD_NODE(ctx, queue_parent, OID_AUTO, "tx",
2776            CTLFLAG_RD, NULL, "TX Queue Statistics");
2777        cpsw_add_queue_sysctls(ctx, node, &sc->tx);
2778
2779        node = SYSCTL_ADD_NODE(ctx, queue_parent, OID_AUTO, "rx",
2780            CTLFLAG_RD, NULL, "RX Queue Statistics");
2781        cpsw_add_queue_sysctls(ctx, node, &sc->rx);
2782
2783        node = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "watchdog",
2784            CTLFLAG_RD, NULL, "Watchdog Statistics");
2785        cpsw_add_watchdog_sysctls(ctx, node, sc);
2786}
2787
2788#ifdef CPSW_ETHERSWITCH
2789static etherswitch_info_t etherswitch_info = {
2790        .es_nports =            CPSW_PORTS + 1,
2791        .es_nvlangroups =       CPSW_VLANS,
2792        .es_name =              "TI Common Platform Ethernet Switch (CPSW)",
2793        .es_vlan_caps =         ETHERSWITCH_VLAN_DOT1Q,
2794};
2795
2796static etherswitch_info_t *
2797cpsw_getinfo(device_t dev)
2798{
2799        return (&etherswitch_info);
2800}
2801
2802static int
2803cpsw_getport(device_t dev, etherswitch_port_t *p)
2804{
2805        int err;
2806        struct cpsw_softc *sc;
2807        struct cpswp_softc *psc;
2808        struct ifmediareq *ifmr;
2809        uint32_t reg;
2810
2811        if (p->es_port < 0 || p->es_port > CPSW_PORTS)
2812                return (ENXIO);
2813
2814        err = 0;
2815        sc = device_get_softc(dev);
2816        if (p->es_port == CPSW_CPU_PORT) {
2817                p->es_flags |= ETHERSWITCH_PORT_CPU;
2818                ifmr = &p->es_ifmr;
2819                ifmr->ifm_current = ifmr->ifm_active =
2820                    IFM_ETHER | IFM_1000_T | IFM_FDX;
2821                ifmr->ifm_mask = 0;
2822                ifmr->ifm_status = IFM_ACTIVE | IFM_AVALID;
2823                ifmr->ifm_count = 0;
2824        } else {
2825                psc = device_get_softc(sc->port[p->es_port - 1].dev);
2826                err = ifmedia_ioctl(psc->ifp, &p->es_ifr,
2827                    &psc->mii->mii_media, SIOCGIFMEDIA);
2828        }
2829        reg = cpsw_read_4(sc, CPSW_PORT_P_VLAN(p->es_port));
2830        p->es_pvid = reg & ETHERSWITCH_VID_MASK;
2831
2832        reg = cpsw_read_4(sc, CPSW_ALE_PORTCTL(p->es_port));
2833        if (reg & ALE_PORTCTL_DROP_UNTAGGED)
2834                p->es_flags |= ETHERSWITCH_PORT_DROPUNTAGGED;
2835        if (reg & ALE_PORTCTL_INGRESS)
2836                p->es_flags |= ETHERSWITCH_PORT_INGRESS;
2837
2838        return (err);
2839}
2840
2841static int
2842cpsw_setport(device_t dev, etherswitch_port_t *p)
2843{
2844        struct cpsw_softc *sc;
2845        struct cpswp_softc *psc;
2846        struct ifmedia *ifm;
2847        uint32_t reg;
2848
2849        if (p->es_port < 0 || p->es_port > CPSW_PORTS)
2850                return (ENXIO);
2851
2852        sc = device_get_softc(dev);
2853        if (p->es_pvid != 0) {
2854                cpsw_write_4(sc, CPSW_PORT_P_VLAN(p->es_port),
2855                    p->es_pvid & ETHERSWITCH_VID_MASK);
2856        }
2857
2858        reg = cpsw_read_4(sc, CPSW_ALE_PORTCTL(p->es_port));
2859        if (p->es_flags & ETHERSWITCH_PORT_DROPUNTAGGED)
2860                reg |= ALE_PORTCTL_DROP_UNTAGGED;
2861        else
2862                reg &= ~ALE_PORTCTL_DROP_UNTAGGED;
2863        if (p->es_flags & ETHERSWITCH_PORT_INGRESS)
2864                reg |= ALE_PORTCTL_INGRESS;
2865        else
2866                reg &= ~ALE_PORTCTL_INGRESS;
2867        cpsw_write_4(sc, CPSW_ALE_PORTCTL(p->es_port), reg);
2868
2869        /* CPU port does not allow media settings. */
2870        if (p->es_port == CPSW_CPU_PORT)
2871                return (0);
2872
2873        psc = device_get_softc(sc->port[p->es_port - 1].dev);
2874        ifm = &psc->mii->mii_media;
2875
2876        return (ifmedia_ioctl(psc->ifp, &p->es_ifr, ifm, SIOCSIFMEDIA));
2877}
2878
2879static int
2880cpsw_getconf(device_t dev, etherswitch_conf_t *conf)
2881{
2882
2883        /* Return the VLAN mode. */
2884        conf->cmd = ETHERSWITCH_CONF_VLAN_MODE;
2885        conf->vlan_mode = ETHERSWITCH_VLAN_DOT1Q;
2886
2887        return (0);
2888}
2889
2890static int
2891cpsw_getvgroup(device_t dev, etherswitch_vlangroup_t *vg)
2892{
2893        int i, vid;
2894        uint32_t ale_entry[3];
2895        struct cpsw_softc *sc;
2896
2897        sc = device_get_softc(dev);
2898
2899        if (vg->es_vlangroup >= CPSW_VLANS)
2900                return (EINVAL);
2901
2902        vg->es_vid = 0;
2903        vid = cpsw_vgroups[vg->es_vlangroup].vid;
2904        if (vid == -1)
2905                return (0);
2906
2907        for (i = 0; i < CPSW_MAX_ALE_ENTRIES; i++) {
2908                cpsw_ale_read_entry(sc, i, ale_entry);
2909                if (ALE_TYPE(ale_entry) != ALE_TYPE_VLAN)
2910                        continue;
2911                if (vid != ALE_VLAN(ale_entry))
2912                        continue;
2913
2914                vg->es_fid = 0;
2915                vg->es_vid = ALE_VLAN(ale_entry) | ETHERSWITCH_VID_VALID;
2916                vg->es_member_ports = ALE_VLAN_MEMBERS(ale_entry);
2917                vg->es_untagged_ports = ALE_VLAN_UNTAG(ale_entry);
2918        }
2919
2920        return (0);
2921}
2922
2923static void
2924cpsw_remove_vlan(struct cpsw_softc *sc, int vlan)
2925{
2926        int i;
2927        uint32_t ale_entry[3];
2928
2929        for (i = 0; i < CPSW_MAX_ALE_ENTRIES; i++) {
2930                cpsw_ale_read_entry(sc, i, ale_entry);
2931                if (ALE_TYPE(ale_entry) != ALE_TYPE_VLAN)
2932                        continue;
2933                if (vlan != ALE_VLAN(ale_entry))
2934                        continue;
2935                ale_entry[0] = ale_entry[1] = ale_entry[2] = 0;
2936                cpsw_ale_write_entry(sc, i, ale_entry);
2937                break;
2938        }
2939}
2940
2941static int
2942cpsw_setvgroup(device_t dev, etherswitch_vlangroup_t *vg)
2943{
2944        int i;
2945        struct cpsw_softc *sc;
2946
2947        sc = device_get_softc(dev);
2948
2949        for (i = 0; i < CPSW_VLANS; i++) {
2950                /* Is this Vlan ID in use by another vlangroup ? */
2951                if (vg->es_vlangroup != i && cpsw_vgroups[i].vid == vg->es_vid)
2952                        return (EINVAL);
2953        }
2954
2955        if (vg->es_vid == 0) {
2956                if (cpsw_vgroups[vg->es_vlangroup].vid == -1)
2957                        return (0);
2958                cpsw_remove_vlan(sc, cpsw_vgroups[vg->es_vlangroup].vid);
2959                cpsw_vgroups[vg->es_vlangroup].vid = -1;
2960                vg->es_untagged_ports = 0;
2961                vg->es_member_ports = 0;
2962                vg->es_vid = 0;
2963                return (0);
2964        }
2965
2966        vg->es_vid &= ETHERSWITCH_VID_MASK;
2967        vg->es_member_ports &= CPSW_PORTS_MASK;
2968        vg->es_untagged_ports &= CPSW_PORTS_MASK;
2969
2970        if (cpsw_vgroups[vg->es_vlangroup].vid != -1 &&
2971            cpsw_vgroups[vg->es_vlangroup].vid != vg->es_vid)
2972                return (EINVAL);
2973
2974        cpsw_vgroups[vg->es_vlangroup].vid = vg->es_vid;
2975        cpsw_ale_update_vlan_table(sc, vg->es_vid, vg->es_member_ports,
2976            vg->es_untagged_ports, vg->es_member_ports, 0);
2977
2978        return (0);
2979}
2980
2981static int
2982cpsw_readreg(device_t dev, int addr)
2983{
2984
2985        /* Not supported. */
2986        return (0);
2987}
2988
2989static int
2990cpsw_writereg(device_t dev, int addr, int value)
2991{
2992
2993        /* Not supported. */
2994        return (0);
2995}
2996
2997static int
2998cpsw_readphy(device_t dev, int phy, int reg)
2999{
3000
3001        /* Not supported. */
3002        return (0);
3003}
3004
3005static int
3006cpsw_writephy(device_t dev, int phy, int reg, int data)
3007{
3008
3009        /* Not supported. */
3010        return (0);
3011}
3012#endif
Note: See TracBrowser for help on using the repository browser.