1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
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
30 #include <sys/param.h>
31 #include <sys/bus.h>
32 #include <sys/errno.h>
33 #include <sys/kernel.h>
34 #include <sys/malloc.h>
35 #include <sys/module.h>
36 #include <sys/socket.h>
37 #include <sys/sockio.h>
38 #include <sys/sysctl.h>
39 #include <sys/systm.h>
40
41 #include <net/if.h>
42 #include <net/if_var.h>
43 #include <net/if_arp.h>
44 #include <net/ethernet.h>
45 #include <net/if_dl.h>
46 #include <net/if_media.h>
47 #include <net/if_types.h>
48
49 #include <machine/bus.h>
50 #include <dev/iicbus/iic.h>
51 #include <dev/iicbus/iiconf.h>
52 #include <dev/iicbus/iicbus.h>
53 #include <dev/mii/mii.h>
54 #include <dev/mii/miivar.h>
55 #include <dev/mdio/mdio.h>
56
57 #include <dev/etherswitch/etherswitch.h>
58
59 #include <dev/etherswitch/arswitch/arswitchreg.h>
60 #include <dev/etherswitch/arswitch/arswitchvar.h>
61 #include <dev/etherswitch/arswitch/arswitch_reg.h>
62 #include <dev/etherswitch/arswitch/arswitch_phy.h>
63 #include <dev/etherswitch/arswitch/arswitch_vlans.h>
64
65 #include <dev/etherswitch/arswitch/arswitch_8216.h>
66 #include <dev/etherswitch/arswitch/arswitch_8226.h>
67 #include <dev/etherswitch/arswitch/arswitch_8316.h>
68 #include <dev/etherswitch/arswitch/arswitch_8327.h>
69
70 #include "mdio_if.h"
71 #include "miibus_if.h"
72 #include "etherswitch_if.h"
73
74 /* Map ETHERSWITCH_PORT_LED_* to Atheros pattern codes */
75 static int led_pattern_table[] = {
76 [ETHERSWITCH_PORT_LED_DEFAULT] = 0x3,
77 [ETHERSWITCH_PORT_LED_ON] = 0x2,
78 [ETHERSWITCH_PORT_LED_OFF] = 0x0,
79 [ETHERSWITCH_PORT_LED_BLINK] = 0x1
80 };
81
82 static inline int arswitch_portforphy(int phy);
83 static void arswitch_tick(void *arg);
84 static int arswitch_ifmedia_upd(if_t);
85 static void arswitch_ifmedia_sts(if_t, struct ifmediareq *);
86 static int ar8xxx_port_vlan_setup(struct arswitch_softc *sc,
87 etherswitch_port_t *p);
88 static int ar8xxx_port_vlan_get(struct arswitch_softc *sc,
89 etherswitch_port_t *p);
90 static int arswitch_setled(struct arswitch_softc *sc, int phy, int led,
91 int style);
92
93 static int
arswitch_probe(device_t dev)94 arswitch_probe(device_t dev)
95 {
96 struct arswitch_softc *sc;
97 uint32_t id;
98 char *chipname, desc[256];
99
100 sc = device_get_softc(dev);
101 bzero(sc, sizeof(*sc));
102 sc->page = -1;
103
104 /* AR8xxx probe */
105 id = arswitch_readreg(dev, AR8X16_REG_MASK_CTRL);
106 sc->chip_rev = (id & AR8X16_MASK_CTRL_REV_MASK);
107 sc->chip_ver = (id & AR8X16_MASK_CTRL_VER_MASK) >> AR8X16_MASK_CTRL_VER_SHIFT;
108 switch (id & (AR8X16_MASK_CTRL_VER_MASK | AR8X16_MASK_CTRL_REV_MASK)) {
109 case 0x0101:
110 chipname = "AR8216";
111 sc->sc_switchtype = AR8X16_SWITCH_AR8216;
112 break;
113 case 0x0201:
114 chipname = "AR8226";
115 sc->sc_switchtype = AR8X16_SWITCH_AR8226;
116 break;
117 /* 0x0301 - AR8236 */
118 case 0x1000:
119 case 0x1001:
120 chipname = "AR8316";
121 sc->sc_switchtype = AR8X16_SWITCH_AR8316;
122 break;
123 case 0x1202:
124 case 0x1204:
125 chipname = "AR8327";
126 sc->sc_switchtype = AR8X16_SWITCH_AR8327;
127 sc->mii_lo_first = 1;
128 break;
129 default:
130 chipname = NULL;
131 }
132
133 DPRINTF(sc, ARSWITCH_DBG_ANY, "chipname=%s, id=%08x\n", chipname, id);
134 if (chipname != NULL) {
135 snprintf(desc, sizeof(desc),
136 "Atheros %s Ethernet Switch (ver %d rev %d)",
137 chipname,
138 sc->chip_ver,
139 sc->chip_rev);
140 device_set_desc_copy(dev, desc);
141 return (BUS_PROBE_DEFAULT);
142 }
143 return (ENXIO);
144 }
145
146 static int
arswitch_attach_phys(struct arswitch_softc * sc)147 arswitch_attach_phys(struct arswitch_softc *sc)
148 {
149 int phy, err = 0;
150 char name[IFNAMSIZ];
151
152 /* PHYs need an interface, so we generate a dummy one */
153 snprintf(name, IFNAMSIZ, "%sport", device_get_nameunit(sc->sc_dev));
154 for (phy = 0; phy < sc->numphys; phy++) {
155 sc->ifp[phy] = if_alloc(IFT_ETHER);
156 if (sc->ifp[phy] == NULL) {
157 device_printf(sc->sc_dev, "couldn't allocate ifnet structure\n");
158 err = ENOMEM;
159 break;
160 }
161
162 if_setsoftc(sc->ifp[phy], sc);
163 if_setflagbits(sc->ifp[phy], IFF_UP | IFF_BROADCAST |
164 IFF_DRV_RUNNING | IFF_SIMPLEX, 0);
165 sc->ifname[phy] = malloc(strlen(name)+1, M_DEVBUF, M_WAITOK);
166 bcopy(name, sc->ifname[phy], strlen(name)+1);
167 if_initname(sc->ifp[phy], sc->ifname[phy],
168 arswitch_portforphy(phy));
169 err = mii_attach(sc->sc_dev, &sc->miibus[phy], sc->ifp[phy],
170 arswitch_ifmedia_upd, arswitch_ifmedia_sts, \
171 BMSR_DEFCAPMASK, phy, MII_OFFSET_ANY, 0);
172 #if 0
173 DPRINTF(sc->sc_dev, "%s attached to pseudo interface %s\n",
174 device_get_nameunit(sc->miibus[phy]),
175 sc->ifp[phy]->if_xname);
176 #endif
177 if (err != 0) {
178 device_printf(sc->sc_dev,
179 "attaching PHY %d failed\n",
180 phy);
181 return (err);
182 }
183
184 if (AR8X16_IS_SWITCH(sc, AR8327)) {
185 int led;
186 char ledname[IFNAMSIZ+4];
187
188 for (led = 0; led < 3; led++) {
189 sprintf(ledname, "%s%dled%d", name,
190 arswitch_portforphy(phy), led+1);
191 sc->dev_led[phy][led].sc = sc;
192 sc->dev_led[phy][led].phy = phy;
193 sc->dev_led[phy][led].lednum = led;
194 }
195 }
196 }
197 return (0);
198 }
199
200 static int
arswitch_reset(device_t dev)201 arswitch_reset(device_t dev)
202 {
203
204 arswitch_writereg(dev, AR8X16_REG_MASK_CTRL,
205 AR8X16_MASK_CTRL_SOFT_RESET);
206 DELAY(1000);
207 if (arswitch_readreg(dev, AR8X16_REG_MASK_CTRL) &
208 AR8X16_MASK_CTRL_SOFT_RESET) {
209 device_printf(dev, "unable to reset switch\n");
210 return (-1);
211 }
212 return (0);
213 }
214
215 static int
arswitch_set_vlan_mode(struct arswitch_softc * sc,uint32_t mode)216 arswitch_set_vlan_mode(struct arswitch_softc *sc, uint32_t mode)
217 {
218
219 /* Check for invalid modes. */
220 if ((mode & sc->info.es_vlan_caps) != mode)
221 return (EINVAL);
222
223 switch (mode) {
224 case ETHERSWITCH_VLAN_DOT1Q:
225 sc->vlan_mode = ETHERSWITCH_VLAN_DOT1Q;
226 break;
227 case ETHERSWITCH_VLAN_PORT:
228 sc->vlan_mode = ETHERSWITCH_VLAN_PORT;
229 break;
230 default:
231 sc->vlan_mode = 0;
232 }
233
234 /* Reset VLANs. */
235 sc->hal.arswitch_vlan_init_hw(sc);
236
237 return (0);
238 }
239
240 static void
ar8xxx_port_init(struct arswitch_softc * sc,int port)241 ar8xxx_port_init(struct arswitch_softc *sc, int port)
242 {
243
244 /* Port0 - CPU */
245 if (port == AR8X16_PORT_CPU) {
246 arswitch_writereg(sc->sc_dev, AR8X16_REG_PORT_STS(0),
247 (AR8X16_IS_SWITCH(sc, AR8216) ?
248 AR8X16_PORT_STS_SPEED_100 : AR8X16_PORT_STS_SPEED_1000) |
249 (AR8X16_IS_SWITCH(sc, AR8216) ? 0 : AR8X16_PORT_STS_RXFLOW) |
250 (AR8X16_IS_SWITCH(sc, AR8216) ? 0 : AR8X16_PORT_STS_TXFLOW) |
251 AR8X16_PORT_STS_RXMAC |
252 AR8X16_PORT_STS_TXMAC |
253 AR8X16_PORT_STS_DUPLEX);
254 arswitch_writereg(sc->sc_dev, AR8X16_REG_PORT_CTRL(0),
255 arswitch_readreg(sc->sc_dev, AR8X16_REG_PORT_CTRL(0)) &
256 ~AR8X16_PORT_CTRL_HEADER);
257 } else {
258 /* Set ports to auto negotiation. */
259 arswitch_writereg(sc->sc_dev, AR8X16_REG_PORT_STS(port),
260 AR8X16_PORT_STS_LINK_AUTO);
261 arswitch_writereg(sc->sc_dev, AR8X16_REG_PORT_CTRL(port),
262 arswitch_readreg(sc->sc_dev, AR8X16_REG_PORT_CTRL(port)) &
263 ~AR8X16_PORT_CTRL_HEADER);
264 }
265 }
266
267 static int
ar8xxx_atu_wait_ready(struct arswitch_softc * sc)268 ar8xxx_atu_wait_ready(struct arswitch_softc *sc)
269 {
270 int ret;
271
272 ARSWITCH_LOCK_ASSERT(sc, MA_OWNED);
273
274 ret = arswitch_waitreg(sc->sc_dev,
275 AR8216_REG_ATU,
276 AR8216_ATU_ACTIVE,
277 0,
278 1000);
279
280 return (ret);
281 }
282
283 /*
284 * Flush all ATU entries.
285 */
286 static int
ar8xxx_atu_flush(struct arswitch_softc * sc)287 ar8xxx_atu_flush(struct arswitch_softc *sc)
288 {
289 int ret;
290
291 ARSWITCH_LOCK_ASSERT(sc, MA_OWNED);
292
293 DPRINTF(sc, ARSWITCH_DBG_ATU, "%s: flushing all ports\n", __func__);
294
295 ret = ar8xxx_atu_wait_ready(sc);
296 if (ret)
297 device_printf(sc->sc_dev, "%s: waitreg failed\n", __func__);
298
299 if (!ret)
300 arswitch_writereg(sc->sc_dev,
301 AR8216_REG_ATU,
302 AR8216_ATU_OP_FLUSH | AR8216_ATU_ACTIVE);
303
304 return (ret);
305 }
306
307 /*
308 * Flush ATU entries for a single port.
309 */
310 static int
ar8xxx_atu_flush_port(struct arswitch_softc * sc,int port)311 ar8xxx_atu_flush_port(struct arswitch_softc *sc, int port)
312 {
313 int ret, val;
314
315 DPRINTF(sc, ARSWITCH_DBG_ATU, "%s: flushing port %d\n", __func__,
316 port);
317
318 ARSWITCH_LOCK_ASSERT(sc, MA_OWNED);
319
320 /* Flush unicast entries on port */
321 val = AR8216_ATU_OP_FLUSH_UNICAST;
322
323 /* TODO: bit 4 indicates whether to flush dynamic (0) or static (1) */
324
325 /* Which port */
326 val |= SM(port, AR8216_ATU_PORT_NUM);
327
328 ret = ar8xxx_atu_wait_ready(sc);
329 if (ret)
330 device_printf(sc->sc_dev, "%s: waitreg failed\n", __func__);
331
332 if (!ret)
333 arswitch_writereg(sc->sc_dev,
334 AR8216_REG_ATU,
335 val | AR8216_ATU_ACTIVE);
336
337 return (ret);
338 }
339
340 /*
341 * XXX TODO: flush a single MAC address.
342 */
343
344 /*
345 * Fetch a single entry from the ATU.
346 */
347 static int
ar8xxx_atu_fetch_table(struct arswitch_softc * sc,etherswitch_atu_entry_t * e,int atu_fetch_op)348 ar8xxx_atu_fetch_table(struct arswitch_softc *sc, etherswitch_atu_entry_t *e,
349 int atu_fetch_op)
350 {
351 uint32_t ret0, ret1, ret2, val;
352
353 ARSWITCH_LOCK_ASSERT(sc, MA_OWNED);
354
355 switch (atu_fetch_op) {
356 case 0:
357 /* Initialise things for the first fetch */
358
359 DPRINTF(sc, ARSWITCH_DBG_ATU, "%s: initializing\n", __func__);
360 (void) ar8xxx_atu_wait_ready(sc);
361
362 arswitch_writereg(sc->sc_dev,
363 AR8216_REG_ATU, AR8216_ATU_OP_GET_NEXT);
364 arswitch_writereg(sc->sc_dev,
365 AR8216_REG_ATU_DATA, 0);
366 arswitch_writereg(sc->sc_dev,
367 AR8216_REG_ATU_CTRL2, 0);
368
369 return (0);
370 case 1:
371 DPRINTF(sc, ARSWITCH_DBG_ATU, "%s: reading next\n", __func__);
372 /*
373 * Attempt to read the next address entry; don't modify what
374 * is there in AT_ADDR{4,5} as its used for the next fetch
375 */
376 (void) ar8xxx_atu_wait_ready(sc);
377
378 /* Begin the next read event; not modifying anything */
379 val = arswitch_readreg(sc->sc_dev, AR8216_REG_ATU);
380 val |= AR8216_ATU_ACTIVE;
381 arswitch_writereg(sc->sc_dev, AR8216_REG_ATU, val);
382
383 /* Wait for it to complete */
384 (void) ar8xxx_atu_wait_ready(sc);
385
386 /* Fetch the ethernet address and ATU status */
387 ret0 = arswitch_readreg(sc->sc_dev, AR8216_REG_ATU);
388 ret1 = arswitch_readreg(sc->sc_dev, AR8216_REG_ATU_DATA);
389 ret2 = arswitch_readreg(sc->sc_dev, AR8216_REG_ATU_CTRL2);
390
391 /* If the status is zero, then we're done */
392 if (MS(ret2, AR8216_ATU_CTRL2_AT_STATUS) == 0)
393 return (-1);
394
395 /* MAC address */
396 e->es_macaddr[5] = MS(ret0, AR8216_ATU_ADDR5);
397 e->es_macaddr[4] = MS(ret0, AR8216_ATU_ADDR4);
398 e->es_macaddr[3] = MS(ret1, AR8216_ATU_ADDR3);
399 e->es_macaddr[2] = MS(ret1, AR8216_ATU_ADDR2);
400 e->es_macaddr[1] = MS(ret1, AR8216_ATU_ADDR1);
401 e->es_macaddr[0] = MS(ret1, AR8216_ATU_ADDR0);
402
403 /* Bitmask of ports this entry is for */
404 e->es_portmask = MS(ret2, AR8216_ATU_CTRL2_DESPORT);
405
406 /* TODO: other flags that are interesting */
407
408 DPRINTF(sc, ARSWITCH_DBG_ATU, "%s: MAC %6D portmask 0x%08x\n",
409 __func__,
410 e->es_macaddr, ":", e->es_portmask);
411 return (0);
412 default:
413 return (-1);
414 }
415 return (-1);
416 }
417
418 /*
419 * Configure aging register defaults.
420 */
421 static int
ar8xxx_atu_learn_default(struct arswitch_softc * sc)422 ar8xxx_atu_learn_default(struct arswitch_softc *sc)
423 {
424 int ret;
425 uint32_t val;
426
427 DPRINTF(sc, ARSWITCH_DBG_ATU, "%s: resetting learning\n", __func__);
428
429 /*
430 * For now, configure the aging defaults:
431 *
432 * + ARP_EN - enable "acknowledgement" of ARP frames - they are
433 * forwarded to the CPU port
434 * + LEARN_CHANGE_EN - hash table violations when learning MAC addresses
435 * will force an entry to be expired/updated and a new one to be
436 * programmed in.
437 * + AGE_EN - enable address table aging
438 * + AGE_TIME - set to 5 minutes
439 */
440 val = 0;
441 val |= AR8216_ATU_CTRL_ARP_EN;
442 val |= AR8216_ATU_CTRL_LEARN_CHANGE;
443 val |= AR8216_ATU_CTRL_AGE_EN;
444 val |= 0x2b; /* 5 minutes; bits 15:0 */
445
446 ret = arswitch_writereg(sc->sc_dev,
447 AR8216_REG_ATU_CTRL,
448 val);
449
450 if (ret)
451 device_printf(sc->sc_dev, "%s: writereg failed\n", __func__);
452
453 return (ret);
454 }
455
456 /*
457 * XXX TODO: add another routine to configure the leaky behaviour
458 * when unknown frames are received. These must be consistent
459 * between ethernet switches.
460 */
461
462 /*
463 * Fetch the configured switch MAC address.
464 */
465 static int
ar8xxx_hw_get_switch_macaddr(struct arswitch_softc * sc,struct ether_addr * ea)466 ar8xxx_hw_get_switch_macaddr(struct arswitch_softc *sc, struct ether_addr *ea)
467 {
468 uint32_t ret0, ret1;
469 char *s;
470
471 s = (void *) ea;
472
473 ret0 = arswitch_readreg(sc->sc_dev, AR8X16_REG_SW_MAC_ADDR0);
474 ret1 = arswitch_readreg(sc->sc_dev, AR8X16_REG_SW_MAC_ADDR1);
475
476 s[5] = MS(ret0, AR8X16_REG_SW_MAC_ADDR0_BYTE5);
477 s[4] = MS(ret0, AR8X16_REG_SW_MAC_ADDR0_BYTE4);
478 s[3] = MS(ret1, AR8X16_REG_SW_MAC_ADDR1_BYTE3);
479 s[2] = MS(ret1, AR8X16_REG_SW_MAC_ADDR1_BYTE2);
480 s[1] = MS(ret1, AR8X16_REG_SW_MAC_ADDR1_BYTE1);
481 s[0] = MS(ret1, AR8X16_REG_SW_MAC_ADDR1_BYTE0);
482
483 return (0);
484 }
485
486 /*
487 * Set the switch mac address.
488 */
489 static int
ar8xxx_hw_set_switch_macaddr(struct arswitch_softc * sc,const struct ether_addr * ea)490 ar8xxx_hw_set_switch_macaddr(struct arswitch_softc *sc,
491 const struct ether_addr *ea)
492 {
493
494 return (ENXIO);
495 }
496
497 /*
498 * XXX TODO: this attach routine does NOT free all memory, resources
499 * upon failure!
500 */
501 static int
arswitch_attach(device_t dev)502 arswitch_attach(device_t dev)
503 {
504 struct arswitch_softc *sc = device_get_softc(dev);
505 struct sysctl_ctx_list *ctx;
506 struct sysctl_oid *tree;
507 int err = 0;
508 int port;
509
510 /* sc->sc_switchtype is already decided in arswitch_probe() */
511 sc->sc_dev = dev;
512 mtx_init(&sc->sc_mtx, "arswitch", NULL, MTX_DEF);
513 sc->page = -1;
514 strlcpy(sc->info.es_name, device_get_desc(dev),
515 sizeof(sc->info.es_name));
516
517 /* Debugging */
518 ctx = device_get_sysctl_ctx(sc->sc_dev);
519 tree = device_get_sysctl_tree(sc->sc_dev);
520 SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
521 "debug", CTLFLAG_RW, &sc->sc_debug, 0,
522 "control debugging printfs");
523
524 /* Allocate a 128 entry ATU table; hopefully its big enough! */
525 /* XXX TODO: make this per chip */
526 sc->atu.entries = malloc(sizeof(etherswitch_atu_entry_t) * 128,
527 M_DEVBUF, M_NOWAIT);
528 if (sc->atu.entries == NULL) {
529 device_printf(sc->sc_dev, "%s: failed to allocate ATU table\n",
530 __func__);
531 return (ENXIO);
532 }
533 sc->atu.count = 0;
534 sc->atu.size = 128;
535
536 /* Default HAL methods */
537 sc->hal.arswitch_port_init = ar8xxx_port_init;
538 sc->hal.arswitch_port_vlan_setup = ar8xxx_port_vlan_setup;
539 sc->hal.arswitch_port_vlan_get = ar8xxx_port_vlan_get;
540 sc->hal.arswitch_vlan_init_hw = ar8xxx_reset_vlans;
541 sc->hal.arswitch_hw_get_switch_macaddr = ar8xxx_hw_get_switch_macaddr;
542 sc->hal.arswitch_hw_set_switch_macaddr = ar8xxx_hw_set_switch_macaddr;
543
544 sc->hal.arswitch_vlan_getvgroup = ar8xxx_getvgroup;
545 sc->hal.arswitch_vlan_setvgroup = ar8xxx_setvgroup;
546
547 sc->hal.arswitch_vlan_get_pvid = ar8xxx_get_pvid;
548 sc->hal.arswitch_vlan_set_pvid = ar8xxx_set_pvid;
549
550 sc->hal.arswitch_get_dot1q_vlan = ar8xxx_get_dot1q_vlan;
551 sc->hal.arswitch_set_dot1q_vlan = ar8xxx_set_dot1q_vlan;
552 sc->hal.arswitch_flush_dot1q_vlan = ar8xxx_flush_dot1q_vlan;
553 sc->hal.arswitch_purge_dot1q_vlan = ar8xxx_purge_dot1q_vlan;
554 sc->hal.arswitch_get_port_vlan = ar8xxx_get_port_vlan;
555 sc->hal.arswitch_set_port_vlan = ar8xxx_set_port_vlan;
556
557 sc->hal.arswitch_atu_flush = ar8xxx_atu_flush;
558 sc->hal.arswitch_atu_flush_port = ar8xxx_atu_flush_port;
559 sc->hal.arswitch_atu_learn_default = ar8xxx_atu_learn_default;
560 sc->hal.arswitch_atu_fetch_table = ar8xxx_atu_fetch_table;
561
562 sc->hal.arswitch_phy_read = arswitch_readphy_internal;
563 sc->hal.arswitch_phy_write = arswitch_writephy_internal;
564
565 /*
566 * Attach switch related functions
567 */
568 if (AR8X16_IS_SWITCH(sc, AR8216))
569 ar8216_attach(sc);
570 else if (AR8X16_IS_SWITCH(sc, AR8226))
571 ar8226_attach(sc);
572 else if (AR8X16_IS_SWITCH(sc, AR8316))
573 ar8316_attach(sc);
574 else if (AR8X16_IS_SWITCH(sc, AR8327))
575 ar8327_attach(sc);
576 else {
577 DPRINTF(sc, ARSWITCH_DBG_ANY,
578 "%s: unknown switch (%d)?\n", __func__, sc->sc_switchtype);
579 return (ENXIO);
580 }
581
582 /* Common defaults. */
583 sc->info.es_nports = 5; /* XXX technically 6, but 6th not used */
584
585 /* XXX Defaults for externally connected AR8316 */
586 sc->numphys = 4;
587 sc->phy4cpu = 1;
588 sc->is_rgmii = 1;
589 sc->is_gmii = 0;
590 sc->is_mii = 0;
591
592 (void) resource_int_value(device_get_name(dev), device_get_unit(dev),
593 "numphys", &sc->numphys);
594 (void) resource_int_value(device_get_name(dev), device_get_unit(dev),
595 "phy4cpu", &sc->phy4cpu);
596 (void) resource_int_value(device_get_name(dev), device_get_unit(dev),
597 "is_rgmii", &sc->is_rgmii);
598 (void) resource_int_value(device_get_name(dev), device_get_unit(dev),
599 "is_gmii", &sc->is_gmii);
600 (void) resource_int_value(device_get_name(dev), device_get_unit(dev),
601 "is_mii", &sc->is_mii);
602
603 if (sc->numphys > AR8X16_NUM_PHYS)
604 sc->numphys = AR8X16_NUM_PHYS;
605
606 /* Reset the switch. */
607 if (arswitch_reset(dev)) {
608 DPRINTF(sc, ARSWITCH_DBG_ANY,
609 "%s: arswitch_reset: failed\n", __func__);
610 return (ENXIO);
611 }
612
613 err = sc->hal.arswitch_hw_setup(sc);
614 if (err != 0) {
615 DPRINTF(sc, ARSWITCH_DBG_ANY,
616 "%s: hw_setup: err=%d\n", __func__, err);
617 return (err);
618 }
619
620 err = sc->hal.arswitch_hw_global_setup(sc);
621 if (err != 0) {
622 DPRINTF(sc, ARSWITCH_DBG_ANY,
623 "%s: hw_global_setup: err=%d\n", __func__, err);
624 return (err);
625 }
626
627 /*
628 * Configure the default address table learning parameters for this
629 * switch.
630 */
631 err = sc->hal.arswitch_atu_learn_default(sc);
632 if (err != 0) {
633 DPRINTF(sc, ARSWITCH_DBG_ANY,
634 "%s: atu_learn_default: err=%d\n", __func__, err);
635 return (err);
636 }
637
638 /* Initialize the switch ports. */
639 for (port = 0; port <= sc->numphys; port++) {
640 sc->hal.arswitch_port_init(sc, port);
641 }
642
643 /*
644 * Attach the PHYs and complete the bus enumeration.
645 */
646 err = arswitch_attach_phys(sc);
647 if (err != 0) {
648 DPRINTF(sc, ARSWITCH_DBG_ANY,
649 "%s: attach_phys: err=%d\n", __func__, err);
650 return (err);
651 }
652
653 /* Default to ingress filters off. */
654 err = arswitch_set_vlan_mode(sc, 0);
655 if (err != 0) {
656 DPRINTF(sc, ARSWITCH_DBG_ANY,
657 "%s: set_vlan_mode: err=%d\n", __func__, err);
658 return (err);
659 }
660
661 bus_generic_probe(dev);
662 bus_enumerate_hinted_children(dev);
663 err = bus_generic_attach(dev);
664 if (err != 0) {
665 DPRINTF(sc, ARSWITCH_DBG_ANY,
666 "%s: bus_generic_attach: err=%d\n", __func__, err);
667 return (err);
668 }
669
670 callout_init_mtx(&sc->callout_tick, &sc->sc_mtx, 0);
671
672 ARSWITCH_LOCK(sc);
673 arswitch_tick(sc);
674 ARSWITCH_UNLOCK(sc);
675
676 return (err);
677 }
678
679 static int
arswitch_detach(device_t dev)680 arswitch_detach(device_t dev)
681 {
682 struct arswitch_softc *sc = device_get_softc(dev);
683 int i;
684
685 callout_drain(&sc->callout_tick);
686
687 for (i=0; i < sc->numphys; i++) {
688 if (sc->miibus[i] != NULL)
689 device_delete_child(dev, sc->miibus[i]);
690 if (sc->ifp[i] != NULL)
691 if_free(sc->ifp[i]);
692 free(sc->ifname[i], M_DEVBUF);
693 }
694
695 free(sc->atu.entries, M_DEVBUF);
696
697 bus_generic_detach(dev);
698 mtx_destroy(&sc->sc_mtx);
699
700 return (0);
701 }
702
703 /*
704 * Convert PHY number to port number. PHY0 is connected to port 1, PHY1 to
705 * port 2, etc.
706 */
707 static inline int
arswitch_portforphy(int phy)708 arswitch_portforphy(int phy)
709 {
710 return (phy+1);
711 }
712
713 static inline struct mii_data *
arswitch_miiforport(struct arswitch_softc * sc,int port)714 arswitch_miiforport(struct arswitch_softc *sc, int port)
715 {
716 int phy = port-1;
717
718 if (phy < 0 || phy >= sc->numphys)
719 return (NULL);
720 return (device_get_softc(sc->miibus[phy]));
721 }
722
723 static inline if_t
arswitch_ifpforport(struct arswitch_softc * sc,int port)724 arswitch_ifpforport(struct arswitch_softc *sc, int port)
725 {
726 int phy = port-1;
727
728 if (phy < 0 || phy >= sc->numphys)
729 return (NULL);
730 return (sc->ifp[phy]);
731 }
732
733 /*
734 * Convert port status to ifmedia.
735 */
736 static void
arswitch_update_ifmedia(int portstatus,u_int * media_status,u_int * media_active)737 arswitch_update_ifmedia(int portstatus, u_int *media_status, u_int *media_active)
738 {
739 *media_active = IFM_ETHER;
740 *media_status = IFM_AVALID;
741
742 if ((portstatus & AR8X16_PORT_STS_LINK_UP) != 0)
743 *media_status |= IFM_ACTIVE;
744 else {
745 *media_active |= IFM_NONE;
746 return;
747 }
748 switch (portstatus & AR8X16_PORT_STS_SPEED_MASK) {
749 case AR8X16_PORT_STS_SPEED_10:
750 *media_active |= IFM_10_T;
751 break;
752 case AR8X16_PORT_STS_SPEED_100:
753 *media_active |= IFM_100_TX;
754 break;
755 case AR8X16_PORT_STS_SPEED_1000:
756 *media_active |= IFM_1000_T;
757 break;
758 }
759 if ((portstatus & AR8X16_PORT_STS_DUPLEX) == 0)
760 *media_active |= IFM_FDX;
761 else
762 *media_active |= IFM_HDX;
763 if ((portstatus & AR8X16_PORT_STS_TXFLOW) != 0)
764 *media_active |= IFM_ETH_TXPAUSE;
765 if ((portstatus & AR8X16_PORT_STS_RXFLOW) != 0)
766 *media_active |= IFM_ETH_RXPAUSE;
767 }
768
769 /*
770 * Poll the status for all PHYs. We're using the switch port status because
771 * thats a lot quicker to read than talking to all the PHYs. Care must be
772 * taken that the resulting ifmedia_active is identical to what the PHY will
773 * compute, or gratuitous link status changes will occur whenever the PHYs
774 * update function is called.
775 */
776 static void
arswitch_miipollstat(struct arswitch_softc * sc)777 arswitch_miipollstat(struct arswitch_softc *sc)
778 {
779 int i;
780 struct mii_data *mii;
781 struct mii_softc *miisc;
782 int portstatus;
783 int port_flap = 0;
784
785 ARSWITCH_LOCK_ASSERT(sc, MA_OWNED);
786
787 for (i = 0; i < sc->numphys; i++) {
788 if (sc->miibus[i] == NULL)
789 continue;
790 mii = device_get_softc(sc->miibus[i]);
791 /* XXX This would be nice to have abstracted out to be per-chip */
792 /* AR8327/AR8337 has a different register base */
793 if (AR8X16_IS_SWITCH(sc, AR8327))
794 portstatus = arswitch_readreg(sc->sc_dev,
795 AR8327_REG_PORT_STATUS(arswitch_portforphy(i)));
796 else
797 portstatus = arswitch_readreg(sc->sc_dev,
798 AR8X16_REG_PORT_STS(arswitch_portforphy(i)));
799 #if 1
800 DPRINTF(sc, ARSWITCH_DBG_POLL, "p[%d]=0x%08x (%b)\n",
801 i,
802 portstatus,
803 portstatus,
804 "\20\3TXMAC\4RXMAC\5TXFLOW\6RXFLOW\7"
805 "DUPLEX\11LINK_UP\12LINK_AUTO\13LINK_PAUSE");
806 #endif
807 /*
808 * If the current status is down, but we have a link
809 * status showing up, we need to do an ATU flush.
810 */
811 if ((mii->mii_media_status & IFM_ACTIVE) == 0 &&
812 (portstatus & AR8X16_PORT_STS_LINK_UP) != 0) {
813 device_printf(sc->sc_dev, "%s: port %d: port -> UP\n",
814 __func__,
815 i);
816 port_flap = 1;
817 }
818 /*
819 * and maybe if a port goes up->down?
820 */
821 if ((mii->mii_media_status & IFM_ACTIVE) != 0 &&
822 (portstatus & AR8X16_PORT_STS_LINK_UP) == 0) {
823 device_printf(sc->sc_dev, "%s: port %d: port -> DOWN\n",
824 __func__,
825 i);
826 port_flap = 1;
827 }
828 arswitch_update_ifmedia(portstatus, &mii->mii_media_status,
829 &mii->mii_media_active);
830 LIST_FOREACH(miisc, &mii->mii_phys, mii_list) {
831 if (IFM_INST(mii->mii_media.ifm_cur->ifm_media) !=
832 miisc->mii_inst)
833 continue;
834 mii_phy_update(miisc, MII_POLLSTAT);
835 }
836 }
837
838 /* If a port went from down->up, flush the ATU */
839 if (port_flap)
840 sc->hal.arswitch_atu_flush(sc);
841 }
842
843 static void
arswitch_tick(void * arg)844 arswitch_tick(void *arg)
845 {
846 struct arswitch_softc *sc = arg;
847
848 arswitch_miipollstat(sc);
849 callout_reset(&sc->callout_tick, hz, arswitch_tick, sc);
850 }
851
852 static void
arswitch_lock(device_t dev)853 arswitch_lock(device_t dev)
854 {
855 struct arswitch_softc *sc = device_get_softc(dev);
856
857 ARSWITCH_LOCK_ASSERT(sc, MA_NOTOWNED);
858 ARSWITCH_LOCK(sc);
859 }
860
861 static void
arswitch_unlock(device_t dev)862 arswitch_unlock(device_t dev)
863 {
864 struct arswitch_softc *sc = device_get_softc(dev);
865
866 ARSWITCH_LOCK_ASSERT(sc, MA_OWNED);
867 ARSWITCH_UNLOCK(sc);
868 }
869
870 static etherswitch_info_t *
arswitch_getinfo(device_t dev)871 arswitch_getinfo(device_t dev)
872 {
873 struct arswitch_softc *sc = device_get_softc(dev);
874
875 return (&sc->info);
876 }
877
878 static int
ar8xxx_port_vlan_get(struct arswitch_softc * sc,etherswitch_port_t * p)879 ar8xxx_port_vlan_get(struct arswitch_softc *sc, etherswitch_port_t *p)
880 {
881 uint32_t reg;
882
883 ARSWITCH_LOCK(sc);
884
885 /* Retrieve the PVID. */
886 sc->hal.arswitch_vlan_get_pvid(sc, p->es_port, &p->es_pvid);
887
888 /* Port flags. */
889 reg = arswitch_readreg(sc->sc_dev, AR8X16_REG_PORT_CTRL(p->es_port));
890 if (reg & AR8X16_PORT_CTRL_DOUBLE_TAG)
891 p->es_flags |= ETHERSWITCH_PORT_DOUBLE_TAG;
892 reg >>= AR8X16_PORT_CTRL_EGRESS_VLAN_MODE_SHIFT;
893 if ((reg & 0x3) == AR8X16_PORT_CTRL_EGRESS_VLAN_MODE_ADD)
894 p->es_flags |= ETHERSWITCH_PORT_ADDTAG;
895 if ((reg & 0x3) == AR8X16_PORT_CTRL_EGRESS_VLAN_MODE_STRIP)
896 p->es_flags |= ETHERSWITCH_PORT_STRIPTAG;
897 ARSWITCH_UNLOCK(sc);
898
899 return (0);
900 }
901
902 static int
arswitch_is_cpuport(struct arswitch_softc * sc,int port)903 arswitch_is_cpuport(struct arswitch_softc *sc, int port)
904 {
905
906 return ((port == AR8X16_PORT_CPU) ||
907 ((AR8X16_IS_SWITCH(sc, AR8327) &&
908 port == AR8327_PORT_GMAC6)));
909 }
910
911 static int
arswitch_getport(device_t dev,etherswitch_port_t * p)912 arswitch_getport(device_t dev, etherswitch_port_t *p)
913 {
914 struct arswitch_softc *sc;
915 struct mii_data *mii;
916 struct ifmediareq *ifmr;
917 int err;
918
919 sc = device_get_softc(dev);
920 /* XXX +1 is for AR8327; should make this configurable! */
921 if (p->es_port < 0 || p->es_port > sc->info.es_nports)
922 return (ENXIO);
923
924 err = sc->hal.arswitch_port_vlan_get(sc, p);
925 if (err != 0)
926 return (err);
927
928 mii = arswitch_miiforport(sc, p->es_port);
929 if (arswitch_is_cpuport(sc, p->es_port)) {
930 /* fill in fixed values for CPU port */
931 /* XXX is this valid in all cases? */
932 p->es_flags |= ETHERSWITCH_PORT_CPU;
933 ifmr = &p->es_ifmr;
934 ifmr->ifm_count = 0;
935 ifmr->ifm_current = ifmr->ifm_active =
936 IFM_ETHER | IFM_1000_T | IFM_FDX;
937 ifmr->ifm_mask = 0;
938 ifmr->ifm_status = IFM_ACTIVE | IFM_AVALID;
939 } else if (mii != NULL) {
940 err = ifmedia_ioctl(mii->mii_ifp, &p->es_ifr,
941 &mii->mii_media, SIOCGIFMEDIA);
942 if (err)
943 return (err);
944 } else {
945 return (ENXIO);
946 }
947
948 if (!arswitch_is_cpuport(sc, p->es_port) &&
949 AR8X16_IS_SWITCH(sc, AR8327)) {
950 int led;
951 p->es_nleds = 3;
952
953 for (led = 0; led < p->es_nleds; led++)
954 {
955 int style;
956 uint32_t val;
957
958 /* Find the right style enum for our pattern */
959 val = arswitch_readreg(dev,
960 ar8327_led_mapping[p->es_port-1][led].reg);
961 val = (val>>ar8327_led_mapping[p->es_port-1][led].shift)&0x03;
962
963 for (style = 0; style < ETHERSWITCH_PORT_LED_MAX; style++)
964 {
965 if (led_pattern_table[style] == val) break;
966 }
967
968 /* can't happen */
969 if (style == ETHERSWITCH_PORT_LED_MAX)
970 style = ETHERSWITCH_PORT_LED_DEFAULT;
971
972 p->es_led[led] = style;
973 }
974 } else
975 {
976 p->es_nleds = 0;
977 }
978
979 return (0);
980 }
981
982 static int
ar8xxx_port_vlan_setup(struct arswitch_softc * sc,etherswitch_port_t * p)983 ar8xxx_port_vlan_setup(struct arswitch_softc *sc, etherswitch_port_t *p)
984 {
985 uint32_t reg;
986 int err;
987
988 ARSWITCH_LOCK(sc);
989
990 /* Set the PVID. */
991 if (p->es_pvid != 0)
992 sc->hal.arswitch_vlan_set_pvid(sc, p->es_port, p->es_pvid);
993
994 /* Mutually exclusive. */
995 if (p->es_flags & ETHERSWITCH_PORT_ADDTAG &&
996 p->es_flags & ETHERSWITCH_PORT_STRIPTAG) {
997 ARSWITCH_UNLOCK(sc);
998 return (EINVAL);
999 }
1000
1001 reg = 0;
1002 if (p->es_flags & ETHERSWITCH_PORT_DOUBLE_TAG)
1003 reg |= AR8X16_PORT_CTRL_DOUBLE_TAG;
1004 if (p->es_flags & ETHERSWITCH_PORT_ADDTAG)
1005 reg |= AR8X16_PORT_CTRL_EGRESS_VLAN_MODE_ADD <<
1006 AR8X16_PORT_CTRL_EGRESS_VLAN_MODE_SHIFT;
1007 if (p->es_flags & ETHERSWITCH_PORT_STRIPTAG)
1008 reg |= AR8X16_PORT_CTRL_EGRESS_VLAN_MODE_STRIP <<
1009 AR8X16_PORT_CTRL_EGRESS_VLAN_MODE_SHIFT;
1010
1011 err = arswitch_modifyreg(sc->sc_dev,
1012 AR8X16_REG_PORT_CTRL(p->es_port),
1013 0x3 << AR8X16_PORT_CTRL_EGRESS_VLAN_MODE_SHIFT |
1014 AR8X16_PORT_CTRL_DOUBLE_TAG, reg);
1015
1016 ARSWITCH_UNLOCK(sc);
1017 return (err);
1018 }
1019
1020 static int
arswitch_setport(device_t dev,etherswitch_port_t * p)1021 arswitch_setport(device_t dev, etherswitch_port_t *p)
1022 {
1023 int err, i;
1024 struct arswitch_softc *sc;
1025 struct ifmedia *ifm;
1026 struct mii_data *mii;
1027 if_t ifp;
1028
1029 sc = device_get_softc(dev);
1030 if (p->es_port < 0 || p->es_port > sc->info.es_nports)
1031 return (ENXIO);
1032
1033 /* Port flags. */
1034 if (sc->vlan_mode == ETHERSWITCH_VLAN_DOT1Q) {
1035 err = sc->hal.arswitch_port_vlan_setup(sc, p);
1036 if (err)
1037 return (err);
1038 }
1039
1040 /* Do not allow media or led changes on CPU port. */
1041 if (arswitch_is_cpuport(sc, p->es_port))
1042 return (0);
1043
1044 if (AR8X16_IS_SWITCH(sc, AR8327))
1045 {
1046 for (i = 0; i < 3; i++)
1047 {
1048 int err;
1049 err = arswitch_setled(sc, p->es_port-1, i, p->es_led[i]);
1050 if (err)
1051 return (err);
1052 }
1053 }
1054
1055 mii = arswitch_miiforport(sc, p->es_port);
1056 if (mii == NULL)
1057 return (ENXIO);
1058
1059 ifp = arswitch_ifpforport(sc, p->es_port);
1060
1061 ifm = &mii->mii_media;
1062 return (ifmedia_ioctl(ifp, &p->es_ifr, ifm, SIOCSIFMEDIA));
1063 }
1064
1065 static int
arswitch_setled(struct arswitch_softc * sc,int phy,int led,int style)1066 arswitch_setled(struct arswitch_softc *sc, int phy, int led, int style)
1067 {
1068 int shift;
1069 int err;
1070
1071 if (phy < 0 || phy > sc->numphys)
1072 return EINVAL;
1073
1074 if (style < 0 || style > ETHERSWITCH_PORT_LED_MAX)
1075 return (EINVAL);
1076
1077 ARSWITCH_LOCK(sc);
1078
1079 shift = ar8327_led_mapping[phy][led].shift;
1080 err = (arswitch_modifyreg(sc->sc_dev,
1081 ar8327_led_mapping[phy][led].reg,
1082 0x03 << shift, led_pattern_table[style] << shift));
1083 ARSWITCH_UNLOCK(sc);
1084
1085 return (err);
1086 }
1087
1088 static void
arswitch_statchg(device_t dev)1089 arswitch_statchg(device_t dev)
1090 {
1091 struct arswitch_softc *sc = device_get_softc(dev);
1092
1093 DPRINTF(sc, ARSWITCH_DBG_POLL, "%s\n", __func__);
1094 }
1095
1096 static int
arswitch_ifmedia_upd(if_t ifp)1097 arswitch_ifmedia_upd(if_t ifp)
1098 {
1099 struct arswitch_softc *sc = if_getsoftc(ifp);
1100 struct mii_data *mii = arswitch_miiforport(sc, if_getdunit(ifp));
1101
1102 if (mii == NULL)
1103 return (ENXIO);
1104 mii_mediachg(mii);
1105 return (0);
1106 }
1107
1108 static void
arswitch_ifmedia_sts(if_t ifp,struct ifmediareq * ifmr)1109 arswitch_ifmedia_sts(if_t ifp, struct ifmediareq *ifmr)
1110 {
1111 struct arswitch_softc *sc = if_getsoftc(ifp);
1112 struct mii_data *mii = arswitch_miiforport(sc, if_getdunit(ifp));
1113
1114 DPRINTF(sc, ARSWITCH_DBG_POLL, "%s\n", __func__);
1115
1116 if (mii == NULL)
1117 return;
1118 mii_pollstat(mii);
1119 ifmr->ifm_active = mii->mii_media_active;
1120 ifmr->ifm_status = mii->mii_media_status;
1121 }
1122
1123 static int
arswitch_getconf(device_t dev,etherswitch_conf_t * conf)1124 arswitch_getconf(device_t dev, etherswitch_conf_t *conf)
1125 {
1126 struct arswitch_softc *sc;
1127 int ret;
1128
1129 sc = device_get_softc(dev);
1130
1131 /* Return the VLAN mode. */
1132 conf->cmd = ETHERSWITCH_CONF_VLAN_MODE;
1133 conf->vlan_mode = sc->vlan_mode;
1134
1135 /* Return the switch ethernet address. */
1136 ret = sc->hal.arswitch_hw_get_switch_macaddr(sc,
1137 &conf->switch_macaddr);
1138 if (ret == 0) {
1139 conf->cmd |= ETHERSWITCH_CONF_SWITCH_MACADDR;
1140 }
1141
1142 return (0);
1143 }
1144
1145 static int
arswitch_setconf(device_t dev,etherswitch_conf_t * conf)1146 arswitch_setconf(device_t dev, etherswitch_conf_t *conf)
1147 {
1148 struct arswitch_softc *sc;
1149 int err;
1150
1151 sc = device_get_softc(dev);
1152
1153 /* Set the VLAN mode. */
1154 if (conf->cmd & ETHERSWITCH_CONF_VLAN_MODE) {
1155 err = arswitch_set_vlan_mode(sc, conf->vlan_mode);
1156 if (err != 0)
1157 return (err);
1158 }
1159
1160 /* TODO: Set the switch ethernet address. */
1161
1162 return (0);
1163 }
1164
1165 static int
arswitch_atu_flush_all(device_t dev)1166 arswitch_atu_flush_all(device_t dev)
1167 {
1168 struct arswitch_softc *sc;
1169 int err;
1170
1171 sc = device_get_softc(dev);
1172 ARSWITCH_LOCK(sc);
1173 err = sc->hal.arswitch_atu_flush(sc);
1174 /* Invalidate cached ATU */
1175 sc->atu.count = 0;
1176 ARSWITCH_UNLOCK(sc);
1177 return (err);
1178 }
1179
1180 static int
arswitch_atu_flush_port(device_t dev,int port)1181 arswitch_atu_flush_port(device_t dev, int port)
1182 {
1183 struct arswitch_softc *sc;
1184 int err;
1185
1186 sc = device_get_softc(dev);
1187 ARSWITCH_LOCK(sc);
1188 err = sc->hal.arswitch_atu_flush_port(sc, port);
1189 /* Invalidate cached ATU */
1190 sc->atu.count = 0;
1191 ARSWITCH_UNLOCK(sc);
1192 return (err);
1193 }
1194
1195 static int
arswitch_atu_fetch_table(device_t dev,etherswitch_atu_table_t * table)1196 arswitch_atu_fetch_table(device_t dev, etherswitch_atu_table_t *table)
1197 {
1198 struct arswitch_softc *sc;
1199 int err, nitems;
1200
1201 sc = device_get_softc(dev);
1202
1203 ARSWITCH_LOCK(sc);
1204 /* Initial setup */
1205 nitems = 0;
1206 err = sc->hal.arswitch_atu_fetch_table(sc, NULL, 0);
1207
1208 /* fetch - ideally yes we'd fetch into a separate table then switch */
1209 while (err == 0 && nitems < sc->atu.size) {
1210 err = sc->hal.arswitch_atu_fetch_table(sc,
1211 &sc->atu.entries[nitems], 1);
1212 if (err == 0) {
1213 sc->atu.entries[nitems].id = nitems;
1214 nitems++;
1215 }
1216 }
1217 sc->atu.count = nitems;
1218 ARSWITCH_UNLOCK(sc);
1219
1220 table->es_nitems = nitems;
1221
1222 return (0);
1223 }
1224
1225 static int
arswitch_atu_fetch_table_entry(device_t dev,etherswitch_atu_entry_t * e)1226 arswitch_atu_fetch_table_entry(device_t dev, etherswitch_atu_entry_t *e)
1227 {
1228 struct arswitch_softc *sc;
1229 int id;
1230
1231 sc = device_get_softc(dev);
1232 id = e->id;
1233
1234 ARSWITCH_LOCK(sc);
1235 if (id > sc->atu.count) {
1236 ARSWITCH_UNLOCK(sc);
1237 return (ENOENT);
1238 }
1239
1240 memcpy(e, &sc->atu.entries[id], sizeof(*e));
1241 ARSWITCH_UNLOCK(sc);
1242 return (0);
1243 }
1244
1245 static int
arswitch_getvgroup(device_t dev,etherswitch_vlangroup_t * e)1246 arswitch_getvgroup(device_t dev, etherswitch_vlangroup_t *e)
1247 {
1248 struct arswitch_softc *sc = device_get_softc(dev);
1249
1250 return (sc->hal.arswitch_vlan_getvgroup(sc, e));
1251 }
1252
1253 static int
arswitch_setvgroup(device_t dev,etherswitch_vlangroup_t * e)1254 arswitch_setvgroup(device_t dev, etherswitch_vlangroup_t *e)
1255 {
1256 struct arswitch_softc *sc = device_get_softc(dev);
1257
1258 return (sc->hal.arswitch_vlan_setvgroup(sc, e));
1259 }
1260
1261 static int
arswitch_readphy(device_t dev,int phy,int reg)1262 arswitch_readphy(device_t dev, int phy, int reg)
1263 {
1264 struct arswitch_softc *sc = device_get_softc(dev);
1265
1266 return (sc->hal.arswitch_phy_read(dev, phy, reg));
1267 }
1268
1269 static int
arswitch_writephy(device_t dev,int phy,int reg,int val)1270 arswitch_writephy(device_t dev, int phy, int reg, int val)
1271 {
1272 struct arswitch_softc *sc = device_get_softc(dev);
1273
1274 return (sc->hal.arswitch_phy_write(dev, phy, reg, val));
1275 }
1276
1277 static device_method_t arswitch_methods[] = {
1278 /* Device interface */
1279 DEVMETHOD(device_probe, arswitch_probe),
1280 DEVMETHOD(device_attach, arswitch_attach),
1281 DEVMETHOD(device_detach, arswitch_detach),
1282
1283 /* bus interface */
1284 DEVMETHOD(bus_add_child, device_add_child_ordered),
1285
1286 /* MII interface */
1287 DEVMETHOD(miibus_readreg, arswitch_readphy),
1288 DEVMETHOD(miibus_writereg, arswitch_writephy),
1289 DEVMETHOD(miibus_statchg, arswitch_statchg),
1290
1291 /* MDIO interface */
1292 DEVMETHOD(mdio_readreg, arswitch_readphy),
1293 DEVMETHOD(mdio_writereg, arswitch_writephy),
1294
1295 /* etherswitch interface */
1296 DEVMETHOD(etherswitch_lock, arswitch_lock),
1297 DEVMETHOD(etherswitch_unlock, arswitch_unlock),
1298 DEVMETHOD(etherswitch_getinfo, arswitch_getinfo),
1299 DEVMETHOD(etherswitch_readreg, arswitch_readreg),
1300 DEVMETHOD(etherswitch_writereg, arswitch_writereg),
1301 DEVMETHOD(etherswitch_readphyreg, arswitch_readphy),
1302 DEVMETHOD(etherswitch_writephyreg, arswitch_writephy),
1303 DEVMETHOD(etherswitch_getport, arswitch_getport),
1304 DEVMETHOD(etherswitch_setport, arswitch_setport),
1305 DEVMETHOD(etherswitch_getvgroup, arswitch_getvgroup),
1306 DEVMETHOD(etherswitch_setvgroup, arswitch_setvgroup),
1307 DEVMETHOD(etherswitch_getconf, arswitch_getconf),
1308 DEVMETHOD(etherswitch_setconf, arswitch_setconf),
1309 DEVMETHOD(etherswitch_flush_all, arswitch_atu_flush_all),
1310 DEVMETHOD(etherswitch_flush_port, arswitch_atu_flush_port),
1311 DEVMETHOD(etherswitch_fetch_table, arswitch_atu_fetch_table),
1312 DEVMETHOD(etherswitch_fetch_table_entry, arswitch_atu_fetch_table_entry),
1313
1314 DEVMETHOD_END
1315 };
1316
1317 DEFINE_CLASS_0(arswitch, arswitch_driver, arswitch_methods,
1318 sizeof(struct arswitch_softc));
1319
1320 DRIVER_MODULE(arswitch, mdio, arswitch_driver, 0, 0);
1321 DRIVER_MODULE(miibus, arswitch, miibus_driver, 0, 0);
1322 DRIVER_MODULE(mdio, arswitch, mdio_driver, 0, 0);
1323 DRIVER_MODULE(etherswitch, arswitch, etherswitch_driver, 0, 0);
1324 MODULE_VERSION(arswitch, 1);
1325 MODULE_DEPEND(arswitch, miibus, 1, 1, 1); /* XXX which versions? */
1326 MODULE_DEPEND(arswitch, etherswitch, 1, 1, 1); /* XXX which versions? */
1327