]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/etherswitch/arswitch/arswitch.c
MFV r329766: 8962 zdb should work on non-idle pools
[FreeBSD/FreeBSD.git] / sys / dev / etherswitch / arswitch / arswitch.c
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 static devclass_t arswitch_devclass;
1348
1349 DRIVER_MODULE(arswitch, mdio, arswitch_driver, arswitch_devclass, 0, 0);
1350 DRIVER_MODULE(miibus, arswitch, miibus_driver, miibus_devclass, 0, 0);
1351 DRIVER_MODULE(mdio, arswitch, mdio_driver, mdio_devclass, 0, 0);
1352 DRIVER_MODULE(etherswitch, arswitch, etherswitch_driver, etherswitch_devclass, 0, 0);
1353 MODULE_VERSION(arswitch, 1);
1354 MODULE_DEPEND(arswitch, miibus, 1, 1, 1); /* XXX which versions? */
1355 MODULE_DEPEND(arswitch, etherswitch, 1, 1, 1); /* XXX which versions? */