common.c 28 KB
Newer Older
1
2
3
/*
 * Stuff used by all variants of the driver
 *
4
 * Copyright (c) 2001 by Stefan Eilers,
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 *                       Hansjoerg Lipp <hjlipp@web.de>,
 *                       Tilman Schmidt <tilman@imap.cc>.
 *
 * =====================================================================
 *	This program is free software; you can redistribute it and/or
 *	modify it under the terms of the GNU General Public License as
 *	published by the Free Software Foundation; either version 2 of
 *	the License, or (at your option) any later version.
 * =====================================================================
 */

#include "gigaset.h"
#include <linux/ctype.h>
#include <linux/module.h>
#include <linux/moduleparam.h>

/* Version Information */
22
#define DRIVER_AUTHOR "Hansjoerg Lipp <hjlipp@web.de>, Tilman Schmidt <tilman@imap.cc>, Stefan Eilers"
23
24
#define DRIVER_DESC "Driver for Gigaset 307x"

25
26
27
28
29
30
#ifdef CONFIG_GIGASET_DEBUG
#define DRIVER_DESC_DEBUG " (debug build)"
#else
#define DRIVER_DESC_DEBUG ""
#endif

31
/* Module parameters */
32
int gigaset_debuglevel;
33
34
35
36
EXPORT_SYMBOL_GPL(gigaset_debuglevel);
module_param_named(debug, gigaset_debuglevel, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(debug, "debug level");

37
/* driver state flags */
38
39
#define VALID_MINOR	0x01
#define VALID_ID	0x02
40

41
42
43
44
45
46
47
48
49
50
51
/**
 * gigaset_dbg_buffer() - dump data in ASCII and hex for debugging
 * @level:	debugging level.
 * @msg:	message prefix.
 * @len:	number of bytes to dump.
 * @buf:	data to dump.
 *
 * If the current debugging level includes one of the bits set in @level,
 * @len bytes starting at @buf are logged to dmesg at KERN_DEBUG prio,
 * prefixed by the text @msg.
 */
52
void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg,
53
			size_t len, const unsigned char *buf)
54
55
{
	unsigned char outbuf[80];
56
	unsigned char c;
57
58
	size_t space = sizeof outbuf - 1;
	unsigned char *out = outbuf;
59
	size_t numin = len;
60

61
	while (numin--) {
62
63
		c = *buf++;
		if (c == '~' || c == '^' || c == '\\') {
64
			if (!space--)
65
66
67
68
				break;
			*out++ = '\\';
		}
		if (c & 0x80) {
69
			if (!space--)
70
71
72
73
74
				break;
			*out++ = '~';
			c ^= 0x80;
		}
		if (c < 0x20 || c == 0x7f) {
75
			if (!space--)
76
				break;
77
			*out++ = '^';
78
			c ^= 0x40;
79
		}
80
		if (!space--)
81
82
			break;
		*out++ = c;
83
84
85
	}
	*out = 0;

86
	gig_dbg(level, "%s (%u bytes): %s", msg, (unsigned) len, outbuf);
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
}
EXPORT_SYMBOL_GPL(gigaset_dbg_buffer);

static int setflags(struct cardstate *cs, unsigned flags, unsigned delay)
{
	int r;

	r = cs->ops->set_modem_ctrl(cs, cs->control_state, flags);
	cs->control_state = flags;
	if (r < 0)
		return r;

	if (delay) {
		set_current_state(TASK_INTERRUPTIBLE);
		schedule_timeout(delay * HZ / 1000);
	}

	return 0;
}

int gigaset_enterconfigmode(struct cardstate *cs)
{
	int i, r;

Tilman Schmidt's avatar
Tilman Schmidt committed
111
	cs->control_state = TIOCM_RTS;
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133

	r = setflags(cs, TIOCM_DTR, 200);
	if (r < 0)
		goto error;
	r = setflags(cs, 0, 200);
	if (r < 0)
		goto error;
	for (i = 0; i < 5; ++i) {
		r = setflags(cs, TIOCM_RTS, 100);
		if (r < 0)
			goto error;
		r = setflags(cs, 0, 100);
		if (r < 0)
			goto error;
	}
	r = setflags(cs, TIOCM_RTS|TIOCM_DTR, 800);
	if (r < 0)
		goto error;

	return 0;

error:
134
	dev_err(cs->dev, "error %d on setuartbits\n", -r);
Tilman Schmidt's avatar
Tilman Schmidt committed
135
	cs->control_state = TIOCM_RTS|TIOCM_DTR;
136
137
	cs->ops->set_modem_ctrl(cs, 0, TIOCM_RTS|TIOCM_DTR);

Tilman Schmidt's avatar
Tilman Schmidt committed
138
	return -1;
139
140
141
142
143
144
145
146
}

static int test_timeout(struct at_state_t *at_state)
{
	if (!at_state->timer_expires)
		return 0;

	if (--at_state->timer_expires) {
147
148
		gig_dbg(DEBUG_MCMD, "decreased timer of %p to %lu",
			at_state, at_state->timer_expires);
149
150
151
152
		return 0;
	}

	if (!gigaset_add_event(at_state->cs, at_state, EV_TIMEOUT, NULL,
Tilman Schmidt's avatar
Tilman Schmidt committed
153
154
155
			       at_state->timer_index, NULL))
			dev_err(at_state->cs->dev, "%s: out of memory\n",
				__func__);
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
	return 1;
}

static void timer_tick(unsigned long data)
{
	struct cardstate *cs = (struct cardstate *) data;
	unsigned long flags;
	unsigned channel;
	struct at_state_t *at_state;
	int timeout = 0;

	spin_lock_irqsave(&cs->lock, flags);

	for (channel = 0; channel < cs->channels; ++channel)
		if (test_timeout(&cs->bcs[channel].at_state))
			timeout = 1;

	if (test_timeout(&cs->at_state))
		timeout = 1;

	list_for_each_entry(at_state, &cs->temp_at_states, list)
		if (test_timeout(at_state))
			timeout = 1;

180
	if (cs->running) {
181
		mod_timer(&cs->timer, jiffies + msecs_to_jiffies(GIG_TICK));
182
		if (timeout) {
183
			gig_dbg(DEBUG_CMD, "scheduling timeout");
184
185
186
187
188
189
190
191
192
193
194
195
			tasklet_schedule(&cs->event_tasklet);
		}
	}

	spin_unlock_irqrestore(&cs->lock, flags);
}

int gigaset_get_channel(struct bc_state *bcs)
{
	unsigned long flags;

	spin_lock_irqsave(&bcs->cs->lock, flags);
Tilman Schmidt's avatar
Tilman Schmidt committed
196
	if (bcs->use_count || !try_module_get(bcs->cs->driver->owner)) {
197
198
		gig_dbg(DEBUG_ANY, "could not allocate channel %d",
			bcs->channel);
199
200
201
202
203
		spin_unlock_irqrestore(&bcs->cs->lock, flags);
		return 0;
	}
	++bcs->use_count;
	bcs->busy = 1;
204
	gig_dbg(DEBUG_ANY, "allocated channel %d", bcs->channel);
205
206
207
208
	spin_unlock_irqrestore(&bcs->cs->lock, flags);
	return 1;
}

209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
struct bc_state *gigaset_get_free_channel(struct cardstate *cs)
{
	unsigned long flags;
	int i;

	spin_lock_irqsave(&cs->lock, flags);
	if (!try_module_get(cs->driver->owner)) {
		gig_dbg(DEBUG_ANY,
			"could not get module for allocating channel");
		spin_unlock_irqrestore(&cs->lock, flags);
		return NULL;
	}
	for (i = 0; i < cs->channels; ++i)
		if (!cs->bcs[i].use_count) {
			++cs->bcs[i].use_count;
			cs->bcs[i].busy = 1;
			spin_unlock_irqrestore(&cs->lock, flags);
			gig_dbg(DEBUG_ANY, "allocated channel %d", i);
			return cs->bcs + i;
		}
	module_put(cs->driver->owner);
	spin_unlock_irqrestore(&cs->lock, flags);
	gig_dbg(DEBUG_ANY, "no free channel");
	return NULL;
}

235
236
237
238
239
240
void gigaset_free_channel(struct bc_state *bcs)
{
	unsigned long flags;

	spin_lock_irqsave(&bcs->cs->lock, flags);
	if (!bcs->busy) {
241
		gig_dbg(DEBUG_ANY, "could not free channel %d", bcs->channel);
242
243
244
245
246
		spin_unlock_irqrestore(&bcs->cs->lock, flags);
		return;
	}
	--bcs->use_count;
	bcs->busy = 0;
Tilman Schmidt's avatar
Tilman Schmidt committed
247
	module_put(bcs->cs->driver->owner);
248
	gig_dbg(DEBUG_ANY, "freed channel %d", bcs->channel);
249
250
251
252
253
254
255
256
257
258
259
260
	spin_unlock_irqrestore(&bcs->cs->lock, flags);
}

int gigaset_get_channels(struct cardstate *cs)
{
	unsigned long flags;
	int i;

	spin_lock_irqsave(&cs->lock, flags);
	for (i = 0; i < cs->channels; ++i)
		if (cs->bcs[i].use_count) {
			spin_unlock_irqrestore(&cs->lock, flags);
261
			gig_dbg(DEBUG_ANY, "could not allocate all channels");
262
263
264
265
266
267
			return 0;
		}
	for (i = 0; i < cs->channels; ++i)
		++cs->bcs[i].use_count;
	spin_unlock_irqrestore(&cs->lock, flags);

268
	gig_dbg(DEBUG_ANY, "allocated all channels");
269
270
271
272
273
274
275
276
277

	return 1;
}

void gigaset_free_channels(struct cardstate *cs)
{
	unsigned long flags;
	int i;

278
	gig_dbg(DEBUG_ANY, "unblocking all channels");
279
280
281
282
283
284
285
286
287
288
289
	spin_lock_irqsave(&cs->lock, flags);
	for (i = 0; i < cs->channels; ++i)
		--cs->bcs[i].use_count;
	spin_unlock_irqrestore(&cs->lock, flags);
}

void gigaset_block_channels(struct cardstate *cs)
{
	unsigned long flags;
	int i;

290
	gig_dbg(DEBUG_ANY, "blocking all channels");
291
292
293
294
295
296
297
298
299
300
	spin_lock_irqsave(&cs->lock, flags);
	for (i = 0; i < cs->channels; ++i)
		++cs->bcs[i].use_count;
	spin_unlock_irqrestore(&cs->lock, flags);
}

static void clear_events(struct cardstate *cs)
{
	struct event_t *ev;
	unsigned head, tail;
301
	unsigned long flags;
302

303
	spin_lock_irqsave(&cs->ev_lock, flags);
304

305
306
	head = cs->ev_head;
	tail = cs->ev_tail;
307
308
309
310
311
312
313

	while (tail != head) {
		ev = cs->events + head;
		kfree(ev->ptr);
		head = (head + 1) % MAX_EVENTS;
	}

314
315
316
	cs->ev_head = tail;

	spin_unlock_irqrestore(&cs->ev_lock, flags);
317
318
}

319
320
321
322
323
324
325
326
327
328
329
330
331
332
/**
 * gigaset_add_event() - add event to device event queue
 * @cs:		device descriptor structure.
 * @at_state:	connection state structure.
 * @type:	event type.
 * @ptr:	pointer parameter for event.
 * @parameter:	integer parameter for event.
 * @arg:	pointer parameter for event.
 *
 * Allocate an event queue entry from the device's event queue, and set it up
 * with the parameters given.
 *
 * Return value: added event
 */
333
struct event_t *gigaset_add_event(struct cardstate *cs,
334
335
				  struct at_state_t *at_state, int type,
				  void *ptr, int parameter, void *arg)
336
337
338
339
340
341
342
{
	unsigned long flags;
	unsigned next, tail;
	struct event_t *event = NULL;

	spin_lock_irqsave(&cs->ev_lock, flags);

343
	tail = cs->ev_tail;
344
	next = (tail + 1) % MAX_EVENTS;
345
	if (unlikely(next == cs->ev_head))
346
		dev_err(cs->dev, "event queue full\n");
347
348
349
350
351
352
353
354
	else {
		event = cs->events + tail;
		event->type = type;
		event->at_state = at_state;
		event->cid = -1;
		event->ptr = ptr;
		event->arg = arg;
		event->parameter = parameter;
355
		cs->ev_tail = next;
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
	}

	spin_unlock_irqrestore(&cs->ev_lock, flags);

	return event;
}
EXPORT_SYMBOL_GPL(gigaset_add_event);

static void free_strings(struct at_state_t *at_state)
{
	int i;

	for (i = 0; i < STR_NUM; ++i) {
		kfree(at_state->str_var[i]);
		at_state->str_var[i] = NULL;
	}
}

static void clear_at_state(struct at_state_t *at_state)
{
	free_strings(at_state);
}

static void dealloc_at_states(struct cardstate *cs)
{
	struct at_state_t *cur, *next;

	list_for_each_entry_safe(cur, next, &cs->temp_at_states, list) {
		list_del(&cur->list);
		free_strings(cur);
		kfree(cur);
	}
}

static void gigaset_freebcs(struct bc_state *bcs)
{
	int i;

394
	gig_dbg(DEBUG_INIT, "freeing bcs[%d]->hw", bcs->channel);
Tilman Schmidt's avatar
Tilman Schmidt committed
395
	if (!bcs->cs->ops->freebcshw(bcs))
396
		gig_dbg(DEBUG_INIT, "failed");
397

398
	gig_dbg(DEBUG_INIT, "clearing bcs[%d]->at_state", bcs->channel);
399
	clear_at_state(&bcs->at_state);
400
	gig_dbg(DEBUG_INIT, "freeing bcs[%d]->skb", bcs->channel);
Tilman Schmidt's avatar
Tilman Schmidt committed
401
402
	dev_kfree_skb(bcs->skb);
	bcs->skb = NULL;
403
404
405
406
407
408
409

	for (i = 0; i < AT_NUM; ++i) {
		kfree(bcs->commands[i]);
		bcs->commands[i] = NULL;
	}
}

410
411
412
413
static struct cardstate *alloc_cs(struct gigaset_driver *drv)
{
	unsigned long flags;
	unsigned i;
Tilman Schmidt's avatar
Tilman Schmidt committed
414
	struct cardstate *cs;
415
	struct cardstate *ret = NULL;
416
417

	spin_lock_irqsave(&drv->lock, flags);
Tilman Schmidt's avatar
Tilman Schmidt committed
418
419
	if (drv->blocked)
		goto exit;
420
	for (i = 0; i < drv->minors; ++i) {
Tilman Schmidt's avatar
Tilman Schmidt committed
421
422
423
424
		cs = drv->cs + i;
		if (!(cs->flags & VALID_MINOR)) {
			cs->flags = VALID_MINOR;
			ret = cs;
425
			break;
426
		}
427
	}
Tilman Schmidt's avatar
Tilman Schmidt committed
428
exit:
429
430
431
432
433
434
	spin_unlock_irqrestore(&drv->lock, flags);
	return ret;
}

static void free_cs(struct cardstate *cs)
{
Tilman Schmidt's avatar
Tilman Schmidt committed
435
	cs->flags = 0;
436
437
438
439
440
441
442
}

static void make_valid(struct cardstate *cs, unsigned mask)
{
	unsigned long flags;
	struct gigaset_driver *drv = cs->driver;
	spin_lock_irqsave(&drv->lock, flags);
Tilman Schmidt's avatar
Tilman Schmidt committed
443
	cs->flags |= mask;
444
445
446
447
448
449
450
451
	spin_unlock_irqrestore(&drv->lock, flags);
}

static void make_invalid(struct cardstate *cs, unsigned mask)
{
	unsigned long flags;
	struct gigaset_driver *drv = cs->driver;
	spin_lock_irqsave(&drv->lock, flags);
Tilman Schmidt's avatar
Tilman Schmidt committed
452
	cs->flags &= ~mask;
453
454
455
	spin_unlock_irqrestore(&drv->lock, flags);
}

456
457
458
459
460
461
462
463
464
/**
 * gigaset_freecs() - free all associated ressources of a device
 * @cs:		device descriptor structure.
 *
 * Stops all tasklets and timers, unregisters the device from all
 * subsystems it was registered to, deallocates the device structure
 * @cs and all structures referenced from it.
 * Operations on the device should be stopped before calling this.
 */
465
466
467
468
469
470
471
472
void gigaset_freecs(struct cardstate *cs)
{
	int i;
	unsigned long flags;

	if (!cs)
		return;

473
	mutex_lock(&cs->mutex);
474
475
476
477
478
479
480

	if (!cs->bcs)
		goto f_cs;
	if (!cs->inbuf)
		goto f_bcs;

	spin_lock_irqsave(&cs->lock, flags);
481
	cs->running = 0;
482
483
	spin_unlock_irqrestore(&cs->lock, flags); /* event handler and timer are
						     not rescheduled below */
484
485
486
487
488
489

	tasklet_kill(&cs->event_tasklet);
	del_timer_sync(&cs->timer);

	switch (cs->cs_init) {
	default:
490
491
492
493
494
495
		/* clear B channel structures */
		for (i = 0; i < cs->channels; ++i) {
			gig_dbg(DEBUG_INIT, "clearing bcs[%d]", i);
			gigaset_freebcs(cs->bcs + i);
		}

496
497
498
		/* clear device sysfs */
		gigaset_free_dev_sysfs(cs);

499
500
		gigaset_if_free(cs);

501
		gig_dbg(DEBUG_INIT, "clearing hw");
502
503
504
505
506
507
		cs->ops->freecshw(cs);

		/* fall through */
	case 2: /* error in initcshw */
		/* Deregister from LL */
		make_invalid(cs, VALID_ID);
508
		gigaset_isdn_unregister(cs);
509
510

		/* fall through */
511
	case 1: /* error when registering to LL */
512
		gig_dbg(DEBUG_INIT, "clearing at_state");
513
514
515
516
		clear_at_state(&cs->at_state);
		dealloc_at_states(cs);

		/* fall through */
517
	case 0:	/* error in basic setup */
518
		clear_events(cs);
519
		gig_dbg(DEBUG_INIT, "freeing inbuf");
520
521
		kfree(cs->inbuf);
	}
522
f_bcs:	gig_dbg(DEBUG_INIT, "freeing bcs[]");
523
	kfree(cs->bcs);
524
f_cs:	gig_dbg(DEBUG_INIT, "freeing cs");
525
	mutex_unlock(&cs->mutex);
526
527
528
529
530
	free_cs(cs);
}
EXPORT_SYMBOL_GPL(gigaset_freecs);

void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs,
531
		     struct cardstate *cs, int cid)
532
533
534
535
536
537
538
539
540
{
	int i;

	INIT_LIST_HEAD(&at_state->list);
	at_state->waiting = 0;
	at_state->getstring = 0;
	at_state->pending_commands = 0;
	at_state->timer_expires = 0;
	at_state->timer_active = 0;
541
542
	at_state->timer_index = 0;
	at_state->seq_index = 0;
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
	at_state->ConState = 0;
	for (i = 0; i < STR_NUM; ++i)
		at_state->str_var[i] = NULL;
	at_state->int_var[VAR_ZDLE] = 0;
	at_state->int_var[VAR_ZCTP] = -1;
	at_state->int_var[VAR_ZSAU] = ZSAU_NULL;
	at_state->cs = cs;
	at_state->bcs = bcs;
	at_state->cid = cid;
	if (!cid)
		at_state->replystruct = cs->tabnocid;
	else
		at_state->replystruct = cs->tabcid;
}


Tilman Schmidt's avatar
Tilman Schmidt committed
559
static void gigaset_inbuf_init(struct inbuf_t *inbuf, struct cardstate *cs)
560
561
/* inbuf->read must be allocated before! */
{
Tilman Schmidt's avatar
Tilman Schmidt committed
562
563
	inbuf->head = 0;
	inbuf->tail = 0;
564
	inbuf->cs = cs;
Tilman Schmidt's avatar
Tilman Schmidt committed
565
	inbuf->inputstate = INS_command;
566
567
}

568
569
570
571
572
573
/**
 * gigaset_fill_inbuf() - append received data to input buffer
 * @inbuf:	buffer structure.
 * @src:	received data.
 * @numbytes:	number of bytes received.
 */
574
575
576
577
578
579
580
581
582
583
584
int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src,
		       unsigned numbytes)
{
	unsigned n, head, tail, bytesleft;

	gig_dbg(DEBUG_INTR, "received %u bytes", numbytes);

	if (!numbytes)
		return 0;

	bytesleft = numbytes;
Tilman Schmidt's avatar
Tilman Schmidt committed
585
586
	tail = inbuf->tail;
	head = inbuf->head;
587
588
589
590
591
592
593
594
595
596
597
	gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail);

	while (bytesleft) {
		if (head > tail)
			n = head - 1 - tail;
		else if (head == 0)
			n = (RBUFSIZE-1) - tail;
		else
			n = RBUFSIZE - tail;
		if (!n) {
			dev_err(inbuf->cs->dev,
598
599
				"buffer overflow (%u bytes lost)\n",
				bytesleft);
600
601
602
603
604
605
606
607
608
609
			break;
		}
		if (n > bytesleft)
			n = bytesleft;
		memcpy(inbuf->data + tail, src, n);
		bytesleft -= n;
		tail = (tail + n) % RBUFSIZE;
		src += n;
	}
	gig_dbg(DEBUG_INTR, "setting tail to %u", tail);
Tilman Schmidt's avatar
Tilman Schmidt committed
610
	inbuf->tail = tail;
611
612
613
614
	return numbytes != bytesleft;
}
EXPORT_SYMBOL_GPL(gigaset_fill_inbuf);

615
616
/* Initialize the b-channel structure */
static struct bc_state *gigaset_initbcs(struct bc_state *bcs,
617
					struct cardstate *cs, int channel)
618
619
620
{
	int i;

Tilman Schmidt's avatar
Tilman Schmidt committed
621
	bcs->tx_skb = NULL;
622
623
624
625
626
627
628

	skb_queue_head_init(&bcs->squeue);

	bcs->corrupted = 0;
	bcs->trans_down = 0;
	bcs->trans_up = 0;

629
	gig_dbg(DEBUG_INIT, "setting up bcs[%d]->at_state", channel);
630
631
632
633
634
635
	gigaset_at_init(&bcs->at_state, bcs, cs, -1);

#ifdef CONFIG_GIGASET_DEBUG
	bcs->emptycount = 0;
#endif

636
	gig_dbg(DEBUG_INIT, "allocating bcs[%d]->skb", channel);
637
638
639
640
	bcs->fcs = PPP_INITFCS;
	bcs->inputstate = 0;
	if (cs->ignoreframes) {
		bcs->skb = NULL;
641
642
643
644
	} else {
		bcs->skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len);
		if (bcs->skb != NULL)
			skb_reserve(bcs->skb, cs->hw_hdr_len);
Tilman Schmidt's avatar
Tilman Schmidt committed
645
		else
646
			pr_err("out of memory\n");
647
648
649
650
651
652
653
654
655
656
657
658
659
	}

	bcs->channel = channel;
	bcs->cs = cs;

	bcs->chstate = 0;
	bcs->use_count = 1;
	bcs->busy = 0;
	bcs->ignore = cs->ignoreframes;

	for (i = 0; i < AT_NUM; ++i)
		bcs->commands[i] = NULL;

660
	gig_dbg(DEBUG_INIT, "  setting up bcs[%d]->hw", channel);
661
662
663
	if (cs->ops->initbcshw(bcs))
		return bcs;

664
	gig_dbg(DEBUG_INIT, "  failed");
665

666
	gig_dbg(DEBUG_INIT, "  freeing bcs[%d]->skb", channel);
Tilman Schmidt's avatar
Tilman Schmidt committed
667
668
	dev_kfree_skb(bcs->skb);
	bcs->skb = NULL;
669
670
671
672

	return NULL;
}

673
674
675
676
677
678
679
680
681
682
683
/**
 * gigaset_initcs() - initialize device structure
 * @drv:	hardware driver the device belongs to
 * @channels:	number of B channels supported by device
 * @onechannel:	!=0 if B channel data and AT commands share one
 *		    communication channel (M10x),
 *		==0 if B channels have separate communication channels (base)
 * @ignoreframes:	number of frames to ignore after setting up B channel
 * @cidmode:	!=0: start in CallID mode
 * @modulename:	name of driver module for LL registration
 *
684
685
686
 * Allocate and initialize cardstate structure for Gigaset driver
 * Calls hardware dependent gigaset_initcshw() function
 * Calls B channel initialization function gigaset_initbcs() for each B channel
687
688
 *
 * Return value:
689
690
691
692
693
694
 *	pointer to cardstate structure
 */
struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
				 int onechannel, int ignoreframes,
				 int cidmode, const char *modulename)
{
Tilman Schmidt's avatar
Tilman Schmidt committed
695
	struct cardstate *cs;
696
	unsigned long flags;
697
698
	int i;

699
	gig_dbg(DEBUG_INIT, "allocating cs");
Tilman Schmidt's avatar
Tilman Schmidt committed
700
701
	cs = alloc_cs(drv);
	if (!cs) {
702
		pr_err("maximum number of devices exceeded\n");
703
704
705
		return NULL;
	}

706
	gig_dbg(DEBUG_INIT, "allocating bcs[0..%d]", channels - 1);
707
	cs->bcs = kmalloc(channels * sizeof(struct bc_state), GFP_KERNEL);
708
	if (!cs->bcs) {
709
		pr_err("out of memory\n");
710
		goto error;
711
	}
712
	gig_dbg(DEBUG_INIT, "allocating inbuf");
713
	cs->inbuf = kmalloc(sizeof(struct inbuf_t), GFP_KERNEL);
714
	if (!cs->inbuf) {
715
		pr_err("out of memory\n");
716
		goto error;
717
	}
718
719
720
721
722
723

	cs->cs_init = 0;
	cs->channels = channels;
	cs->onechannel = onechannel;
	cs->ignoreframes = ignoreframes;
	INIT_LIST_HEAD(&cs->temp_at_states);
724
	cs->running = 0;
725
726
	init_timer(&cs->timer); /* clear next & prev */
	spin_lock_init(&cs->ev_lock);
727
728
	cs->ev_tail = 0;
	cs->ev_head = 0;
729

730
	tasklet_init(&cs->event_tasklet, gigaset_handle_event,
731
		     (unsigned long) cs);
Tilman Schmidt's avatar
Tilman Schmidt committed
732
	cs->commands_pending = 0;
733
734
735
	cs->cur_at_seq = 0;
	cs->gotfwver = -1;
	cs->open_count = 0;
736
	cs->dev = NULL;
737
	cs->tty = NULL;
738
	cs->tty_dev = NULL;
739
	cs->cidmode = cidmode != 0;
740
741
	cs->tabnocid = gigaset_tab_nocid;
	cs->tabcid = gigaset_tab_cid;
742
743
744
745

	init_waitqueue_head(&cs->waitqueue);
	cs->waiting = 0;

Tilman Schmidt's avatar
Tilman Schmidt committed
746
747
	cs->mode = M_UNKNOWN;
	cs->mstate = MS_UNINITIALIZED;
748
749
750

	++cs->cs_init;

751
	gig_dbg(DEBUG_INIT, "setting up at_state");
752
753
754
755
756
	spin_lock_init(&cs->lock);
	gigaset_at_init(&cs->at_state, NULL, cs, 0);
	cs->dle = 0;
	cs->cbytes = 0;

757
	gig_dbg(DEBUG_INIT, "setting up inbuf");
Tilman Schmidt's avatar
Tilman Schmidt committed
758
	gigaset_inbuf_init(cs->inbuf, cs);
759

760
761
	cs->connected = 0;
	cs->isdn_up = 0;
762

763
	gig_dbg(DEBUG_INIT, "setting up cmdbuf");
764
765
766
767
768
	cs->cmdbuf = cs->lastcmdbuf = NULL;
	spin_lock_init(&cs->cmdlock);
	cs->curlen = 0;
	cs->cmdbytes = 0;

769
	gig_dbg(DEBUG_INIT, "setting up iif");
770
	if (!gigaset_isdn_register(cs, modulename)) {
771
		pr_err("error registering ISDN device\n");
772
773
774
775
776
		goto error;
	}

	make_valid(cs, VALID_ID);
	++cs->cs_init;
777
	gig_dbg(DEBUG_INIT, "setting up hw");
778
	if (!cs->ops->initcshw(cs))
779
780
781
782
		goto error;

	++cs->cs_init;

783
	/* set up character device */
784
785
	gigaset_if_init(cs);

786
787
788
	/* set up device sysfs */
	gigaset_init_dev_sysfs(cs);

789
790
791
792
793
794
795
796
797
	/* set up channel data structures */
	for (i = 0; i < channels; ++i) {
		gig_dbg(DEBUG_INIT, "setting up bcs[%d]", i);
		if (!gigaset_initbcs(cs->bcs + i, cs, i)) {
			pr_err("could not allocate channel %d data\n", i);
			goto error;
		}
	}

798
799
800
	spin_lock_irqsave(&cs->lock, flags);
	cs->running = 1;
	spin_unlock_irqrestore(&cs->lock, flags);
801
802
	setup_timer(&cs->timer, timer_tick, (unsigned long) cs);
	cs->timer.expires = jiffies + msecs_to_jiffies(GIG_TICK);
803
804
805
806
	/* FIXME: can jiffies increase too much until the timer is added?
	 * Same problem(?) with mod_timer() in timer_tick(). */
	add_timer(&cs->timer);

807
	gig_dbg(DEBUG_INIT, "cs initialized");
808
809
	return cs;

810
error:
811
	gig_dbg(DEBUG_INIT, "failed");
812
813
814
815
816
	gigaset_freecs(cs);
	return NULL;
}
EXPORT_SYMBOL_GPL(gigaset_initcs);

817
/* ReInitialize the b-channel structure on hangup */
818
819
820
821
822
823
824
825
826
void gigaset_bcs_reinit(struct bc_state *bcs)
{
	struct sk_buff *skb;
	struct cardstate *cs = bcs->cs;
	unsigned long flags;

	while ((skb = skb_dequeue(&bcs->squeue)) != NULL)
		dev_kfree_skb(skb);

827
	spin_lock_irqsave(&cs->lock, flags);
828
829
830
831
	clear_at_state(&bcs->at_state);
	bcs->at_state.ConState = 0;
	bcs->at_state.timer_active = 0;
	bcs->at_state.timer_expires = 0;
832
	bcs->at_state.cid = -1;			/* No CID defined */
833
834
835
836
837
838
839
840
841
842
843
844
	spin_unlock_irqrestore(&cs->lock, flags);

	bcs->inputstate = 0;

#ifdef CONFIG_GIGASET_DEBUG
	bcs->emptycount = 0;
#endif

	bcs->fcs = PPP_INITFCS;
	bcs->chstate = 0;

	bcs->ignore = cs->ignoreframes;
Tilman Schmidt's avatar
Tilman Schmidt committed
845
846
847
848
	if (bcs->ignore) {
		dev_kfree_skb(bcs->skb);
		bcs->skb = NULL;
	}
849
850
851
852
853
854
855
856
857
858
859
860

	cs->ops->reinitbcshw(bcs);
}

static void cleanup_cs(struct cardstate *cs)
{
	struct cmdbuf_t *cb, *tcb;
	int i;
	unsigned long flags;

	spin_lock_irqsave(&cs->lock, flags);

Tilman Schmidt's avatar
Tilman Schmidt committed
861
862
	cs->mode = M_UNKNOWN;
	cs->mstate = MS_UNINITIALIZED;
863
864
865
866
867
868
869

	clear_at_state(&cs->at_state);
	dealloc_at_states(cs);
	free_strings(&cs->at_state);
	gigaset_at_init(&cs->at_state, NULL, cs, 0);

	cs->inbuf->inputstate = INS_command;
Tilman Schmidt's avatar
Tilman Schmidt committed
870
871
	cs->inbuf->head = 0;
	cs->inbuf->tail = 0;
872
873
874
875
876
877
878
879
880
881
882
883
884

	cb = cs->cmdbuf;
	while (cb) {
		tcb = cb;
		cb = cb->next;
		kfree(tcb);
	}
	cs->cmdbuf = cs->lastcmdbuf = NULL;
	cs->curlen = 0;
	cs->cmdbytes = 0;
	cs->gotfwver = -1;
	cs->dle = 0;
	cs->cur_at_seq = 0;
Tilman Schmidt's avatar
Tilman Schmidt committed
885
	cs->commands_pending = 0;
886
887
888
889
890
891
892
	cs->cbytes = 0;

	spin_unlock_irqrestore(&cs->lock, flags);

	for (i = 0; i < cs->channels; ++i) {
		gigaset_freebcs(cs->bcs + i);
		if (!gigaset_initbcs(cs->bcs + i, cs, i))
893
			pr_err("could not allocate channel %d data\n", i);
894
895
896
897
898
899
900
901
902
903
	}

	if (cs->waiting) {
		cs->cmd_result = -ENODEV;
		cs->waiting = 0;
		wake_up_interruptible(&cs->waitqueue);
	}
}


904
905
906
907
908
909
910
911
912
913
914
/**
 * gigaset_start() - start device operations
 * @cs:		device descriptor structure.
 *
 * Prepares the device for use by setting up communication parameters,
 * scheduling an EV_START event to initiate device initialization, and
 * waiting for completion of the initialization.
 *
 * Return value:
 *	1 - success, 0 - error
 */
915
916
int gigaset_start(struct cardstate *cs)
{
917
918
	unsigned long flags;

919
	if (mutex_lock_interruptible(&cs->mutex))
920
921
		return 0;

922
923
924
	spin_lock_irqsave(&cs->lock, flags);
	cs->connected = 1;
	spin_unlock_irqrestore(&cs->lock, flags);
925

Tilman Schmidt's avatar
Tilman Schmidt committed
926
	if (cs->mstate != MS_LOCKED) {
927
928
929
930
931
932
933
934
935
936
		cs->ops->set_modem_ctrl(cs, 0, TIOCM_DTR|TIOCM_RTS);
		cs->ops->baud_rate(cs, B115200);
		cs->ops->set_line_ctrl(cs, CS8);
		cs->control_state = TIOCM_DTR|TIOCM_RTS;
	}

	cs->waiting = 1;

	if (!gigaset_add_event(cs, &cs->at_state, EV_START, NULL, 0, NULL)) {
		cs->waiting = 0;
Tilman Schmidt's avatar
Tilman Schmidt committed
937
		dev_err(cs->dev, "%s: out of memory\n", __func__);
938
939
940
		goto error;
	}

941
	gig_dbg(DEBUG_CMD, "scheduling START");
942
943
944
945
	gigaset_schedule_event(cs);

	wait_event(cs->waitqueue, !cs->waiting);

946
	mutex_unlock(&cs->mutex);
947
948
949
	return 1;

error:
950
	mutex_unlock(&cs->mutex);
951
952
953
954
	return 0;
}
EXPORT_SYMBOL_GPL(gigaset_start);

955
956
957
958
959
960
961
962
963
/**
 * gigaset_shutdown() - shut down device operations
 * @cs:		device descriptor structure.
 *
 * Deactivates the device by scheduling an EV_SHUTDOWN event and
 * waiting for completion of the shutdown.
 *
 * Return value:
 *	0 - success, -1 - error (no device associated)
Tilman Schmidt's avatar
Tilman Schmidt committed
964
965
 */
int gigaset_shutdown(struct cardstate *cs)
966
{
967
	mutex_lock(&cs->mutex);
968

969
970
	if (!(cs->flags & VALID_MINOR)) {
		mutex_unlock(&cs->mutex);
Tilman Schmidt's avatar
Tilman Schmidt committed
971
		return -1;
972
	}
Tilman Schmidt's avatar
Tilman Schmidt committed
973

974
975
976
	cs->waiting = 1;

	if (!gigaset_add_event(cs, &cs->at_state, EV_SHUTDOWN, NULL, 0, NULL)) {
Tilman Schmidt's avatar
Tilman Schmidt committed
977
		dev_err(cs->dev, "%s: out of memory\n", __func__);
978
979
980
		goto exit;
	}

981
	gig_dbg(DEBUG_CMD, "scheduling SHUTDOWN");
982
983
	gigaset_schedule_event(cs);

984
	wait_event(cs->waitqueue, !cs->waiting);
985
986
987
988

	cleanup_cs(cs);

exit:
989
	mutex_unlock(&cs->mutex);
Tilman Schmidt's avatar
Tilman Schmidt committed
990
	return 0;
991
992
993
}
EXPORT_SYMBOL_GPL(gigaset_shutdown);

994
995
996
997
998
999
1000
/**
 * gigaset_stop() - stop device operations
 * @cs:		device descriptor structure.
 *
 * Stops operations on the device by scheduling an EV_STOP event and
 * waiting for completion of the shutdown.
 */
1001
1002
void gigaset_stop(struct cardstate *cs)
{
1003
	mutex_lock(&cs->mutex);
1004
1005
1006
1007

	cs->waiting = 1;

	if (!gigaset_add_event(cs, &cs->at_state, EV_STOP, NULL, 0, NULL)) {
Tilman Schmidt's avatar
Tilman Schmidt committed
1008
		dev_err(cs->dev, "%s: out of memory\n", __func__);
1009
1010
1011
		goto exit;
	}

1012
	gig_dbg(DEBUG_CMD, "scheduling STOP");
1013
1014
	gigaset_schedule_event(cs);

1015
	wait_event(cs->waitqueue, !cs->waiting);
1016
1017
1018
1019

	cleanup_cs(cs);

exit:
1020
	mutex_unlock(&cs->mutex);
1021
1022
1023
1024
}
EXPORT_SYMBOL_GPL(gigaset_stop);

static LIST_HEAD(drivers);
1025
static DEFINE_SPINLOCK(driver_lock);
1026
1027
1028
1029

struct cardstate *gigaset_get_cs_by_id(int id)
{
	unsigned long flags;
1030
1031
	struct cardstate *ret = NULL;
	struct cardstate *cs;
1032
1033
1034
1035
1036
1037
1038
	struct gigaset_driver *drv;
	unsigned i;

	spin_lock_irqsave(&driver_lock, flags);
	list_for_each_entry(drv, &drivers, list) {
		spin_lock(&drv->lock);
		for (i = 0; i < drv->minors; ++i) {
Tilman Schmidt's avatar
Tilman Schmidt committed
1039
1040
1041
			cs = drv->cs + i;
			if ((cs->flags & VALID_ID) && cs->myid == id) {
				ret = cs;
1042
				break;
Tilman Schmidt's avatar
Tilman Schmidt committed
1043
			}
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
		}
		spin_unlock(&drv->lock);
		if (ret)
			break;
	}
	spin_unlock_irqrestore(&driver_lock, flags);
	return ret;
}

void gigaset_debugdrivers(void)
{
	unsigned long flags;
	static struct cardstate *cs;
	struct gigaset_driver *drv;
	unsigned i;

	spin_lock_irqsave(&driver_lock, flags);
	list_for_each_entry(drv, &drivers, list) {
1062
		gig_dbg(DEBUG_DRIVER, "driver %p", drv);
1063
1064
		spin_lock(&drv->lock);
		for (i = 0; i < drv->minors; ++i) {
1065
			gig_dbg(DEBUG_DRIVER, "  index %u", i);
1066
			cs = drv->cs + i;
1067
			gig_dbg(DEBUG_DRIVER, "    cardstate %p", cs);
Tilman Schmidt's avatar
Tilman Schmidt committed
1068
			gig_dbg(DEBUG_DRIVER, "    flags 0x%02x", cs->flags);
1069
1070
1071
1072
			gig_dbg(DEBUG_DRIVER, "    minor_index %u",
				cs->minor_index);
			gig_dbg(DEBUG_DRIVER, "    driver %p", cs->driver);
			gig_dbg(DEBUG_DRIVER, "    i4l id %d", cs->myid);
1073
1074
1075
1076
1077
1078
		}
		spin_unlock(&drv->lock);
	}
	spin_unlock_irqrestore(&driver_lock, flags);
}

1079
static struct cardstate *gigaset_get_cs_by_minor(unsigned minor)
1080
1081
{
	unsigned long flags;
1082
	struct cardstate *ret = NULL;
1083
1084
1085
1086
1087
1088
1089
1090
1091
	struct gigaset_driver *drv;
	unsigned index;

	spin_lock_irqsave(&driver_lock, flags);
	list_for_each_entry(drv, &drivers, list) {
		if (minor < drv->minor || minor >= drv->minor + drv->minors)
			continue;
		index = minor - drv->minor;
		spin_lock(&drv->lock);
Tilman Schmidt's avatar
Tilman Schmidt committed
1092
		if (drv->cs[index].flags & VALID_MINOR)
1093
1094
1095
1096
1097
1098
1099
1100
1101
			ret = drv->cs + index;
		spin_unlock(&drv->lock);
		if (ret)
			break;
	}
	spin_unlock_irqrestore(&driver_lock, flags);
	return ret;
}

1102
1103
1104
1105
1106
1107
1108
struct cardstate *gigaset_get_cs_by_tty(struct tty_struct *tty)
{
	if (tty->index < 0 || tty->index >= tty->driver->num)
		return NULL;
	return gigaset_get_cs_by_minor(tty->index + tty->driver->minor_start);
}

1109
1110
1111
1112
1113
1114
1115
1116
/**
 * gigaset_freedriver() - free all associated ressources of a driver
 * @drv:	driver descriptor structure.
 *
 * Unregisters the driver from the system and deallocates the driver
 * structure @drv and all structures referenced from it.
 * All devices should be shut down before calling this.
 */
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
void gigaset_freedriver(struct gigaset_driver *drv)
{
	unsigned long flags;

	spin_lock_irqsave(&driver_lock, flags);
	list_del(&drv->list);
	spin_unlock_irqrestore(&driver_lock, flags);

	gigaset_if_freedriver(drv);

	kfree(drv->cs);
	kfree(drv);
}
EXPORT_SYMBOL_GPL(gigaset_freedriver);

1132
1133
1134
1135
1136
1137
1138
/**
 * gigaset_initdriver() - initialize driver structure
 * @minor:	First minor number
 * @minors:	Number of minors this driver can handle
 * @procname:	Name of the driver
 * @devname:	Name of the device files (prefix without minor number)
 *
1139
 * Allocate and initialize gigaset_driver structure. Initialize interface.
1140
1141
 *
 * Return value:
1142
 *	Pointer to the gigaset_driver structure on success, NULL on failure.
1143
1144
 */
struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors,
1145
1146
1147
1148
					  const char *procname,
					  const char *devname,
					  const struct gigaset_ops *ops,
					  struct module *owner)
1149
1150
1151
1152
1153
1154
1155
1156
{
	struct gigaset_driver *drv;
	unsigned long flags;
	unsigned i;

	drv = kmalloc(sizeof *drv, GFP_KERNEL);
	if (!drv)
		return NULL;
1157

1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
	drv->have_tty = 0;
	drv->minor = minor;
	drv->minors = minors;
	spin_lock_init(&drv->lock);
	drv->blocked = 0;
	drv->ops = ops;
	drv->owner = owner;
	INIT_LIST_HEAD(&drv->list);

	drv->cs = kmalloc(minors * sizeof *drv->cs, GFP_KERNEL);
	if (!drv->cs)
1169
		goto error;
1170

1171
	for (i = 0; i < minors; ++i) {
Tilman Schmidt's avatar
Tilman Schmidt committed
1172
		drv->cs[i].flags = 0;
1173
1174
1175
		drv->cs[i].driver = drv;
		drv->cs[i].ops = drv->ops;
		drv->cs[i].minor_index = i;
1176
		mutex_init(&drv->cs[i].mutex);
1177
1178
	}

1179
	gigaset_if_initdriver(drv, procname, devname);
1180
1181
1182
1183
1184
1185
1186

	spin_lock_irqsave(&driver_lock, flags);
	list_add(&drv->list, &drivers);
	spin_unlock_irqrestore(&driver_lock, flags);

	return drv;

1187
error:
1188
1189
1190
1191
1192
1193
	kfree(drv->cs);
	kfree(drv);
	return NULL;
}
EXPORT_SYMBOL_GPL(gigaset_initdriver);

1194
1195
1196
1197
1198
1199
1200
/**
 * gigaset_blockdriver() - block driver
 * @drv:	driver descriptor structure.
 *
 * Prevents the driver from attaching new devices, in preparation for
 * deregistration.
 */
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
void gigaset_blockdriver(struct gigaset_driver *drv)
{
	drv->blocked = 1;
}
EXPORT_SYMBOL_GPL(gigaset_blockdriver);

static int __init gigaset_init_module(void)
{
	/* in accordance with the principle of least astonishment,
	 * setting the 'debug' parameter to 1 activates a sensible
	 * set of default debug levels
	 */
	if (gigaset_debuglevel == 1)
		gigaset_debuglevel = DEBUG_DEFAULT;

1216
	pr_info(DRIVER_DESC DRIVER_DESC_DEBUG "\n");
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
	return 0;
}

static void __exit gigaset_exit_module(void)
{
}

module_init(gigaset_init_module);
module_exit(gigaset_exit_module);

MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);

MODULE_LICENSE("GPL");