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