Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.15-rc3 945 lines 24 kB view raw
1/* 2 * ASIX AX8817X based USB 2.0 Ethernet Devices 3 * Copyright (C) 2003-2005 David Hollis <dhollis@davehollis.com> 4 * Copyright (C) 2005 Phil Chang <pchang23@sbcglobal.net> 5 * Copyright (c) 2002-2003 TiVo Inc. 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 */ 21 22// #define DEBUG // error path messages, extra info 23// #define VERBOSE // more; success messages 24 25#include <linux/config.h> 26#include <linux/module.h> 27#include <linux/kmod.h> 28#include <linux/sched.h> 29#include <linux/init.h> 30#include <linux/netdevice.h> 31#include <linux/etherdevice.h> 32#include <linux/ethtool.h> 33#include <linux/workqueue.h> 34#include <linux/mii.h> 35#include <linux/usb.h> 36#include <linux/crc32.h> 37 38#include "usbnet.h" 39 40 41/* ASIX AX8817X based USB 2.0 Ethernet Devices */ 42 43#define AX_CMD_SET_SW_MII 0x06 44#define AX_CMD_READ_MII_REG 0x07 45#define AX_CMD_WRITE_MII_REG 0x08 46#define AX_CMD_SET_HW_MII 0x0a 47#define AX_CMD_READ_EEPROM 0x0b 48#define AX_CMD_WRITE_EEPROM 0x0c 49#define AX_CMD_WRITE_ENABLE 0x0d 50#define AX_CMD_WRITE_DISABLE 0x0e 51#define AX_CMD_WRITE_RX_CTL 0x10 52#define AX_CMD_READ_IPG012 0x11 53#define AX_CMD_WRITE_IPG0 0x12 54#define AX_CMD_WRITE_IPG1 0x13 55#define AX_CMD_WRITE_IPG2 0x14 56#define AX_CMD_WRITE_MULTI_FILTER 0x16 57#define AX_CMD_READ_NODE_ID 0x17 58#define AX_CMD_READ_PHY_ID 0x19 59#define AX_CMD_READ_MEDIUM_STATUS 0x1a 60#define AX_CMD_WRITE_MEDIUM_MODE 0x1b 61#define AX_CMD_READ_MONITOR_MODE 0x1c 62#define AX_CMD_WRITE_MONITOR_MODE 0x1d 63#define AX_CMD_WRITE_GPIOS 0x1f 64#define AX_CMD_SW_RESET 0x20 65#define AX_CMD_SW_PHY_STATUS 0x21 66#define AX_CMD_SW_PHY_SELECT 0x22 67#define AX88772_CMD_READ_NODE_ID 0x13 68 69#define AX_MONITOR_MODE 0x01 70#define AX_MONITOR_LINK 0x02 71#define AX_MONITOR_MAGIC 0x04 72#define AX_MONITOR_HSFS 0x10 73 74/* AX88172 Medium Status Register values */ 75#define AX_MEDIUM_FULL_DUPLEX 0x02 76#define AX_MEDIUM_TX_ABORT_ALLOW 0x04 77#define AX_MEDIUM_FLOW_CONTROL_EN 0x10 78 79#define AX_MCAST_FILTER_SIZE 8 80#define AX_MAX_MCAST 64 81 82#define AX_EEPROM_LEN 0x40 83 84#define AX_SWRESET_CLEAR 0x00 85#define AX_SWRESET_RR 0x01 86#define AX_SWRESET_RT 0x02 87#define AX_SWRESET_PRTE 0x04 88#define AX_SWRESET_PRL 0x08 89#define AX_SWRESET_BZ 0x10 90#define AX_SWRESET_IPRL 0x20 91#define AX_SWRESET_IPPD 0x40 92 93#define AX88772_IPG0_DEFAULT 0x15 94#define AX88772_IPG1_DEFAULT 0x0c 95#define AX88772_IPG2_DEFAULT 0x12 96 97#define AX88772_MEDIUM_FULL_DUPLEX 0x0002 98#define AX88772_MEDIUM_RESERVED 0x0004 99#define AX88772_MEDIUM_RX_FC_ENABLE 0x0010 100#define AX88772_MEDIUM_TX_FC_ENABLE 0x0020 101#define AX88772_MEDIUM_PAUSE_FORMAT 0x0080 102#define AX88772_MEDIUM_RX_ENABLE 0x0100 103#define AX88772_MEDIUM_100MB 0x0200 104#define AX88772_MEDIUM_DEFAULT \ 105 (AX88772_MEDIUM_FULL_DUPLEX | AX88772_MEDIUM_RX_FC_ENABLE | \ 106 AX88772_MEDIUM_TX_FC_ENABLE | AX88772_MEDIUM_100MB | \ 107 AX88772_MEDIUM_RESERVED | AX88772_MEDIUM_RX_ENABLE ) 108 109#define AX_EEPROM_MAGIC 0xdeadbeef 110 111/* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */ 112struct ax8817x_data { 113 u8 multi_filter[AX_MCAST_FILTER_SIZE]; 114}; 115 116struct ax88172_int_data { 117 u16 res1; 118 u8 link; 119 u16 res2; 120 u8 status; 121 u16 res3; 122} __attribute__ ((packed)); 123 124static int ax8817x_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, 125 u16 size, void *data) 126{ 127 return usb_control_msg( 128 dev->udev, 129 usb_rcvctrlpipe(dev->udev, 0), 130 cmd, 131 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 132 value, 133 index, 134 data, 135 size, 136 USB_CTRL_GET_TIMEOUT); 137} 138 139static int ax8817x_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, 140 u16 size, void *data) 141{ 142 return usb_control_msg( 143 dev->udev, 144 usb_sndctrlpipe(dev->udev, 0), 145 cmd, 146 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 147 value, 148 index, 149 data, 150 size, 151 USB_CTRL_SET_TIMEOUT); 152} 153 154static void ax8817x_async_cmd_callback(struct urb *urb, struct pt_regs *regs) 155{ 156 struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context; 157 158 if (urb->status < 0) 159 printk(KERN_DEBUG "ax8817x_async_cmd_callback() failed with %d", 160 urb->status); 161 162 kfree(req); 163 usb_free_urb(urb); 164} 165 166static void ax8817x_status(struct usbnet *dev, struct urb *urb) 167{ 168 struct ax88172_int_data *event; 169 int link; 170 171 if (urb->actual_length < 8) 172 return; 173 174 event = urb->transfer_buffer; 175 link = event->link & 0x01; 176 if (netif_carrier_ok(dev->net) != link) { 177 if (link) { 178 netif_carrier_on(dev->net); 179 usbnet_defer_kevent (dev, EVENT_LINK_RESET ); 180 } else 181 netif_carrier_off(dev->net); 182 devdbg(dev, "ax8817x - Link Status is: %d", link); 183 } 184} 185 186static void 187ax8817x_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index, 188 u16 size, void *data) 189{ 190 struct usb_ctrlrequest *req; 191 int status; 192 struct urb *urb; 193 194 if ((urb = usb_alloc_urb(0, GFP_ATOMIC)) == NULL) { 195 devdbg(dev, "Error allocating URB in write_cmd_async!"); 196 return; 197 } 198 199 if ((req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC)) == NULL) { 200 deverr(dev, "Failed to allocate memory for control request"); 201 usb_free_urb(urb); 202 return; 203 } 204 205 req->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE; 206 req->bRequest = cmd; 207 req->wValue = cpu_to_le16(value); 208 req->wIndex = cpu_to_le16(index); 209 req->wLength = cpu_to_le16(size); 210 211 usb_fill_control_urb(urb, dev->udev, 212 usb_sndctrlpipe(dev->udev, 0), 213 (void *)req, data, size, 214 ax8817x_async_cmd_callback, req); 215 216 if((status = usb_submit_urb(urb, GFP_ATOMIC)) < 0) { 217 deverr(dev, "Error submitting the control message: status=%d", 218 status); 219 kfree(req); 220 usb_free_urb(urb); 221 } 222} 223 224static void ax8817x_set_multicast(struct net_device *net) 225{ 226 struct usbnet *dev = netdev_priv(net); 227 struct ax8817x_data *data = (struct ax8817x_data *)&dev->data; 228 u8 rx_ctl = 0x8c; 229 230 if (net->flags & IFF_PROMISC) { 231 rx_ctl |= 0x01; 232 } else if (net->flags & IFF_ALLMULTI 233 || net->mc_count > AX_MAX_MCAST) { 234 rx_ctl |= 0x02; 235 } else if (net->mc_count == 0) { 236 /* just broadcast and directed */ 237 } else { 238 /* We use the 20 byte dev->data 239 * for our 8 byte filter buffer 240 * to avoid allocating memory that 241 * is tricky to free later */ 242 struct dev_mc_list *mc_list = net->mc_list; 243 u32 crc_bits; 244 int i; 245 246 memset(data->multi_filter, 0, AX_MCAST_FILTER_SIZE); 247 248 /* Build the multicast hash filter. */ 249 for (i = 0; i < net->mc_count; i++) { 250 crc_bits = 251 ether_crc(ETH_ALEN, 252 mc_list->dmi_addr) >> 26; 253 data->multi_filter[crc_bits >> 3] |= 254 1 << (crc_bits & 7); 255 mc_list = mc_list->next; 256 } 257 258 ax8817x_write_cmd_async(dev, AX_CMD_WRITE_MULTI_FILTER, 0, 0, 259 AX_MCAST_FILTER_SIZE, data->multi_filter); 260 261 rx_ctl |= 0x10; 262 } 263 264 ax8817x_write_cmd_async(dev, AX_CMD_WRITE_RX_CTL, rx_ctl, 0, 0, NULL); 265} 266 267static int ax8817x_mdio_read(struct net_device *netdev, int phy_id, int loc) 268{ 269 struct usbnet *dev = netdev_priv(netdev); 270 u16 res; 271 u8 buf[1]; 272 273 ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0, 0, 0, &buf); 274 ax8817x_read_cmd(dev, AX_CMD_READ_MII_REG, phy_id, 275 (__u16)loc, 2, (u16 *)&res); 276 ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, &buf); 277 278 return res & 0xffff; 279} 280 281/* same as above, but converts resulting value to cpu byte order */ 282static int ax8817x_mdio_read_le(struct net_device *netdev, int phy_id, int loc) 283{ 284 return le16_to_cpu(ax8817x_mdio_read(netdev,phy_id, loc)); 285} 286 287static void 288ax8817x_mdio_write(struct net_device *netdev, int phy_id, int loc, int val) 289{ 290 struct usbnet *dev = netdev_priv(netdev); 291 u16 res = val; 292 u8 buf[1]; 293 294 ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0, 0, 0, &buf); 295 ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id, 296 (__u16)loc, 2, (u16 *)&res); 297 ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, &buf); 298} 299 300/* same as above, but converts new value to le16 byte order before writing */ 301static void 302ax8817x_mdio_write_le(struct net_device *netdev, int phy_id, int loc, int val) 303{ 304 ax8817x_mdio_write( netdev, phy_id, loc, cpu_to_le16(val) ); 305} 306 307static int ax88172_link_reset(struct usbnet *dev) 308{ 309 u16 lpa; 310 u16 adv; 311 u16 res; 312 u8 mode; 313 314 mode = AX_MEDIUM_TX_ABORT_ALLOW | AX_MEDIUM_FLOW_CONTROL_EN; 315 lpa = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_LPA); 316 adv = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_ADVERTISE); 317 res = mii_nway_result(lpa|adv); 318 if (res & LPA_DUPLEX) 319 mode |= AX_MEDIUM_FULL_DUPLEX; 320 ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL); 321 322 return 0; 323} 324 325static void 326ax8817x_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo) 327{ 328 struct usbnet *dev = netdev_priv(net); 329 u8 opt; 330 331 if (ax8817x_read_cmd(dev, AX_CMD_READ_MONITOR_MODE, 0, 0, 1, &opt) < 0) { 332 wolinfo->supported = 0; 333 wolinfo->wolopts = 0; 334 return; 335 } 336 wolinfo->supported = WAKE_PHY | WAKE_MAGIC; 337 wolinfo->wolopts = 0; 338 if (opt & AX_MONITOR_MODE) { 339 if (opt & AX_MONITOR_LINK) 340 wolinfo->wolopts |= WAKE_PHY; 341 if (opt & AX_MONITOR_MAGIC) 342 wolinfo->wolopts |= WAKE_MAGIC; 343 } 344} 345 346static int 347ax8817x_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo) 348{ 349 struct usbnet *dev = netdev_priv(net); 350 u8 opt = 0; 351 u8 buf[1]; 352 353 if (wolinfo->wolopts & WAKE_PHY) 354 opt |= AX_MONITOR_LINK; 355 if (wolinfo->wolopts & WAKE_MAGIC) 356 opt |= AX_MONITOR_MAGIC; 357 if (opt != 0) 358 opt |= AX_MONITOR_MODE; 359 360 if (ax8817x_write_cmd(dev, AX_CMD_WRITE_MONITOR_MODE, 361 opt, 0, 0, &buf) < 0) 362 return -EINVAL; 363 364 return 0; 365} 366 367static int ax8817x_get_eeprom_len(struct net_device *net) 368{ 369 return AX_EEPROM_LEN; 370} 371 372static int ax8817x_get_eeprom(struct net_device *net, 373 struct ethtool_eeprom *eeprom, u8 *data) 374{ 375 struct usbnet *dev = netdev_priv(net); 376 u16 *ebuf = (u16 *)data; 377 int i; 378 379 /* Crude hack to ensure that we don't overwrite memory 380 * if an odd length is supplied 381 */ 382 if (eeprom->len % 2) 383 return -EINVAL; 384 385 eeprom->magic = AX_EEPROM_MAGIC; 386 387 /* ax8817x returns 2 bytes from eeprom on read */ 388 for (i=0; i < eeprom->len / 2; i++) { 389 if (ax8817x_read_cmd(dev, AX_CMD_READ_EEPROM, 390 eeprom->offset + i, 0, 2, &ebuf[i]) < 0) 391 return -EINVAL; 392 } 393 return 0; 394} 395 396static void ax8817x_get_drvinfo (struct net_device *net, 397 struct ethtool_drvinfo *info) 398{ 399 /* Inherit standard device info */ 400 usbnet_get_drvinfo(net, info); 401 info->eedump_len = 0x3e; 402} 403 404static int ax8817x_get_settings(struct net_device *net, struct ethtool_cmd *cmd) 405{ 406 struct usbnet *dev = netdev_priv(net); 407 408 return mii_ethtool_gset(&dev->mii,cmd); 409} 410 411static int ax8817x_set_settings(struct net_device *net, struct ethtool_cmd *cmd) 412{ 413 struct usbnet *dev = netdev_priv(net); 414 415 return mii_ethtool_sset(&dev->mii,cmd); 416} 417 418/* We need to override some ethtool_ops so we require our 419 own structure so we don't interfere with other usbnet 420 devices that may be connected at the same time. */ 421static struct ethtool_ops ax8817x_ethtool_ops = { 422 .get_drvinfo = ax8817x_get_drvinfo, 423 .get_link = ethtool_op_get_link, 424 .get_msglevel = usbnet_get_msglevel, 425 .set_msglevel = usbnet_set_msglevel, 426 .get_wol = ax8817x_get_wol, 427 .set_wol = ax8817x_set_wol, 428 .get_eeprom_len = ax8817x_get_eeprom_len, 429 .get_eeprom = ax8817x_get_eeprom, 430 .get_settings = ax8817x_get_settings, 431 .set_settings = ax8817x_set_settings, 432}; 433 434static int ax8817x_ioctl (struct net_device *net, struct ifreq *rq, int cmd) 435{ 436 struct usbnet *dev = netdev_priv(net); 437 438 return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL); 439} 440 441static int ax8817x_bind(struct usbnet *dev, struct usb_interface *intf) 442{ 443 int ret = 0; 444 void *buf; 445 int i; 446 unsigned long gpio_bits = dev->driver_info->data; 447 448 usbnet_get_endpoints(dev,intf); 449 450 buf = kmalloc(ETH_ALEN, GFP_KERNEL); 451 if(!buf) { 452 ret = -ENOMEM; 453 goto out1; 454 } 455 456 /* Toggle the GPIOs in a manufacturer/model specific way */ 457 for (i = 2; i >= 0; i--) { 458 if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS, 459 (gpio_bits >> (i * 8)) & 0xff, 0, 0, 460 buf)) < 0) 461 goto out2; 462 msleep(5); 463 } 464 465 if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, 466 0x80, 0, 0, buf)) < 0) { 467 dbg("send AX_CMD_WRITE_RX_CTL failed: %d", ret); 468 goto out2; 469 } 470 471 /* Get the MAC address */ 472 memset(buf, 0, ETH_ALEN); 473 if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_NODE_ID, 474 0, 0, 6, buf)) < 0) { 475 dbg("read AX_CMD_READ_NODE_ID failed: %d", ret); 476 goto out2; 477 } 478 memcpy(dev->net->dev_addr, buf, ETH_ALEN); 479 480 /* Get the PHY id */ 481 if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_PHY_ID, 482 0, 0, 2, buf)) < 0) { 483 dbg("error on read AX_CMD_READ_PHY_ID: %02x", ret); 484 goto out2; 485 } else if (ret < 2) { 486 /* this should always return 2 bytes */ 487 dbg("AX_CMD_READ_PHY_ID returned less than 2 bytes: ret=%02x", 488 ret); 489 ret = -EIO; 490 goto out2; 491 } 492 493 /* Initialize MII structure */ 494 dev->mii.dev = dev->net; 495 dev->mii.mdio_read = ax8817x_mdio_read; 496 dev->mii.mdio_write = ax8817x_mdio_write; 497 dev->mii.phy_id_mask = 0x3f; 498 dev->mii.reg_num_mask = 0x1f; 499 dev->mii.phy_id = *((u8 *)buf + 1); 500 dev->net->do_ioctl = ax8817x_ioctl; 501 502 dev->net->set_multicast_list = ax8817x_set_multicast; 503 dev->net->ethtool_ops = &ax8817x_ethtool_ops; 504 505 ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET); 506 ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_ADVERTISE, 507 ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP); 508 mii_nway_restart(&dev->mii); 509 510 return 0; 511out2: 512 kfree(buf); 513out1: 514 return ret; 515} 516 517static struct ethtool_ops ax88772_ethtool_ops = { 518 .get_drvinfo = ax8817x_get_drvinfo, 519 .get_link = ethtool_op_get_link, 520 .get_msglevel = usbnet_get_msglevel, 521 .set_msglevel = usbnet_set_msglevel, 522 .get_wol = ax8817x_get_wol, 523 .set_wol = ax8817x_set_wol, 524 .get_eeprom_len = ax8817x_get_eeprom_len, 525 .get_eeprom = ax8817x_get_eeprom, 526 .get_settings = ax8817x_get_settings, 527 .set_settings = ax8817x_set_settings, 528}; 529 530static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf) 531{ 532 int ret; 533 void *buf; 534 535 usbnet_get_endpoints(dev,intf); 536 537 buf = kmalloc(6, GFP_KERNEL); 538 if(!buf) { 539 dbg ("Cannot allocate memory for buffer"); 540 ret = -ENOMEM; 541 goto out1; 542 } 543 544 if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS, 545 0x00B0, 0, 0, buf)) < 0) 546 goto out2; 547 548 msleep(5); 549 if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_PHY_SELECT, 550 0x0001, 0, 0, buf)) < 0) { 551 dbg("Select PHY #1 failed: %d", ret); 552 goto out2; 553 } 554 555 if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_IPPD, 556 0, 0, buf)) < 0) { 557 dbg("Failed to power down internal PHY: %d", ret); 558 goto out2; 559 } 560 561 msleep(150); 562 if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_CLEAR, 563 0, 0, buf)) < 0) { 564 dbg("Failed to perform software reset: %d", ret); 565 goto out2; 566 } 567 568 msleep(150); 569 if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET, 570 AX_SWRESET_IPRL | AX_SWRESET_PRL, 571 0, 0, buf)) < 0) { 572 dbg("Failed to set Internal/External PHY reset control: %d", 573 ret); 574 goto out2; 575 } 576 577 msleep(150); 578 if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, 579 0x0000, 0, 0, buf)) < 0) { 580 dbg("Failed to reset RX_CTL: %d", ret); 581 goto out2; 582 } 583 584 /* Get the MAC address */ 585 memset(buf, 0, ETH_ALEN); 586 if ((ret = ax8817x_read_cmd(dev, AX88772_CMD_READ_NODE_ID, 587 0, 0, ETH_ALEN, buf)) < 0) { 588 dbg("Failed to read MAC address: %d", ret); 589 goto out2; 590 } 591 memcpy(dev->net->dev_addr, buf, ETH_ALEN); 592 593 if ((ret = ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 594 0, 0, 0, buf)) < 0) { 595 dbg("Enabling software MII failed: %d", ret); 596 goto out2; 597 } 598 599 if (((ret = ax8817x_read_cmd(dev, AX_CMD_READ_MII_REG, 600 0x0010, 2, 2, buf)) < 0) 601 || (*((u16 *)buf) != 0x003b)) { 602 dbg("Read PHY register 2 must be 0x3b00: %d", ret); 603 goto out2; 604 } 605 606 /* Initialize MII structure */ 607 dev->mii.dev = dev->net; 608 dev->mii.mdio_read = ax8817x_mdio_read; 609 dev->mii.mdio_write = ax8817x_mdio_write; 610 dev->mii.phy_id_mask = 0xff; 611 dev->mii.reg_num_mask = 0xff; 612 dev->net->do_ioctl = ax8817x_ioctl; 613 614 /* Get the PHY id */ 615 if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_PHY_ID, 616 0, 0, 2, buf)) < 0) { 617 dbg("Error reading PHY ID: %02x", ret); 618 goto out2; 619 } else if (ret < 2) { 620 /* this should always return 2 bytes */ 621 dbg("AX_CMD_READ_PHY_ID returned less than 2 bytes: ret=%02x", 622 ret); 623 ret = -EIO; 624 goto out2; 625 } 626 dev->mii.phy_id = *((u8 *)buf + 1); 627 628 if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_PRL, 629 0, 0, buf)) < 0) { 630 dbg("Set external PHY reset pin level: %d", ret); 631 goto out2; 632 } 633 msleep(150); 634 if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET, 635 AX_SWRESET_IPRL | AX_SWRESET_PRL, 636 0, 0, buf)) < 0) { 637 dbg("Set Internal/External PHY reset control: %d", ret); 638 goto out2; 639 } 640 msleep(150); 641 642 643 dev->net->set_multicast_list = ax8817x_set_multicast; 644 dev->net->ethtool_ops = &ax88772_ethtool_ops; 645 646 ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET); 647 ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_ADVERTISE, 648 ADVERTISE_ALL | ADVERTISE_CSMA); 649 mii_nway_restart(&dev->mii); 650 651 if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, 652 AX88772_MEDIUM_DEFAULT, 0, 0, buf)) < 0) { 653 dbg("Write medium mode register: %d", ret); 654 goto out2; 655 } 656 657 if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_IPG0, 658 AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT, 659 AX88772_IPG2_DEFAULT, 0, buf)) < 0) { 660 dbg("Write IPG,IPG1,IPG2 failed: %d", ret); 661 goto out2; 662 } 663 if ((ret = 664 ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, &buf)) < 0) { 665 dbg("Failed to set hardware MII: %02x", ret); 666 goto out2; 667 } 668 669 /* Set RX_CTL to default values with 2k buffer, and enable cactus */ 670 if ((ret = 671 ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, 0x0088, 0, 0, 672 buf)) < 0) { 673 dbg("Reset RX_CTL failed: %d", ret); 674 goto out2; 675 } 676 677 kfree(buf); 678 679 /* Asix framing packs multiple eth frames into a 2K usb bulk transfer */ 680 if (dev->driver_info->flags & FLAG_FRAMING_AX) { 681 /* hard_mtu is still the default - the device does not support 682 jumbo eth frames */ 683 dev->rx_urb_size = 2048; 684 } 685 686 return 0; 687 688out2: 689 kfree(buf); 690out1: 691 return ret; 692} 693 694static int ax88772_rx_fixup(struct usbnet *dev, struct sk_buff *skb) 695{ 696 u8 *head; 697 u32 header; 698 char *packet; 699 struct sk_buff *ax_skb; 700 u16 size; 701 702 head = (u8 *) skb->data; 703 memcpy(&header, head, sizeof(header)); 704 le32_to_cpus(&header); 705 packet = head + sizeof(header); 706 707 skb_pull(skb, 4); 708 709 while (skb->len > 0) { 710 if ((short)(header & 0x0000ffff) != 711 ~((short)((header & 0xffff0000) >> 16))) { 712 devdbg(dev,"header length data is error"); 713 } 714 /* get the packet length */ 715 size = (u16) (header & 0x0000ffff); 716 717 if ((skb->len) - ((size + 1) & 0xfffe) == 0) 718 return 2; 719 if (size > ETH_FRAME_LEN) { 720 devdbg(dev,"invalid rx length %d", size); 721 return 0; 722 } 723 ax_skb = skb_clone(skb, GFP_ATOMIC); 724 if (ax_skb) { 725 ax_skb->len = size; 726 ax_skb->data = packet; 727 ax_skb->tail = packet + size; 728 usbnet_skb_return(dev, ax_skb); 729 } else { 730 return 0; 731 } 732 733 skb_pull(skb, (size + 1) & 0xfffe); 734 735 if (skb->len == 0) 736 break; 737 738 head = (u8 *) skb->data; 739 memcpy(&header, head, sizeof(header)); 740 le32_to_cpus(&header); 741 packet = head + sizeof(header); 742 skb_pull(skb, 4); 743 } 744 745 if (skb->len < 0) { 746 devdbg(dev,"invalid rx length %d", skb->len); 747 return 0; 748 } 749 return 1; 750} 751 752static struct sk_buff *ax88772_tx_fixup(struct usbnet *dev, struct sk_buff *skb, 753 gfp_t flags) 754{ 755 int padlen; 756 int headroom = skb_headroom(skb); 757 int tailroom = skb_tailroom(skb); 758 u32 packet_len; 759 u32 padbytes = 0xffff0000; 760 761 padlen = ((skb->len + 4) % 512) ? 0 : 4; 762 763 if ((!skb_cloned(skb)) 764 && ((headroom + tailroom) >= (4 + padlen))) { 765 if ((headroom < 4) || (tailroom < padlen)) { 766 skb->data = memmove(skb->head + 4, skb->data, skb->len); 767 skb->tail = skb->data + skb->len; 768 } 769 } else { 770 struct sk_buff *skb2; 771 skb2 = skb_copy_expand(skb, 4, padlen, flags); 772 dev_kfree_skb_any(skb); 773 skb = skb2; 774 if (!skb) 775 return NULL; 776 } 777 778 skb_push(skb, 4); 779 packet_len = (((skb->len - 4) ^ 0x0000ffff) << 16) + (skb->len - 4); 780 memcpy(skb->data, &packet_len, sizeof(packet_len)); 781 782 if ((skb->len % 512) == 0) { 783 memcpy( skb->tail, &padbytes, sizeof(padbytes)); 784 skb_put(skb, sizeof(padbytes)); 785 } 786 return skb; 787} 788 789static int ax88772_link_reset(struct usbnet *dev) 790{ 791 u16 lpa; 792 u16 adv; 793 u16 res; 794 u16 mode; 795 796 mode = AX88772_MEDIUM_DEFAULT; 797 lpa = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_LPA); 798 adv = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_ADVERTISE); 799 res = mii_nway_result(lpa|adv); 800 801 if ((res & LPA_DUPLEX) == 0) 802 mode &= ~AX88772_MEDIUM_FULL_DUPLEX; 803 if ((res & LPA_100) == 0) 804 mode &= ~AX88772_MEDIUM_100MB; 805 ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL); 806 807 return 0; 808} 809 810static const struct driver_info ax8817x_info = { 811 .description = "ASIX AX8817x USB 2.0 Ethernet", 812 .bind = ax8817x_bind, 813 .status = ax8817x_status, 814 .link_reset = ax88172_link_reset, 815 .reset = ax88172_link_reset, 816 .flags = FLAG_ETHER, 817 .data = 0x00130103, 818}; 819 820static const struct driver_info dlink_dub_e100_info = { 821 .description = "DLink DUB-E100 USB Ethernet", 822 .bind = ax8817x_bind, 823 .status = ax8817x_status, 824 .link_reset = ax88172_link_reset, 825 .reset = ax88172_link_reset, 826 .flags = FLAG_ETHER, 827 .data = 0x009f9d9f, 828}; 829 830static const struct driver_info netgear_fa120_info = { 831 .description = "Netgear FA-120 USB Ethernet", 832 .bind = ax8817x_bind, 833 .status = ax8817x_status, 834 .link_reset = ax88172_link_reset, 835 .reset = ax88172_link_reset, 836 .flags = FLAG_ETHER, 837 .data = 0x00130103, 838}; 839 840static const struct driver_info hawking_uf200_info = { 841 .description = "Hawking UF200 USB Ethernet", 842 .bind = ax8817x_bind, 843 .status = ax8817x_status, 844 .link_reset = ax88172_link_reset, 845 .reset = ax88172_link_reset, 846 .flags = FLAG_ETHER, 847 .data = 0x001f1d1f, 848}; 849 850static const struct driver_info ax88772_info = { 851 .description = "ASIX AX88772 USB 2.0 Ethernet", 852 .bind = ax88772_bind, 853 .status = ax8817x_status, 854 .link_reset = ax88772_link_reset, 855 .reset = ax88772_link_reset, 856 .flags = FLAG_ETHER | FLAG_FRAMING_AX, 857 .rx_fixup = ax88772_rx_fixup, 858 .tx_fixup = ax88772_tx_fixup, 859 .data = 0x00130103, 860}; 861 862static const struct usb_device_id products [] = { 863{ 864 // Linksys USB200M 865 USB_DEVICE (0x077b, 0x2226), 866 .driver_info = (unsigned long) &ax8817x_info, 867}, { 868 // Netgear FA120 869 USB_DEVICE (0x0846, 0x1040), 870 .driver_info = (unsigned long) &netgear_fa120_info, 871}, { 872 // DLink DUB-E100 873 USB_DEVICE (0x2001, 0x1a00), 874 .driver_info = (unsigned long) &dlink_dub_e100_info, 875}, { 876 // Intellinet, ST Lab USB Ethernet 877 USB_DEVICE (0x0b95, 0x1720), 878 .driver_info = (unsigned long) &ax8817x_info, 879}, { 880 // Hawking UF200, TrendNet TU2-ET100 881 USB_DEVICE (0x07b8, 0x420a), 882 .driver_info = (unsigned long) &hawking_uf200_info, 883}, { 884 // Billionton Systems, USB2AR 885 USB_DEVICE (0x08dd, 0x90ff), 886 .driver_info = (unsigned long) &ax8817x_info, 887}, { 888 // ATEN UC210T 889 USB_DEVICE (0x0557, 0x2009), 890 .driver_info = (unsigned long) &ax8817x_info, 891}, { 892 // Buffalo LUA-U2-KTX 893 USB_DEVICE (0x0411, 0x003d), 894 .driver_info = (unsigned long) &ax8817x_info, 895}, { 896 // Sitecom LN-029 "USB 2.0 10/100 Ethernet adapter" 897 USB_DEVICE (0x6189, 0x182d), 898 .driver_info = (unsigned long) &ax8817x_info, 899}, { 900 // corega FEther USB2-TX 901 USB_DEVICE (0x07aa, 0x0017), 902 .driver_info = (unsigned long) &ax8817x_info, 903}, { 904 // Surecom EP-1427X-2 905 USB_DEVICE (0x1189, 0x0893), 906 .driver_info = (unsigned long) &ax8817x_info, 907}, { 908 // goodway corp usb gwusb2e 909 USB_DEVICE (0x1631, 0x6200), 910 .driver_info = (unsigned long) &ax8817x_info, 911}, { 912 // ASIX AX88772 10/100 913 USB_DEVICE (0x0b95, 0x7720), 914 .driver_info = (unsigned long) &ax88772_info, 915}, 916 { }, // END 917}; 918MODULE_DEVICE_TABLE(usb, products); 919 920static struct usb_driver asix_driver = { 921 .owner = THIS_MODULE, 922 .name = "asix", 923 .id_table = products, 924 .probe = usbnet_probe, 925 .suspend = usbnet_suspend, 926 .resume = usbnet_resume, 927 .disconnect = usbnet_disconnect, 928}; 929 930static int __init asix_init(void) 931{ 932 return usb_register(&asix_driver); 933} 934module_init(asix_init); 935 936static void __exit asix_exit(void) 937{ 938 usb_deregister(&asix_driver); 939} 940module_exit(asix_exit); 941 942MODULE_AUTHOR("David Hollis"); 943MODULE_DESCRIPTION("ASIX AX8817X based USB 2.0 Ethernet Devices"); 944MODULE_LICENSE("GPL"); 945