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