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