📄 catc.c
字号:
dr->request = q->request; dr->requesttype = 0x40 | q->dir; dr->value = cpu_to_le16(q->value); dr->index = cpu_to_le16(q->index); dr->length = cpu_to_le16(q->len); urb->pipe = q->dir ? usb_rcvctrlpipe(usbdev, 0) : usb_sndctrlpipe(usbdev, 0); urb->transfer_buffer_length = q->len; urb->transfer_buffer = catc->ctrl_buf; urb->setup_packet = (void *) dr; urb->dev = usbdev; if (!q->dir && q->buf && q->len) memcpy(catc->ctrl_buf, q->buf, q->len); if ((status = usb_submit_urb(&catc->ctrl_urb))) err("submit(ctrl_urb) status %d", status);}static void catc_ctrl_done(struct urb *urb){ struct catc *catc = urb->context; struct ctrl_queue *q; long flags; if (urb->status) dbg("ctrl_done, status %d, len %d.", urb->status, urb->actual_length); spin_lock_irqsave(&catc->ctrl_lock, flags); q = catc->ctrl_queue + catc->ctrl_tail; if (q->dir) { if (q->buf && q->len) memcpy(q->buf, catc->ctrl_buf, q->len); else q->buf = catc->ctrl_buf; } if (q->callback) q->callback(catc, q); catc->ctrl_tail = (catc->ctrl_tail + 1) & (CTRL_QUEUE - 1); if (catc->ctrl_head != catc->ctrl_tail) catc_ctrl_run(catc); else clear_bit(CTRL_RUNNING, &catc->flags); spin_unlock_irqrestore(&catc->ctrl_lock, flags);}static int catc_ctrl_async(struct catc *catc, u8 dir, u8 request, u16 value, u16 index, void *buf, int len, void (*callback)(struct catc *catc, struct ctrl_queue *q)){ struct ctrl_queue *q; int retval = 0; long flags; spin_lock_irqsave(&catc->ctrl_lock, flags); q = catc->ctrl_queue + catc->ctrl_head; q->dir = dir; q->request = request; q->value = value; q->index = index; q->buf = buf; q->len = len; q->callback = callback; catc->ctrl_head = (catc->ctrl_head + 1) & (CTRL_QUEUE - 1); if (catc->ctrl_head == catc->ctrl_tail) { err("ctrl queue full"); catc->ctrl_tail = (catc->ctrl_tail + 1) & (CTRL_QUEUE - 1); retval = -1; } if (!test_and_set_bit(CTRL_RUNNING, &catc->flags)) catc_ctrl_run(catc); spin_unlock_irqrestore(&catc->ctrl_lock, flags); return retval;}/* * Statistics. */static void catc_stats_done(struct catc *catc, struct ctrl_queue *q){ int index = q->index - EthStats; u16 data, last; catc->stats_buf[index] = *((char *)q->buf); if (index & 1) return; data = ((u16)catc->stats_buf[index] << 8) | catc->stats_buf[index + 1]; last = catc->stats_vals[index >> 1]; switch (index) { case TxSingleColl: case TxMultiColl: catc->stats.collisions += data - last; break; case TxExcessColl: catc->stats.tx_aborted_errors += data - last; catc->stats.tx_errors += data - last; break; case RxFramErr: catc->stats.rx_frame_errors += data - last; catc->stats.rx_errors += data - last; break; } catc->stats_vals[index >> 1] = data;}static void catc_stats_timer(unsigned long data){ struct catc *catc = (void *) data; int i; for (i = 0; i < 8; i++) catc_get_reg_async(catc, EthStats + 7 - i, catc_stats_done); mod_timer(&catc->timer, jiffies + STATS_UPDATE);}static struct net_device_stats *catc_get_stats(struct net_device *netdev){ struct catc *catc = netdev->priv; return &catc->stats;}/* * Receive modes. Broadcast, Multicast, Promisc. */static void catc_multicast(unsigned char *addr, u8 *multicast){ unsigned int crc = 0xffffffff; u8 byte, idx, bit; for (idx = 0; idx < 6; idx++) for (byte = *addr++, bit = 0; bit < 8; bit++, byte >>= 1) crc = (crc >> 1) ^ (((crc ^ byte) & 1) ? 0xedb88320U : 0); multicast[(crc >> 3) & 0x3f] |= 1 << (crc & 7);}static void catc_set_multicast_list(struct net_device *netdev){ struct catc *catc = netdev->priv; struct dev_mc_list *mc; u8 broadcast[6]; u8 rx = RxEnable | RxPolarity | RxMultiCast; int i; memset(broadcast, 0xff, 6); memset(catc->multicast, 0, 64); catc_multicast(broadcast, catc->multicast); catc_multicast(netdev->dev_addr, catc->multicast); if (netdev->flags & IFF_PROMISC) { memset(catc->multicast, 0xff, 64); rx |= RxPromisc; } if (netdev->flags & IFF_ALLMULTI) memset(catc->multicast, 0xff, 64); for (i = 0, mc = netdev->mc_list; mc && i < netdev->mc_count; i++, mc = mc->next) catc_multicast(mc->dmi_addr, catc->multicast); catc_set_reg_async(catc, RxUnit, rx); catc_write_mem_async(catc, 0xfa80, catc->multicast, 64);}/* * Open, close. */static int catc_open(struct net_device *netdev){ struct catc *catc = netdev->priv; int status; catc->irq_urb.dev = catc->usbdev; if ((status = usb_submit_urb(&catc->irq_urb)) < 0) { err("submit(irq_urb) status %d", status); return -1; } netif_start_queue(netdev); mod_timer(&catc->timer, jiffies + STATS_UPDATE); return 0;}static int catc_stop(struct net_device *netdev){ struct catc *catc = netdev->priv; netif_stop_queue(netdev); del_timer_sync(&catc->timer); usb_unlink_urb(&catc->rx_urb); usb_unlink_urb(&catc->tx_urb); usb_unlink_urb(&catc->irq_urb); usb_unlink_urb(&catc->ctrl_urb); return 0;}/* * USB probe, disconnect. */static void *catc_probe(struct usb_device *usbdev, unsigned int ifnum, const struct usb_device_id *id){ struct net_device *netdev; struct catc *catc; u8 broadcast[6]; int i; if (usb_set_interface(usbdev, ifnum, 1)) { err("Can't set altsetting 1."); return NULL; } catc = kmalloc(sizeof(struct catc), GFP_KERNEL); memset(catc, 0, sizeof(struct catc)); netdev = init_etherdev(0, 0); netdev->open = catc_open; netdev->hard_start_xmit = catc_hard_start_xmit; netdev->stop = catc_stop; netdev->get_stats = catc_get_stats; netdev->tx_timeout = catc_tx_timeout; netdev->watchdog_timeo = TX_TIMEOUT; netdev->set_multicast_list = catc_set_multicast_list; netdev->priv = catc; catc->usbdev = usbdev; catc->netdev = netdev; catc->tx_lock = SPIN_LOCK_UNLOCKED; catc->ctrl_lock = SPIN_LOCK_UNLOCKED; init_timer(&catc->timer); catc->timer.data = (long) catc; catc->timer.function = catc_stats_timer; FILL_CONTROL_URB(&catc->ctrl_urb, usbdev, usb_sndctrlpipe(usbdev, 0), NULL, NULL, 0, catc_ctrl_done, catc); FILL_BULK_URB(&catc->tx_urb, usbdev, usb_sndbulkpipe(usbdev, 1), NULL, 0, catc_tx_done, catc); FILL_BULK_URB(&catc->rx_urb, usbdev, usb_rcvbulkpipe(usbdev, 1), catc->rx_buf, RX_MAX_BURST * (PKT_SZ + 2), catc_rx_done, catc); FILL_INT_URB(&catc->irq_urb, usbdev, usb_rcvintpipe(usbdev, 2), catc->irq_buf, 2, catc_irq_done, catc, 1); dbg("Checking memory size\n"); i = 0x12345678; catc_write_mem(catc, 0x7a80, &i, 4); i = 0x87654321; catc_write_mem(catc, 0xfa80, &i, 4); catc_read_mem(catc, 0x7a80, &i, 4); switch (i) { case 0x12345678: catc_set_reg(catc, TxBufCount, 8); catc_set_reg(catc, RxBufCount, 32); dbg("64k Memory\n"); break; default: warn("Couldn't detect memory size, assuming 32k"); case 0x87654321: catc_set_reg(catc, TxBufCount, 4); catc_set_reg(catc, RxBufCount, 16); dbg("32k Memory\n"); break; } dbg("Getting MAC from SEEROM."); catc_get_mac(catc, netdev->dev_addr); dbg("Setting MAC into registers."); for (i = 0; i < 6; i++) catc_set_reg(catc, StationAddr0 - i, netdev->dev_addr[i]); dbg("Filling the multicast list."); memset(broadcast, 0xff, 8); catc_multicast(broadcast, catc->multicast); catc_multicast(netdev->dev_addr, catc->multicast); catc_write_mem(catc, 0xfa80, catc->multicast, 64); dbg("Clearing error counters."); for (i = 0; i < 8; i++) catc_set_reg(catc, EthStats + i, 0); catc->last_stats = jiffies; dbg("Enabling."); catc_set_reg(catc, MaxBurst, RX_MAX_BURST); catc_set_reg(catc, OpModes, OpTxMerge | OpRxMerge | OpLenInclude | Op3MemWaits); catc_set_reg(catc, LEDCtrl, LEDLink); catc_set_reg(catc, RxUnit, RxEnable | RxPolarity | RxMultiCast); dbg("Init done."); printk(KERN_INFO "%s: CATC EL1210A NetMate USB Ethernet at usb%d:%d.%d, ", netdev->name, usbdev->bus->busnum, usbdev->devnum, ifnum); for (i = 0; i < 5; i++) printk("%2.2x:", netdev->dev_addr[i]); printk("%2.2x.\n", netdev->dev_addr[i]); return catc;}static void catc_disconnect(struct usb_device *usbdev, void *dev_ptr){ struct catc *catc = dev_ptr; unregister_netdev(catc->netdev); kfree(catc->netdev); kfree(catc);}/* * Module functions and tables. */static struct usb_device_id catc_id_table [] = { { USB_DEVICE(0x0423, 0xa) }, /* CATC Netmate */ { USB_DEVICE(0x0423, 0xc) }, /* CATC Netmate II, Belkin F5U111 */ { USB_DEVICE(0x08d1, 0x1) }, /* smartBridges smartNIC */ { }};MODULE_DEVICE_TABLE(usb, catc_id_table);static struct usb_driver catc_driver = { name: "catc", probe: catc_probe, disconnect: catc_disconnect, id_table: catc_id_table,};static int __init catc_init(void){ info(DRIVER_VERSION " " DRIVER_DESC); usb_register(&catc_driver); return 0;}static void __exit catc_exit(void){ usb_deregister(&catc_driver);}module_init(catc_init);module_exit(catc_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -