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