1 /* 2 * usbgem.c: General USB to Fast Ethernet mac driver framework 3 * 4 * Copyright (c) 2002-2012 Masayuki Murayama. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright notice, 10 * this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright notice, 13 * this list of conditions and the following disclaimer in the documentation 14 * and/or other materials provided with the distribution. 15 * 16 * 3. Neither the name of the author nor the names of its contributors may be 17 * used to endorse or promote products derived from this software without 18 * specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 30 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 31 * DAMAGE. 32 */ 33 34 /* 35 * Copyright 2019 Joyent, Inc. 36 * Copyright 2022 Garrett D'Amore 37 */ 38 39 /* 40 * Change log 41 */ 42 43 /* 44 * TODO: 45 * implement DELAYED_START 46 */ 47 48 /* 49 * System Header files. 50 */ 51 #include <sys/types.h> 52 #include <sys/conf.h> 53 #include <sys/debug.h> 54 #include <sys/kmem.h> 55 #include <sys/vtrace.h> 56 #include <sys/ethernet.h> 57 #include <sys/modctl.h> 58 #include <sys/errno.h> 59 #include <sys/ddi.h> 60 #include <sys/sunddi.h> 61 #include <sys/stream.h> /* required for MBLK* */ 62 #include <sys/strsun.h> /* required for mionack() */ 63 #include <sys/byteorder.h> 64 65 #include <sys/usb/usba.h> 66 #include <inet/common.h> 67 #include <inet/led.h> 68 #include <inet/mi.h> 69 #include <inet/nd.h> 70 71 /* supplement definitions */ 72 extern const char *usb_str_cr(usb_cr_t); 73 74 #include <sys/note.h> 75 76 #include "usbgem_mii.h" 77 #include "usbgem.h" 78 79 char ident[] = "usb general ethernet mac driver v" VERSION; 80 81 /* Debugging support */ 82 #ifdef USBGEM_DEBUG_LEVEL 83 static int usbgem_debug = USBGEM_DEBUG_LEVEL; 84 #define DPRINTF(n, args) if (usbgem_debug > (n)) cmn_err args 85 #else 86 #define DPRINTF(n, args) 87 #endif 88 89 /* 90 * Useful macros and typedefs 91 */ 92 #define ROUNDUP(x, a) (((x) + (a) - 1) & ~((a) - 1)) 93 #define DEFAULT_PIPE(dp) ((dp)->reg_data->dev_default_ph) 94 #define VTAG_SIZE 4 95 #define BOOLEAN(x) ((x) != 0) 96 /* 97 * configuration parameters 98 */ 99 #define USBDRV_MAJOR_VER 2 100 #define USBDRV_MINOR_VER 0 101 102 #define ETHERHEADERL (sizeof (struct ether_header)) 103 #define MAXPKTLEN(dp) ((dp)->mtu + ETHERHEADERL) 104 #define MAXPKTBUF(dp) ((dp)->mtu + ETHERHEADERL + ETHERFCSL) 105 106 #define WATCH_INTERVAL_FAST drv_usectohz(100*1000) 107 108 #define STOP_GRACEFUL B_TRUE 109 110 /* 111 * Private functions 112 */ 113 static int usbgem_open_pipes(struct usbgem_dev *dp); 114 static int usbgem_close_pipes(struct usbgem_dev *dp); 115 static void usbgem_intr_cb(usb_pipe_handle_t, usb_intr_req_t *); 116 static void usbgem_bulkin_cb(usb_pipe_handle_t, usb_bulk_req_t *); 117 static void usbgem_bulkout_cb(usb_pipe_handle_t, usb_bulk_req_t *); 118 119 static int usbgem_mii_start(struct usbgem_dev *); 120 static void usbgem_mii_stop(struct usbgem_dev *); 121 122 /* local buffer management */ 123 static int usbgem_init_rx_buf(struct usbgem_dev *); 124 125 /* internal mac interfaces */ 126 static void usbgem_tx_timeout(struct usbgem_dev *); 127 static void usbgem_mii_link_watcher(struct usbgem_dev *); 128 static int usbgem_mac_init(struct usbgem_dev *); 129 static int usbgem_mac_start(struct usbgem_dev *); 130 static int usbgem_mac_stop(struct usbgem_dev *, int, boolean_t); 131 static void usbgem_mac_ioctl(struct usbgem_dev *, queue_t *, mblk_t *); 132 133 int usbgem_speed_value[] = {10, 100, 1000}; 134 135 static int usbgem_ctrl_retry = 5; 136 137 /* usb event support */ 138 static int usbgem_disconnect_cb(dev_info_t *dip); 139 static int usbgem_reconnect_cb(dev_info_t *dip); 140 int usbgem_suspend(dev_info_t *dip); 141 int usbgem_resume(dev_info_t *dip); 142 143 static uint8_t usbgem_bcastaddr[] = { 144 0xff, 0xff, 0xff, 0xff, 0xff, 0xff 145 }; 146 147 extern struct mod_ops mod_miscops; 148 149 static struct modlmisc modlmisc = { 150 &mod_miscops, 151 "usbgem v" VERSION, 152 }; 153 154 static struct modlinkage modlinkage = { 155 MODREV_1, &modlmisc, NULL 156 }; 157 158 /* 159 * _init : done 160 */ 161 int 162 _init(void) 163 { 164 int status; 165 166 DPRINTF(2, (CE_CONT, "!usbgem: _init: called")); 167 status = mod_install(&modlinkage); 168 169 return (status); 170 } 171 172 /* 173 * _fini : done 174 */ 175 int 176 _fini(void) 177 { 178 int status; 179 180 DPRINTF(2, (CE_CONT, "!usbgem: _fini: called")); 181 status = mod_remove(&modlinkage); 182 return (status); 183 } 184 185 int 186 _info(struct modinfo *modinfop) 187 { 188 return (mod_info(&modlinkage, modinfop)); 189 } 190 191 /* ============================================================== */ 192 /* 193 * Ether CRC calculation utilities 194 */ 195 /* ============================================================== */ 196 /* 197 * Ether CRC calculation according to 21143 data sheet 198 */ 199 #define CRC32_POLY_LE 0xedb88320 200 uint32_t 201 usbgem_ether_crc_le(const uint8_t *addr) 202 { 203 int idx; 204 int bit; 205 uint_t data; 206 uint32_t crc = 0xffffffff; 207 208 crc = 0xffffffff; 209 for (idx = 0; idx < ETHERADDRL; idx++) { 210 for (data = *addr++, bit = 0; bit < 8; bit++, data >>= 1) { 211 crc = (crc >> 1) ^ 212 (((crc ^ data) & 1) ? CRC32_POLY_LE : 0); 213 } 214 } 215 return (crc); 216 } 217 218 #define CRC32_POLY_BE 0x04c11db7 219 uint32_t 220 usbgem_ether_crc_be(const uint8_t *addr) 221 { 222 int idx; 223 int bit; 224 uint_t data; 225 uint32_t crc; 226 227 crc = 0xffffffff; 228 for (idx = 0; idx < ETHERADDRL; idx++) { 229 for (data = *addr++, bit = 0; bit < 8; bit++, data >>= 1) { 230 crc = (crc << 1) ^ 231 ((((crc >> 31) ^ data) & 1) ? CRC32_POLY_BE : 0); 232 } 233 } 234 return (crc); 235 } 236 237 int 238 usbgem_prop_get_int(struct usbgem_dev *dp, char *prop_template, int def_val) 239 { 240 char propname[32]; 241 242 (void) sprintf(propname, prop_template, dp->name); 243 244 return (ddi_prop_get_int(DDI_DEV_T_ANY, dp->dip, 245 DDI_PROP_DONTPASS, propname, def_val)); 246 } 247 248 static int 249 usbgem_population(uint32_t x) 250 { 251 int i; 252 int cnt; 253 254 cnt = 0; 255 for (i = 0; i < 32; i++) { 256 if (x & (1 << i)) { 257 cnt++; 258 } 259 } 260 return (cnt); 261 } 262 263 static clock_t 264 usbgem_timestamp_nz() 265 { 266 clock_t now; 267 now = ddi_get_lbolt(); 268 return (now ? now : (clock_t)1); 269 } 270 271 /* ============================================================== */ 272 /* 273 * hardware operations 274 */ 275 /* ============================================================== */ 276 static int 277 usbgem_hal_reset_chip(struct usbgem_dev *dp) 278 { 279 int err; 280 281 sema_p(&dp->hal_op_lock); 282 err = (*dp->ugc.usbgc_reset_chip)(dp); 283 sema_v(&dp->hal_op_lock); 284 return (err); 285 } 286 287 static int 288 usbgem_hal_init_chip(struct usbgem_dev *dp) 289 { 290 int err; 291 292 sema_p(&dp->hal_op_lock); 293 err = (*dp->ugc.usbgc_init_chip)(dp); 294 sema_v(&dp->hal_op_lock); 295 return (err); 296 } 297 298 static int 299 usbgem_hal_attach_chip(struct usbgem_dev *dp) 300 { 301 int err; 302 303 sema_p(&dp->hal_op_lock); 304 err = (*dp->ugc.usbgc_attach_chip)(dp); 305 sema_v(&dp->hal_op_lock); 306 return (err); 307 } 308 309 static int 310 usbgem_hal_set_rx_filter(struct usbgem_dev *dp) 311 { 312 int err; 313 314 sema_p(&dp->hal_op_lock); 315 err = (*dp->ugc.usbgc_set_rx_filter)(dp); 316 sema_v(&dp->hal_op_lock); 317 return (err); 318 } 319 320 static int 321 usbgem_hal_set_media(struct usbgem_dev *dp) 322 { 323 int err; 324 325 sema_p(&dp->hal_op_lock); 326 err = (*dp->ugc.usbgc_set_media)(dp); 327 sema_v(&dp->hal_op_lock); 328 return (err); 329 } 330 331 static int 332 usbgem_hal_start_chip(struct usbgem_dev *dp) 333 { 334 int err; 335 336 sema_p(&dp->hal_op_lock); 337 err = (*dp->ugc.usbgc_start_chip)(dp); 338 sema_v(&dp->hal_op_lock); 339 return (err); 340 } 341 342 static int 343 usbgem_hal_stop_chip(struct usbgem_dev *dp) 344 { 345 int err; 346 347 sema_p(&dp->hal_op_lock); 348 err = (*dp->ugc.usbgc_stop_chip)(dp); 349 sema_v(&dp->hal_op_lock); 350 return (err); 351 } 352 353 static int 354 usbgem_hal_get_stats(struct usbgem_dev *dp) 355 { 356 int err; 357 358 sema_p(&dp->hal_op_lock); 359 err = (*dp->ugc.usbgc_get_stats)(dp); 360 sema_v(&dp->hal_op_lock); 361 return (err); 362 } 363 364 365 /* ============================================================== */ 366 /* 367 * USB pipe management 368 */ 369 /* ============================================================== */ 370 static boolean_t 371 usbgem_rx_start_unit(struct usbgem_dev *dp, usb_bulk_req_t *req) 372 { 373 mblk_t *mp; 374 int err; 375 usb_flags_t flags; 376 377 ASSERT(req); 378 379 mp = allocb(dp->rx_buf_len, BPRI_MED); 380 if (mp == NULL) { 381 cmn_err(CE_WARN, "!%s: %s: failed to allocate mblk", 382 dp->name, __func__); 383 goto err; 384 } 385 386 req->bulk_len = dp->rx_buf_len; 387 req->bulk_data = mp; 388 req->bulk_client_private = (usb_opaque_t)dp; 389 req->bulk_timeout = 0; 390 req->bulk_attributes = USB_ATTRS_SHORT_XFER_OK; 391 req->bulk_cb = usbgem_bulkin_cb; 392 req->bulk_exc_cb = usbgem_bulkin_cb; 393 req->bulk_completion_reason = 0; 394 req->bulk_cb_flags = 0; 395 396 flags = 0; 397 err = usb_pipe_bulk_xfer(dp->bulkin_pipe, req, flags); 398 399 if (err != USB_SUCCESS) { 400 cmn_err(CE_WARN, "%s: failed to bulk_xfer for rx, err:%d", 401 dp->name, err); 402 403 /* free req and mp */ 404 usb_free_bulk_req(req); 405 goto err; 406 } 407 return (B_TRUE); 408 err: 409 return (B_FALSE); 410 } 411 412 /* ============================================================== */ 413 /* 414 * Rx/Tx buffer management 415 */ 416 /* ============================================================== */ 417 static int 418 usbgem_init_rx_buf(struct usbgem_dev *dp) 419 { 420 int i; 421 usb_bulk_req_t *req; 422 423 ASSERT(dp->mac_state == MAC_STATE_ONLINE); 424 425 for (i = 0; i < dp->ugc.usbgc_rx_list_max; i++) { 426 req = usb_alloc_bulk_req(dp->dip, 0, USB_FLAGS_SLEEP); 427 if (req == NULL) { 428 cmn_err(CE_WARN, 429 "!%s: %s: failed to allocate bulkreq for rx", 430 dp->name, __func__); 431 return (USB_FAILURE); 432 } 433 if (!usbgem_rx_start_unit(dp, req)) { 434 return (USB_FAILURE); 435 } 436 mutex_enter(&dp->rxlock); 437 dp->rx_busy_cnt++; 438 mutex_exit(&dp->rxlock); 439 } 440 return (USB_SUCCESS); 441 } 442 443 /* ============================================================== */ 444 /* 445 * memory resource management 446 */ 447 /* ============================================================== */ 448 static int 449 usbgem_free_memory(struct usbgem_dev *dp) 450 { 451 usb_bulk_req_t *req; 452 453 /* free all tx requst structure */ 454 while ((req = dp->tx_free_list) != NULL) { 455 dp->tx_free_list = 456 (usb_bulk_req_t *)req->bulk_client_private; 457 req->bulk_data = NULL; 458 usb_free_bulk_req(req); 459 } 460 return (USB_SUCCESS); 461 } 462 463 static int 464 usbgem_alloc_memory(struct usbgem_dev *dp) 465 { 466 int i; 467 usb_bulk_req_t *req; 468 469 /* allocate tx requests */ 470 dp->tx_free_list = NULL; 471 for (i = 0; i < dp->ugc.usbgc_tx_list_max; i++) { 472 req = usb_alloc_bulk_req(dp->dip, 0, USB_FLAGS_SLEEP); 473 if (req == NULL) { 474 cmn_err(CE_WARN, 475 "%s:%s failed to allocate tx requests", 476 dp->name, __func__); 477 478 /* free partially allocated tx requests */ 479 (void) usbgem_free_memory(dp); 480 return (USB_FAILURE); 481 } 482 483 /* add the new one allocated into tx free list */ 484 req->bulk_client_private = (usb_opaque_t)dp->tx_free_list; 485 dp->tx_free_list = req; 486 } 487 488 return (USB_SUCCESS); 489 } 490 491 /* ========================================================== */ 492 /* 493 * Start transmission. 494 * Return zero on success, 495 */ 496 /* ========================================================== */ 497 498 #ifdef TXTIMEOUT_TEST 499 static int usbgem_send_cnt = 0; 500 #endif 501 502 /* 503 * usbgem_send is used only to send data packet into ethernet line. 504 */ 505 static mblk_t * 506 usbgem_send_common(struct usbgem_dev *dp, mblk_t *mp, uint32_t flags) 507 { 508 int err; 509 mblk_t *new; 510 usb_bulk_req_t *req; 511 int mcast; 512 int bcast; 513 int len; 514 boolean_t intr; 515 usb_flags_t usb_flags = 0; 516 #ifdef USBGEM_DEBUG_LEVEL 517 usb_pipe_state_t p_state; 518 #endif 519 DPRINTF(2, (CE_CONT, "!%s: %s: called", dp->name, __func__)); 520 521 intr = (flags & 1) != 0; 522 len = msgdsize(mp); 523 bcast = 0; 524 mcast = 0; 525 if (mp->b_rptr[0] & 1) { 526 if (bcmp(mp->b_rptr, &usbgem_bcastaddr, ETHERADDRL) == 0) { 527 bcast = 1; 528 } else { 529 mcast = 1; 530 } 531 } 532 new = (*dp->ugc.usbgc_tx_make_packet)(dp, mp); 533 if (new == NULL) { 534 /* 535 * no memory resource. we don't stop downstream, 536 * we just discard the packet. 537 */ 538 DPRINTF(0, (CE_CONT, "!%s: %s: no memory", 539 dp->name, __func__)); 540 freemsg(mp); 541 542 mutex_enter(&dp->txlock); 543 dp->stats.noxmtbuf++; 544 dp->stats.errxmt++; 545 mutex_exit(&dp->txlock); 546 547 return (NULL); 548 } 549 550 ASSERT(new->b_cont == NULL); 551 552 mutex_enter(&dp->txlock); 553 if (dp->tx_free_list == NULL) { 554 /* 555 * no tx free slot 556 */ 557 ASSERT(dp->tx_busy_cnt == dp->ugc.usbgc_tx_list_max); 558 mutex_exit(&dp->txlock); 559 560 DPRINTF(4, (CE_CONT, "!%s: %s: no free slot", 561 dp->name, __func__)); 562 if (new && new != mp) { 563 /* free reallocated message */ 564 freemsg(new); 565 } 566 return (mp); 567 } 568 req = dp->tx_free_list; 569 dp->tx_free_list = (usb_bulk_req_t *)req->bulk_client_private; 570 dp->tx_busy_cnt++; 571 572 if (dp->tx_free_list == NULL) { 573 intr = B_TRUE; 574 } 575 if (intr) { 576 dp->tx_intr_pended++; 577 } 578 DB_TCI(new) = intr; 579 #ifdef USBGEM_DEBUG_LEVEL 580 new->b_datap->db_cksum32 = dp->tx_seq_num; 581 dp->tx_seq_num++; 582 #endif 583 dp->stats.obytes += len; 584 dp->stats.opackets++; 585 if (bcast | mcast) { 586 dp->stats.obcast += bcast; 587 dp->stats.omcast += mcast; 588 } 589 mutex_exit(&dp->txlock); 590 591 DPRINTF(2, (CE_CONT, "!%s: %s: sending", dp->name, __func__)); 592 593 req->bulk_len = (long)new->b_wptr - (long)new->b_rptr; 594 req->bulk_data = new; 595 req->bulk_client_private = (usb_opaque_t)dp; 596 req->bulk_timeout = dp->bulkout_timeout; /* in second */ 597 req->bulk_attributes = 0; 598 req->bulk_cb = usbgem_bulkout_cb; 599 req->bulk_exc_cb = usbgem_bulkout_cb; 600 req->bulk_completion_reason = 0; 601 req->bulk_cb_flags = 0; 602 603 if (intr) { 604 usb_flags = USB_FLAGS_SLEEP; 605 } 606 if ((err = usb_pipe_bulk_xfer(dp->bulkout_pipe, req, usb_flags)) 607 != USB_SUCCESS) { 608 609 /* failed to transfer the packet, discard it. */ 610 freemsg(new); 611 req->bulk_data = NULL; 612 613 /* recycle the request block */ 614 mutex_enter(&dp->txlock); 615 dp->tx_busy_cnt--; 616 req->bulk_client_private = (usb_opaque_t)dp->tx_free_list; 617 dp->tx_free_list = req; 618 mutex_exit(&dp->txlock); 619 620 cmn_err(CE_NOTE, 621 "%s: %s: usb_pipe_bulk_xfer: failed: err:%d", 622 dp->name, __func__, err); 623 624 /* we use another flag to indicate error state. */ 625 if (dp->fatal_error == (clock_t)0) { 626 dp->fatal_error = usbgem_timestamp_nz(); 627 } 628 } else { 629 /* record the start time */ 630 dp->tx_start_time = ddi_get_lbolt(); 631 } 632 633 if (err == USB_SUCCESS && (usb_flags & USB_FLAGS_SLEEP)) { 634 usbgem_bulkout_cb(dp->bulkout_pipe, req); 635 } 636 637 if (new != mp) { 638 freemsg(mp); 639 } 640 return (NULL); 641 } 642 643 int 644 usbgem_restart_nic(struct usbgem_dev *dp) 645 { 646 int ret; 647 int flags = 0; 648 649 DPRINTF(1, (CE_CONT, "!%s: %s: called", dp->name, __func__)); 650 651 ASSERT(dp->mac_state != MAC_STATE_DISCONNECTED); 652 653 /* 654 * ensure to stop the nic 655 */ 656 if (dp->mac_state == MAC_STATE_ONLINE) { 657 (void) usbgem_mac_stop(dp, MAC_STATE_STOPPED, STOP_GRACEFUL); 658 } 659 660 /* now the nic become quiescent, reset the chip */ 661 if (usbgem_hal_reset_chip(dp) != USB_SUCCESS) { 662 cmn_err(CE_WARN, "%s: %s: failed to reset chip", 663 dp->name, __func__); 664 goto err; 665 } 666 667 /* 668 * restore the nic state step by step 669 */ 670 if (dp->nic_state < NIC_STATE_INITIALIZED) { 671 goto done; 672 } 673 674 if (usbgem_mac_init(dp) != USB_SUCCESS) { 675 cmn_err(CE_WARN, "%s: %s: failed to initialize chip", 676 dp->name, __func__); 677 goto err; 678 } 679 680 /* setup mac address and enable rx filter */ 681 sema_p(&dp->rxfilter_lock); 682 dp->rxmode |= RXMODE_ENABLE; 683 ret = usbgem_hal_set_rx_filter(dp); 684 sema_v(&dp->rxfilter_lock); 685 if (ret != USB_SUCCESS) { 686 goto err; 687 } 688 689 /* 690 * update the link state asynchronously 691 */ 692 cv_signal(&dp->link_watcher_wait_cv); 693 694 /* 695 * XXX - a panic happened because of linkdown. 696 * We must check mii_state here, because the link can be down just 697 * before the restart event happen. If the link is down now, 698 * gem_mac_start() will be called from gem_mii_link_check() when 699 * the link become up later. 700 */ 701 if (dp->mii_state == MII_STATE_LINKUP) { 702 if (usbgem_hal_set_media(dp) != USB_SUCCESS) { 703 goto err; 704 } 705 if (dp->nic_state < NIC_STATE_ONLINE) { 706 goto done; 707 } 708 709 (void) usbgem_mac_start(dp); 710 711 } 712 done: 713 return (USB_SUCCESS); 714 err: 715 return (USB_FAILURE); 716 } 717 718 static void 719 usbgem_tx_timeout(struct usbgem_dev *dp) 720 { 721 uint_t rwlock; 722 clock_t now; 723 724 for (; ; ) { 725 mutex_enter(&dp->tx_watcher_lock); 726 (void) cv_timedwait(&dp->tx_watcher_cv, &dp->tx_watcher_lock, 727 dp->tx_watcher_interval + ddi_get_lbolt()); 728 mutex_exit(&dp->tx_watcher_lock); 729 730 if (dp->tx_watcher_stop) { 731 break; 732 } 733 734 now = ddi_get_lbolt(); 735 736 rwlock = RW_READER; 737 again: 738 rw_enter(&dp->dev_state_lock, rwlock); 739 740 if ((dp->mac_state != MAC_STATE_DISCONNECTED && 741 dp->fatal_error && 742 now - dp->fatal_error >= dp->ugc.usbgc_tx_timeout) || 743 (dp->mac_state == MAC_STATE_ONLINE && 744 dp->mii_state == MII_STATE_LINKUP && 745 dp->tx_busy_cnt != 0 && 746 now - dp->tx_start_time >= dp->ugc.usbgc_tx_timeout)) { 747 if (rwlock == RW_READER) { 748 /* 749 * Upgrade dev_state_lock from shared mode 750 * to exclusive mode to restart nic 751 */ 752 rwlock = RW_WRITER; 753 rw_exit(&dp->dev_state_lock); 754 goto again; 755 } 756 cmn_err(CE_WARN, "%s: %s: restarting the nic:" 757 " fatal_error:%ld nic_state:%d" 758 " mac_state:%d starttime:%ld", 759 dp->name, __func__, 760 dp->fatal_error ? now - dp->fatal_error: 0, 761 dp->nic_state, dp->mac_state, 762 dp->tx_busy_cnt ? now - dp->tx_start_time : 0); 763 764 (void) usbgem_restart_nic(dp); 765 } 766 767 rw_exit(&dp->dev_state_lock); 768 } 769 } 770 771 static int 772 usbgem_tx_watcher_start(struct usbgem_dev *dp) 773 { 774 int err; 775 kthread_t *wdth; 776 777 DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__)); 778 779 /* make a first call of uwgem_lw_link_check() */ 780 dp->tx_watcher_stop = 0; 781 dp->tx_watcher_interval = drv_usectohz(1000*1000); 782 783 wdth = thread_create(NULL, 0, usbgem_tx_timeout, dp, 0, &p0, 784 TS_RUN, minclsyspri); 785 if (wdth == NULL) { 786 cmn_err(CE_WARN, 787 "!%s: %s: failed to create a tx_watcher thread", 788 dp->name, __func__); 789 return (USB_FAILURE); 790 } 791 dp->tx_watcher_did = wdth->t_did; 792 793 return (USB_SUCCESS); 794 } 795 796 static void 797 usbgem_tx_watcher_stop(struct usbgem_dev *dp) 798 { 799 DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__)); 800 if (dp->tx_watcher_did) { 801 /* Ensure timer routine stopped */ 802 dp->tx_watcher_stop = 1; 803 cv_signal(&dp->tx_watcher_cv); 804 thread_join(dp->tx_watcher_did); 805 dp->tx_watcher_did = 0; 806 } 807 } 808 809 /* ================================================================== */ 810 /* 811 * Callback handlers 812 */ 813 /* ================================================================== */ 814 static void 815 usbgem_bulkin_cb(usb_pipe_handle_t pipe, usb_bulk_req_t *req) 816 { 817 mblk_t *newmp; 818 mblk_t *mp; 819 mblk_t *tp; 820 uint64_t len = 0; 821 int pkts = 0; 822 int bcast = 0; 823 int mcast = 0; 824 boolean_t busy; 825 struct usbgem_dev *dp; 826 827 dp = (struct usbgem_dev *)req->bulk_client_private; 828 mp = req->bulk_data; 829 req->bulk_data = NULL; 830 831 DPRINTF(2, (CE_CONT, "!%s: %s: mp:%p, cr:%s(%d)", 832 dp->name, __func__, mp, 833 usb_str_cr(req->bulk_completion_reason), 834 req->bulk_completion_reason)); 835 836 /* 837 * we cannot acquire dev_state_lock because the routine 838 * must be executed during usbgem_mac_stop() to avoid 839 * dead lock. 840 * we use a simle membar operation to get the state correctly. 841 */ 842 membar_consumer(); 843 844 if (req->bulk_completion_reason == USB_CR_OK && 845 dp->nic_state == NIC_STATE_ONLINE) { 846 newmp = (*dp->ugc.usbgc_rx_make_packet)(dp, mp); 847 848 if (newmp != mp) { 849 /* the message has been reallocated, free old one */ 850 freemsg(mp); 851 } 852 853 /* the message may includes one or more ethernet packets */ 854 for (tp = newmp; tp; tp = tp->b_next) { 855 len += (uintptr_t)tp->b_wptr - (uintptr_t)tp->b_rptr; 856 pkts++; 857 if (tp->b_rptr[0] & 1) { 858 if (bcmp(tp->b_rptr, &usbgem_bcastaddr, 859 ETHERADDRL) == 0) { 860 bcast++; 861 } else { 862 mcast++; 863 } 864 } 865 } 866 867 /* send up if it is a valid packet */ 868 mac_rx(dp->mh, NULL, newmp); 869 } else { 870 freemsg(mp); 871 len = 0; 872 } 873 874 mutex_enter(&dp->rxlock); 875 /* update rx_active */ 876 if (dp->rx_active) { 877 dp->rx_active = dp->mac_state == MAC_STATE_ONLINE; 878 } 879 880 dp->stats.rbytes += len; 881 dp->stats.rpackets += pkts; 882 if (bcast | mcast) { 883 dp->stats.rbcast += bcast; 884 dp->stats.rmcast += mcast; 885 } 886 mutex_exit(&dp->rxlock); 887 888 if (dp->rx_active) { 889 /* prepare to receive the next packets */ 890 if (usbgem_rx_start_unit(dp, req)) { 891 /* we successed */ 892 goto done; 893 } 894 cmn_err(CE_WARN, 895 "!%s: %s: failed to fill next rx packet", 896 dp->name, __func__); 897 /* 898 * we use another flag to indicate error state. 899 * if we acquire dev_state_lock for RW_WRITER here, 900 * usbgem_mac_stop() may hang. 901 */ 902 if (dp->fatal_error == (clock_t)0) { 903 dp->fatal_error = usbgem_timestamp_nz(); 904 } 905 } else { 906 /* no need to prepare the next packets */ 907 usb_free_bulk_req(req); 908 } 909 910 mutex_enter(&dp->rxlock); 911 dp->rx_active = B_FALSE; 912 dp->rx_busy_cnt--; 913 if (dp->rx_busy_cnt == 0) { 914 /* wake up someone waits for me */ 915 cv_broadcast(&dp->rx_drain_cv); 916 } 917 mutex_exit(&dp->rxlock); 918 done: 919 ; 920 } 921 922 static void 923 usbgem_bulkout_cb(usb_pipe_handle_t pipe, usb_bulk_req_t *req) 924 { 925 boolean_t intr; 926 boolean_t tx_sched; 927 struct usbgem_dev *dp; 928 929 dp = (struct usbgem_dev *)req->bulk_client_private; 930 tx_sched = B_FALSE; 931 932 DPRINTF(2, (CE_CONT, 933 "!%s: %s: cr:%s(%d) cb_flags:0x%x head:%d tail:%d", 934 dp->name, __func__, 935 usb_str_cr(req->bulk_completion_reason), 936 req->bulk_completion_reason, 937 req->bulk_cb_flags, 938 dp->tx_busy_cnt)); 939 940 /* we have finished to transfer the packet into tx fifo */ 941 intr = DB_TCI(req->bulk_data); 942 freemsg(req->bulk_data); 943 944 if (req->bulk_completion_reason != USB_CR_OK && 945 dp->fatal_error == (clock_t)0) { 946 dp->fatal_error = usbgem_timestamp_nz(); 947 } 948 949 mutex_enter(&dp->txlock); 950 951 if (intr) { 952 ASSERT(dp->tx_intr_pended > 0); 953 /* find the last interrupt we have scheduled */ 954 if (--(dp->tx_intr_pended) == 0) { 955 tx_sched = B_TRUE; 956 } 957 } 958 959 ASSERT(dp->tx_busy_cnt > 0); 960 req->bulk_client_private = (usb_opaque_t)dp->tx_free_list; 961 dp->tx_free_list = req; 962 dp->tx_busy_cnt--; 963 964 #ifdef CONFIG_TX_LIMITER 965 if (tx_sched) { 966 dp->tx_max_packets = 967 min(dp->tx_max_packets + 1, dp->ugc.usbgc_tx_list_max); 968 } 969 #endif 970 if (dp->mac_state != MAC_STATE_ONLINE && dp->tx_busy_cnt == 0) { 971 cv_broadcast(&dp->tx_drain_cv); 972 } 973 974 mutex_exit(&dp->txlock); 975 976 if (tx_sched) { 977 mac_tx_update(dp->mh); 978 } 979 } 980 981 static void 982 usbgem_intr_cb(usb_pipe_handle_t ph, usb_intr_req_t *req) 983 { 984 struct usbgem_dev *dp; 985 986 dp = (struct usbgem_dev *)req->intr_client_private; 987 dp->stats.intr++; 988 989 if (req->intr_completion_reason == USB_CR_OK) { 990 (*dp->ugc.usbgc_interrupt)(dp, req->intr_data); 991 } 992 993 /* free the request and data */ 994 usb_free_intr_req(req); 995 } 996 997 /* ======================================================================== */ 998 /* 999 * MII support routines 1000 */ 1001 /* ======================================================================== */ 1002 static void 1003 usbgem_choose_forcedmode(struct usbgem_dev *dp) 1004 { 1005 /* choose media mode */ 1006 if (dp->anadv_1000fdx || dp->anadv_1000hdx) { 1007 dp->speed = USBGEM_SPD_1000; 1008 dp->full_duplex = dp->anadv_1000fdx; 1009 } else if (dp->anadv_100fdx || dp->anadv_100t4) { 1010 dp->speed = USBGEM_SPD_100; 1011 dp->full_duplex = B_TRUE; 1012 } else if (dp->anadv_100hdx) { 1013 dp->speed = USBGEM_SPD_100; 1014 dp->full_duplex = B_FALSE; 1015 } else { 1016 dp->speed = USBGEM_SPD_10; 1017 dp->full_duplex = dp->anadv_10fdx; 1018 } 1019 } 1020 1021 static uint16_t 1022 usbgem_mii_read(struct usbgem_dev *dp, uint_t reg, int *errp) 1023 { 1024 uint16_t val; 1025 1026 sema_p(&dp->hal_op_lock); 1027 val = (*dp->ugc.usbgc_mii_read)(dp, reg, errp); 1028 sema_v(&dp->hal_op_lock); 1029 1030 return (val); 1031 } 1032 1033 static void 1034 usbgem_mii_write(struct usbgem_dev *dp, uint_t reg, uint16_t val, int *errp) 1035 { 1036 sema_p(&dp->hal_op_lock); 1037 (*dp->ugc.usbgc_mii_write)(dp, reg, val, errp); 1038 sema_v(&dp->hal_op_lock); 1039 } 1040 1041 static int 1042 usbgem_mii_probe(struct usbgem_dev *dp) 1043 { 1044 int err; 1045 1046 err = (*dp->ugc.usbgc_mii_probe)(dp); 1047 return (err); 1048 } 1049 1050 static int 1051 usbgem_mii_init(struct usbgem_dev *dp) 1052 { 1053 int err; 1054 1055 err = (*dp->ugc.usbgc_mii_init)(dp); 1056 return (err); 1057 } 1058 1059 #define fc_cap_decode(x) \ 1060 ((((x) & MII_ABILITY_PAUSE) != 0 ? 1 : 0) | \ 1061 (((x) & MII_ABILITY_ASM_DIR) != 0 ? 2 : 0)) 1062 1063 int 1064 usbgem_mii_config_default(struct usbgem_dev *dp, int *errp) 1065 { 1066 uint16_t mii_stat; 1067 uint16_t val; 1068 1069 DPRINTF(1, (CE_CONT, "!%s: %s: called", dp->name, __func__)); 1070 1071 /* 1072 * Configure bits in advertisement register 1073 */ 1074 mii_stat = dp->mii_status; 1075 1076 DPRINTF(1, (CE_CONT, "!%s: %s: MII_STATUS reg:%b", 1077 dp->name, __func__, mii_stat, MII_STATUS_BITS)); 1078 1079 if ((mii_stat & MII_STATUS_ABILITY_TECH) == 0) { 1080 /* it's funny */ 1081 cmn_err(CE_WARN, "!%s: wrong ability bits: mii_status:%b", 1082 dp->name, mii_stat, MII_STATUS_BITS); 1083 return (USB_FAILURE); 1084 } 1085 1086 /* Do not change the rest of ability bits in advert reg */ 1087 val = usbgem_mii_read(dp, MII_AN_ADVERT, errp) & ~MII_ABILITY_ALL; 1088 if (*errp != USB_SUCCESS) { 1089 goto usberr; 1090 } 1091 1092 DPRINTF(0, (CE_CONT, 1093 "!%s: %s: 100T4:%d 100F:%d 100H:%d 10F:%d 10H:%d", 1094 dp->name, __func__, 1095 dp->anadv_100t4, dp->anadv_100fdx, dp->anadv_100hdx, 1096 dp->anadv_10fdx, dp->anadv_10hdx)); 1097 1098 /* set technology bits */ 1099 if (dp->anadv_100t4) { 1100 val |= MII_ABILITY_100BASE_T4; 1101 } 1102 if (dp->anadv_100fdx) { 1103 val |= MII_ABILITY_100BASE_TX_FD; 1104 } 1105 if (dp->anadv_100hdx) { 1106 val |= MII_ABILITY_100BASE_TX; 1107 } 1108 if (dp->anadv_10fdx) { 1109 val |= MII_ABILITY_10BASE_T_FD; 1110 } 1111 if (dp->anadv_10hdx) { 1112 val |= MII_ABILITY_10BASE_T; 1113 } 1114 1115 /* set flow control capabilities */ 1116 if (dp->anadv_pause) { 1117 val |= MII_ABILITY_PAUSE; 1118 } 1119 if (dp->anadv_asmpause) { 1120 val |= MII_ABILITY_ASM_DIR; 1121 } 1122 1123 DPRINTF(0, (CE_CONT, 1124 "!%s: %s: setting MII_AN_ADVERT reg:%b, pause:%d, asmpause:%d", 1125 dp->name, __func__, val, MII_ABILITY_BITS, 1126 dp->anadv_pause, dp->anadv_asmpause)); 1127 1128 usbgem_mii_write(dp, MII_AN_ADVERT, val, errp); 1129 if (*errp != USB_SUCCESS) { 1130 goto usberr; 1131 } 1132 1133 if (dp->mii_status & MII_STATUS_XSTATUS) { 1134 /* 1135 * 1000Base-T GMII support 1136 */ 1137 if (!dp->anadv_autoneg) { 1138 /* enable manual configuration */ 1139 val = MII_1000TC_CFG_EN; 1140 if (dp->anadv_1000t_ms == 2) { 1141 val |= MII_1000TC_CFG_VAL; 1142 } 1143 } else { 1144 val = 0; 1145 if (dp->anadv_1000fdx) { 1146 val |= MII_1000TC_ADV_FULL; 1147 } 1148 if (dp->anadv_1000hdx) { 1149 val |= MII_1000TC_ADV_HALF; 1150 } 1151 switch (dp->anadv_1000t_ms) { 1152 case 1: 1153 /* slave */ 1154 val |= MII_1000TC_CFG_EN; 1155 break; 1156 1157 case 2: 1158 /* master */ 1159 val |= MII_1000TC_CFG_EN | MII_1000TC_CFG_VAL; 1160 break; 1161 1162 default: 1163 /* auto: do nothing */ 1164 break; 1165 } 1166 } 1167 DPRINTF(0, (CE_CONT, 1168 "!%s: %s: setting MII_1000TC reg:%b", 1169 dp->name, __func__, val, MII_1000TC_BITS)); 1170 1171 usbgem_mii_write(dp, MII_1000TC, val, errp); 1172 if (*errp != USB_SUCCESS) { 1173 goto usberr; 1174 } 1175 } 1176 return (USB_SUCCESS); 1177 1178 usberr: 1179 return (*errp); 1180 } 1181 1182 static char *usbgem_fc_type[] = { 1183 "without", 1184 "with symmetric", 1185 "with tx", 1186 "with rx", 1187 }; 1188 1189 #define USBGEM_LINKUP(dp) mac_link_update((dp)->mh, LINK_STATE_UP) 1190 #define USBGEM_LINKDOWN(dp) mac_link_update((dp)->mh, LINK_STATE_DOWN) 1191 1192 static uint8_t usbgem_fc_result[4 /* my cap */][4 /* lp cap */] = { 1193 /* none symm tx rx/symm */ 1194 /* none */ 1195 {FLOW_CONTROL_NONE, 1196 FLOW_CONTROL_NONE, 1197 FLOW_CONTROL_NONE, 1198 FLOW_CONTROL_NONE}, 1199 /* sym */ 1200 {FLOW_CONTROL_NONE, 1201 FLOW_CONTROL_SYMMETRIC, 1202 FLOW_CONTROL_NONE, 1203 FLOW_CONTROL_SYMMETRIC}, 1204 /* tx */ 1205 {FLOW_CONTROL_NONE, 1206 FLOW_CONTROL_NONE, 1207 FLOW_CONTROL_NONE, 1208 FLOW_CONTROL_TX_PAUSE}, 1209 /* rx/symm */ 1210 {FLOW_CONTROL_NONE, 1211 FLOW_CONTROL_SYMMETRIC, 1212 FLOW_CONTROL_RX_PAUSE, 1213 FLOW_CONTROL_SYMMETRIC}, 1214 }; 1215 1216 static boolean_t 1217 usbgem_mii_link_check(struct usbgem_dev *dp, int *oldstatep, int *newstatep) 1218 { 1219 boolean_t tx_sched = B_FALSE; 1220 uint16_t status; 1221 uint16_t advert; 1222 uint16_t lpable; 1223 uint16_t exp; 1224 uint16_t ctl1000; 1225 uint16_t stat1000; 1226 uint16_t val; 1227 clock_t now; 1228 clock_t diff; 1229 int linkdown_action; 1230 boolean_t fix_phy = B_FALSE; 1231 int err; 1232 uint_t rwlock; 1233 1234 DPRINTF(4, (CE_CONT, "!%s: %s: time:%d state:%d", 1235 dp->name, __func__, ddi_get_lbolt(), dp->mii_state)); 1236 1237 if (dp->mii_state != MII_STATE_LINKUP) { 1238 rwlock = RW_WRITER; 1239 } else { 1240 rwlock = RW_READER; 1241 } 1242 again: 1243 rw_enter(&dp->dev_state_lock, rwlock); 1244 1245 /* save old mii state */ 1246 *oldstatep = dp->mii_state; 1247 1248 if (dp->mac_state == MAC_STATE_DISCONNECTED) { 1249 /* stop periodic execution of the link watcher */ 1250 dp->mii_interval = 0; 1251 tx_sched = B_FALSE; 1252 goto next; 1253 } 1254 1255 now = ddi_get_lbolt(); 1256 diff = now - dp->mii_last_check; 1257 dp->mii_last_check = now; 1258 1259 /* 1260 * For NWAM, don't show linkdown state right 1261 * when the device is attached. 1262 */ 1263 if (dp->linkup_delay > 0) { 1264 if (dp->linkup_delay > diff) { 1265 dp->linkup_delay -= diff; 1266 } else { 1267 /* link up timeout */ 1268 dp->linkup_delay = -1; 1269 } 1270 } 1271 1272 next_nowait: 1273 switch (dp->mii_state) { 1274 case MII_STATE_UNKNOWN: 1275 goto reset_phy; 1276 1277 case MII_STATE_RESETTING: 1278 dp->mii_timer -= diff; 1279 if (dp->mii_timer > 0) { 1280 /* don't read phy registers in resetting */ 1281 dp->mii_interval = WATCH_INTERVAL_FAST; 1282 goto next; 1283 } 1284 1285 val = usbgem_mii_read(dp, MII_CONTROL, &err); 1286 if (err != USB_SUCCESS) { 1287 goto usberr; 1288 } 1289 if (val & MII_CONTROL_RESET) { 1290 cmn_err(CE_NOTE, 1291 "!%s: time:%ld resetting phy not complete." 1292 " mii_control:0x%b", 1293 dp->name, ddi_get_lbolt(), 1294 val, MII_CONTROL_BITS); 1295 } 1296 1297 /* ensure neither isolated nor pwrdown nor auto-nego mode */ 1298 usbgem_mii_write(dp, MII_CONTROL, 0, &err); 1299 if (err != USB_SUCCESS) { 1300 goto usberr; 1301 } 1302 #if USBGEM_DEBUG_LEVEL > 10 1303 val = usbgem_mii_read(dp, MII_CONTROL, &err); 1304 cmn_err(CE_CONT, "!%s: readback control %b", 1305 dp->name, val, MII_CONTROL_BITS); 1306 #endif 1307 /* As resetting PHY has completed, configure PHY registers */ 1308 if ((*dp->ugc.usbgc_mii_config)(dp, &err) != USB_SUCCESS) { 1309 /* we failed to configure PHY */ 1310 goto usberr; 1311 } 1312 1313 /* prepare for forced mode */ 1314 usbgem_choose_forcedmode(dp); 1315 1316 dp->mii_lpable = 0; 1317 dp->mii_advert = 0; 1318 dp->mii_exp = 0; 1319 dp->mii_ctl1000 = 0; 1320 dp->mii_stat1000 = 0; 1321 1322 dp->flow_control = FLOW_CONTROL_NONE; 1323 1324 if (!dp->anadv_autoneg) { 1325 /* skip auto-negotiation phase */ 1326 dp->mii_state = MII_STATE_MEDIA_SETUP; 1327 dp->mii_timer = dp->ugc.usbgc_mii_linkdown_timeout; 1328 goto next_nowait; 1329 } 1330 1331 /* issue an auto-negotiation command */ 1332 goto autonego; 1333 1334 case MII_STATE_AUTONEGOTIATING: 1335 /* 1336 * Autonegotiation in progress 1337 */ 1338 dp->mii_timer -= diff; 1339 if (dp->mii_timer - 1340 (dp->ugc.usbgc_mii_an_timeout - dp->ugc.usbgc_mii_an_wait) 1341 > 0) { 1342 /* wait for minimum time (2.3 - 2.5 sec) */ 1343 dp->mii_interval = WATCH_INTERVAL_FAST; 1344 goto next; 1345 } 1346 1347 /* read PHY status */ 1348 status = usbgem_mii_read(dp, MII_STATUS, &err); 1349 if (err != USB_SUCCESS) { 1350 goto usberr; 1351 } 1352 DPRINTF(4, (CE_CONT, 1353 "!%s: %s: called: mii_state:%d MII_STATUS reg:%b", 1354 dp->name, __func__, dp->mii_state, 1355 status, MII_STATUS_BITS)); 1356 1357 if (status & MII_STATUS_REMFAULT) { 1358 /* 1359 * The link parnert told me something wrong happend. 1360 * What do we do ? 1361 */ 1362 cmn_err(CE_CONT, 1363 "!%s: auto-negotiation failed: remote fault", 1364 dp->name); 1365 goto autonego; 1366 } 1367 1368 if ((status & MII_STATUS_ANDONE) == 0) { 1369 if (dp->mii_timer <= 0) { 1370 /* 1371 * Auto-negotiation has been timed out, 1372 * Reset PHY and try again. 1373 */ 1374 if (!dp->mii_supress_msg) { 1375 cmn_err(CE_WARN, 1376 "!%s: auto-negotiation failed:" 1377 " timeout", 1378 dp->name); 1379 dp->mii_supress_msg = B_TRUE; 1380 } 1381 goto autonego; 1382 } 1383 /* 1384 * Auto-negotiation is in progress. Wait for a while. 1385 */ 1386 dp->mii_interval = dp->ugc.usbgc_mii_an_watch_interval; 1387 goto next; 1388 } 1389 1390 /* 1391 * Auto-negotiation has been completed. Let's go to AN_DONE. 1392 */ 1393 dp->mii_state = MII_STATE_AN_DONE; 1394 dp->mii_supress_msg = B_FALSE; 1395 DPRINTF(0, (CE_CONT, 1396 "!%s: auto-negotiation completed, MII_STATUS:%b", 1397 dp->name, status, MII_STATUS_BITS)); 1398 1399 if (dp->ugc.usbgc_mii_an_delay > 0) { 1400 dp->mii_timer = dp->ugc.usbgc_mii_an_delay; 1401 dp->mii_interval = drv_usectohz(20*1000); 1402 goto next; 1403 } 1404 1405 dp->mii_timer = 0; 1406 diff = 0; 1407 goto next_nowait; 1408 1409 case MII_STATE_AN_DONE: 1410 /* 1411 * Auto-negotiation has done. Now we can set up media. 1412 */ 1413 dp->mii_timer -= diff; 1414 if (dp->mii_timer > 0) { 1415 /* wait for a while */ 1416 dp->mii_interval = WATCH_INTERVAL_FAST; 1417 goto next; 1418 } 1419 1420 /* 1421 * Setup speed and duplex mode according with 1422 * the result of auto negotiation. 1423 */ 1424 1425 /* 1426 * Read registers required to determin current 1427 * duplex mode and media speed. 1428 */ 1429 if (dp->ugc.usbgc_mii_an_delay > 0) { 1430 /* the 'status' variable is not initialized yet */ 1431 status = usbgem_mii_read(dp, MII_STATUS, &err); 1432 if (err != USB_SUCCESS) { 1433 goto usberr; 1434 } 1435 } 1436 advert = usbgem_mii_read(dp, MII_AN_ADVERT, &err); 1437 if (err != USB_SUCCESS) { 1438 goto usberr; 1439 } 1440 lpable = usbgem_mii_read(dp, MII_AN_LPABLE, &err); 1441 if (err != USB_SUCCESS) { 1442 goto usberr; 1443 } 1444 exp = usbgem_mii_read(dp, MII_AN_EXPANSION, &err); 1445 if (err != USB_SUCCESS) { 1446 goto usberr; 1447 } 1448 if (exp == 0xffff) { 1449 /* some phys don't have exp register */ 1450 exp = 0; 1451 } 1452 1453 ctl1000 = 0; 1454 stat1000 = 0; 1455 if (dp->mii_status & MII_STATUS_XSTATUS) { 1456 ctl1000 = usbgem_mii_read(dp, MII_1000TC, &err); 1457 if (err != USB_SUCCESS) { 1458 goto usberr; 1459 } 1460 stat1000 = usbgem_mii_read(dp, MII_1000TS, &err); 1461 if (err != USB_SUCCESS) { 1462 goto usberr; 1463 } 1464 } 1465 dp->mii_lpable = lpable; 1466 dp->mii_advert = advert; 1467 dp->mii_exp = exp; 1468 dp->mii_ctl1000 = ctl1000; 1469 dp->mii_stat1000 = stat1000; 1470 1471 cmn_err(CE_CONT, 1472 "!%s: auto-negotiation done: " 1473 "status:%b, advert:%b, lpable:%b, exp:%b", 1474 dp->name, 1475 status, MII_STATUS_BITS, 1476 advert, MII_ABILITY_BITS, 1477 lpable, MII_ABILITY_BITS, 1478 exp, MII_AN_EXP_BITS); 1479 1480 DPRINTF(0, (CE_CONT, "!%s: MII_STATUS:%b", 1481 dp->name, status, MII_STATUS_BITS)); 1482 1483 if (dp->mii_status & MII_STATUS_XSTATUS) { 1484 cmn_err(CE_CONT, 1485 "! MII_1000TC reg:%b, MII_1000TS reg:%b", 1486 ctl1000, MII_1000TC_BITS, 1487 stat1000, MII_1000TS_BITS); 1488 } 1489 1490 if (usbgem_population(lpable) <= 1 && 1491 (exp & MII_AN_EXP_LPCANAN) == 0) { 1492 if ((advert & MII_ABILITY_TECH) != lpable) { 1493 cmn_err(CE_WARN, 1494 "!%s: but the link partner doesn't seem" 1495 " to have auto-negotiation capability." 1496 " please check the link configuration.", 1497 dp->name); 1498 } 1499 /* 1500 * it should be a result of pararell detection, 1501 * which cannot detect duplex mode. 1502 */ 1503 if ((advert & lpable) == 0 && 1504 lpable & MII_ABILITY_10BASE_T) { 1505 /* no common technology, try 10M half mode */ 1506 lpable |= advert & MII_ABILITY_10BASE_T; 1507 fix_phy = B_TRUE; 1508 } 1509 } else if (lpable == 0) { 1510 cmn_err(CE_WARN, "!%s: wrong lpable.", dp->name); 1511 goto reset_phy; 1512 } 1513 /* 1514 * configure current link mode according to AN priority. 1515 */ 1516 val = advert & lpable; 1517 if ((ctl1000 & MII_1000TC_ADV_FULL) && 1518 (stat1000 & MII_1000TS_LP_FULL)) { 1519 /* 1000BaseT & full duplex */ 1520 dp->speed = USBGEM_SPD_1000; 1521 dp->full_duplex = B_TRUE; 1522 } else if ((ctl1000 & MII_1000TC_ADV_HALF) && 1523 (stat1000 & MII_1000TS_LP_HALF)) { 1524 /* 1000BaseT & half duplex */ 1525 dp->speed = USBGEM_SPD_1000; 1526 dp->full_duplex = B_FALSE; 1527 } else if ((val & MII_ABILITY_100BASE_TX_FD)) { 1528 /* 100BaseTx & fullduplex */ 1529 dp->speed = USBGEM_SPD_100; 1530 dp->full_duplex = B_TRUE; 1531 } else if ((val & MII_ABILITY_100BASE_T4)) { 1532 /* 100BaseTx & fullduplex */ 1533 dp->speed = USBGEM_SPD_100; 1534 dp->full_duplex = B_TRUE; 1535 } else if ((val & MII_ABILITY_100BASE_TX)) { 1536 /* 100BaseTx & half duplex */ 1537 dp->speed = USBGEM_SPD_100; 1538 dp->full_duplex = B_FALSE; 1539 } else if ((val & MII_ABILITY_10BASE_T_FD)) { 1540 /* 10BaseT & full duplex */ 1541 dp->speed = USBGEM_SPD_10; 1542 dp->full_duplex = B_TRUE; 1543 } else if ((val & MII_ABILITY_10BASE_T)) { 1544 /* 10BaseT & half duplex */ 1545 dp->speed = USBGEM_SPD_10; 1546 dp->full_duplex = B_FALSE; 1547 } else { 1548 /* 1549 * the link partner doesn't seem to have 1550 * auto-negotiation capability and our PHY 1551 * could not report current mode correctly. 1552 * We guess current mode by mii_control register. 1553 */ 1554 val = usbgem_mii_read(dp, MII_CONTROL, &err); 1555 if (err != USB_SUCCESS) { 1556 goto usberr; 1557 } 1558 1559 /* select 100m half or 10m half */ 1560 dp->speed = (val & MII_CONTROL_100MB) ? 1561 USBGEM_SPD_100 : USBGEM_SPD_10; 1562 dp->full_duplex = B_FALSE; 1563 fix_phy = B_TRUE; 1564 1565 cmn_err(CE_NOTE, 1566 "!%s: auto-negotiation done but " 1567 "common ability not found.\n" 1568 "PHY state: control:%b advert:%b lpable:%b\n" 1569 "guessing %d Mbps %s duplex mode", 1570 dp->name, 1571 val, MII_CONTROL_BITS, 1572 advert, MII_ABILITY_BITS, 1573 lpable, MII_ABILITY_BITS, 1574 usbgem_speed_value[dp->speed], 1575 dp->full_duplex ? "full" : "half"); 1576 } 1577 1578 if (dp->full_duplex) { 1579 dp->flow_control = 1580 usbgem_fc_result[fc_cap_decode(advert)] 1581 [fc_cap_decode(lpable)]; 1582 } else { 1583 dp->flow_control = FLOW_CONTROL_NONE; 1584 } 1585 dp->mii_state = MII_STATE_MEDIA_SETUP; 1586 dp->mii_timer = dp->ugc.usbgc_mii_linkdown_timeout; 1587 goto next_nowait; 1588 1589 case MII_STATE_MEDIA_SETUP: 1590 DPRINTF(2, (CE_CONT, "!%s: setup midia mode", dp->name)); 1591 1592 /* assume the link state is down */ 1593 dp->mii_state = MII_STATE_LINKDOWN; 1594 dp->mii_supress_msg = B_FALSE; 1595 1596 /* use short interval */ 1597 dp->mii_interval = WATCH_INTERVAL_FAST; 1598 1599 if ((!dp->anadv_autoneg) || 1600 dp->ugc.usbgc_mii_an_oneshot || fix_phy) { 1601 1602 /* 1603 * write the result of auto negotiation back. 1604 */ 1605 val = usbgem_mii_read(dp, MII_CONTROL, &err); 1606 if (err != USB_SUCCESS) { 1607 goto usberr; 1608 } 1609 val &= ~(MII_CONTROL_SPEED | MII_CONTROL_FDUPLEX | 1610 MII_CONTROL_ANE | MII_CONTROL_RSAN); 1611 1612 if (dp->full_duplex) { 1613 val |= MII_CONTROL_FDUPLEX; 1614 } 1615 1616 switch (dp->speed) { 1617 case USBGEM_SPD_1000: 1618 val |= MII_CONTROL_1000MB; 1619 break; 1620 1621 case USBGEM_SPD_100: 1622 val |= MII_CONTROL_100MB; 1623 break; 1624 1625 default: 1626 cmn_err(CE_WARN, "%s: unknown speed:%d", 1627 dp->name, dp->speed); 1628 /* FALLTHROUGH */ 1629 1630 case USBGEM_SPD_10: 1631 /* for USBGEM_SPD_10, do nothing */ 1632 break; 1633 } 1634 1635 if (dp->mii_status & MII_STATUS_XSTATUS) { 1636 usbgem_mii_write(dp, 1637 MII_1000TC, MII_1000TC_CFG_EN, &err); 1638 if (err != USB_SUCCESS) { 1639 goto usberr; 1640 } 1641 } 1642 usbgem_mii_write(dp, MII_CONTROL, val, &err); 1643 if (err != USB_SUCCESS) { 1644 goto usberr; 1645 } 1646 } 1647 /* 1648 * XXX -- nic state should be one of 1649 * NIC_STATE_DISCONNECTED 1650 * NIC_STATE_STOPPED 1651 * NIC_STATE_INITIALIZED 1652 * NIC_STATE_ONLINE 1653 */ 1654 if (dp->nic_state >= NIC_STATE_INITIALIZED) { 1655 /* notify the result of autonegotiation to mac */ 1656 if (usbgem_hal_set_media(dp) != USB_SUCCESS) { 1657 goto usberr; 1658 } 1659 } 1660 goto next_nowait; 1661 1662 case MII_STATE_LINKDOWN: 1663 status = usbgem_mii_read(dp, MII_STATUS, &err); 1664 if (err != USB_SUCCESS) { 1665 goto usberr; 1666 } 1667 if (status & MII_STATUS_LINKUP) { 1668 /* 1669 * Link is going up 1670 */ 1671 dp->mii_state = MII_STATE_LINKUP; 1672 dp->mii_supress_msg = B_FALSE; 1673 1674 DPRINTF(0, (CE_CONT, 1675 "!%s: link up detected: status:%b", 1676 dp->name, status, MII_STATUS_BITS)); 1677 1678 /* 1679 * MII_CONTROL_100MB and MII_CONTROL_FDUPLEX are 1680 * ignored when MII_CONTROL_ANE is set. 1681 */ 1682 cmn_err(CE_CONT, 1683 "!%s: Link up: %d Mbps %s duplex %s flow control", 1684 dp->name, 1685 usbgem_speed_value[dp->speed], 1686 dp->full_duplex ? "full" : "half", 1687 usbgem_fc_type[dp->flow_control]); 1688 1689 dp->mii_interval = 1690 dp->ugc.usbgc_mii_link_watch_interval; 1691 1692 if (dp->ugc.usbgc_mii_hw_link_detection && 1693 dp->nic_state == NIC_STATE_ONLINE) { 1694 dp->mii_interval = 0; 1695 } 1696 1697 if (dp->nic_state == NIC_STATE_ONLINE) { 1698 if (dp->mac_state == MAC_STATE_INITIALIZED) { 1699 (void) usbgem_mac_start(dp); 1700 } 1701 tx_sched = B_TRUE; 1702 } 1703 1704 goto next; 1705 } 1706 1707 dp->mii_supress_msg = B_TRUE; 1708 if (dp->anadv_autoneg) { 1709 dp->mii_timer -= diff; 1710 if (dp->mii_timer <= 0) { 1711 /* 1712 * the link down timer expired. 1713 * need to restart auto-negotiation. 1714 */ 1715 linkdown_action = 1716 dp->ugc.usbgc_mii_linkdown_timeout_action; 1717 goto restart_autonego; 1718 } 1719 } 1720 /* don't change mii_state */ 1721 goto next; 1722 1723 case MII_STATE_LINKUP: 1724 if (rwlock == RW_READER) { 1725 /* first pass, read mii status */ 1726 status = usbgem_mii_read(dp, MII_STATUS, &err); 1727 if (err != USB_SUCCESS) { 1728 goto usberr; 1729 } 1730 } 1731 if ((status & MII_STATUS_LINKUP) == 0) { 1732 /* 1733 * Link is going down 1734 */ 1735 cmn_err(CE_NOTE, 1736 "!%s: link down detected: status:%b", 1737 dp->name, status, MII_STATUS_BITS); 1738 /* 1739 * Acquire exclusive lock to change mii_state 1740 */ 1741 if (rwlock == RW_READER) { 1742 rwlock = RW_WRITER; 1743 rw_exit(&dp->dev_state_lock); 1744 goto again; 1745 } 1746 1747 dp->mii_state = MII_STATE_LINKDOWN; 1748 dp->mii_timer = dp->ugc.usbgc_mii_linkdown_timeout; 1749 1750 /* 1751 * As we may change the state of the device, 1752 * let us acquire exclusive lock for the state. 1753 */ 1754 if (dp->nic_state == NIC_STATE_ONLINE && 1755 dp->mac_state == MAC_STATE_ONLINE && 1756 dp->ugc.usbgc_mii_stop_mac_on_linkdown) { 1757 (void) usbgem_restart_nic(dp); 1758 /* drain tx */ 1759 tx_sched = B_TRUE; 1760 } 1761 1762 if (dp->anadv_autoneg) { 1763 /* need to restart auto-negotiation */ 1764 linkdown_action = 1765 dp->ugc.usbgc_mii_linkdown_action; 1766 goto restart_autonego; 1767 } 1768 /* 1769 * don't use hw link down detection until the link 1770 * status become stable for a while. 1771 */ 1772 dp->mii_interval = 1773 dp->ugc.usbgc_mii_link_watch_interval; 1774 1775 goto next; 1776 } 1777 1778 /* 1779 * still link up, no need to change mii_state 1780 */ 1781 if (dp->ugc.usbgc_mii_hw_link_detection && 1782 dp->nic_state == NIC_STATE_ONLINE) { 1783 /* 1784 * no need to check link status periodicly 1785 * if nic can generate interrupts when link go down. 1786 */ 1787 dp->mii_interval = 0; 1788 } 1789 goto next; 1790 } 1791 /* NOTREACHED */ 1792 cmn_err(CE_PANIC, "!%s: %s: not reached", dp->name, __func__); 1793 1794 /* 1795 * Actions for new state. 1796 */ 1797 restart_autonego: 1798 switch (linkdown_action) { 1799 case MII_ACTION_RESET: 1800 if (!dp->mii_supress_msg) { 1801 cmn_err(CE_CONT, "!%s: resetting PHY", dp->name); 1802 } 1803 dp->mii_supress_msg = B_TRUE; 1804 goto reset_phy; 1805 1806 case MII_ACTION_NONE: 1807 dp->mii_supress_msg = B_TRUE; 1808 if (dp->ugc.usbgc_mii_an_oneshot) { 1809 goto autonego; 1810 } 1811 /* PHY will restart autonego automatically */ 1812 dp->mii_state = MII_STATE_AUTONEGOTIATING; 1813 dp->mii_timer = dp->ugc.usbgc_mii_an_timeout; 1814 dp->mii_interval = dp->ugc.usbgc_mii_an_watch_interval; 1815 goto next; 1816 1817 case MII_ACTION_RSA: 1818 if (!dp->mii_supress_msg) { 1819 cmn_err(CE_CONT, "!%s: restarting auto-negotiation", 1820 dp->name); 1821 } 1822 dp->mii_supress_msg = B_TRUE; 1823 goto autonego; 1824 1825 default: 1826 cmn_err(CE_PANIC, "!%s: unknowm linkdown action: %d", 1827 dp->name, dp->ugc.usbgc_mii_linkdown_action); 1828 } 1829 /* NOTREACHED */ 1830 1831 reset_phy: 1832 if (!dp->mii_supress_msg) { 1833 cmn_err(CE_CONT, "!%s: resetting PHY", dp->name); 1834 } 1835 dp->mii_state = MII_STATE_RESETTING; 1836 dp->mii_timer = dp->ugc.usbgc_mii_reset_timeout; 1837 if (!dp->ugc.usbgc_mii_dont_reset) { 1838 usbgem_mii_write(dp, MII_CONTROL, MII_CONTROL_RESET, &err); 1839 if (err != USB_SUCCESS) { 1840 goto usberr; 1841 } 1842 } 1843 dp->mii_interval = WATCH_INTERVAL_FAST; 1844 goto next; 1845 1846 autonego: 1847 if (!dp->mii_supress_msg) { 1848 cmn_err(CE_CONT, "!%s: auto-negotiation started", dp->name); 1849 } 1850 dp->mii_state = MII_STATE_AUTONEGOTIATING; 1851 dp->mii_timer = dp->ugc.usbgc_mii_an_timeout; 1852 1853 /* start/restart autoneg */ 1854 val = usbgem_mii_read(dp, MII_CONTROL, &err) & 1855 ~(MII_CONTROL_ISOLATE | MII_CONTROL_PWRDN | MII_CONTROL_RESET); 1856 if (err != USB_SUCCESS) { 1857 goto usberr; 1858 } 1859 if (val & MII_CONTROL_ANE) { 1860 val |= MII_CONTROL_RSAN; 1861 } 1862 usbgem_mii_write(dp, MII_CONTROL, 1863 val | dp->ugc.usbgc_mii_an_cmd | MII_CONTROL_ANE, &err); 1864 if (err != USB_SUCCESS) { 1865 goto usberr; 1866 } 1867 1868 dp->mii_interval = dp->ugc.usbgc_mii_an_watch_interval; 1869 goto next; 1870 1871 usberr: 1872 dp->mii_state = MII_STATE_UNKNOWN; 1873 dp->mii_interval = dp->ugc.usbgc_mii_link_watch_interval; 1874 tx_sched = B_TRUE; 1875 1876 next: 1877 *newstatep = dp->mii_state; 1878 rw_exit(&dp->dev_state_lock); 1879 return (tx_sched); 1880 } 1881 1882 static void 1883 usbgem_mii_link_watcher(struct usbgem_dev *dp) 1884 { 1885 int old_mii_state; 1886 int new_mii_state; 1887 boolean_t tx_sched; 1888 1889 DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__)); 1890 1891 for (; ; ) { 1892 1893 mutex_enter(&dp->link_watcher_lock); 1894 if (dp->mii_interval) { 1895 (void) cv_timedwait(&dp->link_watcher_wait_cv, 1896 &dp->link_watcher_lock, 1897 dp->mii_interval + ddi_get_lbolt()); 1898 } else { 1899 cv_wait(&dp->link_watcher_wait_cv, 1900 &dp->link_watcher_lock); 1901 } 1902 mutex_exit(&dp->link_watcher_lock); 1903 1904 if (dp->link_watcher_stop) { 1905 break; 1906 } 1907 1908 /* we block callbacks from disconnect/suspend and restart */ 1909 tx_sched = usbgem_mii_link_check(dp, 1910 &old_mii_state, &new_mii_state); 1911 1912 /* 1913 * gld v2 notifier functions are not able to 1914 * be called with any locks in this layer. 1915 */ 1916 if (tx_sched) { 1917 /* kick potentially stopped downstream */ 1918 mac_tx_update(dp->mh); 1919 } 1920 1921 if (old_mii_state != new_mii_state) { 1922 /* notify new mii link state */ 1923 if (new_mii_state == MII_STATE_LINKUP) { 1924 dp->linkup_delay = 0; 1925 USBGEM_LINKUP(dp); 1926 } else if (dp->linkup_delay <= 0) { 1927 USBGEM_LINKDOWN(dp); 1928 } 1929 } else if (dp->linkup_delay < 0) { 1930 /* first linkup timeout */ 1931 dp->linkup_delay = 0; 1932 USBGEM_LINKDOWN(dp); 1933 } 1934 } 1935 1936 thread_exit(); 1937 } 1938 1939 void 1940 usbgem_mii_update_link(struct usbgem_dev *dp) 1941 { 1942 cv_signal(&dp->link_watcher_wait_cv); 1943 } 1944 1945 int 1946 usbgem_mii_probe_default(struct usbgem_dev *dp) 1947 { 1948 int phy; 1949 uint16_t status; 1950 uint16_t xstatus; 1951 int err; 1952 uint16_t adv; 1953 uint16_t adv_org; 1954 1955 DPRINTF(3, (CE_CONT, "!%s: %s: called", dp->name, __func__)); 1956 1957 /* 1958 * Scan PHY 1959 */ 1960 dp->mii_status = 0; 1961 1962 /* Try default phy first */ 1963 if (dp->mii_phy_addr) { 1964 status = usbgem_mii_read(dp, MII_STATUS, &err); 1965 if (err != USB_SUCCESS) { 1966 goto usberr; 1967 } 1968 if (status != 0xffff && status != 0x0000) { 1969 goto PHY_found; 1970 } 1971 1972 if (dp->mii_phy_addr < 0) { 1973 cmn_err(CE_NOTE, 1974 "!%s: failed to probe default internal and/or non-MII PHY", 1975 dp->name); 1976 return (USB_FAILURE); 1977 } 1978 1979 cmn_err(CE_NOTE, 1980 "!%s: failed to probe default MII PHY at %d", 1981 dp->name, dp->mii_phy_addr); 1982 } 1983 1984 /* Try all possible address */ 1985 for (phy = dp->ugc.usbgc_mii_addr_min; phy < 32; phy++) { 1986 dp->mii_phy_addr = phy; 1987 status = usbgem_mii_read(dp, MII_STATUS, &err); 1988 if (err != USB_SUCCESS) { 1989 DPRINTF(0, (CE_CONT, 1990 "!%s: %s: mii_read(status) failed", 1991 dp->name, __func__)); 1992 goto usberr; 1993 } 1994 1995 if (status != 0xffff && status != 0x0000) { 1996 usbgem_mii_write(dp, MII_CONTROL, 0, &err); 1997 if (err != USB_SUCCESS) { 1998 DPRINTF(0, (CE_CONT, 1999 "!%s: %s: mii_write(control) failed", 2000 dp->name, __func__)); 2001 goto usberr; 2002 } 2003 goto PHY_found; 2004 } 2005 } 2006 for (phy = dp->ugc.usbgc_mii_addr_min; phy < 32; phy++) { 2007 dp->mii_phy_addr = phy; 2008 usbgem_mii_write(dp, MII_CONTROL, 0, &err); 2009 if (err != USB_SUCCESS) { 2010 DPRINTF(0, (CE_CONT, 2011 "!%s: %s: mii_write(control) failed", 2012 dp->name, __func__)); 2013 goto usberr; 2014 } 2015 status = usbgem_mii_read(dp, MII_STATUS, &err); 2016 if (err != USB_SUCCESS) { 2017 DPRINTF(0, (CE_CONT, 2018 "!%s: %s: mii_read(status) failed", 2019 dp->name, __func__)); 2020 goto usberr; 2021 } 2022 2023 if (status != 0xffff && status != 0) { 2024 goto PHY_found; 2025 } 2026 } 2027 2028 cmn_err(CE_NOTE, "!%s: no MII PHY found", dp->name); 2029 return (USB_FAILURE); 2030 2031 PHY_found: 2032 dp->mii_status = status; 2033 dp->mii_status_ro = ~status; 2034 dp->mii_phy_id = usbgem_mii_read(dp, MII_PHYIDH, &err) << 16; 2035 if (err != USB_SUCCESS) { 2036 DPRINTF(0, (CE_CONT, 2037 "!%s: %s: mii_read(PHYIDH) failed", 2038 dp->name, __func__)); 2039 goto usberr; 2040 } 2041 dp->mii_phy_id |= usbgem_mii_read(dp, MII_PHYIDL, &err); 2042 if (err != USB_SUCCESS) { 2043 DPRINTF(0, (CE_CONT, 2044 "!%s: %s: mii_read(PHYIDL) failed", 2045 dp->name, __func__)); 2046 goto usberr; 2047 } 2048 2049 if (dp->mii_phy_addr < 0) { 2050 cmn_err(CE_CONT, "!%s: using internal/non-MII PHY(0x%08x)", 2051 dp->name, dp->mii_phy_id); 2052 } else { 2053 cmn_err(CE_CONT, "!%s: MII PHY (0x%08x) found at %d", 2054 dp->name, dp->mii_phy_id, dp->mii_phy_addr); 2055 } 2056 2057 cmn_err(CE_CONT, 2058 "!%s: PHY control:%b, status:%b, advert:%b, lpar:%b, exp:%b", 2059 dp->name, 2060 usbgem_mii_read(dp, MII_CONTROL, &err), MII_CONTROL_BITS, 2061 status, MII_STATUS_BITS, 2062 usbgem_mii_read(dp, MII_AN_ADVERT, &err), MII_ABILITY_BITS, 2063 usbgem_mii_read(dp, MII_AN_LPABLE, &err), MII_ABILITY_BITS, 2064 usbgem_mii_read(dp, MII_AN_EXPANSION, &err), MII_AN_EXP_BITS); 2065 2066 dp->mii_xstatus = 0; 2067 if (status & MII_STATUS_XSTATUS) { 2068 dp->mii_xstatus = usbgem_mii_read(dp, MII_XSTATUS, &err); 2069 2070 cmn_err(CE_CONT, "!%s: xstatus:%b", 2071 dp->name, dp->mii_xstatus, MII_XSTATUS_BITS); 2072 } 2073 dp->mii_xstatus_ro = ~dp->mii_xstatus; 2074 2075 /* check if the phy can advertize pause abilities */ 2076 adv_org = usbgem_mii_read(dp, MII_AN_ADVERT, &err); 2077 if (err != USB_SUCCESS) { 2078 goto usberr; 2079 } 2080 2081 usbgem_mii_write(dp, MII_AN_ADVERT, 2082 MII_ABILITY_PAUSE | MII_ABILITY_ASM_DIR, &err); 2083 if (err != USB_SUCCESS) { 2084 goto usberr; 2085 } 2086 2087 adv = usbgem_mii_read(dp, MII_AN_ADVERT, &err); 2088 if (err != USB_SUCCESS) { 2089 goto usberr; 2090 } 2091 2092 if ((adv & MII_ABILITY_PAUSE) == 0) { 2093 dp->ugc.usbgc_flow_control &= ~1; 2094 } 2095 2096 if ((adv & MII_ABILITY_ASM_DIR) == 0) { 2097 dp->ugc.usbgc_flow_control &= ~2; 2098 } 2099 2100 usbgem_mii_write(dp, MII_AN_ADVERT, adv_org, &err); 2101 if (err != USB_SUCCESS) { 2102 goto usberr; 2103 } 2104 return (USB_SUCCESS); 2105 2106 usberr: 2107 return (USB_FAILURE); 2108 } 2109 2110 int 2111 usbgem_mii_init_default(struct usbgem_dev *dp) 2112 { 2113 /* ENPTY */ 2114 return (USB_SUCCESS); 2115 } 2116 2117 static int 2118 usbgem_mii_start(struct usbgem_dev *dp) 2119 { 2120 int err; 2121 kthread_t *lwth; 2122 2123 DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__)); 2124 2125 /* make a first call of usbgem_mii_link_check() */ 2126 dp->link_watcher_stop = 0; 2127 dp->mii_state = MII_STATE_UNKNOWN; 2128 dp->mii_interval = drv_usectohz(1000*1000); /* 1sec */ 2129 dp->mii_last_check = ddi_get_lbolt(); 2130 dp->linkup_delay = 600 * drv_usectohz(1000*1000); /* 10 minutes */ 2131 2132 lwth = thread_create(NULL, 0, usbgem_mii_link_watcher, dp, 0, &p0, 2133 TS_RUN, minclsyspri); 2134 if (lwth == NULL) { 2135 cmn_err(CE_WARN, 2136 "!%s: %s: failed to create a link watcher thread", 2137 dp->name, __func__); 2138 return (USB_FAILURE); 2139 } 2140 dp->link_watcher_did = lwth->t_did; 2141 2142 return (USB_SUCCESS); 2143 } 2144 2145 static void 2146 usbgem_mii_stop(struct usbgem_dev *dp) 2147 { 2148 DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__)); 2149 2150 /* Ensure timer routine stopped */ 2151 dp->link_watcher_stop = 1; 2152 cv_signal(&dp->link_watcher_wait_cv); 2153 thread_join(dp->link_watcher_did); 2154 } 2155 2156 /* ============================================================== */ 2157 /* 2158 * internal mac register operation interface 2159 */ 2160 /* ============================================================== */ 2161 /* 2162 * usbgem_mac_init: cold start 2163 */ 2164 static int 2165 usbgem_mac_init(struct usbgem_dev *dp) 2166 { 2167 int err; 2168 2169 DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__)); 2170 2171 if (dp->mac_state == MAC_STATE_DISCONNECTED) { 2172 /* pretend we succeeded */ 2173 return (USB_SUCCESS); 2174 } 2175 2176 ASSERT(dp->mac_state == MAC_STATE_STOPPED); 2177 2178 /* reset fatal error timestamp */ 2179 dp->fatal_error = (clock_t)0; 2180 2181 /* reset tx side state */ 2182 mutex_enter(&dp->txlock); 2183 dp->tx_busy_cnt = 0; 2184 dp->tx_max_packets = dp->ugc.usbgc_tx_list_max; 2185 mutex_exit(&dp->txlock); 2186 2187 /* reset rx side state */ 2188 mutex_enter(&dp->rxlock); 2189 dp->rx_busy_cnt = 0; 2190 mutex_exit(&dp->rxlock); 2191 2192 err = usbgem_hal_init_chip(dp); 2193 if (err == USB_SUCCESS) { 2194 dp->mac_state = MAC_STATE_INITIALIZED; 2195 } 2196 2197 return (err); 2198 } 2199 2200 /* 2201 * usbgem_mac_start: warm start 2202 */ 2203 static int 2204 usbgem_mac_start(struct usbgem_dev *dp) 2205 { 2206 int err; 2207 int i; 2208 usb_flags_t flags = 0; 2209 usb_intr_req_t *req; 2210 #ifdef USBGEM_DEBUG_LEVEL 2211 usb_pipe_state_t p_state; 2212 #endif 2213 DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__)); 2214 2215 if (dp->mac_state == MAC_STATE_DISCONNECTED) { 2216 /* do nothing but don't return failure */ 2217 return (USB_SUCCESS); 2218 } 2219 2220 if (dp->mac_state != MAC_STATE_INITIALIZED) { 2221 /* don't return failer */ 2222 DPRINTF(0, (CE_CONT, 2223 "!%s: %s: mac_state(%d) is not MAC_STATE_INITIALIZED", 2224 dp->name, __func__, dp->mac_state)); 2225 goto x; 2226 } 2227 2228 dp->mac_state = MAC_STATE_ONLINE; 2229 2230 if (usbgem_hal_start_chip(dp) != USB_SUCCESS) { 2231 cmn_err(CE_NOTE, 2232 "!%s: %s: usb error was detected during start_chip", 2233 dp->name, __func__); 2234 goto x; 2235 } 2236 2237 #ifdef USBGEM_DEBUG_LEVEL 2238 usb_pipe_get_state(dp->intr_pipe, &p_state, 0); 2239 ASSERT(p_state == USB_PIPE_STATE_IDLE); 2240 #endif /* USBGEM_DEBUG_LEVEL */ 2241 2242 if (dp->ugc.usbgc_interrupt && dp->intr_pipe) { 2243 2244 /* make a request for interrupt */ 2245 2246 req = usb_alloc_intr_req(dp->dip, 0, USB_FLAGS_SLEEP); 2247 if (req == NULL) { 2248 cmn_err(CE_WARN, "!%s: %s: failed to allocate intreq", 2249 dp->name, __func__); 2250 goto x; 2251 } 2252 req->intr_data = NULL; 2253 req->intr_client_private = (usb_opaque_t)dp; 2254 req->intr_timeout = 0; 2255 req->intr_attributes = 2256 USB_ATTRS_SHORT_XFER_OK | USB_ATTRS_AUTOCLEARING; 2257 req->intr_len = dp->ep_intr->wMaxPacketSize; 2258 req->intr_cb = usbgem_intr_cb; 2259 req->intr_exc_cb = usbgem_intr_cb; 2260 req->intr_completion_reason = 0; 2261 req->intr_cb_flags = 0; 2262 2263 err = usb_pipe_intr_xfer(dp->intr_pipe, req, flags); 2264 if (err != USB_SUCCESS) { 2265 cmn_err(CE_WARN, 2266 "%s: err:%d failed to start polling of intr pipe", 2267 dp->name, err); 2268 goto x; 2269 } 2270 } 2271 2272 /* kick to receive the first packet */ 2273 if (usbgem_init_rx_buf(dp) != USB_SUCCESS) { 2274 goto err_stop_intr; 2275 } 2276 dp->rx_active = B_TRUE; 2277 2278 return (USB_SUCCESS); 2279 2280 err_stop_intr: 2281 /* stop the interrupt pipe */ 2282 DPRINTF(0, (CE_CONT, "!%s: %s: FAULURE", dp->name, __func__)); 2283 if (dp->ugc.usbgc_interrupt && dp->intr_pipe) { 2284 usb_pipe_stop_intr_polling(dp->intr_pipe, USB_FLAGS_SLEEP); 2285 } 2286 x: 2287 ASSERT(dp->mac_state == MAC_STATE_ONLINE); 2288 /* we use another flag to indicate error state. */ 2289 if (dp->fatal_error == (clock_t)0) { 2290 dp->fatal_error = usbgem_timestamp_nz(); 2291 } 2292 return (USB_FAILURE); 2293 } 2294 2295 static int 2296 usbgem_mac_stop(struct usbgem_dev *dp, int new_state, boolean_t graceful) 2297 { 2298 DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__)); 2299 2300 /* 2301 * we must have writer lock for dev_state_lock 2302 */ 2303 ASSERT(new_state == MAC_STATE_STOPPED || 2304 new_state == MAC_STATE_DISCONNECTED); 2305 2306 /* stop polling interrupt pipe */ 2307 if (dp->ugc.usbgc_interrupt && dp->intr_pipe) { 2308 usb_pipe_stop_intr_polling(dp->intr_pipe, USB_FLAGS_SLEEP); 2309 } 2310 2311 if (new_state == MAC_STATE_STOPPED || graceful) { 2312 /* stop the nic hardware completely */ 2313 if (usbgem_hal_stop_chip(dp) != USB_SUCCESS) { 2314 (void) usbgem_hal_reset_chip(dp); 2315 } 2316 } 2317 2318 /* stop preparing new rx packets and sending new packets */ 2319 dp->mac_state = new_state; 2320 2321 /* other processors must get mac_state correctly after here */ 2322 membar_producer(); 2323 2324 /* cancel all requests we have sent */ 2325 usb_pipe_reset(dp->dip, dp->bulkin_pipe, USB_FLAGS_SLEEP, NULL, 0); 2326 usb_pipe_reset(dp->dip, dp->bulkout_pipe, USB_FLAGS_SLEEP, NULL, 0); 2327 2328 DPRINTF(0, (CE_CONT, 2329 "!%s: %s: rx_busy_cnt:%d tx_busy_cnt:%d", 2330 dp->name, __func__, dp->rx_busy_cnt, dp->tx_busy_cnt)); 2331 2332 /* 2333 * Here all rx packets has been cancelled and their call back 2334 * function has been exeuted, because we called usb_pipe_reset 2335 * synchronously. 2336 * So actually we just ensure rx_busy_cnt == 0. 2337 */ 2338 mutex_enter(&dp->rxlock); 2339 while (dp->rx_busy_cnt > 0) { 2340 cv_wait(&dp->rx_drain_cv, &dp->rxlock); 2341 } 2342 mutex_exit(&dp->rxlock); 2343 2344 DPRINTF(0, (CE_CONT, "!%s: %s: rx_busy_cnt is %d now", 2345 dp->name, __func__, dp->rx_busy_cnt)); 2346 2347 mutex_enter(&dp->txlock); 2348 while (dp->tx_busy_cnt > 0) { 2349 cv_wait(&dp->tx_drain_cv, &dp->txlock); 2350 } 2351 mutex_exit(&dp->txlock); 2352 2353 DPRINTF(0, (CE_CONT, "!%s: %s: tx_busy_cnt is %d now", 2354 dp->name, __func__, dp->tx_busy_cnt)); 2355 2356 return (USB_SUCCESS); 2357 } 2358 2359 static int 2360 usbgem_add_multicast(struct usbgem_dev *dp, const uint8_t *ep) 2361 { 2362 int cnt; 2363 int err; 2364 2365 DPRINTF(1, (CE_CONT, "!%s: %s: called", dp->name, __func__)); 2366 2367 sema_p(&dp->rxfilter_lock); 2368 if (dp->mc_count_req++ < USBGEM_MAXMC) { 2369 /* append the new address at the end of the mclist */ 2370 cnt = dp->mc_count; 2371 bcopy(ep, dp->mc_list[cnt].addr.ether_addr_octet, 2372 ETHERADDRL); 2373 if (dp->ugc.usbgc_multicast_hash) { 2374 dp->mc_list[cnt].hash = 2375 (*dp->ugc.usbgc_multicast_hash)(dp, ep); 2376 } 2377 dp->mc_count = cnt + 1; 2378 } 2379 2380 if (dp->mc_count_req != dp->mc_count) { 2381 /* multicast address list overflow */ 2382 dp->rxmode |= RXMODE_MULTI_OVF; 2383 } else { 2384 dp->rxmode &= ~RXMODE_MULTI_OVF; 2385 } 2386 2387 if (dp->mac_state != MAC_STATE_DISCONNECTED) { 2388 /* tell new multicast list to the hardware */ 2389 err = usbgem_hal_set_rx_filter(dp); 2390 } 2391 sema_v(&dp->rxfilter_lock); 2392 2393 return (err); 2394 } 2395 2396 static int 2397 usbgem_remove_multicast(struct usbgem_dev *dp, const uint8_t *ep) 2398 { 2399 size_t len; 2400 int i; 2401 int cnt; 2402 int err; 2403 2404 DPRINTF(1, (CE_CONT, "!%s: %s: called", dp->name, __func__)); 2405 2406 sema_p(&dp->rxfilter_lock); 2407 dp->mc_count_req--; 2408 cnt = dp->mc_count; 2409 for (i = 0; i < cnt; i++) { 2410 if (bcmp(ep, &dp->mc_list[i].addr, ETHERADDRL)) { 2411 continue; 2412 } 2413 /* shrink the mclist by copying forward */ 2414 len = (cnt - (i + 1)) * sizeof (*dp->mc_list); 2415 if (len > 0) { 2416 bcopy(&dp->mc_list[i+1], &dp->mc_list[i], len); 2417 } 2418 dp->mc_count--; 2419 break; 2420 } 2421 2422 if (dp->mc_count_req != dp->mc_count) { 2423 /* multicast address list overflow */ 2424 dp->rxmode |= RXMODE_MULTI_OVF; 2425 } else { 2426 dp->rxmode &= ~RXMODE_MULTI_OVF; 2427 } 2428 2429 if (dp->mac_state != MAC_STATE_DISCONNECTED) { 2430 err = usbgem_hal_set_rx_filter(dp); 2431 } 2432 sema_v(&dp->rxfilter_lock); 2433 2434 return (err); 2435 } 2436 2437 2438 /* ============================================================== */ 2439 /* 2440 * ioctl 2441 */ 2442 /* ============================================================== */ 2443 enum ioc_reply { 2444 IOC_INVAL = -1, /* bad, NAK with EINVAL */ 2445 IOC_DONE, /* OK, reply sent */ 2446 IOC_ACK, /* OK, just send ACK */ 2447 IOC_REPLY, /* OK, just send reply */ 2448 IOC_RESTART_ACK, /* OK, restart & ACK */ 2449 IOC_RESTART_REPLY /* OK, restart & reply */ 2450 }; 2451 2452 2453 static int 2454 usbgem_get_def_val(struct usbgem_dev *dp, mac_prop_id_t pr_num, 2455 uint_t pr_valsize, void *pr_val) 2456 { 2457 link_flowctrl_t fl; 2458 int err = 0; 2459 2460 ASSERT(pr_valsize > 0); 2461 switch (pr_num) { 2462 case MAC_PROP_AUTONEG: 2463 *(uint8_t *)pr_val = 2464 BOOLEAN(dp->mii_status & MII_STATUS_CANAUTONEG); 2465 break; 2466 2467 case MAC_PROP_FLOWCTRL: 2468 if (pr_valsize < sizeof (link_flowctrl_t)) { 2469 return (EINVAL); 2470 } 2471 switch (dp->ugc.usbgc_flow_control) { 2472 case FLOW_CONTROL_NONE: 2473 fl = LINK_FLOWCTRL_NONE; 2474 break; 2475 case FLOW_CONTROL_SYMMETRIC: 2476 fl = LINK_FLOWCTRL_BI; 2477 break; 2478 case FLOW_CONTROL_TX_PAUSE: 2479 fl = LINK_FLOWCTRL_TX; 2480 break; 2481 case FLOW_CONTROL_RX_PAUSE: 2482 fl = LINK_FLOWCTRL_RX; 2483 break; 2484 } 2485 bcopy(&fl, pr_val, sizeof (fl)); 2486 break; 2487 2488 case MAC_PROP_ADV_1000FDX_CAP: 2489 case MAC_PROP_EN_1000FDX_CAP: 2490 *(uint8_t *)pr_val = 2491 (dp->mii_xstatus & MII_XSTATUS_1000BASET_FD) || 2492 (dp->mii_xstatus & MII_XSTATUS_1000BASEX_FD); 2493 break; 2494 2495 case MAC_PROP_ADV_1000HDX_CAP: 2496 case MAC_PROP_EN_1000HDX_CAP: 2497 *(uint8_t *)pr_val = 2498 (dp->mii_xstatus & MII_XSTATUS_1000BASET) || 2499 (dp->mii_xstatus & MII_XSTATUS_1000BASEX); 2500 break; 2501 2502 case MAC_PROP_ADV_100T4_CAP: 2503 case MAC_PROP_EN_100T4_CAP: 2504 *(uint8_t *)pr_val = 2505 BOOLEAN(dp->mii_status & MII_STATUS_100_BASE_T4); 2506 break; 2507 2508 case MAC_PROP_ADV_100FDX_CAP: 2509 case MAC_PROP_EN_100FDX_CAP: 2510 *(uint8_t *)pr_val = 2511 BOOLEAN(dp->mii_status & MII_STATUS_100_BASEX_FD); 2512 break; 2513 2514 case MAC_PROP_ADV_100HDX_CAP: 2515 case MAC_PROP_EN_100HDX_CAP: 2516 *(uint8_t *)pr_val = 2517 BOOLEAN(dp->mii_status & MII_STATUS_100_BASEX); 2518 break; 2519 2520 case MAC_PROP_ADV_10FDX_CAP: 2521 case MAC_PROP_EN_10FDX_CAP: 2522 *(uint8_t *)pr_val = 2523 BOOLEAN(dp->mii_status & MII_STATUS_10_FD); 2524 break; 2525 2526 case MAC_PROP_ADV_10HDX_CAP: 2527 case MAC_PROP_EN_10HDX_CAP: 2528 *(uint8_t *)pr_val = 2529 BOOLEAN(dp->mii_status & MII_STATUS_10); 2530 break; 2531 2532 default: 2533 err = ENOTSUP; 2534 break; 2535 } 2536 return (err); 2537 } 2538 2539 static void 2540 usbgem_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t pr_num, 2541 mac_prop_info_handle_t prh) 2542 { 2543 struct usbgem_dev *dp = arg; 2544 link_flowctrl_t fl; 2545 2546 /* 2547 * By default permissions are read/write unless specified 2548 * otherwise by the driver. 2549 */ 2550 2551 switch (pr_num) { 2552 case MAC_PROP_DUPLEX: 2553 case MAC_PROP_SPEED: 2554 case MAC_PROP_STATUS: 2555 case MAC_PROP_ADV_1000FDX_CAP: 2556 case MAC_PROP_ADV_1000HDX_CAP: 2557 case MAC_PROP_ADV_100FDX_CAP: 2558 case MAC_PROP_ADV_100HDX_CAP: 2559 case MAC_PROP_ADV_10FDX_CAP: 2560 case MAC_PROP_ADV_10HDX_CAP: 2561 case MAC_PROP_ADV_100T4_CAP: 2562 case MAC_PROP_EN_100T4_CAP: 2563 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 2564 break; 2565 2566 case MAC_PROP_EN_1000FDX_CAP: 2567 if ((dp->mii_xstatus_ro & MII_XSTATUS_1000BASET_FD) == 0) { 2568 mac_prop_info_set_default_uint8(prh, 2569 BOOLEAN( 2570 dp->mii_xstatus & MII_XSTATUS_1000BASET_FD)); 2571 } else if ((dp->mii_xstatus_ro & MII_XSTATUS_1000BASEX_FD) 2572 == 0) { 2573 mac_prop_info_set_default_uint8(prh, 2574 BOOLEAN( 2575 dp->mii_xstatus & MII_XSTATUS_1000BASEX_FD)); 2576 } else { 2577 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 2578 } 2579 break; 2580 2581 case MAC_PROP_EN_1000HDX_CAP: 2582 if ((dp->mii_xstatus_ro & MII_XSTATUS_1000BASET) == 0) { 2583 mac_prop_info_set_default_uint8(prh, 2584 BOOLEAN( 2585 dp->mii_xstatus & MII_XSTATUS_1000BASET)); 2586 } else if ((dp->mii_xstatus_ro & MII_XSTATUS_1000BASEX) == 0) { 2587 mac_prop_info_set_default_uint8(prh, 2588 BOOLEAN( 2589 dp->mii_xstatus & MII_XSTATUS_1000BASEX)); 2590 } else { 2591 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 2592 } 2593 break; 2594 2595 case MAC_PROP_EN_100FDX_CAP: 2596 if ((dp->mii_status_ro & MII_STATUS_100_BASEX_FD) == 0) { 2597 mac_prop_info_set_default_uint8(prh, 2598 BOOLEAN(dp->mii_status & MII_STATUS_100_BASEX_FD)); 2599 } else { 2600 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 2601 } 2602 break; 2603 2604 case MAC_PROP_EN_100HDX_CAP: 2605 if ((dp->mii_status_ro & MII_STATUS_100_BASEX) == 0) { 2606 mac_prop_info_set_default_uint8(prh, 2607 BOOLEAN(dp->mii_status & MII_STATUS_100_BASEX)); 2608 } else { 2609 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 2610 } 2611 break; 2612 2613 case MAC_PROP_EN_10FDX_CAP: 2614 if ((dp->mii_status_ro & MII_STATUS_10_FD) == 0) { 2615 mac_prop_info_set_default_uint8(prh, 2616 BOOLEAN(dp->mii_status & MII_STATUS_10_FD)); 2617 } else { 2618 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 2619 } 2620 break; 2621 2622 case MAC_PROP_EN_10HDX_CAP: 2623 if ((dp->mii_status_ro & MII_STATUS_10) == 0) { 2624 mac_prop_info_set_default_uint8(prh, 2625 BOOLEAN(dp->mii_status & MII_STATUS_10)); 2626 } else { 2627 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 2628 } 2629 break; 2630 2631 case MAC_PROP_AUTONEG: 2632 if ((dp->mii_status_ro & MII_STATUS_CANAUTONEG) == 0) { 2633 mac_prop_info_set_default_uint8(prh, 2634 BOOLEAN(dp->mii_status & MII_STATUS_CANAUTONEG)); 2635 } else { 2636 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 2637 } 2638 break; 2639 2640 case MAC_PROP_FLOWCTRL: 2641 switch (dp->ugc.usbgc_flow_control) { 2642 case FLOW_CONTROL_NONE: 2643 fl = LINK_FLOWCTRL_NONE; 2644 break; 2645 case FLOW_CONTROL_SYMMETRIC: 2646 fl = LINK_FLOWCTRL_BI; 2647 break; 2648 case FLOW_CONTROL_TX_PAUSE: 2649 fl = LINK_FLOWCTRL_TX; 2650 break; 2651 case FLOW_CONTROL_RX_PAUSE: 2652 fl = LINK_FLOWCTRL_RX; 2653 break; 2654 } 2655 mac_prop_info_set_default_link_flowctrl(prh, fl); 2656 break; 2657 2658 case MAC_PROP_MTU: 2659 mac_prop_info_set_range_uint32(prh, 2660 dp->ugc.usbgc_min_mtu, dp->ugc.usbgc_max_mtu); 2661 break; 2662 2663 case MAC_PROP_PRIVATE: 2664 break; 2665 } 2666 } 2667 2668 static int 2669 usbgem_m_setprop(void *arg, const char *pr_name, mac_prop_id_t pr_num, 2670 uint_t pr_valsize, const void *pr_val) 2671 { 2672 struct usbgem_dev *dp = arg; 2673 int err = 0; 2674 boolean_t update = B_FALSE; 2675 link_flowctrl_t flowctrl; 2676 uint32_t cur_mtu, new_mtu; 2677 2678 rw_enter(&dp->dev_state_lock, RW_WRITER); 2679 switch (pr_num) { 2680 case MAC_PROP_EN_1000FDX_CAP: 2681 if ((dp->mii_xstatus_ro & MII_XSTATUS_1000BASET_FD) == 0 || 2682 (dp->mii_xstatus_ro & MII_XSTATUS_1000BASEX_FD) == 0) { 2683 if (dp->anadv_1000fdx != *(uint8_t *)pr_val) { 2684 dp->anadv_1000fdx = *(uint8_t *)pr_val; 2685 update = B_TRUE; 2686 } 2687 } else { 2688 err = ENOTSUP; 2689 } 2690 break; 2691 2692 case MAC_PROP_EN_1000HDX_CAP: 2693 if ((dp->mii_xstatus_ro & MII_XSTATUS_1000BASET) == 0 || 2694 (dp->mii_xstatus_ro & MII_XSTATUS_1000BASEX) == 0) { 2695 if (dp->anadv_1000hdx != *(uint8_t *)pr_val) { 2696 dp->anadv_1000hdx = *(uint8_t *)pr_val; 2697 update = B_TRUE; 2698 } 2699 } else { 2700 err = ENOTSUP; 2701 } 2702 break; 2703 2704 case MAC_PROP_EN_100FDX_CAP: 2705 if ((dp->mii_status_ro & MII_STATUS_100_BASEX_FD) == 0) { 2706 if (dp->anadv_100fdx != *(uint8_t *)pr_val) { 2707 dp->anadv_100fdx = *(uint8_t *)pr_val; 2708 update = B_TRUE; 2709 } 2710 } else { 2711 err = ENOTSUP; 2712 } 2713 break; 2714 2715 case MAC_PROP_EN_100HDX_CAP: 2716 if ((dp->mii_status_ro & MII_STATUS_100_BASEX) == 0) { 2717 if (dp->anadv_100hdx != *(uint8_t *)pr_val) { 2718 dp->anadv_100hdx = *(uint8_t *)pr_val; 2719 update = B_TRUE; 2720 } 2721 } else { 2722 err = ENOTSUP; 2723 } 2724 break; 2725 2726 case MAC_PROP_EN_10FDX_CAP: 2727 if ((dp->mii_status_ro & MII_STATUS_10_FD) == 0) { 2728 if (dp->anadv_10fdx != *(uint8_t *)pr_val) { 2729 dp->anadv_10fdx = *(uint8_t *)pr_val; 2730 update = B_TRUE; 2731 } 2732 } else { 2733 err = ENOTSUP; 2734 } 2735 break; 2736 2737 case MAC_PROP_EN_10HDX_CAP: 2738 if ((dp->mii_status_ro & MII_STATUS_10_FD) == 0) { 2739 if (dp->anadv_10hdx != *(uint8_t *)pr_val) { 2740 dp->anadv_10hdx = *(uint8_t *)pr_val; 2741 update = B_TRUE; 2742 } 2743 } else { 2744 err = ENOTSUP; 2745 } 2746 break; 2747 2748 case MAC_PROP_AUTONEG: 2749 if ((dp->mii_status_ro & MII_STATUS_CANAUTONEG) == 0) { 2750 if (dp->anadv_autoneg != *(uint8_t *)pr_val) { 2751 dp->anadv_autoneg = *(uint8_t *)pr_val; 2752 update = B_TRUE; 2753 } 2754 } else { 2755 err = ENOTSUP; 2756 } 2757 break; 2758 2759 case MAC_PROP_FLOWCTRL: 2760 bcopy(pr_val, &flowctrl, sizeof (flowctrl)); 2761 2762 switch (flowctrl) { 2763 default: 2764 err = EINVAL; 2765 break; 2766 2767 case LINK_FLOWCTRL_NONE: 2768 if (dp->flow_control != FLOW_CONTROL_NONE) { 2769 dp->flow_control = FLOW_CONTROL_NONE; 2770 update = B_TRUE; 2771 } 2772 break; 2773 2774 case LINK_FLOWCTRL_RX: 2775 if (dp->flow_control != FLOW_CONTROL_RX_PAUSE) { 2776 dp->flow_control = FLOW_CONTROL_RX_PAUSE; 2777 update = B_TRUE; 2778 } 2779 break; 2780 2781 case LINK_FLOWCTRL_TX: 2782 if (dp->flow_control != FLOW_CONTROL_TX_PAUSE) { 2783 dp->flow_control = FLOW_CONTROL_TX_PAUSE; 2784 update = B_TRUE; 2785 } 2786 break; 2787 2788 case LINK_FLOWCTRL_BI: 2789 if (dp->flow_control != FLOW_CONTROL_SYMMETRIC) { 2790 dp->flow_control = FLOW_CONTROL_SYMMETRIC; 2791 update = B_TRUE; 2792 } 2793 break; 2794 } 2795 break; 2796 2797 case MAC_PROP_ADV_1000FDX_CAP: 2798 case MAC_PROP_ADV_1000HDX_CAP: 2799 case MAC_PROP_ADV_100FDX_CAP: 2800 case MAC_PROP_ADV_100HDX_CAP: 2801 case MAC_PROP_ADV_10FDX_CAP: 2802 case MAC_PROP_ADV_10HDX_CAP: 2803 case MAC_PROP_STATUS: 2804 case MAC_PROP_SPEED: 2805 case MAC_PROP_DUPLEX: 2806 err = ENOTSUP; /* read-only prop. Can't set this. */ 2807 break; 2808 2809 case MAC_PROP_MTU: 2810 bcopy(pr_val, &new_mtu, sizeof (new_mtu)); 2811 if (new_mtu != dp->mtu) { 2812 err = EINVAL; 2813 } 2814 break; 2815 2816 case MAC_PROP_PRIVATE: 2817 err = ENOTSUP; 2818 break; 2819 2820 default: 2821 err = ENOTSUP; 2822 break; 2823 } 2824 2825 if (update) { 2826 /* sync with PHY */ 2827 usbgem_choose_forcedmode(dp); 2828 dp->mii_state = MII_STATE_UNKNOWN; 2829 cv_signal(&dp->link_watcher_wait_cv); 2830 } 2831 rw_exit(&dp->dev_state_lock); 2832 return (err); 2833 } 2834 2835 static int 2836 usbgem_m_getprop(void *arg, const char *pr_name, mac_prop_id_t pr_num, 2837 uint_t pr_valsize, void *pr_val) 2838 { 2839 struct usbgem_dev *dp = arg; 2840 int err = 0; 2841 link_flowctrl_t flowctrl; 2842 uint64_t tmp = 0; 2843 2844 if (pr_valsize == 0) { 2845 return (EINVAL); 2846 } 2847 2848 bzero(pr_val, pr_valsize); 2849 rw_enter(&dp->dev_state_lock, RW_READER); 2850 switch (pr_num) { 2851 case MAC_PROP_DUPLEX: 2852 if (pr_valsize >= sizeof (link_duplex_t)) { 2853 if (dp->mii_state != MII_STATE_LINKUP) { 2854 *(link_duplex_t *)pr_val = LINK_DUPLEX_UNKNOWN; 2855 } else if (dp->full_duplex) { 2856 *(link_duplex_t *)pr_val = LINK_DUPLEX_FULL; 2857 } else { 2858 *(link_duplex_t *)pr_val = LINK_DUPLEX_HALF; 2859 } 2860 } else { 2861 err = EINVAL; 2862 } 2863 break; 2864 case MAC_PROP_SPEED: 2865 if (pr_valsize >= sizeof (uint64_t)) { 2866 switch (dp->speed) { 2867 case USBGEM_SPD_1000: 2868 tmp = 1000000000; 2869 break; 2870 case USBGEM_SPD_100: 2871 tmp = 100000000; 2872 break; 2873 case USBGEM_SPD_10: 2874 tmp = 10000000; 2875 break; 2876 default: 2877 tmp = 0; 2878 } 2879 bcopy(&tmp, pr_val, sizeof (tmp)); 2880 } else { 2881 err = EINVAL; 2882 } 2883 break; 2884 2885 case MAC_PROP_AUTONEG: 2886 *(uint8_t *)pr_val = dp->anadv_autoneg; 2887 break; 2888 2889 case MAC_PROP_FLOWCTRL: 2890 if (pr_valsize >= sizeof (link_flowctrl_t)) { 2891 switch (dp->flow_control) { 2892 case FLOW_CONTROL_NONE: 2893 flowctrl = LINK_FLOWCTRL_NONE; 2894 break; 2895 case FLOW_CONTROL_RX_PAUSE: 2896 flowctrl = LINK_FLOWCTRL_RX; 2897 break; 2898 case FLOW_CONTROL_TX_PAUSE: 2899 flowctrl = LINK_FLOWCTRL_TX; 2900 break; 2901 case FLOW_CONTROL_SYMMETRIC: 2902 flowctrl = LINK_FLOWCTRL_BI; 2903 break; 2904 } 2905 bcopy(&flowctrl, pr_val, sizeof (flowctrl)); 2906 } else { 2907 err = EINVAL; 2908 } 2909 break; 2910 2911 case MAC_PROP_ADV_1000FDX_CAP: 2912 case MAC_PROP_ADV_1000HDX_CAP: 2913 case MAC_PROP_ADV_100FDX_CAP: 2914 case MAC_PROP_ADV_100HDX_CAP: 2915 case MAC_PROP_ADV_10FDX_CAP: 2916 case MAC_PROP_ADV_10HDX_CAP: 2917 case MAC_PROP_ADV_100T4_CAP: 2918 usbgem_get_def_val(dp, pr_num, pr_valsize, pr_val); 2919 break; 2920 2921 case MAC_PROP_EN_1000FDX_CAP: 2922 *(uint8_t *)pr_val = dp->anadv_1000fdx; 2923 break; 2924 2925 case MAC_PROP_EN_1000HDX_CAP: 2926 *(uint8_t *)pr_val = dp->anadv_1000hdx; 2927 break; 2928 2929 case MAC_PROP_EN_100FDX_CAP: 2930 *(uint8_t *)pr_val = dp->anadv_100fdx; 2931 break; 2932 2933 case MAC_PROP_EN_100HDX_CAP: 2934 *(uint8_t *)pr_val = dp->anadv_100hdx; 2935 break; 2936 2937 case MAC_PROP_EN_10FDX_CAP: 2938 *(uint8_t *)pr_val = dp->anadv_10fdx; 2939 break; 2940 2941 case MAC_PROP_EN_10HDX_CAP: 2942 *(uint8_t *)pr_val = dp->anadv_10hdx; 2943 break; 2944 2945 case MAC_PROP_EN_100T4_CAP: 2946 *(uint8_t *)pr_val = dp->anadv_100t4; 2947 break; 2948 2949 case MAC_PROP_PRIVATE: 2950 err = ENOTSUP; 2951 break; 2952 2953 default: 2954 err = ENOTSUP; 2955 break; 2956 } 2957 2958 rw_exit(&dp->dev_state_lock); 2959 return (err); 2960 } 2961 2962 static void 2963 usbgem_mac_ioctl(struct usbgem_dev *dp, queue_t *wq, mblk_t *mp) 2964 { 2965 struct iocblk *iocp; 2966 enum ioc_reply status; 2967 2968 DPRINTF(1, (CE_CONT, "!%s: %s: called", dp->name, __func__)); 2969 2970 /* 2971 * Validate the command before bothering with the mutex ... 2972 */ 2973 iocp = (void *)mp->b_rptr; 2974 iocp->ioc_error = 0; 2975 2976 DPRINTF(1, (CE_CONT, "%s: %s cmd:0x%x", dp->name, __func__, 2977 iocp->ioc_cmd)); 2978 2979 miocnak(wq, mp, 0, EINVAL); 2980 } 2981 2982 static int 2983 usbgem_mac_xcvr_inuse(struct usbgem_dev *dp) 2984 { 2985 int val = XCVR_UNDEFINED; 2986 2987 if ((dp->mii_status & MII_STATUS_XSTATUS) == 0) { 2988 if (dp->mii_status & MII_STATUS_100_BASE_T4) { 2989 val = XCVR_100T4; 2990 } else if (dp->mii_status & 2991 (MII_STATUS_100_BASEX_FD | 2992 MII_STATUS_100_BASEX)) { 2993 val = XCVR_100X; 2994 } else if (dp->mii_status & 2995 (MII_STATUS_100_BASE_T2_FD | 2996 MII_STATUS_100_BASE_T2)) { 2997 val = XCVR_100T2; 2998 } else if (dp->mii_status & 2999 (MII_STATUS_10_FD | MII_STATUS_10)) { 3000 val = XCVR_10; 3001 } 3002 } else if (dp->mii_xstatus & 3003 (MII_XSTATUS_1000BASET_FD | MII_XSTATUS_1000BASET)) { 3004 val = XCVR_1000T; 3005 } else if (dp->mii_xstatus & 3006 (MII_XSTATUS_1000BASEX_FD | MII_XSTATUS_1000BASEX)) { 3007 val = XCVR_1000X; 3008 } 3009 3010 return (val); 3011 } 3012 3013 /* ============================================================== */ 3014 /* 3015 * GLDv3 interface 3016 */ 3017 /* ============================================================== */ 3018 static int usbgem_m_getstat(void *, uint_t, uint64_t *); 3019 static int usbgem_m_start(void *); 3020 static void usbgem_m_stop(void *); 3021 static int usbgem_m_setpromisc(void *, boolean_t); 3022 static int usbgem_m_multicst(void *, boolean_t, const uint8_t *); 3023 static int usbgem_m_unicst(void *, const uint8_t *); 3024 static mblk_t *usbgem_m_tx(void *, mblk_t *); 3025 static void usbgem_m_ioctl(void *, queue_t *, mblk_t *); 3026 static int usbgem_m_setprop(void *, const char *, mac_prop_id_t, 3027 uint_t, const void *); 3028 static int usbgem_m_getprop(void *, const char *, mac_prop_id_t, 3029 uint_t, void *); 3030 3031 static mac_callbacks_t gem_m_callbacks = { 3032 MC_IOCTL | MC_SETPROP | MC_GETPROP | MC_PROPINFO, 3033 usbgem_m_getstat, 3034 usbgem_m_start, 3035 usbgem_m_stop, 3036 usbgem_m_setpromisc, 3037 usbgem_m_multicst, 3038 usbgem_m_unicst, 3039 usbgem_m_tx, 3040 NULL, 3041 usbgem_m_ioctl, 3042 NULL, /* m_getcapab */ 3043 NULL, 3044 NULL, 3045 usbgem_m_setprop, 3046 usbgem_m_getprop, 3047 usbgem_m_propinfo, 3048 }; 3049 3050 static int 3051 usbgem_m_start(void *arg) 3052 { 3053 int ret; 3054 int err; 3055 struct usbgem_dev *dp = arg; 3056 3057 DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__)); 3058 3059 err = EIO; 3060 3061 rw_enter(&dp->dev_state_lock, RW_WRITER); 3062 dp->nic_state = NIC_STATE_ONLINE; 3063 3064 if (dp->mac_state == MAC_STATE_DISCONNECTED) { 3065 err = 0; 3066 goto x; 3067 } 3068 if (usbgem_mac_init(dp) != USB_SUCCESS) { 3069 goto x; 3070 } 3071 3072 /* initialize rx filter state */ 3073 sema_p(&dp->rxfilter_lock); 3074 dp->mc_count = 0; 3075 dp->mc_count_req = 0; 3076 3077 bcopy(dp->dev_addr.ether_addr_octet, 3078 dp->cur_addr.ether_addr_octet, ETHERADDRL); 3079 dp->rxmode |= RXMODE_ENABLE; 3080 3081 ret = usbgem_hal_set_rx_filter(dp); 3082 sema_v(&dp->rxfilter_lock); 3083 3084 if (ret != USB_SUCCESS) { 3085 goto x; 3086 } 3087 3088 if (dp->mii_state == MII_STATE_LINKUP) { 3089 /* setup media mode if the link have been up */ 3090 if (usbgem_hal_set_media(dp) != USB_SUCCESS) { 3091 goto x; 3092 } 3093 if (usbgem_mac_start(dp) != USB_SUCCESS) { 3094 goto x; 3095 } 3096 } 3097 3098 err = 0; 3099 x: 3100 rw_exit(&dp->dev_state_lock); 3101 return (err); 3102 } 3103 3104 static void 3105 usbgem_m_stop(void *arg) 3106 { 3107 struct usbgem_dev *dp = arg; 3108 3109 DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__)); 3110 3111 /* stop rx gracefully */ 3112 rw_enter(&dp->dev_state_lock, RW_READER); 3113 sema_p(&dp->rxfilter_lock); 3114 dp->rxmode &= ~RXMODE_ENABLE; 3115 3116 if (dp->mac_state != MAC_STATE_DISCONNECTED) { 3117 (void) usbgem_hal_set_rx_filter(dp); 3118 } 3119 sema_v(&dp->rxfilter_lock); 3120 rw_exit(&dp->dev_state_lock); 3121 3122 /* make the nic state inactive */ 3123 rw_enter(&dp->dev_state_lock, RW_WRITER); 3124 dp->nic_state = NIC_STATE_STOPPED; 3125 3126 /* stop mac completely */ 3127 if (dp->mac_state != MAC_STATE_DISCONNECTED) { 3128 (void) usbgem_mac_stop(dp, MAC_STATE_STOPPED, STOP_GRACEFUL); 3129 } 3130 rw_exit(&dp->dev_state_lock); 3131 } 3132 3133 static int 3134 usbgem_m_multicst(void *arg, boolean_t add, const uint8_t *ep) 3135 { 3136 int err; 3137 int ret; 3138 struct usbgem_dev *dp = arg; 3139 3140 DPRINTF(1, (CE_CONT, "!%s: %s: called", dp->name, __func__)); 3141 3142 rw_enter(&dp->dev_state_lock, RW_READER); 3143 if (add) { 3144 ret = usbgem_add_multicast(dp, ep); 3145 } else { 3146 ret = usbgem_remove_multicast(dp, ep); 3147 } 3148 rw_exit(&dp->dev_state_lock); 3149 3150 err = 0; 3151 if (ret != USB_SUCCESS) { 3152 err = EIO; 3153 } 3154 3155 return (err); 3156 } 3157 3158 static int 3159 usbgem_m_setpromisc(void *arg, boolean_t on) 3160 { 3161 int err; 3162 struct usbgem_dev *dp = arg; 3163 3164 DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__)); 3165 3166 rw_enter(&dp->dev_state_lock, RW_READER); 3167 3168 sema_p(&dp->rxfilter_lock); 3169 if (on) { 3170 dp->rxmode |= RXMODE_PROMISC; 3171 } else { 3172 dp->rxmode &= ~RXMODE_PROMISC; 3173 } 3174 3175 err = 0; 3176 if (dp->mac_state != MAC_STATE_DISCONNECTED) { 3177 if (usbgem_hal_set_rx_filter(dp) != USB_SUCCESS) { 3178 err = EIO; 3179 } 3180 } 3181 sema_v(&dp->rxfilter_lock); 3182 3183 rw_exit(&dp->dev_state_lock); 3184 3185 return (err); 3186 } 3187 3188 int 3189 usbgem_m_getstat(void *arg, uint_t stat, uint64_t *valp) 3190 { 3191 uint64_t val; 3192 struct usbgem_dev *dp = arg; 3193 struct usbgem_stats *gstp = &dp->stats; 3194 3195 DPRINTF(1, (CE_CONT, "!%s: %s: called", dp->name, __func__)); 3196 3197 rw_enter(&dp->dev_state_lock, RW_READER); 3198 if (dp->mac_state == MAC_STATE_DISCONNECTED) { 3199 rw_exit(&dp->dev_state_lock); 3200 return (0); 3201 } 3202 3203 (void) usbgem_hal_get_stats(dp); 3204 rw_exit(&dp->dev_state_lock); 3205 3206 switch (stat) { 3207 case MAC_STAT_IFSPEED: 3208 val = usbgem_speed_value[dp->speed] *1000000ull; 3209 break; 3210 3211 case MAC_STAT_MULTIRCV: 3212 val = gstp->rmcast; 3213 break; 3214 3215 case MAC_STAT_BRDCSTRCV: 3216 val = gstp->rbcast; 3217 break; 3218 3219 case MAC_STAT_MULTIXMT: 3220 val = gstp->omcast; 3221 break; 3222 3223 case MAC_STAT_BRDCSTXMT: 3224 val = gstp->obcast; 3225 break; 3226 3227 case MAC_STAT_NORCVBUF: 3228 val = gstp->norcvbuf + gstp->missed; 3229 break; 3230 3231 case MAC_STAT_IERRORS: 3232 val = gstp->errrcv; 3233 break; 3234 3235 case MAC_STAT_NOXMTBUF: 3236 val = gstp->noxmtbuf; 3237 break; 3238 3239 case MAC_STAT_OERRORS: 3240 val = gstp->errxmt; 3241 break; 3242 3243 case MAC_STAT_COLLISIONS: 3244 val = gstp->collisions; 3245 break; 3246 3247 case MAC_STAT_RBYTES: 3248 val = gstp->rbytes; 3249 break; 3250 3251 case MAC_STAT_IPACKETS: 3252 val = gstp->rpackets; 3253 break; 3254 3255 case MAC_STAT_OBYTES: 3256 val = gstp->obytes; 3257 break; 3258 3259 case MAC_STAT_OPACKETS: 3260 val = gstp->opackets; 3261 break; 3262 3263 case MAC_STAT_UNDERFLOWS: 3264 val = gstp->underflow; 3265 break; 3266 3267 case MAC_STAT_OVERFLOWS: 3268 val = gstp->overflow; 3269 break; 3270 3271 case ETHER_STAT_ALIGN_ERRORS: 3272 val = gstp->frame; 3273 break; 3274 3275 case ETHER_STAT_FCS_ERRORS: 3276 val = gstp->crc; 3277 break; 3278 3279 case ETHER_STAT_FIRST_COLLISIONS: 3280 val = gstp->first_coll; 3281 break; 3282 3283 case ETHER_STAT_MULTI_COLLISIONS: 3284 val = gstp->multi_coll; 3285 break; 3286 3287 case ETHER_STAT_SQE_ERRORS: 3288 val = gstp->sqe; 3289 break; 3290 3291 case ETHER_STAT_DEFER_XMTS: 3292 val = gstp->defer; 3293 break; 3294 3295 case ETHER_STAT_TX_LATE_COLLISIONS: 3296 val = gstp->xmtlatecoll; 3297 break; 3298 3299 case ETHER_STAT_EX_COLLISIONS: 3300 val = gstp->excoll; 3301 break; 3302 3303 case ETHER_STAT_MACXMT_ERRORS: 3304 val = gstp->xmit_internal_err; 3305 break; 3306 3307 case ETHER_STAT_CARRIER_ERRORS: 3308 val = gstp->nocarrier; 3309 break; 3310 3311 case ETHER_STAT_TOOLONG_ERRORS: 3312 val = gstp->frame_too_long; 3313 break; 3314 3315 case ETHER_STAT_MACRCV_ERRORS: 3316 val = gstp->rcv_internal_err; 3317 break; 3318 3319 case ETHER_STAT_XCVR_ADDR: 3320 val = dp->mii_phy_addr; 3321 break; 3322 3323 case ETHER_STAT_XCVR_ID: 3324 val = dp->mii_phy_id; 3325 break; 3326 3327 case ETHER_STAT_XCVR_INUSE: 3328 val = usbgem_mac_xcvr_inuse(dp); 3329 break; 3330 3331 case ETHER_STAT_CAP_1000FDX: 3332 val = (dp->mii_xstatus & MII_XSTATUS_1000BASET_FD) || 3333 (dp->mii_xstatus & MII_XSTATUS_1000BASEX_FD); 3334 break; 3335 3336 case ETHER_STAT_CAP_1000HDX: 3337 val = (dp->mii_xstatus & MII_XSTATUS_1000BASET) || 3338 (dp->mii_xstatus & MII_XSTATUS_1000BASEX); 3339 break; 3340 3341 case ETHER_STAT_CAP_100FDX: 3342 val = BOOLEAN(dp->mii_status & MII_STATUS_100_BASEX_FD); 3343 break; 3344 3345 case ETHER_STAT_CAP_100HDX: 3346 val = BOOLEAN(dp->mii_status & MII_STATUS_100_BASEX); 3347 break; 3348 3349 case ETHER_STAT_CAP_10FDX: 3350 val = BOOLEAN(dp->mii_status & MII_STATUS_10_FD); 3351 break; 3352 3353 case ETHER_STAT_CAP_10HDX: 3354 val = BOOLEAN(dp->mii_status & MII_STATUS_10); 3355 break; 3356 3357 case ETHER_STAT_CAP_ASMPAUSE: 3358 val = dp->ugc.usbgc_flow_control > FLOW_CONTROL_SYMMETRIC; 3359 break; 3360 3361 case ETHER_STAT_CAP_PAUSE: 3362 val = dp->ugc.usbgc_flow_control != FLOW_CONTROL_NONE; 3363 break; 3364 3365 case ETHER_STAT_CAP_AUTONEG: 3366 val = BOOLEAN(dp->mii_status & MII_STATUS_CANAUTONEG); 3367 break; 3368 3369 case ETHER_STAT_ADV_CAP_1000FDX: 3370 val = dp->anadv_1000fdx; 3371 break; 3372 3373 case ETHER_STAT_ADV_CAP_1000HDX: 3374 val = dp->anadv_1000hdx; 3375 break; 3376 3377 case ETHER_STAT_ADV_CAP_100FDX: 3378 val = dp->anadv_100fdx; 3379 break; 3380 3381 case ETHER_STAT_ADV_CAP_100HDX: 3382 val = dp->anadv_100hdx; 3383 break; 3384 3385 case ETHER_STAT_ADV_CAP_10FDX: 3386 val = dp->anadv_10fdx; 3387 break; 3388 3389 case ETHER_STAT_ADV_CAP_10HDX: 3390 val = dp->anadv_10hdx; 3391 break; 3392 3393 case ETHER_STAT_ADV_CAP_ASMPAUSE: 3394 val = dp->anadv_asmpause; 3395 break; 3396 3397 case ETHER_STAT_ADV_CAP_PAUSE: 3398 val = dp->anadv_pause; 3399 break; 3400 3401 case ETHER_STAT_ADV_CAP_AUTONEG: 3402 val = dp->anadv_autoneg; 3403 break; 3404 3405 case ETHER_STAT_LP_CAP_1000FDX: 3406 val = BOOLEAN(dp->mii_stat1000 & MII_1000TS_LP_FULL); 3407 break; 3408 3409 case ETHER_STAT_LP_CAP_1000HDX: 3410 val = BOOLEAN(dp->mii_stat1000 & MII_1000TS_LP_HALF); 3411 break; 3412 3413 case ETHER_STAT_LP_CAP_100FDX: 3414 val = BOOLEAN(dp->mii_lpable & MII_ABILITY_100BASE_TX_FD); 3415 break; 3416 3417 case ETHER_STAT_LP_CAP_100HDX: 3418 val = BOOLEAN(dp->mii_lpable & MII_ABILITY_100BASE_TX); 3419 break; 3420 3421 case ETHER_STAT_LP_CAP_10FDX: 3422 val = BOOLEAN(dp->mii_lpable & MII_ABILITY_10BASE_T_FD); 3423 break; 3424 3425 case ETHER_STAT_LP_CAP_10HDX: 3426 val = BOOLEAN(dp->mii_lpable & MII_ABILITY_10BASE_T); 3427 break; 3428 3429 case ETHER_STAT_LP_CAP_ASMPAUSE: 3430 val = BOOLEAN(dp->mii_lpable & MII_ABILITY_ASM_DIR); 3431 break; 3432 3433 case ETHER_STAT_LP_CAP_PAUSE: 3434 val = BOOLEAN(dp->mii_lpable & MII_ABILITY_PAUSE); 3435 break; 3436 3437 case ETHER_STAT_LP_CAP_AUTONEG: 3438 val = BOOLEAN(dp->mii_exp & MII_AN_EXP_LPCANAN); 3439 break; 3440 3441 case ETHER_STAT_LINK_ASMPAUSE: 3442 val = BOOLEAN(dp->flow_control & 2); 3443 break; 3444 3445 case ETHER_STAT_LINK_PAUSE: 3446 val = BOOLEAN(dp->flow_control & 1); 3447 break; 3448 3449 case ETHER_STAT_LINK_AUTONEG: 3450 val = dp->anadv_autoneg && 3451 BOOLEAN(dp->mii_exp & MII_AN_EXP_LPCANAN); 3452 break; 3453 3454 case ETHER_STAT_LINK_DUPLEX: 3455 val = (dp->mii_state == MII_STATE_LINKUP) ? 3456 (dp->full_duplex ? 2 : 1) : 0; 3457 break; 3458 3459 case ETHER_STAT_TOOSHORT_ERRORS: 3460 val = gstp->runt; 3461 break; 3462 #ifdef NEVER /* it doesn't make sense */ 3463 case ETHER_STAT_CAP_REMFAULT: 3464 val = B_TRUE; 3465 break; 3466 3467 case ETHER_STAT_ADV_REMFAULT: 3468 val = dp->anadv_remfault; 3469 break; 3470 #endif 3471 case ETHER_STAT_LP_REMFAULT: 3472 val = BOOLEAN(dp->mii_lpable & MII_AN_ADVERT_REMFAULT); 3473 break; 3474 3475 case ETHER_STAT_JABBER_ERRORS: 3476 val = gstp->jabber; 3477 break; 3478 3479 case ETHER_STAT_CAP_100T4: 3480 val = BOOLEAN(dp->mii_status & MII_STATUS_100_BASE_T4); 3481 break; 3482 3483 case ETHER_STAT_ADV_CAP_100T4: 3484 val = dp->anadv_100t4; 3485 break; 3486 3487 case ETHER_STAT_LP_CAP_100T4: 3488 val = BOOLEAN(dp->mii_lpable & MII_ABILITY_100BASE_T4); 3489 break; 3490 3491 default: 3492 #if GEM_DEBUG_LEVEL > 2 3493 cmn_err(CE_WARN, 3494 "%s: unrecognized parameter value = %d", 3495 __func__, stat); 3496 #endif 3497 *valp = 0; 3498 return (ENOTSUP); 3499 } 3500 3501 *valp = val; 3502 3503 return (0); 3504 } 3505 3506 static int 3507 usbgem_m_unicst(void *arg, const uint8_t *mac) 3508 { 3509 int err; 3510 struct usbgem_dev *dp = arg; 3511 3512 DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__)); 3513 3514 rw_enter(&dp->dev_state_lock, RW_READER); 3515 3516 sema_p(&dp->rxfilter_lock); 3517 bcopy(mac, dp->cur_addr.ether_addr_octet, ETHERADDRL); 3518 dp->rxmode |= RXMODE_ENABLE; 3519 3520 err = 0; 3521 if (dp->mac_state != MAC_STATE_DISCONNECTED) { 3522 if (usbgem_hal_set_rx_filter(dp) != USB_SUCCESS) { 3523 err = EIO; 3524 } 3525 } 3526 sema_v(&dp->rxfilter_lock); 3527 rw_exit(&dp->dev_state_lock); 3528 3529 return (err); 3530 } 3531 3532 /* 3533 * usbgem_m_tx is used only for sending data packets into ethernet wire. 3534 */ 3535 static mblk_t * 3536 usbgem_m_tx(void *arg, mblk_t *mp_head) 3537 { 3538 int limit; 3539 mblk_t *mp; 3540 mblk_t *nmp; 3541 struct usbgem_dev *dp = arg; 3542 3543 DPRINTF(4, (CE_CONT, "!%s: %s: called", dp->name, __func__)); 3544 3545 mp = mp_head; 3546 3547 rw_enter(&dp->dev_state_lock, RW_READER); 3548 3549 if (dp->mii_state != MII_STATE_LINKUP || 3550 dp->mac_state != MAC_STATE_ONLINE) { 3551 /* some nics hate to send packets during the link is down */ 3552 for (; mp; mp = nmp) { 3553 nmp = mp->b_next; 3554 mp->b_next = NULL; 3555 freemsg(mp); 3556 } 3557 goto x; 3558 } 3559 3560 ASSERT(dp->nic_state == NIC_STATE_ONLINE); 3561 3562 limit = dp->tx_max_packets; 3563 for (; limit-- && mp; mp = nmp) { 3564 nmp = mp->b_next; 3565 mp->b_next = NULL; 3566 if (usbgem_send_common(dp, mp, 3567 (limit == 0 && nmp) ? 1 : 0)) { 3568 mp->b_next = nmp; 3569 break; 3570 } 3571 } 3572 #ifdef CONFIG_TX_LIMITER 3573 if (mp == mp_head) { 3574 /* no packets were sent, descrease allocation limit */ 3575 mutex_enter(&dp->txlock); 3576 dp->tx_max_packets = max(dp->tx_max_packets - 1, 1); 3577 mutex_exit(&dp->txlock); 3578 } 3579 #endif 3580 x: 3581 rw_exit(&dp->dev_state_lock); 3582 3583 return (mp); 3584 } 3585 3586 static void 3587 usbgem_m_ioctl(void *arg, queue_t *wq, mblk_t *mp) 3588 { 3589 struct usbgem_dev *dp = arg; 3590 3591 DPRINTF(1, (CE_CONT, "!%s: %s: called", 3592 ((struct usbgem_dev *)arg)->name, __func__)); 3593 3594 rw_enter(&dp->dev_state_lock, RW_READER); 3595 usbgem_mac_ioctl((struct usbgem_dev *)arg, wq, mp); 3596 rw_exit(&dp->dev_state_lock); 3597 } 3598 3599 static void 3600 usbgem_gld3_init(struct usbgem_dev *dp, mac_register_t *macp) 3601 { 3602 macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER; 3603 macp->m_driver = dp; 3604 macp->m_dip = dp->dip; 3605 macp->m_src_addr = dp->dev_addr.ether_addr_octet; 3606 macp->m_callbacks = &gem_m_callbacks; 3607 macp->m_min_sdu = 0; 3608 macp->m_max_sdu = dp->mtu; 3609 3610 if (dp->misc_flag & USBGEM_VLAN) { 3611 macp->m_margin = VTAG_SIZE; 3612 } 3613 } 3614 3615 /* ======================================================================== */ 3616 /* 3617 * .conf interface 3618 */ 3619 /* ======================================================================== */ 3620 void 3621 usbgem_generate_macaddr(struct usbgem_dev *dp, uint8_t *mac) 3622 { 3623 extern char hw_serial[]; 3624 char *hw_serial_p; 3625 int i; 3626 uint64_t val; 3627 uint64_t key; 3628 3629 cmn_err(CE_NOTE, 3630 "!%s: using temp ether address," 3631 " do not use this for long time", 3632 dp->name); 3633 3634 /* prefer a fixed address for DHCP */ 3635 hw_serial_p = &hw_serial[0]; 3636 val = stoi(&hw_serial_p); 3637 3638 key = 0; 3639 for (i = 0; i < USBGEM_NAME_LEN; i++) { 3640 if (dp->name[i] == 0) { 3641 break; 3642 } 3643 key ^= dp->name[i]; 3644 } 3645 key ^= ddi_get_instance(dp->dip); 3646 val ^= key << 32; 3647 3648 /* generate a local address */ 3649 mac[0] = 0x02; 3650 mac[1] = (uint8_t)(val >> 32); 3651 mac[2] = (uint8_t)(val >> 24); 3652 mac[3] = (uint8_t)(val >> 16); 3653 mac[4] = (uint8_t)(val >> 8); 3654 mac[5] = (uint8_t)val; 3655 } 3656 3657 boolean_t 3658 usbgem_get_mac_addr_conf(struct usbgem_dev *dp) 3659 { 3660 char propname[32]; 3661 char *valstr; 3662 uint8_t mac[ETHERADDRL]; 3663 char *cp; 3664 int c; 3665 int i; 3666 int j; 3667 uint8_t v; 3668 uint8_t d; 3669 uint8_t ored; 3670 3671 DPRINTF(3, (CE_CONT, "!%s: %s: called", dp->name, __func__)); 3672 /* 3673 * Get ethernet address from .conf file 3674 */ 3675 (void) sprintf(propname, "mac-addr"); 3676 if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, dp->dip, 3677 DDI_PROP_DONTPASS, propname, &valstr)) != DDI_PROP_SUCCESS) { 3678 return (B_FALSE); 3679 } 3680 3681 if (strlen(valstr) != ETHERADDRL*3-1) { 3682 goto syntax_err; 3683 } 3684 3685 cp = valstr; 3686 j = 0; 3687 ored = 0; 3688 for (;;) { 3689 v = 0; 3690 for (i = 0; i < 2; i++) { 3691 c = *cp++; 3692 3693 if (c >= 'a' && c <= 'f') { 3694 d = c - 'a' + 10; 3695 } else if (c >= 'A' && c <= 'F') { 3696 d = c - 'A' + 10; 3697 } else if (c >= '0' && c <= '9') { 3698 d = c - '0'; 3699 } else { 3700 goto syntax_err; 3701 } 3702 v = (v << 4) | d; 3703 } 3704 3705 mac[j++] = v; 3706 ored |= v; 3707 if (j == ETHERADDRL) { 3708 /* done */ 3709 break; 3710 } 3711 3712 c = *cp++; 3713 if (c != ':') { 3714 goto syntax_err; 3715 } 3716 } 3717 3718 if (ored == 0) { 3719 usbgem_generate_macaddr(dp, mac); 3720 } 3721 for (i = 0; i < ETHERADDRL; i++) { 3722 dp->dev_addr.ether_addr_octet[i] = mac[i]; 3723 } 3724 ddi_prop_free(valstr); 3725 return (B_TRUE); 3726 3727 syntax_err: 3728 cmn_err(CE_CONT, 3729 "!%s: read mac addr: trying .conf: syntax err %s", 3730 dp->name, valstr); 3731 ddi_prop_free(valstr); 3732 3733 return (B_FALSE); 3734 } 3735 3736 static void 3737 usbgem_read_conf(struct usbgem_dev *dp) 3738 { 3739 int val; 3740 3741 DPRINTF(1, (CE_CONT, "!%s: %s: called", dp->name, __func__)); 3742 3743 /* 3744 * Get media mode infomation from .conf file 3745 */ 3746 dp->anadv_autoneg = usbgem_prop_get_int(dp, "adv_autoneg_cap", 1) != 0; 3747 dp->anadv_1000fdx = usbgem_prop_get_int(dp, "adv_1000fdx_cap", 1) != 0; 3748 dp->anadv_1000hdx = usbgem_prop_get_int(dp, "adv_1000hdx_cap", 1) != 0; 3749 dp->anadv_100t4 = usbgem_prop_get_int(dp, "adv_100T4_cap", 1) != 0; 3750 dp->anadv_100fdx = usbgem_prop_get_int(dp, "adv_100fdx_cap", 1) != 0; 3751 dp->anadv_100hdx = usbgem_prop_get_int(dp, "adv_100hdx_cap", 1) != 0; 3752 dp->anadv_10fdx = usbgem_prop_get_int(dp, "adv_10fdx_cap", 1) != 0; 3753 dp->anadv_10hdx = usbgem_prop_get_int(dp, "adv_10hdx_cap", 1) != 0; 3754 dp->anadv_1000t_ms = usbgem_prop_get_int(dp, "adv_1000t_ms", 0); 3755 3756 if ((ddi_prop_exists(DDI_DEV_T_ANY, dp->dip, 3757 DDI_PROP_DONTPASS, "full-duplex"))) { 3758 dp->full_duplex = 3759 usbgem_prop_get_int(dp, "full-duplex", 1) != 0; 3760 dp->anadv_autoneg = B_FALSE; 3761 if (dp->full_duplex) { 3762 dp->anadv_1000hdx = B_FALSE; 3763 dp->anadv_100hdx = B_FALSE; 3764 dp->anadv_10hdx = B_FALSE; 3765 } else { 3766 dp->anadv_1000fdx = B_FALSE; 3767 dp->anadv_100fdx = B_FALSE; 3768 dp->anadv_10fdx = B_FALSE; 3769 } 3770 } 3771 3772 if ((val = usbgem_prop_get_int(dp, "speed", 0)) > 0) { 3773 dp->anadv_autoneg = B_FALSE; 3774 switch (val) { 3775 case 1000: 3776 dp->speed = USBGEM_SPD_1000; 3777 dp->anadv_100t4 = B_FALSE; 3778 dp->anadv_100fdx = B_FALSE; 3779 dp->anadv_100hdx = B_FALSE; 3780 dp->anadv_10fdx = B_FALSE; 3781 dp->anadv_10hdx = B_FALSE; 3782 break; 3783 case 100: 3784 dp->speed = USBGEM_SPD_100; 3785 dp->anadv_1000fdx = B_FALSE; 3786 dp->anadv_1000hdx = B_FALSE; 3787 dp->anadv_10fdx = B_FALSE; 3788 dp->anadv_10hdx = B_FALSE; 3789 break; 3790 case 10: 3791 dp->speed = USBGEM_SPD_10; 3792 dp->anadv_1000fdx = B_FALSE; 3793 dp->anadv_1000hdx = B_FALSE; 3794 dp->anadv_100t4 = B_FALSE; 3795 dp->anadv_100fdx = B_FALSE; 3796 dp->anadv_100hdx = B_FALSE; 3797 break; 3798 default: 3799 cmn_err(CE_WARN, 3800 "!%s: property %s: illegal value:%d", 3801 dp->name, "speed", val); 3802 dp->anadv_autoneg = B_TRUE; 3803 break; 3804 } 3805 } 3806 val = usbgem_prop_get_int(dp, 3807 "adv_pause", dp->ugc.usbgc_flow_control & 1); 3808 val |= usbgem_prop_get_int(dp, 3809 "adv_asmpause", BOOLEAN(dp->ugc.usbgc_flow_control & 2)) << 1; 3810 if (val > FLOW_CONTROL_RX_PAUSE || val < FLOW_CONTROL_NONE) { 3811 cmn_err(CE_WARN, 3812 "!%s: property %s: illegal value:%d", 3813 dp->name, "flow-control", val); 3814 } else { 3815 val = min(val, dp->ugc.usbgc_flow_control); 3816 } 3817 dp->anadv_pause = BOOLEAN(val & 1); 3818 dp->anadv_asmpause = BOOLEAN(val & 2); 3819 3820 dp->mtu = usbgem_prop_get_int(dp, "mtu", dp->mtu); 3821 dp->txthr = usbgem_prop_get_int(dp, "txthr", dp->txthr); 3822 dp->rxthr = usbgem_prop_get_int(dp, "rxthr", dp->rxthr); 3823 dp->txmaxdma = usbgem_prop_get_int(dp, "txmaxdma", dp->txmaxdma); 3824 dp->rxmaxdma = usbgem_prop_get_int(dp, "rxmaxdma", dp->rxmaxdma); 3825 #ifdef GEM_CONFIG_POLLING 3826 dp->poll_pkt_delay = 3827 usbgem_prop_get_int(dp, "pkt_delay", dp->poll_pkt_delay); 3828 3829 dp->max_poll_interval[GEM_SPD_10] = 3830 usbgem_prop_get_int(dp, "max_poll_interval_10", 3831 dp->max_poll_interval[GEM_SPD_10]); 3832 dp->max_poll_interval[GEM_SPD_100] = 3833 usbgem_prop_get_int(dp, "max_poll_interval_100", 3834 dp->max_poll_interval[GEM_SPD_100]); 3835 dp->max_poll_interval[GEM_SPD_1000] = 3836 usbgem_prop_get_int(dp, "max_poll_interval_1000", 3837 dp->max_poll_interval[GEM_SPD_1000]); 3838 3839 dp->min_poll_interval[GEM_SPD_10] = 3840 usbgem_prop_get_int(dp, "min_poll_interval_10", 3841 dp->min_poll_interval[GEM_SPD_10]); 3842 dp->min_poll_interval[GEM_SPD_100] = 3843 usbgem_prop_get_int(dp, "min_poll_interval_100", 3844 dp->min_poll_interval[GEM_SPD_100]); 3845 dp->min_poll_interval[GEM_SPD_1000] = 3846 usbgem_prop_get_int(dp, "min_poll_interval_1000", 3847 dp->min_poll_interval[GEM_SPD_1000]); 3848 #endif 3849 } 3850 3851 /* 3852 * attach/detatch/usb support 3853 */ 3854 /* ======================================================================== */ 3855 int 3856 usbgem_ctrl_out(struct usbgem_dev *dp, 3857 uint8_t reqt, uint8_t req, uint16_t val, uint16_t ix, uint16_t len, 3858 void *bp, int size) 3859 { 3860 mblk_t *data; 3861 usb_ctrl_setup_t setup; 3862 usb_cr_t completion_reason; 3863 usb_cb_flags_t cb_flags; 3864 usb_flags_t flags; 3865 int i; 3866 int ret; 3867 3868 DPRINTF(4, (CE_CONT, "!%s: %s " 3869 "reqt:0x%02x req:0x%02x val:0x%04x ix:0x%04x len:0x%02x " 3870 "bp:0x%p nic_state:%d", 3871 dp->name, __func__, reqt, req, val, ix, len, bp, dp->nic_state)); 3872 3873 if (dp->mac_state == MAC_STATE_DISCONNECTED) { 3874 return (USB_PIPE_ERROR); 3875 } 3876 3877 data = NULL; 3878 if (size > 0) { 3879 if ((data = allocb(size, 0)) == NULL) { 3880 return (USB_FAILURE); 3881 } 3882 3883 bcopy(bp, data->b_rptr, size); 3884 data->b_wptr = data->b_rptr + size; 3885 } 3886 3887 setup.bmRequestType = reqt; 3888 setup.bRequest = req; 3889 setup.wValue = val; 3890 setup.wIndex = ix; 3891 setup.wLength = len; 3892 setup.attrs = 0; /* attributes */ 3893 3894 for (i = usbgem_ctrl_retry; i > 0; i--) { 3895 completion_reason = 0; 3896 cb_flags = 0; 3897 3898 ret = usb_pipe_ctrl_xfer_wait(DEFAULT_PIPE(dp), 3899 &setup, &data, &completion_reason, &cb_flags, 0); 3900 3901 if (ret == USB_SUCCESS) { 3902 break; 3903 } 3904 if (i == 1) { 3905 cmn_err(CE_WARN, 3906 "!%s: %s failed: " 3907 "reqt:0x%x req:0x%x val:0x%x ix:0x%x len:0x%x " 3908 "ret:%d cr:%s(%d), cb_flags:0x%x %s", 3909 dp->name, __func__, reqt, req, val, ix, len, 3910 ret, usb_str_cr(completion_reason), 3911 completion_reason, 3912 cb_flags, 3913 (i > 1) ? "retrying..." : "fatal"); 3914 } 3915 } 3916 3917 if (data != NULL) { 3918 freemsg(data); 3919 } 3920 3921 return (ret); 3922 } 3923 3924 int 3925 usbgem_ctrl_in(struct usbgem_dev *dp, 3926 uint8_t reqt, uint8_t req, uint16_t val, uint16_t ix, uint16_t len, 3927 void *bp, int size) 3928 { 3929 mblk_t *data; 3930 usb_ctrl_setup_t setup; 3931 usb_cr_t completion_reason; 3932 usb_cb_flags_t cb_flags; 3933 int i; 3934 int ret; 3935 int reclen; 3936 3937 DPRINTF(4, (CE_CONT, 3938 "!%s: %s:" 3939 " reqt:0x%02x req:0x%02x val:0x%04x ix:0x%04x len:0x%02x" 3940 " bp:x%p mac_state:%d", 3941 dp->name, __func__, reqt, req, val, ix, len, bp, dp->mac_state)); 3942 3943 if (dp->mac_state == MAC_STATE_DISCONNECTED) { 3944 return (USB_PIPE_ERROR); 3945 } 3946 3947 data = NULL; 3948 3949 setup.bmRequestType = reqt; 3950 setup.bRequest = req; 3951 setup.wValue = val; 3952 setup.wIndex = ix; 3953 setup.wLength = len; 3954 setup.attrs = USB_ATTRS_AUTOCLEARING; /* XXX */ 3955 3956 for (i = usbgem_ctrl_retry; i > 0; i--) { 3957 completion_reason = 0; 3958 cb_flags = 0; 3959 ret = usb_pipe_ctrl_xfer_wait(DEFAULT_PIPE(dp), &setup, &data, 3960 &completion_reason, &cb_flags, 0); 3961 3962 if (ret == USB_SUCCESS) { 3963 reclen = msgdsize(data); 3964 bcopy(data->b_rptr, bp, min(reclen, size)); 3965 break; 3966 } 3967 if (i == 1) { 3968 cmn_err(CE_WARN, 3969 "!%s: %s failed: " 3970 "reqt:0x%x req:0x%x val:0x%x ix:0x%x len:0x%x " 3971 "ret:%d cr:%s(%d) cb_flags:0x%x %s", 3972 dp->name, __func__, 3973 reqt, req, val, ix, len, 3974 ret, usb_str_cr(completion_reason), 3975 completion_reason, 3976 cb_flags, 3977 (i > 1) ? "retrying..." : "fatal"); 3978 } 3979 } 3980 3981 if (data) { 3982 freemsg(data); 3983 } 3984 3985 return (ret); 3986 } 3987 3988 int 3989 usbgem_ctrl_out_val(struct usbgem_dev *dp, 3990 uint8_t reqt, uint8_t req, uint16_t val, uint16_t ix, uint16_t len, 3991 uint32_t v) 3992 { 3993 uint8_t buf[4]; 3994 3995 /* convert to little endian from native byte order */ 3996 switch (len) { 3997 case 4: 3998 buf[3] = v >> 24; 3999 buf[2] = v >> 16; 4000 /* FALLTHROUGH */ 4001 case 2: 4002 buf[1] = v >> 8; 4003 /* FALLTHROUGH */ 4004 case 1: 4005 buf[0] = v; 4006 } 4007 4008 return (usbgem_ctrl_out(dp, reqt, req, val, ix, len, buf, len)); 4009 } 4010 4011 int 4012 usbgem_ctrl_in_val(struct usbgem_dev *dp, 4013 uint8_t reqt, uint8_t req, uint16_t val, uint16_t ix, uint16_t len, 4014 void *valp) 4015 { 4016 uint8_t buf[4]; 4017 uint_t v; 4018 int err; 4019 4020 #ifdef SANITY 4021 bzero(buf, sizeof (buf)); 4022 #endif 4023 err = usbgem_ctrl_in(dp, reqt, req, val, ix, len, buf, len); 4024 if (err == USB_SUCCESS) { 4025 v = 0; 4026 switch (len) { 4027 case 4: 4028 v |= buf[3] << 24; 4029 v |= buf[2] << 16; 4030 /* FALLTHROUGH */ 4031 case 2: 4032 v |= buf[1] << 8; 4033 /* FALLTHROUGH */ 4034 case 1: 4035 v |= buf[0]; 4036 } 4037 4038 switch (len) { 4039 case 4: 4040 *(uint32_t *)valp = v; 4041 break; 4042 case 2: 4043 *(uint16_t *)valp = v; 4044 break; 4045 case 1: 4046 *(uint8_t *)valp = v; 4047 break; 4048 } 4049 } 4050 return (err); 4051 } 4052 4053 /* 4054 * Attach / detach / disconnect / reconnect management 4055 */ 4056 static int 4057 usbgem_open_pipes(struct usbgem_dev *dp) 4058 { 4059 int i; 4060 int ret; 4061 int ifnum; 4062 int alt; 4063 usb_client_dev_data_t *reg_data; 4064 usb_ep_data_t *ep_tree_node; 4065 4066 DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__)); 4067 4068 ifnum = dp->ugc.usbgc_ifnum; 4069 alt = dp->ugc.usbgc_alt; 4070 4071 ep_tree_node = usb_lookup_ep_data(dp->dip, dp->reg_data, ifnum, alt, 4072 0, USB_EP_ATTR_BULK, USB_EP_DIR_IN); 4073 if (ep_tree_node == NULL) { 4074 cmn_err(CE_WARN, "!%s: %s: ep_bulkin is NULL", 4075 dp->name, __func__); 4076 goto err; 4077 } 4078 dp->ep_bulkin = &ep_tree_node->ep_descr; 4079 4080 ep_tree_node = usb_lookup_ep_data(dp->dip, dp->reg_data, ifnum, alt, 4081 0, USB_EP_ATTR_BULK, USB_EP_DIR_OUT); 4082 if (ep_tree_node == NULL) { 4083 cmn_err(CE_WARN, "!%s: %s: ep_bulkout is NULL", 4084 dp->name, __func__); 4085 goto err; 4086 } 4087 dp->ep_bulkout = &ep_tree_node->ep_descr; 4088 4089 ep_tree_node = usb_lookup_ep_data(dp->dip, dp->reg_data, ifnum, alt, 4090 0, USB_EP_ATTR_INTR, USB_EP_DIR_IN); 4091 if (ep_tree_node) { 4092 dp->ep_intr = &ep_tree_node->ep_descr; 4093 } else { 4094 /* don't care */ 4095 DPRINTF(1, (CE_CONT, "!%s: %s: ep_intr is NULL", 4096 dp->name, __func__)); 4097 dp->ep_intr = NULL; 4098 } 4099 4100 /* XXX -- no need to open default pipe */ 4101 4102 /* open bulk out pipe */ 4103 bzero(&dp->policy_bulkout, sizeof (usb_pipe_policy_t)); 4104 dp->policy_bulkout.pp_max_async_reqs = 1; 4105 4106 if ((ret = usb_pipe_open(dp->dip, 4107 dp->ep_bulkout, &dp->policy_bulkout, USB_FLAGS_SLEEP, 4108 &dp->bulkout_pipe)) != USB_SUCCESS) { 4109 cmn_err(CE_WARN, 4110 "!%s: %s: err:%x: failed to open bulk-out pipe", 4111 dp->name, __func__, ret); 4112 dp->bulkout_pipe = NULL; 4113 goto err; 4114 } 4115 DPRINTF(1, (CE_CONT, "!%s: %s: bulkout_pipe opened successfully", 4116 dp->name, __func__)); 4117 4118 /* open bulk in pipe */ 4119 bzero(&dp->policy_bulkin, sizeof (usb_pipe_policy_t)); 4120 dp->policy_bulkin.pp_max_async_reqs = 1; 4121 if ((ret = usb_pipe_open(dp->dip, 4122 dp->ep_bulkin, &dp->policy_bulkin, USB_FLAGS_SLEEP, 4123 &dp->bulkin_pipe)) != USB_SUCCESS) { 4124 cmn_err(CE_WARN, 4125 "!%s: %s: ret:%x failed to open bulk-in pipe", 4126 dp->name, __func__, ret); 4127 dp->bulkin_pipe = NULL; 4128 goto err; 4129 } 4130 DPRINTF(1, (CE_CONT, "!%s: %s: bulkin_pipe opened successfully", 4131 dp->name, __func__)); 4132 4133 if (dp->ep_intr) { 4134 /* open interrupt pipe */ 4135 bzero(&dp->policy_interrupt, sizeof (usb_pipe_policy_t)); 4136 dp->policy_interrupt.pp_max_async_reqs = 1; 4137 if ((ret = usb_pipe_open(dp->dip, dp->ep_intr, 4138 &dp->policy_interrupt, USB_FLAGS_SLEEP, 4139 &dp->intr_pipe)) != USB_SUCCESS) { 4140 cmn_err(CE_WARN, 4141 "!%s: %s: ret:%x failed to open interrupt pipe", 4142 dp->name, __func__, ret); 4143 dp->intr_pipe = NULL; 4144 goto err; 4145 } 4146 } 4147 DPRINTF(1, (CE_CONT, "!%s: %s: intr_pipe opened successfully", 4148 dp->name, __func__)); 4149 4150 return (USB_SUCCESS); 4151 4152 err: 4153 if (dp->bulkin_pipe) { 4154 usb_pipe_close(dp->dip, 4155 dp->bulkin_pipe, USB_FLAGS_SLEEP, NULL, 0); 4156 dp->bulkin_pipe = NULL; 4157 } 4158 if (dp->bulkout_pipe) { 4159 usb_pipe_close(dp->dip, 4160 dp->bulkout_pipe, USB_FLAGS_SLEEP, NULL, 0); 4161 dp->bulkout_pipe = NULL; 4162 } 4163 if (dp->intr_pipe) { 4164 usb_pipe_close(dp->dip, 4165 dp->intr_pipe, USB_FLAGS_SLEEP, NULL, 0); 4166 dp->intr_pipe = NULL; 4167 } 4168 4169 return (USB_FAILURE); 4170 } 4171 4172 static int 4173 usbgem_close_pipes(struct usbgem_dev *dp) 4174 { 4175 DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__)); 4176 4177 if (dp->intr_pipe) { 4178 usb_pipe_close(dp->dip, 4179 dp->intr_pipe, USB_FLAGS_SLEEP, NULL, 0); 4180 dp->intr_pipe = NULL; 4181 } 4182 DPRINTF(1, (CE_CONT, "!%s: %s: 1", dp->name, __func__)); 4183 4184 ASSERT(dp->bulkin_pipe); 4185 usb_pipe_close(dp->dip, dp->bulkin_pipe, USB_FLAGS_SLEEP, NULL, 0); 4186 dp->bulkin_pipe = NULL; 4187 DPRINTF(1, (CE_CONT, "!%s: %s: 2", dp->name, __func__)); 4188 4189 ASSERT(dp->bulkout_pipe); 4190 usb_pipe_close(dp->dip, dp->bulkout_pipe, USB_FLAGS_SLEEP, NULL, 0); 4191 dp->bulkout_pipe = NULL; 4192 DPRINTF(1, (CE_CONT, "!%s: %s: 3", dp->name, __func__)); 4193 4194 return (USB_SUCCESS); 4195 } 4196 4197 #define FREEZE_GRACEFUL (B_TRUE) 4198 #define FREEZE_NO_GRACEFUL (B_FALSE) 4199 static int 4200 usbgem_freeze_device(struct usbgem_dev *dp, boolean_t graceful) 4201 { 4202 DPRINTF(0, (CE_NOTE, "!%s: %s: called", dp->name, __func__)); 4203 4204 /* stop nic activity */ 4205 (void) usbgem_mac_stop(dp, MAC_STATE_DISCONNECTED, graceful); 4206 4207 /* 4208 * Here we free all memory resource allocated, because it will 4209 * cause to panic the system that we free usb_bulk_req objects 4210 * during the usb device is disconnected. 4211 */ 4212 (void) usbgem_free_memory(dp); 4213 4214 return (USB_SUCCESS); 4215 } 4216 4217 static int 4218 usbgem_disconnect_cb(dev_info_t *dip) 4219 { 4220 int ret; 4221 struct usbgem_dev *dp; 4222 4223 dp = USBGEM_GET_DEV(dip); 4224 4225 cmn_err(CE_NOTE, "!%s: the usb device was disconnected (dp=%p)", 4226 dp->name, (void *)dp); 4227 4228 /* start serialize */ 4229 rw_enter(&dp->dev_state_lock, RW_WRITER); 4230 4231 ret = usbgem_freeze_device(dp, 0); 4232 4233 /* end of serialize */ 4234 rw_exit(&dp->dev_state_lock); 4235 4236 return (ret); 4237 } 4238 4239 static int 4240 usbgem_recover_device(struct usbgem_dev *dp) 4241 { 4242 int err; 4243 4244 DPRINTF(0, (CE_NOTE, "!%s: %s: called", dp->name, __func__)); 4245 4246 err = USB_SUCCESS; 4247 4248 /* reinitialize the usb connection */ 4249 usbgem_close_pipes(dp); 4250 if ((err = usbgem_open_pipes(dp)) != USB_SUCCESS) { 4251 goto x; 4252 } 4253 4254 /* initialize nic state */ 4255 dp->mac_state = MAC_STATE_STOPPED; 4256 dp->mii_state = MII_STATE_UNKNOWN; 4257 4258 /* allocate memory resources again */ 4259 if ((err = usbgem_alloc_memory(dp)) != USB_SUCCESS) { 4260 goto x; 4261 } 4262 4263 /* restart nic and recover state */ 4264 (void) usbgem_restart_nic(dp); 4265 4266 usbgem_mii_init(dp); 4267 4268 /* kick potentially stopped house keeping thread */ 4269 cv_signal(&dp->link_watcher_wait_cv); 4270 x: 4271 return (err); 4272 } 4273 4274 static int 4275 usbgem_reconnect_cb(dev_info_t *dip) 4276 { 4277 int err = USB_SUCCESS; 4278 struct usbgem_dev *dp; 4279 4280 dp = USBGEM_GET_DEV(dip); 4281 DPRINTF(0, (CE_CONT, "!%s: dp=%p", ddi_get_name(dip), dp)); 4282 #ifdef notdef 4283 /* check device changes after disconnect */ 4284 if (usb_check_same_device(dp->dip, NULL, USB_LOG_L2, -1, 4285 USB_CHK_BASIC | USB_CHK_CFG, NULL) != USB_SUCCESS) { 4286 cmn_err(CE_CONT, 4287 "!%s: no or different device installed", dp->name); 4288 return (DDI_SUCCESS); 4289 } 4290 #endif 4291 cmn_err(CE_NOTE, "%s: the usb device was reconnected", dp->name); 4292 4293 /* start serialize */ 4294 rw_enter(&dp->dev_state_lock, RW_WRITER); 4295 4296 if (dp->mac_state == MAC_STATE_DISCONNECTED) { 4297 err = usbgem_recover_device(dp); 4298 } 4299 4300 /* end of serialize */ 4301 rw_exit(&dp->dev_state_lock); 4302 4303 return (err == USB_SUCCESS ? DDI_SUCCESS : DDI_FAILURE); 4304 } 4305 4306 int 4307 usbgem_suspend(dev_info_t *dip) 4308 { 4309 int err = USB_SUCCESS; 4310 struct usbgem_dev *dp; 4311 4312 dp = USBGEM_GET_DEV(dip); 4313 4314 DPRINTF(0, (CE_CONT, "!%s: %s: callded", dp->name, __func__)); 4315 4316 /* start serialize */ 4317 rw_enter(&dp->dev_state_lock, RW_WRITER); 4318 4319 if (dp->mac_state == MAC_STATE_DISCONNECTED) { 4320 err = usbgem_freeze_device(dp, STOP_GRACEFUL); 4321 } 4322 4323 /* end of serialize */ 4324 rw_exit(&dp->dev_state_lock); 4325 4326 return (err == USB_SUCCESS ? DDI_SUCCESS : DDI_FAILURE); 4327 } 4328 4329 int 4330 usbgem_resume(dev_info_t *dip) 4331 { 4332 int err = USB_SUCCESS; 4333 struct usbgem_dev *dp; 4334 4335 dp = USBGEM_GET_DEV(dip); 4336 4337 DPRINTF(0, (CE_CONT, "!%s: %s: callded", dp->name, __func__)); 4338 #ifdef notdef 4339 /* check device changes after disconnect */ 4340 if (usb_check_same_device(dp->dip, NULL, USB_LOG_L2, -1, 4341 USB_CHK_BASIC | USB_CHK_CFG, NULL) != USB_SUCCESS) { 4342 cmn_err(CE_CONT, 4343 "!%s: no or different device installed", dp->name); 4344 return (DDI_SUCCESS); 4345 } 4346 #endif 4347 /* start serialize */ 4348 rw_enter(&dp->dev_state_lock, RW_WRITER); 4349 4350 if (dp->mac_state == MAC_STATE_DISCONNECTED) { 4351 err = usbgem_recover_device(dp); 4352 } 4353 4354 /* end of serialize */ 4355 rw_exit(&dp->dev_state_lock); 4356 4357 return (err == USB_SUCCESS ? DDI_SUCCESS : DDI_FAILURE); 4358 } 4359 4360 #define USBGEM_LOCAL_DATA_SIZE(gc) \ 4361 (sizeof (struct usbgem_dev) + USBGEM_MCALLOC) 4362 4363 struct usbgem_dev * 4364 usbgem_do_attach(dev_info_t *dip, 4365 struct usbgem_conf *gc, void *lp, int lmsize) 4366 { 4367 struct usbgem_dev *dp; 4368 int i; 4369 mac_register_t *macp = NULL; 4370 int ret; 4371 int unit; 4372 int err; 4373 4374 unit = ddi_get_instance(dip); 4375 4376 DPRINTF(2, (CE_CONT, "!usbgem%d: %s: called", unit, __func__)); 4377 4378 /* 4379 * Allocate soft data structure 4380 */ 4381 dp = kmem_zalloc(USBGEM_LOCAL_DATA_SIZE(gc), KM_SLEEP); 4382 if (dp == NULL) { 4383 return (NULL); 4384 } 4385 4386 if ((macp = mac_alloc(MAC_VERSION)) == NULL) { 4387 cmn_err(CE_WARN, "!gem%d: %s: mac_alloc failed", 4388 unit, __func__); 4389 return (NULL); 4390 } 4391 4392 /* link to private area */ 4393 dp->private = lp; 4394 dp->priv_size = lmsize; 4395 dp->mc_list = (struct mcast_addr *)&dp[1]; 4396 4397 dp->dip = dip; 4398 bcopy(gc->usbgc_name, dp->name, USBGEM_NAME_LEN); 4399 4400 /* 4401 * register with usb service 4402 */ 4403 if (usb_client_attach(dip, USBDRV_VERSION, 0) != USB_SUCCESS) { 4404 cmn_err(CE_WARN, 4405 "%s: %s: usb_client_attach failed", 4406 dp->name, __func__); 4407 goto err_free_private; 4408 } 4409 4410 if (usb_get_dev_data(dip, &dp->reg_data, 4411 USB_PARSE_LVL_ALL, 0) != USB_SUCCESS) { 4412 dp->reg_data = NULL; 4413 goto err_unregister_client; 4414 } 4415 #ifdef USBGEM_DEBUG_LEVEL 4416 usb_print_descr_tree(dp->dip, dp->reg_data); 4417 #endif 4418 4419 if (usbgem_open_pipes(dp) != USB_SUCCESS) { 4420 /* failed to open pipes */ 4421 cmn_err(CE_WARN, "!%s: %s: failed to open pipes", 4422 dp->name, __func__); 4423 goto err_unregister_client; 4424 } 4425 4426 /* 4427 * Initialize mutexs and condition variables 4428 */ 4429 mutex_init(&dp->rxlock, NULL, MUTEX_DRIVER, NULL); 4430 mutex_init(&dp->txlock, NULL, MUTEX_DRIVER, NULL); 4431 cv_init(&dp->rx_drain_cv, NULL, CV_DRIVER, NULL); 4432 cv_init(&dp->tx_drain_cv, NULL, CV_DRIVER, NULL); 4433 rw_init(&dp->dev_state_lock, NULL, RW_DRIVER, NULL); 4434 mutex_init(&dp->link_watcher_lock, NULL, MUTEX_DRIVER, NULL); 4435 cv_init(&dp->link_watcher_wait_cv, NULL, CV_DRIVER, NULL); 4436 sema_init(&dp->hal_op_lock, 1, NULL, SEMA_DRIVER, NULL); 4437 sema_init(&dp->rxfilter_lock, 1, NULL, SEMA_DRIVER, NULL); 4438 4439 /* 4440 * Initialize configuration 4441 */ 4442 dp->ugc = *gc; 4443 4444 dp->mtu = ETHERMTU; 4445 dp->rxmode = 0; 4446 dp->speed = USBGEM_SPD_10; /* default is 10Mbps */ 4447 dp->full_duplex = B_FALSE; /* default is half */ 4448 dp->flow_control = FLOW_CONTROL_NONE; 4449 4450 dp->nic_state = NIC_STATE_STOPPED; 4451 dp->mac_state = MAC_STATE_STOPPED; 4452 dp->mii_state = MII_STATE_UNKNOWN; 4453 4454 /* performance tuning parameters */ 4455 dp->txthr = ETHERMAX; /* tx fifo threshoold */ 4456 dp->txmaxdma = 16*4; /* tx max dma burst size */ 4457 dp->rxthr = 128; /* rx fifo threshoold */ 4458 dp->rxmaxdma = 16*4; /* rx max dma burst size */ 4459 4460 /* 4461 * Get media mode infomation from .conf file 4462 */ 4463 usbgem_read_conf(dp); 4464 4465 /* rx_buf_len depend on MTU */ 4466 dp->rx_buf_len = MAXPKTBUF(dp) + dp->ugc.usbgc_rx_header_len; 4467 4468 /* 4469 * Reset the chip 4470 */ 4471 if (usbgem_hal_reset_chip(dp) != USB_SUCCESS) { 4472 cmn_err(CE_WARN, 4473 "!%s: %s: failed to reset the usb device", 4474 dp->name, __func__); 4475 goto err_destroy_locks; 4476 } 4477 4478 /* 4479 * HW dependant paremeter initialization 4480 */ 4481 if (usbgem_hal_attach_chip(dp) != USB_SUCCESS) { 4482 cmn_err(CE_WARN, 4483 "!%s: %s: failed to attach the usb device", 4484 dp->name, __func__); 4485 goto err_destroy_locks; 4486 } 4487 4488 /* allocate resources */ 4489 if (usbgem_alloc_memory(dp) != USB_SUCCESS) { 4490 goto err_destroy_locks; 4491 } 4492 4493 DPRINTF(0, (CE_CONT, 4494 "!%s: %02x:%02x:%02x:%02x:%02x:%02x", 4495 dp->name, 4496 dp->dev_addr.ether_addr_octet[0], 4497 dp->dev_addr.ether_addr_octet[1], 4498 dp->dev_addr.ether_addr_octet[2], 4499 dp->dev_addr.ether_addr_octet[3], 4500 dp->dev_addr.ether_addr_octet[4], 4501 dp->dev_addr.ether_addr_octet[5])); 4502 4503 /* copy mac address */ 4504 dp->cur_addr = dp->dev_addr; 4505 4506 /* pre-calculated tx timeout in second for performance */ 4507 dp->bulkout_timeout = 4508 dp->ugc.usbgc_tx_timeout / drv_usectohz(1000*1000); 4509 4510 usbgem_gld3_init(dp, macp); 4511 4512 /* Probe MII phy (scan phy) */ 4513 dp->mii_lpable = 0; 4514 dp->mii_advert = 0; 4515 dp->mii_exp = 0; 4516 dp->mii_ctl1000 = 0; 4517 dp->mii_stat1000 = 0; 4518 4519 dp->mii_status_ro = 0; 4520 dp->mii_xstatus_ro = 0; 4521 4522 if (usbgem_mii_probe(dp) != USB_SUCCESS) { 4523 cmn_err(CE_WARN, "!%s: %s: mii_probe failed", 4524 dp->name, __func__); 4525 goto err_free_memory; 4526 } 4527 4528 /* mask unsupported abilities */ 4529 dp->anadv_autoneg &= BOOLEAN(dp->mii_status & MII_STATUS_CANAUTONEG); 4530 dp->anadv_1000fdx &= 4531 BOOLEAN(dp->mii_xstatus & 4532 (MII_XSTATUS_1000BASEX_FD | MII_XSTATUS_1000BASET_FD)); 4533 dp->anadv_1000hdx &= 4534 BOOLEAN(dp->mii_xstatus & 4535 (MII_XSTATUS_1000BASEX | MII_XSTATUS_1000BASET)); 4536 dp->anadv_100t4 &= BOOLEAN(dp->mii_status & MII_STATUS_100_BASE_T4); 4537 dp->anadv_100fdx &= BOOLEAN(dp->mii_status & MII_STATUS_100_BASEX_FD); 4538 dp->anadv_100hdx &= BOOLEAN(dp->mii_status & MII_STATUS_100_BASEX); 4539 dp->anadv_10fdx &= BOOLEAN(dp->mii_status & MII_STATUS_10_FD); 4540 dp->anadv_10hdx &= BOOLEAN(dp->mii_status & MII_STATUS_10); 4541 4542 if (usbgem_mii_init(dp) != USB_SUCCESS) { 4543 cmn_err(CE_WARN, "!%s: %s: mii_init failed", 4544 dp->name, __func__); 4545 goto err_free_memory; 4546 } 4547 4548 /* 4549 * Add interrupt to system. 4550 */ 4551 if (ret = mac_register(macp, &dp->mh)) { 4552 cmn_err(CE_WARN, "!%s: mac_register failed, error:%d", 4553 dp->name, ret); 4554 goto err_release_stats; 4555 } 4556 mac_free(macp); 4557 macp = NULL; 4558 4559 if (usb_register_hotplug_cbs(dip, 4560 usbgem_suspend, usbgem_resume) != USB_SUCCESS) { 4561 cmn_err(CE_WARN, 4562 "!%s: %s: failed to register hotplug cbs", 4563 dp->name, __func__); 4564 goto err_unregister_gld; 4565 } 4566 4567 /* reset mii and start mii link watcher */ 4568 if (usbgem_mii_start(dp) != USB_SUCCESS) { 4569 goto err_unregister_hotplug; 4570 } 4571 4572 /* start tx watchdow watcher */ 4573 if (usbgem_tx_watcher_start(dp)) { 4574 goto err_usbgem_mii_stop; 4575 } 4576 4577 ddi_set_driver_private(dip, (caddr_t)dp); 4578 4579 DPRINTF(2, (CE_CONT, "!%s: %s: return: success", dp->name, __func__)); 4580 4581 return (dp); 4582 4583 err_usbgem_mii_stop: 4584 usbgem_mii_stop(dp); 4585 4586 err_unregister_hotplug: 4587 usb_unregister_hotplug_cbs(dip); 4588 4589 err_unregister_gld: 4590 mac_unregister(dp->mh); 4591 4592 err_release_stats: 4593 err_free_memory: 4594 usbgem_free_memory(dp); 4595 4596 err_destroy_locks: 4597 cv_destroy(&dp->tx_drain_cv); 4598 cv_destroy(&dp->rx_drain_cv); 4599 mutex_destroy(&dp->txlock); 4600 mutex_destroy(&dp->rxlock); 4601 rw_destroy(&dp->dev_state_lock); 4602 mutex_destroy(&dp->link_watcher_lock); 4603 cv_destroy(&dp->link_watcher_wait_cv); 4604 sema_destroy(&dp->hal_op_lock); 4605 sema_destroy(&dp->rxfilter_lock); 4606 4607 err_close_pipes: 4608 (void) usbgem_close_pipes(dp); 4609 4610 err_unregister_client: 4611 usb_client_detach(dp->dip, dp->reg_data); 4612 4613 err_free_private: 4614 if (macp) { 4615 mac_free(macp); 4616 } 4617 4618 kmem_free((caddr_t)dp, USBGEM_LOCAL_DATA_SIZE(gc)); 4619 4620 return (NULL); 4621 } 4622 4623 int 4624 usbgem_do_detach(dev_info_t *dip) 4625 { 4626 struct usbgem_dev *dp; 4627 4628 dp = USBGEM_GET_DEV(dip); 4629 4630 /* unregister with gld v3 */ 4631 if (mac_unregister(dp->mh) != DDI_SUCCESS) { 4632 return (DDI_FAILURE); 4633 } 4634 4635 /* unregister with hotplug service */ 4636 usb_unregister_hotplug_cbs(dip); 4637 4638 /* stop tx watchdog watcher */ 4639 usbgem_tx_watcher_stop(dp); 4640 4641 /* stop the link manager */ 4642 usbgem_mii_stop(dp); 4643 4644 /* unregister with usb service */ 4645 (void) usbgem_free_memory(dp); 4646 (void) usbgem_close_pipes(dp); 4647 usb_client_detach(dp->dip, dp->reg_data); 4648 dp->reg_data = NULL; 4649 4650 /* release locks and condition variables */ 4651 mutex_destroy(&dp->txlock); 4652 mutex_destroy(&dp->rxlock); 4653 cv_destroy(&dp->tx_drain_cv); 4654 cv_destroy(&dp->rx_drain_cv); 4655 rw_destroy(&dp->dev_state_lock); 4656 mutex_destroy(&dp->link_watcher_lock); 4657 cv_destroy(&dp->link_watcher_wait_cv); 4658 sema_destroy(&dp->hal_op_lock); 4659 sema_destroy(&dp->rxfilter_lock); 4660 4661 /* release basic memory resources */ 4662 kmem_free((caddr_t)(dp->private), dp->priv_size); 4663 kmem_free((caddr_t)dp, USBGEM_LOCAL_DATA_SIZE(&dp->ugc)); 4664 4665 DPRINTF(2, (CE_CONT, "!%s: %s: return: success", 4666 ddi_driver_name(dip), __func__)); 4667 4668 return (DDI_SUCCESS); 4669 } 4670 4671 int 4672 usbgem_mod_init(struct dev_ops *dop, char *name) 4673 { 4674 major_t major; 4675 major = ddi_name_to_major(name); 4676 if (major == DDI_MAJOR_T_NONE) { 4677 return (DDI_FAILURE); 4678 } 4679 mac_init_ops(dop, name); 4680 4681 return (DDI_SUCCESS); 4682 } 4683 4684 void 4685 usbgem_mod_fini(struct dev_ops *dop) 4686 { 4687 mac_fini_ops(dop); 4688 } 4689 4690 int 4691 usbgem_quiesce(dev_info_t *dip) 4692 { 4693 struct usbgem_dev *dp; 4694 4695 dp = USBGEM_GET_DEV(dip); 4696 4697 ASSERT(dp != NULL); 4698 4699 if (dp->mac_state != MAC_STATE_DISCONNECTED && 4700 dp->mac_state != MAC_STATE_STOPPED) { 4701 if (usbgem_hal_stop_chip(dp) != USB_SUCCESS) { 4702 (void) usbgem_hal_reset_chip(dp); 4703 } 4704 } 4705 4706 /* devo_quiesce() must return DDI_SUCCESS always */ 4707 return (DDI_SUCCESS); 4708 } 4709