| #include <common.h> |
| #include <init.h> |
| #include <net.h> |
| #include <miidev.h> |
| #include <usb/usb.h> |
| #include <usb/usbnet.h> |
| #include <errno.h> |
| #include <malloc.h> |
| #include <asm/byteorder.h> |
| |
| /* ASIX AX8817X based USB 2.0 Ethernet Devices */ |
| |
| #define AX_CMD_SET_SW_MII 0x06 |
| #define AX_CMD_READ_MII_REG 0x07 |
| #define AX_CMD_WRITE_MII_REG 0x08 |
| #define AX_CMD_SET_HW_MII 0x0a |
| #define AX_CMD_READ_EEPROM 0x0b |
| #define AX_CMD_WRITE_EEPROM 0x0c |
| #define AX_CMD_WRITE_ENABLE 0x0d |
| #define AX_CMD_WRITE_DISABLE 0x0e |
| #define AX_CMD_READ_RX_CTL 0x0f |
| #define AX_CMD_WRITE_RX_CTL 0x10 |
| #define AX_CMD_READ_IPG012 0x11 |
| #define AX_CMD_WRITE_IPG0 0x12 |
| #define AX_CMD_WRITE_IPG1 0x13 |
| #define AX_CMD_READ_NODE_ID 0x13 |
| #define AX_CMD_WRITE_IPG2 0x14 |
| #define AX_CMD_WRITE_MULTI_FILTER 0x16 |
| #define AX88172_CMD_READ_NODE_ID 0x17 |
| #define AX_CMD_READ_PHY_ID 0x19 |
| #define AX_CMD_READ_MEDIUM_STATUS 0x1a |
| #define AX_CMD_WRITE_MEDIUM_MODE 0x1b |
| #define AX_CMD_READ_MONITOR_MODE 0x1c |
| #define AX_CMD_WRITE_MONITOR_MODE 0x1d |
| #define AX_CMD_READ_GPIOS 0x1e |
| #define AX_CMD_WRITE_GPIOS 0x1f |
| #define AX_CMD_SW_RESET 0x20 |
| #define AX_CMD_SW_PHY_STATUS 0x21 |
| #define AX_CMD_SW_PHY_SELECT 0x22 |
| |
| #define AX_MONITOR_MODE 0x01 |
| #define AX_MONITOR_LINK 0x02 |
| #define AX_MONITOR_MAGIC 0x04 |
| #define AX_MONITOR_HSFS 0x10 |
| |
| /* AX88172 Medium Status Register values */ |
| #define AX88172_MEDIUM_FD 0x02 |
| #define AX88172_MEDIUM_TX 0x04 |
| #define AX88172_MEDIUM_FC 0x10 |
| #define AX88172_MEDIUM_DEFAULT \ |
| ( AX88172_MEDIUM_FD | AX88172_MEDIUM_TX | AX88172_MEDIUM_FC ) |
| |
| #define AX_MCAST_FILTER_SIZE 8 |
| #define AX_MAX_MCAST 64 |
| |
| #define AX_SWRESET_CLEAR 0x00 |
| #define AX_SWRESET_RR 0x01 |
| #define AX_SWRESET_RT 0x02 |
| #define AX_SWRESET_PRTE 0x04 |
| #define AX_SWRESET_PRL 0x08 |
| #define AX_SWRESET_BZ 0x10 |
| #define AX_SWRESET_IPRL 0x20 |
| #define AX_SWRESET_IPPD 0x40 |
| |
| #define AX88772_IPG0_DEFAULT 0x15 |
| #define AX88772_IPG1_DEFAULT 0x0c |
| #define AX88772_IPG2_DEFAULT 0x12 |
| |
| /* AX88772 & AX88178 Medium Mode Register */ |
| #define AX_MEDIUM_PF 0x0080 |
| #define AX_MEDIUM_JFE 0x0040 |
| #define AX_MEDIUM_TFC 0x0020 |
| #define AX_MEDIUM_RFC 0x0010 |
| #define AX_MEDIUM_ENCK 0x0008 |
| #define AX_MEDIUM_AC 0x0004 |
| #define AX_MEDIUM_FD 0x0002 |
| #define AX_MEDIUM_GM 0x0001 |
| #define AX_MEDIUM_SM 0x1000 |
| #define AX_MEDIUM_SBP 0x0800 |
| #define AX_MEDIUM_PS 0x0200 |
| #define AX_MEDIUM_RE 0x0100 |
| |
| #define AX88178_MEDIUM_DEFAULT \ |
| (AX_MEDIUM_PS | AX_MEDIUM_FD | AX_MEDIUM_AC | \ |
| AX_MEDIUM_RFC | AX_MEDIUM_TFC | AX_MEDIUM_JFE | \ |
| AX_MEDIUM_RE ) |
| |
| #define AX88772_MEDIUM_DEFAULT \ |
| (AX_MEDIUM_FD | AX_MEDIUM_RFC | \ |
| AX_MEDIUM_TFC | AX_MEDIUM_PS | \ |
| AX_MEDIUM_AC | AX_MEDIUM_RE ) |
| |
| /* AX88772 & AX88178 RX_CTL values */ |
| #define AX_RX_CTL_SO 0x0080 |
| #define AX_RX_CTL_AP 0x0020 |
| #define AX_RX_CTL_AM 0x0010 |
| #define AX_RX_CTL_AB 0x0008 |
| #define AX_RX_CTL_SEP 0x0004 |
| #define AX_RX_CTL_AMALL 0x0002 |
| #define AX_RX_CTL_PRO 0x0001 |
| #define AX_RX_CTL_MFB_2048 0x0000 |
| #define AX_RX_CTL_MFB_4096 0x0100 |
| #define AX_RX_CTL_MFB_8192 0x0200 |
| #define AX_RX_CTL_MFB_16384 0x0300 |
| |
| #define AX_DEFAULT_RX_CTL \ |
| (AX_RX_CTL_SO | AX_RX_CTL_AB ) |
| |
| /* GPIO 0 .. 2 toggles */ |
| #define AX_GPIO_GPO0EN 0x01 /* GPIO0 Output enable */ |
| #define AX_GPIO_GPO_0 0x02 /* GPIO0 Output value */ |
| #define AX_GPIO_GPO1EN 0x04 /* GPIO1 Output enable */ |
| #define AX_GPIO_GPO_1 0x08 /* GPIO1 Output value */ |
| #define AX_GPIO_GPO2EN 0x10 /* GPIO2 Output enable */ |
| #define AX_GPIO_GPO_2 0x20 /* GPIO2 Output value */ |
| #define AX_GPIO_RESERVED 0x40 /* Reserved */ |
| #define AX_GPIO_RSE 0x80 /* Reload serial EEPROM */ |
| |
| #define AX_EEPROM_MAGIC 0xdeadbeef |
| #define AX88172_EEPROM_LEN 0x40 |
| #define AX88772_EEPROM_LEN 0xff |
| |
| #define PHY_MODE_MARVELL 0x0000 |
| #define MII_MARVELL_LED_CTRL 0x0018 |
| #define MII_MARVELL_STATUS 0x001b |
| #define MII_MARVELL_CTRL 0x0014 |
| |
| #define MARVELL_LED_MANUAL 0x0019 |
| |
| #define MARVELL_STATUS_HWCFG 0x0004 |
| |
| #define MARVELL_CTRL_TXDELAY 0x0002 |
| #define MARVELL_CTRL_RXDELAY 0x0080 |
| |
| /* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */ |
| struct asix_data { |
| u8 multi_filter[AX_MCAST_FILTER_SIZE]; |
| u8 phymode; |
| u8 ledmode; |
| u8 eeprom_len; |
| }; |
| |
| struct ax88172_int_data { |
| __le16 res1; |
| u8 link; |
| __le16 res2; |
| u8 status; |
| __le16 res3; |
| } __attribute__ ((packed)); |
| |
| static int asix_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, |
| u16 size, void *data) |
| { |
| void *buf; |
| int err = -ENOMEM; |
| |
| dev_dbg(&dev->edev.dev, "asix_read_cmd() cmd=0x%02x value=0x%04x index=0x%04x size=%d", |
| cmd, value, index, size); |
| |
| buf = malloc(size); |
| if (!buf) |
| goto out; |
| |
| err = usb_control_msg( |
| dev->udev, |
| usb_rcvctrlpipe(dev->udev, 0), |
| cmd, |
| USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
| value, |
| index, |
| buf, |
| size, |
| USB_CTRL_GET_TIMEOUT); |
| if (err == size) |
| memcpy(data, buf, size); |
| else if (err >= 0) |
| err = -EINVAL; |
| free(buf); |
| |
| out: |
| return err; |
| } |
| |
| static int asix_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, |
| u16 size, void *data) |
| { |
| void *buf = NULL; |
| int err = -ENOMEM; |
| |
| dev_dbg(&dev->edev.dev, "asix_write_cmd() cmd=0x%02x value=0x%04x index=0x%04x size=%d", |
| cmd, value, index, size); |
| |
| if (data) { |
| buf = malloc(size); |
| if (!buf) |
| goto out; |
| memcpy(buf, data, size); |
| } |
| |
| err = usb_control_msg( |
| dev->udev, |
| usb_sndctrlpipe(dev->udev, 0), |
| cmd, |
| USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
| value, |
| index, |
| buf, |
| size, |
| USB_CTRL_SET_TIMEOUT); |
| free(buf); |
| |
| out: |
| return err; |
| } |
| |
| static inline int asix_set_sw_mii(struct usbnet *dev) |
| { |
| int ret; |
| ret = asix_write_cmd(dev, AX_CMD_SET_SW_MII, 0x0000, 0, 0, NULL); |
| if (ret < 0) |
| dev_err(&dev->edev.dev, "Failed to enable software MII access"); |
| return ret; |
| } |
| |
| static inline int asix_set_hw_mii(struct usbnet *dev) |
| { |
| int ret; |
| ret = asix_write_cmd(dev, AX_CMD_SET_HW_MII, 0x0000, 0, 0, NULL); |
| if (ret < 0) |
| dev_err(&dev->edev.dev, "Failed to enable hardware MII access"); |
| return ret; |
| } |
| |
| static int asix_mdio_read(struct mii_device *mdev, int phy_id, int loc) |
| { |
| struct eth_device *eth = mdev->edev; |
| struct usbnet *dev = eth->priv; |
| __le16 res; |
| |
| asix_set_sw_mii(dev); |
| asix_read_cmd(dev, AX_CMD_READ_MII_REG, phy_id, |
| (__u16)loc, 2, &res); |
| asix_set_hw_mii(dev); |
| |
| dev_dbg(&dev->edev.dev, "asix_mdio_read() phy_id=0x%02x, loc=0x%02x, returns=0x%04x", |
| phy_id, loc, le16_to_cpu(res)); |
| |
| return le16_to_cpu(res); |
| } |
| |
| static int asix_mdio_write(struct mii_device *mdev, int phy_id, int loc, int val) |
| { |
| struct eth_device *eth = mdev->edev; |
| struct usbnet *dev = eth->priv; |
| __le16 res = cpu_to_le16(val); |
| |
| dev_dbg(&dev->edev.dev, "asix_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x", |
| phy_id, loc, val); |
| |
| asix_set_sw_mii(dev); |
| asix_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id, (__u16)loc, 2, &res); |
| asix_set_hw_mii(dev); |
| |
| return 0; |
| } |
| |
| static inline int asix_get_phy_addr(struct usbnet *dev) |
| { |
| u8 buf[2]; |
| int ret = asix_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, 2, buf); |
| |
| dev_dbg(&dev->edev.dev, "asix_get_phy_addr()"); |
| |
| if (ret < 0) { |
| dev_err(&dev->edev.dev, "Error reading PHYID register: %02x", ret); |
| goto out; |
| } |
| dev_dbg(&dev->edev.dev, "asix_get_phy_addr() returning 0x%04x", *((__le16 *)buf)); |
| ret = buf[1]; |
| |
| out: |
| return ret; |
| } |
| |
| static int asix_sw_reset(struct usbnet *dev, u8 flags) |
| { |
| int ret; |
| |
| ret = asix_write_cmd(dev, AX_CMD_SW_RESET, flags, 0, 0, NULL); |
| if (ret < 0) |
| dev_err(&dev->edev.dev, "Failed to send software reset: %02x", ret); |
| |
| return ret; |
| } |
| |
| static u16 asix_read_rx_ctl(struct usbnet *dev) |
| { |
| __le16 v; |
| int ret = asix_read_cmd(dev, AX_CMD_READ_RX_CTL, 0, 0, 2, &v); |
| |
| if (ret < 0) { |
| dev_err(&dev->edev.dev, "Error reading RX_CTL register: %02x", ret); |
| goto out; |
| } |
| ret = le16_to_cpu(v); |
| out: |
| return ret; |
| } |
| |
| static int asix_write_rx_ctl(struct usbnet *dev, u16 mode) |
| { |
| int ret; |
| |
| dev_dbg(&dev->edev.dev, "asix_write_rx_ctl() - mode = 0x%04x", mode); |
| ret = asix_write_cmd(dev, AX_CMD_WRITE_RX_CTL, mode, 0, 0, NULL); |
| if (ret < 0) |
| dev_err(&dev->edev.dev, "Failed to write RX_CTL mode to 0x%04x: %02x", |
| mode, ret); |
| |
| return ret; |
| } |
| |
| static u16 asix_read_medium_status(struct usbnet *dev) |
| { |
| __le16 v; |
| int ret = asix_read_cmd(dev, AX_CMD_READ_MEDIUM_STATUS, 0, 0, 2, &v); |
| |
| if (ret < 0) { |
| dev_err(&dev->edev.dev, "Error reading Medium Status register: %02x", ret); |
| goto out; |
| } |
| ret = le16_to_cpu(v); |
| out: |
| return ret; |
| } |
| |
| static int asix_write_medium_mode(struct usbnet *dev, u16 mode) |
| { |
| int ret; |
| |
| dev_dbg(&dev->edev.dev, "asix_write_medium_mode() - mode = 0x%04x", mode); |
| ret = asix_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL); |
| if (ret < 0) |
| dev_err(&dev->edev.dev, "Failed to write Medium Mode mode to 0x%04x: %02x", |
| mode, ret); |
| |
| return ret; |
| } |
| |
| static int asix_write_gpio(struct usbnet *dev, u16 value, int sleep) |
| { |
| int ret; |
| |
| dev_dbg(&dev->edev.dev,"asix_write_gpio() - value = 0x%04x", value); |
| ret = asix_write_cmd(dev, AX_CMD_WRITE_GPIOS, value, 0, 0, NULL); |
| if (ret < 0) |
| dev_err(&dev->edev.dev, "Failed to write GPIO value 0x%04x: %02x", |
| value, ret); |
| |
| if (sleep) |
| mdelay(sleep); |
| |
| return ret; |
| } |
| |
| static int asix_get_ethaddr(struct eth_device *edev, unsigned char *adr) |
| { |
| struct usbnet *udev = container_of(edev, struct usbnet, edev); |
| int ret; |
| |
| /* Get the MAC address */ |
| if ((ret = asix_read_cmd(udev, AX_CMD_READ_NODE_ID, |
| 0, 0, 6, adr)) < 0) { |
| debug("Failed to read MAC address: %d", ret); |
| return -1; |
| } |
| |
| return 0; |
| } |
| |
| static int asix_set_ethaddr(struct eth_device *edev, unsigned char *adr) |
| { |
| /* not possible? */ |
| return 0; |
| } |
| |
| static int ax88172_get_ethaddr(struct eth_device *edev, unsigned char *adr) |
| { |
| struct usbnet *udev = container_of(edev, struct usbnet, edev); |
| int ret; |
| |
| /* Get the MAC address */ |
| if ((ret = asix_read_cmd(udev, AX88172_CMD_READ_NODE_ID, |
| 0, 0, 6, adr)) < 0) { |
| debug("read AX_CMD_READ_NODE_ID failed: %d", ret); |
| return -1; |
| } |
| |
| return 0; |
| } |
| |
| static int asix_rx_fixup(struct usbnet *dev, void *buf, int len) |
| { |
| unsigned int header; |
| unsigned short size; |
| |
| memcpy(&header, (void*) buf, sizeof(header)); |
| le32_to_cpus(&header); |
| buf += 4; |
| len -= 4; |
| |
| while (len > 0) { |
| if ((short)(header & 0x0000ffff) != ~((short)((header & 0xffff0000) >> 16))) |
| dev_err(&dev->edev.dev, "asix_rx_fixup() Bad Header Length"); |
| |
| /* get the packet length */ |
| size = (unsigned short) (header & 0x0000ffff); |
| |
| if (size > 1514) { |
| dev_err(&dev->edev.dev, "asix_rx_fixup() Bad RX Length %d", size); |
| return 0; |
| } |
| |
| net_receive(buf, size); |
| |
| buf += ((size + 1) & 0xfffe); |
| len -= ((size + 1) & 0xfffe); |
| |
| if (len == 0) |
| break; |
| |
| memcpy(&header, (void*) buf, sizeof(header)); |
| le32_to_cpus(&header); |
| buf += 4; |
| len -= 4; |
| } |
| |
| if (len < 0) { |
| dev_err(&dev->edev.dev,"asix_rx_fixup() Bad SKB Length %d", len); |
| return -1; |
| } |
| return 0; |
| } |
| |
| static int asix_tx_fixup(struct usbnet *dev, |
| void *buf, int len, |
| void *nbuf, int *nlen) |
| { |
| unsigned int packet_len; |
| |
| memmove(nbuf + 4, buf, len); |
| |
| packet_len = ((len ^ 0x0000ffff) << 16) + len; |
| cpu_to_le32s(&packet_len); |
| memcpy(nbuf, &packet_len, 4); |
| len += 4; |
| |
| if((len % 512) == 0) { |
| unsigned int padbytes = 0xffff0000; |
| cpu_to_le32s(&padbytes); |
| memcpy(nbuf + len, &padbytes, 4); |
| len += 4; |
| } |
| |
| *nlen = len; |
| |
| return 0; |
| } |
| |
| static int asix_init_mii(struct usbnet *dev) |
| { |
| dev->miidev.read = asix_mdio_read; |
| dev->miidev.write = asix_mdio_write; |
| dev->miidev.address = asix_get_phy_addr(dev); |
| dev->miidev.flags = 0; |
| dev->miidev.edev = &dev->edev; |
| |
| return mii_register(&dev->miidev); |
| } |
| |
| static int ax88172_link_reset(struct usbnet *dev) |
| { |
| u8 mode; |
| |
| mode = AX88172_MEDIUM_DEFAULT; |
| |
| // if (ecmd.duplex != DUPLEX_FULL) |
| // mode |= ~AX88172_MEDIUM_FD; |
| |
| asix_write_medium_mode(dev, mode); |
| |
| return 0; |
| } |
| |
| static int ax88172_bind(struct usbnet *dev) |
| { |
| int ret = 0; |
| int i; |
| unsigned long gpio_bits = dev->driver_info->data; |
| struct asix_data *data = (struct asix_data *)&dev->data; |
| |
| dev_dbg(&dev->edev.dev, "%s\n", __func__); |
| |
| data->eeprom_len = AX88172_EEPROM_LEN; |
| |
| ret = usbnet_get_endpoints(dev); |
| if (ret) { |
| dev_err(&dev->edev.dev, "can not get EPs\n"); |
| return ret; |
| } |
| |
| /* Toggle the GPIOs in a manufacturer/model specific way */ |
| for (i = 2; i >= 0; i--) { |
| if ((ret = asix_write_cmd(dev, AX_CMD_WRITE_GPIOS, |
| (gpio_bits >> (i * 8)) & 0xff, 0, 0, |
| NULL)) < 0) |
| goto out; |
| mdelay(5); |
| } |
| |
| if ((ret = asix_write_rx_ctl(dev, 0x80)) < 0) |
| goto out; |
| |
| dev->edev.get_ethaddr = ax88172_get_ethaddr; |
| dev->edev.set_ethaddr = asix_set_ethaddr; |
| asix_init_mii(dev); |
| |
| return 0; |
| |
| out: |
| return ret; |
| } |
| |
| static int ax88772_bind(struct usbnet *dev) |
| { |
| int ret, embd_phy; |
| u16 rx_ctl; |
| struct asix_data *data = (struct asix_data *)&dev->data; |
| |
| debug("%s\n", __func__); |
| |
| data->eeprom_len = AX88772_EEPROM_LEN; |
| |
| usbnet_get_endpoints(dev); |
| |
| if ((ret = asix_write_gpio(dev, |
| AX_GPIO_RSE | AX_GPIO_GPO_2 | AX_GPIO_GPO2EN, 5)) < 0) |
| goto out; |
| |
| /* 0x10 is the phy id of the embedded 10/100 ethernet phy */ |
| embd_phy = ((asix_get_phy_addr(dev) & 0x1f) == 0x10 ? 1 : 0); |
| if ((ret = asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT, |
| embd_phy, 0, 0, NULL)) < 0) { |
| debug("Select PHY #1 failed: %d", ret); |
| goto out; |
| } |
| |
| if ((ret = asix_sw_reset(dev, AX_SWRESET_IPPD | AX_SWRESET_PRL)) < 0) |
| goto out; |
| |
| mdelay(150); |
| if ((ret = asix_sw_reset(dev, AX_SWRESET_CLEAR)) < 0) |
| goto out; |
| |
| mdelay(150); |
| if (embd_phy) { |
| if ((ret = asix_sw_reset(dev, AX_SWRESET_IPRL)) < 0) |
| goto out; |
| } |
| else { |
| if ((ret = asix_sw_reset(dev, AX_SWRESET_PRTE)) < 0) |
| goto out; |
| } |
| |
| mdelay(150); |
| rx_ctl = asix_read_rx_ctl(dev); |
| debug("RX_CTL is 0x%04x after software reset", rx_ctl); |
| if ((ret = asix_write_rx_ctl(dev, 0x0000)) < 0) |
| goto out; |
| |
| rx_ctl = asix_read_rx_ctl(dev); |
| debug("RX_CTL is 0x%04x setting to 0x0000", rx_ctl); |
| |
| dev->edev.get_ethaddr = asix_get_ethaddr; |
| dev->edev.set_ethaddr = asix_set_ethaddr; |
| asix_init_mii(dev); |
| |
| if ((ret = asix_sw_reset(dev, AX_SWRESET_PRL)) < 0) |
| goto out; |
| |
| mdelay(150); |
| |
| if ((ret = asix_sw_reset(dev, AX_SWRESET_IPRL | AX_SWRESET_PRL)) < 0) |
| goto out; |
| |
| mdelay(150); |
| |
| if ((ret = asix_write_medium_mode(dev, AX88772_MEDIUM_DEFAULT)) < 0) |
| goto out; |
| |
| if ((ret = asix_write_cmd(dev, AX_CMD_WRITE_IPG0, |
| AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT, |
| AX88772_IPG2_DEFAULT, 0, NULL)) < 0) { |
| debug("Write IPG,IPG1,IPG2 failed: %d", ret); |
| goto out; |
| } |
| |
| /* Set RX_CTL to default values with 2k buffer, and enable cactus */ |
| if ((ret = asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL)) < 0) |
| goto out; |
| |
| rx_ctl = asix_read_rx_ctl(dev); |
| debug("RX_CTL is 0x%04x after all initializations", rx_ctl); |
| |
| rx_ctl = asix_read_medium_status(dev); |
| debug("Medium Status is 0x%04x after all initializations", rx_ctl); |
| |
| /* Asix framing packs multiple eth frames into a 2K usb bulk transfer */ |
| if (dev->driver_info->flags & FLAG_FRAMING_AX) { |
| /* hard_mtu is still the default - the device does not support |
| jumbo eth frames */ |
| dev->rx_urb_size = 2048; |
| } |
| |
| return 0; |
| |
| out: |
| return ret; |
| } |
| |
| static void asix_unbind(struct usbnet *dev) |
| { |
| mii_unregister(&dev->miidev); |
| } |
| |
| static struct driver_info ax8817x_info = { |
| .description = "ASIX AX8817x USB 2.0 Ethernet", |
| .bind = ax88172_bind, |
| .unbind = asix_unbind, |
| .link_reset = ax88172_link_reset, |
| .reset = ax88172_link_reset, |
| .flags = FLAG_ETHER, |
| .data = 0x00130103, |
| }; |
| |
| static struct driver_info dlink_dub_e100_info = { |
| .description = "DLink DUB-E100 USB Ethernet", |
| .bind = ax88172_bind, |
| .unbind = asix_unbind, |
| .link_reset = ax88172_link_reset, |
| .reset = ax88172_link_reset, |
| .flags = FLAG_ETHER, |
| .data = 0x009f9d9f, |
| }; |
| |
| static struct driver_info netgear_fa120_info = { |
| .description = "Netgear FA-120 USB Ethernet", |
| .bind = ax88172_bind, |
| .unbind = asix_unbind, |
| .link_reset = ax88172_link_reset, |
| .reset = ax88172_link_reset, |
| .flags = FLAG_ETHER, |
| .data = 0x00130103, |
| }; |
| |
| static struct driver_info hawking_uf200_info = { |
| .description = "Hawking UF200 USB Ethernet", |
| .bind = ax88172_bind, |
| .unbind = asix_unbind, |
| .link_reset = ax88172_link_reset, |
| .reset = ax88172_link_reset, |
| .flags = FLAG_ETHER, |
| .data = 0x001f1d1f, |
| }; |
| |
| static struct driver_info ax88772_info = { |
| .description = "ASIX AX88772 USB 2.0 Ethernet", |
| .bind = ax88772_bind, |
| .unbind = asix_unbind, |
| .flags = FLAG_ETHER | FLAG_FRAMING_AX, |
| .rx_fixup = asix_rx_fixup, |
| .tx_fixup = asix_tx_fixup, |
| }; |
| |
| static const struct usb_device_id products [] = { |
| { |
| // Linksys USB200M |
| USB_DEVICE (0x077b, 0x2226), |
| .driver_info = &ax8817x_info, |
| }, { |
| // Netgear FA120 |
| USB_DEVICE (0x0846, 0x1040), |
| .driver_info = &netgear_fa120_info, |
| }, { |
| // DLink DUB-E100 |
| USB_DEVICE (0x2001, 0x1a00), |
| .driver_info = &dlink_dub_e100_info, |
| }, { |
| // Intellinet, ST Lab USB Ethernet |
| USB_DEVICE (0x0b95, 0x1720), |
| .driver_info = &ax8817x_info, |
| }, { |
| // Hawking UF200, TrendNet TU2-ET100 |
| USB_DEVICE (0x07b8, 0x420a), |
| .driver_info = &hawking_uf200_info, |
| }, { |
| // Billionton Systems, USB2AR |
| USB_DEVICE (0x08dd, 0x90ff), |
| .driver_info = &ax8817x_info, |
| }, { |
| // ATEN UC210T |
| USB_DEVICE (0x0557, 0x2009), |
| .driver_info = &ax8817x_info, |
| }, { |
| // Buffalo LUA-U2-KTX |
| USB_DEVICE (0x0411, 0x003d), |
| .driver_info = &ax8817x_info, |
| }, { |
| // Sitecom LN-029 "USB 2.0 10/100 Ethernet adapter" |
| USB_DEVICE (0x6189, 0x182d), |
| .driver_info = &ax8817x_info, |
| }, { |
| // corega FEther USB2-TX |
| USB_DEVICE (0x07aa, 0x0017), |
| .driver_info = &ax8817x_info, |
| }, { |
| // Surecom EP-1427X-2 |
| USB_DEVICE (0x1189, 0x0893), |
| .driver_info = &ax8817x_info, |
| }, { |
| // goodway corp usb gwusb2e |
| USB_DEVICE (0x1631, 0x6200), |
| .driver_info = &ax8817x_info, |
| }, { |
| // JVC MP-PRX1 Port Replicator |
| USB_DEVICE (0x04f1, 0x3008), |
| .driver_info = &ax8817x_info, |
| }, { |
| // ASIX AX88772 10/100 |
| USB_DEVICE (0x0b95, 0x7720), |
| .driver_info = &ax88772_info, |
| }, { |
| // Linksys USB200M Rev 2 |
| USB_DEVICE (0x13b1, 0x0018), |
| .driver_info = &ax88772_info, |
| }, { |
| // 0Q0 cable ethernet |
| USB_DEVICE (0x1557, 0x7720), |
| .driver_info = &ax88772_info, |
| }, { |
| // DLink DUB-E100 H/W Ver B1 |
| USB_DEVICE (0x07d1, 0x3c05), |
| .driver_info = &ax88772_info, |
| }, { |
| // DLink DUB-E100 H/W Ver B1 Alternate |
| USB_DEVICE (0x2001, 0x3c05), |
| .driver_info = &ax88772_info, |
| }, { |
| // Apple USB Ethernet Adapter |
| USB_DEVICE(0x05ac, 0x1402), |
| .driver_info = &ax88772_info, |
| }, { |
| // Cables-to-Go USB Ethernet Adapter |
| USB_DEVICE(0x0b95, 0x772a), |
| .driver_info = &ax88772_info, |
| }, |
| { }, // END |
| }; |
| |
| static struct usb_driver asix_driver = { |
| .name = "asix", |
| .id_table = products, |
| .probe = usbnet_probe, |
| .disconnect = usbnet_disconnect, |
| }; |
| |
| static int __init asix_init(void) |
| { |
| return usb_driver_register(&asix_driver); |
| } |
| device_initcall(asix_init); |
| |