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