1 /* 2 * axf_usbgem.c : ASIX AX88172/772 USB to Fast Ethernet Driver for Solaris 3 * 4 * Copyright (c) 2004-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 * Changelog: 36 */ 37 38 /* 39 * TODO 40 * handle RXMODE_ENABLE in set_rx_filter() 41 */ 42 /* ======================================================= */ 43 44 /* 45 * Solaris system header files and macros 46 */ 47 48 /* minimum kernel headers for drivers */ 49 #include <sys/types.h> 50 #include <sys/conf.h> 51 #include <sys/debug.h> 52 #include <sys/kmem.h> 53 #include <sys/modctl.h> 54 #include <sys/errno.h> 55 #include <sys/ddi.h> 56 #include <sys/sunddi.h> 57 #include <sys/byteorder.h> 58 59 /* ethernet stuff */ 60 #include <sys/ethernet.h> 61 62 /* interface card depend stuff */ 63 #include <sys/stropts.h> 64 #include <sys/stream.h> 65 #include <sys/strlog.h> 66 #include <sys/usb/usba.h> 67 #include "usbgem.h" 68 69 /* hardware stuff */ 70 #include "usbgem_mii.h" 71 #include "ax88172reg.h" 72 73 char ident[] = "ax88x72 usbnic driver v" VERSION; 74 75 /* 76 * Useful macros 77 */ 78 #define CHECK_AND_JUMP(err, label) if (err != USB_SUCCESS) goto label 79 #define LE16P(p) ((((uint8_t *)(p))[1] << 8) | ((uint8_t *)(p))[0]) 80 81 #define AX88172(dp) \ 82 (((struct axf_dev *)(dp)->private)->chip->type == CHIP_TYPE_AX88172) 83 84 #define AX88772(dp) \ 85 (((struct axf_dev *)(dp)->private)->chip->type == CHIP_TYPE_AX88772) 86 87 /* 88 * Debugging 89 */ 90 #ifdef DEBUG_LEVEL 91 static int axf_debug = DEBUG_LEVEL; 92 #define DPRINTF(n, args) if (axf_debug > (n)) cmn_err args 93 #else 94 #define DPRINTF(n, args) 95 #endif 96 97 /* 98 * Our configration for ax88172 99 */ 100 /* timeouts */ 101 #define ONESEC (drv_usectohz(1*1000000)) 102 103 /* 104 * RX/TX buffer size 105 */ 106 107 /* 108 * Local device definitions 109 */ 110 struct chip_info { 111 uint16_t vid; /* usb vendor id */ 112 uint16_t pid; /* usb product id */ 113 int type; 114 uint8_t gpio_reset[2]; 115 uint8_t gpio_speed[2]; 116 uint8_t gpio_duplex[2]; 117 char *name; 118 #define CHIP_TYPE_AX88172 0 119 #define CHIP_TYPE_AX88772 1 120 #define CHIP_TYPE_AX88178 2 121 }; 122 123 #define GPIO_DEFAULT {0x00, 0x15}, {0, 0}, {0, 0} 124 struct chip_info chiptbl_88x7x[] = { 125 /* AX88172 */ 126 { 127 /* Planex UE2-100TX, Hawking UF200, TrendNet TU2-ET100 */ 128 0x07b8, 0x420a, CHIP_TYPE_AX88172, 129 130 /* 131 * the default setting covers below: 132 * gpio bit2 has to be 0 and gpio bit0 has to be 1 133 */ 134 {0, 0}, 135 {GPIO_EN1, GPIO_DATA1 | GPIO_EN1}, 136 {0, 0}, 137 "Planex UE2-100TX", /* tested */ 138 }, 139 { 140 0x2001, 0x1a00, CHIP_TYPE_AX88172, 141 {0x9f, 0x9e}, {0, 0}, {0, 0}, 142 "D-Link dube100", /* XXX */ 143 }, 144 { 145 0x077b, 0x2226, CHIP_TYPE_AX88172, 146 GPIO_DEFAULT, 147 "Linksys USB200M", 148 }, 149 { 150 0x0846, 0x1040, CHIP_TYPE_AX88172, 151 GPIO_DEFAULT, 152 "Netgear FA120", 153 }, 154 { 155 0x0b95, 0x1720, CHIP_TYPE_AX88172, 156 GPIO_DEFAULT, 157 "Intellinet, ST Lab USB Ethernet", 158 }, 159 { 160 0x08dd, 0x90ff, CHIP_TYPE_AX88172, 161 GPIO_DEFAULT, 162 "Billionton Systems, USB2AR", 163 }, 164 { 165 0x0557, 0x2009, CHIP_TYPE_AX88172, 166 GPIO_DEFAULT, 167 "ATEN UC210T", 168 }, 169 { 170 0x0411, 0x003d, CHIP_TYPE_AX88172, 171 GPIO_DEFAULT, 172 "Buffalo LUA-U2-KTX", 173 }, 174 { 175 0x6189, 0x182d, CHIP_TYPE_AX88172, 176 GPIO_DEFAULT, 177 "Sitecom LN-029 USB 2.0 10/100 Ethernet adapter", 178 }, 179 { 180 0x07aa, 0x0017, CHIP_TYPE_AX88172, 181 GPIO_DEFAULT, 182 "corega FEther USB2-TX", 183 }, 184 { 185 0x1189, 0x0893, CHIP_TYPE_AX88172, 186 GPIO_DEFAULT, 187 "Surecom EP-1427X-2", 188 }, 189 { 190 0x1631, 0x6200, CHIP_TYPE_AX88172, 191 GPIO_DEFAULT, 192 "goodway corp usb gwusb2e", 193 }, 194 /* AX88772 and AX88178 */ 195 { 196 0x13b1, 0x0018, CHIP_TYPE_AX88772, 197 {0, 0}, {0, 0}, {0, 0}, 198 "Linksys USB200M rev.2", 199 }, 200 { 201 0x1557, 0x7720, CHIP_TYPE_AX88772, 202 {0, 0}, {0, 0}, {0, 0}, 203 "0Q0 cable ethernet", 204 }, 205 { 206 0x07d1, 0x3c05, CHIP_TYPE_AX88772, 207 {0, 0}, {0, 0}, {0, 0}, 208 "DLink DUB E100 ver B1", 209 }, 210 { 211 0x2001, 0x3c05, CHIP_TYPE_AX88772, 212 {0, 0}, {0, 0}, {0, 0}, 213 "DLink DUB E100 ver B1(2)", 214 }, 215 { 216 0x05ac, 0x1402, CHIP_TYPE_AX88772, 217 {0, 0}, {0, 0}, {0, 0}, 218 "Apple Ethernet USB Adapter", 219 }, 220 { 221 0x1737, 0x0039, CHIP_TYPE_AX88178, 222 {0, 0}, {0, 0}, {0, 0}, 223 "Linksys USB1000", 224 }, 225 { 226 0x0411, 0x006e, CHIP_TYPE_AX88178, 227 {0, 0}, {0, 0}, {0, 0}, 228 "Buffalo LUA-U2-KGT/LUA-U2-GT", 229 }, 230 { 231 0x04bb, 0x0930, CHIP_TYPE_AX88178, 232 {0, 0}, {0, 0}, {0, 0}, 233 "I/O DATA ETG-US2", 234 }, 235 { 236 0x050d, 0x5055, CHIP_TYPE_AX88178, 237 {0, 0}, {0, 0}, {0, 0}, 238 "Belkin F5D5055", 239 }, 240 { 241 /* generic ax88772 must be the last entry */ 242 /* planex UE-200TX-G */ 243 0x0b95, 0x7720, CHIP_TYPE_AX88772, 244 {0, 0}, {0, 0}, {0, 0}, 245 "ASIX AX88772/AX88178", /* tested */ 246 }, 247 }; 248 249 #define CHIPTABLESIZE (sizeof (chiptbl_88x7x) / sizeof (struct chip_info)) 250 251 struct axf_dev { 252 /* 253 * Misc HW information 254 */ 255 struct chip_info *chip; 256 uint8_t ipg[3]; 257 uint8_t gpio; 258 uint16_t rcr; 259 uint16_t msr; 260 uint8_t last_link_state; 261 boolean_t phy_has_reset; 262 }; 263 264 /* 265 * private functions 266 */ 267 268 /* mii operations */ 269 static uint16_t axf_mii_read(struct usbgem_dev *, uint_t, int *errp); 270 static void axf_mii_write(struct usbgem_dev *, uint_t, uint16_t, int *errp); 271 272 /* nic operations */ 273 static int axf_reset_chip(struct usbgem_dev *); 274 static int axf_init_chip(struct usbgem_dev *); 275 static int axf_start_chip(struct usbgem_dev *); 276 static int axf_stop_chip(struct usbgem_dev *); 277 static int axf_set_media(struct usbgem_dev *); 278 static int axf_set_rx_filter(struct usbgem_dev *); 279 static int axf_get_stats(struct usbgem_dev *); 280 static void axf_interrupt(struct usbgem_dev *, mblk_t *); 281 282 /* packet operations */ 283 static mblk_t *axf_tx_make_packet(struct usbgem_dev *, mblk_t *); 284 static mblk_t *axf_rx_make_packet(struct usbgem_dev *, mblk_t *); 285 286 /* =============================================================== */ 287 /* 288 * I/O functions 289 */ 290 /* =============================================================== */ 291 /* BEGIN CSTYLED */ 292 #define OUT(dp, req, val, ix, len, buf, errp, label) \ 293 if ((*(errp) = usbgem_ctrl_out((dp), \ 294 /* bmRequestType */ USB_DEV_REQ_HOST_TO_DEV \ 295 | USB_DEV_REQ_TYPE_VENDOR | USB_DEV_REQ_RCPT_DEV, \ 296 /* bRequest */ (req), \ 297 /* wValue */ (val), \ 298 /* wIndex */ (ix), \ 299 /* wLength */ (len), \ 300 /* value */ (buf), \ 301 /* size */ (len))) != USB_SUCCESS) goto label 302 303 #define IN(dp, req, val, ix, len, buf, errp, label) \ 304 if ((*(errp) = usbgem_ctrl_in((dp), \ 305 /* bmRequestType */ USB_DEV_REQ_DEV_TO_HOST \ 306 | USB_DEV_REQ_TYPE_VENDOR | USB_DEV_REQ_RCPT_DEV, \ 307 /* bRequest */ (req), \ 308 /* wValue */ (val), \ 309 /* wIndex */ (ix), \ 310 /* wLength */ (len), \ 311 /* valuep */ (buf), \ 312 /* size */ (len))) != USB_SUCCESS) goto label 313 /* END CSTYLED */ 314 315 /* =============================================================== */ 316 /* 317 * Hardware manupilation 318 */ 319 /* =============================================================== */ 320 static int 321 axf_reset_phy(struct usbgem_dev *dp) 322 { 323 uint8_t phys[2]; 324 uint8_t val8; 325 int err; 326 struct axf_dev *lp = dp->private; 327 328 DPRINTF(2, (CE_CONT, "!%s: %s: called", dp->name, __func__)); 329 330 if (AX88172(dp)) { 331 delay(drv_usectohz(5000)); 332 IN(dp, VCMD_READ_GPIO, 0, 0, 1, &val8, &err, usberr); 333 334 DPRINTF(0, (CE_CONT, "!%s: %s: gpio 0x%b", 335 dp->name, __func__, val8, GPIO_BITS)); 336 337 /* reset MII PHY */ 338 val8 = lp->chip->gpio_reset[1] 339 | lp->chip->gpio_speed[dp->speed] 340 | lp->chip->gpio_duplex[dp->full_duplex]; 341 342 OUT(dp, VCMD_WRITE_GPIO, 343 val8, 0, 0, NULL, &err, usberr); 344 delay(drv_usectohz(5000)); 345 346 val8 = lp->chip->gpio_reset[0] 347 | lp->chip->gpio_speed[dp->speed] 348 | lp->chip->gpio_duplex[dp->full_duplex]; 349 350 OUT(dp, VCMD_WRITE_GPIO, 351 val8, 0, 0, NULL, &err, usberr); 352 delay(drv_usectohz(5000)); 353 } else { 354 lp->gpio = GPIO_RSE | GPIO_DATA2 | GPIO_EN2; 355 OUT(dp, VCMD_WRITE_GPIO, lp->gpio, 0, 356 0, NULL, &err, usberr); 357 drv_usecwait(1000); 358 359 OUT(dp, VCMD_WRITE_PHY_SELECT_88772, 360 dp->mii_phy_addr == 16 ? 1 : 0, 0, 0, NULL, &err, usberr); 361 362 OUT(dp, VCMD_SOFTWARE_RESET_88772, 363 SWRST_IPPD | SWRST_PRL, 0, 0, NULL, &err, usberr); 364 delay(drv_usectohz(150*1000)); 365 OUT(dp, VCMD_SOFTWARE_RESET_88772, 366 0, 0, 0, NULL, &err, usberr); 367 368 OUT(dp, VCMD_SOFTWARE_RESET_88772, 369 dp->mii_phy_addr == 16 ? SWRST_IPRL : SWRST_PRTE, 370 0, 0, NULL, &err, usberr); 371 delay(drv_usectohz(150*1000)); 372 } 373 374 375 return (USB_SUCCESS); 376 377 usberr: 378 return (USB_FAILURE); 379 } 380 381 static int 382 axf_reset_chip(struct usbgem_dev *dp) 383 { 384 int err = USB_SUCCESS; 385 386 if (AX88172(dp)) { 387 /* there are no ways to reset nic */ 388 return (USB_SUCCESS); 389 } 390 #ifdef NEVER 391 OUT(dp, VCMD_SOFTWARE_RESET_88772, 392 SWRST_RR | SWRST_RT, 0, 0, NULL, &err, usberr); 393 OUT(dp, VCMD_SOFTWARE_RESET_88772, 394 0, 0, 0, NULL, &err, usberr); 395 usberr: 396 #endif 397 return (err); 398 } 399 400 /* 401 * Setup ax88172 402 */ 403 static int 404 axf_init_chip(struct usbgem_dev *dp) 405 { 406 int i; 407 uint32_t val; 408 int err = USB_SUCCESS; 409 uint16_t reg; 410 uint8_t buf[2]; 411 uint16_t tmp16; 412 struct axf_dev *lp = dp->private; 413 414 DPRINTF(2, (CE_CONT, "!%s: %s: called", dp->name, __func__)); 415 416 /* rx conrol register: read default value */ 417 if (!AX88172(dp)) { 418 /* clear rx control */ 419 OUT(dp, VCMD_WRITE_RXCTRL, 0, 0, 0, NULL, &err, usberr); 420 } 421 422 IN(dp, VCMD_READ_RXCTRL, 0, 0, 2, buf, &err, usberr); 423 lp->rcr = LE16P(buf); 424 DPRINTF(0, (CE_CONT, "!%s: %s: rcr(default):%b", 425 dp->name, __func__, lp->rcr, RCR_BITS)); 426 427 lp->rcr &= ~RCR_SO; 428 429 /* Media status register */ 430 if (AX88172(dp)) { 431 #ifdef notdef 432 lp->msr = MSR_TXABT; 433 #else 434 lp->msr = 0; 435 #endif 436 } else { 437 lp->msr = MSR_RE | MSR_TXABT; 438 } 439 DPRINTF(0, (CE_CONT, "!%s: %s: msr:%b", 440 dp->name, __func__, lp->msr, MSR_BITS)); 441 err = axf_set_media(dp); 442 CHECK_AND_JUMP(err, usberr); 443 444 /* write IPG0-2 registers */ 445 if (AX88172(dp)) { 446 OUT(dp, VCMD_WRITE_IPG, lp->ipg[0], 0, 0, NULL, &err, usberr); 447 OUT(dp, VCMD_WRITE_IPG1, lp->ipg[1], 0, 0, NULL, &err, usberr); 448 OUT(dp, VCMD_WRITE_IPG2, lp->ipg[2], 0, 0, NULL, &err, usberr); 449 } else { 450 /* EMPTY */ 451 } 452 #ifdef ENABLE_RX_IN_INIT_CHIP 453 /* enable Rx */ 454 lp->rcr |= RCR_SO; 455 OUT(dp, VCMD_WRITE_RXCTRL, lp->rcr, 0, 0, NULL, &err, usberr); 456 #endif 457 usberr: 458 DPRINTF(2, (CE_CONT, "!%s: %s: end (%s)", 459 dp->name, __func__, 460 err, err == USB_SUCCESS ? "success" : "error")); 461 return (err); 462 } 463 464 static int 465 axf_start_chip(struct usbgem_dev *dp) 466 { 467 int err = USB_SUCCESS; 468 struct axf_dev *lp = dp->private; 469 #ifndef ENABLE_RX_IN_INIT_CHIP 470 /* enable Rx */ 471 lp->rcr |= RCR_SO; 472 OUT(dp, VCMD_WRITE_RXCTRL, lp->rcr, 0, 0, NULL, &err, usberr); 473 474 usberr: 475 DPRINTF(2, (CE_CONT, "!%s: %s: end (%s)", 476 dp->name, __func__, 477 err, err == USB_SUCCESS ? "success" : "error")); 478 #endif 479 return (err); 480 } 481 482 static int 483 axf_stop_chip(struct usbgem_dev *dp) 484 { 485 int err = USB_SUCCESS; 486 struct axf_dev *lp = dp->private; 487 488 /* Disable Rx */ 489 lp->rcr &= ~RCR_SO; 490 OUT(dp, VCMD_WRITE_RXCTRL, lp->rcr, 0, 0, NULL, &err, usberr); 491 492 /* 493 * Restore factory mac address 494 * if we have changed current mac address 495 */ 496 if (!AX88172(dp) && 497 bcmp(dp->dev_addr.ether_addr_octet, 498 dp->cur_addr.ether_addr_octet, 499 ETHERADDRL) != 0) { 500 OUT(dp, VCMD_WRITE_NODE_ID_88772, 0, 0, 501 ETHERADDRL, dp->cur_addr.ether_addr_octet, &err, usberr); 502 } 503 usberr: 504 return (axf_reset_chip(dp)); 505 } 506 507 static int 508 axf_get_stats(struct usbgem_dev *dp) 509 { 510 /* empty */ 511 return (USB_SUCCESS); 512 } 513 514 static uint_t 515 axf_mcast_hash(struct usbgem_dev *dp, const uint8_t *addr) 516 { 517 return (usbgem_ether_crc_be(addr) >> (32 - 6)); 518 } 519 520 static int 521 axf_set_rx_filter(struct usbgem_dev *dp) 522 { 523 int i; 524 uint8_t mode; 525 uint8_t mhash[8]; 526 uint8_t buf[2]; 527 uint_t h; 528 int err = USB_SUCCESS; 529 struct axf_dev *lp = dp->private; 530 531 DPRINTF(2, (CE_CONT, "!%s: %s: called, rxmode:%x", 532 dp->name, __func__, dp->rxmode)); 533 534 if (lp->rcr & RCR_SO) { 535 /* set promiscuous mode before changing it. */ 536 OUT(dp, VCMD_WRITE_RXCTRL, 537 lp->rcr | RCR_PRO, 0, 0, NULL, &err, usberr); 538 } 539 540 lp->rcr &= ~(RCR_AP_88772 | RCR_AM | RCR_SEP | RCR_AMALL | RCR_PRO); 541 mode = RCR_AB; /* accept broadcast packets */ 542 543 bzero(mhash, sizeof (mhash)); 544 545 if (dp->rxmode & RXMODE_PROMISC) { 546 /* promiscious mode implies all multicast and all physical */ 547 mode |= RCR_PRO; 548 } else if ((dp->rxmode & RXMODE_ALLMULTI) || dp->mc_count > 32) { 549 /* accept all multicast packets */ 550 mode |= RCR_AMALL; 551 } else if (dp->mc_count > 0) { 552 /* 553 * make hash table to select interresting 554 * multicast address only. 555 */ 556 mode |= RCR_AM; 557 for (i = 0; i < dp->mc_count; i++) { 558 h = dp->mc_list[i].hash; 559 mhash[h / 8] |= 1 << (h % 8); 560 } 561 } 562 if (AX88172(dp)) { 563 if (bcmp(dp->dev_addr.ether_addr_octet, 564 dp->cur_addr.ether_addr_octet, ETHERADDRL) != 0) { 565 /* 566 * we use promiscious mode instead of changing the 567 * mac address in ax88172 568 */ 569 mode |= RCR_PRO; 570 } 571 } else { 572 OUT(dp, VCMD_WRITE_NODE_ID_88772, 0, 0, 573 ETHERADDRL, dp->cur_addr.ether_addr_octet, &err, usberr); 574 } 575 lp->rcr |= mode; 576 577 /* set multicast hash table */ 578 if (mode & RCR_AM) { 579 /* need to set up multicast hash table */ 580 OUT(dp, VCMD_WRITE_MCAST_FILTER, 0, 0, 581 sizeof (mhash), mhash, &err, usberr); 582 } 583 584 /* update rcr */ 585 OUT(dp, VCMD_WRITE_RXCTRL, lp->rcr, 0, 586 0, NULL, &err, usberr); 587 588 #if DEBUG_LEVEL > 1 589 /* verify rxctrl reg */ 590 IN(dp, VCMD_READ_RXCTRL, 0, 0, 2, buf, &err, usberr); 591 cmn_err(CE_CONT, "!%s: %s: rcr:%b returned", 592 dp->name, __func__, LE16P(buf), RCR_BITS); 593 #endif 594 usberr: 595 DPRINTF(2, (CE_CONT, "!%s: %s: end (%s)", 596 dp->name, __func__, 597 err, err == USB_SUCCESS ? "success" : "error")); 598 return (err); 599 } 600 601 static int 602 axf_set_media(struct usbgem_dev *dp) 603 { 604 uint8_t val8; 605 uint8_t gpio; 606 uint8_t gpio_old; 607 int err = USB_SUCCESS; 608 uint16_t msr; 609 struct axf_dev *lp = dp->private; 610 611 IN(dp, VCMD_READ_GPIO, 0, 0, 1, &gpio, &err, usberr); 612 613 DPRINTF(0, (CE_CONT, "!%s: %s: called, gpio:%b", 614 dp->name, __func__, gpio, GPIO_BITS)); 615 616 msr = lp->msr; 617 gpio_old = gpio; 618 gpio = lp->chip->gpio_reset[0]; 619 620 /* setup speed */ 621 if (AX88172(dp)) { 622 /* EMPTY */ 623 } else { 624 msr &= ~(MSR_PS | MSR_GM | MSR_ENCK); 625 626 switch (dp->speed) { 627 case USBGEM_SPD_1000: 628 msr |= MSR_GM | MSR_ENCK; 629 break; 630 631 case USBGEM_SPD_100: 632 msr |= MSR_PS; 633 break; 634 635 case USBGEM_SPD_10: 636 break; 637 } 638 } 639 gpio |= lp->chip->gpio_speed[dp->speed == USBGEM_SPD_100 ? 1 : 0]; 640 641 /* select duplex */ 642 msr &= ~MSR_FDPX; 643 if (dp->full_duplex) { 644 msr |= MSR_FDPX; 645 646 /* select flow control */ 647 if (AX88172(dp)) { 648 msr &= ~MSR_FCEN; 649 switch (dp->flow_control) { 650 case FLOW_CONTROL_TX_PAUSE: 651 case FLOW_CONTROL_SYMMETRIC: 652 case FLOW_CONTROL_RX_PAUSE: 653 msr |= MSR_FCEN; 654 break; 655 } 656 } else { 657 msr &= ~(MSR_RFC | MSR_TFC); 658 switch (dp->flow_control) { 659 case FLOW_CONTROL_TX_PAUSE: 660 msr |= MSR_TFC; 661 break; 662 663 case FLOW_CONTROL_SYMMETRIC: 664 msr |= MSR_TFC | MSR_RFC; 665 break; 666 667 case FLOW_CONTROL_RX_PAUSE: 668 msr |= MSR_RFC; 669 break; 670 } 671 } 672 } 673 gpio |= lp->chip->gpio_duplex[dp->full_duplex ? 1 : 0]; 674 675 /* update medium status register */ 676 lp->msr = msr; 677 OUT(dp, VCMD_WRITE_MEDIUM_STATUS, lp->msr, 0, 678 0, NULL, &err, usberr); 679 680 if (gpio != gpio_old) { 681 /* LED control required for some products */ 682 OUT(dp, VCMD_WRITE_GPIO, 683 gpio, 0, 0, NULL, &err, usberr); 684 } 685 686 usberr: 687 DPRINTF(2, (CE_CONT, "!%s: %s: end (%s)", 688 dp->name, __func__, 689 err, err == USB_SUCCESS ? "success" : "error")); 690 return (err); 691 } 692 693 #define FILL_PKT_HEADER(bp, len) { \ 694 (bp)[0] = (uint8_t)(len); \ 695 (bp)[1] = (uint8_t)((len) >> 8); \ 696 (bp)[2] = (uint8_t)(~(len)); \ 697 (bp)[3] = (uint8_t)((~(len)) >> 8); \ 698 } 699 700 #define PKT_HEADER_SIZE 4 701 702 /* 703 * send/receive packet check 704 */ 705 static mblk_t * 706 axf_tx_make_packet(struct usbgem_dev *dp, mblk_t *mp) 707 { 708 int n; 709 size_t len; 710 size_t pkt_size; 711 mblk_t *new; 712 mblk_t *tp; 713 uint8_t *bp; 714 uint8_t *last_pos; 715 uint_t align_mask; 716 size_t header_size; 717 int pad_size; 718 719 len = msgdsize(mp); 720 721 if (AX88172(dp)) { 722 #ifdef notdef 723 align_mask = 63; 724 #else 725 align_mask = 511; 726 #endif 727 header_size = 0; 728 729 if (len >= ETHERMIN && mp->b_cont == NULL && 730 (len & align_mask) != 0) { 731 /* use the mp "as is" */ 732 return (mp); 733 } 734 } else { 735 align_mask = 511; 736 header_size = PKT_HEADER_SIZE; 737 } 738 739 /* 740 * re-allocate the mp 741 */ 742 /* minimum ethernet packet size of ETHERMIN */ 743 pkt_size = max(len, ETHERMIN); 744 745 if (((pkt_size + header_size) & align_mask) == 0) { 746 /* padding is required in usb communication */ 747 pad_size = PKT_HEADER_SIZE; 748 } else { 749 pad_size = 0; 750 } 751 752 if ((new = allocb(header_size + pkt_size + pad_size, 0)) == NULL) { 753 return (NULL); 754 } 755 756 bp = new->b_rptr; 757 if (header_size) { 758 uint16_t tmp; 759 760 /* add a header */ 761 tmp = (uint16_t)pkt_size; 762 FILL_PKT_HEADER(bp, tmp); 763 bp += header_size; 764 } 765 766 /* copy contents of the buffer */ 767 for (tp = mp; tp; tp = tp->b_cont) { 768 n = (uintptr_t)tp->b_wptr - (uintptr_t)tp->b_rptr; 769 bcopy(tp->b_rptr, bp, n); 770 bp += n; 771 } 772 773 /* add pads for ethernet packets */ 774 last_pos = new->b_rptr + header_size + pkt_size; 775 while (bp < last_pos) { 776 *bp++ = 0; 777 } 778 779 /* add a zero-length pad segment for usb communications */ 780 if (pad_size) { 781 /* add a dummy header for zero-length packet */ 782 FILL_PKT_HEADER(bp, 0); 783 bp += pad_size; 784 } 785 786 /* close the payload of the packet */ 787 new->b_wptr = bp; 788 789 return (new); 790 } 791 792 #if DEBUG_LEVEL > 10 793 static void 794 axf_dump_packet(struct usbgem_dev *dp, uint8_t *bp, int n) 795 { 796 int i; 797 798 for (i = 0; i < n; i += 8, bp += 8) { 799 cmn_err(CE_CONT, "%02x %02x %02x %02x %02x %02x %02x %02x", 800 bp[0], bp[1], bp[2], bp[3], bp[4], bp[5], bp[6], bp[7]); 801 } 802 } 803 #endif 804 805 static mblk_t * 806 axf_rx_make_packet(struct usbgem_dev *dp, mblk_t *mp) 807 { 808 mblk_t *tp; 809 uintptr_t rest; 810 811 if (AX88172(dp)) { 812 return (mp); 813 } 814 815 tp = mp; 816 rest = (uintptr_t)tp->b_wptr - (uintptr_t)tp->b_rptr; 817 818 if (rest <= PKT_HEADER_SIZE) { 819 /* 820 * the usb bulk-in frame doesn't include any valid 821 * ethernet packets. 822 */ 823 return (NULL); 824 } 825 826 for (; ; ) { 827 uint16_t len; 828 uint16_t cksum; 829 830 /* analyse the header of the received usb frame */ 831 len = LE16P(tp->b_rptr + 0); 832 cksum = LE16P(tp->b_rptr + 2); 833 834 /* test if the header is valid */ 835 if (len + cksum != 0xffff) { 836 /* discard whole the packet */ 837 cmn_err(CE_WARN, 838 "!%s: %s: corrupted header:%04x %04x", 839 dp->name, __func__, len, cksum); 840 return (NULL); 841 } 842 #if DEBUG_LEVEL > 0 843 if (len < ETHERMIN || len > ETHERMAX) { 844 cmn_err(CE_NOTE, 845 "!%s: %s: incorrect pktsize:%d", 846 dp->name, __func__, len); 847 } 848 #endif 849 /* extract a ethernet packet from the bulk-in frame */ 850 tp->b_rptr += PKT_HEADER_SIZE; 851 tp->b_wptr = tp->b_rptr + len; 852 853 if (len & 1) { 854 /* 855 * skip a tailing pad byte if the packet 856 * length is odd 857 */ 858 len++; 859 } 860 rest -= len + PKT_HEADER_SIZE; 861 862 if (rest <= PKT_HEADER_SIZE) { 863 /* no more vaild ethernet packets */ 864 break; 865 } 866 867 #if DEBUG_LEVEL > 10 868 axf_dump_packet(dp, tp->b_wptr, 18); 869 #endif 870 /* allocate a mblk_t header for the next ethernet packet */ 871 tp->b_next = dupb(mp); 872 tp->b_next->b_rptr = tp->b_rptr + len; 873 tp = tp->b_next; 874 } 875 876 return (mp); 877 } 878 879 /* 880 * MII Interfaces 881 */ 882 static uint16_t 883 axf_mii_read(struct usbgem_dev *dp, uint_t index, int *errp) 884 { 885 uint8_t buf[2]; 886 uint16_t val; 887 888 DPRINTF(4, (CE_CONT, "!%s: %s: called, ix:%d", 889 dp->name, __func__, index)); 890 891 /* switch to software MII operation mode */ 892 OUT(dp, VCMD_SOFTWARE_MII_OP, 0, 0, 0, NULL, errp, usberr); 893 894 /* Read MII register */ 895 IN(dp, VCMD_READ_MII_REG, dp->mii_phy_addr, index, 896 2, buf, errp, usberr); 897 898 /* switch to hardware MII operation mode */ 899 OUT(dp, VCMD_HARDWARE_MII_OP, 0, 0, 0, NULL, errp, usberr); 900 901 return (LE16P(buf)); 902 903 usberr: 904 cmn_err(CE_CONT, 905 "!%s: %s: usberr(%d) detected", dp->name, __func__, *errp); 906 return (0); 907 } 908 909 static void 910 axf_mii_write(struct usbgem_dev *dp, uint_t index, uint16_t val, int *errp) 911 { 912 uint8_t buf[2]; 913 914 DPRINTF(4, (CE_CONT, "!%s: %s called, reg:%x val:%x", 915 dp->name, __func__, index, val)); 916 917 /* switch software MII operation mode */ 918 OUT(dp, VCMD_SOFTWARE_MII_OP, 0, 0, 0, NULL, errp, usberr); 919 920 /* Write to the specified MII register */ 921 buf[0] = (uint8_t)val; 922 buf[1] = (uint8_t)(val >> 8); 923 OUT(dp, VCMD_WRITE_MII_REG, dp->mii_phy_addr, index, 924 2, buf, errp, usberr); 925 926 /* switch to hardware MII operation mode */ 927 OUT(dp, VCMD_HARDWARE_MII_OP, 0, 0, 0, NULL, errp, usberr); 928 929 usberr: 930 ; 931 } 932 933 static void 934 axf_interrupt(struct usbgem_dev *dp, mblk_t *mp) 935 { 936 uint8_t *bp; 937 struct axf_dev *lp = dp->private; 938 939 bp = mp->b_rptr; 940 941 DPRINTF(2, (CE_CONT, 942 "!%s: %s: size:%d, %02x %02x %02x %02x %02x %02x %02x %02x", 943 dp->name, __func__, mp->b_wptr - mp->b_rptr, 944 bp[0], bp[1], bp[2], bp[3], bp[4], bp[5], bp[6], bp[7])); 945 946 if (lp->last_link_state ^ bp[2]) { 947 usbgem_mii_update_link(dp); 948 } 949 950 lp->last_link_state = bp[2]; 951 } 952 953 /* ======================================================== */ 954 /* 955 * OS depend (device driver DKI) routine 956 */ 957 /* ======================================================== */ 958 #ifdef DEBUG_LEVEL 959 static void 960 axf_eeprom_dump(struct usbgem_dev *dp, int size) 961 { 962 int i; 963 int err; 964 uint8_t w0[2], w1[2], w2[2], w3[2]; 965 966 cmn_err(CE_CONT, "!%s: eeprom dump:", dp->name); 967 968 err = USB_SUCCESS; 969 970 for (i = 0; i < size; i += 4) { 971 IN(dp, VCMD_READ_SROM, i + 0, 0, 2, w0, &err, usberr); 972 IN(dp, VCMD_READ_SROM, i + 1, 0, 2, w1, &err, usberr); 973 IN(dp, VCMD_READ_SROM, i + 2, 0, 2, w2, &err, usberr); 974 IN(dp, VCMD_READ_SROM, i + 3, 0, 2, w3, &err, usberr); 975 cmn_err(CE_CONT, "!0x%02x: 0x%04x 0x%04x 0x%04x 0x%04x", 976 i, 977 (w0[1] << 8) | w0[0], 978 (w1[1] << 8) | w1[0], 979 (w2[1] << 8) | w2[0], 980 (w3[1] << 8) | w3[0]); 981 } 982 usberr: 983 ; 984 } 985 #endif 986 987 static int 988 axf_attach_chip(struct usbgem_dev *dp) 989 { 990 uint8_t phys[2]; 991 int err; 992 uint_t vcmd; 993 int ret; 994 #ifdef CONFIG_FULLSIZE_VLAN 995 uint8_t maxpktsize[2]; 996 uint16_t vlan_pktsize; 997 #endif 998 #ifdef DEBUG_LEVEL 999 uint8_t val8; 1000 #endif 1001 struct axf_dev *lp = dp->private; 1002 1003 DPRINTF(0, (CE_CONT, "!%s: %s enter", dp->name, __func__)); 1004 1005 ret = USB_SUCCESS; 1006 /* 1007 * mac address in EEPROM has loaded to ID registers. 1008 */ 1009 vcmd = AX88172(dp) ? VCMD_READ_NODE_ID : VCMD_READ_NODE_ID_88772; 1010 IN(dp, vcmd, 0, 0, 1011 ETHERADDRL, dp->dev_addr.ether_addr_octet, &err, usberr); 1012 1013 /* 1014 * setup IPG values 1015 */ 1016 lp->ipg[0] = 0x15; 1017 lp->ipg[1] = 0x0c; 1018 lp->ipg[2] = 0x12; 1019 1020 /* 1021 * We cannot scan phy because the nic returns undefined 1022 * value, i.e. remained garbage, when MII phy is not at the 1023 * specified index. 1024 */ 1025 #ifdef DEBUG_LEVELx 1026 if (lp->chip->vid == 0x07b8 && lp->chip->pid == 0x420a) { 1027 /* 1028 * restore the original phy address of brain 1029 * damaged Planex UE2-100TX 1030 */ 1031 OUT(dp, VCMD_WRITE_SROM_ENABLE, 0, 0, 0, NULL, &err, usberr); 1032 OUT(dp, VCMD_WRITE_SROM, 0x11, 0xe004, 0, NULL, &err, usberr); 1033 OUT(dp, VCMD_WRITE_SROM_DISABLE, 0, 0, 0, NULL, &err, usberr); 1034 } 1035 #endif 1036 if (AX88172(dp)) { 1037 IN(dp, VCMD_READ_PHY_IDS, 0, 0, 2, &phys, &err, usberr); 1038 dp->mii_phy_addr = phys[1]; 1039 DPRINTF(0, (CE_CONT, "!%s: %s: phys_addr:%d %d", 1040 dp->name, __func__, phys[0], phys[1])); 1041 } else { 1042 /* use built-in phy */ 1043 dp->mii_phy_addr = 0x10; 1044 } 1045 1046 dp->misc_flag |= USBGEM_VLAN; 1047 #ifdef CONFIG_FULLSIZE_VLAN 1048 if (AX88172(dp) || AX88772(dp)) { 1049 /* check max packet size in srom */ 1050 IN(dp, VCMD_READ_SROM, 0x10, 0, 2, maxpktsize, &err, usberr); 1051 vlan_pktsize = ETHERMAX + ETHERFCSL + 4 /* VTAG_SIZE */; 1052 1053 if (LE16P(maxpktsize) < vlan_pktsize) { 1054 cmn_err(CE_CONT, 1055 "!%s: %s: max packet size in srom is too small, " 1056 "changing %d -> %d, do power cycle for the device", 1057 dp->name, __func__, 1058 LE16P(maxpktsize), vlan_pktsize); 1059 OUT(dp, VCMD_WRITE_SROM_ENABLE, 1060 0, 0, 0, NULL, &err, usberr); 1061 OUT(dp, VCMD_WRITE_SROM, 0x10, 1062 vlan_pktsize, 0, NULL, &err, usberr); 1063 OUT(dp, VCMD_WRITE_SROM_DISABLE, 1064 0, 0, 0, NULL, &err, usberr); 1065 1066 /* need to power off the device */ 1067 ret = USB_FAILURE; 1068 } 1069 } 1070 #endif 1071 #ifdef DEBUG_LEVEL 1072 IN(dp, VCMD_READ_GPIO, 0, 0, 1, &val8, &err, usberr); 1073 cmn_err(CE_CONT, 1074 "!%s: %s: ipg 0x%02x 0x%02x 0x%02x, gpio 0x%b", 1075 dp->name, __func__, lp->ipg[0], lp->ipg[1], lp->ipg[2], 1076 val8, GPIO_BITS); 1077 #endif 1078 /* fix rx buffer size */ 1079 if (!AX88172(dp)) { 1080 dp->rx_buf_len = 2048; 1081 } 1082 1083 #if DEBUG_LEVEL > 0 1084 axf_eeprom_dump(dp, 0x20); 1085 #endif 1086 return (ret); 1087 1088 usberr: 1089 cmn_err(CE_WARN, "%s: %s: usb error detected (%d)", 1090 dp->name, __func__, err); 1091 return (USB_FAILURE); 1092 } 1093 1094 static boolean_t 1095 axf_scan_phy(struct usbgem_dev *dp) 1096 { 1097 int i; 1098 int err; 1099 uint16_t val; 1100 int phy_addr_saved; 1101 struct axf_dev *lp = dp->private; 1102 1103 DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__)); 1104 1105 phy_addr_saved = dp->mii_phy_addr; 1106 1107 /* special probe routine for unreliable MII addr */ 1108 #define PROBE_PAT \ 1109 (MII_ABILITY_100BASE_TX_FD | \ 1110 MII_ABILITY_100BASE_TX | \ 1111 MII_ABILITY_10BASE_T_FD | \ 1112 MII_ABILITY_10BASE_T) 1113 1114 for (i = 0; i < 32; i++) { 1115 dp->mii_phy_addr = i; 1116 axf_mii_write(dp, MII_AN_ADVERT, 0, &err); 1117 if (err != USBGEM_SUCCESS) { 1118 break; 1119 } 1120 val = axf_mii_read(dp, MII_AN_ADVERT, &err); 1121 if (err != USBGEM_SUCCESS) { 1122 break; 1123 } 1124 if (val != 0) { 1125 DPRINTF(0, (CE_CONT, "!%s: %s: index:%d, val %b != 0", 1126 dp->name, __func__, i, val, MII_ABILITY_BITS)); 1127 continue; 1128 } 1129 1130 axf_mii_write(dp, MII_AN_ADVERT, PROBE_PAT, &err); 1131 if (err != USBGEM_SUCCESS) { 1132 break; 1133 } 1134 val = axf_mii_read(dp, MII_AN_ADVERT, &err); 1135 if (err != USBGEM_SUCCESS) { 1136 break; 1137 } 1138 if ((val & MII_ABILITY_TECH) != PROBE_PAT) { 1139 DPRINTF(0, (CE_CONT, "!%s: %s: " 1140 "index:%d, pat:%x != val:%b", 1141 dp->name, __func__, i, 1142 PROBE_PAT, val, MII_ABILITY_BITS)); 1143 continue; 1144 } 1145 1146 /* found */ 1147 dp->mii_phy_addr = phy_addr_saved; 1148 return (i); 1149 } 1150 #undef PROBE_PAT 1151 if (i == 32) { 1152 cmn_err(CE_CONT, "!%s: %s: no mii phy found", 1153 dp->name, __func__); 1154 } else { 1155 cmn_err(CE_CONT, "!%s: %s: i/o error while scanning phy", 1156 dp->name, __func__); 1157 } 1158 dp->mii_phy_addr = phy_addr_saved; 1159 return (-1); 1160 } 1161 1162 static int 1163 axf_mii_probe(struct usbgem_dev *dp) 1164 { 1165 int my_guess; 1166 int err; 1167 uint8_t old_11th[2]; 1168 uint8_t new_11th[2]; 1169 struct axf_dev *lp = dp->private; 1170 1171 DPRINTF(0, (CE_CONT, "!%s: %s: called", dp->name, __func__)); 1172 (void) axf_reset_phy(dp); 1173 lp->phy_has_reset = B_TRUE; 1174 1175 if (AX88172(dp)) { 1176 my_guess = axf_scan_phy(dp); 1177 if (my_guess >= 0 && my_guess < 32 && 1178 my_guess != dp->mii_phy_addr) { 1179 /* 1180 * phy addr in srom is wrong, need to fix it 1181 */ 1182 IN(dp, VCMD_READ_SROM, 1183 0x11, 0, 2, old_11th, &err, usberr); 1184 1185 new_11th[0] = my_guess; 1186 new_11th[1] = old_11th[1]; 1187 1188 OUT(dp, VCMD_WRITE_SROM_ENABLE, 1189 0, 0, 0, NULL, &err, usberr); 1190 OUT(dp, VCMD_WRITE_SROM, 1191 0x11, LE16P(new_11th), 0, NULL, &err, usberr); 1192 OUT(dp, VCMD_WRITE_SROM_DISABLE, 1193 0, 0, 0, NULL, &err, usberr); 1194 #if 1 1195 /* XXX - read back, but it doesn't work, why? */ 1196 delay(drv_usectohz(1000*1000)); 1197 IN(dp, VCMD_READ_SROM, 1198 0x11, 0, 2, new_11th, &err, usberr); 1199 #endif 1200 cmn_err(CE_NOTE, "!%s: %s: phy addr in srom fixed: " 1201 "%04x -> %04x", 1202 dp->name, __func__, 1203 LE16P(old_11th), LE16P(new_11th)); 1204 return (USBGEM_FAILURE); 1205 usberr: 1206 cmn_err(CE_NOTE, 1207 "!%s: %s: failed to patch phy addr, " 1208 "current: %04x", 1209 dp->name, __func__, LE16P(old_11th)); 1210 return (USBGEM_FAILURE); 1211 } 1212 } 1213 return (usbgem_mii_probe_default(dp)); 1214 } 1215 1216 static int 1217 axf_mii_init(struct usbgem_dev *dp) 1218 { 1219 struct axf_dev *lp = dp->private; 1220 1221 DPRINTF(2, (CE_CONT, "!%s: %s: called", dp->name, __func__)); 1222 1223 if (!lp->phy_has_reset) { 1224 (void) axf_reset_phy(dp); 1225 } 1226 1227 /* prepare to reset phy on the next reconnect or resume */ 1228 lp->phy_has_reset = B_FALSE; 1229 1230 return (USB_SUCCESS); 1231 } 1232 1233 static int 1234 axfattach(dev_info_t *dip, ddi_attach_cmd_t cmd) 1235 { 1236 int i; 1237 ddi_iblock_cookie_t c; 1238 int ret; 1239 int revid; 1240 int unit; 1241 int vid; 1242 int pid; 1243 struct chip_info *p; 1244 int len; 1245 const char *drv_name; 1246 struct usbgem_dev *dp; 1247 void *base; 1248 struct usbgem_conf *ugcp; 1249 struct axf_dev *lp; 1250 1251 unit = ddi_get_instance(dip); 1252 drv_name = ddi_driver_name(dip); 1253 1254 DPRINTF(3, (CE_CONT, "!%s%d: %s: called, cmd:%d", 1255 drv_name, unit, __func__, cmd)); 1256 1257 if (cmd == DDI_ATTACH) { 1258 /* 1259 * Check if the chip is supported. 1260 */ 1261 vid = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 1262 "usb-vendor-id", -1); 1263 pid = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 1264 "usb-product-id", -1); 1265 revid = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 1266 "usb-revision-id", -1); 1267 1268 for (i = 0, p = chiptbl_88x7x; i < CHIPTABLESIZE; i++, p++) { 1269 if (p->vid == vid && p->pid == pid) { 1270 /* found */ 1271 cmn_err(CE_CONT, "!%s%d: %s " 1272 "(vid: 0x%04x, did: 0x%04x, revid: 0x%02x)", 1273 drv_name, unit, p->name, vid, pid, revid); 1274 goto chip_found; 1275 } 1276 } 1277 1278 /* Not found */ 1279 cmn_err(CE_WARN, "!%s: %s: wrong usb venid/prodid (0x%x, 0x%x)", 1280 drv_name, __func__, vid, pid); 1281 1282 /* assume 88772 */ 1283 p = &chiptbl_88x7x[CHIPTABLESIZE - 1]; 1284 chip_found: 1285 /* 1286 * construct usbgem configration 1287 */ 1288 ugcp = kmem_zalloc(sizeof (*ugcp), KM_SLEEP); 1289 1290 /* name */ 1291 /* 1292 * softmac requires that ppa is the instance number 1293 * of the device, otherwise it hangs in seaching the device. 1294 */ 1295 (void) sprintf(ugcp->usbgc_name, "%s%d", drv_name, unit); 1296 ugcp->usbgc_ppa = unit; 1297 1298 ugcp->usbgc_ifnum = 0; 1299 ugcp->usbgc_alt = 0; 1300 1301 ugcp->usbgc_tx_list_max = 64; 1302 1303 ugcp->usbgc_rx_header_len = 0; 1304 ugcp->usbgc_rx_list_max = 64; 1305 1306 /* time out parameters */ 1307 ugcp->usbgc_tx_timeout = USBGEM_TX_TIMEOUT; 1308 ugcp->usbgc_tx_timeout_interval = USBGEM_TX_TIMEOUT_INTERVAL; 1309 1310 /* flow control */ 1311 /* 1312 * XXX - flow control caused link down frequently under 1313 * heavy traffic 1314 */ 1315 ugcp->usbgc_flow_control = FLOW_CONTROL_RX_PAUSE; 1316 1317 /* MII timeout parameters */ 1318 ugcp->usbgc_mii_link_watch_interval = ONESEC; 1319 ugcp->usbgc_mii_an_watch_interval = ONESEC/5; 1320 ugcp->usbgc_mii_reset_timeout = MII_RESET_TIMEOUT; /* 1 sec */ 1321 ugcp->usbgc_mii_an_timeout = MII_AN_TIMEOUT; /* 5 sec */ 1322 ugcp->usbgc_mii_an_wait = 0; 1323 ugcp->usbgc_mii_linkdown_timeout = MII_LINKDOWN_TIMEOUT; 1324 1325 ugcp->usbgc_mii_an_delay = ONESEC/10; 1326 ugcp->usbgc_mii_linkdown_action = MII_ACTION_RSA; 1327 ugcp->usbgc_mii_linkdown_timeout_action = MII_ACTION_RESET; 1328 ugcp->usbgc_mii_dont_reset = B_FALSE; 1329 ugcp->usbgc_mii_hw_link_detection = B_TRUE; 1330 ugcp->usbgc_mii_stop_mac_on_linkdown = B_FALSE; 1331 1332 /* I/O methods */ 1333 1334 /* mac operation */ 1335 ugcp->usbgc_attach_chip = &axf_attach_chip; 1336 ugcp->usbgc_reset_chip = &axf_reset_chip; 1337 ugcp->usbgc_init_chip = &axf_init_chip; 1338 ugcp->usbgc_start_chip = &axf_start_chip; 1339 ugcp->usbgc_stop_chip = &axf_stop_chip; 1340 ugcp->usbgc_multicast_hash = &axf_mcast_hash; 1341 1342 ugcp->usbgc_set_rx_filter = &axf_set_rx_filter; 1343 ugcp->usbgc_set_media = &axf_set_media; 1344 ugcp->usbgc_get_stats = &axf_get_stats; 1345 ugcp->usbgc_interrupt = &axf_interrupt; 1346 1347 /* packet operation */ 1348 ugcp->usbgc_tx_make_packet = &axf_tx_make_packet; 1349 ugcp->usbgc_rx_make_packet = &axf_rx_make_packet; 1350 1351 /* mii operations */ 1352 ugcp->usbgc_mii_probe = &axf_mii_probe; 1353 ugcp->usbgc_mii_init = &axf_mii_init; 1354 ugcp->usbgc_mii_config = &usbgem_mii_config_default; 1355 ugcp->usbgc_mii_read = &axf_mii_read; 1356 ugcp->usbgc_mii_write = &axf_mii_write; 1357 1358 /* mtu */ 1359 ugcp->usbgc_min_mtu = ETHERMTU; 1360 ugcp->usbgc_max_mtu = ETHERMTU; 1361 ugcp->usbgc_default_mtu = ETHERMTU; 1362 1363 lp = kmem_zalloc(sizeof (struct axf_dev), KM_SLEEP); 1364 lp->chip = p; 1365 lp->last_link_state = 0; 1366 lp->phy_has_reset = B_FALSE; 1367 1368 dp = usbgem_do_attach(dip, ugcp, lp, sizeof (struct axf_dev)); 1369 1370 kmem_free(ugcp, sizeof (*ugcp)); 1371 1372 if (dp != NULL) { 1373 return (DDI_SUCCESS); 1374 } 1375 1376 err_free_mem: 1377 kmem_free(lp, sizeof (struct axf_dev)); 1378 err_close_pipe: 1379 err: 1380 return (DDI_FAILURE); 1381 } 1382 1383 if (cmd == DDI_RESUME) { 1384 return (usbgem_resume(dip)); 1385 } 1386 1387 return (DDI_FAILURE); 1388 } 1389 1390 static int 1391 axfdetach(dev_info_t *dip, ddi_detach_cmd_t cmd) 1392 { 1393 int ret; 1394 1395 if (cmd == DDI_DETACH) { 1396 ret = usbgem_do_detach(dip); 1397 if (ret != DDI_SUCCESS) { 1398 return (DDI_FAILURE); 1399 } 1400 return (DDI_SUCCESS); 1401 } 1402 if (cmd == DDI_SUSPEND) { 1403 return (usbgem_suspend(dip)); 1404 } 1405 return (DDI_FAILURE); 1406 } 1407 1408 /* ======================================================== */ 1409 /* 1410 * OS depend (loadable streams driver) routine 1411 */ 1412 /* ======================================================== */ 1413 USBGEM_STREAM_OPS(axf_ops, axfattach, axfdetach); 1414 1415 static struct modldrv modldrv = { 1416 &mod_driverops, /* Type of module. This one is a driver */ 1417 ident, 1418 &axf_ops, /* driver ops */ 1419 }; 1420 1421 static struct modlinkage modlinkage = { 1422 MODREV_1, &modldrv, NULL 1423 }; 1424 1425 /* ======================================================== */ 1426 /* 1427 * _init : done 1428 */ 1429 /* ======================================================== */ 1430 int 1431 _init(void) 1432 { 1433 int status; 1434 1435 DPRINTF(2, (CE_CONT, "!axf: _init: called")); 1436 1437 status = usbgem_mod_init(&axf_ops, "axf"); 1438 if (status != DDI_SUCCESS) { 1439 return (status); 1440 } 1441 status = mod_install(&modlinkage); 1442 if (status != DDI_SUCCESS) { 1443 usbgem_mod_fini(&axf_ops); 1444 } 1445 return (status); 1446 } 1447 1448 /* 1449 * _fini : done 1450 */ 1451 int 1452 _fini(void) 1453 { 1454 int status; 1455 1456 DPRINTF(2, (CE_CONT, "!axf: _fini: called")); 1457 status = mod_remove(&modlinkage); 1458 if (status == DDI_SUCCESS) { 1459 usbgem_mod_fini(&axf_ops); 1460 } 1461 return (status); 1462 } 1463 1464 int 1465 _info(struct modinfo *modinfop) 1466 { 1467 return (mod_info(&modlinkage, modinfop)); 1468 } 1469