/****************************************************************************** * usbatm.h - Generic USB xDSL driver core * * Copyright (C) 2001, Alcatel * Copyright (C) 2003, Duncan Sands, SolNegro, Josep Comas * Copyright (C) 2004, David Woodhouse * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 59 * Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ******************************************************************************/ #ifndef _USBATM_H_ #define _USBATM_H_ #include <linux/atm.h> #include <linux/atmdev.h> #include <linux/completion.h> #include <linux/device.h> #include <linux/kernel.h> #include <linux/kref.h> #include <linux/list.h> #include <linux/stringify.h> #include <linux/usb.h> #include <linux/mutex.h> /* #define VERBOSE_DEBUG */ #ifdef DEBUG #define UDSL_ASSERT(instance, x) BUG_ON(!(x)) #else #define UDSL_ASSERT(instance, x) \ do { \ if (!(x)) \ dev_warn(&(instance)->usb_intf->dev, \ "failed assertion '%s' at line %d", \ __stringify(x), __LINE__); \ } while (0) #endif #define usb_err(instance, format, arg...) \ dev_err(&(instance)->usb_intf->dev , format , ## arg) #define usb_info(instance, format, arg...) \ dev_info(&(instance)->usb_intf->dev , format , ## arg) #define usb_warn(instance, format, arg...) \ dev_warn(&(instance)->usb_intf->dev , format , ## arg) #ifdef DEBUG #define usb_dbg(instance, format, arg...) \ dev_printk(KERN_DEBUG , &(instance)->usb_intf->dev , format , ## arg) #else #define usb_dbg(instance, format, arg...) \ do {} while (0) #endif /* FIXME: move to dev_* once ATM is driver model aware */ #define atm_printk(level, instance, format, arg...) \ printk(level "ATM dev %d: " format , \ (instance)->atm_dev->number , ## arg) #define atm_err(instance, format, arg...) \ atm_printk(KERN_ERR, instance , format , ## arg) #define atm_info(instance, format, arg...) \ atm_printk(KERN_INFO, instance , format , ## arg) #define atm_warn(instance, format, arg...) \ atm_printk(KERN_WARNING, instance , format , ## arg) #ifdef DEBUG #define atm_dbg(instance, format, arg...) \ atm_printk(KERN_DEBUG, instance , format , ## arg) #define atm_rldbg(instance, format, arg...) \ if (printk_ratelimit()) \ atm_printk(KERN_DEBUG, instance , format , ## arg) #else #define atm_dbg(instance, format, arg...) \ do {} while (0) #define atm_rldbg(instance, format, arg...) \ do {} while (0) #endif /* flags, set by mini-driver in bind() */ #define UDSL_SKIP_HEAVY_INIT (1<<0) #define UDSL_USE_ISOC (1<<1) #define UDSL_IGNORE_EILSEQ (1<<2) /* mini driver */ struct usbatm_data; /* * Assuming all methods exist and succeed, they are called in this order: * * bind, heavy_init, atm_start, ..., atm_stop, unbind */ struct usbatm_driver { const char *driver_name; /* init device ... can sleep, or cause probe() failure */ int (*bind) (struct usbatm_data *, struct usb_interface *, const struct usb_device_id *id); /* additional device initialization that is too slow to be done in probe() */ int (*heavy_init) (struct usbatm_data *, struct usb_interface *); /* cleanup device ... can sleep, but can't fail */ void (*unbind) (struct usbatm_data *, struct usb_interface *); /* init ATM device ... can sleep, or cause ATM initialization failure */ int (*atm_start) (struct usbatm_data *, struct atm_dev *); /* cleanup ATM device ... can sleep, but can't fail */ void (*atm_stop) (struct usbatm_data *, struct atm_dev *); int bulk_in; /* bulk rx endpoint */ int isoc_in; /* isochronous rx endpoint */ int bulk_out; /* bulk tx endpoint */ unsigned rx_padding; unsigned tx_padding; }; extern int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id, struct usbatm_driver *driver); extern void usbatm_usb_disconnect(struct usb_interface *intf); struct usbatm_channel { int endpoint; /* usb pipe */ unsigned int stride; /* ATM cell size + padding */ unsigned int buf_size; /* urb buffer size */ unsigned int packet_size; /* endpoint maxpacket */ spinlock_t lock; struct list_head list; struct tasklet_struct tasklet; struct timer_list delay; struct usbatm_data *usbatm; }; /* main driver data */ struct usbatm_data { /****************** * public fields * ******************/ /* mini driver */ struct usbatm_driver *driver; void *driver_data; char driver_name[16]; unsigned int flags; /* set by mini-driver in bind() */ /* USB device */ struct usb_device *usb_dev; struct usb_interface *usb_intf; char description[64]; /* ATM device */ struct atm_dev *atm_dev; /******************************** * private fields - do not use * ********************************/ struct kref refcount; struct mutex serialize; int disconnected; /* heavy init */ struct task_struct *thread; struct completion thread_started; struct completion thread_exited; /* ATM device */ struct list_head vcc_list; struct usbatm_channel rx_channel; struct usbatm_channel tx_channel; struct sk_buff_head sndqueue; struct sk_buff *current_skb; /* being emptied */ struct usbatm_vcc_data *cached_vcc; int cached_vci; short cached_vpi; unsigned char *cell_buf; /* holds partial rx cell */ unsigned int buf_usage; struct urb *urbs[0]; }; static inline void *to_usbatm_driver_data(struct usb_interface *intf) { struct usbatm_data *usbatm_instance; if (intf == NULL) return NULL; usbatm_instance = usb_get_intfdata(intf); if (usbatm_instance == NULL) /* set NULL before unbind() */ return NULL; return usbatm_instance->driver_data; /* set NULL after unbind() */ } #endif /* _USBATM_H_ */