diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /drivers/isdn | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/isdn')
140 files changed, 5622 insertions, 3112 deletions
diff --git a/drivers/isdn/Kconfig b/drivers/isdn/Kconfig index 022a19452953..4fb601670de3 100644 --- a/drivers/isdn/Kconfig +++ b/drivers/isdn/Kconfig | |||
@@ -7,15 +7,14 @@ menuconfig ISDN | |||
7 | depends on NET | 7 | depends on NET |
8 | depends on !S390 | 8 | depends on !S390 |
9 | ---help--- | 9 | ---help--- |
10 | ISDN ("Integrated Services Digital Networks", called RNIS in France) | 10 | ISDN ("Integrated Services Digital Network", called RNIS in France) |
11 | is a special type of fully digital telephone service; it's mostly | 11 | is a fully digital telephone service that can be used for voice and |
12 | used to connect to your Internet service provider (with SLIP or | 12 | data connections. If your computer is equipped with an ISDN |
13 | PPP). The main advantage is that the speed is higher than ordinary | 13 | adapter you can use it to connect to your Internet service provider |
14 | modem/telephone connections, and that you can have voice | 14 | (with SLIP or PPP) faster than via a conventional telephone modem |
15 | conversations while downloading stuff. It only works if your | 15 | (though still much slower than with DSL) or to make and accept |
16 | computer is equipped with an ISDN card and both you and your service | 16 | voice calls (eg. turning your PC into a software answering machine |
17 | provider purchased an ISDN line from the phone company. For | 17 | or PABX). |
18 | details, read <http://www.alumni.caltech.edu/~dank/isdn/> on the WWW. | ||
19 | 18 | ||
20 | Select this option if you want your kernel to support ISDN. | 19 | Select this option if you want your kernel to support ISDN. |
21 | 20 | ||
@@ -39,17 +38,22 @@ menuconfig ISDN_I4L | |||
39 | It is still available, though, for use with adapters that are not | 38 | It is still available, though, for use with adapters that are not |
40 | supported by the new CAPI subsystem yet. | 39 | supported by the new CAPI subsystem yet. |
41 | 40 | ||
42 | source "drivers/isdn/mISDN/Kconfig" | ||
43 | |||
44 | source "drivers/isdn/i4l/Kconfig" | 41 | source "drivers/isdn/i4l/Kconfig" |
45 | 42 | ||
46 | menuconfig ISDN_CAPI | 43 | menuconfig ISDN_CAPI |
47 | tristate "CAPI 2.0 subsystem" | 44 | tristate "CAPI 2.0 subsystem" |
48 | help | 45 | help |
49 | This provides the CAPI (Common ISDN Application Programming | 46 | This provides CAPI (the Common ISDN Application Programming |
50 | Interface, a standard making it easy for programs to access ISDN | 47 | Interface) Version 2.0, a standard making it easy for programs to |
51 | hardware, see <http://www.capi.org/>. This is needed for AVM's set | 48 | access ISDN hardware in a device independent way. (For details see |
52 | of active ISDN controllers like B1, T1, M1. | 49 | <http://www.capi.org/>.) CAPI supports making and accepting voice |
50 | and data connections, controlling call options and protocols, | ||
51 | as well as ISDN supplementary services like call forwarding or | ||
52 | three-party conferences (if supported by the specific hardware | ||
53 | driver). | ||
54 | |||
55 | Select this option and the appropriate hardware driver below if | ||
56 | you have an ISDN adapter supported by the CAPI subsystem. | ||
53 | 57 | ||
54 | if ISDN_CAPI | 58 | if ISDN_CAPI |
55 | 59 | ||
@@ -61,4 +65,13 @@ endif # ISDN_CAPI | |||
61 | 65 | ||
62 | source "drivers/isdn/gigaset/Kconfig" | 66 | source "drivers/isdn/gigaset/Kconfig" |
63 | 67 | ||
68 | source "drivers/isdn/hysdn/Kconfig" | ||
69 | |||
70 | source "drivers/isdn/mISDN/Kconfig" | ||
71 | |||
72 | config ISDN_HDLC | ||
73 | tristate | ||
74 | select CRC_CCITT | ||
75 | select BITREVERSE | ||
76 | |||
64 | endif # ISDN | 77 | endif # ISDN |
diff --git a/drivers/isdn/act2000/Kconfig b/drivers/isdn/act2000/Kconfig index 3fc1a5434ef7..fa2673fc69c2 100644 --- a/drivers/isdn/act2000/Kconfig +++ b/drivers/isdn/act2000/Kconfig | |||
@@ -1,6 +1,3 @@ | |||
1 | # | ||
2 | # Config.in for IBM Active 2000 ISDN driver | ||
3 | # | ||
4 | config ISDN_DRV_ACT2000 | 1 | config ISDN_DRV_ACT2000 |
5 | tristate "IBM Active 2000 support" | 2 | tristate "IBM Active 2000 support" |
6 | depends on ISA | 3 | depends on ISA |
@@ -10,4 +7,3 @@ config ISDN_DRV_ACT2000 | |||
10 | into the card using a utility which is part of the latest | 7 | into the card using a utility which is part of the latest |
11 | isdn4k-utils package. Please read the file | 8 | isdn4k-utils package. Please read the file |
12 | <file:Documentation/isdn/README.act2000> for more information. | 9 | <file:Documentation/isdn/README.act2000> for more information. |
13 | |||
diff --git a/drivers/isdn/act2000/module.c b/drivers/isdn/act2000/module.c index f774e12bb64d..05ed72c4cf59 100644 --- a/drivers/isdn/act2000/module.c +++ b/drivers/isdn/act2000/module.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include "act2000_isa.h" | 16 | #include "act2000_isa.h" |
17 | #include "capi.h" | 17 | #include "capi.h" |
18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
19 | #include <linux/slab.h> | ||
19 | #include <linux/init.h> | 20 | #include <linux/init.h> |
20 | 21 | ||
21 | static unsigned short act2000_isa_ports[] = | 22 | static unsigned short act2000_isa_ports[] = |
diff --git a/drivers/isdn/capi/Kconfig b/drivers/isdn/capi/Kconfig index e1afd60924fb..a168e8a891be 100644 --- a/drivers/isdn/capi/Kconfig +++ b/drivers/isdn/capi/Kconfig | |||
@@ -1,6 +1,3 @@ | |||
1 | # | ||
2 | # Config.in for the CAPI subsystem | ||
3 | # | ||
4 | config ISDN_DRV_AVMB1_VERBOSE_REASON | 1 | config ISDN_DRV_AVMB1_VERBOSE_REASON |
5 | bool "Verbose reason code reporting" | 2 | bool "Verbose reason code reporting" |
6 | default y | 3 | default y |
@@ -20,8 +17,7 @@ config CAPI_TRACE | |||
20 | If unsure, say Y. | 17 | If unsure, say Y. |
21 | 18 | ||
22 | config ISDN_CAPI_MIDDLEWARE | 19 | config ISDN_CAPI_MIDDLEWARE |
23 | bool "CAPI2.0 Middleware support (EXPERIMENTAL)" | 20 | bool "CAPI2.0 Middleware support" |
24 | depends on EXPERIMENTAL | ||
25 | help | 21 | help |
26 | This option will enhance the capabilities of the /dev/capi20 | 22 | This option will enhance the capabilities of the /dev/capi20 |
27 | interface. It will provide a means of moving a data connection, | 23 | interface. It will provide a means of moving a data connection, |
@@ -38,18 +34,19 @@ config ISDN_CAPI_CAPI20 | |||
38 | Y/M here. | 34 | Y/M here. |
39 | 35 | ||
40 | config ISDN_CAPI_CAPIFS_BOOL | 36 | config ISDN_CAPI_CAPIFS_BOOL |
41 | bool "CAPI2.0 filesystem support" | 37 | bool "CAPI2.0 filesystem support (DEPRECATED)" |
42 | depends on ISDN_CAPI_MIDDLEWARE && ISDN_CAPI_CAPI20 | 38 | depends on ISDN_CAPI_MIDDLEWARE && ISDN_CAPI_CAPI20 |
39 | help | ||
40 | This option provides a special file system, similar to /dev/pts with | ||
41 | device nodes for the special ttys established by using the | ||
42 | middleware extension above. | ||
43 | You no longer need this, udev fully replaces it. This feature is | ||
44 | scheduled for removal. | ||
43 | 45 | ||
44 | config ISDN_CAPI_CAPIFS | 46 | config ISDN_CAPI_CAPIFS |
45 | tristate | 47 | tristate |
46 | depends on ISDN_CAPI_CAPIFS_BOOL | 48 | depends on ISDN_CAPI_CAPIFS_BOOL |
47 | default ISDN_CAPI_CAPI20 | 49 | default ISDN_CAPI_CAPI20 |
48 | help | ||
49 | This option provides a special file system, similar to /dev/pts with | ||
50 | device nodes for the special ttys established by using the | ||
51 | middleware extension above. If you want to use pppd with | ||
52 | pppdcapiplugin to dial up to your ISP, say Y here. | ||
53 | 50 | ||
54 | config ISDN_CAPI_CAPIDRV | 51 | config ISDN_CAPI_CAPIDRV |
55 | tristate "CAPI2.0 capidrv interface support" | 52 | tristate "CAPI2.0 capidrv interface support" |
@@ -59,4 +56,3 @@ config ISDN_CAPI_CAPIDRV | |||
59 | the legacy isdn4linux link layer. If you have a card which is | 56 | the legacy isdn4linux link layer. If you have a card which is |
60 | supported by a CAPI driver, but still want to use old features like | 57 | supported by a CAPI driver, but still want to use old features like |
61 | ippp interfaces or ttyI emulation, say Y/M here. | 58 | ippp interfaces or ttyI emulation, say Y/M here. |
62 | |||
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 65bf91e16a42..ee5837522f5a 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c | |||
@@ -23,16 +23,13 @@ | |||
23 | #include <linux/smp_lock.h> | 23 | #include <linux/smp_lock.h> |
24 | #include <linux/timer.h> | 24 | #include <linux/timer.h> |
25 | #include <linux/wait.h> | 25 | #include <linux/wait.h> |
26 | #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE | ||
27 | #include <linux/tty.h> | 26 | #include <linux/tty.h> |
28 | #ifdef CONFIG_PPP | ||
29 | #include <linux/netdevice.h> | 27 | #include <linux/netdevice.h> |
30 | #include <linux/ppp_defs.h> | 28 | #include <linux/ppp_defs.h> |
31 | #include <linux/if_ppp.h> | 29 | #include <linux/if_ppp.h> |
32 | #endif /* CONFIG_PPP */ | ||
33 | #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ | ||
34 | #include <linux/skbuff.h> | 30 | #include <linux/skbuff.h> |
35 | #include <linux/proc_fs.h> | 31 | #include <linux/proc_fs.h> |
32 | #include <linux/seq_file.h> | ||
36 | #include <linux/poll.h> | 33 | #include <linux/poll.h> |
37 | #include <linux/capi.h> | 34 | #include <linux/capi.h> |
38 | #include <linux/kernelcapi.h> | 35 | #include <linux/kernelcapi.h> |
@@ -41,35 +38,29 @@ | |||
41 | #include <linux/moduleparam.h> | 38 | #include <linux/moduleparam.h> |
42 | #include <linux/isdn/capiutil.h> | 39 | #include <linux/isdn/capiutil.h> |
43 | #include <linux/isdn/capicmd.h> | 40 | #include <linux/isdn/capicmd.h> |
44 | #if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE) | ||
45 | #include "capifs.h" | ||
46 | #endif | ||
47 | 41 | ||
48 | static char *revision = "$Revision: 1.1.2.7 $"; | 42 | #include "capifs.h" |
49 | 43 | ||
50 | MODULE_DESCRIPTION("CAPI4Linux: Userspace /dev/capi20 interface"); | 44 | MODULE_DESCRIPTION("CAPI4Linux: Userspace /dev/capi20 interface"); |
51 | MODULE_AUTHOR("Carsten Paeth"); | 45 | MODULE_AUTHOR("Carsten Paeth"); |
52 | MODULE_LICENSE("GPL"); | 46 | MODULE_LICENSE("GPL"); |
53 | 47 | ||
54 | #undef _DEBUG_REFCOUNT /* alloc/free and open/close debug */ | ||
55 | #undef _DEBUG_TTYFUNCS /* call to tty_driver */ | 48 | #undef _DEBUG_TTYFUNCS /* call to tty_driver */ |
56 | #undef _DEBUG_DATAFLOW /* data flow */ | 49 | #undef _DEBUG_DATAFLOW /* data flow */ |
57 | 50 | ||
58 | /* -------- driver information -------------------------------------- */ | 51 | /* -------- driver information -------------------------------------- */ |
59 | 52 | ||
60 | static struct class *capi_class; | 53 | static struct class *capi_class; |
61 | |||
62 | static int capi_major = 68; /* allocated */ | 54 | static int capi_major = 68; /* allocated */ |
55 | |||
56 | module_param_named(major, capi_major, uint, 0); | ||
57 | |||
63 | #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE | 58 | #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE |
64 | #define CAPINC_NR_PORTS 32 | 59 | #define CAPINC_NR_PORTS 32 |
65 | #define CAPINC_MAX_PORTS 256 | 60 | #define CAPINC_MAX_PORTS 256 |
66 | static int capi_ttymajor = 191; | 61 | |
67 | static int capi_ttyminors = CAPINC_NR_PORTS; | 62 | static int capi_ttyminors = CAPINC_NR_PORTS; |
68 | #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ | ||
69 | 63 | ||
70 | module_param_named(major, capi_major, uint, 0); | ||
71 | #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE | ||
72 | module_param_named(ttymajor, capi_ttymajor, uint, 0); | ||
73 | module_param_named(ttyminors, capi_ttyminors, uint, 0); | 64 | module_param_named(ttyminors, capi_ttyminors, uint, 0); |
74 | #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ | 65 | #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ |
75 | 66 | ||
@@ -83,53 +74,43 @@ module_param_named(ttyminors, capi_ttyminors, uint, 0); | |||
83 | 74 | ||
84 | struct capidev; | 75 | struct capidev; |
85 | struct capincci; | 76 | struct capincci; |
86 | #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE | ||
87 | struct capiminor; | 77 | struct capiminor; |
88 | 78 | ||
89 | struct datahandle_queue { | 79 | struct ackqueue_entry { |
90 | struct list_head list; | 80 | struct list_head list; |
91 | u16 datahandle; | 81 | u16 datahandle; |
92 | }; | 82 | }; |
93 | 83 | ||
94 | struct capiminor { | 84 | struct capiminor { |
95 | struct list_head list; | 85 | struct kref kref; |
96 | struct capincci *nccip; | 86 | |
97 | unsigned int minor; | 87 | unsigned int minor; |
88 | struct dentry *capifs_dentry; | ||
98 | 89 | ||
99 | struct capi20_appl *ap; | 90 | struct capi20_appl *ap; |
100 | u32 ncci; | 91 | u32 ncci; |
101 | u16 datahandle; | 92 | atomic_t datahandle; |
102 | u16 msgid; | 93 | atomic_t msgid; |
103 | 94 | ||
104 | struct tty_struct *tty; | 95 | struct tty_port port; |
105 | int ttyinstop; | 96 | int ttyinstop; |
106 | int ttyoutstop; | 97 | int ttyoutstop; |
107 | struct sk_buff *ttyskb; | ||
108 | atomic_t ttyopencount; | ||
109 | 98 | ||
110 | struct sk_buff_head inqueue; | 99 | struct sk_buff_head inqueue; |
111 | int inbytes; | 100 | |
112 | struct sk_buff_head outqueue; | 101 | struct sk_buff_head outqueue; |
113 | int outbytes; | 102 | int outbytes; |
103 | struct sk_buff *outskb; | ||
104 | spinlock_t outlock; | ||
114 | 105 | ||
115 | /* transmit path */ | 106 | /* transmit path */ |
116 | struct list_head ackqueue; | 107 | struct list_head ackqueue; |
117 | int nack; | 108 | int nack; |
118 | spinlock_t ackqlock; | 109 | spinlock_t ackqlock; |
119 | }; | 110 | }; |
120 | #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ | ||
121 | |||
122 | /* FIXME: The following lock is a sledgehammer-workaround to a | ||
123 | * locking issue with the capiminor (and maybe other) data structure(s). | ||
124 | * Access to this data is done in a racy way and crashes the machine with | ||
125 | * a FritzCard DSL driver; sooner or later. This is a workaround | ||
126 | * which trades scalability vs stability, so it doesn't crash the kernel anymore. | ||
127 | * The correct (and scalable) fix for the issue seems to require | ||
128 | * an API change to the drivers... . */ | ||
129 | static DEFINE_SPINLOCK(workaround_lock); | ||
130 | 111 | ||
131 | struct capincci { | 112 | struct capincci { |
132 | struct capincci *next; | 113 | struct list_head list; |
133 | u32 ncci; | 114 | u32 ncci; |
134 | struct capidev *cdev; | 115 | struct capidev *cdev; |
135 | #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE | 116 | #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE |
@@ -146,28 +127,28 @@ struct capidev { | |||
146 | struct sk_buff_head recvqueue; | 127 | struct sk_buff_head recvqueue; |
147 | wait_queue_head_t recvwait; | 128 | wait_queue_head_t recvwait; |
148 | 129 | ||
149 | struct capincci *nccis; | 130 | struct list_head nccis; |
150 | 131 | ||
151 | struct mutex ncci_list_mtx; | 132 | struct mutex lock; |
152 | }; | 133 | }; |
153 | 134 | ||
154 | /* -------- global variables ---------------------------------------- */ | 135 | /* -------- global variables ---------------------------------------- */ |
155 | 136 | ||
156 | static DEFINE_RWLOCK(capidev_list_lock); | 137 | static DEFINE_MUTEX(capidev_list_lock); |
157 | static LIST_HEAD(capidev_list); | 138 | static LIST_HEAD(capidev_list); |
158 | 139 | ||
159 | #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE | 140 | #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE |
160 | static DEFINE_RWLOCK(capiminor_list_lock); | ||
161 | static LIST_HEAD(capiminor_list); | ||
162 | #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ | ||
163 | 141 | ||
164 | #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE | 142 | static DEFINE_SPINLOCK(capiminors_lock); |
143 | static struct capiminor **capiminors; | ||
144 | |||
145 | static struct tty_driver *capinc_tty_driver; | ||
146 | |||
165 | /* -------- datahandles --------------------------------------------- */ | 147 | /* -------- datahandles --------------------------------------------- */ |
166 | 148 | ||
167 | static int capincci_add_ack(struct capiminor *mp, u16 datahandle) | 149 | static int capiminor_add_ack(struct capiminor *mp, u16 datahandle) |
168 | { | 150 | { |
169 | struct datahandle_queue *n; | 151 | struct ackqueue_entry *n; |
170 | unsigned long flags; | ||
171 | 152 | ||
172 | n = kmalloc(sizeof(*n), GFP_ATOMIC); | 153 | n = kmalloc(sizeof(*n), GFP_ATOMIC); |
173 | if (unlikely(!n)) { | 154 | if (unlikely(!n)) { |
@@ -176,253 +157,246 @@ static int capincci_add_ack(struct capiminor *mp, u16 datahandle) | |||
176 | } | 157 | } |
177 | n->datahandle = datahandle; | 158 | n->datahandle = datahandle; |
178 | INIT_LIST_HEAD(&n->list); | 159 | INIT_LIST_HEAD(&n->list); |
179 | spin_lock_irqsave(&mp->ackqlock, flags); | 160 | spin_lock_bh(&mp->ackqlock); |
180 | list_add_tail(&n->list, &mp->ackqueue); | 161 | list_add_tail(&n->list, &mp->ackqueue); |
181 | mp->nack++; | 162 | mp->nack++; |
182 | spin_unlock_irqrestore(&mp->ackqlock, flags); | 163 | spin_unlock_bh(&mp->ackqlock); |
183 | return 0; | 164 | return 0; |
184 | } | 165 | } |
185 | 166 | ||
186 | static int capiminor_del_ack(struct capiminor *mp, u16 datahandle) | 167 | static int capiminor_del_ack(struct capiminor *mp, u16 datahandle) |
187 | { | 168 | { |
188 | struct datahandle_queue *p, *tmp; | 169 | struct ackqueue_entry *p, *tmp; |
189 | unsigned long flags; | ||
190 | 170 | ||
191 | spin_lock_irqsave(&mp->ackqlock, flags); | 171 | spin_lock_bh(&mp->ackqlock); |
192 | list_for_each_entry_safe(p, tmp, &mp->ackqueue, list) { | 172 | list_for_each_entry_safe(p, tmp, &mp->ackqueue, list) { |
193 | if (p->datahandle == datahandle) { | 173 | if (p->datahandle == datahandle) { |
194 | list_del(&p->list); | 174 | list_del(&p->list); |
195 | kfree(p); | ||
196 | mp->nack--; | 175 | mp->nack--; |
197 | spin_unlock_irqrestore(&mp->ackqlock, flags); | 176 | spin_unlock_bh(&mp->ackqlock); |
177 | kfree(p); | ||
198 | return 0; | 178 | return 0; |
199 | } | 179 | } |
200 | } | 180 | } |
201 | spin_unlock_irqrestore(&mp->ackqlock, flags); | 181 | spin_unlock_bh(&mp->ackqlock); |
202 | return -1; | 182 | return -1; |
203 | } | 183 | } |
204 | 184 | ||
205 | static void capiminor_del_all_ack(struct capiminor *mp) | 185 | static void capiminor_del_all_ack(struct capiminor *mp) |
206 | { | 186 | { |
207 | struct datahandle_queue *p, *tmp; | 187 | struct ackqueue_entry *p, *tmp; |
208 | unsigned long flags; | ||
209 | 188 | ||
210 | spin_lock_irqsave(&mp->ackqlock, flags); | ||
211 | list_for_each_entry_safe(p, tmp, &mp->ackqueue, list) { | 189 | list_for_each_entry_safe(p, tmp, &mp->ackqueue, list) { |
212 | list_del(&p->list); | 190 | list_del(&p->list); |
213 | kfree(p); | 191 | kfree(p); |
214 | mp->nack--; | 192 | mp->nack--; |
215 | } | 193 | } |
216 | spin_unlock_irqrestore(&mp->ackqlock, flags); | ||
217 | } | 194 | } |
218 | 195 | ||
219 | 196 | ||
220 | /* -------- struct capiminor ---------------------------------------- */ | 197 | /* -------- struct capiminor ---------------------------------------- */ |
221 | 198 | ||
199 | static const struct tty_port_operations capiminor_port_ops; /* we have none */ | ||
200 | |||
222 | static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci) | 201 | static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci) |
223 | { | 202 | { |
224 | struct capiminor *mp, *p; | 203 | struct capiminor *mp; |
225 | unsigned int minor = 0; | 204 | struct device *dev; |
226 | unsigned long flags; | 205 | unsigned int minor; |
227 | 206 | ||
228 | mp = kzalloc(sizeof(*mp), GFP_ATOMIC); | 207 | mp = kzalloc(sizeof(*mp), GFP_KERNEL); |
229 | if (!mp) { | 208 | if (!mp) { |
230 | printk(KERN_ERR "capi: can't alloc capiminor\n"); | 209 | printk(KERN_ERR "capi: can't alloc capiminor\n"); |
231 | return NULL; | 210 | return NULL; |
232 | } | 211 | } |
233 | 212 | ||
213 | kref_init(&mp->kref); | ||
214 | |||
234 | mp->ap = ap; | 215 | mp->ap = ap; |
235 | mp->ncci = ncci; | 216 | mp->ncci = ncci; |
236 | mp->msgid = 0; | ||
237 | atomic_set(&mp->ttyopencount,0); | ||
238 | INIT_LIST_HEAD(&mp->ackqueue); | 217 | INIT_LIST_HEAD(&mp->ackqueue); |
239 | spin_lock_init(&mp->ackqlock); | 218 | spin_lock_init(&mp->ackqlock); |
240 | 219 | ||
241 | skb_queue_head_init(&mp->inqueue); | 220 | skb_queue_head_init(&mp->inqueue); |
242 | skb_queue_head_init(&mp->outqueue); | 221 | skb_queue_head_init(&mp->outqueue); |
222 | spin_lock_init(&mp->outlock); | ||
243 | 223 | ||
244 | /* Allocate the least unused minor number. | 224 | tty_port_init(&mp->port); |
245 | */ | 225 | mp->port.ops = &capiminor_port_ops; |
246 | write_lock_irqsave(&capiminor_list_lock, flags); | 226 | |
247 | if (list_empty(&capiminor_list)) | 227 | /* Allocate the least unused minor number. */ |
248 | list_add(&mp->list, &capiminor_list); | 228 | spin_lock(&capiminors_lock); |
249 | else { | 229 | for (minor = 0; minor < capi_ttyminors; minor++) |
250 | list_for_each_entry(p, &capiminor_list, list) { | 230 | if (!capiminors[minor]) { |
251 | if (p->minor > minor) | 231 | capiminors[minor] = mp; |
252 | break; | 232 | break; |
253 | minor++; | ||
254 | } | ||
255 | |||
256 | if (minor < capi_ttyminors) { | ||
257 | mp->minor = minor; | ||
258 | list_add(&mp->list, p->list.prev); | ||
259 | } | 233 | } |
260 | } | 234 | spin_unlock(&capiminors_lock); |
261 | write_unlock_irqrestore(&capiminor_list_lock, flags); | ||
262 | 235 | ||
263 | if (!(minor < capi_ttyminors)) { | 236 | if (minor == capi_ttyminors) { |
264 | printk(KERN_NOTICE "capi: out of minors\n"); | 237 | printk(KERN_NOTICE "capi: out of minors\n"); |
265 | kfree(mp); | 238 | goto err_out1; |
266 | return NULL; | ||
267 | } | 239 | } |
268 | 240 | ||
241 | mp->minor = minor; | ||
242 | |||
243 | dev = tty_register_device(capinc_tty_driver, minor, NULL); | ||
244 | if (IS_ERR(dev)) | ||
245 | goto err_out2; | ||
246 | |||
269 | return mp; | 247 | return mp; |
248 | |||
249 | err_out2: | ||
250 | spin_lock(&capiminors_lock); | ||
251 | capiminors[minor] = NULL; | ||
252 | spin_unlock(&capiminors_lock); | ||
253 | |||
254 | err_out1: | ||
255 | kfree(mp); | ||
256 | return NULL; | ||
270 | } | 257 | } |
271 | 258 | ||
272 | static void capiminor_free(struct capiminor *mp) | 259 | static void capiminor_destroy(struct kref *kref) |
273 | { | 260 | { |
274 | unsigned long flags; | 261 | struct capiminor *mp = container_of(kref, struct capiminor, kref); |
275 | |||
276 | write_lock_irqsave(&capiminor_list_lock, flags); | ||
277 | list_del(&mp->list); | ||
278 | write_unlock_irqrestore(&capiminor_list_lock, flags); | ||
279 | 262 | ||
280 | kfree_skb(mp->ttyskb); | 263 | kfree_skb(mp->outskb); |
281 | mp->ttyskb = NULL; | ||
282 | skb_queue_purge(&mp->inqueue); | 264 | skb_queue_purge(&mp->inqueue); |
283 | skb_queue_purge(&mp->outqueue); | 265 | skb_queue_purge(&mp->outqueue); |
284 | capiminor_del_all_ack(mp); | 266 | capiminor_del_all_ack(mp); |
285 | kfree(mp); | 267 | kfree(mp); |
286 | } | 268 | } |
287 | 269 | ||
288 | static struct capiminor *capiminor_find(unsigned int minor) | 270 | static struct capiminor *capiminor_get(unsigned int minor) |
289 | { | 271 | { |
290 | struct list_head *l; | 272 | struct capiminor *mp; |
291 | struct capiminor *p = NULL; | ||
292 | 273 | ||
293 | read_lock(&capiminor_list_lock); | 274 | spin_lock(&capiminors_lock); |
294 | list_for_each(l, &capiminor_list) { | 275 | mp = capiminors[minor]; |
295 | p = list_entry(l, struct capiminor, list); | 276 | if (mp) |
296 | if (p->minor == minor) | 277 | kref_get(&mp->kref); |
297 | break; | 278 | spin_unlock(&capiminors_lock); |
298 | } | ||
299 | read_unlock(&capiminor_list_lock); | ||
300 | if (l == &capiminor_list) | ||
301 | return NULL; | ||
302 | 279 | ||
303 | return p; | 280 | return mp; |
281 | } | ||
282 | |||
283 | static inline void capiminor_put(struct capiminor *mp) | ||
284 | { | ||
285 | kref_put(&mp->kref, capiminor_destroy); | ||
286 | } | ||
287 | |||
288 | static void capiminor_free(struct capiminor *mp) | ||
289 | { | ||
290 | tty_unregister_device(capinc_tty_driver, mp->minor); | ||
291 | |||
292 | spin_lock(&capiminors_lock); | ||
293 | capiminors[mp->minor] = NULL; | ||
294 | spin_unlock(&capiminors_lock); | ||
295 | |||
296 | capiminor_put(mp); | ||
304 | } | 297 | } |
305 | #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ | ||
306 | 298 | ||
307 | /* -------- struct capincci ----------------------------------------- */ | 299 | /* -------- struct capincci ----------------------------------------- */ |
308 | 300 | ||
309 | static struct capincci *capincci_alloc(struct capidev *cdev, u32 ncci) | 301 | static void capincci_alloc_minor(struct capidev *cdev, struct capincci *np) |
310 | { | 302 | { |
311 | struct capincci *np, **pp; | 303 | struct capiminor *mp; |
312 | #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE | 304 | dev_t device; |
313 | struct capiminor *mp = NULL; | ||
314 | #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ | ||
315 | 305 | ||
316 | np = kzalloc(sizeof(*np), GFP_ATOMIC); | 306 | if (!(cdev->userflags & CAPIFLAG_HIGHJACKING)) |
317 | if (!np) | 307 | return; |
318 | return NULL; | 308 | |
319 | np->ncci = ncci; | 309 | mp = np->minorp = capiminor_alloc(&cdev->ap, np->ncci); |
320 | np->cdev = cdev; | ||
321 | #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE | ||
322 | mp = NULL; | ||
323 | if (cdev->userflags & CAPIFLAG_HIGHJACKING) | ||
324 | mp = np->minorp = capiminor_alloc(&cdev->ap, ncci); | ||
325 | if (mp) { | 310 | if (mp) { |
326 | mp->nccip = np; | 311 | device = MKDEV(capinc_tty_driver->major, mp->minor); |
327 | #ifdef _DEBUG_REFCOUNT | 312 | mp->capifs_dentry = capifs_new_ncci(mp->minor, device); |
328 | printk(KERN_DEBUG "set mp->nccip\n"); | ||
329 | #endif | ||
330 | #if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE) | ||
331 | capifs_new_ncci(mp->minor, MKDEV(capi_ttymajor, mp->minor)); | ||
332 | #endif | ||
333 | } | 313 | } |
334 | #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ | ||
335 | for (pp=&cdev->nccis; *pp; pp = &(*pp)->next) | ||
336 | ; | ||
337 | *pp = np; | ||
338 | return np; | ||
339 | } | 314 | } |
340 | 315 | ||
341 | static void capincci_free(struct capidev *cdev, u32 ncci) | 316 | static void capincci_free_minor(struct capincci *np) |
342 | { | 317 | { |
343 | struct capincci *np, **pp; | 318 | struct capiminor *mp = np->minorp; |
344 | #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE | 319 | struct tty_struct *tty; |
345 | struct capiminor *mp; | ||
346 | #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ | ||
347 | 320 | ||
348 | pp=&cdev->nccis; | 321 | if (mp) { |
349 | while (*pp) { | 322 | capifs_free_ncci(mp->capifs_dentry); |
350 | np = *pp; | 323 | |
351 | if (ncci == 0xffffffff || np->ncci == ncci) { | 324 | tty = tty_port_tty_get(&mp->port); |
352 | *pp = (*pp)->next; | 325 | if (tty) { |
353 | #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE | 326 | tty_vhangup(tty); |
354 | if ((mp = np->minorp) != NULL) { | 327 | tty_kref_put(tty); |
355 | #if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE) | ||
356 | capifs_free_ncci(mp->minor); | ||
357 | #endif | ||
358 | if (mp->tty) { | ||
359 | mp->nccip = NULL; | ||
360 | #ifdef _DEBUG_REFCOUNT | ||
361 | printk(KERN_DEBUG "reset mp->nccip\n"); | ||
362 | #endif | ||
363 | tty_hangup(mp->tty); | ||
364 | } else { | ||
365 | capiminor_free(mp); | ||
366 | } | ||
367 | } | ||
368 | #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ | ||
369 | kfree(np); | ||
370 | if (*pp == NULL) return; | ||
371 | } else { | ||
372 | pp = &(*pp)->next; | ||
373 | } | 328 | } |
329 | |||
330 | capiminor_free(mp); | ||
374 | } | 331 | } |
375 | } | 332 | } |
376 | 333 | ||
377 | static struct capincci *capincci_find(struct capidev *cdev, u32 ncci) | 334 | static inline unsigned int capincci_minor_opencount(struct capincci *np) |
378 | { | 335 | { |
379 | struct capincci *p; | 336 | struct capiminor *mp = np->minorp; |
337 | unsigned int count = 0; | ||
338 | struct tty_struct *tty; | ||
380 | 339 | ||
381 | for (p=cdev->nccis; p ; p = p->next) { | 340 | if (mp) { |
382 | if (p->ncci == ncci) | 341 | tty = tty_port_tty_get(&mp->port); |
383 | break; | 342 | if (tty) { |
343 | count = tty->count; | ||
344 | tty_kref_put(tty); | ||
345 | } | ||
384 | } | 346 | } |
385 | return p; | 347 | return count; |
386 | } | 348 | } |
387 | 349 | ||
388 | /* -------- struct capidev ------------------------------------------ */ | 350 | #else /* !CONFIG_ISDN_CAPI_MIDDLEWARE */ |
351 | |||
352 | static inline void | ||
353 | capincci_alloc_minor(struct capidev *cdev, struct capincci *np) { } | ||
354 | static inline void capincci_free_minor(struct capincci *np) { } | ||
389 | 355 | ||
390 | static struct capidev *capidev_alloc(void) | 356 | static inline unsigned int capincci_minor_opencount(struct capincci *np) |
391 | { | 357 | { |
392 | struct capidev *cdev; | 358 | return 0; |
393 | unsigned long flags; | 359 | } |
394 | 360 | ||
395 | cdev = kzalloc(sizeof(*cdev), GFP_KERNEL); | 361 | #endif /* !CONFIG_ISDN_CAPI_MIDDLEWARE */ |
396 | if (!cdev) | 362 | |
363 | static struct capincci *capincci_alloc(struct capidev *cdev, u32 ncci) | ||
364 | { | ||
365 | struct capincci *np; | ||
366 | |||
367 | np = kzalloc(sizeof(*np), GFP_KERNEL); | ||
368 | if (!np) | ||
397 | return NULL; | 369 | return NULL; |
370 | np->ncci = ncci; | ||
371 | np->cdev = cdev; | ||
398 | 372 | ||
399 | mutex_init(&cdev->ncci_list_mtx); | 373 | capincci_alloc_minor(cdev, np); |
400 | skb_queue_head_init(&cdev->recvqueue); | 374 | |
401 | init_waitqueue_head(&cdev->recvwait); | 375 | list_add_tail(&np->list, &cdev->nccis); |
402 | write_lock_irqsave(&capidev_list_lock, flags); | 376 | |
403 | list_add_tail(&cdev->list, &capidev_list); | 377 | return np; |
404 | write_unlock_irqrestore(&capidev_list_lock, flags); | ||
405 | return cdev; | ||
406 | } | 378 | } |
407 | 379 | ||
408 | static void capidev_free(struct capidev *cdev) | 380 | static void capincci_free(struct capidev *cdev, u32 ncci) |
409 | { | 381 | { |
410 | unsigned long flags; | 382 | struct capincci *np, *tmp; |
411 | 383 | ||
412 | if (cdev->ap.applid) { | 384 | list_for_each_entry_safe(np, tmp, &cdev->nccis, list) |
413 | capi20_release(&cdev->ap); | 385 | if (ncci == 0xffffffff || np->ncci == ncci) { |
414 | cdev->ap.applid = 0; | 386 | capincci_free_minor(np); |
415 | } | 387 | list_del(&np->list); |
416 | skb_queue_purge(&cdev->recvqueue); | 388 | kfree(np); |
389 | } | ||
390 | } | ||
417 | 391 | ||
418 | mutex_lock(&cdev->ncci_list_mtx); | 392 | static struct capincci *capincci_find(struct capidev *cdev, u32 ncci) |
419 | capincci_free(cdev, 0xffffffff); | 393 | { |
420 | mutex_unlock(&cdev->ncci_list_mtx); | 394 | struct capincci *np; |
421 | 395 | ||
422 | write_lock_irqsave(&capidev_list_lock, flags); | 396 | list_for_each_entry(np, &cdev->nccis, list) |
423 | list_del(&cdev->list); | 397 | if (np->ncci == ncci) |
424 | write_unlock_irqrestore(&capidev_list_lock, flags); | 398 | return np; |
425 | kfree(cdev); | 399 | return NULL; |
426 | } | 400 | } |
427 | 401 | ||
428 | #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE | 402 | #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE |
@@ -432,7 +406,7 @@ static struct sk_buff * | |||
432 | gen_data_b3_resp_for(struct capiminor *mp, struct sk_buff *skb) | 406 | gen_data_b3_resp_for(struct capiminor *mp, struct sk_buff *skb) |
433 | { | 407 | { |
434 | struct sk_buff *nskb; | 408 | struct sk_buff *nskb; |
435 | nskb = alloc_skb(CAPI_DATA_B3_RESP_LEN, GFP_ATOMIC); | 409 | nskb = alloc_skb(CAPI_DATA_B3_RESP_LEN, GFP_KERNEL); |
436 | if (nskb) { | 410 | if (nskb) { |
437 | u16 datahandle = CAPIMSG_U16(skb->data,CAPIMSG_BASELEN+4+4+2); | 411 | u16 datahandle = CAPIMSG_U16(skb->data,CAPIMSG_BASELEN+4+4+2); |
438 | unsigned char *s = skb_put(nskb, CAPI_DATA_B3_RESP_LEN); | 412 | unsigned char *s = skb_put(nskb, CAPI_DATA_B3_RESP_LEN); |
@@ -440,7 +414,7 @@ gen_data_b3_resp_for(struct capiminor *mp, struct sk_buff *skb) | |||
440 | capimsg_setu16(s, 2, mp->ap->applid); | 414 | capimsg_setu16(s, 2, mp->ap->applid); |
441 | capimsg_setu8 (s, 4, CAPI_DATA_B3); | 415 | capimsg_setu8 (s, 4, CAPI_DATA_B3); |
442 | capimsg_setu8 (s, 5, CAPI_RESP); | 416 | capimsg_setu8 (s, 5, CAPI_RESP); |
443 | capimsg_setu16(s, 6, mp->msgid++); | 417 | capimsg_setu16(s, 6, atomic_inc_return(&mp->msgid)); |
444 | capimsg_setu32(s, 8, mp->ncci); | 418 | capimsg_setu32(s, 8, mp->ncci); |
445 | capimsg_setu16(s, 12, datahandle); | 419 | capimsg_setu16(s, 12, datahandle); |
446 | } | 420 | } |
@@ -449,122 +423,156 @@ gen_data_b3_resp_for(struct capiminor *mp, struct sk_buff *skb) | |||
449 | 423 | ||
450 | static int handle_recv_skb(struct capiminor *mp, struct sk_buff *skb) | 424 | static int handle_recv_skb(struct capiminor *mp, struct sk_buff *skb) |
451 | { | 425 | { |
426 | unsigned int datalen = skb->len - CAPIMSG_LEN(skb->data); | ||
427 | struct tty_struct *tty; | ||
452 | struct sk_buff *nskb; | 428 | struct sk_buff *nskb; |
453 | int datalen; | ||
454 | u16 errcode, datahandle; | 429 | u16 errcode, datahandle; |
455 | struct tty_ldisc *ld; | 430 | struct tty_ldisc *ld; |
456 | 431 | int ret = -1; | |
457 | datalen = skb->len - CAPIMSG_LEN(skb->data); | 432 | |
458 | if (mp->tty == NULL) | 433 | tty = tty_port_tty_get(&mp->port); |
459 | { | 434 | if (!tty) { |
460 | #ifdef _DEBUG_DATAFLOW | 435 | #ifdef _DEBUG_DATAFLOW |
461 | printk(KERN_DEBUG "capi: currently no receiver\n"); | 436 | printk(KERN_DEBUG "capi: currently no receiver\n"); |
462 | #endif | 437 | #endif |
463 | return -1; | 438 | return -1; |
464 | } | 439 | } |
465 | 440 | ||
466 | ld = tty_ldisc_ref(mp->tty); | 441 | ld = tty_ldisc_ref(tty); |
467 | if (ld == NULL) | 442 | if (!ld) { |
468 | return -1; | 443 | /* fatal error, do not requeue */ |
444 | ret = 0; | ||
445 | kfree_skb(skb); | ||
446 | goto deref_tty; | ||
447 | } | ||
448 | |||
469 | if (ld->ops->receive_buf == NULL) { | 449 | if (ld->ops->receive_buf == NULL) { |
470 | #if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) | 450 | #if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) |
471 | printk(KERN_DEBUG "capi: ldisc has no receive_buf function\n"); | 451 | printk(KERN_DEBUG "capi: ldisc has no receive_buf function\n"); |
472 | #endif | 452 | #endif |
473 | goto bad; | 453 | /* fatal error, do not requeue */ |
454 | goto free_skb; | ||
474 | } | 455 | } |
475 | if (mp->ttyinstop) { | 456 | if (mp->ttyinstop) { |
476 | #if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) | 457 | #if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) |
477 | printk(KERN_DEBUG "capi: recv tty throttled\n"); | 458 | printk(KERN_DEBUG "capi: recv tty throttled\n"); |
478 | #endif | 459 | #endif |
479 | goto bad; | 460 | goto deref_ldisc; |
480 | } | 461 | } |
481 | if (mp->tty->receive_room < datalen) { | 462 | |
463 | if (tty->receive_room < datalen) { | ||
482 | #if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) | 464 | #if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) |
483 | printk(KERN_DEBUG "capi: no room in tty\n"); | 465 | printk(KERN_DEBUG "capi: no room in tty\n"); |
484 | #endif | 466 | #endif |
485 | goto bad; | 467 | goto deref_ldisc; |
486 | } | 468 | } |
487 | if ((nskb = gen_data_b3_resp_for(mp, skb)) == NULL) { | 469 | |
470 | nskb = gen_data_b3_resp_for(mp, skb); | ||
471 | if (!nskb) { | ||
488 | printk(KERN_ERR "capi: gen_data_b3_resp failed\n"); | 472 | printk(KERN_ERR "capi: gen_data_b3_resp failed\n"); |
489 | goto bad; | 473 | goto deref_ldisc; |
490 | } | 474 | } |
491 | datahandle = CAPIMSG_U16(skb->data,CAPIMSG_BASELEN+4); | 475 | |
476 | datahandle = CAPIMSG_U16(skb->data, CAPIMSG_BASELEN + 4); | ||
477 | |||
492 | errcode = capi20_put_message(mp->ap, nskb); | 478 | errcode = capi20_put_message(mp->ap, nskb); |
493 | if (errcode != CAPI_NOERROR) { | 479 | |
480 | if (errcode == CAPI_NOERROR) { | ||
481 | skb_pull(skb, CAPIMSG_LEN(skb->data)); | ||
482 | #ifdef _DEBUG_DATAFLOW | ||
483 | printk(KERN_DEBUG "capi: DATA_B3_RESP %u len=%d => ldisc\n", | ||
484 | datahandle, skb->len); | ||
485 | #endif | ||
486 | ld->ops->receive_buf(tty, skb->data, NULL, skb->len); | ||
487 | } else { | ||
494 | printk(KERN_ERR "capi: send DATA_B3_RESP failed=%x\n", | 488 | printk(KERN_ERR "capi: send DATA_B3_RESP failed=%x\n", |
495 | errcode); | 489 | errcode); |
496 | kfree_skb(nskb); | 490 | kfree_skb(nskb); |
497 | goto bad; | 491 | |
492 | if (errcode == CAPI_SENDQUEUEFULL) | ||
493 | goto deref_ldisc; | ||
498 | } | 494 | } |
499 | (void)skb_pull(skb, CAPIMSG_LEN(skb->data)); | 495 | |
500 | #ifdef _DEBUG_DATAFLOW | 496 | free_skb: |
501 | printk(KERN_DEBUG "capi: DATA_B3_RESP %u len=%d => ldisc\n", | 497 | ret = 0; |
502 | datahandle, skb->len); | ||
503 | #endif | ||
504 | ld->ops->receive_buf(mp->tty, skb->data, NULL, skb->len); | ||
505 | kfree_skb(skb); | 498 | kfree_skb(skb); |
499 | |||
500 | deref_ldisc: | ||
506 | tty_ldisc_deref(ld); | 501 | tty_ldisc_deref(ld); |
507 | return 0; | 502 | |
508 | bad: | 503 | deref_tty: |
509 | tty_ldisc_deref(ld); | 504 | tty_kref_put(tty); |
510 | return -1; | 505 | return ret; |
511 | } | 506 | } |
512 | 507 | ||
513 | static void handle_minor_recv(struct capiminor *mp) | 508 | static void handle_minor_recv(struct capiminor *mp) |
514 | { | 509 | { |
515 | struct sk_buff *skb; | 510 | struct sk_buff *skb; |
516 | while ((skb = skb_dequeue(&mp->inqueue)) != NULL) { | 511 | |
517 | unsigned int len = skb->len; | 512 | while ((skb = skb_dequeue(&mp->inqueue)) != NULL) |
518 | mp->inbytes -= len; | ||
519 | if (handle_recv_skb(mp, skb) < 0) { | 513 | if (handle_recv_skb(mp, skb) < 0) { |
520 | skb_queue_head(&mp->inqueue, skb); | 514 | skb_queue_head(&mp->inqueue, skb); |
521 | mp->inbytes += len; | ||
522 | return; | 515 | return; |
523 | } | 516 | } |
524 | } | ||
525 | } | 517 | } |
526 | 518 | ||
527 | static int handle_minor_send(struct capiminor *mp) | 519 | static void handle_minor_send(struct capiminor *mp) |
528 | { | 520 | { |
521 | struct tty_struct *tty; | ||
529 | struct sk_buff *skb; | 522 | struct sk_buff *skb; |
530 | u16 len; | 523 | u16 len; |
531 | int count = 0; | ||
532 | u16 errcode; | 524 | u16 errcode; |
533 | u16 datahandle; | 525 | u16 datahandle; |
534 | 526 | ||
535 | if (mp->tty && mp->ttyoutstop) { | 527 | tty = tty_port_tty_get(&mp->port); |
528 | if (!tty) | ||
529 | return; | ||
530 | |||
531 | if (mp->ttyoutstop) { | ||
536 | #if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) | 532 | #if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) |
537 | printk(KERN_DEBUG "capi: send: tty stopped\n"); | 533 | printk(KERN_DEBUG "capi: send: tty stopped\n"); |
538 | #endif | 534 | #endif |
539 | return 0; | 535 | tty_kref_put(tty); |
536 | return; | ||
540 | } | 537 | } |
541 | 538 | ||
542 | while ((skb = skb_dequeue(&mp->outqueue)) != NULL) { | 539 | while (1) { |
543 | datahandle = mp->datahandle; | 540 | spin_lock_bh(&mp->outlock); |
541 | skb = __skb_dequeue(&mp->outqueue); | ||
542 | if (!skb) { | ||
543 | spin_unlock_bh(&mp->outlock); | ||
544 | break; | ||
545 | } | ||
544 | len = (u16)skb->len; | 546 | len = (u16)skb->len; |
547 | mp->outbytes -= len; | ||
548 | spin_unlock_bh(&mp->outlock); | ||
549 | |||
550 | datahandle = atomic_inc_return(&mp->datahandle); | ||
545 | skb_push(skb, CAPI_DATA_B3_REQ_LEN); | 551 | skb_push(skb, CAPI_DATA_B3_REQ_LEN); |
546 | memset(skb->data, 0, CAPI_DATA_B3_REQ_LEN); | 552 | memset(skb->data, 0, CAPI_DATA_B3_REQ_LEN); |
547 | capimsg_setu16(skb->data, 0, CAPI_DATA_B3_REQ_LEN); | 553 | capimsg_setu16(skb->data, 0, CAPI_DATA_B3_REQ_LEN); |
548 | capimsg_setu16(skb->data, 2, mp->ap->applid); | 554 | capimsg_setu16(skb->data, 2, mp->ap->applid); |
549 | capimsg_setu8 (skb->data, 4, CAPI_DATA_B3); | 555 | capimsg_setu8 (skb->data, 4, CAPI_DATA_B3); |
550 | capimsg_setu8 (skb->data, 5, CAPI_REQ); | 556 | capimsg_setu8 (skb->data, 5, CAPI_REQ); |
551 | capimsg_setu16(skb->data, 6, mp->msgid++); | 557 | capimsg_setu16(skb->data, 6, atomic_inc_return(&mp->msgid)); |
552 | capimsg_setu32(skb->data, 8, mp->ncci); /* NCCI */ | 558 | capimsg_setu32(skb->data, 8, mp->ncci); /* NCCI */ |
553 | capimsg_setu32(skb->data, 12, (u32)(long)skb->data);/* Data32 */ | 559 | capimsg_setu32(skb->data, 12, (u32)(long)skb->data);/* Data32 */ |
554 | capimsg_setu16(skb->data, 16, len); /* Data length */ | 560 | capimsg_setu16(skb->data, 16, len); /* Data length */ |
555 | capimsg_setu16(skb->data, 18, datahandle); | 561 | capimsg_setu16(skb->data, 18, datahandle); |
556 | capimsg_setu16(skb->data, 20, 0); /* Flags */ | 562 | capimsg_setu16(skb->data, 20, 0); /* Flags */ |
557 | 563 | ||
558 | if (capincci_add_ack(mp, datahandle) < 0) { | 564 | if (capiminor_add_ack(mp, datahandle) < 0) { |
559 | skb_pull(skb, CAPI_DATA_B3_REQ_LEN); | 565 | skb_pull(skb, CAPI_DATA_B3_REQ_LEN); |
560 | skb_queue_head(&mp->outqueue, skb); | 566 | |
561 | return count; | 567 | spin_lock_bh(&mp->outlock); |
568 | __skb_queue_head(&mp->outqueue, skb); | ||
569 | mp->outbytes += len; | ||
570 | spin_unlock_bh(&mp->outlock); | ||
571 | |||
572 | break; | ||
562 | } | 573 | } |
563 | errcode = capi20_put_message(mp->ap, skb); | 574 | errcode = capi20_put_message(mp->ap, skb); |
564 | if (errcode == CAPI_NOERROR) { | 575 | if (errcode == CAPI_NOERROR) { |
565 | mp->datahandle++; | ||
566 | count++; | ||
567 | mp->outbytes -= len; | ||
568 | #ifdef _DEBUG_DATAFLOW | 576 | #ifdef _DEBUG_DATAFLOW |
569 | printk(KERN_DEBUG "capi: DATA_B3_REQ %u len=%u\n", | 577 | printk(KERN_DEBUG "capi: DATA_B3_REQ %u len=%u\n", |
570 | datahandle, len); | 578 | datahandle, len); |
@@ -575,16 +583,20 @@ static int handle_minor_send(struct capiminor *mp) | |||
575 | 583 | ||
576 | if (errcode == CAPI_SENDQUEUEFULL) { | 584 | if (errcode == CAPI_SENDQUEUEFULL) { |
577 | skb_pull(skb, CAPI_DATA_B3_REQ_LEN); | 585 | skb_pull(skb, CAPI_DATA_B3_REQ_LEN); |
578 | skb_queue_head(&mp->outqueue, skb); | 586 | |
587 | spin_lock_bh(&mp->outlock); | ||
588 | __skb_queue_head(&mp->outqueue, skb); | ||
589 | mp->outbytes += len; | ||
590 | spin_unlock_bh(&mp->outlock); | ||
591 | |||
579 | break; | 592 | break; |
580 | } | 593 | } |
581 | 594 | ||
582 | /* ups, drop packet */ | 595 | /* ups, drop packet */ |
583 | printk(KERN_ERR "capi: put_message = %x\n", errcode); | 596 | printk(KERN_ERR "capi: put_message = %x\n", errcode); |
584 | mp->outbytes -= len; | ||
585 | kfree_skb(skb); | 597 | kfree_skb(skb); |
586 | } | 598 | } |
587 | return count; | 599 | tty_kref_put(tty); |
588 | } | 600 | } |
589 | 601 | ||
590 | #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ | 602 | #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ |
@@ -594,65 +606,56 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb) | |||
594 | { | 606 | { |
595 | struct capidev *cdev = ap->private; | 607 | struct capidev *cdev = ap->private; |
596 | #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE | 608 | #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE |
609 | struct tty_struct *tty; | ||
597 | struct capiminor *mp; | 610 | struct capiminor *mp; |
598 | u16 datahandle; | 611 | u16 datahandle; |
599 | #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ | 612 | #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ |
600 | struct capincci *np; | 613 | struct capincci *np; |
601 | u32 ncci; | 614 | |
602 | unsigned long flags; | 615 | mutex_lock(&cdev->lock); |
603 | 616 | ||
604 | if (CAPIMSG_CMD(skb->data) == CAPI_CONNECT_B3_CONF) { | 617 | if (CAPIMSG_CMD(skb->data) == CAPI_CONNECT_B3_CONF) { |
605 | u16 info = CAPIMSG_U16(skb->data, 12); // Info field | 618 | u16 info = CAPIMSG_U16(skb->data, 12); // Info field |
606 | if ((info & 0xff00) == 0) { | 619 | if ((info & 0xff00) == 0) |
607 | mutex_lock(&cdev->ncci_list_mtx); | ||
608 | capincci_alloc(cdev, CAPIMSG_NCCI(skb->data)); | 620 | capincci_alloc(cdev, CAPIMSG_NCCI(skb->data)); |
609 | mutex_unlock(&cdev->ncci_list_mtx); | ||
610 | } | ||
611 | } | 621 | } |
612 | if (CAPIMSG_CMD(skb->data) == CAPI_CONNECT_B3_IND) { | 622 | if (CAPIMSG_CMD(skb->data) == CAPI_CONNECT_B3_IND) |
613 | mutex_lock(&cdev->ncci_list_mtx); | ||
614 | capincci_alloc(cdev, CAPIMSG_NCCI(skb->data)); | 623 | capincci_alloc(cdev, CAPIMSG_NCCI(skb->data)); |
615 | mutex_unlock(&cdev->ncci_list_mtx); | 624 | |
616 | } | ||
617 | spin_lock_irqsave(&workaround_lock, flags); | ||
618 | if (CAPIMSG_COMMAND(skb->data) != CAPI_DATA_B3) { | 625 | if (CAPIMSG_COMMAND(skb->data) != CAPI_DATA_B3) { |
619 | skb_queue_tail(&cdev->recvqueue, skb); | 626 | skb_queue_tail(&cdev->recvqueue, skb); |
620 | wake_up_interruptible(&cdev->recvwait); | 627 | wake_up_interruptible(&cdev->recvwait); |
621 | spin_unlock_irqrestore(&workaround_lock, flags); | 628 | goto unlock_out; |
622 | return; | ||
623 | } | 629 | } |
624 | ncci = CAPIMSG_CONTROL(skb->data); | 630 | |
625 | for (np = cdev->nccis; np && np->ncci != ncci; np = np->next) | 631 | np = capincci_find(cdev, CAPIMSG_CONTROL(skb->data)); |
626 | ; | ||
627 | if (!np) { | 632 | if (!np) { |
628 | printk(KERN_ERR "BUG: capi_signal: ncci not found\n"); | 633 | printk(KERN_ERR "BUG: capi_signal: ncci not found\n"); |
629 | skb_queue_tail(&cdev->recvqueue, skb); | 634 | skb_queue_tail(&cdev->recvqueue, skb); |
630 | wake_up_interruptible(&cdev->recvwait); | 635 | wake_up_interruptible(&cdev->recvwait); |
631 | spin_unlock_irqrestore(&workaround_lock, flags); | 636 | goto unlock_out; |
632 | return; | ||
633 | } | 637 | } |
638 | |||
634 | #ifndef CONFIG_ISDN_CAPI_MIDDLEWARE | 639 | #ifndef CONFIG_ISDN_CAPI_MIDDLEWARE |
635 | skb_queue_tail(&cdev->recvqueue, skb); | 640 | skb_queue_tail(&cdev->recvqueue, skb); |
636 | wake_up_interruptible(&cdev->recvwait); | 641 | wake_up_interruptible(&cdev->recvwait); |
642 | |||
637 | #else /* CONFIG_ISDN_CAPI_MIDDLEWARE */ | 643 | #else /* CONFIG_ISDN_CAPI_MIDDLEWARE */ |
644 | |||
638 | mp = np->minorp; | 645 | mp = np->minorp; |
639 | if (!mp) { | 646 | if (!mp) { |
640 | skb_queue_tail(&cdev->recvqueue, skb); | 647 | skb_queue_tail(&cdev->recvqueue, skb); |
641 | wake_up_interruptible(&cdev->recvwait); | 648 | wake_up_interruptible(&cdev->recvwait); |
642 | spin_unlock_irqrestore(&workaround_lock, flags); | 649 | goto unlock_out; |
643 | return; | ||
644 | } | 650 | } |
645 | |||
646 | |||
647 | if (CAPIMSG_SUBCOMMAND(skb->data) == CAPI_IND) { | 651 | if (CAPIMSG_SUBCOMMAND(skb->data) == CAPI_IND) { |
648 | |||
649 | datahandle = CAPIMSG_U16(skb->data, CAPIMSG_BASELEN+4+4+2); | 652 | datahandle = CAPIMSG_U16(skb->data, CAPIMSG_BASELEN+4+4+2); |
650 | #ifdef _DEBUG_DATAFLOW | 653 | #ifdef _DEBUG_DATAFLOW |
651 | printk(KERN_DEBUG "capi_signal: DATA_B3_IND %u len=%d\n", | 654 | printk(KERN_DEBUG "capi_signal: DATA_B3_IND %u len=%d\n", |
652 | datahandle, skb->len-CAPIMSG_LEN(skb->data)); | 655 | datahandle, skb->len-CAPIMSG_LEN(skb->data)); |
653 | #endif | 656 | #endif |
654 | skb_queue_tail(&mp->inqueue, skb); | 657 | skb_queue_tail(&mp->inqueue, skb); |
655 | mp->inbytes += skb->len; | 658 | |
656 | handle_minor_recv(mp); | 659 | handle_minor_recv(mp); |
657 | 660 | ||
658 | } else if (CAPIMSG_SUBCOMMAND(skb->data) == CAPI_CONF) { | 661 | } else if (CAPIMSG_SUBCOMMAND(skb->data) == CAPI_CONF) { |
@@ -664,10 +667,13 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb) | |||
664 | CAPIMSG_U16(skb->data, CAPIMSG_BASELEN+4+2)); | 667 | CAPIMSG_U16(skb->data, CAPIMSG_BASELEN+4+2)); |
665 | #endif | 668 | #endif |
666 | kfree_skb(skb); | 669 | kfree_skb(skb); |
667 | (void)capiminor_del_ack(mp, datahandle); | 670 | capiminor_del_ack(mp, datahandle); |
668 | if (mp->tty) | 671 | tty = tty_port_tty_get(&mp->port); |
669 | tty_wakeup(mp->tty); | 672 | if (tty) { |
670 | (void)handle_minor_send(mp); | 673 | tty_wakeup(tty); |
674 | tty_kref_put(tty); | ||
675 | } | ||
676 | handle_minor_send(mp); | ||
671 | 677 | ||
672 | } else { | 678 | } else { |
673 | /* ups, let capi application handle it :-) */ | 679 | /* ups, let capi application handle it :-) */ |
@@ -675,7 +681,9 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb) | |||
675 | wake_up_interruptible(&cdev->recvwait); | 681 | wake_up_interruptible(&cdev->recvwait); |
676 | } | 682 | } |
677 | #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ | 683 | #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ |
678 | spin_unlock_irqrestore(&workaround_lock, flags); | 684 | |
685 | unlock_out: | ||
686 | mutex_unlock(&cdev->lock); | ||
679 | } | 687 | } |
680 | 688 | ||
681 | /* -------- file_operations for capidev ----------------------------- */ | 689 | /* -------- file_operations for capidev ----------------------------- */ |
@@ -686,24 +694,19 @@ capi_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) | |||
686 | struct capidev *cdev = (struct capidev *)file->private_data; | 694 | struct capidev *cdev = (struct capidev *)file->private_data; |
687 | struct sk_buff *skb; | 695 | struct sk_buff *skb; |
688 | size_t copied; | 696 | size_t copied; |
697 | int err; | ||
689 | 698 | ||
690 | if (!cdev->ap.applid) | 699 | if (!cdev->ap.applid) |
691 | return -ENODEV; | 700 | return -ENODEV; |
692 | 701 | ||
693 | if ((skb = skb_dequeue(&cdev->recvqueue)) == NULL) { | 702 | skb = skb_dequeue(&cdev->recvqueue); |
694 | 703 | if (!skb) { | |
695 | if (file->f_flags & O_NONBLOCK) | 704 | if (file->f_flags & O_NONBLOCK) |
696 | return -EAGAIN; | 705 | return -EAGAIN; |
697 | 706 | err = wait_event_interruptible(cdev->recvwait, | |
698 | for (;;) { | 707 | (skb = skb_dequeue(&cdev->recvqueue))); |
699 | interruptible_sleep_on(&cdev->recvwait); | 708 | if (err) |
700 | if ((skb = skb_dequeue(&cdev->recvqueue)) != NULL) | 709 | return err; |
701 | break; | ||
702 | if (signal_pending(current)) | ||
703 | break; | ||
704 | } | ||
705 | if (skb == NULL) | ||
706 | return -ERESTARTNOHAND; | ||
707 | } | 710 | } |
708 | if (skb->len > count) { | 711 | if (skb->len > count) { |
709 | skb_queue_head(&cdev->recvqueue, skb); | 712 | skb_queue_head(&cdev->recvqueue, skb); |
@@ -753,9 +756,9 @@ capi_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos | |||
753 | CAPIMSG_SETAPPID(skb->data, cdev->ap.applid); | 756 | CAPIMSG_SETAPPID(skb->data, cdev->ap.applid); |
754 | 757 | ||
755 | if (CAPIMSG_CMD(skb->data) == CAPI_DISCONNECT_B3_RESP) { | 758 | if (CAPIMSG_CMD(skb->data) == CAPI_DISCONNECT_B3_RESP) { |
756 | mutex_lock(&cdev->ncci_list_mtx); | 759 | mutex_lock(&cdev->lock); |
757 | capincci_free(cdev, CAPIMSG_NCCI(skb->data)); | 760 | capincci_free(cdev, CAPIMSG_NCCI(skb->data)); |
758 | mutex_unlock(&cdev->ncci_list_mtx); | 761 | mutex_unlock(&cdev->lock); |
759 | } | 762 | } |
760 | 763 | ||
761 | cdev->errcode = capi20_put_message(&cdev->ap, skb); | 764 | cdev->errcode = capi20_put_message(&cdev->ap, skb); |
@@ -788,30 +791,35 @@ capi_ioctl(struct inode *inode, struct file *file, | |||
788 | unsigned int cmd, unsigned long arg) | 791 | unsigned int cmd, unsigned long arg) |
789 | { | 792 | { |
790 | struct capidev *cdev = file->private_data; | 793 | struct capidev *cdev = file->private_data; |
791 | struct capi20_appl *ap = &cdev->ap; | ||
792 | capi_ioctl_struct data; | 794 | capi_ioctl_struct data; |
793 | int retval = -EINVAL; | 795 | int retval = -EINVAL; |
794 | void __user *argp = (void __user *)arg; | 796 | void __user *argp = (void __user *)arg; |
795 | 797 | ||
796 | switch (cmd) { | 798 | switch (cmd) { |
797 | case CAPI_REGISTER: | 799 | case CAPI_REGISTER: |
798 | { | 800 | mutex_lock(&cdev->lock); |
799 | if (ap->applid) | ||
800 | return -EEXIST; | ||
801 | 801 | ||
802 | if (copy_from_user(&cdev->ap.rparam, argp, | 802 | if (cdev->ap.applid) { |
803 | sizeof(struct capi_register_params))) | 803 | retval = -EEXIST; |
804 | return -EFAULT; | 804 | goto register_out; |
805 | 805 | } | |
806 | cdev->ap.private = cdev; | 806 | if (copy_from_user(&cdev->ap.rparam, argp, |
807 | cdev->ap.recv_message = capi_recv_message; | 807 | sizeof(struct capi_register_params))) { |
808 | cdev->errcode = capi20_register(ap); | 808 | retval = -EFAULT; |
809 | if (cdev->errcode) { | 809 | goto register_out; |
810 | ap->applid = 0; | 810 | } |
811 | return -EIO; | 811 | cdev->ap.private = cdev; |
812 | } | 812 | cdev->ap.recv_message = capi_recv_message; |
813 | cdev->errcode = capi20_register(&cdev->ap); | ||
814 | retval = (int)cdev->ap.applid; | ||
815 | if (cdev->errcode) { | ||
816 | cdev->ap.applid = 0; | ||
817 | retval = -EIO; | ||
813 | } | 818 | } |
814 | return (int)ap->applid; | 819 | |
820 | register_out: | ||
821 | mutex_unlock(&cdev->lock); | ||
822 | return retval; | ||
815 | 823 | ||
816 | case CAPI_GET_VERSION: | 824 | case CAPI_GET_VERSION: |
817 | { | 825 | { |
@@ -910,101 +918,104 @@ capi_ioctl(struct inode *inode, struct file *file, | |||
910 | return 0; | 918 | return 0; |
911 | 919 | ||
912 | case CAPI_SET_FLAGS: | 920 | case CAPI_SET_FLAGS: |
913 | case CAPI_CLR_FLAGS: | 921 | case CAPI_CLR_FLAGS: { |
914 | { | 922 | unsigned userflags; |
915 | unsigned userflags; | 923 | |
916 | if (copy_from_user(&userflags, argp, | 924 | if (copy_from_user(&userflags, argp, sizeof(userflags))) |
917 | sizeof(userflags))) | 925 | return -EFAULT; |
918 | return -EFAULT; | ||
919 | if (cmd == CAPI_SET_FLAGS) | ||
920 | cdev->userflags |= userflags; | ||
921 | else | ||
922 | cdev->userflags &= ~userflags; | ||
923 | } | ||
924 | return 0; | ||
925 | 926 | ||
927 | mutex_lock(&cdev->lock); | ||
928 | if (cmd == CAPI_SET_FLAGS) | ||
929 | cdev->userflags |= userflags; | ||
930 | else | ||
931 | cdev->userflags &= ~userflags; | ||
932 | mutex_unlock(&cdev->lock); | ||
933 | return 0; | ||
934 | } | ||
926 | case CAPI_GET_FLAGS: | 935 | case CAPI_GET_FLAGS: |
927 | if (copy_to_user(argp, &cdev->userflags, | 936 | if (copy_to_user(argp, &cdev->userflags, |
928 | sizeof(cdev->userflags))) | 937 | sizeof(cdev->userflags))) |
929 | return -EFAULT; | 938 | return -EFAULT; |
930 | return 0; | 939 | return 0; |
931 | 940 | ||
932 | case CAPI_NCCI_OPENCOUNT: | 941 | case CAPI_NCCI_OPENCOUNT: { |
933 | { | 942 | struct capincci *nccip; |
934 | struct capincci *nccip; | 943 | unsigned ncci; |
935 | #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE | 944 | int count = 0; |
936 | struct capiminor *mp; | ||
937 | #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ | ||
938 | unsigned ncci; | ||
939 | int count = 0; | ||
940 | if (copy_from_user(&ncci, argp, sizeof(ncci))) | ||
941 | return -EFAULT; | ||
942 | 945 | ||
943 | mutex_lock(&cdev->ncci_list_mtx); | 946 | if (copy_from_user(&ncci, argp, sizeof(ncci))) |
944 | if ((nccip = capincci_find(cdev, (u32) ncci)) == NULL) { | 947 | return -EFAULT; |
945 | mutex_unlock(&cdev->ncci_list_mtx); | 948 | |
946 | return 0; | 949 | mutex_lock(&cdev->lock); |
947 | } | 950 | nccip = capincci_find(cdev, (u32)ncci); |
948 | #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE | 951 | if (nccip) |
949 | if ((mp = nccip->minorp) != NULL) { | 952 | count = capincci_minor_opencount(nccip); |
950 | count += atomic_read(&mp->ttyopencount); | 953 | mutex_unlock(&cdev->lock); |
951 | } | 954 | return count; |
952 | #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ | 955 | } |
953 | mutex_unlock(&cdev->ncci_list_mtx); | ||
954 | return count; | ||
955 | } | ||
956 | return 0; | ||
957 | 956 | ||
958 | #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE | 957 | #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE |
959 | case CAPI_NCCI_GETUNIT: | 958 | case CAPI_NCCI_GETUNIT: { |
960 | { | 959 | struct capincci *nccip; |
961 | struct capincci *nccip; | 960 | struct capiminor *mp; |
962 | struct capiminor *mp; | 961 | unsigned ncci; |
963 | unsigned ncci; | 962 | int unit = -ESRCH; |
964 | int unit = 0; | 963 | |
965 | if (copy_from_user(&ncci, argp, | 964 | if (copy_from_user(&ncci, argp, sizeof(ncci))) |
966 | sizeof(ncci))) | 965 | return -EFAULT; |
967 | return -EFAULT; | 966 | |
968 | mutex_lock(&cdev->ncci_list_mtx); | 967 | mutex_lock(&cdev->lock); |
969 | nccip = capincci_find(cdev, (u32) ncci); | 968 | nccip = capincci_find(cdev, (u32)ncci); |
970 | if (!nccip || (mp = nccip->minorp) == NULL) { | 969 | if (nccip) { |
971 | mutex_unlock(&cdev->ncci_list_mtx); | 970 | mp = nccip->minorp; |
972 | return -ESRCH; | 971 | if (mp) |
973 | } | 972 | unit = mp->minor; |
974 | unit = mp->minor; | ||
975 | mutex_unlock(&cdev->ncci_list_mtx); | ||
976 | return unit; | ||
977 | } | 973 | } |
978 | return 0; | 974 | mutex_unlock(&cdev->lock); |
975 | return unit; | ||
976 | } | ||
979 | #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ | 977 | #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ |
978 | |||
979 | default: | ||
980 | return -EINVAL; | ||
980 | } | 981 | } |
981 | return -EINVAL; | ||
982 | } | 982 | } |
983 | 983 | ||
984 | static int | 984 | static int capi_open(struct inode *inode, struct file *file) |
985 | capi_open(struct inode *inode, struct file *file) | ||
986 | { | 985 | { |
987 | int ret; | 986 | struct capidev *cdev; |
988 | 987 | ||
989 | lock_kernel(); | 988 | cdev = kzalloc(sizeof(*cdev), GFP_KERNEL); |
990 | if (file->private_data) | 989 | if (!cdev) |
991 | ret = -EEXIST; | 990 | return -ENOMEM; |
992 | else if ((file->private_data = capidev_alloc()) == NULL) | 991 | |
993 | ret = -ENOMEM; | 992 | mutex_init(&cdev->lock); |
994 | else | 993 | skb_queue_head_init(&cdev->recvqueue); |
995 | ret = nonseekable_open(inode, file); | 994 | init_waitqueue_head(&cdev->recvwait); |
996 | unlock_kernel(); | 995 | INIT_LIST_HEAD(&cdev->nccis); |
997 | return ret; | 996 | file->private_data = cdev; |
997 | |||
998 | mutex_lock(&capidev_list_lock); | ||
999 | list_add_tail(&cdev->list, &capidev_list); | ||
1000 | mutex_unlock(&capidev_list_lock); | ||
1001 | |||
1002 | return nonseekable_open(inode, file); | ||
998 | } | 1003 | } |
999 | 1004 | ||
1000 | static int | 1005 | static int capi_release(struct inode *inode, struct file *file) |
1001 | capi_release(struct inode *inode, struct file *file) | ||
1002 | { | 1006 | { |
1003 | struct capidev *cdev = (struct capidev *)file->private_data; | 1007 | struct capidev *cdev = file->private_data; |
1004 | 1008 | ||
1005 | capidev_free(cdev); | 1009 | mutex_lock(&capidev_list_lock); |
1006 | file->private_data = NULL; | 1010 | list_del(&cdev->list); |
1007 | 1011 | mutex_unlock(&capidev_list_lock); | |
1012 | |||
1013 | if (cdev->ap.applid) | ||
1014 | capi20_release(&cdev->ap); | ||
1015 | skb_queue_purge(&cdev->recvqueue); | ||
1016 | capincci_free(cdev, 0xffffffff); | ||
1017 | |||
1018 | kfree(cdev); | ||
1008 | return 0; | 1019 | return 0; |
1009 | } | 1020 | } |
1010 | 1021 | ||
@@ -1023,182 +1034,159 @@ static const struct file_operations capi_fops = | |||
1023 | #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE | 1034 | #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE |
1024 | /* -------- tty_operations for capincci ----------------------------- */ | 1035 | /* -------- tty_operations for capincci ----------------------------- */ |
1025 | 1036 | ||
1026 | static int capinc_tty_open(struct tty_struct * tty, struct file * file) | 1037 | static int |
1038 | capinc_tty_install(struct tty_driver *driver, struct tty_struct *tty) | ||
1027 | { | 1039 | { |
1028 | struct capiminor *mp; | 1040 | int idx = tty->index; |
1029 | unsigned long flags; | 1041 | struct capiminor *mp = capiminor_get(idx); |
1042 | int ret = tty_init_termios(tty); | ||
1043 | |||
1044 | if (ret == 0) { | ||
1045 | tty_driver_kref_get(driver); | ||
1046 | tty->count++; | ||
1047 | tty->driver_data = mp; | ||
1048 | driver->ttys[idx] = tty; | ||
1049 | } else | ||
1050 | capiminor_put(mp); | ||
1051 | return ret; | ||
1052 | } | ||
1030 | 1053 | ||
1031 | if ((mp = capiminor_find(iminor(file->f_path.dentry->d_inode))) == NULL) | 1054 | static void capinc_tty_cleanup(struct tty_struct *tty) |
1032 | return -ENXIO; | 1055 | { |
1033 | if (mp->nccip == NULL) | 1056 | struct capiminor *mp = tty->driver_data; |
1034 | return -ENXIO; | 1057 | tty->driver_data = NULL; |
1058 | capiminor_put(mp); | ||
1059 | } | ||
1035 | 1060 | ||
1036 | tty->driver_data = (void *)mp; | 1061 | static int capinc_tty_open(struct tty_struct *tty, struct file *filp) |
1062 | { | ||
1063 | struct capiminor *mp = tty->driver_data; | ||
1064 | int err; | ||
1065 | |||
1066 | err = tty_port_open(&mp->port, tty, filp); | ||
1067 | if (err) | ||
1068 | return err; | ||
1037 | 1069 | ||
1038 | spin_lock_irqsave(&workaround_lock, flags); | ||
1039 | if (atomic_read(&mp->ttyopencount) == 0) | ||
1040 | mp->tty = tty; | ||
1041 | atomic_inc(&mp->ttyopencount); | ||
1042 | #ifdef _DEBUG_REFCOUNT | ||
1043 | printk(KERN_DEBUG "capinc_tty_open ocount=%d\n", atomic_read(&mp->ttyopencount)); | ||
1044 | #endif | ||
1045 | handle_minor_recv(mp); | 1070 | handle_minor_recv(mp); |
1046 | spin_unlock_irqrestore(&workaround_lock, flags); | ||
1047 | return 0; | 1071 | return 0; |
1048 | } | 1072 | } |
1049 | 1073 | ||
1050 | static void capinc_tty_close(struct tty_struct * tty, struct file * file) | 1074 | static void capinc_tty_close(struct tty_struct *tty, struct file *filp) |
1051 | { | 1075 | { |
1052 | struct capiminor *mp; | 1076 | struct capiminor *mp = tty->driver_data; |
1053 | |||
1054 | mp = (struct capiminor *)tty->driver_data; | ||
1055 | if (mp) { | ||
1056 | if (atomic_dec_and_test(&mp->ttyopencount)) { | ||
1057 | #ifdef _DEBUG_REFCOUNT | ||
1058 | printk(KERN_DEBUG "capinc_tty_close lastclose\n"); | ||
1059 | #endif | ||
1060 | tty->driver_data = NULL; | ||
1061 | mp->tty = NULL; | ||
1062 | } | ||
1063 | #ifdef _DEBUG_REFCOUNT | ||
1064 | printk(KERN_DEBUG "capinc_tty_close ocount=%d\n", atomic_read(&mp->ttyopencount)); | ||
1065 | #endif | ||
1066 | if (mp->nccip == NULL) | ||
1067 | capiminor_free(mp); | ||
1068 | } | ||
1069 | 1077 | ||
1070 | #ifdef _DEBUG_REFCOUNT | 1078 | tty_port_close(&mp->port, tty, filp); |
1071 | printk(KERN_DEBUG "capinc_tty_close\n"); | ||
1072 | #endif | ||
1073 | } | 1079 | } |
1074 | 1080 | ||
1075 | static int capinc_tty_write(struct tty_struct * tty, | 1081 | static int capinc_tty_write(struct tty_struct *tty, |
1076 | const unsigned char *buf, int count) | 1082 | const unsigned char *buf, int count) |
1077 | { | 1083 | { |
1078 | struct capiminor *mp = (struct capiminor *)tty->driver_data; | 1084 | struct capiminor *mp = tty->driver_data; |
1079 | struct sk_buff *skb; | 1085 | struct sk_buff *skb; |
1080 | unsigned long flags; | ||
1081 | 1086 | ||
1082 | #ifdef _DEBUG_TTYFUNCS | 1087 | #ifdef _DEBUG_TTYFUNCS |
1083 | printk(KERN_DEBUG "capinc_tty_write(count=%d)\n", count); | 1088 | printk(KERN_DEBUG "capinc_tty_write(count=%d)\n", count); |
1084 | #endif | 1089 | #endif |
1085 | 1090 | ||
1086 | if (!mp || !mp->nccip) { | 1091 | spin_lock_bh(&mp->outlock); |
1087 | #ifdef _DEBUG_TTYFUNCS | 1092 | skb = mp->outskb; |
1088 | printk(KERN_DEBUG "capinc_tty_write: mp or mp->ncci NULL\n"); | ||
1089 | #endif | ||
1090 | return 0; | ||
1091 | } | ||
1092 | |||
1093 | spin_lock_irqsave(&workaround_lock, flags); | ||
1094 | skb = mp->ttyskb; | ||
1095 | if (skb) { | 1093 | if (skb) { |
1096 | mp->ttyskb = NULL; | 1094 | mp->outskb = NULL; |
1097 | skb_queue_tail(&mp->outqueue, skb); | 1095 | __skb_queue_tail(&mp->outqueue, skb); |
1098 | mp->outbytes += skb->len; | 1096 | mp->outbytes += skb->len; |
1099 | } | 1097 | } |
1100 | 1098 | ||
1101 | skb = alloc_skb(CAPI_DATA_B3_REQ_LEN+count, GFP_ATOMIC); | 1099 | skb = alloc_skb(CAPI_DATA_B3_REQ_LEN+count, GFP_ATOMIC); |
1102 | if (!skb) { | 1100 | if (!skb) { |
1103 | printk(KERN_ERR "capinc_tty_write: alloc_skb failed\n"); | 1101 | printk(KERN_ERR "capinc_tty_write: alloc_skb failed\n"); |
1104 | spin_unlock_irqrestore(&workaround_lock, flags); | 1102 | spin_unlock_bh(&mp->outlock); |
1105 | return -ENOMEM; | 1103 | return -ENOMEM; |
1106 | } | 1104 | } |
1107 | 1105 | ||
1108 | skb_reserve(skb, CAPI_DATA_B3_REQ_LEN); | 1106 | skb_reserve(skb, CAPI_DATA_B3_REQ_LEN); |
1109 | memcpy(skb_put(skb, count), buf, count); | 1107 | memcpy(skb_put(skb, count), buf, count); |
1110 | 1108 | ||
1111 | skb_queue_tail(&mp->outqueue, skb); | 1109 | __skb_queue_tail(&mp->outqueue, skb); |
1112 | mp->outbytes += skb->len; | 1110 | mp->outbytes += skb->len; |
1113 | (void)handle_minor_send(mp); | 1111 | spin_unlock_bh(&mp->outlock); |
1114 | (void)handle_minor_recv(mp); | 1112 | |
1115 | spin_unlock_irqrestore(&workaround_lock, flags); | 1113 | handle_minor_send(mp); |
1114 | |||
1116 | return count; | 1115 | return count; |
1117 | } | 1116 | } |
1118 | 1117 | ||
1119 | static int capinc_tty_put_char(struct tty_struct *tty, unsigned char ch) | 1118 | static int capinc_tty_put_char(struct tty_struct *tty, unsigned char ch) |
1120 | { | 1119 | { |
1121 | struct capiminor *mp = (struct capiminor *)tty->driver_data; | 1120 | struct capiminor *mp = tty->driver_data; |
1121 | bool invoke_send = false; | ||
1122 | struct sk_buff *skb; | 1122 | struct sk_buff *skb; |
1123 | unsigned long flags; | ||
1124 | int ret = 1; | 1123 | int ret = 1; |
1125 | 1124 | ||
1126 | #ifdef _DEBUG_TTYFUNCS | 1125 | #ifdef _DEBUG_TTYFUNCS |
1127 | printk(KERN_DEBUG "capinc_put_char(%u)\n", ch); | 1126 | printk(KERN_DEBUG "capinc_put_char(%u)\n", ch); |
1128 | #endif | 1127 | #endif |
1129 | 1128 | ||
1130 | if (!mp || !mp->nccip) { | 1129 | spin_lock_bh(&mp->outlock); |
1131 | #ifdef _DEBUG_TTYFUNCS | 1130 | skb = mp->outskb; |
1132 | printk(KERN_DEBUG "capinc_tty_put_char: mp or mp->ncci NULL\n"); | ||
1133 | #endif | ||
1134 | return 0; | ||
1135 | } | ||
1136 | |||
1137 | spin_lock_irqsave(&workaround_lock, flags); | ||
1138 | skb = mp->ttyskb; | ||
1139 | if (skb) { | 1131 | if (skb) { |
1140 | if (skb_tailroom(skb) > 0) { | 1132 | if (skb_tailroom(skb) > 0) { |
1141 | *(skb_put(skb, 1)) = ch; | 1133 | *(skb_put(skb, 1)) = ch; |
1142 | spin_unlock_irqrestore(&workaround_lock, flags); | 1134 | goto unlock_out; |
1143 | return 1; | ||
1144 | } | 1135 | } |
1145 | mp->ttyskb = NULL; | 1136 | mp->outskb = NULL; |
1146 | skb_queue_tail(&mp->outqueue, skb); | 1137 | __skb_queue_tail(&mp->outqueue, skb); |
1147 | mp->outbytes += skb->len; | 1138 | mp->outbytes += skb->len; |
1148 | (void)handle_minor_send(mp); | 1139 | invoke_send = true; |
1149 | } | 1140 | } |
1141 | |||
1150 | skb = alloc_skb(CAPI_DATA_B3_REQ_LEN+CAPI_MAX_BLKSIZE, GFP_ATOMIC); | 1142 | skb = alloc_skb(CAPI_DATA_B3_REQ_LEN+CAPI_MAX_BLKSIZE, GFP_ATOMIC); |
1151 | if (skb) { | 1143 | if (skb) { |
1152 | skb_reserve(skb, CAPI_DATA_B3_REQ_LEN); | 1144 | skb_reserve(skb, CAPI_DATA_B3_REQ_LEN); |
1153 | *(skb_put(skb, 1)) = ch; | 1145 | *(skb_put(skb, 1)) = ch; |
1154 | mp->ttyskb = skb; | 1146 | mp->outskb = skb; |
1155 | } else { | 1147 | } else { |
1156 | printk(KERN_ERR "capinc_put_char: char %u lost\n", ch); | 1148 | printk(KERN_ERR "capinc_put_char: char %u lost\n", ch); |
1157 | ret = 0; | 1149 | ret = 0; |
1158 | } | 1150 | } |
1159 | spin_unlock_irqrestore(&workaround_lock, flags); | 1151 | |
1152 | unlock_out: | ||
1153 | spin_unlock_bh(&mp->outlock); | ||
1154 | |||
1155 | if (invoke_send) | ||
1156 | handle_minor_send(mp); | ||
1157 | |||
1160 | return ret; | 1158 | return ret; |
1161 | } | 1159 | } |
1162 | 1160 | ||
1163 | static void capinc_tty_flush_chars(struct tty_struct *tty) | 1161 | static void capinc_tty_flush_chars(struct tty_struct *tty) |
1164 | { | 1162 | { |
1165 | struct capiminor *mp = (struct capiminor *)tty->driver_data; | 1163 | struct capiminor *mp = tty->driver_data; |
1166 | struct sk_buff *skb; | 1164 | struct sk_buff *skb; |
1167 | unsigned long flags; | ||
1168 | 1165 | ||
1169 | #ifdef _DEBUG_TTYFUNCS | 1166 | #ifdef _DEBUG_TTYFUNCS |
1170 | printk(KERN_DEBUG "capinc_tty_flush_chars\n"); | 1167 | printk(KERN_DEBUG "capinc_tty_flush_chars\n"); |
1171 | #endif | 1168 | #endif |
1172 | 1169 | ||
1173 | if (!mp || !mp->nccip) { | 1170 | spin_lock_bh(&mp->outlock); |
1174 | #ifdef _DEBUG_TTYFUNCS | 1171 | skb = mp->outskb; |
1175 | printk(KERN_DEBUG "capinc_tty_flush_chars: mp or mp->ncci NULL\n"); | ||
1176 | #endif | ||
1177 | return; | ||
1178 | } | ||
1179 | |||
1180 | spin_lock_irqsave(&workaround_lock, flags); | ||
1181 | skb = mp->ttyskb; | ||
1182 | if (skb) { | 1172 | if (skb) { |
1183 | mp->ttyskb = NULL; | 1173 | mp->outskb = NULL; |
1184 | skb_queue_tail(&mp->outqueue, skb); | 1174 | __skb_queue_tail(&mp->outqueue, skb); |
1185 | mp->outbytes += skb->len; | 1175 | mp->outbytes += skb->len; |
1186 | (void)handle_minor_send(mp); | 1176 | spin_unlock_bh(&mp->outlock); |
1187 | } | 1177 | |
1188 | (void)handle_minor_recv(mp); | 1178 | handle_minor_send(mp); |
1189 | spin_unlock_irqrestore(&workaround_lock, flags); | 1179 | } else |
1180 | spin_unlock_bh(&mp->outlock); | ||
1181 | |||
1182 | handle_minor_recv(mp); | ||
1190 | } | 1183 | } |
1191 | 1184 | ||
1192 | static int capinc_tty_write_room(struct tty_struct *tty) | 1185 | static int capinc_tty_write_room(struct tty_struct *tty) |
1193 | { | 1186 | { |
1194 | struct capiminor *mp = (struct capiminor *)tty->driver_data; | 1187 | struct capiminor *mp = tty->driver_data; |
1195 | int room; | 1188 | int room; |
1196 | if (!mp || !mp->nccip) { | 1189 | |
1197 | #ifdef _DEBUG_TTYFUNCS | ||
1198 | printk(KERN_DEBUG "capinc_tty_write_room: mp or mp->ncci NULL\n"); | ||
1199 | #endif | ||
1200 | return 0; | ||
1201 | } | ||
1202 | room = CAPINC_MAX_SENDQUEUE-skb_queue_len(&mp->outqueue); | 1190 | room = CAPINC_MAX_SENDQUEUE-skb_queue_len(&mp->outqueue); |
1203 | room *= CAPI_MAX_BLKSIZE; | 1191 | room *= CAPI_MAX_BLKSIZE; |
1204 | #ifdef _DEBUG_TTYFUNCS | 1192 | #ifdef _DEBUG_TTYFUNCS |
@@ -1209,13 +1197,8 @@ static int capinc_tty_write_room(struct tty_struct *tty) | |||
1209 | 1197 | ||
1210 | static int capinc_tty_chars_in_buffer(struct tty_struct *tty) | 1198 | static int capinc_tty_chars_in_buffer(struct tty_struct *tty) |
1211 | { | 1199 | { |
1212 | struct capiminor *mp = (struct capiminor *)tty->driver_data; | 1200 | struct capiminor *mp = tty->driver_data; |
1213 | if (!mp || !mp->nccip) { | 1201 | |
1214 | #ifdef _DEBUG_TTYFUNCS | ||
1215 | printk(KERN_DEBUG "capinc_tty_chars_in_buffer: mp or mp->ncci NULL\n"); | ||
1216 | #endif | ||
1217 | return 0; | ||
1218 | } | ||
1219 | #ifdef _DEBUG_TTYFUNCS | 1202 | #ifdef _DEBUG_TTYFUNCS |
1220 | printk(KERN_DEBUG "capinc_tty_chars_in_buffer = %d nack=%d sq=%d rq=%d\n", | 1203 | printk(KERN_DEBUG "capinc_tty_chars_in_buffer = %d nack=%d sq=%d rq=%d\n", |
1221 | mp->outbytes, mp->nack, | 1204 | mp->outbytes, mp->nack, |
@@ -1244,62 +1227,55 @@ static void capinc_tty_set_termios(struct tty_struct *tty, struct ktermios * old | |||
1244 | #endif | 1227 | #endif |
1245 | } | 1228 | } |
1246 | 1229 | ||
1247 | static void capinc_tty_throttle(struct tty_struct * tty) | 1230 | static void capinc_tty_throttle(struct tty_struct *tty) |
1248 | { | 1231 | { |
1249 | struct capiminor *mp = (struct capiminor *)tty->driver_data; | 1232 | struct capiminor *mp = tty->driver_data; |
1250 | #ifdef _DEBUG_TTYFUNCS | 1233 | #ifdef _DEBUG_TTYFUNCS |
1251 | printk(KERN_DEBUG "capinc_tty_throttle\n"); | 1234 | printk(KERN_DEBUG "capinc_tty_throttle\n"); |
1252 | #endif | 1235 | #endif |
1253 | if (mp) | 1236 | mp->ttyinstop = 1; |
1254 | mp->ttyinstop = 1; | ||
1255 | } | 1237 | } |
1256 | 1238 | ||
1257 | static void capinc_tty_unthrottle(struct tty_struct * tty) | 1239 | static void capinc_tty_unthrottle(struct tty_struct *tty) |
1258 | { | 1240 | { |
1259 | struct capiminor *mp = (struct capiminor *)tty->driver_data; | 1241 | struct capiminor *mp = tty->driver_data; |
1260 | unsigned long flags; | 1242 | |
1261 | #ifdef _DEBUG_TTYFUNCS | 1243 | #ifdef _DEBUG_TTYFUNCS |
1262 | printk(KERN_DEBUG "capinc_tty_unthrottle\n"); | 1244 | printk(KERN_DEBUG "capinc_tty_unthrottle\n"); |
1263 | #endif | 1245 | #endif |
1264 | if (mp) { | 1246 | mp->ttyinstop = 0; |
1265 | spin_lock_irqsave(&workaround_lock, flags); | 1247 | handle_minor_recv(mp); |
1266 | mp->ttyinstop = 0; | ||
1267 | handle_minor_recv(mp); | ||
1268 | spin_unlock_irqrestore(&workaround_lock, flags); | ||
1269 | } | ||
1270 | } | 1248 | } |
1271 | 1249 | ||
1272 | static void capinc_tty_stop(struct tty_struct *tty) | 1250 | static void capinc_tty_stop(struct tty_struct *tty) |
1273 | { | 1251 | { |
1274 | struct capiminor *mp = (struct capiminor *)tty->driver_data; | 1252 | struct capiminor *mp = tty->driver_data; |
1253 | |||
1275 | #ifdef _DEBUG_TTYFUNCS | 1254 | #ifdef _DEBUG_TTYFUNCS |
1276 | printk(KERN_DEBUG "capinc_tty_stop\n"); | 1255 | printk(KERN_DEBUG "capinc_tty_stop\n"); |
1277 | #endif | 1256 | #endif |
1278 | if (mp) { | 1257 | mp->ttyoutstop = 1; |
1279 | mp->ttyoutstop = 1; | ||
1280 | } | ||
1281 | } | 1258 | } |
1282 | 1259 | ||
1283 | static void capinc_tty_start(struct tty_struct *tty) | 1260 | static void capinc_tty_start(struct tty_struct *tty) |
1284 | { | 1261 | { |
1285 | struct capiminor *mp = (struct capiminor *)tty->driver_data; | 1262 | struct capiminor *mp = tty->driver_data; |
1286 | unsigned long flags; | 1263 | |
1287 | #ifdef _DEBUG_TTYFUNCS | 1264 | #ifdef _DEBUG_TTYFUNCS |
1288 | printk(KERN_DEBUG "capinc_tty_start\n"); | 1265 | printk(KERN_DEBUG "capinc_tty_start\n"); |
1289 | #endif | 1266 | #endif |
1290 | if (mp) { | 1267 | mp->ttyoutstop = 0; |
1291 | spin_lock_irqsave(&workaround_lock, flags); | 1268 | handle_minor_send(mp); |
1292 | mp->ttyoutstop = 0; | ||
1293 | (void)handle_minor_send(mp); | ||
1294 | spin_unlock_irqrestore(&workaround_lock, flags); | ||
1295 | } | ||
1296 | } | 1269 | } |
1297 | 1270 | ||
1298 | static void capinc_tty_hangup(struct tty_struct *tty) | 1271 | static void capinc_tty_hangup(struct tty_struct *tty) |
1299 | { | 1272 | { |
1273 | struct capiminor *mp = tty->driver_data; | ||
1274 | |||
1300 | #ifdef _DEBUG_TTYFUNCS | 1275 | #ifdef _DEBUG_TTYFUNCS |
1301 | printk(KERN_DEBUG "capinc_tty_hangup\n"); | 1276 | printk(KERN_DEBUG "capinc_tty_hangup\n"); |
1302 | #endif | 1277 | #endif |
1278 | tty_port_hangup(&mp->port); | ||
1303 | } | 1279 | } |
1304 | 1280 | ||
1305 | static int capinc_tty_break_ctl(struct tty_struct *tty, int state) | 1281 | static int capinc_tty_break_ctl(struct tty_struct *tty, int state) |
@@ -1331,8 +1307,6 @@ static void capinc_tty_send_xchar(struct tty_struct *tty, char ch) | |||
1331 | #endif | 1307 | #endif |
1332 | } | 1308 | } |
1333 | 1309 | ||
1334 | static struct tty_driver *capinc_tty_driver; | ||
1335 | |||
1336 | static const struct tty_operations capinc_ops = { | 1310 | static const struct tty_operations capinc_ops = { |
1337 | .open = capinc_tty_open, | 1311 | .open = capinc_tty_open, |
1338 | .close = capinc_tty_close, | 1312 | .close = capinc_tty_close, |
@@ -1352,25 +1326,34 @@ static const struct tty_operations capinc_ops = { | |||
1352 | .flush_buffer = capinc_tty_flush_buffer, | 1326 | .flush_buffer = capinc_tty_flush_buffer, |
1353 | .set_ldisc = capinc_tty_set_ldisc, | 1327 | .set_ldisc = capinc_tty_set_ldisc, |
1354 | .send_xchar = capinc_tty_send_xchar, | 1328 | .send_xchar = capinc_tty_send_xchar, |
1329 | .install = capinc_tty_install, | ||
1330 | .cleanup = capinc_tty_cleanup, | ||
1355 | }; | 1331 | }; |
1356 | 1332 | ||
1357 | static int capinc_tty_init(void) | 1333 | static int __init capinc_tty_init(void) |
1358 | { | 1334 | { |
1359 | struct tty_driver *drv; | 1335 | struct tty_driver *drv; |
1360 | 1336 | int err; | |
1337 | |||
1361 | if (capi_ttyminors > CAPINC_MAX_PORTS) | 1338 | if (capi_ttyminors > CAPINC_MAX_PORTS) |
1362 | capi_ttyminors = CAPINC_MAX_PORTS; | 1339 | capi_ttyminors = CAPINC_MAX_PORTS; |
1363 | if (capi_ttyminors <= 0) | 1340 | if (capi_ttyminors <= 0) |
1364 | capi_ttyminors = CAPINC_NR_PORTS; | 1341 | capi_ttyminors = CAPINC_NR_PORTS; |
1365 | 1342 | ||
1366 | drv = alloc_tty_driver(capi_ttyminors); | 1343 | capiminors = kzalloc(sizeof(struct capi_minor *) * capi_ttyminors, |
1367 | if (!drv) | 1344 | GFP_KERNEL); |
1345 | if (!capiminors) | ||
1368 | return -ENOMEM; | 1346 | return -ENOMEM; |
1369 | 1347 | ||
1348 | drv = alloc_tty_driver(capi_ttyminors); | ||
1349 | if (!drv) { | ||
1350 | kfree(capiminors); | ||
1351 | return -ENOMEM; | ||
1352 | } | ||
1370 | drv->owner = THIS_MODULE; | 1353 | drv->owner = THIS_MODULE; |
1371 | drv->driver_name = "capi_nc"; | 1354 | drv->driver_name = "capi_nc"; |
1372 | drv->name = "capi"; | 1355 | drv->name = "capi"; |
1373 | drv->major = capi_ttymajor; | 1356 | drv->major = 0; |
1374 | drv->minor_start = 0; | 1357 | drv->minor_start = 0; |
1375 | drv->type = TTY_DRIVER_TYPE_SERIAL; | 1358 | drv->type = TTY_DRIVER_TYPE_SERIAL; |
1376 | drv->subtype = SERIAL_TYPE_NORMAL; | 1359 | drv->subtype = SERIAL_TYPE_NORMAL; |
@@ -1379,27 +1362,39 @@ static int capinc_tty_init(void) | |||
1379 | drv->init_termios.c_oflag = OPOST | ONLCR; | 1362 | drv->init_termios.c_oflag = OPOST | ONLCR; |
1380 | drv->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; | 1363 | drv->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; |
1381 | drv->init_termios.c_lflag = 0; | 1364 | drv->init_termios.c_lflag = 0; |
1382 | drv->flags = TTY_DRIVER_REAL_RAW|TTY_DRIVER_RESET_TERMIOS; | 1365 | drv->flags = |
1366 | TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS | | ||
1367 | TTY_DRIVER_DYNAMIC_DEV; | ||
1383 | tty_set_operations(drv, &capinc_ops); | 1368 | tty_set_operations(drv, &capinc_ops); |
1384 | if (tty_register_driver(drv)) { | 1369 | |
1370 | err = tty_register_driver(drv); | ||
1371 | if (err) { | ||
1385 | put_tty_driver(drv); | 1372 | put_tty_driver(drv); |
1373 | kfree(capiminors); | ||
1386 | printk(KERN_ERR "Couldn't register capi_nc driver\n"); | 1374 | printk(KERN_ERR "Couldn't register capi_nc driver\n"); |
1387 | return -1; | 1375 | return err; |
1388 | } | 1376 | } |
1389 | capinc_tty_driver = drv; | 1377 | capinc_tty_driver = drv; |
1390 | return 0; | 1378 | return 0; |
1391 | } | 1379 | } |
1392 | 1380 | ||
1393 | static void capinc_tty_exit(void) | 1381 | static void __exit capinc_tty_exit(void) |
1394 | { | 1382 | { |
1395 | struct tty_driver *drv = capinc_tty_driver; | 1383 | tty_unregister_driver(capinc_tty_driver); |
1396 | int retval; | 1384 | put_tty_driver(capinc_tty_driver); |
1397 | if ((retval = tty_unregister_driver(drv))) | 1385 | kfree(capiminors); |
1398 | printk(KERN_ERR "capi: failed to unregister capi_nc driver (%d)\n", retval); | ||
1399 | put_tty_driver(drv); | ||
1400 | } | 1386 | } |
1401 | 1387 | ||
1402 | #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ | 1388 | #else /* !CONFIG_ISDN_CAPI_MIDDLEWARE */ |
1389 | |||
1390 | static inline int capinc_tty_init(void) | ||
1391 | { | ||
1392 | return 0; | ||
1393 | } | ||
1394 | |||
1395 | static inline void capinc_tty_exit(void) { } | ||
1396 | |||
1397 | #endif /* !CONFIG_ISDN_CAPI_MIDDLEWARE */ | ||
1403 | 1398 | ||
1404 | /* -------- /proc functions ----------------------------------------- */ | 1399 | /* -------- /proc functions ----------------------------------------- */ |
1405 | 1400 | ||
@@ -1407,134 +1402,91 @@ static void capinc_tty_exit(void) | |||
1407 | * /proc/capi/capi20: | 1402 | * /proc/capi/capi20: |
1408 | * minor applid nrecvctlpkt nrecvdatapkt nsendctlpkt nsenddatapkt | 1403 | * minor applid nrecvctlpkt nrecvdatapkt nsendctlpkt nsenddatapkt |
1409 | */ | 1404 | */ |
1410 | static int proc_capidev_read_proc(char *page, char **start, off_t off, | 1405 | static int capi20_proc_show(struct seq_file *m, void *v) |
1411 | int count, int *eof, void *data) | ||
1412 | { | 1406 | { |
1413 | struct capidev *cdev; | 1407 | struct capidev *cdev; |
1414 | struct list_head *l; | 1408 | struct list_head *l; |
1415 | int len = 0; | ||
1416 | 1409 | ||
1417 | read_lock(&capidev_list_lock); | 1410 | mutex_lock(&capidev_list_lock); |
1418 | list_for_each(l, &capidev_list) { | 1411 | list_for_each(l, &capidev_list) { |
1419 | cdev = list_entry(l, struct capidev, list); | 1412 | cdev = list_entry(l, struct capidev, list); |
1420 | len += sprintf(page+len, "0 %d %lu %lu %lu %lu\n", | 1413 | seq_printf(m, "0 %d %lu %lu %lu %lu\n", |
1421 | cdev->ap.applid, | 1414 | cdev->ap.applid, |
1422 | cdev->ap.nrecvctlpkt, | 1415 | cdev->ap.nrecvctlpkt, |
1423 | cdev->ap.nrecvdatapkt, | 1416 | cdev->ap.nrecvdatapkt, |
1424 | cdev->ap.nsentctlpkt, | 1417 | cdev->ap.nsentctlpkt, |
1425 | cdev->ap.nsentdatapkt); | 1418 | cdev->ap.nsentdatapkt); |
1426 | if (len <= off) { | ||
1427 | off -= len; | ||
1428 | len = 0; | ||
1429 | } else { | ||
1430 | if (len-off > count) | ||
1431 | goto endloop; | ||
1432 | } | ||
1433 | } | 1419 | } |
1420 | mutex_unlock(&capidev_list_lock); | ||
1421 | return 0; | ||
1422 | } | ||
1434 | 1423 | ||
1435 | endloop: | 1424 | static int capi20_proc_open(struct inode *inode, struct file *file) |
1436 | read_unlock(&capidev_list_lock); | 1425 | { |
1437 | if (len < count) | 1426 | return single_open(file, capi20_proc_show, NULL); |
1438 | *eof = 1; | ||
1439 | if (len > count) len = count; | ||
1440 | if (len < 0) len = 0; | ||
1441 | return len; | ||
1442 | } | 1427 | } |
1443 | 1428 | ||
1429 | static const struct file_operations capi20_proc_fops = { | ||
1430 | .owner = THIS_MODULE, | ||
1431 | .open = capi20_proc_open, | ||
1432 | .read = seq_read, | ||
1433 | .llseek = seq_lseek, | ||
1434 | .release = single_release, | ||
1435 | }; | ||
1436 | |||
1444 | /* | 1437 | /* |
1445 | * /proc/capi/capi20ncci: | 1438 | * /proc/capi/capi20ncci: |
1446 | * applid ncci | 1439 | * applid ncci |
1447 | */ | 1440 | */ |
1448 | static int proc_capincci_read_proc(char *page, char **start, off_t off, | 1441 | static int capi20ncci_proc_show(struct seq_file *m, void *v) |
1449 | int count, int *eof, void *data) | ||
1450 | { | 1442 | { |
1451 | struct capidev *cdev; | 1443 | struct capidev *cdev; |
1452 | struct capincci *np; | 1444 | struct capincci *np; |
1453 | struct list_head *l; | ||
1454 | int len = 0; | ||
1455 | 1445 | ||
1456 | read_lock(&capidev_list_lock); | 1446 | mutex_lock(&capidev_list_lock); |
1457 | list_for_each(l, &capidev_list) { | 1447 | list_for_each_entry(cdev, &capidev_list, list) { |
1458 | cdev = list_entry(l, struct capidev, list); | 1448 | mutex_lock(&cdev->lock); |
1459 | for (np=cdev->nccis; np; np = np->next) { | 1449 | list_for_each_entry(np, &cdev->nccis, list) |
1460 | len += sprintf(page+len, "%d 0x%x\n", | 1450 | seq_printf(m, "%d 0x%x\n", cdev->ap.applid, np->ncci); |
1461 | cdev->ap.applid, | 1451 | mutex_unlock(&cdev->lock); |
1462 | np->ncci); | ||
1463 | if (len <= off) { | ||
1464 | off -= len; | ||
1465 | len = 0; | ||
1466 | } else { | ||
1467 | if (len-off > count) | ||
1468 | goto endloop; | ||
1469 | } | ||
1470 | } | ||
1471 | } | 1452 | } |
1472 | endloop: | 1453 | mutex_unlock(&capidev_list_lock); |
1473 | read_unlock(&capidev_list_lock); | 1454 | return 0; |
1474 | *start = page+off; | 1455 | } |
1475 | if (len < count) | 1456 | |
1476 | *eof = 1; | 1457 | static int capi20ncci_proc_open(struct inode *inode, struct file *file) |
1477 | if (len>count) len = count; | 1458 | { |
1478 | if (len<0) len = 0; | 1459 | return single_open(file, capi20ncci_proc_show, NULL); |
1479 | return len; | ||
1480 | } | 1460 | } |
1481 | 1461 | ||
1482 | static struct procfsentries { | 1462 | static const struct file_operations capi20ncci_proc_fops = { |
1483 | char *name; | 1463 | .owner = THIS_MODULE, |
1484 | mode_t mode; | 1464 | .open = capi20ncci_proc_open, |
1485 | int (*read_proc)(char *page, char **start, off_t off, | 1465 | .read = seq_read, |
1486 | int count, int *eof, void *data); | 1466 | .llseek = seq_lseek, |
1487 | struct proc_dir_entry *procent; | 1467 | .release = single_release, |
1488 | } procfsentries[] = { | ||
1489 | /* { "capi", S_IFDIR, 0 }, */ | ||
1490 | { "capi/capi20", 0 , proc_capidev_read_proc }, | ||
1491 | { "capi/capi20ncci", 0 , proc_capincci_read_proc }, | ||
1492 | }; | 1468 | }; |
1493 | 1469 | ||
1494 | static void __init proc_init(void) | 1470 | static void __init proc_init(void) |
1495 | { | 1471 | { |
1496 | int nelem = ARRAY_SIZE(procfsentries); | 1472 | proc_create("capi/capi20", 0, NULL, &capi20_proc_fops); |
1497 | int i; | 1473 | proc_create("capi/capi20ncci", 0, NULL, &capi20ncci_proc_fops); |
1498 | |||
1499 | for (i=0; i < nelem; i++) { | ||
1500 | struct procfsentries *p = procfsentries + i; | ||
1501 | p->procent = create_proc_entry(p->name, p->mode, NULL); | ||
1502 | if (p->procent) p->procent->read_proc = p->read_proc; | ||
1503 | } | ||
1504 | } | 1474 | } |
1505 | 1475 | ||
1506 | static void __exit proc_exit(void) | 1476 | static void __exit proc_exit(void) |
1507 | { | 1477 | { |
1508 | int nelem = ARRAY_SIZE(procfsentries); | 1478 | remove_proc_entry("capi/capi20", NULL); |
1509 | int i; | 1479 | remove_proc_entry("capi/capi20ncci", NULL); |
1510 | |||
1511 | for (i=nelem-1; i >= 0; i--) { | ||
1512 | struct procfsentries *p = procfsentries + i; | ||
1513 | if (p->procent) { | ||
1514 | remove_proc_entry(p->name, NULL); | ||
1515 | p->procent = NULL; | ||
1516 | } | ||
1517 | } | ||
1518 | } | 1480 | } |
1519 | 1481 | ||
1520 | /* -------- init function and module interface ---------------------- */ | 1482 | /* -------- init function and module interface ---------------------- */ |
1521 | 1483 | ||
1522 | 1484 | ||
1523 | static char rev[32]; | ||
1524 | |||
1525 | static int __init capi_init(void) | 1485 | static int __init capi_init(void) |
1526 | { | 1486 | { |
1527 | char *p; | 1487 | const char *compileinfo; |
1528 | char *compileinfo; | ||
1529 | int major_ret; | 1488 | int major_ret; |
1530 | 1489 | ||
1531 | if ((p = strchr(revision, ':')) != NULL && p[1]) { | ||
1532 | strlcpy(rev, p + 2, sizeof(rev)); | ||
1533 | if ((p = strchr(rev, '$')) != NULL && p > rev) | ||
1534 | *(p-1) = 0; | ||
1535 | } else | ||
1536 | strcpy(rev, "1.0"); | ||
1537 | |||
1538 | major_ret = register_chrdev(capi_major, "capi20", &capi_fops); | 1490 | major_ret = register_chrdev(capi_major, "capi20", &capi_fops); |
1539 | if (major_ret < 0) { | 1491 | if (major_ret < 0) { |
1540 | printk(KERN_ERR "capi20: unable to get major %d\n", capi_major); | 1492 | printk(KERN_ERR "capi20: unable to get major %d\n", capi_major); |
@@ -1548,28 +1500,24 @@ static int __init capi_init(void) | |||
1548 | 1500 | ||
1549 | device_create(capi_class, NULL, MKDEV(capi_major, 0), NULL, "capi"); | 1501 | device_create(capi_class, NULL, MKDEV(capi_major, 0), NULL, "capi"); |
1550 | 1502 | ||
1551 | #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE | ||
1552 | if (capinc_tty_init() < 0) { | 1503 | if (capinc_tty_init() < 0) { |
1553 | device_destroy(capi_class, MKDEV(capi_major, 0)); | 1504 | device_destroy(capi_class, MKDEV(capi_major, 0)); |
1554 | class_destroy(capi_class); | 1505 | class_destroy(capi_class); |
1555 | unregister_chrdev(capi_major, "capi20"); | 1506 | unregister_chrdev(capi_major, "capi20"); |
1556 | return -ENOMEM; | 1507 | return -ENOMEM; |
1557 | } | 1508 | } |
1558 | #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ | ||
1559 | 1509 | ||
1560 | proc_init(); | 1510 | proc_init(); |
1561 | 1511 | ||
1562 | #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE | ||
1563 | #if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE) | 1512 | #if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE) |
1564 | compileinfo = " (middleware+capifs)"; | 1513 | compileinfo = " (middleware+capifs)"; |
1565 | #else | 1514 | #elif defined(CONFIG_ISDN_CAPI_MIDDLEWARE) |
1566 | compileinfo = " (no capifs)"; | 1515 | compileinfo = " (no capifs)"; |
1567 | #endif | ||
1568 | #else | 1516 | #else |
1569 | compileinfo = " (no middleware)"; | 1517 | compileinfo = " (no middleware)"; |
1570 | #endif | 1518 | #endif |
1571 | printk(KERN_NOTICE "capi20: Rev %s: started up with major %d%s\n", | 1519 | printk(KERN_NOTICE "CAPI 2.0 started up with major %d%s\n", |
1572 | rev, capi_major, compileinfo); | 1520 | capi_major, compileinfo); |
1573 | 1521 | ||
1574 | return 0; | 1522 | return 0; |
1575 | } | 1523 | } |
@@ -1582,10 +1530,7 @@ static void __exit capi_exit(void) | |||
1582 | class_destroy(capi_class); | 1530 | class_destroy(capi_class); |
1583 | unregister_chrdev(capi_major, "capi20"); | 1531 | unregister_chrdev(capi_major, "capi20"); |
1584 | 1532 | ||
1585 | #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE | ||
1586 | capinc_tty_exit(); | 1533 | capinc_tty_exit(); |
1587 | #endif | ||
1588 | printk(KERN_NOTICE "capi: Rev %s: unloaded\n", rev); | ||
1589 | } | 1534 | } |
1590 | 1535 | ||
1591 | module_init(capi_init); | 1536 | module_init(capi_init); |
diff --git a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c index 3e6d17f42a98..bf55ed5f38e3 100644 --- a/drivers/isdn/capi/capidrv.c +++ b/drivers/isdn/capi/capidrv.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/isdn.h> | 24 | #include <linux/isdn.h> |
25 | #include <linux/isdnif.h> | 25 | #include <linux/isdnif.h> |
26 | #include <linux/proc_fs.h> | 26 | #include <linux/proc_fs.h> |
27 | #include <linux/seq_file.h> | ||
27 | #include <linux/capi.h> | 28 | #include <linux/capi.h> |
28 | #include <linux/kernelcapi.h> | 29 | #include <linux/kernelcapi.h> |
29 | #include <linux/ctype.h> | 30 | #include <linux/ctype.h> |
@@ -34,7 +35,6 @@ | |||
34 | #include <linux/isdn/capicmd.h> | 35 | #include <linux/isdn/capicmd.h> |
35 | #include "capidrv.h" | 36 | #include "capidrv.h" |
36 | 37 | ||
37 | static char *revision = "$Revision: 1.1.2.2 $"; | ||
38 | static int debugmode = 0; | 38 | static int debugmode = 0; |
39 | 39 | ||
40 | MODULE_DESCRIPTION("CAPI4Linux: Interface to ISDN4Linux"); | 40 | MODULE_DESCRIPTION("CAPI4Linux: Interface to ISDN4Linux"); |
@@ -830,7 +830,7 @@ static void handle_controller(_cmsg * cmsg) | |||
830 | case 0: break; | 830 | case 0: break; |
831 | case 1: s = "unknown class"; break; | 831 | case 1: s = "unknown class"; break; |
832 | case 2: s = "unknown function"; break; | 832 | case 2: s = "unknown function"; break; |
833 | default: s = "unkown error"; break; | 833 | default: s = "unknown error"; break; |
834 | } | 834 | } |
835 | if (s) | 835 | if (s) |
836 | printk(KERN_INFO "capidrv-%d: %s from controller 0x%x function %d: %s\n", | 836 | printk(KERN_INFO "capidrv-%d: %s from controller 0x%x function %d: %s\n", |
@@ -2210,96 +2210,73 @@ static int capidrv_delcontr(u16 contr) | |||
2210 | } | 2210 | } |
2211 | 2211 | ||
2212 | 2212 | ||
2213 | static void lower_callback(unsigned int cmd, u32 contr, void *data) | 2213 | static int |
2214 | lower_callback(struct notifier_block *nb, unsigned long val, void *v) | ||
2214 | { | 2215 | { |
2216 | capi_profile profile; | ||
2217 | u32 contr = (long)v; | ||
2215 | 2218 | ||
2216 | switch (cmd) { | 2219 | switch (val) { |
2217 | case KCI_CONTRUP: | 2220 | case CAPICTR_UP: |
2218 | printk(KERN_INFO "capidrv: controller %hu up\n", contr); | 2221 | printk(KERN_INFO "capidrv: controller %hu up\n", contr); |
2219 | (void) capidrv_addcontr(contr, (capi_profile *) data); | 2222 | if (capi20_get_profile(contr, &profile) == CAPI_NOERROR) |
2223 | (void) capidrv_addcontr(contr, &profile); | ||
2220 | break; | 2224 | break; |
2221 | case KCI_CONTRDOWN: | 2225 | case CAPICTR_DOWN: |
2222 | printk(KERN_INFO "capidrv: controller %hu down\n", contr); | 2226 | printk(KERN_INFO "capidrv: controller %hu down\n", contr); |
2223 | (void) capidrv_delcontr(contr); | 2227 | (void) capidrv_delcontr(contr); |
2224 | break; | 2228 | break; |
2225 | } | 2229 | } |
2230 | return NOTIFY_OK; | ||
2226 | } | 2231 | } |
2227 | 2232 | ||
2228 | /* | 2233 | /* |
2229 | * /proc/capi/capidrv: | 2234 | * /proc/capi/capidrv: |
2230 | * nrecvctlpkt nrecvdatapkt nsendctlpkt nsenddatapkt | 2235 | * nrecvctlpkt nrecvdatapkt nsendctlpkt nsenddatapkt |
2231 | */ | 2236 | */ |
2232 | static int proc_capidrv_read_proc(char *page, char **start, off_t off, | 2237 | static int capidrv_proc_show(struct seq_file *m, void *v) |
2233 | int count, int *eof, void *data) | ||
2234 | { | 2238 | { |
2235 | int len = 0; | 2239 | seq_printf(m, "%lu %lu %lu %lu\n", |
2236 | |||
2237 | len += sprintf(page+len, "%lu %lu %lu %lu\n", | ||
2238 | global.ap.nrecvctlpkt, | 2240 | global.ap.nrecvctlpkt, |
2239 | global.ap.nrecvdatapkt, | 2241 | global.ap.nrecvdatapkt, |
2240 | global.ap.nsentctlpkt, | 2242 | global.ap.nsentctlpkt, |
2241 | global.ap.nsentdatapkt); | 2243 | global.ap.nsentdatapkt); |
2242 | if (off+count >= len) | 2244 | return 0; |
2243 | *eof = 1; | ||
2244 | if (len < off) | ||
2245 | return 0; | ||
2246 | *start = page + off; | ||
2247 | return ((count < len-off) ? count : len-off); | ||
2248 | } | 2245 | } |
2249 | 2246 | ||
2250 | static struct procfsentries { | 2247 | static int capidrv_proc_open(struct inode *inode, struct file *file) |
2251 | char *name; | 2248 | { |
2252 | mode_t mode; | 2249 | return single_open(file, capidrv_proc_show, NULL); |
2253 | int (*read_proc)(char *page, char **start, off_t off, | 2250 | } |
2254 | int count, int *eof, void *data); | 2251 | |
2255 | struct proc_dir_entry *procent; | 2252 | static const struct file_operations capidrv_proc_fops = { |
2256 | } procfsentries[] = { | 2253 | .owner = THIS_MODULE, |
2257 | /* { "capi", S_IFDIR, 0 }, */ | 2254 | .open = capidrv_proc_open, |
2258 | { "capi/capidrv", 0 , proc_capidrv_read_proc }, | 2255 | .read = seq_read, |
2256 | .llseek = seq_lseek, | ||
2257 | .release = single_release, | ||
2259 | }; | 2258 | }; |
2260 | 2259 | ||
2261 | static void __init proc_init(void) | 2260 | static void __init proc_init(void) |
2262 | { | 2261 | { |
2263 | int nelem = ARRAY_SIZE(procfsentries); | 2262 | proc_create("capi/capidrv", 0, NULL, &capidrv_proc_fops); |
2264 | int i; | ||
2265 | |||
2266 | for (i=0; i < nelem; i++) { | ||
2267 | struct procfsentries *p = procfsentries + i; | ||
2268 | p->procent = create_proc_entry(p->name, p->mode, NULL); | ||
2269 | if (p->procent) p->procent->read_proc = p->read_proc; | ||
2270 | } | ||
2271 | } | 2263 | } |
2272 | 2264 | ||
2273 | static void __exit proc_exit(void) | 2265 | static void __exit proc_exit(void) |
2274 | { | 2266 | { |
2275 | int nelem = ARRAY_SIZE(procfsentries); | 2267 | remove_proc_entry("capi/capidrv", NULL); |
2276 | int i; | ||
2277 | |||
2278 | for (i=nelem-1; i >= 0; i--) { | ||
2279 | struct procfsentries *p = procfsentries + i; | ||
2280 | if (p->procent) { | ||
2281 | remove_proc_entry(p->name, NULL); | ||
2282 | p->procent = NULL; | ||
2283 | } | ||
2284 | } | ||
2285 | } | 2268 | } |
2286 | 2269 | ||
2270 | static struct notifier_block capictr_nb = { | ||
2271 | .notifier_call = lower_callback, | ||
2272 | }; | ||
2273 | |||
2287 | static int __init capidrv_init(void) | 2274 | static int __init capidrv_init(void) |
2288 | { | 2275 | { |
2289 | capi_profile profile; | 2276 | capi_profile profile; |
2290 | char rev[32]; | ||
2291 | char *p; | ||
2292 | u32 ncontr, contr; | 2277 | u32 ncontr, contr; |
2293 | u16 errcode; | 2278 | u16 errcode; |
2294 | 2279 | ||
2295 | if ((p = strchr(revision, ':')) != NULL && p[1]) { | ||
2296 | strncpy(rev, p + 2, sizeof(rev)); | ||
2297 | rev[sizeof(rev)-1] = 0; | ||
2298 | if ((p = strchr(rev, '$')) != NULL && p > rev) | ||
2299 | *(p-1) = 0; | ||
2300 | } else | ||
2301 | strcpy(rev, "1.0"); | ||
2302 | |||
2303 | global.ap.rparam.level3cnt = -2; /* number of bchannels twice */ | 2280 | global.ap.rparam.level3cnt = -2; /* number of bchannels twice */ |
2304 | global.ap.rparam.datablkcnt = 16; | 2281 | global.ap.rparam.datablkcnt = 16; |
2305 | global.ap.rparam.datablklen = 2048; | 2282 | global.ap.rparam.datablklen = 2048; |
@@ -2310,7 +2287,7 @@ static int __init capidrv_init(void) | |||
2310 | return -EIO; | 2287 | return -EIO; |
2311 | } | 2288 | } |
2312 | 2289 | ||
2313 | capi20_set_callback(&global.ap, lower_callback); | 2290 | register_capictr_notifier(&capictr_nb); |
2314 | 2291 | ||
2315 | errcode = capi20_get_profile(0, &profile); | 2292 | errcode = capi20_get_profile(0, &profile); |
2316 | if (errcode != CAPI_NOERROR) { | 2293 | if (errcode != CAPI_NOERROR) { |
@@ -2327,29 +2304,15 @@ static int __init capidrv_init(void) | |||
2327 | } | 2304 | } |
2328 | proc_init(); | 2305 | proc_init(); |
2329 | 2306 | ||
2330 | printk(KERN_NOTICE "capidrv: Rev %s: loaded\n", rev); | ||
2331 | return 0; | 2307 | return 0; |
2332 | } | 2308 | } |
2333 | 2309 | ||
2334 | static void __exit capidrv_exit(void) | 2310 | static void __exit capidrv_exit(void) |
2335 | { | 2311 | { |
2336 | char rev[32]; | 2312 | unregister_capictr_notifier(&capictr_nb); |
2337 | char *p; | ||
2338 | |||
2339 | if ((p = strchr(revision, ':')) != NULL) { | ||
2340 | strncpy(rev, p + 1, sizeof(rev)); | ||
2341 | rev[sizeof(rev)-1] = 0; | ||
2342 | if ((p = strchr(rev, '$')) != NULL) | ||
2343 | *p = 0; | ||
2344 | } else { | ||
2345 | strcpy(rev, " ??? "); | ||
2346 | } | ||
2347 | |||
2348 | capi20_release(&global.ap); | 2313 | capi20_release(&global.ap); |
2349 | 2314 | ||
2350 | proc_exit(); | 2315 | proc_exit(); |
2351 | |||
2352 | printk(KERN_NOTICE "capidrv: Rev%s: unloaded\n", rev); | ||
2353 | } | 2316 | } |
2354 | 2317 | ||
2355 | module_init(capidrv_init); | 2318 | module_init(capidrv_init); |
diff --git a/drivers/isdn/capi/capifs.c b/drivers/isdn/capi/capifs.c index 9f8f67b6c07f..2b83850997c3 100644 --- a/drivers/isdn/capi/capifs.c +++ b/drivers/isdn/capi/capifs.c | |||
@@ -11,6 +11,7 @@ | |||
11 | 11 | ||
12 | #include <linux/fs.h> | 12 | #include <linux/fs.h> |
13 | #include <linux/mount.h> | 13 | #include <linux/mount.h> |
14 | #include <linux/slab.h> | ||
14 | #include <linux/namei.h> | 15 | #include <linux/namei.h> |
15 | #include <linux/module.h> | 16 | #include <linux/module.h> |
16 | #include <linux/init.h> | 17 | #include <linux/init.h> |
@@ -25,14 +26,10 @@ MODULE_LICENSE("GPL"); | |||
25 | 26 | ||
26 | /* ------------------------------------------------------------------ */ | 27 | /* ------------------------------------------------------------------ */ |
27 | 28 | ||
28 | static char *revision = "$Revision: 1.1.2.3 $"; | ||
29 | |||
30 | /* ------------------------------------------------------------------ */ | ||
31 | |||
32 | #define CAPIFS_SUPER_MAGIC (('C'<<8)|'N') | 29 | #define CAPIFS_SUPER_MAGIC (('C'<<8)|'N') |
33 | 30 | ||
34 | static struct vfsmount *capifs_mnt; | 31 | static struct vfsmount *capifs_mnt; |
35 | static struct dentry *capifs_root; | 32 | static int capifs_mnt_count; |
36 | 33 | ||
37 | static struct { | 34 | static struct { |
38 | int setuid; | 35 | int setuid; |
@@ -118,7 +115,7 @@ capifs_fill_super(struct super_block *s, void *data, int silent) | |||
118 | inode->i_fop = &simple_dir_operations; | 115 | inode->i_fop = &simple_dir_operations; |
119 | inode->i_nlink = 2; | 116 | inode->i_nlink = 2; |
120 | 117 | ||
121 | capifs_root = s->s_root = d_alloc_root(inode); | 118 | s->s_root = d_alloc_root(inode); |
122 | if (s->s_root) | 119 | if (s->s_root) |
123 | return 0; | 120 | return 0; |
124 | 121 | ||
@@ -141,82 +138,98 @@ static struct file_system_type capifs_fs_type = { | |||
141 | .kill_sb = kill_anon_super, | 138 | .kill_sb = kill_anon_super, |
142 | }; | 139 | }; |
143 | 140 | ||
144 | static struct dentry *get_node(int num) | 141 | static struct dentry *new_ncci(unsigned int number, dev_t device) |
145 | { | 142 | { |
146 | char s[10]; | 143 | struct super_block *s = capifs_mnt->mnt_sb; |
147 | struct dentry *root = capifs_root; | 144 | struct dentry *root = s->s_root; |
145 | struct dentry *dentry; | ||
146 | struct inode *inode; | ||
147 | char name[10]; | ||
148 | int namelen; | ||
149 | |||
148 | mutex_lock(&root->d_inode->i_mutex); | 150 | mutex_lock(&root->d_inode->i_mutex); |
149 | return lookup_one_len(s, root, sprintf(s, "%d", num)); | ||
150 | } | ||
151 | 151 | ||
152 | void capifs_new_ncci(unsigned int number, dev_t device) | 152 | namelen = sprintf(name, "%d", number); |
153 | { | 153 | dentry = lookup_one_len(name, root, namelen); |
154 | struct dentry *dentry; | 154 | if (IS_ERR(dentry)) { |
155 | struct inode *inode = new_inode(capifs_mnt->mnt_sb); | 155 | dentry = NULL; |
156 | if (!inode) | 156 | goto unlock_out; |
157 | return; | 157 | } |
158 | inode->i_ino = number+2; | ||
159 | 158 | ||
160 | dentry = get_node(number); | 159 | if (dentry->d_inode) { |
160 | dput(dentry); | ||
161 | dentry = NULL; | ||
162 | goto unlock_out; | ||
163 | } | ||
164 | |||
165 | inode = new_inode(s); | ||
166 | if (!inode) { | ||
167 | dput(dentry); | ||
168 | dentry = NULL; | ||
169 | goto unlock_out; | ||
170 | } | ||
161 | 171 | ||
162 | /* config contents is protected by root's i_mutex */ | 172 | /* config contents is protected by root's i_mutex */ |
163 | inode->i_uid = config.setuid ? config.uid : current_fsuid(); | 173 | inode->i_uid = config.setuid ? config.uid : current_fsuid(); |
164 | inode->i_gid = config.setgid ? config.gid : current_fsgid(); | 174 | inode->i_gid = config.setgid ? config.gid : current_fsgid(); |
165 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; | 175 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; |
176 | inode->i_ino = number + 2; | ||
166 | init_special_inode(inode, S_IFCHR|config.mode, device); | 177 | init_special_inode(inode, S_IFCHR|config.mode, device); |
167 | //inode->i_op = &capifs_file_inode_operations; | ||
168 | 178 | ||
169 | if (!IS_ERR(dentry) && !dentry->d_inode) | 179 | d_instantiate(dentry, inode); |
170 | d_instantiate(dentry, inode); | 180 | dget(dentry); |
171 | mutex_unlock(&capifs_root->d_inode->i_mutex); | 181 | |
182 | unlock_out: | ||
183 | mutex_unlock(&root->d_inode->i_mutex); | ||
184 | |||
185 | return dentry; | ||
172 | } | 186 | } |
173 | 187 | ||
174 | void capifs_free_ncci(unsigned int number) | 188 | struct dentry *capifs_new_ncci(unsigned int number, dev_t device) |
175 | { | 189 | { |
176 | struct dentry *dentry = get_node(number); | 190 | struct dentry *dentry; |
177 | 191 | ||
178 | if (!IS_ERR(dentry)) { | 192 | if (simple_pin_fs(&capifs_fs_type, &capifs_mnt, &capifs_mnt_count) < 0) |
179 | struct inode *inode = dentry->d_inode; | 193 | return NULL; |
180 | if (inode) { | 194 | |
181 | inode->i_nlink--; | 195 | dentry = new_ncci(number, device); |
182 | d_delete(dentry); | 196 | if (!dentry) |
183 | dput(dentry); | 197 | simple_release_fs(&capifs_mnt, &capifs_mnt_count); |
184 | } | 198 | |
199 | return dentry; | ||
200 | } | ||
201 | |||
202 | void capifs_free_ncci(struct dentry *dentry) | ||
203 | { | ||
204 | struct dentry *root = capifs_mnt->mnt_sb->s_root; | ||
205 | struct inode *inode; | ||
206 | |||
207 | if (!dentry) | ||
208 | return; | ||
209 | |||
210 | mutex_lock(&root->d_inode->i_mutex); | ||
211 | |||
212 | inode = dentry->d_inode; | ||
213 | if (inode) { | ||
214 | drop_nlink(inode); | ||
215 | d_delete(dentry); | ||
185 | dput(dentry); | 216 | dput(dentry); |
186 | } | 217 | } |
187 | mutex_unlock(&capifs_root->d_inode->i_mutex); | 218 | dput(dentry); |
219 | |||
220 | mutex_unlock(&root->d_inode->i_mutex); | ||
221 | |||
222 | simple_release_fs(&capifs_mnt, &capifs_mnt_count); | ||
188 | } | 223 | } |
189 | 224 | ||
190 | static int __init capifs_init(void) | 225 | static int __init capifs_init(void) |
191 | { | 226 | { |
192 | char rev[32]; | 227 | return register_filesystem(&capifs_fs_type); |
193 | char *p; | ||
194 | int err; | ||
195 | |||
196 | if ((p = strchr(revision, ':')) != NULL && p[1]) { | ||
197 | strlcpy(rev, p + 2, sizeof(rev)); | ||
198 | if ((p = strchr(rev, '$')) != NULL && p > rev) | ||
199 | *(p-1) = 0; | ||
200 | } else | ||
201 | strcpy(rev, "1.0"); | ||
202 | |||
203 | err = register_filesystem(&capifs_fs_type); | ||
204 | if (!err) { | ||
205 | capifs_mnt = kern_mount(&capifs_fs_type); | ||
206 | if (IS_ERR(capifs_mnt)) { | ||
207 | err = PTR_ERR(capifs_mnt); | ||
208 | unregister_filesystem(&capifs_fs_type); | ||
209 | } | ||
210 | } | ||
211 | if (!err) | ||
212 | printk(KERN_NOTICE "capifs: Rev %s\n", rev); | ||
213 | return err; | ||
214 | } | 228 | } |
215 | 229 | ||
216 | static void __exit capifs_exit(void) | 230 | static void __exit capifs_exit(void) |
217 | { | 231 | { |
218 | unregister_filesystem(&capifs_fs_type); | 232 | unregister_filesystem(&capifs_fs_type); |
219 | mntput(capifs_mnt); | ||
220 | } | 233 | } |
221 | 234 | ||
222 | EXPORT_SYMBOL(capifs_new_ncci); | 235 | EXPORT_SYMBOL(capifs_new_ncci); |
diff --git a/drivers/isdn/capi/capifs.h b/drivers/isdn/capi/capifs.h index d0bd4c3c430a..e193d1189531 100644 --- a/drivers/isdn/capi/capifs.h +++ b/drivers/isdn/capi/capifs.h | |||
@@ -7,5 +7,22 @@ | |||
7 | * | 7 | * |
8 | */ | 8 | */ |
9 | 9 | ||
10 | void capifs_new_ncci(unsigned int num, dev_t device); | 10 | #include <linux/dcache.h> |
11 | void capifs_free_ncci(unsigned int num); | 11 | |
12 | #if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE) | ||
13 | |||
14 | struct dentry *capifs_new_ncci(unsigned int num, dev_t device); | ||
15 | void capifs_free_ncci(struct dentry *dentry); | ||
16 | |||
17 | #else | ||
18 | |||
19 | static inline struct dentry *capifs_new_ncci(unsigned int num, dev_t device) | ||
20 | { | ||
21 | return NULL; | ||
22 | } | ||
23 | |||
24 | static inline void capifs_free_ncci(struct dentry *dentry) | ||
25 | { | ||
26 | } | ||
27 | |||
28 | #endif | ||
diff --git a/drivers/isdn/capi/capilib.c b/drivers/isdn/capi/capilib.c index fcaa1241ee77..0b041df2108c 100644 --- a/drivers/isdn/capi/capilib.c +++ b/drivers/isdn/capi/capilib.c | |||
@@ -1,4 +1,5 @@ | |||
1 | 1 | ||
2 | #include <linux/slab.h> | ||
2 | #include <linux/kernel.h> | 3 | #include <linux/kernel.h> |
3 | #include <linux/module.h> | 4 | #include <linux/module.h> |
4 | #include <linux/isdn/capilli.h> | 5 | #include <linux/isdn/capilli.h> |
diff --git a/drivers/isdn/capi/capiutil.c b/drivers/isdn/capi/capiutil.c index 26626eead828..03c469e4451f 100644 --- a/drivers/isdn/capi/capiutil.c +++ b/drivers/isdn/capi/capiutil.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/mm.h> | 18 | #include <linux/mm.h> |
19 | #include <linux/init.h> | 19 | #include <linux/init.h> |
20 | #include <linux/isdn/capiutil.h> | 20 | #include <linux/isdn/capiutil.h> |
21 | #include <linux/slab.h> | ||
21 | 22 | ||
22 | /* from CAPI2.0 DDK AVM Berlin GmbH */ | 23 | /* from CAPI2.0 DDK AVM Berlin GmbH */ |
23 | 24 | ||
diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c index dc506ab99cac..bd00dceacaf0 100644 --- a/drivers/isdn/capi/kcapi.c +++ b/drivers/isdn/capi/kcapi.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/init.h> | 27 | #include <linux/init.h> |
28 | #include <linux/moduleparam.h> | 28 | #include <linux/moduleparam.h> |
29 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
30 | #include <linux/slab.h> | ||
30 | #include <asm/uaccess.h> | 31 | #include <asm/uaccess.h> |
31 | #include <linux/isdn/capicmd.h> | 32 | #include <linux/isdn/capicmd.h> |
32 | #include <linux/isdn/capiutil.h> | 33 | #include <linux/isdn/capiutil.h> |
@@ -34,10 +35,7 @@ | |||
34 | #include <linux/b1lli.h> | 35 | #include <linux/b1lli.h> |
35 | #endif | 36 | #endif |
36 | #include <linux/mutex.h> | 37 | #include <linux/mutex.h> |
37 | 38 | #include <linux/rcupdate.h> | |
38 | static char *revision = "$Revision: 1.1.2.8 $"; | ||
39 | |||
40 | /* ------------------------------------------------------------- */ | ||
41 | 39 | ||
42 | static int showcapimsgs = 0; | 40 | static int showcapimsgs = 0; |
43 | 41 | ||
@@ -48,12 +46,10 @@ module_param(showcapimsgs, uint, 0); | |||
48 | 46 | ||
49 | /* ------------------------------------------------------------- */ | 47 | /* ------------------------------------------------------------- */ |
50 | 48 | ||
51 | struct capi_notifier { | 49 | struct capictr_event { |
52 | struct work_struct work; | 50 | struct work_struct work; |
53 | unsigned int cmd; | 51 | unsigned int type; |
54 | u32 controller; | 52 | u32 controller; |
55 | u16 applid; | ||
56 | u32 ncci; | ||
57 | }; | 53 | }; |
58 | 54 | ||
59 | /* ------------------------------------------------------------- */ | 55 | /* ------------------------------------------------------------- */ |
@@ -65,30 +61,31 @@ static char capi_manufakturer[64] = "AVM Berlin"; | |||
65 | #define NCCI2CTRL(ncci) (((ncci) >> 24) & 0x7f) | 61 | #define NCCI2CTRL(ncci) (((ncci) >> 24) & 0x7f) |
66 | 62 | ||
67 | LIST_HEAD(capi_drivers); | 63 | LIST_HEAD(capi_drivers); |
68 | DEFINE_RWLOCK(capi_drivers_list_lock); | 64 | DEFINE_MUTEX(capi_drivers_lock); |
69 | 65 | ||
70 | static DEFINE_RWLOCK(application_lock); | 66 | struct capi_ctr *capi_controller[CAPI_MAXCONTR]; |
71 | static DEFINE_MUTEX(controller_mutex); | 67 | DEFINE_MUTEX(capi_controller_lock); |
72 | 68 | ||
73 | struct capi20_appl *capi_applications[CAPI_MAXAPPL]; | 69 | struct capi20_appl *capi_applications[CAPI_MAXAPPL]; |
74 | struct capi_ctr *capi_cards[CAPI_MAXCONTR]; | ||
75 | 70 | ||
76 | static int ncards; | 71 | static int ncontrollers; |
72 | |||
73 | static BLOCKING_NOTIFIER_HEAD(ctr_notifier_list); | ||
77 | 74 | ||
78 | /* -------- controller ref counting -------------------------------------- */ | 75 | /* -------- controller ref counting -------------------------------------- */ |
79 | 76 | ||
80 | static inline struct capi_ctr * | 77 | static inline struct capi_ctr * |
81 | capi_ctr_get(struct capi_ctr *card) | 78 | capi_ctr_get(struct capi_ctr *ctr) |
82 | { | 79 | { |
83 | if (!try_module_get(card->owner)) | 80 | if (!try_module_get(ctr->owner)) |
84 | return NULL; | 81 | return NULL; |
85 | return card; | 82 | return ctr; |
86 | } | 83 | } |
87 | 84 | ||
88 | static inline void | 85 | static inline void |
89 | capi_ctr_put(struct capi_ctr *card) | 86 | capi_ctr_put(struct capi_ctr *ctr) |
90 | { | 87 | { |
91 | module_put(card->owner); | 88 | module_put(ctr->owner); |
92 | } | 89 | } |
93 | 90 | ||
94 | /* ------------------------------------------------------------- */ | 91 | /* ------------------------------------------------------------- */ |
@@ -98,7 +95,7 @@ static inline struct capi_ctr *get_capi_ctr_by_nr(u16 contr) | |||
98 | if (contr - 1 >= CAPI_MAXCONTR) | 95 | if (contr - 1 >= CAPI_MAXCONTR) |
99 | return NULL; | 96 | return NULL; |
100 | 97 | ||
101 | return capi_cards[contr - 1]; | 98 | return capi_controller[contr - 1]; |
102 | } | 99 | } |
103 | 100 | ||
104 | static inline struct capi20_appl *get_capi_appl_by_nr(u16 applid) | 101 | static inline struct capi20_appl *get_capi_appl_by_nr(u16 applid) |
@@ -106,7 +103,7 @@ static inline struct capi20_appl *get_capi_appl_by_nr(u16 applid) | |||
106 | if (applid - 1 >= CAPI_MAXAPPL) | 103 | if (applid - 1 >= CAPI_MAXAPPL) |
107 | return NULL; | 104 | return NULL; |
108 | 105 | ||
109 | return capi_applications[applid - 1]; | 106 | return rcu_dereference(capi_applications[applid - 1]); |
110 | } | 107 | } |
111 | 108 | ||
112 | /* -------- util functions ------------------------------------ */ | 109 | /* -------- util functions ------------------------------------ */ |
@@ -148,106 +145,159 @@ static inline int capi_subcmd_valid(u8 subcmd) | |||
148 | 145 | ||
149 | /* ------------------------------------------------------------ */ | 146 | /* ------------------------------------------------------------ */ |
150 | 147 | ||
151 | static void register_appl(struct capi_ctr *card, u16 applid, capi_register_params *rparam) | 148 | static void |
149 | register_appl(struct capi_ctr *ctr, u16 applid, capi_register_params *rparam) | ||
152 | { | 150 | { |
153 | card = capi_ctr_get(card); | 151 | ctr = capi_ctr_get(ctr); |
154 | 152 | ||
155 | if (card) | 153 | if (ctr) |
156 | card->register_appl(card, applid, rparam); | 154 | ctr->register_appl(ctr, applid, rparam); |
157 | else | 155 | else |
158 | printk(KERN_WARNING "%s: cannot get card resources\n", __func__); | 156 | printk(KERN_WARNING "%s: cannot get controller resources\n", |
157 | __func__); | ||
159 | } | 158 | } |
160 | 159 | ||
161 | 160 | ||
162 | static void release_appl(struct capi_ctr *card, u16 applid) | 161 | static void release_appl(struct capi_ctr *ctr, u16 applid) |
163 | { | 162 | { |
164 | DBG("applid %#x", applid); | 163 | DBG("applid %#x", applid); |
165 | 164 | ||
166 | card->release_appl(card, applid); | 165 | ctr->release_appl(ctr, applid); |
167 | capi_ctr_put(card); | 166 | capi_ctr_put(ctr); |
168 | } | 167 | } |
169 | 168 | ||
170 | /* -------- KCI_CONTRUP --------------------------------------- */ | ||
171 | |||
172 | static void notify_up(u32 contr) | 169 | static void notify_up(u32 contr) |
173 | { | 170 | { |
174 | struct capi_ctr *card = get_capi_ctr_by_nr(contr); | ||
175 | struct capi20_appl *ap; | 171 | struct capi20_appl *ap; |
172 | struct capi_ctr *ctr; | ||
176 | u16 applid; | 173 | u16 applid; |
177 | 174 | ||
178 | if (showcapimsgs & 1) { | 175 | mutex_lock(&capi_controller_lock); |
176 | |||
177 | if (showcapimsgs & 1) | ||
179 | printk(KERN_DEBUG "kcapi: notify up contr %d\n", contr); | 178 | printk(KERN_DEBUG "kcapi: notify up contr %d\n", contr); |
180 | } | 179 | |
181 | if (!card) { | 180 | ctr = get_capi_ctr_by_nr(contr); |
181 | if (ctr) { | ||
182 | if (ctr->state == CAPI_CTR_RUNNING) | ||
183 | goto unlock_out; | ||
184 | |||
185 | ctr->state = CAPI_CTR_RUNNING; | ||
186 | |||
187 | for (applid = 1; applid <= CAPI_MAXAPPL; applid++) { | ||
188 | ap = get_capi_appl_by_nr(applid); | ||
189 | if (!ap) | ||
190 | continue; | ||
191 | register_appl(ctr, applid, &ap->rparam); | ||
192 | } | ||
193 | |||
194 | wake_up_interruptible_all(&ctr->state_wait_queue); | ||
195 | } else | ||
182 | printk(KERN_WARNING "%s: invalid contr %d\n", __func__, contr); | 196 | printk(KERN_WARNING "%s: invalid contr %d\n", __func__, contr); |
183 | return; | ||
184 | } | ||
185 | for (applid = 1; applid <= CAPI_MAXAPPL; applid++) { | ||
186 | ap = get_capi_appl_by_nr(applid); | ||
187 | if (!ap || ap->release_in_progress) continue; | ||
188 | register_appl(card, applid, &ap->rparam); | ||
189 | if (ap->callback && !ap->release_in_progress) | ||
190 | ap->callback(KCI_CONTRUP, contr, &card->profile); | ||
191 | } | ||
192 | } | ||
193 | 197 | ||
194 | /* -------- KCI_CONTRDOWN ------------------------------------- */ | 198 | unlock_out: |
199 | mutex_unlock(&capi_controller_lock); | ||
200 | } | ||
195 | 201 | ||
196 | static void notify_down(u32 contr) | 202 | static void ctr_down(struct capi_ctr *ctr, int new_state) |
197 | { | 203 | { |
198 | struct capi20_appl *ap; | 204 | struct capi20_appl *ap; |
199 | u16 applid; | 205 | u16 applid; |
200 | 206 | ||
201 | if (showcapimsgs & 1) { | 207 | if (ctr->state == CAPI_CTR_DETECTED || ctr->state == CAPI_CTR_DETACHED) |
202 | printk(KERN_DEBUG "kcapi: notify down contr %d\n", contr); | 208 | return; |
203 | } | 209 | |
210 | ctr->state = new_state; | ||
211 | |||
212 | memset(ctr->manu, 0, sizeof(ctr->manu)); | ||
213 | memset(&ctr->version, 0, sizeof(ctr->version)); | ||
214 | memset(&ctr->profile, 0, sizeof(ctr->profile)); | ||
215 | memset(ctr->serial, 0, sizeof(ctr->serial)); | ||
204 | 216 | ||
205 | for (applid = 1; applid <= CAPI_MAXAPPL; applid++) { | 217 | for (applid = 1; applid <= CAPI_MAXAPPL; applid++) { |
206 | ap = get_capi_appl_by_nr(applid); | 218 | ap = get_capi_appl_by_nr(applid); |
207 | if (ap && ap->callback && !ap->release_in_progress) | 219 | if (ap) |
208 | ap->callback(KCI_CONTRDOWN, contr, NULL); | 220 | capi_ctr_put(ctr); |
209 | } | 221 | } |
222 | |||
223 | wake_up_interruptible_all(&ctr->state_wait_queue); | ||
210 | } | 224 | } |
211 | 225 | ||
212 | static void notify_handler(struct work_struct *work) | 226 | static void notify_down(u32 contr) |
213 | { | 227 | { |
214 | struct capi_notifier *np = | 228 | struct capi_ctr *ctr; |
215 | container_of(work, struct capi_notifier, work); | ||
216 | 229 | ||
217 | switch (np->cmd) { | 230 | mutex_lock(&capi_controller_lock); |
218 | case KCI_CONTRUP: | 231 | |
219 | notify_up(np->controller); | 232 | if (showcapimsgs & 1) |
233 | printk(KERN_DEBUG "kcapi: notify down contr %d\n", contr); | ||
234 | |||
235 | ctr = get_capi_ctr_by_nr(contr); | ||
236 | if (ctr) | ||
237 | ctr_down(ctr, CAPI_CTR_DETECTED); | ||
238 | else | ||
239 | printk(KERN_WARNING "%s: invalid contr %d\n", __func__, contr); | ||
240 | |||
241 | mutex_unlock(&capi_controller_lock); | ||
242 | } | ||
243 | |||
244 | static int | ||
245 | notify_handler(struct notifier_block *nb, unsigned long val, void *v) | ||
246 | { | ||
247 | u32 contr = (long)v; | ||
248 | |||
249 | switch (val) { | ||
250 | case CAPICTR_UP: | ||
251 | notify_up(contr); | ||
220 | break; | 252 | break; |
221 | case KCI_CONTRDOWN: | 253 | case CAPICTR_DOWN: |
222 | notify_down(np->controller); | 254 | notify_down(contr); |
223 | break; | 255 | break; |
224 | } | 256 | } |
257 | return NOTIFY_OK; | ||
258 | } | ||
259 | |||
260 | static void do_notify_work(struct work_struct *work) | ||
261 | { | ||
262 | struct capictr_event *event = | ||
263 | container_of(work, struct capictr_event, work); | ||
225 | 264 | ||
226 | kfree(np); | 265 | blocking_notifier_call_chain(&ctr_notifier_list, event->type, |
266 | (void *)(long)event->controller); | ||
267 | kfree(event); | ||
227 | } | 268 | } |
228 | 269 | ||
229 | /* | 270 | /* |
230 | * The notifier will result in adding/deleteing of devices. Devices can | 271 | * The notifier will result in adding/deleteing of devices. Devices can |
231 | * only removed in user process, not in bh. | 272 | * only removed in user process, not in bh. |
232 | */ | 273 | */ |
233 | static int notify_push(unsigned int cmd, u32 controller, u16 applid, u32 ncci) | 274 | static int notify_push(unsigned int event_type, u32 controller) |
234 | { | 275 | { |
235 | struct capi_notifier *np = kmalloc(sizeof(*np), GFP_ATOMIC); | 276 | struct capictr_event *event = kmalloc(sizeof(*event), GFP_ATOMIC); |
236 | 277 | ||
237 | if (!np) | 278 | if (!event) |
238 | return -ENOMEM; | 279 | return -ENOMEM; |
239 | 280 | ||
240 | INIT_WORK(&np->work, notify_handler); | 281 | INIT_WORK(&event->work, do_notify_work); |
241 | np->cmd = cmd; | 282 | event->type = event_type; |
242 | np->controller = controller; | 283 | event->controller = controller; |
243 | np->applid = applid; | ||
244 | np->ncci = ncci; | ||
245 | 284 | ||
246 | schedule_work(&np->work); | 285 | schedule_work(&event->work); |
247 | return 0; | 286 | return 0; |
248 | } | 287 | } |
249 | 288 | ||
250 | 289 | int register_capictr_notifier(struct notifier_block *nb) | |
290 | { | ||
291 | return blocking_notifier_chain_register(&ctr_notifier_list, nb); | ||
292 | } | ||
293 | EXPORT_SYMBOL_GPL(register_capictr_notifier); | ||
294 | |||
295 | int unregister_capictr_notifier(struct notifier_block *nb) | ||
296 | { | ||
297 | return blocking_notifier_chain_unregister(&ctr_notifier_list, nb); | ||
298 | } | ||
299 | EXPORT_SYMBOL_GPL(unregister_capictr_notifier); | ||
300 | |||
251 | /* -------- Receiver ------------------------------------------ */ | 301 | /* -------- Receiver ------------------------------------------ */ |
252 | 302 | ||
253 | static void recv_handler(struct work_struct *work) | 303 | static void recv_handler(struct work_struct *work) |
@@ -273,68 +323,70 @@ static void recv_handler(struct work_struct *work) | |||
273 | 323 | ||
274 | /** | 324 | /** |
275 | * capi_ctr_handle_message() - handle incoming CAPI message | 325 | * capi_ctr_handle_message() - handle incoming CAPI message |
276 | * @card: controller descriptor structure. | 326 | * @ctr: controller descriptor structure. |
277 | * @appl: application ID. | 327 | * @appl: application ID. |
278 | * @skb: message. | 328 | * @skb: message. |
279 | * | 329 | * |
280 | * Called by hardware driver to pass a CAPI message to the application. | 330 | * Called by hardware driver to pass a CAPI message to the application. |
281 | */ | 331 | */ |
282 | 332 | ||
283 | void capi_ctr_handle_message(struct capi_ctr * card, u16 appl, struct sk_buff *skb) | 333 | void capi_ctr_handle_message(struct capi_ctr *ctr, u16 appl, |
334 | struct sk_buff *skb) | ||
284 | { | 335 | { |
285 | struct capi20_appl *ap; | 336 | struct capi20_appl *ap; |
286 | int showctl = 0; | 337 | int showctl = 0; |
287 | u8 cmd, subcmd; | 338 | u8 cmd, subcmd; |
288 | unsigned long flags; | ||
289 | _cdebbuf *cdb; | 339 | _cdebbuf *cdb; |
290 | 340 | ||
291 | if (card->cardstate != CARD_RUNNING) { | 341 | if (ctr->state != CAPI_CTR_RUNNING) { |
292 | cdb = capi_message2str(skb->data); | 342 | cdb = capi_message2str(skb->data); |
293 | if (cdb) { | 343 | if (cdb) { |
294 | printk(KERN_INFO "kcapi: controller [%03d] not active, got: %s", | 344 | printk(KERN_INFO "kcapi: controller [%03d] not active, got: %s", |
295 | card->cnr, cdb->buf); | 345 | ctr->cnr, cdb->buf); |
296 | cdebbuf_free(cdb); | 346 | cdebbuf_free(cdb); |
297 | } else | 347 | } else |
298 | printk(KERN_INFO "kcapi: controller [%03d] not active, cannot trace\n", | 348 | printk(KERN_INFO "kcapi: controller [%03d] not active, cannot trace\n", |
299 | card->cnr); | 349 | ctr->cnr); |
300 | goto error; | 350 | goto error; |
301 | } | 351 | } |
302 | 352 | ||
303 | cmd = CAPIMSG_COMMAND(skb->data); | 353 | cmd = CAPIMSG_COMMAND(skb->data); |
304 | subcmd = CAPIMSG_SUBCOMMAND(skb->data); | 354 | subcmd = CAPIMSG_SUBCOMMAND(skb->data); |
305 | if (cmd == CAPI_DATA_B3 && subcmd == CAPI_IND) { | 355 | if (cmd == CAPI_DATA_B3 && subcmd == CAPI_IND) { |
306 | card->nrecvdatapkt++; | 356 | ctr->nrecvdatapkt++; |
307 | if (card->traceflag > 2) showctl |= 2; | 357 | if (ctr->traceflag > 2) |
358 | showctl |= 2; | ||
308 | } else { | 359 | } else { |
309 | card->nrecvctlpkt++; | 360 | ctr->nrecvctlpkt++; |
310 | if (card->traceflag) showctl |= 2; | 361 | if (ctr->traceflag) |
362 | showctl |= 2; | ||
311 | } | 363 | } |
312 | showctl |= (card->traceflag & 1); | 364 | showctl |= (ctr->traceflag & 1); |
313 | if (showctl & 2) { | 365 | if (showctl & 2) { |
314 | if (showctl & 1) { | 366 | if (showctl & 1) { |
315 | printk(KERN_DEBUG "kcapi: got [%03d] id#%d %s len=%u\n", | 367 | printk(KERN_DEBUG "kcapi: got [%03d] id#%d %s len=%u\n", |
316 | card->cnr, CAPIMSG_APPID(skb->data), | 368 | ctr->cnr, CAPIMSG_APPID(skb->data), |
317 | capi_cmd2str(cmd, subcmd), | 369 | capi_cmd2str(cmd, subcmd), |
318 | CAPIMSG_LEN(skb->data)); | 370 | CAPIMSG_LEN(skb->data)); |
319 | } else { | 371 | } else { |
320 | cdb = capi_message2str(skb->data); | 372 | cdb = capi_message2str(skb->data); |
321 | if (cdb) { | 373 | if (cdb) { |
322 | printk(KERN_DEBUG "kcapi: got [%03d] %s\n", | 374 | printk(KERN_DEBUG "kcapi: got [%03d] %s\n", |
323 | card->cnr, cdb->buf); | 375 | ctr->cnr, cdb->buf); |
324 | cdebbuf_free(cdb); | 376 | cdebbuf_free(cdb); |
325 | } else | 377 | } else |
326 | printk(KERN_DEBUG "kcapi: got [%03d] id#%d %s len=%u, cannot trace\n", | 378 | printk(KERN_DEBUG "kcapi: got [%03d] id#%d %s len=%u, cannot trace\n", |
327 | card->cnr, CAPIMSG_APPID(skb->data), | 379 | ctr->cnr, CAPIMSG_APPID(skb->data), |
328 | capi_cmd2str(cmd, subcmd), | 380 | capi_cmd2str(cmd, subcmd), |
329 | CAPIMSG_LEN(skb->data)); | 381 | CAPIMSG_LEN(skb->data)); |
330 | } | 382 | } |
331 | 383 | ||
332 | } | 384 | } |
333 | 385 | ||
334 | read_lock_irqsave(&application_lock, flags); | 386 | rcu_read_lock(); |
335 | ap = get_capi_appl_by_nr(CAPIMSG_APPID(skb->data)); | 387 | ap = get_capi_appl_by_nr(CAPIMSG_APPID(skb->data)); |
336 | if ((!ap) || (ap->release_in_progress)) { | 388 | if (!ap) { |
337 | read_unlock_irqrestore(&application_lock, flags); | 389 | rcu_read_unlock(); |
338 | cdb = capi_message2str(skb->data); | 390 | cdb = capi_message2str(skb->data); |
339 | if (cdb) { | 391 | if (cdb) { |
340 | printk(KERN_ERR "kcapi: handle_message: applid %d state released (%s)\n", | 392 | printk(KERN_ERR "kcapi: handle_message: applid %d state released (%s)\n", |
@@ -348,7 +400,7 @@ void capi_ctr_handle_message(struct capi_ctr * card, u16 appl, struct sk_buff *s | |||
348 | } | 400 | } |
349 | skb_queue_tail(&ap->recv_queue, skb); | 401 | skb_queue_tail(&ap->recv_queue, skb); |
350 | schedule_work(&ap->recv_work); | 402 | schedule_work(&ap->recv_work); |
351 | read_unlock_irqrestore(&application_lock, flags); | 403 | rcu_read_unlock(); |
352 | 404 | ||
353 | return; | 405 | return; |
354 | 406 | ||
@@ -360,74 +412,54 @@ EXPORT_SYMBOL(capi_ctr_handle_message); | |||
360 | 412 | ||
361 | /** | 413 | /** |
362 | * capi_ctr_ready() - signal CAPI controller ready | 414 | * capi_ctr_ready() - signal CAPI controller ready |
363 | * @card: controller descriptor structure. | 415 | * @ctr: controller descriptor structure. |
364 | * | 416 | * |
365 | * Called by hardware driver to signal that the controller is up and running. | 417 | * Called by hardware driver to signal that the controller is up and running. |
366 | */ | 418 | */ |
367 | 419 | ||
368 | void capi_ctr_ready(struct capi_ctr * card) | 420 | void capi_ctr_ready(struct capi_ctr *ctr) |
369 | { | 421 | { |
370 | card->cardstate = CARD_RUNNING; | 422 | printk(KERN_NOTICE "kcapi: controller [%03d] \"%s\" ready.\n", |
371 | 423 | ctr->cnr, ctr->name); | |
372 | printk(KERN_NOTICE "kcapi: card [%03d] \"%s\" ready.\n", | ||
373 | card->cnr, card->name); | ||
374 | 424 | ||
375 | notify_push(KCI_CONTRUP, card->cnr, 0, 0); | 425 | notify_push(CAPICTR_UP, ctr->cnr); |
376 | } | 426 | } |
377 | 427 | ||
378 | EXPORT_SYMBOL(capi_ctr_ready); | 428 | EXPORT_SYMBOL(capi_ctr_ready); |
379 | 429 | ||
380 | /** | 430 | /** |
381 | * capi_ctr_down() - signal CAPI controller not ready | 431 | * capi_ctr_down() - signal CAPI controller not ready |
382 | * @card: controller descriptor structure. | 432 | * @ctr: controller descriptor structure. |
383 | * | 433 | * |
384 | * Called by hardware driver to signal that the controller is down and | 434 | * Called by hardware driver to signal that the controller is down and |
385 | * unavailable for use. | 435 | * unavailable for use. |
386 | */ | 436 | */ |
387 | 437 | ||
388 | void capi_ctr_down(struct capi_ctr * card) | 438 | void capi_ctr_down(struct capi_ctr *ctr) |
389 | { | 439 | { |
390 | u16 appl; | 440 | printk(KERN_NOTICE "kcapi: controller [%03d] down.\n", ctr->cnr); |
391 | |||
392 | DBG(""); | ||
393 | |||
394 | if (card->cardstate == CARD_DETECTED) | ||
395 | return; | ||
396 | |||
397 | card->cardstate = CARD_DETECTED; | ||
398 | |||
399 | memset(card->manu, 0, sizeof(card->manu)); | ||
400 | memset(&card->version, 0, sizeof(card->version)); | ||
401 | memset(&card->profile, 0, sizeof(card->profile)); | ||
402 | memset(card->serial, 0, sizeof(card->serial)); | ||
403 | |||
404 | for (appl = 1; appl <= CAPI_MAXAPPL; appl++) { | ||
405 | struct capi20_appl *ap = get_capi_appl_by_nr(appl); | ||
406 | if (!ap || ap->release_in_progress) | ||
407 | continue; | ||
408 | |||
409 | capi_ctr_put(card); | ||
410 | } | ||
411 | |||
412 | printk(KERN_NOTICE "kcapi: card [%03d] down.\n", card->cnr); | ||
413 | 441 | ||
414 | notify_push(KCI_CONTRDOWN, card->cnr, 0, 0); | 442 | notify_push(CAPICTR_DOWN, ctr->cnr); |
415 | } | 443 | } |
416 | 444 | ||
417 | EXPORT_SYMBOL(capi_ctr_down); | 445 | EXPORT_SYMBOL(capi_ctr_down); |
418 | 446 | ||
419 | /** | 447 | /** |
420 | * capi_ctr_suspend_output() - suspend controller | 448 | * capi_ctr_suspend_output() - suspend controller |
421 | * @card: controller descriptor structure. | 449 | * @ctr: controller descriptor structure. |
422 | * | 450 | * |
423 | * Called by hardware driver to stop data flow. | 451 | * Called by hardware driver to stop data flow. |
452 | * | ||
453 | * Note: The caller is responsible for synchronizing concurrent state changes | ||
454 | * as well as invocations of capi_ctr_handle_message. | ||
424 | */ | 455 | */ |
425 | 456 | ||
426 | void capi_ctr_suspend_output(struct capi_ctr *card) | 457 | void capi_ctr_suspend_output(struct capi_ctr *ctr) |
427 | { | 458 | { |
428 | if (!card->blocked) { | 459 | if (!ctr->blocked) { |
429 | printk(KERN_DEBUG "kcapi: card [%03d] suspend\n", card->cnr); | 460 | printk(KERN_DEBUG "kcapi: controller [%03d] suspend\n", |
430 | card->blocked = 1; | 461 | ctr->cnr); |
462 | ctr->blocked = 1; | ||
431 | } | 463 | } |
432 | } | 464 | } |
433 | 465 | ||
@@ -435,16 +467,20 @@ EXPORT_SYMBOL(capi_ctr_suspend_output); | |||
435 | 467 | ||
436 | /** | 468 | /** |
437 | * capi_ctr_resume_output() - resume controller | 469 | * capi_ctr_resume_output() - resume controller |
438 | * @card: controller descriptor structure. | 470 | * @ctr: controller descriptor structure. |
439 | * | 471 | * |
440 | * Called by hardware driver to resume data flow. | 472 | * Called by hardware driver to resume data flow. |
473 | * | ||
474 | * Note: The caller is responsible for synchronizing concurrent state changes | ||
475 | * as well as invocations of capi_ctr_handle_message. | ||
441 | */ | 476 | */ |
442 | 477 | ||
443 | void capi_ctr_resume_output(struct capi_ctr *card) | 478 | void capi_ctr_resume_output(struct capi_ctr *ctr) |
444 | { | 479 | { |
445 | if (card->blocked) { | 480 | if (ctr->blocked) { |
446 | printk(KERN_DEBUG "kcapi: card [%03d] resume\n", card->cnr); | 481 | printk(KERN_DEBUG "kcapi: controller [%03d] resumed\n", |
447 | card->blocked = 0; | 482 | ctr->cnr); |
483 | ctr->blocked = 0; | ||
448 | } | 484 | } |
449 | } | 485 | } |
450 | 486 | ||
@@ -454,53 +490,48 @@ EXPORT_SYMBOL(capi_ctr_resume_output); | |||
454 | 490 | ||
455 | /** | 491 | /** |
456 | * attach_capi_ctr() - register CAPI controller | 492 | * attach_capi_ctr() - register CAPI controller |
457 | * @card: controller descriptor structure. | 493 | * @ctr: controller descriptor structure. |
458 | * | 494 | * |
459 | * Called by hardware driver to register a controller with the CAPI subsystem. | 495 | * Called by hardware driver to register a controller with the CAPI subsystem. |
460 | * Return value: 0 on success, error code < 0 on error | 496 | * Return value: 0 on success, error code < 0 on error |
461 | */ | 497 | */ |
462 | 498 | ||
463 | int | 499 | int attach_capi_ctr(struct capi_ctr *ctr) |
464 | attach_capi_ctr(struct capi_ctr *card) | ||
465 | { | 500 | { |
466 | int i; | 501 | int i; |
467 | 502 | ||
468 | mutex_lock(&controller_mutex); | 503 | mutex_lock(&capi_controller_lock); |
469 | 504 | ||
470 | for (i = 0; i < CAPI_MAXCONTR; i++) { | 505 | for (i = 0; i < CAPI_MAXCONTR; i++) { |
471 | if (capi_cards[i] == NULL) | 506 | if (!capi_controller[i]) |
472 | break; | 507 | break; |
473 | } | 508 | } |
474 | if (i == CAPI_MAXCONTR) { | 509 | if (i == CAPI_MAXCONTR) { |
475 | mutex_unlock(&controller_mutex); | 510 | mutex_unlock(&capi_controller_lock); |
476 | printk(KERN_ERR "kcapi: out of controller slots\n"); | 511 | printk(KERN_ERR "kcapi: out of controller slots\n"); |
477 | return -EBUSY; | 512 | return -EBUSY; |
478 | } | 513 | } |
479 | capi_cards[i] = card; | 514 | capi_controller[i] = ctr; |
480 | 515 | ||
481 | mutex_unlock(&controller_mutex); | 516 | ctr->nrecvctlpkt = 0; |
482 | 517 | ctr->nrecvdatapkt = 0; | |
483 | card->nrecvctlpkt = 0; | 518 | ctr->nsentctlpkt = 0; |
484 | card->nrecvdatapkt = 0; | 519 | ctr->nsentdatapkt = 0; |
485 | card->nsentctlpkt = 0; | 520 | ctr->cnr = i + 1; |
486 | card->nsentdatapkt = 0; | 521 | ctr->state = CAPI_CTR_DETECTED; |
487 | card->cnr = i + 1; | 522 | ctr->blocked = 0; |
488 | card->cardstate = CARD_DETECTED; | 523 | ctr->traceflag = showcapimsgs; |
489 | card->blocked = 0; | 524 | init_waitqueue_head(&ctr->state_wait_queue); |
490 | card->traceflag = showcapimsgs; | ||
491 | |||
492 | sprintf(card->procfn, "capi/controllers/%d", card->cnr); | ||
493 | card->procent = create_proc_entry(card->procfn, 0, NULL); | ||
494 | if (card->procent) { | ||
495 | card->procent->read_proc = | ||
496 | (int (*)(char *,char **,off_t,int,int *,void *)) | ||
497 | card->ctr_read_proc; | ||
498 | card->procent->data = card; | ||
499 | } | ||
500 | 525 | ||
501 | ncards++; | 526 | sprintf(ctr->procfn, "capi/controllers/%d", ctr->cnr); |
502 | printk(KERN_NOTICE "kcapi: Controller [%03d]: %s attached\n", | 527 | ctr->procent = proc_create_data(ctr->procfn, 0, NULL, ctr->proc_fops, ctr); |
503 | card->cnr, card->name); | 528 | |
529 | ncontrollers++; | ||
530 | |||
531 | mutex_unlock(&capi_controller_lock); | ||
532 | |||
533 | printk(KERN_NOTICE "kcapi: controller [%03d]: %s attached\n", | ||
534 | ctr->cnr, ctr->name); | ||
504 | return 0; | 535 | return 0; |
505 | } | 536 | } |
506 | 537 | ||
@@ -508,29 +539,38 @@ EXPORT_SYMBOL(attach_capi_ctr); | |||
508 | 539 | ||
509 | /** | 540 | /** |
510 | * detach_capi_ctr() - unregister CAPI controller | 541 | * detach_capi_ctr() - unregister CAPI controller |
511 | * @card: controller descriptor structure. | 542 | * @ctr: controller descriptor structure. |
512 | * | 543 | * |
513 | * Called by hardware driver to remove the registration of a controller | 544 | * Called by hardware driver to remove the registration of a controller |
514 | * with the CAPI subsystem. | 545 | * with the CAPI subsystem. |
515 | * Return value: 0 on success, error code < 0 on error | 546 | * Return value: 0 on success, error code < 0 on error |
516 | */ | 547 | */ |
517 | 548 | ||
518 | int detach_capi_ctr(struct capi_ctr *card) | 549 | int detach_capi_ctr(struct capi_ctr *ctr) |
519 | { | 550 | { |
520 | if (card->cardstate != CARD_DETECTED) | 551 | int err = 0; |
521 | capi_ctr_down(card); | ||
522 | 552 | ||
523 | ncards--; | 553 | mutex_lock(&capi_controller_lock); |
524 | 554 | ||
525 | if (card->procent) { | 555 | ctr_down(ctr, CAPI_CTR_DETACHED); |
526 | remove_proc_entry(card->procfn, NULL); | 556 | |
527 | card->procent = NULL; | 557 | if (capi_controller[ctr->cnr - 1] != ctr) { |
558 | err = -EINVAL; | ||
559 | goto unlock_out; | ||
528 | } | 560 | } |
529 | capi_cards[card->cnr - 1] = NULL; | 561 | capi_controller[ctr->cnr - 1] = NULL; |
530 | printk(KERN_NOTICE "kcapi: Controller [%03d]: %s unregistered\n", | 562 | ncontrollers--; |
531 | card->cnr, card->name); | ||
532 | 563 | ||
533 | return 0; | 564 | if (ctr->procent) |
565 | remove_proc_entry(ctr->procfn, NULL); | ||
566 | |||
567 | printk(KERN_NOTICE "kcapi: controller [%03d]: %s unregistered\n", | ||
568 | ctr->cnr, ctr->name); | ||
569 | |||
570 | unlock_out: | ||
571 | mutex_unlock(&capi_controller_lock); | ||
572 | |||
573 | return err; | ||
534 | } | 574 | } |
535 | 575 | ||
536 | EXPORT_SYMBOL(detach_capi_ctr); | 576 | EXPORT_SYMBOL(detach_capi_ctr); |
@@ -544,11 +584,9 @@ EXPORT_SYMBOL(detach_capi_ctr); | |||
544 | 584 | ||
545 | void register_capi_driver(struct capi_driver *driver) | 585 | void register_capi_driver(struct capi_driver *driver) |
546 | { | 586 | { |
547 | unsigned long flags; | 587 | mutex_lock(&capi_drivers_lock); |
548 | |||
549 | write_lock_irqsave(&capi_drivers_list_lock, flags); | ||
550 | list_add_tail(&driver->list, &capi_drivers); | 588 | list_add_tail(&driver->list, &capi_drivers); |
551 | write_unlock_irqrestore(&capi_drivers_list_lock, flags); | 589 | mutex_unlock(&capi_drivers_lock); |
552 | } | 590 | } |
553 | 591 | ||
554 | EXPORT_SYMBOL(register_capi_driver); | 592 | EXPORT_SYMBOL(register_capi_driver); |
@@ -562,11 +600,9 @@ EXPORT_SYMBOL(register_capi_driver); | |||
562 | 600 | ||
563 | void unregister_capi_driver(struct capi_driver *driver) | 601 | void unregister_capi_driver(struct capi_driver *driver) |
564 | { | 602 | { |
565 | unsigned long flags; | 603 | mutex_lock(&capi_drivers_lock); |
566 | |||
567 | write_lock_irqsave(&capi_drivers_list_lock, flags); | ||
568 | list_del(&driver->list); | 604 | list_del(&driver->list); |
569 | write_unlock_irqrestore(&capi_drivers_list_lock, flags); | 605 | mutex_unlock(&capi_drivers_lock); |
570 | } | 606 | } |
571 | 607 | ||
572 | EXPORT_SYMBOL(unregister_capi_driver); | 608 | EXPORT_SYMBOL(unregister_capi_driver); |
@@ -584,12 +620,21 @@ EXPORT_SYMBOL(unregister_capi_driver); | |||
584 | 620 | ||
585 | u16 capi20_isinstalled(void) | 621 | u16 capi20_isinstalled(void) |
586 | { | 622 | { |
623 | u16 ret = CAPI_REGNOTINSTALLED; | ||
587 | int i; | 624 | int i; |
588 | for (i = 0; i < CAPI_MAXCONTR; i++) { | 625 | |
589 | if (capi_cards[i] && capi_cards[i]->cardstate == CARD_RUNNING) | 626 | mutex_lock(&capi_controller_lock); |
590 | return CAPI_NOERROR; | 627 | |
591 | } | 628 | for (i = 0; i < CAPI_MAXCONTR; i++) |
592 | return CAPI_REGNOTINSTALLED; | 629 | if (capi_controller[i] && |
630 | capi_controller[i]->state == CAPI_CTR_RUNNING) { | ||
631 | ret = CAPI_NOERROR; | ||
632 | break; | ||
633 | } | ||
634 | |||
635 | mutex_unlock(&capi_controller_lock); | ||
636 | |||
637 | return ret; | ||
593 | } | 638 | } |
594 | 639 | ||
595 | EXPORT_SYMBOL(capi20_isinstalled); | 640 | EXPORT_SYMBOL(capi20_isinstalled); |
@@ -610,46 +655,43 @@ u16 capi20_register(struct capi20_appl *ap) | |||
610 | { | 655 | { |
611 | int i; | 656 | int i; |
612 | u16 applid; | 657 | u16 applid; |
613 | unsigned long flags; | ||
614 | 658 | ||
615 | DBG(""); | 659 | DBG(""); |
616 | 660 | ||
617 | if (ap->rparam.datablklen < 128) | 661 | if (ap->rparam.datablklen < 128) |
618 | return CAPI_LOGBLKSIZETOSMALL; | 662 | return CAPI_LOGBLKSIZETOSMALL; |
619 | 663 | ||
620 | write_lock_irqsave(&application_lock, flags); | 664 | ap->nrecvctlpkt = 0; |
665 | ap->nrecvdatapkt = 0; | ||
666 | ap->nsentctlpkt = 0; | ||
667 | ap->nsentdatapkt = 0; | ||
668 | mutex_init(&ap->recv_mtx); | ||
669 | skb_queue_head_init(&ap->recv_queue); | ||
670 | INIT_WORK(&ap->recv_work, recv_handler); | ||
671 | ap->release_in_progress = 0; | ||
672 | |||
673 | mutex_lock(&capi_controller_lock); | ||
621 | 674 | ||
622 | for (applid = 1; applid <= CAPI_MAXAPPL; applid++) { | 675 | for (applid = 1; applid <= CAPI_MAXAPPL; applid++) { |
623 | if (capi_applications[applid - 1] == NULL) | 676 | if (capi_applications[applid - 1] == NULL) |
624 | break; | 677 | break; |
625 | } | 678 | } |
626 | if (applid > CAPI_MAXAPPL) { | 679 | if (applid > CAPI_MAXAPPL) { |
627 | write_unlock_irqrestore(&application_lock, flags); | 680 | mutex_unlock(&capi_controller_lock); |
628 | return CAPI_TOOMANYAPPLS; | 681 | return CAPI_TOOMANYAPPLS; |
629 | } | 682 | } |
630 | 683 | ||
631 | ap->applid = applid; | 684 | ap->applid = applid; |
632 | capi_applications[applid - 1] = ap; | 685 | capi_applications[applid - 1] = ap; |
633 | 686 | ||
634 | ap->nrecvctlpkt = 0; | ||
635 | ap->nrecvdatapkt = 0; | ||
636 | ap->nsentctlpkt = 0; | ||
637 | ap->nsentdatapkt = 0; | ||
638 | ap->callback = NULL; | ||
639 | mutex_init(&ap->recv_mtx); | ||
640 | skb_queue_head_init(&ap->recv_queue); | ||
641 | INIT_WORK(&ap->recv_work, recv_handler); | ||
642 | ap->release_in_progress = 0; | ||
643 | |||
644 | write_unlock_irqrestore(&application_lock, flags); | ||
645 | |||
646 | mutex_lock(&controller_mutex); | ||
647 | for (i = 0; i < CAPI_MAXCONTR; i++) { | 687 | for (i = 0; i < CAPI_MAXCONTR; i++) { |
648 | if (!capi_cards[i] || capi_cards[i]->cardstate != CARD_RUNNING) | 688 | if (!capi_controller[i] || |
689 | capi_controller[i]->state != CAPI_CTR_RUNNING) | ||
649 | continue; | 690 | continue; |
650 | register_appl(capi_cards[i], applid, &ap->rparam); | 691 | register_appl(capi_controller[i], applid, &ap->rparam); |
651 | } | 692 | } |
652 | mutex_unlock(&controller_mutex); | 693 | |
694 | mutex_unlock(&capi_controller_lock); | ||
653 | 695 | ||
654 | if (showcapimsgs & 1) { | 696 | if (showcapimsgs & 1) { |
655 | printk(KERN_DEBUG "kcapi: appl %d up\n", applid); | 697 | printk(KERN_DEBUG "kcapi: appl %d up\n", applid); |
@@ -673,22 +715,24 @@ EXPORT_SYMBOL(capi20_register); | |||
673 | u16 capi20_release(struct capi20_appl *ap) | 715 | u16 capi20_release(struct capi20_appl *ap) |
674 | { | 716 | { |
675 | int i; | 717 | int i; |
676 | unsigned long flags; | ||
677 | 718 | ||
678 | DBG("applid %#x", ap->applid); | 719 | DBG("applid %#x", ap->applid); |
679 | 720 | ||
680 | write_lock_irqsave(&application_lock, flags); | 721 | mutex_lock(&capi_controller_lock); |
722 | |||
681 | ap->release_in_progress = 1; | 723 | ap->release_in_progress = 1; |
682 | capi_applications[ap->applid - 1] = NULL; | 724 | capi_applications[ap->applid - 1] = NULL; |
683 | write_unlock_irqrestore(&application_lock, flags); | ||
684 | 725 | ||
685 | mutex_lock(&controller_mutex); | 726 | synchronize_rcu(); |
727 | |||
686 | for (i = 0; i < CAPI_MAXCONTR; i++) { | 728 | for (i = 0; i < CAPI_MAXCONTR; i++) { |
687 | if (!capi_cards[i] || capi_cards[i]->cardstate != CARD_RUNNING) | 729 | if (!capi_controller[i] || |
730 | capi_controller[i]->state != CAPI_CTR_RUNNING) | ||
688 | continue; | 731 | continue; |
689 | release_appl(capi_cards[i], ap->applid); | 732 | release_appl(capi_controller[i], ap->applid); |
690 | } | 733 | } |
691 | mutex_unlock(&controller_mutex); | 734 | |
735 | mutex_unlock(&capi_controller_lock); | ||
692 | 736 | ||
693 | flush_scheduled_work(); | 737 | flush_scheduled_work(); |
694 | skb_queue_purge(&ap->recv_queue); | 738 | skb_queue_purge(&ap->recv_queue); |
@@ -713,13 +757,13 @@ EXPORT_SYMBOL(capi20_release); | |||
713 | 757 | ||
714 | u16 capi20_put_message(struct capi20_appl *ap, struct sk_buff *skb) | 758 | u16 capi20_put_message(struct capi20_appl *ap, struct sk_buff *skb) |
715 | { | 759 | { |
716 | struct capi_ctr *card; | 760 | struct capi_ctr *ctr; |
717 | int showctl = 0; | 761 | int showctl = 0; |
718 | u8 cmd, subcmd; | 762 | u8 cmd, subcmd; |
719 | 763 | ||
720 | DBG("applid %#x", ap->applid); | 764 | DBG("applid %#x", ap->applid); |
721 | 765 | ||
722 | if (ncards == 0) | 766 | if (ncontrollers == 0) |
723 | return CAPI_REGNOTINSTALLED; | 767 | return CAPI_REGNOTINSTALLED; |
724 | if ((ap->applid == 0) || ap->release_in_progress) | 768 | if ((ap->applid == 0) || ap->release_in_progress) |
725 | return CAPI_ILLAPPNR; | 769 | return CAPI_ILLAPPNR; |
@@ -727,28 +771,33 @@ u16 capi20_put_message(struct capi20_appl *ap, struct sk_buff *skb) | |||
727 | || !capi_cmd_valid(CAPIMSG_COMMAND(skb->data)) | 771 | || !capi_cmd_valid(CAPIMSG_COMMAND(skb->data)) |
728 | || !capi_subcmd_valid(CAPIMSG_SUBCOMMAND(skb->data))) | 772 | || !capi_subcmd_valid(CAPIMSG_SUBCOMMAND(skb->data))) |
729 | return CAPI_ILLCMDORSUBCMDORMSGTOSMALL; | 773 | return CAPI_ILLCMDORSUBCMDORMSGTOSMALL; |
730 | card = get_capi_ctr_by_nr(CAPIMSG_CONTROLLER(skb->data)); | 774 | |
731 | if (!card || card->cardstate != CARD_RUNNING) { | 775 | /* |
732 | card = get_capi_ctr_by_nr(1); // XXX why? | 776 | * The controller reference is protected by the existence of the |
733 | if (!card || card->cardstate != CARD_RUNNING) | 777 | * application passed to us. We assume that the caller properly |
734 | return CAPI_REGNOTINSTALLED; | 778 | * synchronizes this service with capi20_release. |
735 | } | 779 | */ |
736 | if (card->blocked) | 780 | ctr = get_capi_ctr_by_nr(CAPIMSG_CONTROLLER(skb->data)); |
781 | if (!ctr || ctr->state != CAPI_CTR_RUNNING) | ||
782 | return CAPI_REGNOTINSTALLED; | ||
783 | if (ctr->blocked) | ||
737 | return CAPI_SENDQUEUEFULL; | 784 | return CAPI_SENDQUEUEFULL; |
738 | 785 | ||
739 | cmd = CAPIMSG_COMMAND(skb->data); | 786 | cmd = CAPIMSG_COMMAND(skb->data); |
740 | subcmd = CAPIMSG_SUBCOMMAND(skb->data); | 787 | subcmd = CAPIMSG_SUBCOMMAND(skb->data); |
741 | 788 | ||
742 | if (cmd == CAPI_DATA_B3 && subcmd== CAPI_REQ) { | 789 | if (cmd == CAPI_DATA_B3 && subcmd== CAPI_REQ) { |
743 | card->nsentdatapkt++; | 790 | ctr->nsentdatapkt++; |
744 | ap->nsentdatapkt++; | 791 | ap->nsentdatapkt++; |
745 | if (card->traceflag > 2) showctl |= 2; | 792 | if (ctr->traceflag > 2) |
793 | showctl |= 2; | ||
746 | } else { | 794 | } else { |
747 | card->nsentctlpkt++; | 795 | ctr->nsentctlpkt++; |
748 | ap->nsentctlpkt++; | 796 | ap->nsentctlpkt++; |
749 | if (card->traceflag) showctl |= 2; | 797 | if (ctr->traceflag) |
798 | showctl |= 2; | ||
750 | } | 799 | } |
751 | showctl |= (card->traceflag & 1); | 800 | showctl |= (ctr->traceflag & 1); |
752 | if (showctl & 2) { | 801 | if (showctl & 2) { |
753 | if (showctl & 1) { | 802 | if (showctl & 1) { |
754 | printk(KERN_DEBUG "kcapi: put [%03d] id#%d %s len=%u\n", | 803 | printk(KERN_DEBUG "kcapi: put [%03d] id#%d %s len=%u\n", |
@@ -771,7 +820,7 @@ u16 capi20_put_message(struct capi20_appl *ap, struct sk_buff *skb) | |||
771 | CAPIMSG_LEN(skb->data)); | 820 | CAPIMSG_LEN(skb->data)); |
772 | } | 821 | } |
773 | } | 822 | } |
774 | return card->send_message(card, skb); | 823 | return ctr->send_message(ctr, skb); |
775 | } | 824 | } |
776 | 825 | ||
777 | EXPORT_SYMBOL(capi20_put_message); | 826 | EXPORT_SYMBOL(capi20_put_message); |
@@ -788,17 +837,25 @@ EXPORT_SYMBOL(capi20_put_message); | |||
788 | 837 | ||
789 | u16 capi20_get_manufacturer(u32 contr, u8 *buf) | 838 | u16 capi20_get_manufacturer(u32 contr, u8 *buf) |
790 | { | 839 | { |
791 | struct capi_ctr *card; | 840 | struct capi_ctr *ctr; |
841 | u16 ret; | ||
792 | 842 | ||
793 | if (contr == 0) { | 843 | if (contr == 0) { |
794 | strlcpy(buf, capi_manufakturer, CAPI_MANUFACTURER_LEN); | 844 | strlcpy(buf, capi_manufakturer, CAPI_MANUFACTURER_LEN); |
795 | return CAPI_NOERROR; | 845 | return CAPI_NOERROR; |
796 | } | 846 | } |
797 | card = get_capi_ctr_by_nr(contr); | 847 | |
798 | if (!card || card->cardstate != CARD_RUNNING) | 848 | mutex_lock(&capi_controller_lock); |
799 | return CAPI_REGNOTINSTALLED; | 849 | |
800 | strlcpy(buf, card->manu, CAPI_MANUFACTURER_LEN); | 850 | ctr = get_capi_ctr_by_nr(contr); |
801 | return CAPI_NOERROR; | 851 | if (ctr && ctr->state == CAPI_CTR_RUNNING) { |
852 | strlcpy(buf, ctr->manu, CAPI_MANUFACTURER_LEN); | ||
853 | ret = CAPI_NOERROR; | ||
854 | } else | ||
855 | ret = CAPI_REGNOTINSTALLED; | ||
856 | |||
857 | mutex_unlock(&capi_controller_lock); | ||
858 | return ret; | ||
802 | } | 859 | } |
803 | 860 | ||
804 | EXPORT_SYMBOL(capi20_get_manufacturer); | 861 | EXPORT_SYMBOL(capi20_get_manufacturer); |
@@ -815,18 +872,25 @@ EXPORT_SYMBOL(capi20_get_manufacturer); | |||
815 | 872 | ||
816 | u16 capi20_get_version(u32 contr, struct capi_version *verp) | 873 | u16 capi20_get_version(u32 contr, struct capi_version *verp) |
817 | { | 874 | { |
818 | struct capi_ctr *card; | 875 | struct capi_ctr *ctr; |
876 | u16 ret; | ||
819 | 877 | ||
820 | if (contr == 0) { | 878 | if (contr == 0) { |
821 | *verp = driver_version; | 879 | *verp = driver_version; |
822 | return CAPI_NOERROR; | 880 | return CAPI_NOERROR; |
823 | } | 881 | } |
824 | card = get_capi_ctr_by_nr(contr); | ||
825 | if (!card || card->cardstate != CARD_RUNNING) | ||
826 | return CAPI_REGNOTINSTALLED; | ||
827 | 882 | ||
828 | memcpy((void *) verp, &card->version, sizeof(capi_version)); | 883 | mutex_lock(&capi_controller_lock); |
829 | return CAPI_NOERROR; | 884 | |
885 | ctr = get_capi_ctr_by_nr(contr); | ||
886 | if (ctr && ctr->state == CAPI_CTR_RUNNING) { | ||
887 | memcpy(verp, &ctr->version, sizeof(capi_version)); | ||
888 | ret = CAPI_NOERROR; | ||
889 | } else | ||
890 | ret = CAPI_REGNOTINSTALLED; | ||
891 | |||
892 | mutex_unlock(&capi_controller_lock); | ||
893 | return ret; | ||
830 | } | 894 | } |
831 | 895 | ||
832 | EXPORT_SYMBOL(capi20_get_version); | 896 | EXPORT_SYMBOL(capi20_get_version); |
@@ -843,18 +907,25 @@ EXPORT_SYMBOL(capi20_get_version); | |||
843 | 907 | ||
844 | u16 capi20_get_serial(u32 contr, u8 *serial) | 908 | u16 capi20_get_serial(u32 contr, u8 *serial) |
845 | { | 909 | { |
846 | struct capi_ctr *card; | 910 | struct capi_ctr *ctr; |
911 | u16 ret; | ||
847 | 912 | ||
848 | if (contr == 0) { | 913 | if (contr == 0) { |
849 | strlcpy(serial, driver_serial, CAPI_SERIAL_LEN); | 914 | strlcpy(serial, driver_serial, CAPI_SERIAL_LEN); |
850 | return CAPI_NOERROR; | 915 | return CAPI_NOERROR; |
851 | } | 916 | } |
852 | card = get_capi_ctr_by_nr(contr); | ||
853 | if (!card || card->cardstate != CARD_RUNNING) | ||
854 | return CAPI_REGNOTINSTALLED; | ||
855 | 917 | ||
856 | strlcpy((void *) serial, card->serial, CAPI_SERIAL_LEN); | 918 | mutex_lock(&capi_controller_lock); |
857 | return CAPI_NOERROR; | 919 | |
920 | ctr = get_capi_ctr_by_nr(contr); | ||
921 | if (ctr && ctr->state == CAPI_CTR_RUNNING) { | ||
922 | strlcpy(serial, ctr->serial, CAPI_SERIAL_LEN); | ||
923 | ret = CAPI_NOERROR; | ||
924 | } else | ||
925 | ret = CAPI_REGNOTINSTALLED; | ||
926 | |||
927 | mutex_unlock(&capi_controller_lock); | ||
928 | return ret; | ||
858 | } | 929 | } |
859 | 930 | ||
860 | EXPORT_SYMBOL(capi20_get_serial); | 931 | EXPORT_SYMBOL(capi20_get_serial); |
@@ -871,23 +942,65 @@ EXPORT_SYMBOL(capi20_get_serial); | |||
871 | 942 | ||
872 | u16 capi20_get_profile(u32 contr, struct capi_profile *profp) | 943 | u16 capi20_get_profile(u32 contr, struct capi_profile *profp) |
873 | { | 944 | { |
874 | struct capi_ctr *card; | 945 | struct capi_ctr *ctr; |
946 | u16 ret; | ||
875 | 947 | ||
876 | if (contr == 0) { | 948 | if (contr == 0) { |
877 | profp->ncontroller = ncards; | 949 | profp->ncontroller = ncontrollers; |
878 | return CAPI_NOERROR; | 950 | return CAPI_NOERROR; |
879 | } | 951 | } |
880 | card = get_capi_ctr_by_nr(contr); | ||
881 | if (!card || card->cardstate != CARD_RUNNING) | ||
882 | return CAPI_REGNOTINSTALLED; | ||
883 | 952 | ||
884 | memcpy((void *) profp, &card->profile, | 953 | mutex_lock(&capi_controller_lock); |
885 | sizeof(struct capi_profile)); | 954 | |
886 | return CAPI_NOERROR; | 955 | ctr = get_capi_ctr_by_nr(contr); |
956 | if (ctr && ctr->state == CAPI_CTR_RUNNING) { | ||
957 | memcpy(profp, &ctr->profile, sizeof(struct capi_profile)); | ||
958 | ret = CAPI_NOERROR; | ||
959 | } else | ||
960 | ret = CAPI_REGNOTINSTALLED; | ||
961 | |||
962 | mutex_unlock(&capi_controller_lock); | ||
963 | return ret; | ||
887 | } | 964 | } |
888 | 965 | ||
889 | EXPORT_SYMBOL(capi20_get_profile); | 966 | EXPORT_SYMBOL(capi20_get_profile); |
890 | 967 | ||
968 | /* Must be called with capi_controller_lock held. */ | ||
969 | static int wait_on_ctr_state(struct capi_ctr *ctr, unsigned int state) | ||
970 | { | ||
971 | DEFINE_WAIT(wait); | ||
972 | int retval = 0; | ||
973 | |||
974 | ctr = capi_ctr_get(ctr); | ||
975 | if (!ctr) | ||
976 | return -ESRCH; | ||
977 | |||
978 | for (;;) { | ||
979 | prepare_to_wait(&ctr->state_wait_queue, &wait, | ||
980 | TASK_INTERRUPTIBLE); | ||
981 | |||
982 | if (ctr->state == state) | ||
983 | break; | ||
984 | if (ctr->state == CAPI_CTR_DETACHED) { | ||
985 | retval = -ESRCH; | ||
986 | break; | ||
987 | } | ||
988 | if (signal_pending(current)) { | ||
989 | retval = -EINTR; | ||
990 | break; | ||
991 | } | ||
992 | |||
993 | mutex_unlock(&capi_controller_lock); | ||
994 | schedule(); | ||
995 | mutex_lock(&capi_controller_lock); | ||
996 | } | ||
997 | finish_wait(&ctr->state_wait_queue, &wait); | ||
998 | |||
999 | capi_ctr_put(ctr); | ||
1000 | |||
1001 | return retval; | ||
1002 | } | ||
1003 | |||
891 | #ifdef AVMB1_COMPAT | 1004 | #ifdef AVMB1_COMPAT |
892 | static int old_capi_manufacturer(unsigned int cmd, void __user *data) | 1005 | static int old_capi_manufacturer(unsigned int cmd, void __user *data) |
893 | { | 1006 | { |
@@ -895,11 +1008,10 @@ static int old_capi_manufacturer(unsigned int cmd, void __user *data) | |||
895 | avmb1_extcarddef cdef; | 1008 | avmb1_extcarddef cdef; |
896 | avmb1_resetdef rdef; | 1009 | avmb1_resetdef rdef; |
897 | capicardparams cparams; | 1010 | capicardparams cparams; |
898 | struct capi_ctr *card; | 1011 | struct capi_ctr *ctr; |
899 | struct capi_driver *driver = NULL; | 1012 | struct capi_driver *driver = NULL; |
900 | capiloaddata ldata; | 1013 | capiloaddata ldata; |
901 | struct list_head *l; | 1014 | struct list_head *l; |
902 | unsigned long flags; | ||
903 | int retval; | 1015 | int retval; |
904 | 1016 | ||
905 | switch (cmd) { | 1017 | switch (cmd) { |
@@ -919,7 +1031,8 @@ static int old_capi_manufacturer(unsigned int cmd, void __user *data) | |||
919 | cparams.irq = cdef.irq; | 1031 | cparams.irq = cdef.irq; |
920 | cparams.cardnr = cdef.cardnr; | 1032 | cparams.cardnr = cdef.cardnr; |
921 | 1033 | ||
922 | read_lock_irqsave(&capi_drivers_list_lock, flags); | 1034 | mutex_lock(&capi_drivers_lock); |
1035 | |||
923 | switch (cdef.cardtype) { | 1036 | switch (cdef.cardtype) { |
924 | case AVM_CARDTYPE_B1: | 1037 | case AVM_CARDTYPE_B1: |
925 | list_for_each(l, &capi_drivers) { | 1038 | list_for_each(l, &capi_drivers) { |
@@ -940,18 +1053,15 @@ static int old_capi_manufacturer(unsigned int cmd, void __user *data) | |||
940 | break; | 1053 | break; |
941 | } | 1054 | } |
942 | if (!driver) { | 1055 | if (!driver) { |
943 | read_unlock_irqrestore(&capi_drivers_list_lock, flags); | ||
944 | printk(KERN_ERR "kcapi: driver not loaded.\n"); | 1056 | printk(KERN_ERR "kcapi: driver not loaded.\n"); |
945 | return -EIO; | 1057 | retval = -EIO; |
946 | } | 1058 | } else if (!driver->add_card) { |
947 | if (!driver->add_card) { | ||
948 | read_unlock_irqrestore(&capi_drivers_list_lock, flags); | ||
949 | printk(KERN_ERR "kcapi: driver has no add card function.\n"); | 1059 | printk(KERN_ERR "kcapi: driver has no add card function.\n"); |
950 | return -EIO; | 1060 | retval = -EIO; |
951 | } | 1061 | } else |
1062 | retval = driver->add_card(driver, &cparams); | ||
952 | 1063 | ||
953 | retval = driver->add_card(driver, &cparams); | 1064 | mutex_unlock(&capi_drivers_lock); |
954 | read_unlock_irqrestore(&capi_drivers_list_lock, flags); | ||
955 | return retval; | 1065 | return retval; |
956 | 1066 | ||
957 | case AVMB1_LOAD: | 1067 | case AVMB1_LOAD: |
@@ -968,27 +1078,30 @@ static int old_capi_manufacturer(unsigned int cmd, void __user *data) | |||
968 | sizeof(avmb1_loadandconfigdef))) | 1078 | sizeof(avmb1_loadandconfigdef))) |
969 | return -EFAULT; | 1079 | return -EFAULT; |
970 | } | 1080 | } |
971 | card = get_capi_ctr_by_nr(ldef.contr); | 1081 | |
972 | if (!card) | 1082 | mutex_lock(&capi_controller_lock); |
973 | return -EINVAL; | 1083 | |
974 | card = capi_ctr_get(card); | 1084 | ctr = get_capi_ctr_by_nr(ldef.contr); |
975 | if (!card) | 1085 | if (!ctr) { |
976 | return -ESRCH; | 1086 | retval = -EINVAL; |
977 | if (card->load_firmware == NULL) { | 1087 | goto load_unlock_out; |
1088 | } | ||
1089 | |||
1090 | if (ctr->load_firmware == NULL) { | ||
978 | printk(KERN_DEBUG "kcapi: load: no load function\n"); | 1091 | printk(KERN_DEBUG "kcapi: load: no load function\n"); |
979 | capi_ctr_put(card); | 1092 | retval = -ESRCH; |
980 | return -ESRCH; | 1093 | goto load_unlock_out; |
981 | } | 1094 | } |
982 | 1095 | ||
983 | if (ldef.t4file.len <= 0) { | 1096 | if (ldef.t4file.len <= 0) { |
984 | printk(KERN_DEBUG "kcapi: load: invalid parameter: length of t4file is %d ?\n", ldef.t4file.len); | 1097 | printk(KERN_DEBUG "kcapi: load: invalid parameter: length of t4file is %d ?\n", ldef.t4file.len); |
985 | capi_ctr_put(card); | 1098 | retval = -EINVAL; |
986 | return -EINVAL; | 1099 | goto load_unlock_out; |
987 | } | 1100 | } |
988 | if (ldef.t4file.data == NULL) { | 1101 | if (ldef.t4file.data == NULL) { |
989 | printk(KERN_DEBUG "kcapi: load: invalid parameter: dataptr is 0\n"); | 1102 | printk(KERN_DEBUG "kcapi: load: invalid parameter: dataptr is 0\n"); |
990 | capi_ctr_put(card); | 1103 | retval = -EINVAL; |
991 | return -EINVAL; | 1104 | goto load_unlock_out; |
992 | } | 1105 | } |
993 | 1106 | ||
994 | ldata.firmware.user = 1; | 1107 | ldata.firmware.user = 1; |
@@ -998,54 +1111,49 @@ static int old_capi_manufacturer(unsigned int cmd, void __user *data) | |||
998 | ldata.configuration.data = ldef.t4config.data; | 1111 | ldata.configuration.data = ldef.t4config.data; |
999 | ldata.configuration.len = ldef.t4config.len; | 1112 | ldata.configuration.len = ldef.t4config.len; |
1000 | 1113 | ||
1001 | if (card->cardstate != CARD_DETECTED) { | 1114 | if (ctr->state != CAPI_CTR_DETECTED) { |
1002 | printk(KERN_INFO "kcapi: load: contr=%d not in detect state\n", ldef.contr); | 1115 | printk(KERN_INFO "kcapi: load: contr=%d not in detect state\n", ldef.contr); |
1003 | capi_ctr_put(card); | 1116 | retval = -EBUSY; |
1004 | return -EBUSY; | 1117 | goto load_unlock_out; |
1005 | } | 1118 | } |
1006 | card->cardstate = CARD_LOADING; | 1119 | ctr->state = CAPI_CTR_LOADING; |
1007 | |||
1008 | retval = card->load_firmware(card, &ldata); | ||
1009 | 1120 | ||
1121 | retval = ctr->load_firmware(ctr, &ldata); | ||
1010 | if (retval) { | 1122 | if (retval) { |
1011 | card->cardstate = CARD_DETECTED; | 1123 | ctr->state = CAPI_CTR_DETECTED; |
1012 | capi_ctr_put(card); | 1124 | goto load_unlock_out; |
1013 | return retval; | ||
1014 | } | 1125 | } |
1015 | 1126 | ||
1016 | while (card->cardstate != CARD_RUNNING) { | 1127 | retval = wait_on_ctr_state(ctr, CAPI_CTR_RUNNING); |
1017 | |||
1018 | msleep_interruptible(100); /* 0.1 sec */ | ||
1019 | 1128 | ||
1020 | if (signal_pending(current)) { | 1129 | load_unlock_out: |
1021 | capi_ctr_put(card); | 1130 | mutex_unlock(&capi_controller_lock); |
1022 | return -EINTR; | 1131 | return retval; |
1023 | } | ||
1024 | } | ||
1025 | capi_ctr_put(card); | ||
1026 | return 0; | ||
1027 | 1132 | ||
1028 | case AVMB1_RESETCARD: | 1133 | case AVMB1_RESETCARD: |
1029 | if (copy_from_user(&rdef, data, sizeof(avmb1_resetdef))) | 1134 | if (copy_from_user(&rdef, data, sizeof(avmb1_resetdef))) |
1030 | return -EFAULT; | 1135 | return -EFAULT; |
1031 | card = get_capi_ctr_by_nr(rdef.contr); | ||
1032 | if (!card) | ||
1033 | return -ESRCH; | ||
1034 | 1136 | ||
1035 | if (card->cardstate == CARD_DETECTED) | 1137 | retval = 0; |
1036 | return 0; | ||
1037 | 1138 | ||
1038 | card->reset_ctr(card); | 1139 | mutex_lock(&capi_controller_lock); |
1039 | 1140 | ||
1040 | while (card->cardstate > CARD_DETECTED) { | 1141 | ctr = get_capi_ctr_by_nr(rdef.contr); |
1142 | if (!ctr) { | ||
1143 | retval = -ESRCH; | ||
1144 | goto reset_unlock_out; | ||
1145 | } | ||
1041 | 1146 | ||
1042 | msleep_interruptible(100); /* 0.1 sec */ | 1147 | if (ctr->state == CAPI_CTR_DETECTED) |
1148 | goto reset_unlock_out; | ||
1043 | 1149 | ||
1044 | if (signal_pending(current)) | 1150 | ctr->reset_ctr(ctr); |
1045 | return -EINTR; | 1151 | |
1046 | } | 1152 | retval = wait_on_ctr_state(ctr, CAPI_CTR_DETECTED); |
1047 | return 0; | ||
1048 | 1153 | ||
1154 | reset_unlock_out: | ||
1155 | mutex_unlock(&capi_controller_lock); | ||
1156 | return retval; | ||
1049 | } | 1157 | } |
1050 | return -EINVAL; | 1158 | return -EINVAL; |
1051 | } | 1159 | } |
@@ -1062,7 +1170,8 @@ static int old_capi_manufacturer(unsigned int cmd, void __user *data) | |||
1062 | 1170 | ||
1063 | int capi20_manufacturer(unsigned int cmd, void __user *data) | 1171 | int capi20_manufacturer(unsigned int cmd, void __user *data) |
1064 | { | 1172 | { |
1065 | struct capi_ctr *card; | 1173 | struct capi_ctr *ctr; |
1174 | int retval; | ||
1066 | 1175 | ||
1067 | switch (cmd) { | 1176 | switch (cmd) { |
1068 | #ifdef AVMB1_COMPAT | 1177 | #ifdef AVMB1_COMPAT |
@@ -1080,14 +1189,20 @@ int capi20_manufacturer(unsigned int cmd, void __user *data) | |||
1080 | if (copy_from_user(&fdef, data, sizeof(kcapi_flagdef))) | 1189 | if (copy_from_user(&fdef, data, sizeof(kcapi_flagdef))) |
1081 | return -EFAULT; | 1190 | return -EFAULT; |
1082 | 1191 | ||
1083 | card = get_capi_ctr_by_nr(fdef.contr); | 1192 | mutex_lock(&capi_controller_lock); |
1084 | if (!card) | 1193 | |
1085 | return -ESRCH; | 1194 | ctr = get_capi_ctr_by_nr(fdef.contr); |
1195 | if (ctr) { | ||
1196 | ctr->traceflag = fdef.flag; | ||
1197 | printk(KERN_INFO "kcapi: contr [%03d] set trace=%d\n", | ||
1198 | ctr->cnr, ctr->traceflag); | ||
1199 | retval = 0; | ||
1200 | } else | ||
1201 | retval = -ESRCH; | ||
1202 | |||
1203 | mutex_unlock(&capi_controller_lock); | ||
1086 | 1204 | ||
1087 | card->traceflag = fdef.flag; | 1205 | return retval; |
1088 | printk(KERN_INFO "kcapi: contr [%03d] set trace=%d\n", | ||
1089 | card->cnr, card->traceflag); | ||
1090 | return 0; | ||
1091 | } | 1206 | } |
1092 | case KCAPI_CMD_ADDCARD: | 1207 | case KCAPI_CMD_ADDCARD: |
1093 | { | 1208 | { |
@@ -1095,7 +1210,6 @@ int capi20_manufacturer(unsigned int cmd, void __user *data) | |||
1095 | struct capi_driver *driver = NULL; | 1210 | struct capi_driver *driver = NULL; |
1096 | capicardparams cparams; | 1211 | capicardparams cparams; |
1097 | kcapi_carddef cdef; | 1212 | kcapi_carddef cdef; |
1098 | int retval; | ||
1099 | 1213 | ||
1100 | if ((retval = copy_from_user(&cdef, data, sizeof(cdef)))) | 1214 | if ((retval = copy_from_user(&cdef, data, sizeof(cdef)))) |
1101 | return retval; | 1215 | return retval; |
@@ -1107,6 +1221,8 @@ int capi20_manufacturer(unsigned int cmd, void __user *data) | |||
1107 | cparams.cardtype = 0; | 1221 | cparams.cardtype = 0; |
1108 | cdef.driver[sizeof(cdef.driver)-1] = 0; | 1222 | cdef.driver[sizeof(cdef.driver)-1] = 0; |
1109 | 1223 | ||
1224 | mutex_lock(&capi_drivers_lock); | ||
1225 | |||
1110 | list_for_each(l, &capi_drivers) { | 1226 | list_for_each(l, &capi_drivers) { |
1111 | driver = list_entry(l, struct capi_driver, list); | 1227 | driver = list_entry(l, struct capi_driver, list); |
1112 | if (strcmp(driver->name, cdef.driver) == 0) | 1228 | if (strcmp(driver->name, cdef.driver) == 0) |
@@ -1115,15 +1231,15 @@ int capi20_manufacturer(unsigned int cmd, void __user *data) | |||
1115 | if (driver == NULL) { | 1231 | if (driver == NULL) { |
1116 | printk(KERN_ERR "kcapi: driver \"%s\" not loaded.\n", | 1232 | printk(KERN_ERR "kcapi: driver \"%s\" not loaded.\n", |
1117 | cdef.driver); | 1233 | cdef.driver); |
1118 | return -ESRCH; | 1234 | retval = -ESRCH; |
1119 | } | 1235 | } else if (!driver->add_card) { |
1120 | |||
1121 | if (!driver->add_card) { | ||
1122 | printk(KERN_ERR "kcapi: driver \"%s\" has no add card function.\n", cdef.driver); | 1236 | printk(KERN_ERR "kcapi: driver \"%s\" has no add card function.\n", cdef.driver); |
1123 | return -EIO; | 1237 | retval = -EIO; |
1124 | } | 1238 | } else |
1239 | retval = driver->add_card(driver, &cparams); | ||
1125 | 1240 | ||
1126 | return driver->add_card(driver, &cparams); | 1241 | mutex_unlock(&capi_drivers_lock); |
1242 | return retval; | ||
1127 | } | 1243 | } |
1128 | 1244 | ||
1129 | default: | 1245 | default: |
@@ -1137,30 +1253,6 @@ int capi20_manufacturer(unsigned int cmd, void __user *data) | |||
1137 | 1253 | ||
1138 | EXPORT_SYMBOL(capi20_manufacturer); | 1254 | EXPORT_SYMBOL(capi20_manufacturer); |
1139 | 1255 | ||
1140 | /* temporary hack */ | ||
1141 | |||
1142 | /** | ||
1143 | * capi20_set_callback() - set CAPI application notification callback function | ||
1144 | * @ap: CAPI application descriptor structure. | ||
1145 | * @callback: callback function (NULL to remove). | ||
1146 | * | ||
1147 | * If not NULL, the callback function will be called to notify the | ||
1148 | * application of the addition or removal of a controller. | ||
1149 | * The first argument (cmd) will tell whether the controller was added | ||
1150 | * (KCI_CONTRUP) or removed (KCI_CONTRDOWN). | ||
1151 | * The second argument (contr) will be the controller number. | ||
1152 | * For cmd==KCI_CONTRUP the third argument (data) will be a pointer to the | ||
1153 | * new controller's capability profile structure. | ||
1154 | */ | ||
1155 | |||
1156 | void capi20_set_callback(struct capi20_appl *ap, | ||
1157 | void (*callback) (unsigned int cmd, __u32 contr, void *data)) | ||
1158 | { | ||
1159 | ap->callback = callback; | ||
1160 | } | ||
1161 | |||
1162 | EXPORT_SYMBOL(capi20_set_callback); | ||
1163 | |||
1164 | /* ------------------------------------------------------------- */ | 1256 | /* ------------------------------------------------------------- */ |
1165 | /* -------- Init & Cleanup ------------------------------------- */ | 1257 | /* -------- Init & Cleanup ------------------------------------- */ |
1166 | /* ------------------------------------------------------------- */ | 1258 | /* ------------------------------------------------------------- */ |
@@ -1169,27 +1261,21 @@ EXPORT_SYMBOL(capi20_set_callback); | |||
1169 | * init / exit functions | 1261 | * init / exit functions |
1170 | */ | 1262 | */ |
1171 | 1263 | ||
1264 | static struct notifier_block capictr_nb = { | ||
1265 | .notifier_call = notify_handler, | ||
1266 | .priority = INT_MAX, | ||
1267 | }; | ||
1268 | |||
1172 | static int __init kcapi_init(void) | 1269 | static int __init kcapi_init(void) |
1173 | { | 1270 | { |
1174 | char *p; | 1271 | int err; |
1175 | char rev[32]; | ||
1176 | int ret; | ||
1177 | |||
1178 | ret = cdebug_init(); | ||
1179 | if (ret) | ||
1180 | return ret; | ||
1181 | kcapi_proc_init(); | ||
1182 | |||
1183 | if ((p = strchr(revision, ':')) != NULL && p[1]) { | ||
1184 | strlcpy(rev, p + 2, sizeof(rev)); | ||
1185 | if ((p = strchr(rev, '$')) != NULL && p > rev) | ||
1186 | *(p-1) = 0; | ||
1187 | } else | ||
1188 | strcpy(rev, "1.0"); | ||
1189 | 1272 | ||
1190 | printk(KERN_NOTICE "CAPI Subsystem Rev %s\n", rev); | 1273 | register_capictr_notifier(&capictr_nb); |
1191 | 1274 | ||
1192 | return 0; | 1275 | err = cdebug_init(); |
1276 | if (!err) | ||
1277 | kcapi_proc_init(); | ||
1278 | return err; | ||
1193 | } | 1279 | } |
1194 | 1280 | ||
1195 | static void __exit kcapi_exit(void) | 1281 | static void __exit kcapi_exit(void) |
diff --git a/drivers/isdn/capi/kcapi.h b/drivers/isdn/capi/kcapi.h index 244711f7f838..f4620b38ec51 100644 --- a/drivers/isdn/capi/kcapi.h +++ b/drivers/isdn/capi/kcapi.h | |||
@@ -24,16 +24,19 @@ printk(KERN_DEBUG "%s: " format "\n" , __func__ , ## arg); \ | |||
24 | #endif | 24 | #endif |
25 | 25 | ||
26 | enum { | 26 | enum { |
27 | CARD_DETECTED = 1, | 27 | CAPI_CTR_DETACHED = 0, |
28 | CARD_LOADING = 2, | 28 | CAPI_CTR_DETECTED = 1, |
29 | CARD_RUNNING = 3, | 29 | CAPI_CTR_LOADING = 2, |
30 | CAPI_CTR_RUNNING = 3, | ||
30 | }; | 31 | }; |
31 | 32 | ||
32 | extern struct list_head capi_drivers; | 33 | extern struct list_head capi_drivers; |
33 | extern rwlock_t capi_drivers_list_lock; | 34 | extern struct mutex capi_drivers_lock; |
35 | |||
36 | extern struct capi_ctr *capi_controller[CAPI_MAXCONTR]; | ||
37 | extern struct mutex capi_controller_lock; | ||
34 | 38 | ||
35 | extern struct capi20_appl *capi_applications[CAPI_MAXAPPL]; | 39 | extern struct capi20_appl *capi_applications[CAPI_MAXAPPL]; |
36 | extern struct capi_ctr *capi_cards[CAPI_MAXCONTR]; | ||
37 | 40 | ||
38 | #ifdef CONFIG_PROC_FS | 41 | #ifdef CONFIG_PROC_FS |
39 | 42 | ||
diff --git a/drivers/isdn/capi/kcapi_proc.c b/drivers/isdn/capi/kcapi_proc.c index 09d4db764d22..ea2dff602e49 100644 --- a/drivers/isdn/capi/kcapi_proc.c +++ b/drivers/isdn/capi/kcapi_proc.c | |||
@@ -15,13 +15,12 @@ | |||
15 | #include <linux/seq_file.h> | 15 | #include <linux/seq_file.h> |
16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | 17 | ||
18 | static char * | 18 | static char *state2str(unsigned short state) |
19 | cardstate2str(unsigned short cardstate) | ||
20 | { | 19 | { |
21 | switch (cardstate) { | 20 | switch (state) { |
22 | case CARD_DETECTED: return "detected"; | 21 | case CAPI_CTR_DETECTED: return "detected"; |
23 | case CARD_LOADING: return "loading"; | 22 | case CAPI_CTR_LOADING: return "loading"; |
24 | case CARD_RUNNING: return "running"; | 23 | case CAPI_CTR_RUNNING: return "running"; |
25 | default: return "???"; | 24 | default: return "???"; |
26 | } | 25 | } |
27 | } | 26 | } |
@@ -36,9 +35,12 @@ cardstate2str(unsigned short cardstate) | |||
36 | // --------------------------------------------------------------------------- | 35 | // --------------------------------------------------------------------------- |
37 | 36 | ||
38 | static void *controller_start(struct seq_file *seq, loff_t *pos) | 37 | static void *controller_start(struct seq_file *seq, loff_t *pos) |
38 | __acquires(capi_controller_lock) | ||
39 | { | 39 | { |
40 | mutex_lock(&capi_controller_lock); | ||
41 | |||
40 | if (*pos < CAPI_MAXCONTR) | 42 | if (*pos < CAPI_MAXCONTR) |
41 | return &capi_cards[*pos]; | 43 | return &capi_controller[*pos]; |
42 | 44 | ||
43 | return NULL; | 45 | return NULL; |
44 | } | 46 | } |
@@ -47,13 +49,15 @@ static void *controller_next(struct seq_file *seq, void *v, loff_t *pos) | |||
47 | { | 49 | { |
48 | ++*pos; | 50 | ++*pos; |
49 | if (*pos < CAPI_MAXCONTR) | 51 | if (*pos < CAPI_MAXCONTR) |
50 | return &capi_cards[*pos]; | 52 | return &capi_controller[*pos]; |
51 | 53 | ||
52 | return NULL; | 54 | return NULL; |
53 | } | 55 | } |
54 | 56 | ||
55 | static void controller_stop(struct seq_file *seq, void *v) | 57 | static void controller_stop(struct seq_file *seq, void *v) |
58 | __releases(capi_controller_lock) | ||
56 | { | 59 | { |
60 | mutex_unlock(&capi_controller_lock); | ||
57 | } | 61 | } |
58 | 62 | ||
59 | static int controller_show(struct seq_file *seq, void *v) | 63 | static int controller_show(struct seq_file *seq, void *v) |
@@ -65,7 +69,7 @@ static int controller_show(struct seq_file *seq, void *v) | |||
65 | 69 | ||
66 | seq_printf(seq, "%d %-10s %-8s %-16s %s\n", | 70 | seq_printf(seq, "%d %-10s %-8s %-16s %s\n", |
67 | ctr->cnr, ctr->driver_name, | 71 | ctr->cnr, ctr->driver_name, |
68 | cardstate2str(ctr->cardstate), | 72 | state2str(ctr->state), |
69 | ctr->name, | 73 | ctr->name, |
70 | ctr->procinfo ? ctr->procinfo(ctr) : ""); | 74 | ctr->procinfo ? ctr->procinfo(ctr) : ""); |
71 | 75 | ||
@@ -135,9 +139,11 @@ static const struct file_operations proc_contrstats_ops = { | |||
135 | // applid nrecvctlpkt nrecvdatapkt nsentctlpkt nsentdatapkt | 139 | // applid nrecvctlpkt nrecvdatapkt nsentctlpkt nsentdatapkt |
136 | // --------------------------------------------------------------------------- | 140 | // --------------------------------------------------------------------------- |
137 | 141 | ||
138 | static void * | 142 | static void *applications_start(struct seq_file *seq, loff_t *pos) |
139 | applications_start(struct seq_file *seq, loff_t *pos) | 143 | __acquires(capi_controller_lock) |
140 | { | 144 | { |
145 | mutex_lock(&capi_controller_lock); | ||
146 | |||
141 | if (*pos < CAPI_MAXAPPL) | 147 | if (*pos < CAPI_MAXAPPL) |
142 | return &capi_applications[*pos]; | 148 | return &capi_applications[*pos]; |
143 | 149 | ||
@@ -154,9 +160,10 @@ applications_next(struct seq_file *seq, void *v, loff_t *pos) | |||
154 | return NULL; | 160 | return NULL; |
155 | } | 161 | } |
156 | 162 | ||
157 | static void | 163 | static void applications_stop(struct seq_file *seq, void *v) |
158 | applications_stop(struct seq_file *seq, void *v) | 164 | __releases(capi_controller_lock) |
159 | { | 165 | { |
166 | mutex_unlock(&capi_controller_lock); | ||
160 | } | 167 | } |
161 | 168 | ||
162 | static int | 169 | static int |
@@ -239,9 +246,9 @@ static const struct file_operations proc_applstats_ops = { | |||
239 | // --------------------------------------------------------------------------- | 246 | // --------------------------------------------------------------------------- |
240 | 247 | ||
241 | static void *capi_driver_start(struct seq_file *seq, loff_t *pos) | 248 | static void *capi_driver_start(struct seq_file *seq, loff_t *pos) |
242 | __acquires(&capi_drivers_list_lock) | 249 | __acquires(&capi_drivers_lock) |
243 | { | 250 | { |
244 | read_lock(&capi_drivers_list_lock); | 251 | mutex_lock(&capi_drivers_lock); |
245 | return seq_list_start(&capi_drivers, *pos); | 252 | return seq_list_start(&capi_drivers, *pos); |
246 | } | 253 | } |
247 | 254 | ||
@@ -251,9 +258,9 @@ static void *capi_driver_next(struct seq_file *seq, void *v, loff_t *pos) | |||
251 | } | 258 | } |
252 | 259 | ||
253 | static void capi_driver_stop(struct seq_file *seq, void *v) | 260 | static void capi_driver_stop(struct seq_file *seq, void *v) |
254 | __releases(&capi_drivers_list_lock) | 261 | __releases(&capi_drivers_lock) |
255 | { | 262 | { |
256 | read_unlock(&capi_drivers_list_lock); | 263 | mutex_unlock(&capi_drivers_lock); |
257 | } | 264 | } |
258 | 265 | ||
259 | static int capi_driver_show(struct seq_file *seq, void *v) | 266 | static int capi_driver_show(struct seq_file *seq, void *v) |
diff --git a/drivers/isdn/divert/divert_procfs.c b/drivers/isdn/divert/divert_procfs.c index 3697c409bec6..9f49d9065791 100644 --- a/drivers/isdn/divert/divert_procfs.c +++ b/drivers/isdn/divert/divert_procfs.c | |||
@@ -11,6 +11,7 @@ | |||
11 | 11 | ||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/poll.h> | 13 | #include <linux/poll.h> |
14 | #include <linux/slab.h> | ||
14 | #ifdef CONFIG_PROC_FS | 15 | #ifdef CONFIG_PROC_FS |
15 | #include <linux/proc_fs.h> | 16 | #include <linux/proc_fs.h> |
16 | #else | 17 | #else |
diff --git a/drivers/isdn/divert/isdn_divert.c b/drivers/isdn/divert/isdn_divert.c index 77e9fdda0597..70cf6bac7a5a 100644 --- a/drivers/isdn/divert/isdn_divert.c +++ b/drivers/isdn/divert/isdn_divert.c | |||
@@ -10,6 +10,7 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/proc_fs.h> | 12 | #include <linux/proc_fs.h> |
13 | #include <linux/slab.h> | ||
13 | #include <linux/timer.h> | 14 | #include <linux/timer.h> |
14 | #include <linux/jiffies.h> | 15 | #include <linux/jiffies.h> |
15 | 16 | ||
diff --git a/drivers/isdn/gigaset/Kconfig b/drivers/isdn/gigaset/Kconfig index 18ab8652aa57..dcefedc7044a 100644 --- a/drivers/isdn/gigaset/Kconfig +++ b/drivers/isdn/gigaset/Kconfig | |||
@@ -1,6 +1,5 @@ | |||
1 | menuconfig ISDN_DRV_GIGASET | 1 | menuconfig ISDN_DRV_GIGASET |
2 | tristate "Siemens Gigaset support" | 2 | tristate "Siemens Gigaset support" |
3 | depends on ISDN_I4L | ||
4 | select CRC_CCITT | 3 | select CRC_CCITT |
5 | select BITREVERSE | 4 | select BITREVERSE |
6 | help | 5 | help |
@@ -11,9 +10,33 @@ menuconfig ISDN_DRV_GIGASET | |||
11 | If you have one of these devices, say M here and for at least | 10 | If you have one of these devices, say M here and for at least |
12 | one of the connection specific parts that follow. | 11 | one of the connection specific parts that follow. |
13 | This will build a module called "gigaset". | 12 | This will build a module called "gigaset". |
13 | Note: If you build your ISDN subsystem (ISDN_CAPI or ISDN_I4L) | ||
14 | as a module, you have to build this driver as a module too, | ||
15 | otherwise the Gigaset device won't show up as an ISDN device. | ||
14 | 16 | ||
15 | if ISDN_DRV_GIGASET | 17 | if ISDN_DRV_GIGASET |
16 | 18 | ||
19 | config GIGASET_CAPI | ||
20 | bool "Gigaset CAPI support (EXPERIMENTAL)" | ||
21 | depends on EXPERIMENTAL | ||
22 | depends on ISDN_CAPI='y'||(ISDN_CAPI='m'&&ISDN_DRV_GIGASET='m') | ||
23 | default ISDN_I4L='n' | ||
24 | help | ||
25 | Build the Gigaset driver as a CAPI 2.0 driver interfacing with | ||
26 | the Kernel CAPI subsystem. To use it with the old ISDN4Linux | ||
27 | subsystem you'll have to enable the capidrv glue driver. | ||
28 | (select ISDN_CAPI_CAPIDRV.) | ||
29 | Say N to build the old native ISDN4Linux variant. | ||
30 | |||
31 | config GIGASET_I4L | ||
32 | bool | ||
33 | depends on ISDN_I4L='y'||(ISDN_I4L='m'&&ISDN_DRV_GIGASET='m') | ||
34 | default !GIGASET_CAPI | ||
35 | |||
36 | config GIGASET_DUMMYLL | ||
37 | bool | ||
38 | default !GIGASET_CAPI&&!GIGASET_I4L | ||
39 | |||
17 | config GIGASET_BASE | 40 | config GIGASET_BASE |
18 | tristate "Gigaset base station support" | 41 | tristate "Gigaset base station support" |
19 | depends on USB | 42 | depends on USB |
diff --git a/drivers/isdn/gigaset/Makefile b/drivers/isdn/gigaset/Makefile index e9d3189f56b7..c453b72272a0 100644 --- a/drivers/isdn/gigaset/Makefile +++ b/drivers/isdn/gigaset/Makefile | |||
@@ -1,4 +1,7 @@ | |||
1 | gigaset-y := common.o interface.o proc.o ev-layer.o i4l.o asyncdata.o | 1 | gigaset-y := common.o interface.o proc.o ev-layer.o asyncdata.o |
2 | gigaset-$(CONFIG_GIGASET_CAPI) += capi.o | ||
3 | gigaset-$(CONFIG_GIGASET_I4L) += i4l.o | ||
4 | gigaset-$(CONFIG_GIGASET_DUMMYLL) += dummyll.o | ||
2 | usb_gigaset-y := usb-gigaset.o | 5 | usb_gigaset-y := usb-gigaset.o |
3 | ser_gigaset-y := ser-gigaset.o | 6 | ser_gigaset-y := ser-gigaset.o |
4 | bas_gigaset-y := bas-gigaset.o isocdata.o | 7 | bas_gigaset-y := bas-gigaset.o isocdata.o |
diff --git a/drivers/isdn/gigaset/asyncdata.c b/drivers/isdn/gigaset/asyncdata.c index 44a58e6f8f65..c5016bd2d94f 100644 --- a/drivers/isdn/gigaset/asyncdata.c +++ b/drivers/isdn/gigaset/asyncdata.c | |||
@@ -19,7 +19,7 @@ | |||
19 | 19 | ||
20 | /* check if byte must be stuffed/escaped | 20 | /* check if byte must be stuffed/escaped |
21 | * I'm not sure which data should be encoded. | 21 | * I'm not sure which data should be encoded. |
22 | * Therefore I will go the hard way and decode every value | 22 | * Therefore I will go the hard way and encode every value |
23 | * less than 0x20, the flag sequence and the control escape char. | 23 | * less than 0x20, the flag sequence and the control escape char. |
24 | */ | 24 | */ |
25 | static inline int muststuff(unsigned char c) | 25 | static inline int muststuff(unsigned char c) |
@@ -35,303 +35,385 @@ static inline int muststuff(unsigned char c) | |||
35 | 35 | ||
36 | /* == data input =========================================================== */ | 36 | /* == data input =========================================================== */ |
37 | 37 | ||
38 | /* process a block of received bytes in command mode (modem response) | 38 | /* process a block of received bytes in command mode |
39 | * (mstate != MS_LOCKED && (inputstate & INS_command)) | ||
40 | * Append received bytes to the command response buffer and forward them | ||
41 | * line by line to the response handler. Exit whenever a mode/state change | ||
42 | * might have occurred. | ||
43 | * Note: Received lines may be terminated by CR, LF, or CR LF, which will be | ||
44 | * removed before passing the line to the response handler. | ||
39 | * Return value: | 45 | * Return value: |
40 | * number of processed bytes | 46 | * number of processed bytes |
41 | */ | 47 | */ |
42 | static inline int cmd_loop(unsigned char c, unsigned char *src, int numbytes, | 48 | static unsigned cmd_loop(unsigned numbytes, struct inbuf_t *inbuf) |
43 | struct inbuf_t *inbuf) | ||
44 | { | 49 | { |
50 | unsigned char *src = inbuf->data + inbuf->head; | ||
45 | struct cardstate *cs = inbuf->cs; | 51 | struct cardstate *cs = inbuf->cs; |
46 | unsigned cbytes = cs->cbytes; | 52 | unsigned cbytes = cs->cbytes; |
47 | int inputstate = inbuf->inputstate; | 53 | unsigned procbytes = 0; |
48 | int startbytes = numbytes; | 54 | unsigned char c; |
49 | |||
50 | for (;;) { | ||
51 | cs->respdata[cbytes] = c; | ||
52 | if (c == 10 || c == 13) { | ||
53 | gig_dbg(DEBUG_TRANSCMD, "%s: End of Command (%d Bytes)", | ||
54 | __func__, cbytes); | ||
55 | cs->cbytes = cbytes; | ||
56 | gigaset_handle_modem_response(cs); /* can change | ||
57 | cs->dle */ | ||
58 | cbytes = 0; | ||
59 | 55 | ||
60 | if (cs->dle && | 56 | while (procbytes < numbytes) { |
61 | !(inputstate & INS_DLE_command)) { | 57 | c = *src++; |
62 | inputstate &= ~INS_command; | 58 | procbytes++; |
59 | |||
60 | switch (c) { | ||
61 | case '\n': | ||
62 | if (cbytes == 0 && cs->respdata[0] == '\r') { | ||
63 | /* collapse LF with preceding CR */ | ||
64 | cs->respdata[0] = 0; | ||
63 | break; | 65 | break; |
64 | } | 66 | } |
65 | } else { | 67 | /* --v-- fall through --v-- */ |
66 | /* advance in line buffer, checking for overflow */ | 68 | case '\r': |
67 | if (cbytes < MAX_RESP_SIZE - 1) | 69 | /* end of message line, pass to response handler */ |
68 | cbytes++; | 70 | if (cbytes >= MAX_RESP_SIZE) { |
69 | else | 71 | dev_warn(cs->dev, "response too large (%d)\n", |
70 | dev_warn(cs->dev, "response too large\n"); | 72 | cbytes); |
71 | } | 73 | cbytes = MAX_RESP_SIZE; |
74 | } | ||
75 | cs->cbytes = cbytes; | ||
76 | gigaset_dbg_buffer(DEBUG_TRANSCMD, "received response", | ||
77 | cbytes, cs->respdata); | ||
78 | gigaset_handle_modem_response(cs); | ||
79 | cbytes = 0; | ||
72 | 80 | ||
73 | if (!numbytes) | 81 | /* store EOL byte for CRLF collapsing */ |
74 | break; | 82 | cs->respdata[0] = c; |
75 | c = *src++; | 83 | |
76 | --numbytes; | 84 | /* cs->dle may have changed */ |
77 | if (c == DLE_FLAG && | 85 | if (cs->dle && !(inbuf->inputstate & INS_DLE_command)) |
78 | (cs->dle || inputstate & INS_DLE_command)) { | 86 | inbuf->inputstate &= ~INS_command; |
79 | inputstate |= INS_DLE_char; | 87 | |
80 | break; | 88 | /* return for reevaluating state */ |
89 | goto exit; | ||
90 | |||
91 | case DLE_FLAG: | ||
92 | if (inbuf->inputstate & INS_DLE_char) { | ||
93 | /* quoted DLE: clear quote flag */ | ||
94 | inbuf->inputstate &= ~INS_DLE_char; | ||
95 | } else if (cs->dle || | ||
96 | (inbuf->inputstate & INS_DLE_command)) { | ||
97 | /* DLE escape, pass up for handling */ | ||
98 | inbuf->inputstate |= INS_DLE_char; | ||
99 | goto exit; | ||
100 | } | ||
101 | /* quoted or not in DLE mode: treat as regular data */ | ||
102 | /* --v-- fall through --v-- */ | ||
103 | default: | ||
104 | /* append to line buffer if possible */ | ||
105 | if (cbytes < MAX_RESP_SIZE) | ||
106 | cs->respdata[cbytes] = c; | ||
107 | cbytes++; | ||
81 | } | 108 | } |
82 | } | 109 | } |
83 | 110 | exit: | |
84 | cs->cbytes = cbytes; | 111 | cs->cbytes = cbytes; |
85 | inbuf->inputstate = inputstate; | 112 | return procbytes; |
86 | |||
87 | return startbytes - numbytes; | ||
88 | } | 113 | } |
89 | 114 | ||
90 | /* process a block of received bytes in lock mode (tty i/f) | 115 | /* process a block of received bytes in lock mode |
116 | * All received bytes are passed unmodified to the tty i/f. | ||
91 | * Return value: | 117 | * Return value: |
92 | * number of processed bytes | 118 | * number of processed bytes |
93 | */ | 119 | */ |
94 | static inline int lock_loop(unsigned char *src, int numbytes, | 120 | static unsigned lock_loop(unsigned numbytes, struct inbuf_t *inbuf) |
95 | struct inbuf_t *inbuf) | ||
96 | { | 121 | { |
97 | struct cardstate *cs = inbuf->cs; | 122 | unsigned char *src = inbuf->data + inbuf->head; |
98 | |||
99 | gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response", | ||
100 | numbytes, src); | ||
101 | gigaset_if_receive(cs, src, numbytes); | ||
102 | 123 | ||
124 | gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response", numbytes, src); | ||
125 | gigaset_if_receive(inbuf->cs, src, numbytes); | ||
103 | return numbytes; | 126 | return numbytes; |
104 | } | 127 | } |
105 | 128 | ||
129 | /* set up next receive skb for data mode | ||
130 | */ | ||
131 | static void new_rcv_skb(struct bc_state *bcs) | ||
132 | { | ||
133 | struct cardstate *cs = bcs->cs; | ||
134 | unsigned short hw_hdr_len = cs->hw_hdr_len; | ||
135 | |||
136 | if (bcs->ignore) { | ||
137 | bcs->skb = NULL; | ||
138 | return; | ||
139 | } | ||
140 | |||
141 | bcs->skb = dev_alloc_skb(SBUFSIZE + hw_hdr_len); | ||
142 | if (bcs->skb == NULL) { | ||
143 | dev_warn(cs->dev, "could not allocate new skb\n"); | ||
144 | return; | ||
145 | } | ||
146 | skb_reserve(bcs->skb, hw_hdr_len); | ||
147 | } | ||
148 | |||
106 | /* process a block of received bytes in HDLC data mode | 149 | /* process a block of received bytes in HDLC data mode |
150 | * (mstate != MS_LOCKED && !(inputstate & INS_command) && proto2 == L2_HDLC) | ||
107 | * Collect HDLC frames, undoing byte stuffing and watching for DLE escapes. | 151 | * Collect HDLC frames, undoing byte stuffing and watching for DLE escapes. |
108 | * When a frame is complete, check the FCS and pass valid frames to the LL. | 152 | * When a frame is complete, check the FCS and pass valid frames to the LL. |
109 | * If DLE is encountered, return immediately to let the caller handle it. | 153 | * If DLE is encountered, return immediately to let the caller handle it. |
110 | * Return value: | 154 | * Return value: |
111 | * number of processed bytes | 155 | * number of processed bytes |
112 | * numbytes (all bytes processed) on error --FIXME | ||
113 | */ | 156 | */ |
114 | static inline int hdlc_loop(unsigned char c, unsigned char *src, int numbytes, | 157 | static unsigned hdlc_loop(unsigned numbytes, struct inbuf_t *inbuf) |
115 | struct inbuf_t *inbuf) | ||
116 | { | 158 | { |
117 | struct cardstate *cs = inbuf->cs; | 159 | struct cardstate *cs = inbuf->cs; |
118 | struct bc_state *bcs = inbuf->bcs; | 160 | struct bc_state *bcs = cs->bcs; |
119 | int inputstate = bcs->inputstate; | 161 | int inputstate = bcs->inputstate; |
120 | __u16 fcs = bcs->fcs; | 162 | __u16 fcs = bcs->fcs; |
121 | struct sk_buff *skb = bcs->skb; | 163 | struct sk_buff *skb = bcs->skb; |
122 | unsigned char error; | 164 | unsigned char *src = inbuf->data + inbuf->head; |
123 | struct sk_buff *compskb; | 165 | unsigned procbytes = 0; |
124 | int startbytes = numbytes; | 166 | unsigned char c; |
125 | int l; | ||
126 | 167 | ||
127 | if (unlikely(inputstate & INS_byte_stuff)) { | 168 | if (inputstate & INS_byte_stuff) { |
169 | if (!numbytes) | ||
170 | return 0; | ||
128 | inputstate &= ~INS_byte_stuff; | 171 | inputstate &= ~INS_byte_stuff; |
129 | goto byte_stuff; | 172 | goto byte_stuff; |
130 | } | 173 | } |
131 | for (;;) { | 174 | |
132 | if (unlikely(c == PPP_ESCAPE)) { | 175 | while (procbytes < numbytes) { |
133 | if (unlikely(!numbytes)) { | 176 | c = *src++; |
134 | inputstate |= INS_byte_stuff; | 177 | procbytes++; |
178 | if (c == DLE_FLAG) { | ||
179 | if (inputstate & INS_DLE_char) { | ||
180 | /* quoted DLE: clear quote flag */ | ||
181 | inputstate &= ~INS_DLE_char; | ||
182 | } else if (cs->dle || (inputstate & INS_DLE_command)) { | ||
183 | /* DLE escape, pass up for handling */ | ||
184 | inputstate |= INS_DLE_char; | ||
135 | break; | 185 | break; |
136 | } | 186 | } |
137 | c = *src++; | 187 | } |
138 | --numbytes; | 188 | |
139 | if (unlikely(c == DLE_FLAG && | 189 | if (c == PPP_ESCAPE) { |
140 | (cs->dle || | 190 | /* byte stuffing indicator: pull in next byte */ |
141 | inbuf->inputstate & INS_DLE_command))) { | 191 | if (procbytes >= numbytes) { |
142 | inbuf->inputstate |= INS_DLE_char; | 192 | /* end of buffer, save for later processing */ |
143 | inputstate |= INS_byte_stuff; | 193 | inputstate |= INS_byte_stuff; |
144 | break; | 194 | break; |
145 | } | 195 | } |
146 | byte_stuff: | 196 | byte_stuff: |
197 | c = *src++; | ||
198 | procbytes++; | ||
199 | if (c == DLE_FLAG) { | ||
200 | if (inputstate & INS_DLE_char) { | ||
201 | /* quoted DLE: clear quote flag */ | ||
202 | inputstate &= ~INS_DLE_char; | ||
203 | } else if (cs->dle || | ||
204 | (inputstate & INS_DLE_command)) { | ||
205 | /* DLE escape, pass up for handling */ | ||
206 | inputstate |= | ||
207 | INS_DLE_char | INS_byte_stuff; | ||
208 | break; | ||
209 | } | ||
210 | } | ||
147 | c ^= PPP_TRANS; | 211 | c ^= PPP_TRANS; |
148 | if (unlikely(!muststuff(c))) | ||
149 | gig_dbg(DEBUG_HDLC, "byte stuffed: 0x%02x", c); | ||
150 | } else if (unlikely(c == PPP_FLAG)) { | ||
151 | if (unlikely(inputstate & INS_skip_frame)) { | ||
152 | #ifdef CONFIG_GIGASET_DEBUG | ||
153 | if (!(inputstate & INS_have_data)) { /* 7E 7E */ | ||
154 | ++bcs->emptycount; | ||
155 | } else | ||
156 | gig_dbg(DEBUG_HDLC, | ||
157 | "7e----------------------------"); | ||
158 | #endif | ||
159 | |||
160 | /* end of frame */ | ||
161 | error = 1; | ||
162 | gigaset_rcv_error(NULL, cs, bcs); | ||
163 | } else if (!(inputstate & INS_have_data)) { /* 7E 7E */ | ||
164 | #ifdef CONFIG_GIGASET_DEBUG | 212 | #ifdef CONFIG_GIGASET_DEBUG |
165 | ++bcs->emptycount; | 213 | if (!muststuff(c)) |
214 | gig_dbg(DEBUG_HDLC, "byte stuffed: 0x%02x", c); | ||
166 | #endif | 215 | #endif |
167 | break; | 216 | } else if (c == PPP_FLAG) { |
168 | } else { | 217 | /* end of frame: process content if any */ |
218 | if (inputstate & INS_have_data) { | ||
169 | gig_dbg(DEBUG_HDLC, | 219 | gig_dbg(DEBUG_HDLC, |
170 | "7e----------------------------"); | 220 | "7e----------------------------"); |
171 | 221 | ||
172 | /* end of frame */ | 222 | /* check and pass received frame */ |
173 | error = 0; | 223 | if (!skb) { |
174 | 224 | /* skipped frame */ | |
175 | if (unlikely(fcs != PPP_GOODFCS)) { | 225 | gigaset_isdn_rcv_err(bcs); |
226 | } else if (skb->len < 2) { | ||
227 | /* frame too short for FCS */ | ||
228 | dev_warn(cs->dev, | ||
229 | "short frame (%d)\n", | ||
230 | skb->len); | ||
231 | gigaset_isdn_rcv_err(bcs); | ||
232 | dev_kfree_skb_any(skb); | ||
233 | } else if (fcs != PPP_GOODFCS) { | ||
234 | /* frame check error */ | ||
176 | dev_err(cs->dev, | 235 | dev_err(cs->dev, |
177 | "Checksum failed, %u bytes corrupted!\n", | 236 | "Checksum failed, %u bytes corrupted!\n", |
178 | skb->len); | 237 | skb->len); |
179 | compskb = NULL; | 238 | gigaset_isdn_rcv_err(bcs); |
180 | gigaset_rcv_error(compskb, cs, bcs); | 239 | dev_kfree_skb_any(skb); |
181 | error = 1; | ||
182 | } else { | 240 | } else { |
183 | if (likely((l = skb->len) > 2)) { | 241 | /* good frame */ |
184 | skb->tail -= 2; | 242 | __skb_trim(skb, skb->len - 2); |
185 | skb->len -= 2; | 243 | gigaset_skb_rcvd(bcs, skb); |
186 | } else { | ||
187 | dev_kfree_skb(skb); | ||
188 | skb = NULL; | ||
189 | inputstate |= INS_skip_frame; | ||
190 | if (l == 1) { | ||
191 | dev_err(cs->dev, | ||
192 | "invalid packet size (1)!\n"); | ||
193 | error = 1; | ||
194 | gigaset_rcv_error(NULL, | ||
195 | cs, bcs); | ||
196 | } | ||
197 | } | ||
198 | if (likely(!(error || | ||
199 | (inputstate & | ||
200 | INS_skip_frame)))) { | ||
201 | gigaset_rcv_skb(skb, cs, bcs); | ||
202 | } | ||
203 | } | 244 | } |
204 | } | ||
205 | 245 | ||
206 | if (unlikely(error)) | 246 | /* prepare reception of next frame */ |
207 | if (skb) | 247 | inputstate &= ~INS_have_data; |
208 | dev_kfree_skb(skb); | 248 | new_rcv_skb(bcs); |
209 | 249 | skb = bcs->skb; | |
210 | fcs = PPP_INITFCS; | ||
211 | inputstate &= ~(INS_have_data | INS_skip_frame); | ||
212 | if (unlikely(bcs->ignore)) { | ||
213 | inputstate |= INS_skip_frame; | ||
214 | skb = NULL; | ||
215 | } else if (likely((skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)) { | ||
216 | skb_reserve(skb, HW_HDR_LEN); | ||
217 | } else { | 250 | } else { |
218 | dev_warn(cs->dev, | 251 | /* empty frame (7E 7E) */ |
219 | "could not allocate new skb\n"); | 252 | #ifdef CONFIG_GIGASET_DEBUG |
220 | inputstate |= INS_skip_frame; | 253 | ++bcs->emptycount; |
254 | #endif | ||
255 | if (!skb) { | ||
256 | /* skipped (?) */ | ||
257 | gigaset_isdn_rcv_err(bcs); | ||
258 | new_rcv_skb(bcs); | ||
259 | skb = bcs->skb; | ||
260 | } | ||
221 | } | 261 | } |
222 | 262 | ||
223 | break; | 263 | fcs = PPP_INITFCS; |
224 | } else if (unlikely(muststuff(c))) { | 264 | continue; |
265 | #ifdef CONFIG_GIGASET_DEBUG | ||
266 | } else if (muststuff(c)) { | ||
225 | /* Should not happen. Possible after ZDLE=1<CR><LF>. */ | 267 | /* Should not happen. Possible after ZDLE=1<CR><LF>. */ |
226 | gig_dbg(DEBUG_HDLC, "not byte stuffed: 0x%02x", c); | 268 | gig_dbg(DEBUG_HDLC, "not byte stuffed: 0x%02x", c); |
269 | #endif | ||
227 | } | 270 | } |
228 | 271 | ||
229 | /* add character */ | 272 | /* regular data byte, append to skb */ |
230 | |||
231 | #ifdef CONFIG_GIGASET_DEBUG | 273 | #ifdef CONFIG_GIGASET_DEBUG |
232 | if (unlikely(!(inputstate & INS_have_data))) { | 274 | if (!(inputstate & INS_have_data)) { |
233 | gig_dbg(DEBUG_HDLC, "7e (%d x) ================", | 275 | gig_dbg(DEBUG_HDLC, "7e (%d x) ================", |
234 | bcs->emptycount); | 276 | bcs->emptycount); |
235 | bcs->emptycount = 0; | 277 | bcs->emptycount = 0; |
236 | } | 278 | } |
237 | #endif | 279 | #endif |
238 | |||
239 | inputstate |= INS_have_data; | 280 | inputstate |= INS_have_data; |
240 | 281 | if (skb) { | |
241 | if (likely(!(inputstate & INS_skip_frame))) { | 282 | if (skb->len == SBUFSIZE) { |
242 | if (unlikely(skb->len == SBUFSIZE)) { | ||
243 | dev_warn(cs->dev, "received packet too long\n"); | 283 | dev_warn(cs->dev, "received packet too long\n"); |
244 | dev_kfree_skb_any(skb); | 284 | dev_kfree_skb_any(skb); |
245 | skb = NULL; | 285 | /* skip remainder of packet */ |
246 | inputstate |= INS_skip_frame; | 286 | bcs->skb = skb = NULL; |
247 | break; | 287 | } else { |
288 | *__skb_put(skb, 1) = c; | ||
289 | fcs = crc_ccitt_byte(fcs, c); | ||
248 | } | 290 | } |
249 | *__skb_put(skb, 1) = c; | ||
250 | fcs = crc_ccitt_byte(fcs, c); | ||
251 | } | ||
252 | |||
253 | if (unlikely(!numbytes)) | ||
254 | break; | ||
255 | c = *src++; | ||
256 | --numbytes; | ||
257 | if (unlikely(c == DLE_FLAG && | ||
258 | (cs->dle || | ||
259 | inbuf->inputstate & INS_DLE_command))) { | ||
260 | inbuf->inputstate |= INS_DLE_char; | ||
261 | break; | ||
262 | } | 291 | } |
263 | } | 292 | } |
293 | |||
264 | bcs->inputstate = inputstate; | 294 | bcs->inputstate = inputstate; |
265 | bcs->fcs = fcs; | 295 | bcs->fcs = fcs; |
266 | bcs->skb = skb; | 296 | return procbytes; |
267 | return startbytes - numbytes; | ||
268 | } | 297 | } |
269 | 298 | ||
270 | /* process a block of received bytes in transparent data mode | 299 | /* process a block of received bytes in transparent data mode |
300 | * (mstate != MS_LOCKED && !(inputstate & INS_command) && proto2 != L2_HDLC) | ||
271 | * Invert bytes, undoing byte stuffing and watching for DLE escapes. | 301 | * Invert bytes, undoing byte stuffing and watching for DLE escapes. |
272 | * If DLE is encountered, return immediately to let the caller handle it. | 302 | * If DLE is encountered, return immediately to let the caller handle it. |
273 | * Return value: | 303 | * Return value: |
274 | * number of processed bytes | 304 | * number of processed bytes |
275 | * numbytes (all bytes processed) on error --FIXME | ||
276 | */ | 305 | */ |
277 | static inline int iraw_loop(unsigned char c, unsigned char *src, int numbytes, | 306 | static unsigned iraw_loop(unsigned numbytes, struct inbuf_t *inbuf) |
278 | struct inbuf_t *inbuf) | ||
279 | { | 307 | { |
280 | struct cardstate *cs = inbuf->cs; | 308 | struct cardstate *cs = inbuf->cs; |
281 | struct bc_state *bcs = inbuf->bcs; | 309 | struct bc_state *bcs = cs->bcs; |
282 | int inputstate = bcs->inputstate; | 310 | int inputstate = bcs->inputstate; |
283 | struct sk_buff *skb = bcs->skb; | 311 | struct sk_buff *skb = bcs->skb; |
284 | int startbytes = numbytes; | 312 | unsigned char *src = inbuf->data + inbuf->head; |
313 | unsigned procbytes = 0; | ||
314 | unsigned char c; | ||
285 | 315 | ||
286 | for (;;) { | 316 | if (!skb) { |
287 | /* add character */ | 317 | /* skip this block */ |
288 | inputstate |= INS_have_data; | 318 | new_rcv_skb(bcs); |
319 | return numbytes; | ||
320 | } | ||
289 | 321 | ||
290 | if (likely(!(inputstate & INS_skip_frame))) { | 322 | while (procbytes < numbytes && skb->len < SBUFSIZE) { |
291 | if (unlikely(skb->len == SBUFSIZE)) { | 323 | c = *src++; |
292 | //FIXME just pass skb up and allocate a new one | 324 | procbytes++; |
293 | dev_warn(cs->dev, "received packet too long\n"); | 325 | |
294 | dev_kfree_skb_any(skb); | 326 | if (c == DLE_FLAG) { |
295 | skb = NULL; | 327 | if (inputstate & INS_DLE_char) { |
296 | inputstate |= INS_skip_frame; | 328 | /* quoted DLE: clear quote flag */ |
329 | inputstate &= ~INS_DLE_char; | ||
330 | } else if (cs->dle || (inputstate & INS_DLE_command)) { | ||
331 | /* DLE escape, pass up for handling */ | ||
332 | inputstate |= INS_DLE_char; | ||
297 | break; | 333 | break; |
298 | } | 334 | } |
299 | *__skb_put(skb, 1) = bitrev8(c); | ||
300 | } | 335 | } |
301 | 336 | ||
302 | if (unlikely(!numbytes)) | 337 | /* regular data byte: append to current skb */ |
303 | break; | 338 | inputstate |= INS_have_data; |
304 | c = *src++; | 339 | *__skb_put(skb, 1) = bitrev8(c); |
305 | --numbytes; | ||
306 | if (unlikely(c == DLE_FLAG && | ||
307 | (cs->dle || | ||
308 | inbuf->inputstate & INS_DLE_command))) { | ||
309 | inbuf->inputstate |= INS_DLE_char; | ||
310 | break; | ||
311 | } | ||
312 | } | 340 | } |
313 | 341 | ||
314 | /* pass data up */ | 342 | /* pass data up */ |
315 | if (likely(inputstate & INS_have_data)) { | 343 | if (inputstate & INS_have_data) { |
316 | if (likely(!(inputstate & INS_skip_frame))) { | 344 | gigaset_skb_rcvd(bcs, skb); |
317 | gigaset_rcv_skb(skb, cs, bcs); | 345 | inputstate &= ~INS_have_data; |
318 | } | 346 | new_rcv_skb(bcs); |
319 | inputstate &= ~(INS_have_data | INS_skip_frame); | 347 | } |
320 | if (unlikely(bcs->ignore)) { | 348 | |
321 | inputstate |= INS_skip_frame; | 349 | bcs->inputstate = inputstate; |
322 | skb = NULL; | 350 | return procbytes; |
323 | } else if (likely((skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) | 351 | } |
324 | != NULL)) { | 352 | |
325 | skb_reserve(skb, HW_HDR_LEN); | 353 | /* process DLE escapes |
354 | * Called whenever a DLE sequence might be encountered in the input stream. | ||
355 | * Either processes the entire DLE sequence or, if that isn't possible, | ||
356 | * notes the fact that an initial DLE has been received in the INS_DLE_char | ||
357 | * inputstate flag and resumes processing of the sequence on the next call. | ||
358 | */ | ||
359 | static void handle_dle(struct inbuf_t *inbuf) | ||
360 | { | ||
361 | struct cardstate *cs = inbuf->cs; | ||
362 | |||
363 | if (cs->mstate == MS_LOCKED) | ||
364 | return; /* no DLE processing in lock mode */ | ||
365 | |||
366 | if (!(inbuf->inputstate & INS_DLE_char)) { | ||
367 | /* no DLE pending */ | ||
368 | if (inbuf->data[inbuf->head] == DLE_FLAG && | ||
369 | (cs->dle || inbuf->inputstate & INS_DLE_command)) { | ||
370 | /* start of DLE sequence */ | ||
371 | inbuf->head++; | ||
372 | if (inbuf->head == inbuf->tail || | ||
373 | inbuf->head == RBUFSIZE) { | ||
374 | /* end of buffer, save for later processing */ | ||
375 | inbuf->inputstate |= INS_DLE_char; | ||
376 | return; | ||
377 | } | ||
326 | } else { | 378 | } else { |
327 | dev_warn(cs->dev, "could not allocate new skb\n"); | 379 | /* regular data byte */ |
328 | inputstate |= INS_skip_frame; | 380 | return; |
329 | } | 381 | } |
330 | } | 382 | } |
331 | 383 | ||
332 | bcs->inputstate = inputstate; | 384 | /* consume pending DLE */ |
333 | bcs->skb = skb; | 385 | inbuf->inputstate &= ~INS_DLE_char; |
334 | return startbytes - numbytes; | 386 | |
387 | switch (inbuf->data[inbuf->head]) { | ||
388 | case 'X': /* begin of event message */ | ||
389 | if (inbuf->inputstate & INS_command) | ||
390 | dev_notice(cs->dev, | ||
391 | "received <DLE>X in command mode\n"); | ||
392 | inbuf->inputstate |= INS_command | INS_DLE_command; | ||
393 | inbuf->head++; /* byte consumed */ | ||
394 | break; | ||
395 | case '.': /* end of event message */ | ||
396 | if (!(inbuf->inputstate & INS_DLE_command)) | ||
397 | dev_notice(cs->dev, | ||
398 | "received <DLE>. without <DLE>X\n"); | ||
399 | inbuf->inputstate &= ~INS_DLE_command; | ||
400 | /* return to data mode if in DLE mode */ | ||
401 | if (cs->dle) | ||
402 | inbuf->inputstate &= ~INS_command; | ||
403 | inbuf->head++; /* byte consumed */ | ||
404 | break; | ||
405 | case DLE_FLAG: /* DLE in data stream */ | ||
406 | /* mark as quoted */ | ||
407 | inbuf->inputstate |= INS_DLE_char; | ||
408 | if (!(cs->dle || inbuf->inputstate & INS_DLE_command)) | ||
409 | dev_notice(cs->dev, | ||
410 | "received <DLE><DLE> not in DLE mode\n"); | ||
411 | break; /* quoted byte left in buffer */ | ||
412 | default: | ||
413 | dev_notice(cs->dev, "received <DLE><%02x>\n", | ||
414 | inbuf->data[inbuf->head]); | ||
415 | /* quoted byte left in buffer */ | ||
416 | } | ||
335 | } | 417 | } |
336 | 418 | ||
337 | /** | 419 | /** |
@@ -345,94 +427,39 @@ static inline int iraw_loop(unsigned char c, unsigned char *src, int numbytes, | |||
345 | */ | 427 | */ |
346 | void gigaset_m10x_input(struct inbuf_t *inbuf) | 428 | void gigaset_m10x_input(struct inbuf_t *inbuf) |
347 | { | 429 | { |
348 | struct cardstate *cs; | 430 | struct cardstate *cs = inbuf->cs; |
349 | unsigned tail, head, numbytes; | 431 | unsigned numbytes, procbytes; |
350 | unsigned char *src, c; | ||
351 | int procbytes; | ||
352 | |||
353 | head = inbuf->head; | ||
354 | tail = inbuf->tail; | ||
355 | gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail); | ||
356 | |||
357 | if (head != tail) { | ||
358 | cs = inbuf->cs; | ||
359 | src = inbuf->data + head; | ||
360 | numbytes = (head > tail ? RBUFSIZE : tail) - head; | ||
361 | gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes); | ||
362 | 432 | ||
363 | while (numbytes) { | 433 | gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", inbuf->head, inbuf->tail); |
364 | if (cs->mstate == MS_LOCKED) { | ||
365 | procbytes = lock_loop(src, numbytes, inbuf); | ||
366 | src += procbytes; | ||
367 | numbytes -= procbytes; | ||
368 | } else { | ||
369 | c = *src++; | ||
370 | --numbytes; | ||
371 | if (c == DLE_FLAG && (cs->dle || | ||
372 | inbuf->inputstate & INS_DLE_command)) { | ||
373 | if (!(inbuf->inputstate & INS_DLE_char)) { | ||
374 | inbuf->inputstate |= INS_DLE_char; | ||
375 | goto nextbyte; | ||
376 | } | ||
377 | /* <DLE> <DLE> => <DLE> in data stream */ | ||
378 | inbuf->inputstate &= ~INS_DLE_char; | ||
379 | } | ||
380 | 434 | ||
381 | if (!(inbuf->inputstate & INS_DLE_char)) { | 435 | while (inbuf->head != inbuf->tail) { |
382 | 436 | /* check for DLE escape */ | |
383 | /* FIXME use function pointers? */ | 437 | handle_dle(inbuf); |
384 | if (inbuf->inputstate & INS_command) | ||
385 | procbytes = cmd_loop(c, src, numbytes, inbuf); | ||
386 | else if (inbuf->bcs->proto2 == ISDN_PROTO_L2_HDLC) | ||
387 | procbytes = hdlc_loop(c, src, numbytes, inbuf); | ||
388 | else | ||
389 | procbytes = iraw_loop(c, src, numbytes, inbuf); | ||
390 | |||
391 | src += procbytes; | ||
392 | numbytes -= procbytes; | ||
393 | } else { /* DLE char */ | ||
394 | inbuf->inputstate &= ~INS_DLE_char; | ||
395 | switch (c) { | ||
396 | case 'X': /*begin of command*/ | ||
397 | if (inbuf->inputstate & INS_command) | ||
398 | dev_warn(cs->dev, | ||
399 | "received <DLE> 'X' in command mode\n"); | ||
400 | inbuf->inputstate |= | ||
401 | INS_command | INS_DLE_command; | ||
402 | break; | ||
403 | case '.': /*end of command*/ | ||
404 | if (!(inbuf->inputstate & INS_command)) | ||
405 | dev_warn(cs->dev, | ||
406 | "received <DLE> '.' in hdlc mode\n"); | ||
407 | inbuf->inputstate &= cs->dle ? | ||
408 | ~(INS_DLE_command|INS_command) | ||
409 | : ~INS_DLE_command; | ||
410 | break; | ||
411 | //case DLE_FLAG: /*DLE_FLAG in data stream*/ /* schon oben behandelt! */ | ||
412 | default: | ||
413 | dev_err(cs->dev, | ||
414 | "received 0x10 0x%02x!\n", | ||
415 | (int) c); | ||
416 | /* FIXME: reset driver?? */ | ||
417 | } | ||
418 | } | ||
419 | } | ||
420 | nextbyte: | ||
421 | if (!numbytes) { | ||
422 | /* end of buffer, check for wrap */ | ||
423 | if (head > tail) { | ||
424 | head = 0; | ||
425 | src = inbuf->data; | ||
426 | numbytes = tail; | ||
427 | } else { | ||
428 | head = tail; | ||
429 | break; | ||
430 | } | ||
431 | } | ||
432 | } | ||
433 | 438 | ||
434 | gig_dbg(DEBUG_INTR, "setting head to %u", head); | 439 | /* process a contiguous block of bytes */ |
435 | inbuf->head = head; | 440 | numbytes = (inbuf->head > inbuf->tail ? |
441 | RBUFSIZE : inbuf->tail) - inbuf->head; | ||
442 | gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes); | ||
443 | /* | ||
444 | * numbytes may be 0 if handle_dle() ate the last byte. | ||
445 | * This does no harm, *_loop() will just return 0 immediately. | ||
446 | */ | ||
447 | |||
448 | if (cs->mstate == MS_LOCKED) | ||
449 | procbytes = lock_loop(numbytes, inbuf); | ||
450 | else if (inbuf->inputstate & INS_command) | ||
451 | procbytes = cmd_loop(numbytes, inbuf); | ||
452 | else if (cs->bcs->proto2 == L2_HDLC) | ||
453 | procbytes = hdlc_loop(numbytes, inbuf); | ||
454 | else | ||
455 | procbytes = iraw_loop(numbytes, inbuf); | ||
456 | inbuf->head += procbytes; | ||
457 | |||
458 | /* check for buffer wraparound */ | ||
459 | if (inbuf->head >= RBUFSIZE) | ||
460 | inbuf->head = 0; | ||
461 | |||
462 | gig_dbg(DEBUG_INTR, "head set to %u", inbuf->head); | ||
436 | } | 463 | } |
437 | } | 464 | } |
438 | EXPORT_SYMBOL_GPL(gigaset_m10x_input); | 465 | EXPORT_SYMBOL_GPL(gigaset_m10x_input); |
@@ -440,16 +467,16 @@ EXPORT_SYMBOL_GPL(gigaset_m10x_input); | |||
440 | 467 | ||
441 | /* == data output ========================================================== */ | 468 | /* == data output ========================================================== */ |
442 | 469 | ||
443 | /* Encoding of a PPP packet into an octet stuffed HDLC frame | 470 | /* |
444 | * with FCS, opening and closing flags. | 471 | * Encode a data packet into an octet stuffed HDLC frame with FCS, |
472 | * opening and closing flags, preserving headroom data. | ||
445 | * parameters: | 473 | * parameters: |
446 | * skb skb containing original packet (freed upon return) | 474 | * skb skb containing original packet (freed upon return) |
447 | * head number of headroom bytes to allocate in result skb | ||
448 | * tail number of tailroom bytes to allocate in result skb | ||
449 | * Return value: | 475 | * Return value: |
450 | * pointer to newly allocated skb containing the result frame | 476 | * pointer to newly allocated skb containing the result frame |
477 | * and the original link layer header, NULL on error | ||
451 | */ | 478 | */ |
452 | static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int head, int tail) | 479 | static struct sk_buff *HDLC_Encode(struct sk_buff *skb) |
453 | { | 480 | { |
454 | struct sk_buff *hdlc_skb; | 481 | struct sk_buff *hdlc_skb; |
455 | __u16 fcs; | 482 | __u16 fcs; |
@@ -471,16 +498,19 @@ static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int head, int tail) | |||
471 | 498 | ||
472 | /* size of new buffer: original size + number of stuffing bytes | 499 | /* size of new buffer: original size + number of stuffing bytes |
473 | * + 2 bytes FCS + 2 stuffing bytes for FCS (if needed) + 2 flag bytes | 500 | * + 2 bytes FCS + 2 stuffing bytes for FCS (if needed) + 2 flag bytes |
501 | * + room for link layer header | ||
474 | */ | 502 | */ |
475 | hdlc_skb = dev_alloc_skb(skb->len + stuf_cnt + 6 + tail + head); | 503 | hdlc_skb = dev_alloc_skb(skb->len + stuf_cnt + 6 + skb->mac_len); |
476 | if (!hdlc_skb) { | 504 | if (!hdlc_skb) { |
477 | dev_kfree_skb(skb); | 505 | dev_kfree_skb_any(skb); |
478 | return NULL; | 506 | return NULL; |
479 | } | 507 | } |
480 | skb_reserve(hdlc_skb, head); | ||
481 | 508 | ||
482 | /* Copy acknowledge request into new skb */ | 509 | /* Copy link layer header into new skb */ |
483 | memcpy(hdlc_skb->head, skb->head, 2); | 510 | skb_reset_mac_header(hdlc_skb); |
511 | skb_reserve(hdlc_skb, skb->mac_len); | ||
512 | memcpy(skb_mac_header(hdlc_skb), skb_mac_header(skb), skb->mac_len); | ||
513 | hdlc_skb->mac_len = skb->mac_len; | ||
484 | 514 | ||
485 | /* Add flag sequence in front of everything.. */ | 515 | /* Add flag sequence in front of everything.. */ |
486 | *(skb_put(hdlc_skb, 1)) = PPP_FLAG; | 516 | *(skb_put(hdlc_skb, 1)) = PPP_FLAG; |
@@ -511,33 +541,42 @@ static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int head, int tail) | |||
511 | 541 | ||
512 | *(skb_put(hdlc_skb, 1)) = PPP_FLAG; | 542 | *(skb_put(hdlc_skb, 1)) = PPP_FLAG; |
513 | 543 | ||
514 | dev_kfree_skb(skb); | 544 | dev_kfree_skb_any(skb); |
515 | return hdlc_skb; | 545 | return hdlc_skb; |
516 | } | 546 | } |
517 | 547 | ||
518 | /* Encoding of a raw packet into an octet stuffed bit inverted frame | 548 | /* |
549 | * Encode a data packet into an octet stuffed raw bit inverted frame, | ||
550 | * preserving headroom data. | ||
519 | * parameters: | 551 | * parameters: |
520 | * skb skb containing original packet (freed upon return) | 552 | * skb skb containing original packet (freed upon return) |
521 | * head number of headroom bytes to allocate in result skb | ||
522 | * tail number of tailroom bytes to allocate in result skb | ||
523 | * Return value: | 553 | * Return value: |
524 | * pointer to newly allocated skb containing the result frame | 554 | * pointer to newly allocated skb containing the result frame |
555 | * and the original link layer header, NULL on error | ||
525 | */ | 556 | */ |
526 | static struct sk_buff *iraw_encode(struct sk_buff *skb, int head, int tail) | 557 | static struct sk_buff *iraw_encode(struct sk_buff *skb) |
527 | { | 558 | { |
528 | struct sk_buff *iraw_skb; | 559 | struct sk_buff *iraw_skb; |
529 | unsigned char c; | 560 | unsigned char c; |
530 | unsigned char *cp; | 561 | unsigned char *cp; |
531 | int len; | 562 | int len; |
532 | 563 | ||
533 | /* worst case: every byte must be stuffed */ | 564 | /* size of new buffer (worst case = every byte must be stuffed): |
534 | iraw_skb = dev_alloc_skb(2*skb->len + tail + head); | 565 | * 2 * original size + room for link layer header |
566 | */ | ||
567 | iraw_skb = dev_alloc_skb(2*skb->len + skb->mac_len); | ||
535 | if (!iraw_skb) { | 568 | if (!iraw_skb) { |
536 | dev_kfree_skb(skb); | 569 | dev_kfree_skb_any(skb); |
537 | return NULL; | 570 | return NULL; |
538 | } | 571 | } |
539 | skb_reserve(iraw_skb, head); | ||
540 | 572 | ||
573 | /* copy link layer header into new skb */ | ||
574 | skb_reset_mac_header(iraw_skb); | ||
575 | skb_reserve(iraw_skb, skb->mac_len); | ||
576 | memcpy(skb_mac_header(iraw_skb), skb_mac_header(skb), skb->mac_len); | ||
577 | iraw_skb->mac_len = skb->mac_len; | ||
578 | |||
579 | /* copy and stuff data */ | ||
541 | cp = skb->data; | 580 | cp = skb->data; |
542 | len = skb->len; | 581 | len = skb->len; |
543 | while (len--) { | 582 | while (len--) { |
@@ -546,7 +585,7 @@ static struct sk_buff *iraw_encode(struct sk_buff *skb, int head, int tail) | |||
546 | *(skb_put(iraw_skb, 1)) = c; | 585 | *(skb_put(iraw_skb, 1)) = c; |
547 | *(skb_put(iraw_skb, 1)) = c; | 586 | *(skb_put(iraw_skb, 1)) = c; |
548 | } | 587 | } |
549 | dev_kfree_skb(skb); | 588 | dev_kfree_skb_any(skb); |
550 | return iraw_skb; | 589 | return iraw_skb; |
551 | } | 590 | } |
552 | 591 | ||
@@ -555,8 +594,10 @@ static struct sk_buff *iraw_encode(struct sk_buff *skb, int head, int tail) | |||
555 | * @bcs: B channel descriptor structure. | 594 | * @bcs: B channel descriptor structure. |
556 | * @skb: data to send. | 595 | * @skb: data to send. |
557 | * | 596 | * |
558 | * Called by i4l.c to encode and queue an skb for sending, and start | 597 | * Called by LL to encode and queue an skb for sending, and start |
559 | * transmission if necessary. | 598 | * transmission if necessary. |
599 | * Once the payload data has been transmitted completely, gigaset_skb_sent() | ||
600 | * will be called with the skb's link layer header preserved. | ||
560 | * | 601 | * |
561 | * Return value: | 602 | * Return value: |
562 | * number of bytes accepted for sending (skb->len) if ok, | 603 | * number of bytes accepted for sending (skb->len) if ok, |
@@ -564,24 +605,25 @@ static struct sk_buff *iraw_encode(struct sk_buff *skb, int head, int tail) | |||
564 | */ | 605 | */ |
565 | int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb) | 606 | int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb) |
566 | { | 607 | { |
608 | struct cardstate *cs = bcs->cs; | ||
567 | unsigned len = skb->len; | 609 | unsigned len = skb->len; |
568 | unsigned long flags; | 610 | unsigned long flags; |
569 | 611 | ||
570 | if (bcs->proto2 == ISDN_PROTO_L2_HDLC) | 612 | if (bcs->proto2 == L2_HDLC) |
571 | skb = HDLC_Encode(skb, HW_HDR_LEN, 0); | 613 | skb = HDLC_Encode(skb); |
572 | else | 614 | else |
573 | skb = iraw_encode(skb, HW_HDR_LEN, 0); | 615 | skb = iraw_encode(skb); |
574 | if (!skb) { | 616 | if (!skb) { |
575 | dev_err(bcs->cs->dev, | 617 | dev_err(cs->dev, |
576 | "unable to allocate memory for encoding!\n"); | 618 | "unable to allocate memory for encoding!\n"); |
577 | return -ENOMEM; | 619 | return -ENOMEM; |
578 | } | 620 | } |
579 | 621 | ||
580 | skb_queue_tail(&bcs->squeue, skb); | 622 | skb_queue_tail(&bcs->squeue, skb); |
581 | spin_lock_irqsave(&bcs->cs->lock, flags); | 623 | spin_lock_irqsave(&cs->lock, flags); |
582 | if (bcs->cs->connected) | 624 | if (cs->connected) |
583 | tasklet_schedule(&bcs->cs->write_tasklet); | 625 | tasklet_schedule(&cs->write_tasklet); |
584 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | 626 | spin_unlock_irqrestore(&cs->lock, flags); |
585 | 627 | ||
586 | return len; /* ok so far */ | 628 | return len; /* ok so far */ |
587 | } | 629 | } |
diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c index 5ed1d99eb9f3..47a5ffec55a3 100644 --- a/drivers/isdn/gigaset/bas-gigaset.c +++ b/drivers/isdn/gigaset/bas-gigaset.c | |||
@@ -14,11 +14,6 @@ | |||
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include "gigaset.h" | 16 | #include "gigaset.h" |
17 | |||
18 | #include <linux/errno.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/timer.h> | ||
22 | #include <linux/usb.h> | 17 | #include <linux/usb.h> |
23 | #include <linux/module.h> | 18 | #include <linux/module.h> |
24 | #include <linux/moduleparam.h> | 19 | #include <linux/moduleparam.h> |
@@ -57,7 +52,7 @@ MODULE_PARM_DESC(cidmode, "Call-ID mode"); | |||
57 | #define USB_SX353_PRODUCT_ID 0x0022 | 52 | #define USB_SX353_PRODUCT_ID 0x0022 |
58 | 53 | ||
59 | /* table of devices that work with this driver */ | 54 | /* table of devices that work with this driver */ |
60 | static const struct usb_device_id gigaset_table [] = { | 55 | static const struct usb_device_id gigaset_table[] = { |
61 | { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_3070_PRODUCT_ID) }, | 56 | { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_3070_PRODUCT_ID) }, |
62 | { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_3075_PRODUCT_ID) }, | 57 | { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_3075_PRODUCT_ID) }, |
63 | { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_SX303_PRODUCT_ID) }, | 58 | { USB_DEVICE(USB_GIGA_VENDOR_ID, USB_SX303_PRODUCT_ID) }, |
@@ -137,7 +132,7 @@ struct bas_cardstate { | |||
137 | #define BS_RESETTING 0x200 /* waiting for HD_RESET_INTERRUPT_PIPE_ACK */ | 132 | #define BS_RESETTING 0x200 /* waiting for HD_RESET_INTERRUPT_PIPE_ACK */ |
138 | 133 | ||
139 | 134 | ||
140 | static struct gigaset_driver *driver = NULL; | 135 | static struct gigaset_driver *driver; |
141 | 136 | ||
142 | /* usb specific object needed to register this driver with the usb subsystem */ | 137 | /* usb specific object needed to register this driver with the usb subsystem */ |
143 | static struct usb_driver gigaset_usb_driver = { | 138 | static struct usb_driver gigaset_usb_driver = { |
@@ -347,12 +342,7 @@ static inline void error_hangup(struct bc_state *bcs) | |||
347 | { | 342 | { |
348 | struct cardstate *cs = bcs->cs; | 343 | struct cardstate *cs = bcs->cs; |
349 | 344 | ||
350 | gig_dbg(DEBUG_ANY, "%s: scheduling HUP for channel %d", | 345 | gigaset_add_event(cs, &bcs->at_state, EV_HUP, NULL, 0, NULL); |
351 | __func__, bcs->channel); | ||
352 | |||
353 | if (!gigaset_add_event(cs, &bcs->at_state, EV_HUP, NULL, 0, NULL)) | ||
354 | dev_err(cs->dev, "event queue full\n"); | ||
355 | |||
356 | gigaset_schedule_event(cs); | 346 | gigaset_schedule_event(cs); |
357 | } | 347 | } |
358 | 348 | ||
@@ -601,11 +591,12 @@ static int atread_submit(struct cardstate *cs, int timeout) | |||
601 | ucs->dr_cmd_in.wLength = cpu_to_le16(ucs->rcvbuf_size); | 591 | ucs->dr_cmd_in.wLength = cpu_to_le16(ucs->rcvbuf_size); |
602 | usb_fill_control_urb(ucs->urb_cmd_in, ucs->udev, | 592 | usb_fill_control_urb(ucs->urb_cmd_in, ucs->udev, |
603 | usb_rcvctrlpipe(ucs->udev, 0), | 593 | usb_rcvctrlpipe(ucs->udev, 0), |
604 | (unsigned char*) & ucs->dr_cmd_in, | 594 | (unsigned char *) &ucs->dr_cmd_in, |
605 | ucs->rcvbuf, ucs->rcvbuf_size, | 595 | ucs->rcvbuf, ucs->rcvbuf_size, |
606 | read_ctrl_callback, cs->inbuf); | 596 | read_ctrl_callback, cs->inbuf); |
607 | 597 | ||
608 | if ((ret = usb_submit_urb(ucs->urb_cmd_in, GFP_ATOMIC)) != 0) { | 598 | ret = usb_submit_urb(ucs->urb_cmd_in, GFP_ATOMIC); |
599 | if (ret != 0) { | ||
609 | update_basstate(ucs, 0, BS_ATRDPEND); | 600 | update_basstate(ucs, 0, BS_ATRDPEND); |
610 | dev_err(cs->dev, "could not submit HD_READ_ATMESSAGE: %s\n", | 601 | dev_err(cs->dev, "could not submit HD_READ_ATMESSAGE: %s\n", |
611 | get_usb_rcmsg(ret)); | 602 | get_usb_rcmsg(ret)); |
@@ -652,13 +643,11 @@ static void read_int_callback(struct urb *urb) | |||
652 | return; | 643 | return; |
653 | case -ENODEV: /* device removed */ | 644 | case -ENODEV: /* device removed */ |
654 | case -ESHUTDOWN: /* device shut down */ | 645 | case -ESHUTDOWN: /* device shut down */ |
655 | //FIXME use this as disconnect indicator? | ||
656 | gig_dbg(DEBUG_USBREQ, "%s: device disconnected", __func__); | 646 | gig_dbg(DEBUG_USBREQ, "%s: device disconnected", __func__); |
657 | return; | 647 | return; |
658 | default: /* severe trouble */ | 648 | default: /* severe trouble */ |
659 | dev_warn(cs->dev, "interrupt read: %s\n", | 649 | dev_warn(cs->dev, "interrupt read: %s\n", |
660 | get_usb_statmsg(status)); | 650 | get_usb_statmsg(status)); |
661 | //FIXME corrective action? resubmission always ok? | ||
662 | goto resubmit; | 651 | goto resubmit; |
663 | } | 652 | } |
664 | 653 | ||
@@ -742,7 +731,8 @@ static void read_int_callback(struct urb *urb) | |||
742 | kfree(ucs->rcvbuf); | 731 | kfree(ucs->rcvbuf); |
743 | ucs->rcvbuf_size = 0; | 732 | ucs->rcvbuf_size = 0; |
744 | } | 733 | } |
745 | if ((ucs->rcvbuf = kmalloc(l, GFP_ATOMIC)) == NULL) { | 734 | ucs->rcvbuf = kmalloc(l, GFP_ATOMIC); |
735 | if (ucs->rcvbuf == NULL) { | ||
746 | spin_unlock_irqrestore(&cs->lock, flags); | 736 | spin_unlock_irqrestore(&cs->lock, flags); |
747 | dev_err(cs->dev, "out of memory receiving AT data\n"); | 737 | dev_err(cs->dev, "out of memory receiving AT data\n"); |
748 | error_reset(cs); | 738 | error_reset(cs); |
@@ -750,12 +740,12 @@ static void read_int_callback(struct urb *urb) | |||
750 | } | 740 | } |
751 | ucs->rcvbuf_size = l; | 741 | ucs->rcvbuf_size = l; |
752 | ucs->retry_cmd_in = 0; | 742 | ucs->retry_cmd_in = 0; |
753 | if ((rc = atread_submit(cs, BAS_TIMEOUT)) < 0) { | 743 | rc = atread_submit(cs, BAS_TIMEOUT); |
744 | if (rc < 0) { | ||
754 | kfree(ucs->rcvbuf); | 745 | kfree(ucs->rcvbuf); |
755 | ucs->rcvbuf = NULL; | 746 | ucs->rcvbuf = NULL; |
756 | ucs->rcvbuf_size = 0; | 747 | ucs->rcvbuf_size = 0; |
757 | if (rc != -ENODEV) { | 748 | if (rc != -ENODEV) { |
758 | //FIXME corrective action? | ||
759 | spin_unlock_irqrestore(&cs->lock, flags); | 749 | spin_unlock_irqrestore(&cs->lock, flags); |
760 | error_reset(cs); | 750 | error_reset(cs); |
761 | break; | 751 | break; |
@@ -911,7 +901,7 @@ static int starturbs(struct bc_state *bcs) | |||
911 | int rc; | 901 | int rc; |
912 | 902 | ||
913 | /* initialize L2 reception */ | 903 | /* initialize L2 reception */ |
914 | if (bcs->proto2 == ISDN_PROTO_L2_HDLC) | 904 | if (bcs->proto2 == L2_HDLC) |
915 | bcs->inputstate |= INS_flag_hunt; | 905 | bcs->inputstate |= INS_flag_hunt; |
916 | 906 | ||
917 | /* submit all isochronous input URBs */ | 907 | /* submit all isochronous input URBs */ |
@@ -940,7 +930,8 @@ static int starturbs(struct bc_state *bcs) | |||
940 | } | 930 | } |
941 | 931 | ||
942 | dump_urb(DEBUG_ISO, "Initial isoc read", urb); | 932 | dump_urb(DEBUG_ISO, "Initial isoc read", urb); |
943 | if ((rc = usb_submit_urb(urb, GFP_ATOMIC)) != 0) | 933 | rc = usb_submit_urb(urb, GFP_ATOMIC); |
934 | if (rc != 0) | ||
944 | goto error; | 935 | goto error; |
945 | } | 936 | } |
946 | 937 | ||
@@ -1045,7 +1036,8 @@ static int submit_iso_write_urb(struct isow_urbctx_t *ucx) | |||
1045 | 1036 | ||
1046 | /* compute frame length according to flow control */ | 1037 | /* compute frame length according to flow control */ |
1047 | ifd->length = BAS_NORMFRAME; | 1038 | ifd->length = BAS_NORMFRAME; |
1048 | if ((corrbytes = atomic_read(&ubc->corrbytes)) != 0) { | 1039 | corrbytes = atomic_read(&ubc->corrbytes); |
1040 | if (corrbytes != 0) { | ||
1049 | gig_dbg(DEBUG_ISO, "%s: corrbytes=%d", | 1041 | gig_dbg(DEBUG_ISO, "%s: corrbytes=%d", |
1050 | __func__, corrbytes); | 1042 | __func__, corrbytes); |
1051 | if (corrbytes > BAS_HIGHFRAME - BAS_NORMFRAME) | 1043 | if (corrbytes > BAS_HIGHFRAME - BAS_NORMFRAME) |
@@ -1064,7 +1056,7 @@ static int submit_iso_write_urb(struct isow_urbctx_t *ucx) | |||
1064 | "%s: buffer busy at frame %d", | 1056 | "%s: buffer busy at frame %d", |
1065 | __func__, nframe); | 1057 | __func__, nframe); |
1066 | /* tasklet will be restarted from | 1058 | /* tasklet will be restarted from |
1067 | gigaset_send_skb() */ | 1059 | gigaset_isoc_send_skb() */ |
1068 | } else { | 1060 | } else { |
1069 | dev_err(ucx->bcs->cs->dev, | 1061 | dev_err(ucx->bcs->cs->dev, |
1070 | "%s: buffer error %d at frame %d\n", | 1062 | "%s: buffer error %d at frame %d\n", |
@@ -1284,7 +1276,8 @@ static void read_iso_tasklet(unsigned long data) | |||
1284 | for (;;) { | 1276 | for (;;) { |
1285 | /* retrieve URB */ | 1277 | /* retrieve URB */ |
1286 | spin_lock_irqsave(&ubc->isoinlock, flags); | 1278 | spin_lock_irqsave(&ubc->isoinlock, flags); |
1287 | if (!(urb = ubc->isoindone)) { | 1279 | urb = ubc->isoindone; |
1280 | if (!urb) { | ||
1288 | spin_unlock_irqrestore(&ubc->isoinlock, flags); | 1281 | spin_unlock_irqrestore(&ubc->isoinlock, flags); |
1289 | return; | 1282 | return; |
1290 | } | 1283 | } |
@@ -1371,7 +1364,7 @@ static void read_iso_tasklet(unsigned long data) | |||
1371 | "isochronous read: %d data bytes missing\n", | 1364 | "isochronous read: %d data bytes missing\n", |
1372 | totleft); | 1365 | totleft); |
1373 | 1366 | ||
1374 | error: | 1367 | error: |
1375 | /* URB processed, resubmit */ | 1368 | /* URB processed, resubmit */ |
1376 | for (frame = 0; frame < BAS_NUMFRAMES; frame++) { | 1369 | for (frame = 0; frame < BAS_NUMFRAMES; frame++) { |
1377 | urb->iso_frame_desc[frame].status = 0; | 1370 | urb->iso_frame_desc[frame].status = 0; |
@@ -1568,7 +1561,7 @@ static int req_submit(struct bc_state *bcs, int req, int val, int timeout) | |||
1568 | ucs->dr_ctrl.wLength = 0; | 1561 | ucs->dr_ctrl.wLength = 0; |
1569 | usb_fill_control_urb(ucs->urb_ctrl, ucs->udev, | 1562 | usb_fill_control_urb(ucs->urb_ctrl, ucs->udev, |
1570 | usb_sndctrlpipe(ucs->udev, 0), | 1563 | usb_sndctrlpipe(ucs->udev, 0), |
1571 | (unsigned char*) &ucs->dr_ctrl, NULL, 0, | 1564 | (unsigned char *) &ucs->dr_ctrl, NULL, 0, |
1572 | write_ctrl_callback, ucs); | 1565 | write_ctrl_callback, ucs); |
1573 | ucs->retry_ctrl = 0; | 1566 | ucs->retry_ctrl = 0; |
1574 | ret = usb_submit_urb(ucs->urb_ctrl, GFP_ATOMIC); | 1567 | ret = usb_submit_urb(ucs->urb_ctrl, GFP_ATOMIC); |
@@ -1621,7 +1614,8 @@ static int gigaset_init_bchannel(struct bc_state *bcs) | |||
1621 | return -EHOSTUNREACH; | 1614 | return -EHOSTUNREACH; |
1622 | } | 1615 | } |
1623 | 1616 | ||
1624 | if ((ret = starturbs(bcs)) < 0) { | 1617 | ret = starturbs(bcs); |
1618 | if (ret < 0) { | ||
1625 | dev_err(cs->dev, | 1619 | dev_err(cs->dev, |
1626 | "could not start isochronous I/O for channel B%d: %s\n", | 1620 | "could not start isochronous I/O for channel B%d: %s\n", |
1627 | bcs->channel + 1, | 1621 | bcs->channel + 1, |
@@ -1633,7 +1627,8 @@ static int gigaset_init_bchannel(struct bc_state *bcs) | |||
1633 | } | 1627 | } |
1634 | 1628 | ||
1635 | req = bcs->channel ? HD_OPEN_B2CHANNEL : HD_OPEN_B1CHANNEL; | 1629 | req = bcs->channel ? HD_OPEN_B2CHANNEL : HD_OPEN_B1CHANNEL; |
1636 | if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0) { | 1630 | ret = req_submit(bcs, req, 0, BAS_TIMEOUT); |
1631 | if (ret < 0) { | ||
1637 | dev_err(cs->dev, "could not open channel B%d\n", | 1632 | dev_err(cs->dev, "could not open channel B%d\n", |
1638 | bcs->channel + 1); | 1633 | bcs->channel + 1); |
1639 | stopurbs(bcs->hw.bas); | 1634 | stopurbs(bcs->hw.bas); |
@@ -1677,7 +1672,8 @@ static int gigaset_close_bchannel(struct bc_state *bcs) | |||
1677 | 1672 | ||
1678 | /* channel running: tell device to close it */ | 1673 | /* channel running: tell device to close it */ |
1679 | req = bcs->channel ? HD_CLOSE_B2CHANNEL : HD_CLOSE_B1CHANNEL; | 1674 | req = bcs->channel ? HD_CLOSE_B2CHANNEL : HD_CLOSE_B1CHANNEL; |
1680 | if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0) | 1675 | ret = req_submit(bcs, req, 0, BAS_TIMEOUT); |
1676 | if (ret < 0) | ||
1681 | dev_err(cs->dev, "closing channel B%d failed\n", | 1677 | dev_err(cs->dev, "closing channel B%d failed\n", |
1682 | bcs->channel + 1); | 1678 | bcs->channel + 1); |
1683 | 1679 | ||
@@ -1700,13 +1696,14 @@ static void complete_cb(struct cardstate *cs) | |||
1700 | 1696 | ||
1701 | /* unqueue completed buffer */ | 1697 | /* unqueue completed buffer */ |
1702 | cs->cmdbytes -= cs->curlen; | 1698 | cs->cmdbytes -= cs->curlen; |
1703 | gig_dbg(DEBUG_TRANSCMD|DEBUG_LOCKCMD, | 1699 | gig_dbg(DEBUG_OUTPUT, "write_command: sent %u bytes, %u left", |
1704 | "write_command: sent %u bytes, %u left", | ||
1705 | cs->curlen, cs->cmdbytes); | 1700 | cs->curlen, cs->cmdbytes); |
1706 | if ((cs->cmdbuf = cb->next) != NULL) { | 1701 | if (cb->next != NULL) { |
1702 | cs->cmdbuf = cb->next; | ||
1707 | cs->cmdbuf->prev = NULL; | 1703 | cs->cmdbuf->prev = NULL; |
1708 | cs->curlen = cs->cmdbuf->len; | 1704 | cs->curlen = cs->cmdbuf->len; |
1709 | } else { | 1705 | } else { |
1706 | cs->cmdbuf = NULL; | ||
1710 | cs->lastcmdbuf = NULL; | 1707 | cs->lastcmdbuf = NULL; |
1711 | cs->curlen = 0; | 1708 | cs->curlen = 0; |
1712 | } | 1709 | } |
@@ -1833,7 +1830,7 @@ static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len) | |||
1833 | ucs->dr_cmd_out.wLength = cpu_to_le16(len); | 1830 | ucs->dr_cmd_out.wLength = cpu_to_le16(len); |
1834 | usb_fill_control_urb(ucs->urb_cmd_out, ucs->udev, | 1831 | usb_fill_control_urb(ucs->urb_cmd_out, ucs->udev, |
1835 | usb_sndctrlpipe(ucs->udev, 0), | 1832 | usb_sndctrlpipe(ucs->udev, 0), |
1836 | (unsigned char*) &ucs->dr_cmd_out, buf, len, | 1833 | (unsigned char *) &ucs->dr_cmd_out, buf, len, |
1837 | write_command_callback, cs); | 1834 | write_command_callback, cs); |
1838 | rc = usb_submit_urb(ucs->urb_cmd_out, GFP_ATOMIC); | 1835 | rc = usb_submit_urb(ucs->urb_cmd_out, GFP_ATOMIC); |
1839 | if (unlikely(rc)) { | 1836 | if (unlikely(rc)) { |
@@ -1873,13 +1870,13 @@ static int start_cbsend(struct cardstate *cs) | |||
1873 | 1870 | ||
1874 | /* check if suspend requested */ | 1871 | /* check if suspend requested */ |
1875 | if (ucs->basstate & BS_SUSPEND) { | 1872 | if (ucs->basstate & BS_SUSPEND) { |
1876 | gig_dbg(DEBUG_TRANSCMD|DEBUG_LOCKCMD, "suspending"); | 1873 | gig_dbg(DEBUG_OUTPUT, "suspending"); |
1877 | return -EHOSTUNREACH; | 1874 | return -EHOSTUNREACH; |
1878 | } | 1875 | } |
1879 | 1876 | ||
1880 | /* check if AT channel is open */ | 1877 | /* check if AT channel is open */ |
1881 | if (!(ucs->basstate & BS_ATOPEN)) { | 1878 | if (!(ucs->basstate & BS_ATOPEN)) { |
1882 | gig_dbg(DEBUG_TRANSCMD|DEBUG_LOCKCMD, "AT channel not open"); | 1879 | gig_dbg(DEBUG_OUTPUT, "AT channel not open"); |
1883 | rc = req_submit(cs->bcs, HD_OPEN_ATCHANNEL, 0, BAS_TIMEOUT); | 1880 | rc = req_submit(cs->bcs, HD_OPEN_ATCHANNEL, 0, BAS_TIMEOUT); |
1884 | if (rc < 0) { | 1881 | if (rc < 0) { |
1885 | /* flush command queue */ | 1882 | /* flush command queue */ |
@@ -1953,7 +1950,8 @@ static int gigaset_write_cmd(struct cardstate *cs, | |||
1953 | 1950 | ||
1954 | if (len > IF_WRITEBUF) | 1951 | if (len > IF_WRITEBUF) |
1955 | len = IF_WRITEBUF; | 1952 | len = IF_WRITEBUF; |
1956 | if (!(cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC))) { | 1953 | cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC); |
1954 | if (!cb) { | ||
1957 | dev_err(cs->dev, "%s: out of memory\n", __func__); | 1955 | dev_err(cs->dev, "%s: out of memory\n", __func__); |
1958 | rc = -ENOMEM; | 1956 | rc = -ENOMEM; |
1959 | goto notqueued; | 1957 | goto notqueued; |
@@ -2100,14 +2098,15 @@ static int gigaset_initbcshw(struct bc_state *bcs) | |||
2100 | } | 2098 | } |
2101 | ubc->isooutdone = ubc->isooutfree = ubc->isooutovfl = NULL; | 2099 | ubc->isooutdone = ubc->isooutfree = ubc->isooutovfl = NULL; |
2102 | ubc->numsub = 0; | 2100 | ubc->numsub = 0; |
2103 | if (!(ubc->isooutbuf = kmalloc(sizeof(struct isowbuf_t), GFP_KERNEL))) { | 2101 | ubc->isooutbuf = kmalloc(sizeof(struct isowbuf_t), GFP_KERNEL); |
2102 | if (!ubc->isooutbuf) { | ||
2104 | pr_err("out of memory\n"); | 2103 | pr_err("out of memory\n"); |
2105 | kfree(ubc); | 2104 | kfree(ubc); |
2106 | bcs->hw.bas = NULL; | 2105 | bcs->hw.bas = NULL; |
2107 | return 0; | 2106 | return 0; |
2108 | } | 2107 | } |
2109 | tasklet_init(&ubc->sent_tasklet, | 2108 | tasklet_init(&ubc->sent_tasklet, |
2110 | &write_iso_tasklet, (unsigned long) bcs); | 2109 | write_iso_tasklet, (unsigned long) bcs); |
2111 | 2110 | ||
2112 | spin_lock_init(&ubc->isoinlock); | 2111 | spin_lock_init(&ubc->isoinlock); |
2113 | for (i = 0; i < BAS_INURBS; ++i) | 2112 | for (i = 0; i < BAS_INURBS; ++i) |
@@ -2128,7 +2127,7 @@ static int gigaset_initbcshw(struct bc_state *bcs) | |||
2128 | ubc->shared0s = 0; | 2127 | ubc->shared0s = 0; |
2129 | ubc->stolen0s = 0; | 2128 | ubc->stolen0s = 0; |
2130 | tasklet_init(&ubc->rcvd_tasklet, | 2129 | tasklet_init(&ubc->rcvd_tasklet, |
2131 | &read_iso_tasklet, (unsigned long) bcs); | 2130 | read_iso_tasklet, (unsigned long) bcs); |
2132 | return 1; | 2131 | return 1; |
2133 | } | 2132 | } |
2134 | 2133 | ||
@@ -2241,7 +2240,7 @@ static int gigaset_probe(struct usb_interface *interface, | |||
2241 | int i, j; | 2240 | int i, j; |
2242 | int rc; | 2241 | int rc; |
2243 | 2242 | ||
2244 | gig_dbg(DEBUG_ANY, | 2243 | gig_dbg(DEBUG_INIT, |
2245 | "%s: Check if device matches .. (Vendor: 0x%x, Product: 0x%x)", | 2244 | "%s: Check if device matches .. (Vendor: 0x%x, Product: 0x%x)", |
2246 | __func__, le16_to_cpu(udev->descriptor.idVendor), | 2245 | __func__, le16_to_cpu(udev->descriptor.idVendor), |
2247 | le16_to_cpu(udev->descriptor.idProduct)); | 2246 | le16_to_cpu(udev->descriptor.idProduct)); |
@@ -2249,10 +2248,11 @@ static int gigaset_probe(struct usb_interface *interface, | |||
2249 | /* set required alternate setting */ | 2248 | /* set required alternate setting */ |
2250 | hostif = interface->cur_altsetting; | 2249 | hostif = interface->cur_altsetting; |
2251 | if (hostif->desc.bAlternateSetting != 3) { | 2250 | if (hostif->desc.bAlternateSetting != 3) { |
2252 | gig_dbg(DEBUG_ANY, | 2251 | gig_dbg(DEBUG_INIT, |
2253 | "%s: wrong alternate setting %d - trying to switch", | 2252 | "%s: wrong alternate setting %d - trying to switch", |
2254 | __func__, hostif->desc.bAlternateSetting); | 2253 | __func__, hostif->desc.bAlternateSetting); |
2255 | if (usb_set_interface(udev, hostif->desc.bInterfaceNumber, 3) < 0) { | 2254 | if (usb_set_interface(udev, hostif->desc.bInterfaceNumber, 3) |
2255 | < 0) { | ||
2256 | dev_warn(&udev->dev, "usb_set_interface failed, " | 2256 | dev_warn(&udev->dev, "usb_set_interface failed, " |
2257 | "device %d interface %d altsetting %d\n", | 2257 | "device %d interface %d altsetting %d\n", |
2258 | udev->devnum, hostif->desc.bInterfaceNumber, | 2258 | udev->devnum, hostif->desc.bInterfaceNumber, |
@@ -2321,14 +2321,16 @@ static int gigaset_probe(struct usb_interface *interface, | |||
2321 | (endpoint->bEndpointAddress) & 0x0f), | 2321 | (endpoint->bEndpointAddress) & 0x0f), |
2322 | ucs->int_in_buf, IP_MSGSIZE, read_int_callback, cs, | 2322 | ucs->int_in_buf, IP_MSGSIZE, read_int_callback, cs, |
2323 | endpoint->bInterval); | 2323 | endpoint->bInterval); |
2324 | if ((rc = usb_submit_urb(ucs->urb_int_in, GFP_KERNEL)) != 0) { | 2324 | rc = usb_submit_urb(ucs->urb_int_in, GFP_KERNEL); |
2325 | if (rc != 0) { | ||
2325 | dev_err(cs->dev, "could not submit interrupt URB: %s\n", | 2326 | dev_err(cs->dev, "could not submit interrupt URB: %s\n", |
2326 | get_usb_rcmsg(rc)); | 2327 | get_usb_rcmsg(rc)); |
2327 | goto error; | 2328 | goto error; |
2328 | } | 2329 | } |
2329 | 2330 | ||
2330 | /* tell the device that the driver is ready */ | 2331 | /* tell the device that the driver is ready */ |
2331 | if ((rc = req_submit(cs->bcs, HD_DEVICE_INIT_ACK, 0, 0)) != 0) | 2332 | rc = req_submit(cs->bcs, HD_DEVICE_INIT_ACK, 0, 0); |
2333 | if (rc != 0) | ||
2332 | goto error; | 2334 | goto error; |
2333 | 2335 | ||
2334 | /* tell common part that the device is ready */ | 2336 | /* tell common part that the device is ready */ |
@@ -2524,9 +2526,10 @@ static int __init bas_gigaset_init(void) | |||
2524 | int result; | 2526 | int result; |
2525 | 2527 | ||
2526 | /* allocate memory for our driver state and intialize it */ | 2528 | /* allocate memory for our driver state and intialize it */ |
2527 | if ((driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS, | 2529 | driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS, |
2528 | GIGASET_MODULENAME, GIGASET_DEVNAME, | 2530 | GIGASET_MODULENAME, GIGASET_DEVNAME, |
2529 | &gigops, THIS_MODULE)) == NULL) | 2531 | &gigops, THIS_MODULE); |
2532 | if (driver == NULL) | ||
2530 | goto error; | 2533 | goto error; |
2531 | 2534 | ||
2532 | /* register this driver with the USB subsystem */ | 2535 | /* register this driver with the USB subsystem */ |
diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c new file mode 100644 index 000000000000..964a55fb1486 --- /dev/null +++ b/drivers/isdn/gigaset/capi.c | |||
@@ -0,0 +1,2273 @@ | |||
1 | /* | ||
2 | * Kernel CAPI interface for the Gigaset driver | ||
3 | * | ||
4 | * Copyright (c) 2009 by Tilman Schmidt <tilman@imap.cc>. | ||
5 | * | ||
6 | * ===================================================================== | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License as | ||
9 | * published by the Free Software Foundation; either version 2 of | ||
10 | * the License, or (at your option) any later version. | ||
11 | * ===================================================================== | ||
12 | */ | ||
13 | |||
14 | #include "gigaset.h" | ||
15 | #include <linux/proc_fs.h> | ||
16 | #include <linux/seq_file.h> | ||
17 | #include <linux/isdn/capilli.h> | ||
18 | #include <linux/isdn/capicmd.h> | ||
19 | #include <linux/isdn/capiutil.h> | ||
20 | |||
21 | /* missing from kernelcapi.h */ | ||
22 | #define CapiNcpiNotSupportedByProtocol 0x0001 | ||
23 | #define CapiFlagsNotSupportedByProtocol 0x0002 | ||
24 | #define CapiAlertAlreadySent 0x0003 | ||
25 | #define CapiFacilitySpecificFunctionNotSupported 0x3011 | ||
26 | |||
27 | /* missing from capicmd.h */ | ||
28 | #define CAPI_CONNECT_IND_BASELEN (CAPI_MSG_BASELEN+4+2+8*1) | ||
29 | #define CAPI_CONNECT_ACTIVE_IND_BASELEN (CAPI_MSG_BASELEN+4+3*1) | ||
30 | #define CAPI_CONNECT_B3_IND_BASELEN (CAPI_MSG_BASELEN+4+1) | ||
31 | #define CAPI_CONNECT_B3_ACTIVE_IND_BASELEN (CAPI_MSG_BASELEN+4+1) | ||
32 | #define CAPI_DATA_B3_REQ_LEN64 (CAPI_MSG_BASELEN+4+4+2+2+2+8) | ||
33 | #define CAPI_DATA_B3_CONF_LEN (CAPI_MSG_BASELEN+4+2+2) | ||
34 | #define CAPI_DISCONNECT_IND_LEN (CAPI_MSG_BASELEN+4+2) | ||
35 | #define CAPI_DISCONNECT_B3_IND_BASELEN (CAPI_MSG_BASELEN+4+2+1) | ||
36 | #define CAPI_FACILITY_CONF_BASELEN (CAPI_MSG_BASELEN+4+2+2+1) | ||
37 | /* most _CONF messages contain only Controller/PLCI/NCCI and Info parameters */ | ||
38 | #define CAPI_STDCONF_LEN (CAPI_MSG_BASELEN+4+2) | ||
39 | |||
40 | #define CAPI_FACILITY_HANDSET 0x0000 | ||
41 | #define CAPI_FACILITY_DTMF 0x0001 | ||
42 | #define CAPI_FACILITY_V42BIS 0x0002 | ||
43 | #define CAPI_FACILITY_SUPPSVC 0x0003 | ||
44 | #define CAPI_FACILITY_WAKEUP 0x0004 | ||
45 | #define CAPI_FACILITY_LI 0x0005 | ||
46 | |||
47 | #define CAPI_SUPPSVC_GETSUPPORTED 0x0000 | ||
48 | |||
49 | /* missing from capiutil.h */ | ||
50 | #define CAPIMSG_PLCI_PART(m) CAPIMSG_U8(m, 9) | ||
51 | #define CAPIMSG_NCCI_PART(m) CAPIMSG_U16(m, 10) | ||
52 | #define CAPIMSG_HANDLE_REQ(m) CAPIMSG_U16(m, 18) /* DATA_B3_REQ/_IND only! */ | ||
53 | #define CAPIMSG_FLAGS(m) CAPIMSG_U16(m, 20) | ||
54 | #define CAPIMSG_SETCONTROLLER(m, contr) capimsg_setu8(m, 8, contr) | ||
55 | #define CAPIMSG_SETPLCI_PART(m, plci) capimsg_setu8(m, 9, plci) | ||
56 | #define CAPIMSG_SETNCCI_PART(m, ncci) capimsg_setu16(m, 10, ncci) | ||
57 | #define CAPIMSG_SETFLAGS(m, flags) capimsg_setu16(m, 20, flags) | ||
58 | |||
59 | /* parameters with differing location in DATA_B3_CONF/_RESP: */ | ||
60 | #define CAPIMSG_SETHANDLE_CONF(m, handle) capimsg_setu16(m, 12, handle) | ||
61 | #define CAPIMSG_SETINFO_CONF(m, info) capimsg_setu16(m, 14, info) | ||
62 | |||
63 | /* Flags (DATA_B3_REQ/_IND) */ | ||
64 | #define CAPI_FLAGS_DELIVERY_CONFIRMATION 0x04 | ||
65 | #define CAPI_FLAGS_RESERVED (~0x1f) | ||
66 | |||
67 | /* buffer sizes */ | ||
68 | #define MAX_BC_OCTETS 11 | ||
69 | #define MAX_HLC_OCTETS 3 | ||
70 | #define MAX_NUMBER_DIGITS 20 | ||
71 | #define MAX_FMT_IE_LEN 20 | ||
72 | |||
73 | /* values for gigaset_capi_appl.connected */ | ||
74 | #define APCONN_NONE 0 /* inactive/listening */ | ||
75 | #define APCONN_SETUP 1 /* connecting */ | ||
76 | #define APCONN_ACTIVE 2 /* B channel up */ | ||
77 | |||
78 | /* registered application data structure */ | ||
79 | struct gigaset_capi_appl { | ||
80 | struct list_head ctrlist; | ||
81 | struct gigaset_capi_appl *bcnext; | ||
82 | u16 id; | ||
83 | u16 nextMessageNumber; | ||
84 | u32 listenInfoMask; | ||
85 | u32 listenCIPmask; | ||
86 | int connected; | ||
87 | }; | ||
88 | |||
89 | /* CAPI specific controller data structure */ | ||
90 | struct gigaset_capi_ctr { | ||
91 | struct capi_ctr ctr; | ||
92 | struct list_head appls; | ||
93 | struct sk_buff_head sendqueue; | ||
94 | atomic_t sendqlen; | ||
95 | /* two _cmsg structures possibly used concurrently: */ | ||
96 | _cmsg hcmsg; /* for message composition triggered from hardware */ | ||
97 | _cmsg acmsg; /* for dissection of messages sent from application */ | ||
98 | u8 bc_buf[MAX_BC_OCTETS+1]; | ||
99 | u8 hlc_buf[MAX_HLC_OCTETS+1]; | ||
100 | u8 cgpty_buf[MAX_NUMBER_DIGITS+3]; | ||
101 | u8 cdpty_buf[MAX_NUMBER_DIGITS+2]; | ||
102 | }; | ||
103 | |||
104 | /* CIP Value table (from CAPI 2.0 standard, ch. 6.1) */ | ||
105 | static struct { | ||
106 | u8 *bc; | ||
107 | u8 *hlc; | ||
108 | } cip2bchlc[] = { | ||
109 | [1] = { "8090A3", NULL }, | ||
110 | /* Speech (A-law) */ | ||
111 | [2] = { "8890", NULL }, | ||
112 | /* Unrestricted digital information */ | ||
113 | [3] = { "8990", NULL }, | ||
114 | /* Restricted digital information */ | ||
115 | [4] = { "9090A3", NULL }, | ||
116 | /* 3,1 kHz audio (A-law) */ | ||
117 | [5] = { "9190", NULL }, | ||
118 | /* 7 kHz audio */ | ||
119 | [6] = { "9890", NULL }, | ||
120 | /* Video */ | ||
121 | [7] = { "88C0C6E6", NULL }, | ||
122 | /* Packet mode */ | ||
123 | [8] = { "8890218F", NULL }, | ||
124 | /* 56 kbit/s rate adaptation */ | ||
125 | [9] = { "9190A5", NULL }, | ||
126 | /* Unrestricted digital information with tones/announcements */ | ||
127 | [16] = { "8090A3", "9181" }, | ||
128 | /* Telephony */ | ||
129 | [17] = { "9090A3", "9184" }, | ||
130 | /* Group 2/3 facsimile */ | ||
131 | [18] = { "8890", "91A1" }, | ||
132 | /* Group 4 facsimile Class 1 */ | ||
133 | [19] = { "8890", "91A4" }, | ||
134 | /* Teletex service basic and mixed mode | ||
135 | and Group 4 facsimile service Classes II and III */ | ||
136 | [20] = { "8890", "91A8" }, | ||
137 | /* Teletex service basic and processable mode */ | ||
138 | [21] = { "8890", "91B1" }, | ||
139 | /* Teletex service basic mode */ | ||
140 | [22] = { "8890", "91B2" }, | ||
141 | /* International interworking for Videotex */ | ||
142 | [23] = { "8890", "91B5" }, | ||
143 | /* Telex */ | ||
144 | [24] = { "8890", "91B8" }, | ||
145 | /* Message Handling Systems in accordance with X.400 */ | ||
146 | [25] = { "8890", "91C1" }, | ||
147 | /* OSI application in accordance with X.200 */ | ||
148 | [26] = { "9190A5", "9181" }, | ||
149 | /* 7 kHz telephony */ | ||
150 | [27] = { "9190A5", "916001" }, | ||
151 | /* Video telephony, first connection */ | ||
152 | [28] = { "8890", "916002" }, | ||
153 | /* Video telephony, second connection */ | ||
154 | }; | ||
155 | |||
156 | /* | ||
157 | * helper functions | ||
158 | * ================ | ||
159 | */ | ||
160 | |||
161 | /* | ||
162 | * emit unsupported parameter warning | ||
163 | */ | ||
164 | static inline void ignore_cstruct_param(struct cardstate *cs, _cstruct param, | ||
165 | char *msgname, char *paramname) | ||
166 | { | ||
167 | if (param && *param) | ||
168 | dev_warn(cs->dev, "%s: ignoring unsupported parameter: %s\n", | ||
169 | msgname, paramname); | ||
170 | } | ||
171 | |||
172 | /* | ||
173 | * convert hex to binary | ||
174 | */ | ||
175 | static inline u8 hex2bin(char c) | ||
176 | { | ||
177 | int result = c & 0x0f; | ||
178 | if (c & 0x40) | ||
179 | result += 9; | ||
180 | return result; | ||
181 | } | ||
182 | |||
183 | /* | ||
184 | * convert an IE from Gigaset hex string to ETSI binary representation | ||
185 | * including length byte | ||
186 | * return value: result length, -1 on error | ||
187 | */ | ||
188 | static int encode_ie(char *in, u8 *out, int maxlen) | ||
189 | { | ||
190 | int l = 0; | ||
191 | while (*in) { | ||
192 | if (!isxdigit(in[0]) || !isxdigit(in[1]) || l >= maxlen) | ||
193 | return -1; | ||
194 | out[++l] = (hex2bin(in[0]) << 4) + hex2bin(in[1]); | ||
195 | in += 2; | ||
196 | } | ||
197 | out[0] = l; | ||
198 | return l; | ||
199 | } | ||
200 | |||
201 | /* | ||
202 | * convert an IE from ETSI binary representation including length byte | ||
203 | * to Gigaset hex string | ||
204 | */ | ||
205 | static void decode_ie(u8 *in, char *out) | ||
206 | { | ||
207 | int i = *in; | ||
208 | while (i-- > 0) { | ||
209 | /* ToDo: conversion to upper case necessary? */ | ||
210 | *out++ = toupper(hex_asc_hi(*++in)); | ||
211 | *out++ = toupper(hex_asc_lo(*in)); | ||
212 | } | ||
213 | } | ||
214 | |||
215 | /* | ||
216 | * retrieve application data structure for an application ID | ||
217 | */ | ||
218 | static inline struct gigaset_capi_appl * | ||
219 | get_appl(struct gigaset_capi_ctr *iif, u16 appl) | ||
220 | { | ||
221 | struct gigaset_capi_appl *ap; | ||
222 | |||
223 | list_for_each_entry(ap, &iif->appls, ctrlist) | ||
224 | if (ap->id == appl) | ||
225 | return ap; | ||
226 | return NULL; | ||
227 | } | ||
228 | |||
229 | /* | ||
230 | * dump CAPI message to kernel messages for debugging | ||
231 | */ | ||
232 | static inline void dump_cmsg(enum debuglevel level, const char *tag, _cmsg *p) | ||
233 | { | ||
234 | #ifdef CONFIG_GIGASET_DEBUG | ||
235 | _cdebbuf *cdb; | ||
236 | |||
237 | if (!(gigaset_debuglevel & level)) | ||
238 | return; | ||
239 | |||
240 | cdb = capi_cmsg2str(p); | ||
241 | if (cdb) { | ||
242 | gig_dbg(level, "%s: [%d] %s", tag, p->ApplId, cdb->buf); | ||
243 | cdebbuf_free(cdb); | ||
244 | } else { | ||
245 | gig_dbg(level, "%s: [%d] %s", tag, p->ApplId, | ||
246 | capi_cmd2str(p->Command, p->Subcommand)); | ||
247 | } | ||
248 | #endif | ||
249 | } | ||
250 | |||
251 | static inline void dump_rawmsg(enum debuglevel level, const char *tag, | ||
252 | unsigned char *data) | ||
253 | { | ||
254 | #ifdef CONFIG_GIGASET_DEBUG | ||
255 | char *dbgline; | ||
256 | int i, l; | ||
257 | |||
258 | if (!(gigaset_debuglevel & level)) | ||
259 | return; | ||
260 | |||
261 | l = CAPIMSG_LEN(data); | ||
262 | if (l < 12) { | ||
263 | gig_dbg(level, "%s: ??? LEN=%04d", tag, l); | ||
264 | return; | ||
265 | } | ||
266 | gig_dbg(level, "%s: 0x%02x:0x%02x: ID=%03d #0x%04x LEN=%04d NCCI=0x%x", | ||
267 | tag, CAPIMSG_COMMAND(data), CAPIMSG_SUBCOMMAND(data), | ||
268 | CAPIMSG_APPID(data), CAPIMSG_MSGID(data), l, | ||
269 | CAPIMSG_CONTROL(data)); | ||
270 | l -= 12; | ||
271 | dbgline = kmalloc(3*l, GFP_ATOMIC); | ||
272 | if (!dbgline) | ||
273 | return; | ||
274 | for (i = 0; i < l; i++) { | ||
275 | dbgline[3*i] = hex_asc_hi(data[12+i]); | ||
276 | dbgline[3*i+1] = hex_asc_lo(data[12+i]); | ||
277 | dbgline[3*i+2] = ' '; | ||
278 | } | ||
279 | dbgline[3*l-1] = '\0'; | ||
280 | gig_dbg(level, " %s", dbgline); | ||
281 | kfree(dbgline); | ||
282 | if (CAPIMSG_COMMAND(data) == CAPI_DATA_B3 && | ||
283 | (CAPIMSG_SUBCOMMAND(data) == CAPI_REQ || | ||
284 | CAPIMSG_SUBCOMMAND(data) == CAPI_IND) && | ||
285 | CAPIMSG_DATALEN(data) > 0) { | ||
286 | l = CAPIMSG_DATALEN(data); | ||
287 | dbgline = kmalloc(3*l, GFP_ATOMIC); | ||
288 | if (!dbgline) | ||
289 | return; | ||
290 | data += CAPIMSG_LEN(data); | ||
291 | for (i = 0; i < l; i++) { | ||
292 | dbgline[3*i] = hex_asc_hi(data[i]); | ||
293 | dbgline[3*i+1] = hex_asc_lo(data[i]); | ||
294 | dbgline[3*i+2] = ' '; | ||
295 | } | ||
296 | dbgline[3*l-1] = '\0'; | ||
297 | gig_dbg(level, " %s", dbgline); | ||
298 | kfree(dbgline); | ||
299 | } | ||
300 | #endif | ||
301 | } | ||
302 | |||
303 | /* | ||
304 | * format CAPI IE as string | ||
305 | */ | ||
306 | |||
307 | static const char *format_ie(const char *ie) | ||
308 | { | ||
309 | static char result[3*MAX_FMT_IE_LEN]; | ||
310 | int len, count; | ||
311 | char *pout = result; | ||
312 | |||
313 | if (!ie) | ||
314 | return "NULL"; | ||
315 | |||
316 | count = len = ie[0]; | ||
317 | if (count > MAX_FMT_IE_LEN) | ||
318 | count = MAX_FMT_IE_LEN-1; | ||
319 | while (count--) { | ||
320 | *pout++ = hex_asc_hi(*++ie); | ||
321 | *pout++ = hex_asc_lo(*ie); | ||
322 | *pout++ = ' '; | ||
323 | } | ||
324 | if (len > MAX_FMT_IE_LEN) { | ||
325 | *pout++ = '.'; | ||
326 | *pout++ = '.'; | ||
327 | *pout++ = '.'; | ||
328 | } | ||
329 | *--pout = 0; | ||
330 | return result; | ||
331 | } | ||
332 | |||
333 | |||
334 | /* | ||
335 | * driver interface functions | ||
336 | * ========================== | ||
337 | */ | ||
338 | |||
339 | /** | ||
340 | * gigaset_skb_sent() - acknowledge transmission of outgoing skb | ||
341 | * @bcs: B channel descriptor structure. | ||
342 | * @skb: sent data. | ||
343 | * | ||
344 | * Called by hardware module {bas,ser,usb}_gigaset when the data in a | ||
345 | * skb has been successfully sent, for signalling completion to the LL. | ||
346 | */ | ||
347 | void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *dskb) | ||
348 | { | ||
349 | struct cardstate *cs = bcs->cs; | ||
350 | struct gigaset_capi_ctr *iif = cs->iif; | ||
351 | struct gigaset_capi_appl *ap = bcs->ap; | ||
352 | unsigned char *req = skb_mac_header(dskb); | ||
353 | struct sk_buff *cskb; | ||
354 | u16 flags; | ||
355 | |||
356 | /* update statistics */ | ||
357 | ++bcs->trans_up; | ||
358 | |||
359 | if (!ap) { | ||
360 | dev_err(cs->dev, "%s: no application\n", __func__); | ||
361 | return; | ||
362 | } | ||
363 | |||
364 | /* don't send further B3 messages if disconnected */ | ||
365 | if (ap->connected < APCONN_ACTIVE) { | ||
366 | gig_dbg(DEBUG_LLDATA, "disconnected, discarding ack"); | ||
367 | return; | ||
368 | } | ||
369 | |||
370 | /* ToDo: honor unset "delivery confirmation" bit */ | ||
371 | flags = CAPIMSG_FLAGS(req); | ||
372 | |||
373 | /* build DATA_B3_CONF message */ | ||
374 | cskb = alloc_skb(CAPI_DATA_B3_CONF_LEN, GFP_ATOMIC); | ||
375 | if (!cskb) { | ||
376 | dev_err(cs->dev, "%s: out of memory\n", __func__); | ||
377 | return; | ||
378 | } | ||
379 | /* frequent message, avoid _cmsg overhead */ | ||
380 | CAPIMSG_SETLEN(cskb->data, CAPI_DATA_B3_CONF_LEN); | ||
381 | CAPIMSG_SETAPPID(cskb->data, ap->id); | ||
382 | CAPIMSG_SETCOMMAND(cskb->data, CAPI_DATA_B3); | ||
383 | CAPIMSG_SETSUBCOMMAND(cskb->data, CAPI_CONF); | ||
384 | CAPIMSG_SETMSGID(cskb->data, CAPIMSG_MSGID(req)); | ||
385 | CAPIMSG_SETCONTROLLER(cskb->data, iif->ctr.cnr); | ||
386 | CAPIMSG_SETPLCI_PART(cskb->data, bcs->channel + 1); | ||
387 | CAPIMSG_SETNCCI_PART(cskb->data, 1); | ||
388 | CAPIMSG_SETHANDLE_CONF(cskb->data, CAPIMSG_HANDLE_REQ(req)); | ||
389 | if (flags & ~CAPI_FLAGS_DELIVERY_CONFIRMATION) | ||
390 | CAPIMSG_SETINFO_CONF(cskb->data, | ||
391 | CapiFlagsNotSupportedByProtocol); | ||
392 | else | ||
393 | CAPIMSG_SETINFO_CONF(cskb->data, CAPI_NOERROR); | ||
394 | |||
395 | /* emit message */ | ||
396 | dump_rawmsg(DEBUG_LLDATA, "DATA_B3_CONF", cskb->data); | ||
397 | capi_ctr_handle_message(&iif->ctr, ap->id, cskb); | ||
398 | } | ||
399 | EXPORT_SYMBOL_GPL(gigaset_skb_sent); | ||
400 | |||
401 | /** | ||
402 | * gigaset_skb_rcvd() - pass received skb to LL | ||
403 | * @bcs: B channel descriptor structure. | ||
404 | * @skb: received data. | ||
405 | * | ||
406 | * Called by hardware module {bas,ser,usb}_gigaset when user data has | ||
407 | * been successfully received, for passing to the LL. | ||
408 | * Warning: skb must not be accessed anymore! | ||
409 | */ | ||
410 | void gigaset_skb_rcvd(struct bc_state *bcs, struct sk_buff *skb) | ||
411 | { | ||
412 | struct cardstate *cs = bcs->cs; | ||
413 | struct gigaset_capi_ctr *iif = cs->iif; | ||
414 | struct gigaset_capi_appl *ap = bcs->ap; | ||
415 | int len = skb->len; | ||
416 | |||
417 | /* update statistics */ | ||
418 | bcs->trans_down++; | ||
419 | |||
420 | if (!ap) { | ||
421 | dev_err(cs->dev, "%s: no application\n", __func__); | ||
422 | return; | ||
423 | } | ||
424 | |||
425 | /* don't send further B3 messages if disconnected */ | ||
426 | if (ap->connected < APCONN_ACTIVE) { | ||
427 | gig_dbg(DEBUG_LLDATA, "disconnected, discarding data"); | ||
428 | dev_kfree_skb_any(skb); | ||
429 | return; | ||
430 | } | ||
431 | |||
432 | /* | ||
433 | * prepend DATA_B3_IND message to payload | ||
434 | * Parameters: NCCI = 1, all others 0/unused | ||
435 | * frequent message, avoid _cmsg overhead | ||
436 | */ | ||
437 | skb_push(skb, CAPI_DATA_B3_REQ_LEN); | ||
438 | CAPIMSG_SETLEN(skb->data, CAPI_DATA_B3_REQ_LEN); | ||
439 | CAPIMSG_SETAPPID(skb->data, ap->id); | ||
440 | CAPIMSG_SETCOMMAND(skb->data, CAPI_DATA_B3); | ||
441 | CAPIMSG_SETSUBCOMMAND(skb->data, CAPI_IND); | ||
442 | CAPIMSG_SETMSGID(skb->data, ap->nextMessageNumber++); | ||
443 | CAPIMSG_SETCONTROLLER(skb->data, iif->ctr.cnr); | ||
444 | CAPIMSG_SETPLCI_PART(skb->data, bcs->channel + 1); | ||
445 | CAPIMSG_SETNCCI_PART(skb->data, 1); | ||
446 | /* Data parameter not used */ | ||
447 | CAPIMSG_SETDATALEN(skb->data, len); | ||
448 | /* Data handle parameter not used */ | ||
449 | CAPIMSG_SETFLAGS(skb->data, 0); | ||
450 | /* Data64 parameter not present */ | ||
451 | |||
452 | /* emit message */ | ||
453 | dump_rawmsg(DEBUG_LLDATA, "DATA_B3_IND", skb->data); | ||
454 | capi_ctr_handle_message(&iif->ctr, ap->id, skb); | ||
455 | } | ||
456 | EXPORT_SYMBOL_GPL(gigaset_skb_rcvd); | ||
457 | |||
458 | /** | ||
459 | * gigaset_isdn_rcv_err() - signal receive error | ||
460 | * @bcs: B channel descriptor structure. | ||
461 | * | ||
462 | * Called by hardware module {bas,ser,usb}_gigaset when a receive error | ||
463 | * has occurred, for signalling to the LL. | ||
464 | */ | ||
465 | void gigaset_isdn_rcv_err(struct bc_state *bcs) | ||
466 | { | ||
467 | /* if currently ignoring packets, just count down */ | ||
468 | if (bcs->ignore) { | ||
469 | bcs->ignore--; | ||
470 | return; | ||
471 | } | ||
472 | |||
473 | /* update statistics */ | ||
474 | bcs->corrupted++; | ||
475 | |||
476 | /* ToDo: signal error -> LL */ | ||
477 | } | ||
478 | EXPORT_SYMBOL_GPL(gigaset_isdn_rcv_err); | ||
479 | |||
480 | /** | ||
481 | * gigaset_isdn_icall() - signal incoming call | ||
482 | * @at_state: connection state structure. | ||
483 | * | ||
484 | * Called by main module at tasklet level to notify the LL that an incoming | ||
485 | * call has been received. @at_state contains the parameters of the call. | ||
486 | * | ||
487 | * Return value: call disposition (ICALL_*) | ||
488 | */ | ||
489 | int gigaset_isdn_icall(struct at_state_t *at_state) | ||
490 | { | ||
491 | struct cardstate *cs = at_state->cs; | ||
492 | struct bc_state *bcs = at_state->bcs; | ||
493 | struct gigaset_capi_ctr *iif = cs->iif; | ||
494 | struct gigaset_capi_appl *ap; | ||
495 | u32 actCIPmask; | ||
496 | struct sk_buff *skb; | ||
497 | unsigned int msgsize; | ||
498 | int i; | ||
499 | |||
500 | /* | ||
501 | * ToDo: signal calls without a free B channel, too | ||
502 | * (requires a u8 handle for the at_state structure that can | ||
503 | * be stored in the PLCI and used in the CONNECT_RESP message | ||
504 | * handler to retrieve it) | ||
505 | */ | ||
506 | if (!bcs) | ||
507 | return ICALL_IGNORE; | ||
508 | |||
509 | /* prepare CONNECT_IND message, using B channel number as PLCI */ | ||
510 | capi_cmsg_header(&iif->hcmsg, 0, CAPI_CONNECT, CAPI_IND, 0, | ||
511 | iif->ctr.cnr | ((bcs->channel + 1) << 8)); | ||
512 | |||
513 | /* minimum size, all structs empty */ | ||
514 | msgsize = CAPI_CONNECT_IND_BASELEN; | ||
515 | |||
516 | /* Bearer Capability (mandatory) */ | ||
517 | if (at_state->str_var[STR_ZBC]) { | ||
518 | /* pass on BC from Gigaset */ | ||
519 | if (encode_ie(at_state->str_var[STR_ZBC], iif->bc_buf, | ||
520 | MAX_BC_OCTETS) < 0) { | ||
521 | dev_warn(cs->dev, "RING ignored - bad BC %s\n", | ||
522 | at_state->str_var[STR_ZBC]); | ||
523 | return ICALL_IGNORE; | ||
524 | } | ||
525 | |||
526 | /* look up corresponding CIP value */ | ||
527 | iif->hcmsg.CIPValue = 0; /* default if nothing found */ | ||
528 | for (i = 0; i < ARRAY_SIZE(cip2bchlc); i++) | ||
529 | if (cip2bchlc[i].bc != NULL && | ||
530 | cip2bchlc[i].hlc == NULL && | ||
531 | !strcmp(cip2bchlc[i].bc, | ||
532 | at_state->str_var[STR_ZBC])) { | ||
533 | iif->hcmsg.CIPValue = i; | ||
534 | break; | ||
535 | } | ||
536 | } else { | ||
537 | /* no BC (internal call): assume CIP 1 (speech, A-law) */ | ||
538 | iif->hcmsg.CIPValue = 1; | ||
539 | encode_ie(cip2bchlc[1].bc, iif->bc_buf, MAX_BC_OCTETS); | ||
540 | } | ||
541 | iif->hcmsg.BC = iif->bc_buf; | ||
542 | msgsize += iif->hcmsg.BC[0]; | ||
543 | |||
544 | /* High Layer Compatibility (optional) */ | ||
545 | if (at_state->str_var[STR_ZHLC]) { | ||
546 | /* pass on HLC from Gigaset */ | ||
547 | if (encode_ie(at_state->str_var[STR_ZHLC], iif->hlc_buf, | ||
548 | MAX_HLC_OCTETS) < 0) { | ||
549 | dev_warn(cs->dev, "RING ignored - bad HLC %s\n", | ||
550 | at_state->str_var[STR_ZHLC]); | ||
551 | return ICALL_IGNORE; | ||
552 | } | ||
553 | iif->hcmsg.HLC = iif->hlc_buf; | ||
554 | msgsize += iif->hcmsg.HLC[0]; | ||
555 | |||
556 | /* look up corresponding CIP value */ | ||
557 | /* keep BC based CIP value if none found */ | ||
558 | if (at_state->str_var[STR_ZBC]) | ||
559 | for (i = 0; i < ARRAY_SIZE(cip2bchlc); i++) | ||
560 | if (cip2bchlc[i].hlc != NULL && | ||
561 | !strcmp(cip2bchlc[i].hlc, | ||
562 | at_state->str_var[STR_ZHLC]) && | ||
563 | !strcmp(cip2bchlc[i].bc, | ||
564 | at_state->str_var[STR_ZBC])) { | ||
565 | iif->hcmsg.CIPValue = i; | ||
566 | break; | ||
567 | } | ||
568 | } | ||
569 | |||
570 | /* Called Party Number (optional) */ | ||
571 | if (at_state->str_var[STR_ZCPN]) { | ||
572 | i = strlen(at_state->str_var[STR_ZCPN]); | ||
573 | if (i > MAX_NUMBER_DIGITS) { | ||
574 | dev_warn(cs->dev, "RING ignored - bad number %s\n", | ||
575 | at_state->str_var[STR_ZBC]); | ||
576 | return ICALL_IGNORE; | ||
577 | } | ||
578 | iif->cdpty_buf[0] = i + 1; | ||
579 | iif->cdpty_buf[1] = 0x80; /* type / numbering plan unknown */ | ||
580 | memcpy(iif->cdpty_buf+2, at_state->str_var[STR_ZCPN], i); | ||
581 | iif->hcmsg.CalledPartyNumber = iif->cdpty_buf; | ||
582 | msgsize += iif->hcmsg.CalledPartyNumber[0]; | ||
583 | } | ||
584 | |||
585 | /* Calling Party Number (optional) */ | ||
586 | if (at_state->str_var[STR_NMBR]) { | ||
587 | i = strlen(at_state->str_var[STR_NMBR]); | ||
588 | if (i > MAX_NUMBER_DIGITS) { | ||
589 | dev_warn(cs->dev, "RING ignored - bad number %s\n", | ||
590 | at_state->str_var[STR_ZBC]); | ||
591 | return ICALL_IGNORE; | ||
592 | } | ||
593 | iif->cgpty_buf[0] = i + 2; | ||
594 | iif->cgpty_buf[1] = 0x00; /* type / numbering plan unknown */ | ||
595 | iif->cgpty_buf[2] = 0x80; /* pres. allowed, not screened */ | ||
596 | memcpy(iif->cgpty_buf+3, at_state->str_var[STR_NMBR], i); | ||
597 | iif->hcmsg.CallingPartyNumber = iif->cgpty_buf; | ||
598 | msgsize += iif->hcmsg.CallingPartyNumber[0]; | ||
599 | } | ||
600 | |||
601 | /* remaining parameters (not supported, always left NULL): | ||
602 | * - CalledPartySubaddress | ||
603 | * - CallingPartySubaddress | ||
604 | * - AdditionalInfo | ||
605 | * - BChannelinformation | ||
606 | * - Keypadfacility | ||
607 | * - Useruserdata | ||
608 | * - Facilitydataarray | ||
609 | */ | ||
610 | |||
611 | gig_dbg(DEBUG_CMD, "icall: PLCI %x CIP %d BC %s", | ||
612 | iif->hcmsg.adr.adrPLCI, iif->hcmsg.CIPValue, | ||
613 | format_ie(iif->hcmsg.BC)); | ||
614 | gig_dbg(DEBUG_CMD, "icall: HLC %s", | ||
615 | format_ie(iif->hcmsg.HLC)); | ||
616 | gig_dbg(DEBUG_CMD, "icall: CgPty %s", | ||
617 | format_ie(iif->hcmsg.CallingPartyNumber)); | ||
618 | gig_dbg(DEBUG_CMD, "icall: CdPty %s", | ||
619 | format_ie(iif->hcmsg.CalledPartyNumber)); | ||
620 | |||
621 | /* scan application list for matching listeners */ | ||
622 | bcs->ap = NULL; | ||
623 | actCIPmask = 1 | (1 << iif->hcmsg.CIPValue); | ||
624 | list_for_each_entry(ap, &iif->appls, ctrlist) | ||
625 | if (actCIPmask & ap->listenCIPmask) { | ||
626 | /* build CONNECT_IND message for this application */ | ||
627 | iif->hcmsg.ApplId = ap->id; | ||
628 | iif->hcmsg.Messagenumber = ap->nextMessageNumber++; | ||
629 | |||
630 | skb = alloc_skb(msgsize, GFP_ATOMIC); | ||
631 | if (!skb) { | ||
632 | dev_err(cs->dev, "%s: out of memory\n", | ||
633 | __func__); | ||
634 | break; | ||
635 | } | ||
636 | capi_cmsg2message(&iif->hcmsg, __skb_put(skb, msgsize)); | ||
637 | dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg); | ||
638 | |||
639 | /* add to listeners on this B channel, update state */ | ||
640 | ap->bcnext = bcs->ap; | ||
641 | bcs->ap = ap; | ||
642 | bcs->chstate |= CHS_NOTIFY_LL; | ||
643 | ap->connected = APCONN_SETUP; | ||
644 | |||
645 | /* emit message */ | ||
646 | capi_ctr_handle_message(&iif->ctr, ap->id, skb); | ||
647 | } | ||
648 | |||
649 | /* | ||
650 | * Return "accept" if any listeners. | ||
651 | * Gigaset will send ALERTING. | ||
652 | * There doesn't seem to be a way to avoid this. | ||
653 | */ | ||
654 | return bcs->ap ? ICALL_ACCEPT : ICALL_IGNORE; | ||
655 | } | ||
656 | |||
657 | /* | ||
658 | * send a DISCONNECT_IND message to an application | ||
659 | * does not sleep, clobbers the controller's hcmsg structure | ||
660 | */ | ||
661 | static void send_disconnect_ind(struct bc_state *bcs, | ||
662 | struct gigaset_capi_appl *ap, u16 reason) | ||
663 | { | ||
664 | struct cardstate *cs = bcs->cs; | ||
665 | struct gigaset_capi_ctr *iif = cs->iif; | ||
666 | struct sk_buff *skb; | ||
667 | |||
668 | if (ap->connected == APCONN_NONE) | ||
669 | return; | ||
670 | |||
671 | capi_cmsg_header(&iif->hcmsg, ap->id, CAPI_DISCONNECT, CAPI_IND, | ||
672 | ap->nextMessageNumber++, | ||
673 | iif->ctr.cnr | ((bcs->channel + 1) << 8)); | ||
674 | iif->hcmsg.Reason = reason; | ||
675 | skb = alloc_skb(CAPI_DISCONNECT_IND_LEN, GFP_ATOMIC); | ||
676 | if (!skb) { | ||
677 | dev_err(cs->dev, "%s: out of memory\n", __func__); | ||
678 | return; | ||
679 | } | ||
680 | capi_cmsg2message(&iif->hcmsg, __skb_put(skb, CAPI_DISCONNECT_IND_LEN)); | ||
681 | dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg); | ||
682 | ap->connected = APCONN_NONE; | ||
683 | capi_ctr_handle_message(&iif->ctr, ap->id, skb); | ||
684 | } | ||
685 | |||
686 | /* | ||
687 | * send a DISCONNECT_B3_IND message to an application | ||
688 | * Parameters: NCCI = 1, NCPI empty, Reason_B3 = 0 | ||
689 | * does not sleep, clobbers the controller's hcmsg structure | ||
690 | */ | ||
691 | static void send_disconnect_b3_ind(struct bc_state *bcs, | ||
692 | struct gigaset_capi_appl *ap) | ||
693 | { | ||
694 | struct cardstate *cs = bcs->cs; | ||
695 | struct gigaset_capi_ctr *iif = cs->iif; | ||
696 | struct sk_buff *skb; | ||
697 | |||
698 | /* nothing to do if no logical connection active */ | ||
699 | if (ap->connected < APCONN_ACTIVE) | ||
700 | return; | ||
701 | ap->connected = APCONN_SETUP; | ||
702 | |||
703 | capi_cmsg_header(&iif->hcmsg, ap->id, CAPI_DISCONNECT_B3, CAPI_IND, | ||
704 | ap->nextMessageNumber++, | ||
705 | iif->ctr.cnr | ((bcs->channel + 1) << 8) | (1 << 16)); | ||
706 | skb = alloc_skb(CAPI_DISCONNECT_B3_IND_BASELEN, GFP_ATOMIC); | ||
707 | if (!skb) { | ||
708 | dev_err(cs->dev, "%s: out of memory\n", __func__); | ||
709 | return; | ||
710 | } | ||
711 | capi_cmsg2message(&iif->hcmsg, | ||
712 | __skb_put(skb, CAPI_DISCONNECT_B3_IND_BASELEN)); | ||
713 | dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg); | ||
714 | capi_ctr_handle_message(&iif->ctr, ap->id, skb); | ||
715 | } | ||
716 | |||
717 | /** | ||
718 | * gigaset_isdn_connD() - signal D channel connect | ||
719 | * @bcs: B channel descriptor structure. | ||
720 | * | ||
721 | * Called by main module at tasklet level to notify the LL that the D channel | ||
722 | * connection has been established. | ||
723 | */ | ||
724 | void gigaset_isdn_connD(struct bc_state *bcs) | ||
725 | { | ||
726 | struct cardstate *cs = bcs->cs; | ||
727 | struct gigaset_capi_ctr *iif = cs->iif; | ||
728 | struct gigaset_capi_appl *ap = bcs->ap; | ||
729 | struct sk_buff *skb; | ||
730 | unsigned int msgsize; | ||
731 | |||
732 | if (!ap) { | ||
733 | dev_err(cs->dev, "%s: no application\n", __func__); | ||
734 | return; | ||
735 | } | ||
736 | while (ap->bcnext) { | ||
737 | /* this should never happen */ | ||
738 | dev_warn(cs->dev, "%s: dropping extra application %u\n", | ||
739 | __func__, ap->bcnext->id); | ||
740 | send_disconnect_ind(bcs, ap->bcnext, | ||
741 | CapiCallGivenToOtherApplication); | ||
742 | ap->bcnext = ap->bcnext->bcnext; | ||
743 | } | ||
744 | if (ap->connected == APCONN_NONE) { | ||
745 | dev_warn(cs->dev, "%s: application %u not connected\n", | ||
746 | __func__, ap->id); | ||
747 | return; | ||
748 | } | ||
749 | |||
750 | /* prepare CONNECT_ACTIVE_IND message | ||
751 | * Note: LLC not supported by device | ||
752 | */ | ||
753 | capi_cmsg_header(&iif->hcmsg, ap->id, CAPI_CONNECT_ACTIVE, CAPI_IND, | ||
754 | ap->nextMessageNumber++, | ||
755 | iif->ctr.cnr | ((bcs->channel + 1) << 8)); | ||
756 | |||
757 | /* minimum size, all structs empty */ | ||
758 | msgsize = CAPI_CONNECT_ACTIVE_IND_BASELEN; | ||
759 | |||
760 | /* ToDo: set parameter: Connected number | ||
761 | * (requires ev-layer state machine extension to collect | ||
762 | * ZCON device reply) | ||
763 | */ | ||
764 | |||
765 | /* build and emit CONNECT_ACTIVE_IND message */ | ||
766 | skb = alloc_skb(msgsize, GFP_ATOMIC); | ||
767 | if (!skb) { | ||
768 | dev_err(cs->dev, "%s: out of memory\n", __func__); | ||
769 | return; | ||
770 | } | ||
771 | capi_cmsg2message(&iif->hcmsg, __skb_put(skb, msgsize)); | ||
772 | dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg); | ||
773 | capi_ctr_handle_message(&iif->ctr, ap->id, skb); | ||
774 | } | ||
775 | |||
776 | /** | ||
777 | * gigaset_isdn_hupD() - signal D channel hangup | ||
778 | * @bcs: B channel descriptor structure. | ||
779 | * | ||
780 | * Called by main module at tasklet level to notify the LL that the D channel | ||
781 | * connection has been shut down. | ||
782 | */ | ||
783 | void gigaset_isdn_hupD(struct bc_state *bcs) | ||
784 | { | ||
785 | struct gigaset_capi_appl *ap; | ||
786 | |||
787 | /* | ||
788 | * ToDo: pass on reason code reported by device | ||
789 | * (requires ev-layer state machine extension to collect | ||
790 | * ZCAU device reply) | ||
791 | */ | ||
792 | for (ap = bcs->ap; ap != NULL; ap = ap->bcnext) { | ||
793 | send_disconnect_b3_ind(bcs, ap); | ||
794 | send_disconnect_ind(bcs, ap, 0); | ||
795 | } | ||
796 | bcs->ap = NULL; | ||
797 | } | ||
798 | |||
799 | /** | ||
800 | * gigaset_isdn_connB() - signal B channel connect | ||
801 | * @bcs: B channel descriptor structure. | ||
802 | * | ||
803 | * Called by main module at tasklet level to notify the LL that the B channel | ||
804 | * connection has been established. | ||
805 | */ | ||
806 | void gigaset_isdn_connB(struct bc_state *bcs) | ||
807 | { | ||
808 | struct cardstate *cs = bcs->cs; | ||
809 | struct gigaset_capi_ctr *iif = cs->iif; | ||
810 | struct gigaset_capi_appl *ap = bcs->ap; | ||
811 | struct sk_buff *skb; | ||
812 | unsigned int msgsize; | ||
813 | u8 command; | ||
814 | |||
815 | if (!ap) { | ||
816 | dev_err(cs->dev, "%s: no application\n", __func__); | ||
817 | return; | ||
818 | } | ||
819 | while (ap->bcnext) { | ||
820 | /* this should never happen */ | ||
821 | dev_warn(cs->dev, "%s: dropping extra application %u\n", | ||
822 | __func__, ap->bcnext->id); | ||
823 | send_disconnect_ind(bcs, ap->bcnext, | ||
824 | CapiCallGivenToOtherApplication); | ||
825 | ap->bcnext = ap->bcnext->bcnext; | ||
826 | } | ||
827 | if (!ap->connected) { | ||
828 | dev_warn(cs->dev, "%s: application %u not connected\n", | ||
829 | __func__, ap->id); | ||
830 | return; | ||
831 | } | ||
832 | |||
833 | /* | ||
834 | * emit CONNECT_B3_ACTIVE_IND if we already got CONNECT_B3_REQ; | ||
835 | * otherwise we have to emit CONNECT_B3_IND first, and follow up with | ||
836 | * CONNECT_B3_ACTIVE_IND in reply to CONNECT_B3_RESP | ||
837 | * Parameters in both cases always: NCCI = 1, NCPI empty | ||
838 | */ | ||
839 | if (ap->connected >= APCONN_ACTIVE) { | ||
840 | command = CAPI_CONNECT_B3_ACTIVE; | ||
841 | msgsize = CAPI_CONNECT_B3_ACTIVE_IND_BASELEN; | ||
842 | } else { | ||
843 | command = CAPI_CONNECT_B3; | ||
844 | msgsize = CAPI_CONNECT_B3_IND_BASELEN; | ||
845 | } | ||
846 | capi_cmsg_header(&iif->hcmsg, ap->id, command, CAPI_IND, | ||
847 | ap->nextMessageNumber++, | ||
848 | iif->ctr.cnr | ((bcs->channel + 1) << 8) | (1 << 16)); | ||
849 | skb = alloc_skb(msgsize, GFP_ATOMIC); | ||
850 | if (!skb) { | ||
851 | dev_err(cs->dev, "%s: out of memory\n", __func__); | ||
852 | return; | ||
853 | } | ||
854 | capi_cmsg2message(&iif->hcmsg, __skb_put(skb, msgsize)); | ||
855 | dump_cmsg(DEBUG_CMD, __func__, &iif->hcmsg); | ||
856 | ap->connected = APCONN_ACTIVE; | ||
857 | capi_ctr_handle_message(&iif->ctr, ap->id, skb); | ||
858 | } | ||
859 | |||
860 | /** | ||
861 | * gigaset_isdn_hupB() - signal B channel hangup | ||
862 | * @bcs: B channel descriptor structure. | ||
863 | * | ||
864 | * Called by main module to notify the LL that the B channel connection has | ||
865 | * been shut down. | ||
866 | */ | ||
867 | void gigaset_isdn_hupB(struct bc_state *bcs) | ||
868 | { | ||
869 | struct cardstate *cs = bcs->cs; | ||
870 | struct gigaset_capi_appl *ap = bcs->ap; | ||
871 | |||
872 | /* ToDo: assure order of DISCONNECT_B3_IND and DISCONNECT_IND ? */ | ||
873 | |||
874 | if (!ap) { | ||
875 | dev_err(cs->dev, "%s: no application\n", __func__); | ||
876 | return; | ||
877 | } | ||
878 | |||
879 | send_disconnect_b3_ind(bcs, ap); | ||
880 | } | ||
881 | |||
882 | /** | ||
883 | * gigaset_isdn_start() - signal device availability | ||
884 | * @cs: device descriptor structure. | ||
885 | * | ||
886 | * Called by main module to notify the LL that the device is available for | ||
887 | * use. | ||
888 | */ | ||
889 | void gigaset_isdn_start(struct cardstate *cs) | ||
890 | { | ||
891 | struct gigaset_capi_ctr *iif = cs->iif; | ||
892 | |||
893 | /* fill profile data: manufacturer name */ | ||
894 | strcpy(iif->ctr.manu, "Siemens"); | ||
895 | /* CAPI and device version */ | ||
896 | iif->ctr.version.majorversion = 2; /* CAPI 2.0 */ | ||
897 | iif->ctr.version.minorversion = 0; | ||
898 | /* ToDo: check/assert cs->gotfwver? */ | ||
899 | iif->ctr.version.majormanuversion = cs->fwver[0]; | ||
900 | iif->ctr.version.minormanuversion = cs->fwver[1]; | ||
901 | /* number of B channels supported */ | ||
902 | iif->ctr.profile.nbchannel = cs->channels; | ||
903 | /* global options: internal controller, supplementary services */ | ||
904 | iif->ctr.profile.goptions = 0x11; | ||
905 | /* B1 protocols: 64 kbit/s HDLC or transparent */ | ||
906 | iif->ctr.profile.support1 = 0x03; | ||
907 | /* B2 protocols: transparent only */ | ||
908 | /* ToDo: X.75 SLP ? */ | ||
909 | iif->ctr.profile.support2 = 0x02; | ||
910 | /* B3 protocols: transparent only */ | ||
911 | iif->ctr.profile.support3 = 0x01; | ||
912 | /* no serial number */ | ||
913 | strcpy(iif->ctr.serial, "0"); | ||
914 | capi_ctr_ready(&iif->ctr); | ||
915 | } | ||
916 | |||
917 | /** | ||
918 | * gigaset_isdn_stop() - signal device unavailability | ||
919 | * @cs: device descriptor structure. | ||
920 | * | ||
921 | * Called by main module to notify the LL that the device is no longer | ||
922 | * available for use. | ||
923 | */ | ||
924 | void gigaset_isdn_stop(struct cardstate *cs) | ||
925 | { | ||
926 | struct gigaset_capi_ctr *iif = cs->iif; | ||
927 | capi_ctr_down(&iif->ctr); | ||
928 | } | ||
929 | |||
930 | /* | ||
931 | * kernel CAPI callback methods | ||
932 | * ============================ | ||
933 | */ | ||
934 | |||
935 | /* | ||
936 | * load firmware | ||
937 | */ | ||
938 | static int gigaset_load_firmware(struct capi_ctr *ctr, capiloaddata *data) | ||
939 | { | ||
940 | struct cardstate *cs = ctr->driverdata; | ||
941 | |||
942 | /* AVM specific operation, not needed for Gigaset -- ignore */ | ||
943 | dev_notice(cs->dev, "load_firmware ignored\n"); | ||
944 | |||
945 | return 0; | ||
946 | } | ||
947 | |||
948 | /* | ||
949 | * reset (deactivate) controller | ||
950 | */ | ||
951 | static void gigaset_reset_ctr(struct capi_ctr *ctr) | ||
952 | { | ||
953 | struct cardstate *cs = ctr->driverdata; | ||
954 | |||
955 | /* AVM specific operation, not needed for Gigaset -- ignore */ | ||
956 | dev_notice(cs->dev, "reset_ctr ignored\n"); | ||
957 | } | ||
958 | |||
959 | /* | ||
960 | * register CAPI application | ||
961 | */ | ||
962 | static void gigaset_register_appl(struct capi_ctr *ctr, u16 appl, | ||
963 | capi_register_params *rp) | ||
964 | { | ||
965 | struct gigaset_capi_ctr *iif | ||
966 | = container_of(ctr, struct gigaset_capi_ctr, ctr); | ||
967 | struct cardstate *cs = ctr->driverdata; | ||
968 | struct gigaset_capi_appl *ap; | ||
969 | |||
970 | list_for_each_entry(ap, &iif->appls, ctrlist) | ||
971 | if (ap->id == appl) { | ||
972 | dev_notice(cs->dev, | ||
973 | "application %u already registered\n", appl); | ||
974 | return; | ||
975 | } | ||
976 | |||
977 | ap = kzalloc(sizeof(*ap), GFP_KERNEL); | ||
978 | if (!ap) { | ||
979 | dev_err(cs->dev, "%s: out of memory\n", __func__); | ||
980 | return; | ||
981 | } | ||
982 | ap->id = appl; | ||
983 | |||
984 | list_add(&ap->ctrlist, &iif->appls); | ||
985 | } | ||
986 | |||
987 | /* | ||
988 | * release CAPI application | ||
989 | */ | ||
990 | static void gigaset_release_appl(struct capi_ctr *ctr, u16 appl) | ||
991 | { | ||
992 | struct gigaset_capi_ctr *iif | ||
993 | = container_of(ctr, struct gigaset_capi_ctr, ctr); | ||
994 | struct cardstate *cs = iif->ctr.driverdata; | ||
995 | struct gigaset_capi_appl *ap, *tmp; | ||
996 | |||
997 | list_for_each_entry_safe(ap, tmp, &iif->appls, ctrlist) | ||
998 | if (ap->id == appl) { | ||
999 | if (ap->connected != APCONN_NONE) { | ||
1000 | dev_err(cs->dev, | ||
1001 | "%s: application %u still connected\n", | ||
1002 | __func__, ap->id); | ||
1003 | /* ToDo: clear active connection */ | ||
1004 | } | ||
1005 | list_del(&ap->ctrlist); | ||
1006 | kfree(ap); | ||
1007 | } | ||
1008 | |||
1009 | } | ||
1010 | |||
1011 | /* | ||
1012 | * ===================================================================== | ||
1013 | * outgoing CAPI message handler | ||
1014 | * ===================================================================== | ||
1015 | */ | ||
1016 | |||
1017 | /* | ||
1018 | * helper function: emit reply message with given Info value | ||
1019 | */ | ||
1020 | static void send_conf(struct gigaset_capi_ctr *iif, | ||
1021 | struct gigaset_capi_appl *ap, | ||
1022 | struct sk_buff *skb, | ||
1023 | u16 info) | ||
1024 | { | ||
1025 | /* | ||
1026 | * _CONF replies always only have NCCI and Info parameters | ||
1027 | * so they'll fit into the _REQ message skb | ||
1028 | */ | ||
1029 | capi_cmsg_answer(&iif->acmsg); | ||
1030 | iif->acmsg.Info = info; | ||
1031 | capi_cmsg2message(&iif->acmsg, skb->data); | ||
1032 | __skb_trim(skb, CAPI_STDCONF_LEN); | ||
1033 | dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); | ||
1034 | capi_ctr_handle_message(&iif->ctr, ap->id, skb); | ||
1035 | } | ||
1036 | |||
1037 | /* | ||
1038 | * process FACILITY_REQ message | ||
1039 | */ | ||
1040 | static void do_facility_req(struct gigaset_capi_ctr *iif, | ||
1041 | struct gigaset_capi_appl *ap, | ||
1042 | struct sk_buff *skb) | ||
1043 | { | ||
1044 | struct cardstate *cs = iif->ctr.driverdata; | ||
1045 | _cmsg *cmsg = &iif->acmsg; | ||
1046 | struct sk_buff *cskb; | ||
1047 | u8 *pparam; | ||
1048 | unsigned int msgsize = CAPI_FACILITY_CONF_BASELEN; | ||
1049 | u16 function, info; | ||
1050 | static u8 confparam[10]; /* max. 9 octets + length byte */ | ||
1051 | |||
1052 | /* decode message */ | ||
1053 | capi_message2cmsg(cmsg, skb->data); | ||
1054 | dump_cmsg(DEBUG_CMD, __func__, cmsg); | ||
1055 | |||
1056 | /* | ||
1057 | * Facility Request Parameter is not decoded by capi_message2cmsg() | ||
1058 | * encoding depends on Facility Selector | ||
1059 | */ | ||
1060 | switch (cmsg->FacilitySelector) { | ||
1061 | case CAPI_FACILITY_DTMF: /* ToDo */ | ||
1062 | info = CapiFacilityNotSupported; | ||
1063 | confparam[0] = 2; /* length */ | ||
1064 | /* DTMF information: Unknown DTMF request */ | ||
1065 | capimsg_setu16(confparam, 1, 2); | ||
1066 | break; | ||
1067 | |||
1068 | case CAPI_FACILITY_V42BIS: /* not supported */ | ||
1069 | info = CapiFacilityNotSupported; | ||
1070 | confparam[0] = 2; /* length */ | ||
1071 | /* V.42 bis information: not available */ | ||
1072 | capimsg_setu16(confparam, 1, 1); | ||
1073 | break; | ||
1074 | |||
1075 | case CAPI_FACILITY_SUPPSVC: | ||
1076 | /* decode Function parameter */ | ||
1077 | pparam = cmsg->FacilityRequestParameter; | ||
1078 | if (pparam == NULL || *pparam < 2) { | ||
1079 | dev_notice(cs->dev, "%s: %s missing\n", "FACILITY_REQ", | ||
1080 | "Facility Request Parameter"); | ||
1081 | send_conf(iif, ap, skb, CapiIllMessageParmCoding); | ||
1082 | return; | ||
1083 | } | ||
1084 | function = CAPIMSG_U16(pparam, 1); | ||
1085 | switch (function) { | ||
1086 | case CAPI_SUPPSVC_GETSUPPORTED: | ||
1087 | info = CapiSuccess; | ||
1088 | /* Supplementary Service specific parameter */ | ||
1089 | confparam[3] = 6; /* length */ | ||
1090 | /* Supplementary services info: Success */ | ||
1091 | capimsg_setu16(confparam, 4, CapiSuccess); | ||
1092 | /* Supported Services: none */ | ||
1093 | capimsg_setu32(confparam, 6, 0); | ||
1094 | break; | ||
1095 | /* ToDo: add supported services */ | ||
1096 | default: | ||
1097 | info = CapiFacilitySpecificFunctionNotSupported; | ||
1098 | /* Supplementary Service specific parameter */ | ||
1099 | confparam[3] = 2; /* length */ | ||
1100 | /* Supplementary services info: not supported */ | ||
1101 | capimsg_setu16(confparam, 4, | ||
1102 | CapiSupplementaryServiceNotSupported); | ||
1103 | } | ||
1104 | |||
1105 | /* Facility confirmation parameter */ | ||
1106 | confparam[0] = confparam[3] + 3; /* total length */ | ||
1107 | /* Function: copy from _REQ message */ | ||
1108 | capimsg_setu16(confparam, 1, function); | ||
1109 | /* Supplementary Service specific parameter already set above */ | ||
1110 | break; | ||
1111 | |||
1112 | case CAPI_FACILITY_WAKEUP: /* ToDo */ | ||
1113 | info = CapiFacilityNotSupported; | ||
1114 | confparam[0] = 2; /* length */ | ||
1115 | /* Number of accepted awake request parameters: 0 */ | ||
1116 | capimsg_setu16(confparam, 1, 0); | ||
1117 | break; | ||
1118 | |||
1119 | default: | ||
1120 | info = CapiFacilityNotSupported; | ||
1121 | confparam[0] = 0; /* empty struct */ | ||
1122 | } | ||
1123 | |||
1124 | /* send FACILITY_CONF with given Info and confirmation parameter */ | ||
1125 | capi_cmsg_answer(cmsg); | ||
1126 | cmsg->Info = info; | ||
1127 | cmsg->FacilityConfirmationParameter = confparam; | ||
1128 | msgsize += confparam[0]; /* length */ | ||
1129 | cskb = alloc_skb(msgsize, GFP_ATOMIC); | ||
1130 | if (!cskb) { | ||
1131 | dev_err(cs->dev, "%s: out of memory\n", __func__); | ||
1132 | return; | ||
1133 | } | ||
1134 | capi_cmsg2message(cmsg, __skb_put(cskb, msgsize)); | ||
1135 | dump_cmsg(DEBUG_CMD, __func__, cmsg); | ||
1136 | capi_ctr_handle_message(&iif->ctr, ap->id, cskb); | ||
1137 | } | ||
1138 | |||
1139 | |||
1140 | /* | ||
1141 | * process LISTEN_REQ message | ||
1142 | * just store the masks in the application data structure | ||
1143 | */ | ||
1144 | static void do_listen_req(struct gigaset_capi_ctr *iif, | ||
1145 | struct gigaset_capi_appl *ap, | ||
1146 | struct sk_buff *skb) | ||
1147 | { | ||
1148 | /* decode message */ | ||
1149 | capi_message2cmsg(&iif->acmsg, skb->data); | ||
1150 | dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); | ||
1151 | |||
1152 | /* store listening parameters */ | ||
1153 | ap->listenInfoMask = iif->acmsg.InfoMask; | ||
1154 | ap->listenCIPmask = iif->acmsg.CIPmask; | ||
1155 | send_conf(iif, ap, skb, CapiSuccess); | ||
1156 | } | ||
1157 | |||
1158 | /* | ||
1159 | * process ALERT_REQ message | ||
1160 | * nothing to do, Gigaset always alerts anyway | ||
1161 | */ | ||
1162 | static void do_alert_req(struct gigaset_capi_ctr *iif, | ||
1163 | struct gigaset_capi_appl *ap, | ||
1164 | struct sk_buff *skb) | ||
1165 | { | ||
1166 | /* decode message */ | ||
1167 | capi_message2cmsg(&iif->acmsg, skb->data); | ||
1168 | dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); | ||
1169 | send_conf(iif, ap, skb, CapiAlertAlreadySent); | ||
1170 | } | ||
1171 | |||
1172 | /* | ||
1173 | * process CONNECT_REQ message | ||
1174 | * allocate a B channel, prepare dial commands, queue a DIAL event, | ||
1175 | * emit CONNECT_CONF reply | ||
1176 | */ | ||
1177 | static void do_connect_req(struct gigaset_capi_ctr *iif, | ||
1178 | struct gigaset_capi_appl *ap, | ||
1179 | struct sk_buff *skb) | ||
1180 | { | ||
1181 | struct cardstate *cs = iif->ctr.driverdata; | ||
1182 | _cmsg *cmsg = &iif->acmsg; | ||
1183 | struct bc_state *bcs; | ||
1184 | char **commands; | ||
1185 | char *s; | ||
1186 | u8 *pp; | ||
1187 | int i, l; | ||
1188 | u16 info; | ||
1189 | |||
1190 | /* decode message */ | ||
1191 | capi_message2cmsg(cmsg, skb->data); | ||
1192 | dump_cmsg(DEBUG_CMD, __func__, cmsg); | ||
1193 | |||
1194 | /* get free B channel & construct PLCI */ | ||
1195 | bcs = gigaset_get_free_channel(cs); | ||
1196 | if (!bcs) { | ||
1197 | dev_notice(cs->dev, "%s: no B channel available\n", | ||
1198 | "CONNECT_REQ"); | ||
1199 | send_conf(iif, ap, skb, CapiNoPlciAvailable); | ||
1200 | return; | ||
1201 | } | ||
1202 | ap->bcnext = NULL; | ||
1203 | bcs->ap = ap; | ||
1204 | cmsg->adr.adrPLCI |= (bcs->channel + 1) << 8; | ||
1205 | |||
1206 | /* build command table */ | ||
1207 | commands = kzalloc(AT_NUM*(sizeof *commands), GFP_KERNEL); | ||
1208 | if (!commands) | ||
1209 | goto oom; | ||
1210 | |||
1211 | /* encode parameter: Called party number */ | ||
1212 | pp = cmsg->CalledPartyNumber; | ||
1213 | if (pp == NULL || *pp == 0) { | ||
1214 | dev_notice(cs->dev, "%s: %s missing\n", | ||
1215 | "CONNECT_REQ", "Called party number"); | ||
1216 | info = CapiIllMessageParmCoding; | ||
1217 | goto error; | ||
1218 | } | ||
1219 | l = *pp++; | ||
1220 | /* check type of number/numbering plan byte */ | ||
1221 | switch (*pp) { | ||
1222 | case 0x80: /* unknown type / unknown numbering plan */ | ||
1223 | case 0x81: /* unknown type / ISDN/Telephony numbering plan */ | ||
1224 | break; | ||
1225 | default: /* others: warn about potential misinterpretation */ | ||
1226 | dev_notice(cs->dev, "%s: %s type/plan 0x%02x unsupported\n", | ||
1227 | "CONNECT_REQ", "Called party number", *pp); | ||
1228 | } | ||
1229 | pp++; | ||
1230 | l--; | ||
1231 | /* translate "**" internal call prefix to CTP value */ | ||
1232 | if (l >= 2 && pp[0] == '*' && pp[1] == '*') { | ||
1233 | s = "^SCTP=0\r"; | ||
1234 | pp += 2; | ||
1235 | l -= 2; | ||
1236 | } else { | ||
1237 | s = "^SCTP=1\r"; | ||
1238 | } | ||
1239 | commands[AT_TYPE] = kstrdup(s, GFP_KERNEL); | ||
1240 | if (!commands[AT_TYPE]) | ||
1241 | goto oom; | ||
1242 | commands[AT_DIAL] = kmalloc(l+3, GFP_KERNEL); | ||
1243 | if (!commands[AT_DIAL]) | ||
1244 | goto oom; | ||
1245 | snprintf(commands[AT_DIAL], l+3, "D%.*s\r", l, pp); | ||
1246 | |||
1247 | /* encode parameter: Calling party number */ | ||
1248 | pp = cmsg->CallingPartyNumber; | ||
1249 | if (pp != NULL && *pp > 0) { | ||
1250 | l = *pp++; | ||
1251 | |||
1252 | /* check type of number/numbering plan byte */ | ||
1253 | /* ToDo: allow for/handle Ext=1? */ | ||
1254 | switch (*pp) { | ||
1255 | case 0x00: /* unknown type / unknown numbering plan */ | ||
1256 | case 0x01: /* unknown type / ISDN/Telephony num. plan */ | ||
1257 | break; | ||
1258 | default: | ||
1259 | dev_notice(cs->dev, | ||
1260 | "%s: %s type/plan 0x%02x unsupported\n", | ||
1261 | "CONNECT_REQ", "Calling party number", *pp); | ||
1262 | } | ||
1263 | pp++; | ||
1264 | l--; | ||
1265 | |||
1266 | /* check presentation indicator */ | ||
1267 | if (!l) { | ||
1268 | dev_notice(cs->dev, "%s: %s IE truncated\n", | ||
1269 | "CONNECT_REQ", "Calling party number"); | ||
1270 | info = CapiIllMessageParmCoding; | ||
1271 | goto error; | ||
1272 | } | ||
1273 | switch (*pp & 0xfc) { /* ignore Screening indicator */ | ||
1274 | case 0x80: /* Presentation allowed */ | ||
1275 | s = "^SCLIP=1\r"; | ||
1276 | break; | ||
1277 | case 0xa0: /* Presentation restricted */ | ||
1278 | s = "^SCLIP=0\r"; | ||
1279 | break; | ||
1280 | default: | ||
1281 | dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", | ||
1282 | "CONNECT_REQ", | ||
1283 | "Presentation/Screening indicator", | ||
1284 | *pp); | ||
1285 | s = "^SCLIP=1\r"; | ||
1286 | } | ||
1287 | commands[AT_CLIP] = kstrdup(s, GFP_KERNEL); | ||
1288 | if (!commands[AT_CLIP]) | ||
1289 | goto oom; | ||
1290 | pp++; | ||
1291 | l--; | ||
1292 | |||
1293 | if (l) { | ||
1294 | /* number */ | ||
1295 | commands[AT_MSN] = kmalloc(l+8, GFP_KERNEL); | ||
1296 | if (!commands[AT_MSN]) | ||
1297 | goto oom; | ||
1298 | snprintf(commands[AT_MSN], l+8, "^SMSN=%*s\r", l, pp); | ||
1299 | } | ||
1300 | } | ||
1301 | |||
1302 | /* check parameter: CIP Value */ | ||
1303 | if (cmsg->CIPValue >= ARRAY_SIZE(cip2bchlc) || | ||
1304 | (cmsg->CIPValue > 0 && cip2bchlc[cmsg->CIPValue].bc == NULL)) { | ||
1305 | dev_notice(cs->dev, "%s: unknown CIP value %d\n", | ||
1306 | "CONNECT_REQ", cmsg->CIPValue); | ||
1307 | info = CapiCipValueUnknown; | ||
1308 | goto error; | ||
1309 | } | ||
1310 | |||
1311 | /* check/encode parameter: BC */ | ||
1312 | if (cmsg->BC && cmsg->BC[0]) { | ||
1313 | /* explicit BC overrides CIP */ | ||
1314 | l = 2*cmsg->BC[0] + 7; | ||
1315 | commands[AT_BC] = kmalloc(l, GFP_KERNEL); | ||
1316 | if (!commands[AT_BC]) | ||
1317 | goto oom; | ||
1318 | strcpy(commands[AT_BC], "^SBC="); | ||
1319 | decode_ie(cmsg->BC, commands[AT_BC]+5); | ||
1320 | strcpy(commands[AT_BC] + l - 2, "\r"); | ||
1321 | } else if (cip2bchlc[cmsg->CIPValue].bc) { | ||
1322 | l = strlen(cip2bchlc[cmsg->CIPValue].bc) + 7; | ||
1323 | commands[AT_BC] = kmalloc(l, GFP_KERNEL); | ||
1324 | if (!commands[AT_BC]) | ||
1325 | goto oom; | ||
1326 | snprintf(commands[AT_BC], l, "^SBC=%s\r", | ||
1327 | cip2bchlc[cmsg->CIPValue].bc); | ||
1328 | } | ||
1329 | |||
1330 | /* check/encode parameter: HLC */ | ||
1331 | if (cmsg->HLC && cmsg->HLC[0]) { | ||
1332 | /* explicit HLC overrides CIP */ | ||
1333 | l = 2*cmsg->HLC[0] + 7; | ||
1334 | commands[AT_HLC] = kmalloc(l, GFP_KERNEL); | ||
1335 | if (!commands[AT_HLC]) | ||
1336 | goto oom; | ||
1337 | strcpy(commands[AT_HLC], "^SHLC="); | ||
1338 | decode_ie(cmsg->HLC, commands[AT_HLC]+5); | ||
1339 | strcpy(commands[AT_HLC] + l - 2, "\r"); | ||
1340 | } else if (cip2bchlc[cmsg->CIPValue].hlc) { | ||
1341 | l = strlen(cip2bchlc[cmsg->CIPValue].hlc) + 7; | ||
1342 | commands[AT_HLC] = kmalloc(l, GFP_KERNEL); | ||
1343 | if (!commands[AT_HLC]) | ||
1344 | goto oom; | ||
1345 | snprintf(commands[AT_HLC], l, "^SHLC=%s\r", | ||
1346 | cip2bchlc[cmsg->CIPValue].hlc); | ||
1347 | } | ||
1348 | |||
1349 | /* check/encode parameter: B Protocol */ | ||
1350 | if (cmsg->BProtocol == CAPI_DEFAULT) { | ||
1351 | bcs->proto2 = L2_HDLC; | ||
1352 | dev_warn(cs->dev, | ||
1353 | "B2 Protocol X.75 SLP unsupported, using Transparent\n"); | ||
1354 | } else { | ||
1355 | switch (cmsg->B1protocol) { | ||
1356 | case 0: | ||
1357 | bcs->proto2 = L2_HDLC; | ||
1358 | break; | ||
1359 | case 1: | ||
1360 | bcs->proto2 = L2_BITSYNC; | ||
1361 | break; | ||
1362 | default: | ||
1363 | dev_warn(cs->dev, | ||
1364 | "B1 Protocol %u unsupported, using Transparent\n", | ||
1365 | cmsg->B1protocol); | ||
1366 | bcs->proto2 = L2_BITSYNC; | ||
1367 | } | ||
1368 | if (cmsg->B2protocol != 1) | ||
1369 | dev_warn(cs->dev, | ||
1370 | "B2 Protocol %u unsupported, using Transparent\n", | ||
1371 | cmsg->B2protocol); | ||
1372 | if (cmsg->B3protocol != 0) | ||
1373 | dev_warn(cs->dev, | ||
1374 | "B3 Protocol %u unsupported, using Transparent\n", | ||
1375 | cmsg->B3protocol); | ||
1376 | ignore_cstruct_param(cs, cmsg->B1configuration, | ||
1377 | "CONNECT_REQ", "B1 Configuration"); | ||
1378 | ignore_cstruct_param(cs, cmsg->B2configuration, | ||
1379 | "CONNECT_REQ", "B2 Configuration"); | ||
1380 | ignore_cstruct_param(cs, cmsg->B3configuration, | ||
1381 | "CONNECT_REQ", "B3 Configuration"); | ||
1382 | } | ||
1383 | commands[AT_PROTO] = kmalloc(9, GFP_KERNEL); | ||
1384 | if (!commands[AT_PROTO]) | ||
1385 | goto oom; | ||
1386 | snprintf(commands[AT_PROTO], 9, "^SBPR=%u\r", bcs->proto2); | ||
1387 | |||
1388 | /* ToDo: check/encode remaining parameters */ | ||
1389 | ignore_cstruct_param(cs, cmsg->CalledPartySubaddress, | ||
1390 | "CONNECT_REQ", "Called pty subaddr"); | ||
1391 | ignore_cstruct_param(cs, cmsg->CallingPartySubaddress, | ||
1392 | "CONNECT_REQ", "Calling pty subaddr"); | ||
1393 | ignore_cstruct_param(cs, cmsg->LLC, | ||
1394 | "CONNECT_REQ", "LLC"); | ||
1395 | if (cmsg->AdditionalInfo != CAPI_DEFAULT) { | ||
1396 | ignore_cstruct_param(cs, cmsg->BChannelinformation, | ||
1397 | "CONNECT_REQ", "B Channel Information"); | ||
1398 | ignore_cstruct_param(cs, cmsg->Keypadfacility, | ||
1399 | "CONNECT_REQ", "Keypad Facility"); | ||
1400 | ignore_cstruct_param(cs, cmsg->Useruserdata, | ||
1401 | "CONNECT_REQ", "User-User Data"); | ||
1402 | ignore_cstruct_param(cs, cmsg->Facilitydataarray, | ||
1403 | "CONNECT_REQ", "Facility Data Array"); | ||
1404 | } | ||
1405 | |||
1406 | /* encode parameter: B channel to use */ | ||
1407 | commands[AT_ISO] = kmalloc(9, GFP_KERNEL); | ||
1408 | if (!commands[AT_ISO]) | ||
1409 | goto oom; | ||
1410 | snprintf(commands[AT_ISO], 9, "^SISO=%u\r", | ||
1411 | (unsigned) bcs->channel + 1); | ||
1412 | |||
1413 | /* queue & schedule EV_DIAL event */ | ||
1414 | if (!gigaset_add_event(cs, &bcs->at_state, EV_DIAL, commands, | ||
1415 | bcs->at_state.seq_index, NULL)) { | ||
1416 | info = CAPI_MSGOSRESOURCEERR; | ||
1417 | goto error; | ||
1418 | } | ||
1419 | gigaset_schedule_event(cs); | ||
1420 | ap->connected = APCONN_SETUP; | ||
1421 | send_conf(iif, ap, skb, CapiSuccess); | ||
1422 | return; | ||
1423 | |||
1424 | oom: | ||
1425 | dev_err(cs->dev, "%s: out of memory\n", __func__); | ||
1426 | info = CAPI_MSGOSRESOURCEERR; | ||
1427 | error: | ||
1428 | if (commands) | ||
1429 | for (i = 0; i < AT_NUM; i++) | ||
1430 | kfree(commands[i]); | ||
1431 | kfree(commands); | ||
1432 | gigaset_free_channel(bcs); | ||
1433 | send_conf(iif, ap, skb, info); | ||
1434 | } | ||
1435 | |||
1436 | /* | ||
1437 | * process CONNECT_RESP message | ||
1438 | * checks protocol parameters and queues an ACCEPT or HUP event | ||
1439 | */ | ||
1440 | static void do_connect_resp(struct gigaset_capi_ctr *iif, | ||
1441 | struct gigaset_capi_appl *ap, | ||
1442 | struct sk_buff *skb) | ||
1443 | { | ||
1444 | struct cardstate *cs = iif->ctr.driverdata; | ||
1445 | _cmsg *cmsg = &iif->acmsg; | ||
1446 | struct bc_state *bcs; | ||
1447 | struct gigaset_capi_appl *oap; | ||
1448 | int channel; | ||
1449 | |||
1450 | /* decode message */ | ||
1451 | capi_message2cmsg(cmsg, skb->data); | ||
1452 | dump_cmsg(DEBUG_CMD, __func__, cmsg); | ||
1453 | dev_kfree_skb_any(skb); | ||
1454 | |||
1455 | /* extract and check channel number from PLCI */ | ||
1456 | channel = (cmsg->adr.adrPLCI >> 8) & 0xff; | ||
1457 | if (!channel || channel > cs->channels) { | ||
1458 | dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", | ||
1459 | "CONNECT_RESP", "PLCI", cmsg->adr.adrPLCI); | ||
1460 | return; | ||
1461 | } | ||
1462 | bcs = cs->bcs + channel - 1; | ||
1463 | |||
1464 | switch (cmsg->Reject) { | ||
1465 | case 0: /* Accept */ | ||
1466 | /* drop all competing applications, keep only this one */ | ||
1467 | for (oap = bcs->ap; oap != NULL; oap = oap->bcnext) | ||
1468 | if (oap != ap) | ||
1469 | send_disconnect_ind(bcs, oap, | ||
1470 | CapiCallGivenToOtherApplication); | ||
1471 | ap->bcnext = NULL; | ||
1472 | bcs->ap = ap; | ||
1473 | bcs->chstate |= CHS_NOTIFY_LL; | ||
1474 | |||
1475 | /* check/encode B channel protocol */ | ||
1476 | if (cmsg->BProtocol == CAPI_DEFAULT) { | ||
1477 | bcs->proto2 = L2_HDLC; | ||
1478 | dev_warn(cs->dev, | ||
1479 | "B2 Protocol X.75 SLP unsupported, using Transparent\n"); | ||
1480 | } else { | ||
1481 | switch (cmsg->B1protocol) { | ||
1482 | case 0: | ||
1483 | bcs->proto2 = L2_HDLC; | ||
1484 | break; | ||
1485 | case 1: | ||
1486 | bcs->proto2 = L2_BITSYNC; | ||
1487 | break; | ||
1488 | default: | ||
1489 | dev_warn(cs->dev, | ||
1490 | "B1 Protocol %u unsupported, using Transparent\n", | ||
1491 | cmsg->B1protocol); | ||
1492 | bcs->proto2 = L2_BITSYNC; | ||
1493 | } | ||
1494 | if (cmsg->B2protocol != 1) | ||
1495 | dev_warn(cs->dev, | ||
1496 | "B2 Protocol %u unsupported, using Transparent\n", | ||
1497 | cmsg->B2protocol); | ||
1498 | if (cmsg->B3protocol != 0) | ||
1499 | dev_warn(cs->dev, | ||
1500 | "B3 Protocol %u unsupported, using Transparent\n", | ||
1501 | cmsg->B3protocol); | ||
1502 | ignore_cstruct_param(cs, cmsg->B1configuration, | ||
1503 | "CONNECT_RESP", "B1 Configuration"); | ||
1504 | ignore_cstruct_param(cs, cmsg->B2configuration, | ||
1505 | "CONNECT_RESP", "B2 Configuration"); | ||
1506 | ignore_cstruct_param(cs, cmsg->B3configuration, | ||
1507 | "CONNECT_RESP", "B3 Configuration"); | ||
1508 | } | ||
1509 | |||
1510 | /* ToDo: check/encode remaining parameters */ | ||
1511 | ignore_cstruct_param(cs, cmsg->ConnectedNumber, | ||
1512 | "CONNECT_RESP", "Connected Number"); | ||
1513 | ignore_cstruct_param(cs, cmsg->ConnectedSubaddress, | ||
1514 | "CONNECT_RESP", "Connected Subaddress"); | ||
1515 | ignore_cstruct_param(cs, cmsg->LLC, | ||
1516 | "CONNECT_RESP", "LLC"); | ||
1517 | if (cmsg->AdditionalInfo != CAPI_DEFAULT) { | ||
1518 | ignore_cstruct_param(cs, cmsg->BChannelinformation, | ||
1519 | "CONNECT_RESP", "BChannel Information"); | ||
1520 | ignore_cstruct_param(cs, cmsg->Keypadfacility, | ||
1521 | "CONNECT_RESP", "Keypad Facility"); | ||
1522 | ignore_cstruct_param(cs, cmsg->Useruserdata, | ||
1523 | "CONNECT_RESP", "User-User Data"); | ||
1524 | ignore_cstruct_param(cs, cmsg->Facilitydataarray, | ||
1525 | "CONNECT_RESP", "Facility Data Array"); | ||
1526 | } | ||
1527 | |||
1528 | /* Accept call */ | ||
1529 | if (!gigaset_add_event(cs, &cs->bcs[channel-1].at_state, | ||
1530 | EV_ACCEPT, NULL, 0, NULL)) | ||
1531 | return; | ||
1532 | gigaset_schedule_event(cs); | ||
1533 | return; | ||
1534 | |||
1535 | case 1: /* Ignore */ | ||
1536 | /* send DISCONNECT_IND to this application */ | ||
1537 | send_disconnect_ind(bcs, ap, 0); | ||
1538 | |||
1539 | /* remove it from the list of listening apps */ | ||
1540 | if (bcs->ap == ap) { | ||
1541 | bcs->ap = ap->bcnext; | ||
1542 | if (bcs->ap == NULL) | ||
1543 | /* last one: stop ev-layer hupD notifications */ | ||
1544 | bcs->chstate &= ~CHS_NOTIFY_LL; | ||
1545 | return; | ||
1546 | } | ||
1547 | for (oap = bcs->ap; oap != NULL; oap = oap->bcnext) { | ||
1548 | if (oap->bcnext == ap) { | ||
1549 | oap->bcnext = oap->bcnext->bcnext; | ||
1550 | return; | ||
1551 | } | ||
1552 | } | ||
1553 | dev_err(cs->dev, "%s: application %u not found\n", | ||
1554 | __func__, ap->id); | ||
1555 | return; | ||
1556 | |||
1557 | default: /* Reject */ | ||
1558 | /* drop all competing applications, keep only this one */ | ||
1559 | for (oap = bcs->ap; oap != NULL; oap = oap->bcnext) | ||
1560 | if (oap != ap) | ||
1561 | send_disconnect_ind(bcs, oap, | ||
1562 | CapiCallGivenToOtherApplication); | ||
1563 | ap->bcnext = NULL; | ||
1564 | bcs->ap = ap; | ||
1565 | |||
1566 | /* reject call - will trigger DISCONNECT_IND for this app */ | ||
1567 | dev_info(cs->dev, "%s: Reject=%x\n", | ||
1568 | "CONNECT_RESP", cmsg->Reject); | ||
1569 | if (!gigaset_add_event(cs, &cs->bcs[channel-1].at_state, | ||
1570 | EV_HUP, NULL, 0, NULL)) | ||
1571 | return; | ||
1572 | gigaset_schedule_event(cs); | ||
1573 | return; | ||
1574 | } | ||
1575 | } | ||
1576 | |||
1577 | /* | ||
1578 | * process CONNECT_B3_REQ message | ||
1579 | * build NCCI and emit CONNECT_B3_CONF reply | ||
1580 | */ | ||
1581 | static void do_connect_b3_req(struct gigaset_capi_ctr *iif, | ||
1582 | struct gigaset_capi_appl *ap, | ||
1583 | struct sk_buff *skb) | ||
1584 | { | ||
1585 | struct cardstate *cs = iif->ctr.driverdata; | ||
1586 | _cmsg *cmsg = &iif->acmsg; | ||
1587 | int channel; | ||
1588 | |||
1589 | /* decode message */ | ||
1590 | capi_message2cmsg(cmsg, skb->data); | ||
1591 | dump_cmsg(DEBUG_CMD, __func__, cmsg); | ||
1592 | |||
1593 | /* extract and check channel number from PLCI */ | ||
1594 | channel = (cmsg->adr.adrPLCI >> 8) & 0xff; | ||
1595 | if (!channel || channel > cs->channels) { | ||
1596 | dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", | ||
1597 | "CONNECT_B3_REQ", "PLCI", cmsg->adr.adrPLCI); | ||
1598 | send_conf(iif, ap, skb, CapiIllContrPlciNcci); | ||
1599 | return; | ||
1600 | } | ||
1601 | |||
1602 | /* mark logical connection active */ | ||
1603 | ap->connected = APCONN_ACTIVE; | ||
1604 | |||
1605 | /* build NCCI: always 1 (one B3 connection only) */ | ||
1606 | cmsg->adr.adrNCCI |= 1 << 16; | ||
1607 | |||
1608 | /* NCPI parameter: not applicable for B3 Transparent */ | ||
1609 | ignore_cstruct_param(cs, cmsg->NCPI, "CONNECT_B3_REQ", "NCPI"); | ||
1610 | send_conf(iif, ap, skb, (cmsg->NCPI && cmsg->NCPI[0]) ? | ||
1611 | CapiNcpiNotSupportedByProtocol : CapiSuccess); | ||
1612 | } | ||
1613 | |||
1614 | /* | ||
1615 | * process CONNECT_B3_RESP message | ||
1616 | * Depending on the Reject parameter, either emit CONNECT_B3_ACTIVE_IND | ||
1617 | * or queue EV_HUP and emit DISCONNECT_B3_IND. | ||
1618 | * The emitted message is always shorter than the received one, | ||
1619 | * allowing to reuse the skb. | ||
1620 | */ | ||
1621 | static void do_connect_b3_resp(struct gigaset_capi_ctr *iif, | ||
1622 | struct gigaset_capi_appl *ap, | ||
1623 | struct sk_buff *skb) | ||
1624 | { | ||
1625 | struct cardstate *cs = iif->ctr.driverdata; | ||
1626 | _cmsg *cmsg = &iif->acmsg; | ||
1627 | struct bc_state *bcs; | ||
1628 | int channel; | ||
1629 | unsigned int msgsize; | ||
1630 | u8 command; | ||
1631 | |||
1632 | /* decode message */ | ||
1633 | capi_message2cmsg(cmsg, skb->data); | ||
1634 | dump_cmsg(DEBUG_CMD, __func__, cmsg); | ||
1635 | |||
1636 | /* extract and check channel number and NCCI */ | ||
1637 | channel = (cmsg->adr.adrNCCI >> 8) & 0xff; | ||
1638 | if (!channel || channel > cs->channels || | ||
1639 | ((cmsg->adr.adrNCCI >> 16) & 0xffff) != 1) { | ||
1640 | dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", | ||
1641 | "CONNECT_B3_RESP", "NCCI", cmsg->adr.adrNCCI); | ||
1642 | dev_kfree_skb_any(skb); | ||
1643 | return; | ||
1644 | } | ||
1645 | bcs = &cs->bcs[channel-1]; | ||
1646 | |||
1647 | if (cmsg->Reject) { | ||
1648 | /* Reject: clear B3 connect received flag */ | ||
1649 | ap->connected = APCONN_SETUP; | ||
1650 | |||
1651 | /* trigger hangup, causing eventual DISCONNECT_IND */ | ||
1652 | if (!gigaset_add_event(cs, &bcs->at_state, | ||
1653 | EV_HUP, NULL, 0, NULL)) { | ||
1654 | dev_kfree_skb_any(skb); | ||
1655 | return; | ||
1656 | } | ||
1657 | gigaset_schedule_event(cs); | ||
1658 | |||
1659 | /* emit DISCONNECT_B3_IND */ | ||
1660 | command = CAPI_DISCONNECT_B3; | ||
1661 | msgsize = CAPI_DISCONNECT_B3_IND_BASELEN; | ||
1662 | } else { | ||
1663 | /* | ||
1664 | * Accept: emit CONNECT_B3_ACTIVE_IND immediately, as | ||
1665 | * we only send CONNECT_B3_IND if the B channel is up | ||
1666 | */ | ||
1667 | command = CAPI_CONNECT_B3_ACTIVE; | ||
1668 | msgsize = CAPI_CONNECT_B3_ACTIVE_IND_BASELEN; | ||
1669 | } | ||
1670 | capi_cmsg_header(cmsg, ap->id, command, CAPI_IND, | ||
1671 | ap->nextMessageNumber++, cmsg->adr.adrNCCI); | ||
1672 | __skb_trim(skb, msgsize); | ||
1673 | capi_cmsg2message(cmsg, skb->data); | ||
1674 | dump_cmsg(DEBUG_CMD, __func__, cmsg); | ||
1675 | capi_ctr_handle_message(&iif->ctr, ap->id, skb); | ||
1676 | } | ||
1677 | |||
1678 | /* | ||
1679 | * process DISCONNECT_REQ message | ||
1680 | * schedule EV_HUP and emit DISCONNECT_B3_IND if necessary, | ||
1681 | * emit DISCONNECT_CONF reply | ||
1682 | */ | ||
1683 | static void do_disconnect_req(struct gigaset_capi_ctr *iif, | ||
1684 | struct gigaset_capi_appl *ap, | ||
1685 | struct sk_buff *skb) | ||
1686 | { | ||
1687 | struct cardstate *cs = iif->ctr.driverdata; | ||
1688 | _cmsg *cmsg = &iif->acmsg; | ||
1689 | struct bc_state *bcs; | ||
1690 | _cmsg *b3cmsg; | ||
1691 | struct sk_buff *b3skb; | ||
1692 | int channel; | ||
1693 | |||
1694 | /* decode message */ | ||
1695 | capi_message2cmsg(cmsg, skb->data); | ||
1696 | dump_cmsg(DEBUG_CMD, __func__, cmsg); | ||
1697 | |||
1698 | /* extract and check channel number from PLCI */ | ||
1699 | channel = (cmsg->adr.adrPLCI >> 8) & 0xff; | ||
1700 | if (!channel || channel > cs->channels) { | ||
1701 | dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", | ||
1702 | "DISCONNECT_REQ", "PLCI", cmsg->adr.adrPLCI); | ||
1703 | send_conf(iif, ap, skb, CapiIllContrPlciNcci); | ||
1704 | return; | ||
1705 | } | ||
1706 | bcs = cs->bcs + channel - 1; | ||
1707 | |||
1708 | /* ToDo: process parameter: Additional info */ | ||
1709 | if (cmsg->AdditionalInfo != CAPI_DEFAULT) { | ||
1710 | ignore_cstruct_param(cs, cmsg->BChannelinformation, | ||
1711 | "DISCONNECT_REQ", "B Channel Information"); | ||
1712 | ignore_cstruct_param(cs, cmsg->Keypadfacility, | ||
1713 | "DISCONNECT_REQ", "Keypad Facility"); | ||
1714 | ignore_cstruct_param(cs, cmsg->Useruserdata, | ||
1715 | "DISCONNECT_REQ", "User-User Data"); | ||
1716 | ignore_cstruct_param(cs, cmsg->Facilitydataarray, | ||
1717 | "DISCONNECT_REQ", "Facility Data Array"); | ||
1718 | } | ||
1719 | |||
1720 | /* skip if DISCONNECT_IND already sent */ | ||
1721 | if (!ap->connected) | ||
1722 | return; | ||
1723 | |||
1724 | /* check for active logical connection */ | ||
1725 | if (ap->connected >= APCONN_ACTIVE) { | ||
1726 | /* | ||
1727 | * emit DISCONNECT_B3_IND with cause 0x3301 | ||
1728 | * use separate cmsg structure, as the content of iif->acmsg | ||
1729 | * is still needed for creating the _CONF message | ||
1730 | */ | ||
1731 | b3cmsg = kmalloc(sizeof(*b3cmsg), GFP_KERNEL); | ||
1732 | if (!b3cmsg) { | ||
1733 | dev_err(cs->dev, "%s: out of memory\n", __func__); | ||
1734 | send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR); | ||
1735 | return; | ||
1736 | } | ||
1737 | capi_cmsg_header(b3cmsg, ap->id, CAPI_DISCONNECT_B3, CAPI_IND, | ||
1738 | ap->nextMessageNumber++, | ||
1739 | cmsg->adr.adrPLCI | (1 << 16)); | ||
1740 | b3cmsg->Reason_B3 = CapiProtocolErrorLayer1; | ||
1741 | b3skb = alloc_skb(CAPI_DISCONNECT_B3_IND_BASELEN, GFP_KERNEL); | ||
1742 | if (b3skb == NULL) { | ||
1743 | dev_err(cs->dev, "%s: out of memory\n", __func__); | ||
1744 | send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR); | ||
1745 | return; | ||
1746 | } | ||
1747 | capi_cmsg2message(b3cmsg, | ||
1748 | __skb_put(b3skb, CAPI_DISCONNECT_B3_IND_BASELEN)); | ||
1749 | kfree(b3cmsg); | ||
1750 | capi_ctr_handle_message(&iif->ctr, ap->id, b3skb); | ||
1751 | } | ||
1752 | |||
1753 | /* trigger hangup, causing eventual DISCONNECT_IND */ | ||
1754 | if (!gigaset_add_event(cs, &bcs->at_state, EV_HUP, NULL, 0, NULL)) { | ||
1755 | send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR); | ||
1756 | return; | ||
1757 | } | ||
1758 | gigaset_schedule_event(cs); | ||
1759 | |||
1760 | /* emit reply */ | ||
1761 | send_conf(iif, ap, skb, CapiSuccess); | ||
1762 | } | ||
1763 | |||
1764 | /* | ||
1765 | * process DISCONNECT_B3_REQ message | ||
1766 | * schedule EV_HUP and emit DISCONNECT_B3_CONF reply | ||
1767 | */ | ||
1768 | static void do_disconnect_b3_req(struct gigaset_capi_ctr *iif, | ||
1769 | struct gigaset_capi_appl *ap, | ||
1770 | struct sk_buff *skb) | ||
1771 | { | ||
1772 | struct cardstate *cs = iif->ctr.driverdata; | ||
1773 | _cmsg *cmsg = &iif->acmsg; | ||
1774 | int channel; | ||
1775 | |||
1776 | /* decode message */ | ||
1777 | capi_message2cmsg(cmsg, skb->data); | ||
1778 | dump_cmsg(DEBUG_CMD, __func__, cmsg); | ||
1779 | |||
1780 | /* extract and check channel number and NCCI */ | ||
1781 | channel = (cmsg->adr.adrNCCI >> 8) & 0xff; | ||
1782 | if (!channel || channel > cs->channels || | ||
1783 | ((cmsg->adr.adrNCCI >> 16) & 0xffff) != 1) { | ||
1784 | dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", | ||
1785 | "DISCONNECT_B3_REQ", "NCCI", cmsg->adr.adrNCCI); | ||
1786 | send_conf(iif, ap, skb, CapiIllContrPlciNcci); | ||
1787 | return; | ||
1788 | } | ||
1789 | |||
1790 | /* reject if logical connection not active */ | ||
1791 | if (ap->connected < APCONN_ACTIVE) { | ||
1792 | send_conf(iif, ap, skb, | ||
1793 | CapiMessageNotSupportedInCurrentState); | ||
1794 | return; | ||
1795 | } | ||
1796 | |||
1797 | /* trigger hangup, causing eventual DISCONNECT_B3_IND */ | ||
1798 | if (!gigaset_add_event(cs, &cs->bcs[channel-1].at_state, | ||
1799 | EV_HUP, NULL, 0, NULL)) { | ||
1800 | send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR); | ||
1801 | return; | ||
1802 | } | ||
1803 | gigaset_schedule_event(cs); | ||
1804 | |||
1805 | /* NCPI parameter: not applicable for B3 Transparent */ | ||
1806 | ignore_cstruct_param(cs, cmsg->NCPI, | ||
1807 | "DISCONNECT_B3_REQ", "NCPI"); | ||
1808 | send_conf(iif, ap, skb, (cmsg->NCPI && cmsg->NCPI[0]) ? | ||
1809 | CapiNcpiNotSupportedByProtocol : CapiSuccess); | ||
1810 | } | ||
1811 | |||
1812 | /* | ||
1813 | * process DATA_B3_REQ message | ||
1814 | */ | ||
1815 | static void do_data_b3_req(struct gigaset_capi_ctr *iif, | ||
1816 | struct gigaset_capi_appl *ap, | ||
1817 | struct sk_buff *skb) | ||
1818 | { | ||
1819 | struct cardstate *cs = iif->ctr.driverdata; | ||
1820 | int channel = CAPIMSG_PLCI_PART(skb->data); | ||
1821 | u16 ncci = CAPIMSG_NCCI_PART(skb->data); | ||
1822 | u16 msglen = CAPIMSG_LEN(skb->data); | ||
1823 | u16 datalen = CAPIMSG_DATALEN(skb->data); | ||
1824 | u16 flags = CAPIMSG_FLAGS(skb->data); | ||
1825 | |||
1826 | /* frequent message, avoid _cmsg overhead */ | ||
1827 | dump_rawmsg(DEBUG_LLDATA, "DATA_B3_REQ", skb->data); | ||
1828 | |||
1829 | gig_dbg(DEBUG_LLDATA, | ||
1830 | "Receiving data from LL (ch: %d, flg: %x, sz: %d|%d)", | ||
1831 | channel, flags, msglen, datalen); | ||
1832 | |||
1833 | /* check parameters */ | ||
1834 | if (channel == 0 || channel > cs->channels || ncci != 1) { | ||
1835 | dev_notice(cs->dev, "%s: invalid %s 0x%02x\n", | ||
1836 | "DATA_B3_REQ", "NCCI", CAPIMSG_NCCI(skb->data)); | ||
1837 | send_conf(iif, ap, skb, CapiIllContrPlciNcci); | ||
1838 | return; | ||
1839 | } | ||
1840 | if (msglen != CAPI_DATA_B3_REQ_LEN && msglen != CAPI_DATA_B3_REQ_LEN64) | ||
1841 | dev_notice(cs->dev, "%s: unexpected length %d\n", | ||
1842 | "DATA_B3_REQ", msglen); | ||
1843 | if (msglen + datalen != skb->len) | ||
1844 | dev_notice(cs->dev, "%s: length mismatch (%d+%d!=%d)\n", | ||
1845 | "DATA_B3_REQ", msglen, datalen, skb->len); | ||
1846 | if (msglen + datalen > skb->len) { | ||
1847 | /* message too short for announced data length */ | ||
1848 | send_conf(iif, ap, skb, CapiIllMessageParmCoding); /* ? */ | ||
1849 | return; | ||
1850 | } | ||
1851 | if (flags & CAPI_FLAGS_RESERVED) { | ||
1852 | dev_notice(cs->dev, "%s: reserved flags set (%x)\n", | ||
1853 | "DATA_B3_REQ", flags); | ||
1854 | send_conf(iif, ap, skb, CapiIllMessageParmCoding); | ||
1855 | return; | ||
1856 | } | ||
1857 | |||
1858 | /* reject if logical connection not active */ | ||
1859 | if (ap->connected < APCONN_ACTIVE) { | ||
1860 | send_conf(iif, ap, skb, CapiMessageNotSupportedInCurrentState); | ||
1861 | return; | ||
1862 | } | ||
1863 | |||
1864 | /* pull CAPI message into link layer header */ | ||
1865 | skb_reset_mac_header(skb); | ||
1866 | skb->mac_len = msglen; | ||
1867 | skb_pull(skb, msglen); | ||
1868 | |||
1869 | /* pass to device-specific module */ | ||
1870 | if (cs->ops->send_skb(&cs->bcs[channel-1], skb) < 0) { | ||
1871 | send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR); | ||
1872 | return; | ||
1873 | } | ||
1874 | |||
1875 | /* DATA_B3_CONF reply will be sent by gigaset_skb_sent() */ | ||
1876 | |||
1877 | /* | ||
1878 | * ToDo: honor unset "delivery confirmation" bit | ||
1879 | * (send DATA_B3_CONF immediately?) | ||
1880 | */ | ||
1881 | } | ||
1882 | |||
1883 | /* | ||
1884 | * process RESET_B3_REQ message | ||
1885 | * just always reply "not supported by current protocol" | ||
1886 | */ | ||
1887 | static void do_reset_b3_req(struct gigaset_capi_ctr *iif, | ||
1888 | struct gigaset_capi_appl *ap, | ||
1889 | struct sk_buff *skb) | ||
1890 | { | ||
1891 | /* decode message */ | ||
1892 | capi_message2cmsg(&iif->acmsg, skb->data); | ||
1893 | dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); | ||
1894 | send_conf(iif, ap, skb, | ||
1895 | CapiResetProcedureNotSupportedByCurrentProtocol); | ||
1896 | } | ||
1897 | |||
1898 | /* | ||
1899 | * dump unsupported/ignored messages at most twice per minute, | ||
1900 | * some apps send those very frequently | ||
1901 | */ | ||
1902 | static unsigned long ignored_msg_dump_time; | ||
1903 | |||
1904 | /* | ||
1905 | * unsupported CAPI message handler | ||
1906 | */ | ||
1907 | static void do_unsupported(struct gigaset_capi_ctr *iif, | ||
1908 | struct gigaset_capi_appl *ap, | ||
1909 | struct sk_buff *skb) | ||
1910 | { | ||
1911 | /* decode message */ | ||
1912 | capi_message2cmsg(&iif->acmsg, skb->data); | ||
1913 | if (printk_timed_ratelimit(&ignored_msg_dump_time, 30 * 1000)) | ||
1914 | dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); | ||
1915 | send_conf(iif, ap, skb, CapiMessageNotSupportedInCurrentState); | ||
1916 | } | ||
1917 | |||
1918 | /* | ||
1919 | * CAPI message handler: no-op | ||
1920 | */ | ||
1921 | static void do_nothing(struct gigaset_capi_ctr *iif, | ||
1922 | struct gigaset_capi_appl *ap, | ||
1923 | struct sk_buff *skb) | ||
1924 | { | ||
1925 | if (printk_timed_ratelimit(&ignored_msg_dump_time, 30 * 1000)) { | ||
1926 | /* decode message */ | ||
1927 | capi_message2cmsg(&iif->acmsg, skb->data); | ||
1928 | dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); | ||
1929 | } | ||
1930 | dev_kfree_skb_any(skb); | ||
1931 | } | ||
1932 | |||
1933 | static void do_data_b3_resp(struct gigaset_capi_ctr *iif, | ||
1934 | struct gigaset_capi_appl *ap, | ||
1935 | struct sk_buff *skb) | ||
1936 | { | ||
1937 | dump_rawmsg(DEBUG_LLDATA, __func__, skb->data); | ||
1938 | dev_kfree_skb_any(skb); | ||
1939 | } | ||
1940 | |||
1941 | /* table of outgoing CAPI message handlers with lookup function */ | ||
1942 | typedef void (*capi_send_handler_t)(struct gigaset_capi_ctr *, | ||
1943 | struct gigaset_capi_appl *, | ||
1944 | struct sk_buff *); | ||
1945 | |||
1946 | static struct { | ||
1947 | u16 cmd; | ||
1948 | capi_send_handler_t handler; | ||
1949 | } capi_send_handler_table[] = { | ||
1950 | /* most frequent messages first for faster lookup */ | ||
1951 | { CAPI_DATA_B3_REQ, do_data_b3_req }, | ||
1952 | { CAPI_DATA_B3_RESP, do_data_b3_resp }, | ||
1953 | |||
1954 | { CAPI_ALERT_REQ, do_alert_req }, | ||
1955 | { CAPI_CONNECT_ACTIVE_RESP, do_nothing }, | ||
1956 | { CAPI_CONNECT_B3_ACTIVE_RESP, do_nothing }, | ||
1957 | { CAPI_CONNECT_B3_REQ, do_connect_b3_req }, | ||
1958 | { CAPI_CONNECT_B3_RESP, do_connect_b3_resp }, | ||
1959 | { CAPI_CONNECT_B3_T90_ACTIVE_RESP, do_nothing }, | ||
1960 | { CAPI_CONNECT_REQ, do_connect_req }, | ||
1961 | { CAPI_CONNECT_RESP, do_connect_resp }, | ||
1962 | { CAPI_DISCONNECT_B3_REQ, do_disconnect_b3_req }, | ||
1963 | { CAPI_DISCONNECT_B3_RESP, do_nothing }, | ||
1964 | { CAPI_DISCONNECT_REQ, do_disconnect_req }, | ||
1965 | { CAPI_DISCONNECT_RESP, do_nothing }, | ||
1966 | { CAPI_FACILITY_REQ, do_facility_req }, | ||
1967 | { CAPI_FACILITY_RESP, do_nothing }, | ||
1968 | { CAPI_LISTEN_REQ, do_listen_req }, | ||
1969 | { CAPI_SELECT_B_PROTOCOL_REQ, do_unsupported }, | ||
1970 | { CAPI_RESET_B3_REQ, do_reset_b3_req }, | ||
1971 | { CAPI_RESET_B3_RESP, do_nothing }, | ||
1972 | |||
1973 | /* | ||
1974 | * ToDo: support overlap sending (requires ev-layer state | ||
1975 | * machine extension to generate additional ATD commands) | ||
1976 | */ | ||
1977 | { CAPI_INFO_REQ, do_unsupported }, | ||
1978 | { CAPI_INFO_RESP, do_nothing }, | ||
1979 | |||
1980 | /* | ||
1981 | * ToDo: what's the proper response for these? | ||
1982 | */ | ||
1983 | { CAPI_MANUFACTURER_REQ, do_nothing }, | ||
1984 | { CAPI_MANUFACTURER_RESP, do_nothing }, | ||
1985 | }; | ||
1986 | |||
1987 | /* look up handler */ | ||
1988 | static inline capi_send_handler_t lookup_capi_send_handler(const u16 cmd) | ||
1989 | { | ||
1990 | size_t i; | ||
1991 | |||
1992 | for (i = 0; i < ARRAY_SIZE(capi_send_handler_table); i++) | ||
1993 | if (capi_send_handler_table[i].cmd == cmd) | ||
1994 | return capi_send_handler_table[i].handler; | ||
1995 | return NULL; | ||
1996 | } | ||
1997 | |||
1998 | |||
1999 | /** | ||
2000 | * gigaset_send_message() - accept a CAPI message from an application | ||
2001 | * @ctr: controller descriptor structure. | ||
2002 | * @skb: CAPI message. | ||
2003 | * | ||
2004 | * Return value: CAPI error code | ||
2005 | * Note: capidrv (and probably others, too) only uses the return value to | ||
2006 | * decide whether it has to free the skb (only if result != CAPI_NOERROR (0)) | ||
2007 | */ | ||
2008 | static u16 gigaset_send_message(struct capi_ctr *ctr, struct sk_buff *skb) | ||
2009 | { | ||
2010 | struct gigaset_capi_ctr *iif | ||
2011 | = container_of(ctr, struct gigaset_capi_ctr, ctr); | ||
2012 | struct cardstate *cs = ctr->driverdata; | ||
2013 | struct gigaset_capi_appl *ap; | ||
2014 | capi_send_handler_t handler; | ||
2015 | |||
2016 | /* can only handle linear sk_buffs */ | ||
2017 | if (skb_linearize(skb) < 0) { | ||
2018 | dev_warn(cs->dev, "%s: skb_linearize failed\n", __func__); | ||
2019 | return CAPI_MSGOSRESOURCEERR; | ||
2020 | } | ||
2021 | |||
2022 | /* retrieve application data structure */ | ||
2023 | ap = get_appl(iif, CAPIMSG_APPID(skb->data)); | ||
2024 | if (!ap) { | ||
2025 | dev_notice(cs->dev, "%s: application %u not registered\n", | ||
2026 | __func__, CAPIMSG_APPID(skb->data)); | ||
2027 | return CAPI_ILLAPPNR; | ||
2028 | } | ||
2029 | |||
2030 | /* look up command */ | ||
2031 | handler = lookup_capi_send_handler(CAPIMSG_CMD(skb->data)); | ||
2032 | if (!handler) { | ||
2033 | /* unknown/unsupported message type */ | ||
2034 | if (printk_ratelimit()) | ||
2035 | dev_notice(cs->dev, "%s: unsupported message %u\n", | ||
2036 | __func__, CAPIMSG_CMD(skb->data)); | ||
2037 | return CAPI_ILLCMDORSUBCMDORMSGTOSMALL; | ||
2038 | } | ||
2039 | |||
2040 | /* serialize */ | ||
2041 | if (atomic_add_return(1, &iif->sendqlen) > 1) { | ||
2042 | /* queue behind other messages */ | ||
2043 | skb_queue_tail(&iif->sendqueue, skb); | ||
2044 | return CAPI_NOERROR; | ||
2045 | } | ||
2046 | |||
2047 | /* process message */ | ||
2048 | handler(iif, ap, skb); | ||
2049 | |||
2050 | /* process other messages arrived in the meantime */ | ||
2051 | while (atomic_sub_return(1, &iif->sendqlen) > 0) { | ||
2052 | skb = skb_dequeue(&iif->sendqueue); | ||
2053 | if (!skb) { | ||
2054 | /* should never happen */ | ||
2055 | dev_err(cs->dev, "%s: send queue empty\n", __func__); | ||
2056 | continue; | ||
2057 | } | ||
2058 | ap = get_appl(iif, CAPIMSG_APPID(skb->data)); | ||
2059 | if (!ap) { | ||
2060 | /* could that happen? */ | ||
2061 | dev_warn(cs->dev, "%s: application %u vanished\n", | ||
2062 | __func__, CAPIMSG_APPID(skb->data)); | ||
2063 | continue; | ||
2064 | } | ||
2065 | handler = lookup_capi_send_handler(CAPIMSG_CMD(skb->data)); | ||
2066 | if (!handler) { | ||
2067 | /* should never happen */ | ||
2068 | dev_err(cs->dev, "%s: handler %x vanished\n", | ||
2069 | __func__, CAPIMSG_CMD(skb->data)); | ||
2070 | continue; | ||
2071 | } | ||
2072 | handler(iif, ap, skb); | ||
2073 | } | ||
2074 | |||
2075 | return CAPI_NOERROR; | ||
2076 | } | ||
2077 | |||
2078 | /** | ||
2079 | * gigaset_procinfo() - build single line description for controller | ||
2080 | * @ctr: controller descriptor structure. | ||
2081 | * | ||
2082 | * Return value: pointer to generated string (null terminated) | ||
2083 | */ | ||
2084 | static char *gigaset_procinfo(struct capi_ctr *ctr) | ||
2085 | { | ||
2086 | return ctr->name; /* ToDo: more? */ | ||
2087 | } | ||
2088 | |||
2089 | static int gigaset_proc_show(struct seq_file *m, void *v) | ||
2090 | { | ||
2091 | struct capi_ctr *ctr = m->private; | ||
2092 | struct cardstate *cs = ctr->driverdata; | ||
2093 | char *s; | ||
2094 | int i; | ||
2095 | |||
2096 | seq_printf(m, "%-16s %s\n", "name", ctr->name); | ||
2097 | seq_printf(m, "%-16s %s %s\n", "dev", | ||
2098 | dev_driver_string(cs->dev), dev_name(cs->dev)); | ||
2099 | seq_printf(m, "%-16s %d\n", "id", cs->myid); | ||
2100 | if (cs->gotfwver) | ||
2101 | seq_printf(m, "%-16s %d.%d.%d.%d\n", "firmware", | ||
2102 | cs->fwver[0], cs->fwver[1], cs->fwver[2], cs->fwver[3]); | ||
2103 | seq_printf(m, "%-16s %d\n", "channels", cs->channels); | ||
2104 | seq_printf(m, "%-16s %s\n", "onechannel", cs->onechannel ? "yes" : "no"); | ||
2105 | |||
2106 | switch (cs->mode) { | ||
2107 | case M_UNKNOWN: | ||
2108 | s = "unknown"; | ||
2109 | break; | ||
2110 | case M_CONFIG: | ||
2111 | s = "config"; | ||
2112 | break; | ||
2113 | case M_UNIMODEM: | ||
2114 | s = "Unimodem"; | ||
2115 | break; | ||
2116 | case M_CID: | ||
2117 | s = "CID"; | ||
2118 | break; | ||
2119 | default: | ||
2120 | s = "??"; | ||
2121 | } | ||
2122 | seq_printf(m, "%-16s %s\n", "mode", s); | ||
2123 | |||
2124 | switch (cs->mstate) { | ||
2125 | case MS_UNINITIALIZED: | ||
2126 | s = "uninitialized"; | ||
2127 | break; | ||
2128 | case MS_INIT: | ||
2129 | s = "init"; | ||
2130 | break; | ||
2131 | case MS_LOCKED: | ||
2132 | s = "locked"; | ||
2133 | break; | ||
2134 | case MS_SHUTDOWN: | ||
2135 | s = "shutdown"; | ||
2136 | break; | ||
2137 | case MS_RECOVER: | ||
2138 | s = "recover"; | ||
2139 | break; | ||
2140 | case MS_READY: | ||
2141 | s = "ready"; | ||
2142 | break; | ||
2143 | default: | ||
2144 | s = "??"; | ||
2145 | } | ||
2146 | seq_printf(m, "%-16s %s\n", "mstate", s); | ||
2147 | |||
2148 | seq_printf(m, "%-16s %s\n", "running", cs->running ? "yes" : "no"); | ||
2149 | seq_printf(m, "%-16s %s\n", "connected", cs->connected ? "yes" : "no"); | ||
2150 | seq_printf(m, "%-16s %s\n", "isdn_up", cs->isdn_up ? "yes" : "no"); | ||
2151 | seq_printf(m, "%-16s %s\n", "cidmode", cs->cidmode ? "yes" : "no"); | ||
2152 | |||
2153 | for (i = 0; i < cs->channels; i++) { | ||
2154 | seq_printf(m, "[%d]%-13s %d\n", i, "corrupted", | ||
2155 | cs->bcs[i].corrupted); | ||
2156 | seq_printf(m, "[%d]%-13s %d\n", i, "trans_down", | ||
2157 | cs->bcs[i].trans_down); | ||
2158 | seq_printf(m, "[%d]%-13s %d\n", i, "trans_up", | ||
2159 | cs->bcs[i].trans_up); | ||
2160 | seq_printf(m, "[%d]%-13s %d\n", i, "chstate", | ||
2161 | cs->bcs[i].chstate); | ||
2162 | switch (cs->bcs[i].proto2) { | ||
2163 | case L2_BITSYNC: | ||
2164 | s = "bitsync"; | ||
2165 | break; | ||
2166 | case L2_HDLC: | ||
2167 | s = "HDLC"; | ||
2168 | break; | ||
2169 | case L2_VOICE: | ||
2170 | s = "voice"; | ||
2171 | break; | ||
2172 | default: | ||
2173 | s = "??"; | ||
2174 | } | ||
2175 | seq_printf(m, "[%d]%-13s %s\n", i, "proto2", s); | ||
2176 | } | ||
2177 | return 0; | ||
2178 | } | ||
2179 | |||
2180 | static int gigaset_proc_open(struct inode *inode, struct file *file) | ||
2181 | { | ||
2182 | return single_open(file, gigaset_proc_show, PDE(inode)->data); | ||
2183 | } | ||
2184 | |||
2185 | static const struct file_operations gigaset_proc_fops = { | ||
2186 | .owner = THIS_MODULE, | ||
2187 | .open = gigaset_proc_open, | ||
2188 | .read = seq_read, | ||
2189 | .llseek = seq_lseek, | ||
2190 | .release = single_release, | ||
2191 | }; | ||
2192 | |||
2193 | /** | ||
2194 | * gigaset_isdn_regdev() - register device to LL | ||
2195 | * @cs: device descriptor structure. | ||
2196 | * @isdnid: device name. | ||
2197 | * | ||
2198 | * Return value: 1 for success, 0 for failure | ||
2199 | */ | ||
2200 | int gigaset_isdn_regdev(struct cardstate *cs, const char *isdnid) | ||
2201 | { | ||
2202 | struct gigaset_capi_ctr *iif; | ||
2203 | int rc; | ||
2204 | |||
2205 | iif = kmalloc(sizeof(*iif), GFP_KERNEL); | ||
2206 | if (!iif) { | ||
2207 | pr_err("%s: out of memory\n", __func__); | ||
2208 | return 0; | ||
2209 | } | ||
2210 | |||
2211 | /* prepare controller structure */ | ||
2212 | iif->ctr.owner = THIS_MODULE; | ||
2213 | iif->ctr.driverdata = cs; | ||
2214 | strncpy(iif->ctr.name, isdnid, sizeof(iif->ctr.name)); | ||
2215 | iif->ctr.driver_name = "gigaset"; | ||
2216 | iif->ctr.load_firmware = gigaset_load_firmware; | ||
2217 | iif->ctr.reset_ctr = gigaset_reset_ctr; | ||
2218 | iif->ctr.register_appl = gigaset_register_appl; | ||
2219 | iif->ctr.release_appl = gigaset_release_appl; | ||
2220 | iif->ctr.send_message = gigaset_send_message; | ||
2221 | iif->ctr.procinfo = gigaset_procinfo; | ||
2222 | iif->ctr.proc_fops = &gigaset_proc_fops; | ||
2223 | INIT_LIST_HEAD(&iif->appls); | ||
2224 | skb_queue_head_init(&iif->sendqueue); | ||
2225 | atomic_set(&iif->sendqlen, 0); | ||
2226 | |||
2227 | /* register controller with CAPI */ | ||
2228 | rc = attach_capi_ctr(&iif->ctr); | ||
2229 | if (rc) { | ||
2230 | pr_err("attach_capi_ctr failed (%d)\n", rc); | ||
2231 | kfree(iif); | ||
2232 | return 0; | ||
2233 | } | ||
2234 | |||
2235 | cs->iif = iif; | ||
2236 | cs->hw_hdr_len = CAPI_DATA_B3_REQ_LEN; | ||
2237 | return 1; | ||
2238 | } | ||
2239 | |||
2240 | /** | ||
2241 | * gigaset_isdn_unregdev() - unregister device from LL | ||
2242 | * @cs: device descriptor structure. | ||
2243 | */ | ||
2244 | void gigaset_isdn_unregdev(struct cardstate *cs) | ||
2245 | { | ||
2246 | struct gigaset_capi_ctr *iif = cs->iif; | ||
2247 | |||
2248 | detach_capi_ctr(&iif->ctr); | ||
2249 | kfree(iif); | ||
2250 | cs->iif = NULL; | ||
2251 | } | ||
2252 | |||
2253 | static struct capi_driver capi_driver_gigaset = { | ||
2254 | .name = "gigaset", | ||
2255 | .revision = "1.0", | ||
2256 | }; | ||
2257 | |||
2258 | /** | ||
2259 | * gigaset_isdn_regdrv() - register driver to LL | ||
2260 | */ | ||
2261 | void gigaset_isdn_regdrv(void) | ||
2262 | { | ||
2263 | pr_info("Kernel CAPI interface\n"); | ||
2264 | register_capi_driver(&capi_driver_gigaset); | ||
2265 | } | ||
2266 | |||
2267 | /** | ||
2268 | * gigaset_isdn_unregdrv() - unregister driver from LL | ||
2269 | */ | ||
2270 | void gigaset_isdn_unregdrv(void) | ||
2271 | { | ||
2272 | unregister_capi_driver(&capi_driver_gigaset); | ||
2273 | } | ||
diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c index 33dcd8d72b7c..f6f45f221920 100644 --- a/drivers/isdn/gigaset/common.c +++ b/drivers/isdn/gigaset/common.c | |||
@@ -14,7 +14,6 @@ | |||
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include "gigaset.h" | 16 | #include "gigaset.h" |
17 | #include <linux/ctype.h> | ||
18 | #include <linux/module.h> | 17 | #include <linux/module.h> |
19 | #include <linux/moduleparam.h> | 18 | #include <linux/moduleparam.h> |
20 | 19 | ||
@@ -29,7 +28,7 @@ | |||
29 | #endif | 28 | #endif |
30 | 29 | ||
31 | /* Module parameters */ | 30 | /* Module parameters */ |
32 | int gigaset_debuglevel = DEBUG_DEFAULT; | 31 | int gigaset_debuglevel; |
33 | EXPORT_SYMBOL_GPL(gigaset_debuglevel); | 32 | EXPORT_SYMBOL_GPL(gigaset_debuglevel); |
34 | module_param_named(debug, gigaset_debuglevel, int, S_IRUGO|S_IWUSR); | 33 | module_param_named(debug, gigaset_debuglevel, int, S_IRUGO|S_IWUSR); |
35 | MODULE_PARM_DESC(debug, "debug level"); | 34 | MODULE_PARM_DESC(debug, "debug level"); |
@@ -108,7 +107,7 @@ int gigaset_enterconfigmode(struct cardstate *cs) | |||
108 | { | 107 | { |
109 | int i, r; | 108 | int i, r; |
110 | 109 | ||
111 | cs->control_state = TIOCM_RTS; //FIXME | 110 | cs->control_state = TIOCM_RTS; |
112 | 111 | ||
113 | r = setflags(cs, TIOCM_DTR, 200); | 112 | r = setflags(cs, TIOCM_DTR, 200); |
114 | if (r < 0) | 113 | if (r < 0) |
@@ -132,10 +131,10 @@ int gigaset_enterconfigmode(struct cardstate *cs) | |||
132 | 131 | ||
133 | error: | 132 | error: |
134 | dev_err(cs->dev, "error %d on setuartbits\n", -r); | 133 | dev_err(cs->dev, "error %d on setuartbits\n", -r); |
135 | cs->control_state = TIOCM_RTS|TIOCM_DTR; // FIXME is this a good value? | 134 | cs->control_state = TIOCM_RTS|TIOCM_DTR; |
136 | cs->ops->set_modem_ctrl(cs, 0, TIOCM_RTS|TIOCM_DTR); | 135 | cs->ops->set_modem_ctrl(cs, 0, TIOCM_RTS|TIOCM_DTR); |
137 | 136 | ||
138 | return -1; //r | 137 | return -1; |
139 | } | 138 | } |
140 | 139 | ||
141 | static int test_timeout(struct at_state_t *at_state) | 140 | static int test_timeout(struct at_state_t *at_state) |
@@ -149,11 +148,8 @@ static int test_timeout(struct at_state_t *at_state) | |||
149 | return 0; | 148 | return 0; |
150 | } | 149 | } |
151 | 150 | ||
152 | if (!gigaset_add_event(at_state->cs, at_state, EV_TIMEOUT, NULL, | 151 | gigaset_add_event(at_state->cs, at_state, EV_TIMEOUT, NULL, |
153 | at_state->timer_index, NULL)) { | 152 | at_state->timer_index, NULL); |
154 | //FIXME what should we do? | ||
155 | } | ||
156 | |||
157 | return 1; | 153 | return 1; |
158 | } | 154 | } |
159 | 155 | ||
@@ -181,7 +177,7 @@ static void timer_tick(unsigned long data) | |||
181 | if (cs->running) { | 177 | if (cs->running) { |
182 | mod_timer(&cs->timer, jiffies + msecs_to_jiffies(GIG_TICK)); | 178 | mod_timer(&cs->timer, jiffies + msecs_to_jiffies(GIG_TICK)); |
183 | if (timeout) { | 179 | if (timeout) { |
184 | gig_dbg(DEBUG_CMD, "scheduling timeout"); | 180 | gig_dbg(DEBUG_EVENT, "scheduling timeout"); |
185 | tasklet_schedule(&cs->event_tasklet); | 181 | tasklet_schedule(&cs->event_tasklet); |
186 | } | 182 | } |
187 | } | 183 | } |
@@ -195,32 +191,59 @@ int gigaset_get_channel(struct bc_state *bcs) | |||
195 | 191 | ||
196 | spin_lock_irqsave(&bcs->cs->lock, flags); | 192 | spin_lock_irqsave(&bcs->cs->lock, flags); |
197 | if (bcs->use_count || !try_module_get(bcs->cs->driver->owner)) { | 193 | if (bcs->use_count || !try_module_get(bcs->cs->driver->owner)) { |
198 | gig_dbg(DEBUG_ANY, "could not allocate channel %d", | 194 | gig_dbg(DEBUG_CHANNEL, "could not allocate channel %d", |
199 | bcs->channel); | 195 | bcs->channel); |
200 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | 196 | spin_unlock_irqrestore(&bcs->cs->lock, flags); |
201 | return 0; | 197 | return 0; |
202 | } | 198 | } |
203 | ++bcs->use_count; | 199 | ++bcs->use_count; |
204 | bcs->busy = 1; | 200 | bcs->busy = 1; |
205 | gig_dbg(DEBUG_ANY, "allocated channel %d", bcs->channel); | 201 | gig_dbg(DEBUG_CHANNEL, "allocated channel %d", bcs->channel); |
206 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | 202 | spin_unlock_irqrestore(&bcs->cs->lock, flags); |
207 | return 1; | 203 | return 1; |
208 | } | 204 | } |
209 | 205 | ||
206 | struct bc_state *gigaset_get_free_channel(struct cardstate *cs) | ||
207 | { | ||
208 | unsigned long flags; | ||
209 | int i; | ||
210 | |||
211 | spin_lock_irqsave(&cs->lock, flags); | ||
212 | if (!try_module_get(cs->driver->owner)) { | ||
213 | gig_dbg(DEBUG_CHANNEL, | ||
214 | "could not get module for allocating channel"); | ||
215 | spin_unlock_irqrestore(&cs->lock, flags); | ||
216 | return NULL; | ||
217 | } | ||
218 | for (i = 0; i < cs->channels; ++i) | ||
219 | if (!cs->bcs[i].use_count) { | ||
220 | ++cs->bcs[i].use_count; | ||
221 | cs->bcs[i].busy = 1; | ||
222 | spin_unlock_irqrestore(&cs->lock, flags); | ||
223 | gig_dbg(DEBUG_CHANNEL, "allocated channel %d", i); | ||
224 | return cs->bcs + i; | ||
225 | } | ||
226 | module_put(cs->driver->owner); | ||
227 | spin_unlock_irqrestore(&cs->lock, flags); | ||
228 | gig_dbg(DEBUG_CHANNEL, "no free channel"); | ||
229 | return NULL; | ||
230 | } | ||
231 | |||
210 | void gigaset_free_channel(struct bc_state *bcs) | 232 | void gigaset_free_channel(struct bc_state *bcs) |
211 | { | 233 | { |
212 | unsigned long flags; | 234 | unsigned long flags; |
213 | 235 | ||
214 | spin_lock_irqsave(&bcs->cs->lock, flags); | 236 | spin_lock_irqsave(&bcs->cs->lock, flags); |
215 | if (!bcs->busy) { | 237 | if (!bcs->busy) { |
216 | gig_dbg(DEBUG_ANY, "could not free channel %d", bcs->channel); | 238 | gig_dbg(DEBUG_CHANNEL, "could not free channel %d", |
239 | bcs->channel); | ||
217 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | 240 | spin_unlock_irqrestore(&bcs->cs->lock, flags); |
218 | return; | 241 | return; |
219 | } | 242 | } |
220 | --bcs->use_count; | 243 | --bcs->use_count; |
221 | bcs->busy = 0; | 244 | bcs->busy = 0; |
222 | module_put(bcs->cs->driver->owner); | 245 | module_put(bcs->cs->driver->owner); |
223 | gig_dbg(DEBUG_ANY, "freed channel %d", bcs->channel); | 246 | gig_dbg(DEBUG_CHANNEL, "freed channel %d", bcs->channel); |
224 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | 247 | spin_unlock_irqrestore(&bcs->cs->lock, flags); |
225 | } | 248 | } |
226 | 249 | ||
@@ -233,14 +256,15 @@ int gigaset_get_channels(struct cardstate *cs) | |||
233 | for (i = 0; i < cs->channels; ++i) | 256 | for (i = 0; i < cs->channels; ++i) |
234 | if (cs->bcs[i].use_count) { | 257 | if (cs->bcs[i].use_count) { |
235 | spin_unlock_irqrestore(&cs->lock, flags); | 258 | spin_unlock_irqrestore(&cs->lock, flags); |
236 | gig_dbg(DEBUG_ANY, "could not allocate all channels"); | 259 | gig_dbg(DEBUG_CHANNEL, |
260 | "could not allocate all channels"); | ||
237 | return 0; | 261 | return 0; |
238 | } | 262 | } |
239 | for (i = 0; i < cs->channels; ++i) | 263 | for (i = 0; i < cs->channels; ++i) |
240 | ++cs->bcs[i].use_count; | 264 | ++cs->bcs[i].use_count; |
241 | spin_unlock_irqrestore(&cs->lock, flags); | 265 | spin_unlock_irqrestore(&cs->lock, flags); |
242 | 266 | ||
243 | gig_dbg(DEBUG_ANY, "allocated all channels"); | 267 | gig_dbg(DEBUG_CHANNEL, "allocated all channels"); |
244 | 268 | ||
245 | return 1; | 269 | return 1; |
246 | } | 270 | } |
@@ -250,7 +274,7 @@ void gigaset_free_channels(struct cardstate *cs) | |||
250 | unsigned long flags; | 274 | unsigned long flags; |
251 | int i; | 275 | int i; |
252 | 276 | ||
253 | gig_dbg(DEBUG_ANY, "unblocking all channels"); | 277 | gig_dbg(DEBUG_CHANNEL, "unblocking all channels"); |
254 | spin_lock_irqsave(&cs->lock, flags); | 278 | spin_lock_irqsave(&cs->lock, flags); |
255 | for (i = 0; i < cs->channels; ++i) | 279 | for (i = 0; i < cs->channels; ++i) |
256 | --cs->bcs[i].use_count; | 280 | --cs->bcs[i].use_count; |
@@ -262,7 +286,7 @@ void gigaset_block_channels(struct cardstate *cs) | |||
262 | unsigned long flags; | 286 | unsigned long flags; |
263 | int i; | 287 | int i; |
264 | 288 | ||
265 | gig_dbg(DEBUG_ANY, "blocking all channels"); | 289 | gig_dbg(DEBUG_CHANNEL, "blocking all channels"); |
266 | spin_lock_irqsave(&cs->lock, flags); | 290 | spin_lock_irqsave(&cs->lock, flags); |
267 | for (i = 0; i < cs->channels; ++i) | 291 | for (i = 0; i < cs->channels; ++i) |
268 | ++cs->bcs[i].use_count; | 292 | ++cs->bcs[i].use_count; |
@@ -313,6 +337,8 @@ struct event_t *gigaset_add_event(struct cardstate *cs, | |||
313 | unsigned next, tail; | 337 | unsigned next, tail; |
314 | struct event_t *event = NULL; | 338 | struct event_t *event = NULL; |
315 | 339 | ||
340 | gig_dbg(DEBUG_EVENT, "queueing event %d", type); | ||
341 | |||
316 | spin_lock_irqsave(&cs->ev_lock, flags); | 342 | spin_lock_irqsave(&cs->ev_lock, flags); |
317 | 343 | ||
318 | tail = cs->ev_tail; | 344 | tail = cs->ev_tail; |
@@ -367,16 +393,15 @@ static void gigaset_freebcs(struct bc_state *bcs) | |||
367 | int i; | 393 | int i; |
368 | 394 | ||
369 | gig_dbg(DEBUG_INIT, "freeing bcs[%d]->hw", bcs->channel); | 395 | gig_dbg(DEBUG_INIT, "freeing bcs[%d]->hw", bcs->channel); |
370 | if (!bcs->cs->ops->freebcshw(bcs)) { | 396 | if (!bcs->cs->ops->freebcshw(bcs)) |
371 | gig_dbg(DEBUG_INIT, "failed"); | 397 | gig_dbg(DEBUG_INIT, "failed"); |
372 | } | ||
373 | 398 | ||
374 | gig_dbg(DEBUG_INIT, "clearing bcs[%d]->at_state", bcs->channel); | 399 | gig_dbg(DEBUG_INIT, "clearing bcs[%d]->at_state", bcs->channel); |
375 | clear_at_state(&bcs->at_state); | 400 | clear_at_state(&bcs->at_state); |
376 | gig_dbg(DEBUG_INIT, "freeing bcs[%d]->skb", bcs->channel); | 401 | gig_dbg(DEBUG_INIT, "freeing bcs[%d]->skb", bcs->channel); |
402 | dev_kfree_skb(bcs->skb); | ||
403 | bcs->skb = NULL; | ||
377 | 404 | ||
378 | if (bcs->skb) | ||
379 | dev_kfree_skb(bcs->skb); | ||
380 | for (i = 0; i < AT_NUM; ++i) { | 405 | for (i = 0; i < AT_NUM; ++i) { |
381 | kfree(bcs->commands[i]); | 406 | kfree(bcs->commands[i]); |
382 | bcs->commands[i] = NULL; | 407 | bcs->commands[i] = NULL; |
@@ -463,6 +488,12 @@ void gigaset_freecs(struct cardstate *cs) | |||
463 | 488 | ||
464 | switch (cs->cs_init) { | 489 | switch (cs->cs_init) { |
465 | default: | 490 | default: |
491 | /* clear B channel structures */ | ||
492 | for (i = 0; i < cs->channels; ++i) { | ||
493 | gig_dbg(DEBUG_INIT, "clearing bcs[%d]", i); | ||
494 | gigaset_freebcs(cs->bcs + i); | ||
495 | } | ||
496 | |||
466 | /* clear device sysfs */ | 497 | /* clear device sysfs */ |
467 | gigaset_free_dev_sysfs(cs); | 498 | gigaset_free_dev_sysfs(cs); |
468 | 499 | ||
@@ -471,28 +502,20 @@ void gigaset_freecs(struct cardstate *cs) | |||
471 | gig_dbg(DEBUG_INIT, "clearing hw"); | 502 | gig_dbg(DEBUG_INIT, "clearing hw"); |
472 | cs->ops->freecshw(cs); | 503 | cs->ops->freecshw(cs); |
473 | 504 | ||
474 | //FIXME cmdbuf | ||
475 | |||
476 | /* fall through */ | 505 | /* fall through */ |
477 | case 2: /* error in initcshw */ | 506 | case 2: /* error in initcshw */ |
478 | /* Deregister from LL */ | 507 | /* Deregister from LL */ |
479 | make_invalid(cs, VALID_ID); | 508 | make_invalid(cs, VALID_ID); |
480 | gig_dbg(DEBUG_INIT, "clearing iif"); | 509 | gigaset_isdn_unregdev(cs); |
481 | gigaset_i4l_cmd(cs, ISDN_STAT_UNLOAD); | ||
482 | 510 | ||
483 | /* fall through */ | 511 | /* fall through */ |
484 | case 1: /* error when regestering to LL */ | 512 | case 1: /* error when registering to LL */ |
485 | gig_dbg(DEBUG_INIT, "clearing at_state"); | 513 | gig_dbg(DEBUG_INIT, "clearing at_state"); |
486 | clear_at_state(&cs->at_state); | 514 | clear_at_state(&cs->at_state); |
487 | dealloc_at_states(cs); | 515 | dealloc_at_states(cs); |
488 | 516 | ||
489 | /* fall through */ | 517 | /* fall through */ |
490 | case 0: /* error in one call to initbcs */ | 518 | case 0: /* error in basic setup */ |
491 | for (i = 0; i < cs->channels; ++i) { | ||
492 | gig_dbg(DEBUG_INIT, "clearing bcs[%d]", i); | ||
493 | gigaset_freebcs(cs->bcs + i); | ||
494 | } | ||
495 | |||
496 | clear_events(cs); | 519 | clear_events(cs); |
497 | gig_dbg(DEBUG_INIT, "freeing inbuf"); | 520 | gig_dbg(DEBUG_INIT, "freeing inbuf"); |
498 | kfree(cs->inbuf); | 521 | kfree(cs->inbuf); |
@@ -534,16 +557,13 @@ void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs, | |||
534 | } | 557 | } |
535 | 558 | ||
536 | 559 | ||
537 | static void gigaset_inbuf_init(struct inbuf_t *inbuf, struct bc_state *bcs, | 560 | static void gigaset_inbuf_init(struct inbuf_t *inbuf, struct cardstate *cs) |
538 | struct cardstate *cs, int inputstate) | ||
539 | /* inbuf->read must be allocated before! */ | 561 | /* inbuf->read must be allocated before! */ |
540 | { | 562 | { |
541 | inbuf->head = 0; | 563 | inbuf->head = 0; |
542 | inbuf->tail = 0; | 564 | inbuf->tail = 0; |
543 | inbuf->cs = cs; | 565 | inbuf->cs = cs; |
544 | inbuf->bcs = bcs; /*base driver: NULL*/ | 566 | inbuf->inputstate = INS_command; |
545 | inbuf->rcvbuf = NULL; | ||
546 | inbuf->inputstate = inputstate; | ||
547 | } | 567 | } |
548 | 568 | ||
549 | /** | 569 | /** |
@@ -599,7 +619,7 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs, | |||
599 | { | 619 | { |
600 | int i; | 620 | int i; |
601 | 621 | ||
602 | bcs->tx_skb = NULL; //FIXME -> hw part | 622 | bcs->tx_skb = NULL; |
603 | 623 | ||
604 | skb_queue_head_init(&bcs->squeue); | 624 | skb_queue_head_init(&bcs->squeue); |
605 | 625 | ||
@@ -618,13 +638,13 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs, | |||
618 | bcs->fcs = PPP_INITFCS; | 638 | bcs->fcs = PPP_INITFCS; |
619 | bcs->inputstate = 0; | 639 | bcs->inputstate = 0; |
620 | if (cs->ignoreframes) { | 640 | if (cs->ignoreframes) { |
621 | bcs->inputstate |= INS_skip_frame; | ||
622 | bcs->skb = NULL; | 641 | bcs->skb = NULL; |
623 | } else if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL) | 642 | } else { |
624 | skb_reserve(bcs->skb, HW_HDR_LEN); | 643 | bcs->skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len); |
625 | else { | 644 | if (bcs->skb != NULL) |
626 | pr_err("out of memory\n"); | 645 | skb_reserve(bcs->skb, cs->hw_hdr_len); |
627 | bcs->inputstate |= INS_skip_frame; | 646 | else |
647 | pr_err("out of memory\n"); | ||
628 | } | 648 | } |
629 | 649 | ||
630 | bcs->channel = channel; | 650 | bcs->channel = channel; |
@@ -645,8 +665,8 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs, | |||
645 | gig_dbg(DEBUG_INIT, " failed"); | 665 | gig_dbg(DEBUG_INIT, " failed"); |
646 | 666 | ||
647 | gig_dbg(DEBUG_INIT, " freeing bcs[%d]->skb", channel); | 667 | gig_dbg(DEBUG_INIT, " freeing bcs[%d]->skb", channel); |
648 | if (bcs->skb) | 668 | dev_kfree_skb(bcs->skb); |
649 | dev_kfree_skb(bcs->skb); | 669 | bcs->skb = NULL; |
650 | 670 | ||
651 | return NULL; | 671 | return NULL; |
652 | } | 672 | } |
@@ -673,12 +693,13 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, | |||
673 | int onechannel, int ignoreframes, | 693 | int onechannel, int ignoreframes, |
674 | int cidmode, const char *modulename) | 694 | int cidmode, const char *modulename) |
675 | { | 695 | { |
676 | struct cardstate *cs = NULL; | 696 | struct cardstate *cs; |
677 | unsigned long flags; | 697 | unsigned long flags; |
678 | int i; | 698 | int i; |
679 | 699 | ||
680 | gig_dbg(DEBUG_INIT, "allocating cs"); | 700 | gig_dbg(DEBUG_INIT, "allocating cs"); |
681 | if (!(cs = alloc_cs(drv))) { | 701 | cs = alloc_cs(drv); |
702 | if (!cs) { | ||
682 | pr_err("maximum number of devices exceeded\n"); | 703 | pr_err("maximum number of devices exceeded\n"); |
683 | return NULL; | 704 | return NULL; |
684 | } | 705 | } |
@@ -707,7 +728,7 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, | |||
707 | cs->ev_tail = 0; | 728 | cs->ev_tail = 0; |
708 | cs->ev_head = 0; | 729 | cs->ev_head = 0; |
709 | 730 | ||
710 | tasklet_init(&cs->event_tasklet, &gigaset_handle_event, | 731 | tasklet_init(&cs->event_tasklet, gigaset_handle_event, |
711 | (unsigned long) cs); | 732 | (unsigned long) cs); |
712 | cs->commands_pending = 0; | 733 | cs->commands_pending = 0; |
713 | cs->cur_at_seq = 0; | 734 | cs->cur_at_seq = 0; |
@@ -726,14 +747,6 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, | |||
726 | cs->mode = M_UNKNOWN; | 747 | cs->mode = M_UNKNOWN; |
727 | cs->mstate = MS_UNINITIALIZED; | 748 | cs->mstate = MS_UNINITIALIZED; |
728 | 749 | ||
729 | for (i = 0; i < channels; ++i) { | ||
730 | gig_dbg(DEBUG_INIT, "setting up bcs[%d].read", i); | ||
731 | if (!gigaset_initbcs(cs->bcs + i, cs, i)) { | ||
732 | pr_err("could not allocate channel %d data\n", i); | ||
733 | goto error; | ||
734 | } | ||
735 | } | ||
736 | |||
737 | ++cs->cs_init; | 750 | ++cs->cs_init; |
738 | 751 | ||
739 | gig_dbg(DEBUG_INIT, "setting up at_state"); | 752 | gig_dbg(DEBUG_INIT, "setting up at_state"); |
@@ -743,10 +756,7 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, | |||
743 | cs->cbytes = 0; | 756 | cs->cbytes = 0; |
744 | 757 | ||
745 | gig_dbg(DEBUG_INIT, "setting up inbuf"); | 758 | gig_dbg(DEBUG_INIT, "setting up inbuf"); |
746 | if (onechannel) { //FIXME distinction necessary? | 759 | gigaset_inbuf_init(cs->inbuf, cs); |
747 | gigaset_inbuf_init(cs->inbuf, cs->bcs, cs, INS_command); | ||
748 | } else | ||
749 | gigaset_inbuf_init(cs->inbuf, NULL, cs, INS_command); | ||
750 | 760 | ||
751 | cs->connected = 0; | 761 | cs->connected = 0; |
752 | cs->isdn_up = 0; | 762 | cs->isdn_up = 0; |
@@ -758,7 +768,7 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, | |||
758 | cs->cmdbytes = 0; | 768 | cs->cmdbytes = 0; |
759 | 769 | ||
760 | gig_dbg(DEBUG_INIT, "setting up iif"); | 770 | gig_dbg(DEBUG_INIT, "setting up iif"); |
761 | if (!gigaset_register_to_LL(cs, modulename)) { | 771 | if (!gigaset_isdn_regdev(cs, modulename)) { |
762 | pr_err("error registering ISDN device\n"); | 772 | pr_err("error registering ISDN device\n"); |
763 | goto error; | 773 | goto error; |
764 | } | 774 | } |
@@ -777,6 +787,15 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, | |||
777 | /* set up device sysfs */ | 787 | /* set up device sysfs */ |
778 | gigaset_init_dev_sysfs(cs); | 788 | gigaset_init_dev_sysfs(cs); |
779 | 789 | ||
790 | /* set up channel data structures */ | ||
791 | for (i = 0; i < channels; ++i) { | ||
792 | gig_dbg(DEBUG_INIT, "setting up bcs[%d]", i); | ||
793 | if (!gigaset_initbcs(cs->bcs + i, cs, i)) { | ||
794 | pr_err("could not allocate channel %d data\n", i); | ||
795 | goto error; | ||
796 | } | ||
797 | } | ||
798 | |||
780 | spin_lock_irqsave(&cs->lock, flags); | 799 | spin_lock_irqsave(&cs->lock, flags); |
781 | cs->running = 1; | 800 | cs->running = 1; |
782 | spin_unlock_irqrestore(&cs->lock, flags); | 801 | spin_unlock_irqrestore(&cs->lock, flags); |
@@ -824,9 +843,10 @@ void gigaset_bcs_reinit(struct bc_state *bcs) | |||
824 | bcs->chstate = 0; | 843 | bcs->chstate = 0; |
825 | 844 | ||
826 | bcs->ignore = cs->ignoreframes; | 845 | bcs->ignore = cs->ignoreframes; |
827 | if (bcs->ignore) | 846 | if (bcs->ignore) { |
828 | bcs->inputstate |= INS_skip_frame; | 847 | dev_kfree_skb(bcs->skb); |
829 | 848 | bcs->skb = NULL; | |
849 | } | ||
830 | 850 | ||
831 | cs->ops->reinitbcshw(bcs); | 851 | cs->ops->reinitbcshw(bcs); |
832 | } | 852 | } |
@@ -847,8 +867,6 @@ static void cleanup_cs(struct cardstate *cs) | |||
847 | free_strings(&cs->at_state); | 867 | free_strings(&cs->at_state); |
848 | gigaset_at_init(&cs->at_state, NULL, cs, 0); | 868 | gigaset_at_init(&cs->at_state, NULL, cs, 0); |
849 | 869 | ||
850 | kfree(cs->inbuf->rcvbuf); | ||
851 | cs->inbuf->rcvbuf = NULL; | ||
852 | cs->inbuf->inputstate = INS_command; | 870 | cs->inbuf->inputstate = INS_command; |
853 | cs->inbuf->head = 0; | 871 | cs->inbuf->head = 0; |
854 | cs->inbuf->tail = 0; | 872 | cs->inbuf->tail = 0; |
@@ -911,19 +929,14 @@ int gigaset_start(struct cardstate *cs) | |||
911 | cs->ops->baud_rate(cs, B115200); | 929 | cs->ops->baud_rate(cs, B115200); |
912 | cs->ops->set_line_ctrl(cs, CS8); | 930 | cs->ops->set_line_ctrl(cs, CS8); |
913 | cs->control_state = TIOCM_DTR|TIOCM_RTS; | 931 | cs->control_state = TIOCM_DTR|TIOCM_RTS; |
914 | } else { | ||
915 | //FIXME use some saved values? | ||
916 | } | 932 | } |
917 | 933 | ||
918 | cs->waiting = 1; | 934 | cs->waiting = 1; |
919 | 935 | ||
920 | if (!gigaset_add_event(cs, &cs->at_state, EV_START, NULL, 0, NULL)) { | 936 | if (!gigaset_add_event(cs, &cs->at_state, EV_START, NULL, 0, NULL)) { |
921 | cs->waiting = 0; | 937 | cs->waiting = 0; |
922 | //FIXME what should we do? | ||
923 | goto error; | 938 | goto error; |
924 | } | 939 | } |
925 | |||
926 | gig_dbg(DEBUG_CMD, "scheduling START"); | ||
927 | gigaset_schedule_event(cs); | 940 | gigaset_schedule_event(cs); |
928 | 941 | ||
929 | wait_event(cs->waitqueue, !cs->waiting); | 942 | wait_event(cs->waitqueue, !cs->waiting); |
@@ -958,12 +971,8 @@ int gigaset_shutdown(struct cardstate *cs) | |||
958 | 971 | ||
959 | cs->waiting = 1; | 972 | cs->waiting = 1; |
960 | 973 | ||
961 | if (!gigaset_add_event(cs, &cs->at_state, EV_SHUTDOWN, NULL, 0, NULL)) { | 974 | if (!gigaset_add_event(cs, &cs->at_state, EV_SHUTDOWN, NULL, 0, NULL)) |
962 | //FIXME what should we do? | ||
963 | goto exit; | 975 | goto exit; |
964 | } | ||
965 | |||
966 | gig_dbg(DEBUG_CMD, "scheduling SHUTDOWN"); | ||
967 | gigaset_schedule_event(cs); | 976 | gigaset_schedule_event(cs); |
968 | 977 | ||
969 | wait_event(cs->waitqueue, !cs->waiting); | 978 | wait_event(cs->waitqueue, !cs->waiting); |
@@ -989,12 +998,8 @@ void gigaset_stop(struct cardstate *cs) | |||
989 | 998 | ||
990 | cs->waiting = 1; | 999 | cs->waiting = 1; |
991 | 1000 | ||
992 | if (!gigaset_add_event(cs, &cs->at_state, EV_STOP, NULL, 0, NULL)) { | 1001 | if (!gigaset_add_event(cs, &cs->at_state, EV_STOP, NULL, 0, NULL)) |
993 | //FIXME what should we do? | ||
994 | goto exit; | 1002 | goto exit; |
995 | } | ||
996 | |||
997 | gig_dbg(DEBUG_CMD, "scheduling STOP"); | ||
998 | gigaset_schedule_event(cs); | 1003 | gigaset_schedule_event(cs); |
999 | 1004 | ||
1000 | wait_event(cs->waitqueue, !cs->waiting); | 1005 | wait_event(cs->waitqueue, !cs->waiting); |
@@ -1199,11 +1204,13 @@ static int __init gigaset_init_module(void) | |||
1199 | gigaset_debuglevel = DEBUG_DEFAULT; | 1204 | gigaset_debuglevel = DEBUG_DEFAULT; |
1200 | 1205 | ||
1201 | pr_info(DRIVER_DESC DRIVER_DESC_DEBUG "\n"); | 1206 | pr_info(DRIVER_DESC DRIVER_DESC_DEBUG "\n"); |
1207 | gigaset_isdn_regdrv(); | ||
1202 | return 0; | 1208 | return 0; |
1203 | } | 1209 | } |
1204 | 1210 | ||
1205 | static void __exit gigaset_exit_module(void) | 1211 | static void __exit gigaset_exit_module(void) |
1206 | { | 1212 | { |
1213 | gigaset_isdn_unregdrv(); | ||
1207 | } | 1214 | } |
1208 | 1215 | ||
1209 | module_init(gigaset_init_module); | 1216 | module_init(gigaset_init_module); |
diff --git a/drivers/isdn/gigaset/dummyll.c b/drivers/isdn/gigaset/dummyll.c new file mode 100644 index 000000000000..bd0b1eaa7572 --- /dev/null +++ b/drivers/isdn/gigaset/dummyll.c | |||
@@ -0,0 +1,76 @@ | |||
1 | /* | ||
2 | * Dummy LL interface for the Gigaset driver | ||
3 | * | ||
4 | * Copyright (c) 2009 by Tilman Schmidt <tilman@imap.cc>. | ||
5 | * | ||
6 | * ===================================================================== | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License as | ||
9 | * published by the Free Software Foundation; either version 2 of | ||
10 | * the License, or (at your option) any later version. | ||
11 | * ===================================================================== | ||
12 | */ | ||
13 | |||
14 | #include "gigaset.h" | ||
15 | |||
16 | void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb) | ||
17 | { | ||
18 | } | ||
19 | EXPORT_SYMBOL_GPL(gigaset_skb_sent); | ||
20 | |||
21 | void gigaset_skb_rcvd(struct bc_state *bcs, struct sk_buff *skb) | ||
22 | { | ||
23 | } | ||
24 | EXPORT_SYMBOL_GPL(gigaset_skb_rcvd); | ||
25 | |||
26 | void gigaset_isdn_rcv_err(struct bc_state *bcs) | ||
27 | { | ||
28 | } | ||
29 | EXPORT_SYMBOL_GPL(gigaset_isdn_rcv_err); | ||
30 | |||
31 | int gigaset_isdn_icall(struct at_state_t *at_state) | ||
32 | { | ||
33 | return ICALL_IGNORE; | ||
34 | } | ||
35 | |||
36 | void gigaset_isdn_connD(struct bc_state *bcs) | ||
37 | { | ||
38 | } | ||
39 | |||
40 | void gigaset_isdn_hupD(struct bc_state *bcs) | ||
41 | { | ||
42 | } | ||
43 | |||
44 | void gigaset_isdn_connB(struct bc_state *bcs) | ||
45 | { | ||
46 | } | ||
47 | |||
48 | void gigaset_isdn_hupB(struct bc_state *bcs) | ||
49 | { | ||
50 | } | ||
51 | |||
52 | void gigaset_isdn_start(struct cardstate *cs) | ||
53 | { | ||
54 | } | ||
55 | |||
56 | void gigaset_isdn_stop(struct cardstate *cs) | ||
57 | { | ||
58 | } | ||
59 | |||
60 | int gigaset_isdn_regdev(struct cardstate *cs, const char *isdnid) | ||
61 | { | ||
62 | return 1; | ||
63 | } | ||
64 | |||
65 | void gigaset_isdn_unregdev(struct cardstate *cs) | ||
66 | { | ||
67 | } | ||
68 | |||
69 | void gigaset_isdn_regdrv(void) | ||
70 | { | ||
71 | pr_info("no ISDN subsystem interface\n"); | ||
72 | } | ||
73 | |||
74 | void gigaset_isdn_unregdrv(void) | ||
75 | { | ||
76 | } | ||
diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c index cc768caa38f5..206c380c5235 100644 --- a/drivers/isdn/gigaset/ev-layer.c +++ b/drivers/isdn/gigaset/ev-layer.c | |||
@@ -40,8 +40,8 @@ | |||
40 | 40 | ||
41 | /* Possible ASCII responses */ | 41 | /* Possible ASCII responses */ |
42 | #define RSP_OK 0 | 42 | #define RSP_OK 0 |
43 | //#define RSP_BUSY 1 | 43 | #define RSP_BUSY 1 |
44 | //#define RSP_CONNECT 2 | 44 | #define RSP_CONNECT 2 |
45 | #define RSP_ZGCI 3 | 45 | #define RSP_ZGCI 3 |
46 | #define RSP_RING 4 | 46 | #define RSP_RING 4 |
47 | #define RSP_ZAOC 5 | 47 | #define RSP_ZAOC 5 |
@@ -68,7 +68,6 @@ | |||
68 | #define RSP_ZHLC (RSP_STR + STR_ZHLC) | 68 | #define RSP_ZHLC (RSP_STR + STR_ZHLC) |
69 | #define RSP_ERROR -1 /* ERROR */ | 69 | #define RSP_ERROR -1 /* ERROR */ |
70 | #define RSP_WRONG_CID -2 /* unknown cid in cmd */ | 70 | #define RSP_WRONG_CID -2 /* unknown cid in cmd */ |
71 | //#define RSP_EMPTY -3 | ||
72 | #define RSP_UNKNOWN -4 /* unknown response */ | 71 | #define RSP_UNKNOWN -4 /* unknown response */ |
73 | #define RSP_FAIL -5 /* internal error */ | 72 | #define RSP_FAIL -5 /* internal error */ |
74 | #define RSP_INVAL -6 /* invalid response */ | 73 | #define RSP_INVAL -6 /* invalid response */ |
@@ -76,9 +75,9 @@ | |||
76 | #define RSP_NONE -19 | 75 | #define RSP_NONE -19 |
77 | #define RSP_STRING -20 | 76 | #define RSP_STRING -20 |
78 | #define RSP_NULL -21 | 77 | #define RSP_NULL -21 |
79 | //#define RSP_RETRYFAIL -22 | 78 | #define RSP_RETRYFAIL -22 |
80 | //#define RSP_RETRY -23 | 79 | #define RSP_RETRY -23 |
81 | //#define RSP_SKIP -24 | 80 | #define RSP_SKIP -24 |
82 | #define RSP_INIT -27 | 81 | #define RSP_INIT -27 |
83 | #define RSP_ANY -26 | 82 | #define RSP_ANY -26 |
84 | #define RSP_LAST -28 | 83 | #define RSP_LAST -28 |
@@ -127,7 +126,6 @@ | |||
127 | #define ACT_NOTIFY_BC_UP 39 | 126 | #define ACT_NOTIFY_BC_UP 39 |
128 | #define ACT_DIAL 40 | 127 | #define ACT_DIAL 40 |
129 | #define ACT_ACCEPT 41 | 128 | #define ACT_ACCEPT 41 |
130 | #define ACT_PROTO_L2 42 | ||
131 | #define ACT_HUP 43 | 129 | #define ACT_HUP 43 |
132 | #define ACT_IF_LOCK 44 | 130 | #define ACT_IF_LOCK 44 |
133 | #define ACT_START 45 | 131 | #define ACT_START 45 |
@@ -159,229 +157,229 @@ | |||
159 | #define SEQ_UMMODE 11 | 157 | #define SEQ_UMMODE 11 |
160 | 158 | ||
161 | 159 | ||
162 | // 100: init, 200: dle0, 250:dle1, 300: get cid (dial), 350: "hup" (no cid), 400: hup, 500: reset, 600: dial, 700: ring | 160 | /* 100: init, 200: dle0, 250:dle1, 300: get cid (dial), 350: "hup" (no cid), |
161 | * 400: hup, 500: reset, 600: dial, 700: ring */ | ||
163 | struct reply_t gigaset_tab_nocid[] = | 162 | struct reply_t gigaset_tab_nocid[] = |
164 | { | 163 | { |
165 | /* resp_code, min_ConState, max_ConState, parameter, new_ConState, timeout, action, command */ | 164 | /* resp_code, min_ConState, max_ConState, parameter, new_ConState, timeout, |
166 | 165 | * action, command */ | |
167 | /* initialize device, set cid mode if possible */ | 166 | |
168 | //{RSP_INIT, -1, -1,100, 900, 0, {ACT_TEST}}, | 167 | /* initialize device, set cid mode if possible */ |
169 | //{RSP_ERROR, 900,900, -1, 0, 0, {ACT_FAILINIT}}, | 168 | {RSP_INIT, -1, -1, SEQ_INIT, 100, 1, {ACT_TIMEOUT} }, |
170 | //{RSP_OK, 900,900, -1, 100, INIT_TIMEOUT, | 169 | |
171 | // {ACT_TIMEOUT}}, | 170 | {EV_TIMEOUT, 100, 100, -1, 101, 3, {0}, "Z\r"}, |
172 | 171 | {RSP_OK, 101, 103, -1, 120, 5, {ACT_GETSTRING}, | |
173 | {RSP_INIT, -1, -1,SEQ_INIT, 100, INIT_TIMEOUT, | 172 | "+GMR\r"}, |
174 | {ACT_TIMEOUT}}, /* wait until device is ready */ | 173 | |
175 | 174 | {EV_TIMEOUT, 101, 101, -1, 102, 5, {0}, "Z\r"}, | |
176 | {EV_TIMEOUT, 100,100, -1, 101, 3, {0}, "Z\r"}, /* device in transparent mode? try to initialize it. */ | 175 | {RSP_ERROR, 101, 101, -1, 102, 5, {0}, "Z\r"}, |
177 | {RSP_OK, 101,103, -1, 120, 5, {ACT_GETSTRING}, "+GMR\r"}, /* get version */ | 176 | |
178 | 177 | {EV_TIMEOUT, 102, 102, -1, 108, 5, {ACT_SETDLE1}, | |
179 | {EV_TIMEOUT, 101,101, -1, 102, 5, {0}, "Z\r"}, /* timeout => try once again. */ | 178 | "^SDLE=0\r"}, |
180 | {RSP_ERROR, 101,101, -1, 102, 5, {0}, "Z\r"}, /* error => try once again. */ | 179 | {RSP_OK, 108, 108, -1, 104, -1}, |
181 | 180 | {RSP_ZDLE, 104, 104, 0, 103, 5, {0}, "Z\r"}, | |
182 | {EV_TIMEOUT, 102,102, -1, 108, 5, {ACT_SETDLE1}, "^SDLE=0\r"}, /* timeout => try again in DLE mode. */ | 181 | {EV_TIMEOUT, 104, 104, -1, 0, 0, {ACT_FAILINIT} }, |
183 | {RSP_OK, 108,108, -1, 104,-1}, | 182 | {RSP_ERROR, 108, 108, -1, 0, 0, {ACT_FAILINIT} }, |
184 | {RSP_ZDLE, 104,104, 0, 103, 5, {0}, "Z\r"}, | 183 | |
185 | {EV_TIMEOUT, 104,104, -1, 0, 0, {ACT_FAILINIT}}, | 184 | {EV_TIMEOUT, 108, 108, -1, 105, 2, {ACT_SETDLE0, |
186 | {RSP_ERROR, 108,108, -1, 0, 0, {ACT_FAILINIT}}, | 185 | ACT_HUPMODEM, |
187 | 186 | ACT_TIMEOUT} }, | |
188 | {EV_TIMEOUT, 108,108, -1, 105, 2, {ACT_SETDLE0, | 187 | {EV_TIMEOUT, 105, 105, -1, 103, 5, {0}, "Z\r"}, |
189 | ACT_HUPMODEM, | 188 | |
190 | ACT_TIMEOUT}}, /* still timeout => connection in unimodem mode? */ | 189 | {RSP_ERROR, 102, 102, -1, 107, 5, {0}, "^GETPRE\r"}, |
191 | {EV_TIMEOUT, 105,105, -1, 103, 5, {0}, "Z\r"}, | 190 | {RSP_OK, 107, 107, -1, 0, 0, {ACT_CONFIGMODE} }, |
192 | 191 | {RSP_ERROR, 107, 107, -1, 0, 0, {ACT_FAILINIT} }, | |
193 | {RSP_ERROR, 102,102, -1, 107, 5, {0}, "^GETPRE\r"}, /* ERROR on ATZ => maybe in config mode? */ | 192 | {EV_TIMEOUT, 107, 107, -1, 0, 0, {ACT_FAILINIT} }, |
194 | {RSP_OK, 107,107, -1, 0, 0, {ACT_CONFIGMODE}}, | 193 | |
195 | {RSP_ERROR, 107,107, -1, 0, 0, {ACT_FAILINIT}}, | 194 | {RSP_ERROR, 103, 103, -1, 0, 0, {ACT_FAILINIT} }, |
196 | {EV_TIMEOUT, 107,107, -1, 0, 0, {ACT_FAILINIT}}, | 195 | {EV_TIMEOUT, 103, 103, -1, 0, 0, {ACT_FAILINIT} }, |
197 | 196 | ||
198 | {RSP_ERROR, 103,103, -1, 0, 0, {ACT_FAILINIT}}, | 197 | {RSP_STRING, 120, 120, -1, 121, -1, {ACT_SETVER} }, |
199 | {EV_TIMEOUT, 103,103, -1, 0, 0, {ACT_FAILINIT}}, | 198 | |
200 | 199 | {EV_TIMEOUT, 120, 121, -1, 0, 0, {ACT_FAILVER, | |
201 | {RSP_STRING, 120,120, -1, 121,-1, {ACT_SETVER}}, | 200 | ACT_INIT} }, |
202 | 201 | {RSP_ERROR, 120, 121, -1, 0, 0, {ACT_FAILVER, | |
203 | {EV_TIMEOUT, 120,121, -1, 0, 0, {ACT_FAILVER, ACT_INIT}}, | 202 | ACT_INIT} }, |
204 | {RSP_ERROR, 120,121, -1, 0, 0, {ACT_FAILVER, ACT_INIT}}, | 203 | {RSP_OK, 121, 121, -1, 0, 0, {ACT_GOTVER, |
205 | {RSP_OK, 121,121, -1, 0, 0, {ACT_GOTVER, ACT_INIT}}, | 204 | ACT_INIT} }, |
206 | 205 | ||
207 | /* leave dle mode */ | 206 | /* leave dle mode */ |
208 | {RSP_INIT, 0, 0,SEQ_DLE0, 201, 5, {0}, "^SDLE=0\r"}, | 207 | {RSP_INIT, 0, 0, SEQ_DLE0, 201, 5, {0}, "^SDLE=0\r"}, |
209 | {RSP_OK, 201,201, -1, 202,-1}, | 208 | {RSP_OK, 201, 201, -1, 202, -1}, |
210 | {RSP_ZDLE, 202,202, 0, 0, 0, {ACT_DLE0}}, | 209 | {RSP_ZDLE, 202, 202, 0, 0, 0, {ACT_DLE0} }, |
211 | {RSP_NODEV, 200,249, -1, 0, 0, {ACT_FAKEDLE0}}, | 210 | {RSP_NODEV, 200, 249, -1, 0, 0, {ACT_FAKEDLE0} }, |
212 | {RSP_ERROR, 200,249, -1, 0, 0, {ACT_FAILDLE0}}, | 211 | {RSP_ERROR, 200, 249, -1, 0, 0, {ACT_FAILDLE0} }, |
213 | {EV_TIMEOUT, 200,249, -1, 0, 0, {ACT_FAILDLE0}}, | 212 | {EV_TIMEOUT, 200, 249, -1, 0, 0, {ACT_FAILDLE0} }, |
214 | 213 | ||
215 | /* enter dle mode */ | 214 | /* enter dle mode */ |
216 | {RSP_INIT, 0, 0,SEQ_DLE1, 251, 5, {0}, "^SDLE=1\r"}, | 215 | {RSP_INIT, 0, 0, SEQ_DLE1, 251, 5, {0}, "^SDLE=1\r"}, |
217 | {RSP_OK, 251,251, -1, 252,-1}, | 216 | {RSP_OK, 251, 251, -1, 252, -1}, |
218 | {RSP_ZDLE, 252,252, 1, 0, 0, {ACT_DLE1}}, | 217 | {RSP_ZDLE, 252, 252, 1, 0, 0, {ACT_DLE1} }, |
219 | {RSP_ERROR, 250,299, -1, 0, 0, {ACT_FAILDLE1}}, | 218 | {RSP_ERROR, 250, 299, -1, 0, 0, {ACT_FAILDLE1} }, |
220 | {EV_TIMEOUT, 250,299, -1, 0, 0, {ACT_FAILDLE1}}, | 219 | {EV_TIMEOUT, 250, 299, -1, 0, 0, {ACT_FAILDLE1} }, |
221 | 220 | ||
222 | /* incoming call */ | 221 | /* incoming call */ |
223 | {RSP_RING, -1, -1, -1, -1,-1, {ACT_RING}}, | 222 | {RSP_RING, -1, -1, -1, -1, -1, {ACT_RING} }, |
224 | 223 | ||
225 | /* get cid */ | 224 | /* get cid */ |
226 | //{RSP_INIT, 0, 0,300, 901, 0, {ACT_TEST}}, | 225 | {RSP_INIT, 0, 0, SEQ_CID, 301, 5, {0}, "^SGCI?\r"}, |
227 | //{RSP_ERROR, 901,901, -1, 0, 0, {ACT_FAILCID}}, | 226 | {RSP_OK, 301, 301, -1, 302, -1}, |
228 | //{RSP_OK, 901,901, -1, 301, 5, {0}, "^SGCI?\r"}, | 227 | {RSP_ZGCI, 302, 302, -1, 0, 0, {ACT_CID} }, |
229 | 228 | {RSP_ERROR, 301, 349, -1, 0, 0, {ACT_FAILCID} }, | |
230 | {RSP_INIT, 0, 0,SEQ_CID, 301, 5, {0}, "^SGCI?\r"}, | 229 | {EV_TIMEOUT, 301, 349, -1, 0, 0, {ACT_FAILCID} }, |
231 | {RSP_OK, 301,301, -1, 302,-1}, | 230 | |
232 | {RSP_ZGCI, 302,302, -1, 0, 0, {ACT_CID}}, | 231 | /* enter cid mode */ |
233 | {RSP_ERROR, 301,349, -1, 0, 0, {ACT_FAILCID}}, | 232 | {RSP_INIT, 0, 0, SEQ_CIDMODE, 150, 5, {0}, "^SGCI=1\r"}, |
234 | {EV_TIMEOUT, 301,349, -1, 0, 0, {ACT_FAILCID}}, | 233 | {RSP_OK, 150, 150, -1, 0, 0, {ACT_CMODESET} }, |
235 | 234 | {RSP_ERROR, 150, 150, -1, 0, 0, {ACT_FAILCMODE} }, | |
236 | /* enter cid mode */ | 235 | {EV_TIMEOUT, 150, 150, -1, 0, 0, {ACT_FAILCMODE} }, |
237 | {RSP_INIT, 0, 0,SEQ_CIDMODE, 150, 5, {0}, "^SGCI=1\r"}, | 236 | |
238 | {RSP_OK, 150,150, -1, 0, 0, {ACT_CMODESET}}, | 237 | /* leave cid mode */ |
239 | {RSP_ERROR, 150,150, -1, 0, 0, {ACT_FAILCMODE}}, | 238 | {RSP_INIT, 0, 0, SEQ_UMMODE, 160, 5, {0}, "Z\r"}, |
240 | {EV_TIMEOUT, 150,150, -1, 0, 0, {ACT_FAILCMODE}}, | 239 | {RSP_OK, 160, 160, -1, 0, 0, {ACT_UMODESET} }, |
241 | 240 | {RSP_ERROR, 160, 160, -1, 0, 0, {ACT_FAILUMODE} }, | |
242 | /* leave cid mode */ | 241 | {EV_TIMEOUT, 160, 160, -1, 0, 0, {ACT_FAILUMODE} }, |
243 | //{RSP_INIT, 0, 0,SEQ_UMMODE, 160, 5, {0}, "^SGCI=0\r"}, | 242 | |
244 | {RSP_INIT, 0, 0,SEQ_UMMODE, 160, 5, {0}, "Z\r"}, | 243 | /* abort getting cid */ |
245 | {RSP_OK, 160,160, -1, 0, 0, {ACT_UMODESET}}, | 244 | {RSP_INIT, 0, 0, SEQ_NOCID, 0, 0, {ACT_ABORTCID} }, |
246 | {RSP_ERROR, 160,160, -1, 0, 0, {ACT_FAILUMODE}}, | 245 | |
247 | {EV_TIMEOUT, 160,160, -1, 0, 0, {ACT_FAILUMODE}}, | 246 | /* reset */ |
248 | 247 | {RSP_INIT, 0, 0, SEQ_SHUTDOWN, 504, 5, {0}, "Z\r"}, | |
249 | /* abort getting cid */ | 248 | {RSP_OK, 504, 504, -1, 0, 0, {ACT_SDOWN} }, |
250 | {RSP_INIT, 0, 0,SEQ_NOCID, 0, 0, {ACT_ABORTCID}}, | 249 | {RSP_ERROR, 501, 599, -1, 0, 0, {ACT_FAILSDOWN} }, |
251 | 250 | {EV_TIMEOUT, 501, 599, -1, 0, 0, {ACT_FAILSDOWN} }, | |
252 | /* reset */ | 251 | {RSP_NODEV, 501, 599, -1, 0, 0, {ACT_FAKESDOWN} }, |
253 | {RSP_INIT, 0, 0,SEQ_SHUTDOWN, 504, 5, {0}, "Z\r"}, | 252 | |
254 | {RSP_OK, 504,504, -1, 0, 0, {ACT_SDOWN}}, | 253 | {EV_PROC_CIDMODE, -1, -1, -1, -1, -1, {ACT_PROC_CIDMODE} }, |
255 | {RSP_ERROR, 501,599, -1, 0, 0, {ACT_FAILSDOWN}}, | 254 | {EV_IF_LOCK, -1, -1, -1, -1, -1, {ACT_IF_LOCK} }, |
256 | {EV_TIMEOUT, 501,599, -1, 0, 0, {ACT_FAILSDOWN}}, | 255 | {EV_IF_VER, -1, -1, -1, -1, -1, {ACT_IF_VER} }, |
257 | {RSP_NODEV, 501,599, -1, 0, 0, {ACT_FAKESDOWN}}, | 256 | {EV_START, -1, -1, -1, -1, -1, {ACT_START} }, |
258 | 257 | {EV_STOP, -1, -1, -1, -1, -1, {ACT_STOP} }, | |
259 | {EV_PROC_CIDMODE,-1, -1, -1, -1,-1, {ACT_PROC_CIDMODE}}, //FIXME | 258 | {EV_SHUTDOWN, -1, -1, -1, -1, -1, {ACT_SHUTDOWN} }, |
260 | {EV_IF_LOCK, -1, -1, -1, -1,-1, {ACT_IF_LOCK}}, //FIXME | 259 | |
261 | {EV_IF_VER, -1, -1, -1, -1,-1, {ACT_IF_VER}}, //FIXME | 260 | /* misc. */ |
262 | {EV_START, -1, -1, -1, -1,-1, {ACT_START}}, //FIXME | 261 | {RSP_ERROR, -1, -1, -1, -1, -1, {ACT_ERROR} }, |
263 | {EV_STOP, -1, -1, -1, -1,-1, {ACT_STOP}}, //FIXME | 262 | {RSP_ZCFGT, -1, -1, -1, -1, -1, {ACT_DEBUG} }, |
264 | {EV_SHUTDOWN, -1, -1, -1, -1,-1, {ACT_SHUTDOWN}}, //FIXME | 263 | {RSP_ZCFG, -1, -1, -1, -1, -1, {ACT_DEBUG} }, |
265 | 264 | {RSP_ZLOG, -1, -1, -1, -1, -1, {ACT_DEBUG} }, | |
266 | /* misc. */ | 265 | {RSP_ZMWI, -1, -1, -1, -1, -1, {ACT_DEBUG} }, |
267 | {RSP_ERROR, -1, -1, -1, -1, -1, {ACT_ERROR} }, | 266 | {RSP_ZABINFO, -1, -1, -1, -1, -1, {ACT_DEBUG} }, |
268 | {RSP_EMPTY, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME | 267 | {RSP_ZSMLSTCHG, -1, -1, -1, -1, -1, {ACT_DEBUG} }, |
269 | {RSP_ZCFGT, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME | 268 | |
270 | {RSP_ZCFG, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME | 269 | {RSP_ZCAU, -1, -1, -1, -1, -1, {ACT_ZCAU} }, |
271 | {RSP_ZLOG, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME | 270 | {RSP_NONE, -1, -1, -1, -1, -1, {ACT_DEBUG} }, |
272 | {RSP_ZMWI, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME | 271 | {RSP_ANY, -1, -1, -1, -1, -1, {ACT_WARN} }, |
273 | {RSP_ZABINFO, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME | 272 | {RSP_LAST} |
274 | {RSP_ZSMLSTCHG,-1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME | ||
275 | |||
276 | {RSP_ZCAU, -1, -1, -1, -1,-1, {ACT_ZCAU}}, | ||
277 | {RSP_NONE, -1, -1, -1, -1,-1, {ACT_DEBUG}}, | ||
278 | {RSP_ANY, -1, -1, -1, -1,-1, {ACT_WARN}}, | ||
279 | {RSP_LAST} | ||
280 | }; | 273 | }; |
281 | 274 | ||
282 | // 600: start dialing, 650: dial in progress, 800: connection is up, 700: ring, 400: hup, 750: accepted icall | 275 | /* 600: start dialing, 650: dial in progress, 800: connection is up, 700: ring, |
276 | * 400: hup, 750: accepted icall */ | ||
283 | struct reply_t gigaset_tab_cid[] = | 277 | struct reply_t gigaset_tab_cid[] = |
284 | { | 278 | { |
285 | /* resp_code, min_ConState, max_ConState, parameter, new_ConState, timeout, action, command */ | 279 | /* resp_code, min_ConState, max_ConState, parameter, new_ConState, timeout, |
286 | 280 | * action, command */ | |
287 | /* dial */ | 281 | |
288 | {EV_DIAL, -1, -1, -1, -1,-1, {ACT_DIAL}}, //FIXME | 282 | /* dial */ |
289 | {RSP_INIT, 0, 0,SEQ_DIAL, 601, 5, {ACT_CMD+AT_BC}}, | 283 | {EV_DIAL, -1, -1, -1, -1, -1, {ACT_DIAL} }, |
290 | {RSP_OK, 601,601, -1, 602, 5, {ACT_CMD+AT_HLC}}, | 284 | {RSP_INIT, 0, 0, SEQ_DIAL, 601, 5, {ACT_CMD+AT_BC} }, |
291 | {RSP_NULL, 602,602, -1, 603, 5, {ACT_CMD+AT_PROTO}}, | 285 | {RSP_OK, 601, 601, -1, 602, 5, {ACT_CMD+AT_HLC} }, |
292 | {RSP_OK, 602,602, -1, 603, 5, {ACT_CMD+AT_PROTO}}, | 286 | {RSP_NULL, 602, 602, -1, 603, 5, {ACT_CMD+AT_PROTO} }, |
293 | {RSP_OK, 603,603, -1, 604, 5, {ACT_CMD+AT_TYPE}}, | 287 | {RSP_OK, 602, 602, -1, 603, 5, {ACT_CMD+AT_PROTO} }, |
294 | {RSP_OK, 604,604, -1, 605, 5, {ACT_CMD+AT_MSN}}, | 288 | {RSP_OK, 603, 603, -1, 604, 5, {ACT_CMD+AT_TYPE} }, |
295 | {RSP_OK, 605,605, -1, 606, 5, {ACT_CMD+AT_ISO}}, | 289 | {RSP_OK, 604, 604, -1, 605, 5, {ACT_CMD+AT_MSN} }, |
296 | {RSP_NULL, 605,605, -1, 606, 5, {ACT_CMD+AT_ISO}}, | 290 | {RSP_NULL, 605, 605, -1, 606, 5, {ACT_CMD+AT_CLIP} }, |
297 | {RSP_OK, 606,606, -1, 607, 5, {0}, "+VLS=17\r"}, | 291 | {RSP_OK, 605, 605, -1, 606, 5, {ACT_CMD+AT_CLIP} }, |
298 | {RSP_OK, 607,607, -1, 608,-1}, | 292 | {RSP_NULL, 606, 606, -1, 607, 5, {ACT_CMD+AT_ISO} }, |
299 | {RSP_ZSAU, 608,608,ZSAU_PROCEEDING, 609, 5, {ACT_CMD+AT_DIAL}}, | 293 | {RSP_OK, 606, 606, -1, 607, 5, {ACT_CMD+AT_ISO} }, |
300 | {RSP_OK, 609,609, -1, 650, 0, {ACT_DIALING}}, | 294 | {RSP_OK, 607, 607, -1, 608, 5, {0}, "+VLS=17\r"}, |
301 | 295 | {RSP_OK, 608, 608, -1, 609, -1}, | |
302 | {RSP_ERROR, 601,609, -1, 0, 0, {ACT_ABORTDIAL}}, | 296 | {RSP_ZSAU, 609, 609, ZSAU_PROCEEDING, 610, 5, {ACT_CMD+AT_DIAL} }, |
303 | {EV_TIMEOUT, 601,609, -1, 0, 0, {ACT_ABORTDIAL}}, | 297 | {RSP_OK, 610, 610, -1, 650, 0, {ACT_DIALING} }, |
304 | 298 | ||
305 | /* optional dialing responses */ | 299 | {RSP_ERROR, 601, 610, -1, 0, 0, {ACT_ABORTDIAL} }, |
306 | {EV_BC_OPEN, 650,650, -1, 651,-1}, | 300 | {EV_TIMEOUT, 601, 610, -1, 0, 0, {ACT_ABORTDIAL} }, |
307 | {RSP_ZVLS, 608,651, 17, -1,-1, {ACT_DEBUG}}, | 301 | |
308 | {RSP_ZCTP, 609,651, -1, -1,-1, {ACT_DEBUG}}, | 302 | /* optional dialing responses */ |
309 | {RSP_ZCPN, 609,651, -1, -1,-1, {ACT_DEBUG}}, | 303 | {EV_BC_OPEN, 650, 650, -1, 651, -1}, |
310 | {RSP_ZSAU, 650,651,ZSAU_CALL_DELIVERED, -1,-1, {ACT_DEBUG}}, | 304 | {RSP_ZVLS, 609, 651, 17, -1, -1, {ACT_DEBUG} }, |
311 | 305 | {RSP_ZCTP, 610, 651, -1, -1, -1, {ACT_DEBUG} }, | |
312 | /* connect */ | 306 | {RSP_ZCPN, 610, 651, -1, -1, -1, {ACT_DEBUG} }, |
313 | {RSP_ZSAU, 650,650,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT}}, | 307 | {RSP_ZSAU, 650, 651, ZSAU_CALL_DELIVERED, -1, -1, {ACT_DEBUG} }, |
314 | {RSP_ZSAU, 651,651,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT, | 308 | |
315 | ACT_NOTIFY_BC_UP}}, | 309 | /* connect */ |
316 | {RSP_ZSAU, 750,750,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT}}, | 310 | {RSP_ZSAU, 650, 650, ZSAU_ACTIVE, 800, -1, {ACT_CONNECT} }, |
317 | {RSP_ZSAU, 751,751,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT, | 311 | {RSP_ZSAU, 651, 651, ZSAU_ACTIVE, 800, -1, {ACT_CONNECT, |
318 | ACT_NOTIFY_BC_UP}}, | 312 | ACT_NOTIFY_BC_UP} }, |
319 | {EV_BC_OPEN, 800,800, -1, 800,-1, {ACT_NOTIFY_BC_UP}}, | 313 | {RSP_ZSAU, 750, 750, ZSAU_ACTIVE, 800, -1, {ACT_CONNECT} }, |
320 | 314 | {RSP_ZSAU, 751, 751, ZSAU_ACTIVE, 800, -1, {ACT_CONNECT, | |
321 | /* remote hangup */ | 315 | ACT_NOTIFY_BC_UP} }, |
322 | {RSP_ZSAU, 650,651,ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEREJECT}}, | 316 | {EV_BC_OPEN, 800, 800, -1, 800, -1, {ACT_NOTIFY_BC_UP} }, |
323 | {RSP_ZSAU, 750,751,ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP}}, | 317 | |
324 | {RSP_ZSAU, 800,800,ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP}}, | 318 | /* remote hangup */ |
325 | 319 | {RSP_ZSAU, 650, 651, ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEREJECT} }, | |
326 | /* hangup */ | 320 | {RSP_ZSAU, 750, 751, ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP} }, |
327 | {EV_HUP, -1, -1, -1, -1,-1, {ACT_HUP}}, //FIXME | 321 | {RSP_ZSAU, 800, 800, ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP} }, |
328 | {RSP_INIT, -1, -1,SEQ_HUP, 401, 5, {0}, "+VLS=0\r"}, /* hang up */ //-1,-1? | 322 | |
329 | {RSP_OK, 401,401, -1, 402, 5}, | 323 | /* hangup */ |
330 | {RSP_ZVLS, 402,402, 0, 403, 5}, | 324 | {EV_HUP, -1, -1, -1, -1, -1, {ACT_HUP} }, |
331 | {RSP_ZSAU, 403, 403, ZSAU_DISCONNECT_REQ, -1, -1, {ACT_DEBUG} }, | 325 | {RSP_INIT, -1, -1, SEQ_HUP, 401, 5, {0}, "+VLS=0\r"}, |
332 | {RSP_ZSAU, 403, 403, ZSAU_NULL, 0, 0, {ACT_DISCONNECT} }, | 326 | {RSP_OK, 401, 401, -1, 402, 5}, |
333 | {RSP_NODEV, 401, 403, -1, 0, 0, {ACT_FAKEHUP} }, | 327 | {RSP_ZVLS, 402, 402, 0, 403, 5}, |
334 | {RSP_ERROR, 401,401, -1, 0, 0, {ACT_ABORTHUP}}, | 328 | {RSP_ZSAU, 403, 403, ZSAU_DISCONNECT_REQ, -1, -1, {ACT_DEBUG} }, |
335 | {EV_TIMEOUT, 401,403, -1, 0, 0, {ACT_ABORTHUP}}, | 329 | {RSP_ZSAU, 403, 403, ZSAU_NULL, 0, 0, {ACT_DISCONNECT} }, |
336 | 330 | {RSP_NODEV, 401, 403, -1, 0, 0, {ACT_FAKEHUP} }, | |
337 | {EV_BC_CLOSED, 0, 0, -1, 0,-1, {ACT_NOTIFY_BC_DOWN}}, //FIXME new constate + timeout | 331 | {RSP_ERROR, 401, 401, -1, 0, 0, {ACT_ABORTHUP} }, |
338 | 332 | {EV_TIMEOUT, 401, 403, -1, 0, 0, {ACT_ABORTHUP} }, | |
339 | /* ring */ | 333 | |
340 | {RSP_ZBC, 700,700, -1, -1,-1, {0}}, | 334 | {EV_BC_CLOSED, 0, 0, -1, 0, -1, {ACT_NOTIFY_BC_DOWN} }, |
341 | {RSP_ZHLC, 700,700, -1, -1,-1, {0}}, | 335 | |
342 | {RSP_NMBR, 700,700, -1, -1,-1, {0}}, | 336 | /* ring */ |
343 | {RSP_ZCPN, 700,700, -1, -1,-1, {0}}, | 337 | {RSP_ZBC, 700, 700, -1, -1, -1, {0} }, |
344 | {RSP_ZCTP, 700,700, -1, -1,-1, {0}}, | 338 | {RSP_ZHLC, 700, 700, -1, -1, -1, {0} }, |
345 | {EV_TIMEOUT, 700,700, -1, 720,720, {ACT_ICALL}}, | 339 | {RSP_NMBR, 700, 700, -1, -1, -1, {0} }, |
346 | {EV_BC_CLOSED,720,720, -1, 0,-1, {ACT_NOTIFY_BC_DOWN}}, | 340 | {RSP_ZCPN, 700, 700, -1, -1, -1, {0} }, |
347 | 341 | {RSP_ZCTP, 700, 700, -1, -1, -1, {0} }, | |
348 | /*accept icall*/ | 342 | {EV_TIMEOUT, 700, 700, -1, 720, 720, {ACT_ICALL} }, |
349 | {EV_ACCEPT, -1, -1, -1, -1,-1, {ACT_ACCEPT}}, //FIXME | 343 | {EV_BC_CLOSED, 720, 720, -1, 0, -1, {ACT_NOTIFY_BC_DOWN} }, |
350 | {RSP_INIT, 720,720,SEQ_ACCEPT, 721, 5, {ACT_CMD+AT_PROTO}}, | 344 | |
351 | {RSP_OK, 721,721, -1, 722, 5, {ACT_CMD+AT_ISO}}, | 345 | /*accept icall*/ |
352 | {RSP_OK, 722,722, -1, 723, 5, {0}, "+VLS=17\r"}, /* set "Endgeraetemodus" */ | 346 | {EV_ACCEPT, -1, -1, -1, -1, -1, {ACT_ACCEPT} }, |
353 | {RSP_OK, 723,723, -1, 724, 5, {0}}, | 347 | {RSP_INIT, 720, 720, SEQ_ACCEPT, 721, 5, {ACT_CMD+AT_PROTO} }, |
354 | {RSP_ZVLS, 724,724, 17, 750,50, {ACT_ACCEPTED}}, | 348 | {RSP_OK, 721, 721, -1, 722, 5, {ACT_CMD+AT_ISO} }, |
355 | {RSP_ERROR, 721,729, -1, 0, 0, {ACT_ABORTACCEPT}}, | 349 | {RSP_OK, 722, 722, -1, 723, 5, {0}, "+VLS=17\r"}, |
356 | {EV_TIMEOUT, 721,729, -1, 0, 0, {ACT_ABORTACCEPT}}, | 350 | {RSP_OK, 723, 723, -1, 724, 5, {0} }, |
357 | {RSP_ZSAU, 700,729,ZSAU_NULL, 0, 0, {ACT_ABORTACCEPT}}, | 351 | {RSP_ZVLS, 724, 724, 17, 750, 50, {ACT_ACCEPTED} }, |
358 | {RSP_ZSAU, 700,729,ZSAU_ACTIVE, 0, 0, {ACT_ABORTACCEPT}}, | 352 | {RSP_ERROR, 721, 729, -1, 0, 0, {ACT_ABORTACCEPT} }, |
359 | {RSP_ZSAU, 700,729,ZSAU_DISCONNECT_IND, 0, 0, {ACT_ABORTACCEPT}}, | 353 | {EV_TIMEOUT, 721, 729, -1, 0, 0, {ACT_ABORTACCEPT} }, |
360 | 354 | {RSP_ZSAU, 700, 729, ZSAU_NULL, 0, 0, {ACT_ABORTACCEPT} }, | |
361 | {EV_BC_OPEN, 750,750, -1, 751,-1}, | 355 | {RSP_ZSAU, 700, 729, ZSAU_ACTIVE, 0, 0, {ACT_ABORTACCEPT} }, |
362 | {EV_TIMEOUT, 750,751, -1, 0, 0, {ACT_CONNTIMEOUT}}, | 356 | {RSP_ZSAU, 700, 729, ZSAU_DISCONNECT_IND, 0, 0, {ACT_ABORTACCEPT} }, |
363 | 357 | ||
364 | /* B channel closed (general case) */ | 358 | {EV_BC_OPEN, 750, 750, -1, 751, -1}, |
365 | {EV_BC_CLOSED, -1, -1, -1, -1,-1, {ACT_NOTIFY_BC_DOWN}}, //FIXME | 359 | {EV_TIMEOUT, 750, 751, -1, 0, 0, {ACT_CONNTIMEOUT} }, |
366 | 360 | ||
367 | /* misc. */ | 361 | /* B channel closed (general case) */ |
368 | {EV_PROTO_L2, -1, -1, -1, -1,-1, {ACT_PROTO_L2}}, //FIXME | 362 | {EV_BC_CLOSED, -1, -1, -1, -1, -1, {ACT_NOTIFY_BC_DOWN} }, |
369 | 363 | ||
370 | {RSP_ZCON, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME | 364 | /* misc. */ |
371 | {RSP_ZCCR, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME | 365 | {RSP_ZCON, -1, -1, -1, -1, -1, {ACT_DEBUG} }, |
372 | {RSP_ZAOC, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME | 366 | {RSP_ZCCR, -1, -1, -1, -1, -1, {ACT_DEBUG} }, |
373 | {RSP_ZCSTR, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME | 367 | {RSP_ZAOC, -1, -1, -1, -1, -1, {ACT_DEBUG} }, |
374 | 368 | {RSP_ZCSTR, -1, -1, -1, -1, -1, {ACT_DEBUG} }, | |
375 | {RSP_ZCAU, -1, -1, -1, -1,-1, {ACT_ZCAU}}, | 369 | |
376 | {RSP_NONE, -1, -1, -1, -1,-1, {ACT_DEBUG}}, | 370 | {RSP_ZCAU, -1, -1, -1, -1, -1, {ACT_ZCAU} }, |
377 | {RSP_ANY, -1, -1, -1, -1,-1, {ACT_WARN}}, | 371 | {RSP_NONE, -1, -1, -1, -1, -1, {ACT_DEBUG} }, |
378 | {RSP_LAST} | 372 | {RSP_ANY, -1, -1, -1, -1, -1, {ACT_WARN} }, |
373 | {RSP_LAST} | ||
379 | }; | 374 | }; |
380 | 375 | ||
381 | 376 | ||
382 | static const struct resp_type_t resp_type[] = | 377 | static const struct resp_type_t { |
378 | unsigned char *response; | ||
379 | int resp_code; | ||
380 | int type; | ||
381 | } resp_type[] = | ||
383 | { | 382 | { |
384 | /*{"", RSP_EMPTY, RT_NOTHING},*/ | ||
385 | {"OK", RSP_OK, RT_NOTHING}, | 383 | {"OK", RSP_OK, RT_NOTHING}, |
386 | {"ERROR", RSP_ERROR, RT_NOTHING}, | 384 | {"ERROR", RSP_ERROR, RT_NOTHING}, |
387 | {"ZSAU", RSP_ZSAU, RT_ZSAU}, | 385 | {"ZSAU", RSP_ZSAU, RT_ZSAU}, |
@@ -405,7 +403,21 @@ static const struct resp_type_t resp_type[] = | |||
405 | {"ZLOG", RSP_ZLOG, RT_NOTHING}, | 403 | {"ZLOG", RSP_ZLOG, RT_NOTHING}, |
406 | {"ZABINFO", RSP_ZABINFO, RT_NOTHING}, | 404 | {"ZABINFO", RSP_ZABINFO, RT_NOTHING}, |
407 | {"ZSMLSTCHG", RSP_ZSMLSTCHG, RT_NOTHING}, | 405 | {"ZSMLSTCHG", RSP_ZSMLSTCHG, RT_NOTHING}, |
408 | {NULL,0,0} | 406 | {NULL, 0, 0} |
407 | }; | ||
408 | |||
409 | static const struct zsau_resp_t { | ||
410 | unsigned char *str; | ||
411 | int code; | ||
412 | } zsau_resp[] = | ||
413 | { | ||
414 | {"OUTGOING_CALL_PROCEEDING", ZSAU_OUTGOING_CALL_PROCEEDING}, | ||
415 | {"CALL_DELIVERED", ZSAU_CALL_DELIVERED}, | ||
416 | {"ACTIVE", ZSAU_ACTIVE}, | ||
417 | {"DISCONNECT_IND", ZSAU_DISCONNECT_IND}, | ||
418 | {"NULL", ZSAU_NULL}, | ||
419 | {"DISCONNECT_REQ", ZSAU_DISCONNECT_REQ}, | ||
420 | {NULL, ZSAU_UNKNOWN} | ||
409 | }; | 421 | }; |
410 | 422 | ||
411 | /* | 423 | /* |
@@ -415,7 +427,7 @@ static int isdn_getnum(char *p) | |||
415 | { | 427 | { |
416 | int v = -1; | 428 | int v = -1; |
417 | 429 | ||
418 | gig_dbg(DEBUG_TRANSCMD, "string: %s", p); | 430 | gig_dbg(DEBUG_EVENT, "string: %s", p); |
419 | 431 | ||
420 | while (*p >= '0' && *p <= '9') | 432 | while (*p >= '0' && *p <= '9') |
421 | v = ((v < 0) ? 0 : (v * 10)) + (int) ((*p++) - '0'); | 433 | v = ((v < 0) ? 0 : (v * 10)) + (int) ((*p++) - '0'); |
@@ -432,7 +444,7 @@ static int isdn_gethex(char *p) | |||
432 | int v = 0; | 444 | int v = 0; |
433 | int c; | 445 | int c; |
434 | 446 | ||
435 | gig_dbg(DEBUG_TRANSCMD, "string: %s", p); | 447 | gig_dbg(DEBUG_EVENT, "string: %s", p); |
436 | 448 | ||
437 | if (!*p) | 449 | if (!*p) |
438 | return -1; | 450 | return -1; |
@@ -470,7 +482,6 @@ static int cid_of_response(char *s) | |||
470 | if (cid < 1 || cid > 65535) | 482 | if (cid < 1 || cid > 65535) |
471 | return -1; /* CID out of range */ | 483 | return -1; /* CID out of range */ |
472 | return cid; | 484 | return cid; |
473 | //FIXME is ;<digit>+ at end of non-CID response really impossible? | ||
474 | } | 485 | } |
475 | 486 | ||
476 | /** | 487 | /** |
@@ -487,6 +498,7 @@ void gigaset_handle_modem_response(struct cardstate *cs) | |||
487 | int params; | 498 | int params; |
488 | int i, j; | 499 | int i, j; |
489 | const struct resp_type_t *rt; | 500 | const struct resp_type_t *rt; |
501 | const struct zsau_resp_t *zr; | ||
490 | int curarg; | 502 | int curarg; |
491 | unsigned long flags; | 503 | unsigned long flags; |
492 | unsigned next, tail, head; | 504 | unsigned next, tail, head; |
@@ -505,7 +517,6 @@ void gigaset_handle_modem_response(struct cardstate *cs) | |||
505 | return; | 517 | return; |
506 | } | 518 | } |
507 | cs->respdata[len] = 0; | 519 | cs->respdata[len] = 0; |
508 | gig_dbg(DEBUG_TRANSCMD, "raw string: '%s'", cs->respdata); | ||
509 | argv[0] = cs->respdata; | 520 | argv[0] = cs->respdata; |
510 | params = 1; | 521 | params = 1; |
511 | if (cs->at_state.getstring) { | 522 | if (cs->at_state.getstring) { |
@@ -540,14 +551,14 @@ void gigaset_handle_modem_response(struct cardstate *cs) | |||
540 | for (j = 1; j < params; ++j) | 551 | for (j = 1; j < params; ++j) |
541 | argv[j][-1] = 0; | 552 | argv[j][-1] = 0; |
542 | 553 | ||
543 | gig_dbg(DEBUG_TRANSCMD, "CMD received: %s", argv[0]); | 554 | gig_dbg(DEBUG_EVENT, "CMD received: %s", argv[0]); |
544 | if (cid) { | 555 | if (cid) { |
545 | --params; | 556 | --params; |
546 | gig_dbg(DEBUG_TRANSCMD, "CID: %s", argv[params]); | 557 | gig_dbg(DEBUG_EVENT, "CID: %s", argv[params]); |
547 | } | 558 | } |
548 | gig_dbg(DEBUG_TRANSCMD, "available params: %d", params - 1); | 559 | gig_dbg(DEBUG_EVENT, "available params: %d", params - 1); |
549 | for (j = 1; j < params; j++) | 560 | for (j = 1; j < params; j++) |
550 | gig_dbg(DEBUG_TRANSCMD, "param %d: %s", j, argv[j]); | 561 | gig_dbg(DEBUG_EVENT, "param %d: %s", j, argv[j]); |
551 | } | 562 | } |
552 | 563 | ||
553 | spin_lock_irqsave(&cs->ev_lock, flags); | 564 | spin_lock_irqsave(&cs->ev_lock, flags); |
@@ -613,24 +624,14 @@ void gigaset_handle_modem_response(struct cardstate *cs) | |||
613 | event->parameter = ZSAU_NONE; | 624 | event->parameter = ZSAU_NONE; |
614 | break; | 625 | break; |
615 | } | 626 | } |
616 | if (!strcmp(argv[curarg], "OUTGOING_CALL_PROCEEDING")) | 627 | for (zr = zsau_resp; zr->str; ++zr) |
617 | event->parameter = ZSAU_OUTGOING_CALL_PROCEEDING; | 628 | if (!strcmp(argv[curarg], zr->str)) |
618 | else if (!strcmp(argv[curarg], "CALL_DELIVERED")) | 629 | break; |
619 | event->parameter = ZSAU_CALL_DELIVERED; | 630 | event->parameter = zr->code; |
620 | else if (!strcmp(argv[curarg], "ACTIVE")) | 631 | if (!zr->str) |
621 | event->parameter = ZSAU_ACTIVE; | ||
622 | else if (!strcmp(argv[curarg], "DISCONNECT_IND")) | ||
623 | event->parameter = ZSAU_DISCONNECT_IND; | ||
624 | else if (!strcmp(argv[curarg], "NULL")) | ||
625 | event->parameter = ZSAU_NULL; | ||
626 | else if (!strcmp(argv[curarg], "DISCONNECT_REQ")) | ||
627 | event->parameter = ZSAU_DISCONNECT_REQ; | ||
628 | else { | ||
629 | event->parameter = ZSAU_UNKNOWN; | ||
630 | dev_warn(cs->dev, | 632 | dev_warn(cs->dev, |
631 | "%s: unknown parameter %s after ZSAU\n", | 633 | "%s: unknown parameter %s after ZSAU\n", |
632 | __func__, argv[curarg]); | 634 | __func__, argv[curarg]); |
633 | } | ||
634 | ++curarg; | 635 | ++curarg; |
635 | break; | 636 | break; |
636 | case RT_STRING: | 637 | case RT_STRING: |
@@ -640,7 +641,7 @@ void gigaset_handle_modem_response(struct cardstate *cs) | |||
640 | dev_err(cs->dev, "out of memory\n"); | 641 | dev_err(cs->dev, "out of memory\n"); |
641 | ++curarg; | 642 | ++curarg; |
642 | } | 643 | } |
643 | gig_dbg(DEBUG_CMD, "string==%s", | 644 | gig_dbg(DEBUG_EVENT, "string==%s", |
644 | event->ptr ? (char *) event->ptr : "NULL"); | 645 | event->ptr ? (char *) event->ptr : "NULL"); |
645 | break; | 646 | break; |
646 | case RT_ZCAU: | 647 | case RT_ZCAU: |
@@ -667,7 +668,7 @@ void gigaset_handle_modem_response(struct cardstate *cs) | |||
667 | ++curarg; | 668 | ++curarg; |
668 | } else | 669 | } else |
669 | event->parameter = -1; | 670 | event->parameter = -1; |
670 | gig_dbg(DEBUG_CMD, "parameter==%d", event->parameter); | 671 | gig_dbg(DEBUG_EVENT, "parameter==%d", event->parameter); |
671 | break; | 672 | break; |
672 | } | 673 | } |
673 | 674 | ||
@@ -682,7 +683,7 @@ void gigaset_handle_modem_response(struct cardstate *cs) | |||
682 | spin_unlock_irqrestore(&cs->ev_lock, flags); | 683 | spin_unlock_irqrestore(&cs->ev_lock, flags); |
683 | 684 | ||
684 | if (curarg != params) | 685 | if (curarg != params) |
685 | gig_dbg(DEBUG_ANY, | 686 | gig_dbg(DEBUG_EVENT, |
686 | "invalid number of processed parameters: %d/%d", | 687 | "invalid number of processed parameters: %d/%d", |
687 | curarg, params); | 688 | curarg, params); |
688 | } | 689 | } |
@@ -703,8 +704,8 @@ static void disconnect(struct at_state_t **at_state_p) | |||
703 | /* revert to selected idle mode */ | 704 | /* revert to selected idle mode */ |
704 | if (!cs->cidmode) { | 705 | if (!cs->cidmode) { |
705 | cs->at_state.pending_commands |= PC_UMMODE; | 706 | cs->at_state.pending_commands |= PC_UMMODE; |
707 | gig_dbg(DEBUG_EVENT, "Scheduling PC_UMMODE"); | ||
706 | cs->commands_pending = 1; | 708 | cs->commands_pending = 1; |
707 | gig_dbg(DEBUG_CMD, "Scheduling PC_UMMODE"); | ||
708 | } | 709 | } |
709 | spin_unlock_irqrestore(&cs->lock, flags); | 710 | spin_unlock_irqrestore(&cs->lock, flags); |
710 | 711 | ||
@@ -714,7 +715,7 @@ static void disconnect(struct at_state_t **at_state_p) | |||
714 | /* notify LL */ | 715 | /* notify LL */ |
715 | if (bcs->chstate & (CHS_D_UP | CHS_NOTIFY_LL)) { | 716 | if (bcs->chstate & (CHS_D_UP | CHS_NOTIFY_LL)) { |
716 | bcs->chstate &= ~(CHS_D_UP | CHS_NOTIFY_LL); | 717 | bcs->chstate &= ~(CHS_D_UP | CHS_NOTIFY_LL); |
717 | gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DHUP); | 718 | gigaset_isdn_hupD(bcs); |
718 | } | 719 | } |
719 | } else { | 720 | } else { |
720 | /* no B channel assigned: just deallocate */ | 721 | /* no B channel assigned: just deallocate */ |
@@ -782,15 +783,15 @@ static void init_failed(struct cardstate *cs, int mode) | |||
782 | static void schedule_init(struct cardstate *cs, int state) | 783 | static void schedule_init(struct cardstate *cs, int state) |
783 | { | 784 | { |
784 | if (cs->at_state.pending_commands & PC_INIT) { | 785 | if (cs->at_state.pending_commands & PC_INIT) { |
785 | gig_dbg(DEBUG_CMD, "not scheduling PC_INIT again"); | 786 | gig_dbg(DEBUG_EVENT, "not scheduling PC_INIT again"); |
786 | return; | 787 | return; |
787 | } | 788 | } |
788 | cs->mstate = state; | 789 | cs->mstate = state; |
789 | cs->mode = M_UNKNOWN; | 790 | cs->mode = M_UNKNOWN; |
790 | gigaset_block_channels(cs); | 791 | gigaset_block_channels(cs); |
791 | cs->at_state.pending_commands |= PC_INIT; | 792 | cs->at_state.pending_commands |= PC_INIT; |
793 | gig_dbg(DEBUG_EVENT, "Scheduling PC_INIT"); | ||
792 | cs->commands_pending = 1; | 794 | cs->commands_pending = 1; |
793 | gig_dbg(DEBUG_CMD, "Scheduling PC_INIT"); | ||
794 | } | 795 | } |
795 | 796 | ||
796 | /* Add "AT" to a command, add the cid, dle encode it, send the result to the | 797 | /* Add "AT" to a command, add the cid, dle encode it, send the result to the |
@@ -872,12 +873,12 @@ static void bchannel_down(struct bc_state *bcs) | |||
872 | { | 873 | { |
873 | if (bcs->chstate & CHS_B_UP) { | 874 | if (bcs->chstate & CHS_B_UP) { |
874 | bcs->chstate &= ~CHS_B_UP; | 875 | bcs->chstate &= ~CHS_B_UP; |
875 | gigaset_i4l_channel_cmd(bcs, ISDN_STAT_BHUP); | 876 | gigaset_isdn_hupB(bcs); |
876 | } | 877 | } |
877 | 878 | ||
878 | if (bcs->chstate & (CHS_D_UP | CHS_NOTIFY_LL)) { | 879 | if (bcs->chstate & (CHS_D_UP | CHS_NOTIFY_LL)) { |
879 | bcs->chstate &= ~(CHS_D_UP | CHS_NOTIFY_LL); | 880 | bcs->chstate &= ~(CHS_D_UP | CHS_NOTIFY_LL); |
880 | gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DHUP); | 881 | gigaset_isdn_hupD(bcs); |
881 | } | 882 | } |
882 | 883 | ||
883 | gigaset_free_channel(bcs); | 884 | gigaset_free_channel(bcs); |
@@ -894,15 +895,17 @@ static void bchannel_up(struct bc_state *bcs) | |||
894 | } | 895 | } |
895 | 896 | ||
896 | bcs->chstate |= CHS_B_UP; | 897 | bcs->chstate |= CHS_B_UP; |
897 | gigaset_i4l_channel_cmd(bcs, ISDN_STAT_BCONN); | 898 | gigaset_isdn_connB(bcs); |
898 | } | 899 | } |
899 | 900 | ||
900 | static void start_dial(struct at_state_t *at_state, void *data, unsigned seq_index) | 901 | static void start_dial(struct at_state_t *at_state, void *data, |
902 | unsigned seq_index) | ||
901 | { | 903 | { |
902 | struct bc_state *bcs = at_state->bcs; | 904 | struct bc_state *bcs = at_state->bcs; |
903 | struct cardstate *cs = at_state->cs; | 905 | struct cardstate *cs = at_state->cs; |
904 | int retval; | 906 | char **commands = data; |
905 | unsigned long flags; | 907 | unsigned long flags; |
908 | int i; | ||
906 | 909 | ||
907 | bcs->chstate |= CHS_NOTIFY_LL; | 910 | bcs->chstate |= CHS_NOTIFY_LL; |
908 | 911 | ||
@@ -913,19 +916,23 @@ static void start_dial(struct at_state_t *at_state, void *data, unsigned seq_ind | |||
913 | } | 916 | } |
914 | spin_unlock_irqrestore(&cs->lock, flags); | 917 | spin_unlock_irqrestore(&cs->lock, flags); |
915 | 918 | ||
916 | retval = gigaset_isdn_setup_dial(at_state, data); | 919 | for (i = 0; i < AT_NUM; ++i) { |
917 | if (retval != 0) | 920 | kfree(bcs->commands[i]); |
918 | goto error; | 921 | bcs->commands[i] = commands[i]; |
919 | 922 | } | |
920 | 923 | ||
921 | at_state->pending_commands |= PC_CID; | 924 | at_state->pending_commands |= PC_CID; |
922 | gig_dbg(DEBUG_CMD, "Scheduling PC_CID"); | 925 | gig_dbg(DEBUG_EVENT, "Scheduling PC_CID"); |
923 | cs->commands_pending = 1; | 926 | cs->commands_pending = 1; |
924 | return; | 927 | return; |
925 | 928 | ||
926 | error: | 929 | error: |
930 | for (i = 0; i < AT_NUM; ++i) { | ||
931 | kfree(commands[i]); | ||
932 | commands[i] = NULL; | ||
933 | } | ||
927 | at_state->pending_commands |= PC_NOCID; | 934 | at_state->pending_commands |= PC_NOCID; |
928 | gig_dbg(DEBUG_CMD, "Scheduling PC_NOCID"); | 935 | gig_dbg(DEBUG_EVENT, "Scheduling PC_NOCID"); |
929 | cs->commands_pending = 1; | 936 | cs->commands_pending = 1; |
930 | return; | 937 | return; |
931 | } | 938 | } |
@@ -933,20 +940,31 @@ error: | |||
933 | static void start_accept(struct at_state_t *at_state) | 940 | static void start_accept(struct at_state_t *at_state) |
934 | { | 941 | { |
935 | struct cardstate *cs = at_state->cs; | 942 | struct cardstate *cs = at_state->cs; |
936 | int retval; | 943 | struct bc_state *bcs = at_state->bcs; |
944 | int i; | ||
937 | 945 | ||
938 | retval = gigaset_isdn_setup_accept(at_state); | 946 | for (i = 0; i < AT_NUM; ++i) { |
947 | kfree(bcs->commands[i]); | ||
948 | bcs->commands[i] = NULL; | ||
949 | } | ||
939 | 950 | ||
940 | if (retval == 0) { | 951 | bcs->commands[AT_PROTO] = kmalloc(9, GFP_ATOMIC); |
941 | at_state->pending_commands |= PC_ACCEPT; | 952 | bcs->commands[AT_ISO] = kmalloc(9, GFP_ATOMIC); |
942 | gig_dbg(DEBUG_CMD, "Scheduling PC_ACCEPT"); | 953 | if (!bcs->commands[AT_PROTO] || !bcs->commands[AT_ISO]) { |
943 | cs->commands_pending = 1; | 954 | dev_err(at_state->cs->dev, "out of memory\n"); |
944 | } else { | ||
945 | /* error reset */ | 955 | /* error reset */ |
946 | at_state->pending_commands |= PC_HUP; | 956 | at_state->pending_commands |= PC_HUP; |
947 | gig_dbg(DEBUG_CMD, "Scheduling PC_HUP"); | 957 | gig_dbg(DEBUG_EVENT, "Scheduling PC_HUP"); |
948 | cs->commands_pending = 1; | 958 | cs->commands_pending = 1; |
959 | return; | ||
949 | } | 960 | } |
961 | |||
962 | snprintf(bcs->commands[AT_PROTO], 9, "^SBPR=%u\r", bcs->proto2); | ||
963 | snprintf(bcs->commands[AT_ISO], 9, "^SISO=%u\r", bcs->channel + 1); | ||
964 | |||
965 | at_state->pending_commands |= PC_ACCEPT; | ||
966 | gig_dbg(DEBUG_EVENT, "Scheduling PC_ACCEPT"); | ||
967 | cs->commands_pending = 1; | ||
950 | } | 968 | } |
951 | 969 | ||
952 | static void do_start(struct cardstate *cs) | 970 | static void do_start(struct cardstate *cs) |
@@ -957,9 +975,7 @@ static void do_start(struct cardstate *cs) | |||
957 | schedule_init(cs, MS_INIT); | 975 | schedule_init(cs, MS_INIT); |
958 | 976 | ||
959 | cs->isdn_up = 1; | 977 | cs->isdn_up = 1; |
960 | gigaset_i4l_cmd(cs, ISDN_STAT_RUN); | 978 | gigaset_isdn_start(cs); |
961 | // FIXME: not in locked mode | ||
962 | // FIXME 2: only after init sequence | ||
963 | 979 | ||
964 | cs->waiting = 0; | 980 | cs->waiting = 0; |
965 | wake_up(&cs->waitqueue); | 981 | wake_up(&cs->waitqueue); |
@@ -975,7 +991,7 @@ static void finish_shutdown(struct cardstate *cs) | |||
975 | /* Tell the LL that the device is not available .. */ | 991 | /* Tell the LL that the device is not available .. */ |
976 | if (cs->isdn_up) { | 992 | if (cs->isdn_up) { |
977 | cs->isdn_up = 0; | 993 | cs->isdn_up = 0; |
978 | gigaset_i4l_cmd(cs, ISDN_STAT_STOP); | 994 | gigaset_isdn_stop(cs); |
979 | } | 995 | } |
980 | 996 | ||
981 | /* The rest is done by cleanup_cs () in user mode. */ | 997 | /* The rest is done by cleanup_cs () in user mode. */ |
@@ -992,8 +1008,8 @@ static void do_shutdown(struct cardstate *cs) | |||
992 | if (cs->mstate == MS_READY) { | 1008 | if (cs->mstate == MS_READY) { |
993 | cs->mstate = MS_SHUTDOWN; | 1009 | cs->mstate = MS_SHUTDOWN; |
994 | cs->at_state.pending_commands |= PC_SHUTDOWN; | 1010 | cs->at_state.pending_commands |= PC_SHUTDOWN; |
1011 | gig_dbg(DEBUG_EVENT, "Scheduling PC_SHUTDOWN"); | ||
995 | cs->commands_pending = 1; | 1012 | cs->commands_pending = 1; |
996 | gig_dbg(DEBUG_CMD, "Scheduling PC_SHUTDOWN"); | ||
997 | } else | 1013 | } else |
998 | finish_shutdown(cs); | 1014 | finish_shutdown(cs); |
999 | } | 1015 | } |
@@ -1113,7 +1129,6 @@ static int do_lock(struct cardstate *cs) | |||
1113 | 1129 | ||
1114 | break; | 1130 | break; |
1115 | case MS_LOCKED: | 1131 | case MS_LOCKED: |
1116 | //retval = -EACCES; | ||
1117 | break; | 1132 | break; |
1118 | default: | 1133 | default: |
1119 | return -EBUSY; | 1134 | return -EBUSY; |
@@ -1175,8 +1190,8 @@ static void do_action(int action, struct cardstate *cs, | |||
1175 | } | 1190 | } |
1176 | spin_unlock_irqrestore(&cs->lock, flags); | 1191 | spin_unlock_irqrestore(&cs->lock, flags); |
1177 | cs->at_state.pending_commands |= PC_CIDMODE; | 1192 | cs->at_state.pending_commands |= PC_CIDMODE; |
1193 | gig_dbg(DEBUG_EVENT, "Scheduling PC_CIDMODE"); | ||
1178 | cs->commands_pending = 1; | 1194 | cs->commands_pending = 1; |
1179 | gig_dbg(DEBUG_CMD, "Scheduling PC_CIDMODE"); | ||
1180 | break; | 1195 | break; |
1181 | case ACT_FAILINIT: | 1196 | case ACT_FAILINIT: |
1182 | dev_warn(cs->dev, "Could not initialize the device.\n"); | 1197 | dev_warn(cs->dev, "Could not initialize the device.\n"); |
@@ -1243,14 +1258,10 @@ static void do_action(int action, struct cardstate *cs, | |||
1243 | * note that bcs may be NULL if no B channel is free | 1258 | * note that bcs may be NULL if no B channel is free |
1244 | */ | 1259 | */ |
1245 | at_state2->ConState = 700; | 1260 | at_state2->ConState = 700; |
1246 | kfree(at_state2->str_var[STR_NMBR]); | 1261 | for (i = 0; i < STR_NUM; ++i) { |
1247 | at_state2->str_var[STR_NMBR] = NULL; | 1262 | kfree(at_state2->str_var[i]); |
1248 | kfree(at_state2->str_var[STR_ZCPN]); | 1263 | at_state2->str_var[i] = NULL; |
1249 | at_state2->str_var[STR_ZCPN] = NULL; | 1264 | } |
1250 | kfree(at_state2->str_var[STR_ZBC]); | ||
1251 | at_state2->str_var[STR_ZBC] = NULL; | ||
1252 | kfree(at_state2->str_var[STR_ZHLC]); | ||
1253 | at_state2->str_var[STR_ZHLC] = NULL; | ||
1254 | at_state2->int_var[VAR_ZCTP] = -1; | 1265 | at_state2->int_var[VAR_ZCTP] = -1; |
1255 | 1266 | ||
1256 | spin_lock_irqsave(&cs->lock, flags); | 1267 | spin_lock_irqsave(&cs->lock, flags); |
@@ -1276,7 +1287,7 @@ static void do_action(int action, struct cardstate *cs, | |||
1276 | break; | 1287 | break; |
1277 | } | 1288 | } |
1278 | bcs->chstate |= CHS_D_UP; | 1289 | bcs->chstate |= CHS_D_UP; |
1279 | gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DCONN); | 1290 | gigaset_isdn_connD(bcs); |
1280 | cs->ops->init_bchannel(bcs); | 1291 | cs->ops->init_bchannel(bcs); |
1281 | break; | 1292 | break; |
1282 | case ACT_DLE1: | 1293 | case ACT_DLE1: |
@@ -1284,7 +1295,7 @@ static void do_action(int action, struct cardstate *cs, | |||
1284 | bcs = cs->bcs + cs->curchannel; | 1295 | bcs = cs->bcs + cs->curchannel; |
1285 | 1296 | ||
1286 | bcs->chstate |= CHS_D_UP; | 1297 | bcs->chstate |= CHS_D_UP; |
1287 | gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DCONN); | 1298 | gigaset_isdn_connD(bcs); |
1288 | cs->ops->init_bchannel(bcs); | 1299 | cs->ops->init_bchannel(bcs); |
1289 | break; | 1300 | break; |
1290 | case ACT_FAKEHUP: | 1301 | case ACT_FAKEHUP: |
@@ -1369,7 +1380,7 @@ static void do_action(int action, struct cardstate *cs, | |||
1369 | cs->cur_at_seq = SEQ_NONE; | 1380 | cs->cur_at_seq = SEQ_NONE; |
1370 | break; | 1381 | break; |
1371 | 1382 | ||
1372 | case ACT_ABORTACCEPT: /* hangup/error/timeout during ICALL processing */ | 1383 | case ACT_ABORTACCEPT: /* hangup/error/timeout during ICALL procssng */ |
1373 | disconnect(p_at_state); | 1384 | disconnect(p_at_state); |
1374 | break; | 1385 | break; |
1375 | 1386 | ||
@@ -1427,7 +1438,7 @@ static void do_action(int action, struct cardstate *cs, | |||
1427 | case ACT_GOTVER: | 1438 | case ACT_GOTVER: |
1428 | if (cs->gotfwver == 0) { | 1439 | if (cs->gotfwver == 0) { |
1429 | cs->gotfwver = 1; | 1440 | cs->gotfwver = 1; |
1430 | gig_dbg(DEBUG_ANY, | 1441 | gig_dbg(DEBUG_EVENT, |
1431 | "firmware version %02d.%03d.%02d.%02d", | 1442 | "firmware version %02d.%03d.%02d.%02d", |
1432 | cs->fwver[0], cs->fwver[1], | 1443 | cs->fwver[0], cs->fwver[1], |
1433 | cs->fwver[2], cs->fwver[3]); | 1444 | cs->fwver[2], cs->fwver[3]); |
@@ -1443,17 +1454,6 @@ static void do_action(int action, struct cardstate *cs, | |||
1443 | __func__, at_state->ConState); | 1454 | __func__, at_state->ConState); |
1444 | cs->cur_at_seq = SEQ_NONE; | 1455 | cs->cur_at_seq = SEQ_NONE; |
1445 | break; | 1456 | break; |
1446 | #ifdef CONFIG_GIGASET_DEBUG | ||
1447 | case ACT_TEST: | ||
1448 | { | ||
1449 | static int count = 3; //2; //1; | ||
1450 | *p_genresp = 1; | ||
1451 | *p_resp_code = count ? RSP_ERROR : RSP_OK; | ||
1452 | if (count > 0) | ||
1453 | --count; | ||
1454 | } | ||
1455 | break; | ||
1456 | #endif | ||
1457 | case ACT_DEBUG: | 1457 | case ACT_DEBUG: |
1458 | gig_dbg(DEBUG_ANY, "%s: resp_code %d in ConState %d", | 1458 | gig_dbg(DEBUG_ANY, "%s: resp_code %d in ConState %d", |
1459 | __func__, ev->type, at_state->ConState); | 1459 | __func__, ev->type, at_state->ConState); |
@@ -1474,15 +1474,10 @@ static void do_action(int action, struct cardstate *cs, | |||
1474 | case ACT_ACCEPT: | 1474 | case ACT_ACCEPT: |
1475 | start_accept(at_state); | 1475 | start_accept(at_state); |
1476 | break; | 1476 | break; |
1477 | case ACT_PROTO_L2: | ||
1478 | gig_dbg(DEBUG_CMD, "set protocol to %u", | ||
1479 | (unsigned) ev->parameter); | ||
1480 | at_state->bcs->proto2 = ev->parameter; | ||
1481 | break; | ||
1482 | case ACT_HUP: | 1477 | case ACT_HUP: |
1483 | at_state->pending_commands |= PC_HUP; | 1478 | at_state->pending_commands |= PC_HUP; |
1479 | gig_dbg(DEBUG_EVENT, "Scheduling PC_HUP"); | ||
1484 | cs->commands_pending = 1; | 1480 | cs->commands_pending = 1; |
1485 | gig_dbg(DEBUG_CMD, "Scheduling PC_HUP"); | ||
1486 | break; | 1481 | break; |
1487 | 1482 | ||
1488 | /* hotplug events */ | 1483 | /* hotplug events */ |
@@ -1493,7 +1488,7 @@ static void do_action(int action, struct cardstate *cs, | |||
1493 | do_start(cs); | 1488 | do_start(cs); |
1494 | break; | 1489 | break; |
1495 | 1490 | ||
1496 | /* events from the interface */ // FIXME without ACT_xxxx? | 1491 | /* events from the interface */ |
1497 | case ACT_IF_LOCK: | 1492 | case ACT_IF_LOCK: |
1498 | cs->cmd_result = ev->parameter ? do_lock(cs) : do_unlock(cs); | 1493 | cs->cmd_result = ev->parameter ? do_lock(cs) : do_unlock(cs); |
1499 | cs->waiting = 0; | 1494 | cs->waiting = 0; |
@@ -1512,17 +1507,17 @@ static void do_action(int action, struct cardstate *cs, | |||
1512 | wake_up(&cs->waitqueue); | 1507 | wake_up(&cs->waitqueue); |
1513 | break; | 1508 | break; |
1514 | 1509 | ||
1515 | /* events from the proc file system */ // FIXME without ACT_xxxx? | 1510 | /* events from the proc file system */ |
1516 | case ACT_PROC_CIDMODE: | 1511 | case ACT_PROC_CIDMODE: |
1517 | spin_lock_irqsave(&cs->lock, flags); | 1512 | spin_lock_irqsave(&cs->lock, flags); |
1518 | if (ev->parameter != cs->cidmode) { | 1513 | if (ev->parameter != cs->cidmode) { |
1519 | cs->cidmode = ev->parameter; | 1514 | cs->cidmode = ev->parameter; |
1520 | if (ev->parameter) { | 1515 | if (ev->parameter) { |
1521 | cs->at_state.pending_commands |= PC_CIDMODE; | 1516 | cs->at_state.pending_commands |= PC_CIDMODE; |
1522 | gig_dbg(DEBUG_CMD, "Scheduling PC_CIDMODE"); | 1517 | gig_dbg(DEBUG_EVENT, "Scheduling PC_CIDMODE"); |
1523 | } else { | 1518 | } else { |
1524 | cs->at_state.pending_commands |= PC_UMMODE; | 1519 | cs->at_state.pending_commands |= PC_UMMODE; |
1525 | gig_dbg(DEBUG_CMD, "Scheduling PC_UMMODE"); | 1520 | gig_dbg(DEBUG_EVENT, "Scheduling PC_UMMODE"); |
1526 | } | 1521 | } |
1527 | cs->commands_pending = 1; | 1522 | cs->commands_pending = 1; |
1528 | } | 1523 | } |
@@ -1573,6 +1568,8 @@ static void process_event(struct cardstate *cs, struct event_t *ev) | |||
1573 | if (ev->cid >= 0) { | 1568 | if (ev->cid >= 0) { |
1574 | at_state = at_state_from_cid(cs, ev->cid); | 1569 | at_state = at_state_from_cid(cs, ev->cid); |
1575 | if (!at_state) { | 1570 | if (!at_state) { |
1571 | gig_dbg(DEBUG_EVENT, "event %d for invalid cid %d", | ||
1572 | ev->type, ev->cid); | ||
1576 | gigaset_add_event(cs, &cs->at_state, RSP_WRONG_CID, | 1573 | gigaset_add_event(cs, &cs->at_state, RSP_WRONG_CID, |
1577 | NULL, 0, NULL); | 1574 | NULL, 0, NULL); |
1578 | return; | 1575 | return; |
@@ -1580,13 +1577,13 @@ static void process_event(struct cardstate *cs, struct event_t *ev) | |||
1580 | } else { | 1577 | } else { |
1581 | at_state = ev->at_state; | 1578 | at_state = ev->at_state; |
1582 | if (at_state_invalid(cs, at_state)) { | 1579 | if (at_state_invalid(cs, at_state)) { |
1583 | gig_dbg(DEBUG_ANY, "event for invalid at_state %p", | 1580 | gig_dbg(DEBUG_EVENT, "event for invalid at_state %p", |
1584 | at_state); | 1581 | at_state); |
1585 | return; | 1582 | return; |
1586 | } | 1583 | } |
1587 | } | 1584 | } |
1588 | 1585 | ||
1589 | gig_dbg(DEBUG_CMD, "connection state %d, event %d", | 1586 | gig_dbg(DEBUG_EVENT, "connection state %d, event %d", |
1590 | at_state->ConState, ev->type); | 1587 | at_state->ConState, ev->type); |
1591 | 1588 | ||
1592 | bcs = at_state->bcs; | 1589 | bcs = at_state->bcs; |
@@ -1600,11 +1597,11 @@ static void process_event(struct cardstate *cs, struct event_t *ev) | |||
1600 | if (ev->parameter != at_state->timer_index | 1597 | if (ev->parameter != at_state->timer_index |
1601 | || !at_state->timer_active) { | 1598 | || !at_state->timer_active) { |
1602 | ev->type = RSP_NONE; /* old timeout */ | 1599 | ev->type = RSP_NONE; /* old timeout */ |
1603 | gig_dbg(DEBUG_ANY, "old timeout"); | 1600 | gig_dbg(DEBUG_EVENT, "old timeout"); |
1604 | } else if (!at_state->waiting) | 1601 | } else if (!at_state->waiting) |
1605 | gig_dbg(DEBUG_ANY, "timeout occurred"); | 1602 | gig_dbg(DEBUG_EVENT, "timeout occurred"); |
1606 | else | 1603 | else |
1607 | gig_dbg(DEBUG_ANY, "stopped waiting"); | 1604 | gig_dbg(DEBUG_EVENT, "stopped waiting"); |
1608 | } | 1605 | } |
1609 | spin_unlock_irqrestore(&cs->lock, flags); | 1606 | spin_unlock_irqrestore(&cs->lock, flags); |
1610 | 1607 | ||
@@ -1649,7 +1646,8 @@ static void process_event(struct cardstate *cs, struct event_t *ev) | |||
1649 | for (curact = 0; curact < MAXACT; ++curact) { | 1646 | for (curact = 0; curact < MAXACT; ++curact) { |
1650 | /* The row tells us what we should do .. | 1647 | /* The row tells us what we should do .. |
1651 | */ | 1648 | */ |
1652 | do_action(rep->action[curact], cs, bcs, &at_state, &p_command, &genresp, &resp_code, ev); | 1649 | do_action(rep->action[curact], cs, bcs, &at_state, &p_command, |
1650 | &genresp, &resp_code, ev); | ||
1653 | if (!at_state) | 1651 | if (!at_state) |
1654 | break; /* may be freed after disconnect */ | 1652 | break; /* may be freed after disconnect */ |
1655 | } | 1653 | } |
@@ -1661,13 +1659,14 @@ static void process_event(struct cardstate *cs, struct event_t *ev) | |||
1661 | 1659 | ||
1662 | if (genresp) { | 1660 | if (genresp) { |
1663 | spin_lock_irqsave(&cs->lock, flags); | 1661 | spin_lock_irqsave(&cs->lock, flags); |
1664 | at_state->timer_expires = 0; //FIXME | 1662 | at_state->timer_expires = 0; |
1665 | at_state->timer_active = 0; //FIXME | 1663 | at_state->timer_active = 0; |
1666 | spin_unlock_irqrestore(&cs->lock, flags); | 1664 | spin_unlock_irqrestore(&cs->lock, flags); |
1667 | gigaset_add_event(cs, at_state, resp_code, NULL, 0, NULL); | 1665 | gigaset_add_event(cs, at_state, resp_code, |
1666 | NULL, 0, NULL); | ||
1668 | } else { | 1667 | } else { |
1669 | /* Send command to modem if not NULL... */ | 1668 | /* Send command to modem if not NULL... */ |
1670 | if (p_command/*rep->command*/) { | 1669 | if (p_command) { |
1671 | if (cs->connected) | 1670 | if (cs->connected) |
1672 | send_command(cs, p_command, | 1671 | send_command(cs, p_command, |
1673 | sendcid, cs->dle, | 1672 | sendcid, cs->dle, |
@@ -1710,11 +1709,11 @@ static void process_command_flags(struct cardstate *cs) | |||
1710 | cs->commands_pending = 0; | 1709 | cs->commands_pending = 0; |
1711 | 1710 | ||
1712 | if (cs->cur_at_seq) { | 1711 | if (cs->cur_at_seq) { |
1713 | gig_dbg(DEBUG_CMD, "not searching scheduled commands: busy"); | 1712 | gig_dbg(DEBUG_EVENT, "not searching scheduled commands: busy"); |
1714 | return; | 1713 | return; |
1715 | } | 1714 | } |
1716 | 1715 | ||
1717 | gig_dbg(DEBUG_CMD, "searching scheduled commands"); | 1716 | gig_dbg(DEBUG_EVENT, "searching scheduled commands"); |
1718 | 1717 | ||
1719 | sequence = SEQ_NONE; | 1718 | sequence = SEQ_NONE; |
1720 | 1719 | ||
@@ -1754,7 +1753,8 @@ static void process_command_flags(struct cardstate *cs) | |||
1754 | } | 1753 | } |
1755 | } | 1754 | } |
1756 | 1755 | ||
1757 | /* only switch back to unimodem mode, if no commands are pending and no channels are up */ | 1756 | /* only switch back to unimodem mode if no commands are pending and |
1757 | * no channels are up */ | ||
1758 | spin_lock_irqsave(&cs->lock, flags); | 1758 | spin_lock_irqsave(&cs->lock, flags); |
1759 | if (cs->at_state.pending_commands == PC_UMMODE | 1759 | if (cs->at_state.pending_commands == PC_UMMODE |
1760 | && !cs->cidmode | 1760 | && !cs->cidmode |
@@ -1813,9 +1813,8 @@ static void process_command_flags(struct cardstate *cs) | |||
1813 | 1813 | ||
1814 | if (cs->at_state.pending_commands & PC_INIT) { | 1814 | if (cs->at_state.pending_commands & PC_INIT) { |
1815 | cs->at_state.pending_commands &= ~PC_INIT; | 1815 | cs->at_state.pending_commands &= ~PC_INIT; |
1816 | cs->dle = 0; //FIXME | 1816 | cs->dle = 0; |
1817 | cs->inbuf->inputstate = INS_command; | 1817 | cs->inbuf->inputstate = INS_command; |
1818 | //FIXME reset card state (or -> LOCK0)? | ||
1819 | schedule_sequence(cs, &cs->at_state, SEQ_INIT); | 1818 | schedule_sequence(cs, &cs->at_state, SEQ_INIT); |
1820 | return; | 1819 | return; |
1821 | } | 1820 | } |
@@ -1855,7 +1854,7 @@ static void process_command_flags(struct cardstate *cs) | |||
1855 | switch (cs->mode) { | 1854 | switch (cs->mode) { |
1856 | case M_UNIMODEM: | 1855 | case M_UNIMODEM: |
1857 | cs->at_state.pending_commands |= PC_CIDMODE; | 1856 | cs->at_state.pending_commands |= PC_CIDMODE; |
1858 | gig_dbg(DEBUG_CMD, "Scheduling PC_CIDMODE"); | 1857 | gig_dbg(DEBUG_EVENT, "Scheduling PC_CIDMODE"); |
1859 | cs->commands_pending = 1; | 1858 | cs->commands_pending = 1; |
1860 | return; | 1859 | return; |
1861 | #ifdef GIG_MAYINITONDIAL | 1860 | #ifdef GIG_MAYINITONDIAL |
diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h index a2f6125739eb..05947f9c1849 100644 --- a/drivers/isdn/gigaset/gigaset.h +++ b/drivers/isdn/gigaset/gigaset.h | |||
@@ -20,11 +20,12 @@ | |||
20 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 20 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
21 | 21 | ||
22 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
23 | #include <linux/sched.h> | ||
23 | #include <linux/compiler.h> | 24 | #include <linux/compiler.h> |
24 | #include <linux/types.h> | 25 | #include <linux/types.h> |
26 | #include <linux/ctype.h> | ||
27 | #include <linux/slab.h> | ||
25 | #include <linux/spinlock.h> | 28 | #include <linux/spinlock.h> |
26 | #include <linux/isdnif.h> | ||
27 | #include <linux/usb.h> | ||
28 | #include <linux/skbuff.h> | 29 | #include <linux/skbuff.h> |
29 | #include <linux/netdevice.h> | 30 | #include <linux/netdevice.h> |
30 | #include <linux/ppp_defs.h> | 31 | #include <linux/ppp_defs.h> |
@@ -35,12 +36,11 @@ | |||
35 | #include <linux/list.h> | 36 | #include <linux/list.h> |
36 | #include <asm/atomic.h> | 37 | #include <asm/atomic.h> |
37 | 38 | ||
38 | #define GIG_VERSION {0,5,0,0} | 39 | #define GIG_VERSION {0, 5, 0, 0} |
39 | #define GIG_COMPAT {0,4,0,0} | 40 | #define GIG_COMPAT {0, 4, 0, 0} |
40 | 41 | ||
41 | #define MAX_REC_PARAMS 10 /* Max. number of params in response string */ | 42 | #define MAX_REC_PARAMS 10 /* Max. number of params in response string */ |
42 | #define MAX_RESP_SIZE 512 /* Max. size of a response string */ | 43 | #define MAX_RESP_SIZE 511 /* Max. size of a response string */ |
43 | #define HW_HDR_LEN 2 /* Header size used to store ack info */ | ||
44 | 44 | ||
45 | #define MAX_EVENTS 64 /* size of event queue */ | 45 | #define MAX_EVENTS 64 /* size of event queue */ |
46 | 46 | ||
@@ -80,9 +80,10 @@ enum debuglevel { | |||
80 | DEBUG_STREAM = 0x00040, /* application data stream I/O events */ | 80 | DEBUG_STREAM = 0x00040, /* application data stream I/O events */ |
81 | DEBUG_STREAM_DUMP = 0x00080, /* application data stream content */ | 81 | DEBUG_STREAM_DUMP = 0x00080, /* application data stream content */ |
82 | DEBUG_LLDATA = 0x00100, /* sent/received LL data */ | 82 | DEBUG_LLDATA = 0x00100, /* sent/received LL data */ |
83 | DEBUG_EVENT = 0x00200, /* event processing */ | ||
83 | DEBUG_DRIVER = 0x00400, /* driver structure */ | 84 | DEBUG_DRIVER = 0x00400, /* driver structure */ |
84 | DEBUG_HDLC = 0x00800, /* M10x HDLC processing */ | 85 | DEBUG_HDLC = 0x00800, /* M10x HDLC processing */ |
85 | DEBUG_WRITE = 0x01000, /* M105 data write */ | 86 | DEBUG_CHANNEL = 0x01000, /* channel allocation/deallocation */ |
86 | DEBUG_TRANSCMD = 0x02000, /* AT-COMMANDS+RESPONSES */ | 87 | DEBUG_TRANSCMD = 0x02000, /* AT-COMMANDS+RESPONSES */ |
87 | DEBUG_MCMD = 0x04000, /* COMMANDS THAT ARE SENT VERY OFTEN */ | 88 | DEBUG_MCMD = 0x04000, /* COMMANDS THAT ARE SENT VERY OFTEN */ |
88 | DEBUG_INIT = 0x08000, /* (de)allocation+initialization of data | 89 | DEBUG_INIT = 0x08000, /* (de)allocation+initialization of data |
@@ -135,35 +136,32 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, | |||
135 | #define OUT_VENDOR_REQ (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT) | 136 | #define OUT_VENDOR_REQ (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT) |
136 | #define IN_VENDOR_REQ (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT) | 137 | #define IN_VENDOR_REQ (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT) |
137 | 138 | ||
138 | /* int-in-events 3070 */ | 139 | /* interrupt pipe messages */ |
139 | #define HD_B1_FLOW_CONTROL 0x80 | 140 | #define HD_B1_FLOW_CONTROL 0x80 |
140 | #define HD_B2_FLOW_CONTROL 0x81 | 141 | #define HD_B2_FLOW_CONTROL 0x81 |
141 | #define HD_RECEIVEATDATA_ACK (0x35) // 3070 | 142 | #define HD_RECEIVEATDATA_ACK (0x35) /* 3070 */ |
142 | // att: HD_RECEIVE>>AT<<DATA_ACK | 143 | #define HD_READY_SEND_ATDATA (0x36) /* 3070 */ |
143 | #define HD_READY_SEND_ATDATA (0x36) // 3070 | 144 | #define HD_OPEN_ATCHANNEL_ACK (0x37) /* 3070 */ |
144 | #define HD_OPEN_ATCHANNEL_ACK (0x37) // 3070 | 145 | #define HD_CLOSE_ATCHANNEL_ACK (0x38) /* 3070 */ |
145 | #define HD_CLOSE_ATCHANNEL_ACK (0x38) // 3070 | 146 | #define HD_DEVICE_INIT_OK (0x11) /* ISurf USB + 3070 */ |
146 | #define HD_DEVICE_INIT_OK (0x11) // ISurf USB + 3070 | 147 | #define HD_OPEN_B1CHANNEL_ACK (0x51) /* ISurf USB + 3070 */ |
147 | #define HD_OPEN_B1CHANNEL_ACK (0x51) // ISurf USB + 3070 | 148 | #define HD_OPEN_B2CHANNEL_ACK (0x52) /* ISurf USB + 3070 */ |
148 | #define HD_OPEN_B2CHANNEL_ACK (0x52) // ISurf USB + 3070 | 149 | #define HD_CLOSE_B1CHANNEL_ACK (0x53) /* ISurf USB + 3070 */ |
149 | #define HD_CLOSE_B1CHANNEL_ACK (0x53) // ISurf USB + 3070 | 150 | #define HD_CLOSE_B2CHANNEL_ACK (0x54) /* ISurf USB + 3070 */ |
150 | #define HD_CLOSE_B2CHANNEL_ACK (0x54) // ISurf USB + 3070 | 151 | #define HD_SUSPEND_END (0x61) /* ISurf USB */ |
151 | // Powermangment | 152 | #define HD_RESET_INTERRUPT_PIPE_ACK (0xFF) /* ISurf USB + 3070 */ |
152 | #define HD_SUSPEND_END (0x61) // ISurf USB | 153 | |
153 | // Configuration | 154 | /* control requests */ |
154 | #define HD_RESET_INTERRUPT_PIPE_ACK (0xFF) // ISurf USB + 3070 | 155 | #define HD_OPEN_B1CHANNEL (0x23) /* ISurf USB + 3070 */ |
155 | 156 | #define HD_CLOSE_B1CHANNEL (0x24) /* ISurf USB + 3070 */ | |
156 | /* control requests 3070 */ | 157 | #define HD_OPEN_B2CHANNEL (0x25) /* ISurf USB + 3070 */ |
157 | #define HD_OPEN_B1CHANNEL (0x23) // ISurf USB + 3070 | 158 | #define HD_CLOSE_B2CHANNEL (0x26) /* ISurf USB + 3070 */ |
158 | #define HD_CLOSE_B1CHANNEL (0x24) // ISurf USB + 3070 | 159 | #define HD_RESET_INTERRUPT_PIPE (0x27) /* ISurf USB + 3070 */ |
159 | #define HD_OPEN_B2CHANNEL (0x25) // ISurf USB + 3070 | 160 | #define HD_DEVICE_INIT_ACK (0x34) /* ISurf USB + 3070 */ |
160 | #define HD_CLOSE_B2CHANNEL (0x26) // ISurf USB + 3070 | 161 | #define HD_WRITE_ATMESSAGE (0x12) /* 3070 */ |
161 | #define HD_RESET_INTERRUPT_PIPE (0x27) // ISurf USB + 3070 | 162 | #define HD_READ_ATMESSAGE (0x13) /* 3070 */ |
162 | #define HD_DEVICE_INIT_ACK (0x34) // ISurf USB + 3070 | 163 | #define HD_OPEN_ATCHANNEL (0x28) /* 3070 */ |
163 | #define HD_WRITE_ATMESSAGE (0x12) // 3070 | 164 | #define HD_CLOSE_ATCHANNEL (0x29) /* 3070 */ |
164 | #define HD_READ_ATMESSAGE (0x13) // 3070 | ||
165 | #define HD_OPEN_ATCHANNEL (0x28) // 3070 | ||
166 | #define HD_CLOSE_ATCHANNEL (0x29) // 3070 | ||
167 | 165 | ||
168 | /* number of B channels supported by base driver */ | 166 | /* number of B channels supported by base driver */ |
169 | #define BAS_CHANNELS 2 | 167 | #define BAS_CHANNELS 2 |
@@ -193,7 +191,9 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, | |||
193 | #define AT_PROTO 4 | 191 | #define AT_PROTO 4 |
194 | #define AT_TYPE 5 | 192 | #define AT_TYPE 5 |
195 | #define AT_HLC 6 | 193 | #define AT_HLC 6 |
196 | #define AT_NUM 7 | 194 | #define AT_CLIP 7 |
195 | /* total number */ | ||
196 | #define AT_NUM 8 | ||
197 | 197 | ||
198 | /* variables in struct at_state_t */ | 198 | /* variables in struct at_state_t */ |
199 | #define VAR_ZSAU 0 | 199 | #define VAR_ZSAU 0 |
@@ -216,7 +216,6 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, | |||
216 | #define EV_START -110 | 216 | #define EV_START -110 |
217 | #define EV_STOP -111 | 217 | #define EV_STOP -111 |
218 | #define EV_IF_LOCK -112 | 218 | #define EV_IF_LOCK -112 |
219 | #define EV_PROTO_L2 -113 | ||
220 | #define EV_ACCEPT -114 | 219 | #define EV_ACCEPT -114 |
221 | #define EV_DIAL -115 | 220 | #define EV_DIAL -115 |
222 | #define EV_HUP -116 | 221 | #define EV_HUP -116 |
@@ -224,12 +223,11 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, | |||
224 | #define EV_BC_CLOSED -118 | 223 | #define EV_BC_CLOSED -118 |
225 | 224 | ||
226 | /* input state */ | 225 | /* input state */ |
227 | #define INS_command 0x0001 | 226 | #define INS_command 0x0001 /* receiving messages (not payload data) */ |
228 | #define INS_DLE_char 0x0002 | 227 | #define INS_DLE_char 0x0002 /* DLE flag received (in DLE mode) */ |
229 | #define INS_byte_stuff 0x0004 | 228 | #define INS_byte_stuff 0x0004 |
230 | #define INS_have_data 0x0008 | 229 | #define INS_have_data 0x0008 |
231 | #define INS_skip_frame 0x0010 | 230 | #define INS_DLE_command 0x0020 /* DLE message start (<DLE> X) received */ |
232 | #define INS_DLE_command 0x0020 | ||
233 | #define INS_flag_hunt 0x0040 | 231 | #define INS_flag_hunt 0x0040 |
234 | 232 | ||
235 | /* channel state */ | 233 | /* channel state */ |
@@ -259,6 +257,11 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, | |||
259 | #define SM_LOCKED 0 | 257 | #define SM_LOCKED 0 |
260 | #define SM_ISDN 1 /* default */ | 258 | #define SM_ISDN 1 /* default */ |
261 | 259 | ||
260 | /* layer 2 protocols (AT^SBPR=...) */ | ||
261 | #define L2_BITSYNC 0 | ||
262 | #define L2_HDLC 1 | ||
263 | #define L2_VOICE 2 | ||
264 | |||
262 | struct gigaset_ops; | 265 | struct gigaset_ops; |
263 | struct gigaset_driver; | 266 | struct gigaset_driver; |
264 | 267 | ||
@@ -286,8 +289,6 @@ extern struct reply_t gigaset_tab_cid[]; | |||
286 | extern struct reply_t gigaset_tab_nocid[]; | 289 | extern struct reply_t gigaset_tab_nocid[]; |
287 | 290 | ||
288 | struct inbuf_t { | 291 | struct inbuf_t { |
289 | unsigned char *rcvbuf; /* usb-gigaset receive buffer */ | ||
290 | struct bc_state *bcs; | ||
291 | struct cardstate *cs; | 292 | struct cardstate *cs; |
292 | int inputstate; | 293 | int inputstate; |
293 | int head, tail; | 294 | int head, tail; |
@@ -359,12 +360,6 @@ struct at_state_t { | |||
359 | struct bc_state *bcs; | 360 | struct bc_state *bcs; |
360 | }; | 361 | }; |
361 | 362 | ||
362 | struct resp_type_t { | ||
363 | unsigned char *response; | ||
364 | int resp_code; /* RSP_XXXX */ | ||
365 | int type; /* RT_XXXX */ | ||
366 | }; | ||
367 | |||
368 | struct event_t { | 363 | struct event_t { |
369 | int type; | 364 | int type; |
370 | void *ptr, *arg; | 365 | void *ptr, *arg; |
@@ -395,7 +390,7 @@ struct bc_state { | |||
395 | 390 | ||
396 | unsigned chstate; /* bitmap (CHS_*) */ | 391 | unsigned chstate; /* bitmap (CHS_*) */ |
397 | int ignore; | 392 | int ignore; |
398 | unsigned proto2; /* Layer 2 protocol (ISDN_PROTO_L2_*) */ | 393 | unsigned proto2; /* layer 2 protocol (L2_*) */ |
399 | char *commands[AT_NUM]; /* see AT_XXXX */ | 394 | char *commands[AT_NUM]; /* see AT_XXXX */ |
400 | 395 | ||
401 | #ifdef CONFIG_GIGASET_DEBUG | 396 | #ifdef CONFIG_GIGASET_DEBUG |
@@ -410,6 +405,8 @@ struct bc_state { | |||
410 | struct usb_bc_state *usb; /* usb hardware driver (m105) */ | 405 | struct usb_bc_state *usb; /* usb hardware driver (m105) */ |
411 | struct bas_bc_state *bas; /* usb hardware driver (base) */ | 406 | struct bas_bc_state *bas; /* usb hardware driver (base) */ |
412 | } hw; | 407 | } hw; |
408 | |||
409 | void *ap; /* LL application structure */ | ||
413 | }; | 410 | }; |
414 | 411 | ||
415 | struct cardstate { | 412 | struct cardstate { |
@@ -456,12 +453,13 @@ struct cardstate { | |||
456 | 453 | ||
457 | unsigned running; /* !=0 if events are handled */ | 454 | unsigned running; /* !=0 if events are handled */ |
458 | unsigned connected; /* !=0 if hardware is connected */ | 455 | unsigned connected; /* !=0 if hardware is connected */ |
459 | unsigned isdn_up; /* !=0 after ISDN_STAT_RUN */ | 456 | unsigned isdn_up; /* !=0 after gigaset_isdn_start() */ |
460 | 457 | ||
461 | unsigned cidmode; | 458 | unsigned cidmode; |
462 | 459 | ||
463 | int myid; /* id for communication with LL */ | 460 | int myid; /* id for communication with LL */ |
464 | isdn_if iif; | 461 | void *iif; /* LL interface structure */ |
462 | unsigned short hw_hdr_len; /* headroom needed in data skbs */ | ||
465 | 463 | ||
466 | struct reply_t *tabnocid; | 464 | struct reply_t *tabnocid; |
467 | struct reply_t *tabcid; | 465 | struct reply_t *tabcid; |
@@ -476,8 +474,8 @@ struct cardstate { | |||
476 | 474 | ||
477 | struct timer_list timer; | 475 | struct timer_list timer; |
478 | int retry_count; | 476 | int retry_count; |
479 | int dle; /* !=0 if modem commands/responses are | 477 | int dle; /* !=0 if DLE mode is active |
480 | dle encoded */ | 478 | (ZDLE=1 received -- M10x only) */ |
481 | int cur_at_seq; /* sequence of AT commands being | 479 | int cur_at_seq; /* sequence of AT commands being |
482 | processed */ | 480 | processed */ |
483 | int curchannel; /* channel those commands are meant | 481 | int curchannel; /* channel those commands are meant |
@@ -503,7 +501,7 @@ struct cardstate { | |||
503 | spinlock_t ev_lock; | 501 | spinlock_t ev_lock; |
504 | 502 | ||
505 | /* current modem response */ | 503 | /* current modem response */ |
506 | unsigned char respdata[MAX_RESP_SIZE]; | 504 | unsigned char respdata[MAX_RESP_SIZE+1]; |
507 | unsigned cbytes; | 505 | unsigned cbytes; |
508 | 506 | ||
509 | /* private data of hardware drivers */ | 507 | /* private data of hardware drivers */ |
@@ -616,7 +614,9 @@ struct gigaset_ops { | |||
616 | int (*baud_rate)(struct cardstate *cs, unsigned cflag); | 614 | int (*baud_rate)(struct cardstate *cs, unsigned cflag); |
617 | int (*set_line_ctrl)(struct cardstate *cs, unsigned cflag); | 615 | int (*set_line_ctrl)(struct cardstate *cs, unsigned cflag); |
618 | 616 | ||
619 | /* Called from i4l.c to put an skb into the send-queue. */ | 617 | /* Called from LL interface to put an skb into the send-queue. |
618 | * After sending is completed, gigaset_skb_sent() must be called | ||
619 | * with the skb's link layer header preserved. */ | ||
620 | int (*send_skb)(struct bc_state *bcs, struct sk_buff *skb); | 620 | int (*send_skb)(struct bc_state *bcs, struct sk_buff *skb); |
621 | 621 | ||
622 | /* Called from ev-layer.c to process a block of data | 622 | /* Called from ev-layer.c to process a block of data |
@@ -625,7 +625,8 @@ struct gigaset_ops { | |||
625 | 625 | ||
626 | }; | 626 | }; |
627 | 627 | ||
628 | /* = Common structures and definitions ======================================= */ | 628 | /* = Common structures and definitions ======================================= |
629 | */ | ||
629 | 630 | ||
630 | /* Parser states for DLE-Event: | 631 | /* Parser states for DLE-Event: |
631 | * <DLE-EVENT>: <DLE_FLAG> "X" <EVENT> <DLE_FLAG> "." | 632 | * <DLE-EVENT>: <DLE_FLAG> "X" <EVENT> <DLE_FLAG> "." |
@@ -638,8 +639,7 @@ struct gigaset_ops { | |||
638 | * Functions implemented in asyncdata.c | 639 | * Functions implemented in asyncdata.c |
639 | */ | 640 | */ |
640 | 641 | ||
641 | /* Called from i4l.c to put an skb into the send-queue. | 642 | /* Called from LL interface to put an skb into the send queue. */ |
642 | * After sending gigaset_skb_sent() should be called. */ | ||
643 | int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb); | 643 | int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb); |
644 | 644 | ||
645 | /* Called from ev-layer.c to process a block of data | 645 | /* Called from ev-layer.c to process a block of data |
@@ -650,8 +650,7 @@ void gigaset_m10x_input(struct inbuf_t *inbuf); | |||
650 | * Functions implemented in isocdata.c | 650 | * Functions implemented in isocdata.c |
651 | */ | 651 | */ |
652 | 652 | ||
653 | /* Called from i4l.c to put an skb into the send-queue. | 653 | /* Called from LL interface to put an skb into the send queue. */ |
654 | * After sending gigaset_skb_sent() should be called. */ | ||
655 | int gigaset_isoc_send_skb(struct bc_state *bcs, struct sk_buff *skb); | 654 | int gigaset_isoc_send_skb(struct bc_state *bcs, struct sk_buff *skb); |
656 | 655 | ||
657 | /* Called from ev-layer.c to process a block of data | 656 | /* Called from ev-layer.c to process a block of data |
@@ -674,36 +673,28 @@ void gigaset_isowbuf_init(struct isowbuf_t *iwb, unsigned char idle); | |||
674 | int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size); | 673 | int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size); |
675 | 674 | ||
676 | /* =========================================================================== | 675 | /* =========================================================================== |
677 | * Functions implemented in i4l.c/gigaset.h | 676 | * Functions implemented in LL interface |
678 | */ | 677 | */ |
679 | 678 | ||
680 | /* Called by gigaset_initcs() for setting up with the isdn4linux subsystem */ | 679 | /* Called from common.c for setting up/shutting down with the ISDN subsystem */ |
681 | int gigaset_register_to_LL(struct cardstate *cs, const char *isdnid); | 680 | void gigaset_isdn_regdrv(void); |
681 | void gigaset_isdn_unregdrv(void); | ||
682 | int gigaset_isdn_regdev(struct cardstate *cs, const char *isdnid); | ||
683 | void gigaset_isdn_unregdev(struct cardstate *cs); | ||
682 | 684 | ||
683 | /* Called from xxx-gigaset.c to indicate completion of sending an skb */ | 685 | /* Called from hardware module to indicate completion of an skb */ |
684 | void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb); | 686 | void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb); |
687 | void gigaset_skb_rcvd(struct bc_state *bcs, struct sk_buff *skb); | ||
688 | void gigaset_isdn_rcv_err(struct bc_state *bcs); | ||
685 | 689 | ||
686 | /* Called from common.c/ev-layer.c to indicate events relevant to the LL */ | 690 | /* Called from common.c/ev-layer.c to indicate events relevant to the LL */ |
691 | void gigaset_isdn_start(struct cardstate *cs); | ||
692 | void gigaset_isdn_stop(struct cardstate *cs); | ||
687 | int gigaset_isdn_icall(struct at_state_t *at_state); | 693 | int gigaset_isdn_icall(struct at_state_t *at_state); |
688 | int gigaset_isdn_setup_accept(struct at_state_t *at_state); | 694 | void gigaset_isdn_connD(struct bc_state *bcs); |
689 | int gigaset_isdn_setup_dial(struct at_state_t *at_state, void *data); | 695 | void gigaset_isdn_hupD(struct bc_state *bcs); |
690 | 696 | void gigaset_isdn_connB(struct bc_state *bcs); | |
691 | void gigaset_i4l_cmd(struct cardstate *cs, int cmd); | 697 | void gigaset_isdn_hupB(struct bc_state *bcs); |
692 | void gigaset_i4l_channel_cmd(struct bc_state *bcs, int cmd); | ||
693 | |||
694 | |||
695 | static inline void gigaset_isdn_rcv_err(struct bc_state *bcs) | ||
696 | { | ||
697 | isdn_ctrl response; | ||
698 | |||
699 | /* error -> LL */ | ||
700 | gig_dbg(DEBUG_CMD, "sending L1ERR"); | ||
701 | response.driver = bcs->cs->myid; | ||
702 | response.command = ISDN_STAT_L1ERR; | ||
703 | response.arg = bcs->channel; | ||
704 | response.parm.errcode = ISDN_STAT_L1ERR_RECV; | ||
705 | bcs->cs->iif.statcallb(&response); | ||
706 | } | ||
707 | 698 | ||
708 | /* =========================================================================== | 699 | /* =========================================================================== |
709 | * Functions implemented in ev-layer.c | 700 | * Functions implemented in ev-layer.c |
@@ -732,6 +723,7 @@ void gigaset_bcs_reinit(struct bc_state *bcs); | |||
732 | void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs, | 723 | void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs, |
733 | struct cardstate *cs, int cid); | 724 | struct cardstate *cs, int cid); |
734 | int gigaset_get_channel(struct bc_state *bcs); | 725 | int gigaset_get_channel(struct bc_state *bcs); |
726 | struct bc_state *gigaset_get_free_channel(struct cardstate *cs); | ||
735 | void gigaset_free_channel(struct bc_state *bcs); | 727 | void gigaset_free_channel(struct bc_state *bcs); |
736 | int gigaset_get_channels(struct cardstate *cs); | 728 | int gigaset_get_channels(struct cardstate *cs); |
737 | void gigaset_free_channels(struct cardstate *cs); | 729 | void gigaset_free_channels(struct cardstate *cs); |
@@ -781,7 +773,7 @@ struct event_t *gigaset_add_event(struct cardstate *cs, | |||
781 | void *ptr, int parameter, void *arg); | 773 | void *ptr, int parameter, void *arg); |
782 | 774 | ||
783 | /* Called on CONFIG1 command from frontend. */ | 775 | /* Called on CONFIG1 command from frontend. */ |
784 | int gigaset_enterconfigmode(struct cardstate *cs); //0: success <0: errorcode | 776 | int gigaset_enterconfigmode(struct cardstate *cs); |
785 | 777 | ||
786 | /* cs->lock must not be locked */ | 778 | /* cs->lock must not be locked */ |
787 | static inline void gigaset_schedule_event(struct cardstate *cs) | 779 | static inline void gigaset_schedule_event(struct cardstate *cs) |
@@ -798,8 +790,6 @@ static inline void gigaset_schedule_event(struct cardstate *cs) | |||
798 | static inline void gigaset_bchannel_down(struct bc_state *bcs) | 790 | static inline void gigaset_bchannel_down(struct bc_state *bcs) |
799 | { | 791 | { |
800 | gigaset_add_event(bcs->cs, &bcs->at_state, EV_BC_CLOSED, NULL, 0, NULL); | 792 | gigaset_add_event(bcs->cs, &bcs->at_state, EV_BC_CLOSED, NULL, 0, NULL); |
801 | |||
802 | gig_dbg(DEBUG_CMD, "scheduling BC_CLOSED"); | ||
803 | gigaset_schedule_event(bcs->cs); | 793 | gigaset_schedule_event(bcs->cs); |
804 | } | 794 | } |
805 | 795 | ||
@@ -808,43 +798,12 @@ static inline void gigaset_bchannel_down(struct bc_state *bcs) | |||
808 | static inline void gigaset_bchannel_up(struct bc_state *bcs) | 798 | static inline void gigaset_bchannel_up(struct bc_state *bcs) |
809 | { | 799 | { |
810 | gigaset_add_event(bcs->cs, &bcs->at_state, EV_BC_OPEN, NULL, 0, NULL); | 800 | gigaset_add_event(bcs->cs, &bcs->at_state, EV_BC_OPEN, NULL, 0, NULL); |
811 | |||
812 | gig_dbg(DEBUG_CMD, "scheduling BC_OPEN"); | ||
813 | gigaset_schedule_event(bcs->cs); | 801 | gigaset_schedule_event(bcs->cs); |
814 | } | 802 | } |
815 | 803 | ||
816 | /* handling routines for sk_buff */ | 804 | /* handling routines for sk_buff */ |
817 | /* ============================= */ | 805 | /* ============================= */ |
818 | 806 | ||
819 | /* pass received skb to LL | ||
820 | * Warning: skb must not be accessed anymore! | ||
821 | */ | ||
822 | static inline void gigaset_rcv_skb(struct sk_buff *skb, | ||
823 | struct cardstate *cs, | ||
824 | struct bc_state *bcs) | ||
825 | { | ||
826 | cs->iif.rcvcallb_skb(cs->myid, bcs->channel, skb); | ||
827 | bcs->trans_down++; | ||
828 | } | ||
829 | |||
830 | /* handle reception of corrupted skb | ||
831 | * Warning: skb must not be accessed anymore! | ||
832 | */ | ||
833 | static inline void gigaset_rcv_error(struct sk_buff *procskb, | ||
834 | struct cardstate *cs, | ||
835 | struct bc_state *bcs) | ||
836 | { | ||
837 | if (procskb) | ||
838 | dev_kfree_skb(procskb); | ||
839 | |||
840 | if (bcs->ignore) | ||
841 | --bcs->ignore; | ||
842 | else { | ||
843 | ++bcs->corrupted; | ||
844 | gigaset_isdn_rcv_err(bcs); | ||
845 | } | ||
846 | } | ||
847 | |||
848 | /* append received bytes to inbuf */ | 807 | /* append received bytes to inbuf */ |
849 | int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src, | 808 | int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src, |
850 | unsigned numbytes); | 809 | unsigned numbytes); |
diff --git a/drivers/isdn/gigaset/i4l.c b/drivers/isdn/gigaset/i4l.c index 654489d836cd..c22e5ace8276 100644 --- a/drivers/isdn/gigaset/i4l.c +++ b/drivers/isdn/gigaset/i4l.c | |||
@@ -14,6 +14,9 @@ | |||
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include "gigaset.h" | 16 | #include "gigaset.h" |
17 | #include <linux/isdnif.h> | ||
18 | |||
19 | #define HW_HDR_LEN 2 /* Header size used to store ack info */ | ||
17 | 20 | ||
18 | /* == Handling of I4L IO =====================================================*/ | 21 | /* == Handling of I4L IO =====================================================*/ |
19 | 22 | ||
@@ -36,12 +39,12 @@ | |||
36 | static int writebuf_from_LL(int driverID, int channel, int ack, | 39 | static int writebuf_from_LL(int driverID, int channel, int ack, |
37 | struct sk_buff *skb) | 40 | struct sk_buff *skb) |
38 | { | 41 | { |
39 | struct cardstate *cs; | 42 | struct cardstate *cs = gigaset_get_cs_by_id(driverID); |
40 | struct bc_state *bcs; | 43 | struct bc_state *bcs; |
44 | unsigned char *ack_header; | ||
41 | unsigned len; | 45 | unsigned len; |
42 | unsigned skblen; | ||
43 | 46 | ||
44 | if (!(cs = gigaset_get_cs_by_id(driverID))) { | 47 | if (!cs) { |
45 | pr_err("%s: invalid driver ID (%d)\n", __func__, driverID); | 48 | pr_err("%s: invalid driver ID (%d)\n", __func__, driverID); |
46 | return -ENODEV; | 49 | return -ENODEV; |
47 | } | 50 | } |
@@ -75,11 +78,23 @@ static int writebuf_from_LL(int driverID, int channel, int ack, | |||
75 | return -EINVAL; | 78 | return -EINVAL; |
76 | } | 79 | } |
77 | 80 | ||
78 | skblen = ack ? len : 0; | 81 | /* set up acknowledgement header */ |
79 | skb->head[0] = skblen & 0xff; | 82 | if (skb_headroom(skb) < HW_HDR_LEN) { |
80 | skb->head[1] = skblen >> 8; | 83 | /* should never happen */ |
81 | gig_dbg(DEBUG_MCMD, "skb: len=%u, skblen=%u: %02x %02x", | 84 | dev_err(cs->dev, "%s: insufficient skb headroom\n", __func__); |
82 | len, skblen, (unsigned) skb->head[0], (unsigned) skb->head[1]); | 85 | return -ENOMEM; |
86 | } | ||
87 | skb_set_mac_header(skb, -HW_HDR_LEN); | ||
88 | skb->mac_len = HW_HDR_LEN; | ||
89 | ack_header = skb_mac_header(skb); | ||
90 | if (ack) { | ||
91 | ack_header[0] = len & 0xff; | ||
92 | ack_header[1] = len >> 8; | ||
93 | } else { | ||
94 | ack_header[0] = ack_header[1] = 0; | ||
95 | } | ||
96 | gig_dbg(DEBUG_MCMD, "skb: len=%u, ack=%d: %02x %02x", | ||
97 | len, ack, ack_header[0], ack_header[1]); | ||
83 | 98 | ||
84 | /* pass to device-specific module */ | 99 | /* pass to device-specific module */ |
85 | return cs->ops->send_skb(bcs, skb); | 100 | return cs->ops->send_skb(bcs, skb); |
@@ -95,6 +110,8 @@ static int writebuf_from_LL(int driverID, int channel, int ack, | |||
95 | */ | 110 | */ |
96 | void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb) | 111 | void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb) |
97 | { | 112 | { |
113 | isdn_if *iif = bcs->cs->iif; | ||
114 | unsigned char *ack_header = skb_mac_header(skb); | ||
98 | unsigned len; | 115 | unsigned len; |
99 | isdn_ctrl response; | 116 | isdn_ctrl response; |
100 | 117 | ||
@@ -104,8 +121,7 @@ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb) | |||
104 | dev_warn(bcs->cs->dev, "%s: skb->len==%d\n", | 121 | dev_warn(bcs->cs->dev, "%s: skb->len==%d\n", |
105 | __func__, skb->len); | 122 | __func__, skb->len); |
106 | 123 | ||
107 | len = (unsigned char) skb->head[0] | | 124 | len = ack_header[0] + ((unsigned) ack_header[1] << 8); |
108 | (unsigned) (unsigned char) skb->head[1] << 8; | ||
109 | if (len) { | 125 | if (len) { |
110 | gig_dbg(DEBUG_MCMD, "ACKing to LL (id: %d, ch: %d, sz: %u)", | 126 | gig_dbg(DEBUG_MCMD, "ACKing to LL (id: %d, ch: %d, sz: %u)", |
111 | bcs->cs->myid, bcs->channel, len); | 127 | bcs->cs->myid, bcs->channel, len); |
@@ -114,359 +130,297 @@ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb) | |||
114 | response.command = ISDN_STAT_BSENT; | 130 | response.command = ISDN_STAT_BSENT; |
115 | response.arg = bcs->channel; | 131 | response.arg = bcs->channel; |
116 | response.parm.length = len; | 132 | response.parm.length = len; |
117 | bcs->cs->iif.statcallb(&response); | 133 | iif->statcallb(&response); |
118 | } | 134 | } |
119 | } | 135 | } |
120 | EXPORT_SYMBOL_GPL(gigaset_skb_sent); | 136 | EXPORT_SYMBOL_GPL(gigaset_skb_sent); |
121 | 137 | ||
138 | /** | ||
139 | * gigaset_skb_rcvd() - pass received skb to LL | ||
140 | * @bcs: B channel descriptor structure. | ||
141 | * @skb: received data. | ||
142 | * | ||
143 | * Called by hardware module {bas,ser,usb}_gigaset when user data has | ||
144 | * been successfully received, for passing to the LL. | ||
145 | * Warning: skb must not be accessed anymore! | ||
146 | */ | ||
147 | void gigaset_skb_rcvd(struct bc_state *bcs, struct sk_buff *skb) | ||
148 | { | ||
149 | isdn_if *iif = bcs->cs->iif; | ||
150 | |||
151 | iif->rcvcallb_skb(bcs->cs->myid, bcs->channel, skb); | ||
152 | bcs->trans_down++; | ||
153 | } | ||
154 | EXPORT_SYMBOL_GPL(gigaset_skb_rcvd); | ||
155 | |||
156 | /** | ||
157 | * gigaset_isdn_rcv_err() - signal receive error | ||
158 | * @bcs: B channel descriptor structure. | ||
159 | * | ||
160 | * Called by hardware module {bas,ser,usb}_gigaset when a receive error | ||
161 | * has occurred, for signalling to the LL. | ||
162 | */ | ||
163 | void gigaset_isdn_rcv_err(struct bc_state *bcs) | ||
164 | { | ||
165 | isdn_if *iif = bcs->cs->iif; | ||
166 | isdn_ctrl response; | ||
167 | |||
168 | /* if currently ignoring packets, just count down */ | ||
169 | if (bcs->ignore) { | ||
170 | bcs->ignore--; | ||
171 | return; | ||
172 | } | ||
173 | |||
174 | /* update statistics */ | ||
175 | bcs->corrupted++; | ||
176 | |||
177 | /* error -> LL */ | ||
178 | gig_dbg(DEBUG_CMD, "sending L1ERR"); | ||
179 | response.driver = bcs->cs->myid; | ||
180 | response.command = ISDN_STAT_L1ERR; | ||
181 | response.arg = bcs->channel; | ||
182 | response.parm.errcode = ISDN_STAT_L1ERR_RECV; | ||
183 | iif->statcallb(&response); | ||
184 | } | ||
185 | EXPORT_SYMBOL_GPL(gigaset_isdn_rcv_err); | ||
186 | |||
122 | /* This function will be called by LL to send commands | 187 | /* This function will be called by LL to send commands |
123 | * NOTE: LL ignores the returned value, for commands other than ISDN_CMD_IOCTL, | 188 | * NOTE: LL ignores the returned value, for commands other than ISDN_CMD_IOCTL, |
124 | * so don't put too much effort into it. | 189 | * so don't put too much effort into it. |
125 | */ | 190 | */ |
126 | static int command_from_LL(isdn_ctrl *cntrl) | 191 | static int command_from_LL(isdn_ctrl *cntrl) |
127 | { | 192 | { |
128 | struct cardstate *cs = gigaset_get_cs_by_id(cntrl->driver); | 193 | struct cardstate *cs; |
129 | struct bc_state *bcs; | 194 | struct bc_state *bcs; |
130 | int retval = 0; | 195 | int retval = 0; |
131 | struct setup_parm *sp; | 196 | char **commands; |
197 | int ch; | ||
198 | int i; | ||
199 | size_t l; | ||
132 | 200 | ||
133 | gigaset_debugdrivers(); | 201 | gigaset_debugdrivers(); |
134 | 202 | ||
135 | if (!cs) { | 203 | gig_dbg(DEBUG_CMD, "driver: %d, command: %d, arg: 0x%lx", |
204 | cntrl->driver, cntrl->command, cntrl->arg); | ||
205 | |||
206 | cs = gigaset_get_cs_by_id(cntrl->driver); | ||
207 | if (cs == NULL) { | ||
136 | pr_err("%s: invalid driver ID (%d)\n", __func__, cntrl->driver); | 208 | pr_err("%s: invalid driver ID (%d)\n", __func__, cntrl->driver); |
137 | return -ENODEV; | 209 | return -ENODEV; |
138 | } | 210 | } |
211 | ch = cntrl->arg & 0xff; | ||
139 | 212 | ||
140 | switch (cntrl->command) { | 213 | switch (cntrl->command) { |
141 | case ISDN_CMD_IOCTL: | 214 | case ISDN_CMD_IOCTL: |
142 | gig_dbg(DEBUG_ANY, "ISDN_CMD_IOCTL (driver: %d, arg: %ld)", | ||
143 | cntrl->driver, cntrl->arg); | ||
144 | |||
145 | dev_warn(cs->dev, "ISDN_CMD_IOCTL not supported\n"); | 215 | dev_warn(cs->dev, "ISDN_CMD_IOCTL not supported\n"); |
146 | return -EINVAL; | 216 | return -EINVAL; |
147 | 217 | ||
148 | case ISDN_CMD_DIAL: | 218 | case ISDN_CMD_DIAL: |
149 | gig_dbg(DEBUG_ANY, | 219 | gig_dbg(DEBUG_CMD, |
150 | "ISDN_CMD_DIAL (driver: %d, ch: %ld, " | 220 | "ISDN_CMD_DIAL (phone: %s, msn: %s, si1: %d, si2: %d)", |
151 | "phone: %s, ownmsn: %s, si1: %d, si2: %d)", | ||
152 | cntrl->driver, cntrl->arg, | ||
153 | cntrl->parm.setup.phone, cntrl->parm.setup.eazmsn, | 221 | cntrl->parm.setup.phone, cntrl->parm.setup.eazmsn, |
154 | cntrl->parm.setup.si1, cntrl->parm.setup.si2); | 222 | cntrl->parm.setup.si1, cntrl->parm.setup.si2); |
155 | 223 | ||
156 | if (cntrl->arg >= cs->channels) { | 224 | if (ch >= cs->channels) { |
157 | dev_err(cs->dev, | 225 | dev_err(cs->dev, |
158 | "ISDN_CMD_DIAL: invalid channel (%d)\n", | 226 | "ISDN_CMD_DIAL: invalid channel (%d)\n", ch); |
159 | (int) cntrl->arg); | ||
160 | return -EINVAL; | 227 | return -EINVAL; |
161 | } | 228 | } |
162 | 229 | bcs = cs->bcs + ch; | |
163 | bcs = cs->bcs + cntrl->arg; | ||
164 | |||
165 | if (!gigaset_get_channel(bcs)) { | 230 | if (!gigaset_get_channel(bcs)) { |
166 | dev_err(cs->dev, "ISDN_CMD_DIAL: channel not free\n"); | 231 | dev_err(cs->dev, "ISDN_CMD_DIAL: channel not free\n"); |
167 | return -EBUSY; | 232 | return -EBUSY; |
168 | } | 233 | } |
169 | 234 | ||
170 | sp = kmalloc(sizeof *sp, GFP_ATOMIC); | 235 | commands = kzalloc(AT_NUM*(sizeof *commands), GFP_ATOMIC); |
171 | if (!sp) { | 236 | if (!commands) { |
172 | gigaset_free_channel(bcs); | 237 | gigaset_free_channel(bcs); |
173 | dev_err(cs->dev, "ISDN_CMD_DIAL: out of memory\n"); | 238 | dev_err(cs->dev, "ISDN_CMD_DIAL: out of memory\n"); |
174 | return -ENOMEM; | 239 | return -ENOMEM; |
175 | } | 240 | } |
176 | *sp = cntrl->parm.setup; | ||
177 | 241 | ||
178 | if (!gigaset_add_event(cs, &bcs->at_state, EV_DIAL, sp, | 242 | l = 3 + strlen(cntrl->parm.setup.phone); |
243 | commands[AT_DIAL] = kmalloc(l, GFP_ATOMIC); | ||
244 | if (!commands[AT_DIAL]) | ||
245 | goto oom; | ||
246 | if (cntrl->parm.setup.phone[0] == '*' && | ||
247 | cntrl->parm.setup.phone[1] == '*') { | ||
248 | /* internal call: translate ** prefix to CTP value */ | ||
249 | commands[AT_TYPE] = kstrdup("^SCTP=0\r", GFP_ATOMIC); | ||
250 | if (!commands[AT_TYPE]) | ||
251 | goto oom; | ||
252 | snprintf(commands[AT_DIAL], l, | ||
253 | "D%s\r", cntrl->parm.setup.phone+2); | ||
254 | } else { | ||
255 | commands[AT_TYPE] = kstrdup("^SCTP=1\r", GFP_ATOMIC); | ||
256 | if (!commands[AT_TYPE]) | ||
257 | goto oom; | ||
258 | snprintf(commands[AT_DIAL], l, | ||
259 | "D%s\r", cntrl->parm.setup.phone); | ||
260 | } | ||
261 | |||
262 | l = strlen(cntrl->parm.setup.eazmsn); | ||
263 | if (l) { | ||
264 | l += 8; | ||
265 | commands[AT_MSN] = kmalloc(l, GFP_ATOMIC); | ||
266 | if (!commands[AT_MSN]) | ||
267 | goto oom; | ||
268 | snprintf(commands[AT_MSN], l, "^SMSN=%s\r", | ||
269 | cntrl->parm.setup.eazmsn); | ||
270 | } | ||
271 | |||
272 | switch (cntrl->parm.setup.si1) { | ||
273 | case 1: /* audio */ | ||
274 | /* BC = 9090A3: 3.1 kHz audio, A-law */ | ||
275 | commands[AT_BC] = kstrdup("^SBC=9090A3\r", GFP_ATOMIC); | ||
276 | if (!commands[AT_BC]) | ||
277 | goto oom; | ||
278 | break; | ||
279 | case 7: /* data */ | ||
280 | default: /* hope the app knows what it is doing */ | ||
281 | /* BC = 8890: unrestricted digital information */ | ||
282 | commands[AT_BC] = kstrdup("^SBC=8890\r", GFP_ATOMIC); | ||
283 | if (!commands[AT_BC]) | ||
284 | goto oom; | ||
285 | } | ||
286 | /* ToDo: other si1 values, inspect si2, set HLC/LLC */ | ||
287 | |||
288 | commands[AT_PROTO] = kmalloc(9, GFP_ATOMIC); | ||
289 | if (!commands[AT_PROTO]) | ||
290 | goto oom; | ||
291 | snprintf(commands[AT_PROTO], 9, "^SBPR=%u\r", bcs->proto2); | ||
292 | |||
293 | commands[AT_ISO] = kmalloc(9, GFP_ATOMIC); | ||
294 | if (!commands[AT_ISO]) | ||
295 | goto oom; | ||
296 | snprintf(commands[AT_ISO], 9, "^SISO=%u\r", | ||
297 | (unsigned) bcs->channel + 1); | ||
298 | |||
299 | if (!gigaset_add_event(cs, &bcs->at_state, EV_DIAL, commands, | ||
179 | bcs->at_state.seq_index, NULL)) { | 300 | bcs->at_state.seq_index, NULL)) { |
180 | //FIXME what should we do? | 301 | for (i = 0; i < AT_NUM; ++i) |
181 | kfree(sp); | 302 | kfree(commands[i]); |
303 | kfree(commands); | ||
182 | gigaset_free_channel(bcs); | 304 | gigaset_free_channel(bcs); |
183 | return -ENOMEM; | 305 | return -ENOMEM; |
184 | } | 306 | } |
185 | |||
186 | gig_dbg(DEBUG_CMD, "scheduling DIAL"); | ||
187 | gigaset_schedule_event(cs); | 307 | gigaset_schedule_event(cs); |
188 | break; | 308 | break; |
189 | case ISDN_CMD_ACCEPTD: //FIXME | 309 | case ISDN_CMD_ACCEPTD: |
190 | gig_dbg(DEBUG_ANY, "ISDN_CMD_ACCEPTD"); | 310 | gig_dbg(DEBUG_CMD, "ISDN_CMD_ACCEPTD"); |
191 | 311 | if (ch >= cs->channels) { | |
192 | if (cntrl->arg >= cs->channels) { | ||
193 | dev_err(cs->dev, | 312 | dev_err(cs->dev, |
194 | "ISDN_CMD_ACCEPTD: invalid channel (%d)\n", | 313 | "ISDN_CMD_ACCEPTD: invalid channel (%d)\n", ch); |
195 | (int) cntrl->arg); | ||
196 | return -EINVAL; | 314 | return -EINVAL; |
197 | } | 315 | } |
198 | 316 | bcs = cs->bcs + ch; | |
199 | if (!gigaset_add_event(cs, &cs->bcs[cntrl->arg].at_state, | 317 | if (!gigaset_add_event(cs, &bcs->at_state, |
200 | EV_ACCEPT, NULL, 0, NULL)) { | 318 | EV_ACCEPT, NULL, 0, NULL)) |
201 | //FIXME what should we do? | ||
202 | return -ENOMEM; | 319 | return -ENOMEM; |
203 | } | ||
204 | |||
205 | gig_dbg(DEBUG_CMD, "scheduling ACCEPT"); | ||
206 | gigaset_schedule_event(cs); | 320 | gigaset_schedule_event(cs); |
207 | 321 | ||
208 | break; | 322 | break; |
209 | case ISDN_CMD_ACCEPTB: | ||
210 | gig_dbg(DEBUG_ANY, "ISDN_CMD_ACCEPTB"); | ||
211 | break; | ||
212 | case ISDN_CMD_HANGUP: | 323 | case ISDN_CMD_HANGUP: |
213 | gig_dbg(DEBUG_ANY, "ISDN_CMD_HANGUP (ch: %d)", | 324 | gig_dbg(DEBUG_CMD, "ISDN_CMD_HANGUP"); |
214 | (int) cntrl->arg); | 325 | if (ch >= cs->channels) { |
215 | |||
216 | if (cntrl->arg >= cs->channels) { | ||
217 | dev_err(cs->dev, | 326 | dev_err(cs->dev, |
218 | "ISDN_CMD_HANGUP: invalid channel (%d)\n", | 327 | "ISDN_CMD_HANGUP: invalid channel (%d)\n", ch); |
219 | (int) cntrl->arg); | ||
220 | return -EINVAL; | 328 | return -EINVAL; |
221 | } | 329 | } |
222 | 330 | bcs = cs->bcs + ch; | |
223 | if (!gigaset_add_event(cs, &cs->bcs[cntrl->arg].at_state, | 331 | if (!gigaset_add_event(cs, &bcs->at_state, |
224 | EV_HUP, NULL, 0, NULL)) { | 332 | EV_HUP, NULL, 0, NULL)) |
225 | //FIXME what should we do? | ||
226 | return -ENOMEM; | 333 | return -ENOMEM; |
227 | } | ||
228 | |||
229 | gig_dbg(DEBUG_CMD, "scheduling HUP"); | ||
230 | gigaset_schedule_event(cs); | 334 | gigaset_schedule_event(cs); |
231 | 335 | ||
232 | break; | 336 | break; |
233 | case ISDN_CMD_CLREAZ: /* Do not signal incoming signals */ //FIXME | 337 | case ISDN_CMD_CLREAZ: /* Do not signal incoming signals */ |
234 | gig_dbg(DEBUG_ANY, "ISDN_CMD_CLREAZ"); | 338 | dev_info(cs->dev, "ignoring ISDN_CMD_CLREAZ\n"); |
235 | break; | 339 | break; |
236 | case ISDN_CMD_SETEAZ: /* Signal incoming calls for given MSN */ //FIXME | 340 | case ISDN_CMD_SETEAZ: /* Signal incoming calls for given MSN */ |
237 | gig_dbg(DEBUG_ANY, | 341 | dev_info(cs->dev, "ignoring ISDN_CMD_SETEAZ (%s)\n", |
238 | "ISDN_CMD_SETEAZ (id: %d, ch: %ld, number: %s)", | 342 | cntrl->parm.num); |
239 | cntrl->driver, cntrl->arg, cntrl->parm.num); | ||
240 | break; | 343 | break; |
241 | case ISDN_CMD_SETL2: /* Set L2 to given protocol */ | 344 | case ISDN_CMD_SETL2: /* Set L2 to given protocol */ |
242 | gig_dbg(DEBUG_ANY, "ISDN_CMD_SETL2 (ch: %ld, proto: %lx)", | 345 | if (ch >= cs->channels) { |
243 | cntrl->arg & 0xff, (cntrl->arg >> 8)); | ||
244 | |||
245 | if ((cntrl->arg & 0xff) >= cs->channels) { | ||
246 | dev_err(cs->dev, | 346 | dev_err(cs->dev, |
247 | "ISDN_CMD_SETL2: invalid channel (%d)\n", | 347 | "ISDN_CMD_SETL2: invalid channel (%d)\n", ch); |
248 | (int) cntrl->arg & 0xff); | ||
249 | return -EINVAL; | 348 | return -EINVAL; |
250 | } | 349 | } |
251 | 350 | bcs = cs->bcs + ch; | |
252 | if (!gigaset_add_event(cs, &cs->bcs[cntrl->arg & 0xff].at_state, | 351 | if (bcs->chstate & CHS_D_UP) { |
253 | EV_PROTO_L2, NULL, cntrl->arg >> 8, | 352 | dev_err(cs->dev, |
254 | NULL)) { | 353 | "ISDN_CMD_SETL2: channel active (%d)\n", ch); |
255 | //FIXME what should we do? | 354 | return -EINVAL; |
256 | return -ENOMEM; | 355 | } |
356 | switch (cntrl->arg >> 8) { | ||
357 | case ISDN_PROTO_L2_HDLC: | ||
358 | gig_dbg(DEBUG_CMD, "ISDN_CMD_SETL2: setting L2_HDLC"); | ||
359 | bcs->proto2 = L2_HDLC; | ||
360 | break; | ||
361 | case ISDN_PROTO_L2_TRANS: | ||
362 | gig_dbg(DEBUG_CMD, "ISDN_CMD_SETL2: setting L2_VOICE"); | ||
363 | bcs->proto2 = L2_VOICE; | ||
364 | break; | ||
365 | default: | ||
366 | dev_err(cs->dev, | ||
367 | "ISDN_CMD_SETL2: unsupported protocol (%lu)\n", | ||
368 | cntrl->arg >> 8); | ||
369 | return -EINVAL; | ||
257 | } | 370 | } |
258 | |||
259 | gig_dbg(DEBUG_CMD, "scheduling PROTO_L2"); | ||
260 | gigaset_schedule_event(cs); | ||
261 | break; | 371 | break; |
262 | case ISDN_CMD_SETL3: /* Set L3 to given protocol */ | 372 | case ISDN_CMD_SETL3: /* Set L3 to given protocol */ |
263 | gig_dbg(DEBUG_ANY, "ISDN_CMD_SETL3 (ch: %ld, proto: %lx)", | 373 | gig_dbg(DEBUG_CMD, "ISDN_CMD_SETL3"); |
264 | cntrl->arg & 0xff, (cntrl->arg >> 8)); | 374 | if (ch >= cs->channels) { |
265 | |||
266 | if ((cntrl->arg & 0xff) >= cs->channels) { | ||
267 | dev_err(cs->dev, | 375 | dev_err(cs->dev, |
268 | "ISDN_CMD_SETL3: invalid channel (%d)\n", | 376 | "ISDN_CMD_SETL3: invalid channel (%d)\n", ch); |
269 | (int) cntrl->arg & 0xff); | ||
270 | return -EINVAL; | 377 | return -EINVAL; |
271 | } | 378 | } |
272 | 379 | ||
273 | if (cntrl->arg >> 8 != ISDN_PROTO_L3_TRANS) { | 380 | if (cntrl->arg >> 8 != ISDN_PROTO_L3_TRANS) { |
274 | dev_err(cs->dev, | 381 | dev_err(cs->dev, |
275 | "ISDN_CMD_SETL3: invalid protocol %lu\n", | 382 | "ISDN_CMD_SETL3: unsupported protocol (%lu)\n", |
276 | cntrl->arg >> 8); | 383 | cntrl->arg >> 8); |
277 | return -EINVAL; | 384 | return -EINVAL; |
278 | } | 385 | } |
279 | 386 | ||
280 | break; | 387 | break; |
281 | case ISDN_CMD_PROCEED: | 388 | |
282 | gig_dbg(DEBUG_ANY, "ISDN_CMD_PROCEED"); //FIXME | ||
283 | break; | ||
284 | case ISDN_CMD_ALERT: | ||
285 | gig_dbg(DEBUG_ANY, "ISDN_CMD_ALERT"); //FIXME | ||
286 | if (cntrl->arg >= cs->channels) { | ||
287 | dev_err(cs->dev, | ||
288 | "ISDN_CMD_ALERT: invalid channel (%d)\n", | ||
289 | (int) cntrl->arg); | ||
290 | return -EINVAL; | ||
291 | } | ||
292 | //bcs = cs->bcs + cntrl->arg; | ||
293 | //bcs->proto2 = -1; | ||
294 | // FIXME | ||
295 | break; | ||
296 | case ISDN_CMD_REDIR: | ||
297 | gig_dbg(DEBUG_ANY, "ISDN_CMD_REDIR"); //FIXME | ||
298 | break; | ||
299 | case ISDN_CMD_PROT_IO: | ||
300 | gig_dbg(DEBUG_ANY, "ISDN_CMD_PROT_IO"); | ||
301 | break; | ||
302 | case ISDN_CMD_FAXCMD: | ||
303 | gig_dbg(DEBUG_ANY, "ISDN_CMD_FAXCMD"); | ||
304 | break; | ||
305 | case ISDN_CMD_GETL2: | ||
306 | gig_dbg(DEBUG_ANY, "ISDN_CMD_GETL2"); | ||
307 | break; | ||
308 | case ISDN_CMD_GETL3: | ||
309 | gig_dbg(DEBUG_ANY, "ISDN_CMD_GETL3"); | ||
310 | break; | ||
311 | case ISDN_CMD_GETEAZ: | ||
312 | gig_dbg(DEBUG_ANY, "ISDN_CMD_GETEAZ"); | ||
313 | break; | ||
314 | case ISDN_CMD_SETSIL: | ||
315 | gig_dbg(DEBUG_ANY, "ISDN_CMD_SETSIL"); | ||
316 | break; | ||
317 | case ISDN_CMD_GETSIL: | ||
318 | gig_dbg(DEBUG_ANY, "ISDN_CMD_GETSIL"); | ||
319 | break; | ||
320 | default: | 389 | default: |
321 | dev_err(cs->dev, "unknown command %d from LL\n", | 390 | gig_dbg(DEBUG_CMD, "unknown command %d from LL", |
322 | cntrl->command); | 391 | cntrl->command); |
323 | return -EINVAL; | 392 | return -EINVAL; |
324 | } | 393 | } |
325 | 394 | ||
326 | return retval; | 395 | return retval; |
396 | |||
397 | oom: | ||
398 | dev_err(bcs->cs->dev, "out of memory\n"); | ||
399 | for (i = 0; i < AT_NUM; ++i) | ||
400 | kfree(commands[i]); | ||
401 | return -ENOMEM; | ||
327 | } | 402 | } |
328 | 403 | ||
329 | void gigaset_i4l_cmd(struct cardstate *cs, int cmd) | 404 | static void gigaset_i4l_cmd(struct cardstate *cs, int cmd) |
330 | { | 405 | { |
406 | isdn_if *iif = cs->iif; | ||
331 | isdn_ctrl command; | 407 | isdn_ctrl command; |
332 | 408 | ||
333 | command.driver = cs->myid; | 409 | command.driver = cs->myid; |
334 | command.command = cmd; | 410 | command.command = cmd; |
335 | command.arg = 0; | 411 | command.arg = 0; |
336 | cs->iif.statcallb(&command); | 412 | iif->statcallb(&command); |
337 | } | 413 | } |
338 | 414 | ||
339 | void gigaset_i4l_channel_cmd(struct bc_state *bcs, int cmd) | 415 | static void gigaset_i4l_channel_cmd(struct bc_state *bcs, int cmd) |
340 | { | 416 | { |
417 | isdn_if *iif = bcs->cs->iif; | ||
341 | isdn_ctrl command; | 418 | isdn_ctrl command; |
342 | 419 | ||
343 | command.driver = bcs->cs->myid; | 420 | command.driver = bcs->cs->myid; |
344 | command.command = cmd; | 421 | command.command = cmd; |
345 | command.arg = bcs->channel; | 422 | command.arg = bcs->channel; |
346 | bcs->cs->iif.statcallb(&command); | 423 | iif->statcallb(&command); |
347 | } | ||
348 | |||
349 | int gigaset_isdn_setup_dial(struct at_state_t *at_state, void *data) | ||
350 | { | ||
351 | struct bc_state *bcs = at_state->bcs; | ||
352 | unsigned proto; | ||
353 | const char *bc; | ||
354 | size_t length[AT_NUM]; | ||
355 | size_t l; | ||
356 | int i; | ||
357 | struct setup_parm *sp = data; | ||
358 | |||
359 | switch (bcs->proto2) { | ||
360 | case ISDN_PROTO_L2_HDLC: | ||
361 | proto = 1; /* 0: Bitsynchron, 1: HDLC, 2: voice */ | ||
362 | break; | ||
363 | case ISDN_PROTO_L2_TRANS: | ||
364 | proto = 2; /* 0: Bitsynchron, 1: HDLC, 2: voice */ | ||
365 | break; | ||
366 | default: | ||
367 | dev_err(bcs->cs->dev, "%s: invalid L2 protocol: %u\n", | ||
368 | __func__, bcs->proto2); | ||
369 | return -EINVAL; | ||
370 | } | ||
371 | |||
372 | switch (sp->si1) { | ||
373 | case 1: /* audio */ | ||
374 | bc = "9090A3"; /* 3.1 kHz audio, A-law */ | ||
375 | break; | ||
376 | case 7: /* data */ | ||
377 | default: /* hope the app knows what it is doing */ | ||
378 | bc = "8890"; /* unrestricted digital information */ | ||
379 | } | ||
380 | //FIXME add missing si1 values from 1TR6, inspect si2, set HLC/LLC | ||
381 | |||
382 | length[AT_DIAL ] = 1 + strlen(sp->phone) + 1 + 1; | ||
383 | l = strlen(sp->eazmsn); | ||
384 | length[AT_MSN ] = l ? 6 + l + 1 + 1 : 0; | ||
385 | length[AT_BC ] = 5 + strlen(bc) + 1 + 1; | ||
386 | length[AT_PROTO] = 6 + 1 + 1 + 1; /* proto: 1 character */ | ||
387 | length[AT_ISO ] = 6 + 1 + 1 + 1; /* channel: 1 character */ | ||
388 | length[AT_TYPE ] = 6 + 1 + 1 + 1; /* call type: 1 character */ | ||
389 | length[AT_HLC ] = 0; | ||
390 | |||
391 | for (i = 0; i < AT_NUM; ++i) { | ||
392 | kfree(bcs->commands[i]); | ||
393 | bcs->commands[i] = NULL; | ||
394 | if (length[i] && | ||
395 | !(bcs->commands[i] = kmalloc(length[i], GFP_ATOMIC))) { | ||
396 | dev_err(bcs->cs->dev, "out of memory\n"); | ||
397 | return -ENOMEM; | ||
398 | } | ||
399 | } | ||
400 | |||
401 | /* type = 1: extern, 0: intern, 2: recall, 3: door, 4: centrex */ | ||
402 | if (sp->phone[0] == '*' && sp->phone[1] == '*') { | ||
403 | /* internal call: translate ** prefix to CTP value */ | ||
404 | snprintf(bcs->commands[AT_DIAL], length[AT_DIAL], | ||
405 | "D%s\r", sp->phone+2); | ||
406 | strncpy(bcs->commands[AT_TYPE], "^SCTP=0\r", length[AT_TYPE]); | ||
407 | } else { | ||
408 | snprintf(bcs->commands[AT_DIAL], length[AT_DIAL], | ||
409 | "D%s\r", sp->phone); | ||
410 | strncpy(bcs->commands[AT_TYPE], "^SCTP=1\r", length[AT_TYPE]); | ||
411 | } | ||
412 | |||
413 | if (bcs->commands[AT_MSN]) | ||
414 | snprintf(bcs->commands[AT_MSN], length[AT_MSN], | ||
415 | "^SMSN=%s\r", sp->eazmsn); | ||
416 | snprintf(bcs->commands[AT_BC ], length[AT_BC ], | ||
417 | "^SBC=%s\r", bc); | ||
418 | snprintf(bcs->commands[AT_PROTO], length[AT_PROTO], | ||
419 | "^SBPR=%u\r", proto); | ||
420 | snprintf(bcs->commands[AT_ISO ], length[AT_ISO ], | ||
421 | "^SISO=%u\r", (unsigned)bcs->channel + 1); | ||
422 | |||
423 | return 0; | ||
424 | } | ||
425 | |||
426 | int gigaset_isdn_setup_accept(struct at_state_t *at_state) | ||
427 | { | ||
428 | unsigned proto; | ||
429 | size_t length[AT_NUM]; | ||
430 | int i; | ||
431 | struct bc_state *bcs = at_state->bcs; | ||
432 | |||
433 | switch (bcs->proto2) { | ||
434 | case ISDN_PROTO_L2_HDLC: | ||
435 | proto = 1; /* 0: Bitsynchron, 1: HDLC, 2: voice */ | ||
436 | break; | ||
437 | case ISDN_PROTO_L2_TRANS: | ||
438 | proto = 2; /* 0: Bitsynchron, 1: HDLC, 2: voice */ | ||
439 | break; | ||
440 | default: | ||
441 | dev_err(at_state->cs->dev, "%s: invalid protocol: %u\n", | ||
442 | __func__, bcs->proto2); | ||
443 | return -EINVAL; | ||
444 | } | ||
445 | |||
446 | length[AT_DIAL ] = 0; | ||
447 | length[AT_MSN ] = 0; | ||
448 | length[AT_BC ] = 0; | ||
449 | length[AT_PROTO] = 6 + 1 + 1 + 1; /* proto: 1 character */ | ||
450 | length[AT_ISO ] = 6 + 1 + 1 + 1; /* channel: 1 character */ | ||
451 | length[AT_TYPE ] = 0; | ||
452 | length[AT_HLC ] = 0; | ||
453 | |||
454 | for (i = 0; i < AT_NUM; ++i) { | ||
455 | kfree(bcs->commands[i]); | ||
456 | bcs->commands[i] = NULL; | ||
457 | if (length[i] && | ||
458 | !(bcs->commands[i] = kmalloc(length[i], GFP_ATOMIC))) { | ||
459 | dev_err(at_state->cs->dev, "out of memory\n"); | ||
460 | return -ENOMEM; | ||
461 | } | ||
462 | } | ||
463 | |||
464 | snprintf(bcs->commands[AT_PROTO], length[AT_PROTO], | ||
465 | "^SBPR=%u\r", proto); | ||
466 | snprintf(bcs->commands[AT_ISO ], length[AT_ISO ], | ||
467 | "^SISO=%u\r", (unsigned) bcs->channel + 1); | ||
468 | |||
469 | return 0; | ||
470 | } | 424 | } |
471 | 425 | ||
472 | /** | 426 | /** |
@@ -482,13 +436,14 @@ int gigaset_isdn_icall(struct at_state_t *at_state) | |||
482 | { | 436 | { |
483 | struct cardstate *cs = at_state->cs; | 437 | struct cardstate *cs = at_state->cs; |
484 | struct bc_state *bcs = at_state->bcs; | 438 | struct bc_state *bcs = at_state->bcs; |
439 | isdn_if *iif = cs->iif; | ||
485 | isdn_ctrl response; | 440 | isdn_ctrl response; |
486 | int retval; | 441 | int retval; |
487 | 442 | ||
488 | /* fill ICALL structure */ | 443 | /* fill ICALL structure */ |
489 | response.parm.setup.si1 = 0; /* default: unknown */ | 444 | response.parm.setup.si1 = 0; /* default: unknown */ |
490 | response.parm.setup.si2 = 0; | 445 | response.parm.setup.si2 = 0; |
491 | response.parm.setup.screen = 0; //FIXME how to set these? | 446 | response.parm.setup.screen = 0; |
492 | response.parm.setup.plan = 0; | 447 | response.parm.setup.plan = 0; |
493 | if (!at_state->str_var[STR_ZBC]) { | 448 | if (!at_state->str_var[STR_ZBC]) { |
494 | /* no BC (internal call): assume speech, A-law */ | 449 | /* no BC (internal call): assume speech, A-law */ |
@@ -509,29 +464,27 @@ int gigaset_isdn_icall(struct at_state_t *at_state) | |||
509 | return ICALL_IGNORE; | 464 | return ICALL_IGNORE; |
510 | } | 465 | } |
511 | if (at_state->str_var[STR_NMBR]) { | 466 | if (at_state->str_var[STR_NMBR]) { |
512 | strncpy(response.parm.setup.phone, at_state->str_var[STR_NMBR], | 467 | strlcpy(response.parm.setup.phone, at_state->str_var[STR_NMBR], |
513 | sizeof response.parm.setup.phone - 1); | 468 | sizeof response.parm.setup.phone); |
514 | response.parm.setup.phone[sizeof response.parm.setup.phone - 1] = 0; | ||
515 | } else | 469 | } else |
516 | response.parm.setup.phone[0] = 0; | 470 | response.parm.setup.phone[0] = 0; |
517 | if (at_state->str_var[STR_ZCPN]) { | 471 | if (at_state->str_var[STR_ZCPN]) { |
518 | strncpy(response.parm.setup.eazmsn, at_state->str_var[STR_ZCPN], | 472 | strlcpy(response.parm.setup.eazmsn, at_state->str_var[STR_ZCPN], |
519 | sizeof response.parm.setup.eazmsn - 1); | 473 | sizeof response.parm.setup.eazmsn); |
520 | response.parm.setup.eazmsn[sizeof response.parm.setup.eazmsn - 1] = 0; | ||
521 | } else | 474 | } else |
522 | response.parm.setup.eazmsn[0] = 0; | 475 | response.parm.setup.eazmsn[0] = 0; |
523 | 476 | ||
524 | if (!bcs) { | 477 | if (!bcs) { |
525 | dev_notice(cs->dev, "no channel for incoming call\n"); | 478 | dev_notice(cs->dev, "no channel for incoming call\n"); |
526 | response.command = ISDN_STAT_ICALLW; | 479 | response.command = ISDN_STAT_ICALLW; |
527 | response.arg = 0; //FIXME | 480 | response.arg = 0; |
528 | } else { | 481 | } else { |
529 | gig_dbg(DEBUG_CMD, "Sending ICALL"); | 482 | gig_dbg(DEBUG_CMD, "Sending ICALL"); |
530 | response.command = ISDN_STAT_ICALL; | 483 | response.command = ISDN_STAT_ICALL; |
531 | response.arg = bcs->channel; //FIXME | 484 | response.arg = bcs->channel; |
532 | } | 485 | } |
533 | response.driver = cs->myid; | 486 | response.driver = cs->myid; |
534 | retval = cs->iif.statcallb(&response); | 487 | retval = iif->statcallb(&response); |
535 | gig_dbg(DEBUG_CMD, "Response: %d", retval); | 488 | gig_dbg(DEBUG_CMD, "Response: %d", retval); |
536 | switch (retval) { | 489 | switch (retval) { |
537 | case 0: /* no takers */ | 490 | case 0: /* no takers */ |
@@ -560,16 +513,107 @@ int gigaset_isdn_icall(struct at_state_t *at_state) | |||
560 | } | 513 | } |
561 | } | 514 | } |
562 | 515 | ||
563 | /* Set Callback function pointer */ | 516 | /** |
564 | int gigaset_register_to_LL(struct cardstate *cs, const char *isdnid) | 517 | * gigaset_isdn_connD() - signal D channel connect |
518 | * @bcs: B channel descriptor structure. | ||
519 | * | ||
520 | * Called by main module to notify the LL that the D channel connection has | ||
521 | * been established. | ||
522 | */ | ||
523 | void gigaset_isdn_connD(struct bc_state *bcs) | ||
524 | { | ||
525 | gig_dbg(DEBUG_CMD, "sending DCONN"); | ||
526 | gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DCONN); | ||
527 | } | ||
528 | |||
529 | /** | ||
530 | * gigaset_isdn_hupD() - signal D channel hangup | ||
531 | * @bcs: B channel descriptor structure. | ||
532 | * | ||
533 | * Called by main module to notify the LL that the D channel connection has | ||
534 | * been shut down. | ||
535 | */ | ||
536 | void gigaset_isdn_hupD(struct bc_state *bcs) | ||
537 | { | ||
538 | gig_dbg(DEBUG_CMD, "sending DHUP"); | ||
539 | gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DHUP); | ||
540 | } | ||
541 | |||
542 | /** | ||
543 | * gigaset_isdn_connB() - signal B channel connect | ||
544 | * @bcs: B channel descriptor structure. | ||
545 | * | ||
546 | * Called by main module to notify the LL that the B channel connection has | ||
547 | * been established. | ||
548 | */ | ||
549 | void gigaset_isdn_connB(struct bc_state *bcs) | ||
550 | { | ||
551 | gig_dbg(DEBUG_CMD, "sending BCONN"); | ||
552 | gigaset_i4l_channel_cmd(bcs, ISDN_STAT_BCONN); | ||
553 | } | ||
554 | |||
555 | /** | ||
556 | * gigaset_isdn_hupB() - signal B channel hangup | ||
557 | * @bcs: B channel descriptor structure. | ||
558 | * | ||
559 | * Called by main module to notify the LL that the B channel connection has | ||
560 | * been shut down. | ||
561 | */ | ||
562 | void gigaset_isdn_hupB(struct bc_state *bcs) | ||
565 | { | 563 | { |
566 | isdn_if *iif = &cs->iif; | 564 | gig_dbg(DEBUG_CMD, "sending BHUP"); |
565 | gigaset_i4l_channel_cmd(bcs, ISDN_STAT_BHUP); | ||
566 | } | ||
567 | 567 | ||
568 | gig_dbg(DEBUG_ANY, "Register driver capabilities to LL"); | 568 | /** |
569 | * gigaset_isdn_start() - signal device availability | ||
570 | * @cs: device descriptor structure. | ||
571 | * | ||
572 | * Called by main module to notify the LL that the device is available for | ||
573 | * use. | ||
574 | */ | ||
575 | void gigaset_isdn_start(struct cardstate *cs) | ||
576 | { | ||
577 | gig_dbg(DEBUG_CMD, "sending RUN"); | ||
578 | gigaset_i4l_cmd(cs, ISDN_STAT_RUN); | ||
579 | } | ||
580 | |||
581 | /** | ||
582 | * gigaset_isdn_stop() - signal device unavailability | ||
583 | * @cs: device descriptor structure. | ||
584 | * | ||
585 | * Called by main module to notify the LL that the device is no longer | ||
586 | * available for use. | ||
587 | */ | ||
588 | void gigaset_isdn_stop(struct cardstate *cs) | ||
589 | { | ||
590 | gig_dbg(DEBUG_CMD, "sending STOP"); | ||
591 | gigaset_i4l_cmd(cs, ISDN_STAT_STOP); | ||
592 | } | ||
593 | |||
594 | /** | ||
595 | * gigaset_isdn_regdev() - register to LL | ||
596 | * @cs: device descriptor structure. | ||
597 | * @isdnid: device name. | ||
598 | * | ||
599 | * Return value: 1 for success, 0 for failure | ||
600 | */ | ||
601 | int gigaset_isdn_regdev(struct cardstate *cs, const char *isdnid) | ||
602 | { | ||
603 | isdn_if *iif; | ||
604 | |||
605 | pr_info("ISDN4Linux interface\n"); | ||
606 | |||
607 | iif = kmalloc(sizeof *iif, GFP_KERNEL); | ||
608 | if (!iif) { | ||
609 | pr_err("out of memory\n"); | ||
610 | return 0; | ||
611 | } | ||
569 | 612 | ||
570 | if (snprintf(iif->id, sizeof iif->id, "%s_%u", isdnid, cs->minor_index) | 613 | if (snprintf(iif->id, sizeof iif->id, "%s_%u", isdnid, cs->minor_index) |
571 | >= sizeof iif->id) { | 614 | >= sizeof iif->id) { |
572 | pr_err("ID too long: %s\n", isdnid); | 615 | pr_err("ID too long: %s\n", isdnid); |
616 | kfree(iif); | ||
573 | return 0; | 617 | return 0; |
574 | } | 618 | } |
575 | 619 | ||
@@ -593,9 +637,40 @@ int gigaset_register_to_LL(struct cardstate *cs, const char *isdnid) | |||
593 | 637 | ||
594 | if (!register_isdn(iif)) { | 638 | if (!register_isdn(iif)) { |
595 | pr_err("register_isdn failed\n"); | 639 | pr_err("register_isdn failed\n"); |
640 | kfree(iif); | ||
596 | return 0; | 641 | return 0; |
597 | } | 642 | } |
598 | 643 | ||
644 | cs->iif = iif; | ||
599 | cs->myid = iif->channels; /* Set my device id */ | 645 | cs->myid = iif->channels; /* Set my device id */ |
646 | cs->hw_hdr_len = HW_HDR_LEN; | ||
600 | return 1; | 647 | return 1; |
601 | } | 648 | } |
649 | |||
650 | /** | ||
651 | * gigaset_isdn_unregdev() - unregister device from LL | ||
652 | * @cs: device descriptor structure. | ||
653 | */ | ||
654 | void gigaset_isdn_unregdev(struct cardstate *cs) | ||
655 | { | ||
656 | gig_dbg(DEBUG_CMD, "sending UNLOAD"); | ||
657 | gigaset_i4l_cmd(cs, ISDN_STAT_UNLOAD); | ||
658 | kfree(cs->iif); | ||
659 | cs->iif = NULL; | ||
660 | } | ||
661 | |||
662 | /** | ||
663 | * gigaset_isdn_regdrv() - register driver to LL | ||
664 | */ | ||
665 | void gigaset_isdn_regdrv(void) | ||
666 | { | ||
667 | /* nothing to do */ | ||
668 | } | ||
669 | |||
670 | /** | ||
671 | * gigaset_isdn_unregdrv() - unregister driver from LL | ||
672 | */ | ||
673 | void gigaset_isdn_unregdrv(void) | ||
674 | { | ||
675 | /* nothing to do */ | ||
676 | } | ||
diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c index 6a8e1384e7bd..c9f28dd40d5c 100644 --- a/drivers/isdn/gigaset/interface.c +++ b/drivers/isdn/gigaset/interface.c | |||
@@ -13,7 +13,6 @@ | |||
13 | 13 | ||
14 | #include "gigaset.h" | 14 | #include "gigaset.h" |
15 | #include <linux/gigaset_dev.h> | 15 | #include <linux/gigaset_dev.h> |
16 | #include <linux/tty.h> | ||
17 | #include <linux/tty_flip.h> | 16 | #include <linux/tty_flip.h> |
18 | 17 | ||
19 | /*** our ioctls ***/ | 18 | /*** our ioctls ***/ |
@@ -45,8 +44,6 @@ static int if_lock(struct cardstate *cs, int *arg) | |||
45 | cs->waiting = 0; | 44 | cs->waiting = 0; |
46 | return -ENOMEM; | 45 | return -ENOMEM; |
47 | } | 46 | } |
48 | |||
49 | gig_dbg(DEBUG_CMD, "scheduling IF_LOCK"); | ||
50 | gigaset_schedule_event(cs); | 47 | gigaset_schedule_event(cs); |
51 | 48 | ||
52 | wait_event(cs->waitqueue, !cs->waiting); | 49 | wait_event(cs->waitqueue, !cs->waiting); |
@@ -81,8 +78,6 @@ static int if_version(struct cardstate *cs, unsigned arg[4]) | |||
81 | cs->waiting = 0; | 78 | cs->waiting = 0; |
82 | return -ENOMEM; | 79 | return -ENOMEM; |
83 | } | 80 | } |
84 | |||
85 | gig_dbg(DEBUG_CMD, "scheduling IF_VER"); | ||
86 | gigaset_schedule_event(cs); | 81 | gigaset_schedule_event(cs); |
87 | 82 | ||
88 | wait_event(cs->waitqueue, !cs->waiting); | 83 | wait_event(cs->waitqueue, !cs->waiting); |
@@ -162,7 +157,7 @@ static int if_open(struct tty_struct *tty, struct file *filp) | |||
162 | return -ENODEV; | 157 | return -ENODEV; |
163 | 158 | ||
164 | if (mutex_lock_interruptible(&cs->mutex)) | 159 | if (mutex_lock_interruptible(&cs->mutex)) |
165 | return -ERESTARTSYS; // FIXME -EINTR? | 160 | return -ERESTARTSYS; |
166 | tty->driver_data = cs; | 161 | tty->driver_data = cs; |
167 | 162 | ||
168 | ++cs->open_count; | 163 | ++cs->open_count; |
@@ -171,7 +166,7 @@ static int if_open(struct tty_struct *tty, struct file *filp) | |||
171 | spin_lock_irqsave(&cs->lock, flags); | 166 | spin_lock_irqsave(&cs->lock, flags); |
172 | cs->tty = tty; | 167 | cs->tty = tty; |
173 | spin_unlock_irqrestore(&cs->lock, flags); | 168 | spin_unlock_irqrestore(&cs->lock, flags); |
174 | tty->low_latency = 1; //FIXME test | 169 | tty->low_latency = 1; |
175 | } | 170 | } |
176 | 171 | ||
177 | mutex_unlock(&cs->mutex); | 172 | mutex_unlock(&cs->mutex); |
@@ -228,7 +223,7 @@ static int if_ioctl(struct tty_struct *tty, struct file *file, | |||
228 | gig_dbg(DEBUG_IF, "%u: %s(0x%x)", cs->minor_index, __func__, cmd); | 223 | gig_dbg(DEBUG_IF, "%u: %s(0x%x)", cs->minor_index, __func__, cmd); |
229 | 224 | ||
230 | if (mutex_lock_interruptible(&cs->mutex)) | 225 | if (mutex_lock_interruptible(&cs->mutex)) |
231 | return -ERESTARTSYS; // FIXME -EINTR? | 226 | return -ERESTARTSYS; |
232 | 227 | ||
233 | if (!cs->connected) { | 228 | if (!cs->connected) { |
234 | gig_dbg(DEBUG_IF, "not connected"); | 229 | gig_dbg(DEBUG_IF, "not connected"); |
@@ -274,7 +269,7 @@ static int if_ioctl(struct tty_struct *tty, struct file *file, | |||
274 | ? -EFAULT : 0; | 269 | ? -EFAULT : 0; |
275 | break; | 270 | break; |
276 | default: | 271 | default: |
277 | gig_dbg(DEBUG_ANY, "%s: arg not supported - 0x%04x", | 272 | gig_dbg(DEBUG_IF, "%s: arg not supported - 0x%04x", |
278 | __func__, cmd); | 273 | __func__, cmd); |
279 | retval = -ENOIOCTLCMD; | 274 | retval = -ENOIOCTLCMD; |
280 | } | 275 | } |
@@ -299,9 +294,8 @@ static int if_tiocmget(struct tty_struct *tty, struct file *file) | |||
299 | gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); | 294 | gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); |
300 | 295 | ||
301 | if (mutex_lock_interruptible(&cs->mutex)) | 296 | if (mutex_lock_interruptible(&cs->mutex)) |
302 | return -ERESTARTSYS; // FIXME -EINTR? | 297 | return -ERESTARTSYS; |
303 | 298 | ||
304 | // FIXME read from device? | ||
305 | retval = cs->control_state & (TIOCM_RTS|TIOCM_DTR); | 299 | retval = cs->control_state & (TIOCM_RTS|TIOCM_DTR); |
306 | 300 | ||
307 | mutex_unlock(&cs->mutex); | 301 | mutex_unlock(&cs->mutex); |
@@ -326,7 +320,7 @@ static int if_tiocmset(struct tty_struct *tty, struct file *file, | |||
326 | cs->minor_index, __func__, set, clear); | 320 | cs->minor_index, __func__, set, clear); |
327 | 321 | ||
328 | if (mutex_lock_interruptible(&cs->mutex)) | 322 | if (mutex_lock_interruptible(&cs->mutex)) |
329 | return -ERESTARTSYS; // FIXME -EINTR? | 323 | return -ERESTARTSYS; |
330 | 324 | ||
331 | if (!cs->connected) { | 325 | if (!cs->connected) { |
332 | gig_dbg(DEBUG_IF, "not connected"); | 326 | gig_dbg(DEBUG_IF, "not connected"); |
@@ -356,7 +350,7 @@ static int if_write(struct tty_struct *tty, const unsigned char *buf, int count) | |||
356 | gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); | 350 | gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); |
357 | 351 | ||
358 | if (mutex_lock_interruptible(&cs->mutex)) | 352 | if (mutex_lock_interruptible(&cs->mutex)) |
359 | return -ERESTARTSYS; // FIXME -EINTR? | 353 | return -ERESTARTSYS; |
360 | 354 | ||
361 | if (!cs->connected) { | 355 | if (!cs->connected) { |
362 | gig_dbg(DEBUG_IF, "not connected"); | 356 | gig_dbg(DEBUG_IF, "not connected"); |
@@ -390,7 +384,7 @@ static int if_write_room(struct tty_struct *tty) | |||
390 | gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); | 384 | gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); |
391 | 385 | ||
392 | if (mutex_lock_interruptible(&cs->mutex)) | 386 | if (mutex_lock_interruptible(&cs->mutex)) |
393 | return -ERESTARTSYS; // FIXME -EINTR? | 387 | return -ERESTARTSYS; |
394 | 388 | ||
395 | if (!cs->connected) { | 389 | if (!cs->connected) { |
396 | gig_dbg(DEBUG_IF, "not connected"); | 390 | gig_dbg(DEBUG_IF, "not connected"); |
@@ -455,9 +449,8 @@ static void if_throttle(struct tty_struct *tty) | |||
455 | gig_dbg(DEBUG_IF, "not connected"); /* nothing to do */ | 449 | gig_dbg(DEBUG_IF, "not connected"); /* nothing to do */ |
456 | else if (!cs->open_count) | 450 | else if (!cs->open_count) |
457 | dev_warn(cs->dev, "%s: device not opened\n", __func__); | 451 | dev_warn(cs->dev, "%s: device not opened\n", __func__); |
458 | else { | 452 | else |
459 | //FIXME | 453 | gig_dbg(DEBUG_IF, "%s: not implemented\n", __func__); |
460 | } | ||
461 | 454 | ||
462 | mutex_unlock(&cs->mutex); | 455 | mutex_unlock(&cs->mutex); |
463 | } | 456 | } |
@@ -480,9 +473,8 @@ static void if_unthrottle(struct tty_struct *tty) | |||
480 | gig_dbg(DEBUG_IF, "not connected"); /* nothing to do */ | 473 | gig_dbg(DEBUG_IF, "not connected"); /* nothing to do */ |
481 | else if (!cs->open_count) | 474 | else if (!cs->open_count) |
482 | dev_warn(cs->dev, "%s: device not opened\n", __func__); | 475 | dev_warn(cs->dev, "%s: device not opened\n", __func__); |
483 | else { | 476 | else |
484 | //FIXME | 477 | gig_dbg(DEBUG_IF, "%s: not implemented\n", __func__); |
485 | } | ||
486 | 478 | ||
487 | mutex_unlock(&cs->mutex); | 479 | mutex_unlock(&cs->mutex); |
488 | } | 480 | } |
@@ -515,10 +507,9 @@ static void if_set_termios(struct tty_struct *tty, struct ktermios *old) | |||
515 | goto out; | 507 | goto out; |
516 | } | 508 | } |
517 | 509 | ||
518 | // stolen from mct_u232.c | ||
519 | iflag = tty->termios->c_iflag; | 510 | iflag = tty->termios->c_iflag; |
520 | cflag = tty->termios->c_cflag; | 511 | cflag = tty->termios->c_cflag; |
521 | old_cflag = old ? old->c_cflag : cflag; //FIXME? | 512 | old_cflag = old ? old->c_cflag : cflag; |
522 | gig_dbg(DEBUG_IF, "%u: iflag %x cflag %x old %x", | 513 | gig_dbg(DEBUG_IF, "%u: iflag %x cflag %x old %x", |
523 | cs->minor_index, iflag, cflag, old_cflag); | 514 | cs->minor_index, iflag, cflag, old_cflag); |
524 | 515 | ||
@@ -588,7 +579,7 @@ void gigaset_if_init(struct cardstate *cs) | |||
588 | if (!drv->have_tty) | 579 | if (!drv->have_tty) |
589 | return; | 580 | return; |
590 | 581 | ||
591 | tasklet_init(&cs->if_wake_tasklet, &if_wake, (unsigned long) cs); | 582 | tasklet_init(&cs->if_wake_tasklet, if_wake, (unsigned long) cs); |
592 | 583 | ||
593 | mutex_lock(&cs->mutex); | 584 | mutex_lock(&cs->mutex); |
594 | cs->tty_dev = tty_register_device(drv->tty, cs->minor_index, NULL); | 585 | cs->tty_dev = tty_register_device(drv->tty, cs->minor_index, NULL); |
@@ -632,10 +623,10 @@ void gigaset_if_receive(struct cardstate *cs, | |||
632 | struct tty_struct *tty; | 623 | struct tty_struct *tty; |
633 | 624 | ||
634 | spin_lock_irqsave(&cs->lock, flags); | 625 | spin_lock_irqsave(&cs->lock, flags); |
635 | if ((tty = cs->tty) == NULL) | 626 | tty = cs->tty; |
636 | gig_dbg(DEBUG_ANY, "receive on closed device"); | 627 | if (tty == NULL) |
628 | gig_dbg(DEBUG_IF, "receive on closed device"); | ||
637 | else { | 629 | else { |
638 | tty_buffer_request_room(tty, len); | ||
639 | tty_insert_flip_string(tty, buffer, len); | 630 | tty_insert_flip_string(tty, buffer, len); |
640 | tty_flip_buffer_push(tty); | 631 | tty_flip_buffer_push(tty); |
641 | } | 632 | } |
@@ -659,9 +650,9 @@ void gigaset_if_initdriver(struct gigaset_driver *drv, const char *procname, | |||
659 | 650 | ||
660 | drv->have_tty = 0; | 651 | drv->have_tty = 0; |
661 | 652 | ||
662 | if ((drv->tty = alloc_tty_driver(minors)) == NULL) | 653 | drv->tty = tty = alloc_tty_driver(minors); |
654 | if (tty == NULL) | ||
663 | goto enomem; | 655 | goto enomem; |
664 | tty = drv->tty; | ||
665 | 656 | ||
666 | tty->magic = TTY_DRIVER_MAGIC, | 657 | tty->magic = TTY_DRIVER_MAGIC, |
667 | tty->major = GIG_MAJOR, | 658 | tty->major = GIG_MAJOR, |
@@ -676,8 +667,8 @@ void gigaset_if_initdriver(struct gigaset_driver *drv, const char *procname, | |||
676 | 667 | ||
677 | tty->owner = THIS_MODULE; | 668 | tty->owner = THIS_MODULE; |
678 | 669 | ||
679 | tty->init_termios = tty_std_termios; //FIXME | 670 | tty->init_termios = tty_std_termios; |
680 | tty->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; //FIXME | 671 | tty->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; |
681 | tty_set_operations(tty, &if_ops); | 672 | tty_set_operations(tty, &if_ops); |
682 | 673 | ||
683 | ret = tty_register_driver(tty); | 674 | ret = tty_register_driver(tty); |
diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c index 9f3ef7b4248c..16fd3bd48883 100644 --- a/drivers/isdn/gigaset/isocdata.c +++ b/drivers/isdn/gigaset/isocdata.c | |||
@@ -41,7 +41,8 @@ static inline int isowbuf_freebytes(struct isowbuf_t *iwb) | |||
41 | 41 | ||
42 | read = iwb->read; | 42 | read = iwb->read; |
43 | write = iwb->write; | 43 | write = iwb->write; |
44 | if ((freebytes = read - write) > 0) { | 44 | freebytes = read - write; |
45 | if (freebytes > 0) { | ||
45 | /* no wraparound: need padding space within regular area */ | 46 | /* no wraparound: need padding space within regular area */ |
46 | return freebytes - BAS_OUTBUFPAD; | 47 | return freebytes - BAS_OUTBUFPAD; |
47 | } else if (read < BAS_OUTBUFPAD) { | 48 | } else if (read < BAS_OUTBUFPAD) { |
@@ -53,29 +54,6 @@ static inline int isowbuf_freebytes(struct isowbuf_t *iwb) | |||
53 | } | 54 | } |
54 | } | 55 | } |
55 | 56 | ||
56 | /* compare two offsets within the buffer | ||
57 | * The buffer is seen as circular, with the read position as start | ||
58 | * returns -1/0/1 if position a </=/> position b without crossing 'read' | ||
59 | */ | ||
60 | static inline int isowbuf_poscmp(struct isowbuf_t *iwb, int a, int b) | ||
61 | { | ||
62 | int read; | ||
63 | if (a == b) | ||
64 | return 0; | ||
65 | read = iwb->read; | ||
66 | if (a < b) { | ||
67 | if (a < read && read <= b) | ||
68 | return +1; | ||
69 | else | ||
70 | return -1; | ||
71 | } else { | ||
72 | if (b < read && read <= a) | ||
73 | return -1; | ||
74 | else | ||
75 | return +1; | ||
76 | } | ||
77 | } | ||
78 | |||
79 | /* start writing | 57 | /* start writing |
80 | * acquire the write semaphore | 58 | * acquire the write semaphore |
81 | * return true if acquired, false if busy | 59 | * return true if acquired, false if busy |
@@ -271,7 +249,7 @@ static inline void dump_bytes(enum debuglevel level, const char *tag, | |||
271 | * bit 14..13 = number of bits added by stuffing | 249 | * bit 14..13 = number of bits added by stuffing |
272 | */ | 250 | */ |
273 | static const u16 stufftab[5 * 256] = { | 251 | static const u16 stufftab[5 * 256] = { |
274 | // previous 1s = 0: | 252 | /* previous 1s = 0: */ |
275 | 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, | 253 | 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, |
276 | 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x201f, | 254 | 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x201f, |
277 | 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, | 255 | 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, |
@@ -289,7 +267,7 @@ static const u16 stufftab[5 * 256] = { | |||
289 | 0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0ce4, 0x0ce5, 0x0ce6, 0x0ce7, 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced, 0x0cee, 0x0cef, | 267 | 0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0ce4, 0x0ce5, 0x0ce6, 0x0ce7, 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced, 0x0cee, 0x0cef, |
290 | 0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6, 0x10f7, 0x20f8, 0x20f9, 0x20fa, 0x20fb, 0x257c, 0x257d, 0x29be, 0x2ddf, | 268 | 0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6, 0x10f7, 0x20f8, 0x20f9, 0x20fa, 0x20fb, 0x257c, 0x257d, 0x29be, 0x2ddf, |
291 | 269 | ||
292 | // previous 1s = 1: | 270 | /* previous 1s = 1: */ |
293 | 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x200f, | 271 | 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x200f, |
294 | 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x202f, | 272 | 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x202f, |
295 | 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x204f, | 273 | 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x204f, |
@@ -307,7 +285,7 @@ static const u16 stufftab[5 * 256] = { | |||
307 | 0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0ce4, 0x0ce5, 0x0ce6, 0x0ce7, 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced, 0x0cee, 0x2dcf, | 285 | 0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0ce4, 0x0ce5, 0x0ce6, 0x0ce7, 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced, 0x0cee, 0x2dcf, |
308 | 0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6, 0x10f7, 0x20f8, 0x20f9, 0x20fa, 0x20fb, 0x257c, 0x257d, 0x29be, 0x31ef, | 286 | 0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6, 0x10f7, 0x20f8, 0x20f9, 0x20fa, 0x20fb, 0x257c, 0x257d, 0x29be, 0x31ef, |
309 | 287 | ||
310 | // previous 1s = 2: | 288 | /* previous 1s = 2: */ |
311 | 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x2007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x2017, | 289 | 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x2007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x2017, |
312 | 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x2027, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x2037, | 290 | 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x2027, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x2037, |
313 | 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x2047, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x2057, | 291 | 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x2047, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x2057, |
@@ -325,7 +303,7 @@ static const u16 stufftab[5 * 256] = { | |||
325 | 0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0ce4, 0x0ce5, 0x0ce6, 0x2dc7, 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced, 0x0cee, 0x2dd7, | 303 | 0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0ce4, 0x0ce5, 0x0ce6, 0x2dc7, 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced, 0x0cee, 0x2dd7, |
326 | 0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6, 0x31e7, 0x20f8, 0x20f9, 0x20fa, 0x20fb, 0x257c, 0x257d, 0x29be, 0x41f7, | 304 | 0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6, 0x31e7, 0x20f8, 0x20f9, 0x20fa, 0x20fb, 0x257c, 0x257d, 0x29be, 0x41f7, |
327 | 305 | ||
328 | // previous 1s = 3: | 306 | /* previous 1s = 3: */ |
329 | 0x0000, 0x0001, 0x0002, 0x2003, 0x0004, 0x0005, 0x0006, 0x200b, 0x0008, 0x0009, 0x000a, 0x2013, 0x000c, 0x000d, 0x000e, 0x201b, | 307 | 0x0000, 0x0001, 0x0002, 0x2003, 0x0004, 0x0005, 0x0006, 0x200b, 0x0008, 0x0009, 0x000a, 0x2013, 0x000c, 0x000d, 0x000e, 0x201b, |
330 | 0x0010, 0x0011, 0x0012, 0x2023, 0x0014, 0x0015, 0x0016, 0x202b, 0x0018, 0x0019, 0x001a, 0x2033, 0x001c, 0x001d, 0x001e, 0x203b, | 308 | 0x0010, 0x0011, 0x0012, 0x2023, 0x0014, 0x0015, 0x0016, 0x202b, 0x0018, 0x0019, 0x001a, 0x2033, 0x001c, 0x001d, 0x001e, 0x203b, |
331 | 0x0020, 0x0021, 0x0022, 0x2043, 0x0024, 0x0025, 0x0026, 0x204b, 0x0028, 0x0029, 0x002a, 0x2053, 0x002c, 0x002d, 0x002e, 0x205b, | 309 | 0x0020, 0x0021, 0x0022, 0x2043, 0x0024, 0x0025, 0x0026, 0x204b, 0x0028, 0x0029, 0x002a, 0x2053, 0x002c, 0x002d, 0x002e, 0x205b, |
@@ -343,7 +321,7 @@ static const u16 stufftab[5 * 256] = { | |||
343 | 0x0ce0, 0x0ce1, 0x0ce2, 0x2dc3, 0x0ce4, 0x0ce5, 0x0ce6, 0x2dcb, 0x0ce8, 0x0ce9, 0x0cea, 0x2dd3, 0x0cec, 0x0ced, 0x0cee, 0x2ddb, | 321 | 0x0ce0, 0x0ce1, 0x0ce2, 0x2dc3, 0x0ce4, 0x0ce5, 0x0ce6, 0x2dcb, 0x0ce8, 0x0ce9, 0x0cea, 0x2dd3, 0x0cec, 0x0ced, 0x0cee, 0x2ddb, |
344 | 0x10f0, 0x10f1, 0x10f2, 0x31e3, 0x10f4, 0x10f5, 0x10f6, 0x31eb, 0x20f8, 0x20f9, 0x20fa, 0x41f3, 0x257c, 0x257d, 0x29be, 0x46fb, | 322 | 0x10f0, 0x10f1, 0x10f2, 0x31e3, 0x10f4, 0x10f5, 0x10f6, 0x31eb, 0x20f8, 0x20f9, 0x20fa, 0x41f3, 0x257c, 0x257d, 0x29be, 0x46fb, |
345 | 323 | ||
346 | // previous 1s = 4: | 324 | /* previous 1s = 4: */ |
347 | 0x0000, 0x2001, 0x0002, 0x2005, 0x0004, 0x2009, 0x0006, 0x200d, 0x0008, 0x2011, 0x000a, 0x2015, 0x000c, 0x2019, 0x000e, 0x201d, | 325 | 0x0000, 0x2001, 0x0002, 0x2005, 0x0004, 0x2009, 0x0006, 0x200d, 0x0008, 0x2011, 0x000a, 0x2015, 0x000c, 0x2019, 0x000e, 0x201d, |
348 | 0x0010, 0x2021, 0x0012, 0x2025, 0x0014, 0x2029, 0x0016, 0x202d, 0x0018, 0x2031, 0x001a, 0x2035, 0x001c, 0x2039, 0x001e, 0x203d, | 326 | 0x0010, 0x2021, 0x0012, 0x2025, 0x0014, 0x2029, 0x0016, 0x202d, 0x0018, 0x2031, 0x001a, 0x2035, 0x001c, 0x2039, 0x001e, 0x203d, |
349 | 0x0020, 0x2041, 0x0022, 0x2045, 0x0024, 0x2049, 0x0026, 0x204d, 0x0028, 0x2051, 0x002a, 0x2055, 0x002c, 0x2059, 0x002e, 0x205d, | 327 | 0x0020, 0x2041, 0x0022, 0x2045, 0x0024, 0x2049, 0x0026, 0x204d, 0x0028, 0x2051, 0x002a, 0x2055, 0x002c, 0x2059, 0x002e, 0x205d, |
@@ -367,7 +345,8 @@ static const u16 stufftab[5 * 256] = { | |||
367 | * parameters: | 345 | * parameters: |
368 | * cin input byte | 346 | * cin input byte |
369 | * ones number of trailing '1' bits in result before this step | 347 | * ones number of trailing '1' bits in result before this step |
370 | * iwb pointer to output buffer structure (write semaphore must be held) | 348 | * iwb pointer to output buffer structure |
349 | * (write semaphore must be held) | ||
371 | * return value: | 350 | * return value: |
372 | * number of trailing '1' bits in result after this step | 351 | * number of trailing '1' bits in result after this step |
373 | */ | 352 | */ |
@@ -408,7 +387,8 @@ static inline int hdlc_bitstuff_byte(struct isowbuf_t *iwb, unsigned char cin, | |||
408 | * parameters: | 387 | * parameters: |
409 | * in input buffer | 388 | * in input buffer |
410 | * count number of bytes in input buffer | 389 | * count number of bytes in input buffer |
411 | * iwb pointer to output buffer structure (write semaphore must be held) | 390 | * iwb pointer to output buffer structure |
391 | * (write semaphore must be held) | ||
412 | * return value: | 392 | * return value: |
413 | * position of end of packet in output buffer on success, | 393 | * position of end of packet in output buffer on success, |
414 | * -EAGAIN if write semaphore busy or buffer full | 394 | * -EAGAIN if write semaphore busy or buffer full |
@@ -440,7 +420,8 @@ static inline int hdlc_buildframe(struct isowbuf_t *iwb, | |||
440 | fcs = crc_ccitt_byte(fcs, c); | 420 | fcs = crc_ccitt_byte(fcs, c); |
441 | } | 421 | } |
442 | 422 | ||
443 | /* bitstuff and append FCS (complemented, least significant byte first) */ | 423 | /* bitstuff and append FCS |
424 | * (complemented, least significant byte first) */ | ||
444 | fcs ^= 0xffff; | 425 | fcs ^= 0xffff; |
445 | ones = hdlc_bitstuff_byte(iwb, fcs & 0x00ff, ones); | 426 | ones = hdlc_bitstuff_byte(iwb, fcs & 0x00ff, ones); |
446 | ones = hdlc_bitstuff_byte(iwb, (fcs >> 8) & 0x00ff, ones); | 427 | ones = hdlc_bitstuff_byte(iwb, (fcs >> 8) & 0x00ff, ones); |
@@ -459,7 +440,8 @@ static inline int hdlc_buildframe(struct isowbuf_t *iwb, | |||
459 | * parameters: | 440 | * parameters: |
460 | * in input buffer | 441 | * in input buffer |
461 | * count number of bytes in input buffer | 442 | * count number of bytes in input buffer |
462 | * iwb pointer to output buffer structure (write semaphore must be held) | 443 | * iwb pointer to output buffer structure |
444 | * (write semaphore must be held) | ||
463 | * return value: | 445 | * return value: |
464 | * position of end of packet in output buffer on success, | 446 | * position of end of packet in output buffer on success, |
465 | * -EAGAIN if write semaphore busy or buffer full | 447 | * -EAGAIN if write semaphore busy or buffer full |
@@ -500,7 +482,7 @@ int gigaset_isoc_buildframe(struct bc_state *bcs, unsigned char *in, int len) | |||
500 | int result; | 482 | int result; |
501 | 483 | ||
502 | switch (bcs->proto2) { | 484 | switch (bcs->proto2) { |
503 | case ISDN_PROTO_L2_HDLC: | 485 | case L2_HDLC: |
504 | result = hdlc_buildframe(bcs->hw.bas->isooutbuf, in, len); | 486 | result = hdlc_buildframe(bcs->hw.bas->isooutbuf, in, len); |
505 | gig_dbg(DEBUG_ISO, "%s: %d bytes HDLC -> %d", | 487 | gig_dbg(DEBUG_ISO, "%s: %d bytes HDLC -> %d", |
506 | __func__, len, result); | 488 | __func__, len, result); |
@@ -542,8 +524,9 @@ static inline void hdlc_flush(struct bc_state *bcs) | |||
542 | if (likely(bcs->skb != NULL)) | 524 | if (likely(bcs->skb != NULL)) |
543 | skb_trim(bcs->skb, 0); | 525 | skb_trim(bcs->skb, 0); |
544 | else if (!bcs->ignore) { | 526 | else if (!bcs->ignore) { |
545 | if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL) | 527 | bcs->skb = dev_alloc_skb(SBUFSIZE + bcs->cs->hw_hdr_len); |
546 | skb_reserve(bcs->skb, HW_HDR_LEN); | 528 | if (bcs->skb) |
529 | skb_reserve(bcs->skb, bcs->cs->hw_hdr_len); | ||
547 | else | 530 | else |
548 | dev_err(bcs->cs->dev, "could not allocate skb\n"); | 531 | dev_err(bcs->cs->dev, "could not allocate skb\n"); |
549 | } | 532 | } |
@@ -557,43 +540,46 @@ static inline void hdlc_flush(struct bc_state *bcs) | |||
557 | */ | 540 | */ |
558 | static inline void hdlc_done(struct bc_state *bcs) | 541 | static inline void hdlc_done(struct bc_state *bcs) |
559 | { | 542 | { |
543 | struct cardstate *cs = bcs->cs; | ||
560 | struct sk_buff *procskb; | 544 | struct sk_buff *procskb; |
545 | unsigned int len; | ||
561 | 546 | ||
562 | if (unlikely(bcs->ignore)) { | 547 | if (unlikely(bcs->ignore)) { |
563 | bcs->ignore--; | 548 | bcs->ignore--; |
564 | hdlc_flush(bcs); | 549 | hdlc_flush(bcs); |
565 | return; | 550 | return; |
566 | } | 551 | } |
567 | 552 | procskb = bcs->skb; | |
568 | if ((procskb = bcs->skb) == NULL) { | 553 | if (procskb == NULL) { |
569 | /* previous error */ | 554 | /* previous error */ |
570 | gig_dbg(DEBUG_ISO, "%s: skb=NULL", __func__); | 555 | gig_dbg(DEBUG_ISO, "%s: skb=NULL", __func__); |
571 | gigaset_rcv_error(NULL, bcs->cs, bcs); | 556 | gigaset_isdn_rcv_err(bcs); |
572 | } else if (procskb->len < 2) { | 557 | } else if (procskb->len < 2) { |
573 | dev_notice(bcs->cs->dev, "received short frame (%d octets)\n", | 558 | dev_notice(cs->dev, "received short frame (%d octets)\n", |
574 | procskb->len); | 559 | procskb->len); |
575 | bcs->hw.bas->runts++; | 560 | bcs->hw.bas->runts++; |
576 | gigaset_rcv_error(procskb, bcs->cs, bcs); | 561 | dev_kfree_skb_any(procskb); |
562 | gigaset_isdn_rcv_err(bcs); | ||
577 | } else if (bcs->fcs != PPP_GOODFCS) { | 563 | } else if (bcs->fcs != PPP_GOODFCS) { |
578 | dev_notice(bcs->cs->dev, "frame check error (0x%04x)\n", | 564 | dev_notice(cs->dev, "frame check error (0x%04x)\n", bcs->fcs); |
579 | bcs->fcs); | ||
580 | bcs->hw.bas->fcserrs++; | 565 | bcs->hw.bas->fcserrs++; |
581 | gigaset_rcv_error(procskb, bcs->cs, bcs); | 566 | dev_kfree_skb_any(procskb); |
567 | gigaset_isdn_rcv_err(bcs); | ||
582 | } else { | 568 | } else { |
583 | procskb->len -= 2; /* subtract FCS */ | 569 | len = procskb->len; |
584 | procskb->tail -= 2; | 570 | __skb_trim(procskb, len -= 2); /* subtract FCS */ |
585 | gig_dbg(DEBUG_ISO, "%s: good frame (%d octets)", | 571 | gig_dbg(DEBUG_ISO, "%s: good frame (%d octets)", __func__, len); |
586 | __func__, procskb->len); | ||
587 | dump_bytes(DEBUG_STREAM_DUMP, | 572 | dump_bytes(DEBUG_STREAM_DUMP, |
588 | "rcv data", procskb->data, procskb->len); | 573 | "rcv data", procskb->data, len); |
589 | bcs->hw.bas->goodbytes += procskb->len; | 574 | bcs->hw.bas->goodbytes += len; |
590 | gigaset_rcv_skb(procskb, bcs->cs, bcs); | 575 | gigaset_skb_rcvd(bcs, procskb); |
591 | } | 576 | } |
592 | 577 | ||
593 | if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL) | 578 | bcs->skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len); |
594 | skb_reserve(bcs->skb, HW_HDR_LEN); | 579 | if (bcs->skb) |
580 | skb_reserve(bcs->skb, cs->hw_hdr_len); | ||
595 | else | 581 | else |
596 | dev_err(bcs->cs->dev, "could not allocate skb\n"); | 582 | dev_err(cs->dev, "could not allocate skb\n"); |
597 | bcs->fcs = PPP_INITFCS; | 583 | bcs->fcs = PPP_INITFCS; |
598 | } | 584 | } |
599 | 585 | ||
@@ -610,12 +596,8 @@ static inline void hdlc_frag(struct bc_state *bcs, unsigned inbits) | |||
610 | 596 | ||
611 | dev_notice(bcs->cs->dev, "received partial byte (%d bits)\n", inbits); | 597 | dev_notice(bcs->cs->dev, "received partial byte (%d bits)\n", inbits); |
612 | bcs->hw.bas->alignerrs++; | 598 | bcs->hw.bas->alignerrs++; |
613 | gigaset_rcv_error(bcs->skb, bcs->cs, bcs); | 599 | gigaset_isdn_rcv_err(bcs); |
614 | 600 | __skb_trim(bcs->skb, 0); | |
615 | if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL) | ||
616 | skb_reserve(bcs->skb, HW_HDR_LEN); | ||
617 | else | ||
618 | dev_err(bcs->cs->dev, "could not allocate skb\n"); | ||
619 | bcs->fcs = PPP_INITFCS; | 601 | bcs->fcs = PPP_INITFCS; |
620 | } | 602 | } |
621 | 603 | ||
@@ -646,10 +628,10 @@ static const unsigned char bitcounts[256] = { | |||
646 | }; | 628 | }; |
647 | 629 | ||
648 | /* hdlc_unpack | 630 | /* hdlc_unpack |
649 | * perform HDLC frame processing (bit unstuffing, flag detection, FCS calculation) | 631 | * perform HDLC frame processing (bit unstuffing, flag detection, FCS |
650 | * on a sequence of received data bytes (8 bits each, LSB first) | 632 | * calculation) on a sequence of received data bytes (8 bits each, LSB first) |
651 | * pass on successfully received, complete frames as SKBs via gigaset_rcv_skb | 633 | * pass on successfully received, complete frames as SKBs via gigaset_skb_rcvd |
652 | * notify of errors via gigaset_rcv_error | 634 | * notify of errors via gigaset_isdn_rcv_err |
653 | * tally frames, errors etc. in BC structure counters | 635 | * tally frames, errors etc. in BC structure counters |
654 | * parameters: | 636 | * parameters: |
655 | * src received data | 637 | * src received data |
@@ -665,9 +647,12 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count, | |||
665 | 647 | ||
666 | /* load previous state: | 648 | /* load previous state: |
667 | * inputstate = set of flag bits: | 649 | * inputstate = set of flag bits: |
668 | * - INS_flag_hunt: no complete opening flag received since connection setup or last abort | 650 | * - INS_flag_hunt: no complete opening flag received since connection |
669 | * - INS_have_data: at least one complete data byte received since last flag | 651 | * setup or last abort |
670 | * seqlen = number of consecutive '1' bits in last 7 input stream bits (0..7) | 652 | * - INS_have_data: at least one complete data byte received since last |
653 | * flag | ||
654 | * seqlen = number of consecutive '1' bits in last 7 input stream bits | ||
655 | * (0..7) | ||
671 | * inbyte = accumulated partial data byte (if !INS_flag_hunt) | 656 | * inbyte = accumulated partial data byte (if !INS_flag_hunt) |
672 | * inbits = number of valid bits in inbyte, starting at LSB (0..6) | 657 | * inbits = number of valid bits in inbyte, starting at LSB (0..6) |
673 | */ | 658 | */ |
@@ -701,9 +686,11 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count, | |||
701 | inbyte = c >> (lead1 + 1); | 686 | inbyte = c >> (lead1 + 1); |
702 | inbits = 7 - lead1; | 687 | inbits = 7 - lead1; |
703 | if (trail1 >= 8) { | 688 | if (trail1 >= 8) { |
704 | /* interior stuffing: omitting the MSB handles most cases */ | 689 | /* interior stuffing: |
690 | * omitting the MSB handles most cases, | ||
691 | * correct the incorrectly handled | ||
692 | * cases individually */ | ||
705 | inbits--; | 693 | inbits--; |
706 | /* correct the incorrectly handled cases individually */ | ||
707 | switch (c) { | 694 | switch (c) { |
708 | case 0xbe: | 695 | case 0xbe: |
709 | inbyte = 0x3f; | 696 | inbyte = 0x3f; |
@@ -729,13 +716,14 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count, | |||
729 | hdlc_flush(bcs); | 716 | hdlc_flush(bcs); |
730 | inputstate |= INS_flag_hunt; | 717 | inputstate |= INS_flag_hunt; |
731 | } else if (seqlen == 6) { | 718 | } else if (seqlen == 6) { |
732 | /* closing flag, including (6 - lead1) '1's and one '0' from inbits */ | 719 | /* closing flag, including (6 - lead1) '1's |
720 | * and one '0' from inbits */ | ||
733 | if (inbits > 7 - lead1) { | 721 | if (inbits > 7 - lead1) { |
734 | hdlc_frag(bcs, inbits + lead1 - 7); | 722 | hdlc_frag(bcs, inbits + lead1 - 7); |
735 | inputstate &= ~INS_have_data; | 723 | inputstate &= ~INS_have_data; |
736 | } else { | 724 | } else { |
737 | if (inbits < 7 - lead1) | 725 | if (inbits < 7 - lead1) |
738 | ubc->stolen0s ++; | 726 | ubc->stolen0s++; |
739 | if (inputstate & INS_have_data) { | 727 | if (inputstate & INS_have_data) { |
740 | hdlc_done(bcs); | 728 | hdlc_done(bcs); |
741 | inputstate &= ~INS_have_data; | 729 | inputstate &= ~INS_have_data; |
@@ -744,7 +732,7 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count, | |||
744 | 732 | ||
745 | if (c == PPP_FLAG) { | 733 | if (c == PPP_FLAG) { |
746 | /* complete flag, LSB overlaps preceding flag */ | 734 | /* complete flag, LSB overlaps preceding flag */ |
747 | ubc->shared0s ++; | 735 | ubc->shared0s++; |
748 | inbits = 0; | 736 | inbits = 0; |
749 | inbyte = 0; | 737 | inbyte = 0; |
750 | } else if (trail1 != 7) { | 738 | } else if (trail1 != 7) { |
@@ -752,9 +740,11 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count, | |||
752 | inbyte = c >> (lead1 + 1); | 740 | inbyte = c >> (lead1 + 1); |
753 | inbits = 7 - lead1; | 741 | inbits = 7 - lead1; |
754 | if (trail1 >= 8) { | 742 | if (trail1 >= 8) { |
755 | /* interior stuffing: omitting the MSB handles most cases */ | 743 | /* interior stuffing: |
744 | * omitting the MSB handles most cases, | ||
745 | * correct the incorrectly handled | ||
746 | * cases individually */ | ||
756 | inbits--; | 747 | inbits--; |
757 | /* correct the incorrectly handled cases individually */ | ||
758 | switch (c) { | 748 | switch (c) { |
759 | case 0xbe: | 749 | case 0xbe: |
760 | inbyte = 0x3f; | 750 | inbyte = 0x3f; |
@@ -762,7 +752,8 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count, | |||
762 | } | 752 | } |
763 | } | 753 | } |
764 | } else { | 754 | } else { |
765 | /* abort sequence follows, skb already empty anyway */ | 755 | /* abort sequence follows, |
756 | * skb already empty anyway */ | ||
766 | ubc->aborts++; | 757 | ubc->aborts++; |
767 | inputstate |= INS_flag_hunt; | 758 | inputstate |= INS_flag_hunt; |
768 | } | 759 | } |
@@ -787,14 +778,17 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count, | |||
787 | } else { | 778 | } else { |
788 | /* stuffed data */ | 779 | /* stuffed data */ |
789 | if (trail1 < 7) { /* => seqlen == 5 */ | 780 | if (trail1 < 7) { /* => seqlen == 5 */ |
790 | /* stuff bit at position lead1, no interior stuffing */ | 781 | /* stuff bit at position lead1, |
782 | * no interior stuffing */ | ||
791 | unsigned char mask = (1 << lead1) - 1; | 783 | unsigned char mask = (1 << lead1) - 1; |
792 | c = (c & mask) | ((c & ~mask) >> 1); | 784 | c = (c & mask) | ((c & ~mask) >> 1); |
793 | inbyte |= c << inbits; | 785 | inbyte |= c << inbits; |
794 | inbits += 7; | 786 | inbits += 7; |
795 | } else if (seqlen < 5) { /* trail1 >= 8 */ | 787 | } else if (seqlen < 5) { /* trail1 >= 8 */ |
796 | /* interior stuffing: omitting the MSB handles most cases */ | 788 | /* interior stuffing: |
797 | /* correct the incorrectly handled cases individually */ | 789 | * omitting the MSB handles most cases, |
790 | * correct the incorrectly handled | ||
791 | * cases individually */ | ||
798 | switch (c) { | 792 | switch (c) { |
799 | case 0xbe: | 793 | case 0xbe: |
800 | c = 0x7e; | 794 | c = 0x7e; |
@@ -804,8 +798,9 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count, | |||
804 | inbits += 7; | 798 | inbits += 7; |
805 | } else { /* seqlen == 5 && trail1 >= 8 */ | 799 | } else { /* seqlen == 5 && trail1 >= 8 */ |
806 | 800 | ||
807 | /* stuff bit at lead1 *and* interior stuffing */ | 801 | /* stuff bit at lead1 *and* interior |
808 | switch (c) { /* unstuff individually */ | 802 | * stuffing -- unstuff individually */ |
803 | switch (c) { | ||
809 | case 0x7d: | 804 | case 0x7d: |
810 | c = 0x3f; | 805 | c = 0x3f; |
811 | break; | 806 | break; |
@@ -841,7 +836,7 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count, | |||
841 | } | 836 | } |
842 | 837 | ||
843 | /* trans_receive | 838 | /* trans_receive |
844 | * pass on received USB frame transparently as SKB via gigaset_rcv_skb | 839 | * pass on received USB frame transparently as SKB via gigaset_skb_rcvd |
845 | * invert bytes | 840 | * invert bytes |
846 | * tally frames, errors etc. in BC structure counters | 841 | * tally frames, errors etc. in BC structure counters |
847 | * parameters: | 842 | * parameters: |
@@ -852,6 +847,7 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count, | |||
852 | static inline void trans_receive(unsigned char *src, unsigned count, | 847 | static inline void trans_receive(unsigned char *src, unsigned count, |
853 | struct bc_state *bcs) | 848 | struct bc_state *bcs) |
854 | { | 849 | { |
850 | struct cardstate *cs = bcs->cs; | ||
855 | struct sk_buff *skb; | 851 | struct sk_buff *skb; |
856 | int dobytes; | 852 | int dobytes; |
857 | unsigned char *dst; | 853 | unsigned char *dst; |
@@ -861,13 +857,14 @@ static inline void trans_receive(unsigned char *src, unsigned count, | |||
861 | hdlc_flush(bcs); | 857 | hdlc_flush(bcs); |
862 | return; | 858 | return; |
863 | } | 859 | } |
864 | if (unlikely((skb = bcs->skb) == NULL)) { | 860 | skb = bcs->skb; |
865 | bcs->skb = skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN); | 861 | if (unlikely(skb == NULL)) { |
862 | bcs->skb = skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len); | ||
866 | if (!skb) { | 863 | if (!skb) { |
867 | dev_err(bcs->cs->dev, "could not allocate skb\n"); | 864 | dev_err(cs->dev, "could not allocate skb\n"); |
868 | return; | 865 | return; |
869 | } | 866 | } |
870 | skb_reserve(skb, HW_HDR_LEN); | 867 | skb_reserve(skb, cs->hw_hdr_len); |
871 | } | 868 | } |
872 | bcs->hw.bas->goodbytes += skb->len; | 869 | bcs->hw.bas->goodbytes += skb->len; |
873 | dobytes = TRANSBUFSIZE - skb->len; | 870 | dobytes = TRANSBUFSIZE - skb->len; |
@@ -881,23 +878,24 @@ static inline void trans_receive(unsigned char *src, unsigned count, | |||
881 | if (dobytes == 0) { | 878 | if (dobytes == 0) { |
882 | dump_bytes(DEBUG_STREAM_DUMP, | 879 | dump_bytes(DEBUG_STREAM_DUMP, |
883 | "rcv data", skb->data, skb->len); | 880 | "rcv data", skb->data, skb->len); |
884 | gigaset_rcv_skb(skb, bcs->cs, bcs); | 881 | gigaset_skb_rcvd(bcs, skb); |
885 | bcs->skb = skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN); | 882 | bcs->skb = skb = |
883 | dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len); | ||
886 | if (!skb) { | 884 | if (!skb) { |
887 | dev_err(bcs->cs->dev, | 885 | dev_err(cs->dev, "could not allocate skb\n"); |
888 | "could not allocate skb\n"); | ||
889 | return; | 886 | return; |
890 | } | 887 | } |
891 | skb_reserve(bcs->skb, HW_HDR_LEN); | 888 | skb_reserve(skb, cs->hw_hdr_len); |
892 | dobytes = TRANSBUFSIZE; | 889 | dobytes = TRANSBUFSIZE; |
893 | } | 890 | } |
894 | } | 891 | } |
895 | } | 892 | } |
896 | 893 | ||
897 | void gigaset_isoc_receive(unsigned char *src, unsigned count, struct bc_state *bcs) | 894 | void gigaset_isoc_receive(unsigned char *src, unsigned count, |
895 | struct bc_state *bcs) | ||
898 | { | 896 | { |
899 | switch (bcs->proto2) { | 897 | switch (bcs->proto2) { |
900 | case ISDN_PROTO_L2_HDLC: | 898 | case L2_HDLC: |
901 | hdlc_unpack(src, count, bcs); | 899 | hdlc_unpack(src, count, bcs); |
902 | break; | 900 | break; |
903 | default: /* assume transparent */ | 901 | default: /* assume transparent */ |
@@ -907,29 +905,49 @@ void gigaset_isoc_receive(unsigned char *src, unsigned count, struct bc_state *b | |||
907 | 905 | ||
908 | /* == data input =========================================================== */ | 906 | /* == data input =========================================================== */ |
909 | 907 | ||
908 | /* process a block of received bytes in command mode (mstate != MS_LOCKED) | ||
909 | * Append received bytes to the command response buffer and forward them | ||
910 | * line by line to the response handler. | ||
911 | * Note: Received lines may be terminated by CR, LF, or CR LF, which will be | ||
912 | * removed before passing the line to the response handler. | ||
913 | */ | ||
910 | static void cmd_loop(unsigned char *src, int numbytes, struct inbuf_t *inbuf) | 914 | static void cmd_loop(unsigned char *src, int numbytes, struct inbuf_t *inbuf) |
911 | { | 915 | { |
912 | struct cardstate *cs = inbuf->cs; | 916 | struct cardstate *cs = inbuf->cs; |
913 | unsigned cbytes = cs->cbytes; | 917 | unsigned cbytes = cs->cbytes; |
918 | unsigned char c; | ||
914 | 919 | ||
915 | while (numbytes--) { | 920 | while (numbytes--) { |
916 | /* copy next character, check for end of line */ | 921 | c = *src++; |
917 | switch (cs->respdata[cbytes] = *src++) { | 922 | switch (c) { |
918 | case '\r': | ||
919 | case '\n': | 923 | case '\n': |
920 | /* end of line */ | 924 | if (cbytes == 0 && cs->respdata[0] == '\r') { |
921 | gig_dbg(DEBUG_TRANSCMD, "%s: End of Command (%d Bytes)", | 925 | /* collapse LF with preceding CR */ |
922 | __func__, cbytes); | 926 | cs->respdata[0] = 0; |
923 | if (cbytes >= MAX_RESP_SIZE - 1) | 927 | break; |
924 | dev_warn(cs->dev, "response too large\n"); | 928 | } |
929 | /* --v-- fall through --v-- */ | ||
930 | case '\r': | ||
931 | /* end of message line, pass to response handler */ | ||
932 | if (cbytes >= MAX_RESP_SIZE) { | ||
933 | dev_warn(cs->dev, "response too large (%d)\n", | ||
934 | cbytes); | ||
935 | cbytes = MAX_RESP_SIZE; | ||
936 | } | ||
925 | cs->cbytes = cbytes; | 937 | cs->cbytes = cbytes; |
938 | gigaset_dbg_buffer(DEBUG_TRANSCMD, "received response", | ||
939 | cbytes, cs->respdata); | ||
926 | gigaset_handle_modem_response(cs); | 940 | gigaset_handle_modem_response(cs); |
927 | cbytes = 0; | 941 | cbytes = 0; |
942 | |||
943 | /* store EOL byte for CRLF collapsing */ | ||
944 | cs->respdata[0] = c; | ||
928 | break; | 945 | break; |
929 | default: | 946 | default: |
930 | /* advance in line buffer, checking for overflow */ | 947 | /* append to line buffer if possible */ |
931 | if (cbytes < MAX_RESP_SIZE - 1) | 948 | if (cbytes < MAX_RESP_SIZE) |
932 | cbytes++; | 949 | cs->respdata[cbytes] = c; |
950 | cbytes++; | ||
933 | } | 951 | } |
934 | } | 952 | } |
935 | 953 | ||
@@ -960,8 +978,6 @@ void gigaset_isoc_input(struct inbuf_t *inbuf) | |||
960 | numbytes, src); | 978 | numbytes, src); |
961 | gigaset_if_receive(inbuf->cs, src, numbytes); | 979 | gigaset_if_receive(inbuf->cs, src, numbytes); |
962 | } else { | 980 | } else { |
963 | gigaset_dbg_buffer(DEBUG_CMD, "received response", | ||
964 | numbytes, src); | ||
965 | cmd_loop(src, numbytes, inbuf); | 981 | cmd_loop(src, numbytes, inbuf); |
966 | } | 982 | } |
967 | 983 | ||
@@ -981,8 +997,10 @@ void gigaset_isoc_input(struct inbuf_t *inbuf) | |||
981 | * @bcs: B channel descriptor structure. | 997 | * @bcs: B channel descriptor structure. |
982 | * @skb: data to send. | 998 | * @skb: data to send. |
983 | * | 999 | * |
984 | * Called by i4l.c to queue an skb for sending, and start transmission if | 1000 | * Called by LL to queue an skb for sending, and start transmission if |
985 | * necessary. | 1001 | * necessary. |
1002 | * Once the payload data has been transmitted completely, gigaset_skb_sent() | ||
1003 | * will be called with the skb's link layer header preserved. | ||
986 | * | 1004 | * |
987 | * Return value: | 1005 | * Return value: |
988 | * number of bytes accepted for sending (skb->len) if ok, | 1006 | * number of bytes accepted for sending (skb->len) if ok, |
diff --git a/drivers/isdn/gigaset/proc.c b/drivers/isdn/gigaset/proc.c index 9715aad9c3f0..b943efbff44d 100644 --- a/drivers/isdn/gigaset/proc.c +++ b/drivers/isdn/gigaset/proc.c | |||
@@ -14,7 +14,6 @@ | |||
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include "gigaset.h" | 16 | #include "gigaset.h" |
17 | #include <linux/ctype.h> | ||
18 | 17 | ||
19 | static ssize_t show_cidmode(struct device *dev, | 18 | static ssize_t show_cidmode(struct device *dev, |
20 | struct device_attribute *attr, char *buf) | 19 | struct device_attribute *attr, char *buf) |
@@ -39,7 +38,7 @@ static ssize_t set_cidmode(struct device *dev, struct device_attribute *attr, | |||
39 | return -EINVAL; | 38 | return -EINVAL; |
40 | 39 | ||
41 | if (mutex_lock_interruptible(&cs->mutex)) | 40 | if (mutex_lock_interruptible(&cs->mutex)) |
42 | return -ERESTARTSYS; // FIXME -EINTR? | 41 | return -ERESTARTSYS; |
43 | 42 | ||
44 | cs->waiting = 1; | 43 | cs->waiting = 1; |
45 | if (!gigaset_add_event(cs, &cs->at_state, EV_PROC_CIDMODE, | 44 | if (!gigaset_add_event(cs, &cs->at_state, EV_PROC_CIDMODE, |
@@ -48,8 +47,6 @@ static ssize_t set_cidmode(struct device *dev, struct device_attribute *attr, | |||
48 | mutex_unlock(&cs->mutex); | 47 | mutex_unlock(&cs->mutex); |
49 | return -ENOMEM; | 48 | return -ENOMEM; |
50 | } | 49 | } |
51 | |||
52 | gig_dbg(DEBUG_CMD, "scheduling PROC_CIDMODE"); | ||
53 | gigaset_schedule_event(cs); | 50 | gigaset_schedule_event(cs); |
54 | 51 | ||
55 | wait_event(cs->waitqueue, !cs->waiting); | 52 | wait_event(cs->waitqueue, !cs->waiting); |
diff --git a/drivers/isdn/gigaset/ser-gigaset.c b/drivers/isdn/gigaset/ser-gigaset.c index 3071a52467ed..e96c0586886c 100644 --- a/drivers/isdn/gigaset/ser-gigaset.c +++ b/drivers/isdn/gigaset/ser-gigaset.c | |||
@@ -11,11 +11,9 @@ | |||
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include "gigaset.h" | 13 | #include "gigaset.h" |
14 | |||
15 | #include <linux/module.h> | 14 | #include <linux/module.h> |
16 | #include <linux/moduleparam.h> | 15 | #include <linux/moduleparam.h> |
17 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
18 | #include <linux/tty.h> | ||
19 | #include <linux/completion.h> | 17 | #include <linux/completion.h> |
20 | 18 | ||
21 | /* Version Information */ | 19 | /* Version Information */ |
@@ -164,9 +162,15 @@ static void gigaset_modem_fill(unsigned long data) | |||
164 | { | 162 | { |
165 | struct cardstate *cs = (struct cardstate *) data; | 163 | struct cardstate *cs = (struct cardstate *) data; |
166 | struct bc_state *bcs; | 164 | struct bc_state *bcs; |
165 | struct sk_buff *nextskb; | ||
167 | int sent = 0; | 166 | int sent = 0; |
168 | 167 | ||
169 | if (!cs || !(bcs = cs->bcs)) { | 168 | if (!cs) { |
169 | gig_dbg(DEBUG_OUTPUT, "%s: no cardstate", __func__); | ||
170 | return; | ||
171 | } | ||
172 | bcs = cs->bcs; | ||
173 | if (!bcs) { | ||
170 | gig_dbg(DEBUG_OUTPUT, "%s: no cardstate", __func__); | 174 | gig_dbg(DEBUG_OUTPUT, "%s: no cardstate", __func__); |
171 | return; | 175 | return; |
172 | } | 176 | } |
@@ -179,9 +183,11 @@ static void gigaset_modem_fill(unsigned long data) | |||
179 | return; | 183 | return; |
180 | 184 | ||
181 | /* no command to send; get skb */ | 185 | /* no command to send; get skb */ |
182 | if (!(bcs->tx_skb = skb_dequeue(&bcs->squeue))) | 186 | nextskb = skb_dequeue(&bcs->squeue); |
187 | if (!nextskb) | ||
183 | /* no skb either, nothing to do */ | 188 | /* no skb either, nothing to do */ |
184 | return; | 189 | return; |
190 | bcs->tx_skb = nextskb; | ||
185 | 191 | ||
186 | gig_dbg(DEBUG_INTR, "Dequeued skb (Adr: %lx)", | 192 | gig_dbg(DEBUG_INTR, "Dequeued skb (Adr: %lx)", |
187 | (unsigned long) bcs->tx_skb); | 193 | (unsigned long) bcs->tx_skb); |
@@ -236,19 +242,20 @@ static void flush_send_queue(struct cardstate *cs) | |||
236 | * number of bytes queued, or error code < 0 | 242 | * number of bytes queued, or error code < 0 |
237 | */ | 243 | */ |
238 | static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf, | 244 | static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf, |
239 | int len, struct tasklet_struct *wake_tasklet) | 245 | int len, struct tasklet_struct *wake_tasklet) |
240 | { | 246 | { |
241 | struct cmdbuf_t *cb; | 247 | struct cmdbuf_t *cb; |
242 | unsigned long flags; | 248 | unsigned long flags; |
243 | 249 | ||
244 | gigaset_dbg_buffer(cs->mstate != MS_LOCKED ? | 250 | gigaset_dbg_buffer(cs->mstate != MS_LOCKED ? |
245 | DEBUG_TRANSCMD : DEBUG_LOCKCMD, | 251 | DEBUG_TRANSCMD : DEBUG_LOCKCMD, |
246 | "CMD Transmit", len, buf); | 252 | "CMD Transmit", len, buf); |
247 | 253 | ||
248 | if (len <= 0) | 254 | if (len <= 0) |
249 | return 0; | 255 | return 0; |
250 | 256 | ||
251 | if (!(cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC))) { | 257 | cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC); |
258 | if (!cb) { | ||
252 | dev_err(cs->dev, "%s: out of memory!\n", __func__); | 259 | dev_err(cs->dev, "%s: out of memory!\n", __func__); |
253 | return -ENOMEM; | 260 | return -ENOMEM; |
254 | } | 261 | } |
@@ -392,7 +399,6 @@ static void gigaset_device_release(struct device *dev) | |||
392 | struct platform_device *pdev = to_platform_device(dev); | 399 | struct platform_device *pdev = to_platform_device(dev); |
393 | 400 | ||
394 | /* adapted from platform_device_release() in drivers/base/platform.c */ | 401 | /* adapted from platform_device_release() in drivers/base/platform.c */ |
395 | //FIXME is this actually necessary? | ||
396 | kfree(dev->platform_data); | 402 | kfree(dev->platform_data); |
397 | kfree(pdev->resource); | 403 | kfree(pdev->resource); |
398 | } | 404 | } |
@@ -404,16 +410,20 @@ static void gigaset_device_release(struct device *dev) | |||
404 | static int gigaset_initcshw(struct cardstate *cs) | 410 | static int gigaset_initcshw(struct cardstate *cs) |
405 | { | 411 | { |
406 | int rc; | 412 | int rc; |
413 | struct ser_cardstate *scs; | ||
407 | 414 | ||
408 | if (!(cs->hw.ser = kzalloc(sizeof(struct ser_cardstate), GFP_KERNEL))) { | 415 | scs = kzalloc(sizeof(struct ser_cardstate), GFP_KERNEL); |
416 | if (!scs) { | ||
409 | pr_err("out of memory\n"); | 417 | pr_err("out of memory\n"); |
410 | return 0; | 418 | return 0; |
411 | } | 419 | } |
420 | cs->hw.ser = scs; | ||
412 | 421 | ||
413 | cs->hw.ser->dev.name = GIGASET_MODULENAME; | 422 | cs->hw.ser->dev.name = GIGASET_MODULENAME; |
414 | cs->hw.ser->dev.id = cs->minor_index; | 423 | cs->hw.ser->dev.id = cs->minor_index; |
415 | cs->hw.ser->dev.dev.release = gigaset_device_release; | 424 | cs->hw.ser->dev.dev.release = gigaset_device_release; |
416 | if ((rc = platform_device_register(&cs->hw.ser->dev)) != 0) { | 425 | rc = platform_device_register(&cs->hw.ser->dev); |
426 | if (rc != 0) { | ||
417 | pr_err("error %d registering platform device\n", rc); | 427 | pr_err("error %d registering platform device\n", rc); |
418 | kfree(cs->hw.ser); | 428 | kfree(cs->hw.ser); |
419 | cs->hw.ser = NULL; | 429 | cs->hw.ser = NULL; |
@@ -422,7 +432,7 @@ static int gigaset_initcshw(struct cardstate *cs) | |||
422 | dev_set_drvdata(&cs->hw.ser->dev.dev, cs); | 432 | dev_set_drvdata(&cs->hw.ser->dev.dev, cs); |
423 | 433 | ||
424 | tasklet_init(&cs->write_tasklet, | 434 | tasklet_init(&cs->write_tasklet, |
425 | &gigaset_modem_fill, (unsigned long) cs); | 435 | gigaset_modem_fill, (unsigned long) cs); |
426 | return 1; | 436 | return 1; |
427 | } | 437 | } |
428 | 438 | ||
@@ -434,7 +444,8 @@ static int gigaset_initcshw(struct cardstate *cs) | |||
434 | * Called by "gigaset_start" and "gigaset_enterconfigmode" in common.c | 444 | * Called by "gigaset_start" and "gigaset_enterconfigmode" in common.c |
435 | * and by "if_lock" and "if_termios" in interface.c | 445 | * and by "if_lock" and "if_termios" in interface.c |
436 | */ | 446 | */ |
437 | static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state, unsigned new_state) | 447 | static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state, |
448 | unsigned new_state) | ||
438 | { | 449 | { |
439 | struct tty_struct *tty = cs->hw.ser->tty; | 450 | struct tty_struct *tty = cs->hw.ser->tty; |
440 | unsigned int set, clear; | 451 | unsigned int set, clear; |
@@ -520,8 +531,8 @@ gigaset_tty_open(struct tty_struct *tty) | |||
520 | } | 531 | } |
521 | 532 | ||
522 | /* allocate memory for our device state and intialize it */ | 533 | /* allocate memory for our device state and intialize it */ |
523 | if (!(cs = gigaset_initcs(driver, 1, 1, 0, cidmode, | 534 | cs = gigaset_initcs(driver, 1, 1, 0, cidmode, GIGASET_MODULENAME); |
524 | GIGASET_MODULENAME))) | 535 | if (!cs) |
525 | goto error; | 536 | goto error; |
526 | 537 | ||
527 | cs->dev = &cs->hw.ser->dev.dev; | 538 | cs->dev = &cs->hw.ser->dev.dev; |
@@ -690,7 +701,8 @@ gigaset_tty_receive(struct tty_struct *tty, const unsigned char *buf, | |||
690 | 701 | ||
691 | if (!cs) | 702 | if (!cs) |
692 | return; | 703 | return; |
693 | if (!(inbuf = cs->inbuf)) { | 704 | inbuf = cs->inbuf; |
705 | if (!inbuf) { | ||
694 | dev_err(cs->dev, "%s: no inbuf\n", __func__); | 706 | dev_err(cs->dev, "%s: no inbuf\n", __func__); |
695 | cs_put(cs); | 707 | cs_put(cs); |
696 | return; | 708 | return; |
@@ -770,18 +782,21 @@ static int __init ser_gigaset_init(void) | |||
770 | int rc; | 782 | int rc; |
771 | 783 | ||
772 | gig_dbg(DEBUG_INIT, "%s", __func__); | 784 | gig_dbg(DEBUG_INIT, "%s", __func__); |
773 | if ((rc = platform_driver_register(&device_driver)) != 0) { | 785 | rc = platform_driver_register(&device_driver); |
786 | if (rc != 0) { | ||
774 | pr_err("error %d registering platform driver\n", rc); | 787 | pr_err("error %d registering platform driver\n", rc); |
775 | return rc; | 788 | return rc; |
776 | } | 789 | } |
777 | 790 | ||
778 | /* allocate memory for our driver state and intialize it */ | 791 | /* allocate memory for our driver state and intialize it */ |
779 | if (!(driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS, | 792 | driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS, |
780 | GIGASET_MODULENAME, GIGASET_DEVNAME, | 793 | GIGASET_MODULENAME, GIGASET_DEVNAME, |
781 | &ops, THIS_MODULE))) | 794 | &ops, THIS_MODULE); |
795 | if (!driver) | ||
782 | goto error; | 796 | goto error; |
783 | 797 | ||
784 | if ((rc = tty_register_ldisc(N_GIGASET_M101, &gigaset_ldisc)) != 0) { | 798 | rc = tty_register_ldisc(N_GIGASET_M101, &gigaset_ldisc); |
799 | if (rc != 0) { | ||
785 | pr_err("error %d registering line discipline\n", rc); | 800 | pr_err("error %d registering line discipline\n", rc); |
786 | goto error; | 801 | goto error; |
787 | } | 802 | } |
@@ -808,7 +823,8 @@ static void __exit ser_gigaset_exit(void) | |||
808 | driver = NULL; | 823 | driver = NULL; |
809 | } | 824 | } |
810 | 825 | ||
811 | if ((rc = tty_unregister_ldisc(N_GIGASET_M101)) != 0) | 826 | rc = tty_unregister_ldisc(N_GIGASET_M101); |
827 | if (rc != 0) | ||
812 | pr_err("error %d unregistering line discipline\n", rc); | 828 | pr_err("error %d unregistering line discipline\n", rc); |
813 | 829 | ||
814 | platform_driver_unregister(&device_driver); | 830 | platform_driver_unregister(&device_driver); |
diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c index 4deb1ab0dbf8..76dbb20f3065 100644 --- a/drivers/isdn/gigaset/usb-gigaset.c +++ b/drivers/isdn/gigaset/usb-gigaset.c | |||
@@ -16,10 +16,6 @@ | |||
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include "gigaset.h" | 18 | #include "gigaset.h" |
19 | |||
20 | #include <linux/errno.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <linux/usb.h> | 19 | #include <linux/usb.h> |
24 | #include <linux/module.h> | 20 | #include <linux/module.h> |
25 | #include <linux/moduleparam.h> | 21 | #include <linux/moduleparam.h> |
@@ -43,14 +39,14 @@ MODULE_PARM_DESC(cidmode, "Call-ID mode"); | |||
43 | #define GIGASET_MODULENAME "usb_gigaset" | 39 | #define GIGASET_MODULENAME "usb_gigaset" |
44 | #define GIGASET_DEVNAME "ttyGU" | 40 | #define GIGASET_DEVNAME "ttyGU" |
45 | 41 | ||
46 | #define IF_WRITEBUF 2000 //FIXME // WAKEUP_CHARS: 256 | 42 | #define IF_WRITEBUF 2000 /* arbitrary limit */ |
47 | 43 | ||
48 | /* Values for the Gigaset M105 Data */ | 44 | /* Values for the Gigaset M105 Data */ |
49 | #define USB_M105_VENDOR_ID 0x0681 | 45 | #define USB_M105_VENDOR_ID 0x0681 |
50 | #define USB_M105_PRODUCT_ID 0x0009 | 46 | #define USB_M105_PRODUCT_ID 0x0009 |
51 | 47 | ||
52 | /* table of devices that work with this driver */ | 48 | /* table of devices that work with this driver */ |
53 | static const struct usb_device_id gigaset_table [] = { | 49 | static const struct usb_device_id gigaset_table[] = { |
54 | { USB_DEVICE(USB_M105_VENDOR_ID, USB_M105_PRODUCT_ID) }, | 50 | { USB_DEVICE(USB_M105_VENDOR_ID, USB_M105_PRODUCT_ID) }, |
55 | { } /* Terminating entry */ | 51 | { } /* Terminating entry */ |
56 | }; | 52 | }; |
@@ -97,8 +93,8 @@ MODULE_DEVICE_TABLE(usb, gigaset_table); | |||
97 | * 41 19 -- -- -- -- 06 00 00 00 00 xx 11 13 | 93 | * 41 19 -- -- -- -- 06 00 00 00 00 xx 11 13 |
98 | * Used after every "configuration sequence" (RQ 12, RQs 01/03/13). | 94 | * Used after every "configuration sequence" (RQ 12, RQs 01/03/13). |
99 | * xx is usually 0x00 but was 0x7e before starting data transfer | 95 | * xx is usually 0x00 but was 0x7e before starting data transfer |
100 | * in unimodem mode. So, this might be an array of characters that need | 96 | * in unimodem mode. So, this might be an array of characters that |
101 | * special treatment ("commit all bufferd data"?), 11=^Q, 13=^S. | 97 | * need special treatment ("commit all bufferd data"?), 11=^Q, 13=^S. |
102 | * | 98 | * |
103 | * Unimodem mode: use "modprobe ppp_async flag_time=0" as the device _needs_ two | 99 | * Unimodem mode: use "modprobe ppp_async flag_time=0" as the device _needs_ two |
104 | * flags per packet. | 100 | * flags per packet. |
@@ -114,7 +110,7 @@ static int gigaset_suspend(struct usb_interface *intf, pm_message_t message); | |||
114 | static int gigaset_resume(struct usb_interface *intf); | 110 | static int gigaset_resume(struct usb_interface *intf); |
115 | static int gigaset_pre_reset(struct usb_interface *intf); | 111 | static int gigaset_pre_reset(struct usb_interface *intf); |
116 | 112 | ||
117 | static struct gigaset_driver *driver = NULL; | 113 | static struct gigaset_driver *driver; |
118 | 114 | ||
119 | /* usb specific object needed to register this driver with the usb subsystem */ | 115 | /* usb specific object needed to register this driver with the usb subsystem */ |
120 | static struct usb_driver gigaset_usb_driver = { | 116 | static struct usb_driver gigaset_usb_driver = { |
@@ -141,6 +137,7 @@ struct usb_cardstate { | |||
141 | struct urb *bulk_out_urb; | 137 | struct urb *bulk_out_urb; |
142 | 138 | ||
143 | /* Input buffer */ | 139 | /* Input buffer */ |
140 | unsigned char *rcvbuf; | ||
144 | int rcvbuf_size; | 141 | int rcvbuf_size; |
145 | struct urb *read_urb; | 142 | struct urb *read_urb; |
146 | __u8 int_in_endpointAddr; | 143 | __u8 int_in_endpointAddr; |
@@ -164,13 +161,11 @@ static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state, | |||
164 | val = tiocm_to_gigaset(new_state); | 161 | val = tiocm_to_gigaset(new_state); |
165 | 162 | ||
166 | gig_dbg(DEBUG_USBREQ, "set flags 0x%02x with mask 0x%02x", val, mask); | 163 | gig_dbg(DEBUG_USBREQ, "set flags 0x%02x with mask 0x%02x", val, mask); |
167 | // don't use this in an interrupt/BH | ||
168 | r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 7, 0x41, | 164 | r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 7, 0x41, |
169 | (val & 0xff) | ((mask & 0xff) << 8), 0, | 165 | (val & 0xff) | ((mask & 0xff) << 8), 0, |
170 | NULL, 0, 2000 /* timeout? */); | 166 | NULL, 0, 2000 /* timeout? */); |
171 | if (r < 0) | 167 | if (r < 0) |
172 | return r; | 168 | return r; |
173 | //.. | ||
174 | return 0; | 169 | return 0; |
175 | } | 170 | } |
176 | 171 | ||
@@ -220,7 +215,6 @@ static int gigaset_baud_rate(struct cardstate *cs, unsigned cflag) | |||
220 | cflag &= CBAUD; | 215 | cflag &= CBAUD; |
221 | 216 | ||
222 | switch (cflag) { | 217 | switch (cflag) { |
223 | //FIXME more values? | ||
224 | case B300: rate = 300; break; | 218 | case B300: rate = 300; break; |
225 | case B600: rate = 600; break; | 219 | case B600: rate = 600; break; |
226 | case B1200: rate = 1200; break; | 220 | case B1200: rate = 1200; break; |
@@ -273,7 +267,7 @@ static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag) | |||
273 | /* set the number of stop bits */ | 267 | /* set the number of stop bits */ |
274 | if (cflag & CSTOPB) { | 268 | if (cflag & CSTOPB) { |
275 | if ((cflag & CSIZE) == CS5) | 269 | if ((cflag & CSIZE) == CS5) |
276 | val |= 1; /* 1.5 stop bits */ //FIXME is this okay? | 270 | val |= 1; /* 1.5 stop bits */ |
277 | else | 271 | else |
278 | val |= 2; /* 2 stop bits */ | 272 | val |= 2; /* 2 stop bits */ |
279 | } | 273 | } |
@@ -282,7 +276,7 @@ static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag) | |||
282 | } | 276 | } |
283 | 277 | ||
284 | 278 | ||
285 | /*================================================================================================================*/ | 279 | /*============================================================================*/ |
286 | static int gigaset_init_bchannel(struct bc_state *bcs) | 280 | static int gigaset_init_bchannel(struct bc_state *bcs) |
287 | { | 281 | { |
288 | /* nothing to do for M10x */ | 282 | /* nothing to do for M10x */ |
@@ -344,7 +338,6 @@ static void gigaset_modem_fill(unsigned long data) | |||
344 | if (write_modem(cs) < 0) { | 338 | if (write_modem(cs) < 0) { |
345 | gig_dbg(DEBUG_OUTPUT, | 339 | gig_dbg(DEBUG_OUTPUT, |
346 | "modem_fill: write_modem failed"); | 340 | "modem_fill: write_modem failed"); |
347 | // FIXME should we tell the LL? | ||
348 | again = 1; /* no callback will be called! */ | 341 | again = 1; /* no callback will be called! */ |
349 | } | 342 | } |
350 | } | 343 | } |
@@ -356,8 +349,8 @@ static void gigaset_modem_fill(unsigned long data) | |||
356 | */ | 349 | */ |
357 | static void gigaset_read_int_callback(struct urb *urb) | 350 | static void gigaset_read_int_callback(struct urb *urb) |
358 | { | 351 | { |
359 | struct inbuf_t *inbuf = urb->context; | 352 | struct cardstate *cs = urb->context; |
360 | struct cardstate *cs = inbuf->cs; | 353 | struct inbuf_t *inbuf = cs->inbuf; |
361 | int status = urb->status; | 354 | int status = urb->status; |
362 | int r; | 355 | int r; |
363 | unsigned numbytes; | 356 | unsigned numbytes; |
@@ -368,7 +361,7 @@ static void gigaset_read_int_callback(struct urb *urb) | |||
368 | numbytes = urb->actual_length; | 361 | numbytes = urb->actual_length; |
369 | 362 | ||
370 | if (numbytes) { | 363 | if (numbytes) { |
371 | src = inbuf->rcvbuf; | 364 | src = cs->hw.usb->rcvbuf; |
372 | if (unlikely(*src)) | 365 | if (unlikely(*src)) |
373 | dev_warn(cs->dev, | 366 | dev_warn(cs->dev, |
374 | "%s: There was no leading 0, but 0x%02x!\n", | 367 | "%s: There was no leading 0, but 0x%02x!\n", |
@@ -440,7 +433,7 @@ static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb) | |||
440 | struct cmdbuf_t *tcb; | 433 | struct cmdbuf_t *tcb; |
441 | unsigned long flags; | 434 | unsigned long flags; |
442 | int count; | 435 | int count; |
443 | int status = -ENOENT; // FIXME | 436 | int status = -ENOENT; |
444 | struct usb_cardstate *ucs = cs->hw.usb; | 437 | struct usb_cardstate *ucs = cs->hw.usb; |
445 | 438 | ||
446 | do { | 439 | do { |
@@ -480,7 +473,9 @@ static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb) | |||
480 | ucs->busy = 1; | 473 | ucs->busy = 1; |
481 | 474 | ||
482 | spin_lock_irqsave(&cs->lock, flags); | 475 | spin_lock_irqsave(&cs->lock, flags); |
483 | status = cs->connected ? usb_submit_urb(ucs->bulk_out_urb, GFP_ATOMIC) : -ENODEV; | 476 | status = cs->connected ? |
477 | usb_submit_urb(ucs->bulk_out_urb, GFP_ATOMIC) : | ||
478 | -ENODEV; | ||
484 | spin_unlock_irqrestore(&cs->lock, flags); | 479 | spin_unlock_irqrestore(&cs->lock, flags); |
485 | 480 | ||
486 | if (status) { | 481 | if (status) { |
@@ -510,8 +505,8 @@ static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf, | |||
510 | 505 | ||
511 | if (len <= 0) | 506 | if (len <= 0) |
512 | return 0; | 507 | return 0; |
513 | 508 | cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC); | |
514 | if (!(cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC))) { | 509 | if (!cb) { |
515 | dev_err(cs->dev, "%s: out of memory\n", __func__); | 510 | dev_err(cs->dev, "%s: out of memory\n", __func__); |
516 | return -ENOMEM; | 511 | return -ENOMEM; |
517 | } | 512 | } |
@@ -615,7 +610,7 @@ static int gigaset_initcshw(struct cardstate *cs) | |||
615 | ucs->bulk_out_urb = NULL; | 610 | ucs->bulk_out_urb = NULL; |
616 | ucs->read_urb = NULL; | 611 | ucs->read_urb = NULL; |
617 | tasklet_init(&cs->write_tasklet, | 612 | tasklet_init(&cs->write_tasklet, |
618 | &gigaset_modem_fill, (unsigned long) cs); | 613 | gigaset_modem_fill, (unsigned long) cs); |
619 | 614 | ||
620 | return 1; | 615 | return 1; |
621 | } | 616 | } |
@@ -629,7 +624,7 @@ static int write_modem(struct cardstate *cs) | |||
629 | struct usb_cardstate *ucs = cs->hw.usb; | 624 | struct usb_cardstate *ucs = cs->hw.usb; |
630 | unsigned long flags; | 625 | unsigned long flags; |
631 | 626 | ||
632 | gig_dbg(DEBUG_WRITE, "len: %d...", bcs->tx_skb->len); | 627 | gig_dbg(DEBUG_OUTPUT, "len: %d...", bcs->tx_skb->len); |
633 | 628 | ||
634 | if (!bcs->tx_skb->len) { | 629 | if (!bcs->tx_skb->len) { |
635 | dev_kfree_skb_any(bcs->tx_skb); | 630 | dev_kfree_skb_any(bcs->tx_skb); |
@@ -637,9 +632,7 @@ static int write_modem(struct cardstate *cs) | |||
637 | return -EINVAL; | 632 | return -EINVAL; |
638 | } | 633 | } |
639 | 634 | ||
640 | /* Copy data to bulk out buffer and // FIXME copying not necessary | 635 | /* Copy data to bulk out buffer and transmit data */ |
641 | * transmit data | ||
642 | */ | ||
643 | count = min(bcs->tx_skb->len, (unsigned) ucs->bulk_out_size); | 636 | count = min(bcs->tx_skb->len, (unsigned) ucs->bulk_out_size); |
644 | skb_copy_from_linear_data(bcs->tx_skb, ucs->bulk_out_buffer, count); | 637 | skb_copy_from_linear_data(bcs->tx_skb, ucs->bulk_out_buffer, count); |
645 | skb_pull(bcs->tx_skb, count); | 638 | skb_pull(bcs->tx_skb, count); |
@@ -650,7 +643,8 @@ static int write_modem(struct cardstate *cs) | |||
650 | if (cs->connected) { | 643 | if (cs->connected) { |
651 | usb_fill_bulk_urb(ucs->bulk_out_urb, ucs->udev, | 644 | usb_fill_bulk_urb(ucs->bulk_out_urb, ucs->udev, |
652 | usb_sndbulkpipe(ucs->udev, | 645 | usb_sndbulkpipe(ucs->udev, |
653 | ucs->bulk_out_endpointAddr & 0x0f), | 646 | ucs->bulk_out_endpointAddr & |
647 | 0x0f), | ||
654 | ucs->bulk_out_buffer, count, | 648 | ucs->bulk_out_buffer, count, |
655 | gigaset_write_bulk_callback, cs); | 649 | gigaset_write_bulk_callback, cs); |
656 | ret = usb_submit_urb(ucs->bulk_out_urb, GFP_ATOMIC); | 650 | ret = usb_submit_urb(ucs->bulk_out_urb, GFP_ATOMIC); |
@@ -666,7 +660,7 @@ static int write_modem(struct cardstate *cs) | |||
666 | 660 | ||
667 | if (!bcs->tx_skb->len) { | 661 | if (!bcs->tx_skb->len) { |
668 | /* skb sent completely */ | 662 | /* skb sent completely */ |
669 | gigaset_skb_sent(bcs, bcs->tx_skb); //FIXME also, when ret<0? | 663 | gigaset_skb_sent(bcs, bcs->tx_skb); |
670 | 664 | ||
671 | gig_dbg(DEBUG_INTR, "kfree skb (Adr: %lx)!", | 665 | gig_dbg(DEBUG_INTR, "kfree skb (Adr: %lx)!", |
672 | (unsigned long) bcs->tx_skb); | 666 | (unsigned long) bcs->tx_skb); |
@@ -763,8 +757,8 @@ static int gigaset_probe(struct usb_interface *interface, | |||
763 | buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); | 757 | buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); |
764 | ucs->rcvbuf_size = buffer_size; | 758 | ucs->rcvbuf_size = buffer_size; |
765 | ucs->int_in_endpointAddr = endpoint->bEndpointAddress; | 759 | ucs->int_in_endpointAddr = endpoint->bEndpointAddress; |
766 | cs->inbuf[0].rcvbuf = kmalloc(buffer_size, GFP_KERNEL); | 760 | ucs->rcvbuf = kmalloc(buffer_size, GFP_KERNEL); |
767 | if (!cs->inbuf[0].rcvbuf) { | 761 | if (!ucs->rcvbuf) { |
768 | dev_err(cs->dev, "Couldn't allocate rcvbuf\n"); | 762 | dev_err(cs->dev, "Couldn't allocate rcvbuf\n"); |
769 | retval = -ENOMEM; | 763 | retval = -ENOMEM; |
770 | goto error; | 764 | goto error; |
@@ -773,9 +767,9 @@ static int gigaset_probe(struct usb_interface *interface, | |||
773 | usb_fill_int_urb(ucs->read_urb, udev, | 767 | usb_fill_int_urb(ucs->read_urb, udev, |
774 | usb_rcvintpipe(udev, | 768 | usb_rcvintpipe(udev, |
775 | endpoint->bEndpointAddress & 0x0f), | 769 | endpoint->bEndpointAddress & 0x0f), |
776 | cs->inbuf[0].rcvbuf, buffer_size, | 770 | ucs->rcvbuf, buffer_size, |
777 | gigaset_read_int_callback, | 771 | gigaset_read_int_callback, |
778 | cs->inbuf + 0, endpoint->bInterval); | 772 | cs, endpoint->bInterval); |
779 | 773 | ||
780 | retval = usb_submit_urb(ucs->read_urb, GFP_KERNEL); | 774 | retval = usb_submit_urb(ucs->read_urb, GFP_KERNEL); |
781 | if (retval) { | 775 | if (retval) { |
@@ -789,7 +783,7 @@ static int gigaset_probe(struct usb_interface *interface, | |||
789 | 783 | ||
790 | if (!gigaset_start(cs)) { | 784 | if (!gigaset_start(cs)) { |
791 | tasklet_kill(&cs->write_tasklet); | 785 | tasklet_kill(&cs->write_tasklet); |
792 | retval = -ENODEV; //FIXME | 786 | retval = -ENODEV; |
793 | goto error; | 787 | goto error; |
794 | } | 788 | } |
795 | return 0; | 789 | return 0; |
@@ -798,11 +792,11 @@ error: | |||
798 | usb_kill_urb(ucs->read_urb); | 792 | usb_kill_urb(ucs->read_urb); |
799 | kfree(ucs->bulk_out_buffer); | 793 | kfree(ucs->bulk_out_buffer); |
800 | usb_free_urb(ucs->bulk_out_urb); | 794 | usb_free_urb(ucs->bulk_out_urb); |
801 | kfree(cs->inbuf[0].rcvbuf); | 795 | kfree(ucs->rcvbuf); |
802 | usb_free_urb(ucs->read_urb); | 796 | usb_free_urb(ucs->read_urb); |
803 | usb_set_intfdata(interface, NULL); | 797 | usb_set_intfdata(interface, NULL); |
804 | ucs->read_urb = ucs->bulk_out_urb = NULL; | 798 | ucs->read_urb = ucs->bulk_out_urb = NULL; |
805 | cs->inbuf[0].rcvbuf = ucs->bulk_out_buffer = NULL; | 799 | ucs->rcvbuf = ucs->bulk_out_buffer = NULL; |
806 | usb_put_dev(ucs->udev); | 800 | usb_put_dev(ucs->udev); |
807 | ucs->udev = NULL; | 801 | ucs->udev = NULL; |
808 | ucs->interface = NULL; | 802 | ucs->interface = NULL; |
@@ -831,10 +825,10 @@ static void gigaset_disconnect(struct usb_interface *interface) | |||
831 | 825 | ||
832 | kfree(ucs->bulk_out_buffer); | 826 | kfree(ucs->bulk_out_buffer); |
833 | usb_free_urb(ucs->bulk_out_urb); | 827 | usb_free_urb(ucs->bulk_out_urb); |
834 | kfree(cs->inbuf[0].rcvbuf); | 828 | kfree(ucs->rcvbuf); |
835 | usb_free_urb(ucs->read_urb); | 829 | usb_free_urb(ucs->read_urb); |
836 | ucs->read_urb = ucs->bulk_out_urb = NULL; | 830 | ucs->read_urb = ucs->bulk_out_urb = NULL; |
837 | cs->inbuf[0].rcvbuf = ucs->bulk_out_buffer = NULL; | 831 | ucs->rcvbuf = ucs->bulk_out_buffer = NULL; |
838 | 832 | ||
839 | usb_put_dev(ucs->udev); | 833 | usb_put_dev(ucs->udev); |
840 | ucs->interface = NULL; | 834 | ucs->interface = NULL; |
@@ -916,9 +910,10 @@ static int __init usb_gigaset_init(void) | |||
916 | int result; | 910 | int result; |
917 | 911 | ||
918 | /* allocate memory for our driver state and intialize it */ | 912 | /* allocate memory for our driver state and intialize it */ |
919 | if ((driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS, | 913 | driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS, |
920 | GIGASET_MODULENAME, GIGASET_DEVNAME, | 914 | GIGASET_MODULENAME, GIGASET_DEVNAME, |
921 | &ops, THIS_MODULE)) == NULL) | 915 | &ops, THIS_MODULE); |
916 | if (driver == NULL) | ||
922 | goto error; | 917 | goto error; |
923 | 918 | ||
924 | /* register this driver with the USB subsystem */ | 919 | /* register this driver with the USB subsystem */ |
diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c index c72565520e41..94b796d84053 100644 --- a/drivers/isdn/hardware/avm/avm_cs.c +++ b/drivers/isdn/hardware/avm/avm_cs.c | |||
@@ -108,10 +108,7 @@ static int avmcs_probe(struct pcmcia_device *p_dev) | |||
108 | p_dev->io.NumPorts2 = 0; | 108 | p_dev->io.NumPorts2 = 0; |
109 | 109 | ||
110 | /* Interrupt setup */ | 110 | /* Interrupt setup */ |
111 | p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE; | 111 | p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; |
112 | p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; | ||
113 | |||
114 | p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; | ||
115 | 112 | ||
116 | /* General socket configuration */ | 113 | /* General socket configuration */ |
117 | p_dev->conf.Attributes = CONF_ENABLE_IRQ; | 114 | p_dev->conf.Attributes = CONF_ENABLE_IRQ; |
@@ -198,7 +195,6 @@ static int avmcs_config(struct pcmcia_device *link) | |||
198 | */ | 195 | */ |
199 | i = pcmcia_request_irq(link, &link->irq); | 196 | i = pcmcia_request_irq(link, &link->irq); |
200 | if (i != 0) { | 197 | if (i != 0) { |
201 | cs_error(link, RequestIRQ, i); | ||
202 | /* undo */ | 198 | /* undo */ |
203 | pcmcia_disable_device(link); | 199 | pcmcia_disable_device(link); |
204 | break; | 200 | break; |
@@ -209,7 +205,6 @@ static int avmcs_config(struct pcmcia_device *link) | |||
209 | */ | 205 | */ |
210 | i = pcmcia_request_configuration(link, &link->conf); | 206 | i = pcmcia_request_configuration(link, &link->conf); |
211 | if (i != 0) { | 207 | if (i != 0) { |
212 | cs_error(link, RequestConfiguration, i); | ||
213 | pcmcia_disable_device(link); | 208 | pcmcia_disable_device(link); |
214 | break; | 209 | break; |
215 | } | 210 | } |
diff --git a/drivers/isdn/hardware/avm/avmcard.h b/drivers/isdn/hardware/avm/avmcard.h index d964f07e4a56..a70e8854461d 100644 --- a/drivers/isdn/hardware/avm/avmcard.h +++ b/drivers/isdn/hardware/avm/avmcard.h | |||
@@ -556,8 +556,7 @@ u16 b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb); | |||
556 | void b1_parse_version(avmctrl_info *card); | 556 | void b1_parse_version(avmctrl_info *card); |
557 | irqreturn_t b1_interrupt(int interrupt, void *devptr); | 557 | irqreturn_t b1_interrupt(int interrupt, void *devptr); |
558 | 558 | ||
559 | int b1ctl_read_proc(char *page, char **start, off_t off, | 559 | extern const struct file_operations b1ctl_proc_fops; |
560 | int count, int *eof, struct capi_ctr *ctrl); | ||
561 | 560 | ||
562 | avmcard_dmainfo *avmcard_dma_alloc(char *name, struct pci_dev *, | 561 | avmcard_dmainfo *avmcard_dma_alloc(char *name, struct pci_dev *, |
563 | long rsize, long ssize); | 562 | long rsize, long ssize); |
@@ -577,7 +576,6 @@ void b1dma_register_appl(struct capi_ctr *ctrl, | |||
577 | capi_register_params *rp); | 576 | capi_register_params *rp); |
578 | void b1dma_release_appl(struct capi_ctr *ctrl, u16 appl); | 577 | void b1dma_release_appl(struct capi_ctr *ctrl, u16 appl); |
579 | u16 b1dma_send_message(struct capi_ctr *ctrl, struct sk_buff *skb); | 578 | u16 b1dma_send_message(struct capi_ctr *ctrl, struct sk_buff *skb); |
580 | int b1dmactl_read_proc(char *page, char **start, off_t off, | 579 | extern const struct file_operations b1dmactl_proc_fops; |
581 | int count, int *eof, struct capi_ctr *ctrl); | ||
582 | 580 | ||
583 | #endif /* _AVMCARD_H_ */ | 581 | #endif /* _AVMCARD_H_ */ |
diff --git a/drivers/isdn/hardware/avm/b1.c b/drivers/isdn/hardware/avm/b1.c index a7c0083e78a7..2a57da590d79 100644 --- a/drivers/isdn/hardware/avm/b1.c +++ b/drivers/isdn/hardware/avm/b1.c | |||
@@ -12,6 +12,8 @@ | |||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/pci.h> | 14 | #include <linux/pci.h> |
15 | #include <linux/proc_fs.h> | ||
16 | #include <linux/seq_file.h> | ||
15 | #include <linux/skbuff.h> | 17 | #include <linux/skbuff.h> |
16 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
17 | #include <linux/mm.h> | 19 | #include <linux/mm.h> |
@@ -19,6 +21,7 @@ | |||
19 | #include <linux/ioport.h> | 21 | #include <linux/ioport.h> |
20 | #include <linux/capi.h> | 22 | #include <linux/capi.h> |
21 | #include <linux/kernelcapi.h> | 23 | #include <linux/kernelcapi.h> |
24 | #include <linux/slab.h> | ||
22 | #include <asm/io.h> | 25 | #include <asm/io.h> |
23 | #include <linux/init.h> | 26 | #include <linux/init.h> |
24 | #include <asm/uaccess.h> | 27 | #include <asm/uaccess.h> |
@@ -634,18 +637,17 @@ irqreturn_t b1_interrupt(int interrupt, void *devptr) | |||
634 | } | 637 | } |
635 | 638 | ||
636 | /* ------------------------------------------------------------- */ | 639 | /* ------------------------------------------------------------- */ |
637 | int b1ctl_read_proc(char *page, char **start, off_t off, | 640 | static int b1ctl_proc_show(struct seq_file *m, void *v) |
638 | int count, int *eof, struct capi_ctr *ctrl) | ||
639 | { | 641 | { |
642 | struct capi_ctr *ctrl = m->private; | ||
640 | avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); | 643 | avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); |
641 | avmcard *card = cinfo->card; | 644 | avmcard *card = cinfo->card; |
642 | u8 flag; | 645 | u8 flag; |
643 | int len = 0; | ||
644 | char *s; | 646 | char *s; |
645 | 647 | ||
646 | len += sprintf(page+len, "%-16s %s\n", "name", card->name); | 648 | seq_printf(m, "%-16s %s\n", "name", card->name); |
647 | len += sprintf(page+len, "%-16s 0x%x\n", "io", card->port); | 649 | seq_printf(m, "%-16s 0x%x\n", "io", card->port); |
648 | len += sprintf(page+len, "%-16s %d\n", "irq", card->irq); | 650 | seq_printf(m, "%-16s %d\n", "irq", card->irq); |
649 | switch (card->cardtype) { | 651 | switch (card->cardtype) { |
650 | case avm_b1isa: s = "B1 ISA"; break; | 652 | case avm_b1isa: s = "B1 ISA"; break; |
651 | case avm_b1pci: s = "B1 PCI"; break; | 653 | case avm_b1pci: s = "B1 PCI"; break; |
@@ -658,20 +660,20 @@ int b1ctl_read_proc(char *page, char **start, off_t off, | |||
658 | case avm_c2: s = "C2"; break; | 660 | case avm_c2: s = "C2"; break; |
659 | default: s = "???"; break; | 661 | default: s = "???"; break; |
660 | } | 662 | } |
661 | len += sprintf(page+len, "%-16s %s\n", "type", s); | 663 | seq_printf(m, "%-16s %s\n", "type", s); |
662 | if (card->cardtype == avm_t1isa) | 664 | if (card->cardtype == avm_t1isa) |
663 | len += sprintf(page+len, "%-16s %d\n", "cardnr", card->cardnr); | 665 | seq_printf(m, "%-16s %d\n", "cardnr", card->cardnr); |
664 | if ((s = cinfo->version[VER_DRIVER]) != NULL) | 666 | if ((s = cinfo->version[VER_DRIVER]) != NULL) |
665 | len += sprintf(page+len, "%-16s %s\n", "ver_driver", s); | 667 | seq_printf(m, "%-16s %s\n", "ver_driver", s); |
666 | if ((s = cinfo->version[VER_CARDTYPE]) != NULL) | 668 | if ((s = cinfo->version[VER_CARDTYPE]) != NULL) |
667 | len += sprintf(page+len, "%-16s %s\n", "ver_cardtype", s); | 669 | seq_printf(m, "%-16s %s\n", "ver_cardtype", s); |
668 | if ((s = cinfo->version[VER_SERIAL]) != NULL) | 670 | if ((s = cinfo->version[VER_SERIAL]) != NULL) |
669 | len += sprintf(page+len, "%-16s %s\n", "ver_serial", s); | 671 | seq_printf(m, "%-16s %s\n", "ver_serial", s); |
670 | 672 | ||
671 | if (card->cardtype != avm_m1) { | 673 | if (card->cardtype != avm_m1) { |
672 | flag = ((u8 *)(ctrl->profile.manu))[3]; | 674 | flag = ((u8 *)(ctrl->profile.manu))[3]; |
673 | if (flag) | 675 | if (flag) |
674 | len += sprintf(page+len, "%-16s%s%s%s%s%s%s%s\n", | 676 | seq_printf(m, "%-16s%s%s%s%s%s%s%s\n", |
675 | "protocol", | 677 | "protocol", |
676 | (flag & 0x01) ? " DSS1" : "", | 678 | (flag & 0x01) ? " DSS1" : "", |
677 | (flag & 0x02) ? " CT1" : "", | 679 | (flag & 0x02) ? " CT1" : "", |
@@ -685,7 +687,7 @@ int b1ctl_read_proc(char *page, char **start, off_t off, | |||
685 | if (card->cardtype != avm_m1) { | 687 | if (card->cardtype != avm_m1) { |
686 | flag = ((u8 *)(ctrl->profile.manu))[5]; | 688 | flag = ((u8 *)(ctrl->profile.manu))[5]; |
687 | if (flag) | 689 | if (flag) |
688 | len += sprintf(page+len, "%-16s%s%s%s%s\n", | 690 | seq_printf(m, "%-16s%s%s%s%s\n", |
689 | "linetype", | 691 | "linetype", |
690 | (flag & 0x01) ? " point to point" : "", | 692 | (flag & 0x01) ? " point to point" : "", |
691 | (flag & 0x02) ? " point to multipoint" : "", | 693 | (flag & 0x02) ? " point to multipoint" : "", |
@@ -693,16 +695,25 @@ int b1ctl_read_proc(char *page, char **start, off_t off, | |||
693 | (flag & 0x04) ? " leased line with D-channel" : "" | 695 | (flag & 0x04) ? " leased line with D-channel" : "" |
694 | ); | 696 | ); |
695 | } | 697 | } |
696 | len += sprintf(page+len, "%-16s %s\n", "cardname", cinfo->cardname); | 698 | seq_printf(m, "%-16s %s\n", "cardname", cinfo->cardname); |
697 | 699 | ||
698 | if (off+count >= len) | 700 | return 0; |
699 | *eof = 1; | 701 | } |
700 | if (len < off) | 702 | |
701 | return 0; | 703 | static int b1ctl_proc_open(struct inode *inode, struct file *file) |
702 | *start = page + off; | 704 | { |
703 | return ((count < len-off) ? count : len-off); | 705 | return single_open(file, b1ctl_proc_show, PDE(inode)->data); |
704 | } | 706 | } |
705 | 707 | ||
708 | const struct file_operations b1ctl_proc_fops = { | ||
709 | .owner = THIS_MODULE, | ||
710 | .open = b1ctl_proc_open, | ||
711 | .read = seq_read, | ||
712 | .llseek = seq_lseek, | ||
713 | .release = single_release, | ||
714 | }; | ||
715 | EXPORT_SYMBOL(b1ctl_proc_fops); | ||
716 | |||
706 | /* ------------------------------------------------------------- */ | 717 | /* ------------------------------------------------------------- */ |
707 | 718 | ||
708 | #ifdef CONFIG_PCI | 719 | #ifdef CONFIG_PCI |
@@ -781,8 +792,6 @@ EXPORT_SYMBOL(b1_send_message); | |||
781 | EXPORT_SYMBOL(b1_parse_version); | 792 | EXPORT_SYMBOL(b1_parse_version); |
782 | EXPORT_SYMBOL(b1_interrupt); | 793 | EXPORT_SYMBOL(b1_interrupt); |
783 | 794 | ||
784 | EXPORT_SYMBOL(b1ctl_read_proc); | ||
785 | |||
786 | static int __init b1_init(void) | 795 | static int __init b1_init(void) |
787 | { | 796 | { |
788 | char *p; | 797 | char *p; |
diff --git a/drivers/isdn/hardware/avm/b1dma.c b/drivers/isdn/hardware/avm/b1dma.c index 0e84aaae43fd..9c8d7aa053c5 100644 --- a/drivers/isdn/hardware/avm/b1dma.c +++ b/drivers/isdn/hardware/avm/b1dma.c | |||
@@ -11,6 +11,8 @@ | |||
11 | 11 | ||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/proc_fs.h> | ||
15 | #include <linux/seq_file.h> | ||
14 | #include <linux/skbuff.h> | 16 | #include <linux/skbuff.h> |
15 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
16 | #include <linux/mm.h> | 18 | #include <linux/mm.h> |
@@ -18,6 +20,7 @@ | |||
18 | #include <linux/ioport.h> | 20 | #include <linux/ioport.h> |
19 | #include <linux/capi.h> | 21 | #include <linux/capi.h> |
20 | #include <linux/kernelcapi.h> | 22 | #include <linux/kernelcapi.h> |
23 | #include <linux/gfp.h> | ||
21 | #include <asm/io.h> | 24 | #include <asm/io.h> |
22 | #include <linux/init.h> | 25 | #include <linux/init.h> |
23 | #include <asm/uaccess.h> | 26 | #include <asm/uaccess.h> |
@@ -855,21 +858,20 @@ u16 b1dma_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) | |||
855 | 858 | ||
856 | /* ------------------------------------------------------------- */ | 859 | /* ------------------------------------------------------------- */ |
857 | 860 | ||
858 | int b1dmactl_read_proc(char *page, char **start, off_t off, | 861 | static int b1dmactl_proc_show(struct seq_file *m, void *v) |
859 | int count, int *eof, struct capi_ctr *ctrl) | ||
860 | { | 862 | { |
863 | struct capi_ctr *ctrl = m->private; | ||
861 | avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); | 864 | avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); |
862 | avmcard *card = cinfo->card; | 865 | avmcard *card = cinfo->card; |
863 | u8 flag; | 866 | u8 flag; |
864 | int len = 0; | ||
865 | char *s; | 867 | char *s; |
866 | u32 txoff, txlen, rxoff, rxlen, csr; | 868 | u32 txoff, txlen, rxoff, rxlen, csr; |
867 | unsigned long flags; | 869 | unsigned long flags; |
868 | 870 | ||
869 | len += sprintf(page+len, "%-16s %s\n", "name", card->name); | 871 | seq_printf(m, "%-16s %s\n", "name", card->name); |
870 | len += sprintf(page+len, "%-16s 0x%x\n", "io", card->port); | 872 | seq_printf(m, "%-16s 0x%x\n", "io", card->port); |
871 | len += sprintf(page+len, "%-16s %d\n", "irq", card->irq); | 873 | seq_printf(m, "%-16s %d\n", "irq", card->irq); |
872 | len += sprintf(page+len, "%-16s 0x%lx\n", "membase", card->membase); | 874 | seq_printf(m, "%-16s 0x%lx\n", "membase", card->membase); |
873 | switch (card->cardtype) { | 875 | switch (card->cardtype) { |
874 | case avm_b1isa: s = "B1 ISA"; break; | 876 | case avm_b1isa: s = "B1 ISA"; break; |
875 | case avm_b1pci: s = "B1 PCI"; break; | 877 | case avm_b1pci: s = "B1 PCI"; break; |
@@ -882,18 +884,18 @@ int b1dmactl_read_proc(char *page, char **start, off_t off, | |||
882 | case avm_c2: s = "C2"; break; | 884 | case avm_c2: s = "C2"; break; |
883 | default: s = "???"; break; | 885 | default: s = "???"; break; |
884 | } | 886 | } |
885 | len += sprintf(page+len, "%-16s %s\n", "type", s); | 887 | seq_printf(m, "%-16s %s\n", "type", s); |
886 | if ((s = cinfo->version[VER_DRIVER]) != NULL) | 888 | if ((s = cinfo->version[VER_DRIVER]) != NULL) |
887 | len += sprintf(page+len, "%-16s %s\n", "ver_driver", s); | 889 | seq_printf(m, "%-16s %s\n", "ver_driver", s); |
888 | if ((s = cinfo->version[VER_CARDTYPE]) != NULL) | 890 | if ((s = cinfo->version[VER_CARDTYPE]) != NULL) |
889 | len += sprintf(page+len, "%-16s %s\n", "ver_cardtype", s); | 891 | seq_printf(m, "%-16s %s\n", "ver_cardtype", s); |
890 | if ((s = cinfo->version[VER_SERIAL]) != NULL) | 892 | if ((s = cinfo->version[VER_SERIAL]) != NULL) |
891 | len += sprintf(page+len, "%-16s %s\n", "ver_serial", s); | 893 | seq_printf(m, "%-16s %s\n", "ver_serial", s); |
892 | 894 | ||
893 | if (card->cardtype != avm_m1) { | 895 | if (card->cardtype != avm_m1) { |
894 | flag = ((u8 *)(ctrl->profile.manu))[3]; | 896 | flag = ((u8 *)(ctrl->profile.manu))[3]; |
895 | if (flag) | 897 | if (flag) |
896 | len += sprintf(page+len, "%-16s%s%s%s%s%s%s%s\n", | 898 | seq_printf(m, "%-16s%s%s%s%s%s%s%s\n", |
897 | "protocol", | 899 | "protocol", |
898 | (flag & 0x01) ? " DSS1" : "", | 900 | (flag & 0x01) ? " DSS1" : "", |
899 | (flag & 0x02) ? " CT1" : "", | 901 | (flag & 0x02) ? " CT1" : "", |
@@ -907,7 +909,7 @@ int b1dmactl_read_proc(char *page, char **start, off_t off, | |||
907 | if (card->cardtype != avm_m1) { | 909 | if (card->cardtype != avm_m1) { |
908 | flag = ((u8 *)(ctrl->profile.manu))[5]; | 910 | flag = ((u8 *)(ctrl->profile.manu))[5]; |
909 | if (flag) | 911 | if (flag) |
910 | len += sprintf(page+len, "%-16s%s%s%s%s\n", | 912 | seq_printf(m, "%-16s%s%s%s%s\n", |
911 | "linetype", | 913 | "linetype", |
912 | (flag & 0x01) ? " point to point" : "", | 914 | (flag & 0x01) ? " point to point" : "", |
913 | (flag & 0x02) ? " point to multipoint" : "", | 915 | (flag & 0x02) ? " point to multipoint" : "", |
@@ -915,7 +917,7 @@ int b1dmactl_read_proc(char *page, char **start, off_t off, | |||
915 | (flag & 0x04) ? " leased line with D-channel" : "" | 917 | (flag & 0x04) ? " leased line with D-channel" : "" |
916 | ); | 918 | ); |
917 | } | 919 | } |
918 | len += sprintf(page+len, "%-16s %s\n", "cardname", cinfo->cardname); | 920 | seq_printf(m, "%-16s %s\n", "cardname", cinfo->cardname); |
919 | 921 | ||
920 | 922 | ||
921 | spin_lock_irqsave(&card->lock, flags); | 923 | spin_lock_irqsave(&card->lock, flags); |
@@ -930,27 +932,30 @@ int b1dmactl_read_proc(char *page, char **start, off_t off, | |||
930 | 932 | ||
931 | spin_unlock_irqrestore(&card->lock, flags); | 933 | spin_unlock_irqrestore(&card->lock, flags); |
932 | 934 | ||
933 | len += sprintf(page+len, "%-16s 0x%lx\n", | 935 | seq_printf(m, "%-16s 0x%lx\n", "csr (cached)", (unsigned long)card->csr); |
934 | "csr (cached)", (unsigned long)card->csr); | 936 | seq_printf(m, "%-16s 0x%lx\n", "csr", (unsigned long)csr); |
935 | len += sprintf(page+len, "%-16s 0x%lx\n", | 937 | seq_printf(m, "%-16s %lu\n", "txoff", (unsigned long)txoff); |
936 | "csr", (unsigned long)csr); | 938 | seq_printf(m, "%-16s %lu\n", "txlen", (unsigned long)txlen); |
937 | len += sprintf(page+len, "%-16s %lu\n", | 939 | seq_printf(m, "%-16s %lu\n", "rxoff", (unsigned long)rxoff); |
938 | "txoff", (unsigned long)txoff); | 940 | seq_printf(m, "%-16s %lu\n", "rxlen", (unsigned long)rxlen); |
939 | len += sprintf(page+len, "%-16s %lu\n", | 941 | |
940 | "txlen", (unsigned long)txlen); | 942 | return 0; |
941 | len += sprintf(page+len, "%-16s %lu\n", | 943 | } |
942 | "rxoff", (unsigned long)rxoff); | 944 | |
943 | len += sprintf(page+len, "%-16s %lu\n", | 945 | static int b1dmactl_proc_open(struct inode *inode, struct file *file) |
944 | "rxlen", (unsigned long)rxlen); | 946 | { |
945 | 947 | return single_open(file, b1dmactl_proc_show, PDE(inode)->data); | |
946 | if (off+count >= len) | ||
947 | *eof = 1; | ||
948 | if (len < off) | ||
949 | return 0; | ||
950 | *start = page + off; | ||
951 | return ((count < len-off) ? count : len-off); | ||
952 | } | 948 | } |
953 | 949 | ||
950 | const struct file_operations b1dmactl_proc_fops = { | ||
951 | .owner = THIS_MODULE, | ||
952 | .open = b1dmactl_proc_open, | ||
953 | .read = seq_read, | ||
954 | .llseek = seq_lseek, | ||
955 | .release = single_release, | ||
956 | }; | ||
957 | EXPORT_SYMBOL(b1dmactl_proc_fops); | ||
958 | |||
954 | /* ------------------------------------------------------------- */ | 959 | /* ------------------------------------------------------------- */ |
955 | 960 | ||
956 | EXPORT_SYMBOL(b1dma_reset); | 961 | EXPORT_SYMBOL(b1dma_reset); |
@@ -963,7 +968,6 @@ EXPORT_SYMBOL(b1dma_reset_ctr); | |||
963 | EXPORT_SYMBOL(b1dma_register_appl); | 968 | EXPORT_SYMBOL(b1dma_register_appl); |
964 | EXPORT_SYMBOL(b1dma_release_appl); | 969 | EXPORT_SYMBOL(b1dma_release_appl); |
965 | EXPORT_SYMBOL(b1dma_send_message); | 970 | EXPORT_SYMBOL(b1dma_send_message); |
966 | EXPORT_SYMBOL(b1dmactl_read_proc); | ||
967 | 971 | ||
968 | static int __init b1dma_init(void) | 972 | static int __init b1dma_init(void) |
969 | { | 973 | { |
diff --git a/drivers/isdn/hardware/avm/b1isa.c b/drivers/isdn/hardware/avm/b1isa.c index 6461a32bc838..ff5390546f92 100644 --- a/drivers/isdn/hardware/avm/b1isa.c +++ b/drivers/isdn/hardware/avm/b1isa.c | |||
@@ -121,7 +121,7 @@ static int b1isa_probe(struct pci_dev *pdev) | |||
121 | cinfo->capi_ctrl.load_firmware = b1_load_firmware; | 121 | cinfo->capi_ctrl.load_firmware = b1_load_firmware; |
122 | cinfo->capi_ctrl.reset_ctr = b1_reset_ctr; | 122 | cinfo->capi_ctrl.reset_ctr = b1_reset_ctr; |
123 | cinfo->capi_ctrl.procinfo = b1isa_procinfo; | 123 | cinfo->capi_ctrl.procinfo = b1isa_procinfo; |
124 | cinfo->capi_ctrl.ctr_read_proc = b1ctl_read_proc; | 124 | cinfo->capi_ctrl.proc_fops = &b1ctl_proc_fops; |
125 | strcpy(cinfo->capi_ctrl.name, card->name); | 125 | strcpy(cinfo->capi_ctrl.name, card->name); |
126 | 126 | ||
127 | retval = attach_capi_ctr(&cinfo->capi_ctrl); | 127 | retval = attach_capi_ctr(&cinfo->capi_ctrl); |
diff --git a/drivers/isdn/hardware/avm/b1pci.c b/drivers/isdn/hardware/avm/b1pci.c index 5b314a2c4049..c97e4315079d 100644 --- a/drivers/isdn/hardware/avm/b1pci.c +++ b/drivers/isdn/hardware/avm/b1pci.c | |||
@@ -112,7 +112,7 @@ static int b1pci_probe(struct capicardparams *p, struct pci_dev *pdev) | |||
112 | cinfo->capi_ctrl.load_firmware = b1_load_firmware; | 112 | cinfo->capi_ctrl.load_firmware = b1_load_firmware; |
113 | cinfo->capi_ctrl.reset_ctr = b1_reset_ctr; | 113 | cinfo->capi_ctrl.reset_ctr = b1_reset_ctr; |
114 | cinfo->capi_ctrl.procinfo = b1pci_procinfo; | 114 | cinfo->capi_ctrl.procinfo = b1pci_procinfo; |
115 | cinfo->capi_ctrl.ctr_read_proc = b1ctl_read_proc; | 115 | cinfo->capi_ctrl.proc_fops = &b1ctl_proc_fops; |
116 | strcpy(cinfo->capi_ctrl.name, card->name); | 116 | strcpy(cinfo->capi_ctrl.name, card->name); |
117 | cinfo->capi_ctrl.owner = THIS_MODULE; | 117 | cinfo->capi_ctrl.owner = THIS_MODULE; |
118 | 118 | ||
@@ -251,7 +251,7 @@ static int b1pciv4_probe(struct capicardparams *p, struct pci_dev *pdev) | |||
251 | cinfo->capi_ctrl.load_firmware = b1dma_load_firmware; | 251 | cinfo->capi_ctrl.load_firmware = b1dma_load_firmware; |
252 | cinfo->capi_ctrl.reset_ctr = b1dma_reset_ctr; | 252 | cinfo->capi_ctrl.reset_ctr = b1dma_reset_ctr; |
253 | cinfo->capi_ctrl.procinfo = b1pciv4_procinfo; | 253 | cinfo->capi_ctrl.procinfo = b1pciv4_procinfo; |
254 | cinfo->capi_ctrl.ctr_read_proc = b1dmactl_read_proc; | 254 | cinfo->capi_ctrl.proc_fops = &b1dmactl_proc_fops; |
255 | strcpy(cinfo->capi_ctrl.name, card->name); | 255 | strcpy(cinfo->capi_ctrl.name, card->name); |
256 | 256 | ||
257 | retval = attach_capi_ctr(&cinfo->capi_ctrl); | 257 | retval = attach_capi_ctr(&cinfo->capi_ctrl); |
diff --git a/drivers/isdn/hardware/avm/b1pcmcia.c b/drivers/isdn/hardware/avm/b1pcmcia.c index 7740403b40e1..d6391e0afeea 100644 --- a/drivers/isdn/hardware/avm/b1pcmcia.c +++ b/drivers/isdn/hardware/avm/b1pcmcia.c | |||
@@ -108,7 +108,7 @@ static int b1pcmcia_add_card(unsigned int port, unsigned irq, | |||
108 | cinfo->capi_ctrl.load_firmware = b1_load_firmware; | 108 | cinfo->capi_ctrl.load_firmware = b1_load_firmware; |
109 | cinfo->capi_ctrl.reset_ctr = b1_reset_ctr; | 109 | cinfo->capi_ctrl.reset_ctr = b1_reset_ctr; |
110 | cinfo->capi_ctrl.procinfo = b1pcmcia_procinfo; | 110 | cinfo->capi_ctrl.procinfo = b1pcmcia_procinfo; |
111 | cinfo->capi_ctrl.ctr_read_proc = b1ctl_read_proc; | 111 | cinfo->capi_ctrl.proc_fops = &b1ctl_proc_fops; |
112 | strcpy(cinfo->capi_ctrl.name, card->name); | 112 | strcpy(cinfo->capi_ctrl.name, card->name); |
113 | 113 | ||
114 | retval = attach_capi_ctr(&cinfo->capi_ctrl); | 114 | retval = attach_capi_ctr(&cinfo->capi_ctrl); |
diff --git a/drivers/isdn/hardware/avm/c4.c b/drivers/isdn/hardware/avm/c4.c index 6833301a45fc..7715d3242ec8 100644 --- a/drivers/isdn/hardware/avm/c4.c +++ b/drivers/isdn/hardware/avm/c4.c | |||
@@ -11,6 +11,8 @@ | |||
11 | 11 | ||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/proc_fs.h> | ||
15 | #include <linux/seq_file.h> | ||
14 | #include <linux/skbuff.h> | 16 | #include <linux/skbuff.h> |
15 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
16 | #include <linux/mm.h> | 18 | #include <linux/mm.h> |
@@ -20,6 +22,7 @@ | |||
20 | #include <linux/capi.h> | 22 | #include <linux/capi.h> |
21 | #include <linux/kernelcapi.h> | 23 | #include <linux/kernelcapi.h> |
22 | #include <linux/init.h> | 24 | #include <linux/init.h> |
25 | #include <linux/gfp.h> | ||
23 | #include <asm/io.h> | 26 | #include <asm/io.h> |
24 | #include <asm/uaccess.h> | 27 | #include <asm/uaccess.h> |
25 | #include <linux/netdevice.h> | 28 | #include <linux/netdevice.h> |
@@ -1062,19 +1065,18 @@ static char *c4_procinfo(struct capi_ctr *ctrl) | |||
1062 | return cinfo->infobuf; | 1065 | return cinfo->infobuf; |
1063 | } | 1066 | } |
1064 | 1067 | ||
1065 | static int c4_read_proc(char *page, char **start, off_t off, | 1068 | static int c4_proc_show(struct seq_file *m, void *v) |
1066 | int count, int *eof, struct capi_ctr *ctrl) | ||
1067 | { | 1069 | { |
1070 | struct capi_ctr *ctrl = m->private; | ||
1068 | avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); | 1071 | avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); |
1069 | avmcard *card = cinfo->card; | 1072 | avmcard *card = cinfo->card; |
1070 | u8 flag; | 1073 | u8 flag; |
1071 | int len = 0; | ||
1072 | char *s; | 1074 | char *s; |
1073 | 1075 | ||
1074 | len += sprintf(page+len, "%-16s %s\n", "name", card->name); | 1076 | seq_printf(m, "%-16s %s\n", "name", card->name); |
1075 | len += sprintf(page+len, "%-16s 0x%x\n", "io", card->port); | 1077 | seq_printf(m, "%-16s 0x%x\n", "io", card->port); |
1076 | len += sprintf(page+len, "%-16s %d\n", "irq", card->irq); | 1078 | seq_printf(m, "%-16s %d\n", "irq", card->irq); |
1077 | len += sprintf(page+len, "%-16s 0x%lx\n", "membase", card->membase); | 1079 | seq_printf(m, "%-16s 0x%lx\n", "membase", card->membase); |
1078 | switch (card->cardtype) { | 1080 | switch (card->cardtype) { |
1079 | case avm_b1isa: s = "B1 ISA"; break; | 1081 | case avm_b1isa: s = "B1 ISA"; break; |
1080 | case avm_b1pci: s = "B1 PCI"; break; | 1082 | case avm_b1pci: s = "B1 PCI"; break; |
@@ -1087,18 +1089,18 @@ static int c4_read_proc(char *page, char **start, off_t off, | |||
1087 | case avm_c2: s = "C2"; break; | 1089 | case avm_c2: s = "C2"; break; |
1088 | default: s = "???"; break; | 1090 | default: s = "???"; break; |
1089 | } | 1091 | } |
1090 | len += sprintf(page+len, "%-16s %s\n", "type", s); | 1092 | seq_printf(m, "%-16s %s\n", "type", s); |
1091 | if ((s = cinfo->version[VER_DRIVER]) != NULL) | 1093 | if ((s = cinfo->version[VER_DRIVER]) != NULL) |
1092 | len += sprintf(page+len, "%-16s %s\n", "ver_driver", s); | 1094 | seq_printf(m, "%-16s %s\n", "ver_driver", s); |
1093 | if ((s = cinfo->version[VER_CARDTYPE]) != NULL) | 1095 | if ((s = cinfo->version[VER_CARDTYPE]) != NULL) |
1094 | len += sprintf(page+len, "%-16s %s\n", "ver_cardtype", s); | 1096 | seq_printf(m, "%-16s %s\n", "ver_cardtype", s); |
1095 | if ((s = cinfo->version[VER_SERIAL]) != NULL) | 1097 | if ((s = cinfo->version[VER_SERIAL]) != NULL) |
1096 | len += sprintf(page+len, "%-16s %s\n", "ver_serial", s); | 1098 | seq_printf(m, "%-16s %s\n", "ver_serial", s); |
1097 | 1099 | ||
1098 | if (card->cardtype != avm_m1) { | 1100 | if (card->cardtype != avm_m1) { |
1099 | flag = ((u8 *)(ctrl->profile.manu))[3]; | 1101 | flag = ((u8 *)(ctrl->profile.manu))[3]; |
1100 | if (flag) | 1102 | if (flag) |
1101 | len += sprintf(page+len, "%-16s%s%s%s%s%s%s%s\n", | 1103 | seq_printf(m, "%-16s%s%s%s%s%s%s%s\n", |
1102 | "protocol", | 1104 | "protocol", |
1103 | (flag & 0x01) ? " DSS1" : "", | 1105 | (flag & 0x01) ? " DSS1" : "", |
1104 | (flag & 0x02) ? " CT1" : "", | 1106 | (flag & 0x02) ? " CT1" : "", |
@@ -1112,7 +1114,7 @@ static int c4_read_proc(char *page, char **start, off_t off, | |||
1112 | if (card->cardtype != avm_m1) { | 1114 | if (card->cardtype != avm_m1) { |
1113 | flag = ((u8 *)(ctrl->profile.manu))[5]; | 1115 | flag = ((u8 *)(ctrl->profile.manu))[5]; |
1114 | if (flag) | 1116 | if (flag) |
1115 | len += sprintf(page+len, "%-16s%s%s%s%s\n", | 1117 | seq_printf(m, "%-16s%s%s%s%s\n", |
1116 | "linetype", | 1118 | "linetype", |
1117 | (flag & 0x01) ? " point to point" : "", | 1119 | (flag & 0x01) ? " point to point" : "", |
1118 | (flag & 0x02) ? " point to multipoint" : "", | 1120 | (flag & 0x02) ? " point to multipoint" : "", |
@@ -1120,16 +1122,24 @@ static int c4_read_proc(char *page, char **start, off_t off, | |||
1120 | (flag & 0x04) ? " leased line with D-channel" : "" | 1122 | (flag & 0x04) ? " leased line with D-channel" : "" |
1121 | ); | 1123 | ); |
1122 | } | 1124 | } |
1123 | len += sprintf(page+len, "%-16s %s\n", "cardname", cinfo->cardname); | 1125 | seq_printf(m, "%-16s %s\n", "cardname", cinfo->cardname); |
1124 | 1126 | ||
1125 | if (off+count >= len) | 1127 | return 0; |
1126 | *eof = 1; | ||
1127 | if (len < off) | ||
1128 | return 0; | ||
1129 | *start = page + off; | ||
1130 | return ((count < len-off) ? count : len-off); | ||
1131 | } | 1128 | } |
1132 | 1129 | ||
1130 | static int c4_proc_open(struct inode *inode, struct file *file) | ||
1131 | { | ||
1132 | return single_open(file, c4_proc_show, PDE(inode)->data); | ||
1133 | } | ||
1134 | |||
1135 | static const struct file_operations c4_proc_fops = { | ||
1136 | .owner = THIS_MODULE, | ||
1137 | .open = c4_proc_open, | ||
1138 | .read = seq_read, | ||
1139 | .llseek = seq_lseek, | ||
1140 | .release = single_release, | ||
1141 | }; | ||
1142 | |||
1133 | /* ------------------------------------------------------------- */ | 1143 | /* ------------------------------------------------------------- */ |
1134 | 1144 | ||
1135 | static int c4_add_card(struct capicardparams *p, struct pci_dev *dev, | 1145 | static int c4_add_card(struct capicardparams *p, struct pci_dev *dev, |
@@ -1201,7 +1211,7 @@ static int c4_add_card(struct capicardparams *p, struct pci_dev *dev, | |||
1201 | cinfo->capi_ctrl.load_firmware = c4_load_firmware; | 1211 | cinfo->capi_ctrl.load_firmware = c4_load_firmware; |
1202 | cinfo->capi_ctrl.reset_ctr = c4_reset_ctr; | 1212 | cinfo->capi_ctrl.reset_ctr = c4_reset_ctr; |
1203 | cinfo->capi_ctrl.procinfo = c4_procinfo; | 1213 | cinfo->capi_ctrl.procinfo = c4_procinfo; |
1204 | cinfo->capi_ctrl.ctr_read_proc = c4_read_proc; | 1214 | cinfo->capi_ctrl.proc_fops = &c4_proc_fops; |
1205 | strcpy(cinfo->capi_ctrl.name, card->name); | 1215 | strcpy(cinfo->capi_ctrl.name, card->name); |
1206 | 1216 | ||
1207 | retval = attach_capi_ctr(&cinfo->capi_ctrl); | 1217 | retval = attach_capi_ctr(&cinfo->capi_ctrl); |
diff --git a/drivers/isdn/hardware/avm/t1isa.c b/drivers/isdn/hardware/avm/t1isa.c index 1c53fd49adb6..08216b14be13 100644 --- a/drivers/isdn/hardware/avm/t1isa.c +++ b/drivers/isdn/hardware/avm/t1isa.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/kernelcapi.h> | 21 | #include <linux/kernelcapi.h> |
22 | #include <linux/init.h> | 22 | #include <linux/init.h> |
23 | #include <linux/pci.h> | 23 | #include <linux/pci.h> |
24 | #include <linux/gfp.h> | ||
24 | #include <asm/io.h> | 25 | #include <asm/io.h> |
25 | #include <linux/isdn/capicmd.h> | 26 | #include <linux/isdn/capicmd.h> |
26 | #include <linux/isdn/capiutil.h> | 27 | #include <linux/isdn/capiutil.h> |
@@ -429,7 +430,7 @@ static int t1isa_probe(struct pci_dev *pdev, int cardnr) | |||
429 | cinfo->capi_ctrl.load_firmware = t1isa_load_firmware; | 430 | cinfo->capi_ctrl.load_firmware = t1isa_load_firmware; |
430 | cinfo->capi_ctrl.reset_ctr = t1isa_reset_ctr; | 431 | cinfo->capi_ctrl.reset_ctr = t1isa_reset_ctr; |
431 | cinfo->capi_ctrl.procinfo = t1isa_procinfo; | 432 | cinfo->capi_ctrl.procinfo = t1isa_procinfo; |
432 | cinfo->capi_ctrl.ctr_read_proc = b1ctl_read_proc; | 433 | cinfo->capi_ctrl.proc_fops = &b1ctl_proc_fops; |
433 | strcpy(cinfo->capi_ctrl.name, card->name); | 434 | strcpy(cinfo->capi_ctrl.name, card->name); |
434 | 435 | ||
435 | retval = attach_capi_ctr(&cinfo->capi_ctrl); | 436 | retval = attach_capi_ctr(&cinfo->capi_ctrl); |
diff --git a/drivers/isdn/hardware/avm/t1pci.c b/drivers/isdn/hardware/avm/t1pci.c index e6d298d75146..5a3f83098018 100644 --- a/drivers/isdn/hardware/avm/t1pci.c +++ b/drivers/isdn/hardware/avm/t1pci.c | |||
@@ -119,7 +119,7 @@ static int t1pci_add_card(struct capicardparams *p, struct pci_dev *pdev) | |||
119 | cinfo->capi_ctrl.load_firmware = b1dma_load_firmware; | 119 | cinfo->capi_ctrl.load_firmware = b1dma_load_firmware; |
120 | cinfo->capi_ctrl.reset_ctr = b1dma_reset_ctr; | 120 | cinfo->capi_ctrl.reset_ctr = b1dma_reset_ctr; |
121 | cinfo->capi_ctrl.procinfo = t1pci_procinfo; | 121 | cinfo->capi_ctrl.procinfo = t1pci_procinfo; |
122 | cinfo->capi_ctrl.ctr_read_proc = b1dmactl_read_proc; | 122 | cinfo->capi_ctrl.proc_fops = &b1dmactl_proc_fops; |
123 | strcpy(cinfo->capi_ctrl.name, card->name); | 123 | strcpy(cinfo->capi_ctrl.name, card->name); |
124 | 124 | ||
125 | retval = attach_capi_ctr(&cinfo->capi_ctrl); | 125 | retval = attach_capi_ctr(&cinfo->capi_ctrl); |
diff --git a/drivers/isdn/hardware/eicon/capimain.c b/drivers/isdn/hardware/eicon/capimain.c index 98fcdfc7ca55..97a20964cfc7 100644 --- a/drivers/isdn/hardware/eicon/capimain.c +++ b/drivers/isdn/hardware/eicon/capimain.c | |||
@@ -11,8 +11,10 @@ | |||
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/slab.h> | ||
14 | #include <linux/init.h> | 15 | #include <linux/init.h> |
15 | #include <asm/uaccess.h> | 16 | #include <asm/uaccess.h> |
17 | #include <linux/seq_file.h> | ||
16 | #include <linux/skbuff.h> | 18 | #include <linux/skbuff.h> |
17 | 19 | ||
18 | #include "os_capi.h" | 20 | #include "os_capi.h" |
@@ -75,25 +77,32 @@ void diva_os_free_message_buffer(diva_os_message_buffer_s * dmb) | |||
75 | /* | 77 | /* |
76 | * proc function for controller info | 78 | * proc function for controller info |
77 | */ | 79 | */ |
78 | static int diva_ctl_read_proc(char *page, char **start, off_t off, | 80 | static int diva_ctl_proc_show(struct seq_file *m, void *v) |
79 | int count, int *eof, struct capi_ctr *ctrl) | ||
80 | { | 81 | { |
82 | struct capi_ctr *ctrl = m->private; | ||
81 | diva_card *card = (diva_card *) ctrl->driverdata; | 83 | diva_card *card = (diva_card *) ctrl->driverdata; |
82 | int len = 0; | 84 | |
83 | 85 | seq_printf(m, "%s\n", ctrl->name); | |
84 | len += sprintf(page + len, "%s\n", ctrl->name); | 86 | seq_printf(m, "Serial No. : %s\n", ctrl->serial); |
85 | len += sprintf(page + len, "Serial No. : %s\n", ctrl->serial); | 87 | seq_printf(m, "Id : %d\n", card->Id); |
86 | len += sprintf(page + len, "Id : %d\n", card->Id); | 88 | seq_printf(m, "Channels : %d\n", card->d.channels); |
87 | len += sprintf(page + len, "Channels : %d\n", card->d.channels); | 89 | |
88 | 90 | return 0; | |
89 | if (off + count >= len) | 91 | } |
90 | *eof = 1; | 92 | |
91 | if (len < off) | 93 | static int diva_ctl_proc_open(struct inode *inode, struct file *file) |
92 | return 0; | 94 | { |
93 | *start = page + off; | 95 | return single_open(file, diva_ctl_proc_show, NULL); |
94 | return ((count < len - off) ? count : len - off); | ||
95 | } | 96 | } |
96 | 97 | ||
98 | static const struct file_operations diva_ctl_proc_fops = { | ||
99 | .owner = THIS_MODULE, | ||
100 | .open = diva_ctl_proc_open, | ||
101 | .read = seq_read, | ||
102 | .llseek = seq_lseek, | ||
103 | .release = single_release, | ||
104 | }; | ||
105 | |||
97 | /* | 106 | /* |
98 | * set additional os settings in capi_ctr struct | 107 | * set additional os settings in capi_ctr struct |
99 | */ | 108 | */ |
@@ -102,7 +111,7 @@ void diva_os_set_controller_struct(struct capi_ctr *ctrl) | |||
102 | ctrl->driver_name = DRIVERLNAME; | 111 | ctrl->driver_name = DRIVERLNAME; |
103 | ctrl->load_firmware = NULL; | 112 | ctrl->load_firmware = NULL; |
104 | ctrl->reset_ctr = NULL; | 113 | ctrl->reset_ctr = NULL; |
105 | ctrl->ctr_read_proc = diva_ctl_read_proc; | 114 | ctrl->proc_fops = &diva_ctl_proc_fops; |
106 | ctrl->owner = THIS_MODULE; | 115 | ctrl->owner = THIS_MODULE; |
107 | } | 116 | } |
108 | 117 | ||
diff --git a/drivers/isdn/hardware/eicon/di.c b/drivers/isdn/hardware/eicon/di.c index b029d130eb21..cb14ae3e7154 100644 --- a/drivers/isdn/hardware/eicon/di.c +++ b/drivers/isdn/hardware/eicon/di.c | |||
@@ -806,7 +806,7 @@ static void xdi_xlog_request (byte Adapter, byte Id, | |||
806 | DELIVERY - indication entered isdn_rc function | 806 | DELIVERY - indication entered isdn_rc function |
807 | RNR=... - application had returned RNR=... after the | 807 | RNR=... - application had returned RNR=... after the |
808 | look ahead callback | 808 | look ahead callback |
809 | RNum=0 - aplication had not returned any buffer to copy | 809 | RNum=0 - application had not returned any buffer to copy |
810 | this indication and will copy it self | 810 | this indication and will copy it self |
811 | COMPLETE - XDI had copied the data to the buffers provided | 811 | COMPLETE - XDI had copied the data to the buffers provided |
812 | bu the application and is about to issue the | 812 | bu the application and is about to issue the |
diff --git a/drivers/isdn/hardware/eicon/diva_didd.c b/drivers/isdn/hardware/eicon/diva_didd.c index 993b14cf1778..5d06a7437824 100644 --- a/drivers/isdn/hardware/eicon/diva_didd.c +++ b/drivers/isdn/hardware/eicon/diva_didd.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/proc_fs.h> | 17 | #include <linux/proc_fs.h> |
18 | #include <linux/seq_file.h> | ||
18 | #include <net/net_namespace.h> | 19 | #include <net/net_namespace.h> |
19 | 20 | ||
20 | #include "platform.h" | 21 | #include "platform.h" |
@@ -62,39 +63,41 @@ static char *getrev(const char *revision) | |||
62 | return rev; | 63 | return rev; |
63 | } | 64 | } |
64 | 65 | ||
65 | static int | 66 | static int divadidd_proc_show(struct seq_file *m, void *v) |
66 | proc_read(char *page, char **start, off_t off, int count, int *eof, | ||
67 | void *data) | ||
68 | { | 67 | { |
69 | int len = 0; | ||
70 | char tmprev[32]; | 68 | char tmprev[32]; |
71 | 69 | ||
72 | strcpy(tmprev, main_revision); | 70 | strcpy(tmprev, main_revision); |
73 | len += sprintf(page + len, "%s\n", DRIVERNAME); | 71 | seq_printf(m, "%s\n", DRIVERNAME); |
74 | len += sprintf(page + len, "name : %s\n", DRIVERLNAME); | 72 | seq_printf(m, "name : %s\n", DRIVERLNAME); |
75 | len += sprintf(page + len, "release : %s\n", DRIVERRELEASE_DIDD); | 73 | seq_printf(m, "release : %s\n", DRIVERRELEASE_DIDD); |
76 | len += sprintf(page + len, "build : %s(%s)\n", | 74 | seq_printf(m, "build : %s(%s)\n", |
77 | diva_didd_common_code_build, DIVA_BUILD); | 75 | diva_didd_common_code_build, DIVA_BUILD); |
78 | len += sprintf(page + len, "revision : %s\n", getrev(tmprev)); | 76 | seq_printf(m, "revision : %s\n", getrev(tmprev)); |
79 | 77 | ||
80 | if (off + count >= len) | 78 | return 0; |
81 | *eof = 1; | ||
82 | if (len < off) | ||
83 | return 0; | ||
84 | *start = page + off; | ||
85 | return ((count < len - off) ? count : len - off); | ||
86 | } | 79 | } |
87 | 80 | ||
81 | static int divadidd_proc_open(struct inode *inode, struct file *file) | ||
82 | { | ||
83 | return single_open(file, divadidd_proc_show, NULL); | ||
84 | } | ||
85 | |||
86 | static const struct file_operations divadidd_proc_fops = { | ||
87 | .owner = THIS_MODULE, | ||
88 | .open = divadidd_proc_open, | ||
89 | .read = seq_read, | ||
90 | .llseek = seq_lseek, | ||
91 | .release = single_release, | ||
92 | }; | ||
93 | |||
88 | static int DIVA_INIT_FUNCTION create_proc(void) | 94 | static int DIVA_INIT_FUNCTION create_proc(void) |
89 | { | 95 | { |
90 | proc_net_eicon = proc_mkdir("eicon", init_net.proc_net); | 96 | proc_net_eicon = proc_mkdir("eicon", init_net.proc_net); |
91 | 97 | ||
92 | if (proc_net_eicon) { | 98 | if (proc_net_eicon) { |
93 | if ((proc_didd = | 99 | proc_didd = proc_create(DRIVERLNAME, S_IRUGO, proc_net_eicon, |
94 | create_proc_entry(DRIVERLNAME, S_IFREG | S_IRUGO, | 100 | &divadidd_proc_fops); |
95 | proc_net_eicon))) { | ||
96 | proc_didd->read_proc = proc_read; | ||
97 | } | ||
98 | return (1); | 101 | return (1); |
99 | } | 102 | } |
100 | return (0); | 103 | return (0); |
diff --git a/drivers/isdn/hardware/eicon/divasi.c b/drivers/isdn/hardware/eicon/divasi.c index 69e71ebe7841..f577719ab3fa 100644 --- a/drivers/isdn/hardware/eicon/divasi.c +++ b/drivers/isdn/hardware/eicon/divasi.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/poll.h> | 17 | #include <linux/poll.h> |
18 | #include <linux/proc_fs.h> | 18 | #include <linux/proc_fs.h> |
19 | #include <linux/skbuff.h> | 19 | #include <linux/skbuff.h> |
20 | #include <linux/seq_file.h> | ||
20 | #include <linux/smp_lock.h> | 21 | #include <linux/smp_lock.h> |
21 | #include <asm/uaccess.h> | 22 | #include <asm/uaccess.h> |
22 | 23 | ||
@@ -86,39 +87,40 @@ static void diva_um_timer_function(unsigned long data); | |||
86 | extern struct proc_dir_entry *proc_net_eicon; | 87 | extern struct proc_dir_entry *proc_net_eicon; |
87 | static struct proc_dir_entry *um_idi_proc_entry = NULL; | 88 | static struct proc_dir_entry *um_idi_proc_entry = NULL; |
88 | 89 | ||
89 | static int | 90 | static int um_idi_proc_show(struct seq_file *m, void *v) |
90 | um_idi_proc_read(char *page, char **start, off_t off, int count, int *eof, | ||
91 | void *data) | ||
92 | { | 91 | { |
93 | int len = 0; | ||
94 | char tmprev[32]; | 92 | char tmprev[32]; |
95 | 93 | ||
96 | len += sprintf(page + len, "%s\n", DRIVERNAME); | 94 | seq_printf(m, "%s\n", DRIVERNAME); |
97 | len += sprintf(page + len, "name : %s\n", DRIVERLNAME); | 95 | seq_printf(m, "name : %s\n", DRIVERLNAME); |
98 | len += sprintf(page + len, "release : %s\n", DRIVERRELEASE_IDI); | 96 | seq_printf(m, "release : %s\n", DRIVERRELEASE_IDI); |
99 | strcpy(tmprev, main_revision); | 97 | strcpy(tmprev, main_revision); |
100 | len += sprintf(page + len, "revision : %s\n", getrev(tmprev)); | 98 | seq_printf(m, "revision : %s\n", getrev(tmprev)); |
101 | len += sprintf(page + len, "build : %s\n", DIVA_BUILD); | 99 | seq_printf(m, "build : %s\n", DIVA_BUILD); |
102 | len += sprintf(page + len, "major : %d\n", major); | 100 | seq_printf(m, "major : %d\n", major); |
103 | 101 | ||
104 | if (off + count >= len) | 102 | return 0; |
105 | *eof = 1; | 103 | } |
106 | if (len < off) | 104 | |
107 | return 0; | 105 | static int um_idi_proc_open(struct inode *inode, struct file *file) |
108 | *start = page + off; | 106 | { |
109 | return ((count < len - off) ? count : len - off); | 107 | return single_open(file, um_idi_proc_show, NULL); |
110 | } | 108 | } |
111 | 109 | ||
110 | static const struct file_operations um_idi_proc_fops = { | ||
111 | .owner = THIS_MODULE, | ||
112 | .open = um_idi_proc_open, | ||
113 | .read = seq_read, | ||
114 | .llseek = seq_lseek, | ||
115 | .release = single_release, | ||
116 | }; | ||
117 | |||
112 | static int DIVA_INIT_FUNCTION create_um_idi_proc(void) | 118 | static int DIVA_INIT_FUNCTION create_um_idi_proc(void) |
113 | { | 119 | { |
114 | um_idi_proc_entry = create_proc_entry(DRIVERLNAME, | 120 | um_idi_proc_entry = proc_create(DRIVERLNAME, S_IRUGO, proc_net_eicon, |
115 | S_IFREG | S_IRUGO | S_IWUSR, | 121 | &um_idi_proc_fops); |
116 | proc_net_eicon); | ||
117 | if (!um_idi_proc_entry) | 122 | if (!um_idi_proc_entry) |
118 | return (0); | 123 | return (0); |
119 | |||
120 | um_idi_proc_entry->read_proc = um_idi_proc_read; | ||
121 | |||
122 | return (1); | 124 | return (1); |
123 | } | 125 | } |
124 | 126 | ||
diff --git a/drivers/isdn/hardware/eicon/divasproc.c b/drivers/isdn/hardware/eicon/divasproc.c index 040827288ec9..46d44a942624 100644 --- a/drivers/isdn/hardware/eicon/divasproc.c +++ b/drivers/isdn/hardware/eicon/divasproc.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/poll.h> | 15 | #include <linux/poll.h> |
16 | #include <linux/proc_fs.h> | 16 | #include <linux/proc_fs.h> |
17 | #include <linux/seq_file.h> | ||
17 | #include <linux/list.h> | 18 | #include <linux/list.h> |
18 | #include <asm/uaccess.h> | 19 | #include <asm/uaccess.h> |
19 | 20 | ||
@@ -141,14 +142,10 @@ void remove_divas_proc(void) | |||
141 | } | 142 | } |
142 | } | 143 | } |
143 | 144 | ||
144 | /* | 145 | static ssize_t grp_opt_proc_write(struct file *file, const char __user *buffer, |
145 | ** write group_optimization | 146 | size_t count, loff_t *pos) |
146 | */ | ||
147 | static int | ||
148 | write_grp_opt(struct file *file, const char __user *buffer, unsigned long count, | ||
149 | void *data) | ||
150 | { | 147 | { |
151 | diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) data; | 148 | diva_os_xdi_adapter_t *a = PDE(file->f_path.dentry->d_inode)->data; |
152 | PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1]; | 149 | PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1]; |
153 | 150 | ||
154 | if ((count == 1) || (count == 2)) { | 151 | if ((count == 1) || (count == 2)) { |
@@ -172,14 +169,10 @@ write_grp_opt(struct file *file, const char __user *buffer, unsigned long count, | |||
172 | return (-EINVAL); | 169 | return (-EINVAL); |
173 | } | 170 | } |
174 | 171 | ||
175 | /* | 172 | static ssize_t d_l1_down_proc_write(struct file *file, const char __user *buffer, |
176 | ** write dynamic_l1_down | 173 | size_t count, loff_t *pos) |
177 | */ | ||
178 | static int | ||
179 | write_d_l1_down(struct file *file, const char __user *buffer, unsigned long count, | ||
180 | void *data) | ||
181 | { | 174 | { |
182 | diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) data; | 175 | diva_os_xdi_adapter_t *a = PDE(file->f_path.dentry->d_inode)->data; |
183 | PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1]; | 176 | PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1]; |
184 | 177 | ||
185 | if ((count == 1) || (count == 2)) { | 178 | if ((count == 1) || (count == 2)) { |
@@ -203,63 +196,62 @@ write_d_l1_down(struct file *file, const char __user *buffer, unsigned long coun | |||
203 | return (-EINVAL); | 196 | return (-EINVAL); |
204 | } | 197 | } |
205 | 198 | ||
206 | 199 | static int d_l1_down_proc_show(struct seq_file *m, void *v) | |
207 | /* | ||
208 | ** read dynamic_l1_down | ||
209 | */ | ||
210 | static int | ||
211 | read_d_l1_down(char *page, char **start, off_t off, int count, int *eof, | ||
212 | void *data) | ||
213 | { | 200 | { |
214 | int len = 0; | 201 | diva_os_xdi_adapter_t *a = m->private; |
215 | diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) data; | ||
216 | PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1]; | 202 | PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1]; |
217 | 203 | ||
218 | len += sprintf(page + len, "%s\n", | 204 | seq_printf(m, "%s\n", |
219 | (IoAdapter->capi_cfg. | 205 | (IoAdapter->capi_cfg. |
220 | cfg_1 & DIVA_XDI_CAPI_CFG_1_DYNAMIC_L1_ON) ? "1" : | 206 | cfg_1 & DIVA_XDI_CAPI_CFG_1_DYNAMIC_L1_ON) ? "1" : |
221 | "0"); | 207 | "0"); |
208 | return 0; | ||
209 | } | ||
222 | 210 | ||
223 | if (off + count >= len) | 211 | static int d_l1_down_proc_open(struct inode *inode, struct file *file) |
224 | *eof = 1; | 212 | { |
225 | if (len < off) | 213 | return single_open(file, d_l1_down_proc_show, PDE(inode)->data); |
226 | return 0; | ||
227 | *start = page + off; | ||
228 | return ((count < len - off) ? count : len - off); | ||
229 | } | 214 | } |
230 | 215 | ||
231 | /* | 216 | static const struct file_operations d_l1_down_proc_fops = { |
232 | ** read group_optimization | 217 | .owner = THIS_MODULE, |
233 | */ | 218 | .open = d_l1_down_proc_open, |
234 | static int | 219 | .read = seq_read, |
235 | read_grp_opt(char *page, char **start, off_t off, int count, int *eof, | 220 | .llseek = seq_lseek, |
236 | void *data) | 221 | .release = single_release, |
222 | .write = d_l1_down_proc_write, | ||
223 | }; | ||
224 | |||
225 | static int grp_opt_proc_show(struct seq_file *m, void *v) | ||
237 | { | 226 | { |
238 | int len = 0; | 227 | diva_os_xdi_adapter_t *a = m->private; |
239 | diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) data; | ||
240 | PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1]; | 228 | PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1]; |
241 | 229 | ||
242 | len += sprintf(page + len, "%s\n", | 230 | seq_printf(m, "%s\n", |
243 | (IoAdapter->capi_cfg. | 231 | (IoAdapter->capi_cfg. |
244 | cfg_1 & DIVA_XDI_CAPI_CFG_1_GROUP_POPTIMIZATION_ON) | 232 | cfg_1 & DIVA_XDI_CAPI_CFG_1_GROUP_POPTIMIZATION_ON) |
245 | ? "1" : "0"); | 233 | ? "1" : "0"); |
234 | return 0; | ||
235 | } | ||
246 | 236 | ||
247 | if (off + count >= len) | 237 | static int grp_opt_proc_open(struct inode *inode, struct file *file) |
248 | *eof = 1; | 238 | { |
249 | if (len < off) | 239 | return single_open(file, grp_opt_proc_show, PDE(inode)->data); |
250 | return 0; | ||
251 | *start = page + off; | ||
252 | return ((count < len - off) ? count : len - off); | ||
253 | } | 240 | } |
254 | 241 | ||
255 | /* | 242 | static const struct file_operations grp_opt_proc_fops = { |
256 | ** info write | 243 | .owner = THIS_MODULE, |
257 | */ | 244 | .open = grp_opt_proc_open, |
258 | static int | 245 | .read = seq_read, |
259 | info_write(struct file *file, const char __user *buffer, unsigned long count, | 246 | .llseek = seq_lseek, |
260 | void *data) | 247 | .release = single_release, |
248 | .write = grp_opt_proc_write, | ||
249 | }; | ||
250 | |||
251 | static ssize_t info_proc_write(struct file *file, const char __user *buffer, | ||
252 | size_t count, loff_t *pos) | ||
261 | { | 253 | { |
262 | diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) data; | 254 | diva_os_xdi_adapter_t *a = PDE(file->f_path.dentry->d_inode)->data; |
263 | PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1]; | 255 | PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1]; |
264 | char c[4]; | 256 | char c[4]; |
265 | 257 | ||
@@ -277,63 +269,46 @@ info_write(struct file *file, const char __user *buffer, unsigned long count, | |||
277 | return (-EINVAL); | 269 | return (-EINVAL); |
278 | } | 270 | } |
279 | 271 | ||
280 | /* | 272 | static int info_proc_show(struct seq_file *m, void *v) |
281 | ** info read | ||
282 | */ | ||
283 | static int | ||
284 | info_read(char *page, char **start, off_t off, int count, int *eof, | ||
285 | void *data) | ||
286 | { | 273 | { |
287 | int i = 0; | 274 | int i = 0; |
288 | int len = 0; | ||
289 | char *p; | 275 | char *p; |
290 | char tmpser[16]; | 276 | char tmpser[16]; |
291 | diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) data; | 277 | diva_os_xdi_adapter_t *a = m->private; |
292 | PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1]; | 278 | PISDN_ADAPTER IoAdapter = IoAdapters[a->controller - 1]; |
293 | 279 | ||
294 | len += | 280 | seq_printf(m, "Name : %s\n", IoAdapter->Properties.Name); |
295 | sprintf(page + len, "Name : %s\n", | 281 | seq_printf(m, "DSP state : %08x\n", a->dsp_mask); |
296 | IoAdapter->Properties.Name); | 282 | seq_printf(m, "Channels : %02d\n", IoAdapter->Properties.Channels); |
297 | len += sprintf(page + len, "DSP state : %08x\n", a->dsp_mask); | 283 | seq_printf(m, "E. max/used : %03d/%03d\n", |
298 | len += sprintf(page + len, "Channels : %02d\n", | ||
299 | IoAdapter->Properties.Channels); | ||
300 | len += sprintf(page + len, "E. max/used : %03d/%03d\n", | ||
301 | IoAdapter->e_max, IoAdapter->e_count); | 284 | IoAdapter->e_max, IoAdapter->e_count); |
302 | diva_get_vserial_number(IoAdapter, tmpser); | 285 | diva_get_vserial_number(IoAdapter, tmpser); |
303 | len += sprintf(page + len, "Serial : %s\n", tmpser); | 286 | seq_printf(m, "Serial : %s\n", tmpser); |
304 | len += | 287 | seq_printf(m, "IRQ : %d\n", IoAdapter->irq_info.irq_nr); |
305 | sprintf(page + len, "IRQ : %d\n", | 288 | seq_printf(m, "CardIndex : %d\n", a->CardIndex); |
306 | IoAdapter->irq_info.irq_nr); | 289 | seq_printf(m, "CardOrdinal : %d\n", a->CardOrdinal); |
307 | len += sprintf(page + len, "CardIndex : %d\n", a->CardIndex); | 290 | seq_printf(m, "Controller : %d\n", a->controller); |
308 | len += sprintf(page + len, "CardOrdinal : %d\n", a->CardOrdinal); | 291 | seq_printf(m, "Bus-Type : %s\n", |
309 | len += sprintf(page + len, "Controller : %d\n", a->controller); | ||
310 | len += sprintf(page + len, "Bus-Type : %s\n", | ||
311 | (a->Bus == | 292 | (a->Bus == |
312 | DIVAS_XDI_ADAPTER_BUS_ISA) ? "ISA" : "PCI"); | 293 | DIVAS_XDI_ADAPTER_BUS_ISA) ? "ISA" : "PCI"); |
313 | len += sprintf(page + len, "Port-Name : %s\n", a->port_name); | 294 | seq_printf(m, "Port-Name : %s\n", a->port_name); |
314 | if (a->Bus == DIVAS_XDI_ADAPTER_BUS_PCI) { | 295 | if (a->Bus == DIVAS_XDI_ADAPTER_BUS_PCI) { |
315 | len += | 296 | seq_printf(m, "PCI-bus : %d\n", a->resources.pci.bus); |
316 | sprintf(page + len, "PCI-bus : %d\n", | 297 | seq_printf(m, "PCI-func : %d\n", a->resources.pci.func); |
317 | a->resources.pci.bus); | ||
318 | len += | ||
319 | sprintf(page + len, "PCI-func : %d\n", | ||
320 | a->resources.pci.func); | ||
321 | for (i = 0; i < 8; i++) { | 298 | for (i = 0; i < 8; i++) { |
322 | if (a->resources.pci.bar[i]) { | 299 | if (a->resources.pci.bar[i]) { |
323 | len += | 300 | seq_printf(m, |
324 | sprintf(page + len, | ||
325 | "Mem / I/O %d : 0x%x / mapped : 0x%lx", | 301 | "Mem / I/O %d : 0x%x / mapped : 0x%lx", |
326 | i, a->resources.pci.bar[i], | 302 | i, a->resources.pci.bar[i], |
327 | (unsigned long) a->resources. | 303 | (unsigned long) a->resources. |
328 | pci.addr[i]); | 304 | pci.addr[i]); |
329 | if (a->resources.pci.length[i]) { | 305 | if (a->resources.pci.length[i]) { |
330 | len += | 306 | seq_printf(m, |
331 | sprintf(page + len, | ||
332 | " / length : %d", | 307 | " / length : %d", |
333 | a->resources.pci. | 308 | a->resources.pci. |
334 | length[i]); | 309 | length[i]); |
335 | } | 310 | } |
336 | len += sprintf(page + len, "\n"); | 311 | seq_putc(m, '\n'); |
337 | } | 312 | } |
338 | } | 313 | } |
339 | } | 314 | } |
@@ -353,16 +328,25 @@ info_read(char *page, char **start, off_t off, int count, int *eof, | |||
353 | } else { | 328 | } else { |
354 | p = "ready"; | 329 | p = "ready"; |
355 | } | 330 | } |
356 | len += sprintf(page + len, "State : %s\n", p); | 331 | seq_printf(m, "State : %s\n", p); |
357 | 332 | ||
358 | if (off + count >= len) | 333 | return 0; |
359 | *eof = 1; | 334 | } |
360 | if (len < off) | 335 | |
361 | return 0; | 336 | static int info_proc_open(struct inode *inode, struct file *file) |
362 | *start = page + off; | 337 | { |
363 | return ((count < len - off) ? count : len - off); | 338 | return single_open(file, info_proc_show, PDE(inode)->data); |
364 | } | 339 | } |
365 | 340 | ||
341 | static const struct file_operations info_proc_fops = { | ||
342 | .owner = THIS_MODULE, | ||
343 | .open = info_proc_open, | ||
344 | .read = seq_read, | ||
345 | .llseek = seq_lseek, | ||
346 | .release = single_release, | ||
347 | .write = info_proc_write, | ||
348 | }; | ||
349 | |||
366 | /* | 350 | /* |
367 | ** adapter proc init/de-init | 351 | ** adapter proc init/de-init |
368 | */ | 352 | */ |
@@ -380,28 +364,20 @@ int create_adapter_proc(diva_os_xdi_adapter_t * a) | |||
380 | return (0); | 364 | return (0); |
381 | a->proc_adapter_dir = (void *) de; | 365 | a->proc_adapter_dir = (void *) de; |
382 | 366 | ||
383 | if (!(pe = | 367 | pe = proc_create_data(info_proc_name, S_IRUGO | S_IWUSR, de, |
384 | create_proc_entry(info_proc_name, S_IFREG | S_IRUGO | S_IWUSR, de))) | 368 | &info_proc_fops, a); |
369 | if (!pe) | ||
385 | return (0); | 370 | return (0); |
386 | a->proc_info = (void *) pe; | 371 | a->proc_info = (void *) pe; |
387 | pe->write_proc = info_write; | ||
388 | pe->read_proc = info_read; | ||
389 | pe->data = a; | ||
390 | 372 | ||
391 | if ((pe = create_proc_entry(grp_opt_proc_name, | 373 | pe = proc_create_data(grp_opt_proc_name, S_IRUGO | S_IWUSR, de, |
392 | S_IFREG | S_IRUGO | S_IWUSR, de))) { | 374 | &grp_opt_proc_fops, a); |
375 | if (pe) | ||
393 | a->proc_grp_opt = (void *) pe; | 376 | a->proc_grp_opt = (void *) pe; |
394 | pe->write_proc = write_grp_opt; | 377 | pe = proc_create_data(d_l1_down_proc_name, S_IRUGO | S_IWUSR, de, |
395 | pe->read_proc = read_grp_opt; | 378 | &d_l1_down_proc_fops, a); |
396 | pe->data = a; | 379 | if (pe) |
397 | } | ||
398 | if ((pe = create_proc_entry(d_l1_down_proc_name, | ||
399 | S_IFREG | S_IRUGO | S_IWUSR, de))) { | ||
400 | a->proc_d_l1_down = (void *) pe; | 380 | a->proc_d_l1_down = (void *) pe; |
401 | pe->write_proc = write_d_l1_down; | ||
402 | pe->read_proc = read_d_l1_down; | ||
403 | pe->data = a; | ||
404 | } | ||
405 | 381 | ||
406 | DBG_TRC(("proc entry %s created", tmp)); | 382 | DBG_TRC(("proc entry %s created", tmp)); |
407 | 383 | ||
diff --git a/drivers/isdn/hardware/eicon/maintidi.c b/drivers/isdn/hardware/eicon/maintidi.c index 41c26e756452..534978bdf382 100644 --- a/drivers/isdn/hardware/eicon/maintidi.c +++ b/drivers/isdn/hardware/eicon/maintidi.c | |||
@@ -385,7 +385,7 @@ static int SuperTraceMessageInput (void* hLib) { | |||
385 | } | 385 | } |
386 | break; | 386 | break; |
387 | default: | 387 | default: |
388 | diva_mnt_internal_dprintf (0, DLI_ERR, "Unknon IDI Ind (DMA mode): %02x", Ind); | 388 | diva_mnt_internal_dprintf (0, DLI_ERR, "Unknown IDI Ind (DMA mode): %02x", Ind); |
389 | } | 389 | } |
390 | p += (this_ind_length+1); | 390 | p += (this_ind_length+1); |
391 | total_length -= (4 + this_ind_length); | 391 | total_length -= (4 + this_ind_length); |
@@ -420,7 +420,7 @@ static int SuperTraceMessageInput (void* hLib) { | |||
420 | } | 420 | } |
421 | break; | 421 | break; |
422 | default: | 422 | default: |
423 | diva_mnt_internal_dprintf (0, DLI_ERR, "Unknon IDI Ind: %02x", Ind); | 423 | diva_mnt_internal_dprintf (0, DLI_ERR, "Unknown IDI Ind: %02x", Ind); |
424 | } | 424 | } |
425 | } | 425 | } |
426 | } | 426 | } |
diff --git a/drivers/isdn/hardware/eicon/message.c b/drivers/isdn/hardware/eicon/message.c index ae89fb89da64..341ef17c22ac 100644 --- a/drivers/isdn/hardware/eicon/message.c +++ b/drivers/isdn/hardware/eicon/message.c | |||
@@ -2754,7 +2754,7 @@ static byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a, | |||
2754 | for (i = 0; i < w; i++) | 2754 | for (i = 0; i < w; i++) |
2755 | ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id[i] = fax_parms[4].info[1+i]; | 2755 | ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id[i] = fax_parms[4].info[1+i]; |
2756 | ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0; | 2756 | ((T30_INFO *)(plci->fax_connect_info_buffer))->head_line_len = 0; |
2757 | len = offsetof(T30_INFO, station_id) + 20; | 2757 | len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH; |
2758 | w = fax_parms[5].length; | 2758 | w = fax_parms[5].length; |
2759 | if (w > 20) | 2759 | if (w > 20) |
2760 | w = 20; | 2760 | w = 20; |
@@ -2892,7 +2892,7 @@ static byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a, | |||
2892 | && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF) | 2892 | && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF) |
2893 | && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)) | 2893 | && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP)) |
2894 | { | 2894 | { |
2895 | len = offsetof(T30_INFO, station_id) + 20; | 2895 | len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH; |
2896 | if (plci->fax_connect_info_length < len) | 2896 | if (plci->fax_connect_info_length < len) |
2897 | { | 2897 | { |
2898 | ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0; | 2898 | ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0; |
@@ -3802,7 +3802,7 @@ static byte manufacturer_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a, | |||
3802 | break; | 3802 | break; |
3803 | } | 3803 | } |
3804 | ncpi = &m_parms[1]; | 3804 | ncpi = &m_parms[1]; |
3805 | len = offsetof(T30_INFO, station_id) + 20; | 3805 | len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH; |
3806 | if (plci->fax_connect_info_length < len) | 3806 | if (plci->fax_connect_info_length < len) |
3807 | { | 3807 | { |
3808 | ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0; | 3808 | ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0; |
@@ -6830,7 +6830,7 @@ static void nl_ind(PLCI *plci) | |||
6830 | if(((T30_INFO *)plci->NL.RBuffer->P)->station_id_len) | 6830 | if(((T30_INFO *)plci->NL.RBuffer->P)->station_id_len) |
6831 | { | 6831 | { |
6832 | plci->ncpi_buffer[len] = 20; | 6832 | plci->ncpi_buffer[len] = 20; |
6833 | for (i = 0; i < 20; i++) | 6833 | for (i = 0; i < T30_MAX_STATION_ID_LENGTH; i++) |
6834 | plci->ncpi_buffer[++len] = ((T30_INFO *)plci->NL.RBuffer->P)->station_id[i]; | 6834 | plci->ncpi_buffer[++len] = ((T30_INFO *)plci->NL.RBuffer->P)->station_id[i]; |
6835 | } | 6835 | } |
6836 | if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK)) | 6836 | if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK)) |
@@ -6844,7 +6844,7 @@ static void nl_ind(PLCI *plci) | |||
6844 | if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1]) | 6844 | if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1]) |
6845 | & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD))) | 6845 | & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD))) |
6846 | { | 6846 | { |
6847 | i = offsetof(T30_INFO, station_id) + 20 + ((T30_INFO *)plci->NL.RBuffer->P)->head_line_len; | 6847 | i = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + ((T30_INFO *)plci->NL.RBuffer->P)->head_line_len; |
6848 | while (i < plci->NL.RBuffer->length) | 6848 | while (i < plci->NL.RBuffer->length) |
6849 | plci->ncpi_buffer[++len] = plci->NL.RBuffer->P[i++]; | 6849 | plci->ncpi_buffer[++len] = plci->NL.RBuffer->P[i++]; |
6850 | } | 6850 | } |
@@ -8400,7 +8400,7 @@ static word add_b23(PLCI *plci, API_PARSE *bp) | |||
8400 | } | 8400 | } |
8401 | } | 8401 | } |
8402 | /* copy station id to NLC */ | 8402 | /* copy station id to NLC */ |
8403 | for(i=0; i<20; i++) | 8403 | for(i=0; i < T30_MAX_STATION_ID_LENGTH; i++) |
8404 | { | 8404 | { |
8405 | if(i<b3_config_parms[2].length) | 8405 | if(i<b3_config_parms[2].length) |
8406 | { | 8406 | { |
@@ -8411,29 +8411,29 @@ static word add_b23(PLCI *plci, API_PARSE *bp) | |||
8411 | ((T30_INFO *)&nlc[1])->station_id[i] = ' '; | 8411 | ((T30_INFO *)&nlc[1])->station_id[i] = ' '; |
8412 | } | 8412 | } |
8413 | } | 8413 | } |
8414 | ((T30_INFO *)&nlc[1])->station_id_len = 20; | 8414 | ((T30_INFO *)&nlc[1])->station_id_len = T30_MAX_STATION_ID_LENGTH; |
8415 | /* copy head line to NLC */ | 8415 | /* copy head line to NLC */ |
8416 | if(b3_config_parms[3].length) | 8416 | if(b3_config_parms[3].length) |
8417 | { | 8417 | { |
8418 | 8418 | ||
8419 | pos = (byte)(fax_head_line_time (&(((T30_INFO *)&nlc[1])->station_id[20]))); | 8419 | pos = (byte)(fax_head_line_time (&(((T30_INFO *)&nlc[1])->station_id[T30_MAX_STATION_ID_LENGTH]))); |
8420 | if (pos != 0) | 8420 | if (pos != 0) |
8421 | { | 8421 | { |
8422 | if (CAPI_MAX_DATE_TIME_LENGTH + 2 + b3_config_parms[3].length > CAPI_MAX_HEAD_LINE_SPACE) | 8422 | if (CAPI_MAX_DATE_TIME_LENGTH + 2 + b3_config_parms[3].length > CAPI_MAX_HEAD_LINE_SPACE) |
8423 | pos = 0; | 8423 | pos = 0; |
8424 | else | 8424 | else |
8425 | { | 8425 | { |
8426 | ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' '; | 8426 | nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' '; |
8427 | ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' '; | 8427 | nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' '; |
8428 | len = (byte)b3_config_parms[2].length; | 8428 | len = (byte)b3_config_parms[2].length; |
8429 | if (len > 20) | 8429 | if (len > 20) |
8430 | len = 20; | 8430 | len = 20; |
8431 | if (CAPI_MAX_DATE_TIME_LENGTH + 2 + len + 2 + b3_config_parms[3].length <= CAPI_MAX_HEAD_LINE_SPACE) | 8431 | if (CAPI_MAX_DATE_TIME_LENGTH + 2 + len + 2 + b3_config_parms[3].length <= CAPI_MAX_HEAD_LINE_SPACE) |
8432 | { | 8432 | { |
8433 | for (i = 0; i < len; i++) | 8433 | for (i = 0; i < len; i++) |
8434 | ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ((byte *)b3_config_parms[2].info)[1+i]; | 8434 | nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ((byte *)b3_config_parms[2].info)[1+i]; |
8435 | ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' '; | 8435 | nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' '; |
8436 | ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' '; | 8436 | nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' '; |
8437 | } | 8437 | } |
8438 | } | 8438 | } |
8439 | } | 8439 | } |
@@ -8444,9 +8444,8 @@ static word add_b23(PLCI *plci, API_PARSE *bp) | |||
8444 | ((T30_INFO *)&nlc[1])->head_line_len = (byte)(pos + len); | 8444 | ((T30_INFO *)&nlc[1])->head_line_len = (byte)(pos + len); |
8445 | nlc[0] += (byte)(pos + len); | 8445 | nlc[0] += (byte)(pos + len); |
8446 | for (i = 0; i < len; i++) | 8446 | for (i = 0; i < len; i++) |
8447 | ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ((byte *)b3_config_parms[3].info)[1+i]; | 8447 | nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ((byte *)b3_config_parms[3].info)[1+i]; |
8448 | } | 8448 | } else |
8449 | else | ||
8450 | ((T30_INFO *)&nlc[1])->head_line_len = 0; | 8449 | ((T30_INFO *)&nlc[1])->head_line_len = 0; |
8451 | 8450 | ||
8452 | plci->nsf_control_bits = 0; | 8451 | plci->nsf_control_bits = 0; |
@@ -8473,7 +8472,7 @@ static word add_b23(PLCI *plci, API_PARSE *bp) | |||
8473 | fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING; | 8472 | fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING; |
8474 | } | 8473 | } |
8475 | len = nlc[0]; | 8474 | len = nlc[0]; |
8476 | pos = offsetof(T30_INFO, station_id) + 20; | 8475 | pos = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH; |
8477 | if (pos < plci->fax_connect_info_length) | 8476 | if (pos < plci->fax_connect_info_length) |
8478 | { | 8477 | { |
8479 | for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--) | 8478 | for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--) |
@@ -8525,7 +8524,7 @@ static word add_b23(PLCI *plci, API_PARSE *bp) | |||
8525 | } | 8524 | } |
8526 | 8525 | ||
8527 | PUT_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits); | 8526 | PUT_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits); |
8528 | len = offsetof(T30_INFO, station_id) + 20; | 8527 | len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH; |
8529 | for (i = 0; i < len; i++) | 8528 | for (i = 0; i < len; i++) |
8530 | plci->fax_connect_info_buffer[i] = nlc[1+i]; | 8529 | plci->fax_connect_info_buffer[i] = nlc[1+i]; |
8531 | ((T30_INFO *) plci->fax_connect_info_buffer)->head_line_len = 0; | 8530 | ((T30_INFO *) plci->fax_connect_info_buffer)->head_line_len = 0; |
diff --git a/drivers/isdn/hardware/mISDN/avmfritz.c b/drivers/isdn/hardware/mISDN/avmfritz.c index 81ac541d40d9..d4215369bb59 100644 --- a/drivers/isdn/hardware/mISDN/avmfritz.c +++ b/drivers/isdn/hardware/mISDN/avmfritz.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/pci.h> | 24 | #include <linux/pci.h> |
25 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
26 | #include <linux/mISDNhw.h> | 26 | #include <linux/mISDNhw.h> |
27 | #include <linux/slab.h> | ||
27 | #include <asm/unaligned.h> | 28 | #include <asm/unaligned.h> |
28 | #include "ipac.h" | 29 | #include "ipac.h" |
29 | 30 | ||
diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c index a6624ad252c5..75e71b5d9215 100644 --- a/drivers/isdn/hardware/mISDN/hfcmulti.c +++ b/drivers/isdn/hardware/mISDN/hfcmulti.c | |||
@@ -153,6 +153,7 @@ | |||
153 | #define HFC_MULTI_VERSION "2.03" | 153 | #define HFC_MULTI_VERSION "2.03" |
154 | 154 | ||
155 | #include <linux/module.h> | 155 | #include <linux/module.h> |
156 | #include <linux/slab.h> | ||
156 | #include <linux/pci.h> | 157 | #include <linux/pci.h> |
157 | #include <linux/delay.h> | 158 | #include <linux/delay.h> |
158 | #include <linux/mISDNhw.h> | 159 | #include <linux/mISDNhw.h> |
@@ -2846,7 +2847,7 @@ mode_hfcmulti(struct hfc_multi *hc, int ch, int protocol, int slot_tx, | |||
2846 | int conf; | 2847 | int conf; |
2847 | 2848 | ||
2848 | if (ch < 0 || ch > 31) | 2849 | if (ch < 0 || ch > 31) |
2849 | return EINVAL; | 2850 | return -EINVAL; |
2850 | oslot_tx = hc->chan[ch].slot_tx; | 2851 | oslot_tx = hc->chan[ch].slot_tx; |
2851 | oslot_rx = hc->chan[ch].slot_rx; | 2852 | oslot_rx = hc->chan[ch].slot_rx; |
2852 | conf = hc->chan[ch].conf; | 2853 | conf = hc->chan[ch].conf; |
@@ -3152,7 +3153,7 @@ static void | |||
3152 | hfcmulti_pcm(struct hfc_multi *hc, int ch, int slot_tx, int bank_tx, | 3153 | hfcmulti_pcm(struct hfc_multi *hc, int ch, int slot_tx, int bank_tx, |
3153 | int slot_rx, int bank_rx) | 3154 | int slot_rx, int bank_rx) |
3154 | { | 3155 | { |
3155 | if (slot_rx < 0 || slot_rx < 0 || bank_tx < 0 || bank_rx < 0) { | 3156 | if (slot_tx < 0 || slot_rx < 0 || bank_tx < 0 || bank_rx < 0) { |
3156 | /* disable PCM */ | 3157 | /* disable PCM */ |
3157 | mode_hfcmulti(hc, ch, hc->chan[ch].protocol, -1, 0, -1, 0); | 3158 | mode_hfcmulti(hc, ch, hc->chan[ch].protocol, -1, 0, -1, 0); |
3158 | return; | 3159 | return; |
@@ -5265,6 +5266,8 @@ static const struct hm_map hfcm_map[] = { | |||
5265 | /*31*/ {VENDOR_CCD, "XHFC-4S Speech Design", 5, 4, 0, 0, 0, 0, | 5266 | /*31*/ {VENDOR_CCD, "XHFC-4S Speech Design", 5, 4, 0, 0, 0, 0, |
5266 | HFC_IO_MODE_EMBSD, XHFC_IRQ}, | 5267 | HFC_IO_MODE_EMBSD, XHFC_IRQ}, |
5267 | /*32*/ {VENDOR_JH, "HFC-8S (junghanns)", 8, 8, 1, 0, 0, 0, 0, 0}, | 5268 | /*32*/ {VENDOR_JH, "HFC-8S (junghanns)", 8, 8, 1, 0, 0, 0, 0, 0}, |
5269 | /*33*/ {VENDOR_BN, "HFC-2S Beronet Card PCIe", 4, 2, 1, 3, 0, DIP_4S, 0, 0}, | ||
5270 | /*34*/ {VENDOR_BN, "HFC-4S Beronet Card PCIe", 4, 4, 1, 2, 0, DIP_4S, 0, 0}, | ||
5268 | }; | 5271 | }; |
5269 | 5272 | ||
5270 | #undef H | 5273 | #undef H |
@@ -5300,6 +5303,10 @@ static struct pci_device_id hfmultipci_ids[] __devinitdata = { | |||
5300 | PCI_SUBDEVICE_ID_CCD_OV4S, 0, 0, H(28)}, /* OpenVox 4 */ | 5303 | PCI_SUBDEVICE_ID_CCD_OV4S, 0, 0, H(28)}, /* OpenVox 4 */ |
5301 | { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC4S, PCI_VENDOR_ID_CCD, | 5304 | { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC4S, PCI_VENDOR_ID_CCD, |
5302 | PCI_SUBDEVICE_ID_CCD_OV2S, 0, 0, H(29)}, /* OpenVox 2 */ | 5305 | PCI_SUBDEVICE_ID_CCD_OV2S, 0, 0, H(29)}, /* OpenVox 2 */ |
5306 | { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC4S, PCI_VENDOR_ID_CCD, | ||
5307 | 0xb761, 0, 0, H(33)}, /* BN2S PCIe */ | ||
5308 | { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC4S, PCI_VENDOR_ID_CCD, | ||
5309 | 0xb762, 0, 0, H(34)}, /* BN4S PCIe */ | ||
5303 | 5310 | ||
5304 | /* Cards with HFC-8S Chip */ | 5311 | /* Cards with HFC-8S Chip */ |
5305 | { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC8S, PCI_VENDOR_ID_CCD, | 5312 | { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC8S, PCI_VENDOR_ID_CCD, |
diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c index 70e6b0e01121..5940a2c12074 100644 --- a/drivers/isdn/hardware/mISDN/hfcpci.c +++ b/drivers/isdn/hardware/mISDN/hfcpci.c | |||
@@ -48,6 +48,7 @@ | |||
48 | #include <linux/pci.h> | 48 | #include <linux/pci.h> |
49 | #include <linux/delay.h> | 49 | #include <linux/delay.h> |
50 | #include <linux/mISDNhw.h> | 50 | #include <linux/mISDNhw.h> |
51 | #include <linux/slab.h> | ||
51 | 52 | ||
52 | #include "hfc_pci.h" | 53 | #include "hfc_pci.h" |
53 | 54 | ||
diff --git a/drivers/isdn/hardware/mISDN/hfcsusb.c b/drivers/isdn/hardware/mISDN/hfcsusb.c index fc46a26cb14f..b3b7e2879bac 100644 --- a/drivers/isdn/hardware/mISDN/hfcsusb.c +++ b/drivers/isdn/hardware/mISDN/hfcsusb.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/delay.h> | 33 | #include <linux/delay.h> |
34 | #include <linux/usb.h> | 34 | #include <linux/usb.h> |
35 | #include <linux/mISDNhw.h> | 35 | #include <linux/mISDNhw.h> |
36 | #include <linux/slab.h> | ||
36 | #include "hfcsusb.h" | 37 | #include "hfcsusb.h" |
37 | 38 | ||
38 | static const char *hfcsusb_rev = "Revision: 0.3.3 (socket), 2008-11-05"; | 39 | static const char *hfcsusb_rev = "Revision: 0.3.3 (socket), 2008-11-05"; |
@@ -721,7 +722,7 @@ hfcsusb_setup_bch(struct bchannel *bch, int protocol) | |||
721 | switch (protocol) { | 722 | switch (protocol) { |
722 | case (-1): /* used for init */ | 723 | case (-1): /* used for init */ |
723 | bch->state = -1; | 724 | bch->state = -1; |
724 | /* fall trough */ | 725 | /* fall through */ |
725 | case (ISDN_P_NONE): | 726 | case (ISDN_P_NONE): |
726 | if (bch->state == ISDN_P_NONE) | 727 | if (bch->state == ISDN_P_NONE) |
727 | return 0; /* already in idle state */ | 728 | return 0; /* already in idle state */ |
diff --git a/drivers/isdn/hardware/mISDN/hfcsusb.h b/drivers/isdn/hardware/mISDN/hfcsusb.h index 43efe7358fa3..369196adae03 100644 --- a/drivers/isdn/hardware/mISDN/hfcsusb.h +++ b/drivers/isdn/hardware/mISDN/hfcsusb.h | |||
@@ -150,7 +150,7 @@ symbolic(struct hfcusb_symbolic_list list[], const int num) | |||
150 | for (i = 0; list[i].name != NULL; i++) | 150 | for (i = 0; list[i].name != NULL; i++) |
151 | if (list[i].num == num) | 151 | if (list[i].num == num) |
152 | return list[i].name; | 152 | return list[i].name; |
153 | return "<unkown USB Error>"; | 153 | return "<unknown USB Error>"; |
154 | } | 154 | } |
155 | 155 | ||
156 | /* USB descriptor need to contain one of the following EndPoint combination: */ | 156 | /* USB descriptor need to contain one of the following EndPoint combination: */ |
diff --git a/drivers/isdn/hardware/mISDN/mISDNinfineon.c b/drivers/isdn/hardware/mISDN/mISDNinfineon.c index 62441ba53b95..f5b3d2b26a08 100644 --- a/drivers/isdn/hardware/mISDN/mISDNinfineon.c +++ b/drivers/isdn/hardware/mISDN/mISDNinfineon.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include <linux/pci.h> | 42 | #include <linux/pci.h> |
43 | #include <linux/delay.h> | 43 | #include <linux/delay.h> |
44 | #include <linux/mISDNhw.h> | 44 | #include <linux/mISDNhw.h> |
45 | #include <linux/slab.h> | ||
45 | #include "ipac.h" | 46 | #include "ipac.h" |
46 | 47 | ||
47 | #define INFINEON_REV "1.0" | 48 | #define INFINEON_REV "1.0" |
@@ -1133,6 +1134,7 @@ inf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1133 | if (err) { | 1134 | if (err) { |
1134 | kfree(sc); | 1135 | kfree(sc); |
1135 | release_card(card); | 1136 | release_card(card); |
1137 | break; | ||
1136 | } else | 1138 | } else |
1137 | card->sc[i - 1] = sc; | 1139 | card->sc[i - 1] = sc; |
1138 | } | 1140 | } |
diff --git a/drivers/isdn/hardware/mISDN/mISDNipac.c b/drivers/isdn/hardware/mISDN/mISDNipac.c index 613ba0435372..64ecc6f5ffaf 100644 --- a/drivers/isdn/hardware/mISDN/mISDNipac.c +++ b/drivers/isdn/hardware/mISDN/mISDNipac.c | |||
@@ -20,6 +20,7 @@ | |||
20 | * | 20 | * |
21 | */ | 21 | */ |
22 | 22 | ||
23 | #include <linux/slab.h> | ||
23 | #include <linux/module.h> | 24 | #include <linux/module.h> |
24 | #include <linux/mISDNhw.h> | 25 | #include <linux/mISDNhw.h> |
25 | #include "ipac.h" | 26 | #include "ipac.h" |
diff --git a/drivers/isdn/hardware/mISDN/mISDNisar.c b/drivers/isdn/hardware/mISDN/mISDNisar.c index de352a17673a..38eb31439a73 100644 --- a/drivers/isdn/hardware/mISDN/mISDNisar.c +++ b/drivers/isdn/hardware/mISDN/mISDNisar.c | |||
@@ -25,6 +25,7 @@ | |||
25 | */ | 25 | */ |
26 | /* #define DEBUG */ | 26 | /* #define DEBUG */ |
27 | 27 | ||
28 | #include <linux/gfp.h> | ||
28 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
29 | #include <linux/vmalloc.h> | 30 | #include <linux/vmalloc.h> |
30 | #include <linux/mISDNhw.h> | 31 | #include <linux/mISDNhw.h> |
@@ -860,7 +861,7 @@ isar_pump_statev_modem(struct isar_ch *ch, u8 devt) { | |||
860 | pr_debug("%s: pump stev GSTN CLEAR\n", ch->is->name); | 861 | pr_debug("%s: pump stev GSTN CLEAR\n", ch->is->name); |
861 | break; | 862 | break; |
862 | default: | 863 | default: |
863 | pr_info("u%s: nknown pump stev %x\n", ch->is->name, devt); | 864 | pr_info("u%s: unknown pump stev %x\n", ch->is->name, devt); |
864 | break; | 865 | break; |
865 | } | 866 | } |
866 | } | 867 | } |
@@ -1712,13 +1713,13 @@ mISDNisar_init(struct isar_hw *isar, void *hw) | |||
1712 | } | 1713 | } |
1713 | EXPORT_SYMBOL(mISDNisar_init); | 1714 | EXPORT_SYMBOL(mISDNisar_init); |
1714 | 1715 | ||
1715 | static int isar_mod_init(void) | 1716 | static int __init isar_mod_init(void) |
1716 | { | 1717 | { |
1717 | pr_notice("mISDN: ISAR driver Rev. %s\n", ISAR_REV); | 1718 | pr_notice("mISDN: ISAR driver Rev. %s\n", ISAR_REV); |
1718 | return 0; | 1719 | return 0; |
1719 | } | 1720 | } |
1720 | 1721 | ||
1721 | static void isar_mod_cleanup(void) | 1722 | static void __exit isar_mod_cleanup(void) |
1722 | { | 1723 | { |
1723 | pr_notice("mISDN: ISAR module unloaded\n"); | 1724 | pr_notice("mISDN: ISAR module unloaded\n"); |
1724 | } | 1725 | } |
diff --git a/drivers/isdn/hardware/mISDN/netjet.c b/drivers/isdn/hardware/mISDN/netjet.c index 6c1b164937a9..0a3553df065f 100644 --- a/drivers/isdn/hardware/mISDN/netjet.c +++ b/drivers/isdn/hardware/mISDN/netjet.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/pci.h> | 24 | #include <linux/pci.h> |
25 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
26 | #include <linux/mISDNhw.h> | 26 | #include <linux/mISDNhw.h> |
27 | #include <linux/slab.h> | ||
27 | #include "ipac.h" | 28 | #include "ipac.h" |
28 | #include "iohelper.h" | 29 | #include "iohelper.h" |
29 | #include "netjet.h" | 30 | #include "netjet.h" |
diff --git a/drivers/isdn/hardware/mISDN/speedfax.c b/drivers/isdn/hardware/mISDN/speedfax.c index ff3a4e290da3..d097a4e40e2b 100644 --- a/drivers/isdn/hardware/mISDN/speedfax.c +++ b/drivers/isdn/hardware/mISDN/speedfax.c | |||
@@ -23,6 +23,7 @@ | |||
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | #include <linux/slab.h> | ||
26 | #include <linux/pci.h> | 27 | #include <linux/pci.h> |
27 | #include <linux/delay.h> | 28 | #include <linux/delay.h> |
28 | #include <linux/mISDNhw.h> | 29 | #include <linux/mISDNhw.h> |
@@ -110,6 +111,7 @@ set_debug(const char *val, struct kernel_param *kp) | |||
110 | MODULE_AUTHOR("Karsten Keil"); | 111 | MODULE_AUTHOR("Karsten Keil"); |
111 | MODULE_LICENSE("GPL v2"); | 112 | MODULE_LICENSE("GPL v2"); |
112 | MODULE_VERSION(SPEEDFAX_REV); | 113 | MODULE_VERSION(SPEEDFAX_REV); |
114 | MODULE_FIRMWARE("isdn/ISAR.BIN"); | ||
113 | module_param_call(debug, set_debug, param_get_uint, &debug, S_IRUGO | S_IWUSR); | 115 | module_param_call(debug, set_debug, param_get_uint, &debug, S_IRUGO | S_IWUSR); |
114 | MODULE_PARM_DESC(debug, "Speedfax debug mask"); | 116 | MODULE_PARM_DESC(debug, "Speedfax debug mask"); |
115 | module_param(irqloops, uint, S_IRUGO | S_IWUSR); | 117 | module_param(irqloops, uint, S_IRUGO | S_IWUSR); |
diff --git a/drivers/isdn/hardware/mISDN/w6692.c b/drivers/isdn/hardware/mISDN/w6692.c index d3f1077b709b..31f9d71fb22f 100644 --- a/drivers/isdn/hardware/mISDN/w6692.c +++ b/drivers/isdn/hardware/mISDN/w6692.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/pci.h> | 25 | #include <linux/pci.h> |
26 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
27 | #include <linux/mISDNhw.h> | 27 | #include <linux/mISDNhw.h> |
28 | #include <linux/slab.h> | ||
28 | #include "w6692.h" | 29 | #include "w6692.h" |
29 | 30 | ||
30 | #define W6692_REV "2.0" | 31 | #define W6692_REV "2.0" |
@@ -529,6 +530,7 @@ W6692_fill_Bfifo(struct w6692_ch *wch) | |||
529 | } | 530 | } |
530 | } | 531 | } |
531 | 532 | ||
533 | #if 0 | ||
532 | static int | 534 | static int |
533 | setvolume(struct w6692_ch *wch, int mic, struct sk_buff *skb) | 535 | setvolume(struct w6692_ch *wch, int mic, struct sk_buff *skb) |
534 | { | 536 | { |
@@ -571,6 +573,7 @@ enable_pots(struct w6692_ch *wch) | |||
571 | WriteW6692(card, W_PCTL, card->pctl); | 573 | WriteW6692(card, W_PCTL, card->pctl); |
572 | return 0; | 574 | return 0; |
573 | } | 575 | } |
576 | #endif | ||
574 | 577 | ||
575 | static int | 578 | static int |
576 | disable_pots(struct w6692_ch *wch) | 579 | disable_pots(struct w6692_ch *wch) |
diff --git a/drivers/isdn/hisax/Kconfig b/drivers/isdn/hisax/Kconfig index 3464ebc4cdbc..452fde9edf86 100644 --- a/drivers/isdn/hisax/Kconfig +++ b/drivers/isdn/hisax/Kconfig | |||
@@ -109,7 +109,7 @@ config HISAX_16_3 | |||
109 | 109 | ||
110 | config HISAX_TELESPCI | 110 | config HISAX_TELESPCI |
111 | bool "Teles PCI" | 111 | bool "Teles PCI" |
112 | depends on PCI && PCI_LEGACY && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) | 112 | depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) |
113 | help | 113 | help |
114 | This enables HiSax support for the Teles PCI. | 114 | This enables HiSax support for the Teles PCI. |
115 | See <file:Documentation/isdn/README.HiSax> on how to configure it. | 115 | See <file:Documentation/isdn/README.HiSax> on how to configure it. |
@@ -237,7 +237,7 @@ config HISAX_MIC | |||
237 | 237 | ||
238 | config HISAX_NETJET | 238 | config HISAX_NETJET |
239 | bool "NETjet card" | 239 | bool "NETjet card" |
240 | depends on PCI && PCI_LEGACY && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) | 240 | depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) |
241 | help | 241 | help |
242 | This enables HiSax support for the NetJet from Traverse | 242 | This enables HiSax support for the NetJet from Traverse |
243 | Technologies. | 243 | Technologies. |
@@ -248,7 +248,7 @@ config HISAX_NETJET | |||
248 | 248 | ||
249 | config HISAX_NETJET_U | 249 | config HISAX_NETJET_U |
250 | bool "NETspider U card" | 250 | bool "NETspider U card" |
251 | depends on PCI && PCI_LEGACY && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) | 251 | depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) |
252 | help | 252 | help |
253 | This enables HiSax support for the Netspider U interface ISDN card | 253 | This enables HiSax support for the Netspider U interface ISDN card |
254 | from Traverse Technologies. | 254 | from Traverse Technologies. |
@@ -287,7 +287,7 @@ config HISAX_HSTSAPHIR | |||
287 | 287 | ||
288 | config HISAX_BKM_A4T | 288 | config HISAX_BKM_A4T |
289 | bool "Telekom A4T card" | 289 | bool "Telekom A4T card" |
290 | depends on PCI && PCI_LEGACY | 290 | depends on PCI |
291 | help | 291 | help |
292 | This enables HiSax support for the Telekom A4T card. | 292 | This enables HiSax support for the Telekom A4T card. |
293 | 293 | ||
@@ -297,7 +297,7 @@ config HISAX_BKM_A4T | |||
297 | 297 | ||
298 | config HISAX_SCT_QUADRO | 298 | config HISAX_SCT_QUADRO |
299 | bool "Scitel Quadro card" | 299 | bool "Scitel Quadro card" |
300 | depends on PCI && PCI_LEGACY | 300 | depends on PCI |
301 | help | 301 | help |
302 | This enables HiSax support for the Scitel Quadro card. | 302 | This enables HiSax support for the Scitel Quadro card. |
303 | 303 | ||
@@ -316,7 +316,7 @@ config HISAX_GAZEL | |||
316 | 316 | ||
317 | config HISAX_HFC_PCI | 317 | config HISAX_HFC_PCI |
318 | bool "HFC PCI-Bus cards" | 318 | bool "HFC PCI-Bus cards" |
319 | depends on PCI && PCI_LEGACY && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) | 319 | depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) |
320 | help | 320 | help |
321 | This enables HiSax support for the HFC-S PCI 2BDS0 based cards. | 321 | This enables HiSax support for the HFC-S PCI 2BDS0 based cards. |
322 | 322 | ||
@@ -325,7 +325,7 @@ config HISAX_HFC_PCI | |||
325 | 325 | ||
326 | config HISAX_W6692 | 326 | config HISAX_W6692 |
327 | bool "Winbond W6692 based cards" | 327 | bool "Winbond W6692 based cards" |
328 | depends on PCI && PCI_LEGACY | 328 | depends on PCI |
329 | help | 329 | help |
330 | This enables HiSax support for Winbond W6692 based PCI ISDN cards. | 330 | This enables HiSax support for Winbond W6692 based PCI ISDN cards. |
331 | 331 | ||
@@ -341,7 +341,7 @@ config HISAX_HFC_SX | |||
341 | 341 | ||
342 | config HISAX_ENTERNOW_PCI | 342 | config HISAX_ENTERNOW_PCI |
343 | bool "Formula-n enter:now PCI card" | 343 | bool "Formula-n enter:now PCI card" |
344 | depends on HISAX_NETJET && PCI && PCI_LEGACY && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) | 344 | depends on HISAX_NETJET && PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV)) |
345 | help | 345 | help |
346 | This enables HiSax support for the Formula-n enter:now PCI | 346 | This enables HiSax support for the Formula-n enter:now PCI |
347 | ISDN card. | 347 | ISDN card. |
@@ -412,7 +412,7 @@ config HISAX_HFC4S8S | |||
412 | 412 | ||
413 | config HISAX_FRITZ_PCIPNP | 413 | config HISAX_FRITZ_PCIPNP |
414 | tristate "AVM Fritz!Card PCI/PCIv2/PnP support (EXPERIMENTAL)" | 414 | tristate "AVM Fritz!Card PCI/PCIv2/PnP support (EXPERIMENTAL)" |
415 | depends on PCI && PCI_LEGACY && EXPERIMENTAL | 415 | depends on PCI && EXPERIMENTAL |
416 | help | 416 | help |
417 | This enables the driver for the AVM Fritz!Card PCI, | 417 | This enables the driver for the AVM Fritz!Card PCI, |
418 | Fritz!Card PCI v2 and Fritz!Card PnP. | 418 | Fritz!Card PCI v2 and Fritz!Card PnP. |
diff --git a/drivers/isdn/hisax/amd7930_fn.c b/drivers/isdn/hisax/amd7930_fn.c index d6fdf1f66754..5d7278397878 100644 --- a/drivers/isdn/hisax/amd7930_fn.c +++ b/drivers/isdn/hisax/amd7930_fn.c | |||
@@ -59,6 +59,7 @@ | |||
59 | #include "amd7930_fn.h" | 59 | #include "amd7930_fn.h" |
60 | #include <linux/interrupt.h> | 60 | #include <linux/interrupt.h> |
61 | #include <linux/init.h> | 61 | #include <linux/init.h> |
62 | #include <linux/gfp.h> | ||
62 | 63 | ||
63 | static void Amd7930_new_ph(struct IsdnCardState *cs); | 64 | static void Amd7930_new_ph(struct IsdnCardState *cs); |
64 | 65 | ||
diff --git a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c index 7cabc5a19492..fcf4ed1cb4b9 100644 --- a/drivers/isdn/hisax/avm_pci.c +++ b/drivers/isdn/hisax/avm_pci.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include "isac.h" | 17 | #include "isac.h" |
18 | #include "isdnl1.h" | 18 | #include "isdnl1.h" |
19 | #include <linux/pci.h> | 19 | #include <linux/pci.h> |
20 | #include <linux/slab.h> | ||
20 | #include <linux/isapnp.h> | 21 | #include <linux/isapnp.h> |
21 | #include <linux/interrupt.h> | 22 | #include <linux/interrupt.h> |
22 | 23 | ||
@@ -822,7 +823,7 @@ static int __devinit avm_pnp_setup(struct IsdnCardState *cs) | |||
822 | 823 | ||
823 | #endif /* __ISAPNP__ */ | 824 | #endif /* __ISAPNP__ */ |
824 | 825 | ||
825 | #ifndef CONFIG_PCI_LEGACY | 826 | #ifndef CONFIG_PCI |
826 | 827 | ||
827 | static int __devinit avm_pci_setup(struct IsdnCardState *cs) | 828 | static int __devinit avm_pci_setup(struct IsdnCardState *cs) |
828 | { | 829 | { |
@@ -835,7 +836,7 @@ static struct pci_dev *dev_avm __devinitdata = NULL; | |||
835 | 836 | ||
836 | static int __devinit avm_pci_setup(struct IsdnCardState *cs) | 837 | static int __devinit avm_pci_setup(struct IsdnCardState *cs) |
837 | { | 838 | { |
838 | if ((dev_avm = pci_find_device(PCI_VENDOR_ID_AVM, | 839 | if ((dev_avm = hisax_find_pci_device(PCI_VENDOR_ID_AVM, |
839 | PCI_DEVICE_ID_AVM_A1, dev_avm))) { | 840 | PCI_DEVICE_ID_AVM_A1, dev_avm))) { |
840 | 841 | ||
841 | if (pci_enable_device(dev_avm)) | 842 | if (pci_enable_device(dev_avm)) |
@@ -864,7 +865,7 @@ static int __devinit avm_pci_setup(struct IsdnCardState *cs) | |||
864 | return (1); | 865 | return (1); |
865 | } | 866 | } |
866 | 867 | ||
867 | #endif /* CONFIG_PCI_LEGACY */ | 868 | #endif /* CONFIG_PCI */ |
868 | 869 | ||
869 | int __devinit | 870 | int __devinit |
870 | setup_avm_pcipnp(struct IsdnCard *card) | 871 | setup_avm_pcipnp(struct IsdnCard *card) |
diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c index 23560c897ec3..8d1d63a02b34 100644 --- a/drivers/isdn/hisax/avma1_cs.c +++ b/drivers/isdn/hisax/avma1_cs.c | |||
@@ -30,22 +30,6 @@ MODULE_DESCRIPTION("ISDN4Linux: PCMCIA client driver for AVM A1/Fritz!PCMCIA car | |||
30 | MODULE_AUTHOR("Carsten Paeth"); | 30 | MODULE_AUTHOR("Carsten Paeth"); |
31 | MODULE_LICENSE("GPL"); | 31 | MODULE_LICENSE("GPL"); |
32 | 32 | ||
33 | /* | ||
34 | All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If | ||
35 | you do not define PCMCIA_DEBUG at all, all the debug code will be | ||
36 | left out. If you compile with PCMCIA_DEBUG=0, the debug code will | ||
37 | be present but disabled -- but it can then be enabled for specific | ||
38 | modules at load time with a 'pc_debug=#' option to insmod. | ||
39 | */ | ||
40 | #ifdef PCMCIA_DEBUG | ||
41 | static int pc_debug = PCMCIA_DEBUG; | ||
42 | module_param(pc_debug, int, 0); | ||
43 | #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args); | ||
44 | static char *version = | ||
45 | "avma1_cs.c 1.00 1998/01/23 10:00:00 (Carsten Paeth)"; | ||
46 | #else | ||
47 | #define DEBUG(n, args...) | ||
48 | #endif | ||
49 | 33 | ||
50 | /*====================================================================*/ | 34 | /*====================================================================*/ |
51 | 35 | ||
@@ -66,7 +50,7 @@ module_param(isdnprot, int, 0); | |||
66 | handler. | 50 | handler. |
67 | */ | 51 | */ |
68 | 52 | ||
69 | static int avma1cs_config(struct pcmcia_device *link); | 53 | static int avma1cs_config(struct pcmcia_device *link) __devinit ; |
70 | static void avma1cs_release(struct pcmcia_device *link); | 54 | static void avma1cs_release(struct pcmcia_device *link); |
71 | 55 | ||
72 | /* | 56 | /* |
@@ -75,7 +59,7 @@ static void avma1cs_release(struct pcmcia_device *link); | |||
75 | needed to manage one actual PCMCIA card. | 59 | needed to manage one actual PCMCIA card. |
76 | */ | 60 | */ |
77 | 61 | ||
78 | static void avma1cs_detach(struct pcmcia_device *p_dev); | 62 | static void avma1cs_detach(struct pcmcia_device *p_dev) __devexit ; |
79 | 63 | ||
80 | 64 | ||
81 | /* | 65 | /* |
@@ -115,11 +99,11 @@ typedef struct local_info_t { | |||
115 | 99 | ||
116 | ======================================================================*/ | 100 | ======================================================================*/ |
117 | 101 | ||
118 | static int avma1cs_probe(struct pcmcia_device *p_dev) | 102 | static int __devinit avma1cs_probe(struct pcmcia_device *p_dev) |
119 | { | 103 | { |
120 | local_info_t *local; | 104 | local_info_t *local; |
121 | 105 | ||
122 | DEBUG(0, "avma1cs_attach()\n"); | 106 | dev_dbg(&p_dev->dev, "avma1cs_attach()\n"); |
123 | 107 | ||
124 | /* Allocate space for private device-specific data */ | 108 | /* Allocate space for private device-specific data */ |
125 | local = kzalloc(sizeof(local_info_t), GFP_KERNEL); | 109 | local = kzalloc(sizeof(local_info_t), GFP_KERNEL); |
@@ -136,10 +120,7 @@ static int avma1cs_probe(struct pcmcia_device *p_dev) | |||
136 | p_dev->io.IOAddrLines = 5; | 120 | p_dev->io.IOAddrLines = 5; |
137 | 121 | ||
138 | /* Interrupt setup */ | 122 | /* Interrupt setup */ |
139 | p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE; | 123 | p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; |
140 | p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; | ||
141 | |||
142 | p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; | ||
143 | 124 | ||
144 | /* General socket configuration */ | 125 | /* General socket configuration */ |
145 | p_dev->conf.Attributes = CONF_ENABLE_IRQ; | 126 | p_dev->conf.Attributes = CONF_ENABLE_IRQ; |
@@ -159,9 +140,9 @@ static int avma1cs_probe(struct pcmcia_device *p_dev) | |||
159 | 140 | ||
160 | ======================================================================*/ | 141 | ======================================================================*/ |
161 | 142 | ||
162 | static void avma1cs_detach(struct pcmcia_device *link) | 143 | static void __devexit avma1cs_detach(struct pcmcia_device *link) |
163 | { | 144 | { |
164 | DEBUG(0, "avma1cs_detach(0x%p)\n", link); | 145 | dev_dbg(&link->dev, "avma1cs_detach(0x%p)\n", link); |
165 | avma1cs_release(link); | 146 | avma1cs_release(link); |
166 | kfree(link->priv); | 147 | kfree(link->priv); |
167 | } /* avma1cs_detach */ | 148 | } /* avma1cs_detach */ |
@@ -193,7 +174,7 @@ static int avma1cs_configcheck(struct pcmcia_device *p_dev, | |||
193 | } | 174 | } |
194 | 175 | ||
195 | 176 | ||
196 | static int avma1cs_config(struct pcmcia_device *link) | 177 | static int __devinit avma1cs_config(struct pcmcia_device *link) |
197 | { | 178 | { |
198 | local_info_t *dev; | 179 | local_info_t *dev; |
199 | int i; | 180 | int i; |
@@ -203,7 +184,7 @@ static int avma1cs_config(struct pcmcia_device *link) | |||
203 | 184 | ||
204 | dev = link->priv; | 185 | dev = link->priv; |
205 | 186 | ||
206 | DEBUG(0, "avma1cs_config(0x%p)\n", link); | 187 | dev_dbg(&link->dev, "avma1cs_config(0x%p)\n", link); |
207 | 188 | ||
208 | devname[0] = 0; | 189 | devname[0] = 0; |
209 | if (link->prod_id[1]) | 190 | if (link->prod_id[1]) |
@@ -218,7 +199,6 @@ static int avma1cs_config(struct pcmcia_device *link) | |||
218 | */ | 199 | */ |
219 | i = pcmcia_request_irq(link, &link->irq); | 200 | i = pcmcia_request_irq(link, &link->irq); |
220 | if (i != 0) { | 201 | if (i != 0) { |
221 | cs_error(link, RequestIRQ, i); | ||
222 | /* undo */ | 202 | /* undo */ |
223 | pcmcia_disable_device(link); | 203 | pcmcia_disable_device(link); |
224 | break; | 204 | break; |
@@ -229,7 +209,6 @@ static int avma1cs_config(struct pcmcia_device *link) | |||
229 | */ | 209 | */ |
230 | i = pcmcia_request_configuration(link, &link->conf); | 210 | i = pcmcia_request_configuration(link, &link->conf); |
231 | if (i != 0) { | 211 | if (i != 0) { |
232 | cs_error(link, RequestConfiguration, i); | ||
233 | pcmcia_disable_device(link); | 212 | pcmcia_disable_device(link); |
234 | break; | 213 | break; |
235 | } | 214 | } |
@@ -281,7 +260,7 @@ static void avma1cs_release(struct pcmcia_device *link) | |||
281 | { | 260 | { |
282 | local_info_t *local = link->priv; | 261 | local_info_t *local = link->priv; |
283 | 262 | ||
284 | DEBUG(0, "avma1cs_release(0x%p)\n", link); | 263 | dev_dbg(&link->dev, "avma1cs_release(0x%p)\n", link); |
285 | 264 | ||
286 | /* now unregister function with hisax */ | 265 | /* now unregister function with hisax */ |
287 | HiSax_closecard(local->node.minor); | 266 | HiSax_closecard(local->node.minor); |
@@ -303,7 +282,7 @@ static struct pcmcia_driver avma1cs_driver = { | |||
303 | .name = "avma1_cs", | 282 | .name = "avma1_cs", |
304 | }, | 283 | }, |
305 | .probe = avma1cs_probe, | 284 | .probe = avma1cs_probe, |
306 | .remove = avma1cs_detach, | 285 | .remove = __devexit_p(avma1cs_detach), |
307 | .id_table = avma1cs_ids, | 286 | .id_table = avma1cs_ids, |
308 | }; | 287 | }; |
309 | 288 | ||
diff --git a/drivers/isdn/hisax/bkm_a4t.c b/drivers/isdn/hisax/bkm_a4t.c index 9ca2ee54cc94..9f2009c0b69c 100644 --- a/drivers/isdn/hisax/bkm_a4t.c +++ b/drivers/isdn/hisax/bkm_a4t.c | |||
@@ -340,7 +340,7 @@ setup_bkm_a4t(struct IsdnCard *card) | |||
340 | } else | 340 | } else |
341 | return (0); | 341 | return (0); |
342 | 342 | ||
343 | while ((dev_a4t = pci_find_device(PCI_VENDOR_ID_ZORAN, | 343 | while ((dev_a4t = hisax_find_pci_device(PCI_VENDOR_ID_ZORAN, |
344 | PCI_DEVICE_ID_ZORAN_36120, dev_a4t))) { | 344 | PCI_DEVICE_ID_ZORAN_36120, dev_a4t))) { |
345 | ret = a4t_pci_probe(dev_a4t, cs, &found, &pci_memaddr); | 345 | ret = a4t_pci_probe(dev_a4t, cs, &found, &pci_memaddr); |
346 | if (!ret) | 346 | if (!ret) |
diff --git a/drivers/isdn/hisax/bkm_a8.c b/drivers/isdn/hisax/bkm_a8.c index e1ff4717a8a6..e775706c60e3 100644 --- a/drivers/isdn/hisax/bkm_a8.c +++ b/drivers/isdn/hisax/bkm_a8.c | |||
@@ -301,7 +301,7 @@ setup_sct_quadro(struct IsdnCard *card) | |||
301 | (sub_vendor_id != PCI_VENDOR_ID_BERKOM))) | 301 | (sub_vendor_id != PCI_VENDOR_ID_BERKOM))) |
302 | return (0); | 302 | return (0); |
303 | if (cs->subtyp == SCT_1) { | 303 | if (cs->subtyp == SCT_1) { |
304 | while ((dev_a8 = pci_find_device(PCI_VENDOR_ID_PLX, | 304 | while ((dev_a8 = hisax_find_pci_device(PCI_VENDOR_ID_PLX, |
305 | PCI_DEVICE_ID_PLX_9050, dev_a8))) { | 305 | PCI_DEVICE_ID_PLX_9050, dev_a8))) { |
306 | 306 | ||
307 | sub_vendor_id = dev_a8->subsystem_vendor; | 307 | sub_vendor_id = dev_a8->subsystem_vendor; |
diff --git a/drivers/isdn/hisax/callc.c b/drivers/isdn/hisax/callc.c index 475b1a020003..f58ded8f403f 100644 --- a/drivers/isdn/hisax/callc.c +++ b/drivers/isdn/hisax/callc.c | |||
@@ -17,6 +17,7 @@ | |||
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
20 | #include <linux/slab.h> | ||
20 | #include <linux/init.h> | 21 | #include <linux/init.h> |
21 | #include "hisax.h" | 22 | #include "hisax.h" |
22 | #include <linux/isdn/capicmd.h> | 23 | #include <linux/isdn/capicmd.h> |
diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c index 4fab18d4d02f..544cf4b1cce3 100644 --- a/drivers/isdn/hisax/config.c +++ b/drivers/isdn/hisax/config.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/kernel_stat.h> | 23 | #include <linux/kernel_stat.h> |
24 | #include <linux/workqueue.h> | 24 | #include <linux/workqueue.h> |
25 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
26 | #include <linux/slab.h> | ||
26 | #define HISAX_STATUS_BUFSIZE 4096 | 27 | #define HISAX_STATUS_BUFSIZE 4096 |
27 | 28 | ||
28 | /* | 29 | /* |
diff --git a/drivers/isdn/hisax/diva.c b/drivers/isdn/hisax/diva.c index 0b0c2e5d806b..780da9bda915 100644 --- a/drivers/isdn/hisax/diva.c +++ b/drivers/isdn/hisax/diva.c | |||
@@ -1148,7 +1148,7 @@ static int __devinit setup_diva_isapnp(struct IsdnCard *card) | |||
1148 | 1148 | ||
1149 | #endif /* ISAPNP */ | 1149 | #endif /* ISAPNP */ |
1150 | 1150 | ||
1151 | #ifdef CONFIG_PCI_LEGACY | 1151 | #ifdef CONFIG_PCI |
1152 | static struct pci_dev *dev_diva __devinitdata = NULL; | 1152 | static struct pci_dev *dev_diva __devinitdata = NULL; |
1153 | static struct pci_dev *dev_diva_u __devinitdata = NULL; | 1153 | static struct pci_dev *dev_diva_u __devinitdata = NULL; |
1154 | static struct pci_dev *dev_diva201 __devinitdata = NULL; | 1154 | static struct pci_dev *dev_diva201 __devinitdata = NULL; |
@@ -1159,21 +1159,21 @@ static int __devinit setup_diva_pci(struct IsdnCard *card) | |||
1159 | struct IsdnCardState *cs = card->cs; | 1159 | struct IsdnCardState *cs = card->cs; |
1160 | 1160 | ||
1161 | cs->subtyp = 0; | 1161 | cs->subtyp = 0; |
1162 | if ((dev_diva = pci_find_device(PCI_VENDOR_ID_EICON, | 1162 | if ((dev_diva = hisax_find_pci_device(PCI_VENDOR_ID_EICON, |
1163 | PCI_DEVICE_ID_EICON_DIVA20, dev_diva))) { | 1163 | PCI_DEVICE_ID_EICON_DIVA20, dev_diva))) { |
1164 | if (pci_enable_device(dev_diva)) | 1164 | if (pci_enable_device(dev_diva)) |
1165 | return(0); | 1165 | return(0); |
1166 | cs->subtyp = DIVA_PCI; | 1166 | cs->subtyp = DIVA_PCI; |
1167 | cs->irq = dev_diva->irq; | 1167 | cs->irq = dev_diva->irq; |
1168 | cs->hw.diva.cfg_reg = pci_resource_start(dev_diva, 2); | 1168 | cs->hw.diva.cfg_reg = pci_resource_start(dev_diva, 2); |
1169 | } else if ((dev_diva_u = pci_find_device(PCI_VENDOR_ID_EICON, | 1169 | } else if ((dev_diva_u = hisax_find_pci_device(PCI_VENDOR_ID_EICON, |
1170 | PCI_DEVICE_ID_EICON_DIVA20_U, dev_diva_u))) { | 1170 | PCI_DEVICE_ID_EICON_DIVA20_U, dev_diva_u))) { |
1171 | if (pci_enable_device(dev_diva_u)) | 1171 | if (pci_enable_device(dev_diva_u)) |
1172 | return(0); | 1172 | return(0); |
1173 | cs->subtyp = DIVA_PCI; | 1173 | cs->subtyp = DIVA_PCI; |
1174 | cs->irq = dev_diva_u->irq; | 1174 | cs->irq = dev_diva_u->irq; |
1175 | cs->hw.diva.cfg_reg = pci_resource_start(dev_diva_u, 2); | 1175 | cs->hw.diva.cfg_reg = pci_resource_start(dev_diva_u, 2); |
1176 | } else if ((dev_diva201 = pci_find_device(PCI_VENDOR_ID_EICON, | 1176 | } else if ((dev_diva201 = hisax_find_pci_device(PCI_VENDOR_ID_EICON, |
1177 | PCI_DEVICE_ID_EICON_DIVA201, dev_diva201))) { | 1177 | PCI_DEVICE_ID_EICON_DIVA201, dev_diva201))) { |
1178 | if (pci_enable_device(dev_diva201)) | 1178 | if (pci_enable_device(dev_diva201)) |
1179 | return(0); | 1179 | return(0); |
@@ -1183,7 +1183,7 @@ static int __devinit setup_diva_pci(struct IsdnCard *card) | |||
1183 | (ulong) ioremap(pci_resource_start(dev_diva201, 0), 4096); | 1183 | (ulong) ioremap(pci_resource_start(dev_diva201, 0), 4096); |
1184 | cs->hw.diva.cfg_reg = | 1184 | cs->hw.diva.cfg_reg = |
1185 | (ulong) ioremap(pci_resource_start(dev_diva201, 1), 4096); | 1185 | (ulong) ioremap(pci_resource_start(dev_diva201, 1), 4096); |
1186 | } else if ((dev_diva202 = pci_find_device(PCI_VENDOR_ID_EICON, | 1186 | } else if ((dev_diva202 = hisax_find_pci_device(PCI_VENDOR_ID_EICON, |
1187 | PCI_DEVICE_ID_EICON_DIVA202, dev_diva202))) { | 1187 | PCI_DEVICE_ID_EICON_DIVA202, dev_diva202))) { |
1188 | if (pci_enable_device(dev_diva202)) | 1188 | if (pci_enable_device(dev_diva202)) |
1189 | return(0); | 1189 | return(0); |
@@ -1229,14 +1229,14 @@ static int __devinit setup_diva_pci(struct IsdnCard *card) | |||
1229 | return (1); /* card found */ | 1229 | return (1); /* card found */ |
1230 | } | 1230 | } |
1231 | 1231 | ||
1232 | #else /* if !CONFIG_PCI_LEGACY */ | 1232 | #else /* if !CONFIG_PCI */ |
1233 | 1233 | ||
1234 | static int __devinit setup_diva_pci(struct IsdnCard *card) | 1234 | static int __devinit setup_diva_pci(struct IsdnCard *card) |
1235 | { | 1235 | { |
1236 | return (-1); /* card not found; continue search */ | 1236 | return (-1); /* card not found; continue search */ |
1237 | } | 1237 | } |
1238 | 1238 | ||
1239 | #endif /* CONFIG_PCI_LEGACY */ | 1239 | #endif /* CONFIG_PCI */ |
1240 | 1240 | ||
1241 | int __devinit | 1241 | int __devinit |
1242 | setup_diva(struct IsdnCard *card) | 1242 | setup_diva(struct IsdnCard *card) |
diff --git a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c index aa29d1cf16af..5d9d338814aa 100644 --- a/drivers/isdn/hisax/elsa.c +++ b/drivers/isdn/hisax/elsa.c | |||
@@ -19,6 +19,7 @@ | |||
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include <linux/init.h> | 21 | #include <linux/init.h> |
22 | #include <linux/slab.h> | ||
22 | #include "hisax.h" | 23 | #include "hisax.h" |
23 | #include "arcofi.h" | 24 | #include "arcofi.h" |
24 | #include "isac.h" | 25 | #include "isac.h" |
@@ -1025,7 +1026,7 @@ setup_elsa_pcmcia(struct IsdnCard *card) | |||
1025 | cs->irq); | 1026 | cs->irq); |
1026 | } | 1027 | } |
1027 | 1028 | ||
1028 | #ifdef CONFIG_PCI_LEGACY | 1029 | #ifdef CONFIG_PCI |
1029 | static struct pci_dev *dev_qs1000 __devinitdata = NULL; | 1030 | static struct pci_dev *dev_qs1000 __devinitdata = NULL; |
1030 | static struct pci_dev *dev_qs3000 __devinitdata = NULL; | 1031 | static struct pci_dev *dev_qs3000 __devinitdata = NULL; |
1031 | 1032 | ||
@@ -1035,7 +1036,7 @@ setup_elsa_pci(struct IsdnCard *card) | |||
1035 | struct IsdnCardState *cs = card->cs; | 1036 | struct IsdnCardState *cs = card->cs; |
1036 | 1037 | ||
1037 | cs->subtyp = 0; | 1038 | cs->subtyp = 0; |
1038 | if ((dev_qs1000 = pci_find_device(PCI_VENDOR_ID_ELSA, | 1039 | if ((dev_qs1000 = hisax_find_pci_device(PCI_VENDOR_ID_ELSA, |
1039 | PCI_DEVICE_ID_ELSA_MICROLINK, dev_qs1000))) { | 1040 | PCI_DEVICE_ID_ELSA_MICROLINK, dev_qs1000))) { |
1040 | if (pci_enable_device(dev_qs1000)) | 1041 | if (pci_enable_device(dev_qs1000)) |
1041 | return(0); | 1042 | return(0); |
@@ -1043,7 +1044,7 @@ setup_elsa_pci(struct IsdnCard *card) | |||
1043 | cs->irq = dev_qs1000->irq; | 1044 | cs->irq = dev_qs1000->irq; |
1044 | cs->hw.elsa.cfg = pci_resource_start(dev_qs1000, 1); | 1045 | cs->hw.elsa.cfg = pci_resource_start(dev_qs1000, 1); |
1045 | cs->hw.elsa.base = pci_resource_start(dev_qs1000, 3); | 1046 | cs->hw.elsa.base = pci_resource_start(dev_qs1000, 3); |
1046 | } else if ((dev_qs3000 = pci_find_device(PCI_VENDOR_ID_ELSA, | 1047 | } else if ((dev_qs3000 = hisax_find_pci_device(PCI_VENDOR_ID_ELSA, |
1047 | PCI_DEVICE_ID_ELSA_QS3000, dev_qs3000))) { | 1048 | PCI_DEVICE_ID_ELSA_QS3000, dev_qs3000))) { |
1048 | if (pci_enable_device(dev_qs3000)) | 1049 | if (pci_enable_device(dev_qs3000)) |
1049 | return(0); | 1050 | return(0); |
@@ -1093,7 +1094,7 @@ setup_elsa_pci(struct IsdnCard *card) | |||
1093 | { | 1094 | { |
1094 | return (1); | 1095 | return (1); |
1095 | } | 1096 | } |
1096 | #endif /* CONFIG_PCI_LEGACY */ | 1097 | #endif /* CONFIG_PCI */ |
1097 | 1098 | ||
1098 | static int __devinit | 1099 | static int __devinit |
1099 | setup_elsa_common(struct IsdnCard *card) | 1100 | setup_elsa_common(struct IsdnCard *card) |
diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c index f4d0fe29bcf8..c9f2279e21f5 100644 --- a/drivers/isdn/hisax/elsa_cs.c +++ b/drivers/isdn/hisax/elsa_cs.c | |||
@@ -57,23 +57,6 @@ MODULE_DESCRIPTION("ISDN4Linux: PCMCIA client driver for Elsa PCM cards"); | |||
57 | MODULE_AUTHOR("Klaus Lichtenwalder"); | 57 | MODULE_AUTHOR("Klaus Lichtenwalder"); |
58 | MODULE_LICENSE("Dual MPL/GPL"); | 58 | MODULE_LICENSE("Dual MPL/GPL"); |
59 | 59 | ||
60 | /* | ||
61 | All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If | ||
62 | you do not define PCMCIA_DEBUG at all, all the debug code will be | ||
63 | left out. If you compile with PCMCIA_DEBUG=0, the debug code will | ||
64 | be present but disabled -- but it can then be enabled for specific | ||
65 | modules at load time with a 'pc_debug=#' option to insmod. | ||
66 | */ | ||
67 | |||
68 | #ifdef PCMCIA_DEBUG | ||
69 | static int pc_debug = PCMCIA_DEBUG; | ||
70 | module_param(pc_debug, int, 0); | ||
71 | #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args); | ||
72 | static char *version = | ||
73 | "elsa_cs.c $Revision: 1.2.2.4 $ $Date: 2004/01/25 15:07:06 $ (K.Lichtenwalder)"; | ||
74 | #else | ||
75 | #define DEBUG(n, args...) | ||
76 | #endif | ||
77 | 60 | ||
78 | /*====================================================================*/ | 61 | /*====================================================================*/ |
79 | 62 | ||
@@ -93,7 +76,7 @@ module_param(protocol, int, 0); | |||
93 | handler. | 76 | handler. |
94 | */ | 77 | */ |
95 | 78 | ||
96 | static int elsa_cs_config(struct pcmcia_device *link); | 79 | static int elsa_cs_config(struct pcmcia_device *link) __devinit ; |
97 | static void elsa_cs_release(struct pcmcia_device *link); | 80 | static void elsa_cs_release(struct pcmcia_device *link); |
98 | 81 | ||
99 | /* | 82 | /* |
@@ -102,7 +85,7 @@ static void elsa_cs_release(struct pcmcia_device *link); | |||
102 | needed to manage one actual PCMCIA card. | 85 | needed to manage one actual PCMCIA card. |
103 | */ | 86 | */ |
104 | 87 | ||
105 | static void elsa_cs_detach(struct pcmcia_device *p_dev); | 88 | static void elsa_cs_detach(struct pcmcia_device *p_dev) __devexit; |
106 | 89 | ||
107 | /* | 90 | /* |
108 | A driver needs to provide a dev_node_t structure for each device | 91 | A driver needs to provide a dev_node_t structure for each device |
@@ -138,11 +121,11 @@ typedef struct local_info_t { | |||
138 | 121 | ||
139 | ======================================================================*/ | 122 | ======================================================================*/ |
140 | 123 | ||
141 | static int elsa_cs_probe(struct pcmcia_device *link) | 124 | static int __devinit elsa_cs_probe(struct pcmcia_device *link) |
142 | { | 125 | { |
143 | local_info_t *local; | 126 | local_info_t *local; |
144 | 127 | ||
145 | DEBUG(0, "elsa_cs_attach()\n"); | 128 | dev_dbg(&link->dev, "elsa_cs_attach()\n"); |
146 | 129 | ||
147 | /* Allocate space for private device-specific data */ | 130 | /* Allocate space for private device-specific data */ |
148 | local = kzalloc(sizeof(local_info_t), GFP_KERNEL); | 131 | local = kzalloc(sizeof(local_info_t), GFP_KERNEL); |
@@ -154,8 +137,7 @@ static int elsa_cs_probe(struct pcmcia_device *link) | |||
154 | local->cardnr = -1; | 137 | local->cardnr = -1; |
155 | 138 | ||
156 | /* Interrupt setup */ | 139 | /* Interrupt setup */ |
157 | link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; | 140 | link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; |
158 | link->irq.IRQInfo1 = IRQ_LEVEL_ID|IRQ_SHARE_ID; | ||
159 | link->irq.Handler = NULL; | 141 | link->irq.Handler = NULL; |
160 | 142 | ||
161 | /* | 143 | /* |
@@ -184,11 +166,11 @@ static int elsa_cs_probe(struct pcmcia_device *link) | |||
184 | 166 | ||
185 | ======================================================================*/ | 167 | ======================================================================*/ |
186 | 168 | ||
187 | static void elsa_cs_detach(struct pcmcia_device *link) | 169 | static void __devexit elsa_cs_detach(struct pcmcia_device *link) |
188 | { | 170 | { |
189 | local_info_t *info = link->priv; | 171 | local_info_t *info = link->priv; |
190 | 172 | ||
191 | DEBUG(0, "elsa_cs_detach(0x%p)\n", link); | 173 | dev_dbg(&link->dev, "elsa_cs_detach(0x%p)\n", link); |
192 | 174 | ||
193 | info->busy = 1; | 175 | info->busy = 1; |
194 | elsa_cs_release(link); | 176 | elsa_cs_release(link); |
@@ -228,33 +210,28 @@ static int elsa_cs_configcheck(struct pcmcia_device *p_dev, | |||
228 | return -ENODEV; | 210 | return -ENODEV; |
229 | } | 211 | } |
230 | 212 | ||
231 | static int elsa_cs_config(struct pcmcia_device *link) | 213 | static int __devinit elsa_cs_config(struct pcmcia_device *link) |
232 | { | 214 | { |
233 | local_info_t *dev; | 215 | local_info_t *dev; |
234 | int i, last_fn; | 216 | int i; |
235 | IsdnCard_t icard; | 217 | IsdnCard_t icard; |
236 | 218 | ||
237 | DEBUG(0, "elsa_config(0x%p)\n", link); | 219 | dev_dbg(&link->dev, "elsa_config(0x%p)\n", link); |
238 | dev = link->priv; | 220 | dev = link->priv; |
239 | 221 | ||
240 | i = pcmcia_loop_config(link, elsa_cs_configcheck, NULL); | 222 | i = pcmcia_loop_config(link, elsa_cs_configcheck, NULL); |
241 | if (i != 0) { | 223 | if (i != 0) |
242 | last_fn = RequestIO; | 224 | goto failed; |
243 | goto cs_failed; | ||
244 | } | ||
245 | 225 | ||
246 | i = pcmcia_request_irq(link, &link->irq); | 226 | i = pcmcia_request_irq(link, &link->irq); |
247 | if (i != 0) { | 227 | if (i != 0) { |
248 | link->irq.AssignedIRQ = 0; | 228 | link->irq.AssignedIRQ = 0; |
249 | last_fn = RequestIRQ; | 229 | goto failed; |
250 | goto cs_failed; | ||
251 | } | 230 | } |
252 | 231 | ||
253 | i = pcmcia_request_configuration(link, &link->conf); | 232 | i = pcmcia_request_configuration(link, &link->conf); |
254 | if (i != 0) { | 233 | if (i != 0) |
255 | last_fn = RequestConfiguration; | 234 | goto failed; |
256 | goto cs_failed; | ||
257 | } | ||
258 | 235 | ||
259 | /* At this point, the dev_node_t structure(s) should be | 236 | /* At this point, the dev_node_t structure(s) should be |
260 | initialized and arranged in a linked list at link->dev. *//* */ | 237 | initialized and arranged in a linked list at link->dev. *//* */ |
@@ -290,8 +267,7 @@ static int elsa_cs_config(struct pcmcia_device *link) | |||
290 | ((local_info_t*)link->priv)->cardnr = i; | 267 | ((local_info_t*)link->priv)->cardnr = i; |
291 | 268 | ||
292 | return 0; | 269 | return 0; |
293 | cs_failed: | 270 | failed: |
294 | cs_error(link, last_fn, i); | ||
295 | elsa_cs_release(link); | 271 | elsa_cs_release(link); |
296 | return -ENODEV; | 272 | return -ENODEV; |
297 | } /* elsa_cs_config */ | 273 | } /* elsa_cs_config */ |
@@ -308,7 +284,7 @@ static void elsa_cs_release(struct pcmcia_device *link) | |||
308 | { | 284 | { |
309 | local_info_t *local = link->priv; | 285 | local_info_t *local = link->priv; |
310 | 286 | ||
311 | DEBUG(0, "elsa_cs_release(0x%p)\n", link); | 287 | dev_dbg(&link->dev, "elsa_cs_release(0x%p)\n", link); |
312 | 288 | ||
313 | if (local) { | 289 | if (local) { |
314 | if (local->cardnr >= 0) { | 290 | if (local->cardnr >= 0) { |
@@ -351,7 +327,7 @@ static struct pcmcia_driver elsa_cs_driver = { | |||
351 | .name = "elsa_cs", | 327 | .name = "elsa_cs", |
352 | }, | 328 | }, |
353 | .probe = elsa_cs_probe, | 329 | .probe = elsa_cs_probe, |
354 | .remove = elsa_cs_detach, | 330 | .remove = __devexit_p(elsa_cs_detach), |
355 | .id_table = elsa_ids, | 331 | .id_table = elsa_ids, |
356 | .suspend = elsa_suspend, | 332 | .suspend = elsa_suspend, |
357 | .resume = elsa_resume, | 333 | .resume = elsa_resume, |
diff --git a/drivers/isdn/hisax/elsa_ser.c b/drivers/isdn/hisax/elsa_ser.c index 1657bba7879e..cbda3790a10d 100644 --- a/drivers/isdn/hisax/elsa_ser.c +++ b/drivers/isdn/hisax/elsa_ser.c | |||
@@ -9,6 +9,7 @@ | |||
9 | 9 | ||
10 | #include <linux/serial.h> | 10 | #include <linux/serial.h> |
11 | #include <linux/serial_reg.h> | 11 | #include <linux/serial_reg.h> |
12 | #include <linux/slab.h> | ||
12 | 13 | ||
13 | #define MAX_MODEM_BUF 256 | 14 | #define MAX_MODEM_BUF 256 |
14 | #define WAKEUP_CHARS (MAX_MODEM_BUF/2) | 15 | #define WAKEUP_CHARS (MAX_MODEM_BUF/2) |
diff --git a/drivers/isdn/hisax/enternow_pci.c b/drivers/isdn/hisax/enternow_pci.c index 39f421ed8de8..26264abf1f58 100644 --- a/drivers/isdn/hisax/enternow_pci.c +++ b/drivers/isdn/hisax/enternow_pci.c | |||
@@ -406,7 +406,7 @@ setup_enternow_pci(struct IsdnCard *card) | |||
406 | 406 | ||
407 | for ( ;; ) | 407 | for ( ;; ) |
408 | { | 408 | { |
409 | if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET, | 409 | if ((dev_netjet = hisax_find_pci_device(PCI_VENDOR_ID_TIGERJET, |
410 | PCI_DEVICE_ID_TIGERJET_300, dev_netjet))) { | 410 | PCI_DEVICE_ID_TIGERJET_300, dev_netjet))) { |
411 | ret = en_pci_probe(dev_netjet, cs); | 411 | ret = en_pci_probe(dev_netjet, cs); |
412 | if (!ret) | 412 | if (!ret) |
diff --git a/drivers/isdn/hisax/fsm.c b/drivers/isdn/hisax/fsm.c index 34fade96a581..732ea633758c 100644 --- a/drivers/isdn/hisax/fsm.c +++ b/drivers/isdn/hisax/fsm.c | |||
@@ -15,6 +15,7 @@ | |||
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include <linux/slab.h> | ||
18 | #include <linux/init.h> | 19 | #include <linux/init.h> |
19 | #include "hisax.h" | 20 | #include "hisax.h" |
20 | 21 | ||
diff --git a/drivers/isdn/hisax/gazel.c b/drivers/isdn/hisax/gazel.c index 0ea3b4607680..353982fc1436 100644 --- a/drivers/isdn/hisax/gazel.c +++ b/drivers/isdn/hisax/gazel.c | |||
@@ -531,7 +531,7 @@ setup_gazelisa(struct IsdnCard *card, struct IsdnCardState *cs) | |||
531 | return (0); | 531 | return (0); |
532 | } | 532 | } |
533 | 533 | ||
534 | #ifdef CONFIG_PCI_LEGACY | 534 | #ifdef CONFIG_PCI |
535 | static struct pci_dev *dev_tel __devinitdata = NULL; | 535 | static struct pci_dev *dev_tel __devinitdata = NULL; |
536 | 536 | ||
537 | static int __devinit | 537 | static int __devinit |
@@ -546,7 +546,7 @@ setup_gazelpci(struct IsdnCardState *cs) | |||
546 | found = 0; | 546 | found = 0; |
547 | seekcard = PCI_DEVICE_ID_PLX_R685; | 547 | seekcard = PCI_DEVICE_ID_PLX_R685; |
548 | for (nbseek = 0; nbseek < 4; nbseek++) { | 548 | for (nbseek = 0; nbseek < 4; nbseek++) { |
549 | if ((dev_tel = pci_find_device(PCI_VENDOR_ID_PLX, | 549 | if ((dev_tel = hisax_find_pci_device(PCI_VENDOR_ID_PLX, |
550 | seekcard, dev_tel))) { | 550 | seekcard, dev_tel))) { |
551 | if (pci_enable_device(dev_tel)) | 551 | if (pci_enable_device(dev_tel)) |
552 | return 1; | 552 | return 1; |
@@ -620,7 +620,7 @@ setup_gazelpci(struct IsdnCardState *cs) | |||
620 | 620 | ||
621 | return (0); | 621 | return (0); |
622 | } | 622 | } |
623 | #endif /* CONFIG_PCI_LEGACY */ | 623 | #endif /* CONFIG_PCI */ |
624 | 624 | ||
625 | int __devinit | 625 | int __devinit |
626 | setup_gazel(struct IsdnCard *card) | 626 | setup_gazel(struct IsdnCard *card) |
@@ -640,7 +640,7 @@ setup_gazel(struct IsdnCard *card) | |||
640 | return (0); | 640 | return (0); |
641 | } else { | 641 | } else { |
642 | 642 | ||
643 | #ifdef CONFIG_PCI_LEGACY | 643 | #ifdef CONFIG_PCI |
644 | if (setup_gazelpci(cs)) | 644 | if (setup_gazelpci(cs)) |
645 | return (0); | 645 | return (0); |
646 | #else | 646 | #else |
diff --git a/drivers/isdn/hisax/hfc4s8s_l1.c b/drivers/isdn/hisax/hfc4s8s_l1.c index ab98e135bcbb..051b44e2556c 100644 --- a/drivers/isdn/hisax/hfc4s8s_l1.c +++ b/drivers/isdn/hisax/hfc4s8s_l1.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/pci.h> | 25 | #include <linux/pci.h> |
26 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
27 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
28 | #include <linux/slab.h> | ||
28 | #include <linux/timer.h> | 29 | #include <linux/timer.h> |
29 | #include <linux/skbuff.h> | 30 | #include <linux/skbuff.h> |
30 | #include <linux/wait.h> | 31 | #include <linux/wait.h> |
diff --git a/drivers/isdn/hisax/hfc_2bds0.c b/drivers/isdn/hisax/hfc_2bds0.c index 8d22f50760eb..7250f56a5246 100644 --- a/drivers/isdn/hisax/hfc_2bds0.c +++ b/drivers/isdn/hisax/hfc_2bds0.c | |||
@@ -12,6 +12,7 @@ | |||
12 | 12 | ||
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/sched.h> | 14 | #include <linux/sched.h> |
15 | #include <linux/slab.h> | ||
15 | #include "hisax.h" | 16 | #include "hisax.h" |
16 | #include "hfc_2bds0.h" | 17 | #include "hfc_2bds0.h" |
17 | #include "isdnl1.h" | 18 | #include "isdnl1.h" |
diff --git a/drivers/isdn/hisax/hfc_2bs0.c b/drivers/isdn/hisax/hfc_2bs0.c index d0520ad30677..b1f6481e1193 100644 --- a/drivers/isdn/hisax/hfc_2bs0.c +++ b/drivers/isdn/hisax/hfc_2bs0.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include "isac.h" | 16 | #include "isac.h" |
17 | #include "isdnl1.h" | 17 | #include "isdnl1.h" |
18 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
19 | #include <linux/slab.h> | ||
19 | 20 | ||
20 | static inline int | 21 | static inline int |
21 | WaitForBusy(struct IsdnCardState *cs) | 22 | WaitForBusy(struct IsdnCardState *cs) |
diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c index 10914731b304..917cc84065bd 100644 --- a/drivers/isdn/hisax/hfc_pci.c +++ b/drivers/isdn/hisax/hfc_pci.c | |||
@@ -1658,7 +1658,7 @@ setup_hfcpci(struct IsdnCard *card) | |||
1658 | 1658 | ||
1659 | i = 0; | 1659 | i = 0; |
1660 | while (id_list[i].vendor_id) { | 1660 | while (id_list[i].vendor_id) { |
1661 | tmp_hfcpci = pci_find_device(id_list[i].vendor_id, | 1661 | tmp_hfcpci = hisax_find_pci_device(id_list[i].vendor_id, |
1662 | id_list[i].device_id, | 1662 | id_list[i].device_id, |
1663 | dev_hfcpci); | 1663 | dev_hfcpci); |
1664 | i++; | 1664 | i++; |
diff --git a/drivers/isdn/hisax/hfc_sx.c b/drivers/isdn/hisax/hfc_sx.c index 419f87cad8cb..be5faf4aa868 100644 --- a/drivers/isdn/hisax/hfc_sx.c +++ b/drivers/isdn/hisax/hfc_sx.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include "isdnl1.h" | 17 | #include "isdnl1.h" |
18 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
19 | #include <linux/isapnp.h> | 19 | #include <linux/isapnp.h> |
20 | #include <linux/slab.h> | ||
20 | 21 | ||
21 | static const char *hfcsx_revision = "$Revision: 1.12.2.5 $"; | 22 | static const char *hfcsx_revision = "$Revision: 1.12.2.5 $"; |
22 | 23 | ||
diff --git a/drivers/isdn/hisax/hfc_usb.c b/drivers/isdn/hisax/hfc_usb.c index a420b64472e3..ed9527aa5f2c 100644 --- a/drivers/isdn/hisax/hfc_usb.c +++ b/drivers/isdn/hisax/hfc_usb.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <linux/kernel.h> | 39 | #include <linux/kernel.h> |
40 | #include <linux/sched.h> | 40 | #include <linux/sched.h> |
41 | #include <linux/moduleparam.h> | 41 | #include <linux/moduleparam.h> |
42 | #include <linux/slab.h> | ||
42 | #include "hisax.h" | 43 | #include "hisax.h" |
43 | #include "hisax_if.h" | 44 | #include "hisax_if.h" |
44 | #include "hfc_usb.h" | 45 | #include "hfc_usb.h" |
@@ -1086,7 +1087,7 @@ hfc_usb_l2l1(struct hisax_if *my_hisax_if, int pr, void *arg) | |||
1086 | break; | 1087 | break; |
1087 | default: | 1088 | default: |
1088 | DBG(HFCUSB_DBG_STATES, | 1089 | DBG(HFCUSB_DBG_STATES, |
1089 | "HFC_USB: hfc_usb_d_l2l1: unkown state : %#x", pr); | 1090 | "HFC_USB: hfc_usb_d_l2l1: unknown state : %#x", pr); |
1090 | break; | 1091 | break; |
1091 | } | 1092 | } |
1092 | } | 1093 | } |
diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h index 0685c1946969..832a87855ffb 100644 --- a/drivers/isdn/hisax/hisax.h +++ b/drivers/isdn/hisax/hisax.h | |||
@@ -1323,3 +1323,26 @@ void release_tei(struct IsdnCardState *cs); | |||
1323 | char *HiSax_getrev(const char *revision); | 1323 | char *HiSax_getrev(const char *revision); |
1324 | int TeiNew(void); | 1324 | int TeiNew(void); |
1325 | void TeiFree(void); | 1325 | void TeiFree(void); |
1326 | |||
1327 | #ifdef CONFIG_PCI | ||
1328 | |||
1329 | #include <linux/pci.h> | ||
1330 | |||
1331 | /* adaptation wrapper for old usage | ||
1332 | * WARNING! This is unfit for use in a PCI hotplug environment, | ||
1333 | * as the returned PCI device can disappear at any moment in time. | ||
1334 | * Callers should be converted to use pci_get_device() instead. | ||
1335 | */ | ||
1336 | static inline struct pci_dev *hisax_find_pci_device(unsigned int vendor, | ||
1337 | unsigned int device, | ||
1338 | struct pci_dev *from) | ||
1339 | { | ||
1340 | struct pci_dev *pdev; | ||
1341 | |||
1342 | pci_dev_get(from); | ||
1343 | pdev = pci_get_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from); | ||
1344 | pci_dev_put(pdev); | ||
1345 | return pdev; | ||
1346 | } | ||
1347 | |||
1348 | #endif | ||
diff --git a/drivers/isdn/hisax/hisax_isac.c b/drivers/isdn/hisax/hisax_isac.c index d0fefcf999cb..a8447fa2f470 100644 --- a/drivers/isdn/hisax/hisax_isac.c +++ b/drivers/isdn/hisax/hisax_isac.c | |||
@@ -21,6 +21,7 @@ | |||
21 | */ | 21 | */ |
22 | 22 | ||
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <linux/gfp.h> | ||
24 | #include <linux/init.h> | 25 | #include <linux/init.h> |
25 | #include <linux/netdevice.h> | 26 | #include <linux/netdevice.h> |
26 | #include "hisax_isac.h" | 27 | #include "hisax_isac.h" |
diff --git a/drivers/isdn/hisax/hscx.c b/drivers/isdn/hisax/hscx.c index c8f9951f7914..904b9100df95 100644 --- a/drivers/isdn/hisax/hscx.c +++ b/drivers/isdn/hisax/hscx.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include "isac.h" | 16 | #include "isac.h" |
17 | #include "isdnl1.h" | 17 | #include "isdnl1.h" |
18 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
19 | #include <linux/slab.h> | ||
19 | 20 | ||
20 | static char *HSCXVer[] = | 21 | static char *HSCXVer[] = |
21 | {"A1", "?1", "A2", "?3", "A3", "V2.1", "?6", "?7", | 22 | {"A1", "?1", "A2", "?3", "A3", "V2.1", "?6", "?7", |
diff --git a/drivers/isdn/hisax/icc.c b/drivers/isdn/hisax/icc.c index c80cbb8a2ef9..63057268cc3d 100644 --- a/drivers/isdn/hisax/icc.c +++ b/drivers/isdn/hisax/icc.c | |||
@@ -20,6 +20,7 @@ | |||
20 | // #include "arcofi.h" | 20 | // #include "arcofi.h" |
21 | #include "isdnl1.h" | 21 | #include "isdnl1.h" |
22 | #include <linux/interrupt.h> | 22 | #include <linux/interrupt.h> |
23 | #include <linux/slab.h> | ||
23 | 24 | ||
24 | #define DBUSY_TIMER_VALUE 80 | 25 | #define DBUSY_TIMER_VALUE 80 |
25 | #define ARCOFI_USE 0 | 26 | #define ARCOFI_USE 0 |
diff --git a/drivers/isdn/hisax/ipacx.c b/drivers/isdn/hisax/ipacx.c index 00afd5538909..751b25f2ff58 100644 --- a/drivers/isdn/hisax/ipacx.c +++ b/drivers/isdn/hisax/ipacx.c | |||
@@ -10,6 +10,7 @@ | |||
10 | * | 10 | * |
11 | */ | 11 | */ |
12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/slab.h> | ||
13 | #include <linux/init.h> | 14 | #include <linux/init.h> |
14 | #include "hisax_if.h" | 15 | #include "hisax_if.h" |
15 | #include "hisax.h" | 16 | #include "hisax.h" |
diff --git a/drivers/isdn/hisax/isac.c b/drivers/isdn/hisax/isac.c index a19354d94343..2b66728136d5 100644 --- a/drivers/isdn/hisax/isac.c +++ b/drivers/isdn/hisax/isac.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include "arcofi.h" | 18 | #include "arcofi.h" |
19 | #include "isdnl1.h" | 19 | #include "isdnl1.h" |
20 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
21 | #include <linux/slab.h> | ||
21 | #include <linux/init.h> | 22 | #include <linux/init.h> |
22 | 23 | ||
23 | #define DBUSY_TIMER_VALUE 80 | 24 | #define DBUSY_TIMER_VALUE 80 |
diff --git a/drivers/isdn/hisax/isar.c b/drivers/isdn/hisax/isar.c index bfeb9b6aa043..40b914bded8c 100644 --- a/drivers/isdn/hisax/isar.c +++ b/drivers/isdn/hisax/isar.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include "isar.h" | 13 | #include "isar.h" |
14 | #include "isdnl1.h" | 14 | #include "isdnl1.h" |
15 | #include <linux/interrupt.h> | 15 | #include <linux/interrupt.h> |
16 | #include <linux/slab.h> | ||
16 | 17 | ||
17 | #define DBG_LOADFIRM 0 | 18 | #define DBG_LOADFIRM 0 |
18 | #define DUMP_MBOXFRAME 2 | 19 | #define DUMP_MBOXFRAME 2 |
@@ -138,7 +139,7 @@ waitrecmsg(struct IsdnCardState *cs, u_char *len, | |||
138 | while((!(cs->BC_Read_Reg(cs, 0, ISAR_IRQBIT) & ISAR_IRQSTA)) && | 139 | while((!(cs->BC_Read_Reg(cs, 0, ISAR_IRQBIT) & ISAR_IRQSTA)) && |
139 | (timeout++ < maxdelay)) | 140 | (timeout++ < maxdelay)) |
140 | udelay(1); | 141 | udelay(1); |
141 | if (timeout >= maxdelay) { | 142 | if (timeout > maxdelay) { |
142 | printk(KERN_WARNING"isar recmsg IRQSTA timeout\n"); | 143 | printk(KERN_WARNING"isar recmsg IRQSTA timeout\n"); |
143 | return(0); | 144 | return(0); |
144 | } | 145 | } |
diff --git a/drivers/isdn/hisax/isdnl1.c b/drivers/isdn/hisax/isdnl1.c index 9ce6abe05b1a..d5eeacf565d6 100644 --- a/drivers/isdn/hisax/isdnl1.c +++ b/drivers/isdn/hisax/isdnl1.c | |||
@@ -19,6 +19,7 @@ | |||
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include <linux/init.h> | 21 | #include <linux/init.h> |
22 | #include <linux/gfp.h> | ||
22 | #include "hisax.h" | 23 | #include "hisax.h" |
23 | #include "isdnl1.h" | 24 | #include "isdnl1.h" |
24 | 25 | ||
diff --git a/drivers/isdn/hisax/isdnl2.c b/drivers/isdn/hisax/isdnl2.c index 7b9496a63b5f..0858791978d8 100644 --- a/drivers/isdn/hisax/isdnl2.c +++ b/drivers/isdn/hisax/isdnl2.c | |||
@@ -16,6 +16,7 @@ | |||
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <linux/init.h> | 18 | #include <linux/init.h> |
19 | #include <linux/gfp.h> | ||
19 | #include "hisax.h" | 20 | #include "hisax.h" |
20 | #include "isdnl2.h" | 21 | #include "isdnl2.h" |
21 | 22 | ||
diff --git a/drivers/isdn/hisax/isdnl3.c b/drivers/isdn/hisax/isdnl3.c index 06766022d3ae..fd0b643ab740 100644 --- a/drivers/isdn/hisax/isdnl3.c +++ b/drivers/isdn/hisax/isdnl3.c | |||
@@ -16,6 +16,7 @@ | |||
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <linux/init.h> | 18 | #include <linux/init.h> |
19 | #include <linux/slab.h> | ||
19 | #include "hisax.h" | 20 | #include "hisax.h" |
20 | #include "isdnl3.h" | 21 | #include "isdnl3.h" |
21 | 22 | ||
diff --git a/drivers/isdn/hisax/jade.c b/drivers/isdn/hisax/jade.c index 70840a710acf..ea8f840871d0 100644 --- a/drivers/isdn/hisax/jade.c +++ b/drivers/isdn/hisax/jade.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include "jade.h" | 17 | #include "jade.h" |
18 | #include "isdnl1.h" | 18 | #include "isdnl1.h" |
19 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
20 | #include <linux/slab.h> | ||
20 | 21 | ||
21 | 22 | ||
22 | int | 23 | int |
diff --git a/drivers/isdn/hisax/l3dss1.c b/drivers/isdn/hisax/l3dss1.c index a12fa4d34903..cc6ee2d39880 100644 --- a/drivers/isdn/hisax/l3dss1.c +++ b/drivers/isdn/hisax/l3dss1.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include "isdnl3.h" | 23 | #include "isdnl3.h" |
24 | #include "l3dss1.h" | 24 | #include "l3dss1.h" |
25 | #include <linux/ctype.h> | 25 | #include <linux/ctype.h> |
26 | #include <linux/slab.h> | ||
26 | 27 | ||
27 | extern char *HiSax_getrev(const char *revision); | 28 | extern char *HiSax_getrev(const char *revision); |
28 | static const char *dss1_revision = "$Revision: 2.32.2.3 $"; | 29 | static const char *dss1_revision = "$Revision: 2.32.2.3 $"; |
diff --git a/drivers/isdn/hisax/l3ni1.c b/drivers/isdn/hisax/l3ni1.c index 4622d43c7e10..f9584491fe8e 100644 --- a/drivers/isdn/hisax/l3ni1.c +++ b/drivers/isdn/hisax/l3ni1.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include "isdnl3.h" | 22 | #include "isdnl3.h" |
23 | #include "l3ni1.h" | 23 | #include "l3ni1.h" |
24 | #include <linux/ctype.h> | 24 | #include <linux/ctype.h> |
25 | #include <linux/slab.h> | ||
25 | 26 | ||
26 | extern char *HiSax_getrev(const char *revision); | 27 | extern char *HiSax_getrev(const char *revision); |
27 | static const char *ni1_revision = "$Revision: 2.8.2.3 $"; | 28 | static const char *ni1_revision = "$Revision: 2.8.2.3 $"; |
diff --git a/drivers/isdn/hisax/netjet.c b/drivers/isdn/hisax/netjet.c index 02c6fbaeccf8..5d7f0f2ff9b9 100644 --- a/drivers/isdn/hisax/netjet.c +++ b/drivers/isdn/hisax/netjet.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include "isdnl1.h" | 21 | #include "isdnl1.h" |
22 | #include <linux/interrupt.h> | 22 | #include <linux/interrupt.h> |
23 | #include <linux/ppp_defs.h> | 23 | #include <linux/ppp_defs.h> |
24 | #include <linux/slab.h> | ||
24 | #include <asm/io.h> | 25 | #include <asm/io.h> |
25 | #include "netjet.h" | 26 | #include "netjet.h" |
26 | 27 | ||
diff --git a/drivers/isdn/hisax/niccy.c b/drivers/isdn/hisax/niccy.c index ef00633e1d2a..ccaa6e13310f 100644 --- a/drivers/isdn/hisax/niccy.c +++ b/drivers/isdn/hisax/niccy.c | |||
@@ -297,12 +297,12 @@ int __devinit setup_niccy(struct IsdnCard *card) | |||
297 | return 0; | 297 | return 0; |
298 | } | 298 | } |
299 | } else { | 299 | } else { |
300 | #ifdef CONFIG_PCI_LEGACY | 300 | #ifdef CONFIG_PCI |
301 | static struct pci_dev *niccy_dev __devinitdata; | 301 | static struct pci_dev *niccy_dev __devinitdata; |
302 | 302 | ||
303 | u_int pci_ioaddr; | 303 | u_int pci_ioaddr; |
304 | cs->subtyp = 0; | 304 | cs->subtyp = 0; |
305 | if ((niccy_dev = pci_find_device(PCI_VENDOR_ID_SATSAGEM, | 305 | if ((niccy_dev = hisax_find_pci_device(PCI_VENDOR_ID_SATSAGEM, |
306 | PCI_DEVICE_ID_SATSAGEM_NICCY, | 306 | PCI_DEVICE_ID_SATSAGEM_NICCY, |
307 | niccy_dev))) { | 307 | niccy_dev))) { |
308 | if (pci_enable_device(niccy_dev)) | 308 | if (pci_enable_device(niccy_dev)) |
@@ -354,7 +354,7 @@ int __devinit setup_niccy(struct IsdnCard *card) | |||
354 | printk(KERN_WARNING "Niccy: io0 0 and NO_PCI_BIOS\n"); | 354 | printk(KERN_WARNING "Niccy: io0 0 and NO_PCI_BIOS\n"); |
355 | printk(KERN_WARNING "Niccy: unable to config NICCY PCI\n"); | 355 | printk(KERN_WARNING "Niccy: unable to config NICCY PCI\n"); |
356 | return 0; | 356 | return 0; |
357 | #endif /* CONFIG_PCI_LEGACY */ | 357 | #endif /* CONFIG_PCI */ |
358 | } | 358 | } |
359 | printk(KERN_INFO "HiSax: NICCY %s config irq:%d data:0x%X ale:0x%X\n", | 359 | printk(KERN_INFO "HiSax: NICCY %s config irq:%d data:0x%X ale:0x%X\n", |
360 | (cs->subtyp == 1) ? "PnP" : "PCI", | 360 | (cs->subtyp == 1) ? "PnP" : "PCI", |
diff --git a/drivers/isdn/hisax/nj_s.c b/drivers/isdn/hisax/nj_s.c index 8d36ccc87d81..2344e7b33448 100644 --- a/drivers/isdn/hisax/nj_s.c +++ b/drivers/isdn/hisax/nj_s.c | |||
@@ -276,7 +276,7 @@ setup_netjet_s(struct IsdnCard *card) | |||
276 | 276 | ||
277 | for ( ;; ) | 277 | for ( ;; ) |
278 | { | 278 | { |
279 | if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET, | 279 | if ((dev_netjet = hisax_find_pci_device(PCI_VENDOR_ID_TIGERJET, |
280 | PCI_DEVICE_ID_TIGERJET_300, dev_netjet))) { | 280 | PCI_DEVICE_ID_TIGERJET_300, dev_netjet))) { |
281 | ret = njs_pci_probe(dev_netjet, cs); | 281 | ret = njs_pci_probe(dev_netjet, cs); |
282 | if (!ret) | 282 | if (!ret) |
diff --git a/drivers/isdn/hisax/nj_u.c b/drivers/isdn/hisax/nj_u.c index d306c946ffba..095e974aed80 100644 --- a/drivers/isdn/hisax/nj_u.c +++ b/drivers/isdn/hisax/nj_u.c | |||
@@ -240,7 +240,7 @@ setup_netjet_u(struct IsdnCard *card) | |||
240 | 240 | ||
241 | for ( ;; ) | 241 | for ( ;; ) |
242 | { | 242 | { |
243 | if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET, | 243 | if ((dev_netjet = hisax_find_pci_device(PCI_VENDOR_ID_TIGERJET, |
244 | PCI_DEVICE_ID_TIGERJET_300, dev_netjet))) { | 244 | PCI_DEVICE_ID_TIGERJET_300, dev_netjet))) { |
245 | ret = nju_pci_probe(dev_netjet, cs); | 245 | ret = nju_pci_probe(dev_netjet, cs); |
246 | if (!ret) | 246 | if (!ret) |
diff --git a/drivers/isdn/hisax/sedlbauer.c b/drivers/isdn/hisax/sedlbauer.c index 5569a522e2a1..69dfc8d29017 100644 --- a/drivers/isdn/hisax/sedlbauer.c +++ b/drivers/isdn/hisax/sedlbauer.c | |||
@@ -598,7 +598,7 @@ setup_sedlbauer_isapnp(struct IsdnCard *card, int *bytecnt) | |||
598 | } | 598 | } |
599 | #endif /* __ISAPNP__ */ | 599 | #endif /* __ISAPNP__ */ |
600 | 600 | ||
601 | #ifdef CONFIG_PCI_LEGACY | 601 | #ifdef CONFIG_PCI |
602 | static struct pci_dev *dev_sedl __devinitdata = NULL; | 602 | static struct pci_dev *dev_sedl __devinitdata = NULL; |
603 | 603 | ||
604 | static int __devinit | 604 | static int __devinit |
@@ -607,7 +607,7 @@ setup_sedlbauer_pci(struct IsdnCard *card) | |||
607 | struct IsdnCardState *cs = card->cs; | 607 | struct IsdnCardState *cs = card->cs; |
608 | u16 sub_vendor_id, sub_id; | 608 | u16 sub_vendor_id, sub_id; |
609 | 609 | ||
610 | if ((dev_sedl = pci_find_device(PCI_VENDOR_ID_TIGERJET, | 610 | if ((dev_sedl = hisax_find_pci_device(PCI_VENDOR_ID_TIGERJET, |
611 | PCI_DEVICE_ID_TIGERJET_100, dev_sedl))) { | 611 | PCI_DEVICE_ID_TIGERJET_100, dev_sedl))) { |
612 | if (pci_enable_device(dev_sedl)) | 612 | if (pci_enable_device(dev_sedl)) |
613 | return(0); | 613 | return(0); |
@@ -673,7 +673,7 @@ setup_sedlbauer_pci(struct IsdnCard *card) | |||
673 | return (1); | 673 | return (1); |
674 | } | 674 | } |
675 | 675 | ||
676 | #endif /* CONFIG_PCI_LEGACY */ | 676 | #endif /* CONFIG_PCI */ |
677 | 677 | ||
678 | int __devinit | 678 | int __devinit |
679 | setup_sedlbauer(struct IsdnCard *card) | 679 | setup_sedlbauer(struct IsdnCard *card) |
diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c index 9a3c9f5e4fe8..71b3ddef03bb 100644 --- a/drivers/isdn/hisax/sedlbauer_cs.c +++ b/drivers/isdn/hisax/sedlbauer_cs.c | |||
@@ -57,24 +57,6 @@ MODULE_DESCRIPTION("ISDN4Linux: PCMCIA client driver for Sedlbauer cards"); | |||
57 | MODULE_AUTHOR("Marcus Niemann"); | 57 | MODULE_AUTHOR("Marcus Niemann"); |
58 | MODULE_LICENSE("Dual MPL/GPL"); | 58 | MODULE_LICENSE("Dual MPL/GPL"); |
59 | 59 | ||
60 | /* | ||
61 | All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If | ||
62 | you do not define PCMCIA_DEBUG at all, all the debug code will be | ||
63 | left out. If you compile with PCMCIA_DEBUG=0, the debug code will | ||
64 | be present but disabled -- but it can then be enabled for specific | ||
65 | modules at load time with a 'pc_debug=#' option to insmod. | ||
66 | */ | ||
67 | |||
68 | #ifdef PCMCIA_DEBUG | ||
69 | static int pc_debug = PCMCIA_DEBUG; | ||
70 | module_param(pc_debug, int, 0); | ||
71 | #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args); | ||
72 | static char *version = | ||
73 | "sedlbauer_cs.c 1.1a 2001/01/28 15:04:04 (M.Niemann)"; | ||
74 | #else | ||
75 | #define DEBUG(n, args...) | ||
76 | #endif | ||
77 | |||
78 | 60 | ||
79 | /*====================================================================*/ | 61 | /*====================================================================*/ |
80 | 62 | ||
@@ -94,7 +76,7 @@ module_param(protocol, int, 0); | |||
94 | event handler. | 76 | event handler. |
95 | */ | 77 | */ |
96 | 78 | ||
97 | static int sedlbauer_config(struct pcmcia_device *link); | 79 | static int sedlbauer_config(struct pcmcia_device *link) __devinit ; |
98 | static void sedlbauer_release(struct pcmcia_device *link); | 80 | static void sedlbauer_release(struct pcmcia_device *link); |
99 | 81 | ||
100 | /* | 82 | /* |
@@ -103,7 +85,7 @@ static void sedlbauer_release(struct pcmcia_device *link); | |||
103 | needed to manage one actual PCMCIA card. | 85 | needed to manage one actual PCMCIA card. |
104 | */ | 86 | */ |
105 | 87 | ||
106 | static void sedlbauer_detach(struct pcmcia_device *p_dev); | 88 | static void sedlbauer_detach(struct pcmcia_device *p_dev) __devexit; |
107 | 89 | ||
108 | /* | 90 | /* |
109 | You'll also need to prototype all the functions that will actually | 91 | You'll also need to prototype all the functions that will actually |
@@ -147,11 +129,11 @@ typedef struct local_info_t { | |||
147 | 129 | ||
148 | ======================================================================*/ | 130 | ======================================================================*/ |
149 | 131 | ||
150 | static int sedlbauer_probe(struct pcmcia_device *link) | 132 | static int __devinit sedlbauer_probe(struct pcmcia_device *link) |
151 | { | 133 | { |
152 | local_info_t *local; | 134 | local_info_t *local; |
153 | 135 | ||
154 | DEBUG(0, "sedlbauer_attach()\n"); | 136 | dev_dbg(&link->dev, "sedlbauer_attach()\n"); |
155 | 137 | ||
156 | /* Allocate space for private device-specific data */ | 138 | /* Allocate space for private device-specific data */ |
157 | local = kzalloc(sizeof(local_info_t), GFP_KERNEL); | 139 | local = kzalloc(sizeof(local_info_t), GFP_KERNEL); |
@@ -162,8 +144,7 @@ static int sedlbauer_probe(struct pcmcia_device *link) | |||
162 | link->priv = local; | 144 | link->priv = local; |
163 | 145 | ||
164 | /* Interrupt setup */ | 146 | /* Interrupt setup */ |
165 | link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; | 147 | link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; |
166 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; | ||
167 | link->irq.Handler = NULL; | 148 | link->irq.Handler = NULL; |
168 | 149 | ||
169 | /* | 150 | /* |
@@ -196,9 +177,9 @@ static int sedlbauer_probe(struct pcmcia_device *link) | |||
196 | 177 | ||
197 | ======================================================================*/ | 178 | ======================================================================*/ |
198 | 179 | ||
199 | static void sedlbauer_detach(struct pcmcia_device *link) | 180 | static void __devexit sedlbauer_detach(struct pcmcia_device *link) |
200 | { | 181 | { |
201 | DEBUG(0, "sedlbauer_detach(0x%p)\n", link); | 182 | dev_dbg(&link->dev, "sedlbauer_detach(0x%p)\n", link); |
202 | 183 | ||
203 | ((local_info_t *)link->priv)->stop = 1; | 184 | ((local_info_t *)link->priv)->stop = 1; |
204 | sedlbauer_release(link); | 185 | sedlbauer_release(link); |
@@ -214,9 +195,6 @@ static void sedlbauer_detach(struct pcmcia_device *link) | |||
214 | device available to the system. | 195 | device available to the system. |
215 | 196 | ||
216 | ======================================================================*/ | 197 | ======================================================================*/ |
217 | #define CS_CHECK(fn, ret) \ | ||
218 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | ||
219 | |||
220 | static int sedlbauer_config_check(struct pcmcia_device *p_dev, | 198 | static int sedlbauer_config_check(struct pcmcia_device *p_dev, |
221 | cistpl_cftable_entry_t *cfg, | 199 | cistpl_cftable_entry_t *cfg, |
222 | cistpl_cftable_entry_t *dflt, | 200 | cistpl_cftable_entry_t *dflt, |
@@ -293,11 +271,11 @@ static int sedlbauer_config_check(struct pcmcia_device *p_dev, | |||
293 | req->Base = mem->win[0].host_addr; | 271 | req->Base = mem->win[0].host_addr; |
294 | req->Size = mem->win[0].len; | 272 | req->Size = mem->win[0].len; |
295 | req->AccessSpeed = 0; | 273 | req->AccessSpeed = 0; |
296 | if (pcmcia_request_window(&p_dev, req, &p_dev->win) != 0) | 274 | if (pcmcia_request_window(p_dev, req, &p_dev->win) != 0) |
297 | return -ENODEV; | 275 | return -ENODEV; |
298 | map.Page = 0; | 276 | map.Page = 0; |
299 | map.CardOffset = mem->win[0].card_addr; | 277 | map.CardOffset = mem->win[0].card_addr; |
300 | if (pcmcia_map_mem_page(p_dev->win, &map) != 0) | 278 | if (pcmcia_map_mem_page(p_dev, p_dev->win, &map) != 0) |
301 | return -ENODEV; | 279 | return -ENODEV; |
302 | } | 280 | } |
303 | return 0; | 281 | return 0; |
@@ -305,14 +283,14 @@ static int sedlbauer_config_check(struct pcmcia_device *p_dev, | |||
305 | 283 | ||
306 | 284 | ||
307 | 285 | ||
308 | static int sedlbauer_config(struct pcmcia_device *link) | 286 | static int __devinit sedlbauer_config(struct pcmcia_device *link) |
309 | { | 287 | { |
310 | local_info_t *dev = link->priv; | 288 | local_info_t *dev = link->priv; |
311 | win_req_t *req; | 289 | win_req_t *req; |
312 | int last_fn, last_ret; | 290 | int ret; |
313 | IsdnCard_t icard; | 291 | IsdnCard_t icard; |
314 | 292 | ||
315 | DEBUG(0, "sedlbauer_config(0x%p)\n", link); | 293 | dev_dbg(&link->dev, "sedlbauer_config(0x%p)\n", link); |
316 | 294 | ||
317 | req = kzalloc(sizeof(win_req_t), GFP_KERNEL); | 295 | req = kzalloc(sizeof(win_req_t), GFP_KERNEL); |
318 | if (!req) | 296 | if (!req) |
@@ -330,8 +308,8 @@ static int sedlbauer_config(struct pcmcia_device *link) | |||
330 | these things without consulting the CIS, and most client drivers | 308 | these things without consulting the CIS, and most client drivers |
331 | will only use the CIS to fill in implementation-defined details. | 309 | will only use the CIS to fill in implementation-defined details. |
332 | */ | 310 | */ |
333 | last_ret = pcmcia_loop_config(link, sedlbauer_config_check, req); | 311 | ret = pcmcia_loop_config(link, sedlbauer_config_check, req); |
334 | if (last_ret) | 312 | if (ret) |
335 | goto failed; | 313 | goto failed; |
336 | 314 | ||
337 | /* | 315 | /* |
@@ -339,15 +317,20 @@ static int sedlbauer_config(struct pcmcia_device *link) | |||
339 | handler to the interrupt, unless the 'Handler' member of the | 317 | handler to the interrupt, unless the 'Handler' member of the |
340 | irq structure is initialized. | 318 | irq structure is initialized. |
341 | */ | 319 | */ |
342 | if (link->conf.Attributes & CONF_ENABLE_IRQ) | 320 | if (link->conf.Attributes & CONF_ENABLE_IRQ) { |
343 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); | 321 | ret = pcmcia_request_irq(link, &link->irq); |
322 | if (ret) | ||
323 | goto failed; | ||
324 | } | ||
344 | 325 | ||
345 | /* | 326 | /* |
346 | This actually configures the PCMCIA socket -- setting up | 327 | This actually configures the PCMCIA socket -- setting up |
347 | the I/O windows and the interrupt mapping, and putting the | 328 | the I/O windows and the interrupt mapping, and putting the |
348 | card and host interface into "Memory and IO" mode. | 329 | card and host interface into "Memory and IO" mode. |
349 | */ | 330 | */ |
350 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); | 331 | ret = pcmcia_request_configuration(link, &link->conf); |
332 | if (ret) | ||
333 | goto failed; | ||
351 | 334 | ||
352 | /* | 335 | /* |
353 | At this point, the dev_node_t structure(s) need to be | 336 | At this point, the dev_node_t structure(s) need to be |
@@ -380,19 +363,18 @@ static int sedlbauer_config(struct pcmcia_device *link) | |||
380 | icard.protocol = protocol; | 363 | icard.protocol = protocol; |
381 | icard.typ = ISDN_CTYPE_SEDLBAUER_PCMCIA; | 364 | icard.typ = ISDN_CTYPE_SEDLBAUER_PCMCIA; |
382 | 365 | ||
383 | last_ret = hisax_init_pcmcia(link, &(((local_info_t*)link->priv)->stop), &icard); | 366 | ret = hisax_init_pcmcia(link, |
384 | if (last_ret < 0) { | 367 | &(((local_info_t *)link->priv)->stop), &icard); |
385 | printk(KERN_ERR "sedlbauer_cs: failed to initialize SEDLBAUER PCMCIA %d at i/o %#x\n", | 368 | if (ret < 0) { |
386 | last_ret, link->io.BasePort1); | 369 | printk(KERN_ERR "sedlbauer_cs: failed to initialize SEDLBAUER PCMCIA %d at i/o %#x\n", |
370 | ret, link->io.BasePort1); | ||
387 | sedlbauer_release(link); | 371 | sedlbauer_release(link); |
388 | return -ENODEV; | 372 | return -ENODEV; |
389 | } else | 373 | } else |
390 | ((local_info_t*)link->priv)->cardnr = last_ret; | 374 | ((local_info_t *)link->priv)->cardnr = ret; |
391 | 375 | ||
392 | return 0; | 376 | return 0; |
393 | 377 | ||
394 | cs_failed: | ||
395 | cs_error(link, last_fn, last_ret); | ||
396 | failed: | 378 | failed: |
397 | sedlbauer_release(link); | 379 | sedlbauer_release(link); |
398 | return -ENODEV; | 380 | return -ENODEV; |
@@ -410,7 +392,7 @@ failed: | |||
410 | static void sedlbauer_release(struct pcmcia_device *link) | 392 | static void sedlbauer_release(struct pcmcia_device *link) |
411 | { | 393 | { |
412 | local_info_t *local = link->priv; | 394 | local_info_t *local = link->priv; |
413 | DEBUG(0, "sedlbauer_release(0x%p)\n", link); | 395 | dev_dbg(&link->dev, "sedlbauer_release(0x%p)\n", link); |
414 | 396 | ||
415 | if (local) { | 397 | if (local) { |
416 | if (local->cardnr >= 0) { | 398 | if (local->cardnr >= 0) { |
@@ -459,7 +441,7 @@ static struct pcmcia_driver sedlbauer_driver = { | |||
459 | .name = "sedlbauer_cs", | 441 | .name = "sedlbauer_cs", |
460 | }, | 442 | }, |
461 | .probe = sedlbauer_probe, | 443 | .probe = sedlbauer_probe, |
462 | .remove = sedlbauer_detach, | 444 | .remove = __devexit_p(sedlbauer_detach), |
463 | .id_table = sedlbauer_ids, | 445 | .id_table = sedlbauer_ids, |
464 | .suspend = sedlbauer_suspend, | 446 | .suspend = sedlbauer_suspend, |
465 | .resume = sedlbauer_resume, | 447 | .resume = sedlbauer_resume, |
diff --git a/drivers/isdn/hisax/st5481_b.c b/drivers/isdn/hisax/st5481_b.c index 95b1cdd97958..e56e5af889b6 100644 --- a/drivers/isdn/hisax/st5481_b.c +++ b/drivers/isdn/hisax/st5481_b.c | |||
@@ -11,8 +11,8 @@ | |||
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/gfp.h> | ||
14 | #include <linux/usb.h> | 15 | #include <linux/usb.h> |
15 | #include <linux/slab.h> | ||
16 | #include <linux/netdevice.h> | 16 | #include <linux/netdevice.h> |
17 | #include <linux/bitrev.h> | 17 | #include <linux/bitrev.h> |
18 | #include "st5481.h" | 18 | #include "st5481.h" |
diff --git a/drivers/isdn/hisax/st5481_d.c b/drivers/isdn/hisax/st5481_d.c index 39e8e49cfd2d..b7876b19fe73 100644 --- a/drivers/isdn/hisax/st5481_d.c +++ b/drivers/isdn/hisax/st5481_d.c | |||
@@ -11,8 +11,8 @@ | |||
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/gfp.h> | ||
14 | #include <linux/usb.h> | 15 | #include <linux/usb.h> |
15 | #include <linux/slab.h> | ||
16 | #include <linux/netdevice.h> | 16 | #include <linux/netdevice.h> |
17 | #include "st5481.h" | 17 | #include "st5481.h" |
18 | 18 | ||
diff --git a/drivers/isdn/hisax/tei.c b/drivers/isdn/hisax/tei.c index 6e65424f1f04..f4cb178b0666 100644 --- a/drivers/isdn/hisax/tei.c +++ b/drivers/isdn/hisax/tei.c | |||
@@ -17,6 +17,7 @@ | |||
17 | 17 | ||
18 | #include "hisax.h" | 18 | #include "hisax.h" |
19 | #include "isdnl2.h" | 19 | #include "isdnl2.h" |
20 | #include <linux/gfp.h> | ||
20 | #include <linux/init.h> | 21 | #include <linux/init.h> |
21 | #include <linux/random.h> | 22 | #include <linux/random.h> |
22 | 23 | ||
diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c index 623d111544d4..d010a0da8e19 100644 --- a/drivers/isdn/hisax/teles_cs.c +++ b/drivers/isdn/hisax/teles_cs.c | |||
@@ -38,23 +38,6 @@ MODULE_DESCRIPTION("ISDN4Linux: PCMCIA client driver for Teles PCMCIA cards"); | |||
38 | MODULE_AUTHOR("Christof Petig, christof.petig@wtal.de, Karsten Keil, kkeil@suse.de"); | 38 | MODULE_AUTHOR("Christof Petig, christof.petig@wtal.de, Karsten Keil, kkeil@suse.de"); |
39 | MODULE_LICENSE("GPL"); | 39 | MODULE_LICENSE("GPL"); |
40 | 40 | ||
41 | /* | ||
42 | All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If | ||
43 | you do not define PCMCIA_DEBUG at all, all the debug code will be | ||
44 | left out. If you compile with PCMCIA_DEBUG=0, the debug code will | ||
45 | be present but disabled -- but it can then be enabled for specific | ||
46 | modules at load time with a 'pc_debug=#' option to insmod. | ||
47 | */ | ||
48 | |||
49 | #ifdef PCMCIA_DEBUG | ||
50 | static int pc_debug = PCMCIA_DEBUG; | ||
51 | module_param(pc_debug, int, 0); | ||
52 | #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args); | ||
53 | static char *version = | ||
54 | "teles_cs.c 2.10 2002/07/30 22:23:34 kkeil"; | ||
55 | #else | ||
56 | #define DEBUG(n, args...) | ||
57 | #endif | ||
58 | 41 | ||
59 | /*====================================================================*/ | 42 | /*====================================================================*/ |
60 | 43 | ||
@@ -74,7 +57,7 @@ module_param(protocol, int, 0); | |||
74 | handler. | 57 | handler. |
75 | */ | 58 | */ |
76 | 59 | ||
77 | static int teles_cs_config(struct pcmcia_device *link); | 60 | static int teles_cs_config(struct pcmcia_device *link) __devinit ; |
78 | static void teles_cs_release(struct pcmcia_device *link); | 61 | static void teles_cs_release(struct pcmcia_device *link); |
79 | 62 | ||
80 | /* | 63 | /* |
@@ -83,7 +66,7 @@ static void teles_cs_release(struct pcmcia_device *link); | |||
83 | needed to manage one actual PCMCIA card. | 66 | needed to manage one actual PCMCIA card. |
84 | */ | 67 | */ |
85 | 68 | ||
86 | static void teles_detach(struct pcmcia_device *p_dev); | 69 | static void teles_detach(struct pcmcia_device *p_dev) __devexit ; |
87 | 70 | ||
88 | /* | 71 | /* |
89 | A linked list of "instances" of the teles_cs device. Each actual | 72 | A linked list of "instances" of the teles_cs device. Each actual |
@@ -129,11 +112,11 @@ typedef struct local_info_t { | |||
129 | 112 | ||
130 | ======================================================================*/ | 113 | ======================================================================*/ |
131 | 114 | ||
132 | static int teles_probe(struct pcmcia_device *link) | 115 | static int __devinit teles_probe(struct pcmcia_device *link) |
133 | { | 116 | { |
134 | local_info_t *local; | 117 | local_info_t *local; |
135 | 118 | ||
136 | DEBUG(0, "teles_attach()\n"); | 119 | dev_dbg(&link->dev, "teles_attach()\n"); |
137 | 120 | ||
138 | /* Allocate space for private device-specific data */ | 121 | /* Allocate space for private device-specific data */ |
139 | local = kzalloc(sizeof(local_info_t), GFP_KERNEL); | 122 | local = kzalloc(sizeof(local_info_t), GFP_KERNEL); |
@@ -144,8 +127,7 @@ static int teles_probe(struct pcmcia_device *link) | |||
144 | link->priv = local; | 127 | link->priv = local; |
145 | 128 | ||
146 | /* Interrupt setup */ | 129 | /* Interrupt setup */ |
147 | link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; | 130 | link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; |
148 | link->irq.IRQInfo1 = IRQ_LEVEL_ID|IRQ_SHARE_ID; | ||
149 | link->irq.Handler = NULL; | 131 | link->irq.Handler = NULL; |
150 | 132 | ||
151 | /* | 133 | /* |
@@ -174,11 +156,11 @@ static int teles_probe(struct pcmcia_device *link) | |||
174 | 156 | ||
175 | ======================================================================*/ | 157 | ======================================================================*/ |
176 | 158 | ||
177 | static void teles_detach(struct pcmcia_device *link) | 159 | static void __devexit teles_detach(struct pcmcia_device *link) |
178 | { | 160 | { |
179 | local_info_t *info = link->priv; | 161 | local_info_t *info = link->priv; |
180 | 162 | ||
181 | DEBUG(0, "teles_detach(0x%p)\n", link); | 163 | dev_dbg(&link->dev, "teles_detach(0x%p)\n", link); |
182 | 164 | ||
183 | info->busy = 1; | 165 | info->busy = 1; |
184 | teles_cs_release(link); | 166 | teles_cs_release(link); |
@@ -218,33 +200,28 @@ static int teles_cs_configcheck(struct pcmcia_device *p_dev, | |||
218 | return -ENODEV; | 200 | return -ENODEV; |
219 | } | 201 | } |
220 | 202 | ||
221 | static int teles_cs_config(struct pcmcia_device *link) | 203 | static int __devinit teles_cs_config(struct pcmcia_device *link) |
222 | { | 204 | { |
223 | local_info_t *dev; | 205 | local_info_t *dev; |
224 | int i, last_fn; | 206 | int i; |
225 | IsdnCard_t icard; | 207 | IsdnCard_t icard; |
226 | 208 | ||
227 | DEBUG(0, "teles_config(0x%p)\n", link); | 209 | dev_dbg(&link->dev, "teles_config(0x%p)\n", link); |
228 | dev = link->priv; | 210 | dev = link->priv; |
229 | 211 | ||
230 | i = pcmcia_loop_config(link, teles_cs_configcheck, NULL); | 212 | i = pcmcia_loop_config(link, teles_cs_configcheck, NULL); |
231 | if (i != 0) { | 213 | if (i != 0) |
232 | last_fn = RequestIO; | ||
233 | goto cs_failed; | 214 | goto cs_failed; |
234 | } | ||
235 | 215 | ||
236 | i = pcmcia_request_irq(link, &link->irq); | 216 | i = pcmcia_request_irq(link, &link->irq); |
237 | if (i != 0) { | 217 | if (i != 0) { |
238 | link->irq.AssignedIRQ = 0; | 218 | link->irq.AssignedIRQ = 0; |
239 | last_fn = RequestIRQ; | ||
240 | goto cs_failed; | 219 | goto cs_failed; |
241 | } | 220 | } |
242 | 221 | ||
243 | i = pcmcia_request_configuration(link, &link->conf); | 222 | i = pcmcia_request_configuration(link, &link->conf); |
244 | if (i != 0) { | 223 | if (i != 0) |
245 | last_fn = RequestConfiguration; | ||
246 | goto cs_failed; | 224 | goto cs_failed; |
247 | } | ||
248 | 225 | ||
249 | /* At this point, the dev_node_t structure(s) should be | 226 | /* At this point, the dev_node_t structure(s) should be |
250 | initialized and arranged in a linked list at link->dev. *//* */ | 227 | initialized and arranged in a linked list at link->dev. *//* */ |
@@ -283,7 +260,6 @@ static int teles_cs_config(struct pcmcia_device *link) | |||
283 | return 0; | 260 | return 0; |
284 | 261 | ||
285 | cs_failed: | 262 | cs_failed: |
286 | cs_error(link, last_fn, i); | ||
287 | teles_cs_release(link); | 263 | teles_cs_release(link); |
288 | return -ENODEV; | 264 | return -ENODEV; |
289 | } /* teles_cs_config */ | 265 | } /* teles_cs_config */ |
@@ -300,7 +276,7 @@ static void teles_cs_release(struct pcmcia_device *link) | |||
300 | { | 276 | { |
301 | local_info_t *local = link->priv; | 277 | local_info_t *local = link->priv; |
302 | 278 | ||
303 | DEBUG(0, "teles_cs_release(0x%p)\n", link); | 279 | dev_dbg(&link->dev, "teles_cs_release(0x%p)\n", link); |
304 | 280 | ||
305 | if (local) { | 281 | if (local) { |
306 | if (local->cardnr >= 0) { | 282 | if (local->cardnr >= 0) { |
@@ -343,7 +319,7 @@ static struct pcmcia_driver teles_cs_driver = { | |||
343 | .name = "teles_cs", | 319 | .name = "teles_cs", |
344 | }, | 320 | }, |
345 | .probe = teles_probe, | 321 | .probe = teles_probe, |
346 | .remove = teles_detach, | 322 | .remove = __devexit_p(teles_detach), |
347 | .id_table = teles_ids, | 323 | .id_table = teles_ids, |
348 | .suspend = teles_suspend, | 324 | .suspend = teles_suspend, |
349 | .resume = teles_resume, | 325 | .resume = teles_resume, |
diff --git a/drivers/isdn/hisax/telespci.c b/drivers/isdn/hisax/telespci.c index 28b08de4673d..b85ceb3746ce 100644 --- a/drivers/isdn/hisax/telespci.c +++ b/drivers/isdn/hisax/telespci.c | |||
@@ -300,7 +300,7 @@ setup_telespci(struct IsdnCard *card) | |||
300 | if (cs->typ != ISDN_CTYPE_TELESPCI) | 300 | if (cs->typ != ISDN_CTYPE_TELESPCI) |
301 | return (0); | 301 | return (0); |
302 | 302 | ||
303 | if ((dev_tel = pci_find_device (PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36120, dev_tel))) { | 303 | if ((dev_tel = hisax_find_pci_device (PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36120, dev_tel))) { |
304 | if (pci_enable_device(dev_tel)) | 304 | if (pci_enable_device(dev_tel)) |
305 | return(0); | 305 | return(0); |
306 | cs->irq = dev_tel->irq; | 306 | cs->irq = dev_tel->irq; |
diff --git a/drivers/isdn/hisax/w6692.c b/drivers/isdn/hisax/w6692.c index c4d862c11a60..e2cfb6f5aa42 100644 --- a/drivers/isdn/hisax/w6692.c +++ b/drivers/isdn/hisax/w6692.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include "isdnl1.h" | 16 | #include "isdnl1.h" |
17 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
18 | #include <linux/pci.h> | 18 | #include <linux/pci.h> |
19 | #include <linux/slab.h> | ||
19 | 20 | ||
20 | /* table entry in the PCI devices list */ | 21 | /* table entry in the PCI devices list */ |
21 | typedef struct { | 22 | typedef struct { |
@@ -1007,7 +1008,7 @@ setup_w6692(struct IsdnCard *card) | |||
1007 | return (0); | 1008 | return (0); |
1008 | 1009 | ||
1009 | while (id_list[id_idx].vendor_id) { | 1010 | while (id_list[id_idx].vendor_id) { |
1010 | dev_w6692 = pci_find_device(id_list[id_idx].vendor_id, | 1011 | dev_w6692 = hisax_find_pci_device(id_list[id_idx].vendor_id, |
1011 | id_list[id_idx].device_id, | 1012 | id_list[id_idx].device_id, |
1012 | dev_w6692); | 1013 | dev_w6692); |
1013 | if (dev_w6692) { | 1014 | if (dev_w6692) { |
diff --git a/drivers/isdn/hysdn/Kconfig b/drivers/isdn/hysdn/Kconfig index c9e4231968ef..e86bc6583d71 100644 --- a/drivers/isdn/hysdn/Kconfig +++ b/drivers/isdn/hysdn/Kconfig | |||
@@ -1,6 +1,3 @@ | |||
1 | # | ||
2 | # Config.in for HYSDN ISDN driver | ||
3 | # | ||
4 | config HYSDN | 1 | config HYSDN |
5 | tristate "Hypercope HYSDN cards (Champ, Ergo, Metro) support (module only)" | 2 | tristate "Hypercope HYSDN cards (Champ, Ergo, Metro) support (module only)" |
6 | depends on m && PROC_FS && PCI | 3 | depends on m && PROC_FS && PCI |
@@ -15,4 +12,3 @@ config HYSDN_CAPI | |||
15 | depends on HYSDN && ISDN_CAPI | 12 | depends on HYSDN && ISDN_CAPI |
16 | help | 13 | help |
17 | Say Y here if you like to use Hypercope's CAPI 2.0 interface. | 14 | Say Y here if you like to use Hypercope's CAPI 2.0 interface. |
18 | |||
diff --git a/drivers/isdn/hysdn/hycapi.c b/drivers/isdn/hysdn/hycapi.c index 4ffaa14b9fc4..6299b06ae009 100644 --- a/drivers/isdn/hysdn/hycapi.c +++ b/drivers/isdn/hysdn/hycapi.c | |||
@@ -11,10 +11,13 @@ | |||
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/proc_fs.h> | ||
15 | #include <linux/seq_file.h> | ||
14 | #include <linux/signal.h> | 16 | #include <linux/signal.h> |
15 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
16 | #include <linux/skbuff.h> | 18 | #include <linux/skbuff.h> |
17 | #include <linux/netdevice.h> | 19 | #include <linux/netdevice.h> |
20 | #include <linux/slab.h> | ||
18 | 21 | ||
19 | #define VER_DRIVER 0 | 22 | #define VER_DRIVER 0 |
20 | #define VER_CARDTYPE 1 | 23 | #define VER_CARDTYPE 1 |
@@ -432,26 +435,16 @@ static u16 hycapi_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) | |||
432 | return retval; | 435 | return retval; |
433 | } | 436 | } |
434 | 437 | ||
435 | /********************************************************************* | 438 | static int hycapi_proc_show(struct seq_file *m, void *v) |
436 | hycapi_read_proc | ||
437 | |||
438 | Informations provided in the /proc/capi-entries. | ||
439 | |||
440 | *********************************************************************/ | ||
441 | |||
442 | static int hycapi_read_proc(char *page, char **start, off_t off, | ||
443 | int count, int *eof, struct capi_ctr *ctrl) | ||
444 | { | 439 | { |
440 | struct capi_ctr *ctrl = m->private; | ||
445 | hycapictrl_info *cinfo = (hycapictrl_info *)(ctrl->driverdata); | 441 | hycapictrl_info *cinfo = (hycapictrl_info *)(ctrl->driverdata); |
446 | hysdn_card *card = cinfo->card; | 442 | hysdn_card *card = cinfo->card; |
447 | int len = 0; | ||
448 | char *s; | 443 | char *s; |
449 | #ifdef HYCAPI_PRINTFNAMES | 444 | |
450 | printk(KERN_NOTICE "hycapi_read_proc\n"); | 445 | seq_printf(m, "%-16s %s\n", "name", cinfo->cardname); |
451 | #endif | 446 | seq_printf(m, "%-16s 0x%x\n", "io", card->iobase); |
452 | len += sprintf(page+len, "%-16s %s\n", "name", cinfo->cardname); | 447 | seq_printf(m, "%-16s %d\n", "irq", card->irq); |
453 | len += sprintf(page+len, "%-16s 0x%x\n", "io", card->iobase); | ||
454 | len += sprintf(page+len, "%-16s %d\n", "irq", card->irq); | ||
455 | 448 | ||
456 | switch (card->brdtype) { | 449 | switch (card->brdtype) { |
457 | case BD_PCCARD: s = "HYSDN Hycard"; break; | 450 | case BD_PCCARD: s = "HYSDN Hycard"; break; |
@@ -461,24 +454,32 @@ static int hycapi_read_proc(char *page, char **start, off_t off, | |||
461 | case BD_PLEXUS: s = "HYSDN Plexus30"; break; | 454 | case BD_PLEXUS: s = "HYSDN Plexus30"; break; |
462 | default: s = "???"; break; | 455 | default: s = "???"; break; |
463 | } | 456 | } |
464 | len += sprintf(page+len, "%-16s %s\n", "type", s); | 457 | seq_printf(m, "%-16s %s\n", "type", s); |
465 | if ((s = cinfo->version[VER_DRIVER]) != NULL) | 458 | if ((s = cinfo->version[VER_DRIVER]) != NULL) |
466 | len += sprintf(page+len, "%-16s %s\n", "ver_driver", s); | 459 | seq_printf(m, "%-16s %s\n", "ver_driver", s); |
467 | if ((s = cinfo->version[VER_CARDTYPE]) != NULL) | 460 | if ((s = cinfo->version[VER_CARDTYPE]) != NULL) |
468 | len += sprintf(page+len, "%-16s %s\n", "ver_cardtype", s); | 461 | seq_printf(m, "%-16s %s\n", "ver_cardtype", s); |
469 | if ((s = cinfo->version[VER_SERIAL]) != NULL) | 462 | if ((s = cinfo->version[VER_SERIAL]) != NULL) |
470 | len += sprintf(page+len, "%-16s %s\n", "ver_serial", s); | 463 | seq_printf(m, "%-16s %s\n", "ver_serial", s); |
471 | 464 | ||
472 | len += sprintf(page+len, "%-16s %s\n", "cardname", cinfo->cardname); | 465 | seq_printf(m, "%-16s %s\n", "cardname", cinfo->cardname); |
473 | 466 | ||
474 | if (off+count >= len) | 467 | return 0; |
475 | *eof = 1; | 468 | } |
476 | if (len < off) | 469 | |
477 | return 0; | 470 | static int hycapi_proc_open(struct inode *inode, struct file *file) |
478 | *start = page + off; | 471 | { |
479 | return ((count < len-off) ? count : len-off); | 472 | return single_open(file, hycapi_proc_show, PDE(inode)->data); |
480 | } | 473 | } |
481 | 474 | ||
475 | static const struct file_operations hycapi_proc_fops = { | ||
476 | .owner = THIS_MODULE, | ||
477 | .open = hycapi_proc_open, | ||
478 | .read = seq_read, | ||
479 | .llseek = seq_lseek, | ||
480 | .release = single_release, | ||
481 | }; | ||
482 | |||
482 | /************************************************************** | 483 | /************************************************************** |
483 | hycapi_load_firmware | 484 | hycapi_load_firmware |
484 | 485 | ||
@@ -774,7 +775,7 @@ hycapi_capi_create(hysdn_card *card) | |||
774 | ctrl->load_firmware = hycapi_load_firmware; | 775 | ctrl->load_firmware = hycapi_load_firmware; |
775 | ctrl->reset_ctr = hycapi_reset_ctr; | 776 | ctrl->reset_ctr = hycapi_reset_ctr; |
776 | ctrl->procinfo = hycapi_procinfo; | 777 | ctrl->procinfo = hycapi_procinfo; |
777 | ctrl->ctr_read_proc = hycapi_read_proc; | 778 | ctrl->proc_fops = &hycapi_proc_fops; |
778 | strcpy(ctrl->name, cinfo->cardname); | 779 | strcpy(ctrl->name, cinfo->cardname); |
779 | ctrl->owner = THIS_MODULE; | 780 | ctrl->owner = THIS_MODULE; |
780 | 781 | ||
diff --git a/drivers/isdn/hysdn/hysdn_boot.c b/drivers/isdn/hysdn/hysdn_boot.c index be787e16bb79..4f541ef14f9e 100644 --- a/drivers/isdn/hysdn/hysdn_boot.c +++ b/drivers/isdn/hysdn/hysdn_boot.c | |||
@@ -143,7 +143,7 @@ pof_handle_data(hysdn_card * card, int datlen) | |||
143 | (boot->pof_recid == TAG_CABSDATA) ? "CABSDATA" : "ABSDATA", | 143 | (boot->pof_recid == TAG_CABSDATA) ? "CABSDATA" : "ABSDATA", |
144 | datlen, boot->pof_recoffset); | 144 | datlen, boot->pof_recoffset); |
145 | 145 | ||
146 | if ((boot->last_error = card->writebootseq(card, boot->buf.BootBuf, datlen) < 0)) | 146 | if ((boot->last_error = card->writebootseq(card, boot->buf.BootBuf, datlen)) < 0) |
147 | return (boot->last_error); /* error writing data */ | 147 | return (boot->last_error); /* error writing data */ |
148 | 148 | ||
149 | if (boot->pof_recoffset + datlen >= boot->pof_reclen) | 149 | if (boot->pof_recoffset + datlen >= boot->pof_reclen) |
diff --git a/drivers/isdn/hysdn/hysdn_procconf.c b/drivers/isdn/hysdn/hysdn_procconf.c index 90b35e1a4b7e..80966462d6dc 100644 --- a/drivers/isdn/hysdn/hysdn_procconf.c +++ b/drivers/isdn/hysdn/hysdn_procconf.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/poll.h> | 16 | #include <linux/poll.h> |
17 | #include <linux/proc_fs.h> | 17 | #include <linux/proc_fs.h> |
18 | #include <linux/pci.h> | 18 | #include <linux/pci.h> |
19 | #include <linux/slab.h> | ||
19 | #include <linux/smp_lock.h> | 20 | #include <linux/smp_lock.h> |
20 | #include <net/net_namespace.h> | 21 | #include <net/net_namespace.h> |
21 | 22 | ||
diff --git a/drivers/isdn/hysdn/hysdn_proclog.c b/drivers/isdn/hysdn/hysdn_proclog.c index 8bcae28c4409..e83f6fda32fe 100644 --- a/drivers/isdn/hysdn/hysdn_proclog.c +++ b/drivers/isdn/hysdn/hysdn_proclog.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/poll.h> | 14 | #include <linux/poll.h> |
15 | #include <linux/proc_fs.h> | 15 | #include <linux/proc_fs.h> |
16 | #include <linux/sched.h> | 16 | #include <linux/sched.h> |
17 | #include <linux/slab.h> | ||
17 | #include <linux/smp_lock.h> | 18 | #include <linux/smp_lock.h> |
18 | 19 | ||
19 | #include "hysdn_defs.h" | 20 | #include "hysdn_defs.h" |
diff --git a/drivers/isdn/i4l/Kconfig b/drivers/isdn/i4l/Kconfig index 07c4e49f9e77..9c6650ea848e 100644 --- a/drivers/isdn/i4l/Kconfig +++ b/drivers/isdn/i4l/Kconfig | |||
@@ -134,14 +134,7 @@ source "drivers/isdn/sc/Kconfig" | |||
134 | 134 | ||
135 | source "drivers/isdn/act2000/Kconfig" | 135 | source "drivers/isdn/act2000/Kconfig" |
136 | 136 | ||
137 | source "drivers/isdn/hysdn/Kconfig" | ||
138 | |||
139 | endmenu | 137 | endmenu |
140 | # end ISDN_I4L | 138 | # end ISDN_I4L |
141 | endif | 139 | endif |
142 | 140 | ||
143 | config ISDN_HDLC | ||
144 | tristate | ||
145 | select CRC_CCITT | ||
146 | select BITREVERSE | ||
147 | |||
diff --git a/drivers/isdn/i4l/isdn_audio.c b/drivers/isdn/i4l/isdn_audio.c index fb350c567c6b..861bdf3421f2 100644 --- a/drivers/isdn/i4l/isdn_audio.c +++ b/drivers/isdn/i4l/isdn_audio.c | |||
@@ -12,6 +12,7 @@ | |||
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/isdn.h> | 14 | #include <linux/isdn.h> |
15 | #include <linux/slab.h> | ||
15 | #include "isdn_audio.h" | 16 | #include "isdn_audio.h" |
16 | #include "isdn_common.h" | 17 | #include "isdn_common.h" |
17 | 18 | ||
diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c index adb1e8c36b46..70044ee4b228 100644 --- a/drivers/isdn/i4l/isdn_common.c +++ b/drivers/isdn/i4l/isdn_common.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/poll.h> | 16 | #include <linux/poll.h> |
17 | #include <linux/slab.h> | ||
17 | #include <linux/vmalloc.h> | 18 | #include <linux/vmalloc.h> |
18 | #include <linux/isdn.h> | 19 | #include <linux/isdn.h> |
19 | #include <linux/smp_lock.h> | 20 | #include <linux/smp_lock.h> |
@@ -1347,7 +1348,7 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) | |||
1347 | /* | 1348 | /* |
1348 | * isdn net devices manage lots of configuration variables as linked lists. | 1349 | * isdn net devices manage lots of configuration variables as linked lists. |
1349 | * Those lists must only be manipulated from user space. Some of the ioctl's | 1350 | * Those lists must only be manipulated from user space. Some of the ioctl's |
1350 | * service routines access user space and are not atomic. Therefor, ioctl's | 1351 | * service routines access user space and are not atomic. Therefore, ioctl's |
1351 | * manipulating the lists and ioctl's sleeping while accessing the lists | 1352 | * manipulating the lists and ioctl's sleeping while accessing the lists |
1352 | * are serialized by means of a semaphore. | 1353 | * are serialized by means of a semaphore. |
1353 | */ | 1354 | */ |
diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c index 90b56ed8651f..8c85d1e88cc6 100644 --- a/drivers/isdn/i4l/isdn_net.c +++ b/drivers/isdn/i4l/isdn_net.c | |||
@@ -23,6 +23,7 @@ | |||
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include <linux/isdn.h> | 25 | #include <linux/isdn.h> |
26 | #include <linux/slab.h> | ||
26 | #include <net/arp.h> | 27 | #include <net/arp.h> |
27 | #include <net/dst.h> | 28 | #include <net/dst.h> |
28 | #include <net/pkt_sched.h> | 29 | #include <net/pkt_sched.h> |
@@ -1563,7 +1564,7 @@ isdn_net_ciscohdlck_slarp_send_keepalive(unsigned long data) | |||
1563 | *(__be32 *)(p + 4) = cpu_to_be32(CISCO_SLARP_KEEPALIVE); | 1564 | *(__be32 *)(p + 4) = cpu_to_be32(CISCO_SLARP_KEEPALIVE); |
1564 | *(__be32 *)(p + 8) = cpu_to_be32(lp->cisco_myseq); | 1565 | *(__be32 *)(p + 8) = cpu_to_be32(lp->cisco_myseq); |
1565 | *(__be32 *)(p + 12) = cpu_to_be32(lp->cisco_yourseq); | 1566 | *(__be32 *)(p + 12) = cpu_to_be32(lp->cisco_yourseq); |
1566 | *(__be16 *)(p + 16) = cpu_to_be16(0xffff); // reliablity, always 0xffff | 1567 | *(__be16 *)(p + 16) = cpu_to_be16(0xffff); // reliability, always 0xffff |
1567 | p += 18; | 1568 | p += 18; |
1568 | 1569 | ||
1569 | isdn_net_write_super(lp, skb); | 1570 | isdn_net_write_super(lp, skb); |
diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c index 642d5aaf53ce..f37b8f68d0aa 100644 --- a/drivers/isdn/i4l/isdn_ppp.c +++ b/drivers/isdn/i4l/isdn_ppp.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/isdn.h> | 12 | #include <linux/isdn.h> |
13 | #include <linux/poll.h> | 13 | #include <linux/poll.h> |
14 | #include <linux/ppp-comp.h> | 14 | #include <linux/ppp-comp.h> |
15 | #include <linux/slab.h> | ||
15 | #ifdef CONFIG_IPPP_FILTER | 16 | #ifdef CONFIG_IPPP_FILTER |
16 | #include <linux/filter.h> | 17 | #include <linux/filter.h> |
17 | #endif | 18 | #endif |
@@ -836,7 +837,7 @@ isdn_ppp_write(int min, struct file *file, const char __user *buf, int count) | |||
836 | unsigned short hl; | 837 | unsigned short hl; |
837 | struct sk_buff *skb; | 838 | struct sk_buff *skb; |
838 | /* | 839 | /* |
839 | * we need to reserve enought space in front of | 840 | * we need to reserve enough space in front of |
840 | * sk_buff. old call to dev_alloc_skb only reserved | 841 | * sk_buff. old call to dev_alloc_skb only reserved |
841 | * 16 bytes, now we are looking what the driver want | 842 | * 16 bytes, now we are looking what the driver want |
842 | */ | 843 | */ |
@@ -1326,7 +1327,7 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev) | |||
1326 | struct sk_buff *new_skb; | 1327 | struct sk_buff *new_skb; |
1327 | unsigned short hl; | 1328 | unsigned short hl; |
1328 | /* | 1329 | /* |
1329 | * we need to reserve enought space in front of | 1330 | * we need to reserve enough space in front of |
1330 | * sk_buff. old call to dev_alloc_skb only reserved | 1331 | * sk_buff. old call to dev_alloc_skb only reserved |
1331 | * 16 bytes, now we are looking what the driver want. | 1332 | * 16 bytes, now we are looking what the driver want. |
1332 | */ | 1333 | */ |
@@ -1674,7 +1675,7 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, | |||
1674 | * - insert new fragment into the proper sequence slot (once that's done | 1675 | * - insert new fragment into the proper sequence slot (once that's done |
1675 | * newfrag will be set to NULL) | 1676 | * newfrag will be set to NULL) |
1676 | * - reassemble any complete fragment sequence (non-null 'start' | 1677 | * - reassemble any complete fragment sequence (non-null 'start' |
1677 | * indicates there is a continguous sequence present) | 1678 | * indicates there is a contiguous sequence present) |
1678 | * - discard any incomplete sequences that are below minseq -- due | 1679 | * - discard any incomplete sequences that are below minseq -- due |
1679 | * to the fact that sender always increment sequence number, if there | 1680 | * to the fact that sender always increment sequence number, if there |
1680 | * is an incomplete sequence below minseq, no new fragments would | 1681 | * is an incomplete sequence below minseq, no new fragments would |
diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index 2881a66c1aa9..fc8454d2eea5 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #undef ISDN_TTY_STAT_DEBUG | 12 | #undef ISDN_TTY_STAT_DEBUG |
13 | 13 | ||
14 | #include <linux/isdn.h> | 14 | #include <linux/isdn.h> |
15 | #include <linux/slab.h> | ||
15 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
16 | #include <linux/smp_lock.h> | 17 | #include <linux/smp_lock.h> |
17 | #include "isdn_common.h" | 18 | #include "isdn_common.h" |
diff --git a/drivers/isdn/i4l/isdn_ttyfax.c b/drivers/isdn/i4l/isdn_ttyfax.c index 78f7660c1d0e..4c41f191d4e2 100644 --- a/drivers/isdn/i4l/isdn_ttyfax.c +++ b/drivers/isdn/i4l/isdn_ttyfax.c | |||
@@ -470,7 +470,7 @@ isdn_tty_cmd_FCLASS2(char **p, modem_info * info) | |||
470 | } | 470 | } |
471 | return 0; | 471 | return 0; |
472 | } | 472 | } |
473 | /* BADMUL=value - dummy 0=disable errorchk disabled (treshold multiplier) */ | 473 | /* BADMUL=value - dummy 0=disable errorchk disabled (threshold multiplier) */ |
474 | if (!strncmp(p[0], "BADMUL", 6)) { | 474 | if (!strncmp(p[0], "BADMUL", 6)) { |
475 | p[0] += 6; | 475 | p[0] += 6; |
476 | switch (*p[0]) { | 476 | switch (*p[0]) { |
diff --git a/drivers/isdn/i4l/isdn_x25iface.c b/drivers/isdn/i4l/isdn_x25iface.c index 8b3efc243161..efcf1f9327e5 100644 --- a/drivers/isdn/i4l/isdn_x25iface.c +++ b/drivers/isdn/i4l/isdn_x25iface.c | |||
@@ -20,6 +20,7 @@ | |||
20 | /* #include <linux/isdn.h> */ | 20 | /* #include <linux/isdn.h> */ |
21 | #include <linux/netdevice.h> | 21 | #include <linux/netdevice.h> |
22 | #include <linux/concap.h> | 22 | #include <linux/concap.h> |
23 | #include <linux/slab.h> | ||
23 | #include <linux/wanrouter.h> | 24 | #include <linux/wanrouter.h> |
24 | #include <net/x25device.h> | 25 | #include <net/x25device.h> |
25 | #include "isdn_x25iface.h" | 26 | #include "isdn_x25iface.h" |
diff --git a/drivers/isdn/icn/Kconfig b/drivers/isdn/icn/Kconfig index 89d15eed765e..4534f21a1852 100644 --- a/drivers/isdn/icn/Kconfig +++ b/drivers/isdn/icn/Kconfig | |||
@@ -1,6 +1,3 @@ | |||
1 | # | ||
2 | # Config.in for ICN ISDN driver | ||
3 | # | ||
4 | config ISDN_DRV_ICN | 1 | config ISDN_DRV_ICN |
5 | tristate "ICN 2B and 4B support" | 2 | tristate "ICN 2B and 4B support" |
6 | depends on ISA | 3 | depends on ISA |
@@ -13,4 +10,3 @@ config ISDN_DRV_ICN | |||
13 | separately. See <file:Documentation/isdn/README> and | 10 | separately. See <file:Documentation/isdn/README> and |
14 | <file:Documentation/isdn/README.icn> for more | 11 | <file:Documentation/isdn/README.icn> for more |
15 | information. | 12 | information. |
16 | |||
diff --git a/drivers/isdn/icn/icn.c b/drivers/isdn/icn/icn.c index bf7997abc4ac..2e847a90bad0 100644 --- a/drivers/isdn/icn/icn.c +++ b/drivers/isdn/icn/icn.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include "icn.h" | 12 | #include "icn.h" |
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
15 | #include <linux/slab.h> | ||
15 | #include <linux/sched.h> | 16 | #include <linux/sched.h> |
16 | 17 | ||
17 | static int portbase = ICN_BASEADDR; | 18 | static int portbase = ICN_BASEADDR; |
diff --git a/drivers/isdn/isdnloop/isdnloop.c b/drivers/isdn/isdnloop/isdnloop.c index a335c85a736e..b8a1098b66ed 100644 --- a/drivers/isdn/isdnloop/isdnloop.c +++ b/drivers/isdn/isdnloop/isdnloop.c | |||
@@ -11,6 +11,7 @@ | |||
11 | 11 | ||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/interrupt.h> | 13 | #include <linux/interrupt.h> |
14 | #include <linux/slab.h> | ||
14 | #include <linux/init.h> | 15 | #include <linux/init.h> |
15 | #include <linux/sched.h> | 16 | #include <linux/sched.h> |
16 | #include "isdnloop.h" | 17 | #include "isdnloop.h" |
diff --git a/drivers/isdn/mISDN/clock.c b/drivers/isdn/mISDN/clock.c index f1bbc88763b2..1fa629b3b940 100644 --- a/drivers/isdn/mISDN/clock.c +++ b/drivers/isdn/mISDN/clock.c | |||
@@ -33,6 +33,7 @@ | |||
33 | * | 33 | * |
34 | */ | 34 | */ |
35 | 35 | ||
36 | #include <linux/slab.h> | ||
36 | #include <linux/types.h> | 37 | #include <linux/types.h> |
37 | #include <linux/stddef.h> | 38 | #include <linux/stddef.h> |
38 | #include <linux/spinlock.h> | 39 | #include <linux/spinlock.h> |
diff --git a/drivers/isdn/mISDN/core.c b/drivers/isdn/mISDN/core.c index 21d34be5af6a..afeebb00fe0b 100644 --- a/drivers/isdn/mISDN/core.c +++ b/drivers/isdn/mISDN/core.c | |||
@@ -12,6 +12,7 @@ | |||
12 | * | 12 | * |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/slab.h> | ||
15 | #include <linux/types.h> | 16 | #include <linux/types.h> |
16 | #include <linux/stddef.h> | 17 | #include <linux/stddef.h> |
17 | #include <linux/module.h> | 18 | #include <linux/module.h> |
diff --git a/drivers/isdn/mISDN/dsp_cmx.c b/drivers/isdn/mISDN/dsp_cmx.c index 9c7c0d1ba55f..713ef2b805a2 100644 --- a/drivers/isdn/mISDN/dsp_cmx.c +++ b/drivers/isdn/mISDN/dsp_cmx.c | |||
@@ -124,6 +124,7 @@ | |||
124 | 124 | ||
125 | /* delay.h is required for hw_lock.h */ | 125 | /* delay.h is required for hw_lock.h */ |
126 | 126 | ||
127 | #include <linux/slab.h> | ||
127 | #include <linux/delay.h> | 128 | #include <linux/delay.h> |
128 | #include <linux/mISDNif.h> | 129 | #include <linux/mISDNif.h> |
129 | #include <linux/mISDNdsp.h> | 130 | #include <linux/mISDNdsp.h> |
diff --git a/drivers/isdn/mISDN/dsp_core.c b/drivers/isdn/mISDN/dsp_core.c index 77ee2867c8b4..6f5b54864283 100644 --- a/drivers/isdn/mISDN/dsp_core.c +++ b/drivers/isdn/mISDN/dsp_core.c | |||
@@ -110,7 +110,7 @@ | |||
110 | * crossconnections and conferences via software if not possible through | 110 | * crossconnections and conferences via software if not possible through |
111 | * hardware. If hardware capability is available, hardware is used. | 111 | * hardware. If hardware capability is available, hardware is used. |
112 | * | 112 | * |
113 | * Echo: Is generated by CMX and is used to check performane of hard and | 113 | * Echo: Is generated by CMX and is used to check performance of hard and |
114 | * software CMX. | 114 | * software CMX. |
115 | * | 115 | * |
116 | * The CMX has special functions for conferences with one, two and more | 116 | * The CMX has special functions for conferences with one, two and more |
@@ -154,6 +154,7 @@ | |||
154 | */ | 154 | */ |
155 | 155 | ||
156 | #include <linux/delay.h> | 156 | #include <linux/delay.h> |
157 | #include <linux/gfp.h> | ||
157 | #include <linux/mISDNif.h> | 158 | #include <linux/mISDNif.h> |
158 | #include <linux/mISDNdsp.h> | 159 | #include <linux/mISDNdsp.h> |
159 | #include <linux/module.h> | 160 | #include <linux/module.h> |
@@ -1114,7 +1115,7 @@ static struct Bprotocol DSP = { | |||
1114 | .create = dspcreate | 1115 | .create = dspcreate |
1115 | }; | 1116 | }; |
1116 | 1117 | ||
1117 | static int dsp_init(void) | 1118 | static int __init dsp_init(void) |
1118 | { | 1119 | { |
1119 | int err; | 1120 | int err; |
1120 | int tics; | 1121 | int tics; |
@@ -1212,7 +1213,7 @@ static int dsp_init(void) | |||
1212 | } | 1213 | } |
1213 | 1214 | ||
1214 | 1215 | ||
1215 | static void dsp_cleanup(void) | 1216 | static void __exit dsp_cleanup(void) |
1216 | { | 1217 | { |
1217 | mISDN_unregister_Bprotocol(&DSP); | 1218 | mISDN_unregister_Bprotocol(&DSP); |
1218 | 1219 | ||
diff --git a/drivers/isdn/mISDN/dsp_pipeline.c b/drivers/isdn/mISDN/dsp_pipeline.c index e9941678edfa..621f31007095 100644 --- a/drivers/isdn/mISDN/dsp_pipeline.c +++ b/drivers/isdn/mISDN/dsp_pipeline.c | |||
@@ -25,6 +25,7 @@ | |||
25 | */ | 25 | */ |
26 | 26 | ||
27 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
28 | #include <linux/slab.h> | ||
28 | #include <linux/list.h> | 29 | #include <linux/list.h> |
29 | #include <linux/string.h> | 30 | #include <linux/string.h> |
30 | #include <linux/mISDNif.h> | 31 | #include <linux/mISDNif.h> |
diff --git a/drivers/isdn/mISDN/dsp_tones.c b/drivers/isdn/mISDN/dsp_tones.c index 1debf53670de..7dbe54ed1deb 100644 --- a/drivers/isdn/mISDN/dsp_tones.c +++ b/drivers/isdn/mISDN/dsp_tones.c | |||
@@ -8,6 +8,7 @@ | |||
8 | * | 8 | * |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/gfp.h> | ||
11 | #include <linux/mISDNif.h> | 12 | #include <linux/mISDNif.h> |
12 | #include <linux/mISDNdsp.h> | 13 | #include <linux/mISDNdsp.h> |
13 | #include "core.h" | 14 | #include "core.h" |
diff --git a/drivers/isdn/mISDN/hwchannel.c b/drivers/isdn/mISDN/hwchannel.c index e8049be552aa..307bd6e8988b 100644 --- a/drivers/isdn/mISDN/hwchannel.c +++ b/drivers/isdn/mISDN/hwchannel.c | |||
@@ -15,6 +15,7 @@ | |||
15 | * | 15 | * |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <linux/gfp.h> | ||
18 | #include <linux/module.h> | 19 | #include <linux/module.h> |
19 | #include <linux/mISDNhw.h> | 20 | #include <linux/mISDNhw.h> |
20 | 21 | ||
diff --git a/drivers/isdn/mISDN/l1oip_core.c b/drivers/isdn/mISDN/l1oip_core.c index 7e5f30dbc0a0..22f38e48ac4e 100644 --- a/drivers/isdn/mISDN/l1oip_core.c +++ b/drivers/isdn/mISDN/l1oip_core.c | |||
@@ -233,6 +233,7 @@ socket process and create a new one. | |||
233 | #include <linux/inet.h> | 233 | #include <linux/inet.h> |
234 | #include <linux/workqueue.h> | 234 | #include <linux/workqueue.h> |
235 | #include <linux/kthread.h> | 235 | #include <linux/kthread.h> |
236 | #include <linux/slab.h> | ||
236 | #include <net/sock.h> | 237 | #include <net/sock.h> |
237 | #include "core.h" | 238 | #include "core.h" |
238 | #include "l1oip.h" | 239 | #include "l1oip.h" |
@@ -477,7 +478,7 @@ l1oip_socket_parse(struct l1oip *hc, struct sockaddr_in *sin, u8 *buf, int len) | |||
477 | printk(KERN_DEBUG "%s: received frame, parsing... (%d)\n", | 478 | printk(KERN_DEBUG "%s: received frame, parsing... (%d)\n", |
478 | __func__, len); | 479 | __func__, len); |
479 | 480 | ||
480 | /* check lenght */ | 481 | /* check length */ |
481 | if (len < 1+1+2) { | 482 | if (len < 1+1+2) { |
482 | printk(KERN_WARNING "%s: packet error - length %d below " | 483 | printk(KERN_WARNING "%s: packet error - length %d below " |
483 | "4 bytes\n", __func__, len); | 484 | "4 bytes\n", __func__, len); |
@@ -661,7 +662,7 @@ l1oip_socket_thread(void *data) | |||
661 | size_t recvbuf_size = 1500; | 662 | size_t recvbuf_size = 1500; |
662 | int recvlen; | 663 | int recvlen; |
663 | struct socket *socket = NULL; | 664 | struct socket *socket = NULL; |
664 | DECLARE_COMPLETION(wait); | 665 | DECLARE_COMPLETION_ONSTACK(wait); |
665 | 666 | ||
666 | /* allocate buffer memory */ | 667 | /* allocate buffer memory */ |
667 | recvbuf = kmalloc(recvbuf_size, GFP_KERNEL); | 668 | recvbuf = kmalloc(recvbuf_size, GFP_KERNEL); |
@@ -1509,7 +1510,7 @@ l1oip_init(void) | |||
1509 | printk(KERN_DEBUG "%s: interface %d is %s with %s.\n", | 1510 | printk(KERN_DEBUG "%s: interface %d is %s with %s.\n", |
1510 | __func__, l1oip_cnt, pri ? "PRI" : "BRI", | 1511 | __func__, l1oip_cnt, pri ? "PRI" : "BRI", |
1511 | bundle ? "bundled IP packet for all B-channels" : | 1512 | bundle ? "bundled IP packet for all B-channels" : |
1512 | "seperate IP packets for every B-channel"); | 1513 | "separate IP packets for every B-channel"); |
1513 | 1514 | ||
1514 | hc = kzalloc(sizeof(struct l1oip), GFP_ATOMIC); | 1515 | hc = kzalloc(sizeof(struct l1oip), GFP_ATOMIC); |
1515 | if (!hc) { | 1516 | if (!hc) { |
diff --git a/drivers/isdn/mISDN/layer1.c b/drivers/isdn/mISDN/layer1.c index e826eeb1ecec..ac4aa18c632b 100644 --- a/drivers/isdn/mISDN/layer1.c +++ b/drivers/isdn/mISDN/layer1.c | |||
@@ -16,6 +16,7 @@ | |||
16 | */ | 16 | */ |
17 | 17 | ||
18 | 18 | ||
19 | #include <linux/slab.h> | ||
19 | #include <linux/module.h> | 20 | #include <linux/module.h> |
20 | #include <linux/mISDNhw.h> | 21 | #include <linux/mISDNhw.h> |
21 | #include "core.h" | 22 | #include "core.h" |
diff --git a/drivers/isdn/mISDN/layer2.c b/drivers/isdn/mISDN/layer2.c index e17f0044e0b6..c97371788764 100644 --- a/drivers/isdn/mISDN/layer2.c +++ b/drivers/isdn/mISDN/layer2.c | |||
@@ -16,6 +16,7 @@ | |||
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <linux/mISDNif.h> | 18 | #include <linux/mISDNif.h> |
19 | #include <linux/slab.h> | ||
19 | #include "core.h" | 20 | #include "core.h" |
20 | #include "fsm.h" | 21 | #include "fsm.h" |
21 | #include "layer2.h" | 22 | #include "layer2.h" |
diff --git a/drivers/isdn/mISDN/socket.c b/drivers/isdn/mISDN/socket.c index feb0fa45b664..3232206406b1 100644 --- a/drivers/isdn/mISDN/socket.c +++ b/drivers/isdn/mISDN/socket.c | |||
@@ -16,6 +16,7 @@ | |||
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <linux/mISDNif.h> | 18 | #include <linux/mISDNif.h> |
19 | #include <linux/slab.h> | ||
19 | #include "core.h" | 20 | #include "core.h" |
20 | 21 | ||
21 | static u_int *debug; | 22 | static u_int *debug; |
@@ -779,7 +780,7 @@ base_sock_create(struct net *net, struct socket *sock, int protocol) | |||
779 | } | 780 | } |
780 | 781 | ||
781 | static int | 782 | static int |
782 | mISDN_sock_create(struct net *net, struct socket *sock, int proto) | 783 | mISDN_sock_create(struct net *net, struct socket *sock, int proto, int kern) |
783 | { | 784 | { |
784 | int err = -EPROTONOSUPPORT; | 785 | int err = -EPROTONOSUPPORT; |
785 | 786 | ||
@@ -808,8 +809,7 @@ mISDN_sock_create(struct net *net, struct socket *sock, int proto) | |||
808 | return err; | 809 | return err; |
809 | } | 810 | } |
810 | 811 | ||
811 | static struct | 812 | static const struct net_proto_family mISDN_sock_family_ops = { |
812 | net_proto_family mISDN_sock_family_ops = { | ||
813 | .owner = THIS_MODULE, | 813 | .owner = THIS_MODULE, |
814 | .family = PF_ISDN, | 814 | .family = PF_ISDN, |
815 | .create = mISDN_sock_create, | 815 | .create = mISDN_sock_create, |
diff --git a/drivers/isdn/mISDN/stack.c b/drivers/isdn/mISDN/stack.c index 0d05ec43012c..b159bd59e64e 100644 --- a/drivers/isdn/mISDN/stack.c +++ b/drivers/isdn/mISDN/stack.c | |||
@@ -15,6 +15,7 @@ | |||
15 | * | 15 | * |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <linux/slab.h> | ||
18 | #include <linux/mISDNif.h> | 19 | #include <linux/mISDNif.h> |
19 | #include <linux/kthread.h> | 20 | #include <linux/kthread.h> |
20 | #include <linux/smp_lock.h> | 21 | #include <linux/smp_lock.h> |
diff --git a/drivers/isdn/mISDN/tei.c b/drivers/isdn/mISDN/tei.c index e04bad6c5baf..34e898fe2f4f 100644 --- a/drivers/isdn/mISDN/tei.c +++ b/drivers/isdn/mISDN/tei.c | |||
@@ -16,6 +16,7 @@ | |||
16 | */ | 16 | */ |
17 | #include "layer2.h" | 17 | #include "layer2.h" |
18 | #include <linux/random.h> | 18 | #include <linux/random.h> |
19 | #include <linux/slab.h> | ||
19 | #include "core.h" | 20 | #include "core.h" |
20 | 21 | ||
21 | #define ID_REQUEST 1 | 22 | #define ID_REQUEST 1 |
@@ -725,7 +726,7 @@ tei_id_ver_tout_net(struct FsmInst *fi, int event, void *arg) | |||
725 | if (tm->rcnt == 1) { | 726 | if (tm->rcnt == 1) { |
726 | if (*debug & DEBUG_L2_TEI) | 727 | if (*debug & DEBUG_L2_TEI) |
727 | tm->tei_m.printdebug(fi, | 728 | tm->tei_m.printdebug(fi, |
728 | "check req for tei %d sucessful\n", tm->l2->tei); | 729 | "check req for tei %d successful\n", tm->l2->tei); |
729 | mISDN_FsmChangeState(fi, ST_TEI_NOP); | 730 | mISDN_FsmChangeState(fi, ST_TEI_NOP); |
730 | } else if (tm->rcnt > 1) { | 731 | } else if (tm->rcnt > 1) { |
731 | /* duplicate assignment; remove */ | 732 | /* duplicate assignment; remove */ |
diff --git a/drivers/isdn/mISDN/timerdev.c b/drivers/isdn/mISDN/timerdev.c index 5b7e9bf514f1..8785004e85e0 100644 --- a/drivers/isdn/mISDN/timerdev.c +++ b/drivers/isdn/mISDN/timerdev.c | |||
@@ -19,6 +19,7 @@ | |||
19 | 19 | ||
20 | #include <linux/poll.h> | 20 | #include <linux/poll.h> |
21 | #include <linux/vmalloc.h> | 21 | #include <linux/vmalloc.h> |
22 | #include <linux/slab.h> | ||
22 | #include <linux/timer.h> | 23 | #include <linux/timer.h> |
23 | #include <linux/miscdevice.h> | 24 | #include <linux/miscdevice.h> |
24 | #include <linux/module.h> | 25 | #include <linux/module.h> |
diff --git a/drivers/isdn/pcbit/Kconfig b/drivers/isdn/pcbit/Kconfig index ffba6eca1244..e9b2dd85d410 100644 --- a/drivers/isdn/pcbit/Kconfig +++ b/drivers/isdn/pcbit/Kconfig | |||
@@ -1,6 +1,3 @@ | |||
1 | # | ||
2 | # Config.in for PCBIT ISDN driver | ||
3 | # | ||
4 | config ISDN_DRV_PCBIT | 1 | config ISDN_DRV_PCBIT |
5 | tristate "PCBIT-D support" | 2 | tristate "PCBIT-D support" |
6 | depends on ISA && (BROKEN || X86) | 3 | depends on ISA && (BROKEN || X86) |
@@ -11,4 +8,3 @@ config ISDN_DRV_PCBIT | |||
11 | the card using a utility which is distributed separately. See | 8 | the card using a utility which is distributed separately. See |
12 | <file:Documentation/isdn/README> and | 9 | <file:Documentation/isdn/README> and |
13 | <file:Documentation/isdn/README.pcbit> for more information. | 10 | <file:Documentation/isdn/README.pcbit> for more information. |
14 | |||
diff --git a/drivers/isdn/pcbit/callbacks.c b/drivers/isdn/pcbit/callbacks.c index 43ecd0f54235..976143b2346d 100644 --- a/drivers/isdn/pcbit/callbacks.c +++ b/drivers/isdn/pcbit/callbacks.c | |||
@@ -19,7 +19,6 @@ | |||
19 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
20 | 20 | ||
21 | #include <linux/types.h> | 21 | #include <linux/types.h> |
22 | #include <linux/slab.h> | ||
23 | #include <linux/mm.h> | 22 | #include <linux/mm.h> |
24 | #include <linux/skbuff.h> | 23 | #include <linux/skbuff.h> |
25 | 24 | ||
diff --git a/drivers/isdn/pcbit/edss1.c b/drivers/isdn/pcbit/edss1.c index 37e9626cebf6..d5920ae22d73 100644 --- a/drivers/isdn/pcbit/edss1.c +++ b/drivers/isdn/pcbit/edss1.c | |||
@@ -19,7 +19,6 @@ | |||
19 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
20 | 20 | ||
21 | #include <linux/types.h> | 21 | #include <linux/types.h> |
22 | #include <linux/slab.h> | ||
23 | #include <linux/mm.h> | 22 | #include <linux/mm.h> |
24 | #include <linux/skbuff.h> | 23 | #include <linux/skbuff.h> |
25 | 24 | ||
diff --git a/drivers/isdn/sc/Kconfig b/drivers/isdn/sc/Kconfig index e6510ca7bf43..7469863a7925 100644 --- a/drivers/isdn/sc/Kconfig +++ b/drivers/isdn/sc/Kconfig | |||
@@ -1,6 +1,3 @@ | |||
1 | # | ||
2 | # Config.in for Spellcaster ISDN driver | ||
3 | # | ||
4 | config ISDN_DRV_SC | 1 | config ISDN_DRV_SC |
5 | tristate "Spellcaster support" | 2 | tristate "Spellcaster support" |
6 | depends on ISA | 3 | depends on ISA |
@@ -9,4 +6,3 @@ config ISDN_DRV_SC | |||
9 | driver currently builds only in a modularized version. | 6 | driver currently builds only in a modularized version. |
10 | To build it, choose M here: the module will be called sc. | 7 | To build it, choose M here: the module will be called sc. |
11 | See <file:Documentation/isdn/README.sc> for more information. | 8 | See <file:Documentation/isdn/README.sc> for more information. |
12 | |||
diff --git a/drivers/isdn/sc/hardware.h b/drivers/isdn/sc/hardware.h index 9e6d5302bf8e..627324856ead 100644 --- a/drivers/isdn/sc/hardware.h +++ b/drivers/isdn/sc/hardware.h | |||
@@ -87,7 +87,7 @@ | |||
87 | #define BRI_CHANNELS 2 /* Number of B channels */ | 87 | #define BRI_CHANNELS 2 /* Number of B channels */ |
88 | #define BRI_BASEPG_VAL 0x98 | 88 | #define BRI_BASEPG_VAL 0x98 |
89 | #define BRI_MAGIC 0x60000 /* Magic Number */ | 89 | #define BRI_MAGIC 0x60000 /* Magic Number */ |
90 | #define BRI_MEMSIZE 0x10000 /* Ammount of RAM (64K) */ | 90 | #define BRI_MEMSIZE 0x10000 /* Amount of RAM (64K) */ |
91 | #define BRI_PARTNO "72-029" | 91 | #define BRI_PARTNO "72-029" |
92 | #define BRI_FEATURES ISDN_FEATURE_L2_HDLC | ISDN_FEATURE_L3_TRANS; | 92 | #define BRI_FEATURES ISDN_FEATURE_L2_HDLC | ISDN_FEATURE_L3_TRANS; |
93 | /* | 93 | /* |
diff --git a/drivers/isdn/sc/init.c b/drivers/isdn/sc/init.c index 5a0774880d56..ca710ab278ec 100644 --- a/drivers/isdn/sc/init.c +++ b/drivers/isdn/sc/init.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include <linux/interrupt.h> | 9 | #include <linux/interrupt.h> |
10 | #include <linux/delay.h> | 10 | #include <linux/delay.h> |
11 | #include <linux/sched.h> | 11 | #include <linux/sched.h> |
12 | #include <linux/slab.h> | ||
12 | #include "includes.h" | 13 | #include "includes.h" |
13 | #include "hardware.h" | 14 | #include "hardware.h" |
14 | #include "card.h" | 15 | #include "card.h" |