common.c 27.7 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
32
33
34
35
36
/* Module parameters */
int gigaset_debuglevel = DEBUG_DEFAULT;
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
}
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;

	cs->control_state = TIOCM_RTS; //FIXME

	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);
135
136
137
138
139
140
141
142
143
144
145
146
	cs->control_state = TIOCM_RTS|TIOCM_DTR; // FIXME is this a good value?
	cs->ops->set_modem_ctrl(cs, 0, TIOCM_RTS|TIOCM_DTR);

	return -1; //r
}

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,
153
			       at_state->timer_index, NULL)) {
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
		//FIXME what should we do?
	}

	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;

181
	if (cs->running) {
182
		mod_timer(&cs->timer, jiffies + msecs_to_jiffies(GIG_TICK));
183
		if (timeout) {
184
			gig_dbg(DEBUG_CMD, "scheduling timeout");
185
186
187
188
189
190
191
192
193
194
195
196
			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
197
	if (bcs->use_count || !try_module_get(bcs->cs->driver->owner)) {
198
199
		gig_dbg(DEBUG_ANY, "could not allocate channel %d",
			bcs->channel);
200
201
202
203
204
		spin_unlock_irqrestore(&bcs->cs->lock, flags);
		return 0;
	}
	++bcs->use_count;
	bcs->busy = 1;
205
	gig_dbg(DEBUG_ANY, "allocated channel %d", bcs->channel);
206
207
208
209
210
211
212
213
214
215
	spin_unlock_irqrestore(&bcs->cs->lock, flags);
	return 1;
}

void gigaset_free_channel(struct bc_state *bcs)
{
	unsigned long flags;

	spin_lock_irqsave(&bcs->cs->lock, flags);
	if (!bcs->busy) {
216
		gig_dbg(DEBUG_ANY, "could not free channel %d", bcs->channel);
217
218
219
220
221
		spin_unlock_irqrestore(&bcs->cs->lock, flags);
		return;
	}
	--bcs->use_count;
	bcs->busy = 0;
Tilman Schmidt's avatar
Tilman Schmidt committed
222
	module_put(bcs->cs->driver->owner);
223
	gig_dbg(DEBUG_ANY, "freed channel %d", bcs->channel);
224
225
226
227
228
229
230
231
232
233
234
235
	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);
236
			gig_dbg(DEBUG_ANY, "could not allocate all channels");
237
238
239
240
241
242
			return 0;
		}
	for (i = 0; i < cs->channels; ++i)
		++cs->bcs[i].use_count;
	spin_unlock_irqrestore(&cs->lock, flags);

243
	gig_dbg(DEBUG_ANY, "allocated all channels");
244
245
246
247
248
249
250
251
252

	return 1;
}

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

253
	gig_dbg(DEBUG_ANY, "unblocking all channels");
254
255
256
257
258
259
260
261
262
263
264
	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;

265
	gig_dbg(DEBUG_ANY, "blocking all channels");
266
267
268
269
270
271
272
273
274
275
	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;
276
	unsigned long flags;
277

278
	spin_lock_irqsave(&cs->ev_lock, flags);
279

280
281
	head = cs->ev_head;
	tail = cs->ev_tail;
282
283
284
285
286
287
288

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

289
290
291
	cs->ev_head = tail;

	spin_unlock_irqrestore(&cs->ev_lock, flags);
292
293
}

294
295
296
297
298
299
300
301
302
303
304
305
306
307
/**
 * 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
 */
308
struct event_t *gigaset_add_event(struct cardstate *cs,
309
310
				  struct at_state_t *at_state, int type,
				  void *ptr, int parameter, void *arg)
311
312
313
314
315
316
317
{
	unsigned long flags;
	unsigned next, tail;
	struct event_t *event = NULL;

	spin_lock_irqsave(&cs->ev_lock, flags);

318
	tail = cs->ev_tail;
319
	next = (tail + 1) % MAX_EVENTS;
320
	if (unlikely(next == cs->ev_head))
321
		dev_err(cs->dev, "event queue full\n");
322
323
324
325
326
327
328
329
	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;
330
		cs->ev_tail = next;
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
	}

	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;

369
	gig_dbg(DEBUG_INIT, "freeing bcs[%d]->hw", bcs->channel);
370
	if (!bcs->cs->ops->freebcshw(bcs)) {
371
		gig_dbg(DEBUG_INIT, "failed");
372
373
	}

374
	gig_dbg(DEBUG_INIT, "clearing bcs[%d]->at_state", bcs->channel);
375
	clear_at_state(&bcs->at_state);
376
	gig_dbg(DEBUG_INIT, "freeing bcs[%d]->skb", bcs->channel);
377
378
379
380
381
382
383
384
385

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

386
387
388
389
static struct cardstate *alloc_cs(struct gigaset_driver *drv)
{
	unsigned long flags;
	unsigned i;
Tilman Schmidt's avatar
Tilman Schmidt committed
390
	struct cardstate *cs;
391
	struct cardstate *ret = NULL;
392
393

	spin_lock_irqsave(&drv->lock, flags);
Tilman Schmidt's avatar
Tilman Schmidt committed
394
395
	if (drv->blocked)
		goto exit;
396
	for (i = 0; i < drv->minors; ++i) {
Tilman Schmidt's avatar
Tilman Schmidt committed
397
398
399
400
		cs = drv->cs + i;
		if (!(cs->flags & VALID_MINOR)) {
			cs->flags = VALID_MINOR;
			ret = cs;
401
			break;
402
		}
403
	}
Tilman Schmidt's avatar
Tilman Schmidt committed
404
exit:
405
406
407
408
409
410
	spin_unlock_irqrestore(&drv->lock, flags);
	return ret;
}

static void free_cs(struct cardstate *cs)
{
Tilman Schmidt's avatar
Tilman Schmidt committed
411
	cs->flags = 0;
412
413
414
415
416
417
418
}

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
419
	cs->flags |= mask;
420
421
422
423
424
425
426
427
	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
428
	cs->flags &= ~mask;
429
430
431
	spin_unlock_irqrestore(&drv->lock, flags);
}

432
433
434
435
436
437
438
439
440
/**
 * 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.
 */
441
442
443
444
445
446
447
448
void gigaset_freecs(struct cardstate *cs)
{
	int i;
	unsigned long flags;

	if (!cs)
		return;

449
	mutex_lock(&cs->mutex);
450
451
452
453
454
455
456

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

	spin_lock_irqsave(&cs->lock, flags);
457
	cs->running = 0;
458
459
	spin_unlock_irqrestore(&cs->lock, flags); /* event handler and timer are
						     not rescheduled below */
460
461
462
463
464
465

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

	switch (cs->cs_init) {
	default:
466
467
468
		/* clear device sysfs */
		gigaset_free_dev_sysfs(cs);

469
470
		gigaset_if_free(cs);

471
		gig_dbg(DEBUG_INIT, "clearing hw");
472
473
474
475
476
477
478
479
		cs->ops->freecshw(cs);

		//FIXME cmdbuf

		/* fall through */
	case 2: /* error in initcshw */
		/* Deregister from LL */
		make_invalid(cs, VALID_ID);
480
		gig_dbg(DEBUG_INIT, "clearing iif");
481
482
483
484
		gigaset_i4l_cmd(cs, ISDN_STAT_UNLOAD);

		/* fall through */
	case 1: /* error when regestering to LL */
485
		gig_dbg(DEBUG_INIT, "clearing at_state");
486
487
488
489
490
491
		clear_at_state(&cs->at_state);
		dealloc_at_states(cs);

		/* fall through */
	case 0: /* error in one call to initbcs */
		for (i = 0; i < cs->channels; ++i) {
492
			gig_dbg(DEBUG_INIT, "clearing bcs[%d]", i);
493
494
495
496
			gigaset_freebcs(cs->bcs + i);
		}

		clear_events(cs);
497
		gig_dbg(DEBUG_INIT, "freeing inbuf");
498
499
		kfree(cs->inbuf);
	}
500
f_bcs:	gig_dbg(DEBUG_INIT, "freeing bcs[]");
501
	kfree(cs->bcs);
502
f_cs:	gig_dbg(DEBUG_INIT, "freeing cs");
503
	mutex_unlock(&cs->mutex);
504
505
506
507
508
	free_cs(cs);
}
EXPORT_SYMBOL_GPL(gigaset_freecs);

void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs,
509
		     struct cardstate *cs, int cid)
510
511
512
513
514
515
516
517
518
{
	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;
519
520
	at_state->timer_index = 0;
	at_state->seq_index = 0;
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
	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;
}


static void gigaset_inbuf_init(struct inbuf_t *inbuf, struct bc_state *bcs,
538
			       struct cardstate *cs, int inputstate)
539
540
/* inbuf->read must be allocated before! */
{
Tilman Schmidt's avatar
Tilman Schmidt committed
541
542
	inbuf->head = 0;
	inbuf->tail = 0;
543
544
	inbuf->cs = cs;
	inbuf->bcs = bcs; /*base driver: NULL*/
Tilman Schmidt's avatar
Tilman Schmidt committed
545
	inbuf->rcvbuf = NULL;
546
547
548
	inbuf->inputstate = inputstate;
}

549
550
551
552
553
554
/**
 * gigaset_fill_inbuf() - append received data to input buffer
 * @inbuf:	buffer structure.
 * @src:	received data.
 * @numbytes:	number of bytes received.
 */
555
556
557
558
559
560
561
562
563
564
565
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
566
567
	tail = inbuf->tail;
	head = inbuf->head;
568
569
570
571
572
573
574
575
576
577
578
	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,
579
580
				"buffer overflow (%u bytes lost)\n",
				bytesleft);
581
582
583
584
585
586
587
588
589
590
			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
591
	inbuf->tail = tail;
592
593
594
595
	return numbytes != bytesleft;
}
EXPORT_SYMBOL_GPL(gigaset_fill_inbuf);

596
597
/* Initialize the b-channel structure */
static struct bc_state *gigaset_initbcs(struct bc_state *bcs,
598
					struct cardstate *cs, int channel)
599
600
601
602
603
604
605
606
607
608
609
{
	int i;

	bcs->tx_skb = NULL; //FIXME -> hw part

	skb_queue_head_init(&bcs->squeue);

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

610
	gig_dbg(DEBUG_INIT, "setting up bcs[%d]->at_state", channel);
611
612
613
614
615
616
	gigaset_at_init(&bcs->at_state, bcs, cs, -1);

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

617
	gig_dbg(DEBUG_INIT, "allocating bcs[%d]->skb", channel);
618
619
620
621
622
623
624
625
	bcs->fcs = PPP_INITFCS;
	bcs->inputstate = 0;
	if (cs->ignoreframes) {
		bcs->inputstate |= INS_skip_frame;
		bcs->skb = NULL;
	} else if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)
		skb_reserve(bcs->skb, HW_HDR_LEN);
	else {
626
		pr_err("out of memory\n");
627
628
629
630
631
632
633
634
635
636
637
638
639
640
		bcs->inputstate |= INS_skip_frame;
	}

	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;

641
	gig_dbg(DEBUG_INIT, "  setting up bcs[%d]->hw", channel);
642
643
644
	if (cs->ops->initbcshw(bcs))
		return bcs;

645
	gig_dbg(DEBUG_INIT, "  failed");
646

647
	gig_dbg(DEBUG_INIT, "  freeing bcs[%d]->skb", channel);
648
649
650
651
652
653
	if (bcs->skb)
		dev_kfree_skb(bcs->skb);

	return NULL;
}

654
655
656
657
658
659
660
661
662
663
664
/**
 * 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
 *
665
666
667
 * 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
668
669
 *
 * Return value:
670
671
672
673
674
675
676
 *	pointer to cardstate structure
 */
struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
				 int onechannel, int ignoreframes,
				 int cidmode, const char *modulename)
{
	struct cardstate *cs = NULL;
677
	unsigned long flags;
678
679
	int i;

680
	gig_dbg(DEBUG_INIT, "allocating cs");
681
	if (!(cs = alloc_cs(drv))) {
682
		pr_err("maximum number of devices exceeded\n");
683
684
685
		return NULL;
	}

686
	gig_dbg(DEBUG_INIT, "allocating bcs[0..%d]", channels - 1);
687
	cs->bcs = kmalloc(channels * sizeof(struct bc_state), GFP_KERNEL);
688
	if (!cs->bcs) {
689
		pr_err("out of memory\n");
690
		goto error;
691
	}
692
	gig_dbg(DEBUG_INIT, "allocating inbuf");
693
	cs->inbuf = kmalloc(sizeof(struct inbuf_t), GFP_KERNEL);
694
	if (!cs->inbuf) {
695
		pr_err("out of memory\n");
696
		goto error;
697
	}
698
699
700
701
702
703

	cs->cs_init = 0;
	cs->channels = channels;
	cs->onechannel = onechannel;
	cs->ignoreframes = ignoreframes;
	INIT_LIST_HEAD(&cs->temp_at_states);
704
	cs->running = 0;
705
706
	init_timer(&cs->timer); /* clear next & prev */
	spin_lock_init(&cs->ev_lock);
707
708
	cs->ev_tail = 0;
	cs->ev_head = 0;
709

710
711
	tasklet_init(&cs->event_tasklet, &gigaset_handle_event,
		     (unsigned long) cs);
Tilman Schmidt's avatar
Tilman Schmidt committed
712
	cs->commands_pending = 0;
713
714
715
	cs->cur_at_seq = 0;
	cs->gotfwver = -1;
	cs->open_count = 0;
716
	cs->dev = NULL;
717
	cs->tty = NULL;
718
	cs->tty_dev = NULL;
719
	cs->cidmode = cidmode != 0;
720
721
	cs->tabnocid = gigaset_tab_nocid;
	cs->tabcid = gigaset_tab_cid;
722
723
724
725

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

Tilman Schmidt's avatar
Tilman Schmidt committed
726
727
	cs->mode = M_UNKNOWN;
	cs->mstate = MS_UNINITIALIZED;
728
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
738
	}

	++cs->cs_init;

739
	gig_dbg(DEBUG_INIT, "setting up at_state");
740
741
742
743
744
	spin_lock_init(&cs->lock);
	gigaset_at_init(&cs->at_state, NULL, cs, 0);
	cs->dle = 0;
	cs->cbytes = 0;

745
	gig_dbg(DEBUG_INIT, "setting up inbuf");
746
747
748
749
750
	if (onechannel) {			//FIXME distinction necessary?
		gigaset_inbuf_init(cs->inbuf, cs->bcs, cs, INS_command);
	} else
		gigaset_inbuf_init(cs->inbuf, NULL,    cs, INS_command);

751
752
	cs->connected = 0;
	cs->isdn_up = 0;
753

754
	gig_dbg(DEBUG_INIT, "setting up cmdbuf");
755
756
757
758
759
	cs->cmdbuf = cs->lastcmdbuf = NULL;
	spin_lock_init(&cs->cmdlock);
	cs->curlen = 0;
	cs->cmdbytes = 0;

760
	gig_dbg(DEBUG_INIT, "setting up iif");
761
	if (!gigaset_register_to_LL(cs, modulename)) {
762
		pr_err("error registering ISDN device\n");
763
764
765
766
767
		goto error;
	}

	make_valid(cs, VALID_ID);
	++cs->cs_init;
768
	gig_dbg(DEBUG_INIT, "setting up hw");
769
	if (!cs->ops->initcshw(cs))
770
771
772
773
		goto error;

	++cs->cs_init;

774
	/* set up character device */
775
776
	gigaset_if_init(cs);

777
778
779
	/* set up device sysfs */
	gigaset_init_dev_sysfs(cs);

780
781
782
	spin_lock_irqsave(&cs->lock, flags);
	cs->running = 1;
	spin_unlock_irqrestore(&cs->lock, flags);
783
784
	setup_timer(&cs->timer, timer_tick, (unsigned long) cs);
	cs->timer.expires = jiffies + msecs_to_jiffies(GIG_TICK);
785
786
787
788
	/* FIXME: can jiffies increase too much until the timer is added?
	 * Same problem(?) with mod_timer() in timer_tick(). */
	add_timer(&cs->timer);

789
	gig_dbg(DEBUG_INIT, "cs initialized");
790
791
	return cs;

792
error:
793
	gig_dbg(DEBUG_INIT, "failed");
794
795
796
797
798
	gigaset_freecs(cs);
	return NULL;
}
EXPORT_SYMBOL_GPL(gigaset_initcs);

799
/* ReInitialize the b-channel structure on hangup */
800
801
802
803
804
805
806
807
808
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);

809
	spin_lock_irqsave(&cs->lock, flags);
810
811
812
813
	clear_at_state(&bcs->at_state);
	bcs->at_state.ConState = 0;
	bcs->at_state.timer_active = 0;
	bcs->at_state.timer_expires = 0;
814
	bcs->at_state.cid = -1;			/* No CID defined */
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
	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;
	if (bcs->ignore)
		bcs->inputstate |= INS_skip_frame;


	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
842
843
	cs->mode = M_UNKNOWN;
	cs->mstate = MS_UNINITIALIZED;
844
845
846
847
848
849
850
851
852

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

	kfree(cs->inbuf->rcvbuf);
	cs->inbuf->rcvbuf = NULL;
	cs->inbuf->inputstate = INS_command;
Tilman Schmidt's avatar
Tilman Schmidt committed
853
854
	cs->inbuf->head = 0;
	cs->inbuf->tail = 0;
855
856
857
858
859
860
861
862
863
864
865
866
867

	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
868
	cs->commands_pending = 0;
869
870
871
872
873
874
875
	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))
876
			pr_err("could not allocate channel %d data\n", i);
877
878
879
880
881
882
883
884
885
886
	}

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


887
888
889
890
891
892
893
894
895
896
897
/**
 * 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
 */
898
899
int gigaset_start(struct cardstate *cs)
{
900
901
	unsigned long flags;

902
	if (mutex_lock_interruptible(&cs->mutex))
903
904
		return 0;

905
906
907
	spin_lock_irqsave(&cs->lock, flags);
	cs->connected = 1;
	spin_unlock_irqrestore(&cs->lock, flags);
908

Tilman Schmidt's avatar
Tilman Schmidt committed
909
	if (cs->mstate != MS_LOCKED) {
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
		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;
	} else {
		//FIXME use some saved values?
	}

	cs->waiting = 1;

	if (!gigaset_add_event(cs, &cs->at_state, EV_START, NULL, 0, NULL)) {
		cs->waiting = 0;
		//FIXME what should we do?
		goto error;
	}

926
	gig_dbg(DEBUG_CMD, "scheduling START");
927
928
929
930
	gigaset_schedule_event(cs);

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

931
	mutex_unlock(&cs->mutex);
932
933
934
	return 1;

error:
935
	mutex_unlock(&cs->mutex);
936
937
938
939
	return 0;
}
EXPORT_SYMBOL_GPL(gigaset_start);

940
941
942
943
944
945
946
947
948
/**
 * 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
949
950
 */
int gigaset_shutdown(struct cardstate *cs)
951
{
952
	mutex_lock(&cs->mutex);
953

954
955
	if (!(cs->flags & VALID_MINOR)) {
		mutex_unlock(&cs->mutex);
Tilman Schmidt's avatar
Tilman Schmidt committed
956
		return -1;
957
	}
Tilman Schmidt's avatar
Tilman Schmidt committed
958

959
960
961
962
963
964
965
	cs->waiting = 1;

	if (!gigaset_add_event(cs, &cs->at_state, EV_SHUTDOWN, NULL, 0, NULL)) {
		//FIXME what should we do?
		goto exit;
	}

966
	gig_dbg(DEBUG_CMD, "scheduling SHUTDOWN");
967
968
	gigaset_schedule_event(cs);

969
	wait_event(cs->waitqueue, !cs->waiting);
970
971
972
973

	cleanup_cs(cs);

exit:
974
	mutex_unlock(&cs->mutex);
Tilman Schmidt's avatar
Tilman Schmidt committed
975
	return 0;
976
977
978
}
EXPORT_SYMBOL_GPL(gigaset_shutdown);

979
980
981
982
983
984
985
/**
 * 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.
 */
986
987
void gigaset_stop(struct cardstate *cs)
{
988
	mutex_lock(&cs->mutex);
989
990
991
992
993
994
995
996

	cs->waiting = 1;

	if (!gigaset_add_event(cs, &cs->at_state, EV_STOP, NULL, 0, NULL)) {
		//FIXME what should we do?
		goto exit;
	}

997
	gig_dbg(DEBUG_CMD, "scheduling STOP");
998
999
	gigaset_schedule_event(cs);

1000
	wait_event(cs->waitqueue, !cs->waiting);
1001
1002
1003
1004

	cleanup_cs(cs);

exit:
1005
	mutex_unlock(&cs->mutex);
1006
1007
1008
1009
}
EXPORT_SYMBOL_GPL(gigaset_stop);

static LIST_HEAD(drivers);
1010
static DEFINE_SPINLOCK(driver_lock);
1011
1012
1013
1014

struct cardstate *gigaset_get_cs_by_id(int id)
{
	unsigned long flags;
1015
1016
	struct cardstate *ret = NULL;
	struct cardstate *cs;
1017
1018
1019
1020
1021
1022
1023
	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
1024
1025
1026
			cs = drv->cs + i;
			if ((cs->flags & VALID_ID) && cs->myid == id) {
				ret = cs;
1027
				break;
Tilman Schmidt's avatar
Tilman Schmidt committed
1028
			}
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
		}
		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) {
1047
		gig_dbg(DEBUG_DRIVER, "driver %p", drv);
1048
1049
		spin_lock(&drv->lock);
		for (i = 0; i < drv->minors; ++i) {
1050
			gig_dbg(DEBUG_DRIVER, "  index %u", i);
1051
			cs = drv->cs + i;
1052
			gig_dbg(DEBUG_DRIVER, "    cardstate %p", cs);
Tilman Schmidt's avatar
Tilman Schmidt committed
1053
			gig_dbg(DEBUG_DRIVER, "    flags 0x%02x", cs->flags);
1054
1055
1056
1057
			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);
1058
1059
1060
1061
1062
1063
		}
		spin_unlock(&drv->lock);
	}
	spin_unlock_irqrestore(&driver_lock, flags);
}

1064
static struct cardstate *gigaset_get_cs_by_minor(unsigned minor)
1065
1066
{
	unsigned long flags;
1067
	struct cardstate *ret = NULL;
1068
1069
1070
1071
1072
1073
1074
1075
1076
	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
1077
		if (drv->cs[index].flags & VALID_MINOR)
1078
1079
1080
1081
1082
1083
1084
1085
1086
			ret = drv->cs + index;
		spin_unlock(&drv->lock);
		if (ret)
			break;
	}
	spin_unlock_irqrestore(&driver_lock, flags);
	return ret;
}

1087
1088
1089
1090
1091
1092
1093
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);
}

1094
1095
1096
1097
1098
1099
1100
1101
/**
 * 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.
 */
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
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);

1117
1118
1119
1120
1121
1122
1123
/**
 * 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)
 *
1124
 * Allocate and initialize gigaset_driver structure. Initialize interface.
1125
1126
 *
 * Return value:
1127
 *	Pointer to the gigaset_driver structure on success, NULL on failure.
1128
1129
 */
struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors,
1130
1131
1132
1133
					  const char *procname,
					  const char *devname,
					  const struct gigaset_ops *ops,
					  struct module *owner)
1134
1135
1136
1137
1138
1139
1140
1141
{
	struct gigaset_driver *drv;
	unsigned long flags;
	unsigned i;

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

1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
	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)
1154
		goto error;
1155

1156
	for (i = 0; i < minors; ++i) {
Tilman Schmidt's avatar
Tilman Schmidt committed
1157
		drv->cs[i].flags = 0;
1158
1159
1160
		drv->cs[i].driver = drv;
		drv->cs[i].ops = drv->ops;
		drv->cs[i].minor_index = i;
1161
		mutex_init(&drv->cs[i].mutex);
1162
1163
	}

1164
	gigaset_if_initdriver(drv, procname, devname);
1165
1166
1167
1168
1169
1170
1171

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

	return drv;

1172
error:
1173
1174
1175
1176
1177
1178
	kfree(drv->cs);
	kfree(drv);
	return NULL;
}
EXPORT_SYMBOL_GPL(gigaset_initdriver);

1179
1180
1181
1182
1183
1184
1185
/**
 * gigaset_blockdriver() - block driver
 * @drv:	driver descriptor structure.
 *
 * Prevents the driver from attaching new devices, in preparation for
 * deregistration.
 */
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
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;

1201
	pr_info(DRIVER_DESC DRIVER_DESC_DEBUG "\n");
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
	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");