1 /* 2 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* 7 * Copyright (c) 1998 The NetBSD Foundation, Inc. 8 * All rights reserved. 9 * 10 * This code is derived from software contributed to The NetBSD Foundation 11 * by Frank van der Linden. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 23 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 25 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 26 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 * POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 #include <sys/varargs.h> 36 #include <sys/types.h> 37 #include <sys/modctl.h> 38 #include <sys/conf.h> 39 #include <sys/devops.h> 40 #include <sys/stream.h> 41 #include <sys/strsun.h> 42 #include <sys/cmn_err.h> 43 #include <sys/ethernet.h> 44 #include <sys/pci.h> 45 #include <sys/kmem.h> 46 #include <sys/time.h> 47 #include <sys/mii.h> 48 #include <sys/miiregs.h> 49 #include <sys/mac_ether.h> 50 #include <sys/mac_provider.h> 51 #include <sys/strsubr.h> 52 #include <sys/pattr.h> 53 #include <sys/dlpi.h> 54 #include <sys/ddi.h> 55 #include <sys/sunddi.h> 56 57 #include <sys/vlan.h> 58 59 #include "elxl.h" 60 61 static boolean_t elxl_add_intr(elxl_t *); 62 static void elxl_probe_media(elxl_t *); 63 static void elxl_set_rxfilter(elxl_t *); 64 static void elxl_set_media(elxl_t *); 65 static uint16_t elxl_read_eeprom(elxl_t *, int); 66 static void elxl_init(elxl_t *); 67 static void elxl_stop(elxl_t *); 68 static void elxl_reset(elxl_t *); 69 static void elxl_getstats(elxl_t *); 70 71 static int elxl_eeprom_busy(elxl_t *); 72 73 static void elxl_setup_tx(elxl_t *); 74 75 static uint16_t elxl_mii_read(void *, uint8_t, uint8_t); 76 static void elxl_mii_write(void *, uint8_t, uint8_t, uint16_t); 77 static void elxl_mii_notify(void *, link_state_t); 78 79 static int elxl_m_stat(void *, uint_t, uint64_t *); 80 static int elxl_m_start(void *); 81 static void elxl_m_stop(void *); 82 static mblk_t *elxl_m_tx(void *, mblk_t *); 83 static int elxl_m_promisc(void *, boolean_t); 84 static int elxl_m_multicst(void *, boolean_t, const uint8_t *); 85 static int elxl_m_unicst(void *, const uint8_t *); 86 static int elxl_m_getprop(void *, const char *, mac_prop_id_t, uint_t, 87 void *); 88 static int elxl_m_setprop(void *, const char *, mac_prop_id_t, uint_t, 89 const void *); 90 static void elxl_m_propinfo(void *, const char *, mac_prop_id_t, 91 mac_prop_info_handle_t); 92 static boolean_t elxl_m_getcapab(void *, mac_capab_t cap, void *); 93 static uint_t elxl_intr(caddr_t, caddr_t); 94 static void elxl_error(elxl_t *, char *, ...); 95 static void elxl_linkcheck(void *); 96 static int elxl_attach(dev_info_t *); 97 static void elxl_detach(elxl_t *); 98 static void elxl_suspend(elxl_t *); 99 static void elxl_resume(dev_info_t *); 100 static int elxl_ddi_attach(dev_info_t *, ddi_attach_cmd_t); 101 static int elxl_ddi_detach(dev_info_t *, ddi_detach_cmd_t); 102 static int elxl_ddi_quiesce(dev_info_t *); 103 104 static ddi_device_acc_attr_t ex_dev_acc_attr = { 105 DDI_DEVICE_ATTR_V0, 106 DDI_STRUCTURE_LE_ACC, 107 DDI_STRICTORDER_ACC 108 }; 109 110 static ddi_device_acc_attr_t ex_buf_acc_attr = { 111 DDI_DEVICE_ATTR_V0, 112 DDI_NEVERSWAP_ACC, 113 DDI_STORECACHING_OK_ACC 114 }; 115 116 /* 117 * In theory buffers can have more flexible DMA attributes, but since 118 * we're just using a preallocated region with bcopy, there is little 119 * reason to allow for rougher alignment. (Further, the 8-byte 120 * alignment can allow for more efficient bcopy and similar operations 121 * from the buffer.) 122 */ 123 static ddi_dma_attr_t ex_dma_attr = { 124 DMA_ATTR_V0, /* dma_attr_version */ 125 0, /* dma_attr_addr_lo */ 126 0xFFFFFFFFU, /* dma_attr_addr_hi */ 127 0x00FFFFFFU, /* dma_attr_count_max */ 128 8, /* dma_attr_align */ 129 0x7F, /* dma_attr_burstsizes */ 130 1, /* dma_attr_minxfer */ 131 0xFFFFFFFFU, /* dma_attr_maxxfer */ 132 0xFFFFFFFFU, /* dma_attr_seg */ 133 1, /* dma_attr_sgllen */ 134 1, /* dma_attr_granular */ 135 0 /* dma_attr_flags */ 136 }; 137 138 static uint8_t ex_broadcast[6] = { 139 0xff, 0xff, 0xff, 0xff, 0xff, 0xff 140 }; 141 142 /* 143 * Structure to map media-present bits in boards to ifmedia codes and 144 * printable media names. Used for table-driven ifmedia initialization. 145 */ 146 typedef struct ex_media { 147 int exm_mpbit; /* media present bit */ 148 int exm_xcvr; /* XCVR_SEL_* constant */ 149 } ex_media_t; 150 151 /* 152 * Media table for 3c90x chips. Note that chips with MII have no 153 * `native' media. This is sorted in "reverse preference". 154 */ 155 static ex_media_t ex_native_media[] = { 156 { MEDIAOPT_AUI, XCVR_SEL_AUI }, 157 { MEDIAOPT_BNC, XCVR_SEL_BNC }, 158 { MEDIAOPT_10T, XCVR_SEL_10T }, 159 { MEDIAOPT_100TX, XCVR_SEL_AUTO }, /* only 90XB */ 160 { MEDIAOPT_100FX, XCVR_SEL_100FX }, 161 { MEDIAOPT_MII, XCVR_SEL_MII }, 162 { MEDIAOPT_100T4, XCVR_SEL_MII }, 163 { 0, 0 }, 164 }; 165 166 167 /* 168 * NB: There are lots of other models that *could* be supported. 169 * Specifically there are cardbus and miniPCI variants that could be 170 * easily added here, but they require special hacks and I have no 171 * access to the hardware required to verify them. Especially they 172 * seem to require some extra work in another register window, and I 173 * have no supporting documentation. 174 */ 175 static const struct ex_product { 176 uint16_t epp_prodid; /* PCI product ID */ 177 const char *epp_name; /* device name */ 178 unsigned epp_flags; /* initial softc flags */ 179 } ex_products[] = { 180 { 0x4500, "3c450-TX", 0 }, 181 { 0x7646, "3cSOHO100-TX", 0 }, 182 { 0x9000, "3c900-TPO", 0 }, 183 { 0x9001, "3c900-COMBO", 0 }, 184 { 0x9004, "3c900B-TPO", 0 }, 185 { 0x9005, "3c900B-COMBO", 0 }, 186 { 0x9006, "3c900B-TPC", 0 }, 187 { 0x900a, "3c900B-FL", 0 }, 188 { 0x9050, "3c905-TX", 0 }, 189 { 0x9051, "3c905-T4", 0 }, 190 { 0x9055, "3c905B-TX", 0 }, 191 { 0x9056, "3c905B-T4", 0 }, 192 { 0x9058, "3c905B-COMBO", 0 }, 193 { 0x905a, "3c905B-FX", 0 }, 194 { 0x9200, "3c905C-TX", 0 }, 195 { 0x9201, "3c920B-EMB", 0 }, 196 { 0x9202, "3c920B-EMB-WNM", 0 }, 197 { 0x9800, "3c980", 0 }, 198 { 0x9805, "3c980C-TXM", 0 }, 199 200 { 0, NULL, 0 }, 201 }; 202 203 static char *ex_priv_prop[] = { 204 "_media", 205 "_available_media", 206 NULL 207 }; 208 209 static mii_ops_t ex_mii_ops = { 210 MII_OPS_VERSION, 211 elxl_mii_read, 212 elxl_mii_write, 213 elxl_mii_notify, 214 }; 215 216 static mac_callbacks_t elxl_m_callbacks = { 217 MC_GETCAPAB | MC_PROPERTIES, 218 elxl_m_stat, 219 elxl_m_start, 220 elxl_m_stop, 221 elxl_m_promisc, 222 elxl_m_multicst, 223 elxl_m_unicst, 224 elxl_m_tx, 225 NULL, 226 NULL, 227 elxl_m_getcapab, 228 NULL, 229 NULL, 230 elxl_m_setprop, 231 elxl_m_getprop, 232 elxl_m_propinfo 233 }; 234 235 /* 236 * Stream information 237 */ 238 DDI_DEFINE_STREAM_OPS(ex_devops, nulldev, nulldev, 239 elxl_ddi_attach, elxl_ddi_detach, 240 nodev, NULL, D_MP, NULL, elxl_ddi_quiesce); 241 242 /* 243 * Module linkage information. 244 */ 245 246 static struct modldrv ex_modldrv = { 247 &mod_driverops, /* drv_modops */ 248 "3Com EtherLink XL", /* drv_linkinfo */ 249 &ex_devops /* drv_dev_ops */ 250 }; 251 252 static struct modlinkage ex_modlinkage = { 253 MODREV_1, /* ml_rev */ 254 { &ex_modldrv, NULL } /* ml_linkage */ 255 }; 256 257 int 258 _init(void) 259 { 260 int rv; 261 mac_init_ops(&ex_devops, "elxl"); 262 if ((rv = mod_install(&ex_modlinkage)) != DDI_SUCCESS) { 263 mac_fini_ops(&ex_devops); 264 } 265 return (rv); 266 } 267 268 int 269 _fini(void) 270 { 271 int rv; 272 if ((rv = mod_remove(&ex_modlinkage)) == DDI_SUCCESS) { 273 mac_fini_ops(&ex_devops); 274 } 275 return (rv); 276 } 277 278 int 279 _info(struct modinfo *modinfop) 280 { 281 return (mod_info(&ex_modlinkage, modinfop)); 282 } 283 284 static void 285 ex_free_ring(ex_ring_t *r) 286 { 287 for (int i = 0; i < r->r_count; i++) { 288 ex_desc_t *ed = &r->r_desc[i]; 289 if (ed->ed_bufaddr) 290 (void) ddi_dma_unbind_handle(ed->ed_dmah); 291 if (ed->ed_acch) 292 ddi_dma_mem_free(&ed->ed_acch); 293 if (ed->ed_dmah) 294 ddi_dma_free_handle(&ed->ed_dmah); 295 } 296 297 if (r->r_paddr) 298 (void) ddi_dma_unbind_handle(r->r_dmah); 299 if (r->r_acch) 300 ddi_dma_mem_free(&r->r_acch); 301 if (r->r_dmah) 302 ddi_dma_free_handle(&r->r_dmah); 303 304 kmem_free(r->r_desc, sizeof (ex_desc_t) * r->r_count); 305 r->r_desc = NULL; 306 } 307 308 static void 309 elxl_reset_ring(ex_ring_t *r, uint_t dir) 310 { 311 ex_desc_t *ed; 312 ex_pd_t *pd; 313 314 if (dir == DDI_DMA_WRITE) { 315 /* transmit ring, not linked yet */ 316 for (int i = 0; i < r->r_count; i++) { 317 ed = &r->r_desc[i]; 318 pd = ed->ed_pd; 319 PUT_PD(r, pd->pd_link, 0); 320 PUT_PD(r, pd->pd_fsh, 0); 321 PUT_PD(r, pd->pd_len, EX_FR_LAST); 322 PUT_PD(r, pd->pd_addr, ed->ed_bufaddr); 323 } 324 r->r_head = NULL; 325 r->r_tail = NULL; 326 r->r_avail = r->r_count; 327 } else { 328 /* receive is linked into a list */ 329 for (int i = 0; i < r->r_count; i++) { 330 ed = &r->r_desc[i]; 331 pd = ed->ed_pd; 332 PUT_PD(r, pd->pd_link, ed->ed_next->ed_descaddr); 333 PUT_PD(r, pd->pd_status, 0); 334 PUT_PD(r, pd->pd_len, EX_BUFSZ | EX_FR_LAST); 335 PUT_PD(r, pd->pd_addr, ed->ed_bufaddr); 336 } 337 r->r_head = &r->r_desc[0]; 338 r->r_tail = NULL; 339 r->r_avail = 0; 340 } 341 (void) ddi_dma_sync(r->r_dmah, 0, 0, DDI_DMA_SYNC_FORDEV); 342 } 343 344 static boolean_t 345 ex_alloc_ring(elxl_t *sc, int count, ex_ring_t *r, uint_t dir) 346 { 347 dev_info_t *dip = sc->ex_dip; 348 int i; 349 int rv; 350 size_t len; 351 ddi_dma_cookie_t dmac; 352 unsigned ndmac; 353 354 r->r_count = count; 355 r->r_desc = kmem_zalloc(sizeof (ex_desc_t) * count, KM_SLEEP); 356 357 rv = ddi_dma_alloc_handle(dip, &ex_dma_attr, DDI_DMA_DONTWAIT, 358 NULL, &r->r_dmah); 359 if (rv != DDI_SUCCESS) { 360 elxl_error(sc, "unable to allocate descriptor dma handle"); 361 return (B_FALSE); 362 } 363 364 rv = ddi_dma_mem_alloc(r->r_dmah, count * sizeof (struct ex_pd), 365 &ex_dev_acc_attr, DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, NULL, 366 (caddr_t *)&r->r_pd, &len, &r->r_acch); 367 if (rv != DDI_SUCCESS) { 368 elxl_error(sc, "unable to allocate descriptor memory"); 369 return (B_FALSE); 370 } 371 bzero(r->r_pd, len); 372 373 rv = ddi_dma_addr_bind_handle(r->r_dmah, NULL, 374 (caddr_t)r->r_pd, len, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 375 DDI_DMA_DONTWAIT, NULL, &dmac, &ndmac); 376 if (rv != DDI_DMA_MAPPED) { 377 elxl_error(sc, "unable to map descriptor memory"); 378 return (B_FALSE); 379 } 380 r->r_paddr = dmac.dmac_address; 381 382 for (i = 0; i < count; i++) { 383 ex_desc_t *ed = &r->r_desc[i]; 384 ex_pd_t *pd = &r->r_pd[i]; 385 386 ed->ed_pd = pd; 387 ed->ed_off = (i * sizeof (ex_pd_t)); 388 ed->ed_descaddr = r->r_paddr + (i * sizeof (ex_pd_t)); 389 390 /* Link the high level descriptors into a ring. */ 391 ed->ed_next = &r->r_desc[(i + 1) % count]; 392 ed->ed_next->ed_prev = ed; 393 394 rv = ddi_dma_alloc_handle(dip, &ex_dma_attr, 395 DDI_DMA_DONTWAIT, NULL, &ed->ed_dmah); 396 if (rv != 0) { 397 elxl_error(sc, "can't allocate buf dma handle"); 398 return (B_FALSE); 399 } 400 rv = ddi_dma_mem_alloc(ed->ed_dmah, EX_BUFSZ, &ex_buf_acc_attr, 401 DDI_DMA_STREAMING, DDI_DMA_DONTWAIT, NULL, &ed->ed_buf, 402 &len, &ed->ed_acch); 403 if (rv != DDI_SUCCESS) { 404 elxl_error(sc, "unable to allocate buf memory"); 405 return (B_FALSE); 406 } 407 bzero(ed->ed_buf, len); 408 409 rv = ddi_dma_addr_bind_handle(ed->ed_dmah, NULL, 410 ed->ed_buf, len, dir | DDI_DMA_STREAMING, 411 DDI_DMA_DONTWAIT, NULL, &dmac, &ndmac); 412 if (rv != DDI_DMA_MAPPED) { 413 elxl_error(sc, "unable to map buf memory"); 414 return (B_FALSE); 415 } 416 ed->ed_bufaddr = dmac.dmac_address; 417 } 418 419 elxl_reset_ring(r, dir); 420 421 return (B_TRUE); 422 } 423 424 static boolean_t 425 elxl_add_intr(elxl_t *sc) 426 { 427 dev_info_t *dip; 428 int actual; 429 uint_t ipri; 430 431 int rv; 432 433 dip = sc->ex_dip; 434 435 rv = ddi_intr_alloc(dip, &sc->ex_intrh, DDI_INTR_TYPE_FIXED, 436 0, 1, &actual, DDI_INTR_ALLOC_STRICT); 437 if ((rv != DDI_SUCCESS) || (actual != 1)) { 438 elxl_error(sc, "Unable to allocate interrupt, %d, count %d", 439 rv, actual); 440 return (B_FALSE); 441 } 442 443 if (ddi_intr_get_pri(sc->ex_intrh, &ipri) != DDI_SUCCESS) { 444 elxl_error(sc, "Unable to get interrupt priority"); 445 return (B_FALSE); 446 } 447 448 if (ddi_intr_add_handler(sc->ex_intrh, elxl_intr, sc, NULL) != 449 DDI_SUCCESS) { 450 elxl_error(sc, "Can't add interrupt handler"); 451 (void) ddi_intr_free(sc->ex_intrh); 452 sc->ex_intrh = NULL; 453 return (B_FALSE); 454 } 455 mutex_init(&sc->ex_intrlock, NULL, MUTEX_DRIVER, DDI_INTR_PRI(ipri)); 456 mutex_init(&sc->ex_txlock, NULL, MUTEX_DRIVER, DDI_INTR_PRI(ipri)); 457 458 return (B_TRUE); 459 } 460 461 static int 462 elxl_attach(dev_info_t *dip) 463 { 464 elxl_t *sc; 465 mac_register_t *macp; 466 uint16_t val; 467 uint16_t venid; 468 uint16_t devid; 469 int i; 470 471 sc = kmem_zalloc(sizeof (*sc), KM_SLEEP); 472 ddi_set_driver_private(dip, sc); 473 sc->ex_dip = dip; 474 475 if (pci_config_setup(dip, &sc->ex_pcih) != DDI_SUCCESS) { 476 elxl_error(sc, "unable to setup PCI config handle"); 477 goto fail; 478 } 479 venid = pci_config_get16(sc->ex_pcih, PCI_CONF_VENID); 480 devid = pci_config_get16(sc->ex_pcih, PCI_CONF_DEVID); 481 482 if (venid != 0x10b7) { 483 /* Not a 3Com part! */ 484 elxl_error(sc, "Unsupported vendor id (0x%x)", venid); 485 goto fail; 486 } 487 for (i = 0; ex_products[i].epp_name; i++) { 488 if (devid == ex_products[i].epp_prodid) { 489 cmn_err(CE_CONT, "?%s%d: 3Com %s", 490 ddi_driver_name(dip), 491 ddi_get_instance(dip), 492 ex_products[i].epp_name); 493 sc->ex_conf = ex_products[i].epp_flags; 494 break; 495 } 496 } 497 if (ex_products[i].epp_name == NULL) { 498 /* Not a produce we know how to support */ 499 elxl_error(sc, "Unsupported device id (0x%x)", devid); 500 elxl_error(sc, "Driver may or may not function."); 501 } 502 503 pci_config_put16(sc->ex_pcih, PCI_CONF_COMM, 504 pci_config_get16(sc->ex_pcih, PCI_CONF_COMM) | 505 PCI_COMM_IO | PCI_COMM_MAE | PCI_COMM_ME); 506 507 if (ddi_regs_map_setup(dip, 1, &sc->ex_regsva, 0, 0, &ex_dev_acc_attr, 508 &sc->ex_regsh) != DDI_SUCCESS) { 509 elxl_error(sc, "Unable to map device registers"); 510 goto fail; 511 } 512 513 if (!elxl_add_intr(sc)) { 514 goto fail; 515 } 516 517 elxl_reset(sc); 518 519 val = elxl_read_eeprom(sc, EE_OEM_ADDR_0); 520 sc->ex_factaddr[0] = val >> 8; 521 sc->ex_factaddr[1] = val & 0xff; 522 val = elxl_read_eeprom(sc, EE_OEM_ADDR_1); 523 sc->ex_factaddr[2] = val >> 8; 524 sc->ex_factaddr[3] = val & 0xff; 525 val = elxl_read_eeprom(sc, EE_OEM_ADDR_2); 526 sc->ex_factaddr[4] = val >> 8; 527 sc->ex_factaddr[5] = val & 0xff; 528 bcopy(sc->ex_factaddr, sc->ex_curraddr, 6); 529 530 sc->ex_capab = elxl_read_eeprom(sc, EE_CAPABILITIES); 531 532 /* 533 * Is this a 90XB? If bit 2 (supportsLargePackets) is set, or 534 * bit (supportsNoTxLength) is clear, then its a 90X. 535 * Otherwise its a 90XB. 536 */ 537 if ((sc->ex_capab & (1 << 2)) || !(sc->ex_capab & (1 << 9))) { 538 sc->ex_conf &= ~CONF_90XB; 539 } else { 540 sc->ex_conf |= CONF_90XB; 541 } 542 543 if (!ex_alloc_ring(sc, EX_NRX, &sc->ex_rxring, DDI_DMA_READ)) { 544 goto fail; 545 } 546 547 if (!ex_alloc_ring(sc, EX_NTX, &sc->ex_txring, DDI_DMA_WRITE)) { 548 goto fail; 549 } 550 551 elxl_probe_media(sc); 552 553 /* 554 * The probe may have indicated MII! 555 */ 556 if (sc->ex_mediaopt & (MEDIAOPT_MII | MEDIAOPT_100TX)) { 557 sc->ex_miih = mii_alloc(sc, sc->ex_dip, &ex_mii_ops); 558 if (sc->ex_miih == NULL) { 559 goto fail; 560 } 561 /* 562 * Note: The 90XB models can in theory support pause, 563 * but we're not enabling now due to lack of units for 564 * testing with. If this is changed, make sure to 565 * update the code in elxl_mii_notify to set the flow 566 * control field in the W3_MAC_CONTROL register. 567 */ 568 mii_set_pauseable(sc->ex_miih, B_FALSE, B_FALSE); 569 } 570 if ((macp = mac_alloc(MAC_VERSION)) == NULL) { 571 elxl_error(sc, "MAC register allocation failed"); 572 goto fail; 573 } 574 macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER; 575 macp->m_driver = sc; 576 macp->m_dip = dip; 577 macp->m_src_addr = sc->ex_curraddr; 578 macp->m_callbacks = &elxl_m_callbacks; 579 macp->m_min_sdu = 0; 580 macp->m_max_sdu = ETHERMTU; 581 macp->m_margin = VLAN_TAGSZ; 582 macp->m_priv_props = ex_priv_prop; 583 584 (void) ddi_intr_enable(sc->ex_intrh); 585 586 if (mac_register(macp, &sc->ex_mach) == DDI_SUCCESS) { 587 588 /* 589 * Note: we don't want to start link checking 590 * until *after* we have added the MAC handle. 591 */ 592 if (sc->ex_mediaopt & 593 (MEDIAOPT_MASK & ~(MEDIAOPT_MII | MEDIAOPT_100TX))) { 594 595 /* Check non-MII link state once per second. */ 596 sc->ex_linkcheck = 597 ddi_periodic_add(elxl_linkcheck, sc, 10000000, 0); 598 } 599 600 mac_free(macp); 601 return (DDI_SUCCESS); 602 } 603 604 mac_free(macp); 605 606 fail: 607 elxl_detach(sc); 608 return (DDI_FAILURE); 609 } 610 611 /* 612 * Find the media present on non-MII chips, and select the one to use. 613 */ 614 static void 615 elxl_probe_media(elxl_t *sc) 616 { 617 ex_media_t *exm; 618 uint32_t config; 619 uint32_t default_media; 620 uint16_t media_options; 621 622 SET_WIN(3); 623 config = GET32(W3_INTERNAL_CONFIG); 624 media_options = GET16(W3_MEDIAOPT); 625 626 /* 627 * We modify the media_options field so that we have a 628 * consistent view of the media available, without worrying 629 * about the version of ASIC, etc. 630 */ 631 632 /* 633 * 100BASE-TX is handled differently on 90XB from 90X. Older 634 * parts use the external MII to provide this support. 635 */ 636 if (sc->ex_conf & CONF_90XB) { 637 if (media_options & MEDIAOPT_100TX) { 638 /* 639 * 3Com advises that we should only ever use the 640 * auto mode. Notably, it seems that there should 641 * never be a 90XB board with the MEDIAOPT_10T bit set 642 * without this bit. If it happens, the driver will 643 * run in compatible 10BASE-T only mode. 644 */ 645 media_options &= ~MEDIAOPT_10T; 646 } 647 } else { 648 if (media_options & MEDIAOPT_100TX) { 649 /* 650 * If this occurs, we really want to use it like 651 * an MII device. Generally in this situation we 652 * want to use the MII exclusively, and there ought 653 * not be a 10bT transceiver. 654 */ 655 media_options |= MEDIAOPT_MII; 656 media_options &= ~MEDIAOPT_100TX; 657 media_options &= ~MEDIAOPT_10T; 658 659 /* 660 * Additionally, some of these devices map all 661 * internal PHY register at *every* address, not 662 * just the "allowed" address 24. 663 */ 664 sc->ex_conf |= CONF_INTPHY; 665 } 666 /* 667 * Early versions didn't have 10FL models, and used this 668 * bit for something else (VCO). 669 */ 670 media_options &= ~MEDIAOPT_10FL; 671 } 672 if (media_options & MEDIAOPT_100T4) { 673 /* 100BASE-T4 units all use the MII bus. */ 674 media_options |= MEDIAOPT_MII; 675 media_options &= ~MEDIAOPT_100T4; 676 } 677 678 /* Save our media options. */ 679 sc->ex_mediaopt = media_options; 680 681 #define APPEND_MEDIA(str, bit, name) \ 682 if (media_options & (bit)) { \ 683 (void) strlcat(str, *str ? "," : "", sizeof (str)); \ 684 (void) strlcat(str, name, sizeof (str)); \ 685 } 686 687 APPEND_MEDIA(sc->ex_medias, (MEDIAOPT_MII|MEDIAOPT_100TX), "mii"); 688 APPEND_MEDIA(sc->ex_medias, MEDIAOPT_10T, "tp-hdx,tp-fdx"); 689 APPEND_MEDIA(sc->ex_medias, MEDIAOPT_100FX, "fx-hdx,fx-fdx"); 690 APPEND_MEDIA(sc->ex_medias, MEDIAOPT_BNC, "bnc"); 691 APPEND_MEDIA(sc->ex_medias, MEDIAOPT_AUI, "aui"); 692 APPEND_MEDIA(sc->ex_medias, MEDIAOPT_10FL, "fl-hdx,fl-fdx"); 693 694 if (config & XCVR_SEL_100TX) { 695 /* Only found on 90XB. Don't use this, use AUTO instead! */ 696 config |= XCVR_SEL_AUTO; 697 config &= ~XCVR_SEL_100TX; 698 } 699 700 default_media = (config & XCVR_SEL_MASK); 701 702 /* Sanity check that there are any media! */ 703 if ((media_options & MEDIAOPT_MASK) == 0) { 704 elxl_error(sc, 705 "No media present? Attempting to use default."); 706 /* 707 * This "default" may be non-sensical. At worst it should 708 * cause a busted link. 709 */ 710 sc->ex_xcvr = default_media; 711 } 712 713 for (exm = ex_native_media; exm->exm_mpbit != 0; exm++) { 714 if (media_options & exm->exm_mpbit) { 715 if (exm->exm_xcvr == default_media) { 716 /* preferred default is present, just use it */ 717 sc->ex_xcvr = default_media; 718 return; 719 } 720 721 sc->ex_xcvr = exm->exm_xcvr; 722 /* but keep trying for other more preferred options */ 723 } 724 } 725 } 726 727 /* 728 * Setup transmitter parameters. 729 */ 730 static void 731 elxl_setup_tx(elxl_t *sc) 732 { 733 /* 734 * Disable reclaim threshold for 90xB, set free threshold to 735 * 6 * 256 = 1536 for 90x. 736 */ 737 if (sc->ex_conf & CONF_90XB) 738 PUT_CMD(CMD_SET_TXRECLAIM | 255); 739 else 740 PUT8(REG_TXFREETHRESH, 6); 741 742 /* 743 * We've seen underflows at the root cause of NIC hangs on 744 * older cards. Use a store-and-forward model to prevent that. 745 */ 746 PUT_CMD(CMD_SET_TXSTART | EX_BUFSZ >> 2); 747 } 748 749 /* 750 * Bring device up. 751 */ 752 static void 753 elxl_init(elxl_t *sc) 754 { 755 if (sc->ex_suspended) 756 return; 757 758 WAIT_CMD(sc); 759 elxl_stop(sc); 760 761 PUT_CMD(CMD_RX_RESET); 762 WAIT_CMD(sc); 763 PUT_CMD(CMD_TX_RESET); 764 WAIT_CMD(sc); 765 766 /* Load Tx parameters. */ 767 elxl_setup_tx(sc); 768 769 PUT32(REG_DMACTRL, GET32(REG_DMACTRL) | DMACTRL_UPRXEAREN); 770 771 PUT_CMD(CMD_IND_ENABLE | INT_WATCHED); 772 PUT_CMD(CMD_INT_ENABLE | INT_WATCHED); 773 774 PUT_CMD(CMD_INT_ACK | 0xff); 775 776 elxl_set_media(sc); 777 elxl_set_rxfilter(sc); 778 779 /* Configure for VLAN tag sizing. */ 780 SET_WIN(3); 781 if (sc->ex_conf & CONF_90XB) { 782 PUT16(W3_MAX_PKT_SIZE, EX_BUFSZ); 783 } else { 784 PUT16(W3_MAC_CONTROL, GET16(W3_MAC_CONTROL) | 785 MAC_CONTROL_ALLOW_LARGE); 786 } 787 788 PUT_CMD(CMD_SET_RXEARLY | (EX_BUFSZ >> 2)); 789 790 PUT_CMD(CMD_STATS_ENABLE); 791 PUT_CMD(CMD_TX_ENABLE); 792 PUT32(REG_UPLISTPTR, sc->ex_rxring.r_paddr); 793 PUT_CMD(CMD_RX_ENABLE); 794 PUT_CMD(CMD_UP_UNSTALL); 795 } 796 797 /* 798 * Set multicast receive filter. Also take care of promiscuous mode. 799 * Note that *some* of this hardware is fully capable of either a 256 800 * or 64 bit multicast hash. However, we can't determine what the 801 * size of the hash table is easily, and so we are expected to be able 802 * to resubmit the entire list of addresses each time. This puts an 803 * onerous burden on the driver to maintain its list of multicast 804 * addresses. Since multicast stuff is usually not that performance 805 * sensitive, and since we don't usually have much of it, we are just 806 * going to skip it. We allow the upper layers to filter it, as 807 * needed, by setting the all-multicast bit if the hardware can do it. 808 * This also reduces our test burden. 809 */ 810 static void 811 elxl_set_rxfilter(elxl_t *sc) 812 { 813 uint16_t mask = FILTER_UNICAST | FILTER_ALLBCAST; 814 815 if (sc->ex_suspended) 816 return; 817 818 /* 819 * Set the station address and clear the station mask. The latter 820 * is needed for 90x cards, 0 is the default for 90xB cards. 821 */ 822 SET_WIN(2); 823 for (int i = 0; i < ETHERADDRL; i++) { 824 PUT8(W2_STATION_ADDRESS + i, sc->ex_curraddr[i]); 825 PUT8(W2_STATION_MASK + i, 0); 826 } 827 828 if (sc->ex_mccount) { 829 mask |= FILTER_ALLMULTI; 830 } 831 if (sc->ex_promisc) { 832 mask |= FILTER_PROMISC; 833 } 834 PUT_CMD(CMD_SET_FILTER | mask); 835 } 836 837 static void 838 elxl_set_media(elxl_t *sc) 839 { 840 uint32_t configreg; 841 842 SET_WIN(4); 843 PUT16(W4_MEDIASTAT, 0); 844 PUT_CMD(CMD_BNC_DISABLE); 845 drv_usecwait(800); 846 847 /* 848 * Now turn on the selected media/transceiver. 849 */ 850 switch (sc->ex_xcvr) { 851 case XCVR_SEL_10T: 852 sc->ex_mii_active = B_FALSE; 853 PUT16(W4_MEDIASTAT, 854 MEDIASTAT_JABGUARD_EN | MEDIASTAT_LINKBEAT_EN); 855 drv_usecwait(800); 856 break; 857 858 case XCVR_SEL_BNC: 859 sc->ex_mii_active = B_FALSE; 860 PUT_CMD(CMD_BNC_ENABLE); 861 drv_usecwait(800); 862 break; 863 864 case XCVR_SEL_100FX: 865 sc->ex_mii_active = B_FALSE; /* Is this really true? */ 866 PUT16(W4_MEDIASTAT, MEDIASTAT_LINKBEAT_EN); 867 drv_usecwait(800); 868 break; 869 870 case XCVR_SEL_AUI: 871 sc->ex_mii_active = B_FALSE; 872 PUT16(W4_MEDIASTAT, MEDIASTAT_SQE_EN); 873 drv_usecwait(800); 874 break; 875 876 case XCVR_SEL_AUTO: 877 case XCVR_SEL_MII: 878 /* 879 * This is due to paranoia. If a card claims 880 * to default to MII, but doesn't have it set in 881 * media options, then we don't want to leave 882 * the MII active or we'll have problems derferencing 883 * the "mii handle". 884 */ 885 if (sc->ex_miih) { 886 sc->ex_mii_active = B_TRUE; 887 } else { 888 sc->ex_mii_active = B_FALSE; 889 } 890 break; 891 892 default: 893 sc->ex_mii_active = B_FALSE; 894 elxl_error(sc, "Impossible media setting!"); 895 break; 896 } 897 898 SET_WIN(3); 899 configreg = GET32(W3_INTERNAL_CONFIG); 900 901 configreg &= ~(XCVR_SEL_MASK); 902 configreg |= (sc->ex_xcvr); 903 904 PUT32(W3_INTERNAL_CONFIG, configreg); 905 906 /* 907 * If we're not using MII, force the full-duplex setting. MII 908 * based modes handle the full-duplex setting via the MII 909 * notify callback. 910 */ 911 if (!sc->ex_mii_active) { 912 uint16_t mctl; 913 mctl = GET16(W3_MAC_CONTROL); 914 if (sc->ex_fdx) { 915 mctl |= MAC_CONTROL_FDX; 916 } else { 917 mctl &= ~MAC_CONTROL_FDX; 918 } 919 PUT16(W3_MAC_CONTROL, mctl); 920 } 921 } 922 923 /* 924 * Get currently-selected media from card. 925 * (if_media callback, may be called before interface is brought up). 926 */ 927 static void 928 elxl_linkcheck(void *arg) 929 { 930 elxl_t *sc = arg; 931 uint16_t stat; 932 link_state_t link; 933 934 mutex_enter(&sc->ex_txlock); 935 if (sc->ex_mii_active) { 936 mutex_exit(&sc->ex_txlock); 937 return; 938 } 939 if (sc->ex_running && !sc->ex_suspended) { 940 switch (sc->ex_xcvr) { 941 case XCVR_SEL_100FX: 942 /* these media we can detect link on */ 943 SET_WIN(4); 944 stat = GET16(W4_MEDIASTAT); 945 if (stat & MEDIASTAT_LINKDETECT) { 946 sc->ex_link = LINK_STATE_UP; 947 sc->ex_speed = 100000000; 948 } else { 949 sc->ex_link = LINK_STATE_DOWN; 950 sc->ex_speed = 0; 951 } 952 break; 953 954 case XCVR_SEL_10T: 955 /* these media we can detect link on */ 956 SET_WIN(4); 957 stat = GET16(W4_MEDIASTAT); 958 if (stat & MEDIASTAT_LINKDETECT) { 959 sc->ex_link = LINK_STATE_UP; 960 sc->ex_speed = 10000000; 961 } else { 962 sc->ex_link = LINK_STATE_DOWN; 963 sc->ex_speed = 0; 964 } 965 break; 966 967 case XCVR_SEL_BNC: 968 case XCVR_SEL_AUI: 969 default: 970 /* 971 * For these we don't really know the answer, 972 * but if we lie then at least it won't cause 973 * ifconfig to turn off the RUNNING flag. 974 * This is necessary because we might 975 * transition from LINK_STATE_DOWN when 976 * switching media. 977 */ 978 sc->ex_speed = 10000000; 979 sc->ex_link = LINK_STATE_UP; 980 break; 981 } 982 SET_WIN(3); 983 sc->ex_duplex = GET16(W3_MAC_CONTROL) & MAC_CONTROL_FDX ? 984 LINK_DUPLEX_FULL : LINK_DUPLEX_HALF; 985 } else { 986 sc->ex_speed = 0; 987 sc->ex_duplex = LINK_DUPLEX_UNKNOWN; 988 sc->ex_link = LINK_STATE_UNKNOWN; 989 } 990 link = sc->ex_link; 991 mutex_exit(&sc->ex_txlock); 992 993 mac_link_update(sc->ex_mach, link); 994 } 995 996 static int 997 elxl_m_promisc(void *arg, boolean_t on) 998 { 999 elxl_t *sc = arg; 1000 1001 mutex_enter(&sc->ex_intrlock); 1002 mutex_enter(&sc->ex_txlock); 1003 sc->ex_promisc = on; 1004 elxl_set_rxfilter(sc); 1005 mutex_exit(&sc->ex_txlock); 1006 mutex_exit(&sc->ex_intrlock); 1007 return (0); 1008 } 1009 1010 static int 1011 elxl_m_multicst(void *arg, boolean_t add, const uint8_t *addr) 1012 { 1013 elxl_t *sc = arg; 1014 1015 _NOTE(ARGUNUSED(addr)); 1016 1017 mutex_enter(&sc->ex_intrlock); 1018 mutex_enter(&sc->ex_txlock); 1019 if (add) { 1020 sc->ex_mccount++; 1021 if (sc->ex_mccount == 1) { 1022 elxl_set_rxfilter(sc); 1023 } 1024 } else { 1025 sc->ex_mccount--; 1026 if (sc->ex_mccount == 0) { 1027 elxl_set_rxfilter(sc); 1028 } 1029 } 1030 mutex_exit(&sc->ex_txlock); 1031 mutex_exit(&sc->ex_intrlock); 1032 return (0); 1033 } 1034 1035 static int 1036 elxl_m_unicst(void *arg, const uint8_t *addr) 1037 { 1038 elxl_t *sc = arg; 1039 1040 mutex_enter(&sc->ex_intrlock); 1041 mutex_enter(&sc->ex_txlock); 1042 bcopy(addr, sc->ex_curraddr, ETHERADDRL); 1043 elxl_set_rxfilter(sc); 1044 mutex_exit(&sc->ex_txlock); 1045 mutex_exit(&sc->ex_intrlock); 1046 1047 return (0); 1048 } 1049 1050 static mblk_t * 1051 elxl_m_tx(void *arg, mblk_t *mp) 1052 { 1053 elxl_t *sc = arg; 1054 ex_desc_t *txd; 1055 ex_desc_t *first; 1056 ex_desc_t *tail; 1057 size_t len; 1058 ex_ring_t *r; 1059 ex_pd_t *pd; 1060 uint32_t cflags; 1061 mblk_t *nmp; 1062 boolean_t reenable = B_FALSE; 1063 boolean_t reset = B_FALSE; 1064 uint32_t paddr; 1065 1066 r = &sc->ex_txring; 1067 mutex_enter(&sc->ex_txlock); 1068 if (sc->ex_suspended) { 1069 while (mp != NULL) { 1070 sc->ex_nocarrier++; 1071 nmp = mp->b_next; 1072 freemsg(mp); 1073 mp = nmp; 1074 } 1075 mutex_exit(&sc->ex_txlock); 1076 return (NULL); 1077 } 1078 1079 for (int limit = (EX_NTX * 2); limit; limit--) { 1080 uint8_t stat = GET8(REG_TXSTATUS); 1081 if ((stat & TXSTATUS_COMPLETE) == 0) { 1082 break; 1083 } 1084 if (stat & TXSTATUS_MAXCOLLISIONS) { 1085 reenable = B_TRUE; 1086 sc->ex_excoll++; 1087 } 1088 if ((stat & TXSTATUS_ERRS) != 0) { 1089 reset = B_TRUE; 1090 if (stat & TXSTATUS_JABBER) { 1091 sc->ex_jabber++; 1092 } 1093 if (stat & TXSTATUS_RECLAIM_ERR) { 1094 sc->ex_txerr++; 1095 } 1096 if (stat & TXSTATUS_UNDERRUN) { 1097 sc->ex_uflo++; 1098 } 1099 } 1100 PUT8(REG_TXSTATUS, 0); 1101 } 1102 1103 if (reset || reenable) { 1104 paddr = GET32(REG_DNLISTPTR); 1105 if (reset) { 1106 WAIT_CMD(sc); 1107 PUT_CMD(CMD_TX_RESET); 1108 WAIT_CMD(sc); 1109 elxl_setup_tx(sc); 1110 } 1111 PUT_CMD(CMD_TX_ENABLE); 1112 if (paddr) { 1113 PUT32(REG_DNLISTPTR, paddr); 1114 } 1115 } 1116 1117 /* first reclaim any free descriptors */ 1118 while (r->r_avail < r->r_count) { 1119 1120 paddr = GET32(REG_DNLISTPTR); 1121 txd = r->r_head; 1122 if (paddr == txd->ed_descaddr) { 1123 /* still processing this one, we're done */ 1124 break; 1125 } 1126 if (paddr == 0) { 1127 /* done processing the entire list! */ 1128 r->r_head = NULL; 1129 r->r_tail = NULL; 1130 r->r_avail = r->r_count; 1131 break; 1132 } 1133 r->r_avail++; 1134 r->r_head = txd->ed_next; 1135 } 1136 1137 if ((r->r_avail < r->r_count) && (GET32(REG_DNLISTPTR) != 0)) { 1138 PUT_CMD(CMD_DN_STALL); 1139 WAIT_CMD(sc); 1140 } 1141 1142 first = NULL; 1143 tail = r->r_tail; 1144 1145 /* 1146 * If there is already a tx list, select the next desc on the list. 1147 * Otherwise, just pick the first descriptor. 1148 */ 1149 txd = tail ? tail->ed_next : &r->r_desc[0]; 1150 1151 while ((mp != NULL) && (r->r_avail)) { 1152 1153 nmp = mp->b_next; 1154 1155 len = msgsize(mp); 1156 if (len > (ETHERMAX + VLAN_TAGSZ)) { 1157 sc->ex_txerr++; 1158 freemsg(mp); 1159 mp = nmp; 1160 continue; 1161 } 1162 1163 cflags = 0; 1164 if ((sc->ex_conf & CONF_90XB) != 0) { 1165 uint32_t pflags; 1166 hcksum_retrieve(mp, NULL, NULL, NULL, NULL, NULL, NULL, 1167 &pflags); 1168 if (pflags & HCK_IPV4_HDRCKSUM) { 1169 cflags |= EX_DPD_IPCKSUM; 1170 } 1171 if (pflags & HCK_FULLCKSUM) { 1172 cflags |= (EX_DPD_TCPCKSUM | EX_DPD_UDPCKSUM); 1173 } 1174 } 1175 1176 /* Mark this descriptor is in use. We're committed now. */ 1177 mcopymsg(mp, txd->ed_buf); /* frees the mblk! */ 1178 r->r_avail--; 1179 mp = nmp; 1180 1181 /* Accounting stuff. */ 1182 sc->ex_opackets++; 1183 sc->ex_obytes += len; 1184 if (txd->ed_buf[0] & 0x1) { 1185 if (bcmp(txd->ed_buf, ex_broadcast, ETHERADDRL) != 0) { 1186 sc->ex_multixmt++; 1187 } else { 1188 sc->ex_brdcstxmt++; 1189 } 1190 } 1191 1192 pd = txd->ed_pd; 1193 1194 1195 /* 1196 * Zero pad the frame if its too short. This 1197 * also avoids a checksum offload bug. 1198 */ 1199 if (len < 30) { 1200 bzero(txd->ed_buf + len, ETHERMIN - len); 1201 len = ETHERMIN; 1202 } 1203 1204 /* 1205 * If this our first packet so far, record the head 1206 * of the list. 1207 */ 1208 if (first == NULL) { 1209 first = txd; 1210 } 1211 1212 (void) ddi_dma_sync(txd->ed_dmah, 0, 0, DDI_DMA_SYNC_FORDEV); 1213 1214 PUT_PD(r, pd->pd_link, 0); 1215 PUT_PD(r, pd->pd_fsh, len | cflags); 1216 PUT_PD(r, pd->pd_addr, txd->ed_bufaddr); 1217 PUT_PD(r, pd->pd_len, len | EX_FR_LAST); 1218 1219 /* 1220 * Write the link into the previous descriptor. Note that 1221 * if this is the first packet (so no previous queued), this 1222 * will be benign because the previous descriptor won't be 1223 * on any tx list. (Furthermore, we'll clear its link field 1224 * when we do later use it.) 1225 */ 1226 PUT_PD(r, txd->ed_prev->ed_pd->pd_link, txd->ed_descaddr); 1227 } 1228 1229 /* 1230 * Are we submitting any packets? 1231 */ 1232 if (first != NULL) { 1233 /* Interrupt on the last packet. */ 1234 PUT_PD(r, pd->pd_fsh, len | cflags | EX_DPD_DNIND); 1235 1236 if (tail == NULL) { 1237 /* No packets pending, so its a new list head! */ 1238 r->r_head = first; 1239 } else { 1240 pd = tail->ed_pd; 1241 /* We've added frames, so don't interrupt mid-list. */ 1242 PUT_PD(r, pd->pd_fsh, 1243 GET_PD(r, pd->pd_fsh) & ~(EX_DPD_DNIND)); 1244 } 1245 /* Record the last descriptor. */ 1246 r->r_tail = txd; 1247 1248 /* flush the entire ring - we're stopped so its safe */ 1249 (void) ddi_dma_sync(r->r_dmah, 0, 0, DDI_DMA_SYNC_FORDEV); 1250 } 1251 1252 /* Restart transmitter. */ 1253 if (sc->ex_txring.r_head) { 1254 PUT32(REG_DNLISTPTR, sc->ex_txring.r_head->ed_descaddr); 1255 } 1256 PUT_CMD(CMD_DN_UNSTALL); 1257 1258 mutex_exit(&sc->ex_txlock); 1259 1260 return (mp); 1261 } 1262 1263 static mblk_t * 1264 elxl_recv(elxl_t *sc, ex_desc_t *rxd, uint32_t stat) 1265 { 1266 mblk_t *mp = NULL; 1267 uint32_t len; 1268 1269 len = stat & EX_UPD_PKTLENMASK; 1270 if (stat & (EX_UPD_ERR_VLAN | EX_UPD_OVERFLOW)) { 1271 if (stat & EX_UPD_RUNT) { 1272 sc->ex_runt++; 1273 } 1274 if (stat & EX_UPD_OVERRUN) { 1275 sc->ex_oflo++; 1276 } 1277 if (stat & EX_UPD_CRCERR) { 1278 sc->ex_fcs++; 1279 } 1280 if (stat & EX_UPD_ALIGNERR) { 1281 sc->ex_align++; 1282 } 1283 if (stat & EX_UPD_OVERFLOW) { 1284 sc->ex_toolong++; 1285 } 1286 return (NULL); 1287 } 1288 if (len < sizeof (struct ether_header)) { 1289 sc->ex_runt++; 1290 return (NULL); 1291 } 1292 if (len > (ETHERMAX + VLAN_TAGSZ)) { 1293 /* Allow four bytes for the VLAN header */ 1294 sc->ex_toolong++; 1295 return (NULL); 1296 } 1297 if ((mp = allocb(len + 14, BPRI_HI)) == NULL) { 1298 sc->ex_allocbfail++; 1299 return (NULL); 1300 } 1301 1302 (void) ddi_dma_sync(rxd->ed_dmah, 0, 0, DDI_DMA_SYNC_FORKERNEL); 1303 mp->b_rptr += 14; 1304 mp->b_wptr = mp->b_rptr + len; 1305 bcopy(rxd->ed_buf, mp->b_rptr, len); 1306 1307 sc->ex_ipackets++; 1308 sc->ex_ibytes += len; 1309 if (rxd->ed_buf[0] & 0x1) { 1310 if (bcmp(rxd->ed_buf, ex_broadcast, ETHERADDRL) != 0) { 1311 sc->ex_multircv++; 1312 } else { 1313 sc->ex_brdcstrcv++; 1314 } 1315 } 1316 1317 /* 1318 * Set the incoming checksum information for the packet. 1319 */ 1320 if (((sc->ex_conf & CONF_90XB) != 0) && 1321 ((stat & EX_UPD_IPCHECKED) != 0) && 1322 ((stat & (EX_UPD_CKSUMERR)) == 0)) { 1323 uint32_t pflags = 0; 1324 if (stat & EX_UPD_IPCHECKED) { 1325 pflags |= HCK_IPV4_HDRCKSUM; 1326 } 1327 if (stat & (EX_UPD_TCPCHECKED | EX_UPD_UDPCHECKED)) { 1328 pflags |= (HCK_FULLCKSUM | HCK_FULLCKSUM_OK); 1329 } 1330 (void) hcksum_assoc(mp, NULL, NULL, 0, 0, 0, 0, pflags, 0); 1331 } 1332 1333 return (mp); 1334 } 1335 1336 static int 1337 elxl_m_start(void *arg) 1338 { 1339 elxl_t *sc = arg; 1340 1341 mutex_enter(&sc->ex_intrlock); 1342 mutex_enter(&sc->ex_txlock); 1343 1344 elxl_init(sc); 1345 sc->ex_running = B_TRUE; 1346 1347 mutex_exit(&sc->ex_txlock); 1348 mutex_exit(&sc->ex_intrlock); 1349 1350 if (sc->ex_miih) { 1351 mii_start(sc->ex_miih); 1352 } 1353 return (0); 1354 } 1355 1356 static void 1357 elxl_m_stop(void *arg) 1358 { 1359 elxl_t *sc = arg; 1360 1361 if (sc->ex_miih) { 1362 mii_stop(sc->ex_miih); 1363 } 1364 1365 mutex_enter(&sc->ex_intrlock); 1366 mutex_enter(&sc->ex_txlock); 1367 1368 elxl_stop(sc); 1369 sc->ex_running = B_FALSE; 1370 1371 mutex_exit(&sc->ex_txlock); 1372 mutex_exit(&sc->ex_intrlock); 1373 } 1374 1375 static boolean_t 1376 elxl_m_getcapab(void *arg, mac_capab_t cap, void *data) 1377 { 1378 elxl_t *sc = arg; 1379 switch (cap) { 1380 case MAC_CAPAB_HCKSUM: { 1381 uint32_t *flags = data; 1382 if (sc->ex_conf & CONF_90XB) { 1383 *flags = HCKSUM_IPHDRCKSUM | HCKSUM_INET_FULL_V4; 1384 return (B_TRUE); 1385 } 1386 return (B_FALSE); 1387 } 1388 default: 1389 return (B_FALSE); 1390 } 1391 } 1392 1393 static int 1394 elxl_m_getprop(void *arg, const char *name, mac_prop_id_t num, uint_t sz, 1395 void *val) 1396 { 1397 elxl_t *sc = arg; 1398 int rv; 1399 1400 if (sc->ex_mii_active) { 1401 rv = mii_m_getprop(sc->ex_miih, name, num, sz, val); 1402 if (rv != ENOTSUP) 1403 return (rv); 1404 } 1405 1406 switch (num) { 1407 case MAC_PROP_DUPLEX: 1408 *(uint8_t *)val = sc->ex_duplex; 1409 break; 1410 case MAC_PROP_SPEED: 1411 *(uint8_t *)val = sc->ex_speed; 1412 break; 1413 case MAC_PROP_STATUS: 1414 bcopy(&sc->ex_link, val, sizeof (link_state_t)); 1415 break; 1416 1417 case MAC_PROP_PRIVATE: 1418 if (strcmp(name, "_media") == 0) { 1419 char *str; 1420 1421 switch (sc->ex_xcvr) { 1422 case XCVR_SEL_AUTO: 1423 case XCVR_SEL_MII: 1424 str = "mii"; 1425 break; 1426 case XCVR_SEL_10T: 1427 str = sc->ex_fdx ? "tp-fdx" : "tp-hdx"; 1428 break; 1429 case XCVR_SEL_BNC: 1430 str = "bnc"; 1431 break; 1432 case XCVR_SEL_AUI: 1433 if (sc->ex_mediaopt & MEDIAOPT_10FL) { 1434 str = sc->ex_fdx ? "fl-fdx" : "fl-hdx"; 1435 } else { 1436 str = "aui"; 1437 } 1438 break; 1439 case XCVR_SEL_100FX: 1440 str = sc->ex_fdx ? "fx-fdx" : "fx-hdx"; 1441 break; 1442 default: 1443 str = "unknown"; 1444 break; 1445 } 1446 (void) snprintf(val, sz, "%s", str); 1447 return (0); 1448 } 1449 /* 1450 * This available media property is a hack, and should 1451 * be removed when we can provide proper support for 1452 * querying it as proposed in PSARC 2009/235. (At the 1453 * moment the implementation lacks support for using 1454 * MAC_PROP_POSSIBLE with private properties.) 1455 */ 1456 if (strcmp(name, "_available_media") == 0) { 1457 (void) snprintf(val, sz, "%s", sc->ex_medias); 1458 return (0); 1459 } 1460 break; 1461 } 1462 return (ENOTSUP); 1463 } 1464 1465 static int 1466 elxl_m_setprop(void *arg, const char *name, mac_prop_id_t num, uint_t sz, 1467 const void *val) 1468 { 1469 elxl_t *sc = arg; 1470 int rv; 1471 1472 if (sc->ex_mii_active) { 1473 rv = mii_m_setprop(sc->ex_miih, name, num, sz, val); 1474 if (rv != ENOTSUP) { 1475 return (rv); 1476 } 1477 } 1478 switch (num) { 1479 1480 case MAC_PROP_PRIVATE: 1481 if (strcmp(name, "_media") == 0) { 1482 uint32_t mopt = sc->ex_mediaopt; 1483 1484 if (strcmp(val, "mii") == 0) { 1485 if (mopt & MEDIAOPT_100TX) { 1486 sc->ex_xcvr = XCVR_SEL_AUTO; 1487 } else if (mopt & MEDIAOPT_MII) { 1488 sc->ex_xcvr = XCVR_SEL_MII; 1489 } else { 1490 return (EINVAL); 1491 } 1492 } else if (strcmp(val, "tp-fdx") == 0) { 1493 /* select media option */ 1494 if (mopt & MEDIAOPT_10T) { 1495 sc->ex_xcvr = XCVR_SEL_10T; 1496 sc->ex_fdx = B_TRUE; 1497 } else { 1498 return (EINVAL); 1499 } 1500 } else if (strcmp(val, "tp-hdx") == 0) { 1501 /* select media option */ 1502 if (mopt & MEDIAOPT_10T) { 1503 sc->ex_xcvr = XCVR_SEL_10T; 1504 sc->ex_fdx = B_FALSE; 1505 } else { 1506 return (EINVAL); 1507 } 1508 } else if (strcmp(val, "fx-fdx") == 0) { 1509 if (mopt & MEDIAOPT_100FX) { 1510 sc->ex_xcvr = XCVR_SEL_100FX; 1511 sc->ex_fdx = B_TRUE; 1512 } else { 1513 return (EINVAL); 1514 } 1515 } else if (strcmp(val, "fx-hdx") == 0) { 1516 if (mopt & MEDIAOPT_100FX) { 1517 sc->ex_xcvr = XCVR_SEL_100FX; 1518 sc->ex_fdx = B_FALSE; 1519 } else { 1520 return (EINVAL); 1521 } 1522 } else if (strcmp(val, "bnc") == 0) { 1523 if (mopt & MEDIAOPT_BNC) { 1524 sc->ex_xcvr = XCVR_SEL_BNC; 1525 sc->ex_fdx = B_FALSE; 1526 } else { 1527 return (EINVAL); 1528 } 1529 } else if (strcmp(val, "aui") == 0) { 1530 if (mopt & MEDIAOPT_AUI) { 1531 sc->ex_xcvr = XCVR_SEL_AUI; 1532 sc->ex_fdx = B_FALSE; 1533 } else { 1534 return (EINVAL); 1535 } 1536 } else if (strcmp(val, "fl-fdx") == 0) { 1537 if (mopt & MEDIAOPT_10FL) { 1538 sc->ex_xcvr = XCVR_SEL_AUI; 1539 sc->ex_fdx = B_TRUE; 1540 } else { 1541 return (EINVAL); 1542 } 1543 } else if (strcmp(val, "fl-hdx") == 0) { 1544 if (mopt & MEDIAOPT_10FL) { 1545 sc->ex_xcvr = XCVR_SEL_AUI; 1546 sc->ex_fdx = B_FALSE; 1547 } else { 1548 return (EINVAL); 1549 } 1550 1551 } else { 1552 return (EINVAL); 1553 } 1554 goto reset; 1555 } 1556 break; 1557 default: 1558 break; 1559 } 1560 1561 return (ENOTSUP); 1562 1563 reset: 1564 mutex_enter(&sc->ex_intrlock); 1565 mutex_enter(&sc->ex_txlock); 1566 if (!sc->ex_suspended) { 1567 elxl_reset(sc); 1568 if (sc->ex_running) { 1569 elxl_init(sc); 1570 } 1571 } 1572 mutex_exit(&sc->ex_txlock); 1573 mutex_exit(&sc->ex_intrlock); 1574 return (0); 1575 } 1576 1577 static void 1578 elxl_m_propinfo(void *arg, const char *name, mac_prop_id_t num, 1579 mac_prop_info_handle_t prh) 1580 { 1581 elxl_t *sc = arg; 1582 1583 if (sc->ex_mii_active) 1584 mii_m_propinfo(sc->ex_miih, name, num, prh); 1585 1586 switch (num) { 1587 case MAC_PROP_DUPLEX: 1588 case MAC_PROP_SPEED: 1589 case MAC_PROP_STATUS: 1590 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 1591 break; 1592 1593 case MAC_PROP_PRIVATE: 1594 if (strcmp(name, "_available_media") == 0) 1595 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 1596 break; 1597 } 1598 } 1599 1600 static int 1601 elxl_m_stat(void *arg, uint_t stat, uint64_t *val) 1602 { 1603 elxl_t *sc = arg; 1604 1605 if (stat == MAC_STAT_IFSPEED) { 1606 elxl_getstats(sc); 1607 } 1608 1609 if ((sc->ex_mii_active) && 1610 (mii_m_getstat(sc->ex_miih, stat, val) == 0)) { 1611 return (0); 1612 } 1613 1614 switch (stat) { 1615 case MAC_STAT_IFSPEED: 1616 *val = sc->ex_speed; 1617 break; 1618 1619 case ETHER_STAT_LINK_DUPLEX: 1620 *val = sc->ex_duplex; 1621 break; 1622 1623 case MAC_STAT_MULTIRCV: 1624 *val = sc->ex_multircv; 1625 break; 1626 1627 case MAC_STAT_BRDCSTRCV: 1628 *val = sc->ex_brdcstrcv; 1629 break; 1630 1631 case MAC_STAT_MULTIXMT: 1632 *val = sc->ex_multixmt; 1633 break; 1634 1635 case MAC_STAT_BRDCSTXMT: 1636 *val = sc->ex_brdcstxmt; 1637 break; 1638 1639 case MAC_STAT_IPACKETS: 1640 *val = sc->ex_ipackets; 1641 break; 1642 1643 case MAC_STAT_OPACKETS: 1644 *val = sc->ex_opackets; 1645 break; 1646 1647 case MAC_STAT_RBYTES: 1648 *val = sc->ex_ibytes; 1649 break; 1650 case MAC_STAT_OBYTES: 1651 *val = sc->ex_obytes; 1652 break; 1653 1654 case MAC_STAT_COLLISIONS: 1655 case ETHER_STAT_FIRST_COLLISIONS: 1656 *val = sc->ex_singlecol + sc->ex_multcol; 1657 break; 1658 1659 case ETHER_STAT_MULTI_COLLISIONS: 1660 *val = sc->ex_multcol; 1661 break; 1662 1663 case ETHER_STAT_TX_LATE_COLLISIONS: 1664 *val = sc->ex_latecol; 1665 break; 1666 1667 case ETHER_STAT_ALIGN_ERRORS: 1668 *val = sc->ex_align; 1669 break; 1670 1671 case ETHER_STAT_FCS_ERRORS: 1672 *val = sc->ex_fcs; 1673 break; 1674 1675 case ETHER_STAT_SQE_ERRORS: 1676 *val = sc->ex_sqe; 1677 break; 1678 1679 case ETHER_STAT_DEFER_XMTS: 1680 *val = sc->ex_defer; 1681 break; 1682 1683 case ETHER_STAT_CARRIER_ERRORS: 1684 *val = sc->ex_nocarrier; 1685 break; 1686 1687 case ETHER_STAT_TOOLONG_ERRORS: 1688 *val = sc->ex_toolong; 1689 break; 1690 1691 case ETHER_STAT_EX_COLLISIONS: 1692 *val = sc->ex_excoll; 1693 break; 1694 1695 case MAC_STAT_OVERFLOWS: 1696 *val = sc->ex_oflo; 1697 break; 1698 1699 case MAC_STAT_UNDERFLOWS: 1700 *val = sc->ex_uflo; 1701 break; 1702 1703 case ETHER_STAT_TOOSHORT_ERRORS: 1704 *val = sc->ex_runt; 1705 break; 1706 1707 case ETHER_STAT_JABBER_ERRORS: 1708 *val = sc->ex_jabber; 1709 break; 1710 1711 case MAC_STAT_NORCVBUF: 1712 *val = sc->ex_allocbfail; 1713 break; 1714 1715 case MAC_STAT_OERRORS: 1716 *val = sc->ex_jabber + sc->ex_latecol + sc->ex_uflo; 1717 break; 1718 1719 case MAC_STAT_IERRORS: 1720 *val = sc->ex_align + sc->ex_fcs + sc->ex_runt + 1721 sc->ex_toolong + sc->ex_oflo + sc->ex_allocbfail; 1722 break; 1723 1724 default: 1725 return (ENOTSUP); 1726 } 1727 return (0); 1728 } 1729 1730 static uint_t 1731 elxl_intr(caddr_t arg, caddr_t dontcare) 1732 { 1733 elxl_t *sc = (void *)arg; 1734 uint16_t stat; 1735 mblk_t *mphead = NULL; 1736 mblk_t **mpp = &mphead; 1737 1738 _NOTE(ARGUNUSED(dontcare)); 1739 1740 mutex_enter(&sc->ex_intrlock); 1741 if (sc->ex_suspended) { 1742 mutex_exit(&sc->ex_intrlock); 1743 return (DDI_INTR_UNCLAIMED); 1744 } 1745 1746 stat = GET16(REG_CMD_STAT); 1747 1748 if ((stat & INT_LATCH) == 0) { 1749 mutex_exit(&sc->ex_intrlock); 1750 return (DDI_INTR_UNCLAIMED); 1751 } 1752 1753 /* 1754 * Acknowledge interrupts. 1755 */ 1756 PUT_CMD(CMD_INT_ACK | (stat & INT_WATCHED) | INT_LATCH); 1757 1758 if (stat & INT_HOST_ERROR) { 1759 /* XXX: Potentially a good spot for FMA */ 1760 elxl_error(sc, "Adapter failure (%x)", stat); 1761 mutex_enter(&sc->ex_txlock); 1762 elxl_reset(sc); 1763 if (sc->ex_running) 1764 elxl_init(sc); 1765 mutex_exit(&sc->ex_txlock); 1766 mutex_exit(&sc->ex_intrlock); 1767 return (DDI_INTR_CLAIMED); 1768 } 1769 if (stat & INT_UP_COMPLETE) { 1770 ex_ring_t *r; 1771 ex_desc_t *rxd; 1772 ex_pd_t *pd; 1773 mblk_t *mp; 1774 uint32_t pktstat; 1775 1776 r = &sc->ex_rxring; 1777 1778 for (;;) { 1779 rxd = r->r_head; 1780 pd = rxd->ed_pd; 1781 1782 (void) ddi_dma_sync(r->r_dmah, rxd->ed_off, 1783 sizeof (ex_pd_t), DDI_DMA_SYNC_FORKERNEL); 1784 1785 pktstat = GET_PD(r, pd->pd_status); 1786 1787 if ((pktstat & EX_UPD_COMPLETE) == 0) { 1788 break; 1789 } 1790 1791 /* Advance head to next packet. */ 1792 r->r_head = r->r_head->ed_next; 1793 1794 if ((mp = elxl_recv(sc, rxd, pktstat)) != NULL) { 1795 *mpp = mp; 1796 mpp = &mp->b_next; 1797 } 1798 1799 /* clear the upComplete status, reset other fields */ 1800 PUT_PD(r, pd->pd_status, 0); 1801 PUT_PD(r, pd->pd_len, EX_BUFSZ | EX_FR_LAST); 1802 PUT_PD(r, pd->pd_addr, rxd->ed_bufaddr); 1803 (void) ddi_dma_sync(r->r_dmah, rxd->ed_off, 1804 sizeof (ex_pd_t), DDI_DMA_SYNC_FORDEV); 1805 } 1806 1807 /* 1808 * If the engine stalled processing (due to 1809 * insufficient UPDs usually), restart it. 1810 */ 1811 if (GET32(REG_UPLISTPTR) == 0) { 1812 /* 1813 * This seems that it can happen in an RX overrun 1814 * situation. 1815 */ 1816 mutex_enter(&sc->ex_txlock); 1817 if (sc->ex_running) 1818 elxl_init(sc); 1819 mutex_exit(&sc->ex_txlock); 1820 } 1821 PUT_CMD(CMD_UP_UNSTALL); 1822 } 1823 1824 mutex_exit(&sc->ex_intrlock); 1825 1826 if (mphead) { 1827 mac_rx(sc->ex_mach, NULL, mphead); 1828 } 1829 if (stat & INT_STATS) { 1830 elxl_getstats(sc); 1831 } 1832 if (stat & INT_DN_COMPLETE) { 1833 mac_tx_update(sc->ex_mach); 1834 } 1835 1836 return (DDI_INTR_CLAIMED); 1837 } 1838 1839 static void 1840 elxl_getstats(elxl_t *sc) 1841 { 1842 mutex_enter(&sc->ex_txlock); 1843 if (sc->ex_suspended) { 1844 mutex_exit(&sc->ex_txlock); 1845 return; 1846 } 1847 1848 SET_WIN(6); 1849 /* 1850 * We count the packets and bytes elsewhere, but we need to 1851 * read the registers to clear them. 1852 */ 1853 (void) GET8(W6_RX_FRAMES); 1854 (void) GET8(W6_TX_FRAMES); 1855 (void) GET8(W6_UPPER_FRAMES); 1856 (void) GET8(W6_RX_OVERRUNS); /* counted by elxl_recv */ 1857 (void) GET16(W6_RX_BYTES); 1858 (void) GET16(W6_TX_BYTES); 1859 1860 sc->ex_defer += GET8(W6_DEFER); 1861 sc->ex_latecol += GET8(W6_TX_LATE_COL); 1862 sc->ex_singlecol += GET8(W6_SINGLE_COL); 1863 sc->ex_multcol += GET8(W6_MULT_COL); 1864 sc->ex_sqe += GET8(W6_SQE_ERRORS); 1865 sc->ex_nocarrier += GET8(W6_NO_CARRIER); 1866 1867 SET_WIN(4); 1868 /* Note: we ought to report this somewhere... */ 1869 (void) GET8(W4_BADSSD); 1870 1871 mutex_exit(&sc->ex_txlock); 1872 } 1873 1874 static void 1875 elxl_reset(elxl_t *sc) 1876 { 1877 PUT_CMD(CMD_GLOBAL_RESET); 1878 /* 1879 * Some ASICs need a longer time (20 ms) to come properly out 1880 * of reset. Do not reduce this value. 1881 * 1882 * Note that this occurs only during attach and failure recovery, 1883 * so it should be mostly harmless. 1884 */ 1885 drv_usecwait(20000); 1886 WAIT_CMD(sc); 1887 } 1888 1889 static void 1890 elxl_stop(elxl_t *sc) 1891 { 1892 ASSERT(mutex_owned(&sc->ex_intrlock)); 1893 ASSERT(mutex_owned(&sc->ex_txlock)); 1894 1895 if (sc->ex_suspended) 1896 return; 1897 1898 PUT_CMD(CMD_RX_DISABLE); 1899 PUT_CMD(CMD_TX_DISABLE); 1900 PUT_CMD(CMD_BNC_DISABLE); 1901 1902 elxl_reset_ring(&sc->ex_rxring, DDI_DMA_READ); 1903 elxl_reset_ring(&sc->ex_txring, DDI_DMA_WRITE); 1904 1905 PUT_CMD(CMD_INT_ACK | INT_LATCH); 1906 /* Disable all interrupts. (0 means "none".) */ 1907 PUT_CMD(CMD_INT_ENABLE | 0); 1908 } 1909 1910 static void 1911 elxl_suspend(elxl_t *sc) 1912 { 1913 if (sc->ex_miih) { 1914 mii_suspend(sc->ex_miih); 1915 } 1916 1917 mutex_enter(&sc->ex_intrlock); 1918 mutex_enter(&sc->ex_txlock); 1919 elxl_stop(sc); 1920 sc->ex_suspended = B_TRUE; 1921 mutex_exit(&sc->ex_txlock); 1922 mutex_exit(&sc->ex_intrlock); 1923 } 1924 1925 static void 1926 elxl_resume(dev_info_t *dip) 1927 { 1928 elxl_t *sc; 1929 1930 /* This should always succeed. */ 1931 sc = ddi_get_driver_private(dip); 1932 ASSERT(sc); 1933 1934 mutex_enter(&sc->ex_intrlock); 1935 mutex_enter(&sc->ex_txlock); 1936 sc->ex_suspended = B_FALSE; 1937 elxl_reset(sc); 1938 if (sc->ex_running) 1939 elxl_init(sc); 1940 mutex_exit(&sc->ex_txlock); 1941 mutex_exit(&sc->ex_intrlock); 1942 1943 if (sc->ex_miih) { 1944 mii_resume(sc->ex_miih); 1945 } 1946 } 1947 1948 static void 1949 elxl_detach(elxl_t *sc) 1950 { 1951 if (sc->ex_miih) { 1952 /* Detach all PHYs */ 1953 mii_free(sc->ex_miih); 1954 } 1955 if (sc->ex_linkcheck) { 1956 ddi_periodic_delete(sc->ex_linkcheck); 1957 } 1958 1959 if (sc->ex_intrh != NULL) { 1960 (void) ddi_intr_disable(sc->ex_intrh); 1961 (void) ddi_intr_remove_handler(sc->ex_intrh); 1962 (void) ddi_intr_free(sc->ex_intrh); 1963 mutex_destroy(&sc->ex_intrlock); 1964 mutex_destroy(&sc->ex_txlock); 1965 } 1966 1967 if (sc->ex_pcih) { 1968 pci_config_teardown(&sc->ex_pcih); 1969 } 1970 if (sc->ex_regsh) { 1971 ddi_regs_map_free(&sc->ex_regsh); 1972 } 1973 ex_free_ring(&sc->ex_txring); 1974 ex_free_ring(&sc->ex_rxring); 1975 1976 kmem_free(sc, sizeof (*sc)); 1977 } 1978 1979 /* 1980 * Read EEPROM data. If we can't unbusy the EEPROM, then zero will be 1981 * returned. This will probably result in a bogus node address. 1982 */ 1983 static uint16_t 1984 elxl_read_eeprom(elxl_t *sc, int offset) 1985 { 1986 uint16_t data = 0; 1987 1988 SET_WIN(0); 1989 if (elxl_eeprom_busy(sc)) 1990 goto out; 1991 1992 PUT16(W0_EE_CMD, EE_CMD_READ | (offset & 0x3f)); 1993 if (elxl_eeprom_busy(sc)) 1994 goto out; 1995 data = GET16(W0_EE_DATA); 1996 out: 1997 return (data); 1998 } 1999 2000 static int 2001 elxl_eeprom_busy(elxl_t *sc) 2002 { 2003 int i = 2000; 2004 2005 while (i--) { 2006 if (!(GET16(W0_EE_CMD) & EE_CMD_BUSY)) 2007 return (0); 2008 drv_usecwait(100); 2009 } 2010 elxl_error(sc, "Eeprom stays busy."); 2011 return (1); 2012 } 2013 2014 static void 2015 ex_mii_send_bits(struct ex_softc *sc, uint16_t bits, int cnt) 2016 { 2017 uint16_t val; 2018 ASSERT(cnt > 0); 2019 2020 PUT16(W4_PHYSMGMT, PHYSMGMT_DIR); 2021 drv_usecwait(1); 2022 2023 for (int i = (1 << (cnt - 1)); i; i >>= 1) { 2024 if (bits & i) { 2025 val = PHYSMGMT_DIR | PHYSMGMT_DATA; 2026 } else { 2027 val = PHYSMGMT_DIR; 2028 } 2029 PUT16(W4_PHYSMGMT, val); 2030 drv_usecwait(1); 2031 PUT16(W4_PHYSMGMT, val | PHYSMGMT_CLK); 2032 drv_usecwait(1); 2033 PUT16(W4_PHYSMGMT, val); 2034 drv_usecwait(1); 2035 } 2036 } 2037 2038 static void 2039 ex_mii_sync(struct ex_softc *sc) 2040 { 2041 /* 2042 * We set the data bit output, and strobe the clock 32 times. 2043 */ 2044 PUT16(W4_PHYSMGMT, PHYSMGMT_DATA | PHYSMGMT_DIR); 2045 drv_usecwait(1); 2046 2047 for (int i = 0; i < 32; i++) { 2048 PUT16(W4_PHYSMGMT, PHYSMGMT_DATA | PHYSMGMT_DIR | PHYSMGMT_CLK); 2049 drv_usecwait(1); 2050 PUT16(W4_PHYSMGMT, PHYSMGMT_DATA | PHYSMGMT_DIR); 2051 drv_usecwait(1); 2052 } 2053 } 2054 2055 static uint16_t 2056 elxl_mii_read(void *arg, uint8_t phy, uint8_t reg) 2057 { 2058 elxl_t *sc = arg; 2059 uint16_t data; 2060 int val; 2061 2062 if ((sc->ex_conf & CONF_INTPHY) && phy != INTPHY_ID) 2063 return (0xffff); 2064 2065 mutex_enter(&sc->ex_txlock); 2066 SET_WIN(4); 2067 2068 ex_mii_sync(sc); 2069 2070 ex_mii_send_bits(sc, 1, 2); /* start */ 2071 ex_mii_send_bits(sc, 2, 2); /* read command */ 2072 ex_mii_send_bits(sc, phy, 5); 2073 ex_mii_send_bits(sc, reg, 5); 2074 2075 PUT16(W4_PHYSMGMT, 0); /* switch to input */ 2076 drv_usecwait(1); 2077 PUT16(W4_PHYSMGMT, PHYSMGMT_CLK); /* turnaround time */ 2078 drv_usecwait(1); 2079 PUT16(W4_PHYSMGMT, 0); 2080 drv_usecwait(1); 2081 2082 PUT16(W4_PHYSMGMT, PHYSMGMT_CLK); /* idle time */ 2083 drv_usecwait(1); 2084 PUT16(W4_PHYSMGMT, 0); 2085 drv_usecwait(1); 2086 2087 for (data = 0, val = 0x8000; val; val >>= 1) { 2088 if (GET16(W4_PHYSMGMT) & PHYSMGMT_DATA) { 2089 data |= val; 2090 } 2091 /* strobe the clock */ 2092 PUT16(W4_PHYSMGMT, PHYSMGMT_CLK); 2093 drv_usecwait(1); 2094 PUT16(W4_PHYSMGMT, 0); 2095 drv_usecwait(1); 2096 } 2097 2098 /* return to output mode */ 2099 PUT16(W4_PHYSMGMT, PHYSMGMT_DIR); 2100 drv_usecwait(1); 2101 2102 mutex_exit(&sc->ex_txlock); 2103 2104 return (data); 2105 } 2106 2107 static void 2108 elxl_mii_write(void *arg, uint8_t phy, uint8_t reg, uint16_t data) 2109 { 2110 elxl_t *sc = arg; 2111 2112 if ((sc->ex_conf & CONF_INTPHY) && phy != INTPHY_ID) 2113 return; 2114 2115 mutex_enter(&sc->ex_txlock); 2116 SET_WIN(4); 2117 2118 ex_mii_sync(sc); 2119 ex_mii_send_bits(sc, 1, 2); /* start */ 2120 ex_mii_send_bits(sc, 1, 2); /* write */ 2121 ex_mii_send_bits(sc, phy, 5); 2122 ex_mii_send_bits(sc, reg, 5); 2123 ex_mii_send_bits(sc, 2, 2); /* ack/turnaround */ 2124 ex_mii_send_bits(sc, data, 16); 2125 2126 /* return to output mode */ 2127 PUT16(W4_PHYSMGMT, PHYSMGMT_DIR); 2128 drv_usecwait(1); 2129 2130 mutex_exit(&sc->ex_txlock); 2131 } 2132 2133 static void 2134 elxl_mii_notify(void *arg, link_state_t link) 2135 { 2136 elxl_t *sc = arg; 2137 int mctl; 2138 link_duplex_t duplex; 2139 2140 duplex = mii_get_duplex(sc->ex_miih); 2141 2142 mutex_enter(&sc->ex_txlock); 2143 if (!sc->ex_mii_active) { 2144 /* If we're using some other legacy media, bail out now */ 2145 mutex_exit(&sc->ex_txlock); 2146 return; 2147 } 2148 if (!sc->ex_suspended) { 2149 SET_WIN(3); 2150 mctl = GET16(W3_MAC_CONTROL); 2151 if (duplex == LINK_DUPLEX_FULL) 2152 mctl |= MAC_CONTROL_FDX; 2153 else 2154 mctl &= ~MAC_CONTROL_FDX; 2155 PUT16(W3_MAC_CONTROL, mctl); 2156 } 2157 mutex_exit(&sc->ex_txlock); 2158 2159 mac_link_update(sc->ex_mach, link); 2160 } 2161 2162 static int 2163 elxl_ddi_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 2164 { 2165 switch (cmd) { 2166 case DDI_ATTACH: 2167 return (elxl_attach(dip)); 2168 2169 case DDI_RESUME: 2170 elxl_resume(dip); 2171 return (DDI_SUCCESS); 2172 2173 default: 2174 return (DDI_FAILURE); 2175 } 2176 } 2177 2178 static int 2179 elxl_ddi_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 2180 { 2181 elxl_t *sc; 2182 2183 sc = ddi_get_driver_private(dip); 2184 ASSERT(sc); 2185 2186 switch (cmd) { 2187 case DDI_DETACH: 2188 if (mac_disable(sc->ex_mach) != 0) { 2189 return (DDI_FAILURE); 2190 } 2191 (void) mac_unregister(sc->ex_mach); 2192 elxl_detach(sc); 2193 return (DDI_SUCCESS); 2194 2195 case DDI_SUSPEND: 2196 elxl_suspend(sc); 2197 return (DDI_SUCCESS); 2198 2199 default: 2200 return (DDI_FAILURE); 2201 } 2202 } 2203 2204 static int 2205 elxl_ddi_quiesce(dev_info_t *dip) 2206 { 2207 elxl_t *sc; 2208 2209 sc = ddi_get_driver_private(dip); 2210 ASSERT(sc); 2211 2212 if (!sc->ex_suspended) 2213 elxl_reset(sc); 2214 return (DDI_SUCCESS); 2215 } 2216 2217 static void 2218 elxl_error(elxl_t *sc, char *fmt, ...) 2219 { 2220 va_list ap; 2221 char buf[256]; 2222 2223 va_start(ap, fmt); 2224 (void) vsnprintf(buf, sizeof (buf), fmt, ap); 2225 va_end(ap); 2226 2227 cmn_err(CE_WARN, "%s%d: %s", 2228 ddi_driver_name(sc->ex_dip), ddi_get_instance(sc->ex_dip), buf); 2229 } 2230