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