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