📄 kaweth.c
字号:
else { dbg("Set Rx mode to %d", packet_filter_bitmap); } }}/**************************************************************** * kaweth_netdev_stats ****************************************************************/static struct net_device_stats *kaweth_netdev_stats(struct net_device *dev){ struct kaweth_device *kaweth = netdev_priv(dev); return &kaweth->stats;}/**************************************************************** * kaweth_tx_timeout ****************************************************************/static void kaweth_tx_timeout(struct net_device *net){ struct kaweth_device *kaweth = netdev_priv(net); warn("%s: Tx timed out. Resetting.", net->name); kaweth->stats.tx_errors++; net->trans_start = jiffies; usb_unlink_urb(kaweth->tx_urb);}/**************************************************************** * kaweth_suspend ****************************************************************/static int kaweth_suspend(struct usb_interface *intf, pm_message_t message){ struct kaweth_device *kaweth = usb_get_intfdata(intf); unsigned long flags; dbg("Suspending device"); spin_lock_irqsave(&kaweth->device_lock, flags); kaweth->status |= KAWETH_STATUS_SUSPENDING; spin_unlock_irqrestore(&kaweth->device_lock, flags); kaweth_kill_urbs(kaweth); return 0;}/**************************************************************** * kaweth_resume ****************************************************************/static int kaweth_resume(struct usb_interface *intf){ struct kaweth_device *kaweth = usb_get_intfdata(intf); unsigned long flags; dbg("Resuming device"); spin_lock_irqsave(&kaweth->device_lock, flags); kaweth->status &= ~KAWETH_STATUS_SUSPENDING; spin_unlock_irqrestore(&kaweth->device_lock, flags); if (!kaweth->opened) return 0; kaweth_resubmit_rx_urb(kaweth, GFP_NOIO); kaweth_resubmit_int_urb(kaweth, GFP_NOIO); return 0;}/**************************************************************** * kaweth_probe ****************************************************************/static int kaweth_probe( struct usb_interface *intf, const struct usb_device_id *id /* from id_table */ ){ struct usb_device *dev = interface_to_usbdev(intf); struct kaweth_device *kaweth; struct net_device *netdev; const eth_addr_t bcast_addr = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; int result = 0; dbg("Kawasaki Device Probe (Device number:%d): 0x%4.4x:0x%4.4x:0x%4.4x", dev->devnum, le16_to_cpu(dev->descriptor.idVendor), le16_to_cpu(dev->descriptor.idProduct), le16_to_cpu(dev->descriptor.bcdDevice)); dbg("Device at %p", dev); dbg("Descriptor length: %x type: %x", (int)dev->descriptor.bLength, (int)dev->descriptor.bDescriptorType); netdev = alloc_etherdev(sizeof(*kaweth)); if (!netdev) return -ENOMEM; kaweth = netdev_priv(netdev); kaweth->dev = dev; kaweth->net = netdev; spin_lock_init(&kaweth->device_lock); init_waitqueue_head(&kaweth->term_wait); dbg("Resetting."); kaweth_reset(kaweth); /* * If high byte of bcdDevice is nonzero, firmware is already * downloaded. Don't try to do it again, or we'll hang the device. */ if (le16_to_cpu(dev->descriptor.bcdDevice) >> 8) { info("Firmware present in device."); } else { /* Download the firmware */ info("Downloading firmware..."); kaweth->firmware_buf = (__u8 *)__get_free_page(GFP_KERNEL); if ((result = kaweth_download_firmware(kaweth, kaweth_new_code, len_kaweth_new_code, 100, 2)) < 0) { err("Error downloading firmware (%d)", result); goto err_fw; } if ((result = kaweth_download_firmware(kaweth, kaweth_new_code_fix, len_kaweth_new_code_fix, 100, 3)) < 0) { err("Error downloading firmware fix (%d)", result); goto err_fw; } if ((result = kaweth_download_firmware(kaweth, kaweth_trigger_code, len_kaweth_trigger_code, 126, 2)) < 0) { err("Error downloading trigger code (%d)", result); goto err_fw; } if ((result = kaweth_download_firmware(kaweth, kaweth_trigger_code_fix, len_kaweth_trigger_code_fix, 126, 3)) < 0) { err("Error downloading trigger code fix (%d)", result); goto err_fw; } if ((result = kaweth_trigger_firmware(kaweth, 126)) < 0) { err("Error triggering firmware (%d)", result); goto err_fw; } /* Device will now disappear for a moment... */ info("Firmware loaded. I'll be back...");err_fw: free_page((unsigned long)kaweth->firmware_buf); free_netdev(netdev); return -EIO; } result = kaweth_read_configuration(kaweth); if(result < 0) { err("Error reading configuration (%d), no net device created", result); goto err_free_netdev; } info("Statistics collection: %x", kaweth->configuration.statistics_mask); info("Multicast filter limit: %x", kaweth->configuration.max_multicast_filters & ((1 << 15) - 1)); info("MTU: %d", le16_to_cpu(kaweth->configuration.segment_size)); info("Read MAC address %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x", (int)kaweth->configuration.hw_addr[0], (int)kaweth->configuration.hw_addr[1], (int)kaweth->configuration.hw_addr[2], (int)kaweth->configuration.hw_addr[3], (int)kaweth->configuration.hw_addr[4], (int)kaweth->configuration.hw_addr[5]); if(!memcmp(&kaweth->configuration.hw_addr, &bcast_addr, sizeof(bcast_addr))) { err("Firmware not functioning properly, no net device created"); goto err_free_netdev; } if(kaweth_set_urb_size(kaweth, KAWETH_BUF_SIZE) < 0) { dbg("Error setting URB size"); goto err_free_netdev; } if(kaweth_set_sofs_wait(kaweth, KAWETH_SOFS_TO_WAIT) < 0) { err("Error setting SOFS wait"); goto err_free_netdev; } result = kaweth_set_receive_filter(kaweth, KAWETH_PACKET_FILTER_DIRECTED | KAWETH_PACKET_FILTER_BROADCAST | KAWETH_PACKET_FILTER_MULTICAST); if(result < 0) { err("Error setting receive filter"); goto err_free_netdev; } dbg("Initializing net device."); kaweth->intf = intf; kaweth->tx_urb = usb_alloc_urb(0, GFP_KERNEL); if (!kaweth->tx_urb) goto err_free_netdev; kaweth->rx_urb = usb_alloc_urb(0, GFP_KERNEL); if (!kaweth->rx_urb) goto err_only_tx; kaweth->irq_urb = usb_alloc_urb(0, GFP_KERNEL); if (!kaweth->irq_urb) goto err_tx_and_rx; kaweth->intbuffer = usb_buffer_alloc( kaweth->dev, INTBUFFERSIZE, GFP_KERNEL, &kaweth->intbufferhandle); if (!kaweth->intbuffer) goto err_tx_and_rx_and_irq; kaweth->rx_buf = usb_buffer_alloc( kaweth->dev, KAWETH_BUF_SIZE, GFP_KERNEL, &kaweth->rxbufferhandle); if (!kaweth->rx_buf) goto err_all_but_rxbuf; memcpy(netdev->broadcast, &bcast_addr, sizeof(bcast_addr)); memcpy(netdev->dev_addr, &kaweth->configuration.hw_addr, sizeof(kaweth->configuration.hw_addr)); netdev->open = kaweth_open; netdev->stop = kaweth_close; netdev->watchdog_timeo = KAWETH_TX_TIMEOUT; netdev->tx_timeout = kaweth_tx_timeout; netdev->hard_start_xmit = kaweth_start_xmit; netdev->set_multicast_list = kaweth_set_rx_mode; netdev->get_stats = kaweth_netdev_stats; netdev->mtu = le16_to_cpu(kaweth->configuration.segment_size); SET_ETHTOOL_OPS(netdev, &ops); /* kaweth is zeroed as part of alloc_netdev */ INIT_DELAYED_WORK(&kaweth->lowmem_work, kaweth_resubmit_tl); usb_set_intfdata(intf, kaweth);#if 0// dma_supported() is deeply broken on almost all architectures if (dma_supported (&intf->dev, 0xffffffffffffffffULL)) kaweth->net->features |= NETIF_F_HIGHDMA;#endif SET_NETDEV_DEV(netdev, &intf->dev); if (register_netdev(netdev) != 0) { err("Error registering netdev."); goto err_intfdata; } info("kaweth interface created at %s", kaweth->net->name); dbg("Kaweth probe returning."); return 0;err_intfdata: usb_set_intfdata(intf, NULL); usb_buffer_free(kaweth->dev, KAWETH_BUF_SIZE, (void *)kaweth->rx_buf, kaweth->rxbufferhandle);err_all_but_rxbuf: usb_buffer_free(kaweth->dev, INTBUFFERSIZE, (void *)kaweth->intbuffer, kaweth->intbufferhandle);err_tx_and_rx_and_irq: usb_free_urb(kaweth->irq_urb);err_tx_and_rx: usb_free_urb(kaweth->rx_urb);err_only_tx: usb_free_urb(kaweth->tx_urb);err_free_netdev: free_netdev(netdev); return -EIO;}/**************************************************************** * kaweth_disconnect ****************************************************************/static void kaweth_disconnect(struct usb_interface *intf){ struct kaweth_device *kaweth = usb_get_intfdata(intf); struct net_device *netdev; info("Unregistering"); usb_set_intfdata(intf, NULL); if (!kaweth) { warn("unregistering non-existant device"); return; } netdev = kaweth->net; dbg("Unregistering net device"); unregister_netdev(netdev); usb_free_urb(kaweth->rx_urb); usb_free_urb(kaweth->tx_urb); usb_free_urb(kaweth->irq_urb); usb_buffer_free(kaweth->dev, KAWETH_BUF_SIZE, (void *)kaweth->rx_buf, kaweth->rxbufferhandle); usb_buffer_free(kaweth->dev, INTBUFFERSIZE, (void *)kaweth->intbuffer, kaweth->intbufferhandle); free_netdev(netdev);}// FIXME this completion stuff is a modified clone of// an OLD version of some stuff in usb.c ...struct usb_api_data { wait_queue_head_t wqh; int done;};/*-------------------------------------------------------------------* * completion handler for compatibility wrappers (sync control/bulk) * *-------------------------------------------------------------------*/static void usb_api_blocking_completion(struct urb *urb){ struct usb_api_data *awd = (struct usb_api_data *)urb->context; awd->done=1; wake_up(&awd->wqh);}/*-------------------------------------------------------------------* * COMPATIBILITY STUFF * *-------------------------------------------------------------------*/// Starts urb and waits for completion or timeoutstatic int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length){ struct usb_api_data awd; int status; init_waitqueue_head(&awd.wqh); awd.done = 0; urb->context = &awd; status = usb_submit_urb(urb, GFP_NOIO); if (status) { // something went wrong usb_free_urb(urb); return status; } if (!wait_event_timeout(awd.wqh, awd.done, timeout)) { // timeout warn("usb_control/bulk_msg: timeout"); usb_kill_urb(urb); // remove urb safely status = -ETIMEDOUT; } else { status = urb->status; } if (actual_length) { *actual_length = urb->actual_length; } usb_free_urb(urb); return status;}/*-------------------------------------------------------------------*/// returns status (negative) or length (positive)static int kaweth_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe, struct usb_ctrlrequest *cmd, void *data, int len, int timeout){ struct urb *urb; int retv; int length = 0; /* shut up GCC */ urb = usb_alloc_urb(0, GFP_NOIO); if (!urb) return -ENOMEM; usb_fill_control_urb(urb, usb_dev, pipe, (unsigned char*)cmd, data, len, usb_api_blocking_completion, NULL); retv = usb_start_wait_urb(urb, timeout, &length); if (retv < 0) { return retv; } else { return length; }}/**************************************************************** * kaweth_init ****************************************************************/static int __init kaweth_init(void){ dbg("Driver loading"); return usb_register(&kaweth_driver);}/**************************************************************** * kaweth_exit ****************************************************************/static void __exit kaweth_exit(void){ usb_deregister(&kaweth_driver);}module_init(kaweth_init);module_exit(kaweth_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -