kcapi.c 29.7 KB
Newer Older
L
Linus Torvalds 已提交
1
/* $Id: kcapi.c,v 1.1.2.8 2004/03/26 19:57:20 armin Exp $
2
 *
L
Linus Torvalds 已提交
3
 * Kernel CAPI 2.0 Module
4
 *
L
Linus Torvalds 已提交
5 6
 * Copyright 1999 by Carsten Paeth <calle@calle.de>
 * Copyright 2002 by Kai Germaschewski <kai@germaschewski.name>
7
 *
L
Linus Torvalds 已提交
8 9 10 11 12
 * This software may be used and distributed according to the terms
 * of the GNU General Public License, incorporated herein by reference.
 *
 */

13
#define AVMB1_COMPAT
L
Linus Torvalds 已提交
14 15 16 17 18 19 20

#include "kcapi.h"
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/proc_fs.h>
21
#include <linux/sched/signal.h>
L
Linus Torvalds 已提交
22 23 24 25 26 27 28 29
#include <linux/seq_file.h>
#include <linux/skbuff.h>
#include <linux/workqueue.h>
#include <linux/capi.h>
#include <linux/kernelcapi.h>
#include <linux/init.h>
#include <linux/moduleparam.h>
#include <linux/delay.h>
30
#include <linux/slab.h>
31
#include <linux/uaccess.h>
L
Linus Torvalds 已提交
32 33
#include <linux/isdn/capicmd.h>
#include <linux/isdn/capiutil.h>
34
#ifdef AVMB1_COMPAT
L
Linus Torvalds 已提交
35 36
#include <linux/b1lli.h>
#endif
A
Arjan van de Ven 已提交
37
#include <linux/mutex.h>
J
Jan Kiszka 已提交
38
#include <linux/rcupdate.h>
L
Linus Torvalds 已提交
39 40

static int showcapimsgs = 0;
41
static struct workqueue_struct *kcapi_wq;
L
Linus Torvalds 已提交
42 43 44 45 46 47 48 49

MODULE_DESCRIPTION("CAPI4Linux: kernel CAPI layer");
MODULE_AUTHOR("Carsten Paeth");
MODULE_LICENSE("GPL");
module_param(showcapimsgs, uint, 0);

/* ------------------------------------------------------------- */

50
struct capictr_event {
L
Linus Torvalds 已提交
51
	struct work_struct work;
52
	unsigned int type;
L
Linus Torvalds 已提交
53 54 55 56 57
	u32 controller;
};

/* ------------------------------------------------------------- */

58
static struct capi_version driver_version = {2, 0, 1, 1 << 4};
L
Linus Torvalds 已提交
59 60 61 62 63 64
static char driver_serial[CAPI_SERIAL_LEN] = "0004711";
static char capi_manufakturer[64] = "AVM Berlin";

#define NCCI2CTRL(ncci)    (((ncci) >> 24) & 0x7f)

LIST_HEAD(capi_drivers);
65
DEFINE_MUTEX(capi_drivers_lock);
L
Linus Torvalds 已提交
66

67 68 69
struct capi_ctr *capi_controller[CAPI_MAXCONTR];
DEFINE_MUTEX(capi_controller_lock);

L
Linus Torvalds 已提交
70 71
struct capi20_appl *capi_applications[CAPI_MAXAPPL];

72
static int ncontrollers;
L
Linus Torvalds 已提交
73

74 75
static BLOCKING_NOTIFIER_HEAD(ctr_notifier_list);

L
Linus Torvalds 已提交
76 77 78
/* -------- controller ref counting -------------------------------------- */

static inline struct capi_ctr *
79
capi_ctr_get(struct capi_ctr *ctr)
L
Linus Torvalds 已提交
80
{
81
	if (!try_module_get(ctr->owner))
L
Linus Torvalds 已提交
82
		return NULL;
83
	return ctr;
L
Linus Torvalds 已提交
84 85 86
}

static inline void
87
capi_ctr_put(struct capi_ctr *ctr)
L
Linus Torvalds 已提交
88
{
89
	module_put(ctr->owner);
L
Linus Torvalds 已提交
90 91 92 93 94 95
}

/* ------------------------------------------------------------- */

static inline struct capi_ctr *get_capi_ctr_by_nr(u16 contr)
{
96
	if (contr < 1 || contr - 1 >= CAPI_MAXCONTR)
L
Linus Torvalds 已提交
97 98
		return NULL;

99
	return capi_controller[contr - 1];
L
Linus Torvalds 已提交
100 101
}

102 103 104 105
static inline struct capi20_appl *__get_capi_appl_by_nr(u16 applid)
{
	lockdep_assert_held(&capi_controller_lock);

106
	if (applid < 1 || applid - 1 >= CAPI_MAXAPPL)
107 108 109 110 111
		return NULL;

	return capi_applications[applid - 1];
}

L
Linus Torvalds 已提交
112 113
static inline struct capi20_appl *get_capi_appl_by_nr(u16 applid)
{
114
	if (applid < 1 || applid - 1 >= CAPI_MAXAPPL)
L
Linus Torvalds 已提交
115 116
		return NULL;

J
Jan Kiszka 已提交
117
	return rcu_dereference(capi_applications[applid - 1]);
L
Linus Torvalds 已提交
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
}

/* -------- util functions ------------------------------------ */

static inline int capi_cmd_valid(u8 cmd)
{
	switch (cmd) {
	case CAPI_ALERT:
	case CAPI_CONNECT:
	case CAPI_CONNECT_ACTIVE:
	case CAPI_CONNECT_B3_ACTIVE:
	case CAPI_CONNECT_B3:
	case CAPI_CONNECT_B3_T90_ACTIVE:
	case CAPI_DATA_B3:
	case CAPI_DISCONNECT_B3:
	case CAPI_DISCONNECT:
	case CAPI_FACILITY:
	case CAPI_INFO:
	case CAPI_LISTEN:
	case CAPI_MANUFACTURER:
	case CAPI_RESET_B3:
	case CAPI_SELECT_B_PROTOCOL:
		return 1;
	}
	return 0;
}

static inline int capi_subcmd_valid(u8 subcmd)
{
	switch (subcmd) {
	case CAPI_REQ:
	case CAPI_CONF:
	case CAPI_IND:
	case CAPI_RESP:
		return 1;
	}
	return 0;
}

/* ------------------------------------------------------------ */

159 160
static void
register_appl(struct capi_ctr *ctr, u16 applid, capi_register_params *rparam)
L
Linus Torvalds 已提交
161
{
162
	ctr = capi_ctr_get(ctr);
L
Linus Torvalds 已提交
163

164 165
	if (ctr)
		ctr->register_appl(ctr, applid, rparam);
L
Linus Torvalds 已提交
166
	else
167 168
		printk(KERN_WARNING "%s: cannot get controller resources\n",
		       __func__);
L
Linus Torvalds 已提交
169 170 171
}


172
static void release_appl(struct capi_ctr *ctr, u16 applid)
L
Linus Torvalds 已提交
173 174
{
	DBG("applid %#x", applid);
175

176 177
	ctr->release_appl(ctr, applid);
	capi_ctr_put(ctr);
L
Linus Torvalds 已提交
178 179 180 181 182
}

static void notify_up(u32 contr)
{
	struct capi20_appl *ap;
J
Jan Kiszka 已提交
183
	struct capi_ctr *ctr;
L
Linus Torvalds 已提交
184 185
	u16 applid;

186 187
	mutex_lock(&capi_controller_lock);

J
Jan Kiszka 已提交
188
	if (showcapimsgs & 1)
189
		printk(KERN_DEBUG "kcapi: notify up contr %d\n", contr);
J
Jan Kiszka 已提交
190 191 192 193

	ctr = get_capi_ctr_by_nr(contr);
	if (ctr) {
		if (ctr->state == CAPI_CTR_RUNNING)
194
			goto unlock_out;
J
Jan Kiszka 已提交
195 196 197 198

		ctr->state = CAPI_CTR_RUNNING;

		for (applid = 1; applid <= CAPI_MAXAPPL; applid++) {
199 200 201
			ap = __get_capi_appl_by_nr(applid);
			if (ap)
				register_appl(ctr, applid, &ap->rparam);
J
Jan Kiszka 已提交
202
		}
203 204

		wake_up_interruptible_all(&ctr->state_wait_queue);
J
Jan Kiszka 已提交
205
	} else
206
		printk(KERN_WARNING "%s: invalid contr %d\n", __func__, contr);
207 208 209

unlock_out:
	mutex_unlock(&capi_controller_lock);
L
Linus Torvalds 已提交
210 211
}

212
static void ctr_down(struct capi_ctr *ctr, int new_state)
L
Linus Torvalds 已提交
213 214 215 216
{
	struct capi20_appl *ap;
	u16 applid;

217
	if (ctr->state == CAPI_CTR_DETECTED || ctr->state == CAPI_CTR_DETACHED)
J
Jan Kiszka 已提交
218 219
		return;

220
	ctr->state = new_state;
J
Jan Kiszka 已提交
221 222 223 224 225

	memset(ctr->manu, 0, sizeof(ctr->manu));
	memset(&ctr->version, 0, sizeof(ctr->version));
	memset(&ctr->profile, 0, sizeof(ctr->profile));
	memset(ctr->serial, 0, sizeof(ctr->serial));
L
Linus Torvalds 已提交
226 227

	for (applid = 1; applid <= CAPI_MAXAPPL; applid++) {
228
		ap = __get_capi_appl_by_nr(applid);
J
Jan Kiszka 已提交
229
		if (ap)
J
Jan Kiszka 已提交
230
			capi_ctr_put(ctr);
L
Linus Torvalds 已提交
231
	}
232 233

	wake_up_interruptible_all(&ctr->state_wait_queue);
L
Linus Torvalds 已提交
234 235
}

J
Jan Kiszka 已提交
236 237 238 239
static void notify_down(u32 contr)
{
	struct capi_ctr *ctr;

240 241
	mutex_lock(&capi_controller_lock);

J
Jan Kiszka 已提交
242 243 244 245 246
	if (showcapimsgs & 1)
		printk(KERN_DEBUG "kcapi: notify down contr %d\n", contr);

	ctr = get_capi_ctr_by_nr(contr);
	if (ctr)
247
		ctr_down(ctr, CAPI_CTR_DETECTED);
J
Jan Kiszka 已提交
248 249
	else
		printk(KERN_WARNING "%s: invalid contr %d\n", __func__, contr);
250 251

	mutex_unlock(&capi_controller_lock);
J
Jan Kiszka 已提交
252 253
}

254 255
static int
notify_handler(struct notifier_block *nb, unsigned long val, void *v)
L
Linus Torvalds 已提交
256
{
257
	u32 contr = (long)v;
L
Linus Torvalds 已提交
258

259 260 261
	switch (val) {
	case CAPICTR_UP:
		notify_up(contr);
L
Linus Torvalds 已提交
262
		break;
263 264
	case CAPICTR_DOWN:
		notify_down(contr);
L
Linus Torvalds 已提交
265 266
		break;
	}
267 268 269 270 271 272 273
	return NOTIFY_OK;
}

static void do_notify_work(struct work_struct *work)
{
	struct capictr_event *event =
		container_of(work, struct capictr_event, work);
L
Linus Torvalds 已提交
274

275 276 277
	blocking_notifier_call_chain(&ctr_notifier_list, event->type,
				     (void *)(long)event->controller);
	kfree(event);
L
Linus Torvalds 已提交
278 279 280 281 282 283
}

/*
 * The notifier will result in adding/deleteing of devices. Devices can
 * only removed in user process, not in bh.
 */
284
static int notify_push(unsigned int event_type, u32 controller)
L
Linus Torvalds 已提交
285
{
286
	struct capictr_event *event = kmalloc(sizeof(*event), GFP_ATOMIC);
L
Linus Torvalds 已提交
287

288
	if (!event)
L
Linus Torvalds 已提交
289 290
		return -ENOMEM;

291 292 293
	INIT_WORK(&event->work, do_notify_work);
	event->type = event_type;
	event->controller = controller;
L
Linus Torvalds 已提交
294

295
	queue_work(kcapi_wq, &event->work);
L
Linus Torvalds 已提交
296 297 298
	return 0;
}

299 300 301 302 303 304 305 306 307 308 309 310
int register_capictr_notifier(struct notifier_block *nb)
{
	return blocking_notifier_chain_register(&ctr_notifier_list, nb);
}
EXPORT_SYMBOL_GPL(register_capictr_notifier);

int unregister_capictr_notifier(struct notifier_block *nb)
{
	return blocking_notifier_chain_unregister(&ctr_notifier_list, nb);
}
EXPORT_SYMBOL_GPL(unregister_capictr_notifier);

L
Linus Torvalds 已提交
311 312
/* -------- Receiver ------------------------------------------ */

D
David Howells 已提交
313
static void recv_handler(struct work_struct *work)
L
Linus Torvalds 已提交
314 315
{
	struct sk_buff *skb;
D
David Howells 已提交
316 317
	struct capi20_appl *ap =
		container_of(work, struct capi20_appl, recv_work);
L
Linus Torvalds 已提交
318 319 320 321

	if ((!ap) || (ap->release_in_progress))
		return;

322
	mutex_lock(&ap->recv_mtx);
L
Linus Torvalds 已提交
323 324 325 326 327 328 329 330
	while ((skb = skb_dequeue(&ap->recv_queue))) {
		if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_IND)
			ap->nrecvdatapkt++;
		else
			ap->nrecvctlpkt++;

		ap->recv_message(ap, skb);
	}
331
	mutex_unlock(&ap->recv_mtx);
L
Linus Torvalds 已提交
332 333
}

334 335
/**
 * capi_ctr_handle_message() - handle incoming CAPI message
336
 * @ctr:	controller descriptor structure.
337 338 339 340 341 342
 * @appl:	application ID.
 * @skb:	message.
 *
 * Called by hardware driver to pass a CAPI message to the application.
 */

343 344
void capi_ctr_handle_message(struct capi_ctr *ctr, u16 appl,
			     struct sk_buff *skb)
L
Linus Torvalds 已提交
345 346 347 348
{
	struct capi20_appl *ap;
	int showctl = 0;
	u8 cmd, subcmd;
349
	_cdebbuf *cdb;
L
Linus Torvalds 已提交
350

351
	if (ctr->state != CAPI_CTR_RUNNING) {
352 353 354
		cdb = capi_message2str(skb->data);
		if (cdb) {
			printk(KERN_INFO "kcapi: controller [%03d] not active, got: %s",
355
			       ctr->cnr, cdb->buf);
356 357 358
			cdebbuf_free(cdb);
		} else
			printk(KERN_INFO "kcapi: controller [%03d] not active, cannot trace\n",
359
			       ctr->cnr);
L
Linus Torvalds 已提交
360 361 362 363
		goto error;
	}

	cmd = CAPIMSG_COMMAND(skb->data);
364
	subcmd = CAPIMSG_SUBCOMMAND(skb->data);
L
Linus Torvalds 已提交
365
	if (cmd == CAPI_DATA_B3 && subcmd == CAPI_IND) {
366 367 368
		ctr->nrecvdatapkt++;
		if (ctr->traceflag > 2)
			showctl |= 2;
L
Linus Torvalds 已提交
369
	} else {
370 371 372
		ctr->nrecvctlpkt++;
		if (ctr->traceflag)
			showctl |= 2;
L
Linus Torvalds 已提交
373
	}
374
	showctl |= (ctr->traceflag & 1);
L
Linus Torvalds 已提交
375 376
	if (showctl & 2) {
		if (showctl & 1) {
377
			printk(KERN_DEBUG "kcapi: got [%03d] id#%d %s len=%u\n",
378
			       ctr->cnr, CAPIMSG_APPID(skb->data),
L
Linus Torvalds 已提交
379 380 381
			       capi_cmd2str(cmd, subcmd),
			       CAPIMSG_LEN(skb->data));
		} else {
382 383 384
			cdb = capi_message2str(skb->data);
			if (cdb) {
				printk(KERN_DEBUG "kcapi: got [%03d] %s\n",
385
				       ctr->cnr, cdb->buf);
386 387 388
				cdebbuf_free(cdb);
			} else
				printk(KERN_DEBUG "kcapi: got [%03d] id#%d %s len=%u, cannot trace\n",
389 390 391
				       ctr->cnr, CAPIMSG_APPID(skb->data),
				       capi_cmd2str(cmd, subcmd),
				       CAPIMSG_LEN(skb->data));
L
Linus Torvalds 已提交
392 393 394 395
		}

	}

J
Jan Kiszka 已提交
396
	rcu_read_lock();
L
Linus Torvalds 已提交
397
	ap = get_capi_appl_by_nr(CAPIMSG_APPID(skb->data));
J
Jan Kiszka 已提交
398 399
	if (!ap) {
		rcu_read_unlock();
400 401 402
		cdb = capi_message2str(skb->data);
		if (cdb) {
			printk(KERN_ERR "kcapi: handle_message: applid %d state released (%s)\n",
403
			       CAPIMSG_APPID(skb->data), cdb->buf);
404 405 406
			cdebbuf_free(cdb);
		} else
			printk(KERN_ERR "kcapi: handle_message: applid %d state released (%s) cannot trace\n",
407 408
			       CAPIMSG_APPID(skb->data),
			       capi_cmd2str(cmd, subcmd));
L
Linus Torvalds 已提交
409 410 411
		goto error;
	}
	skb_queue_tail(&ap->recv_queue, skb);
412
	queue_work(kcapi_wq, &ap->recv_work);
J
Jan Kiszka 已提交
413
	rcu_read_unlock();
L
Linus Torvalds 已提交
414 415 416 417 418 419 420 421 422

	return;

error:
	kfree_skb(skb);
}

EXPORT_SYMBOL(capi_ctr_handle_message);

423 424
/**
 * capi_ctr_ready() - signal CAPI controller ready
425
 * @ctr:	controller descriptor structure.
426 427 428 429
 *
 * Called by hardware driver to signal that the controller is up and running.
 */

430
void capi_ctr_ready(struct capi_ctr *ctr)
L
Linus Torvalds 已提交
431
{
432 433
	printk(KERN_NOTICE "kcapi: controller [%03d] \"%s\" ready.\n",
	       ctr->cnr, ctr->name);
L
Linus Torvalds 已提交
434

435
	notify_push(CAPICTR_UP, ctr->cnr);
L
Linus Torvalds 已提交
436 437 438 439
}

EXPORT_SYMBOL(capi_ctr_ready);

440
/**
441
 * capi_ctr_down() - signal CAPI controller not ready
442
 * @ctr:	controller descriptor structure.
443 444 445 446 447
 *
 * Called by hardware driver to signal that the controller is down and
 * unavailable for use.
 */

448
void capi_ctr_down(struct capi_ctr *ctr)
L
Linus Torvalds 已提交
449
{
450
	printk(KERN_NOTICE "kcapi: controller [%03d] down.\n", ctr->cnr);
L
Linus Torvalds 已提交
451

452
	notify_push(CAPICTR_DOWN, ctr->cnr);
L
Linus Torvalds 已提交
453 454
}

455
EXPORT_SYMBOL(capi_ctr_down);
L
Linus Torvalds 已提交
456

457 458
/**
 * capi_ctr_suspend_output() - suspend controller
459
 * @ctr:	controller descriptor structure.
460 461
 *
 * Called by hardware driver to stop data flow.
462 463 464
 *
 * Note: The caller is responsible for synchronizing concurrent state changes
 * as well as invocations of capi_ctr_handle_message.
465 466
 */

467
void capi_ctr_suspend_output(struct capi_ctr *ctr)
L
Linus Torvalds 已提交
468
{
469 470 471 472
	if (!ctr->blocked) {
		printk(KERN_DEBUG "kcapi: controller [%03d] suspend\n",
		       ctr->cnr);
		ctr->blocked = 1;
L
Linus Torvalds 已提交
473 474 475 476 477
	}
}

EXPORT_SYMBOL(capi_ctr_suspend_output);

478 479
/**
 * capi_ctr_resume_output() - resume controller
480
 * @ctr:	controller descriptor structure.
481 482
 *
 * Called by hardware driver to resume data flow.
483 484 485
 *
 * Note: The caller is responsible for synchronizing concurrent state changes
 * as well as invocations of capi_ctr_handle_message.
486 487
 */

488
void capi_ctr_resume_output(struct capi_ctr *ctr)
L
Linus Torvalds 已提交
489
{
490 491 492 493
	if (ctr->blocked) {
		printk(KERN_DEBUG "kcapi: controller [%03d] resumed\n",
		       ctr->cnr);
		ctr->blocked = 0;
L
Linus Torvalds 已提交
494 495 496 497 498 499 500
	}
}

EXPORT_SYMBOL(capi_ctr_resume_output);

/* ------------------------------------------------------------- */

501 502
/**
 * attach_capi_ctr() - register CAPI controller
503
 * @ctr:	controller descriptor structure.
504 505 506 507 508
 *
 * Called by hardware driver to register a controller with the CAPI subsystem.
 * Return value: 0 on success, error code < 0 on error
 */

509
int attach_capi_ctr(struct capi_ctr *ctr)
L
Linus Torvalds 已提交
510 511 512
{
	int i;

513
	mutex_lock(&capi_controller_lock);
L
Linus Torvalds 已提交
514 515

	for (i = 0; i < CAPI_MAXCONTR; i++) {
516
		if (!capi_controller[i])
L
Linus Torvalds 已提交
517 518 519
			break;
	}
	if (i == CAPI_MAXCONTR) {
520
		mutex_unlock(&capi_controller_lock);
L
Linus Torvalds 已提交
521
		printk(KERN_ERR "kcapi: out of controller slots\n");
522
		return -EBUSY;
L
Linus Torvalds 已提交
523
	}
524
	capi_controller[i] = ctr;
L
Linus Torvalds 已提交
525

526 527 528 529 530 531 532 533
	ctr->nrecvctlpkt = 0;
	ctr->nrecvdatapkt = 0;
	ctr->nsentctlpkt = 0;
	ctr->nsentdatapkt = 0;
	ctr->cnr = i + 1;
	ctr->state = CAPI_CTR_DETECTED;
	ctr->blocked = 0;
	ctr->traceflag = showcapimsgs;
534
	init_waitqueue_head(&ctr->state_wait_queue);
535 536 537 538 539

	sprintf(ctr->procfn, "capi/controllers/%d", ctr->cnr);
	ctr->procent = proc_create_data(ctr->procfn, 0, NULL, ctr->proc_fops, ctr);

	ncontrollers++;
540 541 542

	mutex_unlock(&capi_controller_lock);

543
	printk(KERN_NOTICE "kcapi: controller [%03d]: %s attached\n",
544
	       ctr->cnr, ctr->name);
L
Linus Torvalds 已提交
545 546 547 548 549
	return 0;
}

EXPORT_SYMBOL(attach_capi_ctr);

550 551
/**
 * detach_capi_ctr() - unregister CAPI controller
552
 * @ctr:	controller descriptor structure.
553 554 555 556 557 558
 *
 * Called by hardware driver to remove the registration of a controller
 * with the CAPI subsystem.
 * Return value: 0 on success, error code < 0 on error
 */

559
int detach_capi_ctr(struct capi_ctr *ctr)
L
Linus Torvalds 已提交
560
{
561
	int err = 0;
L
Linus Torvalds 已提交
562

563
	mutex_lock(&capi_controller_lock);
L
Linus Torvalds 已提交
564

565 566 567 568 569
	ctr_down(ctr, CAPI_CTR_DETACHED);

	if (capi_controller[ctr->cnr - 1] != ctr) {
		err = -EINVAL;
		goto unlock_out;
L
Linus Torvalds 已提交
570
	}
571
	capi_controller[ctr->cnr - 1] = NULL;
572 573 574 575 576
	ncontrollers--;

	if (ctr->procent)
		remove_proc_entry(ctr->procfn, NULL);

577 578
	printk(KERN_NOTICE "kcapi: controller [%03d]: %s unregistered\n",
	       ctr->cnr, ctr->name);
L
Linus Torvalds 已提交
579

580 581 582 583
unlock_out:
	mutex_unlock(&capi_controller_lock);

	return err;
L
Linus Torvalds 已提交
584 585 586 587
}

EXPORT_SYMBOL(detach_capi_ctr);

588 589 590 591 592 593 594
/**
 * register_capi_driver() - register CAPI driver
 * @driver:	driver descriptor structure.
 *
 * Called by hardware driver to register itself with the CAPI subsystem.
 */

L
Linus Torvalds 已提交
595 596
void register_capi_driver(struct capi_driver *driver)
{
597
	mutex_lock(&capi_drivers_lock);
L
Linus Torvalds 已提交
598
	list_add_tail(&driver->list, &capi_drivers);
599
	mutex_unlock(&capi_drivers_lock);
L
Linus Torvalds 已提交
600 601 602 603
}

EXPORT_SYMBOL(register_capi_driver);

604 605 606 607 608 609 610
/**
 * unregister_capi_driver() - unregister CAPI driver
 * @driver:	driver descriptor structure.
 *
 * Called by hardware driver to unregister itself from the CAPI subsystem.
 */

L
Linus Torvalds 已提交
611 612
void unregister_capi_driver(struct capi_driver *driver)
{
613
	mutex_lock(&capi_drivers_lock);
L
Linus Torvalds 已提交
614
	list_del(&driver->list);
615
	mutex_unlock(&capi_drivers_lock);
L
Linus Torvalds 已提交
616 617 618 619 620 621 622 623
}

EXPORT_SYMBOL(unregister_capi_driver);

/* ------------------------------------------------------------- */
/* -------- CAPI2.0 Interface ---------------------------------- */
/* ------------------------------------------------------------- */

624 625 626 627 628 629 630
/**
 * capi20_isinstalled() - CAPI 2.0 operation CAPI_INSTALLED
 *
 * Return value: CAPI result code (CAPI_NOERROR if at least one ISDN controller
 *	is ready for use, CAPI_REGNOTINSTALLED otherwise)
 */

L
Linus Torvalds 已提交
631 632
u16 capi20_isinstalled(void)
{
633
	u16 ret = CAPI_REGNOTINSTALLED;
L
Linus Torvalds 已提交
634
	int i;
635 636 637 638

	mutex_lock(&capi_controller_lock);

	for (i = 0; i < CAPI_MAXCONTR; i++)
639
		if (capi_controller[i] &&
640 641 642 643 644 645 646 647
		    capi_controller[i]->state == CAPI_CTR_RUNNING) {
			ret = CAPI_NOERROR;
			break;
		}

	mutex_unlock(&capi_controller_lock);

	return ret;
L
Linus Torvalds 已提交
648 649 650 651
}

EXPORT_SYMBOL(capi20_isinstalled);

652 653 654 655 656 657 658 659 660 661 662 663
/**
 * capi20_register() - CAPI 2.0 operation CAPI_REGISTER
 * @ap:		CAPI application descriptor structure.
 *
 * Register an application's presence with CAPI.
 * A unique application ID is assigned and stored in @ap->applid.
 * After this function returns successfully, the message receive
 * callback function @ap->recv_message() may be called at any time
 * until capi20_release() has been called for the same @ap.
 * Return value: CAPI result code
 */

L
Linus Torvalds 已提交
664 665 666 667 668 669 670 671 672 673
u16 capi20_register(struct capi20_appl *ap)
{
	int i;
	u16 applid;

	DBG("");

	if (ap->rparam.datablklen < 128)
		return CAPI_LOGBLKSIZETOSMALL;

J
Jan Kiszka 已提交
674 675 676 677 678 679 680 681 682 683
	ap->nrecvctlpkt = 0;
	ap->nrecvdatapkt = 0;
	ap->nsentctlpkt = 0;
	ap->nsentdatapkt = 0;
	mutex_init(&ap->recv_mtx);
	skb_queue_head_init(&ap->recv_queue);
	INIT_WORK(&ap->recv_work, recv_handler);
	ap->release_in_progress = 0;

	mutex_lock(&capi_controller_lock);
L
Linus Torvalds 已提交
684 685 686 687 688 689

	for (applid = 1; applid <= CAPI_MAXAPPL; applid++) {
		if (capi_applications[applid - 1] == NULL)
			break;
	}
	if (applid > CAPI_MAXAPPL) {
J
Jan Kiszka 已提交
690
		mutex_unlock(&capi_controller_lock);
L
Linus Torvalds 已提交
691 692 693 694 695 696 697
		return CAPI_TOOMANYAPPLS;
	}

	ap->applid = applid;
	capi_applications[applid - 1] = ap;

	for (i = 0; i < CAPI_MAXCONTR; i++) {
698 699
		if (!capi_controller[i] ||
		    capi_controller[i]->state != CAPI_CTR_RUNNING)
L
Linus Torvalds 已提交
700
			continue;
701
		register_appl(capi_controller[i], applid, &ap->rparam);
L
Linus Torvalds 已提交
702
	}
703 704

	mutex_unlock(&capi_controller_lock);
L
Linus Torvalds 已提交
705 706 707 708 709 710 711 712 713 714

	if (showcapimsgs & 1) {
		printk(KERN_DEBUG "kcapi: appl %d up\n", applid);
	}

	return CAPI_NOERROR;
}

EXPORT_SYMBOL(capi20_register);

715 716 717 718 719 720 721 722 723 724
/**
 * capi20_release() - CAPI 2.0 operation CAPI_RELEASE
 * @ap:		CAPI application descriptor structure.
 *
 * Terminate an application's registration with CAPI.
 * After this function returns successfully, the message receive
 * callback function @ap->recv_message() will no longer be called.
 * Return value: CAPI result code
 */

L
Linus Torvalds 已提交
725 726 727 728 729 730
u16 capi20_release(struct capi20_appl *ap)
{
	int i;

	DBG("applid %#x", ap->applid);

J
Jan Kiszka 已提交
731 732
	mutex_lock(&capi_controller_lock);

L
Linus Torvalds 已提交
733 734 735
	ap->release_in_progress = 1;
	capi_applications[ap->applid - 1] = NULL;

J
Jan Kiszka 已提交
736
	synchronize_rcu();
737

L
Linus Torvalds 已提交
738
	for (i = 0; i < CAPI_MAXCONTR; i++) {
739 740
		if (!capi_controller[i] ||
		    capi_controller[i]->state != CAPI_CTR_RUNNING)
L
Linus Torvalds 已提交
741
			continue;
742
		release_appl(capi_controller[i], ap->applid);
L
Linus Torvalds 已提交
743
	}
744 745

	mutex_unlock(&capi_controller_lock);
L
Linus Torvalds 已提交
746

747
	flush_workqueue(kcapi_wq);
L
Linus Torvalds 已提交
748 749 750 751 752 753 754 755 756 757 758
	skb_queue_purge(&ap->recv_queue);

	if (showcapimsgs & 1) {
		printk(KERN_DEBUG "kcapi: appl %d down\n", ap->applid);
	}

	return CAPI_NOERROR;
}

EXPORT_SYMBOL(capi20_release);

759 760 761 762 763 764 765 766 767
/**
 * capi20_put_message() - CAPI 2.0 operation CAPI_PUT_MESSAGE
 * @ap:		CAPI application descriptor structure.
 * @skb:	CAPI message.
 *
 * Transfer a single message to CAPI.
 * Return value: CAPI result code
 */

L
Linus Torvalds 已提交
768 769
u16 capi20_put_message(struct capi20_appl *ap, struct sk_buff *skb)
{
770
	struct capi_ctr *ctr;
L
Linus Torvalds 已提交
771 772 773 774
	int showctl = 0;
	u8 cmd, subcmd;

	DBG("applid %#x", ap->applid);
775

776
	if (ncontrollers == 0)
L
Linus Torvalds 已提交
777 778 779 780 781 782 783
		return CAPI_REGNOTINSTALLED;
	if ((ap->applid == 0) || ap->release_in_progress)
		return CAPI_ILLAPPNR;
	if (skb->len < 12
	    || !capi_cmd_valid(CAPIMSG_COMMAND(skb->data))
	    || !capi_subcmd_valid(CAPIMSG_SUBCOMMAND(skb->data)))
		return CAPI_ILLCMDORSUBCMDORMSGTOSMALL;
784 785 786 787 788 789

	/*
	 * The controller reference is protected by the existence of the
	 * application passed to us. We assume that the caller properly
	 * synchronizes this service with capi20_release.
	 */
790
	ctr = get_capi_ctr_by_nr(CAPIMSG_CONTROLLER(skb->data));
791 792
	if (!ctr || ctr->state != CAPI_CTR_RUNNING)
		return CAPI_REGNOTINSTALLED;
793
	if (ctr->blocked)
L
Linus Torvalds 已提交
794 795 796
		return CAPI_SENDQUEUEFULL;

	cmd = CAPIMSG_COMMAND(skb->data);
797
	subcmd = CAPIMSG_SUBCOMMAND(skb->data);
L
Linus Torvalds 已提交
798

799
	if (cmd == CAPI_DATA_B3 && subcmd == CAPI_REQ) {
800
		ctr->nsentdatapkt++;
L
Linus Torvalds 已提交
801
		ap->nsentdatapkt++;
802 803
		if (ctr->traceflag > 2)
			showctl |= 2;
L
Linus Torvalds 已提交
804
	} else {
805
		ctr->nsentctlpkt++;
L
Linus Torvalds 已提交
806
		ap->nsentctlpkt++;
807 808
		if (ctr->traceflag)
			showctl |= 2;
L
Linus Torvalds 已提交
809
	}
810
	showctl |= (ctr->traceflag & 1);
L
Linus Torvalds 已提交
811 812
	if (showctl & 2) {
		if (showctl & 1) {
813
			printk(KERN_DEBUG "kcapi: put [%03d] id#%d %s len=%u\n",
L
Linus Torvalds 已提交
814 815 816 817 818
			       CAPIMSG_CONTROLLER(skb->data),
			       CAPIMSG_APPID(skb->data),
			       capi_cmd2str(cmd, subcmd),
			       CAPIMSG_LEN(skb->data));
		} else {
819 820 821
			_cdebbuf *cdb = capi_message2str(skb->data);
			if (cdb) {
				printk(KERN_DEBUG "kcapi: put [%03d] %s\n",
822 823
				       CAPIMSG_CONTROLLER(skb->data),
				       cdb->buf);
824 825 826
				cdebbuf_free(cdb);
			} else
				printk(KERN_DEBUG "kcapi: put [%03d] id#%d %s len=%u cannot trace\n",
827 828 829 830
				       CAPIMSG_CONTROLLER(skb->data),
				       CAPIMSG_APPID(skb->data),
				       capi_cmd2str(cmd, subcmd),
				       CAPIMSG_LEN(skb->data));
L
Linus Torvalds 已提交
831 832
		}
	}
833
	return ctr->send_message(ctr, skb);
L
Linus Torvalds 已提交
834 835 836 837
}

EXPORT_SYMBOL(capi20_put_message);

838 839 840 841 842 843 844 845 846 847
/**
 * capi20_get_manufacturer() - CAPI 2.0 operation CAPI_GET_MANUFACTURER
 * @contr:	controller number.
 * @buf:	result buffer (64 bytes).
 *
 * Retrieve information about the manufacturer of the specified ISDN controller
 * or (for @contr == 0) the driver itself.
 * Return value: CAPI result code
 */

L
Linus Torvalds 已提交
848 849
u16 capi20_get_manufacturer(u32 contr, u8 *buf)
{
850
	struct capi_ctr *ctr;
851
	u16 ret;
L
Linus Torvalds 已提交
852 853 854 855 856

	if (contr == 0) {
		strlcpy(buf, capi_manufakturer, CAPI_MANUFACTURER_LEN);
		return CAPI_NOERROR;
	}
857 858 859

	mutex_lock(&capi_controller_lock);

860
	ctr = get_capi_ctr_by_nr(contr);
861 862 863 864 865 866 867 868
	if (ctr && ctr->state == CAPI_CTR_RUNNING) {
		strlcpy(buf, ctr->manu, CAPI_MANUFACTURER_LEN);
		ret = CAPI_NOERROR;
	} else
		ret = CAPI_REGNOTINSTALLED;

	mutex_unlock(&capi_controller_lock);
	return ret;
L
Linus Torvalds 已提交
869 870 871 872
}

EXPORT_SYMBOL(capi20_get_manufacturer);

873 874 875 876 877 878 879 880 881 882
/**
 * capi20_get_version() - CAPI 2.0 operation CAPI_GET_VERSION
 * @contr:	controller number.
 * @verp:	result structure.
 *
 * Retrieve version information for the specified ISDN controller
 * or (for @contr == 0) the driver itself.
 * Return value: CAPI result code
 */

L
Linus Torvalds 已提交
883 884
u16 capi20_get_version(u32 contr, struct capi_version *verp)
{
885
	struct capi_ctr *ctr;
886
	u16 ret;
L
Linus Torvalds 已提交
887 888 889 890 891

	if (contr == 0) {
		*verp = driver_version;
		return CAPI_NOERROR;
	}
892 893 894

	mutex_lock(&capi_controller_lock);

895
	ctr = get_capi_ctr_by_nr(contr);
896 897 898 899 900
	if (ctr && ctr->state == CAPI_CTR_RUNNING) {
		memcpy(verp, &ctr->version, sizeof(capi_version));
		ret = CAPI_NOERROR;
	} else
		ret = CAPI_REGNOTINSTALLED;
L
Linus Torvalds 已提交
901

902 903
	mutex_unlock(&capi_controller_lock);
	return ret;
L
Linus Torvalds 已提交
904 905 906 907
}

EXPORT_SYMBOL(capi20_get_version);

908 909 910 911 912 913 914 915 916 917
/**
 * capi20_get_serial() - CAPI 2.0 operation CAPI_GET_SERIAL_NUMBER
 * @contr:	controller number.
 * @serial:	result buffer (8 bytes).
 *
 * Retrieve the serial number of the specified ISDN controller
 * or (for @contr == 0) the driver itself.
 * Return value: CAPI result code
 */

L
Linus Torvalds 已提交
918 919
u16 capi20_get_serial(u32 contr, u8 *serial)
{
920
	struct capi_ctr *ctr;
921
	u16 ret;
L
Linus Torvalds 已提交
922 923 924 925 926

	if (contr == 0) {
		strlcpy(serial, driver_serial, CAPI_SERIAL_LEN);
		return CAPI_NOERROR;
	}
927 928 929

	mutex_lock(&capi_controller_lock);

930
	ctr = get_capi_ctr_by_nr(contr);
931 932 933 934 935
	if (ctr && ctr->state == CAPI_CTR_RUNNING) {
		strlcpy(serial, ctr->serial, CAPI_SERIAL_LEN);
		ret = CAPI_NOERROR;
	} else
		ret = CAPI_REGNOTINSTALLED;
L
Linus Torvalds 已提交
936

937 938
	mutex_unlock(&capi_controller_lock);
	return ret;
L
Linus Torvalds 已提交
939 940 941 942
}

EXPORT_SYMBOL(capi20_get_serial);

943 944 945 946 947 948 949 950 951 952
/**
 * capi20_get_profile() - CAPI 2.0 operation CAPI_GET_PROFILE
 * @contr:	controller number.
 * @profp:	result structure.
 *
 * Retrieve capability information for the specified ISDN controller
 * or (for @contr == 0) the number of installed controllers.
 * Return value: CAPI result code
 */

L
Linus Torvalds 已提交
953 954
u16 capi20_get_profile(u32 contr, struct capi_profile *profp)
{
955
	struct capi_ctr *ctr;
956
	u16 ret;
L
Linus Torvalds 已提交
957 958

	if (contr == 0) {
959
		profp->ncontroller = ncontrollers;
L
Linus Torvalds 已提交
960 961
		return CAPI_NOERROR;
	}
962 963 964

	mutex_lock(&capi_controller_lock);

965
	ctr = get_capi_ctr_by_nr(contr);
966 967 968 969 970
	if (ctr && ctr->state == CAPI_CTR_RUNNING) {
		memcpy(profp, &ctr->profile, sizeof(struct capi_profile));
		ret = CAPI_NOERROR;
	} else
		ret = CAPI_REGNOTINSTALLED;
L
Linus Torvalds 已提交
971

972 973
	mutex_unlock(&capi_controller_lock);
	return ret;
L
Linus Torvalds 已提交
974 975 976 977
}

EXPORT_SYMBOL(capi20_get_profile);

978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013
/* Must be called with capi_controller_lock held. */
static int wait_on_ctr_state(struct capi_ctr *ctr, unsigned int state)
{
	DEFINE_WAIT(wait);
	int retval = 0;

	ctr = capi_ctr_get(ctr);
	if (!ctr)
		return -ESRCH;

	for (;;) {
		prepare_to_wait(&ctr->state_wait_queue, &wait,
				TASK_INTERRUPTIBLE);

		if (ctr->state == state)
			break;
		if (ctr->state == CAPI_CTR_DETACHED) {
			retval = -ESRCH;
			break;
		}
		if (signal_pending(current)) {
			retval = -EINTR;
			break;
		}

		mutex_unlock(&capi_controller_lock);
		schedule();
		mutex_lock(&capi_controller_lock);
	}
	finish_wait(&ctr->state_wait_queue, &wait);

	capi_ctr_put(ctr);

	return retval;
}

1014
#ifdef AVMB1_COMPAT
L
Linus Torvalds 已提交
1015 1016 1017 1018 1019 1020
static int old_capi_manufacturer(unsigned int cmd, void __user *data)
{
	avmb1_loadandconfigdef ldef;
	avmb1_extcarddef cdef;
	avmb1_resetdef rdef;
	capicardparams cparams;
1021
	struct capi_ctr *ctr;
L
Linus Torvalds 已提交
1022 1023 1024 1025 1026 1027 1028 1029 1030
	struct capi_driver *driver = NULL;
	capiloaddata ldata;
	struct list_head *l;
	int retval;

	switch (cmd) {
	case AVMB1_ADDCARD:
	case AVMB1_ADDCARD_WITH_TYPE:
		if (cmd == AVMB1_ADDCARD) {
1031 1032 1033 1034
			if ((retval = copy_from_user(&cdef, data,
						     sizeof(avmb1_carddef))))
				return -EFAULT;
			cdef.cardtype = AVM_CARDTYPE_B1;
1035
			cdef.cardnr = 0;
L
Linus Torvalds 已提交
1036
		} else {
1037 1038 1039
			if ((retval = copy_from_user(&cdef, data,
						     sizeof(avmb1_extcarddef))))
				return -EFAULT;
L
Linus Torvalds 已提交
1040 1041 1042 1043 1044
		}
		cparams.port = cdef.port;
		cparams.irq = cdef.irq;
		cparams.cardnr = cdef.cardnr;

1045 1046
		mutex_lock(&capi_drivers_lock);

1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064
		switch (cdef.cardtype) {
		case AVM_CARDTYPE_B1:
			list_for_each(l, &capi_drivers) {
				driver = list_entry(l, struct capi_driver, list);
				if (strcmp(driver->name, "b1isa") == 0)
					break;
			}
			break;
		case AVM_CARDTYPE_T1:
			list_for_each(l, &capi_drivers) {
				driver = list_entry(l, struct capi_driver, list);
				if (strcmp(driver->name, "t1isa") == 0)
					break;
			}
			break;
		default:
			driver = NULL;
			break;
L
Linus Torvalds 已提交
1065 1066 1067
		}
		if (!driver) {
			printk(KERN_ERR "kcapi: driver not loaded.\n");
1068 1069
			retval = -EIO;
		} else if (!driver->add_card) {
L
Linus Torvalds 已提交
1070
			printk(KERN_ERR "kcapi: driver has no add card function.\n");
1071 1072 1073
			retval = -EIO;
		} else
			retval = driver->add_card(driver, &cparams);
L
Linus Torvalds 已提交
1074

1075
		mutex_unlock(&capi_drivers_lock);
L
Linus Torvalds 已提交
1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091
		return retval;

	case AVMB1_LOAD:
	case AVMB1_LOAD_AND_CONFIG:

		if (cmd == AVMB1_LOAD) {
			if (copy_from_user(&ldef, data,
					   sizeof(avmb1_loaddef)))
				return -EFAULT;
			ldef.t4config.len = 0;
			ldef.t4config.data = NULL;
		} else {
			if (copy_from_user(&ldef, data,
					   sizeof(avmb1_loadandconfigdef)))
				return -EFAULT;
		}
1092 1093 1094

		mutex_lock(&capi_controller_lock);

1095
		ctr = get_capi_ctr_by_nr(ldef.contr);
1096 1097 1098 1099 1100
		if (!ctr) {
			retval = -EINVAL;
			goto load_unlock_out;
		}

1101
		if (ctr->load_firmware == NULL) {
L
Linus Torvalds 已提交
1102
			printk(KERN_DEBUG "kcapi: load: no load function\n");
1103 1104
			retval = -ESRCH;
			goto load_unlock_out;
L
Linus Torvalds 已提交
1105 1106 1107 1108
		}

		if (ldef.t4file.len <= 0) {
			printk(KERN_DEBUG "kcapi: load: invalid parameter: length of t4file is %d ?\n", ldef.t4file.len);
1109 1110
			retval = -EINVAL;
			goto load_unlock_out;
L
Linus Torvalds 已提交
1111
		}
1112
		if (ldef.t4file.data == NULL) {
L
Linus Torvalds 已提交
1113
			printk(KERN_DEBUG "kcapi: load: invalid parameter: dataptr is 0\n");
1114 1115
			retval = -EINVAL;
			goto load_unlock_out;
L
Linus Torvalds 已提交
1116 1117 1118 1119 1120 1121 1122 1123 1124
		}

		ldata.firmware.user = 1;
		ldata.firmware.data = ldef.t4file.data;
		ldata.firmware.len = ldef.t4file.len;
		ldata.configuration.user = 1;
		ldata.configuration.data = ldef.t4config.data;
		ldata.configuration.len = ldef.t4config.len;

1125
		if (ctr->state != CAPI_CTR_DETECTED) {
L
Linus Torvalds 已提交
1126
			printk(KERN_INFO "kcapi: load: contr=%d not in detect state\n", ldef.contr);
1127 1128
			retval = -EBUSY;
			goto load_unlock_out;
L
Linus Torvalds 已提交
1129
		}
1130
		ctr->state = CAPI_CTR_LOADING;
L
Linus Torvalds 已提交
1131

1132
		retval = ctr->load_firmware(ctr, &ldata);
L
Linus Torvalds 已提交
1133
		if (retval) {
1134
			ctr->state = CAPI_CTR_DETECTED;
1135
			goto load_unlock_out;
L
Linus Torvalds 已提交
1136 1137
		}

1138
		retval = wait_on_ctr_state(ctr, CAPI_CTR_RUNNING);
L
Linus Torvalds 已提交
1139

1140
	load_unlock_out:
1141 1142
		mutex_unlock(&capi_controller_lock);
		return retval;
L
Linus Torvalds 已提交
1143 1144 1145 1146

	case AVMB1_RESETCARD:
		if (copy_from_user(&rdef, data, sizeof(avmb1_resetdef)))
			return -EFAULT;
1147 1148 1149 1150 1151

		retval = 0;

		mutex_lock(&capi_controller_lock);

1152
		ctr = get_capi_ctr_by_nr(rdef.contr);
1153 1154 1155 1156
		if (!ctr) {
			retval = -ESRCH;
			goto reset_unlock_out;
		}
L
Linus Torvalds 已提交
1157

1158
		if (ctr->state == CAPI_CTR_DETECTED)
1159
			goto reset_unlock_out;
L
Linus Torvalds 已提交
1160

1161 1162 1163 1164 1165 1166
		if (ctr->reset_ctr == NULL) {
			printk(KERN_DEBUG "kcapi: reset: no reset function\n");
			retval = -ESRCH;
			goto reset_unlock_out;
		}

1167
		ctr->reset_ctr(ctr);
L
Linus Torvalds 已提交
1168

1169
		retval = wait_on_ctr_state(ctr, CAPI_CTR_DETECTED);
L
Linus Torvalds 已提交
1170

1171
	reset_unlock_out:
1172 1173
		mutex_unlock(&capi_controller_lock);
		return retval;
L
Linus Torvalds 已提交
1174 1175 1176 1177 1178
	}
	return -EINVAL;
}
#endif

1179 1180 1181 1182 1183 1184 1185 1186 1187
/**
 * capi20_manufacturer() - CAPI 2.0 operation CAPI_MANUFACTURER
 * @cmd:	command.
 * @data:	parameter.
 *
 * Perform manufacturer specific command.
 * Return value: CAPI result code
 */

1188
int capi20_manufacturer(unsigned long cmd, void __user *data)
L
Linus Torvalds 已提交
1189
{
1190
	struct capi_ctr *ctr;
1191
	int retval;
L
Linus Torvalds 已提交
1192 1193

	switch (cmd) {
1194
#ifdef AVMB1_COMPAT
L
Linus Torvalds 已提交
1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208
	case AVMB1_LOAD:
	case AVMB1_LOAD_AND_CONFIG:
	case AVMB1_RESETCARD:
	case AVMB1_GET_CARDINFO:
	case AVMB1_REMOVECARD:
		return old_capi_manufacturer(cmd, data);
#endif
	case KCAPI_CMD_TRACE:
	{
		kcapi_flagdef fdef;

		if (copy_from_user(&fdef, data, sizeof(kcapi_flagdef)))
			return -EFAULT;

1209 1210
		mutex_lock(&capi_controller_lock);

1211
		ctr = get_capi_ctr_by_nr(fdef.contr);
1212 1213 1214 1215 1216 1217 1218 1219 1220
		if (ctr) {
			ctr->traceflag = fdef.flag;
			printk(KERN_INFO "kcapi: contr [%03d] set trace=%d\n",
			       ctr->cnr, ctr->traceflag);
			retval = 0;
		} else
			retval = -ESRCH;

		mutex_unlock(&capi_controller_lock);
L
Linus Torvalds 已提交
1221

1222
		return retval;
L
Linus Torvalds 已提交
1223 1224 1225 1226 1227 1228 1229 1230 1231
	}
	case KCAPI_CMD_ADDCARD:
	{
		struct list_head *l;
		struct capi_driver *driver = NULL;
		capicardparams cparams;
		kcapi_carddef cdef;

		if ((retval = copy_from_user(&cdef, data, sizeof(cdef))))
1232
			return -EFAULT;
L
Linus Torvalds 已提交
1233 1234 1235 1236 1237 1238

		cparams.port = cdef.port;
		cparams.irq = cdef.irq;
		cparams.membase = cdef.membase;
		cparams.cardnr = cdef.cardnr;
		cparams.cardtype = 0;
1239
		cdef.driver[sizeof(cdef.driver) - 1] = 0;
L
Linus Torvalds 已提交
1240

1241 1242
		mutex_lock(&capi_drivers_lock);

L
Linus Torvalds 已提交
1243 1244 1245 1246 1247
		list_for_each(l, &capi_drivers) {
			driver = list_entry(l, struct capi_driver, list);
			if (strcmp(driver->name, cdef.driver) == 0)
				break;
		}
1248
		if (driver == NULL) {
L
Linus Torvalds 已提交
1249
			printk(KERN_ERR "kcapi: driver \"%s\" not loaded.\n",
1250
			       cdef.driver);
1251 1252
			retval = -ESRCH;
		} else if (!driver->add_card) {
L
Linus Torvalds 已提交
1253
			printk(KERN_ERR "kcapi: driver \"%s\" has no add card function.\n", cdef.driver);
1254 1255 1256
			retval = -EIO;
		} else
			retval = driver->add_card(driver, &cparams);
L
Linus Torvalds 已提交
1257

1258 1259
		mutex_unlock(&capi_drivers_lock);
		return retval;
L
Linus Torvalds 已提交
1260 1261 1262
	}

	default:
1263
		printk(KERN_ERR "kcapi: manufacturer command %lu unknown.\n",
1264
		       cmd);
L
Linus Torvalds 已提交
1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280
		break;

	}
	return -EINVAL;
}

EXPORT_SYMBOL(capi20_manufacturer);

/* ------------------------------------------------------------- */
/* -------- Init & Cleanup ------------------------------------- */
/* ------------------------------------------------------------- */

/*
 * init / exit functions
 */

1281 1282 1283 1284 1285
static struct notifier_block capictr_nb = {
	.notifier_call = notify_handler,
	.priority = INT_MAX,
};

L
Linus Torvalds 已提交
1286 1287
static int __init kcapi_init(void)
{
1288
	int err;
L
Linus Torvalds 已提交
1289

1290 1291 1292 1293
	kcapi_wq = alloc_workqueue("kcapi", 0, 0);
	if (!kcapi_wq)
		return -ENOMEM;

1294 1295
	register_capictr_notifier(&capictr_nb);

1296
	err = cdebug_init();
1297 1298 1299 1300 1301 1302 1303 1304
	if (err) {
		unregister_capictr_notifier(&capictr_nb);
		destroy_workqueue(kcapi_wq);
		return err;
	}

	kcapi_proc_init();
	return 0;
L
Linus Torvalds 已提交
1305 1306 1307 1308
}

static void __exit kcapi_exit(void)
{
1309
	kcapi_proc_exit();
L
Linus Torvalds 已提交
1310

1311
	unregister_capictr_notifier(&capictr_nb);
1312
	cdebug_exit();
1313
	destroy_workqueue(kcapi_wq);
L
Linus Torvalds 已提交
1314 1315 1316 1317
}

module_init(kcapi_init);
module_exit(kcapi_exit);