uboot/drivers/usb/eth/asix.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2011 The Chromium OS Authors.
   3 *
   4 * SPDX-License-Identifier:     GPL-2.0+
   5 */
   6
   7#include <common.h>
   8#include <usb.h>
   9#include <linux/mii.h>
  10#include "usb_ether.h"
  11#include <malloc.h>
  12
  13
  14/* ASIX AX8817X based USB 2.0 Ethernet Devices */
  15
  16#define AX_CMD_SET_SW_MII               0x06
  17#define AX_CMD_READ_MII_REG             0x07
  18#define AX_CMD_WRITE_MII_REG            0x08
  19#define AX_CMD_SET_HW_MII               0x0a
  20#define AX_CMD_READ_EEPROM              0x0b
  21#define AX_CMD_READ_RX_CTL              0x0f
  22#define AX_CMD_WRITE_RX_CTL             0x10
  23#define AX_CMD_WRITE_IPG0               0x12
  24#define AX_CMD_READ_NODE_ID             0x13
  25#define AX_CMD_WRITE_NODE_ID    0x14
  26#define AX_CMD_READ_PHY_ID              0x19
  27#define AX_CMD_WRITE_MEDIUM_MODE        0x1b
  28#define AX_CMD_WRITE_GPIOS              0x1f
  29#define AX_CMD_SW_RESET                 0x20
  30#define AX_CMD_SW_PHY_SELECT            0x22
  31
  32#define AX_SWRESET_CLEAR                0x00
  33#define AX_SWRESET_PRTE                 0x04
  34#define AX_SWRESET_PRL                  0x08
  35#define AX_SWRESET_IPRL                 0x20
  36#define AX_SWRESET_IPPD                 0x40
  37
  38#define AX88772_IPG0_DEFAULT            0x15
  39#define AX88772_IPG1_DEFAULT            0x0c
  40#define AX88772_IPG2_DEFAULT            0x12
  41
  42/* AX88772 & AX88178 Medium Mode Register */
  43#define AX_MEDIUM_PF            0x0080
  44#define AX_MEDIUM_JFE           0x0040
  45#define AX_MEDIUM_TFC           0x0020
  46#define AX_MEDIUM_RFC           0x0010
  47#define AX_MEDIUM_ENCK          0x0008
  48#define AX_MEDIUM_AC            0x0004
  49#define AX_MEDIUM_FD            0x0002
  50#define AX_MEDIUM_GM            0x0001
  51#define AX_MEDIUM_SM            0x1000
  52#define AX_MEDIUM_SBP           0x0800
  53#define AX_MEDIUM_PS            0x0200
  54#define AX_MEDIUM_RE            0x0100
  55
  56#define AX88178_MEDIUM_DEFAULT  \
  57        (AX_MEDIUM_PS | AX_MEDIUM_FD | AX_MEDIUM_AC | \
  58         AX_MEDIUM_RFC | AX_MEDIUM_TFC | AX_MEDIUM_JFE | \
  59         AX_MEDIUM_RE)
  60
  61#define AX88772_MEDIUM_DEFAULT  \
  62        (AX_MEDIUM_FD | AX_MEDIUM_RFC | \
  63         AX_MEDIUM_TFC | AX_MEDIUM_PS | \
  64         AX_MEDIUM_AC | AX_MEDIUM_RE)
  65
  66/* AX88772 & AX88178 RX_CTL values */
  67#define AX_RX_CTL_SO                    0x0080
  68#define AX_RX_CTL_AB                    0x0008
  69
  70#define AX_DEFAULT_RX_CTL       \
  71        (AX_RX_CTL_SO | AX_RX_CTL_AB)
  72
  73/* GPIO 2 toggles */
  74#define AX_GPIO_GPO2EN          0x10    /* GPIO2 Output enable */
  75#define AX_GPIO_GPO_2           0x20    /* GPIO2 Output value */
  76#define AX_GPIO_RSE             0x80    /* Reload serial EEPROM */
  77
  78/* local defines */
  79#define ASIX_BASE_NAME "asx"
  80#define USB_CTRL_SET_TIMEOUT 5000
  81#define USB_CTRL_GET_TIMEOUT 5000
  82#define USB_BULK_SEND_TIMEOUT 5000
  83#define USB_BULK_RECV_TIMEOUT 5000
  84
  85#define AX_RX_URB_SIZE 2048
  86#define PHY_CONNECT_TIMEOUT 5000
  87
  88/* asix_flags defines */
  89#define FLAG_NONE                       0
  90#define FLAG_TYPE_AX88172       (1U << 0)
  91#define FLAG_TYPE_AX88772       (1U << 1)
  92#define FLAG_TYPE_AX88772B      (1U << 2)
  93#define FLAG_EEPROM_MAC         (1U << 3) /* initial mac address in eeprom */
  94
  95/* local vars */
  96static int curr_eth_dev; /* index for name of next device detected */
  97
  98/* driver private */
  99struct asix_private {
 100        int flags;
 101};
 102
 103/*
 104 * Asix infrastructure commands
 105 */
 106static int asix_write_cmd(struct ueth_data *dev, u8 cmd, u16 value, u16 index,
 107                             u16 size, void *data)
 108{
 109        int len;
 110
 111        debug("asix_write_cmd() cmd=0x%02x value=0x%04x index=0x%04x "
 112                "size=%d\n", cmd, value, index, size);
 113
 114        len = usb_control_msg(
 115                dev->pusb_dev,
 116                usb_sndctrlpipe(dev->pusb_dev, 0),
 117                cmd,
 118                USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 119                value,
 120                index,
 121                data,
 122                size,
 123                USB_CTRL_SET_TIMEOUT);
 124
 125        return len == size ? 0 : -1;
 126}
 127
 128static int asix_read_cmd(struct ueth_data *dev, u8 cmd, u16 value, u16 index,
 129                            u16 size, void *data)
 130{
 131        int len;
 132
 133        debug("asix_read_cmd() cmd=0x%02x value=0x%04x index=0x%04x size=%d\n",
 134                cmd, value, index, size);
 135
 136        len = usb_control_msg(
 137                dev->pusb_dev,
 138                usb_rcvctrlpipe(dev->pusb_dev, 0),
 139                cmd,
 140                USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 141                value,
 142                index,
 143                data,
 144                size,
 145                USB_CTRL_GET_TIMEOUT);
 146        return len == size ? 0 : -1;
 147}
 148
 149static inline int asix_set_sw_mii(struct ueth_data *dev)
 150{
 151        int ret;
 152
 153        ret = asix_write_cmd(dev, AX_CMD_SET_SW_MII, 0x0000, 0, 0, NULL);
 154        if (ret < 0)
 155                debug("Failed to enable software MII access\n");
 156        return ret;
 157}
 158
 159static inline int asix_set_hw_mii(struct ueth_data *dev)
 160{
 161        int ret;
 162
 163        ret = asix_write_cmd(dev, AX_CMD_SET_HW_MII, 0x0000, 0, 0, NULL);
 164        if (ret < 0)
 165                debug("Failed to enable hardware MII access\n");
 166        return ret;
 167}
 168
 169static int asix_mdio_read(struct ueth_data *dev, int phy_id, int loc)
 170{
 171        ALLOC_CACHE_ALIGN_BUFFER(__le16, res, 1);
 172
 173        asix_set_sw_mii(dev);
 174        asix_read_cmd(dev, AX_CMD_READ_MII_REG, phy_id, (__u16)loc, 2, res);
 175        asix_set_hw_mii(dev);
 176
 177        debug("asix_mdio_read() phy_id=0x%02x, loc=0x%02x, returns=0x%04x\n",
 178                        phy_id, loc, le16_to_cpu(*res));
 179
 180        return le16_to_cpu(*res);
 181}
 182
 183static void
 184asix_mdio_write(struct ueth_data *dev, int phy_id, int loc, int val)
 185{
 186        ALLOC_CACHE_ALIGN_BUFFER(__le16, res, 1);
 187        *res = cpu_to_le16(val);
 188
 189        debug("asix_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x\n",
 190                        phy_id, loc, val);
 191        asix_set_sw_mii(dev);
 192        asix_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id, (__u16)loc, 2, res);
 193        asix_set_hw_mii(dev);
 194}
 195
 196/*
 197 * Asix "high level" commands
 198 */
 199static int asix_sw_reset(struct ueth_data *dev, u8 flags)
 200{
 201        int ret;
 202
 203        ret = asix_write_cmd(dev, AX_CMD_SW_RESET, flags, 0, 0, NULL);
 204        if (ret < 0)
 205                debug("Failed to send software reset: %02x\n", ret);
 206        else
 207                udelay(150 * 1000);
 208
 209        return ret;
 210}
 211
 212static inline int asix_get_phy_addr(struct ueth_data *dev)
 213{
 214        ALLOC_CACHE_ALIGN_BUFFER(u8, buf, 2);
 215
 216        int ret = asix_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, 2, buf);
 217
 218        debug("asix_get_phy_addr()\n");
 219
 220        if (ret < 0) {
 221                debug("Error reading PHYID register: %02x\n", ret);
 222                goto out;
 223        }
 224        debug("asix_get_phy_addr() returning 0x%02x%02x\n", buf[0], buf[1]);
 225        ret = buf[1];
 226
 227out:
 228        return ret;
 229}
 230
 231static int asix_write_medium_mode(struct ueth_data *dev, u16 mode)
 232{
 233        int ret;
 234
 235        debug("asix_write_medium_mode() - mode = 0x%04x\n", mode);
 236        ret = asix_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode,
 237                        0, 0, NULL);
 238        if (ret < 0) {
 239                debug("Failed to write Medium Mode mode to 0x%04x: %02x\n",
 240                        mode, ret);
 241        }
 242        return ret;
 243}
 244
 245static u16 asix_read_rx_ctl(struct ueth_data *dev)
 246{
 247        ALLOC_CACHE_ALIGN_BUFFER(__le16, v, 1);
 248
 249        int ret = asix_read_cmd(dev, AX_CMD_READ_RX_CTL, 0, 0, 2, v);
 250
 251        if (ret < 0)
 252                debug("Error reading RX_CTL register: %02x\n", ret);
 253        else
 254                ret = le16_to_cpu(*v);
 255        return ret;
 256}
 257
 258static int asix_write_rx_ctl(struct ueth_data *dev, u16 mode)
 259{
 260        int ret;
 261
 262        debug("asix_write_rx_ctl() - mode = 0x%04x\n", mode);
 263        ret = asix_write_cmd(dev, AX_CMD_WRITE_RX_CTL, mode, 0, 0, NULL);
 264        if (ret < 0) {
 265                debug("Failed to write RX_CTL mode to 0x%04x: %02x\n",
 266                                mode, ret);
 267        }
 268        return ret;
 269}
 270
 271static int asix_write_gpio(struct ueth_data *dev, u16 value, int sleep)
 272{
 273        int ret;
 274
 275        debug("asix_write_gpio() - value = 0x%04x\n", value);
 276        ret = asix_write_cmd(dev, AX_CMD_WRITE_GPIOS, value, 0, 0, NULL);
 277        if (ret < 0) {
 278                debug("Failed to write GPIO value 0x%04x: %02x\n",
 279                        value, ret);
 280        }
 281        if (sleep)
 282                udelay(sleep * 1000);
 283
 284        return ret;
 285}
 286
 287static int asix_write_hwaddr(struct eth_device *eth)
 288{
 289        struct ueth_data *dev = (struct ueth_data *)eth->priv;
 290        int ret;
 291        ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buf, ETH_ALEN);
 292
 293        memcpy(buf, eth->enetaddr, ETH_ALEN);
 294
 295        ret = asix_write_cmd(dev, AX_CMD_WRITE_NODE_ID, 0, 0, ETH_ALEN, buf);
 296        if (ret < 0)
 297                debug("Failed to set MAC address: %02x\n", ret);
 298
 299        return ret;
 300}
 301
 302/*
 303 * mii commands
 304 */
 305
 306/*
 307 * mii_nway_restart - restart NWay (autonegotiation) for this interface
 308 *
 309 * Returns 0 on success, negative on error.
 310 */
 311static int mii_nway_restart(struct ueth_data *dev)
 312{
 313        int bmcr;
 314        int r = -1;
 315
 316        /* if autoneg is off, it's an error */
 317        bmcr = asix_mdio_read(dev, dev->phy_id, MII_BMCR);
 318
 319        if (bmcr & BMCR_ANENABLE) {
 320                bmcr |= BMCR_ANRESTART;
 321                asix_mdio_write(dev, dev->phy_id, MII_BMCR, bmcr);
 322                r = 0;
 323        }
 324
 325        return r;
 326}
 327
 328static int asix_read_mac(struct eth_device *eth)
 329{
 330        struct ueth_data *dev = (struct ueth_data *)eth->priv;
 331        struct asix_private *priv = (struct asix_private *)dev->dev_priv;
 332        int i;
 333        ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buf, ETH_ALEN);
 334
 335        if (priv->flags & FLAG_EEPROM_MAC) {
 336                for (i = 0; i < (ETH_ALEN >> 1); i++) {
 337                        if (asix_read_cmd(dev, AX_CMD_READ_EEPROM,
 338                                          0x04 + i, 0, 2, buf) < 0) {
 339                                debug("Failed to read SROM address 04h.\n");
 340                                return -1;
 341                        }
 342                        memcpy((eth->enetaddr + i * 2), buf, 2);
 343                }
 344        } else {
 345                if (asix_read_cmd(dev, AX_CMD_READ_NODE_ID, 0, 0, ETH_ALEN, buf)
 346                     < 0) {
 347                        debug("Failed to read MAC address.\n");
 348                        return -1;
 349                }
 350                memcpy(eth->enetaddr, buf, ETH_ALEN);
 351        }
 352
 353        return 0;
 354}
 355
 356static int asix_basic_reset(struct ueth_data *dev)
 357{
 358        int embd_phy;
 359        u16 rx_ctl;
 360
 361        if (asix_write_gpio(dev,
 362                        AX_GPIO_RSE | AX_GPIO_GPO_2 | AX_GPIO_GPO2EN, 5) < 0)
 363                return -1;
 364
 365        /* 0x10 is the phy id of the embedded 10/100 ethernet phy */
 366        embd_phy = ((asix_get_phy_addr(dev) & 0x1f) == 0x10 ? 1 : 0);
 367        if (asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT,
 368                                embd_phy, 0, 0, NULL) < 0) {
 369                debug("Select PHY #1 failed\n");
 370                return -1;
 371        }
 372
 373        if (asix_sw_reset(dev, AX_SWRESET_IPPD | AX_SWRESET_PRL) < 0)
 374                return -1;
 375
 376        if (asix_sw_reset(dev, AX_SWRESET_CLEAR) < 0)
 377                return -1;
 378
 379        if (embd_phy) {
 380                if (asix_sw_reset(dev, AX_SWRESET_IPRL) < 0)
 381                        return -1;
 382        } else {
 383                if (asix_sw_reset(dev, AX_SWRESET_PRTE) < 0)
 384                        return -1;
 385        }
 386
 387        rx_ctl = asix_read_rx_ctl(dev);
 388        debug("RX_CTL is 0x%04x after software reset\n", rx_ctl);
 389        if (asix_write_rx_ctl(dev, 0x0000) < 0)
 390                return -1;
 391
 392        rx_ctl = asix_read_rx_ctl(dev);
 393        debug("RX_CTL is 0x%04x setting to 0x0000\n", rx_ctl);
 394
 395        dev->phy_id = asix_get_phy_addr(dev);
 396        if (dev->phy_id < 0)
 397                debug("Failed to read phy id\n");
 398
 399        asix_mdio_write(dev, dev->phy_id, MII_BMCR, BMCR_RESET);
 400        asix_mdio_write(dev, dev->phy_id, MII_ADVERTISE,
 401                        ADVERTISE_ALL | ADVERTISE_CSMA);
 402        mii_nway_restart(dev);
 403
 404        if (asix_write_medium_mode(dev, AX88772_MEDIUM_DEFAULT) < 0)
 405                return -1;
 406
 407        if (asix_write_cmd(dev, AX_CMD_WRITE_IPG0,
 408                                AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT,
 409                                AX88772_IPG2_DEFAULT, 0, NULL) < 0) {
 410                debug("Write IPG,IPG1,IPG2 failed\n");
 411                return -1;
 412        }
 413
 414        return 0;
 415}
 416
 417/*
 418 * Asix callbacks
 419 */
 420static int asix_init(struct eth_device *eth, bd_t *bd)
 421{
 422        struct ueth_data        *dev = (struct ueth_data *)eth->priv;
 423        int timeout = 0;
 424#define TIMEOUT_RESOLUTION 50   /* ms */
 425        int link_detected;
 426
 427        debug("** %s()\n", __func__);
 428
 429        if (asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL) < 0)
 430                goto out_err;
 431
 432        do {
 433                link_detected = asix_mdio_read(dev, dev->phy_id, MII_BMSR) &
 434                        BMSR_LSTATUS;
 435                if (!link_detected) {
 436                        if (timeout == 0)
 437                                printf("Waiting for Ethernet connection... ");
 438                        udelay(TIMEOUT_RESOLUTION * 1000);
 439                        timeout += TIMEOUT_RESOLUTION;
 440                }
 441        } while (!link_detected && timeout < PHY_CONNECT_TIMEOUT);
 442        if (link_detected) {
 443                if (timeout != 0)
 444                        printf("done.\n");
 445        } else {
 446                printf("unable to connect.\n");
 447                goto out_err;
 448        }
 449
 450        return 0;
 451out_err:
 452        return -1;
 453}
 454
 455static int asix_send(struct eth_device *eth, void *packet, int length)
 456{
 457        struct ueth_data *dev = (struct ueth_data *)eth->priv;
 458        int err;
 459        u32 packet_len;
 460        int actual_len;
 461        ALLOC_CACHE_ALIGN_BUFFER(unsigned char, msg,
 462                PKTSIZE + sizeof(packet_len));
 463
 464        debug("** %s(), len %d\n", __func__, length);
 465
 466        packet_len = (((length) ^ 0x0000ffff) << 16) + (length);
 467        cpu_to_le32s(&packet_len);
 468
 469        memcpy(msg, &packet_len, sizeof(packet_len));
 470        memcpy(msg + sizeof(packet_len), (void *)packet, length);
 471
 472        err = usb_bulk_msg(dev->pusb_dev,
 473                                usb_sndbulkpipe(dev->pusb_dev, dev->ep_out),
 474                                (void *)msg,
 475                                length + sizeof(packet_len),
 476                                &actual_len,
 477                                USB_BULK_SEND_TIMEOUT);
 478        debug("Tx: len = %u, actual = %u, err = %d\n",
 479                        length + sizeof(packet_len), actual_len, err);
 480
 481        return err;
 482}
 483
 484static int asix_recv(struct eth_device *eth)
 485{
 486        struct ueth_data *dev = (struct ueth_data *)eth->priv;
 487        ALLOC_CACHE_ALIGN_BUFFER(unsigned char, recv_buf, AX_RX_URB_SIZE);
 488        unsigned char *buf_ptr;
 489        int err;
 490        int actual_len;
 491        u32 packet_len;
 492
 493        debug("** %s()\n", __func__);
 494
 495        err = usb_bulk_msg(dev->pusb_dev,
 496                                usb_rcvbulkpipe(dev->pusb_dev, dev->ep_in),
 497                                (void *)recv_buf,
 498                                AX_RX_URB_SIZE,
 499                                &actual_len,
 500                                USB_BULK_RECV_TIMEOUT);
 501        debug("Rx: len = %u, actual = %u, err = %d\n", AX_RX_URB_SIZE,
 502                actual_len, err);
 503        if (err != 0) {
 504                debug("Rx: failed to receive\n");
 505                return -1;
 506        }
 507        if (actual_len > AX_RX_URB_SIZE) {
 508                debug("Rx: received too many bytes %d\n", actual_len);
 509                return -1;
 510        }
 511
 512        buf_ptr = recv_buf;
 513        while (actual_len > 0) {
 514                /*
 515                 * 1st 4 bytes contain the length of the actual data as two
 516                 * complementary 16-bit words. Extract the length of the data.
 517                 */
 518                if (actual_len < sizeof(packet_len)) {
 519                        debug("Rx: incomplete packet length\n");
 520                        return -1;
 521                }
 522                memcpy(&packet_len, buf_ptr, sizeof(packet_len));
 523                le32_to_cpus(&packet_len);
 524                if (((~packet_len >> 16) & 0x7ff) != (packet_len & 0x7ff)) {
 525                        debug("Rx: malformed packet length: %#x (%#x:%#x)\n",
 526                              packet_len, (~packet_len >> 16) & 0x7ff,
 527                              packet_len & 0x7ff);
 528                        return -1;
 529                }
 530                packet_len = packet_len & 0x7ff;
 531                if (packet_len > actual_len - sizeof(packet_len)) {
 532                        debug("Rx: too large packet: %d\n", packet_len);
 533                        return -1;
 534                }
 535
 536                /* Notify net stack */
 537                NetReceive(buf_ptr + sizeof(packet_len), packet_len);
 538
 539                /* Adjust for next iteration. Packets are padded to 16-bits */
 540                if (packet_len & 1)
 541                        packet_len++;
 542                actual_len -= sizeof(packet_len) + packet_len;
 543                buf_ptr += sizeof(packet_len) + packet_len;
 544        }
 545
 546        return err;
 547}
 548
 549static void asix_halt(struct eth_device *eth)
 550{
 551        debug("** %s()\n", __func__);
 552}
 553
 554/*
 555 * Asix probing functions
 556 */
 557void asix_eth_before_probe(void)
 558{
 559        curr_eth_dev = 0;
 560}
 561
 562struct asix_dongle {
 563        unsigned short vendor;
 564        unsigned short product;
 565        int flags;
 566};
 567
 568static const struct asix_dongle asix_dongles[] = {
 569        { 0x05ac, 0x1402, FLAG_TYPE_AX88772 },  /* Apple USB Ethernet Adapter */
 570        { 0x07d1, 0x3c05, FLAG_TYPE_AX88772 },  /* D-Link DUB-E100 H/W Ver B1 */
 571        { 0x2001, 0x1a02, FLAG_TYPE_AX88772 },  /* D-Link DUB-E100 H/W Ver C1 */
 572        /* Cables-to-Go USB Ethernet Adapter */
 573        { 0x0b95, 0x772a, FLAG_TYPE_AX88772 },
 574        { 0x0b95, 0x7720, FLAG_TYPE_AX88772 },  /* Trendnet TU2-ET100 V3.0R */
 575        { 0x0b95, 0x1720, FLAG_TYPE_AX88172 },  /* SMC */
 576        { 0x0db0, 0xa877, FLAG_TYPE_AX88772 },  /* MSI - ASIX 88772a */
 577        { 0x13b1, 0x0018, FLAG_TYPE_AX88172 },  /* Linksys 200M v2.1 */
 578        { 0x1557, 0x7720, FLAG_TYPE_AX88772 },  /* 0Q0 cable ethernet */
 579        /* DLink DUB-E100 H/W Ver B1 Alternate */
 580        { 0x2001, 0x3c05, FLAG_TYPE_AX88772 },
 581        /* ASIX 88772B */
 582        { 0x0b95, 0x772b, FLAG_TYPE_AX88772B | FLAG_EEPROM_MAC },
 583        { 0x0000, 0x0000, FLAG_NONE }   /* END - Do not remove */
 584};
 585
 586/* Probe to see if a new device is actually an asix device */
 587int asix_eth_probe(struct usb_device *dev, unsigned int ifnum,
 588                      struct ueth_data *ss)
 589{
 590        struct usb_interface *iface;
 591        struct usb_interface_descriptor *iface_desc;
 592        int ep_in_found = 0, ep_out_found = 0;
 593        int i;
 594
 595        /* let's examine the device now */
 596        iface = &dev->config.if_desc[ifnum];
 597        iface_desc = &dev->config.if_desc[ifnum].desc;
 598
 599        for (i = 0; asix_dongles[i].vendor != 0; i++) {
 600                if (dev->descriptor.idVendor == asix_dongles[i].vendor &&
 601                    dev->descriptor.idProduct == asix_dongles[i].product)
 602                        /* Found a supported dongle */
 603                        break;
 604        }
 605
 606        if (asix_dongles[i].vendor == 0)
 607                return 0;
 608
 609        memset(ss, 0, sizeof(struct ueth_data));
 610
 611        /* At this point, we know we've got a live one */
 612        debug("\n\nUSB Ethernet device detected: %#04x:%#04x\n",
 613              dev->descriptor.idVendor, dev->descriptor.idProduct);
 614
 615        /* Initialize the ueth_data structure with some useful info */
 616        ss->ifnum = ifnum;
 617        ss->pusb_dev = dev;
 618        ss->subclass = iface_desc->bInterfaceSubClass;
 619        ss->protocol = iface_desc->bInterfaceProtocol;
 620
 621        /* alloc driver private */
 622        ss->dev_priv = calloc(1, sizeof(struct asix_private));
 623        if (!ss->dev_priv)
 624                return 0;
 625
 626        ((struct asix_private *)ss->dev_priv)->flags = asix_dongles[i].flags;
 627
 628        /*
 629         * We are expecting a minimum of 3 endpoints - in, out (bulk), and
 630         * int. We will ignore any others.
 631         */
 632        for (i = 0; i < iface_desc->bNumEndpoints; i++) {
 633                /* is it an BULK endpoint? */
 634                if ((iface->ep_desc[i].bmAttributes &
 635                     USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
 636                        u8 ep_addr = iface->ep_desc[i].bEndpointAddress;
 637                        if (ep_addr & USB_DIR_IN) {
 638                                if (!ep_in_found) {
 639                                        ss->ep_in = ep_addr &
 640                                                USB_ENDPOINT_NUMBER_MASK;
 641                                        ep_in_found = 1;
 642                                }
 643                        } else {
 644                                if (!ep_out_found) {
 645                                        ss->ep_out = ep_addr &
 646                                                USB_ENDPOINT_NUMBER_MASK;
 647                                        ep_out_found = 1;
 648                                }
 649                        }
 650                }
 651
 652                /* is it an interrupt endpoint? */
 653                if ((iface->ep_desc[i].bmAttributes &
 654                    USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
 655                        ss->ep_int = iface->ep_desc[i].bEndpointAddress &
 656                                USB_ENDPOINT_NUMBER_MASK;
 657                        ss->irqinterval = iface->ep_desc[i].bInterval;
 658                }
 659        }
 660        debug("Endpoints In %d Out %d Int %d\n",
 661                  ss->ep_in, ss->ep_out, ss->ep_int);
 662
 663        /* Do some basic sanity checks, and bail if we find a problem */
 664        if (usb_set_interface(dev, iface_desc->bInterfaceNumber, 0) ||
 665            !ss->ep_in || !ss->ep_out || !ss->ep_int) {
 666                debug("Problems with device\n");
 667                return 0;
 668        }
 669        dev->privptr = (void *)ss;
 670        return 1;
 671}
 672
 673int asix_eth_get_info(struct usb_device *dev, struct ueth_data *ss,
 674                                struct eth_device *eth)
 675{
 676        struct asix_private *priv = (struct asix_private *)ss->dev_priv;
 677
 678        if (!eth) {
 679                debug("%s: missing parameter.\n", __func__);
 680                return 0;
 681        }
 682        sprintf(eth->name, "%s%d", ASIX_BASE_NAME, curr_eth_dev++);
 683        eth->init = asix_init;
 684        eth->send = asix_send;
 685        eth->recv = asix_recv;
 686        eth->halt = asix_halt;
 687        if (!(priv->flags & FLAG_TYPE_AX88172))
 688                eth->write_hwaddr = asix_write_hwaddr;
 689        eth->priv = ss;
 690
 691        if (asix_basic_reset(ss))
 692                return 0;
 693
 694        /* Get the MAC address */
 695        if (asix_read_mac(eth))
 696                return 0;
 697        debug("MAC %pM\n", eth->enetaddr);
 698
 699        return 1;
 700}
 701