⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usb_atm.c

📁 h内核
💻 C
📖 第 1 页 / 共 3 页
字号:
	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 + -