diff options
Diffstat (limited to 'drivers/isdn/gigaset/common.c')
-rw-r--r-- | drivers/isdn/gigaset/common.c | 504 |
1 files changed, 267 insertions, 237 deletions
diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c index 64371995c1a9..e55767b2ccd3 100644 --- a/drivers/isdn/gigaset/common.c +++ b/drivers/isdn/gigaset/common.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Stuff used by all variants of the driver | 2 | * Stuff used by all variants of the driver |
3 | * | 3 | * |
4 | * Copyright (c) 2001 by Stefan Eilers <Eilers.Stefan@epost.de>, | 4 | * Copyright (c) 2001 by Stefan Eilers, |
5 | * Hansjoerg Lipp <hjlipp@web.de>, | 5 | * Hansjoerg Lipp <hjlipp@web.de>, |
6 | * Tilman Schmidt <tilman@imap.cc>. | 6 | * Tilman Schmidt <tilman@imap.cc>. |
7 | * | 7 | * |
@@ -11,10 +11,6 @@ | |||
11 | * published by the Free Software Foundation; either version 2 of | 11 | * published by the Free Software Foundation; either version 2 of |
12 | * the License, or (at your option) any later version. | 12 | * the License, or (at your option) any later version. |
13 | * ===================================================================== | 13 | * ===================================================================== |
14 | * ToDo: ... | ||
15 | * ===================================================================== | ||
16 | * Version: $Id: common.c,v 1.104.4.22 2006/02/04 18:28:16 hjlipp Exp $ | ||
17 | * ===================================================================== | ||
18 | */ | 14 | */ |
19 | 15 | ||
20 | #include "gigaset.h" | 16 | #include "gigaset.h" |
@@ -23,7 +19,7 @@ | |||
23 | #include <linux/moduleparam.h> | 19 | #include <linux/moduleparam.h> |
24 | 20 | ||
25 | /* Version Information */ | 21 | /* Version Information */ |
26 | #define DRIVER_AUTHOR "Hansjoerg Lipp <hjlipp@web.de>, Tilman Schmidt <tilman@imap.cc>, Stefan Eilers <Eilers.Stefan@epost.de>" | 22 | #define DRIVER_AUTHOR "Hansjoerg Lipp <hjlipp@web.de>, Tilman Schmidt <tilman@imap.cc>, Stefan Eilers" |
27 | #define DRIVER_DESC "Driver for Gigaset 307x" | 23 | #define DRIVER_DESC "Driver for Gigaset 307x" |
28 | 24 | ||
29 | /* Module parameters */ | 25 | /* Module parameters */ |
@@ -32,21 +28,10 @@ EXPORT_SYMBOL_GPL(gigaset_debuglevel); | |||
32 | module_param_named(debug, gigaset_debuglevel, int, S_IRUGO|S_IWUSR); | 28 | module_param_named(debug, gigaset_debuglevel, int, S_IRUGO|S_IWUSR); |
33 | MODULE_PARM_DESC(debug, "debug level"); | 29 | MODULE_PARM_DESC(debug, "debug level"); |
34 | 30 | ||
35 | /*====================================================================== | 31 | /* driver state flags */ |
36 | Prototypes of internal functions | 32 | #define VALID_MINOR 0x01 |
37 | */ | 33 | #define VALID_ID 0x02 |
38 | 34 | #define ASSIGNED 0x04 | |
39 | //static void gigaset_process_response(int resp_code, int parameter, | ||
40 | // struct at_state_t *at_state, | ||
41 | // unsigned char ** pstring); | ||
42 | static struct cardstate *alloc_cs(struct gigaset_driver *drv); | ||
43 | static void free_cs(struct cardstate *cs); | ||
44 | static void make_valid(struct cardstate *cs, unsigned mask); | ||
45 | static void make_invalid(struct cardstate *cs, unsigned mask); | ||
46 | |||
47 | #define VALID_MINOR 0x01 | ||
48 | #define VALID_ID 0x02 | ||
49 | #define ASSIGNED 0x04 | ||
50 | 35 | ||
51 | /* bitwise byte inversion table */ | 36 | /* bitwise byte inversion table */ |
52 | __u8 gigaset_invtab[256] = { | 37 | __u8 gigaset_invtab[256] = { |
@@ -86,42 +71,40 @@ __u8 gigaset_invtab[256] = { | |||
86 | EXPORT_SYMBOL_GPL(gigaset_invtab); | 71 | EXPORT_SYMBOL_GPL(gigaset_invtab); |
87 | 72 | ||
88 | void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, | 73 | void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, |
89 | size_t len, const unsigned char *buf, int from_user) | 74 | size_t len, const unsigned char *buf) |
90 | { | 75 | { |
91 | unsigned char outbuf[80]; | 76 | unsigned char outbuf[80]; |
92 | unsigned char inbuf[80 - 1]; | 77 | unsigned char c; |
93 | size_t numin; | ||
94 | const unsigned char *in; | ||
95 | size_t space = sizeof outbuf - 1; | 78 | size_t space = sizeof outbuf - 1; |
96 | unsigned char *out = outbuf; | 79 | unsigned char *out = outbuf; |
80 | size_t numin = len; | ||
97 | 81 | ||
98 | if (!from_user) { | 82 | while (numin--) { |
99 | in = buf; | 83 | c = *buf++; |
100 | numin = len; | 84 | if (c == '~' || c == '^' || c == '\\') { |
101 | } else { | 85 | if (!space--) |
102 | numin = len < sizeof inbuf ? len : sizeof inbuf; | 86 | break; |
103 | in = inbuf; | 87 | *out++ = '\\'; |
104 | if (copy_from_user(inbuf, (const unsigned char __user *) buf, numin)) { | ||
105 | strncpy(inbuf, "<FAULT>", sizeof inbuf); | ||
106 | numin = sizeof "<FAULT>" - 1; | ||
107 | } | 88 | } |
108 | } | 89 | if (c & 0x80) { |
109 | 90 | if (!space--) | |
110 | for (; numin && space; --numin, ++in) { | 91 | break; |
111 | --space; | 92 | *out++ = '~'; |
112 | if (*in >= 32) | 93 | c ^= 0x80; |
113 | *out++ = *in; | 94 | } |
114 | else { | 95 | if (c < 0x20 || c == 0x7f) { |
96 | if (!space--) | ||
97 | break; | ||
115 | *out++ = '^'; | 98 | *out++ = '^'; |
116 | if (space) { | 99 | c ^= 0x40; |
117 | *out++ = '@' + *in; | ||
118 | --space; | ||
119 | } | ||
120 | } | 100 | } |
101 | if (!space--) | ||
102 | break; | ||
103 | *out++ = c; | ||
121 | } | 104 | } |
122 | *out = 0; | 105 | *out = 0; |
123 | 106 | ||
124 | dbg(level, "%s (%u bytes): %s", msg, (unsigned) len, outbuf); | 107 | gig_dbg(level, "%s (%u bytes): %s", msg, (unsigned) len, outbuf); |
125 | } | 108 | } |
126 | EXPORT_SYMBOL_GPL(gigaset_dbg_buffer); | 109 | EXPORT_SYMBOL_GPL(gigaset_dbg_buffer); |
127 | 110 | ||
@@ -146,11 +129,6 @@ int gigaset_enterconfigmode(struct cardstate *cs) | |||
146 | { | 129 | { |
147 | int i, r; | 130 | int i, r; |
148 | 131 | ||
149 | if (!atomic_read(&cs->connected)) { | ||
150 | err("not connected!"); | ||
151 | return -1; | ||
152 | } | ||
153 | |||
154 | cs->control_state = TIOCM_RTS; //FIXME | 132 | cs->control_state = TIOCM_RTS; //FIXME |
155 | 133 | ||
156 | r = setflags(cs, TIOCM_DTR, 200); | 134 | r = setflags(cs, TIOCM_DTR, 200); |
@@ -174,7 +152,7 @@ int gigaset_enterconfigmode(struct cardstate *cs) | |||
174 | return 0; | 152 | return 0; |
175 | 153 | ||
176 | error: | 154 | error: |
177 | err("error %d on setuartbits!\n", -r); | 155 | dev_err(cs->dev, "error %d on setuartbits\n", -r); |
178 | cs->control_state = TIOCM_RTS|TIOCM_DTR; // FIXME is this a good value? | 156 | cs->control_state = TIOCM_RTS|TIOCM_DTR; // FIXME is this a good value? |
179 | cs->ops->set_modem_ctrl(cs, 0, TIOCM_RTS|TIOCM_DTR); | 157 | cs->ops->set_modem_ctrl(cs, 0, TIOCM_RTS|TIOCM_DTR); |
180 | 158 | ||
@@ -187,13 +165,13 @@ static int test_timeout(struct at_state_t *at_state) | |||
187 | return 0; | 165 | return 0; |
188 | 166 | ||
189 | if (--at_state->timer_expires) { | 167 | if (--at_state->timer_expires) { |
190 | dbg(DEBUG_MCMD, "decreased timer of %p to %lu", | 168 | gig_dbg(DEBUG_MCMD, "decreased timer of %p to %lu", |
191 | at_state, at_state->timer_expires); | 169 | at_state, at_state->timer_expires); |
192 | return 0; | 170 | return 0; |
193 | } | 171 | } |
194 | 172 | ||
195 | if (!gigaset_add_event(at_state->cs, at_state, EV_TIMEOUT, NULL, | 173 | if (!gigaset_add_event(at_state->cs, at_state, EV_TIMEOUT, NULL, |
196 | atomic_read(&at_state->timer_index), NULL)) { | 174 | at_state->timer_index, NULL)) { |
197 | //FIXME what should we do? | 175 | //FIXME what should we do? |
198 | } | 176 | } |
199 | 177 | ||
@@ -221,10 +199,10 @@ static void timer_tick(unsigned long data) | |||
221 | if (test_timeout(at_state)) | 199 | if (test_timeout(at_state)) |
222 | timeout = 1; | 200 | timeout = 1; |
223 | 201 | ||
224 | if (atomic_read(&cs->running)) { | 202 | if (cs->running) { |
225 | mod_timer(&cs->timer, jiffies + GIG_TICK); | 203 | mod_timer(&cs->timer, jiffies + msecs_to_jiffies(GIG_TICK)); |
226 | if (timeout) { | 204 | if (timeout) { |
227 | dbg(DEBUG_CMD, "scheduling timeout"); | 205 | gig_dbg(DEBUG_CMD, "scheduling timeout"); |
228 | tasklet_schedule(&cs->event_tasklet); | 206 | tasklet_schedule(&cs->event_tasklet); |
229 | } | 207 | } |
230 | } | 208 | } |
@@ -238,13 +216,14 @@ int gigaset_get_channel(struct bc_state *bcs) | |||
238 | 216 | ||
239 | spin_lock_irqsave(&bcs->cs->lock, flags); | 217 | spin_lock_irqsave(&bcs->cs->lock, flags); |
240 | if (bcs->use_count) { | 218 | if (bcs->use_count) { |
241 | dbg(DEBUG_ANY, "could not allocate channel %d", bcs->channel); | 219 | gig_dbg(DEBUG_ANY, "could not allocate channel %d", |
220 | bcs->channel); | ||
242 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | 221 | spin_unlock_irqrestore(&bcs->cs->lock, flags); |
243 | return 0; | 222 | return 0; |
244 | } | 223 | } |
245 | ++bcs->use_count; | 224 | ++bcs->use_count; |
246 | bcs->busy = 1; | 225 | bcs->busy = 1; |
247 | dbg(DEBUG_ANY, "allocated channel %d", bcs->channel); | 226 | gig_dbg(DEBUG_ANY, "allocated channel %d", bcs->channel); |
248 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | 227 | spin_unlock_irqrestore(&bcs->cs->lock, flags); |
249 | return 1; | 228 | return 1; |
250 | } | 229 | } |
@@ -255,13 +234,13 @@ void gigaset_free_channel(struct bc_state *bcs) | |||
255 | 234 | ||
256 | spin_lock_irqsave(&bcs->cs->lock, flags); | 235 | spin_lock_irqsave(&bcs->cs->lock, flags); |
257 | if (!bcs->busy) { | 236 | if (!bcs->busy) { |
258 | dbg(DEBUG_ANY, "could not free channel %d", bcs->channel); | 237 | gig_dbg(DEBUG_ANY, "could not free channel %d", bcs->channel); |
259 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | 238 | spin_unlock_irqrestore(&bcs->cs->lock, flags); |
260 | return; | 239 | return; |
261 | } | 240 | } |
262 | --bcs->use_count; | 241 | --bcs->use_count; |
263 | bcs->busy = 0; | 242 | bcs->busy = 0; |
264 | dbg(DEBUG_ANY, "freed channel %d", bcs->channel); | 243 | gig_dbg(DEBUG_ANY, "freed channel %d", bcs->channel); |
265 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | 244 | spin_unlock_irqrestore(&bcs->cs->lock, flags); |
266 | } | 245 | } |
267 | 246 | ||
@@ -274,14 +253,14 @@ int gigaset_get_channels(struct cardstate *cs) | |||
274 | for (i = 0; i < cs->channels; ++i) | 253 | for (i = 0; i < cs->channels; ++i) |
275 | if (cs->bcs[i].use_count) { | 254 | if (cs->bcs[i].use_count) { |
276 | spin_unlock_irqrestore(&cs->lock, flags); | 255 | spin_unlock_irqrestore(&cs->lock, flags); |
277 | dbg(DEBUG_ANY, "could not allocated all channels"); | 256 | gig_dbg(DEBUG_ANY, "could not allocate all channels"); |
278 | return 0; | 257 | return 0; |
279 | } | 258 | } |
280 | for (i = 0; i < cs->channels; ++i) | 259 | for (i = 0; i < cs->channels; ++i) |
281 | ++cs->bcs[i].use_count; | 260 | ++cs->bcs[i].use_count; |
282 | spin_unlock_irqrestore(&cs->lock, flags); | 261 | spin_unlock_irqrestore(&cs->lock, flags); |
283 | 262 | ||
284 | dbg(DEBUG_ANY, "allocated all channels"); | 263 | gig_dbg(DEBUG_ANY, "allocated all channels"); |
285 | 264 | ||
286 | return 1; | 265 | return 1; |
287 | } | 266 | } |
@@ -291,7 +270,7 @@ void gigaset_free_channels(struct cardstate *cs) | |||
291 | unsigned long flags; | 270 | unsigned long flags; |
292 | int i; | 271 | int i; |
293 | 272 | ||
294 | dbg(DEBUG_ANY, "unblocking all channels"); | 273 | gig_dbg(DEBUG_ANY, "unblocking all channels"); |
295 | spin_lock_irqsave(&cs->lock, flags); | 274 | spin_lock_irqsave(&cs->lock, flags); |
296 | for (i = 0; i < cs->channels; ++i) | 275 | for (i = 0; i < cs->channels; ++i) |
297 | --cs->bcs[i].use_count; | 276 | --cs->bcs[i].use_count; |
@@ -303,7 +282,7 @@ void gigaset_block_channels(struct cardstate *cs) | |||
303 | unsigned long flags; | 282 | unsigned long flags; |
304 | int i; | 283 | int i; |
305 | 284 | ||
306 | dbg(DEBUG_ANY, "blocking all channels"); | 285 | gig_dbg(DEBUG_ANY, "blocking all channels"); |
307 | spin_lock_irqsave(&cs->lock, flags); | 286 | spin_lock_irqsave(&cs->lock, flags); |
308 | for (i = 0; i < cs->channels; ++i) | 287 | for (i = 0; i < cs->channels; ++i) |
309 | ++cs->bcs[i].use_count; | 288 | ++cs->bcs[i].use_count; |
@@ -314,25 +293,27 @@ static void clear_events(struct cardstate *cs) | |||
314 | { | 293 | { |
315 | struct event_t *ev; | 294 | struct event_t *ev; |
316 | unsigned head, tail; | 295 | unsigned head, tail; |
296 | unsigned long flags; | ||
317 | 297 | ||
318 | /* no locking needed (no reader/writer allowed) */ | 298 | spin_lock_irqsave(&cs->ev_lock, flags); |
319 | 299 | ||
320 | head = atomic_read(&cs->ev_head); | 300 | head = cs->ev_head; |
321 | tail = atomic_read(&cs->ev_tail); | 301 | tail = cs->ev_tail; |
322 | 302 | ||
323 | while (tail != head) { | 303 | while (tail != head) { |
324 | ev = cs->events + head; | 304 | ev = cs->events + head; |
325 | kfree(ev->ptr); | 305 | kfree(ev->ptr); |
326 | |||
327 | head = (head + 1) % MAX_EVENTS; | 306 | head = (head + 1) % MAX_EVENTS; |
328 | } | 307 | } |
329 | 308 | ||
330 | atomic_set(&cs->ev_head, tail); | 309 | cs->ev_head = tail; |
310 | |||
311 | spin_unlock_irqrestore(&cs->ev_lock, flags); | ||
331 | } | 312 | } |
332 | 313 | ||
333 | struct event_t *gigaset_add_event(struct cardstate *cs, | 314 | struct event_t *gigaset_add_event(struct cardstate *cs, |
334 | struct at_state_t *at_state, int type, | 315 | struct at_state_t *at_state, int type, |
335 | void *ptr, int parameter, void *arg) | 316 | void *ptr, int parameter, void *arg) |
336 | { | 317 | { |
337 | unsigned long flags; | 318 | unsigned long flags; |
338 | unsigned next, tail; | 319 | unsigned next, tail; |
@@ -340,9 +321,9 @@ struct event_t *gigaset_add_event(struct cardstate *cs, | |||
340 | 321 | ||
341 | spin_lock_irqsave(&cs->ev_lock, flags); | 322 | spin_lock_irqsave(&cs->ev_lock, flags); |
342 | 323 | ||
343 | tail = atomic_read(&cs->ev_tail); | 324 | tail = cs->ev_tail; |
344 | next = (tail + 1) % MAX_EVENTS; | 325 | next = (tail + 1) % MAX_EVENTS; |
345 | if (unlikely(next == atomic_read(&cs->ev_head))) | 326 | if (unlikely(next == cs->ev_head)) |
346 | err("event queue full"); | 327 | err("event queue full"); |
347 | else { | 328 | else { |
348 | event = cs->events + tail; | 329 | event = cs->events + tail; |
@@ -352,7 +333,7 @@ struct event_t *gigaset_add_event(struct cardstate *cs, | |||
352 | event->ptr = ptr; | 333 | event->ptr = ptr; |
353 | event->arg = arg; | 334 | event->arg = arg; |
354 | event->parameter = parameter; | 335 | event->parameter = parameter; |
355 | atomic_set(&cs->ev_tail, next); | 336 | cs->ev_tail = next; |
356 | } | 337 | } |
357 | 338 | ||
358 | spin_unlock_irqrestore(&cs->ev_lock, flags); | 339 | spin_unlock_irqrestore(&cs->ev_lock, flags); |
@@ -391,14 +372,14 @@ static void gigaset_freebcs(struct bc_state *bcs) | |||
391 | { | 372 | { |
392 | int i; | 373 | int i; |
393 | 374 | ||
394 | dbg(DEBUG_INIT, "freeing bcs[%d]->hw", bcs->channel); | 375 | gig_dbg(DEBUG_INIT, "freeing bcs[%d]->hw", bcs->channel); |
395 | if (!bcs->cs->ops->freebcshw(bcs)) { | 376 | if (!bcs->cs->ops->freebcshw(bcs)) { |
396 | dbg(DEBUG_INIT, "failed"); | 377 | gig_dbg(DEBUG_INIT, "failed"); |
397 | } | 378 | } |
398 | 379 | ||
399 | dbg(DEBUG_INIT, "clearing bcs[%d]->at_state", bcs->channel); | 380 | gig_dbg(DEBUG_INIT, "clearing bcs[%d]->at_state", bcs->channel); |
400 | clear_at_state(&bcs->at_state); | 381 | clear_at_state(&bcs->at_state); |
401 | dbg(DEBUG_INIT, "freeing bcs[%d]->skb", bcs->channel); | 382 | gig_dbg(DEBUG_INIT, "freeing bcs[%d]->skb", bcs->channel); |
402 | 383 | ||
403 | if (bcs->skb) | 384 | if (bcs->skb) |
404 | dev_kfree_skb(bcs->skb); | 385 | dev_kfree_skb(bcs->skb); |
@@ -408,6 +389,52 @@ static void gigaset_freebcs(struct bc_state *bcs) | |||
408 | } | 389 | } |
409 | } | 390 | } |
410 | 391 | ||
392 | static struct cardstate *alloc_cs(struct gigaset_driver *drv) | ||
393 | { | ||
394 | unsigned long flags; | ||
395 | unsigned i; | ||
396 | static struct cardstate *ret = NULL; | ||
397 | |||
398 | spin_lock_irqsave(&drv->lock, flags); | ||
399 | for (i = 0; i < drv->minors; ++i) { | ||
400 | if (!(drv->flags[i] & VALID_MINOR)) { | ||
401 | drv->flags[i] = VALID_MINOR; | ||
402 | ret = drv->cs + i; | ||
403 | } | ||
404 | if (ret) | ||
405 | break; | ||
406 | } | ||
407 | spin_unlock_irqrestore(&drv->lock, flags); | ||
408 | return ret; | ||
409 | } | ||
410 | |||
411 | static void free_cs(struct cardstate *cs) | ||
412 | { | ||
413 | unsigned long flags; | ||
414 | struct gigaset_driver *drv = cs->driver; | ||
415 | spin_lock_irqsave(&drv->lock, flags); | ||
416 | drv->flags[cs->minor_index] = 0; | ||
417 | spin_unlock_irqrestore(&drv->lock, flags); | ||
418 | } | ||
419 | |||
420 | static void make_valid(struct cardstate *cs, unsigned mask) | ||
421 | { | ||
422 | unsigned long flags; | ||
423 | struct gigaset_driver *drv = cs->driver; | ||
424 | spin_lock_irqsave(&drv->lock, flags); | ||
425 | drv->flags[cs->minor_index] |= mask; | ||
426 | spin_unlock_irqrestore(&drv->lock, flags); | ||
427 | } | ||
428 | |||
429 | static void make_invalid(struct cardstate *cs, unsigned mask) | ||
430 | { | ||
431 | unsigned long flags; | ||
432 | struct gigaset_driver *drv = cs->driver; | ||
433 | spin_lock_irqsave(&drv->lock, flags); | ||
434 | drv->flags[cs->minor_index] &= ~mask; | ||
435 | spin_unlock_irqrestore(&drv->lock, flags); | ||
436 | } | ||
437 | |||
411 | void gigaset_freecs(struct cardstate *cs) | 438 | void gigaset_freecs(struct cardstate *cs) |
412 | { | 439 | { |
413 | int i; | 440 | int i; |
@@ -416,7 +443,7 @@ void gigaset_freecs(struct cardstate *cs) | |||
416 | if (!cs) | 443 | if (!cs) |
417 | return; | 444 | return; |
418 | 445 | ||
419 | down(&cs->sem); | 446 | mutex_lock(&cs->mutex); |
420 | 447 | ||
421 | if (!cs->bcs) | 448 | if (!cs->bcs) |
422 | goto f_cs; | 449 | goto f_cs; |
@@ -424,8 +451,9 @@ void gigaset_freecs(struct cardstate *cs) | |||
424 | goto f_bcs; | 451 | goto f_bcs; |
425 | 452 | ||
426 | spin_lock_irqsave(&cs->lock, flags); | 453 | spin_lock_irqsave(&cs->lock, flags); |
427 | atomic_set(&cs->running, 0); | 454 | cs->running = 0; |
428 | spin_unlock_irqrestore(&cs->lock, flags); /* event handler and timer are not rescheduled below */ | 455 | spin_unlock_irqrestore(&cs->lock, flags); /* event handler and timer are |
456 | not rescheduled below */ | ||
429 | 457 | ||
430 | tasklet_kill(&cs->event_tasklet); | 458 | tasklet_kill(&cs->event_tasklet); |
431 | del_timer_sync(&cs->timer); | 459 | del_timer_sync(&cs->timer); |
@@ -434,7 +462,7 @@ void gigaset_freecs(struct cardstate *cs) | |||
434 | default: | 462 | default: |
435 | gigaset_if_free(cs); | 463 | gigaset_if_free(cs); |
436 | 464 | ||
437 | dbg(DEBUG_INIT, "clearing hw"); | 465 | gig_dbg(DEBUG_INIT, "clearing hw"); |
438 | cs->ops->freecshw(cs); | 466 | cs->ops->freecshw(cs); |
439 | 467 | ||
440 | //FIXME cmdbuf | 468 | //FIXME cmdbuf |
@@ -443,36 +471,36 @@ void gigaset_freecs(struct cardstate *cs) | |||
443 | case 2: /* error in initcshw */ | 471 | case 2: /* error in initcshw */ |
444 | /* Deregister from LL */ | 472 | /* Deregister from LL */ |
445 | make_invalid(cs, VALID_ID); | 473 | make_invalid(cs, VALID_ID); |
446 | dbg(DEBUG_INIT, "clearing iif"); | 474 | gig_dbg(DEBUG_INIT, "clearing iif"); |
447 | gigaset_i4l_cmd(cs, ISDN_STAT_UNLOAD); | 475 | gigaset_i4l_cmd(cs, ISDN_STAT_UNLOAD); |
448 | 476 | ||
449 | /* fall through */ | 477 | /* fall through */ |
450 | case 1: /* error when regestering to LL */ | 478 | case 1: /* error when regestering to LL */ |
451 | dbg(DEBUG_INIT, "clearing at_state"); | 479 | gig_dbg(DEBUG_INIT, "clearing at_state"); |
452 | clear_at_state(&cs->at_state); | 480 | clear_at_state(&cs->at_state); |
453 | dealloc_at_states(cs); | 481 | dealloc_at_states(cs); |
454 | 482 | ||
455 | /* fall through */ | 483 | /* fall through */ |
456 | case 0: /* error in one call to initbcs */ | 484 | case 0: /* error in one call to initbcs */ |
457 | for (i = 0; i < cs->channels; ++i) { | 485 | for (i = 0; i < cs->channels; ++i) { |
458 | dbg(DEBUG_INIT, "clearing bcs[%d]", i); | 486 | gig_dbg(DEBUG_INIT, "clearing bcs[%d]", i); |
459 | gigaset_freebcs(cs->bcs + i); | 487 | gigaset_freebcs(cs->bcs + i); |
460 | } | 488 | } |
461 | 489 | ||
462 | clear_events(cs); | 490 | clear_events(cs); |
463 | dbg(DEBUG_INIT, "freeing inbuf"); | 491 | gig_dbg(DEBUG_INIT, "freeing inbuf"); |
464 | kfree(cs->inbuf); | 492 | kfree(cs->inbuf); |
465 | } | 493 | } |
466 | f_bcs: dbg(DEBUG_INIT, "freeing bcs[]"); | 494 | f_bcs: gig_dbg(DEBUG_INIT, "freeing bcs[]"); |
467 | kfree(cs->bcs); | 495 | kfree(cs->bcs); |
468 | f_cs: dbg(DEBUG_INIT, "freeing cs"); | 496 | f_cs: gig_dbg(DEBUG_INIT, "freeing cs"); |
469 | up(&cs->sem); | 497 | mutex_unlock(&cs->mutex); |
470 | free_cs(cs); | 498 | free_cs(cs); |
471 | } | 499 | } |
472 | EXPORT_SYMBOL_GPL(gigaset_freecs); | 500 | EXPORT_SYMBOL_GPL(gigaset_freecs); |
473 | 501 | ||
474 | void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs, | 502 | void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs, |
475 | struct cardstate *cs, int cid) | 503 | struct cardstate *cs, int cid) |
476 | { | 504 | { |
477 | int i; | 505 | int i; |
478 | 506 | ||
@@ -482,8 +510,8 @@ void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs, | |||
482 | at_state->pending_commands = 0; | 510 | at_state->pending_commands = 0; |
483 | at_state->timer_expires = 0; | 511 | at_state->timer_expires = 0; |
484 | at_state->timer_active = 0; | 512 | at_state->timer_active = 0; |
485 | atomic_set(&at_state->timer_index, 0); | 513 | at_state->timer_index = 0; |
486 | atomic_set(&at_state->seq_index, 0); | 514 | at_state->seq_index = 0; |
487 | at_state->ConState = 0; | 515 | at_state->ConState = 0; |
488 | for (i = 0; i < STR_NUM; ++i) | 516 | for (i = 0; i < STR_NUM; ++i) |
489 | at_state->str_var[i] = NULL; | 517 | at_state->str_var[i] = NULL; |
@@ -501,7 +529,7 @@ void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs, | |||
501 | 529 | ||
502 | 530 | ||
503 | static void gigaset_inbuf_init(struct inbuf_t *inbuf, struct bc_state *bcs, | 531 | static void gigaset_inbuf_init(struct inbuf_t *inbuf, struct bc_state *bcs, |
504 | struct cardstate *cs, int inputstate) | 532 | struct cardstate *cs, int inputstate) |
505 | /* inbuf->read must be allocated before! */ | 533 | /* inbuf->read must be allocated before! */ |
506 | { | 534 | { |
507 | atomic_set(&inbuf->head, 0); | 535 | atomic_set(&inbuf->head, 0); |
@@ -512,9 +540,50 @@ static void gigaset_inbuf_init(struct inbuf_t *inbuf, struct bc_state *bcs, | |||
512 | inbuf->inputstate = inputstate; | 540 | inbuf->inputstate = inputstate; |
513 | } | 541 | } |
514 | 542 | ||
543 | /* append received bytes to inbuf */ | ||
544 | int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src, | ||
545 | unsigned numbytes) | ||
546 | { | ||
547 | unsigned n, head, tail, bytesleft; | ||
548 | |||
549 | gig_dbg(DEBUG_INTR, "received %u bytes", numbytes); | ||
550 | |||
551 | if (!numbytes) | ||
552 | return 0; | ||
553 | |||
554 | bytesleft = numbytes; | ||
555 | tail = atomic_read(&inbuf->tail); | ||
556 | head = atomic_read(&inbuf->head); | ||
557 | gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail); | ||
558 | |||
559 | while (bytesleft) { | ||
560 | if (head > tail) | ||
561 | n = head - 1 - tail; | ||
562 | else if (head == 0) | ||
563 | n = (RBUFSIZE-1) - tail; | ||
564 | else | ||
565 | n = RBUFSIZE - tail; | ||
566 | if (!n) { | ||
567 | dev_err(inbuf->cs->dev, | ||
568 | "buffer overflow (%u bytes lost)", bytesleft); | ||
569 | break; | ||
570 | } | ||
571 | if (n > bytesleft) | ||
572 | n = bytesleft; | ||
573 | memcpy(inbuf->data + tail, src, n); | ||
574 | bytesleft -= n; | ||
575 | tail = (tail + n) % RBUFSIZE; | ||
576 | src += n; | ||
577 | } | ||
578 | gig_dbg(DEBUG_INTR, "setting tail to %u", tail); | ||
579 | atomic_set(&inbuf->tail, tail); | ||
580 | return numbytes != bytesleft; | ||
581 | } | ||
582 | EXPORT_SYMBOL_GPL(gigaset_fill_inbuf); | ||
583 | |||
515 | /* Initialize the b-channel structure */ | 584 | /* Initialize the b-channel structure */ |
516 | static struct bc_state *gigaset_initbcs(struct bc_state *bcs, | 585 | static struct bc_state *gigaset_initbcs(struct bc_state *bcs, |
517 | struct cardstate *cs, int channel) | 586 | struct cardstate *cs, int channel) |
518 | { | 587 | { |
519 | int i; | 588 | int i; |
520 | 589 | ||
@@ -526,7 +595,7 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs, | |||
526 | bcs->trans_down = 0; | 595 | bcs->trans_down = 0; |
527 | bcs->trans_up = 0; | 596 | bcs->trans_up = 0; |
528 | 597 | ||
529 | dbg(DEBUG_INIT, "setting up bcs[%d]->at_state", channel); | 598 | gig_dbg(DEBUG_INIT, "setting up bcs[%d]->at_state", channel); |
530 | gigaset_at_init(&bcs->at_state, bcs, cs, -1); | 599 | gigaset_at_init(&bcs->at_state, bcs, cs, -1); |
531 | 600 | ||
532 | bcs->rcvbytes = 0; | 601 | bcs->rcvbytes = 0; |
@@ -535,7 +604,7 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs, | |||
535 | bcs->emptycount = 0; | 604 | bcs->emptycount = 0; |
536 | #endif | 605 | #endif |
537 | 606 | ||
538 | dbg(DEBUG_INIT, "allocating bcs[%d]->skb", channel); | 607 | gig_dbg(DEBUG_INIT, "allocating bcs[%d]->skb", channel); |
539 | bcs->fcs = PPP_INITFCS; | 608 | bcs->fcs = PPP_INITFCS; |
540 | bcs->inputstate = 0; | 609 | bcs->inputstate = 0; |
541 | if (cs->ignoreframes) { | 610 | if (cs->ignoreframes) { |
@@ -544,7 +613,7 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs, | |||
544 | } else if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL) | 613 | } else if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL) |
545 | skb_reserve(bcs->skb, HW_HDR_LEN); | 614 | skb_reserve(bcs->skb, HW_HDR_LEN); |
546 | else { | 615 | else { |
547 | warn("could not allocate skb"); | 616 | dev_warn(cs->dev, "could not allocate skb\n"); |
548 | bcs->inputstate |= INS_skip_frame; | 617 | bcs->inputstate |= INS_skip_frame; |
549 | } | 618 | } |
550 | 619 | ||
@@ -559,14 +628,13 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs, | |||
559 | for (i = 0; i < AT_NUM; ++i) | 628 | for (i = 0; i < AT_NUM; ++i) |
560 | bcs->commands[i] = NULL; | 629 | bcs->commands[i] = NULL; |
561 | 630 | ||
562 | dbg(DEBUG_INIT, " setting up bcs[%d]->hw", channel); | 631 | gig_dbg(DEBUG_INIT, " setting up bcs[%d]->hw", channel); |
563 | if (cs->ops->initbcshw(bcs)) | 632 | if (cs->ops->initbcshw(bcs)) |
564 | return bcs; | 633 | return bcs; |
565 | 634 | ||
566 | //error: | 635 | gig_dbg(DEBUG_INIT, " failed"); |
567 | dbg(DEBUG_INIT, " failed"); | ||
568 | 636 | ||
569 | dbg(DEBUG_INIT, " freeing bcs[%d]->skb", channel); | 637 | gig_dbg(DEBUG_INIT, " freeing bcs[%d]->skb", channel); |
570 | if (bcs->skb) | 638 | if (bcs->skb) |
571 | dev_kfree_skb(bcs->skb); | 639 | dev_kfree_skb(bcs->skb); |
572 | 640 | ||
@@ -578,9 +646,10 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs, | |||
578 | * Calls hardware dependent gigaset_initcshw() function | 646 | * Calls hardware dependent gigaset_initcshw() function |
579 | * Calls B channel initialization function gigaset_initbcs() for each B channel | 647 | * Calls B channel initialization function gigaset_initbcs() for each B channel |
580 | * parameters: | 648 | * parameters: |
581 | * drv hardware driver the device belongs to | 649 | * drv hardware driver the device belongs to |
582 | * channels number of B channels supported by device | 650 | * channels number of B channels supported by device |
583 | * onechannel !=0: B channel data and AT commands share one communication channel | 651 | * onechannel !=0: B channel data and AT commands share one |
652 | * communication channel | ||
584 | * ==0: B channels have separate communication channels | 653 | * ==0: B channels have separate communication channels |
585 | * ignoreframes number of frames to ignore after setting up B channel | 654 | * ignoreframes number of frames to ignore after setting up B channel |
586 | * cidmode !=0: start in CallID mode | 655 | * cidmode !=0: start in CallID mode |
@@ -593,17 +662,18 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, | |||
593 | int cidmode, const char *modulename) | 662 | int cidmode, const char *modulename) |
594 | { | 663 | { |
595 | struct cardstate *cs = NULL; | 664 | struct cardstate *cs = NULL; |
665 | unsigned long flags; | ||
596 | int i; | 666 | int i; |
597 | 667 | ||
598 | dbg(DEBUG_INIT, "allocating cs"); | 668 | gig_dbg(DEBUG_INIT, "allocating cs"); |
599 | cs = alloc_cs(drv); | 669 | cs = alloc_cs(drv); |
600 | if (!cs) | 670 | if (!cs) |
601 | goto error; | 671 | goto error; |
602 | dbg(DEBUG_INIT, "allocating bcs[0..%d]", channels - 1); | 672 | gig_dbg(DEBUG_INIT, "allocating bcs[0..%d]", channels - 1); |
603 | cs->bcs = kmalloc(channels * sizeof(struct bc_state), GFP_KERNEL); | 673 | cs->bcs = kmalloc(channels * sizeof(struct bc_state), GFP_KERNEL); |
604 | if (!cs->bcs) | 674 | if (!cs->bcs) |
605 | goto error; | 675 | goto error; |
606 | dbg(DEBUG_INIT, "allocating inbuf"); | 676 | gig_dbg(DEBUG_INIT, "allocating inbuf"); |
607 | cs->inbuf = kmalloc(sizeof(struct inbuf_t), GFP_KERNEL); | 677 | cs->inbuf = kmalloc(sizeof(struct inbuf_t), GFP_KERNEL); |
608 | if (!cs->inbuf) | 678 | if (!cs->inbuf) |
609 | goto error; | 679 | goto error; |
@@ -613,19 +683,23 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, | |||
613 | cs->onechannel = onechannel; | 683 | cs->onechannel = onechannel; |
614 | cs->ignoreframes = ignoreframes; | 684 | cs->ignoreframes = ignoreframes; |
615 | INIT_LIST_HEAD(&cs->temp_at_states); | 685 | INIT_LIST_HEAD(&cs->temp_at_states); |
616 | atomic_set(&cs->running, 0); | 686 | cs->running = 0; |
617 | init_timer(&cs->timer); /* clear next & prev */ | 687 | init_timer(&cs->timer); /* clear next & prev */ |
618 | spin_lock_init(&cs->ev_lock); | 688 | spin_lock_init(&cs->ev_lock); |
619 | atomic_set(&cs->ev_tail, 0); | 689 | cs->ev_tail = 0; |
620 | atomic_set(&cs->ev_head, 0); | 690 | cs->ev_head = 0; |
621 | init_MUTEX_LOCKED(&cs->sem); | 691 | mutex_init(&cs->mutex); |
622 | tasklet_init(&cs->event_tasklet, &gigaset_handle_event, (unsigned long) cs); | 692 | mutex_lock(&cs->mutex); |
693 | |||
694 | tasklet_init(&cs->event_tasklet, &gigaset_handle_event, | ||
695 | (unsigned long) cs); | ||
623 | atomic_set(&cs->commands_pending, 0); | 696 | atomic_set(&cs->commands_pending, 0); |
624 | cs->cur_at_seq = 0; | 697 | cs->cur_at_seq = 0; |
625 | cs->gotfwver = -1; | 698 | cs->gotfwver = -1; |
626 | cs->open_count = 0; | 699 | cs->open_count = 0; |
700 | cs->dev = NULL; | ||
627 | cs->tty = NULL; | 701 | cs->tty = NULL; |
628 | atomic_set(&cs->cidmode, cidmode != 0); | 702 | cs->cidmode = cidmode != 0; |
629 | 703 | ||
630 | //if(onechannel) { //FIXME | 704 | //if(onechannel) { //FIXME |
631 | cs->tabnocid = gigaset_tab_nocid_m10x; | 705 | cs->tabnocid = gigaset_tab_nocid_m10x; |
@@ -642,50 +716,43 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, | |||
642 | atomic_set(&cs->mstate, MS_UNINITIALIZED); | 716 | atomic_set(&cs->mstate, MS_UNINITIALIZED); |
643 | 717 | ||
644 | for (i = 0; i < channels; ++i) { | 718 | for (i = 0; i < channels; ++i) { |
645 | dbg(DEBUG_INIT, "setting up bcs[%d].read", i); | 719 | gig_dbg(DEBUG_INIT, "setting up bcs[%d].read", i); |
646 | if (!gigaset_initbcs(cs->bcs + i, cs, i)) | 720 | if (!gigaset_initbcs(cs->bcs + i, cs, i)) |
647 | goto error; | 721 | goto error; |
648 | } | 722 | } |
649 | 723 | ||
650 | ++cs->cs_init; | 724 | ++cs->cs_init; |
651 | 725 | ||
652 | dbg(DEBUG_INIT, "setting up at_state"); | 726 | gig_dbg(DEBUG_INIT, "setting up at_state"); |
653 | spin_lock_init(&cs->lock); | 727 | spin_lock_init(&cs->lock); |
654 | gigaset_at_init(&cs->at_state, NULL, cs, 0); | 728 | gigaset_at_init(&cs->at_state, NULL, cs, 0); |
655 | cs->dle = 0; | 729 | cs->dle = 0; |
656 | cs->cbytes = 0; | 730 | cs->cbytes = 0; |
657 | 731 | ||
658 | dbg(DEBUG_INIT, "setting up inbuf"); | 732 | gig_dbg(DEBUG_INIT, "setting up inbuf"); |
659 | if (onechannel) { //FIXME distinction necessary? | 733 | if (onechannel) { //FIXME distinction necessary? |
660 | gigaset_inbuf_init(cs->inbuf, cs->bcs, cs, INS_command); | 734 | gigaset_inbuf_init(cs->inbuf, cs->bcs, cs, INS_command); |
661 | } else | 735 | } else |
662 | gigaset_inbuf_init(cs->inbuf, NULL, cs, INS_command); | 736 | gigaset_inbuf_init(cs->inbuf, NULL, cs, INS_command); |
663 | 737 | ||
664 | atomic_set(&cs->connected, 0); | 738 | cs->connected = 0; |
739 | cs->isdn_up = 0; | ||
665 | 740 | ||
666 | dbg(DEBUG_INIT, "setting up cmdbuf"); | 741 | gig_dbg(DEBUG_INIT, "setting up cmdbuf"); |
667 | cs->cmdbuf = cs->lastcmdbuf = NULL; | 742 | cs->cmdbuf = cs->lastcmdbuf = NULL; |
668 | spin_lock_init(&cs->cmdlock); | 743 | spin_lock_init(&cs->cmdlock); |
669 | cs->curlen = 0; | 744 | cs->curlen = 0; |
670 | cs->cmdbytes = 0; | 745 | cs->cmdbytes = 0; |
671 | 746 | ||
672 | /* | 747 | gig_dbg(DEBUG_INIT, "setting up iif"); |
673 | * Tell the ISDN4Linux subsystem (the LL) that | ||
674 | * a driver for a USB-Device is available ! | ||
675 | * If this is done, "isdnctrl" is able to bind a device for this driver even | ||
676 | * if no physical usb-device is currently connected. | ||
677 | * But this device will just be accessable if a physical USB device is connected | ||
678 | * (via "gigaset_probe") . | ||
679 | */ | ||
680 | dbg(DEBUG_INIT, "setting up iif"); | ||
681 | if (!gigaset_register_to_LL(cs, modulename)) { | 748 | if (!gigaset_register_to_LL(cs, modulename)) { |
682 | err("register_isdn=>error"); | 749 | err("register_isdn failed"); |
683 | goto error; | 750 | goto error; |
684 | } | 751 | } |
685 | 752 | ||
686 | make_valid(cs, VALID_ID); | 753 | make_valid(cs, VALID_ID); |
687 | ++cs->cs_init; | 754 | ++cs->cs_init; |
688 | dbg(DEBUG_INIT, "setting up hw"); | 755 | gig_dbg(DEBUG_INIT, "setting up hw"); |
689 | if (!cs->ops->initcshw(cs)) | 756 | if (!cs->ops->initcshw(cs)) |
690 | goto error; | 757 | goto error; |
691 | 758 | ||
@@ -693,27 +760,28 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, | |||
693 | 760 | ||
694 | gigaset_if_init(cs); | 761 | gigaset_if_init(cs); |
695 | 762 | ||
696 | atomic_set(&cs->running, 1); | 763 | spin_lock_irqsave(&cs->lock, flags); |
697 | cs->timer.data = (unsigned long) cs; | 764 | cs->running = 1; |
698 | cs->timer.function = timer_tick; | 765 | spin_unlock_irqrestore(&cs->lock, flags); |
699 | cs->timer.expires = jiffies + GIG_TICK; | 766 | setup_timer(&cs->timer, timer_tick, (unsigned long) cs); |
767 | cs->timer.expires = jiffies + msecs_to_jiffies(GIG_TICK); | ||
700 | /* FIXME: can jiffies increase too much until the timer is added? | 768 | /* FIXME: can jiffies increase too much until the timer is added? |
701 | * Same problem(?) with mod_timer() in timer_tick(). */ | 769 | * Same problem(?) with mod_timer() in timer_tick(). */ |
702 | add_timer(&cs->timer); | 770 | add_timer(&cs->timer); |
703 | 771 | ||
704 | dbg(DEBUG_INIT, "cs initialized!"); | 772 | gig_dbg(DEBUG_INIT, "cs initialized"); |
705 | up(&cs->sem); | 773 | mutex_unlock(&cs->mutex); |
706 | return cs; | 774 | return cs; |
707 | 775 | ||
708 | error: if (cs) | 776 | error: if (cs) |
709 | up(&cs->sem); | 777 | mutex_unlock(&cs->mutex); |
710 | dbg(DEBUG_INIT, "failed"); | 778 | gig_dbg(DEBUG_INIT, "failed"); |
711 | gigaset_freecs(cs); | 779 | gigaset_freecs(cs); |
712 | return NULL; | 780 | return NULL; |
713 | } | 781 | } |
714 | EXPORT_SYMBOL_GPL(gigaset_initcs); | 782 | EXPORT_SYMBOL_GPL(gigaset_initcs); |
715 | 783 | ||
716 | /* ReInitialize the b-channel structure */ /* e.g. called on hangup, disconnect */ | 784 | /* ReInitialize the b-channel structure on hangup */ |
717 | void gigaset_bcs_reinit(struct bc_state *bcs) | 785 | void gigaset_bcs_reinit(struct bc_state *bcs) |
718 | { | 786 | { |
719 | struct sk_buff *skb; | 787 | struct sk_buff *skb; |
@@ -723,12 +791,12 @@ void gigaset_bcs_reinit(struct bc_state *bcs) | |||
723 | while ((skb = skb_dequeue(&bcs->squeue)) != NULL) | 791 | while ((skb = skb_dequeue(&bcs->squeue)) != NULL) |
724 | dev_kfree_skb(skb); | 792 | dev_kfree_skb(skb); |
725 | 793 | ||
726 | spin_lock_irqsave(&cs->lock, flags); //FIXME | 794 | spin_lock_irqsave(&cs->lock, flags); |
727 | clear_at_state(&bcs->at_state); | 795 | clear_at_state(&bcs->at_state); |
728 | bcs->at_state.ConState = 0; | 796 | bcs->at_state.ConState = 0; |
729 | bcs->at_state.timer_active = 0; | 797 | bcs->at_state.timer_active = 0; |
730 | bcs->at_state.timer_expires = 0; | 798 | bcs->at_state.timer_expires = 0; |
731 | bcs->at_state.cid = -1; /* No CID defined */ | 799 | bcs->at_state.cid = -1; /* No CID defined */ |
732 | spin_unlock_irqrestore(&cs->lock, flags); | 800 | spin_unlock_irqrestore(&cs->lock, flags); |
733 | 801 | ||
734 | bcs->inputstate = 0; | 802 | bcs->inputstate = 0; |
@@ -803,11 +871,14 @@ static void cleanup_cs(struct cardstate *cs) | |||
803 | 871 | ||
804 | int gigaset_start(struct cardstate *cs) | 872 | int gigaset_start(struct cardstate *cs) |
805 | { | 873 | { |
806 | if (down_interruptible(&cs->sem)) | 874 | unsigned long flags; |
875 | |||
876 | if (mutex_lock_interruptible(&cs->mutex)) | ||
807 | return 0; | 877 | return 0; |
808 | //info("USB device for Gigaset 307x now attached to Dev %d", ucs->minor); | ||
809 | 878 | ||
810 | atomic_set(&cs->connected, 1); | 879 | spin_lock_irqsave(&cs->lock, flags); |
880 | cs->connected = 1; | ||
881 | spin_unlock_irqrestore(&cs->lock, flags); | ||
811 | 882 | ||
812 | if (atomic_read(&cs->mstate) != MS_LOCKED) { | 883 | if (atomic_read(&cs->mstate) != MS_LOCKED) { |
813 | cs->ops->set_modem_ctrl(cs, 0, TIOCM_DTR|TIOCM_RTS); | 884 | cs->ops->set_modem_ctrl(cs, 0, TIOCM_DTR|TIOCM_RTS); |
@@ -826,23 +897,26 @@ int gigaset_start(struct cardstate *cs) | |||
826 | goto error; | 897 | goto error; |
827 | } | 898 | } |
828 | 899 | ||
829 | dbg(DEBUG_CMD, "scheduling START"); | 900 | gig_dbg(DEBUG_CMD, "scheduling START"); |
830 | gigaset_schedule_event(cs); | 901 | gigaset_schedule_event(cs); |
831 | 902 | ||
832 | wait_event(cs->waitqueue, !cs->waiting); | 903 | wait_event(cs->waitqueue, !cs->waiting); |
833 | 904 | ||
834 | up(&cs->sem); | 905 | /* set up device sysfs */ |
906 | gigaset_init_dev_sysfs(cs); | ||
907 | |||
908 | mutex_unlock(&cs->mutex); | ||
835 | return 1; | 909 | return 1; |
836 | 910 | ||
837 | error: | 911 | error: |
838 | up(&cs->sem); | 912 | mutex_unlock(&cs->mutex); |
839 | return 0; | 913 | return 0; |
840 | } | 914 | } |
841 | EXPORT_SYMBOL_GPL(gigaset_start); | 915 | EXPORT_SYMBOL_GPL(gigaset_start); |
842 | 916 | ||
843 | void gigaset_shutdown(struct cardstate *cs) | 917 | void gigaset_shutdown(struct cardstate *cs) |
844 | { | 918 | { |
845 | down(&cs->sem); | 919 | mutex_lock(&cs->mutex); |
846 | 920 | ||
847 | cs->waiting = 1; | 921 | cs->waiting = 1; |
848 | 922 | ||
@@ -851,11 +925,11 @@ void gigaset_shutdown(struct cardstate *cs) | |||
851 | goto exit; | 925 | goto exit; |
852 | } | 926 | } |
853 | 927 | ||
854 | dbg(DEBUG_CMD, "scheduling SHUTDOWN"); | 928 | gig_dbg(DEBUG_CMD, "scheduling SHUTDOWN"); |
855 | gigaset_schedule_event(cs); | 929 | gigaset_schedule_event(cs); |
856 | 930 | ||
857 | if (wait_event_interruptible(cs->waitqueue, !cs->waiting)) { | 931 | if (wait_event_interruptible(cs->waitqueue, !cs->waiting)) { |
858 | warn("aborted"); | 932 | warn("%s: aborted", __func__); |
859 | //FIXME | 933 | //FIXME |
860 | } | 934 | } |
861 | 935 | ||
@@ -872,15 +946,13 @@ void gigaset_shutdown(struct cardstate *cs) | |||
872 | cleanup_cs(cs); | 946 | cleanup_cs(cs); |
873 | 947 | ||
874 | exit: | 948 | exit: |
875 | up(&cs->sem); | 949 | mutex_unlock(&cs->mutex); |
876 | } | 950 | } |
877 | EXPORT_SYMBOL_GPL(gigaset_shutdown); | 951 | EXPORT_SYMBOL_GPL(gigaset_shutdown); |
878 | 952 | ||
879 | void gigaset_stop(struct cardstate *cs) | 953 | void gigaset_stop(struct cardstate *cs) |
880 | { | 954 | { |
881 | down(&cs->sem); | 955 | mutex_lock(&cs->mutex); |
882 | |||
883 | atomic_set(&cs->connected, 0); | ||
884 | 956 | ||
885 | cs->waiting = 1; | 957 | cs->waiting = 1; |
886 | 958 | ||
@@ -889,21 +961,21 @@ void gigaset_stop(struct cardstate *cs) | |||
889 | goto exit; | 961 | goto exit; |
890 | } | 962 | } |
891 | 963 | ||
892 | dbg(DEBUG_CMD, "scheduling STOP"); | 964 | gig_dbg(DEBUG_CMD, "scheduling STOP"); |
893 | gigaset_schedule_event(cs); | 965 | gigaset_schedule_event(cs); |
894 | 966 | ||
895 | if (wait_event_interruptible(cs->waitqueue, !cs->waiting)) { | 967 | if (wait_event_interruptible(cs->waitqueue, !cs->waiting)) { |
896 | warn("aborted"); | 968 | warn("%s: aborted", __func__); |
897 | //FIXME | 969 | //FIXME |
898 | } | 970 | } |
899 | 971 | ||
900 | /* Tell the LL that the device is not available .. */ | 972 | /* clear device sysfs */ |
901 | gigaset_i4l_cmd(cs, ISDN_STAT_STOP); // FIXME move to event layer? | 973 | gigaset_free_dev_sysfs(cs); |
902 | 974 | ||
903 | cleanup_cs(cs); | 975 | cleanup_cs(cs); |
904 | 976 | ||
905 | exit: | 977 | exit: |
906 | up(&cs->sem); | 978 | mutex_unlock(&cs->mutex); |
907 | } | 979 | } |
908 | EXPORT_SYMBOL_GPL(gigaset_stop); | 980 | EXPORT_SYMBOL_GPL(gigaset_stop); |
909 | 981 | ||
@@ -947,31 +1019,25 @@ void gigaset_debugdrivers(void) | |||
947 | 1019 | ||
948 | spin_lock_irqsave(&driver_lock, flags); | 1020 | spin_lock_irqsave(&driver_lock, flags); |
949 | list_for_each_entry(drv, &drivers, list) { | 1021 | list_for_each_entry(drv, &drivers, list) { |
950 | dbg(DEBUG_DRIVER, "driver %p", drv); | 1022 | gig_dbg(DEBUG_DRIVER, "driver %p", drv); |
951 | spin_lock(&drv->lock); | 1023 | spin_lock(&drv->lock); |
952 | for (i = 0; i < drv->minors; ++i) { | 1024 | for (i = 0; i < drv->minors; ++i) { |
953 | dbg(DEBUG_DRIVER, " index %u", i); | 1025 | gig_dbg(DEBUG_DRIVER, " index %u", i); |
954 | dbg(DEBUG_DRIVER, " flags 0x%02x", drv->flags[i]); | 1026 | gig_dbg(DEBUG_DRIVER, " flags 0x%02x", |
1027 | drv->flags[i]); | ||
955 | cs = drv->cs + i; | 1028 | cs = drv->cs + i; |
956 | dbg(DEBUG_DRIVER, " cardstate %p", cs); | 1029 | gig_dbg(DEBUG_DRIVER, " cardstate %p", cs); |
957 | dbg(DEBUG_DRIVER, " minor_index %u", cs->minor_index); | 1030 | gig_dbg(DEBUG_DRIVER, " minor_index %u", |
958 | dbg(DEBUG_DRIVER, " driver %p", cs->driver); | 1031 | cs->minor_index); |
959 | dbg(DEBUG_DRIVER, " i4l id %d", cs->myid); | 1032 | gig_dbg(DEBUG_DRIVER, " driver %p", cs->driver); |
1033 | gig_dbg(DEBUG_DRIVER, " i4l id %d", cs->myid); | ||
960 | } | 1034 | } |
961 | spin_unlock(&drv->lock); | 1035 | spin_unlock(&drv->lock); |
962 | } | 1036 | } |
963 | spin_unlock_irqrestore(&driver_lock, flags); | 1037 | spin_unlock_irqrestore(&driver_lock, flags); |
964 | } | 1038 | } |
965 | EXPORT_SYMBOL_GPL(gigaset_debugdrivers); | ||
966 | |||
967 | struct cardstate *gigaset_get_cs_by_tty(struct tty_struct *tty) | ||
968 | { | ||
969 | if (tty->index < 0 || tty->index >= tty->driver->num) | ||
970 | return NULL; | ||
971 | return gigaset_get_cs_by_minor(tty->index + tty->driver->minor_start); | ||
972 | } | ||
973 | 1039 | ||
974 | struct cardstate *gigaset_get_cs_by_minor(unsigned minor) | 1040 | static struct cardstate *gigaset_get_cs_by_minor(unsigned minor) |
975 | { | 1041 | { |
976 | unsigned long flags; | 1042 | unsigned long flags; |
977 | static struct cardstate *ret = NULL; | 1043 | static struct cardstate *ret = NULL; |
@@ -994,6 +1060,13 @@ struct cardstate *gigaset_get_cs_by_minor(unsigned minor) | |||
994 | return ret; | 1060 | return ret; |
995 | } | 1061 | } |
996 | 1062 | ||
1063 | struct cardstate *gigaset_get_cs_by_tty(struct tty_struct *tty) | ||
1064 | { | ||
1065 | if (tty->index < 0 || tty->index >= tty->driver->num) | ||
1066 | return NULL; | ||
1067 | return gigaset_get_cs_by_minor(tty->index + tty->driver->minor_start); | ||
1068 | } | ||
1069 | |||
997 | void gigaset_freedriver(struct gigaset_driver *drv) | 1070 | void gigaset_freedriver(struct gigaset_driver *drv) |
998 | { | 1071 | { |
999 | unsigned long flags; | 1072 | unsigned long flags; |
@@ -1014,20 +1087,20 @@ EXPORT_SYMBOL_GPL(gigaset_freedriver); | |||
1014 | /* gigaset_initdriver | 1087 | /* gigaset_initdriver |
1015 | * Allocate and initialize gigaset_driver structure. Initialize interface. | 1088 | * Allocate and initialize gigaset_driver structure. Initialize interface. |
1016 | * parameters: | 1089 | * parameters: |
1017 | * minor First minor number | 1090 | * minor First minor number |
1018 | * minors Number of minors this driver can handle | 1091 | * minors Number of minors this driver can handle |
1019 | * procname Name of the driver (e.g. for /proc/tty/drivers, path in /proc/driver) | 1092 | * procname Name of the driver |
1020 | * devname Name of the device files (prefix without minor number) | 1093 | * devname Name of the device files (prefix without minor number) |
1021 | * devfsname Devfs name of the device files without %d | 1094 | * devfsname Devfs name of the device files without %d |
1022 | * return value: | 1095 | * return value: |
1023 | * Pointer to the gigaset_driver structure on success, NULL on failure. | 1096 | * Pointer to the gigaset_driver structure on success, NULL on failure. |
1024 | */ | 1097 | */ |
1025 | struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors, | 1098 | struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors, |
1026 | const char *procname, | 1099 | const char *procname, |
1027 | const char *devname, | 1100 | const char *devname, |
1028 | const char *devfsname, | 1101 | const char *devfsname, |
1029 | const struct gigaset_ops *ops, | 1102 | const struct gigaset_ops *ops, |
1030 | struct module *owner) | 1103 | struct module *owner) |
1031 | { | 1104 | { |
1032 | struct gigaset_driver *drv; | 1105 | struct gigaset_driver *drv; |
1033 | unsigned long flags; | 1106 | unsigned long flags; |
@@ -1036,8 +1109,9 @@ struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors, | |||
1036 | drv = kmalloc(sizeof *drv, GFP_KERNEL); | 1109 | drv = kmalloc(sizeof *drv, GFP_KERNEL); |
1037 | if (!drv) | 1110 | if (!drv) |
1038 | return NULL; | 1111 | return NULL; |
1112 | |||
1039 | if (!try_module_get(owner)) | 1113 | if (!try_module_get(owner)) |
1040 | return NULL; | 1114 | goto out1; |
1041 | 1115 | ||
1042 | drv->cs = NULL; | 1116 | drv->cs = NULL; |
1043 | drv->have_tty = 0; | 1117 | drv->have_tty = 0; |
@@ -1051,10 +1125,11 @@ struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors, | |||
1051 | 1125 | ||
1052 | drv->cs = kmalloc(minors * sizeof *drv->cs, GFP_KERNEL); | 1126 | drv->cs = kmalloc(minors * sizeof *drv->cs, GFP_KERNEL); |
1053 | if (!drv->cs) | 1127 | if (!drv->cs) |
1054 | goto out1; | 1128 | goto out2; |
1129 | |||
1055 | drv->flags = kmalloc(minors * sizeof *drv->flags, GFP_KERNEL); | 1130 | drv->flags = kmalloc(minors * sizeof *drv->flags, GFP_KERNEL); |
1056 | if (!drv->flags) | 1131 | if (!drv->flags) |
1057 | goto out2; | 1132 | goto out3; |
1058 | 1133 | ||
1059 | for (i = 0; i < minors; ++i) { | 1134 | for (i = 0; i < minors; ++i) { |
1060 | drv->flags[i] = 0; | 1135 | drv->flags[i] = 0; |
@@ -1071,61 +1146,16 @@ struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors, | |||
1071 | 1146 | ||
1072 | return drv; | 1147 | return drv; |
1073 | 1148 | ||
1074 | out2: | 1149 | out3: |
1075 | kfree(drv->cs); | 1150 | kfree(drv->cs); |
1151 | out2: | ||
1152 | module_put(owner); | ||
1076 | out1: | 1153 | out1: |
1077 | kfree(drv); | 1154 | kfree(drv); |
1078 | module_put(owner); | ||
1079 | return NULL; | 1155 | return NULL; |
1080 | } | 1156 | } |
1081 | EXPORT_SYMBOL_GPL(gigaset_initdriver); | 1157 | EXPORT_SYMBOL_GPL(gigaset_initdriver); |
1082 | 1158 | ||
1083 | static struct cardstate *alloc_cs(struct gigaset_driver *drv) | ||
1084 | { | ||
1085 | unsigned long flags; | ||
1086 | unsigned i; | ||
1087 | static struct cardstate *ret = NULL; | ||
1088 | |||
1089 | spin_lock_irqsave(&drv->lock, flags); | ||
1090 | for (i = 0; i < drv->minors; ++i) { | ||
1091 | if (!(drv->flags[i] & VALID_MINOR)) { | ||
1092 | drv->flags[i] = VALID_MINOR; | ||
1093 | ret = drv->cs + i; | ||
1094 | } | ||
1095 | if (ret) | ||
1096 | break; | ||
1097 | } | ||
1098 | spin_unlock_irqrestore(&drv->lock, flags); | ||
1099 | return ret; | ||
1100 | } | ||
1101 | |||
1102 | static void free_cs(struct cardstate *cs) | ||
1103 | { | ||
1104 | unsigned long flags; | ||
1105 | struct gigaset_driver *drv = cs->driver; | ||
1106 | spin_lock_irqsave(&drv->lock, flags); | ||
1107 | drv->flags[cs->minor_index] = 0; | ||
1108 | spin_unlock_irqrestore(&drv->lock, flags); | ||
1109 | } | ||
1110 | |||
1111 | static void make_valid(struct cardstate *cs, unsigned mask) | ||
1112 | { | ||
1113 | unsigned long flags; | ||
1114 | struct gigaset_driver *drv = cs->driver; | ||
1115 | spin_lock_irqsave(&drv->lock, flags); | ||
1116 | drv->flags[cs->minor_index] |= mask; | ||
1117 | spin_unlock_irqrestore(&drv->lock, flags); | ||
1118 | } | ||
1119 | |||
1120 | static void make_invalid(struct cardstate *cs, unsigned mask) | ||
1121 | { | ||
1122 | unsigned long flags; | ||
1123 | struct gigaset_driver *drv = cs->driver; | ||
1124 | spin_lock_irqsave(&drv->lock, flags); | ||
1125 | drv->flags[cs->minor_index] &= ~mask; | ||
1126 | spin_unlock_irqrestore(&drv->lock, flags); | ||
1127 | } | ||
1128 | |||
1129 | /* For drivers without fixed assignment device<->cardstate (usb) */ | 1159 | /* For drivers without fixed assignment device<->cardstate (usb) */ |
1130 | struct cardstate *gigaset_getunassignedcs(struct gigaset_driver *drv) | 1160 | struct cardstate *gigaset_getunassignedcs(struct gigaset_driver *drv) |
1131 | { | 1161 | { |