xref: /freebsd/sys/dev/etherswitch/arswitch/arswitch.c (revision 2c6ceccadeea768efd08c4d85466c76a4f9ec574)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2011-2012 Stefan Bethke.
5  * Copyright (c) 2012 Adrian Chadd.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * $FreeBSD$
30  */
31 
32 #include <sys/param.h>
33 #include <sys/bus.h>
34 #include <sys/errno.h>
35 #include <sys/kernel.h>
36 #include <sys/malloc.h>
37 #include <sys/module.h>
38 #include <sys/socket.h>
39 #include <sys/sockio.h>
40 #include <sys/sysctl.h>
41 #include <sys/systm.h>
42 
43 #include <net/if.h>
44 #include <net/if_var.h>
45 #include <net/if_arp.h>
46 #include <net/ethernet.h>
47 #include <net/if_dl.h>
48 #include <net/if_media.h>
49 #include <net/if_types.h>
50 
51 #include <machine/bus.h>
52 #include <dev/iicbus/iic.h>
53 #include <dev/iicbus/iiconf.h>
54 #include <dev/iicbus/iicbus.h>
55 #include <dev/mii/mii.h>
56 #include <dev/mii/miivar.h>
57 #include <dev/mdio/mdio.h>
58 
59 #include <dev/etherswitch/etherswitch.h>
60 
61 #include <dev/etherswitch/arswitch/arswitchreg.h>
62 #include <dev/etherswitch/arswitch/arswitchvar.h>
63 #include <dev/etherswitch/arswitch/arswitch_reg.h>
64 #include <dev/etherswitch/arswitch/arswitch_phy.h>
65 #include <dev/etherswitch/arswitch/arswitch_vlans.h>
66 
67 #include <dev/etherswitch/arswitch/arswitch_7240.h>
68 #include <dev/etherswitch/arswitch/arswitch_8216.h>
69 #include <dev/etherswitch/arswitch/arswitch_8226.h>
70 #include <dev/etherswitch/arswitch/arswitch_8316.h>
71 #include <dev/etherswitch/arswitch/arswitch_8327.h>
72 #include <dev/etherswitch/arswitch/arswitch_9340.h>
73 
74 #include "mdio_if.h"
75 #include "miibus_if.h"
76 #include "etherswitch_if.h"
77 
78 /* Map ETHERSWITCH_PORT_LED_* to Atheros pattern codes */
79 static int led_pattern_table[] = {
80 	[ETHERSWITCH_PORT_LED_DEFAULT] = 0x3,
81 	[ETHERSWITCH_PORT_LED_ON] = 0x2,
82 	[ETHERSWITCH_PORT_LED_OFF] = 0x0,
83 	[ETHERSWITCH_PORT_LED_BLINK] = 0x1
84 };
85 
86 static inline int arswitch_portforphy(int phy);
87 static void arswitch_tick(void *arg);
88 static int arswitch_ifmedia_upd(struct ifnet *);
89 static void arswitch_ifmedia_sts(struct ifnet *, struct ifmediareq *);
90 static int ar8xxx_port_vlan_setup(struct arswitch_softc *sc,
91     etherswitch_port_t *p);
92 static int ar8xxx_port_vlan_get(struct arswitch_softc *sc,
93     etherswitch_port_t *p);
94 static int arswitch_setled(struct arswitch_softc *sc, int phy, int led,
95     int style);
96 
97 static int
98 arswitch_probe(device_t dev)
99 {
100 	struct arswitch_softc *sc;
101 	uint32_t id;
102 	char *chipname, desc[256];
103 
104 	sc = device_get_softc(dev);
105 	bzero(sc, sizeof(*sc));
106 	sc->page = -1;
107 
108 	/* AR7240 probe */
109 	if (ar7240_probe(dev) == 0) {
110 		chipname = "AR7240";
111 		sc->sc_switchtype = AR8X16_SWITCH_AR7240;
112 		sc->is_internal_switch = 1;
113 		id = 0;
114 		goto done;
115 	}
116 
117 	/* AR9340 probe */
118 	if (ar9340_probe(dev) == 0) {
119 		chipname = "AR9340";
120 		sc->sc_switchtype = AR8X16_SWITCH_AR9340;
121 		sc->is_internal_switch = 1;
122 		id = 0;
123 		goto done;
124 	}
125 
126 	/* AR8xxx probe */
127 	id = arswitch_readreg(dev, AR8X16_REG_MASK_CTRL);
128 	sc->chip_rev = (id & AR8X16_MASK_CTRL_REV_MASK);
129 	sc->chip_ver = (id & AR8X16_MASK_CTRL_VER_MASK) > AR8X16_MASK_CTRL_VER_SHIFT;
130 	switch (id & (AR8X16_MASK_CTRL_VER_MASK | AR8X16_MASK_CTRL_REV_MASK)) {
131 	case 0x0101:
132 		chipname = "AR8216";
133 		sc->sc_switchtype = AR8X16_SWITCH_AR8216;
134 		break;
135 	case 0x0201:
136 		chipname = "AR8226";
137 		sc->sc_switchtype = AR8X16_SWITCH_AR8226;
138 		break;
139 	/* 0x0301 - AR8236 */
140 	case 0x1000:
141 	case 0x1001:
142 		chipname = "AR8316";
143 		sc->sc_switchtype = AR8X16_SWITCH_AR8316;
144 		break;
145 	case 0x1202:
146 	case 0x1204:
147 		chipname = "AR8327";
148 		sc->sc_switchtype = AR8X16_SWITCH_AR8327;
149 		sc->mii_lo_first = 1;
150 		break;
151 	default:
152 		chipname = NULL;
153 	}
154 
155 done:
156 
157 	DPRINTF(sc, ARSWITCH_DBG_ANY, "chipname=%s, id=%08x\n", chipname, id);
158 	if (chipname != NULL) {
159 		snprintf(desc, sizeof(desc),
160 		    "Atheros %s Ethernet Switch (ver %d rev %d)",
161 		    chipname,
162 		    sc->chip_ver,
163 		    sc->chip_rev);
164 		device_set_desc_copy(dev, desc);
165 		return (BUS_PROBE_DEFAULT);
166 	}
167 	return (ENXIO);
168 }
169 
170 static int
171 arswitch_attach_phys(struct arswitch_softc *sc)
172 {
173 	int phy, err = 0;
174 	char name[IFNAMSIZ];
175 
176 	/* PHYs need an interface, so we generate a dummy one */
177 	snprintf(name, IFNAMSIZ, "%sport", device_get_nameunit(sc->sc_dev));
178 	for (phy = 0; phy < sc->numphys; phy++) {
179 		sc->ifp[phy] = if_alloc(IFT_ETHER);
180 		if (sc->ifp[phy] == NULL) {
181 			device_printf(sc->sc_dev, "couldn't allocate ifnet structure\n");
182 			err = ENOMEM;
183 			break;
184 		}
185 
186 		sc->ifp[phy]->if_softc = sc;
187 		sc->ifp[phy]->if_flags |= IFF_UP | IFF_BROADCAST |
188 		    IFF_DRV_RUNNING | IFF_SIMPLEX;
189 		sc->ifname[phy] = malloc(strlen(name)+1, M_DEVBUF, M_WAITOK);
190 		bcopy(name, sc->ifname[phy], strlen(name)+1);
191 		if_initname(sc->ifp[phy], sc->ifname[phy],
192 		    arswitch_portforphy(phy));
193 		err = mii_attach(sc->sc_dev, &sc->miibus[phy], sc->ifp[phy],
194 		    arswitch_ifmedia_upd, arswitch_ifmedia_sts, \
195 		    BMSR_DEFCAPMASK, phy, MII_OFFSET_ANY, 0);
196 #if 0
197 		DPRINTF(sc->sc_dev, "%s attached to pseudo interface %s\n",
198 		    device_get_nameunit(sc->miibus[phy]),
199 		    sc->ifp[phy]->if_xname);
200 #endif
201 		if (err != 0) {
202 			device_printf(sc->sc_dev,
203 			    "attaching PHY %d failed\n",
204 			    phy);
205 			return (err);
206 		}
207 
208 		if (AR8X16_IS_SWITCH(sc, AR8327)) {
209 			int led;
210 			char ledname[IFNAMSIZ+4];
211 
212 			for (led = 0; led < 3; led++) {
213 				sprintf(ledname, "%s%dled%d", name,
214 				    arswitch_portforphy(phy), led+1);
215 				sc->dev_led[phy][led].sc = sc;
216 				sc->dev_led[phy][led].phy = phy;
217 				sc->dev_led[phy][led].lednum = led;
218 			}
219 		}
220 	}
221 	return (0);
222 }
223 
224 static int
225 arswitch_reset(device_t dev)
226 {
227 
228 	arswitch_writereg(dev, AR8X16_REG_MASK_CTRL,
229 	    AR8X16_MASK_CTRL_SOFT_RESET);
230 	DELAY(1000);
231 	if (arswitch_readreg(dev, AR8X16_REG_MASK_CTRL) &
232 	    AR8X16_MASK_CTRL_SOFT_RESET) {
233 		device_printf(dev, "unable to reset switch\n");
234 		return (-1);
235 	}
236 	return (0);
237 }
238 
239 static int
240 arswitch_set_vlan_mode(struct arswitch_softc *sc, uint32_t mode)
241 {
242 
243 	/* Check for invalid modes. */
244 	if ((mode & sc->info.es_vlan_caps) != mode)
245 		return (EINVAL);
246 
247 	switch (mode) {
248 	case ETHERSWITCH_VLAN_DOT1Q:
249 		sc->vlan_mode = ETHERSWITCH_VLAN_DOT1Q;
250 		break;
251 	case ETHERSWITCH_VLAN_PORT:
252 		sc->vlan_mode = ETHERSWITCH_VLAN_PORT;
253 		break;
254 	default:
255 		sc->vlan_mode = 0;
256 	}
257 
258 	/* Reset VLANs. */
259 	sc->hal.arswitch_vlan_init_hw(sc);
260 
261 	return (0);
262 }
263 
264 static void
265 ar8xxx_port_init(struct arswitch_softc *sc, int port)
266 {
267 
268 	/* Port0 - CPU */
269 	if (port == AR8X16_PORT_CPU) {
270 		arswitch_writereg(sc->sc_dev, AR8X16_REG_PORT_STS(0),
271 		    (AR8X16_IS_SWITCH(sc, AR8216) ?
272 		    AR8X16_PORT_STS_SPEED_100 : AR8X16_PORT_STS_SPEED_1000) |
273 		    (AR8X16_IS_SWITCH(sc, AR8216) ? 0 : AR8X16_PORT_STS_RXFLOW) |
274 		    (AR8X16_IS_SWITCH(sc, AR8216) ? 0 : AR8X16_PORT_STS_TXFLOW) |
275 		    AR8X16_PORT_STS_RXMAC |
276 		    AR8X16_PORT_STS_TXMAC |
277 		    AR8X16_PORT_STS_DUPLEX);
278 		arswitch_writereg(sc->sc_dev, AR8X16_REG_PORT_CTRL(0),
279 		    arswitch_readreg(sc->sc_dev, AR8X16_REG_PORT_CTRL(0)) &
280 		    ~AR8X16_PORT_CTRL_HEADER);
281 	} else {
282 		/* Set ports to auto negotiation. */
283 		arswitch_writereg(sc->sc_dev, AR8X16_REG_PORT_STS(port),
284 		    AR8X16_PORT_STS_LINK_AUTO);
285 		arswitch_writereg(sc->sc_dev, AR8X16_REG_PORT_CTRL(port),
286 		    arswitch_readreg(sc->sc_dev, AR8X16_REG_PORT_CTRL(port)) &
287 		    ~AR8X16_PORT_CTRL_HEADER);
288 	}
289 }
290 
291 static int
292 ar8xxx_atu_flush(struct arswitch_softc *sc)
293 {
294 	int ret;
295 
296 	ret = arswitch_waitreg(sc->sc_dev,
297 	    AR8216_REG_ATU,
298 	    AR8216_ATU_ACTIVE,
299 	    0,
300 	    1000);
301 
302 	if (ret)
303 		device_printf(sc->sc_dev, "%s: waitreg failed\n", __func__);
304 
305 	if (!ret)
306 		arswitch_writereg(sc->sc_dev,
307 		    AR8216_REG_ATU,
308 		    AR8216_ATU_OP_FLUSH | AR8216_ATU_ACTIVE);
309 
310 	return (ret);
311 }
312 
313 static int
314 arswitch_attach(device_t dev)
315 {
316 	struct arswitch_softc *sc = device_get_softc(dev);
317 	struct sysctl_ctx_list *ctx;
318 	struct sysctl_oid *tree;
319 	int err = 0;
320 	int port;
321 
322 	/* sc->sc_switchtype is already decided in arswitch_probe() */
323 	sc->sc_dev = dev;
324 	mtx_init(&sc->sc_mtx, "arswitch", NULL, MTX_DEF);
325 	sc->page = -1;
326 	strlcpy(sc->info.es_name, device_get_desc(dev),
327 	    sizeof(sc->info.es_name));
328 
329 	/* Debugging */
330 	ctx = device_get_sysctl_ctx(sc->sc_dev);
331 	tree = device_get_sysctl_tree(sc->sc_dev);
332 	SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
333 	    "debug", CTLFLAG_RW, &sc->sc_debug, 0,
334 	    "control debugging printfs");
335 
336 	/* Default HAL methods */
337 	sc->hal.arswitch_port_init = ar8xxx_port_init;
338 	sc->hal.arswitch_port_vlan_setup = ar8xxx_port_vlan_setup;
339 	sc->hal.arswitch_port_vlan_get = ar8xxx_port_vlan_get;
340 	sc->hal.arswitch_vlan_init_hw = ar8xxx_reset_vlans;
341 
342 	sc->hal.arswitch_vlan_getvgroup = ar8xxx_getvgroup;
343 	sc->hal.arswitch_vlan_setvgroup = ar8xxx_setvgroup;
344 
345 	sc->hal.arswitch_vlan_get_pvid = ar8xxx_get_pvid;
346 	sc->hal.arswitch_vlan_set_pvid = ar8xxx_set_pvid;
347 
348 	sc->hal.arswitch_get_dot1q_vlan = ar8xxx_get_dot1q_vlan;
349 	sc->hal.arswitch_set_dot1q_vlan = ar8xxx_set_dot1q_vlan;
350 	sc->hal.arswitch_flush_dot1q_vlan = ar8xxx_flush_dot1q_vlan;
351 	sc->hal.arswitch_purge_dot1q_vlan = ar8xxx_purge_dot1q_vlan;
352 	sc->hal.arswitch_get_port_vlan = ar8xxx_get_port_vlan;
353 	sc->hal.arswitch_set_port_vlan = ar8xxx_set_port_vlan;
354 
355 	sc->hal.arswitch_atu_flush = ar8xxx_atu_flush;
356 
357 	sc->hal.arswitch_phy_read = arswitch_readphy_internal;
358 	sc->hal.arswitch_phy_write = arswitch_writephy_internal;
359 
360 
361 	/*
362 	 * Attach switch related functions
363 	 */
364 	if (AR8X16_IS_SWITCH(sc, AR7240))
365 		ar7240_attach(sc);
366 	else if (AR8X16_IS_SWITCH(sc, AR9340))
367 		ar9340_attach(sc);
368 	else if (AR8X16_IS_SWITCH(sc, AR8216))
369 		ar8216_attach(sc);
370 	else if (AR8X16_IS_SWITCH(sc, AR8226))
371 		ar8226_attach(sc);
372 	else if (AR8X16_IS_SWITCH(sc, AR8316))
373 		ar8316_attach(sc);
374 	else if (AR8X16_IS_SWITCH(sc, AR8327))
375 		ar8327_attach(sc);
376 	else {
377 		DPRINTF(sc, ARSWITCH_DBG_ANY,
378 		    "%s: unknown switch (%d)?\n", __func__, sc->sc_switchtype);
379 		return (ENXIO);
380 	}
381 
382 	/* Common defaults. */
383 	sc->info.es_nports = 5; /* XXX technically 6, but 6th not used */
384 
385 	/* XXX Defaults for externally connected AR8316 */
386 	sc->numphys = 4;
387 	sc->phy4cpu = 1;
388 	sc->is_rgmii = 1;
389 	sc->is_gmii = 0;
390 	sc->is_mii = 0;
391 
392 	(void) resource_int_value(device_get_name(dev), device_get_unit(dev),
393 	    "numphys", &sc->numphys);
394 	(void) resource_int_value(device_get_name(dev), device_get_unit(dev),
395 	    "phy4cpu", &sc->phy4cpu);
396 	(void) resource_int_value(device_get_name(dev), device_get_unit(dev),
397 	    "is_rgmii", &sc->is_rgmii);
398 	(void) resource_int_value(device_get_name(dev), device_get_unit(dev),
399 	    "is_gmii", &sc->is_gmii);
400 	(void) resource_int_value(device_get_name(dev), device_get_unit(dev),
401 	    "is_mii", &sc->is_mii);
402 
403 	if (sc->numphys > AR8X16_NUM_PHYS)
404 		sc->numphys = AR8X16_NUM_PHYS;
405 
406 	/* Reset the switch. */
407 	if (arswitch_reset(dev)) {
408 		DPRINTF(sc, ARSWITCH_DBG_ANY,
409 		    "%s: arswitch_reset: failed\n", __func__);
410 		return (ENXIO);
411 	}
412 
413 	err = sc->hal.arswitch_hw_setup(sc);
414 	if (err != 0) {
415 		DPRINTF(sc, ARSWITCH_DBG_ANY,
416 		    "%s: hw_setup: err=%d\n", __func__, err);
417 		return (err);
418 	}
419 
420 	err = sc->hal.arswitch_hw_global_setup(sc);
421 	if (err != 0) {
422 		DPRINTF(sc, ARSWITCH_DBG_ANY,
423 		    "%s: hw_global_setup: err=%d\n", __func__, err);
424 		return (err);
425 	}
426 
427 	/* Initialize the switch ports. */
428 	for (port = 0; port <= sc->numphys; port++) {
429 		sc->hal.arswitch_port_init(sc, port);
430 	}
431 
432 	/*
433 	 * Attach the PHYs and complete the bus enumeration.
434 	 */
435 	err = arswitch_attach_phys(sc);
436 	if (err != 0) {
437 		DPRINTF(sc, ARSWITCH_DBG_ANY,
438 		    "%s: attach_phys: err=%d\n", __func__, err);
439 		return (err);
440 	}
441 
442 	/* Default to ingress filters off. */
443 	err = arswitch_set_vlan_mode(sc, 0);
444 	if (err != 0) {
445 		DPRINTF(sc, ARSWITCH_DBG_ANY,
446 		    "%s: set_vlan_mode: err=%d\n", __func__, err);
447 		return (err);
448 	}
449 
450 	bus_generic_probe(dev);
451 	bus_enumerate_hinted_children(dev);
452 	err = bus_generic_attach(dev);
453 	if (err != 0) {
454 		DPRINTF(sc, ARSWITCH_DBG_ANY,
455 		    "%s: bus_generic_attach: err=%d\n", __func__, err);
456 		return (err);
457 	}
458 
459 	callout_init_mtx(&sc->callout_tick, &sc->sc_mtx, 0);
460 
461 	ARSWITCH_LOCK(sc);
462 	arswitch_tick(sc);
463 	ARSWITCH_UNLOCK(sc);
464 
465 	return (err);
466 }
467 
468 static int
469 arswitch_detach(device_t dev)
470 {
471 	struct arswitch_softc *sc = device_get_softc(dev);
472 	int i;
473 
474 	callout_drain(&sc->callout_tick);
475 
476 	for (i=0; i < sc->numphys; i++) {
477 		if (sc->miibus[i] != NULL)
478 			device_delete_child(dev, sc->miibus[i]);
479 		if (sc->ifp[i] != NULL)
480 			if_free(sc->ifp[i]);
481 		free(sc->ifname[i], M_DEVBUF);
482 	}
483 
484 	bus_generic_detach(dev);
485 	mtx_destroy(&sc->sc_mtx);
486 
487 	return (0);
488 }
489 
490 /*
491  * Convert PHY number to port number. PHY0 is connected to port 1, PHY1 to
492  * port 2, etc.
493  */
494 static inline int
495 arswitch_portforphy(int phy)
496 {
497 	return (phy+1);
498 }
499 
500 static inline struct mii_data *
501 arswitch_miiforport(struct arswitch_softc *sc, int port)
502 {
503 	int phy = port-1;
504 
505 	if (phy < 0 || phy >= sc->numphys)
506 		return (NULL);
507 	return (device_get_softc(sc->miibus[phy]));
508 }
509 
510 static inline struct ifnet *
511 arswitch_ifpforport(struct arswitch_softc *sc, int port)
512 {
513 	int phy = port-1;
514 
515 	if (phy < 0 || phy >= sc->numphys)
516 		return (NULL);
517 	return (sc->ifp[phy]);
518 }
519 
520 /*
521  * Convert port status to ifmedia.
522  */
523 static void
524 arswitch_update_ifmedia(int portstatus, u_int *media_status, u_int *media_active)
525 {
526 	*media_active = IFM_ETHER;
527 	*media_status = IFM_AVALID;
528 
529 	if ((portstatus & AR8X16_PORT_STS_LINK_UP) != 0)
530 		*media_status |= IFM_ACTIVE;
531 	else {
532 		*media_active |= IFM_NONE;
533 		return;
534 	}
535 	switch (portstatus & AR8X16_PORT_STS_SPEED_MASK) {
536 	case AR8X16_PORT_STS_SPEED_10:
537 		*media_active |= IFM_10_T;
538 		break;
539 	case AR8X16_PORT_STS_SPEED_100:
540 		*media_active |= IFM_100_TX;
541 		break;
542 	case AR8X16_PORT_STS_SPEED_1000:
543 		*media_active |= IFM_1000_T;
544 		break;
545 	}
546 	if ((portstatus & AR8X16_PORT_STS_DUPLEX) == 0)
547 		*media_active |= IFM_FDX;
548 	else
549 		*media_active |= IFM_HDX;
550 	if ((portstatus & AR8X16_PORT_STS_TXFLOW) != 0)
551 		*media_active |= IFM_ETH_TXPAUSE;
552 	if ((portstatus & AR8X16_PORT_STS_RXFLOW) != 0)
553 		*media_active |= IFM_ETH_RXPAUSE;
554 }
555 
556 /*
557  * Poll the status for all PHYs.  We're using the switch port status because
558  * thats a lot quicker to read than talking to all the PHYs.  Care must be
559  * taken that the resulting ifmedia_active is identical to what the PHY will
560  * compute, or gratuitous link status changes will occur whenever the PHYs
561  * update function is called.
562  */
563 static void
564 arswitch_miipollstat(struct arswitch_softc *sc)
565 {
566 	int i;
567 	struct mii_data *mii;
568 	struct mii_softc *miisc;
569 	int portstatus;
570 	int port_flap = 0;
571 
572 	ARSWITCH_LOCK_ASSERT(sc, MA_OWNED);
573 
574 	for (i = 0; i < sc->numphys; i++) {
575 		if (sc->miibus[i] == NULL)
576 			continue;
577 		mii = device_get_softc(sc->miibus[i]);
578 		/* XXX This would be nice to have abstracted out to be per-chip */
579 		/* AR8327/AR8337 has a different register base */
580 		if (AR8X16_IS_SWITCH(sc, AR8327))
581 			portstatus = arswitch_readreg(sc->sc_dev,
582 			    AR8327_REG_PORT_STATUS(arswitch_portforphy(i)));
583 		else
584 			portstatus = arswitch_readreg(sc->sc_dev,
585 			    AR8X16_REG_PORT_STS(arswitch_portforphy(i)));
586 #if 1
587 		DPRINTF(sc, ARSWITCH_DBG_POLL, "p[%d]=0x%08x (%b)\n",
588 		    i,
589 		    portstatus,
590 		    portstatus,
591 		    "\20\3TXMAC\4RXMAC\5TXFLOW\6RXFLOW\7"
592 		    "DUPLEX\11LINK_UP\12LINK_AUTO\13LINK_PAUSE");
593 #endif
594 		/*
595 		 * If the current status is down, but we have a link
596 		 * status showing up, we need to do an ATU flush.
597 		 */
598 		if ((mii->mii_media_status & IFM_ACTIVE) == 0 &&
599 		    (portstatus & AR8X16_PORT_STS_LINK_UP) != 0) {
600 			device_printf(sc->sc_dev, "%s: port %d: port -> UP\n",
601 			    __func__,
602 			    i);
603 			port_flap = 1;
604 		}
605 		/*
606 		 * and maybe if a port goes up->down?
607 		 */
608 		if ((mii->mii_media_status & IFM_ACTIVE) != 0 &&
609 		    (portstatus & AR8X16_PORT_STS_LINK_UP) == 0) {
610 			device_printf(sc->sc_dev, "%s: port %d: port -> DOWN\n",
611 			    __func__,
612 			    i);
613 			port_flap = 1;
614 		}
615 		arswitch_update_ifmedia(portstatus, &mii->mii_media_status,
616 		    &mii->mii_media_active);
617 		LIST_FOREACH(miisc, &mii->mii_phys, mii_list) {
618 			if (IFM_INST(mii->mii_media.ifm_cur->ifm_media) !=
619 			    miisc->mii_inst)
620 				continue;
621 			mii_phy_update(miisc, MII_POLLSTAT);
622 		}
623 	}
624 
625 	/* If a port went from down->up, flush the ATU */
626 	if (port_flap)
627 		sc->hal.arswitch_atu_flush(sc);
628 }
629 
630 static void
631 arswitch_tick(void *arg)
632 {
633 	struct arswitch_softc *sc = arg;
634 
635 	arswitch_miipollstat(sc);
636 	callout_reset(&sc->callout_tick, hz, arswitch_tick, sc);
637 }
638 
639 static void
640 arswitch_lock(device_t dev)
641 {
642 	struct arswitch_softc *sc = device_get_softc(dev);
643 
644 	ARSWITCH_LOCK_ASSERT(sc, MA_NOTOWNED);
645 	ARSWITCH_LOCK(sc);
646 }
647 
648 static void
649 arswitch_unlock(device_t dev)
650 {
651 	struct arswitch_softc *sc = device_get_softc(dev);
652 
653 	ARSWITCH_LOCK_ASSERT(sc, MA_OWNED);
654 	ARSWITCH_UNLOCK(sc);
655 }
656 
657 static etherswitch_info_t *
658 arswitch_getinfo(device_t dev)
659 {
660 	struct arswitch_softc *sc = device_get_softc(dev);
661 
662 	return (&sc->info);
663 }
664 
665 static int
666 ar8xxx_port_vlan_get(struct arswitch_softc *sc, etherswitch_port_t *p)
667 {
668 	uint32_t reg;
669 
670 	ARSWITCH_LOCK(sc);
671 
672 	/* Retrieve the PVID. */
673 	sc->hal.arswitch_vlan_get_pvid(sc, p->es_port, &p->es_pvid);
674 
675 	/* Port flags. */
676 	reg = arswitch_readreg(sc->sc_dev, AR8X16_REG_PORT_CTRL(p->es_port));
677 	if (reg & AR8X16_PORT_CTRL_DOUBLE_TAG)
678 		p->es_flags |= ETHERSWITCH_PORT_DOUBLE_TAG;
679 	reg >>= AR8X16_PORT_CTRL_EGRESS_VLAN_MODE_SHIFT;
680 	if ((reg & 0x3) == AR8X16_PORT_CTRL_EGRESS_VLAN_MODE_ADD)
681 		p->es_flags |= ETHERSWITCH_PORT_ADDTAG;
682 	if ((reg & 0x3) == AR8X16_PORT_CTRL_EGRESS_VLAN_MODE_STRIP)
683 		p->es_flags |= ETHERSWITCH_PORT_STRIPTAG;
684 	ARSWITCH_UNLOCK(sc);
685 
686 	return (0);
687 }
688 
689 static int
690 arswitch_is_cpuport(struct arswitch_softc *sc, int port)
691 {
692 
693 	return ((port == AR8X16_PORT_CPU) ||
694 	    ((AR8X16_IS_SWITCH(sc, AR8327) &&
695 	      port == AR8327_PORT_GMAC6)));
696 }
697 
698 static int
699 arswitch_getport(device_t dev, etherswitch_port_t *p)
700 {
701 	struct arswitch_softc *sc;
702 	struct mii_data *mii;
703 	struct ifmediareq *ifmr;
704 	int err;
705 
706 	sc = device_get_softc(dev);
707 	/* XXX +1 is for AR8327; should make this configurable! */
708 	if (p->es_port < 0 || p->es_port > sc->info.es_nports)
709 		return (ENXIO);
710 
711 	err = sc->hal.arswitch_port_vlan_get(sc, p);
712 	if (err != 0)
713 		return (err);
714 
715 	mii = arswitch_miiforport(sc, p->es_port);
716 	if (arswitch_is_cpuport(sc, p->es_port)) {
717 		/* fill in fixed values for CPU port */
718 		/* XXX is this valid in all cases? */
719 		p->es_flags |= ETHERSWITCH_PORT_CPU;
720 		ifmr = &p->es_ifmr;
721 		ifmr->ifm_count = 0;
722 		ifmr->ifm_current = ifmr->ifm_active =
723 		    IFM_ETHER | IFM_1000_T | IFM_FDX;
724 		ifmr->ifm_mask = 0;
725 		ifmr->ifm_status = IFM_ACTIVE | IFM_AVALID;
726 	} else if (mii != NULL) {
727 		err = ifmedia_ioctl(mii->mii_ifp, &p->es_ifr,
728 		    &mii->mii_media, SIOCGIFMEDIA);
729 		if (err)
730 			return (err);
731 	} else {
732 		return (ENXIO);
733 	}
734 
735 	if (!arswitch_is_cpuport(sc, p->es_port) &&
736 	    AR8X16_IS_SWITCH(sc, AR8327)) {
737 		int led;
738 		p->es_nleds = 3;
739 
740 		for (led = 0; led < p->es_nleds; led++)
741 		{
742 			int style;
743 			uint32_t val;
744 
745 			/* Find the right style enum for our pattern */
746 			val = arswitch_readreg(dev,
747 			    ar8327_led_mapping[p->es_port-1][led].reg);
748 			val = (val>>ar8327_led_mapping[p->es_port-1][led].shift)&0x03;
749 
750 			for (style = 0; style < ETHERSWITCH_PORT_LED_MAX; style++)
751 			{
752 				if (led_pattern_table[style] == val) break;
753 			}
754 
755 			/* can't happen */
756 			if (style == ETHERSWITCH_PORT_LED_MAX)
757 				style = ETHERSWITCH_PORT_LED_DEFAULT;
758 
759 			p->es_led[led] = style;
760 		}
761 	} else
762 	{
763 		p->es_nleds = 0;
764 	}
765 
766 	return (0);
767 }
768 
769 static int
770 ar8xxx_port_vlan_setup(struct arswitch_softc *sc, etherswitch_port_t *p)
771 {
772 	uint32_t reg;
773 	int err;
774 
775 	ARSWITCH_LOCK(sc);
776 
777 	/* Set the PVID. */
778 	if (p->es_pvid != 0)
779 		sc->hal.arswitch_vlan_set_pvid(sc, p->es_port, p->es_pvid);
780 
781 	/* Mutually exclusive. */
782 	if (p->es_flags & ETHERSWITCH_PORT_ADDTAG &&
783 	    p->es_flags & ETHERSWITCH_PORT_STRIPTAG) {
784 		ARSWITCH_UNLOCK(sc);
785 		return (EINVAL);
786 	}
787 
788 	reg = 0;
789 	if (p->es_flags & ETHERSWITCH_PORT_DOUBLE_TAG)
790 		reg |= AR8X16_PORT_CTRL_DOUBLE_TAG;
791 	if (p->es_flags & ETHERSWITCH_PORT_ADDTAG)
792 		reg |= AR8X16_PORT_CTRL_EGRESS_VLAN_MODE_ADD <<
793 		    AR8X16_PORT_CTRL_EGRESS_VLAN_MODE_SHIFT;
794 	if (p->es_flags & ETHERSWITCH_PORT_STRIPTAG)
795 		reg |= AR8X16_PORT_CTRL_EGRESS_VLAN_MODE_STRIP <<
796 		    AR8X16_PORT_CTRL_EGRESS_VLAN_MODE_SHIFT;
797 
798 	err = arswitch_modifyreg(sc->sc_dev,
799 	    AR8X16_REG_PORT_CTRL(p->es_port),
800 	    0x3 << AR8X16_PORT_CTRL_EGRESS_VLAN_MODE_SHIFT |
801 	    AR8X16_PORT_CTRL_DOUBLE_TAG, reg);
802 
803 	ARSWITCH_UNLOCK(sc);
804 	return (err);
805 }
806 
807 static int
808 arswitch_setport(device_t dev, etherswitch_port_t *p)
809 {
810 	int err, i;
811 	struct arswitch_softc *sc;
812 	struct ifmedia *ifm;
813 	struct mii_data *mii;
814 	struct ifnet *ifp;
815 
816 	sc = device_get_softc(dev);
817 	if (p->es_port < 0 || p->es_port > sc->info.es_nports)
818 		return (ENXIO);
819 
820 	/* Port flags. */
821 	if (sc->vlan_mode == ETHERSWITCH_VLAN_DOT1Q) {
822 		err = sc->hal.arswitch_port_vlan_setup(sc, p);
823 		if (err)
824 			return (err);
825 	}
826 
827 	/* Do not allow media or led changes on CPU port. */
828 	if (arswitch_is_cpuport(sc, p->es_port))
829 		return (0);
830 
831 	if (AR8X16_IS_SWITCH(sc, AR8327))
832 	{
833 		for (i = 0; i < 3; i++)
834 		{
835 			int err;
836 			err = arswitch_setled(sc, p->es_port-1, i, p->es_led[i]);
837 			if (err)
838 				return (err);
839 		}
840 	}
841 
842 	mii = arswitch_miiforport(sc, p->es_port);
843 	if (mii == NULL)
844 		return (ENXIO);
845 
846 	ifp = arswitch_ifpforport(sc, p->es_port);
847 
848 	ifm = &mii->mii_media;
849 	return (ifmedia_ioctl(ifp, &p->es_ifr, ifm, SIOCSIFMEDIA));
850 }
851 
852 static int
853 arswitch_setled(struct arswitch_softc *sc, int phy, int led, int style)
854 {
855 	int shift;
856 	int err;
857 
858 	if (phy < 0 || phy > sc->numphys)
859 		return EINVAL;
860 
861 	if (style < 0 || style > ETHERSWITCH_PORT_LED_MAX)
862 		return (EINVAL);
863 
864 	ARSWITCH_LOCK(sc);
865 
866 	shift = ar8327_led_mapping[phy][led].shift;
867 	err = (arswitch_modifyreg(sc->sc_dev,
868 	    ar8327_led_mapping[phy][led].reg,
869 	    0x03 << shift, led_pattern_table[style] << shift));
870 	ARSWITCH_UNLOCK(sc);
871 
872 	return (err);
873 }
874 
875 static void
876 arswitch_statchg(device_t dev)
877 {
878 	struct arswitch_softc *sc = device_get_softc(dev);
879 
880 	DPRINTF(sc, ARSWITCH_DBG_POLL, "%s\n", __func__);
881 }
882 
883 static int
884 arswitch_ifmedia_upd(struct ifnet *ifp)
885 {
886 	struct arswitch_softc *sc = ifp->if_softc;
887 	struct mii_data *mii = arswitch_miiforport(sc, ifp->if_dunit);
888 
889 	if (mii == NULL)
890 		return (ENXIO);
891 	mii_mediachg(mii);
892 	return (0);
893 }
894 
895 static void
896 arswitch_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
897 {
898 	struct arswitch_softc *sc = ifp->if_softc;
899 	struct mii_data *mii = arswitch_miiforport(sc, ifp->if_dunit);
900 
901 	DPRINTF(sc, ARSWITCH_DBG_POLL, "%s\n", __func__);
902 
903 	if (mii == NULL)
904 		return;
905 	mii_pollstat(mii);
906 	ifmr->ifm_active = mii->mii_media_active;
907 	ifmr->ifm_status = mii->mii_media_status;
908 }
909 
910 static int
911 arswitch_getconf(device_t dev, etherswitch_conf_t *conf)
912 {
913 	struct arswitch_softc *sc;
914 
915 	sc = device_get_softc(dev);
916 
917 	/* Return the VLAN mode. */
918 	conf->cmd = ETHERSWITCH_CONF_VLAN_MODE;
919 	conf->vlan_mode = sc->vlan_mode;
920 
921 	return (0);
922 }
923 
924 static int
925 arswitch_setconf(device_t dev, etherswitch_conf_t *conf)
926 {
927 	struct arswitch_softc *sc;
928 	int err;
929 
930 	sc = device_get_softc(dev);
931 
932 	/* Set the VLAN mode. */
933 	if (conf->cmd & ETHERSWITCH_CONF_VLAN_MODE) {
934 		err = arswitch_set_vlan_mode(sc, conf->vlan_mode);
935 		if (err != 0)
936 			return (err);
937 	}
938 
939 	return (0);
940 }
941 
942 static int
943 arswitch_getvgroup(device_t dev, etherswitch_vlangroup_t *e)
944 {
945 	struct arswitch_softc *sc = device_get_softc(dev);
946 
947 	return (sc->hal.arswitch_vlan_getvgroup(sc, e));
948 }
949 
950 static int
951 arswitch_setvgroup(device_t dev, etherswitch_vlangroup_t *e)
952 {
953 	struct arswitch_softc *sc = device_get_softc(dev);
954 
955 	return (sc->hal.arswitch_vlan_setvgroup(sc, e));
956 }
957 
958 static int
959 arswitch_readphy(device_t dev, int phy, int reg)
960 {
961 	struct arswitch_softc *sc = device_get_softc(dev);
962 
963 	return (sc->hal.arswitch_phy_read(dev, phy, reg));
964 }
965 
966 static int
967 arswitch_writephy(device_t dev, int phy, int reg, int val)
968 {
969 	struct arswitch_softc *sc = device_get_softc(dev);
970 
971 	return (sc->hal.arswitch_phy_write(dev, phy, reg, val));
972 }
973 
974 static device_method_t arswitch_methods[] = {
975 	/* Device interface */
976 	DEVMETHOD(device_probe,		arswitch_probe),
977 	DEVMETHOD(device_attach,	arswitch_attach),
978 	DEVMETHOD(device_detach,	arswitch_detach),
979 
980 	/* bus interface */
981 	DEVMETHOD(bus_add_child,	device_add_child_ordered),
982 
983 	/* MII interface */
984 	DEVMETHOD(miibus_readreg,	arswitch_readphy),
985 	DEVMETHOD(miibus_writereg,	arswitch_writephy),
986 	DEVMETHOD(miibus_statchg,	arswitch_statchg),
987 
988 	/* MDIO interface */
989 	DEVMETHOD(mdio_readreg,		arswitch_readphy),
990 	DEVMETHOD(mdio_writereg,	arswitch_writephy),
991 
992 	/* etherswitch interface */
993 	DEVMETHOD(etherswitch_lock,	arswitch_lock),
994 	DEVMETHOD(etherswitch_unlock,	arswitch_unlock),
995 	DEVMETHOD(etherswitch_getinfo,	arswitch_getinfo),
996 	DEVMETHOD(etherswitch_readreg,	arswitch_readreg),
997 	DEVMETHOD(etherswitch_writereg,	arswitch_writereg),
998 	DEVMETHOD(etherswitch_readphyreg,	arswitch_readphy),
999 	DEVMETHOD(etherswitch_writephyreg,	arswitch_writephy),
1000 	DEVMETHOD(etherswitch_getport,	arswitch_getport),
1001 	DEVMETHOD(etherswitch_setport,	arswitch_setport),
1002 	DEVMETHOD(etherswitch_getvgroup,	arswitch_getvgroup),
1003 	DEVMETHOD(etherswitch_setvgroup,	arswitch_setvgroup),
1004 	DEVMETHOD(etherswitch_getconf,	arswitch_getconf),
1005 	DEVMETHOD(etherswitch_setconf,	arswitch_setconf),
1006 
1007 	DEVMETHOD_END
1008 };
1009 
1010 DEFINE_CLASS_0(arswitch, arswitch_driver, arswitch_methods,
1011     sizeof(struct arswitch_softc));
1012 static devclass_t arswitch_devclass;
1013 
1014 DRIVER_MODULE(arswitch, mdio, arswitch_driver, arswitch_devclass, 0, 0);
1015 DRIVER_MODULE(miibus, arswitch, miibus_driver, miibus_devclass, 0, 0);
1016 DRIVER_MODULE(mdio, arswitch, mdio_driver, mdio_devclass, 0, 0);
1017 DRIVER_MODULE(etherswitch, arswitch, etherswitch_driver, etherswitch_devclass, 0, 0);
1018 MODULE_VERSION(arswitch, 1);
1019 MODULE_DEPEND(arswitch, miibus, 1, 1, 1); /* XXX which versions? */
1020 MODULE_DEPEND(arswitch, etherswitch, 1, 1, 1); /* XXX which versions? */
1021