kcapi.c 29.4 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12
/* $Id: kcapi.c,v 1.1.2.8 2004/03/26 19:57:20 armin Exp $
 * 
 * Kernel CAPI 2.0 Module
 * 
 * Copyright 1999 by Carsten Paeth <calle@calle.de>
 * Copyright 2002 by Kai Germaschewski <kai@germaschewski.name>
 * 
 * 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.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>
L
Linus Torvalds 已提交
31 32 33
#include <asm/uaccess.h>
#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 41 42 43 44 45 46 47 48

static int showcapimsgs = 0;

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

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

49
struct capictr_event {
L
Linus Torvalds 已提交
50
	struct work_struct work;
51
	unsigned int type;
L
Linus Torvalds 已提交
52 53 54 55 56 57 58 59 60 61 62 63
	u32 controller;
};

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

static struct capi_version driver_version = {2, 0, 1, 1<<4};
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);
64
DEFINE_MUTEX(capi_drivers_lock);
L
Linus Torvalds 已提交
65

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

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

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

73 74
static BLOCKING_NOTIFIER_HEAD(ctr_notifier_list);

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

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

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

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

static inline struct capi_ctr *get_capi_ctr_by_nr(u16 contr)
{
	if (contr - 1 >= CAPI_MAXCONTR)
		return NULL;

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

101 102 103 104 105 106 107 108 109 110
static inline struct capi20_appl *__get_capi_appl_by_nr(u16 applid)
{
	lockdep_assert_held(&capi_controller_lock);

	if (applid - 1 >= CAPI_MAXAPPL)
		return NULL;

	return capi_applications[applid - 1];
}

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

J
Jan Kiszka 已提交
116
	return rcu_dereference(capi_applications[applid - 1]);
L
Linus Torvalds 已提交
117 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
}

/* -------- 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;
}

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

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

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


171
static void release_appl(struct capi_ctr *ctr, u16 applid)
L
Linus Torvalds 已提交
172 173 174
{
	DBG("applid %#x", applid);
	
175 176
	ctr->release_appl(ctr, applid);
	capi_ctr_put(ctr);
L
Linus Torvalds 已提交
177 178 179 180 181
}

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

185 186
	mutex_lock(&capi_controller_lock);

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

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

		ctr->state = CAPI_CTR_RUNNING;

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

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

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

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

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

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

	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 已提交
225 226

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

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

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

239 240
	mutex_lock(&capi_controller_lock);

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

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

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

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

258 259 260
	switch (val) {
	case CAPICTR_UP:
		notify_up(contr);
L
Linus Torvalds 已提交
261
		break;
262 263
	case CAPICTR_DOWN:
		notify_down(contr);
L
Linus Torvalds 已提交
264 265
		break;
	}
266 267 268 269 270 271 272
	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 已提交
273

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

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

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

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

294
	schedule_work(&event->work);
L
Linus Torvalds 已提交
295 296 297
	return 0;
}

298 299 300 301 302 303 304 305 306 307 308 309
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 已提交
310 311
/* -------- Receiver ------------------------------------------ */

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

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

321
	mutex_lock(&ap->recv_mtx);
L
Linus Torvalds 已提交
322 323 324 325 326 327 328 329
	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);
	}
330
	mutex_unlock(&ap->recv_mtx);
L
Linus Torvalds 已提交
331 332
}

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

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

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

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

	}

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

	return;

error:
	kfree_skb(skb);
}

EXPORT_SYMBOL(capi_ctr_handle_message);

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

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

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

EXPORT_SYMBOL(capi_ctr_ready);

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

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

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

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

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

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

EXPORT_SYMBOL(capi_ctr_suspend_output);

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

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

EXPORT_SYMBOL(capi_ctr_resume_output);

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

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

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

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

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

525 526 527 528 529 530 531 532
	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;
533
	init_waitqueue_head(&ctr->state_wait_queue);
534 535 536 537 538

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

	ncontrollers++;
539 540 541

	mutex_unlock(&capi_controller_lock);

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

EXPORT_SYMBOL(attach_capi_ctr);

549 550
/**
 * detach_capi_ctr() - unregister CAPI controller
551
 * @ctr:	controller descriptor structure.
552 553 554 555 556 557
 *
 * 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
 */

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

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

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

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

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

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

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

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

EXPORT_SYMBOL(detach_capi_ctr);

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

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

EXPORT_SYMBOL(register_capi_driver);

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

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

EXPORT_SYMBOL(unregister_capi_driver);

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

623 624 625 626 627 628 629
/**
 * 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 已提交
630 631
u16 capi20_isinstalled(void)
{
632
	u16 ret = CAPI_REGNOTINSTALLED;
L
Linus Torvalds 已提交
633
	int i;
634 635 636 637

	mutex_lock(&capi_controller_lock);

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

	mutex_unlock(&capi_controller_lock);

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

EXPORT_SYMBOL(capi20_isinstalled);

651 652 653 654 655 656 657 658 659 660 661 662
/**
 * 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 已提交
663 664 665 666 667 668 669 670 671 672
u16 capi20_register(struct capi20_appl *ap)
{
	int i;
	u16 applid;

	DBG("");

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

J
Jan Kiszka 已提交
673 674 675 676 677 678 679 680 681 682
	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 已提交
683 684 685 686 687 688

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

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

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

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

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

	return CAPI_NOERROR;
}

EXPORT_SYMBOL(capi20_register);

714 715 716 717 718 719 720 721 722 723
/**
 * 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 已提交
724 725 726 727 728 729
u16 capi20_release(struct capi20_appl *ap)
{
	int i;

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

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

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

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

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

	mutex_unlock(&capi_controller_lock);
L
Linus Torvalds 已提交
745 746 747 748 749 750 751 752 753 754 755 756 757

	flush_scheduled_work();
	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);

758 759 760 761 762 763 764 765 766
/**
 * 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 已提交
767 768
u16 capi20_put_message(struct capi20_appl *ap, struct sk_buff *skb)
{
769
	struct capi_ctr *ctr;
L
Linus Torvalds 已提交
770 771 772 773 774
	int showctl = 0;
	u8 cmd, subcmd;

	DBG("applid %#x", ap->applid);
 
775
	if (ncontrollers == 0)
L
Linus Torvalds 已提交
776 777 778 779 780 781 782
		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;
783 784 785 786 787 788

	/*
	 * 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.
	 */
789
	ctr = get_capi_ctr_by_nr(CAPIMSG_CONTROLLER(skb->data));
790 791
	if (!ctr || ctr->state != CAPI_CTR_RUNNING)
		return CAPI_REGNOTINSTALLED;
792
	if (ctr->blocked)
L
Linus Torvalds 已提交
793 794 795 796 797 798
		return CAPI_SENDQUEUEFULL;

	cmd = CAPIMSG_COMMAND(skb->data);
        subcmd = CAPIMSG_SUBCOMMAND(skb->data);

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

EXPORT_SYMBOL(capi20_put_message);

837 838 839 840 841 842 843 844 845 846
/**
 * 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 已提交
847 848
u16 capi20_get_manufacturer(u32 contr, u8 *buf)
{
849
	struct capi_ctr *ctr;
850
	u16 ret;
L
Linus Torvalds 已提交
851 852 853 854 855

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

	mutex_lock(&capi_controller_lock);

859
	ctr = get_capi_ctr_by_nr(contr);
860 861 862 863 864 865 866 867
	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 已提交
868 869 870 871
}

EXPORT_SYMBOL(capi20_get_manufacturer);

872 873 874 875 876 877 878 879 880 881
/**
 * 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 已提交
882 883
u16 capi20_get_version(u32 contr, struct capi_version *verp)
{
884
	struct capi_ctr *ctr;
885
	u16 ret;
L
Linus Torvalds 已提交
886 887 888 889 890

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

	mutex_lock(&capi_controller_lock);

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

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

EXPORT_SYMBOL(capi20_get_version);

907 908 909 910 911 912 913 914 915 916
/**
 * 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 已提交
917 918
u16 capi20_get_serial(u32 contr, u8 *serial)
{
919
	struct capi_ctr *ctr;
920
	u16 ret;
L
Linus Torvalds 已提交
921 922 923 924 925

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

	mutex_lock(&capi_controller_lock);

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

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

EXPORT_SYMBOL(capi20_get_serial);

942 943 944 945 946 947 948 949 950 951
/**
 * 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 已提交
952 953
u16 capi20_get_profile(u32 contr, struct capi_profile *profp)
{
954
	struct capi_ctr *ctr;
955
	u16 ret;
L
Linus Torvalds 已提交
956 957

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

	mutex_lock(&capi_controller_lock);

964
	ctr = get_capi_ctr_by_nr(contr);
965 966 967 968 969
	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 已提交
970

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

EXPORT_SYMBOL(capi20_get_profile);

977 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
/* 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;
}

1013
#ifdef AVMB1_COMPAT
L
Linus Torvalds 已提交
1014 1015 1016 1017 1018 1019
static int old_capi_manufacturer(unsigned int cmd, void __user *data)
{
	avmb1_loadandconfigdef ldef;
	avmb1_extcarddef cdef;
	avmb1_resetdef rdef;
	capicardparams cparams;
1020
	struct capi_ctr *ctr;
L
Linus Torvalds 已提交
1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031
	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) {
		   if ((retval = copy_from_user(&cdef, data,
					    sizeof(avmb1_carddef))))
1032
			   return -EFAULT;
L
Linus Torvalds 已提交
1033 1034 1035 1036
		   cdef.cardtype = AVM_CARDTYPE_B1;
		} else {
		   if ((retval = copy_from_user(&cdef, data,
					    sizeof(avmb1_extcarddef))))
1037
			   return -EFAULT;
L
Linus Torvalds 已提交
1038 1039 1040 1041 1042
		}
		cparams.port = cdef.port;
		cparams.irq = cdef.irq;
		cparams.cardnr = cdef.cardnr;

1043 1044
		mutex_lock(&capi_drivers_lock);

L
Linus Torvalds 已提交
1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065
                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;
		}
		if (!driver) {
			printk(KERN_ERR "kcapi: driver not loaded.\n");
1066 1067
			retval = -EIO;
		} else if (!driver->add_card) {
L
Linus Torvalds 已提交
1068
			printk(KERN_ERR "kcapi: driver has no add card function.\n");
1069 1070 1071
			retval = -EIO;
		} else
			retval = driver->add_card(driver, &cparams);
L
Linus Torvalds 已提交
1072

1073
		mutex_unlock(&capi_drivers_lock);
L
Linus Torvalds 已提交
1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089
		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;
		}
1090 1091 1092

		mutex_lock(&capi_controller_lock);

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

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

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

		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;

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

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

1136
		retval = wait_on_ctr_state(ctr, CAPI_CTR_RUNNING);
L
Linus Torvalds 已提交
1137

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

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

		retval = 0;

		mutex_lock(&capi_controller_lock);

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

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

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

1165
		ctr->reset_ctr(ctr);
L
Linus Torvalds 已提交
1166

1167
		retval = wait_on_ctr_state(ctr, CAPI_CTR_DETECTED);
L
Linus Torvalds 已提交
1168

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

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

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

	switch (cmd) {
1192
#ifdef AVMB1_COMPAT
L
Linus Torvalds 已提交
1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206
	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;

1207 1208
		mutex_lock(&capi_controller_lock);

1209
		ctr = get_capi_ctr_by_nr(fdef.contr);
1210 1211 1212 1213 1214 1215 1216 1217 1218
		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 已提交
1219

1220
		return retval;
L
Linus Torvalds 已提交
1221 1222 1223 1224 1225 1226 1227 1228 1229
	}
	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))))
1230
			return -EFAULT;
L
Linus Torvalds 已提交
1231 1232 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;
		cdef.driver[sizeof(cdef.driver)-1] = 0;

1239 1240
		mutex_lock(&capi_drivers_lock);

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

1256 1257
		mutex_unlock(&capi_drivers_lock);
		return retval;
L
Linus Torvalds 已提交
1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278
	}

	default:
		printk(KERN_ERR "kcapi: manufacturer command %d unknown.\n",
					cmd);
		break;

	}
	return -EINVAL;
}

EXPORT_SYMBOL(capi20_manufacturer);

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

/*
 * init / exit functions
 */

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

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

1288 1289
	register_capictr_notifier(&capictr_nb);

1290 1291 1292 1293
	err = cdebug_init();
	if (!err)
		kcapi_proc_init();
	return err;
L
Linus Torvalds 已提交
1294 1295 1296 1297 1298 1299 1300 1301
}

static void __exit kcapi_exit(void)
{
        kcapi_proc_exit();

	/* make sure all notifiers are finished */
	flush_scheduled_work();
1302
	cdebug_exit();
L
Linus Torvalds 已提交
1303 1304 1305 1306
}

module_init(kcapi_init);
module_exit(kcapi_exit);