📄 asix.c
字号:
asix_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET); asix_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE, ADVERTISE_ALL | ADVERTISE_CSMA); mii_nway_restart(&dev->mii); 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) { dbg("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); dbg("RX_CTL is 0x%04x after all initializations", rx_ctl); rx_ctl = asix_read_medium_status(dev); dbg("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 struct ethtool_ops ax88178_ethtool_ops = { .get_drvinfo = asix_get_drvinfo, .get_link = asix_get_link, .get_msglevel = usbnet_get_msglevel, .set_msglevel = usbnet_set_msglevel, .get_wol = asix_get_wol, .set_wol = asix_set_wol, .get_eeprom_len = asix_get_eeprom_len, .get_eeprom = asix_get_eeprom, .get_settings = usbnet_get_settings, .set_settings = usbnet_set_settings, .nway_reset = usbnet_nway_reset,};static int marvell_phy_init(struct usbnet *dev){ struct asix_data *data = (struct asix_data *)&dev->data; u16 reg; devdbg(dev,"marvell_phy_init()"); reg = asix_mdio_read(dev->net, dev->mii.phy_id, MII_MARVELL_STATUS); devdbg(dev,"MII_MARVELL_STATUS = 0x%04x", reg); asix_mdio_write(dev->net, dev->mii.phy_id, MII_MARVELL_CTRL, MARVELL_CTRL_RXDELAY | MARVELL_CTRL_TXDELAY); if (data->ledmode) { reg = asix_mdio_read(dev->net, dev->mii.phy_id, MII_MARVELL_LED_CTRL); devdbg(dev,"MII_MARVELL_LED_CTRL (1) = 0x%04x", reg); reg &= 0xf8ff; reg |= (1 + 0x0100); asix_mdio_write(dev->net, dev->mii.phy_id, MII_MARVELL_LED_CTRL, reg); reg = asix_mdio_read(dev->net, dev->mii.phy_id, MII_MARVELL_LED_CTRL); devdbg(dev,"MII_MARVELL_LED_CTRL (2) = 0x%04x", reg); reg &= 0xfc0f; } return 0;}static int marvell_led_status(struct usbnet *dev, u16 speed){ u16 reg = asix_mdio_read(dev->net, dev->mii.phy_id, MARVELL_LED_MANUAL); devdbg(dev, "marvell_led_status() read 0x%04x", reg); /* Clear out the center LED bits - 0x03F0 */ reg &= 0xfc0f; switch (speed) { case SPEED_1000: reg |= 0x03e0; break; case SPEED_100: reg |= 0x03b0; break; default: reg |= 0x02f0; } devdbg(dev, "marvell_led_status() writing 0x%04x", reg); asix_mdio_write(dev->net, dev->mii.phy_id, MARVELL_LED_MANUAL, reg); return 0;}static int ax88178_link_reset(struct usbnet *dev){ u16 mode; struct ethtool_cmd ecmd; struct asix_data *data = (struct asix_data *)&dev->data; devdbg(dev,"ax88178_link_reset()"); mii_check_media(&dev->mii, 1, 1); mii_ethtool_gset(&dev->mii, &ecmd); mode = AX88178_MEDIUM_DEFAULT; if (ecmd.speed == SPEED_1000) mode |= AX_MEDIUM_GM | AX_MEDIUM_ENCK; else if (ecmd.speed == SPEED_100) mode |= AX_MEDIUM_PS; else mode &= ~(AX_MEDIUM_PS | AX_MEDIUM_GM); if (ecmd.duplex == DUPLEX_FULL) mode |= AX_MEDIUM_FD; else mode &= ~AX_MEDIUM_FD; devdbg(dev, "ax88178_link_reset() speed: %d duplex: %d setting mode to 0x%04x", ecmd.speed, ecmd.duplex, mode); asix_write_medium_mode(dev, mode); if (data->phymode == PHY_MODE_MARVELL && data->ledmode) marvell_led_status(dev, ecmd.speed); return 0;}static void ax88178_set_mfb(struct usbnet *dev){ u16 mfb = AX_RX_CTL_MFB_16384; u16 rxctl; u16 medium; int old_rx_urb_size = dev->rx_urb_size; if (dev->hard_mtu < 2048) { dev->rx_urb_size = 2048; mfb = AX_RX_CTL_MFB_2048; } else if (dev->hard_mtu < 4096) { dev->rx_urb_size = 4096; mfb = AX_RX_CTL_MFB_4096; } else if (dev->hard_mtu < 8192) { dev->rx_urb_size = 8192; mfb = AX_RX_CTL_MFB_8192; } else if (dev->hard_mtu < 16384) { dev->rx_urb_size = 16384; mfb = AX_RX_CTL_MFB_16384; } rxctl = asix_read_rx_ctl(dev); asix_write_rx_ctl(dev, (rxctl & ~AX_RX_CTL_MFB_16384) | mfb); medium = asix_read_medium_status(dev); if (dev->net->mtu > 1500) medium |= AX_MEDIUM_JFE; else medium &= ~AX_MEDIUM_JFE; asix_write_medium_mode(dev, medium); if (dev->rx_urb_size > old_rx_urb_size) usbnet_unlink_rx_urbs(dev);}static int ax88178_change_mtu(struct net_device *net, int new_mtu){ struct usbnet *dev = netdev_priv(net); int ll_mtu = new_mtu + net->hard_header_len + 4; devdbg(dev, "ax88178_change_mtu() new_mtu=%d", new_mtu); if (new_mtu <= 0 || ll_mtu > 16384) return -EINVAL; if ((ll_mtu % dev->maxpacket) == 0) return -EDOM; net->mtu = new_mtu; dev->hard_mtu = net->mtu + net->hard_header_len; ax88178_set_mfb(dev); return 0;}static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf){ struct asix_data *data = (struct asix_data *)&dev->data; int ret; u8 buf[ETH_ALEN]; __le16 eeprom; u8 status; int gpio0 = 0; u32 phyid; usbnet_get_endpoints(dev,intf); asix_read_cmd(dev, AX_CMD_READ_GPIOS, 0, 0, 1, &status); dbg("GPIO Status: 0x%04x", status); asix_write_cmd(dev, AX_CMD_WRITE_ENABLE, 0, 0, 0, NULL); asix_read_cmd(dev, AX_CMD_READ_EEPROM, 0x0017, 0, 2, &eeprom); asix_write_cmd(dev, AX_CMD_WRITE_DISABLE, 0, 0, 0, NULL); dbg("EEPROM index 0x17 is 0x%04x", eeprom); if (eeprom == cpu_to_le16(0xffff)) { data->phymode = PHY_MODE_MARVELL; data->ledmode = 0; gpio0 = 1; } else { data->phymode = le16_to_cpu(eeprom) & 7; data->ledmode = le16_to_cpu(eeprom) >> 8; gpio0 = (le16_to_cpu(eeprom) & 0x80) ? 0 : 1; } dbg("GPIO0: %d, PhyMode: %d", gpio0, data->phymode); asix_write_gpio(dev, AX_GPIO_RSE | AX_GPIO_GPO_1 | AX_GPIO_GPO1EN, 40); if ((le16_to_cpu(eeprom) >> 8) != 1) { asix_write_gpio(dev, 0x003c, 30); asix_write_gpio(dev, 0x001c, 300); asix_write_gpio(dev, 0x003c, 30); } else { dbg("gpio phymode == 1 path"); asix_write_gpio(dev, AX_GPIO_GPO1EN, 30); asix_write_gpio(dev, AX_GPIO_GPO1EN | AX_GPIO_GPO_1, 30); } asix_sw_reset(dev, 0); msleep(150); asix_sw_reset(dev, AX_SWRESET_PRL | AX_SWRESET_IPPD); msleep(150); asix_write_rx_ctl(dev, 0); /* Get the MAC address */ if ((ret = asix_read_cmd(dev, AX_CMD_READ_NODE_ID, 0, 0, ETH_ALEN, buf)) < 0) { dbg("Failed to read MAC address: %d", ret); goto out; } memcpy(dev->net->dev_addr, buf, ETH_ALEN); /* Initialize MII structure */ dev->mii.dev = dev->net; dev->mii.mdio_read = asix_mdio_read; dev->mii.mdio_write = asix_mdio_write; dev->mii.phy_id_mask = 0x1f; dev->mii.reg_num_mask = 0xff; dev->mii.supports_gmii = 1; dev->net->do_ioctl = asix_ioctl; dev->mii.phy_id = asix_get_phy_addr(dev); dev->net->set_multicast_list = asix_set_multicast; dev->net->ethtool_ops = &ax88178_ethtool_ops; dev->net->change_mtu = &ax88178_change_mtu; phyid = asix_get_phyid(dev); dbg("PHYID=0x%08x", phyid); if (data->phymode == PHY_MODE_MARVELL) { marvell_phy_init(dev); msleep(60); } asix_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET | BMCR_ANENABLE); asix_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE, ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP); asix_mdio_write(dev->net, dev->mii.phy_id, MII_CTRL1000, ADVERTISE_1000FULL); mii_nway_restart(&dev->mii); if ((ret = asix_write_medium_mode(dev, AX88178_MEDIUM_DEFAULT)) < 0) goto out; if ((ret = asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL)) < 0) goto out; /* 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 const struct driver_info ax8817x_info = { .description = "ASIX AX8817x USB 2.0 Ethernet", .bind = ax88172_bind, .status = asix_status, .link_reset = ax88172_link_reset, .reset = ax88172_link_reset, .flags = FLAG_ETHER, .data = 0x00130103,};static const struct driver_info dlink_dub_e100_info = { .description = "DLink DUB-E100 USB Ethernet", .bind = ax88172_bind, .status = asix_status, .link_reset = ax88172_link_reset, .reset = ax88172_link_reset, .flags = FLAG_ETHER, .data = 0x009f9d9f,};static const struct driver_info netgear_fa120_info = { .description = "Netgear FA-120 USB Ethernet", .bind = ax88172_bind, .status = asix_status, .link_reset = ax88172_link_reset, .reset = ax88172_link_reset, .flags = FLAG_ETHER, .data = 0x00130103,};static const struct driver_info hawking_uf200_info = { .description = "Hawking UF200 USB Ethernet", .bind = ax88172_bind, .status = asix_status, .link_reset = ax88172_link_reset, .reset = ax88172_link_reset, .flags = FLAG_ETHER, .data = 0x001f1d1f,};static const struct driver_info ax88772_info = { .description = "ASIX AX88772 USB 2.0 Ethernet", .bind = ax88772_bind, .status = asix_status, .link_reset = ax88772_link_reset, .reset = ax88772_link_reset, .flags = FLAG_ETHER | FLAG_FRAMING_AX, .rx_fixup = asix_rx_fixup, .tx_fixup = asix_tx_fixup,};static const struct driver_info ax88178_info = { .description = "ASIX AX88178 USB 2.0 Ethernet", .bind = ax88178_bind, .status = asix_status, .link_reset = ax88178_link_reset, .reset = ax88178_link_reset, .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 = (unsigned long) &ax8817x_info,}, { // Netgear FA120 USB_DEVICE (0x0846, 0x1040), .driver_info = (unsigned long) &netgear_fa120_info,}, { // DLink DUB-E100 USB_DEVICE (0x2001, 0x1a00), .driver_info = (unsigned long) &dlink_dub_e100_info,}, { // Intellinet, ST Lab USB Ethernet USB_DEVICE (0x0b95, 0x1720), .driver_info = (unsigned long) &ax8817x_info,}, { // Hawking UF200, TrendNet TU2-ET100 USB_DEVICE (0x07b8, 0x420a), .driver_info = (unsigned long) &hawking_uf200_info,}, { // Billionton Systems, USB2AR USB_DEVICE (0x08dd, 0x90ff), .driver_info = (unsigned long) &ax8817x_info,}, { // ATEN UC210T USB_DEVICE (0x0557, 0x2009), .driver_info = (unsigned long) &ax8817x_info,}, { // Buffalo LUA-U2-KTX USB_DEVICE (0x0411, 0x003d), .driver_info = (unsigned long) &ax8817x_info,}, { // Sitecom LN-029 "USB 2.0 10/100 Ethernet adapter" USB_DEVICE (0x6189, 0x182d), .driver_info = (unsigned long) &ax8817x_info,}, { // corega FEther USB2-TX USB_DEVICE (0x07aa, 0x0017), .driver_info = (unsigned long) &ax8817x_info,}, { // Surecom EP-1427X-2 USB_DEVICE (0x1189, 0x0893), .driver_info = (unsigned long) &ax8817x_info,}, { // goodway corp usb gwusb2e USB_DEVICE (0x1631, 0x6200), .driver_info = (unsigned long) &ax8817x_info,}, { // JVC MP-PRX1 Port Replicator USB_DEVICE (0x04f1, 0x3008), .driver_info = (unsigned long) &ax8817x_info,}, { // ASIX AX88772 10/100 USB_DEVICE (0x0b95, 0x7720), .driver_info = (unsigned long) &ax88772_info,}, { // ASIX AX88178 10/100/1000 USB_DEVICE (0x0b95, 0x1780), .driver_info = (unsigned long) &ax88178_info,}, { // Linksys USB200M Rev 2 USB_DEVICE (0x13b1, 0x0018), .driver_info = (unsigned long) &ax88772_info,}, { // 0Q0 cable ethernet USB_DEVICE (0x1557, 0x7720), .driver_info = (unsigned long) &ax88772_info,}, { // DLink DUB-E100 H/W Ver B1 USB_DEVICE (0x07d1, 0x3c05), .driver_info = (unsigned long) &ax88772_info,}, { // DLink DUB-E100 H/W Ver B1 Alternate USB_DEVICE (0x2001, 0x3c05), .driver_info = (unsigned long) &ax88772_info,}, { // Linksys USB1000 USB_DEVICE (0x1737, 0x0039), .driver_info = (unsigned long) &ax88178_info,}, { // IO-DATA ETG-US2 USB_DEVICE (0x04bb, 0x0930), .driver_info = (unsigned long) &ax88178_info,}, { // Belkin F5D5055 USB_DEVICE(0x050d, 0x5055), .driver_info = (unsigned long) &ax88178_info,}, { }, // END};MODULE_DEVICE_TABLE(usb, products);static struct usb_driver asix_driver = { .name = "asix", .id_table = products, .probe = usbnet_probe, .suspend = usbnet_suspend, .resume = usbnet_resume, .disconnect = usbnet_disconnect, .supports_autosuspend = 1,};static int __init asix_init(void){ return usb_register(&asix_driver);}module_init(asix_init);static void __exit asix_exit(void){ usb_deregister(&asix_driver);}module_exit(asix_exit);MODULE_AUTHOR("David Hollis");MODULE_DESCRIPTION("ASIX AX8817X based USB 2.0 Ethernet Devices");MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -