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