xref: /freebsd/sys/dev/etherswitch/arswitch/arswitch.c (revision 8ddb146abcdf061be9f2c0db7e391697dafad85c)
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_wait_ready(struct arswitch_softc *sc)
293 {
294 	int ret;
295 
296 	ARSWITCH_LOCK_ASSERT(sc, MA_OWNED);
297 
298 	ret = arswitch_waitreg(sc->sc_dev,
299 	    AR8216_REG_ATU,
300 	    AR8216_ATU_ACTIVE,
301 	    0,
302 	    1000);
303 
304 	return (ret);
305 }
306 
307 /*
308  * Flush all ATU entries.
309  */
310 static int
311 ar8xxx_atu_flush(struct arswitch_softc *sc)
312 {
313 	int ret;
314 
315 	ARSWITCH_LOCK_ASSERT(sc, MA_OWNED);
316 
317 	DPRINTF(sc, ARSWITCH_DBG_ATU, "%s: flushing all ports\n", __func__);
318 
319 	ret = ar8xxx_atu_wait_ready(sc);
320 	if (ret)
321 		device_printf(sc->sc_dev, "%s: waitreg failed\n", __func__);
322 
323 	if (!ret)
324 		arswitch_writereg(sc->sc_dev,
325 		    AR8216_REG_ATU,
326 		    AR8216_ATU_OP_FLUSH | AR8216_ATU_ACTIVE);
327 
328 	return (ret);
329 }
330 
331 /*
332  * Flush ATU entries for a single port.
333  */
334 static int
335 ar8xxx_atu_flush_port(struct arswitch_softc *sc, int port)
336 {
337 	int ret, val;
338 
339 	DPRINTF(sc, ARSWITCH_DBG_ATU, "%s: flushing port %d\n", __func__,
340 	    port);
341 
342 	ARSWITCH_LOCK_ASSERT(sc, MA_OWNED);
343 
344 	/* Flush unicast entries on port */
345 	val = AR8216_ATU_OP_FLUSH_UNICAST;
346 
347 	/* TODO: bit 4 indicates whether to flush dynamic (0) or static (1) */
348 
349 	/* Which port */
350 	val |= SM(port, AR8216_ATU_PORT_NUM);
351 
352 	ret = ar8xxx_atu_wait_ready(sc);
353 	if (ret)
354 		device_printf(sc->sc_dev, "%s: waitreg failed\n", __func__);
355 
356 	if (!ret)
357 		arswitch_writereg(sc->sc_dev,
358 		    AR8216_REG_ATU,
359 		    val | AR8216_ATU_ACTIVE);
360 
361 	return (ret);
362 }
363 
364 /*
365  * XXX TODO: flush a single MAC address.
366  */
367 
368 /*
369  * Fetch a single entry from the ATU.
370  */
371 static int
372 ar8xxx_atu_fetch_table(struct arswitch_softc *sc, etherswitch_atu_entry_t *e,
373     int atu_fetch_op)
374 {
375 	uint32_t ret0, ret1, ret2, val;
376 
377 	ARSWITCH_LOCK_ASSERT(sc, MA_OWNED);
378 
379 	switch (atu_fetch_op) {
380 	case 0:
381 		/* Initialise things for the first fetch */
382 
383 		DPRINTF(sc, ARSWITCH_DBG_ATU, "%s: initializing\n", __func__);
384 		(void) ar8xxx_atu_wait_ready(sc);
385 
386 		arswitch_writereg(sc->sc_dev,
387 		    AR8216_REG_ATU, AR8216_ATU_OP_GET_NEXT);
388 		arswitch_writereg(sc->sc_dev,
389 		    AR8216_REG_ATU_DATA, 0);
390 		arswitch_writereg(sc->sc_dev,
391 		    AR8216_REG_ATU_CTRL2, 0);
392 
393 		return (0);
394 	case 1:
395 		DPRINTF(sc, ARSWITCH_DBG_ATU, "%s: reading next\n", __func__);
396 		/*
397 		 * Attempt to read the next address entry; don't modify what
398 		 * is there in AT_ADDR{4,5} as its used for the next fetch
399 		 */
400 		(void) ar8xxx_atu_wait_ready(sc);
401 
402 		/* Begin the next read event; not modifying anything */
403 		val = arswitch_readreg(sc->sc_dev, AR8216_REG_ATU);
404 		val |= AR8216_ATU_ACTIVE;
405 		arswitch_writereg(sc->sc_dev, AR8216_REG_ATU, val);
406 
407 		/* Wait for it to complete */
408 		(void) ar8xxx_atu_wait_ready(sc);
409 
410 		/* Fetch the ethernet address and ATU status */
411 		ret0 = arswitch_readreg(sc->sc_dev, AR8216_REG_ATU);
412 		ret1 = arswitch_readreg(sc->sc_dev, AR8216_REG_ATU_DATA);
413 		ret2 = arswitch_readreg(sc->sc_dev, AR8216_REG_ATU_CTRL2);
414 
415 		/* If the status is zero, then we're done */
416 		if (MS(ret2, AR8216_ATU_CTRL2_AT_STATUS) == 0)
417 			return (-1);
418 
419 		/* MAC address */
420 		e->es_macaddr[5] = MS(ret0, AR8216_ATU_ADDR5);
421 		e->es_macaddr[4] = MS(ret0, AR8216_ATU_ADDR4);
422 		e->es_macaddr[3] = MS(ret1, AR8216_ATU_ADDR3);
423 		e->es_macaddr[2] = MS(ret1, AR8216_ATU_ADDR2);
424 		e->es_macaddr[1] = MS(ret1, AR8216_ATU_ADDR1);
425 		e->es_macaddr[0] = MS(ret1, AR8216_ATU_ADDR0);
426 
427 		/* Bitmask of ports this entry is for */
428 		e->es_portmask = MS(ret2, AR8216_ATU_CTRL2_DESPORT);
429 
430 		/* TODO: other flags that are interesting */
431 
432 		DPRINTF(sc, ARSWITCH_DBG_ATU, "%s: MAC %6D portmask 0x%08x\n",
433 		    __func__,
434 		    e->es_macaddr, ":", e->es_portmask);
435 		return (0);
436 	default:
437 		return (-1);
438 	}
439 	return (-1);
440 }
441 
442 /*
443  * Configure aging register defaults.
444  */
445 static int
446 ar8xxx_atu_learn_default(struct arswitch_softc *sc)
447 {
448 	int ret;
449 	uint32_t val;
450 
451 	DPRINTF(sc, ARSWITCH_DBG_ATU, "%s: resetting learning\n", __func__);
452 
453 	/*
454 	 * For now, configure the aging defaults:
455 	 *
456 	 * + ARP_EN - enable "acknowledgement" of ARP frames - they are
457 	 *   forwarded to the CPU port
458 	 * + LEARN_CHANGE_EN - hash table violations when learning MAC addresses
459 	 *   will force an entry to be expired/updated and a new one to be
460 	 *   programmed in.
461 	 * + AGE_EN - enable address table aging
462 	 * + AGE_TIME - set to 5 minutes
463 	 */
464 	val = 0;
465 	val |= AR8216_ATU_CTRL_ARP_EN;
466 	val |= AR8216_ATU_CTRL_LEARN_CHANGE;
467 	val |= AR8216_ATU_CTRL_AGE_EN;
468 	val |= 0x2b;	/* 5 minutes; bits 15:0 */
469 
470 	ret = arswitch_writereg(sc->sc_dev,
471 	    AR8216_REG_ATU_CTRL,
472 	    val);
473 
474 	if (ret)
475 		device_printf(sc->sc_dev, "%s: writereg failed\n", __func__);
476 
477 	return (ret);
478 }
479 
480 /*
481  * XXX TODO: add another routine to configure the leaky behaviour
482  * when unknown frames are received.  These must be consistent
483  * between ethernet switches.
484  */
485 
486 /*
487  * Fetch the configured switch MAC address.
488  */
489 static int
490 ar8xxx_hw_get_switch_macaddr(struct arswitch_softc *sc, struct ether_addr *ea)
491 {
492 	uint32_t ret0, ret1;
493 	char *s;
494 
495 	s = (void *) ea;
496 
497 	ret0 = arswitch_readreg(sc->sc_dev, AR8X16_REG_SW_MAC_ADDR0);
498 	ret1 = arswitch_readreg(sc->sc_dev, AR8X16_REG_SW_MAC_ADDR1);
499 
500 	s[5] = MS(ret0, AR8X16_REG_SW_MAC_ADDR0_BYTE5);
501 	s[4] = MS(ret0, AR8X16_REG_SW_MAC_ADDR0_BYTE4);
502 	s[3] = MS(ret1, AR8X16_REG_SW_MAC_ADDR1_BYTE3);
503 	s[2] = MS(ret1, AR8X16_REG_SW_MAC_ADDR1_BYTE2);
504 	s[1] = MS(ret1, AR8X16_REG_SW_MAC_ADDR1_BYTE1);
505 	s[0] = MS(ret1, AR8X16_REG_SW_MAC_ADDR1_BYTE0);
506 
507 	return (0);
508 }
509 
510 /*
511  * Set the switch mac address.
512  */
513 static int
514 ar8xxx_hw_set_switch_macaddr(struct arswitch_softc *sc,
515     const struct ether_addr *ea)
516 {
517 
518 	return (ENXIO);
519 }
520 
521 /*
522  * XXX TODO: this attach routine does NOT free all memory, resources
523  * upon failure!
524  */
525 static int
526 arswitch_attach(device_t dev)
527 {
528 	struct arswitch_softc *sc = device_get_softc(dev);
529 	struct sysctl_ctx_list *ctx;
530 	struct sysctl_oid *tree;
531 	int err = 0;
532 	int port;
533 
534 	/* sc->sc_switchtype is already decided in arswitch_probe() */
535 	sc->sc_dev = dev;
536 	mtx_init(&sc->sc_mtx, "arswitch", NULL, MTX_DEF);
537 	sc->page = -1;
538 	strlcpy(sc->info.es_name, device_get_desc(dev),
539 	    sizeof(sc->info.es_name));
540 
541 	/* Debugging */
542 	ctx = device_get_sysctl_ctx(sc->sc_dev);
543 	tree = device_get_sysctl_tree(sc->sc_dev);
544 	SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
545 	    "debug", CTLFLAG_RW, &sc->sc_debug, 0,
546 	    "control debugging printfs");
547 
548 	/* Allocate a 128 entry ATU table; hopefully its big enough! */
549 	/* XXX TODO: make this per chip */
550 	sc->atu.entries = malloc(sizeof(etherswitch_atu_entry_t) * 128,
551 	    M_DEVBUF, M_NOWAIT);
552 	if (sc->atu.entries == NULL) {
553 		device_printf(sc->sc_dev, "%s: failed to allocate ATU table\n",
554 		    __func__);
555 		return (ENXIO);
556 	}
557 	sc->atu.count = 0;
558 	sc->atu.size = 128;
559 
560 	/* Default HAL methods */
561 	sc->hal.arswitch_port_init = ar8xxx_port_init;
562 	sc->hal.arswitch_port_vlan_setup = ar8xxx_port_vlan_setup;
563 	sc->hal.arswitch_port_vlan_get = ar8xxx_port_vlan_get;
564 	sc->hal.arswitch_vlan_init_hw = ar8xxx_reset_vlans;
565 	sc->hal.arswitch_hw_get_switch_macaddr = ar8xxx_hw_get_switch_macaddr;
566 	sc->hal.arswitch_hw_set_switch_macaddr = ar8xxx_hw_set_switch_macaddr;
567 
568 	sc->hal.arswitch_vlan_getvgroup = ar8xxx_getvgroup;
569 	sc->hal.arswitch_vlan_setvgroup = ar8xxx_setvgroup;
570 
571 	sc->hal.arswitch_vlan_get_pvid = ar8xxx_get_pvid;
572 	sc->hal.arswitch_vlan_set_pvid = ar8xxx_set_pvid;
573 
574 	sc->hal.arswitch_get_dot1q_vlan = ar8xxx_get_dot1q_vlan;
575 	sc->hal.arswitch_set_dot1q_vlan = ar8xxx_set_dot1q_vlan;
576 	sc->hal.arswitch_flush_dot1q_vlan = ar8xxx_flush_dot1q_vlan;
577 	sc->hal.arswitch_purge_dot1q_vlan = ar8xxx_purge_dot1q_vlan;
578 	sc->hal.arswitch_get_port_vlan = ar8xxx_get_port_vlan;
579 	sc->hal.arswitch_set_port_vlan = ar8xxx_set_port_vlan;
580 
581 	sc->hal.arswitch_atu_flush = ar8xxx_atu_flush;
582 	sc->hal.arswitch_atu_flush_port = ar8xxx_atu_flush_port;
583 	sc->hal.arswitch_atu_learn_default = ar8xxx_atu_learn_default;
584 	sc->hal.arswitch_atu_fetch_table = ar8xxx_atu_fetch_table;
585 
586 	sc->hal.arswitch_phy_read = arswitch_readphy_internal;
587 	sc->hal.arswitch_phy_write = arswitch_writephy_internal;
588 
589 	/*
590 	 * Attach switch related functions
591 	 */
592 	if (AR8X16_IS_SWITCH(sc, AR7240))
593 		ar7240_attach(sc);
594 	else if (AR8X16_IS_SWITCH(sc, AR9340))
595 		ar9340_attach(sc);
596 	else if (AR8X16_IS_SWITCH(sc, AR8216))
597 		ar8216_attach(sc);
598 	else if (AR8X16_IS_SWITCH(sc, AR8226))
599 		ar8226_attach(sc);
600 	else if (AR8X16_IS_SWITCH(sc, AR8316))
601 		ar8316_attach(sc);
602 	else if (AR8X16_IS_SWITCH(sc, AR8327))
603 		ar8327_attach(sc);
604 	else {
605 		DPRINTF(sc, ARSWITCH_DBG_ANY,
606 		    "%s: unknown switch (%d)?\n", __func__, sc->sc_switchtype);
607 		return (ENXIO);
608 	}
609 
610 	/* Common defaults. */
611 	sc->info.es_nports = 5; /* XXX technically 6, but 6th not used */
612 
613 	/* XXX Defaults for externally connected AR8316 */
614 	sc->numphys = 4;
615 	sc->phy4cpu = 1;
616 	sc->is_rgmii = 1;
617 	sc->is_gmii = 0;
618 	sc->is_mii = 0;
619 
620 	(void) resource_int_value(device_get_name(dev), device_get_unit(dev),
621 	    "numphys", &sc->numphys);
622 	(void) resource_int_value(device_get_name(dev), device_get_unit(dev),
623 	    "phy4cpu", &sc->phy4cpu);
624 	(void) resource_int_value(device_get_name(dev), device_get_unit(dev),
625 	    "is_rgmii", &sc->is_rgmii);
626 	(void) resource_int_value(device_get_name(dev), device_get_unit(dev),
627 	    "is_gmii", &sc->is_gmii);
628 	(void) resource_int_value(device_get_name(dev), device_get_unit(dev),
629 	    "is_mii", &sc->is_mii);
630 
631 	if (sc->numphys > AR8X16_NUM_PHYS)
632 		sc->numphys = AR8X16_NUM_PHYS;
633 
634 	/* Reset the switch. */
635 	if (arswitch_reset(dev)) {
636 		DPRINTF(sc, ARSWITCH_DBG_ANY,
637 		    "%s: arswitch_reset: failed\n", __func__);
638 		return (ENXIO);
639 	}
640 
641 	err = sc->hal.arswitch_hw_setup(sc);
642 	if (err != 0) {
643 		DPRINTF(sc, ARSWITCH_DBG_ANY,
644 		    "%s: hw_setup: err=%d\n", __func__, err);
645 		return (err);
646 	}
647 
648 	err = sc->hal.arswitch_hw_global_setup(sc);
649 	if (err != 0) {
650 		DPRINTF(sc, ARSWITCH_DBG_ANY,
651 		    "%s: hw_global_setup: err=%d\n", __func__, err);
652 		return (err);
653 	}
654 
655 	/*
656 	 * Configure the default address table learning parameters for this
657 	 * switch.
658 	 */
659 	err = sc->hal.arswitch_atu_learn_default(sc);
660 	if (err != 0) {
661 		DPRINTF(sc, ARSWITCH_DBG_ANY,
662 		    "%s: atu_learn_default: err=%d\n", __func__, err);
663 		return (err);
664 	}
665 
666 	/* Initialize the switch ports. */
667 	for (port = 0; port <= sc->numphys; port++) {
668 		sc->hal.arswitch_port_init(sc, port);
669 	}
670 
671 	/*
672 	 * Attach the PHYs and complete the bus enumeration.
673 	 */
674 	err = arswitch_attach_phys(sc);
675 	if (err != 0) {
676 		DPRINTF(sc, ARSWITCH_DBG_ANY,
677 		    "%s: attach_phys: err=%d\n", __func__, err);
678 		return (err);
679 	}
680 
681 	/* Default to ingress filters off. */
682 	err = arswitch_set_vlan_mode(sc, 0);
683 	if (err != 0) {
684 		DPRINTF(sc, ARSWITCH_DBG_ANY,
685 		    "%s: set_vlan_mode: err=%d\n", __func__, err);
686 		return (err);
687 	}
688 
689 	bus_generic_probe(dev);
690 	bus_enumerate_hinted_children(dev);
691 	err = bus_generic_attach(dev);
692 	if (err != 0) {
693 		DPRINTF(sc, ARSWITCH_DBG_ANY,
694 		    "%s: bus_generic_attach: err=%d\n", __func__, err);
695 		return (err);
696 	}
697 
698 	callout_init_mtx(&sc->callout_tick, &sc->sc_mtx, 0);
699 
700 	ARSWITCH_LOCK(sc);
701 	arswitch_tick(sc);
702 	ARSWITCH_UNLOCK(sc);
703 
704 	return (err);
705 }
706 
707 static int
708 arswitch_detach(device_t dev)
709 {
710 	struct arswitch_softc *sc = device_get_softc(dev);
711 	int i;
712 
713 	callout_drain(&sc->callout_tick);
714 
715 	for (i=0; i < sc->numphys; i++) {
716 		if (sc->miibus[i] != NULL)
717 			device_delete_child(dev, sc->miibus[i]);
718 		if (sc->ifp[i] != NULL)
719 			if_free(sc->ifp[i]);
720 		free(sc->ifname[i], M_DEVBUF);
721 	}
722 
723 	free(sc->atu.entries, M_DEVBUF);
724 
725 	bus_generic_detach(dev);
726 	mtx_destroy(&sc->sc_mtx);
727 
728 	return (0);
729 }
730 
731 /*
732  * Convert PHY number to port number. PHY0 is connected to port 1, PHY1 to
733  * port 2, etc.
734  */
735 static inline int
736 arswitch_portforphy(int phy)
737 {
738 	return (phy+1);
739 }
740 
741 static inline struct mii_data *
742 arswitch_miiforport(struct arswitch_softc *sc, int port)
743 {
744 	int phy = port-1;
745 
746 	if (phy < 0 || phy >= sc->numphys)
747 		return (NULL);
748 	return (device_get_softc(sc->miibus[phy]));
749 }
750 
751 static inline struct ifnet *
752 arswitch_ifpforport(struct arswitch_softc *sc, int port)
753 {
754 	int phy = port-1;
755 
756 	if (phy < 0 || phy >= sc->numphys)
757 		return (NULL);
758 	return (sc->ifp[phy]);
759 }
760 
761 /*
762  * Convert port status to ifmedia.
763  */
764 static void
765 arswitch_update_ifmedia(int portstatus, u_int *media_status, u_int *media_active)
766 {
767 	*media_active = IFM_ETHER;
768 	*media_status = IFM_AVALID;
769 
770 	if ((portstatus & AR8X16_PORT_STS_LINK_UP) != 0)
771 		*media_status |= IFM_ACTIVE;
772 	else {
773 		*media_active |= IFM_NONE;
774 		return;
775 	}
776 	switch (portstatus & AR8X16_PORT_STS_SPEED_MASK) {
777 	case AR8X16_PORT_STS_SPEED_10:
778 		*media_active |= IFM_10_T;
779 		break;
780 	case AR8X16_PORT_STS_SPEED_100:
781 		*media_active |= IFM_100_TX;
782 		break;
783 	case AR8X16_PORT_STS_SPEED_1000:
784 		*media_active |= IFM_1000_T;
785 		break;
786 	}
787 	if ((portstatus & AR8X16_PORT_STS_DUPLEX) == 0)
788 		*media_active |= IFM_FDX;
789 	else
790 		*media_active |= IFM_HDX;
791 	if ((portstatus & AR8X16_PORT_STS_TXFLOW) != 0)
792 		*media_active |= IFM_ETH_TXPAUSE;
793 	if ((portstatus & AR8X16_PORT_STS_RXFLOW) != 0)
794 		*media_active |= IFM_ETH_RXPAUSE;
795 }
796 
797 /*
798  * Poll the status for all PHYs.  We're using the switch port status because
799  * thats a lot quicker to read than talking to all the PHYs.  Care must be
800  * taken that the resulting ifmedia_active is identical to what the PHY will
801  * compute, or gratuitous link status changes will occur whenever the PHYs
802  * update function is called.
803  */
804 static void
805 arswitch_miipollstat(struct arswitch_softc *sc)
806 {
807 	int i;
808 	struct mii_data *mii;
809 	struct mii_softc *miisc;
810 	int portstatus;
811 	int port_flap = 0;
812 
813 	ARSWITCH_LOCK_ASSERT(sc, MA_OWNED);
814 
815 	for (i = 0; i < sc->numphys; i++) {
816 		if (sc->miibus[i] == NULL)
817 			continue;
818 		mii = device_get_softc(sc->miibus[i]);
819 		/* XXX This would be nice to have abstracted out to be per-chip */
820 		/* AR8327/AR8337 has a different register base */
821 		if (AR8X16_IS_SWITCH(sc, AR8327))
822 			portstatus = arswitch_readreg(sc->sc_dev,
823 			    AR8327_REG_PORT_STATUS(arswitch_portforphy(i)));
824 		else
825 			portstatus = arswitch_readreg(sc->sc_dev,
826 			    AR8X16_REG_PORT_STS(arswitch_portforphy(i)));
827 #if 1
828 		DPRINTF(sc, ARSWITCH_DBG_POLL, "p[%d]=0x%08x (%b)\n",
829 		    i,
830 		    portstatus,
831 		    portstatus,
832 		    "\20\3TXMAC\4RXMAC\5TXFLOW\6RXFLOW\7"
833 		    "DUPLEX\11LINK_UP\12LINK_AUTO\13LINK_PAUSE");
834 #endif
835 		/*
836 		 * If the current status is down, but we have a link
837 		 * status showing up, we need to do an ATU flush.
838 		 */
839 		if ((mii->mii_media_status & IFM_ACTIVE) == 0 &&
840 		    (portstatus & AR8X16_PORT_STS_LINK_UP) != 0) {
841 			device_printf(sc->sc_dev, "%s: port %d: port -> UP\n",
842 			    __func__,
843 			    i);
844 			port_flap = 1;
845 		}
846 		/*
847 		 * and maybe if a port goes up->down?
848 		 */
849 		if ((mii->mii_media_status & IFM_ACTIVE) != 0 &&
850 		    (portstatus & AR8X16_PORT_STS_LINK_UP) == 0) {
851 			device_printf(sc->sc_dev, "%s: port %d: port -> DOWN\n",
852 			    __func__,
853 			    i);
854 			port_flap = 1;
855 		}
856 		arswitch_update_ifmedia(portstatus, &mii->mii_media_status,
857 		    &mii->mii_media_active);
858 		LIST_FOREACH(miisc, &mii->mii_phys, mii_list) {
859 			if (IFM_INST(mii->mii_media.ifm_cur->ifm_media) !=
860 			    miisc->mii_inst)
861 				continue;
862 			mii_phy_update(miisc, MII_POLLSTAT);
863 		}
864 	}
865 
866 	/* If a port went from down->up, flush the ATU */
867 	if (port_flap)
868 		sc->hal.arswitch_atu_flush(sc);
869 }
870 
871 static void
872 arswitch_tick(void *arg)
873 {
874 	struct arswitch_softc *sc = arg;
875 
876 	arswitch_miipollstat(sc);
877 	callout_reset(&sc->callout_tick, hz, arswitch_tick, sc);
878 }
879 
880 static void
881 arswitch_lock(device_t dev)
882 {
883 	struct arswitch_softc *sc = device_get_softc(dev);
884 
885 	ARSWITCH_LOCK_ASSERT(sc, MA_NOTOWNED);
886 	ARSWITCH_LOCK(sc);
887 }
888 
889 static void
890 arswitch_unlock(device_t dev)
891 {
892 	struct arswitch_softc *sc = device_get_softc(dev);
893 
894 	ARSWITCH_LOCK_ASSERT(sc, MA_OWNED);
895 	ARSWITCH_UNLOCK(sc);
896 }
897 
898 static etherswitch_info_t *
899 arswitch_getinfo(device_t dev)
900 {
901 	struct arswitch_softc *sc = device_get_softc(dev);
902 
903 	return (&sc->info);
904 }
905 
906 static int
907 ar8xxx_port_vlan_get(struct arswitch_softc *sc, etherswitch_port_t *p)
908 {
909 	uint32_t reg;
910 
911 	ARSWITCH_LOCK(sc);
912 
913 	/* Retrieve the PVID. */
914 	sc->hal.arswitch_vlan_get_pvid(sc, p->es_port, &p->es_pvid);
915 
916 	/* Port flags. */
917 	reg = arswitch_readreg(sc->sc_dev, AR8X16_REG_PORT_CTRL(p->es_port));
918 	if (reg & AR8X16_PORT_CTRL_DOUBLE_TAG)
919 		p->es_flags |= ETHERSWITCH_PORT_DOUBLE_TAG;
920 	reg >>= AR8X16_PORT_CTRL_EGRESS_VLAN_MODE_SHIFT;
921 	if ((reg & 0x3) == AR8X16_PORT_CTRL_EGRESS_VLAN_MODE_ADD)
922 		p->es_flags |= ETHERSWITCH_PORT_ADDTAG;
923 	if ((reg & 0x3) == AR8X16_PORT_CTRL_EGRESS_VLAN_MODE_STRIP)
924 		p->es_flags |= ETHERSWITCH_PORT_STRIPTAG;
925 	ARSWITCH_UNLOCK(sc);
926 
927 	return (0);
928 }
929 
930 static int
931 arswitch_is_cpuport(struct arswitch_softc *sc, int port)
932 {
933 
934 	return ((port == AR8X16_PORT_CPU) ||
935 	    ((AR8X16_IS_SWITCH(sc, AR8327) &&
936 	      port == AR8327_PORT_GMAC6)));
937 }
938 
939 static int
940 arswitch_getport(device_t dev, etherswitch_port_t *p)
941 {
942 	struct arswitch_softc *sc;
943 	struct mii_data *mii;
944 	struct ifmediareq *ifmr;
945 	int err;
946 
947 	sc = device_get_softc(dev);
948 	/* XXX +1 is for AR8327; should make this configurable! */
949 	if (p->es_port < 0 || p->es_port > sc->info.es_nports)
950 		return (ENXIO);
951 
952 	err = sc->hal.arswitch_port_vlan_get(sc, p);
953 	if (err != 0)
954 		return (err);
955 
956 	mii = arswitch_miiforport(sc, p->es_port);
957 	if (arswitch_is_cpuport(sc, p->es_port)) {
958 		/* fill in fixed values for CPU port */
959 		/* XXX is this valid in all cases? */
960 		p->es_flags |= ETHERSWITCH_PORT_CPU;
961 		ifmr = &p->es_ifmr;
962 		ifmr->ifm_count = 0;
963 		ifmr->ifm_current = ifmr->ifm_active =
964 		    IFM_ETHER | IFM_1000_T | IFM_FDX;
965 		ifmr->ifm_mask = 0;
966 		ifmr->ifm_status = IFM_ACTIVE | IFM_AVALID;
967 	} else if (mii != NULL) {
968 		err = ifmedia_ioctl(mii->mii_ifp, &p->es_ifr,
969 		    &mii->mii_media, SIOCGIFMEDIA);
970 		if (err)
971 			return (err);
972 	} else {
973 		return (ENXIO);
974 	}
975 
976 	if (!arswitch_is_cpuport(sc, p->es_port) &&
977 	    AR8X16_IS_SWITCH(sc, AR8327)) {
978 		int led;
979 		p->es_nleds = 3;
980 
981 		for (led = 0; led < p->es_nleds; led++)
982 		{
983 			int style;
984 			uint32_t val;
985 
986 			/* Find the right style enum for our pattern */
987 			val = arswitch_readreg(dev,
988 			    ar8327_led_mapping[p->es_port-1][led].reg);
989 			val = (val>>ar8327_led_mapping[p->es_port-1][led].shift)&0x03;
990 
991 			for (style = 0; style < ETHERSWITCH_PORT_LED_MAX; style++)
992 			{
993 				if (led_pattern_table[style] == val) break;
994 			}
995 
996 			/* can't happen */
997 			if (style == ETHERSWITCH_PORT_LED_MAX)
998 				style = ETHERSWITCH_PORT_LED_DEFAULT;
999 
1000 			p->es_led[led] = style;
1001 		}
1002 	} else
1003 	{
1004 		p->es_nleds = 0;
1005 	}
1006 
1007 	return (0);
1008 }
1009 
1010 static int
1011 ar8xxx_port_vlan_setup(struct arswitch_softc *sc, etherswitch_port_t *p)
1012 {
1013 	uint32_t reg;
1014 	int err;
1015 
1016 	ARSWITCH_LOCK(sc);
1017 
1018 	/* Set the PVID. */
1019 	if (p->es_pvid != 0)
1020 		sc->hal.arswitch_vlan_set_pvid(sc, p->es_port, p->es_pvid);
1021 
1022 	/* Mutually exclusive. */
1023 	if (p->es_flags & ETHERSWITCH_PORT_ADDTAG &&
1024 	    p->es_flags & ETHERSWITCH_PORT_STRIPTAG) {
1025 		ARSWITCH_UNLOCK(sc);
1026 		return (EINVAL);
1027 	}
1028 
1029 	reg = 0;
1030 	if (p->es_flags & ETHERSWITCH_PORT_DOUBLE_TAG)
1031 		reg |= AR8X16_PORT_CTRL_DOUBLE_TAG;
1032 	if (p->es_flags & ETHERSWITCH_PORT_ADDTAG)
1033 		reg |= AR8X16_PORT_CTRL_EGRESS_VLAN_MODE_ADD <<
1034 		    AR8X16_PORT_CTRL_EGRESS_VLAN_MODE_SHIFT;
1035 	if (p->es_flags & ETHERSWITCH_PORT_STRIPTAG)
1036 		reg |= AR8X16_PORT_CTRL_EGRESS_VLAN_MODE_STRIP <<
1037 		    AR8X16_PORT_CTRL_EGRESS_VLAN_MODE_SHIFT;
1038 
1039 	err = arswitch_modifyreg(sc->sc_dev,
1040 	    AR8X16_REG_PORT_CTRL(p->es_port),
1041 	    0x3 << AR8X16_PORT_CTRL_EGRESS_VLAN_MODE_SHIFT |
1042 	    AR8X16_PORT_CTRL_DOUBLE_TAG, reg);
1043 
1044 	ARSWITCH_UNLOCK(sc);
1045 	return (err);
1046 }
1047 
1048 static int
1049 arswitch_setport(device_t dev, etherswitch_port_t *p)
1050 {
1051 	int err, i;
1052 	struct arswitch_softc *sc;
1053 	struct ifmedia *ifm;
1054 	struct mii_data *mii;
1055 	struct ifnet *ifp;
1056 
1057 	sc = device_get_softc(dev);
1058 	if (p->es_port < 0 || p->es_port > sc->info.es_nports)
1059 		return (ENXIO);
1060 
1061 	/* Port flags. */
1062 	if (sc->vlan_mode == ETHERSWITCH_VLAN_DOT1Q) {
1063 		err = sc->hal.arswitch_port_vlan_setup(sc, p);
1064 		if (err)
1065 			return (err);
1066 	}
1067 
1068 	/* Do not allow media or led changes on CPU port. */
1069 	if (arswitch_is_cpuport(sc, p->es_port))
1070 		return (0);
1071 
1072 	if (AR8X16_IS_SWITCH(sc, AR8327))
1073 	{
1074 		for (i = 0; i < 3; i++)
1075 		{
1076 			int err;
1077 			err = arswitch_setled(sc, p->es_port-1, i, p->es_led[i]);
1078 			if (err)
1079 				return (err);
1080 		}
1081 	}
1082 
1083 	mii = arswitch_miiforport(sc, p->es_port);
1084 	if (mii == NULL)
1085 		return (ENXIO);
1086 
1087 	ifp = arswitch_ifpforport(sc, p->es_port);
1088 
1089 	ifm = &mii->mii_media;
1090 	return (ifmedia_ioctl(ifp, &p->es_ifr, ifm, SIOCSIFMEDIA));
1091 }
1092 
1093 static int
1094 arswitch_setled(struct arswitch_softc *sc, int phy, int led, int style)
1095 {
1096 	int shift;
1097 	int err;
1098 
1099 	if (phy < 0 || phy > sc->numphys)
1100 		return EINVAL;
1101 
1102 	if (style < 0 || style > ETHERSWITCH_PORT_LED_MAX)
1103 		return (EINVAL);
1104 
1105 	ARSWITCH_LOCK(sc);
1106 
1107 	shift = ar8327_led_mapping[phy][led].shift;
1108 	err = (arswitch_modifyreg(sc->sc_dev,
1109 	    ar8327_led_mapping[phy][led].reg,
1110 	    0x03 << shift, led_pattern_table[style] << shift));
1111 	ARSWITCH_UNLOCK(sc);
1112 
1113 	return (err);
1114 }
1115 
1116 static void
1117 arswitch_statchg(device_t dev)
1118 {
1119 	struct arswitch_softc *sc = device_get_softc(dev);
1120 
1121 	DPRINTF(sc, ARSWITCH_DBG_POLL, "%s\n", __func__);
1122 }
1123 
1124 static int
1125 arswitch_ifmedia_upd(struct ifnet *ifp)
1126 {
1127 	struct arswitch_softc *sc = ifp->if_softc;
1128 	struct mii_data *mii = arswitch_miiforport(sc, ifp->if_dunit);
1129 
1130 	if (mii == NULL)
1131 		return (ENXIO);
1132 	mii_mediachg(mii);
1133 	return (0);
1134 }
1135 
1136 static void
1137 arswitch_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
1138 {
1139 	struct arswitch_softc *sc = ifp->if_softc;
1140 	struct mii_data *mii = arswitch_miiforport(sc, ifp->if_dunit);
1141 
1142 	DPRINTF(sc, ARSWITCH_DBG_POLL, "%s\n", __func__);
1143 
1144 	if (mii == NULL)
1145 		return;
1146 	mii_pollstat(mii);
1147 	ifmr->ifm_active = mii->mii_media_active;
1148 	ifmr->ifm_status = mii->mii_media_status;
1149 }
1150 
1151 static int
1152 arswitch_getconf(device_t dev, etherswitch_conf_t *conf)
1153 {
1154 	struct arswitch_softc *sc;
1155 	int ret;
1156 
1157 	sc = device_get_softc(dev);
1158 
1159 	/* Return the VLAN mode. */
1160 	conf->cmd = ETHERSWITCH_CONF_VLAN_MODE;
1161 	conf->vlan_mode = sc->vlan_mode;
1162 
1163 	/* Return the switch ethernet address. */
1164 	ret = sc->hal.arswitch_hw_get_switch_macaddr(sc,
1165 	    &conf->switch_macaddr);
1166 	if (ret == 0) {
1167 		conf->cmd |= ETHERSWITCH_CONF_SWITCH_MACADDR;
1168 	}
1169 
1170 	return (0);
1171 }
1172 
1173 static int
1174 arswitch_setconf(device_t dev, etherswitch_conf_t *conf)
1175 {
1176 	struct arswitch_softc *sc;
1177 	int err;
1178 
1179 	sc = device_get_softc(dev);
1180 
1181 	/* Set the VLAN mode. */
1182 	if (conf->cmd & ETHERSWITCH_CONF_VLAN_MODE) {
1183 		err = arswitch_set_vlan_mode(sc, conf->vlan_mode);
1184 		if (err != 0)
1185 			return (err);
1186 	}
1187 
1188 	/* TODO: Set the switch ethernet address. */
1189 
1190 	return (0);
1191 }
1192 
1193 static int
1194 arswitch_atu_flush_all(device_t dev)
1195 {
1196 	struct arswitch_softc *sc;
1197 	int err;
1198 
1199 	sc = device_get_softc(dev);
1200 	ARSWITCH_LOCK(sc);
1201 	err = sc->hal.arswitch_atu_flush(sc);
1202 	/* Invalidate cached ATU */
1203 	sc->atu.count = 0;
1204 	ARSWITCH_UNLOCK(sc);
1205 	return (err);
1206 }
1207 
1208 static int
1209 arswitch_atu_flush_port(device_t dev, int port)
1210 {
1211 	struct arswitch_softc *sc;
1212 	int err;
1213 
1214 	sc = device_get_softc(dev);
1215 	ARSWITCH_LOCK(sc);
1216 	err = sc->hal.arswitch_atu_flush_port(sc, port);
1217 	/* Invalidate cached ATU */
1218 	sc->atu.count = 0;
1219 	ARSWITCH_UNLOCK(sc);
1220 	return (err);
1221 }
1222 
1223 static int
1224 arswitch_atu_fetch_table(device_t dev, etherswitch_atu_table_t *table)
1225 {
1226 	struct arswitch_softc *sc;
1227 	int err, nitems;
1228 
1229 	sc = device_get_softc(dev);
1230 
1231 	ARSWITCH_LOCK(sc);
1232 	/* Initial setup */
1233 	nitems = 0;
1234 	err = sc->hal.arswitch_atu_fetch_table(sc, NULL, 0);
1235 
1236 	/* fetch - ideally yes we'd fetch into a separate table then switch */
1237 	while (err == 0 && nitems < sc->atu.size) {
1238 		err = sc->hal.arswitch_atu_fetch_table(sc,
1239 		    &sc->atu.entries[nitems], 1);
1240 		if (err == 0) {
1241 			sc->atu.entries[nitems].id = nitems;
1242 			nitems++;
1243 		}
1244 	}
1245 	sc->atu.count = nitems;
1246 	ARSWITCH_UNLOCK(sc);
1247 
1248 	table->es_nitems = nitems;
1249 
1250 	return (0);
1251 }
1252 
1253 static int
1254 arswitch_atu_fetch_table_entry(device_t dev, etherswitch_atu_entry_t *e)
1255 {
1256 	struct arswitch_softc *sc;
1257 	int id;
1258 
1259 	sc = device_get_softc(dev);
1260 	id = e->id;
1261 
1262 	ARSWITCH_LOCK(sc);
1263 	if (id > sc->atu.count) {
1264 		ARSWITCH_UNLOCK(sc);
1265 		return (ENOENT);
1266 	}
1267 
1268 	memcpy(e, &sc->atu.entries[id], sizeof(*e));
1269 	ARSWITCH_UNLOCK(sc);
1270 	return (0);
1271 }
1272 
1273 static int
1274 arswitch_getvgroup(device_t dev, etherswitch_vlangroup_t *e)
1275 {
1276 	struct arswitch_softc *sc = device_get_softc(dev);
1277 
1278 	return (sc->hal.arswitch_vlan_getvgroup(sc, e));
1279 }
1280 
1281 static int
1282 arswitch_setvgroup(device_t dev, etherswitch_vlangroup_t *e)
1283 {
1284 	struct arswitch_softc *sc = device_get_softc(dev);
1285 
1286 	return (sc->hal.arswitch_vlan_setvgroup(sc, e));
1287 }
1288 
1289 static int
1290 arswitch_readphy(device_t dev, int phy, int reg)
1291 {
1292 	struct arswitch_softc *sc = device_get_softc(dev);
1293 
1294 	return (sc->hal.arswitch_phy_read(dev, phy, reg));
1295 }
1296 
1297 static int
1298 arswitch_writephy(device_t dev, int phy, int reg, int val)
1299 {
1300 	struct arswitch_softc *sc = device_get_softc(dev);
1301 
1302 	return (sc->hal.arswitch_phy_write(dev, phy, reg, val));
1303 }
1304 
1305 static device_method_t arswitch_methods[] = {
1306 	/* Device interface */
1307 	DEVMETHOD(device_probe,		arswitch_probe),
1308 	DEVMETHOD(device_attach,	arswitch_attach),
1309 	DEVMETHOD(device_detach,	arswitch_detach),
1310 
1311 	/* bus interface */
1312 	DEVMETHOD(bus_add_child,	device_add_child_ordered),
1313 
1314 	/* MII interface */
1315 	DEVMETHOD(miibus_readreg,	arswitch_readphy),
1316 	DEVMETHOD(miibus_writereg,	arswitch_writephy),
1317 	DEVMETHOD(miibus_statchg,	arswitch_statchg),
1318 
1319 	/* MDIO interface */
1320 	DEVMETHOD(mdio_readreg,		arswitch_readphy),
1321 	DEVMETHOD(mdio_writereg,	arswitch_writephy),
1322 
1323 	/* etherswitch interface */
1324 	DEVMETHOD(etherswitch_lock,	arswitch_lock),
1325 	DEVMETHOD(etherswitch_unlock,	arswitch_unlock),
1326 	DEVMETHOD(etherswitch_getinfo,	arswitch_getinfo),
1327 	DEVMETHOD(etherswitch_readreg,	arswitch_readreg),
1328 	DEVMETHOD(etherswitch_writereg,	arswitch_writereg),
1329 	DEVMETHOD(etherswitch_readphyreg,	arswitch_readphy),
1330 	DEVMETHOD(etherswitch_writephyreg,	arswitch_writephy),
1331 	DEVMETHOD(etherswitch_getport,	arswitch_getport),
1332 	DEVMETHOD(etherswitch_setport,	arswitch_setport),
1333 	DEVMETHOD(etherswitch_getvgroup,	arswitch_getvgroup),
1334 	DEVMETHOD(etherswitch_setvgroup,	arswitch_setvgroup),
1335 	DEVMETHOD(etherswitch_getconf,	arswitch_getconf),
1336 	DEVMETHOD(etherswitch_setconf,	arswitch_setconf),
1337 	DEVMETHOD(etherswitch_flush_all, arswitch_atu_flush_all),
1338 	DEVMETHOD(etherswitch_flush_port, arswitch_atu_flush_port),
1339 	DEVMETHOD(etherswitch_fetch_table, arswitch_atu_fetch_table),
1340 	DEVMETHOD(etherswitch_fetch_table_entry, arswitch_atu_fetch_table_entry),
1341 
1342 	DEVMETHOD_END
1343 };
1344 
1345 DEFINE_CLASS_0(arswitch, arswitch_driver, arswitch_methods,
1346     sizeof(struct arswitch_softc));
1347 
1348 DRIVER_MODULE(arswitch, mdio, arswitch_driver, 0, 0);
1349 DRIVER_MODULE(miibus, arswitch, miibus_driver, 0, 0);
1350 DRIVER_MODULE(mdio, arswitch, mdio_driver, 0, 0);
1351 DRIVER_MODULE(etherswitch, arswitch, etherswitch_driver, 0, 0);
1352 MODULE_VERSION(arswitch, 1);
1353 MODULE_DEPEND(arswitch, miibus, 1, 1, 1); /* XXX which versions? */
1354 MODULE_DEPEND(arswitch, etherswitch, 1, 1, 1); /* XXX which versions? */
1355