📄 usb_atm.c
字号:
struct udsl_vcc_data *new; unsigned int max_pdu; int vci = vcc->vci; short vpi = vcc->vpi; int err; dbg("udsl_atm_open: vpi %hd, vci %d", vpi, vci); if (!instance) { dbg("udsl_atm_open: NULL data!"); return -ENODEV; } /* only support AAL5 */ if ((vcc->qos.aal != ATM_AAL5) || (vcc->qos.rxtp.max_sdu < 0) || (vcc->qos.rxtp.max_sdu > ATM_MAX_AAL5_PDU)) { dbg("udsl_atm_open: unsupported ATM type %d!", vcc->qos.aal); return -EINVAL; } if (instance->firmware_wait && (err = instance->firmware_wait(instance)) < 0) { dbg("udsl_atm_open: firmware not loaded (%d)!", err); return err; } down(&instance->serialize); /* vs self, udsl_atm_close */ if (udsl_find_vcc(instance, vpi, vci)) { dbg("udsl_atm_open: %hd/%d already in use!", vpi, vci); up(&instance->serialize); return -EADDRINUSE; } if (!(new = kmalloc(sizeof(struct udsl_vcc_data), GFP_KERNEL))) { dbg("udsl_atm_open: no memory for vcc_data!"); up(&instance->serialize); return -ENOMEM; } memset(new, 0, sizeof(struct udsl_vcc_data)); new->vcc = vcc; new->vpi = vpi; new->vci = vci; /* udsl_extract_cells requires at least one cell */ max_pdu = max(1, UDSL_NUM_CELLS(vcc->qos.rxtp.max_sdu)) * ATM_CELL_PAYLOAD; if (!(new->sarb = alloc_skb(max_pdu, GFP_KERNEL))) { dbg("udsl_atm_open: no memory for SAR buffer!"); kfree(new); up(&instance->serialize); return -ENOMEM; } vcc->dev_data = new; tasklet_disable(&instance->receive_tasklet); list_add(&new->list, &instance->vcc_list); tasklet_enable(&instance->receive_tasklet); set_bit(ATM_VF_ADDR, &vcc->flags); set_bit(ATM_VF_PARTIAL, &vcc->flags); set_bit(ATM_VF_READY, &vcc->flags); up(&instance->serialize); tasklet_schedule(&instance->receive_tasklet); dbg("udsl_atm_open: allocated vcc data 0x%p (max_pdu: %u)", new, max_pdu); return 0;}static void udsl_atm_close(struct atm_vcc *vcc){ struct udsl_instance_data *instance = vcc->dev->dev_data; struct udsl_vcc_data *vcc_data = vcc->dev_data; dbg("udsl_atm_close called"); if (!instance || !vcc_data) { dbg("udsl_atm_close: NULL data!"); return; } dbg("udsl_atm_close: deallocating vcc 0x%p with vpi %d vci %d", vcc_data, vcc_data->vpi, vcc_data->vci); udsl_cancel_send(instance, vcc); down(&instance->serialize); /* vs self, udsl_atm_open */ tasklet_disable(&instance->receive_tasklet); list_del(&vcc_data->list); tasklet_enable(&instance->receive_tasklet); kfree_skb(vcc_data->sarb); vcc_data->sarb = NULL; kfree(vcc_data); vcc->dev_data = NULL; vcc->vpi = ATM_VPI_UNSPEC; vcc->vci = ATM_VCI_UNSPEC; clear_bit(ATM_VF_READY, &vcc->flags); clear_bit(ATM_VF_PARTIAL, &vcc->flags); clear_bit(ATM_VF_ADDR, &vcc->flags); up(&instance->serialize); dbg("udsl_atm_close successful");}static int udsl_atm_ioctl(struct atm_dev *dev, unsigned int cmd, void __user * arg){ switch (cmd) { case ATM_QUERYLOOP: return put_user(ATM_LM_NONE, (int __user *)arg) ? -EFAULT : 0; default: return -ENOIOCTLCMD; }}/************ USB ************/int udsl_instance_setup(struct usb_device *dev, struct udsl_instance_data *instance){ char *buf; int i, length; kref_init(&instance->refcount); /* one for USB */ udsl_get_instance(instance); /* one for ATM */ init_MUTEX(&instance->serialize); instance->usb_dev = dev; INIT_LIST_HEAD(&instance->vcc_list); instance->status = UDSL_NO_FIRMWARE; init_waitqueue_head(&instance->firmware_waiters); spin_lock_init(&instance->receive_lock); INIT_LIST_HEAD(&instance->spare_receivers); INIT_LIST_HEAD(&instance->filled_receive_buffers); tasklet_init(&instance->receive_tasklet, udsl_process_receive, (unsigned long)instance); INIT_LIST_HEAD(&instance->spare_receive_buffers); skb_queue_head_init(&instance->sndqueue); spin_lock_init(&instance->send_lock); INIT_LIST_HEAD(&instance->spare_senders); INIT_LIST_HEAD(&instance->spare_send_buffers); tasklet_init(&instance->send_tasklet, udsl_process_send, (unsigned long)instance); INIT_LIST_HEAD(&instance->filled_send_buffers); /* receive init */ for (i = 0; i < num_rcv_urbs; i++) { struct udsl_receiver *rcv = &(instance->receivers[i]); if (!(rcv->urb = usb_alloc_urb(0, GFP_KERNEL))) { dbg("udsl_usb_probe: no memory for receive urb %d!", i); goto fail; } rcv->instance = instance; list_add(&rcv->list, &instance->spare_receivers); } for (i = 0; i < num_rcv_bufs; i++) { struct udsl_receive_buffer *buf = &(instance->receive_buffers[i]); buf->base = kmalloc(rcv_buf_size * (ATM_CELL_SIZE + instance->rcv_padding), GFP_KERNEL); if (!buf->base) { dbg("udsl_usb_probe: no memory for receive buffer %d!", i); goto fail; } list_add(&buf->list, &instance->spare_receive_buffers); } /* send init */ for (i = 0; i < num_snd_urbs; i++) { struct udsl_sender *snd = &(instance->senders[i]); if (!(snd->urb = usb_alloc_urb(0, GFP_KERNEL))) { dbg("udsl_usb_probe: no memory for send urb %d!", i); goto fail; } snd->instance = instance; list_add(&snd->list, &instance->spare_senders); } for (i = 0; i < num_snd_bufs; i++) { struct udsl_send_buffer *buf = &(instance->send_buffers[i]); buf->base = kmalloc(snd_buf_size * (ATM_CELL_SIZE + instance->snd_padding), GFP_KERNEL); if (!buf->base) { dbg("udsl_usb_probe: no memory for send buffer %d!", i); goto fail; } list_add(&buf->list, &instance->spare_send_buffers); } /* ATM init */ instance->atm_dev = atm_dev_register(instance->driver_name, &udsl_atm_devops, -1, NULL); if (!instance->atm_dev) { dbg("udsl_usb_probe: failed to register ATM device!"); goto fail; } instance->atm_dev->ci_range.vpi_bits = ATM_CI_MAX; instance->atm_dev->ci_range.vci_bits = ATM_CI_MAX; instance->atm_dev->signal = ATM_PHY_SIG_UNKNOWN; /* temp init ATM device, set to 128kbit */ instance->atm_dev->link_rate = 128 * 1000 / 424; /* device description */ buf = instance->description; length = sizeof(instance->description); if ((i = usb_string(dev, dev->descriptor.iProduct, buf, length)) < 0) goto finish; buf += i; length -= i; i = scnprintf(buf, length, " ("); buf += i; length -= i; if (length <= 0 || (i = usb_make_path(dev, buf, length)) < 0) goto finish; buf += i; length -= i; snprintf(buf, length, ")"); finish: /* ready for ATM callbacks */ wmb(); instance->atm_dev->dev_data = instance; usb_get_dev(dev); return 0; fail: for (i = 0; i < num_snd_bufs; i++) kfree(instance->send_buffers[i].base); for (i = 0; i < num_snd_urbs; i++) usb_free_urb(instance->senders[i].urb); for (i = 0; i < num_rcv_bufs; i++) kfree(instance->receive_buffers[i].base); for (i = 0; i < num_rcv_urbs; i++) usb_free_urb(instance->receivers[i].urb); return -ENOMEM;}void udsl_instance_disconnect(struct udsl_instance_data *instance){ int i; dbg("udsl_instance_disconnect entered"); if (!instance) { dbg("udsl_instance_disconnect: NULL instance!"); return; } /* receive finalize */ tasklet_disable(&instance->receive_tasklet); for (i = 0; i < num_rcv_urbs; i++) usb_kill_urb(instance->receivers[i].urb); /* no need to take the spinlock */ INIT_LIST_HEAD(&instance->filled_receive_buffers); INIT_LIST_HEAD(&instance->spare_receive_buffers); tasklet_enable(&instance->receive_tasklet); for (i = 0; i < num_rcv_urbs; i++) usb_free_urb(instance->receivers[i].urb); for (i = 0; i < num_rcv_bufs; i++) kfree(instance->receive_buffers[i].base); /* send finalize */ tasklet_disable(&instance->send_tasklet); for (i = 0; i < num_snd_urbs; i++) usb_kill_urb(instance->senders[i].urb); /* no need to take the spinlock */ INIT_LIST_HEAD(&instance->spare_senders); INIT_LIST_HEAD(&instance->spare_send_buffers); instance->current_buffer = NULL; tasklet_enable(&instance->send_tasklet); for (i = 0; i < num_snd_urbs; i++) usb_free_urb(instance->senders[i].urb); for (i = 0; i < num_snd_bufs; i++) kfree(instance->send_buffers[i].base); /* ATM finalize */ shutdown_atm_dev(instance->atm_dev);}EXPORT_SYMBOL_GPL(udsl_get_instance);EXPORT_SYMBOL_GPL(udsl_put_instance);EXPORT_SYMBOL_GPL(udsl_instance_setup);EXPORT_SYMBOL_GPL(udsl_instance_disconnect);/************* init *************/static int __init udsl_usb_init(void){ dbg("udsl_usb_init: driver version " DRIVER_VERSION); if (sizeof(struct udsl_control) > sizeof(((struct sk_buff *) 0)->cb)) { printk(KERN_ERR __FILE__ ": unusable with this kernel!\n"); return -EIO; } if ((num_rcv_urbs > UDSL_MAX_RCV_URBS) || (num_snd_urbs > UDSL_MAX_SND_URBS) || (num_rcv_bufs > UDSL_MAX_RCV_BUFS) || (num_snd_bufs > UDSL_MAX_SND_BUFS) || (rcv_buf_size > UDSL_MAX_RCV_BUF_SIZE) || (snd_buf_size > UDSL_MAX_SND_BUF_SIZE)) return -EINVAL; return 0;}static void __exit udsl_usb_exit(void){}module_init(udsl_usb_init);module_exit(udsl_usb_exit);MODULE_AUTHOR(DRIVER_AUTHOR);MODULE_DESCRIPTION(DRIVER_DESC);MODULE_LICENSE("GPL");MODULE_VERSION(DRIVER_VERSION);/************** debug **************/#ifdef VERBOSE_DEBUGstatic int udsl_print_packet(const unsigned char *data, int len){ unsigned char buffer[256]; int i = 0, j = 0; for (i = 0; i < len;) { buffer[0] = '\0'; sprintf(buffer, "%.3d :", i); for (j = 0; (j < 16) && (i < len); j++, i++) { sprintf(buffer, "%s %2.2x", buffer, data[i]); } dbg("%s", buffer); } return i;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -