1 /*- 2 * Copyright (c) 2016-2017 Hiroki Mori 3 * Copyright (c) 2013 Luiz Otavio O Souza. 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 /* 33 * This code is Marvell 88E6060 ethernet switch support code on etherswitch 34 * framework. 35 * 88E6060 support is only port vlan support. Not support ingress/egress 36 * trailer. 37 * 88E6065 support is port and dot1q vlan. Also group base tag support. 38 */ 39 40 #include <sys/param.h> 41 #include <sys/bus.h> 42 #include <sys/errno.h> 43 #include <sys/kernel.h> 44 #include <sys/lock.h> 45 #include <sys/malloc.h> 46 #include <sys/module.h> 47 #include <sys/mutex.h> 48 #include <sys/socket.h> 49 #include <sys/sockio.h> 50 #include <sys/sysctl.h> 51 #include <sys/systm.h> 52 53 #include <net/if.h> 54 #include <net/if_var.h> 55 #include <net/ethernet.h> 56 #include <net/if_media.h> 57 #include <net/if_types.h> 58 59 #include <machine/bus.h> 60 #include <dev/mii/mii.h> 61 #include <dev/mii/miivar.h> 62 #include <dev/mdio/mdio.h> 63 64 #include <dev/etherswitch/etherswitch.h> 65 66 #include "mdio_if.h" 67 #include "miibus_if.h" 68 #include "etherswitch_if.h" 69 70 #define CORE_REGISTER 0x8 71 #define SWITCH_ID 3 72 73 #define PORT_CONTROL 4 74 #define ENGRESSFSHIFT 2 75 #define ENGRESSFMASK 3 76 #define ENGRESSTAGSHIFT 12 77 #define ENGRESSTAGMASK 3 78 79 #define PORT_VLAN_MAP 6 80 #define FORCEMAPSHIFT 8 81 #define FORCEMAPMASK 1 82 83 #define PORT_DEFVLAN 7 84 #define DEFVIDMASK 0xfff 85 #define DEFPRIMASK 7 86 87 #define PORT_CONTROL2 8 88 #define DOT1QMODESHIFT 10 89 #define DOT1QMODEMASK 3 90 #define DOT1QNONE 0 91 #define DOT1QFALLBACK 1 92 #define DOT1QCHECK 2 93 #define DOT1QSECURE 3 94 95 #define GLOBAL_REGISTER 0xf 96 97 #define VTU_OPERATION 5 98 #define VTU_VID_REG 6 99 #define VTU_DATA1_REG 7 100 #define VTU_DATA2_REG 8 101 #define VTU_DATA3_REG 9 102 #define VTU_BUSY 0x8000 103 #define VTU_FLASH 1 104 #define VTU_LOAD_PURGE 3 105 #define VTU_GET_NEXT 4 106 #define VTU_VIOLATION 7 107 108 MALLOC_DECLARE(M_E6060SW); 109 MALLOC_DEFINE(M_E6060SW, "e6060sw", "e6060sw data structures"); 110 111 struct e6060sw_softc { 112 struct mtx sc_mtx; /* serialize access to softc */ 113 device_t sc_dev; 114 int vlan_mode; 115 int media; /* cpu port media */ 116 int cpuport; /* which PHY is connected to the CPU */ 117 int phymask; /* PHYs we manage */ 118 int numports; /* number of ports */ 119 int ifpport[MII_NPHY]; 120 int *portphy; 121 char **ifname; 122 device_t **miibus; 123 struct ifnet **ifp; 124 struct callout callout_tick; 125 etherswitch_info_t info; 126 int smi_offset; 127 int sw_model; 128 }; 129 130 /* Switch Identifier DeviceID */ 131 132 #define E6060 0x60 133 #define E6063 0x63 134 #define E6065 0x65 135 136 #define E6060SW_LOCK(_sc) \ 137 mtx_lock(&(_sc)->sc_mtx) 138 #define E6060SW_UNLOCK(_sc) \ 139 mtx_unlock(&(_sc)->sc_mtx) 140 #define E6060SW_LOCK_ASSERT(_sc, _what) \ 141 mtx_assert(&(_sc)->sc_mtx, (_what)) 142 #define E6060SW_TRYLOCK(_sc) \ 143 mtx_trylock(&(_sc)->sc_mtx) 144 145 #if defined(DEBUG) 146 #define DPRINTF(dev, args...) device_printf(dev, args) 147 #else 148 #define DPRINTF(dev, args...) 149 #endif 150 151 static inline int e6060sw_portforphy(struct e6060sw_softc *, int); 152 static void e6060sw_tick(void *); 153 static int e6060sw_ifmedia_upd(struct ifnet *); 154 static void e6060sw_ifmedia_sts(struct ifnet *, struct ifmediareq *); 155 156 static void e6060sw_setup(device_t dev); 157 static int e6060sw_read_vtu(device_t dev, int num, int *data1, int *data2); 158 static void e6060sw_set_vtu(device_t dev, int num, int data1, int data2); 159 160 static int 161 e6060sw_probe(device_t dev) 162 { 163 int data; 164 struct e6060sw_softc *sc; 165 int devid, i; 166 char *devname; 167 char desc[80]; 168 169 sc = device_get_softc(dev); 170 bzero(sc, sizeof(*sc)); 171 172 for (i = 0; i < 2; ++i) { 173 data = MDIO_READREG(device_get_parent(dev), 174 CORE_REGISTER + i * 0x10, SWITCH_ID); 175 if (bootverbose) 176 device_printf(dev,"Switch Identifier Register %x\n", 177 data); 178 179 devid = data >> 4; 180 if (devid == E6060 || 181 devid == E6063 || devid == E6065) { 182 sc->sw_model = devid; 183 sc->smi_offset = i * 0x10; 184 break; 185 } 186 } 187 if (i == 2) 188 return (ENXIO); 189 190 if (devid == E6060) 191 devname = "88E6060"; 192 else if (devid == E6063) 193 devname = "88E6063"; 194 else if (devid == E6065) 195 devname = "88E6065"; 196 sprintf(desc, "Marvell %s MDIO switch driver at 0x%02x", 197 devname, sc->smi_offset); 198 device_set_desc_copy(dev, desc); 199 200 return (BUS_PROBE_DEFAULT); 201 } 202 203 static int 204 e6060sw_attach_phys(struct e6060sw_softc *sc) 205 { 206 int phy, port, err; 207 char name[IFNAMSIZ]; 208 209 port = 0; 210 err = 0; 211 /* PHYs need an interface, so we generate a dummy one */ 212 snprintf(name, IFNAMSIZ, "%sport", device_get_nameunit(sc->sc_dev)); 213 for (phy = 0; phy < sc->numports; phy++) { 214 if (((1 << phy) & sc->phymask) == 0) 215 continue; 216 sc->ifpport[phy] = port; 217 sc->portphy[port] = phy; 218 sc->ifp[port] = if_alloc(IFT_ETHER); 219 sc->ifp[port]->if_softc = sc; 220 sc->ifp[port]->if_flags |= IFF_UP | IFF_BROADCAST | 221 IFF_DRV_RUNNING | IFF_SIMPLEX; 222 if_initname(sc->ifp[port], name, port); 223 sc->miibus[port] = malloc(sizeof(device_t), M_E6060SW, 224 M_WAITOK | M_ZERO); 225 err = mii_attach(sc->sc_dev, sc->miibus[port], sc->ifp[port], 226 e6060sw_ifmedia_upd, e6060sw_ifmedia_sts, \ 227 BMSR_DEFCAPMASK, phy + sc->smi_offset, MII_OFFSET_ANY, 0); 228 DPRINTF(sc->sc_dev, "%s attached to pseudo interface %s\n", 229 device_get_nameunit(*sc->miibus[port]), 230 sc->ifp[port]->if_xname); 231 if (err != 0) { 232 device_printf(sc->sc_dev, 233 "attaching PHY %d failed\n", 234 phy); 235 break; 236 } 237 ++port; 238 } 239 sc->info.es_nports = port; 240 if (sc->cpuport != -1) { 241 /* assume cpuport is last one */ 242 sc->ifpport[sc->cpuport] = port; 243 sc->portphy[port] = sc->cpuport; 244 ++sc->info.es_nports; 245 } 246 return (err); 247 } 248 249 static int 250 e6060sw_attach(device_t dev) 251 { 252 struct e6060sw_softc *sc; 253 int err; 254 255 sc = device_get_softc(dev); 256 err = 0; 257 258 sc->sc_dev = dev; 259 mtx_init(&sc->sc_mtx, "e6060sw", NULL, MTX_DEF); 260 strlcpy(sc->info.es_name, device_get_desc(dev), 261 sizeof(sc->info.es_name)); 262 263 /* XXX Defaults */ 264 if (sc->sw_model == E6063) { 265 sc->numports = 3; 266 sc->phymask = 0x07; 267 sc->cpuport = 2; 268 } else { 269 sc->numports = 6; 270 sc->phymask = 0x1f; 271 sc->cpuport = 5; 272 } 273 sc->media = 100; 274 275 (void) resource_int_value(device_get_name(dev), device_get_unit(dev), 276 "numports", &sc->numports); 277 (void) resource_int_value(device_get_name(dev), device_get_unit(dev), 278 "phymask", &sc->phymask); 279 (void) resource_int_value(device_get_name(dev), device_get_unit(dev), 280 "cpuport", &sc->cpuport); 281 (void) resource_int_value(device_get_name(dev), device_get_unit(dev), 282 "media", &sc->media); 283 284 if (sc->sw_model == E6060) { 285 sc->info.es_nvlangroups = sc->numports; 286 sc->info.es_vlan_caps = ETHERSWITCH_VLAN_PORT; 287 } else { 288 sc->info.es_nvlangroups = 64; 289 sc->info.es_vlan_caps = ETHERSWITCH_VLAN_PORT | 290 ETHERSWITCH_VLAN_DOT1Q; 291 } 292 293 e6060sw_setup(dev); 294 295 sc->ifp = malloc(sizeof(struct ifnet *) * sc->numports, M_E6060SW, 296 M_WAITOK | M_ZERO); 297 sc->ifname = malloc(sizeof(char *) * sc->numports, M_E6060SW, 298 M_WAITOK | M_ZERO); 299 sc->miibus = malloc(sizeof(device_t *) * sc->numports, M_E6060SW, 300 M_WAITOK | M_ZERO); 301 sc->portphy = malloc(sizeof(int) * sc->numports, M_E6060SW, 302 M_WAITOK | M_ZERO); 303 304 /* 305 * Attach the PHYs and complete the bus enumeration. 306 */ 307 err = e6060sw_attach_phys(sc); 308 if (err != 0) 309 return (err); 310 311 bus_generic_probe(dev); 312 bus_enumerate_hinted_children(dev); 313 err = bus_generic_attach(dev); 314 if (err != 0) 315 return (err); 316 317 callout_init(&sc->callout_tick, 0); 318 319 e6060sw_tick(sc); 320 321 return (err); 322 } 323 324 static int 325 e6060sw_detach(device_t dev) 326 { 327 struct e6060sw_softc *sc; 328 int i, port; 329 330 sc = device_get_softc(dev); 331 332 callout_drain(&sc->callout_tick); 333 334 for (i = 0; i < MII_NPHY; i++) { 335 if (((1 << i) & sc->phymask) == 0) 336 continue; 337 port = e6060sw_portforphy(sc, i); 338 if (sc->miibus[port] != NULL) 339 device_delete_child(dev, (*sc->miibus[port])); 340 if (sc->ifp[port] != NULL) 341 if_free(sc->ifp[port]); 342 free(sc->ifname[port], M_E6060SW); 343 free(sc->miibus[port], M_E6060SW); 344 } 345 346 free(sc->portphy, M_E6060SW); 347 free(sc->miibus, M_E6060SW); 348 free(sc->ifname, M_E6060SW); 349 free(sc->ifp, M_E6060SW); 350 351 bus_generic_detach(dev); 352 mtx_destroy(&sc->sc_mtx); 353 354 return (0); 355 } 356 357 /* 358 * Convert PHY number to port number. 359 */ 360 static inline int 361 e6060sw_portforphy(struct e6060sw_softc *sc, int phy) 362 { 363 364 return (sc->ifpport[phy]); 365 } 366 367 static inline struct mii_data * 368 e6060sw_miiforport(struct e6060sw_softc *sc, int port) 369 { 370 371 if (port < 0 || port > sc->numports) 372 return (NULL); 373 if (port == sc->cpuport) 374 return (NULL); 375 return (device_get_softc(*sc->miibus[port])); 376 } 377 378 static inline struct ifnet * 379 e6060sw_ifpforport(struct e6060sw_softc *sc, int port) 380 { 381 382 if (port < 0 || port > sc->numports) 383 return (NULL); 384 return (sc->ifp[port]); 385 } 386 387 /* 388 * Poll the status for all PHYs. 389 */ 390 static void 391 e6060sw_miipollstat(struct e6060sw_softc *sc) 392 { 393 int i, port; 394 struct mii_data *mii; 395 struct mii_softc *miisc; 396 397 E6060SW_LOCK_ASSERT(sc, MA_NOTOWNED); 398 399 for (i = 0; i < MII_NPHY; i++) { 400 if (((1 << i) & sc->phymask) == 0) 401 continue; 402 port = e6060sw_portforphy(sc, i); 403 if ((*sc->miibus[port]) == NULL) 404 continue; 405 mii = device_get_softc(*sc->miibus[port]); 406 LIST_FOREACH(miisc, &mii->mii_phys, mii_list) { 407 if (IFM_INST(mii->mii_media.ifm_cur->ifm_media) != 408 miisc->mii_inst) 409 continue; 410 ukphy_status(miisc); 411 mii_phy_update(miisc, MII_POLLSTAT); 412 } 413 } 414 } 415 416 static void 417 e6060sw_tick(void *arg) 418 { 419 struct e6060sw_softc *sc; 420 421 sc = arg; 422 423 e6060sw_miipollstat(sc); 424 callout_reset(&sc->callout_tick, hz, e6060sw_tick, sc); 425 } 426 427 static void 428 e6060sw_lock(device_t dev) 429 { 430 struct e6060sw_softc *sc; 431 432 sc = device_get_softc(dev); 433 434 E6060SW_LOCK_ASSERT(sc, MA_NOTOWNED); 435 E6060SW_LOCK(sc); 436 } 437 438 static void 439 e6060sw_unlock(device_t dev) 440 { 441 struct e6060sw_softc *sc; 442 443 sc = device_get_softc(dev); 444 445 E6060SW_LOCK_ASSERT(sc, MA_OWNED); 446 E6060SW_UNLOCK(sc); 447 } 448 449 static etherswitch_info_t * 450 e6060sw_getinfo(device_t dev) 451 { 452 struct e6060sw_softc *sc; 453 454 sc = device_get_softc(dev); 455 456 return (&sc->info); 457 } 458 459 static int 460 e6060sw_getport(device_t dev, etherswitch_port_t *p) 461 { 462 struct e6060sw_softc *sc; 463 struct mii_data *mii; 464 struct ifmediareq *ifmr; 465 int err, phy; 466 467 sc = device_get_softc(dev); 468 ifmr = &p->es_ifmr; 469 470 if (p->es_port < 0 || p->es_port >= sc->numports) 471 return (ENXIO); 472 473 p->es_pvid = 0; 474 if (sc->vlan_mode == ETHERSWITCH_VLAN_DOT1Q) { 475 p->es_pvid = MDIO_READREG(device_get_parent(dev), 476 CORE_REGISTER + sc->smi_offset + p->es_port, 477 PORT_DEFVLAN) & 0xfff; 478 } 479 480 phy = sc->portphy[p->es_port]; 481 mii = e6060sw_miiforport(sc, p->es_port); 482 if (sc->cpuport != -1 && phy == sc->cpuport) { 483 /* fill in fixed values for CPU port */ 484 p->es_flags |= ETHERSWITCH_PORT_CPU; 485 ifmr->ifm_count = 0; 486 if (sc->media == 100) 487 ifmr->ifm_current = ifmr->ifm_active = 488 IFM_ETHER | IFM_100_TX | IFM_FDX; 489 else 490 ifmr->ifm_current = ifmr->ifm_active = 491 IFM_ETHER | IFM_1000_T | IFM_FDX; 492 ifmr->ifm_mask = 0; 493 ifmr->ifm_status = IFM_ACTIVE | IFM_AVALID; 494 } else if (mii != NULL) { 495 err = ifmedia_ioctl(mii->mii_ifp, &p->es_ifr, 496 &mii->mii_media, SIOCGIFMEDIA); 497 if (err) 498 return (err); 499 } else { 500 return (ENXIO); 501 } 502 return (0); 503 } 504 505 static int 506 e6060sw_setport(device_t dev, etherswitch_port_t *p) 507 { 508 struct e6060sw_softc *sc; 509 struct ifmedia *ifm; 510 struct mii_data *mii; 511 struct ifnet *ifp; 512 int err; 513 int data; 514 515 sc = device_get_softc(dev); 516 517 if (p->es_port < 0 || p->es_port >= sc->numports) 518 return (ENXIO); 519 520 if (sc->vlan_mode == ETHERSWITCH_VLAN_DOT1Q) { 521 data = MDIO_READREG(device_get_parent(dev), 522 CORE_REGISTER + sc->smi_offset + p->es_port, 523 PORT_DEFVLAN); 524 data &= ~0xfff; 525 data |= p->es_pvid; 526 data |= 1 << 12; 527 MDIO_WRITEREG(device_get_parent(dev), 528 CORE_REGISTER + sc->smi_offset + p->es_port, 529 PORT_DEFVLAN, data); 530 } 531 532 if (sc->portphy[p->es_port] == sc->cpuport) 533 return(0); 534 535 mii = e6060sw_miiforport(sc, p->es_port); 536 if (mii == NULL) 537 return (ENXIO); 538 539 ifp = e6060sw_ifpforport(sc, p->es_port); 540 541 ifm = &mii->mii_media; 542 err = ifmedia_ioctl(ifp, &p->es_ifr, ifm, SIOCSIFMEDIA); 543 return (err); 544 } 545 546 static int 547 e6060sw_getvgroup(device_t dev, etherswitch_vlangroup_t *vg) 548 { 549 struct e6060sw_softc *sc; 550 int data1, data2; 551 int vid; 552 int i, tag; 553 554 sc = device_get_softc(dev); 555 556 if (sc->vlan_mode == ETHERSWITCH_VLAN_PORT) { 557 vg->es_vid = ETHERSWITCH_VID_VALID; 558 vg->es_vid |= vg->es_vlangroup; 559 data1 = MDIO_READREG(device_get_parent(dev), 560 CORE_REGISTER + sc->smi_offset + vg->es_vlangroup, 561 PORT_VLAN_MAP); 562 vg->es_member_ports = data1 & 0x3f; 563 vg->es_untagged_ports = vg->es_member_ports; 564 vg->es_fid = 0; 565 } else if (sc->vlan_mode == ETHERSWITCH_VLAN_DOT1Q) { 566 if (vg->es_vlangroup == 0) 567 return (0); 568 vid = e6060sw_read_vtu(dev, vg->es_vlangroup, &data1, &data2); 569 if (vid > 0) { 570 vg->es_vid = ETHERSWITCH_VID_VALID; 571 vg->es_vid |= vid; 572 vg->es_member_ports = 0; 573 vg->es_untagged_ports = 0; 574 for (i = 0; i < 4; ++i) { 575 tag = data1 >> (i * 4) & 3; 576 if (tag == 0 || tag == 1) { 577 vg->es_member_ports |= 1 << i; 578 vg->es_untagged_ports |= 1 << i; 579 } else if (tag == 2) { 580 vg->es_member_ports |= 1 << i; 581 } 582 } 583 for (i = 0; i < 2; ++i) { 584 tag = data2 >> (i * 4) & 3; 585 if (tag == 0 || tag == 1) { 586 vg->es_member_ports |= 1 << (i + 4); 587 vg->es_untagged_ports |= 1 << (i + 4); 588 } else if (tag == 2) { 589 vg->es_member_ports |= 1 << (i + 4); 590 } 591 } 592 593 } 594 } else { 595 vg->es_vid = 0; 596 } 597 return (0); 598 } 599 600 static int 601 e6060sw_setvgroup(device_t dev, etherswitch_vlangroup_t *vg) 602 { 603 struct e6060sw_softc *sc; 604 int data1, data2; 605 int i; 606 607 sc = device_get_softc(dev); 608 609 if (sc->vlan_mode == ETHERSWITCH_VLAN_PORT) { 610 data1 = MDIO_READREG(device_get_parent(dev), 611 CORE_REGISTER + sc->smi_offset + vg->es_vlangroup, 612 PORT_VLAN_MAP); 613 data1 &= ~0x3f; 614 data1 |= vg->es_member_ports; 615 MDIO_WRITEREG(device_get_parent(dev), 616 CORE_REGISTER + sc->smi_offset + vg->es_vlangroup, 617 PORT_VLAN_MAP, data1); 618 } else if (sc->vlan_mode == ETHERSWITCH_VLAN_DOT1Q) { 619 if (vg->es_vlangroup == 0) 620 return (0); 621 data1 = 0; 622 data2 = 0; 623 for (i = 0; i < 6; ++i) { 624 if (vg->es_member_ports & 625 vg->es_untagged_ports & (1 << i)) { 626 if (i < 4) { 627 data1 |= (0xd << i * 4); 628 } else { 629 data2 |= (0xd << (i - 4) * 4); 630 } 631 } else if (vg->es_member_ports & (1 << i)) { 632 if (i < 4) { 633 data1 |= (0xe << i * 4); 634 } else { 635 data2 |= (0xe << (i - 4) * 4); 636 } 637 } else { 638 if (i < 4) { 639 data1 |= (0x3 << i * 4); 640 } else { 641 data2 |= (0x3 << (i - 4) * 4); 642 } 643 } 644 } 645 e6060sw_set_vtu(dev, vg->es_vlangroup, data1, data2); 646 } 647 return (0); 648 } 649 650 static void 651 e6060sw_reset_vlans(device_t dev) 652 { 653 struct e6060sw_softc *sc; 654 uint32_t ports; 655 int i; 656 int data; 657 658 sc = device_get_softc(dev); 659 660 for (i = 0; i <= sc->numports; i++) { 661 ports = (1 << (sc->numports + 1)) - 1; 662 ports &= ~(1 << i); 663 if (sc->vlan_mode == ETHERSWITCH_VLAN_PORT) { 664 data = i << 12; 665 } else if (sc->vlan_mode == 0) { 666 data = 1 << 8; 667 } else { 668 data = 0; 669 } 670 data |= ports; 671 MDIO_WRITEREG(device_get_parent(dev), 672 CORE_REGISTER + sc->smi_offset + i, PORT_VLAN_MAP, data); 673 } 674 } 675 676 static void 677 e6060sw_setup(device_t dev) 678 { 679 struct e6060sw_softc *sc; 680 int i; 681 int data; 682 683 sc = device_get_softc(dev); 684 685 for (i = 0; i <= sc->numports; i++) { 686 if (sc->sw_model == E6063 || sc->sw_model == E6065) { 687 data = MDIO_READREG(device_get_parent(dev), 688 CORE_REGISTER + sc->smi_offset + i, PORT_VLAN_MAP); 689 data &= ~(FORCEMAPMASK << FORCEMAPSHIFT); 690 MDIO_WRITEREG(device_get_parent(dev), 691 CORE_REGISTER + sc->smi_offset + i, 692 PORT_VLAN_MAP, data); 693 694 data = MDIO_READREG(device_get_parent(dev), 695 CORE_REGISTER + sc->smi_offset + i, PORT_CONTROL); 696 data |= 3 << ENGRESSFSHIFT; 697 MDIO_WRITEREG(device_get_parent(dev), 698 CORE_REGISTER + sc->smi_offset + i, 699 PORT_CONTROL, data); 700 } 701 } 702 } 703 704 static void 705 e6060sw_dot1q_mode(device_t dev, int mode) 706 { 707 struct e6060sw_softc *sc; 708 int i; 709 int data; 710 711 sc = device_get_softc(dev); 712 713 for (i = 0; i <= sc->numports; i++) { 714 data = MDIO_READREG(device_get_parent(dev), 715 CORE_REGISTER + sc->smi_offset + i, PORT_CONTROL2); 716 data &= ~(DOT1QMODEMASK << DOT1QMODESHIFT); 717 data |= mode << DOT1QMODESHIFT; 718 MDIO_WRITEREG(device_get_parent(dev), 719 CORE_REGISTER + sc->smi_offset + i, PORT_CONTROL2, data); 720 721 data = MDIO_READREG(device_get_parent(dev), 722 CORE_REGISTER + sc->smi_offset + i, 723 PORT_DEFVLAN); 724 data &= ~0xfff; 725 data |= 1; 726 MDIO_WRITEREG(device_get_parent(dev), 727 CORE_REGISTER + sc->smi_offset + i, 728 PORT_DEFVLAN, data); 729 } 730 } 731 732 static int 733 e6060sw_getconf(device_t dev, etherswitch_conf_t *conf) 734 { 735 struct e6060sw_softc *sc; 736 737 sc = device_get_softc(dev); 738 739 /* Return the VLAN mode. */ 740 conf->cmd = ETHERSWITCH_CONF_VLAN_MODE; 741 conf->vlan_mode = sc->vlan_mode; 742 743 return (0); 744 } 745 746 static void 747 e6060sw_init_vtu(device_t dev) 748 { 749 struct e6060sw_softc *sc; 750 int busy; 751 752 sc = device_get_softc(dev); 753 754 MDIO_WRITEREG(device_get_parent(dev), GLOBAL_REGISTER + sc->smi_offset, 755 VTU_OPERATION, VTU_BUSY | (VTU_FLASH << 12)); 756 while (1) { 757 busy = MDIO_READREG(device_get_parent(dev), 758 GLOBAL_REGISTER + sc->smi_offset, VTU_OPERATION); 759 if ((busy & VTU_BUSY) == 0) 760 break; 761 } 762 763 /* initial member set at vlan 1*/ 764 MDIO_WRITEREG(device_get_parent(dev), GLOBAL_REGISTER + sc->smi_offset, 765 VTU_DATA1_REG, 0xcccc); 766 MDIO_WRITEREG(device_get_parent(dev), GLOBAL_REGISTER + sc->smi_offset, 767 VTU_DATA2_REG, 0x00cc); 768 MDIO_WRITEREG(device_get_parent(dev), GLOBAL_REGISTER + sc->smi_offset, 769 VTU_VID_REG, 0x1000 | 1); 770 MDIO_WRITEREG(device_get_parent(dev), GLOBAL_REGISTER + sc->smi_offset, 771 VTU_OPERATION, VTU_BUSY | (VTU_LOAD_PURGE << 12) | 1); 772 while (1) { 773 busy = MDIO_READREG(device_get_parent(dev), 774 GLOBAL_REGISTER + sc->smi_offset, VTU_OPERATION); 775 if ((busy & VTU_BUSY) == 0) 776 break; 777 } 778 } 779 780 static void 781 e6060sw_set_vtu(device_t dev, int num, int data1, int data2) 782 { 783 struct e6060sw_softc *sc; 784 int busy; 785 786 sc = device_get_softc(dev); 787 788 MDIO_WRITEREG(device_get_parent(dev), GLOBAL_REGISTER + sc->smi_offset, 789 VTU_DATA1_REG, data1); 790 MDIO_WRITEREG(device_get_parent(dev), GLOBAL_REGISTER + sc->smi_offset, 791 VTU_DATA2_REG, data2); 792 MDIO_WRITEREG(device_get_parent(dev), GLOBAL_REGISTER + sc->smi_offset, 793 VTU_VID_REG, 0x1000 | num); 794 MDIO_WRITEREG(device_get_parent(dev), GLOBAL_REGISTER + sc->smi_offset, 795 VTU_OPERATION, VTU_BUSY | (VTU_LOAD_PURGE << 12) | num); 796 while (1) { 797 busy = MDIO_READREG(device_get_parent(dev), 798 GLOBAL_REGISTER + sc->smi_offset, VTU_OPERATION); 799 if ((busy & VTU_BUSY) == 0) 800 break; 801 } 802 803 } 804 805 static int 806 e6060sw_read_vtu(device_t dev, int num, int *data1, int *data2) 807 { 808 struct e6060sw_softc *sc; 809 int busy; 810 811 sc = device_get_softc(dev); 812 813 num = num - 1; 814 815 MDIO_WRITEREG(device_get_parent(dev), GLOBAL_REGISTER + sc->smi_offset, 816 VTU_VID_REG, num & 0xfff); 817 /* Get Next */ 818 MDIO_WRITEREG(device_get_parent(dev), GLOBAL_REGISTER + sc->smi_offset, 819 VTU_OPERATION, VTU_BUSY | (VTU_GET_NEXT << 12)); 820 while (1) { 821 busy = MDIO_READREG(device_get_parent(dev), 822 GLOBAL_REGISTER + sc->smi_offset, VTU_OPERATION); 823 if ((busy & VTU_BUSY) == 0) 824 break; 825 } 826 827 int vid = MDIO_READREG(device_get_parent(dev), 828 GLOBAL_REGISTER + sc->smi_offset, VTU_VID_REG); 829 if (vid & 0x1000) { 830 *data1 = MDIO_READREG(device_get_parent(dev), 831 GLOBAL_REGISTER + sc->smi_offset, VTU_DATA1_REG); 832 *data2 = MDIO_READREG(device_get_parent(dev), 833 GLOBAL_REGISTER + sc->smi_offset, VTU_DATA2_REG); 834 835 return (vid & 0xfff); 836 } 837 838 return (-1); 839 } 840 841 static int 842 e6060sw_setconf(device_t dev, etherswitch_conf_t *conf) 843 { 844 struct e6060sw_softc *sc; 845 846 sc = device_get_softc(dev); 847 848 /* Set the VLAN mode. */ 849 if (conf->cmd & ETHERSWITCH_CONF_VLAN_MODE) { 850 if (conf->vlan_mode == ETHERSWITCH_VLAN_PORT) { 851 sc->vlan_mode = ETHERSWITCH_VLAN_PORT; 852 e6060sw_dot1q_mode(dev, DOT1QNONE); 853 e6060sw_reset_vlans(dev); 854 } else if ((sc->sw_model == E6063 || sc->sw_model == E6065) && 855 conf->vlan_mode == ETHERSWITCH_VLAN_DOT1Q) { 856 sc->vlan_mode = ETHERSWITCH_VLAN_DOT1Q; 857 e6060sw_dot1q_mode(dev, DOT1QSECURE); 858 e6060sw_init_vtu(dev); 859 } else { 860 sc->vlan_mode = 0; 861 /* Reset VLANs. */ 862 e6060sw_dot1q_mode(dev, DOT1QNONE); 863 e6060sw_reset_vlans(dev); 864 } 865 } 866 867 return (0); 868 } 869 870 static void 871 e6060sw_statchg(device_t dev) 872 { 873 874 DPRINTF(dev, "%s\n", __func__); 875 } 876 877 static int 878 e6060sw_ifmedia_upd(struct ifnet *ifp) 879 { 880 struct e6060sw_softc *sc; 881 struct mii_data *mii; 882 883 sc = ifp->if_softc; 884 mii = e6060sw_miiforport(sc, ifp->if_dunit); 885 886 DPRINTF(sc->sc_dev, "%s\n", __func__); 887 if (mii == NULL) 888 return (ENXIO); 889 mii_mediachg(mii); 890 return (0); 891 } 892 893 static void 894 e6060sw_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) 895 { 896 struct e6060sw_softc *sc; 897 struct mii_data *mii; 898 899 sc = ifp->if_softc; 900 mii = e6060sw_miiforport(sc, ifp->if_dunit); 901 902 DPRINTF(sc->sc_dev, "%s\n", __func__); 903 904 if (mii == NULL) 905 return; 906 mii_pollstat(mii); 907 ifmr->ifm_active = mii->mii_media_active; 908 ifmr->ifm_status = mii->mii_media_status; 909 } 910 911 static int 912 e6060sw_readphy(device_t dev, int phy, int reg) 913 { 914 struct e6060sw_softc *sc; 915 int data; 916 917 sc = device_get_softc(dev); 918 E6060SW_LOCK_ASSERT(sc, MA_NOTOWNED); 919 920 if (phy < 0 || phy >= 32) 921 return (ENXIO); 922 if (reg < 0 || reg >= 32) 923 return (ENXIO); 924 925 E6060SW_LOCK(sc); 926 data = MDIO_READREG(device_get_parent(dev), phy, reg); 927 E6060SW_UNLOCK(sc); 928 929 return (data); 930 } 931 932 static int 933 e6060sw_writephy(device_t dev, int phy, int reg, int data) 934 { 935 struct e6060sw_softc *sc; 936 int err; 937 938 sc = device_get_softc(dev); 939 E6060SW_LOCK_ASSERT(sc, MA_NOTOWNED); 940 941 if (phy < 0 || phy >= 32) 942 return (ENXIO); 943 if (reg < 0 || reg >= 32) 944 return (ENXIO); 945 946 E6060SW_LOCK(sc); 947 err = MDIO_WRITEREG(device_get_parent(dev), phy, reg, data); 948 E6060SW_UNLOCK(sc); 949 950 return (err); 951 } 952 953 /* addr is 5-8 bit is SMI Device Addres, 0-4 bit is SMI Register Address */ 954 955 static int 956 e6060sw_readreg(device_t dev, int addr) 957 { 958 int devaddr, regaddr; 959 960 devaddr = (addr >> 5) & 0x1f; 961 regaddr = addr & 0x1f; 962 963 return MDIO_READREG(device_get_parent(dev), devaddr, regaddr); 964 } 965 966 /* addr is 5-8 bit is SMI Device Addres, 0-4 bit is SMI Register Address */ 967 968 static int 969 e6060sw_writereg(device_t dev, int addr, int value) 970 { 971 int devaddr, regaddr; 972 973 devaddr = (addr >> 5) & 0x1f; 974 regaddr = addr & 0x1f; 975 976 return (MDIO_WRITEREG(device_get_parent(dev), devaddr, regaddr, value)); 977 } 978 979 static device_method_t e6060sw_methods[] = { 980 /* Device interface */ 981 DEVMETHOD(device_probe, e6060sw_probe), 982 DEVMETHOD(device_attach, e6060sw_attach), 983 DEVMETHOD(device_detach, e6060sw_detach), 984 985 /* bus interface */ 986 DEVMETHOD(bus_add_child, device_add_child_ordered), 987 988 /* MII interface */ 989 DEVMETHOD(miibus_readreg, e6060sw_readphy), 990 DEVMETHOD(miibus_writereg, e6060sw_writephy), 991 DEVMETHOD(miibus_statchg, e6060sw_statchg), 992 993 /* MDIO interface */ 994 DEVMETHOD(mdio_readreg, e6060sw_readphy), 995 DEVMETHOD(mdio_writereg, e6060sw_writephy), 996 997 /* etherswitch interface */ 998 DEVMETHOD(etherswitch_lock, e6060sw_lock), 999 DEVMETHOD(etherswitch_unlock, e6060sw_unlock), 1000 DEVMETHOD(etherswitch_getinfo, e6060sw_getinfo), 1001 DEVMETHOD(etherswitch_readreg, e6060sw_readreg), 1002 DEVMETHOD(etherswitch_writereg, e6060sw_writereg), 1003 DEVMETHOD(etherswitch_readphyreg, e6060sw_readphy), 1004 DEVMETHOD(etherswitch_writephyreg, e6060sw_writephy), 1005 DEVMETHOD(etherswitch_getport, e6060sw_getport), 1006 DEVMETHOD(etherswitch_setport, e6060sw_setport), 1007 DEVMETHOD(etherswitch_getvgroup, e6060sw_getvgroup), 1008 DEVMETHOD(etherswitch_setvgroup, e6060sw_setvgroup), 1009 DEVMETHOD(etherswitch_setconf, e6060sw_setconf), 1010 DEVMETHOD(etherswitch_getconf, e6060sw_getconf), 1011 1012 DEVMETHOD_END 1013 }; 1014 1015 DEFINE_CLASS_0(e6060sw, e6060sw_driver, e6060sw_methods, 1016 sizeof(struct e6060sw_softc)); 1017 static devclass_t e6060sw_devclass; 1018 1019 DRIVER_MODULE(e6060sw, mdio, e6060sw_driver, e6060sw_devclass, 0, 0); 1020 DRIVER_MODULE(miibus, e6060sw, miibus_driver, miibus_devclass, 0, 0); 1021 DRIVER_MODULE(mdio, e6060sw, mdio_driver, mdio_devclass, 0, 0); 1022 DRIVER_MODULE(etherswitch, e6060sw, etherswitch_driver, etherswitch_devclass, 0, 0); 1023 MODULE_VERSION(e6060sw, 1); 1024 MODULE_DEPEND(e6060sw, miibus, 1, 1, 1); /* XXX which versions? */ 1025 MODULE_DEPEND(e6060sw, etherswitch, 1, 1, 1); /* XXX which versions? */ 1026