xref: /freebsd/sys/dev/etherswitch/e6000sw/e6000sw.c (revision 22cf89c938886d14f5796fc49f9f020c23ea8eaf)
1 /*-
2  * Copyright (c) 2015 Semihalf
3  * Copyright (c) 2015 Stormshield
4  * Copyright (c) 2018-2019, Rubicon Communications, LLC (Netgate)
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <sys/cdefs.h>
30 #include "opt_platform.h"
31 
32 #include <sys/param.h>
33 #include <sys/bus.h>
34 #include <sys/errno.h>
35 #include <sys/kernel.h>
36 #include <sys/kthread.h>
37 #include <sys/module.h>
38 #include <sys/taskqueue.h>
39 #include <sys/socket.h>
40 #include <sys/sockio.h>
41 
42 #include <net/if.h>
43 #include <net/if_media.h>
44 #include <net/if_types.h>
45 
46 #include <dev/etherswitch/etherswitch.h>
47 #include <dev/mii/mii.h>
48 #include <dev/mii/miivar.h>
49 
50 #ifdef FDT
51 #include <dev/ofw/ofw_bus.h>
52 #include <dev/ofw/ofw_bus_subr.h>
53 #else
54 #include <machine/stdarg.h>
55 #endif
56 
57 #include "e6000swreg.h"
58 #include "etherswitch_if.h"
59 #include "miibus_if.h"
60 #include "mdio_if.h"
61 
62 MALLOC_DECLARE(M_E6000SW);
63 MALLOC_DEFINE(M_E6000SW, "e6000sw", "e6000sw switch");
64 
65 #define	E6000SW_LOCK(_sc)		sx_xlock(&(_sc)->sx)
66 #define	E6000SW_UNLOCK(_sc)		sx_unlock(&(_sc)->sx)
67 #define	E6000SW_LOCK_ASSERT(_sc, _what)	sx_assert(&(_sc)->sx, (_what))
68 #define	E6000SW_TRYLOCK(_sc)		sx_tryxlock(&(_sc)->sx)
69 #define	E6000SW_WAITREADY(_sc, _reg, _bit)				\
70     e6000sw_waitready((_sc), REG_GLOBAL, (_reg), (_bit))
71 #define	E6000SW_WAITREADY2(_sc, _reg, _bit)				\
72     e6000sw_waitready((_sc), REG_GLOBAL2, (_reg), (_bit))
73 #define	MDIO_READ(dev, addr, reg)					\
74     MDIO_READREG(device_get_parent(dev), (addr), (reg))
75 #define	MDIO_WRITE(dev, addr, reg, val)					\
76     MDIO_WRITEREG(device_get_parent(dev), (addr), (reg), (val))
77 
78 
79 typedef struct e6000sw_softc {
80 	device_t		dev;
81 #ifdef FDT
82 	phandle_t		node;
83 #endif
84 
85 	struct sx		sx;
86 	if_t ifp[E6000SW_MAX_PORTS];
87 	char			*ifname[E6000SW_MAX_PORTS];
88 	device_t		miibus[E6000SW_MAX_PORTS];
89 	struct taskqueue	*sc_tq;
90 	struct timeout_task	sc_tt;
91 
92 	int			vlans[E6000SW_NUM_VLANS];
93 	uint32_t		swid;
94 	uint32_t		vlan_mode;
95 	uint32_t		cpuports_mask;
96 	uint32_t		fixed_mask;
97 	uint32_t		fixed25_mask;
98 	uint32_t		ports_mask;
99 	int			phy_base;
100 	int			sw_addr;
101 	int			num_ports;
102 } e6000sw_softc_t;
103 
104 static etherswitch_info_t etherswitch_info = {
105 	.es_nports =		0,
106 	.es_nvlangroups =	0,
107 	.es_vlan_caps =		ETHERSWITCH_VLAN_PORT | ETHERSWITCH_VLAN_DOT1Q,
108 	.es_name =		"Marvell 6000 series switch"
109 };
110 
111 static void e6000sw_identify(driver_t *, device_t);
112 static int e6000sw_probe(device_t);
113 #ifdef FDT
114 static int e6000sw_parse_fixed_link(e6000sw_softc_t *, phandle_t, uint32_t);
115 static int e6000sw_parse_ethernet(e6000sw_softc_t *, phandle_t, uint32_t);
116 #endif
117 static int e6000sw_attach(device_t);
118 static int e6000sw_detach(device_t);
119 static int e6000sw_read_xmdio(device_t, int, int, int);
120 static int e6000sw_write_xmdio(device_t, int, int, int, int);
121 static int e6000sw_readphy(device_t, int, int);
122 static int e6000sw_writephy(device_t, int, int, int);
123 static int e6000sw_readphy_locked(device_t, int, int);
124 static int e6000sw_writephy_locked(device_t, int, int, int);
125 static etherswitch_info_t* e6000sw_getinfo(device_t);
126 static int e6000sw_getconf(device_t, etherswitch_conf_t *);
127 static int e6000sw_setconf(device_t, etherswitch_conf_t *);
128 static void e6000sw_lock(device_t);
129 static void e6000sw_unlock(device_t);
130 static int e6000sw_getport(device_t, etherswitch_port_t *);
131 static int e6000sw_setport(device_t, etherswitch_port_t *);
132 static int e6000sw_set_vlan_mode(e6000sw_softc_t *, uint32_t);
133 static int e6000sw_readreg_wrapper(device_t, int);
134 static int e6000sw_writereg_wrapper(device_t, int, int);
135 static int e6000sw_getvgroup_wrapper(device_t, etherswitch_vlangroup_t *);
136 static int e6000sw_setvgroup_wrapper(device_t, etherswitch_vlangroup_t *);
137 static int e6000sw_setvgroup(device_t, etherswitch_vlangroup_t *);
138 static int e6000sw_getvgroup(device_t, etherswitch_vlangroup_t *);
139 static void e6000sw_setup(device_t, e6000sw_softc_t *);
140 static void e6000sw_tick(void *, int);
141 static void e6000sw_set_atustat(device_t, e6000sw_softc_t *, int, int);
142 static int e6000sw_atu_flush(device_t, e6000sw_softc_t *, int);
143 static int e6000sw_vtu_flush(e6000sw_softc_t *);
144 static int e6000sw_vtu_update(e6000sw_softc_t *, int, int, int, int, int);
145 static __inline void e6000sw_writereg(e6000sw_softc_t *, int, int, int);
146 static __inline uint32_t e6000sw_readreg(e6000sw_softc_t *, int, int);
147 static int e6000sw_ifmedia_upd(if_t);
148 static void e6000sw_ifmedia_sts(if_t, struct ifmediareq *);
149 static int e6000sw_atu_mac_table(device_t, e6000sw_softc_t *, struct atu_opt *,
150     int);
151 static int e6000sw_get_pvid(e6000sw_softc_t *, int, int *);
152 static void e6000sw_set_pvid(e6000sw_softc_t *, int, int);
153 static __inline bool e6000sw_is_cpuport(e6000sw_softc_t *, int);
154 static __inline bool e6000sw_is_fixedport(e6000sw_softc_t *, int);
155 static __inline bool e6000sw_is_fixed25port(e6000sw_softc_t *, int);
156 static __inline bool e6000sw_is_phyport(e6000sw_softc_t *, int);
157 static __inline bool e6000sw_is_portenabled(e6000sw_softc_t *, int);
158 static __inline struct mii_data *e6000sw_miiforphy(e6000sw_softc_t *,
159     unsigned int);
160 
161 static device_method_t e6000sw_methods[] = {
162 	/* device interface */
163 	DEVMETHOD(device_identify,		e6000sw_identify),
164 	DEVMETHOD(device_probe,			e6000sw_probe),
165 	DEVMETHOD(device_attach,		e6000sw_attach),
166 	DEVMETHOD(device_detach,		e6000sw_detach),
167 
168 	/* bus interface */
169 	DEVMETHOD(bus_add_child,		device_add_child_ordered),
170 
171 	/* mii interface */
172 	DEVMETHOD(miibus_readreg,		e6000sw_readphy_locked),
173 	DEVMETHOD(miibus_writereg,		e6000sw_writephy_locked),
174 
175 	/* etherswitch interface */
176 	DEVMETHOD(etherswitch_getinfo,		e6000sw_getinfo),
177 	DEVMETHOD(etherswitch_getconf,		e6000sw_getconf),
178 	DEVMETHOD(etherswitch_setconf,		e6000sw_setconf),
179 	DEVMETHOD(etherswitch_lock,		e6000sw_lock),
180 	DEVMETHOD(etherswitch_unlock,		e6000sw_unlock),
181 	DEVMETHOD(etherswitch_getport,		e6000sw_getport),
182 	DEVMETHOD(etherswitch_setport,		e6000sw_setport),
183 	DEVMETHOD(etherswitch_readreg,		e6000sw_readreg_wrapper),
184 	DEVMETHOD(etherswitch_writereg,		e6000sw_writereg_wrapper),
185 	DEVMETHOD(etherswitch_readphyreg,	e6000sw_readphy),
186 	DEVMETHOD(etherswitch_writephyreg,	e6000sw_writephy),
187 	DEVMETHOD(etherswitch_setvgroup,	e6000sw_setvgroup_wrapper),
188 	DEVMETHOD(etherswitch_getvgroup,	e6000sw_getvgroup_wrapper),
189 
190 	DEVMETHOD_END
191 };
192 
193 DEFINE_CLASS_0(e6000sw, e6000sw_driver, e6000sw_methods,
194     sizeof(e6000sw_softc_t));
195 
196 DRIVER_MODULE(e6000sw, mdio, e6000sw_driver, 0, 0);
197 DRIVER_MODULE(etherswitch, e6000sw, etherswitch_driver, 0, 0);
198 DRIVER_MODULE(miibus, e6000sw, miibus_driver, 0, 0);
199 MODULE_DEPEND(e6000sw, mdio, 1, 1, 1);
200 
201 
202 static void
203 e6000sw_identify(driver_t *driver, device_t parent)
204 {
205 
206 	if (device_find_child(parent, "e6000sw", -1) == NULL)
207 		BUS_ADD_CHILD(parent, 0, "e6000sw", -1);
208 }
209 
210 static int
211 e6000sw_probe(device_t dev)
212 {
213 	e6000sw_softc_t *sc;
214 	const char *description;
215 #ifdef FDT
216 	phandle_t switch_node;
217 #else
218 	int is_6190;
219 #endif
220 
221 	sc = device_get_softc(dev);
222 	sc->dev = dev;
223 
224 #ifdef FDT
225 	switch_node = ofw_bus_find_compatible(OF_finddevice("/"),
226 	    "marvell,mv88e6085");
227 	if (switch_node == 0) {
228 		switch_node = ofw_bus_find_compatible(OF_finddevice("/"),
229 		    "marvell,mv88e6190");
230 
231 		if (switch_node == 0)
232 			return (ENXIO);
233 
234 		/*
235 		 * Trust DTS and fix the port register offset for the MV88E6190
236 		 * detection bellow.
237 		 */
238 		sc->swid = MV88E6190;
239 	}
240 
241 	if (bootverbose)
242 		device_printf(dev, "Found switch_node: 0x%x\n", switch_node);
243 
244 	sc->node = switch_node;
245 
246 	if (OF_getencprop(sc->node, "reg", &sc->sw_addr,
247 	    sizeof(sc->sw_addr)) < 0)
248 		return (ENXIO);
249 #else
250 	if (resource_int_value(device_get_name(sc->dev),
251 	    device_get_unit(sc->dev), "addr", &sc->sw_addr) != 0)
252 		return (ENXIO);
253 	if (resource_int_value(device_get_name(sc->dev),
254 	    device_get_unit(sc->dev), "is6190", &is_6190) != 0)
255 		/*
256 		 * Check "is8190" to keep backward compatibility with
257 		 * older setups.
258 		 */
259 		resource_int_value(device_get_name(sc->dev),
260 		    device_get_unit(sc->dev), "is8190", &is_6190);
261 	if (is_6190 != 0)
262 		sc->swid = MV88E6190;
263 #endif
264 	if (sc->sw_addr < 0 || sc->sw_addr > 32)
265 		return (ENXIO);
266 
267 	/*
268 	 * Create temporary lock, just to satisfy assertions,
269 	 * when obtaining the switch ID. Destroy immediately afterwards.
270 	 */
271 	sx_init(&sc->sx, "e6000sw_tmp");
272 	E6000SW_LOCK(sc);
273 	sc->swid = e6000sw_readreg(sc, REG_PORT(sc, 0), SWITCH_ID) & 0xfff0;
274 	E6000SW_UNLOCK(sc);
275 	sx_destroy(&sc->sx);
276 
277 	switch (sc->swid) {
278 	case MV88E6141:
279 		description = "Marvell 88E6141";
280 		sc->phy_base = 0x10;
281 		sc->num_ports = 6;
282 		break;
283 	case MV88E6341:
284 		description = "Marvell 88E6341";
285 		sc->phy_base = 0x10;
286 		sc->num_ports = 6;
287 		break;
288 	case MV88E6352:
289 		description = "Marvell 88E6352";
290 		sc->num_ports = 7;
291 		break;
292 	case MV88E6172:
293 		description = "Marvell 88E6172";
294 		sc->num_ports = 7;
295 		break;
296 	case MV88E6176:
297 		description = "Marvell 88E6176";
298 		sc->num_ports = 7;
299 		break;
300 	case MV88E6190:
301 		description = "Marvell 88E6190";
302 		sc->num_ports = 11;
303 		break;
304 	default:
305 		device_printf(dev, "Unrecognized device, id 0x%x.\n", sc->swid);
306 		return (ENXIO);
307 	}
308 
309 	device_set_desc(dev, description);
310 
311 	return (BUS_PROBE_DEFAULT);
312 }
313 
314 #ifdef FDT
315 static int
316 e6000sw_parse_fixed_link(e6000sw_softc_t *sc, phandle_t node, uint32_t port)
317 {
318 	int speed;
319 	phandle_t fixed_link;
320 
321 	fixed_link = ofw_bus_find_child(node, "fixed-link");
322 
323 	if (fixed_link != 0) {
324 		sc->fixed_mask |= (1 << port);
325 
326 		if (OF_getencprop(fixed_link,
327 		    "speed", &speed, sizeof(speed)) < 0) {
328 			device_printf(sc->dev,
329 			    "Port %d has a fixed-link node without a speed "
330 			    "property\n", port);
331 			return (ENXIO);
332 		}
333 		if (speed == 2500 && (MVSWITCH(sc, MV88E6141) ||
334 		     MVSWITCH(sc, MV88E6341) || MVSWITCH(sc, MV88E6190)))
335 			sc->fixed25_mask |= (1 << port);
336 	}
337 
338 	return (0);
339 }
340 
341 static int
342 e6000sw_parse_ethernet(e6000sw_softc_t *sc, phandle_t port_handle, uint32_t port) {
343 	phandle_t switch_eth, switch_eth_handle;
344 
345 	if (OF_getencprop(port_handle, "ethernet", (void*)&switch_eth_handle,
346 	    sizeof(switch_eth_handle)) > 0) {
347 		if (switch_eth_handle > 0) {
348 			switch_eth = OF_node_from_xref(switch_eth_handle);
349 
350 			device_printf(sc->dev, "CPU port at %d\n", port);
351 			sc->cpuports_mask |= (1 << port);
352 
353 			return (e6000sw_parse_fixed_link(sc, switch_eth, port));
354 		} else
355 			device_printf(sc->dev,
356 				"Port %d has ethernet property but it points "
357 				"to an invalid location\n", port);
358 	}
359 
360 	return (0);
361 }
362 
363 static int
364 e6000sw_parse_child_fdt(e6000sw_softc_t *sc, phandle_t child, int *pport)
365 {
366 	uint32_t port;
367 
368 	if (pport == NULL)
369 		return (ENXIO);
370 
371 	if (OF_getencprop(child, "reg", (void *)&port, sizeof(port)) < 0)
372 		return (ENXIO);
373 	if (port >= sc->num_ports)
374 		return (ENXIO);
375 	*pport = port;
376 
377 	if (e6000sw_parse_fixed_link(sc, child, port) != 0)
378 		return (ENXIO);
379 
380 	if (e6000sw_parse_ethernet(sc, child, port) != 0)
381 		return (ENXIO);
382 
383 	if ((sc->fixed_mask & (1 << port)) != 0)
384 		device_printf(sc->dev, "fixed port at %d\n", port);
385 	else
386 		device_printf(sc->dev, "PHY at port %d\n", port);
387 
388 	return (0);
389 }
390 #else
391 
392 static int
393 e6000sw_check_hint_val(device_t dev, int *val, char *fmt, ...)
394 {
395 	char *resname;
396 	int err, len;
397 	va_list ap;
398 
399 	len = min(strlen(fmt) * 2, 128);
400 	if (len == 0)
401 		return (-1);
402 	resname = malloc(len, M_E6000SW, M_WAITOK);
403 	memset(resname, 0, len);
404 	va_start(ap, fmt);
405 	vsnprintf(resname, len - 1, fmt, ap);
406 	va_end(ap);
407 	err = resource_int_value(device_get_name(dev), device_get_unit(dev),
408 	    resname, val);
409 	free(resname, M_E6000SW);
410 
411 	return (err);
412 }
413 
414 static int
415 e6000sw_parse_hinted_port(e6000sw_softc_t *sc, int port)
416 {
417 	int err, val;
418 
419 	err = e6000sw_check_hint_val(sc->dev, &val, "port%ddisabled", port);
420 	if (err == 0 && val != 0)
421 		return (1);
422 
423 	err = e6000sw_check_hint_val(sc->dev, &val, "port%dcpu", port);
424 	if (err == 0 && val != 0) {
425 		sc->cpuports_mask |= (1 << port);
426 		sc->fixed_mask |= (1 << port);
427 		if (bootverbose)
428 			device_printf(sc->dev, "CPU port at %d\n", port);
429 	}
430 	err = e6000sw_check_hint_val(sc->dev, &val, "port%dspeed", port);
431 	if (err == 0 && val != 0) {
432 		sc->fixed_mask |= (1 << port);
433 		if (val == 2500)
434 			sc->fixed25_mask |= (1 << port);
435 	}
436 
437 	if (bootverbose) {
438 		if ((sc->fixed_mask & (1 << port)) != 0)
439 			device_printf(sc->dev, "fixed port at %d\n", port);
440 		else
441 			device_printf(sc->dev, "PHY at port %d\n", port);
442 	}
443 
444 	return (0);
445 }
446 #endif
447 
448 static int
449 e6000sw_init_interface(e6000sw_softc_t *sc, int port)
450 {
451 	char name[IFNAMSIZ];
452 
453 	snprintf(name, IFNAMSIZ, "%sport", device_get_nameunit(sc->dev));
454 
455 	sc->ifp[port] = if_alloc(IFT_ETHER);
456 	if (sc->ifp[port] == NULL)
457 		return (ENOMEM);
458 	if_setsoftc(sc->ifp[port], sc);
459 	if_setflagbits(sc->ifp[port], IFF_UP | IFF_BROADCAST |
460 	    IFF_DRV_RUNNING | IFF_SIMPLEX, 0);
461 	sc->ifname[port] = malloc(strlen(name) + 1, M_E6000SW, M_NOWAIT);
462 	if (sc->ifname[port] == NULL) {
463 		if_free(sc->ifp[port]);
464 		return (ENOMEM);
465 	}
466 	memcpy(sc->ifname[port], name, strlen(name) + 1);
467 	if_initname(sc->ifp[port], sc->ifname[port], port);
468 
469 	return (0);
470 }
471 
472 static int
473 e6000sw_attach_miibus(e6000sw_softc_t *sc, int port)
474 {
475 	int err;
476 
477 	err = mii_attach(sc->dev, &sc->miibus[port], sc->ifp[port],
478 	    e6000sw_ifmedia_upd, e6000sw_ifmedia_sts, BMSR_DEFCAPMASK,
479 	    port + sc->phy_base, MII_OFFSET_ANY, 0);
480 	if (err != 0)
481 		return (err);
482 
483 	return (0);
484 }
485 
486 static void
487 e6000sw_serdes_power(device_t dev, int port, bool sgmii)
488 {
489 	uint32_t reg;
490 
491 	/* SGMII */
492 	reg = e6000sw_read_xmdio(dev, port, E6000SW_SERDES_DEV,
493 	    E6000SW_SERDES_SGMII_CTL);
494 	if (sgmii)
495 		reg &= ~E6000SW_SERDES_PDOWN;
496 	else
497 		reg |= E6000SW_SERDES_PDOWN;
498 	e6000sw_write_xmdio(dev, port, E6000SW_SERDES_DEV,
499 	    E6000SW_SERDES_SGMII_CTL, reg);
500 
501 	/* 10GBASE-R/10GBASE-X4/X2 */
502 	reg = e6000sw_read_xmdio(dev, port, E6000SW_SERDES_DEV,
503 	    E6000SW_SERDES_PCS_CTL1);
504 	if (sgmii)
505 		reg |= E6000SW_SERDES_PDOWN;
506 	else
507 		reg &= ~E6000SW_SERDES_PDOWN;
508 	e6000sw_write_xmdio(dev, port, E6000SW_SERDES_DEV,
509 	    E6000SW_SERDES_PCS_CTL1, reg);
510 }
511 
512 static int
513 e6000sw_attach(device_t dev)
514 {
515 	bool sgmii;
516 	e6000sw_softc_t *sc;
517 #ifdef FDT
518 	phandle_t child, ports;
519 #endif
520 	int err, port;
521 	uint32_t reg;
522 
523 	err = 0;
524 	sc = device_get_softc(dev);
525 
526 	/*
527 	 * According to the Linux source code, all of the Switch IDs we support
528 	 * are multi_chip capable, and should go into multi-chip mode if the
529 	 * sw_addr != 0.
530 	 */
531 	if (MVSWITCH_MULTICHIP(sc))
532 		device_printf(dev, "multi-chip addressing mode (%#x)\n",
533 		    sc->sw_addr);
534 	else
535 		device_printf(dev, "single-chip addressing mode\n");
536 
537 	sx_init(&sc->sx, "e6000sw");
538 
539 	E6000SW_LOCK(sc);
540 	e6000sw_setup(dev, sc);
541 
542 	sc->sc_tq = taskqueue_create("e6000sw_taskq", M_NOWAIT,
543 	    taskqueue_thread_enqueue, &sc->sc_tq);
544 
545 	TIMEOUT_TASK_INIT(sc->sc_tq, &sc->sc_tt, 0, e6000sw_tick, sc);
546 	taskqueue_start_threads(&sc->sc_tq, 1, PI_NET, "%s taskq",
547 	    device_get_nameunit(dev));
548 
549 #ifdef FDT
550 	ports = ofw_bus_find_child(sc->node, "ports");
551 	if (ports == 0) {
552 		device_printf(dev, "failed to parse DTS: no ports found for "
553 		    "switch\n");
554 		E6000SW_UNLOCK(sc);
555 		return (ENXIO);
556 	}
557 
558 	for (child = OF_child(ports); child != 0; child = OF_peer(child)) {
559 		err = e6000sw_parse_child_fdt(sc, child, &port);
560 		if (err != 0) {
561 			device_printf(sc->dev, "failed to parse DTS\n");
562 			goto out_fail;
563 		}
564 #else
565 	for (port = 0; port < sc->num_ports; port++) {
566 		err = e6000sw_parse_hinted_port(sc, port);
567 		if (err != 0)
568 			continue;
569 #endif
570 
571 		/* Port is in use. */
572 		sc->ports_mask |= (1 << port);
573 
574 		err = e6000sw_init_interface(sc, port);
575 		if (err != 0) {
576 			device_printf(sc->dev, "failed to init interface\n");
577 			goto out_fail;
578 		}
579 
580 		if (e6000sw_is_fixedport(sc, port)) {
581 			/* Link must be down to change speed force value. */
582 			reg = e6000sw_readreg(sc, REG_PORT(sc, port),
583 			    PSC_CONTROL);
584 			reg &= ~PSC_CONTROL_LINK_UP;
585 			reg |= PSC_CONTROL_FORCED_LINK;
586 			e6000sw_writereg(sc, REG_PORT(sc, port), PSC_CONTROL,
587 			    reg);
588 
589 			/*
590 			 * Force speed, full-duplex, EEE off and flow-control
591 			 * on.
592 			 */
593 			reg &= ~(PSC_CONTROL_SPD2500 | PSC_CONTROL_ALT_SPD |
594 			    PSC_CONTROL_FORCED_FC | PSC_CONTROL_FC_ON |
595 			    PSC_CONTROL_FORCED_EEE);
596 			if (e6000sw_is_fixed25port(sc, port))
597 				reg |= PSC_CONTROL_SPD2500;
598 			else
599 				reg |= PSC_CONTROL_SPD1000;
600 			if (MVSWITCH(sc, MV88E6190) &&
601 			    e6000sw_is_fixed25port(sc, port))
602 				reg |= PSC_CONTROL_ALT_SPD;
603 			reg |= PSC_CONTROL_FORCED_DPX | PSC_CONTROL_FULLDPX |
604 			    PSC_CONTROL_FORCED_LINK | PSC_CONTROL_LINK_UP |
605 			    PSC_CONTROL_FORCED_SPD;
606 			if (!MVSWITCH(sc, MV88E6190))
607 				reg |= PSC_CONTROL_FORCED_FC | PSC_CONTROL_FC_ON;
608 			if (MVSWITCH(sc, MV88E6141) ||
609 			    MVSWITCH(sc, MV88E6341) ||
610 			    MVSWITCH(sc, MV88E6190))
611 				reg |= PSC_CONTROL_FORCED_EEE;
612 			e6000sw_writereg(sc, REG_PORT(sc, port), PSC_CONTROL,
613 			    reg);
614 			/* Power on the SERDES interfaces. */
615 			if (MVSWITCH(sc, MV88E6190) &&
616 			    (port == 9 || port == 10)) {
617 				if (e6000sw_is_fixed25port(sc, port))
618 					sgmii = false;
619 				else
620 					sgmii = true;
621 				e6000sw_serdes_power(sc->dev, port, sgmii);
622 			}
623 		}
624 
625 		/* Don't attach miibus at CPU/fixed ports */
626 		if (!e6000sw_is_phyport(sc, port))
627 			continue;
628 
629 		err = e6000sw_attach_miibus(sc, port);
630 		if (err != 0) {
631 			device_printf(sc->dev, "failed to attach miibus\n");
632 			goto out_fail;
633 		}
634 	}
635 
636 	etherswitch_info.es_nports = sc->num_ports;
637 
638 	/* Default to port vlan. */
639 	e6000sw_set_vlan_mode(sc, ETHERSWITCH_VLAN_PORT);
640 
641 	reg = e6000sw_readreg(sc, REG_GLOBAL, SWITCH_GLOBAL_STATUS);
642 	if (reg & SWITCH_GLOBAL_STATUS_IR)
643 		device_printf(dev, "switch is ready.\n");
644 	E6000SW_UNLOCK(sc);
645 
646 	bus_generic_probe(dev);
647 	bus_generic_attach(dev);
648 
649 	taskqueue_enqueue_timeout(sc->sc_tq, &sc->sc_tt, hz);
650 
651 	return (0);
652 
653 out_fail:
654 	e6000sw_detach(dev);
655 
656 	return (err);
657 }
658 
659 static int
660 e6000sw_waitready(e6000sw_softc_t *sc, uint32_t phy, uint32_t reg,
661     uint32_t busybit)
662 {
663 	int i;
664 
665 	for (i = 0; i < E6000SW_RETRIES; i++) {
666 		if ((e6000sw_readreg(sc, phy, reg) & busybit) == 0)
667 			return (0);
668 		DELAY(1);
669 	}
670 
671 	return (1);
672 }
673 
674 /* XMDIO/Clause 45 access. */
675 static int
676 e6000sw_read_xmdio(device_t dev, int phy, int devaddr, int devreg)
677 {
678 	e6000sw_softc_t *sc;
679 	uint32_t reg;
680 
681 	sc = device_get_softc(dev);
682 	E6000SW_LOCK_ASSERT(sc, SA_XLOCKED);
683 	if (E6000SW_WAITREADY2(sc, SMI_PHY_CMD_REG, SMI_CMD_BUSY)) {
684 		device_printf(dev, "Timeout while waiting for switch\n");
685 		return (ETIMEDOUT);
686 	}
687 
688 	reg = devaddr & SMI_CMD_REG_ADDR_MASK;
689 	reg |= (phy << SMI_CMD_DEV_ADDR) & SMI_CMD_DEV_ADDR_MASK;
690 
691 	/* Load C45 register address. */
692 	e6000sw_writereg(sc, REG_GLOBAL2, SMI_PHY_DATA_REG, devreg);
693 	e6000sw_writereg(sc, REG_GLOBAL2, SMI_PHY_CMD_REG,
694 	    reg | SMI_CMD_OP_C45_ADDR);
695 	if (E6000SW_WAITREADY2(sc, SMI_PHY_CMD_REG, SMI_CMD_BUSY)) {
696 		device_printf(dev, "Timeout while waiting for switch\n");
697 		return (ETIMEDOUT);
698 	}
699 
700 	/* Start C45 read operation. */
701 	e6000sw_writereg(sc, REG_GLOBAL2, SMI_PHY_CMD_REG,
702 	    reg | SMI_CMD_OP_C45_READ);
703 	if (E6000SW_WAITREADY2(sc, SMI_PHY_CMD_REG, SMI_CMD_BUSY)) {
704 		device_printf(dev, "Timeout while waiting for switch\n");
705 		return (ETIMEDOUT);
706 	}
707 
708 	/* Read C45 data. */
709 	reg = e6000sw_readreg(sc, REG_GLOBAL2, SMI_PHY_DATA_REG);
710 
711 	return (reg & PHY_DATA_MASK);
712 }
713 
714 static int
715 e6000sw_write_xmdio(device_t dev, int phy, int devaddr, int devreg, int val)
716 {
717 	e6000sw_softc_t *sc;
718 	uint32_t reg;
719 
720 	sc = device_get_softc(dev);
721 	E6000SW_LOCK_ASSERT(sc, SA_XLOCKED);
722 	if (E6000SW_WAITREADY2(sc, SMI_PHY_CMD_REG, SMI_CMD_BUSY)) {
723 		device_printf(dev, "Timeout while waiting for switch\n");
724 		return (ETIMEDOUT);
725 	}
726 
727 	reg = devaddr & SMI_CMD_REG_ADDR_MASK;
728 	reg |= (phy << SMI_CMD_DEV_ADDR) & SMI_CMD_DEV_ADDR_MASK;
729 
730 	/* Load C45 register address. */
731 	e6000sw_writereg(sc, REG_GLOBAL2, SMI_PHY_DATA_REG, devreg);
732 	e6000sw_writereg(sc, REG_GLOBAL2, SMI_PHY_CMD_REG,
733 	    reg | SMI_CMD_OP_C45_ADDR);
734 	if (E6000SW_WAITREADY2(sc, SMI_PHY_CMD_REG, SMI_CMD_BUSY)) {
735 		device_printf(dev, "Timeout while waiting for switch\n");
736 		return (ETIMEDOUT);
737 	}
738 
739 	/* Load data and start the C45 write operation. */
740 	e6000sw_writereg(sc, REG_GLOBAL2, SMI_PHY_DATA_REG, devreg);
741 	e6000sw_writereg(sc, REG_GLOBAL2, SMI_PHY_CMD_REG,
742 	    reg | SMI_CMD_OP_C45_WRITE);
743 
744 	return (0);
745 }
746 
747 static int e6000sw_readphy(device_t dev, int phy, int reg)
748 {
749 	e6000sw_softc_t *sc;
750 	int ret;
751 
752 	sc = device_get_softc(dev);
753 	E6000SW_LOCK_ASSERT(sc, SA_UNLOCKED);
754 
755 	E6000SW_LOCK(sc);
756 	ret = e6000sw_readphy_locked(dev, phy, reg);
757 	E6000SW_UNLOCK(sc);
758 
759 	return (ret);
760 }
761 
762 /*
763  * PHY registers are paged. Put page index in reg 22 (accessible from every
764  * page), then access specific register.
765  */
766 static int
767 e6000sw_readphy_locked(device_t dev, int phy, int reg)
768 {
769 	e6000sw_softc_t *sc;
770 	uint32_t val;
771 
772 	sc = device_get_softc(dev);
773 	E6000SW_LOCK_ASSERT(sc, SA_XLOCKED);
774 
775 	if (!e6000sw_is_phyport(sc, phy) || reg >= E6000SW_NUM_PHY_REGS) {
776 		device_printf(dev, "Wrong register address.\n");
777 		return (EINVAL);
778 	}
779 
780 	if (E6000SW_WAITREADY2(sc, SMI_PHY_CMD_REG, SMI_CMD_BUSY)) {
781 		device_printf(dev, "Timeout while waiting for switch\n");
782 		return (ETIMEDOUT);
783 	}
784 
785 	e6000sw_writereg(sc, REG_GLOBAL2, SMI_PHY_CMD_REG,
786 	    SMI_CMD_OP_C22_READ | (reg & SMI_CMD_REG_ADDR_MASK) |
787 	    ((phy << SMI_CMD_DEV_ADDR) & SMI_CMD_DEV_ADDR_MASK));
788 	if (E6000SW_WAITREADY2(sc, SMI_PHY_CMD_REG, SMI_CMD_BUSY)) {
789 		device_printf(dev, "Timeout while waiting for switch\n");
790 		return (ETIMEDOUT);
791 	}
792 
793 	val = e6000sw_readreg(sc, REG_GLOBAL2, SMI_PHY_DATA_REG);
794 
795 	return (val & PHY_DATA_MASK);
796 }
797 
798 static int e6000sw_writephy(device_t dev, int phy, int reg, int data)
799 {
800 	e6000sw_softc_t *sc;
801 	int ret;
802 
803 	sc = device_get_softc(dev);
804 	E6000SW_LOCK_ASSERT(sc, SA_UNLOCKED);
805 
806 	E6000SW_LOCK(sc);
807 	ret = e6000sw_writephy_locked(dev, phy, reg, data);
808 	E6000SW_UNLOCK(sc);
809 
810 	return (ret);
811 }
812 
813 static int
814 e6000sw_writephy_locked(device_t dev, int phy, int reg, int data)
815 {
816 	e6000sw_softc_t *sc;
817 
818 	sc = device_get_softc(dev);
819 	E6000SW_LOCK_ASSERT(sc, SA_XLOCKED);
820 
821 	if (!e6000sw_is_phyport(sc, phy) || reg >= E6000SW_NUM_PHY_REGS) {
822 		device_printf(dev, "Wrong register address.\n");
823 		return (EINVAL);
824 	}
825 
826 	if (E6000SW_WAITREADY2(sc, SMI_PHY_CMD_REG, SMI_CMD_BUSY)) {
827 		device_printf(dev, "Timeout while waiting for switch\n");
828 		return (ETIMEDOUT);
829 	}
830 
831 	e6000sw_writereg(sc, REG_GLOBAL2, SMI_PHY_DATA_REG,
832 	    data & PHY_DATA_MASK);
833 	e6000sw_writereg(sc, REG_GLOBAL2, SMI_PHY_CMD_REG,
834 	    SMI_CMD_OP_C22_WRITE | (reg & SMI_CMD_REG_ADDR_MASK) |
835 	    ((phy << SMI_CMD_DEV_ADDR) & SMI_CMD_DEV_ADDR_MASK));
836 
837 	return (0);
838 }
839 
840 static int
841 e6000sw_detach(device_t dev)
842 {
843 	int phy;
844 	e6000sw_softc_t *sc;
845 
846 	sc = device_get_softc(dev);
847 
848 	if (device_is_attached(dev))
849 		taskqueue_drain_timeout(sc->sc_tq, &sc->sc_tt);
850 
851 	if (sc->sc_tq != NULL)
852 		taskqueue_free(sc->sc_tq);
853 
854 	device_delete_children(dev);
855 
856 	sx_destroy(&sc->sx);
857 	for (phy = 0; phy < sc->num_ports; phy++) {
858 		if (sc->ifp[phy] != NULL)
859 			if_free(sc->ifp[phy]);
860 		if (sc->ifname[phy] != NULL)
861 			free(sc->ifname[phy], M_E6000SW);
862 	}
863 
864 	return (0);
865 }
866 
867 static etherswitch_info_t*
868 e6000sw_getinfo(device_t dev)
869 {
870 
871 	return (&etherswitch_info);
872 }
873 
874 static int
875 e6000sw_getconf(device_t dev, etherswitch_conf_t *conf)
876 {
877 	struct e6000sw_softc *sc;
878 
879 	/* Return the VLAN mode. */
880 	sc = device_get_softc(dev);
881 	conf->cmd = ETHERSWITCH_CONF_VLAN_MODE;
882 	conf->vlan_mode = sc->vlan_mode;
883 
884 	return (0);
885 }
886 
887 static int
888 e6000sw_setconf(device_t dev, etherswitch_conf_t *conf)
889 {
890 	struct e6000sw_softc *sc;
891 
892 	/* Set the VLAN mode. */
893 	sc = device_get_softc(dev);
894 	if (conf->cmd & ETHERSWITCH_CONF_VLAN_MODE) {
895 		E6000SW_LOCK(sc);
896 		e6000sw_set_vlan_mode(sc, conf->vlan_mode);
897 		E6000SW_UNLOCK(sc);
898 	}
899 
900 	return (0);
901 }
902 
903 static void
904 e6000sw_lock(device_t dev)
905 {
906 	struct e6000sw_softc *sc;
907 
908 	sc = device_get_softc(dev);
909 
910 	E6000SW_LOCK_ASSERT(sc, SA_UNLOCKED);
911 	E6000SW_LOCK(sc);
912 }
913 
914 static void
915 e6000sw_unlock(device_t dev)
916 {
917 	struct e6000sw_softc *sc;
918 
919 	sc = device_get_softc(dev);
920 
921 	E6000SW_LOCK_ASSERT(sc, SA_XLOCKED);
922 	E6000SW_UNLOCK(sc);
923 }
924 
925 static int
926 e6000sw_getport(device_t dev, etherswitch_port_t *p)
927 {
928 	struct mii_data *mii;
929 	int err;
930 	struct ifmediareq *ifmr;
931 	uint32_t reg;
932 
933 	e6000sw_softc_t *sc = device_get_softc(dev);
934 	E6000SW_LOCK_ASSERT(sc, SA_UNLOCKED);
935 
936 	if (p->es_port >= sc->num_ports || p->es_port < 0)
937 		return (EINVAL);
938 	if (!e6000sw_is_portenabled(sc, p->es_port))
939 		return (0);
940 
941 	E6000SW_LOCK(sc);
942 	e6000sw_get_pvid(sc, p->es_port, &p->es_pvid);
943 
944 	/* Port flags. */
945 	reg = e6000sw_readreg(sc, REG_PORT(sc, p->es_port), PORT_CONTROL2);
946 	if (reg & PORT_CONTROL2_DISC_TAGGED)
947 		p->es_flags |= ETHERSWITCH_PORT_DROPTAGGED;
948 	if (reg & PORT_CONTROL2_DISC_UNTAGGED)
949 		p->es_flags |= ETHERSWITCH_PORT_DROPUNTAGGED;
950 
951 	err = 0;
952 	if (e6000sw_is_fixedport(sc, p->es_port)) {
953 		if (e6000sw_is_cpuport(sc, p->es_port))
954 			p->es_flags |= ETHERSWITCH_PORT_CPU;
955 		ifmr = &p->es_ifmr;
956 		ifmr->ifm_status = IFM_ACTIVE | IFM_AVALID;
957 		ifmr->ifm_count = 0;
958 		if (e6000sw_is_fixed25port(sc, p->es_port))
959 			ifmr->ifm_active = IFM_2500_T;
960 		else
961 			ifmr->ifm_active = IFM_1000_T;
962 		ifmr->ifm_active |= IFM_ETHER | IFM_FDX;
963 		ifmr->ifm_current = ifmr->ifm_active;
964 		ifmr->ifm_mask = 0;
965 	} else {
966 		mii = e6000sw_miiforphy(sc, p->es_port);
967 		err = ifmedia_ioctl(mii->mii_ifp, &p->es_ifr,
968 		    &mii->mii_media, SIOCGIFMEDIA);
969 	}
970 	E6000SW_UNLOCK(sc);
971 
972 	return (err);
973 }
974 
975 static int
976 e6000sw_setport(device_t dev, etherswitch_port_t *p)
977 {
978 	e6000sw_softc_t *sc;
979 	int err;
980 	struct mii_data *mii;
981 	uint32_t reg;
982 
983 	sc = device_get_softc(dev);
984 	E6000SW_LOCK_ASSERT(sc, SA_UNLOCKED);
985 
986 	if (p->es_port >= sc->num_ports || p->es_port < 0)
987 		return (EINVAL);
988 	if (!e6000sw_is_portenabled(sc, p->es_port))
989 		return (0);
990 
991 	E6000SW_LOCK(sc);
992 
993 	/* Port flags. */
994 	reg = e6000sw_readreg(sc, REG_PORT(sc, p->es_port), PORT_CONTROL2);
995 	if (p->es_flags & ETHERSWITCH_PORT_DROPTAGGED)
996 		reg |= PORT_CONTROL2_DISC_TAGGED;
997 	else
998 		reg &= ~PORT_CONTROL2_DISC_TAGGED;
999 	if (p->es_flags & ETHERSWITCH_PORT_DROPUNTAGGED)
1000 		reg |= PORT_CONTROL2_DISC_UNTAGGED;
1001 	else
1002 		reg &= ~PORT_CONTROL2_DISC_UNTAGGED;
1003 	e6000sw_writereg(sc, REG_PORT(sc, p->es_port), PORT_CONTROL2, reg);
1004 
1005 	err = 0;
1006 	if (p->es_pvid != 0)
1007 		e6000sw_set_pvid(sc, p->es_port, p->es_pvid);
1008 	if (e6000sw_is_phyport(sc, p->es_port)) {
1009 		mii = e6000sw_miiforphy(sc, p->es_port);
1010 		err = ifmedia_ioctl(mii->mii_ifp, &p->es_ifr, &mii->mii_media,
1011 		    SIOCSIFMEDIA);
1012 	}
1013 	E6000SW_UNLOCK(sc);
1014 
1015 	return (err);
1016 }
1017 
1018 static __inline void
1019 e6000sw_port_vlan_assign(e6000sw_softc_t *sc, int port, uint32_t fid,
1020     uint32_t members)
1021 {
1022 	uint32_t reg;
1023 
1024 	reg = e6000sw_readreg(sc, REG_PORT(sc, port), PORT_VLAN_MAP);
1025 	reg &= ~(PORT_MASK(sc) | PORT_VLAN_MAP_FID_MASK);
1026 	reg |= members & PORT_MASK(sc) & ~(1 << port);
1027 	reg |= (fid << PORT_VLAN_MAP_FID) & PORT_VLAN_MAP_FID_MASK;
1028 	e6000sw_writereg(sc, REG_PORT(sc, port), PORT_VLAN_MAP, reg);
1029 	reg = e6000sw_readreg(sc, REG_PORT(sc, port), PORT_CONTROL1);
1030 	reg &= ~PORT_CONTROL1_FID_MASK;
1031 	reg |= (fid >> 4) & PORT_CONTROL1_FID_MASK;
1032 	e6000sw_writereg(sc, REG_PORT(sc, port), PORT_CONTROL1, reg);
1033 }
1034 
1035 static int
1036 e6000sw_init_vlan(struct e6000sw_softc *sc)
1037 {
1038 	int i, port, ret;
1039 	uint32_t members;
1040 
1041 	/* Disable all ports */
1042 	for (port = 0; port < sc->num_ports; port++) {
1043 		ret = e6000sw_readreg(sc, REG_PORT(sc, port), PORT_CONTROL);
1044 		e6000sw_writereg(sc, REG_PORT(sc, port), PORT_CONTROL,
1045 		    (ret & ~PORT_CONTROL_ENABLE));
1046 	}
1047 
1048 	/* Flush VTU. */
1049 	e6000sw_vtu_flush(sc);
1050 
1051 	for (port = 0; port < sc->num_ports; port++) {
1052 		/* Reset the egress and frame mode. */
1053 		ret = e6000sw_readreg(sc, REG_PORT(sc, port), PORT_CONTROL);
1054 		ret &= ~(PORT_CONTROL_EGRESS | PORT_CONTROL_FRAME);
1055 		e6000sw_writereg(sc, REG_PORT(sc, port), PORT_CONTROL, ret);
1056 
1057 		/* Set the 802.1q mode. */
1058 		ret = e6000sw_readreg(sc, REG_PORT(sc, port), PORT_CONTROL2);
1059 		ret &= ~PORT_CONTROL2_DOT1Q;
1060 		if (sc->vlan_mode == ETHERSWITCH_VLAN_DOT1Q)
1061 			ret |= PORT_CONTROL2_DOT1Q;
1062 		e6000sw_writereg(sc, REG_PORT(sc, port), PORT_CONTROL2, ret);
1063 	}
1064 
1065 	for (port = 0; port < sc->num_ports; port++) {
1066 		if (!e6000sw_is_portenabled(sc, port))
1067 			continue;
1068 
1069 		ret = e6000sw_readreg(sc, REG_PORT(sc, port), PORT_VID);
1070 
1071 		/* Set port priority */
1072 		ret &= ~PORT_VID_PRIORITY_MASK;
1073 
1074 		/* Set VID map */
1075 		ret &= ~PORT_VID_DEF_VID_MASK;
1076 		if (sc->vlan_mode == ETHERSWITCH_VLAN_DOT1Q)
1077 			ret |= 1;
1078 		else
1079 			ret |= (port + 1);
1080 		e6000sw_writereg(sc, REG_PORT(sc, port), PORT_VID, ret);
1081 	}
1082 
1083 	/* Assign the member ports to each origin port. */
1084 	for (port = 0; port < sc->num_ports; port++) {
1085 		members = 0;
1086 		if (e6000sw_is_portenabled(sc, port)) {
1087 			for (i = 0; i < sc->num_ports; i++) {
1088 				if (i == port || !e6000sw_is_portenabled(sc, i))
1089 					continue;
1090 				members |= (1 << i);
1091 			}
1092 		}
1093 		/* Default to FID 0. */
1094 		e6000sw_port_vlan_assign(sc, port, 0, members);
1095 	}
1096 
1097 	/* Reset internal VLAN table. */
1098 	for (i = 0; i < nitems(sc->vlans); i++)
1099 		sc->vlans[i] = 0;
1100 
1101 	/* Create default VLAN (1). */
1102 	if (sc->vlan_mode == ETHERSWITCH_VLAN_DOT1Q) {
1103 		sc->vlans[0] = 1;
1104 		e6000sw_vtu_update(sc, 0, sc->vlans[0], 1, 0, sc->ports_mask);
1105 	}
1106 
1107 	/* Enable all ports */
1108 	for (port = 0; port < sc->num_ports; port++) {
1109 		if (!e6000sw_is_portenabled(sc, port))
1110 			continue;
1111 		ret = e6000sw_readreg(sc, REG_PORT(sc, port), PORT_CONTROL);
1112 		e6000sw_writereg(sc, REG_PORT(sc, port), PORT_CONTROL,
1113 		    (ret | PORT_CONTROL_ENABLE));
1114 	}
1115 
1116 	return (0);
1117 }
1118 
1119 static int
1120 e6000sw_set_vlan_mode(struct e6000sw_softc *sc, uint32_t mode)
1121 {
1122 
1123 	E6000SW_LOCK_ASSERT(sc, SA_XLOCKED);
1124 	switch (mode) {
1125 	case ETHERSWITCH_VLAN_PORT:
1126 		sc->vlan_mode = ETHERSWITCH_VLAN_PORT;
1127 		etherswitch_info.es_nvlangroups = sc->num_ports;
1128 		return (e6000sw_init_vlan(sc));
1129 		break;
1130 	case ETHERSWITCH_VLAN_DOT1Q:
1131 		sc->vlan_mode = ETHERSWITCH_VLAN_DOT1Q;
1132 		etherswitch_info.es_nvlangroups = E6000SW_NUM_VLANS;
1133 		return (e6000sw_init_vlan(sc));
1134 		break;
1135 	default:
1136 		return (EINVAL);
1137 	}
1138 }
1139 
1140 /*
1141  * Registers in this switch are divided into sections, specified in
1142  * documentation. So as to access any of them, section index and reg index
1143  * is necessary. etherswitchcfg uses only one variable, so indexes were
1144  * compressed into addr_reg: 32 * section_index + reg_index.
1145  */
1146 static int
1147 e6000sw_readreg_wrapper(device_t dev, int addr_reg)
1148 {
1149 	e6000sw_softc_t *sc;
1150 
1151 	sc = device_get_softc(dev);
1152 	if ((addr_reg > (REG_GLOBAL2 * 32 + REG_NUM_MAX)) ||
1153 	    (addr_reg < (REG_PORT(sc, 0) * 32))) {
1154 		device_printf(dev, "Wrong register address.\n");
1155 		return (EINVAL);
1156 	}
1157 
1158 	return (e6000sw_readreg(device_get_softc(dev), addr_reg / 32,
1159 	    addr_reg % 32));
1160 }
1161 
1162 static int
1163 e6000sw_writereg_wrapper(device_t dev, int addr_reg, int val)
1164 {
1165 	e6000sw_softc_t *sc;
1166 
1167 	sc = device_get_softc(dev);
1168 	if ((addr_reg > (REG_GLOBAL2 * 32 + REG_NUM_MAX)) ||
1169 	    (addr_reg < (REG_PORT(sc, 0) * 32))) {
1170 		device_printf(dev, "Wrong register address.\n");
1171 		return (EINVAL);
1172 	}
1173 	e6000sw_writereg(device_get_softc(dev), addr_reg / 32,
1174 	    addr_reg % 32, val);
1175 
1176 	return (0);
1177 }
1178 
1179 /*
1180  * setvgroup/getvgroup called from etherswitchfcg need to be locked,
1181  * while internal calls do not.
1182  */
1183 static int
1184 e6000sw_setvgroup_wrapper(device_t dev, etherswitch_vlangroup_t *vg)
1185 {
1186 	e6000sw_softc_t *sc;
1187 	int ret;
1188 
1189 	sc = device_get_softc(dev);
1190 	E6000SW_LOCK_ASSERT(sc, SA_UNLOCKED);
1191 
1192 	E6000SW_LOCK(sc);
1193 	ret = e6000sw_setvgroup(dev, vg);
1194 	E6000SW_UNLOCK(sc);
1195 
1196 	return (ret);
1197 }
1198 
1199 static int
1200 e6000sw_getvgroup_wrapper(device_t dev, etherswitch_vlangroup_t *vg)
1201 {
1202 	e6000sw_softc_t *sc;
1203 	int ret;
1204 
1205 	sc = device_get_softc(dev);
1206 	E6000SW_LOCK_ASSERT(sc, SA_UNLOCKED);
1207 
1208 	E6000SW_LOCK(sc);
1209 	ret = e6000sw_getvgroup(dev, vg);
1210 	E6000SW_UNLOCK(sc);
1211 
1212 	return (ret);
1213 }
1214 
1215 static int
1216 e6000sw_set_port_vlan(e6000sw_softc_t *sc, etherswitch_vlangroup_t *vg)
1217 {
1218 	uint32_t port;
1219 
1220 	port = vg->es_vlangroup;
1221 	if (port > sc->num_ports)
1222 		return (EINVAL);
1223 
1224 	if (vg->es_member_ports != vg->es_untagged_ports) {
1225 		device_printf(sc->dev, "Tagged ports not supported.\n");
1226 		return (EINVAL);
1227 	}
1228 
1229 	e6000sw_port_vlan_assign(sc, port, 0, vg->es_untagged_ports);
1230 	vg->es_vid = port | ETHERSWITCH_VID_VALID;
1231 
1232 	return (0);
1233 }
1234 
1235 static int
1236 e6000sw_set_dot1q_vlan(e6000sw_softc_t *sc, etherswitch_vlangroup_t *vg)
1237 {
1238 	int i, vlan;
1239 
1240 	vlan = vg->es_vid & ETHERSWITCH_VID_MASK;
1241 
1242 	/* Set VLAN to '0' removes it from table. */
1243 	if (vlan == 0) {
1244 		e6000sw_vtu_update(sc, VTU_PURGE,
1245 		    sc->vlans[vg->es_vlangroup], 0, 0, 0);
1246 		sc->vlans[vg->es_vlangroup] = 0;
1247 		return (0);
1248 	}
1249 
1250 	/* Is this VLAN already in table ? */
1251 	for (i = 0; i < etherswitch_info.es_nvlangroups; i++)
1252 		if (i != vg->es_vlangroup && vlan == sc->vlans[i])
1253 			return (EINVAL);
1254 
1255 	sc->vlans[vg->es_vlangroup] = vlan;
1256 	e6000sw_vtu_update(sc, 0, vlan, vg->es_vlangroup + 1,
1257 	    vg->es_member_ports & sc->ports_mask,
1258 	    vg->es_untagged_ports & sc->ports_mask);
1259 
1260 	return (0);
1261 }
1262 
1263 static int
1264 e6000sw_setvgroup(device_t dev, etherswitch_vlangroup_t *vg)
1265 {
1266 	e6000sw_softc_t *sc;
1267 
1268 	sc = device_get_softc(dev);
1269 	E6000SW_LOCK_ASSERT(sc, SA_XLOCKED);
1270 
1271 	if (sc->vlan_mode == ETHERSWITCH_VLAN_PORT)
1272 		return (e6000sw_set_port_vlan(sc, vg));
1273 	else if (sc->vlan_mode == ETHERSWITCH_VLAN_DOT1Q)
1274 		return (e6000sw_set_dot1q_vlan(sc, vg));
1275 
1276 	return (EINVAL);
1277 }
1278 
1279 static int
1280 e6000sw_get_port_vlan(e6000sw_softc_t *sc, etherswitch_vlangroup_t *vg)
1281 {
1282 	uint32_t port, reg;
1283 
1284 	port = vg->es_vlangroup;
1285 	if (port > sc->num_ports)
1286 		return (EINVAL);
1287 
1288 	if (!e6000sw_is_portenabled(sc, port)) {
1289 		vg->es_vid = port;
1290 		return (0);
1291 	}
1292 
1293 	reg = e6000sw_readreg(sc, REG_PORT(sc, port), PORT_VLAN_MAP);
1294 	vg->es_untagged_ports = vg->es_member_ports = reg & PORT_MASK(sc);
1295 	vg->es_vid = port | ETHERSWITCH_VID_VALID;
1296 	vg->es_fid = (reg & PORT_VLAN_MAP_FID_MASK) >> PORT_VLAN_MAP_FID;
1297 	reg = e6000sw_readreg(sc, REG_PORT(sc, port), PORT_CONTROL1);
1298 	vg->es_fid |= (reg & PORT_CONTROL1_FID_MASK) << 4;
1299 
1300 	return (0);
1301 }
1302 
1303 static int
1304 e6000sw_get_dot1q_vlan(e6000sw_softc_t *sc, etherswitch_vlangroup_t *vg)
1305 {
1306 	int i, port;
1307 	uint32_t reg;
1308 
1309 	vg->es_fid = 0;
1310 	vg->es_vid = sc->vlans[vg->es_vlangroup];
1311 	vg->es_untagged_ports = vg->es_member_ports = 0;
1312 	if (vg->es_vid == 0)
1313 		return (0);
1314 
1315 	if (E6000SW_WAITREADY(sc, VTU_OPERATION, VTU_BUSY)) {
1316 		device_printf(sc->dev, "VTU unit is busy, cannot access\n");
1317 		return (EBUSY);
1318 	}
1319 
1320 	e6000sw_writereg(sc, REG_GLOBAL, VTU_VID, vg->es_vid - 1);
1321 
1322 	reg = e6000sw_readreg(sc, REG_GLOBAL, VTU_OPERATION);
1323 	reg &= ~VTU_OP_MASK;
1324 	reg |= VTU_GET_NEXT | VTU_BUSY;
1325 	e6000sw_writereg(sc, REG_GLOBAL, VTU_OPERATION, reg);
1326 	if (E6000SW_WAITREADY(sc, VTU_OPERATION, VTU_BUSY)) {
1327 		device_printf(sc->dev, "Timeout while reading\n");
1328 		return (EBUSY);
1329 	}
1330 
1331 	reg = e6000sw_readreg(sc, REG_GLOBAL, VTU_VID);
1332 	if (reg == VTU_VID_MASK || (reg & VTU_VID_VALID) == 0)
1333 		return (EINVAL);
1334 	if ((reg & VTU_VID_MASK) != vg->es_vid)
1335 		return (EINVAL);
1336 
1337 	vg->es_vid |= ETHERSWITCH_VID_VALID;
1338 	reg = e6000sw_readreg(sc, REG_GLOBAL, VTU_DATA);
1339 	for (i = 0; i < sc->num_ports; i++) {
1340 		if (i == VTU_PPREG(sc))
1341 			reg = e6000sw_readreg(sc, REG_GLOBAL, VTU_DATA2);
1342 		port = (reg >> VTU_PORT(sc, i)) & VTU_PORT_MASK;
1343 		if (port == VTU_PORT_UNTAGGED) {
1344 			vg->es_untagged_ports |= (1 << i);
1345 			vg->es_member_ports |= (1 << i);
1346 		} else if (port == VTU_PORT_TAGGED)
1347 			vg->es_member_ports |= (1 << i);
1348 	}
1349 
1350 	return (0);
1351 }
1352 
1353 static int
1354 e6000sw_getvgroup(device_t dev, etherswitch_vlangroup_t *vg)
1355 {
1356 	e6000sw_softc_t *sc;
1357 
1358 	sc = device_get_softc(dev);
1359 	E6000SW_LOCK_ASSERT(sc, SA_XLOCKED);
1360 
1361 	if (sc->vlan_mode == ETHERSWITCH_VLAN_PORT)
1362 		return (e6000sw_get_port_vlan(sc, vg));
1363 	else if (sc->vlan_mode == ETHERSWITCH_VLAN_DOT1Q)
1364 		return (e6000sw_get_dot1q_vlan(sc, vg));
1365 
1366 	return (EINVAL);
1367 }
1368 
1369 static __inline struct mii_data*
1370 e6000sw_miiforphy(e6000sw_softc_t *sc, unsigned int phy)
1371 {
1372 
1373 	if (!e6000sw_is_phyport(sc, phy))
1374 		return (NULL);
1375 
1376 	return (device_get_softc(sc->miibus[phy]));
1377 }
1378 
1379 static int
1380 e6000sw_ifmedia_upd(if_t ifp)
1381 {
1382 	e6000sw_softc_t *sc;
1383 	struct mii_data *mii;
1384 
1385 	sc = if_getsoftc(ifp);
1386 	mii = e6000sw_miiforphy(sc, if_getdunit(ifp));
1387 	if (mii == NULL)
1388 		return (ENXIO);
1389 	mii_mediachg(mii);
1390 
1391 	return (0);
1392 }
1393 
1394 static void
1395 e6000sw_ifmedia_sts(if_t ifp, struct ifmediareq *ifmr)
1396 {
1397 	e6000sw_softc_t *sc;
1398 	struct mii_data *mii;
1399 
1400 	sc = if_getsoftc(ifp);
1401 	mii = e6000sw_miiforphy(sc, if_getdunit(ifp));
1402 
1403 	if (mii == NULL)
1404 		return;
1405 
1406 	mii_pollstat(mii);
1407 	ifmr->ifm_active = mii->mii_media_active;
1408 	ifmr->ifm_status = mii->mii_media_status;
1409 }
1410 
1411 static int
1412 e6000sw_smi_waitready(e6000sw_softc_t *sc, int phy)
1413 {
1414 	int i;
1415 
1416 	for (i = 0; i < E6000SW_SMI_TIMEOUT; i++) {
1417 		if ((MDIO_READ(sc->dev, phy, SMI_CMD) & SMI_CMD_BUSY) == 0)
1418 			return (0);
1419 		DELAY(1);
1420 	}
1421 
1422 	return (1);
1423 }
1424 
1425 static __inline uint32_t
1426 e6000sw_readreg(e6000sw_softc_t *sc, int addr, int reg)
1427 {
1428 
1429 	E6000SW_LOCK_ASSERT(sc, SA_XLOCKED);
1430 
1431 	if (!MVSWITCH_MULTICHIP(sc))
1432 		return (MDIO_READ(sc->dev, addr, reg) & 0xffff);
1433 
1434 	if (e6000sw_smi_waitready(sc, sc->sw_addr)) {
1435 		printf("e6000sw: readreg timeout\n");
1436 		return (0xffff);
1437 	}
1438 	MDIO_WRITE(sc->dev, sc->sw_addr, SMI_CMD,
1439 	    SMI_CMD_OP_C22_READ | (reg & SMI_CMD_REG_ADDR_MASK) |
1440 	    ((addr << SMI_CMD_DEV_ADDR) & SMI_CMD_DEV_ADDR_MASK));
1441 	if (e6000sw_smi_waitready(sc, sc->sw_addr)) {
1442 		printf("e6000sw: readreg timeout\n");
1443 		return (0xffff);
1444 	}
1445 
1446 	return (MDIO_READ(sc->dev, sc->sw_addr, SMI_DATA) & 0xffff);
1447 }
1448 
1449 static __inline void
1450 e6000sw_writereg(e6000sw_softc_t *sc, int addr, int reg, int val)
1451 {
1452 
1453 	E6000SW_LOCK_ASSERT(sc, SA_XLOCKED);
1454 
1455 	if (!MVSWITCH_MULTICHIP(sc)) {
1456 		MDIO_WRITE(sc->dev, addr, reg, val);
1457 		return;
1458 	}
1459 
1460 	if (e6000sw_smi_waitready(sc, sc->sw_addr)) {
1461 		printf("e6000sw: readreg timeout\n");
1462 		return;
1463 	}
1464 	MDIO_WRITE(sc->dev, sc->sw_addr, SMI_DATA, val);
1465 	MDIO_WRITE(sc->dev, sc->sw_addr, SMI_CMD,
1466 	    SMI_CMD_OP_C22_WRITE | (reg & SMI_CMD_REG_ADDR_MASK) |
1467 	    ((addr << SMI_CMD_DEV_ADDR) & SMI_CMD_DEV_ADDR_MASK));
1468 }
1469 
1470 static __inline bool
1471 e6000sw_is_cpuport(e6000sw_softc_t *sc, int port)
1472 {
1473 
1474 	return ((sc->cpuports_mask & (1 << port)) ? true : false);
1475 }
1476 
1477 static __inline bool
1478 e6000sw_is_fixedport(e6000sw_softc_t *sc, int port)
1479 {
1480 
1481 	return ((sc->fixed_mask & (1 << port)) ? true : false);
1482 }
1483 
1484 static __inline bool
1485 e6000sw_is_fixed25port(e6000sw_softc_t *sc, int port)
1486 {
1487 
1488 	return ((sc->fixed25_mask & (1 << port)) ? true : false);
1489 }
1490 
1491 static __inline bool
1492 e6000sw_is_phyport(e6000sw_softc_t *sc, int port)
1493 {
1494 	uint32_t phy_mask;
1495 	phy_mask = ~(sc->fixed_mask | sc->cpuports_mask);
1496 
1497 	return ((phy_mask & (1 << port)) ? true : false);
1498 }
1499 
1500 static __inline bool
1501 e6000sw_is_portenabled(e6000sw_softc_t *sc, int port)
1502 {
1503 
1504 	return ((sc->ports_mask & (1 << port)) ? true : false);
1505 }
1506 
1507 static __inline void
1508 e6000sw_set_pvid(e6000sw_softc_t *sc, int port, int pvid)
1509 {
1510 	uint32_t reg;
1511 
1512 	reg = e6000sw_readreg(sc, REG_PORT(sc, port), PORT_VID);
1513 	reg &= ~PORT_VID_DEF_VID_MASK;
1514 	reg |= (pvid & PORT_VID_DEF_VID_MASK);
1515 	e6000sw_writereg(sc, REG_PORT(sc, port), PORT_VID, reg);
1516 }
1517 
1518 static __inline int
1519 e6000sw_get_pvid(e6000sw_softc_t *sc, int port, int *pvid)
1520 {
1521 
1522 	if (pvid == NULL)
1523 		return (ENXIO);
1524 
1525 	*pvid = e6000sw_readreg(sc, REG_PORT(sc, port), PORT_VID) &
1526 	    PORT_VID_DEF_VID_MASK;
1527 
1528 	return (0);
1529 }
1530 
1531 /*
1532  * Convert port status to ifmedia.
1533  */
1534 static void
1535 e6000sw_update_ifmedia(uint16_t portstatus, u_int *media_status, u_int *media_active)
1536 {
1537 	*media_active = IFM_ETHER;
1538 	*media_status = IFM_AVALID;
1539 
1540 	if ((portstatus & PORT_STATUS_LINK_MASK) != 0)
1541 		*media_status |= IFM_ACTIVE;
1542 	else {
1543 		*media_active |= IFM_NONE;
1544 		return;
1545 	}
1546 
1547 	switch (portstatus & PORT_STATUS_SPEED_MASK) {
1548 	case PORT_STATUS_SPEED_10:
1549 		*media_active |= IFM_10_T;
1550 		break;
1551 	case PORT_STATUS_SPEED_100:
1552 		*media_active |= IFM_100_TX;
1553 		break;
1554 	case PORT_STATUS_SPEED_1000:
1555 		*media_active |= IFM_1000_T;
1556 		break;
1557 	}
1558 
1559 	if ((portstatus & PORT_STATUS_DUPLEX_MASK) == 0)
1560 		*media_active |= IFM_FDX;
1561 	else
1562 		*media_active |= IFM_HDX;
1563 }
1564 
1565 static void
1566 e6000sw_tick(void *arg, int p __unused)
1567 {
1568 	e6000sw_softc_t *sc;
1569 	struct mii_data *mii;
1570 	struct mii_softc *miisc;
1571 	uint16_t portstatus;
1572 	int port;
1573 
1574 	sc = arg;
1575 
1576 	E6000SW_LOCK_ASSERT(sc, SA_UNLOCKED);
1577 
1578 	E6000SW_LOCK(sc);
1579 	for (port = 0; port < sc->num_ports; port++) {
1580 		/* Tick only on PHY ports */
1581 		if (!e6000sw_is_portenabled(sc, port) ||
1582 		    !e6000sw_is_phyport(sc, port))
1583 			continue;
1584 
1585 		mii = e6000sw_miiforphy(sc, port);
1586 		if (mii == NULL)
1587 			continue;
1588 
1589 		portstatus = e6000sw_readreg(sc, REG_PORT(sc, port),
1590 		    PORT_STATUS);
1591 
1592 		e6000sw_update_ifmedia(portstatus,
1593 		    &mii->mii_media_status, &mii->mii_media_active);
1594 
1595 		LIST_FOREACH(miisc, &mii->mii_phys, mii_list) {
1596 			if (IFM_INST(mii->mii_media.ifm_cur->ifm_media)
1597 			    != miisc->mii_inst)
1598 				continue;
1599 			mii_phy_update(miisc, MII_POLLSTAT);
1600 		}
1601 	}
1602 	E6000SW_UNLOCK(sc);
1603 }
1604 
1605 static void
1606 e6000sw_setup(device_t dev, e6000sw_softc_t *sc)
1607 {
1608 	uint32_t atu_ctrl;
1609 
1610 	/* Set aging time. */
1611 	atu_ctrl = e6000sw_readreg(sc, REG_GLOBAL, ATU_CONTROL);
1612 	atu_ctrl &= ~ATU_CONTROL_AGETIME_MASK;
1613 	atu_ctrl |= E6000SW_DEFAULT_AGETIME << ATU_CONTROL_AGETIME;
1614 	e6000sw_writereg(sc, REG_GLOBAL, ATU_CONTROL, atu_ctrl);
1615 
1616 	/* Send all with specific mac address to cpu port */
1617 	e6000sw_writereg(sc, REG_GLOBAL2, MGMT_EN_2x, MGMT_EN_ALL);
1618 	e6000sw_writereg(sc, REG_GLOBAL2, MGMT_EN_0x, MGMT_EN_ALL);
1619 
1620 	/* Disable Remote Management */
1621 	e6000sw_writereg(sc, REG_GLOBAL, SWITCH_GLOBAL_CONTROL2, 0);
1622 
1623 	/* Disable loopback filter and flow control messages */
1624 	e6000sw_writereg(sc, REG_GLOBAL2, SWITCH_MGMT,
1625 	    SWITCH_MGMT_PRI_MASK |
1626 	    (1 << SWITCH_MGMT_RSVD2CPU) |
1627 	    SWITCH_MGMT_FC_PRI_MASK |
1628 	    (1 << SWITCH_MGMT_FORCEFLOW));
1629 
1630 	e6000sw_atu_flush(dev, sc, NO_OPERATION);
1631 	e6000sw_atu_mac_table(dev, sc, NULL, NO_OPERATION);
1632 	e6000sw_set_atustat(dev, sc, 0, COUNT_ALL);
1633 }
1634 
1635 static void
1636 e6000sw_set_atustat(device_t dev, e6000sw_softc_t *sc, int bin, int flag)
1637 {
1638 
1639 	e6000sw_readreg(sc, REG_GLOBAL2, ATU_STATS);
1640 	e6000sw_writereg(sc, REG_GLOBAL2, ATU_STATS, (bin << ATU_STATS_BIN ) |
1641 	    (flag << ATU_STATS_FLAG));
1642 }
1643 
1644 static int
1645 e6000sw_atu_mac_table(device_t dev, e6000sw_softc_t *sc, struct atu_opt *atu,
1646     int flag)
1647 {
1648 	uint16_t ret_opt;
1649 	uint16_t ret_data;
1650 
1651 	if (flag == NO_OPERATION)
1652 		return (0);
1653 	else if ((flag & (LOAD_FROM_FIB | PURGE_FROM_FIB | GET_NEXT_IN_FIB |
1654 	    GET_VIOLATION_DATA | CLEAR_VIOLATION_DATA)) == 0) {
1655 		device_printf(dev, "Wrong Opcode for ATU operation\n");
1656 		return (EINVAL);
1657 	}
1658 
1659 	if (E6000SW_WAITREADY(sc, ATU_OPERATION, ATU_UNIT_BUSY)) {
1660 		device_printf(dev, "ATU unit is busy, cannot access\n");
1661 		return (EBUSY);
1662 	}
1663 
1664 	ret_opt = e6000sw_readreg(sc, REG_GLOBAL, ATU_OPERATION);
1665 	if (flag & LOAD_FROM_FIB) {
1666 		ret_data = e6000sw_readreg(sc, REG_GLOBAL, ATU_DATA);
1667 		e6000sw_writereg(sc, REG_GLOBAL2, ATU_DATA, (ret_data &
1668 		    ~ENTRY_STATE));
1669 	}
1670 	e6000sw_writereg(sc, REG_GLOBAL, ATU_MAC_ADDR01, atu->mac_01);
1671 	e6000sw_writereg(sc, REG_GLOBAL, ATU_MAC_ADDR23, atu->mac_23);
1672 	e6000sw_writereg(sc, REG_GLOBAL, ATU_MAC_ADDR45, atu->mac_45);
1673 	e6000sw_writereg(sc, REG_GLOBAL, ATU_FID, atu->fid);
1674 
1675 	e6000sw_writereg(sc, REG_GLOBAL, ATU_OPERATION,
1676 	    (ret_opt | ATU_UNIT_BUSY | flag));
1677 
1678 	if (E6000SW_WAITREADY(sc, ATU_OPERATION, ATU_UNIT_BUSY))
1679 		device_printf(dev, "Timeout while waiting ATU\n");
1680 	else if (flag & GET_NEXT_IN_FIB) {
1681 		atu->mac_01 = e6000sw_readreg(sc, REG_GLOBAL,
1682 		    ATU_MAC_ADDR01);
1683 		atu->mac_23 = e6000sw_readreg(sc, REG_GLOBAL,
1684 		    ATU_MAC_ADDR23);
1685 		atu->mac_45 = e6000sw_readreg(sc, REG_GLOBAL,
1686 		    ATU_MAC_ADDR45);
1687 	}
1688 
1689 	return (0);
1690 }
1691 
1692 static int
1693 e6000sw_atu_flush(device_t dev, e6000sw_softc_t *sc, int flag)
1694 {
1695 	uint32_t reg;
1696 
1697 	if (flag == NO_OPERATION)
1698 		return (0);
1699 
1700 	if (E6000SW_WAITREADY(sc, ATU_OPERATION, ATU_UNIT_BUSY)) {
1701 		device_printf(dev, "ATU unit is busy, cannot access\n");
1702 		return (EBUSY);
1703 	}
1704 	reg = e6000sw_readreg(sc, REG_GLOBAL, ATU_OPERATION);
1705 	e6000sw_writereg(sc, REG_GLOBAL, ATU_OPERATION,
1706 	    (reg | ATU_UNIT_BUSY | flag));
1707 	if (E6000SW_WAITREADY(sc, ATU_OPERATION, ATU_UNIT_BUSY))
1708 		device_printf(dev, "Timeout while flushing ATU\n");
1709 
1710 	return (0);
1711 }
1712 
1713 static int
1714 e6000sw_vtu_flush(e6000sw_softc_t *sc)
1715 {
1716 
1717 	if (E6000SW_WAITREADY(sc, VTU_OPERATION, VTU_BUSY)) {
1718 		device_printf(sc->dev, "VTU unit is busy, cannot access\n");
1719 		return (EBUSY);
1720 	}
1721 
1722 	e6000sw_writereg(sc, REG_GLOBAL, VTU_OPERATION, VTU_FLUSH | VTU_BUSY);
1723 	if (E6000SW_WAITREADY(sc, VTU_OPERATION, VTU_BUSY)) {
1724 		device_printf(sc->dev, "Timeout while flushing VTU\n");
1725 		return (ETIMEDOUT);
1726 	}
1727 
1728 	return (0);
1729 }
1730 
1731 static int
1732 e6000sw_vtu_update(e6000sw_softc_t *sc, int purge, int vid, int fid,
1733     int members, int untagged)
1734 {
1735 	int i, op;
1736 	uint32_t data[2];
1737 
1738 	if (E6000SW_WAITREADY(sc, VTU_OPERATION, VTU_BUSY)) {
1739 		device_printf(sc->dev, "VTU unit is busy, cannot access\n");
1740 		return (EBUSY);
1741 	}
1742 
1743 	*data = (vid & VTU_VID_MASK);
1744 	if (purge == 0)
1745 		*data |= VTU_VID_VALID;
1746 	e6000sw_writereg(sc, REG_GLOBAL, VTU_VID, *data);
1747 
1748 	if (purge == 0) {
1749 		data[0] = 0;
1750 		data[1] = 0;
1751 		for (i = 0; i < sc->num_ports; i++) {
1752 			if ((untagged & (1 << i)) != 0)
1753 				data[i / VTU_PPREG(sc)] |=
1754 				    VTU_PORT_UNTAGGED << VTU_PORT(sc, i);
1755 			else if ((members & (1 << i)) != 0)
1756 				data[i / VTU_PPREG(sc)] |=
1757 				    VTU_PORT_TAGGED << VTU_PORT(sc, i);
1758 			else
1759 				data[i / VTU_PPREG(sc)] |=
1760 				    VTU_PORT_DISCARD << VTU_PORT(sc, i);
1761 		}
1762 		e6000sw_writereg(sc, REG_GLOBAL, VTU_DATA, data[0]);
1763 		e6000sw_writereg(sc, REG_GLOBAL, VTU_DATA2, data[1]);
1764 		e6000sw_writereg(sc, REG_GLOBAL, VTU_FID,
1765 		    fid & VTU_FID_MASK(sc));
1766 		op = VTU_LOAD;
1767 	} else
1768 		op = VTU_PURGE;
1769 
1770 	e6000sw_writereg(sc, REG_GLOBAL, VTU_OPERATION, op | VTU_BUSY);
1771 	if (E6000SW_WAITREADY(sc, VTU_OPERATION, VTU_BUSY)) {
1772 		device_printf(sc->dev, "Timeout while flushing VTU\n");
1773 		return (ETIMEDOUT);
1774 	}
1775 
1776 	return (0);
1777 }
1778