config.c 49.9 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1
/* $Id: config.c,v 1.1.4.2.2.1 2001/12/09 20:18:40 kai Exp $
Linus Torvalds's avatar
Linus Torvalds committed
2
 *
Linus Torvalds's avatar
Linus Torvalds committed
3 4 5 6 7 8
 * Author       Karsten Keil
 * Copyright    by Karsten Keil      <keil@isdn4linux.de>
 *              by Kai Germaschewski <kai.germaschewski@gmx.de>
 * 
 * This software may be used and distributed according to the terms
 * of the GNU General Public License, incorporated herein by reference.
Linus Torvalds's avatar
Linus Torvalds committed
9
 *
Linus Torvalds's avatar
Linus Torvalds committed
10 11 12 13
 * For changes and modifications please read
 * ../../../Documentation/isdn/HiSax.cert
 *
 * based on the teles driver from Jan den Ouden
Linus Torvalds's avatar
Linus Torvalds committed
14 15
 *
 */
Linus Torvalds's avatar
Linus Torvalds committed
16

Linus Torvalds's avatar
Linus Torvalds committed
17 18 19 20 21 22 23 24
#include <linux/types.h>
#include <linux/stddef.h>
#include <linux/timer.h>
#include <linux/config.h>
#include <linux/init.h>
#include "hisax.h"
#include <linux/module.h>
#include <linux/kernel_stat.h>
Ingo Molnar's avatar
Ingo Molnar committed
25
#include <linux/workqueue.h>
Linus Torvalds's avatar
Linus Torvalds committed
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
#include <linux/interrupt.h>
#define HISAX_STATUS_BUFSIZE 4096
#define INCLUDE_INLINE_FUNCS

/*
 * This structure array contains one entry per card. An entry looks
 * like this:
 *
 * { type, protocol, p0, p1, p2, NULL }
 *
 * type
 *    1 Teles 16.0       p0=irq p1=membase p2=iobase
 *    2 Teles  8.0       p0=irq p1=membase
 *    3 Teles 16.3       p0=irq p1=iobase
 *    4 Creatix PNP      p0=irq p1=IO0 (ISAC)  p2=IO1 (HSCX)
 *    5 AVM A1 (Fritz)   p0=irq p1=iobase
 *    6 ELSA PC          [p0=iobase] or nothing (autodetect)
 *    7 ELSA Quickstep   p0=irq p1=iobase
 *    8 Teles PCMCIA     p0=irq p1=iobase
 *    9 ITK ix1-micro    p0=irq p1=iobase
 *   10 ELSA PCMCIA      p0=irq p1=iobase
 *   11 Eicon.Diehl Diva p0=irq p1=iobase
 *   12 Asuscom ISDNLink p0=irq p1=iobase
 *   13 Teleint          p0=irq p1=iobase
 *   14 Teles 16.3c      p0=irq p1=iobase
 *   15 Sedlbauer speed  p0=irq p1=iobase
 *   15 Sedlbauer PC/104	p0=irq p1=iobase
 *   15 Sedlbauer speed pci	no parameter
 *   16 USR Sportster internal  p0=irq  p1=iobase
 *   17 MIC card                p0=irq  p1=iobase
 *   18 ELSA Quickstep 1000PCI  no parameter
 *   19 Compaq ISDN S0 ISA card p0=irq  p1=IO0 (HSCX)  p2=IO1 (ISAC) p3=IO2
 *   20 Travers Technologies NETjet-S PCI card
 *   21 TELES PCI               no parameter
 *   22 Sedlbauer Speed Star    p0=irq p1=iobase
 *   23 reserved
 *   24 Dr Neuhaus Niccy PnP/PCI card p0=irq p1=IO0 p2=IO1 (PnP only)
 *   25 Teles S0Box             p0=irq p1=iobase (from isapnp setup)
 *   26 AVM A1 PCMCIA (Fritz)   p0=irq p1=iobase
 *   27 AVM PnP/PCI 		p0=irq p1=iobase (PCI no parameter)
 *   28 Sedlbauer Speed Fax+ 	p0=irq p1=iobase (from isapnp setup)
Linus Torvalds's avatar
Linus Torvalds committed
67 68
 *   29 Siemens I-Surf          p0=irq p1=iobase p2=memory (from isapnp setup)
 *   30 ACER P10                p0=irq p1=iobase (from isapnp setup)
Linus Torvalds's avatar
Linus Torvalds committed
69 70 71 72 73 74 75 76 77
 *   31 HST Saphir              p0=irq  p1=iobase
 *   32 Telekom A4T             none
 *   33 Scitel Quadro		p0=subcontroller (4*S0, subctrl 1...4)
 *   34	Gazel ISDN cards
 *   35 HFC 2BDS0 PCI           none
 *   36 Winbond 6692 PCI        none
 *   37 HFC 2BDS0 S+/SP         p0=irq p1=iobase
 *   38 Travers Technologies NETspider-U PCI card
 *   39 HFC 2BDS0-SP PCMCIA     p0=irq p1=iobase
78 79
 *   40 hotplug interface
 *   41 Formula-n enter:now ISDN PCI a/b   none
Linus Torvalds's avatar
Linus Torvalds committed
80 81 82 83 84 85
 *
 * protocol can be either ISDN_PTYPE_EURO or ISDN_PTYPE_1TR6 or ISDN_PTYPE_NI1
 *
 *
 */

Linus Torvalds's avatar
Linus Torvalds committed
86 87 88 89 90 91 92 93 94 95 96 97
const char *CardType[] = {
	"No Card", "Teles 16.0", "Teles 8.0", "Teles 16.3",
	"Creatix/Teles PnP", "AVM A1", "Elsa ML", "Elsa Quickstep",
	"Teles PCMCIA",	"ITK ix1-micro Rev.2", "Elsa PCMCIA",
	"Eicon.Diehl Diva", "ISDNLink",	"TeleInt", "Teles 16.3c",
	"Sedlbauer Speed Card", "USR Sportster", "ith mic Linux",
	"Elsa PCI", "Compaq ISA", "NETjet-S", "Teles PCI", 
	"Sedlbauer Speed Star (PCMCIA)", "AMD 7930", "NICCY", "S0Box",
	"AVM A1 (PCMCIA)", "AVM Fritz PnP/PCI", "Sedlbauer Speed Fax +",
	"Siemens I-Surf", "Acer P10", "HST Saphir", "Telekom A4T",
	"Scitel Quadro", "Gazel", "HFC 2BDS0 PCI", "Winbond 6692",
	"HFC 2BDS0 SX", "NETspider-U", "HFC-2BDS0-SP PCMCIA",
98
	"Hotplug", "Formula-n enter:now PCI a/b", 
Linus Torvalds's avatar
Linus Torvalds committed
99 100 101
};

void HiSax_closecard(int cardnr);
102
static spinlock_t hisax_config_lock = SPIN_LOCK_UNLOCKED;
Linus Torvalds's avatar
Linus Torvalds committed
103 104 105 106

#ifdef CONFIG_HISAX_ELSA
#define DEFAULT_CARD ISDN_CTYPE_ELSA
#define DEFAULT_CFG {0,0,0,0}
Linus Torvalds's avatar
Linus Torvalds committed
107
int elsa_init_pcmcia(void *, int, int *, int);
Linus Torvalds's avatar
Linus Torvalds committed
108
EXPORT_SYMBOL(elsa_init_pcmcia);
Linus Torvalds's avatar
Linus Torvalds committed
109
#endif
Linus Torvalds's avatar
Linus Torvalds committed
110 111 112 113 114 115 116 117 118 119 120 121 122

#ifdef CONFIG_HISAX_AVM_A1
#undef DEFAULT_CARD
#undef DEFAULT_CFG
#define DEFAULT_CARD ISDN_CTYPE_A1
#define DEFAULT_CFG {10,0x340,0,0}
#endif

#ifdef CONFIG_HISAX_AVM_A1_PCMCIA
#undef DEFAULT_CARD
#undef DEFAULT_CFG
#define DEFAULT_CARD ISDN_CTYPE_A1_PCMCIA
#define DEFAULT_CFG {11,0x170,0,0}
Linus Torvalds's avatar
Linus Torvalds committed
123
int avm_a1_init_pcmcia(void *, int, int *, int);
Linus Torvalds's avatar
Linus Torvalds committed
124
EXPORT_SYMBOL(avm_a1_init_pcmcia);
Linus Torvalds's avatar
Linus Torvalds committed
125
#endif
Linus Torvalds's avatar
Linus Torvalds committed
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 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194

#ifdef CONFIG_HISAX_FRITZPCI
#undef DEFAULT_CARD
#undef DEFAULT_CFG
#define DEFAULT_CARD ISDN_CTYPE_FRITZPCI
#define DEFAULT_CFG {0,0,0,0}
#endif

#ifdef CONFIG_HISAX_16_3
#undef DEFAULT_CARD
#undef DEFAULT_CFG
#define DEFAULT_CARD ISDN_CTYPE_16_3
#define DEFAULT_CFG {15,0x180,0,0}
#endif

#ifdef CONFIG_HISAX_S0BOX
#undef DEFAULT_CARD
#undef DEFAULT_CFG
#define DEFAULT_CARD ISDN_CTYPE_S0BOX
#define DEFAULT_CFG {7,0x378,0,0}
#endif

#ifdef CONFIG_HISAX_16_0
#undef DEFAULT_CARD
#undef DEFAULT_CFG
#define DEFAULT_CARD ISDN_CTYPE_16_0
#define DEFAULT_CFG {15,0xd0000,0xd80,0}
#endif

#ifdef CONFIG_HISAX_TELESPCI
#undef DEFAULT_CARD
#undef DEFAULT_CFG
#define DEFAULT_CARD ISDN_CTYPE_TELESPCI
#define DEFAULT_CFG {0,0,0,0}
#endif

#ifdef CONFIG_HISAX_IX1MICROR2
#undef DEFAULT_CARD
#undef DEFAULT_CFG
#define DEFAULT_CARD ISDN_CTYPE_IX1MICROR2
#define DEFAULT_CFG {5,0x390,0,0}
#endif

#ifdef CONFIG_HISAX_DIEHLDIVA
#undef DEFAULT_CARD
#undef DEFAULT_CFG
#define DEFAULT_CARD ISDN_CTYPE_DIEHLDIVA
#define DEFAULT_CFG {0,0x0,0,0}
#endif

#ifdef CONFIG_HISAX_ASUSCOM
#undef DEFAULT_CARD
#undef DEFAULT_CFG
#define DEFAULT_CARD ISDN_CTYPE_ASUSCOM
#define DEFAULT_CFG {5,0x200,0,0}
#endif

#ifdef CONFIG_HISAX_TELEINT
#undef DEFAULT_CARD
#undef DEFAULT_CFG
#define DEFAULT_CARD ISDN_CTYPE_TELEINT
#define DEFAULT_CFG {5,0x300,0,0}
#endif

#ifdef CONFIG_HISAX_SEDLBAUER
#undef DEFAULT_CARD
#undef DEFAULT_CFG
#define DEFAULT_CARD ISDN_CTYPE_SEDLBAUER
#define DEFAULT_CFG {11,0x270,0,0}
Linus Torvalds's avatar
Linus Torvalds committed
195
int sedl_init_pcmcia(void *, int, int *, int);
Linus Torvalds's avatar
Linus Torvalds committed
196
EXPORT_SYMBOL(sedl_init_pcmcia);
Linus Torvalds's avatar
Linus Torvalds committed
197
#endif
Linus Torvalds's avatar
Linus Torvalds committed
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238

#ifdef CONFIG_HISAX_SPORTSTER
#undef DEFAULT_CARD
#undef DEFAULT_CFG
#define DEFAULT_CARD ISDN_CTYPE_SPORTSTER
#define DEFAULT_CFG {7,0x268,0,0}
#endif

#ifdef CONFIG_HISAX_MIC
#undef DEFAULT_CARD
#undef DEFAULT_CFG
#define DEFAULT_CARD ISDN_CTYPE_MIC
#define DEFAULT_CFG {12,0x3e0,0,0}
#endif

#ifdef CONFIG_HISAX_NETJET
#undef DEFAULT_CARD
#undef DEFAULT_CFG
#define DEFAULT_CARD ISDN_CTYPE_NETJET_S
#define DEFAULT_CFG {0,0,0,0}
#endif

#ifdef CONFIG_HISAX_HFCS
#undef DEFAULT_CARD
#undef DEFAULT_CFG
#define DEFAULT_CARD ISDN_CTYPE_TELES3C
#define DEFAULT_CFG {5,0x500,0,0}
#endif

#ifdef CONFIG_HISAX_HFC_PCI
#undef DEFAULT_CARD
#undef DEFAULT_CFG
#define DEFAULT_CARD ISDN_CTYPE_HFC_PCI
#define DEFAULT_CFG {0,0,0,0}
#endif

#ifdef CONFIG_HISAX_HFC_SX
#undef DEFAULT_CARD
#undef DEFAULT_CFG
#define DEFAULT_CARD ISDN_CTYPE_HFC_SX
#define DEFAULT_CFG {5,0x2E0,0,0}
Linus Torvalds's avatar
Linus Torvalds committed
239
int hfc_init_pcmcia(void *, int, int *, int);
Linus Torvalds's avatar
Linus Torvalds committed
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271
EXPORT_SYMBOL(hfc_init_pcmcia);
#endif


#ifdef CONFIG_HISAX_AMD7930
#undef DEFAULT_CARD
#undef DEFAULT_CFG
#define DEFAULT_CARD ISDN_CTYPE_AMD7930
#define DEFAULT_CFG {12,0x3e0,0,0}
#endif

#ifdef CONFIG_HISAX_NICCY
#undef DEFAULT_CARD
#undef DEFAULT_CFG
#define DEFAULT_CARD ISDN_CTYPE_NICCY
#define DEFAULT_CFG {0,0x0,0,0}
#endif

#ifdef CONFIG_HISAX_ISURF
#undef DEFAULT_CARD
#undef DEFAULT_CFG
#define DEFAULT_CARD ISDN_CTYPE_ISURF
#define DEFAULT_CFG {5,0x100,0xc8000,0}
#endif

#ifdef CONFIG_HISAX_HSTSAPHIR
#undef DEFAULT_CARD
#undef DEFAULT_CFG
#define DEFAULT_CARD ISDN_CTYPE_HSTSAPHIR
#define DEFAULT_CFG {5,0x250,0,0}
#endif

Linus Torvalds's avatar
Linus Torvalds committed
272
#ifdef CONFIG_HISAX_BKM_A4T
Linus Torvalds's avatar
Linus Torvalds committed
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327
#undef DEFAULT_CARD
#undef DEFAULT_CFG
#define DEFAULT_CARD ISDN_CTYPE_BKM_A4T
#define DEFAULT_CFG {0,0x0,0,0}
#endif

#ifdef CONFIG_HISAX_SCT_QUADRO
#undef DEFAULT_CARD
#undef DEFAULT_CFG
#define DEFAULT_CARD ISDN_CTYPE_SCT_QUADRO
#define DEFAULT_CFG {1,0x0,0,0}
#endif

#ifdef CONFIG_HISAX_GAZEL
#undef DEFAULT_CARD
#undef DEFAULT_CFG
#define DEFAULT_CARD ISDN_CTYPE_GAZEL
#define DEFAULT_CFG {15,0x180,0,0}
#endif

#ifdef CONFIG_HISAX_W6692
#undef DEFAULT_CARD
#undef DEFAULT_CFG
#define DEFAULT_CARD ISDN_CTYPE_W6692
#define DEFAULT_CFG {0,0,0,0}
#endif

#ifdef CONFIG_HISAX_NETJET_U
#undef DEFAULT_CARD
#undef DEFAULT_CFG
#define DEFAULT_CARD ISDN_CTYPE_NETJET_U
#define DEFAULT_CFG {0,0,0,0}
#endif

#ifdef CONFIG_HISAX_1TR6
#define DEFAULT_PROTO ISDN_PTYPE_1TR6
#define DEFAULT_PROTO_NAME "1TR6"
#endif
#ifdef CONFIG_HISAX_NI1
#undef DEFAULT_PROTO
#define DEFAULT_PROTO ISDN_PTYPE_NI1
#undef DEFAULT_PROTO_NAME
#define DEFAULT_PROTO_NAME "NI1"
#endif
#ifdef CONFIG_HISAX_EURO
#undef DEFAULT_PROTO
#define DEFAULT_PROTO ISDN_PTYPE_EURO
#undef DEFAULT_PROTO_NAME
#define DEFAULT_PROTO_NAME "EURO"
#endif
#ifndef DEFAULT_PROTO
#define DEFAULT_PROTO ISDN_PTYPE_UNKNOWN
#define DEFAULT_PROTO_NAME "UNKNOWN"
#endif
#ifndef DEFAULT_CARD
Linus Torvalds's avatar
Linus Torvalds committed
328 329
#define DEFAULT_CARD 0
#define DEFAULT_CFG {0,0,0,0}
Linus Torvalds's avatar
Linus Torvalds committed
330 331 332 333 334 335 336 337 338 339 340 341 342
#endif

int hisax_init_pcmcia(void *, int *, struct IsdnCard *);
EXPORT_SYMBOL(hisax_init_pcmcia);
EXPORT_SYMBOL(HiSax_closecard);

#define FIRST_CARD { \
	DEFAULT_CARD, \
	DEFAULT_PROTO, \
	DEFAULT_CFG, \
	NULL, \
}

Linus Torvalds's avatar
Linus Torvalds committed
343
struct IsdnCard cards[HISAX_MAX_CARDS] = {
Linus Torvalds's avatar
Linus Torvalds committed
344 345 346
	FIRST_CARD,
};

Linus Torvalds's avatar
Linus Torvalds committed
347 348
#define HISAX_IDSIZE (HISAX_MAX_CARDS*8)
static char HiSaxID[HISAX_IDSIZE] __devinitdata = { 0, };
Linus Torvalds's avatar
Linus Torvalds committed
349 350 351 352

char *HiSax_id __devinitdata = HiSaxID;
#ifdef MODULE
/* Variables for insmod */
Linus Torvalds's avatar
Linus Torvalds committed
353 354 355
static int type[HISAX_MAX_CARDS] __devinitdata = { 0, };
static int protocol[HISAX_MAX_CARDS] __devinitdata = { 0, };
static int io[HISAX_MAX_CARDS] __devinitdata = { 0, };
Linus Torvalds's avatar
Linus Torvalds committed
356 357 358 359 360 361 362 363 364
#undef IO0_IO1
#ifdef CONFIG_HISAX_16_3
#define IO0_IO1
#endif
#ifdef CONFIG_HISAX_NICCY
#undef IO0_IO1
#define IO0_IO1
#endif
#ifdef IO0_IO1
Linus Torvalds's avatar
Linus Torvalds committed
365 366
static int io0[HISAX_MAX_CARDS] __devinitdata = { 0, };
static int io1[HISAX_MAX_CARDS] __devinitdata = { 0, };
Linus Torvalds's avatar
Linus Torvalds committed
367
#endif
Linus Torvalds's avatar
Linus Torvalds committed
368 369
static int irq[HISAX_MAX_CARDS] __devinitdata = { 0, };
static int mem[HISAX_MAX_CARDS] __devinitdata = { 0, };
Linus Torvalds's avatar
Linus Torvalds committed
370 371
static char *id __devinitdata = HiSaxID;

Linus Torvalds's avatar
Linus Torvalds committed
372 373
#define PARM_PARA "1-" __MODULE_STRING(HISAX_MAX_CARDS) "i"

Linus Torvalds's avatar
Linus Torvalds committed
374
MODULE_DESCRIPTION("ISDN4Linux: Driver for passive ISDN cards");
Linus Torvalds's avatar
Linus Torvalds committed
375
MODULE_AUTHOR("Karsten Keil");
Linus Torvalds's avatar
Linus Torvalds committed
376
MODULE_LICENSE("GPL");
Linus Torvalds's avatar
Linus Torvalds committed
377 378 379 380 381
MODULE_PARM(type, PARM_PARA);
MODULE_PARM(protocol, PARM_PARA);
MODULE_PARM(io, PARM_PARA);
MODULE_PARM(irq, PARM_PARA);
MODULE_PARM(mem, PARM_PARA);
Linus Torvalds's avatar
Linus Torvalds committed
382 383
MODULE_PARM(id, "s");
#ifdef IO0_IO1
Linus Torvalds's avatar
Linus Torvalds committed
384 385
MODULE_PARM(io0, PARM_PARA);
MODULE_PARM(io1, PARM_PARA);
Linus Torvalds's avatar
Linus Torvalds committed
386
#endif
Linus Torvalds's avatar
Linus Torvalds committed
387 388 389 390 391 392 393 394 395 396
#endif /* MODULE */

int nrcards;

extern char *l1_revision;
extern char *l2_revision;
extern char *l3_revision;
extern char *lli_revision;
extern char *tei_revision;

Linus Torvalds's avatar
Linus Torvalds committed
397
char *HiSax_getrev(const char *revision)
Linus Torvalds's avatar
Linus Torvalds committed
398 399 400 401 402 403 404 405 406 407 408 409 410
{
	char *rev;
	char *p;

	if ((p = strchr(revision, ':'))) {
		rev = p + 2;
		p = strchr(rev, '$');
		*--p = 0;
	} else
		rev = "???";
	return rev;
}

Linus Torvalds's avatar
Linus Torvalds committed
411
void __init HiSaxVersion(void)
Linus Torvalds's avatar
Linus Torvalds committed
412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429
{
	char tmp[64];

	printk(KERN_INFO "HiSax: Linux Driver for passive ISDN cards\n");
#ifdef MODULE
	printk(KERN_INFO "HiSax: Version 3.5 (module)\n");
#else
	printk(KERN_INFO "HiSax: Version 3.5 (kernel)\n");
#endif
	strcpy(tmp, l1_revision);
	printk(KERN_INFO "HiSax: Layer1 Revision %s\n", HiSax_getrev(tmp));
	strcpy(tmp, l2_revision);
	printk(KERN_INFO "HiSax: Layer2 Revision %s\n", HiSax_getrev(tmp));
	strcpy(tmp, tei_revision);
	printk(KERN_INFO "HiSax: TeiMgr Revision %s\n", HiSax_getrev(tmp));
	strcpy(tmp, l3_revision);
	printk(KERN_INFO "HiSax: Layer3 Revision %s\n", HiSax_getrev(tmp));
	strcpy(tmp, lli_revision);
Linus Torvalds's avatar
Linus Torvalds committed
430 431
	printk(KERN_INFO "HiSax: LinkLayer Revision %s\n",
	       HiSax_getrev(tmp));
Linus Torvalds's avatar
Linus Torvalds committed
432 433 434 435 436
	certification_check(1);
}

#ifndef MODULE
#define MAX_ARG	(HISAX_MAX_CARDS*5)
Linus Torvalds's avatar
Linus Torvalds committed
437
static int __init HiSax_setup(char *line)
Linus Torvalds's avatar
Linus Torvalds committed
438 439 440 441 442 443 444
{
	int i, j, argc;
	int ints[MAX_ARG + 1];
	char *str;

	str = get_options(line, MAX_ARG, ints);
	argc = ints[0];
Linus Torvalds's avatar
Linus Torvalds committed
445
	printk(KERN_DEBUG "HiSax_setup: argc(%d) str(%s)\n", argc, str);
Linus Torvalds's avatar
Linus Torvalds committed
446 447 448
	i = 0;
	j = 1;
	while (argc && (i < HISAX_MAX_CARDS)) {
Linus Torvalds's avatar
Linus Torvalds committed
449
		cards[i].protocol = DEFAULT_PROTO;
Linus Torvalds's avatar
Linus Torvalds committed
450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476
		if (argc) {
			cards[i].typ = ints[j];
			j++;
			argc--;
		}
		if (argc) {
			cards[i].protocol = ints[j];
			j++;
			argc--;
		}
		if (argc) {
			cards[i].para[0] = ints[j];
			j++;
			argc--;
		}
		if (argc) {
			cards[i].para[1] = ints[j];
			j++;
			argc--;
		}
		if (argc) {
			cards[i].para[2] = ints[j];
			j++;
			argc--;
		}
		i++;
	}
Linus Torvalds's avatar
Linus Torvalds committed
477 478 479 480 481 482
  	if (str && *str) {
		if (strlen(str) < HISAX_IDSIZE)
			strcpy(HiSaxID, str);
		else
			printk(KERN_WARNING "HiSax: ID too long!");
	} else
Linus Torvalds's avatar
Linus Torvalds committed
483
		strcpy(HiSaxID, "HiSax");
Linus Torvalds's avatar
Linus Torvalds committed
484 485

	HiSax_id = HiSaxID;
Linus Torvalds's avatar
Linus Torvalds committed
486
	return 1;
Linus Torvalds's avatar
Linus Torvalds committed
487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528
}

__setup("hisax=", HiSax_setup);
#endif /* MODULES */

#if CARD_TELES0
extern int setup_teles0(struct IsdnCard *card);
#endif

#if CARD_TELES3
extern int setup_teles3(struct IsdnCard *card);
#endif

#if CARD_S0BOX
extern int setup_s0box(struct IsdnCard *card);
#endif

#if CARD_TELESPCI
extern int setup_telespci(struct IsdnCard *card);
#endif

#if CARD_AVM_A1
extern int setup_avm_a1(struct IsdnCard *card);
#endif

#if CARD_AVM_A1_PCMCIA
extern int setup_avm_a1_pcmcia(struct IsdnCard *card);
#endif

#if CARD_FRITZPCI
extern int setup_avm_pcipnp(struct IsdnCard *card);
#endif

#if CARD_ELSA
extern int setup_elsa(struct IsdnCard *card);
#endif

#if CARD_IX1MICROR2
extern int setup_ix1micro(struct IsdnCard *card);
#endif

#if CARD_DIEHLDIVA
Linus Torvalds's avatar
Linus Torvalds committed
529
extern int setup_diva(struct IsdnCard *card);
Linus Torvalds's avatar
Linus Torvalds committed
530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607
#endif

#if CARD_ASUSCOM
extern int setup_asuscom(struct IsdnCard *card);
#endif

#if CARD_TELEINT
extern int setup_TeleInt(struct IsdnCard *card);
#endif

#if CARD_SEDLBAUER
extern int setup_sedlbauer(struct IsdnCard *card);
#endif

#if CARD_SPORTSTER
extern int setup_sportster(struct IsdnCard *card);
#endif

#if CARD_MIC
extern int setup_mic(struct IsdnCard *card);
#endif

#if CARD_NETJET_S
extern int setup_netjet_s(struct IsdnCard *card);
#endif

#if CARD_HFCS
extern int setup_hfcs(struct IsdnCard *card);
#endif

#if CARD_HFC_PCI
extern int setup_hfcpci(struct IsdnCard *card);
#endif

#if CARD_HFC_SX
extern int setup_hfcsx(struct IsdnCard *card);
#endif

#if CARD_AMD7930
extern int setup_amd7930(struct IsdnCard *card);
#endif

#if CARD_NICCY
extern int setup_niccy(struct IsdnCard *card);
#endif

#if CARD_ISURF
extern int setup_isurf(struct IsdnCard *card);
#endif

#if CARD_HSTSAPHIR
extern int setup_saphir(struct IsdnCard *card);
#endif

#if CARD_TESTEMU
extern int setup_testemu(struct IsdnCard *card);
#endif

#if CARD_BKM_A4T
extern int setup_bkm_a4t(struct IsdnCard *card);
#endif

#if CARD_SCT_QUADRO
extern int setup_sct_quadro(struct IsdnCard *card);
#endif

#if CARD_GAZEL
extern int setup_gazel(struct IsdnCard *card);
#endif

#if CARD_W6692
extern int setup_w6692(struct IsdnCard *card);
#endif

#if CARD_NETJET_U
extern int setup_netjet_u(struct IsdnCard *card);
#endif

608 609 610 611
#if CARD_FN_ENTERNOW_PCI
extern int setup_enternow_pci(struct IsdnCard *card);
#endif

Linus Torvalds's avatar
Linus Torvalds committed
612 613 614
/*
 * Find card with given driverId
 */
Linus Torvalds's avatar
Linus Torvalds committed
615
static inline struct IsdnCardState *hisax_findcard(int driverid)
Linus Torvalds's avatar
Linus Torvalds committed
616 617 618 619 620 621
{
	int i;

	for (i = 0; i < nrcards; i++)
		if (cards[i].cs)
			if (cards[i].cs->myid == driverid)
Linus Torvalds's avatar
Linus Torvalds committed
622 623
				return cards[i].cs;
	return NULL;
Linus Torvalds's avatar
Linus Torvalds committed
624 625 626 627 628
}

/*
 * Find card with given card number
 */
Linus Torvalds's avatar
Linus Torvalds committed
629
struct IsdnCardState *hisax_get_card(int cardnr)
Linus Torvalds's avatar
Linus Torvalds committed
630
{
Linus Torvalds's avatar
Linus Torvalds committed
631 632 633 634
	if ((cardnr <= nrcards) && (cardnr > 0))
		if (cards[cardnr - 1].cs)
			return cards[cardnr - 1].cs;
	return NULL;
Linus Torvalds's avatar
Linus Torvalds committed
635 636
}

637
int HiSax_readstatus(u8 * buf, int len, int user, int id, int channel)
Linus Torvalds's avatar
Linus Torvalds committed
638
{
Linus Torvalds's avatar
Linus Torvalds committed
639
	int count, cnt;
640
	u8 *p = buf;
Linus Torvalds's avatar
Linus Torvalds committed
641 642 643 644
	struct IsdnCardState *cs = hisax_findcard(id);

	if (cs) {
		if (len > HISAX_STATUS_BUFSIZE) {
Linus Torvalds's avatar
Linus Torvalds committed
645 646 647
			printk(KERN_WARNING
			       "HiSax: status overflow readstat %d/%d\n",
			       len, HISAX_STATUS_BUFSIZE);
Linus Torvalds's avatar
Linus Torvalds committed
648
		}
Linus Torvalds's avatar
Linus Torvalds committed
649
		count = cs->status_end - cs->status_read + 1;
Linus Torvalds's avatar
Linus Torvalds committed
650 651
		if (count >= len)
			count = len;
Arnaldo Carvalho de Melo's avatar
Arnaldo Carvalho de Melo committed
652 653 654 655
		if (user) {
			if (copy_to_user(p, cs->status_read, count))
				return -EFAULT;
		} else
Linus Torvalds's avatar
Linus Torvalds committed
656 657 658 659 660 661 662 663 664 665 666
			memcpy(p, cs->status_read, count);
		cs->status_read += count;
		if (cs->status_read > cs->status_end)
			cs->status_read = cs->status_buf;
		p += count;
		count = len - count;
		while (count) {
			if (count > HISAX_STATUS_BUFSIZE)
				cnt = HISAX_STATUS_BUFSIZE;
			else
				cnt = count;
Arnaldo Carvalho de Melo's avatar
Arnaldo Carvalho de Melo committed
667 668 669 670
			if (user) {
				if (copy_to_user(p, cs->status_read, cnt))
					return -EFAULT;
			} else
Linus Torvalds's avatar
Linus Torvalds committed
671 672 673 674 675 676 677 678
				memcpy(p, cs->status_read, cnt);
			p += cnt;
			cs->status_read += cnt % HISAX_STATUS_BUFSIZE;
			count -= cnt;
		}
		return len;
	} else {
		printk(KERN_ERR
Linus Torvalds's avatar
Linus Torvalds committed
679
		       "HiSax: if_readstatus called with invalid driverId!\n");
Linus Torvalds's avatar
Linus Torvalds committed
680 681 682 683
		return -ENODEV;
	}
}

Linus Torvalds's avatar
Linus Torvalds committed
684
int jiftime(char *s, long mark)
Linus Torvalds's avatar
Linus Torvalds committed
685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701
{
	s += 8;

	*s-- = '\0';
	*s-- = mark % 10 + '0';
	mark /= 10;
	*s-- = mark % 10 + '0';
	mark /= 10;
	*s-- = '.';
	*s-- = mark % 10 + '0';
	mark /= 10;
	*s-- = mark % 6 + '0';
	mark /= 6;
	*s-- = ':';
	*s-- = mark % 10 + '0';
	mark /= 10;
	*s-- = mark % 10 + '0';
Linus Torvalds's avatar
Linus Torvalds committed
702
	return 8;
Linus Torvalds's avatar
Linus Torvalds committed
703 704
}

705
static u8 tmpbuf[HISAX_STATUS_BUFSIZE];
Linus Torvalds's avatar
Linus Torvalds committed
706

Linus Torvalds's avatar
Linus Torvalds committed
707 708
void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt,
		      va_list args)
Linus Torvalds's avatar
Linus Torvalds committed
709
{
Linus Torvalds's avatar
Linus Torvalds committed
710
	/* if head == NULL the fmt contains the full info */
Linus Torvalds's avatar
Linus Torvalds committed
711

712
	unsigned long flags;
Linus Torvalds's avatar
Linus Torvalds committed
713
	int count, i;
714
	u8 *p;
Linus Torvalds's avatar
Linus Torvalds committed
715 716 717
	isdn_ctrl ic;
	int len;

718
	spin_lock_irqsave(&hisax_config_lock, flags);
Linus Torvalds's avatar
Linus Torvalds committed
719 720 721 722 723 724 725 726 727 728 729 730 731 732
	p = tmpbuf;
	if (head) {
		p += jiftime(p, jiffies);
		p += sprintf(p, " %s", head);
		p += vsprintf(p, fmt, args);
		*p++ = '\n';
		*p = 0;
		len = p - tmpbuf;
		p = tmpbuf;
	} else {
		p = fmt;
		len = strlen(fmt);
	}
	if (!cs) {
Linus Torvalds's avatar
Linus Torvalds committed
733 734
		printk(KERN_WARNING "HiSax: No CardStatus for message %s",
		       p);
735
		spin_unlock_irqrestore(&hisax_config_lock, flags);
Linus Torvalds's avatar
Linus Torvalds committed
736 737 738 739
		return;
	}
	if (len > HISAX_STATUS_BUFSIZE) {
		printk(KERN_WARNING "HiSax: status overflow %d/%d\n",
Linus Torvalds's avatar
Linus Torvalds committed
740
		       len, HISAX_STATUS_BUFSIZE);
741
		spin_unlock_irqrestore(&hisax_config_lock, flags);
Linus Torvalds's avatar
Linus Torvalds committed
742 743 744
		return;
	}
	count = len;
Linus Torvalds's avatar
Linus Torvalds committed
745
	i = cs->status_end - cs->status_write + 1;
Linus Torvalds's avatar
Linus Torvalds committed
746 747 748 749 750 751 752 753 754 755 756 757 758
	if (i >= len)
		i = len;
	len -= i;
	memcpy(cs->status_write, p, i);
	cs->status_write += i;
	if (cs->status_write > cs->status_end)
		cs->status_write = cs->status_buf;
	p += i;
	if (len) {
		memcpy(cs->status_write, p, len);
		cs->status_write += len;
	}
#ifdef KERNELSTACK_DEBUG
Linus Torvalds's avatar
Linus Torvalds committed
759
	i = (ulong) & len - current->kernel_stack_page;
Linus Torvalds's avatar
Linus Torvalds committed
760 761 762 763 764 765 766 767 768 769
	sprintf(tmpbuf, "kstack %s %lx use %ld\n", current->comm,
		current->kernel_stack_page, i);
	len = strlen(tmpbuf);
	for (p = tmpbuf, i = len; i > 0; i--, p++) {
		*cs->status_write++ = *p;
		if (cs->status_write > cs->status_end)
			cs->status_write = cs->status_buf;
		count++;
	}
#endif
770
	spin_unlock_irqrestore(&hisax_config_lock, flags);
Linus Torvalds's avatar
Linus Torvalds committed
771 772 773 774 775 776 777 778
	if (count) {
		ic.command = ISDN_STAT_STAVAIL;
		ic.driver = cs->myid;
		ic.arg = count;
		cs->iif.statcallb(&ic);
	}
}

Linus Torvalds's avatar
Linus Torvalds committed
779
void HiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, ...)
Linus Torvalds's avatar
Linus Torvalds committed
780 781 782 783 784 785 786 787
{
	va_list args;

	va_start(args, fmt);
	VHiSax_putstatus(cs, head, fmt, args);
	va_end(args);
}

Linus Torvalds's avatar
Linus Torvalds committed
788
int ll_run(struct IsdnCardState *cs, int addfeatures)
Linus Torvalds's avatar
Linus Torvalds committed
789 790 791 792 793 794 795 796 797 798
{
	isdn_ctrl ic;

	ic.driver = cs->myid;
	ic.command = ISDN_STAT_RUN;
	cs->iif.features |= addfeatures;
	cs->iif.statcallb(&ic);
	return 0;
}

Linus Torvalds's avatar
Linus Torvalds committed
799
void ll_stop(struct IsdnCardState *cs)
Linus Torvalds's avatar
Linus Torvalds committed
800 801 802 803 804 805
{
	isdn_ctrl ic;

	ic.command = ISDN_STAT_STOP;
	ic.driver = cs->myid;
	cs->iif.statcallb(&ic);
Linus Torvalds's avatar
Linus Torvalds committed
806
	//      CallcFreeChan(cs);
Linus Torvalds's avatar
Linus Torvalds committed
807 808
}

Linus Torvalds's avatar
Linus Torvalds committed
809
static void ll_unload(struct IsdnCardState *cs)
Linus Torvalds's avatar
Linus Torvalds committed
810 811 812 813 814 815 816 817 818 819 820 821 822 823
{
	isdn_ctrl ic;

	ic.command = ISDN_STAT_UNLOAD;
	ic.driver = cs->myid;
	cs->iif.statcallb(&ic);
	if (cs->status_buf)
		kfree(cs->status_buf);
	cs->status_read = NULL;
	cs->status_write = NULL;
	cs->status_end = NULL;
	kfree(cs->dlog);
}

Linus Torvalds's avatar
Linus Torvalds committed
824
static void closecard(int cardnr)
Linus Torvalds's avatar
Linus Torvalds committed
825 826 827
{
	struct IsdnCardState *csta = cards[cardnr].cs;

828 829 830
	if (csta->bc_l1_ops->close) {
		csta->bc_l1_ops->close(csta->bcs + 1);
		csta->bc_l1_ops->close(csta->bcs);
Linus Torvalds's avatar
Linus Torvalds committed
831 832
	}

Linus Torvalds's avatar
Linus Torvalds committed
833 834
	skb_queue_purge(&csta->rq);
	skb_queue_purge(&csta->sq);
Linus Torvalds's avatar
Linus Torvalds committed
835 836 837 838 839 840 841 842 843 844 845
	if (csta->rcvbuf) {
		kfree(csta->rcvbuf);
		csta->rcvbuf = NULL;
	}
	if (csta->tx_skb) {
		dev_kfree_skb(csta->tx_skb);
		csta->tx_skb = NULL;
	}
	if (csta->DC_Close != NULL) {
		csta->DC_Close(csta);
	}
Linus Torvalds's avatar
Linus Torvalds committed
846 847 848
	if (csta->cardmsg)
		csta->cardmsg(csta, CARD_RELEASE, NULL);
	if (csta->dbusytimer.function != NULL) // FIXME?
Linus Torvalds's avatar
Linus Torvalds committed
849 850 851 852
		del_timer(&csta->dbusytimer);
	ll_unload(csta);
}

Linus Torvalds's avatar
Linus Torvalds committed
853
static int __devinit init_card(struct IsdnCardState *cs)
Linus Torvalds's avatar
Linus Torvalds committed
854 855 856
{
	int irq_cnt, cnt = 3;

857
	cs->card_ops->init(cs);
858

Linus Torvalds's avatar
Linus Torvalds committed
859
	irq_cnt = kstat_irqs(cs->irq);
Linus Torvalds's avatar
Linus Torvalds committed
860 861
	printk(KERN_INFO "%s: IRQ %d count %d\n", CardType[cs->typ],
	       cs->irq, irq_cnt);
Linus Torvalds's avatar
Linus Torvalds committed
862 863
	if (request_irq(cs->irq, cs->irq_func, cs->irq_flags, "HiSax", cs)) {
		printk(KERN_WARNING "HiSax: couldn't get interrupt %d\n",
Linus Torvalds's avatar
Linus Torvalds committed
864 865
		       cs->irq);
		return 1;
Linus Torvalds's avatar
Linus Torvalds committed
866 867
	}
	while (cnt) {
868
		cs->card_ops->init(cs);
Linus Torvalds's avatar
Linus Torvalds committed
869 870
		set_current_state(TASK_UNINTERRUPTIBLE);
		/* Timeout 10ms */
Linus Torvalds's avatar
Linus Torvalds committed
871 872 873
		schedule_timeout((10 * HZ) / 1000);
		printk(KERN_INFO "%s: IRQ %d count %d\n",
		       CardType[cs->typ], cs->irq, kstat_irqs(cs->irq));
Linus Torvalds's avatar
Linus Torvalds committed
874 875 876 877 878 879
		if (kstat_irqs(cs->irq) == irq_cnt) {
			printk(KERN_WARNING
			       "%s: IRQ(%d) getting no interrupts during init %d\n",
			       CardType[cs->typ], cs->irq, 4 - cnt);
			if (cnt == 1) {
				free_irq(cs->irq, cs);
Linus Torvalds's avatar
Linus Torvalds committed
880
				return 2;
Linus Torvalds's avatar
Linus Torvalds committed
881 882 883 884 885 886
			} else {
				cs->cardmsg(cs, CARD_RESET, NULL);
				cnt--;
			}
		} else {
			cs->cardmsg(cs, CARD_TEST, NULL);
Linus Torvalds's avatar
Linus Torvalds committed
887
			return 0;
Linus Torvalds's avatar
Linus Torvalds committed
888 889
		}
	}
Linus Torvalds's avatar
Linus Torvalds committed
890
	return 3;
Linus Torvalds's avatar
Linus Torvalds committed
891 892
}

Linus Torvalds's avatar
Linus Torvalds committed
893
static int __devinit checkcard(int cardnr, char *id, int *busy_flag)
Linus Torvalds's avatar
Linus Torvalds committed
894 895 896 897 898
{
	int ret = 0;
	struct IsdnCard *card = cards + cardnr;
	struct IsdnCardState *cs;

Linus Torvalds's avatar
Linus Torvalds committed
899 900
	cs = kmalloc(sizeof(struct IsdnCardState), GFP_ATOMIC);
	if (!cs) {
Linus Torvalds's avatar
Linus Torvalds committed
901 902 903
		printk(KERN_WARNING
		       "HiSax: No memory for IsdnCardState(card %d)\n",
		       cardnr + 1);
Linus Torvalds's avatar
Linus Torvalds committed
904
		goto out;
Linus Torvalds's avatar
Linus Torvalds committed
905 906 907
	}
	memset(cs, 0, sizeof(struct IsdnCardState));
	card->cs = cs;
Linus Torvalds's avatar
Linus Torvalds committed
908 909
	cs->chanlimit = 2;	/* maximum B-channel number */
	cs->logecho = 0;	/* No echo logging */
Linus Torvalds's avatar
Linus Torvalds committed
910 911 912 913 914 915 916 917 918 919 920 921 922
	cs->cardnr = cardnr;
	cs->debug = L1_DEB_WARN;
	cs->HW_Flags = 0;
	cs->busy_flag = busy_flag;
	cs->irq_flags = I4L_IRQ_FLAG;
#if TEI_PER_CARD
	if (card->protocol == ISDN_PTYPE_NI1)
		test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags);
#else
	test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags);
#endif
	cs->protocol = card->protocol;

Linus Torvalds's avatar
Linus Torvalds committed
923 924
	if (card->typ <= 0 || card->typ > ISDN_CTYPE_COUNT) {
		printk(KERN_WARNING
Linus Torvalds's avatar
Linus Torvalds committed
925
		       "HiSax: Card Type %d out of range\n", card->typ);
Linus Torvalds's avatar
Linus Torvalds committed
926 927 928 929
		goto outf_cs;
	}
	if (!(cs->dlog = kmalloc(MAX_DLOG_SPACE, GFP_ATOMIC))) {
		printk(KERN_WARNING
Linus Torvalds's avatar
Linus Torvalds committed
930
		       "HiSax: No memory for dlog(card %d)\n", cardnr + 1);
Linus Torvalds's avatar
Linus Torvalds committed
931 932 933 934 935 936 937 938 939 940 941 942 943
		goto outf_cs;
	}
	if (!(cs->status_buf = kmalloc(HISAX_STATUS_BUFSIZE, GFP_ATOMIC))) {
		printk(KERN_WARNING
		       "HiSax: No memory for status_buf(card %d)\n",
		       cardnr + 1);
		goto outf_dlog;
	}
	cs->stlist = NULL;
	cs->status_read = cs->status_buf;
	cs->status_write = cs->status_buf;
	cs->status_end = cs->status_buf + HISAX_STATUS_BUFSIZE - 1;
	cs->typ = card->typ;
944
	spin_lock_init(&cs->lock);
Kai Germaschewski's avatar
Kai Germaschewski committed
945
	SET_MODULE_OWNER(&cs->iif);
Linus Torvalds's avatar
Linus Torvalds committed
946 947 948 949 950 951 952 953 954 955
	strcpy(cs->iif.id, id);
	cs->iif.channels = 2;
	cs->iif.maxbufsize = MAX_DATA_SIZE;
	cs->iif.hl_hdrlen = MAX_HEADER_LEN;
	cs->iif.features =
		ISDN_FEATURE_L2_X75I |
		ISDN_FEATURE_L2_HDLC |
		ISDN_FEATURE_L2_HDLC_56K |
		ISDN_FEATURE_L2_TRANS |
		ISDN_FEATURE_L3_TRANS |
Linus Torvalds's avatar
Linus Torvalds committed
956
#ifdef	CONFIG_HISAX_1TR6
Linus Torvalds's avatar
Linus Torvalds committed
957
		ISDN_FEATURE_P_1TR6 |
Linus Torvalds's avatar
Linus Torvalds committed
958 959
#endif
#ifdef	CONFIG_HISAX_EURO
Linus Torvalds's avatar
Linus Torvalds committed
960
		ISDN_FEATURE_P_EURO |
Linus Torvalds's avatar
Linus Torvalds committed
961 962
#endif
#ifdef	CONFIG_HISAX_NI1
Linus Torvalds's avatar
Linus Torvalds committed
963 964 965
		ISDN_FEATURE_P_NI1 |
#endif
		0;
Linus Torvalds's avatar
Linus Torvalds committed
966

Linus Torvalds's avatar
Linus Torvalds committed
967 968 969 970 971 972 973 974 975 976 977 978 979 980
	cs->iif.command = HiSax_command;
	cs->iif.writecmd = NULL;
	cs->iif.writebuf_skb = HiSax_writebuf_skb;
	cs->iif.readstat = HiSax_readstatus;
	register_isdn(&cs->iif);
	cs->myid = cs->iif.channels;
	printk(KERN_INFO
	       "HiSax: Card %d Protocol %s Id=%s (%d)\n", cardnr + 1,
	       (card->protocol == ISDN_PTYPE_1TR6) ? "1TR6" :
	       (card->protocol == ISDN_PTYPE_EURO) ? "EDSS1" :
	       (card->protocol == ISDN_PTYPE_LEASED) ? "LEASED" :
	       (card->protocol == ISDN_PTYPE_NI1) ? "NI1" :
	       "NONE", cs->iif.id, cs->myid);
	switch (card->typ) {
Linus Torvalds's avatar
Linus Torvalds committed
981
#if CARD_TELES0
Linus Torvalds's avatar
Linus Torvalds committed
982 983 984 985
	case ISDN_CTYPE_16_0:
	case ISDN_CTYPE_8_0:
		ret = setup_teles0(card);
		break;
Linus Torvalds's avatar
Linus Torvalds committed
986 987
#endif
#if CARD_TELES3
Linus Torvalds's avatar
Linus Torvalds committed
988 989 990 991 992 993
	case ISDN_CTYPE_16_3:
	case ISDN_CTYPE_PNP:
	case ISDN_CTYPE_TELESPCMCIA:
	case ISDN_CTYPE_COMPAQ_ISA:
		ret = setup_teles3(card);
		break;
Linus Torvalds's avatar
Linus Torvalds committed
994 995
#endif
#if CARD_S0BOX
Linus Torvalds's avatar
Linus Torvalds committed
996 997 998
	case ISDN_CTYPE_S0BOX:
		ret = setup_s0box(card);
		break;
Linus Torvalds's avatar
Linus Torvalds committed
999 1000
#endif
#if CARD_TELESPCI
Linus Torvalds's avatar
Linus Torvalds committed
1001 1002 1003
	case ISDN_CTYPE_TELESPCI:
		ret = setup_telespci(card);
		break;
Linus Torvalds's avatar
Linus Torvalds committed
1004 1005
#endif
#if CARD_AVM_A1
Linus Torvalds's avatar
Linus Torvalds committed
1006 1007 1008
	case ISDN_CTYPE_A1:
		ret = setup_avm_a1(card);
		break;
Linus Torvalds's avatar
Linus Torvalds committed
1009 1010
#endif
#if CARD_AVM_A1_PCMCIA
Linus Torvalds's avatar
Linus Torvalds committed
1011 1012 1013
	case ISDN_CTYPE_A1_PCMCIA:
		ret = setup_avm_a1_pcmcia(card);
		break;
Linus Torvalds's avatar
Linus Torvalds committed
1014 1015
#endif
#if CARD_FRITZPCI
Linus Torvalds's avatar
Linus Torvalds committed
1016 1017 1018
	case ISDN_CTYPE_FRITZPCI:
		ret = setup_avm_pcipnp(card);
		break;
Linus Torvalds's avatar
Linus Torvalds committed
1019 1020
#endif
#if CARD_ELSA
Linus Torvalds's avatar
Linus Torvalds committed
1021 1022 1023 1024 1025 1026
	case ISDN_CTYPE_ELSA:
	case ISDN_CTYPE_ELSA_PNP:
	case ISDN_CTYPE_ELSA_PCMCIA:
	case ISDN_CTYPE_ELSA_PCI:
		ret = setup_elsa(card);
		break;
Linus Torvalds's avatar
Linus Torvalds committed
1027 1028
#endif
#if CARD_IX1MICROR2
Linus Torvalds's avatar
Linus Torvalds committed
1029 1030 1031
	case ISDN_CTYPE_IX1MICROR2:
		ret = setup_ix1micro(card);
		break;
Linus Torvalds's avatar
Linus Torvalds committed
1032 1033
#endif
#if CARD_DIEHLDIVA
Linus Torvalds's avatar
Linus Torvalds committed
1034 1035 1036
	case ISDN_CTYPE_DIEHLDIVA:
		ret = setup_diva(card);
		break;
Linus Torvalds's avatar
Linus Torvalds committed
1037 1038
#endif
#if CARD_ASUSCOM
Linus Torvalds's avatar
Linus Torvalds committed
1039 1040 1041
	case ISDN_CTYPE_ASUSCOM:
		ret = setup_asuscom(card);
		break;
Linus Torvalds's avatar
Linus Torvalds committed
1042 1043
#endif
#if CARD_TELEINT
Linus Torvalds's avatar
Linus Torvalds committed
1044 1045 1046
	case ISDN_CTYPE_TELEINT:
		ret = setup_TeleInt(card);
		break;
Linus Torvalds's avatar
Linus Torvalds committed
1047 1048
#endif
#if CARD_SEDLBAUER
Linus Torvalds's avatar
Linus Torvalds committed
1049 1050 1051 1052 1053
	case ISDN_CTYPE_SEDLBAUER:
	case ISDN_CTYPE_SEDLBAUER_PCMCIA:
	case ISDN_CTYPE_SEDLBAUER_FAX:
		ret = setup_sedlbauer(card);
		break;
Linus Torvalds's avatar
Linus Torvalds committed
1054 1055
#endif
#if CARD_SPORTSTER
Linus Torvalds's avatar
Linus Torvalds committed
1056 1057 1058
	case ISDN_CTYPE_SPORTSTER:
		ret = setup_sportster(card);
		break;
Linus Torvalds's avatar
Linus Torvalds committed
1059 1060
#endif
#if CARD_MIC
Linus Torvalds's avatar
Linus Torvalds committed
1061 1062 1063
	case ISDN_CTYPE_MIC:
		ret = setup_mic(card);
		break;
Linus Torvalds's avatar
Linus Torvalds committed
1064 1065
#endif
#if CARD_NETJET_S
Linus Torvalds's avatar
Linus Torvalds committed
1066 1067 1068
	case ISDN_CTYPE_NETJET_S:
		ret = setup_netjet_s(card);
		break;
Linus Torvalds's avatar
Linus Torvalds committed
1069 1070
#endif
#if CARD_HFCS
Linus Torvalds's avatar
Linus Torvalds committed
1071 1072 1073 1074
	case ISDN_CTYPE_TELES3C:
	case ISDN_CTYPE_ACERP10:
		ret = setup_hfcs(card);
		break;
Linus Torvalds's avatar
Linus Torvalds committed
1075 1076
#endif
#if CARD_HFC_PCI
Linus Torvalds's avatar
Linus Torvalds committed
1077
	case ISDN_CTYPE_HFC_PCI:
Linus Torvalds's avatar
Linus Torvalds committed
1078 1079
		ret = setup_hfcpci(card);
		break;
Linus Torvalds's avatar
Linus Torvalds committed
1080 1081
#endif
#if CARD_HFC_SX
Linus Torvalds's avatar
Linus Torvalds committed
1082
	case ISDN_CTYPE_HFC_SX:
Linus Torvalds's avatar
Linus Torvalds committed
1083 1084
		ret = setup_hfcsx(card);
		break;
Linus Torvalds's avatar
Linus Torvalds committed
1085 1086
#endif
#if CARD_NICCY
Linus Torvalds's avatar
Linus Torvalds committed
1087 1088 1089
	case ISDN_CTYPE_NICCY:
		ret = setup_niccy(card);
		break;
Linus Torvalds's avatar
Linus Torvalds committed
1090 1091
#endif
#if CARD_AMD7930
Linus Torvalds's avatar
Linus Torvalds committed
1092 1093 1094
	case ISDN_CTYPE_AMD7930:
		ret = setup_amd7930(card);
		break;
Linus Torvalds's avatar
Linus Torvalds committed
1095 1096
#endif
#if CARD_ISURF
Linus Torvalds's avatar
Linus Torvalds committed
1097 1098 1099
	case ISDN_CTYPE_ISURF:
		ret = setup_isurf(card);
		break;
Linus Torvalds's avatar
Linus Torvalds committed
1100 1101
#endif
#if CARD_HSTSAPHIR
Linus Torvalds's avatar
Linus Torvalds committed
1102 1103 1104
	case ISDN_CTYPE_HSTSAPHIR:
		ret = setup_saphir(card);
		break;
Linus Torvalds's avatar
Linus Torvalds committed
1105 1106
#endif
#if CARD_TESTEMU
Linus Torvalds's avatar
Linus Torvalds committed
1107 1108 1109
	case ISDN_CTYPE_TESTEMU:
		ret = setup_testemu(card);
		break;
Linus Torvalds's avatar
Linus Torvalds committed
1110
#endif
Linus Torvalds's avatar
Linus Torvalds committed
1111
#if	CARD_BKM_A4T
Linus Torvalds's avatar
Linus Torvalds committed
1112 1113 1114
	case ISDN_CTYPE_BKM_A4T:
		ret = setup_bkm_a4t(card);
		break;
Linus Torvalds's avatar
Linus Torvalds committed
1115 1116
#endif
#if	CARD_SCT_QUADRO
Linus Torvalds's avatar
Linus Torvalds committed
1117 1118 1119
	case ISDN_CTYPE_SCT_QUADRO:
		ret = setup_sct_quadro(card);
		break;
Linus Torvalds's avatar
Linus Torvalds committed
1120 1121
#endif
#if CARD_GAZEL
Linus Torvalds's avatar
Linus Torvalds committed
1122 1123 1124
	case ISDN_CTYPE_GAZEL:
		ret = setup_gazel(card);
		break;
Linus Torvalds's avatar
Linus Torvalds committed
1125 1126
#endif
#if CARD_W6692
Linus Torvalds's avatar
Linus Torvalds committed
1127 1128 1129
	case ISDN_CTYPE_W6692:
		ret = setup_w6692(card);
		break;
Linus Torvalds's avatar
Linus Torvalds committed
1130 1131
#endif
#if CARD_NETJET_U
Linus Torvalds's avatar
Linus Torvalds committed
1132 1133 1134
	case ISDN_CTYPE_NETJET_U:
		ret = setup_netjet_u(card);
		break;
1135 1136 1137 1138 1139
#endif
#if CARD_FN_ENTERNOW_PCI
	case ISDN_CTYPE_ENTERNOW:
		ret = setup_enternow_pci(card);
		break;
Linus Torvalds's avatar
Linus Torvalds committed
1140
#endif
Linus Torvalds's avatar
Linus Torvalds committed
1141 1142 1143
	case ISDN_CTYPE_DYNAMIC:
		ret = 2;
		break;
Linus Torvalds's avatar
Linus Torvalds committed
1144
	default:
Linus Torvalds's avatar
Linus Torvalds committed
1145
		printk(KERN_WARNING
Linus Torvalds's avatar
Linus Torvalds committed
1146 1147 1148 1149
		       "HiSax: Support for %s Card not selected\n",
		       CardType[card->typ]);
		ll_unload(cs);
		goto outf_cs;
Linus Torvalds's avatar
Linus Torvalds committed
1150 1151 1152
	}
	if (!ret) {
		ll_unload(cs);
Linus Torvalds's avatar
Linus Torvalds committed
1153
		goto outf_cs;
Linus Torvalds's avatar
Linus Torvalds committed
1154 1155
	}
	if (!(cs->rcvbuf = kmalloc(MAX_DFRAME_LEN_L1, GFP_ATOMIC))) {
Linus Torvalds's avatar
Linus Torvalds committed
1156
		printk(KERN_WARNING "HiSax: No memory for isac rcvbuf\n");
Linus Torvalds's avatar
Linus Torvalds committed
1157 1158
		ll_unload(cs);
		goto outf_cs;
Linus Torvalds's avatar
Linus Torvalds committed
1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169
	}
	cs->rcvidx = 0;
	cs->tx_skb = NULL;
	cs->tx_cnt = 0;
	cs->event = 0;

	skb_queue_head_init(&cs->rq);
	skb_queue_head_init(&cs->sq);

	init_bcstate(cs, 0);
	init_bcstate(cs, 1);
Linus Torvalds's avatar
Linus Torvalds committed
1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180

	/* init_card only handles interrupts which are not */
	/* used here for the loadable driver */
	switch (card->typ) {
	case ISDN_CTYPE_DYNAMIC:
		ret = 0;
		break;
	default:
		ret = init_card(cs);
		break;
	}
Linus Torvalds's avatar
Linus Torvalds committed
1181 1182
	if (ret) {
		closecard(cardnr);
Linus Torvalds's avatar
Linus Torvalds committed
1183 1184
		ret = 0;
		goto outf_cs;
Linus Torvalds's avatar
Linus Torvalds committed
1185 1186
	}
	init_tei(cs, cs->protocol);
Linus Torvalds's avatar
Linus Torvalds committed
1187 1188 1189
	ret = CallcNewChan(cs);
	if (ret) {
		closecard(cardnr);
Linus Torvalds's avatar
Linus Torvalds committed
1190 1191
		ret = 0;
		goto outf_cs;
Linus Torvalds's avatar
Linus Torvalds committed
1192
	}
Linus Torvalds's avatar
Linus Torvalds committed
1193 1194 1195
	/* ISAR needs firmware download first */
	if (!test_bit(HW_ISAR, &cs->HW_Flags))
		ll_run(cs, 0);
Linus Torvalds's avatar
Linus Torvalds committed
1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206

	ret = 1;
	goto out;

 outf_dlog:
	kfree(cs->dlog);
 outf_cs:
	kfree(cs);
	card->cs = NULL;
 out:
	return ret;
Linus Torvalds's avatar
Linus Torvalds committed
1207 1208
}

Linus Torvalds's avatar
Linus Torvalds committed
1209
void __devinit HiSax_shiftcards(int idx)
Linus Torvalds's avatar
Linus Torvalds committed
1210 1211 1212 1213 1214 1215 1216
{
	int i;

	for (i = idx; i < (HISAX_MAX_CARDS - 1); i++)
		memcpy(&cards[i], &cards[i + 1], sizeof(cards[i]));
}

Linus Torvalds's avatar
Linus Torvalds committed
1217
int __devinit HiSax_inithardware(int *busy_flag)
Linus Torvalds's avatar
Linus Torvalds committed
1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250
{
	int foundcards = 0;
	int i = 0;
	int t = ',';
	int flg = 0;
	char *id;
	char *next_id = HiSax_id;
	char ids[20];

	if (strchr(HiSax_id, ','))
		t = ',';
	else if (strchr(HiSax_id, '%'))
		t = '%';

	while (i < nrcards) {
		if (cards[i].typ < 1)
			break;
		id = next_id;
		if ((next_id = strchr(id, t))) {
			*next_id++ = 0;
			strcpy(ids, id);
			flg = i + 1;
		} else {
			next_id = id;
			if (flg >= i)
				strcpy(ids, id);
			else
				sprintf(ids, "%s%d", id, i);
		}
		if (checkcard(i, ids, busy_flag)) {
			foundcards++;
			i++;
		} else {
Linus Torvalds's avatar
Linus Torvalds committed
1251 1252
			printk(KERN_WARNING
			       "HiSax: Card %s not installed !\n",
Linus Torvalds's avatar
Linus Torvalds committed
1253 1254 1255 1256 1257 1258 1259 1260
			       CardType[cards[i].typ]);
			HiSax_shiftcards(i);
			nrcards--;
		}
	}
	return foundcards;
}

Linus Torvalds's avatar
Linus Torvalds committed
1261
void HiSax_closecard(int cardnr)
Linus Torvalds's avatar
Linus Torvalds committed
1262
{
Linus Torvalds's avatar
Linus Torvalds committed
1263
	int i, last = nrcards - 1;
Linus Torvalds's avatar
Linus Torvalds committed
1264

Linus Torvalds's avatar
Linus Torvalds committed
1265
	if (cardnr > last)
Linus Torvalds's avatar
Linus Torvalds committed
1266 1267 1268 1269 1270
		return;
	if (cards[cardnr].cs) {
		ll_stop(cards[cardnr].cs);
		release_tei(cards[cardnr].cs);
		CallcFreeChan(cards[cardnr].cs);
Linus Torvalds's avatar
Linus Torvalds committed
1271

Linus Torvalds's avatar
Linus Torvalds committed
1272 1273 1274 1275 1276 1277 1278
		closecard(cardnr);
		if (cards[cardnr].cs->irq)
			free_irq(cards[cardnr].cs->irq, cards[cardnr].cs);
		kfree((void *) cards[cardnr].cs);
		cards[cardnr].cs = NULL;
	}
	i = cardnr;
Linus Torvalds's avatar
Linus Torvalds committed
1279 1280
	while (i <= last) {
		cards[i] = cards[i + 1];
Linus Torvalds's avatar
Linus Torvalds committed
1281 1282 1283 1284 1285
		i++;
	}
	nrcards--;
}

Linus Torvalds's avatar
Linus Torvalds committed
1286
void HiSax_reportcard(int cardnr, int sel)
Linus Torvalds's avatar
Linus Torvalds committed
1287 1288 1289 1290 1291 1292 1293
{
	struct IsdnCardState *cs = cards[cardnr].cs;

	printk(KERN_DEBUG "HiSax: reportcard No %d\n", cardnr + 1);
	printk(KERN_DEBUG "HiSax: Type %s\n", CardType[cs->typ]);
	printk(KERN_DEBUG "HiSax: debuglevel %x\n", cs->debug);
	printk(KERN_DEBUG "HiSax: HiSax_reportcard address 0x%lX\n",
Linus Torvalds's avatar
Linus Torvalds committed
1294
	       (ulong) & HiSax_reportcard);
Linus Torvalds's avatar
Linus Torvalds committed
1295 1296
	printk(KERN_DEBUG "HiSax: cs 0x%lX\n", (ulong) cs);
	printk(KERN_DEBUG "HiSax: HW_Flags %lx bc0 flg %lx bc1 flg %lx\n",
Linus Torvalds's avatar
Linus Torvalds committed
1297
	       cs->HW_Flags, cs->bcs[0].Flag, cs->bcs[1].Flag);
Linus Torvalds's avatar
Linus Torvalds committed
1298
	printk(KERN_DEBUG "HiSax: bcs 0 mode %d ch%d\n",
Linus Torvalds's avatar
Linus Torvalds committed
1299
	       cs->bcs[0].mode, cs->bcs[0].channel);
Linus Torvalds's avatar
Linus Torvalds committed
1300
	printk(KERN_DEBUG "HiSax: bcs 1 mode %d ch%d\n",
Linus Torvalds's avatar
Linus Torvalds committed
1301
	       cs->bcs[1].mode, cs->bcs[1].channel);
Linus Torvalds's avatar
Linus Torvalds committed
1302 1303
#ifdef ERROR_STATISTIC
	printk(KERN_DEBUG "HiSax: dc errors(rx,crc,tx) %d,%d,%d\n",
Linus Torvalds's avatar
Linus Torvalds committed
1304 1305 1306 1307 1308 1309 1310 1311 1312
	       cs->err_rx, cs->err_crc, cs->err_tx);
	printk(KERN_DEBUG
	       "HiSax: bc0 errors(inv,rdo,crc,tx) %d,%d,%d,%d\n",
	       cs->bcs[0].err_inv, cs->bcs[0].err_rdo, cs->bcs[0].err_crc,
	       cs->bcs[0].err_tx);
	printk(KERN_DEBUG
	       "HiSax: bc1 errors(inv,rdo,crc,tx) %d,%d,%d,%d\n",
	       cs->bcs[1].err_inv, cs->bcs[1].err_rdo, cs->bcs[1].err_crc,
	       cs->bcs[1].err_tx);
Linus Torvalds's avatar
Linus Torvalds committed
1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328
	if (sel == 99) {
		cs->err_rx  = 0;
		cs->err_crc = 0;
		cs->err_tx  = 0;
		cs->bcs[0].err_inv = 0;
		cs->bcs[0].err_rdo = 0;
		cs->bcs[0].err_crc = 0;
		cs->bcs[0].err_tx  = 0;
		cs->bcs[1].err_inv = 0;
		cs->bcs[1].err_rdo = 0;
		cs->bcs[1].err_crc = 0;
		cs->bcs[1].err_tx  = 0;
	}
#endif
}

Linus Torvalds's avatar
Linus Torvalds committed
1329
static int __init HiSax_init(void)
Linus Torvalds's avatar
Linus Torvalds committed
1330
{
Linus Torvalds's avatar
Linus Torvalds committed
1331
	int i, retval;
Linus Torvalds's avatar
Linus Torvalds committed
1332
#ifdef MODULE
Linus Torvalds's avatar
Linus Torvalds committed
1333
	int j;
Linus Torvalds's avatar
Linus Torvalds committed
1334
	int nzproto = 0;
Linus Torvalds's avatar
Linus Torvalds committed
1335
#endif
Linus Torvalds's avatar
Linus Torvalds committed
1336 1337

	HiSaxVersion();
Linus Torvalds's avatar
Linus Torvalds committed
1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352
	retval = CallcNew();
	if (retval)
		goto out;
	retval = Isdnl3New();
	if (retval)
		goto out_callc;
	retval = Isdnl2New();
	if (retval)
		goto out_isdnl3;
	retval = TeiNew();
	if (retval)
		goto out_isdnl2;
	retval = Isdnl1New();
	if (retval)
		goto out_tei;
Linus Torvalds's avatar
Linus Torvalds committed
1353 1354 1355

#ifdef MODULE
	if (!type[0]) {
Linus Torvalds's avatar
Linus Torvalds committed
1356
		/* We 'll register drivers later, but init basic functions */
Linus Torvalds's avatar
Linus Torvalds committed
1357 1358
		for (i = 0; i < HISAX_MAX_CARDS; i++)
			cards[i].typ = 0;
Linus Torvalds's avatar
Linus Torvalds committed
1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394
		return 0;
	}
#ifdef CONFIG_HISAX_ELSA
	if (type[0] == ISDN_CTYPE_ELSA_PCMCIA) {
		/* we have exported  and return in this case */
		return 0;
	}
#endif
#ifdef CONFIG_HISAX_SEDLBAUER
	if (type[0] == ISDN_CTYPE_SEDLBAUER_PCMCIA) {
		/* we have to export  and return in this case */
		return 0;
	}
#endif
#ifdef CONFIG_HISAX_AVM_A1_PCMCIA
	if (type[0] == ISDN_CTYPE_A1_PCMCIA) {
		/* we have to export  and return in this case */
		return 0;
	}
#endif
#ifdef CONFIG_HISAX_HFC_SX
	if (type[0] == ISDN_CTYPE_HFC_SP_PCMCIA) {
		/* we have to export  and return in this case */
		return 0;
	}
#endif
#endif
	nrcards = 0;
#ifdef MODULE
	if (id)			/* If id= string used */
		HiSax_id = id;
	for (i = j = 0; j < HISAX_MAX_CARDS; i++) {
		cards[j].typ = type[i];
		if (protocol[i]) {
			cards[j].protocol = protocol[i];
			nzproto++;
Linus Torvalds's avatar
Linus Torvalds committed
1395 1396
		} else {
			cards[j].protocol = DEFAULT_PROTO;
Linus Torvalds's avatar
Linus Torvalds committed
1397 1398
		}
		switch (type[i]) {
Linus Torvalds's avatar
Linus Torvalds committed
1399 1400 1401 1402 1403
		case ISDN_CTYPE_16_0:
			cards[j].para[0] = irq[i];
			cards[j].para[1] = mem[i];
			cards[j].para[2] = io[i];
			break;
Linus Torvalds's avatar
Linus Torvalds committed
1404

Linus Torvalds's avatar
Linus Torvalds committed
1405 1406 1407 1408
		case ISDN_CTYPE_8_0:
			cards[j].para[0] = irq[i];
			cards[j].para[1] = mem[i];
			break;
Linus Torvalds's avatar
Linus Torvalds committed
1409 1410

#ifdef IO0_IO1
Linus Torvalds's avatar
Linus Torvalds committed
1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469
		case ISDN_CTYPE_PNP:
		case ISDN_CTYPE_NICCY:
			cards[j].para[0] = irq[i];
			cards[j].para[1] = io0[i];
			cards[j].para[2] = io1[i];
			break;
		case ISDN_CTYPE_COMPAQ_ISA:
			cards[j].para[0] = irq[i];
			cards[j].para[1] = io0[i];
			cards[j].para[2] = io1[i];
			cards[j].para[3] = io[i];
			break;
#endif
		case ISDN_CTYPE_ELSA:
		case ISDN_CTYPE_HFC_PCI:
			cards[j].para[0] = io[i];
			break;
		case ISDN_CTYPE_16_3:
		case ISDN_CTYPE_TELESPCMCIA:
		case ISDN_CTYPE_A1:
		case ISDN_CTYPE_A1_PCMCIA:
		case ISDN_CTYPE_ELSA_PNP:
		case ISDN_CTYPE_ELSA_PCMCIA:
		case ISDN_CTYPE_IX1MICROR2:
		case ISDN_CTYPE_DIEHLDIVA:
		case ISDN_CTYPE_ASUSCOM:
		case ISDN_CTYPE_TELEINT:
		case ISDN_CTYPE_SEDLBAUER:
		case ISDN_CTYPE_SEDLBAUER_PCMCIA:
		case ISDN_CTYPE_SEDLBAUER_FAX:
		case ISDN_CTYPE_SPORTSTER:
		case ISDN_CTYPE_MIC:
		case ISDN_CTYPE_TELES3C:
		case ISDN_CTYPE_ACERP10:
		case ISDN_CTYPE_S0BOX:
		case ISDN_CTYPE_FRITZPCI:
		case ISDN_CTYPE_HSTSAPHIR:
		case ISDN_CTYPE_GAZEL:
		case ISDN_CTYPE_HFC_SX:
		case ISDN_CTYPE_HFC_SP_PCMCIA:
			cards[j].para[0] = irq[i];
			cards[j].para[1] = io[i];
			break;
		case ISDN_CTYPE_ISURF:
			cards[j].para[0] = irq[i];
			cards[j].para[1] = io[i];
			cards[j].para[2] = mem[i];
			break;
		case ISDN_CTYPE_ELSA_PCI:
		case ISDN_CTYPE_NETJET_S:
		case ISDN_CTYPE_AMD7930:
		case ISDN_CTYPE_TELESPCI:
		case ISDN_CTYPE_W6692:
		case ISDN_CTYPE_NETJET_U:
			break;
		case ISDN_CTYPE_BKM_A4T:
			break;
		case ISDN_CTYPE_SCT_QUADRO:
			if (irq[i]) {
Linus Torvalds's avatar
Linus Torvalds committed
1470
				cards[j].para[0] = irq[i];
Linus Torvalds's avatar
Linus Torvalds committed
1471 1472 1473
			} else {
				/* QUADRO is a 4 BRI card */
				cards[j++].para[0] = 1;
Linus Torvalds's avatar
Linus Torvalds committed
1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489
				/* we need to check if further cards can be added */
				if (j < HISAX_MAX_CARDS) {
					cards[j].typ = ISDN_CTYPE_SCT_QUADRO;
					cards[j].protocol = protocol[i];
					cards[j++].para[0] = 2;
				}
				if (j < HISAX_MAX_CARDS) {
					cards[j].typ = ISDN_CTYPE_SCT_QUADRO;
					cards[j].protocol = protocol[i];
					cards[j++].para[0] = 3;
				}
				if (j < HISAX_MAX_CARDS) {
					cards[j].typ = ISDN_CTYPE_SCT_QUADRO;
					cards[j].protocol = protocol[i];
					cards[j].para[0] = 4;
				}
Linus Torvalds's avatar
Linus Torvalds committed
1490 1491
			}
			break;
Linus Torvalds's avatar
Linus Torvalds committed
1492 1493 1494 1495
		}
		j++;
	}
	if (!nzproto) {
Linus Torvalds's avatar
Linus Torvalds committed
1496 1497 1498 1499
		printk(KERN_WARNING
		       "HiSax: Warning - no protocol specified\n");
		printk(KERN_WARNING "HiSax: using protocol %s\n",
		       DEFAULT_PROTO_NAME);
Linus Torvalds's avatar
Linus Torvalds committed
1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511
	}
#endif
	if (!HiSax_id)
		HiSax_id = HiSaxID;
	if (!HiSaxID[0])
		strcpy(HiSaxID, "HiSax");
	for (i = 0; i < HISAX_MAX_CARDS; i++)
		if (cards[i].typ > 0)
			nrcards++;
	printk(KERN_DEBUG "HiSax: Total %d card%s defined\n",
	       nrcards, (nrcards > 1) ? "s" : "");

Linus Torvalds's avatar
Linus Torvalds committed
1512
	/* Install only, if at least one card found */
Dave Jones's avatar
Dave Jones committed
1513 1514
	if (!HiSax_inithardware(NULL))
		return -ENODEV;
Linus Torvalds's avatar
Linus Torvalds committed
1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526
	return 0;

 out_tei:
	TeiFree();
 out_isdnl2:
	Isdnl2Free();
 out_isdnl3:
	Isdnl3Free();
 out_callc:
	CallcFree();
 out:
	return retval;
Linus Torvalds's avatar
Linus Torvalds committed
1527 1528
}

Linus Torvalds's avatar
Linus Torvalds committed
1529
static void __exit HiSax_exit(void)
Linus Torvalds's avatar
Linus Torvalds committed
1530
{
Linus Torvalds's avatar
Linus Torvalds committed
1531
	int cardnr = nrcards - 1;
Linus Torvalds's avatar
Linus Torvalds committed
1532

Linus Torvalds's avatar
Linus Torvalds committed
1533
	while (cardnr >= 0)
Linus Torvalds's avatar
Linus Torvalds committed
1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551
		HiSax_closecard(cardnr--);
	Isdnl1Free();
	TeiFree();
	Isdnl2Free();
	Isdnl3Free();
	CallcFree();
	printk(KERN_INFO "HiSax module removed\n");
}

#ifdef CONFIG_HISAX_ELSA
int elsa_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot)
{
#ifdef MODULE
	int i;

	nrcards = 0;
	/* Initialize all structs, even though we only accept
	   two pcmcia cards
Linus Torvalds's avatar
Linus Torvalds committed
1552
	*/
Linus Torvalds's avatar
Linus Torvalds committed
1553 1554 1555 1556 1557 1558
	for (i = 0; i < HISAX_MAX_CARDS; i++) {
		cards[i].para[0] = irq[i];
		cards[i].para[1] = io[i];
		cards[i].typ = type[i];
		if (protocol[i]) {
			cards[i].protocol = protocol[i];
Linus Torvalds's avatar
Linus Torvalds committed
1559 1560
		} else {
			cards[i].protocol = DEFAULT_PROTO;
Linus Torvalds's avatar
Linus Torvalds committed
1561 1562 1563
		}
	}
	cards[0].para[0] = pcm_irq;
Linus Torvalds's avatar
Linus Torvalds committed
1564
	cards[0].para[1] = (int) pcm_iob;
Linus Torvalds's avatar
Linus Torvalds committed
1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577
	cards[0].protocol = prot;
	cards[0].typ = ISDN_CTYPE_ELSA_PCMCIA;

	if (!HiSax_id)
		HiSax_id = HiSaxID;
	if (!HiSaxID[0])
		strcpy(HiSaxID, "HiSax");
	for (i = 0; i < HISAX_MAX_CARDS; i++)
		if (cards[i].typ > 0)
			nrcards++;
	printk(KERN_DEBUG "HiSax: Total %d card%s defined\n",
	       nrcards, (nrcards > 1) ? "s" : "");

Dave Jones's avatar
Dave Jones committed
1578 1579
	if (!HiSax_inithardware(busy_flag))
		return -ENODEV;
Linus Torvalds's avatar
Linus Torvalds committed
1580 1581
	printk(KERN_NOTICE "HiSax: module installed\n");
#endif
Linus Torvalds's avatar
Linus Torvalds committed
1582
	return 0;
Linus Torvalds's avatar
Linus Torvalds committed
1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594
}
#endif

#ifdef CONFIG_HISAX_HFC_SX
int hfc_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot)
{
#ifdef MODULE
	int i;

	nrcards = 0;
	/* Initialize all structs, even though we only accept
	   two pcmcia cards
Linus Torvalds's avatar
Linus Torvalds committed
1595
	*/
Linus Torvalds's avatar
Linus Torvalds committed
1596 1597 1598 1599 1600 1601
	for (i = 0; i < HISAX_MAX_CARDS; i++) {
		cards[i].para[0] = irq[i];
		cards[i].para[1] = io[i];
		cards[i].typ = type[i];
		if (protocol[i]) {
			cards[i].protocol = protocol[i];
Linus Torvalds's avatar
Linus Torvalds committed
1602 1603
		} else {
			cards[i].protocol = DEFAULT_PROTO;
Linus Torvalds's avatar
Linus Torvalds committed
1604 1605 1606
		}
	}
	cards[0].para[0] = pcm_irq;
Linus Torvalds's avatar
Linus Torvalds committed
1607
	cards[0].para[1] = (int) pcm_iob;
Linus Torvalds's avatar
Linus Torvalds committed
1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620
	cards[0].protocol = prot;
	cards[0].typ = ISDN_CTYPE_HFC_SP_PCMCIA;

	if (!HiSax_id)
		HiSax_id = HiSaxID;
	if (!HiSaxID[0])
		strcpy(HiSaxID, "HiSax");
	for (i = 0; i < HISAX_MAX_CARDS; i++)
		if (cards[i].typ > 0)
			nrcards++;
	printk(KERN_DEBUG "HiSax: Total %d card%s defined\n",
	       nrcards, (nrcards > 1) ? "s" : "");

Dave Jones's avatar
Dave Jones committed
1621 1622
	if (!HiSax_inithardware(busy_flag))
		return -ENODEV;
Linus Torvalds's avatar
Linus Torvalds committed
1623 1624
	printk(KERN_NOTICE "HiSax: module installed\n");
#endif
Linus Torvalds's avatar
Linus Torvalds committed
1625
	return 0;
Linus Torvalds's avatar
Linus Torvalds committed
1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637
}
#endif

#ifdef CONFIG_HISAX_SEDLBAUER
int sedl_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot)
{
#ifdef MODULE
	int i;

	nrcards = 0;
	/* Initialize all structs, even though we only accept
	   two pcmcia cards
Linus Torvalds's avatar
Linus Torvalds committed
1638
	*/
Linus Torvalds's avatar
Linus Torvalds committed
1639 1640 1641 1642 1643 1644
	for (i = 0; i < HISAX_MAX_CARDS; i++) {
		cards[i].para[0] = irq[i];
		cards[i].para[1] = io[i];
		cards[i].typ = type[i];
		if (protocol[i]) {
			cards[i].protocol = protocol[i];
Linus Torvalds's avatar
Linus Torvalds committed
1645 1646
		} else {
			cards[i].protocol = DEFAULT_PROTO;
Linus Torvalds's avatar
Linus Torvalds committed
1647 1648 1649
		}
	}
	cards[0].para[0] = pcm_irq;
Linus Torvalds's avatar
Linus Torvalds committed
1650
	cards[0].para[1] = (int) pcm_iob;
Linus Torvalds's avatar
Linus Torvalds committed
1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663
	cards[0].protocol = prot;
	cards[0].typ = ISDN_CTYPE_SEDLBAUER_PCMCIA;

	if (!HiSax_id)
		HiSax_id = HiSaxID;
	if (!HiSaxID[0])
		strcpy(HiSaxID, "HiSax");
	for (i = 0; i < HISAX_MAX_CARDS; i++)
		if (cards[i].typ > 0)
			nrcards++;
	printk(KERN_DEBUG "HiSax: Total %d card%s defined\n",
	       nrcards, (nrcards > 1) ? "s" : "");

Dave Jones's avatar
Dave Jones committed
1664 1665
	if (!HiSax_inithardware(busy_flag))
		return -ENODEV;
Linus Torvalds's avatar
Linus Torvalds committed
1666 1667
	printk(KERN_NOTICE "HiSax: module installed\n");
#endif
Linus Torvalds's avatar
Linus Torvalds committed
1668
	return 0;
Linus Torvalds's avatar
Linus Torvalds committed
1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680
}
#endif

#ifdef CONFIG_HISAX_AVM_A1_PCMCIA
int avm_a1_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot)
{
#ifdef MODULE
	int i;

	nrcards = 0;
	/* Initialize all structs, even though we only accept
	   two pcmcia cards
Linus Torvalds's avatar
Linus Torvalds committed
1681
	*/
Linus Torvalds's avatar
Linus Torvalds committed
1682 1683 1684 1685 1686 1687
	for (i = 0; i < HISAX_MAX_CARDS; i++) {
		cards[i].para[0] = irq[i];
		cards[i].para[1] = io[i];
		cards[i].typ = type[i];
		if (protocol[i]) {
			cards[i].protocol = protocol[i];
Linus Torvalds's avatar
Linus Torvalds committed
1688 1689
		} else {
			cards[i].protocol = DEFAULT_PROTO;
Linus Torvalds's avatar
Linus Torvalds committed
1690 1691 1692
		}
	}
	cards[0].para[0] = pcm_irq;
Linus Torvalds's avatar
Linus Torvalds committed
1693
	cards[0].para[1] = (int) pcm_iob;
Linus Torvalds's avatar
Linus Torvalds committed
1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706
	cards[0].protocol = prot;
	cards[0].typ = ISDN_CTYPE_A1_PCMCIA;

	if (!HiSax_id)
		HiSax_id = HiSaxID;
	if (!HiSaxID[0])
		strcpy(HiSaxID, "HiSax");
	for (i = 0; i < HISAX_MAX_CARDS; i++)
		if (cards[i].typ > 0)
			nrcards++;
	printk(KERN_DEBUG "HiSax: Total %d card%s defined\n",
	       nrcards, (nrcards > 1) ? "s" : "");

Dave Jones's avatar
Dave Jones committed
1707 1708
	if (!HiSax_inithardware(busy_flag))
		return -ENODEV;
Linus Torvalds's avatar
Linus Torvalds committed
1709 1710
	printk(KERN_NOTICE "HiSax: module installed\n");
#endif
Linus Torvalds's avatar
Linus Torvalds committed
1711
	return 0;
Linus Torvalds's avatar
Linus Torvalds committed
1712 1713 1714
}
#endif

Linus Torvalds's avatar
Linus Torvalds committed
1715 1716
int __devinit hisax_init_pcmcia(void *pcm_iob, int *busy_flag,
				struct IsdnCard *card)
Linus Torvalds's avatar
Linus Torvalds committed
1717
{
1718
	u8 ids[16];
Linus Torvalds's avatar
Linus Torvalds committed
1719 1720 1721 1722 1723 1724 1725 1726
	int ret = -1;

	cards[nrcards] = *card;
	if (nrcards)
		sprintf(ids, "HiSax%d", nrcards);
	else
		sprintf(ids, "HiSax");
	if (!checkcard(nrcards, ids, busy_flag)) {
Linus Torvalds's avatar
Linus Torvalds committed
1727
		return -1;
Linus Torvalds's avatar
Linus Torvalds committed
1728 1729 1730
	}
	ret = nrcards;
	nrcards++;
Linus Torvalds's avatar
Linus Torvalds committed
1731
	return ret;
Linus Torvalds's avatar
Linus Torvalds committed
1732 1733
}

Linus Torvalds's avatar
Linus Torvalds committed
1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745
#include "hisax_if.h"

EXPORT_SYMBOL(hisax_register);
EXPORT_SYMBOL(hisax_unregister);

static void hisax_d_l1l2(struct hisax_if *ifc, int pr, void *arg);
static void hisax_b_l1l2(struct hisax_if *ifc, int pr, void *arg);
static void hisax_d_l2l1(struct PStack *st, int pr, void *arg);
static void hisax_b_l2l1(struct PStack *st, int pr, void *arg);
static int hisax_cardmsg(struct IsdnCardState *cs, int mt, void *arg);
static int hisax_bc_setstack(struct PStack *st, struct BCState *bcs);
static void hisax_bc_close(struct BCState *bcs);
1746
static void hisax_bh(void *data);
Linus Torvalds's avatar
Linus Torvalds committed
1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777
static void EChannel_proc_rcv(struct hisax_d_if *d_if);

int hisax_register(struct hisax_d_if *hisax_d_if, struct hisax_b_if *b_if[],
		   char *name, int protocol)
{
	int i, retval;
	char id[20];
	struct IsdnCardState *cs;

	for (i = 0; i < HISAX_MAX_CARDS; i++) {
		if (!cards[i].typ)
			break;
	}

	if (i >= HISAX_MAX_CARDS)
		return -EBUSY;

	cards[i].typ = ISDN_CTYPE_DYNAMIC;
	cards[i].protocol = protocol;
	sprintf(id, "%s%d", name, i);
	nrcards++;
	retval = checkcard(i, id, 0);
	if (retval == 0) { // yuck
		cards[i].typ = 0;
		nrcards--;
		return retval;
	}
	cs = cards[i].cs;
	hisax_d_if->cs = cs;
	cs->hw.hisax_d_if = hisax_d_if;
	cs->cardmsg = hisax_cardmsg;
Kai Germaschewski's avatar
Kai Germaschewski committed
1778
	cs->iif.owner = hisax_d_if->owner; // FIXME should be done before registering
1779
	INIT_WORK(&cs->work, hisax_bh, cs);
Linus Torvalds's avatar
Linus Torvalds committed
1780
	cs->channel[0].d_st->l1.l2l1 = hisax_d_l2l1;
1781 1782
	cs->bc_l1_ops->open = hisax_bc_setstack;
	cs->bc_l1_ops->close = hisax_bc_close;
Linus Torvalds's avatar
Linus Torvalds committed
1783

1784
	for (i = 0; i < 2; i++) {
Linus Torvalds's avatar
Linus Torvalds committed
1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804
		b_if[i]->ifc.l1l2 = hisax_b_l1l2;

		hisax_d_if->b_if[i] = b_if[i];
	}
	hisax_d_if->ifc.l1l2 = hisax_d_l1l2;
	skb_queue_head_init(&hisax_d_if->erq);
	clear_bit(0, &hisax_d_if->ph_state);
	
	return 0;
}

void hisax_unregister(struct hisax_d_if *hisax_d_if)
{
	cards[hisax_d_if->cs->cardnr].typ = 0;
	HiSax_closecard(hisax_d_if->cs->cardnr);
	skb_queue_purge(&hisax_d_if->erq);
}

#include "isdnl1.h"

1805
static void hisax_bh(void *data)
Linus Torvalds's avatar
Linus Torvalds committed
1806
{
1807
	struct IsdnCardState *cs = data;
Linus Torvalds's avatar
Linus Torvalds committed
1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820
	struct PStack *st;
	int pr;

	if (test_and_clear_bit(D_RCVBUFREADY, &cs->event))
		DChannel_proc_rcv(cs);
	if (test_and_clear_bit(E_RCVBUFREADY, &cs->event))
		EChannel_proc_rcv(cs->hw.hisax_d_if);
	if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) {
		if (test_bit(0, &cs->hw.hisax_d_if->ph_state))
			pr = PH_ACTIVATE | INDICATION;
		else
			pr = PH_DEACTIVATE | INDICATION;
		for (st = cs->stlist; st; st = st->next)
Linus Torvalds's avatar
Linus Torvalds committed
1821
			L1L2(st, pr, NULL);
Linus Torvalds's avatar
Linus Torvalds committed
1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847
		
	}
}

static inline void D_L2L1(struct hisax_d_if *d_if, int pr, void *arg)
{
	struct hisax_if *ifc = (struct hisax_if *) d_if;
	ifc->l2l1(ifc, pr, arg);
}

static inline void B_L2L1(struct hisax_b_if *b_if, int pr, void *arg)
{
	struct hisax_if *ifc = (struct hisax_if *) b_if;
	ifc->l2l1(ifc, pr, arg);
}

static void hisax_d_l1l2(struct hisax_if *ifc, int pr, void *arg)
{
	struct hisax_d_if *d_if = (struct hisax_d_if *) ifc;
	struct IsdnCardState *cs = d_if->cs;
	struct PStack *st;
	struct sk_buff *skb;

	switch (pr) {
	case PH_ACTIVATE | INDICATION:
		set_bit(0, &d_if->ph_state);
1848
		sched_d_event(cs, D_L1STATECHANGE);
Linus Torvalds's avatar
Linus Torvalds committed
1849 1850 1851
		break;
	case PH_DEACTIVATE | INDICATION:
		clear_bit(0, &d_if->ph_state);
1852
		sched_d_event(cs, D_L1STATECHANGE);
Linus Torvalds's avatar
Linus Torvalds committed
1853 1854 1855
		break;
	case PH_DATA | INDICATION:
		skb_queue_tail(&cs->rq, arg);
1856
		sched_d_event(cs, D_RCVBUFREADY);
Linus Torvalds's avatar
Linus Torvalds committed
1857 1858 1859 1860 1861 1862 1863 1864 1865 1866
		break;
	case PH_DATA | CONFIRM:
		skb = skb_dequeue(&cs->sq);
		if (skb) {
			D_L2L1(d_if, PH_DATA | REQUEST, skb);
			break;
		}
		clear_bit(FLG_L1_DBUSY, &cs->HW_Flags);
		for (st = cs->stlist; st; st = st->next) {
			if (test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags)) {
Linus Torvalds's avatar
Linus Torvalds committed
1867
				L1L2(st, PH_PULL | CONFIRM, NULL);
Linus Torvalds's avatar
Linus Torvalds committed
1868 1869 1870 1871 1872 1873
				break;
			}
		}
		break;
	case PH_DATA_E | INDICATION:
		skb_queue_tail(&d_if->erq, arg);
1874
		sched_d_event(cs, E_RCVBUFREADY);
Linus Torvalds's avatar
Linus Torvalds committed
1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891
		break;
	default:
		printk("pr %#x\n", pr);
		break;
	}
}

static void hisax_b_l1l2(struct hisax_if *ifc, int pr, void *arg)
{
	struct hisax_b_if *b_if = (struct hisax_b_if *) ifc;
	struct BCState *bcs = b_if->bcs;
	struct PStack *st = bcs->st;
	struct sk_buff *skb;

	// FIXME use isdnl1?
	switch (pr) {
	case PH_ACTIVATE | INDICATION:
Linus Torvalds's avatar
Linus Torvalds committed
1892
		L1L2(st, pr, NULL);
Linus Torvalds's avatar
Linus Torvalds committed
1893 1894
		break;
	case PH_DEACTIVATE | INDICATION:
Linus Torvalds's avatar
Linus Torvalds committed
1895
		L1L2(st, pr, NULL);
1896 1897
		clear_bit(BC_FLG_BUSY, &bcs->Flag);
		skb_queue_purge(&bcs->squeue);
Linus Torvalds's avatar
Linus Torvalds committed
1898 1899 1900 1901
		bcs->hw.b_if = NULL;
		break;
	case PH_DATA | INDICATION:
		skb_queue_tail(&bcs->rqueue, arg);
1902
		sched_b_event(bcs, B_RCVBUFREADY);
Linus Torvalds's avatar
Linus Torvalds committed
1903 1904
		break;
	case PH_DATA | CONFIRM:
1905 1906
		skb = arg;
		bcs->tx_cnt -= skb->truesize;
1907
		xmit_complete_b(bcs);
Linus Torvalds's avatar
Linus Torvalds committed
1908 1909 1910 1911 1912 1913 1914
		skb = skb_dequeue(&bcs->squeue);
		if (skb) {
			B_L2L1(b_if, PH_DATA | REQUEST, skb);
			break;
		}
		clear_bit(BC_FLG_BUSY, &bcs->Flag);
		if (test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags)) {
Linus Torvalds's avatar
Linus Torvalds committed
1915
			L1L2(st, PH_PULL | CONFIRM, NULL);
Linus Torvalds's avatar
Linus Torvalds committed
1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945
		}
		break;
	default:
		printk("hisax_b_l1l2 pr %#x\n", pr);
		break;
	}
}

static void hisax_d_l2l1(struct PStack *st, int pr, void *arg)
{
	struct IsdnCardState *cs = st->l1.hardware;
	struct hisax_d_if *hisax_d_if = cs->hw.hisax_d_if;
	struct sk_buff *skb = arg;

	switch (pr) {
	case PH_DATA | REQUEST:
	case PH_PULL | INDICATION:
		if (cs->debug & DEB_DLOG_HEX)
			LogFrame(cs, skb->data, skb->len);
		if (cs->debug & DEB_DLOG_VERBOSE)
			dlogframe(cs, skb, 0);
		Logl2Frame(cs, skb, "PH_DATA_REQ", 0);
		// FIXME lock?
		if (!test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags))
			D_L2L1(hisax_d_if, PH_DATA | REQUEST, skb);
		else
			skb_queue_tail(&cs->sq, skb);
		break;
	case PH_PULL | REQUEST:
		if (!test_bit(FLG_L1_DBUSY, &cs->HW_Flags))
Linus Torvalds's avatar
Linus Torvalds committed
1946
			L1L2(st, PH_PULL | CONFIRM, NULL);
Linus Torvalds's avatar
Linus Torvalds committed
1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980
		else
			set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
		break;
	default:
		D_L2L1(hisax_d_if, pr, arg);
		break;
	}
}

static int hisax_cardmsg(struct IsdnCardState *cs, int mt, void *arg)
{
	return 0;
}

static void hisax_b_l2l1(struct PStack *st, int pr, void *arg)
{
	struct BCState *bcs = st->l1.bcs;
	struct hisax_b_if *b_if = bcs->hw.b_if;

	switch (pr) {
	case PH_ACTIVATE | REQUEST:
		B_L2L1(b_if, pr, (void *) st->l1.mode);
		break;
	case PH_DATA | REQUEST:
	case PH_PULL | INDICATION:
		// FIXME lock?
		if (!test_and_set_bit(BC_FLG_BUSY, &bcs->Flag)) {
			B_L2L1(b_if, PH_DATA | REQUEST, arg);
		} else {
			skb_queue_tail(&bcs->squeue, arg);
		}
		break;
	case PH_PULL | REQUEST:
		if (!test_bit(BC_FLG_BUSY, &bcs->Flag))
Linus Torvalds's avatar
Linus Torvalds committed
1981
			L1L2(st, PH_PULL | CONFIRM, NULL);
Linus Torvalds's avatar
Linus Torvalds committed
1982 1983 1984
		else
			set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
		break;
1985 1986 1987
	case PH_DEACTIVATE | REQUEST:
		test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
		skb_queue_purge(&bcs->squeue);
Linus Torvalds's avatar
Linus Torvalds committed
1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004
	default:
		B_L2L1(b_if, pr, arg);
		break;
	}
}

static int hisax_bc_setstack(struct PStack *st, struct BCState *bcs)
{
	struct IsdnCardState *cs = st->l1.hardware;
	struct hisax_d_if *hisax_d_if = cs->hw.hisax_d_if;

	bcs->channel = st->l1.bc;

	bcs->hw.b_if = hisax_d_if->b_if[st->l1.bc];
	hisax_d_if->b_if[st->l1.bc]->bcs = bcs;

	st->l1.bcs = bcs;
Linus Torvalds's avatar
Linus Torvalds committed
2005
	st->l1.l2l1 = hisax_b_l2l1;
Linus Torvalds's avatar
Linus Torvalds committed
2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024
	setstack_manager(st);
	bcs->st = st;
	setstack_l1_B(st);
	skb_queue_head_init(&bcs->rqueue);
	skb_queue_head_init(&bcs->squeue);
	return 0;
}

static void hisax_bc_close(struct BCState *bcs)
{
	struct hisax_b_if *b_if = bcs->hw.b_if;

	if (b_if)
		B_L2L1(b_if, PH_DEACTIVATE | REQUEST, NULL);
}

static void EChannel_proc_rcv(struct hisax_d_if *d_if)
{
	struct IsdnCardState *cs = d_if->cs;
2025
	u8 *ptr;
Linus Torvalds's avatar
Linus Torvalds committed
2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050
	struct sk_buff *skb;

	while ((skb = skb_dequeue(&d_if->erq)) != NULL) {
		if (cs->debug & DEB_DLOG_HEX) {
			ptr = cs->dlog;
			if ((skb->len) < MAX_DLOG_SPACE / 3 - 10) {
				*ptr++ = 'E';
				*ptr++ = 'C';
				*ptr++ = 'H';
				*ptr++ = 'O';
				*ptr++ = ':';
				ptr += QuickHex(ptr, skb->data, skb->len);
				ptr--;
				*ptr++ = '\n';
				*ptr = 0;
				HiSax_putstatus(cs, NULL, cs->dlog);
			} else
				HiSax_putstatus(cs, "LogEcho: ",
						"warning Frame too big (%d)",
						skb->len);
		}
		dev_kfree_skb_any(skb);
	}
}

Linus Torvalds's avatar
Linus Torvalds committed
2051 2052
#include <linux/pci.h>

Linus Torvalds's avatar
Linus Torvalds committed
2053
static struct pci_device_id hisax_pci_tbl[] __initdata = {
Linus Torvalds's avatar
Linus Torvalds committed
2054
#ifdef CONFIG_HISAX_FRITZPCI
Linus Torvalds's avatar
Linus Torvalds committed
2055
	{PCI_VENDOR_ID_AVM,      PCI_DEVICE_ID_AVM_A1,           PCI_ANY_ID, PCI_ANY_ID},
Linus Torvalds's avatar
Linus Torvalds committed
2056 2057 2058 2059 2060
#endif
#ifdef CONFIG_HISAX_DIEHLDIVA
	{PCI_VENDOR_ID_EICON,    PCI_DEVICE_ID_EICON_DIVA20,     PCI_ANY_ID, PCI_ANY_ID},
	{PCI_VENDOR_ID_EICON,    PCI_DEVICE_ID_EICON_DIVA20_U,   PCI_ANY_ID, PCI_ANY_ID},
	{PCI_VENDOR_ID_EICON,    PCI_DEVICE_ID_EICON_DIVA201,    PCI_ANY_ID, PCI_ANY_ID},
2061
	{PCI_VENDOR_ID_EICON,    PCI_DEVICE_ID_EICON_DIVA202,    PCI_ANY_ID, PCI_ANY_ID},
Linus Torvalds's avatar
Linus Torvalds committed
2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116
#endif
#ifdef CONFIG_HISAX_ELSA
	{PCI_VENDOR_ID_ELSA,     PCI_DEVICE_ID_ELSA_MICROLINK,   PCI_ANY_ID, PCI_ANY_ID},
	{PCI_VENDOR_ID_ELSA,     PCI_DEVICE_ID_ELSA_QS3000,      PCI_ANY_ID, PCI_ANY_ID},
#endif
#ifdef CONFIG_HISAX_GAZEL
	{PCI_VENDOR_ID_PLX,      PCI_DEVICE_ID_PLX_R685,         PCI_ANY_ID, PCI_ANY_ID},
	{PCI_VENDOR_ID_PLX,      PCI_DEVICE_ID_PLX_R753,         PCI_ANY_ID, PCI_ANY_ID},
	{PCI_VENDOR_ID_PLX,      PCI_DEVICE_ID_PLX_DJINN_ITOO,   PCI_ANY_ID, PCI_ANY_ID},
#endif
#ifdef CONFIG_HISAX_QUADRO
	{PCI_VENDOR_ID_PLX,      PCI_DEVICE_ID_PLX_9050,         PCI_ANY_ID, PCI_ANY_ID},
#endif
#ifdef CONFIG_HISAX_NICCY
	{PCI_VENDOR_ID_SATSAGEM, PCI_DEVICE_ID_SATSAGEM_NICCY,   PCI_ANY_ID,PCI_ANY_ID},
#endif
#ifdef CONFIG_HISAX_SEDLBAUER
	{PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_100,     PCI_ANY_ID,PCI_ANY_ID},
#endif
#if defined(CONFIG_HISAX_NETJET) || defined(CONFIG_HISAX_NETJET_U)
	{PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_300,     PCI_ANY_ID,PCI_ANY_ID},
#endif
#if defined(CONFIG_HISAX_TELESPCI) || defined(CONFIG_HISAX_SCT_QUADRO)
	{PCI_VENDOR_ID_ZORAN,    PCI_DEVICE_ID_ZORAN_36120,      PCI_ANY_ID,PCI_ANY_ID},
#endif
#ifdef CONFIG_HISAX_W6692
	{PCI_VENDOR_ID_DYNALINK, PCI_DEVICE_ID_DYNALINK_IS64PH,  PCI_ANY_ID,PCI_ANY_ID},
	{PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND2_6692,    PCI_ANY_ID,PCI_ANY_ID},
#endif
#ifdef CONFIG_HISAX_HFC_PCI
	{PCI_VENDOR_ID_CCD,      PCI_DEVICE_ID_CCD_2BD0,         PCI_ANY_ID, PCI_ANY_ID},
	{PCI_VENDOR_ID_CCD,      PCI_DEVICE_ID_CCD_B000,         PCI_ANY_ID, PCI_ANY_ID},
	{PCI_VENDOR_ID_CCD,      PCI_DEVICE_ID_CCD_B006,         PCI_ANY_ID, PCI_ANY_ID},
	{PCI_VENDOR_ID_CCD,      PCI_DEVICE_ID_CCD_B007,         PCI_ANY_ID, PCI_ANY_ID},
	{PCI_VENDOR_ID_CCD,      PCI_DEVICE_ID_CCD_B008,         PCI_ANY_ID, PCI_ANY_ID},
	{PCI_VENDOR_ID_CCD,      PCI_DEVICE_ID_CCD_B009,         PCI_ANY_ID, PCI_ANY_ID},
	{PCI_VENDOR_ID_CCD,      PCI_DEVICE_ID_CCD_B00A,         PCI_ANY_ID, PCI_ANY_ID},
	{PCI_VENDOR_ID_CCD,      PCI_DEVICE_ID_CCD_B00B,         PCI_ANY_ID, PCI_ANY_ID},
	{PCI_VENDOR_ID_CCD,      PCI_DEVICE_ID_CCD_B00C,         PCI_ANY_ID, PCI_ANY_ID},
	{PCI_VENDOR_ID_CCD,      PCI_DEVICE_ID_CCD_B100,         PCI_ANY_ID, PCI_ANY_ID},
	{PCI_VENDOR_ID_ABOCOM,   PCI_DEVICE_ID_ABOCOM_2BD1,      PCI_ANY_ID, PCI_ANY_ID},
	{PCI_VENDOR_ID_ASUSTEK,  PCI_DEVICE_ID_ASUSTEK_0675,     PCI_ANY_ID, PCI_ANY_ID},
	{PCI_VENDOR_ID_BERKOM,   PCI_DEVICE_ID_BERKOM_T_CONCEPT, PCI_ANY_ID, PCI_ANY_ID},
	{PCI_VENDOR_ID_BERKOM,   PCI_DEVICE_ID_BERKOM_A1T,       PCI_ANY_ID, PCI_ANY_ID},
	{PCI_VENDOR_ID_ANIGMA,   PCI_DEVICE_ID_ANIGMA_MC145575,  PCI_ANY_ID, PCI_ANY_ID},
	{PCI_VENDOR_ID_ZOLTRIX,  PCI_DEVICE_ID_ZOLTRIX_2BD0,     PCI_ANY_ID, PCI_ANY_ID},
	{PCI_VENDOR_ID_DIGI,     PCI_DEVICE_ID_DIGI_DF_M_IOM2_E, PCI_ANY_ID, PCI_ANY_ID},
	{PCI_VENDOR_ID_DIGI,     PCI_DEVICE_ID_DIGI_DF_M_E,      PCI_ANY_ID, PCI_ANY_ID},
	{PCI_VENDOR_ID_DIGI,     PCI_DEVICE_ID_DIGI_DF_M_IOM2_A, PCI_ANY_ID, PCI_ANY_ID},
	{PCI_VENDOR_ID_DIGI,     PCI_DEVICE_ID_DIGI_DF_M_A,      PCI_ANY_ID, PCI_ANY_ID},
#endif
	{ }				/* Terminating entry */
};

MODULE_DEVICE_TABLE(pci, hisax_pci_tbl);
Linus Torvalds's avatar
Linus Torvalds committed
2117 2118 2119

module_init(HiSax_init);
module_exit(HiSax_exit);
2120 2121 2122 2123 2124 2125 2126 2127

EXPORT_SYMBOL(FsmNew);
EXPORT_SYMBOL(FsmFree);
EXPORT_SYMBOL(FsmEvent);
EXPORT_SYMBOL(FsmChangeState);
EXPORT_SYMBOL(FsmInitTimer);
EXPORT_SYMBOL(FsmDelTimer);
EXPORT_SYMBOL(FsmRestartTimer);